From 12eb0e5d8937aa0e32676750b6b66aaabedcb571 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Fri, 30 Aug 2019 16:24:09 -0400 Subject: [PATCH] libroot: Add a private __look_up_in_path function. Refactored out of execvpe. Originally I did this for my attempted change to posix_spawn, but that change turned out to be wrong and actually not that beneficial. This bit seems potentially useful, though, so here it is. --- headers/private/libroot/libroot_private.h | 1 + src/system/libroot/os/image.cpp | 49 +++++++++++++++++++++++ src/system/libroot/posix/unistd/exec.cpp | 46 +++------------------ 3 files changed, 55 insertions(+), 41 deletions(-) diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h index caa9be1cce..1126704be6 100644 --- a/headers/private/libroot/libroot_private.h +++ b/headers/private/libroot/libroot_private.h @@ -23,6 +23,7 @@ extern int __gABIVersion; extern char _single_threaded; /* This determines if a process runs single threaded or not */ +status_t __look_up_in_path(const char *name, char *buffer); status_t __parse_invoke_line(char *invoker, char ***_newArgs, char * const **_oldArgs, int32 *_argCount, const char *arg0); status_t __get_next_image_dependency(image_id id, uint32 *cookie, diff --git a/src/system/libroot/os/image.cpp b/src/system/libroot/os/image.cpp index 8edba44348..e672ce8b8b 100644 --- a/src/system/libroot/os/image.cpp +++ b/src/system/libroot/os/image.cpp @@ -314,6 +314,55 @@ clear_caches(void *address, size_t length, uint32 flags) // #pragma mark - +status_t +__look_up_in_path(const char *file, char *buffer) +{ + // get the PATH + const char* paths = getenv("PATH"); + if (paths == NULL) + return B_ENTRY_NOT_FOUND; + + int fileNameLen = strlen(file); + + // iterate through the paths + const char* pathEnd = paths - 1; + while (pathEnd != NULL) { + paths = pathEnd + 1; + pathEnd = strchr(paths, ':'); + int pathLen = (pathEnd ? pathEnd - paths : strlen(paths)); + + // We skip empty paths and those that would become too long. + // The latter is not really correct, but practically irrelevant. + if (pathLen == 0 + || pathLen + 1 + fileNameLen >= B_PATH_NAME_LENGTH) { + continue; + } + + // concatinate the program path + char path[B_PATH_NAME_LENGTH]; + memcpy(path, paths, pathLen); + path[pathLen] = '\0'; + + if (path[pathLen - 1] != '/') + strcat(path, "/"); + strcat(path, file); + + // check whether it is a file + struct stat st; + if (stat(path, &st) != 0 || !S_ISREG(st.st_mode)) + continue; + + // if executable, we've found what we are looking for + if (access(path, X_OK) == 0) { + strlcpy(buffer, path, B_PATH_NAME_LENGTH); + return B_OK; + } + } + + return B_ENTRY_NOT_FOUND; +} + + static char * next_argument(char **_start, bool separate) { diff --git a/src/system/libroot/posix/unistd/exec.cpp b/src/system/libroot/posix/unistd/exec.cpp index bbc7446655..3e56b127d8 100644 --- a/src/system/libroot/posix/unistd/exec.cpp +++ b/src/system/libroot/posix/unistd/exec.cpp @@ -157,50 +157,14 @@ execvpe(const char* file, char* const argv[], char* const environment[]) // file is just a leaf name, so we have to look it up in the path - // get the PATH - const char* paths = getenv("PATH"); - if (paths == NULL) { - __set_errno(B_ENTRY_NOT_FOUND); + char path[B_PATH_NAME_LENGTH]; + status_t status = __look_up_in_path(file, path); + if (status != B_OK) { + __set_errno(status); return -1; } - int fileNameLen = strlen(file); - - // iterate through the paths - const char* pathEnd = paths - 1; - while (pathEnd != NULL) { - paths = pathEnd + 1; - pathEnd = strchr(paths, ':'); - int pathLen = (pathEnd ? pathEnd - paths : strlen(paths)); - - // We skip empty paths and those that would become too long. - // The latter is not really correct, but practically irrelevant. - if (pathLen == 0 - || pathLen + 1 + fileNameLen >= B_PATH_NAME_LENGTH) { - continue; - } - - // concatinate the program path - char path[B_PATH_NAME_LENGTH]; - memcpy(path, paths, pathLen); - path[pathLen] = '\0'; - - if (path[pathLen - 1] != '/') - strcat(path, "/"); - strcat(path, file); - - // check whether it is a file - struct stat st; - if (stat(path, &st) != 0 || !S_ISREG(st.st_mode)) - continue; - - // if executable, execute it - if (access(path, X_OK) == 0) - return do_exec(path, argv, environment, true); - } - - __set_errno(B_ENTRY_NOT_FOUND); - return -1; + return do_exec(path, argv, environment, true); }