env.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include "env.h"
  2. #include <util/generic/maybe.h>
  3. #include <util/generic/string.h>
  4. #include <util/generic/yexception.h>
  5. #ifdef _win_
  6. #include <util/generic/vector.h>
  7. #include "winint.h"
  8. #else
  9. #include <cerrno>
  10. #include <cstdlib>
  11. #endif
  12. /**
  13. * On Windows there may be many copies of enviroment variables, there at least two known, one is
  14. * manipulated by Win32 API, another by C runtime, so we must be consistent in the choice of
  15. * functions used to manipulate them.
  16. *
  17. * Relevant links:
  18. * - http://bugs.python.org/issue16633
  19. * - https://a.yandex-team.ru/review/108892/details
  20. */
  21. TMaybe<TString> TryGetEnv(const TString& key) {
  22. #ifdef _win_
  23. size_t len = GetEnvironmentVariableA(key.data(), nullptr, 0);
  24. if (len == 0) {
  25. if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
  26. return Nothing();
  27. }
  28. return TString{};
  29. }
  30. TVector<char> buffer(len);
  31. size_t bufferSize;
  32. do {
  33. bufferSize = buffer.size();
  34. len = GetEnvironmentVariableA(key.data(), buffer.data(), static_cast<DWORD>(bufferSize));
  35. if (len > bufferSize) {
  36. buffer.resize(len);
  37. }
  38. } while (len > bufferSize);
  39. return TString(buffer.data(), len);
  40. #else
  41. const char* env = getenv(key.data());
  42. if (!env) {
  43. return Nothing();
  44. }
  45. return TString(env);
  46. #endif
  47. }
  48. TString GetEnv(const TString& key, const TString& def) {
  49. TMaybe<TString> value = TryGetEnv(key);
  50. if (value.Defined()) {
  51. return *std::move(value);
  52. }
  53. return def;
  54. }
  55. void SetEnv(const TString& key, const TString& value) {
  56. bool isOk = false;
  57. int errorCode = 0;
  58. #ifdef _win_
  59. isOk = SetEnvironmentVariable(key.data(), value.data());
  60. if (!isOk) {
  61. errorCode = GetLastError();
  62. }
  63. #else
  64. isOk = (0 == setenv(key.data(), value.data(), true /*replace*/));
  65. if (!isOk) {
  66. errorCode = errno;
  67. }
  68. #endif
  69. Y_ENSURE_EX(isOk, TSystemError() << "failed to SetEnv with error-code " << errorCode);
  70. }
  71. void UnsetEnv(const TString& key) {
  72. bool notFound = false;
  73. #ifdef _win_
  74. bool ok = SetEnvironmentVariable(key.c_str(), NULL);
  75. notFound = !ok && (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
  76. #else
  77. bool ok = (0 == unsetenv(key.c_str()));
  78. #if defined(_darwin_)
  79. notFound = !ok && (errno == EINVAL);
  80. #endif
  81. #endif
  82. Y_ENSURE_EX(ok || notFound, TSystemError() << "failed to unset environment variable " << key.Quote());
  83. }