1 /* $OpenBSD: exec.c,v 1.21 2013/09/30 12:02:33 millert 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/types.h> 32 #include <sys/uio.h> 33 34 #include <errno.h> 35 #include <limits.h> 36 #include <paths.h> 37 #include <stdarg.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 extern char **environ; 44 45 int 46 execl(const char *name, const char *arg, ...) 47 { 48 va_list ap; 49 char **argv; 50 int n; 51 52 va_start(ap, arg); 53 n = 1; 54 while (va_arg(ap, char *) != NULL) 55 n++; 56 va_end(ap); 57 argv = alloca((n + 1) * sizeof(*argv)); 58 if (argv == NULL) { 59 errno = ENOMEM; 60 return (-1); 61 } 62 va_start(ap, arg); 63 n = 1; 64 argv[0] = (char *)arg; 65 while ((argv[n] = va_arg(ap, char *)) != NULL) 66 n++; 67 va_end(ap); 68 return (execve(name, argv, environ)); 69 } 70 71 int 72 execle(const char *name, const char *arg, ...) 73 { 74 va_list ap; 75 char **argv, **envp; 76 int n; 77 78 va_start(ap, arg); 79 n = 1; 80 while (va_arg(ap, char *) != NULL) 81 n++; 82 va_end(ap); 83 argv = alloca((n + 1) * sizeof(*argv)); 84 if (argv == NULL) { 85 errno = ENOMEM; 86 return (-1); 87 } 88 va_start(ap, arg); 89 n = 1; 90 argv[0] = (char *)arg; 91 while ((argv[n] = va_arg(ap, char *)) != NULL) 92 n++; 93 envp = va_arg(ap, char **); 94 va_end(ap); 95 return (execve(name, argv, envp)); 96 } 97 98 int 99 execlp(const char *name, const char *arg, ...) 100 { 101 va_list ap; 102 char **argv; 103 int n; 104 105 va_start(ap, arg); 106 n = 1; 107 while (va_arg(ap, char *) != NULL) 108 n++; 109 va_end(ap); 110 argv = alloca((n + 1) * sizeof(*argv)); 111 if (argv == NULL) { 112 errno = ENOMEM; 113 return (-1); 114 } 115 va_start(ap, arg); 116 n = 1; 117 argv[0] = (char *)arg; 118 while ((argv[n] = va_arg(ap, char *)) != NULL) 119 n++; 120 va_end(ap); 121 return (execvp(name, argv)); 122 } 123 124 int 125 execv(const char *name, char *const *argv) 126 { 127 (void)execve(name, argv, environ); 128 return (-1); 129 } 130 131 int 132 execvpe(const char *name, char *const *argv, char *const *envp) 133 { 134 char **memp; 135 int cnt; 136 size_t lp, ln, len; 137 char *p; 138 int eacces = 0; 139 char *bp, *cur, *path, buf[PATH_MAX]; 140 141 /* 142 * Do not allow null name 143 */ 144 if (name == NULL || *name == '\0') { 145 errno = ENOENT; 146 return (-1); 147 } 148 149 /* If it's an absolute or relative path name, it's easy. */ 150 if (strchr(name, '/')) { 151 bp = (char *)name; 152 cur = path = NULL; 153 goto retry; 154 } 155 bp = buf; 156 157 /* Get the path we're searching. */ 158 if (!(path = getenv("PATH"))) 159 path = _PATH_DEFPATH; 160 len = strlen(path) + 1; 161 cur = alloca(len); 162 if (cur == NULL) { 163 errno = ENOMEM; 164 return (-1); 165 } 166 strlcpy(cur, path, len); 167 path = cur; 168 while ((p = strsep(&cur, ":"))) { 169 /* 170 * It's a SHELL path -- double, leading and trailing colons 171 * mean the current directory. 172 */ 173 if (!*p) { 174 p = "."; 175 lp = 1; 176 } else 177 lp = strlen(p); 178 ln = strlen(name); 179 180 /* 181 * If the path is too long complain. This is a possible 182 * security issue; given a way to make the path too long 183 * the user may execute the wrong program. 184 */ 185 if (lp + ln + 2 > sizeof(buf)) { 186 struct iovec iov[3]; 187 188 iov[0].iov_base = "execvp: "; 189 iov[0].iov_len = 8; 190 iov[1].iov_base = p; 191 iov[1].iov_len = lp; 192 iov[2].iov_base = ": path too long\n"; 193 iov[2].iov_len = 16; 194 (void)writev(STDERR_FILENO, iov, 3); 195 continue; 196 } 197 bcopy(p, buf, lp); 198 buf[lp] = '/'; 199 bcopy(name, buf + lp + 1, ln); 200 buf[lp + ln + 1] = '\0'; 201 202 retry: (void)execve(bp, argv, envp); 203 switch(errno) { 204 case E2BIG: 205 goto done; 206 case EISDIR: 207 case ELOOP: 208 case ENAMETOOLONG: 209 case ENOENT: 210 break; 211 case ENOEXEC: 212 for (cnt = 0; argv[cnt]; ++cnt) 213 ; 214 memp = alloca((cnt + 2) * sizeof(char *)); 215 if (memp == NULL) 216 goto done; 217 memp[0] = "sh"; 218 memp[1] = bp; 219 bcopy(argv + 1, memp + 2, cnt * sizeof(char *)); 220 (void)execve(_PATH_BSHELL, memp, envp); 221 goto done; 222 case ENOMEM: 223 goto done; 224 case ENOTDIR: 225 break; 226 case ETXTBSY: 227 /* 228 * We used to retry here, but sh(1) doesn't. 229 */ 230 goto done; 231 case EACCES: 232 eacces = 1; 233 break; 234 default: 235 goto done; 236 } 237 } 238 if (eacces) 239 errno = EACCES; 240 else if (!errno) 241 errno = ENOENT; 242 done: 243 return (-1); 244 } 245 246 int 247 execvp(const char *name, char *const *argv) 248 { 249 return execvpe(name, argv, environ); 250 } 251 252