Commit | Line | Data |
---|---|---|
468a338d KB |
1 | /*- |
2 | * Copyright (c) 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
6 | */ | |
7 | ||
2ce81398 | 8 | #if defined(LIBC_SCCS) && !defined(lint) |
57047b12 | 9 | static char sccsid[] = "@(#)exec.c 5.8 (Berkeley) %G%"; |
468a338d | 10 | #endif /* LIBC_SCCS and not lint */ |
b8f253e8 | 11 | |
468a338d KB |
12 | #include <sys/param.h> |
13 | #include <sys/types.h> | |
a69e788c | 14 | #include <errno.h> |
468a338d | 15 | #include <unistd.h> |
c98aae91 | 16 | #include <stdlib.h> |
e0cd943a | 17 | #if __STDC__ |
468a338d | 18 | #include <stdarg.h> |
e0cd943a DS |
19 | #else |
20 | #include <varargs.h> | |
21 | #endif | |
c98aae91 | 22 | #include <string.h> |
468a338d KB |
23 | #include <stdio.h> |
24 | #include <paths.h> | |
25 | ||
26 | extern char **environ; | |
27 | ||
e0cd943a DS |
28 | static char ** |
29 | buildargv(ap, arg, envpp) | |
30 | va_list ap; | |
31 | const char *arg; | |
32 | char ***envpp; | |
468a338d KB |
33 | { |
34 | register size_t max, off; | |
0331f271 | 35 | register char **argv = NULL; |
468a338d KB |
36 | |
37 | for (off = max = 0;; ++off) { | |
38 | if (off >= max) { | |
39 | max += 50; /* Starts out at 0. */ | |
40 | max *= 2; /* Ramp up fast. */ | |
41 | if (!(argv = realloc(argv, max * sizeof(char *)))) | |
42 | return(NULL); | |
43 | if (off == 0) { | |
44 | argv[0] = (char *)arg; | |
45 | off = 1; | |
46 | } | |
47 | } | |
48 | if (!(argv[off] = va_arg(ap, char *))) | |
49 | break; | |
50 | } | |
51 | /* Get environment pointer if need user supposed to provide one. */ | |
52 | if (envpp) | |
53 | *envpp = va_arg(ap, char **); | |
54 | return(argv); | |
55 | } | |
56 | ||
e0cd943a DS |
57 | int |
58 | #if __STDC__ | |
59 | execl(const char *name, const char *arg, ...) | |
60 | #else | |
61 | execl(name, arg, va_alist) | |
62 | const char *name; | |
63 | const char *arg; | |
64 | va_dcl | |
65 | #endif | |
468a338d KB |
66 | { |
67 | va_list ap; | |
68 | int sverrno; | |
69 | char **argv; | |
70 | ||
e0cd943a | 71 | #if __STDC__ |
468a338d | 72 | va_start(ap, arg); |
e0cd943a DS |
73 | #else |
74 | va_start(ap); | |
75 | #endif | |
468a338d KB |
76 | if (argv = buildargv(ap, arg, (char ***)NULL)) |
77 | (void)execve(name, argv, environ); | |
78 | va_end(ap); | |
79 | sverrno = errno; | |
80 | free(argv); | |
81 | errno = sverrno; | |
82 | return(-1); | |
83 | } | |
84 | ||
e0cd943a DS |
85 | int |
86 | #if __STDC__ | |
87 | execle(const char *name, const char *arg, ...) | |
88 | #else | |
89 | execle(name, arg, va_alist) | |
90 | const char *name; | |
91 | const char *arg; | |
92 | va_dcl | |
93 | #endif | |
468a338d KB |
94 | { |
95 | va_list ap; | |
96 | int sverrno; | |
97 | char **argv, **envp; | |
98 | ||
e0cd943a | 99 | #if __STDC__ |
468a338d | 100 | va_start(ap, arg); |
e0cd943a DS |
101 | #else |
102 | va_start(ap); | |
103 | #endif | |
468a338d KB |
104 | if (argv = buildargv(ap, arg, &envp)) |
105 | (void)execve(name, argv, envp); | |
106 | va_end(ap); | |
107 | sverrno = errno; | |
108 | free(argv); | |
109 | errno = sverrno; | |
110 | return(-1); | |
111 | } | |
112 | ||
e0cd943a DS |
113 | int |
114 | #if __STDC__ | |
115 | execlp(const char *name, const char *arg, ...) | |
116 | #else | |
117 | execlp(name, arg, va_alist) | |
118 | const char *name; | |
119 | const char *arg; | |
120 | va_dcl | |
121 | #endif | |
468a338d KB |
122 | { |
123 | va_list ap; | |
124 | int sverrno; | |
125 | char **argv; | |
a69e788c | 126 | |
e0cd943a | 127 | #if __STDC__ |
468a338d | 128 | va_start(ap, arg); |
e0cd943a DS |
129 | #else |
130 | va_start(ap); | |
131 | #endif | |
468a338d KB |
132 | if (argv = buildargv(ap, arg, (char ***)NULL)) |
133 | (void)execvp(name, argv); | |
134 | va_end(ap); | |
135 | sverrno = errno; | |
136 | free(argv); | |
137 | errno = sverrno; | |
138 | return(-1); | |
139 | } | |
a69e788c | 140 | |
e0cd943a DS |
141 | int |
142 | execv(name, argv) | |
143 | const char *name; | |
144 | char * const *argv; | |
a69e788c | 145 | { |
468a338d KB |
146 | (void)execve(name, argv, environ); |
147 | return(-1); | |
a69e788c BJ |
148 | } |
149 | ||
e0cd943a DS |
150 | int |
151 | execvp(name, argv) | |
152 | const char *name; | |
153 | char * const *argv; | |
a69e788c | 154 | { |
468a338d KB |
155 | register char *p; |
156 | int eacces, etxtbsy; | |
57047b12 | 157 | char *bp, *cur, *path, buf[MAXPATHLEN]; |
468a338d KB |
158 | |
159 | /* If it's an absolute or relative path name, it's easy. */ | |
160 | if (index(name, '/')) { | |
57047b12 KB |
161 | bp = (char *)name; |
162 | cur = path = NULL; | |
163 | goto retry; | |
468a338d | 164 | } |
57047b12 | 165 | bp = buf; |
468a338d KB |
166 | |
167 | /* Get the path we're searching. */ | |
168 | if (!(path = getenv("PATH"))) | |
169 | path = _PATH_DEFPATH; | |
170 | cur = path = strdup(path); | |
171 | ||
172 | eacces = etxtbsy = 0; | |
173 | while (p = strsep(&cur, ":")) { | |
174 | /* | |
175 | * It's a SHELL path -- double, leading and trailing colons | |
176 | * mean the current directory. | |
177 | */ | |
178 | if (!*p) | |
179 | p = "."; | |
180 | (void)snprintf(buf, sizeof(buf), "%s/%s", p, name); | |
181 | ||
57047b12 | 182 | retry: (void)execve(bp, argv, environ); |
a69e788c | 183 | switch(errno) { |
468a338d KB |
184 | case EACCES: |
185 | eacces = 1; | |
186 | break; | |
187 | case ENOENT: | |
188 | break; | |
189 | case ENOEXEC: { | |
190 | register size_t cnt; | |
191 | register char **ap; | |
192 | ||
193 | for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt); | |
194 | if (ap = malloc((cnt + 2) * sizeof(char *))) { | |
57047b12 | 195 | bcopy(argv + 1, ap + 2, cnt * sizeof(char *)); |
468a338d | 196 | ap[0] = "sh"; |
57047b12 | 197 | ap[1] = bp; |
468a338d KB |
198 | (void)execve(_PATH_BSHELL, ap, environ); |
199 | free(ap); | |
a69e788c | 200 | } |
468a338d KB |
201 | goto done; |
202 | } | |
a69e788c | 203 | case ETXTBSY: |
468a338d KB |
204 | if (etxtbsy < 3) |
205 | (void)sleep(++etxtbsy); | |
a69e788c | 206 | goto retry; |
468a338d KB |
207 | default: |
208 | goto done; | |
a69e788c | 209 | } |
468a338d | 210 | } |
a69e788c BJ |
211 | if (eacces) |
212 | errno = EACCES; | |
468a338d KB |
213 | else if (!errno) |
214 | errno = ENOENT; | |
57047b12 KB |
215 | done: if (path) |
216 | free(path); | |
a69e788c BJ |
217 | return(-1); |
218 | } |