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