aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.posix
diff options
context:
space:
mode:
Diffstat (limited to 'nihil.posix')
-rw-r--r--nihil.posix/CMakeLists.txt1
-rw-r--r--nihil.posix/execv.ccm6
-rw-r--r--nihil.posix/open.ccm16
-rw-r--r--nihil.posix/posix.ccm1
-rw-r--r--nihil.posix/progname.ccm68
5 files changed, 88 insertions, 4 deletions
diff --git a/nihil.posix/CMakeLists.txt b/nihil.posix/CMakeLists.txt
index d76ae4d..25f13f1 100644
--- a/nihil.posix/CMakeLists.txt
+++ b/nihil.posix/CMakeLists.txt
@@ -30,6 +30,7 @@ target_sources(nihil.posix
open_in_path.ccm
paths.ccm
process.ccm
+ progname.ccm
read_file.ccm
rename.ccm
spawn.ccm
diff --git a/nihil.posix/execv.ccm b/nihil.posix/execv.ccm
index d598d94..cd501f7 100644
--- a/nihil.posix/execv.ccm
+++ b/nihil.posix/execv.ccm
@@ -3,6 +3,10 @@ module;
#include <unistd.h> // execv()
+#include "nihil.hh"
+
+extern char **environ; // NOLINT
+
export module nihil.posix:execv;
import nihil.std;
@@ -56,7 +60,7 @@ export struct execv final
[&] (fd const &file) {
#if NIHIL_HAVE_FEXECVE == 1
- ::fexecv(file.get(), self.m_args.data());
+ ::fexecve(file.get(), self.m_args.data(), environ);
return std::unexpected(error("execve failed", error(sys_error())));
#else
std::ignore = file;
diff --git a/nihil.posix/open.ccm b/nihil.posix/open.ccm
index f2f5ecd..a5a9e5d 100644
--- a/nihil.posix/open.ccm
+++ b/nihil.posix/open.ccm
@@ -39,9 +39,6 @@ export inline constexpr auto open_shared_lock = open_flags::mask<O_SHLOCK>();
export inline constexpr auto open_exclusive_lock = open_flags::mask<O_EXLOCK>();
export inline constexpr auto open_directory = open_flags::mask<O_DIRECTORY>();
export inline constexpr auto open_nofollow = open_flags::mask<O_NOFOLLOW>();
-export inline constexpr auto open_nofollow_any = open_flags::mask<O_NOFOLLOW_ANY>();
-export inline constexpr auto open_symlink = open_flags::mask<O_SYMLINK>();
-export inline constexpr auto open_eventonly = open_flags::mask<O_EVTONLY>();
export inline constexpr auto open_close_on_exec = open_flags::mask<O_CLOEXEC>();
export inline constexpr auto open_resolve_beneath = open_flags::mask<O_RESOLVE_BENEATH>();
@@ -62,6 +59,19 @@ export inline constexpr auto open_path = open_flags::mask<O_PATH>();
export inline constexpr auto open_empty_path = open_flags::mask<O_EMPTY_PATH>();
#endif
+// macOS
+#ifdef O_NOFOLLOW_ANY
+export inline constexpr auto open_nofollow_any = open_flags::mask<O_NOFOLLOW_ANY>();
+#endif
+
+#ifdef O_SYMLINK
+export inline constexpr auto open_symlink = open_flags::mask<O_SYMLINK>();
+#endif
+
+#ifdef O_EVTONLY
+export inline constexpr auto open_eventonly = open_flags::mask<O_EVTONLY>();
+#endif
+
// Open the given file and return an fd for it.
export [[nodiscard]] auto open(std::filesystem::path const &filename, open_flags flags,
int mode = 0777) -> std::expected<fd, error>
diff --git a/nihil.posix/posix.ccm b/nihil.posix/posix.ccm
index aa21649..c80724d 100644
--- a/nihil.posix/posix.ccm
+++ b/nihil.posix/posix.ccm
@@ -19,6 +19,7 @@ export import :open;
export import :open_in_path;
export import :paths;
export import :process;
+export import :progname;
export import :read_file;
export import :rename;
export import :spawn;
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