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