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