1 /* $OpenBSD: exec.c,v 1.19 2012/03/21 23:20:35 matthew Exp $ */ 2 /*- 3 * Copyright (c) 1991, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/uio.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <stdio.h> 39 #include <paths.h> 40 #include <stdarg.h> 41 42 extern char **environ; 43 44 int 45 execl(const char *name, const char *arg, ...) 46 { 47 va_list ap; 48 char **argv; 49 int n; 50 51 va_start(ap, arg); 52 n = 1; 53 while (va_arg(ap, char *) != NULL) 54 n++; 55 va_end(ap); 56 argv = alloca((n + 1) * sizeof(*argv)); 57 if (argv == NULL) { 58 errno = ENOMEM; 59 return (-1); 60 } 61 va_start(ap, arg); 62 n = 1; 63 argv[0] = (char *)arg; 64 while ((argv[n] = va_arg(ap, char *)) != NULL) 65 n++; 66 va_end(ap); 67 return (execve(name, argv, environ)); 68 } 69 70 int 71 execle(const char *name, const char *arg, ...) 72 { 73 va_list ap; 74 char **argv, **envp; 75 int n; 76 77 va_start(ap, arg); 78 n = 1; 79 while (va_arg(ap, char *) != NULL) 80 n++; 81 va_end(ap); 82 argv = alloca((n + 1) * sizeof(*argv)); 83 if (argv == NULL) { 84 errno = ENOMEM; 85 return (-1); 86 } 87 va_start(ap, arg); 88 n = 1; 89 argv[0] = (char *)arg; 90 while ((argv[n] = va_arg(ap, char *)) != NULL) 91 n++; 92 envp = va_arg(ap, char **); 93 va_end(ap); 94 return (execve(name, argv, envp)); 95 } 96 97 int 98 execlp(const char *name, const char *arg, ...) 99 { 100 va_list ap; 101 char **argv; 102 int n; 103 104 va_start(ap, arg); 105 n = 1; 106 while (va_arg(ap, char *) != NULL) 107 n++; 108 va_end(ap); 109 argv = alloca((n + 1) * sizeof(*argv)); 110 if (argv == NULL) { 111 errno = ENOMEM; 112 return (-1); 113 } 114 va_start(ap, arg); 115 n = 1; 116 argv[0] = (char *)arg; 117 while ((argv[n] = va_arg(ap, char *)) != NULL) 118 n++; 119 va_end(ap); 120 return (execvp(name, argv)); 121 } 122 123 int 124 execv(const char *name, char *const *argv) 125 { 126 (void)execve(name, argv, environ); 127 return (-1); 128 } 129 130 int 131 execvpe(const char *name, char *const *argv, char *const *envp) 132 { 133 char **memp; 134 int cnt, lp, ln, len; 135 char *p; 136 int eacces = 0; 137 char *bp, *cur, *path, buf[MAXPATHLEN]; 138 139 /* 140 * Do not allow null name 141 */ 142 if (name == NULL || *name == '\0') { 143 errno = ENOENT; 144 return (-1); 145 } 146 147 /* If it's an absolute or relative path name, it's easy. */ 148 if (strchr(name, '/')) { 149 bp = (char *)name; 150 cur = path = NULL; 151 goto retry; 152 } 153 bp = buf; 154 155 /* Get the path we're searching. */ 156 if (!(path = getenv("PATH"))) 157 path = _PATH_DEFPATH; 158 len = strlen(path) + 1; 159 cur = alloca(len); 160 if (cur == NULL) { 161 errno = ENOMEM; 162 return (-1); 163 } 164 strlcpy(cur, path, len); 165 path = cur; 166 while ((p = strsep(&cur, ":"))) { 167 /* 168 * It's a SHELL path -- double, leading and trailing colons 169 * mean the current directory. 170 */ 171 if (!*p) { 172 p = "."; 173 lp = 1; 174 } else 175 lp = strlen(p); 176 ln = strlen(name); 177 178 /* 179 * If the path is too long complain. This is a possible 180 * security issue; given a way to make the path too long 181 * the user may execute the wrong program. 182 */ 183 if (lp + ln + 2 > sizeof(buf)) { 184 struct iovec iov[3]; 185 186 iov[0].iov_base = "execvp: "; 187 iov[0].iov_len = 8; 188 iov[1].iov_base = p; 189 iov[1].iov_len = lp; 190 iov[2].iov_base = ": path too long\n"; 191 iov[2].iov_len = 16; 192 (void)writev(STDERR_FILENO, iov, 3); 193 continue; 194 } 195 bcopy(p, buf, lp); 196 buf[lp] = '/'; 197 bcopy(name, buf + lp + 1, ln); 198 buf[lp + ln + 1] = '\0'; 199 200 retry: (void)execve(bp, argv, envp); 201 switch(errno) { 202 case E2BIG: 203 goto done; 204 case EISDIR: 205 case ELOOP: 206 case ENAMETOOLONG: 207 case ENOENT: 208 break; 209 case ENOEXEC: 210 for (cnt = 0; argv[cnt]; ++cnt) 211 ; 212 memp = alloca((cnt + 2) * sizeof(char *)); 213 if (memp == NULL) 214 goto done; 215 memp[0] = "sh"; 216 memp[1] = bp; 217 bcopy(argv + 1, memp + 2, cnt * sizeof(char *)); 218 (void)execve(_PATH_BSHELL, memp, envp); 219 goto done; 220 case ENOMEM: 221 goto done; 222 case ENOTDIR: 223 break; 224 case ETXTBSY: 225 /* 226 * We used to retry here, but sh(1) doesn't. 227 */ 228 goto done; 229 case EACCES: 230 eacces = 1; 231 break; 232 default: 233 goto done; 234 } 235 } 236 if (eacces) 237 errno = EACCES; 238 else if (!errno) 239 errno = ENOENT; 240 done: 241 return (-1); 242 } 243 244 int 245 execvp(const char *name, char *const *argv) 246 { 247 return execvpe(name, argv, environ); 248 } 249 250