1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/environment.h"
6
7 #include <array>
8 #include <string_view>
9
10 #include "base/memory/ptr_util.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "build/build_config.h"
14
15 #if BUILDFLAG(IS_WIN)
16 #include <windows.h>
17 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
18 #include <stdlib.h>
19 #endif
20
21 namespace base {
22
23 namespace {
24
25 class EnvironmentImpl : public Environment {
26 public:
GetVar(std::string_view variable_name,std::string * result)27 bool GetVar(std::string_view variable_name, std::string* result) override {
28 if (GetVarImpl(variable_name, result))
29 return true;
30
31 // Some commonly used variable names are uppercase while others
32 // are lowercase, which is inconsistent. Let's try to be helpful
33 // and look for a variable name with the reverse case.
34 // I.e. HTTP_PROXY may be http_proxy for some users/systems.
35 char first_char = variable_name[0];
36 std::string alternate_case_var;
37 if (IsAsciiLower(first_char))
38 alternate_case_var = ToUpperASCII(variable_name);
39 else if (IsAsciiUpper(first_char))
40 alternate_case_var = ToLowerASCII(variable_name);
41 else
42 return false;
43 return GetVarImpl(alternate_case_var, result);
44 }
45
SetVar(std::string_view variable_name,const std::string & new_value)46 bool SetVar(std::string_view variable_name,
47 const std::string& new_value) override {
48 return SetVarImpl(variable_name, new_value);
49 }
50
UnSetVar(std::string_view variable_name)51 bool UnSetVar(std::string_view variable_name) override {
52 return UnSetVarImpl(variable_name);
53 }
54
55 private:
GetVarImpl(std::string_view variable_name,std::string * result)56 bool GetVarImpl(std::string_view variable_name, std::string* result) {
57 #if BUILDFLAG(IS_WIN)
58 std::wstring wide_name = UTF8ToWide(variable_name);
59 if (!result) {
60 return ::GetEnvironmentVariable(wide_name.c_str(), nullptr, 0) != 0;
61 }
62 // Documented to be the maximum environment variable size.
63 std::array<wchar_t, 32767> value;
64 DWORD value_length =
65 ::GetEnvironmentVariable(wide_name.c_str(), value.data(), value.size());
66 if (value_length == 0) {
67 return false;
68 }
69 CHECK_LE(value_length, value.size() - 1)
70 << "value should fit in the buffer (including the null terminator)";
71 WideToUTF8(value.data(), value_length, result);
72 return true;
73 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
74 const char* env_value = getenv(std::string(variable_name).c_str());
75 if (!env_value)
76 return false;
77 // Note that the variable may be defined but empty.
78 if (result)
79 *result = env_value;
80 return true;
81 #endif
82 }
83
SetVarImpl(std::string_view variable_name,const std::string & new_value)84 bool SetVarImpl(std::string_view variable_name,
85 const std::string& new_value) {
86 #if BUILDFLAG(IS_WIN)
87 // On success, a nonzero value is returned.
88 return !!SetEnvironmentVariable(UTF8ToWide(variable_name).c_str(),
89 UTF8ToWide(new_value).c_str());
90 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
91 // On success, zero is returned.
92 return !setenv(variable_name.data(), new_value.c_str(), 1);
93 #endif
94 }
95
UnSetVarImpl(std::string_view variable_name)96 bool UnSetVarImpl(std::string_view variable_name) {
97 #if BUILDFLAG(IS_WIN)
98 // On success, a nonzero value is returned.
99 return !!SetEnvironmentVariable(UTF8ToWide(variable_name).c_str(), nullptr);
100 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
101 // On success, zero is returned.
102 return !unsetenv(variable_name.data());
103 #endif
104 }
105 };
106
107 } // namespace
108
109 namespace env_vars {
110
111 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
112 // On Posix systems, this variable contains the location of the user's home
113 // directory. (e.g, /home/username/).
114 const char kHome[] = "HOME";
115 #endif
116
117 } // namespace env_vars
118
119 Environment::~Environment() = default;
120
121 // static
Create()122 std::unique_ptr<Environment> Environment::Create() {
123 return std::make_unique<EnvironmentImpl>();
124 }
125
HasVar(std::string_view variable_name)126 bool Environment::HasVar(std::string_view variable_name) {
127 return GetVar(variable_name, nullptr);
128 }
129
130 } // namespace base
131