1 /* $OpenBSD: exec.c,v 1.23 2016/03/13 18:34:20 guenther 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 int 44 execl(const char *name, const char *arg, ...) 45 { 46 va_list ap; 47 char **argv; 48 int n; 49 50 va_start(ap, arg); 51 n = 1; 52 while (va_arg(ap, char *) != NULL) 53 n++; 54 va_end(ap); 55 argv = alloca((n + 1) * sizeof(*argv)); 56 if (argv == NULL) { 57 errno = ENOMEM; 58 return (-1); 59 } 60 va_start(ap, arg); 61 n = 1; 62 argv[0] = (char *)arg; 63 while ((argv[n] = va_arg(ap, char *)) != NULL) 64 n++; 65 va_end(ap); 66 return (execve(name, argv, environ)); 67 } 68 DEF_WEAK(execl); 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; 135 size_t lp, ln, len; 136 char *p; 137 int eacces = 0; 138 char *bp, *cur, *path, buf[PATH_MAX]; 139 140 /* 141 * Do not allow null name 142 */ 143 if (name == NULL || *name == '\0') { 144 errno = ENOENT; 145 return (-1); 146 } 147 148 /* If it's an absolute or relative path name, it's easy. */ 149 if (strchr(name, '/')) { 150 bp = (char *)name; 151 cur = path = NULL; 152 goto retry; 153 } 154 bp = buf; 155 156 /* Get the path we're searching. */ 157 if (!(path = getenv("PATH"))) 158 path = _PATH_DEFPATH; 159 len = strlen(path) + 1; 160 cur = alloca(len); 161 if (cur == NULL) { 162 errno = ENOMEM; 163 return (-1); 164 } 165 strlcpy(cur, path, len); 166 path = cur; 167 while ((p = strsep(&cur, ":"))) { 168 /* 169 * It's a SHELL path -- double, leading and trailing colons 170 * mean the current directory. 171 */ 172 if (!*p) { 173 p = "."; 174 lp = 1; 175 } else 176 lp = strlen(p); 177 ln = strlen(name); 178 179 /* 180 * If the path is too long complain. This is a possible 181 * security issue; given a way to make the path too long 182 * the user may execute the wrong program. 183 */ 184 if (lp + ln + 2 > sizeof(buf)) { 185 struct iovec iov[3]; 186 187 iov[0].iov_base = "execvp: "; 188 iov[0].iov_len = 8; 189 iov[1].iov_base = p; 190 iov[1].iov_len = lp; 191 iov[2].iov_base = ": path too long\n"; 192 iov[2].iov_len = 16; 193 (void)writev(STDERR_FILENO, iov, 3); 194 continue; 195 } 196 bcopy(p, buf, lp); 197 buf[lp] = '/'; 198 bcopy(name, buf + lp + 1, ln); 199 buf[lp + ln + 1] = '\0'; 200 201 retry: (void)execve(bp, argv, envp); 202 switch(errno) { 203 case E2BIG: 204 goto done; 205 case EISDIR: 206 case ELOOP: 207 case ENAMETOOLONG: 208 case ENOENT: 209 break; 210 case ENOEXEC: 211 for (cnt = 0; argv[cnt]; ++cnt) 212 ; 213 memp = alloca((cnt + 2) * sizeof(char *)); 214 if (memp == NULL) 215 goto done; 216 memp[0] = "sh"; 217 memp[1] = bp; 218 bcopy(argv + 1, memp + 2, cnt * sizeof(char *)); 219 (void)execve(_PATH_BSHELL, memp, envp); 220 goto done; 221 case ENOMEM: 222 goto done; 223 case ENOTDIR: 224 break; 225 case ETXTBSY: 226 /* 227 * We used to retry here, but sh(1) doesn't. 228 */ 229 goto done; 230 case EACCES: 231 eacces = 1; 232 break; 233 default: 234 goto done; 235 } 236 } 237 if (eacces) 238 errno = EACCES; 239 else if (!errno) 240 errno = ENOENT; 241 done: 242 return (-1); 243 } 244 DEF_WEAK(execvpe); 245 246 int 247 execvp(const char *name, char *const *argv) 248 { 249 return execvpe(name, argv, environ); 250 } 251 DEF_WEAK(execvp); 252 253