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 <cstdlib>
00036 #include <iostream>
00037 #include <fstream>
00038 #include <map>
00039
00040 using std::cout;
00041 using std::endl;
00042 using std::cerr;
00043 using std::ofstream;
00044 using std::ios;
00045 using std::map;
00046
00047 #ifdef HAVE_LIBREADLINE
00048 # if defined(HAVE_READLINE_READLINE_H)
00049 # include <readline/readline.h>
00050 # elif defined(HAVE_READLINE_H)
00051 # include <readline.h>
00052 # else
00053 extern "C" {
00054 char *readline(const char *);
00055 }
00056 # endif
00057 char *cmdline = NULL;
00058 #else
00059
00060 #endif
00061
00062 #ifdef HAVE_READLINE_HISTORY
00063 # if defined(HAVE_READLINE_HISTORY_H)
00064 # include <readline/history.h>
00065 # elif defined(HAVE_HISTORY_H)
00066 # include <history.h>
00067 # else
00068 extern "C" {
00069 int add_history(const char *);
00070 int write_history(const char *);
00071 int read_history(const char *);
00072 }
00073 # endif
00074
00075 #endif
00076 #define SIZE_COMMUNICATION_BUFFER 4096*4096
00077 #include "CmdClient.h"
00078 #include "PPTClient.h"
00079 #include "BESDebug.h"
00080
00081 CmdClient::~CmdClient()
00082 {
00083 if (_strmCreated && _strm) {
00084 _strm->flush();
00085 delete _strm;
00086 _strm = 0;
00087 } else if (_strm) {
00088 _strm->flush();
00089 }
00090 if (_client) {
00091 delete _client;
00092 _client = 0;
00093 }
00094 }
00095
00110 void
00111 CmdClient::startClient(const string & host, int portVal, int timeout)
00112 {
00113 _client = new PPTClient(host, portVal, timeout);
00114 _client->initConnection();
00115 }
00116
00126 void
00127 CmdClient::startClient(const string & unixStr, int timeout)
00128 {
00129 _client = new PPTClient(unixStr, timeout);
00130 _client->initConnection();
00131 }
00132
00141 void
00142 CmdClient::shutdownClient()
00143 {
00144 if( _client )
00145 _client->closeConnection();
00146 }
00147
00164 void
00165 CmdClient::setOutput(ostream * strm, bool created)
00166 {
00167 if (_strmCreated && _strm) {
00168 _strm->flush();
00169 delete _strm;
00170 } else if (_strm) {
00171 _strm->flush();
00172 }
00173 _strm = strm;
00174 _strmCreated = created;
00175 }
00176
00187 void
00188 CmdClient::executeClientCommand(const string & cmd)
00189 {
00190 string suppress = "suppress";
00191 if (cmd.compare(0, suppress.length(), suppress) == 0) {
00192 setOutput(NULL, false);
00193 } else {
00194 string output = "output to";
00195 if (cmd.compare(0, output.length(), output) == 0) {
00196 string subcmd = cmd.substr(output.length() + 1);
00197 string screen = "screen";
00198 if (subcmd.compare(0, screen.length(), screen) == 0) {
00199 setOutput(&cout, false);
00200 } else {
00201
00202 string file = subcmd.substr(0, subcmd.length() - 1);
00203 ofstream *fstrm = new ofstream(file.c_str(), ios::app);
00204 if (!(*fstrm)) {
00205 if( fstrm ) delete fstrm ;
00206 cerr << "Unable to set client output to file " << file
00207 << endl;
00208 } else {
00209 setOutput(fstrm, true);
00210 }
00211 }
00212 } else {
00213 cerr << "Improper client command " << cmd << endl;
00214 }
00215 }
00216 }
00217
00232 void
00233 CmdClient::executeCommand(const string & cmd, int repeat )
00234 {
00235 string client = "client";
00236 if (cmd.compare(0, client.length(), client) == 0) {
00237 executeClientCommand(cmd.substr(client.length() + 1));
00238 } else {
00239 if( repeat < 1 ) repeat = 1 ;
00240 for( int i = 0; i < repeat; i++ )
00241 {
00242 BESDEBUG( "cmdln", "cmdclient sending " << cmd << endl )
00243 map<string,string> extensions ;
00244 _client->send(cmd, extensions);
00245
00246 BESDEBUG( "cmdln", "cmdclient receiving " << endl )
00247
00248 bool done = false ;
00249 while( !done )
00250 {
00251 done = _client->receive( extensions, _strm ) ;
00252 if( extensions["status"] == "error" )
00253 {
00254
00255
00256 _strm->flush() ;
00257 }
00258 }
00259 if( BESDebug::IsSet( "cmdln" ) )
00260 {
00261 BESDEBUG( "cmdln", "extensions:" << endl )
00262 map<string,string>::const_iterator i = extensions.begin() ;
00263 map<string,string>::const_iterator e = extensions.end() ;
00264 for( ; i != e; i++ )
00265 {
00266 BESDEBUG( "cmdln", " " << (*i).first << " = " << (*i).second << endl )
00267 }
00268 BESDEBUG( "cmdln", "cmdclient done receiving " << endl )
00269 }
00270
00271 _strm->flush();
00272 }
00273 }
00274 }
00275
00290 void
00291 CmdClient::executeCommands(const string & cmd_list, int repeat)
00292 {
00293 if( repeat < 1 ) repeat = 1 ;
00294 for( int i = 0; i < repeat; i++ )
00295 {
00296 std::string::size_type start = 0;
00297 std::string::size_type end = 0;
00298 while ((end = cmd_list.find(';', start)) != string::npos) {
00299 string cmd = cmd_list.substr(start, end - start + 1);
00300 executeCommand(cmd, 1);
00301 start = end + 1;
00302 }
00303 }
00304 }
00305
00327 void
00328 CmdClient::executeCommands(ifstream & istrm, int repeat)
00329 {
00330 if( repeat < 1 ) repeat = 1 ;
00331 for( int i = 0; i < repeat; i++ )
00332 {
00333 istrm.clear( ) ;
00334 istrm.seekg( 0, ios::beg ) ;
00335 string cmd;
00336 bool done = false;
00337 while (!done) {
00338 char line[4096];
00339 line[0] = '\0';
00340 istrm.getline(line, 4096, '\n');
00341 string nextLine = line;
00342 if (nextLine == "") {
00343 if (cmd != "") {
00344 this->executeCommands(cmd, 1);
00345 }
00346 done = true;
00347 } else {
00348 std::string::size_type i = nextLine.find_last_of(';');
00349 if (i == string::npos) {
00350 if (cmd == "") {
00351 cmd = nextLine;
00352 } else {
00353 cmd += " " + nextLine;
00354 }
00355 } else {
00356 string sub = nextLine.substr(0, i + 1);
00357 if (cmd == "") {
00358 cmd = sub;
00359 } else {
00360 cmd += " " + sub;
00361 }
00362 this->executeCommands(cmd, 1);
00363 if (i == nextLine.length() || i == nextLine.length() - 1) {
00364 cmd = "";
00365 } else {
00366 cmd = nextLine.substr(i + 1, nextLine.length());
00367 }
00368 }
00369 }
00370 }
00371 }
00372 }
00373
00389 void
00390 CmdClient::interact()
00391 {
00392 cout << endl << endl
00393 << "Type 'exit' to exit the command line client and 'help' or '?' "
00394 << "to display the help screen" << endl << endl;
00395
00396 bool done = false;
00397 while (!done) {
00398 string message = "";
00399 size_t len = this->readLine(message);
00400 if (len == -1 || message == "exit" || message == "exit;") {
00401 done = true;
00402 } else if (message == "help" || message == "help;"
00403 || message == "?") {
00404 this->displayHelp();
00405 } else if (len != 0 && message != "") {
00406 if (message[message.length() - 1] != ';') {
00407 cerr << "Commands must end with a semicolon" << endl;
00408 } else {
00409 this->executeCommands(message, 1);
00410 }
00411 }
00412 }
00413 }
00414
00420 size_t
00421 CmdClient::readLine(string & msg)
00422 {
00423 size_t len = 0;
00424 char *buf = (char *) NULL;
00425 buf =::readline("BESClient> ");
00426 if (buf && *buf) {
00427 len = strlen(buf);
00428 #ifdef HAVE_READLINE_HISTORY
00429 add_history(buf);
00430 #endif
00431 if (len > SIZE_COMMUNICATION_BUFFER) {
00432 cerr << __FILE__ << __LINE__
00433 <<
00434 ": incoming data buffer exceeds maximum capacity with lenght "
00435 << len << endl;
00436 exit(1);
00437 } else {
00438 msg = buf;
00439 }
00440 } else {
00441 if (!buf) {
00442
00443
00444
00445
00446
00447 len = -1;
00448 }
00449 }
00450 if (buf) {
00451 free(buf);
00452 buf = (char *) NULL;
00453 }
00454 return len;
00455 }
00456
00459 void
00460 CmdClient::displayHelp()
00461 {
00462 cout << endl;
00463 cout << endl;
00464 cout << "BES Command Line Client Help" << endl;
00465 cout << endl;
00466 cout << "Client commands available:" << endl;
00467 cout <<
00468 " exit - exit the command line interface" <<
00469 endl;
00470 cout << " help - display this help screen" <<
00471 endl;
00472 cout <<
00473 " client suppress; - suppress output from the server" <<
00474 endl;
00475 cout <<
00476 " client output to screen; - display server output to the screen"
00477 << endl;
00478 cout <<
00479 " client output to <file>; - display server output to specified file"
00480 << endl;
00481 cout << endl;
00482 cout <<
00483 "Any commands beginning with 'client' must end with a semicolon" <<
00484 endl;
00485 cout << endl;
00486 cout << "To display the list of commands available from the server "
00487 << "please type the command 'show help;'" << endl;
00488 cout << endl;
00489 cout << endl;
00490 }
00491
00496 bool
00497 CmdClient::isConnected()
00498 {
00499 if (_client)
00500 return _client->isConnected();
00501 return false;
00502 }
00503
00506 void
00507 CmdClient::brokenPipe()
00508 {
00509 if (_client)
00510 _client->brokenPipe();
00511 }
00512
00519 void
00520 CmdClient::dump(ostream & strm) const
00521 {
00522 strm << BESIndent::LMarg << "CmdClient::dump - ("
00523 << (void *) this << ")" << endl;
00524 BESIndent::Indent();
00525 if (_client) {
00526 strm << BESIndent::LMarg << "client:" << endl;
00527 BESIndent::Indent();
00528 _client->dump(strm);
00529 BESIndent::UnIndent();
00530 } else {
00531 strm << BESIndent::LMarg << "client: null" << endl;
00532 }
00533 strm << BESIndent::LMarg << "stream: " << (void *) _strm << endl;
00534 strm << BESIndent::LMarg << "stream created? " << _strmCreated << endl;
00535 BESIndent::UnIndent();
00536 }