aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.posix/progname.ccm
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-07-02 00:33:19 +0100
committerLexi Winter <lexi@le-fay.org>2025-07-02 00:33:19 +0100
commit8c9688fff4446a1b0f5fe9a9be0c50084726cc4d (patch)
treeca9a10be5795d976c0cbc73ad1111517bb4e22bf /nihil.posix/progname.ccm
parent47999457e647352ae7e71d43c65e7b39ae5ca567 (diff)
downloadnihil-8c9688fff4446a1b0f5fe9a9be0c50084726cc4d.tar.gz
nihil-8c9688fff4446a1b0f5fe9a9be0c50084726cc4d.tar.bz2
CLI cleanups; fix the FreeBSD build
Diffstat (limited to 'nihil.posix/progname.ccm')
-rw-r--r--nihil.posix/progname.ccm68
1 files changed, 68 insertions, 0 deletions
diff --git a/nihil.posix/progname.ccm b/nihil.posix/progname.ccm
new file mode 100644
index 0000000..127b972
--- /dev/null
+++ b/nihil.posix/progname.ccm
@@ -0,0 +1,68 @@
+// This source code is released into the public domain.
+module;
+
+// progname: wrappers for getprogname and setprogname.
+//
+// setprogname() doesn't copy the provided name, which makes it awkward to provide
+// dynamic values (e.g., std::string). We solve this by making setprogname a guard
+// object which resets the previous progname when it's destroyed. This also happens
+// to be useful in cases like nihil.cli where we want to temporarily set the progname.
+
+#include <stdlib.h> // NOLINT
+
+export module nihil.posix:progname;
+
+import nihil.std;
+
+namespace nihil {
+
+// Get the current program name. We could return std::string_view here, but since
+// the current program name can change unexpectedly, we don't.
+export [[nodiscard]] auto getprogname() -> std::optional<std::string>
+{
+ if (auto const *progname = ::getprogname(); progname != nullptr)
+ return {progname};
+ return {};
+}
+
+// Set the progname name to a new value for the lifetime of this object.
+// Reset it to the previous value when the object is destroyed.
+export struct setprogname final
+{
+ // Set the program name.
+ explicit setprogname(std::string_view const progname)
+ : m_progname(progname)
+ , m_old_progname(::getprogname())
+ {
+ ::setprogname(m_progname.data());
+ }
+
+ // Restore the old name on destruction.
+ ~setprogname()
+ {
+ if (m_old_progname != nullptr)
+ ::setprogname(m_old_progname);
+ }
+
+ // Restore the old program name immediately.
+ auto release() -> void
+ {
+ if (m_old_progname != nullptr) {
+ ::setprogname(m_old_progname);
+ m_old_progname = nullptr;
+ }
+ }
+
+ // Not copyable.
+ setprogname(setprogname const &) = delete;
+ auto operator=(setprogname const &) -> setprogname & = delete;
+
+ // Not movable.
+ setprogname(setprogname &&) = delete;
+ auto operator=(setprogname &&) -> setprogname & = delete;
+
+private:
+ std::string m_progname;
+ char const *m_old_progname;
+};
+} // namespace nihil