summaryrefslogtreecommitdiffstats
path: root/util/system/env.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/system/env.cpp
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/system/env.cpp')
-rw-r--r--util/system/env.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/util/system/env.cpp b/util/system/env.cpp
new file mode 100644
index 00000000000..ead9b566a5f
--- /dev/null
+++ b/util/system/env.cpp
@@ -0,0 +1,67 @@
+#include "env.h"
+
+#include <util/generic/string.h>
+#include <util/generic/yexception.h>
+
+#ifdef _win_
+ #include <util/generic/vector.h>
+ #include "winint.h"
+#else
+ #include <cerrno>
+ #include <cstdlib>
+#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
+ */
+
+TString GetEnv(const TString& key, const TString& def) {
+#ifdef _win_
+ size_t len = GetEnvironmentVariableA(key.data(), nullptr, 0);
+
+ if (len == 0) {
+ if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
+ return def;
+ }
+ return TString{};
+ }
+
+ TVector<char> buffer(len);
+ size_t bufferSize;
+ do {
+ bufferSize = buffer.size();
+ len = GetEnvironmentVariableA(key.data(), buffer.data(), static_cast<DWORD>(bufferSize));
+ if (len > bufferSize) {
+ buffer.resize(len);
+ }
+ } while (len > bufferSize);
+
+ return TString(buffer.data(), len);
+#else
+ const char* env = getenv(key.data());
+ return env ? TString(env) : def;
+#endif
+}
+
+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);
+}