OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
ServerApp.cc
Go to the documentation of this file.
00001 // ServerApp.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025 
00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
00032 
00033 #include <signal.h>
00034 #include <unistd.h> // for getpid
00035 #include <grp.h>    // for getgrnam
00036 #include <pwd.h>    // for getpwnam
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     // OS/2 and TPF don't support groups.
00122 
00123     // get group id or name from BES configuration file
00124     // If BES.Group begins with # then it is a group id,
00125     // else it is a group name and look up the id.
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         // group id starts with a #, so is a group id
00156         const char *group_c = group_str.c_str() ;
00157         group_c++ ;
00158         new_gid = atoi( group_c ) ;
00159     }
00160     else
00161     {
00162         // specified group is a group name
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     // Get user name or id from the BES configuration file.
00211     // If the BES.User value begins with # then it is a user
00212     // id, else it is a user name and need to look up the
00213     // user id.
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     // new user id cannot be root (0)
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     // If you change the getopt statement below, be sure to make the
00293     // corresponding change in daemon.cc and besctl.in
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 ; // we can ignore the /var/run directory option here
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     // before we can do any processing, log any messages, initialize any
00331     // modules, do anything, we need to determine where the BES
00332     // configuration file lives. From here we get the name of the log
00333     // file, group and user id, and information that the modules will
00334     // need to run properly.
00335 
00336     // If the -c optiion was passed, set the config file name in TheBESKeys
00337     if( !dashc.empty() )
00338     {
00339         TheBESKeys::ConfigFile = dashc ;
00340     }
00341 
00342     // If the -c option was not passed, but the -i option
00343     // was passed, then use the -i option to construct
00344     // the path to the config file
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     // Now that we have the configuration information, we can log to the
00356     // BES log file if there are errors in starting up, etc...
00357 
00358     uid_t curr_euid = geteuid() ;
00359 #ifndef BES_DEVELOPER
00360     // must be root to run this app and to set user id and group id later
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     // register the two debug context for the server and ppt. The
00373     // Default Module will register the bes context.
00374     BESDebug::Register( "server" ) ;
00375     BESDebug::Register( "ppt" ) ;
00376 
00377     // Before we can load modules, start writing to the BES log
00378     // file, etc... we need to run as the proper user. Set the user
00379     // id and the group id to what is specified in the BES
00380     // configuration file
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     // Because we are now running as the user specified in the
00396     // configuraiton file, we won't be able to listen on system ports.
00397     // If this is a problem, we may need to move this code above setting
00398     // the user and group ids.
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", "ServerApp: done initializing default module"
00516                         << endl ) ;
00517 
00518     BESDEBUG( "server", "ServerApp: initializing default commands ... "
00519                         << endl ) ;
00520     BESXMLDefaultCommands::initialize( argc, argv ) ;
00521     BESDEBUG( "server", "ServerApp: done initializing default commands"
00522                         << endl ) ;
00523 
00524     // This will load and initialize all of the modules
00525     BESDEBUG( "server", "ServerApp: initializing loaded modules ... "
00526                         << endl ) ;
00527     int ret = BESModuleApp::initialize( argc, argv ) ;
00528     BESDEBUG( "server", "ServerApp: done initializing loaded modules"
00529                         << endl ) ;
00530 
00531     BESDEBUG( "server", "ServerApp: initialized settings:" << *this ) ;
00532 
00533     if( needhelp )
00534     {
00535         BESServerUtils::show_usage( BESApp::TheApplication()->appName() ) ;
00536     }
00537 
00538     return ret ;
00539 }
00540 
00541 int
00542 ServerApp::run()
00543 {
00544     try
00545     {
00546         BESDEBUG( "server", "ServerApp: initializing memory pool ... "
00547                             << endl ) ;
00548         BESMemoryManager::initialize_memory_pool() ;
00549         BESDEBUG( "server", "OK" << endl ) ;
00550 
00551         SocketListener listener ;
00552 
00553         if( _portVal )
00554         {
00555             _ts = new TcpSocket( _portVal ) ;
00556             listener.listen( _ts ) ;
00557             BESDEBUG( "server", "ServerApp: listening on port ("
00558                                 << _portVal << ")" << endl ) ;
00559         }
00560 
00561         if( !_unixSocket.empty() )
00562         {
00563             _us = new UnixSocket( _unixSocket ) ;
00564             listener.listen( _us ) ;
00565             BESDEBUG( "server", "ServerApp: listening on unix socket ("
00566                                 << _unixSocket << ")" << endl ) ;
00567         }
00568 
00569         BESServerHandler handler ;
00570 
00571         _ps = new PPTServer( &handler, &listener, _secure ) ;
00572         _ps->initConnection() ;
00573     }
00574     catch( BESError &se )
00575     {
00576         cerr << se.get_message() << endl ;
00577         (*BESLog::TheLog()) << se.get_message() << endl ;
00578         return 1 ;
00579     }
00580     catch( ... )
00581     {
00582         cerr << "caught unknown exception" << endl ;
00583         (*BESLog::TheLog()) << "caught unknown exception initializing sockets"
00584                             << endl ;
00585         return 1 ;
00586     }
00587 
00588     return 0 ;
00589 }
00590 
00591 int
00592 ServerApp::terminate( int sig )
00593 {
00594     pid_t apppid = getpid() ;
00595     if( apppid == _mypid )
00596     {
00597         if( _ps )
00598         {
00599             _ps->closeConnection() ;
00600             delete _ps ;
00601         }
00602         if( _ts )
00603         {
00604             _ts->close() ;
00605             delete _ts ;
00606         }
00607         if( _us )
00608         {
00609             _us->close() ;
00610             delete _us ;
00611         }
00612 
00613         // Do this in the reverse order that it was initialized. So
00614         // terminate the loaded modules first, then the default
00615         // commands, then the default module.
00616         BESDEBUG( "server", "ServerApp: terminating loaded modules ...  "
00617                             << endl ) ;
00618         BESModuleApp::terminate( sig ) ;
00619         BESDEBUG( "server", "ServerApp: done terminating loaded modules"
00620                             << endl ) ;
00621 
00622         BESDEBUG( "server", "ServerApp: terminating default commands ...  "
00623                             << endl ) ;
00624         BESXMLDefaultCommands::terminate( ) ;
00625         BESDEBUG( "server", "ServerApp: done terminating default commands ...  "
00626                             << endl ) ;
00627 
00628         BESDEBUG( "server", "ServerApp: terminating default module ... "
00629                             << endl ) ;
00630         BESDefaultModule::terminate( ) ;
00631         BESDEBUG( "server", "ServerApp: done terminating default module ... "
00632                             << endl ) ;
00633     }
00634     return sig ;
00635 }
00636 
00643 void
00644 ServerApp::dump( ostream &strm ) const
00645 {
00646     strm << BESIndent::LMarg << "ServerApp::dump - ("
00647                              << (void *)this << ")" << endl ;
00648     BESIndent::Indent() ;
00649     strm << BESIndent::LMarg << "got port? " << _gotPort << endl ;
00650     strm << BESIndent::LMarg << "port: " << _portVal << endl ;
00651     strm << BESIndent::LMarg << "unix socket: " << _unixSocket << endl ;
00652     strm << BESIndent::LMarg << "is secure? " << _secure << endl ;
00653     strm << BESIndent::LMarg << "pid: " << _mypid << endl ;
00654     if( _ts )
00655     {
00656         strm << BESIndent::LMarg << "tcp socket:" << endl ;
00657         BESIndent::Indent() ;
00658         _ts->dump( strm ) ;
00659         BESIndent::UnIndent() ;
00660     }
00661     else
00662     {
00663         strm << BESIndent::LMarg << "tcp socket: null" << endl ;
00664     }
00665     if( _us )
00666     {
00667         strm << BESIndent::LMarg << "unix socket:" << endl ;
00668         BESIndent::Indent() ;
00669         _us->dump( strm ) ;
00670         BESIndent::UnIndent() ;
00671     }
00672     else
00673     {
00674         strm << BESIndent::LMarg << "unix socket: null" << endl ;
00675     }
00676     if( _ps )
00677     {
00678         strm << BESIndent::LMarg << "ppt server:" << endl ;
00679         BESIndent::Indent() ;
00680         _ps->dump( strm ) ;
00681         BESIndent::UnIndent() ;
00682     }
00683     else
00684     {
00685         strm << BESIndent::LMarg << "ppt server: null" << endl ;
00686     }
00687     BESModuleApp::dump( strm ) ;
00688     BESIndent::UnIndent() ;
00689 }
00690 
00691 int
00692 main( int argc, char **argv )
00693 {
00694     try
00695     {
00696         ServerApp app ;
00697         return app.main( argc, argv ) ;
00698     }
00699     catch( BESError &e )
00700     {
00701         cerr << "Caught unhandled exception: " << endl ;
00702         cerr << e.get_message() << endl ;
00703         return 1 ;
00704     }
00705     catch( ... )
00706     {
00707         cerr << "Caught unhandled, unknown exception" << endl ;
00708         return 1 ;
00709     }
00710     return 0 ;
00711 }
00712