xref: /csrg-svn/lib/libc/gen/exec.c (revision 61111)
146592Sbostic /*-
2*61111Sbostic  * Copyright (c) 1991, 1993
3*61111Sbostic  *	The Regents of the University of California.  All rights reserved.
446592Sbostic  *
546592Sbostic  * %sccs.include.redist.c%
646592Sbostic  */
746592Sbostic 
826549Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*61111Sbostic static char sccsid[] = "@(#)exec.c	8.1 (Berkeley) 06/04/93";
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>
1750056Sbostic #include <string.h>
1850056Sbostic #include <stdio.h>
1950056Sbostic #include <paths.h>
2050056Sbostic 
2146598Sdonn #if __STDC__
2246592Sbostic #include <stdarg.h>
2346598Sdonn #else
2446598Sdonn #include <varargs.h>
2546598Sdonn #endif
261965Swnj 
2746592Sbostic extern char **environ;
281965Swnj 
2946598Sdonn static char **
buildargv(ap,arg,envpp)3046598Sdonn buildargv(ap, arg, envpp)
3146598Sdonn 	va_list ap;
3246598Sdonn 	const char *arg;
3346598Sdonn 	char ***envpp;
341965Swnj {
3553399Sbostic 	static int memsize;
3653399Sbostic 	static char **argv;
3753399Sbostic 	register int off;
3846592Sbostic 
3953399Sbostic 	argv = NULL;
4053399Sbostic 	for (off = 0;; ++off) {
4153399Sbostic 		if (off >= memsize) {
4253399Sbostic 			memsize += 50;	/* Starts out at 0. */
4353399Sbostic 			memsize *= 2;	/* Ramp up fast. */
4453399Sbostic 			if (!(argv = realloc(argv, memsize * sizeof(char *)))) {
4553399Sbostic 				memsize = 0;
4653399Sbostic 				return (NULL);
4753399Sbostic 			}
4846592Sbostic 			if (off == 0) {
4946592Sbostic 				argv[0] = (char *)arg;
5046592Sbostic 				off = 1;
5146592Sbostic 			}
5246592Sbostic 		}
5346592Sbostic 		if (!(argv[off] = va_arg(ap, char *)))
5446592Sbostic 			break;
5546592Sbostic 	}
5650056Sbostic 	/* Get environment pointer if user supposed to provide one. */
5746592Sbostic 	if (envpp)
5846592Sbostic 		*envpp = va_arg(ap, char **);
5953399Sbostic 	return (argv);
601965Swnj }
611965Swnj 
6246598Sdonn int
6346598Sdonn #if __STDC__
execl(const char * name,const char * arg,...)6446598Sdonn execl(const char *name, const char *arg, ...)
6546598Sdonn #else
6646598Sdonn execl(name, arg, va_alist)
6746598Sdonn 	const char *name;
6846598Sdonn 	const char *arg;
6946598Sdonn 	va_dcl
7046598Sdonn #endif
711965Swnj {
7246592Sbostic 	va_list ap;
7346592Sbostic 	int sverrno;
7446592Sbostic 	char **argv;
751965Swnj 
7646598Sdonn #if __STDC__
7746592Sbostic 	va_start(ap, arg);
7846598Sdonn #else
7946598Sdonn 	va_start(ap);
8046598Sdonn #endif
8153399Sbostic 	if (argv = buildargv(ap, arg, NULL))
8246592Sbostic 		(void)execve(name, argv, environ);
8346592Sbostic 	va_end(ap);
8446592Sbostic 	sverrno = errno;
8546592Sbostic 	free(argv);
8646592Sbostic 	errno = sverrno;
8753399Sbostic 	return (-1);
8846592Sbostic }
891965Swnj 
9046598Sdonn int
9146598Sdonn #if __STDC__
execle(const char * name,const char * arg,...)9246598Sdonn execle(const char *name, const char *arg, ...)
9346598Sdonn #else
9446598Sdonn execle(name, arg, va_alist)
9546598Sdonn 	const char *name;
9646598Sdonn 	const char *arg;
9746598Sdonn 	va_dcl
9846598Sdonn #endif
9946592Sbostic {
10046592Sbostic 	va_list ap;
10146592Sbostic 	int sverrno;
10246592Sbostic 	char **argv, **envp;
10346592Sbostic 
10446598Sdonn #if __STDC__
10546592Sbostic 	va_start(ap, arg);
10646598Sdonn #else
10746598Sdonn 	va_start(ap);
10846598Sdonn #endif
10946592Sbostic 	if (argv = buildargv(ap, arg, &envp))
11046592Sbostic 		(void)execve(name, argv, envp);
11146592Sbostic 	va_end(ap);
11246592Sbostic 	sverrno = errno;
11346592Sbostic 	free(argv);
11446592Sbostic 	errno = sverrno;
11553399Sbostic 	return (-1);
11646592Sbostic }
11746592Sbostic 
11846598Sdonn int
11946598Sdonn #if __STDC__
execlp(const char * name,const char * arg,...)12046598Sdonn execlp(const char *name, const char *arg, ...)
12146598Sdonn #else
12246598Sdonn execlp(name, arg, va_alist)
12346598Sdonn 	const char *name;
12446598Sdonn 	const char *arg;
12546598Sdonn 	va_dcl
12646598Sdonn #endif
12746592Sbostic {
12846592Sbostic 	va_list ap;
12946592Sbostic 	int sverrno;
13046592Sbostic 	char **argv;
13146592Sbostic 
13246598Sdonn #if __STDC__
13346592Sbostic 	va_start(ap, arg);
13446598Sdonn #else
13546598Sdonn 	va_start(ap);
13646598Sdonn #endif
13753399Sbostic 	if (argv = buildargv(ap, arg, NULL))
13846592Sbostic 		(void)execvp(name, argv);
13946592Sbostic 	va_end(ap);
14046592Sbostic 	sverrno = errno;
14146592Sbostic 	free(argv);
14246592Sbostic 	errno = sverrno;
14353399Sbostic 	return (-1);
14446592Sbostic }
14546592Sbostic 
14646598Sdonn int
execv(name,argv)14746598Sdonn execv(name, argv)
14846598Sdonn 	const char *name;
14946598Sdonn 	char * const *argv;
15046592Sbostic {
15146592Sbostic 	(void)execve(name, argv, environ);
15253399Sbostic 	return (-1);
15346592Sbostic }
15446592Sbostic 
15546598Sdonn int
execvp(name,argv)15646598Sdonn execvp(name, argv)
15746598Sdonn 	const char *name;
15846598Sdonn 	char * const *argv;
15946592Sbostic {
16053399Sbostic 	static int memsize;
16153399Sbostic 	static char **memp;
16253399Sbostic 	register int cnt, lp, ln;
16346592Sbostic 	register char *p;
16446592Sbostic 	int eacces, etxtbsy;
16547448Sbostic 	char *bp, *cur, *path, buf[MAXPATHLEN];
16646592Sbostic 
16746592Sbostic 	/* If it's an absolute or relative path name, it's easy. */
16846592Sbostic 	if (index(name, '/')) {
16947448Sbostic 		bp = (char *)name;
17047448Sbostic 		cur = path = NULL;
17147448Sbostic 		goto retry;
17246592Sbostic 	}
17347448Sbostic 	bp = buf;
17446592Sbostic 
17546592Sbostic 	/* Get the path we're searching. */
17646592Sbostic 	if (!(path = getenv("PATH")))
17746592Sbostic 		path = _PATH_DEFPATH;
17846592Sbostic 	cur = path = strdup(path);
17946592Sbostic 
18046592Sbostic 	eacces = etxtbsy = 0;
18146592Sbostic 	while (p = strsep(&cur, ":")) {
18246592Sbostic 		/*
18346592Sbostic 		 * It's a SHELL path -- double, leading and trailing colons
18446592Sbostic 		 * mean the current directory.
18546592Sbostic 		 */
18650056Sbostic 		if (!*p) {
18746592Sbostic 			p = ".";
18850056Sbostic 			lp = 1;
18950056Sbostic 		} else
19050056Sbostic 			lp = strlen(p);
19150056Sbostic 		ln = strlen(name);
19246592Sbostic 
19350056Sbostic 		/*
19450056Sbostic 		 * If the path is too long complain.  This is a possible
19550056Sbostic 		 * security issue; given a way to make the path too long
19650056Sbostic 		 * the user may execute the wrong program.
19750056Sbostic 		 */
19850056Sbostic 		if (lp + ln + 2 > sizeof(buf)) {
19950056Sbostic 			(void)write(STDERR_FILENO, "execvp: ", 8);
20050056Sbostic 			(void)write(STDERR_FILENO, p, lp);
20150056Sbostic 			(void)write(STDERR_FILENO, ": path too long\n", 16);
20250056Sbostic 			continue;
20350056Sbostic 		}
20450056Sbostic 		bcopy(p, buf, lp);
20550056Sbostic 		buf[lp] = '/';
20650056Sbostic 		bcopy(name, buf + lp + 1, ln);
20750056Sbostic 		buf[lp + ln + 1] = '\0';
20850056Sbostic 
20947448Sbostic retry:		(void)execve(bp, argv, environ);
2101965Swnj 		switch(errno) {
21146592Sbostic 		case EACCES:
21246592Sbostic 			eacces = 1;
21346592Sbostic 			break;
21446592Sbostic 		case ENOENT:
21546592Sbostic 			break;
21653399Sbostic 		case ENOEXEC:
21753399Sbostic 			for (cnt = 0; argv[cnt]; ++cnt);
21853399Sbostic 			if ((cnt + 2) * sizeof(char *) > memsize) {
21953399Sbostic 				memsize = (cnt + 2) * sizeof(char *);
22053399Sbostic 				if ((memp = realloc(memp, memsize)) == NULL) {
22153399Sbostic 					memsize = 0;
22253399Sbostic 					goto done;
22353399Sbostic 				}
2241965Swnj 			}
22553399Sbostic 			memp[0] = "sh";
22653399Sbostic 			memp[1] = bp;
22753399Sbostic 			bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
22853399Sbostic 			(void)execve(_PATH_BSHELL, memp, environ);
22946592Sbostic 			goto done;
2301965Swnj 		case ETXTBSY:
23146592Sbostic 			if (etxtbsy < 3)
23246592Sbostic 				(void)sleep(++etxtbsy);
2331965Swnj 			goto retry;
23446592Sbostic 		default:
23546592Sbostic 			goto done;
2361965Swnj 		}
23746592Sbostic 	}
2381965Swnj 	if (eacces)
2391965Swnj 		errno = EACCES;
24046592Sbostic 	else if (!errno)
24146592Sbostic 		errno = ENOENT;
24247448Sbostic done:	if (path)
24347448Sbostic 		free(path);
24453399Sbostic 	return (-1);
2451965Swnj }
246