LibCore: Add function for searching a file in $PATH

This extracts the logic of searching for a file in $PATH from
System::exec to a separate function.
This commit is contained in:
Itamar 2022-07-16 16:55:44 +03:00 committed by Andreas Kling
parent 01f0ae20b6
commit 91a03bc6ae
Notes: sideshowbarker 2024-07-17 08:42:05 +09:00
2 changed files with 21 additions and 21 deletions

View file

@ -12,6 +12,7 @@
#include <AK/StdLibExtras.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <LibCore/File.h>
#include <LibCore/System.h>
#include <limits.h>
#include <stdarg.h>
@ -931,6 +932,22 @@ ErrorOr<void> adjtime(const struct timeval* delta, struct timeval* old_delta)
}
#endif
ErrorOr<String> find_file_in_path(StringView filename)
{
auto const* path_ptr = getenv("PATH");
StringView path { path_ptr, strlen(path_ptr) };
if (path.is_empty())
path = "/bin:/usr/bin"sv;
auto parts = path.split_view(':');
for (auto& part : parts) {
auto candidate = String::formatted("{}/{}", part, filename);
if (Core::File::exists(candidate)) {
return candidate;
}
}
return Error::from_errno(ENOENT);
}
ErrorOr<void> exec(StringView filename, Span<StringView> arguments, SearchInPath search_in_path, Optional<Span<StringView>> environment)
{
#ifdef __serenity__
@ -971,28 +988,10 @@ ErrorOr<void> exec(StringView filename, Span<StringView> arguments, SearchInPath
return {};
};
if (search_in_path == SearchInPath::Yes && !filename.contains('/')) {
auto const* path_ptr = getenv("PATH");
StringView path { path_ptr, strlen(path_ptr) };
if (path.is_empty())
path = "/bin:/usr/bin"sv;
auto parts = path.split_view(':');
for (auto& part : parts) {
auto candidate = String::formatted("{}/{}", part, filename);
params.path = { candidate.characters(), candidate.length() };
auto result = run_exec(params);
if (result.is_error()) {
if (result.error().code() != ENOENT)
return result.error();
} else {
VERIFY_NOT_REACHED();
}
}
return Error::from_syscall("exec"sv, -ENOENT);
} else {
params.path = { filename.characters_without_null_termination(), filename.length() };
}
bool should_search_in_path = search_in_path == SearchInPath::Yes && !filename.contains('/');
String exec_filename = should_search_in_path ? TRY(find_file_in_path(filename)) : filename.to_string();
params.path = { exec_filename.characters(), exec_filename.length() };
TRY(run_exec(params));
VERIFY_NOT_REACHED();
#else

View file

@ -160,6 +160,7 @@ ErrorOr<Array<int, 2>> pipe2(int flags);
#ifndef AK_OS_ANDROID
ErrorOr<void> adjtime(const struct timeval* delta, struct timeval* old_delta);
#endif
ErrorOr<String> find_file_in_path(StringView filename);
enum class SearchInPath {
No,
Yes,