exec.c revision 31309
10SN/A/*- 216531Sdfuchs * Copyright (c) 1991, 1993 30SN/A * The Regents of the University of California. All rights reserved. 40SN/A * 50SN/A * Redistribution and use in source and binary forms, with or without 60SN/A * modification, are permitted provided that the following conditions 72362SN/A * are met: 80SN/A * 1. Redistributions of source code must retain the above copyright 92362SN/A * notice, this list of conditions and the following disclaimer. 100SN/A * 2. Redistributions in binary form must reproduce the above copyright 110SN/A * notice, this list of conditions and the following disclaimer in the 120SN/A * documentation and/or other materials provided with the distribution. 130SN/A * 3. All advertising materials mentioning features or use of this software 140SN/A * must display the following acknowledgement: 150SN/A * This product includes software developed by the University of 160SN/A * California, Berkeley and its contributors. 170SN/A * 4. Neither the name of the University nor the names of its contributors 180SN/A * may be used to endorse or promote products derived from this software 190SN/A * without specific prior written permission. 200SN/A * 212362SN/A * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 222362SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 232362SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 240SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 250SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 260SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 270SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 280SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 290SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 300SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 310SN/A * SUCH DAMAGE. 320SN/A */ 330SN/A 340SN/A#if defined(LIBC_SCCS) && !defined(lint) 350SN/A#if 0 360SN/Astatic char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93"; 370SN/A#endif 38277SN/Astatic const char rcsid[] = 3916531Sdfuchs "$Id: exec.c,v 1.6 1997/10/14 07:23:16 bde Exp $"; 400SN/A#endif /* LIBC_SCCS and not lint */ 410SN/A 420SN/A#include <sys/param.h> 430SN/A#include <sys/types.h> 440SN/A#include <sys/stat.h> 450SN/A#include <errno.h> 460SN/A#include <unistd.h> 470SN/A#include <stdlib.h> 480SN/A#include <string.h> 490SN/A#include <stdio.h> 500SN/A#include <paths.h> 510SN/A 520SN/A#if __STDC__ 530SN/A#include <stdarg.h> 540SN/A#else 550SN/A#include <varargs.h> 560SN/A#endif 570SN/A 580SN/Aextern char **environ; 590SN/A 600SN/Astatic char ** 610SN/Abuildargv(ap, arg, envpp) 620SN/A va_list ap; 630SN/A const char *arg; 640SN/A char ***envpp; 650SN/A{ 660SN/A register char **argv, **nargv; 670SN/A register int memsize, off; 680SN/A 690SN/A argv = NULL; 700SN/A for (off = memsize = 0;; ++off) { 710SN/A if (off >= memsize) { 720SN/A memsize += 50; /* Starts out at 0. */ 730SN/A memsize *= 2; /* Ramp up fast. */ 740SN/A nargv = realloc(argv, memsize * sizeof(char *)); 750SN/A if (nargv == NULL) { 760SN/A free(argv); 770SN/A return (NULL); 780SN/A } 790SN/A argv = nargv; 800SN/A if (off == 0) { 810SN/A argv[0] = (char *)arg; 820SN/A off = 1; 830SN/A } 840SN/A } 850SN/A if (!(argv[off] = va_arg(ap, char *))) 860SN/A break; 870SN/A } 880SN/A /* Get environment pointer if user supposed to provide one. */ 890SN/A if (envpp) 900SN/A *envpp = va_arg(ap, char **); 910SN/A return (argv); 920SN/A} 930SN/A 940SN/Aint 950SN/A#if __STDC__ 960SN/Aexecl(const char *name, const char *arg, ...) 970SN/A#else 980SN/Aexecl(name, arg, va_alist) 990SN/A const char *name; 1000SN/A const char *arg; 1010SN/A va_dcl 1020SN/A#endif 1030SN/A{ 1040SN/A va_list ap; 1050SN/A int sverrno; 1060SN/A char **argv; 1070SN/A 1080SN/A#if __STDC__ 1090SN/A va_start(ap, arg); 1100SN/A#else 111469SN/A va_start(ap); 1120SN/A#endif 1130SN/A if ( (argv = buildargv(ap, arg, NULL)) ) 1140SN/A (void)execve(name, argv, environ); 1150SN/A va_end(ap); 1160SN/A sverrno = errno; 1170SN/A free(argv); 1180SN/A errno = sverrno; 1190SN/A return (-1); 1200SN/A} 1210SN/A 1220SN/Aint 1230SN/A#if __STDC__ 1240SN/Aexecle(const char *name, const char *arg, ...) 1250SN/A#else 126277SN/Aexecle(name, arg, va_alist) 1270SN/A const char *name; 1280SN/A const char *arg; 1290SN/A va_dcl 1300SN/A#endif 1310SN/A{ 1320SN/A va_list ap; 1330SN/A int sverrno; 1340SN/A char **argv, **envp; 1358565SN/A 1360SN/A#if __STDC__ 1370SN/A va_start(ap, arg); 1380SN/A#else 1390SN/A va_start(ap); 1400SN/A#endif 1410SN/A if ( (argv = buildargv(ap, arg, &envp)) ) 1420SN/A (void)execve(name, argv, envp); 1430SN/A va_end(ap); 1440SN/A sverrno = errno; 1450SN/A free(argv); 1460SN/A errno = sverrno; 1470SN/A return (-1); 1480SN/A} 1490SN/A 1500SN/Aint 1510SN/A#if __STDC__ 1520SN/Aexeclp(const char *name, const char *arg, ...) 1530SN/A#else 1540SN/Aexeclp(name, arg, va_alist) 1550SN/A const char *name; 1560SN/A const char *arg; 1570SN/A va_dcl 1580SN/A#endif 1590SN/A{ 16016531Sdfuchs va_list ap; 1610SN/A int sverrno; 1620SN/A char **argv; 1630SN/A 16416531Sdfuchs#if __STDC__ 1650SN/A va_start(ap, arg); 1660SN/A#else 1670SN/A va_start(ap); 1680SN/A#endif 1690SN/A if ( (argv = buildargv(ap, arg, NULL)) ) 1700SN/A (void)execvp(name, argv); 1710SN/A va_end(ap); 1720SN/A sverrno = errno; 1730SN/A free(argv); 1740SN/A errno = sverrno; 1750SN/A return (-1); 1760SN/A} 1770SN/A 1780SN/Aint 1790SN/Aexecv(name, argv) 1800SN/A const char *name; 1810SN/A char * const *argv; 1820SN/A{ 1830SN/A (void)execve(name, argv, environ); 1840SN/A return (-1); 1850SN/A} 1860SN/A 1870SN/Aint 1880SN/Aexecvp(name, argv) 1890SN/A const char *name; 1900SN/A char * const *argv; 1910SN/A{ 1920SN/A char **memp; 1930SN/A register int cnt, lp, ln; 1940SN/A register char *p; 1950SN/A int eacces, save_errno; 1960SN/A char *bp, *cur, *path, buf[MAXPATHLEN]; 1970SN/A struct stat sb; 1980SN/A 1990SN/A eacces = 0; 2000SN/A 2010SN/A /* If it's an absolute or relative path name, it's easy. */ 2020SN/A if (index(name, '/')) { 2030SN/A bp = (char *)name; 2040SN/A cur = path = NULL; 2050SN/A goto retry; 2060SN/A } 2070SN/A bp = buf; 2080SN/A 2090SN/A /* If it's an empty path name, fail in the usual POSIX way. */ 2100SN/A if (*name == '\0') { 2110SN/A errno = ENOENT; 2120SN/A return (-1); 2130SN/A } 2140SN/A 2150SN/A /* Get the path we're searching. */ 2160SN/A if (!(path = getenv("PATH"))) 2170SN/A path = _PATH_DEFPATH; 2180SN/A cur = path = strdup(path); 2190SN/A 2200SN/A while ( (p = strsep(&cur, ":")) ) { 2210SN/A /* 2220SN/A * It's a SHELL path -- double, leading and trailing colons 2230SN/A * mean the current directory. 2240SN/A */ 2250SN/A if (!*p) { 2260SN/A p = "."; 2270SN/A lp = 1; 2280SN/A } else 2290SN/A lp = strlen(p); 2300SN/A ln = strlen(name); 2310SN/A 2320SN/A /* 2330SN/A * If the path is too long complain. This is a possible 2340SN/A * security issue; given a way to make the path too long 2350SN/A * the user may execute the wrong program. 2360SN/A */ 2370SN/A if (lp + ln + 2 > sizeof(buf)) { 2380SN/A (void)write(STDERR_FILENO, "execvp: ", 8); 2390SN/A (void)write(STDERR_FILENO, p, lp); 2400SN/A (void)write(STDERR_FILENO, ": path too long\n", 16); 2410SN/A continue; 2420SN/A } 2430SN/A bcopy(p, buf, lp); 2440SN/A buf[lp] = '/'; 2450SN/A bcopy(name, buf + lp + 1, ln); 2460SN/A buf[lp + ln + 1] = '\0'; 2470SN/A 2480SN/Aretry: (void)execve(bp, argv, environ); 2490SN/A switch(errno) { 2500SN/A case E2BIG: 2510SN/A goto done; 2520SN/A case ELOOP: 2530SN/A case ENAMETOOLONG: 2540SN/A case ENOENT: 2550SN/A break; 2560SN/A case ENOEXEC: 2570SN/A for (cnt = 0; argv[cnt]; ++cnt) 2580SN/A ; 2590SN/A memp = malloc((cnt + 2) * sizeof(char *)); 2600SN/A if (memp == NULL) 2610SN/A goto done; 2620SN/A memp[0] = "sh"; 2630SN/A memp[1] = bp; 2640SN/A bcopy(argv + 1, memp + 2, cnt * sizeof(char *)); 2650SN/A (void)execve(_PATH_BSHELL, memp, environ); 2660SN/A free(memp); 2670SN/A goto done; 2680SN/A case ENOMEM: 2690SN/A goto done; 2700SN/A case ENOTDIR: 2710SN/A break; 2720SN/A case ETXTBSY: 2730SN/A /* 2740SN/A * We used to retry here, but sh(1) doesn't. 2750SN/A */ 2760SN/A goto done; 2770SN/A default: 2780SN/A /* 2790SN/A * EACCES may be for an inaccessible directory or 2800SN/A * a non-executable file. Call stat() to decide 2810SN/A * which. This also handles ambiguities for EFAULT 2820SN/A * and EIO, and undocumented errors like ESTALE. 2830SN/A * We hope that the race for a stat() is unimportant. 2840SN/A */ 2850SN/A save_errno = errno; 2860SN/A if (stat(bp, &sb) != 0) 28716531Sdfuchs break; 2880SN/A if (save_errno == EACCES) { 2890SN/A eacces = 1; 2900SN/A continue; 2910SN/A } 2920SN/A errno = save_errno; 2930SN/A goto done; 2940SN/A } 29516531Sdfuchs } 2960SN/A if (eacces) 2970SN/A errno = EACCES; 2980SN/A else 2990SN/A errno = ENOENT; 3000SN/Adone: if (path) 3010SN/A free(path); 3020SN/A return (-1); 3030SN/A} 3040SN/A