xref: /csrg-svn/lib/libc/gen/exec.c (revision 46598)
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