diff options
| author | Bruce Evans <bde@FreeBSD.org> | 1997-10-14 07:23:16 +0000 |
|---|---|---|
| committer | Bruce Evans <bde@FreeBSD.org> | 1997-10-14 07:23:16 +0000 |
| commit | 1df595f25dae340c439be4d028cbb72a0894e1a6 (patch) | |
| tree | ec650375e10a3d64a0455f61db291fae0e549e4a /lib/libc/gen/exec.c | |
| parent | 7c66fb14b3bf04a36e736396f807fcbfa149c40d (diff) | |
Notes
Diffstat (limited to 'lib/libc/gen/exec.c')
| -rw-r--r-- | lib/libc/gen/exec.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c index 72b6db43b1da..c083957c4d9c 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); |
