From 8c9688fff4446a1b0f5fe9a9be0c50084726cc4d Mon Sep 17 00:00:00 2001 From: Lexi Winter Date: Wed, 2 Jul 2025 00:33:19 +0100 Subject: CLI cleanups; fix the FreeBSD build --- nihil.posix/CMakeLists.txt | 1 + nihil.posix/execv.ccm | 6 +++- nihil.posix/open.ccm | 16 +++++++++-- nihil.posix/posix.ccm | 1 + nihil.posix/progname.ccm | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 nihil.posix/progname.ccm (limited to 'nihil.posix') 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 // 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(); export inline constexpr auto open_exclusive_lock = open_flags::mask(); export inline constexpr auto open_directory = open_flags::mask(); export inline constexpr auto open_nofollow = open_flags::mask(); -export inline constexpr auto open_nofollow_any = open_flags::mask(); -export inline constexpr auto open_symlink = open_flags::mask(); -export inline constexpr auto open_eventonly = open_flags::mask(); export inline constexpr auto open_close_on_exec = open_flags::mask(); export inline constexpr auto open_resolve_beneath = open_flags::mask(); @@ -62,6 +59,19 @@ export inline constexpr auto open_path = open_flags::mask(); export inline constexpr auto open_empty_path = open_flags::mask(); #endif +// macOS +#ifdef O_NOFOLLOW_ANY +export inline constexpr auto open_nofollow_any = open_flags::mask(); +#endif + +#ifdef O_SYMLINK +export inline constexpr auto open_symlink = open_flags::mask(); +#endif + +#ifdef O_EVTONLY +export inline constexpr auto open_eventonly = open_flags::mask(); +#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 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 // 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 +{ + 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 -- cgit v1.2.3