Environment.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.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. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #include "Environment.h"
  10. #include <AK/ByteString.h>
  11. #if defined(AK_OS_MACOS) || defined(AK_OS_IOS)
  12. # include <crt_externs.h>
  13. #else
  14. extern char** environ;
  15. #endif
  16. namespace Core::Environment {
  17. char** raw_environ()
  18. {
  19. #if defined(AK_OS_MACOS) || defined(AK_OS_IOS)
  20. return *_NSGetEnviron();
  21. #else
  22. return environ;
  23. #endif
  24. }
  25. Entry Entry::from_chars(char const* input)
  26. {
  27. return Entry::from_string({ input, strlen(input) });
  28. }
  29. Entry Entry::from_string(StringView input)
  30. {
  31. auto split_index = input.find('=');
  32. if (!split_index.has_value()) {
  33. return Entry {
  34. .full_entry = input,
  35. .name = input,
  36. .value = ""sv,
  37. };
  38. }
  39. return Entry {
  40. .full_entry = input,
  41. .name = input.substring_view(0, *split_index),
  42. .value = input.substring_view(*split_index + 1),
  43. };
  44. }
  45. EntryIterator EntryIterator::begin()
  46. {
  47. return EntryIterator(0);
  48. }
  49. EntryIterator EntryIterator::end()
  50. {
  51. auto environment = raw_environ();
  52. size_t env_count = 0;
  53. for (size_t i = 0; environment[i]; ++i)
  54. ++env_count;
  55. return EntryIterator(env_count);
  56. }
  57. EntryIterator entries()
  58. {
  59. return EntryIterator::begin();
  60. }
  61. size_t size()
  62. {
  63. auto environment = raw_environ();
  64. size_t environ_size = 0;
  65. while (environment[environ_size])
  66. ++environ_size;
  67. return environ_size;
  68. }
  69. bool has(StringView name)
  70. {
  71. return get(name).has_value();
  72. }
  73. Optional<StringView> get(StringView name, [[maybe_unused]] SecureOnly secure)
  74. {
  75. StringBuilder builder;
  76. builder.append(name);
  77. builder.append('\0');
  78. // Note the explicit null terminators above.
  79. #if defined(AK_OS_MACOS) || defined(AK_OS_ANDROID)
  80. char* result = ::getenv(builder.string_view().characters_without_null_termination());
  81. #else
  82. char* result;
  83. if (secure == SecureOnly::Yes) {
  84. result = ::secure_getenv(builder.string_view().characters_without_null_termination());
  85. } else {
  86. result = ::getenv(builder.string_view().characters_without_null_termination());
  87. }
  88. #endif
  89. if (result)
  90. return StringView { result, strlen(result) };
  91. return {};
  92. }
  93. ErrorOr<void> set(StringView name, StringView value, Overwrite overwrite)
  94. {
  95. auto builder = TRY(StringBuilder::create());
  96. TRY(builder.try_append(name));
  97. TRY(builder.try_append('\0'));
  98. TRY(builder.try_append(value));
  99. TRY(builder.try_append('\0'));
  100. // Note the explicit null terminators above.
  101. auto c_name = builder.string_view().characters_without_null_termination();
  102. auto c_value = c_name + name.length() + 1;
  103. auto rc = ::setenv(c_name, c_value, overwrite == Overwrite::Yes ? 1 : 0);
  104. if (rc < 0)
  105. return Error::from_errno(errno);
  106. return {};
  107. }
  108. ErrorOr<void> unset(StringView name)
  109. {
  110. auto builder = TRY(StringBuilder::create());
  111. TRY(builder.try_append(name));
  112. TRY(builder.try_append('\0'));
  113. // Note the explicit null terminator above.
  114. auto rc = ::unsetenv(builder.string_view().characters_without_null_termination());
  115. if (rc < 0)
  116. return Error::from_errno(errno);
  117. return {};
  118. }
  119. ErrorOr<void> put(StringView env)
  120. {
  121. #if defined(AK_OS_SERENITY)
  122. auto rc = ::serenity_putenv(env.characters_without_null_termination(), env.length());
  123. #else
  124. // Leak somewhat unavoidable here due to the putenv API.
  125. auto leaked_new_env = strndup(env.characters_without_null_termination(), env.length());
  126. auto rc = ::putenv(leaked_new_env);
  127. #endif
  128. if (rc < 0)
  129. return Error::from_errno(errno);
  130. return {};
  131. }
  132. ErrorOr<void> clear()
  133. {
  134. #if defined(AK_OS_MACOS)
  135. auto environment = raw_environ();
  136. for (size_t environ_size = 0; environment[environ_size]; ++environ_size) {
  137. environment[environ_size] = NULL;
  138. }
  139. #else
  140. auto rc = ::clearenv();
  141. if (rc < 0)
  142. return Error::from_errno(errno);
  143. #endif
  144. return {};
  145. }
  146. }