]> git.saurik.com Git - apple/libc.git/blame - gen/exec.c
Libc-262.3.2.tar.gz
[apple/libc.git] / gen / exec.c
CommitLineData
e9ce8d39
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
734aad71 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
e9ce8d39 7 *
734aad71
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
e9ce8d39
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
734aad71
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
e9ce8d39
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 * Copyright (c) 1991, 1993
27 * The Regents of the University of California. All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57
58#include <sys/param.h>
59#include <sys/types.h>
60#include <sys/uio.h>
61#include <errno.h>
62#include <unistd.h>
63#include <stdlib.h>
64#include <string.h>
65#include <stdio.h>
66#include <paths.h>
67
68#ifdef __STDC__
69#include <stdarg.h>
70#else
71#include <varargs.h>
72#endif
73
74#if defined(__APPLE__)
75#include <crt_externs.h>
76#define environ (*_NSGetEnviron())
77#else
78extern char **environ;
79#endif
80
81int
82#ifdef __STDC__
83execl(const char *name, const char *arg, ...)
84#else
85execl(name, arg, va_alist)
86 const char *name;
87 const char *arg;
88 va_dcl
89#endif
90{
91 va_list ap;
92 char **argv;
93 int n;
94
95#ifdef __STDC__
96 va_start(ap, arg);
97#else
98 va_start(ap);
99#endif
100 n = 1;
101 while (va_arg(ap, char *) != NULL)
102 n++;
103 va_end(ap);
104 argv = alloca((n + 1) * sizeof(*argv));
105 if (argv == NULL) {
106 errno = ENOMEM;
107 return (-1);
108 }
109#ifdef __STDC__
110 va_start(ap, arg);
111#else
112 va_start(ap);
113#endif
114 n = 1;
115 argv[0] = (char *)arg;
116 while ((argv[n] = va_arg(ap, char *)) != NULL)
117 n++;
118 va_end(ap);
119 return (execve(name, argv, environ));
120}
121
122int
123#ifdef __STDC__
124execle(const char *name, const char *arg, ...)
125#else
126execle(name, arg, va_alist)
127 const char *name;
128 const char *arg;
129 va_dcl
130#endif
131{
132 va_list ap;
133 char **argv, **envp;
134 int n;
135
136#ifdef __STDC__
137 va_start(ap, arg);
138#else
139 va_start(ap);
140#endif
141 n = 1;
142 while (va_arg(ap, char *) != NULL)
143 n++;
144 va_end(ap);
145 argv = alloca((n + 1) * sizeof(*argv));
146 if (argv == NULL) {
147 errno = ENOMEM;
148 return (-1);
149 }
150#ifdef __STDC__
151 va_start(ap, arg);
152#else
153 va_start(ap);
154#endif
155 n = 1;
156 argv[0] = (char *)arg;
157 while ((argv[n] = va_arg(ap, char *)) != NULL)
158 n++;
159 envp = va_arg(ap, char **);
160 va_end(ap);
161 return (execve(name, argv, envp));
162}
163
164int
165#ifdef __STDC__
166execlp(const char *name, const char *arg, ...)
167#else
168execlp(name, arg, va_alist)
169 const char *name;
170 const char *arg;
171 va_dcl
172#endif
173{
174 va_list ap;
175 char **argv;
176 int n;
177
178#ifdef __STDC__
179 va_start(ap, arg);
180#else
181 va_start(ap);
182#endif
183 n = 1;
184 while (va_arg(ap, char *) != NULL)
185 n++;
186 va_end(ap);
187 argv = alloca((n + 1) * sizeof(*argv));
188 if (argv == NULL) {
189 errno = ENOMEM;
190 return (-1);
191 }
192#ifdef __STDC__
193 va_start(ap, arg);
194#else
195 va_start(ap);
196#endif
197 n = 1;
198 argv[0] = (char *)arg;
199 while ((argv[n] = va_arg(ap, char *)) != NULL)
200 n++;
201 va_end(ap);
202 return (execvp(name, argv));
203}
204
205int
206execv(name, argv)
207 const char *name;
208 char * const *argv;
209{
210 (void)execve(name, argv, environ);
211 return (-1);
212}
213
214int
215execvp(name, argv)
216 const char *name;
217 char * const *argv;
218{
219 char **memp;
220 register int cnt, lp, ln;
221 register char *p;
222 int eacces = 0, etxtbsy = 0;
223 char *bp, *cur, *path, buf[MAXPATHLEN];
224
225 /*
226 * Do not allow null name
227 */
228 if (name == NULL || *name == '\0') {
229 errno = ENOENT;
230 return (-1);
231 }
232
233 /* If it's an absolute or relative path name, it's easy. */
234 if (strchr(name, '/')) {
235 bp = (char *)name;
236 cur = path = NULL;
237 goto retry;
238 }
239 bp = buf;
240
241 /* Get the path we're searching. */
242 if (!(path = getenv("PATH")))
243 path = _PATH_DEFPATH;
244 cur = alloca(strlen(path) + 1);
245 if (cur == NULL) {
246 errno = ENOMEM;
247 return (-1);
248 }
249 strcpy(cur, path);
250 path = cur;
251 while ((p = strsep(&cur, ":"))) {
252 /*
253 * It's a SHELL path -- double, leading and trailing colons
254 * mean the current directory.
255 */
256 if (!*p) {
257 p = ".";
258 lp = 1;
259 } else
260 lp = strlen(p);
261 ln = strlen(name);
262
263 /*
264 * If the path is too long complain. This is a possible
265 * security issue; given a way to make the path too long
266 * the user may execute the wrong program.
267 */
268 if (lp + ln + 2 > sizeof(buf)) {
269 struct iovec iov[3];
270
271 iov[0].iov_base = "execvp: ";
272 iov[0].iov_len = 8;
273 iov[1].iov_base = p;
274 iov[1].iov_len = lp;
275 iov[2].iov_base = ": path too long\n";
276 iov[2].iov_len = 16;
277 (void)writev(STDERR_FILENO, iov, 3);
278 continue;
279 }
280 bcopy(p, buf, lp);
281 buf[lp] = '/';
282 bcopy(name, buf + lp + 1, ln);
283 buf[lp + ln + 1] = '\0';
284
285retry: (void)execve(bp, argv, environ);
286 switch(errno) {
287 case E2BIG:
288 goto done;
289 case ELOOP:
290 case ENAMETOOLONG:
291 case ENOENT:
292 break;
293 case ENOEXEC:
294 for (cnt = 0; argv[cnt]; ++cnt)
295 ;
296 memp = alloca((cnt + 2) * sizeof(char *));
297 if (memp == NULL)
298 goto done;
299 memp[0] = "sh";
300 memp[1] = bp;
301 bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
302 (void)execve(_PATH_BSHELL, memp, environ);
303 goto done;
304 case ENOMEM:
305 goto done;
306 case ENOTDIR:
307 break;
308 case ETXTBSY:
309 /*
310 * We used to retry here, but sh(1) doesn't.
311 */
312 goto done;
313 case EACCES:
314 eacces = 1;
315 break;
316 default:
317 goto done;
318 }
319 }
320 if (eacces)
321 errno = EACCES;
322 else if (!errno)
323 errno = ENOENT;
324done:
325 return (-1);
326}