1 // Copyright 2010 Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "utils/env.hpp"
31 #if defined(HAVE_CONFIG_H)
40 #include "utils/format/macros.hpp"
41 #include "utils/logging/macros.hpp"
42 #include "utils/optional.ipp"
45 using utils::optional
;
49 extern char** environ
;
53 /// Gets all environment variables.
55 /// \return A mapping of (name, value) pairs describing the environment
57 std::map
< std::string
, std::string
>
58 utils::getallenv(void)
60 std::map
< std::string
, std::string
> allenv
;
61 for (char** envp
= environ
; *envp
!= NULL
; envp
++) {
62 const std::string oneenv
= *envp
;
63 const std::string::size_type pos
= oneenv
.find('=');
64 const std::string name
= oneenv
.substr(0, pos
);
65 const std::string value
= oneenv
.substr(pos
+ 1);
67 PRE(allenv
.find(name
) == allenv
.end());
74 /// Gets the value of an environment variable.
76 /// \param name The name of the environment variable to query.
78 /// \return The value of the environment variable if it is defined, or none
80 optional
< std::string
>
81 utils::getenv(const std::string
& name
)
83 const char* value
= std::getenv(name
.c_str());
85 LD(F("Environment variable '%s' is not defined") % name
);
88 LD(F("Environment variable '%s' is '%s'") % name
% value
);
89 return utils::make_optional(std::string(value
));
94 /// Gets the value of an environment variable with a default fallback.
96 /// \param name The name of the environment variable to query.
97 /// \param default_value The value to return if the variable is not defined.
99 /// \return The value of the environment variable.
101 utils::getenv_with_default(const std::string
& name
,
102 const std::string
& default_value
)
104 const char* value
= std::getenv(name
.c_str());
106 LD(F("Environment variable '%s' is not defined; using default '%s'") %
107 name
% default_value
);
108 return default_value
;
110 LD(F("Environment variable '%s' is '%s'") % name
% value
);
116 /// Sets the value of an environment variable.
118 /// \param name The name of the environment variable to set.
119 /// \param val The value to set the environment variable to. May be empty.
121 /// \throw std::runtime_error If there is an error setting the environment
124 utils::setenv(const std::string
& name
, const std::string
& val
)
126 LD(F("Setting environment variable '%s' to '%s'") % name
% val
);
127 #if defined(HAVE_SETENV)
128 if (::setenv(name
.c_str(), val
.c_str(), 1) == -1) {
129 const int original_errno
= errno
;
130 throw std::runtime_error(F("Failed to set environment variable '%s' to "
132 name
% val
% std::strerror(original_errno
));
134 #elif defined(HAVE_PUTENV)
135 if (::putenv((F("%s=%s") % name
% val
).c_str()) == -1) {
136 const int original_errno
= errno
;
137 throw std::runtime_error(F("Failed to set environment variable '%s' to "
139 name
% val
% std::strerror(original_errno
));
142 # error "Don't know how to set an environment variable."
147 /// Unsets an environment variable.
149 /// \param name The name of the environment variable to unset.
151 /// \throw std::runtime_error If there is an error unsetting the environment
154 utils::unsetenv(const std::string
& name
)
156 LD(F("Unsetting environment variable '%s'") % name
);
157 #if defined(HAVE_UNSETENV)
158 if (::unsetenv(name
.c_str()) == -1) {
159 const int original_errno
= errno
;
160 throw std::runtime_error(F("Failed to unset environment variable "
162 name
% std::strerror(original_errno
));
164 #elif defined(HAVE_PUTENV)
165 if (::putenv((F("%s=") % name
).c_str()) == -1) {
166 const int original_errno
= errno
;
167 throw std::runtime_error(F("Failed to unset environment variable "
169 name
% std::strerror(original_errno
));
172 # error "Don't know how to unset an environment variable."