Index: Lib/os.py =================================================================== --- Lib/os.py (revision 52316) +++ Lib/os.py (working copy) @@ -308,6 +308,13 @@ except NameError: environ = {} +def _exists(name): + try: + eval(name) + return True + except NameError: + return False + def execl(file, *args): """execl(file, *args) @@ -339,22 +346,23 @@ env = args[-1] execvpe(file, args[:-1], env) -def execvp(file, args): - """execp(file, args) +if not _exists("execvp"): + def execvp(file, args): + """execp(file, args) - Execute the executable file (which is searched for along $PATH) - with argument list args, replacing the current process. - args may be a list or tuple of strings. """ - _execvpe(file, args) + Execute the executable file (which is searched for along $PATH) + with argument list args, replacing the current process. + args may be a list or tuple of strings. """ + _execvpe(file, args) -def execvpe(file, args, env): - """execvpe(file, args, env) + def execvpe(file, args, env): + """execvpe(file, args, env) - Execute the executable file (which is searched for along $PATH) - with argument list args and environment env , replacing the - current process. - args may be a list or tuple of strings. """ - _execvpe(file, args, env) + Execute the executable file (which is searched for along $PATH) + with argument list args and environment env , replacing the + current process. + args may be a list or tuple of strings. """ + _execvpe(file, args, env) __all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) @@ -505,13 +513,6 @@ return environ.get(key, default) __all__.append("getenv") -def _exists(name): - try: - eval(name) - return True - except NameError: - return False - # Supply spawn*() (probably only for Unix) if _exists("fork") and not _exists("spawnv") and _exists("execv"): Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 52316) +++ Modules/posixmodule.c (working copy) @@ -123,7 +123,9 @@ #ifdef _MSC_VER /* Microsoft compiler */ #define HAVE_GETCWD 1 #define HAVE_SPAWNV 1 +#define HAVE_SPAWNVP 1 #define HAVE_EXECV 1 +#define HAVE_EXECVP 1 #define HAVE_PIPE 1 #define HAVE_POPEN 1 #define HAVE_SYSTEM 1 @@ -2836,6 +2838,220 @@ #endif /* HAVE_EXECV */ +#ifdef HAVE_EXECVP +PyDoc_STRVAR(posix_execvp__doc__, +"execvp(file, args)\n\n\ +Execute the executable file (which is searched for along $PATH)\n\ +with argument list args, replacing the current process.\n\ +\n\ + file: name of executable file\n\ + args: tuple or list of strings"); + +static PyObject * +posix_execvp(PyObject *self, PyObject *args) +{ + char *path; + PyObject *argv; + char **argvlist; + Py_ssize_t i, argc; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + + /* execvp has two arguments: (path, argv), where + argv is a list or tuple of strings. */ + + if (!PyArg_ParseTuple(args, "etO:execvp", + Py_FileSystemDefaultEncoding, + &path, &argv)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, "execvp() arg 2 must be a tuple or list"); + PyMem_Free(path); + return NULL; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyMem_Free(path); + return PyErr_NoMemory(); + } + for (i = 0; i < argc; i++) { + if (!PyArg_Parse((*getitem)(argv, i), "et", + Py_FileSystemDefaultEncoding, + &argvlist[i])) { + free_string_array(argvlist, i); + PyErr_SetString(PyExc_TypeError, + "execvp() arg 2 must contain only strings"); + PyMem_Free(path); + return NULL; + + } + } + argvlist[argc] = NULL; + + execvp(path, argvlist); + + /* If we get here it's definitely an error */ + + free_string_array(argvlist, argc); + PyMem_Free(path); + return posix_error(); +} + + +PyDoc_STRVAR(posix_execvpe__doc__, +"execvpe(path, args, env)\n\n\ +Execute the executable file (which is searched for along $PATH)\n\ +with argument list args and environment env, replacing the\n\ +current process.\n\ +\n\ + path: name of executable file\n\ + args: tuple or list of arguments\n\ + env: dictionary of strings mapping to strings"); + +static PyObject * +posix_execvpe(PyObject *self, PyObject *args) +{ + char *path; + PyObject *argv, *env; + char **argvlist; + char **envlist; + PyObject *key, *val, *keys=NULL, *vals=NULL; + Py_ssize_t i, pos, argc, envc; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + Py_ssize_t lastarg = 0; + + /* execvpe has three arguments: (path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyArg_ParseTuple(args, "etOO:execvpe", + Py_FileSystemDefaultEncoding, + &path, &argv, &env)) + return NULL; + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "execvpe() arg 2 must be a tuple or list"); + goto fail_0; + } + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "execvpe() arg 3 must be a mapping object"); + goto fail_0; + } + + argvlist = PyMem_NEW(char *, argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + goto fail_0; + } + for (i = 0; i < argc; i++) { + if (!PyArg_Parse((*getitem)(argv, i), + "et;execvpe() arg 2 must contain only strings", + Py_FileSystemDefaultEncoding, + &argvlist[i])) + { + lastarg = i; + goto fail_1; + } + } + lastarg = argc; + argvlist[argc] = NULL; + + i = PyMapping_Size(env); + if (i < 0) + goto fail_1; + envlist = PyMem_NEW(char *, i + 1); + if (envlist == NULL) { + PyErr_NoMemory(); + goto fail_1; + } + envc = 0; + keys = PyMapping_Keys(env); + vals = PyMapping_Values(env); + if (!keys || !vals) + goto fail_2; + if (!PyList_Check(keys) || !PyList_Check(vals)) { + PyErr_SetString(PyExc_TypeError, + "execvpe(): env.keys() or env.values() is not a list"); + goto fail_2; + } + + for (pos = 0; pos < i; pos++) { + char *p, *k, *v; + size_t len; + + key = PyList_GetItem(keys, pos); + val = PyList_GetItem(vals, pos); + if (!key || !val) + goto fail_2; + + if (!PyArg_Parse( + key, + "s;execvpe() arg 3 contains a non-string key", + &k) || + !PyArg_Parse( + val, + "s;execvpe() arg 3 contains a non-string value", + &v)) + { + goto fail_2; + } + +#if defined(PYOS_OS2) + /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */ + if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) { +#endif + len = PyString_Size(key) + PyString_Size(val) + 2; + p = PyMem_NEW(char, len); + if (p == NULL) { + PyErr_NoMemory(); + goto fail_2; + } + PyOS_snprintf(p, len, "%s=%s", k, v); + envlist[envc++] = p; +#if defined(PYOS_OS2) + } +#endif + } + envlist[envc] = 0; + + execvpe(path, argvlist, envlist); + + /* If we get here it's definitely an error */ + + (void) posix_error(); + + fail_2: + while (--envc >= 0) + PyMem_DEL(envlist[envc]); + PyMem_DEL(envlist); + fail_1: + free_string_array(argvlist, lastarg); + Py_XDECREF(vals); + Py_XDECREF(keys); + fail_0: + PyMem_Free(path); + return NULL; +} +#endif /* HAVE_EXECVP */ + + #ifdef HAVE_SPAWNV PyDoc_STRVAR(posix_spawnv__doc__, "spawnv(mode, path, args)\n\n\ @@ -3078,7 +3294,7 @@ } /* OS/2 supports spawnvp & spawnvpe natively */ -#if defined(PYOS_OS2) +#if defined(PYOS_OS2) || defined(HAVE_SPAWNVP) PyDoc_STRVAR(posix_spawnvp__doc__, "spawnvp(mode, file, args)\n\n\ Execute the program 'file' in a new process, using the environment\n\ @@ -3300,7 +3516,7 @@ PyMem_Free(path); return res; } -#endif /* PYOS_OS2 */ +#endif /* PYOS_OS2 || HAVE_SPAWNVP */ #endif /* HAVE_SPAWNV */ @@ -7999,13 +8215,17 @@ {"execv", posix_execv, METH_VARARGS, posix_execv__doc__}, {"execve", posix_execve, METH_VARARGS, posix_execve__doc__}, #endif /* HAVE_EXECV */ +#ifdef HAVE_EXECVP + {"execvp", posix_execvp, METH_VARARGS, posix_execvp__doc__}, + {"execvpe", posix_execvpe, METH_VARARGS, posix_execvpe__doc__}, +#endif /* HAVE_EXECVP */ #ifdef HAVE_SPAWNV {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__}, {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__}, -#if defined(PYOS_OS2) +#if defined(PYOS_OS2) || defined(HAVE_SPAWNVP) {"spawnvp", posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__}, {"spawnvpe", posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__}, -#endif /* PYOS_OS2 */ +#endif /* PYOS_OS2 || HAVE_SPAWNVP */ #endif /* HAVE_SPAWNV */ #ifdef HAVE_FORK1 {"fork1", posix_fork1, METH_NOARGS, posix_fork1__doc__},