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 #include "config.h"
00034
00035 #ifdef __cplusplus
00036 extern "C" {
00037 #include <sys/types.h>
00038 #include "regex.h"
00039 }
00040 #endif
00041
00042 #include <cerrno>
00043 #include <cstring>
00044
00045 #if HAVE_UNISTD_H
00046 #include <unistd.h>
00047 #endif
00048
00049 #include "BESKeys.h"
00050 #include "BESUtil.h"
00051 #include "BESFSDir.h"
00052 #include "BESFSFile.h"
00053 #include "BESInternalFatalError.h"
00054 #include "BESSyntaxUserError.h"
00055
00056 #define BES_INCLUDE_KEY "BES.Include"
00057
00058 vector<string> BESKeys::KeyList ;
00059
00076 BESKeys::BESKeys( const string &keys_file_name )
00077 : _keys_file( 0 ),
00078 _keys_file_name( keys_file_name ),
00079 _the_keys( 0 ),
00080 _own_keys( true )
00081 {
00082 _the_keys = new map<string,vector<string> >;
00083 initialize_keys( ) ;
00084 }
00085
00086 BESKeys::BESKeys( const string &keys_file_name, map<string,vector<string> > *keys)
00087 : _keys_file( 0 ),
00088 _keys_file_name( keys_file_name ),
00089 _the_keys( keys ),
00090 _own_keys( false )
00091 {
00092 initialize_keys( ) ;
00093 }
00094
00097 BESKeys::~BESKeys()
00098 {
00099 clean() ;
00100 }
00101
00102 void
00103 BESKeys::initialize_keys( )
00104 {
00105 _keys_file = new ifstream( _keys_file_name.c_str() ) ;
00106 int myerrno = errno ;
00107 if( !(*_keys_file) )
00108 {
00109 char path[500] ;
00110 getcwd( path, sizeof( path ) ) ;
00111 string s = string("BES: fatal, cannot open BES configuration file ")
00112 + _keys_file_name + ": " ;
00113 char *err = strerror( myerrno ) ;
00114 if( err )
00115 s += err ;
00116 else
00117 s += "Unknown error" ;
00118
00119 s += (string)".\n" + "The current working directory is " + path + "\n" ;
00120 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00121 }
00122
00123 try
00124 {
00125 load_keys() ;
00126 }
00127 catch( BESError &e )
00128 {
00129
00130
00131 clean() ;
00132 throw BESInternalFatalError( e.get_message(),
00133 e.get_file(), e.get_line() ) ;
00134 }
00135 catch(...)
00136 {
00137 clean() ;
00138 string s = (string)"Undefined exception while trying to load keys "
00139 + "from bes configuration file " + _keys_file_name ;
00140 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00141 }
00142 }
00143
00144 void
00145 BESKeys::clean()
00146 {
00147 if( _keys_file )
00148 {
00149 _keys_file->close() ;
00150 delete _keys_file ;
00151 }
00152 if( _the_keys && _own_keys )
00153 {
00154 delete _the_keys ;
00155 }
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165 bool
00166 BESKeys::LoadedKeys( const string &key_file )
00167 {
00168 vector<string>::const_iterator i = BESKeys::KeyList.begin() ;
00169 vector<string>::const_iterator e = BESKeys::KeyList.end() ;
00170 for( ; i != e; i++ )
00171 {
00172 if( (*i) == key_file )
00173 {
00174 return true ;
00175 }
00176 }
00177 return false ;
00178 }
00179
00180 void
00181 BESKeys::load_keys()
00182 {
00183 char buffer[255];
00184 string key,value;
00185 while(!(*_keys_file).eof())
00186 {
00187 if((*_keys_file).getline(buffer,255))
00188 {
00189 bool addto = false ;
00190 if( break_pair( buffer, key, value, addto ) )
00191 {
00192 if( key == BES_INCLUDE_KEY )
00193 {
00194 load_include_files( value ) ;
00195 }
00196 else
00197 {
00198 set_key( key, value, addto ) ;
00199 }
00200 }
00201 }
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 inline bool
00214 BESKeys::break_pair( const char* b, string& key, string &value, bool &addto )
00215 {
00216 addto = false ;
00217
00218 if( b && ( b[0] != '#' ) && ( !only_blanks( b ) ) )
00219 {
00220 register size_t l = strlen( b ) ;
00221 if( l > 1 )
00222 {
00223 int pos = 0 ;
00224 bool done = false ;
00225 for( register size_t j = 0; j < l && !done ; j++ )
00226 {
00227 if( b[j] == '=' )
00228 {
00229 if( !addto ) pos = j ;
00230 else
00231 {
00232 if( pos != static_cast<int>(j-1) )
00233 {
00234 string s = string("BES: Invalid entry ") + b
00235 + " in configuration file "
00236 + _keys_file_name
00237 + " '+' character found in variable name"
00238 + " or attempting '+=' with space"
00239 + " between the characters.\n" ;
00240 throw BESInternalFatalError( s, __FILE__, __LINE__);
00241 }
00242 }
00243 done = true ;
00244 }
00245 else if( b[j] == '+' )
00246 {
00247 addto = true ;
00248 pos = j ;
00249 }
00250 }
00251 if( !done )
00252 {
00253 string s = string("BES: Invalid entry ") + b
00254 + " in configuration file "
00255 + _keys_file_name + ": "
00256 + " '=' character not found.\n" ;
00257 throw BESInternalFatalError( s, __FILE__, __LINE__);
00258 }
00259
00260 string s = b ;
00261 key = s.substr( 0, pos ) ;
00262 BESUtil::removeLeadingAndTrailingBlanks( key ) ;
00263 if( addto ) value = s.substr( pos+2, s.size() ) ;
00264 else value = s.substr( pos+1, s.size() ) ;
00265 BESUtil::removeLeadingAndTrailingBlanks( value ) ;
00266
00267 return true;
00268 }
00269
00270 return false;
00271 }
00272
00273 return false;
00274 }
00275
00285 void
00286 BESKeys::load_include_files( const string &files )
00287 {
00288 string newdir ;
00289 BESFSFile allfiles( files ) ;
00290
00291
00292
00293 if( !files.empty() && files[0] == '/' )
00294 {
00295 newdir = allfiles.getDirName() ;
00296 }
00297 else
00298 {
00299
00300
00301 BESFSFile currfile( _keys_file_name ) ;
00302 string currdir = currfile.getDirName() ;
00303
00304 string alldir = allfiles.getDirName() ;
00305
00306 if( ( currdir == "./" || currdir == "." )
00307 && ( alldir == "./" || alldir == "." ) )
00308 {
00309 newdir = "./" ;
00310 }
00311 else
00312 {
00313 if( alldir == "./" || alldir == "." )
00314 {
00315 newdir = currdir ;
00316 }
00317 else
00318 {
00319 newdir = currdir + "/" + alldir ;
00320 }
00321 }
00322 }
00323
00324
00325
00326 BESFSDir fsd( newdir, allfiles.getFileName() ) ;
00327 BESFSDir::fileIterator i = fsd.beginOfFileList() ;
00328 BESFSDir::fileIterator e = fsd.endOfFileList() ;
00329 for( ; i != e; i++ )
00330 {
00331 load_include_file( (*i).getFullPath() ) ;
00332 }
00333 }
00334
00341 void
00342 BESKeys::load_include_file( const string &file )
00343 {
00344
00345
00346
00347 if( !BESKeys::LoadedKeys( file ) )
00348 {
00349 BESKeys::KeyList.push_back( file ) ;
00350 BESKeys tmp( file, _the_keys ) ;
00351 }
00352 }
00353
00354 bool
00355 BESKeys::only_blanks(const char *line)
00356 {
00357 int val;
00358 regex_t rx;
00359 string expr = "[^[:space:]]" ;
00360 val = regcomp( &rx, expr.c_str(), REG_ICASE ) ;
00361
00362 if( val != 0 )
00363 {
00364 string s = (string)"Regular expression " + expr
00365 + " did not compile correctly "
00366 + " in configuration file " + _keys_file_name ;
00367 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00368 }
00369 val = regexec( &rx, line, 0, 0, REG_NOTBOL ) ;
00370 if( val == 0 )
00371 {
00372 regfree( &rx ) ;
00373 return false ;
00374 }
00375 else
00376 {
00377 if( val == REG_NOMATCH )
00378 {
00379 regfree( &rx ) ;
00380 return true ;
00381 }
00382 else if( val == REG_ESPACE )
00383 {
00384 string s = (string)"Execution of regular expression out of space"
00385 + " in configuration file " + _keys_file_name ;
00386 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00387 }
00388 else
00389 {
00390 string s = (string)"Execution of regular expression has unknown "
00391 + " problem in configuration file " + _keys_file_name ;
00392 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00393 }
00394 }
00395 }
00396
00413 void
00414 BESKeys::set_key( const string &key, const string &val, bool addto )
00415 {
00416 map<string,vector<string> >::iterator i ;
00417 i = _the_keys->find( key ) ;
00418 if( i == _the_keys->end() )
00419 {
00420 vector<string> vals ;
00421 (*_the_keys)[key] = vals ;
00422 }
00423 if( !addto ) (*_the_keys)[key].clear() ;
00424 if( !val.empty() )
00425 {
00426 (*_the_keys)[key].push_back( val ) ;
00427 }
00428 }
00429
00441 void
00442 BESKeys::set_key( const string &pair )
00443 {
00444 string key ;
00445 string val ;
00446 bool addto = false ;
00447 break_pair( pair.c_str(), key, val, addto ) ;
00448 set_key( key, val, addto ) ;
00449 }
00450
00465 void
00466 BESKeys::get_value( const string& s, string &val, bool &found )
00467 {
00468 found = false ;
00469 map<string,vector<string> >::iterator i ;
00470 i = _the_keys->find( s ) ;
00471 if( i != _the_keys->end() )
00472 {
00473 found = true ;
00474 if( (*i).second.size() > 1 )
00475 {
00476 string err = string("Multiple values for the key ") + s
00477 + " found, should only be one." ;
00478 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00479 }
00480 if( (*i).second.size() == 1 )
00481 {
00482 val = (*i).second[0] ;
00483 }
00484 else
00485 {
00486 val = "" ;
00487 }
00488 }
00489 }
00490
00502 void
00503 BESKeys::get_values( const string& s, vector<string> &vals, bool &found )
00504 {
00505 found = false ;
00506 map<string,vector<string> >::iterator i ;
00507 i = _the_keys->find( s ) ;
00508 if( i != _the_keys->end() )
00509 {
00510 found = true ;
00511 vals = (*i).second ;
00512 }
00513 }
00514
00521 void
00522 BESKeys::dump( ostream &strm ) const
00523 {
00524 strm << BESIndent::LMarg << "BESKeys::dump - ("
00525 << (void *)this << ")" << endl ;
00526 BESIndent::Indent() ;
00527 strm << BESIndent::LMarg << "key file:" << _keys_file_name << endl ;
00528 if( _keys_file && *_keys_file )
00529 {
00530 strm << BESIndent::LMarg << "key file is valid" << endl ;
00531 }
00532 else
00533 {
00534 strm << BESIndent::LMarg << "key file is NOT valid" << endl ;
00535 }
00536 if( _the_keys && _the_keys->size() )
00537 {
00538 strm << BESIndent::LMarg << " keys:" << endl ;
00539 BESIndent::Indent() ;
00540 Keys_citer i = _the_keys->begin() ;
00541 Keys_citer ie = _the_keys->end() ;
00542 for( ; i != ie; i++ )
00543 {
00544 strm << BESIndent::LMarg << (*i).first << ":" << endl ;
00545 BESIndent::Indent() ;
00546 vector<string>::const_iterator v = (*i).second.begin() ;
00547 vector<string>::const_iterator ve = (*i).second.end() ;
00548 for( ; v != ve; v++ )
00549 {
00550 strm << (*v) << endl ;
00551 }
00552 BESIndent::UnIndent() ;
00553 }
00554 BESIndent::UnIndent() ;
00555 }
00556 else
00557 {
00558 strm << BESIndent::LMarg << "keys: none" << endl ;
00559 }
00560 BESIndent::UnIndent() ;
00561 }
00562