CmdClient.cc

Go to the documentation of this file.
00001 // CmdClient.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,2005 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 "config.h"
00034 
00035 #include <iostream>
00036 #include <fstream>
00037 
00038 using std::cout;
00039 using std::endl;
00040 using std::cerr;
00041 using std::ofstream;
00042 using std::ios;
00043 
00044 #ifdef HAVE_LIBREADLINE
00045 #  if defined(HAVE_READLINE_READLINE_H)
00046 #    include <readline/readline.h>
00047 #  elif defined(HAVE_READLINE_H)
00048 #    include <readline.h>
00049 #  else                         /* !defined(HAVE_READLINE_H) */
00050 extern "C" {
00051     char *readline(const char *);
00052 }
00053 #  endif                        /* !defined(HAVE_READLINE_H) */
00054 char *cmdline = NULL;
00055 #else                           /* !defined(HAVE_READLINE_READLINE_H) */
00056   /* no readline */
00057 #endif                          /* HAVE_LIBREADLINE */
00058 
00059 #ifdef HAVE_READLINE_HISTORY
00060 #  if defined(HAVE_READLINE_HISTORY_H)
00061 #    include <readline/history.h>
00062 #  elif defined(HAVE_HISTORY_H)
00063 #    include <history.h>
00064 #  else                         /* !defined(HAVE_HISTORY_H) */
00065 extern "C" {
00066     int add_history(const char *);
00067     int write_history(const char *);
00068     int read_history(const char *);
00069 }
00070 #  endif                        /* defined(HAVE_READLINE_HISTORY_H) */
00071   /* no history */
00072 #endif                          /* HAVE_READLINE_HISTORY */
00073 #define SIZE_COMMUNICATION_BUFFER 4096*4096
00074 #include "CmdClient.h"
00075 #include "PPTClient.h"
00076 CmdClient::~CmdClient()
00077 {
00078     if (_strmCreated && _strm) {
00079         _strm->flush();
00080         delete _strm;
00081         _strm = 0;
00082     } else if (_strm) {
00083         _strm->flush();
00084     }
00085     if (_client) {
00086         delete _client;
00087         _client = 0;
00088     }
00089 }
00090 
00105 void
00106  CmdClient::startClient(const string & host, int portVal, int timeout)
00107 {
00108     _client = new PPTClient(host, portVal, timeout);
00109     _client->initConnection();
00110 }
00111 
00121 void CmdClient::startClient(const string & unixStr, int timeout)
00122 {
00123     _client = new PPTClient(unixStr, timeout);
00124     _client->initConnection();
00125 }
00126 
00136 void CmdClient::shutdownClient()
00137 {
00138     if( _client )
00139         _client->closeConnection();
00140 }
00141 
00157 void CmdClient::setOutput(ostream * strm, bool created)
00158 {
00159     if (_strmCreated && _strm) {
00160         _strm->flush();
00161         delete _strm;
00162     } else if (_strm) {
00163         _strm->flush();
00164     }
00165     _strm = strm;
00166     _strmCreated = created;
00167 }
00168 
00180 void CmdClient::executeClientCommand(const string & cmd)
00181 {
00182     string suppress = "suppress";
00183     if (cmd.compare(0, suppress.length(), suppress) == 0) {
00184         setOutput(NULL, false);
00185     } else {
00186         string output = "output to";
00187         if (cmd.compare(0, output.length(), output) == 0) {
00188             string subcmd = cmd.substr(output.length() + 1);
00189             string screen = "screen";
00190             if (subcmd.compare(0, screen.length(), screen) == 0) {
00191                 setOutput(&cout, false);
00192             } else {
00193                 // subcmd is the name of the file - the semicolon
00194                 string file = subcmd.substr(0, subcmd.length() - 1);
00195                 ofstream *fstrm = new ofstream(file.c_str(), ios::app);
00196                 if (!(*fstrm)) {
00197                     cerr << "Unable to set client output to file " << file
00198                         << endl;
00199                 } else {
00200                     setOutput(fstrm, true);
00201                 }
00202             }
00203         } else {
00204             cerr << "Improper client command " << cmd << endl;
00205         }
00206     }
00207 }
00208 
00223 void CmdClient::executeCommand(const string & cmd, int repeat )
00224 {
00225     string client = "client";
00226     if (cmd.compare(0, client.length(), client) == 0) {
00227         executeClientCommand(cmd.substr(client.length() + 1));
00228     } else {
00229         if( repeat < 1 ) repeat = 1 ;
00230         for( int i = 0; i < repeat; i++ )
00231         {
00232             _client->send(cmd);
00233             _client->receive(_strm);
00234             _strm->flush();
00235         }
00236     }
00237 }
00238 
00253 void CmdClient::executeCommands(const string & cmd_list, int repeat)
00254 {
00255     if( repeat < 1 ) repeat = 1 ;
00256     for( int i = 0; i < repeat; i++ )
00257     {
00258         std::string::size_type start = 0;
00259         std::string::size_type end = 0;
00260         while ((end = cmd_list.find(';', start)) != string::npos) {
00261             string cmd = cmd_list.substr(start, end - start + 1);
00262             executeCommand(cmd, 1);
00263             start = end + 1;
00264         }
00265     }
00266 }
00267 
00288 void CmdClient::executeCommands(ifstream & istrm, int repeat)
00289 {
00290     if( repeat < 1 ) repeat = 1 ;
00291     for( int i = 0; i < repeat; i++ )
00292     {
00293         istrm.clear( ) ;
00294         istrm.seekg( 0, ios::beg ) ;
00295         string cmd;
00296         bool done = false;
00297         while (!done) {
00298             char line[4096];
00299             line[0] = '\0';
00300             istrm.getline(line, 4096, '\n');
00301             string nextLine = line;
00302             if (nextLine == "") {
00303                 if (cmd != "") {
00304                     this->executeCommands(cmd, 1);
00305                 }
00306                 done = true;
00307             } else {
00308                 std::string::size_type i = nextLine.find_last_of(';');
00309                 if (i == string::npos) {
00310                     if (cmd == "") {
00311                         cmd = nextLine;
00312                     } else {
00313                         cmd += " " + nextLine;
00314                     }
00315                 } else {
00316                     string sub = nextLine.substr(0, i + 1);
00317                     if (cmd == "") {
00318                         cmd = sub;
00319                     } else {
00320                         cmd += " " + sub;
00321                     }
00322                     this->executeCommands(cmd, 1);
00323                     if (i == nextLine.length() || i == nextLine.length() - 1) {
00324                         cmd = "";
00325                     } else {
00326                         cmd = nextLine.substr(i + 1, nextLine.length());
00327                     }
00328                 }
00329             }
00330         }
00331     }
00332 }
00333 
00351 void CmdClient::interact()
00352 {
00353     cout << endl << endl
00354         << "Type 'exit' to exit the command line client and 'help' or '?' "
00355         << "to display the help screen" << endl << endl;
00356 
00357     bool done = false;
00358     while (!done) {
00359         string message = "";
00360         size_t len = this->readLine(message);
00361         if (len == -1 || message == "exit" || message == "exit;") {
00362             done = true;
00363         } else if (message == "help" || message == "help;"
00364                    || message == "?") {
00365             this->displayHelp();
00366         } else if (len != 0 && message != "") {
00367             if (message[message.length() - 1] != ';') {
00368                 cerr << "Commands must end with a semicolon" << endl;
00369             } else {
00370                 this->executeCommands(message, 1);
00371                 message = "";   // Needed? Added during debugging. jhrg 9/8/05
00372                 len = 0;
00373             }
00374         }
00375     }
00376 }
00377 
00378 size_t CmdClient::readLine(string & msg)
00379 {
00380     size_t len = 0;
00381     char *buf = (char *) NULL;
00382     buf =::readline("BESClient> ");
00383     if (buf && *buf) {
00384         len = strlen(buf);
00385 #ifdef HAVE_READLINE_HISTORY
00386         add_history(buf);
00387 #endif
00388         if (len > SIZE_COMMUNICATION_BUFFER) {
00389             cerr << __FILE__ << __LINE__
00390                 <<
00391                 ": incoming data buffer exceeds maximum capacity with lenght "
00392                 << len << endl;
00393             exit(1);
00394         } else {
00395             msg = buf;
00396         }
00397     } else {
00398         if (!buf) {
00399             // If a null buffer is returned then this means that EOF is
00400             // returned. This is different from the user just hitting enter,
00401             // which means a character buffer is returned, but is empty.
00402             
00403             // Problem: len is unsigned.
00404             len = -1;
00405         }
00406     }
00407     if (buf) {
00408         free(buf);
00409         buf = (char *) NULL;
00410     }
00411     return len;
00412 }
00413 
00414 void CmdClient::displayHelp()
00415 {
00416     cout << endl;
00417     cout << endl;
00418     cout << "BES Command Line Client Help" << endl;
00419     cout << endl;
00420     cout << "Client commands available:" << endl;
00421     cout <<
00422         "    exit                     - exit the command line interface" <<
00423         endl;
00424     cout << "    help                     - display this help screen" <<
00425         endl;
00426     cout <<
00427         "    client suppress;         - suppress output from the server" <<
00428         endl;
00429     cout <<
00430         "    client output to screen; - display server output to the screen"
00431         << endl;
00432     cout <<
00433         "    client output to <file>; - display server output to specified file"
00434         << endl;
00435     cout << endl;
00436     cout <<
00437         "Any commands beginning with 'client' must end with a semicolon" <<
00438         endl;
00439     cout << endl;
00440     cout << "To display the list of commands available from the server "
00441         << "please type the command 'show help;'" << endl;
00442     cout << endl;
00443     cout << endl;
00444 }
00445 
00446 bool CmdClient::isConnected()
00447 {
00448     if (_client)
00449         return _client->isConnected();
00450     return false;
00451 }
00452 
00453 void CmdClient::brokenPipe()
00454 {
00455     if (_client)
00456         _client->brokenPipe();
00457 }
00458 
00465 void CmdClient::dump(ostream & strm) const
00466 {
00467     strm << BESIndent::LMarg << "CmdClient::dump - ("
00468         << (void *) this << ")" << endl;
00469     BESIndent::Indent();
00470     if (_client) {
00471         strm << BESIndent::LMarg << "client:" << endl;
00472         BESIndent::Indent();
00473         _client->dump(strm);
00474         BESIndent::UnIndent();
00475     } else {
00476         strm << BESIndent::LMarg << "client: null" << endl;
00477     }
00478     strm << BESIndent::LMarg << "stream: " << (void *) _strm << endl;
00479     strm << BESIndent::LMarg << "stream created? " << _strmCreated << endl;
00480     BESIndent::UnIndent();
00481 }

Generated on Wed Jan 2 06:01:19 2008 for OPeNDAP Back End Server (BES) by  doxygen 1.5.4