00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00090 if (argc > 0)
00091 printUsage(argv[0]);
00092 return -1;
00093 }
00094 std::string fileName(argv[1]);
00095 if (fileName == string("--help")) {
00096
00097 printUsage(argv[0]);
00098 return 0;
00099 }
00100
00101
00102 ITerm *term = TermFactory::createTerm(fileName);
00103 if (!term)
00104 return -1;
00105
00106
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
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
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
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
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
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
00169 string line;
00170 while (getline(std::cin, line)) {
00171 termWrite(term, line);
00172 termRead(term);
00173 }
00174 }
00175
00176
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
00184 delete term;
00185
00186
00187 return bErr ? -1 : 0;
00188 }
00189