#pragma once ///@file #include "types.hh" #include "error.hh" #include "file-descriptor.hh" #include #include #include #include #include #include #include #include namespace nix { struct Sink; struct Source; class Pid { pid_t pid = -1; bool separatePG = false; int killSignal = SIGKILL; public: Pid(); explicit Pid(pid_t pid): pid(pid) {} Pid(Pid && other); Pid & operator=(Pid && other); ~Pid() noexcept(false); explicit operator bool() const { return pid != -1; } int kill(); int wait(); void setSeparatePG(bool separatePG); void setKillSignal(int signal); pid_t release(); pid_t get() const { return pid; } }; /** * Kill all processes running under the specified uid by sending them * a SIGKILL. */ void killUser(uid_t uid); /** * Fork a process that runs the given function, and return the child * pid to the caller. */ struct ProcessOptions { std::string errorPrefix = ""; bool dieWithParent = true; bool runExitHandlers = false; /** * use clone() with the specified flags (Linux only) */ int cloneFlags = 0; }; [[nodiscard]] Pid startProcess(std::function fun, const ProcessOptions & options = ProcessOptions()); /** * Run a program and return its stdout in a string (i.e., like the * shell backtick operator). */ std::string runProgram(Path program, bool searchPath = false, const Strings & args = Strings(), bool isInteractive = false); struct RunOptions { Path program; bool searchPath = true; Strings args = {}; std::optional uid = {}; std::optional gid = {}; std::optional chdir = {}; std::optional> environment = {}; bool captureStdout = false; bool mergeStderrToStdout = false; bool isInteractive = false; }; struct [[nodiscard("you must call RunningProgram::wait()")]] RunningProgram { friend RunningProgram runProgram2(const RunOptions & options); private: Path program; Pid pid; std::unique_ptr stdoutSource; AutoCloseFD stdout_; RunningProgram(PathView program, Pid pid, AutoCloseFD stdout); public: RunningProgram() = default; ~RunningProgram(); void wait(); Source * getStdout() const { return stdoutSource.get(); }; }; std::pair runProgram(RunOptions && options); RunningProgram runProgram2(const RunOptions & options); class ExecError : public Error { public: int status; template ExecError(int status, const Args & ... args) : Error(args...), status(status) { } }; /** * Convert the exit status of a child as returned by wait() into an * error string. */ std::string statusToString(int status); bool statusOk(int status); }