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 <signal.h>
00034 #include <unistd.h>
00035 #include <grp.h>
00036 #include <pwd.h>
00037
00038 #include <iostream>
00039 #include <fstream>
00040 #include <sstream>
00041 #include <cstdlib>
00042
00043 using std::cout ;
00044 using std::cerr ;
00045 using std::endl ;
00046 using std::ios ;
00047 using std::ostringstream ;
00048 using std::ofstream ;
00049
00050 #include "config.h"
00051
00052 #include "ServerApp.h"
00053 #include "ServerExitConditions.h"
00054 #include "TheBESKeys.h"
00055 #include "BESLog.h"
00056 #include "SocketListener.h"
00057 #include "TcpSocket.h"
00058 #include "UnixSocket.h"
00059 #include "BESServerHandler.h"
00060 #include "BESError.h"
00061 #include "PPTServer.h"
00062 #include "BESMemoryManager.h"
00063 #include "BESDebug.h"
00064 #include "BESServerUtils.h"
00065
00066 #include "BESDefaultModule.h"
00067 #include "BESXMLDefaultCommands.h"
00068
00069 ServerApp::ServerApp()
00070 : BESModuleApp(),
00071 _portVal( 0 ),
00072 _gotPort( false ),
00073 _unixSocket( "" ),
00074 _secure( false ),
00075 _mypid( 0 ),
00076 _ts( 0 ),
00077 _us( 0 ),
00078 _ps( 0 )
00079 {
00080 _mypid = getpid() ;
00081 }
00082
00083 ServerApp::~ServerApp()
00084 {
00085 }
00086
00087 void
00088 ServerApp::signalTerminate( int sig )
00089 {
00090 if( sig == SIGTERM )
00091 {
00092 BESApp::TheApplication()->terminate( sig ) ;
00093 exit( SERVER_EXIT_NORMAL_SHUTDOWN ) ;
00094 }
00095 }
00096
00097 void
00098 ServerApp::signalInterrupt( int sig )
00099 {
00100 if( sig == SIGINT )
00101 {
00102 BESApp::TheApplication()->terminate( sig ) ;
00103 exit( SERVER_EXIT_NORMAL_SHUTDOWN ) ;
00104 }
00105 }
00106
00107 void
00108 ServerApp::signalRestart( int sig )
00109 {
00110 if( sig == SIGUSR1 )
00111 {
00112 BESApp::TheApplication()->terminate( sig ) ;
00113 exit( SERVER_EXIT_RESTART ) ;
00114 }
00115 }
00116
00117 void
00118 ServerApp::set_group_id()
00119 {
00120 #if !defined(OS2) && !defined(TPF)
00121
00122
00123
00124
00125
00126 BESDEBUG( "server", "ServerApp: Setting group id ... " << endl ) ;
00127 bool found = false ;
00128 string key = "BES.Group" ;
00129 string group_str ;
00130 try
00131 {
00132 TheBESKeys::TheKeys()->get_value( key, group_str, found ) ;
00133 }
00134 catch( BESError &e )
00135 {
00136 BESDEBUG( "server", "FAILED" << endl ) ;
00137 string err = string("FAILED: ") + e.get_message() ;
00138 cerr << err << endl ;
00139 (*BESLog::TheLog()) << err << endl ;
00140 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00141 }
00142 if( !found || group_str.empty() )
00143 {
00144 BESDEBUG( "server", "FAILED" << endl ) ;
00145 string err = "FAILED: Group not specified in BES configuration file" ;
00146 cerr << err << endl ;
00147 (*BESLog::TheLog()) << err << endl ;
00148 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00149 }
00150 BESDEBUG( "server", "to " << group_str << " ... " << endl ) ;
00151
00152 gid_t new_gid = 0 ;
00153 if( group_str[0] == '#' )
00154 {
00155
00156 const char *group_c = group_str.c_str() ;
00157 group_c++ ;
00158 new_gid = atoi( group_c ) ;
00159 }
00160 else
00161 {
00162
00163 struct group *ent ;
00164 ent = getgrnam( group_str.c_str() ) ;
00165 if( !ent )
00166 {
00167 BESDEBUG( "server", "FAILED" << endl ) ;
00168 string err = (string)"FAILED: Group " + group_str
00169 + " does not exist" ;
00170 cerr << err << endl ;
00171 (*BESLog::TheLog()) << err << endl ;
00172 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00173 }
00174 new_gid = ent->gr_gid ;
00175 }
00176
00177 if( new_gid < 1 )
00178 {
00179 BESDEBUG( "server", "FAILED" << endl ) ;
00180 ostringstream err ;
00181 err << "FAILED: Group id " << new_gid
00182 << " not a valid group id for BES" ;
00183 cerr << err.str() << endl ;
00184 (*BESLog::TheLog()) << err.str() << endl ;
00185 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00186 }
00187
00188 BESDEBUG( "server", "to id " << new_gid << " ... " << endl ) ;
00189 if( setgid( new_gid ) == -1 )
00190 {
00191 BESDEBUG( "server", "FAILED" << endl ) ;
00192 ostringstream err ;
00193 err << "FAILED: unable to set the group id to " << new_gid ;
00194 cerr << err.str() << endl ;
00195 (*BESLog::TheLog()) << err.str() << endl ;
00196 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00197 }
00198
00199 BESDEBUG( "server", "OK" << endl ) ;
00200 #else
00201 BESDEBUG( "server", "ServerApp: Groups not supported in this OS" << endl ) ;
00202 #endif
00203 }
00204
00205 void
00206 ServerApp::set_user_id()
00207 {
00208 BESDEBUG( "server", "ServerApp: Setting user id ... " << endl ) ;
00209
00210
00211
00212
00213
00214 bool found = false ;
00215 string key = "BES.User" ;
00216 string user_str ;
00217 try
00218 {
00219 TheBESKeys::TheKeys()->get_value( key, user_str, found ) ;
00220 }
00221 catch( BESError &e )
00222 {
00223 BESDEBUG( "server", "FAILED" << endl ) ;
00224 string err = (string)"FAILED: " + e.get_message() ;
00225 cerr << err << endl ;
00226 (*BESLog::TheLog()) << err << endl ;
00227 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00228 }
00229 if( !found || user_str.empty() )
00230 {
00231 BESDEBUG( "server", "FAILED" << endl ) ;
00232 string err = (string)"FAILED: User not specified in BES config file" ;
00233 cerr << err << endl ;
00234 (*BESLog::TheLog()) << err << endl ;
00235 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00236 }
00237 BESDEBUG( "server", "to " << user_str << " ... " << endl ) ;
00238
00239 uid_t new_id = 0 ;
00240 if( user_str[0] == '#' )
00241 {
00242 const char *user_str_c = user_str.c_str() ;
00243 user_str_c++ ;
00244 new_id = atoi( user_str_c ) ;
00245 }
00246 else
00247 {
00248 struct passwd *ent ;
00249 ent = getpwnam( user_str.c_str() ) ;
00250 if( !ent )
00251 {
00252 BESDEBUG( "server", "FAILED" << endl ) ;
00253 string err = (string)"FAILED: Bad user name specified: "
00254 + user_str ;
00255 cerr << err << endl ;
00256 (*BESLog::TheLog()) << err << endl ;
00257 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00258 }
00259 new_id = ent->pw_uid ;
00260 }
00261
00262
00263 if( !new_id )
00264 {
00265 BESDEBUG( "server", "FAILED" << endl ) ;
00266 string err = (string)"FAILED: BES cannot run as root" ;
00267 cerr << err << endl ;
00268 (*BESLog::TheLog()) << err << endl ;
00269 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00270 }
00271
00272 BESDEBUG( "server", "to " << new_id << " ... " << endl ) ;
00273 if( setuid( new_id ) == -1 )
00274 {
00275 BESDEBUG( "server", "FAILED" << endl ) ;
00276 ostringstream err ;
00277 err << "FAILED: Unable to set user id to " << new_id ;
00278 cerr << err.str() << endl ;
00279 (*BESLog::TheLog()) << err.str() << endl ;
00280 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00281 }
00282 }
00283
00284 int
00285 ServerApp::initialize( int argc, char **argv )
00286 {
00287 int c = 0 ;
00288 bool needhelp = false ;
00289 string dashi ;
00290 string dashc ;
00291
00292
00293
00294 while( ( c = getopt( argc, argv, "hvsd:c:p:u:i:r:" ) ) != EOF )
00295 {
00296 switch( c )
00297 {
00298 case 'i':
00299 dashi = optarg ;
00300 break ;
00301 case 'c':
00302 dashc = optarg ;
00303 break ;
00304 case 'r':
00305 break ;
00306 case 'p':
00307 _portVal = atoi( optarg ) ;
00308 _gotPort = true ;
00309 break ;
00310 case 'u':
00311 _unixSocket = optarg ;
00312 break ;
00313 case 'd':
00314 BESDebug::SetUp( optarg ) ;
00315 break ;
00316 case 'v':
00317 BESServerUtils::show_version( BESApp::TheApplication()->appName() ) ;
00318 break ;
00319 case 's':
00320 _secure = true ;
00321 break ;
00322 case 'h':
00323 case '?':
00324 default:
00325 needhelp = true ;
00326 break ;
00327 }
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337 if( !dashc.empty() )
00338 {
00339 TheBESKeys::ConfigFile = dashc ;
00340 }
00341
00342
00343
00344
00345 if( dashc.empty() && !dashi.empty() )
00346 {
00347 if( dashi[dashi.length()-1] != '/' )
00348 {
00349 dashi += '/' ;
00350 }
00351 string conf_file = dashi + "etc/bes/bes.conf" ;
00352 TheBESKeys::ConfigFile = conf_file ;
00353 }
00354
00355
00356
00357
00358 uid_t curr_euid = geteuid() ;
00359 #ifndef BES_DEVELOPER
00360
00361 if( curr_euid )
00362 {
00363 string err = "FAILED: Must be root to run BES" ;
00364 cerr << err << endl ;
00365 (*BESLog::TheLog()) << err << endl ;
00366 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00367 }
00368 #else
00369 cout << "Developer Mode: not testing if BES is run by root" << endl ;
00370 #endif
00371
00372
00373
00374 BESDebug::Register( "server" ) ;
00375 BESDebug::Register( "ppt" ) ;
00376
00377
00378
00379
00380
00381 if( curr_euid == 0 )
00382 {
00383 #ifdef BES_DEVELOPER
00384 cout << "Developer Mode: Running as root - setting group and user ids"
00385 << endl ;
00386 #endif
00387 set_group_id() ;
00388 set_user_id() ;
00389 }
00390 else
00391 {
00392 cout << "Developer Mode: Not setting group or user ids" << endl ;
00393 }
00394
00395
00396
00397
00398
00399 bool found = false ;
00400 string port_key = "BES.ServerPort" ;
00401 if( !_gotPort )
00402 {
00403 string sPort ;
00404 try
00405 {
00406 TheBESKeys::TheKeys()->get_value( port_key, sPort, found ) ;
00407 }
00408 catch( BESError &e )
00409 {
00410 BESDEBUG( "server", "FAILED" << endl ) ;
00411 string err = (string)"FAILED: " + e.get_message() ;
00412 cerr << err << endl ;
00413 (*BESLog::TheLog()) << err << endl ;
00414 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00415 }
00416 if( found )
00417 {
00418 _portVal = atoi( sPort.c_str() ) ;
00419 if( _portVal != 0 )
00420 {
00421 _gotPort = true ;
00422 }
00423 }
00424 }
00425
00426 found = false ;
00427 string socket_key = "BES.ServerUnixSocket" ;
00428 if( _unixSocket == "" )
00429 {
00430 try
00431 {
00432 TheBESKeys::TheKeys()->get_value( socket_key, _unixSocket, found ) ;
00433 }
00434 catch( BESError &e )
00435 {
00436 BESDEBUG( "server", "FAILED" << endl ) ;
00437 string err = (string)"FAILED: " + e.get_message() ;
00438 cerr << err << endl ;
00439 (*BESLog::TheLog()) << err << endl ;
00440 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00441 }
00442 }
00443
00444 if( !_gotPort && _unixSocket == "" )
00445 {
00446 string msg = "Must specify a tcp port or a unix socket or both\n" ;
00447 msg += "Please specify on the command line with -p <port>" ;
00448 msg += " and/or -u <unix_socket>\n" ;
00449 msg += "Or specify in the bes configuration file with "
00450 + port_key + " and/or " + socket_key + "\n" ;
00451 cout << endl << msg ;
00452 (*BESLog::TheLog()) << msg << endl ;
00453 BESServerUtils::show_usage( BESApp::TheApplication()->appName() ) ;
00454 }
00455
00456 found = false ;
00457 if( _secure == false )
00458 {
00459 string key = "BES.ServerSecure" ;
00460 string isSecure ;
00461 try
00462 {
00463 TheBESKeys::TheKeys()->get_value( key, isSecure, found ) ;
00464 }
00465 catch( BESError &e )
00466 {
00467 BESDEBUG( "server", "FAILED" << endl ) ;
00468 string err = (string)"FAILED: " + e.get_message() ;
00469 cerr << err << endl ;
00470 (*BESLog::TheLog()) << err << endl ;
00471 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00472 }
00473 if( isSecure == "Yes" || isSecure == "YES" || isSecure == "yes" )
00474 {
00475 _secure = true ;
00476 }
00477 }
00478
00479 BESDEBUG( "server", "ServerApp: Registering signal SIGTERM ... " << endl ) ;
00480 if( signal( SIGTERM, signalTerminate ) == SIG_ERR )
00481 {
00482 BESDEBUG( "server", "FAILED" << endl ) ;
00483 string err = "FAILED: cannot register SIGTERM signal handler" ;
00484 cerr << err << endl ;
00485 (*BESLog::TheLog()) << err << endl ;
00486 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00487 }
00488 BESDEBUG( "server", "OK" << endl ) ;
00489
00490 BESDEBUG( "server", "ServerApp: Registering signal SIGINT ... " << endl ) ;
00491 if( signal( SIGINT, signalInterrupt ) == SIG_ERR )
00492 {
00493 BESDEBUG( "server", "FAILED" << endl ) ;
00494 string err = "FAILED: cannot register SIGINT signal handler" ;
00495 cerr << err << endl ;
00496 (*BESLog::TheLog()) << err << endl ;
00497 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00498 }
00499 BESDEBUG( "server", "OK" << endl ) ;
00500
00501 BESDEBUG( "server", "ServerApp: Registering signal SIGUSR1 ... " << endl ) ;
00502 if( signal( SIGUSR1, signalRestart ) == SIG_ERR )
00503 {
00504 BESDEBUG( "server", "FAILED" << endl ) ;
00505 string err = "FAILED: cannot register SIGUSR1 signal handler" ;
00506 cerr << err << endl ;
00507 (*BESLog::TheLog()) << err << endl ;
00508 exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00509 }
00510 BESDEBUG( "server", "OK" << endl ) ;
00511
00512 BESDEBUG( "server", "ServerApp: initializing default module ... "
00513 << endl ) ;
00514 BESDefaultModule::initialize( argc, argv ) ;
00515 BESDEBUG( "server", "OK" << endl ) ;
00516
00517 BESDEBUG( "server", "ServerApp: initializing default commands ... "
00518 << endl ) ;
00519 BESXMLDefaultCommands::initialize( argc, argv ) ;
00520 BESDEBUG( "server", "OK" << endl ) ;
00521
00522
00523 int ret = BESModuleApp::initialize( argc, argv ) ;
00524
00525 BESDEBUG( "server", "ServerApp: initialized settings:" << *this ) ;
00526
00527 if( needhelp )
00528 {
00529 BESServerUtils::show_usage( BESApp::TheApplication()->appName() ) ;
00530 }
00531
00532 return ret ;
00533 }
00534
00535 int
00536 ServerApp::run()
00537 {
00538 try
00539 {
00540 BESDEBUG( "server", "ServerApp: initializing memory pool ... "
00541 << endl ) ;
00542 BESMemoryManager::initialize_memory_pool() ;
00543 BESDEBUG( "server", "OK" << endl ) ;
00544
00545 SocketListener listener ;
00546
00547 if( _portVal )
00548 {
00549 _ts = new TcpSocket( _portVal ) ;
00550 listener.listen( _ts ) ;
00551 BESDEBUG( "server", "ServerApp: listening on port ("
00552 << _portVal << ")" << endl ) ;
00553 }
00554
00555 if( !_unixSocket.empty() )
00556 {
00557 _us = new UnixSocket( _unixSocket ) ;
00558 listener.listen( _us ) ;
00559 BESDEBUG( "server", "ServerApp: listening on unix socket ("
00560 << _unixSocket << ")" << endl ) ;
00561 }
00562
00563 BESServerHandler handler ;
00564
00565 _ps = new PPTServer( &handler, &listener, _secure ) ;
00566 _ps->initConnection() ;
00567 }
00568 catch( BESError &se )
00569 {
00570 cerr << se.get_message() << endl ;
00571 (*BESLog::TheLog()) << se.get_message() << endl ;
00572 return 1 ;
00573 }
00574 catch( ... )
00575 {
00576 cerr << "caught unknown exception" << endl ;
00577 (*BESLog::TheLog()) << "caught unknown exception initializing sockets"
00578 << endl ;
00579 return 1 ;
00580 }
00581
00582 return 0 ;
00583 }
00584
00585 int
00586 ServerApp::terminate( int sig )
00587 {
00588 pid_t apppid = getpid() ;
00589 if( apppid == _mypid )
00590 {
00591 if( _ps )
00592 {
00593 _ps->closeConnection() ;
00594 delete _ps ;
00595 }
00596 if( _ts )
00597 {
00598 _ts->close() ;
00599 delete _ts ;
00600 }
00601 if( _us )
00602 {
00603 _us->close() ;
00604 delete _us ;
00605 }
00606
00607 BESDEBUG( "server", "ServerApp: terminating default module ... "
00608 << endl ) ;
00609 BESDefaultModule::terminate( ) ;
00610 BESDEBUG( "server", "OK" << endl ) ;
00611
00612 BESDEBUG( "server", "ServerApp: terminating default commands ... "
00613 << endl ) ;
00614 BESXMLDefaultCommands::terminate( ) ;
00615 BESDEBUG( "server", "OK" << endl ) ;
00616
00617 BESModuleApp::terminate( sig ) ;
00618 }
00619 return sig ;
00620 }
00621
00628 void
00629 ServerApp::dump( ostream &strm ) const
00630 {
00631 strm << BESIndent::LMarg << "ServerApp::dump - ("
00632 << (void *)this << ")" << endl ;
00633 BESIndent::Indent() ;
00634 strm << BESIndent::LMarg << "got port? " << _gotPort << endl ;
00635 strm << BESIndent::LMarg << "port: " << _portVal << endl ;
00636 strm << BESIndent::LMarg << "unix socket: " << _unixSocket << endl ;
00637 strm << BESIndent::LMarg << "is secure? " << _secure << endl ;
00638 strm << BESIndent::LMarg << "pid: " << _mypid << endl ;
00639 if( _ts )
00640 {
00641 strm << BESIndent::LMarg << "tcp socket:" << endl ;
00642 BESIndent::Indent() ;
00643 _ts->dump( strm ) ;
00644 BESIndent::UnIndent() ;
00645 }
00646 else
00647 {
00648 strm << BESIndent::LMarg << "tcp socket: null" << endl ;
00649 }
00650 if( _us )
00651 {
00652 strm << BESIndent::LMarg << "unix socket:" << endl ;
00653 BESIndent::Indent() ;
00654 _us->dump( strm ) ;
00655 BESIndent::UnIndent() ;
00656 }
00657 else
00658 {
00659 strm << BESIndent::LMarg << "unix socket: null" << endl ;
00660 }
00661 if( _ps )
00662 {
00663 strm << BESIndent::LMarg << "ppt server:" << endl ;
00664 BESIndent::Indent() ;
00665 _ps->dump( strm ) ;
00666 BESIndent::UnIndent() ;
00667 }
00668 else
00669 {
00670 strm << BESIndent::LMarg << "ppt server: null" << endl ;
00671 }
00672 BESModuleApp::dump( strm ) ;
00673 BESIndent::UnIndent() ;
00674 }
00675
00676 int
00677 main( int argc, char **argv )
00678 {
00679 try
00680 {
00681 ServerApp app ;
00682 return app.main( argc, argv ) ;
00683 }
00684 catch( BESError &e )
00685 {
00686 cerr << "Caught unhandled exception: " << endl ;
00687 cerr << e.get_message() << endl ;
00688 return 1 ;
00689 }
00690 catch( ... )
00691 {
00692 cerr << "Caught unhandled, unknown exception" << endl ;
00693 return 1 ;
00694 }
00695 return 0 ;
00696 }
00697