4.4lite2, safely uses malloc, with freebsd fixes too
authorderaadt <deraadt@openbsd.org>
Thu, 5 Dec 1996 05:37:10 +0000 (05:37 +0000)
committerderaadt <deraadt@openbsd.org>
Thu, 5 Dec 1996 05:37:10 +0000 (05:37 +0000)
lib/libc/gen/exec.c

index ad4e2c7..0a92106 100644 (file)
@@ -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)