146592Sbostic /*- 246592Sbostic * Copyright (c) 1991 The Regents of the University of California. 346592Sbostic * All rights reserved. 446592Sbostic * 546592Sbostic * %sccs.include.redist.c% 646592Sbostic */ 746592Sbostic 826549Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*46598Sdonn static char sccsid[] = "@(#)exec.c 5.6 (Berkeley) 02/23/91"; 1046592Sbostic #endif /* LIBC_SCCS and not lint */ 1122086Smckusick 1246592Sbostic #include <sys/param.h> 1346592Sbostic #include <sys/types.h> 141965Swnj #include <errno.h> 1546592Sbostic #include <unistd.h> 1646572Sdonn #include <stdlib.h> 17*46598Sdonn #if __STDC__ 1846592Sbostic #include <stdarg.h> 19*46598Sdonn #else 20*46598Sdonn #include <varargs.h> 21*46598Sdonn #endif 2246572Sdonn #include <string.h> 2346592Sbostic #include <stdio.h> 2446592Sbostic #include <paths.h> 251965Swnj 2646592Sbostic extern char **environ; 271965Swnj 28*46598Sdonn static char ** 29*46598Sdonn buildargv(ap, arg, envpp) 30*46598Sdonn va_list ap; 31*46598Sdonn const char *arg; 32*46598Sdonn char ***envpp; 331965Swnj { 3446592Sbostic register size_t max, off; 3546592Sbostic register char **argv; 3646592Sbostic 3746592Sbostic for (off = max = 0;; ++off) { 3846592Sbostic if (off >= max) { 3946592Sbostic max += 50; /* Starts out at 0. */ 4046592Sbostic max *= 2; /* Ramp up fast. */ 4146592Sbostic if (!(argv = realloc(argv, max * sizeof(char *)))) 4246592Sbostic return(NULL); 4346592Sbostic if (off == 0) { 4446592Sbostic argv[0] = (char *)arg; 4546592Sbostic off = 1; 4646592Sbostic } 4746592Sbostic } 4846592Sbostic if (!(argv[off] = va_arg(ap, char *))) 4946592Sbostic break; 5046592Sbostic } 5146592Sbostic /* Get environment pointer if need user supposed to provide one. */ 5246592Sbostic if (envpp) 5346592Sbostic *envpp = va_arg(ap, char **); 5446592Sbostic return(argv); 551965Swnj } 561965Swnj 57*46598Sdonn int 58*46598Sdonn #if __STDC__ 59*46598Sdonn execl(const char *name, const char *arg, ...) 60*46598Sdonn #else 61*46598Sdonn execl(name, arg, va_alist) 62*46598Sdonn const char *name; 63*46598Sdonn const char *arg; 64*46598Sdonn va_dcl 65*46598Sdonn #endif 661965Swnj { 6746592Sbostic va_list ap; 6846592Sbostic int sverrno; 6946592Sbostic char **argv; 701965Swnj 71*46598Sdonn #if __STDC__ 7246592Sbostic va_start(ap, arg); 73*46598Sdonn #else 74*46598Sdonn va_start(ap); 75*46598Sdonn #endif 7646592Sbostic if (argv = buildargv(ap, arg, (char ***)NULL)) 7746592Sbostic (void)execve(name, argv, environ); 7846592Sbostic va_end(ap); 7946592Sbostic sverrno = errno; 8046592Sbostic free(argv); 8146592Sbostic errno = sverrno; 8246592Sbostic return(-1); 8346592Sbostic } 841965Swnj 85*46598Sdonn int 86*46598Sdonn #if __STDC__ 87*46598Sdonn execle(const char *name, const char *arg, ...) 88*46598Sdonn #else 89*46598Sdonn execle(name, arg, va_alist) 90*46598Sdonn const char *name; 91*46598Sdonn const char *arg; 92*46598Sdonn va_dcl 93*46598Sdonn #endif 9446592Sbostic { 9546592Sbostic va_list ap; 9646592Sbostic int sverrno; 9746592Sbostic char **argv, **envp; 9846592Sbostic 99*46598Sdonn #if __STDC__ 10046592Sbostic va_start(ap, arg); 101*46598Sdonn #else 102*46598Sdonn va_start(ap); 103*46598Sdonn #endif 10446592Sbostic if (argv = buildargv(ap, arg, &envp)) 10546592Sbostic (void)execve(name, argv, envp); 10646592Sbostic va_end(ap); 10746592Sbostic sverrno = errno; 10846592Sbostic free(argv); 10946592Sbostic errno = sverrno; 11046592Sbostic return(-1); 11146592Sbostic } 11246592Sbostic 113*46598Sdonn int 114*46598Sdonn #if __STDC__ 115*46598Sdonn execlp(const char *name, const char *arg, ...) 116*46598Sdonn #else 117*46598Sdonn execlp(name, arg, va_alist) 118*46598Sdonn const char *name; 119*46598Sdonn const char *arg; 120*46598Sdonn va_dcl 121*46598Sdonn #endif 12246592Sbostic { 12346592Sbostic va_list ap; 12446592Sbostic int sverrno; 12546592Sbostic char **argv; 12646592Sbostic 127*46598Sdonn #if __STDC__ 12846592Sbostic va_start(ap, arg); 129*46598Sdonn #else 130*46598Sdonn va_start(ap); 131*46598Sdonn #endif 13246592Sbostic if (argv = buildargv(ap, arg, (char ***)NULL)) 13346592Sbostic (void)execvp(name, argv); 13446592Sbostic va_end(ap); 13546592Sbostic sverrno = errno; 13646592Sbostic free(argv); 13746592Sbostic errno = sverrno; 13846592Sbostic return(-1); 13946592Sbostic } 14046592Sbostic 141*46598Sdonn int 142*46598Sdonn execv(name, argv) 143*46598Sdonn const char *name; 144*46598Sdonn char * const *argv; 14546592Sbostic { 14646592Sbostic (void)execve(name, argv, environ); 14746592Sbostic return(-1); 14846592Sbostic } 14946592Sbostic 150*46598Sdonn int 151*46598Sdonn execvp(name, argv) 152*46598Sdonn const char *name; 153*46598Sdonn char * const *argv; 15446592Sbostic { 15546592Sbostic register char *p; 15646592Sbostic int eacces, etxtbsy; 15746592Sbostic char *cur, *path, buf[MAXPATHLEN]; 15846592Sbostic 15946592Sbostic /* If it's an absolute or relative path name, it's easy. */ 16046592Sbostic if (index(name, '/')) { 16146592Sbostic (void)execve(name, argv, environ); 16246592Sbostic return(-1); 16346592Sbostic } 16446592Sbostic 16546592Sbostic /* Get the path we're searching. */ 16646592Sbostic if (!(path = getenv("PATH"))) 16746592Sbostic path = _PATH_DEFPATH; 16846592Sbostic cur = path = strdup(path); 16946592Sbostic 17046592Sbostic eacces = etxtbsy = 0; 17146592Sbostic while (p = strsep(&cur, ":")) { 17246592Sbostic /* 17346592Sbostic * It's a SHELL path -- double, leading and trailing colons 17446592Sbostic * mean the current directory. 17546592Sbostic */ 17646592Sbostic if (!*p) 17746592Sbostic p = "."; 17846592Sbostic (void)snprintf(buf, sizeof(buf), "%s/%s", p, name); 17946592Sbostic 18046592Sbostic retry: (void)execve(buf, argv, environ); 1811965Swnj switch(errno) { 18246592Sbostic case EACCES: 18346592Sbostic eacces = 1; 18446592Sbostic break; 18546592Sbostic case ENOENT: 18646592Sbostic break; 18746592Sbostic case ENOEXEC: { 18846592Sbostic register size_t cnt; 18946592Sbostic register char **ap; 19046592Sbostic 19146592Sbostic for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt); 19246592Sbostic if (ap = malloc((cnt + 2) * sizeof(char *))) { 19346592Sbostic bcopy(argv, ap + 2, cnt * sizeof(char *)); 19446592Sbostic ap[0] = "sh"; 19546592Sbostic ap[1] = buf; 19646592Sbostic (void)execve(_PATH_BSHELL, ap, environ); 19746592Sbostic free(ap); 1981965Swnj } 19946592Sbostic goto done; 20046592Sbostic } 2011965Swnj case ETXTBSY: 20246592Sbostic if (etxtbsy < 3) 20346592Sbostic (void)sleep(++etxtbsy); 2041965Swnj goto retry; 20546592Sbostic default: 20646592Sbostic goto done; 2071965Swnj } 20846592Sbostic } 2091965Swnj if (eacces) 2101965Swnj errno = EACCES; 21146592Sbostic else if (!errno) 21246592Sbostic errno = ENOENT; 21346592Sbostic done: free(path); 2141965Swnj return(-1); 2151965Swnj } 216