11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*	$OpenBSD: exec.c,v 1.18 2005/08/08 08:05:34 espie Exp $ */
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*-
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1991, 1993
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    documentation and/or other materials provided with the distribution.
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. Neither the name of the University nor the names of its contributors
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    may be used to endorse or promote products derived from this software
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    without specific prior written permission.
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h>
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/uio.h>
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <unistd.h>
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <limits.h>
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
392cc2b2be692f1d559a09d2066e56e450249cc9c0Carl Shapiro#include <strings.h>
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <paths.h>
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdarg.h>
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <alloca.h>
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectextern char **environ;
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexecl(const char *name, const char *arg, ...)
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_list ap;
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char **argv;
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_start(ap, arg);
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n = 1;
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (va_arg(ap, char *) != NULL)
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n++;
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_end(ap);
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	argv = alloca((n + 1) * sizeof(*argv));
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (argv == NULL) {
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = ENOMEM;
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_start(ap, arg);
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n = 1;
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	argv[0] = (char *)arg;
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((argv[n] = va_arg(ap, char *)) != NULL)
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n++;
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_end(ap);
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (execve(name, argv, environ));
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexecle(const char *name, const char *arg, ...)
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_list ap;
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char **argv, **envp;
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_start(ap, arg);
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n = 1;
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (va_arg(ap, char *) != NULL)
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n++;
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_end(ap);
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	argv = alloca((n + 1) * sizeof(*argv));
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (argv == NULL) {
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = ENOMEM;
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_start(ap, arg);
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n = 1;
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	argv[0] = (char *)arg;
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((argv[n] = va_arg(ap, char *)) != NULL)
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n++;
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	envp = va_arg(ap, char **);
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_end(ap);
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (execve(name, argv, envp));
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexeclp(const char *name, const char *arg, ...)
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_list ap;
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char **argv;
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_start(ap, arg);
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n = 1;
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (va_arg(ap, char *) != NULL)
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n++;
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_end(ap);
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	argv = alloca((n + 1) * sizeof(*argv));
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (argv == NULL) {
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = ENOMEM;
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_start(ap, arg);
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n = 1;
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	argv[0] = (char *)arg;
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((argv[n] = va_arg(ap, char *)) != NULL)
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n++;
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_end(ap);
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (execvp(name, argv));
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexecv(const char *name, char * const *argv)
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	(void)execve(name, argv, environ);
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (-1);
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexecvp(const char *name, char * const *argv)
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char **memp;
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int cnt, lp, ln, len;
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *p;
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int eacces = 0;
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *bp, *cur, *path, buf[MAXPATHLEN];
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Do not allow null name
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (name == NULL || *name == '\0') {
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = ENOENT;
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 	}
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* If it's an absolute or relative path name, it's easy. */
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (strchr(name, '/')) {
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		bp = (char *)name;
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cur = path = NULL;
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		goto retry;
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	bp = buf;
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Get the path we're searching. */
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!(path = getenv("PATH")))
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		path = _PATH_DEFPATH;
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	len = strlen(path) + 1;
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cur = alloca(len);
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (cur == NULL) {
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = ENOMEM;
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	strlcpy(cur, path, len);
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	path = cur;
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((p = strsep(&cur, ":"))) {
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * It's a SHELL path -- double, leading and trailing colons
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * mean the current directory.
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (!*p) {
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			p = ".";
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			lp = 1;
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			lp = strlen(p);
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ln = strlen(name);
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * If the path is too long complain.  This is a possible
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * security issue; given a way to make the path too long
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * the user may execute the wrong program.
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (lp + ln + 2 > (int)sizeof(buf)) {
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			struct iovec iov[3];
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			iov[0].iov_base = "execvp: ";
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			iov[0].iov_len = 8;
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			iov[1].iov_base = p;
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			iov[1].iov_len = lp;
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			iov[2].iov_base = ": path too long\n";
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			iov[2].iov_len = 16;
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(void)writev(STDERR_FILENO, iov, 3);
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
19828a7c35feac8d73b94f99493534dad069afe5049Jim Huang		memcpy(buf, p, lp);
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		buf[lp] = '/';
20028a7c35feac8d73b94f99493534dad069afe5049Jim Huang		memcpy(buf + lp + 1, name, ln);
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		buf[lp + ln + 1] = '\0';
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectretry:		(void)execve(bp, argv, environ);
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch(errno) {
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case E2BIG:
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case EISDIR:
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ELOOP:
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ENAMETOOLONG:
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ENOENT:
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ENOEXEC:
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			for (cnt = 0; argv[cnt]; ++cnt)
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				;
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			memp = alloca((cnt + 2) * sizeof(char *));
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (memp == NULL)
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto done;
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			memp[0] = "sh";
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			memp[1] = bp;
22028a7c35feac8d73b94f99493534dad069afe5049Jim Huang			memcpy(memp + 2, argv + 1, cnt * sizeof(char *));
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(void)execve(_PATH_BSHELL, memp, environ);
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ENOMEM:
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ENOTDIR:
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ETXTBSY:
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * We used to retry here, but sh(1) doesn't.
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case EACCES:
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			eacces = 1;
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (eacces)
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EACCES;
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else if (!errno)
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = ENOENT;
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdone:
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (-1);
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
246