Environment.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright (c) 2021-2022, Andreas Kling <andreas@ladybird.org>
  3. * Copyright (c) 2021-2022, Kenneth Myhra <kennethmyhra@serenityos.org>
  4. * Copyright (c) 2021-2024, Sam Atkins <atkinssj@serenityos.org>
  5. * Copyright (c) 2022, Matthias Zimmerman <matthias291999@gmail.com>
  6. * Copyright (c) 2024, stasoid <stasoid@yahoo.com>
  7. *
  8. * SPDX-License-Identifier: BSD-2-Clause
  9. */
  10. #include "Environment.h"
  11. #include <AK/ByteString.h>
  12. #if defined(AK_OS_MACOS) || defined(AK_OS_IOS)
  13. # include <crt_externs.h>
  14. #elif !defined(AK_OS_WINDOWS)
  15. extern "C" char** environ;
  16. #endif
  17. namespace Core::Environment {
  18. char** raw_environ()
  19. {
  20. #if defined(AK_OS_MACOS) || defined(AK_OS_IOS)
  21. return *_NSGetEnviron();
  22. #elif defined AK_OS_WINDOWS
  23. return *__p__environ();
  24. #else
  25. return environ;
  26. #endif
  27. }
  28. Entry Entry::from_chars(char const* input)
  29. {
  30. return Entry::from_string({ input, strlen(input) });
  31. }
  32. Entry Entry::from_string(StringView input)
  33. {
  34. auto split_index = input.find('=');
  35. if (!split_index.has_value()) {
  36. return Entry {
  37. .full_entry = input,
  38. .name = input,
  39. .value = ""sv,
  40. };
  41. }
  42. return Entry {
  43. .full_entry = input,
  44. .name = input.substring_view(0, *split_index),
  45. .value = input.substring_view(*split_index + 1),
  46. };
  47. }
  48. EntryIterator EntryIterator::begin()
  49. {
  50. return EntryIterator(0);
  51. }
  52. EntryIterator EntryIterator::end()
  53. {
  54. auto environment = raw_environ();
  55. size_t env_count = 0;
  56. for (size_t i = 0; environment[i]; ++i)
  57. ++env_count;
  58. return EntryIterator(env_count);
  59. }
  60. EntryIterator entries()
  61. {
  62. return EntryIterator::begin();
  63. }
  64. size_t size()
  65. {
  66. auto environment = raw_environ();
  67. size_t environ_size = 0;
  68. while (environment[environ_size])
  69. ++environ_size;
  70. return environ_size;
  71. }
  72. bool has(StringView name)
  73. {
  74. return get(name).has_value();
  75. }
  76. Optional<StringView> get(StringView name, [[maybe_unused]] SecureOnly secure)
  77. {
  78. StringBuilder builder;
  79. builder.append(name);
  80. builder.append('\0');
  81. // Note the explicit null terminators above.
  82. // FreeBSD < 14, Android, generic BSDs, and Windows do not support secure_getenv.
  83. #if (defined(__FreeBSD__) && __FreeBSD__ >= 14) || (!defined(AK_OS_BSD_GENERIC) && !defined(AK_OS_ANDROID) && !defined(AK_OS_WINDOWS))
  84. char* result;
  85. if (secure == SecureOnly::Yes) {
  86. result = ::secure_getenv(builder.string_view().characters_without_null_termination());
  87. } else {
  88. result = ::getenv(builder.string_view().characters_without_null_termination());
  89. }
  90. #else
  91. char* result = ::getenv(builder.string_view().characters_without_null_termination());
  92. #endif
  93. if (result)
  94. return StringView { result, strlen(result) };
  95. return {};
  96. }
  97. ErrorOr<void> set(StringView name, StringView value, Overwrite overwrite)
  98. {
  99. auto builder = TRY(StringBuilder::create());
  100. TRY(builder.try_append(name));
  101. TRY(builder.try_append('\0'));
  102. TRY(builder.try_append(value));
  103. TRY(builder.try_append('\0'));
  104. // Note the explicit null terminators above.
  105. auto c_name = builder.string_view().characters_without_null_termination();
  106. auto c_value = c_name + name.length() + 1;
  107. #ifndef AK_OS_WINDOWS
  108. auto rc = ::setenv(c_name, c_value, overwrite == Overwrite::Yes ? 1 : 0);
  109. #else
  110. if (overwrite == Overwrite::No && getenv(c_name))
  111. return {};
  112. auto rc = _putenv_s(c_name, c_value);
  113. #endif
  114. if (rc < 0)
  115. return Error::from_errno(errno);
  116. return {};
  117. }
  118. ErrorOr<void> unset(StringView name)
  119. {
  120. auto builder = TRY(StringBuilder::create());
  121. TRY(builder.try_append(name));
  122. TRY(builder.try_append('\0'));
  123. // Note the explicit null terminator above.
  124. auto c_name = builder.string_view().characters_without_null_termination();
  125. #ifndef AK_OS_WINDOWS
  126. auto rc = ::unsetenv(c_name);
  127. #else
  128. auto rc = _putenv_s(c_name, "");
  129. #endif
  130. if (rc < 0)
  131. return Error::from_errno(errno);
  132. return {};
  133. }
  134. ErrorOr<void> put(StringView env)
  135. {
  136. #if defined(AK_OS_SERENITY)
  137. auto rc = ::serenity_putenv(env.characters_without_null_termination(), env.length());
  138. #elif defined(AK_OS_WINDOWS)
  139. ByteString str = env;
  140. auto rc = ::putenv(str.characters());
  141. #else
  142. // Leak somewhat unavoidable here due to the putenv API.
  143. auto leaked_new_env = strndup(env.characters_without_null_termination(), env.length());
  144. auto rc = ::putenv(leaked_new_env);
  145. #endif
  146. if (rc < 0)
  147. return Error::from_errno(errno);
  148. return {};
  149. }
  150. ErrorOr<void> clear()
  151. {
  152. #if (defined(__FreeBSD__) && __FreeBSD__ < 14)
  153. environ = nullptr;
  154. #elif defined(AK_OS_BSD_GENERIC) && !defined(AK_OS_FREEBSD)
  155. auto environment = raw_environ();
  156. for (size_t environ_size = 0; environment[environ_size]; ++environ_size) {
  157. environment[environ_size] = NULL;
  158. }
  159. #elif defined(AK_OS_WINDOWS)
  160. // environ = 0 doesn't work on Windows
  161. while (auto str = raw_environ()[0]) {
  162. auto eq = strchr(str, '=');
  163. VERIFY(eq);
  164. size_t name_len = eq - str;
  165. auto result = unset({ str, name_len });
  166. if (result.is_error())
  167. return result;
  168. }
  169. #else
  170. auto rc = ::clearenv();
  171. if (rc < 0)
  172. return Error::from_errno(errno);
  173. #endif
  174. return {};
  175. }
  176. }