diff options
author | Roland McGrath <roland@gnu.org> | 2005-02-16 10:56:35 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2005-02-16 10:56:35 +0000 |
commit | c82d3c397924234b88ee620270b20a56630357ea (patch) | |
tree | 436cc1751348dec1888deaf76a78b7eae608b4fa /posix | |
parent | 877ed680f90948e43af92e2de4568826c2323077 (diff) | |
download | glibc-c82d3c397924234b88ee620270b20a56630357ea.tar.gz glibc-c82d3c397924234b88ee620270b20a56630357ea.tar.xz glibc-c82d3c397924234b88ee620270b20a56630357ea.zip |
2005-01-27 Jakub Jelinek <jakub@redhat.com>
* posix/execvp.c: Include stdbool.h.
Diffstat (limited to 'posix')
-rw-r--r-- | posix/execvp.c | 96 |
1 files changed, 66 insertions, 30 deletions
diff --git a/posix/execvp.c b/posix/execvp.c index d6f60c02e7..a79d4a89c5 100644 --- a/posix/execvp.c +++ b/posix/execvp.c @@ -18,6 +18,7 @@ #include <unistd.h> #include <stdarg.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <errno.h> @@ -26,9 +27,9 @@ /* The file is accessible but it is not an executable file. Invoke the shell to interpret it as a script. */ -static void +static char ** internal_function -script_execute (const char *file, char *const argv[]) +allocate_scripts_argv (const char *file, char *const argv[]) { /* Count the arguments. */ int argc = 0; @@ -36,19 +37,19 @@ script_execute (const char *file, char *const argv[]) ; /* Construct an argument list for the shell. */ - { - char *new_argv[argc + 1]; - new_argv[0] = (char *) _PATH_BSHELL; - new_argv[1] = (char *) file; - while (argc > 1) - { - new_argv[argc] = argv[argc - 1]; - --argc; - } - - /* Execute the shell. */ - __execve (new_argv[0], new_argv, __environ); - } + char **new_argv = (char **) malloc ((argc + 1) * sizeof (char *)); + if (new_argv != NULL) + { + new_argv[0] = (char *) _PATH_BSHELL; + new_argv[1] = (char *) file; + while (argc > 1) + { + new_argv[argc] = argv[argc - 1]; + --argc; + } + } + + return new_argv; } @@ -66,42 +67,58 @@ execvp (file, argv) return -1; } + char **script_argv = NULL; + if (strchr (file, '/') != NULL) { /* Don't search when it contains a slash. */ __execve (file, argv, __environ); if (errno == ENOEXEC) - script_execute (file, argv); + { + script_argv = allocate_scripts_argv (file, argv); + if (script_argv != NULL) + { + __execve (script_argv[0], script_argv, __environ); + + free (script_argv); + } + } } else { - int got_eacces = 0; - char *path, *p, *name; - size_t len; - size_t pathlen; - - path = getenv ("PATH"); + char *path = getenv ("PATH"); + bool path_malloc = false; 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'. */ - len = confstr (_CS_PATH, (char *) NULL, 0); - path = (char *) __alloca (1 + len); + size_t len = confstr (_CS_PATH, (char *) NULL, 0); + path = (char *) malloc (1 + len); + if (path == NULL) + return -1; path[0] = ':'; (void) confstr (_CS_PATH, path + 1, len); + path_malloc = true; } - len = strlen (file) + 1; - pathlen = strlen (path); - name = __alloca (pathlen + len + 1); + size_t len = strlen (file) + 1; + size_t pathlen = strlen (path); + char *name = malloc (pathlen + len + 1); + if (name == NULL) + { + if (path_malloc) + free (path); + return -1; + } /* Copy the file name at the top. */ name = (char *) memcpy (name + pathlen + 1, file, len); /* And add the slash. */ *--name = '/'; - p = path; + bool got_eacces = false; + char *p = path; do { char *startp; @@ -120,7 +137,21 @@ execvp (file, argv) __execve (startp, argv, __environ); if (errno == ENOEXEC) - script_execute (startp, argv); + { + if (script_argv == NULL) + { + script_argv = allocate_scripts_argv (file, argv); + if (script_argv == NULL) + { + /* A possible EACCES error is not as important as + the ENOMEM. */ + got_eacces = false; + break; + } + } + + __execve (script_argv[0], script_argv, __environ); + } switch (errno) { @@ -128,7 +159,7 @@ execvp (file, argv) /* 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 = 1; + got_eacces = true; case ENOENT: case ESTALE: case ENOTDIR: @@ -156,6 +187,11 @@ execvp (file, argv) /* At least one failure was due to permissions, so report that error. */ __set_errno (EACCES); + + free (script_argv); + free (name); + if (path_malloc) + free (path); } /* Return the error from the last attempt (probably ENOENT). */ |