/************************************************************* * vt100 terminal emulator - Script file support * * v2.7 870825 ACS - Wait for the reply from AbortIO(). * Use the *InfoMsg*() routines in window.c. Provide * for multiple script files on command line * (companion to the changes in init.c). Add the * ability to set shortcuts from init file. * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 * v2.5 870214 DBW - more additions (see readme file) * v2.4 861214 DBW - lots of fixes/additions (see readme file) * v2.3 861101 DBW - minor bug fixes * v2.2 861012 DBW - more of the same * v2.1 860915 DBW - new features (see README) * 860901 ACS - Added BAUD, PARITY and WORD commands & handling * 860823 DBW - Integrated and rewrote lots of code * 860815 Steve Drew: Initial version written of SCRIPT.C * v2.0 860809 DBW - Major rewrite * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes * v1.0 860712 DBW - First version released * *************************************************************/ #include "vt100.h" struct COMMAND { void (*func)(); char *cname; }; struct LABEL { struct LABEL *next; char *name; long pos; }; extern long atol(); struct SHORT_CUTS { char *cname; char *pos; }; /* Following variables are set up in init.c's InitDefaults. They tell ** us if there are any other script files listed on the command line so ** that we can execute them when a prior script is done. */ extern int script_files_todo; extern char **script_files; /**************** globals needed ******************/ char on_string[20]; /* string to match on for on cmd */ char wait_string[20]; /* string to match of for wait cmd */ char golabel[20]; /* label we are looking for in goto */ char on_cmd[20]; /* command to execute when on matchs*/ int onsize; /* size of on_string */ int waitsize; /* size of wait_string */ int onpos; /* position in on string for search */ int waitpos; /* pos in wait_string for search */ int on_match; /* flag set while doing on_cmd */ FILE *sf; /* file pointer for script file */ struct LABEL *lbase = NULL; /* will point to first label */ struct LABEL *labels; /* current label pointer */ void cmd_short(); /********************** command tables *******************************/ static struct COMMAND inicmds[] = { /* initialization commands */ cmd_bkg, "bac", /* set background color */ cmd_bold, "bol", /* set bold color */ cmd_buf, "buf", /* set buffer size */ cmd_cursor, "cur", /* set cursor color */ cmd_depth, "dep", /* set screen depth */ cmd_fore, "for", /* set foreground color */ cmd_inter, "int", /* interlace ON/OFF */ cmd_lines, "lin", /* num lines */ cmd_screen, "scr", /* Screen WB/CUST */ cmd_volume, "vol", /* set volume */ cmd_wb, "wb", /* use WB colors */ cmd_short, "sho", /* Set shortcuts */ cmd_null, NULL /* mark the end of the list */ }; static struct COMMAND scrcmds[] = { /* script only commands */ cmd_as, "asc", /* ascii send */ cmd_beep, "bee", /* Beep */ cmd_cap, "cap", /* ascii capture on/off */ cmd_cd, "cd", /* change directory */ cmd_delay, "del", /* delay amount of seconds */ cmd_goto, "got", /* goto label */ cmd_kb, "kb", /* kermit bye (for server) */ cmd_kg, "kg", /* kermit get file */ cmd_kr, "kr", /* kermit receive file */ cmd_ks, "ks", /* kermit send file */ cmd_on, "on", /* on a 'string' do a cmd */ cmd_sb, "sb", /* Send a break */ cmd_send, "send", /* send string to host */ cmd_wait, "wait", /* wait for a host string */ cmd_xr, "xr", /* xmodem receive file */ cmd_xs, "xs", /* xmodem send file */ cmd_null, NULL /* mark the end of the list */ }; static struct COMMAND commands[]= { /* generally available commands */ cmd_appcur, "app", /* turn app. cursor on/off */ cmd_baud, "bau", /* Set Baud Rate */ cmd_bt, "bre", /* Set Break Time */ cmd_conv, "con", /* convert fn to lowercase */ cmd_echo, "ech", /* turn echo on or off */ cmd_exit, "exi", /* exit script file */ cmd_fnc, "f", /* define function key */ cmd_key, "key", /* keyscript character */ cmd_mode, "mod", /* KERMIT transfer mode */ cmd_numkey, "numkey", /* turn numeric kpad on/off */ cmd_parity, "parity", /* Set Parity */ cmd_swap, "swap", /* Swap BS and DEL */ cmd_wrap, "wrap", /* turn wrap on or off */ cmd_null, NULL /* mark the end of the list */ }; /* NB: The structures referenced in the structure may be found in ** init.c */ #ifdef BUGFIXES extern struct filecmd { #else struct filecmd { #endif char ac; /* ASCII Capture */ char as; /* ASCII Send */ char xs; /* Xmodem Send */ char xr; /* Xmodem Receive */ char kg; /* Kermit Get */ char kr; /* Kermit Receive */ char ks; /* Kermit Send */ char kb; /* Kermit Bye */ char nl; } filecmd_chars; #ifdef BUGFIXES extern struct baducmd { #else struct baducmd { #endif char b03; /* 0300 */ char b12; /* 1200 */ char b24; /* 2400 */ char b48; /* 4800 */ char b96; /* 9600 */ char bnl; } baudcmd_chars; #ifdef BUGFIXES extern struct parcmd { #else struct parcmd { #endif char no; /* NOne */ char ma; /* MArk */ char sp; /* SPace */ char ev; /* EVen */ char od; /* ODd */ char nl; } parcmd_chars; #ifdef BUGFIXES extern struct modcmd { #else struct modcmd { #endif char im; /* IMage */ char tx; /* TeXt */ char cn; /* CoNvert */ char nl; } modcmd_chars; extern struct scrcmd { char em; /* Execute Macro */ char ab; /* Abort Macro */ char nl; } scrcmd_chars; extern struct { char sb; /* Send Break */ char hu; /* Hang Up */ char cd; /* Change Dir */ char cs; /* Clear Screen */ char ec; /* ECho */ char wr; /* WRap */ char nk; /* Num Key */ char ac; /* App Cur */ char bs; /* BS<->DEL */ char nl; } utilcmd_chars; static struct SHORT_CUTS shortkeys[] = { /* Short-cut keys */ /* File items: */ "cap", &(filecmd_chars.ac), /* ascii capture on/off */ "asc", &(filecmd_chars.as), /* ascii send */ "xr", &(filecmd_chars.xs), /* xmodem receive file */ "xs", &(filecmd_chars.xr), /* xmodem send file */ "kg", &(filecmd_chars.kg), /* kermit get file */ "kr", &(filecmd_chars.kr), /* kermit receive file */ "ks", &(filecmd_chars.ks), /* kermit send file */ "kb", &(filecmd_chars.kb), /* kermit bye (for server) */ /* Comm items: */ "300", &(baudcmd_chars.b03), /* Set Baud Rate */ "1200", &(baudcmd_chars.b12), /* Set Baud Rate */ "2400", &(baudcmd_chars.b24), /* Set Baud Rate */ "4800", &(baudcmd_chars.b48), /* Set Baud Rate */ "9600", &(baudcmd_chars.b96), /* Set Baud Rate */ "none", &(parcmd_chars.no), /* Set Parity */ "mark", &(parcmd_chars.ma), /* Set Parity */ "space", &(parcmd_chars.sp), /* Set Parity */ "even", &(parcmd_chars.ev), /* Set Parity */ "odd", &(parcmd_chars.od), /* Set Parity */ "image", &(modcmd_chars.im), /* KERMIT transfer mode */ "text", &(modcmd_chars.tx), /* KERMIT transfer mode */ "convert", &(modcmd_chars.cn), /* KERMIT transfer mode */ /* Script items: */ "execute", &(scrcmd_chars.em), /* execute macro */ "abort", &(scrcmd_chars.ab), /* abort macro */ /* Util items: */ "sb", &(utilcmd_chars.sb), /* send break */ "hang", &(utilcmd_chars.hu), /* hang up */ "cd", &(utilcmd_chars.cd), /* change directory */ "clear", &(utilcmd_chars.cs), /* clear screen */ "ech", &(utilcmd_chars.ec), /* turn echo on or off */ "wrap", &(utilcmd_chars.wr), /* turn wrap on or off */ "numkey", &(utilcmd_chars.nk), /* turn numeric kpad on/off */ "app", &(utilcmd_chars.ac), /* turn app. cursor on/off */ "con", &(utilcmd_chars.bs), /* convert bs to del */ "swap", &(utilcmd_chars.bs), /* Swap BS and DEL */ NULL, NULL }; /********************************************************************/ /* checks char to see if match with on string or wait_string */ /* if on string match oncmd gets executed imediately, */ /* if wait_string match script_wait is set. */ /********************************************************************/ chk_script(c) char c; { if (on_string[0] != '\0') { if (on_string[onpos] == c) { onpos++; if (onpos == onsize) { on_match = TRUE; do_script_cmd(ONCOMMAND); on_match = FALSE; return(0); } } else onpos = 0; } if (wait_string[0] != '\0') { if (wait_string[waitpos] != c) { waitpos = 0; return(0); } waitpos++; if (waitpos != waitsize) return(0); wait_string[0] = '\0'; script_wait = FALSE; } } script_start(file) char *file; { char *sfile = NULL; if (strlen(file) == 0 || *file == '#') return(0); if ((sf = fopen(file, "r")) == NULL) { sfile = AllocMem((LONG)(strlen(file)+3), MEMF_PUBLIC|MEMF_CLEAR); strcpy(sfile, "S:"); strcat(sfile, file); if((sf = fopen(sfile, "r")) == NULL) { InfoMsg2Line("Can't open script file",file); return(0); } } script_on = TRUE; script_wait = FALSE; wait_string[0] = '\0'; on_string[0] = '\0'; on_match = FALSE; lbase = NULL; if(sfile) FreeMem(sfile, (LONG)strlen(file)+3); } /* return pointer to next word. set l to size of the word */ char *next_wrd(s,l) char *s; int *l; { char *p; while(*s && (*s == ' ' || *s == '\t')) s++; p = s; while(*s && (*s != ' ' && *s != '\t')) s++; *l = s-p; return(p); } exe_cmd(p,l) char *p; int l; { int i,l2; /* downcase the command */ for (i=0; i= l2 && strncmp(p, inicmds[i].cname, l2) == 0) { (*inicmds[i].func)(next_wrd(p+l, &l)); return(TRUE); } } /* or the script command list */ else for (i=0; scrcmds[i].func != cmd_null; ++i) { l2 = strlen(scrcmds[i].cname); if (l >= l2 && strncmp(p, scrcmds[i].cname, l2) == 0) { (*scrcmds[i].func)(next_wrd(p+l, &l)); return(TRUE); } } /* now search for it (in the standard command list) */ for (i=0; commands[i].func != cmd_null; ++i) { l2 = strlen(commands[i].cname); if (l >= l2 && strncmp(p, commands[i].cname, l2) == 0) { (*commands[i].func)(next_wrd(p+l, &l)); return(TRUE); } } if (doing_init) { puts("INIT - unknown command:"); puts(p); } else InfoMsg2Line("Script - unknown command:",p); return(FALSE); } struct LABEL *find_label(lname) char *lname; { struct LABEL *label; label = lbase; while(label != NULL) { if (strcmp(label->name, lname) == 0) return (label); label = label->next; } return(NULL); } do_script_cmd(stat) int stat; { int len,l; char line[256]; char *p; /* if ON command is matched and we were */ /* doing a DELAY then abort the delay timer,*/ /* except if on_cmd was just a SEND. */ if (stat == ONCOMMAND) { strcpy(line,on_cmd); p = next_wrd(line,&l); if (*p != 's' && script_wait == WAIT_TIMER) { AbortIO((char *) &Script_Timer); Wait (1L << Script_Timer_Port->mp_SigBit); #ifdef BUGFIXES WaitIO(&Script_Timer); #else WaitIO(Script_Timer); #endif /* script will proceed after on command */ script_wait = FALSE; } exe_cmd(p,l); return(0); } script_wait = FALSE; while(fgets(line,256,sf) != NULL) { len = strlen(line); line[--len] = '\0'; p = next_wrd(&line[0], &l); if (*(p + l - 1) == ':') { /* its a label */ *(p + l - 1) = '\0'; if (find_label(p) == NULL) { /* it's a new label */ if (lbase == NULL) { /* it's the first label */ labels = lbase = (struct LABEL *) malloc(sizeof (struct LABEL)); } else { labels->next = (struct LABEL *) malloc(sizeof (struct LABEL)); labels = labels->next; } labels->pos = ftell(sf); labels->name = malloc(l); labels->next = NULL; strcpy(labels->name, p); if (stat == GOTOLABEL && strcmp(p, golabel) == 0) stat = NEXTCOMMAND; } p = next_wrd(p+l+1, &l); } /* end of it's a label */ if (stat == GOTOLABEL || *p == '#') continue; if (*p) exe_cmd(p,l); return(0); } /* end of while */ if (stat == GOTOLABEL) InfoMsg2Line("Script - label not found:",golabel); exit_script(); if(script_files_todo > 0) { script_files_todo--; script_start(*(script_files++)); } } exit_script() { if (script_wait == WAIT_TIMER) { /* timer not done yet */ AbortIO((char *) &Script_Timer); /* so abort it */ Wait (1L << Script_Timer_Port->mp_SigBit); /* Wait for the sig */ #ifdef BUGFIXES WaitIO(&Script_Timer); /* Get my reply back */ #else WaitIO(Script_Timer); /* Get my reply back */ #endif } InfoMsg1Line("Script - terminated"); script_on = FALSE; script_wait = TRUE; fclose(sf); } /* remove quotes terminate string & return pointer to start */ char *tostring(ptr) char *ptr; { char *s1,*s2; s1 = ptr; if (*ptr == '"') { while(*ptr++ && *ptr != '"') ; if (*ptr == '"') { *ptr = '\0'; ptr = s2 = ++s1; while(*s2) { if (*s2 != '^') *s1++ = *s2; else if (*(s2+1) == '^') *s1++ = *s2++; else *s1++ = ((*++s2)|' ')-96; s2++; } *s1 = '\0'; return(ptr); } } if (*s1 == '^') { *s1 = (*(s1+1)|' ')-96; *(s1+1) = '\0'; return(s1); } *(s1+1) = '\0'; return(s1); } /***************************** SCRIPT COMMANDS ********************/ void cmd_goto(lname) char *lname; { struct LABEL *label; /* if on_cmd was a goto kill wait state */ if (on_match) { wait_string[0] = '\0'; script_wait = FALSE; } if ((label = find_label(lname)) == NULL) { /* is it forward */ strcpy(golabel,lname); do_script_cmd(GOTOLABEL); } else { fseek(sf,(long)(label->pos),0); } } void cmd_send(str) char *str; { sendstring(tostring(str)); } void cmd_wait(str) char *str; { str = tostring(str); *(str+20) = '\0'; /* 20 characters max */ strcpy(wait_string, str); waitsize = strlen(str); script_wait = WAIT_STRING; } void cmd_on(str) char *str; { char *p; p = tostring(str); strcpy(on_string, p); onsize = strlen(p); *(p+onsize+2+20) = '\0'; /* 20 characters max */ strcpy(on_cmd,p+onsize+2); } void cmd_delay(seconds) char *seconds; { script_wait = WAIT_TIMER; Script_Timer.tr_time.tv_secs = atoi(seconds); Script_Timer.tr_time.tv_micro = 0; SendIO((char *) &Script_Timer.tr_node); } void cmd_exit(option) char *option; { char *p; int l; if (doing_init) return; if (*option) { p = next_wrd(option,&l); *(p+l) = '\000'; if (strcmp(p,"vt100") == 0 || strcmp(p,"VT100") == 0) cleanup("Exit vt100 from script",0); exit_script(); script_start(p); } else { exit_script(); if(script_files_todo > 0) { script_files_todo--; script_start(*(script_files++)); } } } void cmd_ks(file) char *file; { multi_xfer(file, doksend, 1); } void cmd_kr(file) char *file; { multi_xfer(file, dokreceive, 0); } void cmd_kg(file) char *file; { server = TRUE; multi_xfer(file, dokreceive, 0); } void cmd_kb() { saybye(); } void cmd_xs(file) char *file; { multi_xfer(file, XMODEM_Send_File, 1); } void cmd_xr(file) char *file; { multi_xfer(file, XMODEM_Read_File, 1); } void cmd_cap(file) char *file; { do_capture(file); } void cmd_as(file) char *file; { do_send(file); } void cmd_cd(name) char *name; { set_dir(name); } void cmd_sb(str) char *str; { sendbreak(); } void cmd_baud(rate) char *rate; { int i = atoi(rate); switch( i ) { case 300: case 1200: case 2400: case 4800: case 9600: if (doing_init) p_baud = i; else setserbaud(i, TRUE); break; default: if (doing_init) { puts("INIT - invalid baud rate:"); puts(rate); } else InfoMsg2Line("Script - invalid baud rate: ",rate); break; } } void cmd_parity(par) char *par; { int i; switch( *par|' ' ) { case 'n': i = 0; break; case 'm': i = 1; break; case 's': i = 2; break; case 'e': i = 3; break; case 'o': i = 4; break; default: if (doing_init) { puts("INIT - invalid parity:"); puts(par); } else InfoMsg2Line("Script - invalid parity: ",par); return; } p_parity = i; if (doing_init) return; ClearMenuStrip( mywindow ); /* Remove old menu */ InitCommItems(); /* Re-do comm menu */ SetMenuStrip(mywindow,&menu[0]); /* Re-display the menu */ } void cmd_bt(breaklength) char *breaklength; { p_break = atol(breaklength); if (doing_init) return; AbortIO(Read_Request); Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit); WaitIO(Read_Request); Read_Request->io_BrkTime = Write_Request->io_BrkTime = p_break; setparams(); } void cmd_mode(tmode) char *tmode; { switch (*tmode|' ') { case 'i': p_mode = 0; break; case 'c': p_mode = 1; break; default: if (doing_init) { puts("INIT - invalid transfer mode: "); puts(tmode); } else InfoMsg2Line("Script - invalid transfer mode: ",tmode); return; } if (doing_init) return; ClearMenuStrip(mywindow); InitCommItems(); /* Re-do comm menu */ SetMenuStrip(mywindow,&menu[0]); } void cmd_beep(dummy) char *dummy; { if (p_volume == 0) DisplayBeep(NULL); else { BeginIO(&Audio_Request); WaitIO(&Audio_Request); } } void setvar(par,typ,var) char *par; int typ,*var; { int i; switch (typ) { case 0: /* ON/OFF or YES/NO */ case 1: /* not case */ if ((par[1]|' ') == 'n' || (par[0]|' ') == 'y') *var = 1-typ; else *var = typ; break; case 2: /* read hex number */ if (sscanf(par,"%x",&i) == 1) *var = i; break; case 3: /* read decimal number */ if (sscanf(par,"%d",&i) == 1) *var = i; break; } } void cmd_echo(par) char *par; { setvar(par,0,&p_echo); if (doing_init == 0) redoutil(); } void cmd_wrap(par) char *par; { setvar(par,0,&p_wrap); if (doing_init == 0) redoutil(); } void cmd_numkey(par) char *par; { setvar(par,1,&p_keyapp); if (doing_init == 0) redoutil(); } void cmd_appcur(par) char *par; { setvar(par,0,&p_curapp); if (doing_init == 0) redoutil(); } void cmd_swap(par) char *par; { setvar(par,0,&p_bs_del); if (doing_init == 0) redoutil(); } void cmd_bkg(par) char *par; { setvar(par,2,&p_background); } void cmd_bold(par) char *par; { setvar(par,2,&p_bold); } void cmd_buf(par) char *par; { setvar(par,3,&p_buffer); } void cmd_cursor(par) char *par; { setvar(par,2,&p_cursor); } void cmd_depth(par) char *par; { setvar(par,3,&p_depth); } void cmd_fore(par) char *par; { setvar(par,2,&p_foreground); } void cmd_inter(par) char *par; { setvar(par,0,&p_interlace); } void cmd_lines(par) char *par; { setvar(par,3,&p_lines); } void cmd_screen(par) char *par; { if ((par[0]|' ') == 'w') p_screen = 0; else p_screen = 1; } void cmd_wb(par) char *par; { setvar(par,0,&p_wbcolors); } void cmd_short(par) /* Set keyboard shortcuts */ char *par; { int i, l, l2; register char *p = par; /* downcase the next word */ for (i=0; p[i] && (p[i] != ' '); i++) p[i] |= ' '; l = i; /* Find the command name. If found set the shortcut key to the ** user's value. If no value then set the key to ' ' to indicate no ** shortcur available. */ for(i = 0; shortkeys[i].cname != NULL; i++) { l2 = strlen(shortkeys[i].cname); if (l >= l2 && strncmp(p, shortkeys[i].cname, l2) == 0) { for( ; p[l] && (p[l] == ' '); l++) ; if(p[l]) *(shortkeys[i].pos) = p[l]; else *(shortkeys[i].pos) = ' '; } } } void cmd_key(par) char *par; { int i; if (sscanf(par,"%x",&i) == 1) p_keyscript = (char)(i & 0x7f); } void cmd_volume(par) char *par; { setvar(par,3,&p_volume); } void cmd_conv(par) char *par; { setvar(par,0,&p_convert); if (doing_init == 0) redoutil(); } void cmd_fnc(par) char *par; { char *s; int l; int i = atoi(par); s = par; if (*s) s = next_wrd(s,&l); /* skip key number */ if (*s) s = next_wrd(s+l+1,&l); /* point at desired string */ if (*s) s = tostring(s); /* convert the string */ if (*s && i > 0 && i < 21) { if (i > 10) { p_F[i-11] = malloc(strlen(s)+1); strcpy(p_F[i-11],s); } else { p_f[i-1] = malloc(strlen(s)+1); strcpy(p_f[i-1],s); } } } void cmd_null(dummy) char *dummy; { }