From b410d6e4ce58c177569d42b51772f7bb239a24a3 Mon Sep 17 00:00:00 2001 From: darylm503 Date: Thu, 26 Jan 2012 22:04:41 +0000 Subject: [PATCH] AppPkg/Applications/Python: Get Python startup process fully working for EDK II. AppPkg.dsc: Clean up and add Socket support. Applications/Python/PythonCore.inf: Re-order source files. Applications/Python/Efi/config.c: Add all mandatory modules. Disable remaining. Applications/Python/Efi/edk2module.c: EDK II port of posixmodule.c. Applications/Python/Efi/getpath.c: Determine initial module search path. Applications/Python/Ia32/pyconfig.h: Configuration macros for Ia32. Applications/Python/Ipf/pyconfig.h: Configuration macros for Ipf. Applications/Python/PyMod-2.7.2/Include/osdefs.h: Select appropriate directory and path separators for UEFI. Applications/Python/PyMod-2.7.2/Lib/ntpath.py: Allow multi-character device names to left of colon. Applications/Python/PyMod-2.7.2/Lib/os.py: Add edk2 as a supported OS. Applications/Python/PyMod-2.7.2/Lib/site.py: UEFI-specific path and environment setup. Applications/Python/PyMod-2.7.2/Modules/errnomodule.c: Sync with errno.h. Applications/Python/PyMod-2.7.2/Modules/selectmodule.c: Add UEFI support. Applications/Python/PyMod-2.7.2/Modules/socketmodule.h: Add UEFI support. Applications/Python/PyMod-2.7.2/Modules/zlib/zutil.h: Add UEFI support. Applications/Python/PyMod-2.7.2/Python/getcopyright.c: Add Intel copyright. Applications/Python/X64/pyconfig.h: Configuration macros for X64. Signed-off-by: darylm503 Reviewed-by: geekboy15a Reviewed-by: jljusten Reviewed-by: lpleahy Reviewed-by: leegrosenbaum git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12957 6f19259b-4bc3-4df7-8a09-765794883524 --- AppPkg/AppPkg.dsc | 37 +- AppPkg/Applications/Python/Efi/config.c | 100 +- AppPkg/Applications/Python/Efi/edk2module.c | 7409 +++++++++++++++++ AppPkg/Applications/Python/Efi/getpath.c | 73 +- AppPkg/Applications/Python/Ia32/pyconfig.h | 27 +- AppPkg/Applications/Python/Ipf/pyconfig.h | 176 +- .../Python/PyMod-2.7.2/Include/osdefs.h | 5 +- .../Python/PyMod-2.7.2/Lib/ntpath.py | 528 ++ .../Applications/Python/PyMod-2.7.2/Lib/os.py | 773 ++ .../Python/PyMod-2.7.2/Lib/site.py | 536 ++ .../Python/PyMod-2.7.2/Modules/errnomodule.c | 845 ++ .../Python/PyMod-2.7.2/Modules/selectmodule.c | 1912 +++++ .../Python/PyMod-2.7.2/Modules/socketmodule.h | 250 + .../Python/PyMod-2.7.2/Modules/zlib/zutil.h | 4 +- .../Python/PyMod-2.7.2/Python/getcopyright.c | 36 + AppPkg/Applications/Python/PythonCore.inf | 68 +- AppPkg/Applications/Python/X64/pyconfig.h | 27 +- 17 files changed, 12508 insertions(+), 298 deletions(-) create mode 100644 AppPkg/Applications/Python/Efi/edk2module.c create mode 100644 AppPkg/Applications/Python/PyMod-2.7.2/Lib/ntpath.py create mode 100644 AppPkg/Applications/Python/PyMod-2.7.2/Lib/os.py create mode 100644 AppPkg/Applications/Python/PyMod-2.7.2/Lib/site.py create mode 100644 AppPkg/Applications/Python/PyMod-2.7.2/Modules/errnomodule.c create mode 100644 AppPkg/Applications/Python/PyMod-2.7.2/Modules/selectmodule.c create mode 100644 AppPkg/Applications/Python/PyMod-2.7.2/Modules/socketmodule.h create mode 100644 AppPkg/Applications/Python/PyMod-2.7.2/Python/getcopyright.c diff --git a/AppPkg/AppPkg.dsc b/AppPkg/AppPkg.dsc index 43a93369b9..60ff05fa41 100644 --- a/AppPkg/AppPkg.dsc +++ b/AppPkg/AppPkg.dsc @@ -71,6 +71,8 @@ SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf PathLib|ShellPkg/Library/BasePathLib/BasePathLib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + ################################################################################################### # # Components Section - list of the modules and components that will be processed by compilation @@ -100,37 +102,18 @@ #### After extracting the Python distribution, un-comment the following line to build Python. # AppPkg/Applications/Python/PythonCore.inf -########## -# Socket Applications - LibC based -########## -# AppPkg/Applications/Sockets/DataSink/DataSink.inf -# AppPkg/Applications/Sockets/DataSource/DataSource.inf -# SocketPkg/Application/FtpNew/FTP.inf -# AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.inf -# AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.inf -# AppPkg/Applications/Sockets/GetHostByName/GetHostByName.inf -# AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.inf -# AppPkg/Applications/Sockets/GetNetByName/GetNetByName.inf -# AppPkg/Applications/Sockets/GetServByName/GetServByName.inf -# AppPkg/Applications/Sockets/GetServByPort/GetServByPort.inf -# AppPkg/Applications/Sockets/RecvDgram/RecvDgram.inf -# SocketPkg/Application/route/route.inf -# AppPkg/Applications/Sockets/SetHostName/SetHostName.inf -# AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.inf -# AppPkg/Applications/Sockets/TftpServer/TftpServer.inf -# AppPkg/Applications/Sockets/WebServer/WebServer.inf { -# -# gStdLibTokenSpaceGuid.WebServer_HttpPort|80 -# } ############################################################################## # -# Include Boilerplate text required for building with the Standard Libraries. -# -############################################################################## # Specify whether we are running in an emulation environment, or not. -# Define EMULATE if we are. +# Define EMULATE if we are, else keep the DEFINE commented out. # -#DEFINE EMULATE = 1 +# DEFINE EMULATE = 1 +############################################################################## +# +# Include Boilerplate text required for building with the Standard Libraries. +# +############################################################################## !include StdLib/StdLib.inc +!include AppPkg/Applications/Sockets/Sockets.inc diff --git a/AppPkg/Applications/Python/Efi/config.c b/AppPkg/Applications/Python/Efi/config.c index 98e7e2a31e..60df9b4dc3 100644 --- a/AppPkg/Applications/Python/Efi/config.c +++ b/AppPkg/Applications/Python/Efi/config.c @@ -30,7 +30,7 @@ extern void initimageop(void); #endif extern void initmath(void); extern void init_md5(void); -extern void initnt(void); +extern void initedk2(void); extern void initoperator(void); extern void initsignal(void); extern void init_sha(void); @@ -80,6 +80,9 @@ extern void init_ast(void); extern void init_io(void); extern void _PyWarnings_Init(void); +extern void init_socket(void); +extern void initselect(void); + /* tools/freeze/makeconfig.py marker for additional "extern" */ /* -- ADDMODULE MARKER 1 -- */ @@ -90,37 +93,60 @@ struct _inittab _PyImport_Inittab[] = { {"array", initarray}, {"_ast", init_ast}, -#ifdef MS_WINDOWS -#ifndef MS_WINI64 - {"audioop", initaudioop}, -#endif -#endif {"binascii", initbinascii}, - //{"cmath", initcmath}, {"errno", initerrno}, - + {"future_builtins", initfuture_builtins}, {"gc", initgc}, {"signal", initsignal}, - -#if 0 - {"future_builtins", initfuture_builtins}, -#ifndef MS_WINI64 - {"imageop", initimageop}, -#endif + {"edk2", initedk2}, + {"operator", initoperator}, + {"_weakref", init_weakref}, {"math", initmath}, + {"time", inittime}, + {"datetime", initdatetime}, + {"cStringIO", initcStringIO}, + {"_codecs", init_codecs}, + + /* CJK codecs */ + {"_multibytecodec", init_multibytecodec}, + {"_codecs_cn", init_codecs_cn}, + {"_codecs_hk", init_codecs_hk}, + {"_codecs_iso2022", init_codecs_iso2022}, + {"_codecs_jp", init_codecs_jp}, + {"_codecs_kr", init_codecs_kr}, + {"_codecs_tw", init_codecs_tw}, + + {"_bisect", init_bisect}, {"_md5", init_md5}, - //{"nt", initnt}, /* Use the NT os functions, not posix */ - {"operator", initoperator}, {"_sha", init_sha}, {"_sha256", init_sha256}, {"_sha512", init_sha512}, + {"_random", init_random}, + {"_heapq", init_heapq}, + {"itertools", inititertools}, + {"_collections", init_collections}, + {"_sre", init_sre}, + {"parser", initparser}, + {"_struct", init_struct}, + {"cPickle", initcPickle}, + {"strop", initstrop}, - {"time", inittime}, + {"_functools", init_functools}, + {"cmath", initcmath}, + {"_json", init_json}, + + {"_socket", init_socket}, + {"select", initselect}, + + {"xxsubtype", initxxsubtype}, + +#if 0 +#ifndef MS_WINI64 + {"imageop", initimageop}, +#endif #ifdef WITH_THREAD {"thread", initthread}, #endif - {"cStringIO", initcStringIO}, - {"cPickle", initcPickle}, #ifdef WIN32 {"msvcrt", initmsvcrt}, {"_locale", init_locale}, @@ -128,42 +154,14 @@ struct _inittab _PyImport_Inittab[] = { /* XXX Should _subprocess go in a WIN32 block? not WIN64? */ //{"_subprocess", init_subprocess}, - {"_codecs", init_codecs}, - //{"_weakref", init_weakref}, //{"_hotshot", init_hotshot}, - {"_random", init_random}, - {"_bisect", init_bisect}, - {"_heapq", init_heapq}, //{"_lsprof", init_lsprof}, - {"itertools", inititertools}, - {"_collections", init_collections}, - {"_symtable", init_symtable}, //{"mmap", initmmap}, - {"_csv", init_csv}, - {"_sre", init_sre}, -#endif - - {"parser", initparser}, - -#if 0 //{"_winreg", init_winreg}, - {"_struct", init_struct}, - {"datetime", initdatetime}, - {"_functools", init_functools}, - {"_json", init_json}, - - {"xxsubtype", initxxsubtype}, - //{"zipimport", initzipimport}, - //{"zlib", initzlib}, - - /* CJK codecs */ - {"_multibytecodec", init_multibytecodec}, - {"_codecs_cn", init_codecs_cn}, - {"_codecs_hk", init_codecs_hk}, - {"_codecs_iso2022", init_codecs_iso2022}, - {"_codecs_jp", init_codecs_jp}, - {"_codecs_kr", init_codecs_kr}, - {"_codecs_tw", init_codecs_tw}, + {"_symtable", init_symtable}, + {"_csv", init_csv}, + {"zipimport", initzipimport}, + {"zlib", initzlib}, #endif /* tools/freeze/makeconfig.py marker for additional "_inittab" entries */ diff --git a/AppPkg/Applications/Python/Efi/edk2module.c b/AppPkg/Applications/Python/Efi/edk2module.c new file mode 100644 index 0000000000..451bf473be --- /dev/null +++ b/AppPkg/Applications/Python/Efi/edk2module.c @@ -0,0 +1,7409 @@ +/** @file + OS-specific module implementation for EDK II and UEFI. + Derived from posixmodule.c in Python 2.7.2. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ +#define PY_SSIZE_T_CLEAN + +#include "Python.h" +#include "structseq.h" + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +PyDoc_STRVAR(posix__doc__, +"This module provides access to operating system functionality that is\n\ +standardized by the C Standard and the POSIX standard (a thinly\n\ +disguised Unix interface). Refer to the library manual and\n\ +corresponding Unix manual entries for more information on calls."); + +#ifndef Py_USING_UNICODE + /* This is used in signatures of functions. */ + #define Py_UNICODE void +#endif + +#ifdef HAVE_SYS_TYPES_H + #include +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_SYS_STAT_H + #include +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_SYS_WAIT_H + #include /* For WNOHANG */ +#endif + +#ifdef HAVE_SIGNAL_H + #include +#endif + +#ifdef HAVE_FCNTL_H + #include +#endif /* HAVE_FCNTL_H */ + +#ifdef HAVE_GRP_H + #include +#endif + +#ifdef HAVE_SYSEXITS_H + #include +#endif /* HAVE_SYSEXITS_H */ + +#ifdef HAVE_SYS_LOADAVG_H + #include +#endif + +#ifdef HAVE_UTIME_H + #include +#endif /* HAVE_UTIME_H */ + +#ifdef HAVE_SYS_UTIME_H + #include + #define HAVE_UTIME_H /* pretend we do for the rest of this file */ +#endif /* HAVE_SYS_UTIME_H */ + +#ifdef HAVE_SYS_TIMES_H + #include +#endif /* HAVE_SYS_TIMES_H */ + +#ifdef HAVE_SYS_PARAM_H + #include +#endif /* HAVE_SYS_PARAM_H */ + +#ifdef HAVE_SYS_UTSNAME_H + #include +#endif /* HAVE_SYS_UTSNAME_H */ + +#ifdef HAVE_DIRENT_H + #include + #define NAMLEN(dirent) wcslen((dirent)->FileName) +#else + #define dirent direct + #define NAMLEN(dirent) (dirent)->d_namlen + #ifdef HAVE_SYS_NDIR_H + #include + #endif + #ifdef HAVE_SYS_DIR_H + #include + #endif + #ifdef HAVE_NDIR_H + #include + #endif +#endif + +#ifndef MAXPATHLEN + #if defined(PATH_MAX) && PATH_MAX > 1024 + #define MAXPATHLEN PATH_MAX + #else + #define MAXPATHLEN 1024 + #endif +#endif /* MAXPATHLEN */ + +#define WAIT_TYPE int +#define WAIT_STATUS_INT(s) (s) + +/* Issue #1983: pid_t can be longer than a C long on some systems */ +#if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT + #define PARSE_PID "i" + #define PyLong_FromPid PyInt_FromLong + #define PyLong_AsPid PyInt_AsLong +#elif SIZEOF_PID_T == SIZEOF_LONG + #define PARSE_PID "l" + #define PyLong_FromPid PyInt_FromLong + #define PyLong_AsPid PyInt_AsLong +#elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG + #define PARSE_PID "L" + #define PyLong_FromPid PyLong_FromLongLong + #define PyLong_AsPid PyInt_AsLongLong +#else + #error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)" +#endif /* SIZEOF_PID_T */ + +/* Don't use the "_r" form if we don't need it (also, won't have a + prototype for it, at least on Solaris -- maybe others as well?). */ +#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD) + #define USE_CTERMID_R +#endif + +#if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD) + #define USE_TMPNAM_R +#endif + +/* choose the appropriate stat and fstat functions and return structs */ +#undef STAT +#undef FSTAT +#undef STRUCT_STAT +#define STAT stat +#define FSTAT fstat +#define STRUCT_STAT struct stat + +/* dummy version. _PyVerify_fd() is already defined in fileobject.h */ +#define _PyVerify_fd_dup2(A, B) (1) + +#ifndef UEFI_ENV +/* Return a dictionary corresponding to the POSIX environment table */ +extern char **environ; + +static PyObject * +convertenviron(void) +{ + PyObject *d; + char **e; + d = PyDict_New(); + if (d == NULL) + return NULL; + if (environ == NULL) + return d; + /* This part ignores errors */ + for (e = environ; *e != NULL; e++) { + PyObject *k; + PyObject *v; + char *p = strchr(*e, '='); + if (p == NULL) + continue; + k = PyString_FromStringAndSize(*e, (int)(p-*e)); + if (k == NULL) { + PyErr_Clear(); + continue; + } + v = PyString_FromString(p+1); + if (v == NULL) { + PyErr_Clear(); + Py_DECREF(k); + continue; + } + if (PyDict_GetItem(d, k) == NULL) { + if (PyDict_SetItem(d, k, v) != 0) + PyErr_Clear(); + } + Py_DECREF(k); + Py_DECREF(v); + } + return d; +} +#endif /* UEFI_ENV */ + +/* Set a POSIX-specific error from errno, and return NULL */ + +static PyObject * +posix_error(void) +{ + return PyErr_SetFromErrno(PyExc_OSError); +} +static PyObject * +posix_error_with_filename(char* name) +{ + return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); +} + + +static PyObject * +posix_error_with_allocated_filename(char* name) +{ + PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); + PyMem_Free(name); + return rc; +} + +/* POSIX generic methods */ + +static PyObject * +posix_fildes(PyObject *fdobj, int (*func)(int)) +{ + int fd; + int res; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd < 0) + return NULL; + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS + res = (*func)(fd); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +posix_1str(PyObject *args, char *format, int (*func)(const char*)) +{ + char *path1 = NULL; + int res; + if (!PyArg_ParseTuple(args, format, + Py_FileSystemDefaultEncoding, &path1)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = (*func)(path1); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error_with_allocated_filename(path1); + PyMem_Free(path1); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +posix_2str(PyObject *args, + char *format, + int (*func)(const char *, const char *)) +{ + char *path1 = NULL, *path2 = NULL; + int res; + if (!PyArg_ParseTuple(args, format, + Py_FileSystemDefaultEncoding, &path1, + Py_FileSystemDefaultEncoding, &path2)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = (*func)(path1, path2); + Py_END_ALLOW_THREADS + PyMem_Free(path1); + PyMem_Free(path2); + if (res != 0) + /* XXX how to report both path1 and path2??? */ + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(stat_result__doc__, +"stat_result: Result from stat or lstat.\n\n\ +This object may be accessed either as a tuple of\n\ + (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ +or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ +\n\ +Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ +or st_flags, they are available as attributes only.\n\ +\n\ +See os.stat for more information."); + +static PyStructSequence_Field stat_result_fields[] = { + {"st_mode", "protection bits"}, + //{"st_ino", "inode"}, + //{"st_dev", "device"}, + //{"st_nlink", "number of hard links"}, + //{"st_uid", "user ID of owner"}, + //{"st_gid", "group ID of owner"}, + {"st_size", "total size, in bytes"}, + /* The NULL is replaced with PyStructSequence_UnnamedField later. */ + {NULL, "integer time of last access"}, + {NULL, "integer time of last modification"}, + {NULL, "integer time of last change"}, + {"st_atime", "time of last access"}, + {"st_mtime", "time of last modification"}, + {"st_ctime", "time of last change"}, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + {"st_blksize", "blocksize for filesystem I/O"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + {"st_blocks", "number of blocks allocated"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + {"st_rdev", "device type (if inode device)"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_FLAGS + {"st_flags", "user defined flags for file"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_GEN + {"st_gen", "generation number"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + {"st_birthtime", "time of creation"}, +#endif + {0} +}; + +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE +#define ST_BLKSIZE_IDX 8 +#else +#define ST_BLKSIZE_IDX 12 +#endif + +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS +#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) +#else +#define ST_BLOCKS_IDX ST_BLKSIZE_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_RDEV +#define ST_RDEV_IDX (ST_BLOCKS_IDX+1) +#else +#define ST_RDEV_IDX ST_BLOCKS_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_FLAGS +#define ST_FLAGS_IDX (ST_RDEV_IDX+1) +#else +#define ST_FLAGS_IDX ST_RDEV_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_GEN +#define ST_GEN_IDX (ST_FLAGS_IDX+1) +#else +#define ST_GEN_IDX ST_FLAGS_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME +#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) +#else +#define ST_BIRTHTIME_IDX ST_GEN_IDX +#endif + +static PyStructSequence_Desc stat_result_desc = { + "stat_result", /* name */ + stat_result__doc__, /* doc */ + stat_result_fields, + 10 +}; + +#ifndef UEFI_ENV /* Not in UEFI */ +PyDoc_STRVAR(statvfs_result__doc__, +"statvfs_result: Result from statvfs or fstatvfs.\n\n\ +This object may be accessed either as a tuple of\n\ + (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ +or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ +\n\ +See os.statvfs for more information."); + +static PyStructSequence_Field statvfs_result_fields[] = { + {"f_bsize", }, + {"f_frsize", }, + {"f_blocks", }, + {"f_bfree", }, + {"f_bavail", }, + {"f_files", }, + {"f_ffree", }, + {"f_favail", }, + {"f_flag", }, + {"f_namemax",}, + {0} +}; + +static PyStructSequence_Desc statvfs_result_desc = { + "statvfs_result", /* name */ + statvfs_result__doc__, /* doc */ + statvfs_result_fields, + 10 +}; +#endif + +static int initialized; +static PyTypeObject StatResultType; +static PyTypeObject StatVFSResultType; +static newfunc structseq_new; + +static PyObject * +statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyStructSequence *result; + int i; + + result = (PyStructSequence*)structseq_new(type, args, kwds); + if (!result) + return NULL; + /* If we have been initialized from a tuple, + st_?time might be set to None. Initialize it + from the int slots. */ + for (i = 7; i <= 9; i++) { + if (result->ob_item[i+3] == Py_None) { + Py_DECREF(Py_None); + Py_INCREF(result->ob_item[i]); + result->ob_item[i+3] = result->ob_item[i]; + } + } + return (PyObject*)result; +} + + + +/* If true, st_?time is float. */ +#if defined(UEFI_ENV) + static int _stat_float_times = 0; +#else + static int _stat_float_times = 1; +#endif + +PyDoc_STRVAR(stat_float_times__doc__, +"stat_float_times([newval]) -> oldval\n\n\ +Determine whether os.[lf]stat represents time stamps as float objects.\n\ +If newval is True, future calls to stat() return floats, if it is False,\n\ +future calls return ints. \n\ +If newval is omitted, return the current setting.\n"); + +static PyObject* +stat_float_times(PyObject* self, PyObject *args) +{ + int newval = -1; + + if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval)) + return NULL; + if (newval == -1) + /* Return old value */ + return PyBool_FromLong(_stat_float_times); + _stat_float_times = newval; + Py_INCREF(Py_None); + return Py_None; +} + +static void +fill_time(PyObject *v, int index, time_t sec, unsigned long nsec) +{ + PyObject *fval,*ival; +#if SIZEOF_TIME_T > SIZEOF_LONG + ival = PyLong_FromLongLong((PY_LONG_LONG)sec); +#else + ival = PyInt_FromLong((long)sec); +#endif + if (!ival) + return; + if (_stat_float_times) { + fval = PyFloat_FromDouble(sec + 1e-9*nsec); + } else { + fval = ival; + Py_INCREF(fval); + } + PyStructSequence_SET_ITEM(v, index, ival); + PyStructSequence_SET_ITEM(v, index+3, fval); +} + +/* pack a system stat C structure into the Python stat tuple + (used by posix_stat() and posix_fstat()) */ +static PyObject* +_pystat_fromstructstat(STRUCT_STAT *st) +{ + unsigned long ansec, mnsec, cnsec; + PyObject *v = PyStructSequence_New(&StatResultType); + if (v == NULL) + return NULL; + + PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode)); + PyStructSequence_SET_ITEM(v, 1, + PyLong_FromLongLong((PY_LONG_LONG)st->st_size)); + + ansec = mnsec = cnsec = 0; + /* The index used by fill_time is the index of the integer time. + fill_time will add 3 to the index to get the floating time index. + */ + fill_time(v, 2, st->st_atime, ansec); + fill_time(v, 3, st->st_mtime, mnsec); + fill_time(v, 4, st->st_mtime, cnsec); + +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, + PyInt_FromLong((long)st->st_blksize)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, + PyInt_FromLong((long)st->st_blocks)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, + PyInt_FromLong((long)st->st_rdev)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_GEN + PyStructSequence_SET_ITEM(v, ST_GEN_IDX, + PyInt_FromLong((long)st->st_gen)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + { + PyObject *val; + unsigned long bsec,bnsec; + bsec = (long)st->st_birthtime; +#ifdef HAVE_STAT_TV_NSEC2 + bnsec = st->st_birthtimespec.tv_nsec; +#else + bnsec = 0; +#endif + if (_stat_float_times) { + val = PyFloat_FromDouble(bsec + 1e-9*bnsec); + } else { + val = PyInt_FromLong((long)bsec); + } + PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, + val); + } +#endif +#ifdef HAVE_STRUCT_STAT_ST_FLAGS + PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, + PyInt_FromLong((long)st->st_flags)); +#endif + + if (PyErr_Occurred()) { + Py_DECREF(v); + return NULL; + } + + return v; +} + +static PyObject * +posix_do_stat(PyObject *self, PyObject *args, + char *format, + int (*statfunc)(const char *, STRUCT_STAT *), + char *wformat, + int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *)) +{ + STRUCT_STAT st; + char *path = NULL; /* pass this to stat; do not free() it */ + char *pathfree = NULL; /* this memory must be free'd */ + int res; + PyObject *result; + + if (!PyArg_ParseTuple(args, format, + Py_FileSystemDefaultEncoding, &path)) + return NULL; + pathfree = path; + + Py_BEGIN_ALLOW_THREADS + res = (*statfunc)(path, &st); + Py_END_ALLOW_THREADS + + if (res != 0) { + result = posix_error_with_filename(pathfree); + } + else + result = _pystat_fromstructstat(&st); + + PyMem_Free(pathfree); + return result; +} + +/* POSIX methods */ + +PyDoc_STRVAR(posix_access__doc__, +"access(path, mode) -> True if granted, False otherwise\n\n\ +Use the real uid/gid to test for access to a path. Note that most\n\ +operations will use the effective uid/gid, therefore this routine can\n\ +be used in a suid/sgid environment to test if the invoking user has the\n\ +specified access to the path. The mode argument can be F_OK to test\n\ +existence, or the inclusive-OR of R_OK, W_OK, and X_OK."); + +static PyObject * +posix_access(PyObject *self, PyObject *args) +{ + char *path; + int mode; + + int res; + if (!PyArg_ParseTuple(args, "eti:access", + Py_FileSystemDefaultEncoding, &path, &mode)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = access(path, mode); + Py_END_ALLOW_THREADS + PyMem_Free(path); + return PyBool_FromLong(res == 0); +} + +#ifndef F_OK + #define F_OK 0 +#endif +#ifndef R_OK + #define R_OK 4 +#endif +#ifndef W_OK + #define W_OK 2 +#endif +#ifndef X_OK + #define X_OK 1 +#endif + +PyDoc_STRVAR(posix_chdir__doc__, +"chdir(path)\n\n\ +Change the current working directory to the specified path."); + +static PyObject * +posix_chdir(PyObject *self, PyObject *args) +{ + return posix_1str(args, "et:chdir", chdir); +} + +PyDoc_STRVAR(posix_chmod__doc__, +"chmod(path, mode)\n\n\ +Change the access permissions of a file."); + +static PyObject * +posix_chmod(PyObject *self, PyObject *args) +{ + char *path = NULL; + int i; + int res; + if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding, + &path, &i)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = chmod(path, i); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error_with_allocated_filename(path); + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +} + +#ifdef HAVE_FCHMOD +PyDoc_STRVAR(posix_fchmod__doc__, +"fchmod(fd, mode)\n\n\ +Change the access permissions of the file given by file\n\ +descriptor fd."); + +static PyObject * +posix_fchmod(PyObject *self, PyObject *args) +{ + int fd, mode, res; + if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = fchmod(fd, mode); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_FCHMOD */ + +#ifdef HAVE_LCHMOD +PyDoc_STRVAR(posix_lchmod__doc__, +"lchmod(path, mode)\n\n\ +Change the access permissions of a file. If path is a symlink, this\n\ +affects the link itself rather than the target."); + +static PyObject * +posix_lchmod(PyObject *self, PyObject *args) +{ + char *path = NULL; + int i; + int res; + if (!PyArg_ParseTuple(args, "eti:lchmod", Py_FileSystemDefaultEncoding, + &path, &i)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = lchmod(path, i); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error_with_allocated_filename(path); + PyMem_Free(path); + Py_RETURN_NONE; +} +#endif /* HAVE_LCHMOD */ + + +#ifdef HAVE_CHFLAGS +PyDoc_STRVAR(posix_chflags__doc__, +"chflags(path, flags)\n\n\ +Set file flags."); + +static PyObject * +posix_chflags(PyObject *self, PyObject *args) +{ + char *path; + unsigned long flags; + int res; + if (!PyArg_ParseTuple(args, "etk:chflags", + Py_FileSystemDefaultEncoding, &path, &flags)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = chflags(path, flags); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error_with_allocated_filename(path); + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_CHFLAGS */ + +#ifdef HAVE_LCHFLAGS +PyDoc_STRVAR(posix_lchflags__doc__, +"lchflags(path, flags)\n\n\ +Set file flags.\n\ +This function will not follow symbolic links."); + +static PyObject * +posix_lchflags(PyObject *self, PyObject *args) +{ + char *path; + unsigned long flags; + int res; + if (!PyArg_ParseTuple(args, "etk:lchflags", + Py_FileSystemDefaultEncoding, &path, &flags)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = lchflags(path, flags); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error_with_allocated_filename(path); + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_LCHFLAGS */ + +#ifdef HAVE_CHROOT +PyDoc_STRVAR(posix_chroot__doc__, +"chroot(path)\n\n\ +Change root directory to path."); + +static PyObject * +posix_chroot(PyObject *self, PyObject *args) +{ + return posix_1str(args, "et:chroot", chroot); +} +#endif + +#ifdef HAVE_FSYNC +PyDoc_STRVAR(posix_fsync__doc__, +"fsync(fildes)\n\n\ +force write of file with filedescriptor to disk."); + +static PyObject * +posix_fsync(PyObject *self, PyObject *fdobj) +{ + return posix_fildes(fdobj, fsync); +} +#endif /* HAVE_FSYNC */ + +#ifdef HAVE_FDATASYNC + +#ifdef __hpux +extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ +#endif + +PyDoc_STRVAR(posix_fdatasync__doc__, +"fdatasync(fildes)\n\n\ +force write of file with filedescriptor to disk.\n\ + does not force update of metadata."); + +static PyObject * +posix_fdatasync(PyObject *self, PyObject *fdobj) +{ + return posix_fildes(fdobj, fdatasync); +} +#endif /* HAVE_FDATASYNC */ + + +#ifdef HAVE_CHOWN +PyDoc_STRVAR(posix_chown__doc__, +"chown(path, uid, gid)\n\n\ +Change the owner and group id of path to the numeric uid and gid."); + +static PyObject * +posix_chown(PyObject *self, PyObject *args) +{ + char *path = NULL; + long uid, gid; + int res; + if (!PyArg_ParseTuple(args, "etll:chown", + Py_FileSystemDefaultEncoding, &path, + &uid, &gid)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = chown(path, (uid_t) uid, (gid_t) gid); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error_with_allocated_filename(path); + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_CHOWN */ + +#ifdef HAVE_FCHOWN +PyDoc_STRVAR(posix_fchown__doc__, +"fchown(fd, uid, gid)\n\n\ +Change the owner and group id of the file given by file descriptor\n\ +fd to the numeric uid and gid."); + +static PyObject * +posix_fchown(PyObject *self, PyObject *args) +{ + int fd; + long uid, gid; + int res; + if (!PyArg_ParseTuple(args, "ill:chown", &fd, &uid, &gid)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = fchown(fd, (uid_t) uid, (gid_t) gid); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_FCHOWN */ + +#ifdef HAVE_LCHOWN +PyDoc_STRVAR(posix_lchown__doc__, +"lchown(path, uid, gid)\n\n\ +Change the owner and group id of path to the numeric uid and gid.\n\ +This function will not follow symbolic links."); + +static PyObject * +posix_lchown(PyObject *self, PyObject *args) +{ + char *path = NULL; + long uid, gid; + int res; + if (!PyArg_ParseTuple(args, "etll:lchown", + Py_FileSystemDefaultEncoding, &path, + &uid, &gid)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = lchown(path, (uid_t) uid, (gid_t) gid); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error_with_allocated_filename(path); + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_LCHOWN */ + + +#ifdef HAVE_GETCWD +PyDoc_STRVAR(posix_getcwd__doc__, +"getcwd() -> path\n\n\ +Return a string representing the current working directory."); + +static PyObject * +posix_getcwd(PyObject *self, PyObject *noargs) +{ + int bufsize_incr = 1024; + int bufsize = 0; + char *tmpbuf = NULL; + char *res = NULL; + PyObject *dynamic_return; + + Py_BEGIN_ALLOW_THREADS + do { + bufsize = bufsize + bufsize_incr; + tmpbuf = malloc(bufsize); + if (tmpbuf == NULL) { + break; + } + res = getcwd(tmpbuf, bufsize); + if (res == NULL) { + free(tmpbuf); + } + } while ((res == NULL) && (errno == ERANGE)); + Py_END_ALLOW_THREADS + + if (res == NULL) + return posix_error(); + + dynamic_return = PyString_FromString(tmpbuf); + free(tmpbuf); + + return dynamic_return; +} + +#ifdef Py_USING_UNICODE +PyDoc_STRVAR(posix_getcwdu__doc__, +"getcwdu() -> path\n\n\ +Return a unicode string representing the current working directory."); + +static PyObject * +posix_getcwdu(PyObject *self, PyObject *noargs) +{ + char buf[1026]; + char *res; + + Py_BEGIN_ALLOW_THREADS + res = getcwd(buf, sizeof buf); + Py_END_ALLOW_THREADS + if (res == NULL) + return posix_error(); + return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict"); +} +#endif /* Py_USING_UNICODE */ +#endif /* HAVE_GETCWD */ + + +PyDoc_STRVAR(posix_listdir__doc__, +"listdir(path) -> list_of_strings\n\n\ +Return a list containing the names of the entries in the directory.\n\ +\n\ + path: path of directory to list\n\ +\n\ +The list is in arbitrary order. It does not include the special\n\ +entries '.' and '..' even if they are present in the directory."); + +static PyObject * +posix_listdir(PyObject *self, PyObject *args) +{ + /* XXX Should redo this putting the (now four) versions of opendir + in separate files instead of having them all here... */ + + char *name = NULL; + char *MBname; + PyObject *d, *v; + DIR *dirp; + struct dirent *ep; + int arg_is_unicode = 1; + + errno = 0; + if (!PyArg_ParseTuple(args, "U:listdir", &v)) { + arg_is_unicode = 0; + PyErr_Clear(); + } + if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name)) + return NULL; + Py_BEGIN_ALLOW_THREADS + dirp = opendir(name); + Py_END_ALLOW_THREADS + if (dirp == NULL) { + return posix_error_with_allocated_filename(name); + } + if ((d = PyList_New(0)) == NULL) { + Py_BEGIN_ALLOW_THREADS + closedir(dirp); + Py_END_ALLOW_THREADS + PyMem_Free(name); + return NULL; + } + if((MBname = malloc(NAME_MAX)) == NULL) { + Py_BEGIN_ALLOW_THREADS + closedir(dirp); + Py_END_ALLOW_THREADS + Py_DECREF(d); + PyMem_Free(name); + return NULL; + } + for (;;) { + errno = 0; + Py_BEGIN_ALLOW_THREADS + ep = readdir(dirp); + Py_END_ALLOW_THREADS + if (ep == NULL) { + if ((errno == 0) || (errno == EISDIR)) { + break; + } else { + Py_BEGIN_ALLOW_THREADS + closedir(dirp); + Py_END_ALLOW_THREADS + Py_DECREF(d); + return posix_error_with_allocated_filename(name); + } + } + if (ep->FileName[0] == L'.' && + (NAMLEN(ep) == 1 || + (ep->FileName[1] == L'.' && NAMLEN(ep) == 2))) + continue; + if(wcstombs(MBname, ep->FileName, NAME_MAX) == -1) { + free(MBname); + Py_BEGIN_ALLOW_THREADS + closedir(dirp); + Py_END_ALLOW_THREADS + Py_DECREF(d); + PyMem_Free(name); + return NULL; + } + v = PyString_FromStringAndSize(MBname, strlen(MBname)); + if (v == NULL) { + Py_DECREF(d); + d = NULL; + break; + } +#ifdef Py_USING_UNICODE + if (arg_is_unicode) { + PyObject *w; + + w = PyUnicode_FromEncodedObject(v, + Py_FileSystemDefaultEncoding, + "strict"); + if (w != NULL) { + Py_DECREF(v); + v = w; + } + else { + /* fall back to the original byte string, as + discussed in patch #683592 */ + PyErr_Clear(); + } + } +#endif + if (PyList_Append(d, v) != 0) { + Py_DECREF(v); + Py_DECREF(d); + d = NULL; + break; + } + Py_DECREF(v); + } + Py_BEGIN_ALLOW_THREADS + closedir(dirp); + Py_END_ALLOW_THREADS + PyMem_Free(name); + if(MBname != NULL) { + free(MBname); + } + + return d; + +} /* end of posix_listdir */ + +#ifdef MS_WINDOWS +/* A helper function for abspath on win32 */ +static PyObject * +posix__getfullpathname(PyObject *self, PyObject *args) +{ + /* assume encoded strings won't more than double no of chars */ + char inbuf[MAX_PATH*2]; + char *inbufp = inbuf; + Py_ssize_t insize = sizeof(inbuf); + char outbuf[MAX_PATH*2]; + char *temp; + + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) { + Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po); + Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf; + Py_UNICODE *wtemp; + DWORD result; + PyObject *v; + result = GetFullPathNameW(wpath, + sizeof(woutbuf)/sizeof(woutbuf[0]), + woutbuf, &wtemp); + if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) { + woutbufp = malloc(result * sizeof(Py_UNICODE)); + if (!woutbufp) + return PyErr_NoMemory(); + result = GetFullPathNameW(wpath, result, woutbufp, &wtemp); + } + if (result) + v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp)); + else + v = win32_error_unicode("GetFullPathNameW", wpath); + if (woutbufp != woutbuf) + free(woutbufp); + return v; + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + + if (!PyArg_ParseTuple (args, "et#:_getfullpathname", + Py_FileSystemDefaultEncoding, &inbufp, + &insize)) + return NULL; + if (!GetFullPathName(inbuf, sizeof(outbuf)/sizeof(outbuf[0]), + outbuf, &temp)) + return win32_error("GetFullPathName", inbuf); + if (PyUnicode_Check(PyTuple_GetItem(args, 0))) { + return PyUnicode_Decode(outbuf, strlen(outbuf), + Py_FileSystemDefaultEncoding, NULL); + } + return PyString_FromString(outbuf); +} /* end of posix__getfullpathname */ +#endif /* MS_WINDOWS */ + +PyDoc_STRVAR(posix_mkdir__doc__, +"mkdir(path [, mode=0777])\n\n\ +Create a directory."); + +static PyObject * +posix_mkdir(PyObject *self, PyObject *args) +{ + int res; + char *path = NULL; + int mode = 0777; + + if (!PyArg_ParseTuple(args, "et|i:mkdir", + Py_FileSystemDefaultEncoding, &path, &mode)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = mkdir(path, mode); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error_with_allocated_filename(path); + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +} + + +/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ +#if defined(HAVE_SYS_RESOURCE_H) +#include +#endif + + +#ifdef HAVE_NICE +PyDoc_STRVAR(posix_nice__doc__, +"nice(inc) -> new_priority\n\n\ +Decrease the priority of process by inc and return the new priority."); + +static PyObject * +posix_nice(PyObject *self, PyObject *args) +{ + int increment, value; + + if (!PyArg_ParseTuple(args, "i:nice", &increment)) + return NULL; + + /* There are two flavours of 'nice': one that returns the new + priority (as required by almost all standards out there) and the + Linux/FreeBSD/BSDI one, which returns '0' on success and advices + the use of getpriority() to get the new priority. + + If we are of the nice family that returns the new priority, we + need to clear errno before the call, and check if errno is filled + before calling posix_error() on a returnvalue of -1, because the + -1 may be the actual new priority! */ + + errno = 0; + value = nice(increment); +#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY) + if (value == 0) + value = getpriority(PRIO_PROCESS, 0); +#endif + if (value == -1 && errno != 0) + /* either nice() or getpriority() returned an error */ + return posix_error(); + return PyInt_FromLong((long) value); +} +#endif /* HAVE_NICE */ + +PyDoc_STRVAR(posix_rename__doc__, +"rename(old, new)\n\n\ +Rename a file or directory."); + +static PyObject * +posix_rename(PyObject *self, PyObject *args) +{ + return posix_2str(args, "etet:rename", rename); +} + + +PyDoc_STRVAR(posix_rmdir__doc__, +"rmdir(path)\n\n\ +Remove a directory."); + +static PyObject * +posix_rmdir(PyObject *self, PyObject *args) +{ + return posix_1str(args, "et:rmdir", rmdir); +} + + +PyDoc_STRVAR(posix_stat__doc__, +"stat(path) -> stat result\n\n\ +Perform a stat system call on the given path."); + +static PyObject * +posix_stat(PyObject *self, PyObject *args) +{ + return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL); +} + + +#ifdef HAVE_SYSTEM +PyDoc_STRVAR(posix_system__doc__, +"system(command) -> exit_status\n\n\ +Execute the command (a string) in a subshell."); + +static PyObject * +posix_system(PyObject *self, PyObject *args) +{ + char *command; + long sts; + if (!PyArg_ParseTuple(args, "s:system", &command)) + return NULL; + Py_BEGIN_ALLOW_THREADS + sts = system(command); + Py_END_ALLOW_THREADS + return PyInt_FromLong(sts); +} +#endif + + +PyDoc_STRVAR(posix_umask__doc__, +"umask(new_mask) -> old_mask\n\n\ +Set the current numeric umask and return the previous umask."); + +static PyObject * +posix_umask(PyObject *self, PyObject *args) +{ + int i; + if (!PyArg_ParseTuple(args, "i:umask", &i)) + return NULL; + i = (int)umask(i); + if (i < 0) + return posix_error(); + return PyInt_FromLong((long)i); +} + + +PyDoc_STRVAR(posix_unlink__doc__, +"unlink(path)\n\n\ +Remove a file (same as remove(path))."); + +PyDoc_STRVAR(posix_remove__doc__, +"remove(path)\n\n\ +Remove a file (same as unlink(path))."); + +static PyObject * +posix_unlink(PyObject *self, PyObject *args) +{ + return posix_1str(args, "et:remove", unlink); +} + + +static int +extract_time(PyObject *t, time_t* sec, long* usec) +{ + time_t intval; + if (PyFloat_Check(t)) { + double tval = PyFloat_AsDouble(t); + PyObject *intobj = PyNumber_Long(t); + if (!intobj) + return -1; +#if SIZEOF_TIME_T > SIZEOF_LONG + intval = PyInt_AsUnsignedLongLongMask(intobj); +#else + intval = PyInt_AsLong(intobj); +#endif + Py_DECREF(intobj); + if (intval == -1 && PyErr_Occurred()) + return -1; + *sec = intval; + *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */ + if (*usec < 0) + /* If rounding gave us a negative number, + truncate. */ + *usec = 0; + return 0; + } +#if SIZEOF_TIME_T > SIZEOF_LONG + intval = PyInt_AsUnsignedLongLongMask(t); +#else + intval = PyInt_AsLong(t); +#endif + if (intval == -1 && PyErr_Occurred()) + return -1; + *sec = intval; + *usec = 0; + return 0; +} + +PyDoc_STRVAR(posix_utime__doc__, +"utime(path, (atime, mtime))\n\ +utime(path, None)\n\n\ +Set the access and modified time of the file to the given values. If the\n\ +second form is used, set the access and modified times to the current time."); + +static PyObject * +posix_utime(PyObject *self, PyObject *args) +{ + char *path = NULL; + time_t atime, mtime; + long ausec, musec; + int res; + PyObject* arg; + +#if defined(HAVE_UTIMES) + struct timeval buf[2]; +#define ATIME buf[0].tv_sec +#define MTIME buf[1].tv_sec +#elif defined(HAVE_UTIME_H) +/* XXX should define struct utimbuf instead, above */ + struct utimbuf buf; +#define ATIME buf.actime +#define MTIME buf.modtime +#define UTIME_ARG &buf +#else /* HAVE_UTIMES */ + time_t buf[2]; +#define ATIME buf[0] +#define MTIME buf[1] +#define UTIME_ARG buf +#endif /* HAVE_UTIMES */ + + + if (!PyArg_ParseTuple(args, "etO:utime", + Py_FileSystemDefaultEncoding, &path, &arg)) + return NULL; + if (arg == Py_None) { + /* optional time values not given */ + Py_BEGIN_ALLOW_THREADS + res = utime(path, NULL); + Py_END_ALLOW_THREADS + } + else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) { + PyErr_SetString(PyExc_TypeError, + "utime() arg 2 must be a tuple (atime, mtime)"); + PyMem_Free(path); + return NULL; + } + else { + if (extract_time(PyTuple_GET_ITEM(arg, 0), + &atime, &ausec) == -1) { + PyMem_Free(path); + return NULL; + } + if (extract_time(PyTuple_GET_ITEM(arg, 1), + &mtime, &musec) == -1) { + PyMem_Free(path); + return NULL; + } + ATIME = atime; + MTIME = mtime; +#ifdef HAVE_UTIMES + buf[0].tv_usec = ausec; + buf[1].tv_usec = musec; + Py_BEGIN_ALLOW_THREADS + res = utimes(path, buf); + Py_END_ALLOW_THREADS +#else + Py_BEGIN_ALLOW_THREADS + res = utime(path, UTIME_ARG); + Py_END_ALLOW_THREADS +#endif /* HAVE_UTIMES */ + } + if (res < 0) { + return posix_error_with_allocated_filename(path); + } + PyMem_Free(path); + Py_INCREF(Py_None); + return Py_None; +#undef UTIME_ARG +#undef ATIME +#undef MTIME +} + + +/* Process operations */ + +PyDoc_STRVAR(posix__exit__doc__, +"_exit(status)\n\n\ +Exit to the system with specified status, without normal exit processing."); + +static PyObject * +posix__exit(PyObject *self, PyObject *args) +{ + int sts; + if (!PyArg_ParseTuple(args, "i:_exit", &sts)) + return NULL; + _Exit(sts); + return NULL; /* Make gcc -Wall happy */ +} + +#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) +static void +free_string_array(char **array, Py_ssize_t count) +{ + Py_ssize_t i; + for (i = 0; i < count; i++) + PyMem_Free(array[i]); + PyMem_DEL(array); +} +#endif + + +#ifdef HAVE_EXECV +PyDoc_STRVAR(posix_execv__doc__, +"execv(path, args)\n\n\ +Execute an executable path with arguments, replacing current process.\n\ +\n\ + path: path of executable file\n\ + args: tuple or list of strings"); + +static PyObject * +posix_execv(PyObject *self, PyObject *args) +{ + char *path; + PyObject *argv; + char **argvlist; + Py_ssize_t i, argc; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + + /* execv has two arguments: (path, argv), where + argv is a list or tuple of strings. */ + + if (!PyArg_ParseTuple(args, "etO:execv", + Py_FileSystemDefaultEncoding, + &path, &argv)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list"); + PyMem_Free(path); + return NULL; + } + if (argc < 1) { + PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); + PyMem_Free(path); + return NULL; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyMem_Free(path); + return PyErr_NoMemory(); + } + for (i = 0; i < argc; i++) { + if (!PyArg_Parse((*getitem)(argv, i), "et", + Py_FileSystemDefaultEncoding, + &argvlist[i])) { + free_string_array(argvlist, i); + PyErr_SetString(PyExc_TypeError, + "execv() arg 2 must contain only strings"); + PyMem_Free(path); + return NULL; + + } + } + argvlist[argc] = NULL; + + execv(path, argvlist); + + /* If we get here it's definitely an error */ + + free_string_array(argvlist, argc); + PyMem_Free(path); + return posix_error(); +} + + +PyDoc_STRVAR(posix_execve__doc__, +"execve(path, args, env)\n\n\ +Execute a path with arguments and environment, replacing current process.\n\ +\n\ + path: path of executable file\n\ + args: tuple or list of arguments\n\ + env: dictionary of strings mapping to strings"); + +static PyObject * +posix_execve(PyObject *self, PyObject *args) +{ + char *path; + PyObject *argv, *env; + char **argvlist; + char **envlist; + PyObject *key, *val, *keys=NULL, *vals=NULL; + Py_ssize_t i, pos, argc, envc; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + Py_ssize_t lastarg = 0; + + /* execve has three arguments: (path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyArg_ParseTuple(args, "etOO:execve", + Py_FileSystemDefaultEncoding, + &path, &argv, &env)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "execve() arg 2 must be a tuple or list"); + goto fail_0; + } + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "execve() arg 3 must be a mapping object"); + goto fail_0; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + goto fail_0; + } + for (i = 0; i < argc; i++) { + if (!PyArg_Parse((*getitem)(argv, i), + "et;execve() arg 2 must contain only strings", + Py_FileSystemDefaultEncoding, + &argvlist[i])) + { + lastarg = i; + goto fail_1; + } + } + lastarg = argc; + argvlist[argc] = NULL; + + i = PyMapping_Size(env); + if (i < 0) + goto fail_1; + envlist = PyMem_NEW(char *, i + 1); + if (envlist == NULL) { + PyErr_NoMemory(); + goto fail_1; + } + envc = 0; + keys = PyMapping_Keys(env); + vals = PyMapping_Values(env); + if (!keys || !vals) + goto fail_2; + if (!PyList_Check(keys) || !PyList_Check(vals)) { + PyErr_SetString(PyExc_TypeError, + "execve(): env.keys() or env.values() is not a list"); + goto fail_2; + } + + for (pos = 0; pos < i; pos++) { + char *p, *k, *v; + size_t len; + + key = PyList_GetItem(keys, pos); + val = PyList_GetItem(vals, pos); + if (!key || !val) + goto fail_2; + + if (!PyArg_Parse( + key, + "s;execve() arg 3 contains a non-string key", + &k) || + !PyArg_Parse( + val, + "s;execve() arg 3 contains a non-string value", + &v)) + { + goto fail_2; + } + +#if defined(PYOS_OS2) + /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */ + if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) { +#endif + len = PyString_Size(key) + PyString_Size(val) + 2; + p = PyMem_NEW(char, len); + if (p == NULL) { + PyErr_NoMemory(); + goto fail_2; + } + PyOS_snprintf(p, len, "%s=%s", k, v); + envlist[envc++] = p; +#if defined(PYOS_OS2) + } +#endif + } + envlist[envc] = 0; + + execve(path, argvlist, envlist); + + /* If we get here it's definitely an error */ + + (void) posix_error(); + + fail_2: + while (--envc >= 0) + PyMem_DEL(envlist[envc]); + PyMem_DEL(envlist); + fail_1: + free_string_array(argvlist, lastarg); + Py_XDECREF(vals); + Py_XDECREF(keys); + fail_0: + PyMem_Free(path); + return NULL; +} +#endif /* HAVE_EXECV */ + + +#ifdef HAVE_SPAWNV +PyDoc_STRVAR(posix_spawnv__doc__, +"spawnv(mode, path, args)\n\n\ +Execute the program 'path' in a new process.\n\ +\n\ + mode: mode of process creation\n\ + path: path of executable file\n\ + args: tuple or list of strings"); + +static PyObject * +posix_spawnv(PyObject *self, PyObject *args) +{ + char *path; + PyObject *argv; + char **argvlist; + int mode, i; + Py_ssize_t argc; + Py_intptr_t spawnval; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + + /* spawnv has three arguments: (mode, path, argv), where + argv is a list or tuple of strings. */ + + if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode, + Py_FileSystemDefaultEncoding, + &path, &argv)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "spawnv() arg 2 must be a tuple or list"); + PyMem_Free(path); + return NULL; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyMem_Free(path); + return PyErr_NoMemory(); + } + for (i = 0; i < argc; i++) { + if (!PyArg_Parse((*getitem)(argv, i), "et", + Py_FileSystemDefaultEncoding, + &argvlist[i])) { + free_string_array(argvlist, i); + PyErr_SetString( + PyExc_TypeError, + "spawnv() arg 2 must contain only strings"); + PyMem_Free(path); + return NULL; + } + } + argvlist[argc] = NULL; + +#if defined(PYOS_OS2) && defined(PYCC_GCC) + Py_BEGIN_ALLOW_THREADS + spawnval = spawnv(mode, path, argvlist); + Py_END_ALLOW_THREADS +#else + if (mode == _OLD_P_OVERLAY) + mode = _P_OVERLAY; + + Py_BEGIN_ALLOW_THREADS + spawnval = _spawnv(mode, path, argvlist); + Py_END_ALLOW_THREADS +#endif + + free_string_array(argvlist, argc); + PyMem_Free(path); + + if (spawnval == -1) + return posix_error(); + else +#if SIZEOF_LONG == SIZEOF_VOID_P + return Py_BuildValue("l", (long) spawnval); +#else + return Py_BuildValue("L", (PY_LONG_LONG) spawnval); +#endif +} + + +PyDoc_STRVAR(posix_spawnve__doc__, +"spawnve(mode, path, args, env)\n\n\ +Execute the program 'path' in a new process.\n\ +\n\ + mode: mode of process creation\n\ + path: path of executable file\n\ + args: tuple or list of arguments\n\ + env: dictionary of strings mapping to strings"); + +static PyObject * +posix_spawnve(PyObject *self, PyObject *args) +{ + char *path; + PyObject *argv, *env; + char **argvlist; + char **envlist; + PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL; + int mode, pos, envc; + Py_ssize_t argc, i; + Py_intptr_t spawnval; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + Py_ssize_t lastarg = 0; + + /* spawnve has four arguments: (mode, path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode, + Py_FileSystemDefaultEncoding, + &path, &argv, &env)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "spawnve() arg 2 must be a tuple or list"); + goto fail_0; + } + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "spawnve() arg 3 must be a mapping object"); + goto fail_0; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + goto fail_0; + } + for (i = 0; i < argc; i++) { + if (!PyArg_Parse((*getitem)(argv, i), + "et;spawnve() arg 2 must contain only strings", + Py_FileSystemDefaultEncoding, + &argvlist[i])) + { + lastarg = i; + goto fail_1; + } + } + lastarg = argc; + argvlist[argc] = NULL; + + i = PyMapping_Size(env); + if (i < 0) + goto fail_1; + envlist = PyMem_NEW(char *, i + 1); + if (envlist == NULL) { + PyErr_NoMemory(); + goto fail_1; + } + envc = 0; + keys = PyMapping_Keys(env); + vals = PyMapping_Values(env); + if (!keys || !vals) + goto fail_2; + if (!PyList_Check(keys) || !PyList_Check(vals)) { + PyErr_SetString(PyExc_TypeError, + "spawnve(): env.keys() or env.values() is not a list"); + goto fail_2; + } + + for (pos = 0; pos < i; pos++) { + char *p, *k, *v; + size_t len; + + key = PyList_GetItem(keys, pos); + val = PyList_GetItem(vals, pos); + if (!key || !val) + goto fail_2; + + if (!PyArg_Parse( + key, + "s;spawnve() arg 3 contains a non-string key", + &k) || + !PyArg_Parse( + val, + "s;spawnve() arg 3 contains a non-string value", + &v)) + { + goto fail_2; + } + len = PyString_Size(key) + PyString_Size(val) + 2; + p = PyMem_NEW(char, len); + if (p == NULL) { + PyErr_NoMemory(); + goto fail_2; + } + PyOS_snprintf(p, len, "%s=%s", k, v); + envlist[envc++] = p; + } + envlist[envc] = 0; + +#if defined(PYOS_OS2) && defined(PYCC_GCC) + Py_BEGIN_ALLOW_THREADS + spawnval = spawnve(mode, path, argvlist, envlist); + Py_END_ALLOW_THREADS +#else + if (mode == _OLD_P_OVERLAY) + mode = _P_OVERLAY; + + Py_BEGIN_ALLOW_THREADS + spawnval = _spawnve(mode, path, argvlist, envlist); + Py_END_ALLOW_THREADS +#endif + + if (spawnval == -1) + (void) posix_error(); + else +#if SIZEOF_LONG == SIZEOF_VOID_P + res = Py_BuildValue("l", (long) spawnval); +#else + res = Py_BuildValue("L", (PY_LONG_LONG) spawnval); +#endif + + fail_2: + while (--envc >= 0) + PyMem_DEL(envlist[envc]); + PyMem_DEL(envlist); + fail_1: + free_string_array(argvlist, lastarg); + Py_XDECREF(vals); + Py_XDECREF(keys); + fail_0: + PyMem_Free(path); + return res; +} + +/* OS/2 supports spawnvp & spawnvpe natively */ +#if defined(PYOS_OS2) +PyDoc_STRVAR(posix_spawnvp__doc__, +"spawnvp(mode, file, args)\n\n\ +Execute the program 'file' in a new process, using the environment\n\ +search path to find the file.\n\ +\n\ + mode: mode of process creation\n\ + file: executable file name\n\ + args: tuple or list of strings"); + +static PyObject * +posix_spawnvp(PyObject *self, PyObject *args) +{ + char *path; + PyObject *argv; + char **argvlist; + int mode, i, argc; + Py_intptr_t spawnval; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + + /* spawnvp has three arguments: (mode, path, argv), where + argv is a list or tuple of strings. */ + + if (!PyArg_ParseTuple(args, "ietO:spawnvp", &mode, + Py_FileSystemDefaultEncoding, + &path, &argv)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "spawnvp() arg 2 must be a tuple or list"); + PyMem_Free(path); + return NULL; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyMem_Free(path); + return PyErr_NoMemory(); + } + for (i = 0; i < argc; i++) { + if (!PyArg_Parse((*getitem)(argv, i), "et", + Py_FileSystemDefaultEncoding, + &argvlist[i])) { + free_string_array(argvlist, i); + PyErr_SetString( + PyExc_TypeError, + "spawnvp() arg 2 must contain only strings"); + PyMem_Free(path); + return NULL; + } + } + argvlist[argc] = NULL; + + Py_BEGIN_ALLOW_THREADS +#if defined(PYCC_GCC) + spawnval = spawnvp(mode, path, argvlist); +#else + spawnval = _spawnvp(mode, path, argvlist); +#endif + Py_END_ALLOW_THREADS + + free_string_array(argvlist, argc); + PyMem_Free(path); + + if (spawnval == -1) + return posix_error(); + else + return Py_BuildValue("l", (long) spawnval); +} + + +PyDoc_STRVAR(posix_spawnvpe__doc__, +"spawnvpe(mode, file, args, env)\n\n\ +Execute the program 'file' in a new process, using the environment\n\ +search path to find the file.\n\ +\n\ + mode: mode of process creation\n\ + file: executable file name\n\ + args: tuple or list of arguments\n\ + env: dictionary of strings mapping to strings"); + +static PyObject * +posix_spawnvpe(PyObject *self, PyObject *args) +{ + char *path; + PyObject *argv, *env; + char **argvlist; + char **envlist; + PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL; + int mode, i, pos, argc, envc; + Py_intptr_t spawnval; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + int lastarg = 0; + + /* spawnvpe has four arguments: (mode, path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode, + Py_FileSystemDefaultEncoding, + &path, &argv, &env)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "spawnvpe() arg 2 must be a tuple or list"); + goto fail_0; + } + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "spawnvpe() arg 3 must be a mapping object"); + goto fail_0; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + goto fail_0; + } + for (i = 0; i < argc; i++) { + if (!PyArg_Parse((*getitem)(argv, i), + "et;spawnvpe() arg 2 must contain only strings", + Py_FileSystemDefaultEncoding, + &argvlist[i])) + { + lastarg = i; + goto fail_1; + } + } + lastarg = argc; + argvlist[argc] = NULL; + + i = PyMapping_Size(env); + if (i < 0) + goto fail_1; + envlist = PyMem_NEW(char *, i + 1); + if (envlist == NULL) { + PyErr_NoMemory(); + goto fail_1; + } + envc = 0; + keys = PyMapping_Keys(env); + vals = PyMapping_Values(env); + if (!keys || !vals) + goto fail_2; + if (!PyList_Check(keys) || !PyList_Check(vals)) { + PyErr_SetString(PyExc_TypeError, + "spawnvpe(): env.keys() or env.values() is not a list"); + goto fail_2; + } + + for (pos = 0; pos < i; pos++) { + char *p, *k, *v; + size_t len; + + key = PyList_GetItem(keys, pos); + val = PyList_GetItem(vals, pos); + if (!key || !val) + goto fail_2; + + if (!PyArg_Parse( + key, + "s;spawnvpe() arg 3 contains a non-string key", + &k) || + !PyArg_Parse( + val, + "s;spawnvpe() arg 3 contains a non-string value", + &v)) + { + goto fail_2; + } + len = PyString_Size(key) + PyString_Size(val) + 2; + p = PyMem_NEW(char, len); + if (p == NULL) { + PyErr_NoMemory(); + goto fail_2; + } + PyOS_snprintf(p, len, "%s=%s", k, v); + envlist[envc++] = p; + } + envlist[envc] = 0; + + Py_BEGIN_ALLOW_THREADS +#if defined(PYCC_GCC) + spawnval = spawnvpe(mode, path, argvlist, envlist); +#else + spawnval = _spawnvpe(mode, path, argvlist, envlist); +#endif + Py_END_ALLOW_THREADS + + if (spawnval == -1) + (void) posix_error(); + else + res = Py_BuildValue("l", (long) spawnval); + + fail_2: + while (--envc >= 0) + PyMem_DEL(envlist[envc]); + PyMem_DEL(envlist); + fail_1: + free_string_array(argvlist, lastarg); + Py_XDECREF(vals); + Py_XDECREF(keys); + fail_0: + PyMem_Free(path); + return res; +} +#endif /* PYOS_OS2 */ +#endif /* HAVE_SPAWNV */ + + +#ifdef HAVE_FORK1 +PyDoc_STRVAR(posix_fork1__doc__, +"fork1() -> pid\n\n\ +Fork a child process with a single multiplexed (i.e., not bound) thread.\n\ +\n\ +Return 0 to child process and PID of child to parent process."); + +static PyObject * +posix_fork1(PyObject *self, PyObject *noargs) +{ + pid_t pid; + int result = 0; + _PyImport_AcquireLock(); + pid = fork1(); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork(); + } else { + /* parent: release the import lock. */ + result = _PyImport_ReleaseLock(); + } + if (pid == -1) + return posix_error(); + if (result < 0) { + /* Don't clobber the OSError if the fork failed. */ + PyErr_SetString(PyExc_RuntimeError, + "not holding the import lock"); + return NULL; + } + return PyLong_FromPid(pid); +} +#endif + + +#ifdef HAVE_FORK +PyDoc_STRVAR(posix_fork__doc__, +"fork() -> pid\n\n\ +Fork a child process.\n\ +Return 0 to child process and PID of child to parent process."); + +static PyObject * +posix_fork(PyObject *self, PyObject *noargs) +{ + pid_t pid; + int result = 0; + _PyImport_AcquireLock(); + pid = fork(); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork(); + } else { + /* parent: release the import lock. */ + result = _PyImport_ReleaseLock(); + } + if (pid == -1) + return posix_error(); + if (result < 0) { + /* Don't clobber the OSError if the fork failed. */ + PyErr_SetString(PyExc_RuntimeError, + "not holding the import lock"); + return NULL; + } + return PyLong_FromPid(pid); +} +#endif + +/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ +/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */ +#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) +#define DEV_PTY_FILE "/dev/ptc" +#define HAVE_DEV_PTMX +#else +#define DEV_PTY_FILE "/dev/ptmx" +#endif + +#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) +#ifdef HAVE_PTY_H +#include +#else +#ifdef HAVE_LIBUTIL_H +#include +#else +#ifdef HAVE_UTIL_H +#include +#endif /* HAVE_UTIL_H */ +#endif /* HAVE_LIBUTIL_H */ +#endif /* HAVE_PTY_H */ +#ifdef HAVE_STROPTS_H +#include +#endif +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ + +#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) +PyDoc_STRVAR(posix_openpty__doc__, +"openpty() -> (master_fd, slave_fd)\n\n\ +Open a pseudo-terminal, returning open fd's for both master and slave end.\n"); + +static PyObject * +posix_openpty(PyObject *self, PyObject *noargs) +{ + int master_fd, slave_fd; +#ifndef HAVE_OPENPTY + char * slave_name; +#endif +#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) + PyOS_sighandler_t sig_saved; +#ifdef sun + extern char *ptsname(int fildes); +#endif +#endif + +#ifdef HAVE_OPENPTY + if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) + return posix_error(); +#elif defined(HAVE__GETPTY) + slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); + if (slave_name == NULL) + return posix_error(); + + slave_fd = open(slave_name, O_RDWR); + if (slave_fd < 0) + return posix_error(); +#else + master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ + if (master_fd < 0) + return posix_error(); + sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); + /* change permission of slave */ + if (grantpt(master_fd) < 0) { + PyOS_setsig(SIGCHLD, sig_saved); + return posix_error(); + } + /* unlock slave */ + if (unlockpt(master_fd) < 0) { + PyOS_setsig(SIGCHLD, sig_saved); + return posix_error(); + } + PyOS_setsig(SIGCHLD, sig_saved); + slave_name = ptsname(master_fd); /* get name of slave */ + if (slave_name == NULL) + return posix_error(); + slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ + if (slave_fd < 0) + return posix_error(); +#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) + ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ + ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ +#ifndef __hpux + ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ +#endif /* __hpux */ +#endif /* HAVE_CYGWIN */ +#endif /* HAVE_OPENPTY */ + + return Py_BuildValue("(ii)", master_fd, slave_fd); + +} +#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ + +#ifdef HAVE_FORKPTY +PyDoc_STRVAR(posix_forkpty__doc__, +"forkpty() -> (pid, master_fd)\n\n\ +Fork a new process with a new pseudo-terminal as controlling tty.\n\n\ +Like fork(), return 0 as pid to child process, and PID of child to parent.\n\ +To both, return fd of newly opened pseudo-terminal.\n"); + +static PyObject * +posix_forkpty(PyObject *self, PyObject *noargs) +{ + int master_fd = -1, result = 0; + pid_t pid; + + _PyImport_AcquireLock(); + pid = forkpty(&master_fd, NULL, NULL, NULL); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork(); + } else { + /* parent: release the import lock. */ + result = _PyImport_ReleaseLock(); + } + if (pid == -1) + return posix_error(); + if (result < 0) { + /* Don't clobber the OSError if the fork failed. */ + PyErr_SetString(PyExc_RuntimeError, + "not holding the import lock"); + return NULL; + } + return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); +} +#endif + +#ifdef HAVE_GETEGID +PyDoc_STRVAR(posix_getegid__doc__, +"getegid() -> egid\n\n\ +Return the current process's effective group id."); + +static PyObject * +posix_getegid(PyObject *self, PyObject *noargs) +{ + return PyInt_FromLong((long)getegid()); +} +#endif + + +#ifdef HAVE_GETEUID +PyDoc_STRVAR(posix_geteuid__doc__, +"geteuid() -> euid\n\n\ +Return the current process's effective user id."); + +static PyObject * +posix_geteuid(PyObject *self, PyObject *noargs) +{ + return PyInt_FromLong((long)geteuid()); +} +#endif + + +#ifdef HAVE_GETGID +PyDoc_STRVAR(posix_getgid__doc__, +"getgid() -> gid\n\n\ +Return the current process's group id."); + +static PyObject * +posix_getgid(PyObject *self, PyObject *noargs) +{ + return PyInt_FromLong((long)getgid()); +} +#endif + + +PyDoc_STRVAR(posix_getpid__doc__, +"getpid() -> pid\n\n\ +Return the current process id"); + +static PyObject * +posix_getpid(PyObject *self, PyObject *noargs) +{ + return PyLong_FromPid(getpid()); +} + + +#ifdef HAVE_GETGROUPS +PyDoc_STRVAR(posix_getgroups__doc__, +"getgroups() -> list of group IDs\n\n\ +Return list of supplemental group IDs for the process."); + +static PyObject * +posix_getgroups(PyObject *self, PyObject *noargs) +{ + PyObject *result = NULL; + +#ifdef NGROUPS_MAX +#define MAX_GROUPS NGROUPS_MAX +#else + /* defined to be 16 on Solaris7, so this should be a small number */ +#define MAX_GROUPS 64 +#endif + gid_t grouplist[MAX_GROUPS]; + + /* On MacOSX getgroups(2) can return more than MAX_GROUPS results + * This is a helper variable to store the intermediate result when + * that happens. + * + * To keep the code readable the OSX behaviour is unconditional, + * according to the POSIX spec this should be safe on all unix-y + * systems. + */ + gid_t* alt_grouplist = grouplist; + int n; + + n = getgroups(MAX_GROUPS, grouplist); + if (n < 0) { + if (errno == EINVAL) { + n = getgroups(0, NULL); + if (n == -1) { + return posix_error(); + } + if (n == 0) { + /* Avoid malloc(0) */ + alt_grouplist = grouplist; + } else { + alt_grouplist = PyMem_Malloc(n * sizeof(gid_t)); + if (alt_grouplist == NULL) { + errno = EINVAL; + return posix_error(); + } + n = getgroups(n, alt_grouplist); + if (n == -1) { + PyMem_Free(alt_grouplist); + return posix_error(); + } + } + } else { + return posix_error(); + } + } + result = PyList_New(n); + if (result != NULL) { + int i; + for (i = 0; i < n; ++i) { + PyObject *o = PyInt_FromLong((long)alt_grouplist[i]); + if (o == NULL) { + Py_DECREF(result); + result = NULL; + break; + } + PyList_SET_ITEM(result, i, o); + } + } + + if (alt_grouplist != grouplist) { + PyMem_Free(alt_grouplist); + } + + return result; +} +#endif + +#ifdef HAVE_INITGROUPS +PyDoc_STRVAR(posix_initgroups__doc__, +"initgroups(username, gid) -> None\n\n\ +Call the system initgroups() to initialize the group access list with all of\n\ +the groups of which the specified username is a member, plus the specified\n\ +group id."); + +static PyObject * +posix_initgroups(PyObject *self, PyObject *args) +{ + char *username; + long gid; + + if (!PyArg_ParseTuple(args, "sl:initgroups", &username, &gid)) + return NULL; + + if (initgroups(username, (gid_t) gid) == -1) + return PyErr_SetFromErrno(PyExc_OSError); + + Py_INCREF(Py_None); + return Py_None; +} +#endif + +#ifdef HAVE_GETPGID +PyDoc_STRVAR(posix_getpgid__doc__, +"getpgid(pid) -> pgid\n\n\ +Call the system call getpgid()."); + +static PyObject * +posix_getpgid(PyObject *self, PyObject *args) +{ + pid_t pid, pgid; + if (!PyArg_ParseTuple(args, PARSE_PID ":getpgid", &pid)) + return NULL; + pgid = getpgid(pid); + if (pgid < 0) + return posix_error(); + return PyLong_FromPid(pgid); +} +#endif /* HAVE_GETPGID */ + + +#ifdef HAVE_GETPGRP +PyDoc_STRVAR(posix_getpgrp__doc__, +"getpgrp() -> pgrp\n\n\ +Return the current process group id."); + +static PyObject * +posix_getpgrp(PyObject *self, PyObject *noargs) +{ +#ifdef GETPGRP_HAVE_ARG + return PyLong_FromPid(getpgrp(0)); +#else /* GETPGRP_HAVE_ARG */ + return PyLong_FromPid(getpgrp()); +#endif /* GETPGRP_HAVE_ARG */ +} +#endif /* HAVE_GETPGRP */ + + +#ifdef HAVE_SETPGRP +PyDoc_STRVAR(posix_setpgrp__doc__, +"setpgrp()\n\n\ +Make this process the process group leader."); + +static PyObject * +posix_setpgrp(PyObject *self, PyObject *noargs) +{ +#ifdef SETPGRP_HAVE_ARG + if (setpgrp(0, 0) < 0) +#else /* SETPGRP_HAVE_ARG */ + if (setpgrp() < 0) +#endif /* SETPGRP_HAVE_ARG */ + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} + +#endif /* HAVE_SETPGRP */ + +#ifdef HAVE_GETPPID +PyDoc_STRVAR(posix_getppid__doc__, +"getppid() -> ppid\n\n\ +Return the parent's process id."); + +static PyObject * +posix_getppid(PyObject *self, PyObject *noargs) +{ + return PyLong_FromPid(getppid()); +} +#endif + + +#ifdef HAVE_GETLOGIN +PyDoc_STRVAR(posix_getlogin__doc__, +"getlogin() -> string\n\n\ +Return the actual login name."); + +static PyObject * +posix_getlogin(PyObject *self, PyObject *noargs) +{ + PyObject *result = NULL; + char *name; + int old_errno = errno; + + errno = 0; + name = getlogin(); + if (name == NULL) { + if (errno) + posix_error(); + else + PyErr_SetString(PyExc_OSError, + "unable to determine login name"); + } + else + result = PyString_FromString(name); + errno = old_errno; + + return result; +} +#endif + +PyDoc_STRVAR(posix_getuid__doc__, +"getuid() -> uid\n\n\ +Return the current process's user id."); + +static PyObject * +posix_getuid(PyObject *self, PyObject *noargs) +{ + return PyInt_FromLong((long)getuid()); +} + + +#ifdef HAVE_KILL +PyDoc_STRVAR(posix_kill__doc__, +"kill(pid, sig)\n\n\ +Kill a process with a signal."); + +static PyObject * +posix_kill(PyObject *self, PyObject *args) +{ + pid_t pid; + int sig; + if (!PyArg_ParseTuple(args, PARSE_PID "i:kill", &pid, &sig)) + return NULL; +#if defined(PYOS_OS2) && !defined(PYCC_GCC) + if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) { + APIRET rc; + if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR) + return os2_error(rc); + + } else if (sig == XCPT_SIGNAL_KILLPROC) { + APIRET rc; + if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR) + return os2_error(rc); + + } else + return NULL; /* Unrecognized Signal Requested */ +#else + if (kill(pid, sig) == -1) + return posix_error(); +#endif + Py_INCREF(Py_None); + return Py_None; +} +#endif + +#ifdef HAVE_KILLPG +PyDoc_STRVAR(posix_killpg__doc__, +"killpg(pgid, sig)\n\n\ +Kill a process group with a signal."); + +static PyObject * +posix_killpg(PyObject *self, PyObject *args) +{ + int sig; + pid_t pgid; + /* XXX some man pages make the `pgid` parameter an int, others + a pid_t. Since getpgrp() returns a pid_t, we assume killpg should + take the same type. Moreover, pid_t is always at least as wide as + int (else compilation of this module fails), which is safe. */ + if (!PyArg_ParseTuple(args, PARSE_PID "i:killpg", &pgid, &sig)) + return NULL; + if (killpg(pgid, sig) == -1) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif + +#ifdef HAVE_PLOCK + +#ifdef HAVE_SYS_LOCK_H +#include +#endif + +PyDoc_STRVAR(posix_plock__doc__, +"plock(op)\n\n\ +Lock program segments into memory."); + +static PyObject * +posix_plock(PyObject *self, PyObject *args) +{ + int op; + if (!PyArg_ParseTuple(args, "i:plock", &op)) + return NULL; + if (plock(op) == -1) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif + + +#ifdef HAVE_POPEN +PyDoc_STRVAR(posix_popen__doc__, +"popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\ +Open a pipe to/from a command returning a file object."); + +#if defined(PYOS_OS2) +#if defined(PYCC_VACPP) +static int +async_system(const char *command) +{ + char errormsg[256], args[1024]; + RESULTCODES rcodes; + APIRET rc; + + char *shell = getenv("COMSPEC"); + if (!shell) + shell = "cmd"; + + /* avoid overflowing the argument buffer */ + if (strlen(shell) + 3 + strlen(command) >= 1024) + return ERROR_NOT_ENOUGH_MEMORY + + args[0] = '\0'; + strcat(args, shell); + strcat(args, "/c "); + strcat(args, command); + + /* execute asynchronously, inheriting the environment */ + rc = DosExecPgm(errormsg, + sizeof(errormsg), + EXEC_ASYNC, + args, + NULL, + &rcodes, + shell); + return rc; +} + +static FILE * +popen(const char *command, const char *mode, int pipesize, int *err) +{ + int oldfd, tgtfd; + HFILE pipeh[2]; + APIRET rc; + + /* mode determines which of stdin or stdout is reconnected to + * the pipe to the child + */ + if (strchr(mode, 'r') != NULL) { + tgt_fd = 1; /* stdout */ + } else if (strchr(mode, 'w')) { + tgt_fd = 0; /* stdin */ + } else { + *err = ERROR_INVALID_ACCESS; + return NULL; + } + + /* setup the pipe */ + if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) { + *err = rc; + return NULL; + } + + /* prevent other threads accessing stdio */ + DosEnterCritSec(); + + /* reconnect stdio and execute child */ + oldfd = dup(tgtfd); + close(tgtfd); + if (dup2(pipeh[tgtfd], tgtfd) == 0) { + DosClose(pipeh[tgtfd]); + rc = async_system(command); + } + + /* restore stdio */ + dup2(oldfd, tgtfd); + close(oldfd); + + /* allow other threads access to stdio */ + DosExitCritSec(); + + /* if execution of child was successful return file stream */ + if (rc == NO_ERROR) + return fdopen(pipeh[1 - tgtfd], mode); + else { + DosClose(pipeh[1 - tgtfd]); + *err = rc; + return NULL; + } +} + +static PyObject * +posix_popen(PyObject *self, PyObject *args) +{ + char *name; + char *mode = "r"; + int err, bufsize = -1; + FILE *fp; + PyObject *f; + if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize)) + return NULL; + Py_BEGIN_ALLOW_THREADS + fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err); + Py_END_ALLOW_THREADS + if (fp == NULL) + return os2_error(err); + + f = PyFile_FromFile(fp, name, mode, fclose); + if (f != NULL) + PyFile_SetBufSize(f, bufsize); + return f; +} + +#elif defined(PYCC_GCC) + +/* standard posix version of popen() support */ +static PyObject * +posix_popen(PyObject *self, PyObject *args) +{ + char *name; + char *mode = "r"; + int bufsize = -1; + FILE *fp; + PyObject *f; + if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize)) + return NULL; + Py_BEGIN_ALLOW_THREADS + fp = popen(name, mode); + Py_END_ALLOW_THREADS + if (fp == NULL) + return posix_error(); + f = PyFile_FromFile(fp, name, mode, pclose); + if (f != NULL) + PyFile_SetBufSize(f, bufsize); + return f; +} + +/* fork() under OS/2 has lots'o'warts + * EMX supports pipe() and spawn*() so we can synthesize popen[234]() + * most of this code is a ripoff of the win32 code, but using the + * capabilities of EMX's C library routines + */ + +/* These tell _PyPopen() whether to return 1, 2, or 3 file objects. */ +#define POPEN_1 1 +#define POPEN_2 2 +#define POPEN_3 3 +#define POPEN_4 4 + +static PyObject *_PyPopen(char *, int, int, int); +static int _PyPclose(FILE *file); + +/* + * Internal dictionary mapping popen* file pointers to process handles, + * for use when retrieving the process exit code. See _PyPclose() below + * for more information on this dictionary's use. + */ +static PyObject *_PyPopenProcs = NULL; + +/* os2emx version of popen2() + * + * The result of this function is a pipe (file) connected to the + * process's stdin, and a pipe connected to the process's stdout. + */ + +static PyObject * +os2emx_popen2(PyObject *self, PyObject *args) +{ + PyObject *f; + int tm=0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'"); + return NULL; + } else + tm = O_BINARY; + + f = _PyPopen(cmdstring, tm, POPEN_2, bufsize); + + return f; +} + +/* + * Variation on os2emx.popen2 + * + * The result of this function is 3 pipes - the process's stdin, + * stdout and stderr + */ + +static PyObject * +os2emx_popen3(PyObject *self, PyObject *args) +{ + PyObject *f; + int tm = 0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'"); + return NULL; + } else + tm = O_BINARY; + + f = _PyPopen(cmdstring, tm, POPEN_3, bufsize); + + return f; +} + +/* + * Variation on os2emx.popen2 + * + * The result of this function is 2 pipes - the processes stdin, + * and stdout+stderr combined as a single pipe. + */ + +static PyObject * +os2emx_popen4(PyObject *self, PyObject *args) +{ + PyObject *f; + int tm = 0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'"); + return NULL; + } else + tm = O_BINARY; + + f = _PyPopen(cmdstring, tm, POPEN_4, bufsize); + + return f; +} + +/* a couple of structures for convenient handling of multiple + * file handles and pipes + */ +struct file_ref +{ + int handle; + int flags; +}; + +struct pipe_ref +{ + int rd; + int wr; +}; + +/* The following code is derived from the win32 code */ + +static PyObject * +_PyPopen(char *cmdstring, int mode, int n, int bufsize) +{ + struct file_ref stdio[3]; + struct pipe_ref p_fd[3]; + FILE *p_s[3]; + int file_count, i, pipe_err; + pid_t pipe_pid; + char *shell, *sh_name, *opt, *rd_mode, *wr_mode; + PyObject *f, *p_f[3]; + + /* file modes for subsequent fdopen's on pipe handles */ + if (mode == O_TEXT) + { + rd_mode = "rt"; + wr_mode = "wt"; + } + else + { + rd_mode = "rb"; + wr_mode = "wb"; + } + + /* prepare shell references */ + if ((shell = getenv("EMXSHELL")) == NULL) + if ((shell = getenv("COMSPEC")) == NULL) + { + errno = ENOENT; + return posix_error(); + } + + sh_name = _getname(shell); + if (stricmp(sh_name, "cmd.exe") == 0 || stricmp(sh_name, "4os2.exe") == 0) + opt = "/c"; + else + opt = "-c"; + + /* save current stdio fds + their flags, and set not inheritable */ + i = pipe_err = 0; + while (pipe_err >= 0 && i < 3) + { + pipe_err = stdio[i].handle = dup(i); + stdio[i].flags = fcntl(i, F_GETFD, 0); + fcntl(stdio[i].handle, F_SETFD, stdio[i].flags | FD_CLOEXEC); + i++; + } + if (pipe_err < 0) + { + /* didn't get them all saved - clean up and bail out */ + int saved_err = errno; + while (i-- > 0) + { + close(stdio[i].handle); + } + errno = saved_err; + return posix_error(); + } + + /* create pipe ends */ + file_count = 2; + if (n == POPEN_3) + file_count = 3; + i = pipe_err = 0; + while ((pipe_err == 0) && (i < file_count)) + pipe_err = pipe((int *)&p_fd[i++]); + if (pipe_err < 0) + { + /* didn't get them all made - clean up and bail out */ + while (i-- > 0) + { + close(p_fd[i].wr); + close(p_fd[i].rd); + } + errno = EPIPE; + return posix_error(); + } + + /* change the actual standard IO streams over temporarily, + * making the retained pipe ends non-inheritable + */ + pipe_err = 0; + + /* - stdin */ + if (dup2(p_fd[0].rd, 0) == 0) + { + close(p_fd[0].rd); + i = fcntl(p_fd[0].wr, F_GETFD, 0); + fcntl(p_fd[0].wr, F_SETFD, i | FD_CLOEXEC); + if ((p_s[0] = fdopen(p_fd[0].wr, wr_mode)) == NULL) + { + close(p_fd[0].wr); + pipe_err = -1; + } + } + else + { + pipe_err = -1; + } + + /* - stdout */ + if (pipe_err == 0) + { + if (dup2(p_fd[1].wr, 1) == 1) + { + close(p_fd[1].wr); + i = fcntl(p_fd[1].rd, F_GETFD, 0); + fcntl(p_fd[1].rd, F_SETFD, i | FD_CLOEXEC); + if ((p_s[1] = fdopen(p_fd[1].rd, rd_mode)) == NULL) + { + close(p_fd[1].rd); + pipe_err = -1; + } + } + else + { + pipe_err = -1; + } + } + + /* - stderr, as required */ + if (pipe_err == 0) + switch (n) + { + case POPEN_3: + { + if (dup2(p_fd[2].wr, 2) == 2) + { + close(p_fd[2].wr); + i = fcntl(p_fd[2].rd, F_GETFD, 0); + fcntl(p_fd[2].rd, F_SETFD, i | FD_CLOEXEC); + if ((p_s[2] = fdopen(p_fd[2].rd, rd_mode)) == NULL) + { + close(p_fd[2].rd); + pipe_err = -1; + } + } + else + { + pipe_err = -1; + } + break; + } + + case POPEN_4: + { + if (dup2(1, 2) != 2) + { + pipe_err = -1; + } + break; + } + } + + /* spawn the child process */ + if (pipe_err == 0) + { + pipe_pid = spawnlp(P_NOWAIT, shell, shell, opt, cmdstring, (char *)0); + if (pipe_pid == -1) + { + pipe_err = -1; + } + else + { + /* save the PID into the FILE structure + * NOTE: this implementation doesn't actually + * take advantage of this, but do it for + * completeness - AIM Apr01 + */ + for (i = 0; i < file_count; i++) + p_s[i]->_pid = pipe_pid; + } + } + + /* reset standard IO to normal */ + for (i = 0; i < 3; i++) + { + dup2(stdio[i].handle, i); + fcntl(i, F_SETFD, stdio[i].flags); + close(stdio[i].handle); + } + + /* if any remnant problems, clean up and bail out */ + if (pipe_err < 0) + { + for (i = 0; i < 3; i++) + { + close(p_fd[i].rd); + close(p_fd[i].wr); + } + errno = EPIPE; + return posix_error_with_filename(cmdstring); + } + + /* build tuple of file objects to return */ + if ((p_f[0] = PyFile_FromFile(p_s[0], cmdstring, wr_mode, _PyPclose)) != NULL) + PyFile_SetBufSize(p_f[0], bufsize); + if ((p_f[1] = PyFile_FromFile(p_s[1], cmdstring, rd_mode, _PyPclose)) != NULL) + PyFile_SetBufSize(p_f[1], bufsize); + if (n == POPEN_3) + { + if ((p_f[2] = PyFile_FromFile(p_s[2], cmdstring, rd_mode, _PyPclose)) != NULL) + PyFile_SetBufSize(p_f[0], bufsize); + f = PyTuple_Pack(3, p_f[0], p_f[1], p_f[2]); + } + else + f = PyTuple_Pack(2, p_f[0], p_f[1]); + + /* + * Insert the files we've created into the process dictionary + * all referencing the list with the process handle and the + * initial number of files (see description below in _PyPclose). + * Since if _PyPclose later tried to wait on a process when all + * handles weren't closed, it could create a deadlock with the + * child, we spend some energy here to try to ensure that we + * either insert all file handles into the dictionary or none + * at all. It's a little clumsy with the various popen modes + * and variable number of files involved. + */ + if (!_PyPopenProcs) + { + _PyPopenProcs = PyDict_New(); + } + + if (_PyPopenProcs) + { + PyObject *procObj, *pidObj, *intObj, *fileObj[3]; + int ins_rc[3]; + + fileObj[0] = fileObj[1] = fileObj[2] = NULL; + ins_rc[0] = ins_rc[1] = ins_rc[2] = 0; + + procObj = PyList_New(2); + pidObj = PyLong_FromPid(pipe_pid); + intObj = PyInt_FromLong((long) file_count); + + if (procObj && pidObj && intObj) + { + PyList_SetItem(procObj, 0, pidObj); + PyList_SetItem(procObj, 1, intObj); + + fileObj[0] = PyLong_FromVoidPtr(p_s[0]); + if (fileObj[0]) + { + ins_rc[0] = PyDict_SetItem(_PyPopenProcs, + fileObj[0], + procObj); + } + fileObj[1] = PyLong_FromVoidPtr(p_s[1]); + if (fileObj[1]) + { + ins_rc[1] = PyDict_SetItem(_PyPopenProcs, + fileObj[1], + procObj); + } + if (file_count >= 3) + { + fileObj[2] = PyLong_FromVoidPtr(p_s[2]); + if (fileObj[2]) + { + ins_rc[2] = PyDict_SetItem(_PyPopenProcs, + fileObj[2], + procObj); + } + } + + if (ins_rc[0] < 0 || !fileObj[0] || + ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) || + ins_rc[2] < 0 || (file_count > 2 && !fileObj[2])) + { + /* Something failed - remove any dictionary + * entries that did make it. + */ + if (!ins_rc[0] && fileObj[0]) + { + PyDict_DelItem(_PyPopenProcs, + fileObj[0]); + } + if (!ins_rc[1] && fileObj[1]) + { + PyDict_DelItem(_PyPopenProcs, + fileObj[1]); + } + if (!ins_rc[2] && fileObj[2]) + { + PyDict_DelItem(_PyPopenProcs, + fileObj[2]); + } + } + } + + /* + * Clean up our localized references for the dictionary keys + * and value since PyDict_SetItem will Py_INCREF any copies + * that got placed in the dictionary. + */ + Py_XDECREF(procObj); + Py_XDECREF(fileObj[0]); + Py_XDECREF(fileObj[1]); + Py_XDECREF(fileObj[2]); + } + + /* Child is launched. */ + return f; +} + +/* + * Wrapper for fclose() to use for popen* files, so we can retrieve the + * exit code for the child process and return as a result of the close. + * + * This function uses the _PyPopenProcs dictionary in order to map the + * input file pointer to information about the process that was + * originally created by the popen* call that created the file pointer. + * The dictionary uses the file pointer as a key (with one entry + * inserted for each file returned by the original popen* call) and a + * single list object as the value for all files from a single call. + * The list object contains the Win32 process handle at [0], and a file + * count at [1], which is initialized to the total number of file + * handles using that list. + * + * This function closes whichever handle it is passed, and decrements + * the file count in the dictionary for the process handle pointed to + * by this file. On the last close (when the file count reaches zero), + * this function will wait for the child process and then return its + * exit code as the result of the close() operation. This permits the + * files to be closed in any order - it is always the close() of the + * final handle that will return the exit code. + * + * NOTE: This function is currently called with the GIL released. + * hence we use the GILState API to manage our state. + */ + +static int _PyPclose(FILE *file) +{ + int result; + int exit_code; + pid_t pipe_pid; + PyObject *procObj, *pidObj, *intObj, *fileObj; + int file_count; +#ifdef WITH_THREAD + PyGILState_STATE state; +#endif + + /* Close the file handle first, to ensure it can't block the + * child from exiting if it's the last handle. + */ + result = fclose(file); + +#ifdef WITH_THREAD + state = PyGILState_Ensure(); +#endif + if (_PyPopenProcs) + { + if ((fileObj = PyLong_FromVoidPtr(file)) != NULL && + (procObj = PyDict_GetItem(_PyPopenProcs, + fileObj)) != NULL && + (pidObj = PyList_GetItem(procObj,0)) != NULL && + (intObj = PyList_GetItem(procObj,1)) != NULL) + { + pipe_pid = (pid_t) PyLong_AsPid(pidObj); + file_count = (int) PyInt_AsLong(intObj); + + if (file_count > 1) + { + /* Still other files referencing process */ + file_count--; + PyList_SetItem(procObj,1, + PyInt_FromLong((long) file_count)); + } + else + { + /* Last file for this process */ + if (result != EOF && + waitpid(pipe_pid, &exit_code, 0) == pipe_pid) + { + /* extract exit status */ + if (WIFEXITED(exit_code)) + { + result = WEXITSTATUS(exit_code); + } + else + { + errno = EPIPE; + result = -1; + } + } + else + { + /* Indicate failure - this will cause the file object + * to raise an I/O error and translate the last + * error code from errno. We do have a problem with + * last errors that overlap the normal errno table, + * but that's a consistent problem with the file object. + */ + result = -1; + } + } + + /* Remove this file pointer from dictionary */ + PyDict_DelItem(_PyPopenProcs, fileObj); + + if (PyDict_Size(_PyPopenProcs) == 0) + { + Py_DECREF(_PyPopenProcs); + _PyPopenProcs = NULL; + } + + } /* if object retrieval ok */ + + Py_XDECREF(fileObj); + } /* if _PyPopenProcs */ + +#ifdef WITH_THREAD + PyGILState_Release(state); +#endif + return result; +} + +#endif /* PYCC_??? */ + +#elif defined(MS_WINDOWS) + +/* + * Portable 'popen' replacement for Win32. + * + * Written by Bill Tutt . Minor tweaks + * and 2.0 integration by Fredrik Lundh + * Return code handling by David Bolen . + */ + +#include +#include +#include + +/* These tell _PyPopen() wether to return 1, 2, or 3 file objects. */ +#define POPEN_1 1 +#define POPEN_2 2 +#define POPEN_3 3 +#define POPEN_4 4 + +static PyObject *_PyPopen(char *, int, int); +static int _PyPclose(FILE *file); + +/* + * Internal dictionary mapping popen* file pointers to process handles, + * for use when retrieving the process exit code. See _PyPclose() below + * for more information on this dictionary's use. + */ +static PyObject *_PyPopenProcs = NULL; + + +/* popen that works from a GUI. + * + * The result of this function is a pipe (file) connected to the + * processes stdin or stdout, depending on the requested mode. + */ + +static PyObject * +posix_popen(PyObject *self, PyObject *args) +{ + PyObject *f; + int tm = 0; + + char *cmdstring; + char *mode = "r"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 'r') + tm = _O_RDONLY; + else if (*mode != 'w') { + PyErr_SetString(PyExc_ValueError, "popen() arg 2 must be 'r' or 'w'"); + return NULL; + } else + tm = _O_WRONLY; + + if (bufsize != -1) { + PyErr_SetString(PyExc_ValueError, "popen() arg 3 must be -1"); + return NULL; + } + + if (*(mode+1) == 't') + f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1); + else if (*(mode+1) == 'b') + f = _PyPopen(cmdstring, tm | _O_BINARY, POPEN_1); + else + f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1); + + return f; +} + +/* Variation on win32pipe.popen + * + * The result of this function is a pipe (file) connected to the + * process's stdin, and a pipe connected to the process's stdout. + */ + +static PyObject * +win32_popen2(PyObject *self, PyObject *args) +{ + PyObject *f; + int tm=0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = _O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "popen2() arg 2 must be 't' or 'b'"); + return NULL; + } else + tm = _O_BINARY; + + if (bufsize != -1) { + PyErr_SetString(PyExc_ValueError, "popen2() arg 3 must be -1"); + return NULL; + } + + f = _PyPopen(cmdstring, tm, POPEN_2); + + return f; +} + +/* + * Variation on + * + * The result of this function is 3 pipes - the process's stdin, + * stdout and stderr + */ + +static PyObject * +win32_popen3(PyObject *self, PyObject *args) +{ + PyObject *f; + int tm = 0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = _O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "popen3() arg 2 must be 't' or 'b'"); + return NULL; + } else + tm = _O_BINARY; + + if (bufsize != -1) { + PyErr_SetString(PyExc_ValueError, "popen3() arg 3 must be -1"); + return NULL; + } + + f = _PyPopen(cmdstring, tm, POPEN_3); + + return f; +} + +/* + * Variation on win32pipe.popen + * + * The result of this function is 2 pipes - the processes stdin, + * and stdout+stderr combined as a single pipe. + */ + +static PyObject * +win32_popen4(PyObject *self, PyObject *args) +{ + PyObject *f; + int tm = 0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = _O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "popen4() arg 2 must be 't' or 'b'"); + return NULL; + } else + tm = _O_BINARY; + + if (bufsize != -1) { + PyErr_SetString(PyExc_ValueError, "popen4() arg 3 must be -1"); + return NULL; + } + + f = _PyPopen(cmdstring, tm, POPEN_4); + + return f; +} + +static BOOL +_PyPopenCreateProcess(char *cmdstring, + HANDLE hStdin, + HANDLE hStdout, + HANDLE hStderr, + HANDLE *hProcess) +{ + PROCESS_INFORMATION piProcInfo; + STARTUPINFO siStartInfo; + DWORD dwProcessFlags = 0; /* no NEW_CONSOLE by default for Ctrl+C handling */ + char *s1,*s2, *s3 = " /c "; + const char *szConsoleSpawn = "w9xpopen.exe"; + int i; + Py_ssize_t x; + + if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) { + char *comshell; + + s1 = (char *)alloca(i); + if (!(x = GetEnvironmentVariable("COMSPEC", s1, i))) + /* x < i, so x fits into an integer */ + return (int)x; + + /* Explicitly check if we are using COMMAND.COM. If we are + * then use the w9xpopen hack. + */ + comshell = s1 + x; + while (comshell >= s1 && *comshell != '\\') + --comshell; + ++comshell; + + if (GetVersion() < 0x80000000 && + _stricmp(comshell, "command.com") != 0) { + /* NT/2000 and not using command.com. */ + x = i + strlen(s3) + strlen(cmdstring) + 1; + s2 = (char *)alloca(x); + ZeroMemory(s2, x); + PyOS_snprintf(s2, x, "%s%s%s", s1, s3, cmdstring); + } + else { + /* + * Oh gag, we're on Win9x or using COMMAND.COM. Use + * the workaround listed in KB: Q150956 + */ + char modulepath[_MAX_PATH]; + struct stat statinfo; + GetModuleFileName(NULL, modulepath, sizeof(modulepath)); + for (x = i = 0; modulepath[i]; i++) + if (modulepath[i] == SEP) + x = i+1; + modulepath[x] = '\0'; + /* Create the full-name to w9xpopen, so we can test it exists */ + strncat(modulepath, + szConsoleSpawn, + (sizeof(modulepath)/sizeof(modulepath[0])) + -strlen(modulepath)); + if (stat(modulepath, &statinfo) != 0) { + size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]); + /* Eeek - file-not-found - possibly an embedding + situation - see if we can locate it in sys.prefix + */ + strncpy(modulepath, + Py_GetExecPrefix(), + mplen); + modulepath[mplen-1] = '\0'; + if (modulepath[strlen(modulepath)-1] != '\\') + strcat(modulepath, "\\"); + strncat(modulepath, + szConsoleSpawn, + mplen-strlen(modulepath)); + /* No where else to look - raise an easily identifiable + error, rather than leaving Windows to report + "file not found" - as the user is probably blissfully + unaware this shim EXE is used, and it will confuse them. + (well, it confused me for a while ;-) + */ + if (stat(modulepath, &statinfo) != 0) { + PyErr_Format(PyExc_RuntimeError, + "Can not locate '%s' which is needed " + "for popen to work with your shell " + "or platform.", + szConsoleSpawn); + return FALSE; + } + } + x = i + strlen(s3) + strlen(cmdstring) + 1 + + strlen(modulepath) + + strlen(szConsoleSpawn) + 1; + + s2 = (char *)alloca(x); + ZeroMemory(s2, x); + /* To maintain correct argument passing semantics, + we pass the command-line as it stands, and allow + quoting to be applied. w9xpopen.exe will then + use its argv vector, and re-quote the necessary + args for the ultimate child process. + */ + PyOS_snprintf( + s2, x, + "\"%s\" %s%s%s", + modulepath, + s1, + s3, + cmdstring); + /* Not passing CREATE_NEW_CONSOLE has been known to + cause random failures on win9x. Specifically a + dialog: + "Your program accessed mem currently in use at xxx" + and a hopeful warning about the stability of your + system. + Cost is Ctrl+C won't kill children, but anyone + who cares can have a go! + */ + dwProcessFlags |= CREATE_NEW_CONSOLE; + } + } + + /* Could be an else here to try cmd.exe / command.com in the path + Now we'll just error out.. */ + else { + PyErr_SetString(PyExc_RuntimeError, + "Cannot locate a COMSPEC environment variable to " + "use as the shell"); + return FALSE; + } + + ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); + siStartInfo.cb = sizeof(STARTUPINFO); + siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + siStartInfo.hStdInput = hStdin; + siStartInfo.hStdOutput = hStdout; + siStartInfo.hStdError = hStderr; + siStartInfo.wShowWindow = SW_HIDE; + + if (CreateProcess(NULL, + s2, + NULL, + NULL, + TRUE, + dwProcessFlags, + NULL, + NULL, + &siStartInfo, + &piProcInfo) ) { + /* Close the handles now so anyone waiting is woken. */ + CloseHandle(piProcInfo.hThread); + + /* Return process handle */ + *hProcess = piProcInfo.hProcess; + return TRUE; + } + win32_error("CreateProcess", s2); + return FALSE; +} + +/* The following code is based off of KB: Q190351 */ + +static PyObject * +_PyPopen(char *cmdstring, int mode, int n) +{ + HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr, + hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup, + hChildStderrRdDup, hProcess; /* hChildStdoutWrDup; */ + + SECURITY_ATTRIBUTES saAttr; + BOOL fSuccess; + int fd1, fd2, fd3; + FILE *f1, *f2, *f3; + long file_count; + PyObject *f; + + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + + if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) + return win32_error("CreatePipe", NULL); + + /* Create new output read handle and the input write handle. Set + * the inheritance properties to FALSE. Otherwise, the child inherits + * these handles; resulting in non-closeable handles to the pipes + * being created. */ + fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, + GetCurrentProcess(), &hChildStdinWrDup, 0, + FALSE, + DUPLICATE_SAME_ACCESS); + if (!fSuccess) + return win32_error("DuplicateHandle", NULL); + + /* Close the inheritable version of ChildStdin + that we're using. */ + CloseHandle(hChildStdinWr); + + if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) + return win32_error("CreatePipe", NULL); + + fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, + GetCurrentProcess(), &hChildStdoutRdDup, 0, + FALSE, DUPLICATE_SAME_ACCESS); + if (!fSuccess) + return win32_error("DuplicateHandle", NULL); + + /* Close the inheritable version of ChildStdout + that we're using. */ + CloseHandle(hChildStdoutRd); + + if (n != POPEN_4) { + if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0)) + return win32_error("CreatePipe", NULL); + fSuccess = DuplicateHandle(GetCurrentProcess(), + hChildStderrRd, + GetCurrentProcess(), + &hChildStderrRdDup, 0, + FALSE, DUPLICATE_SAME_ACCESS); + if (!fSuccess) + return win32_error("DuplicateHandle", NULL); + /* Close the inheritable version of ChildStdErr that we're using. */ + CloseHandle(hChildStderrRd); + } + + switch (n) { + case POPEN_1: + switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) { + case _O_WRONLY | _O_TEXT: + /* Case for writing to child Stdin in text mode. */ + fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode); + f1 = _fdopen(fd1, "w"); + f = PyFile_FromFile(f1, cmdstring, "w", _PyPclose); + PyFile_SetBufSize(f, 0); + /* We don't care about these pipes anymore, so close them. */ + CloseHandle(hChildStdoutRdDup); + CloseHandle(hChildStderrRdDup); + break; + + case _O_RDONLY | _O_TEXT: + /* Case for reading from child Stdout in text mode. */ + fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode); + f1 = _fdopen(fd1, "r"); + f = PyFile_FromFile(f1, cmdstring, "r", _PyPclose); + PyFile_SetBufSize(f, 0); + /* We don't care about these pipes anymore, so close them. */ + CloseHandle(hChildStdinWrDup); + CloseHandle(hChildStderrRdDup); + break; + + case _O_RDONLY | _O_BINARY: + /* Case for readinig from child Stdout in binary mode. */ + fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode); + f1 = _fdopen(fd1, "rb"); + f = PyFile_FromFile(f1, cmdstring, "rb", _PyPclose); + PyFile_SetBufSize(f, 0); + /* We don't care about these pipes anymore, so close them. */ + CloseHandle(hChildStdinWrDup); + CloseHandle(hChildStderrRdDup); + break; + + case _O_WRONLY | _O_BINARY: + /* Case for writing to child Stdin in binary mode. */ + fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode); + f1 = _fdopen(fd1, "wb"); + f = PyFile_FromFile(f1, cmdstring, "wb", _PyPclose); + PyFile_SetBufSize(f, 0); + /* We don't care about these pipes anymore, so close them. */ + CloseHandle(hChildStdoutRdDup); + CloseHandle(hChildStderrRdDup); + break; + } + file_count = 1; + break; + + case POPEN_2: + case POPEN_4: + { + char *m1, *m2; + PyObject *p1, *p2; + + if (mode & _O_TEXT) { + m1 = "r"; + m2 = "w"; + } else { + m1 = "rb"; + m2 = "wb"; + } + + fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode); + f1 = _fdopen(fd1, m2); + fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode); + f2 = _fdopen(fd2, m1); + p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose); + PyFile_SetBufSize(p1, 0); + p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose); + PyFile_SetBufSize(p2, 0); + + if (n != 4) + CloseHandle(hChildStderrRdDup); + + f = PyTuple_Pack(2,p1,p2); + Py_XDECREF(p1); + Py_XDECREF(p2); + file_count = 2; + break; + } + + case POPEN_3: + { + char *m1, *m2; + PyObject *p1, *p2, *p3; + + if (mode & _O_TEXT) { + m1 = "r"; + m2 = "w"; + } else { + m1 = "rb"; + m2 = "wb"; + } + + fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode); + f1 = _fdopen(fd1, m2); + fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode); + f2 = _fdopen(fd2, m1); + fd3 = _open_osfhandle((Py_intptr_t)hChildStderrRdDup, mode); + f3 = _fdopen(fd3, m1); + p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose); + p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose); + p3 = PyFile_FromFile(f3, cmdstring, m1, _PyPclose); + PyFile_SetBufSize(p1, 0); + PyFile_SetBufSize(p2, 0); + PyFile_SetBufSize(p3, 0); + f = PyTuple_Pack(3,p1,p2,p3); + Py_XDECREF(p1); + Py_XDECREF(p2); + Py_XDECREF(p3); + file_count = 3; + break; + } + } + + if (n == POPEN_4) { + if (!_PyPopenCreateProcess(cmdstring, + hChildStdinRd, + hChildStdoutWr, + hChildStdoutWr, + &hProcess)) + return NULL; + } + else { + if (!_PyPopenCreateProcess(cmdstring, + hChildStdinRd, + hChildStdoutWr, + hChildStderrWr, + &hProcess)) + return NULL; + } + + /* + * Insert the files we've created into the process dictionary + * all referencing the list with the process handle and the + * initial number of files (see description below in _PyPclose). + * Since if _PyPclose later tried to wait on a process when all + * handles weren't closed, it could create a deadlock with the + * child, we spend some energy here to try to ensure that we + * either insert all file handles into the dictionary or none + * at all. It's a little clumsy with the various popen modes + * and variable number of files involved. + */ + if (!_PyPopenProcs) { + _PyPopenProcs = PyDict_New(); + } + + if (_PyPopenProcs) { + PyObject *procObj, *hProcessObj, *intObj, *fileObj[3]; + int ins_rc[3]; + + fileObj[0] = fileObj[1] = fileObj[2] = NULL; + ins_rc[0] = ins_rc[1] = ins_rc[2] = 0; + + procObj = PyList_New(2); + hProcessObj = PyLong_FromVoidPtr(hProcess); + intObj = PyInt_FromLong(file_count); + + if (procObj && hProcessObj && intObj) { + PyList_SetItem(procObj,0,hProcessObj); + PyList_SetItem(procObj,1,intObj); + + fileObj[0] = PyLong_FromVoidPtr(f1); + if (fileObj[0]) { + ins_rc[0] = PyDict_SetItem(_PyPopenProcs, + fileObj[0], + procObj); + } + if (file_count >= 2) { + fileObj[1] = PyLong_FromVoidPtr(f2); + if (fileObj[1]) { + ins_rc[1] = PyDict_SetItem(_PyPopenProcs, + fileObj[1], + procObj); + } + } + if (file_count >= 3) { + fileObj[2] = PyLong_FromVoidPtr(f3); + if (fileObj[2]) { + ins_rc[2] = PyDict_SetItem(_PyPopenProcs, + fileObj[2], + procObj); + } + } + + if (ins_rc[0] < 0 || !fileObj[0] || + ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) || + ins_rc[2] < 0 || (file_count > 2 && !fileObj[2])) { + /* Something failed - remove any dictionary + * entries that did make it. + */ + if (!ins_rc[0] && fileObj[0]) { + PyDict_DelItem(_PyPopenProcs, + fileObj[0]); + } + if (!ins_rc[1] && fileObj[1]) { + PyDict_DelItem(_PyPopenProcs, + fileObj[1]); + } + if (!ins_rc[2] && fileObj[2]) { + PyDict_DelItem(_PyPopenProcs, + fileObj[2]); + } + } + } + + /* + * Clean up our localized references for the dictionary keys + * and value since PyDict_SetItem will Py_INCREF any copies + * that got placed in the dictionary. + */ + Py_XDECREF(procObj); + Py_XDECREF(fileObj[0]); + Py_XDECREF(fileObj[1]); + Py_XDECREF(fileObj[2]); + } + + /* Child is launched. Close the parents copy of those pipe + * handles that only the child should have open. You need to + * make sure that no handles to the write end of the output pipe + * are maintained in this process or else the pipe will not close + * when the child process exits and the ReadFile will hang. */ + + if (!CloseHandle(hChildStdinRd)) + return win32_error("CloseHandle", NULL); + + if (!CloseHandle(hChildStdoutWr)) + return win32_error("CloseHandle", NULL); + + if ((n != 4) && (!CloseHandle(hChildStderrWr))) + return win32_error("CloseHandle", NULL); + + return f; +} + +/* + * Wrapper for fclose() to use for popen* files, so we can retrieve the + * exit code for the child process and return as a result of the close. + * + * This function uses the _PyPopenProcs dictionary in order to map the + * input file pointer to information about the process that was + * originally created by the popen* call that created the file pointer. + * The dictionary uses the file pointer as a key (with one entry + * inserted for each file returned by the original popen* call) and a + * single list object as the value for all files from a single call. + * The list object contains the Win32 process handle at [0], and a file + * count at [1], which is initialized to the total number of file + * handles using that list. + * + * This function closes whichever handle it is passed, and decrements + * the file count in the dictionary for the process handle pointed to + * by this file. On the last close (when the file count reaches zero), + * this function will wait for the child process and then return its + * exit code as the result of the close() operation. This permits the + * files to be closed in any order - it is always the close() of the + * final handle that will return the exit code. + * + * NOTE: This function is currently called with the GIL released. + * hence we use the GILState API to manage our state. + */ + +static int _PyPclose(FILE *file) +{ + int result; + DWORD exit_code; + HANDLE hProcess; + PyObject *procObj, *hProcessObj, *intObj, *fileObj; + long file_count; +#ifdef WITH_THREAD + PyGILState_STATE state; +#endif + + /* Close the file handle first, to ensure it can't block the + * child from exiting if it's the last handle. + */ + result = fclose(file); +#ifdef WITH_THREAD + state = PyGILState_Ensure(); +#endif + if (_PyPopenProcs) { + if ((fileObj = PyLong_FromVoidPtr(file)) != NULL && + (procObj = PyDict_GetItem(_PyPopenProcs, + fileObj)) != NULL && + (hProcessObj = PyList_GetItem(procObj,0)) != NULL && + (intObj = PyList_GetItem(procObj,1)) != NULL) { + + hProcess = PyLong_AsVoidPtr(hProcessObj); + file_count = PyInt_AsLong(intObj); + + if (file_count > 1) { + /* Still other files referencing process */ + file_count--; + PyList_SetItem(procObj,1, + PyInt_FromLong(file_count)); + } else { + /* Last file for this process */ + if (result != EOF && + WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED && + GetExitCodeProcess(hProcess, &exit_code)) { + /* Possible truncation here in 16-bit environments, but + * real exit codes are just the lower byte in any event. + */ + result = exit_code; + } else { + /* Indicate failure - this will cause the file object + * to raise an I/O error and translate the last Win32 + * error code from errno. We do have a problem with + * last errors that overlap the normal errno table, + * but that's a consistent problem with the file object. + */ + if (result != EOF) { + /* If the error wasn't from the fclose(), then + * set errno for the file object error handling. + */ + errno = GetLastError(); + } + result = -1; + } + + /* Free up the native handle at this point */ + CloseHandle(hProcess); + } + + /* Remove this file pointer from dictionary */ + PyDict_DelItem(_PyPopenProcs, fileObj); + + if (PyDict_Size(_PyPopenProcs) == 0) { + Py_DECREF(_PyPopenProcs); + _PyPopenProcs = NULL; + } + + } /* if object retrieval ok */ + + Py_XDECREF(fileObj); + } /* if _PyPopenProcs */ + +#ifdef WITH_THREAD + PyGILState_Release(state); +#endif + return result; +} + +#else /* which OS? */ +static PyObject * +posix_popen(PyObject *self, PyObject *args) +{ + char *name; + char *mode = "r"; + int bufsize = -1; + FILE *fp; + PyObject *f; + if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize)) + return NULL; + /* Strip mode of binary or text modifiers */ + if (strcmp(mode, "rb") == 0 || strcmp(mode, "rt") == 0) + mode = "r"; + else if (strcmp(mode, "wb") == 0 || strcmp(mode, "wt") == 0) + mode = "w"; + Py_BEGIN_ALLOW_THREADS + fp = popen(name, mode); + Py_END_ALLOW_THREADS + if (fp == NULL) + return posix_error(); + f = PyFile_FromFile(fp, name, mode, pclose); + if (f != NULL) + PyFile_SetBufSize(f, bufsize); + return f; +} + +#endif /* PYOS_??? */ +#endif /* HAVE_POPEN */ + + +#ifdef HAVE_SETUID +PyDoc_STRVAR(posix_setuid__doc__, +"setuid(uid)\n\n\ +Set the current process's user id."); + +static PyObject * +posix_setuid(PyObject *self, PyObject *args) +{ + long uid_arg; + uid_t uid; + if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg)) + return NULL; + uid = uid_arg; + if (uid != uid_arg) { + PyErr_SetString(PyExc_OverflowError, "user id too big"); + return NULL; + } + if (setuid(uid) < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_SETUID */ + + +#ifdef HAVE_SETEUID +PyDoc_STRVAR(posix_seteuid__doc__, +"seteuid(uid)\n\n\ +Set the current process's effective user id."); + +static PyObject * +posix_seteuid (PyObject *self, PyObject *args) +{ + long euid_arg; + uid_t euid; + if (!PyArg_ParseTuple(args, "l", &euid_arg)) + return NULL; + euid = euid_arg; + if (euid != euid_arg) { + PyErr_SetString(PyExc_OverflowError, "user id too big"); + return NULL; + } + if (seteuid(euid) < 0) { + return posix_error(); + } else { + Py_INCREF(Py_None); + return Py_None; + } +} +#endif /* HAVE_SETEUID */ + +#ifdef HAVE_SETEGID +PyDoc_STRVAR(posix_setegid__doc__, +"setegid(gid)\n\n\ +Set the current process's effective group id."); + +static PyObject * +posix_setegid (PyObject *self, PyObject *args) +{ + long egid_arg; + gid_t egid; + if (!PyArg_ParseTuple(args, "l", &egid_arg)) + return NULL; + egid = egid_arg; + if (egid != egid_arg) { + PyErr_SetString(PyExc_OverflowError, "group id too big"); + return NULL; + } + if (setegid(egid) < 0) { + return posix_error(); + } else { + Py_INCREF(Py_None); + return Py_None; + } +} +#endif /* HAVE_SETEGID */ + +#ifdef HAVE_SETREUID +PyDoc_STRVAR(posix_setreuid__doc__, +"setreuid(ruid, euid)\n\n\ +Set the current process's real and effective user ids."); + +static PyObject * +posix_setreuid (PyObject *self, PyObject *args) +{ + long ruid_arg, euid_arg; + uid_t ruid, euid; + if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg)) + return NULL; + if (ruid_arg == -1) + ruid = (uid_t)-1; /* let the compiler choose how -1 fits */ + else + ruid = ruid_arg; /* otherwise, assign from our long */ + if (euid_arg == -1) + euid = (uid_t)-1; + else + euid = euid_arg; + if ((euid_arg != -1 && euid != euid_arg) || + (ruid_arg != -1 && ruid != ruid_arg)) { + PyErr_SetString(PyExc_OverflowError, "user id too big"); + return NULL; + } + if (setreuid(ruid, euid) < 0) { + return posix_error(); + } else { + Py_INCREF(Py_None); + return Py_None; + } +} +#endif /* HAVE_SETREUID */ + +#ifdef HAVE_SETREGID +PyDoc_STRVAR(posix_setregid__doc__, +"setregid(rgid, egid)\n\n\ +Set the current process's real and effective group ids."); + +static PyObject * +posix_setregid (PyObject *self, PyObject *args) +{ + long rgid_arg, egid_arg; + gid_t rgid, egid; + if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg)) + return NULL; + if (rgid_arg == -1) + rgid = (gid_t)-1; /* let the compiler choose how -1 fits */ + else + rgid = rgid_arg; /* otherwise, assign from our long */ + if (egid_arg == -1) + egid = (gid_t)-1; + else + egid = egid_arg; + if ((egid_arg != -1 && egid != egid_arg) || + (rgid_arg != -1 && rgid != rgid_arg)) { + PyErr_SetString(PyExc_OverflowError, "group id too big"); + return NULL; + } + if (setregid(rgid, egid) < 0) { + return posix_error(); + } else { + Py_INCREF(Py_None); + return Py_None; + } +} +#endif /* HAVE_SETREGID */ + +#ifdef HAVE_SETGID +PyDoc_STRVAR(posix_setgid__doc__, +"setgid(gid)\n\n\ +Set the current process's group id."); + +static PyObject * +posix_setgid(PyObject *self, PyObject *args) +{ + long gid_arg; + gid_t gid; + if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg)) + return NULL; + gid = gid_arg; + if (gid != gid_arg) { + PyErr_SetString(PyExc_OverflowError, "group id too big"); + return NULL; + } + if (setgid(gid) < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_SETGID */ + +#ifdef HAVE_SETGROUPS +PyDoc_STRVAR(posix_setgroups__doc__, +"setgroups(list)\n\n\ +Set the groups of the current process to list."); + +static PyObject * +posix_setgroups(PyObject *self, PyObject *groups) +{ + int i, len; + gid_t grouplist[MAX_GROUPS]; + + if (!PySequence_Check(groups)) { + PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); + return NULL; + } + len = PySequence_Size(groups); + if (len > MAX_GROUPS) { + PyErr_SetString(PyExc_ValueError, "too many groups"); + return NULL; + } + for(i = 0; i < len; i++) { + PyObject *elem; + elem = PySequence_GetItem(groups, i); + if (!elem) + return NULL; + if (!PyInt_Check(elem)) { + if (!PyLong_Check(elem)) { + PyErr_SetString(PyExc_TypeError, + "groups must be integers"); + Py_DECREF(elem); + return NULL; + } else { + unsigned long x = PyLong_AsUnsignedLong(elem); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "group id too big"); + Py_DECREF(elem); + return NULL; + } + grouplist[i] = x; + /* read back to see if it fits in gid_t */ + if (grouplist[i] != x) { + PyErr_SetString(PyExc_TypeError, + "group id too big"); + Py_DECREF(elem); + return NULL; + } + } + } else { + long x = PyInt_AsLong(elem); + grouplist[i] = x; + if (grouplist[i] != x) { + PyErr_SetString(PyExc_TypeError, + "group id too big"); + Py_DECREF(elem); + return NULL; + } + } + Py_DECREF(elem); + } + + if (setgroups(len, grouplist) < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_SETGROUPS */ + +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) +static PyObject * +wait_helper(pid_t pid, int status, struct rusage *ru) +{ + PyObject *result; + static PyObject *struct_rusage; + + if (pid == -1) + return posix_error(); + + if (struct_rusage == NULL) { + PyObject *m = PyImport_ImportModuleNoBlock("resource"); + if (m == NULL) + return NULL; + struct_rusage = PyObject_GetAttrString(m, "struct_rusage"); + Py_DECREF(m); + if (struct_rusage == NULL) + return NULL; + } + + /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ + result = PyStructSequence_New((PyTypeObject*) struct_rusage); + if (!result) + return NULL; + +#ifndef doubletime +#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) +#endif + + PyStructSequence_SET_ITEM(result, 0, + PyFloat_FromDouble(doubletime(ru->ru_utime))); + PyStructSequence_SET_ITEM(result, 1, + PyFloat_FromDouble(doubletime(ru->ru_stime))); +#define SET_INT(result, index, value)\ + PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value)) + SET_INT(result, 2, ru->ru_maxrss); + SET_INT(result, 3, ru->ru_ixrss); + SET_INT(result, 4, ru->ru_idrss); + SET_INT(result, 5, ru->ru_isrss); + SET_INT(result, 6, ru->ru_minflt); + SET_INT(result, 7, ru->ru_majflt); + SET_INT(result, 8, ru->ru_nswap); + SET_INT(result, 9, ru->ru_inblock); + SET_INT(result, 10, ru->ru_oublock); + SET_INT(result, 11, ru->ru_msgsnd); + SET_INT(result, 12, ru->ru_msgrcv); + SET_INT(result, 13, ru->ru_nsignals); + SET_INT(result, 14, ru->ru_nvcsw); + SET_INT(result, 15, ru->ru_nivcsw); +#undef SET_INT + + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); +} +#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ + +#ifdef HAVE_WAIT3 +PyDoc_STRVAR(posix_wait3__doc__, +"wait3(options) -> (pid, status, rusage)\n\n\ +Wait for completion of a child process."); + +static PyObject * +posix_wait3(PyObject *self, PyObject *args) +{ + pid_t pid; + int options; + struct rusage ru; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:wait3", &options)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + pid = wait3(&status, options, &ru); + Py_END_ALLOW_THREADS + + return wait_helper(pid, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT3 */ + +#ifdef HAVE_WAIT4 +PyDoc_STRVAR(posix_wait4__doc__, +"wait4(pid, options) -> (pid, status, rusage)\n\n\ +Wait for completion of a given child process."); + +static PyObject * +posix_wait4(PyObject *self, PyObject *args) +{ + pid_t pid; + int options; + struct rusage ru; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + pid = wait4(pid, &status, options, &ru); + Py_END_ALLOW_THREADS + + return wait_helper(pid, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT4 */ + +#ifdef HAVE_WAITPID +PyDoc_STRVAR(posix_waitpid__doc__, +"waitpid(pid, options) -> (pid, status)\n\n\ +Wait for completion of a given child process."); + +static PyObject * +posix_waitpid(PyObject *self, PyObject *args) +{ + pid_t pid; + int options; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options)) + return NULL; + Py_BEGIN_ALLOW_THREADS + pid = waitpid(pid, &status, options); + Py_END_ALLOW_THREADS + if (pid == -1) + return posix_error(); + + return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); +} + +#elif defined(HAVE_CWAIT) + +/* MS C has a variant of waitpid() that's usable for most purposes. */ +PyDoc_STRVAR(posix_waitpid__doc__, +"waitpid(pid, options) -> (pid, status << 8)\n\n" +"Wait for completion of a given process. options is ignored on Windows."); + +static PyObject * +posix_waitpid(PyObject *self, PyObject *args) +{ + Py_intptr_t pid; + int status, options; + + if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options)) + return NULL; + Py_BEGIN_ALLOW_THREADS + pid = _cwait(&status, pid, options); + Py_END_ALLOW_THREADS + if (pid == -1) + return posix_error(); + + /* shift the status left a byte so this is more like the POSIX waitpid */ + return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8); +} +#endif /* HAVE_WAITPID || HAVE_CWAIT */ + +#ifdef HAVE_WAIT +PyDoc_STRVAR(posix_wait__doc__, +"wait() -> (pid, status)\n\n\ +Wait for completion of a child process."); + +static PyObject * +posix_wait(PyObject *self, PyObject *noargs) +{ + pid_t pid; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + Py_BEGIN_ALLOW_THREADS + pid = wait(&status); + Py_END_ALLOW_THREADS + if (pid == -1) + return posix_error(); + + return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); +} +#endif + + +PyDoc_STRVAR(posix_lstat__doc__, +"lstat(path) -> stat result\n\n\ +Like stat(path), but do not follow symbolic links."); + +static PyObject * +posix_lstat(PyObject *self, PyObject *args) +{ +#ifdef HAVE_LSTAT + return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL); +#else /* !HAVE_LSTAT */ + return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL); +#endif /* !HAVE_LSTAT */ +} + + +#ifdef HAVE_READLINK +PyDoc_STRVAR(posix_readlink__doc__, +"readlink(path) -> path\n\n\ +Return a string representing the path to which the symbolic link points."); + +static PyObject * +posix_readlink(PyObject *self, PyObject *args) +{ + PyObject* v; + char buf[MAXPATHLEN]; + char *path; + int n; +#ifdef Py_USING_UNICODE + int arg_is_unicode = 0; +#endif + + if (!PyArg_ParseTuple(args, "et:readlink", + Py_FileSystemDefaultEncoding, &path)) + return NULL; +#ifdef Py_USING_UNICODE + v = PySequence_GetItem(args, 0); + if (v == NULL) { + PyMem_Free(path); + return NULL; + } + + if (PyUnicode_Check(v)) { + arg_is_unicode = 1; + } + Py_DECREF(v); +#endif + + Py_BEGIN_ALLOW_THREADS + n = readlink(path, buf, (int) sizeof buf); + Py_END_ALLOW_THREADS + if (n < 0) + return posix_error_with_allocated_filename(path); + + PyMem_Free(path); + v = PyString_FromStringAndSize(buf, n); +#ifdef Py_USING_UNICODE + if (arg_is_unicode) { + PyObject *w; + + w = PyUnicode_FromEncodedObject(v, + Py_FileSystemDefaultEncoding, + "strict"); + if (w != NULL) { + Py_DECREF(v); + v = w; + } + else { + /* fall back to the original byte string, as + discussed in patch #683592 */ + PyErr_Clear(); + } + } +#endif + return v; +} +#endif /* HAVE_READLINK */ + + +#ifdef HAVE_SYMLINK +PyDoc_STRVAR(posix_symlink__doc__, +"symlink(src, dst)\n\n\ +Create a symbolic link pointing to src named dst."); + +static PyObject * +posix_symlink(PyObject *self, PyObject *args) +{ + return posix_2str(args, "etet:symlink", symlink); +} +#endif /* HAVE_SYMLINK */ + + +#ifdef HAVE_TIMES +#if defined(PYCC_VACPP) && defined(PYOS_OS2) +static long +system_uptime(void) +{ + ULONG value = 0; + + Py_BEGIN_ALLOW_THREADS + DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value)); + Py_END_ALLOW_THREADS + + return value; +} + +static PyObject * +posix_times(PyObject *self, PyObject *noargs) +{ + /* Currently Only Uptime is Provided -- Others Later */ + return Py_BuildValue("ddddd", + (double)0 /* t.tms_utime / HZ */, + (double)0 /* t.tms_stime / HZ */, + (double)0 /* t.tms_cutime / HZ */, + (double)0 /* t.tms_cstime / HZ */, + (double)system_uptime() / 1000); +} +#else /* not OS2 */ +#define NEED_TICKS_PER_SECOND +static long ticks_per_second = -1; +static PyObject * +posix_times(PyObject *self, PyObject *noargs) +{ + struct tms t; + clock_t c; + errno = 0; + c = times(&t); + if (c == (clock_t) -1) + return posix_error(); + return Py_BuildValue("ddddd", + (double)t.tms_utime / ticks_per_second, + (double)t.tms_stime / ticks_per_second, + (double)t.tms_cutime / ticks_per_second, + (double)t.tms_cstime / ticks_per_second, + (double)c / ticks_per_second); +} +#endif /* not OS2 */ +#endif /* HAVE_TIMES */ + + +#ifdef HAVE_TIMES +PyDoc_STRVAR(posix_times__doc__, +"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\ +Return a tuple of floating point numbers indicating process times."); +#endif + + +#ifdef HAVE_GETSID +PyDoc_STRVAR(posix_getsid__doc__, +"getsid(pid) -> sid\n\n\ +Call the system call getsid()."); + +static PyObject * +posix_getsid(PyObject *self, PyObject *args) +{ + pid_t pid; + int sid; + if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid)) + return NULL; + sid = getsid(pid); + if (sid < 0) + return posix_error(); + return PyInt_FromLong((long)sid); +} +#endif /* HAVE_GETSID */ + + +#ifdef HAVE_SETSID +PyDoc_STRVAR(posix_setsid__doc__, +"setsid()\n\n\ +Call the system call setsid()."); + +static PyObject * +posix_setsid(PyObject *self, PyObject *noargs) +{ + if (setsid() < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_SETSID */ + +#ifdef HAVE_SETPGID +PyDoc_STRVAR(posix_setpgid__doc__, +"setpgid(pid, pgrp)\n\n\ +Call the system call setpgid()."); + +static PyObject * +posix_setpgid(PyObject *self, PyObject *args) +{ + pid_t pid; + int pgrp; + if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp)) + return NULL; + if (setpgid(pid, pgrp) < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_SETPGID */ + + +#ifdef HAVE_TCGETPGRP +PyDoc_STRVAR(posix_tcgetpgrp__doc__, +"tcgetpgrp(fd) -> pgid\n\n\ +Return the process group associated with the terminal given by a fd."); + +static PyObject * +posix_tcgetpgrp(PyObject *self, PyObject *args) +{ + int fd; + pid_t pgid; + if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd)) + return NULL; + pgid = tcgetpgrp(fd); + if (pgid < 0) + return posix_error(); + return PyLong_FromPid(pgid); +} +#endif /* HAVE_TCGETPGRP */ + + +#ifdef HAVE_TCSETPGRP +PyDoc_STRVAR(posix_tcsetpgrp__doc__, +"tcsetpgrp(fd, pgid)\n\n\ +Set the process group associated with the terminal given by a fd."); + +static PyObject * +posix_tcsetpgrp(PyObject *self, PyObject *args) +{ + int fd; + pid_t pgid; + if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid)) + return NULL; + if (tcsetpgrp(fd, pgid) < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_TCSETPGRP */ + +/* Functions acting on file descriptors */ + +PyDoc_STRVAR(posix_open__doc__, +"open(filename, flag [, mode=0777]) -> fd\n\n\ +Open a file (for low level IO)."); + +static PyObject * +posix_open(PyObject *self, PyObject *args) +{ + char *file = NULL; + int flag; + int mode = 0777; + int fd; + + if (!PyArg_ParseTuple(args, "eti|i", + Py_FileSystemDefaultEncoding, &file, + &flag, &mode)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + fd = open(file, flag, mode); + Py_END_ALLOW_THREADS + if (fd < 0) + return posix_error_with_allocated_filename(file); + PyMem_Free(file); + return PyInt_FromLong((long)fd); +} + + +PyDoc_STRVAR(posix_close__doc__, +"close(fd)\n\n\ +Close a file descriptor (for low level IO)."); + +static PyObject * +posix_close(PyObject *self, PyObject *args) +{ + int fd, res; + if (!PyArg_ParseTuple(args, "i:close", &fd)) + return NULL; + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS + res = close(fd); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} + + +PyDoc_STRVAR(posix_closerange__doc__, +"closerange(fd_low, fd_high)\n\n\ +Closes all file descriptors in [fd_low, fd_high), ignoring errors."); + +static PyObject * +posix_closerange(PyObject *self, PyObject *args) +{ + int fd_from, fd_to, i; + if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to)) + return NULL; + Py_BEGIN_ALLOW_THREADS + for (i = fd_from; i < fd_to; i++) + if (_PyVerify_fd(i)) + close(i); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} + + +PyDoc_STRVAR(posix_dup__doc__, +"dup(fd) -> fd2\n\n\ +Return a duplicate of a file descriptor."); + +static PyObject * +posix_dup(PyObject *self, PyObject *args) +{ + int fd; + if (!PyArg_ParseTuple(args, "i:dup", &fd)) + return NULL; + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS + fd = dup(fd); + Py_END_ALLOW_THREADS + if (fd < 0) + return posix_error(); + return PyInt_FromLong((long)fd); +} + + +PyDoc_STRVAR(posix_dup2__doc__, +"dup2(old_fd, new_fd)\n\n\ +Duplicate file descriptor."); + +static PyObject * +posix_dup2(PyObject *self, PyObject *args) +{ + int fd, fd2, res; + if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2)) + return NULL; + if (!_PyVerify_fd_dup2(fd, fd2)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS + res = dup2(fd, fd2); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} + + +PyDoc_STRVAR(posix_lseek__doc__, +"lseek(fd, pos, how) -> newpos\n\n\ +Set the current position of a file descriptor."); + +static PyObject * +posix_lseek(PyObject *self, PyObject *args) +{ + int fd, how; + off_t pos, res; + PyObject *posobj; + if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how)) + return NULL; +#ifdef SEEK_SET + /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ + switch (how) { + case 0: how = SEEK_SET; break; + case 1: how = SEEK_CUR; break; + case 2: how = SEEK_END; break; + } +#endif /* SEEK_END */ + +#if !defined(HAVE_LARGEFILE_SUPPORT) + pos = PyInt_AsLong(posobj); +#else + pos = PyLong_Check(posobj) ? + PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj); +#endif + if (PyErr_Occurred()) + return NULL; + + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS + res = lseek(fd, pos, how); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + +#if !defined(HAVE_LARGEFILE_SUPPORT) + return PyInt_FromLong(res); +#else + return PyLong_FromLongLong(res); +#endif +} + + +PyDoc_STRVAR(posix_read__doc__, +"read(fd, buffersize) -> string\n\n\ +Read a file descriptor."); + +static PyObject * +posix_read(PyObject *self, PyObject *args) +{ + int fd, size, n; + PyObject *buffer; + if (!PyArg_ParseTuple(args, "ii:read", &fd, &size)) + return NULL; + if (size < 0) { + errno = EINVAL; + return posix_error(); + } + buffer = PyString_FromStringAndSize((char *)NULL, size); + if (buffer == NULL) + return NULL; + if (!_PyVerify_fd(fd)) { + Py_DECREF(buffer); + return posix_error(); + } + Py_BEGIN_ALLOW_THREADS + n = read(fd, PyString_AsString(buffer), size); + Py_END_ALLOW_THREADS + if (n < 0) { + Py_DECREF(buffer); + return posix_error(); + } + if (n != size) + _PyString_Resize(&buffer, n); + return buffer; +} + + +PyDoc_STRVAR(posix_write__doc__, +"write(fd, string) -> byteswritten\n\n\ +Write a string to a file descriptor."); + +static PyObject * +posix_write(PyObject *self, PyObject *args) +{ + Py_buffer pbuf; + int fd; + Py_ssize_t size; + + if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf)) + return NULL; + if (!_PyVerify_fd(fd)) { + PyBuffer_Release(&pbuf); + return posix_error(); + } + Py_BEGIN_ALLOW_THREADS + size = write(fd, pbuf.buf, (size_t)pbuf.len); + Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); + if (size < 0) + return posix_error(); + return PyInt_FromSsize_t(size); +} + + +PyDoc_STRVAR(posix_fstat__doc__, +"fstat(fd) -> stat result\n\n\ +Like stat(), but for an open file descriptor."); + +static PyObject * +posix_fstat(PyObject *self, PyObject *args) +{ + int fd; + STRUCT_STAT st; + int res; + if (!PyArg_ParseTuple(args, "i:fstat", &fd)) + return NULL; + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS + res = FSTAT(fd, &st); + Py_END_ALLOW_THREADS + if (res != 0) { + return posix_error(); + } + + return _pystat_fromstructstat(&st); +} + + +PyDoc_STRVAR(posix_fdopen__doc__, +"fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\ +Return an open file object connected to a file descriptor."); + +static PyObject * +posix_fdopen(PyObject *self, PyObject *args) +{ + int fd; + char *orgmode = "r"; + int bufsize = -1; + FILE *fp; + PyObject *f; + char *mode; + if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize)) + return NULL; + + /* Sanitize mode. See fileobject.c */ + mode = PyMem_MALLOC(strlen(orgmode)+3); + if (!mode) { + PyErr_NoMemory(); + return NULL; + } + strcpy(mode, orgmode); + if (_PyFile_SanitizeMode(mode)) { + PyMem_FREE(mode); + return NULL; + } + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS +#if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H) + if (mode[0] == 'a') { + /* try to make sure the O_APPEND flag is set */ + int flags; + flags = fcntl(fd, F_GETFL); + if (flags != -1) + fcntl(fd, F_SETFL, flags | O_APPEND); + fp = fdopen(fd, mode); + if (fp == NULL && flags != -1) + /* restore old mode if fdopen failed */ + fcntl(fd, F_SETFL, flags); + } else { + fp = fdopen(fd, mode); + } +#else + fp = fdopen(fd, mode); +#endif + Py_END_ALLOW_THREADS + PyMem_FREE(mode); + if (fp == NULL) + return posix_error(); + f = PyFile_FromFile(fp, "", orgmode, fclose); + if (f != NULL) + PyFile_SetBufSize(f, bufsize); + return f; +} + +PyDoc_STRVAR(posix_isatty__doc__, +"isatty(fd) -> bool\n\n\ +Return True if the file descriptor 'fd' is an open file descriptor\n\ +connected to the slave end of a terminal."); + +static PyObject * +posix_isatty(PyObject *self, PyObject *args) +{ + int fd; + if (!PyArg_ParseTuple(args, "i:isatty", &fd)) + return NULL; + if (!_PyVerify_fd(fd)) + return PyBool_FromLong(0); + return PyBool_FromLong(isatty(fd)); +} + +#ifdef HAVE_PIPE +PyDoc_STRVAR(posix_pipe__doc__, +"pipe() -> (read_end, write_end)\n\n\ +Create a pipe."); + +static PyObject * +posix_pipe(PyObject *self, PyObject *noargs) +{ +#if defined(PYOS_OS2) + HFILE read, write; + APIRET rc; + + Py_BEGIN_ALLOW_THREADS + rc = DosCreatePipe( &read, &write, 4096); + Py_END_ALLOW_THREADS + if (rc != NO_ERROR) + return os2_error(rc); + + return Py_BuildValue("(ii)", read, write); +#else +#if !defined(MS_WINDOWS) + int fds[2]; + int res; + Py_BEGIN_ALLOW_THREADS + res = pipe(fds); + Py_END_ALLOW_THREADS + if (res != 0) + return posix_error(); + return Py_BuildValue("(ii)", fds[0], fds[1]); +#else /* MS_WINDOWS */ + HANDLE read, write; + int read_fd, write_fd; + BOOL ok; + Py_BEGIN_ALLOW_THREADS + ok = CreatePipe(&read, &write, NULL, 0); + Py_END_ALLOW_THREADS + if (!ok) + return win32_error("CreatePipe", NULL); + read_fd = _open_osfhandle((Py_intptr_t)read, 0); + write_fd = _open_osfhandle((Py_intptr_t)write, 1); + return Py_BuildValue("(ii)", read_fd, write_fd); +#endif /* MS_WINDOWS */ +#endif +} +#endif /* HAVE_PIPE */ + + +#ifdef HAVE_MKFIFO +PyDoc_STRVAR(posix_mkfifo__doc__, +"mkfifo(filename [, mode=0666])\n\n\ +Create a FIFO (a POSIX named pipe)."); + +static PyObject * +posix_mkfifo(PyObject *self, PyObject *args) +{ + char *filename; + int mode = 0666; + int res; + if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = mkfifo(filename, mode); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif + + +#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) +PyDoc_STRVAR(posix_mknod__doc__, +"mknod(filename [, mode=0600, device])\n\n\ +Create a filesystem node (file, device special file or named pipe)\n\ +named filename. mode specifies both the permissions to use and the\n\ +type of node to be created, being combined (bitwise OR) with one of\n\ +S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\ +device defines the newly created device special file (probably using\n\ +os.makedev()), otherwise it is ignored."); + + +static PyObject * +posix_mknod(PyObject *self, PyObject *args) +{ + char *filename; + int mode = 0600; + int device = 0; + int res; + if (!PyArg_ParseTuple(args, "s|ii:mknod", &filename, &mode, &device)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = mknod(filename, mode, device); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif + +#ifdef HAVE_DEVICE_MACROS +PyDoc_STRVAR(posix_major__doc__, +"major(device) -> major number\n\ +Extracts a device major number from a raw device number."); + +static PyObject * +posix_major(PyObject *self, PyObject *args) +{ + int device; + if (!PyArg_ParseTuple(args, "i:major", &device)) + return NULL; + return PyInt_FromLong((long)major(device)); +} + +PyDoc_STRVAR(posix_minor__doc__, +"minor(device) -> minor number\n\ +Extracts a device minor number from a raw device number."); + +static PyObject * +posix_minor(PyObject *self, PyObject *args) +{ + int device; + if (!PyArg_ParseTuple(args, "i:minor", &device)) + return NULL; + return PyInt_FromLong((long)minor(device)); +} + +PyDoc_STRVAR(posix_makedev__doc__, +"makedev(major, minor) -> device number\n\ +Composes a raw device number from the major and minor device numbers."); + +static PyObject * +posix_makedev(PyObject *self, PyObject *args) +{ + int major, minor; + if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor)) + return NULL; + return PyInt_FromLong((long)makedev(major, minor)); +} +#endif /* device macros */ + + +#ifdef HAVE_FTRUNCATE +PyDoc_STRVAR(posix_ftruncate__doc__, +"ftruncate(fd, length)\n\n\ +Truncate a file to a specified length."); + +static PyObject * +posix_ftruncate(PyObject *self, PyObject *args) +{ + int fd; + off_t length; + int res; + PyObject *lenobj; + + if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj)) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + length = PyInt_AsLong(lenobj); +#else + length = PyLong_Check(lenobj) ? + PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj); +#endif + if (PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + res = ftruncate(fd, length); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif + +#ifdef HAVE_PUTENV +PyDoc_STRVAR(posix_putenv__doc__, +"putenv(key, value)\n\n\ +Change or add an environment variable."); + +/* Save putenv() parameters as values here, so we can collect them when they + * get re-set with another call for the same key. */ +static PyObject *posix_putenv_garbage; + +static PyObject * +posix_putenv(PyObject *self, PyObject *args) +{ + char *s1, *s2; + char *newenv; + PyObject *newstr; + size_t len; + + if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2)) + return NULL; + +#if defined(PYOS_OS2) + if (stricmp(s1, "BEGINLIBPATH") == 0) { + APIRET rc; + + rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH); + if (rc != NO_ERROR) + return os2_error(rc); + + } else if (stricmp(s1, "ENDLIBPATH") == 0) { + APIRET rc; + + rc = DosSetExtLIBPATH(s2, END_LIBPATH); + if (rc != NO_ERROR) + return os2_error(rc); + } else { +#endif + + /* XXX This can leak memory -- not easy to fix :-( */ + len = strlen(s1) + strlen(s2) + 2; + /* len includes space for a trailing \0; the size arg to + PyString_FromStringAndSize does not count that */ + newstr = PyString_FromStringAndSize(NULL, (int)len - 1); + if (newstr == NULL) + return PyErr_NoMemory(); + newenv = PyString_AS_STRING(newstr); + PyOS_snprintf(newenv, len, "%s=%s", s1, s2); + if (putenv(newenv)) { + Py_DECREF(newstr); + posix_error(); + return NULL; + } + /* Install the first arg and newstr in posix_putenv_garbage; + * this will cause previous value to be collected. This has to + * happen after the real putenv() call because the old value + * was still accessible until then. */ + if (PyDict_SetItem(posix_putenv_garbage, + PyTuple_GET_ITEM(args, 0), newstr)) { + /* really not much we can do; just leak */ + PyErr_Clear(); + } + else { + Py_DECREF(newstr); + } + +#if defined(PYOS_OS2) + } +#endif + Py_INCREF(Py_None); + return Py_None; +} +#endif /* putenv */ + +#ifdef HAVE_UNSETENV +PyDoc_STRVAR(posix_unsetenv__doc__, +"unsetenv(key)\n\n\ +Delete an environment variable."); + +static PyObject * +posix_unsetenv(PyObject *self, PyObject *args) +{ + char *s1; + + if (!PyArg_ParseTuple(args, "s:unsetenv", &s1)) + return NULL; + + unsetenv(s1); + + /* Remove the key from posix_putenv_garbage; + * this will cause it to be collected. This has to + * happen after the real unsetenv() call because the + * old value was still accessible until then. + */ + if (PyDict_DelItem(posix_putenv_garbage, + PyTuple_GET_ITEM(args, 0))) { + /* really not much we can do; just leak */ + PyErr_Clear(); + } + + Py_INCREF(Py_None); + return Py_None; +} +#endif /* unsetenv */ + +PyDoc_STRVAR(posix_strerror__doc__, +"strerror(code) -> string\n\n\ +Translate an error code to a message string."); + +static PyObject * +posix_strerror(PyObject *self, PyObject *args) +{ + int code; + char *message; + if (!PyArg_ParseTuple(args, "i:strerror", &code)) + return NULL; + message = strerror(code); + if (message == NULL) { + PyErr_SetString(PyExc_ValueError, + "strerror() argument out of range"); + return NULL; + } + return PyString_FromString(message); +} + + +#ifdef HAVE_SYS_WAIT_H + +#ifdef WCOREDUMP +PyDoc_STRVAR(posix_WCOREDUMP__doc__, +"WCOREDUMP(status) -> bool\n\n\ +Return True if the process returning 'status' was dumped to a core file."); + +static PyObject * +posix_WCOREDUMP(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WCOREDUMP(status)); +} +#endif /* WCOREDUMP */ + +#ifdef WIFCONTINUED +PyDoc_STRVAR(posix_WIFCONTINUED__doc__, +"WIFCONTINUED(status) -> bool\n\n\ +Return True if the process returning 'status' was continued from a\n\ +job control stop."); + +static PyObject * +posix_WIFCONTINUED(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WIFCONTINUED(status)); +} +#endif /* WIFCONTINUED */ + +#ifdef WIFSTOPPED +PyDoc_STRVAR(posix_WIFSTOPPED__doc__, +"WIFSTOPPED(status) -> bool\n\n\ +Return True if the process returning 'status' was stopped."); + +static PyObject * +posix_WIFSTOPPED(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WIFSTOPPED(status)); +} +#endif /* WIFSTOPPED */ + +#ifdef WIFSIGNALED +PyDoc_STRVAR(posix_WIFSIGNALED__doc__, +"WIFSIGNALED(status) -> bool\n\n\ +Return True if the process returning 'status' was terminated by a signal."); + +static PyObject * +posix_WIFSIGNALED(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WIFSIGNALED(status)); +} +#endif /* WIFSIGNALED */ + +#ifdef WIFEXITED +PyDoc_STRVAR(posix_WIFEXITED__doc__, +"WIFEXITED(status) -> bool\n\n\ +Return true if the process returning 'status' exited using the exit()\n\ +system call."); + +static PyObject * +posix_WIFEXITED(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status))) + return NULL; + + return PyBool_FromLong(WIFEXITED(status)); +} +#endif /* WIFEXITED */ + +#ifdef WEXITSTATUS +PyDoc_STRVAR(posix_WEXITSTATUS__doc__, +"WEXITSTATUS(status) -> integer\n\n\ +Return the process return code from 'status'."); + +static PyObject * +posix_WEXITSTATUS(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status))) + return NULL; + + return Py_BuildValue("i", WEXITSTATUS(status)); +} +#endif /* WEXITSTATUS */ + +#ifdef WTERMSIG +PyDoc_STRVAR(posix_WTERMSIG__doc__, +"WTERMSIG(status) -> integer\n\n\ +Return the signal that terminated the process that provided the 'status'\n\ +value."); + +static PyObject * +posix_WTERMSIG(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status))) + return NULL; + + return Py_BuildValue("i", WTERMSIG(status)); +} +#endif /* WTERMSIG */ + +#ifdef WSTOPSIG +PyDoc_STRVAR(posix_WSTOPSIG__doc__, +"WSTOPSIG(status) -> integer\n\n\ +Return the signal that stopped the process that provided\n\ +the 'status' value."); + +static PyObject * +posix_WSTOPSIG(PyObject *self, PyObject *args) +{ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status))) + return NULL; + + return Py_BuildValue("i", WSTOPSIG(status)); +} +#endif /* WSTOPSIG */ + +#endif /* HAVE_SYS_WAIT_H */ + + +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) +#ifdef _SCO_DS +/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the + needed definitions in sys/statvfs.h */ +#define _SVID3 +#endif +#include + +static PyObject* +_pystatvfs_fromstructstatvfs(struct statvfs st) { + PyObject *v = PyStructSequence_New(&StatVFSResultType); + if (v == NULL) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong((long) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax)); +#else + PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, + PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, + PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, + PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, + PyLong_FromLongLong((PY_LONG_LONG) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, + PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, + PyLong_FromLongLong((PY_LONG_LONG) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax)); +#endif + + return v; +} + +PyDoc_STRVAR(posix_fstatvfs__doc__, +"fstatvfs(fd) -> statvfs result\n\n\ +Perform an fstatvfs system call on the given fd."); + +static PyObject * +posix_fstatvfs(PyObject *self, PyObject *args) +{ + int fd, res; + struct statvfs st; + + if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = fstatvfs(fd, &st); + Py_END_ALLOW_THREADS + if (res != 0) + return posix_error(); + + return _pystatvfs_fromstructstatvfs(st); +} +#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */ + + +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) +#include + +PyDoc_STRVAR(posix_statvfs__doc__, +"statvfs(path) -> statvfs result\n\n\ +Perform a statvfs system call on the given path."); + +static PyObject * +posix_statvfs(PyObject *self, PyObject *args) +{ + char *path; + int res; + struct statvfs st; + if (!PyArg_ParseTuple(args, "s:statvfs", &path)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = statvfs(path, &st); + Py_END_ALLOW_THREADS + if (res != 0) + return posix_error_with_filename(path); + + return _pystatvfs_fromstructstatvfs(st); +} +#endif /* HAVE_STATVFS */ + + +#ifdef HAVE_TEMPNAM +PyDoc_STRVAR(posix_tempnam__doc__, +"tempnam([dir[, prefix]]) -> string\n\n\ +Return a unique name for a temporary file.\n\ +The directory and a prefix may be specified as strings; they may be omitted\n\ +or None if not needed."); + +static PyObject * +posix_tempnam(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + char *dir = NULL; + char *pfx = NULL; + char *name; + + if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx)) + return NULL; + + if (PyErr_Warn(PyExc_RuntimeWarning, + "tempnam is a potential security risk to your program") < 0) + return NULL; + + if (PyErr_WarnPy3k("tempnam has been removed in 3.x; " + "use the tempfile module", 1) < 0) + return NULL; + + name = tempnam(dir, pfx); + if (name == NULL) + return PyErr_NoMemory(); + result = PyString_FromString(name); + free(name); + return result; +} +#endif + + +#ifdef HAVE_TMPFILE +PyDoc_STRVAR(posix_tmpfile__doc__, +"tmpfile() -> file object\n\n\ +Create a temporary file with no directory entries."); + +static PyObject * +posix_tmpfile(PyObject *self, PyObject *noargs) +{ + FILE *fp; + + if (PyErr_WarnPy3k("tmpfile has been removed in 3.x; " + "use the tempfile module", 1) < 0) + return NULL; + + fp = tmpfile(); + if (fp == NULL) + return posix_error(); + return PyFile_FromFile(fp, "", "w+b", fclose); +} +#endif + + +#ifdef HAVE_TMPNAM +PyDoc_STRVAR(posix_tmpnam__doc__, +"tmpnam() -> string\n\n\ +Return a unique name for a temporary file."); + +static PyObject * +posix_tmpnam(PyObject *self, PyObject *noargs) +{ + char buffer[L_tmpnam]; + char *name; + + if (PyErr_Warn(PyExc_RuntimeWarning, + "tmpnam is a potential security risk to your program") < 0) + return NULL; + + if (PyErr_WarnPy3k("tmpnam has been removed in 3.x; " + "use the tempfile module", 1) < 0) + return NULL; + +#ifdef USE_TMPNAM_R + name = tmpnam_r(buffer); +#else + name = tmpnam(buffer); +#endif + if (name == NULL) { + PyObject *err = Py_BuildValue("is", 0, +#ifdef USE_TMPNAM_R + "unexpected NULL from tmpnam_r" +#else + "unexpected NULL from tmpnam" +#endif + ); + PyErr_SetObject(PyExc_OSError, err); + Py_XDECREF(err); + return NULL; + } + return PyString_FromString(buffer); +} +#endif + + +/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). + * It maps strings representing configuration variable names to + * integer values, allowing those functions to be called with the + * magic names instead of polluting the module's namespace with tons of + * rarely-used constants. There are three separate tables that use + * these definitions. + * + * This code is always included, even if none of the interfaces that + * need it are included. The #if hackery needed to avoid it would be + * sufficiently pervasive that it's not worth the loss of readability. + */ +struct constdef { + char *name; + long value; +}; + +static int +conv_confname(PyObject *arg, int *valuep, struct constdef *table, + size_t tablesize) +{ + if (PyInt_Check(arg)) { + *valuep = PyInt_AS_LONG(arg); + return 1; + } + if (PyString_Check(arg)) { + /* look up the value in the table using a binary search */ + size_t lo = 0; + size_t mid; + size_t hi = tablesize; + int cmp; + char *confname = PyString_AS_STRING(arg); + while (lo < hi) { + mid = (lo + hi) / 2; + cmp = strcmp(confname, table[mid].name); + if (cmp < 0) + hi = mid; + else if (cmp > 0) + lo = mid + 1; + else { + *valuep = table[mid].value; + return 1; + } + } + PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); + } + else + PyErr_SetString(PyExc_TypeError, + "configuration names must be strings or integers"); + return 0; +} + + +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) +static struct constdef posix_constants_pathconf[] = { +#ifdef _PC_ABI_AIO_XFER_MAX + {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, +#endif +#ifdef _PC_ABI_ASYNC_IO + {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, +#endif +#ifdef _PC_ASYNC_IO + {"PC_ASYNC_IO", _PC_ASYNC_IO}, +#endif +#ifdef _PC_CHOWN_RESTRICTED + {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, +#endif +#ifdef _PC_FILESIZEBITS + {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, +#endif +#ifdef _PC_LAST + {"PC_LAST", _PC_LAST}, +#endif +#ifdef _PC_LINK_MAX + {"PC_LINK_MAX", _PC_LINK_MAX}, +#endif +#ifdef _PC_MAX_CANON + {"PC_MAX_CANON", _PC_MAX_CANON}, +#endif +#ifdef _PC_MAX_INPUT + {"PC_MAX_INPUT", _PC_MAX_INPUT}, +#endif +#ifdef _PC_NAME_MAX + {"PC_NAME_MAX", _PC_NAME_MAX}, +#endif +#ifdef _PC_NO_TRUNC + {"PC_NO_TRUNC", _PC_NO_TRUNC}, +#endif +#ifdef _PC_PATH_MAX + {"PC_PATH_MAX", _PC_PATH_MAX}, +#endif +#ifdef _PC_PIPE_BUF + {"PC_PIPE_BUF", _PC_PIPE_BUF}, +#endif +#ifdef _PC_PRIO_IO + {"PC_PRIO_IO", _PC_PRIO_IO}, +#endif +#ifdef _PC_SOCK_MAXBUF + {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, +#endif +#ifdef _PC_SYNC_IO + {"PC_SYNC_IO", _PC_SYNC_IO}, +#endif +#ifdef _PC_VDISABLE + {"PC_VDISABLE", _PC_VDISABLE}, +#endif +}; + +static int +conv_path_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_pathconf, + sizeof(posix_constants_pathconf) + / sizeof(struct constdef)); +} +#endif + +#ifdef HAVE_FPATHCONF +PyDoc_STRVAR(posix_fpathconf__doc__, +"fpathconf(fd, name) -> integer\n\n\ +Return the configuration limit name for the file descriptor fd.\n\ +If there is no limit, return -1."); + +static PyObject * +posix_fpathconf(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + int name, fd; + + if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd, + conv_path_confname, &name)) { + long limit; + + errno = 0; + limit = fpathconf(fd, name); + if (limit == -1 && errno != 0) + posix_error(); + else + result = PyInt_FromLong(limit); + } + return result; +} +#endif + + +#ifdef HAVE_PATHCONF +PyDoc_STRVAR(posix_pathconf__doc__, +"pathconf(path, name) -> integer\n\n\ +Return the configuration limit name for the file or directory path.\n\ +If there is no limit, return -1."); + +static PyObject * +posix_pathconf(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + int name; + char *path; + + if (PyArg_ParseTuple(args, "sO&:pathconf", &path, + conv_path_confname, &name)) { + long limit; + + errno = 0; + limit = pathconf(path, name); + if (limit == -1 && errno != 0) { + if (errno == EINVAL) + /* could be a path or name problem */ + posix_error(); + else + posix_error_with_filename(path); + } + else + result = PyInt_FromLong(limit); + } + return result; +} +#endif + +#ifdef HAVE_CONFSTR +static struct constdef posix_constants_confstr[] = { +#ifdef _CS_ARCHITECTURE + {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, +#endif +#ifdef _CS_HOSTNAME + {"CS_HOSTNAME", _CS_HOSTNAME}, +#endif +#ifdef _CS_HW_PROVIDER + {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, +#endif +#ifdef _CS_HW_SERIAL + {"CS_HW_SERIAL", _CS_HW_SERIAL}, +#endif +#ifdef _CS_INITTAB_NAME + {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, +#endif +#ifdef _CS_LFS64_CFLAGS + {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, +#endif +#ifdef _CS_LFS64_LDFLAGS + {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, +#endif +#ifdef _CS_LFS64_LIBS + {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, +#endif +#ifdef _CS_LFS64_LINTFLAGS + {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, +#endif +#ifdef _CS_LFS_CFLAGS + {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, +#endif +#ifdef _CS_LFS_LDFLAGS + {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, +#endif +#ifdef _CS_LFS_LIBS + {"CS_LFS_LIBS", _CS_LFS_LIBS}, +#endif +#ifdef _CS_LFS_LINTFLAGS + {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, +#endif +#ifdef _CS_MACHINE + {"CS_MACHINE", _CS_MACHINE}, +#endif +#ifdef _CS_PATH + {"CS_PATH", _CS_PATH}, +#endif +#ifdef _CS_RELEASE + {"CS_RELEASE", _CS_RELEASE}, +#endif +#ifdef _CS_SRPC_DOMAIN + {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, +#endif +#ifdef _CS_SYSNAME + {"CS_SYSNAME", _CS_SYSNAME}, +#endif +#ifdef _CS_VERSION + {"CS_VERSION", _CS_VERSION}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS + {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS + {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LIBS + {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS + {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS + {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS + {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS + {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS + {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_CFLAGS + {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS + {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LIBS + {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS + {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS + {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS + {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, +#endif +#ifdef _MIPS_CS_AVAIL_PROCESSORS + {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, +#endif +#ifdef _MIPS_CS_BASE + {"MIPS_CS_BASE", _MIPS_CS_BASE}, +#endif +#ifdef _MIPS_CS_HOSTID + {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, +#endif +#ifdef _MIPS_CS_HW_NAME + {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, +#endif +#ifdef _MIPS_CS_NUM_PROCESSORS + {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, +#endif +#ifdef _MIPS_CS_OSREL_MAJ + {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, +#endif +#ifdef _MIPS_CS_OSREL_MIN + {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, +#endif +#ifdef _MIPS_CS_OSREL_PATCH + {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, +#endif +#ifdef _MIPS_CS_OS_NAME + {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, +#endif +#ifdef _MIPS_CS_OS_PROVIDER + {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, +#endif +#ifdef _MIPS_CS_PROCESSORS + {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, +#endif +#ifdef _MIPS_CS_SERIAL + {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, +#endif +#ifdef _MIPS_CS_VENDOR + {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, +#endif +}; + +static int +conv_confstr_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_confstr, + sizeof(posix_constants_confstr) + / sizeof(struct constdef)); +} + +PyDoc_STRVAR(posix_confstr__doc__, +"confstr(name) -> string\n\n\ +Return a string-valued system configuration variable."); + +static PyObject * +posix_confstr(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + int name; + char buffer[256]; + + if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) { + int len; + + errno = 0; + len = confstr(name, buffer, sizeof(buffer)); + if (len == 0) { + if (errno) { + posix_error(); + } + else { + result = Py_None; + Py_INCREF(Py_None); + } + } + else { + if ((unsigned int)len >= sizeof(buffer)) { + result = PyString_FromStringAndSize(NULL, len-1); + if (result != NULL) + confstr(name, PyString_AS_STRING(result), len); + } + else + result = PyString_FromStringAndSize(buffer, len-1); + } + } + return result; +} +#endif + + +#ifdef HAVE_SYSCONF +static struct constdef posix_constants_sysconf[] = { +#ifdef _SC_2_CHAR_TERM + {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, +#endif +#ifdef _SC_2_C_BIND + {"SC_2_C_BIND", _SC_2_C_BIND}, +#endif +#ifdef _SC_2_C_DEV + {"SC_2_C_DEV", _SC_2_C_DEV}, +#endif +#ifdef _SC_2_C_VERSION + {"SC_2_C_VERSION", _SC_2_C_VERSION}, +#endif +#ifdef _SC_2_FORT_DEV + {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, +#endif +#ifdef _SC_2_FORT_RUN + {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, +#endif +#ifdef _SC_2_LOCALEDEF + {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, +#endif +#ifdef _SC_2_SW_DEV + {"SC_2_SW_DEV", _SC_2_SW_DEV}, +#endif +#ifdef _SC_2_UPE + {"SC_2_UPE", _SC_2_UPE}, +#endif +#ifdef _SC_2_VERSION + {"SC_2_VERSION", _SC_2_VERSION}, +#endif +#ifdef _SC_ABI_ASYNCHRONOUS_IO + {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ACL + {"SC_ACL", _SC_ACL}, +#endif +#ifdef _SC_AIO_LISTIO_MAX + {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, +#endif +#ifdef _SC_AIO_MAX + {"SC_AIO_MAX", _SC_AIO_MAX}, +#endif +#ifdef _SC_AIO_PRIO_DELTA_MAX + {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, +#endif +#ifdef _SC_ARG_MAX + {"SC_ARG_MAX", _SC_ARG_MAX}, +#endif +#ifdef _SC_ASYNCHRONOUS_IO + {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ATEXIT_MAX + {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, +#endif +#ifdef _SC_AUDIT + {"SC_AUDIT", _SC_AUDIT}, +#endif +#ifdef _SC_AVPHYS_PAGES + {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, +#endif +#ifdef _SC_BC_BASE_MAX + {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, +#endif +#ifdef _SC_BC_DIM_MAX + {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, +#endif +#ifdef _SC_BC_SCALE_MAX + {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, +#endif +#ifdef _SC_BC_STRING_MAX + {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, +#endif +#ifdef _SC_CAP + {"SC_CAP", _SC_CAP}, +#endif +#ifdef _SC_CHARCLASS_NAME_MAX + {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, +#endif +#ifdef _SC_CHAR_BIT + {"SC_CHAR_BIT", _SC_CHAR_BIT}, +#endif +#ifdef _SC_CHAR_MAX + {"SC_CHAR_MAX", _SC_CHAR_MAX}, +#endif +#ifdef _SC_CHAR_MIN + {"SC_CHAR_MIN", _SC_CHAR_MIN}, +#endif +#ifdef _SC_CHILD_MAX + {"SC_CHILD_MAX", _SC_CHILD_MAX}, +#endif +#ifdef _SC_CLK_TCK + {"SC_CLK_TCK", _SC_CLK_TCK}, +#endif +#ifdef _SC_COHER_BLKSZ + {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, +#endif +#ifdef _SC_COLL_WEIGHTS_MAX + {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, +#endif +#ifdef _SC_DCACHE_ASSOC + {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, +#endif +#ifdef _SC_DCACHE_BLKSZ + {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, +#endif +#ifdef _SC_DCACHE_LINESZ + {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, +#endif +#ifdef _SC_DCACHE_SZ + {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, +#endif +#ifdef _SC_DCACHE_TBLKSZ + {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, +#endif +#ifdef _SC_DELAYTIMER_MAX + {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, +#endif +#ifdef _SC_EQUIV_CLASS_MAX + {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, +#endif +#ifdef _SC_EXPR_NEST_MAX + {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, +#endif +#ifdef _SC_FSYNC + {"SC_FSYNC", _SC_FSYNC}, +#endif +#ifdef _SC_GETGR_R_SIZE_MAX + {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, +#endif +#ifdef _SC_GETPW_R_SIZE_MAX + {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, +#endif +#ifdef _SC_ICACHE_ASSOC + {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, +#endif +#ifdef _SC_ICACHE_BLKSZ + {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, +#endif +#ifdef _SC_ICACHE_LINESZ + {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, +#endif +#ifdef _SC_ICACHE_SZ + {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, +#endif +#ifdef _SC_INF + {"SC_INF", _SC_INF}, +#endif +#ifdef _SC_INT_MAX + {"SC_INT_MAX", _SC_INT_MAX}, +#endif +#ifdef _SC_INT_MIN + {"SC_INT_MIN", _SC_INT_MIN}, +#endif +#ifdef _SC_IOV_MAX + {"SC_IOV_MAX", _SC_IOV_MAX}, +#endif +#ifdef _SC_IP_SECOPTS + {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, +#endif +#ifdef _SC_JOB_CONTROL + {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, +#endif +#ifdef _SC_KERN_POINTERS + {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, +#endif +#ifdef _SC_KERN_SIM + {"SC_KERN_SIM", _SC_KERN_SIM}, +#endif +#ifdef _SC_LINE_MAX + {"SC_LINE_MAX", _SC_LINE_MAX}, +#endif +#ifdef _SC_LOGIN_NAME_MAX + {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, +#endif +#ifdef _SC_LOGNAME_MAX + {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, +#endif +#ifdef _SC_LONG_BIT + {"SC_LONG_BIT", _SC_LONG_BIT}, +#endif +#ifdef _SC_MAC + {"SC_MAC", _SC_MAC}, +#endif +#ifdef _SC_MAPPED_FILES + {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, +#endif +#ifdef _SC_MAXPID + {"SC_MAXPID", _SC_MAXPID}, +#endif +#ifdef _SC_MB_LEN_MAX + {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, +#endif +#ifdef _SC_MEMLOCK + {"SC_MEMLOCK", _SC_MEMLOCK}, +#endif +#ifdef _SC_MEMLOCK_RANGE + {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, +#endif +#ifdef _SC_MEMORY_PROTECTION + {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, +#endif +#ifdef _SC_MESSAGE_PASSING + {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, +#endif +#ifdef _SC_MMAP_FIXED_ALIGNMENT + {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, +#endif +#ifdef _SC_MQ_OPEN_MAX + {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, +#endif +#ifdef _SC_MQ_PRIO_MAX + {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX}, +#endif +#ifdef _SC_NACLS_MAX + {"SC_NACLS_MAX", _SC_NACLS_MAX}, +#endif +#ifdef _SC_NGROUPS_MAX + {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX}, +#endif +#ifdef _SC_NL_ARGMAX + {"SC_NL_ARGMAX", _SC_NL_ARGMAX}, +#endif +#ifdef _SC_NL_LANGMAX + {"SC_NL_LANGMAX", _SC_NL_LANGMAX}, +#endif +#ifdef _SC_NL_MSGMAX + {"SC_NL_MSGMAX", _SC_NL_MSGMAX}, +#endif +#ifdef _SC_NL_NMAX + {"SC_NL_NMAX", _SC_NL_NMAX}, +#endif +#ifdef _SC_NL_SETMAX + {"SC_NL_SETMAX", _SC_NL_SETMAX}, +#endif +#ifdef _SC_NL_TEXTMAX + {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX}, +#endif +#ifdef _SC_NPROCESSORS_CONF + {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF}, +#endif +#ifdef _SC_NPROCESSORS_ONLN + {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN}, +#endif +#ifdef _SC_NPROC_CONF + {"SC_NPROC_CONF", _SC_NPROC_CONF}, +#endif +#ifdef _SC_NPROC_ONLN + {"SC_NPROC_ONLN", _SC_NPROC_ONLN}, +#endif +#ifdef _SC_NZERO + {"SC_NZERO", _SC_NZERO}, +#endif +#ifdef _SC_OPEN_MAX + {"SC_OPEN_MAX", _SC_OPEN_MAX}, +#endif +#ifdef _SC_PAGESIZE + {"SC_PAGESIZE", _SC_PAGESIZE}, +#endif +#ifdef _SC_PAGE_SIZE + {"SC_PAGE_SIZE", _SC_PAGE_SIZE}, +#endif +#ifdef _SC_PASS_MAX + {"SC_PASS_MAX", _SC_PASS_MAX}, +#endif +#ifdef _SC_PHYS_PAGES + {"SC_PHYS_PAGES", _SC_PHYS_PAGES}, +#endif +#ifdef _SC_PII + {"SC_PII", _SC_PII}, +#endif +#ifdef _SC_PII_INTERNET + {"SC_PII_INTERNET", _SC_PII_INTERNET}, +#endif +#ifdef _SC_PII_INTERNET_DGRAM + {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM}, +#endif +#ifdef _SC_PII_INTERNET_STREAM + {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM}, +#endif +#ifdef _SC_PII_OSI + {"SC_PII_OSI", _SC_PII_OSI}, +#endif +#ifdef _SC_PII_OSI_CLTS + {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, +#endif +#ifdef _SC_PII_OSI_COTS + {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, +#endif +#ifdef _SC_PII_OSI_M + {"SC_PII_OSI_M", _SC_PII_OSI_M}, +#endif +#ifdef _SC_PII_SOCKET + {"SC_PII_SOCKET", _SC_PII_SOCKET}, +#endif +#ifdef _SC_PII_XTI + {"SC_PII_XTI", _SC_PII_XTI}, +#endif +#ifdef _SC_POLL + {"SC_POLL", _SC_POLL}, +#endif +#ifdef _SC_PRIORITIZED_IO + {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO}, +#endif +#ifdef _SC_PRIORITY_SCHEDULING + {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING}, +#endif +#ifdef _SC_REALTIME_SIGNALS + {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS}, +#endif +#ifdef _SC_RE_DUP_MAX + {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX}, +#endif +#ifdef _SC_RTSIG_MAX + {"SC_RTSIG_MAX", _SC_RTSIG_MAX}, +#endif +#ifdef _SC_SAVED_IDS + {"SC_SAVED_IDS", _SC_SAVED_IDS}, +#endif +#ifdef _SC_SCHAR_MAX + {"SC_SCHAR_MAX", _SC_SCHAR_MAX}, +#endif +#ifdef _SC_SCHAR_MIN + {"SC_SCHAR_MIN", _SC_SCHAR_MIN}, +#endif +#ifdef _SC_SELECT + {"SC_SELECT", _SC_SELECT}, +#endif +#ifdef _SC_SEMAPHORES + {"SC_SEMAPHORES", _SC_SEMAPHORES}, +#endif +#ifdef _SC_SEM_NSEMS_MAX + {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX}, +#endif +#ifdef _SC_SEM_VALUE_MAX + {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX}, +#endif +#ifdef _SC_SHARED_MEMORY_OBJECTS + {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS}, +#endif +#ifdef _SC_SHRT_MAX + {"SC_SHRT_MAX", _SC_SHRT_MAX}, +#endif +#ifdef _SC_SHRT_MIN + {"SC_SHRT_MIN", _SC_SHRT_MIN}, +#endif +#ifdef _SC_SIGQUEUE_MAX + {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, +#endif +#ifdef _SC_SIGRT_MAX + {"SC_SIGRT_MAX", _SC_SIGRT_MAX}, +#endif +#ifdef _SC_SIGRT_MIN + {"SC_SIGRT_MIN", _SC_SIGRT_MIN}, +#endif +#ifdef _SC_SOFTPOWER + {"SC_SOFTPOWER", _SC_SOFTPOWER}, +#endif +#ifdef _SC_SPLIT_CACHE + {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE}, +#endif +#ifdef _SC_SSIZE_MAX + {"SC_SSIZE_MAX", _SC_SSIZE_MAX}, +#endif +#ifdef _SC_STACK_PROT + {"SC_STACK_PROT", _SC_STACK_PROT}, +#endif +#ifdef _SC_STREAM_MAX + {"SC_STREAM_MAX", _SC_STREAM_MAX}, +#endif +#ifdef _SC_SYNCHRONIZED_IO + {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO}, +#endif +#ifdef _SC_THREADS + {"SC_THREADS", _SC_THREADS}, +#endif +#ifdef _SC_THREAD_ATTR_STACKADDR + {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR}, +#endif +#ifdef _SC_THREAD_ATTR_STACKSIZE + {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE}, +#endif +#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS + {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, +#endif +#ifdef _SC_THREAD_KEYS_MAX + {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX}, +#endif +#ifdef _SC_THREAD_PRIORITY_SCHEDULING + {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING}, +#endif +#ifdef _SC_THREAD_PRIO_INHERIT + {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT}, +#endif +#ifdef _SC_THREAD_PRIO_PROTECT + {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT}, +#endif +#ifdef _SC_THREAD_PROCESS_SHARED + {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED}, +#endif +#ifdef _SC_THREAD_SAFE_FUNCTIONS + {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS}, +#endif +#ifdef _SC_THREAD_STACK_MIN + {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN}, +#endif +#ifdef _SC_THREAD_THREADS_MAX + {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX}, +#endif +#ifdef _SC_TIMERS + {"SC_TIMERS", _SC_TIMERS}, +#endif +#ifdef _SC_TIMER_MAX + {"SC_TIMER_MAX", _SC_TIMER_MAX}, +#endif +#ifdef _SC_TTY_NAME_MAX + {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, +#endif +#ifdef _SC_TZNAME_MAX + {"SC_TZNAME_MAX", _SC_TZNAME_MAX}, +#endif +#ifdef _SC_T_IOV_MAX + {"SC_T_IOV_MAX", _SC_T_IOV_MAX}, +#endif +#ifdef _SC_UCHAR_MAX + {"SC_UCHAR_MAX", _SC_UCHAR_MAX}, +#endif +#ifdef _SC_UINT_MAX + {"SC_UINT_MAX", _SC_UINT_MAX}, +#endif +#ifdef _SC_UIO_MAXIOV + {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV}, +#endif +#ifdef _SC_ULONG_MAX + {"SC_ULONG_MAX", _SC_ULONG_MAX}, +#endif +#ifdef _SC_USHRT_MAX + {"SC_USHRT_MAX", _SC_USHRT_MAX}, +#endif +#ifdef _SC_VERSION + {"SC_VERSION", _SC_VERSION}, +#endif +#ifdef _SC_WORD_BIT + {"SC_WORD_BIT", _SC_WORD_BIT}, +#endif +#ifdef _SC_XBS5_ILP32_OFF32 + {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32}, +#endif +#ifdef _SC_XBS5_ILP32_OFFBIG + {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG}, +#endif +#ifdef _SC_XBS5_LP64_OFF64 + {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64}, +#endif +#ifdef _SC_XBS5_LPBIG_OFFBIG + {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG}, +#endif +#ifdef _SC_XOPEN_CRYPT + {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT}, +#endif +#ifdef _SC_XOPEN_ENH_I18N + {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N}, +#endif +#ifdef _SC_XOPEN_LEGACY + {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, +#endif +#ifdef _SC_XOPEN_REALTIME + {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME}, +#endif +#ifdef _SC_XOPEN_REALTIME_THREADS + {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS}, +#endif +#ifdef _SC_XOPEN_SHM + {"SC_XOPEN_SHM", _SC_XOPEN_SHM}, +#endif +#ifdef _SC_XOPEN_UNIX + {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX}, +#endif +#ifdef _SC_XOPEN_VERSION + {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION}, +#endif +#ifdef _SC_XOPEN_XCU_VERSION + {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION}, +#endif +#ifdef _SC_XOPEN_XPG2 + {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2}, +#endif +#ifdef _SC_XOPEN_XPG3 + {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3}, +#endif +#ifdef _SC_XOPEN_XPG4 + {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4}, +#endif +}; + +static int +conv_sysconf_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_sysconf, + sizeof(posix_constants_sysconf) + / sizeof(struct constdef)); +} + +PyDoc_STRVAR(posix_sysconf__doc__, +"sysconf(name) -> integer\n\n\ +Return an integer-valued system configuration variable."); + +static PyObject * +posix_sysconf(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + int name; + + if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) { + int value; + + errno = 0; + value = sysconf(name); + if (value == -1 && errno != 0) + posix_error(); + else + result = PyInt_FromLong(value); + } + return result; +} +#endif + + +/* This code is used to ensure that the tables of configuration value names + * are in sorted order as required by conv_confname(), and also to build the + * the exported dictionaries that are used to publish information about the + * names available on the host platform. + * + * Sorting the table at runtime ensures that the table is properly ordered + * when used, even for platforms we're not able to test on. It also makes + * it easier to add additional entries to the tables. + */ + +static int +cmp_constdefs(const void *v1, const void *v2) +{ + const struct constdef *c1 = + (const struct constdef *) v1; + const struct constdef *c2 = + (const struct constdef *) v2; + + return strcmp(c1->name, c2->name); +} + +static int +setup_confname_table(struct constdef *table, size_t tablesize, + char *tablename, PyObject *module) +{ + PyObject *d = NULL; + size_t i; + + qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); + d = PyDict_New(); + if (d == NULL) + return -1; + + for (i=0; i < tablesize; ++i) { + PyObject *o = PyInt_FromLong(table[i].value); + if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { + Py_XDECREF(o); + Py_DECREF(d); + return -1; + } + Py_DECREF(o); + } + return PyModule_AddObject(module, tablename, d); +} + +/* Return -1 on failure, 0 on success. */ +static int +setup_confname_tables(PyObject *module) +{ +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) + if (setup_confname_table(posix_constants_pathconf, + sizeof(posix_constants_pathconf) + / sizeof(struct constdef), + "pathconf_names", module)) + return -1; +#endif +#ifdef HAVE_CONFSTR + if (setup_confname_table(posix_constants_confstr, + sizeof(posix_constants_confstr) + / sizeof(struct constdef), + "confstr_names", module)) + return -1; +#endif +#ifdef HAVE_SYSCONF + if (setup_confname_table(posix_constants_sysconf, + sizeof(posix_constants_sysconf) + / sizeof(struct constdef), + "sysconf_names", module)) + return -1; +#endif + return 0; +} + + +PyDoc_STRVAR(posix_abort__doc__, +"abort() -> does not return!\n\n\ +Abort the interpreter immediately. This 'dumps core' or otherwise fails\n\ +in the hardest way possible on the hosting operating system."); + +static PyObject * +posix_abort(PyObject *self, PyObject *noargs) +{ + abort(); + /*NOTREACHED*/ + Py_FatalError("abort() called from Python code didn't abort!"); + return NULL; +} + +#ifdef HAVE_SETRESUID +PyDoc_STRVAR(posix_setresuid__doc__, +"setresuid(ruid, euid, suid)\n\n\ +Set the current process's real, effective, and saved user ids."); + +static PyObject* +posix_setresuid (PyObject *self, PyObject *args) +{ + /* We assume uid_t is no larger than a long. */ + long ruid, euid, suid; + if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid)) + return NULL; + if (setresuid(ruid, euid, suid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_SETRESGID +PyDoc_STRVAR(posix_setresgid__doc__, +"setresgid(rgid, egid, sgid)\n\n\ +Set the current process's real, effective, and saved group ids."); + +static PyObject* +posix_setresgid (PyObject *self, PyObject *args) +{ + /* We assume uid_t is no larger than a long. */ + long rgid, egid, sgid; + if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid)) + return NULL; + if (setresgid(rgid, egid, sgid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_GETRESUID +PyDoc_STRVAR(posix_getresuid__doc__, +"getresuid() -> (ruid, euid, suid)\n\n\ +Get tuple of the current process's real, effective, and saved user ids."); + +static PyObject* +posix_getresuid (PyObject *self, PyObject *noargs) +{ + uid_t ruid, euid, suid; + long l_ruid, l_euid, l_suid; + if (getresuid(&ruid, &euid, &suid) < 0) + return posix_error(); + /* Force the values into long's as we don't know the size of uid_t. */ + l_ruid = ruid; + l_euid = euid; + l_suid = suid; + return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid); +} +#endif + +#ifdef HAVE_GETRESGID +PyDoc_STRVAR(posix_getresgid__doc__, +"getresgid() -> (rgid, egid, sgid)\n\n\ +Get tuple of the current process's real, effective, and saved group ids."); + +static PyObject* +posix_getresgid (PyObject *self, PyObject *noargs) +{ + uid_t rgid, egid, sgid; + long l_rgid, l_egid, l_sgid; + if (getresgid(&rgid, &egid, &sgid) < 0) + return posix_error(); + /* Force the values into long's as we don't know the size of uid_t. */ + l_rgid = rgid; + l_egid = egid; + l_sgid = sgid; + return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid); +} +#endif + +static PyMethodDef posix_methods[] = { + {"access", posix_access, METH_VARARGS, posix_access__doc__}, +#ifdef HAVE_TTYNAME + {"ttyname", posix_ttyname, METH_VARARGS, posix_ttyname__doc__}, +#endif + {"chdir", posix_chdir, METH_VARARGS, posix_chdir__doc__}, +#ifdef HAVE_CHFLAGS + {"chflags", posix_chflags, METH_VARARGS, posix_chflags__doc__}, +#endif /* HAVE_CHFLAGS */ + {"chmod", posix_chmod, METH_VARARGS, posix_chmod__doc__}, +#ifdef HAVE_FCHMOD + {"fchmod", posix_fchmod, METH_VARARGS, posix_fchmod__doc__}, +#endif /* HAVE_FCHMOD */ +#ifdef HAVE_CHOWN + {"chown", posix_chown, METH_VARARGS, posix_chown__doc__}, +#endif /* HAVE_CHOWN */ +#ifdef HAVE_LCHMOD + {"lchmod", posix_lchmod, METH_VARARGS, posix_lchmod__doc__}, +#endif /* HAVE_LCHMOD */ +#ifdef HAVE_FCHOWN + {"fchown", posix_fchown, METH_VARARGS, posix_fchown__doc__}, +#endif /* HAVE_FCHOWN */ +#ifdef HAVE_LCHFLAGS + {"lchflags", posix_lchflags, METH_VARARGS, posix_lchflags__doc__}, +#endif /* HAVE_LCHFLAGS */ +#ifdef HAVE_LCHOWN + {"lchown", posix_lchown, METH_VARARGS, posix_lchown__doc__}, +#endif /* HAVE_LCHOWN */ +#ifdef HAVE_CHROOT + {"chroot", posix_chroot, METH_VARARGS, posix_chroot__doc__}, +#endif +#ifdef HAVE_CTERMID + {"ctermid", posix_ctermid, METH_NOARGS, posix_ctermid__doc__}, +#endif +#ifdef HAVE_GETCWD + {"getcwd", posix_getcwd, METH_NOARGS, posix_getcwd__doc__}, +#ifdef Py_USING_UNICODE + {"getcwdu", posix_getcwdu, METH_NOARGS, posix_getcwdu__doc__}, +#endif +#endif +#ifdef HAVE_LINK + {"link", posix_link, METH_VARARGS, posix_link__doc__}, +#endif /* HAVE_LINK */ + {"listdir", posix_listdir, METH_VARARGS, posix_listdir__doc__}, + {"lstat", posix_lstat, METH_VARARGS, posix_lstat__doc__}, + {"mkdir", posix_mkdir, METH_VARARGS, posix_mkdir__doc__}, +#ifdef HAVE_NICE + {"nice", posix_nice, METH_VARARGS, posix_nice__doc__}, +#endif /* HAVE_NICE */ +#ifdef HAVE_READLINK + {"readlink", posix_readlink, METH_VARARGS, posix_readlink__doc__}, +#endif /* HAVE_READLINK */ + {"rename", posix_rename, METH_VARARGS, posix_rename__doc__}, + {"rmdir", posix_rmdir, METH_VARARGS, posix_rmdir__doc__}, + {"stat", posix_stat, METH_VARARGS, posix_stat__doc__}, + //{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__}, +#ifdef HAVE_SYMLINK + {"symlink", posix_symlink, METH_VARARGS, posix_symlink__doc__}, +#endif /* HAVE_SYMLINK */ +#ifdef HAVE_SYSTEM + {"system", posix_system, METH_VARARGS, posix_system__doc__}, +#endif + {"umask", posix_umask, METH_VARARGS, posix_umask__doc__}, +#ifdef HAVE_UNAME + {"uname", posix_uname, METH_NOARGS, posix_uname__doc__}, +#endif /* HAVE_UNAME */ + {"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__}, + {"remove", posix_unlink, METH_VARARGS, posix_remove__doc__}, + {"utime", posix_utime, METH_VARARGS, posix_utime__doc__}, +#ifdef HAVE_TIMES + {"times", posix_times, METH_NOARGS, posix_times__doc__}, +#endif /* HAVE_TIMES */ + {"_exit", posix__exit, METH_VARARGS, posix__exit__doc__}, +#ifdef HAVE_EXECV + {"execv", posix_execv, METH_VARARGS, posix_execv__doc__}, + {"execve", posix_execve, METH_VARARGS, posix_execve__doc__}, +#endif /* HAVE_EXECV */ +#ifdef HAVE_SPAWNV + {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__}, + {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__}, +#if defined(PYOS_OS2) + {"spawnvp", posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__}, + {"spawnvpe", posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__}, +#endif /* PYOS_OS2 */ +#endif /* HAVE_SPAWNV */ +#ifdef HAVE_FORK1 + {"fork1", posix_fork1, METH_NOARGS, posix_fork1__doc__}, +#endif /* HAVE_FORK1 */ +#ifdef HAVE_FORK + {"fork", posix_fork, METH_NOARGS, posix_fork__doc__}, +#endif /* HAVE_FORK */ +#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) + {"openpty", posix_openpty, METH_NOARGS, posix_openpty__doc__}, +#endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */ +#ifdef HAVE_FORKPTY + {"forkpty", posix_forkpty, METH_NOARGS, posix_forkpty__doc__}, +#endif /* HAVE_FORKPTY */ +#ifdef HAVE_GETEGID + {"getegid", posix_getegid, METH_NOARGS, posix_getegid__doc__}, +#endif /* HAVE_GETEGID */ +#ifdef HAVE_GETEUID + {"geteuid", posix_geteuid, METH_NOARGS, posix_geteuid__doc__}, +#endif /* HAVE_GETEUID */ +#ifdef HAVE_GETGID + {"getgid", posix_getgid, METH_NOARGS, posix_getgid__doc__}, +#endif /* HAVE_GETGID */ +#ifdef HAVE_GETGROUPS + {"getgroups", posix_getgroups, METH_NOARGS, posix_getgroups__doc__}, +#endif + {"getpid", posix_getpid, METH_NOARGS, posix_getpid__doc__}, +#ifdef HAVE_GETPGRP + {"getpgrp", posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__}, +#endif /* HAVE_GETPGRP */ +#ifdef HAVE_GETPPID + {"getppid", posix_getppid, METH_NOARGS, posix_getppid__doc__}, +#endif /* HAVE_GETPPID */ +#ifdef HAVE_GETUID + {"getuid", posix_getuid, METH_NOARGS, posix_getuid__doc__}, +#endif /* HAVE_GETUID */ +#ifdef HAVE_GETLOGIN + {"getlogin", posix_getlogin, METH_NOARGS, posix_getlogin__doc__}, +#endif +#ifdef HAVE_KILL + {"kill", posix_kill, METH_VARARGS, posix_kill__doc__}, +#endif /* HAVE_KILL */ +#ifdef HAVE_KILLPG + {"killpg", posix_killpg, METH_VARARGS, posix_killpg__doc__}, +#endif /* HAVE_KILLPG */ +#ifdef HAVE_PLOCK + {"plock", posix_plock, METH_VARARGS, posix_plock__doc__}, +#endif /* HAVE_PLOCK */ +#ifdef HAVE_POPEN + {"popen", posix_popen, METH_VARARGS, posix_popen__doc__}, +#ifdef MS_WINDOWS + {"popen2", win32_popen2, METH_VARARGS}, + {"popen3", win32_popen3, METH_VARARGS}, + {"popen4", win32_popen4, METH_VARARGS}, + {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__}, + {"kill", win32_kill, METH_VARARGS, win32_kill__doc__}, +#else +#if defined(PYOS_OS2) && defined(PYCC_GCC) + {"popen2", os2emx_popen2, METH_VARARGS}, + {"popen3", os2emx_popen3, METH_VARARGS}, + {"popen4", os2emx_popen4, METH_VARARGS}, +#endif +#endif +#endif /* HAVE_POPEN */ +#ifdef HAVE_SETUID + {"setuid", posix_setuid, METH_VARARGS, posix_setuid__doc__}, +#endif /* HAVE_SETUID */ +#ifdef HAVE_SETEUID + {"seteuid", posix_seteuid, METH_VARARGS, posix_seteuid__doc__}, +#endif /* HAVE_SETEUID */ +#ifdef HAVE_SETEGID + {"setegid", posix_setegid, METH_VARARGS, posix_setegid__doc__}, +#endif /* HAVE_SETEGID */ +#ifdef HAVE_SETREUID + {"setreuid", posix_setreuid, METH_VARARGS, posix_setreuid__doc__}, +#endif /* HAVE_SETREUID */ +#ifdef HAVE_SETREGID + {"setregid", posix_setregid, METH_VARARGS, posix_setregid__doc__}, +#endif /* HAVE_SETREGID */ +#ifdef HAVE_SETGID + {"setgid", posix_setgid, METH_VARARGS, posix_setgid__doc__}, +#endif /* HAVE_SETGID */ +#ifdef HAVE_SETGROUPS + {"setgroups", posix_setgroups, METH_O, posix_setgroups__doc__}, +#endif /* HAVE_SETGROUPS */ +#ifdef HAVE_INITGROUPS + {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__}, +#endif /* HAVE_INITGROUPS */ +#ifdef HAVE_GETPGID + {"getpgid", posix_getpgid, METH_VARARGS, posix_getpgid__doc__}, +#endif /* HAVE_GETPGID */ +#ifdef HAVE_SETPGRP + {"setpgrp", posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__}, +#endif /* HAVE_SETPGRP */ +#ifdef HAVE_WAIT + {"wait", posix_wait, METH_NOARGS, posix_wait__doc__}, +#endif /* HAVE_WAIT */ +#ifdef HAVE_WAIT3 + {"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__}, +#endif /* HAVE_WAIT3 */ +#ifdef HAVE_WAIT4 + {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__}, +#endif /* HAVE_WAIT4 */ +#if defined(HAVE_WAITPID) || defined(HAVE_CWAIT) + {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__}, +#endif /* HAVE_WAITPID */ +#ifdef HAVE_GETSID + {"getsid", posix_getsid, METH_VARARGS, posix_getsid__doc__}, +#endif /* HAVE_GETSID */ +#ifdef HAVE_SETSID + {"setsid", posix_setsid, METH_NOARGS, posix_setsid__doc__}, +#endif /* HAVE_SETSID */ +#ifdef HAVE_SETPGID + {"setpgid", posix_setpgid, METH_VARARGS, posix_setpgid__doc__}, +#endif /* HAVE_SETPGID */ +#ifdef HAVE_TCGETPGRP + {"tcgetpgrp", posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__}, +#endif /* HAVE_TCGETPGRP */ +#ifdef HAVE_TCSETPGRP + {"tcsetpgrp", posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__}, +#endif /* HAVE_TCSETPGRP */ + {"open", posix_open, METH_VARARGS, posix_open__doc__}, + {"close", posix_close, METH_VARARGS, posix_close__doc__}, + {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__}, + {"dup", posix_dup, METH_VARARGS, posix_dup__doc__}, + {"dup2", posix_dup2, METH_VARARGS, posix_dup2__doc__}, + {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__}, + {"read", posix_read, METH_VARARGS, posix_read__doc__}, + {"write", posix_write, METH_VARARGS, posix_write__doc__}, + {"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__}, + {"fdopen", posix_fdopen, METH_VARARGS, posix_fdopen__doc__}, + {"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__}, +#ifdef HAVE_PIPE + {"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__}, +#endif +#ifdef HAVE_MKFIFO + {"mkfifo", posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__}, +#endif +#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) + {"mknod", posix_mknod, METH_VARARGS, posix_mknod__doc__}, +#endif +#ifdef HAVE_DEVICE_MACROS + {"major", posix_major, METH_VARARGS, posix_major__doc__}, + {"minor", posix_minor, METH_VARARGS, posix_minor__doc__}, + {"makedev", posix_makedev, METH_VARARGS, posix_makedev__doc__}, +#endif +#ifdef HAVE_FTRUNCATE + {"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__}, +#endif +#ifdef HAVE_PUTENV + {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__}, +#endif +#ifdef HAVE_UNSETENV + {"unsetenv", posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__}, +#endif + {"strerror", posix_strerror, METH_VARARGS, posix_strerror__doc__}, +#ifdef HAVE_FCHDIR + {"fchdir", posix_fchdir, METH_O, posix_fchdir__doc__}, +#endif +#ifdef HAVE_FSYNC + {"fsync", posix_fsync, METH_O, posix_fsync__doc__}, +#endif +#ifdef HAVE_FDATASYNC + {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__}, +#endif +#ifdef HAVE_SYS_WAIT_H +#ifdef WCOREDUMP + {"WCOREDUMP", posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__}, +#endif /* WCOREDUMP */ +#ifdef WIFCONTINUED + {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__}, +#endif /* WIFCONTINUED */ +#ifdef WIFSTOPPED + {"WIFSTOPPED", posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__}, +#endif /* WIFSTOPPED */ +#ifdef WIFSIGNALED + {"WIFSIGNALED", posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__}, +#endif /* WIFSIGNALED */ +#ifdef WIFEXITED + {"WIFEXITED", posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__}, +#endif /* WIFEXITED */ +#ifdef WEXITSTATUS + {"WEXITSTATUS", posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__}, +#endif /* WEXITSTATUS */ +#ifdef WTERMSIG + {"WTERMSIG", posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__}, +#endif /* WTERMSIG */ +#ifdef WSTOPSIG + {"WSTOPSIG", posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__}, +#endif /* WSTOPSIG */ +#endif /* HAVE_SYS_WAIT_H */ +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) + {"fstatvfs", posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__}, +#endif +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) + {"statvfs", posix_statvfs, METH_VARARGS, posix_statvfs__doc__}, +#endif +#ifdef HAVE_TMPFILE + {"tmpfile", posix_tmpfile, METH_NOARGS, posix_tmpfile__doc__}, +#endif +#ifdef HAVE_TEMPNAM + {"tempnam", posix_tempnam, METH_VARARGS, posix_tempnam__doc__}, +#endif +#ifdef HAVE_TMPNAM + {"tmpnam", posix_tmpnam, METH_NOARGS, posix_tmpnam__doc__}, +#endif +#ifdef HAVE_CONFSTR + {"confstr", posix_confstr, METH_VARARGS, posix_confstr__doc__}, +#endif +#ifdef HAVE_SYSCONF + {"sysconf", posix_sysconf, METH_VARARGS, posix_sysconf__doc__}, +#endif +#ifdef HAVE_FPATHCONF + {"fpathconf", posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__}, +#endif +#ifdef HAVE_PATHCONF + {"pathconf", posix_pathconf, METH_VARARGS, posix_pathconf__doc__}, +#endif + {"abort", posix_abort, METH_NOARGS, posix_abort__doc__}, +#ifdef HAVE_SETRESUID + {"setresuid", posix_setresuid, METH_VARARGS, posix_setresuid__doc__}, +#endif +#ifdef HAVE_SETRESGID + {"setresgid", posix_setresgid, METH_VARARGS, posix_setresgid__doc__}, +#endif +#ifdef HAVE_GETRESUID + {"getresuid", posix_getresuid, METH_NOARGS, posix_getresuid__doc__}, +#endif +#ifdef HAVE_GETRESGID + {"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__}, +#endif + + {NULL, NULL} /* Sentinel */ +}; + + +static int +ins(PyObject *module, char *symbol, long value) +{ + return PyModule_AddIntConstant(module, symbol, value); +} + +static int +all_ins(PyObject *d) +{ +#ifdef F_OK + if (ins(d, "F_OK", (long)F_OK)) return -1; +#endif +#ifdef R_OK + if (ins(d, "R_OK", (long)R_OK)) return -1; +#endif +#ifdef W_OK + if (ins(d, "W_OK", (long)W_OK)) return -1; +#endif +#ifdef X_OK + if (ins(d, "X_OK", (long)X_OK)) return -1; +#endif +#ifdef NGROUPS_MAX + if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1; +#endif +#ifdef TMP_MAX + if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1; +#endif +#ifdef WCONTINUED + if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1; +#endif +#ifdef WNOHANG + if (ins(d, "WNOHANG", (long)WNOHANG)) return -1; +#endif +#ifdef WUNTRACED + if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1; +#endif +#ifdef O_RDONLY + if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1; +#endif +#ifdef O_WRONLY + if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1; +#endif +#ifdef O_RDWR + if (ins(d, "O_RDWR", (long)O_RDWR)) return -1; +#endif +#ifdef O_NDELAY + if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1; +#endif +#ifdef O_NONBLOCK + if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1; +#endif +#ifdef O_APPEND + if (ins(d, "O_APPEND", (long)O_APPEND)) return -1; +#endif +#ifdef O_DSYNC + if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1; +#endif +#ifdef O_RSYNC + if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1; +#endif +#ifdef O_SYNC + if (ins(d, "O_SYNC", (long)O_SYNC)) return -1; +#endif +#ifdef O_NOCTTY + if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1; +#endif +#ifdef O_CREAT + if (ins(d, "O_CREAT", (long)O_CREAT)) return -1; +#endif +#ifdef O_EXCL + if (ins(d, "O_EXCL", (long)O_EXCL)) return -1; +#endif +#ifdef O_TRUNC + if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1; +#endif +#ifdef O_BINARY + if (ins(d, "O_BINARY", (long)O_BINARY)) return -1; +#endif +#ifdef O_TEXT + if (ins(d, "O_TEXT", (long)O_TEXT)) return -1; +#endif +#ifdef O_LARGEFILE + if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1; +#endif +#ifdef O_SHLOCK + if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1; +#endif +#ifdef O_EXLOCK + if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1; +#endif + +/* MS Windows */ +#ifdef O_NOINHERIT + /* Don't inherit in child processes. */ + if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1; +#endif +#ifdef _O_SHORT_LIVED + /* Optimize for short life (keep in memory). */ + /* MS forgot to define this one with a non-underscore form too. */ + if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1; +#endif +#ifdef O_TEMPORARY + /* Automatically delete when last handle is closed. */ + if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1; +#endif +#ifdef O_RANDOM + /* Optimize for random access. */ + if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1; +#endif +#ifdef O_SEQUENTIAL + /* Optimize for sequential access. */ + if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1; +#endif + +/* GNU extensions. */ +#ifdef O_ASYNC + /* Send a SIGIO signal whenever input or output + becomes available on file descriptor */ + if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1; +#endif +#ifdef O_DIRECT + /* Direct disk access. */ + if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1; +#endif +#ifdef O_DIRECTORY + /* Must be a directory. */ + if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1; +#endif +#ifdef O_NOFOLLOW + /* Do not follow links. */ + if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1; +#endif +#ifdef O_NOATIME + /* Do not update the access time. */ + if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1; +#endif + + /* These come from sysexits.h */ +#ifdef EX_OK + if (ins(d, "EX_OK", (long)EX_OK)) return -1; +#endif /* EX_OK */ +#ifdef EX_USAGE + if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1; +#endif /* EX_USAGE */ +#ifdef EX_DATAERR + if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1; +#endif /* EX_DATAERR */ +#ifdef EX_NOINPUT + if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1; +#endif /* EX_NOINPUT */ +#ifdef EX_NOUSER + if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1; +#endif /* EX_NOUSER */ +#ifdef EX_NOHOST + if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1; +#endif /* EX_NOHOST */ +#ifdef EX_UNAVAILABLE + if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1; +#endif /* EX_UNAVAILABLE */ +#ifdef EX_SOFTWARE + if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1; +#endif /* EX_SOFTWARE */ +#ifdef EX_OSERR + if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1; +#endif /* EX_OSERR */ +#ifdef EX_OSFILE + if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1; +#endif /* EX_OSFILE */ +#ifdef EX_CANTCREAT + if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1; +#endif /* EX_CANTCREAT */ +#ifdef EX_IOERR + if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1; +#endif /* EX_IOERR */ +#ifdef EX_TEMPFAIL + if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1; +#endif /* EX_TEMPFAIL */ +#ifdef EX_PROTOCOL + if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1; +#endif /* EX_PROTOCOL */ +#ifdef EX_NOPERM + if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1; +#endif /* EX_NOPERM */ +#ifdef EX_CONFIG + if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1; +#endif /* EX_CONFIG */ +#ifdef EX_NOTFOUND + if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1; +#endif /* EX_NOTFOUND */ + +#ifdef HAVE_SPAWNV +#if defined(PYOS_OS2) && defined(PYCC_GCC) + if (ins(d, "P_WAIT", (long)P_WAIT)) return -1; + if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1; + if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1; + if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1; + if (ins(d, "P_SESSION", (long)P_SESSION)) return -1; + if (ins(d, "P_DETACH", (long)P_DETACH)) return -1; + if (ins(d, "P_PM", (long)P_PM)) return -1; + if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1; + if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1; + if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1; + if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1; + if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1; + if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1; + if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1; + if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1; + if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1; + if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1; + if (ins(d, "P_TILDE", (long)P_TILDE)) return -1; + if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1; + if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1; +#else + if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1; + if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1; + if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1; + if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1; + if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1; +#endif +#endif + return 0; +} + +#define INITFUNC initedk2 +#define MODNAME "edk2" + +PyMODINIT_FUNC +INITFUNC(void) +{ + PyObject *m, *v; + + m = Py_InitModule3(MODNAME, + posix_methods, + posix__doc__); + if (m == NULL) + return; + +#ifndef UEFI_ENV + /* Initialize environ dictionary */ + v = convertenviron(); + Py_XINCREF(v); + if (v == NULL || PyModule_AddObject(m, "environ", v) != 0) + return; + Py_DECREF(v); +#endif /* UEFI_ENV */ + + if (all_ins(m)) + return; + + if (setup_confname_tables(m)) + return; + + Py_INCREF(PyExc_OSError); + PyModule_AddObject(m, "error", PyExc_OSError); + +#ifdef HAVE_PUTENV + if (posix_putenv_garbage == NULL) + posix_putenv_garbage = PyDict_New(); +#endif + + if (!initialized) { + stat_result_desc.name = MODNAME ".stat_result"; + stat_result_desc.fields[2].name = PyStructSequence_UnnamedField; + stat_result_desc.fields[3].name = PyStructSequence_UnnamedField; + stat_result_desc.fields[4].name = PyStructSequence_UnnamedField; + PyStructSequence_InitType(&StatResultType, &stat_result_desc); + structseq_new = StatResultType.tp_new; + StatResultType.tp_new = statresult_new; + + //statvfs_result_desc.name = MODNAME ".statvfs_result"; + //PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc); +#ifdef NEED_TICKS_PER_SECOND +# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) + ticks_per_second = sysconf(_SC_CLK_TCK); +# elif defined(HZ) + ticks_per_second = HZ; +# else + ticks_per_second = 60; /* magic fallback value; may be bogus */ +# endif +#endif + } + Py_INCREF((PyObject*) &StatResultType); + PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType); + //Py_INCREF((PyObject*) &StatVFSResultType); + //PyModule_AddObject(m, "statvfs_result", + // (PyObject*) &StatVFSResultType); + initialized = 1; + +} + +#ifdef __cplusplus +} +#endif + + diff --git a/AppPkg/Applications/Python/Efi/getpath.c b/AppPkg/Applications/Python/Efi/getpath.c index ba837bf522..5a8c520027 100644 --- a/AppPkg/Applications/Python/Efi/getpath.c +++ b/AppPkg/Applications/Python/Efi/getpath.c @@ -32,6 +32,7 @@ **/ #include #include +#include #ifdef __cplusplus extern "C" { @@ -126,15 +127,12 @@ isfile(char *filename) { struct stat buf; if (stat(filename, &buf) != 0) { - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] Not Found: file = \"%s\"\n", __func__, __LINE__, filename); return 0; } //if (!S_ISREG(buf.st_mode)) if (S_ISDIR(buf.st_mode)) { - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] Is DIR: file = \"%s\"\n", __func__, __LINE__, filename); return 0; } - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] SUCCESS: file = \"%s\"\n", __func__, __LINE__, filename); return 1; } @@ -159,11 +157,9 @@ ismodule(char *filename) if (strlen(filename) < MAXPATHLEN) { strcat(filename, Py_OptimizeFlag ? "o" : "c"); if (isfile(filename)) { - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename); return 1; } } - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] FAIL: file = \"%s\"\n", __func__, __LINE__, filename); return 0; } @@ -304,7 +300,6 @@ isxfile(char *filename) char *newbn; int bnlen; - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] ENTER: file = \"%s\"\n", __func__, __LINE__, filename); bn = basename(filename); // Separate off the file name component reduce(filename); // and isolate the path component bnlen = strlen(bn); @@ -315,22 +310,17 @@ isxfile(char *filename) bnlen += 4; } else if(strcmp(newbn, ".efi") != 0) { - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Bad extension\n", __func__, __LINE__); return 0; // File can not be executable. } joinpath(filename, bn); // Stitch path and file name back together - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename); if (stat(filename, &buf) != 0) { // Now, verify that file exists - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Does not exist\n", __func__, __LINE__); return 0; } if(S_ISDIR(buf.st_mode)) { // And it is not a directory. - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Is a directory\n", __func__, __LINE__); return 0; } - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] EXIT: file = \"%s\"\n", __func__, __LINE__, filename); return 1; } @@ -390,17 +380,12 @@ set_volume(char *Dest, char *path) { size_t VolLen; - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] ENTER: path = \"%s\"\n", __func__, __LINE__, path); if(is_absolute(path)) { VolLen = strcspn(path, "/\\:"); - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: VolLen = %d\n", __func__, __LINE__, VolLen); if((VolLen != 0) && (path[VolLen] == ':')) { (void) strncpyX(Dest, path, VolLen + 1); - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: VolLen = %d, Dest = \"%s\" path = \"%s\"\n", - // __func__, __LINE__, VolLen, Dest, path); } } - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] EXIT: Dest = \"%s\"\n", __func__, __LINE__, Dest); } @@ -481,16 +466,10 @@ calculate_path(void) char *prog = Py_GetProgramName(); char argv0_path[MAXPATHLEN+1]; char zip_path[MAXPATHLEN+1]; - //int pfound, efound; /* 1 if found; -1 if found build directory */ char *buf; size_t bufsz; size_t prefixsz; char *defpath; - //uint32_t nsexeclength = MAXPATHLEN; - - //unixify(path); - //unixify(rtpypath); - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]:\nENTER prog=\"%s\"\n path=\"%s\"\n", __func__, __LINE__, prog, path); /* ########################################################################### @@ -520,7 +499,6 @@ calculate_path(void) strncpy(progpath, path, MAXPATHLEN); joinpath(progpath, prog); - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath); if (isxfile(progpath)) break; @@ -539,10 +517,7 @@ calculate_path(void) argv0_path[MAXPATHLEN] = '\0'; set_volume(volume_name, argv0_path); - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: volume_name = \"%s\"\n", __func__, __LINE__, volume_name); reduce(argv0_path); - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath); - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: argv0_path = \"%s\"\n", __func__, __LINE__, argv0_path); /* At this point, argv0_path is guaranteed to be less than MAXPATHLEN bytes long. */ @@ -552,17 +527,9 @@ calculate_path(void) This is the full path to the platform independent libraries. ########################################################################### */ - //if (!(pfound = search_for_prefix(argv0_path, home))) { - // if (!Py_FrozenFlag) - // fprintf(stderr, - // "Could not find platform independent libraries \n"); strncpy(prefix, volume_name, MAXPATHLEN); joinpath(prefix, PREFIX); joinpath(prefix, lib_python); - //} - //else - // reduce(prefix); - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: V = \"%s\", Prefix = \"%s\"\n", __func__, __LINE__, volume_name, prefix); /* ########################################################################### Build the FULL path to the zipped-up Python library. @@ -570,37 +537,20 @@ calculate_path(void) strncpy(zip_path, prefix, MAXPATHLEN); zip_path[MAXPATHLEN] = '\0'; - //if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */ - reduce(zip_path); - //reduce(zip_path); - //} - //else - // strncpy(zip_path, PREFIX, MAXPATHLEN); + reduce(zip_path); joinpath(zip_path, "python00.zip"); bufsz = strlen(zip_path); /* Replace "00" with version */ zip_path[bufsz - 6] = VERSION[0]; zip_path[bufsz - 5] = VERSION[1]; - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Zip_path = \"%s\"\n", __func__, __LINE__, zip_path); /* ########################################################################### Build the FULL path to dynamically loadable libraries. ########################################################################### */ - //if (!(efound = search_for_exec_prefix(argv0_path, home))) { - // if (!Py_FrozenFlag) - // fprintf(stderr, - // "Could not find platform dependent libraries \n"); strncpy(exec_prefix, volume_name, MAXPATHLEN); joinpath(exec_prefix, EXEC_PREFIX); joinpath(exec_prefix, lib_python); - joinpath(exec_prefix, "dynaload"); - //} - /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Exec_prefix = \"%s\"\n", __func__, __LINE__, exec_prefix); - - //if ((!pfound || !efound) && !Py_FrozenFlag) - // fprintf(stderr, - // "Consider setting $PYTHONHOME to [%c]\n", DELIM); + joinpath(exec_prefix, "lib-dynload"); /* ########################################################################### Build the module search path. @@ -611,7 +561,6 @@ calculate_path(void) * If we're loading relative to the build directory, * return the compiled-in defaults instead. */ - //if (pfound > 0) { reduce(prefix); reduce(prefix); /* The prefix is the root directory, but reduce() chopped @@ -624,11 +573,6 @@ calculate_path(void) prefix[bufsz] = SEP; prefix[bufsz+1] = 0; } - //} - //else - // strncpy(prefix, PREFIX, MAXPATHLEN); - -//if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__, __LINE__, prefix); /* Calculate size of return buffer. */ @@ -655,7 +599,6 @@ calculate_path(void) } defpath = delim + 1; } -//if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: defpath = \"%s\"\n", __func__, __LINE__, defpath); bufsz += strlen(zip_path) + 1; bufsz += strlen(exec_prefix) + 1; @@ -670,7 +613,6 @@ calculate_path(void) module_search_path = PYTHONPATH; } else { - //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]:\n", __func__, __LINE__); /* Run-time value of $PYTHONPATH goes first */ if (rtpypath) { strcpy(buf, rtpypath); @@ -678,12 +620,10 @@ calculate_path(void) } else buf[0] = '\0'; -//if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: RTpath = \"%s\"\n", __func__, __LINE__, buf); /* Next is the default zip path */ strcat(buf, zip_path); strcat(buf, delimiter); -//if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: +Zip = \"%s\"\n", __func__, __LINE__, buf); /* Next goes merge of compile-time $PYTHONPATH with * dynamically located prefix. @@ -710,17 +650,13 @@ calculate_path(void) defpath = delim + 1; } strcat(buf, delimiter); -//if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: +Merge = \"%s\"\n", __func__, __LINE__, buf); /* Finally, on goes the directory for dynamic-load modules */ strcat(buf, exec_prefix); /* And publish the results */ module_search_path = buf; -//if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path); } - - //if (efound > 0) { /* At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib. We want to get back to the root value, so we have to remove the final three segments to get VOL:/Efi/StdLib. Because we don't know what VOL is, and @@ -737,9 +673,6 @@ calculate_path(void) exec_prefix[bufsz] = SEP; exec_prefix[bufsz+1] = 0; } - //} - //else - // strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN); if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path); if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__, __LINE__, prefix); if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: exec_prefix = \"%s\"\n", __func__, __LINE__, exec_prefix); diff --git a/AppPkg/Applications/Python/Ia32/pyconfig.h b/AppPkg/Applications/Python/Ia32/pyconfig.h index 866c0f0b13..6b05e4e161 100644 --- a/AppPkg/Applications/Python/Ia32/pyconfig.h +++ b/AppPkg/Applications/Python/Ia32/pyconfig.h @@ -10,16 +10,15 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ - - #ifndef Py_PYCONFIG_H #define Py_PYCONFIG_H -#define PLATFORM "UEFI 2.3 Ia32" +#include + +/* Define to indicate that code is being built to run in the UEFI Environment. */ +#define UEFI_ENV EFI_SYSTEM_TABLE_REVISION -//#ifndef PYTHONPATH -//# define PYTHONPATH "/Efi/StdLib/lib/python.27;/Efi/StdLib/lib/python.27/lib-dynload" -//#endif +#define PLATFORM "UEFI" /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD @@ -185,7 +184,7 @@ /* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_DIRENT_H +#define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H @@ -328,7 +327,7 @@ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the `getpeername' function. */ -#undef HAVE_GETPEERNAME +#define HAVE_GETPEERNAME 1 /* Define to 1 if you have the `getpgid' function. */ #undef HAVE_GETPGID @@ -514,10 +513,10 @@ #undef HAVE_PLOCK /* Define to 1 if you have the `poll' function. */ -#undef HAVE_POLL +#define HAVE_POLL 1 /* Define to 1 if you have the header file. */ -#define HAVE_POLL_H 1 +#undef HAVE_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_PROCESS_H @@ -550,7 +549,7 @@ #undef HAVE_READLINK /* Define to 1 if you have the `realpath' function. */ -#undef HAVE_REALPATH +#define HAVE_REALPATH 1 /* Define if you have readline 2.1 */ #undef HAVE_RL_CALLBACK @@ -577,7 +576,7 @@ #undef HAVE_ROUND /* Define to 1 if you have the `select' function. */ -#undef HAVE_SELECT +#define HAVE_SELECT 1 /* Define to 1 if you have the `sem_getvalue' function. */ #undef HAVE_SEM_GETVALUE @@ -824,7 +823,7 @@ #define HAVE_TEMPNAM 1 /* Define to 1 if you have the header file. */ -#define HAVE_TERMIOS_H 1 +#undef HAVE_TERMIOS_H /* Define to 1 if you have the header file. */ #undef HAVE_TERM_H @@ -888,7 +887,7 @@ #undef HAVE_UTIMES /* Define to 1 if you have the header file. */ -#undef HAVE_UTIME_H +#define HAVE_UTIME_H 1 /* Define to 1 if you have the `wait3' function. */ #undef HAVE_WAIT3 diff --git a/AppPkg/Applications/Python/Ipf/pyconfig.h b/AppPkg/Applications/Python/Ipf/pyconfig.h index cad7132c8c..3d8d03bd22 100644 --- a/AppPkg/Applications/Python/Ipf/pyconfig.h +++ b/AppPkg/Applications/Python/Ipf/pyconfig.h @@ -1,9 +1,24 @@ -/* pyconfig.h.in. Generated from configure.in by autoheader. */ - - +/** @file + Manually generated Python Configuration file for EDK II. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ #ifndef Py_PYCONFIG_H #define Py_PYCONFIG_H +#include + +/* Define to indicate that code is being built to run in the UEFI Environment. */ +#define UEFI_ENV EFI_SYSTEM_TABLE_REVISION + +#define PLATFORM "UEFI" /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD @@ -89,16 +104,16 @@ #undef HAVE_BROKEN_POLL /* Define if the Posix semaphores do not work on your system */ -#define HAVE_BROKEN_POSIX_SEMAPHORES +#define HAVE_BROKEN_POSIX_SEMAPHORES 1 /* Define if pthread_sigmask() does not work on your system. */ -#define HAVE_BROKEN_PTHREAD_SIGMASK +#define HAVE_BROKEN_PTHREAD_SIGMASK 1 /* define to 1 if your sem_getvalue is broken. */ -#undef HAVE_BROKEN_SEM_GETVALUE +#define HAVE_BROKEN_SEM_GETVALUE 1 /* Define this if you have the type _Bool. */ -#define HAVE_C99_BOOL +#define HAVE_C99_BOOL 1 /* Define to 1 if you have the `chflags' function. */ #undef HAVE_CHFLAGS @@ -110,7 +125,7 @@ #undef HAVE_CHROOT /* Define to 1 if you have the `clock' function. */ -#define HAVE_CLOCK +#define HAVE_CLOCK 1 /* Define to 1 if you have the `confstr' function. */ #undef HAVE_CONFSTR @@ -119,7 +134,7 @@ #undef HAVE_CONIO_H /* Define to 1 if you have the `copysign' function. */ -#define HAVE_COPYSIGN 1 +#undef HAVE_COPYSIGN /* Define to 1 if you have the `ctermid' function. */ #undef HAVE_CTERMID @@ -169,7 +184,7 @@ /* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_DIRENT_H +#define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H @@ -269,10 +284,10 @@ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getcwd' function. */ -#undef HAVE_GETCWD +#define HAVE_GETCWD 1 /* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */ -#define HAVE_GETC_UNLOCKED +#undef HAVE_GETC_UNLOCKED /* Define to 1 if you have the `getgroups' function. */ #undef HAVE_GETGROUPS @@ -308,7 +323,7 @@ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the `getpeername' function. */ -#undef HAVE_GETPEERNAME +#define HAVE_GETPEERNAME 1 /* Define to 1 if you have the `getpgid' function. */ #undef HAVE_GETPGID @@ -359,10 +374,10 @@ #undef HAVE_IEEEFP_H /* Define if you have the 'inet_aton' function. */ -#undef HAVE_INET_ATON +#define HAVE_INET_ATON 1 /* Define if you have the 'inet_pton' function. */ -#undef HAVE_INET_PTON +#define HAVE_INET_PTON 1 /* Define to 1 if you have the `initgroups' function. */ #undef HAVE_INITGROUPS @@ -383,7 +398,7 @@ #undef HAVE_KQUEUE /* Define to 1 if you have the header file. */ -#define HAVE_LANGINFO_H 1 +#undef HAVE_LANGINFO_H /* non-functional in EFI. */ /* Defined to enable large file support when an off_t is bigger than a long and long long is available and at least as big as an off_t. You may need to @@ -437,10 +452,10 @@ #undef HAVE_LOG1P /* Define this if you have the type long double. */ -#define HAVE_LONG_DOUBLE +#undef HAVE_LONG_DOUBLE /* Define this if you have the type long long. */ -#define HAVE_LONG_LONG +#define HAVE_LONG_LONG 1 /* Define to 1 if you have the `lstat' function. */ #define HAVE_LSTAT 1 @@ -494,7 +509,7 @@ #undef HAVE_PLOCK /* Define to 1 if you have the `poll' function. */ -#undef HAVE_POLL +#define HAVE_POLL 1 /* Define to 1 if you have the header file. */ #undef HAVE_POLL_H @@ -503,7 +518,7 @@ #undef HAVE_PROCESS_H /* Define if your compiler supports function prototype */ -#define HAVE_PROTOTYPES +#define HAVE_PROTOTYPES 1 /* Define if you have GNU PTH threads. */ #undef HAVE_PTH @@ -530,7 +545,7 @@ #undef HAVE_READLINK /* Define to 1 if you have the `realpath' function. */ -#undef HAVE_REALPATH +#define HAVE_REALPATH 1 /* Define if you have readline 2.1 */ #undef HAVE_RL_CALLBACK @@ -557,7 +572,7 @@ #undef HAVE_ROUND /* Define to 1 if you have the `select' function. */ -#undef HAVE_SELECT +#define HAVE_SELECT 1 /* Define to 1 if you have the `sem_getvalue' function. */ #undef HAVE_SEM_GETVALUE @@ -614,7 +629,7 @@ #undef HAVE_SETUID /* Define to 1 if you have the `setvbuf' function. */ -#undef HAVE_SETVBUF +#define HAVE_SETVBUF 1 /* Define to 1 if you have the header file. */ #undef HAVE_SHADOW_H @@ -647,7 +662,7 @@ #undef HAVE_SPAWN_H /* Define if your compiler provides ssize_t */ -#undef HAVE_SSIZE_T +#define HAVE_SSIZE_T 1 /* Define to 1 if you have the `statvfs' function. */ #undef HAVE_STATVFS @@ -660,7 +675,7 @@ /* Define if your compiler supports variable length function prototypes (e.g. void fprintf(FILE *, char *, ...);) *and* */ -#define HAVE_STDARG_PROTOTYPES +#define HAVE_STDARG_PROTOTYPES 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 @@ -756,16 +771,16 @@ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ -#undef HAVE_SYS_POLL_H +#define HAVE_SYS_POLL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SELECT_H +#define HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SOCKET_H +#define HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H @@ -804,7 +819,7 @@ #define HAVE_TEMPNAM 1 /* Define to 1 if you have the header file. */ -#define HAVE_TERMIOS_H 1 +#undef HAVE_TERMIOS_H /* Define to 1 if you have the header file. */ #undef HAVE_TERM_H @@ -851,7 +866,7 @@ #undef HAVE_UNAME /* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H +#define HAVE_UNISTD_H 1 /* Define to 1 if you have the `unsetenv' function. */ #undef HAVE_UNSETENV @@ -859,7 +874,7 @@ /* Define if you have a useable wchar_t type defined in wchar.h; useable means wchar_t must be an unsigned type with at least 16 bits. (see Include/unicodeobject.h). */ -#define HAVE_USABLE_WCHAR_T +#define HAVE_USABLE_WCHAR_T 1 /* Define to 1 if you have the header file. */ #undef HAVE_UTIL_H @@ -868,7 +883,7 @@ #undef HAVE_UTIMES /* Define to 1 if you have the header file. */ -#undef HAVE_UTIME_H +#define HAVE_UTIME_H 1 /* Define to 1 if you have the `wait3' function. */ #undef HAVE_WAIT3 @@ -880,14 +895,14 @@ #undef HAVE_WAITPID /* Define if the compiler provides a wchar.h header file. */ -#define HAVE_WCHAR_H +#define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcscoll' function. */ -#undef HAVE_WCSCOLL +#define HAVE_WCSCOLL 1 /* Define if tzset() actually switches the local timezone in a meaningful way. */ -#define HAVE_WORKING_TZSET +#undef HAVE_WORKING_TZSET /* Define if the zlib library has inflateCopy */ #undef HAVE_ZLIB_COPY @@ -913,25 +928,25 @@ #undef MVWDELCH_IS_EXPRESSION /* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT +#define PACKAGE_BUGREPORT "edk2-devel@lists.sourceforge.net" /* Define to the full name of this package. */ -#define PACKAGE_NAME EDK II Python Package +#define PACKAGE_NAME "EDK II Python Package" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING EDK II Python Package V0.1 +#define PACKAGE_STRING "EDK II Python Package V0.2" /* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME UDK_Python +#define PACKAGE_TARNAME "EADK_Python" /* Define to the home page for this package. */ -#define PACKAGE_URL http://edk2.tianocore.org/toolkit/python +#define PACKAGE_URL "http://edk2.tianocore.org/toolkit/python" /* Define to the version of this package. */ -#undef PACKAGE_VERSION V0.1 +#define PACKAGE_VERSION "V0.2" /* Define if POSIX semaphores aren't enabled on your system */ -#define POSIX_SEMAPHORES_NOT_ENABLED +#define POSIX_SEMAPHORES_NOT_ENABLED 1 /* Defined if PTHREAD_SCOPE_SYSTEM supported. */ #undef PTHREAD_SYSTEM_SCHED_SUPPORTED @@ -940,13 +955,13 @@ #undef PYLONG_BITS_IN_DIGIT /* Define to printf format modifier for long long type */ -#undef PY_FORMAT_LONG_LONG +#define PY_FORMAT_LONG_LONG "ll" /* Define to printf format modifier for Py_ssize_t */ -#undef PY_FORMAT_SIZE_T +#define PY_FORMAT_SIZE_T "z" /* Define as the integral type used for Unicode representation. */ -#undef PY_UNICODE_TYPE +#define PY_UNICODE_TYPE wchar_t /* Define if you want to build an interpreter with many run-time checks. */ #undef Py_DEBUG @@ -973,55 +988,59 @@ #undef SIGNED_RIGHT_SHIFT_ZERO_FILLS /* The size of `double', as computed by sizeof. */ -#undef SIZEOF_DOUBLE +#define SIZEOF_DOUBLE 8 /* The size of `float', as computed by sizeof. */ -#undef SIZEOF_FLOAT +#define SIZEOF_FLOAT 4 /* The size of `fpos_t', as computed by sizeof. */ -#undef SIZEOF_FPOS_T +#define SIZEOF_FPOS_T 8 /* The size of `int', as computed by sizeof. */ -#undef SIZEOF_INT +#define SIZEOF_INT 4 /* The size of `long', as computed by sizeof. */ -#undef SIZEOF_LONG +#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */ +#define SIZEOF_LONG 4 +#else +#define SIZEOF_LONG 8 +#endif /* The size of `long double', as computed by sizeof. */ #undef SIZEOF_LONG_DOUBLE /* The size of `long long', as computed by sizeof. */ -#undef SIZEOF_LONG_LONG +#define SIZEOF_LONG_LONG 8 /* The size of `off_t', as computed by sizeof. */ -#undef SIZEOF_OFF_T +#define SIZEOF_OFF_T 8 /* The size of `pid_t', as computed by sizeof. */ -#undef SIZEOF_PID_T +#define SIZEOF_PID_T 4 /* The size of `pthread_t', as computed by sizeof. */ #undef SIZEOF_PTHREAD_T /* The size of `short', as computed by sizeof. */ -#undef SIZEOF_SHORT +#define SIZEOF_SHORT 2 /* The size of `size_t', as computed by sizeof. */ -#undef SIZEOF_SIZE_T +#define SIZEOF_SIZE_T 8 /* The size of `time_t', as computed by sizeof. */ -#undef SIZEOF_TIME_T +#define SIZEOF_TIME_T 4 /* The size of `uintptr_t', as computed by sizeof. */ -#undef SIZEOF_UINTPTR_T +#define SIZEOF_UINTPTR_T 8 /* The size of `void *', as computed by sizeof. */ -#undef SIZEOF_VOID_P +#define SIZEOF_VOID_P 8 /* The size of `wchar_t', as computed by sizeof. */ -#undef SIZEOF_WCHAR_T +#define SIZEOF_WCHAR_T 2 /* The size of `_Bool', as computed by sizeof. */ -#undef SIZEOF__BOOL +#define SIZEOF__BOOL 1 /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 @@ -1190,59 +1209,52 @@ #undef __EXTENSIONS__ /* Define to 'long' if doesn't define. */ -#undef clock_t +//#undef clock_t /* Define to empty if `const' does not conform to ANSI C. */ -#undef const +//#undef const /* Define to `int' if doesn't define. */ -#undef gid_t +//#undef gid_t /* Define to the type of a signed integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ -#undef int32_t +//#undef int32_t /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ -#undef int64_t +//#undef int64_t /* Define to `int' if does not define. */ -#undef mode_t +//#undef mode_t /* Define to `long int' if does not define. */ -#undef off_t +//#undef off_t /* Define to `int' if does not define. */ -#undef pid_t +//#undef pid_t /* Define to empty if the keyword does not work. */ -#undef signed +//#undef signed /* Define to `unsigned int' if does not define. */ -#undef size_t +//#undef size_t /* Define to `int' if does not define. */ -#undef socklen_t +//#undef socklen_t /* Define to `int' if doesn't define. */ -#undef uid_t +//#undef uid_t /* Define to the type of an unsigned integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ -#undef uint32_t +//#undef uint32_t /* Define to the type of an unsigned integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ -#undef uint64_t +//#undef uint64_t /* Define to empty if the keyword does not work. */ -#undef volatile - - -/* Define the macros needed if on a UnixWare 7.x system. */ -#if defined(__USLC__) && defined(__SCO_VERSION__) -#define STRICT_SYSV_CURSES /* Don't use ncurses extensions */ -#endif +//#undef volatile #endif /*Py_PYCONFIG_H*/ - diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Include/osdefs.h b/AppPkg/Applications/Python/PyMod-2.7.2/Include/osdefs.h index 4d25a8faa2..f6bfdb01cc 100644 --- a/AppPkg/Applications/Python/PyMod-2.7.2/Include/osdefs.h +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Include/osdefs.h @@ -18,7 +18,7 @@ extern "C" { /* Mod by chrish: QNX has WATCOM, but isn't DOS */ -#if !defined(__QNX__) && !defined(EFIAPI) +#if !defined(__QNX__) && !defined(UEFI_ENV) #if defined(MS_WINDOWS) || defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__DJGPP__) || defined(PYOS_OS2) #if defined(PYOS_OS2) && defined(PYCC_GCC) #define MAXPATHLEN 260 @@ -57,8 +57,9 @@ extern "C" { /* Search path entry delimiter */ #ifndef DELIM - #ifdef EFIAPI + #ifdef UEFI_ENV #define DELIM ';' + #define DELIM_STR ";" #else #define DELIM ':' #endif diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Lib/ntpath.py b/AppPkg/Applications/Python/PyMod-2.7.2/Lib/ntpath.py new file mode 100644 index 0000000000..970a6038cf --- /dev/null +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Lib/ntpath.py @@ -0,0 +1,528 @@ +# Module 'ntpath' -- common operations on WinNT/Win95 pathnames +"""Common pathname manipulations, WindowsNT/95 version. + +Instead of importing this module directly, import os and refer to this +module as os.path. +""" + +import os +import sys +import stat +import genericpath +import warnings + +from genericpath import * + +__all__ = ["normcase","isabs","join","splitdrive","split","splitext", + "basename","dirname","commonprefix","getsize","getmtime", + "getatime","getctime", "islink","exists","lexists","isdir","isfile", + "ismount","walk","expanduser","expandvars","normpath","abspath", + "splitunc","curdir","pardir","sep","pathsep","defpath","altsep", + "extsep","devnull","realpath","supports_unicode_filenames","relpath"] + +# strings representing various path-related bits and pieces +curdir = '.' +pardir = '..' +extsep = '.' +sep = '\\' +pathsep = ';' +altsep = '/' +defpath = '.;C:\\bin' +if 'ce' in sys.builtin_module_names: + defpath = '\\Windows' +elif 'os2' in sys.builtin_module_names: + # OS/2 w/ VACPP + altsep = '/' +devnull = 'nul' + +# Normalize the case of a pathname and map slashes to backslashes. +# Other normalizations (such as optimizing '../' away) are not done +# (this is done by normpath). + +def normcase(s): + """Normalize case of pathname. + + Makes all characters lowercase and all slashes into backslashes.""" + return s.replace("/", "\\").lower() + + +# Return whether a path is absolute. +# Trivial in Posix, harder on the Mac or MS-DOS. +# For DOS it is absolute if it starts with a slash or backslash (current +# volume), or if a pathname after the volume letter and colon / UNC resource +# starts with a slash or backslash. + +def isabs(s): + """Test whether a path is absolute""" + s = splitdrive(s)[1] + return s != '' and s[:1] in '/\\' + + +# Join two (or more) paths. + +def join(a, *p): + """Join two or more pathname components, inserting "\\" as needed. + If any component is an absolute path, all previous path components + will be discarded.""" + path = a + for b in p: + b_wins = 0 # set to 1 iff b makes path irrelevant + if path == "": + b_wins = 1 + + elif isabs(b): + # This probably wipes out path so far. However, it's more + # complicated if path begins with a drive letter: + # 1. join('c:', '/a') == 'c:/a' + # 2. join('c:/', '/a') == 'c:/a' + # But + # 3. join('c:/a', '/b') == '/b' + # 4. join('c:', 'd:/') = 'd:/' + # 5. join('c:/', 'd:/') = 'd:/' + if path[1:2] != ":" or b[1:2] == ":": + # Path doesn't start with a drive letter, or cases 4 and 5. + b_wins = 1 + + # Else path has a drive letter, and b doesn't but is absolute. + elif len(path) > 3 or (len(path) == 3 and + path[-1] not in "/\\"): + # case 3 + b_wins = 1 + + if b_wins: + path = b + else: + # Join, and ensure there's a separator. + assert len(path) > 0 + if path[-1] in "/\\": + if b and b[0] in "/\\": + path += b[1:] + else: + path += b + elif path[-1] == ":": + path += b + elif b: + if b[0] in "/\\": + path += b + else: + path += "\\" + b + else: + # path is not empty and does not end with a backslash, + # but b is empty; since, e.g., split('a/') produces + # ('a', ''), it's best if join() adds a backslash in + # this case. + path += '\\' + + return path + + +# Split a path in a drive specification (a drive letter followed by a +# colon) and the path specification. +# It is always true that drivespec + pathspec == p +def splitdrive(p): + """Split a pathname into drive and path specifiers. Returns a 2-tuple +"(drive,path)"; either part may be empty""" + pparts = p.split(':', 2) + numparts = len(pparts) + if numparts == 2: + return pparts[0] + ':', pparts[1] + else: + if numparts == 1: + return '', pparts[0] + return '', p + + +# Parse UNC paths +def splitunc(p): + """Split a pathname into UNC mount point and relative path specifiers. + + Return a 2-tuple (unc, rest); either part may be empty. + If unc is not empty, it has the form '//host/mount' (or similar + using backslashes). unc+rest is always the input path. + Paths containing drive letters never have an UNC part. + """ + if len(p.split(':', 2)) > 1: + return '', p # Drive letter present + firstTwo = p[0:2] + if firstTwo == '//' or firstTwo == '\\\\': + # is a UNC path: + # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter + # \\machine\mountpoint\directories... + # directory ^^^^^^^^^^^^^^^ + normp = normcase(p) + index = normp.find('\\', 2) + if index == -1: + ##raise RuntimeError, 'illegal UNC path: "' + p + '"' + return ("", p) + index = normp.find('\\', index + 1) + if index == -1: + index = len(p) + return p[:index], p[index:] + return '', p + + +# Split a path in head (everything up to the last '/') and tail (the +# rest). After the trailing '/' is stripped, the invariant +# join(head, tail) == p holds. +# The resulting head won't end in '/' unless it is the root. + +def split(p): + """Split a pathname. + + Return tuple (head, tail) where tail is everything after the final slash. + Either part may be empty.""" + + d, p = splitdrive(p) + # set i to index beyond p's last slash + i = len(p) + while i and p[i-1] not in '/\\': + i = i - 1 + head, tail = p[:i], p[i:] # now tail has no slashes + # remove trailing slashes from head, unless it's all slashes + head2 = head + while head2 and head2[-1] in '/\\': + head2 = head2[:-1] + head = head2 or head + return d + head, tail + + +# Split a path in root and extension. +# The extension is everything starting at the last dot in the last +# pathname component; the root is everything before that. +# It is always true that root + ext == p. + +def splitext(p): + return genericpath._splitext(p, sep, altsep, extsep) +splitext.__doc__ = genericpath._splitext.__doc__ + + +# Return the tail (basename) part of a path. + +def basename(p): + """Returns the final component of a pathname""" + return split(p)[1] + + +# Return the head (dirname) part of a path. + +def dirname(p): + """Returns the directory component of a pathname""" + return split(p)[0] + +# Is a path a symbolic link? +# This will always return false on systems where posix.lstat doesn't exist. + +def islink(path): + """Test for symbolic link. + On WindowsNT/95 and OS/2 always returns false + """ + return False + +# alias exists to lexists +lexists = exists + +# Is a path a mount point? Either a root (with or without drive letter) +# or an UNC path with at most a / or \ after the mount point. + +def ismount(path): + """Test whether a path is a mount point (defined as root of drive)""" + unc, rest = splitunc(path) + if unc: + return rest in ("", "/", "\\") + p = splitdrive(path)[1] + return len(p) == 1 and p[0] in '/\\' + + +# Directory tree walk. +# For each directory under top (including top itself, but excluding +# '.' and '..'), func(arg, dirname, filenames) is called, where +# dirname is the name of the directory and filenames is the list +# of files (and subdirectories etc.) in the directory. +# The func may modify the filenames list, to implement a filter, +# or to impose a different order of visiting. + +def walk(top, func, arg): + """Directory tree walk with callback function. + + For each directory in the directory tree rooted at top (including top + itself, but excluding '.' and '..'), call func(arg, dirname, fnames). + dirname is the name of the directory, and fnames a list of the names of + the files and subdirectories in dirname (excluding '.' and '..'). func + may modify the fnames list in-place (e.g. via del or slice assignment), + and walk will only recurse into the subdirectories whose names remain in + fnames; this can be used to implement a filter, or to impose a specific + order of visiting. No semantics are defined for, or required of, arg, + beyond that arg is always passed to func. It can be used, e.g., to pass + a filename pattern, or a mutable object designed to accumulate + statistics. Passing None for arg is common.""" + warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.", + stacklevel=2) + try: + names = os.listdir(top) + except os.error: + return + func(arg, top, names) + for name in names: + name = join(top, name) + if isdir(name): + walk(name, func, arg) + + +# Expand paths beginning with '~' or '~user'. +# '~' means $HOME; '~user' means that user's home directory. +# If the path doesn't begin with '~', or if the user or $HOME is unknown, +# the path is returned unchanged (leaving error reporting to whatever +# function is called with the expanded path as argument). +# See also module 'glob' for expansion of *, ? and [...] in pathnames. +# (A function should also be defined to do full *sh-style environment +# variable expansion.) + +def expanduser(path): + """Expand ~ and ~user constructs. + + If user or $HOME is unknown, do nothing.""" + if path[:1] != '~': + return path + i, n = 1, len(path) + while i < n and path[i] not in '/\\': + i = i + 1 + + if 'HOME' in os.environ: + userhome = os.environ['HOME'] + elif 'USERPROFILE' in os.environ: + userhome = os.environ['USERPROFILE'] + elif not 'HOMEPATH' in os.environ: + return path + else: + try: + drive = os.environ['HOMEDRIVE'] + except KeyError: + drive = '' + userhome = join(drive, os.environ['HOMEPATH']) + + if i != 1: #~user + userhome = join(dirname(userhome), path[1:i]) + + return userhome + path[i:] + + +# Expand paths containing shell variable substitutions. +# The following rules apply: +# - no expansion within single quotes +# - '$$' is translated into '$' +# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2% +# - ${varname} is accepted. +# - $varname is accepted. +# - %varname% is accepted. +# - varnames can be made out of letters, digits and the characters '_-' +# (though is not verified in the ${varname} and %varname% cases) +# XXX With COMMAND.COM you can use any characters in a variable name, +# XXX except '^|<>='. + +def expandvars(path): + """Expand shell variables of the forms $var, ${var} and %var%. + + Unknown variables are left unchanged.""" + if '$' not in path and '%' not in path: + return path + import string + varchars = string.ascii_letters + string.digits + '_-' + res = '' + index = 0 + pathlen = len(path) + while index < pathlen: + c = path[index] + if c == '\'': # no expansion within single quotes + path = path[index + 1:] + pathlen = len(path) + try: + index = path.index('\'') + res = res + '\'' + path[:index + 1] + except ValueError: + res = res + path + index = pathlen - 1 + elif c == '%': # variable or '%' + if path[index + 1:index + 2] == '%': + res = res + c + index = index + 1 + else: + path = path[index+1:] + pathlen = len(path) + try: + index = path.index('%') + except ValueError: + res = res + '%' + path + index = pathlen - 1 + else: + var = path[:index] + if var in os.environ: + res = res + os.environ[var] + else: + res = res + '%' + var + '%' + elif c == '$': # variable or '$$' + if path[index + 1:index + 2] == '$': + res = res + c + index = index + 1 + elif path[index + 1:index + 2] == '{': + path = path[index+2:] + pathlen = len(path) + try: + index = path.index('}') + var = path[:index] + if var in os.environ: + res = res + os.environ[var] + else: + res = res + '${' + var + '}' + except ValueError: + res = res + '${' + path + index = pathlen - 1 + else: + var = '' + index = index + 1 + c = path[index:index + 1] + while c != '' and c in varchars: + var = var + c + index = index + 1 + c = path[index:index + 1] + if var in os.environ: + res = res + os.environ[var] + else: + res = res + '$' + var + if c != '': + index = index - 1 + else: + res = res + c + index = index + 1 + return res + + +# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B. +# Previously, this function also truncated pathnames to 8+3 format, +# but as this module is called "ntpath", that's obviously wrong! + +def normpath(path): + """Normalize path, eliminating double slashes, etc.""" + # Preserve unicode (if path is unicode) + backslash, dot = (u'\\', u'.') if isinstance(path, unicode) else ('\\', '.') + if path.startswith(('\\\\.\\', '\\\\?\\')): + # in the case of paths with these prefixes: + # \\.\ -> device names + # \\?\ -> literal paths + # do not do any normalization, but return the path unchanged + return path + path = path.replace("/", "\\") + prefix, path = splitdrive(path) + # We need to be careful here. If the prefix is empty, and the path starts + # with a backslash, it could either be an absolute path on the current + # drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It + # is therefore imperative NOT to collapse multiple backslashes blindly in + # that case. + # The code below preserves multiple backslashes when there is no drive + # letter. This means that the invalid filename \\\a\b is preserved + # unchanged, where a\\\b is normalised to a\b. It's not clear that there + # is any better behaviour for such edge cases. + if prefix == '': + # No drive letter - preserve initial backslashes + while path[:1] == "\\": + prefix = prefix + backslash + path = path[1:] + else: + # We have a drive letter - collapse initial backslashes + if path.startswith("\\"): + prefix = prefix + backslash + path = path.lstrip("\\") + comps = path.split("\\") + i = 0 + while i < len(comps): + if comps[i] in ('.', ''): + del comps[i] + elif comps[i] == '..': + if i > 0 and comps[i-1] != '..': + del comps[i-1:i+1] + i -= 1 + elif i == 0 and prefix.endswith("\\"): + del comps[i] + else: + i += 1 + else: + i += 1 + # If the path is now empty, substitute '.' + if not prefix and not comps: + comps.append(dot) + return prefix + backslash.join(comps) + + +# Return an absolute path. +try: + from nt import _getfullpathname + +except ImportError: # not running on Windows - mock up something sensible + def abspath(path): + """Return the absolute version of a path.""" + if not isabs(path): + if isinstance(path, unicode): + cwd = os.getcwdu() + else: + cwd = os.getcwd() + path = join(cwd, path) + return normpath(path) + +else: # use native Windows method on Windows + def abspath(path): + """Return the absolute version of a path.""" + + if path: # Empty path must return current working directory. + try: + path = _getfullpathname(path) + except WindowsError: + pass # Bad path - return unchanged. + elif isinstance(path, unicode): + path = os.getcwdu() + else: + path = os.getcwd() + return normpath(path) + +# realpath is a no-op on systems without islink support +realpath = abspath +# Win9x family and earlier have no Unicode filename support. +supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and + sys.getwindowsversion()[3] >= 2) + +def _abspath_split(path): + abs = abspath(normpath(path)) + prefix, rest = splitunc(abs) + is_unc = bool(prefix) + if not is_unc: + prefix, rest = splitdrive(abs) + return is_unc, prefix, [x for x in rest.split(sep) if x] + +def relpath(path, start=curdir): + """Return a relative version of a path""" + + if not path: + raise ValueError("no path specified") + + start_is_unc, start_prefix, start_list = _abspath_split(start) + path_is_unc, path_prefix, path_list = _abspath_split(path) + + if path_is_unc ^ start_is_unc: + raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" + % (path, start)) + if path_prefix.lower() != start_prefix.lower(): + if path_is_unc: + raise ValueError("path is on UNC root %s, start on UNC root %s" + % (path_prefix, start_prefix)) + else: + raise ValueError("path is on drive %s, start on drive %s" + % (path_prefix, start_prefix)) + # Work out how much of the filepath is shared by start and path. + i = 0 + for e1, e2 in zip(start_list, path_list): + if e1.lower() != e2.lower(): + break + i += 1 + + rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + if not rel_list: + return curdir + return join(*rel_list) diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Lib/os.py b/AppPkg/Applications/Python/PyMod-2.7.2/Lib/os.py new file mode 100644 index 0000000000..413e4aea82 --- /dev/null +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Lib/os.py @@ -0,0 +1,773 @@ +"""OS routines for Mac, NT, Posix, or UEFI depending on what system we're on. + +This exports: + - all functions from edk2, posix, nt, os2, or ce, e.g. unlink, stat, etc. + - os.path is one of the modules uefipath, posixpath, or ntpath + - os.name is 'edk2', 'posix', 'nt', 'os2', 'ce' or 'riscos' + - os.curdir is a string representing the current directory ('.' or ':') + - os.pardir is a string representing the parent directory ('..' or '::') + - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\') + - os.extsep is the extension separator ('.' or '/') + - os.altsep is the alternate pathname separator (None or '/') + - os.pathsep is the component separator used in $PATH etc + - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n') + - os.defpath is the default search path for executables + - os.devnull is the file path of the null device ('/dev/null', etc.) + +Programs that import and use 'os' stand a better chance of being +portable between different platforms. Of course, they must then +only use functions that are defined by all platforms (e.g., unlink +and opendir), and leave all pathname manipulation to os.path +(e.g., split and join). +""" + +#' + +import sys, errno + +_names = sys.builtin_module_names + +# Note: more names are added to __all__ later. +__all__ = ["altsep", "curdir", "pardir", "sep", "extsep", "pathsep", "linesep", + "defpath", "name", "path", "devnull", + "SEEK_SET", "SEEK_CUR", "SEEK_END"] + +def _get_exports_list(module): + try: + return list(module.__all__) + except AttributeError: + return [n for n in dir(module) if n[0] != '_'] + +if 'posix' in _names: + name = 'posix' + linesep = '\n' + from posix import * + try: + from posix import _exit + except ImportError: + pass + import posixpath as path + + import posix + __all__.extend(_get_exports_list(posix)) + del posix + +elif 'nt' in _names: + name = 'nt' + linesep = '\r\n' + from nt import * + try: + from nt import _exit + except ImportError: + pass + import ntpath as path + + import nt + __all__.extend(_get_exports_list(nt)) + del nt + +elif 'os2' in _names: + name = 'os2' + linesep = '\r\n' + from os2 import * + try: + from os2 import _exit + except ImportError: + pass + if sys.version.find('EMX GCC') == -1: + import ntpath as path + else: + import os2emxpath as path + from _emx_link import link + + import os2 + __all__.extend(_get_exports_list(os2)) + del os2 + +elif 'ce' in _names: + name = 'ce' + linesep = '\r\n' + from ce import * + try: + from ce import _exit + except ImportError: + pass + # We can use the standard Windows path. + import ntpath as path + + import ce + __all__.extend(_get_exports_list(ce)) + del ce + +elif 'riscos' in _names: + name = 'riscos' + linesep = '\n' + from riscos import * + try: + from riscos import _exit + except ImportError: + pass + import riscospath as path + + import riscos + __all__.extend(_get_exports_list(riscos)) + del riscos + +elif 'edk2' in _names: + name = 'edk2' + linesep = '\n' + from edk2 import * + try: + from edk2 import _exit + except ImportError: + pass + import ntpath as path + + import edk2 + __all__.extend(_get_exports_list(edk2)) + del edk2 + +else: + raise ImportError, 'no os specific module found' + +sys.modules['os.path'] = path +from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep, + devnull) + +del _names + +# Python uses fixed values for the SEEK_ constants; they are mapped +# to native constants if necessary in posixmodule.c +SEEK_SET = 0 +SEEK_CUR = 1 +SEEK_END = 2 + +#' + +# Super directory utilities. +# (Inspired by Eric Raymond; the doc strings are mostly his) + +def makedirs(name, mode=0777): + """makedirs(path [, mode=0777]) + + Super-mkdir; create a leaf directory and all intermediate ones. + Works like mkdir, except that any intermediate path segment (not + just the rightmost) will be created if it does not exist. This is + recursive. + + """ + head, tail = path.split(name) + if not tail: + head, tail = path.split(head) + if head and tail and not path.exists(head): + try: + makedirs(head, mode) + except OSError, e: + # be happy if someone already created the path + if e.errno != errno.EEXIST: + raise + if tail == curdir: # xxx/newdir/. exists if xxx/newdir exists + return + mkdir(name, mode) + +def removedirs(name): + """removedirs(path) + + Super-rmdir; remove a leaf directory and all empty intermediate + ones. Works like rmdir except that, if the leaf directory is + successfully removed, directories corresponding to rightmost path + segments will be pruned away until either the whole path is + consumed or an error occurs. Errors during this latter phase are + ignored -- they generally mean that a directory was not empty. + + """ + rmdir(name) + head, tail = path.split(name) + if not tail: + head, tail = path.split(head) + while head and tail: + try: + rmdir(head) + except error: + break + head, tail = path.split(head) + +def renames(old, new): + """renames(old, new) + + Super-rename; create directories as necessary and delete any left + empty. Works like rename, except creation of any intermediate + directories needed to make the new pathname good is attempted + first. After the rename, directories corresponding to rightmost + path segments of the old name will be pruned way until either the + whole path is consumed or a nonempty directory is found. + + Note: this function can fail with the new directory structure made + if you lack permissions needed to unlink the leaf directory or + file. + + """ + head, tail = path.split(new) + if head and tail and not path.exists(head): + makedirs(head) + rename(old, new) + head, tail = path.split(old) + if head and tail: + try: + removedirs(head) + except error: + pass + +__all__.extend(["makedirs", "removedirs", "renames"]) + +def walk(top, topdown=True, onerror=None, followlinks=False): + """Directory tree generator. + + For each directory in the directory tree rooted at top (including top + itself, but excluding '.' and '..'), yields a 3-tuple + + dirpath, dirnames, filenames + + dirpath is a string, the path to the directory. dirnames is a list of + the names of the subdirectories in dirpath (excluding '.' and '..'). + filenames is a list of the names of the non-directory files in dirpath. + Note that the names in the lists are just names, with no path components. + To get a full path (which begins with top) to a file or directory in + dirpath, do os.path.join(dirpath, name). + + If optional arg 'topdown' is true or not specified, the triple for a + directory is generated before the triples for any of its subdirectories + (directories are generated top down). If topdown is false, the triple + for a directory is generated after the triples for all of its + subdirectories (directories are generated bottom up). + + When topdown is true, the caller can modify the dirnames list in-place + (e.g., via del or slice assignment), and walk will only recurse into the + subdirectories whose names remain in dirnames; this can be used to prune + the search, or to impose a specific order of visiting. Modifying + dirnames when topdown is false is ineffective, since the directories in + dirnames have already been generated by the time dirnames itself is + generated. + + By default errors from the os.listdir() call are ignored. If + optional arg 'onerror' is specified, it should be a function; it + will be called with one argument, an os.error instance. It can + report the error to continue with the walk, or raise the exception + to abort the walk. Note that the filename is available as the + filename attribute of the exception object. + + By default, os.walk does not follow symbolic links to subdirectories on + systems that support them. In order to get this functionality, set the + optional argument 'followlinks' to true. + + Caution: if you pass a relative pathname for top, don't change the + current working directory between resumptions of walk. walk never + changes the current directory, and assumes that the client doesn't + either. + + Example: + + import os + from os.path import join, getsize + for root, dirs, files in os.walk('python/Lib/email'): + print root, "consumes", + print sum([getsize(join(root, name)) for name in files]), + print "bytes in", len(files), "non-directory files" + if 'CVS' in dirs: + dirs.remove('CVS') # don't visit CVS directories + """ + + islink, join, isdir = path.islink, path.join, path.isdir + + # We may not have read permission for top, in which case we can't + # get a list of the files the directory contains. os.path.walk + # always suppressed the exception then, rather than blow up for a + # minor reason when (say) a thousand readable directories are still + # left to visit. That logic is copied here. + try: + # Note that listdir and error are globals in this module due + # to earlier import-*. + names = listdir(top) + except error, err: + if onerror is not None: + onerror(err) + return + + dirs, nondirs = [], [] + for name in names: + if isdir(join(top, name)): + dirs.append(name) + else: + nondirs.append(name) + + if topdown: + yield top, dirs, nondirs + for name in dirs: + new_path = join(top, name) + if followlinks or not islink(new_path): + for x in walk(new_path, topdown, onerror, followlinks): + yield x + if not topdown: + yield top, dirs, nondirs + +__all__.append("walk") + +# Make sure os.environ exists, at least +try: + environ +except NameError: + environ = {} + +def execl(file, *args): + """execl(file, *args) + + Execute the executable file with argument list args, replacing the + current process. """ + execv(file, args) + +def execle(file, *args): + """execle(file, *args, env) + + Execute the executable file with argument list args and + environment env, replacing the current process. """ + env = args[-1] + execve(file, args[:-1], env) + +def execlp(file, *args): + """execlp(file, *args) + + Execute the executable file (which is searched for along $PATH) + with argument list args, replacing the current process. """ + execvp(file, args) + +def execlpe(file, *args): + """execlpe(file, *args, env) + + Execute the executable file (which is searched for along $PATH) + with argument list args and environment env, replacing the current + process. """ + env = args[-1] + execvpe(file, args[:-1], env) + +def execvp(file, args): + """execvp(file, args) + + Execute the executable file (which is searched for along $PATH) + with argument list args, replacing the current process. + args may be a list or tuple of strings. """ + _execvpe(file, args) + +def execvpe(file, args, env): + """execvpe(file, args, env) + + Execute the executable file (which is searched for along $PATH) + with argument list args and environment env , replacing the + current process. + args may be a list or tuple of strings. """ + _execvpe(file, args, env) + +__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) + +def _execvpe(file, args, env=None): + if env is not None: + func = execve + argrest = (args, env) + else: + func = execv + argrest = (args,) + env = environ + + head, tail = path.split(file) + if head: + func(file, *argrest) + return + if 'PATH' in env: + envpath = env['PATH'] + else: + envpath = defpath + PATH = envpath.split(pathsep) + saved_exc = None + saved_tb = None + for dir in PATH: + fullname = path.join(dir, file) + try: + func(fullname, *argrest) + except error, e: + tb = sys.exc_info()[2] + if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR + and saved_exc is None): + saved_exc = e + saved_tb = tb + if saved_exc: + raise error, saved_exc, saved_tb + raise error, e, tb + +# Change environ to automatically call putenv() if it exists +try: + # This will fail if there's no putenv + putenv +except NameError: + pass +else: + import UserDict + + # Fake unsetenv() for Windows + # not sure about os2 here but + # I'm guessing they are the same. + + if name in ('os2', 'nt'): + def unsetenv(key): + putenv(key, "") + + if name == "riscos": + # On RISC OS, all env access goes through getenv and putenv + from riscosenviron import _Environ + elif name in ('os2', 'nt'): # Where Env Var Names Must Be UPPERCASE + # But we store them as upper case + class _Environ(UserDict.IterableUserDict): + def __init__(self, environ): + UserDict.UserDict.__init__(self) + data = self.data + for k, v in environ.items(): + data[k.upper()] = v + def __setitem__(self, key, item): + putenv(key, item) + self.data[key.upper()] = item + def __getitem__(self, key): + return self.data[key.upper()] + try: + unsetenv + except NameError: + def __delitem__(self, key): + del self.data[key.upper()] + else: + def __delitem__(self, key): + unsetenv(key) + del self.data[key.upper()] + def clear(self): + for key in self.data.keys(): + unsetenv(key) + del self.data[key] + def pop(self, key, *args): + unsetenv(key) + return self.data.pop(key.upper(), *args) + def has_key(self, key): + return key.upper() in self.data + def __contains__(self, key): + return key.upper() in self.data + def get(self, key, failobj=None): + return self.data.get(key.upper(), failobj) + def update(self, dict=None, **kwargs): + if dict: + try: + keys = dict.keys() + except AttributeError: + # List of (key, value) + for k, v in dict: + self[k] = v + else: + # got keys + # cannot use items(), since mappings + # may not have them. + for k in keys: + self[k] = dict[k] + if kwargs: + self.update(kwargs) + def copy(self): + return dict(self) + + else: # Where Env Var Names Can Be Mixed Case + class _Environ(UserDict.IterableUserDict): + def __init__(self, environ): + UserDict.UserDict.__init__(self) + self.data = environ + def __setitem__(self, key, item): + putenv(key, item) + self.data[key] = item + def update(self, dict=None, **kwargs): + if dict: + try: + keys = dict.keys() + except AttributeError: + # List of (key, value) + for k, v in dict: + self[k] = v + else: + # got keys + # cannot use items(), since mappings + # may not have them. + for k in keys: + self[k] = dict[k] + if kwargs: + self.update(kwargs) + try: + unsetenv + except NameError: + pass + else: + def __delitem__(self, key): + unsetenv(key) + del self.data[key] + def clear(self): + for key in self.data.keys(): + unsetenv(key) + del self.data[key] + def pop(self, key, *args): + unsetenv(key) + return self.data.pop(key, *args) + def copy(self): + return dict(self) + + + environ = _Environ(environ) + +def getenv(key, default=None): + """Get an environment variable, return None if it doesn't exist. + The optional second argument can specify an alternate default.""" + return environ.get(key, default) +__all__.append("getenv") + +def _exists(name): + return name in globals() + +# Supply spawn*() (probably only for Unix) +if _exists("fork") and not _exists("spawnv") and _exists("execv"): + + P_WAIT = 0 + P_NOWAIT = P_NOWAITO = 1 + + # XXX Should we support P_DETACH? I suppose it could fork()**2 + # and close the std I/O streams. Also, P_OVERLAY is the same + # as execv*()? + + def _spawnvef(mode, file, args, env, func): + # Internal helper; func is the exec*() function to use + pid = fork() + if not pid: + # Child + try: + if env is None: + func(file, args) + else: + func(file, args, env) + except: + _exit(127) + else: + # Parent + if mode == P_NOWAIT: + return pid # Caller is responsible for waiting! + while 1: + wpid, sts = waitpid(pid, 0) + if WIFSTOPPED(sts): + continue + elif WIFSIGNALED(sts): + return -WTERMSIG(sts) + elif WIFEXITED(sts): + return WEXITSTATUS(sts) + else: + raise error, "Not stopped, signaled or exited???" + + def spawnv(mode, file, args): + """spawnv(mode, file, args) -> integer + +Execute file with arguments from args in a subprocess. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return _spawnvef(mode, file, args, None, execv) + + def spawnve(mode, file, args, env): + """spawnve(mode, file, args, env) -> integer + +Execute file with arguments from args in a subprocess with the +specified environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return _spawnvef(mode, file, args, env, execve) + + # Note: spawnvp[e] is't currently supported on Windows + + def spawnvp(mode, file, args): + """spawnvp(mode, file, args) -> integer + +Execute file (which is looked for along $PATH) with arguments from +args in a subprocess. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return _spawnvef(mode, file, args, None, execvp) + + def spawnvpe(mode, file, args, env): + """spawnvpe(mode, file, args, env) -> integer + +Execute file (which is looked for along $PATH) with arguments from +args in a subprocess with the supplied environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return _spawnvef(mode, file, args, env, execvpe) + +if _exists("spawnv"): + # These aren't supplied by the basic Windows code + # but can be easily implemented in Python + + def spawnl(mode, file, *args): + """spawnl(mode, file, *args) -> integer + +Execute file with arguments from args in a subprocess. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return spawnv(mode, file, args) + + def spawnle(mode, file, *args): + """spawnle(mode, file, *args, env) -> integer + +Execute file with arguments from args in a subprocess with the +supplied environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + env = args[-1] + return spawnve(mode, file, args[:-1], env) + + + __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",]) + + +if _exists("spawnvp"): + # At the moment, Windows doesn't implement spawnvp[e], + # so it won't have spawnlp[e] either. + def spawnlp(mode, file, *args): + """spawnlp(mode, file, *args) -> integer + +Execute file (which is looked for along $PATH) with arguments from +args in a subprocess with the supplied environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return spawnvp(mode, file, args) + + def spawnlpe(mode, file, *args): + """spawnlpe(mode, file, *args, env) -> integer + +Execute file (which is looked for along $PATH) with arguments from +args in a subprocess with the supplied environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + env = args[-1] + return spawnvpe(mode, file, args[:-1], env) + + + __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",]) + + +# Supply popen2 etc. (for Unix) +if _exists("fork"): + if not _exists("popen2"): + def popen2(cmd, mode="t", bufsize=-1): + """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' + may be a sequence, in which case arguments will be passed directly to + the program without shell intervention (as with os.spawnv()). If 'cmd' + is a string it will be passed to the shell (as with os.system()). If + 'bufsize' is specified, it sets the buffer size for the I/O pipes. The + file objects (child_stdin, child_stdout) are returned.""" + import warnings + msg = "os.popen2 is deprecated. Use the subprocess module." + warnings.warn(msg, DeprecationWarning, stacklevel=2) + + import subprocess + PIPE = subprocess.PIPE + p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring), + bufsize=bufsize, stdin=PIPE, stdout=PIPE, + close_fds=True) + return p.stdin, p.stdout + __all__.append("popen2") + + if not _exists("popen3"): + def popen3(cmd, mode="t", bufsize=-1): + """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' + may be a sequence, in which case arguments will be passed directly to + the program without shell intervention (as with os.spawnv()). If 'cmd' + is a string it will be passed to the shell (as with os.system()). If + 'bufsize' is specified, it sets the buffer size for the I/O pipes. The + file objects (child_stdin, child_stdout, child_stderr) are returned.""" + import warnings + msg = "os.popen3 is deprecated. Use the subprocess module." + warnings.warn(msg, DeprecationWarning, stacklevel=2) + + import subprocess + PIPE = subprocess.PIPE + p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring), + bufsize=bufsize, stdin=PIPE, stdout=PIPE, + stderr=PIPE, close_fds=True) + return p.stdin, p.stdout, p.stderr + __all__.append("popen3") + + if not _exists("popen4"): + def popen4(cmd, mode="t", bufsize=-1): + """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' + may be a sequence, in which case arguments will be passed directly to + the program without shell intervention (as with os.spawnv()). If 'cmd' + is a string it will be passed to the shell (as with os.system()). If + 'bufsize' is specified, it sets the buffer size for the I/O pipes. The + file objects (child_stdin, child_stdout_stderr) are returned.""" + import warnings + msg = "os.popen4 is deprecated. Use the subprocess module." + warnings.warn(msg, DeprecationWarning, stacklevel=2) + + import subprocess + PIPE = subprocess.PIPE + p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring), + bufsize=bufsize, stdin=PIPE, stdout=PIPE, + stderr=subprocess.STDOUT, close_fds=True) + return p.stdin, p.stdout + __all__.append("popen4") + +import copy_reg as _copy_reg + +def _make_stat_result(tup, dict): + return stat_result(tup, dict) + +def _pickle_stat_result(sr): + (type, args) = sr.__reduce__() + return (_make_stat_result, args) + +try: + _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result) +except NameError: # stat_result may not exist + pass + +def _make_statvfs_result(tup, dict): + return statvfs_result(tup, dict) + +def _pickle_statvfs_result(sr): + (type, args) = sr.__reduce__() + return (_make_statvfs_result, args) + +try: + _copy_reg.pickle(statvfs_result, _pickle_statvfs_result, + _make_statvfs_result) +except NameError: # statvfs_result may not exist + pass + +if not _exists("urandom"): + def urandom(n): + """urandom(n) -> str + + Return a string of n random bytes suitable for cryptographic use. + + """ + try: + _urandomfd = open("/dev/urandom", O_RDONLY) + except (OSError, IOError): + raise NotImplementedError("/dev/urandom (or equivalent) not found") + try: + bs = b"" + while n > len(bs): + bs += read(_urandomfd, n - len(bs)) + finally: + close(_urandomfd) + return bs diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Lib/site.py b/AppPkg/Applications/Python/PyMod-2.7.2/Lib/site.py new file mode 100644 index 0000000000..de366e8dbf --- /dev/null +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Lib/site.py @@ -0,0 +1,536 @@ +"""Append module search paths for third-party packages to sys.path. + +**************************************************************** +* This module is automatically imported during initialization. * +**************************************************************** + +This is a UEFI-specific version of site.py. + +In earlier versions of Python (up to 1.5a3), scripts or modules that +needed to use site-specific modules would place ``import site'' +somewhere near the top of their code. Because of the automatic +import, this is no longer necessary (but code that does it still +works). + +This will append site-specific paths to the module search path. It +starts with sys.prefix and sys.exec_prefix (if different) and appends +lib/python/site-packages as well as lib/site-python. +The resulting directories, if they exist, are appended to sys.path, +and also inspected for path configuration files. + +A path configuration file is a file whose name has the form +.pth; its contents are additional directories (one per line) +to be added to sys.path. Non-existing directories (or +non-directories) are never added to sys.path; no directory is added to +sys.path more than once. Blank lines and lines beginning with +'#' are skipped. Lines starting with 'import' are executed. + +For example, suppose sys.prefix and sys.exec_prefix are set to +/Efi/StdLib and there is a directory /Efi/StdLib/lib/python2.7/site-packages +with three subdirectories, foo, bar and spam, and two path +configuration files, foo.pth and bar.pth. Assume foo.pth contains the +following: + + # foo package configuration + foo + bar + bletch + +and bar.pth contains: + + # bar package configuration + bar + +Then the following directories are added to sys.path, in this order: + + /Efi/StdLib/lib/python2.7/site-packages/bar + /Efi/StdLib/lib/python2.7/site-packages/foo + +Note that bletch is omitted because it doesn't exist; bar precedes foo +because bar.pth comes alphabetically before foo.pth; and spam is +omitted because it is not mentioned in either path configuration file. + +After these path manipulations, an attempt is made to import a module +named sitecustomize, which can perform arbitrary additional +site-specific customizations. If this import fails with an +ImportError exception, it is silently ignored. + +Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +""" + +import sys +import os +import __builtin__ +import traceback + +# Prefixes for site-packages; add additional prefixes like /usr/local here +PREFIXES = [sys.prefix, sys.exec_prefix] +# Enable per user site-packages directory +# set it to False to disable the feature or True to force the feature +ENABLE_USER_SITE = False + +# for distutils.commands.install +# These values are initialized by the getuserbase() and getusersitepackages() +# functions, through the main() function when Python starts. +USER_SITE = None +USER_BASE = None + + +def makepath(*paths): + dir = os.path.join(*paths) + try: + dir = os.path.abspath(dir) + except OSError: + pass + return dir, os.path.normcase(dir) + + +def abs__file__(): + """Set all module' __file__ attribute to an absolute path""" + for m in sys.modules.values(): + if hasattr(m, '__loader__'): + continue # don't mess with a PEP 302-supplied __file__ + try: + m.__file__ = os.path.abspath(m.__file__) + except (AttributeError, OSError): + pass + + +def removeduppaths(): + """ Remove duplicate entries from sys.path along with making them + absolute""" + # This ensures that the initial path provided by the interpreter contains + # only absolute pathnames, even if we're running from the build directory. + L = [] + known_paths = set() + for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in known_paths: + L.append(dir) + known_paths.add(dircase) + sys.path[:] = L + return known_paths + + +def _init_pathinfo(): + """Return a set containing all existing directory entries from sys.path""" + d = set() + for dir in sys.path: + try: + if os.path.isdir(dir): + dir, dircase = makepath(dir) + d.add(dircase) + except TypeError: + continue + return d + + +def addpackage(sitedir, name, known_paths): + """Process a .pth file within the site-packages directory: + For each line in the file, either combine it with sitedir to a path + and add that to known_paths, or execute it if it starts with 'import '. + """ + if known_paths is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + f = open(fullname, "rU") + except IOError: + return + with f: + for n, line in enumerate(f): + if line.startswith("#"): + continue + try: + if line.startswith(("import ", "import\t")): + exec line + continue + line = line.rstrip() + dir, dircase = makepath(sitedir, line) + if not dircase in known_paths and os.path.exists(dir): + sys.path.append(dir) + known_paths.add(dircase) + except Exception as err: + print >>sys.stderr, "Error processing line {:d} of {}:\n".format( + n+1, fullname) + for record in traceback.format_exception(*sys.exc_info()): + for line in record.splitlines(): + print >>sys.stderr, ' '+line + print >>sys.stderr, "\nRemainder of file ignored" + break + if reset: + known_paths = None + return known_paths + + +def addsitedir(sitedir, known_paths=None): + """Add 'sitedir' argument to sys.path if missing and handle .pth files in + 'sitedir'""" + if known_paths is None: + known_paths = _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in known_paths: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + dotpth = os.extsep + "pth" + names = [name for name in names if name.endswith(dotpth)] + for name in sorted(names): + addpackage(sitedir, name, known_paths) + if reset: + known_paths = None + return known_paths + + +def check_enableusersite(): + """Check if user site directory is safe for inclusion + + The function tests for the command line flag (including environment var), + process uid/gid equal to effective uid/gid. + + None: Disabled for security reasons + False: Disabled by user (command line option) + True: Safe and enabled + """ + if sys.flags.no_user_site: + return False + + if hasattr(os, "getuid") and hasattr(os, "geteuid"): + # check process uid == effective uid + if os.geteuid() != os.getuid(): + return None + if hasattr(os, "getgid") and hasattr(os, "getegid"): + # check process gid == effective gid + if os.getegid() != os.getgid(): + return None + + return True + +def getuserbase(): + """Returns the `user base` directory path. + + The `user base` directory can be used to store data. If the global + variable ``USER_BASE`` is not initialized yet, this function will also set + it. + """ + global USER_BASE + if USER_BASE is not None: + return USER_BASE + from sysconfig import get_config_var + USER_BASE = get_config_var('userbase') + return USER_BASE + +def getusersitepackages(): + """Returns the user-specific site-packages directory path. + + If the global variable ``USER_SITE`` is not initialized yet, this + function will also set it. + """ + global USER_SITE + user_base = getuserbase() # this will also set USER_BASE + + if USER_SITE is not None: + return USER_SITE + + from sysconfig import get_path + import os + + USER_SITE = get_path('purelib', '%s_user' % os.name) + return USER_SITE + +def addusersitepackages(known_paths): + """Add a per user site-package to sys.path + + Each user has its own python directory with site-packages in the + home directory. + """ + # get the per user site-package path + # this call will also make sure USER_BASE and USER_SITE are set + user_site = getusersitepackages() + + if ENABLE_USER_SITE and os.path.isdir(user_site): + addsitedir(user_site, known_paths) + return known_paths + +def getsitepackages(): + """Returns a list containing all global site-packages directories + (and possibly site-python). + + For each directory present in the global ``PREFIXES``, this function + will find its `site-packages` subdirectory depending on the system + environment, and will return a list of full paths. + """ + sitepackages = [] + seen = set() + + for prefix in PREFIXES: + if not prefix or prefix in seen: + continue + seen.add(prefix) + + sitepackages.append(os.path.join(prefix, "lib", + "python." + sys.version[0] + sys.version[2], + "site-packages")) + sitepackages.append(os.path.join(prefix, "lib", "site-python")) + return sitepackages + +def addsitepackages(known_paths): + """Add site-packages (and possibly site-python) to sys.path""" + for sitedir in getsitepackages(): + if os.path.isdir(sitedir): + addsitedir(sitedir, known_paths) + + return known_paths + +def setBEGINLIBPATH(): + """The UEFI port has optional extension modules that do double duty + as DLLs (even though they have .efi file extensions) for other extensions. + The library search path needs to be amended so these will be found + during module import. Use BEGINLIBPATH so that these are at the start + of the library search path. + + """ + dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") + libpath = os.environ['BEGINLIBPATH'].split(os.path.pathsep) + if libpath[-1]: + libpath.append(dllpath) + else: + libpath[-1] = dllpath + os.environ['BEGINLIBPATH'] = os.path.pathsep.join(libpath) + + +def setquit(): + """Define new builtins 'quit' and 'exit'. + + These are objects which make the interpreter exit when called. + The repr of each object contains a hint at how it works. + + """ + eof = 'Ctrl-D (i.e. EOF)' + + class Quitter(object): + def __init__(self, name): + self.name = name + def __repr__(self): + return 'Use %s() or %s to exit' % (self.name, eof) + def __call__(self, code=None): + # Shells like IDLE catch the SystemExit, but listen when their + # stdin wrapper is closed. + try: + sys.stdin.close() + except: + pass + raise SystemExit(code) + __builtin__.quit = Quitter('quit') + __builtin__.exit = Quitter('exit') + + +class _Printer(object): + """interactive prompt objects for printing the license text, a list of + contributors and the copyright notice.""" + + MAXLINES = 23 + + def __init__(self, name, data, files=(), dirs=()): + self.__name = name + self.__data = data + self.__files = files + self.__dirs = dirs + self.__lines = None + + def __setup(self): + if self.__lines: + return + data = None + for dir in self.__dirs: + for filename in self.__files: + filename = os.path.join(dir, filename) + try: + fp = file(filename, "rU") + data = fp.read() + fp.close() + break + except IOError: + pass + if data: + break + if not data: + data = self.__data + self.__lines = data.split('\n') + self.__linecnt = len(self.__lines) + + def __repr__(self): + self.__setup() + if len(self.__lines) <= self.MAXLINES: + return "\n".join(self.__lines) + else: + return "Type %s() to see the full %s text" % ((self.__name,)*2) + + def __call__(self): + self.__setup() + prompt = 'Hit Return for more, or q (and Return) to quit: ' + lineno = 0 + while 1: + try: + for i in range(lineno, lineno + self.MAXLINES): + print self.__lines[i] + except IndexError: + break + else: + lineno += self.MAXLINES + key = None + while key is None: + key = raw_input(prompt) + if key not in ('', 'q'): + key = None + if key == 'q': + break + +def setcopyright(): + """Set 'copyright' and 'credits' in __builtin__""" + __builtin__.copyright = _Printer("copyright", sys.copyright) + __builtin__.credits = _Printer("credits", """\ + Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands + for supporting Python development. See www.python.org for more information.""") + here = os.path.dirname(os.__file__) + __builtin__.license = _Printer( + "license", "See http://www.python.org/%.3s/license.html" % sys.version, + ["LICENSE.txt", "LICENSE"], + [os.path.join(here, os.pardir), here, os.curdir]) + + +class _Helper(object): + """Define the builtin 'help'. + This is a wrapper around pydoc.help (with a twist). + + """ + + def __repr__(self): + return "Type help() for interactive help, " \ + "or help(object) for help about object." + + def __call__(self, *args, **kwds): + import pydoc + return pydoc.help(*args, **kwds) + +def sethelper(): + __builtin__.help = _Helper() + +#### +# Keep around for future mbcs support. +#### +#def aliasmbcs(): +# """On Windows, some default encodings are not provided by Python, +# while they are always available as "mbcs" in each locale. Make +# them usable by aliasing to "mbcs" in such a case.""" +# if sys.platform == 'win32': +# import locale, codecs +# enc = locale.getdefaultlocale()[1] +# if enc.startswith('cp'): # "cp***" ? +# try: +# codecs.lookup(enc) +# except LookupError: +# import encodings +# encodings._cache[enc] = encodings._unknown +# encodings.aliases.aliases[enc] = 'mbcs' + +def setencoding(): + """Set the string encoding used by the Unicode implementation. The + default is 'ascii', but if you're willing to experiment, you can + change this.""" + encoding = "ascii" # Default value set by _PyUnicode_Init() + if 0: + # Enable to support locale aware default string encodings. + import locale + loc = locale.getdefaultlocale() + if loc[1]: + encoding = loc[1] + if 0: + # Enable to switch off string to Unicode coercion and implicit + # Unicode to string conversion. + encoding = "undefined" + if encoding != "ascii": + # On Non-Unicode builds this will raise an AttributeError... + sys.setdefaultencoding(encoding) # Needs Python Unicode build ! + + +def execsitecustomize(): + """Run custom site specific code, if available.""" + try: + import sitecustomize + except ImportError: + pass + except Exception: + if sys.flags.verbose: + sys.excepthook(*sys.exc_info()) + else: + print >>sys.stderr, \ + "'import sitecustomize' failed; use -v for traceback" + + +def execusercustomize(): + """Run custom user specific code, if available.""" + try: + import usercustomize + except ImportError: + pass + except Exception: + if sys.flags.verbose: + sys.excepthook(*sys.exc_info()) + else: + print>>sys.stderr, \ + "'import usercustomize' failed; use -v for traceback" + + +def main(): + abs__file__() + known_paths = removeduppaths() + setquit() + setcopyright() + sethelper() +# aliasmbcs() + setencoding() + execsitecustomize() + # Remove sys.setdefaultencoding() so that users cannot change the + # encoding after initialization. The test for presence is needed when + # this module is run as a script, because this code is executed twice. + if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding + +main() + +def _script(): + help = """\ + %s + + Path elements are normally separated by '%s'. + """ + print "sys.path = [" + for dir in sys.path: + print " %r," % (dir,) + print "]" + + import textwrap + print textwrap.dedent(help % (sys.argv[0], os.pathsep)) + sys.exit(0) + +if __name__ == '__main__': + _script() diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Modules/errnomodule.c b/AppPkg/Applications/Python/PyMod-2.7.2/Modules/errnomodule.c new file mode 100644 index 0000000000..a325389469 --- /dev/null +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Modules/errnomodule.c @@ -0,0 +1,845 @@ + +/* Errno module + + Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +*/ + +#include "Python.h" + +/* Windows socket errors (WSA*) */ +#ifdef MS_WINDOWS +#include +#endif + +/* + * Pull in the system error definitions + */ + +static PyMethodDef errno_methods[] = { + {NULL, NULL} +}; + +/* Helper function doing the dictionary inserting */ + +static void +_inscode(PyObject *d, PyObject *de, char *name, int code) +{ + PyObject *u = PyString_FromString(name); + PyObject *v = PyInt_FromLong((long) code); + + /* Don't bother checking for errors; they'll be caught at the end + * of the module initialization function by the caller of + * initerrno(). + */ + if (u && v) { + /* insert in modules dict */ + PyDict_SetItem(d, u, v); + /* insert in errorcode dict */ + PyDict_SetItem(de, v, u); + } + Py_XDECREF(u); + Py_XDECREF(v); +} + +PyDoc_STRVAR(errno__doc__, +"This module makes available standard errno system symbols.\n\ +\n\ +The value of each symbol is the corresponding integer value,\n\ +e.g., on most systems, errno.ENOENT equals the integer 2.\n\ +\n\ +The dictionary errno.errorcode maps numeric codes to symbol names,\n\ +e.g., errno.errorcode[2] could be the string 'ENOENT'.\n\ +\n\ +Symbols that are not relevant to the underlying system are not defined.\n\ +\n\ +To map error codes to error messages, use the function os.strerror(),\n\ +e.g. os.strerror(2) could return 'No such file or directory'."); + +PyMODINIT_FUNC +initerrno(void) +{ + PyObject *m, *d, *de; + m = Py_InitModule3("errno", errno_methods, errno__doc__); + if (m == NULL) + return; + d = PyModule_GetDict(m); + de = PyDict_New(); + if (!d || !de || PyDict_SetItemString(d, "errorcode", de) < 0) + return; + +/* Macro so I don't have to edit each and every line below... */ +#define inscode(d, ds, de, name, code, comment) _inscode(d, de, name, code) + + /* + * The names and comments are borrowed from linux/include/errno.h, + * which should be pretty all-inclusive + */ + +#ifdef ENODEV + inscode(d, ds, de, "ENODEV", ENODEV, "No such device"); +#endif +#ifdef ENOCSI + inscode(d, ds, de, "ENOCSI", ENOCSI, "No CSI structure available"); +#endif +#ifdef EHOSTUNREACH + inscode(d, ds, de, "EHOSTUNREACH", EHOSTUNREACH, "No route to host"); +#else +#ifdef WSAEHOSTUNREACH + inscode(d, ds, de, "EHOSTUNREACH", WSAEHOSTUNREACH, "No route to host"); +#endif +#endif +#ifdef ENOMSG + inscode(d, ds, de, "ENOMSG", ENOMSG, "No message of desired type"); +#endif +#ifdef EUCLEAN + inscode(d, ds, de, "EUCLEAN", EUCLEAN, "Structure needs cleaning"); +#endif +#ifdef EL2NSYNC + inscode(d, ds, de, "EL2NSYNC", EL2NSYNC, "Level 2 not synchronized"); +#endif +#ifdef EL2HLT + inscode(d, ds, de, "EL2HLT", EL2HLT, "Level 2 halted"); +#endif +#ifdef ENODATA + inscode(d, ds, de, "ENODATA", ENODATA, "No data available"); +#endif +#ifdef ENOTBLK + inscode(d, ds, de, "ENOTBLK", ENOTBLK, "Block device required"); +#endif +#ifdef ENOSYS + inscode(d, ds, de, "ENOSYS", ENOSYS, "Function not implemented"); +#endif +#ifdef EPIPE + inscode(d, ds, de, "EPIPE", EPIPE, "Broken pipe"); +#endif +#ifdef EINVAL + inscode(d, ds, de, "EINVAL", EINVAL, "Invalid argument"); +#else +#ifdef WSAEINVAL + inscode(d, ds, de, "EINVAL", WSAEINVAL, "Invalid argument"); +#endif +#endif +#ifdef EOVERFLOW + inscode(d, ds, de, "EOVERFLOW", EOVERFLOW, "Value too large for defined data type"); +#endif +#ifdef EADV + inscode(d, ds, de, "EADV", EADV, "Advertise error"); +#endif +#ifdef EINTR + inscode(d, ds, de, "EINTR", EINTR, "Interrupted system call"); +#else +#ifdef WSAEINTR + inscode(d, ds, de, "EINTR", WSAEINTR, "Interrupted system call"); +#endif +#endif +#ifdef EUSERS + inscode(d, ds, de, "EUSERS", EUSERS, "Too many users"); +#else +#ifdef WSAEUSERS + inscode(d, ds, de, "EUSERS", WSAEUSERS, "Too many users"); +#endif +#endif +#ifdef ENOTEMPTY + inscode(d, ds, de, "ENOTEMPTY", ENOTEMPTY, "Directory not empty"); +#else +#ifdef WSAENOTEMPTY + inscode(d, ds, de, "ENOTEMPTY", WSAENOTEMPTY, "Directory not empty"); +#endif +#endif +#ifdef ENOBUFS + inscode(d, ds, de, "ENOBUFS", ENOBUFS, "No buffer space available"); +#else +#ifdef WSAENOBUFS + inscode(d, ds, de, "ENOBUFS", WSAENOBUFS, "No buffer space available"); +#endif +#endif +#ifdef EPROTO + inscode(d, ds, de, "EPROTO", EPROTO, "Protocol error"); +#endif +#ifdef EREMOTE + inscode(d, ds, de, "EREMOTE", EREMOTE, "Object is remote"); +#else +#ifdef WSAEREMOTE + inscode(d, ds, de, "EREMOTE", WSAEREMOTE, "Object is remote"); +#endif +#endif +#ifdef ENAVAIL + inscode(d, ds, de, "ENAVAIL", ENAVAIL, "No XENIX semaphores available"); +#endif +#ifdef ECHILD + inscode(d, ds, de, "ECHILD", ECHILD, "No child processes"); +#endif +#ifdef ELOOP + inscode(d, ds, de, "ELOOP", ELOOP, "Too many symbolic links encountered"); +#else +#ifdef WSAELOOP + inscode(d, ds, de, "ELOOP", WSAELOOP, "Too many symbolic links encountered"); +#endif +#endif +#ifdef EXDEV + inscode(d, ds, de, "EXDEV", EXDEV, "Cross-device link"); +#endif +#ifdef E2BIG + inscode(d, ds, de, "E2BIG", E2BIG, "Arg list too long"); +#endif +#ifdef ESRCH + inscode(d, ds, de, "ESRCH", ESRCH, "No such process"); +#endif +#ifdef EMSGSIZE + inscode(d, ds, de, "EMSGSIZE", EMSGSIZE, "Message too long"); +#else +#ifdef WSAEMSGSIZE + inscode(d, ds, de, "EMSGSIZE", WSAEMSGSIZE, "Message too long"); +#endif +#endif +#ifdef EAFNOSUPPORT + inscode(d, ds, de, "EAFNOSUPPORT", EAFNOSUPPORT, "Address family not supported by protocol"); +#else +#ifdef WSAEAFNOSUPPORT + inscode(d, ds, de, "EAFNOSUPPORT", WSAEAFNOSUPPORT, "Address family not supported by protocol"); +#endif +#endif +#ifdef EBADR + inscode(d, ds, de, "EBADR", EBADR, "Invalid request descriptor"); +#endif +#ifdef EHOSTDOWN + inscode(d, ds, de, "EHOSTDOWN", EHOSTDOWN, "Host is down"); +#else +#ifdef WSAEHOSTDOWN + inscode(d, ds, de, "EHOSTDOWN", WSAEHOSTDOWN, "Host is down"); +#endif +#endif +#ifdef EPFNOSUPPORT + inscode(d, ds, de, "EPFNOSUPPORT", EPFNOSUPPORT, "Protocol family not supported"); +#else +#ifdef WSAEPFNOSUPPORT + inscode(d, ds, de, "EPFNOSUPPORT", WSAEPFNOSUPPORT, "Protocol family not supported"); +#endif +#endif +#ifdef ENOPROTOOPT + inscode(d, ds, de, "ENOPROTOOPT", ENOPROTOOPT, "Protocol not available"); +#else +#ifdef WSAENOPROTOOPT + inscode(d, ds, de, "ENOPROTOOPT", WSAENOPROTOOPT, "Protocol not available"); +#endif +#endif +#ifdef EBUSY + inscode(d, ds, de, "EBUSY", EBUSY, "Device or resource busy"); +#endif +#ifdef EWOULDBLOCK + inscode(d, ds, de, "EWOULDBLOCK", EWOULDBLOCK, "Operation would block"); +#else +#ifdef WSAEWOULDBLOCK + inscode(d, ds, de, "EWOULDBLOCK", WSAEWOULDBLOCK, "Operation would block"); +#endif +#endif +#ifdef EBADFD + inscode(d, ds, de, "EBADFD", EBADFD, "File descriptor in bad state"); +#endif +#ifdef EDOTDOT + inscode(d, ds, de, "EDOTDOT", EDOTDOT, "RFS specific error"); +#endif +#ifdef EISCONN + inscode(d, ds, de, "EISCONN", EISCONN, "Transport endpoint is already connected"); +#else +#ifdef WSAEISCONN + inscode(d, ds, de, "EISCONN", WSAEISCONN, "Transport endpoint is already connected"); +#endif +#endif +#ifdef ENOANO + inscode(d, ds, de, "ENOANO", ENOANO, "No anode"); +#endif +#ifdef ESHUTDOWN + inscode(d, ds, de, "ESHUTDOWN", ESHUTDOWN, "Cannot send after transport endpoint shutdown"); +#else +#ifdef WSAESHUTDOWN + inscode(d, ds, de, "ESHUTDOWN", WSAESHUTDOWN, "Cannot send after transport endpoint shutdown"); +#endif +#endif +#ifdef ECHRNG + inscode(d, ds, de, "ECHRNG", ECHRNG, "Channel number out of range"); +#endif +#ifdef ELIBBAD + inscode(d, ds, de, "ELIBBAD", ELIBBAD, "Accessing a corrupted shared library"); +#endif +#ifdef ENONET + inscode(d, ds, de, "ENONET", ENONET, "Machine is not on the network"); +#endif +#ifdef EBADE + inscode(d, ds, de, "EBADE", EBADE, "Invalid exchange"); +#endif +#ifdef EBADF + inscode(d, ds, de, "EBADF", EBADF, "Bad file number"); +#else +#ifdef WSAEBADF + inscode(d, ds, de, "EBADF", WSAEBADF, "Bad file number"); +#endif +#endif +#ifdef EMULTIHOP + inscode(d, ds, de, "EMULTIHOP", EMULTIHOP, "Multihop attempted"); +#endif +#ifdef EIO + inscode(d, ds, de, "EIO", EIO, "I/O error"); +#endif +#ifdef EUNATCH + inscode(d, ds, de, "EUNATCH", EUNATCH, "Protocol driver not attached"); +#endif +#ifdef EPROTOTYPE + inscode(d, ds, de, "EPROTOTYPE", EPROTOTYPE, "Protocol wrong type for socket"); +#else +#ifdef WSAEPROTOTYPE + inscode(d, ds, de, "EPROTOTYPE", WSAEPROTOTYPE, "Protocol wrong type for socket"); +#endif +#endif +#ifdef ENOSPC + inscode(d, ds, de, "ENOSPC", ENOSPC, "No space left on device"); +#endif +#ifdef ENOEXEC + inscode(d, ds, de, "ENOEXEC", ENOEXEC, "Exec format error"); +#endif +#ifdef EALREADY + inscode(d, ds, de, "EALREADY", EALREADY, "Operation already in progress"); +#else +#ifdef WSAEALREADY + inscode(d, ds, de, "EALREADY", WSAEALREADY, "Operation already in progress"); +#endif +#endif +#ifdef ENETDOWN + inscode(d, ds, de, "ENETDOWN", ENETDOWN, "Network is down"); +#else +#ifdef WSAENETDOWN + inscode(d, ds, de, "ENETDOWN", WSAENETDOWN, "Network is down"); +#endif +#endif +#ifdef ENOTNAM + inscode(d, ds, de, "ENOTNAM", ENOTNAM, "Not a XENIX named type file"); +#endif +#ifdef EACCES + inscode(d, ds, de, "EACCES", EACCES, "Permission denied"); +#else +#ifdef WSAEACCES + inscode(d, ds, de, "EACCES", WSAEACCES, "Permission denied"); +#endif +#endif +#ifdef ELNRNG + inscode(d, ds, de, "ELNRNG", ELNRNG, "Link number out of range"); +#endif +#ifdef EILSEQ + inscode(d, ds, de, "EILSEQ", EILSEQ, "Illegal byte sequence"); +#endif +#ifdef ENOTDIR + inscode(d, ds, de, "ENOTDIR", ENOTDIR, "Not a directory"); +#endif +#ifdef ENOTUNIQ + inscode(d, ds, de, "ENOTUNIQ", ENOTUNIQ, "Name not unique on network"); +#endif +#ifdef EPERM + inscode(d, ds, de, "EPERM", EPERM, "Operation not permitted"); +#endif +#ifdef EDOM + inscode(d, ds, de, "EDOM", EDOM, "Math argument out of domain of func"); +#endif +#ifdef EXFULL + inscode(d, ds, de, "EXFULL", EXFULL, "Exchange full"); +#endif +#ifdef ECONNREFUSED + inscode(d, ds, de, "ECONNREFUSED", ECONNREFUSED, "Connection refused"); +#else +#ifdef WSAECONNREFUSED + inscode(d, ds, de, "ECONNREFUSED", WSAECONNREFUSED, "Connection refused"); +#endif +#endif +#ifdef EISDIR + inscode(d, ds, de, "EISDIR", EISDIR, "Is a directory"); +#endif +#ifdef EPROTONOSUPPORT + inscode(d, ds, de, "EPROTONOSUPPORT", EPROTONOSUPPORT, "Protocol not supported"); +#else +#ifdef WSAEPROTONOSUPPORT + inscode(d, ds, de, "EPROTONOSUPPORT", WSAEPROTONOSUPPORT, "Protocol not supported"); +#endif +#endif +#ifdef EROFS + inscode(d, ds, de, "EROFS", EROFS, "Read-only file system"); +#endif +#ifdef EADDRNOTAVAIL + inscode(d, ds, de, "EADDRNOTAVAIL", EADDRNOTAVAIL, "Cannot assign requested address"); +#else +#ifdef WSAEADDRNOTAVAIL + inscode(d, ds, de, "EADDRNOTAVAIL", WSAEADDRNOTAVAIL, "Cannot assign requested address"); +#endif +#endif +#ifdef EIDRM + inscode(d, ds, de, "EIDRM", EIDRM, "Identifier removed"); +#endif +#ifdef ECOMM + inscode(d, ds, de, "ECOMM", ECOMM, "Communication error on send"); +#endif +#ifdef ESRMNT + inscode(d, ds, de, "ESRMNT", ESRMNT, "Srmount error"); +#endif +#ifdef EREMOTEIO + inscode(d, ds, de, "EREMOTEIO", EREMOTEIO, "Remote I/O error"); +#endif +#ifdef EL3RST + inscode(d, ds, de, "EL3RST", EL3RST, "Level 3 reset"); +#endif +#ifdef EBADMSG + inscode(d, ds, de, "EBADMSG", EBADMSG, "Not a data message"); +#endif +#ifdef ENFILE + inscode(d, ds, de, "ENFILE", ENFILE, "File table overflow"); +#endif +#ifdef ELIBMAX + inscode(d, ds, de, "ELIBMAX", ELIBMAX, "Attempting to link in too many shared libraries"); +#endif +#ifdef ESPIPE + inscode(d, ds, de, "ESPIPE", ESPIPE, "Illegal seek"); +#endif +#ifdef ENOLINK + inscode(d, ds, de, "ENOLINK", ENOLINK, "Link has been severed"); +#endif +#ifdef ENETRESET + inscode(d, ds, de, "ENETRESET", ENETRESET, "Network dropped connection because of reset"); +#else +#ifdef WSAENETRESET + inscode(d, ds, de, "ENETRESET", WSAENETRESET, "Network dropped connection because of reset"); +#endif +#endif +#ifdef ETIMEDOUT + inscode(d, ds, de, "ETIMEDOUT", ETIMEDOUT, "Connection timed out"); +#else +#ifdef WSAETIMEDOUT + inscode(d, ds, de, "ETIMEDOUT", WSAETIMEDOUT, "Connection timed out"); +#endif +#endif +#ifdef ENOENT + inscode(d, ds, de, "ENOENT", ENOENT, "No such file or directory"); +#endif +#ifdef EEXIST + inscode(d, ds, de, "EEXIST", EEXIST, "File exists"); +#endif +#ifdef EDQUOT + inscode(d, ds, de, "EDQUOT", EDQUOT, "Quota exceeded"); +#else +#ifdef WSAEDQUOT + inscode(d, ds, de, "EDQUOT", WSAEDQUOT, "Quota exceeded"); +#endif +#endif +#ifdef ENOSTR + inscode(d, ds, de, "ENOSTR", ENOSTR, "Device not a stream"); +#endif +#ifdef EBADSLT + inscode(d, ds, de, "EBADSLT", EBADSLT, "Invalid slot"); +#endif +#ifdef EBADRQC + inscode(d, ds, de, "EBADRQC", EBADRQC, "Invalid request code"); +#endif +#ifdef ELIBACC + inscode(d, ds, de, "ELIBACC", ELIBACC, "Can not access a needed shared library"); +#endif +#ifdef EFAULT + inscode(d, ds, de, "EFAULT", EFAULT, "Bad address"); +#else +#ifdef WSAEFAULT + inscode(d, ds, de, "EFAULT", WSAEFAULT, "Bad address"); +#endif +#endif +#ifdef EFBIG + inscode(d, ds, de, "EFBIG", EFBIG, "File too large"); +#endif +#ifdef EDEADLK + inscode(d, ds, de, "EDEADLK", EDEADLK, "Resource deadlock would occur"); +#endif +#ifdef ENOTCONN + inscode(d, ds, de, "ENOTCONN", ENOTCONN, "Transport endpoint is not connected"); +#else +#ifdef WSAENOTCONN + inscode(d, ds, de, "ENOTCONN", WSAENOTCONN, "Transport endpoint is not connected"); +#endif +#endif +#ifdef EDESTADDRREQ + inscode(d, ds, de, "EDESTADDRREQ", EDESTADDRREQ, "Destination address required"); +#else +#ifdef WSAEDESTADDRREQ + inscode(d, ds, de, "EDESTADDRREQ", WSAEDESTADDRREQ, "Destination address required"); +#endif +#endif +#ifdef ELIBSCN + inscode(d, ds, de, "ELIBSCN", ELIBSCN, ".lib section in a.out corrupted"); +#endif +#ifdef ENOLCK + inscode(d, ds, de, "ENOLCK", ENOLCK, "No record locks available"); +#endif +#ifdef EISNAM + inscode(d, ds, de, "EISNAM", EISNAM, "Is a named type file"); +#endif +#ifdef ECONNABORTED + inscode(d, ds, de, "ECONNABORTED", ECONNABORTED, "Software caused connection abort"); +#else +#ifdef WSAECONNABORTED + inscode(d, ds, de, "ECONNABORTED", WSAECONNABORTED, "Software caused connection abort"); +#endif +#endif +#ifdef ENETUNREACH + inscode(d, ds, de, "ENETUNREACH", ENETUNREACH, "Network is unreachable"); +#else +#ifdef WSAENETUNREACH + inscode(d, ds, de, "ENETUNREACH", WSAENETUNREACH, "Network is unreachable"); +#endif +#endif +#ifdef ESTALE + inscode(d, ds, de, "ESTALE", ESTALE, "Stale NFS file handle"); +#else +#ifdef WSAESTALE + inscode(d, ds, de, "ESTALE", WSAESTALE, "Stale NFS file handle"); +#endif +#endif +#ifdef ENOSR + inscode(d, ds, de, "ENOSR", ENOSR, "Out of streams resources"); +#endif +#ifdef ENOMEM + inscode(d, ds, de, "ENOMEM", ENOMEM, "Out of memory"); +#endif +#ifdef ENOTSOCK + inscode(d, ds, de, "ENOTSOCK", ENOTSOCK, "Socket operation on non-socket"); +#else +#ifdef WSAENOTSOCK + inscode(d, ds, de, "ENOTSOCK", WSAENOTSOCK, "Socket operation on non-socket"); +#endif +#endif +#ifdef ESTRPIPE + inscode(d, ds, de, "ESTRPIPE", ESTRPIPE, "Streams pipe error"); +#endif +#ifdef EMLINK + inscode(d, ds, de, "EMLINK", EMLINK, "Too many links"); +#endif +#ifdef ERANGE + inscode(d, ds, de, "ERANGE", ERANGE, "Math result not representable"); +#endif +#ifdef ELIBEXEC + inscode(d, ds, de, "ELIBEXEC", ELIBEXEC, "Cannot exec a shared library directly"); +#endif +#ifdef EL3HLT + inscode(d, ds, de, "EL3HLT", EL3HLT, "Level 3 halted"); +#endif +#ifdef ECONNRESET + inscode(d, ds, de, "ECONNRESET", ECONNRESET, "Connection reset by peer"); +#else +#ifdef WSAECONNRESET + inscode(d, ds, de, "ECONNRESET", WSAECONNRESET, "Connection reset by peer"); +#endif +#endif +#ifdef EADDRINUSE + inscode(d, ds, de, "EADDRINUSE", EADDRINUSE, "Address already in use"); +#else +#ifdef WSAEADDRINUSE + inscode(d, ds, de, "EADDRINUSE", WSAEADDRINUSE, "Address already in use"); +#endif +#endif +#ifdef EOPNOTSUPP + inscode(d, ds, de, "EOPNOTSUPP", EOPNOTSUPP, "Operation not supported on transport endpoint"); +#else +#ifdef WSAEOPNOTSUPP + inscode(d, ds, de, "EOPNOTSUPP", WSAEOPNOTSUPP, "Operation not supported on transport endpoint"); +#endif +#endif +#ifdef EREMCHG + inscode(d, ds, de, "EREMCHG", EREMCHG, "Remote address changed"); +#endif +#ifdef EAGAIN + inscode(d, ds, de, "EAGAIN", EAGAIN, "Try again"); +#endif +#ifdef ENAMETOOLONG + inscode(d, ds, de, "ENAMETOOLONG", ENAMETOOLONG, "File name too long"); +#else +#ifdef WSAENAMETOOLONG + inscode(d, ds, de, "ENAMETOOLONG", WSAENAMETOOLONG, "File name too long"); +#endif +#endif +#ifdef ENOTTY + inscode(d, ds, de, "ENOTTY", ENOTTY, "Not a typewriter"); +#endif +#ifdef ERESTART + inscode(d, ds, de, "ERESTART", ERESTART, "Interrupted system call should be restarted"); +#endif +#ifdef ESOCKTNOSUPPORT + inscode(d, ds, de, "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, "Socket type not supported"); +#else +#ifdef WSAESOCKTNOSUPPORT + inscode(d, ds, de, "ESOCKTNOSUPPORT", WSAESOCKTNOSUPPORT, "Socket type not supported"); +#endif +#endif +#ifdef ETIME + inscode(d, ds, de, "ETIME", ETIME, "Timer expired"); +#endif +#ifdef EBFONT + inscode(d, ds, de, "EBFONT", EBFONT, "Bad font file format"); +#endif +#ifdef EDEADLOCK + inscode(d, ds, de, "EDEADLOCK", EDEADLOCK, "Error EDEADLOCK"); +#endif +#ifdef ETOOMANYREFS + inscode(d, ds, de, "ETOOMANYREFS", ETOOMANYREFS, "Too many references: cannot splice"); +#else +#ifdef WSAETOOMANYREFS + inscode(d, ds, de, "ETOOMANYREFS", WSAETOOMANYREFS, "Too many references: cannot splice"); +#endif +#endif +#ifdef EMFILE + inscode(d, ds, de, "EMFILE", EMFILE, "Too many open files"); +#else +#ifdef WSAEMFILE + inscode(d, ds, de, "EMFILE", WSAEMFILE, "Too many open files"); +#endif +#endif +#ifdef ETXTBSY + inscode(d, ds, de, "ETXTBSY", ETXTBSY, "Text file busy"); +#endif +#ifdef EINPROGRESS + inscode(d, ds, de, "EINPROGRESS", EINPROGRESS, "Operation now in progress"); +#else +#ifdef WSAEINPROGRESS + inscode(d, ds, de, "EINPROGRESS", WSAEINPROGRESS, "Operation now in progress"); +#endif +#endif +#ifdef ENXIO + inscode(d, ds, de, "ENXIO", ENXIO, "No such device or address"); +#endif +#ifdef ENOPKG + inscode(d, ds, de, "ENOPKG", ENOPKG, "Package not installed"); +#endif +#ifdef WSASY + inscode(d, ds, de, "WSASY", WSASY, "Error WSASY"); +#endif +#ifdef WSAEHOSTDOWN + inscode(d, ds, de, "WSAEHOSTDOWN", WSAEHOSTDOWN, "Host is down"); +#endif +#ifdef WSAENETDOWN + inscode(d, ds, de, "WSAENETDOWN", WSAENETDOWN, "Network is down"); +#endif +#ifdef WSAENOTSOCK + inscode(d, ds, de, "WSAENOTSOCK", WSAENOTSOCK, "Socket operation on non-socket"); +#endif +#ifdef WSAEHOSTUNREACH + inscode(d, ds, de, "WSAEHOSTUNREACH", WSAEHOSTUNREACH, "No route to host"); +#endif +#ifdef WSAELOOP + inscode(d, ds, de, "WSAELOOP", WSAELOOP, "Too many symbolic links encountered"); +#endif +#ifdef WSAEMFILE + inscode(d, ds, de, "WSAEMFILE", WSAEMFILE, "Too many open files"); +#endif +#ifdef WSAESTALE + inscode(d, ds, de, "WSAESTALE", WSAESTALE, "Stale NFS file handle"); +#endif +#ifdef WSAVERNOTSUPPORTED + inscode(d, ds, de, "WSAVERNOTSUPPORTED", WSAVERNOTSUPPORTED, "Error WSAVERNOTSUPPORTED"); +#endif +#ifdef WSAENETUNREACH + inscode(d, ds, de, "WSAENETUNREACH", WSAENETUNREACH, "Network is unreachable"); +#endif +#ifdef WSAEPROCLIM + inscode(d, ds, de, "WSAEPROCLIM", WSAEPROCLIM, "Error WSAEPROCLIM"); +#endif +#ifdef WSAEFAULT + inscode(d, ds, de, "WSAEFAULT", WSAEFAULT, "Bad address"); +#endif +#ifdef WSANOTINITIALISED + inscode(d, ds, de, "WSANOTINITIALISED", WSANOTINITIALISED, "Error WSANOTINITIALISED"); +#endif +#ifdef WSAEUSERS + inscode(d, ds, de, "WSAEUSERS", WSAEUSERS, "Too many users"); +#endif +#ifdef WSAMAKEASYNCREPL + inscode(d, ds, de, "WSAMAKEASYNCREPL", WSAMAKEASYNCREPL, "Error WSAMAKEASYNCREPL"); +#endif +#ifdef WSAENOPROTOOPT + inscode(d, ds, de, "WSAENOPROTOOPT", WSAENOPROTOOPT, "Protocol not available"); +#endif +#ifdef WSAECONNABORTED + inscode(d, ds, de, "WSAECONNABORTED", WSAECONNABORTED, "Software caused connection abort"); +#endif +#ifdef WSAENAMETOOLONG + inscode(d, ds, de, "WSAENAMETOOLONG", WSAENAMETOOLONG, "File name too long"); +#endif +#ifdef WSAENOTEMPTY + inscode(d, ds, de, "WSAENOTEMPTY", WSAENOTEMPTY, "Directory not empty"); +#endif +#ifdef WSAESHUTDOWN + inscode(d, ds, de, "WSAESHUTDOWN", WSAESHUTDOWN, "Cannot send after transport endpoint shutdown"); +#endif +#ifdef WSAEAFNOSUPPORT + inscode(d, ds, de, "WSAEAFNOSUPPORT", WSAEAFNOSUPPORT, "Address family not supported by protocol"); +#endif +#ifdef WSAETOOMANYREFS + inscode(d, ds, de, "WSAETOOMANYREFS", WSAETOOMANYREFS, "Too many references: cannot splice"); +#endif +#ifdef WSAEACCES + inscode(d, ds, de, "WSAEACCES", WSAEACCES, "Permission denied"); +#endif +#ifdef WSATR + inscode(d, ds, de, "WSATR", WSATR, "Error WSATR"); +#endif +#ifdef WSABASEERR + inscode(d, ds, de, "WSABASEERR", WSABASEERR, "Error WSABASEERR"); +#endif +#ifdef WSADESCRIPTIO + inscode(d, ds, de, "WSADESCRIPTIO", WSADESCRIPTIO, "Error WSADESCRIPTIO"); +#endif +#ifdef WSAEMSGSIZE + inscode(d, ds, de, "WSAEMSGSIZE", WSAEMSGSIZE, "Message too long"); +#endif +#ifdef WSAEBADF + inscode(d, ds, de, "WSAEBADF", WSAEBADF, "Bad file number"); +#endif +#ifdef WSAECONNRESET + inscode(d, ds, de, "WSAECONNRESET", WSAECONNRESET, "Connection reset by peer"); +#endif +#ifdef WSAGETSELECTERRO + inscode(d, ds, de, "WSAGETSELECTERRO", WSAGETSELECTERRO, "Error WSAGETSELECTERRO"); +#endif +#ifdef WSAETIMEDOUT + inscode(d, ds, de, "WSAETIMEDOUT", WSAETIMEDOUT, "Connection timed out"); +#endif +#ifdef WSAENOBUFS + inscode(d, ds, de, "WSAENOBUFS", WSAENOBUFS, "No buffer space available"); +#endif +#ifdef WSAEDISCON + inscode(d, ds, de, "WSAEDISCON", WSAEDISCON, "Error WSAEDISCON"); +#endif +#ifdef WSAEINTR + inscode(d, ds, de, "WSAEINTR", WSAEINTR, "Interrupted system call"); +#endif +#ifdef WSAEPROTOTYPE + inscode(d, ds, de, "WSAEPROTOTYPE", WSAEPROTOTYPE, "Protocol wrong type for socket"); +#endif +#ifdef WSAHOS + inscode(d, ds, de, "WSAHOS", WSAHOS, "Error WSAHOS"); +#endif +#ifdef WSAEADDRINUSE + inscode(d, ds, de, "WSAEADDRINUSE", WSAEADDRINUSE, "Address already in use"); +#endif +#ifdef WSAEADDRNOTAVAIL + inscode(d, ds, de, "WSAEADDRNOTAVAIL", WSAEADDRNOTAVAIL, "Cannot assign requested address"); +#endif +#ifdef WSAEALREADY + inscode(d, ds, de, "WSAEALREADY", WSAEALREADY, "Operation already in progress"); +#endif +#ifdef WSAEPROTONOSUPPORT + inscode(d, ds, de, "WSAEPROTONOSUPPORT", WSAEPROTONOSUPPORT, "Protocol not supported"); +#endif +#ifdef WSASYSNOTREADY + inscode(d, ds, de, "WSASYSNOTREADY", WSASYSNOTREADY, "Error WSASYSNOTREADY"); +#endif +#ifdef WSAEWOULDBLOCK + inscode(d, ds, de, "WSAEWOULDBLOCK", WSAEWOULDBLOCK, "Operation would block"); +#endif +#ifdef WSAEPFNOSUPPORT + inscode(d, ds, de, "WSAEPFNOSUPPORT", WSAEPFNOSUPPORT, "Protocol family not supported"); +#endif +#ifdef WSAEOPNOTSUPP + inscode(d, ds, de, "WSAEOPNOTSUPP", WSAEOPNOTSUPP, "Operation not supported on transport endpoint"); +#endif +#ifdef WSAEISCONN + inscode(d, ds, de, "WSAEISCONN", WSAEISCONN, "Transport endpoint is already connected"); +#endif +#ifdef WSAEDQUOT + inscode(d, ds, de, "WSAEDQUOT", WSAEDQUOT, "Quota exceeded"); +#endif +#ifdef WSAENOTCONN + inscode(d, ds, de, "WSAENOTCONN", WSAENOTCONN, "Transport endpoint is not connected"); +#endif +#ifdef WSAEREMOTE + inscode(d, ds, de, "WSAEREMOTE", WSAEREMOTE, "Object is remote"); +#endif +#ifdef WSAEINVAL + inscode(d, ds, de, "WSAEINVAL", WSAEINVAL, "Invalid argument"); +#endif +#ifdef WSAEINPROGRESS + inscode(d, ds, de, "WSAEINPROGRESS", WSAEINPROGRESS, "Operation now in progress"); +#endif +#ifdef WSAGETSELECTEVEN + inscode(d, ds, de, "WSAGETSELECTEVEN", WSAGETSELECTEVEN, "Error WSAGETSELECTEVEN"); +#endif +#ifdef WSAESOCKTNOSUPPORT + inscode(d, ds, de, "WSAESOCKTNOSUPPORT", WSAESOCKTNOSUPPORT, "Socket type not supported"); +#endif +#ifdef WSAGETASYNCERRO + inscode(d, ds, de, "WSAGETASYNCERRO", WSAGETASYNCERRO, "Error WSAGETASYNCERRO"); +#endif +#ifdef WSAMAKESELECTREPL + inscode(d, ds, de, "WSAMAKESELECTREPL", WSAMAKESELECTREPL, "Error WSAMAKESELECTREPL"); +#endif +#ifdef WSAGETASYNCBUFLE + inscode(d, ds, de, "WSAGETASYNCBUFLE", WSAGETASYNCBUFLE, "Error WSAGETASYNCBUFLE"); +#endif +#ifdef WSAEDESTADDRREQ + inscode(d, ds, de, "WSAEDESTADDRREQ", WSAEDESTADDRREQ, "Destination address required"); +#endif +#ifdef WSAECONNREFUSED + inscode(d, ds, de, "WSAECONNREFUSED", WSAECONNREFUSED, "Connection refused"); +#endif +#ifdef WSAENETRESET + inscode(d, ds, de, "WSAENETRESET", WSAENETRESET, "Network dropped connection because of reset"); +#endif +#ifdef WSAN + inscode(d, ds, de, "WSAN", WSAN, "Error WSAN"); +#endif + +/* These symbols are added for EDK II support. */ +#ifdef EMINERRORVAL + inscode(d, ds, de, "EMINERRORVAL", EMINERRORVAL, "Lowest valid error value"); +#endif +#ifdef ENOTSUP + inscode(d, ds, de, "ENOTSUP", ENOTSUP, "Operation not supported"); +#endif +#ifdef EBADRPC + inscode(d, ds, de, "EBADRPC", EBADRPC, "RPC struct is bad"); +#endif +#ifdef ERPCMISMATCH + inscode(d, ds, de, "ERPCMISMATCH", ERPCMISMATCH, "RPC version wrong"); +#endif +#ifdef EPROGUNAVAIL + inscode(d, ds, de, "EPROGUNAVAIL", EPROGUNAVAIL, "RPC prog. not avail"); +#endif +#ifdef EPROGMISMATCH + inscode(d, ds, de, "EPROGMISMATCH", EPROGMISMATCH, "Program version wrong"); +#endif +#ifdef EPROCUNAVAIL + inscode(d, ds, de, "EPROCUNAVAIL", EPROCUNAVAIL, "Bad procedure for program"); +#endif +#ifdef EFTYPE + inscode(d, ds, de, "EFTYPE", EFTYPE, "Inappropriate file type or format"); +#endif +#ifdef EAUTH + inscode(d, ds, de, "EAUTH", EAUTH, "Authentication error"); +#endif +#ifdef ENEEDAUTH + inscode(d, ds, de, "ENEEDAUTH", ENEEDAUTH, "Need authenticator"); +#endif +#ifdef ECANCELED + inscode(d, ds, de, "ECANCELED", ECANCELED, "Operation canceled"); +#endif +#ifdef ENOATTR + inscode(d, ds, de, "ENOATTR", ENOATTR, "Attribute not found"); +#endif +#ifdef EDOOFUS + inscode(d, ds, de, "EDOOFUS", EDOOFUS, "Programming Error"); +#endif +#ifdef EBUFSIZE + inscode(d, ds, de, "EBUFSIZE", EBUFSIZE, "Buffer too small to hold result"); +#endif +#ifdef EMAXERRORVAL + inscode(d, ds, de, "EMAXERRORVAL", EMAXERRORVAL, "One more than the highest defined error value"); +#endif + + Py_DECREF(de); +} diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Modules/selectmodule.c b/AppPkg/Applications/Python/PyMod-2.7.2/Modules/selectmodule.c new file mode 100644 index 0000000000..d1fe57c145 --- /dev/null +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Modules/selectmodule.c @@ -0,0 +1,1912 @@ +/* select - Module containing unix select(2) call. + Under Unix, the file descriptors are small integers. + Under Win32, select only exists for sockets, and sockets may + have any value except INVALID_SOCKET. + Under BeOS, we suffer the same dichotomy as Win32; sockets can be anything + >= 0. +*/ + +#include "Python.h" +#include + +#ifdef __APPLE__ + /* Perform runtime testing for a broken poll on OSX to make it easier + * to use the same binary on multiple releases of the OS. + */ +#undef HAVE_BROKEN_POLL +#endif + +/* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined. + 64 is too small (too many people have bumped into that limit). + Here we boost it. + Users who want even more than the boosted limit should #define + FD_SETSIZE higher before this; e.g., via compiler /D switch. +*/ +#if defined(MS_WINDOWS) && !defined(FD_SETSIZE) +#define FD_SETSIZE 512 +#endif + +#if defined(HAVE_POLL_H) +#include +#elif defined(HAVE_SYS_POLL_H) +#include +#endif + +#ifdef __sgi +/* This is missing from unistd.h */ +extern void bzero(void *, int); +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#if defined(PYOS_OS2) && !defined(PYCC_GCC) +#include +#include +#endif + +#ifdef MS_WINDOWS +# include +#else +# define SOCKET int +# ifdef __BEOS__ +# include +# elif defined(__VMS) +# include +# endif +#endif + +static PyObject *SelectError; + +/* list of Python objects and their file descriptor */ +typedef struct { + PyObject *obj; /* owned reference */ + SOCKET fd; + int sentinel; /* -1 == sentinel */ +} pylist; + +static void +reap_obj(pylist fd2obj[FD_SETSIZE + 1]) +{ + int i; + for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) { + Py_XDECREF(fd2obj[i].obj); + fd2obj[i].obj = NULL; + } + fd2obj[0].sentinel = -1; +} + + +/* returns -1 and sets the Python exception if an error occurred, otherwise + returns a number >= 0 +*/ +static int +seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) +{ + int i; + int max = -1; + int index = 0; + int len = -1; + PyObject* fast_seq = NULL; + PyObject* o = NULL; + + fd2obj[0].obj = (PyObject*)0; /* set list to zero size */ + FD_ZERO(set); + + fast_seq = PySequence_Fast(seq, "arguments 1-3 must be sequences"); + if (!fast_seq) + return -1; + + len = PySequence_Fast_GET_SIZE(fast_seq); + + for (i = 0; i < len; i++) { + SOCKET v; + + /* any intervening fileno() calls could decr this refcnt */ + if (!(o = PySequence_Fast_GET_ITEM(fast_seq, i))) + return -1; + + Py_INCREF(o); + v = PyObject_AsFileDescriptor( o ); + if (v == -1) goto finally; + +#if defined(_MSC_VER) && !defined(UEFI_ENV) + max = 0; /* not used for Win32 */ +#else /* !_MSC_VER */ + if (v < 0 || v >= FD_SETSIZE) { + PyErr_SetString(PyExc_ValueError, + "filedescriptor out of range in select()"); + goto finally; + } + if (v > max) + max = v; +#endif /* _MSC_VER */ + FD_SET(v, set); + + /* add object and its file descriptor to the list */ + if (index >= FD_SETSIZE) { + PyErr_SetString(PyExc_ValueError, + "too many file descriptors in select()"); + goto finally; + } + fd2obj[index].obj = o; + fd2obj[index].fd = v; + fd2obj[index].sentinel = 0; + fd2obj[++index].sentinel = -1; + } + Py_DECREF(fast_seq); + return max+1; + + finally: + Py_XDECREF(o); + Py_DECREF(fast_seq); + return -1; +} + +/* returns NULL and sets the Python exception if an error occurred */ +static PyObject * +set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) +{ + int i, j, count=0; + PyObject *list, *o; + SOCKET fd; + + for (j = 0; fd2obj[j].sentinel >= 0; j++) { + if (FD_ISSET(fd2obj[j].fd, set)) + count++; + } + list = PyList_New(count); + if (!list) + return NULL; + + i = 0; + for (j = 0; fd2obj[j].sentinel >= 0; j++) { + fd = fd2obj[j].fd; + if (FD_ISSET(fd, set)) { +#if !defined(_MSC_VER) || defined(UEFI_ENV) + if (fd > FD_SETSIZE) { + PyErr_SetString(PyExc_SystemError, + "filedescriptor out of range returned in select()"); + goto finally; + } +#endif + o = fd2obj[j].obj; + fd2obj[j].obj = NULL; + /* transfer ownership */ + if (PyList_SetItem(list, i, o) < 0) + goto finally; + + i++; + } + } + return list; + finally: + Py_DECREF(list); + return NULL; +} + +#undef SELECT_USES_HEAP +#if FD_SETSIZE > 1024 +#define SELECT_USES_HEAP +#endif /* FD_SETSIZE > 1024 */ + +static PyObject * +select_select(PyObject *self, PyObject *args) +{ +#ifdef SELECT_USES_HEAP + pylist *rfd2obj, *wfd2obj, *efd2obj; +#else /* !SELECT_USES_HEAP */ + /* XXX: All this should probably be implemented as follows: + * - find the highest descriptor we're interested in + * - add one + * - that's the size + * See: Stevens, APitUE, $12.5.1 + */ + pylist rfd2obj[FD_SETSIZE + 1]; + pylist wfd2obj[FD_SETSIZE + 1]; + pylist efd2obj[FD_SETSIZE + 1]; +#endif /* SELECT_USES_HEAP */ + PyObject *ifdlist, *ofdlist, *efdlist; + PyObject *ret = NULL; + PyObject *tout = Py_None; + fd_set ifdset, ofdset, efdset; + double timeout; + struct timeval tv, *tvp; + long seconds; + int imax, omax, emax, max; + int n; + + /* convert arguments */ + if (!PyArg_UnpackTuple(args, "select", 3, 4, + &ifdlist, &ofdlist, &efdlist, &tout)) + return NULL; + + if (tout == Py_None) + tvp = (struct timeval *)0; + else if (!PyNumber_Check(tout)) { + PyErr_SetString(PyExc_TypeError, + "timeout must be a float or None"); + return NULL; + } + else { + timeout = PyFloat_AsDouble(tout); + if (timeout == -1 && PyErr_Occurred()) + return NULL; + if (timeout > (double)LONG_MAX) { + PyErr_SetString(PyExc_OverflowError, + "timeout period too long"); + return NULL; + } + seconds = (long)timeout; + timeout = timeout - (double)seconds; + tv.tv_sec = seconds; + tv.tv_usec = (long)(timeout * 1E6); + tvp = &tv; + } + + +#ifdef SELECT_USES_HEAP + /* Allocate memory for the lists */ + rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); + wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); + efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); + if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) { + if (rfd2obj) PyMem_DEL(rfd2obj); + if (wfd2obj) PyMem_DEL(wfd2obj); + if (efd2obj) PyMem_DEL(efd2obj); + return PyErr_NoMemory(); + } +#endif /* SELECT_USES_HEAP */ + /* Convert sequences to fd_sets, and get maximum fd number + * propagates the Python exception set in seq2set() + */ + rfd2obj[0].sentinel = -1; + wfd2obj[0].sentinel = -1; + efd2obj[0].sentinel = -1; + if ((imax=seq2set(ifdlist, &ifdset, rfd2obj)) < 0) + goto finally; + if ((omax=seq2set(ofdlist, &ofdset, wfd2obj)) < 0) + goto finally; + if ((emax=seq2set(efdlist, &efdset, efd2obj)) < 0) + goto finally; + max = imax; + if (omax > max) max = omax; + if (emax > max) max = emax; + + Py_BEGIN_ALLOW_THREADS + n = select(max, &ifdset, &ofdset, &efdset, tvp); + Py_END_ALLOW_THREADS + +#ifdef MS_WINDOWS + if (n == SOCKET_ERROR) { + PyErr_SetExcFromWindowsErr(SelectError, WSAGetLastError()); + } +#else + if (n < 0) { + PyErr_SetFromErrno(SelectError); + } +#endif + else { + /* any of these three calls can raise an exception. it's more + convenient to test for this after all three calls... but + is that acceptable? + */ + ifdlist = set2list(&ifdset, rfd2obj); + ofdlist = set2list(&ofdset, wfd2obj); + efdlist = set2list(&efdset, efd2obj); + if (PyErr_Occurred()) + ret = NULL; + else + ret = PyTuple_Pack(3, ifdlist, ofdlist, efdlist); + + Py_DECREF(ifdlist); + Py_DECREF(ofdlist); + Py_DECREF(efdlist); + } + + finally: + reap_obj(rfd2obj); + reap_obj(wfd2obj); + reap_obj(efd2obj); +#ifdef SELECT_USES_HEAP + PyMem_DEL(rfd2obj); + PyMem_DEL(wfd2obj); + PyMem_DEL(efd2obj); +#endif /* SELECT_USES_HEAP */ + return ret; +} + +#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) +/* + * poll() support + */ + +typedef struct { + PyObject_HEAD + PyObject *dict; + int ufd_uptodate; + int ufd_len; + struct pollfd *ufds; +} pollObject; + +static PyTypeObject poll_Type; + +/* Update the malloc'ed array of pollfds to match the dictionary + contained within a pollObject. Return 1 on success, 0 on an error. +*/ + +static int +update_ufd_array(pollObject *self) +{ + Py_ssize_t i, pos; + PyObject *key, *value; + struct pollfd *old_ufds = self->ufds; + + self->ufd_len = PyDict_Size(self->dict); + PyMem_RESIZE(self->ufds, struct pollfd, self->ufd_len); + if (self->ufds == NULL) { + self->ufds = old_ufds; + PyErr_NoMemory(); + return 0; + } + + i = pos = 0; + while (PyDict_Next(self->dict, &pos, &key, &value)) { + self->ufds[i].fd = PyInt_AsLong(key); + self->ufds[i].events = (short)PyInt_AsLong(value); + i++; + } + self->ufd_uptodate = 1; + return 1; +} + +PyDoc_STRVAR(poll_register_doc, +"register(fd [, eventmask] ) -> None\n\n\ +Register a file descriptor with the polling object.\n\ +fd -- either an integer, or an object with a fileno() method returning an\n\ + int.\n\ +events -- an optional bitmask describing the type of events to check for"); + +static PyObject * +poll_register(pollObject *self, PyObject *args) +{ + PyObject *o, *key, *value; + int fd, events = POLLIN | POLLPRI | POLLOUT; + int err; + + if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) { + return NULL; + } + + fd = PyObject_AsFileDescriptor(o); + if (fd == -1) return NULL; + + /* Add entry to the internal dictionary: the key is the + file descriptor, and the value is the event mask. */ + key = PyInt_FromLong(fd); + if (key == NULL) + return NULL; + value = PyInt_FromLong(events); + if (value == NULL) { + Py_DECREF(key); + return NULL; + } + err = PyDict_SetItem(self->dict, key, value); + Py_DECREF(key); + Py_DECREF(value); + if (err < 0) + return NULL; + + self->ufd_uptodate = 0; + + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(poll_modify_doc, +"modify(fd, eventmask) -> None\n\n\ +Modify an already registered file descriptor.\n\ +fd -- either an integer, or an object with a fileno() method returning an\n\ + int.\n\ +events -- an optional bitmask describing the type of events to check for"); + +static PyObject * +poll_modify(pollObject *self, PyObject *args) +{ + PyObject *o, *key, *value; + int fd, events; + int err; + + if (!PyArg_ParseTuple(args, "Oi:modify", &o, &events)) { + return NULL; + } + + fd = PyObject_AsFileDescriptor(o); + if (fd == -1) return NULL; + + /* Modify registered fd */ + key = PyInt_FromLong(fd); + if (key == NULL) + return NULL; + if (PyDict_GetItem(self->dict, key) == NULL) { + errno = ENOENT; + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + value = PyInt_FromLong(events); + if (value == NULL) { + Py_DECREF(key); + return NULL; + } + err = PyDict_SetItem(self->dict, key, value); + Py_DECREF(key); + Py_DECREF(value); + if (err < 0) + return NULL; + + self->ufd_uptodate = 0; + + Py_INCREF(Py_None); + return Py_None; +} + + +PyDoc_STRVAR(poll_unregister_doc, +"unregister(fd) -> None\n\n\ +Remove a file descriptor being tracked by the polling object."); + +static PyObject * +poll_unregister(pollObject *self, PyObject *o) +{ + PyObject *key; + int fd; + + fd = PyObject_AsFileDescriptor( o ); + if (fd == -1) + return NULL; + + /* Check whether the fd is already in the array */ + key = PyInt_FromLong(fd); + if (key == NULL) + return NULL; + + if (PyDict_DelItem(self->dict, key) == -1) { + Py_DECREF(key); + /* This will simply raise the KeyError set by PyDict_DelItem + if the file descriptor isn't registered. */ + return NULL; + } + + Py_DECREF(key); + self->ufd_uptodate = 0; + + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(poll_poll_doc, +"poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\ +Polls the set of registered file descriptors, returning a list containing \n\ +any descriptors that have events or errors to report."); + +static PyObject * +poll_poll(pollObject *self, PyObject *args) +{ + PyObject *result_list = NULL, *tout = NULL; + int timeout = 0, poll_result, i, j; + PyObject *value = NULL, *num = NULL; + + if (!PyArg_UnpackTuple(args, "poll", 0, 1, &tout)) { + return NULL; + } + + /* Check values for timeout */ + if (tout == NULL || tout == Py_None) + timeout = -1; + else if (!PyNumber_Check(tout)) { + PyErr_SetString(PyExc_TypeError, + "timeout must be an integer or None"); + return NULL; + } + else { + tout = PyNumber_Int(tout); + if (!tout) + return NULL; + timeout = PyInt_AsLong(tout); + Py_DECREF(tout); + if (timeout == -1 && PyErr_Occurred()) + return NULL; + } + + /* Ensure the ufd array is up to date */ + if (!self->ufd_uptodate) + if (update_ufd_array(self) == 0) + return NULL; + + /* call poll() */ + Py_BEGIN_ALLOW_THREADS + poll_result = poll(self->ufds, self->ufd_len, timeout); + Py_END_ALLOW_THREADS + + if (poll_result < 0) { + PyErr_SetFromErrno(SelectError); + return NULL; + } + + /* build the result list */ + + result_list = PyList_New(poll_result); + if (!result_list) + return NULL; + else { + for (i = 0, j = 0; j < poll_result; j++) { + /* skip to the next fired descriptor */ + while (!self->ufds[i].revents) { + i++; + } + /* if we hit a NULL return, set value to NULL + and break out of loop; code at end will + clean up result_list */ + value = PyTuple_New(2); + if (value == NULL) + goto error; + num = PyInt_FromLong(self->ufds[i].fd); + if (num == NULL) { + Py_DECREF(value); + goto error; + } + PyTuple_SET_ITEM(value, 0, num); + + /* The &0xffff is a workaround for AIX. 'revents' + is a 16-bit short, and IBM assigned POLLNVAL + to be 0x8000, so the conversion to int results + in a negative number. See SF bug #923315. */ + num = PyInt_FromLong(self->ufds[i].revents & 0xffff); + if (num == NULL) { + Py_DECREF(value); + goto error; + } + PyTuple_SET_ITEM(value, 1, num); + if ((PyList_SetItem(result_list, j, value)) == -1) { + Py_DECREF(value); + goto error; + } + i++; + } + } + return result_list; + + error: + Py_DECREF(result_list); + return NULL; +} + +static PyMethodDef poll_methods[] = { + {"register", (PyCFunction)poll_register, + METH_VARARGS, poll_register_doc}, + {"modify", (PyCFunction)poll_modify, + METH_VARARGS, poll_modify_doc}, + {"unregister", (PyCFunction)poll_unregister, + METH_O, poll_unregister_doc}, + {"poll", (PyCFunction)poll_poll, + METH_VARARGS, poll_poll_doc}, + {NULL, NULL} /* sentinel */ +}; + +static pollObject * +newPollObject(void) +{ + pollObject *self; + self = PyObject_New(pollObject, &poll_Type); + if (self == NULL) + return NULL; + /* ufd_uptodate is a Boolean, denoting whether the + array pointed to by ufds matches the contents of the dictionary. */ + self->ufd_uptodate = 0; + self->ufds = NULL; + self->dict = PyDict_New(); + if (self->dict == NULL) { + Py_DECREF(self); + return NULL; + } + return self; +} + +static void +poll_dealloc(pollObject *self) +{ + if (self->ufds != NULL) + PyMem_DEL(self->ufds); + Py_XDECREF(self->dict); + PyObject_Del(self); +} + +static PyObject * +poll_getattr(pollObject *self, char *name) +{ + return Py_FindMethod(poll_methods, (PyObject *)self, name); +} + +static PyTypeObject poll_Type = { + /* The ob_type field must be initialized in the module init function + * to be portable to Windows without using C++. */ + PyVarObject_HEAD_INIT(NULL, 0) + "select.poll", /*tp_name*/ + sizeof(pollObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)poll_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + (getattrfunc)poll_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ +}; + +PyDoc_STRVAR(poll_doc, +"Returns a polling object, which supports registering and\n\ +unregistering file descriptors, and then polling them for I/O events."); + +static PyObject * +select_poll(PyObject *self, PyObject *unused) +{ + return (PyObject *)newPollObject(); +} + +#ifdef __APPLE__ +/* + * On some systems poll() sets errno on invalid file descriptors. We test + * for this at runtime because this bug may be fixed or introduced between + * OS releases. + */ +static int select_have_broken_poll(void) +{ + int poll_test; + int filedes[2]; + + struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 }; + + /* Create a file descriptor to make invalid */ + if (pipe(filedes) < 0) { + return 1; + } + poll_struct.fd = filedes[0]; + close(filedes[0]); + close(filedes[1]); + poll_test = poll(&poll_struct, 1, 0); + if (poll_test < 0) { + return 1; + } else if (poll_test == 0 && poll_struct.revents != POLLNVAL) { + return 1; + } + return 0; +} +#endif /* __APPLE__ */ + +#endif /* HAVE_POLL */ + +#ifdef HAVE_EPOLL +/* ************************************************************************** + * epoll interface for Linux 2.6 + * + * Written by Christian Heimes + * Inspired by Twisted's _epoll.pyx and select.poll() + */ + +#ifdef HAVE_SYS_EPOLL_H +#include +#endif + +typedef struct { + PyObject_HEAD + SOCKET epfd; /* epoll control file descriptor */ +} pyEpoll_Object; + +static PyTypeObject pyEpoll_Type; +#define pyepoll_CHECK(op) (PyObject_TypeCheck((op), &pyEpoll_Type)) + +static PyObject * +pyepoll_err_closed(void) +{ + PyErr_SetString(PyExc_ValueError, "I/O operation on closed epoll fd"); + return NULL; +} + +static int +pyepoll_internal_close(pyEpoll_Object *self) +{ + int save_errno = 0; + if (self->epfd >= 0) { + int epfd = self->epfd; + self->epfd = -1; + Py_BEGIN_ALLOW_THREADS + if (close(epfd) < 0) + save_errno = errno; + Py_END_ALLOW_THREADS + } + return save_errno; +} + +static PyObject * +newPyEpoll_Object(PyTypeObject *type, int sizehint, SOCKET fd) +{ + pyEpoll_Object *self; + + if (sizehint == -1) { + sizehint = FD_SETSIZE-1; + } + else if (sizehint < 1) { + PyErr_Format(PyExc_ValueError, + "sizehint must be greater zero, got %d", + sizehint); + return NULL; + } + + assert(type != NULL && type->tp_alloc != NULL); + self = (pyEpoll_Object *) type->tp_alloc(type, 0); + if (self == NULL) + return NULL; + + if (fd == -1) { + Py_BEGIN_ALLOW_THREADS + self->epfd = epoll_create(sizehint); + Py_END_ALLOW_THREADS + } + else { + self->epfd = fd; + } + if (self->epfd < 0) { + Py_DECREF(self); + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + return (PyObject *)self; +} + + +static PyObject * +pyepoll_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + int sizehint = -1; + static char *kwlist[] = {"sizehint", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:epoll", kwlist, + &sizehint)) + return NULL; + + return newPyEpoll_Object(type, sizehint, -1); +} + + +static void +pyepoll_dealloc(pyEpoll_Object *self) +{ + (void)pyepoll_internal_close(self); + Py_TYPE(self)->tp_free(self); +} + +static PyObject* +pyepoll_close(pyEpoll_Object *self) +{ + errno = pyepoll_internal_close(self); + if (errno < 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(pyepoll_close_doc, +"close() -> None\n\ +\n\ +Close the epoll control file descriptor. Further operations on the epoll\n\ +object will raise an exception."); + +static PyObject* +pyepoll_get_closed(pyEpoll_Object *self) +{ + if (self->epfd < 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static PyObject* +pyepoll_fileno(pyEpoll_Object *self) +{ + if (self->epfd < 0) + return pyepoll_err_closed(); + return PyInt_FromLong(self->epfd); +} + +PyDoc_STRVAR(pyepoll_fileno_doc, +"fileno() -> int\n\ +\n\ +Return the epoll control file descriptor."); + +static PyObject* +pyepoll_fromfd(PyObject *cls, PyObject *args) +{ + SOCKET fd; + + if (!PyArg_ParseTuple(args, "i:fromfd", &fd)) + return NULL; + + return newPyEpoll_Object((PyTypeObject*)cls, -1, fd); +} + +PyDoc_STRVAR(pyepoll_fromfd_doc, +"fromfd(fd) -> epoll\n\ +\n\ +Create an epoll object from a given control fd."); + +static PyObject * +pyepoll_internal_ctl(int epfd, int op, PyObject *pfd, unsigned int events) +{ + struct epoll_event ev; + int result; + int fd; + + if (epfd < 0) + return pyepoll_err_closed(); + + fd = PyObject_AsFileDescriptor(pfd); + if (fd == -1) { + return NULL; + } + + switch(op) { + case EPOLL_CTL_ADD: + case EPOLL_CTL_MOD: + ev.events = events; + ev.data.fd = fd; + Py_BEGIN_ALLOW_THREADS + result = epoll_ctl(epfd, op, fd, &ev); + Py_END_ALLOW_THREADS + break; + case EPOLL_CTL_DEL: + /* In kernel versions before 2.6.9, the EPOLL_CTL_DEL + * operation required a non-NULL pointer in event, even + * though this argument is ignored. */ + Py_BEGIN_ALLOW_THREADS + result = epoll_ctl(epfd, op, fd, &ev); + if (errno == EBADF) { + /* fd already closed */ + result = 0; + errno = 0; + } + Py_END_ALLOW_THREADS + break; + default: + result = -1; + errno = EINVAL; + } + + if (result < 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject * +pyepoll_register(pyEpoll_Object *self, PyObject *args, PyObject *kwds) +{ + PyObject *pfd; + unsigned int events = EPOLLIN | EPOLLOUT | EPOLLPRI; + static char *kwlist[] = {"fd", "eventmask", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|I:register", kwlist, + &pfd, &events)) { + return NULL; + } + + return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_ADD, pfd, events); +} + +PyDoc_STRVAR(pyepoll_register_doc, +"register(fd[, eventmask]) -> None\n\ +\n\ +Registers a new fd or modifies an already registered fd.\n\ +fd is the target file descriptor of the operation.\n\ +events is a bit set composed of the various EPOLL constants; the default\n\ +is EPOLL_IN | EPOLL_OUT | EPOLL_PRI.\n\ +\n\ +The epoll interface supports all file descriptors that support poll."); + +static PyObject * +pyepoll_modify(pyEpoll_Object *self, PyObject *args, PyObject *kwds) +{ + PyObject *pfd; + unsigned int events; + static char *kwlist[] = {"fd", "eventmask", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OI:modify", kwlist, + &pfd, &events)) { + return NULL; + } + + return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_MOD, pfd, events); +} + +PyDoc_STRVAR(pyepoll_modify_doc, +"modify(fd, eventmask) -> None\n\ +\n\ +fd is the target file descriptor of the operation\n\ +events is a bit set composed of the various EPOLL constants"); + +static PyObject * +pyepoll_unregister(pyEpoll_Object *self, PyObject *args, PyObject *kwds) +{ + PyObject *pfd; + static char *kwlist[] = {"fd", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:unregister", kwlist, + &pfd)) { + return NULL; + } + + return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_DEL, pfd, 0); +} + +PyDoc_STRVAR(pyepoll_unregister_doc, +"unregister(fd) -> None\n\ +\n\ +fd is the target file descriptor of the operation."); + +static PyObject * +pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds) +{ + double dtimeout = -1.; + int timeout; + int maxevents = -1; + int nfds, i; + PyObject *elist = NULL, *etuple = NULL; + struct epoll_event *evs = NULL; + static char *kwlist[] = {"timeout", "maxevents", NULL}; + + if (self->epfd < 0) + return pyepoll_err_closed(); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|di:poll", kwlist, + &dtimeout, &maxevents)) { + return NULL; + } + + if (dtimeout < 0) { + timeout = -1; + } + else if (dtimeout * 1000.0 > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "timeout is too large"); + return NULL; + } + else { + timeout = (int)(dtimeout * 1000.0); + } + + if (maxevents == -1) { + maxevents = FD_SETSIZE-1; + } + else if (maxevents < 1) { + PyErr_Format(PyExc_ValueError, + "maxevents must be greater than 0, got %d", + maxevents); + return NULL; + } + + evs = PyMem_New(struct epoll_event, maxevents); + if (evs == NULL) { + Py_DECREF(self); + PyErr_NoMemory(); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + nfds = epoll_wait(self->epfd, evs, maxevents, timeout); + Py_END_ALLOW_THREADS + if (nfds < 0) { + PyErr_SetFromErrno(PyExc_IOError); + goto error; + } + + elist = PyList_New(nfds); + if (elist == NULL) { + goto error; + } + + for (i = 0; i < nfds; i++) { + etuple = Py_BuildValue("iI", evs[i].data.fd, evs[i].events); + if (etuple == NULL) { + Py_CLEAR(elist); + goto error; + } + PyList_SET_ITEM(elist, i, etuple); + } + + error: + PyMem_Free(evs); + return elist; +} + +PyDoc_STRVAR(pyepoll_poll_doc, +"poll([timeout=-1[, maxevents=-1]]) -> [(fd, events), (...)]\n\ +\n\ +Wait for events on the epoll file descriptor for a maximum time of timeout\n\ +in seconds (as float). -1 makes poll wait indefinitely.\n\ +Up to maxevents are returned to the caller."); + +static PyMethodDef pyepoll_methods[] = { + {"fromfd", (PyCFunction)pyepoll_fromfd, + METH_VARARGS | METH_CLASS, pyepoll_fromfd_doc}, + {"close", (PyCFunction)pyepoll_close, METH_NOARGS, + pyepoll_close_doc}, + {"fileno", (PyCFunction)pyepoll_fileno, METH_NOARGS, + pyepoll_fileno_doc}, + {"modify", (PyCFunction)pyepoll_modify, + METH_VARARGS | METH_KEYWORDS, pyepoll_modify_doc}, + {"register", (PyCFunction)pyepoll_register, + METH_VARARGS | METH_KEYWORDS, pyepoll_register_doc}, + {"unregister", (PyCFunction)pyepoll_unregister, + METH_VARARGS | METH_KEYWORDS, pyepoll_unregister_doc}, + {"poll", (PyCFunction)pyepoll_poll, + METH_VARARGS | METH_KEYWORDS, pyepoll_poll_doc}, + {NULL, NULL}, +}; + +static PyGetSetDef pyepoll_getsetlist[] = { + {"closed", (getter)pyepoll_get_closed, NULL, + "True if the epoll handler is closed"}, + {0}, +}; + +PyDoc_STRVAR(pyepoll_doc, +"select.epoll([sizehint=-1])\n\ +\n\ +Returns an epolling object\n\ +\n\ +sizehint must be a positive integer or -1 for the default size. The\n\ +sizehint is used to optimize internal data structures. It doesn't limit\n\ +the maximum number of monitored events."); + +static PyTypeObject pyEpoll_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "select.epoll", /* tp_name */ + sizeof(pyEpoll_Object), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pyepoll_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + pyepoll_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pyepoll_methods, /* tp_methods */ + 0, /* tp_members */ + pyepoll_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + pyepoll_new, /* tp_new */ + 0, /* tp_free */ +}; + +#endif /* HAVE_EPOLL */ + +#ifdef HAVE_KQUEUE +/* ************************************************************************** + * kqueue interface for BSD + * + * Copyright (c) 2000 Doug White, 2006 James Knight, 2007 Christian Heimes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_SYS_EVENT_H +#include +#endif + +PyDoc_STRVAR(kqueue_event_doc, +"kevent(ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0)\n\ +\n\ +This object is the equivalent of the struct kevent for the C API.\n\ +\n\ +See the kqueue manpage for more detailed information about the meaning\n\ +of the arguments.\n\ +\n\ +One minor note: while you might hope that udata could store a\n\ +reference to a python object, it cannot, because it is impossible to\n\ +keep a proper reference count of the object once it's passed into the\n\ +kernel. Therefore, I have restricted it to only storing an integer. I\n\ +recommend ignoring it and simply using the 'ident' field to key off\n\ +of. You could also set up a dictionary on the python side to store a\n\ +udata->object mapping."); + +typedef struct { + PyObject_HEAD + struct kevent e; +} kqueue_event_Object; + +static PyTypeObject kqueue_event_Type; + +#define kqueue_event_Check(op) (PyObject_TypeCheck((op), &kqueue_event_Type)) + +typedef struct { + PyObject_HEAD + SOCKET kqfd; /* kqueue control fd */ +} kqueue_queue_Object; + +static PyTypeObject kqueue_queue_Type; + +#define kqueue_queue_Check(op) (PyObject_TypeCheck((op), &kqueue_queue_Type)) + +#if (SIZEOF_UINTPTR_T != SIZEOF_VOID_P) +# error uintptr_t does not match void *! +#elif (SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG) +# define T_UINTPTRT T_ULONGLONG +# define T_INTPTRT T_LONGLONG +# define PyLong_AsUintptr_t PyLong_AsUnsignedLongLong +# define UINTPTRT_FMT_UNIT "K" +# define INTPTRT_FMT_UNIT "L" +#elif (SIZEOF_UINTPTR_T == SIZEOF_LONG) +# define T_UINTPTRT T_ULONG +# define T_INTPTRT T_LONG +# define PyLong_AsUintptr_t PyLong_AsUnsignedLong +# define UINTPTRT_FMT_UNIT "k" +# define INTPTRT_FMT_UNIT "l" +#elif (SIZEOF_UINTPTR_T == SIZEOF_INT) +# define T_UINTPTRT T_UINT +# define T_INTPTRT T_INT +# define PyLong_AsUintptr_t PyLong_AsUnsignedLong +# define UINTPTRT_FMT_UNIT "I" +# define INTPTRT_FMT_UNIT "i" +#else +# error uintptr_t does not match int, long, or long long! +#endif + +/* Unfortunately, we can't store python objects in udata, because + * kevents in the kernel can be removed without warning, which would + * forever lose the refcount on the object stored with it. + */ + +#define KQ_OFF(x) offsetof(kqueue_event_Object, x) +static struct PyMemberDef kqueue_event_members[] = { + {"ident", T_UINTPTRT, KQ_OFF(e.ident)}, + {"filter", T_SHORT, KQ_OFF(e.filter)}, + {"flags", T_USHORT, KQ_OFF(e.flags)}, + {"fflags", T_UINT, KQ_OFF(e.fflags)}, + {"data", T_INTPTRT, KQ_OFF(e.data)}, + {"udata", T_UINTPTRT, KQ_OFF(e.udata)}, + {NULL} /* Sentinel */ +}; +#undef KQ_OFF + +static PyObject * + +kqueue_event_repr(kqueue_event_Object *s) +{ + char buf[1024]; + PyOS_snprintf( + buf, sizeof(buf), + "", + (size_t)(s->e.ident), s->e.filter, s->e.flags, + s->e.fflags, (Py_ssize_t)(s->e.data), s->e.udata); + return PyString_FromString(buf); +} + +static int +kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds) +{ + PyObject *pfd; + static char *kwlist[] = {"ident", "filter", "flags", "fflags", + "data", "udata", NULL}; + static char *fmt = "O|hhi" INTPTRT_FMT_UNIT UINTPTRT_FMT_UNIT ":kevent"; + + EV_SET(&(self->e), 0, EVFILT_READ, EV_ADD, 0, 0, 0); /* defaults */ + + if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist, + &pfd, &(self->e.filter), &(self->e.flags), + &(self->e.fflags), &(self->e.data), &(self->e.udata))) { + return -1; + } + + if (PyLong_Check(pfd)) { + self->e.ident = PyLong_AsUintptr_t(pfd); + } + else { + self->e.ident = PyObject_AsFileDescriptor(pfd); + } + if (PyErr_Occurred()) { + return -1; + } + return 0; +} + +static PyObject * +kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o, + int op) +{ + Py_intptr_t result = 0; + + if (!kqueue_event_Check(o)) { + if (op == Py_EQ || op == Py_NE) { + PyObject *res = op == Py_EQ ? Py_False : Py_True; + Py_INCREF(res); + return res; + } + PyErr_Format(PyExc_TypeError, + "can't compare %.200s to %.200s", + Py_TYPE(s)->tp_name, Py_TYPE(o)->tp_name); + return NULL; + } + if (((result = s->e.ident - o->e.ident) == 0) && + ((result = s->e.filter - o->e.filter) == 0) && + ((result = s->e.flags - o->e.flags) == 0) && + ((result = s->e.fflags - o->e.fflags) == 0) && + ((result = s->e.data - o->e.data) == 0) && + ((result = s->e.udata - o->e.udata) == 0) + ) { + result = 0; + } + + switch (op) { + case Py_EQ: + result = (result == 0); + break; + case Py_NE: + result = (result != 0); + break; + case Py_LE: + result = (result <= 0); + break; + case Py_GE: + result = (result >= 0); + break; + case Py_LT: + result = (result < 0); + break; + case Py_GT: + result = (result > 0); + break; + } + return PyBool_FromLong((long)result); +} + +static PyTypeObject kqueue_event_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "select.kevent", /* tp_name */ + sizeof(kqueue_event_Object), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)kqueue_event_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + kqueue_event_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)kqueue_event_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + kqueue_event_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)kqueue_event_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ +}; + +static PyObject * +kqueue_queue_err_closed(void) +{ + PyErr_SetString(PyExc_ValueError, "I/O operation on closed kqueue fd"); + return NULL; +} + +static int +kqueue_queue_internal_close(kqueue_queue_Object *self) +{ + int save_errno = 0; + if (self->kqfd >= 0) { + int kqfd = self->kqfd; + self->kqfd = -1; + Py_BEGIN_ALLOW_THREADS + if (close(kqfd) < 0) + save_errno = errno; + Py_END_ALLOW_THREADS + } + return save_errno; +} + +static PyObject * +newKqueue_Object(PyTypeObject *type, SOCKET fd) +{ + kqueue_queue_Object *self; + assert(type != NULL && type->tp_alloc != NULL); + self = (kqueue_queue_Object *) type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + + if (fd == -1) { + Py_BEGIN_ALLOW_THREADS + self->kqfd = kqueue(); + Py_END_ALLOW_THREADS + } + else { + self->kqfd = fd; + } + if (self->kqfd < 0) { + Py_DECREF(self); + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + return (PyObject *)self; +} + +static PyObject * +kqueue_queue_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + + if ((args != NULL && PyObject_Size(args)) || + (kwds != NULL && PyObject_Size(kwds))) { + PyErr_SetString(PyExc_ValueError, + "select.kqueue doesn't accept arguments"); + return NULL; + } + + return newKqueue_Object(type, -1); +} + +static void +kqueue_queue_dealloc(kqueue_queue_Object *self) +{ + kqueue_queue_internal_close(self); + Py_TYPE(self)->tp_free(self); +} + +static PyObject* +kqueue_queue_close(kqueue_queue_Object *self) +{ + errno = kqueue_queue_internal_close(self); + if (errno < 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(kqueue_queue_close_doc, +"close() -> None\n\ +\n\ +Close the kqueue control file descriptor. Further operations on the kqueue\n\ +object will raise an exception."); + +static PyObject* +kqueue_queue_get_closed(kqueue_queue_Object *self) +{ + if (self->kqfd < 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static PyObject* +kqueue_queue_fileno(kqueue_queue_Object *self) +{ + if (self->kqfd < 0) + return kqueue_queue_err_closed(); + return PyInt_FromLong(self->kqfd); +} + +PyDoc_STRVAR(kqueue_queue_fileno_doc, +"fileno() -> int\n\ +\n\ +Return the kqueue control file descriptor."); + +static PyObject* +kqueue_queue_fromfd(PyObject *cls, PyObject *args) +{ + SOCKET fd; + + if (!PyArg_ParseTuple(args, "i:fromfd", &fd)) + return NULL; + + return newKqueue_Object((PyTypeObject*)cls, fd); +} + +PyDoc_STRVAR(kqueue_queue_fromfd_doc, +"fromfd(fd) -> kqueue\n\ +\n\ +Create a kqueue object from a given control fd."); + +static PyObject * +kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) +{ + int nevents = 0; + int gotevents = 0; + int nchanges = 0; + int i = 0; + PyObject *otimeout = NULL; + PyObject *ch = NULL; + PyObject *it = NULL, *ei = NULL; + PyObject *result = NULL; + struct kevent *evl = NULL; + struct kevent *chl = NULL; + struct timespec timeoutspec; + struct timespec *ptimeoutspec; + + if (self->kqfd < 0) + return kqueue_queue_err_closed(); + + if (!PyArg_ParseTuple(args, "Oi|O:control", &ch, &nevents, &otimeout)) + return NULL; + + if (nevents < 0) { + PyErr_Format(PyExc_ValueError, + "Length of eventlist must be 0 or positive, got %d", + nevents); + return NULL; + } + + if (otimeout == Py_None || otimeout == NULL) { + ptimeoutspec = NULL; + } + else if (PyNumber_Check(otimeout)) { + double timeout; + long seconds; + + timeout = PyFloat_AsDouble(otimeout); + if (timeout == -1 && PyErr_Occurred()) + return NULL; + if (timeout > (double)LONG_MAX) { + PyErr_SetString(PyExc_OverflowError, + "timeout period too long"); + return NULL; + } + if (timeout < 0) { + PyErr_SetString(PyExc_ValueError, + "timeout must be positive or None"); + return NULL; + } + + seconds = (long)timeout; + timeout = timeout - (double)seconds; + timeoutspec.tv_sec = seconds; + timeoutspec.tv_nsec = (long)(timeout * 1E9); + ptimeoutspec = &timeoutspec; + } + else { + PyErr_Format(PyExc_TypeError, + "timeout argument must be an number " + "or None, got %.200s", + Py_TYPE(otimeout)->tp_name); + return NULL; + } + + if (ch != NULL && ch != Py_None) { + it = PyObject_GetIter(ch); + if (it == NULL) { + PyErr_SetString(PyExc_TypeError, + "changelist is not iterable"); + return NULL; + } + nchanges = PyObject_Size(ch); + if (nchanges < 0) { + goto error; + } + + chl = PyMem_New(struct kevent, nchanges); + if (chl == NULL) { + PyErr_NoMemory(); + goto error; + } + i = 0; + while ((ei = PyIter_Next(it)) != NULL) { + if (!kqueue_event_Check(ei)) { + Py_DECREF(ei); + PyErr_SetString(PyExc_TypeError, + "changelist must be an iterable of " + "select.kevent objects"); + goto error; + } else { + chl[i++] = ((kqueue_event_Object *)ei)->e; + } + Py_DECREF(ei); + } + } + Py_CLEAR(it); + + /* event list */ + if (nevents) { + evl = PyMem_New(struct kevent, nevents); + if (evl == NULL) { + PyErr_NoMemory(); + goto error; + } + } + + Py_BEGIN_ALLOW_THREADS + gotevents = kevent(self->kqfd, chl, nchanges, + evl, nevents, ptimeoutspec); + Py_END_ALLOW_THREADS + + if (gotevents == -1) { + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + + result = PyList_New(gotevents); + if (result == NULL) { + goto error; + } + + for (i = 0; i < gotevents; i++) { + kqueue_event_Object *ch; + + ch = PyObject_New(kqueue_event_Object, &kqueue_event_Type); + if (ch == NULL) { + goto error; + } + ch->e = evl[i]; + PyList_SET_ITEM(result, i, (PyObject *)ch); + } + PyMem_Free(chl); + PyMem_Free(evl); + return result; + + error: + PyMem_Free(chl); + PyMem_Free(evl); + Py_XDECREF(result); + Py_XDECREF(it); + return NULL; +} + +PyDoc_STRVAR(kqueue_queue_control_doc, +"control(changelist, max_events[, timeout=None]) -> eventlist\n\ +\n\ +Calls the kernel kevent function.\n\ +- changelist must be a list of kevent objects describing the changes\n\ + to be made to the kernel's watch list or None.\n\ +- max_events lets you specify the maximum number of events that the\n\ + kernel will return.\n\ +- timeout is the maximum time to wait in seconds, or else None,\n\ + to wait forever. timeout accepts floats for smaller timeouts, too."); + + +static PyMethodDef kqueue_queue_methods[] = { + {"fromfd", (PyCFunction)kqueue_queue_fromfd, + METH_VARARGS | METH_CLASS, kqueue_queue_fromfd_doc}, + {"close", (PyCFunction)kqueue_queue_close, METH_NOARGS, + kqueue_queue_close_doc}, + {"fileno", (PyCFunction)kqueue_queue_fileno, METH_NOARGS, + kqueue_queue_fileno_doc}, + {"control", (PyCFunction)kqueue_queue_control, + METH_VARARGS , kqueue_queue_control_doc}, + {NULL, NULL}, +}; + +static PyGetSetDef kqueue_queue_getsetlist[] = { + {"closed", (getter)kqueue_queue_get_closed, NULL, + "True if the kqueue handler is closed"}, + {0}, +}; + +PyDoc_STRVAR(kqueue_queue_doc, +"Kqueue syscall wrapper.\n\ +\n\ +For example, to start watching a socket for input:\n\ +>>> kq = kqueue()\n\ +>>> sock = socket()\n\ +>>> sock.connect((host, port))\n\ +>>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_ADD)], 0)\n\ +\n\ +To wait one second for it to become writeable:\n\ +>>> kq.control(None, 1, 1000)\n\ +\n\ +To stop listening:\n\ +>>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_DELETE)], 0)"); + +static PyTypeObject kqueue_queue_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "select.kqueue", /* tp_name */ + sizeof(kqueue_queue_Object), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)kqueue_queue_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + kqueue_queue_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + kqueue_queue_methods, /* tp_methods */ + 0, /* tp_members */ + kqueue_queue_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + kqueue_queue_new, /* tp_new */ + 0, /* tp_free */ +}; + +#endif /* HAVE_KQUEUE */ +/* ************************************************************************ */ + +PyDoc_STRVAR(select_doc, +"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\ +\n\ +Wait until one or more file descriptors are ready for some kind of I/O.\n\ +The first three arguments are sequences of file descriptors to be waited for:\n\ +rlist -- wait until ready for reading\n\ +wlist -- wait until ready for writing\n\ +xlist -- wait for an ``exceptional condition''\n\ +If only one kind of condition is required, pass [] for the other lists.\n\ +A file descriptor is either a socket or file object, or a small integer\n\ +gotten from a fileno() method call on one of those.\n\ +\n\ +The optional 4th argument specifies a timeout in seconds; it may be\n\ +a floating point number to specify fractions of seconds. If it is absent\n\ +or None, the call will never time out.\n\ +\n\ +The return value is a tuple of three lists corresponding to the first three\n\ +arguments; each contains the subset of the corresponding file descriptors\n\ +that are ready.\n\ +\n\ +*** IMPORTANT NOTICE ***\n\ +On Windows and OpenVMS, only sockets are supported; on Unix, all file\n\ +descriptors can be used."); + +static PyMethodDef select_methods[] = { + {"select", select_select, METH_VARARGS, select_doc}, +#ifdef HAVE_POLL + {"poll", select_poll, METH_NOARGS, poll_doc}, +#endif /* HAVE_POLL */ + {0, 0}, /* sentinel */ +}; + +PyDoc_STRVAR(module_doc, +"This module supports asynchronous I/O on multiple file descriptors.\n\ +\n\ +*** IMPORTANT NOTICE ***\n\ +On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors."); + +PyMODINIT_FUNC +initselect(void) +{ + PyObject *m; + m = Py_InitModule3("select", select_methods, module_doc); + if (m == NULL) + return; + + SelectError = PyErr_NewException("select.error", NULL, NULL); + Py_INCREF(SelectError); + PyModule_AddObject(m, "error", SelectError); + +#ifdef PIPE_BUF +#ifdef HAVE_BROKEN_PIPE_BUF +#undef PIPE_BUF +#define PIPE_BUF 512 +#endif + PyModule_AddIntConstant(m, "PIPE_BUF", PIPE_BUF); +#endif + +#if defined(HAVE_POLL) +#ifdef __APPLE__ + if (select_have_broken_poll()) { + if (PyObject_DelAttrString(m, "poll") == -1) { + PyErr_Clear(); + } + } else { +#else + { +#endif + Py_TYPE(&poll_Type) = &PyType_Type; + PyModule_AddIntConstant(m, "POLLIN", POLLIN); + PyModule_AddIntConstant(m, "POLLPRI", POLLPRI); + PyModule_AddIntConstant(m, "POLLOUT", POLLOUT); + PyModule_AddIntConstant(m, "POLLERR", POLLERR); + PyModule_AddIntConstant(m, "POLLHUP", POLLHUP); + PyModule_AddIntConstant(m, "POLLNVAL", POLLNVAL); + +#ifdef POLLRDNORM + PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM); +#endif +#ifdef POLLRDBAND + PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND); +#endif +#ifdef POLLWRNORM + PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM); +#endif +#ifdef POLLWRBAND + PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND); +#endif +#ifdef POLLMSG + PyModule_AddIntConstant(m, "POLLMSG", POLLMSG); +#endif + } +#endif /* HAVE_POLL */ + +#ifdef HAVE_EPOLL + Py_TYPE(&pyEpoll_Type) = &PyType_Type; + if (PyType_Ready(&pyEpoll_Type) < 0) + return; + + Py_INCREF(&pyEpoll_Type); + PyModule_AddObject(m, "epoll", (PyObject *) &pyEpoll_Type); + + PyModule_AddIntConstant(m, "EPOLLIN", EPOLLIN); + PyModule_AddIntConstant(m, "EPOLLOUT", EPOLLOUT); + PyModule_AddIntConstant(m, "EPOLLPRI", EPOLLPRI); + PyModule_AddIntConstant(m, "EPOLLERR", EPOLLERR); + PyModule_AddIntConstant(m, "EPOLLHUP", EPOLLHUP); + PyModule_AddIntConstant(m, "EPOLLET", EPOLLET); +#ifdef EPOLLONESHOT + /* Kernel 2.6.2+ */ + PyModule_AddIntConstant(m, "EPOLLONESHOT", EPOLLONESHOT); +#endif + /* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */ + PyModule_AddIntConstant(m, "EPOLLRDNORM", EPOLLRDNORM); + PyModule_AddIntConstant(m, "EPOLLRDBAND", EPOLLRDBAND); + PyModule_AddIntConstant(m, "EPOLLWRNORM", EPOLLWRNORM); + PyModule_AddIntConstant(m, "EPOLLWRBAND", EPOLLWRBAND); + PyModule_AddIntConstant(m, "EPOLLMSG", EPOLLMSG); +#endif /* HAVE_EPOLL */ + +#ifdef HAVE_KQUEUE + kqueue_event_Type.tp_new = PyType_GenericNew; + Py_TYPE(&kqueue_event_Type) = &PyType_Type; + if(PyType_Ready(&kqueue_event_Type) < 0) + return; + + Py_INCREF(&kqueue_event_Type); + PyModule_AddObject(m, "kevent", (PyObject *)&kqueue_event_Type); + + Py_TYPE(&kqueue_queue_Type) = &PyType_Type; + if(PyType_Ready(&kqueue_queue_Type) < 0) + return; + Py_INCREF(&kqueue_queue_Type); + PyModule_AddObject(m, "kqueue", (PyObject *)&kqueue_queue_Type); + + /* event filters */ + PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ); + PyModule_AddIntConstant(m, "KQ_FILTER_WRITE", EVFILT_WRITE); + PyModule_AddIntConstant(m, "KQ_FILTER_AIO", EVFILT_AIO); + PyModule_AddIntConstant(m, "KQ_FILTER_VNODE", EVFILT_VNODE); + PyModule_AddIntConstant(m, "KQ_FILTER_PROC", EVFILT_PROC); +#ifdef EVFILT_NETDEV + PyModule_AddIntConstant(m, "KQ_FILTER_NETDEV", EVFILT_NETDEV); +#endif + PyModule_AddIntConstant(m, "KQ_FILTER_SIGNAL", EVFILT_SIGNAL); + PyModule_AddIntConstant(m, "KQ_FILTER_TIMER", EVFILT_TIMER); + + /* event flags */ + PyModule_AddIntConstant(m, "KQ_EV_ADD", EV_ADD); + PyModule_AddIntConstant(m, "KQ_EV_DELETE", EV_DELETE); + PyModule_AddIntConstant(m, "KQ_EV_ENABLE", EV_ENABLE); + PyModule_AddIntConstant(m, "KQ_EV_DISABLE", EV_DISABLE); + PyModule_AddIntConstant(m, "KQ_EV_ONESHOT", EV_ONESHOT); + PyModule_AddIntConstant(m, "KQ_EV_CLEAR", EV_CLEAR); + + PyModule_AddIntConstant(m, "KQ_EV_SYSFLAGS", EV_SYSFLAGS); + PyModule_AddIntConstant(m, "KQ_EV_FLAG1", EV_FLAG1); + + PyModule_AddIntConstant(m, "KQ_EV_EOF", EV_EOF); + PyModule_AddIntConstant(m, "KQ_EV_ERROR", EV_ERROR); + + /* READ WRITE filter flag */ + PyModule_AddIntConstant(m, "KQ_NOTE_LOWAT", NOTE_LOWAT); + + /* VNODE filter flags */ + PyModule_AddIntConstant(m, "KQ_NOTE_DELETE", NOTE_DELETE); + PyModule_AddIntConstant(m, "KQ_NOTE_WRITE", NOTE_WRITE); + PyModule_AddIntConstant(m, "KQ_NOTE_EXTEND", NOTE_EXTEND); + PyModule_AddIntConstant(m, "KQ_NOTE_ATTRIB", NOTE_ATTRIB); + PyModule_AddIntConstant(m, "KQ_NOTE_LINK", NOTE_LINK); + PyModule_AddIntConstant(m, "KQ_NOTE_RENAME", NOTE_RENAME); + PyModule_AddIntConstant(m, "KQ_NOTE_REVOKE", NOTE_REVOKE); + + /* PROC filter flags */ + PyModule_AddIntConstant(m, "KQ_NOTE_EXIT", NOTE_EXIT); + PyModule_AddIntConstant(m, "KQ_NOTE_FORK", NOTE_FORK); + PyModule_AddIntConstant(m, "KQ_NOTE_EXEC", NOTE_EXEC); + PyModule_AddIntConstant(m, "KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK); + PyModule_AddIntConstant(m, "KQ_NOTE_PDATAMASK", NOTE_PDATAMASK); + + PyModule_AddIntConstant(m, "KQ_NOTE_TRACK", NOTE_TRACK); + PyModule_AddIntConstant(m, "KQ_NOTE_CHILD", NOTE_CHILD); + PyModule_AddIntConstant(m, "KQ_NOTE_TRACKERR", NOTE_TRACKERR); + + /* NETDEV filter flags */ +#ifdef EVFILT_NETDEV + PyModule_AddIntConstant(m, "KQ_NOTE_LINKUP", NOTE_LINKUP); + PyModule_AddIntConstant(m, "KQ_NOTE_LINKDOWN", NOTE_LINKDOWN); + PyModule_AddIntConstant(m, "KQ_NOTE_LINKINV", NOTE_LINKINV); +#endif + +#endif /* HAVE_KQUEUE */ +} diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Modules/socketmodule.h b/AppPkg/Applications/Python/PyMod-2.7.2/Modules/socketmodule.h new file mode 100644 index 0000000000..56ee42222e --- /dev/null +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Modules/socketmodule.h @@ -0,0 +1,250 @@ +/* Socket module header file */ + +/* Includes needed for the sockaddr_* symbols below */ +#ifndef MS_WINDOWS +#ifdef __VMS +# include +# else +# include +# endif +# include +# if !(defined(UEFI_ENV) || defined(__BEOS__) || defined(__CYGWIN__) || (defined(PYOS_OS2) && defined(PYCC_VACPP))) +# include +# endif + +#else /* MS_WINDOWS */ +# include +# include +/* VC6 is shipped with old platform headers, and does not have MSTcpIP.h + * Separate SDKs have all the functions we want, but older ones don't have + * any version information. + * I use SIO_GET_MULTICAST_FILTER to detect a decent SDK. + */ +# ifdef SIO_GET_MULTICAST_FILTER +# include /* for SIO_RCVALL */ +# define HAVE_ADDRINFO +# define HAVE_SOCKADDR_STORAGE +# define HAVE_GETADDRINFO +# define HAVE_GETNAMEINFO +# define ENABLE_IPV6 +# else +typedef int socklen_t; +# endif /* IPPROTO_IPV6 */ +#endif /* MS_WINDOWS */ + +#ifdef HAVE_SYS_UN_H +# include +#else +# undef AF_UNIX +#endif + +#ifdef HAVE_LINUX_NETLINK_H +# ifdef HAVE_ASM_TYPES_H +# include +# endif +# include +#else +# undef AF_NETLINK +#endif + +#ifdef HAVE_BLUETOOTH_BLUETOOTH_H +#include +#include +#include +#include +#include +#endif + +#ifdef HAVE_BLUETOOTH_H +#include +#endif + +#ifdef HAVE_NETPACKET_PACKET_H +# include +# include +# include +#endif + +#ifdef HAVE_LINUX_TIPC_H +# include +#endif + +#ifndef Py__SOCKET_H +#define Py__SOCKET_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Python module and C API name */ +#define PySocket_MODULE_NAME "_socket" +#define PySocket_CAPI_NAME "CAPI" +#define PySocket_CAPSULE_NAME (PySocket_MODULE_NAME "." PySocket_CAPI_NAME) + +/* Abstract the socket file descriptor type */ +#ifdef MS_WINDOWS +typedef SOCKET SOCKET_T; +# ifdef MS_WIN64 +# define SIZEOF_SOCKET_T 8 +# else +# define SIZEOF_SOCKET_T 4 +# endif +#else +typedef int SOCKET_T; +# define SIZEOF_SOCKET_T SIZEOF_INT +#endif + +/* Socket address */ +typedef union sock_addr { + struct sockaddr_in in; +#ifdef AF_UNIX + struct sockaddr_un un; +#endif +#ifdef AF_NETLINK + struct sockaddr_nl nl; +#endif +#ifdef ENABLE_IPV6 + struct sockaddr_in6 in6; + struct sockaddr_storage storage; +#endif +#ifdef HAVE_BLUETOOTH_BLUETOOTH_H + struct sockaddr_l2 bt_l2; + struct sockaddr_rc bt_rc; + struct sockaddr_sco bt_sco; + struct sockaddr_hci bt_hci; +#endif +#ifdef HAVE_NETPACKET_PACKET_H + struct sockaddr_ll ll; +#endif +} sock_addr_t; + +/* The object holding a socket. It holds some extra information, + like the address family, which is used to decode socket address + arguments properly. */ + +typedef struct { + PyObject_HEAD + SOCKET_T sock_fd; /* Socket file descriptor */ + int sock_family; /* Address family, e.g., AF_INET */ + int sock_type; /* Socket type, e.g., SOCK_STREAM */ + int sock_proto; /* Protocol type, usually 0 */ + PyObject *(*errorhandler)(void); /* Error handler; checks + errno, returns NULL and + sets a Python exception */ + double sock_timeout; /* Operation timeout in seconds; + 0.0 means non-blocking */ +} PySocketSockObject; + +/* --- C API ----------------------------------------------------*/ + +/* Short explanation of what this C API export mechanism does + and how it works: + + The _ssl module needs access to the type object defined in + the _socket module. Since cross-DLL linking introduces a lot of + problems on many platforms, the "trick" is to wrap the + C API of a module in a struct which then gets exported to + other modules via a PyCapsule. + + The code in socketmodule.c defines this struct (which currently + only contains the type object reference, but could very + well also include other C APIs needed by other modules) + and exports it as PyCapsule via the module dictionary + under the name "CAPI". + + Other modules can now include the socketmodule.h file + which defines the needed C APIs to import and set up + a static copy of this struct in the importing module. + + After initialization, the importing module can then + access the C APIs from the _socket module by simply + referring to the static struct, e.g. + + Load _socket module and its C API; this sets up the global + PySocketModule: + + if (PySocketModule_ImportModuleAndAPI()) + return; + + + Now use the C API as if it were defined in the using + module: + + if (!PyArg_ParseTuple(args, "O!|zz:ssl", + + PySocketModule.Sock_Type, + + (PyObject*)&Sock, + &key_file, &cert_file)) + return NULL; + + Support could easily be extended to export more C APIs/symbols + this way. Currently, only the type object is exported, + other candidates would be socket constructors and socket + access functions. + +*/ + +/* C API for usage by other Python modules */ +typedef struct { + PyTypeObject *Sock_Type; + PyObject *error; +} PySocketModule_APIObject; + +/* XXX The net effect of the following appears to be to define a function + XXX named PySocketModule_APIObject in _ssl.c. It's unclear why it isn't + XXX defined there directly. + + >>> It's defined here because other modules might also want to use + >>> the C API. + +*/ +#ifndef PySocket_BUILDING_SOCKET + +/* --- C API ----------------------------------------------------*/ + +/* Interfacestructure to C API for other modules. + Call PySocketModule_ImportModuleAndAPI() to initialize this + structure. After that usage is simple: + + if (!PyArg_ParseTuple(args, "O!|zz:ssl", + &PySocketModule.Sock_Type, (PyObject*)&Sock, + &key_file, &cert_file)) + return NULL; + ... +*/ + +static +PySocketModule_APIObject PySocketModule; + +/* You *must* call this before using any of the functions in + PySocketModule and check its outcome; otherwise all accesses will + result in a segfault. Returns 0 on success. */ + +#ifndef DPRINTF +# define DPRINTF if (0) printf +#endif + +static +int PySocketModule_ImportModuleAndAPI(void) +{ + void *api; + + DPRINTF(" Loading capsule %s\n", PySocket_CAPSULE_NAME); + api = PyCapsule_Import(PySocket_CAPSULE_NAME, 1); + if (api == NULL) + goto onError; + memcpy(&PySocketModule, api, sizeof(PySocketModule)); + DPRINTF(" API object loaded and initialized.\n"); + return 0; + + onError: + DPRINTF(" not found.\n"); + return -1; +} + +#endif /* !PySocket_BUILDING_SOCKET */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py__SOCKET_H */ diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Modules/zlib/zutil.h b/AppPkg/Applications/Python/PyMod-2.7.2/Modules/zlib/zutil.h index 46f89878d6..9f4d1a6f9e 100644 --- a/AppPkg/Applications/Python/PyMod-2.7.2/Modules/zlib/zutil.h +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Modules/zlib/zutil.h @@ -161,8 +161,8 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define fdopen(fd,mode) NULL /* No fdopen() */ #endif -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# if defined(_WIN32_WCE) || defined(_EFI_STDLIB) +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined(UEFI_ENV) +# if defined(_WIN32_WCE) # define fdopen(fd,mode) NULL /* No fdopen() */ # ifndef _PTRDIFF_T_DEFINED typedef int ptrdiff_t; diff --git a/AppPkg/Applications/Python/PyMod-2.7.2/Python/getcopyright.c b/AppPkg/Applications/Python/PyMod-2.7.2/Python/getcopyright.c new file mode 100644 index 0000000000..66ebc75193 --- /dev/null +++ b/AppPkg/Applications/Python/PyMod-2.7.2/Python/getcopyright.c @@ -0,0 +1,36 @@ +/* Return the copyright string. This is updated manually. + + Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +*/ + +#include "Python.h" + +static char cprt[] = +"\ +Copyright (c) 2010-2011 Intel Corporation.\n\ +All Rights Reserved.\n\ +\n\ +Copyright (c) 2001-2011 Python Software Foundation.\n\ +All Rights Reserved.\n\ +\n\ +Copyright (c) 2000 BeOpen.com.\n\ +All Rights Reserved.\n\ +\n\ +Copyright (c) 1995-2001 Corporation for National Research Initiatives.\n\ +All Rights Reserved.\n\ +\n\ +Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.\n\ +All Rights Reserved."; + +const char * +Py_GetCopyright(void) +{ + return cprt; +} diff --git a/AppPkg/Applications/Python/PythonCore.inf b/AppPkg/Applications/Python/PythonCore.inf index 15fac14c66..28b6e9d59c 100644 --- a/AppPkg/Applications/Python/PythonCore.inf +++ b/AppPkg/Applications/Python/PythonCore.inf @@ -34,19 +34,19 @@ LibString LibStdio LibGdtoa - LibWchar LibMath + LibWchar LibGen LibNetUtil - DevShell BsdSocketLib EfiSocketLib + DevShell [Sources] #EFI -- EFI specific code Efi/config.c - Efi/getpath.c Efi/edk2module.c + Efi/getpath.c #Parser Python-2.7.2/Parser/acceler.c @@ -63,6 +63,10 @@ Python-2.7.2/Parser/tokenizer.c #Python + PyMod-2.7.2/Python/getcopyright.c + PyMod-2.7.2/Python/import.c + PyMod-2.7.2/Python/marshal.c + Python-2.7.2/Python/_warnings.c Python-2.7.2/Python/asdl.c Python-2.7.2/Python/ast.c @@ -79,14 +83,11 @@ Python-2.7.2/Python/future.c Python-2.7.2/Python/getargs.c Python-2.7.2/Python/getcompiler.c - Python-2.7.2/Python/getcopyright.c Python-2.7.2/Python/getopt.c Python-2.7.2/Python/getplatform.c Python-2.7.2/Python/getversion.c Python-2.7.2/Python/graminit.c - Python-2.7.2/Python/import.c Python-2.7.2/Python/importdl.c - Python-2.7.2/Python/marshal.c Python-2.7.2/Python/modsupport.c Python-2.7.2/Python/mysnprintf.c Python-2.7.2/Python/mystrtoul.c @@ -111,47 +112,42 @@ Python-2.7.2/Modules/python.c Python-2.7.2/Modules/getbuildinfo.c - Python-2.7.2/Modules/arraymodule.c - Python-2.7.2/Modules/binascii.c - Python-2.7.2/Modules/errnomodule.c - Python-2.7.2/Modules/gcmodule.c - Python-2.7.2/Modules/signalmodule.c - Python-2.7.2/Modules/operator.c - Python-2.7.2/Modules/_weakref.c - Python-2.7.2/Modules/mathmodule.c - Python-2.7.2/Modules/_math.c - Python-2.7.2/Modules/timemodule.c - Python-2.7.2/Modules/datetimemodule.c - Python-2.7.2/Modules/cStringIO.c - Python-2.7.2/Modules/_codecsmodule.c - Python-2.7.2/Modules/_randommodule.c - Python-2.7.2/Modules/xxsubtype.c + PyMod-2.7.2/Modules/_sre.c + PyMod-2.7.2/Modules/errnomodule.c + PyMod-2.7.2/Modules/selectmodule.c - Python-2.7.2/Modules/_heapqmodule.c - Python-2.7.2/Modules/itertoolsmodule.c + Python-2.7.2/Modules/_bisectmodule.c + Python-2.7.2/Modules/_codecsmodule.c Python-2.7.2/Modules/_collectionsmodule.c - Python-2.7.2/Modules/_sre.c - Python-2.7.2/Modules/parsermodule.c - Python-2.7.2/Modules/_struct.c - Python-2.7.2/Modules/cPickle.c Python-2.7.2/Modules/_functoolsmodule.c - Python-2.7.2/Modules/cmathmodule.c + Python-2.7.2/Modules/_heapqmodule.c Python-2.7.2/Modules/_json.c - - Python-2.7.2/Modules/_bisectmodule.c + Python-2.7.2/Modules/_math.c + Python-2.7.2/Modules/_randommodule.c + Python-2.7.2/Modules/_struct.c + Python-2.7.2/Modules/_weakref.c + Python-2.7.2/Modules/arraymodule.c + Python-2.7.2/Modules/binascii.c + Python-2.7.2/Modules/cmathmodule.c + Python-2.7.2/Modules/cPickle.c + Python-2.7.2/Modules/cStringIO.c + Python-2.7.2/Modules/datetimemodule.c Python-2.7.2/Modules/future_builtins.c + Python-2.7.2/Modules/gcmodule.c + Python-2.7.2/Modules/itertoolsmodule.c + Python-2.7.2/Modules/mathmodule.c Python-2.7.2/Modules/md5.c Python-2.7.2/Modules/md5module.c + Python-2.7.2/Modules/operator.c + Python-2.7.2/Modules/parsermodule.c Python-2.7.2/Modules/shamodule.c Python-2.7.2/Modules/sha256module.c Python-2.7.2/Modules/sha512module.c - Python-2.7.2/Modules/stropmodule.c - - # Socket related modules -# Python-$(PYTHON_VERSION)/Modules/getaddrinfo.c # included by socketmodule.c -# Python-$(PYTHON_VERSION)/Modules/getnameinfo.c # included by socketmodule.c - Python-2.7.2/Modules/selectmodule.c + Python-2.7.2/Modules/signalmodule.c Python-2.7.2/Modules/socketmodule.c + Python-2.7.2/Modules/stropmodule.c + Python-2.7.2/Modules/timemodule.c + Python-2.7.2/Modules/xxsubtype.c # Python-$(PYTHON_VERSION)/Modules/imageop.c # Python-$(PYTHON_VERSION)/Modules/_csv.c diff --git a/AppPkg/Applications/Python/X64/pyconfig.h b/AppPkg/Applications/Python/X64/pyconfig.h index 41b06827f5..ef95d1be62 100644 --- a/AppPkg/Applications/Python/X64/pyconfig.h +++ b/AppPkg/Applications/Python/X64/pyconfig.h @@ -10,16 +10,15 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ - - #ifndef Py_PYCONFIG_H #define Py_PYCONFIG_H -#define PLATFORM "UEFI 2.3 X64" +#include + +/* Define to indicate that code is being built to run in the UEFI Environment. */ +#define UEFI_ENV EFI_SYSTEM_TABLE_REVISION -//#ifndef PYTHONPATH -//# define PYTHONPATH "/Efi/StdLib/lib/python.27;/Efi/StdLib/lib/python.27/lib-dynload" -//#endif +#define PLATFORM "UEFI" /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD @@ -185,7 +184,7 @@ /* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_DIRENT_H +#define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H @@ -328,7 +327,7 @@ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the `getpeername' function. */ -#undef HAVE_GETPEERNAME +#define HAVE_GETPEERNAME 1 /* Define to 1 if you have the `getpgid' function. */ #undef HAVE_GETPGID @@ -514,10 +513,10 @@ #undef HAVE_PLOCK /* Define to 1 if you have the `poll' function. */ -#undef HAVE_POLL +#define HAVE_POLL 1 /* Define to 1 if you have the header file. */ -#define HAVE_POLL_H 1 +#undef HAVE_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_PROCESS_H @@ -550,7 +549,7 @@ #undef HAVE_READLINK /* Define to 1 if you have the `realpath' function. */ -#undef HAVE_REALPATH +#define HAVE_REALPATH 1 /* Define if you have readline 2.1 */ #undef HAVE_RL_CALLBACK @@ -577,7 +576,7 @@ #undef HAVE_ROUND /* Define to 1 if you have the `select' function. */ -#undef HAVE_SELECT +#define HAVE_SELECT 1 /* Define to 1 if you have the `sem_getvalue' function. */ #undef HAVE_SEM_GETVALUE @@ -824,7 +823,7 @@ #define HAVE_TEMPNAM 1 /* Define to 1 if you have the header file. */ -#define HAVE_TERMIOS_H 1 +#undef HAVE_TERMIOS_H /* Define to 1 if you have the header file. */ #undef HAVE_TERM_H @@ -888,7 +887,7 @@ #undef HAVE_UTIMES /* Define to 1 if you have the header file. */ -#undef HAVE_UTIME_H +#define HAVE_UTIME_H 1 /* Define to 1 if you have the `wait3' function. */ #undef HAVE_WAIT3 -- 2.39.2