import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / gen / execvp.c
blobb3a0c42f0cb9ad74f3f90c266e6d5445d274b813
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
31 * execlp(name, arg,...,0) (like execl, but does path search)
32 * execvp(name, argv) (like execv, but does path search)
35 #pragma weak _execlp = execlp
36 #pragma weak _execvp = execvp
38 #include "lint.h"
39 #include <sys/types.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <alloca.h>
43 #include <errno.h>
44 #include <limits.h>
45 #include <stdarg.h>
46 #include <stdlib.h>
47 #include <paths.h>
50 * Passing INHERIT_ENV (which is an invalid pointer) to execvpe causes the
51 * environment to be inherited. This is *only* an implementation detail.
53 #define INHERIT_ENV ((char *const *)~0UL)
55 static const char *execat(const char *, const char *, char *);
57 extern int __xpg4; /* defined in xpg4.c; 0 if not xpg4-compiled program */
59 /*VARARGS1*/
60 int
61 execlp(const char *name, const char *arg0, ...)
63 char **argp;
64 va_list args;
65 char **argvec;
66 int err;
67 int nargs = 0;
68 char *nextarg;
71 * count the number of arguments in the variable argument list
72 * and allocate an argument vector for them on the stack,
73 * adding space for a terminating null pointer at the end
74 * and one additional space for argv[0] which is no longer
75 * counted by the varargs loop.
78 va_start(args, arg0);
80 while (va_arg(args, char *) != NULL)
81 nargs++;
83 va_end(args);
86 * load the arguments in the variable argument list
87 * into the argument vector and add the terminating null pointer
90 va_start(args, arg0);
91 /* workaround for bugid 1242839 */
92 argvec = alloca((size_t)((nargs + 2) * sizeof (char *)));
93 nextarg = va_arg(args, char *);
94 argp = argvec;
95 *argp++ = (char *)arg0;
96 while (nargs-- && nextarg != NULL) {
97 *argp = nextarg;
98 argp++;
99 nextarg = va_arg(args, char *);
101 va_end(args);
102 *argp = NULL;
105 * call execvp()
108 err = execvp(name, argvec);
109 return (err);
113 execvpe(const char *name, char *const *argv, char *const *envp)
115 const char *pathstr;
116 char fname[PATH_MAX+2];
117 char *newargs[256];
118 int i;
119 const char *cp;
120 unsigned etxtbsy = 1;
121 int eacces = 0;
123 if (*name == '\0') {
124 errno = ENOENT;
125 return (-1);
127 if ((pathstr = getenv("PATH")) == NULL) {
128 if (geteuid() == 0 || getuid() == 0) {
129 pathstr = "/usr/bin:/usr/ccs/bin:/usr/bin:"
130 "/opt/SUNWspro/bin:/usr/sbin";
132 } else {
133 pathstr = "/usr/bin:/usr/ccs/bin:"
134 "/opt/SUNWspro/bin:";
137 cp = strchr(name, '/')? (const char *)"": pathstr;
139 do {
140 cp = execat(cp, name, fname);
141 retry:
143 * 4025035 and 4038378
144 * if a filename begins with a "-" prepend "./" so that
145 * the shell can't interpret it as an option
147 if (*fname == '-') {
148 size_t size = strlen(fname) + 1;
149 if ((size + 2) > sizeof (fname)) {
150 errno = E2BIG;
151 return (-1);
153 (void) memmove(fname + 2, fname, size);
154 fname[0] = '.';
155 fname[1] = '/';
157 if (envp == INHERIT_ENV)
158 (void) execv(fname, argv);
159 else
160 (void) execve(fname, argv, envp);
161 switch (errno) {
162 case ENOEXEC:
163 newargs[0] = "sh";
164 newargs[1] = fname;
165 for (i = 1; (newargs[i + 1] = argv[i]) != NULL; ++i) {
166 if (i >= 254) {
167 errno = E2BIG;
168 return (-1);
171 if (envp == INHERIT_ENV)
172 (void) execv(_PATH_BSHELL, newargs);
173 else
174 (void) execve(_PATH_BSHELL, newargs, envp);
175 return (-1);
176 case ETXTBSY:
177 if (++etxtbsy > 5)
178 return (-1);
179 (void) sleep(etxtbsy);
180 goto retry;
181 case EACCES:
182 ++eacces;
183 break;
184 case ENOMEM:
185 case E2BIG:
186 case EFAULT:
187 return (-1);
189 } while (cp);
190 if (eacces)
191 errno = EACCES;
192 return (-1);
196 execvp(const char *name, char *const *argv)
198 return execvpe(name, argv, INHERIT_ENV);
201 static const char *
202 execat(const char *s1, const char *s2, char *si)
204 char *s;
205 int cnt = PATH_MAX + 1; /* number of characters in s2 */
207 s = si;
208 while (*s1 && *s1 != ':') {
209 if (cnt > 0) {
210 *s++ = *s1++;
211 cnt--;
212 } else
213 s1++;
215 if (si != s && cnt > 0) {
216 *s++ = '/';
217 cnt--;
219 while (*s2 && cnt > 0) {
220 *s++ = *s2++;
221 cnt--;
223 *s = '\0';
224 return (*s1 ? ++s1: 0);