#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <limits.h> | |
#include "libc.h" | |
extern char** __environ; | |
int __execvpe(const char* file, char* const argv[], char* const envp[]) { | |
const char *p, *z, *path = getenv("PATH"); | |
size_t l, k; | |
int seen_eacces = 0; | |
errno = ENOENT; | |
if (!*file) | |
return -1; | |
if (strchr(file, '/')) | |
return execve(file, argv, envp); | |
if (!path) | |
path = "/usr/local/bin:/bin:/usr/bin"; | |
k = strnlen(file, NAME_MAX + 1); | |
if (k > NAME_MAX) { | |
errno = ENAMETOOLONG; | |
return -1; | |
} | |
l = strnlen(path, PATH_MAX - 1) + 1; | |
for (p = path;; p = z) { | |
char b[l + k + 1]; | |
z = strchr(p, ':'); | |
if (!z) | |
z = p + strlen(p); | |
if (z - p >= l) { | |
if (!*z++) | |
break; | |
continue; | |
} | |
memcpy(b, p, z - p); | |
b[z - p] = '/'; | |
memcpy(b + (z - p) + (z > p), file, k + 1); | |
execve(b, argv, envp); | |
if (errno == EACCES) | |
seen_eacces = 1; | |
else if (errno != ENOENT) | |
return -1; | |
if (!*z++) | |
break; | |
} | |
if (seen_eacces) | |
errno = EACCES; | |
return -1; | |
} | |
int execvp(const char* file, char* const argv[]) { | |
return __execvpe(file, argv, __environ); | |
} | |
weak_alias(__execvpe, execvpe); |