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 #include <signal.h>
00036
00037 #include <cstdlib>
00038 #include <iostream>
00039 #include <string>
00040 #include <fstream>
00041
00042 #ifdef HAVE_UNISTD_H
00043 #include <unistd.h>
00044 #endif
00045
00046 using std::cout ;
00047 using std::cerr ;
00048 using std::endl ;
00049 using std::flush ;
00050 using std::string ;
00051 using std::ofstream ;
00052
00053 #include "CmdApp.h"
00054 #include "CmdClient.h"
00055 #include "CmdTranslation.h"
00056 #include "BESError.h"
00057 #include "BESDebug.h"
00058
00059 #define BES_CMDLN_DEFAULT_TIMEOUT 5
00060
00061 CmdApp::CmdApp()
00062 : BESBaseApp(),
00063 _client( 0 ),
00064 _hostStr( "" ),
00065 _unixStr( "" ),
00066 _portVal( 0 ),
00067 _outputStrm( 0 ),
00068 _inputStrm( 0 ),
00069 _createdInputStrm( false ),
00070 _timeout( 0 ),
00071 _repeat( 0 )
00072 {
00073 }
00074
00075 CmdApp::~CmdApp()
00076 {
00077 if( _client )
00078 {
00079 delete _client ;
00080 _client = 0 ;
00081 }
00082 }
00083
00084 void
00085 CmdApp::showVersion()
00086 {
00087 cout << appName() << ": version 2.0" << endl ;
00088 }
00089
00090 void
00091 CmdApp::showUsage( )
00092 {
00093 cout << endl ;
00094 cout << appName() << ": the following flags are available:" << endl ;
00095 cout << " -h <host> - specifies a host for TCP/IP connection" << endl ;
00096 cout << " -p <port> - specifies a port for TCP/IP connection" << endl ;
00097 cout << " -u <unixSocket> - specifies a unix socket for connection. " << endl ;
00098 cout << " -x <command> - specifies a command for the server to execute" << endl ;
00099 cout << " -i <inputFile> - specifies a file name for a sequence of input commands" << endl ;
00100 cout << " -f <outputFile> - specifies a file name to output the results of the input" << endl ;
00101 cout << " -t <timeoutVal> - specifies an optional timeout value in seconds" << endl ;
00102 cout << " -d - sets the optional debug flag for the client session" << endl ;
00103 cout << " -r <num> - repeat the command(s) num times" << endl ;
00104 cout << " -? - display this list of flags" << endl ;
00105 cout << endl ;
00106 BESDebug::Help( cout ) ;
00107 }
00108
00109 void
00110 CmdApp::signalCannotConnect( int sig )
00111 {
00112 if( sig == SIGCONT )
00113 {
00114 CmdApp *app = dynamic_cast<CmdApp *>(BESApp::TheApplication()) ;
00115 if( app )
00116 {
00117 CmdClient *client = app->client() ;
00118 if( client && !client->isConnected() )
00119 {
00120 cout << BESApp::TheApplication()->appName()
00121 << ": No response, server may be down or "
00122 << "busy with another incoming connection. exiting!\n" ;
00123 exit( 1 ) ;
00124 }
00125 }
00126 }
00127 }
00128
00129 void
00130 CmdApp::signalInterrupt( int sig )
00131 {
00132 if( sig == SIGINT )
00133 {
00134 cout << BESApp::TheApplication()->appName()
00135 << ": Please type exit to terminate the session" << endl ;
00136 }
00137 if( signal( SIGINT, CmdApp::signalInterrupt ) == SIG_ERR )
00138 {
00139 cerr << BESApp::TheApplication()->appName()
00140 << ": Could not re-register signal\n" ;
00141 }
00142 }
00143
00144 void
00145 CmdApp::signalTerminate( int sig )
00146 {
00147 if( sig == SIGTERM )
00148 {
00149 cout << BESApp::TheApplication()->appName()
00150 << ": Please type exit to terminate the session" << endl ;
00151 }
00152 if( signal( SIGTERM, CmdApp::signalTerminate ) == SIG_ERR )
00153 {
00154 cerr << BESApp::TheApplication()->appName()
00155 << ": Could not re-register signal\n" ;
00156 }
00157 }
00158
00159 void
00160 CmdApp::signalBrokenPipe( int sig )
00161 {
00162 if( sig == SIGPIPE )
00163 {
00164 cout << BESApp::TheApplication()->appName()
00165 << ": got a broken pipe, server may be down or the port invalid."
00166 << endl
00167 << "Please check parameters and try again" << endl ;
00168 CmdApp *app = dynamic_cast<CmdApp *>(BESApp::TheApplication()) ;
00169 if( app )
00170 {
00171 CmdClient *client = app->client() ;
00172 if( client )
00173 {
00174 client->brokenPipe() ;
00175 client->shutdownClient() ;
00176 delete client;
00177 client = 0;
00178 }
00179 }
00180 exit( 1 ) ;
00181 }
00182 }
00183
00184 void
00185 CmdApp::registerSignals()
00186 {
00187
00188 BESDEBUG( "cmdln", "CmdApp: Registering signal SIGCONT ... " << endl ) ;
00189 if( signal( SIGCONT, signalCannotConnect ) == SIG_ERR )
00190 {
00191 BESDEBUG( "cmdln", "FAILED" << endl ) ;
00192 cerr << appName() << "Failed to register signal SIGCONT" << endl ;
00193 exit( 1 ) ;
00194 }
00195 BESDEBUG( "cmdln", "OK" << endl ) ;
00196
00197
00198
00199 BESDEBUG( "cmdln", "CmdApp: Registering signal SIGINT ... " << endl ) ;
00200 if( signal( SIGINT, signalInterrupt ) == SIG_ERR )
00201 {
00202 BESDEBUG( "cmdln", "FAILED" << endl ) ;
00203 cerr << appName() << "Failed to register signal SIGINT" << endl ;
00204 exit( 1 ) ;
00205 }
00206 BESDEBUG( "cmdln", "OK" << endl ) ;
00207
00208
00209
00210 BESDEBUG( "cmdln", "CmdApp: Registering signal SIGTERM ... " << endl ) ;
00211 if( signal( SIGTERM, signalTerminate ) == SIG_ERR )
00212 {
00213 BESDEBUG( "cmdln", "FAILED" << endl ) ;
00214 cerr << appName() << "Failed to register signal SIGTERM" << endl ;
00215 exit( 1 ) ;
00216 }
00217 BESDEBUG( "cmdln", "OK" << endl ) ;
00218
00219
00220 BESDEBUG( "cmdln", "CmdApp: Registering signal SIGPIPE ... " << endl ) ;
00221 if( signal( SIGPIPE, CmdApp::signalBrokenPipe ) == SIG_ERR )
00222 {
00223 BESDEBUG( "cmdln", "FAILED" << endl ) ;
00224 cerr << appName() << "Failed to register signal SIGPIPE" << endl ;
00225 exit( 1 ) ;
00226 }
00227 BESDEBUG( "cmdln", "OK" << endl ) ;
00228 }
00229
00230 int
00231 CmdApp::initialize( int argc, char **argv )
00232 {
00233 int retVal = BESBaseApp::initialize( argc, argv ) ;
00234 if( retVal != 0 )
00235 return retVal ;
00236
00237 CmdTranslation::initialize( argc, argv ) ;
00238
00239 string portStr = "" ;
00240 string outputStr = "" ;
00241 string inputStr = "" ;
00242 string timeoutStr = "" ;
00243 string repeatStr = "" ;
00244
00245 bool badUsage = false ;
00246
00247 int c ;
00248
00249 while( ( c = getopt( argc, argv, "?vd:h:p:t:u:x:f:i:r:" ) ) != EOF )
00250 {
00251 switch( c )
00252 {
00253 case 't':
00254 timeoutStr = optarg ;
00255 break ;
00256 case 'h':
00257 _hostStr = optarg ;
00258 break ;
00259 case 'd':
00260 BESDebug::SetUp( optarg ) ;
00261 break ;
00262 case 'v':
00263 {
00264 showVersion() ;
00265 exit( 0 ) ;
00266 }
00267 break ;
00268 case 'p':
00269 portStr = optarg ;
00270 break ;
00271 case 'u':
00272 _unixStr = optarg ;
00273 break ;
00274 case 'x':
00275 _cmd = optarg ;
00276 break ;
00277 case 'f':
00278 outputStr = optarg ;
00279 break ;
00280 case 'i':
00281 inputStr = optarg ;
00282 break ;
00283 case 'r':
00284 repeatStr = optarg ;
00285 break ;
00286 case '?':
00287 {
00288 showUsage() ;
00289 exit( 0 ) ;
00290 }
00291 break ;
00292 }
00293 }
00294 if( _hostStr == "" && _unixStr == "" )
00295 {
00296 cerr << "host/port or unix socket must be specified" << endl ;
00297 badUsage = true ;
00298 }
00299
00300 if( _hostStr != "" && _unixStr != "" )
00301 {
00302 cerr << "must specify either a host and port or a unix socket" << endl ;
00303 badUsage = true ;
00304 }
00305
00306 if( portStr != "" && _unixStr != "" )
00307 {
00308 cerr << "must specify either a host and port or a unix socket" << endl ;
00309 badUsage = true ;
00310 }
00311
00312 if( _hostStr != "" )
00313 {
00314 if( portStr == "" )
00315 {
00316 cout << "port must be specified when specifying a host" << endl ;
00317 badUsage = true ;
00318 }
00319 else
00320 {
00321 _portVal = atoi( portStr.c_str() ) ;
00322 }
00323 }
00324
00325 if( timeoutStr != "" )
00326 {
00327 _timeout = atoi( timeoutStr.c_str() ) ;
00328 }
00329 else
00330 {
00331 _timeout = BES_CMDLN_DEFAULT_TIMEOUT ;
00332 }
00333
00334 if( outputStr != "" )
00335 {
00336 if( _cmd == "" && inputStr == "" )
00337 {
00338 cerr << "When specifying an output file you must either "
00339 << "specify a command or an input file"
00340 << endl ;
00341 badUsage = true ;
00342 }
00343 else if( _cmd != "" && inputStr != "" )
00344 {
00345 cerr << "You must specify either a command or an input file on "
00346 << "the command line, not both"
00347 << endl ;
00348 badUsage = true ;
00349 }
00350 }
00351
00352 if( badUsage == true )
00353 {
00354 showUsage( ) ;
00355 return 1 ;
00356 }
00357
00358 if( outputStr != "" )
00359 {
00360 _outputStrm = new ofstream( outputStr.c_str() ) ;
00361 if( !(*_outputStrm) )
00362 {
00363 cerr << "could not open the output file " << outputStr << endl ;
00364 badUsage = true ;
00365 }
00366 }
00367
00368 if( inputStr != "" )
00369 {
00370 _inputStrm = new ifstream( inputStr.c_str() ) ;
00371 if( !(*_inputStrm) )
00372 {
00373 cerr << "could not open the input file " << inputStr << endl ;
00374 badUsage = true ;
00375 }
00376 _createdInputStrm = true ;
00377 }
00378
00379 if( !repeatStr.empty() )
00380 {
00381 _repeat = atoi( repeatStr.c_str() ) ;
00382 if( !_repeat && repeatStr != "0" )
00383 {
00384 cerr << "repeat number invalid: " << repeatStr << endl ;
00385 badUsage = true ;
00386 }
00387 if( !_repeat )
00388 {
00389 _repeat = 1 ;
00390 }
00391 }
00392
00393 if( badUsage == true )
00394 {
00395 showUsage( ) ;
00396 return 1 ;
00397 }
00398
00399 registerSignals() ;
00400
00401 BESDEBUG( "cmdln", "CmdApp: initialized settings:" << endl << *this ) ;
00402
00403 return 0 ;
00404 }
00405
00406 int
00407 CmdApp::run()
00408 {
00409 try
00410 {
00411 _client = new CmdClient( ) ;
00412 if( _hostStr != "" )
00413 {
00414 BESDEBUG( "cmdln", "CmdApp: Connecting to host: " << _hostStr
00415 << " at port: " << _portVal << " ... " << endl ) ;
00416 _client->startClient( _hostStr, _portVal, _timeout ) ;
00417 }
00418 else
00419 {
00420 BESDEBUG( "cmdln", "CmdApp: Connecting to unix socket: "
00421 << _unixStr << " ... " << endl ) ;
00422 _client->startClient( _unixStr, _timeout ) ;
00423 }
00424
00425 if( _outputStrm )
00426 {
00427 _client->setOutput( _outputStrm, true ) ;
00428 }
00429 else
00430 {
00431 _client->setOutput( &cout, false ) ;
00432 }
00433 BESDEBUG( "cmdln", "OK" << endl ) ;
00434 }
00435 catch( BESError &e )
00436 {
00437 if( _client )
00438 {
00439 _client->shutdownClient() ;
00440 delete _client ;
00441 _client = 0 ;
00442 }
00443 BESDEBUG( "cmdln", "FAILED" << endl ) ;
00444 cerr << "error starting the client" << endl ;
00445 cerr << e.get_message() << endl ;
00446 exit( 1 ) ;
00447 }
00448
00449 bool do_exit = false ;
00450 try
00451 {
00452 if( _cmd != "" )
00453 {
00454 do_exit = _client->executeCommands( _cmd, _repeat ) ;
00455 }
00456 else if( _inputStrm )
00457 {
00458 do_exit = _client->executeCommands( *_inputStrm, _repeat ) ;
00459 }
00460 else
00461 {
00462 do_exit = _client->interact() ;
00463 }
00464 }
00465 catch( BESError &e )
00466 {
00467 cerr << "error processing commands" << endl ;
00468 cerr << e.get_message() << endl ;
00469 }
00470
00471 try
00472 {
00473 BESDEBUG( "cmdln", "CmdApp: shutting down client ... " << endl ) ;
00474 if( _client )
00475 {
00476
00477 if( !do_exit )
00478 _client->shutdownClient() ;
00479 delete _client ;
00480 _client = 0 ;
00481 }
00482 BESDEBUG( "cmdln", "OK" << endl ) ;
00483
00484 BESDEBUG( "cmdln", "CmdApp: closing input stream ... " << endl ) ;
00485 if( _createdInputStrm )
00486 {
00487 _inputStrm->close() ;
00488 delete _inputStrm ;
00489 _inputStrm = 0 ;
00490 }
00491 BESDEBUG( "cmdln", "OK" << endl ) ;
00492 }
00493 catch( BESError &e )
00494 {
00495 BESDEBUG( "cmdln", "FAILED" << endl ) ;
00496 cerr << "error closing the client" << endl ;
00497 cerr << e.get_message() << endl ;
00498 return 1 ;
00499 }
00500
00501 return 0 ;
00502 }
00503
00510 void
00511 CmdApp::dump( ostream &strm ) const
00512 {
00513 strm << BESIndent::LMarg << "CmdApp::dump - ("
00514 << (void *)this << ")" << endl ;
00515 BESIndent::Indent() ;
00516 if( _client )
00517 {
00518 strm << BESIndent::LMarg << "client: " << endl ;
00519 BESIndent::Indent() ;
00520 _client->dump( strm ) ;
00521 BESIndent::UnIndent() ;
00522 }
00523 else
00524 {
00525 strm << BESIndent::LMarg << "client: null" << endl ;
00526 }
00527 strm << BESIndent::LMarg << "host: " << _hostStr << endl ;
00528 strm << BESIndent::LMarg << "unix socket: " << _unixStr << endl ;
00529 strm << BESIndent::LMarg << "port: " << _portVal << endl ;
00530 strm << BESIndent::LMarg << "command: " << _cmd << endl ;
00531 strm << BESIndent::LMarg << "output stream: " << (void *)_outputStrm << endl ;
00532 strm << BESIndent::LMarg << "input stream: " << (void *)_inputStrm << endl ;
00533 strm << BESIndent::LMarg << "created input stream? " << _createdInputStrm << endl ;
00534 strm << BESIndent::LMarg << "timeout: " << _timeout << endl ;
00535 BESBaseApp::dump( strm ) ;
00536 BESIndent::UnIndent() ;
00537 }
00538
00539 int
00540 main( int argc, char **argv )
00541 {
00542 CmdApp app ;
00543 return app.main( argc, argv ) ;
00544 }
00545