172db608eSbostic /*- 272db608eSbostic * Copyright (c) 1991 The Regents of the University of California. 372db608eSbostic * All rights reserved. 472db608eSbostic * 572db608eSbostic * %sccs.include.redist.c% 6f8f88d12Swnj */ 772db608eSbostic 872db608eSbostic #if defined(LIBC_SCCS) && !defined(lint) 9*3c93bb12Sbostic static char sccsid[] = "@(#)exec.c 5.8 (Berkeley) 03/15/91"; 1072db608eSbostic #endif /* LIBC_SCCS and not lint */ 1172db608eSbostic 1272db608eSbostic #include <sys/param.h> 1372db608eSbostic #include <sys/types.h> 14f8f88d12Swnj #include <errno.h> 155ba59b7eSdonn #include <unistd.h> 1672db608eSbostic #include <stdlib.h> 179e1dd68bSdonn #if __STDC__ 1872db608eSbostic #include <stdarg.h> 199e1dd68bSdonn #else 209e1dd68bSdonn #include <varargs.h> 219e1dd68bSdonn #endif 2272db608eSbostic #include <string.h> 2372db608eSbostic #include <stdio.h> 2472db608eSbostic #include <paths.h> 25f8f88d12Swnj 2672db608eSbostic extern char **environ; 27f8f88d12Swnj 289e1dd68bSdonn static char ** 299e1dd68bSdonn buildargv(ap, arg, envpp) 309e1dd68bSdonn va_list ap; 319e1dd68bSdonn const char *arg; 329e1dd68bSdonn char ***envpp; 33f8f88d12Swnj { 3472db608eSbostic register size_t max, off; 35e2415f6eSbostic register char **argv = NULL; 36f8f88d12Swnj 3772db608eSbostic for (off = max = 0;; ++off) { 3872db608eSbostic if (off >= max) { 3972db608eSbostic max += 50; /* Starts out at 0. */ 4072db608eSbostic max *= 2; /* Ramp up fast. */ 4172db608eSbostic if (!(argv = realloc(argv, max * sizeof(char *)))) 4272db608eSbostic return(NULL); 4372db608eSbostic if (off == 0) { 4472db608eSbostic argv[0] = (char *)arg; 4572db608eSbostic off = 1; 46f8f88d12Swnj } 47f8f88d12Swnj } 4872db608eSbostic if (!(argv[off] = va_arg(ap, char *))) 49f8f88d12Swnj break; 5072db608eSbostic } 5172db608eSbostic /* Get environment pointer if need user supposed to provide one. */ 5272db608eSbostic if (envpp) 5372db608eSbostic *envpp = va_arg(ap, char **); 5472db608eSbostic return(argv); 5572db608eSbostic } 5672db608eSbostic 579e1dd68bSdonn int 589e1dd68bSdonn #if __STDC__ 599e1dd68bSdonn execl(const char *name, const char *arg, ...) 609e1dd68bSdonn #else 619e1dd68bSdonn execl(name, arg, va_alist) 629e1dd68bSdonn const char *name; 639e1dd68bSdonn const char *arg; 649e1dd68bSdonn va_dcl 659e1dd68bSdonn #endif 6672db608eSbostic { 6772db608eSbostic va_list ap; 6872db608eSbostic int sverrno; 6972db608eSbostic char **argv; 7072db608eSbostic 719e1dd68bSdonn #if __STDC__ 7272db608eSbostic va_start(ap, arg); 739e1dd68bSdonn #else 749e1dd68bSdonn va_start(ap); 759e1dd68bSdonn #endif 7672db608eSbostic if (argv = buildargv(ap, arg, (char ***)NULL)) 7772db608eSbostic (void)execve(name, argv, environ); 7872db608eSbostic va_end(ap); 7972db608eSbostic sverrno = errno; 8072db608eSbostic free(argv); 8172db608eSbostic errno = sverrno; 82f8f88d12Swnj return(-1); 83f8f88d12Swnj } 8472db608eSbostic 859e1dd68bSdonn int 869e1dd68bSdonn #if __STDC__ 879e1dd68bSdonn execle(const char *name, const char *arg, ...) 889e1dd68bSdonn #else 899e1dd68bSdonn execle(name, arg, va_alist) 909e1dd68bSdonn const char *name; 919e1dd68bSdonn const char *arg; 929e1dd68bSdonn va_dcl 939e1dd68bSdonn #endif 9472db608eSbostic { 9572db608eSbostic va_list ap; 9672db608eSbostic int sverrno; 9772db608eSbostic char **argv, **envp; 9872db608eSbostic 999e1dd68bSdonn #if __STDC__ 10072db608eSbostic va_start(ap, arg); 1019e1dd68bSdonn #else 1029e1dd68bSdonn va_start(ap); 1039e1dd68bSdonn #endif 10472db608eSbostic if (argv = buildargv(ap, arg, &envp)) 10572db608eSbostic (void)execve(name, argv, envp); 10672db608eSbostic va_end(ap); 10772db608eSbostic sverrno = errno; 10872db608eSbostic free(argv); 10972db608eSbostic errno = sverrno; 11072db608eSbostic return(-1); 11172db608eSbostic } 11272db608eSbostic 1139e1dd68bSdonn int 1149e1dd68bSdonn #if __STDC__ 1159e1dd68bSdonn execlp(const char *name, const char *arg, ...) 1169e1dd68bSdonn #else 1179e1dd68bSdonn execlp(name, arg, va_alist) 1189e1dd68bSdonn const char *name; 1199e1dd68bSdonn const char *arg; 1209e1dd68bSdonn va_dcl 1219e1dd68bSdonn #endif 12272db608eSbostic { 12372db608eSbostic va_list ap; 12472db608eSbostic int sverrno; 12572db608eSbostic char **argv; 12672db608eSbostic 1279e1dd68bSdonn #if __STDC__ 12872db608eSbostic va_start(ap, arg); 1299e1dd68bSdonn #else 1309e1dd68bSdonn va_start(ap); 1319e1dd68bSdonn #endif 13272db608eSbostic if (argv = buildargv(ap, arg, (char ***)NULL)) 13372db608eSbostic (void)execvp(name, argv); 13472db608eSbostic va_end(ap); 13572db608eSbostic sverrno = errno; 13672db608eSbostic free(argv); 13772db608eSbostic errno = sverrno; 13872db608eSbostic return(-1); 13972db608eSbostic } 14072db608eSbostic 1419e1dd68bSdonn int 1429e1dd68bSdonn execv(name, argv) 1439e1dd68bSdonn const char *name; 1449e1dd68bSdonn char * const *argv; 14572db608eSbostic { 14672db608eSbostic (void)execve(name, argv, environ); 14772db608eSbostic return(-1); 14872db608eSbostic } 14972db608eSbostic 1509e1dd68bSdonn int 1519e1dd68bSdonn execvp(name, argv) 1529e1dd68bSdonn const char *name; 1539e1dd68bSdonn char * const *argv; 15472db608eSbostic { 15572db608eSbostic register char *p; 15672db608eSbostic int eacces, etxtbsy; 157*3c93bb12Sbostic char *bp, *cur, *path, buf[MAXPATHLEN]; 15872db608eSbostic 15972db608eSbostic /* If it's an absolute or relative path name, it's easy. */ 16072db608eSbostic if (index(name, '/')) { 161*3c93bb12Sbostic bp = (char *)name; 162*3c93bb12Sbostic cur = path = NULL; 163*3c93bb12Sbostic goto retry; 16472db608eSbostic } 165*3c93bb12Sbostic bp = buf; 16672db608eSbostic 16772db608eSbostic /* Get the path we're searching. */ 16872db608eSbostic if (!(path = getenv("PATH"))) 16972db608eSbostic path = _PATH_DEFPATH; 17072db608eSbostic cur = path = strdup(path); 17172db608eSbostic 17272db608eSbostic eacces = etxtbsy = 0; 17372db608eSbostic while (p = strsep(&cur, ":")) { 17472db608eSbostic /* 17572db608eSbostic * It's a SHELL path -- double, leading and trailing colons 17672db608eSbostic * mean the current directory. 17772db608eSbostic */ 17872db608eSbostic if (!*p) 17972db608eSbostic p = "."; 18072db608eSbostic (void)snprintf(buf, sizeof(buf), "%s/%s", p, name); 18172db608eSbostic 182*3c93bb12Sbostic retry: (void)execve(bp, argv, environ); 18372db608eSbostic switch(errno) { 18472db608eSbostic case EACCES: 18572db608eSbostic eacces = 1; 18672db608eSbostic break; 18772db608eSbostic case ENOENT: 18872db608eSbostic break; 18972db608eSbostic case ENOEXEC: { 19072db608eSbostic register size_t cnt; 19172db608eSbostic register char **ap; 19272db608eSbostic 19372db608eSbostic for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt); 19472db608eSbostic if (ap = malloc((cnt + 2) * sizeof(char *))) { 195*3c93bb12Sbostic bcopy(argv + 1, ap + 2, cnt * sizeof(char *)); 19672db608eSbostic ap[0] = "sh"; 197*3c93bb12Sbostic ap[1] = bp; 19872db608eSbostic (void)execve(_PATH_BSHELL, ap, environ); 19972db608eSbostic free(ap); 20072db608eSbostic } 20172db608eSbostic goto done; 20272db608eSbostic } 20372db608eSbostic case ETXTBSY: 20472db608eSbostic if (etxtbsy < 3) 20572db608eSbostic (void)sleep(++etxtbsy); 20672db608eSbostic goto retry; 20772db608eSbostic default: 20872db608eSbostic goto done; 20972db608eSbostic } 21072db608eSbostic } 211f8f88d12Swnj if (eacces) 212f8f88d12Swnj errno = EACCES; 21372db608eSbostic else if (!errno) 21472db608eSbostic errno = ENOENT; 215*3c93bb12Sbostic done: if (path) 216*3c93bb12Sbostic free(path); 217f8f88d12Swnj return(-1); 218f8f88d12Swnj } 219