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