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