diff options
-rw-r--r-- | lib/libc/gen/exec.c | 133 |
1 files changed, 67 insertions, 66 deletions
diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c index ad4e2c7ca1e..0a921063b6b 100644 --- a/lib/libc/gen/exec.c +++ b/lib/libc/gen/exec.c @@ -32,7 +32,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: exec.c,v 1.4 1996/10/27 23:02:23 tholo Exp $"; +static char rcsid[] = "$OpenBSD: exec.c,v 1.5 1996/12/05 05:37:10 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -52,6 +52,40 @@ static char rcsid[] = "$OpenBSD: exec.c,v 1.4 1996/10/27 23:02:23 tholo Exp $"; extern char **environ; +static char ** +buildargv(ap, arg, envpp) + va_list ap; + const char *arg; + char ***envpp; +{ + register char **argv, **nargv; + register int memsize, off; + + argv = NULL; + for (off = memsize = 0;; ++off) { + if (off >= memsize) { + memsize += 50; /* Starts out at 0. */ + memsize *= 2; /* Ramp up fast. */ + nargv = realloc(argv, memsize * sizeof(char *)); + if (nargv == NULL) { + free(argv); + return (NULL); + } + argv = nargv; + if (off == 0) { + argv[0] = (char *)arg; + off = 1; + } + } + if (!(argv[off] = va_arg(ap, char *))) + break; + } + /* Get environment pointer if user supposed to provide one. */ + if (envpp) + *envpp = va_arg(ap, char **); + return (argv); +} + int #if __STDC__ execl(const char *name, const char *arg, ...) @@ -63,31 +97,21 @@ execl(name, arg, va_alist) #endif { va_list ap; + int sverrno; char **argv; - int i; - -#if __STDC__ - va_start(ap, arg); -#else - va_start(ap); -#endif - for (i = 1; va_arg(ap, char *) != NULL; i++) - ; - va_end(ap); - argv = alloca (i * sizeof (char *)); - #if __STDC__ va_start(ap, arg); #else va_start(ap); #endif - argv[0] = (char *) arg; - for (i = 1; (argv[i] = (char *) va_arg(ap, char *)) != NULL; i++) - ; + if ((argv = buildargv(ap, arg, NULL))) + (void)execve(name, argv, environ); va_end(ap); - - return execve(name, argv, environ); + sverrno = errno; + free(argv); + errno = sverrno; + return (-1); } int @@ -101,32 +125,21 @@ execle(name, arg, va_alist) #endif { va_list ap; + int sverrno; char **argv, **envp; - int i; #if __STDC__ va_start(ap, arg); #else va_start(ap); #endif - for (i = 1; va_arg(ap, char *) != NULL; i++) - ; + if ((argv = buildargv(ap, arg, &envp))) + (void)execve(name, argv, envp); va_end(ap); - - argv = alloca (i * sizeof (char *)); - -#if __STDC__ - va_start(ap, arg); -#else - va_start(ap); -#endif - argv[0] = (char *) arg; - for (i = 1; (argv[i] = (char *) va_arg(ap, char *)) != NULL; i++) - ; - envp = (char **) va_arg(ap, char **); - va_end(ap); - - return execve(name, argv, envp); + sverrno = errno; + free(argv); + errno = sverrno; + return (-1); } int @@ -140,31 +153,21 @@ execlp(name, arg, va_alist) #endif { va_list ap; + int sverrno; char **argv; - int i; #if __STDC__ va_start(ap, arg); #else va_start(ap); #endif - for (i = 1; va_arg(ap, char *) != NULL; i++) - ; + if ((argv = buildargv(ap, arg, NULL))) + (void)execvp(name, argv); va_end(ap); - - argv = alloca (i * sizeof (char *)); - -#if __STDC__ - va_start(ap, arg); -#else - va_start(ap); -#endif - argv[0] = (char *) arg; - for (i = 1; (argv[i] = va_arg(ap, char *)) != NULL; i++) - ; - va_end(ap); - - return execvp(name, argv); + sverrno = errno; + free(argv); + errno = sverrno; + return (-1); } int @@ -172,7 +175,8 @@ execv(name, argv) const char *name; char * const *argv; { - return execve(name, argv, environ); + (void)execve(name, argv, environ); + return (-1); } int @@ -180,8 +184,7 @@ execvp(name, argv) const char *name; char * const *argv; { - static int memsize; - static char **memp; + char **memp; register int cnt, lp, ln; register char *p; int eacces = 0, etxtbsy = 0; @@ -193,7 +196,7 @@ execvp(name, argv) if (name == NULL || *name == '\0') { errno = ENOENT; return (-1); - } + } /* If it's an absolute or relative path name, it's easy. */ if (strchr(name, '/')) { @@ -208,7 +211,7 @@ execvp(name, argv) path = _PATH_DEFPATH; cur = path = strdup(path); - while (p = strsep(&cur, ":")) { + while ((p = strsep(&cur, ":"))) { /* * It's a SHELL path -- double, leading and trailing colons * mean the current directory. @@ -244,18 +247,16 @@ retry: (void)execve(bp, argv, environ); case ENOENT: break; case ENOEXEC: - for (cnt = 0; argv[cnt]; ++cnt); - if ((cnt + 2) * sizeof(char *) > memsize) { - memsize = (cnt + 2) * sizeof(char *); - if ((memp = realloc(memp, memsize)) == NULL) { - memsize = 0; - goto done; - } - } + for (cnt = 0; argv[cnt]; ++cnt) + ; + memp = malloc((cnt + 2) * sizeof(char *)); + if (memp == NULL) + goto done; memp[0] = "sh"; memp[1] = bp; bcopy(argv + 1, memp + 2, cnt * sizeof(char *)); (void)execve(_PATH_BSHELL, memp, environ); + free(memp); goto done; case ETXTBSY: if (etxtbsy < 3) |