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 map<string,vector<string> >::iterator i ;
00175 i = _the_keys->find( key ) ;
00176 if( i == _the_keys->end() )
00177 {
00178 vector<string> vals ;
00179 (*_the_keys)[key] = vals ;
00180 }
00181 if( !value.empty() )
00182 {
00183 (*_the_keys)[key].push_back( value ) ;
00184 }
00185 }
00186 }
00187 }
00188 }
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 inline bool
00200 BESKeys::break_pair( const char* b, string& key, string &value, bool &addto )
00201 {
00202 addto = false ;
00203
00204 if( b && ( b[0] != '#' ) && ( !only_blanks( b ) ) )
00205 {
00206 register size_t l = strlen( b ) ;
00207 if( l > 1 )
00208 {
00209 int pos = 0 ;
00210 bool done = false ;
00211 for( register size_t j = 0; j < l && !done ; j++ )
00212 {
00213 if( b[j] == '=' )
00214 {
00215 if( !addto ) pos = j ;
00216 else
00217 {
00218 if( pos != j-1 )
00219 {
00220 string s = string("BES: Invalid entry ") + b
00221 + " in configuration file "
00222 + _keys_file_name
00223 + " '+' character found in variable name"
00224 + " or attempting '+=' with space"
00225 + " between the characters.\n" ;
00226 throw BESInternalFatalError( s, __FILE__, __LINE__);
00227 }
00228 }
00229 done = true ;
00230 }
00231 else if( b[j] == '+' )
00232 {
00233 addto = true ;
00234 pos = j ;
00235 }
00236 }
00237 if( !done )
00238 {
00239 string s = string("BES: Invalid entry ") + b
00240 + " in configuration file "
00241 + _keys_file_name + ": "
00242 + " '=' character not found.\n" ;
00243 throw BESInternalFatalError( s, __FILE__, __LINE__);
00244 }
00245
00246 string s = b ;
00247 key = s.substr( 0, pos ) ;
00248 BESUtil::removeLeadingAndTrailingBlanks( key ) ;
00249 if( addto ) value = s.substr( pos+2, s.size() ) ;
00250 else value = s.substr( pos+1, s.size() ) ;
00251 BESUtil::removeLeadingAndTrailingBlanks( value ) ;
00252
00253 return true;
00254 }
00255
00256 return false;
00257 }
00258
00259 return false;
00260 }
00261
00271 void
00272 BESKeys::load_include_files( const string &files )
00273 {
00274 string newdir ;
00275 BESFSFile allfiles( files ) ;
00276
00277
00278
00279 if( !files.empty() && files[0] == '/' )
00280 {
00281 newdir = allfiles.getDirName() ;
00282 }
00283 else
00284 {
00285
00286
00287 BESFSFile currfile( _keys_file_name ) ;
00288 string currdir = currfile.getDirName() ;
00289
00290 string alldir = allfiles.getDirName() ;
00291
00292 if( ( currdir == "./" || currdir == "." )
00293 && ( alldir == "./" || alldir == "." ) ) newdir = "./" ;
00294 else newdir = currdir + "/" + alldir ;
00295 }
00296
00297
00298
00299 BESFSDir fsd( newdir, allfiles.getFileName() ) ;
00300 BESFSDir::fileIterator i = fsd.beginOfFileList() ;
00301 BESFSDir::fileIterator e = fsd.endOfFileList() ;
00302 for( ; i != e; i++ )
00303 {
00304 load_include_file( (*i).getFullPath() ) ;
00305 }
00306 }
00307
00314 void
00315 BESKeys::load_include_file( const string &file )
00316 {
00317
00318
00319 BESKeys tmp( file, _the_keys ) ;
00320 }
00321
00322 bool
00323 BESKeys::only_blanks(const char *line)
00324 {
00325 int val;
00326 regex_t rx;
00327 string expr = "[^[:space:]]" ;
00328 val = regcomp( &rx, expr.c_str(), REG_ICASE ) ;
00329
00330 if( val != 0 )
00331 {
00332 string s = (string)"Regular expression " + expr
00333 + " did not compile correctly "
00334 + " in configuration file " + _keys_file_name ;
00335 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00336 }
00337 val = regexec( &rx, line, 0, 0, REG_NOTBOL ) ;
00338 if( val == 0 )
00339 {
00340 regfree( &rx ) ;
00341 return false ;
00342 }
00343 else
00344 {
00345 if( val == REG_NOMATCH )
00346 {
00347 regfree( &rx ) ;
00348 return true ;
00349 }
00350 else if( val == REG_ESPACE )
00351 {
00352 string s = (string)"Execution of regular expression out of space"
00353 + " in configuration file " + _keys_file_name ;
00354 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00355 }
00356 else
00357 {
00358 string s = (string)"Execution of regular expression has unknown "
00359 + " problem in configuration file " + _keys_file_name ;
00360 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00361 }
00362 }
00363 }
00364
00381 void
00382 BESKeys::set_key( const string &key, const string &val, bool addto )
00383 {
00384 map<string,vector<string> >::iterator i ;
00385 i = _the_keys->find( key ) ;
00386 if( i == _the_keys->end() )
00387 {
00388 vector<string> vals ;
00389 (*_the_keys)[key] = vals ;
00390 }
00391 if( !addto ) (*_the_keys)[key].clear() ;
00392 if( !val.empty() )
00393 {
00394 (*_the_keys)[key].push_back( val ) ;
00395 }
00396 }
00397
00409 void
00410 BESKeys::set_key( const string &pair )
00411 {
00412 string key ;
00413 string val ;
00414 bool addto = false ;
00415 break_pair( pair.c_str(), key, val, addto ) ;
00416 set_key( key, val, addto ) ;
00417 }
00418
00433 void
00434 BESKeys::get_value( const string& s, string &val, bool &found )
00435 {
00436 found = false ;
00437 map<string,vector<string> >::iterator i ;
00438 i = _the_keys->find( s ) ;
00439 if( i != _the_keys->end() )
00440 {
00441 found = true ;
00442 if( (*i).second.size() > 1 )
00443 {
00444 string err = string("Multiple values for the key ") + s
00445 + " found, should only be one." ;
00446 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00447 }
00448 if( (*i).second.size() == 1 )
00449 {
00450 val = (*i).second[0] ;
00451 }
00452 else
00453 {
00454 val = "" ;
00455 }
00456 }
00457 }
00458
00470 void
00471 BESKeys::get_values( const string& s, vector<string> &vals, bool &found )
00472 {
00473 found = false ;
00474 map<string,vector<string> >::iterator i ;
00475 i = _the_keys->find( s ) ;
00476 if( i != _the_keys->end() )
00477 {
00478 found = true ;
00479 vals = (*i).second ;
00480 }
00481 }
00482
00489 void
00490 BESKeys::dump( ostream &strm ) const
00491 {
00492 strm << BESIndent::LMarg << "BESKeys::dump - ("
00493 << (void *)this << ")" << endl ;
00494 BESIndent::Indent() ;
00495 strm << BESIndent::LMarg << "key file:" << _keys_file_name << endl ;
00496 if( _keys_file && *_keys_file )
00497 {
00498 strm << BESIndent::LMarg << "key file is valid" << endl ;
00499 }
00500 else
00501 {
00502 strm << BESIndent::LMarg << "key file is NOT valid" << endl ;
00503 }
00504 if( _the_keys && _the_keys->size() )
00505 {
00506 strm << BESIndent::LMarg << " keys:" << endl ;
00507 BESIndent::Indent() ;
00508 Keys_citer i = _the_keys->begin() ;
00509 Keys_citer ie = _the_keys->end() ;
00510 for( ; i != ie; i++ )
00511 {
00512 strm << BESIndent::LMarg << (*i).first << ":" << endl ;
00513 BESIndent::Indent() ;
00514 vector<string>::const_iterator v = (*i).second.begin() ;
00515 vector<string>::const_iterator ve = (*i).second.end() ;
00516 for( ; v != ve; v++ )
00517 {
00518 strm << (*v) << endl ;
00519 }
00520 BESIndent::UnIndent() ;
00521 }
00522 BESIndent::UnIndent() ;
00523 }
00524 else
00525 {
00526 strm << BESIndent::LMarg << "keys: none" << endl ;
00527 }
00528 BESIndent::UnIndent() ;
00529 }
00530