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