Home | History | Annotate | Download | only in Modules
      1 
      2 /* POSIX module implementation */
      3 
      4 /* This file is also used for Windows NT/MS-Win and OS/2.  In that case the
      5    module actually calls itself 'nt' or 'os2', not 'posix', and a few
      6    functions are either unimplemented or implemented differently.  The source
      7    assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
      8    of the compiler used.  Different compilers define their own feature
      9    test macro, e.g. '__BORLANDC__' or '_MSC_VER'.  For OS/2, the compiler
     10    independent macro PYOS_OS2 should be defined.  On OS/2 the default
     11    compiler is assumed to be IBM's VisualAge C++ (VACPP).  PYCC_GCC is used
     12    as the compiler specific macro for the EMX port of gcc to OS/2. */
     13 
     14 #ifdef __APPLE__
     15    /*
     16     * Step 1 of support for weak-linking a number of symbols existing on
     17     * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
     18     * at the end of this file for more information.
     19     */
     20 #  pragma weak lchown
     21 #  pragma weak statvfs
     22 #  pragma weak fstatvfs
     23 
     24 #endif /* __APPLE__ */
     25 
     26 #define PY_SSIZE_T_CLEAN
     27 
     28 #include "Python.h"
     29 #include "structseq.h"
     30 #ifndef MS_WINDOWS
     31 #include "posixmodule.h"
     32 #endif
     33 
     34 #if defined(__VMS)
     35 #    include <unixio.h>
     36 #endif /* defined(__VMS) */
     37 
     38 #ifdef __cplusplus
     39 extern "C" {
     40 #endif
     41 
     42 PyDoc_STRVAR(posix__doc__,
     43 "This module provides access to operating system functionality that is\n\
     44 standardized by the C Standard and the POSIX standard (a thinly\n\
     45 disguised Unix interface).  Refer to the library manual and\n\
     46 corresponding Unix manual entries for more information on calls.");
     47 
     48 #ifndef Py_USING_UNICODE
     49 /* This is used in signatures of functions. */
     50 #define Py_UNICODE void
     51 #endif
     52 
     53 #if defined(PYOS_OS2)
     54 #define  INCL_DOS
     55 #define  INCL_DOSERRORS
     56 #define  INCL_DOSPROCESS
     57 #define  INCL_NOPMAPI
     58 #include <os2.h>
     59 #if defined(PYCC_GCC)
     60 #include <ctype.h>
     61 #include <io.h>
     62 #include <stdio.h>
     63 #include <process.h>
     64 #endif
     65 #include "osdefs.h"
     66 #endif
     67 
     68 #ifdef HAVE_SYS_TYPES_H
     69 #include <sys/types.h>
     70 #endif /* HAVE_SYS_TYPES_H */
     71 
     72 #ifdef HAVE_SYS_STAT_H
     73 #include <sys/stat.h>
     74 #endif /* HAVE_SYS_STAT_H */
     75 
     76 #ifdef HAVE_SYS_WAIT_H
     77 #include <sys/wait.h>           /* For WNOHANG */
     78 #endif
     79 
     80 #ifdef HAVE_SIGNAL_H
     81 #include <signal.h>
     82 #endif
     83 
     84 #ifdef HAVE_FCNTL_H
     85 #include <fcntl.h>
     86 #endif /* HAVE_FCNTL_H */
     87 
     88 #ifdef HAVE_GRP_H
     89 #include <grp.h>
     90 #endif
     91 
     92 #ifdef HAVE_SYSEXITS_H
     93 #include <sysexits.h>
     94 #endif /* HAVE_SYSEXITS_H */
     95 
     96 #ifdef HAVE_SYS_LOADAVG_H
     97 #include <sys/loadavg.h>
     98 #endif
     99 
    100 /* Various compilers have only certain posix functions */
    101 /* XXX Gosh I wish these were all moved into pyconfig.h */
    102 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
    103 #include <process.h>
    104 #else
    105 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
    106 #define HAVE_GETCWD     1
    107 #define HAVE_OPENDIR    1
    108 #define HAVE_SYSTEM     1
    109 #if defined(__OS2__)
    110 #define HAVE_EXECV      1
    111 #define HAVE_WAIT       1
    112 #endif
    113 #include <process.h>
    114 #else
    115 #ifdef __BORLANDC__             /* Borland compiler */
    116 #define HAVE_EXECV      1
    117 #define HAVE_GETCWD     1
    118 #define HAVE_OPENDIR    1
    119 #define HAVE_PIPE       1
    120 #define HAVE_POPEN      1
    121 #define HAVE_SYSTEM     1
    122 #define HAVE_WAIT       1
    123 #else
    124 #ifdef _MSC_VER         /* Microsoft compiler */
    125 #define HAVE_GETCWD     1
    126 #define HAVE_SPAWNV     1
    127 #define HAVE_EXECV      1
    128 #define HAVE_PIPE       1
    129 #define HAVE_POPEN      1
    130 #define HAVE_SYSTEM     1
    131 #define HAVE_CWAIT      1
    132 #define HAVE_FSYNC      1
    133 #define fsync _commit
    134 #else
    135 #if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
    136 /* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
    137 #else                   /* all other compilers */
    138 /* Unix functions that the configure script doesn't check for */
    139 #define HAVE_EXECV      1
    140 #define HAVE_FORK       1
    141 #if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
    142 #define HAVE_FORK1      1
    143 #endif
    144 #define HAVE_GETCWD     1
    145 #define HAVE_GETEGID    1
    146 #define HAVE_GETEUID    1
    147 #define HAVE_GETGID     1
    148 #define HAVE_GETPPID    1
    149 #define HAVE_GETUID     1
    150 #define HAVE_KILL       1
    151 #define HAVE_OPENDIR    1
    152 #define HAVE_PIPE       1
    153 #ifndef __rtems__
    154 #define HAVE_POPEN      1
    155 #endif
    156 #define HAVE_SYSTEM     1
    157 #define HAVE_WAIT       1
    158 #define HAVE_TTYNAME    1
    159 #endif  /* PYOS_OS2 && PYCC_GCC && __VMS */
    160 #endif  /* _MSC_VER */
    161 #endif  /* __BORLANDC__ */
    162 #endif  /* ! __WATCOMC__ || __QNX__ */
    163 #endif /* ! __IBMC__ */
    164 
    165 #ifndef _MSC_VER
    166 
    167 #if defined(__sgi)&&_COMPILER_VERSION>=700
    168 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
    169    (default) */
    170 extern char        *ctermid_r(char *);
    171 #endif
    172 
    173 #ifndef HAVE_UNISTD_H
    174 #if defined(PYCC_VACPP)
    175 extern int mkdir(char *);
    176 #else
    177 #if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
    178 extern int mkdir(const char *);
    179 #else
    180 extern int mkdir(const char *, mode_t);
    181 #endif
    182 #endif
    183 #if defined(__IBMC__) || defined(__IBMCPP__)
    184 extern int chdir(char *);
    185 extern int rmdir(char *);
    186 #else
    187 extern int chdir(const char *);
    188 extern int rmdir(const char *);
    189 #endif
    190 #ifdef __BORLANDC__
    191 extern int chmod(const char *, int);
    192 #else
    193 extern int chmod(const char *, mode_t);
    194 #endif
    195 /*#ifdef HAVE_FCHMOD
    196 extern int fchmod(int, mode_t);
    197 #endif*/
    198 /*#ifdef HAVE_LCHMOD
    199 extern int lchmod(const char *, mode_t);
    200 #endif*/
    201 extern int chown(const char *, uid_t, gid_t);
    202 extern char *getcwd(char *, int);
    203 extern char *strerror(int);
    204 extern int link(const char *, const char *);
    205 extern int rename(const char *, const char *);
    206 extern int stat(const char *, struct stat *);
    207 extern int unlink(const char *);
    208 extern int pclose(FILE *);
    209 #ifdef HAVE_SYMLINK
    210 extern int symlink(const char *, const char *);
    211 #endif /* HAVE_SYMLINK */
    212 #ifdef HAVE_LSTAT
    213 extern int lstat(const char *, struct stat *);
    214 #endif /* HAVE_LSTAT */
    215 #endif /* !HAVE_UNISTD_H */
    216 
    217 #endif /* !_MSC_VER */
    218 
    219 #ifdef HAVE_UTIME_H
    220 #include <utime.h>
    221 #endif /* HAVE_UTIME_H */
    222 
    223 #ifdef HAVE_SYS_UTIME_H
    224 #include <sys/utime.h>
    225 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
    226 #endif /* HAVE_SYS_UTIME_H */
    227 
    228 #ifdef HAVE_SYS_TIMES_H
    229 #include <sys/times.h>
    230 #endif /* HAVE_SYS_TIMES_H */
    231 
    232 #ifdef HAVE_SYS_PARAM_H
    233 #include <sys/param.h>
    234 #endif /* HAVE_SYS_PARAM_H */
    235 
    236 #ifdef HAVE_SYS_UTSNAME_H
    237 #include <sys/utsname.h>
    238 #endif /* HAVE_SYS_UTSNAME_H */
    239 
    240 #ifdef HAVE_DIRENT_H
    241 #include <dirent.h>
    242 #define NAMLEN(dirent) strlen((dirent)->d_name)
    243 #else
    244 #if defined(__WATCOMC__) && !defined(__QNX__)
    245 #include <direct.h>
    246 #define NAMLEN(dirent) strlen((dirent)->d_name)
    247 #else
    248 #define dirent direct
    249 #define NAMLEN(dirent) (dirent)->d_namlen
    250 #endif
    251 #ifdef HAVE_SYS_NDIR_H
    252 #include <sys/ndir.h>
    253 #endif
    254 #ifdef HAVE_SYS_DIR_H
    255 #include <sys/dir.h>
    256 #endif
    257 #ifdef HAVE_NDIR_H
    258 #include <ndir.h>
    259 #endif
    260 #endif
    261 
    262 #ifdef _MSC_VER
    263 #ifdef HAVE_DIRECT_H
    264 #include <direct.h>
    265 #endif
    266 #ifdef HAVE_IO_H
    267 #include <io.h>
    268 #endif
    269 #ifdef HAVE_PROCESS_H
    270 #include <process.h>
    271 #endif
    272 #include "osdefs.h"
    273 #include <malloc.h>
    274 #include <windows.h>
    275 #include <shellapi.h>   /* for ShellExecute() */
    276 #define popen   _popen
    277 #define pclose  _pclose
    278 #endif /* _MSC_VER */
    279 
    280 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
    281 #include <io.h>
    282 #endif /* OS2 */
    283 
    284 #ifndef MAXPATHLEN
    285 #if defined(PATH_MAX) && PATH_MAX > 1024
    286 #define MAXPATHLEN PATH_MAX
    287 #else
    288 #define MAXPATHLEN 1024
    289 #endif
    290 #endif /* MAXPATHLEN */
    291 
    292 #ifdef UNION_WAIT
    293 /* Emulate some macros on systems that have a union instead of macros */
    294 
    295 #ifndef WIFEXITED
    296 #define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
    297 #endif
    298 
    299 #ifndef WEXITSTATUS
    300 #define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
    301 #endif
    302 
    303 #ifndef WTERMSIG
    304 #define WTERMSIG(u_wait) ((u_wait).w_termsig)
    305 #endif
    306 
    307 #define WAIT_TYPE union wait
    308 #define WAIT_STATUS_INT(s) (s.w_status)
    309 
    310 #else /* !UNION_WAIT */
    311 #define WAIT_TYPE int
    312 #define WAIT_STATUS_INT(s) (s)
    313 #endif /* UNION_WAIT */
    314 
    315 /* Issue #1983: pid_t can be longer than a C long on some systems */
    316 #if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
    317 #define PARSE_PID "i"
    318 #define PyLong_FromPid PyInt_FromLong
    319 #define PyLong_AsPid PyInt_AsLong
    320 #elif SIZEOF_PID_T == SIZEOF_LONG
    321 #define PARSE_PID "l"
    322 #define PyLong_FromPid PyInt_FromLong
    323 #define PyLong_AsPid PyInt_AsLong
    324 #elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
    325 #define PARSE_PID "L"
    326 #define PyLong_FromPid PyLong_FromLongLong
    327 #define PyLong_AsPid PyInt_AsLongLong
    328 #else
    329 #error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)"
    330 #endif /* SIZEOF_PID_T */
    331 
    332 /* Don't use the "_r" form if we don't need it (also, won't have a
    333    prototype for it, at least on Solaris -- maybe others as well?). */
    334 #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
    335 #define USE_CTERMID_R
    336 #endif
    337 
    338 #if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)
    339 #define USE_TMPNAM_R
    340 #endif
    341 
    342 #if defined(MAJOR_IN_MKDEV)
    343 #include <sys/mkdev.h>
    344 #else
    345 #if defined(MAJOR_IN_SYSMACROS)
    346 #include <sys/sysmacros.h>
    347 #endif
    348 #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
    349 #include <sys/mkdev.h>
    350 #endif
    351 #endif
    352 
    353 
    354 #ifndef MS_WINDOWS
    355 PyObject *
    356 _PyInt_FromUid(uid_t uid)
    357 {
    358     if (uid <= LONG_MAX)
    359         return PyInt_FromLong(uid);
    360     return PyLong_FromUnsignedLong(uid);
    361 }
    362 
    363 PyObject *
    364 _PyInt_FromGid(gid_t gid)
    365 {
    366     if (gid <= LONG_MAX)
    367         return PyInt_FromLong(gid);
    368     return PyLong_FromUnsignedLong(gid);
    369 }
    370 
    371 int
    372 _Py_Uid_Converter(PyObject *obj, void *p)
    373 {
    374     int overflow;
    375     long result;
    376     if (PyFloat_Check(obj)) {
    377         PyErr_SetString(PyExc_TypeError,
    378                         "integer argument expected, got float");
    379         return 0;
    380     }
    381     result = PyLong_AsLongAndOverflow(obj, &overflow);
    382     if (overflow < 0)
    383         goto OverflowDown;
    384     if (!overflow && result == -1) {
    385         /* error or -1 */
    386         if (PyErr_Occurred())
    387             return 0;
    388         *(uid_t *)p = (uid_t)-1;
    389     }
    390     else {
    391         /* unsigned uid_t */
    392         unsigned long uresult;
    393         if (overflow > 0) {
    394             uresult = PyLong_AsUnsignedLong(obj);
    395             if (PyErr_Occurred()) {
    396                 if (PyErr_ExceptionMatches(PyExc_OverflowError))
    397                     goto OverflowUp;
    398                 return 0;
    399             }
    400         } else {
    401             if (result < 0)
    402                 goto OverflowDown;
    403             uresult = result;
    404         }
    405         if (sizeof(uid_t) < sizeof(long) &&
    406             (unsigned long)(uid_t)uresult != uresult)
    407             goto OverflowUp;
    408         *(uid_t *)p = (uid_t)uresult;
    409     }
    410     return 1;
    411 
    412 OverflowDown:
    413     PyErr_SetString(PyExc_OverflowError,
    414                     "user id is less than minimum");
    415     return 0;
    416 
    417 OverflowUp:
    418     PyErr_SetString(PyExc_OverflowError,
    419                     "user id is greater than maximum");
    420     return 0;
    421 }
    422 
    423 int
    424 _Py_Gid_Converter(PyObject *obj, void *p)
    425 {
    426     int overflow;
    427     long result;
    428     if (PyFloat_Check(obj)) {
    429         PyErr_SetString(PyExc_TypeError,
    430                         "integer argument expected, got float");
    431         return 0;
    432     }
    433     result = PyLong_AsLongAndOverflow(obj, &overflow);
    434     if (overflow < 0)
    435         goto OverflowDown;
    436     if (!overflow && result == -1) {
    437         /* error or -1 */
    438         if (PyErr_Occurred())
    439             return 0;
    440         *(gid_t *)p = (gid_t)-1;
    441     }
    442     else {
    443         /* unsigned gid_t */
    444         unsigned long uresult;
    445         if (overflow > 0) {
    446             uresult = PyLong_AsUnsignedLong(obj);
    447             if (PyErr_Occurred()) {
    448                 if (PyErr_ExceptionMatches(PyExc_OverflowError))
    449                     goto OverflowUp;
    450                 return 0;
    451             }
    452         } else {
    453             if (result < 0)
    454                 goto OverflowDown;
    455             uresult = result;
    456         }
    457         if (sizeof(gid_t) < sizeof(long) &&
    458             (unsigned long)(gid_t)uresult != uresult)
    459             goto OverflowUp;
    460         *(gid_t *)p = (gid_t)uresult;
    461     }
    462     return 1;
    463 
    464 OverflowDown:
    465     PyErr_SetString(PyExc_OverflowError,
    466                     "group id is less than minimum");
    467     return 0;
    468 
    469 OverflowUp:
    470     PyErr_SetString(PyExc_OverflowError,
    471                     "group id is greater than maximum");
    472     return 0;
    473 }
    474 #endif /* MS_WINDOWS */
    475 
    476 
    477 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
    478 static int
    479 _Py_Dev_Converter(PyObject *obj, void *p)
    480 {
    481     PyObject *index = PyNumber_Index(obj);
    482     if (index == NULL)
    483         return 0;
    484     if (PyInt_Check(index)) {
    485         long x = PyInt_AS_LONG(index);
    486         Py_DECREF(index);
    487         if (x == -1 && PyErr_Occurred())
    488             return 0;
    489         if (x < 0) {
    490             PyErr_SetString(PyExc_OverflowError,
    491                             "can't convert negative number to unsigned long");
    492             return 0;
    493         }
    494         *((dev_t *)p) = (unsigned long)x;
    495     }
    496     else if (PyLong_Check(index)) {
    497 #ifdef HAVE_LONG_LONG
    498         *((dev_t *)p) = PyLong_AsUnsignedLongLong(index);
    499 #else
    500         *((dev_t *)p) = PyLong_AsUnsignedLong(index);
    501 #endif
    502         Py_DECREF(index);
    503         if (PyErr_Occurred())
    504             return 0;
    505     }
    506     else {
    507         Py_DECREF(index);
    508         PyErr_Format(PyExc_TypeError,
    509                      "expected int/long, %s found",
    510                      Py_TYPE(obj)->tp_name);
    511         return 0;
    512     }
    513     return 1;
    514 }
    515 
    516 #endif
    517 
    518 #ifdef HAVE_LONG_LONG
    519 static PyObject *
    520 _PyInt_FromDev(PY_LONG_LONG v)
    521 {
    522     if (LONG_MIN <= v && v <= LONG_MAX)
    523         return PyInt_FromLong((long)v);
    524     else
    525         return PyLong_FromLongLong(v);
    526 }
    527 #else
    528 #  define _PyInt_FromDev PyInt_FromLong
    529 #endif
    530 
    531 
    532 #if defined _MSC_VER && _MSC_VER >= 1400
    533 /* Microsoft CRT in VS2005 and higher will verify that a filehandle is
    534  * valid and raise an assertion if it isn't.
    535  * Normally, an invalid fd is likely to be a C program error and therefore
    536  * an assertion can be useful, but it does contradict the POSIX standard
    537  * which for write(2) states:
    538  *    "Otherwise, -1 shall be returned and errno set to indicate the error."
    539  *    "[EBADF] The fildes argument is not a valid file descriptor open for
    540  *     writing."
    541  * Furthermore, python allows the user to enter any old integer
    542  * as a fd and should merely raise a python exception on error.
    543  * The Microsoft CRT doesn't provide an official way to check for the
    544  * validity of a file descriptor, but we can emulate its internal behaviour
    545  * by using the exported __pinfo data member and knowledge of the
    546  * internal structures involved.
    547  * The structures below must be updated for each version of visual studio
    548  * according to the file internal.h in the CRT source, until MS comes
    549  * up with a less hacky way to do this.
    550  * (all of this is to avoid globally modifying the CRT behaviour using
    551  * _set_invalid_parameter_handler() and _CrtSetReportMode())
    552  */
    553 /* The actual size of the structure is determined at runtime.
    554  * Only the first items must be present.
    555  */
    556 typedef struct {
    557     intptr_t osfhnd;
    558     char osfile;
    559 } my_ioinfo;
    560 
    561 extern __declspec(dllimport) char * __pioinfo[];
    562 #define IOINFO_L2E 5
    563 #define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
    564 #define IOINFO_ARRAYS 64
    565 #define _NHANDLE_           (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
    566 #define FOPEN 0x01
    567 #define _NO_CONSOLE_FILENO (intptr_t)-2
    568 
    569 /* This function emulates what the windows CRT does to validate file handles */
    570 int
    571 _PyVerify_fd(int fd)
    572 {
    573     const int i1 = fd >> IOINFO_L2E;
    574     const int i2 = fd & ((1 << IOINFO_L2E) - 1);
    575 
    576     static int sizeof_ioinfo = 0;
    577 
    578     /* Determine the actual size of the ioinfo structure,
    579      * as used by the CRT loaded in memory
    580      */
    581     if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
    582         sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
    583     }
    584     if (sizeof_ioinfo == 0) {
    585         /* This should not happen... */
    586         goto fail;
    587     }
    588 
    589     /* See that it isn't a special CLEAR fileno */
    590     if (fd != _NO_CONSOLE_FILENO) {
    591         /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that.  Instead
    592          * we check pointer validity and other info
    593          */
    594         if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
    595             /* finally, check that the file is open */
    596             my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
    597             if (info->osfile & FOPEN) {
    598                 return 1;
    599             }
    600         }
    601     }
    602   fail:
    603     errno = EBADF;
    604     return 0;
    605 }
    606 
    607 /* the special case of checking dup2.  The target fd must be in a sensible range */
    608 static int
    609 _PyVerify_fd_dup2(int fd1, int fd2)
    610 {
    611     if (!_PyVerify_fd(fd1))
    612         return 0;
    613     if (fd2 == _NO_CONSOLE_FILENO)
    614         return 0;
    615     if ((unsigned)fd2 < _NHANDLE_)
    616         return 1;
    617     else
    618         return 0;
    619 }
    620 #else
    621 /* dummy version. _PyVerify_fd() is already defined in fileobject.h */
    622 #define _PyVerify_fd_dup2(A, B) (1)
    623 #endif
    624 
    625 /* Return a dictionary corresponding to the POSIX environment table */
    626 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
    627 /* On Darwin/MacOSX a shared library or framework has no access to
    628 ** environ directly, we must obtain it with _NSGetEnviron(). See also
    629 ** man environ(7).
    630 */
    631 #include <crt_externs.h>
    632 static char **environ;
    633 #elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
    634 extern char **environ;
    635 #endif /* !_MSC_VER */
    636 
    637 static PyObject *
    638 convertenviron(void)
    639 {
    640     PyObject *d;
    641     char **e;
    642 #if defined(PYOS_OS2)
    643     APIRET rc;
    644     char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
    645 #endif
    646     d = PyDict_New();
    647     if (d == NULL)
    648         return NULL;
    649 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
    650     if (environ == NULL)
    651         environ = *_NSGetEnviron();
    652 #endif
    653     if (environ == NULL)
    654         return d;
    655     /* This part ignores errors */
    656     for (e = environ; *e != NULL; e++) {
    657         PyObject *k;
    658         PyObject *v;
    659         char *p = strchr(*e, '=');
    660         if (p == NULL)
    661             continue;
    662         k = PyString_FromStringAndSize(*e, (int)(p-*e));
    663         if (k == NULL) {
    664             PyErr_Clear();
    665             continue;
    666         }
    667         v = PyString_FromString(p+1);
    668         if (v == NULL) {
    669             PyErr_Clear();
    670             Py_DECREF(k);
    671             continue;
    672         }
    673         if (PyDict_GetItem(d, k) == NULL) {
    674             if (PyDict_SetItem(d, k, v) != 0)
    675                 PyErr_Clear();
    676         }
    677         Py_DECREF(k);
    678         Py_DECREF(v);
    679     }
    680 #if defined(PYOS_OS2)
    681     rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
    682     if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
    683         PyObject *v = PyString_FromString(buffer);
    684             PyDict_SetItemString(d, "BEGINLIBPATH", v);
    685         Py_DECREF(v);
    686     }
    687     rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
    688     if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
    689         PyObject *v = PyString_FromString(buffer);
    690             PyDict_SetItemString(d, "ENDLIBPATH", v);
    691         Py_DECREF(v);
    692     }
    693 #endif
    694     return d;
    695 }
    696 
    697 
    698 /* Set a POSIX-specific error from errno, and return NULL */
    699 
    700 static PyObject *
    701 posix_error(void)
    702 {
    703     return PyErr_SetFromErrno(PyExc_OSError);
    704 }
    705 static PyObject *
    706 posix_error_with_filename(char* name)
    707 {
    708     return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
    709 }
    710 
    711 #ifdef MS_WINDOWS
    712 static PyObject *
    713 posix_error_with_unicode_filename(Py_UNICODE* name)
    714 {
    715     return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name);
    716 }
    717 #endif /* MS_WINDOWS */
    718 
    719 
    720 static PyObject *
    721 posix_error_with_allocated_filename(char* name)
    722 {
    723     PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
    724     PyMem_Free(name);
    725     return rc;
    726 }
    727 
    728 #ifdef MS_WINDOWS
    729 static PyObject *
    730 win32_error(char* function, char* filename)
    731 {
    732     /* XXX We should pass the function name along in the future.
    733        (_winreg.c also wants to pass the function name.)
    734        This would however require an additional param to the
    735        Windows error object, which is non-trivial.
    736     */
    737     errno = GetLastError();
    738     if (filename)
    739         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
    740     else
    741         return PyErr_SetFromWindowsErr(errno);
    742 }
    743 
    744 static PyObject *
    745 win32_error_unicode(char* function, Py_UNICODE* filename)
    746 {
    747     /* XXX - see win32_error for comments on 'function' */
    748     errno = GetLastError();
    749     if (filename)
    750         return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);
    751     else
    752         return PyErr_SetFromWindowsErr(errno);
    753 }
    754 
    755 static int
    756 convert_to_unicode(PyObject **param)
    757 {
    758     if (PyUnicode_CheckExact(*param))
    759         Py_INCREF(*param);
    760     else if (PyUnicode_Check(*param))
    761         /* For a Unicode subtype that's not a Unicode object,
    762            return a true Unicode object with the same data. */
    763         *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(*param),
    764                                        PyUnicode_GET_SIZE(*param));
    765     else
    766         *param = PyUnicode_FromEncodedObject(*param,
    767                                              Py_FileSystemDefaultEncoding,
    768                                              "strict");
    769     return (*param) != NULL;
    770 }
    771 
    772 #endif /* MS_WINDOWS */
    773 
    774 #if defined(PYOS_OS2)
    775 /**********************************************************************
    776  *         Helper Function to Trim and Format OS/2 Messages
    777  **********************************************************************/
    778 static void
    779 os2_formatmsg(char *msgbuf, int msglen, char *reason)
    780 {
    781     msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
    782 
    783     if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
    784         char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
    785 
    786         while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc)))
    787             *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
    788     }
    789 
    790     /* Add Optional Reason Text */
    791     if (reason) {
    792         strcat(msgbuf, " : ");
    793         strcat(msgbuf, reason);
    794     }
    795 }
    796 
    797 /**********************************************************************
    798  *             Decode an OS/2 Operating System Error Code
    799  *
    800  * A convenience function to lookup an OS/2 error code and return a
    801  * text message we can use to raise a Python exception.
    802  *
    803  * Notes:
    804  *   The messages for errors returned from the OS/2 kernel reside in
    805  *   the file OSO001.MSG in the \OS2 directory hierarchy.
    806  *
    807  **********************************************************************/
    808 static char *
    809 os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
    810 {
    811     APIRET rc;
    812     ULONG  msglen;
    813 
    814     /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
    815     Py_BEGIN_ALLOW_THREADS
    816     rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
    817                        errorcode, "oso001.msg", &msglen);
    818     Py_END_ALLOW_THREADS
    819 
    820     if (rc == NO_ERROR)
    821         os2_formatmsg(msgbuf, msglen, reason);
    822     else
    823         PyOS_snprintf(msgbuf, msgbuflen,
    824                       "unknown OS error #%d", errorcode);
    825 
    826     return msgbuf;
    827 }
    828 
    829 /* Set an OS/2-specific error and return NULL.  OS/2 kernel
    830    errors are not in a global variable e.g. 'errno' nor are
    831    they congruent with posix error numbers. */
    832 
    833 static PyObject *
    834 os2_error(int code)
    835 {
    836     char text[1024];
    837     PyObject *v;
    838 
    839     os2_strerror(text, sizeof(text), code, "");
    840 
    841     v = Py_BuildValue("(is)", code, text);
    842     if (v != NULL) {
    843         PyErr_SetObject(PyExc_OSError, v);
    844         Py_DECREF(v);
    845     }
    846     return NULL; /* Signal to Python that an Exception is Pending */
    847 }
    848 
    849 #endif /* OS2 */
    850 
    851 /* POSIX generic methods */
    852 
    853 static PyObject *
    854 posix_fildes(PyObject *fdobj, int (*func)(int))
    855 {
    856     int fd;
    857     int res;
    858     fd = PyObject_AsFileDescriptor(fdobj);
    859     if (fd < 0)
    860         return NULL;
    861     if (!_PyVerify_fd(fd))
    862         return posix_error();
    863     Py_BEGIN_ALLOW_THREADS
    864     res = (*func)(fd);
    865     Py_END_ALLOW_THREADS
    866     if (res < 0)
    867         return posix_error();
    868     Py_INCREF(Py_None);
    869     return Py_None;
    870 }
    871 
    872 static PyObject *
    873 posix_1str(PyObject *args, char *format, int (*func)(const char*))
    874 {
    875     char *path1 = NULL;
    876     int res;
    877     if (!PyArg_ParseTuple(args, format,
    878                           Py_FileSystemDefaultEncoding, &path1))
    879         return NULL;
    880     Py_BEGIN_ALLOW_THREADS
    881     res = (*func)(path1);
    882     Py_END_ALLOW_THREADS
    883     if (res < 0)
    884         return posix_error_with_allocated_filename(path1);
    885     PyMem_Free(path1);
    886     Py_INCREF(Py_None);
    887     return Py_None;
    888 }
    889 
    890 static PyObject *
    891 posix_2str(PyObject *args,
    892            char *format,
    893            int (*func)(const char *, const char *))
    894 {
    895     char *path1 = NULL, *path2 = NULL;
    896     int res;
    897     if (!PyArg_ParseTuple(args, format,
    898                           Py_FileSystemDefaultEncoding, &path1,
    899                           Py_FileSystemDefaultEncoding, &path2))
    900         return NULL;
    901     Py_BEGIN_ALLOW_THREADS
    902     res = (*func)(path1, path2);
    903     Py_END_ALLOW_THREADS
    904     PyMem_Free(path1);
    905     PyMem_Free(path2);
    906     if (res != 0)
    907         /* XXX how to report both path1 and path2??? */
    908         return posix_error();
    909     Py_INCREF(Py_None);
    910     return Py_None;
    911 }
    912 
    913 #ifdef MS_WINDOWS
    914 static PyObject*
    915 win32_1str(PyObject* args, char* func,
    916            char* format, BOOL (__stdcall *funcA)(LPCSTR),
    917            char* wformat, BOOL (__stdcall *funcW)(LPWSTR))
    918 {
    919     PyObject *uni;
    920     char *ansi;
    921     BOOL result;
    922 
    923     if (!PyArg_ParseTuple(args, wformat, &uni))
    924         PyErr_Clear();
    925     else {
    926         Py_BEGIN_ALLOW_THREADS
    927         result = funcW(PyUnicode_AsUnicode(uni));
    928         Py_END_ALLOW_THREADS
    929         if (!result)
    930             return win32_error_unicode(func, PyUnicode_AsUnicode(uni));
    931         Py_INCREF(Py_None);
    932         return Py_None;
    933     }
    934     if (!PyArg_ParseTuple(args, format, &ansi))
    935         return NULL;
    936     Py_BEGIN_ALLOW_THREADS
    937     result = funcA(ansi);
    938     Py_END_ALLOW_THREADS
    939     if (!result)
    940         return win32_error(func, ansi);
    941     Py_INCREF(Py_None);
    942     return Py_None;
    943 
    944 }
    945 
    946 /* This is a reimplementation of the C library's chdir function,
    947    but one that produces Win32 errors instead of DOS error codes.
    948    chdir is essentially a wrapper around SetCurrentDirectory; however,
    949    it also needs to set "magic" environment variables indicating
    950    the per-drive current directory, which are of the form =<drive>: */
    951 static BOOL __stdcall
    952 win32_chdir(LPCSTR path)
    953 {
    954     char new_path[MAX_PATH+1];
    955     int result;
    956     char env[4] = "=x:";
    957 
    958     if(!SetCurrentDirectoryA(path))
    959         return FALSE;
    960     result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
    961     if (!result)
    962         return FALSE;
    963     /* In the ANSI API, there should not be any paths longer
    964        than MAX_PATH. */
    965     assert(result <= MAX_PATH+1);
    966     if (strncmp(new_path, "\\\\", 2) == 0 ||
    967         strncmp(new_path, "//", 2) == 0)
    968         /* UNC path, nothing to do. */
    969         return TRUE;
    970     env[1] = new_path[0];
    971     return SetEnvironmentVariableA(env, new_path);
    972 }
    973 
    974 /* The Unicode version differs from the ANSI version
    975    since the current directory might exceed MAX_PATH characters */
    976 static BOOL __stdcall
    977 win32_wchdir(LPCWSTR path)
    978 {
    979     wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
    980     int result;
    981     wchar_t env[4] = L"=x:";
    982 
    983     if(!SetCurrentDirectoryW(path))
    984         return FALSE;
    985     result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
    986     if (!result)
    987         return FALSE;
    988     if (result > MAX_PATH+1) {
    989         new_path = malloc(result * sizeof(wchar_t));
    990         if (!new_path) {
    991             SetLastError(ERROR_OUTOFMEMORY);
    992             return FALSE;
    993         }
    994         result = GetCurrentDirectoryW(result, new_path);
    995         if (!result) {
    996             free(new_path);
    997             return FALSE;
    998         }
    999     }
   1000     if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
   1001         wcsncmp(new_path, L"//", 2) == 0)
   1002         /* UNC path, nothing to do. */
   1003         return TRUE;
   1004     env[1] = new_path[0];
   1005     result = SetEnvironmentVariableW(env, new_path);
   1006     if (new_path != _new_path)
   1007         free(new_path);
   1008     return result;
   1009 }
   1010 #endif
   1011 
   1012 /* choose the appropriate stat and fstat functions and return structs */
   1013 #undef STAT
   1014 #undef FSTAT
   1015 #undef STRUCT_STAT
   1016 #if defined(MS_WIN64) || defined(MS_WINDOWS)
   1017 #       define STAT win32_stat
   1018 #       define FSTAT win32_fstat
   1019 #       define STRUCT_STAT struct win32_stat
   1020 #else
   1021 #       define STAT stat
   1022 #       define FSTAT fstat
   1023 #       define STRUCT_STAT struct stat
   1024 #endif
   1025 
   1026 #ifdef MS_WINDOWS
   1027 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
   1028    - time stamps are restricted to second resolution
   1029    - file modification times suffer from forth-and-back conversions between
   1030      UTC and local time
   1031    Therefore, we implement our own stat, based on the Win32 API directly.
   1032 */
   1033 #define HAVE_STAT_NSEC 1
   1034 
   1035 struct win32_stat{
   1036     int st_dev;
   1037     __int64 st_ino;
   1038     unsigned short st_mode;
   1039     int st_nlink;
   1040     int st_uid;
   1041     int st_gid;
   1042     int st_rdev;
   1043     __int64 st_size;
   1044     time_t st_atime;
   1045     int st_atime_nsec;
   1046     time_t st_mtime;
   1047     int st_mtime_nsec;
   1048     time_t st_ctime;
   1049     int st_ctime_nsec;
   1050 };
   1051 
   1052 static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
   1053 
   1054 static void
   1055 FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
   1056 {
   1057     /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
   1058     /* Cannot simply cast and dereference in_ptr,
   1059        since it might not be aligned properly */
   1060     __int64 in;
   1061     memcpy(&in, in_ptr, sizeof(in));
   1062     *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
   1063     *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
   1064 }
   1065 
   1066 static void
   1067 time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
   1068 {
   1069     /* XXX endianness */
   1070     __int64 out;
   1071     out = time_in + secs_between_epochs;
   1072     out = out * 10000000 + nsec_in / 100;
   1073     memcpy(out_ptr, &out, sizeof(out));
   1074 }
   1075 
   1076 /* Below, we *know* that ugo+r is 0444 */
   1077 #if _S_IREAD != 0400
   1078 #error Unsupported C library
   1079 #endif
   1080 static int
   1081 attributes_to_mode(DWORD attr)
   1082 {
   1083     int m = 0;
   1084     if (attr & FILE_ATTRIBUTE_DIRECTORY)
   1085         m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
   1086     else
   1087         m |= _S_IFREG;
   1088     if (attr & FILE_ATTRIBUTE_READONLY)
   1089         m |= 0444;
   1090     else
   1091         m |= 0666;
   1092     return m;
   1093 }
   1094 
   1095 static int
   1096 attribute_data_to_stat(WIN32_FILE_ATTRIBUTE_DATA *info, struct win32_stat *result)
   1097 {
   1098     memset(result, 0, sizeof(*result));
   1099     result->st_mode = attributes_to_mode(info->dwFileAttributes);
   1100     result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
   1101     FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
   1102     FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
   1103     FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
   1104 
   1105     return 0;
   1106 }
   1107 
   1108 static BOOL
   1109 attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
   1110 {
   1111     HANDLE hFindFile;
   1112     WIN32_FIND_DATAA FileData;
   1113     hFindFile = FindFirstFileA(pszFile, &FileData);
   1114     if (hFindFile == INVALID_HANDLE_VALUE)
   1115         return FALSE;
   1116     FindClose(hFindFile);
   1117     pfad->dwFileAttributes = FileData.dwFileAttributes;
   1118     pfad->ftCreationTime   = FileData.ftCreationTime;
   1119     pfad->ftLastAccessTime = FileData.ftLastAccessTime;
   1120     pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
   1121     pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
   1122     pfad->nFileSizeLow     = FileData.nFileSizeLow;
   1123     return TRUE;
   1124 }
   1125 
   1126 static BOOL
   1127 attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
   1128 {
   1129     HANDLE hFindFile;
   1130     WIN32_FIND_DATAW FileData;
   1131     hFindFile = FindFirstFileW(pszFile, &FileData);
   1132     if (hFindFile == INVALID_HANDLE_VALUE)
   1133         return FALSE;
   1134     FindClose(hFindFile);
   1135     pfad->dwFileAttributes = FileData.dwFileAttributes;
   1136     pfad->ftCreationTime   = FileData.ftCreationTime;
   1137     pfad->ftLastAccessTime = FileData.ftLastAccessTime;
   1138     pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
   1139     pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
   1140     pfad->nFileSizeLow     = FileData.nFileSizeLow;
   1141     return TRUE;
   1142 }
   1143 
   1144 static int
   1145 win32_stat(const char* path, struct win32_stat *result)
   1146 {
   1147     WIN32_FILE_ATTRIBUTE_DATA info;
   1148     int code;
   1149     char *dot;
   1150     if (!GetFileAttributesExA(path, GetFileExInfoStandard, &info)) {
   1151         if (GetLastError() != ERROR_SHARING_VIOLATION) {
   1152             /* Protocol violation: we explicitly clear errno, instead of
   1153                setting it to a POSIX error. Callers should use GetLastError. */
   1154             errno = 0;
   1155             return -1;
   1156         } else {
   1157             /* Could not get attributes on open file. Fall back to
   1158                reading the directory. */
   1159             if (!attributes_from_dir(path, &info)) {
   1160                 /* Very strange. This should not fail now */
   1161                 errno = 0;
   1162                 return -1;
   1163             }
   1164         }
   1165     }
   1166     code = attribute_data_to_stat(&info, result);
   1167     if (code != 0)
   1168         return code;
   1169     /* Set S_IFEXEC if it is an .exe, .bat, ... */
   1170     dot = strrchr(path, '.');
   1171     if (dot) {
   1172         if (stricmp(dot, ".bat") == 0 ||
   1173         stricmp(dot, ".cmd") == 0 ||
   1174         stricmp(dot, ".exe") == 0 ||
   1175         stricmp(dot, ".com") == 0)
   1176             result->st_mode |= 0111;
   1177     }
   1178     return code;
   1179 }
   1180 
   1181 static int
   1182 win32_wstat(const wchar_t* path, struct win32_stat *result)
   1183 {
   1184     int code;
   1185     const wchar_t *dot;
   1186     WIN32_FILE_ATTRIBUTE_DATA info;
   1187     if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
   1188         if (GetLastError() != ERROR_SHARING_VIOLATION) {
   1189             /* Protocol violation: we explicitly clear errno, instead of
   1190                setting it to a POSIX error. Callers should use GetLastError. */
   1191             errno = 0;
   1192             return -1;
   1193         } else {
   1194             /* Could not get attributes on open file. Fall back to
   1195                reading the directory. */
   1196             if (!attributes_from_dir_w(path, &info)) {
   1197                 /* Very strange. This should not fail now */
   1198                 errno = 0;
   1199                 return -1;
   1200             }
   1201         }
   1202     }
   1203     code = attribute_data_to_stat(&info, result);
   1204     if (code < 0)
   1205         return code;
   1206     /* Set IFEXEC if it is an .exe, .bat, ... */
   1207     dot = wcsrchr(path, '.');
   1208     if (dot) {
   1209         if (_wcsicmp(dot, L".bat") == 0 ||
   1210             _wcsicmp(dot, L".cmd") == 0 ||
   1211             _wcsicmp(dot, L".exe") == 0 ||
   1212             _wcsicmp(dot, L".com") == 0)
   1213             result->st_mode |= 0111;
   1214     }
   1215     return code;
   1216 }
   1217 
   1218 static int
   1219 win32_fstat(int file_number, struct win32_stat *result)
   1220 {
   1221     BY_HANDLE_FILE_INFORMATION info;
   1222     HANDLE h;
   1223     int type;
   1224 
   1225     h = (HANDLE)_get_osfhandle(file_number);
   1226 
   1227     /* Protocol violation: we explicitly clear errno, instead of
   1228        setting it to a POSIX error. Callers should use GetLastError. */
   1229     errno = 0;
   1230 
   1231     if (h == INVALID_HANDLE_VALUE) {
   1232         /* This is really a C library error (invalid file handle).
   1233            We set the Win32 error to the closes one matching. */
   1234         SetLastError(ERROR_INVALID_HANDLE);
   1235         return -1;
   1236     }
   1237     memset(result, 0, sizeof(*result));
   1238 
   1239     type = GetFileType(h);
   1240     if (type == FILE_TYPE_UNKNOWN) {
   1241         DWORD error = GetLastError();
   1242         if (error != 0) {
   1243         return -1;
   1244         }
   1245         /* else: valid but unknown file */
   1246     }
   1247 
   1248     if (type != FILE_TYPE_DISK) {
   1249         if (type == FILE_TYPE_CHAR)
   1250             result->st_mode = _S_IFCHR;
   1251         else if (type == FILE_TYPE_PIPE)
   1252             result->st_mode = _S_IFIFO;
   1253         return 0;
   1254     }
   1255 
   1256     if (!GetFileInformationByHandle(h, &info)) {
   1257         return -1;
   1258     }
   1259 
   1260     /* similar to stat() */
   1261     result->st_mode = attributes_to_mode(info.dwFileAttributes);
   1262     result->st_size = (((__int64)info.nFileSizeHigh)<<32) + info.nFileSizeLow;
   1263     FILE_TIME_to_time_t_nsec(&info.ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
   1264     FILE_TIME_to_time_t_nsec(&info.ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
   1265     FILE_TIME_to_time_t_nsec(&info.ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
   1266     /* specific to fstat() */
   1267     result->st_nlink = info.nNumberOfLinks;
   1268     result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
   1269     return 0;
   1270 }
   1271 
   1272 #endif /* MS_WINDOWS */
   1273 
   1274 PyDoc_STRVAR(stat_result__doc__,
   1275 "stat_result: Result from stat or lstat.\n\n\
   1276 This object may be accessed either as a tuple of\n\
   1277   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
   1278 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
   1279 \n\
   1280 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
   1281 or st_flags, they are available as attributes only.\n\
   1282 \n\
   1283 See os.stat for more information.");
   1284 
   1285 static PyStructSequence_Field stat_result_fields[] = {
   1286     {"st_mode",    "protection bits"},
   1287     {"st_ino",     "inode"},
   1288     {"st_dev",     "device"},
   1289     {"st_nlink",   "number of hard links"},
   1290     {"st_uid",     "user ID of owner"},
   1291     {"st_gid",     "group ID of owner"},
   1292     {"st_size",    "total size, in bytes"},
   1293     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
   1294     {NULL,   "integer time of last access"},
   1295     {NULL,   "integer time of last modification"},
   1296     {NULL,   "integer time of last change"},
   1297     {"st_atime",   "time of last access"},
   1298     {"st_mtime",   "time of last modification"},
   1299     {"st_ctime",   "time of last change"},
   1300 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
   1301     {"st_blksize", "blocksize for filesystem I/O"},
   1302 #endif
   1303 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
   1304     {"st_blocks",  "number of blocks allocated"},
   1305 #endif
   1306 #ifdef HAVE_STRUCT_STAT_ST_RDEV
   1307     {"st_rdev",    "device type (if inode device)"},
   1308 #endif
   1309 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
   1310     {"st_flags",   "user defined flags for file"},
   1311 #endif
   1312 #ifdef HAVE_STRUCT_STAT_ST_GEN
   1313     {"st_gen",    "generation number"},
   1314 #endif
   1315 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
   1316     {"st_birthtime",   "time of creation"},
   1317 #endif
   1318     {0}
   1319 };
   1320 
   1321 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
   1322 #define ST_BLKSIZE_IDX 13
   1323 #else
   1324 #define ST_BLKSIZE_IDX 12
   1325 #endif
   1326 
   1327 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
   1328 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
   1329 #else
   1330 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
   1331 #endif
   1332 
   1333 #ifdef HAVE_STRUCT_STAT_ST_RDEV
   1334 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
   1335 #else
   1336 #define ST_RDEV_IDX ST_BLOCKS_IDX
   1337 #endif
   1338 
   1339 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
   1340 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
   1341 #else
   1342 #define ST_FLAGS_IDX ST_RDEV_IDX
   1343 #endif
   1344 
   1345 #ifdef HAVE_STRUCT_STAT_ST_GEN
   1346 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
   1347 #else
   1348 #define ST_GEN_IDX ST_FLAGS_IDX
   1349 #endif
   1350 
   1351 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
   1352 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
   1353 #else
   1354 #define ST_BIRTHTIME_IDX ST_GEN_IDX
   1355 #endif
   1356 
   1357 static PyStructSequence_Desc stat_result_desc = {
   1358     "stat_result", /* name */
   1359     stat_result__doc__, /* doc */
   1360     stat_result_fields,
   1361     10
   1362 };
   1363 
   1364 PyDoc_STRVAR(statvfs_result__doc__,
   1365 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
   1366 This object may be accessed either as a tuple of\n\
   1367   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
   1368 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
   1369 \n\
   1370 See os.statvfs for more information.");
   1371 
   1372 static PyStructSequence_Field statvfs_result_fields[] = {
   1373     {"f_bsize",  },
   1374     {"f_frsize", },
   1375     {"f_blocks", },
   1376     {"f_bfree",  },
   1377     {"f_bavail", },
   1378     {"f_files",  },
   1379     {"f_ffree",  },
   1380     {"f_favail", },
   1381     {"f_flag",   },
   1382     {"f_namemax",},
   1383     {0}
   1384 };
   1385 
   1386 static PyStructSequence_Desc statvfs_result_desc = {
   1387     "statvfs_result", /* name */
   1388     statvfs_result__doc__, /* doc */
   1389     statvfs_result_fields,
   1390     10
   1391 };
   1392 
   1393 static int initialized;
   1394 static PyTypeObject StatResultType;
   1395 static PyTypeObject StatVFSResultType;
   1396 static newfunc structseq_new;
   1397 
   1398 static PyObject *
   1399 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
   1400 {
   1401     PyStructSequence *result;
   1402     int i;
   1403 
   1404     result = (PyStructSequence*)structseq_new(type, args, kwds);
   1405     if (!result)
   1406         return NULL;
   1407     /* If we have been initialized from a tuple,
   1408        st_?time might be set to None. Initialize it
   1409        from the int slots.  */
   1410     for (i = 7; i <= 9; i++) {
   1411         if (result->ob_item[i+3] == Py_None) {
   1412             Py_DECREF(Py_None);
   1413             Py_INCREF(result->ob_item[i]);
   1414             result->ob_item[i+3] = result->ob_item[i];
   1415         }
   1416     }
   1417     return (PyObject*)result;
   1418 }
   1419 
   1420 
   1421 
   1422 /* If true, st_?time is float. */
   1423 static int _stat_float_times = 1;
   1424 
   1425 PyDoc_STRVAR(stat_float_times__doc__,
   1426 "stat_float_times([newval]) -> oldval\n\n\
   1427 Determine whether os.[lf]stat represents time stamps as float objects.\n\
   1428 If newval is True, future calls to stat() return floats, if it is False,\n\
   1429 future calls return ints. \n\
   1430 If newval is omitted, return the current setting.\n");
   1431 
   1432 static PyObject*
   1433 stat_float_times(PyObject* self, PyObject *args)
   1434 {
   1435     int newval = -1;
   1436     if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
   1437         return NULL;
   1438     if (newval == -1)
   1439         /* Return old value */
   1440         return PyBool_FromLong(_stat_float_times);
   1441     _stat_float_times = newval;
   1442     Py_INCREF(Py_None);
   1443     return Py_None;
   1444 }
   1445 
   1446 static void
   1447 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
   1448 {
   1449     PyObject *fval,*ival;
   1450 #if SIZEOF_TIME_T > SIZEOF_LONG
   1451     ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
   1452 #else
   1453     ival = PyInt_FromLong((long)sec);
   1454 #endif
   1455     if (!ival)
   1456         return;
   1457     if (_stat_float_times) {
   1458         fval = PyFloat_FromDouble(sec + 1e-9*nsec);
   1459     } else {
   1460         fval = ival;
   1461         Py_INCREF(fval);
   1462     }
   1463     PyStructSequence_SET_ITEM(v, index, ival);
   1464     PyStructSequence_SET_ITEM(v, index+3, fval);
   1465 }
   1466 
   1467 /* pack a system stat C structure into the Python stat tuple
   1468    (used by posix_stat() and posix_fstat()) */
   1469 static PyObject*
   1470 _pystat_fromstructstat(STRUCT_STAT *st)
   1471 {
   1472     unsigned long ansec, mnsec, cnsec;
   1473     PyObject *v = PyStructSequence_New(&StatResultType);
   1474     if (v == NULL)
   1475         return NULL;
   1476 
   1477     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
   1478 #ifdef HAVE_LARGEFILE_SUPPORT
   1479     PyStructSequence_SET_ITEM(v, 1,
   1480                               PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
   1481 #else
   1482     PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long)st->st_ino));
   1483 #endif
   1484 #ifdef MS_WINDOWS
   1485     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
   1486 #else
   1487     PyStructSequence_SET_ITEM(v, 2, _PyInt_FromDev(st->st_dev));
   1488 #endif
   1489     PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink));
   1490 #if defined(MS_WINDOWS)
   1491     PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong(0));
   1492     PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong(0));
   1493 #else
   1494     PyStructSequence_SET_ITEM(v, 4, _PyInt_FromUid(st->st_uid));
   1495     PyStructSequence_SET_ITEM(v, 5, _PyInt_FromGid(st->st_gid));
   1496 #endif
   1497 #ifdef HAVE_LARGEFILE_SUPPORT
   1498     PyStructSequence_SET_ITEM(v, 6,
   1499                               PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
   1500 #else
   1501     PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong(st->st_size));
   1502 #endif
   1503 
   1504 #if defined(HAVE_STAT_TV_NSEC)
   1505     ansec = st->st_atim.tv_nsec;
   1506     mnsec = st->st_mtim.tv_nsec;
   1507     cnsec = st->st_ctim.tv_nsec;
   1508 #elif defined(HAVE_STAT_TV_NSEC2)
   1509     ansec = st->st_atimespec.tv_nsec;
   1510     mnsec = st->st_mtimespec.tv_nsec;
   1511     cnsec = st->st_ctimespec.tv_nsec;
   1512 #elif defined(HAVE_STAT_NSEC)
   1513     ansec = st->st_atime_nsec;
   1514     mnsec = st->st_mtime_nsec;
   1515     cnsec = st->st_ctime_nsec;
   1516 #else
   1517     ansec = mnsec = cnsec = 0;
   1518 #endif
   1519     fill_time(v, 7, st->st_atime, ansec);
   1520     fill_time(v, 8, st->st_mtime, mnsec);
   1521     fill_time(v, 9, st->st_ctime, cnsec);
   1522 
   1523 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
   1524     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
   1525                               PyInt_FromLong((long)st->st_blksize));
   1526 #endif
   1527 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
   1528     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
   1529                               PyInt_FromLong((long)st->st_blocks));
   1530 #endif
   1531 #ifdef HAVE_STRUCT_STAT_ST_RDEV
   1532     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
   1533                               PyInt_FromLong((long)st->st_rdev));
   1534 #endif
   1535 #ifdef HAVE_STRUCT_STAT_ST_GEN
   1536     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
   1537                               PyInt_FromLong((long)st->st_gen));
   1538 #endif
   1539 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
   1540     {
   1541       PyObject *val;
   1542       unsigned long bsec,bnsec;
   1543       bsec = (long)st->st_birthtime;
   1544 #ifdef HAVE_STAT_TV_NSEC2
   1545       bnsec = st->st_birthtimespec.tv_nsec;
   1546 #else
   1547       bnsec = 0;
   1548 #endif
   1549       if (_stat_float_times) {
   1550         val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
   1551       } else {
   1552         val = PyInt_FromLong((long)bsec);
   1553       }
   1554       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
   1555                                 val);
   1556     }
   1557 #endif
   1558 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
   1559     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
   1560                               PyInt_FromLong((long)st->st_flags));
   1561 #endif
   1562 
   1563     if (PyErr_Occurred()) {
   1564         Py_DECREF(v);
   1565         return NULL;
   1566     }
   1567 
   1568     return v;
   1569 }
   1570 
   1571 #ifdef MS_WINDOWS
   1572 
   1573 /* IsUNCRoot -- test whether the supplied path is of the form \\SERVER\SHARE\,
   1574    where / can be used in place of \ and the trailing slash is optional.
   1575    Both SERVER and SHARE must have at least one character.
   1576 */
   1577 
   1578 #define ISSLASHA(c) ((c) == '\\' || (c) == '/')
   1579 #define ISSLASHW(c) ((c) == L'\\' || (c) == L'/')
   1580 #ifndef ARRAYSIZE
   1581 #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
   1582 #endif
   1583 
   1584 static BOOL
   1585 IsUNCRootA(char *path, int pathlen)
   1586 {
   1587     #define ISSLASH ISSLASHA
   1588 
   1589     int i, share;
   1590 
   1591     if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
   1592         /* minimum UNCRoot is \\x\y */
   1593         return FALSE;
   1594     for (i = 2; i < pathlen ; i++)
   1595         if (ISSLASH(path[i])) break;
   1596     if (i == 2 || i == pathlen)
   1597         /* do not allow \\\SHARE or \\SERVER */
   1598         return FALSE;
   1599     share = i+1;
   1600     for (i = share; i < pathlen; i++)
   1601         if (ISSLASH(path[i])) break;
   1602     return (i != share && (i == pathlen || i == pathlen-1));
   1603 
   1604     #undef ISSLASH
   1605 }
   1606 
   1607 static BOOL
   1608 IsUNCRootW(Py_UNICODE *path, int pathlen)
   1609 {
   1610     #define ISSLASH ISSLASHW
   1611 
   1612     int i, share;
   1613 
   1614     if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
   1615         /* minimum UNCRoot is \\x\y */
   1616         return FALSE;
   1617     for (i = 2; i < pathlen ; i++)
   1618         if (ISSLASH(path[i])) break;
   1619     if (i == 2 || i == pathlen)
   1620         /* do not allow \\\SHARE or \\SERVER */
   1621         return FALSE;
   1622     share = i+1;
   1623     for (i = share; i < pathlen; i++)
   1624         if (ISSLASH(path[i])) break;
   1625     return (i != share && (i == pathlen || i == pathlen-1));
   1626 
   1627     #undef ISSLASH
   1628 }
   1629 #endif /* MS_WINDOWS */
   1630 
   1631 static PyObject *
   1632 posix_do_stat(PyObject *self, PyObject *args,
   1633               char *format,
   1634 #ifdef __VMS
   1635               int (*statfunc)(const char *, STRUCT_STAT *, ...),
   1636 #else
   1637               int (*statfunc)(const char *, STRUCT_STAT *),
   1638 #endif
   1639               char *wformat,
   1640               int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
   1641 {
   1642     STRUCT_STAT st;
   1643     char *path = NULL;          /* pass this to stat; do not free() it */
   1644     char *pathfree = NULL;  /* this memory must be free'd */
   1645     int res;
   1646     PyObject *result;
   1647 
   1648 #ifdef MS_WINDOWS
   1649     Py_UNICODE *wpath;
   1650     if (PyArg_ParseTuple(args, wformat, &wpath)) {
   1651         Py_BEGIN_ALLOW_THREADS
   1652         res = wstatfunc(wpath, &st);
   1653         Py_END_ALLOW_THREADS
   1654 
   1655         if (res != 0)
   1656             return win32_error_unicode("stat", wpath);
   1657         return _pystat_fromstructstat(&st);
   1658     }
   1659     /* Drop the argument parsing error as narrow strings
   1660        are also valid. */
   1661     PyErr_Clear();
   1662 #endif
   1663 
   1664     if (!PyArg_ParseTuple(args, format,
   1665                           Py_FileSystemDefaultEncoding, &path))
   1666         return NULL;
   1667     pathfree = path;
   1668 
   1669     Py_BEGIN_ALLOW_THREADS
   1670     res = (*statfunc)(path, &st);
   1671     Py_END_ALLOW_THREADS
   1672 
   1673     if (res != 0) {
   1674 #ifdef MS_WINDOWS
   1675         result = win32_error("stat", pathfree);
   1676 #else
   1677         result = posix_error_with_filename(pathfree);
   1678 #endif
   1679     }
   1680     else
   1681         result = _pystat_fromstructstat(&st);
   1682 
   1683     PyMem_Free(pathfree);
   1684     return result;
   1685 }
   1686 
   1687 /* POSIX methods */
   1688 
   1689 PyDoc_STRVAR(posix_access__doc__,
   1690 "access(path, mode) -> True if granted, False otherwise\n\n\
   1691 Use the real uid/gid to test for access to a path.  Note that most\n\
   1692 operations will use the effective uid/gid, therefore this routine can\n\
   1693 be used in a suid/sgid environment to test if the invoking user has the\n\
   1694 specified access to the path.  The mode argument can be F_OK to test\n\
   1695 existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
   1696 
   1697 static PyObject *
   1698 posix_access(PyObject *self, PyObject *args)
   1699 {
   1700     char *path;
   1701     int mode;
   1702 
   1703 #ifdef MS_WINDOWS
   1704     DWORD attr;
   1705     Py_UNICODE *wpath;
   1706     if (PyArg_ParseTuple(args, "ui:access", &wpath, &mode)) {
   1707         Py_BEGIN_ALLOW_THREADS
   1708         attr = GetFileAttributesW(wpath);
   1709         Py_END_ALLOW_THREADS
   1710         goto finish;
   1711     }
   1712     /* Drop the argument parsing error as narrow strings
   1713        are also valid. */
   1714     PyErr_Clear();
   1715     if (!PyArg_ParseTuple(args, "eti:access",
   1716                           Py_FileSystemDefaultEncoding, &path, &mode))
   1717         return NULL;
   1718     Py_BEGIN_ALLOW_THREADS
   1719     attr = GetFileAttributesA(path);
   1720     Py_END_ALLOW_THREADS
   1721     PyMem_Free(path);
   1722 finish:
   1723     if (attr == 0xFFFFFFFF)
   1724         /* File does not exist, or cannot read attributes */
   1725         return PyBool_FromLong(0);
   1726     /* Access is possible if either write access wasn't requested, or
   1727        the file isn't read-only, or if it's a directory, as there are
   1728        no read-only directories on Windows. */
   1729     return PyBool_FromLong(!(mode & 2)
   1730                            || !(attr & FILE_ATTRIBUTE_READONLY)
   1731                            || (attr & FILE_ATTRIBUTE_DIRECTORY));
   1732 #else /* MS_WINDOWS */
   1733     int res;
   1734     if (!PyArg_ParseTuple(args, "eti:access",
   1735                           Py_FileSystemDefaultEncoding, &path, &mode))
   1736         return NULL;
   1737     Py_BEGIN_ALLOW_THREADS
   1738     res = access(path, mode);
   1739     Py_END_ALLOW_THREADS
   1740     PyMem_Free(path);
   1741     return PyBool_FromLong(res == 0);
   1742 #endif /* MS_WINDOWS */
   1743 }
   1744 
   1745 #ifndef F_OK
   1746 #define F_OK 0
   1747 #endif
   1748 #ifndef R_OK
   1749 #define R_OK 4
   1750 #endif
   1751 #ifndef W_OK
   1752 #define W_OK 2
   1753 #endif
   1754 #ifndef X_OK
   1755 #define X_OK 1
   1756 #endif
   1757 
   1758 #ifdef HAVE_TTYNAME
   1759 PyDoc_STRVAR(posix_ttyname__doc__,
   1760 "ttyname(fd) -> string\n\n\
   1761 Return the name of the terminal device connected to 'fd'.");
   1762 
   1763 static PyObject *
   1764 posix_ttyname(PyObject *self, PyObject *args)
   1765 {
   1766     int id;
   1767     char *ret;
   1768 
   1769     if (!PyArg_ParseTuple(args, "i:ttyname", &id))
   1770         return NULL;
   1771 
   1772 #if defined(__VMS)
   1773     /* file descriptor 0 only, the default input device (stdin) */
   1774     if (id == 0) {
   1775         ret = ttyname();
   1776     }
   1777     else {
   1778         ret = NULL;
   1779     }
   1780 #else
   1781     ret = ttyname(id);
   1782 #endif
   1783     if (ret == NULL)
   1784         return posix_error();
   1785     return PyString_FromString(ret);
   1786 }
   1787 #endif
   1788 
   1789 #ifdef HAVE_CTERMID
   1790 PyDoc_STRVAR(posix_ctermid__doc__,
   1791 "ctermid() -> string\n\n\
   1792 Return the name of the controlling terminal for this process.");
   1793 
   1794 static PyObject *
   1795 posix_ctermid(PyObject *self, PyObject *noargs)
   1796 {
   1797     char *ret;
   1798     char buffer[L_ctermid];
   1799 
   1800 #ifdef USE_CTERMID_R
   1801     ret = ctermid_r(buffer);
   1802 #else
   1803     ret = ctermid(buffer);
   1804 #endif
   1805     if (ret == NULL)
   1806         return posix_error();
   1807     return PyString_FromString(buffer);
   1808 }
   1809 #endif
   1810 
   1811 PyDoc_STRVAR(posix_chdir__doc__,
   1812 "chdir(path)\n\n\
   1813 Change the current working directory to the specified path.");
   1814 
   1815 static PyObject *
   1816 posix_chdir(PyObject *self, PyObject *args)
   1817 {
   1818 #ifdef MS_WINDOWS
   1819     return win32_1str(args, "chdir", "s:chdir", win32_chdir, "U:chdir", win32_wchdir);
   1820 #elif defined(PYOS_OS2) && defined(PYCC_GCC)
   1821     return posix_1str(args, "et:chdir", _chdir2);
   1822 #elif defined(__VMS)
   1823     return posix_1str(args, "et:chdir", (int (*)(const char *))chdir);
   1824 #else
   1825     return posix_1str(args, "et:chdir", chdir);
   1826 #endif
   1827 }
   1828 
   1829 #ifdef HAVE_FCHDIR
   1830 PyDoc_STRVAR(posix_fchdir__doc__,
   1831 "fchdir(fildes)\n\n\
   1832 Change to the directory of the given file descriptor.  fildes must be\n\
   1833 opened on a directory, not a file.");
   1834 
   1835 static PyObject *
   1836 posix_fchdir(PyObject *self, PyObject *fdobj)
   1837 {
   1838     return posix_fildes(fdobj, fchdir);
   1839 }
   1840 #endif /* HAVE_FCHDIR */
   1841 
   1842 
   1843 PyDoc_STRVAR(posix_chmod__doc__,
   1844 "chmod(path, mode)\n\n\
   1845 Change the access permissions of a file.");
   1846 
   1847 static PyObject *
   1848 posix_chmod(PyObject *self, PyObject *args)
   1849 {
   1850     char *path = NULL;
   1851     int i;
   1852     int res;
   1853 #ifdef MS_WINDOWS
   1854     DWORD attr;
   1855     Py_UNICODE *wpath;
   1856     if (PyArg_ParseTuple(args, "ui|:chmod", &wpath, &i)) {
   1857         Py_BEGIN_ALLOW_THREADS
   1858         attr = GetFileAttributesW(wpath);
   1859         if (attr != 0xFFFFFFFF) {
   1860             if (i & _S_IWRITE)
   1861                 attr &= ~FILE_ATTRIBUTE_READONLY;
   1862             else
   1863                 attr |= FILE_ATTRIBUTE_READONLY;
   1864             res = SetFileAttributesW(wpath, attr);
   1865         }
   1866         else
   1867             res = 0;
   1868         Py_END_ALLOW_THREADS
   1869         if (!res)
   1870             return win32_error_unicode("chmod", wpath);
   1871         Py_INCREF(Py_None);
   1872         return Py_None;
   1873     }
   1874     /* Drop the argument parsing error as narrow strings
   1875        are also valid. */
   1876     PyErr_Clear();
   1877 
   1878     if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
   1879                           &path, &i))
   1880         return NULL;
   1881     Py_BEGIN_ALLOW_THREADS
   1882     attr = GetFileAttributesA(path);
   1883     if (attr != 0xFFFFFFFF) {
   1884         if (i & _S_IWRITE)
   1885             attr &= ~FILE_ATTRIBUTE_READONLY;
   1886         else
   1887             attr |= FILE_ATTRIBUTE_READONLY;
   1888         res = SetFileAttributesA(path, attr);
   1889     }
   1890     else
   1891         res = 0;
   1892     Py_END_ALLOW_THREADS
   1893     if (!res) {
   1894         win32_error("chmod", path);
   1895         PyMem_Free(path);
   1896         return NULL;
   1897     }
   1898     PyMem_Free(path);
   1899     Py_INCREF(Py_None);
   1900     return Py_None;
   1901 #else /* MS_WINDOWS */
   1902     if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
   1903                           &path, &i))
   1904         return NULL;
   1905     Py_BEGIN_ALLOW_THREADS
   1906     res = chmod(path, i);
   1907     Py_END_ALLOW_THREADS
   1908     if (res < 0)
   1909         return posix_error_with_allocated_filename(path);
   1910     PyMem_Free(path);
   1911     Py_INCREF(Py_None);
   1912     return Py_None;
   1913 #endif
   1914 }
   1915 
   1916 #ifdef HAVE_FCHMOD
   1917 PyDoc_STRVAR(posix_fchmod__doc__,
   1918 "fchmod(fd, mode)\n\n\
   1919 Change the access permissions of the file given by file\n\
   1920 descriptor fd.");
   1921 
   1922 static PyObject *
   1923 posix_fchmod(PyObject *self, PyObject *args)
   1924 {
   1925     int fd, mode, res;
   1926     if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
   1927         return NULL;
   1928     Py_BEGIN_ALLOW_THREADS
   1929     res = fchmod(fd, mode);
   1930     Py_END_ALLOW_THREADS
   1931     if (res < 0)
   1932         return posix_error();
   1933     Py_RETURN_NONE;
   1934 }
   1935 #endif /* HAVE_FCHMOD */
   1936 
   1937 #ifdef HAVE_LCHMOD
   1938 PyDoc_STRVAR(posix_lchmod__doc__,
   1939 "lchmod(path, mode)\n\n\
   1940 Change the access permissions of a file. If path is a symlink, this\n\
   1941 affects the link itself rather than the target.");
   1942 
   1943 static PyObject *
   1944 posix_lchmod(PyObject *self, PyObject *args)
   1945 {
   1946     char *path = NULL;
   1947     int i;
   1948     int res;
   1949     if (!PyArg_ParseTuple(args, "eti:lchmod", Py_FileSystemDefaultEncoding,
   1950                           &path, &i))
   1951         return NULL;
   1952     Py_BEGIN_ALLOW_THREADS
   1953     res = lchmod(path, i);
   1954     Py_END_ALLOW_THREADS
   1955     if (res < 0)
   1956         return posix_error_with_allocated_filename(path);
   1957     PyMem_Free(path);
   1958     Py_RETURN_NONE;
   1959 }
   1960 #endif /* HAVE_LCHMOD */
   1961 
   1962 
   1963 #ifdef HAVE_CHFLAGS
   1964 PyDoc_STRVAR(posix_chflags__doc__,
   1965 "chflags(path, flags)\n\n\
   1966 Set file flags.");
   1967 
   1968 static PyObject *
   1969 posix_chflags(PyObject *self, PyObject *args)
   1970 {
   1971     char *path;
   1972     unsigned long flags;
   1973     int res;
   1974     if (!PyArg_ParseTuple(args, "etk:chflags",
   1975                           Py_FileSystemDefaultEncoding, &path, &flags))
   1976         return NULL;
   1977     Py_BEGIN_ALLOW_THREADS
   1978     res = chflags(path, flags);
   1979     Py_END_ALLOW_THREADS
   1980     if (res < 0)
   1981         return posix_error_with_allocated_filename(path);
   1982     PyMem_Free(path);
   1983     Py_INCREF(Py_None);
   1984     return Py_None;
   1985 }
   1986 #endif /* HAVE_CHFLAGS */
   1987 
   1988 #ifdef HAVE_LCHFLAGS
   1989 PyDoc_STRVAR(posix_lchflags__doc__,
   1990 "lchflags(path, flags)\n\n\
   1991 Set file flags.\n\
   1992 This function will not follow symbolic links.");
   1993 
   1994 static PyObject *
   1995 posix_lchflags(PyObject *self, PyObject *args)
   1996 {
   1997     char *path;
   1998     unsigned long flags;
   1999     int res;
   2000     if (!PyArg_ParseTuple(args, "etk:lchflags",
   2001                           Py_FileSystemDefaultEncoding, &path, &flags))
   2002         return NULL;
   2003     Py_BEGIN_ALLOW_THREADS
   2004     res = lchflags(path, flags);
   2005     Py_END_ALLOW_THREADS
   2006     if (res < 0)
   2007         return posix_error_with_allocated_filename(path);
   2008     PyMem_Free(path);
   2009     Py_INCREF(Py_None);
   2010     return Py_None;
   2011 }
   2012 #endif /* HAVE_LCHFLAGS */
   2013 
   2014 #ifdef HAVE_CHROOT
   2015 PyDoc_STRVAR(posix_chroot__doc__,
   2016 "chroot(path)\n\n\
   2017 Change root directory to path.");
   2018 
   2019 static PyObject *
   2020 posix_chroot(PyObject *self, PyObject *args)
   2021 {
   2022     return posix_1str(args, "et:chroot", chroot);
   2023 }
   2024 #endif
   2025 
   2026 #ifdef HAVE_FSYNC
   2027 PyDoc_STRVAR(posix_fsync__doc__,
   2028 "fsync(fildes)\n\n\
   2029 force write of file with filedescriptor to disk.");
   2030 
   2031 static PyObject *
   2032 posix_fsync(PyObject *self, PyObject *fdobj)
   2033 {
   2034     return posix_fildes(fdobj, fsync);
   2035 }
   2036 #endif /* HAVE_FSYNC */
   2037 
   2038 #ifdef HAVE_FDATASYNC
   2039 
   2040 #ifdef __hpux
   2041 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
   2042 #endif
   2043 
   2044 PyDoc_STRVAR(posix_fdatasync__doc__,
   2045 "fdatasync(fildes)\n\n\
   2046 force write of file with filedescriptor to disk.\n\
   2047  does not force update of metadata.");
   2048 
   2049 static PyObject *
   2050 posix_fdatasync(PyObject *self, PyObject *fdobj)
   2051 {
   2052     return posix_fildes(fdobj, fdatasync);
   2053 }
   2054 #endif /* HAVE_FDATASYNC */
   2055 
   2056 
   2057 #ifdef HAVE_CHOWN
   2058 PyDoc_STRVAR(posix_chown__doc__,
   2059 "chown(path, uid, gid)\n\n\
   2060 Change the owner and group id of path to the numeric uid and gid.");
   2061 
   2062 static PyObject *
   2063 posix_chown(PyObject *self, PyObject *args)
   2064 {
   2065     char *path = NULL;
   2066     uid_t uid;
   2067     gid_t gid;
   2068     int res;
   2069     if (!PyArg_ParseTuple(args, "etO&O&:chown",
   2070                           Py_FileSystemDefaultEncoding, &path,
   2071                           _Py_Uid_Converter, &uid,
   2072                           _Py_Gid_Converter, &gid))
   2073         return NULL;
   2074     Py_BEGIN_ALLOW_THREADS
   2075     res = chown(path, uid, gid);
   2076     Py_END_ALLOW_THREADS
   2077     if (res < 0)
   2078         return posix_error_with_allocated_filename(path);
   2079     PyMem_Free(path);
   2080     Py_INCREF(Py_None);
   2081     return Py_None;
   2082 }
   2083 #endif /* HAVE_CHOWN */
   2084 
   2085 #ifdef HAVE_FCHOWN
   2086 PyDoc_STRVAR(posix_fchown__doc__,
   2087 "fchown(fd, uid, gid)\n\n\
   2088 Change the owner and group id of the file given by file descriptor\n\
   2089 fd to the numeric uid and gid.");
   2090 
   2091 static PyObject *
   2092 posix_fchown(PyObject *self, PyObject *args)
   2093 {
   2094     int fd;
   2095     uid_t uid;
   2096     gid_t gid;
   2097     int res;
   2098     if (!PyArg_ParseTuple(args, "iO&O&:fchown", &fd,
   2099                           _Py_Uid_Converter, &uid,
   2100                           _Py_Gid_Converter, &gid))
   2101         return NULL;
   2102     Py_BEGIN_ALLOW_THREADS
   2103     res = fchown(fd, uid, gid);
   2104     Py_END_ALLOW_THREADS
   2105     if (res < 0)
   2106         return posix_error();
   2107     Py_RETURN_NONE;
   2108 }
   2109 #endif /* HAVE_FCHOWN */
   2110 
   2111 #ifdef HAVE_LCHOWN
   2112 PyDoc_STRVAR(posix_lchown__doc__,
   2113 "lchown(path, uid, gid)\n\n\
   2114 Change the owner and group id of path to the numeric uid and gid.\n\
   2115 This function will not follow symbolic links.");
   2116 
   2117 static PyObject *
   2118 posix_lchown(PyObject *self, PyObject *args)
   2119 {
   2120     char *path = NULL;
   2121     uid_t uid;
   2122     gid_t gid;
   2123     int res;
   2124     if (!PyArg_ParseTuple(args, "etO&O&:lchown",
   2125                           Py_FileSystemDefaultEncoding, &path,
   2126                           _Py_Uid_Converter, &uid,
   2127                           _Py_Gid_Converter, &gid))
   2128         return NULL;
   2129     Py_BEGIN_ALLOW_THREADS
   2130     res = lchown(path, uid, gid);
   2131     Py_END_ALLOW_THREADS
   2132     if (res < 0)
   2133         return posix_error_with_allocated_filename(path);
   2134     PyMem_Free(path);
   2135     Py_INCREF(Py_None);
   2136     return Py_None;
   2137 }
   2138 #endif /* HAVE_LCHOWN */
   2139 
   2140 
   2141 #ifdef HAVE_GETCWD
   2142 PyDoc_STRVAR(posix_getcwd__doc__,
   2143 "getcwd() -> path\n\n\
   2144 Return a string representing the current working directory.");
   2145 
   2146 #if (defined(__sun) && defined(__SVR4)) || \
   2147      defined(__OpenBSD__)               || \
   2148      defined(__NetBSD__)
   2149 /* Issue 9185: getcwd() returns NULL/ERANGE indefinitely. */
   2150 static PyObject *
   2151 posix_getcwd(PyObject *self, PyObject *noargs)
   2152 {
   2153     char buf[PATH_MAX+2];
   2154     char *res;
   2155 
   2156     Py_BEGIN_ALLOW_THREADS
   2157     res = getcwd(buf, sizeof buf);
   2158     Py_END_ALLOW_THREADS
   2159 
   2160     if (res == NULL)
   2161         return posix_error();
   2162 
   2163     return PyString_FromString(buf);
   2164 }
   2165 #else
   2166 static PyObject *
   2167 posix_getcwd(PyObject *self, PyObject *noargs)
   2168 {
   2169     int bufsize_incr = 1024;
   2170     int bufsize = 0;
   2171     char *tmpbuf = NULL;
   2172     char *res = NULL;
   2173     PyObject *dynamic_return;
   2174 
   2175     Py_BEGIN_ALLOW_THREADS
   2176     do {
   2177         bufsize = bufsize + bufsize_incr;
   2178         tmpbuf = malloc(bufsize);
   2179         if (tmpbuf == NULL) {
   2180             break;
   2181         }
   2182 #if defined(PYOS_OS2) && defined(PYCC_GCC)
   2183         res = _getcwd2(tmpbuf, bufsize);
   2184 #else
   2185         res = getcwd(tmpbuf, bufsize);
   2186 #endif
   2187 
   2188         if (res == NULL) {
   2189             free(tmpbuf);
   2190         }
   2191     } while ((res == NULL) && (errno == ERANGE));
   2192     Py_END_ALLOW_THREADS
   2193 
   2194     if (res == NULL)
   2195         return posix_error();
   2196 
   2197     dynamic_return = PyString_FromString(tmpbuf);
   2198     free(tmpbuf);
   2199 
   2200     return dynamic_return;
   2201 }
   2202 #endif /* getcwd() NULL/ERANGE workaround. */
   2203 
   2204 #ifdef Py_USING_UNICODE
   2205 PyDoc_STRVAR(posix_getcwdu__doc__,
   2206 "getcwdu() -> path\n\n\
   2207 Return a unicode string representing the current working directory.");
   2208 
   2209 static PyObject *
   2210 posix_getcwdu(PyObject *self, PyObject *noargs)
   2211 {
   2212     char buf[1026];
   2213     char *res;
   2214 
   2215 #ifdef MS_WINDOWS
   2216     DWORD len;
   2217     wchar_t wbuf[1026];
   2218     wchar_t *wbuf2 = wbuf;
   2219     PyObject *resobj;
   2220     Py_BEGIN_ALLOW_THREADS
   2221     len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
   2222     /* If the buffer is large enough, len does not include the
   2223        terminating \0. If the buffer is too small, len includes
   2224        the space needed for the terminator. */
   2225     if (len >= sizeof wbuf/ sizeof wbuf[0]) {
   2226         wbuf2 = malloc(len * sizeof(wchar_t));
   2227         if (wbuf2)
   2228             len = GetCurrentDirectoryW(len, wbuf2);
   2229     }
   2230     Py_END_ALLOW_THREADS
   2231     if (!wbuf2) {
   2232         PyErr_NoMemory();
   2233         return NULL;
   2234     }
   2235     if (!len) {
   2236         if (wbuf2 != wbuf) free(wbuf2);
   2237         return win32_error("getcwdu", NULL);
   2238     }
   2239     resobj = PyUnicode_FromWideChar(wbuf2, len);
   2240     if (wbuf2 != wbuf) free(wbuf2);
   2241     return resobj;
   2242 #endif /* MS_WINDOWS */
   2243 
   2244     Py_BEGIN_ALLOW_THREADS
   2245 #if defined(PYOS_OS2) && defined(PYCC_GCC)
   2246     res = _getcwd2(buf, sizeof buf);
   2247 #else
   2248     res = getcwd(buf, sizeof buf);
   2249 #endif
   2250     Py_END_ALLOW_THREADS
   2251     if (res == NULL)
   2252         return posix_error();
   2253     return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict");
   2254 }
   2255 #endif /* Py_USING_UNICODE */
   2256 #endif /* HAVE_GETCWD */
   2257 
   2258 
   2259 #ifdef HAVE_LINK
   2260 PyDoc_STRVAR(posix_link__doc__,
   2261 "link(src, dst)\n\n\
   2262 Create a hard link to a file.");
   2263 
   2264 static PyObject *
   2265 posix_link(PyObject *self, PyObject *args)
   2266 {
   2267     return posix_2str(args, "etet:link", link);
   2268 }
   2269 #endif /* HAVE_LINK */
   2270 
   2271 
   2272 PyDoc_STRVAR(posix_listdir__doc__,
   2273 "listdir(path) -> list_of_strings\n\n\
   2274 Return a list containing the names of the entries in the directory.\n\
   2275 \n\
   2276     path: path of directory to list\n\
   2277 \n\
   2278 The list is in arbitrary order.  It does not include the special\n\
   2279 entries '.' and '..' even if they are present in the directory.");
   2280 
   2281 static PyObject *
   2282 posix_listdir(PyObject *self, PyObject *args)
   2283 {
   2284     /* XXX Should redo this putting the (now four) versions of opendir
   2285        in separate files instead of having them all here... */
   2286 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
   2287 
   2288     PyObject *d, *v;
   2289     HANDLE hFindFile;
   2290     BOOL result;
   2291     WIN32_FIND_DATA FileData;
   2292     char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
   2293     char *bufptr = namebuf;
   2294     Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */
   2295 
   2296     Py_UNICODE *wpath;
   2297     if (PyArg_ParseTuple(args, "u:listdir", &wpath)) {
   2298         WIN32_FIND_DATAW wFileData;
   2299         Py_UNICODE *wnamebuf;
   2300         /* Overallocate for \\*.*\0 */
   2301         len = wcslen(wpath);
   2302         wnamebuf = malloc((len + 5) * sizeof(wchar_t));
   2303         if (!wnamebuf) {
   2304             PyErr_NoMemory();
   2305             return NULL;
   2306         }
   2307         wcscpy(wnamebuf, wpath);
   2308         if (len > 0) {
   2309             Py_UNICODE wch = wnamebuf[len-1];
   2310             if (wch != L'/' && wch != L'\\' && wch != L':')
   2311                 wnamebuf[len++] = L'\\';
   2312             wcscpy(wnamebuf + len, L"*.*");
   2313         }
   2314         if ((d = PyList_New(0)) == NULL) {
   2315             free(wnamebuf);
   2316             return NULL;
   2317         }
   2318         Py_BEGIN_ALLOW_THREADS
   2319         hFindFile = FindFirstFileW(wnamebuf, &wFileData);
   2320         Py_END_ALLOW_THREADS
   2321         if (hFindFile == INVALID_HANDLE_VALUE) {
   2322             int error = GetLastError();
   2323             if (error == ERROR_FILE_NOT_FOUND) {
   2324                 free(wnamebuf);
   2325                 return d;
   2326             }
   2327             Py_DECREF(d);
   2328             win32_error_unicode("FindFirstFileW", wnamebuf);
   2329             free(wnamebuf);
   2330             return NULL;
   2331         }
   2332         do {
   2333             /* Skip over . and .. */
   2334             if (wcscmp(wFileData.cFileName, L".") != 0 &&
   2335                 wcscmp(wFileData.cFileName, L"..") != 0) {
   2336                 v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData.cFileName));
   2337                 if (v == NULL) {
   2338                     Py_DECREF(d);
   2339                     d = NULL;
   2340                     break;
   2341                 }
   2342                 if (PyList_Append(d, v) != 0) {
   2343                     Py_DECREF(v);
   2344                     Py_DECREF(d);
   2345                     d = NULL;
   2346                     break;
   2347                 }
   2348                 Py_DECREF(v);
   2349             }
   2350             Py_BEGIN_ALLOW_THREADS
   2351             result = FindNextFileW(hFindFile, &wFileData);
   2352             Py_END_ALLOW_THREADS
   2353             /* FindNextFile sets error to ERROR_NO_MORE_FILES if
   2354                it got to the end of the directory. */
   2355             if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
   2356                 Py_DECREF(d);
   2357                 win32_error_unicode("FindNextFileW", wnamebuf);
   2358                 FindClose(hFindFile);
   2359                 free(wnamebuf);
   2360                 return NULL;
   2361             }
   2362         } while (result == TRUE);
   2363 
   2364         if (FindClose(hFindFile) == FALSE) {
   2365             Py_DECREF(d);
   2366             win32_error_unicode("FindClose", wnamebuf);
   2367             free(wnamebuf);
   2368             return NULL;
   2369         }
   2370         free(wnamebuf);
   2371         return d;
   2372     }
   2373     /* Drop the argument parsing error as narrow strings
   2374        are also valid. */
   2375     PyErr_Clear();
   2376 
   2377     if (!PyArg_ParseTuple(args, "et#:listdir",
   2378                           Py_FileSystemDefaultEncoding, &bufptr, &len))
   2379         return NULL;
   2380     if (len > 0) {
   2381         char ch = namebuf[len-1];
   2382         if (ch != SEP && ch != ALTSEP && ch != ':')
   2383             namebuf[len++] = '/';
   2384         strcpy(namebuf + len, "*.*");
   2385     }
   2386 
   2387     if ((d = PyList_New(0)) == NULL)
   2388         return NULL;
   2389 
   2390     Py_BEGIN_ALLOW_THREADS
   2391     hFindFile = FindFirstFile(namebuf, &FileData);
   2392     Py_END_ALLOW_THREADS
   2393     if (hFindFile == INVALID_HANDLE_VALUE) {
   2394         int error = GetLastError();
   2395         if (error == ERROR_FILE_NOT_FOUND)
   2396             return d;
   2397         Py_DECREF(d);
   2398         return win32_error("FindFirstFile", namebuf);
   2399     }
   2400     do {
   2401         /* Skip over . and .. */
   2402         if (strcmp(FileData.cFileName, ".") != 0 &&
   2403             strcmp(FileData.cFileName, "..") != 0) {
   2404             v = PyString_FromString(FileData.cFileName);
   2405             if (v == NULL) {
   2406                 Py_DECREF(d);
   2407                 d = NULL;
   2408                 break;
   2409             }
   2410             if (PyList_Append(d, v) != 0) {
   2411                 Py_DECREF(v);
   2412                 Py_DECREF(d);
   2413                 d = NULL;
   2414                 break;
   2415             }
   2416             Py_DECREF(v);
   2417         }
   2418         Py_BEGIN_ALLOW_THREADS
   2419         result = FindNextFile(hFindFile, &FileData);
   2420         Py_END_ALLOW_THREADS
   2421         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
   2422            it got to the end of the directory. */
   2423         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
   2424             Py_DECREF(d);
   2425             win32_error("FindNextFile", namebuf);
   2426             FindClose(hFindFile);
   2427             return NULL;
   2428         }
   2429     } while (result == TRUE);
   2430 
   2431     if (FindClose(hFindFile) == FALSE) {
   2432         Py_DECREF(d);
   2433         return win32_error("FindClose", namebuf);
   2434     }
   2435 
   2436     return d;
   2437 
   2438 #elif defined(PYOS_OS2)
   2439 
   2440 #ifndef MAX_PATH
   2441 #define MAX_PATH    CCHMAXPATH
   2442 #endif
   2443     char *name, *pt;
   2444     Py_ssize_t len;
   2445     PyObject *d, *v;
   2446     char namebuf[MAX_PATH+5];
   2447     HDIR  hdir = 1;
   2448     ULONG srchcnt = 1;
   2449     FILEFINDBUF3   ep;
   2450     APIRET rc;
   2451 
   2452     if (!PyArg_ParseTuple(args, "t#:listdir", &name, &len))
   2453         return NULL;
   2454     if (len >= MAX_PATH) {
   2455         PyErr_SetString(PyExc_ValueError, "path too long");
   2456         return NULL;
   2457     }
   2458     strcpy(namebuf, name);
   2459     for (pt = namebuf; *pt; pt++)
   2460         if (*pt == ALTSEP)
   2461             *pt = SEP;
   2462     if (namebuf[len-1] != SEP)
   2463         namebuf[len++] = SEP;
   2464     strcpy(namebuf + len, "*.*");
   2465 
   2466     if ((d = PyList_New(0)) == NULL)
   2467         return NULL;
   2468 
   2469     rc = DosFindFirst(namebuf,         /* Wildcard Pattern to Match */
   2470                       &hdir,           /* Handle to Use While Search Directory */
   2471                       FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
   2472                       &ep, sizeof(ep), /* Structure to Receive Directory Entry */
   2473                       &srchcnt,        /* Max and Actual Count of Entries Per Iteration */
   2474                       FIL_STANDARD);   /* Format of Entry (EAs or Not) */
   2475 
   2476     if (rc != NO_ERROR) {
   2477         errno = ENOENT;
   2478         return posix_error_with_filename(name);
   2479     }
   2480 
   2481     if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
   2482         do {
   2483             if (ep.achName[0] == '.'
   2484             && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
   2485                 continue; /* Skip Over "." and ".." Names */
   2486 
   2487             strcpy(namebuf, ep.achName);
   2488 
   2489             /* Leave Case of Name Alone -- In Native Form */
   2490             /* (Removed Forced Lowercasing Code) */
   2491 
   2492             v = PyString_FromString(namebuf);
   2493             if (v == NULL) {
   2494                 Py_DECREF(d);
   2495                 d = NULL;
   2496                 break;
   2497             }
   2498             if (PyList_Append(d, v) != 0) {
   2499                 Py_DECREF(v);
   2500                 Py_DECREF(d);
   2501                 d = NULL;
   2502                 break;
   2503             }
   2504             Py_DECREF(v);
   2505         } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
   2506     }
   2507 
   2508     return d;
   2509 #else
   2510 
   2511     char *name = NULL;
   2512     PyObject *d, *v;
   2513     DIR *dirp;
   2514     struct dirent *ep;
   2515     int arg_is_unicode = 1;
   2516 
   2517     errno = 0;
   2518     if (!PyArg_ParseTuple(args, "U:listdir", &v)) {
   2519         arg_is_unicode = 0;
   2520         PyErr_Clear();
   2521     }
   2522     if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name))
   2523         return NULL;
   2524     Py_BEGIN_ALLOW_THREADS
   2525     dirp = opendir(name);
   2526     Py_END_ALLOW_THREADS
   2527     if (dirp == NULL) {
   2528         return posix_error_with_allocated_filename(name);
   2529     }
   2530     if ((d = PyList_New(0)) == NULL) {
   2531         Py_BEGIN_ALLOW_THREADS
   2532         closedir(dirp);
   2533         Py_END_ALLOW_THREADS
   2534         PyMem_Free(name);
   2535         return NULL;
   2536     }
   2537     for (;;) {
   2538         errno = 0;
   2539         Py_BEGIN_ALLOW_THREADS
   2540         ep = readdir(dirp);
   2541         Py_END_ALLOW_THREADS
   2542         if (ep == NULL) {
   2543             if (errno == 0) {
   2544                 break;
   2545             } else {
   2546                 Py_BEGIN_ALLOW_THREADS
   2547                 closedir(dirp);
   2548                 Py_END_ALLOW_THREADS
   2549                 Py_DECREF(d);
   2550                 return posix_error_with_allocated_filename(name);
   2551             }
   2552         }
   2553         if (ep->d_name[0] == '.' &&
   2554             (NAMLEN(ep) == 1 ||
   2555              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
   2556             continue;
   2557         v = PyString_FromStringAndSize(ep->d_name, NAMLEN(ep));
   2558         if (v == NULL) {
   2559             Py_DECREF(d);
   2560             d = NULL;
   2561             break;
   2562         }
   2563 #ifdef Py_USING_UNICODE
   2564         if (arg_is_unicode) {
   2565             PyObject *w;
   2566 
   2567             w = PyUnicode_FromEncodedObject(v,
   2568                                             Py_FileSystemDefaultEncoding,
   2569                                             "strict");
   2570             if (w != NULL) {
   2571                 Py_DECREF(v);
   2572                 v = w;
   2573             }
   2574             else {
   2575                 /* fall back to the original byte string, as
   2576                    discussed in patch #683592 */
   2577                 PyErr_Clear();
   2578             }
   2579         }
   2580 #endif
   2581         if (PyList_Append(d, v) != 0) {
   2582             Py_DECREF(v);
   2583             Py_DECREF(d);
   2584             d = NULL;
   2585             break;
   2586         }
   2587         Py_DECREF(v);
   2588     }
   2589     Py_BEGIN_ALLOW_THREADS
   2590     closedir(dirp);
   2591     Py_END_ALLOW_THREADS
   2592     PyMem_Free(name);
   2593 
   2594     return d;
   2595 
   2596 #endif /* which OS */
   2597 }  /* end of posix_listdir */
   2598 
   2599 #ifdef MS_WINDOWS
   2600 /* A helper function for abspath on win32 */
   2601 static PyObject *
   2602 posix__getfullpathname(PyObject *self, PyObject *args)
   2603 {
   2604     /* assume encoded strings won't more than double no of chars */
   2605     char inbuf[MAX_PATH*2];
   2606     char *inbufp = inbuf;
   2607     Py_ssize_t insize = sizeof(inbuf);
   2608     char outbuf[MAX_PATH*2];
   2609     char *temp;
   2610 
   2611     Py_UNICODE *wpath;
   2612     if (PyArg_ParseTuple(args, "u|:_getfullpathname", &wpath)) {
   2613         Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
   2614         Py_UNICODE *wtemp;
   2615         DWORD result;
   2616         PyObject *v;
   2617         result = GetFullPathNameW(wpath,
   2618                                   sizeof(woutbuf)/sizeof(woutbuf[0]),
   2619                                   woutbuf, &wtemp);
   2620         if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) {
   2621             woutbufp = malloc(result * sizeof(Py_UNICODE));
   2622             if (!woutbufp)
   2623                 return PyErr_NoMemory();
   2624             result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
   2625         }
   2626         if (result)
   2627             v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp));
   2628         else
   2629             v = win32_error_unicode("GetFullPathNameW", wpath);
   2630         if (woutbufp != woutbuf)
   2631             free(woutbufp);
   2632         return v;
   2633     }
   2634     /* Drop the argument parsing error as narrow strings
   2635        are also valid. */
   2636     PyErr_Clear();
   2637 
   2638     if (!PyArg_ParseTuple (args, "et#:_getfullpathname",
   2639                            Py_FileSystemDefaultEncoding, &inbufp,
   2640                            &insize))
   2641         return NULL;
   2642     if (!GetFullPathName(inbuf, sizeof(outbuf)/sizeof(outbuf[0]),
   2643                          outbuf, &temp))
   2644         return win32_error("GetFullPathName", inbuf);
   2645     if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
   2646         return PyUnicode_Decode(outbuf, strlen(outbuf),
   2647                                 Py_FileSystemDefaultEncoding, NULL);
   2648     }
   2649     return PyString_FromString(outbuf);
   2650 } /* end of posix__getfullpathname */
   2651 #endif /* MS_WINDOWS */
   2652 
   2653 PyDoc_STRVAR(posix_mkdir__doc__,
   2654 "mkdir(path [, mode=0777])\n\n\
   2655 Create a directory.");
   2656 
   2657 static PyObject *
   2658 posix_mkdir(PyObject *self, PyObject *args)
   2659 {
   2660     int res;
   2661     char *path = NULL;
   2662     int mode = 0777;
   2663 
   2664 #ifdef MS_WINDOWS
   2665     Py_UNICODE *wpath;
   2666     if (PyArg_ParseTuple(args, "u|i:mkdir", &wpath, &mode)) {
   2667         Py_BEGIN_ALLOW_THREADS
   2668         res = CreateDirectoryW(wpath, NULL);
   2669         Py_END_ALLOW_THREADS
   2670         if (!res)
   2671             return win32_error_unicode("mkdir", wpath);
   2672         Py_INCREF(Py_None);
   2673         return Py_None;
   2674     }
   2675     /* Drop the argument parsing error as narrow strings
   2676        are also valid. */
   2677     PyErr_Clear();
   2678     if (!PyArg_ParseTuple(args, "et|i:mkdir",
   2679                           Py_FileSystemDefaultEncoding, &path, &mode))
   2680         return NULL;
   2681     Py_BEGIN_ALLOW_THREADS
   2682     res = CreateDirectoryA(path, NULL);
   2683     Py_END_ALLOW_THREADS
   2684     if (!res) {
   2685         win32_error("mkdir", path);
   2686         PyMem_Free(path);
   2687         return NULL;
   2688     }
   2689     PyMem_Free(path);
   2690     Py_INCREF(Py_None);
   2691     return Py_None;
   2692 #else /* MS_WINDOWS */
   2693 
   2694     if (!PyArg_ParseTuple(args, "et|i:mkdir",
   2695                           Py_FileSystemDefaultEncoding, &path, &mode))
   2696         return NULL;
   2697     Py_BEGIN_ALLOW_THREADS
   2698 #if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
   2699     res = mkdir(path);
   2700 #else
   2701     res = mkdir(path, mode);
   2702 #endif
   2703     Py_END_ALLOW_THREADS
   2704     if (res < 0)
   2705         return posix_error_with_allocated_filename(path);
   2706     PyMem_Free(path);
   2707     Py_INCREF(Py_None);
   2708     return Py_None;
   2709 #endif /* MS_WINDOWS */
   2710 }
   2711 
   2712 
   2713 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
   2714 #if defined(HAVE_SYS_RESOURCE_H)
   2715 #include <sys/resource.h>
   2716 #endif
   2717 
   2718 
   2719 #ifdef HAVE_NICE
   2720 PyDoc_STRVAR(posix_nice__doc__,
   2721 "nice(inc) -> new_priority\n\n\
   2722 Decrease the priority of process by inc and return the new priority.");
   2723 
   2724 static PyObject *
   2725 posix_nice(PyObject *self, PyObject *args)
   2726 {
   2727     int increment, value;
   2728 
   2729     if (!PyArg_ParseTuple(args, "i:nice", &increment))
   2730         return NULL;
   2731 
   2732     /* There are two flavours of 'nice': one that returns the new
   2733        priority (as required by almost all standards out there) and the
   2734        Linux/FreeBSD/BSDI one, which returns '0' on success and advices
   2735        the use of getpriority() to get the new priority.
   2736 
   2737        If we are of the nice family that returns the new priority, we
   2738        need to clear errno before the call, and check if errno is filled
   2739        before calling posix_error() on a returnvalue of -1, because the
   2740        -1 may be the actual new priority! */
   2741 
   2742     errno = 0;
   2743     value = nice(increment);
   2744 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
   2745     if (value == 0)
   2746         value = getpriority(PRIO_PROCESS, 0);
   2747 #endif
   2748     if (value == -1 && errno != 0)
   2749         /* either nice() or getpriority() returned an error */
   2750         return posix_error();
   2751     return PyInt_FromLong((long) value);
   2752 }
   2753 #endif /* HAVE_NICE */
   2754 
   2755 PyDoc_STRVAR(posix_rename__doc__,
   2756 "rename(old, new)\n\n\
   2757 Rename a file or directory.");
   2758 
   2759 static PyObject *
   2760 posix_rename(PyObject *self, PyObject *args)
   2761 {
   2762 #ifdef MS_WINDOWS
   2763     PyObject *o1, *o2;
   2764     char *p1, *p2;
   2765     BOOL result;
   2766     if (!PyArg_ParseTuple(args, "OO:rename", &o1, &o2))
   2767         goto error;
   2768     if (!convert_to_unicode(&o1))
   2769         goto error;
   2770     if (!convert_to_unicode(&o2)) {
   2771         Py_DECREF(o1);
   2772         goto error;
   2773     }
   2774     Py_BEGIN_ALLOW_THREADS
   2775     result = MoveFileW(PyUnicode_AsUnicode(o1),
   2776                        PyUnicode_AsUnicode(o2));
   2777     Py_END_ALLOW_THREADS
   2778     Py_DECREF(o1);
   2779     Py_DECREF(o2);
   2780     if (!result)
   2781         return win32_error("rename", NULL);
   2782     Py_INCREF(Py_None);
   2783     return Py_None;
   2784 error:
   2785     PyErr_Clear();
   2786     if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2))
   2787         return NULL;
   2788     Py_BEGIN_ALLOW_THREADS
   2789     result = MoveFileA(p1, p2);
   2790     Py_END_ALLOW_THREADS
   2791     if (!result)
   2792         return win32_error("rename", NULL);
   2793     Py_INCREF(Py_None);
   2794     return Py_None;
   2795 #else
   2796     return posix_2str(args, "etet:rename", rename);
   2797 #endif
   2798 }
   2799 
   2800 
   2801 PyDoc_STRVAR(posix_rmdir__doc__,
   2802 "rmdir(path)\n\n\
   2803 Remove a directory.");
   2804 
   2805 static PyObject *
   2806 posix_rmdir(PyObject *self, PyObject *args)
   2807 {
   2808 #ifdef MS_WINDOWS
   2809     return win32_1str(args, "rmdir", "s:rmdir", RemoveDirectoryA, "U:rmdir", RemoveDirectoryW);
   2810 #else
   2811     return posix_1str(args, "et:rmdir", rmdir);
   2812 #endif
   2813 }
   2814 
   2815 
   2816 PyDoc_STRVAR(posix_stat__doc__,
   2817 "stat(path) -> stat result\n\n\
   2818 Perform a stat system call on the given path.");
   2819 
   2820 static PyObject *
   2821 posix_stat(PyObject *self, PyObject *args)
   2822 {
   2823 #ifdef MS_WINDOWS
   2824     return posix_do_stat(self, args, "et:stat", STAT, "u:stat", win32_wstat);
   2825 #else
   2826     return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL);
   2827 #endif
   2828 }
   2829 
   2830 
   2831 #ifdef HAVE_SYSTEM
   2832 PyDoc_STRVAR(posix_system__doc__,
   2833 "system(command) -> exit_status\n\n\
   2834 Execute the command (a string) in a subshell.");
   2835 
   2836 static PyObject *
   2837 posix_system(PyObject *self, PyObject *args)
   2838 {
   2839     char *command;
   2840     long sts;
   2841     if (!PyArg_ParseTuple(args, "s:system", &command))
   2842         return NULL;
   2843     Py_BEGIN_ALLOW_THREADS
   2844     sts = system(command);
   2845     Py_END_ALLOW_THREADS
   2846     return PyInt_FromLong(sts);
   2847 }
   2848 #endif
   2849 
   2850 
   2851 PyDoc_STRVAR(posix_umask__doc__,
   2852 "umask(new_mask) -> old_mask\n\n\
   2853 Set the current numeric umask and return the previous umask.");
   2854 
   2855 static PyObject *
   2856 posix_umask(PyObject *self, PyObject *args)
   2857 {
   2858     int i;
   2859     if (!PyArg_ParseTuple(args, "i:umask", &i))
   2860         return NULL;
   2861     i = (int)umask(i);
   2862     if (i < 0)
   2863         return posix_error();
   2864     return PyInt_FromLong((long)i);
   2865 }
   2866 
   2867 
   2868 PyDoc_STRVAR(posix_unlink__doc__,
   2869 "unlink(path)\n\n\
   2870 Remove a file (same as remove(path)).");
   2871 
   2872 PyDoc_STRVAR(posix_remove__doc__,
   2873 "remove(path)\n\n\
   2874 Remove a file (same as unlink(path)).");
   2875 
   2876 static PyObject *
   2877 posix_unlink(PyObject *self, PyObject *args)
   2878 {
   2879 #ifdef MS_WINDOWS
   2880     return win32_1str(args, "remove", "s:remove", DeleteFileA, "U:remove", DeleteFileW);
   2881 #else
   2882     return posix_1str(args, "et:remove", unlink);
   2883 #endif
   2884 }
   2885 
   2886 
   2887 #ifdef HAVE_UNAME
   2888 PyDoc_STRVAR(posix_uname__doc__,
   2889 "uname() -> (sysname, nodename, release, version, machine)\n\n\
   2890 Return a tuple identifying the current operating system.");
   2891 
   2892 static PyObject *
   2893 posix_uname(PyObject *self, PyObject *noargs)
   2894 {
   2895     struct utsname u;
   2896     int res;
   2897 
   2898     Py_BEGIN_ALLOW_THREADS
   2899     res = uname(&u);
   2900     Py_END_ALLOW_THREADS
   2901     if (res < 0)
   2902         return posix_error();
   2903     return Py_BuildValue("(sssss)",
   2904                          u.sysname,
   2905                          u.nodename,
   2906                          u.release,
   2907                          u.version,
   2908                          u.machine);
   2909 }
   2910 #endif /* HAVE_UNAME */
   2911 
   2912 static int
   2913 extract_time(PyObject *t, time_t* sec, long* usec)
   2914 {
   2915     time_t intval;
   2916     if (PyFloat_Check(t)) {
   2917         double tval = PyFloat_AsDouble(t);
   2918         PyObject *intobj = PyNumber_Long(t);
   2919         if (!intobj)
   2920             return -1;
   2921 #if SIZEOF_TIME_T > SIZEOF_LONG
   2922         intval = PyInt_AsUnsignedLongLongMask(intobj);
   2923 #else
   2924         intval = PyInt_AsLong(intobj);
   2925 #endif
   2926         Py_DECREF(intobj);
   2927         if (intval == -1 && PyErr_Occurred())
   2928             return -1;
   2929         *sec = intval;
   2930         *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
   2931         if (*usec < 0)
   2932             /* If rounding gave us a negative number,
   2933                truncate.  */
   2934             *usec = 0;
   2935         return 0;
   2936     }
   2937 #if SIZEOF_TIME_T > SIZEOF_LONG
   2938     intval = PyInt_AsUnsignedLongLongMask(t);
   2939 #else
   2940     intval = PyInt_AsLong(t);
   2941 #endif
   2942     if (intval == -1 && PyErr_Occurred())
   2943         return -1;
   2944     *sec = intval;
   2945     *usec = 0;
   2946     return 0;
   2947 }
   2948 
   2949 PyDoc_STRVAR(posix_utime__doc__,
   2950 "utime(path, (atime, mtime))\n\
   2951 utime(path, None)\n\n\
   2952 Set the access and modified time of the file to the given values.  If the\n\
   2953 second form is used, set the access and modified times to the current time.");
   2954 
   2955 static PyObject *
   2956 posix_utime(PyObject *self, PyObject *args)
   2957 {
   2958 #ifdef MS_WINDOWS
   2959     PyObject *arg;
   2960     wchar_t *wpath = NULL;
   2961     char *apath = NULL;
   2962     HANDLE hFile;
   2963     time_t atimesec, mtimesec;
   2964     long ausec, musec;
   2965     FILETIME atime, mtime;
   2966     PyObject *result = NULL;
   2967 
   2968     if (PyArg_ParseTuple(args, "uO|:utime", &wpath, &arg)) {
   2969         Py_BEGIN_ALLOW_THREADS
   2970         hFile = CreateFileW(wpath, FILE_WRITE_ATTRIBUTES, 0,
   2971                             NULL, OPEN_EXISTING,
   2972                             FILE_FLAG_BACKUP_SEMANTICS, NULL);
   2973         Py_END_ALLOW_THREADS
   2974         if (hFile == INVALID_HANDLE_VALUE)
   2975             return win32_error_unicode("utime", wpath);
   2976     } else
   2977         /* Drop the argument parsing error as narrow strings
   2978            are also valid. */
   2979         PyErr_Clear();
   2980 
   2981     if (!wpath) {
   2982         if (!PyArg_ParseTuple(args, "etO:utime",
   2983                               Py_FileSystemDefaultEncoding, &apath, &arg))
   2984             return NULL;
   2985         Py_BEGIN_ALLOW_THREADS
   2986         hFile = CreateFileA(apath, FILE_WRITE_ATTRIBUTES, 0,
   2987                             NULL, OPEN_EXISTING,
   2988                             FILE_FLAG_BACKUP_SEMANTICS, NULL);
   2989         Py_END_ALLOW_THREADS
   2990         if (hFile == INVALID_HANDLE_VALUE) {
   2991             win32_error("utime", apath);
   2992             PyMem_Free(apath);
   2993             return NULL;
   2994         }
   2995         PyMem_Free(apath);
   2996     }
   2997 
   2998     if (arg == Py_None) {
   2999         SYSTEMTIME now;
   3000         GetSystemTime(&now);
   3001         if (!SystemTimeToFileTime(&now, &mtime) ||
   3002             !SystemTimeToFileTime(&now, &atime)) {
   3003             win32_error("utime", NULL);
   3004             goto done;
   3005         }
   3006     }
   3007     else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
   3008         PyErr_SetString(PyExc_TypeError,
   3009                         "utime() arg 2 must be a tuple (atime, mtime)");
   3010         goto done;
   3011     }
   3012     else {
   3013         if (extract_time(PyTuple_GET_ITEM(arg, 0),
   3014                          &atimesec, &ausec) == -1)
   3015             goto done;
   3016         time_t_to_FILE_TIME(atimesec, 1000*ausec, &atime);
   3017         if (extract_time(PyTuple_GET_ITEM(arg, 1),
   3018                          &mtimesec, &musec) == -1)
   3019             goto done;
   3020         time_t_to_FILE_TIME(mtimesec, 1000*musec, &mtime);
   3021     }
   3022     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
   3023         /* Avoid putting the file name into the error here,
   3024            as that may confuse the user into believing that
   3025            something is wrong with the file, when it also
   3026            could be the time stamp that gives a problem. */
   3027         win32_error("utime", NULL);
   3028         goto done;
   3029     }
   3030     Py_INCREF(Py_None);
   3031     result = Py_None;
   3032 done:
   3033     CloseHandle(hFile);
   3034     return result;
   3035 #else /* MS_WINDOWS */
   3036 
   3037     char *path = NULL;
   3038     time_t atime, mtime;
   3039     long ausec, musec;
   3040     int res;
   3041     PyObject* arg;
   3042 
   3043 #if defined(HAVE_UTIMES)
   3044     struct timeval buf[2];
   3045 #define ATIME buf[0].tv_sec
   3046 #define MTIME buf[1].tv_sec
   3047 #elif defined(HAVE_UTIME_H)
   3048 /* XXX should define struct utimbuf instead, above */
   3049     struct utimbuf buf;
   3050 #define ATIME buf.actime
   3051 #define MTIME buf.modtime
   3052 #define UTIME_ARG &buf
   3053 #else /* HAVE_UTIMES */
   3054     time_t buf[2];
   3055 #define ATIME buf[0]
   3056 #define MTIME buf[1]
   3057 #define UTIME_ARG buf
   3058 #endif /* HAVE_UTIMES */
   3059 
   3060 
   3061     if (!PyArg_ParseTuple(args, "etO:utime",
   3062                           Py_FileSystemDefaultEncoding, &path, &arg))
   3063         return NULL;
   3064     if (arg == Py_None) {
   3065         /* optional time values not given */
   3066         Py_BEGIN_ALLOW_THREADS
   3067         res = utime(path, NULL);
   3068         Py_END_ALLOW_THREADS
   3069     }
   3070     else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
   3071         PyErr_SetString(PyExc_TypeError,
   3072                         "utime() arg 2 must be a tuple (atime, mtime)");
   3073         PyMem_Free(path);
   3074         return NULL;
   3075     }
   3076     else {
   3077         if (extract_time(PyTuple_GET_ITEM(arg, 0),
   3078                          &atime, &ausec) == -1) {
   3079             PyMem_Free(path);
   3080             return NULL;
   3081         }
   3082         if (extract_time(PyTuple_GET_ITEM(arg, 1),
   3083                          &mtime, &musec) == -1) {
   3084             PyMem_Free(path);
   3085             return NULL;
   3086         }
   3087         ATIME = atime;
   3088         MTIME = mtime;
   3089 #ifdef HAVE_UTIMES
   3090         buf[0].tv_usec = ausec;
   3091         buf[1].tv_usec = musec;
   3092         Py_BEGIN_ALLOW_THREADS
   3093         res = utimes(path, buf);
   3094         Py_END_ALLOW_THREADS
   3095 #else
   3096         Py_BEGIN_ALLOW_THREADS
   3097         res = utime(path, UTIME_ARG);
   3098         Py_END_ALLOW_THREADS
   3099 #endif /* HAVE_UTIMES */
   3100     }
   3101     if (res < 0) {
   3102         return posix_error_with_allocated_filename(path);
   3103     }
   3104     PyMem_Free(path);
   3105     Py_INCREF(Py_None);
   3106     return Py_None;
   3107 #undef UTIME_ARG
   3108 #undef ATIME
   3109 #undef MTIME
   3110 #endif /* MS_WINDOWS */
   3111 }
   3112 
   3113 
   3114 /* Process operations */
   3115 
   3116 PyDoc_STRVAR(posix__exit__doc__,
   3117 "_exit(status)\n\n\
   3118 Exit to the system with specified status, without normal exit processing.");
   3119 
   3120 static PyObject *
   3121 posix__exit(PyObject *self, PyObject *args)
   3122 {
   3123     int sts;
   3124     if (!PyArg_ParseTuple(args, "i:_exit", &sts))
   3125         return NULL;
   3126     _exit(sts);
   3127     return NULL; /* Make gcc -Wall happy */
   3128 }
   3129 
   3130 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
   3131 static void
   3132 free_string_array(char **array, Py_ssize_t count)
   3133 {
   3134     Py_ssize_t i;
   3135     for (i = 0; i < count; i++)
   3136         PyMem_Free(array[i]);
   3137     PyMem_DEL(array);
   3138 }
   3139 #endif
   3140 
   3141 
   3142 #ifdef HAVE_EXECV
   3143 PyDoc_STRVAR(posix_execv__doc__,
   3144 "execv(path, args)\n\n\
   3145 Execute an executable path with arguments, replacing current process.\n\
   3146 \n\
   3147     path: path of executable file\n\
   3148     args: tuple or list of strings");
   3149 
   3150 static PyObject *
   3151 posix_execv(PyObject *self, PyObject *args)
   3152 {
   3153     char *path;
   3154     PyObject *argv;
   3155     char **argvlist;
   3156     Py_ssize_t i, argc;
   3157     PyObject *(*getitem)(PyObject *, Py_ssize_t);
   3158 
   3159     /* execv has two arguments: (path, argv), where
   3160        argv is a list or tuple of strings. */
   3161 
   3162     if (!PyArg_ParseTuple(args, "etO:execv",
   3163                           Py_FileSystemDefaultEncoding,
   3164                           &path, &argv))
   3165         return NULL;
   3166     if (PyList_Check(argv)) {
   3167         argc = PyList_Size(argv);
   3168         getitem = PyList_GetItem;
   3169     }
   3170     else if (PyTuple_Check(argv)) {
   3171         argc = PyTuple_Size(argv);
   3172         getitem = PyTuple_GetItem;
   3173     }
   3174     else {
   3175         PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
   3176         PyMem_Free(path);
   3177         return NULL;
   3178     }
   3179     if (argc < 1) {
   3180         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
   3181         PyMem_Free(path);
   3182         return NULL;
   3183     }
   3184 
   3185     argvlist = PyMem_NEW(char *, argc+1);
   3186     if (argvlist == NULL) {
   3187         PyMem_Free(path);
   3188         return PyErr_NoMemory();
   3189     }
   3190     for (i = 0; i < argc; i++) {
   3191         if (!PyArg_Parse((*getitem)(argv, i), "et",
   3192                          Py_FileSystemDefaultEncoding,
   3193                          &argvlist[i])) {
   3194             free_string_array(argvlist, i);
   3195             PyErr_SetString(PyExc_TypeError,
   3196                             "execv() arg 2 must contain only strings");
   3197             PyMem_Free(path);
   3198             return NULL;
   3199 
   3200         }
   3201     }
   3202     argvlist[argc] = NULL;
   3203 
   3204     execv(path, argvlist);
   3205 
   3206     /* If we get here it's definitely an error */
   3207 
   3208     free_string_array(argvlist, argc);
   3209     PyMem_Free(path);
   3210     return posix_error();
   3211 }
   3212 
   3213 
   3214 PyDoc_STRVAR(posix_execve__doc__,
   3215 "execve(path, args, env)\n\n\
   3216 Execute a path with arguments and environment, replacing current process.\n\
   3217 \n\
   3218     path: path of executable file\n\
   3219     args: tuple or list of arguments\n\
   3220     env: dictionary of strings mapping to strings");
   3221 
   3222 static PyObject *
   3223 posix_execve(PyObject *self, PyObject *args)
   3224 {
   3225     char *path;
   3226     PyObject *argv, *env;
   3227     char **argvlist;
   3228     char **envlist;
   3229     PyObject *key, *val, *keys=NULL, *vals=NULL;
   3230     Py_ssize_t i, pos, argc, envc;
   3231     PyObject *(*getitem)(PyObject *, Py_ssize_t);
   3232     Py_ssize_t lastarg = 0;
   3233 
   3234     /* execve has three arguments: (path, argv, env), where
   3235        argv is a list or tuple of strings and env is a dictionary
   3236        like posix.environ. */
   3237 
   3238     if (!PyArg_ParseTuple(args, "etOO:execve",
   3239                           Py_FileSystemDefaultEncoding,
   3240                           &path, &argv, &env))
   3241         return NULL;
   3242     if (PyList_Check(argv)) {
   3243         argc = PyList_Size(argv);
   3244         getitem = PyList_GetItem;
   3245     }
   3246     else if (PyTuple_Check(argv)) {
   3247         argc = PyTuple_Size(argv);
   3248         getitem = PyTuple_GetItem;
   3249     }
   3250     else {
   3251         PyErr_SetString(PyExc_TypeError,
   3252                         "execve() arg 2 must be a tuple or list");
   3253         goto fail_0;
   3254     }
   3255     if (!PyMapping_Check(env)) {
   3256         PyErr_SetString(PyExc_TypeError,
   3257                         "execve() arg 3 must be a mapping object");
   3258         goto fail_0;
   3259     }
   3260 
   3261     argvlist = PyMem_NEW(char *, argc+1);
   3262     if (argvlist == NULL) {
   3263         PyErr_NoMemory();
   3264         goto fail_0;
   3265     }
   3266     for (i = 0; i < argc; i++) {
   3267         if (!PyArg_Parse((*getitem)(argv, i),
   3268                          "et;execve() arg 2 must contain only strings",
   3269                          Py_FileSystemDefaultEncoding,
   3270                          &argvlist[i]))
   3271         {
   3272             lastarg = i;
   3273             goto fail_1;
   3274         }
   3275     }
   3276     lastarg = argc;
   3277     argvlist[argc] = NULL;
   3278 
   3279     i = PyMapping_Size(env);
   3280     if (i < 0)
   3281         goto fail_1;
   3282     envlist = PyMem_NEW(char *, i + 1);
   3283     if (envlist == NULL) {
   3284         PyErr_NoMemory();
   3285         goto fail_1;
   3286     }
   3287     envc = 0;
   3288     keys = PyMapping_Keys(env);
   3289     vals = PyMapping_Values(env);
   3290     if (!keys || !vals)
   3291         goto fail_2;
   3292     if (!PyList_Check(keys) || !PyList_Check(vals)) {
   3293         PyErr_SetString(PyExc_TypeError,
   3294                         "execve(): env.keys() or env.values() is not a list");
   3295         goto fail_2;
   3296     }
   3297 
   3298     for (pos = 0; pos < i; pos++) {
   3299         char *p, *k, *v;
   3300         size_t len;
   3301 
   3302         key = PyList_GetItem(keys, pos);
   3303         val = PyList_GetItem(vals, pos);
   3304         if (!key || !val)
   3305             goto fail_2;
   3306 
   3307         if (!PyArg_Parse(
   3308                     key,
   3309                     "s;execve() arg 3 contains a non-string key",
   3310                     &k) ||
   3311             !PyArg_Parse(
   3312                 val,
   3313                 "s;execve() arg 3 contains a non-string value",
   3314                 &v))
   3315         {
   3316             goto fail_2;
   3317         }
   3318 
   3319 #if defined(PYOS_OS2)
   3320         /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
   3321         if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
   3322 #endif
   3323         len = PyString_Size(key) + PyString_Size(val) + 2;
   3324         p = PyMem_NEW(char, len);
   3325         if (p == NULL) {
   3326             PyErr_NoMemory();
   3327             goto fail_2;
   3328         }
   3329         PyOS_snprintf(p, len, "%s=%s", k, v);
   3330         envlist[envc++] = p;
   3331 #if defined(PYOS_OS2)
   3332         }
   3333 #endif
   3334     }
   3335     envlist[envc] = 0;
   3336 
   3337     execve(path, argvlist, envlist);
   3338 
   3339     /* If we get here it's definitely an error */
   3340 
   3341     (void) posix_error();
   3342 
   3343   fail_2:
   3344     while (--envc >= 0)
   3345         PyMem_DEL(envlist[envc]);
   3346     PyMem_DEL(envlist);
   3347   fail_1:
   3348     free_string_array(argvlist, lastarg);
   3349     Py_XDECREF(vals);
   3350     Py_XDECREF(keys);
   3351   fail_0:
   3352     PyMem_Free(path);
   3353     return NULL;
   3354 }
   3355 #endif /* HAVE_EXECV */
   3356 
   3357 
   3358 #ifdef HAVE_SPAWNV
   3359 PyDoc_STRVAR(posix_spawnv__doc__,
   3360 "spawnv(mode, path, args)\n\n\
   3361 Execute the program 'path' in a new process.\n\
   3362 \n\
   3363     mode: mode of process creation\n\
   3364     path: path of executable file\n\
   3365     args: tuple or list of strings");
   3366 
   3367 static PyObject *
   3368 posix_spawnv(PyObject *self, PyObject *args)
   3369 {
   3370     char *path;
   3371     PyObject *argv;
   3372     char **argvlist;
   3373     int mode, i;
   3374     Py_ssize_t argc;
   3375     Py_intptr_t spawnval;
   3376     PyObject *(*getitem)(PyObject *, Py_ssize_t);
   3377 
   3378     /* spawnv has three arguments: (mode, path, argv), where
   3379        argv is a list or tuple of strings. */
   3380 
   3381     if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode,
   3382                           Py_FileSystemDefaultEncoding,
   3383                           &path, &argv))
   3384         return NULL;
   3385     if (PyList_Check(argv)) {
   3386         argc = PyList_Size(argv);
   3387         getitem = PyList_GetItem;
   3388     }
   3389     else if (PyTuple_Check(argv)) {
   3390         argc = PyTuple_Size(argv);
   3391         getitem = PyTuple_GetItem;
   3392     }
   3393     else {
   3394         PyErr_SetString(PyExc_TypeError,
   3395                         "spawnv() arg 2 must be a tuple or list");
   3396         PyMem_Free(path);
   3397         return NULL;
   3398     }
   3399 
   3400     argvlist = PyMem_NEW(char *, argc+1);
   3401     if (argvlist == NULL) {
   3402         PyMem_Free(path);
   3403         return PyErr_NoMemory();
   3404     }
   3405     for (i = 0; i < argc; i++) {
   3406         if (!PyArg_Parse((*getitem)(argv, i), "et",
   3407                          Py_FileSystemDefaultEncoding,
   3408                          &argvlist[i])) {
   3409             free_string_array(argvlist, i);
   3410             PyErr_SetString(
   3411                 PyExc_TypeError,
   3412                 "spawnv() arg 2 must contain only strings");
   3413             PyMem_Free(path);
   3414             return NULL;
   3415         }
   3416     }
   3417     argvlist[argc] = NULL;
   3418 
   3419 #if defined(PYOS_OS2) && defined(PYCC_GCC)
   3420     Py_BEGIN_ALLOW_THREADS
   3421     spawnval = spawnv(mode, path, argvlist);
   3422     Py_END_ALLOW_THREADS
   3423 #else
   3424     if (mode == _OLD_P_OVERLAY)
   3425         mode = _P_OVERLAY;
   3426 
   3427     Py_BEGIN_ALLOW_THREADS
   3428     spawnval = _spawnv(mode, path, argvlist);
   3429     Py_END_ALLOW_THREADS
   3430 #endif
   3431 
   3432     free_string_array(argvlist, argc);
   3433     PyMem_Free(path);
   3434 
   3435     if (spawnval == -1)
   3436         return posix_error();
   3437     else
   3438 #if SIZEOF_LONG == SIZEOF_VOID_P
   3439         return Py_BuildValue("l", (long) spawnval);
   3440 #else
   3441         return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
   3442 #endif
   3443 }
   3444 
   3445 
   3446 PyDoc_STRVAR(posix_spawnve__doc__,
   3447 "spawnve(mode, path, args, env)\n\n\
   3448 Execute the program 'path' in a new process.\n\
   3449 \n\
   3450     mode: mode of process creation\n\
   3451     path: path of executable file\n\
   3452     args: tuple or list of arguments\n\
   3453     env: dictionary of strings mapping to strings");
   3454 
   3455 static PyObject *
   3456 posix_spawnve(PyObject *self, PyObject *args)
   3457 {
   3458     char *path;
   3459     PyObject *argv, *env;
   3460     char **argvlist;
   3461     char **envlist;
   3462     PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
   3463     int mode, pos, envc;
   3464     Py_ssize_t argc, i;
   3465     Py_intptr_t spawnval;
   3466     PyObject *(*getitem)(PyObject *, Py_ssize_t);
   3467     Py_ssize_t lastarg = 0;
   3468 
   3469     /* spawnve has four arguments: (mode, path, argv, env), where
   3470        argv is a list or tuple of strings and env is a dictionary
   3471        like posix.environ. */
   3472 
   3473     if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode,
   3474                           Py_FileSystemDefaultEncoding,
   3475                           &path, &argv, &env))
   3476         return NULL;
   3477     if (PyList_Check(argv)) {
   3478         argc = PyList_Size(argv);
   3479         getitem = PyList_GetItem;
   3480     }
   3481     else if (PyTuple_Check(argv)) {
   3482         argc = PyTuple_Size(argv);
   3483         getitem = PyTuple_GetItem;
   3484     }
   3485     else {
   3486         PyErr_SetString(PyExc_TypeError,
   3487                         "spawnve() arg 2 must be a tuple or list");
   3488         goto fail_0;
   3489     }
   3490     if (!PyMapping_Check(env)) {
   3491         PyErr_SetString(PyExc_TypeError,
   3492                         "spawnve() arg 3 must be a mapping object");
   3493         goto fail_0;
   3494     }
   3495 
   3496     argvlist = PyMem_NEW(char *, argc+1);
   3497     if (argvlist == NULL) {
   3498         PyErr_NoMemory();
   3499         goto fail_0;
   3500     }
   3501     for (i = 0; i < argc; i++) {
   3502         if (!PyArg_Parse((*getitem)(argv, i),
   3503                      "et;spawnve() arg 2 must contain only strings",
   3504                          Py_FileSystemDefaultEncoding,
   3505                          &argvlist[i]))
   3506         {
   3507             lastarg = i;
   3508             goto fail_1;
   3509         }
   3510     }
   3511     lastarg = argc;
   3512     argvlist[argc] = NULL;
   3513 
   3514     i = PyMapping_Size(env);
   3515     if (i < 0)
   3516         goto fail_1;
   3517     envlist = PyMem_NEW(char *, i + 1);
   3518     if (envlist == NULL) {
   3519         PyErr_NoMemory();
   3520         goto fail_1;
   3521     }
   3522     envc = 0;
   3523     keys = PyMapping_Keys(env);
   3524     vals = PyMapping_Values(env);
   3525     if (!keys || !vals)
   3526         goto fail_2;
   3527     if (!PyList_Check(keys) || !PyList_Check(vals)) {
   3528         PyErr_SetString(PyExc_TypeError,
   3529                         "spawnve(): env.keys() or env.values() is not a list");
   3530         goto fail_2;
   3531     }
   3532 
   3533     for (pos = 0; pos < i; pos++) {
   3534         char *p, *k, *v;
   3535         size_t len;
   3536 
   3537         key = PyList_GetItem(keys, pos);
   3538         val = PyList_GetItem(vals, pos);
   3539         if (!key || !val)
   3540             goto fail_2;
   3541 
   3542         if (!PyArg_Parse(
   3543                     key,
   3544                     "s;spawnve() arg 3 contains a non-string key",
   3545                     &k) ||
   3546             !PyArg_Parse(
   3547                 val,
   3548                 "s;spawnve() arg 3 contains a non-string value",
   3549                 &v))
   3550         {
   3551             goto fail_2;
   3552         }
   3553         len = PyString_Size(key) + PyString_Size(val) + 2;
   3554         p = PyMem_NEW(char, len);
   3555         if (p == NULL) {
   3556             PyErr_NoMemory();
   3557             goto fail_2;
   3558         }
   3559         PyOS_snprintf(p, len, "%s=%s", k, v);
   3560         envlist[envc++] = p;
   3561     }
   3562     envlist[envc] = 0;
   3563 
   3564 #if defined(PYOS_OS2) && defined(PYCC_GCC)
   3565     Py_BEGIN_ALLOW_THREADS
   3566     spawnval = spawnve(mode, path, argvlist, envlist);
   3567     Py_END_ALLOW_THREADS
   3568 #else
   3569     if (mode == _OLD_P_OVERLAY)
   3570         mode = _P_OVERLAY;
   3571 
   3572     Py_BEGIN_ALLOW_THREADS
   3573     spawnval = _spawnve(mode, path, argvlist, envlist);
   3574     Py_END_ALLOW_THREADS
   3575 #endif
   3576 
   3577     if (spawnval == -1)
   3578         (void) posix_error();
   3579     else
   3580 #if SIZEOF_LONG == SIZEOF_VOID_P
   3581         res = Py_BuildValue("l", (long) spawnval);
   3582 #else
   3583         res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
   3584 #endif
   3585 
   3586   fail_2:
   3587     while (--envc >= 0)
   3588         PyMem_DEL(envlist[envc]);
   3589     PyMem_DEL(envlist);
   3590   fail_1:
   3591     free_string_array(argvlist, lastarg);
   3592     Py_XDECREF(vals);
   3593     Py_XDECREF(keys);
   3594   fail_0:
   3595     PyMem_Free(path);
   3596     return res;
   3597 }
   3598 
   3599 /* OS/2 supports spawnvp & spawnvpe natively */
   3600 #if defined(PYOS_OS2)
   3601 PyDoc_STRVAR(posix_spawnvp__doc__,
   3602 "spawnvp(mode, file, args)\n\n\
   3603 Execute the program 'file' in a new process, using the environment\n\
   3604 search path to find the file.\n\
   3605 \n\
   3606     mode: mode of process creation\n\
   3607     file: executable file name\n\
   3608     args: tuple or list of strings");
   3609 
   3610 static PyObject *
   3611 posix_spawnvp(PyObject *self, PyObject *args)
   3612 {
   3613     char *path;
   3614     PyObject *argv;
   3615     char **argvlist;
   3616     int mode, i, argc;
   3617     Py_intptr_t spawnval;
   3618     PyObject *(*getitem)(PyObject *, Py_ssize_t);
   3619 
   3620     /* spawnvp has three arguments: (mode, path, argv), where
   3621        argv is a list or tuple of strings. */
   3622 
   3623     if (!PyArg_ParseTuple(args, "ietO:spawnvp", &mode,
   3624                           Py_FileSystemDefaultEncoding,
   3625                           &path, &argv))
   3626         return NULL;
   3627     if (PyList_Check(argv)) {
   3628         argc = PyList_Size(argv);
   3629         getitem = PyList_GetItem;
   3630     }
   3631     else if (PyTuple_Check(argv)) {
   3632         argc = PyTuple_Size(argv);
   3633         getitem = PyTuple_GetItem;
   3634     }
   3635     else {
   3636         PyErr_SetString(PyExc_TypeError,
   3637                         "spawnvp() arg 2 must be a tuple or list");
   3638         PyMem_Free(path);
   3639         return NULL;
   3640     }
   3641 
   3642     argvlist = PyMem_NEW(char *, argc+1);
   3643     if (argvlist == NULL) {
   3644         PyMem_Free(path);
   3645         return PyErr_NoMemory();
   3646     }
   3647     for (i = 0; i < argc; i++) {
   3648         if (!PyArg_Parse((*getitem)(argv, i), "et",
   3649                          Py_FileSystemDefaultEncoding,
   3650                          &argvlist[i])) {
   3651             free_string_array(argvlist, i);
   3652             PyErr_SetString(
   3653                 PyExc_TypeError,
   3654                 "spawnvp() arg 2 must contain only strings");
   3655             PyMem_Free(path);
   3656             return NULL;
   3657         }
   3658     }
   3659     argvlist[argc] = NULL;
   3660 
   3661     Py_BEGIN_ALLOW_THREADS
   3662 #if defined(PYCC_GCC)
   3663     spawnval = spawnvp(mode, path, argvlist);
   3664 #else
   3665     spawnval = _spawnvp(mode, path, argvlist);
   3666 #endif
   3667     Py_END_ALLOW_THREADS
   3668 
   3669     free_string_array(argvlist, argc);
   3670     PyMem_Free(path);
   3671 
   3672     if (spawnval == -1)
   3673         return posix_error();
   3674     else
   3675         return Py_BuildValue("l", (long) spawnval);
   3676 }
   3677 
   3678 
   3679 PyDoc_STRVAR(posix_spawnvpe__doc__,
   3680 "spawnvpe(mode, file, args, env)\n\n\
   3681 Execute the program 'file' in a new process, using the environment\n\
   3682 search path to find the file.\n\
   3683 \n\
   3684     mode: mode of process creation\n\
   3685     file: executable file name\n\
   3686     args: tuple or list of arguments\n\
   3687     env: dictionary of strings mapping to strings");
   3688 
   3689 static PyObject *
   3690 posix_spawnvpe(PyObject *self, PyObject *args)
   3691 {
   3692     char *path;
   3693     PyObject *argv, *env;
   3694     char **argvlist;
   3695     char **envlist;
   3696     PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
   3697     int mode, i, pos, argc, envc;
   3698     Py_intptr_t spawnval;
   3699     PyObject *(*getitem)(PyObject *, Py_ssize_t);
   3700     int lastarg = 0;
   3701 
   3702     /* spawnvpe has four arguments: (mode, path, argv, env), where
   3703        argv is a list or tuple of strings and env is a dictionary
   3704        like posix.environ. */
   3705 
   3706     if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
   3707                           Py_FileSystemDefaultEncoding,
   3708                           &path, &argv, &env))
   3709         return NULL;
   3710     if (PyList_Check(argv)) {
   3711         argc = PyList_Size(argv);
   3712         getitem = PyList_GetItem;
   3713     }
   3714     else if (PyTuple_Check(argv)) {
   3715         argc = PyTuple_Size(argv);
   3716         getitem = PyTuple_GetItem;
   3717     }
   3718     else {
   3719         PyErr_SetString(PyExc_TypeError,
   3720                         "spawnvpe() arg 2 must be a tuple or list");
   3721         goto fail_0;
   3722     }
   3723     if (!PyMapping_Check(env)) {
   3724         PyErr_SetString(PyExc_TypeError,
   3725                         "spawnvpe() arg 3 must be a mapping object");
   3726         goto fail_0;
   3727     }
   3728 
   3729     argvlist = PyMem_NEW(char *, argc+1);
   3730     if (argvlist == NULL) {
   3731         PyErr_NoMemory();
   3732         goto fail_0;
   3733     }
   3734     for (i = 0; i < argc; i++) {
   3735         if (!PyArg_Parse((*getitem)(argv, i),
   3736                      "et;spawnvpe() arg 2 must contain only strings",
   3737                          Py_FileSystemDefaultEncoding,
   3738                          &argvlist[i]))
   3739         {
   3740             lastarg = i;
   3741             goto fail_1;
   3742         }
   3743     }
   3744     lastarg = argc;
   3745     argvlist[argc] = NULL;
   3746 
   3747     i = PyMapping_Size(env);
   3748     if (i < 0)
   3749         goto fail_1;
   3750     envlist = PyMem_NEW(char *, i + 1);
   3751     if (envlist == NULL) {
   3752         PyErr_NoMemory();
   3753         goto fail_1;
   3754     }
   3755     envc = 0;
   3756     keys = PyMapping_Keys(env);
   3757     vals = PyMapping_Values(env);
   3758     if (!keys || !vals)
   3759         goto fail_2;
   3760     if (!PyList_Check(keys) || !PyList_Check(vals)) {
   3761         PyErr_SetString(PyExc_TypeError,
   3762                         "spawnvpe(): env.keys() or env.values() is not a list");
   3763         goto fail_2;
   3764     }
   3765 
   3766     for (pos = 0; pos < i; pos++) {
   3767         char *p, *k, *v;
   3768         size_t len;
   3769 
   3770         key = PyList_GetItem(keys, pos);
   3771         val = PyList_GetItem(vals, pos);
   3772         if (!key || !val)
   3773             goto fail_2;
   3774 
   3775         if (!PyArg_Parse(
   3776                     key,
   3777                     "s;spawnvpe() arg 3 contains a non-string key",
   3778                     &k) ||
   3779             !PyArg_Parse(
   3780                 val,
   3781                 "s;spawnvpe() arg 3 contains a non-string value",
   3782                 &v))
   3783         {
   3784             goto fail_2;
   3785         }
   3786         len = PyString_Size(key) + PyString_Size(val) + 2;
   3787         p = PyMem_NEW(char, len);
   3788         if (p == NULL) {
   3789             PyErr_NoMemory();
   3790             goto fail_2;
   3791         }
   3792         PyOS_snprintf(p, len, "%s=%s", k, v);
   3793         envlist[envc++] = p;
   3794     }
   3795     envlist[envc] = 0;
   3796 
   3797     Py_BEGIN_ALLOW_THREADS
   3798 #if defined(PYCC_GCC)
   3799     spawnval = spawnvpe(mode, path, argvlist, envlist);
   3800 #else
   3801     spawnval = _spawnvpe(mode, path, argvlist, envlist);
   3802 #endif
   3803     Py_END_ALLOW_THREADS
   3804 
   3805     if (spawnval == -1)
   3806         (void) posix_error();
   3807     else
   3808         res = Py_BuildValue("l", (long) spawnval);
   3809 
   3810   fail_2:
   3811     while (--envc >= 0)
   3812         PyMem_DEL(envlist[envc]);
   3813     PyMem_DEL(envlist);
   3814   fail_1:
   3815     free_string_array(argvlist, lastarg);
   3816     Py_XDECREF(vals);
   3817     Py_XDECREF(keys);
   3818   fail_0:
   3819     PyMem_Free(path);
   3820     return res;
   3821 }
   3822 #endif /* PYOS_OS2 */
   3823 #endif /* HAVE_SPAWNV */
   3824 
   3825 
   3826 #ifdef HAVE_FORK1
   3827 PyDoc_STRVAR(posix_fork1__doc__,
   3828 "fork1() -> pid\n\n\
   3829 Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
   3830 \n\
   3831 Return 0 to child process and PID of child to parent process.");
   3832 
   3833 static PyObject *
   3834 posix_fork1(PyObject *self, PyObject *noargs)
   3835 {
   3836     pid_t pid;
   3837     int result = 0;
   3838     _PyImport_AcquireLock();
   3839     pid = fork1();
   3840     if (pid == 0) {
   3841         /* child: this clobbers and resets the import lock. */
   3842         PyOS_AfterFork();
   3843     } else {
   3844         /* parent: release the import lock. */
   3845         result = _PyImport_ReleaseLock();
   3846     }
   3847     if (pid == -1)
   3848         return posix_error();
   3849     if (result < 0) {
   3850         /* Don't clobber the OSError if the fork failed. */
   3851         PyErr_SetString(PyExc_RuntimeError,
   3852                         "not holding the import lock");
   3853         return NULL;
   3854     }
   3855     return PyLong_FromPid(pid);
   3856 }
   3857 #endif
   3858 
   3859 
   3860 #ifdef HAVE_FORK
   3861 PyDoc_STRVAR(posix_fork__doc__,
   3862 "fork() -> pid\n\n\
   3863 Fork a child process.\n\
   3864 Return 0 to child process and PID of child to parent process.");
   3865 
   3866 static PyObject *
   3867 posix_fork(PyObject *self, PyObject *noargs)
   3868 {
   3869     pid_t pid;
   3870     int result = 0;
   3871     _PyImport_AcquireLock();
   3872     pid = fork();
   3873     if (pid == 0) {
   3874         /* child: this clobbers and resets the import lock. */
   3875         PyOS_AfterFork();
   3876     } else {
   3877         /* parent: release the import lock. */
   3878         result = _PyImport_ReleaseLock();
   3879     }
   3880     if (pid == -1)
   3881         return posix_error();
   3882     if (result < 0) {
   3883         /* Don't clobber the OSError if the fork failed. */
   3884         PyErr_SetString(PyExc_RuntimeError,
   3885                         "not holding the import lock");
   3886         return NULL;
   3887     }
   3888     return PyLong_FromPid(pid);
   3889 }
   3890 #endif
   3891 
   3892 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
   3893 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
   3894 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
   3895 #define DEV_PTY_FILE "/dev/ptc"
   3896 #define HAVE_DEV_PTMX
   3897 #else
   3898 #define DEV_PTY_FILE "/dev/ptmx"
   3899 #endif
   3900 
   3901 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
   3902 #ifdef HAVE_PTY_H
   3903 #include <pty.h>
   3904 #else
   3905 #ifdef HAVE_LIBUTIL_H
   3906 #include <libutil.h>
   3907 #else
   3908 #ifdef HAVE_UTIL_H
   3909 #include <util.h>
   3910 #endif /* HAVE_UTIL_H */
   3911 #endif /* HAVE_LIBUTIL_H */
   3912 #endif /* HAVE_PTY_H */
   3913 #ifdef HAVE_STROPTS_H
   3914 #include <stropts.h>
   3915 #endif
   3916 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
   3917 
   3918 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
   3919 PyDoc_STRVAR(posix_openpty__doc__,
   3920 "openpty() -> (master_fd, slave_fd)\n\n\
   3921 Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
   3922 
   3923 static PyObject *
   3924 posix_openpty(PyObject *self, PyObject *noargs)
   3925 {
   3926     int master_fd, slave_fd;
   3927 #ifndef HAVE_OPENPTY
   3928     char * slave_name;
   3929 #endif
   3930 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
   3931     PyOS_sighandler_t sig_saved;
   3932 #ifdef sun
   3933     extern char *ptsname(int fildes);
   3934 #endif
   3935 #endif
   3936 
   3937 #ifdef HAVE_OPENPTY
   3938     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
   3939         return posix_error();
   3940 #elif defined(HAVE__GETPTY)
   3941     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
   3942     if (slave_name == NULL)
   3943         return posix_error();
   3944 
   3945     slave_fd = open(slave_name, O_RDWR);
   3946     if (slave_fd < 0)
   3947         return posix_error();
   3948 #else
   3949     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
   3950     if (master_fd < 0)
   3951         return posix_error();
   3952     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
   3953     /* change permission of slave */
   3954     if (grantpt(master_fd) < 0) {
   3955         PyOS_setsig(SIGCHLD, sig_saved);
   3956         return posix_error();
   3957     }
   3958     /* unlock slave */
   3959     if (unlockpt(master_fd) < 0) {
   3960         PyOS_setsig(SIGCHLD, sig_saved);
   3961         return posix_error();
   3962     }
   3963     PyOS_setsig(SIGCHLD, sig_saved);
   3964     slave_name = ptsname(master_fd); /* get name of slave */
   3965     if (slave_name == NULL)
   3966         return posix_error();
   3967     slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
   3968     if (slave_fd < 0)
   3969         return posix_error();
   3970 #if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
   3971     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
   3972     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
   3973 #ifndef __hpux
   3974     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
   3975 #endif /* __hpux */
   3976 #endif /* HAVE_CYGWIN */
   3977 #endif /* HAVE_OPENPTY */
   3978 
   3979     return Py_BuildValue("(ii)", master_fd, slave_fd);
   3980 
   3981 }
   3982 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
   3983 
   3984 #ifdef HAVE_FORKPTY
   3985 PyDoc_STRVAR(posix_forkpty__doc__,
   3986 "forkpty() -> (pid, master_fd)\n\n\
   3987 Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
   3988 Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
   3989 To both, return fd of newly opened pseudo-terminal.\n");
   3990 
   3991 static PyObject *
   3992 posix_forkpty(PyObject *self, PyObject *noargs)
   3993 {
   3994     int master_fd = -1, result = 0;
   3995     pid_t pid;
   3996 
   3997     _PyImport_AcquireLock();
   3998     pid = forkpty(&master_fd, NULL, NULL, NULL);
   3999     if (pid == 0) {
   4000         /* child: this clobbers and resets the import lock. */
   4001         PyOS_AfterFork();
   4002     } else {
   4003         /* parent: release the import lock. */
   4004         result = _PyImport_ReleaseLock();
   4005     }
   4006     if (pid == -1)
   4007         return posix_error();
   4008     if (result < 0) {
   4009         /* Don't clobber the OSError if the fork failed. */
   4010         PyErr_SetString(PyExc_RuntimeError,
   4011                         "not holding the import lock");
   4012         return NULL;
   4013     }
   4014     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
   4015 }
   4016 #endif
   4017 
   4018 #ifdef HAVE_GETEGID
   4019 PyDoc_STRVAR(posix_getegid__doc__,
   4020 "getegid() -> egid\n\n\
   4021 Return the current process's effective group id.");
   4022 
   4023 static PyObject *
   4024 posix_getegid(PyObject *self, PyObject *noargs)
   4025 {
   4026     return _PyInt_FromGid(getegid());
   4027 }
   4028 #endif
   4029 
   4030 
   4031 #ifdef HAVE_GETEUID
   4032 PyDoc_STRVAR(posix_geteuid__doc__,
   4033 "geteuid() -> euid\n\n\
   4034 Return the current process's effective user id.");
   4035 
   4036 static PyObject *
   4037 posix_geteuid(PyObject *self, PyObject *noargs)
   4038 {
   4039     return _PyInt_FromUid(geteuid());
   4040 }
   4041 #endif
   4042 
   4043 
   4044 #ifdef HAVE_GETGID
   4045 PyDoc_STRVAR(posix_getgid__doc__,
   4046 "getgid() -> gid\n\n\
   4047 Return the current process's group id.");
   4048 
   4049 static PyObject *
   4050 posix_getgid(PyObject *self, PyObject *noargs)
   4051 {
   4052     return _PyInt_FromGid(getgid());
   4053 }
   4054 #endif
   4055 
   4056 
   4057 PyDoc_STRVAR(posix_getpid__doc__,
   4058 "getpid() -> pid\n\n\
   4059 Return the current process id");
   4060 
   4061 static PyObject *
   4062 posix_getpid(PyObject *self, PyObject *noargs)
   4063 {
   4064     return PyLong_FromPid(getpid());
   4065 }
   4066 
   4067 
   4068 #ifdef HAVE_GETGROUPS
   4069 PyDoc_STRVAR(posix_getgroups__doc__,
   4070 "getgroups() -> list of group IDs\n\n\
   4071 Return list of supplemental group IDs for the process.");
   4072 
   4073 static PyObject *
   4074 posix_getgroups(PyObject *self, PyObject *noargs)
   4075 {
   4076     PyObject *result = NULL;
   4077 
   4078 #ifdef NGROUPS_MAX
   4079 #define MAX_GROUPS NGROUPS_MAX
   4080 #else
   4081     /* defined to be 16 on Solaris7, so this should be a small number */
   4082 #define MAX_GROUPS 64
   4083 #endif
   4084     gid_t grouplist[MAX_GROUPS];
   4085 
   4086     /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
   4087      * This is a helper variable to store the intermediate result when
   4088      * that happens.
   4089      *
   4090      * To keep the code readable the OSX behaviour is unconditional,
   4091      * according to the POSIX spec this should be safe on all unix-y
   4092      * systems.
   4093      */
   4094     gid_t* alt_grouplist = grouplist;
   4095     int n;
   4096 
   4097 #ifdef __APPLE__
   4098     /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
   4099      * there are more groups than can fit in grouplist.  Therefore, on OS X
   4100      * always first call getgroups with length 0 to get the actual number
   4101      * of groups.
   4102      */
   4103     n = getgroups(0, NULL);
   4104     if (n < 0) {
   4105         return posix_error();
   4106     } else if (n <= MAX_GROUPS) {
   4107         /* groups will fit in existing array */
   4108         alt_grouplist = grouplist;
   4109     } else {
   4110         alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
   4111         if (alt_grouplist == NULL) {
   4112             errno = EINVAL;
   4113             return posix_error();
   4114         }
   4115     }
   4116 
   4117     n = getgroups(n, alt_grouplist);
   4118     if (n == -1) {
   4119         if (alt_grouplist != grouplist) {
   4120             PyMem_Free(alt_grouplist);
   4121         }
   4122         return posix_error();
   4123     }
   4124 #else
   4125     n = getgroups(MAX_GROUPS, grouplist);
   4126     if (n < 0) {
   4127         if (errno == EINVAL) {
   4128             n = getgroups(0, NULL);
   4129             if (n == -1) {
   4130                 return posix_error();
   4131             }
   4132             if (n == 0) {
   4133                 /* Avoid malloc(0) */
   4134                 alt_grouplist = grouplist;
   4135             } else {
   4136                 alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
   4137                 if (alt_grouplist == NULL) {
   4138                     errno = EINVAL;
   4139                     return posix_error();
   4140                 }
   4141                 n = getgroups(n, alt_grouplist);
   4142                 if (n == -1) {
   4143                     PyMem_Free(alt_grouplist);
   4144                     return posix_error();
   4145                 }
   4146             }
   4147         } else {
   4148             return posix_error();
   4149         }
   4150     }
   4151 #endif
   4152 
   4153     result = PyList_New(n);
   4154     if (result != NULL) {
   4155         int i;
   4156         for (i = 0; i < n; ++i) {
   4157             PyObject *o = _PyInt_FromGid(alt_grouplist[i]);
   4158             if (o == NULL) {
   4159                 Py_DECREF(result);
   4160                 result = NULL;
   4161                 break;
   4162             }
   4163             PyList_SET_ITEM(result, i, o);
   4164         }
   4165     }
   4166 
   4167     if (alt_grouplist != grouplist) {
   4168         PyMem_Free(alt_grouplist);
   4169     }
   4170 
   4171     return result;
   4172 }
   4173 #endif
   4174 
   4175 #ifdef HAVE_INITGROUPS
   4176 PyDoc_STRVAR(posix_initgroups__doc__,
   4177 "initgroups(username, gid) -> None\n\n\
   4178 Call the system initgroups() to initialize the group access list with all of\n\
   4179 the groups of which the specified username is a member, plus the specified\n\
   4180 group id.");
   4181 
   4182 static PyObject *
   4183 posix_initgroups(PyObject *self, PyObject *args)
   4184 {
   4185     char *username;
   4186 #ifdef __APPLE__
   4187     int gid;
   4188 #else
   4189     gid_t gid;
   4190 #endif
   4191 
   4192 #ifdef __APPLE__
   4193     if (!PyArg_ParseTuple(args, "si:initgroups", &username,
   4194                           &gid))
   4195 #else
   4196     if (!PyArg_ParseTuple(args, "sO&:initgroups", &username,
   4197                           _Py_Gid_Converter, &gid))
   4198 #endif
   4199         return NULL;
   4200 
   4201     if (initgroups(username, gid) == -1)
   4202         return PyErr_SetFromErrno(PyExc_OSError);
   4203 
   4204     Py_INCREF(Py_None);
   4205     return Py_None;
   4206 }
   4207 #endif
   4208 
   4209 #ifdef HAVE_GETPGID
   4210 PyDoc_STRVAR(posix_getpgid__doc__,
   4211 "getpgid(pid) -> pgid\n\n\
   4212 Call the system call getpgid().");
   4213 
   4214 static PyObject *
   4215 posix_getpgid(PyObject *self, PyObject *args)
   4216 {
   4217     pid_t pid, pgid;
   4218     if (!PyArg_ParseTuple(args, PARSE_PID ":getpgid", &pid))
   4219         return NULL;
   4220     pgid = getpgid(pid);
   4221     if (pgid < 0)
   4222         return posix_error();
   4223     return PyLong_FromPid(pgid);
   4224 }
   4225 #endif /* HAVE_GETPGID */
   4226 
   4227 
   4228 #ifdef HAVE_GETPGRP
   4229 PyDoc_STRVAR(posix_getpgrp__doc__,
   4230 "getpgrp() -> pgrp\n\n\
   4231 Return the current process group id.");
   4232 
   4233 static PyObject *
   4234 posix_getpgrp(PyObject *self, PyObject *noargs)
   4235 {
   4236 #ifdef GETPGRP_HAVE_ARG
   4237     return PyLong_FromPid(getpgrp(0));
   4238 #else /* GETPGRP_HAVE_ARG */
   4239     return PyLong_FromPid(getpgrp());
   4240 #endif /* GETPGRP_HAVE_ARG */
   4241 }
   4242 #endif /* HAVE_GETPGRP */
   4243 
   4244 
   4245 #ifdef HAVE_SETPGRP
   4246 PyDoc_STRVAR(posix_setpgrp__doc__,
   4247 "setpgrp()\n\n\
   4248 Make this process the process group leader.");
   4249 
   4250 static PyObject *
   4251 posix_setpgrp(PyObject *self, PyObject *noargs)
   4252 {
   4253 #ifdef SETPGRP_HAVE_ARG
   4254     if (setpgrp(0, 0) < 0)
   4255 #else /* SETPGRP_HAVE_ARG */
   4256     if (setpgrp() < 0)
   4257 #endif /* SETPGRP_HAVE_ARG */
   4258         return posix_error();
   4259     Py_INCREF(Py_None);
   4260     return Py_None;
   4261 }
   4262 
   4263 #endif /* HAVE_SETPGRP */
   4264 
   4265 #ifdef HAVE_GETPPID
   4266 PyDoc_STRVAR(posix_getppid__doc__,
   4267 "getppid() -> ppid\n\n\
   4268 Return the parent's process id.");
   4269 
   4270 static PyObject *
   4271 posix_getppid(PyObject *self, PyObject *noargs)
   4272 {
   4273     return PyLong_FromPid(getppid());
   4274 }
   4275 #endif
   4276 
   4277 
   4278 #ifdef HAVE_GETLOGIN
   4279 PyDoc_STRVAR(posix_getlogin__doc__,
   4280 "getlogin() -> string\n\n\
   4281 Return the actual login name.");
   4282 
   4283 static PyObject *
   4284 posix_getlogin(PyObject *self, PyObject *noargs)
   4285 {
   4286     PyObject *result = NULL;
   4287     char *name;
   4288     int old_errno = errno;
   4289 
   4290     errno = 0;
   4291     name = getlogin();
   4292     if (name == NULL) {
   4293         if (errno)
   4294         posix_error();
   4295         else
   4296         PyErr_SetString(PyExc_OSError,
   4297                         "unable to determine login name");
   4298     }
   4299     else
   4300         result = PyString_FromString(name);
   4301     errno = old_errno;
   4302 
   4303     return result;
   4304 }
   4305 #endif
   4306 
   4307 #ifdef HAVE_GETUID
   4308 PyDoc_STRVAR(posix_getuid__doc__,
   4309 "getuid() -> uid\n\n\
   4310 Return the current process's user id.");
   4311 
   4312 static PyObject *
   4313 posix_getuid(PyObject *self, PyObject *noargs)
   4314 {
   4315     return _PyInt_FromUid(getuid());
   4316 }
   4317 #endif
   4318 
   4319 
   4320 #ifdef HAVE_KILL
   4321 PyDoc_STRVAR(posix_kill__doc__,
   4322 "kill(pid, sig)\n\n\
   4323 Kill a process with a signal.");
   4324 
   4325 static PyObject *
   4326 posix_kill(PyObject *self, PyObject *args)
   4327 {
   4328     pid_t pid;
   4329     int sig;
   4330     if (!PyArg_ParseTuple(args, PARSE_PID "i:kill", &pid, &sig))
   4331         return NULL;
   4332 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
   4333     if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
   4334         APIRET rc;
   4335         if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
   4336             return os2_error(rc);
   4337 
   4338     } else if (sig == XCPT_SIGNAL_KILLPROC) {
   4339         APIRET rc;
   4340         if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
   4341             return os2_error(rc);
   4342 
   4343     } else
   4344         return NULL; /* Unrecognized Signal Requested */
   4345 #else
   4346     if (kill(pid, sig) == -1)
   4347         return posix_error();
   4348 #endif
   4349     Py_INCREF(Py_None);
   4350     return Py_None;
   4351 }
   4352 #endif
   4353 
   4354 #ifdef HAVE_KILLPG
   4355 PyDoc_STRVAR(posix_killpg__doc__,
   4356 "killpg(pgid, sig)\n\n\
   4357 Kill a process group with a signal.");
   4358 
   4359 static PyObject *
   4360 posix_killpg(PyObject *self, PyObject *args)
   4361 {
   4362     int sig;
   4363     pid_t pgid;
   4364     /* XXX some man pages make the `pgid` parameter an int, others
   4365        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
   4366        take the same type. Moreover, pid_t is always at least as wide as
   4367        int (else compilation of this module fails), which is safe. */
   4368     if (!PyArg_ParseTuple(args, PARSE_PID "i:killpg", &pgid, &sig))
   4369         return NULL;
   4370     if (killpg(pgid, sig) == -1)
   4371         return posix_error();
   4372     Py_INCREF(Py_None);
   4373     return Py_None;
   4374 }
   4375 #endif
   4376 
   4377 #ifdef MS_WINDOWS
   4378 PyDoc_STRVAR(win32_kill__doc__,
   4379 "kill(pid, sig)\n\n\
   4380 Kill a process with a signal.");
   4381 
   4382 static PyObject *
   4383 win32_kill(PyObject *self, PyObject *args)
   4384 {
   4385     PyObject *result;
   4386     DWORD pid, sig, err;
   4387     HANDLE handle;
   4388 
   4389     if (!PyArg_ParseTuple(args, "kk:kill", &pid, &sig))
   4390         return NULL;
   4391 
   4392     /* Console processes which share a common console can be sent CTRL+C or
   4393        CTRL+BREAK events, provided they handle said events. */
   4394     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
   4395         if (GenerateConsoleCtrlEvent(sig, pid) == 0) {
   4396             err = GetLastError();
   4397             return PyErr_SetFromWindowsErr(err);
   4398         }
   4399         else
   4400             Py_RETURN_NONE;
   4401     }
   4402 
   4403     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
   4404        attempt to open and terminate the process. */
   4405     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
   4406     if (handle == NULL) {
   4407         err = GetLastError();
   4408         return PyErr_SetFromWindowsErr(err);
   4409     }
   4410 
   4411     if (TerminateProcess(handle, sig) == 0) {
   4412         err = GetLastError();
   4413         result = PyErr_SetFromWindowsErr(err);
   4414     } else {
   4415         Py_INCREF(Py_None);
   4416         result = Py_None;
   4417     }
   4418 
   4419     CloseHandle(handle);
   4420     return result;
   4421 }
   4422 
   4423 PyDoc_STRVAR(posix__isdir__doc__,
   4424 "Return true if the pathname refers to an existing directory.");
   4425 
   4426 static PyObject *
   4427 posix__isdir(PyObject *self, PyObject *args)
   4428 {
   4429     char *path;
   4430     Py_UNICODE *wpath;
   4431     DWORD attributes;
   4432 
   4433     if (PyArg_ParseTuple(args, "u|:_isdir", &wpath)) {
   4434         attributes = GetFileAttributesW(wpath);
   4435         if (attributes == INVALID_FILE_ATTRIBUTES)
   4436             Py_RETURN_FALSE;
   4437         goto check;
   4438     }
   4439     /* Drop the argument parsing error as narrow strings
   4440        are also valid. */
   4441     PyErr_Clear();
   4442 
   4443     if (!PyArg_ParseTuple(args, "et:_isdir",
   4444                           Py_FileSystemDefaultEncoding, &path))
   4445         return NULL;
   4446 
   4447     attributes = GetFileAttributesA(path);
   4448     PyMem_Free(path);
   4449     if (attributes == INVALID_FILE_ATTRIBUTES)
   4450         Py_RETURN_FALSE;
   4451 
   4452 check:
   4453     if (attributes & FILE_ATTRIBUTE_DIRECTORY)
   4454         Py_RETURN_TRUE;
   4455     else
   4456         Py_RETURN_FALSE;
   4457 }
   4458 #endif /* MS_WINDOWS */
   4459 
   4460 #ifdef HAVE_PLOCK
   4461 
   4462 #ifdef HAVE_SYS_LOCK_H
   4463 #include <sys/lock.h>
   4464 #endif
   4465 
   4466 PyDoc_STRVAR(posix_plock__doc__,
   4467 "plock(op)\n\n\
   4468 Lock program segments into memory.");
   4469 
   4470 static PyObject *
   4471 posix_plock(PyObject *self, PyObject *args)
   4472 {
   4473     int op;
   4474     if (!PyArg_ParseTuple(args, "i:plock", &op))
   4475         return NULL;
   4476     if (plock(op) == -1)
   4477         return posix_error();
   4478     Py_INCREF(Py_None);
   4479     return Py_None;
   4480 }
   4481 #endif
   4482 
   4483 
   4484 #ifdef HAVE_POPEN
   4485 PyDoc_STRVAR(posix_popen__doc__,
   4486 "popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\
   4487 Open a pipe to/from a command returning a file object.");
   4488 
   4489 #if defined(PYOS_OS2)
   4490 #if defined(PYCC_VACPP)
   4491 static int
   4492 async_system(const char *command)
   4493 {
   4494     char errormsg[256], args[1024];
   4495     RESULTCODES rcodes;
   4496     APIRET rc;
   4497 
   4498     char *shell = getenv("COMSPEC");
   4499     if (!shell)
   4500         shell = "cmd";
   4501 
   4502     /* avoid overflowing the argument buffer */
   4503     if (strlen(shell) + 3 + strlen(command) >= 1024)
   4504         return ERROR_NOT_ENOUGH_MEMORY
   4505 
   4506     args[0] = '\0';
   4507     strcat(args, shell);
   4508     strcat(args, "/c ");
   4509     strcat(args, command);
   4510 
   4511     /* execute asynchronously, inheriting the environment */
   4512     rc = DosExecPgm(errormsg,
   4513                     sizeof(errormsg),
   4514                     EXEC_ASYNC,
   4515                     args,
   4516                     NULL,
   4517                     &rcodes,
   4518                     shell);
   4519     return rc;
   4520 }
   4521 
   4522 static FILE *
   4523 popen(const char *command, const char *mode, int pipesize, int *err)
   4524 {
   4525     int oldfd, tgtfd;
   4526     HFILE pipeh[2];
   4527     APIRET rc;
   4528 
   4529     /* mode determines which of stdin or stdout is reconnected to
   4530      * the pipe to the child
   4531      */
   4532     if (strchr(mode, 'r') != NULL) {
   4533         tgt_fd = 1;             /* stdout */
   4534     } else if (strchr(mode, 'w')) {
   4535         tgt_fd = 0;             /* stdin */
   4536     } else {
   4537         *err = ERROR_INVALID_ACCESS;
   4538         return NULL;
   4539     }
   4540 
   4541     /* setup the pipe */
   4542     if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) {
   4543         *err = rc;
   4544         return NULL;
   4545     }
   4546 
   4547     /* prevent other threads accessing stdio */
   4548     DosEnterCritSec();
   4549 
   4550     /* reconnect stdio and execute child */
   4551     oldfd = dup(tgtfd);
   4552     close(tgtfd);
   4553     if (dup2(pipeh[tgtfd], tgtfd) == 0) {
   4554         DosClose(pipeh[tgtfd]);
   4555         rc = async_system(command);
   4556     }
   4557 
   4558     /* restore stdio */
   4559     dup2(oldfd, tgtfd);
   4560     close(oldfd);
   4561 
   4562     /* allow other threads access to stdio */
   4563     DosExitCritSec();
   4564 
   4565     /* if execution of child was successful return file stream */
   4566     if (rc == NO_ERROR)
   4567         return fdopen(pipeh[1 - tgtfd], mode);
   4568     else {
   4569         DosClose(pipeh[1 - tgtfd]);
   4570         *err = rc;
   4571         return NULL;
   4572     }
   4573 }
   4574 
   4575 static PyObject *
   4576 posix_popen(PyObject *self, PyObject *args)
   4577 {
   4578     char *name;
   4579     char *mode = "r";
   4580     int   err, bufsize = -1;
   4581     FILE *fp;
   4582     PyObject *f;
   4583     if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
   4584         return NULL;
   4585     Py_BEGIN_ALLOW_THREADS
   4586     fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err);
   4587     Py_END_ALLOW_THREADS
   4588     if (fp == NULL)
   4589         return os2_error(err);
   4590 
   4591     f = PyFile_FromFile(fp, name, mode, fclose);
   4592     if (f != NULL)
   4593         PyFile_SetBufSize(f, bufsize);
   4594     return f;
   4595 }
   4596 
   4597 #elif defined(PYCC_GCC)
   4598 
   4599 /* standard posix version of popen() support */
   4600 static PyObject *
   4601 posix_popen(PyObject *self, PyObject *args)
   4602 {
   4603     char *name;
   4604     char *mode = "r";
   4605     int bufsize = -1;
   4606     FILE *fp;
   4607     PyObject *f;
   4608     if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
   4609         return NULL;
   4610     Py_BEGIN_ALLOW_THREADS
   4611     fp = popen(name, mode);
   4612     Py_END_ALLOW_THREADS
   4613     if (fp == NULL)
   4614         return posix_error();
   4615     f = PyFile_FromFile(fp, name, mode, pclose);
   4616     if (f != NULL)
   4617         PyFile_SetBufSize(f, bufsize);
   4618     return f;
   4619 }
   4620 
   4621 /* fork() under OS/2 has lots'o'warts
   4622  * EMX supports pipe() and spawn*() so we can synthesize popen[234]()
   4623  * most of this code is a ripoff of the win32 code, but using the
   4624  * capabilities of EMX's C library routines
   4625  */
   4626 
   4627 /* These tell _PyPopen() whether to return 1, 2, or 3 file objects. */
   4628 #define POPEN_1 1
   4629 #define POPEN_2 2
   4630 #define POPEN_3 3
   4631 #define POPEN_4 4
   4632 
   4633 static PyObject *_PyPopen(char *, int, int, int);
   4634 static int _PyPclose(FILE *file);
   4635 
   4636 /*
   4637  * Internal dictionary mapping popen* file pointers to process handles,
   4638  * for use when retrieving the process exit code.  See _PyPclose() below
   4639  * for more information on this dictionary's use.
   4640  */
   4641 static PyObject *_PyPopenProcs = NULL;
   4642 
   4643 /* os2emx version of popen2()
   4644  *
   4645  * The result of this function is a pipe (file) connected to the
   4646  * process's stdin, and a pipe connected to the process's stdout.
   4647  */
   4648 
   4649 static PyObject *
   4650 os2emx_popen2(PyObject *self, PyObject  *args)
   4651 {
   4652     PyObject *f;
   4653     int tm=0;
   4654 
   4655     char *cmdstring;
   4656     char *mode = "t";
   4657     int bufsize = -1;
   4658     if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
   4659         return NULL;
   4660 
   4661     if (*mode == 't')
   4662         tm = O_TEXT;
   4663     else if (*mode != 'b') {
   4664         PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
   4665         return NULL;
   4666     } else
   4667         tm = O_BINARY;
   4668 
   4669     f = _PyPopen(cmdstring, tm, POPEN_2, bufsize);
   4670 
   4671     return f;
   4672 }
   4673 
   4674 /*
   4675  * Variation on os2emx.popen2
   4676  *
   4677  * The result of this function is 3 pipes - the process's stdin,
   4678  * stdout and stderr
   4679  */
   4680 
   4681 static PyObject *
   4682 os2emx_popen3(PyObject *self, PyObject *args)
   4683 {
   4684     PyObject *f;
   4685     int tm = 0;
   4686 
   4687     char *cmdstring;
   4688     char *mode = "t";
   4689     int bufsize = -1;
   4690     if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
   4691         return NULL;
   4692 
   4693     if (*mode == 't')
   4694         tm = O_TEXT;
   4695     else if (*mode != 'b') {
   4696         PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
   4697         return NULL;
   4698     } else
   4699         tm = O_BINARY;
   4700 
   4701     f = _PyPopen(cmdstring, tm, POPEN_3, bufsize);
   4702 
   4703     return f;
   4704 }
   4705 
   4706 /*
   4707  * Variation on os2emx.popen2
   4708  *
   4709  * The result of this function is 2 pipes - the processes stdin,
   4710  * and stdout+stderr combined as a single pipe.
   4711  */
   4712 
   4713 static PyObject *
   4714 os2emx_popen4(PyObject *self, PyObject  *args)
   4715 {
   4716     PyObject *f;
   4717     int tm = 0;
   4718 
   4719     char *cmdstring;
   4720     char *mode = "t";
   4721     int bufsize = -1;
   4722     if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
   4723         return NULL;
   4724 
   4725     if (*mode == 't')
   4726         tm = O_TEXT;
   4727     else if (*mode != 'b') {
   4728         PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
   4729         return NULL;
   4730     } else
   4731         tm = O_BINARY;
   4732 
   4733     f = _PyPopen(cmdstring, tm, POPEN_4, bufsize);
   4734 
   4735     return f;
   4736 }
   4737 
   4738 /* a couple of structures for convenient handling of multiple
   4739  * file handles and pipes
   4740  */
   4741 struct file_ref
   4742 {
   4743     int handle;
   4744     int flags;
   4745 };
   4746 
   4747 struct pipe_ref
   4748 {
   4749     int rd;
   4750     int wr;
   4751 };
   4752 
   4753 /* The following code is derived from the win32 code */
   4754 
   4755 static PyObject *
   4756 _PyPopen(char *cmdstring, int mode, int n, int bufsize)
   4757 {
   4758     struct file_ref stdio[3];
   4759     struct pipe_ref p_fd[3];
   4760     FILE *p_s[3];
   4761     int file_count, i, pipe_err;
   4762     pid_t pipe_pid;
   4763     char *shell, *sh_name, *opt, *rd_mode, *wr_mode;
   4764     PyObject *f, *p_f[3];
   4765 
   4766     /* file modes for subsequent fdopen's on pipe handles */
   4767     if (mode == O_TEXT)
   4768     {
   4769         rd_mode = "rt";
   4770         wr_mode = "wt";
   4771     }
   4772     else
   4773     {
   4774         rd_mode = "rb";
   4775         wr_mode = "wb";
   4776     }
   4777 
   4778     /* prepare shell references */
   4779     if ((shell = getenv("EMXSHELL")) == NULL)
   4780         if ((shell = getenv("COMSPEC")) == NULL)
   4781         {
   4782             errno = ENOENT;
   4783             return posix_error();
   4784         }
   4785 
   4786     sh_name = _getname(shell);
   4787     if (stricmp(sh_name, "cmd.exe") == 0 || stricmp(sh_name, "4os2.exe") == 0)
   4788         opt = "/c";
   4789     else
   4790         opt = "-c";
   4791 
   4792     /* save current stdio fds + their flags, and set not inheritable */
   4793     i = pipe_err = 0;
   4794     while (pipe_err >= 0 && i < 3)
   4795     {
   4796         pipe_err = stdio[i].handle = dup(i);
   4797         stdio[i].flags = fcntl(i, F_GETFD, 0);
   4798         fcntl(stdio[i].handle, F_SETFD, stdio[i].flags | FD_CLOEXEC);
   4799         i++;
   4800     }
   4801     if (pipe_err < 0)
   4802     {
   4803         /* didn't get them all saved - clean up and bail out */
   4804         int saved_err = errno;
   4805         while (i-- > 0)
   4806         {
   4807             close(stdio[i].handle);
   4808         }
   4809         errno = saved_err;
   4810         return posix_error();
   4811     }
   4812 
   4813     /* create pipe ends */
   4814     file_count = 2;
   4815     if (n == POPEN_3)
   4816         file_count = 3;
   4817     i = pipe_err = 0;
   4818     while ((pipe_err == 0) && (i < file_count))
   4819         pipe_err = pipe((int *)&p_fd[i++]);
   4820     if (pipe_err < 0)
   4821     {
   4822         /* didn't get them all made - clean up and bail out */
   4823         while (i-- > 0)
   4824         {
   4825             close(p_fd[i].wr);
   4826             close(p_fd[i].rd);
   4827         }
   4828         errno = EPIPE;
   4829         return posix_error();
   4830     }
   4831 
   4832     /* change the actual standard IO streams over temporarily,
   4833      * making the retained pipe ends non-inheritable
   4834      */
   4835     pipe_err = 0;
   4836 
   4837     /* - stdin */
   4838     if (dup2(p_fd[0].rd, 0) == 0)
   4839     {
   4840         close(p_fd[0].rd);
   4841         i = fcntl(p_fd[0].wr, F_GETFD, 0);
   4842         fcntl(p_fd[0].wr, F_SETFD, i | FD_CLOEXEC);
   4843         if ((p_s[0] = fdopen(p_fd[0].wr, wr_mode)) == NULL)
   4844         {
   4845             close(p_fd[0].wr);
   4846             pipe_err = -1;
   4847         }
   4848     }
   4849     else
   4850     {
   4851         pipe_err = -1;
   4852     }
   4853 
   4854     /* - stdout */
   4855     if (pipe_err == 0)
   4856     {
   4857         if (dup2(p_fd[1].wr, 1) == 1)
   4858         {
   4859             close(p_fd[1].wr);
   4860             i = fcntl(p_fd[1].rd, F_GETFD, 0);
   4861             fcntl(p_fd[1].rd, F_SETFD, i | FD_CLOEXEC);
   4862             if ((p_s[1] = fdopen(p_fd[1].rd, rd_mode)) == NULL)
   4863             {
   4864                 close(p_fd[1].rd);
   4865                 pipe_err = -1;
   4866             }
   4867         }
   4868         else
   4869         {
   4870             pipe_err = -1;
   4871         }
   4872     }
   4873 
   4874     /* - stderr, as required */
   4875     if (pipe_err == 0)
   4876         switch (n)
   4877         {
   4878             case POPEN_3:
   4879             {
   4880                 if (dup2(p_fd[2].wr, 2) == 2)
   4881                 {
   4882                     close(p_fd[2].wr);
   4883                     i = fcntl(p_fd[2].rd, F_GETFD, 0);
   4884                     fcntl(p_fd[2].rd, F_SETFD, i | FD_CLOEXEC);
   4885                     if ((p_s[2] = fdopen(p_fd[2].rd, rd_mode)) == NULL)
   4886                     {
   4887                         close(p_fd[2].rd);
   4888                         pipe_err = -1;
   4889                     }
   4890                 }
   4891                 else
   4892                 {
   4893                     pipe_err = -1;
   4894                 }
   4895                 break;
   4896             }
   4897 
   4898             case POPEN_4:
   4899             {
   4900                 if (dup2(1, 2) != 2)
   4901                 {
   4902                     pipe_err = -1;
   4903                 }
   4904                 break;
   4905             }
   4906         }
   4907 
   4908     /* spawn the child process */
   4909     if (pipe_err == 0)
   4910     {
   4911         pipe_pid = spawnlp(P_NOWAIT, shell, shell, opt, cmdstring, (char *)0);
   4912         if (pipe_pid == -1)
   4913         {
   4914             pipe_err = -1;
   4915         }
   4916         else
   4917         {
   4918             /* save the PID into the FILE structure
   4919              * NOTE: this implementation doesn't actually
   4920              * take advantage of this, but do it for
   4921              * completeness - AIM Apr01
   4922              */
   4923             for (i = 0; i < file_count; i++)
   4924                 p_s[i]->_pid = pipe_pid;
   4925         }
   4926     }
   4927 
   4928     /* reset standard IO to normal */
   4929     for (i = 0; i < 3; i++)
   4930     {
   4931         dup2(stdio[i].handle, i);
   4932         fcntl(i, F_SETFD, stdio[i].flags);
   4933         close(stdio[i].handle);
   4934     }
   4935 
   4936     /* if any remnant problems, clean up and bail out */
   4937     if (pipe_err < 0)
   4938     {
   4939         for (i = 0; i < 3; i++)
   4940         {
   4941             close(p_fd[i].rd);
   4942             close(p_fd[i].wr);
   4943         }
   4944         errno = EPIPE;
   4945         return posix_error_with_filename(cmdstring);
   4946     }
   4947 
   4948     /* build tuple of file objects to return */
   4949     if ((p_f[0] = PyFile_FromFile(p_s[0], cmdstring, wr_mode, _PyPclose)) != NULL)
   4950         PyFile_SetBufSize(p_f[0], bufsize);
   4951     if ((p_f[1] = PyFile_FromFile(p_s[1], cmdstring, rd_mode, _PyPclose)) != NULL)
   4952         PyFile_SetBufSize(p_f[1], bufsize);
   4953     if (n == POPEN_3)
   4954     {
   4955         if ((p_f[2] = PyFile_FromFile(p_s[2], cmdstring, rd_mode, _PyPclose)) != NULL)
   4956             PyFile_SetBufSize(p_f[0], bufsize);
   4957         f = PyTuple_Pack(3, p_f[0], p_f[1], p_f[2]);
   4958     }
   4959     else
   4960         f = PyTuple_Pack(2, p_f[0], p_f[1]);
   4961 
   4962     /*
   4963      * Insert the files we've created into the process dictionary
   4964      * all referencing the list with the process handle and the
   4965      * initial number of files (see description below in _PyPclose).
   4966      * Since if _PyPclose later tried to wait on a process when all
   4967      * handles weren't closed, it could create a deadlock with the
   4968      * child, we spend some energy here to try to ensure that we
   4969      * either insert all file handles into the dictionary or none
   4970      * at all.  It's a little clumsy with the various popen modes
   4971      * and variable number of files involved.
   4972      */
   4973     if (!_PyPopenProcs)
   4974     {
   4975         _PyPopenProcs = PyDict_New();
   4976     }
   4977 
   4978     if (_PyPopenProcs)
   4979     {
   4980         PyObject *procObj, *pidObj, *intObj, *fileObj[3];
   4981         int ins_rc[3];
   4982 
   4983         fileObj[0] = fileObj[1] = fileObj[2] = NULL;
   4984         ins_rc[0]  = ins_rc[1]  = ins_rc[2]  = 0;
   4985 
   4986         procObj = PyList_New(2);
   4987         pidObj = PyLong_FromPid(pipe_pid);
   4988         intObj = PyInt_FromLong((long) file_count);
   4989 
   4990         if (procObj && pidObj && intObj)
   4991         {
   4992             PyList_SetItem(procObj, 0, pidObj);
   4993             PyList_SetItem(procObj, 1, intObj);
   4994 
   4995             fileObj[0] = PyLong_FromVoidPtr(p_s[0]);
   4996             if (fileObj[0])
   4997             {
   4998                 ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
   4999                                            fileObj[0],
   5000                                            procObj);
   5001             }
   5002             fileObj[1] = PyLong_FromVoidPtr(p_s[1]);
   5003             if (fileObj[1])
   5004             {
   5005                 ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
   5006                                            fileObj[1],
   5007                                            procObj);
   5008             }
   5009             if (file_count >= 3)
   5010             {
   5011                 fileObj[2] = PyLong_FromVoidPtr(p_s[2]);
   5012                 if (fileObj[2])
   5013                 {
   5014                     ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
   5015                                                fileObj[2],
   5016                                                procObj);
   5017                 }
   5018             }
   5019 
   5020             if (ins_rc[0] < 0 || !fileObj[0] ||
   5021                 ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
   5022                 ins_rc[2] < 0 || (file_count > 2 && !fileObj[2]))
   5023             {
   5024                 /* Something failed - remove any dictionary
   5025                  * entries that did make it.
   5026                  */
   5027                 if (!ins_rc[0] && fileObj[0])
   5028                 {
   5029                     PyDict_DelItem(_PyPopenProcs,
   5030                                    fileObj[0]);
   5031                 }
   5032                 if (!ins_rc[1] && fileObj[1])
   5033                 {
   5034                     PyDict_DelItem(_PyPopenProcs,
   5035                                    fileObj[1]);
   5036                 }
   5037                 if (!ins_rc[2] && fileObj[2])
   5038                 {
   5039                     PyDict_DelItem(_PyPopenProcs,
   5040                                    fileObj[2]);
   5041                 }
   5042             }
   5043         }
   5044 
   5045         /*
   5046          * Clean up our localized references for the dictionary keys
   5047          * and value since PyDict_SetItem will Py_INCREF any copies
   5048          * that got placed in the dictionary.
   5049          */
   5050         Py_XDECREF(procObj);
   5051         Py_XDECREF(fileObj[0]);
   5052         Py_XDECREF(fileObj[1]);
   5053         Py_XDECREF(fileObj[2]);
   5054     }
   5055 
   5056     /* Child is launched. */
   5057     return f;
   5058 }
   5059 
   5060 /*
   5061  * Wrapper for fclose() to use for popen* files, so we can retrieve the
   5062  * exit code for the child process and return as a result of the close.
   5063  *
   5064  * This function uses the _PyPopenProcs dictionary in order to map the
   5065  * input file pointer to information about the process that was
   5066  * originally created by the popen* call that created the file pointer.
   5067  * The dictionary uses the file pointer as a key (with one entry
   5068  * inserted for each file returned by the original popen* call) and a
   5069  * single list object as the value for all files from a single call.
   5070  * The list object contains the Win32 process handle at [0], and a file
   5071  * count at [1], which is initialized to the total number of file
   5072  * handles using that list.
   5073  *
   5074  * This function closes whichever handle it is passed, and decrements
   5075  * the file count in the dictionary for the process handle pointed to
   5076  * by this file.  On the last close (when the file count reaches zero),
   5077  * this function will wait for the child process and then return its
   5078  * exit code as the result of the close() operation.  This permits the
   5079  * files to be closed in any order - it is always the close() of the
   5080  * final handle that will return the exit code.
   5081  *
   5082  * NOTE: This function is currently called with the GIL released.
   5083  * hence we use the GILState API to manage our state.
   5084  */
   5085 
   5086 static int _PyPclose(FILE *file)
   5087 {
   5088     int result;
   5089     int exit_code;
   5090     pid_t pipe_pid;
   5091     PyObject *procObj, *pidObj, *intObj, *fileObj;
   5092     int file_count;
   5093 #ifdef WITH_THREAD
   5094     PyGILState_STATE state;
   5095 #endif
   5096 
   5097     /* Close the file handle first, to ensure it can't block the
   5098      * child from exiting if it's the last handle.
   5099      */
   5100     result = fclose(file);
   5101 
   5102 #ifdef WITH_THREAD
   5103     state = PyGILState_Ensure();
   5104 #endif
   5105     if (_PyPopenProcs)
   5106     {
   5107         if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
   5108             (procObj = PyDict_GetItem(_PyPopenProcs,
   5109                                       fileObj)) != NULL &&
   5110             (pidObj = PyList_GetItem(procObj,0)) != NULL &&
   5111             (intObj = PyList_GetItem(procObj,1)) != NULL)
   5112         {
   5113             pipe_pid = (pid_t) PyLong_AsPid(pidObj);
   5114             file_count = (int) PyInt_AsLong(intObj);
   5115 
   5116             if (file_count > 1)
   5117             {
   5118                 /* Still other files referencing process */
   5119                 file_count--;
   5120                 PyList_SetItem(procObj,1,
   5121                                PyInt_FromLong((long) file_count));
   5122             }
   5123             else
   5124             {
   5125                 /* Last file for this process */
   5126                 if (result != EOF &&
   5127                     waitpid(pipe_pid, &exit_code, 0) == pipe_pid)
   5128                 {
   5129                     /* extract exit status */
   5130                     if (WIFEXITED(exit_code))
   5131                     {
   5132                         result = WEXITSTATUS(exit_code);
   5133                     }
   5134                     else
   5135                     {
   5136                         errno = EPIPE;
   5137                         result = -1;
   5138                     }
   5139                 }
   5140                 else
   5141                 {
   5142                     /* Indicate failure - this will cause the file object
   5143                      * to raise an I/O error and translate the last
   5144                      * error code from errno.  We do have a problem with
   5145                      * last errors that overlap the normal errno table,
   5146                      * but that's a consistent problem with the file object.
   5147                      */
   5148                     result = -1;
   5149                 }
   5150             }
   5151 
   5152             /* Remove this file pointer from dictionary */
   5153             PyDict_DelItem(_PyPopenProcs, fileObj);
   5154 
   5155             if (PyDict_Size(_PyPopenProcs) == 0)
   5156             {
   5157                 Py_DECREF(_PyPopenProcs);
   5158                 _PyPopenProcs = NULL;
   5159             }
   5160 
   5161         } /* if object retrieval ok */
   5162 
   5163         Py_XDECREF(fileObj);
   5164     } /* if _PyPopenProcs */
   5165 
   5166 #ifdef WITH_THREAD
   5167     PyGILState_Release(state);
   5168 #endif
   5169     return result;
   5170 }
   5171 
   5172 #endif /* PYCC_??? */
   5173 
   5174 #elif defined(MS_WINDOWS)
   5175 
   5176 /*
   5177  * Portable 'popen' replacement for Win32.
   5178  *
   5179  * Written by Bill Tutt <billtut (at) microsoft.com>.  Minor tweaks
   5180  * and 2.0 integration by Fredrik Lundh <fredrik (at) pythonware.com>
   5181  * Return code handling by David Bolen <db3l (at) fitlinxx.com>.
   5182  */
   5183 
   5184 #include <malloc.h>
   5185 #include <io.h>
   5186 #include <fcntl.h>
   5187 
   5188 /* These tell _PyPopen() wether to return 1, 2, or 3 file objects. */
   5189 #define POPEN_1 1
   5190 #define POPEN_2 2
   5191 #define POPEN_3 3
   5192 #define POPEN_4 4
   5193 
   5194 static PyObject *_PyPopen(char *, int, int);
   5195 static int _PyPclose(FILE *file);
   5196 
   5197 /*
   5198  * Internal dictionary mapping popen* file pointers to process handles,
   5199  * for use when retrieving the process exit code.  See _PyPclose() below
   5200  * for more information on this dictionary's use.
   5201  */
   5202 static PyObject *_PyPopenProcs = NULL;
   5203 
   5204 
   5205 /* popen that works from a GUI.
   5206  *
   5207  * The result of this function is a pipe (file) connected to the
   5208  * processes stdin or stdout, depending on the requested mode.
   5209  */
   5210 
   5211 static PyObject *
   5212 posix_popen(PyObject *self, PyObject *args)
   5213 {
   5214     PyObject *f;
   5215     int tm = 0;
   5216 
   5217     char *cmdstring;
   5218     char *mode = "r";
   5219     int bufsize = -1;
   5220     if (!PyArg_ParseTuple(args, "s|si:popen", &cmdstring, &mode, &bufsize))
   5221         return NULL;
   5222 
   5223     if (*mode == 'r')
   5224         tm = _O_RDONLY;
   5225     else if (*mode != 'w') {
   5226         PyErr_SetString(PyExc_ValueError, "popen() arg 2 must be 'r' or 'w'");
   5227         return NULL;
   5228     } else
   5229         tm = _O_WRONLY;
   5230 
   5231     if (bufsize != -1) {
   5232         PyErr_SetString(PyExc_ValueError, "popen() arg 3 must be -1");
   5233         return NULL;
   5234     }
   5235 
   5236     if (*(mode+1) == 't')
   5237         f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
   5238     else if (*(mode+1) == 'b')
   5239         f = _PyPopen(cmdstring, tm | _O_BINARY, POPEN_1);
   5240     else
   5241         f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
   5242 
   5243     return f;
   5244 }
   5245 
   5246 /* Variation on win32pipe.popen
   5247  *
   5248  * The result of this function is a pipe (file) connected to the
   5249  * process's stdin, and a pipe connected to the process's stdout.
   5250  */
   5251 
   5252 static PyObject *
   5253 win32_popen2(PyObject *self, PyObject  *args)
   5254 {
   5255     PyObject *f;
   5256     int tm=0;
   5257 
   5258     char *cmdstring;
   5259     char *mode = "t";
   5260     int bufsize = -1;
   5261     if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
   5262         return NULL;
   5263 
   5264     if (*mode == 't')
   5265         tm = _O_TEXT;
   5266     else if (*mode != 'b') {
   5267         PyErr_SetString(PyExc_ValueError, "popen2() arg 2 must be 't' or 'b'");
   5268         return NULL;
   5269     } else
   5270         tm = _O_BINARY;
   5271 
   5272     if (bufsize != -1) {
   5273         PyErr_SetString(PyExc_ValueError, "popen2() arg 3 must be -1");
   5274         return NULL;
   5275     }
   5276 
   5277     f = _PyPopen(cmdstring, tm, POPEN_2);
   5278 
   5279     return f;
   5280 }
   5281 
   5282 /*
   5283  * Variation on <om win32pipe.popen>
   5284  *
   5285  * The result of this function is 3 pipes - the process's stdin,
   5286  * stdout and stderr
   5287  */
   5288 
   5289 static PyObject *
   5290 win32_popen3(PyObject *self, PyObject *args)
   5291 {
   5292     PyObject *f;
   5293     int tm = 0;
   5294 
   5295     char *cmdstring;
   5296     char *mode = "t";
   5297     int bufsize = -1;
   5298     if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
   5299         return NULL;
   5300 
   5301     if (*mode == 't')
   5302         tm = _O_TEXT;
   5303     else if (*mode != 'b') {
   5304         PyErr_SetString(PyExc_ValueError, "popen3() arg 2 must be 't' or 'b'");
   5305         return NULL;
   5306     } else
   5307         tm = _O_BINARY;
   5308 
   5309     if (bufsize != -1) {
   5310         PyErr_SetString(PyExc_ValueError, "popen3() arg 3 must be -1");
   5311         return NULL;
   5312     }
   5313 
   5314     f = _PyPopen(cmdstring, tm, POPEN_3);
   5315 
   5316     return f;
   5317 }
   5318 
   5319 /*
   5320  * Variation on win32pipe.popen
   5321  *
   5322  * The result of this function is 2 pipes - the processes stdin,
   5323  * and stdout+stderr combined as a single pipe.
   5324  */
   5325 
   5326 static PyObject *
   5327 win32_popen4(PyObject *self, PyObject  *args)
   5328 {
   5329     PyObject *f;
   5330     int tm = 0;
   5331 
   5332     char *cmdstring;
   5333     char *mode = "t";
   5334     int bufsize = -1;
   5335     if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
   5336         return NULL;
   5337 
   5338     if (*mode == 't')
   5339         tm = _O_TEXT;
   5340     else if (*mode != 'b') {
   5341         PyErr_SetString(PyExc_ValueError, "popen4() arg 2 must be 't' or 'b'");
   5342         return NULL;
   5343     } else
   5344         tm = _O_BINARY;
   5345 
   5346     if (bufsize != -1) {
   5347         PyErr_SetString(PyExc_ValueError, "popen4() arg 3 must be -1");
   5348         return NULL;
   5349     }
   5350 
   5351     f = _PyPopen(cmdstring, tm, POPEN_4);
   5352 
   5353     return f;
   5354 }
   5355 
   5356 static BOOL
   5357 _PyPopenCreateProcess(char *cmdstring,
   5358                       HANDLE hStdin,
   5359                       HANDLE hStdout,
   5360                       HANDLE hStderr,
   5361                       HANDLE *hProcess)
   5362 {
   5363     PROCESS_INFORMATION piProcInfo;
   5364     STARTUPINFO siStartInfo;
   5365     DWORD dwProcessFlags = 0;  /* no NEW_CONSOLE by default for Ctrl+C handling */
   5366     char *s1,*s2, *s3 = " /c ";
   5367     const char *szConsoleSpawn = "w9xpopen.exe";
   5368     int i;
   5369     Py_ssize_t x;
   5370 
   5371     if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) {
   5372         char *comshell;
   5373 
   5374         s1 = (char *)alloca(i);
   5375         if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
   5376             /* x < i, so x fits into an integer */
   5377             return (int)x;
   5378 
   5379         /* Explicitly check if we are using COMMAND.COM.  If we are
   5380          * then use the w9xpopen hack.
   5381          */
   5382         comshell = s1 + x;
   5383         while (comshell >= s1 && *comshell != '\\')
   5384             --comshell;
   5385         ++comshell;
   5386 
   5387         if (GetVersion() < 0x80000000 &&
   5388             _stricmp(comshell, "command.com") != 0) {
   5389             /* NT/2000 and not using command.com. */
   5390             x = i + strlen(s3) + strlen(cmdstring) + 1;
   5391             s2 = (char *)alloca(x);
   5392             ZeroMemory(s2, x);
   5393             PyOS_snprintf(s2, x, "%s%s%s", s1, s3, cmdstring);
   5394         }
   5395         else {
   5396             /*
   5397              * Oh gag, we're on Win9x or using COMMAND.COM. Use
   5398              * the workaround listed in KB: Q150956
   5399              */
   5400             char modulepath[_MAX_PATH];
   5401             struct stat statinfo;
   5402             GetModuleFileName(NULL, modulepath, sizeof(modulepath));
   5403             for (x = i = 0; modulepath[i]; i++)
   5404                 if (modulepath[i] == SEP)
   5405                     x = i+1;
   5406             modulepath[x] = '\0';
   5407             /* Create the full-name to w9xpopen, so we can test it exists */
   5408             strncat(modulepath,
   5409                     szConsoleSpawn,
   5410                     (sizeof(modulepath)/sizeof(modulepath[0]))
   5411                         -strlen(modulepath));
   5412             if (stat(modulepath, &statinfo) != 0) {
   5413                 size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]);
   5414                 /* Eeek - file-not-found - possibly an embedding
   5415                    situation - see if we can locate it in sys.prefix
   5416                 */
   5417                 strncpy(modulepath,
   5418                         Py_GetExecPrefix(),
   5419                         mplen);
   5420                 modulepath[mplen-1] = '\0';
   5421                 if (modulepath[strlen(modulepath)-1] != '\\')
   5422                     strcat(modulepath, "\\");
   5423                 strncat(modulepath,
   5424                         szConsoleSpawn,
   5425                         mplen-strlen(modulepath));
   5426                 /* No where else to look - raise an easily identifiable
   5427                    error, rather than leaving Windows to report
   5428                    "file not found" - as the user is probably blissfully
   5429                    unaware this shim EXE is used, and it will confuse them.
   5430                    (well, it confused me for a while ;-)
   5431                 */
   5432                 if (stat(modulepath, &statinfo) != 0) {
   5433                     PyErr_Format(PyExc_RuntimeError,
   5434                                  "Can not locate '%s' which is needed "
   5435                                  "for popen to work with your shell "
   5436                                  "or platform.",
   5437                                  szConsoleSpawn);
   5438                     return FALSE;
   5439                 }
   5440             }
   5441             x = i + strlen(s3) + strlen(cmdstring) + 1 +
   5442                 strlen(modulepath) +
   5443                 strlen(szConsoleSpawn) + 1;
   5444 
   5445             s2 = (char *)alloca(x);
   5446             ZeroMemory(s2, x);
   5447             /* To maintain correct argument passing semantics,
   5448                we pass the command-line as it stands, and allow
   5449                quoting to be applied.  w9xpopen.exe will then
   5450                use its argv vector, and re-quote the necessary
   5451                args for the ultimate child process.
   5452             */
   5453             PyOS_snprintf(
   5454                 s2, x,
   5455                 "\"%s\" %s%s%s",
   5456                 modulepath,
   5457                 s1,
   5458                 s3,
   5459                 cmdstring);
   5460             /* Not passing CREATE_NEW_CONSOLE has been known to
   5461                cause random failures on win9x.  Specifically a
   5462                dialog:
   5463                "Your program accessed mem currently in use at xxx"
   5464                and a hopeful warning about the stability of your
   5465                system.
   5466                Cost is Ctrl+C won't kill children, but anyone
   5467                who cares can have a go!
   5468             */
   5469             dwProcessFlags |= CREATE_NEW_CONSOLE;
   5470         }
   5471     }
   5472 
   5473     /* Could be an else here to try cmd.exe / command.com in the path
   5474        Now we'll just error out.. */
   5475     else {
   5476         PyErr_SetString(PyExc_RuntimeError,
   5477                         "Cannot locate a COMSPEC environment variable to "
   5478                         "use as the shell");
   5479         return FALSE;
   5480     }
   5481 
   5482     ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
   5483     siStartInfo.cb = sizeof(STARTUPINFO);
   5484     siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
   5485     siStartInfo.hStdInput = hStdin;
   5486     siStartInfo.hStdOutput = hStdout;
   5487     siStartInfo.hStdError = hStderr;
   5488     siStartInfo.wShowWindow = SW_HIDE;
   5489 
   5490     if (CreateProcess(NULL,
   5491                       s2,
   5492                       NULL,
   5493                       NULL,
   5494                       TRUE,
   5495                       dwProcessFlags,
   5496                       NULL,
   5497                       NULL,
   5498                       &siStartInfo,
   5499                       &piProcInfo) ) {
   5500         /* Close the handles now so anyone waiting is woken. */
   5501         CloseHandle(piProcInfo.hThread);
   5502 
   5503         /* Return process handle */
   5504         *hProcess = piProcInfo.hProcess;
   5505         return TRUE;
   5506     }
   5507     win32_error("CreateProcess", s2);
   5508     return FALSE;
   5509 }
   5510 
   5511 /* The following code is based off of KB: Q190351 */
   5512 
   5513 static PyObject *
   5514 _PyPopen(char *cmdstring, int mode, int n)
   5515 {
   5516     HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
   5517         hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup,
   5518         hChildStderrRdDup, hProcess; /* hChildStdoutWrDup; */
   5519 
   5520     SECURITY_ATTRIBUTES saAttr;
   5521     BOOL fSuccess;
   5522     int fd1, fd2, fd3;
   5523     FILE *f1, *f2, *f3;
   5524     long file_count;
   5525     PyObject *f;
   5526 
   5527     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
   5528     saAttr.bInheritHandle = TRUE;
   5529     saAttr.lpSecurityDescriptor = NULL;
   5530 
   5531     if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
   5532         return win32_error("CreatePipe", NULL);
   5533 
   5534     /* Create new output read handle and the input write handle. Set
   5535      * the inheritance properties to FALSE. Otherwise, the child inherits
   5536      * these handles; resulting in non-closeable handles to the pipes
   5537      * being created. */
   5538      fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
   5539                                 GetCurrentProcess(), &hChildStdinWrDup, 0,
   5540                                 FALSE,
   5541                                 DUPLICATE_SAME_ACCESS);
   5542      if (!fSuccess)
   5543          return win32_error("DuplicateHandle", NULL);
   5544 
   5545      /* Close the inheritable version of ChildStdin
   5546     that we're using. */
   5547      CloseHandle(hChildStdinWr);
   5548 
   5549      if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
   5550          return win32_error("CreatePipe", NULL);
   5551 
   5552      fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
   5553                                 GetCurrentProcess(), &hChildStdoutRdDup, 0,
   5554                                 FALSE, DUPLICATE_SAME_ACCESS);
   5555      if (!fSuccess)
   5556          return win32_error("DuplicateHandle", NULL);
   5557 
   5558      /* Close the inheritable version of ChildStdout
   5559         that we're using. */
   5560      CloseHandle(hChildStdoutRd);
   5561 
   5562      if (n != POPEN_4) {
   5563          if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
   5564              return win32_error("CreatePipe", NULL);
   5565          fSuccess = DuplicateHandle(GetCurrentProcess(),
   5566                                     hChildStderrRd,
   5567                                     GetCurrentProcess(),
   5568                                     &hChildStderrRdDup, 0,
   5569                                     FALSE, DUPLICATE_SAME_ACCESS);
   5570          if (!fSuccess)
   5571              return win32_error("DuplicateHandle", NULL);
   5572          /* Close the inheritable version of ChildStdErr that we're using. */
   5573          CloseHandle(hChildStderrRd);
   5574      }
   5575 
   5576      switch (n) {
   5577      case POPEN_1:
   5578          switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) {
   5579          case _O_WRONLY | _O_TEXT:
   5580              /* Case for writing to child Stdin in text mode. */
   5581              fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
   5582              f1 = _fdopen(fd1, "w");
   5583              f = PyFile_FromFile(f1, cmdstring, "w", _PyPclose);
   5584              PyFile_SetBufSize(f, 0);
   5585              /* We don't care about these pipes anymore, so close them. */
   5586              CloseHandle(hChildStdoutRdDup);
   5587              CloseHandle(hChildStderrRdDup);
   5588              break;
   5589 
   5590          case _O_RDONLY | _O_TEXT:
   5591              /* Case for reading from child Stdout in text mode. */
   5592              fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
   5593              f1 = _fdopen(fd1, "r");
   5594              f = PyFile_FromFile(f1, cmdstring, "r", _PyPclose);
   5595              PyFile_SetBufSize(f, 0);
   5596              /* We don't care about these pipes anymore, so close them. */
   5597              CloseHandle(hChildStdinWrDup);
   5598              CloseHandle(hChildStderrRdDup);
   5599              break;
   5600 
   5601          case _O_RDONLY | _O_BINARY:
   5602              /* Case for readinig from child Stdout in binary mode. */
   5603              fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
   5604              f1 = _fdopen(fd1, "rb");
   5605              f = PyFile_FromFile(f1, cmdstring, "rb", _PyPclose);
   5606              PyFile_SetBufSize(f, 0);
   5607              /* We don't care about these pipes anymore, so close them. */
   5608              CloseHandle(hChildStdinWrDup);
   5609              CloseHandle(hChildStderrRdDup);
   5610              break;
   5611 
   5612          case _O_WRONLY | _O_BINARY:
   5613              /* Case for writing to child Stdin in binary mode. */
   5614              fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
   5615              f1 = _fdopen(fd1, "wb");
   5616              f = PyFile_FromFile(f1, cmdstring, "wb", _PyPclose);
   5617              PyFile_SetBufSize(f, 0);
   5618              /* We don't care about these pipes anymore, so close them. */
   5619              CloseHandle(hChildStdoutRdDup);
   5620              CloseHandle(hChildStderrRdDup);
   5621              break;
   5622          }
   5623          file_count = 1;
   5624          break;
   5625 
   5626      case POPEN_2:
   5627      case POPEN_4:
   5628      {
   5629          char *m1, *m2;
   5630          PyObject *p1, *p2;
   5631 
   5632          if (mode & _O_TEXT) {
   5633              m1 = "r";
   5634              m2 = "w";
   5635          } else {
   5636              m1 = "rb";
   5637              m2 = "wb";
   5638          }
   5639 
   5640          fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
   5641          f1 = _fdopen(fd1, m2);
   5642          fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
   5643          f2 = _fdopen(fd2, m1);
   5644          p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
   5645          PyFile_SetBufSize(p1, 0);
   5646          p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
   5647          PyFile_SetBufSize(p2, 0);
   5648 
   5649          if (n != 4)
   5650              CloseHandle(hChildStderrRdDup);
   5651 
   5652          f = PyTuple_Pack(2,p1,p2);
   5653          Py_XDECREF(p1);
   5654          Py_XDECREF(p2);
   5655          file_count = 2;
   5656          break;
   5657      }
   5658 
   5659      case POPEN_3:
   5660      {
   5661          char *m1, *m2;
   5662          PyObject *p1, *p2, *p3;
   5663 
   5664          if (mode & _O_TEXT) {
   5665              m1 = "r";
   5666              m2 = "w";
   5667          } else {
   5668              m1 = "rb";
   5669              m2 = "wb";
   5670          }
   5671 
   5672          fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
   5673          f1 = _fdopen(fd1, m2);
   5674          fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
   5675          f2 = _fdopen(fd2, m1);
   5676          fd3 = _open_osfhandle((Py_intptr_t)hChildStderrRdDup, mode);
   5677          f3 = _fdopen(fd3, m1);
   5678          p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
   5679          p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
   5680          p3 = PyFile_FromFile(f3, cmdstring, m1, _PyPclose);
   5681          PyFile_SetBufSize(p1, 0);
   5682          PyFile_SetBufSize(p2, 0);
   5683          PyFile_SetBufSize(p3, 0);
   5684          f = PyTuple_Pack(3,p1,p2,p3);
   5685          Py_XDECREF(p1);
   5686          Py_XDECREF(p2);
   5687          Py_XDECREF(p3);
   5688          file_count = 3;
   5689          break;
   5690      }
   5691      }
   5692 
   5693      if (n == POPEN_4) {
   5694          if (!_PyPopenCreateProcess(cmdstring,
   5695                                     hChildStdinRd,
   5696                                     hChildStdoutWr,
   5697                                     hChildStdoutWr,
   5698                                     &hProcess))
   5699              return NULL;
   5700      }
   5701      else {
   5702          if (!_PyPopenCreateProcess(cmdstring,
   5703                                     hChildStdinRd,
   5704                                     hChildStdoutWr,
   5705                                     hChildStderrWr,
   5706                                     &hProcess))
   5707              return NULL;
   5708      }
   5709 
   5710      /*
   5711       * Insert the files we've created into the process dictionary
   5712       * all referencing the list with the process handle and the
   5713       * initial number of files (see description below in _PyPclose).
   5714       * Since if _PyPclose later tried to wait on a process when all
   5715       * handles weren't closed, it could create a deadlock with the
   5716       * child, we spend some energy here to try to ensure that we
   5717       * either insert all file handles into the dictionary or none
   5718       * at all.  It's a little clumsy with the various popen modes
   5719       * and variable number of files involved.
   5720       */
   5721      if (!_PyPopenProcs) {
   5722          _PyPopenProcs = PyDict_New();
   5723      }
   5724 
   5725      if (_PyPopenProcs) {
   5726          PyObject *procObj, *hProcessObj, *intObj, *fileObj[3];
   5727          int ins_rc[3];
   5728 
   5729          fileObj[0] = fileObj[1] = fileObj[2] = NULL;
   5730          ins_rc[0]  = ins_rc[1]  = ins_rc[2]  = 0;
   5731 
   5732          procObj = PyList_New(2);
   5733          hProcessObj = PyLong_FromVoidPtr(hProcess);
   5734          intObj = PyInt_FromLong(file_count);
   5735 
   5736          if (procObj && hProcessObj && intObj) {
   5737              PyList_SetItem(procObj,0,hProcessObj);
   5738              PyList_SetItem(procObj,1,intObj);
   5739 
   5740              fileObj[0] = PyLong_FromVoidPtr(f1);
   5741              if (fileObj[0]) {
   5742                 ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
   5743                                            fileObj[0],
   5744                                            procObj);
   5745              }
   5746              if (file_count >= 2) {
   5747                  fileObj[1] = PyLong_FromVoidPtr(f2);
   5748                  if (fileObj[1]) {
   5749                     ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
   5750                                                fileObj[1],
   5751                                                procObj);
   5752                  }
   5753              }
   5754              if (file_count >= 3) {
   5755                  fileObj[2] = PyLong_FromVoidPtr(f3);
   5756                  if (fileObj[2]) {
   5757                     ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
   5758                                                fileObj[2],
   5759                                                procObj);
   5760                  }
   5761              }
   5762 
   5763              if (ins_rc[0] < 0 || !fileObj[0] ||
   5764                  ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
   5765                  ins_rc[2] < 0 || (file_count > 2 && !fileObj[2])) {
   5766                  /* Something failed - remove any dictionary
   5767                   * entries that did make it.
   5768                   */
   5769                  if (!ins_rc[0] && fileObj[0]) {
   5770                      PyDict_DelItem(_PyPopenProcs,
   5771                                     fileObj[0]);
   5772                  }
   5773                  if (!ins_rc[1] && fileObj[1]) {
   5774                      PyDict_DelItem(_PyPopenProcs,
   5775                                     fileObj[1]);
   5776                  }
   5777                  if (!ins_rc[2] && fileObj[2]) {
   5778                      PyDict_DelItem(_PyPopenProcs,
   5779                                     fileObj[2]);
   5780                  }
   5781              }
   5782          }
   5783 
   5784          /*
   5785           * Clean up our localized references for the dictionary keys
   5786           * and value since PyDict_SetItem will Py_INCREF any copies
   5787           * that got placed in the dictionary.
   5788           */
   5789          Py_XDECREF(procObj);
   5790          Py_XDECREF(fileObj[0]);
   5791          Py_XDECREF(fileObj[1]);
   5792          Py_XDECREF(fileObj[2]);
   5793      }
   5794 
   5795      /* Child is launched. Close the parents copy of those pipe
   5796       * handles that only the child should have open.  You need to
   5797       * make sure that no handles to the write end of the output pipe
   5798       * are maintained in this process or else the pipe will not close
   5799       * when the child process exits and the ReadFile will hang. */
   5800 
   5801      if (!CloseHandle(hChildStdinRd))
   5802          return win32_error("CloseHandle", NULL);
   5803 
   5804      if (!CloseHandle(hChildStdoutWr))
   5805          return win32_error("CloseHandle", NULL);
   5806 
   5807      if ((n != 4) && (!CloseHandle(hChildStderrWr)))
   5808          return win32_error("CloseHandle", NULL);
   5809 
   5810      return f;
   5811 }
   5812 
   5813 /*
   5814  * Wrapper for fclose() to use for popen* files, so we can retrieve the
   5815  * exit code for the child process and return as a result of the close.
   5816  *
   5817  * This function uses the _PyPopenProcs dictionary in order to map the
   5818  * input file pointer to information about the process that was
   5819  * originally created by the popen* call that created the file pointer.
   5820  * The dictionary uses the file pointer as a key (with one entry
   5821  * inserted for each file returned by the original popen* call) and a
   5822  * single list object as the value for all files from a single call.
   5823  * The list object contains the Win32 process handle at [0], and a file
   5824  * count at [1], which is initialized to the total number of file
   5825  * handles using that list.
   5826  *
   5827  * This function closes whichever handle it is passed, and decrements
   5828  * the file count in the dictionary for the process handle pointed to
   5829  * by this file.  On the last close (when the file count reaches zero),
   5830  * this function will wait for the child process and then return its
   5831  * exit code as the result of the close() operation.  This permits the
   5832  * files to be closed in any order - it is always the close() of the
   5833  * final handle that will return the exit code.
   5834  *
   5835  * NOTE: This function is currently called with the GIL released.
   5836  * hence we use the GILState API to manage our state.
   5837  */
   5838 
   5839 static int _PyPclose(FILE *file)
   5840 {
   5841     int result;
   5842     DWORD exit_code;
   5843     HANDLE hProcess;
   5844     PyObject *procObj, *hProcessObj, *intObj, *fileObj;
   5845     long file_count;
   5846 #ifdef WITH_THREAD
   5847     PyGILState_STATE state;
   5848 #endif
   5849 
   5850     /* Close the file handle first, to ensure it can't block the
   5851      * child from exiting if it's the last handle.
   5852      */
   5853     result = fclose(file);
   5854 #ifdef WITH_THREAD
   5855     state = PyGILState_Ensure();
   5856 #endif
   5857     if (_PyPopenProcs) {
   5858         if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
   5859             (procObj = PyDict_GetItem(_PyPopenProcs,
   5860                                       fileObj)) != NULL &&
   5861             (hProcessObj = PyList_GetItem(procObj,0)) != NULL &&
   5862             (intObj = PyList_GetItem(procObj,1)) != NULL) {
   5863 
   5864             hProcess = PyLong_AsVoidPtr(hProcessObj);
   5865             file_count = PyInt_AsLong(intObj);
   5866 
   5867             if (file_count > 1) {
   5868                 /* Still other files referencing process */
   5869                 file_count--;
   5870                 PyList_SetItem(procObj,1,
   5871                                PyInt_FromLong(file_count));
   5872             } else {
   5873                 /* Last file for this process */
   5874                 if (result != EOF &&
   5875                     WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
   5876                     GetExitCodeProcess(hProcess, &exit_code)) {
   5877                     /* Possible truncation here in 16-bit environments, but
   5878                      * real exit codes are just the lower byte in any event.
   5879                      */
   5880                     result = exit_code;
   5881                 } else {
   5882                     /* Indicate failure - this will cause the file object
   5883                      * to raise an I/O error and translate the last Win32
   5884                      * error code from errno.  We do have a problem with
   5885                      * last errors that overlap the normal errno table,
   5886                      * but that's a consistent problem with the file object.
   5887                      */
   5888                     if (result != EOF) {
   5889                         /* If the error wasn't from the fclose(), then
   5890                          * set errno for the file object error handling.
   5891                          */
   5892                         errno = GetLastError();
   5893                     }
   5894                     result = -1;
   5895                 }
   5896 
   5897                 /* Free up the native handle at this point */
   5898                 CloseHandle(hProcess);
   5899             }
   5900 
   5901             /* Remove this file pointer from dictionary */
   5902             PyDict_DelItem(_PyPopenProcs, fileObj);
   5903 
   5904             if (PyDict_Size(_PyPopenProcs) == 0) {
   5905                 Py_DECREF(_PyPopenProcs);
   5906                 _PyPopenProcs = NULL;
   5907             }
   5908 
   5909         } /* if object retrieval ok */
   5910 
   5911         Py_XDECREF(fileObj);
   5912     } /* if _PyPopenProcs */
   5913 
   5914 #ifdef WITH_THREAD
   5915     PyGILState_Release(state);
   5916 #endif
   5917     return result;
   5918 }
   5919 
   5920 #else /* which OS? */
   5921 static PyObject *
   5922 posix_popen(PyObject *self, PyObject *args)
   5923 {
   5924     char *name;
   5925     char *mode = "r";
   5926     int bufsize = -1;
   5927     FILE *fp;
   5928     PyObject *f;
   5929     if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
   5930         return NULL;
   5931     /* Strip mode of binary or text modifiers */
   5932     if (strcmp(mode, "rb") == 0 || strcmp(mode, "rt") == 0)
   5933         mode = "r";
   5934     else if (strcmp(mode, "wb") == 0 || strcmp(mode, "wt") == 0)
   5935         mode = "w";
   5936     Py_BEGIN_ALLOW_THREADS
   5937     fp = popen(name, mode);
   5938     Py_END_ALLOW_THREADS
   5939     if (fp == NULL)
   5940         return posix_error();
   5941     f = PyFile_FromFile(fp, name, mode, pclose);
   5942     if (f != NULL)
   5943         PyFile_SetBufSize(f, bufsize);
   5944     return f;
   5945 }
   5946 
   5947 #endif /* PYOS_??? */
   5948 #endif /* HAVE_POPEN */
   5949 
   5950 
   5951 #ifdef HAVE_SETUID
   5952 PyDoc_STRVAR(posix_setuid__doc__,
   5953 "setuid(uid)\n\n\
   5954 Set the current process's user id.");
   5955 
   5956 static PyObject *
   5957 posix_setuid(PyObject *self, PyObject *args)
   5958 {
   5959     uid_t uid;
   5960     if (!PyArg_ParseTuple(args, "O&:setuid", _Py_Uid_Converter, &uid))
   5961         return NULL;
   5962     if (setuid(uid) < 0)
   5963         return posix_error();
   5964     Py_INCREF(Py_None);
   5965     return Py_None;
   5966 }
   5967 #endif /* HAVE_SETUID */
   5968 
   5969 
   5970 #ifdef HAVE_SETEUID
   5971 PyDoc_STRVAR(posix_seteuid__doc__,
   5972 "seteuid(uid)\n\n\
   5973 Set the current process's effective user id.");
   5974 
   5975 static PyObject *
   5976 posix_seteuid (PyObject *self, PyObject *args)
   5977 {
   5978     uid_t euid;
   5979     if (!PyArg_ParseTuple(args, "O&:seteuid", _Py_Uid_Converter, &euid))
   5980         return NULL;
   5981     if (seteuid(euid) < 0) {
   5982         return posix_error();
   5983     } else {
   5984         Py_INCREF(Py_None);
   5985         return Py_None;
   5986     }
   5987 }
   5988 #endif /* HAVE_SETEUID */
   5989 
   5990 #ifdef HAVE_SETEGID
   5991 PyDoc_STRVAR(posix_setegid__doc__,
   5992 "setegid(gid)\n\n\
   5993 Set the current process's effective group id.");
   5994 
   5995 static PyObject *
   5996 posix_setegid (PyObject *self, PyObject *args)
   5997 {
   5998     gid_t egid;
   5999     if (!PyArg_ParseTuple(args, "O&:setegid", _Py_Gid_Converter, &egid))
   6000         return NULL;
   6001     if (setegid(egid) < 0) {
   6002         return posix_error();
   6003     } else {
   6004         Py_INCREF(Py_None);
   6005         return Py_None;
   6006     }
   6007 }
   6008 #endif /* HAVE_SETEGID */
   6009 
   6010 #ifdef HAVE_SETREUID
   6011 PyDoc_STRVAR(posix_setreuid__doc__,
   6012 "setreuid(ruid, euid)\n\n\
   6013 Set the current process's real and effective user ids.");
   6014 
   6015 static PyObject *
   6016 posix_setreuid (PyObject *self, PyObject *args)
   6017 {
   6018     uid_t ruid, euid;
   6019     if (!PyArg_ParseTuple(args, "O&O&:setreuid",
   6020                           _Py_Uid_Converter, &ruid,
   6021                           _Py_Uid_Converter, &euid))
   6022         return NULL;
   6023     if (setreuid(ruid, euid) < 0) {
   6024         return posix_error();
   6025     } else {
   6026         Py_INCREF(Py_None);
   6027         return Py_None;
   6028     }
   6029 }
   6030 #endif /* HAVE_SETREUID */
   6031 
   6032 #ifdef HAVE_SETREGID
   6033 PyDoc_STRVAR(posix_setregid__doc__,
   6034 "setregid(rgid, egid)\n\n\
   6035 Set the current process's real and effective group ids.");
   6036 
   6037 static PyObject *
   6038 posix_setregid (PyObject *self, PyObject *args)
   6039 {
   6040     gid_t rgid, egid;
   6041     if (!PyArg_ParseTuple(args, "O&O&:setregid",
   6042                           _Py_Gid_Converter, &rgid,
   6043                           _Py_Gid_Converter, &egid))
   6044         return NULL;
   6045     if (setregid(rgid, egid) < 0) {
   6046         return posix_error();
   6047     } else {
   6048         Py_INCREF(Py_None);
   6049         return Py_None;
   6050     }
   6051 }
   6052 #endif /* HAVE_SETREGID */
   6053 
   6054 #ifdef HAVE_SETGID
   6055 PyDoc_STRVAR(posix_setgid__doc__,
   6056 "setgid(gid)\n\n\
   6057 Set the current process's group id.");
   6058 
   6059 static PyObject *
   6060 posix_setgid(PyObject *self, PyObject *args)
   6061 {
   6062     gid_t gid;
   6063     if (!PyArg_ParseTuple(args, "O&:setgid", _Py_Gid_Converter, &gid))
   6064         return NULL;
   6065     if (setgid(gid) < 0)
   6066         return posix_error();
   6067     Py_INCREF(Py_None);
   6068     return Py_None;
   6069 }
   6070 #endif /* HAVE_SETGID */
   6071 
   6072 #ifdef HAVE_SETGROUPS
   6073 PyDoc_STRVAR(posix_setgroups__doc__,
   6074 "setgroups(list)\n\n\
   6075 Set the groups of the current process to list.");
   6076 
   6077 static PyObject *
   6078 posix_setgroups(PyObject *self, PyObject *groups)
   6079 {
   6080     int i, len;
   6081     gid_t grouplist[MAX_GROUPS];
   6082 
   6083     if (!PySequence_Check(groups)) {
   6084         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
   6085         return NULL;
   6086     }
   6087     len = PySequence_Size(groups);
   6088     if (len > MAX_GROUPS) {
   6089         PyErr_SetString(PyExc_ValueError, "too many groups");
   6090         return NULL;
   6091     }
   6092     for(i = 0; i < len; i++) {
   6093         PyObject *elem;
   6094         elem = PySequence_GetItem(groups, i);
   6095         if (!elem)
   6096             return NULL;
   6097         if (!PyInt_Check(elem) && !PyLong_Check(elem)) {
   6098             PyErr_SetString(PyExc_TypeError,
   6099                             "groups must be integers");
   6100             Py_DECREF(elem);
   6101             return NULL;
   6102         } else {
   6103             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
   6104                 Py_DECREF(elem);
   6105                 return NULL;
   6106             }
   6107         }
   6108         Py_DECREF(elem);
   6109     }
   6110 
   6111     if (setgroups(len, grouplist) < 0)
   6112         return posix_error();
   6113     Py_INCREF(Py_None);
   6114     return Py_None;
   6115 }
   6116 #endif /* HAVE_SETGROUPS */
   6117 
   6118 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
   6119 static PyObject *
   6120 wait_helper(pid_t pid, int status, struct rusage *ru)
   6121 {
   6122     PyObject *result;
   6123     static PyObject *struct_rusage;
   6124 
   6125     if (pid == -1)
   6126         return posix_error();
   6127 
   6128     if (struct_rusage == NULL) {
   6129         PyObject *m = PyImport_ImportModuleNoBlock("resource");
   6130         if (m == NULL)
   6131             return NULL;
   6132         struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
   6133         Py_DECREF(m);
   6134         if (struct_rusage == NULL)
   6135             return NULL;
   6136     }
   6137 
   6138     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
   6139     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
   6140     if (!result)
   6141         return NULL;
   6142 
   6143 #ifndef doubletime
   6144 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
   6145 #endif
   6146 
   6147     PyStructSequence_SET_ITEM(result, 0,
   6148                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
   6149     PyStructSequence_SET_ITEM(result, 1,
   6150                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
   6151 #define SET_INT(result, index, value)\
   6152         PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value))
   6153     SET_INT(result, 2, ru->ru_maxrss);
   6154     SET_INT(result, 3, ru->ru_ixrss);
   6155     SET_INT(result, 4, ru->ru_idrss);
   6156     SET_INT(result, 5, ru->ru_isrss);
   6157     SET_INT(result, 6, ru->ru_minflt);
   6158     SET_INT(result, 7, ru->ru_majflt);
   6159     SET_INT(result, 8, ru->ru_nswap);
   6160     SET_INT(result, 9, ru->ru_inblock);
   6161     SET_INT(result, 10, ru->ru_oublock);
   6162     SET_INT(result, 11, ru->ru_msgsnd);
   6163     SET_INT(result, 12, ru->ru_msgrcv);
   6164     SET_INT(result, 13, ru->ru_nsignals);
   6165     SET_INT(result, 14, ru->ru_nvcsw);
   6166     SET_INT(result, 15, ru->ru_nivcsw);
   6167 #undef SET_INT
   6168 
   6169     if (PyErr_Occurred()) {
   6170         Py_DECREF(result);
   6171         return NULL;
   6172     }
   6173 
   6174     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
   6175 }
   6176 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
   6177 
   6178 #ifdef HAVE_WAIT3
   6179 PyDoc_STRVAR(posix_wait3__doc__,
   6180 "wait3(options) -> (pid, status, rusage)\n\n\
   6181 Wait for completion of a child process.");
   6182 
   6183 static PyObject *
   6184 posix_wait3(PyObject *self, PyObject *args)
   6185 {
   6186     pid_t pid;
   6187     int options;
   6188     struct rusage ru;
   6189     WAIT_TYPE status;
   6190     WAIT_STATUS_INT(status) = 0;
   6191 
   6192     if (!PyArg_ParseTuple(args, "i:wait3", &options))
   6193         return NULL;
   6194 
   6195     Py_BEGIN_ALLOW_THREADS
   6196     pid = wait3(&status, options, &ru);
   6197     Py_END_ALLOW_THREADS
   6198 
   6199     return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
   6200 }
   6201 #endif /* HAVE_WAIT3 */
   6202 
   6203 #ifdef HAVE_WAIT4
   6204 PyDoc_STRVAR(posix_wait4__doc__,
   6205 "wait4(pid, options) -> (pid, status, rusage)\n\n\
   6206 Wait for completion of a given child process.");
   6207 
   6208 static PyObject *
   6209 posix_wait4(PyObject *self, PyObject *args)
   6210 {
   6211     pid_t pid;
   6212     int options;
   6213     struct rusage ru;
   6214     WAIT_TYPE status;
   6215     WAIT_STATUS_INT(status) = 0;
   6216 
   6217     if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options))
   6218         return NULL;
   6219 
   6220     Py_BEGIN_ALLOW_THREADS
   6221     pid = wait4(pid, &status, options, &ru);
   6222     Py_END_ALLOW_THREADS
   6223 
   6224     return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
   6225 }
   6226 #endif /* HAVE_WAIT4 */
   6227 
   6228 #ifdef HAVE_WAITPID
   6229 PyDoc_STRVAR(posix_waitpid__doc__,
   6230 "waitpid(pid, options) -> (pid, status)\n\n\
   6231 Wait for completion of a given child process.");
   6232 
   6233 static PyObject *
   6234 posix_waitpid(PyObject *self, PyObject *args)
   6235 {
   6236     pid_t pid;
   6237     int options;
   6238     WAIT_TYPE status;
   6239     WAIT_STATUS_INT(status) = 0;
   6240 
   6241     if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
   6242         return NULL;
   6243     Py_BEGIN_ALLOW_THREADS
   6244     pid = waitpid(pid, &status, options);
   6245     Py_END_ALLOW_THREADS
   6246     if (pid == -1)
   6247         return posix_error();
   6248 
   6249     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
   6250 }
   6251 
   6252 #elif defined(HAVE_CWAIT)
   6253 
   6254 /* MS C has a variant of waitpid() that's usable for most purposes. */
   6255 PyDoc_STRVAR(posix_waitpid__doc__,
   6256 "waitpid(pid, options) -> (pid, status << 8)\n\n"
   6257 "Wait for completion of a given process.  options is ignored on Windows.");
   6258 
   6259 static PyObject *
   6260 posix_waitpid(PyObject *self, PyObject *args)
   6261 {
   6262     Py_intptr_t pid;
   6263     int status, options;
   6264 
   6265     if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
   6266         return NULL;
   6267     Py_BEGIN_ALLOW_THREADS
   6268     pid = _cwait(&status, pid, options);
   6269     Py_END_ALLOW_THREADS
   6270     if (pid == -1)
   6271         return posix_error();
   6272 
   6273     /* shift the status left a byte so this is more like the POSIX waitpid */
   6274     return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
   6275 }
   6276 #endif /* HAVE_WAITPID || HAVE_CWAIT */
   6277 
   6278 #ifdef HAVE_WAIT
   6279 PyDoc_STRVAR(posix_wait__doc__,
   6280 "wait() -> (pid, status)\n\n\
   6281 Wait for completion of a child process.");
   6282 
   6283 static PyObject *
   6284 posix_wait(PyObject *self, PyObject *noargs)
   6285 {
   6286     pid_t pid;
   6287     WAIT_TYPE status;
   6288     WAIT_STATUS_INT(status) = 0;
   6289 
   6290     Py_BEGIN_ALLOW_THREADS
   6291     pid = wait(&status);
   6292     Py_END_ALLOW_THREADS
   6293     if (pid == -1)
   6294         return posix_error();
   6295 
   6296     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
   6297 }
   6298 #endif
   6299 
   6300 
   6301 PyDoc_STRVAR(posix_lstat__doc__,
   6302 "lstat(path) -> stat result\n\n\
   6303 Like stat(path), but do not follow symbolic links.");
   6304 
   6305 static PyObject *
   6306 posix_lstat(PyObject *self, PyObject *args)
   6307 {
   6308 #ifdef HAVE_LSTAT
   6309     return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL);
   6310 #else /* !HAVE_LSTAT */
   6311 #ifdef MS_WINDOWS
   6312     return posix_do_stat(self, args, "et:lstat", STAT, "u:lstat", win32_wstat);
   6313 #else
   6314     return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL);
   6315 #endif
   6316 #endif /* !HAVE_LSTAT */
   6317 }
   6318 
   6319 
   6320 #ifdef HAVE_READLINK
   6321 PyDoc_STRVAR(posix_readlink__doc__,
   6322 "readlink(path) -> path\n\n\
   6323 Return a string representing the path to which the symbolic link points.");
   6324 
   6325 static PyObject *
   6326 posix_readlink(PyObject *self, PyObject *args)
   6327 {
   6328     PyObject* v;
   6329     char buf[MAXPATHLEN];
   6330     char *path;
   6331     int n;
   6332 #ifdef Py_USING_UNICODE
   6333     int arg_is_unicode = 0;
   6334 #endif
   6335 
   6336     if (!PyArg_ParseTuple(args, "et:readlink",
   6337                           Py_FileSystemDefaultEncoding, &path))
   6338         return NULL;
   6339 #ifdef Py_USING_UNICODE
   6340     v = PySequence_GetItem(args, 0);
   6341     if (v == NULL) {
   6342         PyMem_Free(path);
   6343         return NULL;
   6344     }
   6345 
   6346     if (PyUnicode_Check(v)) {
   6347         arg_is_unicode = 1;
   6348     }
   6349     Py_DECREF(v);
   6350 #endif
   6351 
   6352     Py_BEGIN_ALLOW_THREADS
   6353     n = readlink(path, buf, (int) sizeof buf);
   6354     Py_END_ALLOW_THREADS
   6355     if (n < 0)
   6356         return posix_error_with_allocated_filename(path);
   6357 
   6358     PyMem_Free(path);
   6359     v = PyString_FromStringAndSize(buf, n);
   6360 #ifdef Py_USING_UNICODE
   6361     if (arg_is_unicode) {
   6362         PyObject *w;
   6363 
   6364         w = PyUnicode_FromEncodedObject(v,
   6365                                         Py_FileSystemDefaultEncoding,
   6366                                         "strict");
   6367         if (w != NULL) {
   6368             Py_DECREF(v);
   6369             v = w;
   6370         }
   6371         else {
   6372             /* fall back to the original byte string, as
   6373                discussed in patch #683592 */
   6374             PyErr_Clear();
   6375         }
   6376     }
   6377 #endif
   6378     return v;
   6379 }
   6380 #endif /* HAVE_READLINK */
   6381 
   6382 
   6383 #ifdef HAVE_SYMLINK
   6384 PyDoc_STRVAR(posix_symlink__doc__,
   6385 "symlink(src, dst)\n\n\
   6386 Create a symbolic link pointing to src named dst.");
   6387 
   6388 static PyObject *
   6389 posix_symlink(PyObject *self, PyObject *args)
   6390 {
   6391     return posix_2str(args, "etet:symlink", symlink);
   6392 }
   6393 #endif /* HAVE_SYMLINK */
   6394 
   6395 
   6396 #ifdef HAVE_TIMES
   6397 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
   6398 static long
   6399 system_uptime(void)
   6400 {
   6401     ULONG     value = 0;
   6402 
   6403     Py_BEGIN_ALLOW_THREADS
   6404     DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
   6405     Py_END_ALLOW_THREADS
   6406 
   6407     return value;
   6408 }
   6409 
   6410 static PyObject *
   6411 posix_times(PyObject *self, PyObject *noargs)
   6412 {
   6413     /* Currently Only Uptime is Provided -- Others Later */
   6414     return Py_BuildValue("ddddd",
   6415                          (double)0 /* t.tms_utime / HZ */,
   6416                          (double)0 /* t.tms_stime / HZ */,
   6417                          (double)0 /* t.tms_cutime / HZ */,
   6418                          (double)0 /* t.tms_cstime / HZ */,
   6419                          (double)system_uptime() / 1000);
   6420 }
   6421 #else /* not OS2 */
   6422 #define NEED_TICKS_PER_SECOND
   6423 static long ticks_per_second = -1;
   6424 static PyObject *
   6425 posix_times(PyObject *self, PyObject *noargs)
   6426 {
   6427     struct tms t;
   6428     clock_t c;
   6429     errno = 0;
   6430     c = times(&t);
   6431     if (c == (clock_t) -1)
   6432         return posix_error();
   6433     return Py_BuildValue("ddddd",
   6434                          (double)t.tms_utime / ticks_per_second,
   6435                          (double)t.tms_stime / ticks_per_second,
   6436                          (double)t.tms_cutime / ticks_per_second,
   6437                          (double)t.tms_cstime / ticks_per_second,
   6438                          (double)c / ticks_per_second);
   6439 }
   6440 #endif /* not OS2 */
   6441 #endif /* HAVE_TIMES */
   6442 
   6443 
   6444 #ifdef MS_WINDOWS
   6445 #define HAVE_TIMES      /* so the method table will pick it up */
   6446 static PyObject *
   6447 posix_times(PyObject *self, PyObject *noargs)
   6448 {
   6449     FILETIME create, exit, kernel, user;
   6450     HANDLE hProc;
   6451     hProc = GetCurrentProcess();
   6452     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
   6453     /* The fields of a FILETIME structure are the hi and lo part
   6454        of a 64-bit value expressed in 100 nanosecond units.
   6455        1e7 is one second in such units; 1e-7 the inverse.
   6456        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
   6457     */
   6458     return Py_BuildValue(
   6459         "ddddd",
   6460         (double)(user.dwHighDateTime*429.4967296 +
   6461                  user.dwLowDateTime*1e-7),
   6462         (double)(kernel.dwHighDateTime*429.4967296 +
   6463                  kernel.dwLowDateTime*1e-7),
   6464         (double)0,
   6465         (double)0,
   6466         (double)0);
   6467 }
   6468 #endif /* MS_WINDOWS */
   6469 
   6470 #ifdef HAVE_TIMES
   6471 PyDoc_STRVAR(posix_times__doc__,
   6472 "times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
   6473 Return a tuple of floating point numbers indicating process times.");
   6474 #endif
   6475 
   6476 
   6477 #ifdef HAVE_GETSID
   6478 PyDoc_STRVAR(posix_getsid__doc__,
   6479 "getsid(pid) -> sid\n\n\
   6480 Call the system call getsid().");
   6481 
   6482 static PyObject *
   6483 posix_getsid(PyObject *self, PyObject *args)
   6484 {
   6485     pid_t pid;
   6486     int sid;
   6487     if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid))
   6488         return NULL;
   6489     sid = getsid(pid);
   6490     if (sid < 0)
   6491         return posix_error();
   6492     return PyInt_FromLong((long)sid);
   6493 }
   6494 #endif /* HAVE_GETSID */
   6495 
   6496 
   6497 #ifdef HAVE_SETSID
   6498 PyDoc_STRVAR(posix_setsid__doc__,
   6499 "setsid()\n\n\
   6500 Call the system call setsid().");
   6501 
   6502 static PyObject *
   6503 posix_setsid(PyObject *self, PyObject *noargs)
   6504 {
   6505     if (setsid() < 0)
   6506         return posix_error();
   6507     Py_INCREF(Py_None);
   6508     return Py_None;
   6509 }
   6510 #endif /* HAVE_SETSID */
   6511 
   6512 #ifdef HAVE_SETPGID
   6513 PyDoc_STRVAR(posix_setpgid__doc__,
   6514 "setpgid(pid, pgrp)\n\n\
   6515 Call the system call setpgid().");
   6516 
   6517 static PyObject *
   6518 posix_setpgid(PyObject *self, PyObject *args)
   6519 {
   6520     pid_t pid;
   6521     int pgrp;
   6522     if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp))
   6523         return NULL;
   6524     if (setpgid(pid, pgrp) < 0)
   6525         return posix_error();
   6526     Py_INCREF(Py_None);
   6527     return Py_None;
   6528 }
   6529 #endif /* HAVE_SETPGID */
   6530 
   6531 
   6532 #ifdef HAVE_TCGETPGRP
   6533 PyDoc_STRVAR(posix_tcgetpgrp__doc__,
   6534 "tcgetpgrp(fd) -> pgid\n\n\
   6535 Return the process group associated with the terminal given by a fd.");
   6536 
   6537 static PyObject *
   6538 posix_tcgetpgrp(PyObject *self, PyObject *args)
   6539 {
   6540     int fd;
   6541     pid_t pgid;
   6542     if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
   6543         return NULL;
   6544     pgid = tcgetpgrp(fd);
   6545     if (pgid < 0)
   6546         return posix_error();
   6547     return PyLong_FromPid(pgid);
   6548 }
   6549 #endif /* HAVE_TCGETPGRP */
   6550 
   6551 
   6552 #ifdef HAVE_TCSETPGRP
   6553 PyDoc_STRVAR(posix_tcsetpgrp__doc__,
   6554 "tcsetpgrp(fd, pgid)\n\n\
   6555 Set the process group associated with the terminal given by a fd.");
   6556 
   6557 static PyObject *
   6558 posix_tcsetpgrp(PyObject *self, PyObject *args)
   6559 {
   6560     int fd;
   6561     pid_t pgid;
   6562     if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid))
   6563         return NULL;
   6564     if (tcsetpgrp(fd, pgid) < 0)
   6565         return posix_error();
   6566     Py_INCREF(Py_None);
   6567     return Py_None;
   6568 }
   6569 #endif /* HAVE_TCSETPGRP */
   6570 
   6571 /* Functions acting on file descriptors */
   6572 
   6573 PyDoc_STRVAR(posix_open__doc__,
   6574 "open(filename, flag [, mode=0777]) -> fd\n\n\
   6575 Open a file (for low level IO).");
   6576 
   6577 static PyObject *
   6578 posix_open(PyObject *self, PyObject *args)
   6579 {
   6580     char *file = NULL;
   6581     int flag;
   6582     int mode = 0777;
   6583     int fd;
   6584 
   6585 #ifdef MS_WINDOWS
   6586     Py_UNICODE *wpath;
   6587     if (PyArg_ParseTuple(args, "ui|i:mkdir", &wpath, &flag, &mode)) {
   6588         Py_BEGIN_ALLOW_THREADS
   6589         fd = _wopen(wpath, flag, mode);
   6590         Py_END_ALLOW_THREADS
   6591         if (fd < 0)
   6592             return posix_error();
   6593         return PyInt_FromLong((long)fd);
   6594     }
   6595     /* Drop the argument parsing error as narrow strings
   6596        are also valid. */
   6597     PyErr_Clear();
   6598 #endif
   6599 
   6600     if (!PyArg_ParseTuple(args, "eti|i",
   6601                           Py_FileSystemDefaultEncoding, &file,
   6602                           &flag, &mode))
   6603         return NULL;
   6604 
   6605     Py_BEGIN_ALLOW_THREADS
   6606     fd = open(file, flag, mode);
   6607     Py_END_ALLOW_THREADS
   6608     if (fd < 0)
   6609         return posix_error_with_allocated_filename(file);
   6610     PyMem_Free(file);
   6611     return PyInt_FromLong((long)fd);
   6612 }
   6613 
   6614 
   6615 PyDoc_STRVAR(posix_close__doc__,
   6616 "close(fd)\n\n\
   6617 Close a file descriptor (for low level IO).");
   6618 
   6619 /*
   6620 The underscore at end of function name avoids a name clash with the libc
   6621 function posix_close.
   6622 */
   6623 static PyObject *
   6624 posix_close_(PyObject *self, PyObject *args)
   6625 {
   6626     int fd, res;
   6627     if (!PyArg_ParseTuple(args, "i:close", &fd))
   6628         return NULL;
   6629     if (!_PyVerify_fd(fd))
   6630         return posix_error();
   6631     Py_BEGIN_ALLOW_THREADS
   6632     res = close(fd);
   6633     Py_END_ALLOW_THREADS
   6634     if (res < 0)
   6635         return posix_error();
   6636     Py_INCREF(Py_None);
   6637     return Py_None;
   6638 }
   6639 
   6640 
   6641 PyDoc_STRVAR(posix_closerange__doc__,
   6642 "closerange(fd_low, fd_high)\n\n\
   6643 Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
   6644 
   6645 static PyObject *
   6646 posix_closerange(PyObject *self, PyObject *args)
   6647 {
   6648     int fd_from, fd_to, i;
   6649     if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
   6650         return NULL;
   6651     Py_BEGIN_ALLOW_THREADS
   6652     for (i = fd_from; i < fd_to; i++)
   6653         if (_PyVerify_fd(i))
   6654             close(i);
   6655     Py_END_ALLOW_THREADS
   6656     Py_RETURN_NONE;
   6657 }
   6658 
   6659 
   6660 PyDoc_STRVAR(posix_dup__doc__,
   6661 "dup(fd) -> fd2\n\n\
   6662 Return a duplicate of a file descriptor.");
   6663 
   6664 static PyObject *
   6665 posix_dup(PyObject *self, PyObject *args)
   6666 {
   6667     int fd;
   6668     if (!PyArg_ParseTuple(args, "i:dup", &fd))
   6669         return NULL;
   6670     if (!_PyVerify_fd(fd))
   6671         return posix_error();
   6672     Py_BEGIN_ALLOW_THREADS
   6673     fd = dup(fd);
   6674     Py_END_ALLOW_THREADS
   6675     if (fd < 0)
   6676         return posix_error();
   6677     return PyInt_FromLong((long)fd);
   6678 }
   6679 
   6680 
   6681 PyDoc_STRVAR(posix_dup2__doc__,
   6682 "dup2(old_fd, new_fd)\n\n\
   6683 Duplicate file descriptor.");
   6684 
   6685 static PyObject *
   6686 posix_dup2(PyObject *self, PyObject *args)
   6687 {
   6688     int fd, fd2, res;
   6689     if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
   6690         return NULL;
   6691     if (!_PyVerify_fd_dup2(fd, fd2))
   6692         return posix_error();
   6693     Py_BEGIN_ALLOW_THREADS
   6694     res = dup2(fd, fd2);
   6695     Py_END_ALLOW_THREADS
   6696     if (res < 0)
   6697         return posix_error();
   6698     Py_INCREF(Py_None);
   6699     return Py_None;
   6700 }
   6701 
   6702 
   6703 PyDoc_STRVAR(posix_lseek__doc__,
   6704 "lseek(fd, pos, how) -> newpos\n\n\
   6705 Set the current position of a file descriptor.\n\
   6706 Return the new cursor position in bytes, starting from the beginning.");
   6707 
   6708 static PyObject *
   6709 posix_lseek(PyObject *self, PyObject *args)
   6710 {
   6711     int fd, how;
   6712 #if defined(MS_WIN64) || defined(MS_WINDOWS)
   6713     PY_LONG_LONG pos, res;
   6714 #else
   6715     off_t pos, res;
   6716 #endif
   6717     PyObject *posobj;
   6718     if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
   6719         return NULL;
   6720 #ifdef SEEK_SET
   6721     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
   6722     switch (how) {
   6723     case 0: how = SEEK_SET; break;
   6724     case 1: how = SEEK_CUR; break;
   6725     case 2: how = SEEK_END; break;
   6726     }
   6727 #endif /* SEEK_END */
   6728 
   6729 #if !defined(HAVE_LARGEFILE_SUPPORT)
   6730     pos = PyInt_AsLong(posobj);
   6731 #else
   6732     pos = PyLong_Check(posobj) ?
   6733         PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj);
   6734 #endif
   6735     if (PyErr_Occurred())
   6736         return NULL;
   6737 
   6738     if (!_PyVerify_fd(fd))
   6739         return posix_error();
   6740     Py_BEGIN_ALLOW_THREADS
   6741 #if defined(MS_WIN64) || defined(MS_WINDOWS)
   6742     res = _lseeki64(fd, pos, how);
   6743 #else
   6744     res = lseek(fd, pos, how);
   6745 #endif
   6746     Py_END_ALLOW_THREADS
   6747     if (res < 0)
   6748         return posix_error();
   6749 
   6750 #if !defined(HAVE_LARGEFILE_SUPPORT)
   6751     return PyInt_FromLong(res);
   6752 #else
   6753     return PyLong_FromLongLong(res);
   6754 #endif
   6755 }
   6756 
   6757 
   6758 PyDoc_STRVAR(posix_read__doc__,
   6759 "read(fd, buffersize) -> string\n\n\
   6760 Read a file descriptor.");
   6761 
   6762 static PyObject *
   6763 posix_read(PyObject *self, PyObject *args)
   6764 {
   6765     int fd, size, n;
   6766     PyObject *buffer;
   6767     if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
   6768         return NULL;
   6769     if (size < 0) {
   6770         errno = EINVAL;
   6771         return posix_error();
   6772     }
   6773     buffer = PyString_FromStringAndSize((char *)NULL, size);
   6774     if (buffer == NULL)
   6775         return NULL;
   6776     if (!_PyVerify_fd(fd)) {
   6777         Py_DECREF(buffer);
   6778         return posix_error();
   6779     }
   6780     Py_BEGIN_ALLOW_THREADS
   6781     n = read(fd, PyString_AsString(buffer), size);
   6782     Py_END_ALLOW_THREADS
   6783     if (n < 0) {
   6784         Py_DECREF(buffer);
   6785         return posix_error();
   6786     }
   6787     if (n != size)
   6788         _PyString_Resize(&buffer, n);
   6789     return buffer;
   6790 }
   6791 
   6792 
   6793 PyDoc_STRVAR(posix_write__doc__,
   6794 "write(fd, string) -> byteswritten\n\n\
   6795 Write a string to a file descriptor.");
   6796 
   6797 static PyObject *
   6798 posix_write(PyObject *self, PyObject *args)
   6799 {
   6800     Py_buffer pbuf;
   6801     int fd;
   6802     Py_ssize_t size, len;
   6803 
   6804     if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
   6805         return NULL;
   6806     if (!_PyVerify_fd(fd)) {
   6807         PyBuffer_Release(&pbuf);
   6808         return posix_error();
   6809     }
   6810     len = pbuf.len;
   6811     Py_BEGIN_ALLOW_THREADS
   6812 #if defined(MS_WIN64) || defined(MS_WINDOWS)
   6813     if (len > INT_MAX)
   6814         len = INT_MAX;
   6815     size = write(fd, pbuf.buf, (int)len);
   6816 #else
   6817     size = write(fd, pbuf.buf, len);
   6818 #endif
   6819     Py_END_ALLOW_THREADS
   6820     PyBuffer_Release(&pbuf);
   6821     if (size < 0)
   6822         return posix_error();
   6823     return PyInt_FromSsize_t(size);
   6824 }
   6825 
   6826 
   6827 PyDoc_STRVAR(posix_fstat__doc__,
   6828 "fstat(fd) -> stat result\n\n\
   6829 Like stat(), but for an open file descriptor.");
   6830 
   6831 static PyObject *
   6832 posix_fstat(PyObject *self, PyObject *args)
   6833 {
   6834     int fd;
   6835     STRUCT_STAT st;
   6836     int res;
   6837     if (!PyArg_ParseTuple(args, "i:fstat", &fd))
   6838         return NULL;
   6839 #ifdef __VMS
   6840     /* on OpenVMS we must ensure that all bytes are written to the file */
   6841     fsync(fd);
   6842 #endif
   6843     if (!_PyVerify_fd(fd))
   6844         return posix_error();
   6845     Py_BEGIN_ALLOW_THREADS
   6846     res = FSTAT(fd, &st);
   6847     Py_END_ALLOW_THREADS
   6848     if (res != 0) {
   6849 #ifdef MS_WINDOWS
   6850         return win32_error("fstat", NULL);
   6851 #else
   6852         return posix_error();
   6853 #endif
   6854     }
   6855 
   6856     return _pystat_fromstructstat(&st);
   6857 }
   6858 
   6859 
   6860 PyDoc_STRVAR(posix_fdopen__doc__,
   6861 "fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
   6862 Return an open file object connected to a file descriptor.");
   6863 
   6864 static PyObject *
   6865 posix_fdopen(PyObject *self, PyObject *args)
   6866 {
   6867     int fd;
   6868     char *orgmode = "r";
   6869     int bufsize = -1;
   6870     FILE *fp;
   6871     PyObject *f;
   6872     char *mode;
   6873     if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize))
   6874         return NULL;
   6875 
   6876     /* Sanitize mode.  See fileobject.c */
   6877     mode = PyMem_MALLOC(strlen(orgmode)+3);
   6878     if (!mode) {
   6879         PyErr_NoMemory();
   6880         return NULL;
   6881     }
   6882     strcpy(mode, orgmode);
   6883     if (_PyFile_SanitizeMode(mode)) {
   6884         PyMem_FREE(mode);
   6885         return NULL;
   6886     }
   6887     if (!_PyVerify_fd(fd)) {
   6888         PyMem_FREE(mode);
   6889         return posix_error();
   6890     }
   6891 #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
   6892     {
   6893         struct stat buf;
   6894         const char *msg;
   6895         PyObject *exc;
   6896         if (fstat(fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
   6897             PyMem_FREE(mode);
   6898             msg = strerror(EISDIR);
   6899             exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
   6900                                         EISDIR, msg, "<fdopen>");
   6901             if (exc) {
   6902                 PyErr_SetObject(PyExc_IOError, exc);
   6903                 Py_DECREF(exc);
   6904             }
   6905             return NULL;
   6906         }
   6907     }
   6908 #endif
   6909     /* The dummy filename used here must be kept in sync with the value
   6910        tested against in gzip.GzipFile.__init__() - see issue #13781. */
   6911     f = PyFile_FromFile(NULL, "<fdopen>", orgmode, fclose);
   6912     if (f == NULL) {
   6913         PyMem_FREE(mode);
   6914         return NULL;
   6915     }
   6916     Py_BEGIN_ALLOW_THREADS
   6917 #if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H)
   6918     if (mode[0] == 'a') {
   6919         /* try to make sure the O_APPEND flag is set */
   6920         int flags;
   6921         flags = fcntl(fd, F_GETFL);
   6922         if (flags != -1)
   6923             fcntl(fd, F_SETFL, flags | O_APPEND);
   6924         fp = fdopen(fd, mode);
   6925         if (fp == NULL && flags != -1)
   6926             /* restore old mode if fdopen failed */
   6927             fcntl(fd, F_SETFL, flags);
   6928     } else {
   6929         fp = fdopen(fd, mode);
   6930     }
   6931 #else
   6932     fp = fdopen(fd, mode);
   6933 #endif
   6934     Py_END_ALLOW_THREADS
   6935     PyMem_FREE(mode);
   6936     if (fp == NULL) {
   6937         Py_DECREF(f);
   6938         return posix_error();
   6939     }
   6940     /* We now know we will succeed, so initialize the file object. */
   6941     ((PyFileObject *)f)->f_fp = fp;
   6942     PyFile_SetBufSize(f, bufsize);
   6943     return f;
   6944 }
   6945 
   6946 PyDoc_STRVAR(posix_isatty__doc__,
   6947 "isatty(fd) -> bool\n\n\
   6948 Return True if the file descriptor 'fd' is an open file descriptor\n\
   6949 connected to the slave end of a terminal.");
   6950 
   6951 static PyObject *
   6952 posix_isatty(PyObject *self, PyObject *args)
   6953 {
   6954     int fd;
   6955     if (!PyArg_ParseTuple(args, "i:isatty", &fd))
   6956         return NULL;
   6957     if (!_PyVerify_fd(fd))
   6958         return PyBool_FromLong(0);
   6959     return PyBool_FromLong(isatty(fd));
   6960 }
   6961 
   6962 #ifdef HAVE_PIPE
   6963 PyDoc_STRVAR(posix_pipe__doc__,
   6964 "pipe() -> (read_end, write_end)\n\n\
   6965 Create a pipe.");
   6966 
   6967 static PyObject *
   6968 posix_pipe(PyObject *self, PyObject *noargs)
   6969 {
   6970 #if defined(PYOS_OS2)
   6971     HFILE read, write;
   6972     APIRET rc;
   6973 
   6974     Py_BEGIN_ALLOW_THREADS
   6975     rc = DosCreatePipe( &read, &write, 4096);
   6976     Py_END_ALLOW_THREADS
   6977     if (rc != NO_ERROR)
   6978         return os2_error(rc);
   6979 
   6980     return Py_BuildValue("(ii)", read, write);
   6981 #else
   6982 #if !defined(MS_WINDOWS)
   6983     int fds[2];
   6984     int res;
   6985     Py_BEGIN_ALLOW_THREADS
   6986     res = pipe(fds);
   6987     Py_END_ALLOW_THREADS
   6988     if (res != 0)
   6989         return posix_error();
   6990     return Py_BuildValue("(ii)", fds[0], fds[1]);
   6991 #else /* MS_WINDOWS */
   6992     HANDLE read, write;
   6993     int read_fd, write_fd;
   6994     BOOL ok;
   6995     Py_BEGIN_ALLOW_THREADS
   6996     ok = CreatePipe(&read, &write, NULL, 0);
   6997     Py_END_ALLOW_THREADS
   6998     if (!ok)
   6999         return win32_error("CreatePipe", NULL);
   7000     read_fd = _open_osfhandle((Py_intptr_t)read, 0);
   7001     write_fd = _open_osfhandle((Py_intptr_t)write, 1);
   7002     return Py_BuildValue("(ii)", read_fd, write_fd);
   7003 #endif /* MS_WINDOWS */
   7004 #endif
   7005 }
   7006 #endif  /* HAVE_PIPE */
   7007 
   7008 
   7009 #ifdef HAVE_MKFIFO
   7010 PyDoc_STRVAR(posix_mkfifo__doc__,
   7011 "mkfifo(filename [, mode=0666])\n\n\
   7012 Create a FIFO (a POSIX named pipe).");
   7013 
   7014 static PyObject *
   7015 posix_mkfifo(PyObject *self, PyObject *args)
   7016 {
   7017     char *filename;
   7018     int mode = 0666;
   7019     int res;
   7020     if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode))
   7021         return NULL;
   7022     Py_BEGIN_ALLOW_THREADS
   7023     res = mkfifo(filename, mode);
   7024     Py_END_ALLOW_THREADS
   7025     if (res < 0)
   7026         return posix_error();
   7027     Py_INCREF(Py_None);
   7028     return Py_None;
   7029 }
   7030 #endif
   7031 
   7032 
   7033 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
   7034 PyDoc_STRVAR(posix_mknod__doc__,
   7035 "mknod(filename [, mode=0600, device])\n\n\
   7036 Create a filesystem node (file, device special file or named pipe)\n\
   7037 named filename. mode specifies both the permissions to use and the\n\
   7038 type of node to be created, being combined (bitwise OR) with one of\n\
   7039 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
   7040 device defines the newly created device special file (probably using\n\
   7041 os.makedev()), otherwise it is ignored.");
   7042 
   7043 
   7044 static PyObject *
   7045 posix_mknod(PyObject *self, PyObject *args)
   7046 {
   7047     char *filename;
   7048     int mode = 0600;
   7049     dev_t device = 0;
   7050     int res;
   7051     if (!PyArg_ParseTuple(args, "s|iO&:mknod",
   7052         &filename, &mode,
   7053         _Py_Dev_Converter, &device))
   7054         return NULL;
   7055     Py_BEGIN_ALLOW_THREADS
   7056     res = mknod(filename, mode, device);
   7057     Py_END_ALLOW_THREADS
   7058     if (res < 0)
   7059         return posix_error();
   7060     Py_INCREF(Py_None);
   7061     return Py_None;
   7062 }
   7063 #endif
   7064 
   7065 #ifdef HAVE_DEVICE_MACROS
   7066 PyDoc_STRVAR(posix_major__doc__,
   7067 "major(device) -> major number\n\
   7068 Extracts a device major number from a raw device number.");
   7069 
   7070 static PyObject *
   7071 posix_major(PyObject *self, PyObject *args)
   7072 {
   7073     dev_t device;
   7074     if (!PyArg_ParseTuple(args, "O&:major", _Py_Dev_Converter, &device))
   7075         return NULL;
   7076     return PyInt_FromLong((long)major(device));
   7077 }
   7078 
   7079 PyDoc_STRVAR(posix_minor__doc__,
   7080 "minor(device) -> minor number\n\
   7081 Extracts a device minor number from a raw device number.");
   7082 
   7083 static PyObject *
   7084 posix_minor(PyObject *self, PyObject *args)
   7085 {
   7086     dev_t device;
   7087     if (!PyArg_ParseTuple(args, "O&:minor", _Py_Dev_Converter, &device))
   7088         return NULL;
   7089     return PyInt_FromLong((long)minor(device));
   7090 }
   7091 
   7092 PyDoc_STRVAR(posix_makedev__doc__,
   7093 "makedev(major, minor) -> device number\n\
   7094 Composes a raw device number from the major and minor device numbers.");
   7095 
   7096 static PyObject *
   7097 posix_makedev(PyObject *self, PyObject *args)
   7098 {
   7099     int major, minor;
   7100     if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
   7101         return NULL;
   7102     return _PyInt_FromDev(makedev(major, minor));
   7103 }
   7104 #endif /* device macros */
   7105 
   7106 
   7107 #ifdef HAVE_FTRUNCATE
   7108 PyDoc_STRVAR(posix_ftruncate__doc__,
   7109 "ftruncate(fd, length)\n\n\
   7110 Truncate a file to a specified length.");
   7111 
   7112 static PyObject *
   7113 posix_ftruncate(PyObject *self, PyObject *args)
   7114 {
   7115     int fd;
   7116     off_t length;
   7117     int res;
   7118     PyObject *lenobj;
   7119 
   7120     if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
   7121         return NULL;
   7122 
   7123 #if !defined(HAVE_LARGEFILE_SUPPORT)
   7124     length = PyInt_AsLong(lenobj);
   7125 #else
   7126     length = PyLong_Check(lenobj) ?
   7127         PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj);
   7128 #endif
   7129     if (PyErr_Occurred())
   7130         return NULL;
   7131 
   7132     Py_BEGIN_ALLOW_THREADS
   7133     res = ftruncate(fd, length);
   7134     Py_END_ALLOW_THREADS
   7135     if (res < 0)
   7136         return posix_error();
   7137     Py_INCREF(Py_None);
   7138     return Py_None;
   7139 }
   7140 #endif
   7141 
   7142 #ifdef HAVE_PUTENV
   7143 PyDoc_STRVAR(posix_putenv__doc__,
   7144 "putenv(key, value)\n\n\
   7145 Change or add an environment variable.");
   7146 
   7147 /* Save putenv() parameters as values here, so we can collect them when they
   7148  * get re-set with another call for the same key. */
   7149 static PyObject *posix_putenv_garbage;
   7150 
   7151 static PyObject *
   7152 posix_putenv(PyObject *self, PyObject *args)
   7153 {
   7154     char *s1, *s2;
   7155     char *newenv;
   7156     PyObject *newstr;
   7157     size_t len;
   7158 
   7159     if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2))
   7160         return NULL;
   7161 
   7162 #if defined(PYOS_OS2)
   7163     if (stricmp(s1, "BEGINLIBPATH") == 0) {
   7164         APIRET rc;
   7165 
   7166         rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
   7167         if (rc != NO_ERROR)
   7168             return os2_error(rc);
   7169 
   7170     } else if (stricmp(s1, "ENDLIBPATH") == 0) {
   7171         APIRET rc;
   7172 
   7173         rc = DosSetExtLIBPATH(s2, END_LIBPATH);
   7174         if (rc != NO_ERROR)
   7175             return os2_error(rc);
   7176     } else {
   7177 #endif
   7178 
   7179     /* XXX This can leak memory -- not easy to fix :-( */
   7180     len = strlen(s1) + strlen(s2) + 2;
   7181 #ifdef MS_WINDOWS
   7182     if (_MAX_ENV < (len - 1)) {
   7183         PyErr_Format(PyExc_ValueError,
   7184                      "the environment variable is longer than %u bytes",
   7185                      _MAX_ENV);
   7186         return NULL;
   7187     }
   7188 #endif
   7189     /* len includes space for a trailing \0; the size arg to
   7190        PyString_FromStringAndSize does not count that */
   7191     newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
   7192     if (newstr == NULL)
   7193         return PyErr_NoMemory();
   7194     newenv = PyString_AS_STRING(newstr);
   7195     PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
   7196     if (putenv(newenv)) {
   7197         Py_DECREF(newstr);
   7198         posix_error();
   7199         return NULL;
   7200     }
   7201     /* Install the first arg and newstr in posix_putenv_garbage;
   7202      * this will cause previous value to be collected.  This has to
   7203      * happen after the real putenv() call because the old value
   7204      * was still accessible until then. */
   7205     if (PyDict_SetItem(posix_putenv_garbage,
   7206                        PyTuple_GET_ITEM(args, 0), newstr)) {
   7207         /* really not much we can do; just leak */
   7208         PyErr_Clear();
   7209     }
   7210     else {
   7211         Py_DECREF(newstr);
   7212     }
   7213 
   7214 #if defined(PYOS_OS2)
   7215     }
   7216 #endif
   7217     Py_INCREF(Py_None);
   7218     return Py_None;
   7219 }
   7220 #endif /* putenv */
   7221 
   7222 #ifdef HAVE_UNSETENV
   7223 PyDoc_STRVAR(posix_unsetenv__doc__,
   7224 "unsetenv(key)\n\n\
   7225 Delete an environment variable.");
   7226 
   7227 static PyObject *
   7228 posix_unsetenv(PyObject *self, PyObject *args)
   7229 {
   7230     char *s1;
   7231 #ifndef HAVE_BROKEN_UNSETENV
   7232     int err;
   7233 #endif
   7234 
   7235     if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
   7236         return NULL;
   7237 
   7238 #ifdef HAVE_BROKEN_UNSETENV
   7239     unsetenv(s1);
   7240 #else
   7241     err = unsetenv(s1);
   7242     if (err)
   7243         return posix_error();
   7244 #endif
   7245 
   7246     /* Remove the key from posix_putenv_garbage;
   7247      * this will cause it to be collected.  This has to
   7248      * happen after the real unsetenv() call because the
   7249      * old value was still accessible until then.
   7250      */
   7251     if (PyDict_DelItem(posix_putenv_garbage,
   7252                        PyTuple_GET_ITEM(args, 0))) {
   7253         /* really not much we can do; just leak */
   7254         PyErr_Clear();
   7255     }
   7256 
   7257     Py_INCREF(Py_None);
   7258     return Py_None;
   7259 }
   7260 #endif /* unsetenv */
   7261 
   7262 PyDoc_STRVAR(posix_strerror__doc__,
   7263 "strerror(code) -> string\n\n\
   7264 Translate an error code to a message string.");
   7265 
   7266 static PyObject *
   7267 posix_strerror(PyObject *self, PyObject *args)
   7268 {
   7269     int code;
   7270     char *message;
   7271     if (!PyArg_ParseTuple(args, "i:strerror", &code))
   7272         return NULL;
   7273     message = strerror(code);
   7274     if (message == NULL) {
   7275         PyErr_SetString(PyExc_ValueError,
   7276                         "strerror() argument out of range");
   7277         return NULL;
   7278     }
   7279     return PyString_FromString(message);
   7280 }
   7281 
   7282 
   7283 #ifdef HAVE_SYS_WAIT_H
   7284 
   7285 #ifdef WCOREDUMP
   7286 PyDoc_STRVAR(posix_WCOREDUMP__doc__,
   7287 "WCOREDUMP(status) -> bool\n\n\
   7288 Return True if the process returning 'status' was dumped to a core file.");
   7289 
   7290 static PyObject *
   7291 posix_WCOREDUMP(PyObject *self, PyObject *args)
   7292 {
   7293     WAIT_TYPE status;
   7294     WAIT_STATUS_INT(status) = 0;
   7295 
   7296     if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
   7297         return NULL;
   7298 
   7299     return PyBool_FromLong(WCOREDUMP(status));
   7300 }
   7301 #endif /* WCOREDUMP */
   7302 
   7303 #ifdef WIFCONTINUED
   7304 PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
   7305 "WIFCONTINUED(status) -> bool\n\n\
   7306 Return True if the process returning 'status' was continued from a\n\
   7307 job control stop.");
   7308 
   7309 static PyObject *
   7310 posix_WIFCONTINUED(PyObject *self, PyObject *args)
   7311 {
   7312     WAIT_TYPE status;
   7313     WAIT_STATUS_INT(status) = 0;
   7314 
   7315     if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
   7316         return NULL;
   7317 
   7318     return PyBool_FromLong(WIFCONTINUED(status));
   7319 }
   7320 #endif /* WIFCONTINUED */
   7321 
   7322 #ifdef WIFSTOPPED
   7323 PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
   7324 "WIFSTOPPED(status) -> bool\n\n\
   7325 Return True if the process returning 'status' was stopped.");
   7326 
   7327 static PyObject *
   7328 posix_WIFSTOPPED(PyObject *self, PyObject *args)
   7329 {
   7330     WAIT_TYPE status;
   7331     WAIT_STATUS_INT(status) = 0;
   7332 
   7333     if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
   7334         return NULL;
   7335 
   7336     return PyBool_FromLong(WIFSTOPPED(status));
   7337 }
   7338 #endif /* WIFSTOPPED */
   7339 
   7340 #ifdef WIFSIGNALED
   7341 PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
   7342 "WIFSIGNALED(status) -> bool\n\n\
   7343 Return True if the process returning 'status' was terminated by a signal.");
   7344 
   7345 static PyObject *
   7346 posix_WIFSIGNALED(PyObject *self, PyObject *args)
   7347 {
   7348     WAIT_TYPE status;
   7349     WAIT_STATUS_INT(status) = 0;
   7350 
   7351     if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
   7352         return NULL;
   7353 
   7354     return PyBool_FromLong(WIFSIGNALED(status));
   7355 }
   7356 #endif /* WIFSIGNALED */
   7357 
   7358 #ifdef WIFEXITED
   7359 PyDoc_STRVAR(posix_WIFEXITED__doc__,
   7360 "WIFEXITED(status) -> bool\n\n\
   7361 Return true if the process returning 'status' exited using the exit()\n\
   7362 system call.");
   7363 
   7364 static PyObject *
   7365 posix_WIFEXITED(PyObject *self, PyObject *args)
   7366 {
   7367     WAIT_TYPE status;
   7368     WAIT_STATUS_INT(status) = 0;
   7369 
   7370     if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
   7371         return NULL;
   7372 
   7373     return PyBool_FromLong(WIFEXITED(status));
   7374 }
   7375 #endif /* WIFEXITED */
   7376 
   7377 #ifdef WEXITSTATUS
   7378 PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
   7379 "WEXITSTATUS(status) -> integer\n\n\
   7380 Return the process return code from 'status'.");
   7381 
   7382 static PyObject *
   7383 posix_WEXITSTATUS(PyObject *self, PyObject *args)
   7384 {
   7385     WAIT_TYPE status;
   7386     WAIT_STATUS_INT(status) = 0;
   7387 
   7388     if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
   7389         return NULL;
   7390 
   7391     return Py_BuildValue("i", WEXITSTATUS(status));
   7392 }
   7393 #endif /* WEXITSTATUS */
   7394 
   7395 #ifdef WTERMSIG
   7396 PyDoc_STRVAR(posix_WTERMSIG__doc__,
   7397 "WTERMSIG(status) -> integer\n\n\
   7398 Return the signal that terminated the process that provided the 'status'\n\
   7399 value.");
   7400 
   7401 static PyObject *
   7402 posix_WTERMSIG(PyObject *self, PyObject *args)
   7403 {
   7404     WAIT_TYPE status;
   7405     WAIT_STATUS_INT(status) = 0;
   7406 
   7407     if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
   7408         return NULL;
   7409 
   7410     return Py_BuildValue("i", WTERMSIG(status));
   7411 }
   7412 #endif /* WTERMSIG */
   7413 
   7414 #ifdef WSTOPSIG
   7415 PyDoc_STRVAR(posix_WSTOPSIG__doc__,
   7416 "WSTOPSIG(status) -> integer\n\n\
   7417 Return the signal that stopped the process that provided\n\
   7418 the 'status' value.");
   7419 
   7420 static PyObject *
   7421 posix_WSTOPSIG(PyObject *self, PyObject *args)
   7422 {
   7423     WAIT_TYPE status;
   7424     WAIT_STATUS_INT(status) = 0;
   7425 
   7426     if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
   7427         return NULL;
   7428 
   7429     return Py_BuildValue("i", WSTOPSIG(status));
   7430 }
   7431 #endif /* WSTOPSIG */
   7432 
   7433 #endif /* HAVE_SYS_WAIT_H */
   7434 
   7435 
   7436 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
   7437 #ifdef _SCO_DS
   7438 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
   7439    needed definitions in sys/statvfs.h */
   7440 #define _SVID3
   7441 #endif
   7442 #include <sys/statvfs.h>
   7443 
   7444 static PyObject*
   7445 _pystatvfs_fromstructstatvfs(struct statvfs st) {
   7446     PyObject *v = PyStructSequence_New(&StatVFSResultType);
   7447     if (v == NULL)
   7448         return NULL;
   7449 
   7450 #if !defined(HAVE_LARGEFILE_SUPPORT)
   7451     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
   7452     PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
   7453     PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) st.f_blocks));
   7454     PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) st.f_bfree));
   7455     PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) st.f_bavail));
   7456     PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) st.f_files));
   7457     PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong((long) st.f_ffree));
   7458     PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) st.f_favail));
   7459     PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
   7460     PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
   7461 #else
   7462     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
   7463     PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
   7464     PyStructSequence_SET_ITEM(v, 2,
   7465                               PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
   7466     PyStructSequence_SET_ITEM(v, 3,
   7467                               PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
   7468     PyStructSequence_SET_ITEM(v, 4,
   7469                               PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
   7470     PyStructSequence_SET_ITEM(v, 5,
   7471                               PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
   7472     PyStructSequence_SET_ITEM(v, 6,
   7473                               PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
   7474     PyStructSequence_SET_ITEM(v, 7,
   7475                               PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
   7476     PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
   7477     PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
   7478 #endif
   7479 
   7480     return v;
   7481 }
   7482 
   7483 PyDoc_STRVAR(posix_fstatvfs__doc__,
   7484 "fstatvfs(fd) -> statvfs result\n\n\
   7485 Perform an fstatvfs system call on the given fd.");
   7486 
   7487 static PyObject *
   7488 posix_fstatvfs(PyObject *self, PyObject *args)
   7489 {
   7490     int fd, res;
   7491     struct statvfs st;
   7492 
   7493     if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
   7494         return NULL;
   7495     Py_BEGIN_ALLOW_THREADS
   7496     res = fstatvfs(fd, &st);
   7497     Py_END_ALLOW_THREADS
   7498     if (res != 0)
   7499         return posix_error();
   7500 
   7501     return _pystatvfs_fromstructstatvfs(st);
   7502 }
   7503 #endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
   7504 
   7505 
   7506 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
   7507 #include <sys/statvfs.h>
   7508 
   7509 PyDoc_STRVAR(posix_statvfs__doc__,
   7510 "statvfs(path) -> statvfs result\n\n\
   7511 Perform a statvfs system call on the given path.");
   7512 
   7513 static PyObject *
   7514 posix_statvfs(PyObject *self, PyObject *args)
   7515 {
   7516     char *path;
   7517     int res;
   7518     struct statvfs st;
   7519     if (!PyArg_ParseTuple(args, "s:statvfs", &path))
   7520         return NULL;
   7521     Py_BEGIN_ALLOW_THREADS
   7522     res = statvfs(path, &st);
   7523     Py_END_ALLOW_THREADS
   7524     if (res != 0)
   7525         return posix_error_with_filename(path);
   7526 
   7527     return _pystatvfs_fromstructstatvfs(st);
   7528 }
   7529 #endif /* HAVE_STATVFS */
   7530 
   7531 
   7532 #ifdef HAVE_TEMPNAM
   7533 PyDoc_STRVAR(posix_tempnam__doc__,
   7534 "tempnam([dir[, prefix]]) -> string\n\n\
   7535 Return a unique name for a temporary file.\n\
   7536 The directory and a prefix may be specified as strings; they may be omitted\n\
   7537 or None if not needed.");
   7538 
   7539 static PyObject *
   7540 posix_tempnam(PyObject *self, PyObject *args)
   7541 {
   7542     PyObject *result = NULL;
   7543     char *dir = NULL;
   7544     char *pfx = NULL;
   7545     char *name;
   7546 
   7547     if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx))
   7548     return NULL;
   7549 
   7550     if (PyErr_Warn(PyExc_RuntimeWarning,
   7551                    "tempnam is a potential security risk to your program") < 0)
   7552         return NULL;
   7553 
   7554     if (PyErr_WarnPy3k("tempnam has been removed in 3.x; "
   7555                        "use the tempfile module", 1) < 0)
   7556         return NULL;
   7557 
   7558 #ifdef MS_WINDOWS
   7559     name = _tempnam(dir, pfx);
   7560 #else
   7561     name = tempnam(dir, pfx);
   7562 #endif
   7563     if (name == NULL)
   7564         return PyErr_NoMemory();
   7565     result = PyString_FromString(name);
   7566     free(name);
   7567     return result;
   7568 }
   7569 #endif
   7570 
   7571 
   7572 #ifdef HAVE_TMPFILE
   7573 PyDoc_STRVAR(posix_tmpfile__doc__,
   7574 "tmpfile() -> file object\n\n\
   7575 Create a temporary file with no directory entries.");
   7576 
   7577 static PyObject *
   7578 posix_tmpfile(PyObject *self, PyObject *noargs)
   7579 {
   7580     FILE *fp;
   7581 
   7582     if (PyErr_WarnPy3k("tmpfile has been removed in 3.x; "
   7583                        "use the tempfile module", 1) < 0)
   7584         return NULL;
   7585 
   7586     fp = tmpfile();
   7587     if (fp == NULL)
   7588         return posix_error();
   7589     return PyFile_FromFile(fp, "<tmpfile>", "w+b", fclose);
   7590 }
   7591 #endif
   7592 
   7593 
   7594 #ifdef HAVE_TMPNAM
   7595 PyDoc_STRVAR(posix_tmpnam__doc__,
   7596 "tmpnam() -> string\n\n\
   7597 Return a unique name for a temporary file.");
   7598 
   7599 static PyObject *
   7600 posix_tmpnam(PyObject *self, PyObject *noargs)
   7601 {
   7602     char buffer[L_tmpnam];
   7603     char *name;
   7604 
   7605     if (PyErr_Warn(PyExc_RuntimeWarning,
   7606                    "tmpnam is a potential security risk to your program") < 0)
   7607         return NULL;
   7608 
   7609     if (PyErr_WarnPy3k("tmpnam has been removed in 3.x; "
   7610                        "use the tempfile module", 1) < 0)
   7611         return NULL;
   7612 
   7613 #ifdef USE_TMPNAM_R
   7614     name = tmpnam_r(buffer);
   7615 #else
   7616     name = tmpnam(buffer);
   7617 #endif
   7618     if (name == NULL) {
   7619         PyObject *err = Py_BuildValue("is", 0,
   7620 #ifdef USE_TMPNAM_R
   7621                                       "unexpected NULL from tmpnam_r"
   7622 #else
   7623                                       "unexpected NULL from tmpnam"
   7624 #endif
   7625                                       );
   7626         PyErr_SetObject(PyExc_OSError, err);
   7627         Py_XDECREF(err);
   7628         return NULL;
   7629     }
   7630     return PyString_FromString(buffer);
   7631 }
   7632 #endif
   7633 
   7634 
   7635 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
   7636  * It maps strings representing configuration variable names to
   7637  * integer values, allowing those functions to be called with the
   7638  * magic names instead of polluting the module's namespace with tons of
   7639  * rarely-used constants.  There are three separate tables that use
   7640  * these definitions.
   7641  *
   7642  * This code is always included, even if none of the interfaces that
   7643  * need it are included.  The #if hackery needed to avoid it would be
   7644  * sufficiently pervasive that it's not worth the loss of readability.
   7645  */
   7646 struct constdef {
   7647     char *name;
   7648     long value;
   7649 };
   7650 
   7651 static int
   7652 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
   7653               size_t tablesize)
   7654 {
   7655     if (PyInt_Check(arg)) {
   7656         *valuep = PyInt_AS_LONG(arg);
   7657         return 1;
   7658     }
   7659     if (PyString_Check(arg)) {
   7660         /* look up the value in the table using a binary search */
   7661         size_t lo = 0;
   7662         size_t mid;
   7663         size_t hi = tablesize;
   7664         int cmp;
   7665         char *confname = PyString_AS_STRING(arg);
   7666         while (lo < hi) {
   7667             mid = (lo + hi) / 2;
   7668             cmp = strcmp(confname, table[mid].name);
   7669             if (cmp < 0)
   7670                 hi = mid;
   7671             else if (cmp > 0)
   7672                 lo = mid + 1;
   7673             else {
   7674                 *valuep = table[mid].value;
   7675                 return 1;
   7676             }
   7677         }
   7678         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
   7679     }
   7680     else
   7681         PyErr_SetString(PyExc_TypeError,
   7682                         "configuration names must be strings or integers");
   7683     return 0;
   7684 }
   7685 
   7686 
   7687 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
   7688 static struct constdef  posix_constants_pathconf[] = {
   7689 #ifdef _PC_ABI_AIO_XFER_MAX
   7690     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
   7691 #endif
   7692 #ifdef _PC_ABI_ASYNC_IO
   7693     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
   7694 #endif
   7695 #ifdef _PC_ASYNC_IO
   7696     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
   7697 #endif
   7698 #ifdef _PC_CHOWN_RESTRICTED
   7699     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
   7700 #endif
   7701 #ifdef _PC_FILESIZEBITS
   7702     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
   7703 #endif
   7704 #ifdef _PC_LAST
   7705     {"PC_LAST", _PC_LAST},
   7706 #endif
   7707 #ifdef _PC_LINK_MAX
   7708     {"PC_LINK_MAX",     _PC_LINK_MAX},
   7709 #endif
   7710 #ifdef _PC_MAX_CANON
   7711     {"PC_MAX_CANON",    _PC_MAX_CANON},
   7712 #endif
   7713 #ifdef _PC_MAX_INPUT
   7714     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
   7715 #endif
   7716 #ifdef _PC_NAME_MAX
   7717     {"PC_NAME_MAX",     _PC_NAME_MAX},
   7718 #endif
   7719 #ifdef _PC_NO_TRUNC
   7720     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
   7721 #endif
   7722 #ifdef _PC_PATH_MAX
   7723     {"PC_PATH_MAX",     _PC_PATH_MAX},
   7724 #endif
   7725 #ifdef _PC_PIPE_BUF
   7726     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
   7727 #endif
   7728 #ifdef _PC_PRIO_IO
   7729     {"PC_PRIO_IO",      _PC_PRIO_IO},
   7730 #endif
   7731 #ifdef _PC_SOCK_MAXBUF
   7732     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
   7733 #endif
   7734 #ifdef _PC_SYNC_IO
   7735     {"PC_SYNC_IO",      _PC_SYNC_IO},
   7736 #endif
   7737 #ifdef _PC_VDISABLE
   7738     {"PC_VDISABLE",     _PC_VDISABLE},
   7739 #endif
   7740 };
   7741 
   7742 static int
   7743 conv_path_confname(PyObject *arg, int *valuep)
   7744 {
   7745     return conv_confname(arg, valuep, posix_constants_pathconf,
   7746                          sizeof(posix_constants_pathconf)
   7747                            / sizeof(struct constdef));
   7748 }
   7749 #endif
   7750 
   7751 #ifdef HAVE_FPATHCONF
   7752 PyDoc_STRVAR(posix_fpathconf__doc__,
   7753 "fpathconf(fd, name) -> integer\n\n\
   7754 Return the configuration limit name for the file descriptor fd.\n\
   7755 If there is no limit, return -1.");
   7756 
   7757 static PyObject *
   7758 posix_fpathconf(PyObject *self, PyObject *args)
   7759 {
   7760     PyObject *result = NULL;
   7761     int name, fd;
   7762 
   7763     if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
   7764                          conv_path_confname, &name)) {
   7765         long limit;
   7766 
   7767         errno = 0;
   7768         limit = fpathconf(fd, name);
   7769         if (limit == -1 && errno != 0)
   7770             posix_error();
   7771         else
   7772             result = PyInt_FromLong(limit);
   7773     }
   7774     return result;
   7775 }
   7776 #endif
   7777 
   7778 
   7779 #ifdef HAVE_PATHCONF
   7780 PyDoc_STRVAR(posix_pathconf__doc__,
   7781 "pathconf(path, name) -> integer\n\n\
   7782 Return the configuration limit name for the file or directory path.\n\
   7783 If there is no limit, return -1.");
   7784 
   7785 static PyObject *
   7786 posix_pathconf(PyObject *self, PyObject *args)
   7787 {
   7788     PyObject *result = NULL;
   7789     int name;
   7790     char *path;
   7791 
   7792     if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
   7793                          conv_path_confname, &name)) {
   7794     long limit;
   7795 
   7796     errno = 0;
   7797     limit = pathconf(path, name);
   7798     if (limit == -1 && errno != 0) {
   7799         if (errno == EINVAL)
   7800             /* could be a path or name problem */
   7801             posix_error();
   7802         else
   7803             posix_error_with_filename(path);
   7804     }
   7805     else
   7806         result = PyInt_FromLong(limit);
   7807     }
   7808     return result;
   7809 }
   7810 #endif
   7811 
   7812 #ifdef HAVE_CONFSTR
   7813 static struct constdef posix_constants_confstr[] = {
   7814 #ifdef _CS_ARCHITECTURE
   7815     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
   7816 #endif
   7817 #ifdef _CS_HOSTNAME
   7818     {"CS_HOSTNAME",     _CS_HOSTNAME},
   7819 #endif
   7820 #ifdef _CS_HW_PROVIDER
   7821     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
   7822 #endif
   7823 #ifdef _CS_HW_SERIAL
   7824     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
   7825 #endif
   7826 #ifdef _CS_INITTAB_NAME
   7827     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
   7828 #endif
   7829 #ifdef _CS_LFS64_CFLAGS
   7830     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
   7831 #endif
   7832 #ifdef _CS_LFS64_LDFLAGS
   7833     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
   7834 #endif
   7835 #ifdef _CS_LFS64_LIBS
   7836     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
   7837 #endif
   7838 #ifdef _CS_LFS64_LINTFLAGS
   7839     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
   7840 #endif
   7841 #ifdef _CS_LFS_CFLAGS
   7842     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
   7843 #endif
   7844 #ifdef _CS_LFS_LDFLAGS
   7845     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
   7846 #endif
   7847 #ifdef _CS_LFS_LIBS
   7848     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
   7849 #endif
   7850 #ifdef _CS_LFS_LINTFLAGS
   7851     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
   7852 #endif
   7853 #ifdef _CS_MACHINE
   7854     {"CS_MACHINE",      _CS_MACHINE},
   7855 #endif
   7856 #ifdef _CS_PATH
   7857     {"CS_PATH", _CS_PATH},
   7858 #endif
   7859 #ifdef _CS_RELEASE
   7860     {"CS_RELEASE",      _CS_RELEASE},
   7861 #endif
   7862 #ifdef _CS_SRPC_DOMAIN
   7863     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
   7864 #endif
   7865 #ifdef _CS_SYSNAME
   7866     {"CS_SYSNAME",      _CS_SYSNAME},
   7867 #endif
   7868 #ifdef _CS_VERSION
   7869     {"CS_VERSION",      _CS_VERSION},
   7870 #endif
   7871 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
   7872     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
   7873 #endif
   7874 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
   7875     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
   7876 #endif
   7877 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
   7878     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
   7879 #endif
   7880 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
   7881     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
   7882 #endif
   7883 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
   7884     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
   7885 #endif
   7886 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
   7887     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
   7888 #endif
   7889 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
   7890     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
   7891 #endif
   7892 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
   7893     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
   7894 #endif
   7895 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
   7896     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
   7897 #endif
   7898 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
   7899     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
   7900 #endif
   7901 #ifdef _CS_XBS5_LP64_OFF64_LIBS
   7902     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
   7903 #endif
   7904 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
   7905     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
   7906 #endif
   7907 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
   7908     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
   7909 #endif
   7910 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
   7911     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
   7912 #endif
   7913 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
   7914     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
   7915 #endif
   7916 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
   7917     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
   7918 #endif
   7919 #ifdef _MIPS_CS_AVAIL_PROCESSORS
   7920     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
   7921 #endif
   7922 #ifdef _MIPS_CS_BASE
   7923     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
   7924 #endif
   7925 #ifdef _MIPS_CS_HOSTID
   7926     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
   7927 #endif
   7928 #ifdef _MIPS_CS_HW_NAME
   7929     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
   7930 #endif
   7931 #ifdef _MIPS_CS_NUM_PROCESSORS
   7932     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
   7933 #endif
   7934 #ifdef _MIPS_CS_OSREL_MAJ
   7935     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
   7936 #endif
   7937 #ifdef _MIPS_CS_OSREL_MIN
   7938     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
   7939 #endif
   7940 #ifdef _MIPS_CS_OSREL_PATCH
   7941     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
   7942 #endif
   7943 #ifdef _MIPS_CS_OS_NAME
   7944     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
   7945 #endif
   7946 #ifdef _MIPS_CS_OS_PROVIDER
   7947     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
   7948 #endif
   7949 #ifdef _MIPS_CS_PROCESSORS
   7950     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
   7951 #endif
   7952 #ifdef _MIPS_CS_SERIAL
   7953     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
   7954 #endif
   7955 #ifdef _MIPS_CS_VENDOR
   7956     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
   7957 #endif
   7958 };
   7959 
   7960 static int
   7961 conv_confstr_confname(PyObject *arg, int *valuep)
   7962 {
   7963     return conv_confname(arg, valuep, posix_constants_confstr,
   7964                          sizeof(posix_constants_confstr)
   7965                            / sizeof(struct constdef));
   7966 }
   7967 
   7968 PyDoc_STRVAR(posix_confstr__doc__,
   7969 "confstr(name) -> string\n\n\
   7970 Return a string-valued system configuration variable.");
   7971 
   7972 static PyObject *
   7973 posix_confstr(PyObject *self, PyObject *args)
   7974 {
   7975     PyObject *result = NULL;
   7976     int name;
   7977     char buffer[256];
   7978 
   7979     if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) {
   7980     int len;
   7981 
   7982     errno = 0;
   7983     len = confstr(name, buffer, sizeof(buffer));
   7984     if (len == 0) {
   7985         if (errno) {
   7986         posix_error();
   7987         }
   7988         else {
   7989         result = Py_None;
   7990         Py_INCREF(Py_None);
   7991         }
   7992     }
   7993     else {
   7994         if ((unsigned int)len >= sizeof(buffer)) {
   7995         result = PyString_FromStringAndSize(NULL, len-1);
   7996         if (result != NULL)
   7997             confstr(name, PyString_AS_STRING(result), len);
   7998         }
   7999         else
   8000         result = PyString_FromStringAndSize(buffer, len-1);
   8001     }
   8002     }
   8003     return result;
   8004 }
   8005 #endif
   8006 
   8007 
   8008 #ifdef HAVE_SYSCONF
   8009 static struct constdef posix_constants_sysconf[] = {
   8010 #ifdef _SC_2_CHAR_TERM
   8011     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
   8012 #endif
   8013 #ifdef _SC_2_C_BIND
   8014     {"SC_2_C_BIND",     _SC_2_C_BIND},
   8015 #endif
   8016 #ifdef _SC_2_C_DEV
   8017     {"SC_2_C_DEV",      _SC_2_C_DEV},
   8018 #endif
   8019 #ifdef _SC_2_C_VERSION
   8020     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
   8021 #endif
   8022 #ifdef _SC_2_FORT_DEV
   8023     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
   8024 #endif
   8025 #ifdef _SC_2_FORT_RUN
   8026     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
   8027 #endif
   8028 #ifdef _SC_2_LOCALEDEF
   8029     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
   8030 #endif
   8031 #ifdef _SC_2_SW_DEV
   8032     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
   8033 #endif
   8034 #ifdef _SC_2_UPE
   8035     {"SC_2_UPE",        _SC_2_UPE},
   8036 #endif
   8037 #ifdef _SC_2_VERSION
   8038     {"SC_2_VERSION",    _SC_2_VERSION},
   8039 #endif
   8040 #ifdef _SC_ABI_ASYNCHRONOUS_IO
   8041     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
   8042 #endif
   8043 #ifdef _SC_ACL
   8044     {"SC_ACL",  _SC_ACL},
   8045 #endif
   8046 #ifdef _SC_AIO_LISTIO_MAX
   8047     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
   8048 #endif
   8049 #ifdef _SC_AIO_MAX
   8050     {"SC_AIO_MAX",      _SC_AIO_MAX},
   8051 #endif
   8052 #ifdef _SC_AIO_PRIO_DELTA_MAX
   8053     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
   8054 #endif
   8055 #ifdef _SC_ARG_MAX
   8056     {"SC_ARG_MAX",      _SC_ARG_MAX},
   8057 #endif
   8058 #ifdef _SC_ASYNCHRONOUS_IO
   8059     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
   8060 #endif
   8061 #ifdef _SC_ATEXIT_MAX
   8062     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
   8063 #endif
   8064 #ifdef _SC_AUDIT
   8065     {"SC_AUDIT",        _SC_AUDIT},
   8066 #endif
   8067 #ifdef _SC_AVPHYS_PAGES
   8068     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
   8069 #endif
   8070 #ifdef _SC_BC_BASE_MAX
   8071     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
   8072 #endif
   8073 #ifdef _SC_BC_DIM_MAX
   8074     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
   8075 #endif
   8076 #ifdef _SC_BC_SCALE_MAX
   8077     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
   8078 #endif
   8079 #ifdef _SC_BC_STRING_MAX
   8080     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
   8081 #endif
   8082 #ifdef _SC_CAP
   8083     {"SC_CAP",  _SC_CAP},
   8084 #endif
   8085 #ifdef _SC_CHARCLASS_NAME_MAX
   8086     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
   8087 #endif
   8088 #ifdef _SC_CHAR_BIT
   8089     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
   8090 #endif
   8091 #ifdef _SC_CHAR_MAX
   8092     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
   8093 #endif
   8094 #ifdef _SC_CHAR_MIN
   8095     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
   8096 #endif
   8097 #ifdef _SC_CHILD_MAX
   8098     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
   8099 #endif
   8100 #ifdef _SC_CLK_TCK
   8101     {"SC_CLK_TCK",      _SC_CLK_TCK},
   8102 #endif
   8103 #ifdef _SC_COHER_BLKSZ
   8104     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
   8105 #endif
   8106 #ifdef _SC_COLL_WEIGHTS_MAX
   8107     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
   8108 #endif
   8109 #ifdef _SC_DCACHE_ASSOC
   8110     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
   8111 #endif
   8112 #ifdef _SC_DCACHE_BLKSZ
   8113     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
   8114 #endif
   8115 #ifdef _SC_DCACHE_LINESZ
   8116     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
   8117 #endif
   8118 #ifdef _SC_DCACHE_SZ
   8119     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
   8120 #endif
   8121 #ifdef _SC_DCACHE_TBLKSZ
   8122     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
   8123 #endif
   8124 #ifdef _SC_DELAYTIMER_MAX
   8125     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
   8126 #endif
   8127 #ifdef _SC_EQUIV_CLASS_MAX
   8128     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
   8129 #endif
   8130 #ifdef _SC_EXPR_NEST_MAX
   8131     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
   8132 #endif
   8133 #ifdef _SC_FSYNC
   8134     {"SC_FSYNC",        _SC_FSYNC},
   8135 #endif
   8136 #ifdef _SC_GETGR_R_SIZE_MAX
   8137     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
   8138 #endif
   8139 #ifdef _SC_GETPW_R_SIZE_MAX
   8140     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
   8141 #endif
   8142 #ifdef _SC_ICACHE_ASSOC
   8143     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
   8144 #endif
   8145 #ifdef _SC_ICACHE_BLKSZ
   8146     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
   8147 #endif
   8148 #ifdef _SC_ICACHE_LINESZ
   8149     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
   8150 #endif
   8151 #ifdef _SC_ICACHE_SZ
   8152     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
   8153 #endif
   8154 #ifdef _SC_INF
   8155     {"SC_INF",  _SC_INF},
   8156 #endif
   8157 #ifdef _SC_INT_MAX
   8158     {"SC_INT_MAX",      _SC_INT_MAX},
   8159 #endif
   8160 #ifdef _SC_INT_MIN
   8161     {"SC_INT_MIN",      _SC_INT_MIN},
   8162 #endif
   8163 #ifdef _SC_IOV_MAX
   8164     {"SC_IOV_MAX",      _SC_IOV_MAX},
   8165 #endif
   8166 #ifdef _SC_IP_SECOPTS
   8167     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
   8168 #endif
   8169 #ifdef _SC_JOB_CONTROL
   8170     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
   8171 #endif
   8172 #ifdef _SC_KERN_POINTERS
   8173     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
   8174 #endif
   8175 #ifdef _SC_KERN_SIM
   8176     {"SC_KERN_SIM",     _SC_KERN_SIM},
   8177 #endif
   8178 #ifdef _SC_LINE_MAX
   8179     {"SC_LINE_MAX",     _SC_LINE_MAX},
   8180 #endif
   8181 #ifdef _SC_LOGIN_NAME_MAX
   8182     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
   8183 #endif
   8184 #ifdef _SC_LOGNAME_MAX
   8185     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
   8186 #endif
   8187 #ifdef _SC_LONG_BIT
   8188     {"SC_LONG_BIT",     _SC_LONG_BIT},
   8189 #endif
   8190 #ifdef _SC_MAC
   8191     {"SC_MAC",  _SC_MAC},
   8192 #endif
   8193 #ifdef _SC_MAPPED_FILES
   8194     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
   8195 #endif
   8196 #ifdef _SC_MAXPID
   8197     {"SC_MAXPID",       _SC_MAXPID},
   8198 #endif
   8199 #ifdef _SC_MB_LEN_MAX
   8200     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
   8201 #endif
   8202 #ifdef _SC_MEMLOCK
   8203     {"SC_MEMLOCK",      _SC_MEMLOCK},
   8204 #endif
   8205 #ifdef _SC_MEMLOCK_RANGE
   8206     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
   8207 #endif
   8208 #ifdef _SC_MEMORY_PROTECTION
   8209     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
   8210 #endif
   8211 #ifdef _SC_MESSAGE_PASSING
   8212     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
   8213 #endif
   8214 #ifdef _SC_MMAP_FIXED_ALIGNMENT
   8215     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
   8216 #endif
   8217 #ifdef _SC_MQ_OPEN_MAX
   8218     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
   8219 #endif
   8220 #ifdef _SC_MQ_PRIO_MAX
   8221     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
   8222 #endif
   8223 #ifdef _SC_NACLS_MAX
   8224     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
   8225 #endif
   8226 #ifdef _SC_NGROUPS_MAX
   8227     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
   8228 #endif
   8229 #ifdef _SC_NL_ARGMAX
   8230     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
   8231 #endif
   8232 #ifdef _SC_NL_LANGMAX
   8233     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
   8234 #endif
   8235 #ifdef _SC_NL_MSGMAX
   8236     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
   8237 #endif
   8238 #ifdef _SC_NL_NMAX
   8239     {"SC_NL_NMAX",      _SC_NL_NMAX},
   8240 #endif
   8241 #ifdef _SC_NL_SETMAX
   8242     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
   8243 #endif
   8244 #ifdef _SC_NL_TEXTMAX
   8245     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
   8246 #endif
   8247 #ifdef _SC_NPROCESSORS_CONF
   8248     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
   8249 #endif
   8250 #ifdef _SC_NPROCESSORS_ONLN
   8251     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
   8252 #endif
   8253 #ifdef _SC_NPROC_CONF
   8254     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
   8255 #endif
   8256 #ifdef _SC_NPROC_ONLN
   8257     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
   8258 #endif
   8259 #ifdef _SC_NZERO
   8260     {"SC_NZERO",        _SC_NZERO},
   8261 #endif
   8262 #ifdef _SC_OPEN_MAX
   8263     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
   8264 #endif
   8265 #ifdef _SC_PAGESIZE
   8266     {"SC_PAGESIZE",     _SC_PAGESIZE},
   8267 #endif
   8268 #ifdef _SC_PAGE_SIZE
   8269     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
   8270 #endif
   8271 #ifdef _SC_PASS_MAX
   8272     {"SC_PASS_MAX",     _SC_PASS_MAX},
   8273 #endif
   8274 #ifdef _SC_PHYS_PAGES
   8275     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
   8276 #endif
   8277 #ifdef _SC_PII
   8278     {"SC_PII",  _SC_PII},
   8279 #endif
   8280 #ifdef _SC_PII_INTERNET
   8281     {"SC_PII_INTERNET", _SC_PII_INTERNET},
   8282 #endif
   8283 #ifdef _SC_PII_INTERNET_DGRAM
   8284     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
   8285 #endif
   8286 #ifdef _SC_PII_INTERNET_STREAM
   8287     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
   8288 #endif
   8289 #ifdef _SC_PII_OSI
   8290     {"SC_PII_OSI",      _SC_PII_OSI},
   8291 #endif
   8292 #ifdef _SC_PII_OSI_CLTS
   8293     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
   8294 #endif
   8295 #ifdef _SC_PII_OSI_COTS
   8296     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
   8297 #endif
   8298 #ifdef _SC_PII_OSI_M
   8299     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
   8300 #endif
   8301 #ifdef _SC_PII_SOCKET
   8302     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
   8303 #endif
   8304 #ifdef _SC_PII_XTI
   8305     {"SC_PII_XTI",      _SC_PII_XTI},
   8306 #endif
   8307 #ifdef _SC_POLL
   8308     {"SC_POLL", _SC_POLL},
   8309 #endif
   8310 #ifdef _SC_PRIORITIZED_IO
   8311     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
   8312 #endif
   8313 #ifdef _SC_PRIORITY_SCHEDULING
   8314     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
   8315 #endif
   8316 #ifdef _SC_REALTIME_SIGNALS
   8317     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
   8318 #endif
   8319 #ifdef _SC_RE_DUP_MAX
   8320     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
   8321 #endif
   8322 #ifdef _SC_RTSIG_MAX
   8323     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
   8324 #endif
   8325 #ifdef _SC_SAVED_IDS
   8326     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
   8327 #endif
   8328 #ifdef _SC_SCHAR_MAX
   8329     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
   8330 #endif
   8331 #ifdef _SC_SCHAR_MIN
   8332     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
   8333 #endif
   8334 #ifdef _SC_SELECT
   8335     {"SC_SELECT",       _SC_SELECT},
   8336 #endif
   8337 #ifdef _SC_SEMAPHORES
   8338     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
   8339 #endif
   8340 #ifdef _SC_SEM_NSEMS_MAX
   8341     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
   8342 #endif
   8343 #ifdef _SC_SEM_VALUE_MAX
   8344     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
   8345 #endif
   8346 #ifdef _SC_SHARED_MEMORY_OBJECTS
   8347     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
   8348 #endif
   8349 #ifdef _SC_SHRT_MAX
   8350     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
   8351 #endif
   8352 #ifdef _SC_SHRT_MIN
   8353     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
   8354 #endif
   8355 #ifdef _SC_SIGQUEUE_MAX
   8356     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
   8357 #endif
   8358 #ifdef _SC_SIGRT_MAX
   8359     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
   8360 #endif
   8361 #ifdef _SC_SIGRT_MIN
   8362     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
   8363 #endif
   8364 #ifdef _SC_SOFTPOWER
   8365     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
   8366 #endif
   8367 #ifdef _SC_SPLIT_CACHE
   8368     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
   8369 #endif
   8370 #ifdef _SC_SSIZE_MAX
   8371     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
   8372 #endif
   8373 #ifdef _SC_STACK_PROT
   8374     {"SC_STACK_PROT",   _SC_STACK_PROT},
   8375 #endif
   8376 #ifdef _SC_STREAM_MAX
   8377     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
   8378 #endif
   8379 #ifdef _SC_SYNCHRONIZED_IO
   8380     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
   8381 #endif
   8382 #ifdef _SC_THREADS
   8383     {"SC_THREADS",      _SC_THREADS},
   8384 #endif
   8385 #ifdef _SC_THREAD_ATTR_STACKADDR
   8386     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
   8387 #endif
   8388 #ifdef _SC_THREAD_ATTR_STACKSIZE
   8389     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
   8390 #endif
   8391 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
   8392     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
   8393 #endif
   8394 #ifdef _SC_THREAD_KEYS_MAX
   8395     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
   8396 #endif
   8397 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
   8398     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
   8399 #endif
   8400 #ifdef _SC_THREAD_PRIO_INHERIT
   8401     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
   8402 #endif
   8403 #ifdef _SC_THREAD_PRIO_PROTECT
   8404     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
   8405 #endif
   8406 #ifdef _SC_THREAD_PROCESS_SHARED
   8407     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
   8408 #endif
   8409 #ifdef _SC_THREAD_SAFE_FUNCTIONS
   8410     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
   8411 #endif
   8412 #ifdef _SC_THREAD_STACK_MIN
   8413     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
   8414 #endif
   8415 #ifdef _SC_THREAD_THREADS_MAX
   8416     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
   8417 #endif
   8418 #ifdef _SC_TIMERS
   8419     {"SC_TIMERS",       _SC_TIMERS},
   8420 #endif
   8421 #ifdef _SC_TIMER_MAX
   8422     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
   8423 #endif
   8424 #ifdef _SC_TTY_NAME_MAX
   8425     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
   8426 #endif
   8427 #ifdef _SC_TZNAME_MAX
   8428     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
   8429 #endif
   8430 #ifdef _SC_T_IOV_MAX
   8431     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
   8432 #endif
   8433 #ifdef _SC_UCHAR_MAX
   8434     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
   8435 #endif
   8436 #ifdef _SC_UINT_MAX
   8437     {"SC_UINT_MAX",     _SC_UINT_MAX},
   8438 #endif
   8439 #ifdef _SC_UIO_MAXIOV
   8440     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
   8441 #endif
   8442 #ifdef _SC_ULONG_MAX
   8443     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
   8444 #endif
   8445 #ifdef _SC_USHRT_MAX
   8446     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
   8447 #endif
   8448 #ifdef _SC_VERSION
   8449     {"SC_VERSION",      _SC_VERSION},
   8450 #endif
   8451 #ifdef _SC_WORD_BIT
   8452     {"SC_WORD_BIT",     _SC_WORD_BIT},
   8453 #endif
   8454 #ifdef _SC_XBS5_ILP32_OFF32
   8455     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
   8456 #endif
   8457 #ifdef _SC_XBS5_ILP32_OFFBIG
   8458     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
   8459 #endif
   8460 #ifdef _SC_XBS5_LP64_OFF64
   8461     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
   8462 #endif
   8463 #ifdef _SC_XBS5_LPBIG_OFFBIG
   8464     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
   8465 #endif
   8466 #ifdef _SC_XOPEN_CRYPT
   8467     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
   8468 #endif
   8469 #ifdef _SC_XOPEN_ENH_I18N
   8470     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
   8471 #endif
   8472 #ifdef _SC_XOPEN_LEGACY
   8473     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
   8474 #endif
   8475 #ifdef _SC_XOPEN_REALTIME
   8476     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
   8477 #endif
   8478 #ifdef _SC_XOPEN_REALTIME_THREADS
   8479     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
   8480 #endif
   8481 #ifdef _SC_XOPEN_SHM
   8482     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
   8483 #endif
   8484 #ifdef _SC_XOPEN_UNIX
   8485     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
   8486 #endif
   8487 #ifdef _SC_XOPEN_VERSION
   8488     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
   8489 #endif
   8490 #ifdef _SC_XOPEN_XCU_VERSION
   8491     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
   8492 #endif
   8493 #ifdef _SC_XOPEN_XPG2
   8494     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
   8495 #endif
   8496 #ifdef _SC_XOPEN_XPG3
   8497     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
   8498 #endif
   8499 #ifdef _SC_XOPEN_XPG4
   8500     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
   8501 #endif
   8502 };
   8503 
   8504 static int
   8505 conv_sysconf_confname(PyObject *arg, int *valuep)
   8506 {
   8507     return conv_confname(arg, valuep, posix_constants_sysconf,
   8508                          sizeof(posix_constants_sysconf)
   8509                            / sizeof(struct constdef));
   8510 }
   8511 
   8512 PyDoc_STRVAR(posix_sysconf__doc__,
   8513 "sysconf(name) -> integer\n\n\
   8514 Return an integer-valued system configuration variable.");
   8515 
   8516 static PyObject *
   8517 posix_sysconf(PyObject *self, PyObject *args)
   8518 {
   8519     PyObject *result = NULL;
   8520     int name;
   8521 
   8522     if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
   8523         int value;
   8524 
   8525         errno = 0;
   8526         value = sysconf(name);
   8527         if (value == -1 && errno != 0)
   8528             posix_error();
   8529         else
   8530             result = PyInt_FromLong(value);
   8531     }
   8532     return result;
   8533 }
   8534 #endif
   8535 
   8536 
   8537 /* This code is used to ensure that the tables of configuration value names
   8538  * are in sorted order as required by conv_confname(), and also to build
   8539  * the exported dictionaries that are used to publish information about the
   8540  * names available on the host platform.
   8541  *
   8542  * Sorting the table at runtime ensures that the table is properly ordered
   8543  * when used, even for platforms we're not able to test on.  It also makes
   8544  * it easier to add additional entries to the tables.
   8545  */
   8546 
   8547 static int
   8548 cmp_constdefs(const void *v1,  const void *v2)
   8549 {
   8550     const struct constdef *c1 =
   8551     (const struct constdef *) v1;
   8552     const struct constdef *c2 =
   8553     (const struct constdef *) v2;
   8554 
   8555     return strcmp(c1->name, c2->name);
   8556 }
   8557 
   8558 static int
   8559 setup_confname_table(struct constdef *table, size_t tablesize,
   8560                      char *tablename, PyObject *module)
   8561 {
   8562     PyObject *d = NULL;
   8563     size_t i;
   8564     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
   8565     d = PyDict_New();
   8566     if (d == NULL)
   8567         return -1;
   8568 
   8569     for (i=0; i < tablesize; ++i) {
   8570         PyObject *o = PyInt_FromLong(table[i].value);
   8571         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
   8572             Py_XDECREF(o);
   8573             Py_DECREF(d);
   8574             return -1;
   8575         }
   8576         Py_DECREF(o);
   8577     }
   8578     return PyModule_AddObject(module, tablename, d);
   8579 }
   8580 
   8581 /* Return -1 on failure, 0 on success. */
   8582 static int
   8583 setup_confname_tables(PyObject *module)
   8584 {
   8585 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
   8586     if (setup_confname_table(posix_constants_pathconf,
   8587                              sizeof(posix_constants_pathconf)
   8588                                / sizeof(struct constdef),
   8589                              "pathconf_names", module))
   8590         return -1;
   8591 #endif
   8592 #ifdef HAVE_CONFSTR
   8593     if (setup_confname_table(posix_constants_confstr,
   8594                              sizeof(posix_constants_confstr)
   8595                                / sizeof(struct constdef),
   8596                              "confstr_names", module))
   8597         return -1;
   8598 #endif
   8599 #ifdef HAVE_SYSCONF
   8600     if (setup_confname_table(posix_constants_sysconf,
   8601                              sizeof(posix_constants_sysconf)
   8602                                / sizeof(struct constdef),
   8603                              "sysconf_names", module))
   8604         return -1;
   8605 #endif
   8606     return 0;
   8607 }
   8608 
   8609 
   8610 PyDoc_STRVAR(posix_abort__doc__,
   8611 "abort() -> does not return!\n\n\
   8612 Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
   8613 in the hardest way possible on the hosting operating system.");
   8614 
   8615 static PyObject *
   8616 posix_abort(PyObject *self, PyObject *noargs)
   8617 {
   8618     abort();
   8619     /*NOTREACHED*/
   8620     Py_FatalError("abort() called from Python code didn't abort!");
   8621     return NULL;
   8622 }
   8623 
   8624 #ifdef MS_WINDOWS
   8625 PyDoc_STRVAR(win32_startfile__doc__,
   8626 "startfile(filepath [, operation]) - Start a file with its associated\n\
   8627 application.\n\
   8628 \n\
   8629 When \"operation\" is not specified or \"open\", this acts like\n\
   8630 double-clicking the file in Explorer, or giving the file name as an\n\
   8631 argument to the DOS \"start\" command: the file is opened with whatever\n\
   8632 application (if any) its extension is associated.\n\
   8633 When another \"operation\" is given, it specifies what should be done with\n\
   8634 the file.  A typical operation is \"print\".\n\
   8635 \n\
   8636 startfile returns as soon as the associated application is launched.\n\
   8637 There is no option to wait for the application to close, and no way\n\
   8638 to retrieve the application's exit status.\n\
   8639 \n\
   8640 The filepath is relative to the current directory.  If you want to use\n\
   8641 an absolute path, make sure the first character is not a slash (\"/\");\n\
   8642 the underlying Win32 ShellExecute function doesn't work if it is.");
   8643 
   8644 static PyObject *
   8645 win32_startfile(PyObject *self, PyObject *args)
   8646 {
   8647     char *filepath;
   8648     Py_UNICODE *wpath;
   8649     char *operation = NULL;
   8650     HINSTANCE rc;
   8651 
   8652     PyObject *woperation = NULL;
   8653     if (!PyArg_ParseTuple(args, "u|s:startfile",
   8654                           &wpath, &operation)) {
   8655         PyErr_Clear();
   8656         goto normal;
   8657     }
   8658 
   8659     if (operation) {
   8660         woperation = PyUnicode_DecodeASCII(operation,
   8661                                            strlen(operation), NULL);
   8662         if (!woperation) {
   8663             PyErr_Clear();
   8664             operation = NULL;
   8665             goto normal;
   8666         }
   8667     }
   8668 
   8669     Py_BEGIN_ALLOW_THREADS
   8670     rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0,
   8671         wpath,
   8672         NULL, NULL, SW_SHOWNORMAL);
   8673     Py_END_ALLOW_THREADS
   8674 
   8675     Py_XDECREF(woperation);
   8676     if (rc <= (HINSTANCE)32) {
   8677         PyObject *errval = win32_error_unicode("startfile", wpath);
   8678         return errval;
   8679     }
   8680     Py_INCREF(Py_None);
   8681     return Py_None;
   8682 
   8683 normal:
   8684     if (!PyArg_ParseTuple(args, "et|s:startfile",
   8685                           Py_FileSystemDefaultEncoding, &filepath,
   8686                           &operation))
   8687         return NULL;
   8688     Py_BEGIN_ALLOW_THREADS
   8689     rc = ShellExecute((HWND)0, operation, filepath,
   8690                       NULL, NULL, SW_SHOWNORMAL);
   8691     Py_END_ALLOW_THREADS
   8692     if (rc <= (HINSTANCE)32) {
   8693         PyObject *errval = win32_error("startfile", filepath);
   8694         PyMem_Free(filepath);
   8695         return errval;
   8696     }
   8697     PyMem_Free(filepath);
   8698     Py_INCREF(Py_None);
   8699     return Py_None;
   8700 }
   8701 #endif /* MS_WINDOWS */
   8702 
   8703 #ifdef HAVE_GETLOADAVG
   8704 PyDoc_STRVAR(posix_getloadavg__doc__,
   8705 "getloadavg() -> (float, float, float)\n\n\
   8706 Return the number of processes in the system run queue averaged over\n\
   8707 the last 1, 5, and 15 minutes or raises OSError if the load average\n\
   8708 was unobtainable");
   8709 
   8710 static PyObject *
   8711 posix_getloadavg(PyObject *self, PyObject *noargs)
   8712 {
   8713     double loadavg[3];
   8714     if (getloadavg(loadavg, 3)!=3) {
   8715         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
   8716         return NULL;
   8717     } else
   8718         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
   8719 }
   8720 #endif
   8721 
   8722 PyDoc_STRVAR(posix_urandom__doc__,
   8723 "urandom(n) -> str\n\n\
   8724 Return n random bytes suitable for cryptographic use.");
   8725 
   8726 static PyObject *
   8727 posix_urandom(PyObject *self, PyObject *args)
   8728 {
   8729     Py_ssize_t size;
   8730     PyObject *result;
   8731     int ret;
   8732 
   8733      /* Read arguments */
   8734     if (!PyArg_ParseTuple(args, "n:urandom", &size))
   8735         return NULL;
   8736     if (size < 0)
   8737         return PyErr_Format(PyExc_ValueError,
   8738                             "negative argument not allowed");
   8739     result = PyBytes_FromStringAndSize(NULL, size);
   8740     if (result == NULL)
   8741         return NULL;
   8742 
   8743     ret = _PyOS_URandom(PyBytes_AS_STRING(result),
   8744                         PyBytes_GET_SIZE(result));
   8745     if (ret == -1) {
   8746         Py_DECREF(result);
   8747         return NULL;
   8748     }
   8749     return result;
   8750 }
   8751 
   8752 #ifdef HAVE_SETRESUID
   8753 PyDoc_STRVAR(posix_setresuid__doc__,
   8754 "setresuid(ruid, euid, suid)\n\n\
   8755 Set the current process's real, effective, and saved user ids.");
   8756 
   8757 static PyObject*
   8758 posix_setresuid (PyObject *self, PyObject *args)
   8759 {
   8760     uid_t ruid, euid, suid;
   8761     if (!PyArg_ParseTuple(args, "O&O&O&:setresuid",
   8762                           _Py_Uid_Converter, &ruid,
   8763                           _Py_Uid_Converter, &euid,
   8764                           _Py_Uid_Converter, &suid))
   8765         return NULL;
   8766     if (setresuid(ruid, euid, suid) < 0)
   8767         return posix_error();
   8768     Py_RETURN_NONE;
   8769 }
   8770 #endif
   8771 
   8772 #ifdef HAVE_SETRESGID
   8773 PyDoc_STRVAR(posix_setresgid__doc__,
   8774 "setresgid(rgid, egid, sgid)\n\n\
   8775 Set the current process's real, effective, and saved group ids.");
   8776 
   8777 static PyObject*
   8778 posix_setresgid (PyObject *self, PyObject *args)
   8779 {
   8780     gid_t rgid, egid, sgid;
   8781     if (!PyArg_ParseTuple(args, "O&O&O&:setresgid",
   8782                           _Py_Gid_Converter, &rgid,
   8783                           _Py_Gid_Converter, &egid,
   8784                           _Py_Gid_Converter, &sgid))
   8785         return NULL;
   8786     if (setresgid(rgid, egid, sgid) < 0)
   8787         return posix_error();
   8788     Py_RETURN_NONE;
   8789 }
   8790 #endif
   8791 
   8792 #ifdef HAVE_GETRESUID
   8793 PyDoc_STRVAR(posix_getresuid__doc__,
   8794 "getresuid() -> (ruid, euid, suid)\n\n\
   8795 Get tuple of the current process's real, effective, and saved user ids.");
   8796 
   8797 static PyObject*
   8798 posix_getresuid (PyObject *self, PyObject *noargs)
   8799 {
   8800     uid_t ruid, euid, suid;
   8801     if (getresuid(&ruid, &euid, &suid) < 0)
   8802         return posix_error();
   8803     return Py_BuildValue("(NNN)", _PyInt_FromUid(ruid),
   8804                                   _PyInt_FromUid(euid),
   8805                                   _PyInt_FromUid(suid));
   8806 }
   8807 #endif
   8808 
   8809 #ifdef HAVE_GETRESGID
   8810 PyDoc_STRVAR(posix_getresgid__doc__,
   8811 "getresgid() -> (rgid, egid, sgid)\n\n\
   8812 Get tuple of the current process's real, effective, and saved group ids.");
   8813 
   8814 static PyObject*
   8815 posix_getresgid (PyObject *self, PyObject *noargs)
   8816 {
   8817     uid_t rgid, egid, sgid;
   8818     if (getresgid(&rgid, &egid, &sgid) < 0)
   8819         return posix_error();
   8820     return Py_BuildValue("(NNN)", _PyInt_FromGid(rgid),
   8821                                   _PyInt_FromGid(egid),
   8822                                   _PyInt_FromGid(sgid));
   8823 }
   8824 #endif
   8825 
   8826 static PyMethodDef posix_methods[] = {
   8827     {"access",          posix_access, METH_VARARGS, posix_access__doc__},
   8828 #ifdef HAVE_TTYNAME
   8829     {"ttyname",         posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
   8830 #endif
   8831     {"chdir",           posix_chdir, METH_VARARGS, posix_chdir__doc__},
   8832 #ifdef HAVE_CHFLAGS
   8833     {"chflags",         posix_chflags, METH_VARARGS, posix_chflags__doc__},
   8834 #endif /* HAVE_CHFLAGS */
   8835     {"chmod",           posix_chmod, METH_VARARGS, posix_chmod__doc__},
   8836 #ifdef HAVE_FCHMOD
   8837     {"fchmod",          posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
   8838 #endif /* HAVE_FCHMOD */
   8839 #ifdef HAVE_CHOWN
   8840     {"chown",           posix_chown, METH_VARARGS, posix_chown__doc__},
   8841 #endif /* HAVE_CHOWN */
   8842 #ifdef HAVE_LCHMOD
   8843     {"lchmod",          posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
   8844 #endif /* HAVE_LCHMOD */
   8845 #ifdef HAVE_FCHOWN
   8846     {"fchown",          posix_fchown, METH_VARARGS, posix_fchown__doc__},
   8847 #endif /* HAVE_FCHOWN */
   8848 #ifdef HAVE_LCHFLAGS
   8849     {"lchflags",        posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
   8850 #endif /* HAVE_LCHFLAGS */
   8851 #ifdef HAVE_LCHOWN
   8852     {"lchown",          posix_lchown, METH_VARARGS, posix_lchown__doc__},
   8853 #endif /* HAVE_LCHOWN */
   8854 #ifdef HAVE_CHROOT
   8855     {"chroot",          posix_chroot, METH_VARARGS, posix_chroot__doc__},
   8856 #endif
   8857 #ifdef HAVE_CTERMID
   8858     {"ctermid",         posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
   8859 #endif
   8860 #ifdef HAVE_GETCWD
   8861     {"getcwd",          posix_getcwd, METH_NOARGS, posix_getcwd__doc__},
   8862 #ifdef Py_USING_UNICODE
   8863     {"getcwdu",         posix_getcwdu, METH_NOARGS, posix_getcwdu__doc__},
   8864 #endif
   8865 #endif
   8866 #ifdef HAVE_LINK
   8867     {"link",            posix_link, METH_VARARGS, posix_link__doc__},
   8868 #endif /* HAVE_LINK */
   8869     {"listdir",         posix_listdir, METH_VARARGS, posix_listdir__doc__},
   8870     {"lstat",           posix_lstat, METH_VARARGS, posix_lstat__doc__},
   8871     {"mkdir",           posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
   8872 #ifdef HAVE_NICE
   8873     {"nice",            posix_nice, METH_VARARGS, posix_nice__doc__},
   8874 #endif /* HAVE_NICE */
   8875 #ifdef HAVE_READLINK
   8876     {"readlink",        posix_readlink, METH_VARARGS, posix_readlink__doc__},
   8877 #endif /* HAVE_READLINK */
   8878     {"rename",          posix_rename, METH_VARARGS, posix_rename__doc__},
   8879     {"rmdir",           posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
   8880     {"stat",            posix_stat, METH_VARARGS, posix_stat__doc__},
   8881     {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
   8882 #ifdef HAVE_SYMLINK
   8883     {"symlink",         posix_symlink, METH_VARARGS, posix_symlink__doc__},
   8884 #endif /* HAVE_SYMLINK */
   8885 #ifdef HAVE_SYSTEM
   8886     {"system",          posix_system, METH_VARARGS, posix_system__doc__},
   8887 #endif
   8888     {"umask",           posix_umask, METH_VARARGS, posix_umask__doc__},
   8889 #ifdef HAVE_UNAME
   8890     {"uname",           posix_uname, METH_NOARGS, posix_uname__doc__},
   8891 #endif /* HAVE_UNAME */
   8892     {"unlink",          posix_unlink, METH_VARARGS, posix_unlink__doc__},
   8893     {"remove",          posix_unlink, METH_VARARGS, posix_remove__doc__},
   8894     {"utime",           posix_utime, METH_VARARGS, posix_utime__doc__},
   8895 #ifdef HAVE_TIMES
   8896     {"times",           posix_times, METH_NOARGS, posix_times__doc__},
   8897 #endif /* HAVE_TIMES */
   8898     {"_exit",           posix__exit, METH_VARARGS, posix__exit__doc__},
   8899 #ifdef HAVE_EXECV
   8900     {"execv",           posix_execv, METH_VARARGS, posix_execv__doc__},
   8901     {"execve",          posix_execve, METH_VARARGS, posix_execve__doc__},
   8902 #endif /* HAVE_EXECV */
   8903 #ifdef HAVE_SPAWNV
   8904     {"spawnv",          posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
   8905     {"spawnve",         posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
   8906 #if defined(PYOS_OS2)
   8907     {"spawnvp",         posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
   8908     {"spawnvpe",        posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
   8909 #endif /* PYOS_OS2 */
   8910 #endif /* HAVE_SPAWNV */
   8911 #ifdef HAVE_FORK1
   8912     {"fork1",       posix_fork1, METH_NOARGS, posix_fork1__doc__},
   8913 #endif /* HAVE_FORK1 */
   8914 #ifdef HAVE_FORK
   8915     {"fork",            posix_fork, METH_NOARGS, posix_fork__doc__},
   8916 #endif /* HAVE_FORK */
   8917 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
   8918     {"openpty",         posix_openpty, METH_NOARGS, posix_openpty__doc__},
   8919 #endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
   8920 #ifdef HAVE_FORKPTY
   8921     {"forkpty",         posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
   8922 #endif /* HAVE_FORKPTY */
   8923 #ifdef HAVE_GETEGID
   8924     {"getegid",         posix_getegid, METH_NOARGS, posix_getegid__doc__},
   8925 #endif /* HAVE_GETEGID */
   8926 #ifdef HAVE_GETEUID
   8927     {"geteuid",         posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
   8928 #endif /* HAVE_GETEUID */
   8929 #ifdef HAVE_GETGID
   8930     {"getgid",          posix_getgid, METH_NOARGS, posix_getgid__doc__},
   8931 #endif /* HAVE_GETGID */
   8932 #ifdef HAVE_GETGROUPS
   8933     {"getgroups",       posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
   8934 #endif
   8935     {"getpid",          posix_getpid, METH_NOARGS, posix_getpid__doc__},
   8936 #ifdef HAVE_GETPGRP
   8937     {"getpgrp",         posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
   8938 #endif /* HAVE_GETPGRP */
   8939 #ifdef HAVE_GETPPID
   8940     {"getppid",         posix_getppid, METH_NOARGS, posix_getppid__doc__},
   8941 #endif /* HAVE_GETPPID */
   8942 #ifdef HAVE_GETUID
   8943     {"getuid",          posix_getuid, METH_NOARGS, posix_getuid__doc__},
   8944 #endif /* HAVE_GETUID */
   8945 #ifdef HAVE_GETLOGIN
   8946     {"getlogin",        posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
   8947 #endif
   8948 #ifdef HAVE_KILL
   8949     {"kill",            posix_kill, METH_VARARGS, posix_kill__doc__},
   8950 #endif /* HAVE_KILL */
   8951 #ifdef HAVE_KILLPG
   8952     {"killpg",          posix_killpg, METH_VARARGS, posix_killpg__doc__},
   8953 #endif /* HAVE_KILLPG */
   8954 #ifdef HAVE_PLOCK
   8955     {"plock",           posix_plock, METH_VARARGS, posix_plock__doc__},
   8956 #endif /* HAVE_PLOCK */
   8957 #ifdef HAVE_POPEN
   8958     {"popen",           posix_popen, METH_VARARGS, posix_popen__doc__},
   8959 #ifdef MS_WINDOWS
   8960     {"popen2",          win32_popen2, METH_VARARGS},
   8961     {"popen3",          win32_popen3, METH_VARARGS},
   8962     {"popen4",          win32_popen4, METH_VARARGS},
   8963     {"startfile",       win32_startfile, METH_VARARGS, win32_startfile__doc__},
   8964     {"kill",    win32_kill, METH_VARARGS, win32_kill__doc__},
   8965 #else
   8966 #if defined(PYOS_OS2) && defined(PYCC_GCC)
   8967     {"popen2",          os2emx_popen2, METH_VARARGS},
   8968     {"popen3",          os2emx_popen3, METH_VARARGS},
   8969     {"popen4",          os2emx_popen4, METH_VARARGS},
   8970 #endif
   8971 #endif
   8972 #endif /* HAVE_POPEN */
   8973 #ifdef HAVE_SETUID
   8974     {"setuid",          posix_setuid, METH_VARARGS, posix_setuid__doc__},
   8975 #endif /* HAVE_SETUID */
   8976 #ifdef HAVE_SETEUID
   8977     {"seteuid",         posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
   8978 #endif /* HAVE_SETEUID */
   8979 #ifdef HAVE_SETEGID
   8980     {"setegid",         posix_setegid, METH_VARARGS, posix_setegid__doc__},
   8981 #endif /* HAVE_SETEGID */
   8982 #ifdef HAVE_SETREUID
   8983     {"setreuid",        posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
   8984 #endif /* HAVE_SETREUID */
   8985 #ifdef HAVE_SETREGID
   8986     {"setregid",        posix_setregid, METH_VARARGS, posix_setregid__doc__},
   8987 #endif /* HAVE_SETREGID */
   8988 #ifdef HAVE_SETGID
   8989     {"setgid",          posix_setgid, METH_VARARGS, posix_setgid__doc__},
   8990 #endif /* HAVE_SETGID */
   8991 #ifdef HAVE_SETGROUPS
   8992     {"setgroups",       posix_setgroups, METH_O, posix_setgroups__doc__},
   8993 #endif /* HAVE_SETGROUPS */
   8994 #ifdef HAVE_INITGROUPS
   8995     {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
   8996 #endif /* HAVE_INITGROUPS */
   8997 #ifdef HAVE_GETPGID
   8998     {"getpgid",         posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
   8999 #endif /* HAVE_GETPGID */
   9000 #ifdef HAVE_SETPGRP
   9001     {"setpgrp",         posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
   9002 #endif /* HAVE_SETPGRP */
   9003 #ifdef HAVE_WAIT
   9004     {"wait",            posix_wait, METH_NOARGS, posix_wait__doc__},
   9005 #endif /* HAVE_WAIT */
   9006 #ifdef HAVE_WAIT3
   9007     {"wait3",           posix_wait3, METH_VARARGS, posix_wait3__doc__},
   9008 #endif /* HAVE_WAIT3 */
   9009 #ifdef HAVE_WAIT4
   9010     {"wait4",           posix_wait4, METH_VARARGS, posix_wait4__doc__},
   9011 #endif /* HAVE_WAIT4 */
   9012 #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
   9013     {"waitpid",         posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
   9014 #endif /* HAVE_WAITPID */
   9015 #ifdef HAVE_GETSID
   9016     {"getsid",          posix_getsid, METH_VARARGS, posix_getsid__doc__},
   9017 #endif /* HAVE_GETSID */
   9018 #ifdef HAVE_SETSID
   9019     {"setsid",          posix_setsid, METH_NOARGS, posix_setsid__doc__},
   9020 #endif /* HAVE_SETSID */
   9021 #ifdef HAVE_SETPGID
   9022     {"setpgid",         posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
   9023 #endif /* HAVE_SETPGID */
   9024 #ifdef HAVE_TCGETPGRP
   9025     {"tcgetpgrp",       posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
   9026 #endif /* HAVE_TCGETPGRP */
   9027 #ifdef HAVE_TCSETPGRP
   9028     {"tcsetpgrp",       posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
   9029 #endif /* HAVE_TCSETPGRP */
   9030     {"open",            posix_open, METH_VARARGS, posix_open__doc__},
   9031     {"close",           posix_close_, METH_VARARGS, posix_close__doc__},
   9032     {"closerange",      posix_closerange, METH_VARARGS, posix_closerange__doc__},
   9033     {"dup",             posix_dup, METH_VARARGS, posix_dup__doc__},
   9034     {"dup2",            posix_dup2, METH_VARARGS, posix_dup2__doc__},
   9035     {"lseek",           posix_lseek, METH_VARARGS, posix_lseek__doc__},
   9036     {"read",            posix_read, METH_VARARGS, posix_read__doc__},
   9037     {"write",           posix_write, METH_VARARGS, posix_write__doc__},
   9038     {"fstat",           posix_fstat, METH_VARARGS, posix_fstat__doc__},
   9039     {"fdopen",          posix_fdopen, METH_VARARGS, posix_fdopen__doc__},
   9040     {"isatty",          posix_isatty, METH_VARARGS, posix_isatty__doc__},
   9041 #ifdef HAVE_PIPE
   9042     {"pipe",            posix_pipe, METH_NOARGS, posix_pipe__doc__},
   9043 #endif
   9044 #ifdef HAVE_MKFIFO
   9045     {"mkfifo",          posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
   9046 #endif
   9047 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
   9048     {"mknod",           posix_mknod, METH_VARARGS, posix_mknod__doc__},
   9049 #endif
   9050 #ifdef HAVE_DEVICE_MACROS
   9051     {"major",           posix_major, METH_VARARGS, posix_major__doc__},
   9052     {"minor",           posix_minor, METH_VARARGS, posix_minor__doc__},
   9053     {"makedev",         posix_makedev, METH_VARARGS, posix_makedev__doc__},
   9054 #endif
   9055 #ifdef HAVE_FTRUNCATE
   9056     {"ftruncate",       posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
   9057 #endif
   9058 #ifdef HAVE_PUTENV
   9059     {"putenv",          posix_putenv, METH_VARARGS, posix_putenv__doc__},
   9060 #endif
   9061 #ifdef HAVE_UNSETENV
   9062     {"unsetenv",        posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
   9063 #endif
   9064     {"strerror",        posix_strerror, METH_VARARGS, posix_strerror__doc__},
   9065 #ifdef HAVE_FCHDIR
   9066     {"fchdir",          posix_fchdir, METH_O, posix_fchdir__doc__},
   9067 #endif
   9068 #ifdef HAVE_FSYNC
   9069     {"fsync",       posix_fsync, METH_O, posix_fsync__doc__},
   9070 #endif
   9071 #ifdef HAVE_FDATASYNC
   9072     {"fdatasync",   posix_fdatasync,  METH_O, posix_fdatasync__doc__},
   9073 #endif
   9074 #ifdef HAVE_SYS_WAIT_H
   9075 #ifdef WCOREDUMP
   9076     {"WCOREDUMP",       posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
   9077 #endif /* WCOREDUMP */
   9078 #ifdef WIFCONTINUED
   9079     {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
   9080 #endif /* WIFCONTINUED */
   9081 #ifdef WIFSTOPPED
   9082     {"WIFSTOPPED",      posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
   9083 #endif /* WIFSTOPPED */
   9084 #ifdef WIFSIGNALED
   9085     {"WIFSIGNALED",     posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
   9086 #endif /* WIFSIGNALED */
   9087 #ifdef WIFEXITED
   9088     {"WIFEXITED",       posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
   9089 #endif /* WIFEXITED */
   9090 #ifdef WEXITSTATUS
   9091     {"WEXITSTATUS",     posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
   9092 #endif /* WEXITSTATUS */
   9093 #ifdef WTERMSIG
   9094     {"WTERMSIG",        posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
   9095 #endif /* WTERMSIG */
   9096 #ifdef WSTOPSIG
   9097     {"WSTOPSIG",        posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
   9098 #endif /* WSTOPSIG */
   9099 #endif /* HAVE_SYS_WAIT_H */
   9100 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
   9101     {"fstatvfs",        posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
   9102 #endif
   9103 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
   9104     {"statvfs",         posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
   9105 #endif
   9106 #ifdef HAVE_TMPFILE
   9107     {"tmpfile",         posix_tmpfile, METH_NOARGS, posix_tmpfile__doc__},
   9108 #endif
   9109 #ifdef HAVE_TEMPNAM
   9110     {"tempnam",         posix_tempnam, METH_VARARGS, posix_tempnam__doc__},
   9111 #endif
   9112 #ifdef HAVE_TMPNAM
   9113     {"tmpnam",          posix_tmpnam, METH_NOARGS, posix_tmpnam__doc__},
   9114 #endif
   9115 #ifdef HAVE_CONFSTR
   9116     {"confstr",         posix_confstr, METH_VARARGS, posix_confstr__doc__},
   9117 #endif
   9118 #ifdef HAVE_SYSCONF
   9119     {"sysconf",         posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
   9120 #endif
   9121 #ifdef HAVE_FPATHCONF
   9122     {"fpathconf",       posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
   9123 #endif
   9124 #ifdef HAVE_PATHCONF
   9125     {"pathconf",        posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
   9126 #endif
   9127     {"abort",           posix_abort, METH_NOARGS, posix_abort__doc__},
   9128 #ifdef MS_WINDOWS
   9129     {"_getfullpathname",        posix__getfullpathname, METH_VARARGS, NULL},
   9130     {"_isdir",                  posix__isdir, METH_VARARGS, posix__isdir__doc__},
   9131 #endif
   9132 #ifdef HAVE_GETLOADAVG
   9133     {"getloadavg",      posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
   9134 #endif
   9135 #ifdef HAVE_SETRESUID
   9136     {"setresuid",       posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
   9137 #endif
   9138 #ifdef HAVE_SETRESGID
   9139     {"setresgid",       posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
   9140 #endif
   9141 #ifdef HAVE_GETRESUID
   9142     {"getresuid",       posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
   9143 #endif
   9144 #ifdef HAVE_GETRESGID
   9145     {"getresgid",       posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
   9146 #endif
   9147     {"urandom",         posix_urandom,   METH_VARARGS, posix_urandom__doc__},
   9148     {NULL,              NULL}            /* Sentinel */
   9149 };
   9150 
   9151 
   9152 static int
   9153 ins(PyObject *module, char *symbol, long value)
   9154 {
   9155     return PyModule_AddIntConstant(module, symbol, value);
   9156 }
   9157 
   9158 #if defined(PYOS_OS2)
   9159 /* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
   9160 static int insertvalues(PyObject *module)
   9161 {
   9162     APIRET    rc;
   9163     ULONG     values[QSV_MAX+1];
   9164     PyObject *v;
   9165     char     *ver, tmp[50];
   9166 
   9167     Py_BEGIN_ALLOW_THREADS
   9168     rc = DosQuerySysInfo(1L, QSV_MAX, &values[1], sizeof(ULONG) * QSV_MAX);
   9169     Py_END_ALLOW_THREADS
   9170 
   9171     if (rc != NO_ERROR) {
   9172         os2_error(rc);
   9173         return -1;
   9174     }
   9175 
   9176     if (ins(module, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
   9177     if (ins(module, "memkernel",    values[QSV_TOTRESMEM])) return -1;
   9178     if (ins(module, "memvirtual",   values[QSV_TOTAVAILMEM])) return -1;
   9179     if (ins(module, "maxpathlen",   values[QSV_MAX_PATH_LENGTH])) return -1;
   9180     if (ins(module, "maxnamelen",   values[QSV_MAX_COMP_LENGTH])) return -1;
   9181     if (ins(module, "revision",     values[QSV_VERSION_REVISION])) return -1;
   9182     if (ins(module, "timeslice",    values[QSV_MIN_SLICE])) return -1;
   9183 
   9184     switch (values[QSV_VERSION_MINOR]) {
   9185     case 0:  ver = "2.00"; break;
   9186     case 10: ver = "2.10"; break;
   9187     case 11: ver = "2.11"; break;
   9188     case 30: ver = "3.00"; break;
   9189     case 40: ver = "4.00"; break;
   9190     case 50: ver = "5.00"; break;
   9191     default:
   9192         PyOS_snprintf(tmp, sizeof(tmp),
   9193                       "%d-%d", values[QSV_VERSION_MAJOR],
   9194                       values[QSV_VERSION_MINOR]);
   9195         ver = &tmp[0];
   9196     }
   9197 
   9198     /* Add Indicator of the Version of the Operating System */
   9199     if (PyModule_AddStringConstant(module, "version", tmp) < 0)
   9200         return -1;
   9201 
   9202     /* Add Indicator of Which Drive was Used to Boot the System */
   9203     tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
   9204     tmp[1] = ':';
   9205     tmp[2] = '\0';
   9206 
   9207     return PyModule_AddStringConstant(module, "bootdrive", tmp);
   9208 }
   9209 #endif
   9210 
   9211 static int
   9212 all_ins(PyObject *d)
   9213 {
   9214 #ifdef F_OK
   9215     if (ins(d, "F_OK", (long)F_OK)) return -1;
   9216 #endif
   9217 #ifdef R_OK
   9218     if (ins(d, "R_OK", (long)R_OK)) return -1;
   9219 #endif
   9220 #ifdef W_OK
   9221     if (ins(d, "W_OK", (long)W_OK)) return -1;
   9222 #endif
   9223 #ifdef X_OK
   9224     if (ins(d, "X_OK", (long)X_OK)) return -1;
   9225 #endif
   9226 #ifdef NGROUPS_MAX
   9227     if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
   9228 #endif
   9229 #ifdef TMP_MAX
   9230     if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
   9231 #endif
   9232 #ifdef WCONTINUED
   9233     if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
   9234 #endif
   9235 #ifdef WNOHANG
   9236     if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
   9237 #endif
   9238 #ifdef WUNTRACED
   9239     if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
   9240 #endif
   9241 #ifdef O_RDONLY
   9242     if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
   9243 #endif
   9244 #ifdef O_WRONLY
   9245     if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
   9246 #endif
   9247 #ifdef O_RDWR
   9248     if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
   9249 #endif
   9250 #ifdef O_NDELAY
   9251     if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
   9252 #endif
   9253 #ifdef O_NONBLOCK
   9254     if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
   9255 #endif
   9256 #ifdef O_APPEND
   9257     if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
   9258 #endif
   9259 #ifdef O_DSYNC
   9260     if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
   9261 #endif
   9262 #ifdef O_RSYNC
   9263     if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
   9264 #endif
   9265 #ifdef O_SYNC
   9266     if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
   9267 #endif
   9268 #ifdef O_NOCTTY
   9269     if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
   9270 #endif
   9271 #ifdef O_CREAT
   9272     if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
   9273 #endif
   9274 #ifdef O_EXCL
   9275     if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
   9276 #endif
   9277 #ifdef O_TRUNC
   9278     if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
   9279 #endif
   9280 #ifdef O_BINARY
   9281     if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
   9282 #endif
   9283 #ifdef O_TEXT
   9284     if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
   9285 #endif
   9286 #ifdef O_LARGEFILE
   9287     if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
   9288 #endif
   9289 #ifdef O_SHLOCK
   9290     if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
   9291 #endif
   9292 #ifdef O_EXLOCK
   9293     if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
   9294 #endif
   9295 
   9296 /* MS Windows */
   9297 #ifdef O_NOINHERIT
   9298     /* Don't inherit in child processes. */
   9299     if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
   9300 #endif
   9301 #ifdef _O_SHORT_LIVED
   9302     /* Optimize for short life (keep in memory). */
   9303     /* MS forgot to define this one with a non-underscore form too. */
   9304     if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
   9305 #endif
   9306 #ifdef O_TEMPORARY
   9307     /* Automatically delete when last handle is closed. */
   9308     if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
   9309 #endif
   9310 #ifdef O_RANDOM
   9311     /* Optimize for random access. */
   9312     if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
   9313 #endif
   9314 #ifdef O_SEQUENTIAL
   9315     /* Optimize for sequential access. */
   9316     if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
   9317 #endif
   9318 
   9319 /* GNU extensions. */
   9320 #ifdef O_ASYNC
   9321     /* Send a SIGIO signal whenever input or output
   9322        becomes available on file descriptor */
   9323     if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
   9324 #endif
   9325 #ifdef O_DIRECT
   9326     /* Direct disk access. */
   9327     if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
   9328 #endif
   9329 #ifdef O_DIRECTORY
   9330     /* Must be a directory.      */
   9331     if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
   9332 #endif
   9333 #ifdef O_NOFOLLOW
   9334     /* Do not follow links.      */
   9335     if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
   9336 #endif
   9337 #ifdef O_NOATIME
   9338     /* Do not update the access time. */
   9339     if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
   9340 #endif
   9341 
   9342     /* These come from sysexits.h */
   9343 #ifdef EX_OK
   9344     if (ins(d, "EX_OK", (long)EX_OK)) return -1;
   9345 #endif /* EX_OK */
   9346 #ifdef EX_USAGE
   9347     if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
   9348 #endif /* EX_USAGE */
   9349 #ifdef EX_DATAERR
   9350     if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
   9351 #endif /* EX_DATAERR */
   9352 #ifdef EX_NOINPUT
   9353     if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
   9354 #endif /* EX_NOINPUT */
   9355 #ifdef EX_NOUSER
   9356     if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
   9357 #endif /* EX_NOUSER */
   9358 #ifdef EX_NOHOST
   9359     if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
   9360 #endif /* EX_NOHOST */
   9361 #ifdef EX_UNAVAILABLE
   9362     if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
   9363 #endif /* EX_UNAVAILABLE */
   9364 #ifdef EX_SOFTWARE
   9365     if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
   9366 #endif /* EX_SOFTWARE */
   9367 #ifdef EX_OSERR
   9368     if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
   9369 #endif /* EX_OSERR */
   9370 #ifdef EX_OSFILE
   9371     if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
   9372 #endif /* EX_OSFILE */
   9373 #ifdef EX_CANTCREAT
   9374     if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
   9375 #endif /* EX_CANTCREAT */
   9376 #ifdef EX_IOERR
   9377     if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
   9378 #endif /* EX_IOERR */
   9379 #ifdef EX_TEMPFAIL
   9380     if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
   9381 #endif /* EX_TEMPFAIL */
   9382 #ifdef EX_PROTOCOL
   9383     if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
   9384 #endif /* EX_PROTOCOL */
   9385 #ifdef EX_NOPERM
   9386     if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
   9387 #endif /* EX_NOPERM */
   9388 #ifdef EX_CONFIG
   9389     if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
   9390 #endif /* EX_CONFIG */
   9391 #ifdef EX_NOTFOUND
   9392     if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
   9393 #endif /* EX_NOTFOUND */
   9394 
   9395 #ifdef HAVE_SPAWNV
   9396 #if defined(PYOS_OS2) && defined(PYCC_GCC)
   9397     if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
   9398     if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
   9399     if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
   9400     if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
   9401     if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
   9402     if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
   9403     if (ins(d, "P_PM", (long)P_PM)) return -1;
   9404     if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
   9405     if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
   9406     if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
   9407     if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
   9408     if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
   9409     if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
   9410     if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
   9411     if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
   9412     if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
   9413     if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
   9414     if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
   9415     if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
   9416     if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
   9417 #else
   9418     if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
   9419     if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
   9420     if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
   9421     if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
   9422     if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
   9423 #endif
   9424 #endif
   9425 
   9426 #if defined(PYOS_OS2)
   9427     if (insertvalues(d)) return -1;
   9428 #endif
   9429     return 0;
   9430 }
   9431 
   9432 
   9433 #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
   9434 #define INITFUNC initnt
   9435 #define MODNAME "nt"
   9436 
   9437 #elif defined(PYOS_OS2)
   9438 #define INITFUNC initos2
   9439 #define MODNAME "os2"
   9440 
   9441 #else
   9442 #define INITFUNC initposix
   9443 #define MODNAME "posix"
   9444 #endif
   9445 
   9446 PyMODINIT_FUNC
   9447 INITFUNC(void)
   9448 {
   9449     PyObject *m, *v;
   9450 
   9451     m = Py_InitModule3(MODNAME,
   9452                        posix_methods,
   9453                        posix__doc__);
   9454     if (m == NULL)
   9455         return;
   9456 
   9457     /* Initialize environ dictionary */
   9458     v = convertenviron();
   9459     Py_XINCREF(v);
   9460     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
   9461         return;
   9462     Py_DECREF(v);
   9463 
   9464     if (all_ins(m))
   9465         return;
   9466 
   9467     if (setup_confname_tables(m))
   9468         return;
   9469 
   9470     Py_INCREF(PyExc_OSError);
   9471     PyModule_AddObject(m, "error", PyExc_OSError);
   9472 
   9473 #ifdef HAVE_PUTENV
   9474     if (posix_putenv_garbage == NULL)
   9475         posix_putenv_garbage = PyDict_New();
   9476 #endif
   9477 
   9478     if (!initialized) {
   9479         stat_result_desc.name = MODNAME ".stat_result";
   9480         stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
   9481         stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
   9482         stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
   9483         PyStructSequence_InitType(&StatResultType, &stat_result_desc);
   9484         structseq_new = StatResultType.tp_new;
   9485         StatResultType.tp_new = statresult_new;
   9486 
   9487         statvfs_result_desc.name = MODNAME ".statvfs_result";
   9488         PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
   9489 #ifdef NEED_TICKS_PER_SECOND
   9490 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
   9491         ticks_per_second = sysconf(_SC_CLK_TCK);
   9492 #  elif defined(HZ)
   9493         ticks_per_second = HZ;
   9494 #  else
   9495         ticks_per_second = 60; /* magic fallback value; may be bogus */
   9496 #  endif
   9497 #endif
   9498     }
   9499     Py_INCREF((PyObject*) &StatResultType);
   9500     PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
   9501     Py_INCREF((PyObject*) &StatVFSResultType);
   9502     PyModule_AddObject(m, "statvfs_result",
   9503                        (PyObject*) &StatVFSResultType);
   9504     initialized = 1;
   9505 
   9506 #ifdef __APPLE__
   9507     /*
   9508      * Step 2 of weak-linking support on Mac OS X.
   9509      *
   9510      * The code below removes functions that are not available on the
   9511      * currently active platform.
   9512      *
   9513      * This block allow one to use a python binary that was build on
   9514      * OSX 10.4 on OSX 10.3, without loosing access to new APIs on
   9515      * OSX 10.4.
   9516      */
   9517 #ifdef HAVE_FSTATVFS
   9518     if (fstatvfs == NULL) {
   9519         if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
   9520             return;
   9521         }
   9522     }
   9523 #endif /* HAVE_FSTATVFS */
   9524 
   9525 #ifdef HAVE_STATVFS
   9526     if (statvfs == NULL) {
   9527         if (PyObject_DelAttrString(m, "statvfs") == -1) {
   9528             return;
   9529         }
   9530     }
   9531 #endif /* HAVE_STATVFS */
   9532 
   9533 # ifdef HAVE_LCHOWN
   9534     if (lchown == NULL) {
   9535         if (PyObject_DelAttrString(m, "lchown") == -1) {
   9536             return;
   9537         }
   9538     }
   9539 #endif /* HAVE_LCHOWN */
   9540 
   9541 
   9542 #endif /* __APPLE__ */
   9543 
   9544 }
   9545 
   9546 #ifdef __cplusplus
   9547 }
   9548 #endif
   9549 
   9550 
   9551