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
39extern "C" {
40#endif
41
42PyDoc_STRVAR(posix__doc__,
43"This module provides access to operating system functionality that is\n\
44standardized by the C Standard and the POSIX standard (a thinly\n\
45disguised Unix interface).  Refer to the library manual and\n\
46corresponding 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) */
170extern char        *ctermid_r(char *);
171#endif
172
173#ifndef HAVE_UNISTD_H
174#if defined(PYCC_VACPP)
175extern int mkdir(char *);
176#else
177#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
178extern int mkdir(const char *);
179#else
180extern int mkdir(const char *, mode_t);
181#endif
182#endif
183#if defined(__IBMC__) || defined(__IBMCPP__)
184extern int chdir(char *);
185extern int rmdir(char *);
186#else
187extern int chdir(const char *);
188extern int rmdir(const char *);
189#endif
190#ifdef __BORLANDC__
191extern int chmod(const char *, int);
192#else
193extern int chmod(const char *, mode_t);
194#endif
195/*#ifdef HAVE_FCHMOD
196extern int fchmod(int, mode_t);
197#endif*/
198/*#ifdef HAVE_LCHMOD
199extern int lchmod(const char *, mode_t);
200#endif*/
201extern int chown(const char *, uid_t, gid_t);
202extern char *getcwd(char *, int);
203extern char *strerror(int);
204extern int link(const char *, const char *);
205extern int rename(const char *, const char *);
206extern int stat(const char *, struct stat *);
207extern int unlink(const char *);
208extern int pclose(FILE *);
209#ifdef HAVE_SYMLINK
210extern int symlink(const char *, const char *);
211#endif /* HAVE_SYMLINK */
212#ifdef HAVE_LSTAT
213extern 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
355PyObject *
356_PyInt_FromUid(uid_t uid)
357{
358    if (uid <= LONG_MAX)
359        return PyInt_FromLong(uid);
360    return PyLong_FromUnsignedLong(uid);
361}
362
363PyObject *
364_PyInt_FromGid(gid_t gid)
365{
366    if (gid <= LONG_MAX)
367        return PyInt_FromLong(gid);
368    return PyLong_FromUnsignedLong(gid);
369}
370
371int
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
412OverflowDown:
413    PyErr_SetString(PyExc_OverflowError,
414                    "user id is less than minimum");
415    return 0;
416
417OverflowUp:
418    PyErr_SetString(PyExc_OverflowError,
419                    "user id is greater than maximum");
420    return 0;
421}
422
423int
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
464OverflowDown:
465    PyErr_SetString(PyExc_OverflowError,
466                    "group id is less than minimum");
467    return 0;
468
469OverflowUp:
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)
478static 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
519static 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 */
556typedef struct {
557    intptr_t osfhnd;
558    char osfile;
559} my_ioinfo;
560
561extern __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 */
570int
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 */
608static 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>
632static char **environ;
633#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
634extern char **environ;
635#endif /* !_MSC_VER */
636
637static PyObject *
638convertenviron(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
700static PyObject *
701posix_error(void)
702{
703    return PyErr_SetFromErrno(PyExc_OSError);
704}
705static PyObject *
706posix_error_with_filename(char* name)
707{
708    return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
709}
710
711#ifdef MS_WINDOWS
712static PyObject *
713posix_error_with_unicode_filename(Py_UNICODE* name)
714{
715    return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name);
716}
717#endif /* MS_WINDOWS */
718
719
720static PyObject *
721posix_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
729static PyObject *
730win32_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
744static PyObject *
745win32_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
755static int
756convert_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 **********************************************************************/
778static void
779os2_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 **********************************************************************/
808static char *
809os2_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
833static PyObject *
834os2_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
853static PyObject *
854posix_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
872static PyObject *
873posix_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
890static PyObject *
891posix_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
914static PyObject*
915win32_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>: */
951static BOOL __stdcall
952win32_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 */
976static BOOL __stdcall
977win32_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
1035struct 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
1052static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
1053
1054static void
1055FILE_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
1066static void
1067time_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
1080static int
1081attributes_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
1095static int
1096attribute_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
1108static BOOL
1109attributes_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
1126static BOOL
1127attributes_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
1144static int
1145win32_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
1181static int
1182win32_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
1218static int
1219win32_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
1274PyDoc_STRVAR(stat_result__doc__,
1275"stat_result: Result from stat or lstat.\n\n\
1276This object may be accessed either as a tuple of\n\
1277  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1278or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1279\n\
1280Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1281or st_flags, they are available as attributes only.\n\
1282\n\
1283See os.stat for more information.");
1284
1285static 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
1357static PyStructSequence_Desc stat_result_desc = {
1358    "stat_result", /* name */
1359    stat_result__doc__, /* doc */
1360    stat_result_fields,
1361    10
1362};
1363
1364PyDoc_STRVAR(statvfs_result__doc__,
1365"statvfs_result: Result from statvfs or fstatvfs.\n\n\
1366This object may be accessed either as a tuple of\n\
1367  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1368or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1369\n\
1370See os.statvfs for more information.");
1371
1372static 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
1386static PyStructSequence_Desc statvfs_result_desc = {
1387    "statvfs_result", /* name */
1388    statvfs_result__doc__, /* doc */
1389    statvfs_result_fields,
1390    10
1391};
1392
1393static int initialized;
1394static PyTypeObject StatResultType;
1395static PyTypeObject StatVFSResultType;
1396static newfunc structseq_new;
1397
1398static PyObject *
1399statresult_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. */
1423static int _stat_float_times = 1;
1424
1425PyDoc_STRVAR(stat_float_times__doc__,
1426"stat_float_times([newval]) -> oldval\n\n\
1427Determine whether os.[lf]stat represents time stamps as float objects.\n\
1428If newval is True, future calls to stat() return floats, if it is False,\n\
1429future calls return ints. \n\
1430If newval is omitted, return the current setting.\n");
1431
1432static PyObject*
1433stat_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
1446static void
1447fill_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()) */
1469static 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
1584static BOOL
1585IsUNCRootA(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
1607static BOOL
1608IsUNCRootW(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
1631static PyObject *
1632posix_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
1689PyDoc_STRVAR(posix_access__doc__,
1690"access(path, mode) -> True if granted, False otherwise\n\n\
1691Use the real uid/gid to test for access to a path.  Note that most\n\
1692operations will use the effective uid/gid, therefore this routine can\n\
1693be used in a suid/sgid environment to test if the invoking user has the\n\
1694specified access to the path.  The mode argument can be F_OK to test\n\
1695existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
1696
1697static PyObject *
1698posix_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);
1722finish:
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
1759PyDoc_STRVAR(posix_ttyname__doc__,
1760"ttyname(fd) -> string\n\n\
1761Return the name of the terminal device connected to 'fd'.");
1762
1763static PyObject *
1764posix_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
1790PyDoc_STRVAR(posix_ctermid__doc__,
1791"ctermid() -> string\n\n\
1792Return the name of the controlling terminal for this process.");
1793
1794static PyObject *
1795posix_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
1811PyDoc_STRVAR(posix_chdir__doc__,
1812"chdir(path)\n\n\
1813Change the current working directory to the specified path.");
1814
1815static PyObject *
1816posix_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
1830PyDoc_STRVAR(posix_fchdir__doc__,
1831"fchdir(fildes)\n\n\
1832Change to the directory of the given file descriptor.  fildes must be\n\
1833opened on a directory, not a file.");
1834
1835static PyObject *
1836posix_fchdir(PyObject *self, PyObject *fdobj)
1837{
1838    return posix_fildes(fdobj, fchdir);
1839}
1840#endif /* HAVE_FCHDIR */
1841
1842
1843PyDoc_STRVAR(posix_chmod__doc__,
1844"chmod(path, mode)\n\n\
1845Change the access permissions of a file.");
1846
1847static PyObject *
1848posix_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
1917PyDoc_STRVAR(posix_fchmod__doc__,
1918"fchmod(fd, mode)\n\n\
1919Change the access permissions of the file given by file\n\
1920descriptor fd.");
1921
1922static PyObject *
1923posix_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
1938PyDoc_STRVAR(posix_lchmod__doc__,
1939"lchmod(path, mode)\n\n\
1940Change the access permissions of a file. If path is a symlink, this\n\
1941affects the link itself rather than the target.");
1942
1943static PyObject *
1944posix_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
1964PyDoc_STRVAR(posix_chflags__doc__,
1965"chflags(path, flags)\n\n\
1966Set file flags.");
1967
1968static PyObject *
1969posix_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
1989PyDoc_STRVAR(posix_lchflags__doc__,
1990"lchflags(path, flags)\n\n\
1991Set file flags.\n\
1992This function will not follow symbolic links.");
1993
1994static PyObject *
1995posix_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
2015PyDoc_STRVAR(posix_chroot__doc__,
2016"chroot(path)\n\n\
2017Change root directory to path.");
2018
2019static PyObject *
2020posix_chroot(PyObject *self, PyObject *args)
2021{
2022    return posix_1str(args, "et:chroot", chroot);
2023}
2024#endif
2025
2026#ifdef HAVE_FSYNC
2027PyDoc_STRVAR(posix_fsync__doc__,
2028"fsync(fildes)\n\n\
2029force write of file with filedescriptor to disk.");
2030
2031static PyObject *
2032posix_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
2041extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
2042#endif
2043
2044PyDoc_STRVAR(posix_fdatasync__doc__,
2045"fdatasync(fildes)\n\n\
2046force write of file with filedescriptor to disk.\n\
2047 does not force update of metadata.");
2048
2049static PyObject *
2050posix_fdatasync(PyObject *self, PyObject *fdobj)
2051{
2052    return posix_fildes(fdobj, fdatasync);
2053}
2054#endif /* HAVE_FDATASYNC */
2055
2056
2057#ifdef HAVE_CHOWN
2058PyDoc_STRVAR(posix_chown__doc__,
2059"chown(path, uid, gid)\n\n\
2060Change the owner and group id of path to the numeric uid and gid.");
2061
2062static PyObject *
2063posix_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
2086PyDoc_STRVAR(posix_fchown__doc__,
2087"fchown(fd, uid, gid)\n\n\
2088Change the owner and group id of the file given by file descriptor\n\
2089fd to the numeric uid and gid.");
2090
2091static PyObject *
2092posix_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
2112PyDoc_STRVAR(posix_lchown__doc__,
2113"lchown(path, uid, gid)\n\n\
2114Change the owner and group id of path to the numeric uid and gid.\n\
2115This function will not follow symbolic links.");
2116
2117static PyObject *
2118posix_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
2142PyDoc_STRVAR(posix_getcwd__doc__,
2143"getcwd() -> path\n\n\
2144Return 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. */
2150static PyObject *
2151posix_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
2166static PyObject *
2167posix_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
2205PyDoc_STRVAR(posix_getcwdu__doc__,
2206"getcwdu() -> path\n\n\
2207Return a unicode string representing the current working directory.");
2208
2209static PyObject *
2210posix_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
2260PyDoc_STRVAR(posix_link__doc__,
2261"link(src, dst)\n\n\
2262Create a hard link to a file.");
2263
2264static PyObject *
2265posix_link(PyObject *self, PyObject *args)
2266{
2267    return posix_2str(args, "etet:link", link);
2268}
2269#endif /* HAVE_LINK */
2270
2271
2272PyDoc_STRVAR(posix_listdir__doc__,
2273"listdir(path) -> list_of_strings\n\n\
2274Return a list containing the names of the entries in the directory.\n\
2275\n\
2276    path: path of directory to list\n\
2277\n\
2278The list is in arbitrary order.  It does not include the special\n\
2279entries '.' and '..' even if they are present in the directory.");
2280
2281static PyObject *
2282posix_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 */
2601static PyObject *
2602posix__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
2653PyDoc_STRVAR(posix_mkdir__doc__,
2654"mkdir(path [, mode=0777])\n\n\
2655Create a directory.");
2656
2657static PyObject *
2658posix_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
2720PyDoc_STRVAR(posix_nice__doc__,
2721"nice(inc) -> new_priority\n\n\
2722Decrease the priority of process by inc and return the new priority.");
2723
2724static PyObject *
2725posix_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
2755PyDoc_STRVAR(posix_rename__doc__,
2756"rename(old, new)\n\n\
2757Rename a file or directory.");
2758
2759static PyObject *
2760posix_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;
2784error:
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
2801PyDoc_STRVAR(posix_rmdir__doc__,
2802"rmdir(path)\n\n\
2803Remove a directory.");
2804
2805static PyObject *
2806posix_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
2816PyDoc_STRVAR(posix_stat__doc__,
2817"stat(path) -> stat result\n\n\
2818Perform a stat system call on the given path.");
2819
2820static PyObject *
2821posix_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
2832PyDoc_STRVAR(posix_system__doc__,
2833"system(command) -> exit_status\n\n\
2834Execute the command (a string) in a subshell.");
2835
2836static PyObject *
2837posix_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
2851PyDoc_STRVAR(posix_umask__doc__,
2852"umask(new_mask) -> old_mask\n\n\
2853Set the current numeric umask and return the previous umask.");
2854
2855static PyObject *
2856posix_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
2868PyDoc_STRVAR(posix_unlink__doc__,
2869"unlink(path)\n\n\
2870Remove a file (same as remove(path)).");
2871
2872PyDoc_STRVAR(posix_remove__doc__,
2873"remove(path)\n\n\
2874Remove a file (same as unlink(path)).");
2875
2876static PyObject *
2877posix_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
2888PyDoc_STRVAR(posix_uname__doc__,
2889"uname() -> (sysname, nodename, release, version, machine)\n\n\
2890Return a tuple identifying the current operating system.");
2891
2892static PyObject *
2893posix_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
2912static int
2913extract_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
2949PyDoc_STRVAR(posix_utime__doc__,
2950"utime(path, (atime, mtime))\n\
2951utime(path, None)\n\n\
2952Set the access and modified time of the file to the given values.  If the\n\
2953second form is used, set the access and modified times to the current time.");
2954
2955static PyObject *
2956posix_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;
3032done:
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
3116PyDoc_STRVAR(posix__exit__doc__,
3117"_exit(status)\n\n\
3118Exit to the system with specified status, without normal exit processing.");
3119
3120static PyObject *
3121posix__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)
3131static void
3132free_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
3143PyDoc_STRVAR(posix_execv__doc__,
3144"execv(path, args)\n\n\
3145Execute 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
3150static PyObject *
3151posix_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
3214PyDoc_STRVAR(posix_execve__doc__,
3215"execve(path, args, env)\n\n\
3216Execute 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
3222static PyObject *
3223posix_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
3359PyDoc_STRVAR(posix_spawnv__doc__,
3360"spawnv(mode, path, args)\n\n\
3361Execute 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
3367static PyObject *
3368posix_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
3446PyDoc_STRVAR(posix_spawnve__doc__,
3447"spawnve(mode, path, args, env)\n\n\
3448Execute 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
3455static PyObject *
3456posix_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)
3601PyDoc_STRVAR(posix_spawnvp__doc__,
3602"spawnvp(mode, file, args)\n\n\
3603Execute the program 'file' in a new process, using the environment\n\
3604search 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
3610static PyObject *
3611posix_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
3679PyDoc_STRVAR(posix_spawnvpe__doc__,
3680"spawnvpe(mode, file, args, env)\n\n\
3681Execute the program 'file' in a new process, using the environment\n\
3682search 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
3689static PyObject *
3690posix_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
3827PyDoc_STRVAR(posix_fork1__doc__,
3828"fork1() -> pid\n\n\
3829Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
3830\n\
3831Return 0 to child process and PID of child to parent process.");
3832
3833static PyObject *
3834posix_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
3861PyDoc_STRVAR(posix_fork__doc__,
3862"fork() -> pid\n\n\
3863Fork a child process.\n\
3864Return 0 to child process and PID of child to parent process.");
3865
3866static PyObject *
3867posix_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)
3919PyDoc_STRVAR(posix_openpty__doc__,
3920"openpty() -> (master_fd, slave_fd)\n\n\
3921Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
3922
3923static PyObject *
3924posix_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
3985PyDoc_STRVAR(posix_forkpty__doc__,
3986"forkpty() -> (pid, master_fd)\n\n\
3987Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
3988Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
3989To both, return fd of newly opened pseudo-terminal.\n");
3990
3991static PyObject *
3992posix_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
4019PyDoc_STRVAR(posix_getegid__doc__,
4020"getegid() -> egid\n\n\
4021Return the current process's effective group id.");
4022
4023static PyObject *
4024posix_getegid(PyObject *self, PyObject *noargs)
4025{
4026    return _PyInt_FromGid(getegid());
4027}
4028#endif
4029
4030
4031#ifdef HAVE_GETEUID
4032PyDoc_STRVAR(posix_geteuid__doc__,
4033"geteuid() -> euid\n\n\
4034Return the current process's effective user id.");
4035
4036static PyObject *
4037posix_geteuid(PyObject *self, PyObject *noargs)
4038{
4039    return _PyInt_FromUid(geteuid());
4040}
4041#endif
4042
4043
4044#ifdef HAVE_GETGID
4045PyDoc_STRVAR(posix_getgid__doc__,
4046"getgid() -> gid\n\n\
4047Return the current process's group id.");
4048
4049static PyObject *
4050posix_getgid(PyObject *self, PyObject *noargs)
4051{
4052    return _PyInt_FromGid(getgid());
4053}
4054#endif
4055
4056
4057PyDoc_STRVAR(posix_getpid__doc__,
4058"getpid() -> pid\n\n\
4059Return the current process id");
4060
4061static PyObject *
4062posix_getpid(PyObject *self, PyObject *noargs)
4063{
4064    return PyLong_FromPid(getpid());
4065}
4066
4067
4068#ifdef HAVE_GETGROUPS
4069PyDoc_STRVAR(posix_getgroups__doc__,
4070"getgroups() -> list of group IDs\n\n\
4071Return list of supplemental group IDs for the process.");
4072
4073static PyObject *
4074posix_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
4176PyDoc_STRVAR(posix_initgroups__doc__,
4177"initgroups(username, gid) -> None\n\n\
4178Call the system initgroups() to initialize the group access list with all of\n\
4179the groups of which the specified username is a member, plus the specified\n\
4180group id.");
4181
4182static PyObject *
4183posix_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
4210PyDoc_STRVAR(posix_getpgid__doc__,
4211"getpgid(pid) -> pgid\n\n\
4212Call the system call getpgid().");
4213
4214static PyObject *
4215posix_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
4229PyDoc_STRVAR(posix_getpgrp__doc__,
4230"getpgrp() -> pgrp\n\n\
4231Return the current process group id.");
4232
4233static PyObject *
4234posix_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
4246PyDoc_STRVAR(posix_setpgrp__doc__,
4247"setpgrp()\n\n\
4248Make this process the process group leader.");
4249
4250static PyObject *
4251posix_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
4266PyDoc_STRVAR(posix_getppid__doc__,
4267"getppid() -> ppid\n\n\
4268Return the parent's process id.");
4269
4270static PyObject *
4271posix_getppid(PyObject *self, PyObject *noargs)
4272{
4273    return PyLong_FromPid(getppid());
4274}
4275#endif
4276
4277
4278#ifdef HAVE_GETLOGIN
4279PyDoc_STRVAR(posix_getlogin__doc__,
4280"getlogin() -> string\n\n\
4281Return the actual login name.");
4282
4283static PyObject *
4284posix_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
4308PyDoc_STRVAR(posix_getuid__doc__,
4309"getuid() -> uid\n\n\
4310Return the current process's user id.");
4311
4312static PyObject *
4313posix_getuid(PyObject *self, PyObject *noargs)
4314{
4315    return _PyInt_FromUid(getuid());
4316}
4317#endif
4318
4319
4320#ifdef HAVE_KILL
4321PyDoc_STRVAR(posix_kill__doc__,
4322"kill(pid, sig)\n\n\
4323Kill a process with a signal.");
4324
4325static PyObject *
4326posix_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
4355PyDoc_STRVAR(posix_killpg__doc__,
4356"killpg(pgid, sig)\n\n\
4357Kill a process group with a signal.");
4358
4359static PyObject *
4360posix_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
4378PyDoc_STRVAR(win32_kill__doc__,
4379"kill(pid, sig)\n\n\
4380Kill a process with a signal.");
4381
4382static PyObject *
4383win32_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
4423PyDoc_STRVAR(posix__isdir__doc__,
4424"Return true if the pathname refers to an existing directory.");
4425
4426static PyObject *
4427posix__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
4452check:
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
4466PyDoc_STRVAR(posix_plock__doc__,
4467"plock(op)\n\n\
4468Lock program segments into memory.");
4469
4470static PyObject *
4471posix_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
4485PyDoc_STRVAR(posix_popen__doc__,
4486"popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\
4487Open a pipe to/from a command returning a file object.");
4488
4489#if defined(PYOS_OS2)
4490#if defined(PYCC_VACPP)
4491static int
4492async_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
4522static FILE *
4523popen(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
4575static PyObject *
4576posix_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 */
4600static PyObject *
4601posix_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
4633static PyObject *_PyPopen(char *, int, int, int);
4634static 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 */
4641static 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
4649static PyObject *
4650os2emx_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
4681static PyObject *
4682os2emx_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
4713static PyObject *
4714os2emx_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 */
4741struct file_ref
4742{
4743    int handle;
4744    int flags;
4745};
4746
4747struct pipe_ref
4748{
4749    int rd;
4750    int wr;
4751};
4752
4753/* The following code is derived from the win32 code */
4754
4755static 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
5086static 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@microsoft.com>.  Minor tweaks
5180 * and 2.0 integration by Fredrik Lundh <fredrik@pythonware.com>
5181 * Return code handling by David Bolen <db3l@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
5194static PyObject *_PyPopen(char *, int, int);
5195static 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 */
5202static 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
5211static PyObject *
5212posix_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
5252static PyObject *
5253win32_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
5289static PyObject *
5290win32_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
5326static PyObject *
5327win32_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
5356static 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
5513static 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
5839static 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? */
5921static PyObject *
5922posix_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
5952PyDoc_STRVAR(posix_setuid__doc__,
5953"setuid(uid)\n\n\
5954Set the current process's user id.");
5955
5956static PyObject *
5957posix_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
5971PyDoc_STRVAR(posix_seteuid__doc__,
5972"seteuid(uid)\n\n\
5973Set the current process's effective user id.");
5974
5975static PyObject *
5976posix_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
5991PyDoc_STRVAR(posix_setegid__doc__,
5992"setegid(gid)\n\n\
5993Set the current process's effective group id.");
5994
5995static PyObject *
5996posix_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
6011PyDoc_STRVAR(posix_setreuid__doc__,
6012"setreuid(ruid, euid)\n\n\
6013Set the current process's real and effective user ids.");
6014
6015static PyObject *
6016posix_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
6033PyDoc_STRVAR(posix_setregid__doc__,
6034"setregid(rgid, egid)\n\n\
6035Set the current process's real and effective group ids.");
6036
6037static PyObject *
6038posix_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
6055PyDoc_STRVAR(posix_setgid__doc__,
6056"setgid(gid)\n\n\
6057Set the current process's group id.");
6058
6059static PyObject *
6060posix_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
6073PyDoc_STRVAR(posix_setgroups__doc__,
6074"setgroups(list)\n\n\
6075Set the groups of the current process to list.");
6076
6077static PyObject *
6078posix_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)
6119static PyObject *
6120wait_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
6179PyDoc_STRVAR(posix_wait3__doc__,
6180"wait3(options) -> (pid, status, rusage)\n\n\
6181Wait for completion of a child process.");
6182
6183static PyObject *
6184posix_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
6204PyDoc_STRVAR(posix_wait4__doc__,
6205"wait4(pid, options) -> (pid, status, rusage)\n\n\
6206Wait for completion of a given child process.");
6207
6208static PyObject *
6209posix_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
6229PyDoc_STRVAR(posix_waitpid__doc__,
6230"waitpid(pid, options) -> (pid, status)\n\n\
6231Wait for completion of a given child process.");
6232
6233static PyObject *
6234posix_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. */
6255PyDoc_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
6259static PyObject *
6260posix_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
6279PyDoc_STRVAR(posix_wait__doc__,
6280"wait() -> (pid, status)\n\n\
6281Wait for completion of a child process.");
6282
6283static PyObject *
6284posix_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
6301PyDoc_STRVAR(posix_lstat__doc__,
6302"lstat(path) -> stat result\n\n\
6303Like stat(path), but do not follow symbolic links.");
6304
6305static PyObject *
6306posix_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
6321PyDoc_STRVAR(posix_readlink__doc__,
6322"readlink(path) -> path\n\n\
6323Return a string representing the path to which the symbolic link points.");
6324
6325static PyObject *
6326posix_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
6384PyDoc_STRVAR(posix_symlink__doc__,
6385"symlink(src, dst)\n\n\
6386Create a symbolic link pointing to src named dst.");
6387
6388static PyObject *
6389posix_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)
6398static long
6399system_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
6410static PyObject *
6411posix_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
6423static long ticks_per_second = -1;
6424static PyObject *
6425posix_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 */
6446static PyObject *
6447posix_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
6471PyDoc_STRVAR(posix_times__doc__,
6472"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
6473Return a tuple of floating point numbers indicating process times.");
6474#endif
6475
6476
6477#ifdef HAVE_GETSID
6478PyDoc_STRVAR(posix_getsid__doc__,
6479"getsid(pid) -> sid\n\n\
6480Call the system call getsid().");
6481
6482static PyObject *
6483posix_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
6498PyDoc_STRVAR(posix_setsid__doc__,
6499"setsid()\n\n\
6500Call the system call setsid().");
6501
6502static PyObject *
6503posix_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
6513PyDoc_STRVAR(posix_setpgid__doc__,
6514"setpgid(pid, pgrp)\n\n\
6515Call the system call setpgid().");
6516
6517static PyObject *
6518posix_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
6533PyDoc_STRVAR(posix_tcgetpgrp__doc__,
6534"tcgetpgrp(fd) -> pgid\n\n\
6535Return the process group associated with the terminal given by a fd.");
6536
6537static PyObject *
6538posix_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
6553PyDoc_STRVAR(posix_tcsetpgrp__doc__,
6554"tcsetpgrp(fd, pgid)\n\n\
6555Set the process group associated with the terminal given by a fd.");
6556
6557static PyObject *
6558posix_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
6573PyDoc_STRVAR(posix_open__doc__,
6574"open(filename, flag [, mode=0777]) -> fd\n\n\
6575Open a file (for low level IO).");
6576
6577static PyObject *
6578posix_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
6615PyDoc_STRVAR(posix_close__doc__,
6616"close(fd)\n\n\
6617Close a file descriptor (for low level IO).");
6618
6619/*
6620The underscore at end of function name avoids a name clash with the libc
6621function posix_close.
6622*/
6623static PyObject *
6624posix_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
6641PyDoc_STRVAR(posix_closerange__doc__,
6642"closerange(fd_low, fd_high)\n\n\
6643Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
6644
6645static PyObject *
6646posix_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
6660PyDoc_STRVAR(posix_dup__doc__,
6661"dup(fd) -> fd2\n\n\
6662Return a duplicate of a file descriptor.");
6663
6664static PyObject *
6665posix_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
6681PyDoc_STRVAR(posix_dup2__doc__,
6682"dup2(old_fd, new_fd)\n\n\
6683Duplicate file descriptor.");
6684
6685static PyObject *
6686posix_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
6703PyDoc_STRVAR(posix_lseek__doc__,
6704"lseek(fd, pos, how) -> newpos\n\n\
6705Set the current position of a file descriptor.\n\
6706Return the new cursor position in bytes, starting from the beginning.");
6707
6708static PyObject *
6709posix_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
6758PyDoc_STRVAR(posix_read__doc__,
6759"read(fd, buffersize) -> string\n\n\
6760Read a file descriptor.");
6761
6762static PyObject *
6763posix_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
6793PyDoc_STRVAR(posix_write__doc__,
6794"write(fd, string) -> byteswritten\n\n\
6795Write a string to a file descriptor.");
6796
6797static PyObject *
6798posix_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
6827PyDoc_STRVAR(posix_fstat__doc__,
6828"fstat(fd) -> stat result\n\n\
6829Like stat(), but for an open file descriptor.");
6830
6831static PyObject *
6832posix_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
6860PyDoc_STRVAR(posix_fdopen__doc__,
6861"fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
6862Return an open file object connected to a file descriptor.");
6863
6864static PyObject *
6865posix_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
6946PyDoc_STRVAR(posix_isatty__doc__,
6947"isatty(fd) -> bool\n\n\
6948Return True if the file descriptor 'fd' is an open file descriptor\n\
6949connected to the slave end of a terminal.");
6950
6951static PyObject *
6952posix_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
6963PyDoc_STRVAR(posix_pipe__doc__,
6964"pipe() -> (read_end, write_end)\n\n\
6965Create a pipe.");
6966
6967static PyObject *
6968posix_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
7010PyDoc_STRVAR(posix_mkfifo__doc__,
7011"mkfifo(filename [, mode=0666])\n\n\
7012Create a FIFO (a POSIX named pipe).");
7013
7014static PyObject *
7015posix_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)
7034PyDoc_STRVAR(posix_mknod__doc__,
7035"mknod(filename [, mode=0600, device])\n\n\
7036Create a filesystem node (file, device special file or named pipe)\n\
7037named filename. mode specifies both the permissions to use and the\n\
7038type of node to be created, being combined (bitwise OR) with one of\n\
7039S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
7040device defines the newly created device special file (probably using\n\
7041os.makedev()), otherwise it is ignored.");
7042
7043
7044static PyObject *
7045posix_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
7066PyDoc_STRVAR(posix_major__doc__,
7067"major(device) -> major number\n\
7068Extracts a device major number from a raw device number.");
7069
7070static PyObject *
7071posix_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
7079PyDoc_STRVAR(posix_minor__doc__,
7080"minor(device) -> minor number\n\
7081Extracts a device minor number from a raw device number.");
7082
7083static PyObject *
7084posix_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
7092PyDoc_STRVAR(posix_makedev__doc__,
7093"makedev(major, minor) -> device number\n\
7094Composes a raw device number from the major and minor device numbers.");
7095
7096static PyObject *
7097posix_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
7108PyDoc_STRVAR(posix_ftruncate__doc__,
7109"ftruncate(fd, length)\n\n\
7110Truncate a file to a specified length.");
7111
7112static PyObject *
7113posix_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
7143PyDoc_STRVAR(posix_putenv__doc__,
7144"putenv(key, value)\n\n\
7145Change 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. */
7149static PyObject *posix_putenv_garbage;
7150
7151static PyObject *
7152posix_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
7223PyDoc_STRVAR(posix_unsetenv__doc__,
7224"unsetenv(key)\n\n\
7225Delete an environment variable.");
7226
7227static PyObject *
7228posix_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
7262PyDoc_STRVAR(posix_strerror__doc__,
7263"strerror(code) -> string\n\n\
7264Translate an error code to a message string.");
7265
7266static PyObject *
7267posix_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
7286PyDoc_STRVAR(posix_WCOREDUMP__doc__,
7287"WCOREDUMP(status) -> bool\n\n\
7288Return True if the process returning 'status' was dumped to a core file.");
7289
7290static PyObject *
7291posix_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
7304PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
7305"WIFCONTINUED(status) -> bool\n\n\
7306Return True if the process returning 'status' was continued from a\n\
7307job control stop.");
7308
7309static PyObject *
7310posix_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
7323PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
7324"WIFSTOPPED(status) -> bool\n\n\
7325Return True if the process returning 'status' was stopped.");
7326
7327static PyObject *
7328posix_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
7341PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
7342"WIFSIGNALED(status) -> bool\n\n\
7343Return True if the process returning 'status' was terminated by a signal.");
7344
7345static PyObject *
7346posix_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
7359PyDoc_STRVAR(posix_WIFEXITED__doc__,
7360"WIFEXITED(status) -> bool\n\n\
7361Return true if the process returning 'status' exited using the exit()\n\
7362system call.");
7363
7364static PyObject *
7365posix_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
7378PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
7379"WEXITSTATUS(status) -> integer\n\n\
7380Return the process return code from 'status'.");
7381
7382static PyObject *
7383posix_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
7396PyDoc_STRVAR(posix_WTERMSIG__doc__,
7397"WTERMSIG(status) -> integer\n\n\
7398Return the signal that terminated the process that provided the 'status'\n\
7399value.");
7400
7401static PyObject *
7402posix_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
7415PyDoc_STRVAR(posix_WSTOPSIG__doc__,
7416"WSTOPSIG(status) -> integer\n\n\
7417Return the signal that stopped the process that provided\n\
7418the 'status' value.");
7419
7420static PyObject *
7421posix_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
7444static 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
7483PyDoc_STRVAR(posix_fstatvfs__doc__,
7484"fstatvfs(fd) -> statvfs result\n\n\
7485Perform an fstatvfs system call on the given fd.");
7486
7487static PyObject *
7488posix_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
7509PyDoc_STRVAR(posix_statvfs__doc__,
7510"statvfs(path) -> statvfs result\n\n\
7511Perform a statvfs system call on the given path.");
7512
7513static PyObject *
7514posix_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
7533PyDoc_STRVAR(posix_tempnam__doc__,
7534"tempnam([dir[, prefix]]) -> string\n\n\
7535Return a unique name for a temporary file.\n\
7536The directory and a prefix may be specified as strings; they may be omitted\n\
7537or None if not needed.");
7538
7539static PyObject *
7540posix_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
7573PyDoc_STRVAR(posix_tmpfile__doc__,
7574"tmpfile() -> file object\n\n\
7575Create a temporary file with no directory entries.");
7576
7577static PyObject *
7578posix_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
7595PyDoc_STRVAR(posix_tmpnam__doc__,
7596"tmpnam() -> string\n\n\
7597Return a unique name for a temporary file.");
7598
7599static PyObject *
7600posix_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 */
7646struct constdef {
7647    char *name;
7648    long value;
7649};
7650
7651static int
7652conv_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)
7688static 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
7742static int
7743conv_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
7752PyDoc_STRVAR(posix_fpathconf__doc__,
7753"fpathconf(fd, name) -> integer\n\n\
7754Return the configuration limit name for the file descriptor fd.\n\
7755If there is no limit, return -1.");
7756
7757static PyObject *
7758posix_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
7780PyDoc_STRVAR(posix_pathconf__doc__,
7781"pathconf(path, name) -> integer\n\n\
7782Return the configuration limit name for the file or directory path.\n\
7783If there is no limit, return -1.");
7784
7785static PyObject *
7786posix_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
7813static 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
7960static int
7961conv_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
7968PyDoc_STRVAR(posix_confstr__doc__,
7969"confstr(name) -> string\n\n\
7970Return a string-valued system configuration variable.");
7971
7972static PyObject *
7973posix_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
8009static 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
8504static int
8505conv_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
8512PyDoc_STRVAR(posix_sysconf__doc__,
8513"sysconf(name) -> integer\n\n\
8514Return an integer-valued system configuration variable.");
8515
8516static PyObject *
8517posix_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
8547static int
8548cmp_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
8558static int
8559setup_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. */
8582static int
8583setup_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
8610PyDoc_STRVAR(posix_abort__doc__,
8611"abort() -> does not return!\n\n\
8612Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
8613in the hardest way possible on the hosting operating system.");
8614
8615static PyObject *
8616posix_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
8625PyDoc_STRVAR(win32_startfile__doc__,
8626"startfile(filepath [, operation]) - Start a file with its associated\n\
8627application.\n\
8628\n\
8629When \"operation\" is not specified or \"open\", this acts like\n\
8630double-clicking the file in Explorer, or giving the file name as an\n\
8631argument to the DOS \"start\" command: the file is opened with whatever\n\
8632application (if any) its extension is associated.\n\
8633When another \"operation\" is given, it specifies what should be done with\n\
8634the file.  A typical operation is \"print\".\n\
8635\n\
8636startfile returns as soon as the associated application is launched.\n\
8637There is no option to wait for the application to close, and no way\n\
8638to retrieve the application's exit status.\n\
8639\n\
8640The filepath is relative to the current directory.  If you want to use\n\
8641an absolute path, make sure the first character is not a slash (\"/\");\n\
8642the underlying Win32 ShellExecute function doesn't work if it is.");
8643
8644static PyObject *
8645win32_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
8683normal:
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
8704PyDoc_STRVAR(posix_getloadavg__doc__,
8705"getloadavg() -> (float, float, float)\n\n\
8706Return the number of processes in the system run queue averaged over\n\
8707the last 1, 5, and 15 minutes or raises OSError if the load average\n\
8708was unobtainable");
8709
8710static PyObject *
8711posix_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
8722PyDoc_STRVAR(posix_urandom__doc__,
8723"urandom(n) -> str\n\n\
8724Return n random bytes suitable for cryptographic use.");
8725
8726static PyObject *
8727posix_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
8753PyDoc_STRVAR(posix_setresuid__doc__,
8754"setresuid(ruid, euid, suid)\n\n\
8755Set the current process's real, effective, and saved user ids.");
8756
8757static PyObject*
8758posix_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
8773PyDoc_STRVAR(posix_setresgid__doc__,
8774"setresgid(rgid, egid, sgid)\n\n\
8775Set the current process's real, effective, and saved group ids.");
8776
8777static PyObject*
8778posix_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
8793PyDoc_STRVAR(posix_getresuid__doc__,
8794"getresuid() -> (ruid, euid, suid)\n\n\
8795Get tuple of the current process's real, effective, and saved user ids.");
8796
8797static PyObject*
8798posix_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
8810PyDoc_STRVAR(posix_getresgid__doc__,
8811"getresgid() -> (rgid, egid, sgid)\n\n\
8812Get tuple of the current process's real, effective, and saved group ids.");
8813
8814static PyObject*
8815posix_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
8826static 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
9152static int
9153ins(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 */
9160static 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
9211static int
9212all_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
9446PyMODINIT_FUNC
9447INITFUNC(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