📄 expresp.c
字号:
/*+------------------------------------------------------------------------- expresp.c - HDB expect/respond per SCO Devices file wht@n4hgf.Mt-Park.GA.US Meaning of some of the escape characters: \p - pause (approximately 1/4-1/2 second delay) \d - delay (2 seconds) \D - phone number/token \T - phone number with Dialcodes and character translation \N - null byte \K - insert a BREAK \E - turn on echo checking (for slow devices) \e - turn off echo checking \r - carriage return \c - no new-line \n - send new-line \s - send space \nnn - send octal number \\ - send backslash \m### - sleep ### (decimal) milliseconds (non-standard) Speed - Hayes-specific "CONNECT" handler Defined functions: execute_expresp(expresp_script) expect(str) pcmd_expresp(param) respond(str)--------------------------------------------------------------------------*//*+:EDITS:*//*:09-10-1992-13:59-wht@n4hgf-ECU release 3.20 *//*:09-04-1992-19:07-wht@n4hgf-new msec delay syntax + harden *//*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA *//*:12-16-1991-15:25-wht@n4hgf-allow for backslash in expect and respond *//*:10-09-1991-20:21-wht@n4hgf-bad llookfor echo argument *//*:08-01-1991-05:00-wht@n4hgf-\n sent CR not NL *//*:08-01-1991-04:31-wht@n4hgf-nap min of hzmsec if \m *//*:08-01-1991-04:22-wht@n4hgf-detect NULL expect string *//*:07-25-1991-12:57-wht@n4hgf-ECU release 3.10 *//*:07-17-1991-07:04-wht@n4hgf-avoid SCO UNIX nap bug *//*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */#include "ecu.h"#include "ecuerror.h"#include "esd.h"#include "var.h"#include "proc.h"#define MAX_FIELDS 50 /* max fields in a chat script */#define MAX_EXPRESP 511 /* max length of a chat script */#define MAX_EXPECT 63 /* max length of expect string */#define DEFAULT_TIMEOUT_MSECS (45*1000L)#define ERDEBUG(verb,str,arg) if(expresp_verbosity >= verb) \ pprintf(str,arg)long atol();char *strip_phone_num();char *dialcodes_translate();extern int proctrace;int expresp_verbosity = 0;ulong expect_timeout_msecs = DEFAULT_TIMEOUT_MSECS;int expresp_echo_check = 0;char last_Speed_result[32];/*+------------------------------------------------------------------------- expect(str) - expect (read) string from remotereturn code on failure, 0 on success--------------------------------------------------------------------------*/intexpect(str)char *str;{ int erc; int itmp; char op; char s4[4]; char parsebuf[MAX_EXPECT + 1]; int remaining = MAX_EXPECT; long atol(); register char *cptr; register char *parsed = parsebuf; int old_ttymode = get_ttymode(); if(!str) { ERDEBUG(2,"expect string NULL\n",0); return(eExpectRespondFail); } if(old_ttymode != 2) ttymode(2); /* * ~?[] */ if((*str == '~') && *(str + 1) && (*(str + 2) == '[')) { op = *(str + 1); str += 3; switch(op) { case 'm': /* msec expect timeout */ case 't': /* sec expect timeout */ expect_timeout_msecs = atol(str); if(op == 't') expect_timeout_msecs *= 1000L; ERDEBUG(2,"expect timeout = %lu msec\n",expect_timeout_msecs); break; default: ERDEBUG(0,"\nexpect: invalid subop: ~%c[]\n",op); break; } if(cptr = strchr(str,']')) str = cptr + 1; else { ERDEBUG(0,"\nexpect: missing ] after ~[%c\n",op); erc = eExpectRespondFail; goto DID_NOT_GET_EXPECTED; } } ERDEBUG(2,"expect: <<%s>>\n",str); if(!strlen(str) || !strcmp(str,"\"\"")) goto GOT_EXPECTED; if(!strcmp(str,"Speed")) { LRWT lr; long ms_start; long ms_now; struct timeb now_timeb; ftime(&now_timeb); ms_start = (now_timeb.time * 1000) + now_timeb.millitm; do { last_Speed_result[0] = 0; lr.to1 = 90 * 100L; lr.to2 = 120L; /* allow interrupts + cooked read */ lr.raw_flag = 0x80; lr.buffer = last_Speed_result; lr.bufsize = sizeof(last_Speed_result); lr.delim = "\n"; lr.echo_flag = !!expresp_verbosity; lgets_timeout(&lr); ftime(&now_timeb); ms_now = (now_timeb.time * 1000) + now_timeb.millitm; } while(!sigint && !lr.count && ((ms_now - ms_start) < 90*1000L)); if(sigint || strncmp(lr.buffer,"CONNECT",7)) goto DID_NOT_GET_EXPECTED; else goto GOT_EXPECTED; } cptr = str; while(remaining && *cptr) { if(*cptr == '\\') { if(!*(++cptr)) /* if no character after escape, ... */ { ERDEBUG(2," error: str ended with '\\'\n",0); goto DID_NOT_GET_EXPECTED; } if(isdigit(*cptr)) /* handle \ooo */ { strncpy(s4,cptr,3); s4[3] = 0; sscanf(s4,"%o",&itmp); cptr += strspn(s4,"01234567"); *parsed++ = (char)itmp; remaining--; continue; } switch(*cptr) { case 'n': *parsed++ = 0x0A; remaining--; break; case 'r': *parsed++ = 0x0D; remaining--; break; case '\\': *parsed++ = '\\'; remaining--; break; case '~': *parsed++ = '~'; remaining--; break; case 's': *parsed++ = ' '; remaining--; break; default: ERDEBUG(2," meaningless here: \\%c\n",*cptr); break; } cptr++; } else { *parsed++ = *cptr++; remaining--; } } *parsed = 0; if(!remaining) ERDEBUG(1," expect string too long\n",0); if(expresp_verbosity >= 3) hex_dump(parsebuf,strlen(parsebuf),"expecting",1); if(llookfor(parsebuf,expect_timeout_msecs,!!expresp_verbosity)) {GOT_EXPECTED: ERDEBUG(2,"[EXPECT SUCCEEDED]\n",0); erc = 0; goto RESTORE_TTYMODE_AND_RETURN_ERC; }DID_NOT_GET_EXPECTED: ERDEBUG(2,"[EXPECT FAILED%s]\n",(sigint) ? " (interrupted)" : ""); if(sigint) { sigint = 0; erc = eCONINT; } else erc = eExpectRespondFail; goto RESTORE_TTYMODE_AND_RETURN_ERC;RESTORE_TTYMODE_AND_RETURN_ERC: if(old_ttymode != 2) ttymode(old_ttymode); return(erc);} /* end of expect *//*+------------------------------------------------------------------------- respond(str) - send to remotewe enable SIGINT processing in here and return if 'sigint'detected, but here, unlike many other places, we do *not* resetsigint (since we do not really "handle" it)--------------------------------------------------------------------------*/voidrespond(str)register char *str;{ int itmp; long nap_msec; char s4[4]; char *cptr; char *phnum; char op; int send_no_cr = 0; int old_ttymode = get_ttymode(); if(sigint) return; ttymode(2); /* enable SIGINT/sigint */ ERDEBUG(2,"respond: <<%s>>\n",str); while(*str) { if(*str == '\\') { if(isdigit(*++str)) /* handle \ooo */ { strncpy(s4,str,3); s4[3] = 0; sscanf(s4,"%o",&itmp); str += strspn(s4,"01234567") - 1; /* -1 because str++ later */ lputc((char)itmp); } else switch(*str) { case 'p': /* pause (approximately 1/4-1/2 second delay) */ ldraino(0); /* wait for output to drain */ if(Nap(400L) < 0) goto RETURN; break; case 'M': /* CLOCAL on */ case 'm': /* CLOCAL off */ itmp = (*str == 'M'); lCLOCAL(itmp); ERDEBUG(2,"CLOCAL set %s\n",(itmp) ? "ON" : "OFF"); break; case 'd': /* delay (2 seconds) */ ldraino(0); /* wait for output to drain */ if(Nap(2000L) < 0) goto RETURN; break; case 'D': /* phone number/token */ cptr = strip_phone_num(shm->Ltelno); if(expresp_echo_check) lputs_paced(40,cptr); else lputs(cptr); break; case 'T': /* phnum with Dialcodes and char translation */ phnum = strip_phone_num(shm->Ltelno); cptr = dialcodes_translate(&phnum); if(expresp_echo_check) { lputs_paced(40,cptr); lputs_paced(40,phnum); } else { lputs(cptr); lputs(phnum); } break; case 'N': /* null byte */ lputc(0); break; case 'K': /* insert a BREAK */ lbreak(); break; case 'E': /* turn on echo checking (for slow devices) */ expresp_echo_check = 1; break; case 'e': /* turn off echo checking */ expresp_echo_check = 0; break; case 'r': /* carriage return */ lputc(0x0D); break; case 'c': /* no new-line */ send_no_cr = 1; break; case 'n': /* send new-line */ lputc(0x0A); break; case '\\': /* send backslash */ lputc('\\'); break; case '~': /* send tilde */ lputc('~'); break; } } else if((*str == '~') && *(str + 1) && (*(str + 2) == '[')) { op = *(str + 1); str += 3; switch(op) { case 'n': /* nap for milliseconds */ nap_msec = atol(str); if(nap_msec < 0L) nap_msec = 0; if(nap_msec >= 500) ERDEBUG(2,"nap for %lu msec\n",nap_msec); Nap(nap_msec); break; default: ERDEBUG(0,"\nrespond: invalid subop: ~%c[]\n",op); break; } if(cptr = strchr(str,']')) str = cptr + 1; else { ERDEBUG(0,"\nrespond: missing ] after ~[%c\n",op); goto RETURN; } } else lputc(*str); if(expresp_echo_check) { ldraino(1); /* wait for output to drain, then flush input */ Nap(40L); /* fake it */ } str++; } if(!send_no_cr) lputc(0x0D);RETURN: ttymode(old_ttymode);} /* end of respond *//*+------------------------------------------------------------------------- execute_expresp(expresp_script)return 0 on success, else error code--------------------------------------------------------------------------*/intexecute_expresp(expresp_script)char *expresp_script;{ char *fields[MAX_FIELDS + 1]; int ifields; int nfields; int erc; char expresp_copy[MAX_EXPRESP + 1]; char *expect_this; char *send_on_fail;#define EXPECT_STATE (!(ifields & 1)) /* even numbered fields are expect */ expresp_echo_check = 0; last_Speed_result[0] = 0; ERDEBUG(2,"[EXPECT/RESPOND INITIAL TIMEOUT %ld MSEC]\n", expect_timeout_msecs); strncpy(expresp_copy,expresp_script,sizeof(expresp_copy)); build_arg_array(expresp_copy,fields,MAX_FIELDS,&nfields); if(!nfields) /* if no script, assume success */ { ERDEBUG(2,"[EMPTY SCRIPT - EXPECT/RESPOND SUCCEEDED]\n",0); return(0); } for(ifields = 0; ifields < nfields; ifields++) { if(sigint) break; if(EXPECT_STATE) { expect_this = fields[ifields]; while(1) /* until break or return(error) */ { if(send_on_fail = strchr(expect_this,'-')) *send_on_fail++ = 0; if(!(erc = expect(expect_this))) break; if((erc != eExpectRespondFail) || !send_on_fail) { ERDEBUG(2,"[EXPECT/RESPOND FAILED]\n",0); return(eExpectRespondFail); } if(expect_this = strchr(send_on_fail,'-')) *expect_this++ = 0; if(sigint) break; respond(send_on_fail); } } else respond(fields[ifields]); } if(sigint) { sigint = 0; ERDEBUG(2,"[CONSOLE INTERRUPT]\n",0); return(eCONINT); } ERDEBUG(2,"[EXPECT/RESPOND SUCCEEDED]\n",0); return(0);} /* end of execute_expresp *//*+------------------------------------------------------------------------- pcmd_expresp(param)expresp [-v[v...]] <exp-resp-str> [<timeout_msecs>]--------------------------------------------------------------------------*/intpcmd_expresp(param)ESD *param;{ int erc; int itmp; char *cptr; ESD *tesd; char switches[8]; if((tesd = esdalloc(MAX_EXPRESP + 1)) == (ESD *)0) return(eNoMemory); get_switches(param,switches,sizeof(switches)); if(erc = gstr(param,tesd,0)) { esdfree(tesd); return(erc); } expect_timeout_msecs = DEFAULT_TIMEOUT_MSECS; expresp_verbosity = (!!strchr(switches,'v')) || proctrace; if(expresp_verbosity) { cptr = switches; itmp = 0; while(*cptr) itmp += (*cptr++ == 'v'); if(itmp > 1) expresp_verbosity = itmp; } if(erc = gint(param,&expect_timeout_msecs)) { /* if something there non-integer */ if(!end_of_cmd(param)) { erc = eSyntaxError; goto RETURN; } } erc = execute_expresp(tesd->pb);RETURN: esdfree(tesd); iv[0] = !!erc; if(proctrace) pprintf("$i00 = %7ld (0x%08lx,0%lo)\n",iv[0],iv[0],iv[0]); if(erc == eExpectRespondFail) erc = 0; return(erc);} /* end of pcmd_expresp *//* vi: set tabstop=4 shiftwidth=4: *//* end of expresp.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -