-// ANNA - Anna is Not 'N' Anymore
+// ANNA - Anna is Not Nothingness Anymore
//
// (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
//
-// https://bitbucket.org/testillano/anna
+// http://redmine.teslayout.com/projects/anna-suite
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
-// * Neither the name of Google Inc. nor the names of its
+// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
#include <anna/config/defines.hpp>
#include <anna/core/tracing/Logger.hpp>
#include <anna/core/tracing/TraceMethod.hpp>
+#include <anna/core/functions.hpp>
-#include <boost/program_options.hpp>
-#include <boost/algorithm/string.hpp>
-
-
-#include <stdlib.h>
+#include <stdlib.h> // getenv / setenv
+#include <string>
using namespace std;
using namespace anna;
+extern int errno;
-
-void Environment::initialize() throw() {
+void Environment::initialize(char **envp) throw() {
LOGMETHOD(TraceMethod tm("Environment", "initialize", ANNA_FILE_LOCATION));
// clear data
- a_managedVars.clear();
- // Register:
- namespace po = boost::program_options;
- po::options_description desc("Options");
- FILE *fp;
- char c_var[256];
- std::string var;
- /* Open the command for reading. */
- fp = popen("env | cut -d'=' -f1", "r");
-
- if(fp == NULL) {
- Logger::error("Failed to get environment variables list", ANNA_FILE_LOCATION);
- return;
- }
-
- /* Read the output a line at a time - output it. */
- while(fgets(c_var, sizeof(c_var) - 1, fp) != NULL) {
- var = c_var;
- boost::trim(var);
- desc.add_options()(var.c_str(), var.c_str());
- a_managedVars[var] = ""; // temporary
- }
+ a_vars.clear();
- /* close */
- pclose(fp);
- // Parsing:
- po::variables_map vm;
+ if(!envp) return;
- try {
- po::store(po::parse_environment(desc, [](const std::string & variable) { return variable; }), vm); // can throw
- std::map<std::string, std::string>::const_iterator it;
- std::string var, val;
+ // register data
+ std::string assignment, var, val;
- for(it = a_managedVars.begin(); it != a_managedVars.end(); it++) {
- var = (*it).first;
+ while(*envp) {
+ assignment = *envp;
+ std::size_t equalPos = assignment.find("=");
- if(vm.count(var.c_str())) { // protection
- val = vm[var.c_str()].as<std::string>();
- a_managedVars[var] = val;
- }
+ if(equalPos != string::npos) { // protection
+ var = assignment.substr(0, equalPos - 1);
+ val = assignment.substr(equalPos, assignment.size() - 1);
+ a_vars[var] = val;
}
- po::notify(vm);
- } catch(po::error& e) {
- Logger::error(e.what(), ANNA_FILE_LOCATION);
+ envp++;
}
}
-std::string Environment::getValue(const char* variableName, bool exceptionIfMissing) const throw(RuntimeException) {
- std::string result = "";
-
+std::string Environment::getValue(const char* variableName, bool exceptionIfMissing) throw(RuntimeException) {
if(!variableName)
throw RuntimeException("Invalid NULL variable name!", ANNA_FILE_LOCATION);
- std::map<std::string, std::string>::const_iterator it = a_managedVars.find(variableName);
+ std::string var = variableName;
+ return getValue(var, exceptionIfMissing);
+}
+
+std::string Environment::getValue(const std::string &variableName, bool exceptionIfMissing) throw(RuntimeException) {
+ std::string result = "";
+ std::map<std::string, std::string>::const_iterator it = a_vars.find(variableName);
+
+ if(it == a_vars.end()) {
+ char *current = getenv(variableName.c_str());
+
+ if(!current) {
+ std::string msg = "The variable '";
+ msg += variableName;
+ msg += "' is not defined in the environment.";
+ LOGDEBUG(Logger::debug(msg, ANNA_FILE_LOCATION));
+
+ if(exceptionIfMissing) throw RuntimeException(msg, ANNA_FILE_LOCATION);
+ } else {
+ // assignment
+ a_vars[variableName] = current;
+ result = current;
+ }
+ } else {
+ result = it->second;
+ }
+
+ return result;
+}
- if(it == a_managedVars.end()) {
- std::string msg = "The variable '";
- msg += variableName;
- msg += "' is not defined in the environment.";
- LOGDEBUG(Logger::debug(msg, ANNA_FILE_LOCATION));
- if(exceptionIfMissing) throw RuntimeException(msg, ANNA_FILE_LOCATION);
+void Environment::setVariable(const std::string &name, const std::string &value, bool overwrite) throw(RuntimeException) {
+ if(name == "") throw RuntimeException("Must provide non-empty variable name", ANNA_FILE_LOCATION);
- return "";
+ if(setenv(name.c_str(), value.c_str(), overwrite ? 1 : 0) != 0) {
+ std::string msg = "Cannot set the environment variable '";
+ msg += name;
+ msg += "=\"";
+ msg += value;
+ msg += "\"'. The errno is ";
+ msg += anna::functions::asString(errno);
+ throw RuntimeException(msg, ANNA_FILE_LOCATION);
}
- return it->second;
+ // optimization
+ if(overwrite)
+ a_vars[name] = value;
+}
+
+
+void Environment::unsetVariable(const std::string &name) throw(RuntimeException) {
+ if(name == "") throw RuntimeException("Must provide non-empty variable name", ANNA_FILE_LOCATION);
+
+ if(unsetenv(name.c_str()) != 0) {
+ std::string msg = "Cannot unset the environment variable named '";
+ msg += name;
+ msg += "'. The errno is ";
+ msg += anna::functions::asString(errno);
+ throw RuntimeException(msg, ANNA_FILE_LOCATION);
+ }
+
+ std::map<std::string, std::string>::iterator it = a_vars.find(name);
+
+ if(it != a_vars.end()) a_vars.erase(it);
}