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