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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /* 33 * execlp(name, arg,...,0) (like execl, but does path search) 34 * execvp(name, argv) (like execv, but does path search) 35 */ 36 37 #pragma weak _execlp = execlp 38 #pragma weak _execvp = execvp 39 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> 49 50 static const char *execat(const char *, const char *, char *); 51 52 extern int __xpg4; /* defined in xpg4.c; 0 if not xpg4-compiled program */ 53 54 /*VARARGS1*/ 55 int 56 execlp(const char *name, const char *arg0, ...) 57 { 58 char **argp; 59 va_list args; 60 char **argvec; 61 int err; 62 int nargs = 0; 63 char *nextarg; 64 65 /* 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. 71 */ 72 73 va_start(args, arg0); 74 75 while (va_arg(args, char *) != (char *)0) 76 nargs++; 77 78 va_end(args); 79 80 /* 81 * load the arguments in the variable argument list 82 * into the argument vector and add the terminating null pointer 83 */ 84 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 *); 95 } 96 va_end(args); 97 *argp = (char *)0; 98 99 /* 100 * call execvp() 101 */ 102 103 err = execvp(name, argvec); 104 return (err); 105 } 106 107 int 108 execvp(const char *name, char *const *argv) 109 { 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"; 121 122 if (*name == '\0') { 123 errno = ENOENT; 124 return (-1); 125 } 126 if ((pathstr = getenv("PATH")) == NULL) { 127 /* 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. 135 */ 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"; 142 } 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:"; 149 } 150 } 151 } 152 cp = strchr(name, '/')? (const char *)"": pathstr; 153 154 do { 155 cp = execat(cp, name, fname); 156 retry: 157 /* 158 * 4025035 and 4038378 159 * if a filename begins with a "-" prepend "./" so that 160 * the shell can't interpret it as an option 161 */ 162 if (*fname == '-') { 163 size_t size = strlen(fname) + 1; 164 if ((size + 2) > sizeof (fname)) { 165 errno = E2BIG; 166 return (-1); 167 } 168 (void) memmove(fname + 2, fname, size); 169 fname[0] = '.'; 170 fname[1] = '/'; 171 } 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; 179 } 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); 186 } 187 } 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); 202 } 203 } while (cp); 204 if (eacces) 205 errno = EACCES; 206 return (-1); 207 } 208 209 static const char * 210 execat(const char *s1, const char *s2, char *si) 211 { 212 char *s; 213 int cnt = PATH_MAX + 1; /* number of characters in s2 */ 214 215 s = si; 216 while (*s1 && *s1 != ':') { 217 if (cnt > 0) { 218 *s++ = *s1++; 219 cnt--; 220 } else 221 s1++; 222 } 223 if (si != s && cnt > 0) { 224 *s++ = '/'; 225 cnt--; 226 } 227 while (*s2 && cnt > 0) { 228 *s++ = *s2++; 229 cnt--; 230 } 231 *s = '\0'; 232 return (*s1 ? ++s1: 0); 233 } 234