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) 2015, Daryl McDaniel. All rights reserved.<BR>
6     Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
7     This program and the accompanying materials are licensed and made available under
8     the terms and conditions of the BSD License that accompanies this distribution.
9     The full text of the license may be found at
10     http://opensource.org/licenses/bsd-license.
11 
12     THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13     WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 **/
15 #define PY_SSIZE_T_CLEAN
16 
17 #include "Python.h"
18 #include "structseq.h"
19 
20 #include  <stdio.h>
21 #include  <stdlib.h>
22 #include  <wchar.h>
23 #include  <sys/syslimits.h>
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 PyDoc_STRVAR(edk2__doc__,
30              "This module provides access to UEFI firmware functionality that is\n\
31              standardized by the C Standard and the POSIX standard (a thinly\n\
32              disguised Unix interface).  Refer to the library manual and\n\
33              corresponding UEFI Specification entries for more information on calls.");
34 
35 #ifndef Py_USING_UNICODE
36   /* This is used in signatures of functions. */
37   #define Py_UNICODE void
38 #endif
39 
40 #ifdef HAVE_SYS_TYPES_H
41   #include <sys/types.h>
42 #endif /* HAVE_SYS_TYPES_H */
43 
44 #ifdef HAVE_SYS_STAT_H
45   #include <sys/stat.h>
46 #endif /* HAVE_SYS_STAT_H */
47 
48 #ifdef HAVE_SYS_WAIT_H
49   #include <sys/wait.h>           /* For WNOHANG */
50 #endif
51 
52 #ifdef HAVE_SIGNAL_H
53   #include <signal.h>
54 #endif
55 
56 #ifdef HAVE_FCNTL_H
57   #include <fcntl.h>
58 #endif /* HAVE_FCNTL_H */
59 
60 #ifdef HAVE_GRP_H
61   #include <grp.h>
62 #endif
63 
64 #ifdef HAVE_SYSEXITS_H
65   #include <sysexits.h>
66 #endif /* HAVE_SYSEXITS_H */
67 
68 #ifdef HAVE_SYS_LOADAVG_H
69   #include <sys/loadavg.h>
70 #endif
71 
72 #ifdef HAVE_UTIME_H
73   #include <utime.h>
74 #endif /* HAVE_UTIME_H */
75 
76 #ifdef HAVE_SYS_UTIME_H
77   #include <sys/utime.h>
78   #define HAVE_UTIME_H /* pretend we do for the rest of this file */
79 #endif /* HAVE_SYS_UTIME_H */
80 
81 #ifdef HAVE_SYS_TIMES_H
82   #include <sys/times.h>
83 #endif /* HAVE_SYS_TIMES_H */
84 
85 #ifdef HAVE_SYS_PARAM_H
86   #include <sys/param.h>
87 #endif /* HAVE_SYS_PARAM_H */
88 
89 #ifdef HAVE_SYS_UTSNAME_H
90   #include <sys/utsname.h>
91 #endif /* HAVE_SYS_UTSNAME_H */
92 
93 #ifdef HAVE_DIRENT_H
94   #include <dirent.h>
95   #define NAMLEN(dirent) wcslen((dirent)->FileName)
96 #else
97   #define dirent direct
98   #define NAMLEN(dirent) (dirent)->d_namlen
99   #ifdef HAVE_SYS_NDIR_H
100     #include <sys/ndir.h>
101   #endif
102   #ifdef HAVE_SYS_DIR_H
103     #include <sys/dir.h>
104   #endif
105   #ifdef HAVE_NDIR_H
106     #include <ndir.h>
107   #endif
108 #endif
109 
110 #ifndef MAXPATHLEN
111   #if defined(PATH_MAX) && PATH_MAX > 1024
112     #define MAXPATHLEN PATH_MAX
113   #else
114     #define MAXPATHLEN 1024
115   #endif
116 #endif /* MAXPATHLEN */
117 
118 #define WAIT_TYPE int
119 #define WAIT_STATUS_INT(s) (s)
120 
121 /* Issue #1983: pid_t can be longer than a C long on some systems */
122 #if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
123   #define PARSE_PID "i"
124   #define PyLong_FromPid PyInt_FromLong
125   #define PyLong_AsPid PyInt_AsLong
126 #elif SIZEOF_PID_T == SIZEOF_LONG
127   #define PARSE_PID "l"
128   #define PyLong_FromPid PyInt_FromLong
129   #define PyLong_AsPid PyInt_AsLong
130 #elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
131   #define PARSE_PID "L"
132   #define PyLong_FromPid PyLong_FromLongLong
133   #define PyLong_AsPid PyInt_AsLongLong
134 #else
135   #error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)"
136 #endif /* SIZEOF_PID_T */
137 
138 /* Don't use the "_r" form if we don't need it (also, won't have a
139    prototype for it, at least on Solaris -- maybe others as well?). */
140 #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
141   #define USE_CTERMID_R
142 #endif
143 
144 #if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)
145   #define USE_TMPNAM_R
146 #endif
147 
148 /* choose the appropriate stat and fstat functions and return structs */
149 #undef STAT
150 #undef FSTAT
151 #undef STRUCT_STAT
152 #define STAT stat
153 #define FSTAT fstat
154 #define STRUCT_STAT struct stat
155 
156 /* dummy version. _PyVerify_fd() is already defined in fileobject.h */
157 #define _PyVerify_fd_dup2(A, B) (1)
158 
159 #ifndef UEFI_C_SOURCE
160 /* Return a dictionary corresponding to the POSIX environment table */
161 extern char **environ;
162 
163 static PyObject *
convertenviron(void)164 convertenviron(void)
165 {
166     PyObject *d;
167     char **e;
168     d = PyDict_New();
169     if (d == NULL)
170         return NULL;
171     if (environ == NULL)
172         return d;
173     /* This part ignores errors */
174     for (e = environ; *e != NULL; e++) {
175         PyObject *k;
176         PyObject *v;
177         char *p = strchr(*e, '=');
178         if (p == NULL)
179             continue;
180         k = PyString_FromStringAndSize(*e, (int)(p-*e));
181         if (k == NULL) {
182             PyErr_Clear();
183             continue;
184         }
185         v = PyString_FromString(p+1);
186         if (v == NULL) {
187             PyErr_Clear();
188             Py_DECREF(k);
189             continue;
190         }
191         if (PyDict_GetItem(d, k) == NULL) {
192             if (PyDict_SetItem(d, k, v) != 0)
193                 PyErr_Clear();
194         }
195         Py_DECREF(k);
196         Py_DECREF(v);
197     }
198     return d;
199 }
200 #endif  /* UEFI_C_SOURCE */
201 
202 /* Set a POSIX-specific error from errno, and return NULL */
203 
204 static PyObject *
edk2_error(void)205 edk2_error(void)
206 {
207     return PyErr_SetFromErrno(PyExc_OSError);
208 }
209 static PyObject *
edk2_error_with_filename(char * name)210 edk2_error_with_filename(char* name)
211 {
212     return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
213 }
214 
215 
216 static PyObject *
edk2_error_with_allocated_filename(char * name)217 edk2_error_with_allocated_filename(char* name)
218 {
219     PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
220     PyMem_Free(name);
221     return rc;
222 }
223 
224 /* POSIX generic methods */
225 
226 #ifndef UEFI_C_SOURCE
227   static PyObject *
edk2_fildes(PyObject * fdobj,int (* func)(int))228   edk2_fildes(PyObject *fdobj, int (*func)(int))
229   {
230       int fd;
231       int res;
232       fd = PyObject_AsFileDescriptor(fdobj);
233       if (fd < 0)
234           return NULL;
235       if (!_PyVerify_fd(fd))
236           return edk2_error();
237       Py_BEGIN_ALLOW_THREADS
238       res = (*func)(fd);
239       Py_END_ALLOW_THREADS
240       if (res < 0)
241           return edk2_error();
242       Py_INCREF(Py_None);
243       return Py_None;
244   }
245 #endif  /* UEFI_C_SOURCE */
246 
247 static PyObject *
edk2_1str(PyObject * args,char * format,int (* func)(const char *))248 edk2_1str(PyObject *args, char *format, int (*func)(const char*))
249 {
250     char *path1 = NULL;
251     int res;
252     if (!PyArg_ParseTuple(args, format,
253                           Py_FileSystemDefaultEncoding, &path1))
254         return NULL;
255     Py_BEGIN_ALLOW_THREADS
256     res = (*func)(path1);
257     Py_END_ALLOW_THREADS
258     if (res < 0)
259         return edk2_error_with_allocated_filename(path1);
260     PyMem_Free(path1);
261     Py_INCREF(Py_None);
262     return Py_None;
263 }
264 
265 static PyObject *
edk2_2str(PyObject * args,char * format,int (* func)(const char *,const char *))266 edk2_2str(PyObject *args,
267            char *format,
268            int (*func)(const char *, const char *))
269 {
270     char *path1 = NULL, *path2 = NULL;
271     int res;
272     if (!PyArg_ParseTuple(args, format,
273                           Py_FileSystemDefaultEncoding, &path1,
274                           Py_FileSystemDefaultEncoding, &path2))
275         return NULL;
276     Py_BEGIN_ALLOW_THREADS
277     res = (*func)(path1, path2);
278     Py_END_ALLOW_THREADS
279     PyMem_Free(path1);
280     PyMem_Free(path2);
281     if (res != 0)
282         /* XXX how to report both path1 and path2??? */
283         return edk2_error();
284     Py_INCREF(Py_None);
285     return Py_None;
286 }
287 
288 PyDoc_STRVAR(stat_result__doc__,
289 "stat_result: Result from stat or lstat.\n\n\
290 This object may be accessed either as a tuple of\n\
291   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
292 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
293 \n\
294 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
295 or st_flags, they are available as attributes only.\n\
296 \n\
297 See os.stat for more information.");
298 
299 static PyStructSequence_Field stat_result_fields[] = {
300     {"st_mode",    "protection bits"},
301     //{"st_ino",     "inode"},
302     //{"st_dev",     "device"},
303     //{"st_nlink",   "number of hard links"},
304     //{"st_uid",     "user ID of owner"},
305     //{"st_gid",     "group ID of owner"},
306     {"st_size",    "total size, in bytes"},
307     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
308     {NULL,   "integer time of last access"},
309     {NULL,   "integer time of last modification"},
310     {NULL,   "integer time of last change"},
311     {"st_atime",   "time of last access"},
312     {"st_mtime",   "time of last modification"},
313     {"st_ctime",   "time of last change"},
314 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
315     {"st_blksize", "blocksize for filesystem I/O"},
316 #endif
317 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
318     {"st_blocks",  "number of blocks allocated"},
319 #endif
320 #ifdef HAVE_STRUCT_STAT_ST_RDEV
321     {"st_rdev",    "device type (if inode device)"},
322 #endif
323 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
324     {"st_flags",   "user defined flags for file"},
325 #endif
326 #ifdef HAVE_STRUCT_STAT_ST_GEN
327     {"st_gen",    "generation number"},
328 #endif
329 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
330     {"st_birthtime",   "time of creation"},
331 #endif
332     {0}
333 };
334 
335 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
336 #define ST_BLKSIZE_IDX 8
337 #else
338 #define ST_BLKSIZE_IDX 12
339 #endif
340 
341 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
342 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
343 #else
344 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
345 #endif
346 
347 #ifdef HAVE_STRUCT_STAT_ST_RDEV
348 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
349 #else
350 #define ST_RDEV_IDX ST_BLOCKS_IDX
351 #endif
352 
353 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
354 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
355 #else
356 #define ST_FLAGS_IDX ST_RDEV_IDX
357 #endif
358 
359 #ifdef HAVE_STRUCT_STAT_ST_GEN
360 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
361 #else
362 #define ST_GEN_IDX ST_FLAGS_IDX
363 #endif
364 
365 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
366 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
367 #else
368 #define ST_BIRTHTIME_IDX ST_GEN_IDX
369 #endif
370 
371 static PyStructSequence_Desc stat_result_desc = {
372     "stat_result", /* name */
373     stat_result__doc__, /* doc */
374     stat_result_fields,
375     10
376 };
377 
378 #ifndef UEFI_C_SOURCE   /* Not in UEFI */
379 PyDoc_STRVAR(statvfs_result__doc__,
380 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
381 This object may be accessed either as a tuple of\n\
382   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
383 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
384 \n\
385 See os.statvfs for more information.");
386 
387 static PyStructSequence_Field statvfs_result_fields[] = {
388     {"f_bsize",  },
389     {"f_frsize", },
390     {"f_blocks", },
391     {"f_bfree",  },
392     {"f_bavail", },
393     {"f_files",  },
394     {"f_ffree",  },
395     {"f_favail", },
396     {"f_flag",   },
397     {"f_namemax",},
398     {0}
399 };
400 
401 static PyStructSequence_Desc statvfs_result_desc = {
402     "statvfs_result", /* name */
403     statvfs_result__doc__, /* doc */
404     statvfs_result_fields,
405     10
406 };
407 
408 static PyTypeObject StatVFSResultType;
409 #endif
410 
411 static int initialized;
412 static PyTypeObject StatResultType;
413 static newfunc structseq_new;
414 
415 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)416 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
417 {
418     PyStructSequence *result;
419     int i;
420 
421     result = (PyStructSequence*)structseq_new(type, args, kwds);
422     if (!result)
423         return NULL;
424     /* If we have been initialized from a tuple,
425        st_?time might be set to None. Initialize it
426        from the int slots.  */
427     for (i = 7; i <= 9; i++) {
428         if (result->ob_item[i+3] == Py_None) {
429             Py_DECREF(Py_None);
430             Py_INCREF(result->ob_item[i]);
431             result->ob_item[i+3] = result->ob_item[i];
432         }
433     }
434     return (PyObject*)result;
435 }
436 
437 
438 
439 /* If true, st_?time is float. */
440 #if defined(UEFI_C_SOURCE)
441   static int _stat_float_times = 0;
442 #else
443   static int _stat_float_times = 1;
444 
445 PyDoc_STRVAR(stat_float_times__doc__,
446 "stat_float_times([newval]) -> oldval\n\n\
447 Determine whether os.[lf]stat represents time stamps as float objects.\n\
448 If newval is True, future calls to stat() return floats, if it is False,\n\
449 future calls return ints. \n\
450 If newval is omitted, return the current setting.\n");
451 
452 static PyObject*
stat_float_times(PyObject * self,PyObject * args)453 stat_float_times(PyObject* self, PyObject *args)
454 {
455     int newval = -1;
456 
457     if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
458         return NULL;
459     if (newval == -1)
460         /* Return old value */
461         return PyBool_FromLong(_stat_float_times);
462     _stat_float_times = newval;
463     Py_INCREF(Py_None);
464     return Py_None;
465 }
466 #endif  /* UEFI_C_SOURCE */
467 
468 static void
fill_time(PyObject * v,int index,time_t sec,unsigned long nsec)469 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
470 {
471     PyObject *fval,*ival;
472 #if SIZEOF_TIME_T > SIZEOF_LONG
473     ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
474 #else
475     ival = PyInt_FromLong((long)sec);
476 #endif
477     if (!ival)
478         return;
479     if (_stat_float_times) {
480         fval = PyFloat_FromDouble(sec + 1e-9*nsec);
481     } else {
482         fval = ival;
483         Py_INCREF(fval);
484     }
485     PyStructSequence_SET_ITEM(v, index, ival);
486     PyStructSequence_SET_ITEM(v, index+3, fval);
487 }
488 
489 /* pack a system stat C structure into the Python stat tuple
490    (used by edk2_stat() and edk2_fstat()) */
491 static PyObject*
_pystat_fromstructstat(STRUCT_STAT * st)492 _pystat_fromstructstat(STRUCT_STAT *st)
493 {
494     unsigned long ansec, mnsec, cnsec;
495     PyObject *v = PyStructSequence_New(&StatResultType);
496     if (v == NULL)
497         return NULL;
498 
499     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
500     PyStructSequence_SET_ITEM(v, 1,
501                               PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
502 
503     ansec = mnsec = cnsec = 0;
504     /* The index used by fill_time is the index of the integer time.
505        fill_time will add 3 to the index to get the floating time index.
506     */
507     fill_time(v, 2, st->st_atime, ansec);
508     fill_time(v, 3, st->st_mtime, mnsec);
509     fill_time(v, 4, st->st_mtime, cnsec);
510 
511 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
512     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
513                               PyInt_FromLong((long)st->st_blksize));
514 #endif
515 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
516     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
517                               PyInt_FromLong((long)st->st_blocks));
518 #endif
519 #ifdef HAVE_STRUCT_STAT_ST_RDEV
520     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
521                               PyInt_FromLong((long)st->st_rdev));
522 #endif
523 #ifdef HAVE_STRUCT_STAT_ST_GEN
524     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
525                               PyInt_FromLong((long)st->st_gen));
526 #endif
527 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
528     {
529       PyObject *val;
530       unsigned long bsec,bnsec;
531       bsec = (long)st->st_birthtime;
532 #ifdef HAVE_STAT_TV_NSEC2
533       bnsec = st->st_birthtimespec.tv_nsec;
534 #else
535       bnsec = 0;
536 #endif
537       if (_stat_float_times) {
538         val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
539       } else {
540         val = PyInt_FromLong((long)bsec);
541       }
542       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
543                                 val);
544     }
545 #endif
546 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
547     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
548                               PyInt_FromLong((long)st->st_flags));
549 #endif
550 
551     if (PyErr_Occurred()) {
552         Py_DECREF(v);
553         return NULL;
554     }
555 
556     return v;
557 }
558 
559 static PyObject *
edk2_do_stat(PyObject * self,PyObject * args,char * format,int (* statfunc)(const char *,STRUCT_STAT *),char * wformat,int (* wstatfunc)(const Py_UNICODE *,STRUCT_STAT *))560 edk2_do_stat(PyObject *self, PyObject *args,
561               char *format,
562               int (*statfunc)(const char *, STRUCT_STAT *),
563               char *wformat,
564               int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
565 {
566     STRUCT_STAT st;
567     char *path = NULL;          /* pass this to stat; do not free() it */
568     char *pathfree = NULL;  /* this memory must be free'd */
569     int res;
570     PyObject *result;
571 
572     if (!PyArg_ParseTuple(args, format,
573                           Py_FileSystemDefaultEncoding, &path))
574         return NULL;
575     pathfree = path;
576 
577     Py_BEGIN_ALLOW_THREADS
578     res = (*statfunc)(path, &st);
579     Py_END_ALLOW_THREADS
580 
581     if (res != 0) {
582         result = edk2_error_with_filename(pathfree);
583     }
584     else
585         result = _pystat_fromstructstat(&st);
586 
587     PyMem_Free(pathfree);
588     return result;
589 }
590 
591 /* POSIX methods */
592 
593 PyDoc_STRVAR(edk2_access__doc__,
594 "access(path, mode) -> True if granted, False otherwise\n\n\
595 Use the real uid/gid to test for access to a path.  Note that most\n\
596 operations will use the effective uid/gid, therefore this routine can\n\
597 be used in a suid/sgid environment to test if the invoking user has the\n\
598 specified access to the path.  The mode argument can be F_OK to test\n\
599 existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
600 
601 static PyObject *
edk2_access(PyObject * self,PyObject * args)602 edk2_access(PyObject *self, PyObject *args)
603 {
604     char *path;
605     int mode;
606 
607     int res;
608     if (!PyArg_ParseTuple(args, "eti:access",
609                           Py_FileSystemDefaultEncoding, &path, &mode))
610         return NULL;
611     Py_BEGIN_ALLOW_THREADS
612     res = access(path, mode);
613     Py_END_ALLOW_THREADS
614     PyMem_Free(path);
615     return PyBool_FromLong(res == 0);
616 }
617 
618 #ifndef F_OK
619   #define F_OK 0
620 #endif
621 #ifndef R_OK
622   #define R_OK 4
623 #endif
624 #ifndef W_OK
625   #define W_OK 2
626 #endif
627 #ifndef X_OK
628   #define X_OK 1
629 #endif
630 
631 PyDoc_STRVAR(edk2_chdir__doc__,
632 "chdir(path)\n\n\
633 Change the current working directory to the specified path.");
634 
635 static PyObject *
edk2_chdir(PyObject * self,PyObject * args)636 edk2_chdir(PyObject *self, PyObject *args)
637 {
638     return edk2_1str(args, "et:chdir", chdir);
639 }
640 
641 PyDoc_STRVAR(edk2_chmod__doc__,
642 "chmod(path, mode)\n\n\
643 Change the access permissions of a file.");
644 
645 static PyObject *
edk2_chmod(PyObject * self,PyObject * args)646 edk2_chmod(PyObject *self, PyObject *args)
647 {
648     char *path = NULL;
649     int i;
650     int res;
651     if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
652                           &path, &i))
653         return NULL;
654     Py_BEGIN_ALLOW_THREADS
655     res = chmod(path, i);
656     Py_END_ALLOW_THREADS
657     if (res < 0)
658         return edk2_error_with_allocated_filename(path);
659     PyMem_Free(path);
660     Py_INCREF(Py_None);
661     return Py_None;
662 }
663 
664 #ifdef HAVE_FCHMOD
665 PyDoc_STRVAR(edk2_fchmod__doc__,
666 "fchmod(fd, mode)\n\n\
667 Change the access permissions of the file given by file\n\
668 descriptor fd.");
669 
670 static PyObject *
edk2_fchmod(PyObject * self,PyObject * args)671 edk2_fchmod(PyObject *self, PyObject *args)
672 {
673     int fd, mode, res;
674     if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
675         return NULL;
676     Py_BEGIN_ALLOW_THREADS
677     res = fchmod(fd, mode);
678     Py_END_ALLOW_THREADS
679     if (res < 0)
680         return edk2_error();
681     Py_RETURN_NONE;
682 }
683 #endif /* HAVE_FCHMOD */
684 
685 #ifdef HAVE_LCHMOD
686 PyDoc_STRVAR(edk2_lchmod__doc__,
687 "lchmod(path, mode)\n\n\
688 Change the access permissions of a file. If path is a symlink, this\n\
689 affects the link itself rather than the target.");
690 
691 static PyObject *
edk2_lchmod(PyObject * self,PyObject * args)692 edk2_lchmod(PyObject *self, PyObject *args)
693 {
694     char *path = NULL;
695     int i;
696     int res;
697     if (!PyArg_ParseTuple(args, "eti:lchmod", Py_FileSystemDefaultEncoding,
698                           &path, &i))
699         return NULL;
700     Py_BEGIN_ALLOW_THREADS
701     res = lchmod(path, i);
702     Py_END_ALLOW_THREADS
703     if (res < 0)
704         return edk2_error_with_allocated_filename(path);
705     PyMem_Free(path);
706     Py_RETURN_NONE;
707 }
708 #endif /* HAVE_LCHMOD */
709 
710 
711 #ifdef HAVE_CHFLAGS
712 PyDoc_STRVAR(edk2_chflags__doc__,
713 "chflags(path, flags)\n\n\
714 Set file flags.");
715 
716 static PyObject *
edk2_chflags(PyObject * self,PyObject * args)717 edk2_chflags(PyObject *self, PyObject *args)
718 {
719     char *path;
720     unsigned long flags;
721     int res;
722     if (!PyArg_ParseTuple(args, "etk:chflags",
723                           Py_FileSystemDefaultEncoding, &path, &flags))
724         return NULL;
725     Py_BEGIN_ALLOW_THREADS
726     res = chflags(path, flags);
727     Py_END_ALLOW_THREADS
728     if (res < 0)
729         return edk2_error_with_allocated_filename(path);
730     PyMem_Free(path);
731     Py_INCREF(Py_None);
732     return Py_None;
733 }
734 #endif /* HAVE_CHFLAGS */
735 
736 #ifdef HAVE_LCHFLAGS
737 PyDoc_STRVAR(edk2_lchflags__doc__,
738 "lchflags(path, flags)\n\n\
739 Set file flags.\n\
740 This function will not follow symbolic links.");
741 
742 static PyObject *
edk2_lchflags(PyObject * self,PyObject * args)743 edk2_lchflags(PyObject *self, PyObject *args)
744 {
745     char *path;
746     unsigned long flags;
747     int res;
748     if (!PyArg_ParseTuple(args, "etk:lchflags",
749                           Py_FileSystemDefaultEncoding, &path, &flags))
750         return NULL;
751     Py_BEGIN_ALLOW_THREADS
752     res = lchflags(path, flags);
753     Py_END_ALLOW_THREADS
754     if (res < 0)
755         return edk2_error_with_allocated_filename(path);
756     PyMem_Free(path);
757     Py_INCREF(Py_None);
758     return Py_None;
759 }
760 #endif /* HAVE_LCHFLAGS */
761 
762 #ifdef HAVE_CHROOT
763 PyDoc_STRVAR(edk2_chroot__doc__,
764 "chroot(path)\n\n\
765 Change root directory to path.");
766 
767 static PyObject *
edk2_chroot(PyObject * self,PyObject * args)768 edk2_chroot(PyObject *self, PyObject *args)
769 {
770     return edk2_1str(args, "et:chroot", chroot);
771 }
772 #endif
773 
774 #ifdef HAVE_FSYNC
775 PyDoc_STRVAR(edk2_fsync__doc__,
776 "fsync(fildes)\n\n\
777 force write of file with filedescriptor to disk.");
778 
779 static PyObject *
edk2_fsync(PyObject * self,PyObject * fdobj)780 edk2_fsync(PyObject *self, PyObject *fdobj)
781 {
782     return edk2_fildes(fdobj, fsync);
783 }
784 #endif /* HAVE_FSYNC */
785 
786 #ifdef HAVE_FDATASYNC
787 
788 #ifdef __hpux
789 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
790 #endif
791 
792 PyDoc_STRVAR(edk2_fdatasync__doc__,
793 "fdatasync(fildes)\n\n\
794 force write of file with filedescriptor to disk.\n\
795  does not force update of metadata.");
796 
797 static PyObject *
edk2_fdatasync(PyObject * self,PyObject * fdobj)798 edk2_fdatasync(PyObject *self, PyObject *fdobj)
799 {
800     return edk2_fildes(fdobj, fdatasync);
801 }
802 #endif /* HAVE_FDATASYNC */
803 
804 
805 #ifdef HAVE_CHOWN
806 PyDoc_STRVAR(edk2_chown__doc__,
807 "chown(path, uid, gid)\n\n\
808 Change the owner and group id of path to the numeric uid and gid.");
809 
810 static PyObject *
edk2_chown(PyObject * self,PyObject * args)811 edk2_chown(PyObject *self, PyObject *args)
812 {
813     char *path = NULL;
814     long uid, gid;
815     int res;
816     if (!PyArg_ParseTuple(args, "etll:chown",
817                           Py_FileSystemDefaultEncoding, &path,
818                           &uid, &gid))
819         return NULL;
820     Py_BEGIN_ALLOW_THREADS
821     res = chown(path, (uid_t) uid, (gid_t) gid);
822     Py_END_ALLOW_THREADS
823     if (res < 0)
824         return edk2_error_with_allocated_filename(path);
825     PyMem_Free(path);
826     Py_INCREF(Py_None);
827     return Py_None;
828 }
829 #endif /* HAVE_CHOWN */
830 
831 #ifdef HAVE_FCHOWN
832 PyDoc_STRVAR(edk2_fchown__doc__,
833 "fchown(fd, uid, gid)\n\n\
834 Change the owner and group id of the file given by file descriptor\n\
835 fd to the numeric uid and gid.");
836 
837 static PyObject *
edk2_fchown(PyObject * self,PyObject * args)838 edk2_fchown(PyObject *self, PyObject *args)
839 {
840     int fd;
841     long uid, gid;
842     int res;
843     if (!PyArg_ParseTuple(args, "ill:chown", &fd, &uid, &gid))
844         return NULL;
845     Py_BEGIN_ALLOW_THREADS
846     res = fchown(fd, (uid_t) uid, (gid_t) gid);
847     Py_END_ALLOW_THREADS
848     if (res < 0)
849         return edk2_error();
850     Py_RETURN_NONE;
851 }
852 #endif /* HAVE_FCHOWN */
853 
854 #ifdef HAVE_LCHOWN
855 PyDoc_STRVAR(edk2_lchown__doc__,
856 "lchown(path, uid, gid)\n\n\
857 Change the owner and group id of path to the numeric uid and gid.\n\
858 This function will not follow symbolic links.");
859 
860 static PyObject *
edk2_lchown(PyObject * self,PyObject * args)861 edk2_lchown(PyObject *self, PyObject *args)
862 {
863     char *path = NULL;
864     long uid, gid;
865     int res;
866     if (!PyArg_ParseTuple(args, "etll:lchown",
867                           Py_FileSystemDefaultEncoding, &path,
868                           &uid, &gid))
869         return NULL;
870     Py_BEGIN_ALLOW_THREADS
871     res = lchown(path, (uid_t) uid, (gid_t) gid);
872     Py_END_ALLOW_THREADS
873     if (res < 0)
874         return edk2_error_with_allocated_filename(path);
875     PyMem_Free(path);
876     Py_INCREF(Py_None);
877     return Py_None;
878 }
879 #endif /* HAVE_LCHOWN */
880 
881 
882 #ifdef HAVE_GETCWD
883 PyDoc_STRVAR(edk2_getcwd__doc__,
884 "getcwd() -> path\n\n\
885 Return a string representing the current working directory.");
886 
887 static PyObject *
edk2_getcwd(PyObject * self,PyObject * noargs)888 edk2_getcwd(PyObject *self, PyObject *noargs)
889 {
890     int bufsize_incr = 1024;
891     int bufsize = 0;
892     char *tmpbuf = NULL;
893     char *res = NULL;
894     PyObject *dynamic_return;
895 
896     Py_BEGIN_ALLOW_THREADS
897     do {
898         bufsize = bufsize + bufsize_incr;
899         tmpbuf = malloc(bufsize);
900         if (tmpbuf == NULL) {
901             break;
902         }
903         res = getcwd(tmpbuf, bufsize);
904         if (res == NULL) {
905             free(tmpbuf);
906         }
907     } while ((res == NULL) && (errno == ERANGE));
908     Py_END_ALLOW_THREADS
909 
910     if (res == NULL)
911         return edk2_error();
912 
913     dynamic_return = PyString_FromString(tmpbuf);
914     free(tmpbuf);
915 
916     return dynamic_return;
917 }
918 
919 #ifdef Py_USING_UNICODE
920 PyDoc_STRVAR(edk2_getcwdu__doc__,
921 "getcwdu() -> path\n\n\
922 Return a unicode string representing the current working directory.");
923 
924 static PyObject *
edk2_getcwdu(PyObject * self,PyObject * noargs)925 edk2_getcwdu(PyObject *self, PyObject *noargs)
926 {
927     char buf[1026];
928     char *res;
929 
930     Py_BEGIN_ALLOW_THREADS
931     res = getcwd(buf, sizeof buf);
932     Py_END_ALLOW_THREADS
933     if (res == NULL)
934         return edk2_error();
935     return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict");
936 }
937 #endif /* Py_USING_UNICODE */
938 #endif /* HAVE_GETCWD */
939 
940 
941 PyDoc_STRVAR(edk2_listdir__doc__,
942 "listdir(path) -> list_of_strings\n\n\
943 Return a list containing the names of the entries in the directory.\n\
944 \n\
945     path: path of directory to list\n\
946 \n\
947 The list is in arbitrary order.  It does not include the special\n\
948 entries '.' and '..' even if they are present in the directory.");
949 
950 static PyObject *
edk2_listdir(PyObject * self,PyObject * args)951 edk2_listdir(PyObject *self, PyObject *args)
952 {
953     /* XXX Should redo this putting the (now four) versions of opendir
954        in separate files instead of having them all here... */
955 
956     char           *name            = NULL;
957     char           *MBname;
958     PyObject       *d, *v;
959     DIR            *dirp;
960     struct dirent  *ep;
961     int             arg_is_unicode  = 1;
962 
963     errno = 0;
964     if (!PyArg_ParseTuple(args, "U:listdir", &v)) {
965         arg_is_unicode = 0;
966         PyErr_Clear();
967     }
968     if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name))
969         return NULL;
970     Py_BEGIN_ALLOW_THREADS
971     dirp = opendir(name);
972     Py_END_ALLOW_THREADS
973     if (dirp == NULL) {
974         return edk2_error_with_allocated_filename(name);
975     }
976     if ((d = PyList_New(0)) == NULL) {
977         Py_BEGIN_ALLOW_THREADS
978         closedir(dirp);
979         Py_END_ALLOW_THREADS
980         PyMem_Free(name);
981         return NULL;
982     }
983     if((MBname = malloc(NAME_MAX)) == NULL) {
984       Py_BEGIN_ALLOW_THREADS
985       closedir(dirp);
986       Py_END_ALLOW_THREADS
987       Py_DECREF(d);
988       PyMem_Free(name);
989       return NULL;
990     }
991     for (;;) {
992         errno = 0;
993         Py_BEGIN_ALLOW_THREADS
994         ep = readdir(dirp);
995         Py_END_ALLOW_THREADS
996         if (ep == NULL) {
997             if ((errno == 0) || (errno == EISDIR)) {
998                 break;
999             } else {
1000                 Py_BEGIN_ALLOW_THREADS
1001                 closedir(dirp);
1002                 Py_END_ALLOW_THREADS
1003                 Py_DECREF(d);
1004                 return edk2_error_with_allocated_filename(name);
1005             }
1006         }
1007         if (ep->FileName[0] == L'.' &&
1008             (NAMLEN(ep) == 1 ||
1009              (ep->FileName[1] == L'.' && NAMLEN(ep) == 2)))
1010             continue;
1011         if(wcstombs(MBname, ep->FileName, NAME_MAX) == -1) {
1012           free(MBname);
1013           Py_BEGIN_ALLOW_THREADS
1014           closedir(dirp);
1015           Py_END_ALLOW_THREADS
1016           Py_DECREF(d);
1017           PyMem_Free(name);
1018           return NULL;
1019         }
1020         v = PyString_FromStringAndSize(MBname, strlen(MBname));
1021         if (v == NULL) {
1022             Py_DECREF(d);
1023             d = NULL;
1024             break;
1025         }
1026 #ifdef Py_USING_UNICODE
1027         if (arg_is_unicode) {
1028             PyObject *w;
1029 
1030             w = PyUnicode_FromEncodedObject(v,
1031                                             Py_FileSystemDefaultEncoding,
1032                                             "strict");
1033             if (w != NULL) {
1034                 Py_DECREF(v);
1035                 v = w;
1036             }
1037             else {
1038                 /* fall back to the original byte string, as
1039                    discussed in patch #683592 */
1040                 PyErr_Clear();
1041             }
1042         }
1043 #endif
1044         if (PyList_Append(d, v) != 0) {
1045             Py_DECREF(v);
1046             Py_DECREF(d);
1047             d = NULL;
1048             break;
1049         }
1050         Py_DECREF(v);
1051     }
1052     Py_BEGIN_ALLOW_THREADS
1053     closedir(dirp);
1054     Py_END_ALLOW_THREADS
1055     PyMem_Free(name);
1056     if(MBname != NULL) {
1057       free(MBname);
1058     }
1059 
1060     return d;
1061 
1062 }  /* end of edk2_listdir */
1063 
1064 PyDoc_STRVAR(edk2_mkdir__doc__,
1065 "mkdir(path [, mode=0777])\n\n\
1066 Create a directory.");
1067 
1068 static PyObject *
edk2_mkdir(PyObject * self,PyObject * args)1069 edk2_mkdir(PyObject *self, PyObject *args)
1070 {
1071     int res;
1072     char *path = NULL;
1073     int mode = 0777;
1074 
1075     if (!PyArg_ParseTuple(args, "et|i:mkdir",
1076                           Py_FileSystemDefaultEncoding, &path, &mode))
1077         return NULL;
1078     Py_BEGIN_ALLOW_THREADS
1079     res = mkdir(path, mode);
1080     Py_END_ALLOW_THREADS
1081     if (res < 0)
1082         return edk2_error_with_allocated_filename(path);
1083     PyMem_Free(path);
1084     Py_INCREF(Py_None);
1085     return Py_None;
1086 }
1087 
1088 
1089 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
1090 #if defined(HAVE_SYS_RESOURCE_H)
1091 #include <sys/resource.h>
1092 #endif
1093 
1094 
1095 #ifdef HAVE_NICE
1096 PyDoc_STRVAR(edk2_nice__doc__,
1097 "nice(inc) -> new_priority\n\n\
1098 Decrease the priority of process by inc and return the new priority.");
1099 
1100 static PyObject *
edk2_nice(PyObject * self,PyObject * args)1101 edk2_nice(PyObject *self, PyObject *args)
1102 {
1103     int increment, value;
1104 
1105     if (!PyArg_ParseTuple(args, "i:nice", &increment))
1106         return NULL;
1107 
1108     /* There are two flavours of 'nice': one that returns the new
1109        priority (as required by almost all standards out there) and the
1110        Linux/FreeBSD/BSDI one, which returns '0' on success and advices
1111        the use of getpriority() to get the new priority.
1112 
1113        If we are of the nice family that returns the new priority, we
1114        need to clear errno before the call, and check if errno is filled
1115        before calling edk2_error() on a returnvalue of -1, because the
1116        -1 may be the actual new priority! */
1117 
1118     errno = 0;
1119     value = nice(increment);
1120 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
1121     if (value == 0)
1122         value = getpriority(PRIO_PROCESS, 0);
1123 #endif
1124     if (value == -1 && errno != 0)
1125         /* either nice() or getpriority() returned an error */
1126         return edk2_error();
1127     return PyInt_FromLong((long) value);
1128 }
1129 #endif /* HAVE_NICE */
1130 
1131 PyDoc_STRVAR(edk2_rename__doc__,
1132 "rename(old, new)\n\n\
1133 Rename a file or directory.");
1134 
1135 static PyObject *
edk2_rename(PyObject * self,PyObject * args)1136 edk2_rename(PyObject *self, PyObject *args)
1137 {
1138     return edk2_2str(args, "etet:rename", rename);
1139 }
1140 
1141 
1142 PyDoc_STRVAR(edk2_rmdir__doc__,
1143 "rmdir(path)\n\n\
1144 Remove a directory.");
1145 
1146 static PyObject *
edk2_rmdir(PyObject * self,PyObject * args)1147 edk2_rmdir(PyObject *self, PyObject *args)
1148 {
1149     return edk2_1str(args, "et:rmdir", rmdir);
1150 }
1151 
1152 
1153 PyDoc_STRVAR(edk2_stat__doc__,
1154 "stat(path) -> stat result\n\n\
1155 Perform a stat system call on the given path.");
1156 
1157 static PyObject *
edk2_stat(PyObject * self,PyObject * args)1158 edk2_stat(PyObject *self, PyObject *args)
1159 {
1160     return edk2_do_stat(self, args, "et:stat", STAT, NULL, NULL);
1161 }
1162 
1163 
1164 #ifdef HAVE_SYSTEM
1165 PyDoc_STRVAR(edk2_system__doc__,
1166 "system(command) -> exit_status\n\n\
1167 Execute the command (a string) in a subshell.");
1168 
1169 static PyObject *
edk2_system(PyObject * self,PyObject * args)1170 edk2_system(PyObject *self, PyObject *args)
1171 {
1172     char *command;
1173     long sts;
1174     if (!PyArg_ParseTuple(args, "s:system", &command))
1175         return NULL;
1176     Py_BEGIN_ALLOW_THREADS
1177     sts = system(command);
1178     Py_END_ALLOW_THREADS
1179     return PyInt_FromLong(sts);
1180 }
1181 #endif
1182 
1183 
1184 PyDoc_STRVAR(edk2_umask__doc__,
1185 "umask(new_mask) -> old_mask\n\n\
1186 Set the current numeric umask and return the previous umask.");
1187 
1188 static PyObject *
edk2_umask(PyObject * self,PyObject * args)1189 edk2_umask(PyObject *self, PyObject *args)
1190 {
1191     int i;
1192     if (!PyArg_ParseTuple(args, "i:umask", &i))
1193         return NULL;
1194     i = (int)umask(i);
1195     if (i < 0)
1196         return edk2_error();
1197     return PyInt_FromLong((long)i);
1198 }
1199 
1200 
1201 PyDoc_STRVAR(edk2_unlink__doc__,
1202 "unlink(path)\n\n\
1203 Remove a file (same as remove(path)).");
1204 
1205 PyDoc_STRVAR(edk2_remove__doc__,
1206 "remove(path)\n\n\
1207 Remove a file (same as unlink(path)).");
1208 
1209 static PyObject *
edk2_unlink(PyObject * self,PyObject * args)1210 edk2_unlink(PyObject *self, PyObject *args)
1211 {
1212     return edk2_1str(args, "et:remove", unlink);
1213 }
1214 
1215 
1216 static int
extract_time(PyObject * t,time_t * sec,long * usec)1217 extract_time(PyObject *t, time_t* sec, long* usec)
1218 {
1219     time_t intval;
1220     if (PyFloat_Check(t)) {
1221         double tval = PyFloat_AsDouble(t);
1222         PyObject *intobj = PyNumber_Long(t);
1223         if (!intobj)
1224             return -1;
1225 #if SIZEOF_TIME_T > SIZEOF_LONG
1226         intval = PyInt_AsUnsignedLongLongMask(intobj);
1227 #else
1228         intval = PyInt_AsLong(intobj);
1229 #endif
1230         Py_DECREF(intobj);
1231         if (intval == -1 && PyErr_Occurred())
1232             return -1;
1233         *sec = intval;
1234         *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
1235         if (*usec < 0)
1236             /* If rounding gave us a negative number,
1237                truncate.  */
1238             *usec = 0;
1239         return 0;
1240     }
1241 #if SIZEOF_TIME_T > SIZEOF_LONG
1242     intval = PyInt_AsUnsignedLongLongMask(t);
1243 #else
1244     intval = PyInt_AsLong(t);
1245 #endif
1246     if (intval == -1 && PyErr_Occurred())
1247         return -1;
1248     *sec = intval;
1249     *usec = 0;
1250     return 0;
1251 }
1252 
1253 PyDoc_STRVAR(edk2_utime__doc__,
1254 "utime(path, (atime, mtime))\n\
1255 utime(path, None)\n\n\
1256 Set the access and modified time of the file to the given values.  If the\n\
1257 second form is used, set the access and modified times to the current time.");
1258 
1259 static PyObject *
edk2_utime(PyObject * self,PyObject * args)1260 edk2_utime(PyObject *self, PyObject *args)
1261 {
1262     char *path = NULL;
1263     time_t atime, mtime;
1264     long ausec, musec;
1265     int res;
1266     PyObject* arg;
1267 
1268 #if defined(HAVE_UTIMES)
1269     struct timeval buf[2];
1270 #define ATIME buf[0].tv_sec
1271 #define MTIME buf[1].tv_sec
1272 #elif defined(HAVE_UTIME_H)
1273 /* XXX should define struct utimbuf instead, above */
1274     struct utimbuf buf;
1275 #define ATIME buf.actime
1276 #define MTIME buf.modtime
1277 #define UTIME_ARG &buf
1278 #else /* HAVE_UTIMES */
1279     time_t buf[2];
1280 #define ATIME buf[0]
1281 #define MTIME buf[1]
1282 #define UTIME_ARG buf
1283 #endif /* HAVE_UTIMES */
1284 
1285 
1286     if (!PyArg_ParseTuple(args, "etO:utime",
1287                           Py_FileSystemDefaultEncoding, &path, &arg))
1288         return NULL;
1289     if (arg == Py_None) {
1290         /* optional time values not given */
1291         Py_BEGIN_ALLOW_THREADS
1292         res = utime(path, NULL);
1293         Py_END_ALLOW_THREADS
1294     }
1295     else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
1296         PyErr_SetString(PyExc_TypeError,
1297                         "utime() arg 2 must be a tuple (atime, mtime)");
1298         PyMem_Free(path);
1299         return NULL;
1300     }
1301     else {
1302         if (extract_time(PyTuple_GET_ITEM(arg, 0),
1303                          &atime, &ausec) == -1) {
1304             PyMem_Free(path);
1305             return NULL;
1306         }
1307         if (extract_time(PyTuple_GET_ITEM(arg, 1),
1308                          &mtime, &musec) == -1) {
1309             PyMem_Free(path);
1310             return NULL;
1311         }
1312         ATIME = atime;
1313         MTIME = mtime;
1314 #ifdef HAVE_UTIMES
1315         buf[0].tv_usec = ausec;
1316         buf[1].tv_usec = musec;
1317         Py_BEGIN_ALLOW_THREADS
1318         res = utimes(path, buf);
1319         Py_END_ALLOW_THREADS
1320 #else
1321         Py_BEGIN_ALLOW_THREADS
1322         res = utime(path, UTIME_ARG);
1323         Py_END_ALLOW_THREADS
1324 #endif /* HAVE_UTIMES */
1325     }
1326     if (res < 0) {
1327         return edk2_error_with_allocated_filename(path);
1328     }
1329     PyMem_Free(path);
1330     Py_INCREF(Py_None);
1331     return Py_None;
1332 #undef UTIME_ARG
1333 #undef ATIME
1334 #undef MTIME
1335 }
1336 
1337 
1338 /* Process operations */
1339 
1340 PyDoc_STRVAR(edk2__exit__doc__,
1341 "_exit(status)\n\n\
1342 Exit to the system with specified status, without normal exit processing.");
1343 
1344 static PyObject *
edk2__exit(PyObject * self,PyObject * args)1345 edk2__exit(PyObject *self, PyObject *args)
1346 {
1347     int sts;
1348     if (!PyArg_ParseTuple(args, "i:_exit", &sts))
1349         return NULL;
1350     _Exit(sts);
1351     return NULL; /* Make gcc -Wall happy */
1352 }
1353 
1354 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
1355 static void
free_string_array(char ** array,Py_ssize_t count)1356 free_string_array(char **array, Py_ssize_t count)
1357 {
1358     Py_ssize_t i;
1359     for (i = 0; i < count; i++)
1360         PyMem_Free(array[i]);
1361     PyMem_DEL(array);
1362 }
1363 #endif
1364 
1365 
1366 #ifdef HAVE_EXECV
1367 PyDoc_STRVAR(edk2_execv__doc__,
1368 "execv(path, args)\n\n\
1369 Execute an executable path with arguments, replacing current process.\n\
1370 \n\
1371     path: path of executable file\n\
1372     args: tuple or list of strings");
1373 
1374 static PyObject *
edk2_execv(PyObject * self,PyObject * args)1375 edk2_execv(PyObject *self, PyObject *args)
1376 {
1377     char *path;
1378     PyObject *argv;
1379     char **argvlist;
1380     Py_ssize_t i, argc;
1381     PyObject *(*getitem)(PyObject *, Py_ssize_t);
1382 
1383     /* execv has two arguments: (path, argv), where
1384        argv is a list or tuple of strings. */
1385 
1386     if (!PyArg_ParseTuple(args, "etO:execv",
1387                           Py_FileSystemDefaultEncoding,
1388                           &path, &argv))
1389         return NULL;
1390     if (PyList_Check(argv)) {
1391         argc = PyList_Size(argv);
1392         getitem = PyList_GetItem;
1393     }
1394     else if (PyTuple_Check(argv)) {
1395         argc = PyTuple_Size(argv);
1396         getitem = PyTuple_GetItem;
1397     }
1398     else {
1399         PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
1400         PyMem_Free(path);
1401         return NULL;
1402     }
1403     if (argc < 1) {
1404         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
1405         PyMem_Free(path);
1406         return NULL;
1407     }
1408 
1409     argvlist = PyMem_NEW(char *, argc+1);
1410     if (argvlist == NULL) {
1411         PyMem_Free(path);
1412         return PyErr_NoMemory();
1413     }
1414     for (i = 0; i < argc; i++) {
1415         if (!PyArg_Parse((*getitem)(argv, i), "et",
1416                          Py_FileSystemDefaultEncoding,
1417                          &argvlist[i])) {
1418             free_string_array(argvlist, i);
1419             PyErr_SetString(PyExc_TypeError,
1420                             "execv() arg 2 must contain only strings");
1421             PyMem_Free(path);
1422             return NULL;
1423 
1424         }
1425     }
1426     argvlist[argc] = NULL;
1427 
1428     execv(path, argvlist);
1429 
1430     /* If we get here it's definitely an error */
1431 
1432     free_string_array(argvlist, argc);
1433     PyMem_Free(path);
1434     return edk2_error();
1435 }
1436 
1437 
1438 PyDoc_STRVAR(edk2_execve__doc__,
1439 "execve(path, args, env)\n\n\
1440 Execute a path with arguments and environment, replacing current process.\n\
1441 \n\
1442     path: path of executable file\n\
1443     args: tuple or list of arguments\n\
1444     env: dictionary of strings mapping to strings");
1445 
1446 static PyObject *
edk2_execve(PyObject * self,PyObject * args)1447 edk2_execve(PyObject *self, PyObject *args)
1448 {
1449     char *path;
1450     PyObject *argv, *env;
1451     char **argvlist;
1452     char **envlist;
1453     PyObject *key, *val, *keys=NULL, *vals=NULL;
1454     Py_ssize_t i, pos, argc, envc;
1455     PyObject *(*getitem)(PyObject *, Py_ssize_t);
1456     Py_ssize_t lastarg = 0;
1457 
1458     /* execve has three arguments: (path, argv, env), where
1459        argv is a list or tuple of strings and env is a dictionary
1460        like posix.environ. */
1461 
1462     if (!PyArg_ParseTuple(args, "etOO:execve",
1463                           Py_FileSystemDefaultEncoding,
1464                           &path, &argv, &env))
1465         return NULL;
1466     if (PyList_Check(argv)) {
1467         argc = PyList_Size(argv);
1468         getitem = PyList_GetItem;
1469     }
1470     else if (PyTuple_Check(argv)) {
1471         argc = PyTuple_Size(argv);
1472         getitem = PyTuple_GetItem;
1473     }
1474     else {
1475         PyErr_SetString(PyExc_TypeError,
1476                         "execve() arg 2 must be a tuple or list");
1477         goto fail_0;
1478     }
1479     if (!PyMapping_Check(env)) {
1480         PyErr_SetString(PyExc_TypeError,
1481                         "execve() arg 3 must be a mapping object");
1482         goto fail_0;
1483     }
1484 
1485     argvlist = PyMem_NEW(char *, argc+1);
1486     if (argvlist == NULL) {
1487         PyErr_NoMemory();
1488         goto fail_0;
1489     }
1490     for (i = 0; i < argc; i++) {
1491         if (!PyArg_Parse((*getitem)(argv, i),
1492                          "et;execve() arg 2 must contain only strings",
1493                          Py_FileSystemDefaultEncoding,
1494                          &argvlist[i]))
1495         {
1496             lastarg = i;
1497             goto fail_1;
1498         }
1499     }
1500     lastarg = argc;
1501     argvlist[argc] = NULL;
1502 
1503     i = PyMapping_Size(env);
1504     if (i < 0)
1505         goto fail_1;
1506     envlist = PyMem_NEW(char *, i + 1);
1507     if (envlist == NULL) {
1508         PyErr_NoMemory();
1509         goto fail_1;
1510     }
1511     envc = 0;
1512     keys = PyMapping_Keys(env);
1513     vals = PyMapping_Values(env);
1514     if (!keys || !vals)
1515         goto fail_2;
1516     if (!PyList_Check(keys) || !PyList_Check(vals)) {
1517         PyErr_SetString(PyExc_TypeError,
1518                         "execve(): env.keys() or env.values() is not a list");
1519         goto fail_2;
1520     }
1521 
1522     for (pos = 0; pos < i; pos++) {
1523         char *p, *k, *v;
1524         size_t len;
1525 
1526         key = PyList_GetItem(keys, pos);
1527         val = PyList_GetItem(vals, pos);
1528         if (!key || !val)
1529             goto fail_2;
1530 
1531         if (!PyArg_Parse(
1532                     key,
1533                     "s;execve() arg 3 contains a non-string key",
1534                     &k) ||
1535             !PyArg_Parse(
1536                 val,
1537                 "s;execve() arg 3 contains a non-string value",
1538                 &v))
1539         {
1540             goto fail_2;
1541         }
1542 
1543 #if defined(PYOS_OS2)
1544         /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
1545         if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
1546 #endif
1547         len = PyString_Size(key) + PyString_Size(val) + 2;
1548         p = PyMem_NEW(char, len);
1549         if (p == NULL) {
1550             PyErr_NoMemory();
1551             goto fail_2;
1552         }
1553         PyOS_snprintf(p, len, "%s=%s", k, v);
1554         envlist[envc++] = p;
1555 #if defined(PYOS_OS2)
1556         }
1557 #endif
1558     }
1559     envlist[envc] = 0;
1560 
1561     execve(path, argvlist, envlist);
1562 
1563     /* If we get here it's definitely an error */
1564 
1565     (void) edk2_error();
1566 
1567   fail_2:
1568     while (--envc >= 0)
1569         PyMem_DEL(envlist[envc]);
1570     PyMem_DEL(envlist);
1571   fail_1:
1572     free_string_array(argvlist, lastarg);
1573     Py_XDECREF(vals);
1574     Py_XDECREF(keys);
1575   fail_0:
1576     PyMem_Free(path);
1577     return NULL;
1578 }
1579 #endif /* HAVE_EXECV */
1580 
1581 
1582 #ifdef HAVE_SPAWNV
1583 PyDoc_STRVAR(edk2_spawnv__doc__,
1584 "spawnv(mode, path, args)\n\n\
1585 Execute the program 'path' in a new process.\n\
1586 \n\
1587     mode: mode of process creation\n\
1588     path: path of executable file\n\
1589     args: tuple or list of strings");
1590 
1591 static PyObject *
edk2_spawnv(PyObject * self,PyObject * args)1592 edk2_spawnv(PyObject *self, PyObject *args)
1593 {
1594     char *path;
1595     PyObject *argv;
1596     char **argvlist;
1597     int mode, i;
1598     Py_ssize_t argc;
1599     Py_intptr_t spawnval;
1600     PyObject *(*getitem)(PyObject *, Py_ssize_t);
1601 
1602     /* spawnv has three arguments: (mode, path, argv), where
1603        argv is a list or tuple of strings. */
1604 
1605     if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode,
1606                           Py_FileSystemDefaultEncoding,
1607                           &path, &argv))
1608         return NULL;
1609     if (PyList_Check(argv)) {
1610         argc = PyList_Size(argv);
1611         getitem = PyList_GetItem;
1612     }
1613     else if (PyTuple_Check(argv)) {
1614         argc = PyTuple_Size(argv);
1615         getitem = PyTuple_GetItem;
1616     }
1617     else {
1618         PyErr_SetString(PyExc_TypeError,
1619                         "spawnv() arg 2 must be a tuple or list");
1620         PyMem_Free(path);
1621         return NULL;
1622     }
1623 
1624     argvlist = PyMem_NEW(char *, argc+1);
1625     if (argvlist == NULL) {
1626         PyMem_Free(path);
1627         return PyErr_NoMemory();
1628     }
1629     for (i = 0; i < argc; i++) {
1630         if (!PyArg_Parse((*getitem)(argv, i), "et",
1631                          Py_FileSystemDefaultEncoding,
1632                          &argvlist[i])) {
1633             free_string_array(argvlist, i);
1634             PyErr_SetString(
1635                 PyExc_TypeError,
1636                 "spawnv() arg 2 must contain only strings");
1637             PyMem_Free(path);
1638             return NULL;
1639         }
1640     }
1641     argvlist[argc] = NULL;
1642 
1643 #if defined(PYOS_OS2) && defined(PYCC_GCC)
1644     Py_BEGIN_ALLOW_THREADS
1645     spawnval = spawnv(mode, path, argvlist);
1646     Py_END_ALLOW_THREADS
1647 #else
1648     if (mode == _OLD_P_OVERLAY)
1649         mode = _P_OVERLAY;
1650 
1651     Py_BEGIN_ALLOW_THREADS
1652     spawnval = _spawnv(mode, path, argvlist);
1653     Py_END_ALLOW_THREADS
1654 #endif
1655 
1656     free_string_array(argvlist, argc);
1657     PyMem_Free(path);
1658 
1659     if (spawnval == -1)
1660         return edk2_error();
1661     else
1662 #if SIZEOF_LONG == SIZEOF_VOID_P
1663         return Py_BuildValue("l", (long) spawnval);
1664 #else
1665         return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
1666 #endif
1667 }
1668 
1669 
1670 PyDoc_STRVAR(edk2_spawnve__doc__,
1671 "spawnve(mode, path, args, env)\n\n\
1672 Execute the program 'path' in a new process.\n\
1673 \n\
1674     mode: mode of process creation\n\
1675     path: path of executable file\n\
1676     args: tuple or list of arguments\n\
1677     env: dictionary of strings mapping to strings");
1678 
1679 static PyObject *
edk2_spawnve(PyObject * self,PyObject * args)1680 edk2_spawnve(PyObject *self, PyObject *args)
1681 {
1682     char *path;
1683     PyObject *argv, *env;
1684     char **argvlist;
1685     char **envlist;
1686     PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
1687     int mode, pos, envc;
1688     Py_ssize_t argc, i;
1689     Py_intptr_t spawnval;
1690     PyObject *(*getitem)(PyObject *, Py_ssize_t);
1691     Py_ssize_t lastarg = 0;
1692 
1693     /* spawnve has four arguments: (mode, path, argv, env), where
1694        argv is a list or tuple of strings and env is a dictionary
1695        like posix.environ. */
1696 
1697     if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode,
1698                           Py_FileSystemDefaultEncoding,
1699                           &path, &argv, &env))
1700         return NULL;
1701     if (PyList_Check(argv)) {
1702         argc = PyList_Size(argv);
1703         getitem = PyList_GetItem;
1704     }
1705     else if (PyTuple_Check(argv)) {
1706         argc = PyTuple_Size(argv);
1707         getitem = PyTuple_GetItem;
1708     }
1709     else {
1710         PyErr_SetString(PyExc_TypeError,
1711                         "spawnve() arg 2 must be a tuple or list");
1712         goto fail_0;
1713     }
1714     if (!PyMapping_Check(env)) {
1715         PyErr_SetString(PyExc_TypeError,
1716                         "spawnve() arg 3 must be a mapping object");
1717         goto fail_0;
1718     }
1719 
1720     argvlist = PyMem_NEW(char *, argc+1);
1721     if (argvlist == NULL) {
1722         PyErr_NoMemory();
1723         goto fail_0;
1724     }
1725     for (i = 0; i < argc; i++) {
1726         if (!PyArg_Parse((*getitem)(argv, i),
1727                      "et;spawnve() arg 2 must contain only strings",
1728                          Py_FileSystemDefaultEncoding,
1729                          &argvlist[i]))
1730         {
1731             lastarg = i;
1732             goto fail_1;
1733         }
1734     }
1735     lastarg = argc;
1736     argvlist[argc] = NULL;
1737 
1738     i = PyMapping_Size(env);
1739     if (i < 0)
1740         goto fail_1;
1741     envlist = PyMem_NEW(char *, i + 1);
1742     if (envlist == NULL) {
1743         PyErr_NoMemory();
1744         goto fail_1;
1745     }
1746     envc = 0;
1747     keys = PyMapping_Keys(env);
1748     vals = PyMapping_Values(env);
1749     if (!keys || !vals)
1750         goto fail_2;
1751     if (!PyList_Check(keys) || !PyList_Check(vals)) {
1752         PyErr_SetString(PyExc_TypeError,
1753                         "spawnve(): env.keys() or env.values() is not a list");
1754         goto fail_2;
1755     }
1756 
1757     for (pos = 0; pos < i; pos++) {
1758         char *p, *k, *v;
1759         size_t len;
1760 
1761         key = PyList_GetItem(keys, pos);
1762         val = PyList_GetItem(vals, pos);
1763         if (!key || !val)
1764             goto fail_2;
1765 
1766         if (!PyArg_Parse(
1767                     key,
1768                     "s;spawnve() arg 3 contains a non-string key",
1769                     &k) ||
1770             !PyArg_Parse(
1771                 val,
1772                 "s;spawnve() arg 3 contains a non-string value",
1773                 &v))
1774         {
1775             goto fail_2;
1776         }
1777         len = PyString_Size(key) + PyString_Size(val) + 2;
1778         p = PyMem_NEW(char, len);
1779         if (p == NULL) {
1780             PyErr_NoMemory();
1781             goto fail_2;
1782         }
1783         PyOS_snprintf(p, len, "%s=%s", k, v);
1784         envlist[envc++] = p;
1785     }
1786     envlist[envc] = 0;
1787 
1788 #if defined(PYOS_OS2) && defined(PYCC_GCC)
1789     Py_BEGIN_ALLOW_THREADS
1790     spawnval = spawnve(mode, path, argvlist, envlist);
1791     Py_END_ALLOW_THREADS
1792 #else
1793     if (mode == _OLD_P_OVERLAY)
1794         mode = _P_OVERLAY;
1795 
1796     Py_BEGIN_ALLOW_THREADS
1797     spawnval = _spawnve(mode, path, argvlist, envlist);
1798     Py_END_ALLOW_THREADS
1799 #endif
1800 
1801     if (spawnval == -1)
1802         (void) edk2_error();
1803     else
1804 #if SIZEOF_LONG == SIZEOF_VOID_P
1805         res = Py_BuildValue("l", (long) spawnval);
1806 #else
1807         res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
1808 #endif
1809 
1810   fail_2:
1811     while (--envc >= 0)
1812         PyMem_DEL(envlist[envc]);
1813     PyMem_DEL(envlist);
1814   fail_1:
1815     free_string_array(argvlist, lastarg);
1816     Py_XDECREF(vals);
1817     Py_XDECREF(keys);
1818   fail_0:
1819     PyMem_Free(path);
1820     return res;
1821 }
1822 
1823 /* OS/2 supports spawnvp & spawnvpe natively */
1824 #if defined(PYOS_OS2)
1825 PyDoc_STRVAR(edk2_spawnvp__doc__,
1826 "spawnvp(mode, file, args)\n\n\
1827 Execute the program 'file' in a new process, using the environment\n\
1828 search path to find the file.\n\
1829 \n\
1830     mode: mode of process creation\n\
1831     file: executable file name\n\
1832     args: tuple or list of strings");
1833 
1834 static PyObject *
edk2_spawnvp(PyObject * self,PyObject * args)1835 edk2_spawnvp(PyObject *self, PyObject *args)
1836 {
1837     char *path;
1838     PyObject *argv;
1839     char **argvlist;
1840     int mode, i, argc;
1841     Py_intptr_t spawnval;
1842     PyObject *(*getitem)(PyObject *, Py_ssize_t);
1843 
1844     /* spawnvp has three arguments: (mode, path, argv), where
1845        argv is a list or tuple of strings. */
1846 
1847     if (!PyArg_ParseTuple(args, "ietO:spawnvp", &mode,
1848                           Py_FileSystemDefaultEncoding,
1849                           &path, &argv))
1850         return NULL;
1851     if (PyList_Check(argv)) {
1852         argc = PyList_Size(argv);
1853         getitem = PyList_GetItem;
1854     }
1855     else if (PyTuple_Check(argv)) {
1856         argc = PyTuple_Size(argv);
1857         getitem = PyTuple_GetItem;
1858     }
1859     else {
1860         PyErr_SetString(PyExc_TypeError,
1861                         "spawnvp() arg 2 must be a tuple or list");
1862         PyMem_Free(path);
1863         return NULL;
1864     }
1865 
1866     argvlist = PyMem_NEW(char *, argc+1);
1867     if (argvlist == NULL) {
1868         PyMem_Free(path);
1869         return PyErr_NoMemory();
1870     }
1871     for (i = 0; i < argc; i++) {
1872         if (!PyArg_Parse((*getitem)(argv, i), "et",
1873                          Py_FileSystemDefaultEncoding,
1874                          &argvlist[i])) {
1875             free_string_array(argvlist, i);
1876             PyErr_SetString(
1877                 PyExc_TypeError,
1878                 "spawnvp() arg 2 must contain only strings");
1879             PyMem_Free(path);
1880             return NULL;
1881         }
1882     }
1883     argvlist[argc] = NULL;
1884 
1885     Py_BEGIN_ALLOW_THREADS
1886 #if defined(PYCC_GCC)
1887     spawnval = spawnvp(mode, path, argvlist);
1888 #else
1889     spawnval = _spawnvp(mode, path, argvlist);
1890 #endif
1891     Py_END_ALLOW_THREADS
1892 
1893     free_string_array(argvlist, argc);
1894     PyMem_Free(path);
1895 
1896     if (spawnval == -1)
1897         return edk2_error();
1898     else
1899         return Py_BuildValue("l", (long) spawnval);
1900 }
1901 
1902 
1903 PyDoc_STRVAR(edk2_spawnvpe__doc__,
1904 "spawnvpe(mode, file, args, env)\n\n\
1905 Execute the program 'file' in a new process, using the environment\n\
1906 search path to find the file.\n\
1907 \n\
1908     mode: mode of process creation\n\
1909     file: executable file name\n\
1910     args: tuple or list of arguments\n\
1911     env: dictionary of strings mapping to strings");
1912 
1913 static PyObject *
edk2_spawnvpe(PyObject * self,PyObject * args)1914 edk2_spawnvpe(PyObject *self, PyObject *args)
1915 {
1916     char *path;
1917     PyObject *argv, *env;
1918     char **argvlist;
1919     char **envlist;
1920     PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
1921     int mode, i, pos, argc, envc;
1922     Py_intptr_t spawnval;
1923     PyObject *(*getitem)(PyObject *, Py_ssize_t);
1924     int lastarg = 0;
1925 
1926     /* spawnvpe has four arguments: (mode, path, argv, env), where
1927        argv is a list or tuple of strings and env is a dictionary
1928        like posix.environ. */
1929 
1930     if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
1931                           Py_FileSystemDefaultEncoding,
1932                           &path, &argv, &env))
1933         return NULL;
1934     if (PyList_Check(argv)) {
1935         argc = PyList_Size(argv);
1936         getitem = PyList_GetItem;
1937     }
1938     else if (PyTuple_Check(argv)) {
1939         argc = PyTuple_Size(argv);
1940         getitem = PyTuple_GetItem;
1941     }
1942     else {
1943         PyErr_SetString(PyExc_TypeError,
1944                         "spawnvpe() arg 2 must be a tuple or list");
1945         goto fail_0;
1946     }
1947     if (!PyMapping_Check(env)) {
1948         PyErr_SetString(PyExc_TypeError,
1949                         "spawnvpe() arg 3 must be a mapping object");
1950         goto fail_0;
1951     }
1952 
1953     argvlist = PyMem_NEW(char *, argc+1);
1954     if (argvlist == NULL) {
1955         PyErr_NoMemory();
1956         goto fail_0;
1957     }
1958     for (i = 0; i < argc; i++) {
1959         if (!PyArg_Parse((*getitem)(argv, i),
1960                      "et;spawnvpe() arg 2 must contain only strings",
1961                          Py_FileSystemDefaultEncoding,
1962                          &argvlist[i]))
1963         {
1964             lastarg = i;
1965             goto fail_1;
1966         }
1967     }
1968     lastarg = argc;
1969     argvlist[argc] = NULL;
1970 
1971     i = PyMapping_Size(env);
1972     if (i < 0)
1973         goto fail_1;
1974     envlist = PyMem_NEW(char *, i + 1);
1975     if (envlist == NULL) {
1976         PyErr_NoMemory();
1977         goto fail_1;
1978     }
1979     envc = 0;
1980     keys = PyMapping_Keys(env);
1981     vals = PyMapping_Values(env);
1982     if (!keys || !vals)
1983         goto fail_2;
1984     if (!PyList_Check(keys) || !PyList_Check(vals)) {
1985         PyErr_SetString(PyExc_TypeError,
1986                         "spawnvpe(): env.keys() or env.values() is not a list");
1987         goto fail_2;
1988     }
1989 
1990     for (pos = 0; pos < i; pos++) {
1991         char *p, *k, *v;
1992         size_t len;
1993 
1994         key = PyList_GetItem(keys, pos);
1995         val = PyList_GetItem(vals, pos);
1996         if (!key || !val)
1997             goto fail_2;
1998 
1999         if (!PyArg_Parse(
2000                     key,
2001                     "s;spawnvpe() arg 3 contains a non-string key",
2002                     &k) ||
2003             !PyArg_Parse(
2004                 val,
2005                 "s;spawnvpe() arg 3 contains a non-string value",
2006                 &v))
2007         {
2008             goto fail_2;
2009         }
2010         len = PyString_Size(key) + PyString_Size(val) + 2;
2011         p = PyMem_NEW(char, len);
2012         if (p == NULL) {
2013             PyErr_NoMemory();
2014             goto fail_2;
2015         }
2016         PyOS_snprintf(p, len, "%s=%s", k, v);
2017         envlist[envc++] = p;
2018     }
2019     envlist[envc] = 0;
2020 
2021     Py_BEGIN_ALLOW_THREADS
2022 #if defined(PYCC_GCC)
2023     spawnval = spawnvpe(mode, path, argvlist, envlist);
2024 #else
2025     spawnval = _spawnvpe(mode, path, argvlist, envlist);
2026 #endif
2027     Py_END_ALLOW_THREADS
2028 
2029     if (spawnval == -1)
2030         (void) edk2_error();
2031     else
2032         res = Py_BuildValue("l", (long) spawnval);
2033 
2034   fail_2:
2035     while (--envc >= 0)
2036         PyMem_DEL(envlist[envc]);
2037     PyMem_DEL(envlist);
2038   fail_1:
2039     free_string_array(argvlist, lastarg);
2040     Py_XDECREF(vals);
2041     Py_XDECREF(keys);
2042   fail_0:
2043     PyMem_Free(path);
2044     return res;
2045 }
2046 #endif /* PYOS_OS2 */
2047 #endif /* HAVE_SPAWNV */
2048 
2049 
2050 #ifdef HAVE_FORK1
2051 PyDoc_STRVAR(edk2_fork1__doc__,
2052 "fork1() -> pid\n\n\
2053 Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
2054 \n\
2055 Return 0 to child process and PID of child to parent process.");
2056 
2057 static PyObject *
edk2_fork1(PyObject * self,PyObject * noargs)2058 edk2_fork1(PyObject *self, PyObject *noargs)
2059 {
2060     pid_t pid;
2061     int result = 0;
2062     _PyImport_AcquireLock();
2063     pid = fork1();
2064     if (pid == 0) {
2065         /* child: this clobbers and resets the import lock. */
2066         PyOS_AfterFork();
2067     } else {
2068         /* parent: release the import lock. */
2069         result = _PyImport_ReleaseLock();
2070     }
2071     if (pid == -1)
2072         return edk2_error();
2073     if (result < 0) {
2074         /* Don't clobber the OSError if the fork failed. */
2075         PyErr_SetString(PyExc_RuntimeError,
2076                         "not holding the import lock");
2077         return NULL;
2078     }
2079     return PyLong_FromPid(pid);
2080 }
2081 #endif
2082 
2083 
2084 #ifdef HAVE_FORK
2085 PyDoc_STRVAR(edk2_fork__doc__,
2086 "fork() -> pid\n\n\
2087 Fork a child process.\n\
2088 Return 0 to child process and PID of child to parent process.");
2089 
2090 static PyObject *
edk2_fork(PyObject * self,PyObject * noargs)2091 edk2_fork(PyObject *self, PyObject *noargs)
2092 {
2093     pid_t pid;
2094     int result = 0;
2095     _PyImport_AcquireLock();
2096     pid = fork();
2097     if (pid == 0) {
2098         /* child: this clobbers and resets the import lock. */
2099         PyOS_AfterFork();
2100     } else {
2101         /* parent: release the import lock. */
2102         result = _PyImport_ReleaseLock();
2103     }
2104     if (pid == -1)
2105         return edk2_error();
2106     if (result < 0) {
2107         /* Don't clobber the OSError if the fork failed. */
2108         PyErr_SetString(PyExc_RuntimeError,
2109                         "not holding the import lock");
2110         return NULL;
2111     }
2112     return PyLong_FromPid(pid);
2113 }
2114 #endif
2115 
2116 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
2117 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
2118 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
2119 #define DEV_PTY_FILE "/dev/ptc"
2120 #define HAVE_DEV_PTMX
2121 #else
2122 #define DEV_PTY_FILE "/dev/ptmx"
2123 #endif
2124 
2125 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
2126 #ifdef HAVE_PTY_H
2127 #include <pty.h>
2128 #else
2129 #ifdef HAVE_LIBUTIL_H
2130 #include <libutil.h>
2131 #else
2132 #ifdef HAVE_UTIL_H
2133 #include <util.h>
2134 #endif /* HAVE_UTIL_H */
2135 #endif /* HAVE_LIBUTIL_H */
2136 #endif /* HAVE_PTY_H */
2137 #ifdef HAVE_STROPTS_H
2138 #include <stropts.h>
2139 #endif
2140 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
2141 
2142 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
2143 PyDoc_STRVAR(edk2_openpty__doc__,
2144 "openpty() -> (master_fd, slave_fd)\n\n\
2145 Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
2146 
2147 static PyObject *
edk2_openpty(PyObject * self,PyObject * noargs)2148 edk2_openpty(PyObject *self, PyObject *noargs)
2149 {
2150     int master_fd, slave_fd;
2151 #ifndef HAVE_OPENPTY
2152     char * slave_name;
2153 #endif
2154 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
2155     PyOS_sighandler_t sig_saved;
2156 #ifdef sun
2157     extern char *ptsname(int fildes);
2158 #endif
2159 #endif
2160 
2161 #ifdef HAVE_OPENPTY
2162     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
2163         return edk2_error();
2164 #elif defined(HAVE__GETPTY)
2165     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
2166     if (slave_name == NULL)
2167         return edk2_error();
2168 
2169     slave_fd = open(slave_name, O_RDWR);
2170     if (slave_fd < 0)
2171         return edk2_error();
2172 #else
2173     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
2174     if (master_fd < 0)
2175         return edk2_error();
2176     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
2177     /* change permission of slave */
2178     if (grantpt(master_fd) < 0) {
2179         PyOS_setsig(SIGCHLD, sig_saved);
2180         return edk2_error();
2181     }
2182     /* unlock slave */
2183     if (unlockpt(master_fd) < 0) {
2184         PyOS_setsig(SIGCHLD, sig_saved);
2185         return edk2_error();
2186     }
2187     PyOS_setsig(SIGCHLD, sig_saved);
2188     slave_name = ptsname(master_fd); /* get name of slave */
2189     if (slave_name == NULL)
2190         return edk2_error();
2191     slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
2192     if (slave_fd < 0)
2193         return edk2_error();
2194 #if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
2195     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
2196     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
2197 #ifndef __hpux
2198     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
2199 #endif /* __hpux */
2200 #endif /* HAVE_CYGWIN */
2201 #endif /* HAVE_OPENPTY */
2202 
2203     return Py_BuildValue("(ii)", master_fd, slave_fd);
2204 
2205 }
2206 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
2207 
2208 #ifdef HAVE_FORKPTY
2209 PyDoc_STRVAR(edk2_forkpty__doc__,
2210 "forkpty() -> (pid, master_fd)\n\n\
2211 Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
2212 Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
2213 To both, return fd of newly opened pseudo-terminal.\n");
2214 
2215 static PyObject *
edk2_forkpty(PyObject * self,PyObject * noargs)2216 edk2_forkpty(PyObject *self, PyObject *noargs)
2217 {
2218     int master_fd = -1, result = 0;
2219     pid_t pid;
2220 
2221     _PyImport_AcquireLock();
2222     pid = forkpty(&master_fd, NULL, NULL, NULL);
2223     if (pid == 0) {
2224         /* child: this clobbers and resets the import lock. */
2225         PyOS_AfterFork();
2226     } else {
2227         /* parent: release the import lock. */
2228         result = _PyImport_ReleaseLock();
2229     }
2230     if (pid == -1)
2231         return edk2_error();
2232     if (result < 0) {
2233         /* Don't clobber the OSError if the fork failed. */
2234         PyErr_SetString(PyExc_RuntimeError,
2235                         "not holding the import lock");
2236         return NULL;
2237     }
2238     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
2239 }
2240 #endif
2241 
2242 PyDoc_STRVAR(edk2_getpid__doc__,
2243 "getpid() -> pid\n\n\
2244 Return the current process id");
2245 
2246 static PyObject *
edk2_getpid(PyObject * self,PyObject * noargs)2247 edk2_getpid(PyObject *self, PyObject *noargs)
2248 {
2249     return PyLong_FromPid(getpid());
2250 }
2251 
2252 
2253 #ifdef HAVE_GETLOGIN
2254 PyDoc_STRVAR(edk2_getlogin__doc__,
2255 "getlogin() -> string\n\n\
2256 Return the actual login name.");
2257 
2258 static PyObject *
edk2_getlogin(PyObject * self,PyObject * noargs)2259 edk2_getlogin(PyObject *self, PyObject *noargs)
2260 {
2261     PyObject *result = NULL;
2262     char *name;
2263     int old_errno = errno;
2264 
2265     errno = 0;
2266     name = getlogin();
2267     if (name == NULL) {
2268         if (errno)
2269         edk2_error();
2270         else
2271         PyErr_SetString(PyExc_OSError,
2272                         "unable to determine login name");
2273     }
2274     else
2275         result = PyString_FromString(name);
2276     errno = old_errno;
2277 
2278     return result;
2279 }
2280 #endif
2281 
2282 #ifdef HAVE_KILL
2283 PyDoc_STRVAR(edk2_kill__doc__,
2284 "kill(pid, sig)\n\n\
2285 Kill a process with a signal.");
2286 
2287 static PyObject *
edk2_kill(PyObject * self,PyObject * args)2288 edk2_kill(PyObject *self, PyObject *args)
2289 {
2290     pid_t pid;
2291     int sig;
2292     if (!PyArg_ParseTuple(args, PARSE_PID "i:kill", &pid, &sig))
2293         return NULL;
2294 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
2295     if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
2296         APIRET rc;
2297         if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
2298             return os2_error(rc);
2299 
2300     } else if (sig == XCPT_SIGNAL_KILLPROC) {
2301         APIRET rc;
2302         if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
2303             return os2_error(rc);
2304 
2305     } else
2306         return NULL; /* Unrecognized Signal Requested */
2307 #else
2308     if (kill(pid, sig) == -1)
2309         return edk2_error();
2310 #endif
2311     Py_INCREF(Py_None);
2312     return Py_None;
2313 }
2314 #endif
2315 
2316 #ifdef HAVE_PLOCK
2317 
2318 #ifdef HAVE_SYS_LOCK_H
2319 #include <sys/lock.h>
2320 #endif
2321 
2322 PyDoc_STRVAR(edk2_plock__doc__,
2323 "plock(op)\n\n\
2324 Lock program segments into memory.");
2325 
2326 static PyObject *
edk2_plock(PyObject * self,PyObject * args)2327 edk2_plock(PyObject *self, PyObject *args)
2328 {
2329     int op;
2330     if (!PyArg_ParseTuple(args, "i:plock", &op))
2331         return NULL;
2332     if (plock(op) == -1)
2333         return edk2_error();
2334     Py_INCREF(Py_None);
2335     return Py_None;
2336 }
2337 #endif
2338 
2339 
2340 #ifdef HAVE_POPEN
2341 PyDoc_STRVAR(edk2_popen__doc__,
2342 "popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\
2343 Open a pipe to/from a command returning a file object.");
2344 
2345 static PyObject *
edk2_popen(PyObject * self,PyObject * args)2346 edk2_popen(PyObject *self, PyObject *args)
2347 {
2348     char *name;
2349     char *mode = "r";
2350     int bufsize = -1;
2351     FILE *fp;
2352     PyObject *f;
2353     if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
2354         return NULL;
2355     /* Strip mode of binary or text modifiers */
2356     if (strcmp(mode, "rb") == 0 || strcmp(mode, "rt") == 0)
2357         mode = "r";
2358     else if (strcmp(mode, "wb") == 0 || strcmp(mode, "wt") == 0)
2359         mode = "w";
2360     Py_BEGIN_ALLOW_THREADS
2361     fp = popen(name, mode);
2362     Py_END_ALLOW_THREADS
2363     if (fp == NULL)
2364         return edk2_error();
2365     f = PyFile_FromFile(fp, name, mode, pclose);
2366     if (f != NULL)
2367         PyFile_SetBufSize(f, bufsize);
2368     return f;
2369 }
2370 
2371 #endif /* HAVE_POPEN */
2372 
2373 
2374 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2375 static PyObject *
wait_helper(pid_t pid,int status,struct rusage * ru)2376 wait_helper(pid_t pid, int status, struct rusage *ru)
2377 {
2378     PyObject *result;
2379     static PyObject *struct_rusage;
2380 
2381     if (pid == -1)
2382         return edk2_error();
2383 
2384     if (struct_rusage == NULL) {
2385         PyObject *m = PyImport_ImportModuleNoBlock("resource");
2386         if (m == NULL)
2387             return NULL;
2388         struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
2389         Py_DECREF(m);
2390         if (struct_rusage == NULL)
2391             return NULL;
2392     }
2393 
2394     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
2395     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
2396     if (!result)
2397         return NULL;
2398 
2399 #ifndef doubletime
2400 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
2401 #endif
2402 
2403     PyStructSequence_SET_ITEM(result, 0,
2404                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
2405     PyStructSequence_SET_ITEM(result, 1,
2406                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
2407 #define SET_INT(result, index, value)\
2408         PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value))
2409     SET_INT(result, 2, ru->ru_maxrss);
2410     SET_INT(result, 3, ru->ru_ixrss);
2411     SET_INT(result, 4, ru->ru_idrss);
2412     SET_INT(result, 5, ru->ru_isrss);
2413     SET_INT(result, 6, ru->ru_minflt);
2414     SET_INT(result, 7, ru->ru_majflt);
2415     SET_INT(result, 8, ru->ru_nswap);
2416     SET_INT(result, 9, ru->ru_inblock);
2417     SET_INT(result, 10, ru->ru_oublock);
2418     SET_INT(result, 11, ru->ru_msgsnd);
2419     SET_INT(result, 12, ru->ru_msgrcv);
2420     SET_INT(result, 13, ru->ru_nsignals);
2421     SET_INT(result, 14, ru->ru_nvcsw);
2422     SET_INT(result, 15, ru->ru_nivcsw);
2423 #undef SET_INT
2424 
2425     if (PyErr_Occurred()) {
2426         Py_DECREF(result);
2427         return NULL;
2428     }
2429 
2430     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
2431 }
2432 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
2433 
2434 #ifdef HAVE_WAIT3
2435 PyDoc_STRVAR(edk2_wait3__doc__,
2436 "wait3(options) -> (pid, status, rusage)\n\n\
2437 Wait for completion of a child process.");
2438 
2439 static PyObject *
edk2_wait3(PyObject * self,PyObject * args)2440 edk2_wait3(PyObject *self, PyObject *args)
2441 {
2442     pid_t pid;
2443     int options;
2444     struct rusage ru;
2445     WAIT_TYPE status;
2446     WAIT_STATUS_INT(status) = 0;
2447 
2448     if (!PyArg_ParseTuple(args, "i:wait3", &options))
2449         return NULL;
2450 
2451     Py_BEGIN_ALLOW_THREADS
2452     pid = wait3(&status, options, &ru);
2453     Py_END_ALLOW_THREADS
2454 
2455     return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
2456 }
2457 #endif /* HAVE_WAIT3 */
2458 
2459 #ifdef HAVE_WAIT4
2460 PyDoc_STRVAR(edk2_wait4__doc__,
2461 "wait4(pid, options) -> (pid, status, rusage)\n\n\
2462 Wait for completion of a given child process.");
2463 
2464 static PyObject *
edk2_wait4(PyObject * self,PyObject * args)2465 edk2_wait4(PyObject *self, PyObject *args)
2466 {
2467     pid_t pid;
2468     int options;
2469     struct rusage ru;
2470     WAIT_TYPE status;
2471     WAIT_STATUS_INT(status) = 0;
2472 
2473     if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options))
2474         return NULL;
2475 
2476     Py_BEGIN_ALLOW_THREADS
2477     pid = wait4(pid, &status, options, &ru);
2478     Py_END_ALLOW_THREADS
2479 
2480     return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
2481 }
2482 #endif /* HAVE_WAIT4 */
2483 
2484 #ifdef HAVE_WAITPID
2485 PyDoc_STRVAR(edk2_waitpid__doc__,
2486 "waitpid(pid, options) -> (pid, status)\n\n\
2487 Wait for completion of a given child process.");
2488 
2489 static PyObject *
edk2_waitpid(PyObject * self,PyObject * args)2490 edk2_waitpid(PyObject *self, PyObject *args)
2491 {
2492     pid_t pid;
2493     int options;
2494     WAIT_TYPE status;
2495     WAIT_STATUS_INT(status) = 0;
2496 
2497     if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
2498         return NULL;
2499     Py_BEGIN_ALLOW_THREADS
2500     pid = waitpid(pid, &status, options);
2501     Py_END_ALLOW_THREADS
2502     if (pid == -1)
2503         return edk2_error();
2504 
2505     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
2506 }
2507 
2508 #elif defined(HAVE_CWAIT)
2509 
2510 /* MS C has a variant of waitpid() that's usable for most purposes. */
2511 PyDoc_STRVAR(edk2_waitpid__doc__,
2512 "waitpid(pid, options) -> (pid, status << 8)\n\n"
2513 "Wait for completion of a given process.  options is ignored on Windows.");
2514 
2515 static PyObject *
edk2_waitpid(PyObject * self,PyObject * args)2516 edk2_waitpid(PyObject *self, PyObject *args)
2517 {
2518     Py_intptr_t pid;
2519     int status, options;
2520 
2521     if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
2522         return NULL;
2523     Py_BEGIN_ALLOW_THREADS
2524     pid = _cwait(&status, pid, options);
2525     Py_END_ALLOW_THREADS
2526     if (pid == -1)
2527         return edk2_error();
2528 
2529     /* shift the status left a byte so this is more like the POSIX waitpid */
2530     return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
2531 }
2532 #endif /* HAVE_WAITPID || HAVE_CWAIT */
2533 
2534 #ifdef HAVE_WAIT
2535 PyDoc_STRVAR(edk2_wait__doc__,
2536 "wait() -> (pid, status)\n\n\
2537 Wait for completion of a child process.");
2538 
2539 static PyObject *
edk2_wait(PyObject * self,PyObject * noargs)2540 edk2_wait(PyObject *self, PyObject *noargs)
2541 {
2542     pid_t pid;
2543     WAIT_TYPE status;
2544     WAIT_STATUS_INT(status) = 0;
2545 
2546     Py_BEGIN_ALLOW_THREADS
2547     pid = wait(&status);
2548     Py_END_ALLOW_THREADS
2549     if (pid == -1)
2550         return edk2_error();
2551 
2552     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
2553 }
2554 #endif
2555 
2556 
2557 PyDoc_STRVAR(edk2_lstat__doc__,
2558 "lstat(path) -> stat result\n\n\
2559 Like stat(path), but do not follow symbolic links.");
2560 
2561 static PyObject *
edk2_lstat(PyObject * self,PyObject * args)2562 edk2_lstat(PyObject *self, PyObject *args)
2563 {
2564 #ifdef HAVE_LSTAT
2565     return edk2_do_stat(self, args, "et:lstat", lstat, NULL, NULL);
2566 #else /* !HAVE_LSTAT */
2567     return edk2_do_stat(self, args, "et:lstat", STAT, NULL, NULL);
2568 #endif /* !HAVE_LSTAT */
2569 }
2570 
2571 
2572 #ifdef HAVE_READLINK
2573 PyDoc_STRVAR(edk2_readlink__doc__,
2574 "readlink(path) -> path\n\n\
2575 Return a string representing the path to which the symbolic link points.");
2576 
2577 static PyObject *
edk2_readlink(PyObject * self,PyObject * args)2578 edk2_readlink(PyObject *self, PyObject *args)
2579 {
2580     PyObject* v;
2581     char buf[MAXPATHLEN];
2582     char *path;
2583     int n;
2584 #ifdef Py_USING_UNICODE
2585     int arg_is_unicode = 0;
2586 #endif
2587 
2588     if (!PyArg_ParseTuple(args, "et:readlink",
2589                           Py_FileSystemDefaultEncoding, &path))
2590         return NULL;
2591 #ifdef Py_USING_UNICODE
2592     v = PySequence_GetItem(args, 0);
2593     if (v == NULL) {
2594         PyMem_Free(path);
2595         return NULL;
2596     }
2597 
2598     if (PyUnicode_Check(v)) {
2599         arg_is_unicode = 1;
2600     }
2601     Py_DECREF(v);
2602 #endif
2603 
2604     Py_BEGIN_ALLOW_THREADS
2605     n = readlink(path, buf, (int) sizeof buf);
2606     Py_END_ALLOW_THREADS
2607     if (n < 0)
2608         return edk2_error_with_allocated_filename(path);
2609 
2610     PyMem_Free(path);
2611     v = PyString_FromStringAndSize(buf, n);
2612 #ifdef Py_USING_UNICODE
2613     if (arg_is_unicode) {
2614         PyObject *w;
2615 
2616         w = PyUnicode_FromEncodedObject(v,
2617                                         Py_FileSystemDefaultEncoding,
2618                                         "strict");
2619         if (w != NULL) {
2620             Py_DECREF(v);
2621             v = w;
2622         }
2623         else {
2624             /* fall back to the original byte string, as
2625                discussed in patch #683592 */
2626             PyErr_Clear();
2627         }
2628     }
2629 #endif
2630     return v;
2631 }
2632 #endif /* HAVE_READLINK */
2633 
2634 
2635 #ifdef HAVE_SYMLINK
2636 PyDoc_STRVAR(edk2_symlink__doc__,
2637 "symlink(src, dst)\n\n\
2638 Create a symbolic link pointing to src named dst.");
2639 
2640 static PyObject *
edk2_symlink(PyObject * self,PyObject * args)2641 edk2_symlink(PyObject *self, PyObject *args)
2642 {
2643     return edk2_2str(args, "etet:symlink", symlink);
2644 }
2645 #endif /* HAVE_SYMLINK */
2646 
2647 
2648 #ifdef HAVE_TIMES
2649 #define NEED_TICKS_PER_SECOND
2650 static long ticks_per_second = -1;
2651 static PyObject *
edk2_times(PyObject * self,PyObject * noargs)2652 edk2_times(PyObject *self, PyObject *noargs)
2653 {
2654     struct tms t;
2655     clock_t c;
2656     errno = 0;
2657     c = times(&t);
2658     if (c == (clock_t) -1)
2659         return edk2_error();
2660     return Py_BuildValue("ddddd",
2661                          (double)t.tms_utime / ticks_per_second,
2662                          (double)t.tms_stime / ticks_per_second,
2663                          (double)t.tms_cutime / ticks_per_second,
2664                          (double)t.tms_cstime / ticks_per_second,
2665                          (double)c / ticks_per_second);
2666 }
2667 #endif /* HAVE_TIMES */
2668 
2669 
2670 #ifdef HAVE_TIMES
2671 PyDoc_STRVAR(edk2_times__doc__,
2672 "times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
2673 Return a tuple of floating point numbers indicating process times.");
2674 #endif
2675 
2676 
2677 #ifdef HAVE_GETSID
2678 PyDoc_STRVAR(edk2_getsid__doc__,
2679 "getsid(pid) -> sid\n\n\
2680 Call the system call getsid().");
2681 
2682 static PyObject *
edk2_getsid(PyObject * self,PyObject * args)2683 edk2_getsid(PyObject *self, PyObject *args)
2684 {
2685     pid_t pid;
2686     int sid;
2687     if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid))
2688         return NULL;
2689     sid = getsid(pid);
2690     if (sid < 0)
2691         return edk2_error();
2692     return PyInt_FromLong((long)sid);
2693 }
2694 #endif /* HAVE_GETSID */
2695 
2696 
2697 #ifdef HAVE_SETSID
2698 PyDoc_STRVAR(edk2_setsid__doc__,
2699 "setsid()\n\n\
2700 Call the system call setsid().");
2701 
2702 static PyObject *
edk2_setsid(PyObject * self,PyObject * noargs)2703 edk2_setsid(PyObject *self, PyObject *noargs)
2704 {
2705     if (setsid() < 0)
2706         return edk2_error();
2707     Py_INCREF(Py_None);
2708     return Py_None;
2709 }
2710 #endif /* HAVE_SETSID */
2711 
2712 #ifdef HAVE_SETPGID
2713 PyDoc_STRVAR(edk2_setpgid__doc__,
2714 "setpgid(pid, pgrp)\n\n\
2715 Call the system call setpgid().");
2716 
2717 static PyObject *
edk2_setpgid(PyObject * self,PyObject * args)2718 edk2_setpgid(PyObject *self, PyObject *args)
2719 {
2720     pid_t pid;
2721     int pgrp;
2722     if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp))
2723         return NULL;
2724     if (setpgid(pid, pgrp) < 0)
2725         return edk2_error();
2726     Py_INCREF(Py_None);
2727     return Py_None;
2728 }
2729 #endif /* HAVE_SETPGID */
2730 
2731 
2732 #ifdef HAVE_TCGETPGRP
2733 PyDoc_STRVAR(edk2_tcgetpgrp__doc__,
2734 "tcgetpgrp(fd) -> pgid\n\n\
2735 Return the process group associated with the terminal given by a fd.");
2736 
2737 static PyObject *
edk2_tcgetpgrp(PyObject * self,PyObject * args)2738 edk2_tcgetpgrp(PyObject *self, PyObject *args)
2739 {
2740     int fd;
2741     pid_t pgid;
2742     if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
2743         return NULL;
2744     pgid = tcgetpgrp(fd);
2745     if (pgid < 0)
2746         return edk2_error();
2747     return PyLong_FromPid(pgid);
2748 }
2749 #endif /* HAVE_TCGETPGRP */
2750 
2751 
2752 #ifdef HAVE_TCSETPGRP
2753 PyDoc_STRVAR(edk2_tcsetpgrp__doc__,
2754 "tcsetpgrp(fd, pgid)\n\n\
2755 Set the process group associated with the terminal given by a fd.");
2756 
2757 static PyObject *
edk2_tcsetpgrp(PyObject * self,PyObject * args)2758 edk2_tcsetpgrp(PyObject *self, PyObject *args)
2759 {
2760     int fd;
2761     pid_t pgid;
2762     if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid))
2763         return NULL;
2764     if (tcsetpgrp(fd, pgid) < 0)
2765         return edk2_error();
2766     Py_INCREF(Py_None);
2767     return Py_None;
2768 }
2769 #endif /* HAVE_TCSETPGRP */
2770 
2771 /* Functions acting on file descriptors */
2772 
2773 PyDoc_STRVAR(edk2_open__doc__,
2774 "open(filename, flag [, mode=0777]) -> fd\n\n\
2775 Open a file (for low level IO).");
2776 
2777 static PyObject *
edk2_open(PyObject * self,PyObject * args)2778 edk2_open(PyObject *self, PyObject *args)
2779 {
2780     char *file = NULL;
2781     int flag;
2782     int mode = 0777;
2783     int fd;
2784 
2785     if (!PyArg_ParseTuple(args, "eti|i",
2786                           Py_FileSystemDefaultEncoding, &file,
2787                           &flag, &mode))
2788         return NULL;
2789 
2790     Py_BEGIN_ALLOW_THREADS
2791     fd = open(file, flag, mode);
2792     Py_END_ALLOW_THREADS
2793     if (fd < 0)
2794         return edk2_error_with_allocated_filename(file);
2795     PyMem_Free(file);
2796     return PyInt_FromLong((long)fd);
2797 }
2798 
2799 
2800 PyDoc_STRVAR(edk2_close__doc__,
2801 "close(fd)\n\n\
2802 Close a file descriptor (for low level IO).");
2803 
2804 static PyObject *
edk2_close(PyObject * self,PyObject * args)2805 edk2_close(PyObject *self, PyObject *args)
2806 {
2807     int fd, res;
2808     if (!PyArg_ParseTuple(args, "i:close", &fd))
2809         return NULL;
2810     if (!_PyVerify_fd(fd))
2811         return edk2_error();
2812     Py_BEGIN_ALLOW_THREADS
2813     res = close(fd);
2814     Py_END_ALLOW_THREADS
2815     if (res < 0)
2816         return edk2_error();
2817     Py_INCREF(Py_None);
2818     return Py_None;
2819 }
2820 
2821 
2822 PyDoc_STRVAR(edk2_closerange__doc__,
2823 "closerange(fd_low, fd_high)\n\n\
2824 Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
2825 
2826 static PyObject *
edk2_closerange(PyObject * self,PyObject * args)2827 edk2_closerange(PyObject *self, PyObject *args)
2828 {
2829     int fd_from, fd_to, i;
2830     if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
2831         return NULL;
2832     Py_BEGIN_ALLOW_THREADS
2833     for (i = fd_from; i < fd_to; i++)
2834         if (_PyVerify_fd(i))
2835             close(i);
2836     Py_END_ALLOW_THREADS
2837     Py_RETURN_NONE;
2838 }
2839 
2840 
2841 PyDoc_STRVAR(edk2_dup__doc__,
2842 "dup(fd) -> fd2\n\n\
2843 Return a duplicate of a file descriptor.");
2844 
2845 static PyObject *
edk2_dup(PyObject * self,PyObject * args)2846 edk2_dup(PyObject *self, PyObject *args)
2847 {
2848     int fd;
2849     if (!PyArg_ParseTuple(args, "i:dup", &fd))
2850         return NULL;
2851     if (!_PyVerify_fd(fd))
2852         return edk2_error();
2853     Py_BEGIN_ALLOW_THREADS
2854     fd = dup(fd);
2855     Py_END_ALLOW_THREADS
2856     if (fd < 0)
2857         return edk2_error();
2858     return PyInt_FromLong((long)fd);
2859 }
2860 
2861 
2862 PyDoc_STRVAR(edk2_dup2__doc__,
2863 "dup2(old_fd, new_fd)\n\n\
2864 Duplicate file descriptor.");
2865 
2866 static PyObject *
edk2_dup2(PyObject * self,PyObject * args)2867 edk2_dup2(PyObject *self, PyObject *args)
2868 {
2869     int fd, fd2, res;
2870     if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
2871         return NULL;
2872     if (!_PyVerify_fd_dup2(fd, fd2))
2873         return edk2_error();
2874     Py_BEGIN_ALLOW_THREADS
2875     res = dup2(fd, fd2);
2876     Py_END_ALLOW_THREADS
2877     if (res < 0)
2878         return edk2_error();
2879     Py_INCREF(Py_None);
2880     return Py_None;
2881 }
2882 
2883 
2884 PyDoc_STRVAR(edk2_lseek__doc__,
2885 "lseek(fd, pos, how) -> newpos\n\n\
2886 Set the current position of a file descriptor.");
2887 
2888 static PyObject *
edk2_lseek(PyObject * self,PyObject * args)2889 edk2_lseek(PyObject *self, PyObject *args)
2890 {
2891     int fd, how;
2892     off_t pos, res;
2893     PyObject *posobj;
2894     if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
2895         return NULL;
2896 #ifdef SEEK_SET
2897     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
2898     switch (how) {
2899     case 0: how = SEEK_SET; break;
2900     case 1: how = SEEK_CUR; break;
2901     case 2: how = SEEK_END; break;
2902     }
2903 #endif /* SEEK_END */
2904 
2905 #if !defined(HAVE_LARGEFILE_SUPPORT)
2906     pos = PyInt_AsLong(posobj);
2907 #else
2908     pos = PyLong_Check(posobj) ?
2909         PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj);
2910 #endif
2911     if (PyErr_Occurred())
2912         return NULL;
2913 
2914     if (!_PyVerify_fd(fd))
2915         return edk2_error();
2916     Py_BEGIN_ALLOW_THREADS
2917     res = lseek(fd, pos, how);
2918     Py_END_ALLOW_THREADS
2919     if (res < 0)
2920         return edk2_error();
2921 
2922 #if !defined(HAVE_LARGEFILE_SUPPORT)
2923     return PyInt_FromLong(res);
2924 #else
2925     return PyLong_FromLongLong(res);
2926 #endif
2927 }
2928 
2929 
2930 PyDoc_STRVAR(edk2_read__doc__,
2931 "read(fd, buffersize) -> string\n\n\
2932 Read a file descriptor.");
2933 
2934 static PyObject *
edk2_read(PyObject * self,PyObject * args)2935 edk2_read(PyObject *self, PyObject *args)
2936 {
2937     int fd, size, n;
2938     PyObject *buffer;
2939     if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
2940         return NULL;
2941     if (size < 0) {
2942         errno = EINVAL;
2943         return edk2_error();
2944     }
2945     buffer = PyString_FromStringAndSize((char *)NULL, size);
2946     if (buffer == NULL)
2947         return NULL;
2948     if (!_PyVerify_fd(fd)) {
2949         Py_DECREF(buffer);
2950         return edk2_error();
2951     }
2952     Py_BEGIN_ALLOW_THREADS
2953     n = read(fd, PyString_AsString(buffer), size);
2954     Py_END_ALLOW_THREADS
2955     if (n < 0) {
2956         Py_DECREF(buffer);
2957         return edk2_error();
2958     }
2959     if (n != size)
2960         _PyString_Resize(&buffer, n);
2961     return buffer;
2962 }
2963 
2964 
2965 PyDoc_STRVAR(edk2_write__doc__,
2966 "write(fd, string) -> byteswritten\n\n\
2967 Write a string to a file descriptor.");
2968 
2969 static PyObject *
edk2_write(PyObject * self,PyObject * args)2970 edk2_write(PyObject *self, PyObject *args)
2971 {
2972     Py_buffer pbuf;
2973     int fd;
2974     Py_ssize_t size;
2975 
2976     if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
2977         return NULL;
2978     if (!_PyVerify_fd(fd)) {
2979         PyBuffer_Release(&pbuf);
2980         return edk2_error();
2981     }
2982     Py_BEGIN_ALLOW_THREADS
2983     size = write(fd, pbuf.buf, (size_t)pbuf.len);
2984     Py_END_ALLOW_THREADS
2985     PyBuffer_Release(&pbuf);
2986     if (size < 0)
2987         return edk2_error();
2988     return PyInt_FromSsize_t(size);
2989 }
2990 
2991 
2992 PyDoc_STRVAR(edk2_fstat__doc__,
2993 "fstat(fd) -> stat result\n\n\
2994 Like stat(), but for an open file descriptor.");
2995 
2996 static PyObject *
edk2_fstat(PyObject * self,PyObject * args)2997 edk2_fstat(PyObject *self, PyObject *args)
2998 {
2999     int fd;
3000     STRUCT_STAT st;
3001     int res;
3002     if (!PyArg_ParseTuple(args, "i:fstat", &fd))
3003         return NULL;
3004     if (!_PyVerify_fd(fd))
3005         return edk2_error();
3006     Py_BEGIN_ALLOW_THREADS
3007     res = FSTAT(fd, &st);
3008     Py_END_ALLOW_THREADS
3009     if (res != 0) {
3010       return edk2_error();
3011     }
3012 
3013     return _pystat_fromstructstat(&st);
3014 }
3015 
3016 
3017 PyDoc_STRVAR(edk2_fdopen__doc__,
3018 "fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
3019 Return an open file object connected to a file descriptor.");
3020 
3021 static PyObject *
edk2_fdopen(PyObject * self,PyObject * args)3022 edk2_fdopen(PyObject *self, PyObject *args)
3023 {
3024     int fd;
3025     char *orgmode = "r";
3026     int bufsize = -1;
3027     FILE *fp;
3028     PyObject *f;
3029     char *mode;
3030     if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize))
3031         return NULL;
3032 
3033     /* Sanitize mode.  See fileobject.c */
3034     mode = PyMem_MALLOC(strlen(orgmode)+3);
3035     if (!mode) {
3036         PyErr_NoMemory();
3037         return NULL;
3038     }
3039     strcpy(mode, orgmode);
3040     if (_PyFile_SanitizeMode(mode)) {
3041         PyMem_FREE(mode);
3042         return NULL;
3043     }
3044     if (!_PyVerify_fd(fd))
3045         return edk2_error();
3046     Py_BEGIN_ALLOW_THREADS
3047 #if defined(HAVE_FCNTL_H)
3048     if (mode[0] == 'a') {
3049         /* try to make sure the O_APPEND flag is set */
3050         int flags;
3051         flags = fcntl(fd, F_GETFL);
3052         if (flags != -1)
3053             fcntl(fd, F_SETFL, flags | O_APPEND);
3054         fp = fdopen(fd, mode);
3055         if (fp == NULL && flags != -1)
3056             /* restore old mode if fdopen failed */
3057             fcntl(fd, F_SETFL, flags);
3058     } else {
3059         fp = fdopen(fd, mode);
3060     }
3061 #else
3062     fp = fdopen(fd, mode);
3063 #endif
3064     Py_END_ALLOW_THREADS
3065     PyMem_FREE(mode);
3066     if (fp == NULL)
3067         return edk2_error();
3068     f = PyFile_FromFile(fp, "<fdopen>", orgmode, fclose);
3069     if (f != NULL)
3070         PyFile_SetBufSize(f, bufsize);
3071     return f;
3072 }
3073 
3074 PyDoc_STRVAR(edk2_isatty__doc__,
3075 "isatty(fd) -> bool\n\n\
3076 Return True if the file descriptor 'fd' is an open file descriptor\n\
3077 connected to the slave end of a terminal.");
3078 
3079 static PyObject *
edk2_isatty(PyObject * self,PyObject * args)3080 edk2_isatty(PyObject *self, PyObject *args)
3081 {
3082     int fd;
3083     if (!PyArg_ParseTuple(args, "i:isatty", &fd))
3084         return NULL;
3085     if (!_PyVerify_fd(fd))
3086         return PyBool_FromLong(0);
3087     return PyBool_FromLong(isatty(fd));
3088 }
3089 
3090 #ifdef HAVE_PIPE
3091 PyDoc_STRVAR(edk2_pipe__doc__,
3092 "pipe() -> (read_end, write_end)\n\n\
3093 Create a pipe.");
3094 
3095 static PyObject *
edk2_pipe(PyObject * self,PyObject * noargs)3096 edk2_pipe(PyObject *self, PyObject *noargs)
3097 {
3098     int fds[2];
3099     int res;
3100     Py_BEGIN_ALLOW_THREADS
3101     res = pipe(fds);
3102     Py_END_ALLOW_THREADS
3103     if (res != 0)
3104         return edk2_error();
3105     return Py_BuildValue("(ii)", fds[0], fds[1]);
3106 }
3107 #endif  /* HAVE_PIPE */
3108 
3109 
3110 #ifdef HAVE_MKFIFO
3111 PyDoc_STRVAR(edk2_mkfifo__doc__,
3112 "mkfifo(filename [, mode=0666])\n\n\
3113 Create a FIFO (a POSIX named pipe).");
3114 
3115 static PyObject *
edk2_mkfifo(PyObject * self,PyObject * args)3116 edk2_mkfifo(PyObject *self, PyObject *args)
3117 {
3118     char *filename;
3119     int mode = 0666;
3120     int res;
3121     if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode))
3122         return NULL;
3123     Py_BEGIN_ALLOW_THREADS
3124     res = mkfifo(filename, mode);
3125     Py_END_ALLOW_THREADS
3126     if (res < 0)
3127         return edk2_error();
3128     Py_INCREF(Py_None);
3129     return Py_None;
3130 }
3131 #endif
3132 
3133 
3134 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
3135 PyDoc_STRVAR(edk2_mknod__doc__,
3136 "mknod(filename [, mode=0600, device])\n\n\
3137 Create a filesystem node (file, device special file or named pipe)\n\
3138 named filename. mode specifies both the permissions to use and the\n\
3139 type of node to be created, being combined (bitwise OR) with one of\n\
3140 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
3141 device defines the newly created device special file (probably using\n\
3142 os.makedev()), otherwise it is ignored.");
3143 
3144 
3145 static PyObject *
edk2_mknod(PyObject * self,PyObject * args)3146 edk2_mknod(PyObject *self, PyObject *args)
3147 {
3148     char *filename;
3149     int mode = 0600;
3150     int device = 0;
3151     int res;
3152     if (!PyArg_ParseTuple(args, "s|ii:mknod", &filename, &mode, &device))
3153         return NULL;
3154     Py_BEGIN_ALLOW_THREADS
3155     res = mknod(filename, mode, device);
3156     Py_END_ALLOW_THREADS
3157     if (res < 0)
3158         return edk2_error();
3159     Py_INCREF(Py_None);
3160     return Py_None;
3161 }
3162 #endif
3163 
3164 #ifdef HAVE_DEVICE_MACROS
3165 PyDoc_STRVAR(edk2_major__doc__,
3166 "major(device) -> major number\n\
3167 Extracts a device major number from a raw device number.");
3168 
3169 static PyObject *
edk2_major(PyObject * self,PyObject * args)3170 edk2_major(PyObject *self, PyObject *args)
3171 {
3172     int device;
3173     if (!PyArg_ParseTuple(args, "i:major", &device))
3174         return NULL;
3175     return PyInt_FromLong((long)major(device));
3176 }
3177 
3178 PyDoc_STRVAR(edk2_minor__doc__,
3179 "minor(device) -> minor number\n\
3180 Extracts a device minor number from a raw device number.");
3181 
3182 static PyObject *
edk2_minor(PyObject * self,PyObject * args)3183 edk2_minor(PyObject *self, PyObject *args)
3184 {
3185     int device;
3186     if (!PyArg_ParseTuple(args, "i:minor", &device))
3187         return NULL;
3188     return PyInt_FromLong((long)minor(device));
3189 }
3190 
3191 PyDoc_STRVAR(edk2_makedev__doc__,
3192 "makedev(major, minor) -> device number\n\
3193 Composes a raw device number from the major and minor device numbers.");
3194 
3195 static PyObject *
edk2_makedev(PyObject * self,PyObject * args)3196 edk2_makedev(PyObject *self, PyObject *args)
3197 {
3198     int major, minor;
3199     if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
3200         return NULL;
3201     return PyInt_FromLong((long)makedev(major, minor));
3202 }
3203 #endif /* device macros */
3204 
3205 
3206 #ifdef HAVE_FTRUNCATE
3207 PyDoc_STRVAR(edk2_ftruncate__doc__,
3208 "ftruncate(fd, length)\n\n\
3209 Truncate a file to a specified length.");
3210 
3211 static PyObject *
edk2_ftruncate(PyObject * self,PyObject * args)3212 edk2_ftruncate(PyObject *self, PyObject *args)
3213 {
3214     int fd;
3215     off_t length;
3216     int res;
3217     PyObject *lenobj;
3218 
3219     if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
3220         return NULL;
3221 
3222 #if !defined(HAVE_LARGEFILE_SUPPORT)
3223     length = PyInt_AsLong(lenobj);
3224 #else
3225     length = PyLong_Check(lenobj) ?
3226         PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj);
3227 #endif
3228     if (PyErr_Occurred())
3229         return NULL;
3230 
3231     Py_BEGIN_ALLOW_THREADS
3232     res = ftruncate(fd, length);
3233     Py_END_ALLOW_THREADS
3234     if (res < 0)
3235         return edk2_error();
3236     Py_INCREF(Py_None);
3237     return Py_None;
3238 }
3239 #endif
3240 
3241 #ifdef HAVE_PUTENV
3242 PyDoc_STRVAR(edk2_putenv__doc__,
3243 "putenv(key, value)\n\n\
3244 Change or add an environment variable.");
3245 
3246 /* Save putenv() parameters as values here, so we can collect them when they
3247  * get re-set with another call for the same key. */
3248 static PyObject *edk2_putenv_garbage;
3249 
3250 static PyObject *
edk2_putenv(PyObject * self,PyObject * args)3251 edk2_putenv(PyObject *self, PyObject *args)
3252 {
3253     char *s1, *s2;
3254     char *newenv;
3255     PyObject *newstr;
3256     size_t len;
3257 
3258     if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2))
3259         return NULL;
3260 
3261     /* XXX This can leak memory -- not easy to fix :-( */
3262     len = strlen(s1) + strlen(s2) + 2;
3263     /* len includes space for a trailing \0; the size arg to
3264        PyString_FromStringAndSize does not count that */
3265     newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
3266     if (newstr == NULL)
3267         return PyErr_NoMemory();
3268     newenv = PyString_AS_STRING(newstr);
3269     PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
3270     if (putenv(newenv)) {
3271         Py_DECREF(newstr);
3272         edk2_error();
3273         return NULL;
3274     }
3275     /* Install the first arg and newstr in edk2_putenv_garbage;
3276      * this will cause previous value to be collected.  This has to
3277      * happen after the real putenv() call because the old value
3278      * was still accessible until then. */
3279     if (PyDict_SetItem(edk2_putenv_garbage,
3280                        PyTuple_GET_ITEM(args, 0), newstr)) {
3281         /* really not much we can do; just leak */
3282         PyErr_Clear();
3283     }
3284     else {
3285         Py_DECREF(newstr);
3286     }
3287 
3288     Py_INCREF(Py_None);
3289     return Py_None;
3290 }
3291 #endif /* putenv */
3292 
3293 #ifdef HAVE_UNSETENV
3294 PyDoc_STRVAR(edk2_unsetenv__doc__,
3295 "unsetenv(key)\n\n\
3296 Delete an environment variable.");
3297 
3298 static PyObject *
edk2_unsetenv(PyObject * self,PyObject * args)3299 edk2_unsetenv(PyObject *self, PyObject *args)
3300 {
3301     char *s1;
3302 
3303     if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
3304         return NULL;
3305 
3306     unsetenv(s1);
3307 
3308     /* Remove the key from edk2_putenv_garbage;
3309      * this will cause it to be collected.  This has to
3310      * happen after the real unsetenv() call because the
3311      * old value was still accessible until then.
3312      */
3313     if (PyDict_DelItem(edk2_putenv_garbage,
3314                        PyTuple_GET_ITEM(args, 0))) {
3315         /* really not much we can do; just leak */
3316         PyErr_Clear();
3317     }
3318 
3319     Py_INCREF(Py_None);
3320     return Py_None;
3321 }
3322 #endif /* unsetenv */
3323 
3324 PyDoc_STRVAR(edk2_strerror__doc__,
3325 "strerror(code) -> string\n\n\
3326 Translate an error code to a message string.");
3327 
3328 static PyObject *
edk2_strerror(PyObject * self,PyObject * args)3329 edk2_strerror(PyObject *self, PyObject *args)
3330 {
3331     int code;
3332     char *message;
3333     if (!PyArg_ParseTuple(args, "i:strerror", &code))
3334         return NULL;
3335     message = strerror(code);
3336     if (message == NULL) {
3337         PyErr_SetString(PyExc_ValueError,
3338                         "strerror() argument out of range");
3339         return NULL;
3340     }
3341     return PyString_FromString(message);
3342 }
3343 
3344 
3345 #ifdef HAVE_SYS_WAIT_H
3346 
3347 #ifdef WCOREDUMP
3348 PyDoc_STRVAR(edk2_WCOREDUMP__doc__,
3349 "WCOREDUMP(status) -> bool\n\n\
3350 Return True if the process returning 'status' was dumped to a core file.");
3351 
3352 static PyObject *
edk2_WCOREDUMP(PyObject * self,PyObject * args)3353 edk2_WCOREDUMP(PyObject *self, PyObject *args)
3354 {
3355     WAIT_TYPE status;
3356     WAIT_STATUS_INT(status) = 0;
3357 
3358     if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
3359         return NULL;
3360 
3361     return PyBool_FromLong(WCOREDUMP(status));
3362 }
3363 #endif /* WCOREDUMP */
3364 
3365 #ifdef WIFCONTINUED
3366 PyDoc_STRVAR(edk2_WIFCONTINUED__doc__,
3367 "WIFCONTINUED(status) -> bool\n\n\
3368 Return True if the process returning 'status' was continued from a\n\
3369 job control stop.");
3370 
3371 static PyObject *
edk2_WIFCONTINUED(PyObject * self,PyObject * args)3372 edk2_WIFCONTINUED(PyObject *self, PyObject *args)
3373 {
3374     WAIT_TYPE status;
3375     WAIT_STATUS_INT(status) = 0;
3376 
3377     if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
3378         return NULL;
3379 
3380     return PyBool_FromLong(WIFCONTINUED(status));
3381 }
3382 #endif /* WIFCONTINUED */
3383 
3384 #ifdef WIFSTOPPED
3385 PyDoc_STRVAR(edk2_WIFSTOPPED__doc__,
3386 "WIFSTOPPED(status) -> bool\n\n\
3387 Return True if the process returning 'status' was stopped.");
3388 
3389 static PyObject *
edk2_WIFSTOPPED(PyObject * self,PyObject * args)3390 edk2_WIFSTOPPED(PyObject *self, PyObject *args)
3391 {
3392     WAIT_TYPE status;
3393     WAIT_STATUS_INT(status) = 0;
3394 
3395     if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
3396         return NULL;
3397 
3398     return PyBool_FromLong(WIFSTOPPED(status));
3399 }
3400 #endif /* WIFSTOPPED */
3401 
3402 #ifdef WIFSIGNALED
3403 PyDoc_STRVAR(edk2_WIFSIGNALED__doc__,
3404 "WIFSIGNALED(status) -> bool\n\n\
3405 Return True if the process returning 'status' was terminated by a signal.");
3406 
3407 static PyObject *
edk2_WIFSIGNALED(PyObject * self,PyObject * args)3408 edk2_WIFSIGNALED(PyObject *self, PyObject *args)
3409 {
3410     WAIT_TYPE status;
3411     WAIT_STATUS_INT(status) = 0;
3412 
3413     if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
3414         return NULL;
3415 
3416     return PyBool_FromLong(WIFSIGNALED(status));
3417 }
3418 #endif /* WIFSIGNALED */
3419 
3420 #ifdef WIFEXITED
3421 PyDoc_STRVAR(edk2_WIFEXITED__doc__,
3422 "WIFEXITED(status) -> bool\n\n\
3423 Return true if the process returning 'status' exited using the exit()\n\
3424 system call.");
3425 
3426 static PyObject *
edk2_WIFEXITED(PyObject * self,PyObject * args)3427 edk2_WIFEXITED(PyObject *self, PyObject *args)
3428 {
3429     WAIT_TYPE status;
3430     WAIT_STATUS_INT(status) = 0;
3431 
3432     if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
3433         return NULL;
3434 
3435     return PyBool_FromLong(WIFEXITED(status));
3436 }
3437 #endif /* WIFEXITED */
3438 
3439 #ifdef WEXITSTATUS
3440 PyDoc_STRVAR(edk2_WEXITSTATUS__doc__,
3441 "WEXITSTATUS(status) -> integer\n\n\
3442 Return the process return code from 'status'.");
3443 
3444 static PyObject *
edk2_WEXITSTATUS(PyObject * self,PyObject * args)3445 edk2_WEXITSTATUS(PyObject *self, PyObject *args)
3446 {
3447     WAIT_TYPE status;
3448     WAIT_STATUS_INT(status) = 0;
3449 
3450     if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
3451         return NULL;
3452 
3453     return Py_BuildValue("i", WEXITSTATUS(status));
3454 }
3455 #endif /* WEXITSTATUS */
3456 
3457 #ifdef WTERMSIG
3458 PyDoc_STRVAR(edk2_WTERMSIG__doc__,
3459 "WTERMSIG(status) -> integer\n\n\
3460 Return the signal that terminated the process that provided the 'status'\n\
3461 value.");
3462 
3463 static PyObject *
edk2_WTERMSIG(PyObject * self,PyObject * args)3464 edk2_WTERMSIG(PyObject *self, PyObject *args)
3465 {
3466     WAIT_TYPE status;
3467     WAIT_STATUS_INT(status) = 0;
3468 
3469     if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
3470         return NULL;
3471 
3472     return Py_BuildValue("i", WTERMSIG(status));
3473 }
3474 #endif /* WTERMSIG */
3475 
3476 #ifdef WSTOPSIG
3477 PyDoc_STRVAR(edk2_WSTOPSIG__doc__,
3478 "WSTOPSIG(status) -> integer\n\n\
3479 Return the signal that stopped the process that provided\n\
3480 the 'status' value.");
3481 
3482 static PyObject *
edk2_WSTOPSIG(PyObject * self,PyObject * args)3483 edk2_WSTOPSIG(PyObject *self, PyObject *args)
3484 {
3485     WAIT_TYPE status;
3486     WAIT_STATUS_INT(status) = 0;
3487 
3488     if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
3489         return NULL;
3490 
3491     return Py_BuildValue("i", WSTOPSIG(status));
3492 }
3493 #endif /* WSTOPSIG */
3494 
3495 #endif /* HAVE_SYS_WAIT_H */
3496 
3497 
3498 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
3499 #include <sys/statvfs.h>
3500 
3501 static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st)3502 _pystatvfs_fromstructstatvfs(struct statvfs st) {
3503     PyObject *v = PyStructSequence_New(&StatVFSResultType);
3504     if (v == NULL)
3505         return NULL;
3506 
3507 #if !defined(HAVE_LARGEFILE_SUPPORT)
3508     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
3509     PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
3510     PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) st.f_blocks));
3511     PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) st.f_bfree));
3512     PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) st.f_bavail));
3513     PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) st.f_files));
3514     PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong((long) st.f_ffree));
3515     PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) st.f_favail));
3516     PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
3517     PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
3518 #else
3519     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
3520     PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
3521     PyStructSequence_SET_ITEM(v, 2,
3522                               PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
3523     PyStructSequence_SET_ITEM(v, 3,
3524                               PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
3525     PyStructSequence_SET_ITEM(v, 4,
3526                               PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
3527     PyStructSequence_SET_ITEM(v, 5,
3528                               PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
3529     PyStructSequence_SET_ITEM(v, 6,
3530                               PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
3531     PyStructSequence_SET_ITEM(v, 7,
3532                               PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
3533     PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
3534     PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
3535 #endif
3536 
3537     return v;
3538 }
3539 
3540 PyDoc_STRVAR(edk2_fstatvfs__doc__,
3541 "fstatvfs(fd) -> statvfs result\n\n\
3542 Perform an fstatvfs system call on the given fd.");
3543 
3544 static PyObject *
edk2_fstatvfs(PyObject * self,PyObject * args)3545 edk2_fstatvfs(PyObject *self, PyObject *args)
3546 {
3547     int fd, res;
3548     struct statvfs st;
3549 
3550     if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
3551         return NULL;
3552     Py_BEGIN_ALLOW_THREADS
3553     res = fstatvfs(fd, &st);
3554     Py_END_ALLOW_THREADS
3555     if (res != 0)
3556         return edk2_error();
3557 
3558     return _pystatvfs_fromstructstatvfs(st);
3559 }
3560 #endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
3561 
3562 
3563 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
3564 #include <sys/statvfs.h>
3565 
3566 PyDoc_STRVAR(edk2_statvfs__doc__,
3567 "statvfs(path) -> statvfs result\n\n\
3568 Perform a statvfs system call on the given path.");
3569 
3570 static PyObject *
edk2_statvfs(PyObject * self,PyObject * args)3571 edk2_statvfs(PyObject *self, PyObject *args)
3572 {
3573     char *path;
3574     int res;
3575     struct statvfs st;
3576     if (!PyArg_ParseTuple(args, "s:statvfs", &path))
3577         return NULL;
3578     Py_BEGIN_ALLOW_THREADS
3579     res = statvfs(path, &st);
3580     Py_END_ALLOW_THREADS
3581     if (res != 0)
3582         return edk2_error_with_filename(path);
3583 
3584     return _pystatvfs_fromstructstatvfs(st);
3585 }
3586 #endif /* HAVE_STATVFS */
3587 
3588 
3589 #ifdef HAVE_TEMPNAM
3590 PyDoc_STRVAR(edk2_tempnam__doc__,
3591 "tempnam([dir[, prefix]]) -> string\n\n\
3592 Return a unique name for a temporary file.\n\
3593 The directory and a prefix may be specified as strings; they may be omitted\n\
3594 or None if not needed.");
3595 
3596 static PyObject *
edk2_tempnam(PyObject * self,PyObject * args)3597 edk2_tempnam(PyObject *self, PyObject *args)
3598 {
3599     PyObject *result = NULL;
3600     char *dir = NULL;
3601     char *pfx = NULL;
3602     char *name;
3603 
3604     if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx))
3605     return NULL;
3606 
3607     if (PyErr_Warn(PyExc_RuntimeWarning,
3608                    "tempnam is a potential security risk to your program") < 0)
3609         return NULL;
3610 
3611     if (PyErr_WarnPy3k("tempnam has been removed in 3.x; "
3612                        "use the tempfile module", 1) < 0)
3613         return NULL;
3614 
3615     name = tempnam(dir, pfx);
3616     if (name == NULL)
3617         return PyErr_NoMemory();
3618     result = PyString_FromString(name);
3619     free(name);
3620     return result;
3621 }
3622 #endif
3623 
3624 
3625 #ifdef HAVE_TMPFILE
3626 PyDoc_STRVAR(edk2_tmpfile__doc__,
3627 "tmpfile() -> file object\n\n\
3628 Create a temporary file with no directory entries.");
3629 
3630 static PyObject *
edk2_tmpfile(PyObject * self,PyObject * noargs)3631 edk2_tmpfile(PyObject *self, PyObject *noargs)
3632 {
3633     FILE *fp;
3634 
3635     if (PyErr_WarnPy3k("tmpfile has been removed in 3.x; "
3636                        "use the tempfile module", 1) < 0)
3637         return NULL;
3638 
3639     fp = tmpfile();
3640     if (fp == NULL)
3641         return edk2_error();
3642     return PyFile_FromFile(fp, "<tmpfile>", "w+b", fclose);
3643 }
3644 #endif
3645 
3646 
3647 #ifdef HAVE_TMPNAM
3648 PyDoc_STRVAR(edk2_tmpnam__doc__,
3649 "tmpnam() -> string\n\n\
3650 Return a unique name for a temporary file.");
3651 
3652 static PyObject *
edk2_tmpnam(PyObject * self,PyObject * noargs)3653 edk2_tmpnam(PyObject *self, PyObject *noargs)
3654 {
3655     char buffer[L_tmpnam];
3656     char *name;
3657 
3658     if (PyErr_Warn(PyExc_RuntimeWarning,
3659                    "tmpnam is a potential security risk to your program") < 0)
3660         return NULL;
3661 
3662     if (PyErr_WarnPy3k("tmpnam has been removed in 3.x; "
3663                        "use the tempfile module", 1) < 0)
3664         return NULL;
3665 
3666 #ifdef USE_TMPNAM_R
3667     name = tmpnam_r(buffer);
3668 #else
3669     name = tmpnam(buffer);
3670 #endif
3671     if (name == NULL) {
3672         PyObject *err = Py_BuildValue("is", 0,
3673 #ifdef USE_TMPNAM_R
3674                                       "unexpected NULL from tmpnam_r"
3675 #else
3676                                       "unexpected NULL from tmpnam"
3677 #endif
3678                                       );
3679         PyErr_SetObject(PyExc_OSError, err);
3680         Py_XDECREF(err);
3681         return NULL;
3682     }
3683     return PyString_FromString(buffer);
3684 }
3685 #endif
3686 
3687 PyDoc_STRVAR(edk2_abort__doc__,
3688 "abort() -> does not return!\n\n\
3689 Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
3690 in the hardest way possible on the hosting operating system.");
3691 
3692 static PyObject *
edk2_abort(PyObject * self,PyObject * noargs)3693 edk2_abort(PyObject *self, PyObject *noargs)
3694 {
3695     abort();
3696     /*NOTREACHED*/
3697     Py_FatalError("abort() called from Python code didn't abort!");
3698     return NULL;
3699 }
3700 
3701 static PyMethodDef edk2_methods[] = {
3702     {"access",          edk2_access,     METH_VARARGS, edk2_access__doc__},
3703 #ifdef HAVE_TTYNAME
3704     {"ttyname",         edk2_ttyname, METH_VARARGS, edk2_ttyname__doc__},
3705 #endif
3706     {"chdir",           edk2_chdir,      METH_VARARGS, edk2_chdir__doc__},
3707 #ifdef HAVE_CHFLAGS
3708     {"chflags",         edk2_chflags, METH_VARARGS, edk2_chflags__doc__},
3709 #endif /* HAVE_CHFLAGS */
3710     {"chmod",           edk2_chmod,      METH_VARARGS, edk2_chmod__doc__},
3711 #ifdef HAVE_FCHMOD
3712     {"fchmod",          edk2_fchmod, METH_VARARGS, edk2_fchmod__doc__},
3713 #endif /* HAVE_FCHMOD */
3714 #ifdef HAVE_CHOWN
3715     {"chown",           edk2_chown, METH_VARARGS, edk2_chown__doc__},
3716 #endif /* HAVE_CHOWN */
3717 #ifdef HAVE_LCHMOD
3718     {"lchmod",          edk2_lchmod, METH_VARARGS, edk2_lchmod__doc__},
3719 #endif /* HAVE_LCHMOD */
3720 #ifdef HAVE_FCHOWN
3721     {"fchown",          edk2_fchown, METH_VARARGS, edk2_fchown__doc__},
3722 #endif /* HAVE_FCHOWN */
3723 #ifdef HAVE_LCHFLAGS
3724     {"lchflags",        edk2_lchflags, METH_VARARGS, edk2_lchflags__doc__},
3725 #endif /* HAVE_LCHFLAGS */
3726 #ifdef HAVE_LCHOWN
3727     {"lchown",          edk2_lchown, METH_VARARGS, edk2_lchown__doc__},
3728 #endif /* HAVE_LCHOWN */
3729 #ifdef HAVE_CHROOT
3730     {"chroot",          edk2_chroot, METH_VARARGS, edk2_chroot__doc__},
3731 #endif
3732 #ifdef HAVE_CTERMID
3733     {"ctermid",         edk2_ctermid, METH_NOARGS, edk2_ctermid__doc__},
3734 #endif
3735 #ifdef HAVE_GETCWD
3736     {"getcwd",          edk2_getcwd,     METH_NOARGS,  edk2_getcwd__doc__},
3737 #ifdef Py_USING_UNICODE
3738     {"getcwdu",         edk2_getcwdu,    METH_NOARGS,  edk2_getcwdu__doc__},
3739 #endif
3740 #endif
3741 #ifdef HAVE_LINK
3742     {"link",            edk2_link, METH_VARARGS, edk2_link__doc__},
3743 #endif /* HAVE_LINK */
3744     {"listdir",         edk2_listdir,    METH_VARARGS, edk2_listdir__doc__},
3745     {"lstat",           edk2_lstat,      METH_VARARGS, edk2_lstat__doc__},
3746     {"mkdir",           edk2_mkdir,      METH_VARARGS, edk2_mkdir__doc__},
3747 #ifdef HAVE_NICE
3748     {"nice",            edk2_nice, METH_VARARGS, edk2_nice__doc__},
3749 #endif /* HAVE_NICE */
3750 #ifdef HAVE_READLINK
3751     {"readlink",        edk2_readlink, METH_VARARGS, edk2_readlink__doc__},
3752 #endif /* HAVE_READLINK */
3753     {"rename",          edk2_rename,     METH_VARARGS, edk2_rename__doc__},
3754     {"rmdir",           edk2_rmdir,      METH_VARARGS, edk2_rmdir__doc__},
3755     {"stat",            edk2_stat,       METH_VARARGS, edk2_stat__doc__},
3756     //{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
3757 #ifdef HAVE_SYMLINK
3758     {"symlink",         edk2_symlink, METH_VARARGS, edk2_symlink__doc__},
3759 #endif /* HAVE_SYMLINK */
3760 #ifdef HAVE_SYSTEM
3761     {"system",          edk2_system, METH_VARARGS, edk2_system__doc__},
3762 #endif
3763     {"umask",           edk2_umask,      METH_VARARGS, edk2_umask__doc__},
3764 #ifdef HAVE_UNAME
3765     {"uname",           edk2_uname, METH_NOARGS, edk2_uname__doc__},
3766 #endif /* HAVE_UNAME */
3767     {"unlink",          edk2_unlink,     METH_VARARGS, edk2_unlink__doc__},
3768     {"remove",          edk2_unlink,     METH_VARARGS, edk2_remove__doc__},
3769     {"utime",           edk2_utime,      METH_VARARGS, edk2_utime__doc__},
3770 #ifdef HAVE_TIMES
3771     {"times",           edk2_times, METH_NOARGS, edk2_times__doc__},
3772 #endif /* HAVE_TIMES */
3773     {"_exit",           edk2__exit,      METH_VARARGS, edk2__exit__doc__},
3774 #ifdef HAVE_EXECV
3775     {"execv",           edk2_execv, METH_VARARGS, edk2_execv__doc__},
3776     {"execve",          edk2_execve, METH_VARARGS, edk2_execve__doc__},
3777 #endif /* HAVE_EXECV */
3778 #ifdef HAVE_SPAWNV
3779     {"spawnv",          edk2_spawnv, METH_VARARGS, edk2_spawnv__doc__},
3780     {"spawnve",         edk2_spawnve, METH_VARARGS, edk2_spawnve__doc__},
3781 #if defined(PYOS_OS2)
3782     {"spawnvp",         edk2_spawnvp, METH_VARARGS, edk2_spawnvp__doc__},
3783     {"spawnvpe",        edk2_spawnvpe, METH_VARARGS, edk2_spawnvpe__doc__},
3784 #endif /* PYOS_OS2 */
3785 #endif /* HAVE_SPAWNV */
3786 #ifdef HAVE_FORK1
3787     {"fork1",       edk2_fork1, METH_NOARGS, edk2_fork1__doc__},
3788 #endif /* HAVE_FORK1 */
3789 #ifdef HAVE_FORK
3790     {"fork",            edk2_fork, METH_NOARGS, edk2_fork__doc__},
3791 #endif /* HAVE_FORK */
3792 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
3793     {"openpty",         edk2_openpty, METH_NOARGS, edk2_openpty__doc__},
3794 #endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
3795 #ifdef HAVE_FORKPTY
3796     {"forkpty",         edk2_forkpty, METH_NOARGS, edk2_forkpty__doc__},
3797 #endif /* HAVE_FORKPTY */
3798     {"getpid",          edk2_getpid,     METH_NOARGS,  edk2_getpid__doc__},
3799 #ifdef HAVE_GETPGRP
3800     {"getpgrp",         edk2_getpgrp, METH_NOARGS, edk2_getpgrp__doc__},
3801 #endif /* HAVE_GETPGRP */
3802 #ifdef HAVE_GETPPID
3803     {"getppid",         edk2_getppid, METH_NOARGS, edk2_getppid__doc__},
3804 #endif /* HAVE_GETPPID */
3805 #ifdef HAVE_GETLOGIN
3806     {"getlogin",        edk2_getlogin, METH_NOARGS, edk2_getlogin__doc__},
3807 #endif
3808 #ifdef HAVE_KILL
3809     {"kill",            edk2_kill, METH_VARARGS, edk2_kill__doc__},
3810 #endif /* HAVE_KILL */
3811 #ifdef HAVE_KILLPG
3812     {"killpg",          edk2_killpg, METH_VARARGS, edk2_killpg__doc__},
3813 #endif /* HAVE_KILLPG */
3814 #ifdef HAVE_PLOCK
3815     {"plock",           edk2_plock, METH_VARARGS, edk2_plock__doc__},
3816 #endif /* HAVE_PLOCK */
3817 #ifdef HAVE_POPEN
3818     {"popen",           edk2_popen, METH_VARARGS, edk2_popen__doc__},
3819 #endif /* HAVE_POPEN */
3820 #ifdef HAVE_SETGROUPS
3821     {"setgroups",       edk2_setgroups, METH_O, edk2_setgroups__doc__},
3822 #endif /* HAVE_SETGROUPS */
3823 #ifdef HAVE_INITGROUPS
3824     {"initgroups",      edk2_initgroups, METH_VARARGS, edk2_initgroups__doc__},
3825 #endif /* HAVE_INITGROUPS */
3826 #ifdef HAVE_GETPGID
3827     {"getpgid",         edk2_getpgid, METH_VARARGS, edk2_getpgid__doc__},
3828 #endif /* HAVE_GETPGID */
3829 #ifdef HAVE_SETPGRP
3830     {"setpgrp",         edk2_setpgrp, METH_NOARGS, edk2_setpgrp__doc__},
3831 #endif /* HAVE_SETPGRP */
3832 #ifdef HAVE_WAIT
3833     {"wait",            edk2_wait, METH_NOARGS, edk2_wait__doc__},
3834 #endif /* HAVE_WAIT */
3835 #ifdef HAVE_WAIT3
3836     {"wait3",           edk2_wait3, METH_VARARGS, edk2_wait3__doc__},
3837 #endif /* HAVE_WAIT3 */
3838 #ifdef HAVE_WAIT4
3839     {"wait4",           edk2_wait4, METH_VARARGS, edk2_wait4__doc__},
3840 #endif /* HAVE_WAIT4 */
3841 #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
3842     {"waitpid",         edk2_waitpid, METH_VARARGS, edk2_waitpid__doc__},
3843 #endif /* HAVE_WAITPID */
3844 #ifdef HAVE_GETSID
3845     {"getsid",          edk2_getsid, METH_VARARGS, edk2_getsid__doc__},
3846 #endif /* HAVE_GETSID */
3847 #ifdef HAVE_SETSID
3848     {"setsid",          edk2_setsid, METH_NOARGS, edk2_setsid__doc__},
3849 #endif /* HAVE_SETSID */
3850 #ifdef HAVE_SETPGID
3851     {"setpgid",         edk2_setpgid, METH_VARARGS, edk2_setpgid__doc__},
3852 #endif /* HAVE_SETPGID */
3853 #ifdef HAVE_TCGETPGRP
3854     {"tcgetpgrp",       edk2_tcgetpgrp, METH_VARARGS, edk2_tcgetpgrp__doc__},
3855 #endif /* HAVE_TCGETPGRP */
3856 #ifdef HAVE_TCSETPGRP
3857     {"tcsetpgrp",       edk2_tcsetpgrp, METH_VARARGS, edk2_tcsetpgrp__doc__},
3858 #endif /* HAVE_TCSETPGRP */
3859     {"open",            edk2_open,       METH_VARARGS, edk2_open__doc__},
3860     {"close",           edk2_close,      METH_VARARGS, edk2_close__doc__},
3861     {"closerange",      edk2_closerange, METH_VARARGS, edk2_closerange__doc__},
3862     {"dup",             edk2_dup,        METH_VARARGS, edk2_dup__doc__},
3863     {"dup2",            edk2_dup2,       METH_VARARGS, edk2_dup2__doc__},
3864     {"lseek",           edk2_lseek,      METH_VARARGS, edk2_lseek__doc__},
3865     {"read",            edk2_read,       METH_VARARGS, edk2_read__doc__},
3866     {"write",           edk2_write,      METH_VARARGS, edk2_write__doc__},
3867     {"fstat",           edk2_fstat,      METH_VARARGS, edk2_fstat__doc__},
3868     {"fdopen",          edk2_fdopen,     METH_VARARGS, edk2_fdopen__doc__},
3869     {"isatty",          edk2_isatty,     METH_VARARGS, edk2_isatty__doc__},
3870 #ifdef HAVE_PIPE
3871     {"pipe",            edk2_pipe, METH_NOARGS, edk2_pipe__doc__},
3872 #endif
3873 #ifdef HAVE_MKFIFO
3874     {"mkfifo",          edk2_mkfifo, METH_VARARGS, edk2_mkfifo__doc__},
3875 #endif
3876 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
3877     {"mknod",           edk2_mknod, METH_VARARGS, edk2_mknod__doc__},
3878 #endif
3879 #ifdef HAVE_DEVICE_MACROS
3880     {"major",           edk2_major, METH_VARARGS, edk2_major__doc__},
3881     {"minor",           edk2_minor, METH_VARARGS, edk2_minor__doc__},
3882     {"makedev",         edk2_makedev, METH_VARARGS, edk2_makedev__doc__},
3883 #endif
3884 #ifdef HAVE_FTRUNCATE
3885     {"ftruncate",       edk2_ftruncate, METH_VARARGS, edk2_ftruncate__doc__},
3886 #endif
3887 #ifdef HAVE_PUTENV
3888     {"putenv",          edk2_putenv, METH_VARARGS, edk2_putenv__doc__},
3889 #endif
3890 #ifdef HAVE_UNSETENV
3891     {"unsetenv",        edk2_unsetenv, METH_VARARGS, edk2_unsetenv__doc__},
3892 #endif
3893     {"strerror",        edk2_strerror,   METH_VARARGS, edk2_strerror__doc__},
3894 #ifdef HAVE_FCHDIR
3895     {"fchdir",          edk2_fchdir, METH_O, edk2_fchdir__doc__},
3896 #endif
3897 #ifdef HAVE_FSYNC
3898     {"fsync",       edk2_fsync, METH_O, edk2_fsync__doc__},
3899 #endif
3900 #ifdef HAVE_FDATASYNC
3901     {"fdatasync",   edk2_fdatasync,  METH_O, edk2_fdatasync__doc__},
3902 #endif
3903 #ifdef HAVE_SYS_WAIT_H
3904 #ifdef WCOREDUMP
3905     {"WCOREDUMP",       edk2_WCOREDUMP, METH_VARARGS, edk2_WCOREDUMP__doc__},
3906 #endif /* WCOREDUMP */
3907 #ifdef WIFCONTINUED
3908     {"WIFCONTINUED",edk2_WIFCONTINUED, METH_VARARGS, edk2_WIFCONTINUED__doc__},
3909 #endif /* WIFCONTINUED */
3910 #ifdef WIFSTOPPED
3911     {"WIFSTOPPED",      edk2_WIFSTOPPED, METH_VARARGS, edk2_WIFSTOPPED__doc__},
3912 #endif /* WIFSTOPPED */
3913 #ifdef WIFSIGNALED
3914     {"WIFSIGNALED",     edk2_WIFSIGNALED, METH_VARARGS, edk2_WIFSIGNALED__doc__},
3915 #endif /* WIFSIGNALED */
3916 #ifdef WIFEXITED
3917     {"WIFEXITED",       edk2_WIFEXITED, METH_VARARGS, edk2_WIFEXITED__doc__},
3918 #endif /* WIFEXITED */
3919 #ifdef WEXITSTATUS
3920     {"WEXITSTATUS",     edk2_WEXITSTATUS, METH_VARARGS, edk2_WEXITSTATUS__doc__},
3921 #endif /* WEXITSTATUS */
3922 #ifdef WTERMSIG
3923     {"WTERMSIG",        edk2_WTERMSIG, METH_VARARGS, edk2_WTERMSIG__doc__},
3924 #endif /* WTERMSIG */
3925 #ifdef WSTOPSIG
3926     {"WSTOPSIG",        edk2_WSTOPSIG, METH_VARARGS, edk2_WSTOPSIG__doc__},
3927 #endif /* WSTOPSIG */
3928 #endif /* HAVE_SYS_WAIT_H */
3929 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
3930     {"fstatvfs",        edk2_fstatvfs, METH_VARARGS, edk2_fstatvfs__doc__},
3931 #endif
3932 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
3933     {"statvfs",         edk2_statvfs, METH_VARARGS, edk2_statvfs__doc__},
3934 #endif
3935 #ifdef HAVE_TMPFILE
3936     {"tmpfile",         edk2_tmpfile,    METH_NOARGS,  edk2_tmpfile__doc__},
3937 #endif
3938 #ifdef HAVE_TEMPNAM
3939     {"tempnam",         edk2_tempnam,    METH_VARARGS, edk2_tempnam__doc__},
3940 #endif
3941 #ifdef HAVE_TMPNAM
3942     {"tmpnam",          edk2_tmpnam,     METH_NOARGS,  edk2_tmpnam__doc__},
3943 #endif
3944 #ifdef HAVE_CONFSTR
3945     {"confstr",         edk2_confstr, METH_VARARGS, edk2_confstr__doc__},
3946 #endif
3947 #ifdef HAVE_SYSCONF
3948     {"sysconf",         edk2_sysconf, METH_VARARGS, edk2_sysconf__doc__},
3949 #endif
3950 #ifdef HAVE_FPATHCONF
3951     {"fpathconf",       edk2_fpathconf, METH_VARARGS, edk2_fpathconf__doc__},
3952 #endif
3953 #ifdef HAVE_PATHCONF
3954     {"pathconf",        edk2_pathconf, METH_VARARGS, edk2_pathconf__doc__},
3955 #endif
3956     {"abort",           edk2_abort,      METH_NOARGS,  edk2_abort__doc__},
3957 
3958     {NULL,              NULL}            /* Sentinel */
3959 };
3960 
3961 
3962 static int
ins(PyObject * module,char * symbol,long value)3963 ins(PyObject *module, char *symbol, long value)
3964 {
3965     return PyModule_AddIntConstant(module, symbol, value);
3966 }
3967 
3968 static int
all_ins(PyObject * d)3969 all_ins(PyObject *d)
3970 {
3971 #ifdef F_OK
3972     if (ins(d, "F_OK", (long)F_OK)) return -1;
3973 #endif
3974 #ifdef R_OK
3975     if (ins(d, "R_OK", (long)R_OK)) return -1;
3976 #endif
3977 #ifdef W_OK
3978     if (ins(d, "W_OK", (long)W_OK)) return -1;
3979 #endif
3980 #ifdef X_OK
3981     if (ins(d, "X_OK", (long)X_OK)) return -1;
3982 #endif
3983 #ifdef NGROUPS_MAX
3984     if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
3985 #endif
3986 #ifdef TMP_MAX
3987     if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
3988 #endif
3989 #ifdef WCONTINUED
3990     if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
3991 #endif
3992 #ifdef WNOHANG
3993     if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
3994 #endif
3995 #ifdef WUNTRACED
3996     if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
3997 #endif
3998 #ifdef O_RDONLY
3999     if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
4000 #endif
4001 #ifdef O_WRONLY
4002     if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
4003 #endif
4004 #ifdef O_RDWR
4005     if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
4006 #endif
4007 #ifdef O_NDELAY
4008     if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
4009 #endif
4010 #ifdef O_NONBLOCK
4011     if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
4012 #endif
4013 #ifdef O_APPEND
4014     if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
4015 #endif
4016 #ifdef O_DSYNC
4017     if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
4018 #endif
4019 #ifdef O_RSYNC
4020     if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
4021 #endif
4022 #ifdef O_SYNC
4023     if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
4024 #endif
4025 #ifdef O_NOCTTY
4026     if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
4027 #endif
4028 #ifdef O_CREAT
4029     if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
4030 #endif
4031 #ifdef O_EXCL
4032     if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
4033 #endif
4034 #ifdef O_TRUNC
4035     if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
4036 #endif
4037 #ifdef O_BINARY
4038     if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
4039 #endif
4040 #ifdef O_TEXT
4041     if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
4042 #endif
4043 #ifdef O_LARGEFILE
4044     if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
4045 #endif
4046 #ifdef O_SHLOCK
4047     if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
4048 #endif
4049 #ifdef O_EXLOCK
4050     if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
4051 #endif
4052 
4053 /* MS Windows */
4054 #ifdef O_NOINHERIT
4055     /* Don't inherit in child processes. */
4056     if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
4057 #endif
4058 #ifdef _O_SHORT_LIVED
4059     /* Optimize for short life (keep in memory). */
4060     /* MS forgot to define this one with a non-underscore form too. */
4061     if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
4062 #endif
4063 #ifdef O_TEMPORARY
4064     /* Automatically delete when last handle is closed. */
4065     if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
4066 #endif
4067 #ifdef O_RANDOM
4068     /* Optimize for random access. */
4069     if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
4070 #endif
4071 #ifdef O_SEQUENTIAL
4072     /* Optimize for sequential access. */
4073     if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
4074 #endif
4075 
4076 /* GNU extensions. */
4077 #ifdef O_ASYNC
4078     /* Send a SIGIO signal whenever input or output
4079        becomes available on file descriptor */
4080     if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
4081 #endif
4082 #ifdef O_DIRECT
4083     /* Direct disk access. */
4084     if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
4085 #endif
4086 #ifdef O_DIRECTORY
4087     /* Must be a directory.      */
4088     if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
4089 #endif
4090 #ifdef O_NOFOLLOW
4091     /* Do not follow links.      */
4092     if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
4093 #endif
4094 #ifdef O_NOATIME
4095     /* Do not update the access time. */
4096     if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
4097 #endif
4098 
4099     /* These come from sysexits.h */
4100 #ifdef EX_OK
4101     if (ins(d, "EX_OK", (long)EX_OK)) return -1;
4102 #endif /* EX_OK */
4103 #ifdef EX_USAGE
4104     if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
4105 #endif /* EX_USAGE */
4106 #ifdef EX_DATAERR
4107     if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
4108 #endif /* EX_DATAERR */
4109 #ifdef EX_NOINPUT
4110     if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
4111 #endif /* EX_NOINPUT */
4112 #ifdef EX_NOUSER
4113     if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
4114 #endif /* EX_NOUSER */
4115 #ifdef EX_NOHOST
4116     if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
4117 #endif /* EX_NOHOST */
4118 #ifdef EX_UNAVAILABLE
4119     if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
4120 #endif /* EX_UNAVAILABLE */
4121 #ifdef EX_SOFTWARE
4122     if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
4123 #endif /* EX_SOFTWARE */
4124 #ifdef EX_OSERR
4125     if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
4126 #endif /* EX_OSERR */
4127 #ifdef EX_OSFILE
4128     if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
4129 #endif /* EX_OSFILE */
4130 #ifdef EX_CANTCREAT
4131     if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
4132 #endif /* EX_CANTCREAT */
4133 #ifdef EX_IOERR
4134     if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
4135 #endif /* EX_IOERR */
4136 #ifdef EX_TEMPFAIL
4137     if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
4138 #endif /* EX_TEMPFAIL */
4139 #ifdef EX_PROTOCOL
4140     if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
4141 #endif /* EX_PROTOCOL */
4142 #ifdef EX_NOPERM
4143     if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
4144 #endif /* EX_NOPERM */
4145 #ifdef EX_CONFIG
4146     if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
4147 #endif /* EX_CONFIG */
4148 #ifdef EX_NOTFOUND
4149     if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
4150 #endif /* EX_NOTFOUND */
4151 
4152 #ifdef HAVE_SPAWNV
4153     if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
4154     if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
4155     if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
4156     if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
4157     if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
4158 #endif
4159   return 0;
4160 }
4161 
4162 #define INITFUNC initedk2
4163 #define MODNAME "edk2"
4164 
4165 PyMODINIT_FUNC
INITFUNC(void)4166 INITFUNC(void)
4167 {
4168     PyObject *m;
4169 
4170 #ifndef UEFI_C_SOURCE
4171   PyObject *v;
4172 #endif
4173 
4174     m = Py_InitModule3(MODNAME,
4175                        edk2_methods,
4176                        edk2__doc__);
4177     if (m == NULL)
4178         return;
4179 
4180 #ifndef UEFI_C_SOURCE
4181     /* Initialize environ dictionary */
4182     v = convertenviron();
4183     Py_XINCREF(v);
4184     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
4185         return;
4186     Py_DECREF(v);
4187 #endif  /* UEFI_C_SOURCE */
4188 
4189     if (all_ins(m))
4190         return;
4191 
4192     Py_INCREF(PyExc_OSError);
4193     PyModule_AddObject(m, "error", PyExc_OSError);
4194 
4195 #ifdef HAVE_PUTENV
4196     if (edk2_putenv_garbage == NULL)
4197         edk2_putenv_garbage = PyDict_New();
4198 #endif
4199 
4200     if (!initialized) {
4201         stat_result_desc.name = MODNAME ".stat_result";
4202         stat_result_desc.fields[2].name = PyStructSequence_UnnamedField;
4203         stat_result_desc.fields[3].name = PyStructSequence_UnnamedField;
4204         stat_result_desc.fields[4].name = PyStructSequence_UnnamedField;
4205         PyStructSequence_InitType(&StatResultType, &stat_result_desc);
4206         structseq_new = StatResultType.tp_new;
4207         StatResultType.tp_new = statresult_new;
4208 
4209         //statvfs_result_desc.name = MODNAME ".statvfs_result";
4210         //PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
4211 #ifdef NEED_TICKS_PER_SECOND
4212 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
4213         ticks_per_second = sysconf(_SC_CLK_TCK);
4214 #  elif defined(HZ)
4215         ticks_per_second = HZ;
4216 #  else
4217         ticks_per_second = 60; /* magic fallback value; may be bogus */
4218 #  endif
4219 #endif
4220     }
4221     Py_INCREF((PyObject*) &StatResultType);
4222     PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
4223     //Py_INCREF((PyObject*) &StatVFSResultType);
4224     //PyModule_AddObject(m, "statvfs_result",
4225     //                   (PyObject*) &StatVFSResultType);
4226     initialized = 1;
4227 
4228 }
4229 
4230 #ifdef __cplusplus
4231 }
4232 #endif
4233 
4234 
4235