home *** CD-ROM | disk | FTP | other *** search
- #import "Escaper.h"
- #import "Term.h"
- #import "Modem.h"
- #import "Source.h"
- #import "StringResponder.h"
- #import "Fdset.h"
- #import <stdio.h>
- #import <ctype.h>
- #import <libc.h>
-
- #define MAXARGS 10
- #define stripNL(temp) if (temp[strlen(temp)-1] == '\n') temp[strlen(temp)-1] = 0;
-
- struct scriptCommand {
- char *cmd;
- enum escapeFunction func;
- };
-
- static struct scriptCommand decode[] =
- {
- {"nop",nop},
- {"stop",stop},
- {"protocol", protocol},
- {"parity",parity},
- {"send",sendfile},
- {"receive",receivefile},
- {"capture",capture},
- {"hangup",hangup},
- {"baudrate",baudrate},
- {"echo",echo},
- {"say",say},
- {"expect",expect},
- {"dial",dial},
- {"readscript",readscript}
- };
-
- #define NUL '\0'
- void breakIntoWords(char *line, char *words[])
- {
- char *p = line;
- int i;
-
- for(i=0; *p; i++) {
- while( *p && isspace(*p))
- p++;
- if (*p == NUL) break;
- words[i]=p;
- while( *p && !isspace(*p))
- p++;
- if (*p)
- *p++ = NUL;
- }
- words[i]=NULL;
- }
-
- int member(int ch, char * set)
- {
- return(strchr(set,ch) != 0);
- }
-
- @implementation Escaper
-
- + newEscaperWithTerm:(id)t andModem:(id)m
- {
- int i;
- self = [super new];
- term = t;
- modem = m;
- for (i=0; i<128; i++) keymap[i]=nop;
- keymap['b']=baudrate;
- keymap['d']=dial;
- keymap[CTRL('d')]=stop;
- keymap['p']=protocol;
- keymap[CTRL('p')]=parity;
- keymap['s']=sendfile;
- keymap['r']=receivefile;
- keymap['c']=capture;
- keymap['h']=hangup;
- keymap['e']=readscript; // for (e)xecute script file
- return self;
- }
-
- - readScript:(char *)file
- {
- FILE *fin;
- char line[200], *args[MAXARGS];
- int i;
- id source;
-
- fin = fopen(file,"r");
- if (fin==NULL) {
- sprintf(line,"couldn't open script file %s\n",file);
- [term putString:line];
- return nil;
- }
- while (fgets(line,sizeof(line),fin)) {
- breakIntoWords(line,args);
- if (args[0]==NULL || *args[0]=='%') continue; // % is for comments
- for(i=0; i<sizeof(decode)/sizeof(decode[0]); i++) {
- if (strcmp(args[0],decode[i].cmd) == 0) { // then we found a command
- source = [Source newStrings:args+1];
- [self doFunction:decode[i].func withInput:source];
- }
- }
- }
- return self;
- }
-
-
- - doFunction:(enum escapeFunction) func withInput:(id)source
- {
- char temp[200];
- switch (func) {
- case dial: {
- char dialPrefix[]="ATDT", dialPostfix[]="\r"; // constants for now; later local var's of modem
- char pn[200];
-
- [source getline:pn size:sizeof(pn) WithPrompt:"Enter phone number:"];
- sprintf(temp,"%s%s%s\n",dialPrefix, pn, dialPostfix);
- [self autoDial:temp];
- break;
- }
- case baudrate: {
- int bps;
- [source getline:temp size:sizeof(temp) WithPrompt:"Enter new baud rate [300,1200,2400,4800,9600]:"];
- sscanf(temp,"%d",&bps);
- [modem setSpeed:bps];
- sprintf(temp,"Modem speed set to %d\n",[modem getSpeed]);
- [term putString:temp];
- break;
- }
- case readscript:
- [source getline:temp size:sizeof(temp) WithPrompt:"Enter script file:"];
- stripNL(temp);
- [self readScript:temp];
- break;
- case stop:
- [term reset];
- [modem endCapture];
- [term putString:"\nquitting \n"];
- exit(0);
- break;
- case protocol: {
- enum direction dir;
- char p;
- do {
- p = [source getcharWithPrompt:"\nEnter direction [(s)end,(r)eceive]:"];
- } while (!member(p,"sr"));
- dir = (p=='s')?tohost:fromhost;
- sprintf(temp, "\nEnter desired %s protocol [(x)modem,xmodem(1)k,(y)modem,(z)modem]:",
- (dir==tohost)?"send":"receive");
- do {
- p = [source getcharWithPrompt:temp];
- } while (!member(p,"x1yz"));
- [modem setProtocol:p dir:dir];
- sprintf(temp,"\nSend protocol is %c\n",[modem getProtocolDir:tohost]);
- [term putString:temp];
- sprintf(temp,"\nReceive protocol is %c\n",[modem getProtocolDir:fromhost]);
- [term putString:temp];
- break;
- }
- case parity: {
- int par, parity;
- do {
- par = [source getcharWithPrompt:"\nEnter desired parity (even, odd, or none) [e,o,n]:"];
- if (par=='e' || par=='E')
- parity=EVENP;
- else if (par=='o' || par=='O')
- parity=ODDP;
- else if (par=='n' || par=='N')
- parity=NOPARITY;
- else
- parity=ILLEGAL_PARITY;
- } while (parity == ILLEGAL_PARITY);
- [modem setParity:parity];
- sprintf(temp,"\nParity is %c\n",par);
- [term putString:temp];
- break;
- }
- case sendfile:
- {
- char trigger[100];
- struct stat dummy;
- int cc;
-
- do {
- [source getline:temp size:sizeof(temp) WithPrompt:"\nEnter file to send:"];
- stripNL(temp);
- // check for existence of file
- if ((cc = stat(temp, &dummy)) != 0)
- [source putString:"Couldn't open file...try again"];
- } while (temp[0] && cc != 0); // null filename means abort command
- if (temp[0]) {
- [source getline:trigger size:sizeof(trigger) WithPrompt:"\nEnter command to send to host:"];
- [[term pushState] reset];
- [modem writeOut:trigger];
- [modem sendFile:temp];
- [term popState];
- }
- break;
- }
- case receivefile:
- [[term pushState] reset];
- [modem receive];
- [term popState];
- break;
- case capture:
- if ([modem isCapturing]) {
- [term putString:"Ending capture to file\n"];
- [modem endCapture];
- }
- else {
- [source getline:temp size:sizeof(temp) WithPrompt:"\nEnter file to save to [tip.record]:"];
- stripNL(temp);
- if (*temp == 0)
- strcpy(temp,"tip.record");
- [modem captureSessionInFile:temp];
- }
- break;
- case hangup:
- [[term pushState] reset];
- [modem hangup];
- [term popState];
- break;
- case nop:
- break;
- case echo:
- while ([source getline:temp size:sizeof(temp)]) {
- [term putString:temp];
- [term putString:" "];
- }
- [term putString:"\n"];
- break;
- case say:
- {
- int firstarg=1;
- while ([source getline:temp size:sizeof(temp)]) {
- if (firstarg)
- firstarg = 0;
- else
- [modem writeOut:" "];
- [modem writeOut:temp];
- }
- [modem writeOut:"\r"];
- }
- break;
- case expect:
- {
- // can't write this bit just yet
- }
- break;
- default:
- break;
- }
- return self;
- }
-
- - doEscape:(char) func
- {
- return [self doFunction:keymap[func] withInput:term];
- }
-
- - bindChar:(char) ch toFunction:(enum escapeFunction) func
- {
- keymap[ch] = func;
- return self;
- }
-
- - autoDial:(char *)dialString
- {
- id s;
- id sr;
- int i;
- char line[200];
- enum responses {connect=1,connect1200,connect2400,no_carrier,busy,no_dialtone,user_abort};
- enum responses seen;
-
- s = [Fdset new];
- [s addfd:[modem getfd]];
- [s addfd:[term getfd]];
- sr = [StringResponder new];
- [sr addString:"CONNECT!" returnValue:connect];
- [sr addString:"CONNECT 1200!" returnValue:connect1200];
- [sr addString:"CONNECT 2400!" returnValue:connect2400];
- [sr addString:"NO CARRIER!" returnValue:no_carrier];
- [sr addString:"BUSY!" returnValue:busy];
- [sr addString:"NO DIALTONE!" returnValue:no_dialtone];
- try_again:
- [modem writeOut:dialString paced:10000];
- for (seen=0; !seen && [s waitOnInputFor:60]; ) {
- if ([s getReadyfd] == [term getfd]) { // check for user abort
- [term readInto:line];
- if (strchr(line,27)) {
- seen = user_abort;
- break;
- }
- }
- [modem readInto:line];
- [term putString:line];
- for (i=0;i<strlen(line);i++) { // convert end of line chars to !
- if (line[i]=='\r' || line[i]=='\n') line[i]='!';
- }
- seen = [sr inputString:line];
- }
- if (!seen)
- [term putString:"modem is not responding as expected\n"];
- else {
- switch (seen) {
- case connect:
- [term ringBell];
- break;
- case connect1200:
- [modem setSpeed:1200];
- [term ringBell];
- break;
- case connect2400:
- [modem setSpeed:2400];
- [term ringBell];
- break;
- case no_carrier:
- [term putString:"modem detected no carrier, trying again...\n"];
- goto try_again;
- break;
- case busy:
- [term putString:"busy, trying again...\n"];
- sleep(10);
- goto try_again;
- break;
- case no_dialtone:
- [term putString:"modem couldn't get dialtone; check phone\n"];
- break;
- case user_abort:
- [term putString:"User aborted dialing\n"];
- break;
- }
- }
- [s free];
- [sr free];
- return self;
- }
-
-
- @end
-