1 /*
2  * Environment.hpp
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant
7  * to the terms of a commercial license agreement with RStudio, then
8  * this program is licensed to you under the terms of version 3 of the
9  * GNU Affero General Public License. This program is distributed WITHOUT
10  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13  *
14  */
15 
16 #ifndef CORE_SYSTEM_ENVIRONMENT_HPP
17 #define CORE_SYSTEM_ENVIRONMENT_HPP
18 
19 #include <string>
20 
21 #include <boost/noncopyable.hpp>
22 
23 #include <core/system/Types.hpp>
24 
25 namespace rstudio {
26 namespace core {
27 namespace system {
28 
29 // NOTE: all environment variables are UTF8-encoded
30 
31 
32 /****************************************************************
33    Direct manipulation of global environment
34 *****************************************************************/
35 
36 std::string getenv(const std::string& name);
37 void setenv(const std::string& name, const std::string& value);
38 void unsetenv(const std::string& name);
39 
40 
41 /****************************************************************
42    Read current environment into memory and access its variables
43 *****************************************************************/
44 
45 // get a copy of all current environment variables
46 void environment(Options* pEnvironment);
47 
48 // get an environment variable within an Options structure
49 std::string getenv(const Options& environment, const std::string& name);
50 
51 
52 /****************************************************************
53    Manipulating the memory environment variable structure. These
54    functions are typically used for preparing values to be passed
55    as ProcessOptions::environnent
56 *****************************************************************/
57 
58 // set an environment variable within an Options structure (replaces
59 // any existing value)
60 void setenv(Options* pEnvironment,
61             const std::string& name,
62             const std::string& value);
63 
64 // remove an enviroment variable from an Options structure
65 void unsetenv(Options* pEnvironment,
66               const std::string& name);
67 
68 void getModifiedEnv(const Options& extraVars, Options* pEnv);
69 
70 // add to the PATH
71 void addToPath(const std::string& filePath,
72                bool prepend = false);
73 
74 // add to the PATH within a string
75 void addToPath(std::string* pPath,
76                const std::string& filePath,
77                bool prepend = false);
78 
79 // add to the PATH within an Options struture
80 void addToPath(Options* pEnvironment,
81                const std::string& filePath,
82                bool prepend = false);
83 
84 /****************************************************************
85    Utility functions
86 *****************************************************************/
87 
88 bool parseEnvVar(const std::string envVar, Option* pEnvVar);
89 
90 // expand environment variables in a string; for example /$USER/foo to
91 // /bob/foo when USER=bob
92 std::string expandEnvVars(const Options& environment, const std::string& str);
93 
94 // forwards environment variables specified as a vector of strings from the current environment
95 // to the desired environment object
96 void forwardEnvVars(const std::vector<std::string>& vars, Options* pEnvironment);
97 
98 // set an environment variable in some scope (overridding and
99 // later restoring a previously-set environment variable)
100 class EnvironmentScope : boost::noncopyable
101 {
102 
103 public:
104 
EnvironmentScope(const char * variable,const char * value)105    EnvironmentScope(const char* variable,
106                     const char* value)
107       : variable_(variable),
108         value_(::getenv(variable))
109    {
110       core::system::setenv(variable, value);
111    }
112 
~EnvironmentScope()113    ~EnvironmentScope()
114    {
115       if (value_)
116       {
117          core::system::setenv(variable_, value_);
118       }
119       else
120       {
121          core::system::unsetenv(variable_);
122       }
123    }
124 
125 private:
126    const char* variable_;
127    const char* value_;
128 
129 };
130 
131 } // namespace system
132 } // namespace core
133 } // namespace rstudio
134 
135 #endif // CORE_SYSTEM_ENVIRONMENT_HPP
136