6811333 Remove prom_printf() message in emlxs driver
[opensolaris.git] / usr / src / lib / libc / port / gen / execvp.c
blobe46308bc1d670d6f7844d1d0d0c870579e7ff31c
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 */
30 #pragma ident "%Z%%M% %I% %E% SMI"
33 * execlp(name, arg,...,0) (like execl, but does path search)
34 * execvp(name, argv) (like execv, but does path search)
37 #pragma weak _execlp = execlp
38 #pragma weak _execvp = execvp
40 #include "lint.h"
41 #include <sys/types.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <alloca.h>
45 #include <errno.h>
46 #include <limits.h>
47 #include <stdarg.h>
48 #include <stdlib.h>
50 static const char *execat(const char *, const char *, char *);
52 extern int __xpg4; /* defined in xpg4.c; 0 if not xpg4-compiled program */
54 /*VARARGS1*/
55 int
56 execlp(const char *name, const char *arg0, ...)
58 char **argp;
59 va_list args;
60 char **argvec;
61 int err;
62 int nargs = 0;
63 char *nextarg;
66 * count the number of arguments in the variable argument list
67 * and allocate an argument vector for them on the stack,
68 * adding space for a terminating null pointer at the end
69 * and one additional space for argv[0] which is no longer
70 * counted by the varargs loop.
73 va_start(args, arg0);
75 while (va_arg(args, char *) != (char *)0)
76 nargs++;
78 va_end(args);
81 * load the arguments in the variable argument list
82 * into the argument vector and add the terminating null pointer
85 va_start(args, arg0);
86 /* workaround for bugid 1242839 */
87 argvec = alloca((size_t)((nargs + 2) * sizeof (char *)));
88 nextarg = va_arg(args, char *);
89 argp = argvec;
90 *argp++ = (char *)arg0;
91 while (nargs-- && nextarg != (char *)0) {
92 *argp = nextarg;
93 argp++;
94 nextarg = va_arg(args, char *);
96 va_end(args);
97 *argp = (char *)0;
100 * call execvp()
103 err = execvp(name, argvec);
104 return (err);
108 execvp(const char *name, char *const *argv)
110 const char *pathstr;
111 char fname[PATH_MAX+2];
112 char *newargs[256];
113 int i;
114 const char *cp;
115 unsigned etxtbsy = 1;
116 int eacces = 0;
117 char *shpath;
118 static const char *sun_path = "/bin/sh";
119 static const char *xpg4_path = "/usr/xpg4/bin/sh";
120 static const char *shell = "sh";
122 if (*name == '\0') {
123 errno = ENOENT;
124 return (-1);
126 if ((pathstr = getenv("PATH")) == NULL) {
128 * XPG4: pathstr is equivalent to CSPATH, except that
129 * :/usr/sbin is appended when root, and pathstr must end
130 * with a colon when not root. Keep these paths in sync
131 * with CSPATH in confstr.c. Note that pathstr must end
132 * with a colon when not root so that when name doesn't
133 * contain '/', the last call to execat() will result in an
134 * attempt to execv name from the current directory.
136 if (geteuid() == 0 || getuid() == 0) {
137 if (__xpg4 == 0) { /* not XPG4 */
138 pathstr = "/usr/sbin:/usr/ccs/bin:/usr/bin";
139 } else { /* XPG4 (CSPATH + /usr/sbin) */
140 pathstr = "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:"
141 "/opt/SUNWspro/bin:/usr/sbin";
143 } else {
144 if (__xpg4 == 0) { /* not XPG4 */
145 pathstr = "/usr/ccs/bin:/usr/bin:";
146 } else { /* XPG4 (CSPATH) */
147 pathstr = "/usr/xpg4/bin:/usr/ccs/bin:"
148 "/usr/bin:/opt/SUNWspro/bin:";
152 cp = strchr(name, '/')? (const char *)"": pathstr;
154 do {
155 cp = execat(cp, name, fname);
156 retry:
158 * 4025035 and 4038378
159 * if a filename begins with a "-" prepend "./" so that
160 * the shell can't interpret it as an option
162 if (*fname == '-') {
163 size_t size = strlen(fname) + 1;
164 if ((size + 2) > sizeof (fname)) {
165 errno = E2BIG;
166 return (-1);
168 (void) memmove(fname + 2, fname, size);
169 fname[0] = '.';
170 fname[1] = '/';
172 (void) execv(fname, argv);
173 switch (errno) {
174 case ENOEXEC:
175 if (__xpg4 == 0) { /* not XPG4 */
176 shpath = (char *)sun_path;
177 } else { /* XPG4 */
178 shpath = (char *)xpg4_path;
180 newargs[0] = (char *)shell;
181 newargs[1] = fname;
182 for (i = 1; (newargs[i + 1] = argv[i]) != NULL; ++i) {
183 if (i >= 254) {
184 errno = E2BIG;
185 return (-1);
188 (void) execv((const char *)shpath, newargs);
189 return (-1);
190 case ETXTBSY:
191 if (++etxtbsy > 5)
192 return (-1);
193 (void) sleep(etxtbsy);
194 goto retry;
195 case EACCES:
196 ++eacces;
197 break;
198 case ENOMEM:
199 case E2BIG:
200 case EFAULT:
201 return (-1);
203 } while (cp);
204 if (eacces)
205 errno = EACCES;
206 return (-1);
209 static const char *
210 execat(const char *s1, const char *s2, char *si)
212 char *s;
213 int cnt = PATH_MAX + 1; /* number of characters in s2 */
215 s = si;
216 while (*s1 && *s1 != ':') {
217 if (cnt > 0) {
218 *s++ = *s1++;
219 cnt--;
220 } else
221 s1++;
223 if (si != s && cnt > 0) {
224 *s++ = '/';
225 cnt--;
227 while (*s2 && cnt > 0) {
228 *s++ = *s2++;
229 cnt--;
231 *s = '\0';
232 return (*s1 ? ++s1: 0);