xref: /original-bsd/lib/libc/gen/exec.c (revision 3c93bb12)
172db608eSbostic /*-
272db608eSbostic  * Copyright (c) 1991 The Regents of the University of California.
372db608eSbostic  * All rights reserved.
472db608eSbostic  *
572db608eSbostic  * %sccs.include.redist.c%
6f8f88d12Swnj  */
772db608eSbostic 
872db608eSbostic #if defined(LIBC_SCCS) && !defined(lint)
9*3c93bb12Sbostic static char sccsid[] = "@(#)exec.c	5.8 (Berkeley) 03/15/91";
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>
179e1dd68bSdonn #if __STDC__
1872db608eSbostic #include <stdarg.h>
199e1dd68bSdonn #else
209e1dd68bSdonn #include <varargs.h>
219e1dd68bSdonn #endif
2272db608eSbostic #include <string.h>
2372db608eSbostic #include <stdio.h>
2472db608eSbostic #include <paths.h>
25f8f88d12Swnj 
2672db608eSbostic extern char **environ;
27f8f88d12Swnj 
289e1dd68bSdonn static char **
299e1dd68bSdonn buildargv(ap, arg, envpp)
309e1dd68bSdonn 	va_list ap;
319e1dd68bSdonn 	const char *arg;
329e1dd68bSdonn 	char ***envpp;
33f8f88d12Swnj {
3472db608eSbostic 	register size_t max, off;
35e2415f6eSbostic 	register char **argv = NULL;
36f8f88d12Swnj 
3772db608eSbostic 	for (off = max = 0;; ++off) {
3872db608eSbostic 		if (off >= max) {
3972db608eSbostic 			max += 50;	/* Starts out at 0. */
4072db608eSbostic 			max *= 2;	/* Ramp up fast. */
4172db608eSbostic 			if (!(argv = realloc(argv, max * sizeof(char *))))
4272db608eSbostic 				return(NULL);
4372db608eSbostic 			if (off == 0) {
4472db608eSbostic 				argv[0] = (char *)arg;
4572db608eSbostic 				off = 1;
46f8f88d12Swnj 			}
47f8f88d12Swnj 		}
4872db608eSbostic 		if (!(argv[off] = va_arg(ap, char *)))
49f8f88d12Swnj 			break;
5072db608eSbostic 	}
5172db608eSbostic 	/* Get environment pointer if need user supposed to provide one. */
5272db608eSbostic 	if (envpp)
5372db608eSbostic 		*envpp = va_arg(ap, char **);
5472db608eSbostic 	return(argv);
5572db608eSbostic }
5672db608eSbostic 
579e1dd68bSdonn int
589e1dd68bSdonn #if __STDC__
599e1dd68bSdonn execl(const char *name, const char *arg, ...)
609e1dd68bSdonn #else
619e1dd68bSdonn execl(name, arg, va_alist)
629e1dd68bSdonn 	const char *name;
639e1dd68bSdonn 	const char *arg;
649e1dd68bSdonn 	va_dcl
659e1dd68bSdonn #endif
6672db608eSbostic {
6772db608eSbostic 	va_list ap;
6872db608eSbostic 	int sverrno;
6972db608eSbostic 	char **argv;
7072db608eSbostic 
719e1dd68bSdonn #if __STDC__
7272db608eSbostic 	va_start(ap, arg);
739e1dd68bSdonn #else
749e1dd68bSdonn 	va_start(ap);
759e1dd68bSdonn #endif
7672db608eSbostic 	if (argv = buildargv(ap, arg, (char ***)NULL))
7772db608eSbostic 		(void)execve(name, argv, environ);
7872db608eSbostic 	va_end(ap);
7972db608eSbostic 	sverrno = errno;
8072db608eSbostic 	free(argv);
8172db608eSbostic 	errno = sverrno;
82f8f88d12Swnj 	return(-1);
83f8f88d12Swnj }
8472db608eSbostic 
859e1dd68bSdonn int
869e1dd68bSdonn #if __STDC__
879e1dd68bSdonn execle(const char *name, const char *arg, ...)
889e1dd68bSdonn #else
899e1dd68bSdonn execle(name, arg, va_alist)
909e1dd68bSdonn 	const char *name;
919e1dd68bSdonn 	const char *arg;
929e1dd68bSdonn 	va_dcl
939e1dd68bSdonn #endif
9472db608eSbostic {
9572db608eSbostic 	va_list ap;
9672db608eSbostic 	int sverrno;
9772db608eSbostic 	char **argv, **envp;
9872db608eSbostic 
999e1dd68bSdonn #if __STDC__
10072db608eSbostic 	va_start(ap, arg);
1019e1dd68bSdonn #else
1029e1dd68bSdonn 	va_start(ap);
1039e1dd68bSdonn #endif
10472db608eSbostic 	if (argv = buildargv(ap, arg, &envp))
10572db608eSbostic 		(void)execve(name, argv, envp);
10672db608eSbostic 	va_end(ap);
10772db608eSbostic 	sverrno = errno;
10872db608eSbostic 	free(argv);
10972db608eSbostic 	errno = sverrno;
11072db608eSbostic 	return(-1);
11172db608eSbostic }
11272db608eSbostic 
1139e1dd68bSdonn int
1149e1dd68bSdonn #if __STDC__
1159e1dd68bSdonn execlp(const char *name, const char *arg, ...)
1169e1dd68bSdonn #else
1179e1dd68bSdonn execlp(name, arg, va_alist)
1189e1dd68bSdonn 	const char *name;
1199e1dd68bSdonn 	const char *arg;
1209e1dd68bSdonn 	va_dcl
1219e1dd68bSdonn #endif
12272db608eSbostic {
12372db608eSbostic 	va_list ap;
12472db608eSbostic 	int sverrno;
12572db608eSbostic 	char **argv;
12672db608eSbostic 
1279e1dd68bSdonn #if __STDC__
12872db608eSbostic 	va_start(ap, arg);
1299e1dd68bSdonn #else
1309e1dd68bSdonn 	va_start(ap);
1319e1dd68bSdonn #endif
13272db608eSbostic 	if (argv = buildargv(ap, arg, (char ***)NULL))
13372db608eSbostic 		(void)execvp(name, argv);
13472db608eSbostic 	va_end(ap);
13572db608eSbostic 	sverrno = errno;
13672db608eSbostic 	free(argv);
13772db608eSbostic 	errno = sverrno;
13872db608eSbostic 	return(-1);
13972db608eSbostic }
14072db608eSbostic 
1419e1dd68bSdonn int
1429e1dd68bSdonn execv(name, argv)
1439e1dd68bSdonn 	const char *name;
1449e1dd68bSdonn 	char * const *argv;
14572db608eSbostic {
14672db608eSbostic 	(void)execve(name, argv, environ);
14772db608eSbostic 	return(-1);
14872db608eSbostic }
14972db608eSbostic 
1509e1dd68bSdonn int
1519e1dd68bSdonn execvp(name, argv)
1529e1dd68bSdonn 	const char *name;
1539e1dd68bSdonn 	char * const *argv;
15472db608eSbostic {
15572db608eSbostic 	register char *p;
15672db608eSbostic 	int eacces, etxtbsy;
157*3c93bb12Sbostic 	char *bp, *cur, *path, buf[MAXPATHLEN];
15872db608eSbostic 
15972db608eSbostic 	/* If it's an absolute or relative path name, it's easy. */
16072db608eSbostic 	if (index(name, '/')) {
161*3c93bb12Sbostic 		bp = (char *)name;
162*3c93bb12Sbostic 		cur = path = NULL;
163*3c93bb12Sbostic 		goto retry;
16472db608eSbostic 	}
165*3c93bb12Sbostic 	bp = buf;
16672db608eSbostic 
16772db608eSbostic 	/* Get the path we're searching. */
16872db608eSbostic 	if (!(path = getenv("PATH")))
16972db608eSbostic 		path = _PATH_DEFPATH;
17072db608eSbostic 	cur = path = strdup(path);
17172db608eSbostic 
17272db608eSbostic 	eacces = etxtbsy = 0;
17372db608eSbostic 	while (p = strsep(&cur, ":")) {
17472db608eSbostic 		/*
17572db608eSbostic 		 * It's a SHELL path -- double, leading and trailing colons
17672db608eSbostic 		 * mean the current directory.
17772db608eSbostic 		 */
17872db608eSbostic 		if (!*p)
17972db608eSbostic 			p = ".";
18072db608eSbostic 		(void)snprintf(buf, sizeof(buf), "%s/%s", p, name);
18172db608eSbostic 
182*3c93bb12Sbostic retry:		(void)execve(bp, argv, environ);
18372db608eSbostic 		switch(errno) {
18472db608eSbostic 		case EACCES:
18572db608eSbostic 			eacces = 1;
18672db608eSbostic 			break;
18772db608eSbostic 		case ENOENT:
18872db608eSbostic 			break;
18972db608eSbostic 		case ENOEXEC: {
19072db608eSbostic 			register size_t cnt;
19172db608eSbostic 			register char **ap;
19272db608eSbostic 
19372db608eSbostic 			for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
19472db608eSbostic 			if (ap = malloc((cnt + 2) * sizeof(char *))) {
195*3c93bb12Sbostic 				bcopy(argv + 1, ap + 2, cnt * sizeof(char *));
19672db608eSbostic 				ap[0] = "sh";
197*3c93bb12Sbostic 				ap[1] = bp;
19872db608eSbostic 				(void)execve(_PATH_BSHELL, ap, environ);
19972db608eSbostic 				free(ap);
20072db608eSbostic 			}
20172db608eSbostic 			goto done;
20272db608eSbostic 		}
20372db608eSbostic 		case ETXTBSY:
20472db608eSbostic 			if (etxtbsy < 3)
20572db608eSbostic 				(void)sleep(++etxtbsy);
20672db608eSbostic 			goto retry;
20772db608eSbostic 		default:
20872db608eSbostic 			goto done;
20972db608eSbostic 		}
21072db608eSbostic 	}
211f8f88d12Swnj 	if (eacces)
212f8f88d12Swnj 		errno = EACCES;
21372db608eSbostic 	else if (!errno)
21472db608eSbostic 		errno = ENOENT;
215*3c93bb12Sbostic done:	if (path)
216*3c93bb12Sbostic 		free(path);
217f8f88d12Swnj 	return(-1);
218f8f88d12Swnj }
219