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*47448Sbostic static char sccsid[] = "@(#)exec.c 5.8 (Berkeley) 03/15/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> 1746598Sdonn #if __STDC__ 1846592Sbostic #include <stdarg.h> 1946598Sdonn #else 2046598Sdonn #include <varargs.h> 2146598Sdonn #endif 2246572Sdonn #include <string.h> 2346592Sbostic #include <stdio.h> 2446592Sbostic #include <paths.h> 251965Swnj 2646592Sbostic extern char **environ; 271965Swnj 2846598Sdonn static char ** 2946598Sdonn buildargv(ap, arg, envpp) 3046598Sdonn va_list ap; 3146598Sdonn const char *arg; 3246598Sdonn char ***envpp; 331965Swnj { 3446592Sbostic register size_t max, off; 3547039Sbostic register char **argv = NULL; 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 5746598Sdonn int 5846598Sdonn #if __STDC__ 5946598Sdonn execl(const char *name, const char *arg, ...) 6046598Sdonn #else 6146598Sdonn execl(name, arg, va_alist) 6246598Sdonn const char *name; 6346598Sdonn const char *arg; 6446598Sdonn va_dcl 6546598Sdonn #endif 661965Swnj { 6746592Sbostic va_list ap; 6846592Sbostic int sverrno; 6946592Sbostic char **argv; 701965Swnj 7146598Sdonn #if __STDC__ 7246592Sbostic va_start(ap, arg); 7346598Sdonn #else 7446598Sdonn va_start(ap); 7546598Sdonn #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 8546598Sdonn int 8646598Sdonn #if __STDC__ 8746598Sdonn execle(const char *name, const char *arg, ...) 8846598Sdonn #else 8946598Sdonn execle(name, arg, va_alist) 9046598Sdonn const char *name; 9146598Sdonn const char *arg; 9246598Sdonn va_dcl 9346598Sdonn #endif 9446592Sbostic { 9546592Sbostic va_list ap; 9646592Sbostic int sverrno; 9746592Sbostic char **argv, **envp; 9846592Sbostic 9946598Sdonn #if __STDC__ 10046592Sbostic va_start(ap, arg); 10146598Sdonn #else 10246598Sdonn va_start(ap); 10346598Sdonn #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 11346598Sdonn int 11446598Sdonn #if __STDC__ 11546598Sdonn execlp(const char *name, const char *arg, ...) 11646598Sdonn #else 11746598Sdonn execlp(name, arg, va_alist) 11846598Sdonn const char *name; 11946598Sdonn const char *arg; 12046598Sdonn va_dcl 12146598Sdonn #endif 12246592Sbostic { 12346592Sbostic va_list ap; 12446592Sbostic int sverrno; 12546592Sbostic char **argv; 12646592Sbostic 12746598Sdonn #if __STDC__ 12846592Sbostic va_start(ap, arg); 12946598Sdonn #else 13046598Sdonn va_start(ap); 13146598Sdonn #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 14146598Sdonn int 14246598Sdonn execv(name, argv) 14346598Sdonn const char *name; 14446598Sdonn char * const *argv; 14546592Sbostic { 14646592Sbostic (void)execve(name, argv, environ); 14746592Sbostic return(-1); 14846592Sbostic } 14946592Sbostic 15046598Sdonn int 15146598Sdonn execvp(name, argv) 15246598Sdonn const char *name; 15346598Sdonn char * const *argv; 15446592Sbostic { 15546592Sbostic register char *p; 15646592Sbostic int eacces, etxtbsy; 157*47448Sbostic char *bp, *cur, *path, buf[MAXPATHLEN]; 15846592Sbostic 15946592Sbostic /* If it's an absolute or relative path name, it's easy. */ 16046592Sbostic if (index(name, '/')) { 161*47448Sbostic bp = (char *)name; 162*47448Sbostic cur = path = NULL; 163*47448Sbostic goto retry; 16446592Sbostic } 165*47448Sbostic bp = buf; 16646592Sbostic 16746592Sbostic /* Get the path we're searching. */ 16846592Sbostic if (!(path = getenv("PATH"))) 16946592Sbostic path = _PATH_DEFPATH; 17046592Sbostic cur = path = strdup(path); 17146592Sbostic 17246592Sbostic eacces = etxtbsy = 0; 17346592Sbostic while (p = strsep(&cur, ":")) { 17446592Sbostic /* 17546592Sbostic * It's a SHELL path -- double, leading and trailing colons 17646592Sbostic * mean the current directory. 17746592Sbostic */ 17846592Sbostic if (!*p) 17946592Sbostic p = "."; 18046592Sbostic (void)snprintf(buf, sizeof(buf), "%s/%s", p, name); 18146592Sbostic 182*47448Sbostic retry: (void)execve(bp, argv, environ); 1831965Swnj switch(errno) { 18446592Sbostic case EACCES: 18546592Sbostic eacces = 1; 18646592Sbostic break; 18746592Sbostic case ENOENT: 18846592Sbostic break; 18946592Sbostic case ENOEXEC: { 19046592Sbostic register size_t cnt; 19146592Sbostic register char **ap; 19246592Sbostic 19346592Sbostic for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt); 19446592Sbostic if (ap = malloc((cnt + 2) * sizeof(char *))) { 195*47448Sbostic bcopy(argv + 1, ap + 2, cnt * sizeof(char *)); 19646592Sbostic ap[0] = "sh"; 197*47448Sbostic ap[1] = bp; 19846592Sbostic (void)execve(_PATH_BSHELL, ap, environ); 19946592Sbostic free(ap); 2001965Swnj } 20146592Sbostic goto done; 20246592Sbostic } 2031965Swnj case ETXTBSY: 20446592Sbostic if (etxtbsy < 3) 20546592Sbostic (void)sleep(++etxtbsy); 2061965Swnj goto retry; 20746592Sbostic default: 20846592Sbostic goto done; 2091965Swnj } 21046592Sbostic } 2111965Swnj if (eacces) 2121965Swnj errno = EACCES; 21346592Sbostic else if (!errno) 21446592Sbostic errno = ENOENT; 215*47448Sbostic done: if (path) 216*47448Sbostic free(path); 2171965Swnj return(-1); 2181965Swnj } 219