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