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