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
00074 BESKeys::BESKeys( const string &keys_file_name )
00075 : _keys_file( 0 ),
00076 _keys_file_name( keys_file_name ),
00077 _the_keys( 0 ),
00078 _own_keys( true )
00079 {
00080 _the_keys = new map<string,vector<string> >;
00081 initialize_keys( ) ;
00082 }
00083
00084 BESKeys::BESKeys( const string &keys_file_name, map<string,vector<string> > *keys)
00085 : _keys_file( 0 ),
00086 _keys_file_name( keys_file_name ),
00087 _the_keys( keys ),
00088 _own_keys( false )
00089 {
00090 initialize_keys( ) ;
00091 }
00092
00095 BESKeys::~BESKeys()
00096 {
00097 clean() ;
00098 }
00099
00100 void
00101 BESKeys::initialize_keys( )
00102 {
00103 _keys_file = new ifstream( _keys_file_name.c_str() ) ;
00104 int myerrno = errno ;
00105 if( !(*_keys_file) )
00106 {
00107 char path[500] ;
00108 getcwd( path, sizeof( path ) ) ;
00109 string s = string("BES: fatal, cannot open BES configuration file ")
00110 + _keys_file_name + ": " ;
00111 char *err = strerror( myerrno ) ;
00112 if( err )
00113 s += err ;
00114 else
00115 s += "Unknown error" ;
00116
00117 s += (string)".\n" + "The current working directory is " + path + "\n" ;
00118 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00119 }
00120
00121 try
00122 {
00123 load_keys() ;
00124 }
00125 catch( BESError &e )
00126 {
00127
00128
00129 clean() ;
00130 throw BESInternalFatalError( e.get_message(),
00131 e.get_file(), e.get_line() ) ;
00132 }
00133 catch(...)
00134 {
00135 clean() ;
00136 string s = (string)"Undefined exception while trying to load keys "
00137 + "from bes configuration file " + _keys_file_name ;
00138 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00139 }
00140 }
00141
00142 void
00143 BESKeys::clean()
00144 {
00145 if( _keys_file )
00146 {
00147 _keys_file->close() ;
00148 delete _keys_file ;
00149 }
00150 if( _the_keys && _own_keys )
00151 {
00152 delete _the_keys ;
00153 }
00154 }
00155
00156 void
00157 BESKeys::load_keys()
00158 {
00159 char buffer[255];
00160 string key,value;
00161 while(!(*_keys_file).eof())
00162 {
00163 if((*_keys_file).getline(buffer,255))
00164 {
00165 bool addto = false ;
00166 if( break_pair( buffer, key, value, addto ) )
00167 {
00168 if( key == BES_INCLUDE_KEY )
00169 {
00170 load_include_files( value ) ;
00171 }
00172 else
00173 {
00174 set_key( key, value, addto ) ;
00175 }
00176 }
00177 }
00178 }
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 inline bool
00190 BESKeys::break_pair( const char* b, string& key, string &value, bool &addto )
00191 {
00192 addto = false ;
00193
00194 if( b && ( b[0] != '#' ) && ( !only_blanks( b ) ) )
00195 {
00196 register size_t l = strlen( b ) ;
00197 if( l > 1 )
00198 {
00199 int pos = 0 ;
00200 bool done = false ;
00201 for( register size_t j = 0; j < l && !done ; j++ )
00202 {
00203 if( b[j] == '=' )
00204 {
00205 if( !addto ) pos = j ;
00206 else
00207 {
00208 if( pos != j-1 )
00209 {
00210 string s = string("BES: Invalid entry ") + b
00211 + " in configuration file "
00212 + _keys_file_name
00213 + " '+' character found in variable name"
00214 + " or attempting '+=' with space"
00215 + " between the characters.\n" ;
00216 throw BESInternalFatalError( s, __FILE__, __LINE__);
00217 }
00218 }
00219 done = true ;
00220 }
00221 else if( b[j] == '+' )
00222 {
00223 addto = true ;
00224 pos = j ;
00225 }
00226 }
00227 if( !done )
00228 {
00229 string s = string("BES: Invalid entry ") + b
00230 + " in configuration file "
00231 + _keys_file_name + ": "
00232 + " '=' character not found.\n" ;
00233 throw BESInternalFatalError( s, __FILE__, __LINE__);
00234 }
00235
00236 string s = b ;
00237 key = s.substr( 0, pos ) ;
00238 BESUtil::removeLeadingAndTrailingBlanks( key ) ;
00239 if( addto ) value = s.substr( pos+2, s.size() ) ;
00240 else value = s.substr( pos+1, s.size() ) ;
00241 BESUtil::removeLeadingAndTrailingBlanks( value ) ;
00242
00243 return true;
00244 }
00245
00246 return false;
00247 }
00248
00249 return false;
00250 }
00251
00261 void
00262 BESKeys::load_include_files( const string &files )
00263 {
00264 string newdir ;
00265 BESFSFile allfiles( files ) ;
00266
00267
00268
00269 if( !files.empty() && files[0] == '/' )
00270 {
00271 newdir = allfiles.getDirName() ;
00272 }
00273 else
00274 {
00275
00276
00277 BESFSFile currfile( _keys_file_name ) ;
00278 string currdir = currfile.getDirName() ;
00279
00280 string alldir = allfiles.getDirName() ;
00281
00282 if( ( currdir == "./" || currdir == "." )
00283 && ( alldir == "./" || alldir == "." ) ) newdir = "./" ;
00284 else newdir = currdir + "/" + alldir ;
00285 }
00286
00287
00288
00289 BESFSDir fsd( newdir, allfiles.getFileName() ) ;
00290 BESFSDir::fileIterator i = fsd.beginOfFileList() ;
00291 BESFSDir::fileIterator e = fsd.endOfFileList() ;
00292 for( ; i != e; i++ )
00293 {
00294 load_include_file( (*i).getFullPath() ) ;
00295 }
00296 }
00297
00304 void
00305 BESKeys::load_include_file( const string &file )
00306 {
00307
00308
00309 BESKeys tmp( file, _the_keys ) ;
00310 }
00311
00312 bool
00313 BESKeys::only_blanks(const char *line)
00314 {
00315 int val;
00316 regex_t rx;
00317 string expr = "[^[:space:]]" ;
00318 val = regcomp( &rx, expr.c_str(), REG_ICASE ) ;
00319
00320 if( val != 0 )
00321 {
00322 string s = (string)"Regular expression " + expr
00323 + " did not compile correctly "
00324 + " in configuration file " + _keys_file_name ;
00325 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00326 }
00327 val = regexec( &rx, line, 0, 0, REG_NOTBOL ) ;
00328 if( val == 0 )
00329 {
00330 regfree( &rx ) ;
00331 return false ;
00332 }
00333 else
00334 {
00335 if( val == REG_NOMATCH )
00336 {
00337 regfree( &rx ) ;
00338 return true ;
00339 }
00340 else if( val == REG_ESPACE )
00341 {
00342 string s = (string)"Execution of regular expression out of space"
00343 + " in configuration file " + _keys_file_name ;
00344 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00345 }
00346 else
00347 {
00348 string s = (string)"Execution of regular expression has unknown "
00349 + " problem in configuration file " + _keys_file_name ;
00350 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00351 }
00352 }
00353 }
00354
00371 void
00372 BESKeys::set_key( const string &key, const string &val, bool addto )
00373 {
00374 map<string,vector<string> >::iterator i ;
00375 i = _the_keys->find( key ) ;
00376 if( i == _the_keys->end() )
00377 {
00378 vector<string> vals ;
00379 (*_the_keys)[key] = vals ;
00380 }
00381 if( !addto ) (*_the_keys)[key].clear() ;
00382 if( !val.empty() )
00383 {
00384 (*_the_keys)[key].push_back( val ) ;
00385 }
00386 }
00387
00399 void
00400 BESKeys::set_key( const string &pair )
00401 {
00402 string key ;
00403 string val ;
00404 bool addto = false ;
00405 break_pair( pair.c_str(), key, val, addto ) ;
00406 set_key( key, val, addto ) ;
00407 }
00408
00423 void
00424 BESKeys::get_value( const string& s, string &val, bool &found )
00425 {
00426 found = false ;
00427 map<string,vector<string> >::iterator i ;
00428 i = _the_keys->find( s ) ;
00429 if( i != _the_keys->end() )
00430 {
00431 found = true ;
00432 if( (*i).second.size() > 1 )
00433 {
00434 string err = string("Multiple values for the key ") + s
00435 + " found, should only be one." ;
00436 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00437 }
00438 if( (*i).second.size() == 1 )
00439 {
00440 val = (*i).second[0] ;
00441 }
00442 else
00443 {
00444 val = "" ;
00445 }
00446 }
00447 }
00448
00460 void
00461 BESKeys::get_values( const string& s, vector<string> &vals, bool &found )
00462 {
00463 found = false ;
00464 map<string,vector<string> >::iterator i ;
00465 i = _the_keys->find( s ) ;
00466 if( i != _the_keys->end() )
00467 {
00468 found = true ;
00469 vals = (*i).second ;
00470 }
00471 }
00472
00479 void
00480 BESKeys::dump( ostream &strm ) const
00481 {
00482 strm << BESIndent::LMarg << "BESKeys::dump - ("
00483 << (void *)this << ")" << endl ;
00484 BESIndent::Indent() ;
00485 strm << BESIndent::LMarg << "key file:" << _keys_file_name << endl ;
00486 if( _keys_file && *_keys_file )
00487 {
00488 strm << BESIndent::LMarg << "key file is valid" << endl ;
00489 }
00490 else
00491 {
00492 strm << BESIndent::LMarg << "key file is NOT valid" << endl ;
00493 }
00494 if( _the_keys && _the_keys->size() )
00495 {
00496 strm << BESIndent::LMarg << " keys:" << endl ;
00497 BESIndent::Indent() ;
00498 Keys_citer i = _the_keys->begin() ;
00499 Keys_citer ie = _the_keys->end() ;
00500 for( ; i != ie; i++ )
00501 {
00502 strm << BESIndent::LMarg << (*i).first << ":" << endl ;
00503 BESIndent::Indent() ;
00504 vector<string>::const_iterator v = (*i).second.begin() ;
00505 vector<string>::const_iterator ve = (*i).second.end() ;
00506 for( ; v != ve; v++ )
00507 {
00508 strm << (*v) << endl ;
00509 }
00510 BESIndent::UnIndent() ;
00511 }
00512 BESIndent::UnIndent() ;
00513 }
00514 else
00515 {
00516 strm << BESIndent::LMarg << "keys: none" << endl ;
00517 }
00518 BESIndent::UnIndent() ;
00519 }
00520