// This source code is released into the public domain. module; #include #include // NOLINT: getenv_r #include "nihil.hh" export module nihil.posix:getenv; import nihil.std; import nihil.util; namespace nihil { // Find a variable by the given name in the environment by calling getenv_r() if available, // or getenv() if not. In either case the value is copied, so will not be affected by // future calls to setenv(). export [[nodiscard]] auto getenv(std::string_view varname) -> std::expected { auto errno_guard = save_errno(); auto cvarname = std::string(varname); #if NIHIL_HAVE_GETENV_R == 1 // Start with a buffer of this size, and double it every iteration. constexpr auto bufinc = std::size_t{1024}; auto buf = std::vector(bufinc); for (;;) { auto const ret = ::getenv_r(cvarname.c_str(), buf.data(), buf.size()); if (ret == 0) return {std::string(buf.data())}; if (ret == -1 && errno == ERANGE) { buf.resize(buf.size() * 2); continue; } return std::unexpected(error(std::errc(errno))); } #else // NIHIL_HAVE_GETENV_R // getenv() may not set errno on failure, so initialise it to a reasonable value. errno = ENOENT; auto const *v = ::getenv(cvarname.c_str()); // NOLINT if (v != nullptr) return {std::string(v)}; return error(sys_error()); #endif // NIHIL_HAVE_GETENV_R } } // namespace nihil