1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* Copyright (c) 1988 AT&T */ 30 /* All Rights Reserved */ 31 32 33 /* 34 * execlp(name, arg,...,0) (like execl, but does path search) 35 * execvp(name, argv) (like execv, but does path search) 36 */ 37 #pragma weak execlp = _execlp 38 #pragma weak execvp = _execvp 39 #include "synonyms.h" 40 #include <sys/types.h> 41 #include <unistd.h> 42 #include <string.h> 43 #include <alloca.h> 44 #include <errno.h> 45 #include <limits.h> 46 #include <stdarg.h> 47 #include <stdlib.h> 48 49 static const char *execat(const char *, const char *, char *); 50 51 extern int __xpg4; /* defined in xpg4.c; 0 if not xpg4-compiled program */ 52 53 /*VARARGS1*/ 54 int 55 execlp(const char *name, const char *arg0, ...) 56 { 57 char **argp; 58 va_list args; 59 char **argvec; 60 int err; 61 int nargs = 0; 62 char *nextarg; 63 64 /* 65 * count the number of arguments in the variable argument list 66 * and allocate an argument vector for them on the stack, 67 * adding space for a terminating null pointer at the end 68 * and one additional space for argv[0] which is no longer 69 * counted by the varargs loop. 70 */ 71 72 va_start(args, arg0); 73 74 while (va_arg(args, char *) != (char *)0) 75 nargs++; 76 77 va_end(args); 78 79 /* 80 * load the arguments in the variable argument list 81 * into the argument vector and add the terminating null pointer 82 */ 83 84 va_start(args, arg0); 85 /* workaround for bugid 1242839 */ 86 argvec = alloca((size_t)((nargs + 2) * sizeof (char *))); 87 nextarg = va_arg(args, char *); 88 argp = argvec; 89 *argp++ = (char *)arg0; 90 while (nargs-- && nextarg != (char *)0) { 91 *argp = nextarg; 92 argp++; 93 nextarg = va_arg(args, char *); 94 } 95 va_end(args); 96 *argp = (char *)0; 97 98 /* 99 * call execvp() 100 */ 101 102 err = execvp(name, argvec); 103 return (err); 104 } 105 106 int 107 execvp(const char *name, char *const *argv) 108 { 109 const char *pathstr; 110 char fname[PATH_MAX+2]; 111 char *newargs[256]; 112 int i; 113 const char *cp; 114 unsigned etxtbsy = 1; 115 int eacces = 0; 116 char *shpath; 117 static const char *sun_path = "/bin/sh"; 118 static const char *xpg4_path = "/usr/xpg4/bin/sh"; 119 static const char *shell = "sh"; 120 121 if (*name == '\0') { 122 errno = ENOENT; 123 return (-1); 124 } 125 if ((pathstr = getenv("PATH")) == NULL) { 126 /* 127 * XPG4: pathstr is equivalent to CSPATH, except that 128 * :/usr/sbin is appended when root, and pathstr must end 129 * with a colon when not root. Keep these paths in sync 130 * with CSPATH in confstr.c. Note that pathstr must end 131 * with a colon when not root so that when name doesn't 132 * contain '/', the last call to execat() will result in an 133 * attempt to execv name from the current directory. 134 */ 135 if (geteuid() == 0 || getuid() == 0) { 136 if (__xpg4 == 0) { /* not XPG4 */ 137 pathstr = "/usr/sbin:/usr/ccs/bin:/usr/bin"; 138 } else { /* XPG4 (CSPATH + /usr/sbin) */ 139 pathstr = "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:" 140 "/opt/SUNWspro/bin:/usr/sbin"; 141 } 142 } else { 143 if (__xpg4 == 0) { /* not XPG4 */ 144 pathstr = "/usr/ccs/bin:/usr/bin:"; 145 } else { /* XPG4 (CSPATH) */ 146 pathstr = "/usr/xpg4/bin:/usr/ccs/bin:" 147 "/usr/bin:/opt/SUNWspro/bin:"; 148 } 149 } 150 } 151 cp = strchr(name, '/')? (const char *)"": pathstr; 152 153 do { 154 cp = execat(cp, name, fname); 155 retry: 156 /* 157 * 4025035 and 4038378 158 * if a filename begins with a "-" prepend "./" so that 159 * the shell can't interpret it as an option 160 */ 161 if (*fname == '-') { 162 size_t size = strlen(fname) + 1; 163 if ((size + 2) > sizeof (fname)) { 164 errno = E2BIG; 165 return (-1); 166 } 167 (void) memmove(fname + 2, fname, size); 168 fname[0] = '.'; 169 fname[1] = '/'; 170 } 171 (void) execv(fname, argv); 172 switch (errno) { 173 case ENOEXEC: 174 if (__xpg4 == 0) { /* not XPG4 */ 175 shpath = (char *)sun_path; 176 } else { /* XPG4 */ 177 shpath = (char *)xpg4_path; 178 } 179 newargs[0] = (char *)shell; 180 newargs[1] = fname; 181 for (i = 1; (newargs[i + 1] = argv[i]) != NULL; ++i) { 182 if (i >= 254) { 183 errno = E2BIG; 184 return (-1); 185 } 186 } 187 (void) execv((const char *)shpath, newargs); 188 return (-1); 189 case ETXTBSY: 190 if (++etxtbsy > 5) 191 return (-1); 192 (void) sleep(etxtbsy); 193 goto retry; 194 case EACCES: 195 ++eacces; 196 break; 197 case ENOMEM: 198 case E2BIG: 199 case EFAULT: 200 return (-1); 201 } 202 } while (cp); 203 if (eacces) 204 errno = EACCES; 205 return (-1); 206 } 207 208 static const char * 209 execat(const char *s1, const char *s2, char *si) 210 { 211 char *s; 212 int cnt = PATH_MAX + 1; /* number of characters in s2 */ 213 214 s = si; 215 while (*s1 && *s1 != ':') { 216 if (cnt > 0) { 217 *s++ = *s1++; 218 cnt--; 219 } else 220 s1++; 221 } 222 if (si != s && cnt > 0) { 223 *s++ = '/'; 224 cnt--; 225 } 226 while (*s2 && cnt > 0) { 227 *s++ = *s2++; 228 cnt--; 229 } 230 *s = '\0'; 231 return (*s1 ? ++s1: 0); 232 } 233