#include "env.h" #include #include #include #ifdef _win_ #include #include "winint.h" #else #include #include #endif /** * On Windows there may be many copies of enviroment variables, there at least two known, one is * manipulated by Win32 API, another by C runtime, so we must be consistent in the choice of * functions used to manipulate them. * * Relevant links: * - http://bugs.python.org/issue16633 * - https://a.yandex-team.ru/review/108892/details */ TMaybe TryGetEnv(const TString& key) { #ifdef _win_ size_t len = GetEnvironmentVariableA(key.data(), nullptr, 0); if (len == 0) { if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) { return Nothing(); } return TString{}; } TVector buffer(len); size_t bufferSize; do { bufferSize = buffer.size(); len = GetEnvironmentVariableA(key.data(), buffer.data(), static_cast(bufferSize)); if (len > bufferSize) { buffer.resize(len); } } while (len > bufferSize); return TString(buffer.data(), len); #else const char* env = getenv(key.data()); if (!env) { return Nothing(); } return TString(env); #endif } TString GetEnv(const TString& key, const TString& def) { TMaybe value = TryGetEnv(key); if (value.Defined()) { return *std::move(value); } return def; } void SetEnv(const TString& key, const TString& value) { bool isOk = false; int errorCode = 0; #ifdef _win_ isOk = SetEnvironmentVariable(key.data(), value.data()); if (!isOk) { errorCode = GetLastError(); } #else isOk = (0 == setenv(key.data(), value.data(), true /*replace*/)); if (!isOk) { errorCode = errno; } #endif Y_ENSURE_EX(isOk, TSystemError() << "failed to SetEnv with error-code " << errorCode); } void UnsetEnv(const TString& key) { bool notFound = false; #ifdef _win_ bool ok = SetEnvironmentVariable(key.c_str(), NULL); notFound = !ok && (GetLastError() == ERROR_ENVVAR_NOT_FOUND); #else bool ok = (0 == unsetenv(key.c_str())); #if defined(_darwin_) notFound = !ok && (errno == EINVAL); #endif #endif Y_ENSURE_EX(ok || notFound, TSystemError() << "failed to unset environment variable " << key.Quote()); }