1 /*
2  *
3  * Copyright 2019 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include <grpc/support/port_platform.h>
20 
21 #include "src/core/lib/gprpp/global_config_env.h"
22 
23 #include <ctype.h>
24 #include <string.h>
25 
26 #include <string>
27 
28 #include "absl/strings/str_format.h"
29 
30 #include <grpc/support/alloc.h>
31 #include <grpc/support/log.h>
32 #include <grpc/support/string_util.h>
33 
34 #include "src/core/lib/gpr/env.h"
35 #include "src/core/lib/gpr/string.h"
36 
37 namespace grpc_core {
38 
39 namespace {
40 
DefaultGlobalConfigEnvErrorFunction(const char * error_message)41 void DefaultGlobalConfigEnvErrorFunction(const char* error_message) {
42   gpr_log(GPR_ERROR, "%s", error_message);
43 }
44 
45 GlobalConfigEnvErrorFunctionType g_global_config_env_error_func =
46     DefaultGlobalConfigEnvErrorFunction;
47 
LogParsingError(const char * name,const char * value)48 void LogParsingError(const char* name, const char* value) {
49   std::string error_message = absl::StrFormat(
50       "Illegal value '%s' specified for environment variable '%s'", value,
51       name);
52   (*g_global_config_env_error_func)(error_message.c_str());
53 }
54 
55 }  // namespace
56 
SetGlobalConfigEnvErrorFunction(GlobalConfigEnvErrorFunctionType func)57 void SetGlobalConfigEnvErrorFunction(GlobalConfigEnvErrorFunctionType func) {
58   g_global_config_env_error_func = func;
59 }
60 
GetValue()61 grpc_core::UniquePtr<char> GlobalConfigEnv::GetValue() {
62   return grpc_core::UniquePtr<char>(gpr_getenv(GetName()));
63 }
64 
SetValue(const char * value)65 void GlobalConfigEnv::SetValue(const char* value) {
66   gpr_setenv(GetName(), value);
67 }
68 
Unset()69 void GlobalConfigEnv::Unset() { gpr_unsetenv(GetName()); }
70 
GetName()71 char* GlobalConfigEnv::GetName() {
72   // This makes sure that name_ is in a canonical form having uppercase
73   // letters. This is okay to be called serveral times.
74   for (char* c = name_; *c != 0; ++c) {
75     *c = toupper(*c);
76   }
77   return name_;
78 }
79 static_assert(std::is_trivially_destructible<GlobalConfigEnvBool>::value,
80               "GlobalConfigEnvBool needs to be trivially destructible.");
81 
Get()82 bool GlobalConfigEnvBool::Get() {
83   grpc_core::UniquePtr<char> str = GetValue();
84   if (str == nullptr) {
85     return default_value_;
86   }
87   // parsing given value string.
88   bool result = false;
89   if (!gpr_parse_bool_value(str.get(), &result)) {
90     LogParsingError(GetName(), str.get());
91     result = default_value_;
92   }
93   return result;
94 }
95 
Set(bool value)96 void GlobalConfigEnvBool::Set(bool value) {
97   SetValue(value ? "true" : "false");
98 }
99 
100 static_assert(std::is_trivially_destructible<GlobalConfigEnvInt32>::value,
101               "GlobalConfigEnvInt32 needs to be trivially destructible.");
102 
Get()103 int32_t GlobalConfigEnvInt32::Get() {
104   grpc_core::UniquePtr<char> str = GetValue();
105   if (str == nullptr) {
106     return default_value_;
107   }
108   // parsing given value string.
109   char* end = str.get();
110   long result = strtol(str.get(), &end, 10);
111   if (*end != 0) {
112     LogParsingError(GetName(), str.get());
113     result = default_value_;
114   }
115   return static_cast<int32_t>(result);
116 }
117 
Set(int32_t value)118 void GlobalConfigEnvInt32::Set(int32_t value) {
119   char buffer[GPR_LTOA_MIN_BUFSIZE];
120   gpr_ltoa(value, buffer);
121   SetValue(buffer);
122 }
123 
124 static_assert(std::is_trivially_destructible<GlobalConfigEnvString>::value,
125               "GlobalConfigEnvString needs to be trivially destructible.");
126 
Get()127 grpc_core::UniquePtr<char> GlobalConfigEnvString::Get() {
128   grpc_core::UniquePtr<char> str = GetValue();
129   if (str == nullptr) {
130     return grpc_core::UniquePtr<char>(gpr_strdup(default_value_));
131   }
132   return str;
133 }
134 
Set(const char * value)135 void GlobalConfigEnvString::Set(const char* value) { SetValue(value); }
136 
137 }  // namespace grpc_core
138