RSC  0.17.1
Environment.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSC project
4  *
5  * Copyright (C) 2011-2018 Jan Moringen
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #include "Environment.h"
28 
29 #include <algorithm>
30 #include <iterator>
31 
32 // For dynamic libs the environ variable is not available
33 // on MacOS, hence a workaround is needed. See also:
34 // http://article.gmane.org/gmane.comp.lib.boost.devel/103843
35 #if defined(__APPLE__) && defined(__DYNAMIC__)
36 #include <crt_externs.h>
37 #define environ (*_NSGetEnviron())
38 #endif
39 
40 #include <boost/algorithm/string.hpp>
41 #include <boost/program_options.hpp>
42 #include <boost/program_options/environment_iterator.hpp>
43 
45 
46 using namespace std;
47 
48 using namespace boost;
49 using namespace boost::filesystem;
50 
51 using namespace rsc::logging;
52 
53 namespace rsc {
54 namespace config {
55 
57 #ifndef _WIN32
58  return "/etc/";
59 #else
60  return "c:\\";
61 #endif
62 }
63 
64 path prefixConfigDirectory(const path& prefix) {
65 #ifndef _WIN32
66  // The "common" rule in the "else" leg would lead to "/usr/etc",
67  // which does not normally exist. Therefore, we treat the "/usr"
68  // prefix specially.
69  if (prefix == "/usr") {
70  return systemConfigDirectory();
71  } else {
72  return prefix / "etc/";
73  }
74 #else
75  return prefix / "etc";
76 #endif
77 }
78 
80 #ifndef _WIN32
81  char* rawHome = getenv("HOME");
82  if (!rawHome) {
83  throw runtime_error("Home directory not defined in HOME variable.");
84  }
85  string home = string(rawHome) + string("/");
86 #else
87  char* rawHomeDrive = getenv("HOMEDRIVE");
88  if (!rawHomeDrive) {
89  throw runtime_error("HOMEDRIVE variable not set.");
90  }
91  char* rawHomePath = getenv("HOMEPATH");
92  if (!rawHomePath) {
93  throw runtime_error("HOMEPATH variable not set.");
94  }
95  string home = string(rawHomeDrive) + string(rawHomePath) + string("\\");
96 #endif
97  return home;
98 }
99 
101  return userHomeDirectory() / ".config";
102 }
103 
104 boost::shared_ptr<std::string> getEnvironmentVariable(const std::string& name) {
105  for (environment_iterator it = environment_iterator(environ); it
106  != environment_iterator(); ++it) {
107  if (it->first == name) {
108  return boost::shared_ptr<string>(new string(it->second));
109  }
110  }
111  return boost::shared_ptr<string>();
112 }
113 
114 string transformName(const string& name, const string& prefix,
115  const bool& stripPrefix) {
116  if (starts_with(name, prefix)) {
117  string result;
118  string::const_iterator start = name.begin();
119  if (stripPrefix) {
120  start = start + prefix.size();
121  }
122  transform(start, name.end(), back_inserter(result), &::tolower);
123  return result;
124  } else {
125  return "";
126  }
127 }
128 
129 EnvironmentVariableSource::Match::Match(const string& rawName,
130  const string& transformedName,
131  const string& value)
132  : rawName(rawName), transformedName(transformedName), value(value) {
133 }
134 
136  return this->rawName;
137 }
138 
140  return this->transformedName;
141 }
142 
144  return this->value;
145 }
146 
148  const bool& stripPrefix) :
149  logger(Logger::getLogger("rsc.config.EnvironmentVariableSource")), prefix(
150  prefix), stripPrefix(stripPrefix) {
151 }
152 
154  if (!this->matches) {
155  this->matches.reset(new Matches());
156  for (environment_iterator it = environment_iterator(environ); it
157  != environment_iterator(); ++it) {
158  string name = transformName(it->first, this->prefix, this->stripPrefix);
159  if (name.empty()) {
160  continue;
161  }
162  this->matches->push_back(Match(it->first, name, it->second));
163  }
164  }
165  return *this->matches;
166 }
167 
170  for (Matches::const_iterator it = matches.begin();
171  it != matches.end(); ++it) {
172  vector<string> key;
173  split(key, it->getTransformedName(), is_any_of("_"));
174  const string& value = it->getValue();
175  RSCTRACE(logger, "Option " << key << " -> " << value);
176  handler.handleOption(key, value);
177  }
178 }
179 
180 }
181 }
void provideOptions(OptionHandler &handler)
Implementations should pass all configuration options to handler.
string transformName(const string &name, const string &prefix, const bool &stripPrefix)
virtual void handleOption(const std::vector< std::string > &key, const std::string &value)=0
This method is called once for each individual option available from a given ConfigSource.
path userConfigDirectory()
Return the canonical directory for configuration files of the user associated with the current proces...
Matches getMatches()
Return matching environment variables.
Implementations of this interface receive options from ConfigSource objects.
Definition: OptionHandler.h:43
STL namespace.
boost::shared_ptr< std::string > getEnvironmentVariable(const std::string &name)
Return the value of the environment value name or an empty pointer.
path systemConfigDirectory()
Return the directory in which system-wide configuration files are located.
Definition: Environment.cpp:56
path prefixConfigDirectory(const path &prefix)
Definition: Environment.cpp:64
const std::string & getRawName() const
LoggerPtr getLogger()
#define RSCTRACE(logger, msg)
Definition: Logger.h:210
rsc::logging::LoggerPtr logger
Definition: Environment.h:159
Provides a hierarchical logging system with the possibility to install different backends, which are instances of LoggingSystem.
boost::shared_ptr< Matches > matches
Definition: Environment.h:164
path userHomeDirectory()
Return the home directory of the user associated with the current process.
Definition: Environment.cpp:79
void handler(int signal)
Interface for logging adapters that can be used with RSC.
Definition: Logger.h:54
EnvironmentVariableSource(const std::string &prefix="", const bool &stripPrefix=true)
Construct a source that collect environment variables whose name starts with prefix.
const std::string & getTransformedName() const