diff options
| author | Lexi Winter <lexi@le-fay.org> | 2025-06-29 19:19:23 +0100 |
|---|---|---|
| committer | Lexi Winter <lexi@le-fay.org> | 2025-06-29 19:19:23 +0100 |
| commit | a8b0ea58e60bb0326b7f7c8f3c736d89ce9ef1df (patch) | |
| tree | 6dafcf2674780649dcdc2649855722357837a68e /nihil.posix | |
| parent | 4fa6821e0645ff61a9380cd090abff472205c630 (diff) | |
| download | nihil-a8b0ea58e60bb0326b7f7c8f3c736d89ce9ef1df.tar.gz nihil-a8b0ea58e60bb0326b7f7c8f3c736d89ce9ef1df.tar.bz2 | |
wip macOS port
Diffstat (limited to 'nihil.posix')
| -rw-r--r-- | nihil.posix/CMakeLists.txt | 50 | ||||
| -rw-r--r-- | nihil.posix/argv.cc (renamed from nihil.posix/posix.argv.cc) | 0 | ||||
| -rw-r--r-- | nihil.posix/argv.ccm (renamed from nihil.posix/posix.argv.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/ensure_dir.cc (renamed from nihil.posix/posix.ensure_dir.cc) | 0 | ||||
| -rw-r--r-- | nihil.posix/ensure_dir.ccm (renamed from nihil.posix/posix.ensure_dir.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/exec.cc (renamed from nihil.posix/posix.exec.cc) | 0 | ||||
| -rw-r--r-- | nihil.posix/exec.ccm (renamed from nihil.posix/posix.exec.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/executor.ccm | 27 | ||||
| -rw-r--r-- | nihil.posix/execv.cc | 43 | ||||
| -rw-r--r-- | nihil.posix/execv.ccm | 47 | ||||
| -rw-r--r-- | nihil.posix/fd.cc (renamed from nihil.posix/posix.fd.cc) | 0 | ||||
| -rw-r--r-- | nihil.posix/fd.ccm (renamed from nihil.posix/posix.fd.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/fexecv.ccm | 53 | ||||
| -rw-r--r-- | nihil.posix/find_in_path.cc | 52 | ||||
| -rw-r--r-- | nihil.posix/find_in_path.ccm | 24 | ||||
| -rw-r--r-- | nihil.posix/getenv.cc (renamed from nihil.posix/posix.getenv.cc) | 13 | ||||
| -rw-r--r-- | nihil.posix/getenv.ccm (renamed from nihil.posix/posix.getenv.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/open.cc (renamed from nihil.posix/posix.open.cc) | 0 | ||||
| -rw-r--r-- | nihil.posix/open.ccm (renamed from nihil.posix/posix.open.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/open_in_path.cc (renamed from nihil.posix/posix.find_in_path.cc) | 3 | ||||
| -rw-r--r-- | nihil.posix/open_in_path.ccm | 23 | ||||
| -rw-r--r-- | nihil.posix/posix.ccm | 18 | ||||
| -rw-r--r-- | nihil.posix/process.cc (renamed from nihil.posix/posix.process.cc) | 0 | ||||
| -rw-r--r-- | nihil.posix/process.ccm (renamed from nihil.posix/posix.process.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/read_file.ccm (renamed from nihil.posix/posix.read_file.ccm) | 1 | ||||
| -rw-r--r-- | nihil.posix/rename.cc (renamed from nihil.posix/posix.rename.cc) | 0 | ||||
| -rw-r--r-- | nihil.posix/rename.ccm (renamed from nihil.posix/posix.rename.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/spawn.ccm (renamed from nihil.posix/posix.spawn.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/tempfile.cc (renamed from nihil.posix/posix.tempfile.cc) | 0 | ||||
| -rw-r--r-- | nihil.posix/tempfile.ccm (renamed from nihil.posix/posix.tempfile.ccm) | 0 | ||||
| -rw-r--r-- | nihil.posix/write_file.ccm (renamed from nihil.posix/posix.write_file.ccm) | 0 |
31 files changed, 316 insertions, 38 deletions
diff --git a/nihil.posix/CMakeLists.txt b/nihil.posix/CMakeLists.txt index 6f410ce..62f6aaf 100644 --- a/nihil.posix/CMakeLists.txt +++ b/nihil.posix/CMakeLists.txt @@ -2,36 +2,40 @@ add_library(nihil.posix STATIC) target_link_libraries(nihil.posix PRIVATE - nihil.error nihil.flagset nihil.guard nihil.monad) + nihil.core nihil.error nihil.flagset nihil.guard nihil.monad) target_sources(nihil.posix PUBLIC FILE_SET modules TYPE CXX_MODULES FILES posix.ccm - posix.argv.ccm - posix.ensure_dir.ccm - posix.exec.ccm - posix.fd.ccm - posix.getenv.ccm - posix.open.ccm - posix.process.ccm - posix.read_file.ccm - posix.rename.ccm - posix.spawn.ccm - posix.tempfile.ccm - posix.write_file.ccm + argv.ccm + ensure_dir.ccm + exec.ccm + execv.ccm + executor.ccm + fd.ccm + find_in_path.ccm + getenv.ccm + open.ccm + process.ccm + read_file.ccm + rename.ccm + spawn.ccm + tempfile.ccm + write_file.ccm PRIVATE - posix.argv.cc - posix.ensure_dir.cc - posix.exec.cc - posix.getenv.cc - posix.fd.cc - posix.find_in_path.cc - posix.open.cc - posix.process.cc - posix.rename.cc - posix.tempfile.cc + argv.cc + ensure_dir.cc + exec.cc + execv.cc + getenv.cc + fd.cc + find_in_path.cc + open.cc + process.cc + rename.cc + tempfile.cc ) if(NIHIL_TESTS) diff --git a/nihil.posix/posix.argv.cc b/nihil.posix/argv.cc index e6b1389..e6b1389 100644 --- a/nihil.posix/posix.argv.cc +++ b/nihil.posix/argv.cc diff --git a/nihil.posix/posix.argv.ccm b/nihil.posix/argv.ccm index 6f60f4b..6f60f4b 100644 --- a/nihil.posix/posix.argv.ccm +++ b/nihil.posix/argv.ccm diff --git a/nihil.posix/posix.ensure_dir.cc b/nihil.posix/ensure_dir.cc index 88e8898..88e8898 100644 --- a/nihil.posix/posix.ensure_dir.cc +++ b/nihil.posix/ensure_dir.cc diff --git a/nihil.posix/posix.ensure_dir.ccm b/nihil.posix/ensure_dir.ccm index fa92a90..fa92a90 100644 --- a/nihil.posix/posix.ensure_dir.ccm +++ b/nihil.posix/ensure_dir.ccm diff --git a/nihil.posix/posix.exec.cc b/nihil.posix/exec.cc index 5bdcbf7..5bdcbf7 100644 --- a/nihil.posix/posix.exec.cc +++ b/nihil.posix/exec.cc diff --git a/nihil.posix/posix.exec.ccm b/nihil.posix/exec.ccm index 6098318..6098318 100644 --- a/nihil.posix/posix.exec.ccm +++ b/nihil.posix/exec.ccm diff --git a/nihil.posix/executor.ccm b/nihil.posix/executor.ccm new file mode 100644 index 0000000..f348dc8 --- /dev/null +++ b/nihil.posix/executor.ccm @@ -0,0 +1,27 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <concepts> +#include <type_traits> + +export module nihil.posix:executor; + +namespace nihil { + +/* + * A concept to mark spawn executors. + */ + +export struct exec_tag{}; + +export template<typename T> +concept executor = + requires (T e) { + std::same_as<exec_tag, typename std::remove_cvref_t<T>::tag>; + { e.exec() }; + }; + +} // namespace nihil diff --git a/nihil.posix/execv.cc b/nihil.posix/execv.cc new file mode 100644 index 0000000..63f9698 --- /dev/null +++ b/nihil.posix/execv.cc @@ -0,0 +1,43 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <coroutine> +#include <expected> +#include <format> +#include <string> +#include <utility> + +#include <err.h> +#include <fcntl.h> +#include <unistd.h> + +extern char **environ; + +module nihil.posix; + +import nihil.error; +import nihil.monad; + +namespace nihil { + +execv::execv(std::filesystem::path path, argv &&args) noexcept + : m_path(std::move(path)) + , m_args(std::move(args)) +{ +} + +auto execv::exec(this execv &self) -> std::expected<void, error> +{ + ::execve(self.m_path.string().c_str(), self.m_args.data(), environ); + return std::unexpected(error("execve failed", error(std::errc(errno)))); +} + +execv::execv(execv &&) noexcept = default; +execv::execv(execv const &) = default; +auto execv::operator=(this execv &, execv &&) -> execv & = default; +auto execv::operator=(this execv &, execv const &) -> execv & = default; + +} // namespace nihil diff --git a/nihil.posix/execv.ccm b/nihil.posix/execv.ccm new file mode 100644 index 0000000..ca036a1 --- /dev/null +++ b/nihil.posix/execv.ccm @@ -0,0 +1,47 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <expected> +#include <filesystem> +#include <string> + +export module nihil.posix:execv; + +import nihil.error; +import :argv; +import :executor; + +namespace nihil { + +/* + * execv: use a filename and an argument vector to call ::execve(). + * This is the lowest-level executor which all others are implemented + * in terms of, if fexecve is not available. + * + * TODO: Should have a way to pass the environment (envp). + */ +export struct execv final +{ + using tag = exec_tag; + + execv(std::filesystem::path, argv &&) noexcept; + + [[nodiscard]] auto exec(this execv &) -> std::expected<void, error>; + + // Movable + execv(execv &&) noexcept; + auto operator=(this execv &, execv &&) noexcept -> execv &; + + // Copyable. + execv(execv const &); + auto operator=(this execv &, execv const &) -> execv &; + +private: + std::filesystem::path m_path; + argv m_args; +}; + +} // namespace nihil diff --git a/nihil.posix/posix.fd.cc b/nihil.posix/fd.cc index 6d5e54f..6d5e54f 100644 --- a/nihil.posix/posix.fd.cc +++ b/nihil.posix/fd.cc diff --git a/nihil.posix/posix.fd.ccm b/nihil.posix/fd.ccm index b937f46..b937f46 100644 --- a/nihil.posix/posix.fd.ccm +++ b/nihil.posix/fd.ccm diff --git a/nihil.posix/fexecv.ccm b/nihil.posix/fexecv.ccm new file mode 100644 index 0000000..5ad6c62 --- /dev/null +++ b/nihil.posix/fexecv.ccm @@ -0,0 +1,53 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <expected> +#include <string> + +#include "nihil.hh" + +#ifdef NIHIL_HAVE_FEXECVE + +export module nihil.posix:fexecv; + +import nihil.error; +import :argv; +import :executor; +import :fd; + +namespace nihil { + +/* + * fexecv: use a file descriptor and an argument vector to call ::fexecve(). + * This is the lowest-level executor which all others are implemented + * in terms of (if it's available). + * + * TODO: Should have a way to pass the environment (envp). + */ +export struct fexecv final { + using tag = exec_tag; + + fexecv(fd &&execfd, argv &&args) noexcept; + + [[nodiscard]] auto exec(this fexecv &self) + -> std::expected<void, error>; + + // Movable + fexecv(fexecv &&) noexcept; + auto operator=(this fexecv &, fexecv &&) noexcept -> fexecv&; + + // Not copyable (because we hold the open fd object) + fexecv(fexecv const &) = delete; + auto operator=(this fexecv &, fexecv const &) -> fexecv& = delete; + +private: + fd m_execfd; + argv m_args; +}; + +} // namespace nihil + +#endif // NIHIL_HAVE_FEXECVE
\ No newline at end of file diff --git a/nihil.posix/find_in_path.cc b/nihil.posix/find_in_path.cc new file mode 100644 index 0000000..7b03faa --- /dev/null +++ b/nihil.posix/find_in_path.cc @@ -0,0 +1,52 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <filesystem> +#include <optional> +#include <ranges> +#include <string> + +#include <fcntl.h> +#include <paths.h> +#include <unistd.h> + +module nihil.posix; + +namespace nihil { + +auto find_in_path(std::filesystem::path const &file) -> std::optional<std::filesystem::path> +{ + using namespace std::literals; + + auto try_return = [](std::filesystem::path file) + -> std::optional<std::filesystem::path> + { + auto ret = ::access(file.string().c_str(), X_OK); + if (ret == 0) + return {std::move(file)}; + return {}; + }; + + // Absolute pathname skips the search. + if (file.is_absolute()) + return try_return(file); + + auto path = getenv("PATH").value_or(_PATH_DEFPATH); + + for (auto &&dir : path | std::views::split(':')) { + // An empty $PATH element means cwd. + auto sdir = dir.empty() + ? std::filesystem::path(".") + : std::filesystem::path(std::string_view(dir)); + + if (auto ret = try_return(sdir / file); ret) + return ret; + } + + return {}; +} + +} // namespace nihil diff --git a/nihil.posix/find_in_path.ccm b/nihil.posix/find_in_path.ccm new file mode 100644 index 0000000..4988a12 --- /dev/null +++ b/nihil.posix/find_in_path.ccm @@ -0,0 +1,24 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <filesystem> +#include <optional> + +export module nihil.posix:find_in_path; + +import nihil.error; +import :fd; + +namespace nihil { + +/* + * Find an executable in $PATH and return the full path. If $PATH is not set, uses _PATH_DEFPATH. + * If the file can't be found or opened, returns std::nullopt. + */ +export [[nodiscard]] auto find_in_path(std::filesystem::path const &file) + -> std::optional<std::filesystem::path>; + +} // namespace nihil diff --git a/nihil.posix/posix.getenv.cc b/nihil.posix/getenv.cc index 36df950..ad93305 100644 --- a/nihil.posix/posix.getenv.cc +++ b/nihil.posix/getenv.cc @@ -1,4 +1,3 @@ - /* * This source code is released into the public domain. */ @@ -13,6 +12,8 @@ module; #include <unistd.h> +#include "nihil.hh" + module nihil.posix; import nihil.error; @@ -21,10 +22,12 @@ namespace nihil { auto getenv(std::string_view varname) -> std::expected<std::string, error> { + auto cvarname = std::string(varname); + +#ifdef NIHIL_HAVE_GETENV_R // Start with a buffer of this size, and double it every iteration. constexpr auto bufinc = std::size_t{1024}; - auto cvarname = std::string(varname); auto buf = std::vector<char>(bufinc); for (;;) { auto const ret = ::getenv_r(cvarname.c_str(), @@ -40,6 +43,12 @@ auto getenv(std::string_view varname) -> std::expected<std::string, error> return std::unexpected(error(std::errc(errno))); } +#else // NIHIL_HAVE_GETENV_R + auto *v = ::getenv(cvarname.c_str()); + if (v == nullptr) + return std::unexpected(error(std::errc(errno))); + return {std::string(v)}; +#endif // NIHIL_HAVE_GETENV_R } } // namespace nihil diff --git a/nihil.posix/posix.getenv.ccm b/nihil.posix/getenv.ccm index 465f7e7..465f7e7 100644 --- a/nihil.posix/posix.getenv.ccm +++ b/nihil.posix/getenv.ccm diff --git a/nihil.posix/posix.open.cc b/nihil.posix/open.cc index 9ef6538..9ef6538 100644 --- a/nihil.posix/posix.open.cc +++ b/nihil.posix/open.cc diff --git a/nihil.posix/posix.open.ccm b/nihil.posix/open.ccm index eaedacd..eaedacd 100644 --- a/nihil.posix/posix.open.ccm +++ b/nihil.posix/open.ccm diff --git a/nihil.posix/posix.find_in_path.cc b/nihil.posix/open_in_path.cc index 6be963c..30021ca 100644 --- a/nihil.posix/posix.find_in_path.cc +++ b/nihil.posix/open_in_path.cc @@ -16,8 +16,7 @@ module nihil.posix; namespace nihil { -auto find_in_path(std::filesystem::path const &file) - -> std::optional<fd> +auto open_in_path(std::filesystem::path const &file) -> std::optional<fd> { using namespace std::literals; diff --git a/nihil.posix/open_in_path.ccm b/nihil.posix/open_in_path.ccm new file mode 100644 index 0000000..1fae56b --- /dev/null +++ b/nihil.posix/open_in_path.ccm @@ -0,0 +1,23 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <filesystem> +#include <optional> + +export module nihil.posix:find_in_path; + +import nihil.error; +import :fd; + +namespace nihil { + +/* + * Find an executable in $PATH and open it with O_EXEC. If $PATH is not set, uses _PATH_DEFPATH. + * If the file can't be found or opened, returns std::nullopt. + */ +export [[nodiscard]] auto open_in_path(std::filesystem::path const &file) -> std::optional<fd>; + +} // namespace nihil diff --git a/nihil.posix/posix.ccm b/nihil.posix/posix.ccm index e63ad6b..ea13f81 100644 --- a/nihil.posix/posix.ccm +++ b/nihil.posix/posix.ccm @@ -9,6 +9,8 @@ module; #include <optional> #include <string> +#include "nihil.hh" + export module nihil.posix; import nihil.error; @@ -16,7 +18,9 @@ import nihil.error; export import :argv; export import :ensure_dir; export import :exec; +export import :execv; export import :fd; +export import :find_in_path; export import :getenv; export import :open; export import :process; @@ -26,14 +30,6 @@ export import :spawn; export import :tempfile; export import :write_file; -export namespace nihil { - -/* - * Find an executable in $PATH, open it with O_EXEC and return the fd. - * If $PATH is not set, uses _PATH_DEFPATH. If the file can't be found - * or opened, returns std::nullopt. - */ -[[nodiscard]] auto find_in_path(std::filesystem::path const &file) - -> std::optional<fd>; - -} // namespace nihil +#ifdef NIHIL_HAVE_FEXECVE +export import :fexecv; +#endif diff --git a/nihil.posix/posix.process.cc b/nihil.posix/process.cc index 70e84b7..70e84b7 100644 --- a/nihil.posix/posix.process.cc +++ b/nihil.posix/process.cc diff --git a/nihil.posix/posix.process.ccm b/nihil.posix/process.ccm index 425deac..425deac 100644 --- a/nihil.posix/posix.process.ccm +++ b/nihil.posix/process.ccm diff --git a/nihil.posix/posix.read_file.ccm b/nihil.posix/read_file.ccm index c950f67..be9e102 100644 --- a/nihil.posix/posix.read_file.ccm +++ b/nihil.posix/read_file.ccm @@ -4,6 +4,7 @@ module; +#include <algorithm> #include <expected> #include <filesystem> #include <iterator> diff --git a/nihil.posix/posix.rename.cc b/nihil.posix/rename.cc index 9203d08..9203d08 100644 --- a/nihil.posix/posix.rename.cc +++ b/nihil.posix/rename.cc diff --git a/nihil.posix/posix.rename.ccm b/nihil.posix/rename.ccm index 796ec5b..796ec5b 100644 --- a/nihil.posix/posix.rename.ccm +++ b/nihil.posix/rename.ccm diff --git a/nihil.posix/posix.spawn.ccm b/nihil.posix/spawn.ccm index 4cce334..4cce334 100644 --- a/nihil.posix/posix.spawn.ccm +++ b/nihil.posix/spawn.ccm diff --git a/nihil.posix/posix.tempfile.cc b/nihil.posix/tempfile.cc index b1d3dee..b1d3dee 100644 --- a/nihil.posix/posix.tempfile.cc +++ b/nihil.posix/tempfile.cc diff --git a/nihil.posix/posix.tempfile.ccm b/nihil.posix/tempfile.ccm index 82f3be4..82f3be4 100644 --- a/nihil.posix/posix.tempfile.ccm +++ b/nihil.posix/tempfile.ccm diff --git a/nihil.posix/posix.write_file.ccm b/nihil.posix/write_file.ccm index 867e0db..867e0db 100644 --- a/nihil.posix/posix.write_file.ccm +++ b/nihil.posix/write_file.ccm |
