posixmodule.c revision 3886bb6997f8f7b0b64eed19045161e697f415fe
1/*********************************************************** 2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, 3The Netherlands. 4 5 All Rights Reserved 6 7Permission to use, copy, modify, and distribute this software and its 8documentation for any purpose and without fee is hereby granted, 9provided that the above copyright notice appear in all copies and that 10both that copyright notice and this permission notice appear in 11supporting documentation, and that the names of Stichting Mathematisch 12Centrum or CWI or Corporation for National Research Initiatives or 13CNRI not be used in advertising or publicity pertaining to 14distribution of the software without specific, written prior 15permission. 16 17While CWI is the initial source for this software, a modified version 18is made available by the Corporation for National Research Initiatives 19(CNRI) at the Internet address ftp://ftp.python.org. 20 21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH 22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH 24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 28PERFORMANCE OF THIS SOFTWARE. 29 30******************************************************************/ 31 32/* POSIX module implementation */ 33 34/* This file is also used for Windows NT and MS-Win. In that case the module 35 actually calls itself 'nt', not 'posix', and a few functions are 36 either unimplemented or implemented differently. The source 37 assumes that for Windows NT, the macro 'MS_WIN32' is defined independent 38 of the compiler used. Different compilers define their own feature 39 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */ 40 41/* See also ../Dos/dosmodule.c */ 42 43static char posix__doc__ [] = 44"This module provides access to operating system functionality that is\n\ 45standardized by the C Standard and the POSIX standard (a thinly\n\ 46disguised Unix interface). Refer to the library manual and\n\ 47corresponding Unix manual entries for more information on calls."; 48 49#include "Python.h" 50 51#if defined(PYOS_OS2) 52#define INCL_DOS 53#define INCL_DOSERRORS 54#define INCL_DOSPROCESS 55#define INCL_NOPMAPI 56#include <os2.h> 57#endif 58 59#include <sys/types.h> 60#include <sys/stat.h> 61#ifdef HAVE_SYS_WAIT_H 62#include <sys/wait.h> /* For WNOHANG */ 63#endif 64 65#ifdef HAVE_SIGNAL_H 66#include <signal.h> 67#endif 68 69#include "mytime.h" /* For clock_t on some systems */ 70 71#ifdef HAVE_FCNTL_H 72#include <fcntl.h> 73#endif /* HAVE_FCNTL_H */ 74 75/* Various compilers have only certain posix functions */ 76/* XXX Gosh I wish these were all moved into config.h */ 77#if defined(PYCC_VACPP) && defined(PYOS_OS2) 78#include <process.h> 79#else 80#if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ 81#define HAVE_GETCWD 1 82#define HAVE_OPENDIR 1 83#define HAVE_SYSTEM 1 84#if defined(__OS2__) 85#define HAVE_EXECV 1 86#define HAVE_WAIT 1 87#endif 88#include <process.h> 89#else 90#ifdef __BORLANDC__ /* Borland compiler */ 91#define HAVE_EXECV 1 92#define HAVE_GETCWD 1 93#define HAVE_GETEGID 1 94#define HAVE_GETEUID 1 95#define HAVE_GETGID 1 96#define HAVE_GETPPID 1 97#define HAVE_GETUID 1 98#define HAVE_KILL 1 99#define HAVE_OPENDIR 1 100#define HAVE_PIPE 1 101#define HAVE_POPEN 1 102#define HAVE_SYSTEM 1 103#define HAVE_WAIT 1 104#else 105#ifdef _MSC_VER /* Microsoft compiler */ 106#define HAVE_GETCWD 1 107#ifdef MS_WIN32 108#define HAVE_EXECV 1 109#define HAVE_PIPE 1 110#define HAVE_POPEN 1 111#define HAVE_SYSTEM 1 112#else /* 16-bit Windows */ 113#endif /* !MS_WIN32 */ 114#else /* all other compilers */ 115/* Unix functions that the configure script doesn't check for */ 116#define HAVE_EXECV 1 117#define HAVE_FORK 1 118#define HAVE_GETCWD 1 119#define HAVE_GETEGID 1 120#define HAVE_GETEUID 1 121#define HAVE_GETGID 1 122#define HAVE_GETPPID 1 123#define HAVE_GETUID 1 124#define HAVE_KILL 1 125#define HAVE_OPENDIR 1 126#define HAVE_PIPE 1 127#define HAVE_POPEN 1 128#define HAVE_SYSTEM 1 129#define HAVE_WAIT 1 130#endif /* _MSC_VER */ 131#endif /* __BORLANDC__ */ 132#endif /* ! __WATCOMC__ || __QNX__ */ 133#endif /* ! __IBMC__ */ 134 135#ifndef _MSC_VER 136 137#ifdef HAVE_UNISTD_H 138#include <unistd.h> 139#endif 140 141#ifdef NeXT 142/* NeXT's <unistd.h> and <utime.h> aren't worth much */ 143#undef HAVE_UNISTD_H 144#undef HAVE_UTIME_H 145#define HAVE_WAITPID 146/* #undef HAVE_GETCWD */ 147#endif 148 149#ifdef HAVE_UNISTD_H 150/* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */ 151extern int rename(); 152extern int pclose(); 153extern int lstat(); 154extern int symlink(); 155#else /* !HAVE_UNISTD_H */ 156#if defined(PYCC_VACPP) 157extern int mkdir Py_PROTO((char *)); 158#else 159#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__) 160extern int mkdir Py_PROTO((const char *)); 161#else 162extern int mkdir Py_PROTO((const char *, mode_t)); 163#endif 164#endif 165#if defined(__IBMC__) || defined(__IBMCPP__) 166extern int chdir Py_PROTO((char *)); 167extern int rmdir Py_PROTO((char *)); 168#else 169extern int chdir Py_PROTO((const char *)); 170extern int rmdir Py_PROTO((const char *)); 171#endif 172extern int chmod Py_PROTO((const char *, mode_t)); 173extern int chown Py_PROTO((const char *, uid_t, gid_t)); 174extern char *getcwd Py_PROTO((char *, int)); 175extern char *strerror Py_PROTO((int)); 176extern int link Py_PROTO((const char *, const char *)); 177extern int rename Py_PROTO((const char *, const char *)); 178extern int stat Py_PROTO((const char *, struct stat *)); 179extern int unlink Py_PROTO((const char *)); 180extern int pclose Py_PROTO((FILE *)); 181#ifdef HAVE_SYMLINK 182extern int symlink Py_PROTO((const char *, const char *)); 183#endif /* HAVE_SYMLINK */ 184#ifdef HAVE_LSTAT 185extern int lstat Py_PROTO((const char *, struct stat *)); 186#endif /* HAVE_LSTAT */ 187#endif /* !HAVE_UNISTD_H */ 188 189#endif /* !_MSC_VER */ 190 191#ifdef HAVE_UTIME_H 192#include <utime.h> 193#endif /* HAVE_UTIME_H */ 194 195#ifdef HAVE_SYS_UTIME_H 196#include <sys/utime.h> 197#define HAVE_UTIME_H /* pretend we do for the rest of this file */ 198#endif /* HAVE_SYS_UTIME_H */ 199 200#ifdef HAVE_SYS_TIMES_H 201#include <sys/times.h> 202#endif /* HAVE_SYS_TIMES_H */ 203 204#ifdef HAVE_SYS_PARAM_H 205#include <sys/param.h> 206#endif /* HAVE_SYS_PARAM_H */ 207 208#ifdef HAVE_SYS_UTSNAME_H 209#include <sys/utsname.h> 210#endif /* HAVE_SYS_UTSNAME_H */ 211 212#ifndef MAXPATHLEN 213#define MAXPATHLEN 1024 214#endif /* MAXPATHLEN */ 215 216#ifdef HAVE_DIRENT_H 217#include <dirent.h> 218#define NAMLEN(dirent) strlen((dirent)->d_name) 219#else 220#if defined(__WATCOMC__) && !defined(__QNX__) 221#include <direct.h> 222#define NAMLEN(dirent) strlen((dirent)->d_name) 223#else 224#define dirent direct 225#define NAMLEN(dirent) (dirent)->d_namlen 226#endif 227#ifdef HAVE_SYS_NDIR_H 228#include <sys/ndir.h> 229#endif 230#ifdef HAVE_SYS_DIR_H 231#include <sys/dir.h> 232#endif 233#ifdef HAVE_NDIR_H 234#include <ndir.h> 235#endif 236#endif 237 238#ifdef _MSC_VER 239#include <direct.h> 240#include <io.h> 241#include <process.h> 242#include <windows.h> 243#ifdef MS_WIN32 244#define popen _popen 245#define pclose _pclose 246#else /* 16-bit Windows */ 247#include <dos.h> 248#include <ctype.h> 249#endif /* MS_WIN32 */ 250#endif /* _MSC_VER */ 251 252#if defined(PYCC_VACPP) && defined(PYOS_OS2) 253#include <io.h> 254#endif /* OS2 */ 255 256/* Return a dictionary corresponding to the POSIX environment table */ 257 258#if !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) ) 259extern char **environ; 260#endif /* !_MSC_VER */ 261 262static PyObject * 263convertenviron() 264{ 265 PyObject *d; 266 char **e; 267 d = PyDict_New(); 268 if (d == NULL) 269 return NULL; 270 if (environ == NULL) 271 return d; 272 /* XXX This part ignores errors */ 273 for (e = environ; *e != NULL; e++) { 274 PyObject *v; 275 char *p = strchr(*e, '='); 276 if (p == NULL) 277 continue; 278 v = PyString_FromString(p+1); 279 if (v == NULL) 280 continue; 281 *p = '\0'; 282 (void) PyDict_SetItemString(d, *e, v); 283 *p = '='; 284 Py_DECREF(v); 285 } 286#if defined(PYOS_OS2) 287 { 288 APIRET rc; 289 char buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */ 290 291 rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH); 292 if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */ 293 PyObject *v = PyString_FromString(buffer); 294 PyDict_SetItemString(d, "BEGINLIBPATH", v); 295 Py_DECREF(v); 296 } 297 rc = DosQueryExtLIBPATH(buffer, END_LIBPATH); 298 if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */ 299 PyObject *v = PyString_FromString(buffer); 300 PyDict_SetItemString(d, "ENDLIBPATH", v); 301 Py_DECREF(v); 302 } 303 } 304#endif 305 return d; 306} 307 308 309static PyObject *PosixError; /* Exception posix.error */ 310 311/* Set a POSIX-specific error from errno, and return NULL */ 312 313static PyObject * 314posix_error() 315{ 316 return PyErr_SetFromErrno(PosixError); 317} 318static PyObject * 319posix_error_with_filename(name) 320 char* name; 321{ 322 return PyErr_SetFromErrnoWithFilename(PosixError, name); 323} 324 325 326#if defined(PYOS_OS2) 327/********************************************************************** 328 * Helper Function to Trim and Format OS/2 Messages 329 **********************************************************************/ 330 static void 331os2_formatmsg(char *msgbuf, int msglen, char *reason) 332{ 333 msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */ 334 335 if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */ 336 char *lastc = &msgbuf[ strlen(msgbuf)-1 ]; 337 338 while (lastc > msgbuf && isspace(*lastc)) 339 *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */ 340 } 341 342 /* Add Optional Reason Text */ 343 if (reason) { 344 strcat(msgbuf, " : "); 345 strcat(msgbuf, reason); 346 } 347} 348 349/********************************************************************** 350 * Decode an OS/2 Operating System Error Code 351 * 352 * A convenience function to lookup an OS/2 error code and return a 353 * text message we can use to raise a Python exception. 354 * 355 * Notes: 356 * The messages for errors returned from the OS/2 kernel reside in 357 * the file OSO001.MSG in the \OS2 directory hierarchy. 358 * 359 **********************************************************************/ 360 static char * 361os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason) 362{ 363 APIRET rc; 364 ULONG msglen; 365 366 /* Retrieve Kernel-Related Error Message from OSO001.MSG File */ 367 Py_BEGIN_ALLOW_THREADS 368 rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen, 369 errorcode, "oso001.msg", &msglen); 370 Py_END_ALLOW_THREADS 371 372 if (rc == NO_ERROR) 373 os2_formatmsg(msgbuf, msglen, reason); 374 else 375 sprintf(msgbuf, "unknown OS error #%d", errorcode); 376 377 return msgbuf; 378} 379 380/* Set an OS/2-specific error and return NULL. OS/2 kernel 381 errors are not in a global variable e.g. 'errno' nor are 382 they congruent with posix error numbers. */ 383 384static PyObject * os2_error(int code) 385{ 386 char text[1024]; 387 PyObject *v; 388 389 os2_strerror(text, sizeof(text), code, ""); 390 391 v = Py_BuildValue("(is)", code, text); 392 if (v != NULL) { 393 PyErr_SetObject(PosixError, v); 394 Py_DECREF(v); 395 } 396 return NULL; /* Signal to Python that an Exception is Pending */ 397} 398 399#endif /* OS2 */ 400 401/* POSIX generic methods */ 402 403static PyObject * 404posix_1str(args, func) 405 PyObject *args; 406 int (*func) Py_FPROTO((const char *)); 407{ 408 char *path1; 409 int res; 410 if (!PyArg_Parse(args, "s", &path1)) 411 return NULL; 412 Py_BEGIN_ALLOW_THREADS 413 res = (*func)(path1); 414 Py_END_ALLOW_THREADS 415 if (res < 0) 416 return posix_error_with_filename(path1); 417 Py_INCREF(Py_None); 418 return Py_None; 419} 420 421static PyObject * 422posix_2str(args, func) 423 PyObject *args; 424 int (*func) Py_FPROTO((const char *, const char *)); 425{ 426 char *path1, *path2; 427 int res; 428 if (!PyArg_Parse(args, "(ss)", &path1, &path2)) 429 return NULL; 430 Py_BEGIN_ALLOW_THREADS 431 res = (*func)(path1, path2); 432 Py_END_ALLOW_THREADS 433 if (res != 0) 434 /* XXX how to report both path1 and path2??? */ 435 return posix_error(); 436 Py_INCREF(Py_None); 437 return Py_None; 438} 439 440static PyObject * 441posix_strint(args, func) 442 PyObject *args; 443 int (*func) Py_FPROTO((const char *, int)); 444{ 445 char *path; 446 int i; 447 int res; 448 if (!PyArg_Parse(args, "(si)", &path, &i)) 449 return NULL; 450 Py_BEGIN_ALLOW_THREADS 451 res = (*func)(path, i); 452 Py_END_ALLOW_THREADS 453 if (res < 0) 454 return posix_error_with_filename(path); 455 Py_INCREF(Py_None); 456 return Py_None; 457} 458 459static PyObject * 460posix_strintint(args, func) 461 PyObject *args; 462 int (*func) Py_FPROTO((const char *, int, int)); 463{ 464 char *path; 465 int i,i2; 466 int res; 467 if (!PyArg_Parse(args, "(sii)", &path, &i, &i2)) 468 return NULL; 469 Py_BEGIN_ALLOW_THREADS 470 res = (*func)(path, i, i2); 471 Py_END_ALLOW_THREADS 472 if (res < 0) 473 return posix_error_with_filename(path); 474 Py_INCREF(Py_None); 475 return Py_None; 476} 477 478static PyObject * 479posix_do_stat(self, args, statfunc) 480 PyObject *self; 481 PyObject *args; 482 int (*statfunc) Py_FPROTO((const char *, struct stat *)); 483{ 484 struct stat st; 485 char *path; 486 int res; 487 if (!PyArg_Parse(args, "s", &path)) 488 return NULL; 489 Py_BEGIN_ALLOW_THREADS 490 res = (*statfunc)(path, &st); 491 Py_END_ALLOW_THREADS 492 if (res != 0) 493 return posix_error_with_filename(path); 494 return Py_BuildValue("(llllllllll)", 495 (long)st.st_mode, 496 (long)st.st_ino, 497 (long)st.st_dev, 498 (long)st.st_nlink, 499 (long)st.st_uid, 500 (long)st.st_gid, 501 (long)st.st_size, 502 (long)st.st_atime, 503 (long)st.st_mtime, 504 (long)st.st_ctime); 505} 506 507 508/* POSIX methods */ 509 510static char posix_chdir__doc__[] = 511"chdir(path) -> None\n\ 512Change the current working directory to the specified path."; 513 514static PyObject * 515posix_chdir(self, args) 516 PyObject *self; 517 PyObject *args; 518{ 519 return posix_1str(args, chdir); 520} 521 522 523static char posix_chmod__doc__[] = 524"chmod(path, mode) -> None\n\ 525Change the access permissions of a file."; 526 527static PyObject * 528posix_chmod(self, args) 529 PyObject *self; 530 PyObject *args; 531{ 532 return posix_strint(args, chmod); 533} 534 535 536#ifdef HAVE_CHOWN 537static char posix_chown__doc__[] = 538"chown(path, uid, gid) -> None\n\ 539Change the owner and group id of path to the numeric uid and gid."; 540 541static PyObject * 542posix_chown(self, args) 543 PyObject *self; 544 PyObject *args; 545{ 546 return posix_strintint(args, chown); 547} 548#endif /* HAVE_CHOWN */ 549 550 551#ifdef HAVE_GETCWD 552static char posix_getcwd__doc__[] = 553"getcwd() -> path\n\ 554Return a string representing the current working directory."; 555 556static PyObject * 557posix_getcwd(self, args) 558 PyObject *self; 559 PyObject *args; 560{ 561 char buf[1026]; 562 char *res; 563 if (!PyArg_NoArgs(args)) 564 return NULL; 565 Py_BEGIN_ALLOW_THREADS 566 res = getcwd(buf, sizeof buf); 567 Py_END_ALLOW_THREADS 568 if (res == NULL) 569 return posix_error(); 570 return PyString_FromString(buf); 571} 572#endif 573 574 575#ifdef HAVE_LINK 576static char posix_link__doc__[] = 577"link(src, dst) -> None\n\ 578Create a hard link to a file."; 579 580static PyObject * 581posix_link(self, args) 582 PyObject *self; 583 PyObject *args; 584{ 585 return posix_2str(args, link); 586} 587#endif /* HAVE_LINK */ 588 589 590static char posix_listdir__doc__[] = 591"listdir(path) -> list_of_strings\n\ 592Return a list containing the names of the entries in the directory.\n\ 593\n\ 594 path: path of directory to list\n\ 595\n\ 596The list is in arbitrary order. It does not include the special\n\ 597entries '.' and '..' even if they are present in the directory."; 598 599static PyObject * 600posix_listdir(self, args) 601 PyObject *self; 602 PyObject *args; 603{ 604 /* XXX Should redo this putting the (now four) versions of opendir 605 in separate files instead of having them all here... */ 606#if defined(MS_WIN32) && !defined(HAVE_OPENDIR) 607 608 char *name; 609 int len; 610 PyObject *d, *v; 611 HANDLE hFindFile; 612 WIN32_FIND_DATA FileData; 613 char namebuf[MAX_PATH+5]; 614 615 if (!PyArg_Parse(args, "t#", &name, &len)) 616 return NULL; 617 if (len >= MAX_PATH) { 618 PyErr_SetString(PyExc_ValueError, "path too long"); 619 return NULL; 620 } 621 strcpy(namebuf, name); 622 if (namebuf[len-1] != '/' && namebuf[len-1] != '\\') 623 namebuf[len++] = '/'; 624 strcpy(namebuf + len, "*.*"); 625 626 if ((d = PyList_New(0)) == NULL) 627 return NULL; 628 629 hFindFile = FindFirstFile(namebuf, &FileData); 630 if (hFindFile == INVALID_HANDLE_VALUE) { 631 errno = GetLastError(); 632 if (errno == ERROR_FILE_NOT_FOUND) 633 return PyList_New(0); 634 return posix_error(); 635 } 636 do { 637 if (FileData.cFileName[0] == '.' && 638 (FileData.cFileName[1] == '\0' || 639 FileData.cFileName[1] == '.' && 640 FileData.cFileName[2] == '\0')) 641 continue; 642 v = PyString_FromString(FileData.cFileName); 643 if (v == NULL) { 644 Py_DECREF(d); 645 d = NULL; 646 break; 647 } 648 if (PyList_Append(d, v) != 0) { 649 Py_DECREF(v); 650 Py_DECREF(d); 651 d = NULL; 652 break; 653 } 654 Py_DECREF(v); 655 } while (FindNextFile(hFindFile, &FileData) == TRUE); 656 657 if (FindClose(hFindFile) == FALSE) { 658 errno = GetLastError(); 659 return posix_error(); 660 } 661 662 return d; 663 664#else /* !MS_WIN32 */ 665#ifdef _MSC_VER /* 16-bit Windows */ 666 667#ifndef MAX_PATH 668#define MAX_PATH 250 669#endif 670 char *name, *pt; 671 int len; 672 PyObject *d, *v; 673 char namebuf[MAX_PATH+5]; 674 struct _find_t ep; 675 676 if (!PyArg_Parse(args, "t#", &name, &len)) 677 return NULL; 678 if (len >= MAX_PATH) { 679 PyErr_SetString(PyExc_ValueError, "path too long"); 680 return NULL; 681 } 682 strcpy(namebuf, name); 683 for (pt = namebuf; *pt; pt++) 684 if (*pt == '/') 685 *pt = '\\'; 686 if (namebuf[len-1] != '\\') 687 namebuf[len++] = '\\'; 688 strcpy(namebuf + len, "*.*"); 689 690 if ((d = PyList_New(0)) == NULL) 691 return NULL; 692 693 if (_dos_findfirst(namebuf, _A_RDONLY | 694 _A_HIDDEN | _A_SYSTEM | _A_SUBDIR, &ep) != 0) 695 { 696 errno = ENOENT; 697 return posix_error(); 698 } 699 do { 700 if (ep.name[0] == '.' && 701 (ep.name[1] == '\0' || 702 ep.name[1] == '.' && 703 ep.name[2] == '\0')) 704 continue; 705 strcpy(namebuf, ep.name); 706 for (pt = namebuf; *pt; pt++) 707 if (isupper(*pt)) 708 *pt = tolower(*pt); 709 v = PyString_FromString(namebuf); 710 if (v == NULL) { 711 Py_DECREF(d); 712 d = NULL; 713 break; 714 } 715 if (PyList_Append(d, v) != 0) { 716 Py_DECREF(v); 717 Py_DECREF(d); 718 d = NULL; 719 break; 720 } 721 Py_DECREF(v); 722 } while (_dos_findnext(&ep) == 0); 723 724 return d; 725 726#else 727#if defined(PYOS_OS2) 728 729#ifndef MAX_PATH 730#define MAX_PATH CCHMAXPATH 731#endif 732 char *name, *pt; 733 int len; 734 PyObject *d, *v; 735 char namebuf[MAX_PATH+5]; 736 HDIR hdir = 1; 737 ULONG srchcnt = 1; 738 FILEFINDBUF3 ep; 739 APIRET rc; 740 741 if (!PyArg_Parse(args, "t#", &name, &len)) 742 return NULL; 743 if (len >= MAX_PATH) { 744 PyErr_SetString(PyExc_ValueError, "path too long"); 745 return NULL; 746 } 747 strcpy(namebuf, name); 748 for (pt = namebuf; *pt; pt++) 749 if (*pt == '/') 750 *pt = '\\'; 751 if (namebuf[len-1] != '\\') 752 namebuf[len++] = '\\'; 753 strcpy(namebuf + len, "*.*"); 754 755 if ((d = PyList_New(0)) == NULL) 756 return NULL; 757 758 rc = DosFindFirst(namebuf, /* Wildcard Pattern to Match */ 759 &hdir, /* Handle to Use While Search Directory */ 760 FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY, 761 &ep, sizeof(ep), /* Structure to Receive Directory Entry */ 762 &srchcnt, /* Max and Actual Count of Entries Per Iteration */ 763 FIL_STANDARD); /* Format of Entry (EAs or Not) */ 764 765 if (rc != NO_ERROR) { 766 errno = ENOENT; 767 return posix_error(); 768 } 769 770 if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */ 771 do { 772 if (ep.achName[0] == '.' 773 && (ep.achName[1] == '\0' || ep.achName[1] == '.' && ep.achName[2] == '\0')) 774 continue; /* Skip Over "." and ".." Names */ 775 776 strcpy(namebuf, ep.achName); 777 778 /* Leave Case of Name Alone -- In Native Form */ 779 /* (Removed Forced Lowercasing Code) */ 780 781 v = PyString_FromString(namebuf); 782 if (v == NULL) { 783 Py_DECREF(d); 784 d = NULL; 785 break; 786 } 787 if (PyList_Append(d, v) != 0) { 788 Py_DECREF(v); 789 Py_DECREF(d); 790 d = NULL; 791 break; 792 } 793 Py_DECREF(v); 794 } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0); 795 } 796 797 return d; 798#else 799 800 char *name; 801 PyObject *d, *v; 802 DIR *dirp; 803 struct dirent *ep; 804 if (!PyArg_Parse(args, "s", &name)) 805 return NULL; 806 Py_BEGIN_ALLOW_THREADS 807 if ((dirp = opendir(name)) == NULL) { 808 Py_BLOCK_THREADS 809 return posix_error(); 810 } 811 if ((d = PyList_New(0)) == NULL) { 812 closedir(dirp); 813 Py_BLOCK_THREADS 814 return NULL; 815 } 816 while ((ep = readdir(dirp)) != NULL) { 817 if (ep->d_name[0] == '.' && 818 (NAMLEN(ep) == 1 || 819 (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) 820 continue; 821 v = PyString_FromStringAndSize(ep->d_name, NAMLEN(ep)); 822 if (v == NULL) { 823 Py_DECREF(d); 824 d = NULL; 825 break; 826 } 827 if (PyList_Append(d, v) != 0) { 828 Py_DECREF(v); 829 Py_DECREF(d); 830 d = NULL; 831 break; 832 } 833 Py_DECREF(v); 834 } 835 closedir(dirp); 836 Py_END_ALLOW_THREADS 837 838 return d; 839 840#endif /* !PYOS_OS2 */ 841#endif /* !_MSC_VER */ 842#endif /* !MS_WIN32 */ 843} 844 845static char posix_mkdir__doc__[] = 846"mkdir(path [, mode=0777]) -> None\n\ 847Create a directory."; 848 849static PyObject * 850posix_mkdir(self, args) 851 PyObject *self; 852 PyObject *args; 853{ 854 int res; 855 char *path; 856 int mode = 0777; 857 if (!PyArg_ParseTuple(args, "s|i", &path, &mode)) 858 return NULL; 859 Py_BEGIN_ALLOW_THREADS 860#if ( defined(__WATCOMC__) || defined(_MSC_VER) || defined(PYCC_VACPP) ) && !defined(__QNX__) 861 res = mkdir(path); 862#else 863 res = mkdir(path, mode); 864#endif 865 Py_END_ALLOW_THREADS 866 if (res < 0) 867 return posix_error_with_filename(path); 868 Py_INCREF(Py_None); 869 return Py_None; 870} 871 872 873#ifdef HAVE_NICE 874static char posix_nice__doc__[] = 875"nice(inc) -> new_priority\n\ 876Decrease the priority of process and return new priority."; 877 878static PyObject * 879posix_nice(self, args) 880 PyObject *self; 881 PyObject *args; 882{ 883 int increment, value; 884 885 if (!PyArg_Parse(args, "i", &increment)) 886 return NULL; 887 value = nice(increment); 888 if (value == -1) 889 return posix_error(); 890 return PyInt_FromLong((long) value); 891} 892#endif /* HAVE_NICE */ 893 894 895static char posix_rename__doc__[] = 896"rename(old, new) -> None\n\ 897Rename a file or directory."; 898 899static PyObject * 900posix_rename(self, args) 901 PyObject *self; 902 PyObject *args; 903{ 904 return posix_2str(args, rename); 905} 906 907 908static char posix_rmdir__doc__[] = 909"rmdir(path) -> None\n\ 910Remove a directory."; 911 912static PyObject * 913posix_rmdir(self, args) 914 PyObject *self; 915 PyObject *args; 916{ 917 return posix_1str(args, rmdir); 918} 919 920 921static char posix_stat__doc__[] = 922"stat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\ 923Perform a stat system call on the given path."; 924 925static PyObject * 926posix_stat(self, args) 927 PyObject *self; 928 PyObject *args; 929{ 930 return posix_do_stat(self, args, stat); 931} 932 933 934#ifdef HAVE_SYSTEM 935static char posix_system__doc__[] = 936"system(command) -> exit_status\n\ 937Execute the command (a string) in a subshell."; 938 939static PyObject * 940posix_system(self, args) 941 PyObject *self; 942 PyObject *args; 943{ 944 char *command; 945 long sts; 946 if (!PyArg_Parse(args, "s", &command)) 947 return NULL; 948 Py_BEGIN_ALLOW_THREADS 949 sts = system(command); 950 Py_END_ALLOW_THREADS 951 return PyInt_FromLong(sts); 952} 953#endif 954 955 956static char posix_umask__doc__[] = 957"umask(new_mask) -> old_mask\n\ 958Set the current numeric umask and return the previous umask."; 959 960static PyObject * 961posix_umask(self, args) 962 PyObject *self; 963 PyObject *args; 964{ 965 int i; 966 if (!PyArg_Parse(args, "i", &i)) 967 return NULL; 968 i = umask(i); 969 if (i < 0) 970 return posix_error(); 971 return PyInt_FromLong((long)i); 972} 973 974 975static char posix_unlink__doc__[] = 976"unlink(path) -> None\n\ 977Remove a file (same as remove(path))."; 978 979static char posix_remove__doc__[] = 980"remove(path) -> None\n\ 981Remove a file (same as unlink(path))."; 982 983static PyObject * 984posix_unlink(self, args) 985 PyObject *self; 986 PyObject *args; 987{ 988 return posix_1str(args, unlink); 989} 990 991 992#ifdef HAVE_UNAME 993static char posix_uname__doc__[] = 994"uname() -> (sysname, nodename, release, version, machine)\n\ 995Return a tuple identifying the current operating system."; 996 997static PyObject * 998posix_uname(self, args) 999 PyObject *self; 1000 PyObject *args; 1001{ 1002 struct utsname u; 1003 int res; 1004 if (!PyArg_NoArgs(args)) 1005 return NULL; 1006 Py_BEGIN_ALLOW_THREADS 1007 res = uname(&u); 1008 Py_END_ALLOW_THREADS 1009 if (res < 0) 1010 return posix_error(); 1011 return Py_BuildValue("(sssss)", 1012 u.sysname, 1013 u.nodename, 1014 u.release, 1015 u.version, 1016 u.machine); 1017} 1018#endif /* HAVE_UNAME */ 1019 1020 1021static char posix_utime__doc__[] = 1022"utime(path, (atime, utime)) -> None\n\ 1023Set the access and modified time of the file to the given values."; 1024 1025static PyObject * 1026posix_utime(self, args) 1027 PyObject *self; 1028 PyObject *args; 1029{ 1030 char *path; 1031 long atime, mtime; 1032 int res; 1033 1034/* XXX should define struct utimbuf instead, above */ 1035#ifdef HAVE_UTIME_H 1036 struct utimbuf buf; 1037#define ATIME buf.actime 1038#define MTIME buf.modtime 1039#define UTIME_ARG &buf 1040#else /* HAVE_UTIME_H */ 1041 time_t buf[2]; 1042#define ATIME buf[0] 1043#define MTIME buf[1] 1044#define UTIME_ARG buf 1045#endif /* HAVE_UTIME_H */ 1046 1047 if (!PyArg_Parse(args, "(s(ll))", &path, &atime, &mtime)) 1048 return NULL; 1049 ATIME = atime; 1050 MTIME = mtime; 1051 Py_BEGIN_ALLOW_THREADS 1052 res = utime(path, UTIME_ARG); 1053 Py_END_ALLOW_THREADS 1054 if (res < 0) 1055 return posix_error_with_filename(path); 1056 Py_INCREF(Py_None); 1057 return Py_None; 1058#undef UTIME_ARG 1059#undef ATIME 1060#undef MTIME 1061} 1062 1063 1064/* Process operations */ 1065 1066static char posix__exit__doc__[] = 1067"_exit(status)\n\ 1068Exit to the system with specified status, without normal exit processing."; 1069 1070static PyObject * 1071posix__exit(self, args) 1072 PyObject *self; 1073 PyObject *args; 1074{ 1075 int sts; 1076 if (!PyArg_Parse(args, "i", &sts)) 1077 return NULL; 1078 _exit(sts); 1079 return NULL; /* Make gcc -Wall happy */ 1080} 1081 1082 1083#ifdef HAVE_EXECV 1084static char posix_execv__doc__[] = 1085"execv(path, args)\n\ 1086Execute an executable path with arguments, replacing current process.\n\ 1087\n\ 1088 path: path of executable file\n\ 1089 args: tuple or list of strings"; 1090 1091static PyObject * 1092posix_execv(self, args) 1093 PyObject *self; 1094 PyObject *args; 1095{ 1096 char *path; 1097 PyObject *argv; 1098 char **argvlist; 1099 int i, argc; 1100 PyObject *(*getitem) Py_PROTO((PyObject *, int)); 1101 1102 /* execv has two arguments: (path, argv), where 1103 argv is a list or tuple of strings. */ 1104 1105 if (!PyArg_Parse(args, "(sO)", &path, &argv)) 1106 return NULL; 1107 if (PyList_Check(argv)) { 1108 argc = PyList_Size(argv); 1109 getitem = PyList_GetItem; 1110 } 1111 else if (PyTuple_Check(argv)) { 1112 argc = PyTuple_Size(argv); 1113 getitem = PyTuple_GetItem; 1114 } 1115 else { 1116 badarg: 1117 PyErr_BadArgument(); 1118 return NULL; 1119 } 1120 1121 argvlist = PyMem_NEW(char *, argc+1); 1122 if (argvlist == NULL) 1123 return NULL; 1124 for (i = 0; i < argc; i++) { 1125 if (!PyArg_Parse((*getitem)(argv, i), "s", &argvlist[i])) { 1126 PyMem_DEL(argvlist); 1127 goto badarg; 1128 } 1129 } 1130 argvlist[argc] = NULL; 1131 1132#ifdef BAD_EXEC_PROTOTYPES 1133 execv(path, (const char **) argvlist); 1134#else /* BAD_EXEC_PROTOTYPES */ 1135 execv(path, argvlist); 1136#endif /* BAD_EXEC_PROTOTYPES */ 1137 1138 /* If we get here it's definitely an error */ 1139 1140 PyMem_DEL(argvlist); 1141 return posix_error(); 1142} 1143 1144 1145static char posix_execve__doc__[] = 1146"execve(path, args, env)\n\ 1147Execute a path with arguments and environment, replacing current process.\n\ 1148\n\ 1149 path: path of executable file\n\ 1150 args: tuple or list of arguments\n\ 1151 env: dictonary of strings mapping to strings"; 1152 1153static PyObject * 1154posix_execve(self, args) 1155 PyObject *self; 1156 PyObject *args; 1157{ 1158 char *path; 1159 PyObject *argv, *env; 1160 char **argvlist; 1161 char **envlist; 1162 PyObject *key, *val, *keys=NULL, *vals=NULL; 1163 int i, pos, argc, envc; 1164 PyObject *(*getitem) Py_PROTO((PyObject *, int)); 1165 1166 /* execve has three arguments: (path, argv, env), where 1167 argv is a list or tuple of strings and env is a dictionary 1168 like posix.environ. */ 1169 1170 if (!PyArg_Parse(args, "(sOO)", &path, &argv, &env)) 1171 return NULL; 1172 if (PyList_Check(argv)) { 1173 argc = PyList_Size(argv); 1174 getitem = PyList_GetItem; 1175 } 1176 else if (PyTuple_Check(argv)) { 1177 argc = PyTuple_Size(argv); 1178 getitem = PyTuple_GetItem; 1179 } 1180 else { 1181 PyErr_SetString(PyExc_TypeError, "argv must be tuple or list"); 1182 return NULL; 1183 } 1184 if (!PyMapping_Check(env)) { 1185 PyErr_SetString(PyExc_TypeError, "env must be mapping object"); 1186 return NULL; 1187 } 1188 1189 argvlist = PyMem_NEW(char *, argc+1); 1190 if (argvlist == NULL) { 1191 PyErr_NoMemory(); 1192 return NULL; 1193 } 1194 for (i = 0; i < argc; i++) { 1195 if (!PyArg_Parse((*getitem)(argv, i), 1196 "s;argv must be list of strings", 1197 &argvlist[i])) 1198 { 1199 goto fail_1; 1200 } 1201 } 1202 argvlist[argc] = NULL; 1203 1204 i = PyMapping_Length(env); 1205 envlist = PyMem_NEW(char *, i + 1); 1206 if (envlist == NULL) { 1207 PyErr_NoMemory(); 1208 goto fail_1; 1209 } 1210 envc = 0; 1211 keys = PyMapping_Keys(env); 1212 vals = PyMapping_Values(env); 1213 if (!keys || !vals) 1214 goto fail_2; 1215 1216 for (pos = 0; pos < i; pos++) { 1217 char *p, *k, *v; 1218 1219 key = PyList_GetItem(keys, pos); 1220 val = PyList_GetItem(vals, pos); 1221 if (!key || !val) 1222 goto fail_2; 1223 1224 if (!PyArg_Parse(key, "s;non-string key in env", &k) || 1225 !PyArg_Parse(val, "s;non-string value in env", &v)) 1226 { 1227 goto fail_2; 1228 } 1229 1230#if defined(PYOS_OS2) 1231 /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */ 1232 if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) { 1233#endif 1234 p = PyMem_NEW(char, PyString_Size(key)+PyString_Size(val) + 2); 1235 if (p == NULL) { 1236 PyErr_NoMemory(); 1237 goto fail_2; 1238 } 1239 sprintf(p, "%s=%s", k, v); 1240 envlist[envc++] = p; 1241#if defined(PYOS_OS2) 1242 } 1243#endif 1244 } 1245 envlist[envc] = 0; 1246 1247 1248#ifdef BAD_EXEC_PROTOTYPES 1249 execve(path, (const char **)argvlist, envlist); 1250#else /* BAD_EXEC_PROTOTYPES */ 1251 execve(path, argvlist, envlist); 1252#endif /* BAD_EXEC_PROTOTYPES */ 1253 1254 /* If we get here it's definitely an error */ 1255 1256 (void) posix_error(); 1257 1258 fail_2: 1259 while (--envc >= 0) 1260 PyMem_DEL(envlist[envc]); 1261 PyMem_DEL(envlist); 1262 fail_1: 1263 PyMem_DEL(argvlist); 1264 Py_XDECREF(vals); 1265 Py_XDECREF(keys); 1266 return NULL; 1267} 1268#endif /* HAVE_EXECV */ 1269 1270 1271#ifdef HAVE_FORK 1272static char posix_fork__doc__[] = 1273"fork() -> pid\n\ 1274Fork a child process.\n\ 1275\n\ 1276Return 0 to child process and PID of child to parent process."; 1277 1278static PyObject * 1279posix_fork(self, args) 1280 PyObject *self; 1281 PyObject *args; 1282{ 1283 int pid; 1284 if (!PyArg_NoArgs(args)) 1285 return NULL; 1286 pid = fork(); 1287 if (pid == -1) 1288 return posix_error(); 1289 PyOS_AfterFork(); 1290 return PyInt_FromLong((long)pid); 1291} 1292#endif 1293 1294 1295#ifdef HAVE_GETEGID 1296static char posix_getegid__doc__[] = 1297"getegid() -> egid\n\ 1298Return the current process's effective group id."; 1299 1300static PyObject * 1301posix_getegid(self, args) 1302 PyObject *self; 1303 PyObject *args; 1304{ 1305 if (!PyArg_NoArgs(args)) 1306 return NULL; 1307 return PyInt_FromLong((long)getegid()); 1308} 1309#endif 1310 1311 1312#ifdef HAVE_GETEUID 1313static char posix_geteuid__doc__[] = 1314"geteuid() -> euid\n\ 1315Return the current process's effective user id."; 1316 1317static PyObject * 1318posix_geteuid(self, args) 1319 PyObject *self; 1320 PyObject *args; 1321{ 1322 if (!PyArg_NoArgs(args)) 1323 return NULL; 1324 return PyInt_FromLong((long)geteuid()); 1325} 1326#endif 1327 1328 1329#ifdef HAVE_GETGID 1330static char posix_getgid__doc__[] = 1331"getgid() -> gid\n\ 1332Return the current process's group id."; 1333 1334static PyObject * 1335posix_getgid(self, args) 1336 PyObject *self; 1337 PyObject *args; 1338{ 1339 if (!PyArg_NoArgs(args)) 1340 return NULL; 1341 return PyInt_FromLong((long)getgid()); 1342} 1343#endif 1344 1345 1346static char posix_getpid__doc__[] = 1347"getpid() -> pid\n\ 1348Return the current process id"; 1349 1350static PyObject * 1351posix_getpid(self, args) 1352 PyObject *self; 1353 PyObject *args; 1354{ 1355 if (!PyArg_NoArgs(args)) 1356 return NULL; 1357 return PyInt_FromLong((long)getpid()); 1358} 1359 1360 1361#ifdef HAVE_GETPGRP 1362static char posix_getpgrp__doc__[] = 1363"getpgrp() -> pgrp\n\ 1364Return the current process group id."; 1365 1366static PyObject * 1367posix_getpgrp(self, args) 1368 PyObject *self; 1369 PyObject *args; 1370{ 1371 if (!PyArg_NoArgs(args)) 1372 return NULL; 1373#ifdef GETPGRP_HAVE_ARG 1374 return PyInt_FromLong((long)getpgrp(0)); 1375#else /* GETPGRP_HAVE_ARG */ 1376 return PyInt_FromLong((long)getpgrp()); 1377#endif /* GETPGRP_HAVE_ARG */ 1378} 1379#endif /* HAVE_GETPGRP */ 1380 1381 1382#ifdef HAVE_SETPGRP 1383static char posix_setpgrp__doc__[] = 1384"setpgrp() -> None\n\ 1385Make this process a session leader."; 1386 1387static PyObject * 1388posix_setpgrp(self, args) 1389 PyObject *self; 1390 PyObject *args; 1391{ 1392 if (!PyArg_NoArgs(args)) 1393 return NULL; 1394#ifdef SETPGRP_HAVE_ARG 1395 if (setpgrp(0, 0) < 0) 1396#else /* SETPGRP_HAVE_ARG */ 1397 if (setpgrp() < 0) 1398#endif /* SETPGRP_HAVE_ARG */ 1399 return posix_error(); 1400 Py_INCREF(Py_None); 1401 return Py_None; 1402} 1403 1404#endif /* HAVE_SETPGRP */ 1405 1406#ifdef HAVE_GETPPID 1407static char posix_getppid__doc__[] = 1408"getppid() -> ppid\n\ 1409Return the parent's process id."; 1410 1411static PyObject * 1412posix_getppid(self, args) 1413 PyObject *self; 1414 PyObject *args; 1415{ 1416 if (!PyArg_NoArgs(args)) 1417 return NULL; 1418 return PyInt_FromLong((long)getppid()); 1419} 1420#endif 1421 1422 1423#ifdef HAVE_GETUID 1424static char posix_getuid__doc__[] = 1425"getuid() -> uid\n\ 1426Return the current process's user id."; 1427 1428static PyObject * 1429posix_getuid(self, args) 1430 PyObject *self; 1431 PyObject *args; 1432{ 1433 if (!PyArg_NoArgs(args)) 1434 return NULL; 1435 return PyInt_FromLong((long)getuid()); 1436} 1437#endif 1438 1439 1440#ifdef HAVE_KILL 1441static char posix_kill__doc__[] = 1442"kill(pid, sig) -> None\n\ 1443Kill a process with a signal."; 1444 1445static PyObject * 1446posix_kill(self, args) 1447 PyObject *self; 1448 PyObject *args; 1449{ 1450 int pid, sig; 1451 if (!PyArg_Parse(args, "(ii)", &pid, &sig)) 1452 return NULL; 1453#if defined(PYOS_OS2) 1454 if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) { 1455 APIRET rc; 1456 if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR) 1457 return os2_error(rc); 1458 1459 } else if (sig == XCPT_SIGNAL_KILLPROC) { 1460 APIRET rc; 1461 if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR) 1462 return os2_error(rc); 1463 1464 } else 1465 return NULL; /* Unrecognized Signal Requested */ 1466#else 1467 if (kill(pid, sig) == -1) 1468 return posix_error(); 1469#endif 1470 Py_INCREF(Py_None); 1471 return Py_None; 1472} 1473#endif 1474 1475#ifdef HAVE_PLOCK 1476 1477#ifdef HAVE_SYS_LOCK_H 1478#include <sys/lock.h> 1479#endif 1480 1481static char posix_plock__doc__[] = 1482"plock(op) -> None\n\ 1483Lock program segments into memory."; 1484 1485static PyObject * 1486posix_plock(self, args) 1487 PyObject *self; 1488 PyObject *args; 1489{ 1490 int op; 1491 if (!PyArg_Parse(args, "i", &op)) 1492 return NULL; 1493 if (plock(op) == -1) 1494 return posix_error(); 1495 Py_INCREF(Py_None); 1496 return Py_None; 1497} 1498#endif 1499 1500 1501#ifdef HAVE_POPEN 1502static char posix_popen__doc__[] = 1503"popen(command [, mode='r' [, bufsize]]) -> pipe\n\ 1504Open a pipe to/from a command returning a file object."; 1505 1506#if defined(PYOS_OS2) 1507static int 1508async_system(const char *command) 1509{ 1510 char *p, errormsg[256], args[1024]; 1511 RESULTCODES rcodes; 1512 APIRET rc; 1513 char *shell = getenv("COMSPEC"); 1514 if (!shell) 1515 shell = "cmd"; 1516 1517 strcpy(args, shell); 1518 p = &args[ strlen(args)+1 ]; 1519 strcpy(p, "/c "); 1520 strcat(p, command); 1521 p += strlen(p) + 1; 1522 *p = '\0'; 1523 1524 rc = DosExecPgm(errormsg, sizeof(errormsg), 1525 EXEC_ASYNC, /* Execute Async w/o Wait for Results */ 1526 args, 1527 NULL, /* Inherit Parent's Environment */ 1528 &rcodes, shell); 1529 return rc; 1530} 1531 1532static FILE * 1533popen(const char *command, const char *mode, int pipesize, int *err) 1534{ 1535 HFILE rhan, whan; 1536 FILE *retfd = NULL; 1537 APIRET rc = DosCreatePipe(&rhan, &whan, pipesize); 1538 1539 if (rc != NO_ERROR) { 1540 *err = rc; 1541 return NULL; /* ERROR - Unable to Create Anon Pipe */ 1542 } 1543 1544 if (strchr(mode, 'r') != NULL) { /* Treat Command as a Data Source */ 1545 int oldfd = dup(1); /* Save STDOUT Handle in Another Handle */ 1546 1547 DosEnterCritSec(); /* Stop Other Threads While Changing Handles */ 1548 close(1); /* Make STDOUT Available for Reallocation */ 1549 1550 if (dup2(whan, 1) == 0) { /* Connect STDOUT to Pipe Write Side */ 1551 DosClose(whan); /* Close Now-Unused Pipe Write Handle */ 1552 1553 if (async_system(command) == NO_ERROR) 1554 retfd = fdopen(rhan, mode); /* And Return Pipe Read Handle */ 1555 } 1556 1557 dup2(oldfd, 1); /* Reconnect STDOUT to Original Handle */ 1558 DosExitCritSec(); /* Now Allow Other Threads to Run */ 1559 1560 close(oldfd); /* And Close Saved STDOUT Handle */ 1561 return retfd; /* Return fd of Pipe or NULL if Error */ 1562 1563 } else if (strchr(mode, 'w')) { /* Treat Command as a Data Sink */ 1564 int oldfd = dup(0); /* Save STDIN Handle in Another Handle */ 1565 1566 DosEnterCritSec(); /* Stop Other Threads While Changing Handles */ 1567 close(0); /* Make STDIN Available for Reallocation */ 1568 1569 if (dup2(rhan, 0) == 0) { /* Connect STDIN to Pipe Read Side */ 1570 DosClose(rhan); /* Close Now-Unused Pipe Read Handle */ 1571 1572 if (async_system(command) == NO_ERROR) 1573 retfd = fdopen(whan, mode); /* And Return Pipe Write Handle */ 1574 } 1575 1576 dup2(oldfd, 0); /* Reconnect STDIN to Original Handle */ 1577 DosExitCritSec(); /* Now Allow Other Threads to Run */ 1578 1579 close(oldfd); /* And Close Saved STDIN Handle */ 1580 return retfd; /* Return fd of Pipe or NULL if Error */ 1581 1582 } else { 1583 *err = ERROR_INVALID_ACCESS; 1584 return NULL; /* ERROR - Invalid Mode (Neither Read nor Write) */ 1585 } 1586} 1587 1588static PyObject * 1589posix_popen(self, args) 1590 PyObject *self; 1591 PyObject *args; 1592{ 1593 char *name; 1594 char *mode = "r"; 1595 int err, bufsize = -1; 1596 FILE *fp; 1597 PyObject *f; 1598 if (!PyArg_ParseTuple(args, "s|si", &name, &mode, &bufsize)) 1599 return NULL; 1600 Py_BEGIN_ALLOW_THREADS 1601 fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err); 1602 Py_END_ALLOW_THREADS 1603 if (fp == NULL) 1604 return os2_error(err); 1605 1606 f = PyFile_FromFile(fp, name, mode, fclose); 1607 if (f != NULL) 1608 PyFile_SetBufSize(f, bufsize); 1609 return f; 1610} 1611 1612#else 1613static PyObject * 1614posix_popen(self, args) 1615 PyObject *self; 1616 PyObject *args; 1617{ 1618 char *name; 1619 char *mode = "r"; 1620 int bufsize = -1; 1621 FILE *fp; 1622 PyObject *f; 1623 if (!PyArg_ParseTuple(args, "s|si", &name, &mode, &bufsize)) 1624 return NULL; 1625 Py_BEGIN_ALLOW_THREADS 1626 fp = popen(name, mode); 1627 Py_END_ALLOW_THREADS 1628 if (fp == NULL) 1629 return posix_error(); 1630 f = PyFile_FromFile(fp, name, mode, pclose); 1631 if (f != NULL) 1632 PyFile_SetBufSize(f, bufsize); 1633 return f; 1634} 1635#endif 1636 1637#endif /* HAVE_POPEN */ 1638 1639 1640#ifdef HAVE_SETUID 1641static char posix_setuid__doc__[] = 1642"setuid(uid) -> None\n\ 1643Set the current process's user id."; 1644static PyObject * 1645posix_setuid(self, args) 1646 PyObject *self; 1647 PyObject *args; 1648{ 1649 int uid; 1650 if (!PyArg_Parse(args, "i", &uid)) 1651 return NULL; 1652 if (setuid(uid) < 0) 1653 return posix_error(); 1654 Py_INCREF(Py_None); 1655 return Py_None; 1656} 1657#endif /* HAVE_SETUID */ 1658 1659 1660#ifdef HAVE_SETGID 1661static char posix_setgid__doc__[] = 1662"setgid(gid) -> None\n\ 1663Set the current process's group id."; 1664 1665static PyObject * 1666posix_setgid(self, args) 1667 PyObject *self; 1668 PyObject *args; 1669{ 1670 int gid; 1671 if (!PyArg_Parse(args, "i", &gid)) 1672 return NULL; 1673 if (setgid(gid) < 0) 1674 return posix_error(); 1675 Py_INCREF(Py_None); 1676 return Py_None; 1677} 1678#endif /* HAVE_SETGID */ 1679 1680 1681#ifdef HAVE_WAITPID 1682static char posix_waitpid__doc__[] = 1683"waitpid(pid, options) -> (pid, status)\n\ 1684Wait for completion of a give child process."; 1685 1686static PyObject * 1687posix_waitpid(self, args) 1688 PyObject *self; 1689 PyObject *args; 1690{ 1691 int pid, options, sts = 0; 1692 if (!PyArg_Parse(args, "(ii)", &pid, &options)) 1693 return NULL; 1694 Py_BEGIN_ALLOW_THREADS 1695#ifdef NeXT 1696 pid = wait4(pid, (union wait *)&sts, options, NULL); 1697#else 1698 pid = waitpid(pid, &sts, options); 1699#endif 1700 Py_END_ALLOW_THREADS 1701 if (pid == -1) 1702 return posix_error(); 1703 else 1704 return Py_BuildValue("ii", pid, sts); 1705} 1706#endif /* HAVE_WAITPID */ 1707 1708 1709#ifdef HAVE_WAIT 1710static char posix_wait__doc__[] = 1711"wait() -> (pid, status)\n\ 1712Wait for completion of a child process."; 1713 1714static PyObject * 1715posix_wait(self, args) 1716 PyObject *self; 1717 PyObject *args; 1718{ 1719 int pid, sts; 1720 Py_BEGIN_ALLOW_THREADS 1721#ifdef NeXT 1722 pid = wait((union wait *)&sts); 1723#else 1724 pid = wait(&sts); 1725#endif 1726 Py_END_ALLOW_THREADS 1727 if (pid == -1) 1728 return posix_error(); 1729 else 1730 return Py_BuildValue("ii", pid, sts); 1731} 1732#endif 1733 1734 1735static char posix_lstat__doc__[] = 1736"lstat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\ 1737Like stat(path), but do not follow symbolic links."; 1738 1739static PyObject * 1740posix_lstat(self, args) 1741 PyObject *self; 1742 PyObject *args; 1743{ 1744#ifdef HAVE_LSTAT 1745 return posix_do_stat(self, args, lstat); 1746#else /* !HAVE_LSTAT */ 1747 return posix_do_stat(self, args, stat); 1748#endif /* !HAVE_LSTAT */ 1749} 1750 1751 1752#ifdef HAVE_READLINK 1753static char posix_readlink__doc__[] = 1754"readlink(path) -> path\n\ 1755Return a string representing the path to which the symbolic link points."; 1756 1757static PyObject * 1758posix_readlink(self, args) 1759 PyObject *self; 1760 PyObject *args; 1761{ 1762 char buf[MAXPATHLEN]; 1763 char *path; 1764 int n; 1765 if (!PyArg_Parse(args, "s", &path)) 1766 return NULL; 1767 Py_BEGIN_ALLOW_THREADS 1768 n = readlink(path, buf, (int) sizeof buf); 1769 Py_END_ALLOW_THREADS 1770 if (n < 0) 1771 return posix_error_with_filename(path); 1772 return PyString_FromStringAndSize(buf, n); 1773} 1774#endif /* HAVE_READLINK */ 1775 1776 1777#ifdef HAVE_SYMLINK 1778static char posix_symlink__doc__[] = 1779"symlink(src, dst) -> None\n\ 1780Create a symbolic link."; 1781 1782static PyObject * 1783posix_symlink(self, args) 1784 PyObject *self; 1785 PyObject *args; 1786{ 1787 return posix_2str(args, symlink); 1788} 1789#endif /* HAVE_SYMLINK */ 1790 1791 1792#ifdef HAVE_TIMES 1793#ifndef HZ 1794#define HZ 60 /* Universal constant :-) */ 1795#endif /* HZ */ 1796 1797#if defined(PYCC_VACPP) && defined(PYOS_OS2) 1798static long 1799system_uptime() 1800{ 1801 ULONG value = 0; 1802 1803 Py_BEGIN_ALLOW_THREADS 1804 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value)); 1805 Py_END_ALLOW_THREADS 1806 1807 return value; 1808} 1809 1810static PyObject * 1811posix_times(self, args) 1812 PyObject *self; 1813 PyObject *args; 1814{ 1815 if (!PyArg_NoArgs(args)) 1816 return NULL; 1817 1818 /* Currently Only Uptime is Provided -- Others Later */ 1819 return Py_BuildValue("ddddd", 1820 (double)0 /* t.tms_utime / HZ */, 1821 (double)0 /* t.tms_stime / HZ */, 1822 (double)0 /* t.tms_cutime / HZ */, 1823 (double)0 /* t.tms_cstime / HZ */, 1824 (double)system_uptime() / 1000); 1825} 1826#else /* not OS2 */ 1827static PyObject * 1828posix_times(self, args) 1829 PyObject *self; 1830 PyObject *args; 1831{ 1832 struct tms t; 1833 clock_t c; 1834 if (!PyArg_NoArgs(args)) 1835 return NULL; 1836 errno = 0; 1837 c = times(&t); 1838 if (c == (clock_t) -1) 1839 return posix_error(); 1840 return Py_BuildValue("ddddd", 1841 (double)t.tms_utime / HZ, 1842 (double)t.tms_stime / HZ, 1843 (double)t.tms_cutime / HZ, 1844 (double)t.tms_cstime / HZ, 1845 (double)c / HZ); 1846} 1847#endif /* not OS2 */ 1848#endif /* HAVE_TIMES */ 1849 1850 1851#ifdef MS_WIN32 1852#define HAVE_TIMES /* so the method table will pick it up */ 1853static PyObject * 1854posix_times(self, args) 1855 PyObject *self; 1856 PyObject *args; 1857{ 1858 FILETIME create, exit, kernel, user; 1859 HANDLE hProc; 1860 if (!PyArg_NoArgs(args)) 1861 return NULL; 1862 hProc = GetCurrentProcess(); 1863 GetProcessTimes(hProc,&create, &exit, &kernel, &user); 1864 return Py_BuildValue( 1865 "ddddd", 1866 (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime)/2E6, 1867 (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6, 1868 (double)0, 1869 (double)0, 1870 (double)0); 1871} 1872#endif /* MS_WIN32 */ 1873 1874#ifdef HAVE_TIMES 1875static char posix_times__doc__[] = 1876"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\ 1877Return a tuple of floating point numbers indicating process times."; 1878#endif 1879 1880 1881#ifdef HAVE_SETSID 1882static char posix_setsid__doc__[] = 1883"setsid() -> None\n\ 1884Call the system call setsid()."; 1885 1886static PyObject * 1887posix_setsid(self, args) 1888 PyObject *self; 1889 PyObject *args; 1890{ 1891 if (!PyArg_NoArgs(args)) 1892 return NULL; 1893 if (setsid() < 0) 1894 return posix_error(); 1895 Py_INCREF(Py_None); 1896 return Py_None; 1897} 1898#endif /* HAVE_SETSID */ 1899 1900#ifdef HAVE_SETPGID 1901static char posix_setpgid__doc__[] = 1902"setpgid(pid, pgrp) -> None\n\ 1903Call the system call setpgid()."; 1904 1905static PyObject * 1906posix_setpgid(self, args) 1907 PyObject *self; 1908 PyObject *args; 1909{ 1910 int pid, pgrp; 1911 if (!PyArg_Parse(args, "(ii)", &pid, &pgrp)) 1912 return NULL; 1913 if (setpgid(pid, pgrp) < 0) 1914 return posix_error(); 1915 Py_INCREF(Py_None); 1916 return Py_None; 1917} 1918#endif /* HAVE_SETPGID */ 1919 1920 1921#ifdef HAVE_TCGETPGRP 1922static char posix_tcgetpgrp__doc__[] = 1923"tcgetpgrp(fd) -> pgid\n\ 1924Return the process group associated with the terminal given by a fd."; 1925 1926static PyObject * 1927posix_tcgetpgrp(self, args) 1928 PyObject *self; 1929 PyObject *args; 1930{ 1931 int fd, pgid; 1932 if (!PyArg_Parse(args, "i", &fd)) 1933 return NULL; 1934 pgid = tcgetpgrp(fd); 1935 if (pgid < 0) 1936 return posix_error(); 1937 return PyInt_FromLong((long)pgid); 1938} 1939#endif /* HAVE_TCGETPGRP */ 1940 1941 1942#ifdef HAVE_TCSETPGRP 1943static char posix_tcsetpgrp__doc__[] = 1944"tcsetpgrp(fd, pgid) -> None\n\ 1945Set the process group associated with the terminal given by a fd."; 1946 1947static PyObject * 1948posix_tcsetpgrp(self, args) 1949 PyObject *self; 1950 PyObject *args; 1951{ 1952 int fd, pgid; 1953 if (!PyArg_Parse(args, "(ii)", &fd, &pgid)) 1954 return NULL; 1955 if (tcsetpgrp(fd, pgid) < 0) 1956 return posix_error(); 1957 Py_INCREF(Py_None); 1958 return Py_None; 1959} 1960#endif /* HAVE_TCSETPGRP */ 1961 1962/* Functions acting on file descriptors */ 1963 1964static char posix_open__doc__[] = 1965"open(filename, flag [, mode=0777]) -> fd\n\ 1966Open a file (for low level IO)."; 1967 1968static PyObject * 1969posix_open(self, args) 1970 PyObject *self; 1971 PyObject *args; 1972{ 1973 char *file; 1974 int flag; 1975 int mode = 0777; 1976 int fd; 1977 if (!PyArg_ParseTuple(args, "si|i", &file, &flag, &mode)) 1978 return NULL; 1979 1980 Py_BEGIN_ALLOW_THREADS 1981 fd = open(file, flag, mode); 1982 Py_END_ALLOW_THREADS 1983 if (fd < 0) 1984 return posix_error_with_filename(file); 1985 return PyInt_FromLong((long)fd); 1986} 1987 1988 1989static char posix_close__doc__[] = 1990"close(fd) -> None\n\ 1991Close a file descriptor (for low level IO)."; 1992 1993static PyObject * 1994posix_close(self, args) 1995 PyObject *self; 1996 PyObject *args; 1997{ 1998 int fd, res; 1999 if (!PyArg_Parse(args, "i", &fd)) 2000 return NULL; 2001 Py_BEGIN_ALLOW_THREADS 2002 res = close(fd); 2003 Py_END_ALLOW_THREADS 2004 if (res < 0) 2005 return posix_error(); 2006 Py_INCREF(Py_None); 2007 return Py_None; 2008} 2009 2010 2011static char posix_dup__doc__[] = 2012"dup(fd) -> fd2\n\ 2013Return a duplicate of a file descriptor."; 2014 2015static PyObject * 2016posix_dup(self, args) 2017 PyObject *self; 2018 PyObject *args; 2019{ 2020 int fd; 2021 if (!PyArg_Parse(args, "i", &fd)) 2022 return NULL; 2023 Py_BEGIN_ALLOW_THREADS 2024 fd = dup(fd); 2025 Py_END_ALLOW_THREADS 2026 if (fd < 0) 2027 return posix_error(); 2028 return PyInt_FromLong((long)fd); 2029} 2030 2031 2032static char posix_dup2__doc__[] = 2033"dup2(fd, fd2) -> None\n\ 2034Duplicate file descriptor."; 2035 2036static PyObject * 2037posix_dup2(self, args) 2038 PyObject *self; 2039 PyObject *args; 2040{ 2041 int fd, fd2, res; 2042 if (!PyArg_Parse(args, "(ii)", &fd, &fd2)) 2043 return NULL; 2044 Py_BEGIN_ALLOW_THREADS 2045 res = dup2(fd, fd2); 2046 Py_END_ALLOW_THREADS 2047 if (res < 0) 2048 return posix_error(); 2049 Py_INCREF(Py_None); 2050 return Py_None; 2051} 2052 2053 2054static char posix_lseek__doc__[] = 2055"lseek(fd, pos, how) -> newpos\n\ 2056Set the current position of a file descriptor."; 2057 2058static PyObject * 2059posix_lseek(self, args) 2060 PyObject *self; 2061 PyObject *args; 2062{ 2063 int fd, how; 2064 long pos, res; 2065 if (!PyArg_Parse(args, "(ili)", &fd, &pos, &how)) 2066 return NULL; 2067#ifdef SEEK_SET 2068 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ 2069 switch (how) { 2070 case 0: how = SEEK_SET; break; 2071 case 1: how = SEEK_CUR; break; 2072 case 2: how = SEEK_END; break; 2073 } 2074#endif /* SEEK_END */ 2075 Py_BEGIN_ALLOW_THREADS 2076 res = lseek(fd, pos, how); 2077 Py_END_ALLOW_THREADS 2078 if (res < 0) 2079 return posix_error(); 2080 return PyInt_FromLong(res); 2081} 2082 2083 2084static char posix_read__doc__[] = 2085"read(fd, buffersize) -> string\n\ 2086Read a file descriptor."; 2087 2088static PyObject * 2089posix_read(self, args) 2090 PyObject *self; 2091 PyObject *args; 2092{ 2093 int fd, size, n; 2094 PyObject *buffer; 2095 if (!PyArg_Parse(args, "(ii)", &fd, &size)) 2096 return NULL; 2097 buffer = PyString_FromStringAndSize((char *)NULL, size); 2098 if (buffer == NULL) 2099 return NULL; 2100 Py_BEGIN_ALLOW_THREADS 2101 n = read(fd, PyString_AsString(buffer), size); 2102 Py_END_ALLOW_THREADS 2103 if (n < 0) { 2104 Py_DECREF(buffer); 2105 return posix_error(); 2106 } 2107 if (n != size) 2108 _PyString_Resize(&buffer, n); 2109 return buffer; 2110} 2111 2112 2113static char posix_write__doc__[] = 2114"write(fd, string) -> byteswritten\n\ 2115Write a string to a file descriptor."; 2116 2117static PyObject * 2118posix_write(self, args) 2119 PyObject *self; 2120 PyObject *args; 2121{ 2122 int fd, size; 2123 char *buffer; 2124 if (!PyArg_Parse(args, "(is#)", &fd, &buffer, &size)) 2125 return NULL; 2126 Py_BEGIN_ALLOW_THREADS 2127 size = write(fd, buffer, size); 2128 Py_END_ALLOW_THREADS 2129 if (size < 0) 2130 return posix_error(); 2131 return PyInt_FromLong((long)size); 2132} 2133 2134 2135static char posix_fstat__doc__[]= 2136"fstat(fd) -> (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ 2137Like stat(), but for an open file descriptor."; 2138 2139static PyObject * 2140posix_fstat(self, args) 2141 PyObject *self; 2142 PyObject *args; 2143{ 2144 int fd; 2145 struct stat st; 2146 int res; 2147 if (!PyArg_Parse(args, "i", &fd)) 2148 return NULL; 2149 Py_BEGIN_ALLOW_THREADS 2150 res = fstat(fd, &st); 2151 Py_END_ALLOW_THREADS 2152 if (res != 0) 2153 return posix_error(); 2154 return Py_BuildValue("(llllllllll)", 2155 (long)st.st_mode, 2156 (long)st.st_ino, 2157 (long)st.st_dev, 2158 (long)st.st_nlink, 2159 (long)st.st_uid, 2160 (long)st.st_gid, 2161 (long)st.st_size, 2162 (long)st.st_atime, 2163 (long)st.st_mtime, 2164 (long)st.st_ctime); 2165} 2166 2167 2168static char posix_fdopen__doc__[] = 2169"fdopen(fd, [, mode='r' [, bufsize]]) -> file_object\n\ 2170Return an open file object connected to a file descriptor."; 2171 2172static PyObject * 2173posix_fdopen(self, args) 2174 PyObject *self; 2175 PyObject *args; 2176{ 2177 extern int fclose Py_PROTO((FILE *)); 2178 int fd; 2179 char *mode = "r"; 2180 int bufsize = -1; 2181 FILE *fp; 2182 PyObject *f; 2183 if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize)) 2184 return NULL; 2185 2186 Py_BEGIN_ALLOW_THREADS 2187 fp = fdopen(fd, mode); 2188 Py_END_ALLOW_THREADS 2189 if (fp == NULL) 2190 return posix_error(); 2191 f = PyFile_FromFile(fp, "(fdopen)", mode, fclose); 2192 if (f != NULL) 2193 PyFile_SetBufSize(f, bufsize); 2194 return f; 2195} 2196 2197 2198#ifdef HAVE_PIPE 2199static char posix_pipe__doc__[] = 2200"pipe() -> (read_end, write_end)\n\ 2201Create a pipe."; 2202 2203static PyObject * 2204posix_pipe(self, args) 2205 PyObject *self; 2206 PyObject *args; 2207{ 2208#if defined(PYOS_OS2) 2209 HFILE read, write; 2210 APIRET rc; 2211 2212 if (!PyArg_Parse(args, "")) 2213 return NULL; 2214 2215 Py_BEGIN_ALLOW_THREADS 2216 rc = DosCreatePipe( &read, &write, 4096); 2217 Py_END_ALLOW_THREADS 2218 if (rc != NO_ERROR) 2219 return os2_error(rc); 2220 2221 return Py_BuildValue("(ii)", read, write); 2222#else 2223#if !defined(MS_WIN32) 2224 int fds[2]; 2225 int res; 2226 if (!PyArg_Parse(args, "")) 2227 return NULL; 2228 Py_BEGIN_ALLOW_THREADS 2229 res = pipe(fds); 2230 Py_END_ALLOW_THREADS 2231 if (res != 0) 2232 return posix_error(); 2233 return Py_BuildValue("(ii)", fds[0], fds[1]); 2234#else /* MS_WIN32 */ 2235 HANDLE read, write; 2236 int read_fd, write_fd; 2237 BOOL ok; 2238 if (!PyArg_Parse(args, "")) 2239 return NULL; 2240 Py_BEGIN_ALLOW_THREADS 2241 ok = CreatePipe(&read, &write, NULL, 0); 2242 Py_END_ALLOW_THREADS 2243 if (!ok) 2244 return posix_error(); 2245 read_fd = _open_osfhandle((long)read, 0); 2246 write_fd = _open_osfhandle((long)write, 1); 2247 return Py_BuildValue("(ii)", read_fd, write_fd); 2248#endif /* MS_WIN32 */ 2249#endif 2250} 2251#endif /* HAVE_PIPE */ 2252 2253 2254#ifdef HAVE_MKFIFO 2255static char posix_mkfifo__doc__[] = 2256"mkfifo(file, [, mode=0666]) -> None\n\ 2257Create a FIFO (a POSIX named pipe)."; 2258 2259static PyObject * 2260posix_mkfifo(self, args) 2261 PyObject *self; 2262 PyObject *args; 2263{ 2264 char *file; 2265 int mode = 0666; 2266 int res; 2267 if (!PyArg_ParseTuple(args, "s|i", &file, &mode)) 2268 return NULL; 2269 Py_BEGIN_ALLOW_THREADS 2270 res = mkfifo(file, mode); 2271 Py_END_ALLOW_THREADS 2272 if (res < 0) 2273 return posix_error(); 2274 Py_INCREF(Py_None); 2275 return Py_None; 2276} 2277#endif 2278 2279 2280#ifdef HAVE_FTRUNCATE 2281static char posix_ftruncate__doc__[] = 2282"ftruncate(fd, length) -> None\n\ 2283Truncate a file to a specified length."; 2284 2285static PyObject * 2286posix_ftruncate(self, args) 2287 PyObject *self; /* Not used */ 2288 PyObject *args; 2289{ 2290 int fd; 2291 long length; 2292 int res; 2293 2294 if (!PyArg_Parse(args, "(il)", &fd, &length)) 2295 return NULL; 2296 2297 Py_BEGIN_ALLOW_THREADS 2298 res = ftruncate(fd, length); 2299 Py_END_ALLOW_THREADS 2300 if (res < 0) { 2301 PyErr_SetFromErrno(PyExc_IOError); 2302 return NULL; 2303 } 2304 Py_INCREF(Py_None); 2305 return Py_None; 2306} 2307#endif 2308 2309#ifdef NeXT 2310#define HAVE_PUTENV 2311/* Steve Spicklemire got this putenv from NeXTAnswers */ 2312static int 2313putenv(char *newval) 2314{ 2315 extern char **environ; 2316 2317 static int firstTime = 1; 2318 char **ep; 2319 char *cp; 2320 int esiz; 2321 char *np; 2322 2323 if (!(np = strchr(newval, '='))) 2324 return 1; 2325 *np = '\0'; 2326 2327 /* look it up */ 2328 for (ep=environ ; *ep ; ep++) 2329 { 2330 /* this should always be true... */ 2331 if (cp = strchr(*ep, '=')) 2332 { 2333 *cp = '\0'; 2334 if (!strcmp(*ep, newval)) 2335 { 2336 /* got it! */ 2337 *cp = '='; 2338 break; 2339 } 2340 *cp = '='; 2341 } 2342 else 2343 { 2344 *np = '='; 2345 return 1; 2346 } 2347 } 2348 2349 *np = '='; 2350 if (*ep) 2351 { 2352 /* the string was already there: 2353 just replace it with the new one */ 2354 *ep = newval; 2355 return 0; 2356 } 2357 2358 /* expand environ by one */ 2359 for (esiz=2, ep=environ ; *ep ; ep++) 2360 esiz++; 2361 if (firstTime) 2362 { 2363 char **epp; 2364 char **newenv; 2365 if (!(newenv = malloc(esiz * sizeof(char *)))) 2366 return 1; 2367 2368 for (ep=environ, epp=newenv ; *ep ;) 2369 *epp++ = *ep++; 2370 *epp++ = newval; 2371 *epp = (char *) 0; 2372 environ = newenv; 2373 } 2374 else 2375 { 2376 if (!(environ = realloc(environ, esiz * sizeof(char *)))) 2377 return 1; 2378 environ[esiz - 2] = newval; 2379 environ[esiz - 1] = (char *) 0; 2380 firstTime = 0; 2381 } 2382 2383 return 0; 2384} 2385#endif /* NeXT */ 2386 2387 2388#ifdef HAVE_PUTENV 2389static char posix_putenv__doc__[] = 2390"putenv(key, value) -> None\n\ 2391Change or add an environment variable."; 2392 2393#ifdef __BEOS__ 2394/* We have putenv(), but not in the headers (as of PR2). - [cjh] */ 2395int putenv( const char *str ); 2396#endif 2397 2398static PyObject * 2399posix_putenv(self, args) 2400 PyObject *self; 2401 PyObject *args; 2402{ 2403 char *s1, *s2; 2404 char *new; 2405 2406 if (!PyArg_ParseTuple(args, "ss", &s1, &s2)) 2407 return NULL; 2408 2409#if defined(PYOS_OS2) 2410 if (stricmp(s1, "BEGINLIBPATH") == 0) { 2411 APIRET rc; 2412 2413 if (strlen(s2) == 0) /* If New Value is an Empty String */ 2414 s2 = NULL; /* Then OS/2 API Wants a NULL to Undefine It */ 2415 2416 rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH); 2417 if (rc != NO_ERROR) 2418 return os2_error(rc); 2419 2420 } else if (stricmp(s1, "ENDLIBPATH") == 0) { 2421 APIRET rc; 2422 2423 if (strlen(s2) == 0) /* If New Value is an Empty String */ 2424 s2 = NULL; /* Then OS/2 API Wants a NULL to Undefine It */ 2425 2426 rc = DosSetExtLIBPATH(s2, END_LIBPATH); 2427 if (rc != NO_ERROR) 2428 return os2_error(rc); 2429 } else { 2430#endif 2431 2432 /* XXX This leaks memory -- not easy to fix :-( */ 2433 if ((new = malloc(strlen(s1) + strlen(s2) + 2)) == NULL) 2434 return PyErr_NoMemory(); 2435 (void) sprintf(new, "%s=%s", s1, s2); 2436 if (putenv(new)) { 2437 posix_error(); 2438 return NULL; 2439 } 2440 2441#if defined(PYOS_OS2) 2442 } 2443#endif 2444 Py_INCREF(Py_None); 2445 return Py_None; 2446} 2447#endif /* putenv */ 2448 2449#ifdef HAVE_STRERROR 2450static char posix_strerror__doc__[] = 2451"strerror(code) -> string\n\ 2452Translate an error code to a message string."; 2453 2454PyObject * 2455posix_strerror(self, args) 2456 PyObject *self; 2457 PyObject *args; 2458{ 2459 int code; 2460 char *message; 2461 if (!PyArg_ParseTuple(args, "i", &code)) 2462 return NULL; 2463 message = strerror(code); 2464 if (message == NULL) { 2465 PyErr_SetString(PyExc_ValueError, 2466 "strerror code out of range"); 2467 return NULL; 2468 } 2469 return PyString_FromString(message); 2470} 2471#endif /* strerror */ 2472 2473 2474#ifdef HAVE_SYS_WAIT_H 2475 2476#ifdef WIFSTOPPED 2477static char posix_WIFSTOPPED__doc__[] = 2478"WIFSTOPPED(status) -> Boolean\n\ 2479See Unix documentation."; 2480 2481static PyObject * 2482posix_WIFSTOPPED(self, args) 2483 PyObject *self; 2484 PyObject *args; 2485{ 2486 int status = 0; 2487 2488 if (!PyArg_Parse(args, "i", &status)) 2489 { 2490 return NULL; 2491 } 2492 2493 return Py_BuildValue("i", WIFSTOPPED(status)); 2494} 2495#endif /* WIFSTOPPED */ 2496 2497#ifdef WIFSIGNALED 2498static char posix_WIFSIGNALED__doc__[] = 2499"WIFSIGNALED(status) -> Boolean\n\ 2500See Unix documentation."; 2501 2502static PyObject * 2503posix_WIFSIGNALED(self, args) 2504 PyObject *self; 2505 PyObject *args; 2506{ 2507 int status = 0; 2508 2509 if (!PyArg_Parse(args, "i", &status)) 2510 { 2511 return NULL; 2512 } 2513 2514 return Py_BuildValue("i", WIFSIGNALED(status)); 2515} 2516#endif /* WIFSIGNALED */ 2517 2518#ifdef WIFEXITED 2519static char posix_WIFEXITED__doc__[] = 2520"WIFEXITED(status) -> Boolean\n\ 2521See Unix documentation."; 2522 2523static PyObject * 2524posix_WIFEXITED(self, args) 2525 PyObject *self; 2526 PyObject *args; 2527{ 2528 int status = 0; 2529 2530 if (!PyArg_Parse(args, "i", &status)) 2531 { 2532 return NULL; 2533 } 2534 2535 return Py_BuildValue("i", WIFEXITED(status)); 2536} 2537#endif /* WIFEXITED */ 2538 2539#ifdef WIFSTOPPED 2540static char posix_WEXITSTATUS__doc__[] = 2541"WEXITSTATUS(status) -> integer\n\ 2542See Unix documentation."; 2543 2544static PyObject * 2545posix_WEXITSTATUS(self, args) 2546 PyObject *self; 2547 PyObject *args; 2548{ 2549 int status = 0; 2550 2551 if (!PyArg_Parse(args, "i", &status)) 2552 { 2553 return NULL; 2554 } 2555 2556 return Py_BuildValue("i", WEXITSTATUS(status)); 2557} 2558#endif /* WEXITSTATUS */ 2559 2560#ifdef WTERMSIG 2561static char posix_WTERMSIG__doc__[] = 2562"WTERMSIG(status) -> integer\n\ 2563See Unix documentation."; 2564 2565static PyObject * 2566posix_WTERMSIG(self, args) 2567 PyObject *self; 2568 PyObject *args; 2569{ 2570 int status = 0; 2571 2572 if (!PyArg_Parse(args, "i", &status)) 2573 { 2574 return NULL; 2575 } 2576 2577 return Py_BuildValue("i", WTERMSIG(status)); 2578} 2579#endif /* WTERMSIG */ 2580 2581#ifdef WSTOPSIG 2582static char posix_WSTOPSIG__doc__[] = 2583"WSTOPSIG(status) -> integer\n\ 2584See Unix documentation."; 2585 2586static PyObject * 2587posix_WSTOPSIG(self, args) 2588 PyObject *self; 2589 PyObject *args; 2590{ 2591 int status = 0; 2592 2593 if (!PyArg_Parse(args, "i", &status)) 2594 { 2595 return NULL; 2596 } 2597 2598 return Py_BuildValue("i", WSTOPSIG(status)); 2599} 2600#endif /* WSTOPSIG */ 2601 2602#endif /* HAVE_SYS_WAIT_H */ 2603 2604 2605static PyMethodDef posix_methods[] = { 2606 {"chdir", posix_chdir, 0, posix_chdir__doc__}, 2607 {"chmod", posix_chmod, 0, posix_chmod__doc__}, 2608#ifdef HAVE_CHOWN 2609 {"chown", posix_chown, 0, posix_chown__doc__}, 2610#endif /* HAVE_CHOWN */ 2611#ifdef HAVE_GETCWD 2612 {"getcwd", posix_getcwd, 0, posix_getcwd__doc__}, 2613#endif 2614#ifdef HAVE_LINK 2615 {"link", posix_link, 0, posix_link__doc__}, 2616#endif /* HAVE_LINK */ 2617 {"listdir", posix_listdir, 0, posix_listdir__doc__}, 2618 {"lstat", posix_lstat, 0, posix_lstat__doc__}, 2619 {"mkdir", posix_mkdir, 1, posix_mkdir__doc__}, 2620#ifdef HAVE_NICE 2621 {"nice", posix_nice, 0, posix_nice__doc__}, 2622#endif /* HAVE_NICE */ 2623#ifdef HAVE_READLINK 2624 {"readlink", posix_readlink, 0, posix_readlink__doc__}, 2625#endif /* HAVE_READLINK */ 2626 {"rename", posix_rename, 0, posix_rename__doc__}, 2627 {"rmdir", posix_rmdir, 0, posix_rmdir__doc__}, 2628 {"stat", posix_stat, 0, posix_stat__doc__}, 2629#ifdef HAVE_SYMLINK 2630 {"symlink", posix_symlink, 0, posix_symlink__doc__}, 2631#endif /* HAVE_SYMLINK */ 2632#ifdef HAVE_SYSTEM 2633 {"system", posix_system, 0, posix_system__doc__}, 2634#endif 2635 {"umask", posix_umask, 0, posix_umask__doc__}, 2636#ifdef HAVE_UNAME 2637 {"uname", posix_uname, 0, posix_uname__doc__}, 2638#endif /* HAVE_UNAME */ 2639 {"unlink", posix_unlink, 0, posix_unlink__doc__}, 2640 {"remove", posix_unlink, 0, posix_remove__doc__}, 2641 {"utime", posix_utime, 0, posix_utime__doc__}, 2642#ifdef HAVE_TIMES 2643 {"times", posix_times, 0, posix_times__doc__}, 2644#endif /* HAVE_TIMES */ 2645 {"_exit", posix__exit, 0, posix__exit__doc__}, 2646#ifdef HAVE_EXECV 2647 {"execv", posix_execv, 0, posix_execv__doc__}, 2648 {"execve", posix_execve, 0, posix_execve__doc__}, 2649#endif /* HAVE_EXECV */ 2650#ifdef HAVE_FORK 2651 {"fork", posix_fork, 0, posix_fork__doc__}, 2652#endif /* HAVE_FORK */ 2653#ifdef HAVE_GETEGID 2654 {"getegid", posix_getegid, 0, posix_getegid__doc__}, 2655#endif /* HAVE_GETEGID */ 2656#ifdef HAVE_GETEUID 2657 {"geteuid", posix_geteuid, 0, posix_geteuid__doc__}, 2658#endif /* HAVE_GETEUID */ 2659#ifdef HAVE_GETGID 2660 {"getgid", posix_getgid, 0, posix_getgid__doc__}, 2661#endif /* HAVE_GETGID */ 2662 {"getpid", posix_getpid, 0, posix_getpid__doc__}, 2663#ifdef HAVE_GETPGRP 2664 {"getpgrp", posix_getpgrp, 0, posix_getpgrp__doc__}, 2665#endif /* HAVE_GETPGRP */ 2666#ifdef HAVE_GETPPID 2667 {"getppid", posix_getppid, 0, posix_getppid__doc__}, 2668#endif /* HAVE_GETPPID */ 2669#ifdef HAVE_GETUID 2670 {"getuid", posix_getuid, 0, posix_getuid__doc__}, 2671#endif /* HAVE_GETUID */ 2672#ifdef HAVE_KILL 2673 {"kill", posix_kill, 0, posix_kill__doc__}, 2674#endif /* HAVE_KILL */ 2675#ifdef HAVE_PLOCK 2676 {"plock", posix_plock, 0, posix_plock__doc__}, 2677#endif /* HAVE_PLOCK */ 2678#ifdef HAVE_POPEN 2679 {"popen", posix_popen, 1, posix_popen__doc__}, 2680#endif /* HAVE_POPEN */ 2681#ifdef HAVE_SETUID 2682 {"setuid", posix_setuid, 0, posix_setuid__doc__}, 2683#endif /* HAVE_SETUID */ 2684#ifdef HAVE_SETGID 2685 {"setgid", posix_setgid, 0, posix_setgid__doc__}, 2686#endif /* HAVE_SETGID */ 2687#ifdef HAVE_SETPGRP 2688 {"setpgrp", posix_setpgrp, 0, posix_setpgrp__doc__}, 2689#endif /* HAVE_SETPGRP */ 2690#ifdef HAVE_WAIT 2691 {"wait", posix_wait, 0, posix_wait__doc__}, 2692#endif /* HAVE_WAIT */ 2693#ifdef HAVE_WAITPID 2694 {"waitpid", posix_waitpid, 0, posix_waitpid__doc__}, 2695#endif /* HAVE_WAITPID */ 2696#ifdef HAVE_SETSID 2697 {"setsid", posix_setsid, 0, posix_setsid__doc__}, 2698#endif /* HAVE_SETSID */ 2699#ifdef HAVE_SETPGID 2700 {"setpgid", posix_setpgid, 0, posix_setpgid__doc__}, 2701#endif /* HAVE_SETPGID */ 2702#ifdef HAVE_TCGETPGRP 2703 {"tcgetpgrp", posix_tcgetpgrp, 0, posix_tcgetpgrp__doc__}, 2704#endif /* HAVE_TCGETPGRP */ 2705#ifdef HAVE_TCSETPGRP 2706 {"tcsetpgrp", posix_tcsetpgrp, 0, posix_tcsetpgrp__doc__}, 2707#endif /* HAVE_TCSETPGRP */ 2708 {"open", posix_open, 1, posix_open__doc__}, 2709 {"close", posix_close, 0, posix_close__doc__}, 2710 {"dup", posix_dup, 0, posix_dup__doc__}, 2711 {"dup2", posix_dup2, 0, posix_dup2__doc__}, 2712 {"lseek", posix_lseek, 0, posix_lseek__doc__}, 2713 {"read", posix_read, 0, posix_read__doc__}, 2714 {"write", posix_write, 0, posix_write__doc__}, 2715 {"fstat", posix_fstat, 0, posix_fstat__doc__}, 2716 {"fdopen", posix_fdopen, 1, posix_fdopen__doc__}, 2717#ifdef HAVE_PIPE 2718 {"pipe", posix_pipe, 0, posix_pipe__doc__}, 2719#endif 2720#ifdef HAVE_MKFIFO 2721 {"mkfifo", posix_mkfifo, 1, posix_mkfifo__doc__}, 2722#endif 2723#ifdef HAVE_FTRUNCATE 2724 {"ftruncate", posix_ftruncate, 1, posix_ftruncate__doc__}, 2725#endif 2726#ifdef HAVE_PUTENV 2727 {"putenv", posix_putenv, 1, posix_putenv__doc__}, 2728#endif 2729#ifdef HAVE_STRERROR 2730 {"strerror", posix_strerror, 1, posix_strerror__doc__}, 2731#endif 2732#ifdef HAVE_SYS_WAIT_H 2733#ifdef WIFSTOPPED 2734 {"WIFSTOPPED", posix_WIFSTOPPED, 0, posix_WIFSTOPPED__doc__}, 2735#endif /* WIFSTOPPED */ 2736#ifdef WIFSIGNALED 2737 {"WIFSIGNALED", posix_WIFSIGNALED, 0, posix_WIFSIGNALED__doc__}, 2738#endif /* WIFSIGNALED */ 2739#ifdef WIFEXITED 2740 {"WIFEXITED", posix_WIFEXITED, 0, posix_WIFEXITED__doc__}, 2741#endif /* WIFEXITED */ 2742#ifdef WEXITSTATUS 2743 {"WEXITSTATUS", posix_WEXITSTATUS, 0, posix_WEXITSTATUS__doc__}, 2744#endif /* WEXITSTATUS */ 2745#ifdef WTERMSIG 2746 {"WTERMSIG", posix_WTERMSIG, 0, posix_WTERMSIG__doc__}, 2747#endif /* WTERMSIG */ 2748#ifdef WSTOPSIG 2749 {"WSTOPSIG", posix_WSTOPSIG, 0, posix_WSTOPSIG__doc__}, 2750#endif /* WSTOPSIG */ 2751#endif /* HAVE_SYS_WAIT_H */ 2752 {NULL, NULL} /* Sentinel */ 2753}; 2754 2755 2756static int 2757ins(d, symbol, value) 2758 PyObject* d; 2759 char* symbol; 2760 long value; 2761{ 2762 PyObject* v = PyInt_FromLong(value); 2763 if (!v || PyDict_SetItemString(d, symbol, v) < 0) 2764 return -1; /* triggers fatal error */ 2765 2766 Py_DECREF(v); 2767 return 0; 2768} 2769 2770#if defined(PYOS_OS2) 2771/* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */ 2772static int insertvalues(PyObject *d) 2773{ 2774 APIRET rc; 2775 ULONG values[QSV_MAX+1]; 2776 PyObject *v; 2777 char *ver, tmp[10]; 2778 2779 Py_BEGIN_ALLOW_THREADS 2780 rc = DosQuerySysInfo(1, QSV_MAX, &values[1], sizeof(values)); 2781 Py_END_ALLOW_THREADS 2782 2783 if (rc != NO_ERROR) { 2784 os2_error(rc); 2785 return -1; 2786 } 2787 2788 if (ins(d, "meminstalled", values[QSV_TOTPHYSMEM])) return -1; 2789 if (ins(d, "memkernel", values[QSV_TOTRESMEM])) return -1; 2790 if (ins(d, "memvirtual", values[QSV_TOTAVAILMEM])) return -1; 2791 if (ins(d, "maxpathlen", values[QSV_MAX_PATH_LENGTH])) return -1; 2792 if (ins(d, "maxnamelen", values[QSV_MAX_COMP_LENGTH])) return -1; 2793 if (ins(d, "revision", values[QSV_VERSION_REVISION])) return -1; 2794 if (ins(d, "timeslice", values[QSV_MIN_SLICE])) return -1; 2795 2796 switch (values[QSV_VERSION_MINOR]) { 2797 case 0: ver = "2.00"; break; 2798 case 10: ver = "2.10"; break; 2799 case 11: ver = "2.11"; break; 2800 case 30: ver = "3.00"; break; 2801 case 40: ver = "4.00"; break; 2802 case 50: ver = "5.00"; break; 2803 default: 2804 sprintf(tmp, "%d-%d", values[QSV_VERSION_MAJOR], 2805 values[QSV_VERSION_MINOR]); 2806 ver = &tmp[0]; 2807 } 2808 2809 /* Add Indicator of the Version of the Operating System */ 2810 v = PyString_FromString(ver); 2811 if (!v || PyDict_SetItemString(d, "version", v) < 0) 2812 return -1; 2813 Py_DECREF(v); 2814 2815 /* Add Indicator of Which Drive was Used to Boot the System */ 2816 tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1; 2817 tmp[1] = ':'; 2818 tmp[2] = '\0'; 2819 2820 v = PyString_FromString(tmp); 2821 if (!v || PyDict_SetItemString(d, "bootdrive", v) < 0) 2822 return -1; 2823 Py_DECREF(v); 2824 2825 return 0; 2826} 2827#endif 2828 2829static int 2830all_ins(d) 2831 PyObject* d; 2832{ 2833#ifdef WNOHANG 2834 if (ins(d, "WNOHANG", (long)WNOHANG)) return -1; 2835#endif 2836#ifdef O_RDONLY 2837 if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1; 2838#endif 2839#ifdef O_WRONLY 2840 if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1; 2841#endif 2842#ifdef O_RDWR 2843 if (ins(d, "O_RDWR", (long)O_RDWR)) return -1; 2844#endif 2845#ifdef O_NDELAY 2846 if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1; 2847#endif 2848#ifdef O_NONBLOCK 2849 if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1; 2850#endif 2851#ifdef O_APPEND 2852 if (ins(d, "O_APPEND", (long)O_APPEND)) return -1; 2853#endif 2854#ifdef O_DSYNC 2855 if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1; 2856#endif 2857#ifdef O_RSYNC 2858 if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1; 2859#endif 2860#ifdef O_SYNC 2861 if (ins(d, "O_SYNC", (long)O_SYNC)) return -1; 2862#endif 2863#ifdef O_NOCTTY 2864 if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1; 2865#endif 2866#ifdef O_CREAT 2867 if (ins(d, "O_CREAT", (long)O_CREAT)) return -1; 2868#endif 2869#ifdef O_EXCL 2870 if (ins(d, "O_EXCL", (long)O_EXCL)) return -1; 2871#endif 2872#ifdef O_TRUNC 2873 if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1; 2874#endif 2875#ifdef O_BINARY 2876 if (ins(d, "O_BINARY", (long)O_BINARY)) return -1; 2877#endif 2878#ifdef O_TEXT 2879 if (ins(d, "O_TEXT", (long)O_TEXT)) return -1; 2880#endif 2881 2882#if defined(PYOS_OS2) 2883 if (insertvalues(d)) return -1; 2884#endif 2885 return 0; 2886} 2887 2888 2889#if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(__QNX__) 2890#define INITFUNC initnt 2891#define MODNAME "nt" 2892#else 2893#if defined(PYOS_OS2) 2894#define INITFUNC initos2 2895#define MODNAME "os2" 2896#else 2897#define INITFUNC initposix 2898#define MODNAME "posix" 2899#endif 2900#endif 2901 2902DL_EXPORT(void) 2903INITFUNC() 2904{ 2905 PyObject *m, *d, *v; 2906 2907 m = Py_InitModule4(MODNAME, 2908 posix_methods, 2909 posix__doc__, 2910 (PyObject *)NULL, 2911 PYTHON_API_VERSION); 2912 d = PyModule_GetDict(m); 2913 2914 /* Initialize environ dictionary */ 2915 v = convertenviron(); 2916 if (v == NULL || PyDict_SetItemString(d, "environ", v) != 0) 2917 return; 2918 Py_DECREF(v); 2919 2920 if (all_ins(d)) 2921 return; 2922 2923 Py_INCREF(PyExc_OSError); 2924 PosixError = PyExc_OSError; 2925 PyDict_SetItemString(d, "error", PosixError); 2926} 2927