xref: /original-bsd/lib/libc/gen/exec.c (revision 72db608e)
1*72db608eSbostic /*-
2*72db608eSbostic  * Copyright (c) 1991 The Regents of the University of California.
3*72db608eSbostic  * All rights reserved.
4*72db608eSbostic  *
5*72db608eSbostic  * %sccs.include.redist.c%
6f8f88d12Swnj  */
7*72db608eSbostic 
8*72db608eSbostic #if defined(LIBC_SCCS) && !defined(lint)
9*72db608eSbostic static char sccsid[] = "@(#)exec.c	5.5 (Berkeley) 02/23/91";
10*72db608eSbostic #endif /* LIBC_SCCS and not lint */
11*72db608eSbostic 
12*72db608eSbostic #include <sys/param.h>
13*72db608eSbostic #include <sys/types.h>
14f8f88d12Swnj #include <errno.h>
155ba59b7eSdonn #include <unistd.h>
16*72db608eSbostic #include <stdlib.h>
17*72db608eSbostic #include <stdarg.h>
18*72db608eSbostic #include <string.h>
19*72db608eSbostic #include <stdio.h>
20*72db608eSbostic #include <paths.h>
21f8f88d12Swnj 
22*72db608eSbostic extern char **environ;
23f8f88d12Swnj 
24*72db608eSbostic static char **buildargv(va_list ap, const char *arg, char ***envpp)
25f8f88d12Swnj {
26*72db608eSbostic 	register size_t max, off;
27*72db608eSbostic 	register char **argv;
28f8f88d12Swnj 
29*72db608eSbostic 	for (off = max = 0;; ++off) {
30*72db608eSbostic 		if (off >= max) {
31*72db608eSbostic 			max += 50;	/* Starts out at 0. */
32*72db608eSbostic 			max *= 2;	/* Ramp up fast. */
33*72db608eSbostic 			if (!(argv = realloc(argv, max * sizeof(char *))))
34*72db608eSbostic 				return(NULL);
35*72db608eSbostic 			if (off == 0) {
36*72db608eSbostic 				argv[0] = (char *)arg;
37*72db608eSbostic 				off = 1;
38f8f88d12Swnj 			}
39f8f88d12Swnj 		}
40*72db608eSbostic 		if (!(argv[off] = va_arg(ap, char *)))
41f8f88d12Swnj 			break;
42*72db608eSbostic 	}
43*72db608eSbostic 	/* Get environment pointer if need user supposed to provide one. */
44*72db608eSbostic 	if (envpp)
45*72db608eSbostic 		*envpp = va_arg(ap, char **);
46*72db608eSbostic 	return(argv);
47*72db608eSbostic }
48*72db608eSbostic 
49*72db608eSbostic int execl(const char *name, const char *arg, ...)
50*72db608eSbostic {
51*72db608eSbostic 	va_list ap;
52*72db608eSbostic 	int sverrno;
53*72db608eSbostic 	char **argv;
54*72db608eSbostic 
55*72db608eSbostic 	va_start(ap, arg);
56*72db608eSbostic 	if (argv = buildargv(ap, arg, (char ***)NULL))
57*72db608eSbostic 		(void)execve(name, argv, environ);
58*72db608eSbostic 	va_end(ap);
59*72db608eSbostic 	sverrno = errno;
60*72db608eSbostic 	free(argv);
61*72db608eSbostic 	errno = sverrno;
62f8f88d12Swnj 	return(-1);
63f8f88d12Swnj }
64*72db608eSbostic 
65*72db608eSbostic int execle(const char *name, const char *arg, ...)
66*72db608eSbostic {
67*72db608eSbostic 	va_list ap;
68*72db608eSbostic 	int sverrno;
69*72db608eSbostic 	char **argv, **envp;
70*72db608eSbostic 
71*72db608eSbostic 	va_start(ap, arg);
72*72db608eSbostic 	if (argv = buildargv(ap, arg, &envp))
73*72db608eSbostic 		(void)execve(name, argv, envp);
74*72db608eSbostic 	va_end(ap);
75*72db608eSbostic 	sverrno = errno;
76*72db608eSbostic 	free(argv);
77*72db608eSbostic 	errno = sverrno;
78*72db608eSbostic 	return(-1);
79*72db608eSbostic }
80*72db608eSbostic 
81*72db608eSbostic int execlp(const char *name, const char *arg, ...)
82*72db608eSbostic {
83*72db608eSbostic 	va_list ap;
84*72db608eSbostic 	int sverrno;
85*72db608eSbostic 	char **argv;
86*72db608eSbostic 
87*72db608eSbostic 	va_start(ap, arg);
88*72db608eSbostic 	if (argv = buildargv(ap, arg, (char ***)NULL))
89*72db608eSbostic 		(void)execvp(name, argv);
90*72db608eSbostic 	va_end(ap);
91*72db608eSbostic 	sverrno = errno;
92*72db608eSbostic 	free(argv);
93*72db608eSbostic 	errno = sverrno;
94*72db608eSbostic 	return(-1);
95*72db608eSbostic }
96*72db608eSbostic 
97*72db608eSbostic int execv(const char *name, char * const *argv)
98*72db608eSbostic {
99*72db608eSbostic 	(void)execve(name, argv, environ);
100*72db608eSbostic 	return(-1);
101*72db608eSbostic }
102*72db608eSbostic 
103*72db608eSbostic int execvp(const char *name, char * const *argv)
104*72db608eSbostic {
105*72db608eSbostic 	register char *p;
106*72db608eSbostic 	int eacces, etxtbsy;
107*72db608eSbostic 	char *cur, *path, buf[MAXPATHLEN];
108*72db608eSbostic 
109*72db608eSbostic 	/* If it's an absolute or relative path name, it's easy. */
110*72db608eSbostic 	if (index(name, '/')) {
111*72db608eSbostic 		(void)execve(name, argv, environ);
112*72db608eSbostic 		return(-1);
113*72db608eSbostic 	}
114*72db608eSbostic 
115*72db608eSbostic 	/* Get the path we're searching. */
116*72db608eSbostic 	if (!(path = getenv("PATH")))
117*72db608eSbostic 		path = _PATH_DEFPATH;
118*72db608eSbostic 	cur = path = strdup(path);
119*72db608eSbostic 
120*72db608eSbostic 	eacces = etxtbsy = 0;
121*72db608eSbostic 	while (p = strsep(&cur, ":")) {
122*72db608eSbostic 		/*
123*72db608eSbostic 		 * It's a SHELL path -- double, leading and trailing colons
124*72db608eSbostic 		 * mean the current directory.
125*72db608eSbostic 		 */
126*72db608eSbostic 		if (!*p)
127*72db608eSbostic 			p = ".";
128*72db608eSbostic 		(void)snprintf(buf, sizeof(buf), "%s/%s", p, name);
129*72db608eSbostic 
130*72db608eSbostic retry:		(void)execve(buf, argv, environ);
131*72db608eSbostic 		switch(errno) {
132*72db608eSbostic 		case EACCES:
133*72db608eSbostic 			eacces = 1;
134*72db608eSbostic 			break;
135*72db608eSbostic 		case ENOENT:
136*72db608eSbostic 			break;
137*72db608eSbostic 		case ENOEXEC: {
138*72db608eSbostic 			register size_t cnt;
139*72db608eSbostic 			register char **ap;
140*72db608eSbostic 
141*72db608eSbostic 			for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
142*72db608eSbostic 			if (ap = malloc((cnt + 2) * sizeof(char *))) {
143*72db608eSbostic 				bcopy(argv, ap + 2, cnt * sizeof(char *));
144*72db608eSbostic 				ap[0] = "sh";
145*72db608eSbostic 				ap[1] = buf;
146*72db608eSbostic 				(void)execve(_PATH_BSHELL, ap, environ);
147*72db608eSbostic 				free(ap);
148*72db608eSbostic 			}
149*72db608eSbostic 			goto done;
150*72db608eSbostic 		}
151*72db608eSbostic 		case ETXTBSY:
152*72db608eSbostic 			if (etxtbsy < 3)
153*72db608eSbostic 				(void)sleep(++etxtbsy);
154*72db608eSbostic 			goto retry;
155*72db608eSbostic 		default:
156*72db608eSbostic 			goto done;
157*72db608eSbostic 		}
158*72db608eSbostic 	}
159f8f88d12Swnj 	if (eacces)
160f8f88d12Swnj 		errno = EACCES;
161*72db608eSbostic 	else if (!errno)
162*72db608eSbostic 		errno = ENOENT;
163*72db608eSbostic done:	free(path);
164f8f88d12Swnj 	return(-1);
165f8f88d12Swnj }
166