1/** @file
2    OS-specific module implementation for EDK II and UEFI.
3    Derived from posixmodule.c in Python 2.7.2.
4
5    Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
6    This program and the accompanying materials are licensed and made available under
7    the terms and conditions of the BSD License that accompanies this distribution.
8    The full text of the license may be found at
9    http://opensource.org/licenses/bsd-license.
10
11    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13**/
14#define PY_SSIZE_T_CLEAN
15
16#include "Python.h"
17#include "structseq.h"
18
19#include  <stdio.h>
20#include  <stdlib.h>
21#include  <wchar.h>
22#include  <sys/syslimits.h>
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28PyDoc_STRVAR(edk2__doc__,
29             "This module provides access to UEFI firmware functionality that is\n\
30             standardized by the C Standard and the POSIX standard (a thinly\n\
31             disguised Unix interface).  Refer to the library manual and\n\
32             corresponding UEFI Specification entries for more information on calls.");
33
34#ifndef Py_USING_UNICODE
35  /* This is used in signatures of functions. */
36  #define Py_UNICODE void
37#endif
38
39#ifdef HAVE_SYS_TYPES_H
40  #include <sys/types.h>
41#endif /* HAVE_SYS_TYPES_H */
42
43#ifdef HAVE_SYS_STAT_H
44  #include <sys/stat.h>
45#endif /* HAVE_SYS_STAT_H */
46
47#ifdef HAVE_SYS_WAIT_H
48  #include <sys/wait.h>           /* For WNOHANG */
49#endif
50
51#ifdef HAVE_SIGNAL_H
52  #include <signal.h>
53#endif
54
55#ifdef HAVE_FCNTL_H
56  #include <fcntl.h>
57#endif /* HAVE_FCNTL_H */
58
59#ifdef HAVE_GRP_H
60  #include <grp.h>
61#endif
62
63#ifdef HAVE_SYSEXITS_H
64  #include <sysexits.h>
65#endif /* HAVE_SYSEXITS_H */
66
67#ifdef HAVE_SYS_LOADAVG_H
68  #include <sys/loadavg.h>
69#endif
70
71#ifdef HAVE_UTIME_H
72  #include <utime.h>
73#endif /* HAVE_UTIME_H */
74
75#ifdef HAVE_SYS_UTIME_H
76  #include <sys/utime.h>
77  #define HAVE_UTIME_H /* pretend we do for the rest of this file */
78#endif /* HAVE_SYS_UTIME_H */
79
80#ifdef HAVE_SYS_TIMES_H
81  #include <sys/times.h>
82#endif /* HAVE_SYS_TIMES_H */
83
84#ifdef HAVE_SYS_PARAM_H
85  #include <sys/param.h>
86#endif /* HAVE_SYS_PARAM_H */
87
88#ifdef HAVE_SYS_UTSNAME_H
89  #include <sys/utsname.h>
90#endif /* HAVE_SYS_UTSNAME_H */
91
92#ifdef HAVE_DIRENT_H
93  #include <dirent.h>
94  #define NAMLEN(dirent) wcslen((dirent)->FileName)
95#else
96  #define dirent direct
97  #define NAMLEN(dirent) (dirent)->d_namlen
98  #ifdef HAVE_SYS_NDIR_H
99    #include <sys/ndir.h>
100  #endif
101  #ifdef HAVE_SYS_DIR_H
102    #include <sys/dir.h>
103  #endif
104  #ifdef HAVE_NDIR_H
105    #include <ndir.h>
106  #endif
107#endif
108
109#ifndef MAXPATHLEN
110  #if defined(PATH_MAX) && PATH_MAX > 1024
111    #define MAXPATHLEN PATH_MAX
112  #else
113    #define MAXPATHLEN 1024
114  #endif
115#endif /* MAXPATHLEN */
116
117#define WAIT_TYPE int
118#define WAIT_STATUS_INT(s) (s)
119
120/* Issue #1983: pid_t can be longer than a C long on some systems */
121#if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
122  #define PARSE_PID "i"
123  #define PyLong_FromPid PyInt_FromLong
124  #define PyLong_AsPid PyInt_AsLong
125#elif SIZEOF_PID_T == SIZEOF_LONG
126  #define PARSE_PID "l"
127  #define PyLong_FromPid PyInt_FromLong
128  #define PyLong_AsPid PyInt_AsLong
129#elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
130  #define PARSE_PID "L"
131  #define PyLong_FromPid PyLong_FromLongLong
132  #define PyLong_AsPid PyInt_AsLongLong
133#else
134  #error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)"
135#endif /* SIZEOF_PID_T */
136
137/* Don't use the "_r" form if we don't need it (also, won't have a
138   prototype for it, at least on Solaris -- maybe others as well?). */
139#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
140  #define USE_CTERMID_R
141#endif
142
143#if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)
144  #define USE_TMPNAM_R
145#endif
146
147/* choose the appropriate stat and fstat functions and return structs */
148#undef STAT
149#undef FSTAT
150#undef STRUCT_STAT
151#define STAT stat
152#define FSTAT fstat
153#define STRUCT_STAT struct stat
154
155/* dummy version. _PyVerify_fd() is already defined in fileobject.h */
156#define _PyVerify_fd_dup2(A, B) (1)
157
158#ifndef UEFI_C_SOURCE
159/* Return a dictionary corresponding to the POSIX environment table */
160extern char **environ;
161
162static PyObject *
163convertenviron(void)
164{
165    PyObject *d;
166    char **e;
167    d = PyDict_New();
168    if (d == NULL)
169        return NULL;
170    if (environ == NULL)
171        return d;
172    /* This part ignores errors */
173    for (e = environ; *e != NULL; e++) {
174        PyObject *k;
175        PyObject *v;
176        char *p = strchr(*e, '=');
177        if (p == NULL)
178            continue;
179        k = PyString_FromStringAndSize(*e, (int)(p-*e));
180        if (k == NULL) {
181            PyErr_Clear();
182            continue;
183        }
184        v = PyString_FromString(p+1);
185        if (v == NULL) {
186            PyErr_Clear();
187            Py_DECREF(k);
188            continue;
189        }
190        if (PyDict_GetItem(d, k) == NULL) {
191            if (PyDict_SetItem(d, k, v) != 0)
192                PyErr_Clear();
193        }
194        Py_DECREF(k);
195        Py_DECREF(v);
196    }
197    return d;
198}
199#endif  /* UEFI_C_SOURCE */
200
201/* Set a POSIX-specific error from errno, and return NULL */
202
203static PyObject *
204posix_error(void)
205{
206    return PyErr_SetFromErrno(PyExc_OSError);
207}
208static PyObject *
209posix_error_with_filename(char* name)
210{
211    return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
212}
213
214
215static PyObject *
216posix_error_with_allocated_filename(char* name)
217{
218    PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
219    PyMem_Free(name);
220    return rc;
221}
222
223/* POSIX generic methods */
224
225#ifndef UEFI_C_SOURCE
226  static PyObject *
227  posix_fildes(PyObject *fdobj, int (*func)(int))
228  {
229      int fd;
230      int res;
231      fd = PyObject_AsFileDescriptor(fdobj);
232      if (fd < 0)
233          return NULL;
234      if (!_PyVerify_fd(fd))
235          return posix_error();
236      Py_BEGIN_ALLOW_THREADS
237      res = (*func)(fd);
238      Py_END_ALLOW_THREADS
239      if (res < 0)
240          return posix_error();
241      Py_INCREF(Py_None);
242      return Py_None;
243  }
244#endif  /* UEFI_C_SOURCE */
245
246static PyObject *
247posix_1str(PyObject *args, char *format, int (*func)(const char*))
248{
249    char *path1 = NULL;
250    int res;
251    if (!PyArg_ParseTuple(args, format,
252                          Py_FileSystemDefaultEncoding, &path1))
253        return NULL;
254    Py_BEGIN_ALLOW_THREADS
255    res = (*func)(path1);
256    Py_END_ALLOW_THREADS
257    if (res < 0)
258        return posix_error_with_allocated_filename(path1);
259    PyMem_Free(path1);
260    Py_INCREF(Py_None);
261    return Py_None;
262}
263
264static PyObject *
265posix_2str(PyObject *args,
266           char *format,
267           int (*func)(const char *, const char *))
268{
269    char *path1 = NULL, *path2 = NULL;
270    int res;
271    if (!PyArg_ParseTuple(args, format,
272                          Py_FileSystemDefaultEncoding, &path1,
273                          Py_FileSystemDefaultEncoding, &path2))
274        return NULL;
275    Py_BEGIN_ALLOW_THREADS
276    res = (*func)(path1, path2);
277    Py_END_ALLOW_THREADS
278    PyMem_Free(path1);
279    PyMem_Free(path2);
280    if (res != 0)
281        /* XXX how to report both path1 and path2??? */
282        return posix_error();
283    Py_INCREF(Py_None);
284    return Py_None;
285}
286
287PyDoc_STRVAR(stat_result__doc__,
288"stat_result: Result from stat or lstat.\n\n\
289This object may be accessed either as a tuple of\n\
290  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
291or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
292\n\
293Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
294or st_flags, they are available as attributes only.\n\
295\n\
296See os.stat for more information.");
297
298static PyStructSequence_Field stat_result_fields[] = {
299    {"st_mode",    "protection bits"},
300    //{"st_ino",     "inode"},
301    //{"st_dev",     "device"},
302    //{"st_nlink",   "number of hard links"},
303    //{"st_uid",     "user ID of owner"},
304    //{"st_gid",     "group ID of owner"},
305    {"st_size",    "total size, in bytes"},
306    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
307    {NULL,   "integer time of last access"},
308    {NULL,   "integer time of last modification"},
309    {NULL,   "integer time of last change"},
310    {"st_atime",   "time of last access"},
311    {"st_mtime",   "time of last modification"},
312    {"st_ctime",   "time of last change"},
313#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
314    {"st_blksize", "blocksize for filesystem I/O"},
315#endif
316#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
317    {"st_blocks",  "number of blocks allocated"},
318#endif
319#ifdef HAVE_STRUCT_STAT_ST_RDEV
320    {"st_rdev",    "device type (if inode device)"},
321#endif
322#ifdef HAVE_STRUCT_STAT_ST_FLAGS
323    {"st_flags",   "user defined flags for file"},
324#endif
325#ifdef HAVE_STRUCT_STAT_ST_GEN
326    {"st_gen",    "generation number"},
327#endif
328#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
329    {"st_birthtime",   "time of creation"},
330#endif
331    {0}
332};
333
334#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
335#define ST_BLKSIZE_IDX 8
336#else
337#define ST_BLKSIZE_IDX 12
338#endif
339
340#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
341#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
342#else
343#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
344#endif
345
346#ifdef HAVE_STRUCT_STAT_ST_RDEV
347#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
348#else
349#define ST_RDEV_IDX ST_BLOCKS_IDX
350#endif
351
352#ifdef HAVE_STRUCT_STAT_ST_FLAGS
353#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
354#else
355#define ST_FLAGS_IDX ST_RDEV_IDX
356#endif
357
358#ifdef HAVE_STRUCT_STAT_ST_GEN
359#define ST_GEN_IDX (ST_FLAGS_IDX+1)
360#else
361#define ST_GEN_IDX ST_FLAGS_IDX
362#endif
363
364#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
365#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
366#else
367#define ST_BIRTHTIME_IDX ST_GEN_IDX
368#endif
369
370static PyStructSequence_Desc stat_result_desc = {
371    "stat_result", /* name */
372    stat_result__doc__, /* doc */
373    stat_result_fields,
374    10
375};
376
377#ifndef UEFI_C_SOURCE   /* Not in UEFI */
378PyDoc_STRVAR(statvfs_result__doc__,
379"statvfs_result: Result from statvfs or fstatvfs.\n\n\
380This object may be accessed either as a tuple of\n\
381  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
382or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
383\n\
384See os.statvfs for more information.");
385
386static PyStructSequence_Field statvfs_result_fields[] = {
387    {"f_bsize",  },
388    {"f_frsize", },
389    {"f_blocks", },
390    {"f_bfree",  },
391    {"f_bavail", },
392    {"f_files",  },
393    {"f_ffree",  },
394    {"f_favail", },
395    {"f_flag",   },
396    {"f_namemax",},
397    {0}
398};
399
400static PyStructSequence_Desc statvfs_result_desc = {
401    "statvfs_result", /* name */
402    statvfs_result__doc__, /* doc */
403    statvfs_result_fields,
404    10
405};
406
407static PyTypeObject StatVFSResultType;
408#endif
409
410static int initialized;
411static PyTypeObject StatResultType;
412static newfunc structseq_new;
413
414static PyObject *
415statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
416{
417    PyStructSequence *result;
418    int i;
419
420    result = (PyStructSequence*)structseq_new(type, args, kwds);
421    if (!result)
422        return NULL;
423    /* If we have been initialized from a tuple,
424       st_?time might be set to None. Initialize it
425       from the int slots.  */
426    for (i = 7; i <= 9; i++) {
427        if (result->ob_item[i+3] == Py_None) {
428            Py_DECREF(Py_None);
429            Py_INCREF(result->ob_item[i]);
430            result->ob_item[i+3] = result->ob_item[i];
431        }
432    }
433    return (PyObject*)result;
434}
435
436
437
438/* If true, st_?time is float. */
439#if defined(UEFI_C_SOURCE)
440  static int _stat_float_times = 0;
441#else
442  static int _stat_float_times = 1;
443
444PyDoc_STRVAR(stat_float_times__doc__,
445"stat_float_times([newval]) -> oldval\n\n\
446Determine whether os.[lf]stat represents time stamps as float objects.\n\
447If newval is True, future calls to stat() return floats, if it is False,\n\
448future calls return ints. \n\
449If newval is omitted, return the current setting.\n");
450
451static PyObject*
452stat_float_times(PyObject* self, PyObject *args)
453{
454    int newval = -1;
455
456    if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
457        return NULL;
458    if (newval == -1)
459        /* Return old value */
460        return PyBool_FromLong(_stat_float_times);
461    _stat_float_times = newval;
462    Py_INCREF(Py_None);
463    return Py_None;
464}
465#endif  /* UEFI_C_SOURCE */
466
467static void
468fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
469{
470    PyObject *fval,*ival;
471#if SIZEOF_TIME_T > SIZEOF_LONG
472    ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
473#else
474    ival = PyInt_FromLong((long)sec);
475#endif
476    if (!ival)
477        return;
478    if (_stat_float_times) {
479        fval = PyFloat_FromDouble(sec + 1e-9*nsec);
480    } else {
481        fval = ival;
482        Py_INCREF(fval);
483    }
484    PyStructSequence_SET_ITEM(v, index, ival);
485    PyStructSequence_SET_ITEM(v, index+3, fval);
486}
487
488/* pack a system stat C structure into the Python stat tuple
489   (used by posix_stat() and posix_fstat()) */
490static PyObject*
491_pystat_fromstructstat(STRUCT_STAT *st)
492{
493    unsigned long ansec, mnsec, cnsec;
494    PyObject *v = PyStructSequence_New(&StatResultType);
495    if (v == NULL)
496        return NULL;
497
498    PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
499    PyStructSequence_SET_ITEM(v, 1,
500                              PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
501
502    ansec = mnsec = cnsec = 0;
503    /* The index used by fill_time is the index of the integer time.
504       fill_time will add 3 to the index to get the floating time index.
505    */
506    fill_time(v, 2, st->st_atime, ansec);
507    fill_time(v, 3, st->st_mtime, mnsec);
508    fill_time(v, 4, st->st_mtime, cnsec);
509
510#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
511    PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
512                              PyInt_FromLong((long)st->st_blksize));
513#endif
514#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
515    PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
516                              PyInt_FromLong((long)st->st_blocks));
517#endif
518#ifdef HAVE_STRUCT_STAT_ST_RDEV
519    PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
520                              PyInt_FromLong((long)st->st_rdev));
521#endif
522#ifdef HAVE_STRUCT_STAT_ST_GEN
523    PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
524                              PyInt_FromLong((long)st->st_gen));
525#endif
526#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
527    {
528      PyObject *val;
529      unsigned long bsec,bnsec;
530      bsec = (long)st->st_birthtime;
531#ifdef HAVE_STAT_TV_NSEC2
532      bnsec = st->st_birthtimespec.tv_nsec;
533#else
534      bnsec = 0;
535#endif
536      if (_stat_float_times) {
537        val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
538      } else {
539        val = PyInt_FromLong((long)bsec);
540      }
541      PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
542                                val);
543    }
544#endif
545#ifdef HAVE_STRUCT_STAT_ST_FLAGS
546    PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
547                              PyInt_FromLong((long)st->st_flags));
548#endif
549
550    if (PyErr_Occurred()) {
551        Py_DECREF(v);
552        return NULL;
553    }
554
555    return v;
556}
557
558static PyObject *
559posix_do_stat(PyObject *self, PyObject *args,
560              char *format,
561              int (*statfunc)(const char *, STRUCT_STAT *),
562              char *wformat,
563              int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
564{
565    STRUCT_STAT st;
566    char *path = NULL;          /* pass this to stat; do not free() it */
567    char *pathfree = NULL;  /* this memory must be free'd */
568    int res;
569    PyObject *result;
570
571    if (!PyArg_ParseTuple(args, format,
572                          Py_FileSystemDefaultEncoding, &path))
573        return NULL;
574    pathfree = path;
575
576    Py_BEGIN_ALLOW_THREADS
577    res = (*statfunc)(path, &st);
578    Py_END_ALLOW_THREADS
579
580    if (res != 0) {
581        result = posix_error_with_filename(pathfree);
582    }
583    else
584        result = _pystat_fromstructstat(&st);
585
586    PyMem_Free(pathfree);
587    return result;
588}
589
590/* POSIX methods */
591
592PyDoc_STRVAR(posix_access__doc__,
593"access(path, mode) -> True if granted, False otherwise\n\n\
594Use the real uid/gid to test for access to a path.  Note that most\n\
595operations will use the effective uid/gid, therefore this routine can\n\
596be used in a suid/sgid environment to test if the invoking user has the\n\
597specified access to the path.  The mode argument can be F_OK to test\n\
598existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
599
600static PyObject *
601posix_access(PyObject *self, PyObject *args)
602{
603    char *path;
604    int mode;
605
606    int res;
607    if (!PyArg_ParseTuple(args, "eti:access",
608                          Py_FileSystemDefaultEncoding, &path, &mode))
609        return NULL;
610    Py_BEGIN_ALLOW_THREADS
611    res = access(path, mode);
612    Py_END_ALLOW_THREADS
613    PyMem_Free(path);
614    return PyBool_FromLong(res == 0);
615}
616
617#ifndef F_OK
618  #define F_OK 0
619#endif
620#ifndef R_OK
621  #define R_OK 4
622#endif
623#ifndef W_OK
624  #define W_OK 2
625#endif
626#ifndef X_OK
627  #define X_OK 1
628#endif
629
630PyDoc_STRVAR(posix_chdir__doc__,
631"chdir(path)\n\n\
632Change the current working directory to the specified path.");
633
634static PyObject *
635posix_chdir(PyObject *self, PyObject *args)
636{
637    return posix_1str(args, "et:chdir", chdir);
638}
639
640PyDoc_STRVAR(posix_chmod__doc__,
641"chmod(path, mode)\n\n\
642Change the access permissions of a file.");
643
644static PyObject *
645posix_chmod(PyObject *self, PyObject *args)
646{
647    char *path = NULL;
648    int i;
649    int res;
650    if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
651                          &path, &i))
652        return NULL;
653    Py_BEGIN_ALLOW_THREADS
654    res = chmod(path, i);
655    Py_END_ALLOW_THREADS
656    if (res < 0)
657        return posix_error_with_allocated_filename(path);
658    PyMem_Free(path);
659    Py_INCREF(Py_None);
660    return Py_None;
661}
662
663#ifdef HAVE_FCHMOD
664PyDoc_STRVAR(posix_fchmod__doc__,
665"fchmod(fd, mode)\n\n\
666Change the access permissions of the file given by file\n\
667descriptor fd.");
668
669static PyObject *
670posix_fchmod(PyObject *self, PyObject *args)
671{
672    int fd, mode, res;
673    if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
674        return NULL;
675    Py_BEGIN_ALLOW_THREADS
676    res = fchmod(fd, mode);
677    Py_END_ALLOW_THREADS
678    if (res < 0)
679        return posix_error();
680    Py_RETURN_NONE;
681}
682#endif /* HAVE_FCHMOD */
683
684#ifdef HAVE_LCHMOD
685PyDoc_STRVAR(posix_lchmod__doc__,
686"lchmod(path, mode)\n\n\
687Change the access permissions of a file. If path is a symlink, this\n\
688affects the link itself rather than the target.");
689
690static PyObject *
691posix_lchmod(PyObject *self, PyObject *args)
692{
693    char *path = NULL;
694    int i;
695    int res;
696    if (!PyArg_ParseTuple(args, "eti:lchmod", Py_FileSystemDefaultEncoding,
697                          &path, &i))
698        return NULL;
699    Py_BEGIN_ALLOW_THREADS
700    res = lchmod(path, i);
701    Py_END_ALLOW_THREADS
702    if (res < 0)
703        return posix_error_with_allocated_filename(path);
704    PyMem_Free(path);
705    Py_RETURN_NONE;
706}
707#endif /* HAVE_LCHMOD */
708
709
710#ifdef HAVE_CHFLAGS
711PyDoc_STRVAR(posix_chflags__doc__,
712"chflags(path, flags)\n\n\
713Set file flags.");
714
715static PyObject *
716posix_chflags(PyObject *self, PyObject *args)
717{
718    char *path;
719    unsigned long flags;
720    int res;
721    if (!PyArg_ParseTuple(args, "etk:chflags",
722                          Py_FileSystemDefaultEncoding, &path, &flags))
723        return NULL;
724    Py_BEGIN_ALLOW_THREADS
725    res = chflags(path, flags);
726    Py_END_ALLOW_THREADS
727    if (res < 0)
728        return posix_error_with_allocated_filename(path);
729    PyMem_Free(path);
730    Py_INCREF(Py_None);
731    return Py_None;
732}
733#endif /* HAVE_CHFLAGS */
734
735#ifdef HAVE_LCHFLAGS
736PyDoc_STRVAR(posix_lchflags__doc__,
737"lchflags(path, flags)\n\n\
738Set file flags.\n\
739This function will not follow symbolic links.");
740
741static PyObject *
742posix_lchflags(PyObject *self, PyObject *args)
743{
744    char *path;
745    unsigned long flags;
746    int res;
747    if (!PyArg_ParseTuple(args, "etk:lchflags",
748                          Py_FileSystemDefaultEncoding, &path, &flags))
749        return NULL;
750    Py_BEGIN_ALLOW_THREADS
751    res = lchflags(path, flags);
752    Py_END_ALLOW_THREADS
753    if (res < 0)
754        return posix_error_with_allocated_filename(path);
755    PyMem_Free(path);
756    Py_INCREF(Py_None);
757    return Py_None;
758}
759#endif /* HAVE_LCHFLAGS */
760
761#ifdef HAVE_CHROOT
762PyDoc_STRVAR(posix_chroot__doc__,
763"chroot(path)\n\n\
764Change root directory to path.");
765
766static PyObject *
767posix_chroot(PyObject *self, PyObject *args)
768{
769    return posix_1str(args, "et:chroot", chroot);
770}
771#endif
772
773#ifdef HAVE_FSYNC
774PyDoc_STRVAR(posix_fsync__doc__,
775"fsync(fildes)\n\n\
776force write of file with filedescriptor to disk.");
777
778static PyObject *
779posix_fsync(PyObject *self, PyObject *fdobj)
780{
781    return posix_fildes(fdobj, fsync);
782}
783#endif /* HAVE_FSYNC */
784
785#ifdef HAVE_FDATASYNC
786
787#ifdef __hpux
788extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
789#endif
790
791PyDoc_STRVAR(posix_fdatasync__doc__,
792"fdatasync(fildes)\n\n\
793force write of file with filedescriptor to disk.\n\
794 does not force update of metadata.");
795
796static PyObject *
797posix_fdatasync(PyObject *self, PyObject *fdobj)
798{
799    return posix_fildes(fdobj, fdatasync);
800}
801#endif /* HAVE_FDATASYNC */
802
803
804#ifdef HAVE_CHOWN
805PyDoc_STRVAR(posix_chown__doc__,
806"chown(path, uid, gid)\n\n\
807Change the owner and group id of path to the numeric uid and gid.");
808
809static PyObject *
810posix_chown(PyObject *self, PyObject *args)
811{
812    char *path = NULL;
813    long uid, gid;
814    int res;
815    if (!PyArg_ParseTuple(args, "etll:chown",
816                          Py_FileSystemDefaultEncoding, &path,
817                          &uid, &gid))
818        return NULL;
819    Py_BEGIN_ALLOW_THREADS
820    res = chown(path, (uid_t) uid, (gid_t) gid);
821    Py_END_ALLOW_THREADS
822    if (res < 0)
823        return posix_error_with_allocated_filename(path);
824    PyMem_Free(path);
825    Py_INCREF(Py_None);
826    return Py_None;
827}
828#endif /* HAVE_CHOWN */
829
830#ifdef HAVE_FCHOWN
831PyDoc_STRVAR(posix_fchown__doc__,
832"fchown(fd, uid, gid)\n\n\
833Change the owner and group id of the file given by file descriptor\n\
834fd to the numeric uid and gid.");
835
836static PyObject *
837posix_fchown(PyObject *self, PyObject *args)
838{
839    int fd;
840    long uid, gid;
841    int res;
842    if (!PyArg_ParseTuple(args, "ill:chown", &fd, &uid, &gid))
843        return NULL;
844    Py_BEGIN_ALLOW_THREADS
845    res = fchown(fd, (uid_t) uid, (gid_t) gid);
846    Py_END_ALLOW_THREADS
847    if (res < 0)
848        return posix_error();
849    Py_RETURN_NONE;
850}
851#endif /* HAVE_FCHOWN */
852
853#ifdef HAVE_LCHOWN
854PyDoc_STRVAR(posix_lchown__doc__,
855"lchown(path, uid, gid)\n\n\
856Change the owner and group id of path to the numeric uid and gid.\n\
857This function will not follow symbolic links.");
858
859static PyObject *
860posix_lchown(PyObject *self, PyObject *args)
861{
862    char *path = NULL;
863    long uid, gid;
864    int res;
865    if (!PyArg_ParseTuple(args, "etll:lchown",
866                          Py_FileSystemDefaultEncoding, &path,
867                          &uid, &gid))
868        return NULL;
869    Py_BEGIN_ALLOW_THREADS
870    res = lchown(path, (uid_t) uid, (gid_t) gid);
871    Py_END_ALLOW_THREADS
872    if (res < 0)
873        return posix_error_with_allocated_filename(path);
874    PyMem_Free(path);
875    Py_INCREF(Py_None);
876    return Py_None;
877}
878#endif /* HAVE_LCHOWN */
879
880
881#ifdef HAVE_GETCWD
882PyDoc_STRVAR(posix_getcwd__doc__,
883"getcwd() -> path\n\n\
884Return a string representing the current working directory.");
885
886static PyObject *
887posix_getcwd(PyObject *self, PyObject *noargs)
888{
889    int bufsize_incr = 1024;
890    int bufsize = 0;
891    char *tmpbuf = NULL;
892    char *res = NULL;
893    PyObject *dynamic_return;
894
895    Py_BEGIN_ALLOW_THREADS
896    do {
897        bufsize = bufsize + bufsize_incr;
898        tmpbuf = malloc(bufsize);
899        if (tmpbuf == NULL) {
900            break;
901        }
902        res = getcwd(tmpbuf, bufsize);
903        if (res == NULL) {
904            free(tmpbuf);
905        }
906    } while ((res == NULL) && (errno == ERANGE));
907    Py_END_ALLOW_THREADS
908
909    if (res == NULL)
910        return posix_error();
911
912    dynamic_return = PyString_FromString(tmpbuf);
913    free(tmpbuf);
914
915    return dynamic_return;
916}
917
918#ifdef Py_USING_UNICODE
919PyDoc_STRVAR(posix_getcwdu__doc__,
920"getcwdu() -> path\n\n\
921Return a unicode string representing the current working directory.");
922
923static PyObject *
924posix_getcwdu(PyObject *self, PyObject *noargs)
925{
926    char buf[1026];
927    char *res;
928
929    Py_BEGIN_ALLOW_THREADS
930    res = getcwd(buf, sizeof buf);
931    Py_END_ALLOW_THREADS
932    if (res == NULL)
933        return posix_error();
934    return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict");
935}
936#endif /* Py_USING_UNICODE */
937#endif /* HAVE_GETCWD */
938
939
940PyDoc_STRVAR(posix_listdir__doc__,
941"listdir(path) -> list_of_strings\n\n\
942Return a list containing the names of the entries in the directory.\n\
943\n\
944    path: path of directory to list\n\
945\n\
946The list is in arbitrary order.  It does not include the special\n\
947entries '.' and '..' even if they are present in the directory.");
948
949static PyObject *
950posix_listdir(PyObject *self, PyObject *args)
951{
952    /* XXX Should redo this putting the (now four) versions of opendir
953       in separate files instead of having them all here... */
954
955    char           *name            = NULL;
956    char           *MBname;
957    PyObject       *d, *v;
958    DIR            *dirp;
959    struct dirent  *ep;
960    int             arg_is_unicode  = 1;
961
962    errno = 0;
963    if (!PyArg_ParseTuple(args, "U:listdir", &v)) {
964        arg_is_unicode = 0;
965        PyErr_Clear();
966    }
967    if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name))
968        return NULL;
969    Py_BEGIN_ALLOW_THREADS
970    dirp = opendir(name);
971    Py_END_ALLOW_THREADS
972    if (dirp == NULL) {
973        return posix_error_with_allocated_filename(name);
974    }
975    if ((d = PyList_New(0)) == NULL) {
976        Py_BEGIN_ALLOW_THREADS
977        closedir(dirp);
978        Py_END_ALLOW_THREADS
979        PyMem_Free(name);
980        return NULL;
981    }
982    if((MBname = malloc(NAME_MAX)) == NULL) {
983      Py_BEGIN_ALLOW_THREADS
984      closedir(dirp);
985      Py_END_ALLOW_THREADS
986      Py_DECREF(d);
987      PyMem_Free(name);
988      return NULL;
989    }
990    for (;;) {
991        errno = 0;
992        Py_BEGIN_ALLOW_THREADS
993        ep = readdir(dirp);
994        Py_END_ALLOW_THREADS
995        if (ep == NULL) {
996            if ((errno == 0) || (errno == EISDIR)) {
997                break;
998            } else {
999                Py_BEGIN_ALLOW_THREADS
1000                closedir(dirp);
1001                Py_END_ALLOW_THREADS
1002                Py_DECREF(d);
1003                return posix_error_with_allocated_filename(name);
1004            }
1005        }
1006        if (ep->FileName[0] == L'.' &&
1007            (NAMLEN(ep) == 1 ||
1008             (ep->FileName[1] == L'.' && NAMLEN(ep) == 2)))
1009            continue;
1010        if(wcstombs(MBname, ep->FileName, NAME_MAX) == -1) {
1011          free(MBname);
1012          Py_BEGIN_ALLOW_THREADS
1013          closedir(dirp);
1014          Py_END_ALLOW_THREADS
1015          Py_DECREF(d);
1016          PyMem_Free(name);
1017          return NULL;
1018        }
1019        v = PyString_FromStringAndSize(MBname, strlen(MBname));
1020        if (v == NULL) {
1021            Py_DECREF(d);
1022            d = NULL;
1023            break;
1024        }
1025#ifdef Py_USING_UNICODE
1026        if (arg_is_unicode) {
1027            PyObject *w;
1028
1029            w = PyUnicode_FromEncodedObject(v,
1030                                            Py_FileSystemDefaultEncoding,
1031                                            "strict");
1032            if (w != NULL) {
1033                Py_DECREF(v);
1034                v = w;
1035            }
1036            else {
1037                /* fall back to the original byte string, as
1038                   discussed in patch #683592 */
1039                PyErr_Clear();
1040            }
1041        }
1042#endif
1043        if (PyList_Append(d, v) != 0) {
1044            Py_DECREF(v);
1045            Py_DECREF(d);
1046            d = NULL;
1047            break;
1048        }
1049        Py_DECREF(v);
1050    }
1051    Py_BEGIN_ALLOW_THREADS
1052    closedir(dirp);
1053    Py_END_ALLOW_THREADS
1054    PyMem_Free(name);
1055    if(MBname != NULL) {
1056      free(MBname);
1057    }
1058
1059    return d;
1060
1061}  /* end of posix_listdir */
1062
1063#ifdef MS_WINDOWS
1064/* A helper function for abspath on win32 */
1065static PyObject *
1066posix__getfullpathname(PyObject *self, PyObject *args)
1067{
1068    /* assume encoded strings won't more than double no of chars */
1069    char inbuf[MAX_PATH*2];
1070    char *inbufp = inbuf;
1071    Py_ssize_t insize = sizeof(inbuf);
1072    char outbuf[MAX_PATH*2];
1073    char *temp;
1074
1075    PyUnicodeObject *po;
1076    if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) {
1077        Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
1078        Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
1079        Py_UNICODE *wtemp;
1080        DWORD result;
1081        PyObject *v;
1082        result = GetFullPathNameW(wpath,
1083                                  sizeof(woutbuf)/sizeof(woutbuf[0]),
1084                                  woutbuf, &wtemp);
1085        if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) {
1086            woutbufp = malloc(result * sizeof(Py_UNICODE));
1087            if (!woutbufp)
1088                return PyErr_NoMemory();
1089            result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
1090        }
1091        if (result)
1092            v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp));
1093        else
1094            v = win32_error_unicode("GetFullPathNameW", wpath);
1095        if (woutbufp != woutbuf)
1096            free(woutbufp);
1097        return v;
1098    }
1099    /* Drop the argument parsing error as narrow strings
1100       are also valid. */
1101    PyErr_Clear();
1102
1103    if (!PyArg_ParseTuple (args, "et#:_getfullpathname",
1104                           Py_FileSystemDefaultEncoding, &inbufp,
1105                           &insize))
1106        return NULL;
1107    if (!GetFullPathName(inbuf, sizeof(outbuf)/sizeof(outbuf[0]),
1108                         outbuf, &temp))
1109        return win32_error("GetFullPathName", inbuf);
1110    if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
1111        return PyUnicode_Decode(outbuf, strlen(outbuf),
1112                                Py_FileSystemDefaultEncoding, NULL);
1113    }
1114    return PyString_FromString(outbuf);
1115} /* end of posix__getfullpathname */
1116#endif /* MS_WINDOWS */
1117
1118PyDoc_STRVAR(posix_mkdir__doc__,
1119"mkdir(path [, mode=0777])\n\n\
1120Create a directory.");
1121
1122static PyObject *
1123posix_mkdir(PyObject *self, PyObject *args)
1124{
1125    int res;
1126    char *path = NULL;
1127    int mode = 0777;
1128
1129    if (!PyArg_ParseTuple(args, "et|i:mkdir",
1130                          Py_FileSystemDefaultEncoding, &path, &mode))
1131        return NULL;
1132    Py_BEGIN_ALLOW_THREADS
1133    res = mkdir(path, mode);
1134    Py_END_ALLOW_THREADS
1135    if (res < 0)
1136        return posix_error_with_allocated_filename(path);
1137    PyMem_Free(path);
1138    Py_INCREF(Py_None);
1139    return Py_None;
1140}
1141
1142
1143/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
1144#if defined(HAVE_SYS_RESOURCE_H)
1145#include <sys/resource.h>
1146#endif
1147
1148
1149#ifdef HAVE_NICE
1150PyDoc_STRVAR(posix_nice__doc__,
1151"nice(inc) -> new_priority\n\n\
1152Decrease the priority of process by inc and return the new priority.");
1153
1154static PyObject *
1155posix_nice(PyObject *self, PyObject *args)
1156{
1157    int increment, value;
1158
1159    if (!PyArg_ParseTuple(args, "i:nice", &increment))
1160        return NULL;
1161
1162    /* There are two flavours of 'nice': one that returns the new
1163       priority (as required by almost all standards out there) and the
1164       Linux/FreeBSD/BSDI one, which returns '0' on success and advices
1165       the use of getpriority() to get the new priority.
1166
1167       If we are of the nice family that returns the new priority, we
1168       need to clear errno before the call, and check if errno is filled
1169       before calling posix_error() on a returnvalue of -1, because the
1170       -1 may be the actual new priority! */
1171
1172    errno = 0;
1173    value = nice(increment);
1174#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
1175    if (value == 0)
1176        value = getpriority(PRIO_PROCESS, 0);
1177#endif
1178    if (value == -1 && errno != 0)
1179        /* either nice() or getpriority() returned an error */
1180        return posix_error();
1181    return PyInt_FromLong((long) value);
1182}
1183#endif /* HAVE_NICE */
1184
1185PyDoc_STRVAR(posix_rename__doc__,
1186"rename(old, new)\n\n\
1187Rename a file or directory.");
1188
1189static PyObject *
1190posix_rename(PyObject *self, PyObject *args)
1191{
1192    return posix_2str(args, "etet:rename", rename);
1193}
1194
1195
1196PyDoc_STRVAR(posix_rmdir__doc__,
1197"rmdir(path)\n\n\
1198Remove a directory.");
1199
1200static PyObject *
1201posix_rmdir(PyObject *self, PyObject *args)
1202{
1203    return posix_1str(args, "et:rmdir", rmdir);
1204}
1205
1206
1207PyDoc_STRVAR(posix_stat__doc__,
1208"stat(path) -> stat result\n\n\
1209Perform a stat system call on the given path.");
1210
1211static PyObject *
1212posix_stat(PyObject *self, PyObject *args)
1213{
1214    return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL);
1215}
1216
1217
1218#ifdef HAVE_SYSTEM
1219PyDoc_STRVAR(posix_system__doc__,
1220"system(command) -> exit_status\n\n\
1221Execute the command (a string) in a subshell.");
1222
1223static PyObject *
1224posix_system(PyObject *self, PyObject *args)
1225{
1226    char *command;
1227    long sts;
1228    if (!PyArg_ParseTuple(args, "s:system", &command))
1229        return NULL;
1230    Py_BEGIN_ALLOW_THREADS
1231    sts = system(command);
1232    Py_END_ALLOW_THREADS
1233    return PyInt_FromLong(sts);
1234}
1235#endif
1236
1237
1238PyDoc_STRVAR(posix_umask__doc__,
1239"umask(new_mask) -> old_mask\n\n\
1240Set the current numeric umask and return the previous umask.");
1241
1242static PyObject *
1243posix_umask(PyObject *self, PyObject *args)
1244{
1245    int i;
1246    if (!PyArg_ParseTuple(args, "i:umask", &i))
1247        return NULL;
1248    i = (int)umask(i);
1249    if (i < 0)
1250        return posix_error();
1251    return PyInt_FromLong((long)i);
1252}
1253
1254
1255PyDoc_STRVAR(posix_unlink__doc__,
1256"unlink(path)\n\n\
1257Remove a file (same as remove(path)).");
1258
1259PyDoc_STRVAR(posix_remove__doc__,
1260"remove(path)\n\n\
1261Remove a file (same as unlink(path)).");
1262
1263static PyObject *
1264posix_unlink(PyObject *self, PyObject *args)
1265{
1266    return posix_1str(args, "et:remove", unlink);
1267}
1268
1269
1270static int
1271extract_time(PyObject *t, time_t* sec, long* usec)
1272{
1273    time_t intval;
1274    if (PyFloat_Check(t)) {
1275        double tval = PyFloat_AsDouble(t);
1276        PyObject *intobj = PyNumber_Long(t);
1277        if (!intobj)
1278            return -1;
1279#if SIZEOF_TIME_T > SIZEOF_LONG
1280        intval = PyInt_AsUnsignedLongLongMask(intobj);
1281#else
1282        intval = PyInt_AsLong(intobj);
1283#endif
1284        Py_DECREF(intobj);
1285        if (intval == -1 && PyErr_Occurred())
1286            return -1;
1287        *sec = intval;
1288        *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
1289        if (*usec < 0)
1290            /* If rounding gave us a negative number,
1291               truncate.  */
1292            *usec = 0;
1293        return 0;
1294    }
1295#if SIZEOF_TIME_T > SIZEOF_LONG
1296    intval = PyInt_AsUnsignedLongLongMask(t);
1297#else
1298    intval = PyInt_AsLong(t);
1299#endif
1300    if (intval == -1 && PyErr_Occurred())
1301        return -1;
1302    *sec = intval;
1303    *usec = 0;
1304    return 0;
1305}
1306
1307PyDoc_STRVAR(posix_utime__doc__,
1308"utime(path, (atime, mtime))\n\
1309utime(path, None)\n\n\
1310Set the access and modified time of the file to the given values.  If the\n\
1311second form is used, set the access and modified times to the current time.");
1312
1313static PyObject *
1314posix_utime(PyObject *self, PyObject *args)
1315{
1316    char *path = NULL;
1317    time_t atime, mtime;
1318    long ausec, musec;
1319    int res;
1320    PyObject* arg;
1321
1322#if defined(HAVE_UTIMES)
1323    struct timeval buf[2];
1324#define ATIME buf[0].tv_sec
1325#define MTIME buf[1].tv_sec
1326#elif defined(HAVE_UTIME_H)
1327/* XXX should define struct utimbuf instead, above */
1328    struct utimbuf buf;
1329#define ATIME buf.actime
1330#define MTIME buf.modtime
1331#define UTIME_ARG &buf
1332#else /* HAVE_UTIMES */
1333    time_t buf[2];
1334#define ATIME buf[0]
1335#define MTIME buf[1]
1336#define UTIME_ARG buf
1337#endif /* HAVE_UTIMES */
1338
1339
1340    if (!PyArg_ParseTuple(args, "etO:utime",
1341                          Py_FileSystemDefaultEncoding, &path, &arg))
1342        return NULL;
1343    if (arg == Py_None) {
1344        /* optional time values not given */
1345        Py_BEGIN_ALLOW_THREADS
1346        res = utime(path, NULL);
1347        Py_END_ALLOW_THREADS
1348    }
1349    else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
1350        PyErr_SetString(PyExc_TypeError,
1351                        "utime() arg 2 must be a tuple (atime, mtime)");
1352        PyMem_Free(path);
1353        return NULL;
1354    }
1355    else {
1356        if (extract_time(PyTuple_GET_ITEM(arg, 0),
1357                         &atime, &ausec) == -1) {
1358            PyMem_Free(path);
1359            return NULL;
1360        }
1361        if (extract_time(PyTuple_GET_ITEM(arg, 1),
1362                         &mtime, &musec) == -1) {
1363            PyMem_Free(path);
1364            return NULL;
1365        }
1366        ATIME = atime;
1367        MTIME = mtime;
1368#ifdef HAVE_UTIMES
1369        buf[0].tv_usec = ausec;
1370        buf[1].tv_usec = musec;
1371        Py_BEGIN_ALLOW_THREADS
1372        res = utimes(path, buf);
1373        Py_END_ALLOW_THREADS
1374#else
1375        Py_BEGIN_ALLOW_THREADS
1376        res = utime(path, UTIME_ARG);
1377        Py_END_ALLOW_THREADS
1378#endif /* HAVE_UTIMES */
1379    }
1380    if (res < 0) {
1381        return posix_error_with_allocated_filename(path);
1382    }
1383    PyMem_Free(path);
1384    Py_INCREF(Py_None);
1385    return Py_None;
1386#undef UTIME_ARG
1387#undef ATIME
1388#undef MTIME
1389}
1390
1391
1392/* Process operations */
1393
1394PyDoc_STRVAR(posix__exit__doc__,
1395"_exit(status)\n\n\
1396Exit to the system with specified status, without normal exit processing.");
1397
1398static PyObject *
1399posix__exit(PyObject *self, PyObject *args)
1400{
1401    int sts;
1402    if (!PyArg_ParseTuple(args, "i:_exit", &sts))
1403        return NULL;
1404    _Exit(sts);
1405    return NULL; /* Make gcc -Wall happy */
1406}
1407
1408#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
1409static void
1410free_string_array(char **array, Py_ssize_t count)
1411{
1412    Py_ssize_t i;
1413    for (i = 0; i < count; i++)
1414        PyMem_Free(array[i]);
1415    PyMem_DEL(array);
1416}
1417#endif
1418
1419
1420#ifdef HAVE_EXECV
1421PyDoc_STRVAR(posix_execv__doc__,
1422"execv(path, args)\n\n\
1423Execute an executable path with arguments, replacing current process.\n\
1424\n\
1425    path: path of executable file\n\
1426    args: tuple or list of strings");
1427
1428static PyObject *
1429posix_execv(PyObject *self, PyObject *args)
1430{
1431    char *path;
1432    PyObject *argv;
1433    char **argvlist;
1434    Py_ssize_t i, argc;
1435    PyObject *(*getitem)(PyObject *, Py_ssize_t);
1436
1437    /* execv has two arguments: (path, argv), where
1438       argv is a list or tuple of strings. */
1439
1440    if (!PyArg_ParseTuple(args, "etO:execv",
1441                          Py_FileSystemDefaultEncoding,
1442                          &path, &argv))
1443        return NULL;
1444    if (PyList_Check(argv)) {
1445        argc = PyList_Size(argv);
1446        getitem = PyList_GetItem;
1447    }
1448    else if (PyTuple_Check(argv)) {
1449        argc = PyTuple_Size(argv);
1450        getitem = PyTuple_GetItem;
1451    }
1452    else {
1453        PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
1454        PyMem_Free(path);
1455        return NULL;
1456    }
1457    if (argc < 1) {
1458        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
1459        PyMem_Free(path);
1460        return NULL;
1461    }
1462
1463    argvlist = PyMem_NEW(char *, argc+1);
1464    if (argvlist == NULL) {
1465        PyMem_Free(path);
1466        return PyErr_NoMemory();
1467    }
1468    for (i = 0; i < argc; i++) {
1469        if (!PyArg_Parse((*getitem)(argv, i), "et",
1470                         Py_FileSystemDefaultEncoding,
1471                         &argvlist[i])) {
1472            free_string_array(argvlist, i);
1473            PyErr_SetString(PyExc_TypeError,
1474                            "execv() arg 2 must contain only strings");
1475            PyMem_Free(path);
1476            return NULL;
1477
1478        }
1479    }
1480    argvlist[argc] = NULL;
1481
1482    execv(path, argvlist);
1483
1484    /* If we get here it's definitely an error */
1485
1486    free_string_array(argvlist, argc);
1487    PyMem_Free(path);
1488    return posix_error();
1489}
1490
1491
1492PyDoc_STRVAR(posix_execve__doc__,
1493"execve(path, args, env)\n\n\
1494Execute a path with arguments and environment, replacing current process.\n\
1495\n\
1496    path: path of executable file\n\
1497    args: tuple or list of arguments\n\
1498    env: dictionary of strings mapping to strings");
1499
1500static PyObject *
1501posix_execve(PyObject *self, PyObject *args)
1502{
1503    char *path;
1504    PyObject *argv, *env;
1505    char **argvlist;
1506    char **envlist;
1507    PyObject *key, *val, *keys=NULL, *vals=NULL;
1508    Py_ssize_t i, pos, argc, envc;
1509    PyObject *(*getitem)(PyObject *, Py_ssize_t);
1510    Py_ssize_t lastarg = 0;
1511
1512    /* execve has three arguments: (path, argv, env), where
1513       argv is a list or tuple of strings and env is a dictionary
1514       like posix.environ. */
1515
1516    if (!PyArg_ParseTuple(args, "etOO:execve",
1517                          Py_FileSystemDefaultEncoding,
1518                          &path, &argv, &env))
1519        return NULL;
1520    if (PyList_Check(argv)) {
1521        argc = PyList_Size(argv);
1522        getitem = PyList_GetItem;
1523    }
1524    else if (PyTuple_Check(argv)) {
1525        argc = PyTuple_Size(argv);
1526        getitem = PyTuple_GetItem;
1527    }
1528    else {
1529        PyErr_SetString(PyExc_TypeError,
1530                        "execve() arg 2 must be a tuple or list");
1531        goto fail_0;
1532    }
1533    if (!PyMapping_Check(env)) {
1534        PyErr_SetString(PyExc_TypeError,
1535                        "execve() arg 3 must be a mapping object");
1536        goto fail_0;
1537    }
1538
1539    argvlist = PyMem_NEW(char *, argc+1);
1540    if (argvlist == NULL) {
1541        PyErr_NoMemory();
1542        goto fail_0;
1543    }
1544    for (i = 0; i < argc; i++) {
1545        if (!PyArg_Parse((*getitem)(argv, i),
1546                         "et;execve() arg 2 must contain only strings",
1547                         Py_FileSystemDefaultEncoding,
1548                         &argvlist[i]))
1549        {
1550            lastarg = i;
1551            goto fail_1;
1552        }
1553    }
1554    lastarg = argc;
1555    argvlist[argc] = NULL;
1556
1557    i = PyMapping_Size(env);
1558    if (i < 0)
1559        goto fail_1;
1560    envlist = PyMem_NEW(char *, i + 1);
1561    if (envlist == NULL) {
1562        PyErr_NoMemory();
1563        goto fail_1;
1564    }
1565    envc = 0;
1566    keys = PyMapping_Keys(env);
1567    vals = PyMapping_Values(env);
1568    if (!keys || !vals)
1569        goto fail_2;
1570    if (!PyList_Check(keys) || !PyList_Check(vals)) {
1571        PyErr_SetString(PyExc_TypeError,
1572                        "execve(): env.keys() or env.values() is not a list");
1573        goto fail_2;
1574    }
1575
1576    for (pos = 0; pos < i; pos++) {
1577        char *p, *k, *v;
1578        size_t len;
1579
1580        key = PyList_GetItem(keys, pos);
1581        val = PyList_GetItem(vals, pos);
1582        if (!key || !val)
1583            goto fail_2;
1584
1585        if (!PyArg_Parse(
1586                    key,
1587                    "s;execve() arg 3 contains a non-string key",
1588                    &k) ||
1589            !PyArg_Parse(
1590                val,
1591                "s;execve() arg 3 contains a non-string value",
1592                &v))
1593        {
1594            goto fail_2;
1595        }
1596
1597#if defined(PYOS_OS2)
1598        /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
1599        if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
1600#endif
1601        len = PyString_Size(key) + PyString_Size(val) + 2;
1602        p = PyMem_NEW(char, len);
1603        if (p == NULL) {
1604            PyErr_NoMemory();
1605            goto fail_2;
1606        }
1607        PyOS_snprintf(p, len, "%s=%s", k, v);
1608        envlist[envc++] = p;
1609#if defined(PYOS_OS2)
1610        }
1611#endif
1612    }
1613    envlist[envc] = 0;
1614
1615    execve(path, argvlist, envlist);
1616
1617    /* If we get here it's definitely an error */
1618
1619    (void) posix_error();
1620
1621  fail_2:
1622    while (--envc >= 0)
1623        PyMem_DEL(envlist[envc]);
1624    PyMem_DEL(envlist);
1625  fail_1:
1626    free_string_array(argvlist, lastarg);
1627    Py_XDECREF(vals);
1628    Py_XDECREF(keys);
1629  fail_0:
1630    PyMem_Free(path);
1631    return NULL;
1632}
1633#endif /* HAVE_EXECV */
1634
1635
1636#ifdef HAVE_SPAWNV
1637PyDoc_STRVAR(posix_spawnv__doc__,
1638"spawnv(mode, path, args)\n\n\
1639Execute the program 'path' in a new process.\n\
1640\n\
1641    mode: mode of process creation\n\
1642    path: path of executable file\n\
1643    args: tuple or list of strings");
1644
1645static PyObject *
1646posix_spawnv(PyObject *self, PyObject *args)
1647{
1648    char *path;
1649    PyObject *argv;
1650    char **argvlist;
1651    int mode, i;
1652    Py_ssize_t argc;
1653    Py_intptr_t spawnval;
1654    PyObject *(*getitem)(PyObject *, Py_ssize_t);
1655
1656    /* spawnv has three arguments: (mode, path, argv), where
1657       argv is a list or tuple of strings. */
1658
1659    if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode,
1660                          Py_FileSystemDefaultEncoding,
1661                          &path, &argv))
1662        return NULL;
1663    if (PyList_Check(argv)) {
1664        argc = PyList_Size(argv);
1665        getitem = PyList_GetItem;
1666    }
1667    else if (PyTuple_Check(argv)) {
1668        argc = PyTuple_Size(argv);
1669        getitem = PyTuple_GetItem;
1670    }
1671    else {
1672        PyErr_SetString(PyExc_TypeError,
1673                        "spawnv() arg 2 must be a tuple or list");
1674        PyMem_Free(path);
1675        return NULL;
1676    }
1677
1678    argvlist = PyMem_NEW(char *, argc+1);
1679    if (argvlist == NULL) {
1680        PyMem_Free(path);
1681        return PyErr_NoMemory();
1682    }
1683    for (i = 0; i < argc; i++) {
1684        if (!PyArg_Parse((*getitem)(argv, i), "et",
1685                         Py_FileSystemDefaultEncoding,
1686                         &argvlist[i])) {
1687            free_string_array(argvlist, i);
1688            PyErr_SetString(
1689                PyExc_TypeError,
1690                "spawnv() arg 2 must contain only strings");
1691            PyMem_Free(path);
1692            return NULL;
1693        }
1694    }
1695    argvlist[argc] = NULL;
1696
1697#if defined(PYOS_OS2) && defined(PYCC_GCC)
1698    Py_BEGIN_ALLOW_THREADS
1699    spawnval = spawnv(mode, path, argvlist);
1700    Py_END_ALLOW_THREADS
1701#else
1702    if (mode == _OLD_P_OVERLAY)
1703        mode = _P_OVERLAY;
1704
1705    Py_BEGIN_ALLOW_THREADS
1706    spawnval = _spawnv(mode, path, argvlist);
1707    Py_END_ALLOW_THREADS
1708#endif
1709
1710    free_string_array(argvlist, argc);
1711    PyMem_Free(path);
1712
1713    if (spawnval == -1)
1714        return posix_error();
1715    else
1716#if SIZEOF_LONG == SIZEOF_VOID_P
1717        return Py_BuildValue("l", (long) spawnval);
1718#else
1719        return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
1720#endif
1721}
1722
1723
1724PyDoc_STRVAR(posix_spawnve__doc__,
1725"spawnve(mode, path, args, env)\n\n\
1726Execute the program 'path' in a new process.\n\
1727\n\
1728    mode: mode of process creation\n\
1729    path: path of executable file\n\
1730    args: tuple or list of arguments\n\
1731    env: dictionary of strings mapping to strings");
1732
1733static PyObject *
1734posix_spawnve(PyObject *self, PyObject *args)
1735{
1736    char *path;
1737    PyObject *argv, *env;
1738    char **argvlist;
1739    char **envlist;
1740    PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
1741    int mode, pos, envc;
1742    Py_ssize_t argc, i;
1743    Py_intptr_t spawnval;
1744    PyObject *(*getitem)(PyObject *, Py_ssize_t);
1745    Py_ssize_t lastarg = 0;
1746
1747    /* spawnve has four arguments: (mode, path, argv, env), where
1748       argv is a list or tuple of strings and env is a dictionary
1749       like posix.environ. */
1750
1751    if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode,
1752                          Py_FileSystemDefaultEncoding,
1753                          &path, &argv, &env))
1754        return NULL;
1755    if (PyList_Check(argv)) {
1756        argc = PyList_Size(argv);
1757        getitem = PyList_GetItem;
1758    }
1759    else if (PyTuple_Check(argv)) {
1760        argc = PyTuple_Size(argv);
1761        getitem = PyTuple_GetItem;
1762    }
1763    else {
1764        PyErr_SetString(PyExc_TypeError,
1765                        "spawnve() arg 2 must be a tuple or list");
1766        goto fail_0;
1767    }
1768    if (!PyMapping_Check(env)) {
1769        PyErr_SetString(PyExc_TypeError,
1770                        "spawnve() arg 3 must be a mapping object");
1771        goto fail_0;
1772    }
1773
1774    argvlist = PyMem_NEW(char *, argc+1);
1775    if (argvlist == NULL) {
1776        PyErr_NoMemory();
1777        goto fail_0;
1778    }
1779    for (i = 0; i < argc; i++) {
1780        if (!PyArg_Parse((*getitem)(argv, i),
1781                     "et;spawnve() arg 2 must contain only strings",
1782                         Py_FileSystemDefaultEncoding,
1783                         &argvlist[i]))
1784        {
1785            lastarg = i;
1786            goto fail_1;
1787        }
1788    }
1789    lastarg = argc;
1790    argvlist[argc] = NULL;
1791
1792    i = PyMapping_Size(env);
1793    if (i < 0)
1794        goto fail_1;
1795    envlist = PyMem_NEW(char *, i + 1);
1796    if (envlist == NULL) {
1797        PyErr_NoMemory();
1798        goto fail_1;
1799    }
1800    envc = 0;
1801    keys = PyMapping_Keys(env);
1802    vals = PyMapping_Values(env);
1803    if (!keys || !vals)
1804        goto fail_2;
1805    if (!PyList_Check(keys) || !PyList_Check(vals)) {
1806        PyErr_SetString(PyExc_TypeError,
1807                        "spawnve(): env.keys() or env.values() is not a list");
1808        goto fail_2;
1809    }
1810
1811    for (pos = 0; pos < i; pos++) {
1812        char *p, *k, *v;
1813        size_t len;
1814
1815        key = PyList_GetItem(keys, pos);
1816        val = PyList_GetItem(vals, pos);
1817        if (!key || !val)
1818            goto fail_2;
1819
1820        if (!PyArg_Parse(
1821                    key,
1822                    "s;spawnve() arg 3 contains a non-string key",
1823                    &k) ||
1824            !PyArg_Parse(
1825                val,
1826                "s;spawnve() arg 3 contains a non-string value",
1827                &v))
1828        {
1829            goto fail_2;
1830        }
1831        len = PyString_Size(key) + PyString_Size(val) + 2;
1832        p = PyMem_NEW(char, len);
1833        if (p == NULL) {
1834            PyErr_NoMemory();
1835            goto fail_2;
1836        }
1837        PyOS_snprintf(p, len, "%s=%s", k, v);
1838        envlist[envc++] = p;
1839    }
1840    envlist[envc] = 0;
1841
1842#if defined(PYOS_OS2) && defined(PYCC_GCC)
1843    Py_BEGIN_ALLOW_THREADS
1844    spawnval = spawnve(mode, path, argvlist, envlist);
1845    Py_END_ALLOW_THREADS
1846#else
1847    if (mode == _OLD_P_OVERLAY)
1848        mode = _P_OVERLAY;
1849
1850    Py_BEGIN_ALLOW_THREADS
1851    spawnval = _spawnve(mode, path, argvlist, envlist);
1852    Py_END_ALLOW_THREADS
1853#endif
1854
1855    if (spawnval == -1)
1856        (void) posix_error();
1857    else
1858#if SIZEOF_LONG == SIZEOF_VOID_P
1859        res = Py_BuildValue("l", (long) spawnval);
1860#else
1861        res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
1862#endif
1863
1864  fail_2:
1865    while (--envc >= 0)
1866        PyMem_DEL(envlist[envc]);
1867    PyMem_DEL(envlist);
1868  fail_1:
1869    free_string_array(argvlist, lastarg);
1870    Py_XDECREF(vals);
1871    Py_XDECREF(keys);
1872  fail_0:
1873    PyMem_Free(path);
1874    return res;
1875}
1876
1877/* OS/2 supports spawnvp & spawnvpe natively */
1878#if defined(PYOS_OS2)
1879PyDoc_STRVAR(posix_spawnvp__doc__,
1880"spawnvp(mode, file, args)\n\n\
1881Execute the program 'file' in a new process, using the environment\n\
1882search path to find the file.\n\
1883\n\
1884    mode: mode of process creation\n\
1885    file: executable file name\n\
1886    args: tuple or list of strings");
1887
1888static PyObject *
1889posix_spawnvp(PyObject *self, PyObject *args)
1890{
1891    char *path;
1892    PyObject *argv;
1893    char **argvlist;
1894    int mode, i, argc;
1895    Py_intptr_t spawnval;
1896    PyObject *(*getitem)(PyObject *, Py_ssize_t);
1897
1898    /* spawnvp has three arguments: (mode, path, argv), where
1899       argv is a list or tuple of strings. */
1900
1901    if (!PyArg_ParseTuple(args, "ietO:spawnvp", &mode,
1902                          Py_FileSystemDefaultEncoding,
1903                          &path, &argv))
1904        return NULL;
1905    if (PyList_Check(argv)) {
1906        argc = PyList_Size(argv);
1907        getitem = PyList_GetItem;
1908    }
1909    else if (PyTuple_Check(argv)) {
1910        argc = PyTuple_Size(argv);
1911        getitem = PyTuple_GetItem;
1912    }
1913    else {
1914        PyErr_SetString(PyExc_TypeError,
1915                        "spawnvp() arg 2 must be a tuple or list");
1916        PyMem_Free(path);
1917        return NULL;
1918    }
1919
1920    argvlist = PyMem_NEW(char *, argc+1);
1921    if (argvlist == NULL) {
1922        PyMem_Free(path);
1923        return PyErr_NoMemory();
1924    }
1925    for (i = 0; i < argc; i++) {
1926        if (!PyArg_Parse((*getitem)(argv, i), "et",
1927                         Py_FileSystemDefaultEncoding,
1928                         &argvlist[i])) {
1929            free_string_array(argvlist, i);
1930            PyErr_SetString(
1931                PyExc_TypeError,
1932                "spawnvp() arg 2 must contain only strings");
1933            PyMem_Free(path);
1934            return NULL;
1935        }
1936    }
1937    argvlist[argc] = NULL;
1938
1939    Py_BEGIN_ALLOW_THREADS
1940#if defined(PYCC_GCC)
1941    spawnval = spawnvp(mode, path, argvlist);
1942#else
1943    spawnval = _spawnvp(mode, path, argvlist);
1944#endif
1945    Py_END_ALLOW_THREADS
1946
1947    free_string_array(argvlist, argc);
1948    PyMem_Free(path);
1949
1950    if (spawnval == -1)
1951        return posix_error();
1952    else
1953        return Py_BuildValue("l", (long) spawnval);
1954}
1955
1956
1957PyDoc_STRVAR(posix_spawnvpe__doc__,
1958"spawnvpe(mode, file, args, env)\n\n\
1959Execute the program 'file' in a new process, using the environment\n\
1960search path to find the file.\n\
1961\n\
1962    mode: mode of process creation\n\
1963    file: executable file name\n\
1964    args: tuple or list of arguments\n\
1965    env: dictionary of strings mapping to strings");
1966
1967static PyObject *
1968posix_spawnvpe(PyObject *self, PyObject *args)
1969{
1970    char *path;
1971    PyObject *argv, *env;
1972    char **argvlist;
1973    char **envlist;
1974    PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
1975    int mode, i, pos, argc, envc;
1976    Py_intptr_t spawnval;
1977    PyObject *(*getitem)(PyObject *, Py_ssize_t);
1978    int lastarg = 0;
1979
1980    /* spawnvpe has four arguments: (mode, path, argv, env), where
1981       argv is a list or tuple of strings and env is a dictionary
1982       like posix.environ. */
1983
1984    if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
1985                          Py_FileSystemDefaultEncoding,
1986                          &path, &argv, &env))
1987        return NULL;
1988    if (PyList_Check(argv)) {
1989        argc = PyList_Size(argv);
1990        getitem = PyList_GetItem;
1991    }
1992    else if (PyTuple_Check(argv)) {
1993        argc = PyTuple_Size(argv);
1994        getitem = PyTuple_GetItem;
1995    }
1996    else {
1997        PyErr_SetString(PyExc_TypeError,
1998                        "spawnvpe() arg 2 must be a tuple or list");
1999        goto fail_0;
2000    }
2001    if (!PyMapping_Check(env)) {
2002        PyErr_SetString(PyExc_TypeError,
2003                        "spawnvpe() arg 3 must be a mapping object");
2004        goto fail_0;
2005    }
2006
2007    argvlist = PyMem_NEW(char *, argc+1);
2008    if (argvlist == NULL) {
2009        PyErr_NoMemory();
2010        goto fail_0;
2011    }
2012    for (i = 0; i < argc; i++) {
2013        if (!PyArg_Parse((*getitem)(argv, i),
2014                     "et;spawnvpe() arg 2 must contain only strings",
2015                         Py_FileSystemDefaultEncoding,
2016                         &argvlist[i]))
2017        {
2018            lastarg = i;
2019            goto fail_1;
2020        }
2021    }
2022    lastarg = argc;
2023    argvlist[argc] = NULL;
2024
2025    i = PyMapping_Size(env);
2026    if (i < 0)
2027        goto fail_1;
2028    envlist = PyMem_NEW(char *, i + 1);
2029    if (envlist == NULL) {
2030        PyErr_NoMemory();
2031        goto fail_1;
2032    }
2033    envc = 0;
2034    keys = PyMapping_Keys(env);
2035    vals = PyMapping_Values(env);
2036    if (!keys || !vals)
2037        goto fail_2;
2038    if (!PyList_Check(keys) || !PyList_Check(vals)) {
2039        PyErr_SetString(PyExc_TypeError,
2040                        "spawnvpe(): env.keys() or env.values() is not a list");
2041        goto fail_2;
2042    }
2043
2044    for (pos = 0; pos < i; pos++) {
2045        char *p, *k, *v;
2046        size_t len;
2047
2048        key = PyList_GetItem(keys, pos);
2049        val = PyList_GetItem(vals, pos);
2050        if (!key || !val)
2051            goto fail_2;
2052
2053        if (!PyArg_Parse(
2054                    key,
2055                    "s;spawnvpe() arg 3 contains a non-string key",
2056                    &k) ||
2057            !PyArg_Parse(
2058                val,
2059                "s;spawnvpe() arg 3 contains a non-string value",
2060                &v))
2061        {
2062            goto fail_2;
2063        }
2064        len = PyString_Size(key) + PyString_Size(val) + 2;
2065        p = PyMem_NEW(char, len);
2066        if (p == NULL) {
2067            PyErr_NoMemory();
2068            goto fail_2;
2069        }
2070        PyOS_snprintf(p, len, "%s=%s", k, v);
2071        envlist[envc++] = p;
2072    }
2073    envlist[envc] = 0;
2074
2075    Py_BEGIN_ALLOW_THREADS
2076#if defined(PYCC_GCC)
2077    spawnval = spawnvpe(mode, path, argvlist, envlist);
2078#else
2079    spawnval = _spawnvpe(mode, path, argvlist, envlist);
2080#endif
2081    Py_END_ALLOW_THREADS
2082
2083    if (spawnval == -1)
2084        (void) posix_error();
2085    else
2086        res = Py_BuildValue("l", (long) spawnval);
2087
2088  fail_2:
2089    while (--envc >= 0)
2090        PyMem_DEL(envlist[envc]);
2091    PyMem_DEL(envlist);
2092  fail_1:
2093    free_string_array(argvlist, lastarg);
2094    Py_XDECREF(vals);
2095    Py_XDECREF(keys);
2096  fail_0:
2097    PyMem_Free(path);
2098    return res;
2099}
2100#endif /* PYOS_OS2 */
2101#endif /* HAVE_SPAWNV */
2102
2103
2104#ifdef HAVE_FORK1
2105PyDoc_STRVAR(posix_fork1__doc__,
2106"fork1() -> pid\n\n\
2107Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
2108\n\
2109Return 0 to child process and PID of child to parent process.");
2110
2111static PyObject *
2112posix_fork1(PyObject *self, PyObject *noargs)
2113{
2114    pid_t pid;
2115    int result = 0;
2116    _PyImport_AcquireLock();
2117    pid = fork1();
2118    if (pid == 0) {
2119        /* child: this clobbers and resets the import lock. */
2120        PyOS_AfterFork();
2121    } else {
2122        /* parent: release the import lock. */
2123        result = _PyImport_ReleaseLock();
2124    }
2125    if (pid == -1)
2126        return posix_error();
2127    if (result < 0) {
2128        /* Don't clobber the OSError if the fork failed. */
2129        PyErr_SetString(PyExc_RuntimeError,
2130                        "not holding the import lock");
2131        return NULL;
2132    }
2133    return PyLong_FromPid(pid);
2134}
2135#endif
2136
2137
2138#ifdef HAVE_FORK
2139PyDoc_STRVAR(posix_fork__doc__,
2140"fork() -> pid\n\n\
2141Fork a child process.\n\
2142Return 0 to child process and PID of child to parent process.");
2143
2144static PyObject *
2145posix_fork(PyObject *self, PyObject *noargs)
2146{
2147    pid_t pid;
2148    int result = 0;
2149    _PyImport_AcquireLock();
2150    pid = fork();
2151    if (pid == 0) {
2152        /* child: this clobbers and resets the import lock. */
2153        PyOS_AfterFork();
2154    } else {
2155        /* parent: release the import lock. */
2156        result = _PyImport_ReleaseLock();
2157    }
2158    if (pid == -1)
2159        return posix_error();
2160    if (result < 0) {
2161        /* Don't clobber the OSError if the fork failed. */
2162        PyErr_SetString(PyExc_RuntimeError,
2163                        "not holding the import lock");
2164        return NULL;
2165    }
2166    return PyLong_FromPid(pid);
2167}
2168#endif
2169
2170/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
2171/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
2172#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
2173#define DEV_PTY_FILE "/dev/ptc"
2174#define HAVE_DEV_PTMX
2175#else
2176#define DEV_PTY_FILE "/dev/ptmx"
2177#endif
2178
2179#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
2180#ifdef HAVE_PTY_H
2181#include <pty.h>
2182#else
2183#ifdef HAVE_LIBUTIL_H
2184#include <libutil.h>
2185#else
2186#ifdef HAVE_UTIL_H
2187#include <util.h>
2188#endif /* HAVE_UTIL_H */
2189#endif /* HAVE_LIBUTIL_H */
2190#endif /* HAVE_PTY_H */
2191#ifdef HAVE_STROPTS_H
2192#include <stropts.h>
2193#endif
2194#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
2195
2196#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
2197PyDoc_STRVAR(posix_openpty__doc__,
2198"openpty() -> (master_fd, slave_fd)\n\n\
2199Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
2200
2201static PyObject *
2202posix_openpty(PyObject *self, PyObject *noargs)
2203{
2204    int master_fd, slave_fd;
2205#ifndef HAVE_OPENPTY
2206    char * slave_name;
2207#endif
2208#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
2209    PyOS_sighandler_t sig_saved;
2210#ifdef sun
2211    extern char *ptsname(int fildes);
2212#endif
2213#endif
2214
2215#ifdef HAVE_OPENPTY
2216    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
2217        return posix_error();
2218#elif defined(HAVE__GETPTY)
2219    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
2220    if (slave_name == NULL)
2221        return posix_error();
2222
2223    slave_fd = open(slave_name, O_RDWR);
2224    if (slave_fd < 0)
2225        return posix_error();
2226#else
2227    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
2228    if (master_fd < 0)
2229        return posix_error();
2230    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
2231    /* change permission of slave */
2232    if (grantpt(master_fd) < 0) {
2233        PyOS_setsig(SIGCHLD, sig_saved);
2234        return posix_error();
2235    }
2236    /* unlock slave */
2237    if (unlockpt(master_fd) < 0) {
2238        PyOS_setsig(SIGCHLD, sig_saved);
2239        return posix_error();
2240    }
2241    PyOS_setsig(SIGCHLD, sig_saved);
2242    slave_name = ptsname(master_fd); /* get name of slave */
2243    if (slave_name == NULL)
2244        return posix_error();
2245    slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
2246    if (slave_fd < 0)
2247        return posix_error();
2248#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
2249    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
2250    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
2251#ifndef __hpux
2252    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
2253#endif /* __hpux */
2254#endif /* HAVE_CYGWIN */
2255#endif /* HAVE_OPENPTY */
2256
2257    return Py_BuildValue("(ii)", master_fd, slave_fd);
2258
2259}
2260#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
2261
2262#ifdef HAVE_FORKPTY
2263PyDoc_STRVAR(posix_forkpty__doc__,
2264"forkpty() -> (pid, master_fd)\n\n\
2265Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
2266Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
2267To both, return fd of newly opened pseudo-terminal.\n");
2268
2269static PyObject *
2270posix_forkpty(PyObject *self, PyObject *noargs)
2271{
2272    int master_fd = -1, result = 0;
2273    pid_t pid;
2274
2275    _PyImport_AcquireLock();
2276    pid = forkpty(&master_fd, NULL, NULL, NULL);
2277    if (pid == 0) {
2278        /* child: this clobbers and resets the import lock. */
2279        PyOS_AfterFork();
2280    } else {
2281        /* parent: release the import lock. */
2282        result = _PyImport_ReleaseLock();
2283    }
2284    if (pid == -1)
2285        return posix_error();
2286    if (result < 0) {
2287        /* Don't clobber the OSError if the fork failed. */
2288        PyErr_SetString(PyExc_RuntimeError,
2289                        "not holding the import lock");
2290        return NULL;
2291    }
2292    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
2293}
2294#endif
2295
2296#ifdef HAVE_GETEGID
2297PyDoc_STRVAR(posix_getegid__doc__,
2298"getegid() -> egid\n\n\
2299Return the current process's effective group id.");
2300
2301static PyObject *
2302posix_getegid(PyObject *self, PyObject *noargs)
2303{
2304    return PyInt_FromLong((long)getegid());
2305}
2306#endif
2307
2308
2309#ifdef HAVE_GETEUID
2310PyDoc_STRVAR(posix_geteuid__doc__,
2311"geteuid() -> euid\n\n\
2312Return the current process's effective user id.");
2313
2314static PyObject *
2315posix_geteuid(PyObject *self, PyObject *noargs)
2316{
2317    return PyInt_FromLong((long)geteuid());
2318}
2319#endif
2320
2321
2322#ifdef HAVE_GETGID
2323PyDoc_STRVAR(posix_getgid__doc__,
2324"getgid() -> gid\n\n\
2325Return the current process's group id.");
2326
2327static PyObject *
2328posix_getgid(PyObject *self, PyObject *noargs)
2329{
2330    return PyInt_FromLong((long)getgid());
2331}
2332#endif
2333
2334
2335PyDoc_STRVAR(posix_getpid__doc__,
2336"getpid() -> pid\n\n\
2337Return the current process id");
2338
2339static PyObject *
2340posix_getpid(PyObject *self, PyObject *noargs)
2341{
2342    return PyLong_FromPid(getpid());
2343}
2344
2345
2346#ifdef HAVE_GETGROUPS
2347PyDoc_STRVAR(posix_getgroups__doc__,
2348"getgroups() -> list of group IDs\n\n\
2349Return list of supplemental group IDs for the process.");
2350
2351static PyObject *
2352posix_getgroups(PyObject *self, PyObject *noargs)
2353{
2354    PyObject *result = NULL;
2355
2356#ifdef NGROUPS_MAX
2357#define MAX_GROUPS NGROUPS_MAX
2358#else
2359    /* defined to be 16 on Solaris7, so this should be a small number */
2360#define MAX_GROUPS 64
2361#endif
2362    gid_t grouplist[MAX_GROUPS];
2363
2364    /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
2365     * This is a helper variable to store the intermediate result when
2366     * that happens.
2367     *
2368     * To keep the code readable the OSX behaviour is unconditional,
2369     * according to the POSIX spec this should be safe on all unix-y
2370     * systems.
2371     */
2372    gid_t* alt_grouplist = grouplist;
2373    int n;
2374
2375    n = getgroups(MAX_GROUPS, grouplist);
2376    if (n < 0) {
2377        if (errno == EINVAL) {
2378            n = getgroups(0, NULL);
2379            if (n == -1) {
2380                return posix_error();
2381            }
2382            if (n == 0) {
2383                /* Avoid malloc(0) */
2384                alt_grouplist = grouplist;
2385            } else {
2386                alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
2387                if (alt_grouplist == NULL) {
2388                    errno = EINVAL;
2389                    return posix_error();
2390                }
2391                n = getgroups(n, alt_grouplist);
2392                if (n == -1) {
2393                    PyMem_Free(alt_grouplist);
2394                    return posix_error();
2395                }
2396            }
2397        } else {
2398            return posix_error();
2399        }
2400    }
2401    result = PyList_New(n);
2402    if (result != NULL) {
2403        int i;
2404        for (i = 0; i < n; ++i) {
2405            PyObject *o = PyInt_FromLong((long)alt_grouplist[i]);
2406            if (o == NULL) {
2407                Py_DECREF(result);
2408                result = NULL;
2409                break;
2410            }
2411            PyList_SET_ITEM(result, i, o);
2412        }
2413    }
2414
2415    if (alt_grouplist != grouplist) {
2416        PyMem_Free(alt_grouplist);
2417    }
2418
2419    return result;
2420}
2421#endif
2422
2423#ifdef HAVE_INITGROUPS
2424PyDoc_STRVAR(posix_initgroups__doc__,
2425"initgroups(username, gid) -> None\n\n\
2426Call the system initgroups() to initialize the group access list with all of\n\
2427the groups of which the specified username is a member, plus the specified\n\
2428group id.");
2429
2430static PyObject *
2431posix_initgroups(PyObject *self, PyObject *args)
2432{
2433    char *username;
2434    long gid;
2435
2436    if (!PyArg_ParseTuple(args, "sl:initgroups", &username, &gid))
2437        return NULL;
2438
2439    if (initgroups(username, (gid_t) gid) == -1)
2440        return PyErr_SetFromErrno(PyExc_OSError);
2441
2442    Py_INCREF(Py_None);
2443    return Py_None;
2444}
2445#endif
2446
2447#ifdef HAVE_GETPGID
2448PyDoc_STRVAR(posix_getpgid__doc__,
2449"getpgid(pid) -> pgid\n\n\
2450Call the system call getpgid().");
2451
2452static PyObject *
2453posix_getpgid(PyObject *self, PyObject *args)
2454{
2455    pid_t pid, pgid;
2456    if (!PyArg_ParseTuple(args, PARSE_PID ":getpgid", &pid))
2457        return NULL;
2458    pgid = getpgid(pid);
2459    if (pgid < 0)
2460        return posix_error();
2461    return PyLong_FromPid(pgid);
2462}
2463#endif /* HAVE_GETPGID */
2464
2465
2466#ifdef HAVE_GETPGRP
2467PyDoc_STRVAR(posix_getpgrp__doc__,
2468"getpgrp() -> pgrp\n\n\
2469Return the current process group id.");
2470
2471static PyObject *
2472posix_getpgrp(PyObject *self, PyObject *noargs)
2473{
2474#ifdef GETPGRP_HAVE_ARG
2475    return PyLong_FromPid(getpgrp(0));
2476#else /* GETPGRP_HAVE_ARG */
2477    return PyLong_FromPid(getpgrp());
2478#endif /* GETPGRP_HAVE_ARG */
2479}
2480#endif /* HAVE_GETPGRP */
2481
2482
2483#ifdef HAVE_SETPGRP
2484PyDoc_STRVAR(posix_setpgrp__doc__,
2485"setpgrp()\n\n\
2486Make this process the process group leader.");
2487
2488static PyObject *
2489posix_setpgrp(PyObject *self, PyObject *noargs)
2490{
2491#ifdef SETPGRP_HAVE_ARG
2492    if (setpgrp(0, 0) < 0)
2493#else /* SETPGRP_HAVE_ARG */
2494    if (setpgrp() < 0)
2495#endif /* SETPGRP_HAVE_ARG */
2496        return posix_error();
2497    Py_INCREF(Py_None);
2498    return Py_None;
2499}
2500
2501#endif /* HAVE_SETPGRP */
2502
2503#ifdef HAVE_GETPPID
2504PyDoc_STRVAR(posix_getppid__doc__,
2505"getppid() -> ppid\n\n\
2506Return the parent's process id.");
2507
2508static PyObject *
2509posix_getppid(PyObject *self, PyObject *noargs)
2510{
2511    return PyLong_FromPid(getppid());
2512}
2513#endif
2514
2515
2516#ifdef HAVE_GETLOGIN
2517PyDoc_STRVAR(posix_getlogin__doc__,
2518"getlogin() -> string\n\n\
2519Return the actual login name.");
2520
2521static PyObject *
2522posix_getlogin(PyObject *self, PyObject *noargs)
2523{
2524    PyObject *result = NULL;
2525    char *name;
2526    int old_errno = errno;
2527
2528    errno = 0;
2529    name = getlogin();
2530    if (name == NULL) {
2531        if (errno)
2532        posix_error();
2533        else
2534        PyErr_SetString(PyExc_OSError,
2535                        "unable to determine login name");
2536    }
2537    else
2538        result = PyString_FromString(name);
2539    errno = old_errno;
2540
2541    return result;
2542}
2543#endif
2544
2545#ifndef UEFI_C_SOURCE
2546PyDoc_STRVAR(posix_getuid__doc__,
2547"getuid() -> uid\n\n\
2548Return the current process's user id.");
2549
2550static PyObject *
2551posix_getuid(PyObject *self, PyObject *noargs)
2552{
2553    return PyInt_FromLong((long)getuid());
2554}
2555#endif  /* UEFI_C_SOURCE */
2556
2557#ifdef HAVE_KILL
2558PyDoc_STRVAR(posix_kill__doc__,
2559"kill(pid, sig)\n\n\
2560Kill a process with a signal.");
2561
2562static PyObject *
2563posix_kill(PyObject *self, PyObject *args)
2564{
2565    pid_t pid;
2566    int sig;
2567    if (!PyArg_ParseTuple(args, PARSE_PID "i:kill", &pid, &sig))
2568        return NULL;
2569#if defined(PYOS_OS2) && !defined(PYCC_GCC)
2570    if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
2571        APIRET rc;
2572        if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
2573            return os2_error(rc);
2574
2575    } else if (sig == XCPT_SIGNAL_KILLPROC) {
2576        APIRET rc;
2577        if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
2578            return os2_error(rc);
2579
2580    } else
2581        return NULL; /* Unrecognized Signal Requested */
2582#else
2583    if (kill(pid, sig) == -1)
2584        return posix_error();
2585#endif
2586    Py_INCREF(Py_None);
2587    return Py_None;
2588}
2589#endif
2590
2591#ifdef HAVE_KILLPG
2592PyDoc_STRVAR(posix_killpg__doc__,
2593"killpg(pgid, sig)\n\n\
2594Kill a process group with a signal.");
2595
2596static PyObject *
2597posix_killpg(PyObject *self, PyObject *args)
2598{
2599    int sig;
2600    pid_t pgid;
2601    /* XXX some man pages make the `pgid` parameter an int, others
2602       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
2603       take the same type. Moreover, pid_t is always at least as wide as
2604       int (else compilation of this module fails), which is safe. */
2605    if (!PyArg_ParseTuple(args, PARSE_PID "i:killpg", &pgid, &sig))
2606        return NULL;
2607    if (killpg(pgid, sig) == -1)
2608        return posix_error();
2609    Py_INCREF(Py_None);
2610    return Py_None;
2611}
2612#endif
2613
2614#ifdef HAVE_PLOCK
2615
2616#ifdef HAVE_SYS_LOCK_H
2617#include <sys/lock.h>
2618#endif
2619
2620PyDoc_STRVAR(posix_plock__doc__,
2621"plock(op)\n\n\
2622Lock program segments into memory.");
2623
2624static PyObject *
2625posix_plock(PyObject *self, PyObject *args)
2626{
2627    int op;
2628    if (!PyArg_ParseTuple(args, "i:plock", &op))
2629        return NULL;
2630    if (plock(op) == -1)
2631        return posix_error();
2632    Py_INCREF(Py_None);
2633    return Py_None;
2634}
2635#endif
2636
2637
2638#ifdef HAVE_POPEN
2639PyDoc_STRVAR(posix_popen__doc__,
2640"popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\
2641Open a pipe to/from a command returning a file object.");
2642
2643#if defined(PYOS_OS2)
2644#if defined(PYCC_VACPP)
2645static int
2646async_system(const char *command)
2647{
2648    char errormsg[256], args[1024];
2649    RESULTCODES rcodes;
2650    APIRET rc;
2651
2652    char *shell = getenv("COMSPEC");
2653    if (!shell)
2654        shell = "cmd";
2655
2656    /* avoid overflowing the argument buffer */
2657    if (strlen(shell) + 3 + strlen(command) >= 1024)
2658        return ERROR_NOT_ENOUGH_MEMORY
2659
2660    args[0] = '\0';
2661    strcat(args, shell);
2662    strcat(args, "/c ");
2663    strcat(args, command);
2664
2665    /* execute asynchronously, inheriting the environment */
2666    rc = DosExecPgm(errormsg,
2667                    sizeof(errormsg),
2668                    EXEC_ASYNC,
2669                    args,
2670                    NULL,
2671                    &rcodes,
2672                    shell);
2673    return rc;
2674}
2675
2676static FILE *
2677popen(const char *command, const char *mode, int pipesize, int *err)
2678{
2679    int oldfd, tgtfd;
2680    HFILE pipeh[2];
2681    APIRET rc;
2682
2683    /* mode determines which of stdin or stdout is reconnected to
2684     * the pipe to the child
2685     */
2686    if (strchr(mode, 'r') != NULL) {
2687        tgt_fd = 1;             /* stdout */
2688    } else if (strchr(mode, 'w')) {
2689        tgt_fd = 0;             /* stdin */
2690    } else {
2691        *err = ERROR_INVALID_ACCESS;
2692        return NULL;
2693    }
2694
2695    /* setup the pipe */
2696    if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) {
2697        *err = rc;
2698        return NULL;
2699    }
2700
2701    /* prevent other threads accessing stdio */
2702    DosEnterCritSec();
2703
2704    /* reconnect stdio and execute child */
2705    oldfd = dup(tgtfd);
2706    close(tgtfd);
2707    if (dup2(pipeh[tgtfd], tgtfd) == 0) {
2708        DosClose(pipeh[tgtfd]);
2709        rc = async_system(command);
2710    }
2711
2712    /* restore stdio */
2713    dup2(oldfd, tgtfd);
2714    close(oldfd);
2715
2716    /* allow other threads access to stdio */
2717    DosExitCritSec();
2718
2719    /* if execution of child was successful return file stream */
2720    if (rc == NO_ERROR)
2721        return fdopen(pipeh[1 - tgtfd], mode);
2722    else {
2723        DosClose(pipeh[1 - tgtfd]);
2724        *err = rc;
2725        return NULL;
2726    }
2727}
2728
2729static PyObject *
2730posix_popen(PyObject *self, PyObject *args)
2731{
2732    char *name;
2733    char *mode = "r";
2734    int   err, bufsize = -1;
2735    FILE *fp;
2736    PyObject *f;
2737    if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
2738        return NULL;
2739    Py_BEGIN_ALLOW_THREADS
2740    fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err);
2741    Py_END_ALLOW_THREADS
2742    if (fp == NULL)
2743        return os2_error(err);
2744
2745    f = PyFile_FromFile(fp, name, mode, fclose);
2746    if (f != NULL)
2747        PyFile_SetBufSize(f, bufsize);
2748    return f;
2749}
2750
2751#elif defined(PYCC_GCC)
2752
2753/* standard posix version of popen() support */
2754static PyObject *
2755posix_popen(PyObject *self, PyObject *args)
2756{
2757    char *name;
2758    char *mode = "r";
2759    int bufsize = -1;
2760    FILE *fp;
2761    PyObject *f;
2762    if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
2763        return NULL;
2764    Py_BEGIN_ALLOW_THREADS
2765    fp = popen(name, mode);
2766    Py_END_ALLOW_THREADS
2767    if (fp == NULL)
2768        return posix_error();
2769    f = PyFile_FromFile(fp, name, mode, pclose);
2770    if (f != NULL)
2771        PyFile_SetBufSize(f, bufsize);
2772    return f;
2773}
2774
2775/* fork() under OS/2 has lots'o'warts
2776 * EMX supports pipe() and spawn*() so we can synthesize popen[234]()
2777 * most of this code is a ripoff of the win32 code, but using the
2778 * capabilities of EMX's C library routines
2779 */
2780
2781/* These tell _PyPopen() whether to return 1, 2, or 3 file objects. */
2782#define POPEN_1 1
2783#define POPEN_2 2
2784#define POPEN_3 3
2785#define POPEN_4 4
2786
2787static PyObject *_PyPopen(char *, int, int, int);
2788static int _PyPclose(FILE *file);
2789
2790/*
2791 * Internal dictionary mapping popen* file pointers to process handles,
2792 * for use when retrieving the process exit code.  See _PyPclose() below
2793 * for more information on this dictionary's use.
2794 */
2795static PyObject *_PyPopenProcs = NULL;
2796
2797/* os2emx version of popen2()
2798 *
2799 * The result of this function is a pipe (file) connected to the
2800 * process's stdin, and a pipe connected to the process's stdout.
2801 */
2802
2803static PyObject *
2804os2emx_popen2(PyObject *self, PyObject  *args)
2805{
2806    PyObject *f;
2807    int tm=0;
2808
2809    char *cmdstring;
2810    char *mode = "t";
2811    int bufsize = -1;
2812    if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
2813        return NULL;
2814
2815    if (*mode == 't')
2816        tm = O_TEXT;
2817    else if (*mode != 'b') {
2818        PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2819        return NULL;
2820    } else
2821        tm = O_BINARY;
2822
2823    f = _PyPopen(cmdstring, tm, POPEN_2, bufsize);
2824
2825    return f;
2826}
2827
2828/*
2829 * Variation on os2emx.popen2
2830 *
2831 * The result of this function is 3 pipes - the process's stdin,
2832 * stdout and stderr
2833 */
2834
2835static PyObject *
2836os2emx_popen3(PyObject *self, PyObject *args)
2837{
2838    PyObject *f;
2839    int tm = 0;
2840
2841    char *cmdstring;
2842    char *mode = "t";
2843    int bufsize = -1;
2844    if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
2845        return NULL;
2846
2847    if (*mode == 't')
2848        tm = O_TEXT;
2849    else if (*mode != 'b') {
2850        PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2851        return NULL;
2852    } else
2853        tm = O_BINARY;
2854
2855    f = _PyPopen(cmdstring, tm, POPEN_3, bufsize);
2856
2857    return f;
2858}
2859
2860/*
2861 * Variation on os2emx.popen2
2862 *
2863 * The result of this function is 2 pipes - the processes stdin,
2864 * and stdout+stderr combined as a single pipe.
2865 */
2866
2867static PyObject *
2868os2emx_popen4(PyObject *self, PyObject  *args)
2869{
2870    PyObject *f;
2871    int tm = 0;
2872
2873    char *cmdstring;
2874    char *mode = "t";
2875    int bufsize = -1;
2876    if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
2877        return NULL;
2878
2879    if (*mode == 't')
2880        tm = O_TEXT;
2881    else if (*mode != 'b') {
2882        PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2883        return NULL;
2884    } else
2885        tm = O_BINARY;
2886
2887    f = _PyPopen(cmdstring, tm, POPEN_4, bufsize);
2888
2889    return f;
2890}
2891
2892/* a couple of structures for convenient handling of multiple
2893 * file handles and pipes
2894 */
2895struct file_ref
2896{
2897    int handle;
2898    int flags;
2899};
2900
2901struct pipe_ref
2902{
2903    int rd;
2904    int wr;
2905};
2906
2907/* The following code is derived from the win32 code */
2908
2909static PyObject *
2910_PyPopen(char *cmdstring, int mode, int n, int bufsize)
2911{
2912    struct file_ref stdio[3];
2913    struct pipe_ref p_fd[3];
2914    FILE *p_s[3];
2915    int file_count, i, pipe_err;
2916    pid_t pipe_pid;
2917    char *shell, *sh_name, *opt, *rd_mode, *wr_mode;
2918    PyObject *f, *p_f[3];
2919
2920    /* file modes for subsequent fdopen's on pipe handles */
2921    if (mode == O_TEXT)
2922    {
2923        rd_mode = "rt";
2924        wr_mode = "wt";
2925    }
2926    else
2927    {
2928        rd_mode = "rb";
2929        wr_mode = "wb";
2930    }
2931
2932    /* prepare shell references */
2933    if ((shell = getenv("EMXSHELL")) == NULL)
2934        if ((shell = getenv("COMSPEC")) == NULL)
2935        {
2936            errno = ENOENT;
2937            return posix_error();
2938        }
2939
2940    sh_name = _getname(shell);
2941    if (stricmp(sh_name, "cmd.exe") == 0 || stricmp(sh_name, "4os2.exe") == 0)
2942        opt = "/c";
2943    else
2944        opt = "-c";
2945
2946    /* save current stdio fds + their flags, and set not inheritable */
2947    i = pipe_err = 0;
2948    while (pipe_err >= 0 && i < 3)
2949    {
2950        pipe_err = stdio[i].handle = dup(i);
2951        stdio[i].flags = fcntl(i, F_GETFD, 0);
2952        fcntl(stdio[i].handle, F_SETFD, stdio[i].flags | FD_CLOEXEC);
2953        i++;
2954    }
2955    if (pipe_err < 0)
2956    {
2957        /* didn't get them all saved - clean up and bail out */
2958        int saved_err = errno;
2959        while (i-- > 0)
2960        {
2961            close(stdio[i].handle);
2962        }
2963        errno = saved_err;
2964        return posix_error();
2965    }
2966
2967    /* create pipe ends */
2968    file_count = 2;
2969    if (n == POPEN_3)
2970        file_count = 3;
2971    i = pipe_err = 0;
2972    while ((pipe_err == 0) && (i < file_count))
2973        pipe_err = pipe((int *)&p_fd[i++]);
2974    if (pipe_err < 0)
2975    {
2976        /* didn't get them all made - clean up and bail out */
2977        while (i-- > 0)
2978        {
2979            close(p_fd[i].wr);
2980            close(p_fd[i].rd);
2981        }
2982        errno = EPIPE;
2983        return posix_error();
2984    }
2985
2986    /* change the actual standard IO streams over temporarily,
2987     * making the retained pipe ends non-inheritable
2988     */
2989    pipe_err = 0;
2990
2991    /* - stdin */
2992    if (dup2(p_fd[0].rd, 0) == 0)
2993    {
2994        close(p_fd[0].rd);
2995        i = fcntl(p_fd[0].wr, F_GETFD, 0);
2996        fcntl(p_fd[0].wr, F_SETFD, i | FD_CLOEXEC);
2997        if ((p_s[0] = fdopen(p_fd[0].wr, wr_mode)) == NULL)
2998        {
2999            close(p_fd[0].wr);
3000            pipe_err = -1;
3001        }
3002    }
3003    else
3004    {
3005        pipe_err = -1;
3006    }
3007
3008    /* - stdout */
3009    if (pipe_err == 0)
3010    {
3011        if (dup2(p_fd[1].wr, 1) == 1)
3012        {
3013            close(p_fd[1].wr);
3014            i = fcntl(p_fd[1].rd, F_GETFD, 0);
3015            fcntl(p_fd[1].rd, F_SETFD, i | FD_CLOEXEC);
3016            if ((p_s[1] = fdopen(p_fd[1].rd, rd_mode)) == NULL)
3017            {
3018                close(p_fd[1].rd);
3019                pipe_err = -1;
3020            }
3021        }
3022        else
3023        {
3024            pipe_err = -1;
3025        }
3026    }
3027
3028    /* - stderr, as required */
3029    if (pipe_err == 0)
3030        switch (n)
3031        {
3032            case POPEN_3:
3033            {
3034                if (dup2(p_fd[2].wr, 2) == 2)
3035                {
3036                    close(p_fd[2].wr);
3037                    i = fcntl(p_fd[2].rd, F_GETFD, 0);
3038                    fcntl(p_fd[2].rd, F_SETFD, i | FD_CLOEXEC);
3039                    if ((p_s[2] = fdopen(p_fd[2].rd, rd_mode)) == NULL)
3040                    {
3041                        close(p_fd[2].rd);
3042                        pipe_err = -1;
3043                    }
3044                }
3045                else
3046                {
3047                    pipe_err = -1;
3048                }
3049                break;
3050            }
3051
3052            case POPEN_4:
3053            {
3054                if (dup2(1, 2) != 2)
3055                {
3056                    pipe_err = -1;
3057                }
3058                break;
3059            }
3060        }
3061
3062    /* spawn the child process */
3063    if (pipe_err == 0)
3064    {
3065        pipe_pid = spawnlp(P_NOWAIT, shell, shell, opt, cmdstring, (char *)0);
3066        if (pipe_pid == -1)
3067        {
3068            pipe_err = -1;
3069        }
3070        else
3071        {
3072            /* save the PID into the FILE structure
3073             * NOTE: this implementation doesn't actually
3074             * take advantage of this, but do it for
3075             * completeness - AIM Apr01
3076             */
3077            for (i = 0; i < file_count; i++)
3078                p_s[i]->_pid = pipe_pid;
3079        }
3080    }
3081
3082    /* reset standard IO to normal */
3083    for (i = 0; i < 3; i++)
3084    {
3085        dup2(stdio[i].handle, i);
3086        fcntl(i, F_SETFD, stdio[i].flags);
3087        close(stdio[i].handle);
3088    }
3089
3090    /* if any remnant problems, clean up and bail out */
3091    if (pipe_err < 0)
3092    {
3093        for (i = 0; i < 3; i++)
3094        {
3095            close(p_fd[i].rd);
3096            close(p_fd[i].wr);
3097        }
3098        errno = EPIPE;
3099        return posix_error_with_filename(cmdstring);
3100    }
3101
3102    /* build tuple of file objects to return */
3103    if ((p_f[0] = PyFile_FromFile(p_s[0], cmdstring, wr_mode, _PyPclose)) != NULL)
3104        PyFile_SetBufSize(p_f[0], bufsize);
3105    if ((p_f[1] = PyFile_FromFile(p_s[1], cmdstring, rd_mode, _PyPclose)) != NULL)
3106        PyFile_SetBufSize(p_f[1], bufsize);
3107    if (n == POPEN_3)
3108    {
3109        if ((p_f[2] = PyFile_FromFile(p_s[2], cmdstring, rd_mode, _PyPclose)) != NULL)
3110            PyFile_SetBufSize(p_f[0], bufsize);
3111        f = PyTuple_Pack(3, p_f[0], p_f[1], p_f[2]);
3112    }
3113    else
3114        f = PyTuple_Pack(2, p_f[0], p_f[1]);
3115
3116    /*
3117     * Insert the files we've created into the process dictionary
3118     * all referencing the list with the process handle and the
3119     * initial number of files (see description below in _PyPclose).
3120     * Since if _PyPclose later tried to wait on a process when all
3121     * handles weren't closed, it could create a deadlock with the
3122     * child, we spend some energy here to try to ensure that we
3123     * either insert all file handles into the dictionary or none
3124     * at all.  It's a little clumsy with the various popen modes
3125     * and variable number of files involved.
3126     */
3127    if (!_PyPopenProcs)
3128    {
3129        _PyPopenProcs = PyDict_New();
3130    }
3131
3132    if (_PyPopenProcs)
3133    {
3134        PyObject *procObj, *pidObj, *intObj, *fileObj[3];
3135        int ins_rc[3];
3136
3137        fileObj[0] = fileObj[1] = fileObj[2] = NULL;
3138        ins_rc[0]  = ins_rc[1]  = ins_rc[2]  = 0;
3139
3140        procObj = PyList_New(2);
3141        pidObj = PyLong_FromPid(pipe_pid);
3142        intObj = PyInt_FromLong((long) file_count);
3143
3144        if (procObj && pidObj && intObj)
3145        {
3146            PyList_SetItem(procObj, 0, pidObj);
3147            PyList_SetItem(procObj, 1, intObj);
3148
3149            fileObj[0] = PyLong_FromVoidPtr(p_s[0]);
3150            if (fileObj[0])
3151            {
3152                ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
3153                                           fileObj[0],
3154                                           procObj);
3155            }
3156            fileObj[1] = PyLong_FromVoidPtr(p_s[1]);
3157            if (fileObj[1])
3158            {
3159                ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
3160                                           fileObj[1],
3161                                           procObj);
3162            }
3163            if (file_count >= 3)
3164            {
3165                fileObj[2] = PyLong_FromVoidPtr(p_s[2]);
3166                if (fileObj[2])
3167                {
3168                    ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
3169                                               fileObj[2],
3170                                               procObj);
3171                }
3172            }
3173
3174            if (ins_rc[0] < 0 || !fileObj[0] ||
3175                ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
3176                ins_rc[2] < 0 || (file_count > 2 && !fileObj[2]))
3177            {
3178                /* Something failed - remove any dictionary
3179                 * entries that did make it.
3180                 */
3181                if (!ins_rc[0] && fileObj[0])
3182                {
3183                    PyDict_DelItem(_PyPopenProcs,
3184                                   fileObj[0]);
3185                }
3186                if (!ins_rc[1] && fileObj[1])
3187                {
3188                    PyDict_DelItem(_PyPopenProcs,
3189                                   fileObj[1]);
3190                }
3191                if (!ins_rc[2] && fileObj[2])
3192                {
3193                    PyDict_DelItem(_PyPopenProcs,
3194                                   fileObj[2]);
3195                }
3196            }
3197        }
3198
3199        /*
3200         * Clean up our localized references for the dictionary keys
3201         * and value since PyDict_SetItem will Py_INCREF any copies
3202         * that got placed in the dictionary.
3203         */
3204        Py_XDECREF(procObj);
3205        Py_XDECREF(fileObj[0]);
3206        Py_XDECREF(fileObj[1]);
3207        Py_XDECREF(fileObj[2]);
3208    }
3209
3210    /* Child is launched. */
3211    return f;
3212}
3213
3214/*
3215 * Wrapper for fclose() to use for popen* files, so we can retrieve the
3216 * exit code for the child process and return as a result of the close.
3217 *
3218 * This function uses the _PyPopenProcs dictionary in order to map the
3219 * input file pointer to information about the process that was
3220 * originally created by the popen* call that created the file pointer.
3221 * The dictionary uses the file pointer as a key (with one entry
3222 * inserted for each file returned by the original popen* call) and a
3223 * single list object as the value for all files from a single call.
3224 * The list object contains the Win32 process handle at [0], and a file
3225 * count at [1], which is initialized to the total number of file
3226 * handles using that list.
3227 *
3228 * This function closes whichever handle it is passed, and decrements
3229 * the file count in the dictionary for the process handle pointed to
3230 * by this file.  On the last close (when the file count reaches zero),
3231 * this function will wait for the child process and then return its
3232 * exit code as the result of the close() operation.  This permits the
3233 * files to be closed in any order - it is always the close() of the
3234 * final handle that will return the exit code.
3235 *
3236 * NOTE: This function is currently called with the GIL released.
3237 * hence we use the GILState API to manage our state.
3238 */
3239
3240static int _PyPclose(FILE *file)
3241{
3242    int result;
3243    int exit_code;
3244    pid_t pipe_pid;
3245    PyObject *procObj, *pidObj, *intObj, *fileObj;
3246    int file_count;
3247#ifdef WITH_THREAD
3248    PyGILState_STATE state;
3249#endif
3250
3251    /* Close the file handle first, to ensure it can't block the
3252     * child from exiting if it's the last handle.
3253     */
3254    result = fclose(file);
3255
3256#ifdef WITH_THREAD
3257    state = PyGILState_Ensure();
3258#endif
3259    if (_PyPopenProcs)
3260    {
3261        if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
3262            (procObj = PyDict_GetItem(_PyPopenProcs,
3263                                      fileObj)) != NULL &&
3264            (pidObj = PyList_GetItem(procObj,0)) != NULL &&
3265            (intObj = PyList_GetItem(procObj,1)) != NULL)
3266        {
3267            pipe_pid = (pid_t) PyLong_AsPid(pidObj);
3268            file_count = (int) PyInt_AsLong(intObj);
3269
3270            if (file_count > 1)
3271            {
3272                /* Still other files referencing process */
3273                file_count--;
3274                PyList_SetItem(procObj,1,
3275                               PyInt_FromLong((long) file_count));
3276            }
3277            else
3278            {
3279                /* Last file for this process */
3280                if (result != EOF &&
3281                    waitpid(pipe_pid, &exit_code, 0) == pipe_pid)
3282                {
3283                    /* extract exit status */
3284                    if (WIFEXITED(exit_code))
3285                    {
3286                        result = WEXITSTATUS(exit_code);
3287                    }
3288                    else
3289                    {
3290                        errno = EPIPE;
3291                        result = -1;
3292                    }
3293                }
3294                else
3295                {
3296                    /* Indicate failure - this will cause the file object
3297                     * to raise an I/O error and translate the last
3298                     * error code from errno.  We do have a problem with
3299                     * last errors that overlap the normal errno table,
3300                     * but that's a consistent problem with the file object.
3301                     */
3302                    result = -1;
3303                }
3304            }
3305
3306            /* Remove this file pointer from dictionary */
3307            PyDict_DelItem(_PyPopenProcs, fileObj);
3308
3309            if (PyDict_Size(_PyPopenProcs) == 0)
3310            {
3311                Py_DECREF(_PyPopenProcs);
3312                _PyPopenProcs = NULL;
3313            }
3314
3315        } /* if object retrieval ok */
3316
3317        Py_XDECREF(fileObj);
3318    } /* if _PyPopenProcs */
3319
3320#ifdef WITH_THREAD
3321    PyGILState_Release(state);
3322#endif
3323    return result;
3324}
3325
3326#endif /* PYCC_??? */
3327
3328#elif defined(MS_WINDOWS)
3329
3330/*
3331 * Portable 'popen' replacement for Win32.
3332 *
3333 * Written by Bill Tutt <billtut@microsoft.com>.  Minor tweaks
3334 * and 2.0 integration by Fredrik Lundh <fredrik@pythonware.com>
3335 * Return code handling by David Bolen <db3l@fitlinxx.com>.
3336 */
3337
3338#include <malloc.h>
3339#include <io.h>
3340#include <fcntl.h>
3341
3342/* These tell _PyPopen() wether to return 1, 2, or 3 file objects. */
3343#define POPEN_1 1
3344#define POPEN_2 2
3345#define POPEN_3 3
3346#define POPEN_4 4
3347
3348static PyObject *_PyPopen(char *, int, int);
3349static int _PyPclose(FILE *file);
3350
3351/*
3352 * Internal dictionary mapping popen* file pointers to process handles,
3353 * for use when retrieving the process exit code.  See _PyPclose() below
3354 * for more information on this dictionary's use.
3355 */
3356static PyObject *_PyPopenProcs = NULL;
3357
3358
3359/* popen that works from a GUI.
3360 *
3361 * The result of this function is a pipe (file) connected to the
3362 * processes stdin or stdout, depending on the requested mode.
3363 */
3364
3365static PyObject *
3366posix_popen(PyObject *self, PyObject *args)
3367{
3368    PyObject *f;
3369    int tm = 0;
3370
3371    char *cmdstring;
3372    char *mode = "r";
3373    int bufsize = -1;
3374    if (!PyArg_ParseTuple(args, "s|si:popen", &cmdstring, &mode, &bufsize))
3375        return NULL;
3376
3377    if (*mode == 'r')
3378        tm = _O_RDONLY;
3379    else if (*mode != 'w') {
3380        PyErr_SetString(PyExc_ValueError, "popen() arg 2 must be 'r' or 'w'");
3381        return NULL;
3382    } else
3383        tm = _O_WRONLY;
3384
3385    if (bufsize != -1) {
3386        PyErr_SetString(PyExc_ValueError, "popen() arg 3 must be -1");
3387        return NULL;
3388    }
3389
3390    if (*(mode+1) == 't')
3391        f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
3392    else if (*(mode+1) == 'b')
3393        f = _PyPopen(cmdstring, tm | _O_BINARY, POPEN_1);
3394    else
3395        f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
3396
3397    return f;
3398}
3399
3400/* Variation on win32pipe.popen
3401 *
3402 * The result of this function is a pipe (file) connected to the
3403 * process's stdin, and a pipe connected to the process's stdout.
3404 */
3405
3406static PyObject *
3407win32_popen2(PyObject *self, PyObject  *args)
3408{
3409    PyObject *f;
3410    int tm=0;
3411
3412    char *cmdstring;
3413    char *mode = "t";
3414    int bufsize = -1;
3415    if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
3416        return NULL;
3417
3418    if (*mode == 't')
3419        tm = _O_TEXT;
3420    else if (*mode != 'b') {
3421        PyErr_SetString(PyExc_ValueError, "popen2() arg 2 must be 't' or 'b'");
3422        return NULL;
3423    } else
3424        tm = _O_BINARY;
3425
3426    if (bufsize != -1) {
3427        PyErr_SetString(PyExc_ValueError, "popen2() arg 3 must be -1");
3428        return NULL;
3429    }
3430
3431    f = _PyPopen(cmdstring, tm, POPEN_2);
3432
3433    return f;
3434}
3435
3436/*
3437 * Variation on <om win32pipe.popen>
3438 *
3439 * The result of this function is 3 pipes - the process's stdin,
3440 * stdout and stderr
3441 */
3442
3443static PyObject *
3444win32_popen3(PyObject *self, PyObject *args)
3445{
3446    PyObject *f;
3447    int tm = 0;
3448
3449    char *cmdstring;
3450    char *mode = "t";
3451    int bufsize = -1;
3452    if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
3453        return NULL;
3454
3455    if (*mode == 't')
3456        tm = _O_TEXT;
3457    else if (*mode != 'b') {
3458        PyErr_SetString(PyExc_ValueError, "popen3() arg 2 must be 't' or 'b'");
3459        return NULL;
3460    } else
3461        tm = _O_BINARY;
3462
3463    if (bufsize != -1) {
3464        PyErr_SetString(PyExc_ValueError, "popen3() arg 3 must be -1");
3465        return NULL;
3466    }
3467
3468    f = _PyPopen(cmdstring, tm, POPEN_3);
3469
3470    return f;
3471}
3472
3473/*
3474 * Variation on win32pipe.popen
3475 *
3476 * The result of this function is 2 pipes - the processes stdin,
3477 * and stdout+stderr combined as a single pipe.
3478 */
3479
3480static PyObject *
3481win32_popen4(PyObject *self, PyObject  *args)
3482{
3483    PyObject *f;
3484    int tm = 0;
3485
3486    char *cmdstring;
3487    char *mode = "t";
3488    int bufsize = -1;
3489    if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
3490        return NULL;
3491
3492    if (*mode == 't')
3493        tm = _O_TEXT;
3494    else if (*mode != 'b') {
3495        PyErr_SetString(PyExc_ValueError, "popen4() arg 2 must be 't' or 'b'");
3496        return NULL;
3497    } else
3498        tm = _O_BINARY;
3499
3500    if (bufsize != -1) {
3501        PyErr_SetString(PyExc_ValueError, "popen4() arg 3 must be -1");
3502        return NULL;
3503    }
3504
3505    f = _PyPopen(cmdstring, tm, POPEN_4);
3506
3507    return f;
3508}
3509
3510static BOOL
3511_PyPopenCreateProcess(char *cmdstring,
3512                      HANDLE hStdin,
3513                      HANDLE hStdout,
3514                      HANDLE hStderr,
3515                      HANDLE *hProcess)
3516{
3517    PROCESS_INFORMATION piProcInfo;
3518    STARTUPINFO siStartInfo;
3519    DWORD dwProcessFlags = 0;  /* no NEW_CONSOLE by default for Ctrl+C handling */
3520    char *s1,*s2, *s3 = " /c ";
3521    const char *szConsoleSpawn = "w9xpopen.exe";
3522    int i;
3523    Py_ssize_t x;
3524
3525    if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) {
3526        char *comshell;
3527
3528        s1 = (char *)alloca(i);
3529        if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
3530            /* x < i, so x fits into an integer */
3531            return (int)x;
3532
3533        /* Explicitly check if we are using COMMAND.COM.  If we are
3534         * then use the w9xpopen hack.
3535         */
3536        comshell = s1 + x;
3537        while (comshell >= s1 && *comshell != '\\')
3538            --comshell;
3539        ++comshell;
3540
3541        if (GetVersion() < 0x80000000 &&
3542            _stricmp(comshell, "command.com") != 0) {
3543            /* NT/2000 and not using command.com. */
3544            x = i + strlen(s3) + strlen(cmdstring) + 1;
3545            s2 = (char *)alloca(x);
3546            ZeroMemory(s2, x);
3547            PyOS_snprintf(s2, x, "%s%s%s", s1, s3, cmdstring);
3548        }
3549        else {
3550            /*
3551             * Oh gag, we're on Win9x or using COMMAND.COM. Use
3552             * the workaround listed in KB: Q150956
3553             */
3554            char modulepath[_MAX_PATH];
3555            struct stat statinfo;
3556            GetModuleFileName(NULL, modulepath, sizeof(modulepath));
3557            for (x = i = 0; modulepath[i]; i++)
3558                if (modulepath[i] == SEP)
3559                    x = i+1;
3560            modulepath[x] = '\0';
3561            /* Create the full-name to w9xpopen, so we can test it exists */
3562            strncat(modulepath,
3563                    szConsoleSpawn,
3564                    (sizeof(modulepath)/sizeof(modulepath[0]))
3565                        -strlen(modulepath));
3566            if (stat(modulepath, &statinfo) != 0) {
3567                size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]);
3568                /* Eeek - file-not-found - possibly an embedding
3569                   situation - see if we can locate it in sys.prefix
3570                */
3571                strncpy(modulepath,
3572                        Py_GetExecPrefix(),
3573                        mplen);
3574                modulepath[mplen-1] = '\0';
3575                if (modulepath[strlen(modulepath)-1] != '\\')
3576                    strcat(modulepath, "\\");
3577                strncat(modulepath,
3578                        szConsoleSpawn,
3579                        mplen-strlen(modulepath));
3580                /* No where else to look - raise an easily identifiable
3581                   error, rather than leaving Windows to report
3582                   "file not found" - as the user is probably blissfully
3583                   unaware this shim EXE is used, and it will confuse them.
3584                   (well, it confused me for a while ;-)
3585                */
3586                if (stat(modulepath, &statinfo) != 0) {
3587                    PyErr_Format(PyExc_RuntimeError,
3588                                 "Can not locate '%s' which is needed "
3589                                 "for popen to work with your shell "
3590                                 "or platform.",
3591                                 szConsoleSpawn);
3592                    return FALSE;
3593                }
3594            }
3595            x = i + strlen(s3) + strlen(cmdstring) + 1 +
3596                strlen(modulepath) +
3597                strlen(szConsoleSpawn) + 1;
3598
3599            s2 = (char *)alloca(x);
3600            ZeroMemory(s2, x);
3601            /* To maintain correct argument passing semantics,
3602               we pass the command-line as it stands, and allow
3603               quoting to be applied.  w9xpopen.exe will then
3604               use its argv vector, and re-quote the necessary
3605               args for the ultimate child process.
3606            */
3607            PyOS_snprintf(
3608                s2, x,
3609                "\"%s\" %s%s%s",
3610                modulepath,
3611                s1,
3612                s3,
3613                cmdstring);
3614            /* Not passing CREATE_NEW_CONSOLE has been known to
3615               cause random failures on win9x.  Specifically a
3616               dialog:
3617               "Your program accessed mem currently in use at xxx"
3618               and a hopeful warning about the stability of your
3619               system.
3620               Cost is Ctrl+C won't kill children, but anyone
3621               who cares can have a go!
3622            */
3623            dwProcessFlags |= CREATE_NEW_CONSOLE;
3624        }
3625    }
3626
3627    /* Could be an else here to try cmd.exe / command.com in the path
3628       Now we'll just error out.. */
3629    else {
3630        PyErr_SetString(PyExc_RuntimeError,
3631                        "Cannot locate a COMSPEC environment variable to "
3632                        "use as the shell");
3633        return FALSE;
3634    }
3635
3636    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
3637    siStartInfo.cb = sizeof(STARTUPINFO);
3638    siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
3639    siStartInfo.hStdInput = hStdin;
3640    siStartInfo.hStdOutput = hStdout;
3641    siStartInfo.hStdError = hStderr;
3642    siStartInfo.wShowWindow = SW_HIDE;
3643
3644    if (CreateProcess(NULL,
3645                      s2,
3646                      NULL,
3647                      NULL,
3648                      TRUE,
3649                      dwProcessFlags,
3650                      NULL,
3651                      NULL,
3652                      &siStartInfo,
3653                      &piProcInfo) ) {
3654        /* Close the handles now so anyone waiting is woken. */
3655        CloseHandle(piProcInfo.hThread);
3656
3657        /* Return process handle */
3658        *hProcess = piProcInfo.hProcess;
3659        return TRUE;
3660    }
3661    win32_error("CreateProcess", s2);
3662    return FALSE;
3663}
3664
3665/* The following code is based off of KB: Q190351 */
3666
3667static PyObject *
3668_PyPopen(char *cmdstring, int mode, int n)
3669{
3670    HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
3671        hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup,
3672        hChildStderrRdDup, hProcess; /* hChildStdoutWrDup; */
3673
3674    SECURITY_ATTRIBUTES saAttr;
3675    BOOL fSuccess;
3676    int fd1, fd2, fd3;
3677    FILE *f1, *f2, *f3;
3678    long file_count;
3679    PyObject *f;
3680
3681    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
3682    saAttr.bInheritHandle = TRUE;
3683    saAttr.lpSecurityDescriptor = NULL;
3684
3685    if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
3686        return win32_error("CreatePipe", NULL);
3687
3688    /* Create new output read handle and the input write handle. Set
3689     * the inheritance properties to FALSE. Otherwise, the child inherits
3690     * these handles; resulting in non-closeable handles to the pipes
3691     * being created. */
3692     fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
3693                                GetCurrentProcess(), &hChildStdinWrDup, 0,
3694                                FALSE,
3695                                DUPLICATE_SAME_ACCESS);
3696     if (!fSuccess)
3697         return win32_error("DuplicateHandle", NULL);
3698
3699     /* Close the inheritable version of ChildStdin
3700    that we're using. */
3701     CloseHandle(hChildStdinWr);
3702
3703     if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
3704         return win32_error("CreatePipe", NULL);
3705
3706     fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
3707                                GetCurrentProcess(), &hChildStdoutRdDup, 0,
3708                                FALSE, DUPLICATE_SAME_ACCESS);
3709     if (!fSuccess)
3710         return win32_error("DuplicateHandle", NULL);
3711
3712     /* Close the inheritable version of ChildStdout
3713        that we're using. */
3714     CloseHandle(hChildStdoutRd);
3715
3716     if (n != POPEN_4) {
3717         if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
3718             return win32_error("CreatePipe", NULL);
3719         fSuccess = DuplicateHandle(GetCurrentProcess(),
3720                                    hChildStderrRd,
3721                                    GetCurrentProcess(),
3722                                    &hChildStderrRdDup, 0,
3723                                    FALSE, DUPLICATE_SAME_ACCESS);
3724         if (!fSuccess)
3725             return win32_error("DuplicateHandle", NULL);
3726         /* Close the inheritable version of ChildStdErr that we're using. */
3727         CloseHandle(hChildStderrRd);
3728     }
3729
3730     switch (n) {
3731     case POPEN_1:
3732         switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) {
3733         case _O_WRONLY | _O_TEXT:
3734             /* Case for writing to child Stdin in text mode. */
3735             fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
3736             f1 = _fdopen(fd1, "w");
3737             f = PyFile_FromFile(f1, cmdstring, "w", _PyPclose);
3738             PyFile_SetBufSize(f, 0);
3739             /* We don't care about these pipes anymore, so close them. */
3740             CloseHandle(hChildStdoutRdDup);
3741             CloseHandle(hChildStderrRdDup);
3742             break;
3743
3744         case _O_RDONLY | _O_TEXT:
3745             /* Case for reading from child Stdout in text mode. */
3746             fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
3747             f1 = _fdopen(fd1, "r");
3748             f = PyFile_FromFile(f1, cmdstring, "r", _PyPclose);
3749             PyFile_SetBufSize(f, 0);
3750             /* We don't care about these pipes anymore, so close them. */
3751             CloseHandle(hChildStdinWrDup);
3752             CloseHandle(hChildStderrRdDup);
3753             break;
3754
3755         case _O_RDONLY | _O_BINARY:
3756             /* Case for readinig from child Stdout in binary mode. */
3757             fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
3758             f1 = _fdopen(fd1, "rb");
3759             f = PyFile_FromFile(f1, cmdstring, "rb", _PyPclose);
3760             PyFile_SetBufSize(f, 0);
3761             /* We don't care about these pipes anymore, so close them. */
3762             CloseHandle(hChildStdinWrDup);
3763             CloseHandle(hChildStderrRdDup);
3764             break;
3765
3766         case _O_WRONLY | _O_BINARY:
3767             /* Case for writing to child Stdin in binary mode. */
3768             fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
3769             f1 = _fdopen(fd1, "wb");
3770             f = PyFile_FromFile(f1, cmdstring, "wb", _PyPclose);
3771             PyFile_SetBufSize(f, 0);
3772             /* We don't care about these pipes anymore, so close them. */
3773             CloseHandle(hChildStdoutRdDup);
3774             CloseHandle(hChildStderrRdDup);
3775             break;
3776         }
3777         file_count = 1;
3778         break;
3779
3780     case POPEN_2:
3781     case POPEN_4:
3782     {
3783         char *m1, *m2;
3784         PyObject *p1, *p2;
3785
3786         if (mode & _O_TEXT) {
3787             m1 = "r";
3788             m2 = "w";
3789         } else {
3790             m1 = "rb";
3791             m2 = "wb";
3792         }
3793
3794         fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
3795         f1 = _fdopen(fd1, m2);
3796         fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
3797         f2 = _fdopen(fd2, m1);
3798         p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
3799         PyFile_SetBufSize(p1, 0);
3800         p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
3801         PyFile_SetBufSize(p2, 0);
3802
3803         if (n != 4)
3804             CloseHandle(hChildStderrRdDup);
3805
3806         f = PyTuple_Pack(2,p1,p2);
3807         Py_XDECREF(p1);
3808         Py_XDECREF(p2);
3809         file_count = 2;
3810         break;
3811     }
3812
3813     case POPEN_3:
3814     {
3815         char *m1, *m2;
3816         PyObject *p1, *p2, *p3;
3817
3818         if (mode & _O_TEXT) {
3819             m1 = "r";
3820             m2 = "w";
3821         } else {
3822             m1 = "rb";
3823             m2 = "wb";
3824         }
3825
3826         fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
3827         f1 = _fdopen(fd1, m2);
3828         fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
3829         f2 = _fdopen(fd2, m1);
3830         fd3 = _open_osfhandle((Py_intptr_t)hChildStderrRdDup, mode);
3831         f3 = _fdopen(fd3, m1);
3832         p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
3833         p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
3834         p3 = PyFile_FromFile(f3, cmdstring, m1, _PyPclose);
3835         PyFile_SetBufSize(p1, 0);
3836         PyFile_SetBufSize(p2, 0);
3837         PyFile_SetBufSize(p3, 0);
3838         f = PyTuple_Pack(3,p1,p2,p3);
3839         Py_XDECREF(p1);
3840         Py_XDECREF(p2);
3841         Py_XDECREF(p3);
3842         file_count = 3;
3843         break;
3844     }
3845     }
3846
3847     if (n == POPEN_4) {
3848         if (!_PyPopenCreateProcess(cmdstring,
3849                                    hChildStdinRd,
3850                                    hChildStdoutWr,
3851                                    hChildStdoutWr,
3852                                    &hProcess))
3853             return NULL;
3854     }
3855     else {
3856         if (!_PyPopenCreateProcess(cmdstring,
3857                                    hChildStdinRd,
3858                                    hChildStdoutWr,
3859                                    hChildStderrWr,
3860                                    &hProcess))
3861             return NULL;
3862     }
3863
3864     /*
3865      * Insert the files we've created into the process dictionary
3866      * all referencing the list with the process handle and the
3867      * initial number of files (see description below in _PyPclose).
3868      * Since if _PyPclose later tried to wait on a process when all
3869      * handles weren't closed, it could create a deadlock with the
3870      * child, we spend some energy here to try to ensure that we
3871      * either insert all file handles into the dictionary or none
3872      * at all.  It's a little clumsy with the various popen modes
3873      * and variable number of files involved.
3874      */
3875     if (!_PyPopenProcs) {
3876         _PyPopenProcs = PyDict_New();
3877     }
3878
3879     if (_PyPopenProcs) {
3880         PyObject *procObj, *hProcessObj, *intObj, *fileObj[3];
3881         int ins_rc[3];
3882
3883         fileObj[0] = fileObj[1] = fileObj[2] = NULL;
3884         ins_rc[0]  = ins_rc[1]  = ins_rc[2]  = 0;
3885
3886         procObj = PyList_New(2);
3887         hProcessObj = PyLong_FromVoidPtr(hProcess);
3888         intObj = PyInt_FromLong(file_count);
3889
3890         if (procObj && hProcessObj && intObj) {
3891             PyList_SetItem(procObj,0,hProcessObj);
3892             PyList_SetItem(procObj,1,intObj);
3893
3894             fileObj[0] = PyLong_FromVoidPtr(f1);
3895             if (fileObj[0]) {
3896                ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
3897                                           fileObj[0],
3898                                           procObj);
3899             }
3900             if (file_count >= 2) {
3901                 fileObj[1] = PyLong_FromVoidPtr(f2);
3902                 if (fileObj[1]) {
3903                    ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
3904                                               fileObj[1],
3905                                               procObj);
3906                 }
3907             }
3908             if (file_count >= 3) {
3909                 fileObj[2] = PyLong_FromVoidPtr(f3);
3910                 if (fileObj[2]) {
3911                    ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
3912                                               fileObj[2],
3913                                               procObj);
3914                 }
3915             }
3916
3917             if (ins_rc[0] < 0 || !fileObj[0] ||
3918                 ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
3919                 ins_rc[2] < 0 || (file_count > 2 && !fileObj[2])) {
3920                 /* Something failed - remove any dictionary
3921                  * entries that did make it.
3922                  */
3923                 if (!ins_rc[0] && fileObj[0]) {
3924                     PyDict_DelItem(_PyPopenProcs,
3925                                    fileObj[0]);
3926                 }
3927                 if (!ins_rc[1] && fileObj[1]) {
3928                     PyDict_DelItem(_PyPopenProcs,
3929                                    fileObj[1]);
3930                 }
3931                 if (!ins_rc[2] && fileObj[2]) {
3932                     PyDict_DelItem(_PyPopenProcs,
3933                                    fileObj[2]);
3934                 }
3935             }
3936         }
3937
3938         /*
3939          * Clean up our localized references for the dictionary keys
3940          * and value since PyDict_SetItem will Py_INCREF any copies
3941          * that got placed in the dictionary.
3942          */
3943         Py_XDECREF(procObj);
3944         Py_XDECREF(fileObj[0]);
3945         Py_XDECREF(fileObj[1]);
3946         Py_XDECREF(fileObj[2]);
3947     }
3948
3949     /* Child is launched. Close the parents copy of those pipe
3950      * handles that only the child should have open.  You need to
3951      * make sure that no handles to the write end of the output pipe
3952      * are maintained in this process or else the pipe will not close
3953      * when the child process exits and the ReadFile will hang. */
3954
3955     if (!CloseHandle(hChildStdinRd))
3956         return win32_error("CloseHandle", NULL);
3957
3958     if (!CloseHandle(hChildStdoutWr))
3959         return win32_error("CloseHandle", NULL);
3960
3961     if ((n != 4) && (!CloseHandle(hChildStderrWr)))
3962         return win32_error("CloseHandle", NULL);
3963
3964     return f;
3965}
3966
3967/*
3968 * Wrapper for fclose() to use for popen* files, so we can retrieve the
3969 * exit code for the child process and return as a result of the close.
3970 *
3971 * This function uses the _PyPopenProcs dictionary in order to map the
3972 * input file pointer to information about the process that was
3973 * originally created by the popen* call that created the file pointer.
3974 * The dictionary uses the file pointer as a key (with one entry
3975 * inserted for each file returned by the original popen* call) and a
3976 * single list object as the value for all files from a single call.
3977 * The list object contains the Win32 process handle at [0], and a file
3978 * count at [1], which is initialized to the total number of file
3979 * handles using that list.
3980 *
3981 * This function closes whichever handle it is passed, and decrements
3982 * the file count in the dictionary for the process handle pointed to
3983 * by this file.  On the last close (when the file count reaches zero),
3984 * this function will wait for the child process and then return its
3985 * exit code as the result of the close() operation.  This permits the
3986 * files to be closed in any order - it is always the close() of the
3987 * final handle that will return the exit code.
3988 *
3989 * NOTE: This function is currently called with the GIL released.
3990 * hence we use the GILState API to manage our state.
3991 */
3992
3993static int _PyPclose(FILE *file)
3994{
3995    int result;
3996    DWORD exit_code;
3997    HANDLE hProcess;
3998    PyObject *procObj, *hProcessObj, *intObj, *fileObj;
3999    long file_count;
4000#ifdef WITH_THREAD
4001    PyGILState_STATE state;
4002#endif
4003
4004    /* Close the file handle first, to ensure it can't block the
4005     * child from exiting if it's the last handle.
4006     */
4007    result = fclose(file);
4008#ifdef WITH_THREAD
4009    state = PyGILState_Ensure();
4010#endif
4011    if (_PyPopenProcs) {
4012        if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
4013            (procObj = PyDict_GetItem(_PyPopenProcs,
4014                                      fileObj)) != NULL &&
4015            (hProcessObj = PyList_GetItem(procObj,0)) != NULL &&
4016            (intObj = PyList_GetItem(procObj,1)) != NULL) {
4017
4018            hProcess = PyLong_AsVoidPtr(hProcessObj);
4019            file_count = PyInt_AsLong(intObj);
4020
4021            if (file_count > 1) {
4022                /* Still other files referencing process */
4023                file_count--;
4024                PyList_SetItem(procObj,1,
4025                               PyInt_FromLong(file_count));
4026            } else {
4027                /* Last file for this process */
4028                if (result != EOF &&
4029                    WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
4030                    GetExitCodeProcess(hProcess, &exit_code)) {
4031                    /* Possible truncation here in 16-bit environments, but
4032                     * real exit codes are just the lower byte in any event.
4033                     */
4034                    result = exit_code;
4035                } else {
4036                    /* Indicate failure - this will cause the file object
4037                     * to raise an I/O error and translate the last Win32
4038                     * error code from errno.  We do have a problem with
4039                     * last errors that overlap the normal errno table,
4040                     * but that's a consistent problem with the file object.
4041                     */
4042                    if (result != EOF) {
4043                        /* If the error wasn't from the fclose(), then
4044                         * set errno for the file object error handling.
4045                         */
4046                        errno = GetLastError();
4047                    }
4048                    result = -1;
4049                }
4050
4051                /* Free up the native handle at this point */
4052                CloseHandle(hProcess);
4053            }
4054
4055            /* Remove this file pointer from dictionary */
4056            PyDict_DelItem(_PyPopenProcs, fileObj);
4057
4058            if (PyDict_Size(_PyPopenProcs) == 0) {
4059                Py_DECREF(_PyPopenProcs);
4060                _PyPopenProcs = NULL;
4061            }
4062
4063        } /* if object retrieval ok */
4064
4065        Py_XDECREF(fileObj);
4066    } /* if _PyPopenProcs */
4067
4068#ifdef WITH_THREAD
4069    PyGILState_Release(state);
4070#endif
4071    return result;
4072}
4073
4074#else /* which OS? */
4075static PyObject *
4076posix_popen(PyObject *self, PyObject *args)
4077{
4078    char *name;
4079    char *mode = "r";
4080    int bufsize = -1;
4081    FILE *fp;
4082    PyObject *f;
4083    if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
4084        return NULL;
4085    /* Strip mode of binary or text modifiers */
4086    if (strcmp(mode, "rb") == 0 || strcmp(mode, "rt") == 0)
4087        mode = "r";
4088    else if (strcmp(mode, "wb") == 0 || strcmp(mode, "wt") == 0)
4089        mode = "w";
4090    Py_BEGIN_ALLOW_THREADS
4091    fp = popen(name, mode);
4092    Py_END_ALLOW_THREADS
4093    if (fp == NULL)
4094        return posix_error();
4095    f = PyFile_FromFile(fp, name, mode, pclose);
4096    if (f != NULL)
4097        PyFile_SetBufSize(f, bufsize);
4098    return f;
4099}
4100
4101#endif /* PYOS_??? */
4102#endif /* HAVE_POPEN */
4103
4104
4105#ifdef HAVE_SETUID
4106PyDoc_STRVAR(posix_setuid__doc__,
4107"setuid(uid)\n\n\
4108Set the current process's user id.");
4109
4110static PyObject *
4111posix_setuid(PyObject *self, PyObject *args)
4112{
4113    long uid_arg;
4114    uid_t uid;
4115    if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
4116        return NULL;
4117    uid = uid_arg;
4118    if (uid != uid_arg) {
4119        PyErr_SetString(PyExc_OverflowError, "user id too big");
4120        return NULL;
4121    }
4122    if (setuid(uid) < 0)
4123        return posix_error();
4124    Py_INCREF(Py_None);
4125    return Py_None;
4126}
4127#endif /* HAVE_SETUID */
4128
4129
4130#ifdef HAVE_SETEUID
4131PyDoc_STRVAR(posix_seteuid__doc__,
4132"seteuid(uid)\n\n\
4133Set the current process's effective user id.");
4134
4135static PyObject *
4136posix_seteuid (PyObject *self, PyObject *args)
4137{
4138    long euid_arg;
4139    uid_t euid;
4140    if (!PyArg_ParseTuple(args, "l", &euid_arg))
4141        return NULL;
4142    euid = euid_arg;
4143    if (euid != euid_arg) {
4144        PyErr_SetString(PyExc_OverflowError, "user id too big");
4145        return NULL;
4146    }
4147    if (seteuid(euid) < 0) {
4148        return posix_error();
4149    } else {
4150        Py_INCREF(Py_None);
4151        return Py_None;
4152    }
4153}
4154#endif /* HAVE_SETEUID */
4155
4156#ifdef HAVE_SETEGID
4157PyDoc_STRVAR(posix_setegid__doc__,
4158"setegid(gid)\n\n\
4159Set the current process's effective group id.");
4160
4161static PyObject *
4162posix_setegid (PyObject *self, PyObject *args)
4163{
4164    long egid_arg;
4165    gid_t egid;
4166    if (!PyArg_ParseTuple(args, "l", &egid_arg))
4167        return NULL;
4168    egid = egid_arg;
4169    if (egid != egid_arg) {
4170        PyErr_SetString(PyExc_OverflowError, "group id too big");
4171        return NULL;
4172    }
4173    if (setegid(egid) < 0) {
4174        return posix_error();
4175    } else {
4176        Py_INCREF(Py_None);
4177        return Py_None;
4178    }
4179}
4180#endif /* HAVE_SETEGID */
4181
4182#ifdef HAVE_SETREUID
4183PyDoc_STRVAR(posix_setreuid__doc__,
4184"setreuid(ruid, euid)\n\n\
4185Set the current process's real and effective user ids.");
4186
4187static PyObject *
4188posix_setreuid (PyObject *self, PyObject *args)
4189{
4190    long ruid_arg, euid_arg;
4191    uid_t ruid, euid;
4192    if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
4193        return NULL;
4194    if (ruid_arg == -1)
4195        ruid = (uid_t)-1;  /* let the compiler choose how -1 fits */
4196    else
4197        ruid = ruid_arg;  /* otherwise, assign from our long */
4198    if (euid_arg == -1)
4199        euid = (uid_t)-1;
4200    else
4201        euid = euid_arg;
4202    if ((euid_arg != -1 && euid != euid_arg) ||
4203        (ruid_arg != -1 && ruid != ruid_arg)) {
4204        PyErr_SetString(PyExc_OverflowError, "user id too big");
4205        return NULL;
4206    }
4207    if (setreuid(ruid, euid) < 0) {
4208        return posix_error();
4209    } else {
4210        Py_INCREF(Py_None);
4211        return Py_None;
4212    }
4213}
4214#endif /* HAVE_SETREUID */
4215
4216#ifdef HAVE_SETREGID
4217PyDoc_STRVAR(posix_setregid__doc__,
4218"setregid(rgid, egid)\n\n\
4219Set the current process's real and effective group ids.");
4220
4221static PyObject *
4222posix_setregid (PyObject *self, PyObject *args)
4223{
4224    long rgid_arg, egid_arg;
4225    gid_t rgid, egid;
4226    if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
4227        return NULL;
4228    if (rgid_arg == -1)
4229        rgid = (gid_t)-1;  /* let the compiler choose how -1 fits */
4230    else
4231        rgid = rgid_arg;  /* otherwise, assign from our long */
4232    if (egid_arg == -1)
4233        egid = (gid_t)-1;
4234    else
4235        egid = egid_arg;
4236    if ((egid_arg != -1 && egid != egid_arg) ||
4237        (rgid_arg != -1 && rgid != rgid_arg)) {
4238        PyErr_SetString(PyExc_OverflowError, "group id too big");
4239        return NULL;
4240    }
4241    if (setregid(rgid, egid) < 0) {
4242        return posix_error();
4243    } else {
4244        Py_INCREF(Py_None);
4245        return Py_None;
4246    }
4247}
4248#endif /* HAVE_SETREGID */
4249
4250#ifdef HAVE_SETGID
4251PyDoc_STRVAR(posix_setgid__doc__,
4252"setgid(gid)\n\n\
4253Set the current process's group id.");
4254
4255static PyObject *
4256posix_setgid(PyObject *self, PyObject *args)
4257{
4258    long gid_arg;
4259    gid_t gid;
4260    if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
4261        return NULL;
4262    gid = gid_arg;
4263    if (gid != gid_arg) {
4264        PyErr_SetString(PyExc_OverflowError, "group id too big");
4265        return NULL;
4266    }
4267    if (setgid(gid) < 0)
4268        return posix_error();
4269    Py_INCREF(Py_None);
4270    return Py_None;
4271}
4272#endif /* HAVE_SETGID */
4273
4274#ifdef HAVE_SETGROUPS
4275PyDoc_STRVAR(posix_setgroups__doc__,
4276"setgroups(list)\n\n\
4277Set the groups of the current process to list.");
4278
4279static PyObject *
4280posix_setgroups(PyObject *self, PyObject *groups)
4281{
4282    int i, len;
4283    gid_t grouplist[MAX_GROUPS];
4284
4285    if (!PySequence_Check(groups)) {
4286        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
4287        return NULL;
4288    }
4289    len = PySequence_Size(groups);
4290    if (len > MAX_GROUPS) {
4291        PyErr_SetString(PyExc_ValueError, "too many groups");
4292        return NULL;
4293    }
4294    for(i = 0; i < len; i++) {
4295        PyObject *elem;
4296        elem = PySequence_GetItem(groups, i);
4297        if (!elem)
4298            return NULL;
4299        if (!PyInt_Check(elem)) {
4300            if (!PyLong_Check(elem)) {
4301                PyErr_SetString(PyExc_TypeError,
4302                                "groups must be integers");
4303                Py_DECREF(elem);
4304                return NULL;
4305            } else {
4306                unsigned long x = PyLong_AsUnsignedLong(elem);
4307                if (PyErr_Occurred()) {
4308                    PyErr_SetString(PyExc_TypeError,
4309                                    "group id too big");
4310                    Py_DECREF(elem);
4311                    return NULL;
4312                }
4313                grouplist[i] = x;
4314                /* read back to see if it fits in gid_t */
4315                if (grouplist[i] != x) {
4316                    PyErr_SetString(PyExc_TypeError,
4317                                    "group id too big");
4318                    Py_DECREF(elem);
4319                    return NULL;
4320                }
4321            }
4322        } else {
4323            long x  = PyInt_AsLong(elem);
4324            grouplist[i] = x;
4325            if (grouplist[i] != x) {
4326                PyErr_SetString(PyExc_TypeError,
4327                                "group id too big");
4328                Py_DECREF(elem);
4329                return NULL;
4330            }
4331        }
4332        Py_DECREF(elem);
4333    }
4334
4335    if (setgroups(len, grouplist) < 0)
4336        return posix_error();
4337    Py_INCREF(Py_None);
4338    return Py_None;
4339}
4340#endif /* HAVE_SETGROUPS */
4341
4342#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
4343static PyObject *
4344wait_helper(pid_t pid, int status, struct rusage *ru)
4345{
4346    PyObject *result;
4347    static PyObject *struct_rusage;
4348
4349    if (pid == -1)
4350        return posix_error();
4351
4352    if (struct_rusage == NULL) {
4353        PyObject *m = PyImport_ImportModuleNoBlock("resource");
4354        if (m == NULL)
4355            return NULL;
4356        struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
4357        Py_DECREF(m);
4358        if (struct_rusage == NULL)
4359            return NULL;
4360    }
4361
4362    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
4363    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
4364    if (!result)
4365        return NULL;
4366
4367#ifndef doubletime
4368#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
4369#endif
4370
4371    PyStructSequence_SET_ITEM(result, 0,
4372                              PyFloat_FromDouble(doubletime(ru->ru_utime)));
4373    PyStructSequence_SET_ITEM(result, 1,
4374                              PyFloat_FromDouble(doubletime(ru->ru_stime)));
4375#define SET_INT(result, index, value)\
4376        PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value))
4377    SET_INT(result, 2, ru->ru_maxrss);
4378    SET_INT(result, 3, ru->ru_ixrss);
4379    SET_INT(result, 4, ru->ru_idrss);
4380    SET_INT(result, 5, ru->ru_isrss);
4381    SET_INT(result, 6, ru->ru_minflt);
4382    SET_INT(result, 7, ru->ru_majflt);
4383    SET_INT(result, 8, ru->ru_nswap);
4384    SET_INT(result, 9, ru->ru_inblock);
4385    SET_INT(result, 10, ru->ru_oublock);
4386    SET_INT(result, 11, ru->ru_msgsnd);
4387    SET_INT(result, 12, ru->ru_msgrcv);
4388    SET_INT(result, 13, ru->ru_nsignals);
4389    SET_INT(result, 14, ru->ru_nvcsw);
4390    SET_INT(result, 15, ru->ru_nivcsw);
4391#undef SET_INT
4392
4393    if (PyErr_Occurred()) {
4394        Py_DECREF(result);
4395        return NULL;
4396    }
4397
4398    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
4399}
4400#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
4401
4402#ifdef HAVE_WAIT3
4403PyDoc_STRVAR(posix_wait3__doc__,
4404"wait3(options) -> (pid, status, rusage)\n\n\
4405Wait for completion of a child process.");
4406
4407static PyObject *
4408posix_wait3(PyObject *self, PyObject *args)
4409{
4410    pid_t pid;
4411    int options;
4412    struct rusage ru;
4413    WAIT_TYPE status;
4414    WAIT_STATUS_INT(status) = 0;
4415
4416    if (!PyArg_ParseTuple(args, "i:wait3", &options))
4417        return NULL;
4418
4419    Py_BEGIN_ALLOW_THREADS
4420    pid = wait3(&status, options, &ru);
4421    Py_END_ALLOW_THREADS
4422
4423    return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
4424}
4425#endif /* HAVE_WAIT3 */
4426
4427#ifdef HAVE_WAIT4
4428PyDoc_STRVAR(posix_wait4__doc__,
4429"wait4(pid, options) -> (pid, status, rusage)\n\n\
4430Wait for completion of a given child process.");
4431
4432static PyObject *
4433posix_wait4(PyObject *self, PyObject *args)
4434{
4435    pid_t pid;
4436    int options;
4437    struct rusage ru;
4438    WAIT_TYPE status;
4439    WAIT_STATUS_INT(status) = 0;
4440
4441    if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options))
4442        return NULL;
4443
4444    Py_BEGIN_ALLOW_THREADS
4445    pid = wait4(pid, &status, options, &ru);
4446    Py_END_ALLOW_THREADS
4447
4448    return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
4449}
4450#endif /* HAVE_WAIT4 */
4451
4452#ifdef HAVE_WAITPID
4453PyDoc_STRVAR(posix_waitpid__doc__,
4454"waitpid(pid, options) -> (pid, status)\n\n\
4455Wait for completion of a given child process.");
4456
4457static PyObject *
4458posix_waitpid(PyObject *self, PyObject *args)
4459{
4460    pid_t pid;
4461    int options;
4462    WAIT_TYPE status;
4463    WAIT_STATUS_INT(status) = 0;
4464
4465    if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
4466        return NULL;
4467    Py_BEGIN_ALLOW_THREADS
4468    pid = waitpid(pid, &status, options);
4469    Py_END_ALLOW_THREADS
4470    if (pid == -1)
4471        return posix_error();
4472
4473    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
4474}
4475
4476#elif defined(HAVE_CWAIT)
4477
4478/* MS C has a variant of waitpid() that's usable for most purposes. */
4479PyDoc_STRVAR(posix_waitpid__doc__,
4480"waitpid(pid, options) -> (pid, status << 8)\n\n"
4481"Wait for completion of a given process.  options is ignored on Windows.");
4482
4483static PyObject *
4484posix_waitpid(PyObject *self, PyObject *args)
4485{
4486    Py_intptr_t pid;
4487    int status, options;
4488
4489    if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
4490        return NULL;
4491    Py_BEGIN_ALLOW_THREADS
4492    pid = _cwait(&status, pid, options);
4493    Py_END_ALLOW_THREADS
4494    if (pid == -1)
4495        return posix_error();
4496
4497    /* shift the status left a byte so this is more like the POSIX waitpid */
4498    return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
4499}
4500#endif /* HAVE_WAITPID || HAVE_CWAIT */
4501
4502#ifdef HAVE_WAIT
4503PyDoc_STRVAR(posix_wait__doc__,
4504"wait() -> (pid, status)\n\n\
4505Wait for completion of a child process.");
4506
4507static PyObject *
4508posix_wait(PyObject *self, PyObject *noargs)
4509{
4510    pid_t pid;
4511    WAIT_TYPE status;
4512    WAIT_STATUS_INT(status) = 0;
4513
4514    Py_BEGIN_ALLOW_THREADS
4515    pid = wait(&status);
4516    Py_END_ALLOW_THREADS
4517    if (pid == -1)
4518        return posix_error();
4519
4520    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
4521}
4522#endif
4523
4524
4525PyDoc_STRVAR(posix_lstat__doc__,
4526"lstat(path) -> stat result\n\n\
4527Like stat(path), but do not follow symbolic links.");
4528
4529static PyObject *
4530posix_lstat(PyObject *self, PyObject *args)
4531{
4532#ifdef HAVE_LSTAT
4533    return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL);
4534#else /* !HAVE_LSTAT */
4535    return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL);
4536#endif /* !HAVE_LSTAT */
4537}
4538
4539
4540#ifdef HAVE_READLINK
4541PyDoc_STRVAR(posix_readlink__doc__,
4542"readlink(path) -> path\n\n\
4543Return a string representing the path to which the symbolic link points.");
4544
4545static PyObject *
4546posix_readlink(PyObject *self, PyObject *args)
4547{
4548    PyObject* v;
4549    char buf[MAXPATHLEN];
4550    char *path;
4551    int n;
4552#ifdef Py_USING_UNICODE
4553    int arg_is_unicode = 0;
4554#endif
4555
4556    if (!PyArg_ParseTuple(args, "et:readlink",
4557                          Py_FileSystemDefaultEncoding, &path))
4558        return NULL;
4559#ifdef Py_USING_UNICODE
4560    v = PySequence_GetItem(args, 0);
4561    if (v == NULL) {
4562        PyMem_Free(path);
4563        return NULL;
4564    }
4565
4566    if (PyUnicode_Check(v)) {
4567        arg_is_unicode = 1;
4568    }
4569    Py_DECREF(v);
4570#endif
4571
4572    Py_BEGIN_ALLOW_THREADS
4573    n = readlink(path, buf, (int) sizeof buf);
4574    Py_END_ALLOW_THREADS
4575    if (n < 0)
4576        return posix_error_with_allocated_filename(path);
4577
4578    PyMem_Free(path);
4579    v = PyString_FromStringAndSize(buf, n);
4580#ifdef Py_USING_UNICODE
4581    if (arg_is_unicode) {
4582        PyObject *w;
4583
4584        w = PyUnicode_FromEncodedObject(v,
4585                                        Py_FileSystemDefaultEncoding,
4586                                        "strict");
4587        if (w != NULL) {
4588            Py_DECREF(v);
4589            v = w;
4590        }
4591        else {
4592            /* fall back to the original byte string, as
4593               discussed in patch #683592 */
4594            PyErr_Clear();
4595        }
4596    }
4597#endif
4598    return v;
4599}
4600#endif /* HAVE_READLINK */
4601
4602
4603#ifdef HAVE_SYMLINK
4604PyDoc_STRVAR(posix_symlink__doc__,
4605"symlink(src, dst)\n\n\
4606Create a symbolic link pointing to src named dst.");
4607
4608static PyObject *
4609posix_symlink(PyObject *self, PyObject *args)
4610{
4611    return posix_2str(args, "etet:symlink", symlink);
4612}
4613#endif /* HAVE_SYMLINK */
4614
4615
4616#ifdef HAVE_TIMES
4617#if defined(PYCC_VACPP) && defined(PYOS_OS2)
4618static long
4619system_uptime(void)
4620{
4621    ULONG     value = 0;
4622
4623    Py_BEGIN_ALLOW_THREADS
4624    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
4625    Py_END_ALLOW_THREADS
4626
4627    return value;
4628}
4629
4630static PyObject *
4631posix_times(PyObject *self, PyObject *noargs)
4632{
4633    /* Currently Only Uptime is Provided -- Others Later */
4634    return Py_BuildValue("ddddd",
4635                         (double)0 /* t.tms_utime / HZ */,
4636                         (double)0 /* t.tms_stime / HZ */,
4637                         (double)0 /* t.tms_cutime / HZ */,
4638                         (double)0 /* t.tms_cstime / HZ */,
4639                         (double)system_uptime() / 1000);
4640}
4641#else /* not OS2 */
4642#define NEED_TICKS_PER_SECOND
4643static long ticks_per_second = -1;
4644static PyObject *
4645posix_times(PyObject *self, PyObject *noargs)
4646{
4647    struct tms t;
4648    clock_t c;
4649    errno = 0;
4650    c = times(&t);
4651    if (c == (clock_t) -1)
4652        return posix_error();
4653    return Py_BuildValue("ddddd",
4654                         (double)t.tms_utime / ticks_per_second,
4655                         (double)t.tms_stime / ticks_per_second,
4656                         (double)t.tms_cutime / ticks_per_second,
4657                         (double)t.tms_cstime / ticks_per_second,
4658                         (double)c / ticks_per_second);
4659}
4660#endif /* not OS2 */
4661#endif /* HAVE_TIMES */
4662
4663
4664#ifdef HAVE_TIMES
4665PyDoc_STRVAR(posix_times__doc__,
4666"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
4667Return a tuple of floating point numbers indicating process times.");
4668#endif
4669
4670
4671#ifdef HAVE_GETSID
4672PyDoc_STRVAR(posix_getsid__doc__,
4673"getsid(pid) -> sid\n\n\
4674Call the system call getsid().");
4675
4676static PyObject *
4677posix_getsid(PyObject *self, PyObject *args)
4678{
4679    pid_t pid;
4680    int sid;
4681    if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid))
4682        return NULL;
4683    sid = getsid(pid);
4684    if (sid < 0)
4685        return posix_error();
4686    return PyInt_FromLong((long)sid);
4687}
4688#endif /* HAVE_GETSID */
4689
4690
4691#ifdef HAVE_SETSID
4692PyDoc_STRVAR(posix_setsid__doc__,
4693"setsid()\n\n\
4694Call the system call setsid().");
4695
4696static PyObject *
4697posix_setsid(PyObject *self, PyObject *noargs)
4698{
4699    if (setsid() < 0)
4700        return posix_error();
4701    Py_INCREF(Py_None);
4702    return Py_None;
4703}
4704#endif /* HAVE_SETSID */
4705
4706#ifdef HAVE_SETPGID
4707PyDoc_STRVAR(posix_setpgid__doc__,
4708"setpgid(pid, pgrp)\n\n\
4709Call the system call setpgid().");
4710
4711static PyObject *
4712posix_setpgid(PyObject *self, PyObject *args)
4713{
4714    pid_t pid;
4715    int pgrp;
4716    if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp))
4717        return NULL;
4718    if (setpgid(pid, pgrp) < 0)
4719        return posix_error();
4720    Py_INCREF(Py_None);
4721    return Py_None;
4722}
4723#endif /* HAVE_SETPGID */
4724
4725
4726#ifdef HAVE_TCGETPGRP
4727PyDoc_STRVAR(posix_tcgetpgrp__doc__,
4728"tcgetpgrp(fd) -> pgid\n\n\
4729Return the process group associated with the terminal given by a fd.");
4730
4731static PyObject *
4732posix_tcgetpgrp(PyObject *self, PyObject *args)
4733{
4734    int fd;
4735    pid_t pgid;
4736    if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
4737        return NULL;
4738    pgid = tcgetpgrp(fd);
4739    if (pgid < 0)
4740        return posix_error();
4741    return PyLong_FromPid(pgid);
4742}
4743#endif /* HAVE_TCGETPGRP */
4744
4745
4746#ifdef HAVE_TCSETPGRP
4747PyDoc_STRVAR(posix_tcsetpgrp__doc__,
4748"tcsetpgrp(fd, pgid)\n\n\
4749Set the process group associated with the terminal given by a fd.");
4750
4751static PyObject *
4752posix_tcsetpgrp(PyObject *self, PyObject *args)
4753{
4754    int fd;
4755    pid_t pgid;
4756    if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid))
4757        return NULL;
4758    if (tcsetpgrp(fd, pgid) < 0)
4759        return posix_error();
4760    Py_INCREF(Py_None);
4761    return Py_None;
4762}
4763#endif /* HAVE_TCSETPGRP */
4764
4765/* Functions acting on file descriptors */
4766
4767PyDoc_STRVAR(posix_open__doc__,
4768"open(filename, flag [, mode=0777]) -> fd\n\n\
4769Open a file (for low level IO).");
4770
4771static PyObject *
4772posix_open(PyObject *self, PyObject *args)
4773{
4774    char *file = NULL;
4775    int flag;
4776    int mode = 0777;
4777    int fd;
4778
4779    if (!PyArg_ParseTuple(args, "eti|i",
4780                          Py_FileSystemDefaultEncoding, &file,
4781                          &flag, &mode))
4782        return NULL;
4783
4784    Py_BEGIN_ALLOW_THREADS
4785    fd = open(file, flag, mode);
4786    Py_END_ALLOW_THREADS
4787    if (fd < 0)
4788        return posix_error_with_allocated_filename(file);
4789    PyMem_Free(file);
4790    return PyInt_FromLong((long)fd);
4791}
4792
4793
4794PyDoc_STRVAR(posix_close__doc__,
4795"close(fd)\n\n\
4796Close a file descriptor (for low level IO).");
4797
4798static PyObject *
4799posix_close(PyObject *self, PyObject *args)
4800{
4801    int fd, res;
4802    if (!PyArg_ParseTuple(args, "i:close", &fd))
4803        return NULL;
4804    if (!_PyVerify_fd(fd))
4805        return posix_error();
4806    Py_BEGIN_ALLOW_THREADS
4807    res = close(fd);
4808    Py_END_ALLOW_THREADS
4809    if (res < 0)
4810        return posix_error();
4811    Py_INCREF(Py_None);
4812    return Py_None;
4813}
4814
4815
4816PyDoc_STRVAR(posix_closerange__doc__,
4817"closerange(fd_low, fd_high)\n\n\
4818Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
4819
4820static PyObject *
4821posix_closerange(PyObject *self, PyObject *args)
4822{
4823    int fd_from, fd_to, i;
4824    if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
4825        return NULL;
4826    Py_BEGIN_ALLOW_THREADS
4827    for (i = fd_from; i < fd_to; i++)
4828        if (_PyVerify_fd(i))
4829            close(i);
4830    Py_END_ALLOW_THREADS
4831    Py_RETURN_NONE;
4832}
4833
4834
4835PyDoc_STRVAR(posix_dup__doc__,
4836"dup(fd) -> fd2\n\n\
4837Return a duplicate of a file descriptor.");
4838
4839static PyObject *
4840posix_dup(PyObject *self, PyObject *args)
4841{
4842    int fd;
4843    if (!PyArg_ParseTuple(args, "i:dup", &fd))
4844        return NULL;
4845    if (!_PyVerify_fd(fd))
4846        return posix_error();
4847    Py_BEGIN_ALLOW_THREADS
4848    fd = dup(fd);
4849    Py_END_ALLOW_THREADS
4850    if (fd < 0)
4851        return posix_error();
4852    return PyInt_FromLong((long)fd);
4853}
4854
4855
4856PyDoc_STRVAR(posix_dup2__doc__,
4857"dup2(old_fd, new_fd)\n\n\
4858Duplicate file descriptor.");
4859
4860static PyObject *
4861posix_dup2(PyObject *self, PyObject *args)
4862{
4863    int fd, fd2, res;
4864    if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
4865        return NULL;
4866    if (!_PyVerify_fd_dup2(fd, fd2))
4867        return posix_error();
4868    Py_BEGIN_ALLOW_THREADS
4869    res = dup2(fd, fd2);
4870    Py_END_ALLOW_THREADS
4871    if (res < 0)
4872        return posix_error();
4873    Py_INCREF(Py_None);
4874    return Py_None;
4875}
4876
4877
4878PyDoc_STRVAR(posix_lseek__doc__,
4879"lseek(fd, pos, how) -> newpos\n\n\
4880Set the current position of a file descriptor.");
4881
4882static PyObject *
4883posix_lseek(PyObject *self, PyObject *args)
4884{
4885    int fd, how;
4886    off_t pos, res;
4887    PyObject *posobj;
4888    if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
4889        return NULL;
4890#ifdef SEEK_SET
4891    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
4892    switch (how) {
4893    case 0: how = SEEK_SET; break;
4894    case 1: how = SEEK_CUR; break;
4895    case 2: how = SEEK_END; break;
4896    }
4897#endif /* SEEK_END */
4898
4899#if !defined(HAVE_LARGEFILE_SUPPORT)
4900    pos = PyInt_AsLong(posobj);
4901#else
4902    pos = PyLong_Check(posobj) ?
4903        PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj);
4904#endif
4905    if (PyErr_Occurred())
4906        return NULL;
4907
4908    if (!_PyVerify_fd(fd))
4909        return posix_error();
4910    Py_BEGIN_ALLOW_THREADS
4911    res = lseek(fd, pos, how);
4912    Py_END_ALLOW_THREADS
4913    if (res < 0)
4914        return posix_error();
4915
4916#if !defined(HAVE_LARGEFILE_SUPPORT)
4917    return PyInt_FromLong(res);
4918#else
4919    return PyLong_FromLongLong(res);
4920#endif
4921}
4922
4923
4924PyDoc_STRVAR(posix_read__doc__,
4925"read(fd, buffersize) -> string\n\n\
4926Read a file descriptor.");
4927
4928static PyObject *
4929posix_read(PyObject *self, PyObject *args)
4930{
4931    int fd, size, n;
4932    PyObject *buffer;
4933    if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
4934        return NULL;
4935    if (size < 0) {
4936        errno = EINVAL;
4937        return posix_error();
4938    }
4939    buffer = PyString_FromStringAndSize((char *)NULL, size);
4940    if (buffer == NULL)
4941        return NULL;
4942    if (!_PyVerify_fd(fd)) {
4943        Py_DECREF(buffer);
4944        return posix_error();
4945    }
4946    Py_BEGIN_ALLOW_THREADS
4947    n = read(fd, PyString_AsString(buffer), size);
4948    Py_END_ALLOW_THREADS
4949    if (n < 0) {
4950        Py_DECREF(buffer);
4951        return posix_error();
4952    }
4953    if (n != size)
4954        _PyString_Resize(&buffer, n);
4955    return buffer;
4956}
4957
4958
4959PyDoc_STRVAR(posix_write__doc__,
4960"write(fd, string) -> byteswritten\n\n\
4961Write a string to a file descriptor.");
4962
4963static PyObject *
4964posix_write(PyObject *self, PyObject *args)
4965{
4966    Py_buffer pbuf;
4967    int fd;
4968    Py_ssize_t size;
4969
4970    if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
4971        return NULL;
4972    if (!_PyVerify_fd(fd)) {
4973        PyBuffer_Release(&pbuf);
4974        return posix_error();
4975    }
4976    Py_BEGIN_ALLOW_THREADS
4977    size = write(fd, pbuf.buf, (size_t)pbuf.len);
4978    Py_END_ALLOW_THREADS
4979    PyBuffer_Release(&pbuf);
4980    if (size < 0)
4981        return posix_error();
4982    return PyInt_FromSsize_t(size);
4983}
4984
4985
4986PyDoc_STRVAR(posix_fstat__doc__,
4987"fstat(fd) -> stat result\n\n\
4988Like stat(), but for an open file descriptor.");
4989
4990static PyObject *
4991posix_fstat(PyObject *self, PyObject *args)
4992{
4993    int fd;
4994    STRUCT_STAT st;
4995    int res;
4996    if (!PyArg_ParseTuple(args, "i:fstat", &fd))
4997        return NULL;
4998    if (!_PyVerify_fd(fd))
4999        return posix_error();
5000    Py_BEGIN_ALLOW_THREADS
5001    res = FSTAT(fd, &st);
5002    Py_END_ALLOW_THREADS
5003    if (res != 0) {
5004      return posix_error();
5005    }
5006
5007    return _pystat_fromstructstat(&st);
5008}
5009
5010
5011PyDoc_STRVAR(posix_fdopen__doc__,
5012"fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
5013Return an open file object connected to a file descriptor.");
5014
5015static PyObject *
5016posix_fdopen(PyObject *self, PyObject *args)
5017{
5018    int fd;
5019    char *orgmode = "r";
5020    int bufsize = -1;
5021    FILE *fp;
5022    PyObject *f;
5023    char *mode;
5024    if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize))
5025        return NULL;
5026
5027    /* Sanitize mode.  See fileobject.c */
5028    mode = PyMem_MALLOC(strlen(orgmode)+3);
5029    if (!mode) {
5030        PyErr_NoMemory();
5031        return NULL;
5032    }
5033    strcpy(mode, orgmode);
5034    if (_PyFile_SanitizeMode(mode)) {
5035        PyMem_FREE(mode);
5036        return NULL;
5037    }
5038    if (!_PyVerify_fd(fd))
5039        return posix_error();
5040    Py_BEGIN_ALLOW_THREADS
5041#if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H)
5042    if (mode[0] == 'a') {
5043        /* try to make sure the O_APPEND flag is set */
5044        int flags;
5045        flags = fcntl(fd, F_GETFL);
5046        if (flags != -1)
5047            fcntl(fd, F_SETFL, flags | O_APPEND);
5048        fp = fdopen(fd, mode);
5049        if (fp == NULL && flags != -1)
5050            /* restore old mode if fdopen failed */
5051            fcntl(fd, F_SETFL, flags);
5052    } else {
5053        fp = fdopen(fd, mode);
5054    }
5055#else
5056    fp = fdopen(fd, mode);
5057#endif
5058    Py_END_ALLOW_THREADS
5059    PyMem_FREE(mode);
5060    if (fp == NULL)
5061        return posix_error();
5062    f = PyFile_FromFile(fp, "<fdopen>", orgmode, fclose);
5063    if (f != NULL)
5064        PyFile_SetBufSize(f, bufsize);
5065    return f;
5066}
5067
5068PyDoc_STRVAR(posix_isatty__doc__,
5069"isatty(fd) -> bool\n\n\
5070Return True if the file descriptor 'fd' is an open file descriptor\n\
5071connected to the slave end of a terminal.");
5072
5073static PyObject *
5074posix_isatty(PyObject *self, PyObject *args)
5075{
5076    int fd;
5077    if (!PyArg_ParseTuple(args, "i:isatty", &fd))
5078        return NULL;
5079    if (!_PyVerify_fd(fd))
5080        return PyBool_FromLong(0);
5081    return PyBool_FromLong(isatty(fd));
5082}
5083
5084#ifdef HAVE_PIPE
5085PyDoc_STRVAR(posix_pipe__doc__,
5086"pipe() -> (read_end, write_end)\n\n\
5087Create a pipe.");
5088
5089static PyObject *
5090posix_pipe(PyObject *self, PyObject *noargs)
5091{
5092#if defined(PYOS_OS2)
5093    HFILE read, write;
5094    APIRET rc;
5095
5096    Py_BEGIN_ALLOW_THREADS
5097    rc = DosCreatePipe( &read, &write, 4096);
5098    Py_END_ALLOW_THREADS
5099    if (rc != NO_ERROR)
5100        return os2_error(rc);
5101
5102    return Py_BuildValue("(ii)", read, write);
5103#else
5104#if !defined(MS_WINDOWS)
5105    int fds[2];
5106    int res;
5107    Py_BEGIN_ALLOW_THREADS
5108    res = pipe(fds);
5109    Py_END_ALLOW_THREADS
5110    if (res != 0)
5111        return posix_error();
5112    return Py_BuildValue("(ii)", fds[0], fds[1]);
5113#else /* MS_WINDOWS */
5114    HANDLE read, write;
5115    int read_fd, write_fd;
5116    BOOL ok;
5117    Py_BEGIN_ALLOW_THREADS
5118    ok = CreatePipe(&read, &write, NULL, 0);
5119    Py_END_ALLOW_THREADS
5120    if (!ok)
5121        return win32_error("CreatePipe", NULL);
5122    read_fd = _open_osfhandle((Py_intptr_t)read, 0);
5123    write_fd = _open_osfhandle((Py_intptr_t)write, 1);
5124    return Py_BuildValue("(ii)", read_fd, write_fd);
5125#endif /* MS_WINDOWS */
5126#endif
5127}
5128#endif  /* HAVE_PIPE */
5129
5130
5131#ifdef HAVE_MKFIFO
5132PyDoc_STRVAR(posix_mkfifo__doc__,
5133"mkfifo(filename [, mode=0666])\n\n\
5134Create a FIFO (a POSIX named pipe).");
5135
5136static PyObject *
5137posix_mkfifo(PyObject *self, PyObject *args)
5138{
5139    char *filename;
5140    int mode = 0666;
5141    int res;
5142    if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode))
5143        return NULL;
5144    Py_BEGIN_ALLOW_THREADS
5145    res = mkfifo(filename, mode);
5146    Py_END_ALLOW_THREADS
5147    if (res < 0)
5148        return posix_error();
5149    Py_INCREF(Py_None);
5150    return Py_None;
5151}
5152#endif
5153
5154
5155#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
5156PyDoc_STRVAR(posix_mknod__doc__,
5157"mknod(filename [, mode=0600, device])\n\n\
5158Create a filesystem node (file, device special file or named pipe)\n\
5159named filename. mode specifies both the permissions to use and the\n\
5160type of node to be created, being combined (bitwise OR) with one of\n\
5161S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
5162device defines the newly created device special file (probably using\n\
5163os.makedev()), otherwise it is ignored.");
5164
5165
5166static PyObject *
5167posix_mknod(PyObject *self, PyObject *args)
5168{
5169    char *filename;
5170    int mode = 0600;
5171    int device = 0;
5172    int res;
5173    if (!PyArg_ParseTuple(args, "s|ii:mknod", &filename, &mode, &device))
5174        return NULL;
5175    Py_BEGIN_ALLOW_THREADS
5176    res = mknod(filename, mode, device);
5177    Py_END_ALLOW_THREADS
5178    if (res < 0)
5179        return posix_error();
5180    Py_INCREF(Py_None);
5181    return Py_None;
5182}
5183#endif
5184
5185#ifdef HAVE_DEVICE_MACROS
5186PyDoc_STRVAR(posix_major__doc__,
5187"major(device) -> major number\n\
5188Extracts a device major number from a raw device number.");
5189
5190static PyObject *
5191posix_major(PyObject *self, PyObject *args)
5192{
5193    int device;
5194    if (!PyArg_ParseTuple(args, "i:major", &device))
5195        return NULL;
5196    return PyInt_FromLong((long)major(device));
5197}
5198
5199PyDoc_STRVAR(posix_minor__doc__,
5200"minor(device) -> minor number\n\
5201Extracts a device minor number from a raw device number.");
5202
5203static PyObject *
5204posix_minor(PyObject *self, PyObject *args)
5205{
5206    int device;
5207    if (!PyArg_ParseTuple(args, "i:minor", &device))
5208        return NULL;
5209    return PyInt_FromLong((long)minor(device));
5210}
5211
5212PyDoc_STRVAR(posix_makedev__doc__,
5213"makedev(major, minor) -> device number\n\
5214Composes a raw device number from the major and minor device numbers.");
5215
5216static PyObject *
5217posix_makedev(PyObject *self, PyObject *args)
5218{
5219    int major, minor;
5220    if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
5221        return NULL;
5222    return PyInt_FromLong((long)makedev(major, minor));
5223}
5224#endif /* device macros */
5225
5226
5227#ifdef HAVE_FTRUNCATE
5228PyDoc_STRVAR(posix_ftruncate__doc__,
5229"ftruncate(fd, length)\n\n\
5230Truncate a file to a specified length.");
5231
5232static PyObject *
5233posix_ftruncate(PyObject *self, PyObject *args)
5234{
5235    int fd;
5236    off_t length;
5237    int res;
5238    PyObject *lenobj;
5239
5240    if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
5241        return NULL;
5242
5243#if !defined(HAVE_LARGEFILE_SUPPORT)
5244    length = PyInt_AsLong(lenobj);
5245#else
5246    length = PyLong_Check(lenobj) ?
5247        PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj);
5248#endif
5249    if (PyErr_Occurred())
5250        return NULL;
5251
5252    Py_BEGIN_ALLOW_THREADS
5253    res = ftruncate(fd, length);
5254    Py_END_ALLOW_THREADS
5255    if (res < 0)
5256        return posix_error();
5257    Py_INCREF(Py_None);
5258    return Py_None;
5259}
5260#endif
5261
5262#ifdef HAVE_PUTENV
5263PyDoc_STRVAR(posix_putenv__doc__,
5264"putenv(key, value)\n\n\
5265Change or add an environment variable.");
5266
5267/* Save putenv() parameters as values here, so we can collect them when they
5268 * get re-set with another call for the same key. */
5269static PyObject *posix_putenv_garbage;
5270
5271static PyObject *
5272posix_putenv(PyObject *self, PyObject *args)
5273{
5274    char *s1, *s2;
5275    char *newenv;
5276    PyObject *newstr;
5277    size_t len;
5278
5279    if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2))
5280        return NULL;
5281
5282#if defined(PYOS_OS2)
5283    if (stricmp(s1, "BEGINLIBPATH") == 0) {
5284        APIRET rc;
5285
5286        rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
5287        if (rc != NO_ERROR)
5288            return os2_error(rc);
5289
5290    } else if (stricmp(s1, "ENDLIBPATH") == 0) {
5291        APIRET rc;
5292
5293        rc = DosSetExtLIBPATH(s2, END_LIBPATH);
5294        if (rc != NO_ERROR)
5295            return os2_error(rc);
5296    } else {
5297#endif
5298
5299    /* XXX This can leak memory -- not easy to fix :-( */
5300    len = strlen(s1) + strlen(s2) + 2;
5301    /* len includes space for a trailing \0; the size arg to
5302       PyString_FromStringAndSize does not count that */
5303    newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
5304    if (newstr == NULL)
5305        return PyErr_NoMemory();
5306    newenv = PyString_AS_STRING(newstr);
5307    PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
5308    if (putenv(newenv)) {
5309        Py_DECREF(newstr);
5310        posix_error();
5311        return NULL;
5312    }
5313    /* Install the first arg and newstr in posix_putenv_garbage;
5314     * this will cause previous value to be collected.  This has to
5315     * happen after the real putenv() call because the old value
5316     * was still accessible until then. */
5317    if (PyDict_SetItem(posix_putenv_garbage,
5318                       PyTuple_GET_ITEM(args, 0), newstr)) {
5319        /* really not much we can do; just leak */
5320        PyErr_Clear();
5321    }
5322    else {
5323        Py_DECREF(newstr);
5324    }
5325
5326#if defined(PYOS_OS2)
5327    }
5328#endif
5329    Py_INCREF(Py_None);
5330    return Py_None;
5331}
5332#endif /* putenv */
5333
5334#ifdef HAVE_UNSETENV
5335PyDoc_STRVAR(posix_unsetenv__doc__,
5336"unsetenv(key)\n\n\
5337Delete an environment variable.");
5338
5339static PyObject *
5340posix_unsetenv(PyObject *self, PyObject *args)
5341{
5342    char *s1;
5343
5344    if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
5345        return NULL;
5346
5347    unsetenv(s1);
5348
5349    /* Remove the key from posix_putenv_garbage;
5350     * this will cause it to be collected.  This has to
5351     * happen after the real unsetenv() call because the
5352     * old value was still accessible until then.
5353     */
5354    if (PyDict_DelItem(posix_putenv_garbage,
5355                       PyTuple_GET_ITEM(args, 0))) {
5356        /* really not much we can do; just leak */
5357        PyErr_Clear();
5358    }
5359
5360    Py_INCREF(Py_None);
5361    return Py_None;
5362}
5363#endif /* unsetenv */
5364
5365PyDoc_STRVAR(posix_strerror__doc__,
5366"strerror(code) -> string\n\n\
5367Translate an error code to a message string.");
5368
5369static PyObject *
5370posix_strerror(PyObject *self, PyObject *args)
5371{
5372    int code;
5373    char *message;
5374    if (!PyArg_ParseTuple(args, "i:strerror", &code))
5375        return NULL;
5376    message = strerror(code);
5377    if (message == NULL) {
5378        PyErr_SetString(PyExc_ValueError,
5379                        "strerror() argument out of range");
5380        return NULL;
5381    }
5382    return PyString_FromString(message);
5383}
5384
5385
5386#ifdef HAVE_SYS_WAIT_H
5387
5388#ifdef WCOREDUMP
5389PyDoc_STRVAR(posix_WCOREDUMP__doc__,
5390"WCOREDUMP(status) -> bool\n\n\
5391Return True if the process returning 'status' was dumped to a core file.");
5392
5393static PyObject *
5394posix_WCOREDUMP(PyObject *self, PyObject *args)
5395{
5396    WAIT_TYPE status;
5397    WAIT_STATUS_INT(status) = 0;
5398
5399    if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
5400        return NULL;
5401
5402    return PyBool_FromLong(WCOREDUMP(status));
5403}
5404#endif /* WCOREDUMP */
5405
5406#ifdef WIFCONTINUED
5407PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
5408"WIFCONTINUED(status) -> bool\n\n\
5409Return True if the process returning 'status' was continued from a\n\
5410job control stop.");
5411
5412static PyObject *
5413posix_WIFCONTINUED(PyObject *self, PyObject *args)
5414{
5415    WAIT_TYPE status;
5416    WAIT_STATUS_INT(status) = 0;
5417
5418    if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
5419        return NULL;
5420
5421    return PyBool_FromLong(WIFCONTINUED(status));
5422}
5423#endif /* WIFCONTINUED */
5424
5425#ifdef WIFSTOPPED
5426PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
5427"WIFSTOPPED(status) -> bool\n\n\
5428Return True if the process returning 'status' was stopped.");
5429
5430static PyObject *
5431posix_WIFSTOPPED(PyObject *self, PyObject *args)
5432{
5433    WAIT_TYPE status;
5434    WAIT_STATUS_INT(status) = 0;
5435
5436    if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
5437        return NULL;
5438
5439    return PyBool_FromLong(WIFSTOPPED(status));
5440}
5441#endif /* WIFSTOPPED */
5442
5443#ifdef WIFSIGNALED
5444PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
5445"WIFSIGNALED(status) -> bool\n\n\
5446Return True if the process returning 'status' was terminated by a signal.");
5447
5448static PyObject *
5449posix_WIFSIGNALED(PyObject *self, PyObject *args)
5450{
5451    WAIT_TYPE status;
5452    WAIT_STATUS_INT(status) = 0;
5453
5454    if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
5455        return NULL;
5456
5457    return PyBool_FromLong(WIFSIGNALED(status));
5458}
5459#endif /* WIFSIGNALED */
5460
5461#ifdef WIFEXITED
5462PyDoc_STRVAR(posix_WIFEXITED__doc__,
5463"WIFEXITED(status) -> bool\n\n\
5464Return true if the process returning 'status' exited using the exit()\n\
5465system call.");
5466
5467static PyObject *
5468posix_WIFEXITED(PyObject *self, PyObject *args)
5469{
5470    WAIT_TYPE status;
5471    WAIT_STATUS_INT(status) = 0;
5472
5473    if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
5474        return NULL;
5475
5476    return PyBool_FromLong(WIFEXITED(status));
5477}
5478#endif /* WIFEXITED */
5479
5480#ifdef WEXITSTATUS
5481PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
5482"WEXITSTATUS(status) -> integer\n\n\
5483Return the process return code from 'status'.");
5484
5485static PyObject *
5486posix_WEXITSTATUS(PyObject *self, PyObject *args)
5487{
5488    WAIT_TYPE status;
5489    WAIT_STATUS_INT(status) = 0;
5490
5491    if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
5492        return NULL;
5493
5494    return Py_BuildValue("i", WEXITSTATUS(status));
5495}
5496#endif /* WEXITSTATUS */
5497
5498#ifdef WTERMSIG
5499PyDoc_STRVAR(posix_WTERMSIG__doc__,
5500"WTERMSIG(status) -> integer\n\n\
5501Return the signal that terminated the process that provided the 'status'\n\
5502value.");
5503
5504static PyObject *
5505posix_WTERMSIG(PyObject *self, PyObject *args)
5506{
5507    WAIT_TYPE status;
5508    WAIT_STATUS_INT(status) = 0;
5509
5510    if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
5511        return NULL;
5512
5513    return Py_BuildValue("i", WTERMSIG(status));
5514}
5515#endif /* WTERMSIG */
5516
5517#ifdef WSTOPSIG
5518PyDoc_STRVAR(posix_WSTOPSIG__doc__,
5519"WSTOPSIG(status) -> integer\n\n\
5520Return the signal that stopped the process that provided\n\
5521the 'status' value.");
5522
5523static PyObject *
5524posix_WSTOPSIG(PyObject *self, PyObject *args)
5525{
5526    WAIT_TYPE status;
5527    WAIT_STATUS_INT(status) = 0;
5528
5529    if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
5530        return NULL;
5531
5532    return Py_BuildValue("i", WSTOPSIG(status));
5533}
5534#endif /* WSTOPSIG */
5535
5536#endif /* HAVE_SYS_WAIT_H */
5537
5538
5539#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
5540#ifdef _SCO_DS
5541/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
5542   needed definitions in sys/statvfs.h */
5543#define _SVID3
5544#endif
5545#include <sys/statvfs.h>
5546
5547static PyObject*
5548_pystatvfs_fromstructstatvfs(struct statvfs st) {
5549    PyObject *v = PyStructSequence_New(&StatVFSResultType);
5550    if (v == NULL)
5551        return NULL;
5552
5553#if !defined(HAVE_LARGEFILE_SUPPORT)
5554    PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
5555    PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
5556    PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) st.f_blocks));
5557    PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) st.f_bfree));
5558    PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) st.f_bavail));
5559    PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) st.f_files));
5560    PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong((long) st.f_ffree));
5561    PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) st.f_favail));
5562    PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
5563    PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
5564#else
5565    PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
5566    PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
5567    PyStructSequence_SET_ITEM(v, 2,
5568                              PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
5569    PyStructSequence_SET_ITEM(v, 3,
5570                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
5571    PyStructSequence_SET_ITEM(v, 4,
5572                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
5573    PyStructSequence_SET_ITEM(v, 5,
5574                              PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
5575    PyStructSequence_SET_ITEM(v, 6,
5576                              PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
5577    PyStructSequence_SET_ITEM(v, 7,
5578                              PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
5579    PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
5580    PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
5581#endif
5582
5583    return v;
5584}
5585
5586PyDoc_STRVAR(posix_fstatvfs__doc__,
5587"fstatvfs(fd) -> statvfs result\n\n\
5588Perform an fstatvfs system call on the given fd.");
5589
5590static PyObject *
5591posix_fstatvfs(PyObject *self, PyObject *args)
5592{
5593    int fd, res;
5594    struct statvfs st;
5595
5596    if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
5597        return NULL;
5598    Py_BEGIN_ALLOW_THREADS
5599    res = fstatvfs(fd, &st);
5600    Py_END_ALLOW_THREADS
5601    if (res != 0)
5602        return posix_error();
5603
5604    return _pystatvfs_fromstructstatvfs(st);
5605}
5606#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
5607
5608
5609#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
5610#include <sys/statvfs.h>
5611
5612PyDoc_STRVAR(posix_statvfs__doc__,
5613"statvfs(path) -> statvfs result\n\n\
5614Perform a statvfs system call on the given path.");
5615
5616static PyObject *
5617posix_statvfs(PyObject *self, PyObject *args)
5618{
5619    char *path;
5620    int res;
5621    struct statvfs st;
5622    if (!PyArg_ParseTuple(args, "s:statvfs", &path))
5623        return NULL;
5624    Py_BEGIN_ALLOW_THREADS
5625    res = statvfs(path, &st);
5626    Py_END_ALLOW_THREADS
5627    if (res != 0)
5628        return posix_error_with_filename(path);
5629
5630    return _pystatvfs_fromstructstatvfs(st);
5631}
5632#endif /* HAVE_STATVFS */
5633
5634
5635#ifdef HAVE_TEMPNAM
5636PyDoc_STRVAR(posix_tempnam__doc__,
5637"tempnam([dir[, prefix]]) -> string\n\n\
5638Return a unique name for a temporary file.\n\
5639The directory and a prefix may be specified as strings; they may be omitted\n\
5640or None if not needed.");
5641
5642static PyObject *
5643posix_tempnam(PyObject *self, PyObject *args)
5644{
5645    PyObject *result = NULL;
5646    char *dir = NULL;
5647    char *pfx = NULL;
5648    char *name;
5649
5650    if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx))
5651    return NULL;
5652
5653    if (PyErr_Warn(PyExc_RuntimeWarning,
5654                   "tempnam is a potential security risk to your program") < 0)
5655        return NULL;
5656
5657    if (PyErr_WarnPy3k("tempnam has been removed in 3.x; "
5658                       "use the tempfile module", 1) < 0)
5659        return NULL;
5660
5661    name = tempnam(dir, pfx);
5662    if (name == NULL)
5663        return PyErr_NoMemory();
5664    result = PyString_FromString(name);
5665    free(name);
5666    return result;
5667}
5668#endif
5669
5670
5671#ifdef HAVE_TMPFILE
5672PyDoc_STRVAR(posix_tmpfile__doc__,
5673"tmpfile() -> file object\n\n\
5674Create a temporary file with no directory entries.");
5675
5676static PyObject *
5677posix_tmpfile(PyObject *self, PyObject *noargs)
5678{
5679    FILE *fp;
5680
5681    if (PyErr_WarnPy3k("tmpfile has been removed in 3.x; "
5682                       "use the tempfile module", 1) < 0)
5683        return NULL;
5684
5685    fp = tmpfile();
5686    if (fp == NULL)
5687        return posix_error();
5688    return PyFile_FromFile(fp, "<tmpfile>", "w+b", fclose);
5689}
5690#endif
5691
5692
5693#ifdef HAVE_TMPNAM
5694PyDoc_STRVAR(posix_tmpnam__doc__,
5695"tmpnam() -> string\n\n\
5696Return a unique name for a temporary file.");
5697
5698static PyObject *
5699posix_tmpnam(PyObject *self, PyObject *noargs)
5700{
5701    char buffer[L_tmpnam];
5702    char *name;
5703
5704    if (PyErr_Warn(PyExc_RuntimeWarning,
5705                   "tmpnam is a potential security risk to your program") < 0)
5706        return NULL;
5707
5708    if (PyErr_WarnPy3k("tmpnam has been removed in 3.x; "
5709                       "use the tempfile module", 1) < 0)
5710        return NULL;
5711
5712#ifdef USE_TMPNAM_R
5713    name = tmpnam_r(buffer);
5714#else
5715    name = tmpnam(buffer);
5716#endif
5717    if (name == NULL) {
5718        PyObject *err = Py_BuildValue("is", 0,
5719#ifdef USE_TMPNAM_R
5720                                      "unexpected NULL from tmpnam_r"
5721#else
5722                                      "unexpected NULL from tmpnam"
5723#endif
5724                                      );
5725        PyErr_SetObject(PyExc_OSError, err);
5726        Py_XDECREF(err);
5727        return NULL;
5728    }
5729    return PyString_FromString(buffer);
5730}
5731#endif
5732
5733
5734/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
5735 * It maps strings representing configuration variable names to
5736 * integer values, allowing those functions to be called with the
5737 * magic names instead of polluting the module's namespace with tons of
5738 * rarely-used constants.  There are three separate tables that use
5739 * these definitions.
5740 *
5741 * This code is always included, even if none of the interfaces that
5742 * need it are included.  The #if hackery needed to avoid it would be
5743 * sufficiently pervasive that it's not worth the loss of readability.
5744 */
5745struct constdef {
5746    char *name;
5747    long value;
5748};
5749
5750#ifndef UEFI_C_SOURCE
5751static int
5752conv_confname(PyObject *arg, int *valuep, struct constdef *table,
5753              size_t tablesize)
5754{
5755    if (PyInt_Check(arg)) {
5756        *valuep = PyInt_AS_LONG(arg);
5757        return 1;
5758    }
5759    if (PyString_Check(arg)) {
5760        /* look up the value in the table using a binary search */
5761        size_t lo = 0;
5762        size_t mid;
5763        size_t hi = tablesize;
5764        int cmp;
5765        char *confname = PyString_AS_STRING(arg);
5766        while (lo < hi) {
5767            mid = (lo + hi) / 2;
5768            cmp = strcmp(confname, table[mid].name);
5769            if (cmp < 0)
5770                hi = mid;
5771            else if (cmp > 0)
5772                lo = mid + 1;
5773            else {
5774                *valuep = table[mid].value;
5775                return 1;
5776            }
5777        }
5778        PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
5779    }
5780    else
5781        PyErr_SetString(PyExc_TypeError,
5782                        "configuration names must be strings or integers");
5783    return 0;
5784}
5785#endif  /* UEFI_C_SOURCE */
5786
5787#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
5788static struct constdef  posix_constants_pathconf[] = {
5789#ifdef _PC_ABI_AIO_XFER_MAX
5790    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
5791#endif
5792#ifdef _PC_ABI_ASYNC_IO
5793    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
5794#endif
5795#ifdef _PC_ASYNC_IO
5796    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
5797#endif
5798#ifdef _PC_CHOWN_RESTRICTED
5799    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
5800#endif
5801#ifdef _PC_FILESIZEBITS
5802    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
5803#endif
5804#ifdef _PC_LAST
5805    {"PC_LAST", _PC_LAST},
5806#endif
5807#ifdef _PC_LINK_MAX
5808    {"PC_LINK_MAX",     _PC_LINK_MAX},
5809#endif
5810#ifdef _PC_MAX_CANON
5811    {"PC_MAX_CANON",    _PC_MAX_CANON},
5812#endif
5813#ifdef _PC_MAX_INPUT
5814    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
5815#endif
5816#ifdef _PC_NAME_MAX
5817    {"PC_NAME_MAX",     _PC_NAME_MAX},
5818#endif
5819#ifdef _PC_NO_TRUNC
5820    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
5821#endif
5822#ifdef _PC_PATH_MAX
5823    {"PC_PATH_MAX",     _PC_PATH_MAX},
5824#endif
5825#ifdef _PC_PIPE_BUF
5826    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
5827#endif
5828#ifdef _PC_PRIO_IO
5829    {"PC_PRIO_IO",      _PC_PRIO_IO},
5830#endif
5831#ifdef _PC_SOCK_MAXBUF
5832    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
5833#endif
5834#ifdef _PC_SYNC_IO
5835    {"PC_SYNC_IO",      _PC_SYNC_IO},
5836#endif
5837#ifdef _PC_VDISABLE
5838    {"PC_VDISABLE",     _PC_VDISABLE},
5839#endif
5840};
5841
5842static int
5843conv_path_confname(PyObject *arg, int *valuep)
5844{
5845    return conv_confname(arg, valuep, posix_constants_pathconf,
5846                         sizeof(posix_constants_pathconf)
5847                           / sizeof(struct constdef));
5848}
5849#endif
5850
5851#ifdef HAVE_FPATHCONF
5852PyDoc_STRVAR(posix_fpathconf__doc__,
5853"fpathconf(fd, name) -> integer\n\n\
5854Return the configuration limit name for the file descriptor fd.\n\
5855If there is no limit, return -1.");
5856
5857static PyObject *
5858posix_fpathconf(PyObject *self, PyObject *args)
5859{
5860    PyObject *result = NULL;
5861    int name, fd;
5862
5863    if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
5864                         conv_path_confname, &name)) {
5865        long limit;
5866
5867        errno = 0;
5868        limit = fpathconf(fd, name);
5869        if (limit == -1 && errno != 0)
5870            posix_error();
5871        else
5872            result = PyInt_FromLong(limit);
5873    }
5874    return result;
5875}
5876#endif
5877
5878
5879#ifdef HAVE_PATHCONF
5880PyDoc_STRVAR(posix_pathconf__doc__,
5881"pathconf(path, name) -> integer\n\n\
5882Return the configuration limit name for the file or directory path.\n\
5883If there is no limit, return -1.");
5884
5885static PyObject *
5886posix_pathconf(PyObject *self, PyObject *args)
5887{
5888    PyObject *result = NULL;
5889    int name;
5890    char *path;
5891
5892    if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
5893                         conv_path_confname, &name)) {
5894    long limit;
5895
5896    errno = 0;
5897    limit = pathconf(path, name);
5898    if (limit == -1 && errno != 0) {
5899        if (errno == EINVAL)
5900            /* could be a path or name problem */
5901            posix_error();
5902        else
5903            posix_error_with_filename(path);
5904    }
5905    else
5906        result = PyInt_FromLong(limit);
5907    }
5908    return result;
5909}
5910#endif
5911
5912#ifdef HAVE_CONFSTR
5913static struct constdef posix_constants_confstr[] = {
5914#ifdef _CS_ARCHITECTURE
5915    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
5916#endif
5917#ifdef _CS_HOSTNAME
5918    {"CS_HOSTNAME",     _CS_HOSTNAME},
5919#endif
5920#ifdef _CS_HW_PROVIDER
5921    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
5922#endif
5923#ifdef _CS_HW_SERIAL
5924    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
5925#endif
5926#ifdef _CS_INITTAB_NAME
5927    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
5928#endif
5929#ifdef _CS_LFS64_CFLAGS
5930    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
5931#endif
5932#ifdef _CS_LFS64_LDFLAGS
5933    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
5934#endif
5935#ifdef _CS_LFS64_LIBS
5936    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
5937#endif
5938#ifdef _CS_LFS64_LINTFLAGS
5939    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
5940#endif
5941#ifdef _CS_LFS_CFLAGS
5942    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
5943#endif
5944#ifdef _CS_LFS_LDFLAGS
5945    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
5946#endif
5947#ifdef _CS_LFS_LIBS
5948    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
5949#endif
5950#ifdef _CS_LFS_LINTFLAGS
5951    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
5952#endif
5953#ifdef _CS_MACHINE
5954    {"CS_MACHINE",      _CS_MACHINE},
5955#endif
5956#ifdef _CS_PATH
5957    {"CS_PATH", _CS_PATH},
5958#endif
5959#ifdef _CS_RELEASE
5960    {"CS_RELEASE",      _CS_RELEASE},
5961#endif
5962#ifdef _CS_SRPC_DOMAIN
5963    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
5964#endif
5965#ifdef _CS_SYSNAME
5966    {"CS_SYSNAME",      _CS_SYSNAME},
5967#endif
5968#ifdef _CS_VERSION
5969    {"CS_VERSION",      _CS_VERSION},
5970#endif
5971#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
5972    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
5973#endif
5974#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
5975    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
5976#endif
5977#ifdef _CS_XBS5_ILP32_OFF32_LIBS
5978    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
5979#endif
5980#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
5981    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
5982#endif
5983#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
5984    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
5985#endif
5986#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
5987    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
5988#endif
5989#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
5990    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
5991#endif
5992#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
5993    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
5994#endif
5995#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
5996    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
5997#endif
5998#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
5999    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
6000#endif
6001#ifdef _CS_XBS5_LP64_OFF64_LIBS
6002    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
6003#endif
6004#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
6005    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
6006#endif
6007#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
6008    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
6009#endif
6010#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
6011    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
6012#endif
6013#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
6014    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
6015#endif
6016#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
6017    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
6018#endif
6019#ifdef _MIPS_CS_AVAIL_PROCESSORS
6020    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
6021#endif
6022#ifdef _MIPS_CS_BASE
6023    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
6024#endif
6025#ifdef _MIPS_CS_HOSTID
6026    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
6027#endif
6028#ifdef _MIPS_CS_HW_NAME
6029    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
6030#endif
6031#ifdef _MIPS_CS_NUM_PROCESSORS
6032    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
6033#endif
6034#ifdef _MIPS_CS_OSREL_MAJ
6035    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
6036#endif
6037#ifdef _MIPS_CS_OSREL_MIN
6038    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
6039#endif
6040#ifdef _MIPS_CS_OSREL_PATCH
6041    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
6042#endif
6043#ifdef _MIPS_CS_OS_NAME
6044    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
6045#endif
6046#ifdef _MIPS_CS_OS_PROVIDER
6047    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
6048#endif
6049#ifdef _MIPS_CS_PROCESSORS
6050    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
6051#endif
6052#ifdef _MIPS_CS_SERIAL
6053    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
6054#endif
6055#ifdef _MIPS_CS_VENDOR
6056    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
6057#endif
6058};
6059
6060static int
6061conv_confstr_confname(PyObject *arg, int *valuep)
6062{
6063    return conv_confname(arg, valuep, posix_constants_confstr,
6064                         sizeof(posix_constants_confstr)
6065                           / sizeof(struct constdef));
6066}
6067
6068PyDoc_STRVAR(posix_confstr__doc__,
6069"confstr(name) -> string\n\n\
6070Return a string-valued system configuration variable.");
6071
6072static PyObject *
6073posix_confstr(PyObject *self, PyObject *args)
6074{
6075    PyObject *result = NULL;
6076    int name;
6077    char buffer[256];
6078
6079    if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) {
6080    int len;
6081
6082    errno = 0;
6083    len = confstr(name, buffer, sizeof(buffer));
6084    if (len == 0) {
6085        if (errno) {
6086        posix_error();
6087        }
6088        else {
6089        result = Py_None;
6090        Py_INCREF(Py_None);
6091        }
6092    }
6093    else {
6094        if ((unsigned int)len >= sizeof(buffer)) {
6095        result = PyString_FromStringAndSize(NULL, len-1);
6096        if (result != NULL)
6097            confstr(name, PyString_AS_STRING(result), len);
6098        }
6099        else
6100        result = PyString_FromStringAndSize(buffer, len-1);
6101    }
6102    }
6103    return result;
6104}
6105#endif
6106
6107
6108#ifdef HAVE_SYSCONF
6109static struct constdef posix_constants_sysconf[] = {
6110#ifdef _SC_2_CHAR_TERM
6111    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
6112#endif
6113#ifdef _SC_2_C_BIND
6114    {"SC_2_C_BIND",     _SC_2_C_BIND},
6115#endif
6116#ifdef _SC_2_C_DEV
6117    {"SC_2_C_DEV",      _SC_2_C_DEV},
6118#endif
6119#ifdef _SC_2_C_VERSION
6120    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
6121#endif
6122#ifdef _SC_2_FORT_DEV
6123    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
6124#endif
6125#ifdef _SC_2_FORT_RUN
6126    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
6127#endif
6128#ifdef _SC_2_LOCALEDEF
6129    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
6130#endif
6131#ifdef _SC_2_SW_DEV
6132    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
6133#endif
6134#ifdef _SC_2_UPE
6135    {"SC_2_UPE",        _SC_2_UPE},
6136#endif
6137#ifdef _SC_2_VERSION
6138    {"SC_2_VERSION",    _SC_2_VERSION},
6139#endif
6140#ifdef _SC_ABI_ASYNCHRONOUS_IO
6141    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
6142#endif
6143#ifdef _SC_ACL
6144    {"SC_ACL",  _SC_ACL},
6145#endif
6146#ifdef _SC_AIO_LISTIO_MAX
6147    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
6148#endif
6149#ifdef _SC_AIO_MAX
6150    {"SC_AIO_MAX",      _SC_AIO_MAX},
6151#endif
6152#ifdef _SC_AIO_PRIO_DELTA_MAX
6153    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
6154#endif
6155#ifdef _SC_ARG_MAX
6156    {"SC_ARG_MAX",      _SC_ARG_MAX},
6157#endif
6158#ifdef _SC_ASYNCHRONOUS_IO
6159    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
6160#endif
6161#ifdef _SC_ATEXIT_MAX
6162    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
6163#endif
6164#ifdef _SC_AUDIT
6165    {"SC_AUDIT",        _SC_AUDIT},
6166#endif
6167#ifdef _SC_AVPHYS_PAGES
6168    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
6169#endif
6170#ifdef _SC_BC_BASE_MAX
6171    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
6172#endif
6173#ifdef _SC_BC_DIM_MAX
6174    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
6175#endif
6176#ifdef _SC_BC_SCALE_MAX
6177    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
6178#endif
6179#ifdef _SC_BC_STRING_MAX
6180    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
6181#endif
6182#ifdef _SC_CAP
6183    {"SC_CAP",  _SC_CAP},
6184#endif
6185#ifdef _SC_CHARCLASS_NAME_MAX
6186    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
6187#endif
6188#ifdef _SC_CHAR_BIT
6189    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
6190#endif
6191#ifdef _SC_CHAR_MAX
6192    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
6193#endif
6194#ifdef _SC_CHAR_MIN
6195    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
6196#endif
6197#ifdef _SC_CHILD_MAX
6198    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
6199#endif
6200#ifdef _SC_CLK_TCK
6201    {"SC_CLK_TCK",      _SC_CLK_TCK},
6202#endif
6203#ifdef _SC_COHER_BLKSZ
6204    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
6205#endif
6206#ifdef _SC_COLL_WEIGHTS_MAX
6207    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
6208#endif
6209#ifdef _SC_DCACHE_ASSOC
6210    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
6211#endif
6212#ifdef _SC_DCACHE_BLKSZ
6213    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
6214#endif
6215#ifdef _SC_DCACHE_LINESZ
6216    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
6217#endif
6218#ifdef _SC_DCACHE_SZ
6219    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
6220#endif
6221#ifdef _SC_DCACHE_TBLKSZ
6222    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
6223#endif
6224#ifdef _SC_DELAYTIMER_MAX
6225    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
6226#endif
6227#ifdef _SC_EQUIV_CLASS_MAX
6228    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
6229#endif
6230#ifdef _SC_EXPR_NEST_MAX
6231    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
6232#endif
6233#ifdef _SC_FSYNC
6234    {"SC_FSYNC",        _SC_FSYNC},
6235#endif
6236#ifdef _SC_GETGR_R_SIZE_MAX
6237    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
6238#endif
6239#ifdef _SC_GETPW_R_SIZE_MAX
6240    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
6241#endif
6242#ifdef _SC_ICACHE_ASSOC
6243    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
6244#endif
6245#ifdef _SC_ICACHE_BLKSZ
6246    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
6247#endif
6248#ifdef _SC_ICACHE_LINESZ
6249    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
6250#endif
6251#ifdef _SC_ICACHE_SZ
6252    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
6253#endif
6254#ifdef _SC_INF
6255    {"SC_INF",  _SC_INF},
6256#endif
6257#ifdef _SC_INT_MAX
6258    {"SC_INT_MAX",      _SC_INT_MAX},
6259#endif
6260#ifdef _SC_INT_MIN
6261    {"SC_INT_MIN",      _SC_INT_MIN},
6262#endif
6263#ifdef _SC_IOV_MAX
6264    {"SC_IOV_MAX",      _SC_IOV_MAX},
6265#endif
6266#ifdef _SC_IP_SECOPTS
6267    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
6268#endif
6269#ifdef _SC_JOB_CONTROL
6270    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
6271#endif
6272#ifdef _SC_KERN_POINTERS
6273    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
6274#endif
6275#ifdef _SC_KERN_SIM
6276    {"SC_KERN_SIM",     _SC_KERN_SIM},
6277#endif
6278#ifdef _SC_LINE_MAX
6279    {"SC_LINE_MAX",     _SC_LINE_MAX},
6280#endif
6281#ifdef _SC_LOGIN_NAME_MAX
6282    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
6283#endif
6284#ifdef _SC_LOGNAME_MAX
6285    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
6286#endif
6287#ifdef _SC_LONG_BIT
6288    {"SC_LONG_BIT",     _SC_LONG_BIT},
6289#endif
6290#ifdef _SC_MAC
6291    {"SC_MAC",  _SC_MAC},
6292#endif
6293#ifdef _SC_MAPPED_FILES
6294    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
6295#endif
6296#ifdef _SC_MAXPID
6297    {"SC_MAXPID",       _SC_MAXPID},
6298#endif
6299#ifdef _SC_MB_LEN_MAX
6300    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
6301#endif
6302#ifdef _SC_MEMLOCK
6303    {"SC_MEMLOCK",      _SC_MEMLOCK},
6304#endif
6305#ifdef _SC_MEMLOCK_RANGE
6306    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
6307#endif
6308#ifdef _SC_MEMORY_PROTECTION
6309    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
6310#endif
6311#ifdef _SC_MESSAGE_PASSING
6312    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
6313#endif
6314#ifdef _SC_MMAP_FIXED_ALIGNMENT
6315    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
6316#endif
6317#ifdef _SC_MQ_OPEN_MAX
6318    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
6319#endif
6320#ifdef _SC_MQ_PRIO_MAX
6321    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
6322#endif
6323#ifdef _SC_NACLS_MAX
6324    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
6325#endif
6326#ifdef _SC_NGROUPS_MAX
6327    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
6328#endif
6329#ifdef _SC_NL_ARGMAX
6330    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
6331#endif
6332#ifdef _SC_NL_LANGMAX
6333    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
6334#endif
6335#ifdef _SC_NL_MSGMAX
6336    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
6337#endif
6338#ifdef _SC_NL_NMAX
6339    {"SC_NL_NMAX",      _SC_NL_NMAX},
6340#endif
6341#ifdef _SC_NL_SETMAX
6342    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
6343#endif
6344#ifdef _SC_NL_TEXTMAX
6345    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
6346#endif
6347#ifdef _SC_NPROCESSORS_CONF
6348    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
6349#endif
6350#ifdef _SC_NPROCESSORS_ONLN
6351    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
6352#endif
6353#ifdef _SC_NPROC_CONF
6354    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
6355#endif
6356#ifdef _SC_NPROC_ONLN
6357    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
6358#endif
6359#ifdef _SC_NZERO
6360    {"SC_NZERO",        _SC_NZERO},
6361#endif
6362#ifdef _SC_OPEN_MAX
6363    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
6364#endif
6365#ifdef _SC_PAGESIZE
6366    {"SC_PAGESIZE",     _SC_PAGESIZE},
6367#endif
6368#ifdef _SC_PAGE_SIZE
6369    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
6370#endif
6371#ifdef _SC_PASS_MAX
6372    {"SC_PASS_MAX",     _SC_PASS_MAX},
6373#endif
6374#ifdef _SC_PHYS_PAGES
6375    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
6376#endif
6377#ifdef _SC_PII
6378    {"SC_PII",  _SC_PII},
6379#endif
6380#ifdef _SC_PII_INTERNET
6381    {"SC_PII_INTERNET", _SC_PII_INTERNET},
6382#endif
6383#ifdef _SC_PII_INTERNET_DGRAM
6384    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
6385#endif
6386#ifdef _SC_PII_INTERNET_STREAM
6387    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
6388#endif
6389#ifdef _SC_PII_OSI
6390    {"SC_PII_OSI",      _SC_PII_OSI},
6391#endif
6392#ifdef _SC_PII_OSI_CLTS
6393    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
6394#endif
6395#ifdef _SC_PII_OSI_COTS
6396    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
6397#endif
6398#ifdef _SC_PII_OSI_M
6399    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
6400#endif
6401#ifdef _SC_PII_SOCKET
6402    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
6403#endif
6404#ifdef _SC_PII_XTI
6405    {"SC_PII_XTI",      _SC_PII_XTI},
6406#endif
6407#ifdef _SC_POLL
6408    {"SC_POLL", _SC_POLL},
6409#endif
6410#ifdef _SC_PRIORITIZED_IO
6411    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
6412#endif
6413#ifdef _SC_PRIORITY_SCHEDULING
6414    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
6415#endif
6416#ifdef _SC_REALTIME_SIGNALS
6417    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
6418#endif
6419#ifdef _SC_RE_DUP_MAX
6420    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
6421#endif
6422#ifdef _SC_RTSIG_MAX
6423    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
6424#endif
6425#ifdef _SC_SAVED_IDS
6426    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
6427#endif
6428#ifdef _SC_SCHAR_MAX
6429    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
6430#endif
6431#ifdef _SC_SCHAR_MIN
6432    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
6433#endif
6434#ifdef _SC_SELECT
6435    {"SC_SELECT",       _SC_SELECT},
6436#endif
6437#ifdef _SC_SEMAPHORES
6438    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
6439#endif
6440#ifdef _SC_SEM_NSEMS_MAX
6441    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
6442#endif
6443#ifdef _SC_SEM_VALUE_MAX
6444    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
6445#endif
6446#ifdef _SC_SHARED_MEMORY_OBJECTS
6447    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
6448#endif
6449#ifdef _SC_SHRT_MAX
6450    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
6451#endif
6452#ifdef _SC_SHRT_MIN
6453    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
6454#endif
6455#ifdef _SC_SIGQUEUE_MAX
6456    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
6457#endif
6458#ifdef _SC_SIGRT_MAX
6459    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
6460#endif
6461#ifdef _SC_SIGRT_MIN
6462    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
6463#endif
6464#ifdef _SC_SOFTPOWER
6465    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
6466#endif
6467#ifdef _SC_SPLIT_CACHE
6468    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
6469#endif
6470#ifdef _SC_SSIZE_MAX
6471    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
6472#endif
6473#ifdef _SC_STACK_PROT
6474    {"SC_STACK_PROT",   _SC_STACK_PROT},
6475#endif
6476#ifdef _SC_STREAM_MAX
6477    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
6478#endif
6479#ifdef _SC_SYNCHRONIZED_IO
6480    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
6481#endif
6482#ifdef _SC_THREADS
6483    {"SC_THREADS",      _SC_THREADS},
6484#endif
6485#ifdef _SC_THREAD_ATTR_STACKADDR
6486    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
6487#endif
6488#ifdef _SC_THREAD_ATTR_STACKSIZE
6489    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
6490#endif
6491#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
6492    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
6493#endif
6494#ifdef _SC_THREAD_KEYS_MAX
6495    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
6496#endif
6497#ifdef _SC_THREAD_PRIORITY_SCHEDULING
6498    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
6499#endif
6500#ifdef _SC_THREAD_PRIO_INHERIT
6501    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
6502#endif
6503#ifdef _SC_THREAD_PRIO_PROTECT
6504    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
6505#endif
6506#ifdef _SC_THREAD_PROCESS_SHARED
6507    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
6508#endif
6509#ifdef _SC_THREAD_SAFE_FUNCTIONS
6510    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
6511#endif
6512#ifdef _SC_THREAD_STACK_MIN
6513    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
6514#endif
6515#ifdef _SC_THREAD_THREADS_MAX
6516    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
6517#endif
6518#ifdef _SC_TIMERS
6519    {"SC_TIMERS",       _SC_TIMERS},
6520#endif
6521#ifdef _SC_TIMER_MAX
6522    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
6523#endif
6524#ifdef _SC_TTY_NAME_MAX
6525    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
6526#endif
6527#ifdef _SC_TZNAME_MAX
6528    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
6529#endif
6530#ifdef _SC_T_IOV_MAX
6531    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
6532#endif
6533#ifdef _SC_UCHAR_MAX
6534    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
6535#endif
6536#ifdef _SC_UINT_MAX
6537    {"SC_UINT_MAX",     _SC_UINT_MAX},
6538#endif
6539#ifdef _SC_UIO_MAXIOV
6540    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
6541#endif
6542#ifdef _SC_ULONG_MAX
6543    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
6544#endif
6545#ifdef _SC_USHRT_MAX
6546    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
6547#endif
6548#ifdef _SC_VERSION
6549    {"SC_VERSION",      _SC_VERSION},
6550#endif
6551#ifdef _SC_WORD_BIT
6552    {"SC_WORD_BIT",     _SC_WORD_BIT},
6553#endif
6554#ifdef _SC_XBS5_ILP32_OFF32
6555    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
6556#endif
6557#ifdef _SC_XBS5_ILP32_OFFBIG
6558    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
6559#endif
6560#ifdef _SC_XBS5_LP64_OFF64
6561    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
6562#endif
6563#ifdef _SC_XBS5_LPBIG_OFFBIG
6564    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
6565#endif
6566#ifdef _SC_XOPEN_CRYPT
6567    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
6568#endif
6569#ifdef _SC_XOPEN_ENH_I18N
6570    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
6571#endif
6572#ifdef _SC_XOPEN_LEGACY
6573    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
6574#endif
6575#ifdef _SC_XOPEN_REALTIME
6576    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
6577#endif
6578#ifdef _SC_XOPEN_REALTIME_THREADS
6579    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
6580#endif
6581#ifdef _SC_XOPEN_SHM
6582    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
6583#endif
6584#ifdef _SC_XOPEN_UNIX
6585    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
6586#endif
6587#ifdef _SC_XOPEN_VERSION
6588    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
6589#endif
6590#ifdef _SC_XOPEN_XCU_VERSION
6591    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
6592#endif
6593#ifdef _SC_XOPEN_XPG2
6594    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
6595#endif
6596#ifdef _SC_XOPEN_XPG3
6597    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
6598#endif
6599#ifdef _SC_XOPEN_XPG4
6600    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
6601#endif
6602};
6603
6604static int
6605conv_sysconf_confname(PyObject *arg, int *valuep)
6606{
6607    return conv_confname(arg, valuep, posix_constants_sysconf,
6608                         sizeof(posix_constants_sysconf)
6609                           / sizeof(struct constdef));
6610}
6611
6612PyDoc_STRVAR(posix_sysconf__doc__,
6613"sysconf(name) -> integer\n\n\
6614Return an integer-valued system configuration variable.");
6615
6616static PyObject *
6617posix_sysconf(PyObject *self, PyObject *args)
6618{
6619    PyObject *result = NULL;
6620    int name;
6621
6622    if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
6623        int value;
6624
6625        errno = 0;
6626        value = sysconf(name);
6627        if (value == -1 && errno != 0)
6628            posix_error();
6629        else
6630            result = PyInt_FromLong(value);
6631    }
6632    return result;
6633}
6634#endif
6635
6636
6637#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) || defined(HAVE_CONFSTR) || defined(HAVE_SYSCONF)
6638/* This code is used to ensure that the tables of configuration value names
6639 * are in sorted order as required by conv_confname(), and also to build the
6640 * the exported dictionaries that are used to publish information about the
6641 * names available on the host platform.
6642 *
6643 * Sorting the table at runtime ensures that the table is properly ordered
6644 * when used, even for platforms we're not able to test on.  It also makes
6645 * it easier to add additional entries to the tables.
6646 */
6647
6648static int
6649cmp_constdefs(const void *v1,  const void *v2)
6650{
6651    const struct constdef *c1 =
6652    (const struct constdef *) v1;
6653    const struct constdef *c2 =
6654    (const struct constdef *) v2;
6655
6656    return strcmp(c1->name, c2->name);
6657}
6658
6659static int
6660setup_confname_table(struct constdef *table, size_t tablesize,
6661                     char *tablename, PyObject *module)
6662{
6663    PyObject *d = NULL;
6664    size_t i;
6665
6666    qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
6667    d = PyDict_New();
6668    if (d == NULL)
6669        return -1;
6670
6671    for (i=0; i < tablesize; ++i) {
6672        PyObject *o = PyInt_FromLong(table[i].value);
6673        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
6674            Py_XDECREF(o);
6675            Py_DECREF(d);
6676            return -1;
6677        }
6678        Py_DECREF(o);
6679    }
6680    return PyModule_AddObject(module, tablename, d);
6681}
6682#endif  /* HAVE_FPATHCONF || HAVE_PATHCONF || HAVE_CONFSTR || HAVE_SYSCONF */
6683
6684/* Return -1 on failure, 0 on success. */
6685static int
6686setup_confname_tables(PyObject *module)
6687{
6688#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
6689    if (setup_confname_table(posix_constants_pathconf,
6690                             sizeof(posix_constants_pathconf)
6691                               / sizeof(struct constdef),
6692                             "pathconf_names", module))
6693        return -1;
6694#endif
6695#ifdef HAVE_CONFSTR
6696    if (setup_confname_table(posix_constants_confstr,
6697                             sizeof(posix_constants_confstr)
6698                               / sizeof(struct constdef),
6699                             "confstr_names", module))
6700        return -1;
6701#endif
6702#ifdef HAVE_SYSCONF
6703    if (setup_confname_table(posix_constants_sysconf,
6704                             sizeof(posix_constants_sysconf)
6705                               / sizeof(struct constdef),
6706                             "sysconf_names", module))
6707        return -1;
6708#endif
6709    return 0;
6710}
6711
6712
6713PyDoc_STRVAR(posix_abort__doc__,
6714"abort() -> does not return!\n\n\
6715Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
6716in the hardest way possible on the hosting operating system.");
6717
6718static PyObject *
6719posix_abort(PyObject *self, PyObject *noargs)
6720{
6721    abort();
6722    /*NOTREACHED*/
6723    Py_FatalError("abort() called from Python code didn't abort!");
6724    return NULL;
6725}
6726
6727#ifdef HAVE_SETRESUID
6728PyDoc_STRVAR(posix_setresuid__doc__,
6729"setresuid(ruid, euid, suid)\n\n\
6730Set the current process's real, effective, and saved user ids.");
6731
6732static PyObject*
6733posix_setresuid (PyObject *self, PyObject *args)
6734{
6735    /* We assume uid_t is no larger than a long. */
6736    long ruid, euid, suid;
6737    if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
6738        return NULL;
6739    if (setresuid(ruid, euid, suid) < 0)
6740        return posix_error();
6741    Py_RETURN_NONE;
6742}
6743#endif
6744
6745#ifdef HAVE_SETRESGID
6746PyDoc_STRVAR(posix_setresgid__doc__,
6747"setresgid(rgid, egid, sgid)\n\n\
6748Set the current process's real, effective, and saved group ids.");
6749
6750static PyObject*
6751posix_setresgid (PyObject *self, PyObject *args)
6752{
6753    /* We assume uid_t is no larger than a long. */
6754    long rgid, egid, sgid;
6755    if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
6756        return NULL;
6757    if (setresgid(rgid, egid, sgid) < 0)
6758        return posix_error();
6759    Py_RETURN_NONE;
6760}
6761#endif
6762
6763#ifdef HAVE_GETRESUID
6764PyDoc_STRVAR(posix_getresuid__doc__,
6765"getresuid() -> (ruid, euid, suid)\n\n\
6766Get tuple of the current process's real, effective, and saved user ids.");
6767
6768static PyObject*
6769posix_getresuid (PyObject *self, PyObject *noargs)
6770{
6771    uid_t ruid, euid, suid;
6772    long l_ruid, l_euid, l_suid;
6773    if (getresuid(&ruid, &euid, &suid) < 0)
6774        return posix_error();
6775    /* Force the values into long's as we don't know the size of uid_t. */
6776    l_ruid = ruid;
6777    l_euid = euid;
6778    l_suid = suid;
6779    return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
6780}
6781#endif
6782
6783#ifdef HAVE_GETRESGID
6784PyDoc_STRVAR(posix_getresgid__doc__,
6785"getresgid() -> (rgid, egid, sgid)\n\n\
6786Get tuple of the current process's real, effective, and saved group ids.");
6787
6788static PyObject*
6789posix_getresgid (PyObject *self, PyObject *noargs)
6790{
6791    uid_t rgid, egid, sgid;
6792    long l_rgid, l_egid, l_sgid;
6793    if (getresgid(&rgid, &egid, &sgid) < 0)
6794        return posix_error();
6795    /* Force the values into long's as we don't know the size of uid_t. */
6796    l_rgid = rgid;
6797    l_egid = egid;
6798    l_sgid = sgid;
6799    return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
6800}
6801#endif
6802
6803static PyMethodDef posix_methods[] = {
6804    {"access",          posix_access,     METH_VARARGS, posix_access__doc__},
6805#ifdef HAVE_TTYNAME
6806    {"ttyname",         posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
6807#endif
6808    {"chdir",           posix_chdir,      METH_VARARGS, posix_chdir__doc__},
6809#ifdef HAVE_CHFLAGS
6810    {"chflags",         posix_chflags, METH_VARARGS, posix_chflags__doc__},
6811#endif /* HAVE_CHFLAGS */
6812    {"chmod",           posix_chmod,      METH_VARARGS, posix_chmod__doc__},
6813#ifdef HAVE_FCHMOD
6814    {"fchmod",          posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
6815#endif /* HAVE_FCHMOD */
6816#ifdef HAVE_CHOWN
6817    {"chown",           posix_chown, METH_VARARGS, posix_chown__doc__},
6818#endif /* HAVE_CHOWN */
6819#ifdef HAVE_LCHMOD
6820    {"lchmod",          posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
6821#endif /* HAVE_LCHMOD */
6822#ifdef HAVE_FCHOWN
6823    {"fchown",          posix_fchown, METH_VARARGS, posix_fchown__doc__},
6824#endif /* HAVE_FCHOWN */
6825#ifdef HAVE_LCHFLAGS
6826    {"lchflags",        posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
6827#endif /* HAVE_LCHFLAGS */
6828#ifdef HAVE_LCHOWN
6829    {"lchown",          posix_lchown, METH_VARARGS, posix_lchown__doc__},
6830#endif /* HAVE_LCHOWN */
6831#ifdef HAVE_CHROOT
6832    {"chroot",          posix_chroot, METH_VARARGS, posix_chroot__doc__},
6833#endif
6834#ifdef HAVE_CTERMID
6835    {"ctermid",         posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
6836#endif
6837#ifdef HAVE_GETCWD
6838    {"getcwd",          posix_getcwd,     METH_NOARGS,  posix_getcwd__doc__},
6839#ifdef Py_USING_UNICODE
6840    {"getcwdu",         posix_getcwdu,    METH_NOARGS,  posix_getcwdu__doc__},
6841#endif
6842#endif
6843#ifdef HAVE_LINK
6844    {"link",            posix_link, METH_VARARGS, posix_link__doc__},
6845#endif /* HAVE_LINK */
6846    {"listdir",         posix_listdir,    METH_VARARGS, posix_listdir__doc__},
6847    {"lstat",           posix_lstat,      METH_VARARGS, posix_lstat__doc__},
6848    {"mkdir",           posix_mkdir,      METH_VARARGS, posix_mkdir__doc__},
6849#ifdef HAVE_NICE
6850    {"nice",            posix_nice, METH_VARARGS, posix_nice__doc__},
6851#endif /* HAVE_NICE */
6852#ifdef HAVE_READLINK
6853    {"readlink",        posix_readlink, METH_VARARGS, posix_readlink__doc__},
6854#endif /* HAVE_READLINK */
6855    {"rename",          posix_rename,     METH_VARARGS, posix_rename__doc__},
6856    {"rmdir",           posix_rmdir,      METH_VARARGS, posix_rmdir__doc__},
6857    {"stat",            posix_stat,       METH_VARARGS, posix_stat__doc__},
6858    //{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
6859#ifdef HAVE_SYMLINK
6860    {"symlink",         posix_symlink, METH_VARARGS, posix_symlink__doc__},
6861#endif /* HAVE_SYMLINK */
6862#ifdef HAVE_SYSTEM
6863    {"system",          posix_system, METH_VARARGS, posix_system__doc__},
6864#endif
6865    {"umask",           posix_umask,      METH_VARARGS, posix_umask__doc__},
6866#ifdef HAVE_UNAME
6867    {"uname",           posix_uname, METH_NOARGS, posix_uname__doc__},
6868#endif /* HAVE_UNAME */
6869    {"unlink",          posix_unlink,     METH_VARARGS, posix_unlink__doc__},
6870    {"remove",          posix_unlink,     METH_VARARGS, posix_remove__doc__},
6871    {"utime",           posix_utime,      METH_VARARGS, posix_utime__doc__},
6872#ifdef HAVE_TIMES
6873    {"times",           posix_times, METH_NOARGS, posix_times__doc__},
6874#endif /* HAVE_TIMES */
6875    {"_exit",           posix__exit,      METH_VARARGS, posix__exit__doc__},
6876#ifdef HAVE_EXECV
6877    {"execv",           posix_execv, METH_VARARGS, posix_execv__doc__},
6878    {"execve",          posix_execve, METH_VARARGS, posix_execve__doc__},
6879#endif /* HAVE_EXECV */
6880#ifdef HAVE_SPAWNV
6881    {"spawnv",          posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
6882    {"spawnve",         posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
6883#if defined(PYOS_OS2)
6884    {"spawnvp",         posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
6885    {"spawnvpe",        posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
6886#endif /* PYOS_OS2 */
6887#endif /* HAVE_SPAWNV */
6888#ifdef HAVE_FORK1
6889    {"fork1",       posix_fork1, METH_NOARGS, posix_fork1__doc__},
6890#endif /* HAVE_FORK1 */
6891#ifdef HAVE_FORK
6892    {"fork",            posix_fork, METH_NOARGS, posix_fork__doc__},
6893#endif /* HAVE_FORK */
6894#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
6895    {"openpty",         posix_openpty, METH_NOARGS, posix_openpty__doc__},
6896#endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
6897#ifdef HAVE_FORKPTY
6898    {"forkpty",         posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
6899#endif /* HAVE_FORKPTY */
6900#ifdef HAVE_GETEGID
6901    {"getegid",         posix_getegid, METH_NOARGS, posix_getegid__doc__},
6902#endif /* HAVE_GETEGID */
6903#ifdef HAVE_GETEUID
6904    {"geteuid",         posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
6905#endif /* HAVE_GETEUID */
6906#ifdef HAVE_GETGID
6907    {"getgid",          posix_getgid, METH_NOARGS, posix_getgid__doc__},
6908#endif /* HAVE_GETGID */
6909#ifdef HAVE_GETGROUPS
6910    {"getgroups",       posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
6911#endif
6912    {"getpid",          posix_getpid,     METH_NOARGS,  posix_getpid__doc__},
6913#ifdef HAVE_GETPGRP
6914    {"getpgrp",         posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
6915#endif /* HAVE_GETPGRP */
6916#ifdef HAVE_GETPPID
6917    {"getppid",         posix_getppid, METH_NOARGS, posix_getppid__doc__},
6918#endif /* HAVE_GETPPID */
6919#ifdef HAVE_GETUID
6920    {"getuid",          posix_getuid, METH_NOARGS, posix_getuid__doc__},
6921#endif /* HAVE_GETUID */
6922#ifdef HAVE_GETLOGIN
6923    {"getlogin",        posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
6924#endif
6925#ifdef HAVE_KILL
6926    {"kill",            posix_kill, METH_VARARGS, posix_kill__doc__},
6927#endif /* HAVE_KILL */
6928#ifdef HAVE_KILLPG
6929    {"killpg",          posix_killpg, METH_VARARGS, posix_killpg__doc__},
6930#endif /* HAVE_KILLPG */
6931#ifdef HAVE_PLOCK
6932    {"plock",           posix_plock, METH_VARARGS, posix_plock__doc__},
6933#endif /* HAVE_PLOCK */
6934#ifdef HAVE_POPEN
6935    {"popen",           posix_popen, METH_VARARGS, posix_popen__doc__},
6936#ifdef MS_WINDOWS
6937    {"popen2",          win32_popen2, METH_VARARGS},
6938    {"popen3",          win32_popen3, METH_VARARGS},
6939    {"popen4",          win32_popen4, METH_VARARGS},
6940    {"startfile",       win32_startfile, METH_VARARGS, win32_startfile__doc__},
6941    {"kill",    win32_kill, METH_VARARGS, win32_kill__doc__},
6942#else
6943#if defined(PYOS_OS2) && defined(PYCC_GCC)
6944    {"popen2",          os2emx_popen2, METH_VARARGS},
6945    {"popen3",          os2emx_popen3, METH_VARARGS},
6946    {"popen4",          os2emx_popen4, METH_VARARGS},
6947#endif
6948#endif
6949#endif /* HAVE_POPEN */
6950#ifdef HAVE_SETUID
6951    {"setuid",          posix_setuid, METH_VARARGS, posix_setuid__doc__},
6952#endif /* HAVE_SETUID */
6953#ifdef HAVE_SETEUID
6954    {"seteuid",         posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
6955#endif /* HAVE_SETEUID */
6956#ifdef HAVE_SETEGID
6957    {"setegid",         posix_setegid, METH_VARARGS, posix_setegid__doc__},
6958#endif /* HAVE_SETEGID */
6959#ifdef HAVE_SETREUID
6960    {"setreuid",        posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
6961#endif /* HAVE_SETREUID */
6962#ifdef HAVE_SETREGID
6963    {"setregid",        posix_setregid, METH_VARARGS, posix_setregid__doc__},
6964#endif /* HAVE_SETREGID */
6965#ifdef HAVE_SETGID
6966    {"setgid",          posix_setgid, METH_VARARGS, posix_setgid__doc__},
6967#endif /* HAVE_SETGID */
6968#ifdef HAVE_SETGROUPS
6969    {"setgroups",       posix_setgroups, METH_O, posix_setgroups__doc__},
6970#endif /* HAVE_SETGROUPS */
6971#ifdef HAVE_INITGROUPS
6972    {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
6973#endif /* HAVE_INITGROUPS */
6974#ifdef HAVE_GETPGID
6975    {"getpgid",         posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
6976#endif /* HAVE_GETPGID */
6977#ifdef HAVE_SETPGRP
6978    {"setpgrp",         posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
6979#endif /* HAVE_SETPGRP */
6980#ifdef HAVE_WAIT
6981    {"wait",            posix_wait, METH_NOARGS, posix_wait__doc__},
6982#endif /* HAVE_WAIT */
6983#ifdef HAVE_WAIT3
6984    {"wait3",           posix_wait3, METH_VARARGS, posix_wait3__doc__},
6985#endif /* HAVE_WAIT3 */
6986#ifdef HAVE_WAIT4
6987    {"wait4",           posix_wait4, METH_VARARGS, posix_wait4__doc__},
6988#endif /* HAVE_WAIT4 */
6989#if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
6990    {"waitpid",         posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
6991#endif /* HAVE_WAITPID */
6992#ifdef HAVE_GETSID
6993    {"getsid",          posix_getsid, METH_VARARGS, posix_getsid__doc__},
6994#endif /* HAVE_GETSID */
6995#ifdef HAVE_SETSID
6996    {"setsid",          posix_setsid, METH_NOARGS, posix_setsid__doc__},
6997#endif /* HAVE_SETSID */
6998#ifdef HAVE_SETPGID
6999    {"setpgid",         posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
7000#endif /* HAVE_SETPGID */
7001#ifdef HAVE_TCGETPGRP
7002    {"tcgetpgrp",       posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
7003#endif /* HAVE_TCGETPGRP */
7004#ifdef HAVE_TCSETPGRP
7005    {"tcsetpgrp",       posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
7006#endif /* HAVE_TCSETPGRP */
7007    {"open",            posix_open,       METH_VARARGS, posix_open__doc__},
7008    {"close",           posix_close,      METH_VARARGS, posix_close__doc__},
7009    {"closerange",      posix_closerange, METH_VARARGS, posix_closerange__doc__},
7010    {"dup",             posix_dup,        METH_VARARGS, posix_dup__doc__},
7011    {"dup2",            posix_dup2,       METH_VARARGS, posix_dup2__doc__},
7012    {"lseek",           posix_lseek,      METH_VARARGS, posix_lseek__doc__},
7013    {"read",            posix_read,       METH_VARARGS, posix_read__doc__},
7014    {"write",           posix_write,      METH_VARARGS, posix_write__doc__},
7015    {"fstat",           posix_fstat,      METH_VARARGS, posix_fstat__doc__},
7016    {"fdopen",          posix_fdopen,     METH_VARARGS, posix_fdopen__doc__},
7017    {"isatty",          posix_isatty,     METH_VARARGS, posix_isatty__doc__},
7018#ifdef HAVE_PIPE
7019    {"pipe",            posix_pipe, METH_NOARGS, posix_pipe__doc__},
7020#endif
7021#ifdef HAVE_MKFIFO
7022    {"mkfifo",          posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
7023#endif
7024#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
7025    {"mknod",           posix_mknod, METH_VARARGS, posix_mknod__doc__},
7026#endif
7027#ifdef HAVE_DEVICE_MACROS
7028    {"major",           posix_major, METH_VARARGS, posix_major__doc__},
7029    {"minor",           posix_minor, METH_VARARGS, posix_minor__doc__},
7030    {"makedev",         posix_makedev, METH_VARARGS, posix_makedev__doc__},
7031#endif
7032#ifdef HAVE_FTRUNCATE
7033    {"ftruncate",       posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
7034#endif
7035#ifdef HAVE_PUTENV
7036    {"putenv",          posix_putenv, METH_VARARGS, posix_putenv__doc__},
7037#endif
7038#ifdef HAVE_UNSETENV
7039    {"unsetenv",        posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
7040#endif
7041    {"strerror",        posix_strerror,   METH_VARARGS, posix_strerror__doc__},
7042#ifdef HAVE_FCHDIR
7043    {"fchdir",          posix_fchdir, METH_O, posix_fchdir__doc__},
7044#endif
7045#ifdef HAVE_FSYNC
7046    {"fsync",       posix_fsync, METH_O, posix_fsync__doc__},
7047#endif
7048#ifdef HAVE_FDATASYNC
7049    {"fdatasync",   posix_fdatasync,  METH_O, posix_fdatasync__doc__},
7050#endif
7051#ifdef HAVE_SYS_WAIT_H
7052#ifdef WCOREDUMP
7053    {"WCOREDUMP",       posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
7054#endif /* WCOREDUMP */
7055#ifdef WIFCONTINUED
7056    {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
7057#endif /* WIFCONTINUED */
7058#ifdef WIFSTOPPED
7059    {"WIFSTOPPED",      posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
7060#endif /* WIFSTOPPED */
7061#ifdef WIFSIGNALED
7062    {"WIFSIGNALED",     posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
7063#endif /* WIFSIGNALED */
7064#ifdef WIFEXITED
7065    {"WIFEXITED",       posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
7066#endif /* WIFEXITED */
7067#ifdef WEXITSTATUS
7068    {"WEXITSTATUS",     posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
7069#endif /* WEXITSTATUS */
7070#ifdef WTERMSIG
7071    {"WTERMSIG",        posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
7072#endif /* WTERMSIG */
7073#ifdef WSTOPSIG
7074    {"WSTOPSIG",        posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
7075#endif /* WSTOPSIG */
7076#endif /* HAVE_SYS_WAIT_H */
7077#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
7078    {"fstatvfs",        posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
7079#endif
7080#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
7081    {"statvfs",         posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
7082#endif
7083#ifdef HAVE_TMPFILE
7084    {"tmpfile",         posix_tmpfile,    METH_NOARGS,  posix_tmpfile__doc__},
7085#endif
7086#ifdef HAVE_TEMPNAM
7087    {"tempnam",         posix_tempnam,    METH_VARARGS, posix_tempnam__doc__},
7088#endif
7089#ifdef HAVE_TMPNAM
7090    {"tmpnam",          posix_tmpnam,     METH_NOARGS,  posix_tmpnam__doc__},
7091#endif
7092#ifdef HAVE_CONFSTR
7093    {"confstr",         posix_confstr, METH_VARARGS, posix_confstr__doc__},
7094#endif
7095#ifdef HAVE_SYSCONF
7096    {"sysconf",         posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
7097#endif
7098#ifdef HAVE_FPATHCONF
7099    {"fpathconf",       posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
7100#endif
7101#ifdef HAVE_PATHCONF
7102    {"pathconf",        posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
7103#endif
7104    {"abort",           posix_abort,      METH_NOARGS,  posix_abort__doc__},
7105#ifdef HAVE_SETRESUID
7106    {"setresuid",       posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
7107#endif
7108#ifdef HAVE_SETRESGID
7109    {"setresgid",       posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
7110#endif
7111#ifdef HAVE_GETRESUID
7112    {"getresuid",       posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
7113#endif
7114#ifdef HAVE_GETRESGID
7115    {"getresgid",       posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
7116#endif
7117
7118    {NULL,              NULL}            /* Sentinel */
7119};
7120
7121
7122static int
7123ins(PyObject *module, char *symbol, long value)
7124{
7125    return PyModule_AddIntConstant(module, symbol, value);
7126}
7127
7128static int
7129all_ins(PyObject *d)
7130{
7131#ifdef F_OK
7132    if (ins(d, "F_OK", (long)F_OK)) return -1;
7133#endif
7134#ifdef R_OK
7135    if (ins(d, "R_OK", (long)R_OK)) return -1;
7136#endif
7137#ifdef W_OK
7138    if (ins(d, "W_OK", (long)W_OK)) return -1;
7139#endif
7140#ifdef X_OK
7141    if (ins(d, "X_OK", (long)X_OK)) return -1;
7142#endif
7143#ifdef NGROUPS_MAX
7144    if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
7145#endif
7146#ifdef TMP_MAX
7147    if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
7148#endif
7149#ifdef WCONTINUED
7150    if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
7151#endif
7152#ifdef WNOHANG
7153    if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
7154#endif
7155#ifdef WUNTRACED
7156    if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
7157#endif
7158#ifdef O_RDONLY
7159    if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
7160#endif
7161#ifdef O_WRONLY
7162    if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
7163#endif
7164#ifdef O_RDWR
7165    if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
7166#endif
7167#ifdef O_NDELAY
7168    if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
7169#endif
7170#ifdef O_NONBLOCK
7171    if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
7172#endif
7173#ifdef O_APPEND
7174    if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
7175#endif
7176#ifdef O_DSYNC
7177    if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
7178#endif
7179#ifdef O_RSYNC
7180    if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
7181#endif
7182#ifdef O_SYNC
7183    if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
7184#endif
7185#ifdef O_NOCTTY
7186    if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
7187#endif
7188#ifdef O_CREAT
7189    if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
7190#endif
7191#ifdef O_EXCL
7192    if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
7193#endif
7194#ifdef O_TRUNC
7195    if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
7196#endif
7197#ifdef O_BINARY
7198    if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
7199#endif
7200#ifdef O_TEXT
7201    if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
7202#endif
7203#ifdef O_LARGEFILE
7204    if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
7205#endif
7206#ifdef O_SHLOCK
7207    if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
7208#endif
7209#ifdef O_EXLOCK
7210    if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
7211#endif
7212
7213/* MS Windows */
7214#ifdef O_NOINHERIT
7215    /* Don't inherit in child processes. */
7216    if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
7217#endif
7218#ifdef _O_SHORT_LIVED
7219    /* Optimize for short life (keep in memory). */
7220    /* MS forgot to define this one with a non-underscore form too. */
7221    if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
7222#endif
7223#ifdef O_TEMPORARY
7224    /* Automatically delete when last handle is closed. */
7225    if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
7226#endif
7227#ifdef O_RANDOM
7228    /* Optimize for random access. */
7229    if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
7230#endif
7231#ifdef O_SEQUENTIAL
7232    /* Optimize for sequential access. */
7233    if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
7234#endif
7235
7236/* GNU extensions. */
7237#ifdef O_ASYNC
7238    /* Send a SIGIO signal whenever input or output
7239       becomes available on file descriptor */
7240    if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
7241#endif
7242#ifdef O_DIRECT
7243    /* Direct disk access. */
7244    if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
7245#endif
7246#ifdef O_DIRECTORY
7247    /* Must be a directory.      */
7248    if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
7249#endif
7250#ifdef O_NOFOLLOW
7251    /* Do not follow links.      */
7252    if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
7253#endif
7254#ifdef O_NOATIME
7255    /* Do not update the access time. */
7256    if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
7257#endif
7258
7259    /* These come from sysexits.h */
7260#ifdef EX_OK
7261    if (ins(d, "EX_OK", (long)EX_OK)) return -1;
7262#endif /* EX_OK */
7263#ifdef EX_USAGE
7264    if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
7265#endif /* EX_USAGE */
7266#ifdef EX_DATAERR
7267    if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
7268#endif /* EX_DATAERR */
7269#ifdef EX_NOINPUT
7270    if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
7271#endif /* EX_NOINPUT */
7272#ifdef EX_NOUSER
7273    if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
7274#endif /* EX_NOUSER */
7275#ifdef EX_NOHOST
7276    if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
7277#endif /* EX_NOHOST */
7278#ifdef EX_UNAVAILABLE
7279    if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
7280#endif /* EX_UNAVAILABLE */
7281#ifdef EX_SOFTWARE
7282    if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
7283#endif /* EX_SOFTWARE */
7284#ifdef EX_OSERR
7285    if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
7286#endif /* EX_OSERR */
7287#ifdef EX_OSFILE
7288    if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
7289#endif /* EX_OSFILE */
7290#ifdef EX_CANTCREAT
7291    if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
7292#endif /* EX_CANTCREAT */
7293#ifdef EX_IOERR
7294    if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
7295#endif /* EX_IOERR */
7296#ifdef EX_TEMPFAIL
7297    if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
7298#endif /* EX_TEMPFAIL */
7299#ifdef EX_PROTOCOL
7300    if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
7301#endif /* EX_PROTOCOL */
7302#ifdef EX_NOPERM
7303    if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
7304#endif /* EX_NOPERM */
7305#ifdef EX_CONFIG
7306    if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
7307#endif /* EX_CONFIG */
7308#ifdef EX_NOTFOUND
7309    if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
7310#endif /* EX_NOTFOUND */
7311
7312#ifdef HAVE_SPAWNV
7313#if defined(PYOS_OS2) && defined(PYCC_GCC)
7314    if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
7315    if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
7316    if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
7317    if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
7318    if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
7319    if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
7320    if (ins(d, "P_PM", (long)P_PM)) return -1;
7321    if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
7322    if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
7323    if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
7324    if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
7325    if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
7326    if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
7327    if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
7328    if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
7329    if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
7330    if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
7331    if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
7332    if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
7333    if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
7334#else
7335    if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
7336    if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
7337    if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
7338    if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
7339    if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
7340#endif
7341#endif
7342  return 0;
7343}
7344
7345#define INITFUNC initedk2
7346#define MODNAME "edk2"
7347
7348PyMODINIT_FUNC
7349INITFUNC(void)
7350{
7351    PyObject *m;
7352
7353#ifndef UEFI_C_SOURCE
7354  PyObject *v;
7355#endif
7356
7357    m = Py_InitModule3(MODNAME,
7358                       posix_methods,
7359                       edk2__doc__);
7360    if (m == NULL)
7361        return;
7362
7363#ifndef UEFI_C_SOURCE
7364    /* Initialize environ dictionary */
7365    v = convertenviron();
7366    Py_XINCREF(v);
7367    if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
7368        return;
7369    Py_DECREF(v);
7370#endif  /* UEFI_C_SOURCE */
7371
7372    if (all_ins(m))
7373        return;
7374
7375    if (setup_confname_tables(m))
7376        return;
7377
7378    Py_INCREF(PyExc_OSError);
7379    PyModule_AddObject(m, "error", PyExc_OSError);
7380
7381#ifdef HAVE_PUTENV
7382    if (posix_putenv_garbage == NULL)
7383        posix_putenv_garbage = PyDict_New();
7384#endif
7385
7386    if (!initialized) {
7387        stat_result_desc.name = MODNAME ".stat_result";
7388        stat_result_desc.fields[2].name = PyStructSequence_UnnamedField;
7389        stat_result_desc.fields[3].name = PyStructSequence_UnnamedField;
7390        stat_result_desc.fields[4].name = PyStructSequence_UnnamedField;
7391        PyStructSequence_InitType(&StatResultType, &stat_result_desc);
7392        structseq_new = StatResultType.tp_new;
7393        StatResultType.tp_new = statresult_new;
7394
7395        //statvfs_result_desc.name = MODNAME ".statvfs_result";
7396        //PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
7397#ifdef NEED_TICKS_PER_SECOND
7398#  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
7399        ticks_per_second = sysconf(_SC_CLK_TCK);
7400#  elif defined(HZ)
7401        ticks_per_second = HZ;
7402#  else
7403        ticks_per_second = 60; /* magic fallback value; may be bogus */
7404#  endif
7405#endif
7406    }
7407    Py_INCREF((PyObject*) &StatResultType);
7408    PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
7409    //Py_INCREF((PyObject*) &StatVFSResultType);
7410    //PyModule_AddObject(m, "statvfs_result",
7411    //                   (PyObject*) &StatVFSResultType);
7412    initialized = 1;
7413
7414}
7415
7416#ifdef __cplusplus
7417}
7418#endif
7419
7420
7421