/* * This source code is released into the public domain. */ #ifndef LFJAIL_PROCESS_HH #define LFJAIL_PROCESS_HH #include namespace lfjail { /* * wait_result: the exit status of a process. */ struct wait_result final { // Return true if the process exited normally with an exit code of // zero, otherwise false. auto okay(this wait_result const &) -> bool; explicit operator bool(this wait_result const &); // Return the exit status, if any. auto status(this wait_result const &) -> std::optional; // Return the exit signal, if any. auto signal(this wait_result const &) -> std::optional; private: friend struct process; int _status; // Construct a new wait_result from the output of waitpid(). wait_result(int status); }; /* * process: represents a process we created, which can be waited for. */ struct process final { process() = delete; process(::pid_t pid); // When destroyed, we automatically wait for the process to // avoid creating zombie processes. ~process(); // Movable. process(process &&) noexcept = default; auto operator=(process &&) noexcept -> process& = default; // Not copyable. process(process const &) = delete; auto operator=(process const &) -> process& = delete; // Get the child's process id. auto pid(this process const &self) noexcept -> ::pid_t; // Wait for this process to exit (by calling waitpid()) and return // its exit status. This destroys the process state, leaving this // object in a moved-from state. auto wait(this process &&) -> wait_result; // Release this process so we won't try to wait for it when // destroying this object. auto release(this process &&) -> ::pid_t; private: ::pid_t _pid; }; } #endif // !LFJAIL_PROCESS_HH