1*72db608eSbostic /*- 2*72db608eSbostic * Copyright (c) 1991 The Regents of the University of California. 3*72db608eSbostic * All rights reserved. 4*72db608eSbostic * 5*72db608eSbostic * %sccs.include.redist.c% 6f8f88d12Swnj */ 7*72db608eSbostic 8*72db608eSbostic #if defined(LIBC_SCCS) && !defined(lint) 9*72db608eSbostic static char sccsid[] = "@(#)exec.c 5.5 (Berkeley) 02/23/91"; 10*72db608eSbostic #endif /* LIBC_SCCS and not lint */ 11*72db608eSbostic 12*72db608eSbostic #include <sys/param.h> 13*72db608eSbostic #include <sys/types.h> 14f8f88d12Swnj #include <errno.h> 155ba59b7eSdonn #include <unistd.h> 16*72db608eSbostic #include <stdlib.h> 17*72db608eSbostic #include <stdarg.h> 18*72db608eSbostic #include <string.h> 19*72db608eSbostic #include <stdio.h> 20*72db608eSbostic #include <paths.h> 21f8f88d12Swnj 22*72db608eSbostic extern char **environ; 23f8f88d12Swnj 24*72db608eSbostic static char **buildargv(va_list ap, const char *arg, char ***envpp) 25f8f88d12Swnj { 26*72db608eSbostic register size_t max, off; 27*72db608eSbostic register char **argv; 28f8f88d12Swnj 29*72db608eSbostic for (off = max = 0;; ++off) { 30*72db608eSbostic if (off >= max) { 31*72db608eSbostic max += 50; /* Starts out at 0. */ 32*72db608eSbostic max *= 2; /* Ramp up fast. */ 33*72db608eSbostic if (!(argv = realloc(argv, max * sizeof(char *)))) 34*72db608eSbostic return(NULL); 35*72db608eSbostic if (off == 0) { 36*72db608eSbostic argv[0] = (char *)arg; 37*72db608eSbostic off = 1; 38f8f88d12Swnj } 39f8f88d12Swnj } 40*72db608eSbostic if (!(argv[off] = va_arg(ap, char *))) 41f8f88d12Swnj break; 42*72db608eSbostic } 43*72db608eSbostic /* Get environment pointer if need user supposed to provide one. */ 44*72db608eSbostic if (envpp) 45*72db608eSbostic *envpp = va_arg(ap, char **); 46*72db608eSbostic return(argv); 47*72db608eSbostic } 48*72db608eSbostic 49*72db608eSbostic int execl(const char *name, const char *arg, ...) 50*72db608eSbostic { 51*72db608eSbostic va_list ap; 52*72db608eSbostic int sverrno; 53*72db608eSbostic char **argv; 54*72db608eSbostic 55*72db608eSbostic va_start(ap, arg); 56*72db608eSbostic if (argv = buildargv(ap, arg, (char ***)NULL)) 57*72db608eSbostic (void)execve(name, argv, environ); 58*72db608eSbostic va_end(ap); 59*72db608eSbostic sverrno = errno; 60*72db608eSbostic free(argv); 61*72db608eSbostic errno = sverrno; 62f8f88d12Swnj return(-1); 63f8f88d12Swnj } 64*72db608eSbostic 65*72db608eSbostic int execle(const char *name, const char *arg, ...) 66*72db608eSbostic { 67*72db608eSbostic va_list ap; 68*72db608eSbostic int sverrno; 69*72db608eSbostic char **argv, **envp; 70*72db608eSbostic 71*72db608eSbostic va_start(ap, arg); 72*72db608eSbostic if (argv = buildargv(ap, arg, &envp)) 73*72db608eSbostic (void)execve(name, argv, envp); 74*72db608eSbostic va_end(ap); 75*72db608eSbostic sverrno = errno; 76*72db608eSbostic free(argv); 77*72db608eSbostic errno = sverrno; 78*72db608eSbostic return(-1); 79*72db608eSbostic } 80*72db608eSbostic 81*72db608eSbostic int execlp(const char *name, const char *arg, ...) 82*72db608eSbostic { 83*72db608eSbostic va_list ap; 84*72db608eSbostic int sverrno; 85*72db608eSbostic char **argv; 86*72db608eSbostic 87*72db608eSbostic va_start(ap, arg); 88*72db608eSbostic if (argv = buildargv(ap, arg, (char ***)NULL)) 89*72db608eSbostic (void)execvp(name, argv); 90*72db608eSbostic va_end(ap); 91*72db608eSbostic sverrno = errno; 92*72db608eSbostic free(argv); 93*72db608eSbostic errno = sverrno; 94*72db608eSbostic return(-1); 95*72db608eSbostic } 96*72db608eSbostic 97*72db608eSbostic int execv(const char *name, char * const *argv) 98*72db608eSbostic { 99*72db608eSbostic (void)execve(name, argv, environ); 100*72db608eSbostic return(-1); 101*72db608eSbostic } 102*72db608eSbostic 103*72db608eSbostic int execvp(const char *name, char * const *argv) 104*72db608eSbostic { 105*72db608eSbostic register char *p; 106*72db608eSbostic int eacces, etxtbsy; 107*72db608eSbostic char *cur, *path, buf[MAXPATHLEN]; 108*72db608eSbostic 109*72db608eSbostic /* If it's an absolute or relative path name, it's easy. */ 110*72db608eSbostic if (index(name, '/')) { 111*72db608eSbostic (void)execve(name, argv, environ); 112*72db608eSbostic return(-1); 113*72db608eSbostic } 114*72db608eSbostic 115*72db608eSbostic /* Get the path we're searching. */ 116*72db608eSbostic if (!(path = getenv("PATH"))) 117*72db608eSbostic path = _PATH_DEFPATH; 118*72db608eSbostic cur = path = strdup(path); 119*72db608eSbostic 120*72db608eSbostic eacces = etxtbsy = 0; 121*72db608eSbostic while (p = strsep(&cur, ":")) { 122*72db608eSbostic /* 123*72db608eSbostic * It's a SHELL path -- double, leading and trailing colons 124*72db608eSbostic * mean the current directory. 125*72db608eSbostic */ 126*72db608eSbostic if (!*p) 127*72db608eSbostic p = "."; 128*72db608eSbostic (void)snprintf(buf, sizeof(buf), "%s/%s", p, name); 129*72db608eSbostic 130*72db608eSbostic retry: (void)execve(buf, argv, environ); 131*72db608eSbostic switch(errno) { 132*72db608eSbostic case EACCES: 133*72db608eSbostic eacces = 1; 134*72db608eSbostic break; 135*72db608eSbostic case ENOENT: 136*72db608eSbostic break; 137*72db608eSbostic case ENOEXEC: { 138*72db608eSbostic register size_t cnt; 139*72db608eSbostic register char **ap; 140*72db608eSbostic 141*72db608eSbostic for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt); 142*72db608eSbostic if (ap = malloc((cnt + 2) * sizeof(char *))) { 143*72db608eSbostic bcopy(argv, ap + 2, cnt * sizeof(char *)); 144*72db608eSbostic ap[0] = "sh"; 145*72db608eSbostic ap[1] = buf; 146*72db608eSbostic (void)execve(_PATH_BSHELL, ap, environ); 147*72db608eSbostic free(ap); 148*72db608eSbostic } 149*72db608eSbostic goto done; 150*72db608eSbostic } 151*72db608eSbostic case ETXTBSY: 152*72db608eSbostic if (etxtbsy < 3) 153*72db608eSbostic (void)sleep(++etxtbsy); 154*72db608eSbostic goto retry; 155*72db608eSbostic default: 156*72db608eSbostic goto done; 157*72db608eSbostic } 158*72db608eSbostic } 159f8f88d12Swnj if (eacces) 160f8f88d12Swnj errno = EACCES; 161*72db608eSbostic else if (!errno) 162*72db608eSbostic errno = ENOENT; 163*72db608eSbostic done: free(path); 164f8f88d12Swnj return(-1); 165f8f88d12Swnj } 166