diff options
author | Ulrich Drepper <drepper@redhat.com> | 2009-06-02 07:03:02 -0700 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-06-02 07:03:02 -0700 |
commit | 3d5243d4160519e56cba6eceae9b1d0e6b642515 (patch) | |
tree | 0a604dc10d26cd8d340eaeba814abd6cbf8bbe0c /posix/execvp.c | |
parent | fd96f062085be71f4e2c07c98a3002bd55793b6e (diff) | |
download | glibc-3d5243d4160519e56cba6eceae9b1d0e6b642515.tar.gz glibc-3d5243d4160519e56cba6eceae9b1d0e6b642515.tar.xz glibc-3d5243d4160519e56cba6eceae9b1d0e6b642515.zip |
Implement execvpe.
There is some existing practice in other OSes and it's trivial to implement giving the existing code. Fixes BZ #10221.
Diffstat (limited to 'posix/execvp.c')
-rw-r--r-- | posix/execvp.c | 192 |
1 files changed, 2 insertions, 190 deletions
diff --git a/posix/execvp.c b/posix/execvp.c index 887379e3a2..81e6d589f1 100644 --- a/posix/execvp.c +++ b/posix/execvp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92, 1995-99, 2002, 2004, 2005, 2007 +/* Copyright (C) 1991,92, 1995-99, 2002, 2004, 2005, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,31 +17,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include <alloca.h> #include <unistd.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <paths.h> - - -/* The file is accessible but it is not an executable file. Invoke - the shell to interpret it as a script. */ -static void -internal_function -scripts_argv (const char *file, char *const argv[], int argc, char **new_argv) -{ - /* Construct an argument list for the shell. */ - new_argv[0] = (char *) _PATH_BSHELL; - new_argv[1] = (char *) file; - while (argc > 1) - { - new_argv[argc] = argv[argc - 1]; - --argc; - } -} /* Execute FILE, searching in the `PATH' environment variable if it contains @@ -51,170 +27,6 @@ execvp (file, argv) const char *file; char *const argv[]; { - if (*file == '\0') - { - /* We check the simple case first. */ - __set_errno (ENOENT); - return -1; - } - - if (strchr (file, '/') != NULL) - { - /* Don't search when it contains a slash. */ - __execve (file, argv, __environ); - - if (errno == ENOEXEC) - { - /* Count the arguments. */ - int argc = 0; - while (argv[argc++]) - ; - size_t len = (argc + 1) * sizeof (char *); - char **script_argv; - void *ptr = NULL; - if (__libc_use_alloca (len)) - script_argv = alloca (len); - else - script_argv = ptr = malloc (len); - - if (script_argv != NULL) - { - scripts_argv (file, argv, argc, script_argv); - __execve (script_argv[0], script_argv, __environ); - - free (ptr); - } - } - } - else - { - size_t pathlen; - size_t alloclen = 0; - char *path = getenv ("PATH"); - if (path == NULL) - { - pathlen = confstr (_CS_PATH, (char *) NULL, 0); - alloclen = pathlen + 1; - } - else - pathlen = strlen (path); - - size_t len = strlen (file) + 1; - alloclen += pathlen + len + 1; - - char *name; - char *path_malloc = NULL; - if (__libc_use_alloca (alloclen)) - name = alloca (alloclen); - else - { - path_malloc = name = malloc (alloclen); - if (name == NULL) - return -1; - } - - if (path == NULL) - { - /* There is no `PATH' in the environment. - The default search path is the current directory - followed by the path `confstr' returns for `_CS_PATH'. */ - path = name + pathlen + len + 1; - path[0] = ':'; - (void) confstr (_CS_PATH, path + 1, pathlen); - } - - /* Copy the file name at the top. */ - name = (char *) memcpy (name + pathlen + 1, file, len); - /* And add the slash. */ - *--name = '/'; - - char **script_argv = NULL; - void *script_argv_malloc = NULL; - bool got_eacces = false; - char *p = path; - do - { - char *startp; - - path = p; - p = __strchrnul (path, ':'); - - if (p == path) - /* Two adjacent colons, or a colon at the beginning or the end - of `PATH' means to search the current directory. */ - startp = name + 1; - else - startp = (char *) memcpy (name - (p - path), path, p - path); - - /* Try to execute this name. If it works, execve will not return. */ - __execve (startp, argv, __environ); - - if (errno == ENOEXEC) - { - if (script_argv == NULL) - { - /* Count the arguments. */ - int argc = 0; - while (argv[argc++]) - ; - size_t arglen = (argc + 1) * sizeof (char *); - if (__libc_use_alloca (alloclen + arglen)) - script_argv = alloca (arglen); - else - script_argv = script_argv_malloc = malloc (arglen); - if (script_argv == NULL) - { - /* A possible EACCES error is not as important as - the ENOMEM. */ - got_eacces = false; - break; - } - scripts_argv (startp, argv, argc, script_argv); - } - - __execve (script_argv[0], script_argv, __environ); - } - - switch (errno) - { - case EACCES: - /* Record the we got a `Permission denied' error. If we end - up finding no executable we can use, we want to diagnose - that we did find one but were denied access. */ - got_eacces = true; - case ENOENT: - case ESTALE: - case ENOTDIR: - /* Those errors indicate the file is missing or not executable - by us, in which case we want to just try the next path - directory. */ - case ENODEV: - case ETIMEDOUT: - /* Some strange filesystems like AFS return even - stranger error numbers. They cannot reasonably mean - anything else so ignore those, too. */ - break; - - default: - /* Some other error means we found an executable file, but - something went wrong executing it; return the error to our - caller. */ - return -1; - } - } - while (*p++ != '\0'); - - /* We tried every element and none of them worked. */ - if (got_eacces) - /* At least one failure was due to permissions, so report that - error. */ - __set_errno (EACCES); - - free (script_argv_malloc); - free (path_malloc); - } - - /* Return the error from the last attempt (probably ENOENT). */ - return -1; + return __execvpe (file, argv, __environ); } libc_hidden_def (execvp) |