diff options
author | peter <peter@FreeBSD.org> | 1999-03-23 16:40:34 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1999-03-23 16:40:34 +0000 |
commit | 578ecf706ca430d14a8acbe37b6fc416d8a19caf (patch) | |
tree | 38d1a5c190ac2dc8e7cb2a6194e42b203779142f /lib | |
parent | e1c9acedca824cb3a177d665495a51bcebd0763a (diff) | |
download | FreeBSD-src-578ecf706ca430d14a8acbe37b6fc416d8a19caf.zip FreeBSD-src-578ecf706ca430d14a8acbe37b6fc416d8a19caf.tar.gz |
Remove last remaining references to malloc/realloc and functions that
call them. All the execX() libc functions should be vfork() safe now.
Specifically:
- execlp() does the argument count-and-build into a vector from alloca
(like the others) - buildargv() is no longer used (and gone).
- execvp() uses alloca/strcpy rather than strdup().
- the ENOEXEC handler uses alloca rather than malloc.
- a couple of free() calls removed - alloca works on the local stack and
the allocations are freed on function exit (which is why buildargv
wasn't useful - it's alloca() context would disappear on return).
Along the way:
- If alloca() fails (can it?), set errno = ENOMEM explicitly.
- The ENOEXEC recovery routine that trys again with /bin/sh appeared to
not be terminating the new argv[] array for /bin/sh, allowing it to
walk off the end of the list.
I dithered a bit about using alloca() even more as it's most commonly
associated with gcc. However, standalone portable (using malloc) and
machine-specific assembler alloca implementations appear to be available
on just about all the architectures we're likely to want to port to.
alloca will be the least of our problems if ever going to another compiler.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/gen/exec.c | 90 |
1 files changed, 40 insertions, 50 deletions
diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c index 6b19842..467be81 100644 --- a/lib/libc/gen/exec.c +++ b/lib/libc/gen/exec.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93"; #endif static const char rcsid[] = - "$Id: exec.c,v 1.9 1998/10/14 20:23:40 des Exp $"; + "$Id: exec.c,v 1.10 1998/10/15 17:14:15 des Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -57,40 +57,6 @@ static const char rcsid[] = 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, ...) @@ -115,8 +81,10 @@ execl(name, arg, va_alist) n++; va_end(ap); argv = alloca((n + 1) * sizeof(*argv)); - if (argv == NULL) + if (argv == NULL) { + errno = ENOMEM; return (-1); + } #if __STDC__ va_start(ap, arg); #else @@ -154,8 +122,10 @@ execle(name, arg, va_alist) n++; va_end(ap); argv = alloca((n + 1) * sizeof(*argv)); - if (argv == NULL) + if (argv == NULL) { + errno = ENOMEM; return (-1); + } #if __STDC__ va_start(ap, arg); #else @@ -183,19 +153,33 @@ execlp(name, arg, va_alist) va_list ap; int sverrno; char **argv; + int n; #if __STDC__ va_start(ap, arg); #else va_start(ap); #endif - if ( (argv = buildargv(ap, arg, NULL)) ) - (void)execvp(name, argv); + n = 1; + while (va_arg(ap, char *) != NULL) + n++; va_end(ap); - sverrno = errno; - free(argv); - errno = sverrno; - return (-1); + argv = alloca((n + 1) * sizeof(*argv)); + if (argv == NULL) { + errno = ENOMEM; + return (-1); + } +#if __STDC__ + va_start(ap, arg); +#else + va_start(ap); +#endif + n = 1; + argv[0] = (char *)arg; + while ((argv[n] = va_arg(ap, char *)) != NULL) + n++; + va_end(ap); + return (execvp(name, argv)); } int @@ -238,8 +222,13 @@ execvp(name, argv) /* Get the path we're searching. */ if (!(path = getenv("PATH"))) path = _PATH_DEFPATH; - cur = path = strdup(path); - + cur = alloca(strlen(path) + 1); + if (cur == NULL) { + errno = ENOMEM; + return (-1); + } + strcpy(cur, path); + path = cur; while ( (p = strsep(&cur, ":")) ) { /* * It's a SHELL path -- double, leading and trailing colons @@ -279,14 +268,16 @@ retry: (void)execve(bp, argv, environ); case ENOEXEC: for (cnt = 0; argv[cnt]; ++cnt) ; - memp = malloc((cnt + 2) * sizeof(char *)); - if (memp == NULL) + memp = alloca((cnt + 3) * sizeof(char *)); + if (memp == NULL) { + /* errno = ENOMEM; XXX override ENOEXEC? */ goto done; + } memp[0] = "sh"; memp[1] = bp; bcopy(argv + 1, memp + 2, cnt * sizeof(char *)); + memp[cnt + 2] = NULL; (void)execve(_PATH_BSHELL, memp, environ); - free(memp); goto done; case ENOMEM: goto done; @@ -320,7 +311,6 @@ retry: (void)execve(bp, argv, environ); errno = EACCES; else errno = ENOENT; -done: if (path) - free(path); +done: return (-1); } |