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
25namespace absl {
26namespace base_internal {
27
28namespace {
29
30#ifdef _WIN32
31const int kMaxEnvVarValueSize = 1024;
32#endif
33
34void SetEnvVar(const char* name, const char* value) {
35#ifdef _WIN32
36 SetEnvironmentVariableA(name, value);
37#else
38 if (value == nullptr) {
39 ::unsetenv(name);
40 } else {
41 ::setenv(name, value, 1);
42 }
43#endif
44}
45
46} // namespace
47
48ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)
49 : var_name_(var_name), was_unset_(false) {
50#ifdef _WIN32
51 char buf[kMaxEnvVarValueSize];
52 auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf));
53 ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size");
54
55 if (get_res == 0) {
56 was_unset_ = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
57 } else {
58 old_value_.assign(buf, get_res);
59 }
60
61 SetEnvironmentVariableA(var_name_.c_str(), new_value);
62#else
63 const char* val = ::getenv(var_name_.c_str());
64 if (val == nullptr) {
65 was_unset_ = true;
66 } else {
67 old_value_ = val;
68 }
69#endif
70
71 SetEnvVar(var_name_.c_str(), new_value);
72}
73
74ScopedSetEnv::~ScopedSetEnv() {
75 SetEnvVar(var_name_.c_str(), was_unset_ ? nullptr : old_value_.c_str());
76}
77
78} // namespace base_internal
79} // namespace absl
80