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
26extern "C" {
27#endif
28
29PyDoc_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 */
161extern char **environ;
162
163static PyObject *
164convertenviron(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
204static PyObject *
205edk2_error(void)
206{
207    return PyErr_SetFromErrno(PyExc_OSError);
208}
209static PyObject *
210edk2_error_with_filename(char* name)
211{
212    return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
213}
214
215
216static PyObject *
217edk2_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 *
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
247static PyObject *
248edk2_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
265static PyObject *
266edk2_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
288PyDoc_STRVAR(stat_result__doc__,
289"stat_result: Result from stat or lstat.\n\n\
290This object may be accessed either as a tuple of\n\
291  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
292or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
293\n\
294Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
295or st_flags, they are available as attributes only.\n\
296\n\
297See os.stat for more information.");
298
299static 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
371static 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 */
379PyDoc_STRVAR(statvfs_result__doc__,
380"statvfs_result: Result from statvfs or fstatvfs.\n\n\
381This object may be accessed either as a tuple of\n\
382  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
383or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
384\n\
385See os.statvfs for more information.");
386
387static 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
401static PyStructSequence_Desc statvfs_result_desc = {
402    "statvfs_result", /* name */
403    statvfs_result__doc__, /* doc */
404    statvfs_result_fields,
405    10
406};
407
408static PyTypeObject StatVFSResultType;
409#endif
410
411static int initialized;
412static PyTypeObject StatResultType;
413static newfunc structseq_new;
414
415static PyObject *
416statresult_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
445PyDoc_STRVAR(stat_float_times__doc__,
446"stat_float_times([newval]) -> oldval\n\n\
447Determine whether os.[lf]stat represents time stamps as float objects.\n\
448If newval is True, future calls to stat() return floats, if it is False,\n\
449future calls return ints. \n\
450If newval is omitted, return the current setting.\n");
451
452static PyObject*
453stat_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
468static void
469fill_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()) */
491static PyObject*
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
559static PyObject *
560edk2_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
593PyDoc_STRVAR(edk2_access__doc__,
594"access(path, mode) -> True if granted, False otherwise\n\n\
595Use the real uid/gid to test for access to a path.  Note that most\n\
596operations will use the effective uid/gid, therefore this routine can\n\
597be used in a suid/sgid environment to test if the invoking user has the\n\
598specified access to the path.  The mode argument can be F_OK to test\n\
599existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
600
601static PyObject *
602edk2_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
631PyDoc_STRVAR(edk2_chdir__doc__,
632"chdir(path)\n\n\
633Change the current working directory to the specified path.");
634
635static PyObject *
636edk2_chdir(PyObject *self, PyObject *args)
637{
638    return edk2_1str(args, "et:chdir", chdir);
639}
640
641PyDoc_STRVAR(edk2_chmod__doc__,
642"chmod(path, mode)\n\n\
643Change the access permissions of a file.");
644
645static PyObject *
646edk2_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
665PyDoc_STRVAR(edk2_fchmod__doc__,
666"fchmod(fd, mode)\n\n\
667Change the access permissions of the file given by file\n\
668descriptor fd.");
669
670static PyObject *
671edk2_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
686PyDoc_STRVAR(edk2_lchmod__doc__,
687"lchmod(path, mode)\n\n\
688Change the access permissions of a file. If path is a symlink, this\n\
689affects the link itself rather than the target.");
690
691static PyObject *
692edk2_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
712PyDoc_STRVAR(edk2_chflags__doc__,
713"chflags(path, flags)\n\n\
714Set file flags.");
715
716static PyObject *
717edk2_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
737PyDoc_STRVAR(edk2_lchflags__doc__,
738"lchflags(path, flags)\n\n\
739Set file flags.\n\
740This function will not follow symbolic links.");
741
742static PyObject *
743edk2_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
763PyDoc_STRVAR(edk2_chroot__doc__,
764"chroot(path)\n\n\
765Change root directory to path.");
766
767static PyObject *
768edk2_chroot(PyObject *self, PyObject *args)
769{
770    return edk2_1str(args, "et:chroot", chroot);
771}
772#endif
773
774#ifdef HAVE_FSYNC
775PyDoc_STRVAR(edk2_fsync__doc__,
776"fsync(fildes)\n\n\
777force write of file with filedescriptor to disk.");
778
779static PyObject *
780edk2_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
789extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
790#endif
791
792PyDoc_STRVAR(edk2_fdatasync__doc__,
793"fdatasync(fildes)\n\n\
794force write of file with filedescriptor to disk.\n\
795 does not force update of metadata.");
796
797static PyObject *
798edk2_fdatasync(PyObject *self, PyObject *fdobj)
799{
800    return edk2_fildes(fdobj, fdatasync);
801}
802#endif /* HAVE_FDATASYNC */
803
804
805#ifdef HAVE_CHOWN
806PyDoc_STRVAR(edk2_chown__doc__,
807"chown(path, uid, gid)\n\n\
808Change the owner and group id of path to the numeric uid and gid.");
809
810static PyObject *
811edk2_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
832PyDoc_STRVAR(edk2_fchown__doc__,
833"fchown(fd, uid, gid)\n\n\
834Change the owner and group id of the file given by file descriptor\n\
835fd to the numeric uid and gid.");
836
837static PyObject *
838edk2_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
855PyDoc_STRVAR(edk2_lchown__doc__,
856"lchown(path, uid, gid)\n\n\
857Change the owner and group id of path to the numeric uid and gid.\n\
858This function will not follow symbolic links.");
859
860static PyObject *
861edk2_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
883PyDoc_STRVAR(edk2_getcwd__doc__,
884"getcwd() -> path\n\n\
885Return a string representing the current working directory.");
886
887static PyObject *
888edk2_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
920PyDoc_STRVAR(edk2_getcwdu__doc__,
921"getcwdu() -> path\n\n\
922Return a unicode string representing the current working directory.");
923
924static PyObject *
925edk2_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
941PyDoc_STRVAR(edk2_listdir__doc__,
942"listdir(path) -> list_of_strings\n\n\
943Return a list containing the names of the entries in the directory.\n\
944\n\
945    path: path of directory to list\n\
946\n\
947The list is in arbitrary order.  It does not include the special\n\
948entries '.' and '..' even if they are present in the directory.");
949
950static PyObject *
951edk2_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
1064PyDoc_STRVAR(edk2_mkdir__doc__,
1065"mkdir(path [, mode=0777])\n\n\
1066Create a directory.");
1067
1068static PyObject *
1069edk2_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
1096PyDoc_STRVAR(edk2_nice__doc__,
1097"nice(inc) -> new_priority\n\n\
1098Decrease the priority of process by inc and return the new priority.");
1099
1100static PyObject *
1101edk2_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
1131PyDoc_STRVAR(edk2_rename__doc__,
1132"rename(old, new)\n\n\
1133Rename a file or directory.");
1134
1135static PyObject *
1136edk2_rename(PyObject *self, PyObject *args)
1137{
1138    return edk2_2str(args, "etet:rename", rename);
1139}
1140
1141
1142PyDoc_STRVAR(edk2_rmdir__doc__,
1143"rmdir(path)\n\n\
1144Remove a directory.");
1145
1146static PyObject *
1147edk2_rmdir(PyObject *self, PyObject *args)
1148{
1149    return edk2_1str(args, "et:rmdir", rmdir);
1150}
1151
1152
1153PyDoc_STRVAR(edk2_stat__doc__,
1154"stat(path) -> stat result\n\n\
1155Perform a stat system call on the given path.");
1156
1157static PyObject *
1158edk2_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
1165PyDoc_STRVAR(edk2_system__doc__,
1166"system(command) -> exit_status\n\n\
1167Execute the command (a string) in a subshell.");
1168
1169static PyObject *
1170edk2_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
1184PyDoc_STRVAR(edk2_umask__doc__,
1185"umask(new_mask) -> old_mask\n\n\
1186Set the current numeric umask and return the previous umask.");
1187
1188static PyObject *
1189edk2_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
1201PyDoc_STRVAR(edk2_unlink__doc__,
1202"unlink(path)\n\n\
1203Remove a file (same as remove(path)).");
1204
1205PyDoc_STRVAR(edk2_remove__doc__,
1206"remove(path)\n\n\
1207Remove a file (same as unlink(path)).");
1208
1209static PyObject *
1210edk2_unlink(PyObject *self, PyObject *args)
1211{
1212    return edk2_1str(args, "et:remove", unlink);
1213}
1214
1215
1216static int
1217extract_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
1253PyDoc_STRVAR(edk2_utime__doc__,
1254"utime(path, (atime, mtime))\n\
1255utime(path, None)\n\n\
1256Set the access and modified time of the file to the given values.  If the\n\
1257second form is used, set the access and modified times to the current time.");
1258
1259static PyObject *
1260edk2_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
1340PyDoc_STRVAR(edk2__exit__doc__,
1341"_exit(status)\n\n\
1342Exit to the system with specified status, without normal exit processing.");
1343
1344static PyObject *
1345edk2__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)
1355static void
1356free_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
1367PyDoc_STRVAR(edk2_execv__doc__,
1368"execv(path, args)\n\n\
1369Execute 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
1374static PyObject *
1375edk2_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
1438PyDoc_STRVAR(edk2_execve__doc__,
1439"execve(path, args, env)\n\n\
1440Execute 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
1446static PyObject *
1447edk2_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
1583PyDoc_STRVAR(edk2_spawnv__doc__,
1584"spawnv(mode, path, args)\n\n\
1585Execute 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
1591static PyObject *
1592edk2_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
1670PyDoc_STRVAR(edk2_spawnve__doc__,
1671"spawnve(mode, path, args, env)\n\n\
1672Execute 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
1679static PyObject *
1680edk2_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)
1825PyDoc_STRVAR(edk2_spawnvp__doc__,
1826"spawnvp(mode, file, args)\n\n\
1827Execute the program 'file' in a new process, using the environment\n\
1828search 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
1834static PyObject *
1835edk2_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
1903PyDoc_STRVAR(edk2_spawnvpe__doc__,
1904"spawnvpe(mode, file, args, env)\n\n\
1905Execute the program 'file' in a new process, using the environment\n\
1906search 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
1913static PyObject *
1914edk2_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
2051PyDoc_STRVAR(edk2_fork1__doc__,
2052"fork1() -> pid\n\n\
2053Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
2054\n\
2055Return 0 to child process and PID of child to parent process.");
2056
2057static PyObject *
2058edk2_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
2085PyDoc_STRVAR(edk2_fork__doc__,
2086"fork() -> pid\n\n\
2087Fork a child process.\n\
2088Return 0 to child process and PID of child to parent process.");
2089
2090static PyObject *
2091edk2_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)
2143PyDoc_STRVAR(edk2_openpty__doc__,
2144"openpty() -> (master_fd, slave_fd)\n\n\
2145Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
2146
2147static PyObject *
2148edk2_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
2209PyDoc_STRVAR(edk2_forkpty__doc__,
2210"forkpty() -> (pid, master_fd)\n\n\
2211Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
2212Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
2213To both, return fd of newly opened pseudo-terminal.\n");
2214
2215static PyObject *
2216edk2_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
2242PyDoc_STRVAR(edk2_getpid__doc__,
2243"getpid() -> pid\n\n\
2244Return the current process id");
2245
2246static PyObject *
2247edk2_getpid(PyObject *self, PyObject *noargs)
2248{
2249    return PyLong_FromPid(getpid());
2250}
2251
2252
2253#ifdef HAVE_GETLOGIN
2254PyDoc_STRVAR(edk2_getlogin__doc__,
2255"getlogin() -> string\n\n\
2256Return the actual login name.");
2257
2258static PyObject *
2259edk2_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
2283PyDoc_STRVAR(edk2_kill__doc__,
2284"kill(pid, sig)\n\n\
2285Kill a process with a signal.");
2286
2287static PyObject *
2288edk2_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
2322PyDoc_STRVAR(edk2_plock__doc__,
2323"plock(op)\n\n\
2324Lock program segments into memory.");
2325
2326static PyObject *
2327edk2_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
2341PyDoc_STRVAR(edk2_popen__doc__,
2342"popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\
2343Open a pipe to/from a command returning a file object.");
2344
2345static PyObject *
2346edk2_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)
2375static PyObject *
2376wait_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
2435PyDoc_STRVAR(edk2_wait3__doc__,
2436"wait3(options) -> (pid, status, rusage)\n\n\
2437Wait for completion of a child process.");
2438
2439static PyObject *
2440edk2_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
2460PyDoc_STRVAR(edk2_wait4__doc__,
2461"wait4(pid, options) -> (pid, status, rusage)\n\n\
2462Wait for completion of a given child process.");
2463
2464static PyObject *
2465edk2_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
2485PyDoc_STRVAR(edk2_waitpid__doc__,
2486"waitpid(pid, options) -> (pid, status)\n\n\
2487Wait for completion of a given child process.");
2488
2489static PyObject *
2490edk2_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. */
2511PyDoc_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
2515static PyObject *
2516edk2_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
2535PyDoc_STRVAR(edk2_wait__doc__,
2536"wait() -> (pid, status)\n\n\
2537Wait for completion of a child process.");
2538
2539static PyObject *
2540edk2_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
2557PyDoc_STRVAR(edk2_lstat__doc__,
2558"lstat(path) -> stat result\n\n\
2559Like stat(path), but do not follow symbolic links.");
2560
2561static PyObject *
2562edk2_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
2573PyDoc_STRVAR(edk2_readlink__doc__,
2574"readlink(path) -> path\n\n\
2575Return a string representing the path to which the symbolic link points.");
2576
2577static PyObject *
2578edk2_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
2636PyDoc_STRVAR(edk2_symlink__doc__,
2637"symlink(src, dst)\n\n\
2638Create a symbolic link pointing to src named dst.");
2639
2640static PyObject *
2641edk2_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
2650static long ticks_per_second = -1;
2651static PyObject *
2652edk2_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
2671PyDoc_STRVAR(edk2_times__doc__,
2672"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
2673Return a tuple of floating point numbers indicating process times.");
2674#endif
2675
2676
2677#ifdef HAVE_GETSID
2678PyDoc_STRVAR(edk2_getsid__doc__,
2679"getsid(pid) -> sid\n\n\
2680Call the system call getsid().");
2681
2682static PyObject *
2683edk2_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
2698PyDoc_STRVAR(edk2_setsid__doc__,
2699"setsid()\n\n\
2700Call the system call setsid().");
2701
2702static PyObject *
2703edk2_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
2713PyDoc_STRVAR(edk2_setpgid__doc__,
2714"setpgid(pid, pgrp)\n\n\
2715Call the system call setpgid().");
2716
2717static PyObject *
2718edk2_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
2733PyDoc_STRVAR(edk2_tcgetpgrp__doc__,
2734"tcgetpgrp(fd) -> pgid\n\n\
2735Return the process group associated with the terminal given by a fd.");
2736
2737static PyObject *
2738edk2_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
2753PyDoc_STRVAR(edk2_tcsetpgrp__doc__,
2754"tcsetpgrp(fd, pgid)\n\n\
2755Set the process group associated with the terminal given by a fd.");
2756
2757static PyObject *
2758edk2_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
2773PyDoc_STRVAR(edk2_open__doc__,
2774"open(filename, flag [, mode=0777]) -> fd\n\n\
2775Open a file (for low level IO).");
2776
2777static PyObject *
2778edk2_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
2800PyDoc_STRVAR(edk2_close__doc__,
2801"close(fd)\n\n\
2802Close a file descriptor (for low level IO).");
2803
2804static PyObject *
2805edk2_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
2822PyDoc_STRVAR(edk2_closerange__doc__,
2823"closerange(fd_low, fd_high)\n\n\
2824Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
2825
2826static PyObject *
2827edk2_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
2841PyDoc_STRVAR(edk2_dup__doc__,
2842"dup(fd) -> fd2\n\n\
2843Return a duplicate of a file descriptor.");
2844
2845static PyObject *
2846edk2_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
2862PyDoc_STRVAR(edk2_dup2__doc__,
2863"dup2(old_fd, new_fd)\n\n\
2864Duplicate file descriptor.");
2865
2866static PyObject *
2867edk2_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
2884PyDoc_STRVAR(edk2_lseek__doc__,
2885"lseek(fd, pos, how) -> newpos\n\n\
2886Set the current position of a file descriptor.");
2887
2888static PyObject *
2889edk2_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
2930PyDoc_STRVAR(edk2_read__doc__,
2931"read(fd, buffersize) -> string\n\n\
2932Read a file descriptor.");
2933
2934static PyObject *
2935edk2_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
2965PyDoc_STRVAR(edk2_write__doc__,
2966"write(fd, string) -> byteswritten\n\n\
2967Write a string to a file descriptor.");
2968
2969static PyObject *
2970edk2_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
2992PyDoc_STRVAR(edk2_fstat__doc__,
2993"fstat(fd) -> stat result\n\n\
2994Like stat(), but for an open file descriptor.");
2995
2996static PyObject *
2997edk2_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
3017PyDoc_STRVAR(edk2_fdopen__doc__,
3018"fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
3019Return an open file object connected to a file descriptor.");
3020
3021static PyObject *
3022edk2_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
3074PyDoc_STRVAR(edk2_isatty__doc__,
3075"isatty(fd) -> bool\n\n\
3076Return True if the file descriptor 'fd' is an open file descriptor\n\
3077connected to the slave end of a terminal.");
3078
3079static PyObject *
3080edk2_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
3091PyDoc_STRVAR(edk2_pipe__doc__,
3092"pipe() -> (read_end, write_end)\n\n\
3093Create a pipe.");
3094
3095static PyObject *
3096edk2_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
3111PyDoc_STRVAR(edk2_mkfifo__doc__,
3112"mkfifo(filename [, mode=0666])\n\n\
3113Create a FIFO (a POSIX named pipe).");
3114
3115static PyObject *
3116edk2_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)
3135PyDoc_STRVAR(edk2_mknod__doc__,
3136"mknod(filename [, mode=0600, device])\n\n\
3137Create a filesystem node (file, device special file or named pipe)\n\
3138named filename. mode specifies both the permissions to use and the\n\
3139type of node to be created, being combined (bitwise OR) with one of\n\
3140S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
3141device defines the newly created device special file (probably using\n\
3142os.makedev()), otherwise it is ignored.");
3143
3144
3145static PyObject *
3146edk2_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
3165PyDoc_STRVAR(edk2_major__doc__,
3166"major(device) -> major number\n\
3167Extracts a device major number from a raw device number.");
3168
3169static PyObject *
3170edk2_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
3178PyDoc_STRVAR(edk2_minor__doc__,
3179"minor(device) -> minor number\n\
3180Extracts a device minor number from a raw device number.");
3181
3182static PyObject *
3183edk2_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
3191PyDoc_STRVAR(edk2_makedev__doc__,
3192"makedev(major, minor) -> device number\n\
3193Composes a raw device number from the major and minor device numbers.");
3194
3195static PyObject *
3196edk2_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
3207PyDoc_STRVAR(edk2_ftruncate__doc__,
3208"ftruncate(fd, length)\n\n\
3209Truncate a file to a specified length.");
3210
3211static PyObject *
3212edk2_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
3242PyDoc_STRVAR(edk2_putenv__doc__,
3243"putenv(key, value)\n\n\
3244Change 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. */
3248static PyObject *edk2_putenv_garbage;
3249
3250static PyObject *
3251edk2_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
3294PyDoc_STRVAR(edk2_unsetenv__doc__,
3295"unsetenv(key)\n\n\
3296Delete an environment variable.");
3297
3298static PyObject *
3299edk2_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
3324PyDoc_STRVAR(edk2_strerror__doc__,
3325"strerror(code) -> string\n\n\
3326Translate an error code to a message string.");
3327
3328static PyObject *
3329edk2_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
3348PyDoc_STRVAR(edk2_WCOREDUMP__doc__,
3349"WCOREDUMP(status) -> bool\n\n\
3350Return True if the process returning 'status' was dumped to a core file.");
3351
3352static PyObject *
3353edk2_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
3366PyDoc_STRVAR(edk2_WIFCONTINUED__doc__,
3367"WIFCONTINUED(status) -> bool\n\n\
3368Return True if the process returning 'status' was continued from a\n\
3369job control stop.");
3370
3371static PyObject *
3372edk2_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
3385PyDoc_STRVAR(edk2_WIFSTOPPED__doc__,
3386"WIFSTOPPED(status) -> bool\n\n\
3387Return True if the process returning 'status' was stopped.");
3388
3389static PyObject *
3390edk2_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
3403PyDoc_STRVAR(edk2_WIFSIGNALED__doc__,
3404"WIFSIGNALED(status) -> bool\n\n\
3405Return True if the process returning 'status' was terminated by a signal.");
3406
3407static PyObject *
3408edk2_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
3421PyDoc_STRVAR(edk2_WIFEXITED__doc__,
3422"WIFEXITED(status) -> bool\n\n\
3423Return true if the process returning 'status' exited using the exit()\n\
3424system call.");
3425
3426static PyObject *
3427edk2_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
3440PyDoc_STRVAR(edk2_WEXITSTATUS__doc__,
3441"WEXITSTATUS(status) -> integer\n\n\
3442Return the process return code from 'status'.");
3443
3444static PyObject *
3445edk2_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
3458PyDoc_STRVAR(edk2_WTERMSIG__doc__,
3459"WTERMSIG(status) -> integer\n\n\
3460Return the signal that terminated the process that provided the 'status'\n\
3461value.");
3462
3463static PyObject *
3464edk2_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
3477PyDoc_STRVAR(edk2_WSTOPSIG__doc__,
3478"WSTOPSIG(status) -> integer\n\n\
3479Return the signal that stopped the process that provided\n\
3480the 'status' value.");
3481
3482static PyObject *
3483edk2_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
3501static PyObject*
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
3540PyDoc_STRVAR(edk2_fstatvfs__doc__,
3541"fstatvfs(fd) -> statvfs result\n\n\
3542Perform an fstatvfs system call on the given fd.");
3543
3544static PyObject *
3545edk2_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
3566PyDoc_STRVAR(edk2_statvfs__doc__,
3567"statvfs(path) -> statvfs result\n\n\
3568Perform a statvfs system call on the given path.");
3569
3570static PyObject *
3571edk2_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
3590PyDoc_STRVAR(edk2_tempnam__doc__,
3591"tempnam([dir[, prefix]]) -> string\n\n\
3592Return a unique name for a temporary file.\n\
3593The directory and a prefix may be specified as strings; they may be omitted\n\
3594or None if not needed.");
3595
3596static PyObject *
3597edk2_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
3626PyDoc_STRVAR(edk2_tmpfile__doc__,
3627"tmpfile() -> file object\n\n\
3628Create a temporary file with no directory entries.");
3629
3630static PyObject *
3631edk2_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
3648PyDoc_STRVAR(edk2_tmpnam__doc__,
3649"tmpnam() -> string\n\n\
3650Return a unique name for a temporary file.");
3651
3652static PyObject *
3653edk2_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
3687PyDoc_STRVAR(edk2_abort__doc__,
3688"abort() -> does not return!\n\n\
3689Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
3690in the hardest way possible on the hosting operating system.");
3691
3692static PyObject *
3693edk2_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
3701static 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
3962static int
3963ins(PyObject *module, char *symbol, long value)
3964{
3965    return PyModule_AddIntConstant(module, symbol, value);
3966}
3967
3968static int
3969all_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
4165PyMODINIT_FUNC
4166INITFUNC(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