diff options
author | Roland McGrath <roland@gnu.org> | 1995-04-03 09:00:10 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1995-04-03 09:00:10 +0000 |
commit | c4bf5a3e9a6bddb74d649a7d687111f7c2df04e1 (patch) | |
tree | 8d812046a186ae4dc885ee981ba310d524147466 /posix/execvp.c | |
parent | e607b492e56e2fc3c08e72d5a58349354a584cf2 (diff) | |
download | glibc-c4bf5a3e9a6bddb74d649a7d687111f7c2df04e1.tar.gz |
* posix/execvp.c: Don't use stat to search path; just try execv
until it works.
Diffstat (limited to 'posix/execvp.c')
-rw-r--r-- | posix/execvp.c | 67 |
1 files changed, 22 insertions, 45 deletions
diff --git a/posix/execvp.c b/posix/execvp.c index 01ae0d10a9..723e7fa503 100644 --- a/posix/execvp.c +++ b/posix/execvp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,34 +16,25 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <ansidecl.h> #include <unistd.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> -#include <sys/stat.h> -#include <limits.h> -#include <sys/types.h> - -#ifndef HAVE_GNU_LD -#define __environ environ -#endif /* Execute FILE, searching in the `PATH' environment variable if it contains no slashes, with arguments ARGV and environment from `environ'. */ int -DEFUN(execvp, (file, argv), CONST char *file AND char *CONST argv[]) +execvp (file, argv) + const char *file; + char *const argv[]; { - if (strchr (file, '/') == NULL) + if (strchr (file, '/') != NULL) + /* Don't search when it contains a slash. */ + return execv (file, argv); + else { - char *path, *p; - struct stat st; + char *path, *p, *name; size_t len; - uid_t uid; - gid_t gid; - int ngroups; - gid_t groups[NGROUPS_MAX]; - char *name; path = getenv ("PATH"); if (path == NULL) @@ -59,9 +50,6 @@ DEFUN(execvp, (file, argv), CONST char *file AND char *CONST argv[]) len = strlen (file) + 1; name = __alloca (strlen (path) + len); - uid = geteuid (); - gid = getegid (); - ngroups = getgroups (sizeof (groups) / sizeof (groups[0]), groups); p = path; do { @@ -81,32 +69,21 @@ DEFUN(execvp, (file, argv), CONST char *file AND char *CONST argv[]) name[p - path] = '/'; (void) memcpy (&name[(p - path) + 1], file, len); } - if (stat (name, &st) == 0 && S_ISREG (st.st_mode)) - { - int bit = S_IXOTH; - if (st.st_uid == uid) - bit = S_IXUSR; - else if (st.st_gid == gid) - bit = S_IXGRP; - else - { - register int i; - for (i = 0; i < ngroups; ++i) - if (st.st_gid == groups[i]) - { - bit = S_IXGRP; - break; - } - } - if (st.st_mode & bit) - { - file = name; - break; - } - } + + /* Try to execute this name. If it works, execv will not return. */ + execv (name, argv); + if (errno != ENOENT && errno != EACCES) + /* Those errors indicate the file is missing or not executable + by us, in which case we want to just try the next path + directory. 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'); } - return __execve (file, argv, __environ); + /* We tried every element and none of them worked. + Return the error from the last attempt (probably ENOENT). */ + return -1; } |