| #include "libc.h" |
| #include <errno.h> |
| #include <limits.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| 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); |