diff --git a/libos/include/os/Process.h b/libos/include/os/Process.h index ac2fa586..768a76da 100644 --- a/libos/include/os/Process.h +++ b/libos/include/os/Process.h @@ -59,6 +59,37 @@ namespace os */ static Result exec(StringView path, Slice args, Slice env, bool search_in_path = true); + /** + * @brief Spawn a new process from an executable file. + * + * @param path The new executable's path. + * @param args The argument list to pass to the new process. + * @param search_in_path Determines whether to search in the system binary directories if path is just a name. + * @return Result An error, or the process ID of the new process. + */ + static Result spawn(StringView path, Slice args, bool search_in_path = true); + + /** + * @brief Spawn a new process from an executable file. + * + * @param path The new executable's path. + * @param args The argument list to pass to the new process. + * @param search_in_path Determines whether to search in the system binary directories if path is just a name. + * @return Result An error, or the process ID of the new process. + */ + static Result spawn(StringView path, Slice args, bool search_in_path = true); + + /** + * @brief Spawn a new process from an executable file. + * + * @param path The new executable's path. + * @param args The argument list to pass to the new process. + * @param env The environment to pass to the new process, instead of the current environment. + * @param search_in_path Determines whether to search in the system binary directories if path is just a name. + * @return Result An error, or the process ID of the new process. + */ + static Result spawn(StringView path, Slice args, Slice env, bool search_in_path = true); + // To use as the child argument to wait() to wait for any child. static constexpr pid_t ANY_CHILD = -1; diff --git a/libos/src/Process.cpp b/libos/src/Process.cpp index bf18e12b..af67b900 100644 --- a/libos/src/Process.cpp +++ b/libos/src/Process.cpp @@ -8,11 +8,14 @@ */ #include +#include #include #include #include #include +extern char** environ; + namespace os { Result Process::fork() @@ -64,6 +67,58 @@ namespace os return err(errno); } + static Result do_spawn(const char* path, char** argv, char** envp, bool use_path) + { + pid_t child = fork(); + if (child < 0) return err(errno); + if (child == 0) + { + if (use_path) execvpe(path, argv, envp); + else + execve(path, argv, envp); + _exit(127); + } + return child; + } + + Result Process::spawn(StringView path, Slice args, bool search_in_path) + { + Vector argv; + for (const auto& arg : args) { TRY(argv.try_append(arg.chars())); } + TRY(argv.try_append(nullptr)); + + return do_spawn(path.chars(), const_cast(argv.data()), environ, search_in_path); + } + + Result Process::spawn(StringView path, Slice args, bool search_in_path) + { + Vector argv; + for (const auto& arg : args) + { + TRY(argv.try_append(arg.chars())); + dbgln("os::Process:spawn() adding new argument: %s", arg.chars()); + } + TRY(argv.try_append(nullptr)); + + dbgln("os::Process:spawn() invoking do_spawn(): path=%s, argv=%p, envp=%p", path.chars(), + const_cast(argv.data()), environ); + + return do_spawn(path.chars(), const_cast(argv.data()), environ, search_in_path); + } + + Result Process::spawn(StringView path, Slice args, Slice env, bool search_in_path) + { + Vector argv; + for (const auto& arg : args) { TRY(argv.try_append(arg.chars())); } + TRY(argv.try_append(nullptr)); + + Vector envp; + for (const auto& arg : env) { TRY(envp.try_append(arg.chars())); } + TRY(envp.try_append(nullptr)); + + return do_spawn(path.chars(), const_cast(argv.data()), const_cast(envp.data()), search_in_path); + } + Result Process::wait(pid_t child, int* status, int options) { long rc = syscall(SYS_waitpid, child, status, options);