1 // Copyright 2019 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/base/internal/scoped_set_env.h"
16 
17 #ifdef _WIN32
18 #include <windows.h>
19 #endif
20 
21 #include <cstdlib>
22 
23 #include "absl/base/internal/raw_logging.h"
24 
25 namespace absl {
26 ABSL_NAMESPACE_BEGIN
27 namespace base_internal {
28 
29 namespace {
30 
31 #ifdef _WIN32
32 const int kMaxEnvVarValueSize = 1024;
33 #endif
34 
SetEnvVar(const char * name,const char * value)35 void SetEnvVar(const char* name, const char* value) {
36 #ifdef _WIN32
37   SetEnvironmentVariableA(name, value);
38 #else
39   if (value == nullptr) {
40     ::unsetenv(name);
41   } else {
42     ::setenv(name, value, 1);
43   }
44 #endif
45 }
46 
47 }  // namespace
48 
ScopedSetEnv(const char * var_name,const char * new_value)49 ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)
50     : var_name_(var_name), was_unset_(false) {
51 #ifdef _WIN32
52   char buf[kMaxEnvVarValueSize];
53   auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf));
54   ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size");
55 
56   if (get_res == 0) {
57     was_unset_ = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
58   } else {
59     old_value_.assign(buf, get_res);
60   }
61 
62   SetEnvironmentVariableA(var_name_.c_str(), new_value);
63 #else
64   const char* val = ::getenv(var_name_.c_str());
65   if (val == nullptr) {
66     was_unset_ = true;
67   } else {
68     old_value_ = val;
69   }
70 #endif
71 
72   SetEnvVar(var_name_.c_str(), new_value);
73 }
74 
~ScopedSetEnv()75 ScopedSetEnv::~ScopedSetEnv() {
76   SetEnvVar(var_name_.c_str(), was_unset_ ? nullptr : old_value_.c_str());
77 }
78 
79 }  // namespace base_internal
80 ABSL_NAMESPACE_END
81 }  // namespace absl
82