summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/gen/exec.c')
-rw-r--r--lib/libc/gen/exec.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c
index 72b6db4..c083957 100644
--- a/lib/libc/gen/exec.c
+++ b/lib/libc/gen/exec.c
@@ -32,11 +32,16 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
+#endif
+static const char rcsid[] =
+ "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
@@ -187,10 +192,11 @@ execvp(name, argv)
char **memp;
register int cnt, lp, ln;
register char *p;
- int eacces, etxtbsy;
+ int eacces, save_errno;
char *bp, *cur, *path, buf[MAXPATHLEN];
+ struct stat sb;
- eacces = etxtbsy = 0;
+ eacces = 0;
/* If it's an absolute or relative path name, it's easy. */
if (index(name, '/')) {
@@ -241,9 +247,10 @@ execvp(name, argv)
retry: (void)execve(bp, argv, environ);
switch(errno) {
- case EACCES:
- eacces = 1;
- break;
+ case E2BIG:
+ goto done;
+ case ELOOP:
+ case ENAMETOOLONG:
case ENOENT:
break;
case ENOEXEC:
@@ -258,17 +265,37 @@ retry: (void)execve(bp, argv, environ);
(void)execve(_PATH_BSHELL, memp, environ);
free(memp);
goto done;
+ case ENOMEM:
+ goto done;
+ case ENOTDIR:
+ break;
case ETXTBSY:
- if (etxtbsy < 3)
- (void)sleep(++etxtbsy);
- goto retry;
+ /*
+ * We used to retry here, but sh(1) doesn't.
+ */
+ goto done;
default:
+ /*
+ * EACCES may be for an inaccessible directory or
+ * a non-executable file. Call stat() to decide
+ * which. This also handles ambiguities for EFAULT
+ * and EIO, and undocumented errors like ESTALE.
+ * We hope that the race for a stat() is unimportant.
+ */
+ save_errno = errno;
+ if (stat(argv[0], &sb) != 0)
+ break;
+ if (save_errno == EACCES) {
+ eacces = 1;
+ continue;
+ }
+ errno = save_errno;
goto done;
}
}
if (eacces)
errno = EACCES;
- else if (!errno)
+ else
errno = ENOENT;
done: if (path)
free(path);
OpenPOWER on IntegriCloud