]>
Commit | Line | Data |
---|---|---|
320054e8 DG |
1 | #include <stdlib.h> |
2 | #include <string.h> | |
3 | #include <unistd.h> | |
4 | #include <errno.h> | |
5 | #include <limits.h> | |
6 | ||
7 | extern char **__environ; | |
8 | ||
9 | int __execvpe(const char *file, char *const argv[], char *const envp[]) | |
10 | { | |
11 | const char *p, *z, *path = getenv("PATH"); | |
12 | size_t l, k; | |
13 | int seen_eacces = 0; | |
14 | ||
15 | errno = ENOENT; | |
16 | if (!*file) return -1; | |
17 | ||
18 | if (strchr(file, '/')) | |
19 | return execve(file, argv, envp); | |
20 | ||
21 | if (!path) path = "/usr/local/bin:/bin:/usr/bin"; | |
22 | k = strnlen(file, NAME_MAX+1); | |
23 | if (k > NAME_MAX) { | |
24 | errno = ENAMETOOLONG; | |
25 | return -1; | |
26 | } | |
27 | l = strnlen(path, PATH_MAX-1)+1; | |
28 | ||
29 | for(p=path; ; p=z) { | |
30 | char b[l+k+1]; | |
f41256b6 | 31 | z = __strchrnul(p, ':'); |
320054e8 DG |
32 | if (z-p >= l) { |
33 | if (!*z++) break; | |
34 | continue; | |
35 | } | |
36 | memcpy(b, p, z-p); | |
37 | b[z-p] = '/'; | |
38 | memcpy(b+(z-p)+(z>p), file, k+1); | |
39 | execve(b, argv, envp); | |
40 | switch (errno) { | |
41 | case EACCES: | |
42 | seen_eacces = 1; | |
43 | case ENOENT: | |
44 | case ENOTDIR: | |
45 | break; | |
46 | default: | |
47 | return -1; | |
48 | } | |
49 | if (!*z++) break; | |
50 | } | |
51 | if (seen_eacces) errno = EACCES; | |
52 | return -1; | |
53 | } | |
54 | ||
55 | int execvp(const char *file, char *const argv[]) | |
56 | { | |
57 | return __execvpe(file, argv, __environ); | |
58 | } | |
59 | ||
60 | weak_alias(__execvpe, execvpe); |