1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __SCCSID("@(#)exec.c 8.1 (Berkeley) 6/4/93");
34 __FBSDID("$FreeBSD$");
35
36 #include "namespace.h"
37 #include <sys/param.h>
38 #include <sys/stat.h>
39 #include <errno.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <paths.h>
45
46 #include <stdarg.h>
47 #include "un-namespace.h"
48 #include "libc_private.h"
49
50 extern char **environ;
51
52 int
execl(const char * name,const char * arg,...)53 execl(const char *name, const char *arg, ...)
54 {
55 va_list ap;
56 const char **argv;
57 int n;
58
59 va_start(ap, arg);
60 n = 1;
61 while (va_arg(ap, char *) != NULL)
62 n++;
63 va_end(ap);
64 argv = alloca((n + 1) * sizeof(*argv));
65 if (argv == NULL) {
66 errno = ENOMEM;
67 return (-1);
68 }
69 va_start(ap, arg);
70 n = 1;
71 argv[0] = arg;
72 while ((argv[n] = va_arg(ap, char *)) != NULL)
73 n++;
74 va_end(ap);
75 return (_execve(name, __DECONST(char **, argv), environ));
76 }
77
78 int
execle(const char * name,const char * arg,...)79 execle(const char *name, const char *arg, ...)
80 {
81 va_list ap;
82 const char **argv;
83 char **envp;
84 int n;
85
86 va_start(ap, arg);
87 n = 1;
88 while (va_arg(ap, char *) != NULL)
89 n++;
90 va_end(ap);
91 argv = alloca((n + 1) * sizeof(*argv));
92 if (argv == NULL) {
93 errno = ENOMEM;
94 return (-1);
95 }
96 va_start(ap, arg);
97 n = 1;
98 argv[0] = arg;
99 while ((argv[n] = va_arg(ap, char *)) != NULL)
100 n++;
101 envp = va_arg(ap, char **);
102 va_end(ap);
103 return (_execve(name, __DECONST(char **, argv), envp));
104 }
105
106 int
execlp(const char * name,const char * arg,...)107 execlp(const char *name, const char *arg, ...)
108 {
109 va_list ap;
110 const char **argv;
111 int n;
112
113 va_start(ap, arg);
114 n = 1;
115 while (va_arg(ap, char *) != NULL)
116 n++;
117 va_end(ap);
118 argv = alloca((n + 1) * sizeof(*argv));
119 if (argv == NULL) {
120 errno = ENOMEM;
121 return (-1);
122 }
123 va_start(ap, arg);
124 n = 1;
125 argv[0] = arg;
126 while ((argv[n] = va_arg(ap, char *)) != NULL)
127 n++;
128 va_end(ap);
129 return (execvp(name, __DECONST(char **, argv)));
130 }
131
132 int
execv(const char * name,char * const * argv)133 execv(const char *name, char * const *argv)
134 {
135 (void)_execve(name, argv, environ);
136 return (-1);
137 }
138
139 int
execvp(const char * name,char * const * argv)140 execvp(const char *name, char * const *argv)
141 {
142 return (_execvpe(name, argv, environ));
143 }
144
145 static int
execvPe(const char * name,const char * path,char * const * argv,char * const * envp)146 execvPe(const char *name, const char *path, char * const *argv,
147 char * const *envp)
148 {
149 const char **memp;
150 size_t cnt, lp, ln;
151 int eacces, save_errno;
152 char *cur, buf[MAXPATHLEN];
153 const char *p, *bp;
154 struct stat sb;
155
156 eacces = 0;
157
158 /* If it's an absolute or relative path name, it's easy. */
159 if (strchr(name, '/')) {
160 bp = name;
161 cur = NULL;
162 goto retry;
163 }
164 bp = buf;
165
166 /* If it's an empty path name, fail in the usual POSIX way. */
167 if (*name == '\0') {
168 errno = ENOENT;
169 return (-1);
170 }
171
172 cur = alloca(strlen(path) + 1);
173 if (cur == NULL) {
174 errno = ENOMEM;
175 return (-1);
176 }
177 strcpy(cur, path);
178 while ((p = strsep(&cur, ":")) != NULL) {
179 /*
180 * It's a SHELL path -- double, leading and trailing colons
181 * mean the current directory.
182 */
183 if (*p == '\0') {
184 p = ".";
185 lp = 1;
186 } else
187 lp = strlen(p);
188 ln = strlen(name);
189
190 /*
191 * If the path is too long complain. This is a possible
192 * security issue; given a way to make the path too long
193 * the user may execute the wrong program.
194 */
195 if (lp + ln + 2 > sizeof(buf)) {
196 (void)_write(STDERR_FILENO, "execvP: ", 8);
197 (void)_write(STDERR_FILENO, p, lp);
198 (void)_write(STDERR_FILENO, ": path too long\n",
199 16);
200 continue;
201 }
202 bcopy(p, buf, lp);
203 buf[lp] = '/';
204 bcopy(name, buf + lp + 1, ln);
205 buf[lp + ln + 1] = '\0';
206
207 retry: (void)_execve(bp, argv, envp);
208 switch (errno) {
209 case E2BIG:
210 goto done;
211 case ELOOP:
212 case ENAMETOOLONG:
213 case ENOENT:
214 break;
215 case ENOEXEC:
216 for (cnt = 0; argv[cnt]; ++cnt)
217 ;
218 memp = alloca((cnt + 2) * sizeof(char *));
219 if (memp == NULL) {
220 /* errno = ENOMEM; XXX override ENOEXEC? */
221 goto done;
222 }
223 memp[0] = "sh";
224 memp[1] = bp;
225 bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
226 (void)_execve(_PATH_BSHELL,
227 __DECONST(char **, memp), envp);
228 goto done;
229 case ENOMEM:
230 goto done;
231 case ENOTDIR:
232 break;
233 case ETXTBSY:
234 /*
235 * We used to retry here, but sh(1) doesn't.
236 */
237 goto done;
238 default:
239 /*
240 * EACCES may be for an inaccessible directory or
241 * a non-executable file. Call stat() to decide
242 * which. This also handles ambiguities for EFAULT
243 * and EIO, and undocumented errors like ESTALE.
244 * We hope that the race for a stat() is unimportant.
245 */
246 save_errno = errno;
247 if (stat(bp, &sb) != 0)
248 break;
249 if (save_errno == EACCES) {
250 eacces = 1;
251 continue;
252 }
253 errno = save_errno;
254 goto done;
255 }
256 }
257 if (eacces)
258 errno = EACCES;
259 else
260 errno = ENOENT;
261 done:
262 return (-1);
263 }
264
265 int
execvP(const char * name,const char * path,char * const argv[])266 execvP(const char *name, const char *path, char * const argv[])
267 {
268 return execvPe(name, path, argv, environ);
269 }
270
271 int
_execvpe(const char * name,char * const argv[],char * const envp[])272 _execvpe(const char *name, char * const argv[], char * const envp[])
273 {
274 const char *path;
275
276 /* Get the path we're searching. */
277 if ((path = getenv("PATH")) == NULL)
278 path = _PATH_DEFPATH;
279
280 return (execvPe(name, path, argv, envp));
281 }
282