aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.posix/process.cc
diff options
context:
space:
mode:
Diffstat (limited to 'nihil.posix/process.cc')
-rw-r--r--nihil.posix/process.cc102
1 files changed, 102 insertions, 0 deletions
diff --git a/nihil.posix/process.cc b/nihil.posix/process.cc
new file mode 100644
index 0000000..70e84b7
--- /dev/null
+++ b/nihil.posix/process.cc
@@ -0,0 +1,102 @@
+/*
+ * This source code is released into the public domain.
+ */
+
+module;
+
+#include <cerrno>
+#include <cstring>
+#include <expected>
+#include <format>
+#include <optional>
+#include <system_error>
+#include <utility>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+module nihil.posix;
+
+import nihil.error;
+
+namespace nihil {
+
+auto wait_result::okay(this wait_result const &self) -> bool
+{
+ return self.status() == 0;
+}
+
+wait_result::operator bool(this wait_result const &self)
+{
+ return self.okay();
+}
+
+auto wait_result::status(this wait_result const &self) -> std::optional<int>
+{
+ if (WIFEXITED(self._status))
+ return WEXITSTATUS(self._status);
+ return {};
+}
+
+auto wait_result::signal(this wait_result const &self) -> std::optional<int>
+{
+ if (WIFSIGNALED(self._status))
+ return WTERMSIG(self._status);
+ return {};
+}
+
+wait_result::wait_result(int status)
+ : _status(status)
+{}
+
+process::process(::pid_t pid)
+ : m_pid(pid)
+{}
+
+process::~process() {
+ if (m_pid == -1)
+ return;
+
+ auto status = int{};
+ std::ignore = waitpid(m_pid, &status, WEXITED);
+}
+
+process::process(process &&other) noexcept
+ : m_pid(std::exchange(other.m_pid, -1))
+{
+}
+
+auto process::operator=(this process &self, process &&other) noexcept
+ -> process &
+{
+ if (&self != &other) {
+ self.m_pid = std::exchange(other.m_pid, -1);
+ }
+
+ return self;
+}
+
+// Get the child's process id.
+auto process::pid(this process const &self) noexcept -> ::pid_t
+{
+ return self.m_pid;
+}
+
+auto process::wait(this process &&self) -> std::expected<wait_result, error>
+{
+ auto status = int{};
+ auto ret = waitpid(self.m_pid, &status, WEXITED);
+ if (ret == -1)
+ return std::unexpected(error(std::errc(errno)));
+
+ return wait_result(status);
+}
+
+auto process::release(this process &&self) -> ::pid_t
+{
+ auto const ret = self.pid();
+ self.m_pid = -1;
+ return ret;
+}
+
+} // namespace nihil