It has been a while since I last worked on Aesalon proper.
[aesalon.git] / monitor / src / misc / Configuration.cpp
blob47efb8dc44cbe938f7eac7d979179d558a36cfa4
1 #include <fstream>
2 #include <iostream>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <dirent.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <sys/stat.h>
10 #include "Configuration.h"
11 #include "LogSystem.h"
12 #include "misc/StreamAsString.h"
14 namespace Misc {
16 Configuration::Configuration(char **argv) : m_argv(argv) {
17 processSearchPaths();
18 processFile(AesalonGlobalConfig);
19 processFile(AesalonUserConfig);
20 processFile(AesalonLocalConfig);
21 processArgv();
24 Configuration::~Configuration() {
25 for(ModuleMap::iterator i = m_moduleMap.begin(); i != m_moduleMap.end(); ++ i) {
26 if(i->second != NULL) delete i->second;
30 ConfigurationModule *Configuration::module(const std::string &name) {
31 ConfigurationModule *module = m_moduleMap[name];
32 if(module == NULL) {
33 module = new ConfigurationModule(name);
34 m_moduleMap[name] = module;
36 return module;
39 void Configuration::processFile(const std::string &path) {
40 std::ifstream file(path.c_str(), std::ios_base::in);
42 if(!file.is_open()) return;
44 ConfigurationModule *module = this->module("global");
46 while(!file.eof()) {
47 char buffer[1024];
48 file.getline(buffer, sizeof(buffer));
50 if(buffer[0] == '#') continue;
52 std::string line = buffer;
53 if(line.length() == 0) continue;
55 std::string::size_type divider = line.find(' ');
56 std::string command = line.substr(0, divider);
57 std::string content;
59 if(divider == std::string::npos) content = "";
60 else content = line.substr(divider+1);
62 if(command == "module") {
63 module = this->module(content);
65 else if(command == "set") {
66 divider = content.find('=');
67 if(divider == std::string::npos) {
68 LogSystem::logConfigurationMessage(Misc::StreamAsString() << "Mangled configuration file: set has no argument.");
70 std::string variable = content.substr(0, divider);
71 content.erase(0, divider+1);
72 module->item(variable)->setData(content);
74 else {
75 LogSystem::logConfigurationMessage(Misc::StreamAsString() << "Mangled configuration file: unknown command \"" << command << "\"");
79 file.close();
82 void Configuration::processSearchPaths() {
83 const char *pathEnv = getenv("AesalonSearchPath");
84 if(pathEnv == NULL) {
85 LogSystem::logConfigurationMessage("Enviroment variable AesalonSearchPath not set; cannot load modules.");
86 return;
88 std::string searchPaths = pathEnv;
90 traverse("searchPaths")->setData(searchPaths);
92 do {
93 std::string::size_type position = searchPaths.find(":");
94 std::string path = searchPaths.substr(0, position);
95 if(position != std::string::npos) searchPaths.erase(0, searchPaths.find(":") + 1);
96 else searchPaths.erase();
98 DIR *directory = opendir(path.c_str());
99 if(directory == NULL) {
100 LogSystem::logConfigurationMessage(Misc::StreamAsString() << "Cannot open search path \"" << path << "\": " << strerror(errno));
102 else {
103 struct dirent *file;
105 while((file = readdir(directory)) != NULL) {
106 if(!strcmp(file->d_name, ".") || !strcmp(file->d_name, "..")) continue;
108 std::string dirpath = path + "/";
109 dirpath += file->d_name;
111 struct stat file_stat;
112 if(stat(dirpath.c_str(), &file_stat) == 0) {
113 if(S_ISDIR(file_stat.st_mode)) {
114 /*dirpath += "/monitor.conf";*/
115 if(stat((dirpath + "/monitor.conf").c_str(), &file_stat) == 0 && S_ISREG(file_stat.st_mode)) {
116 processFile(dirpath + "/monitor.conf");
117 traverse(std::string(file->d_name) + ".modulePath")->setData(dirpath);
124 closedir(directory);
125 } while(searchPaths.length());
128 void Configuration::processArgv() {
129 int i = 0;
131 /* This will occur in a very few circumstances, mainly mangled exec() calls. */
132 if(m_argv[0] == NULL) return;
134 bool eoaFound = false;
136 while(m_argv[++i] != NULL) {
138 if(eoaFound) {
139 addLaunchArgument(m_argv[i]);
140 continue;
142 else if(m_argv[i][0] != '-' || m_argv[i][1] != '-') {
143 /*LogSystem::logConfigurationMessage(Misc::StreamAsString()
144 << "Mangled argument \"" << m_argv[i] << "\"; all arguments begin with a double dash.");*/
145 eoaFound = true;
146 addLaunchArgument(m_argv[i]);
147 continue;
149 std::string argument = &m_argv[i][2];
150 if(argument.length() == 0) {
151 eoaFound = true;
152 continue;
155 std::string::size_type divider = argument.find('=');
156 if(divider == std::string::npos) {
157 traverse(argument)->setData("true");
159 else {
160 traverse(argument.substr(0, divider))->setData(argument.substr(divider+1));
165 ConfigurationItem *Configuration::traverse(std::string path) {
166 std::string::size_type divider = path.find('.');
167 std::string moduleName;
168 if(divider != std::string::npos) {
169 /*LogSystem::logConfigurationMessage(Misc::StreamAsString() << "Poorly-formed traverse path \"" << path << "\"; no item specified.");*/
170 /*return NULL;*/
171 moduleName = path.substr(0, divider);
172 path.erase(0, divider+1);
174 else moduleName = "global";
176 ConfigurationModule *module = this->module(moduleName);
178 return module->item(path);
181 void Configuration::addLaunchArgument(const std::string &argument) {
182 m_launchArguments.push_back(argument);
185 } // namespace Misc