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
25 extern "C" {
26 #endif
27 
28 PyDoc_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 */
160 extern char **environ;
161 
162 static PyObject *
convertenviron(void)163 convertenviron(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 
203 static PyObject *
posix_error(void)204 posix_error(void)
205 {
206     return PyErr_SetFromErrno(PyExc_OSError);
207 }
208 static PyObject *
posix_error_with_filename(char * name)209 posix_error_with_filename(char* name)
210 {
211     return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
212 }
213 
214 
215 static PyObject *
posix_error_with_allocated_filename(char * name)216 posix_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 *
posix_fildes(PyObject * fdobj,int (* func)(int))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 
246 static PyObject *
posix_1str(PyObject * args,char * format,int (* func)(const char *))247 posix_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 
264 static PyObject *
posix_2str(PyObject * args,char * format,int (* func)(const char *,const char *))265 posix_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 
287 PyDoc_STRVAR(stat_result__doc__,
288 "stat_result: Result from stat or lstat.\n\n\
289 This object may be accessed either as a tuple of\n\
290   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
291 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
292 \n\
293 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
294 or st_flags, they are available as attributes only.\n\
295 \n\
296 See os.stat for more information.");
297 
298 static 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 
370 static 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 */
378 PyDoc_STRVAR(statvfs_result__doc__,
379 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
380 This object may be accessed either as a tuple of\n\
381   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
382 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
383 \n\
384 See os.statvfs for more information.");
385 
386 static 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 
400 static PyStructSequence_Desc statvfs_result_desc = {
401     "statvfs_result", /* name */
402     statvfs_result__doc__, /* doc */
403     statvfs_result_fields,
404     10
405 };
406 
407 static PyTypeObject StatVFSResultType;
408 #endif
409 
410 static int initialized;
411 static PyTypeObject StatResultType;
412 static newfunc structseq_new;
413 
414 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)415 statresult_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 
444 PyDoc_STRVAR(stat_float_times__doc__,
445 "stat_float_times([newval]) -> oldval\n\n\
446 Determine whether os.[lf]stat represents time stamps as float objects.\n\
447 If newval is True, future calls to stat() return floats, if it is False,\n\
448 future calls return ints. \n\
449 If newval is omitted, return the current setting.\n");
450 
451 static PyObject*
stat_float_times(PyObject * self,PyObject * args)452 stat_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 
467 static void
fill_time(PyObject * v,int index,time_t sec,unsigned long nsec)468 fill_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()) */
490 static PyObject*
_pystat_fromstructstat(STRUCT_STAT * st)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 
558 static PyObject *
posix_do_stat(PyObject * self,PyObject * args,char * format,int (* statfunc)(const char *,STRUCT_STAT *),char * wformat,int (* wstatfunc)(const Py_UNICODE *,STRUCT_STAT *))559 posix_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 
592 PyDoc_STRVAR(posix_access__doc__,
593 "access(path, mode) -> True if granted, False otherwise\n\n\
594 Use the real uid/gid to test for access to a path.  Note that most\n\
595 operations will use the effective uid/gid, therefore this routine can\n\
596 be used in a suid/sgid environment to test if the invoking user has the\n\
597 specified access to the path.  The mode argument can be F_OK to test\n\
598 existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
599 
600 static PyObject *
posix_access(PyObject * self,PyObject * args)601 posix_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 
630 PyDoc_STRVAR(posix_chdir__doc__,
631 "chdir(path)\n\n\
632 Change the current working directory to the specified path.");
633 
634 static PyObject *
posix_chdir(PyObject * self,PyObject * args)635 posix_chdir(PyObject *self, PyObject *args)
636 {
637     return posix_1str(args, "et:chdir", chdir);
638 }
639 
640 PyDoc_STRVAR(posix_chmod__doc__,
641 "chmod(path, mode)\n\n\
642 Change the access permissions of a file.");
643 
644 static PyObject *
posix_chmod(PyObject * self,PyObject * args)645 posix_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
664 PyDoc_STRVAR(posix_fchmod__doc__,
665 "fchmod(fd, mode)\n\n\
666 Change the access permissions of the file given by file\n\
667 descriptor fd.");
668 
669 static PyObject *
posix_fchmod(PyObject * self,PyObject * args)670 posix_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
685 PyDoc_STRVAR(posix_lchmod__doc__,
686 "lchmod(path, mode)\n\n\
687 Change the access permissions of a file. If path is a symlink, this\n\
688 affects the link itself rather than the target.");
689 
690 static PyObject *
posix_lchmod(PyObject * self,PyObject * args)691 posix_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
711 PyDoc_STRVAR(posix_chflags__doc__,
712 "chflags(path, flags)\n\n\
713 Set file flags.");
714 
715 static PyObject *
posix_chflags(PyObject * self,PyObject * args)716 posix_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
736 PyDoc_STRVAR(posix_lchflags__doc__,
737 "lchflags(path, flags)\n\n\
738 Set file flags.\n\
739 This function will not follow symbolic links.");
740 
741 static PyObject *
posix_lchflags(PyObject * self,PyObject * args)742 posix_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
762 PyDoc_STRVAR(posix_chroot__doc__,
763 "chroot(path)\n\n\
764 Change root directory to path.");
765 
766 static PyObject *
posix_chroot(PyObject * self,PyObject * args)767 posix_chroot(PyObject *self, PyObject *args)
768 {
769     return posix_1str(args, "et:chroot", chroot);
770 }
771 #endif
772 
773 #ifdef HAVE_FSYNC
774 PyDoc_STRVAR(posix_fsync__doc__,
775 "fsync(fildes)\n\n\
776 force write of file with filedescriptor to disk.");
777 
778 static PyObject *
posix_fsync(PyObject * self,PyObject * fdobj)779 posix_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
788 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
789 #endif
790 
791 PyDoc_STRVAR(posix_fdatasync__doc__,
792 "fdatasync(fildes)\n\n\
793 force write of file with filedescriptor to disk.\n\
794  does not force update of metadata.");
795 
796 static PyObject *
posix_fdatasync(PyObject * self,PyObject * fdobj)797 posix_fdatasync(PyObject *self, PyObject *fdobj)
798 {
799     return posix_fildes(fdobj, fdatasync);
800 }
801 #endif /* HAVE_FDATASYNC */
802 
803 
804 #ifdef HAVE_CHOWN
805 PyDoc_STRVAR(posix_chown__doc__,
806 "chown(path, uid, gid)\n\n\
807 Change the owner and group id of path to the numeric uid and gid.");
808 
809 static PyObject *
posix_chown(PyObject * self,PyObject * args)810 posix_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
831 PyDoc_STRVAR(posix_fchown__doc__,
832 "fchown(fd, uid, gid)\n\n\
833 Change the owner and group id of the file given by file descriptor\n\
834 fd to the numeric uid and gid.");
835 
836 static PyObject *
posix_fchown(PyObject * self,PyObject * args)837 posix_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
854 PyDoc_STRVAR(posix_lchown__doc__,
855 "lchown(path, uid, gid)\n\n\
856 Change the owner and group id of path to the numeric uid and gid.\n\
857 This function will not follow symbolic links.");
858 
859 static PyObject *
posix_lchown(PyObject * self,PyObject * args)860 posix_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
882 PyDoc_STRVAR(posix_getcwd__doc__,
883 "getcwd() -> path\n\n\
884 Return a string representing the current working directory.");
885 
886 static PyObject *
posix_getcwd(PyObject * self,PyObject * noargs)887 posix_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
919 PyDoc_STRVAR(posix_getcwdu__doc__,
920 "getcwdu() -> path\n\n\
921 Return a unicode string representing the current working directory.");
922 
923 static PyObject *
posix_getcwdu(PyObject * self,PyObject * noargs)924 posix_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 
940 PyDoc_STRVAR(posix_listdir__doc__,
941 "listdir(path) -> list_of_strings\n\n\
942 Return a list containing the names of the entries in the directory.\n\
943 \n\
944     path: path of directory to list\n\
945 \n\
946 The list is in arbitrary order.  It does not include the special\n\
947 entries '.' and '..' even if they are present in the directory.");
948 
949 static PyObject *
posix_listdir(PyObject * self,PyObject * args)950 posix_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 */
1065 static PyObject *
posix__getfullpathname(PyObject * self,PyObject * args)1066 posix__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 
1118 PyDoc_STRVAR(posix_mkdir__doc__,
1119 "mkdir(path [, mode=0777])\n\n\
1120 Create a directory.");
1121 
1122 static PyObject *
posix_mkdir(PyObject * self,PyObject * args)1123 posix_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
1150 PyDoc_STRVAR(posix_nice__doc__,
1151 "nice(inc) -> new_priority\n\n\
1152 Decrease the priority of process by inc and return the new priority.");
1153 
1154 static PyObject *
posix_nice(PyObject * self,PyObject * args)1155 posix_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 
1185 PyDoc_STRVAR(posix_rename__doc__,
1186 "rename(old, new)\n\n\
1187 Rename a file or directory.");
1188 
1189 static PyObject *
posix_rename(PyObject * self,PyObject * args)1190 posix_rename(PyObject *self, PyObject *args)
1191 {
1192     return posix_2str(args, "etet:rename", rename);
1193 }
1194 
1195 
1196 PyDoc_STRVAR(posix_rmdir__doc__,
1197 "rmdir(path)\n\n\
1198 Remove a directory.");
1199 
1200 static PyObject *
posix_rmdir(PyObject * self,PyObject * args)1201 posix_rmdir(PyObject *self, PyObject *args)
1202 {
1203     return posix_1str(args, "et:rmdir", rmdir);
1204 }
1205 
1206 
1207 PyDoc_STRVAR(posix_stat__doc__,
1208 "stat(path) -> stat result\n\n\
1209 Perform a stat system call on the given path.");
1210 
1211 static PyObject *
posix_stat(PyObject * self,PyObject * args)1212 posix_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
1219 PyDoc_STRVAR(posix_system__doc__,
1220 "system(command) -> exit_status\n\n\
1221 Execute the command (a string) in a subshell.");
1222 
1223 static PyObject *
posix_system(PyObject * self,PyObject * args)1224 posix_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 
1238 PyDoc_STRVAR(posix_umask__doc__,
1239 "umask(new_mask) -> old_mask\n\n\
1240 Set the current numeric umask and return the previous umask.");
1241 
1242 static PyObject *
posix_umask(PyObject * self,PyObject * args)1243 posix_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 
1255 PyDoc_STRVAR(posix_unlink__doc__,
1256 "unlink(path)\n\n\
1257 Remove a file (same as remove(path)).");
1258 
1259 PyDoc_STRVAR(posix_remove__doc__,
1260 "remove(path)\n\n\
1261 Remove a file (same as unlink(path)).");
1262 
1263 static PyObject *
posix_unlink(PyObject * self,PyObject * args)1264 posix_unlink(PyObject *self, PyObject *args)
1265 {
1266     return posix_1str(args, "et:remove", unlink);
1267 }
1268 
1269 
1270 static int
extract_time(PyObject * t,time_t * sec,long * usec)1271 extract_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 
1307 PyDoc_STRVAR(posix_utime__doc__,
1308 "utime(path, (atime, mtime))\n\
1309 utime(path, None)\n\n\
1310 Set the access and modified time of the file to the given values.  If the\n\
1311 second form is used, set the access and modified times to the current time.");
1312 
1313 static PyObject *
posix_utime(PyObject * self,PyObject * args)1314 posix_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 
1394 PyDoc_STRVAR(posix__exit__doc__,
1395 "_exit(status)\n\n\
1396 Exit to the system with specified status, without normal exit processing.");
1397 
1398 static PyObject *
posix__exit(PyObject * self,PyObject * args)1399 posix__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)
1409 static void
free_string_array(char ** array,Py_ssize_t count)1410 free_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
1421 PyDoc_STRVAR(posix_execv__doc__,
1422 "execv(path, args)\n\n\
1423 Execute 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 
1428 static PyObject *
posix_execv(PyObject * self,PyObject * args)1429 posix_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 
1492 PyDoc_STRVAR(posix_execve__doc__,
1493 "execve(path, args, env)\n\n\
1494 Execute 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 
1500 static PyObject *
posix_execve(PyObject * self,PyObject * args)1501 posix_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
1637 PyDoc_STRVAR(posix_spawnv__doc__,
1638 "spawnv(mode, path, args)\n\n\
1639 Execute 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 
1645 static PyObject *
posix_spawnv(PyObject * self,PyObject * args)1646 posix_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 
1724 PyDoc_STRVAR(posix_spawnve__doc__,
1725 "spawnve(mode, path, args, env)\n\n\
1726 Execute 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 
1733 static PyObject *
posix_spawnve(PyObject * self,PyObject * args)1734 posix_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)
1879 PyDoc_STRVAR(posix_spawnvp__doc__,
1880 "spawnvp(mode, file, args)\n\n\
1881 Execute the program 'file' in a new process, using the environment\n\
1882 search 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 
1888 static PyObject *
posix_spawnvp(PyObject * self,PyObject * args)1889 posix_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 
1957 PyDoc_STRVAR(posix_spawnvpe__doc__,
1958 "spawnvpe(mode, file, args, env)\n\n\
1959 Execute the program 'file' in a new process, using the environment\n\
1960 search 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 
1967 static PyObject *
posix_spawnvpe(PyObject * self,PyObject * args)1968 posix_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
2105 PyDoc_STRVAR(posix_fork1__doc__,
2106 "fork1() -> pid\n\n\
2107 Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
2108 \n\
2109 Return 0 to child process and PID of child to parent process.");
2110 
2111 static PyObject *
posix_fork1(PyObject * self,PyObject * noargs)2112 posix_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
2139 PyDoc_STRVAR(posix_fork__doc__,
2140 "fork() -> pid\n\n\
2141 Fork a child process.\n\
2142 Return 0 to child process and PID of child to parent process.");
2143 
2144 static PyObject *
posix_fork(PyObject * self,PyObject * noargs)2145 posix_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)
2197 PyDoc_STRVAR(posix_openpty__doc__,
2198 "openpty() -> (master_fd, slave_fd)\n\n\
2199 Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
2200 
2201 static PyObject *
posix_openpty(PyObject * self,PyObject * noargs)2202 posix_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
2263 PyDoc_STRVAR(posix_forkpty__doc__,
2264 "forkpty() -> (pid, master_fd)\n\n\
2265 Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
2266 Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
2267 To both, return fd of newly opened pseudo-terminal.\n");
2268 
2269 static PyObject *
posix_forkpty(PyObject * self,PyObject * noargs)2270 posix_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
2297 PyDoc_STRVAR(posix_getegid__doc__,
2298 "getegid() -> egid\n\n\
2299 Return the current process's effective group id.");
2300 
2301 static PyObject *
posix_getegid(PyObject * self,PyObject * noargs)2302 posix_getegid(PyObject *self, PyObject *noargs)
2303 {
2304     return PyInt_FromLong((long)getegid());
2305 }
2306 #endif
2307 
2308 
2309 #ifdef HAVE_GETEUID
2310 PyDoc_STRVAR(posix_geteuid__doc__,
2311 "geteuid() -> euid\n\n\
2312 Return the current process's effective user id.");
2313 
2314 static PyObject *
posix_geteuid(PyObject * self,PyObject * noargs)2315 posix_geteuid(PyObject *self, PyObject *noargs)
2316 {
2317     return PyInt_FromLong((long)geteuid());
2318 }
2319 #endif
2320 
2321 
2322 #ifdef HAVE_GETGID
2323 PyDoc_STRVAR(posix_getgid__doc__,
2324 "getgid() -> gid\n\n\
2325 Return the current process's group id.");
2326 
2327 static PyObject *
posix_getgid(PyObject * self,PyObject * noargs)2328 posix_getgid(PyObject *self, PyObject *noargs)
2329 {
2330     return PyInt_FromLong((long)getgid());
2331 }
2332 #endif
2333 
2334 
2335 PyDoc_STRVAR(posix_getpid__doc__,
2336 "getpid() -> pid\n\n\
2337 Return the current process id");
2338 
2339 static PyObject *
posix_getpid(PyObject * self,PyObject * noargs)2340 posix_getpid(PyObject *self, PyObject *noargs)
2341 {
2342     return PyLong_FromPid(getpid());
2343 }
2344 
2345 
2346 #ifdef HAVE_GETGROUPS
2347 PyDoc_STRVAR(posix_getgroups__doc__,
2348 "getgroups() -> list of group IDs\n\n\
2349 Return list of supplemental group IDs for the process.");
2350 
2351 static PyObject *
posix_getgroups(PyObject * self,PyObject * noargs)2352 posix_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
2424 PyDoc_STRVAR(posix_initgroups__doc__,
2425 "initgroups(username, gid) -> None\n\n\
2426 Call the system initgroups() to initialize the group access list with all of\n\
2427 the groups of which the specified username is a member, plus the specified\n\
2428 group id.");
2429 
2430 static PyObject *
posix_initgroups(PyObject * self,PyObject * args)2431 posix_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
2448 PyDoc_STRVAR(posix_getpgid__doc__,
2449 "getpgid(pid) -> pgid\n\n\
2450 Call the system call getpgid().");
2451 
2452 static PyObject *
posix_getpgid(PyObject * self,PyObject * args)2453 posix_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
2467 PyDoc_STRVAR(posix_getpgrp__doc__,
2468 "getpgrp() -> pgrp\n\n\
2469 Return the current process group id.");
2470 
2471 static PyObject *
posix_getpgrp(PyObject * self,PyObject * noargs)2472 posix_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
2484 PyDoc_STRVAR(posix_setpgrp__doc__,
2485 "setpgrp()\n\n\
2486 Make this process the process group leader.");
2487 
2488 static PyObject *
posix_setpgrp(PyObject * self,PyObject * noargs)2489 posix_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
2504 PyDoc_STRVAR(posix_getppid__doc__,
2505 "getppid() -> ppid\n\n\
2506 Return the parent's process id.");
2507 
2508 static PyObject *
posix_getppid(PyObject * self,PyObject * noargs)2509 posix_getppid(PyObject *self, PyObject *noargs)
2510 {
2511     return PyLong_FromPid(getppid());
2512 }
2513 #endif
2514 
2515 
2516 #ifdef HAVE_GETLOGIN
2517 PyDoc_STRVAR(posix_getlogin__doc__,
2518 "getlogin() -> string\n\n\
2519 Return the actual login name.");
2520 
2521 static PyObject *
posix_getlogin(PyObject * self,PyObject * noargs)2522 posix_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
2546 PyDoc_STRVAR(posix_getuid__doc__,
2547 "getuid() -> uid\n\n\
2548 Return the current process's user id.");
2549 
2550 static PyObject *
posix_getuid(PyObject * self,PyObject * noargs)2551 posix_getuid(PyObject *self, PyObject *noargs)
2552 {
2553     return PyInt_FromLong((long)getuid());
2554 }
2555 #endif  /* UEFI_C_SOURCE */
2556 
2557 #ifdef HAVE_KILL
2558 PyDoc_STRVAR(posix_kill__doc__,
2559 "kill(pid, sig)\n\n\
2560 Kill a process with a signal.");
2561 
2562 static PyObject *
posix_kill(PyObject * self,PyObject * args)2563 posix_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
2592 PyDoc_STRVAR(posix_killpg__doc__,
2593 "killpg(pgid, sig)\n\n\
2594 Kill a process group with a signal.");
2595 
2596 static PyObject *
posix_killpg(PyObject * self,PyObject * args)2597 posix_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 
2620 PyDoc_STRVAR(posix_plock__doc__,
2621 "plock(op)\n\n\
2622 Lock program segments into memory.");
2623 
2624 static PyObject *
posix_plock(PyObject * self,PyObject * args)2625 posix_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
2639 PyDoc_STRVAR(posix_popen__doc__,
2640 "popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\
2641 Open a pipe to/from a command returning a file object.");
2642 
2643 #if defined(PYOS_OS2)
2644 #if defined(PYCC_VACPP)
2645 static int
async_system(const char * command)2646 async_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 
2676 static FILE *
popen(const char * command,const char * mode,int pipesize,int * err)2677 popen(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 
2729 static PyObject *
posix_popen(PyObject * self,PyObject * args)2730 posix_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 */
2754 static PyObject *
posix_popen(PyObject * self,PyObject * args)2755 posix_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 
2787 static PyObject *_PyPopen(char *, int, int, int);
2788 static 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  */
2795 static 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 
2803 static PyObject *
os2emx_popen2(PyObject * self,PyObject * args)2804 os2emx_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 
2835 static PyObject *
os2emx_popen3(PyObject * self,PyObject * args)2836 os2emx_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 
2867 static PyObject *
os2emx_popen4(PyObject * self,PyObject * args)2868 os2emx_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  */
2895 struct file_ref
2896 {
2897     int handle;
2898     int flags;
2899 };
2900 
2901 struct pipe_ref
2902 {
2903     int rd;
2904     int wr;
2905 };
2906 
2907 /* The following code is derived from the win32 code */
2908 
2909 static PyObject *
_PyPopen(char * cmdstring,int mode,int n,int bufsize)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 
_PyPclose(FILE * file)3240 static 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 
3348 static PyObject *_PyPopen(char *, int, int);
3349 static 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  */
3356 static 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 
3365 static PyObject *
posix_popen(PyObject * self,PyObject * args)3366 posix_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 
3406 static PyObject *
win32_popen2(PyObject * self,PyObject * args)3407 win32_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 
3443 static PyObject *
win32_popen3(PyObject * self,PyObject * args)3444 win32_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 
3480 static PyObject *
win32_popen4(PyObject * self,PyObject * args)3481 win32_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 
3510 static BOOL
_PyPopenCreateProcess(char * cmdstring,HANDLE hStdin,HANDLE hStdout,HANDLE hStderr,HANDLE * hProcess)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 
3667 static PyObject *
_PyPopen(char * cmdstring,int mode,int n)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 
_PyPclose(FILE * file)3993 static 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? */
4075 static PyObject *
posix_popen(PyObject * self,PyObject * args)4076 posix_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
4106 PyDoc_STRVAR(posix_setuid__doc__,
4107 "setuid(uid)\n\n\
4108 Set the current process's user id.");
4109 
4110 static PyObject *
posix_setuid(PyObject * self,PyObject * args)4111 posix_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
4131 PyDoc_STRVAR(posix_seteuid__doc__,
4132 "seteuid(uid)\n\n\
4133 Set the current process's effective user id.");
4134 
4135 static PyObject *
posix_seteuid(PyObject * self,PyObject * args)4136 posix_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
4157 PyDoc_STRVAR(posix_setegid__doc__,
4158 "setegid(gid)\n\n\
4159 Set the current process's effective group id.");
4160 
4161 static PyObject *
posix_setegid(PyObject * self,PyObject * args)4162 posix_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
4183 PyDoc_STRVAR(posix_setreuid__doc__,
4184 "setreuid(ruid, euid)\n\n\
4185 Set the current process's real and effective user ids.");
4186 
4187 static PyObject *
posix_setreuid(PyObject * self,PyObject * args)4188 posix_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
4217 PyDoc_STRVAR(posix_setregid__doc__,
4218 "setregid(rgid, egid)\n\n\
4219 Set the current process's real and effective group ids.");
4220 
4221 static PyObject *
posix_setregid(PyObject * self,PyObject * args)4222 posix_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
4251 PyDoc_STRVAR(posix_setgid__doc__,
4252 "setgid(gid)\n\n\
4253 Set the current process's group id.");
4254 
4255 static PyObject *
posix_setgid(PyObject * self,PyObject * args)4256 posix_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
4275 PyDoc_STRVAR(posix_setgroups__doc__,
4276 "setgroups(list)\n\n\
4277 Set the groups of the current process to list.");
4278 
4279 static PyObject *
posix_setgroups(PyObject * self,PyObject * groups)4280 posix_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)
4343 static PyObject *
wait_helper(pid_t pid,int status,struct rusage * ru)4344 wait_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
4403 PyDoc_STRVAR(posix_wait3__doc__,
4404 "wait3(options) -> (pid, status, rusage)\n\n\
4405 Wait for completion of a child process.");
4406 
4407 static PyObject *
posix_wait3(PyObject * self,PyObject * args)4408 posix_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
4428 PyDoc_STRVAR(posix_wait4__doc__,
4429 "wait4(pid, options) -> (pid, status, rusage)\n\n\
4430 Wait for completion of a given child process.");
4431 
4432 static PyObject *
posix_wait4(PyObject * self,PyObject * args)4433 posix_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
4453 PyDoc_STRVAR(posix_waitpid__doc__,
4454 "waitpid(pid, options) -> (pid, status)\n\n\
4455 Wait for completion of a given child process.");
4456 
4457 static PyObject *
posix_waitpid(PyObject * self,PyObject * args)4458 posix_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. */
4479 PyDoc_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 
4483 static PyObject *
posix_waitpid(PyObject * self,PyObject * args)4484 posix_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
4503 PyDoc_STRVAR(posix_wait__doc__,
4504 "wait() -> (pid, status)\n\n\
4505 Wait for completion of a child process.");
4506 
4507 static PyObject *
posix_wait(PyObject * self,PyObject * noargs)4508 posix_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 
4525 PyDoc_STRVAR(posix_lstat__doc__,
4526 "lstat(path) -> stat result\n\n\
4527 Like stat(path), but do not follow symbolic links.");
4528 
4529 static PyObject *
posix_lstat(PyObject * self,PyObject * args)4530 posix_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
4541 PyDoc_STRVAR(posix_readlink__doc__,
4542 "readlink(path) -> path\n\n\
4543 Return a string representing the path to which the symbolic link points.");
4544 
4545 static PyObject *
posix_readlink(PyObject * self,PyObject * args)4546 posix_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
4604 PyDoc_STRVAR(posix_symlink__doc__,
4605 "symlink(src, dst)\n\n\
4606 Create a symbolic link pointing to src named dst.");
4607 
4608 static PyObject *
posix_symlink(PyObject * self,PyObject * args)4609 posix_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)
4618 static long
system_uptime(void)4619 system_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 
4630 static PyObject *
posix_times(PyObject * self,PyObject * noargs)4631 posix_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
4643 static long ticks_per_second = -1;
4644 static PyObject *
posix_times(PyObject * self,PyObject * noargs)4645 posix_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
4665 PyDoc_STRVAR(posix_times__doc__,
4666 "times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
4667 Return a tuple of floating point numbers indicating process times.");
4668 #endif
4669 
4670 
4671 #ifdef HAVE_GETSID
4672 PyDoc_STRVAR(posix_getsid__doc__,
4673 "getsid(pid) -> sid\n\n\
4674 Call the system call getsid().");
4675 
4676 static PyObject *
posix_getsid(PyObject * self,PyObject * args)4677 posix_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
4692 PyDoc_STRVAR(posix_setsid__doc__,
4693 "setsid()\n\n\
4694 Call the system call setsid().");
4695 
4696 static PyObject *
posix_setsid(PyObject * self,PyObject * noargs)4697 posix_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
4707 PyDoc_STRVAR(posix_setpgid__doc__,
4708 "setpgid(pid, pgrp)\n\n\
4709 Call the system call setpgid().");
4710 
4711 static PyObject *
posix_setpgid(PyObject * self,PyObject * args)4712 posix_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
4727 PyDoc_STRVAR(posix_tcgetpgrp__doc__,
4728 "tcgetpgrp(fd) -> pgid\n\n\
4729 Return the process group associated with the terminal given by a fd.");
4730 
4731 static PyObject *
posix_tcgetpgrp(PyObject * self,PyObject * args)4732 posix_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
4747 PyDoc_STRVAR(posix_tcsetpgrp__doc__,
4748 "tcsetpgrp(fd, pgid)\n\n\
4749 Set the process group associated with the terminal given by a fd.");
4750 
4751 static PyObject *
posix_tcsetpgrp(PyObject * self,PyObject * args)4752 posix_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 
4767 PyDoc_STRVAR(posix_open__doc__,
4768 "open(filename, flag [, mode=0777]) -> fd\n\n\
4769 Open a file (for low level IO).");
4770 
4771 static PyObject *
posix_open(PyObject * self,PyObject * args)4772 posix_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 
4794 PyDoc_STRVAR(posix_close__doc__,
4795 "close(fd)\n\n\
4796 Close a file descriptor (for low level IO).");
4797 
4798 static PyObject *
posix_close(PyObject * self,PyObject * args)4799 posix_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 
4816 PyDoc_STRVAR(posix_closerange__doc__,
4817 "closerange(fd_low, fd_high)\n\n\
4818 Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
4819 
4820 static PyObject *
posix_closerange(PyObject * self,PyObject * args)4821 posix_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 
4835 PyDoc_STRVAR(posix_dup__doc__,
4836 "dup(fd) -> fd2\n\n\
4837 Return a duplicate of a file descriptor.");
4838 
4839 static PyObject *
posix_dup(PyObject * self,PyObject * args)4840 posix_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 
4856 PyDoc_STRVAR(posix_dup2__doc__,
4857 "dup2(old_fd, new_fd)\n\n\
4858 Duplicate file descriptor.");
4859 
4860 static PyObject *
posix_dup2(PyObject * self,PyObject * args)4861 posix_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 
4878 PyDoc_STRVAR(posix_lseek__doc__,
4879 "lseek(fd, pos, how) -> newpos\n\n\
4880 Set the current position of a file descriptor.");
4881 
4882 static PyObject *
posix_lseek(PyObject * self,PyObject * args)4883 posix_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 
4924 PyDoc_STRVAR(posix_read__doc__,
4925 "read(fd, buffersize) -> string\n\n\
4926 Read a file descriptor.");
4927 
4928 static PyObject *
posix_read(PyObject * self,PyObject * args)4929 posix_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 
4959 PyDoc_STRVAR(posix_write__doc__,
4960 "write(fd, string) -> byteswritten\n\n\
4961 Write a string to a file descriptor.");
4962 
4963 static PyObject *
posix_write(PyObject * self,PyObject * args)4964 posix_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 
4986 PyDoc_STRVAR(posix_fstat__doc__,
4987 "fstat(fd) -> stat result\n\n\
4988 Like stat(), but for an open file descriptor.");
4989 
4990 static PyObject *
posix_fstat(PyObject * self,PyObject * args)4991 posix_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 
5011 PyDoc_STRVAR(posix_fdopen__doc__,
5012 "fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
5013 Return an open file object connected to a file descriptor.");
5014 
5015 static PyObject *
posix_fdopen(PyObject * self,PyObject * args)5016 posix_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 
5068 PyDoc_STRVAR(posix_isatty__doc__,
5069 "isatty(fd) -> bool\n\n\
5070 Return True if the file descriptor 'fd' is an open file descriptor\n\
5071 connected to the slave end of a terminal.");
5072 
5073 static PyObject *
posix_isatty(PyObject * self,PyObject * args)5074 posix_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
5085 PyDoc_STRVAR(posix_pipe__doc__,
5086 "pipe() -> (read_end, write_end)\n\n\
5087 Create a pipe.");
5088 
5089 static PyObject *
posix_pipe(PyObject * self,PyObject * noargs)5090 posix_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
5132 PyDoc_STRVAR(posix_mkfifo__doc__,
5133 "mkfifo(filename [, mode=0666])\n\n\
5134 Create a FIFO (a POSIX named pipe).");
5135 
5136 static PyObject *
posix_mkfifo(PyObject * self,PyObject * args)5137 posix_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)
5156 PyDoc_STRVAR(posix_mknod__doc__,
5157 "mknod(filename [, mode=0600, device])\n\n\
5158 Create a filesystem node (file, device special file or named pipe)\n\
5159 named filename. mode specifies both the permissions to use and the\n\
5160 type of node to be created, being combined (bitwise OR) with one of\n\
5161 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
5162 device defines the newly created device special file (probably using\n\
5163 os.makedev()), otherwise it is ignored.");
5164 
5165 
5166 static PyObject *
posix_mknod(PyObject * self,PyObject * args)5167 posix_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
5186 PyDoc_STRVAR(posix_major__doc__,
5187 "major(device) -> major number\n\
5188 Extracts a device major number from a raw device number.");
5189 
5190 static PyObject *
posix_major(PyObject * self,PyObject * args)5191 posix_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 
5199 PyDoc_STRVAR(posix_minor__doc__,
5200 "minor(device) -> minor number\n\
5201 Extracts a device minor number from a raw device number.");
5202 
5203 static PyObject *
posix_minor(PyObject * self,PyObject * args)5204 posix_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 
5212 PyDoc_STRVAR(posix_makedev__doc__,
5213 "makedev(major, minor) -> device number\n\
5214 Composes a raw device number from the major and minor device numbers.");
5215 
5216 static PyObject *
posix_makedev(PyObject * self,PyObject * args)5217 posix_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
5228 PyDoc_STRVAR(posix_ftruncate__doc__,
5229 "ftruncate(fd, length)\n\n\
5230 Truncate a file to a specified length.");
5231 
5232 static PyObject *
posix_ftruncate(PyObject * self,PyObject * args)5233 posix_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
5263 PyDoc_STRVAR(posix_putenv__doc__,
5264 "putenv(key, value)\n\n\
5265 Change 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. */
5269 static PyObject *posix_putenv_garbage;
5270 
5271 static PyObject *
posix_putenv(PyObject * self,PyObject * args)5272 posix_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
5335 PyDoc_STRVAR(posix_unsetenv__doc__,
5336 "unsetenv(key)\n\n\
5337 Delete an environment variable.");
5338 
5339 static PyObject *
posix_unsetenv(PyObject * self,PyObject * args)5340 posix_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 
5365 PyDoc_STRVAR(posix_strerror__doc__,
5366 "strerror(code) -> string\n\n\
5367 Translate an error code to a message string.");
5368 
5369 static PyObject *
posix_strerror(PyObject * self,PyObject * args)5370 posix_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
5389 PyDoc_STRVAR(posix_WCOREDUMP__doc__,
5390 "WCOREDUMP(status) -> bool\n\n\
5391 Return True if the process returning 'status' was dumped to a core file.");
5392 
5393 static PyObject *
posix_WCOREDUMP(PyObject * self,PyObject * args)5394 posix_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
5407 PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
5408 "WIFCONTINUED(status) -> bool\n\n\
5409 Return True if the process returning 'status' was continued from a\n\
5410 job control stop.");
5411 
5412 static PyObject *
posix_WIFCONTINUED(PyObject * self,PyObject * args)5413 posix_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
5426 PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
5427 "WIFSTOPPED(status) -> bool\n\n\
5428 Return True if the process returning 'status' was stopped.");
5429 
5430 static PyObject *
posix_WIFSTOPPED(PyObject * self,PyObject * args)5431 posix_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
5444 PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
5445 "WIFSIGNALED(status) -> bool\n\n\
5446 Return True if the process returning 'status' was terminated by a signal.");
5447 
5448 static PyObject *
posix_WIFSIGNALED(PyObject * self,PyObject * args)5449 posix_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
5462 PyDoc_STRVAR(posix_WIFEXITED__doc__,
5463 "WIFEXITED(status) -> bool\n\n\
5464 Return true if the process returning 'status' exited using the exit()\n\
5465 system call.");
5466 
5467 static PyObject *
posix_WIFEXITED(PyObject * self,PyObject * args)5468 posix_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
5481 PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
5482 "WEXITSTATUS(status) -> integer\n\n\
5483 Return the process return code from 'status'.");
5484 
5485 static PyObject *
posix_WEXITSTATUS(PyObject * self,PyObject * args)5486 posix_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
5499 PyDoc_STRVAR(posix_WTERMSIG__doc__,
5500 "WTERMSIG(status) -> integer\n\n\
5501 Return the signal that terminated the process that provided the 'status'\n\
5502 value.");
5503 
5504 static PyObject *
posix_WTERMSIG(PyObject * self,PyObject * args)5505 posix_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
5518 PyDoc_STRVAR(posix_WSTOPSIG__doc__,
5519 "WSTOPSIG(status) -> integer\n\n\
5520 Return the signal that stopped the process that provided\n\
5521 the 'status' value.");
5522 
5523 static PyObject *
posix_WSTOPSIG(PyObject * self,PyObject * args)5524 posix_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 
5547 static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st)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 
5586 PyDoc_STRVAR(posix_fstatvfs__doc__,
5587 "fstatvfs(fd) -> statvfs result\n\n\
5588 Perform an fstatvfs system call on the given fd.");
5589 
5590 static PyObject *
posix_fstatvfs(PyObject * self,PyObject * args)5591 posix_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 
5612 PyDoc_STRVAR(posix_statvfs__doc__,
5613 "statvfs(path) -> statvfs result\n\n\
5614 Perform a statvfs system call on the given path.");
5615 
5616 static PyObject *
posix_statvfs(PyObject * self,PyObject * args)5617 posix_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
5636 PyDoc_STRVAR(posix_tempnam__doc__,
5637 "tempnam([dir[, prefix]]) -> string\n\n\
5638 Return a unique name for a temporary file.\n\
5639 The directory and a prefix may be specified as strings; they may be omitted\n\
5640 or None if not needed.");
5641 
5642 static PyObject *
posix_tempnam(PyObject * self,PyObject * args)5643 posix_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
5672 PyDoc_STRVAR(posix_tmpfile__doc__,
5673 "tmpfile() -> file object\n\n\
5674 Create a temporary file with no directory entries.");
5675 
5676 static PyObject *
posix_tmpfile(PyObject * self,PyObject * noargs)5677 posix_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
5694 PyDoc_STRVAR(posix_tmpnam__doc__,
5695 "tmpnam() -> string\n\n\
5696 Return a unique name for a temporary file.");
5697 
5698 static PyObject *
posix_tmpnam(PyObject * self,PyObject * noargs)5699 posix_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  */
5745 struct constdef {
5746     char *name;
5747     long value;
5748 };
5749 
5750 #ifndef UEFI_C_SOURCE
5751 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)5752 conv_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)
5788 static 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 
5842 static int
conv_path_confname(PyObject * arg,int * valuep)5843 conv_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
5852 PyDoc_STRVAR(posix_fpathconf__doc__,
5853 "fpathconf(fd, name) -> integer\n\n\
5854 Return the configuration limit name for the file descriptor fd.\n\
5855 If there is no limit, return -1.");
5856 
5857 static PyObject *
posix_fpathconf(PyObject * self,PyObject * args)5858 posix_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
5880 PyDoc_STRVAR(posix_pathconf__doc__,
5881 "pathconf(path, name) -> integer\n\n\
5882 Return the configuration limit name for the file or directory path.\n\
5883 If there is no limit, return -1.");
5884 
5885 static PyObject *
posix_pathconf(PyObject * self,PyObject * args)5886 posix_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
5913 static 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 
6060 static int
conv_confstr_confname(PyObject * arg,int * valuep)6061 conv_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 
6068 PyDoc_STRVAR(posix_confstr__doc__,
6069 "confstr(name) -> string\n\n\
6070 Return a string-valued system configuration variable.");
6071 
6072 static PyObject *
posix_confstr(PyObject * self,PyObject * args)6073 posix_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
6109 static 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 
6604 static int
conv_sysconf_confname(PyObject * arg,int * valuep)6605 conv_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 
6612 PyDoc_STRVAR(posix_sysconf__doc__,
6613 "sysconf(name) -> integer\n\n\
6614 Return an integer-valued system configuration variable.");
6615 
6616 static PyObject *
posix_sysconf(PyObject * self,PyObject * args)6617 posix_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 
6648 static int
cmp_constdefs(const void * v1,const void * v2)6649 cmp_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 
6659 static int
setup_confname_table(struct constdef * table,size_t tablesize,char * tablename,PyObject * module)6660 setup_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. */
6685 static int
setup_confname_tables(PyObject * module)6686 setup_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 
6713 PyDoc_STRVAR(posix_abort__doc__,
6714 "abort() -> does not return!\n\n\
6715 Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
6716 in the hardest way possible on the hosting operating system.");
6717 
6718 static PyObject *
posix_abort(PyObject * self,PyObject * noargs)6719 posix_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
6728 PyDoc_STRVAR(posix_setresuid__doc__,
6729 "setresuid(ruid, euid, suid)\n\n\
6730 Set the current process's real, effective, and saved user ids.");
6731 
6732 static PyObject*
posix_setresuid(PyObject * self,PyObject * args)6733 posix_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
6746 PyDoc_STRVAR(posix_setresgid__doc__,
6747 "setresgid(rgid, egid, sgid)\n\n\
6748 Set the current process's real, effective, and saved group ids.");
6749 
6750 static PyObject*
posix_setresgid(PyObject * self,PyObject * args)6751 posix_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
6764 PyDoc_STRVAR(posix_getresuid__doc__,
6765 "getresuid() -> (ruid, euid, suid)\n\n\
6766 Get tuple of the current process's real, effective, and saved user ids.");
6767 
6768 static PyObject*
posix_getresuid(PyObject * self,PyObject * noargs)6769 posix_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
6784 PyDoc_STRVAR(posix_getresgid__doc__,
6785 "getresgid() -> (rgid, egid, sgid)\n\n\
6786 Get tuple of the current process's real, effective, and saved group ids.");
6787 
6788 static PyObject*
posix_getresgid(PyObject * self,PyObject * noargs)6789 posix_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 
6803 static 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 
7122 static int
ins(PyObject * module,char * symbol,long value)7123 ins(PyObject *module, char *symbol, long value)
7124 {
7125     return PyModule_AddIntConstant(module, symbol, value);
7126 }
7127 
7128 static int
all_ins(PyObject * d)7129 all_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 
7348 PyMODINIT_FUNC
INITFUNC(void)7349 INITFUNC(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