/************************************************************* * vt100 terminal emulator - Script file support * :ts=8 * * v2.9 ACS - Add support for font size, external transfer program * support, new ASIS option to LACE cmd and AREXX support. * v2.8a 880331 ACS - Allow comments on XPROTO and FONT. * 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" #define DNMAXLEN 9 extern struct MsgPort *mySerPort; /* in vt100.c */ struct COMMAND { int (*func)(); char *cname; int minlen; int validfrom; }; #define INIT 1 #define SCRIPT 2 #define NONREXX 4 #define REXXONLY 8 struct LABEL { struct LABEL *next; char *name; long pos; }; extern long atol(); #if MANX extern char *index(); #endif /* MANX */ #if LATTICE #define index(a,b) stpchr(a,b) #endif /* LATTICE */ 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 = NULL; /* file pointer for script file */ struct LABEL *lbase = NULL; /* will point to first label */ struct LABEL *labels; /* current label pointer */ char errmsg[80]; /* Error msg from routines */ #if AREXX int implied_rexx; /* cmd_rx() invoked as impled cmd */ #endif /* AREXX */ /************************ command table *********************************/ static struct COMMAND commands[] = { cmd_appcur, "appcursor", 3, INIT|SCRIPT, /* turn app. cursor on/off */ cmd_as, "ascii", 3, SCRIPT, /* ascii send */ cmd_ac, "autochop", 3, INIT|SCRIPT, /* XMODEM autochop */ cmd_bkg, "background", 3, INIT, /* set background color */ cmd_baud, "baud", 3, INIT|SCRIPT, /* Set Baud Rate */ cmd_beep, "beep", 3, SCRIPT, /* Beep */ cmd_bold, "bold", 3, INIT, /* set bold color */ cmd_bt, "breaktime", 3, INIT|SCRIPT, /* Set Break Time */ cmd_buf, "buffer", 3, INIT, /* set buffer size */ cmd_cap, "capture", 3, SCRIPT, /* ascii capture on/off */ cmd_cd, "cd", 2, SCRIPT, /* change directory */ cmd_conv, "convert", 4, INIT|SCRIPT, /* convert fn to lowercase */ cmd_cursor, "cursor", 3, INIT, /* set cursor color */ cmd_delay, "delay", 3, SCRIPT, /* delay amount of seconds */ cmd_depth, "depth", 3, INIT, /* set screen depth */ cmd_device, "device", 3, INIT, /* set serial device name */ cmd_display, "display", 3, SCRIPT, /* Display data on screen */ cmd_echo, "echo", 3, INIT|SCRIPT, /* turn echo on or off */ cmd_exit, "exit", 3, INIT|SCRIPT|NONREXX, /* exit script file */ cmd_ext, "external", 4, INIT|SCRIPT, /* external xfer pgms */ cmd_fnc, "f", 1, INIT|SCRIPT, /* define function key */ cmd_font, "font", 3, INIT, /* set font */ cmd_fonts, "fontsize", 5, INIT, /* set fontsize */ cmd_fore, "foreground", 3, INIT, /* set foreground color */ #if AREXX cmd_fwd, "forward", 3, REXXONLY, /* forward data to rexx */ #endif /* AREXX */ cmd_goto, "goto", 3, SCRIPT|NONREXX,/* goto label */ cmd_inter, "interlace", 3, INIT, /* interlace ON/OFF */ cmd_kb, "kb", 2, SCRIPT, /* kermit bye (for server) */ cmd_key, "keyscript", 3, INIT|SCRIPT, /* keyscript character */ cmd_kg, "kg", 2, SCRIPT, /* kermit get file */ cmd_kmaxpk, "kmaxpack", 8, INIT|SCRIPT, /* Kermit maximum packet size */ cmd_kr, "kr", 2, SCRIPT, /* kermit receive file */ cmd_ks, "ks", 2, SCRIPT, /* kermit send file */ cmd_lines, "lines", 3, INIT, /* num lines */ cmd_mode, "mode", 3, INIT|SCRIPT, /* KERMIT transfer mode */ cmd_mouse, "mouse", 3, INIT|SCRIPT, /* Mouse control */ cmd_msg, "msg", 3, SCRIPT, /* Display a message */ cmd_numkey, "numkey", 6, INIT|SCRIPT, /* turn numeric kpad on/off */ cmd_on, "on", 2, SCRIPT, /* on a 'string' do a cmd */ cmd_parity, "parity", 6, INIT|SCRIPT, /* Set Parity */ cmd_recf, "recfile", 4, SCRIPT, /* receive a file from host */ cmd_rx, "rx", 2, INIT|SCRIPT, /* Specific invocation */ cmd_sb, "sb", 2, SCRIPT, /* Send a break */ cmd_screen, "screen", 3, INIT, /* Screen WB/CUST */ cmd_send, "send", 4, SCRIPT, /* send string to host */ cmd_sendf, "sendfile", 5, SCRIPT, /* send a file to host */ cmd_share, "shareserial", 5, INIT|SCRIPT, /* ShareSerial device */ cmd_short, "shortcut", 3, INIT, /* Set shortcuts */ cmd_swap, "swap", 4, INIT|SCRIPT, /* Swap BS and DEL */ cmd_unit, "unit", 4, INIT, /* Unit of serial.device to use */ cmd_volume, "volume", 3, INIT, /* set volume */ cmd_wait, "wait", 4, SCRIPT|NONREXX, /* wait for a host string */ cmd_wb, "wbcolors", 3, INIT, /* use WB colors */ cmd_wrap, "wrap", 4, INIT|SCRIPT, /* turn wrap on or off */ cmd_xbeep, "xbeep", 4, INIT|SCRIPT, /* Beep at end of xfer */ cmd_xproto, "xprotocol", 5, INIT|SCRIPT, /* Xfer Protocol */ cmd_xr, "xr", 2, SCRIPT, /* xmodem receive file */ cmd_xs, "xs", 2, SCRIPT, /* xmodem send file */ cmd_null, NULL, 0, 0 /* mark the end of the list */ }; char *xprotos[] = { /* Order *must* be same as corresponding p_xproto values */ "ascii", "xmodem", "xmodemcrc", "kermit" }; /* NB: The structures referenced in the structure may be found in ** init.c */ extern struct filecmd { char mo; /* Mode */ char se; /* Send */ char re; /* Receive */ char kg; /* Kermit Get */ char kb; /* Kermit Bye */ char ca; /* Capture or Capturing */ char nl; } filecmd_chars; extern struct mode_cmd { char as; /* ascii mode */ char xm; /* xmodem mode */ char xmc; /* xmodem crc mode */ char ke; /* kermit mode */ char nl; } modecmd_chars; extern struct baducmd { char b03; /* 0300 */ char b12; /* 1200 */ char b24; /* 2400 */ char b48; /* 4800 */ char b96; /* 9600 */ char bnl; } baudcmd_chars; extern struct parcmd { char no; /* NOne */ char ma; /* MArk */ char sp; /* SPace */ char ev; /* EVen */ char od; /* ODd */ char nl; } parcmd_chars; extern struct commcmd { char nl0; /* Baud Sub-Item */ char nl1; /* Parity Sub-Item */ char nl2; /* Xfer mode Sub-Item */ char sh; /* Shared item */ char nl; } commcmd_chars; extern struct modcmd { char im; /* IMage */ char tx; /* TeXt */ char cn; /* CoNvert */ char ac; /* AutoChop */ char nl; } modcmd_chars; extern struct scrcmd { char em; /* Execute Macro */ char ab; /* Abort Macro */ char rx; /* AREXX 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 xb; /* Beep at end of Xfer */ char mu; /* Mouse up events */ char md; /* Mouse down events */ char nl; } utilcmd_chars; static struct SHORT_CUTS shortkeys[] = { /* Short-cut keys */ /* File items: */ "se", &(filecmd_chars.se), /* Send file */ "re", &(filecmd_chars.re), /* Receive file */ "kb", &(filecmd_chars.kb), /* kermit bye (for server) */ "kg", &(filecmd_chars.kg), /* kermit get (for server) */ "cap", &(filecmd_chars.ca), /* Capture */ /* Mode items: */ "asc", &(modecmd_chars.as), /* ascii mode */ "xmc", &(modecmd_chars.xmc), /* xmodemcrc mode */ "xm", &(modecmd_chars.xm), /* xmodem mode */ "ke", &(modecmd_chars.ke), /* kermit mode */ /* Comm items: */ "share", &(commcmd_chars.sh), /* Shared */ "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 */ "autochop", &(modcmd_chars.ac), /* XMODEM autochop */ /* Script items: */ "execute", &(scrcmd_chars.em), /* execute macro */ "abort", &(scrcmd_chars.ab), /* abort macro */ "rx", &(scrcmd_chars.rx), /* rexx 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 */ "xbeep", &(utilcmd_chars.xb), /* Beep at end of xfer */ "mouseup", &(utilcmd_chars.mu), /* Mouse up events */ "mousedn", &(utilcmd_chars.md), /* Mouse dn events */ NULL, NULL }; static int cmd_from_script; /* != 0 iff cmd from a script */ /********************************************************************/ /* 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; on_string[0] = '\0'; on_cmd[0] = '\0'; onpos = 0; 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) register char *p; int l; { int i, l2, cmdrc = CMDOK; register struct COMMAND *cmd; /* downcase the command */ for (i=0; ifunc != cmd_null; cmd++) { int validfrom = cmd->validfrom; if(*p != cmd->cname[0]) continue; l2 = strlen(cmd->cname); if(l >= cmd->minlen && l <= l2 && strncmp(p, cmd->cname, l) == 0) { if( (!doing_init && (validfrom == INIT)) || (((validfrom & NONREXX) == NONREXX) && CmdFromRexx) || (((validfrom & REXXONLY) == REXXONLY) && !CmdFromRexx) ) return(CMDBS); cmd_from_script = 1; cmdrc = (*(cmd->func))(next_wrd(p+l, &l)); cmd_from_script = 0; if(errmsg[0]) if(doing_init) { puts("Init:"); puts(errmsg); } else InfoMsg2Line("Script:", errmsg); return(cmdrc); } } #if AREXX if(implied_rexx == 0 && RexxSysBase != NULL) { implied_rexx = 1; cmdrc = cmd_rx(p); implied_rexx = 0; return(cmdrc); } #endif /* AREXX */ if (doing_init) { puts("Init: unknown command:"); puts(p); } else InfoMsg2Line("Script - unknown command:",p); return(CMDNF); } 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) { if(!CheckIO((struct IORequest *)&Script_Timer)) AbortIO((struct IORequest *)&Script_Timer); Wait (1L << Script_Timer_Port->mp_SigBit); WaitIO((struct IORequest *)&Script_Timer); /* script will proceed after on command */ script_wait = FALSE; } exe_cmd(p,l); return(0); } script_wait = FALSE; if(CmdFromRexx) return; 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 */ if(!CheckIO((struct IORequest *)&Script_Timer)) AbortIO((struct IORequest *)&Script_Timer); /* so abort it */ Wait (1L << Script_Timer_Port->mp_SigBit); /* Wait for the sig */ WaitIO((struct IORequest *)&Script_Timer); /* Get my reply back */ } InfoMsg1Line("Script: terminated"); script_on = FALSE; script_wait = TRUE; on_match = FALSE; wait_string[0] = '\0'; on_string[0] = '\0'; on_cmd[0] = '\0'; fclose(sf); sf = NULL; if (reqwinup && ((reqwindow->Flags) & WINDOWACTIVE)) ActivateWindow(mywindow); return 0; } /* remove quotes terminate string & return pointer to start */ char *tostring(ptr) char *ptr; { register char *s1, *s2; if(*ptr == '\0') return ptr; s1 = ptr; if (*ptr == '"') { while(*ptr++) { if(*ptr == '"') if(*(ptr+1) == '"') ptr++; else break; } /* Only 2 ways out: encounter an single " or hit \0. */ if (*ptr == '"') *ptr = '\0'; ptr = s2 = ++s1; while(*s2) { switch(*s2) { case '"': if(*(s2+1) == '"') *s1++ = *s2++; break; case '^': if(*(s2+1) == '^') *s1++ = *s2++; else *s1++ = ((*++s2) | ' ') - 96; break; default: *s1++ = *s2; break; } s2++; } *s1 = '\0'; return(ptr); } if (*s1 == '^') { *s1 = (*(s1+1)|' ')-96; *(s1+1) = '\0'; return(s1); } *(s1+1) = '\0'; return(s1); } /***************************** SCRIPT COMMANDS ********************/ 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); } return 0; } cmd_send(str) char *str; { register char *p = tostring(str); int i, len = strlen(p); if(p_echo) for(i = 0; i < len; i++) { doremote(*p); sendchar(*(p++)); } else sendstring(p); return 0; } cmd_wait(str) char *str; { int waitstrsize = sizeof(wait_string) - 1; str = tostring(str); strncpy(wait_string, str, waitstrsize); wait_string[waitstrsize] = '\0'; waitsize = strlen(wait_string); script_wait = WAIT_STRING; return 0; } cmd_on(str) char *str; { char *p; p = tostring(str); if( (onsize = strlen(p)) == 0) { on_string[0] = '\0'; on_cmd[0] = '\0'; } else { int onstrsize = sizeof(on_string) - 1, oncmdsize = sizeof(on_cmd) - 1, len; strncpy(on_string, p, onstrsize); on_string[onstrsize] = '\0'; p = next_wrd(p+onsize+1, &len); strncpy(on_cmd, p, oncmdsize); on_cmd[oncmdsize] = '\0'; } return 0; } 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((struct IORequest *)&Script_Timer.tr_node); return 0; } cmd_exit(option) char *option; { char *p; int l; if (doing_init) return 0; 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++)); } } return 0; } cmd_ext(parms) char *parms; { struct ExternalXfer *cexp; int i, j, len, nxfer, ci_strcmp(), cmdrc = CMDOK; char *p, temp[80], bound, *send, *dn; unsigned long mem_type = MEMF_PUBLIC | MEMF_CLEAR; parms = next_wrd(parms, &len); /* Step to start of display name */ if(len <= 0) { /* No next word...error */ strcpy(errmsg, "No display name for EXT command."); return CMDFAIL; } dn = parms; /* Remember start of display name */ parms += len; /* Step to end of word */ *(parms++) = '\0'; /* Mark end of display name and step beyond it */ if(len > DNMAXLEN) { *(dn+DNMAXLEN) = '\0'; sprintf(temp, "Display name more than %d chars, 1st %d used in EXT %s", DNMAXLEN, DNMAXLEN, dn); if(doing_init) { puts("Init:"); puts(temp); } else InfoMsg2Line("Script:", temp); cmdrc = CMDWARN; } parms = next_wrd(parms, &len); /* Step to start of SEND cmd */ /* Find a matching ExternalXfer structure based on display name */ for(i = 0; i < NumExts; i++) { if(ci_strcmp(ExtXfer[i]->downname, dn) == 0) if(len > 0) /* Replace this entry */ break; else { /* remove this entry from the list */ struct ExternalXfer *p = ExtXfer[i]; FreeMem(p->dispname, (long)(strlen(p->dispname)+1)); FreeMem(p->downname, (long)(strlen(p->downname)+1)); FreeMem(p->send, (long)(strlen(p->send)+1)); FreeMem(p->receive, (long)(strlen(p->receive)+1)); FreeMem(p, (long)sizeof(struct ExternalXfer)); ExtXfer[i] = NULL; for(j = i+1; j < NumExts; j++) ExtXfer[j-1] = ExtXfer[j]; NumExts--; if(!doing_init) InitFileItems(); return; } } nxfer = i; /* Remember index of match or where to put new... */ cexp = ExtXfer[nxfer]; /* ...and its location. */ bound = *(parms++); /* Remember starting quote for SEND command and step over it */ if((p = index(parms, bound)) == NULL) { sprintf(errmsg, "No ending quote for SEND cmd in EXT %s", dn); return CMDFAIL; } *p = '\0'; /* Replace ending quote with NULL */ send = parms; /* Remember start of SEND cmd... */ parms = ++p; /* ...and step over the NULL */ parms = next_wrd(parms, &len); /* Step to start of RECEIVE cmd */ if(len <= 0) { sprintf(errmsg, "No RECEIVE command for EXT %s", dn); return CMDFAIL; } bound = *(parms++); if((p =index(parms, bound)) == NULL) { sprintf(errmsg, "No ending quote for RECEIVE cmd in EXT %s", dn); return CMDFAIL; } *p = '\0'; if(cexp) { /* changing a current entry */ FreeMem(cexp->dispname, (long)(strlen(cexp->dispname)+1)); FreeMem(cexp->downname, (long)(strlen(cexp->downname)+1)); FreeMem(cexp->send, (long)(strlen(cexp->send)+1)); FreeMem(cexp->receive, (long)(strlen(cexp->receive)+1)); cexp->cmdkey = '\0'; } else if(nxfer >= EXTMAX) { sprintf(errmsg, "EXT %s would add more than %d external protocols", dn, EXTMAX); return CMDFAIL; } else { cexp = (struct ExternalXfer *) AllocMem((long)sizeof(struct ExternalXfer), mem_type); ExtXfer[nxfer] = cexp; NumExts++; } /* Initialize the new ExternalXfer entry. Leave room in dispname for ** a checkmark (2 character widths). */ len = strlen(dn); cexp->dispname = (char *)AllocMem((long)len+3, mem_type); strcpy(cexp->dispname, " "); strcat(cexp->dispname, dn); cexp->downname = (char *)AllocMem((long)len+1, mem_type); for(i = 0; i < len; i++) cexp->downname[i] = dn[i] | ' '; cexp->send = (char *)AllocMem((long)strlen(send)+1, mem_type); strcpy(cexp->send, send); cexp->receive = (char *)AllocMem((long)strlen(parms)+1, mem_type); strcpy(cexp->receive, parms); if(!doing_init) InitFileItems(); return cmdrc; } cmd_ks(file) char *file; { char name[MAXGADSTR], *p; if(file) strcpy(name, file); else name[0] = '\0'; if(file == NULL || *file == '\0' || !cmd_from_script) { req("Kermit Send:",name,1); p = name; if(file && !cmd_from_script) strcpy(file, name); } else p = file; multi_xfer(p, doksend, 1); return CMDOK; } cmd_kr(file) char *file; { char name[80]; name[0] = '\0'; multi_xfer(name, dokreceive, 0); return CMDOK; } cmd_kg(file) char *file; { char name[MAXGADSTR], *p; if(file) strcpy(name, file); else name[0] = '\0'; server = TRUE; if(file == NULL || *file == '\0' || !cmd_from_script) { req("Kermit GET remote file(s):", name, 1); p = name; if(file && !cmd_from_script) strcpy(file, name); } else p = file; multi_xfer(p, dokreceive, 0); return CMDOK; } cmd_kb() { saybye(); return CMDOK; } cmd_recf(file) char *file; { int cmdrc = CMDOK; switch(p_xproto) { case 0: /* Ascii */ do_capture(file); break; case 1: /* Xmodem */ case 2: /* XmodemCRC */ if(p_parity > 0) { InfoMsg1Line("Parity setting prevents XMODEM receive."); break; } cmd_xr(file); break; case 3: /* Kermit */ cmd_kr(file); break; default: if(p_xproto > MODEMAX + NumExts - 1) cmd_kr(file); else cmdrc = do_ext(ExtXfer[p_xproto-MODEMAX], ExtXfer[p_xproto-MODEMAX]->receive, file); } return cmdrc; } cmd_sendf(file) char *file; { int cmdrc = CMDOK; switch(p_xproto) { case 0: /* Ascii */ do_send(file); break; case 1: /* Xmodem */ case 2: /* XmodemCRC */ if(p_parity > 0) { InfoMsg1Line("Parity setting prevents XMODEM send."); cmdrc = CMDFAIL; break; } cmd_xs(file); break; case 3: /* Kermit */ cmd_ks(file); break; default: if(p_xproto > MODEMAX + NumExts - 1) cmd_ks(file); else cmdrc = do_ext(ExtXfer[p_xproto-MODEMAX], ExtXfer[p_xproto-MODEMAX]->send, file); } return cmdrc; } cmd_xs(file) char *file; { char name[MAXGADSTR], *p; if(file) strcpy(name, file); else name[0] = '\0'; if(file == NULL || *file == '\0' || !cmd_from_script) { req("Xmodem Send:",name,1); p = name; if(file && !cmd_from_script) strcpy(file, name); } else p = file; multi_xfer(p, XMODEM_Send_File, 1); return CMDOK; } cmd_xr(file) char *file; { char name[MAXGADSTR], *p; if(file) strcpy(name, file); else name[0] = '\0'; if(file == NULL || *file == '\0' || !cmd_from_script) { req("Xmodem Receive:",name,1); p = name; if(file && !cmd_from_script) strcpy(file, name); } else p = file; multi_xfer(p, XMODEM_Read_File, 1); return CMDOK; } cmd_cd(name) char *name; { set_dir(name); return CMDOK; } cmd_sb(str) char *str; { sendbreak(); return CMDOK; } cmd_baud(rate) char *rate; { int i = atoi(rate), cmdrc = CMDOK; switch( i ) { case 300: case 1200: case 2400: case 4800: case 9600: if (doing_init) p_baud = i; else setserbaud(i, TRUE); break; default: strcpy(errmsg, "Invalid baud rate: "); strcat(errmsg, rate); cmdrc = CMDFAIL; break; } return cmdrc; } 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: strcpy(errmsg, "Init: invalid parity: "); strcat(errmsg, par); return CMDFAIL; } p_parity = i; if (doing_init == 0) redocomm(); return CMDOK; } #if AREXX cmd_rx(cmd) char *cmd; { int cmdrc = CMDOK, ret = do_rx(cmd, implied_rexx); char *msg = NULL; errmsg[0] = '\0'; if(ret) { cmdrc = CMDFAIL; if(doing_init) printf("Init:\n%s\n", rexxerrmsgs[ret]); else InfoMsg2Line("Script:", rexxerrmsgs[ret]); } return cmdrc; } #else cmd_rx(cmd) char *cmd; { char *msg = "AREXX not compiled into this version."; if(doing_init) printf("Init:\n%s\n", msg); else InfoMsg2Line("Script:", msg); return CMDFAIL; } #endif cmd_bt(breaklength) char *breaklength; { p_break = atol(breaklength); if (doing_init) return CMDOK; AbortIO((struct IORequest *)Read_Request); Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit); WaitIO((struct IORequest *)Read_Request); Read_Request->io_BrkTime = Write_Request->io_BrkTime = p_break; setparams(); return CMDOK; } cmd_kmaxpk(pks) char *pks; { int i = atoi(pks), cmdrc = CMDOK; if(i <= MAXLONGPKS) p_kmaxpack = i; else { sprintf(errmsg, "Kermit packet size too big: %d", pks); cmdrc = CMDFAIL; } return cmdrc; } cmd_mode(tmode) char *tmode; { switch (*tmode|' ') { case 'i': p_mode = 0; break; case 'c': p_mode = 1; break; default: strcpy(errmsg, "Init: invalid transfer mode: "); strcat(errmsg, tmode); return CMDFAIL; } if (doing_init == 0) redocomm(); return CMDOK; } cmd_as(file) char *file; { do_send(file); return CMDOK; } cmd_cap(file) char *file; { do_capture(file); return CMDOK; } cmd_beep(dummy) char *dummy; { if (p_volume == 0) DisplayBeep(NULL); else { BeginIO((struct IORequest *)&Audio_Request); WaitIO((struct IORequest *)&Audio_Request); } return CMDOK; } 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; } } cmd_ac(par) char *par; { setvar(par,0,&p_autochop); if (doing_init == 0) redoutil(); return CMDOK; } cmd_echo(par) char *par; { setvar(par,0,&p_echo); if (doing_init == 0) redoutil(); return CMDOK; } cmd_wrap(par) char *par; { setvar(par,0,&p_wrap); if (doing_init == 0) redoutil(); return CMDOK; } cmd_share(parm) char *parm; { int oldval = p_shared; setvar(parm, 0, &p_shared); if(Read_Request && (oldval ^ p_shared)) { /* Port is going from shared->exclusive or vice-versa. Close it and ** re-open */ if(!CheckIO((struct IORequest *)Read_Request)) AbortIO((struct IORequest *)Read_Request); Wait (1L <mp_SigBit); WaitIO((struct IORequest *)Read_Request); CloseDevice((struct IORequest *)Read_Request); if(p_shared) Read_Request->io_SerFlags |= SERF_SHARED; else Read_Request->io_SerFlags &= (-1L ^ SERF_SHARED); if(OpenDevice(mysername,(LONG)p_unit,(struct IORequest *)Read_Request,NULL)) cleanup("Can't re-open Read device",0); InitCommItems(); setparams(); } return CMDOK; } cmd_xbeep(par) char *par; { setvar(par,0,&p_xbeep); if (doing_init == 0) redoutil(); return CMDOK; } cmd_xproto(par) char *par; { int i, len, save, cmdrc = CMDOK; next_wrd(par, &len); p_xproto = MODEMAX + 1; /* Establish an out of bounds default */ if(len) { par[len] = '\0'; /* downcase the parameter */ for(i = 0; i < len; i++) par[i] |= ' '; for(i = 0; i < MODEMAX; i++) if(strcmp(par, &(*(xprotos[i]))) == 0) { p_xproto = i; break; } } if(p_xproto >= MODEMAX) { /* Not a built-in protocol...check the defined external protocols */ p_xproto = 0; if(len > DNMAXLEN) { save = *(par+DNMAXLEN); *(par+DNMAXLEN) = '\0'; } for(i = 0; i < NumExts; i++) { if(strcmp(par, ExtXfer[i]->downname) == 0) { p_xproto = MODEMAX + i; break; } } if(p_xproto == 0) { p_xproto = MODEMAX - 1; if(len > DNMAXLEN) *(par+DNMAXLEN) = save; sprintf(errmsg, "XPROTO beginning \"%.10s\" unknown, %s used", par, &(*(xprotos[p_xproto]))); cmdrc = CMDFAIL; } } if(!doing_init) redofile(); return cmdrc; } cmd_numkey(par) char *par; { setvar(par,1,&p_keyapp); if (doing_init == 0) redoutil(); return CMDOK; } cmd_appcur(par) char *par; { setvar(par,0,&p_curapp); if (doing_init == 0) redoutil(); return CMDOK; } cmd_swap(par) char *par; { setvar(par,0,&p_bs_del); if (doing_init == 0) redoutil(); /* Calls InitUtilItems which does swap_bs_del() */ else { swap_bs_del(); /* Setup keys[] properly... */ swap_bs_del(); /* ...for new mode */ } return CMDOK; } cmd_bkg(par) char *par; { setvar(par,2,&p_background); return CMDOK; } cmd_bold(par) char *par; { setvar(par,2,&p_bold); return CMDOK; } cmd_buf(par) char *par; { setvar(par,3,&p_buffer); return CMDOK; } cmd_cursor(par) char *par; { setvar(par,2,&p_cursor); return CMDOK; } cmd_depth(par) char *par; { setvar(par,3,&p_depth); return CMDOK; } cmd_device(par) char *par; { int len, cmdrc = CMDOK; char temp[80]; next_wrd(par, &len); if(len > SERNAMESIZE) { printf(temp, "Init:\nDevice parm too long, %s used", SERIALNAME); strcpy(mysername, SERIALNAME); cmdrc = CMDFAIL; } else strcpy(mysername, par); return cmdrc; } cmd_display(str) char *str; { register char *p; for(p = tostring(str); *p; p++) doremote(*p); return CMDOK; } cmd_fore(par) char *par; { setvar(par,2,&p_foreground); return CMDOK; } #if AREXX /* This routine *depends* on the fact that the FORWARD command is only ** valid from AREXX. It then assumes that it can open RXSNAME. **/ cmd_fwd(par) char *par; { int i; if(ForwardPortName != NULL) { FreeMem(ForwardPortName, (LONG)strlen(ForwardPortName) + 1); ForwardPortName = NULL; } forwarding = 0; if(RexxSysBase == NULL) { RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME, 0L); if( (i = makerexxport()) != 0) { strcpy(errmsg, rexxerrmsgs[i]); return CMDFAIL; } } if(par && *par) { if(ForwardPortName = AllocMem((LONG)strlen(par)+1, MEMF_PUBLIC | MEMF_CLEAR)) { strcpy(ForwardPortName, par); forwarding = 1; } else { strcpy(errmsg, "Can't allocate memory for an AREXX forward port"); return CMDFAIL; } } return CMDOK; } #else cmd_fwd(par) { return CMDFAIL; } #endif /* AREXX */ cmd_font(par) char *par; { char temp[80]; int len, cmdrc = CMDOK; next_wrd(par, &len); temp[0] = '\0'; /* myfontname has been initialized from p_font in InitDefaults() in ** init.c */ if(!len) { sprintf(temp, "Init:\nNo font specified, \"%s\" used", myfontname); cmdrc = CMDWARN; } else { if(*par && len) { if(len < MAXFONTVARLEN) { par[len] = '\0'; strcpy(myfontname, par); strcat(myfontname,FONTSUFFIX); } else { sprintf(temp, "Init:\nFont specification too long, \"%s\" used", myfontname); cmdrc = CMDWARN; } } } myattr.ta_Name = (STRPTR)myfontname; if(*temp) puts(temp); return cmdrc; } cmd_fonts(par) char *par; { char temp[80]; int len, size, cmdrc = CMDOK; next_wrd(par, &len); temp[0] = '\0'; /* myfontname has been initialized from p_font in InitDefaults() in ** init.c */ if(!len) { strcpy(temp, "Init:\nNo font size specified, \"8\" used"); cmdrc = CMDWARN; } else { if(*par && len) { size = atoi(par); if(size > 0) myattr.ta_YSize = size; else { myattr.ta_YSize = 8; sprintf(temp, "Init:\nFont size \"%s\" invalid, \"8\" used", par); cmdrc = CMDWARN; } } } if(*temp) puts(temp); return cmdrc; } cmd_inter(par) char *par; { if(strcmp(par, "asis") == 0) p_interlace = 2; else setvar(par,0,&p_interlace); return CMDOK; } cmd_mouse(par) char *par; { switch (par[0]|' ') { case 'b': p_mouse_up = p_mouse_down = 1; /* send both */ break; case 'o': p_mouse_up = p_mouse_down = 0; /* mouse off */ break; case 'u': p_mouse_up = 1; /* up only */ p_mouse_down = 0; break; case 'd': /* down only */ p_mouse_down = 1; p_mouse_up = 0; break; default: return CMDFAIL; } return CMDOK; } cmd_msg(par) char *par; { register char *p, *s; int newline = 1; /* Whether we need to scroll */ for(s = p = tostring(par); *p; p++) { if(*p == '\n') { *p = '\0'; InfoMsgNoScroll(s); ScrollInfoMsg(1); newline = 0; s = p + 1; } else if(*p == '\r') { *p = '\0'; InfoMsgNoScroll(s); newline = 0; s = p + 1; } else newline = 1; } if(*s) InfoMsgNoScroll(s); if(newline) ScrollInfoMsg(1); return CMDOK; } cmd_lines(par) char *par; { setvar(par,3,&p_lines); return CMDOK; } cmd_screen(par) char *par; { if ((par[0]|' ') == 'w') p_screen = 0; else p_screen = 1; return CMDOK; } cmd_unit(par) char *par; { setvar(par, 3, &p_unit); return CMDOK; } cmd_wb(par) char *par; { setvar(par,0,&p_wbcolors); return CMDOK; } 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] != ' ') && (p[i] != '\t'); 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 ** shortcut 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] == ' ') || (p[l] == '\t')) ; l++) ; if(p[l]) *(shortkeys[i].pos) = p[l]; else *(shortkeys[i].pos) = ' '; return CMDOK; } } /* Not a "normal" item so try an ExternalXfer item */ p = next_wrd(par, &l); if(l > 0) { *(p+l) = '\0'; for(i = 0; i < NumExts; i++) if(strcmp(p, ExtXfer[i]->downname) == 0) { p = next_wrd(p+l+1, &l); if(l <= 0) break; ExtXfer[i]->cmdkey = *p; return CMDOK; } } sprintf(errmsg, "Unknown shortcut: %s", par); return CMDFAIL; } cmd_key(par) char *par; { int i; if (sscanf(par,"%x",&i) == 1) p_keyscript = (char)(i & 0x7f); return CMDOK; } cmd_volume(par) char *par; { setvar(par,3,&p_volume); return CMDOK; } cmd_conv(par) char *par; { setvar(par,0,&p_convert); if (doing_init == 0) redoutil(); return CMDOK; } 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(*par == 'm') { /* Mouse prefix */ p_f[10] = malloc(strlen(s) + 1); strcpy(p_f[10], s); } else 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); } } return CMDOK; } cmd_null(dummy) char *dummy; { return CMDOK; } /* Case-insensitive strcmp() */ ci_strcmp(p1, p2) char *p1, *p2; { while( *p1 && ((*p1 | ' ') == (*p2 | ' ')) ) { ++p1; ++p2; } return(*p1 != *p2); } do_ext(exp, pgmname, file) struct ExternalXfer *exp; char *pgmname, *file; { char *local = "@LOCAL", *remote = "@REMOTE", *command, localfn[MAXGADSTR], remotefn[MAXGADSTR], *p, *p1; int len = 0, locallen = strlen(local), remotelen = strlen(remote); if(file) strcpy(localfn, file); else localfn[0] = '\0'; remotefn[0] = '\0'; /* Get the initial length of the command then go through the user's ** command string looking for @LOCAL and @REMOTE. When we encounter one of ** these strings then, if we don't already have the appropriate filename, ** we'll put up a requester asking for it. Whether we put up the requester ** or not we must still account for the length of the replacement filename ** so that when we AllocMem() for the command we'll only get what we need. */ len = strlen(pgmname) + 1; for(p = pgmname; *p; p++) { if(*p == '@') if(strncmp(p+1, local+1, locallen-1) == 0) { if(!cmd_from_script || localfn[0] == '\0') req("Local file name:", localfn, 1); if(!localfn[0]) /* No filename specified */ return CMDFAIL; if(file && !cmd_from_script) strcpy(file, localfn); len += strlen(localfn); len -= locallen; p += locallen; } else if(strncmp(p+1, remote+1, remotelen-1) == 0) { req("Remote file name:", remotefn, 1); if(!remotefn[0]) /* No filename specified */ return CMDFAIL; len += strlen(remotefn); len -= remotelen; p += remotelen; } } /* for p = pgmname */ /* Allocate space for the command and copy the command string to it ** replacing @LOCAL and @REMOTE with localfn and remotefn, respectively */ command = AllocMem((long)len, MEMF_PUBLIC | MEMF_CLEAR); if(localfn[0] || remotefn[0]) { for(p = pgmname, p1 = p; *p; p++) { if(strncmp(p, local, locallen) == 0) { strncat(command, p1, p - p1); strcat(command, localfn); p += locallen; p1 = p; } else if(strncmp(p, remote, remotelen) == 0) { strncat(command, p1, p - p1); strcat(command, remotefn); p += remotelen; p1 = p; } } strcat(command, p1); /* Don't forget the tail of the command! */ } else strcpy(command, pgmname); /* Close down VT100's use of the serial port */ if(!CheckIO((struct IORequest *)Read_Request)) AbortIO((struct IORequest *)Read_Request); Wait (1L <mp_SigBit); WaitIO((struct IORequest *)Read_Request); if(!p_shared) CloseDevice((struct IORequest *)Read_Request); Execute(command, 0L, 0L); /* Invoke the external xfer pgm */ FreeMem(command, (long)len); if(!p_shared && OpenDevice(mysername,(LONG)p_unit,(struct IORequest *)Read_Request,NULL)) cleanup("Can't re-open Read device",0); setparams(); return CMDOK; }