From: Daryl McDaniel Date: Wed, 23 Dec 2015 00:01:30 +0000 (+0000) Subject: AppPkg/.../Python-2.7.10: Remove irrelevant conditional code from edk2module.c. X-Git-Tag: edk2-stable201903~8172 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=173523c20de4f882250c5aaf072cf94e327dfb4e AppPkg/.../Python-2.7.10: Remove irrelevant conditional code from edk2module.c. Remove sections of conditional code that are not relevant to the EDK II or UEFI environments. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Daryl McDaniel Reviewed-by: Erik Bjorge git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19459 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/AppPkg/Applications/Python/Python-2.7.10/PyMod-2.7.10/Modules/edk2module.c b/AppPkg/Applications/Python/Python-2.7.10/PyMod-2.7.10/Modules/edk2module.c index 037849504f..9460a50bc5 100644 --- a/AppPkg/Applications/Python/Python-2.7.10/PyMod-2.7.10/Modules/edk2module.c +++ b/AppPkg/Applications/Python/Python-2.7.10/PyMod-2.7.10/Modules/edk2module.c @@ -1060,61 +1060,6 @@ posix_listdir(PyObject *self, PyObject *args) } /* 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."); @@ -2293,45 +2238,6 @@ posix_forkpty(PyObject *self, PyObject *noargs) } #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"); @@ -2342,177 +2248,6 @@ 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\ @@ -2542,18 +2277,6 @@ posix_getlogin(PyObject *self, PyObject *noargs) } #endif -#ifndef UEFI_C_SOURCE -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()); -} -#endif /* UEFI_C_SOURCE */ - #ifdef HAVE_KILL PyDoc_STRVAR(posix_kill__doc__, "kill(pid, sig)\n\n\ @@ -2588,29 +2311,6 @@ posix_kill(PyObject *self, PyObject *args) } #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 @@ -2640,116 +2340,6 @@ 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) @@ -2761,6 +2351,11 @@ posix_popen(PyObject *self, PyObject *args) 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 @@ -2772,4033 +2367,1334 @@ posix_popen(PyObject *self, PyObject *args) 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. - */ +#endif /* HAVE_POPEN */ +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) static PyObject * -os2emx_popen2(PyObject *self, PyObject *args) +wait_helper(pid_t pid, int status, struct rusage *ru) { - PyObject *f; - int tm=0; + PyObject *result; + static PyObject *struct_rusage; - char *cmdstring; - char *mode = "t"; - int bufsize = -1; - if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize)) - return NULL; + 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; + } - if (*mode == 't') - tm = O_TEXT; - else if (*mode != 'b') { - PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'"); + /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ + result = PyStructSequence_New((PyTypeObject*) struct_rusage); + if (!result) return NULL; - } else - tm = O_BINARY; - f = _PyPopen(cmdstring, tm, POPEN_2, bufsize); +#ifndef doubletime +#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) +#endif - return f; + 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 */ -/* - * Variation on os2emx.popen2 - * - * The result of this function is 3 pipes - the process's stdin, - * stdout and stderr - */ +#ifdef HAVE_WAIT3 +PyDoc_STRVAR(posix_wait3__doc__, +"wait3(options) -> (pid, status, rusage)\n\n\ +Wait for completion of a child process."); static PyObject * -os2emx_popen3(PyObject *self, PyObject *args) +posix_wait3(PyObject *self, PyObject *args) { - PyObject *f; - int tm = 0; + pid_t pid; + int options; + struct rusage ru; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - char *cmdstring; - char *mode = "t"; - int bufsize = -1; - if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize)) + if (!PyArg_ParseTuple(args, "i:wait3", &options)) 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; + Py_BEGIN_ALLOW_THREADS + pid = wait3(&status, options, &ru); + Py_END_ALLOW_THREADS - f = _PyPopen(cmdstring, tm, POPEN_3, bufsize); - - return f; + return wait_helper(pid, WAIT_STATUS_INT(status), &ru); } +#endif /* HAVE_WAIT3 */ -/* - * Variation on os2emx.popen2 - * - * The result of this function is 2 pipes - the processes stdin, - * and stdout+stderr combined as a single pipe. - */ +#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 * -os2emx_popen4(PyObject *self, PyObject *args) +posix_wait4(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; + pid_t pid; + int options; + struct rusage ru; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (*mode == 't') - tm = O_TEXT; - else if (*mode != 'b') { - PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'"); + if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options)) return NULL; - } else - tm = O_BINARY; - f = _PyPopen(cmdstring, tm, POPEN_4, bufsize); + Py_BEGIN_ALLOW_THREADS + pid = wait4(pid, &status, options, &ru); + Py_END_ALLOW_THREADS - return f; + return wait_helper(pid, WAIT_STATUS_INT(status), &ru); } +#endif /* HAVE_WAIT4 */ -/* 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 */ +#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 * -_PyPopen(char *cmdstring, int mode, int n, int bufsize) +posix_waitpid(PyObject *self, PyObject *args) { - 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(); - } + pid_t pid; + int options; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - /* 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; + 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(); - } - - /* 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; - } + return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); +} - /* - 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; - } - } +#elif defined(HAVE_CWAIT) - /* - 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; - } +/* 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."); - case POPEN_4: - { - if (dup2(1, 2) != 2) - { - pipe_err = -1; - } - break; - } - } +static PyObject * +posix_waitpid(PyObject *self, PyObject *args) +{ + Py_intptr_t pid; + int status, options; - /* 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; - } - } + 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(); - /* 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); - } + /* 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 */ - /* 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); - } +#ifdef HAVE_WAIT +PyDoc_STRVAR(posix_wait__doc__, +"wait() -> (pid, status)\n\n\ +Wait for completion of a child process."); - /* 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(); - } +static PyObject * +posix_wait(PyObject *self, PyObject *noargs) +{ + pid_t pid; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (_PyPopenProcs) - { - PyObject *procObj, *pidObj, *intObj, *fileObj[3]; - int ins_rc[3]; + Py_BEGIN_ALLOW_THREADS + pid = wait(&status); + Py_END_ALLOW_THREADS + if (pid == -1) + return posix_error(); - fileObj[0] = fileObj[1] = fileObj[2] = NULL; - ins_rc[0] = ins_rc[1] = ins_rc[2] = 0; + return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); +} +#endif - 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); - } - } +PyDoc_STRVAR(posix_lstat__doc__, +"lstat(path) -> stat result\n\n\ +Like stat(path), but do not follow symbolic links."); - 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]); - } - } - } +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 */ +} - /* - * 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; -} +#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."); -/* - * 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) +static PyObject * +posix_readlink(PyObject *self, PyObject *args) { - int result; - int exit_code; - pid_t pipe_pid; - PyObject *procObj, *pidObj, *intObj, *fileObj; - int file_count; -#ifdef WITH_THREAD - PyGILState_STATE state; + PyObject* v; + char buf[MAXPATHLEN]; + char *path; + int n; +#ifdef Py_USING_UNICODE + int arg_is_unicode = 0; #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); + 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; + } -#ifdef WITH_THREAD - state = PyGILState_Ensure(); + if (PyUnicode_Check(v)) { + arg_is_unicode = 1; + } + Py_DECREF(v); #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_BEGIN_ALLOW_THREADS + n = readlink(path, buf, (int) sizeof buf); + Py_END_ALLOW_THREADS + if (n < 0) + return posix_error_with_allocated_filename(path); - Py_XDECREF(fileObj); - } /* if _PyPopenProcs */ + PyMem_Free(path); + v = PyString_FromStringAndSize(buf, n); +#ifdef Py_USING_UNICODE + if (arg_is_unicode) { + PyObject *w; -#ifdef WITH_THREAD - PyGILState_Release(state); + 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 result; + return v; } - -#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; +#endif /* HAVE_READLINK */ -/* 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. - */ +#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_popen(PyObject *self, PyObject *args) +posix_symlink(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; + return posix_2str(args, "etet:symlink", symlink); +} +#endif /* HAVE_SYMLINK */ - 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. - */ +#ifdef HAVE_TIMES +#define NEED_TICKS_PER_SECOND +static long ticks_per_second = -1; static PyObject * -win32_popen2(PyObject *self, PyObject *args) +posix_times(PyObject *self, PyObject *noargs) { - 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; + 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 /* HAVE_TIMES */ - if (bufsize != -1) { - PyErr_SetString(PyExc_ValueError, "popen2() arg 3 must be -1"); - return NULL; - } - f = _PyPopen(cmdstring, tm, POPEN_2); +#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 - return f; -} -/* - * Variation on - * - * The result of this function is 3 pipes - the process's stdin, - * stdout and stderr - */ +#ifdef HAVE_GETSID +PyDoc_STRVAR(posix_getsid__doc__, +"getsid(pid) -> sid\n\n\ +Call the system call getsid()."); static PyObject * -win32_popen3(PyObject *self, PyObject *args) +posix_getsid(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'"); + pid_t pid; + int sid; + if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid)) return NULL; - } else - tm = _O_BINARY; + sid = getsid(pid); + if (sid < 0) + return posix_error(); + return PyInt_FromLong((long)sid); +} +#endif /* HAVE_GETSID */ - if (bufsize != -1) { - PyErr_SetString(PyExc_ValueError, "popen3() arg 3 must be -1"); - return NULL; - } - f = _PyPopen(cmdstring, tm, POPEN_3); +#ifdef HAVE_SETSID +PyDoc_STRVAR(posix_setsid__doc__, +"setsid()\n\n\ +Call the system call setsid()."); - return f; +static PyObject * +posix_setsid(PyObject *self, PyObject *noargs) +{ + if (setsid() < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; } +#endif /* HAVE_SETSID */ -/* - * Variation on win32pipe.popen - * - * The result of this function is 2 pipes - the processes stdin, - * and stdout+stderr combined as a single pipe. - */ +#ifdef HAVE_SETPGID +PyDoc_STRVAR(posix_setpgid__doc__, +"setpgid(pid, pgrp)\n\n\ +Call the system call setpgid()."); static PyObject * -win32_popen4(PyObject *self, PyObject *args) +posix_setpgid(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"); + pid_t pid; + int pgrp; + if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp)) return NULL; - } - - f = _PyPopen(cmdstring, tm, POPEN_4); - - return f; + if (setpgid(pid, pgrp) < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; } +#endif /* HAVE_SETPGID */ -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 */ +#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 * -_PyPopen(char *cmdstring, int mode, int n) +posix_tcgetpgrp(PyObject *self, PyObject *args) { - 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; + 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 */ -/* - * 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; - } +#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."); - } /* if object retrieval ok */ +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 */ - Py_XDECREF(fileObj); - } /* if _PyPopenProcs */ +/* Functions acting on file descriptors */ -#ifdef WITH_THREAD - PyGILState_Release(state); -#endif - return result; -} +PyDoc_STRVAR(posix_open__doc__, +"open(filename, flag [, mode=0777]) -> fd\n\n\ +Open a file (for low level IO)."); -#else /* which OS? */ static PyObject * -posix_popen(PyObject *self, PyObject *args) +posix_open(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)) + char *file = NULL; + int flag; + int mode = 0777; + int fd; + + if (!PyArg_ParseTuple(args, "eti|i", + Py_FileSystemDefaultEncoding, &file, + &flag, &mode)) 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); + fd = open(file, flag, 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; + if (fd < 0) + return posix_error_with_allocated_filename(file); + PyMem_Free(file); + return PyInt_FromLong((long)fd); } -#endif /* PYOS_??? */ -#endif /* HAVE_POPEN */ - -#ifdef HAVE_SETUID -PyDoc_STRVAR(posix_setuid__doc__, -"setuid(uid)\n\n\ -Set the current process's user id."); +PyDoc_STRVAR(posix_close__doc__, +"close(fd)\n\n\ +Close a file descriptor (for low level IO)."); static PyObject * -posix_setuid(PyObject *self, PyObject *args) +posix_close(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"); + int fd, res; + if (!PyArg_ParseTuple(args, "i:close", &fd)) return NULL; - } - if (setuid(uid) < 0) + 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; } -#endif /* HAVE_SETUID */ -#ifdef HAVE_SETEUID -PyDoc_STRVAR(posix_seteuid__doc__, -"seteuid(uid)\n\n\ -Set the current process's effective user id."); +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_seteuid (PyObject *self, PyObject *args) +posix_closerange(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"); + int fd_from, fd_to, i; + if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to)) return NULL; - } - if (seteuid(euid) < 0) { - return posix_error(); - } else { - Py_INCREF(Py_None); - return Py_None; - } + 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; } -#endif /* HAVE_SETEUID */ -#ifdef HAVE_SETEGID -PyDoc_STRVAR(posix_setegid__doc__, -"setegid(gid)\n\n\ -Set the current process's effective group id."); + +PyDoc_STRVAR(posix_dup__doc__, +"dup(fd) -> fd2\n\n\ +Return a duplicate of a file descriptor."); static PyObject * -posix_setegid (PyObject *self, PyObject *args) +posix_dup(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"); + int fd; + if (!PyArg_ParseTuple(args, "i:dup", &fd)) return NULL; - } - if (setegid(egid) < 0) { + if (!_PyVerify_fd(fd)) return posix_error(); - } else { - Py_INCREF(Py_None); - return Py_None; - } + Py_BEGIN_ALLOW_THREADS + fd = dup(fd); + Py_END_ALLOW_THREADS + if (fd < 0) + return posix_error(); + return PyInt_FromLong((long)fd); } -#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."); + +PyDoc_STRVAR(posix_dup2__doc__, +"dup2(old_fd, new_fd)\n\n\ +Duplicate file descriptor."); static PyObject * -posix_setreuid (PyObject *self, PyObject *args) +posix_dup2(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"); + int fd, fd2, res; + if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2)) return NULL; - } - if (setregid(rgid, egid) < 0) { + if (!_PyVerify_fd_dup2(fd, fd2)) 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) + 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; } -#endif /* HAVE_SETGID */ -#ifdef HAVE_SETGROUPS -PyDoc_STRVAR(posix_setgroups__doc__, -"setgroups(list)\n\n\ -Set the groups of the current process to list."); + +PyDoc_STRVAR(posix_lseek__doc__, +"lseek(fd, pos, how) -> newpos\n\n\ +Set the current position of a file descriptor."); static PyObject * -posix_setgroups(PyObject *self, PyObject *groups) +posix_lseek(PyObject *self, PyObject *args) { - int i, len; - gid_t grouplist[MAX_GROUPS]; - - if (!PySequence_Check(groups)) { - PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); + 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; } - len = PySequence_Size(groups); - if (len > MAX_GROUPS) { - PyErr_SetString(PyExc_ValueError, "too many groups"); +#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; - } - 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) + if (!_PyVerify_fd(fd)) 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) + Py_BEGIN_ALLOW_THREADS + res = lseek(fd, pos, how); + Py_END_ALLOW_THREADS + if (res < 0) 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) +#if !defined(HAVE_LARGEFILE_SUPPORT) + return PyInt_FromLong(res); +#else + return PyLong_FromLongLong(res); #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."); + +PyDoc_STRVAR(posix_read__doc__, +"read(fd, buffersize) -> string\n\n\ +Read a file descriptor."); static PyObject * -posix_wait3(PyObject *self, PyObject *args) +posix_read(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)) + 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 - pid = wait3(&status, options, &ru); + n = read(fd, PyString_AsString(buffer), size); Py_END_ALLOW_THREADS - - return wait_helper(pid, WAIT_STATUS_INT(status), &ru); + if (n < 0) { + Py_DECREF(buffer); + return posix_error(); + } + if (n != size) + _PyString_Resize(&buffer, n); + return buffer; } -#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."); + +PyDoc_STRVAR(posix_write__doc__, +"write(fd, string) -> byteswritten\n\n\ +Write a string to a file descriptor."); static PyObject * -posix_wait4(PyObject *self, PyObject *args) +posix_write(PyObject *self, PyObject *args) { - pid_t pid; - int options; - struct rusage ru; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; + Py_buffer pbuf; + int fd; + Py_ssize_t size; - if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options)) + if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf)) return NULL; - + if (!_PyVerify_fd(fd)) { + PyBuffer_Release(&pbuf); + return posix_error(); + } Py_BEGIN_ALLOW_THREADS - pid = wait4(pid, &status, options, &ru); + size = write(fd, pbuf.buf, (size_t)pbuf.len); Py_END_ALLOW_THREADS - - return wait_helper(pid, WAIT_STATUS_INT(status), &ru); + PyBuffer_Release(&pbuf); + if (size < 0) + return posix_error(); + return PyInt_FromSsize_t(size); } -#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."); + +PyDoc_STRVAR(posix_fstat__doc__, +"fstat(fd) -> stat result\n\n\ +Like stat(), but for an open file descriptor."); static PyObject * -posix_waitpid(PyObject *self, PyObject *args) +posix_fstat(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)) + 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 - pid = waitpid(pid, &status, options); + res = FSTAT(fd, &st); Py_END_ALLOW_THREADS - if (pid == -1) - return posix_error(); + if (res != 0) { + return posix_error(); + } - return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); + return _pystat_fromstructstat(&st); } -#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."); +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_waitpid(PyObject *self, PyObject *args) +posix_fdopen(PyObject *self, PyObject *args) { - Py_intptr_t pid; - int status, options; + 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; - if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options)) + /* 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 - pid = _cwait(&status, pid, options); +#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 - if (pid == -1) + PyMem_FREE(mode); + if (fp == NULL) 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); + f = PyFile_FromFile(fp, "", orgmode, fclose); + if (f != NULL) + PyFile_SetBufSize(f, bufsize); + return f; } -#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."); +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_wait(PyObject *self, PyObject *noargs) +posix_isatty(PyObject *self, PyObject *args) { - pid_t pid; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; + 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) +{ + int fds[2]; + int res; Py_BEGIN_ALLOW_THREADS - pid = wait(&status); + res = pipe(fds); Py_END_ALLOW_THREADS - if (pid == -1) + if (res != 0) return posix_error(); - - return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); + return Py_BuildValue("(ii)", fds[0], fds[1]); } -#endif +#endif /* HAVE_PIPE */ -PyDoc_STRVAR(posix_lstat__doc__, -"lstat(path) -> stat result\n\n\ -Like stat(path), but do not follow symbolic links."); +#ifdef HAVE_MKFIFO +PyDoc_STRVAR(posix_mkfifo__doc__, +"mkfifo(filename [, mode=0666])\n\n\ +Create a FIFO (a POSIX named pipe)."); static PyObject * -posix_lstat(PyObject *self, PyObject *args) +posix_mkfifo(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 */ + 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 -#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."); +#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_readlink(PyObject *self, PyObject *args) +posix_mknod(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); + char *filename; + int mode = 0600; + int device = 0; + int res; + if (!PyArg_ParseTuple(args, "s|ii:mknod", &filename, &mode, &device)) 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); + res = mknod(filename, mode, device); 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; + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; } -#endif /* HAVE_READLINK */ - +#endif -#ifdef HAVE_SYMLINK -PyDoc_STRVAR(posix_symlink__doc__, -"symlink(src, dst)\n\n\ -Create a symbolic link pointing to src named dst."); +#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_symlink(PyObject *self, PyObject *args) +posix_major(PyObject *self, PyObject *args) { - return posix_2str(args, "etet:symlink", symlink); + int device; + if (!PyArg_ParseTuple(args, "i:major", &device)) + return NULL; + return PyInt_FromLong((long)major(device)); } -#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; -} +PyDoc_STRVAR(posix_minor__doc__, +"minor(device) -> minor number\n\ +Extracts a device minor number from a raw device number."); static PyObject * -posix_times(PyObject *self, PyObject *noargs) +posix_minor(PyObject *self, PyObject *args) { - /* 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); + int device; + if (!PyArg_ParseTuple(args, "i:minor", &device)) + return NULL; + return PyInt_FromLong((long)minor(device)); } -#else /* not OS2 */ -#define NEED_TICKS_PER_SECOND -static long ticks_per_second = -1; + +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_times(PyObject *self, PyObject *noargs) +posix_makedev(PyObject *self, PyObject *args) { - 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); + int major, minor; + if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor)) + return NULL; + return PyInt_FromLong((long)makedev(major, minor)); } -#endif /* not OS2 */ -#endif /* HAVE_TIMES */ +#endif /* device macros */ -#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()."); +#ifdef HAVE_FTRUNCATE +PyDoc_STRVAR(posix_ftruncate__doc__, +"ftruncate(fd, length)\n\n\ +Truncate a file to a specified length."); static PyObject * -posix_getsid(PyObject *self, PyObject *args) +posix_ftruncate(PyObject *self, PyObject *args) { - pid_t pid; - int sid; - if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid)) + int fd; + off_t length; + int res; + PyObject *lenobj; + + if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj)) return NULL; - sid = getsid(pid); - if (sid < 0) + +#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(); - return PyInt_FromLong((long)sid); + Py_INCREF(Py_None); + return Py_None; } -#endif /* HAVE_GETSID */ +#endif +#ifdef HAVE_PUTENV +PyDoc_STRVAR(posix_putenv__doc__, +"putenv(key, value)\n\n\ +Change or add an environment variable."); -#ifdef HAVE_SETSID -PyDoc_STRVAR(posix_setsid__doc__, -"setsid()\n\n\ -Call the system call setsid()."); +/* 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_setsid(PyObject *self, PyObject *noargs) +posix_putenv(PyObject *self, PyObject *args) { - if (setsid() < 0) - return posix_error(); + char *s1, *s2; + char *newenv; + PyObject *newstr; + size_t len; + + if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2)) + return NULL; + + /* 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); + } + Py_INCREF(Py_None); return Py_None; } -#endif /* HAVE_SETSID */ +#endif /* putenv */ -#ifdef HAVE_SETPGID -PyDoc_STRVAR(posix_setpgid__doc__, -"setpgid(pid, pgrp)\n\n\ -Call the system call setpgid()."); +#ifdef HAVE_UNSETENV +PyDoc_STRVAR(posix_unsetenv__doc__, +"unsetenv(key)\n\n\ +Delete an environment variable."); static PyObject * -posix_setpgid(PyObject *self, PyObject *args) +posix_unsetenv(PyObject *self, PyObject *args) { - pid_t pid; - int pgrp; - if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp)) + char *s1; + + if (!PyArg_ParseTuple(args, "s:unsetenv", &s1)) return NULL; - if (setpgid(pid, pgrp) < 0) - return posix_error(); + + 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 /* HAVE_SETPGID */ - +#endif /* unsetenv */ -#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."); +PyDoc_STRVAR(posix_strerror__doc__, +"strerror(code) -> string\n\n\ +Translate an error code to a message string."); static PyObject * -posix_tcgetpgrp(PyObject *self, PyObject *args) +posix_strerror(PyObject *self, PyObject *args) { - int fd; - pid_t pgid; - if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd)) + int code; + char *message; + if (!PyArg_ParseTuple(args, "i:strerror", &code)) return NULL; - pgid = tcgetpgrp(fd); - if (pgid < 0) - return posix_error(); - return PyLong_FromPid(pgid); + message = strerror(code); + if (message == NULL) { + PyErr_SetString(PyExc_ValueError, + "strerror() argument out of range"); + return NULL; + } + return PyString_FromString(message); } -#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."); +#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_tcsetpgrp(PyObject *self, PyObject *args) +posix_WCOREDUMP(PyObject *self, PyObject *args) { - int fd; - pid_t pgid; - if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid)) + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status))) 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 */ + return PyBool_FromLong(WCOREDUMP(status)); +} +#endif /* WCOREDUMP */ -PyDoc_STRVAR(posix_open__doc__, -"open(filename, flag [, mode=0777]) -> fd\n\n\ -Open a file (for low level IO)."); +#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_open(PyObject *self, PyObject *args) +posix_WIFCONTINUED(PyObject *self, PyObject *args) { - char *file = NULL; - int flag; - int mode = 0777; - int fd; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "eti|i", - Py_FileSystemDefaultEncoding, &file, - &flag, &mode)) + if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status))) 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); + return PyBool_FromLong(WIFCONTINUED(status)); } +#endif /* WIFCONTINUED */ - -PyDoc_STRVAR(posix_close__doc__, -"close(fd)\n\n\ -Close a file descriptor (for low level IO)."); +#ifdef WIFSTOPPED +PyDoc_STRVAR(posix_WIFSTOPPED__doc__, +"WIFSTOPPED(status) -> bool\n\n\ +Return True if the process returning 'status' was stopped."); static PyObject * -posix_close(PyObject *self, PyObject *args) +posix_WIFSTOPPED(PyObject *self, PyObject *args) { - int fd, res; - if (!PyArg_ParseTuple(args, "i:close", &fd)) + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status))) 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; -} + return PyBool_FromLong(WIFSTOPPED(status)); +} +#endif /* WIFSTOPPED */ -PyDoc_STRVAR(posix_closerange__doc__, -"closerange(fd_low, fd_high)\n\n\ -Closes all file descriptors in [fd_low, fd_high), ignoring errors."); +#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_closerange(PyObject *self, PyObject *args) +posix_WIFSIGNALED(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 */ + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; -#if !defined(HAVE_LARGEFILE_SUPPORT) - pos = PyInt_AsLong(posobj); -#else - pos = PyLong_Check(posobj) ? - PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj); -#endif - if (PyErr_Occurred()) + if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status))) 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; + return PyBool_FromLong(WIFSIGNALED(status)); } +#endif /* WIFSIGNALED */ - -PyDoc_STRVAR(posix_write__doc__, -"write(fd, string) -> byteswritten\n\n\ -Write a string to a file descriptor."); +#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_write(PyObject *self, PyObject *args) +posix_WIFEXITED(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."); + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; -static PyObject * -posix_fstat(PyObject *self, PyObject *args) -{ - int fd; - STRUCT_STAT st; - int res; - if (!PyArg_ParseTuple(args, "i:fstat", &fd)) + if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status))) 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); + return PyBool_FromLong(WIFEXITED(status)); } +#endif /* WIFEXITED */ - -PyDoc_STRVAR(posix_fdopen__doc__, -"fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\ -Return an open file object connected to a file descriptor."); +#ifdef WEXITSTATUS +PyDoc_STRVAR(posix_WEXITSTATUS__doc__, +"WEXITSTATUS(status) -> integer\n\n\ +Return the process return code from 'status'."); static PyObject * -posix_fdopen(PyObject *self, PyObject *args) +posix_WEXITSTATUS(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; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - /* 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); + if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status))) 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; -}; - -#ifndef UEFI_C_SOURCE -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; -} -#endif /* UEFI_C_SOURCE */ - -#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 -}; + return Py_BuildValue("i", WEXITSTATUS(status)); +} +#endif /* WEXITSTATUS */ -static int -conv_sysconf_confname(PyObject *arg, int *valuep) +#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) { - return conv_confname(arg, valuep, posix_constants_sysconf, - sizeof(posix_constants_sysconf) - / sizeof(struct constdef)); + 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 */ -PyDoc_STRVAR(posix_sysconf__doc__, -"sysconf(name) -> integer\n\n\ -Return an integer-valued system configuration variable."); +#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_sysconf(PyObject *self, PyObject *args) +posix_WSTOPSIG(PyObject *self, PyObject *args) { - PyObject *result = NULL; - int name; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; - if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) { - int value; + if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status))) + return NULL; - errno = 0; - value = sysconf(name); - if (value == -1 && errno != 0) - posix_error(); - else - result = PyInt_FromLong(value); - } - return result; + return Py_BuildValue("i", WSTOPSIG(status)); } -#endif +#endif /* WSTOPSIG */ +#endif /* HAVE_SYS_WAIT_H */ -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) || defined(HAVE_CONFSTR) || defined(HAVE_SYSCONF) -/* 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; +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) +#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 strcmp(c1->name, c2->name); + return v; } -static int -setup_confname_table(struct constdef *table, size_t tablesize, - char *tablename, PyObject *module) +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) { - PyObject *d = NULL; - size_t i; + int fd, res; + struct statvfs st; - qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); - d = PyDict_New(); - if (d == NULL) - return -1; + 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(); - 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 _pystatvfs_fromstructstatvfs(st); } -#endif /* HAVE_FPATHCONF || HAVE_PATHCONF || HAVE_CONFSTR || HAVE_SYSCONF */ +#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */ -/* Return -1 on failure, 0 on success. */ -static int -setup_confname_tables(PyObject *module) + +#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) { -#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; + 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 */ -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."); +#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_abort(PyObject *self, PyObject *noargs) +posix_tempnam(PyObject *self, PyObject *args) { - abort(); - /*NOTREACHED*/ - Py_FatalError("abort() called from Python code didn't abort!"); + PyObject *result = NULL; + char *dir = NULL; + char *pfx = NULL; + char *name; + + if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx)) 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."); + if (PyErr_Warn(PyExc_RuntimeWarning, + "tempnam is a potential security risk to your program") < 0) + return NULL; -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)) + if (PyErr_WarnPy3k("tempnam has been removed in 3.x; " + "use the tempfile module", 1) < 0) return NULL; - if (setresuid(ruid, euid, suid) < 0) - return posix_error(); - Py_RETURN_NONE; + + name = tempnam(dir, pfx); + if (name == NULL) + return PyErr_NoMemory(); + result = PyString_FromString(name); + free(name); + return result; } #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) +#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) { - /* We assume uid_t is no larger than a long. */ - long rgid, egid, sgid; - if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid)) + FILE *fp; + + if (PyErr_WarnPy3k("tmpfile has been removed in 3.x; " + "use the tempfile module", 1) < 0) return NULL; - if (setresgid(rgid, egid, sgid) < 0) + + fp = tmpfile(); + if (fp == NULL) return posix_error(); - Py_RETURN_NONE; + return PyFile_FromFile(fp, "", "w+b", fclose); } #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) +#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) { - 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); + 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 -#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."); +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_getresgid (PyObject *self, PyObject *noargs) +static PyObject * +posix_abort(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); + abort(); + /*NOTREACHED*/ + Py_FatalError("abort() called from Python code didn't abort!"); + return NULL; } -#endif static PyMethodDef posix_methods[] = { {"access", posix_access, METH_VARARGS, posix_access__doc__}, @@ -6897,18 +3793,6 @@ static PyMethodDef posix_methods[] = { #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__}, @@ -6916,9 +3800,6 @@ static PyMethodDef posix_methods[] = { #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 @@ -6933,38 +3814,7 @@ static PyMethodDef posix_methods[] = { #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 */ @@ -7102,18 +3952,6 @@ static PyMethodDef posix_methods[] = { {"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 */ }; @@ -7310,34 +4148,11 @@ all_ins(PyObject *d) #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; }