/** * @file Process.cpp * @author apio (cloudapio.eu) * @brief Functions to manipulate processes. * * @copyright Copyright (c) 2023, the Luna authors. * */ #include #include #include #include #include extern char** environ; namespace os { Result Process::fork() { long rc = syscall(SYS_fork); return Result::from_syscall(rc); } Result Process::exec(StringView path, Slice args, bool search_in_path) { Vector argv; TRY(argv.try_reserve(args.size() + 1)); for (const auto& arg : args) { TRY(argv.try_append(arg.chars())); } TRY(argv.try_append(nullptr)); if (search_in_path) execvp(path.chars(), const_cast(argv.data())); else execv(path.chars(), const_cast(argv.data())); return err(errno); } Result Process::exec(StringView path, Slice args, bool search_in_path) { Vector argv; TRY(argv.try_reserve(args.size() + 1)); for (const auto& arg : args) { TRY(argv.try_append(arg.chars())); } TRY(argv.try_append(nullptr)); if (search_in_path) execvp(path.chars(), const_cast(argv.data())); else execv(path.chars(), const_cast(argv.data())); return err(errno); } Result Process::exec(StringView path, Slice args, Slice env, bool search_in_path) { Vector argv; TRY(argv.try_reserve(args.size() + 1)); for (const auto& arg : args) { TRY(argv.try_append(arg.chars())); } TRY(argv.try_append(nullptr)); Vector envp; TRY(envp.try_reserve(env.size() + 1)); for (const auto& arg : env) { TRY(envp.try_append(arg.chars())); } TRY(envp.try_append(nullptr)); if (search_in_path) execvpe(path.chars(), const_cast(argv.data()), const_cast(envp.data())); else execve(path.chars(), const_cast(argv.data()), const_cast(envp.data())); 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; TRY(argv.try_reserve(args.size() + 1)); 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; TRY(argv.try_reserve(args.size() + 1)); 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, Slice env, bool search_in_path) { Vector argv; TRY(argv.try_reserve(args.size() + 1)); for (const auto& arg : args) { TRY(argv.try_append(arg.chars())); } TRY(argv.try_append(nullptr)); Vector envp; TRY(envp.try_reserve(env.size() + 1)); 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); return Result::from_syscall(rc); } Result Process::kill(pid_t pid, int signo) { long rc = syscall(SYS_kill, pid, signo); return Result::from_syscall(rc); } [[noreturn]] void Process::exit(int status) { ::exit(status); } }