/****************************************************************************** * to emulate the serial input and output of an 8051 controller * * main.cc - the main stuff * ******************************************************************************/ #include "ddconfig.h" #include #include #include #include #include #include #include #include #include #if defined(HAVE_GETOPT_H) # include #endif #include "fileio.hh" #include "frontend.hh" #include "posix_signal.hh" Viewer *view; FileIO *fobj; struct auto_answer_t { char *pattern; int p_len; char *answer; int a_len; }; enum { aa_len= 100 }; struct auto_answer_t aa[aa_len]; int max_pattern_len= 0; int aa_p_num= 0; int aa_a_num= 0; char *aa_queue; int aa_q_len= 0; void init_aa() { int i; for (i= 0; i < aa_len; i++) { aa[i].pattern= 0; aa[i].p_len= 0; aa[i].answer= 0; aa[i].a_len= 0; } } void start_aa() { if (max_pattern_len > 0) { aa_queue= (char*)malloc(max_pattern_len); aa_queue[0]= 0; } else aa_queue= NULL; } void new_aa_pattern(char *s, int len) { if (aa_p_num < aa_len) { aa[aa_p_num].pattern= s; aa[aa_p_num].p_len= len; aa_p_num++; if (len > max_pattern_len) max_pattern_len= len; } } void new_aa_answer(char *s, int len) { if (aa_a_num < aa_len) { aa[aa_a_num].answer= s; aa[aa_a_num].a_len= len; aa_a_num++; } } // 0: no match // 1: partial match // 2: full match int check_pattern(char *p, int pl, char *q, int ql) { int m= pl, i; if (ql < m) m= ql; if (m == 0) return 0; for (i= 0; i= max_pattern_len) shift_queue(); aa_queue[aa_q_len++]= c; // search for (i=p= 0; i < aa_p_num; i++) { int m= check_pattern(aa[i].pattern, aa[i].p_len, aa_queue, aa_q_len); if (m == 2) { // found a full match int j; for (j=0; j < aa[i].a_len; j++) { fobj->SendByte(aa[i].answer[j]); } shift_queue(); return; } if (m == 1) p++; } if (!p) shift_queue(); } // globals int doloop = 1; // the signal handler void HandleSig(int info) { doloop = 0; } int hex2bin(char h) { int cv= 0; if ((h >= '0') && (h <= '9')) cv= h-'0'; else if ((h >= 'A') && (h <= 'F')) cv= 10 + h-'A'; else if ((h >= 'a') && (h <= 'f')) cv= 10 + h-'a'; return cv; } /* Convert C escapes into bin chars */ char * unesc_cstr(char *s, int *len) { char *d= (char*)malloc(strlen(s)); int i, j; d[j= 0]= 0; for (i= 0; s[i]!=0; i++) { if (s[i]=='\\') { if (s[++i]==0) break; switch (s[i]) { case 'a': d[j++]= '\a'; d[j]= 0; break; case 'b': d[j++]= '\b'; d[j]= 0; break; case 'e': d[j++]= 27; d[j]= 0; break; case 'f': d[j++]= '\f'; d[j]= 0; break; case 'n': d[j++]= '\n'; d[j]= 0; break; case 'r': d[j++]= '\r'; d[j]= 0; break; case 't': d[j++]= '\t'; d[j]= 0; break; case 'v': d[j++]= '\v'; d[j]= 0; break; case '\\': d[j++]= '\\'; d[j]= 0; break; case '\'': d[j++]= '\''; d[j]= 0; break; case '\"': d[j++]= '\"'; d[j]= 0; break; case '?': d[j++]= '?'; d[j]= 0; break; case 'x': { if (s[++i]==0) break; int n= 0, l= strspn(&s[i], "0123456789abcdefABCDEF"), v= 0, cv; do { cv= hex2bin(s[i]); v= (v*16) + cv; if (s[++i]==0) break; } while (++n < l); d[j++]= v&0xff; d[j]= 0; i--; break; } case 'u': { if (s[++i]==0) break; int n= 0, l= 4, v= 0, cv; do { cv= hex2bin(s[i]); v= (v*16) + cv; if (s[++i]==0) break; } while (++n < l); d[j++]= v&0xff; d[j]= 0; i--; break; } case 'U': { if (s[++i]==0) break; int n= 0, l= 8, v= 0, cv; do { cv= hex2bin(s[i]); v= (v*16) + cv; if (s[++i]==0) break; } while (++n < l); d[j++]= v&0xff; d[j]= 0; i--; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int n= 0, l= strspn(&s[i], "01234567"), v= 0; if (l>3) l= 3; do { v= (v*8) + (s[i]-'0'); if (s[++i]==0) break; } while (++n < l); d[j++]= v&0xff; d[j]= 0; i--; break; } default: d[j++]= s[i]; d[j]= 0; break; } if (s[i]==0) break; } else { d[j++]= s[i]; d[j]= 0; } } if (len) *len= j; return d; } // usage void PrintUsage(char *progname) { std::cout << "Usage: " << progname << " [-i ] [-o ] [-hIO]\n"; std::cout << "-i \t is the pipe to the controllers' serial input\n"; std::cout << "-o \t is the pipe to the controllers' serial output\n"; std::cout << "-I \t\thexa filter on input\n"; std::cout << "-O \t\thexa filter on output\n"; std::cout << "-L n\t\tSet line length of hex dump in output panel (def=8)\n"; std::cout << "-a string\tPattern for autoanswer\n"; std::cout << "-A string\tAnswer for autoanswer\n"; std::cout << "-h\t\tshow the help\n"; std::cout << "\nTim Hurman - t.hurman@virgin.net\n"; exit(0); } // the main function int main(int argc, char **argv) { char *string = new char[MAX_SIZ]; extern char *optarg; int errflg=0; int c, l= 8; enum filter_t fi= flt_none, fo= flt_none; const char *infile = DEF_INFILE; const char *outfile = DEF_OUTFILE; // sort out any command line params while ((c = getopt(argc, argv, "i:o:hOIL:a:A:")) != EOF) switch(c) { case 'i': infile = optarg; break; case 'o': outfile = optarg; break; case 'I': fi= flt_hex; break; case 'O': fo= flt_hex; break; case 'L': l= strtol(optarg, 0, 0); break; case 'h': errflg++; break; case 'a': { int l; char *s= unesc_cstr(optarg, &l); new_aa_pattern(s, l); break; } case 'A': { int l; char *s= unesc_cstr(optarg, &l); new_aa_answer(s, l); break; } default: std::cerr << "Invalid or unknown switch\n"; errflg++; break; } // was there a problem if(errflg) PrintUsage(argv[0]); // the main objects needed view = new Viewer(); fobj = new FileIO(infile, outfile); SigHandler *sig = new SigHandler(); view->iflt_mode(fi); view->oflt_mode(fo); view->set_length(l); // add a signal handler for ^C sig->SetSignal(SIGINT, HandleSig); start_aa(); // set the timeout for waiting for a char fd_set s; while(doloop) { int ret, i; FD_ZERO(&s); FD_SET(fileno(stdin), &s); FD_SET(fobj->infile_id(), &s); i= select(FD_SETSIZE, &s, NULL, NULL, NULL); if (i >= 0) { if (FD_ISSET(fileno(stdin), &s)) { ret= view->GetChInWin(&string[0]); if (ret > 0) { fobj->SendByte(string[0]); } else if (ret < 0) break; } if (FD_ISSET(fobj->infile_id(), &s)) { if (fobj->RecvByte(string) > 0) { aa_proc(string[0]); view->AddChOutWin(string[0]); } } } //usleep(5000); } delete fobj; delete view; delete sig; delete string; return(0); }