chat.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Kamil Dudka <xdudka00@stud.fit.vutbr.cz>
00003  *
00004  * This file is part of rob08
00005  *
00006  * rob08 is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * any later version.
00010  *
00011  * rob08 is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with rob08.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #include "config.h"
00021 
00022 #include "robIO.h"
00023 #include "term.h"
00024 
00025 #ifndef BUILDING_DOX
00026 #   include <errno.h>
00027 #   include <readline/readline.h>
00028 #   include <readline/history.h>
00029 #   include <signal.h>
00030 #   include <sstream>
00031 #   include <stdlib.h>
00032 #   include <string>
00033 #   include <strings.h>
00034 #endif
00035 
00036 using namespace StreamDecorator;
00037 using std::string;
00038 
00040 static const char *stty = "stty";
00041 
00043 static const char *sttyInitString = "5:4:800004bf:a30:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0";
00044 
00046 static const int dtPingTimeout = 1000;
00047 
00049 static const int dtCharTimeout = 100;
00050 
00052 static const char *histFile = ".rob08_terminal_history";
00053 
00058 void printUsage(string path) {
00059     std::cout << "Usage: " << path << " PTY_DEVICE" << std::endl;
00060 }
00061 
00063 void termWrite(IWriter *writer, const string &data) {
00064     std::cerr
00065         << Color(C_YELLOW) << "send: " << Color(C_NO_COLOR)
00066         << data << std::flush;
00067     writer->writeText(data);
00068     std::cerr << std::endl;
00069 }
00070 
00072 bool termRead(ICharReader *reader) {
00073     if (!reader->hasInput(dtPingTimeout))
00074         return false;
00075 
00076     std::cerr << Color(C_LIGHT_BLUE) << "recv: " << Color(C_NO_COLOR) << std::flush;
00077     char c;
00078     while (reader->hasInput(dtCharTimeout) && reader->getChar(c))
00079         std::cout << c << std::flush;
00080     std::cerr << std::endl;
00081     return true;
00082 }
00083 
00084 int main(int argc, char *argv[]) {
00085 #if CONSOLE_COLOR_OUTPUT
00086     Color::enable(true);
00087 #endif
00088     if (argc != 2) {
00089         // invalid count of arguments
00090         if (argc > 0)
00091             printUsage(argv[0]);
00092         return -1;
00093     }
00094     std::string fileName(argv[1]);
00095     if (fileName == string("--help")) {
00096         // --help
00097         printUsage(argv[0]);
00098         return 0;
00099     }
00100 
00101     // open terminal
00102     ITerm *term = TermFactory::createTerm(fileName);
00103     if (!term)
00104         return -1;
00105 
00106     // run stty to initialize PTY slave
00107     string initCmd(stty);
00108     initCmd += " -F ";
00109     initCmd += fileName;
00110     initCmd += " ";
00111     initCmd += sttyInitString;
00112     int rc = system(initCmd.c_str());
00113     if (rc)
00114         std::cerr << Error(E_ERROR, fileName, "stty command failed: ") << "system(" << initCmd << ") = " << rc << std::endl;
00115 
00116     // determine terminal mode
00117     bool interactiveMode = ttyname(STDIN_FILENO);
00118     if (interactiveMode)
00119         std::cerr << Error(E_NOTE, "terminal", "working in interactive mode") << std::endl;
00120     else
00121         std::cerr << Error(E_NOTE, "terminal", "working in batch mode") << std::endl;
00122 
00123     if (interactiveMode) {
00124         // set signal handler
00125         struct sigaction sa;
00126         bzero(&sa, sizeof(sa));
00127         sa.sa_handler = SIG_IGN;
00128         if (0!= sigaction(SIGINT, &sa, NULL))
00129             std::cerr << Error(E_WARNING, argv[0], "can't set SIGINT signal handler to SIG_IGN") << std::endl;
00130     }
00131 
00132     // check connection (FIXME: not tested)
00133     if (term->hasInput(0)) {
00134         std::cerr << Error(E_WARNING, fileName, "reading data from input:") << std::flush;
00135         char c;
00136         while (term->hasInput(0) && term->getChar(c))
00137             std::cout << c << std::flush;
00138         std::cerr << std::endl;
00139     }
00140 
00141     // ping TriloBot
00142     termWrite(term, "!1GY1");
00143     if (!termRead(term))
00144         std::cerr << Error(E_ERROR, fileName, "no response, TriloBot seems to be dead") << std::endl;
00145     else
00146         std::cerr << std::endl;
00147 
00148     if (interactiveMode) {
00149         // interactive mode
00150         read_history(histFile);
00151         std::ostringstream tmp;
00152         tmp << Color(C_LIGHT_GREEN) << "TriloBot" << Color(C_NO_COLOR) << " >>> " << std::flush;
00153         string prompt(tmp.str());
00154         const char *line;
00155         while ((line = readline(prompt.c_str()))) {
00156             if (!*line)
00157                 continue;
00158             add_history(line);
00159             termWrite(term, line);
00160             termRead(term);
00161             std::cout << std::endl;
00162         }
00163         std::cout << std::endl;
00164         if (write_history(histFile))
00165             std::cerr << Error(E_WARNING, histFile, "unable to save history, errno = ") << errno << std::endl;
00166         clear_history();
00167     } else {
00168         // batch mode
00169         string line;
00170         while (getline(std::cin, line)) {
00171             termWrite(term, line);
00172             termRead(term);
00173         }
00174     }
00175 
00176     // check for lexical errors
00177     bool bErr = false;
00178     if (term -> hasError()) {
00179         bErr = true;
00180         std::cerr << Error(E_NOTE, fileName, "terminal error(s) detected") << std::endl;
00181     }
00182 
00183     // destroy objects in reverse order
00184     delete term;
00185 
00186     // final application exit code
00187     return bErr ? -1 : 0;
00188 }
00189 

Generated on Fri Jul 10 22:42:01 2009 for rob08 by  doxygen 1.5.4