00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "cmconfig.h"
00040 #include "consmgr.h"
00041 #ifdef HAVE_GETCAP
00042 # include "cfg_getcap.h"
00043 #endif
00044 #ifdef HAVE_LIBCONFIG
00045 # include "cfg_libconfig.h"
00046 #endif
00047 #ifdef HAVE_YAML
00048 # include "cfg_yaml.h"
00049 #endif
00050
00051 #include <sstream>
00052
00053
00054
00055
00056 #if MULTIPLE_CONFIG_FILES
00057 ConfigDB::ConfigDB(void)
00058 {
00059 this->init();
00060 }
00061
00062 void
00063 ConfigDB::init(void)
00064 {
00065
00066
00067
00068 pret = pthread_mutex_init(&files_mtx, NULL);
00069 PTHREAD_CHECK_AND_THROW(pret, "mutex_init(files_mtx)");
00070
00071 return;
00072 }
00073
00074 ConfigDB::ConfigDB(const string &file)
00075 {
00076 this->init();
00077 this->add_db(file);
00078
00079 return;
00080 }
00081
00082 ConfigDB::~ConfigDB(void)
00083 {
00084 pret = pthread_mutex_destroy(&files_mtx);
00085 PTHREAD_CHECK_AND_THROW(pret, "mutex_destroy(files_mtx)");
00086
00087 return;
00088 }
00089
00090
00091
00092
00093
00094 void
00095 ConfigDB::add_db(const string &file)
00096 {
00097
00098
00099
00100 pret = pthread_mutex_lock(&files_mtx);
00101 PTHREAD_CHECK_AND_THROW(pret, "mutex_lock(files_mtx)");
00102
00103 clog << "ConfigDB::add_db: Adding database '" << file << "'" << endl;
00104
00105 db_files.push_back(file);
00106
00107 pret = pthread_mutex_unlock(&files_mtx);
00108 PTHREAD_CHECK_AND_THROW(pret, "mutex_unlock(files_mtx)");
00109
00110 return;
00111 }
00112
00113 int
00114 ConfigDB::db_count(void)
00115 {
00116 int count;
00117
00118
00119
00120
00121 pret = pthread_mutex_lock(&files_mtx);
00122 PTHREAD_CHECK_AND_THROW(pret, "mutex_lock(files_mtx)");
00123
00124 count = db_files.size();
00125
00126 pret = pthread_mutex_unlock(&files_mtx);
00127 PTHREAD_CHECK_AND_THROW(pret, "mutex_unlock(files_mtx)");
00128
00129 return count;
00130 }
00131 #endif
00132
00133
00134
00135
00136
00137 Config::Config(const string &filename) : filename(filename)
00138 {
00139 }
00140
00141 Config::~Config()
00142 {
00143 }
00144
00146 const char* Config::keytexts[] = {
00147 "host",
00148 "port",
00149 "local_socket",
00150 "logfile",
00151 "device",
00152 };
00160 const std::vector<std::string>
00161 Config::config_keys(Config::keytexts,
00162 Config::keytexts + (sizeof(Config::keytexts) /
00163 sizeof(Config::keytexts[0])));
00164
00165
00166
00167
00168
00169
00170
00171 ConfigException::ConfigException(const string &r) : reason(r) {}
00172 ConfigException::ConfigException(const string &r, const string &f, const int l)
00173 : reason(r), file(f), line(l) {}
00174
00175 void
00176 ConfigException::set_file(const string &f)
00177 {
00178 file = f;
00179 return;
00180 }
00181
00182 void
00183 ConfigException::set_line(const int l)
00184 {
00185 line = l;
00186 return;
00187 }
00188
00189 const char *
00190 ConfigException::what() const throw()
00191 {
00192 std::ostringstream reason_str;
00193
00194 reason_str << reason;
00195 if (file.length() > 0) {
00196 if (line > 0)
00197 reason_str << " at " << file << ":" << line;
00198 else
00199 reason_str << " in " << file;
00200 } else {
00201 if (line > 0)
00202 reason_str << " on line " << line;
00203 }
00204
00205 return(reason_str.str().c_str());
00206 }
00207
00208 const char *
00209 ConfigBadFile::what() const throw()
00210 {
00211 std::ostringstream reason_str;
00212
00213 reason_str << "Cannot read configuration file ";
00214 if (file.length() > 0)
00215 reason_str << file;
00216 if (saved_errno)
00217 reason_str << ": " << ::strerror(saved_errno);
00218
00219 return(reason_str.str().c_str());
00220 }
00221
00222
00223
00224 ConfigParseException::ConfigParseException(const int l, const string &r)
00225 : ConfigException("Parse error")
00226 {
00227 line = l;
00228 }
00229
00230
00231 ConfigUnfoundException::ConfigUnfoundException(const string &element,
00232 const string &r)
00233 : ConfigException(r), node(element)
00234 {
00235 }
00236
00237 const char *
00238 ConfigUnfoundException::what(void) const throw()
00239 {
00240
00241
00242 if (! reason.empty())
00243 return(reason.c_str());
00244
00245 std::ostringstream reason_str;
00246
00247 reason_str << "Unable to find element '" << node << "' in configuration";
00248 if (file.length() > 0) {
00249 reason_str << " file (" << file << ")";
00250 }
00251 reason_str << ".";
00252
00253 return(reason_str.str().c_str());
00254 }
00255
00256
00257
00258
00259 Config *
00260 ConfigFactory::config_object(const string &filename)
00261 {
00262
00263
00264
00265 size_t suffix_pos = filename.find_last_of('.');
00266
00267
00268
00269
00270
00271 if (::access(filename.c_str(), R_OK) < 0)
00272 throw ConfigBadFile(filename, errno);
00273 #if HAVE_YAML
00274
00275 if ((suffix_pos != string::npos) &&
00276 (filename.substr(suffix_pos) == ".yaml")) {
00277 #ifdef CONFIGURATION_DEBUGGING
00278 cerr << "Returning a YAML config object" << endl;
00279 #endif
00280 return new_config<YAML>(filename);
00281 } else
00282 #endif
00283 #if HAVE_LIBCONFIG
00284 if ((suffix_pos != string::npos) &&
00285 (filename.substr(suffix_pos) == ".cfg")) {
00286 #ifdef CONFIGURATION_DEBUGGING
00287 cerr << "Config file is a libconfig config file?" << endl;
00288 #endif
00289 return new_config<LibConfig>(filename);
00290 } else
00291 #endif
00292 #if HAVE_GETCAP
00293 #ifdef CONFIGURATION_DEBUGGING
00294 clog << "Presuming '" << filename << "' is a termcap-style file." << endl;
00295 #endif
00296 return new_config<Getcap>(filename);
00297 #endif
00298
00299 throw string("Unable to instantiate a Config element for file " + filename);
00300 }
00301
00302 template <class CFG_type>
00303 Config *ConfigFactory::new_config(const string &filename)
00304 {
00305 return new CFG_type(filename);
00306 }