xref: /original-bsd/lib/libc/gen/exec.c (revision bac379f5)
172db608eSbostic /*-
2*bac379f5Sbostic  * Copyright (c) 1991, 1993
3*bac379f5Sbostic  *	The Regents of the University of California.  All rights reserved.
472db608eSbostic  *
572db608eSbostic  * %sccs.include.redist.c%
6f8f88d12Swnj  */
772db608eSbostic 
872db608eSbostic #if defined(LIBC_SCCS) && !defined(lint)
9*bac379f5Sbostic static char sccsid[] = "@(#)exec.c	8.1 (Berkeley) 06/04/93";
1072db608eSbostic #endif /* LIBC_SCCS and not lint */
1172db608eSbostic 
1272db608eSbostic #include <sys/param.h>
1372db608eSbostic #include <sys/types.h>
14f8f88d12Swnj #include <errno.h>
155ba59b7eSdonn #include <unistd.h>
1672db608eSbostic #include <stdlib.h>
17d37da86fSbostic #include <string.h>
18d37da86fSbostic #include <stdio.h>
19d37da86fSbostic #include <paths.h>
20d37da86fSbostic 
219e1dd68bSdonn #if __STDC__
2272db608eSbostic #include <stdarg.h>
239e1dd68bSdonn #else
249e1dd68bSdonn #include <varargs.h>
259e1dd68bSdonn #endif
26f8f88d12Swnj 
2772db608eSbostic extern char **environ;
28f8f88d12Swnj 
299e1dd68bSdonn static char **
buildargv(ap,arg,envpp)309e1dd68bSdonn buildargv(ap, arg, envpp)
319e1dd68bSdonn 	va_list ap;
329e1dd68bSdonn 	const char *arg;
339e1dd68bSdonn 	char ***envpp;
34f8f88d12Swnj {
35208aaaf1Sbostic 	static int memsize;
36208aaaf1Sbostic 	static char **argv;
37208aaaf1Sbostic 	register int off;
38f8f88d12Swnj 
39208aaaf1Sbostic 	argv = NULL;
40208aaaf1Sbostic 	for (off = 0;; ++off) {
41208aaaf1Sbostic 		if (off >= memsize) {
42208aaaf1Sbostic 			memsize += 50;	/* Starts out at 0. */
43208aaaf1Sbostic 			memsize *= 2;	/* Ramp up fast. */
44208aaaf1Sbostic 			if (!(argv = realloc(argv, memsize * sizeof(char *)))) {
45208aaaf1Sbostic 				memsize = 0;
4672db608eSbostic 				return (NULL);
47208aaaf1Sbostic 			}
4872db608eSbostic 			if (off == 0) {
4972db608eSbostic 				argv[0] = (char *)arg;
5072db608eSbostic 				off = 1;
51f8f88d12Swnj 			}
52f8f88d12Swnj 		}
5372db608eSbostic 		if (!(argv[off] = va_arg(ap, char *)))
54f8f88d12Swnj 			break;
5572db608eSbostic 	}
56d37da86fSbostic 	/* Get environment pointer if user supposed to provide one. */
5772db608eSbostic 	if (envpp)
5872db608eSbostic 		*envpp = va_arg(ap, char **);
5972db608eSbostic 	return (argv);
6072db608eSbostic }
6172db608eSbostic 
629e1dd68bSdonn int
639e1dd68bSdonn #if __STDC__
execl(const char * name,const char * arg,...)649e1dd68bSdonn execl(const char *name, const char *arg, ...)
659e1dd68bSdonn #else
669e1dd68bSdonn execl(name, arg, va_alist)
679e1dd68bSdonn 	const char *name;
689e1dd68bSdonn 	const char *arg;
699e1dd68bSdonn 	va_dcl
709e1dd68bSdonn #endif
7172db608eSbostic {
7272db608eSbostic 	va_list ap;
7372db608eSbostic 	int sverrno;
7472db608eSbostic 	char **argv;
7572db608eSbostic 
769e1dd68bSdonn #if __STDC__
7772db608eSbostic 	va_start(ap, arg);
789e1dd68bSdonn #else
799e1dd68bSdonn 	va_start(ap);
809e1dd68bSdonn #endif
81208aaaf1Sbostic 	if (argv = buildargv(ap, arg, NULL))
8272db608eSbostic 		(void)execve(name, argv, environ);
8372db608eSbostic 	va_end(ap);
8472db608eSbostic 	sverrno = errno;
8572db608eSbostic 	free(argv);
8672db608eSbostic 	errno = sverrno;
87f8f88d12Swnj 	return (-1);
88f8f88d12Swnj }
8972db608eSbostic 
909e1dd68bSdonn int
919e1dd68bSdonn #if __STDC__
execle(const char * name,const char * arg,...)929e1dd68bSdonn execle(const char *name, const char *arg, ...)
939e1dd68bSdonn #else
949e1dd68bSdonn execle(name, arg, va_alist)
959e1dd68bSdonn 	const char *name;
969e1dd68bSdonn 	const char *arg;
979e1dd68bSdonn 	va_dcl
989e1dd68bSdonn #endif
9972db608eSbostic {
10072db608eSbostic 	va_list ap;
10172db608eSbostic 	int sverrno;
10272db608eSbostic 	char **argv, **envp;
10372db608eSbostic 
1049e1dd68bSdonn #if __STDC__
10572db608eSbostic 	va_start(ap, arg);
1069e1dd68bSdonn #else
1079e1dd68bSdonn 	va_start(ap);
1089e1dd68bSdonn #endif
10972db608eSbostic 	if (argv = buildargv(ap, arg, &envp))
11072db608eSbostic 		(void)execve(name, argv, envp);
11172db608eSbostic 	va_end(ap);
11272db608eSbostic 	sverrno = errno;
11372db608eSbostic 	free(argv);
11472db608eSbostic 	errno = sverrno;
11572db608eSbostic 	return (-1);
11672db608eSbostic }
11772db608eSbostic 
1189e1dd68bSdonn int
1199e1dd68bSdonn #if __STDC__
execlp(const char * name,const char * arg,...)1209e1dd68bSdonn execlp(const char *name, const char *arg, ...)
1219e1dd68bSdonn #else
1229e1dd68bSdonn execlp(name, arg, va_alist)
1239e1dd68bSdonn 	const char *name;
1249e1dd68bSdonn 	const char *arg;
1259e1dd68bSdonn 	va_dcl
1269e1dd68bSdonn #endif
12772db608eSbostic {
12872db608eSbostic 	va_list ap;
12972db608eSbostic 	int sverrno;
13072db608eSbostic 	char **argv;
13172db608eSbostic 
1329e1dd68bSdonn #if __STDC__
13372db608eSbostic 	va_start(ap, arg);
1349e1dd68bSdonn #else
1359e1dd68bSdonn 	va_start(ap);
1369e1dd68bSdonn #endif
137208aaaf1Sbostic 	if (argv = buildargv(ap, arg, NULL))
13872db608eSbostic 		(void)execvp(name, argv);
13972db608eSbostic 	va_end(ap);
14072db608eSbostic 	sverrno = errno;
14172db608eSbostic 	free(argv);
14272db608eSbostic 	errno = sverrno;
14372db608eSbostic 	return (-1);
14472db608eSbostic }
14572db608eSbostic 
1469e1dd68bSdonn int
execv(name,argv)1479e1dd68bSdonn execv(name, argv)
1489e1dd68bSdonn 	const char *name;
1499e1dd68bSdonn 	char * const *argv;
15072db608eSbostic {
15172db608eSbostic 	(void)execve(name, argv, environ);
15272db608eSbostic 	return (-1);
15372db608eSbostic }
15472db608eSbostic 
1559e1dd68bSdonn int
execvp(name,argv)1569e1dd68bSdonn execvp(name, argv)
1579e1dd68bSdonn 	const char *name;
1589e1dd68bSdonn 	char * const *argv;
15972db608eSbostic {
160208aaaf1Sbostic 	static int memsize;
161208aaaf1Sbostic 	static char **memp;
162208aaaf1Sbostic 	register int cnt, lp, ln;
16372db608eSbostic 	register char *p;
16472db608eSbostic 	int eacces, etxtbsy;
1653c93bb12Sbostic 	char *bp, *cur, *path, buf[MAXPATHLEN];
16672db608eSbostic 
16772db608eSbostic 	/* If it's an absolute or relative path name, it's easy. */
16872db608eSbostic 	if (index(name, '/')) {
1693c93bb12Sbostic 		bp = (char *)name;
1703c93bb12Sbostic 		cur = path = NULL;
1713c93bb12Sbostic 		goto retry;
17272db608eSbostic 	}
1733c93bb12Sbostic 	bp = buf;
17472db608eSbostic 
17572db608eSbostic 	/* Get the path we're searching. */
17672db608eSbostic 	if (!(path = getenv("PATH")))
17772db608eSbostic 		path = _PATH_DEFPATH;
17872db608eSbostic 	cur = path = strdup(path);
17972db608eSbostic 
18072db608eSbostic 	eacces = etxtbsy = 0;
18172db608eSbostic 	while (p = strsep(&cur, ":")) {
18272db608eSbostic 		/*
18372db608eSbostic 		 * It's a SHELL path -- double, leading and trailing colons
18472db608eSbostic 		 * mean the current directory.
18572db608eSbostic 		 */
186d37da86fSbostic 		if (!*p) {
18772db608eSbostic 			p = ".";
188d37da86fSbostic 			lp = 1;
189d37da86fSbostic 		} else
190d37da86fSbostic 			lp = strlen(p);
191d37da86fSbostic 		ln = strlen(name);
192d37da86fSbostic 
193d37da86fSbostic 		/*
194d37da86fSbostic 		 * If the path is too long complain.  This is a possible
195d37da86fSbostic 		 * security issue; given a way to make the path too long
196d37da86fSbostic 		 * the user may execute the wrong program.
197d37da86fSbostic 		 */
198d37da86fSbostic 		if (lp + ln + 2 > sizeof(buf)) {
199d37da86fSbostic 			(void)write(STDERR_FILENO, "execvp: ", 8);
200d37da86fSbostic 			(void)write(STDERR_FILENO, p, lp);
201d37da86fSbostic 			(void)write(STDERR_FILENO, ": path too long\n", 16);
202d37da86fSbostic 			continue;
203d37da86fSbostic 		}
204d37da86fSbostic 		bcopy(p, buf, lp);
205d37da86fSbostic 		buf[lp] = '/';
206d37da86fSbostic 		bcopy(name, buf + lp + 1, ln);
207d37da86fSbostic 		buf[lp + ln + 1] = '\0';
20872db608eSbostic 
2093c93bb12Sbostic retry:		(void)execve(bp, argv, environ);
21072db608eSbostic 		switch(errno) {
21172db608eSbostic 		case EACCES:
21272db608eSbostic 			eacces = 1;
21372db608eSbostic 			break;
21472db608eSbostic 		case ENOENT:
21572db608eSbostic 			break;
216208aaaf1Sbostic 		case ENOEXEC:
217208aaaf1Sbostic 			for (cnt = 0; argv[cnt]; ++cnt);
218208aaaf1Sbostic 			if ((cnt + 2) * sizeof(char *) > memsize) {
219208aaaf1Sbostic 				memsize = (cnt + 2) * sizeof(char *);
220208aaaf1Sbostic 				if ((memp = realloc(memp, memsize)) == NULL) {
221208aaaf1Sbostic 					memsize = 0;
22272db608eSbostic 					goto done;
22372db608eSbostic 				}
224208aaaf1Sbostic 			}
225208aaaf1Sbostic 			memp[0] = "sh";
226208aaaf1Sbostic 			memp[1] = bp;
227208aaaf1Sbostic 			bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
228208aaaf1Sbostic 			(void)execve(_PATH_BSHELL, memp, environ);
229208aaaf1Sbostic 			goto done;
23072db608eSbostic 		case ETXTBSY:
23172db608eSbostic 			if (etxtbsy < 3)
23272db608eSbostic 				(void)sleep(++etxtbsy);
23372db608eSbostic 			goto retry;
23472db608eSbostic 		default:
23572db608eSbostic 			goto done;
23672db608eSbostic 		}
23772db608eSbostic 	}
238f8f88d12Swnj 	if (eacces)
239f8f88d12Swnj 		errno = EACCES;
24072db608eSbostic 	else if (!errno)
24172db608eSbostic 		errno = ENOENT;
2423c93bb12Sbostic done:	if (path)
2433c93bb12Sbostic 		free(path);
244f8f88d12Swnj 	return (-1);
245f8f88d12Swnj }
246