xref: /original-bsd/lib/libc/gen/exec.c (revision 9e1dd68b)
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*9e1dd68bSdonn static char sccsid[] = "@(#)exec.c	5.6 (Berkeley) 02/23/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>
17*9e1dd68bSdonn #if __STDC__
1872db608eSbostic #include <stdarg.h>
19*9e1dd68bSdonn #else
20*9e1dd68bSdonn #include <varargs.h>
21*9e1dd68bSdonn #endif
2272db608eSbostic #include <string.h>
2372db608eSbostic #include <stdio.h>
2472db608eSbostic #include <paths.h>
25f8f88d12Swnj 
2672db608eSbostic extern char **environ;
27f8f88d12Swnj 
28*9e1dd68bSdonn static char **
29*9e1dd68bSdonn buildargv(ap, arg, envpp)
30*9e1dd68bSdonn 	va_list ap;
31*9e1dd68bSdonn 	const char *arg;
32*9e1dd68bSdonn 	char ***envpp;
33f8f88d12Swnj {
3472db608eSbostic 	register size_t max, off;
3572db608eSbostic 	register char **argv;
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 
57*9e1dd68bSdonn int
58*9e1dd68bSdonn #if __STDC__
59*9e1dd68bSdonn execl(const char *name, const char *arg, ...)
60*9e1dd68bSdonn #else
61*9e1dd68bSdonn execl(name, arg, va_alist)
62*9e1dd68bSdonn 	const char *name;
63*9e1dd68bSdonn 	const char *arg;
64*9e1dd68bSdonn 	va_dcl
65*9e1dd68bSdonn #endif
6672db608eSbostic {
6772db608eSbostic 	va_list ap;
6872db608eSbostic 	int sverrno;
6972db608eSbostic 	char **argv;
7072db608eSbostic 
71*9e1dd68bSdonn #if __STDC__
7272db608eSbostic 	va_start(ap, arg);
73*9e1dd68bSdonn #else
74*9e1dd68bSdonn 	va_start(ap);
75*9e1dd68bSdonn #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 
85*9e1dd68bSdonn int
86*9e1dd68bSdonn #if __STDC__
87*9e1dd68bSdonn execle(const char *name, const char *arg, ...)
88*9e1dd68bSdonn #else
89*9e1dd68bSdonn execle(name, arg, va_alist)
90*9e1dd68bSdonn 	const char *name;
91*9e1dd68bSdonn 	const char *arg;
92*9e1dd68bSdonn 	va_dcl
93*9e1dd68bSdonn #endif
9472db608eSbostic {
9572db608eSbostic 	va_list ap;
9672db608eSbostic 	int sverrno;
9772db608eSbostic 	char **argv, **envp;
9872db608eSbostic 
99*9e1dd68bSdonn #if __STDC__
10072db608eSbostic 	va_start(ap, arg);
101*9e1dd68bSdonn #else
102*9e1dd68bSdonn 	va_start(ap);
103*9e1dd68bSdonn #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 
113*9e1dd68bSdonn int
114*9e1dd68bSdonn #if __STDC__
115*9e1dd68bSdonn execlp(const char *name, const char *arg, ...)
116*9e1dd68bSdonn #else
117*9e1dd68bSdonn execlp(name, arg, va_alist)
118*9e1dd68bSdonn 	const char *name;
119*9e1dd68bSdonn 	const char *arg;
120*9e1dd68bSdonn 	va_dcl
121*9e1dd68bSdonn #endif
12272db608eSbostic {
12372db608eSbostic 	va_list ap;
12472db608eSbostic 	int sverrno;
12572db608eSbostic 	char **argv;
12672db608eSbostic 
127*9e1dd68bSdonn #if __STDC__
12872db608eSbostic 	va_start(ap, arg);
129*9e1dd68bSdonn #else
130*9e1dd68bSdonn 	va_start(ap);
131*9e1dd68bSdonn #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 
141*9e1dd68bSdonn int
142*9e1dd68bSdonn execv(name, argv)
143*9e1dd68bSdonn 	const char *name;
144*9e1dd68bSdonn 	char * const *argv;
14572db608eSbostic {
14672db608eSbostic 	(void)execve(name, argv, environ);
14772db608eSbostic 	return(-1);
14872db608eSbostic }
14972db608eSbostic 
150*9e1dd68bSdonn int
151*9e1dd68bSdonn execvp(name, argv)
152*9e1dd68bSdonn 	const char *name;
153*9e1dd68bSdonn 	char * const *argv;
15472db608eSbostic {
15572db608eSbostic 	register char *p;
15672db608eSbostic 	int eacces, etxtbsy;
15772db608eSbostic 	char *cur, *path, buf[MAXPATHLEN];
15872db608eSbostic 
15972db608eSbostic 	/* If it's an absolute or relative path name, it's easy. */
16072db608eSbostic 	if (index(name, '/')) {
16172db608eSbostic 		(void)execve(name, argv, environ);
16272db608eSbostic 		return(-1);
16372db608eSbostic 	}
16472db608eSbostic 
16572db608eSbostic 	/* Get the path we're searching. */
16672db608eSbostic 	if (!(path = getenv("PATH")))
16772db608eSbostic 		path = _PATH_DEFPATH;
16872db608eSbostic 	cur = path = strdup(path);
16972db608eSbostic 
17072db608eSbostic 	eacces = etxtbsy = 0;
17172db608eSbostic 	while (p = strsep(&cur, ":")) {
17272db608eSbostic 		/*
17372db608eSbostic 		 * It's a SHELL path -- double, leading and trailing colons
17472db608eSbostic 		 * mean the current directory.
17572db608eSbostic 		 */
17672db608eSbostic 		if (!*p)
17772db608eSbostic 			p = ".";
17872db608eSbostic 		(void)snprintf(buf, sizeof(buf), "%s/%s", p, name);
17972db608eSbostic 
18072db608eSbostic retry:		(void)execve(buf, argv, environ);
18172db608eSbostic 		switch(errno) {
18272db608eSbostic 		case EACCES:
18372db608eSbostic 			eacces = 1;
18472db608eSbostic 			break;
18572db608eSbostic 		case ENOENT:
18672db608eSbostic 			break;
18772db608eSbostic 		case ENOEXEC: {
18872db608eSbostic 			register size_t cnt;
18972db608eSbostic 			register char **ap;
19072db608eSbostic 
19172db608eSbostic 			for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
19272db608eSbostic 			if (ap = malloc((cnt + 2) * sizeof(char *))) {
19372db608eSbostic 				bcopy(argv, ap + 2, cnt * sizeof(char *));
19472db608eSbostic 				ap[0] = "sh";
19572db608eSbostic 				ap[1] = buf;
19672db608eSbostic 				(void)execve(_PATH_BSHELL, ap, environ);
19772db608eSbostic 				free(ap);
19872db608eSbostic 			}
19972db608eSbostic 			goto done;
20072db608eSbostic 		}
20172db608eSbostic 		case ETXTBSY:
20272db608eSbostic 			if (etxtbsy < 3)
20372db608eSbostic 				(void)sleep(++etxtbsy);
20472db608eSbostic 			goto retry;
20572db608eSbostic 		default:
20672db608eSbostic 			goto done;
20772db608eSbostic 		}
20872db608eSbostic 	}
209f8f88d12Swnj 	if (eacces)
210f8f88d12Swnj 		errno = EACCES;
21172db608eSbostic 	else if (!errno)
21272db608eSbostic 		errno = ENOENT;
21372db608eSbostic done:	free(path);
214f8f88d12Swnj 	return(-1);
215f8f88d12Swnj }
216