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