1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 17:07:34 +00:00

Userland: Consolidate most PATH resolving into a single implementation

We previously had at least three different implementations for resolving
executables in the PATH, all of which had slightly different
characteristics.

Merge those into a single implementation to keep the behaviour
consistent, and maybe to make that implementation more configurable in
the future.
This commit is contained in:
Tim Schumacher 2022-08-20 18:31:03 +02:00 committed by Linus Groh
parent 39a3775f48
commit 5f99934dce
13 changed files with 74 additions and 95 deletions

View file

@ -953,22 +953,6 @@ 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 = DEFAULT_PATH_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__
@ -1009,8 +993,18 @@ ErrorOr<void> exec(StringView filename, Span<StringView> arguments, SearchInPath
return {};
};
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();
String exec_filename;
if (search_in_path == SearchInPath::Yes) {
auto maybe_executable = Core::File::resolve_executable_from_environment(filename);
if (!maybe_executable.has_value())
return ENOENT;
exec_filename = maybe_executable.release_value();
} else {
exec_filename = filename.to_string();
}
params.path = { exec_filename.characters(), exec_filename.length() };
TRY(run_exec(params));
@ -1039,21 +1033,16 @@ ErrorOr<void> exec(StringView filename, Span<StringView> arguments, SearchInPath
if (search_in_path == SearchInPath::Yes && !filename.contains('/')) {
# if defined(__APPLE__) || defined(__FreeBSD__)
// These BSDs don't support execvpe(), so we'll have to manually search the PATH.
// This is copy-pasted from LibC's execvpe() with minor changes.
ScopedValueRollback errno_rollback(errno);
String path = getenv("PATH");
if (path.is_empty())
path = DEFAULT_PATH;
auto parts = path.split(':');
for (auto& part : parts) {
auto candidate = String::formatted("{}/{}", part, filename);
rc = ::execve(candidate.characters(), argv.data(), envp.data());
if (rc < 0 && errno != ENOENT) {
errno_rollback.set_override_rollback_value(errno);
return Error::from_syscall("exec"sv, rc);
}
auto maybe_executable = Core::File::resolve_executable_from_environment(filename_string);
if (!maybe_executable.has_value()) {
errno_rollback.set_override_rollback_value(ENOENT);
return Error::from_errno(ENOENT);
}
errno_rollback.set_override_rollback_value(ENOENT);
rc = ::execve(maybe_executable.release_value().characters(), argv.data(), envp.data());
# else
rc = ::execvpe(filename_string.characters(), argv.data(), envp.data());
# endif