aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--posix/execvp.c67
2 files changed, 25 insertions, 45 deletions
diff --git a/ChangeLog b/ChangeLog
index 1f6e98a6b6..88babc2b39 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
Sun Apr 2 13:13:52 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+ * posix/execvp.c: Don't use stat to search path; just try execv
+ until it works.
+
* sysdeps/mach/hurd/i386/trampoline.c: Add a link to
SS->active_resources, so that _hurdsig_longjmp_from_handler will
be called when a longjmp unwinds the signal frame.
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;
}