home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff330.lzh / Vt100 / Src.lzh / Src / script.c < prev    next >
C/C++ Source or Header  |  1990-03-01  |  42KB  |  1,815 lines

  1. static char rcsid[] = "$RCSfile: script.c,v $ $Revision: 1.5 $";
  2.  
  3. /*************************************************************
  4.  * vt100 terminal emulator - Script file support
  5.  *                :ts=8
  6.  *
  7.  * $Log:    script.c,v $
  8.  * Revision 1.5  89/12/14  20:32:10  acs
  9.  * Wasn't beeping after a transfer using external protocols.
  10.  * 
  11.  * Revision 1.4  89/12/11  20:35:04  acs
  12.  * 1) do_script_cmd(): if(CmdFromRexx) should return a value.  Thanks to
  13.  *    William Dimm (wdimm@lehi3b15.csee.Lehigh.EDU).
  14.  * 2) cmd_ext(): After successfully deleting an external protocol it should
  15.  *    return CMDOK.  Thanks again, William!
  16.  * 3) Displaynames for external protocols no longer need 2 spaces before
  17.  *    the name.
  18.  * 
  19.  * Revision 1.3  89/11/02  10:27:06  acs
  20.  * New command: STRIP which will strip parity from data destined for
  21.  * display.
  22.  * 
  23.  * Revision 1.2  89/11/01  15:32:54  acs
  24.  * 1) Make cmd_from_script accessible to other source modules.
  25.  * 2) Add RCS id and change log.
  26.  * 
  27.  *    v2.9 ACS - Add support for font size, external transfer program
  28.  *           support, new ASIS option to LACE cmd and AREXX support.
  29.  *    v2.8a 880331 ACS - Allow comments on XPROTO and FONT.
  30.  *    v2.7 870825 ACS - Wait for the reply from AbortIO().
  31.  *              Use the *InfoMsg*() routines in window.c.  Provide
  32.  *              for multiple script files on command line
  33.  *              (companion to the changes in init.c).  Add the
  34.  *              ability to set shortcuts from init file.
  35.  *    v2.6 870227 DBW - bug fixes for all the stuff in v2.5
  36.  *    v2.5 870214 DBW - more additions (see readme file)
  37.  *    v2.4 861214 DBW - lots of fixes/additions (see readme file)
  38.  *    v2.3 861101 DBW - minor bug fixes
  39.  *    v2.2 861012 DBW - more of the same
  40.  *    v2.1 860915 DBW - new features (see README)
  41.  *         860901 ACS - Added BAUD, PARITY and WORD commands & handling
  42.  *         860823 DBW - Integrated and rewrote lots of code
  43.  *         860815 Steve Drew: Initial version written of SCRIPT.C
  44.  *    v2.0 860809 DBW - Major rewrite
  45.  *    v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes
  46.  *    v1.0 860712 DBW - First version released
  47.  *
  48.  *************************************************************/
  49.  
  50. #include "vt100.h"
  51.  
  52. #define DNMAXLEN    9
  53.  
  54. extern struct MsgPort *mySerPort;    /* in vt100.c */
  55.  
  56. struct COMMAND {
  57.     int (*func)();
  58.     char *cname;
  59.     int    minlen;
  60.     int    validfrom;
  61. };
  62.  
  63. #define INIT        1
  64. #define SCRIPT        2
  65. #define NONREXX        4
  66. #define REXXONLY    8
  67.  
  68. struct LABEL  {
  69.     struct LABEL *next;
  70.     char *name;
  71.     long pos;
  72. };
  73.  
  74. extern long atol();
  75.  
  76. #if MANX
  77. extern char *index();
  78. #endif    /* MANX */
  79.  
  80. #if LATTICE
  81. #define index(a,b) stpchr(a,b)
  82. #endif    /* LATTICE */
  83.  
  84. struct SHORT_CUTS {
  85.     char *cname;
  86.     char *pos;
  87. };
  88.     
  89. /*   Following variables are set up in init.c's InitDefaults.  They tell
  90. ** us if there are any other script files listed on the command line so
  91. ** that we can execute them when a prior script is done.  */
  92.  
  93. extern int script_files_todo;
  94. extern char **script_files;
  95.  
  96. /****************  globals  needed  ******************/
  97.  
  98. char        on_string[20];         /* string to match on for on cmd     */
  99. char        wait_string[20];     /* string to match of for wait cmd  */
  100. char        golabel[20];         /* label we are looking for in goto */
  101. char        on_cmd[20];         /* command to execute when on matchs*/
  102. int        onsize;             /* size of on_string         */
  103. int        waitsize;         /* size of wait_string         */
  104. int        onpos;             /* position in on string for search */
  105. int        waitpos;         /* pos in wait_string for search     */
  106. int        on_match;         /* flag set while doing on_cmd     */
  107. FILE        *sf = NULL;         /* file pointer for script file     */
  108. struct LABEL    *lbase = NULL;         /* will point to first label     */
  109. struct LABEL    *labels;         /* current label pointer         */
  110. char        errmsg[80];         /* Error msg from routines         */
  111. #if AREXX
  112. int        implied_rexx;        /* cmd_rx() invoked as impled cmd     */
  113. #endif /* AREXX */
  114.  
  115. /************************ command table *********************************/
  116. static struct COMMAND commands[] = {
  117. cmd_appcur,    "appcursor",    3, INIT|SCRIPT,    /* turn app. cursor on/off    */
  118. cmd_as,        "ascii",    3, SCRIPT,    /* ascii send            */
  119. cmd_ac,        "autochop",    3, INIT|SCRIPT,    /* XMODEM autochop        */
  120. cmd_bkg,    "background",    3, INIT,    /* set background color        */
  121. cmd_baud,    "baud",        3, INIT|SCRIPT,    /* Set Baud Rate        */
  122. cmd_beep,    "beep",        3, SCRIPT,    /* Beep                */
  123. cmd_bold,    "bold",        3, INIT,    /* set bold color        */
  124. cmd_bt,        "breaktime",    3, INIT|SCRIPT,    /* Set Break Time        */
  125. cmd_buf,    "buffer",    3, INIT,    /* set buffer size        */
  126. cmd_cap,    "capture",    3, SCRIPT,    /* ascii capture on/off        */
  127. cmd_cd,        "cd",        2, SCRIPT,    /* change directory        */
  128. cmd_conv,    "convert",    4, INIT|SCRIPT,    /* convert fn to lowercase    */
  129. cmd_cursor,    "cursor",    3, INIT,    /* set cursor color        */
  130. cmd_delay,    "delay",    3, SCRIPT,    /* delay amount of seconds    */
  131. cmd_depth,    "depth",    3, INIT,    /* set screen depth        */
  132. cmd_device,    "device",    3, INIT,    /* set serial device name    */
  133. cmd_display,    "display",    3, SCRIPT,    /* Display data on screen    */
  134. cmd_echo,    "echo",        3, INIT|SCRIPT,    /* turn echo on or off        */
  135. cmd_exit,    "exit",        3, INIT|SCRIPT|NONREXX,    /* exit script file    */
  136. cmd_ext,    "external",    4, INIT|SCRIPT,    /* external xfer pgms        */
  137. cmd_fnc,    "f",        1, INIT|SCRIPT,    /* define function key        */
  138. cmd_font,    "font",        3, INIT,    /* set font            */
  139. cmd_fonts,    "fontsize",    5, INIT,    /* set fontsize            */
  140. cmd_fore,    "foreground",    3, INIT,    /* set foreground color        */
  141. #if AREXX
  142. cmd_fwd,    "forward",    3, REXXONLY,    /* forward data to rexx        */
  143. #endif /* AREXX */
  144. cmd_goto,    "goto",        3, SCRIPT|NONREXX,/* goto label            */
  145. cmd_inter,    "interlace",    3, INIT,    /* interlace ON/OFF        */
  146. cmd_kb,        "kb",        2, SCRIPT,    /* kermit bye (for server)    */
  147. cmd_key,    "keyscript",    3, INIT|SCRIPT,    /* keyscript character        */
  148. cmd_kg,        "kg",        2, SCRIPT,    /* kermit get file        */
  149. cmd_kmaxpk,    "kmaxpack",    8, INIT|SCRIPT,    /* Kermit maximum packet size    */
  150. cmd_kr,        "kr",        2, SCRIPT,    /* kermit receive file        */
  151. cmd_ks,        "ks",        2, SCRIPT,    /* kermit send file        */
  152. cmd_lines,    "lines",    3, INIT,    /* num lines            */
  153. cmd_mode,    "mode",        3, INIT|SCRIPT,    /* KERMIT transfer mode        */
  154. cmd_mouse,    "mouse",    3, INIT|SCRIPT,    /* Mouse control        */
  155. cmd_msg,    "msg",        3, SCRIPT,    /* Display a message        */
  156. cmd_numkey,    "numkey",    6, INIT|SCRIPT,    /* turn numeric kpad on/off    */
  157. cmd_on,        "on",        2, SCRIPT,    /* on a 'string' do a cmd    */
  158. cmd_parity,    "parity",    6, INIT|SCRIPT,    /* Set Parity            */
  159. cmd_recf,    "recfile",    4, SCRIPT,    /* receive a file from host    */
  160. cmd_rx,        "rx",        2, INIT|SCRIPT,    /* Specific invocation        */
  161. cmd_sb,        "sb",        2, SCRIPT,    /* Send a break            */
  162. cmd_screen,    "screen",    3, INIT,    /* Screen WB/CUST        */
  163. cmd_send,    "send",        4, SCRIPT,    /* send string to host        */
  164. cmd_sendf,    "sendfile",    5, SCRIPT,    /* send a file to host        */
  165. cmd_share,    "shareserial",    5, INIT|SCRIPT,    /* ShareSerial device        */
  166. cmd_short,    "shortcut",    3, INIT,    /* Set shortcuts        */
  167. cmd_strip,    "strip",    2, INIT|SCRIPT,    /* Strip parity for display    */
  168. cmd_swap,    "swap",        4, INIT|SCRIPT,    /* Swap BS and DEL        */
  169. cmd_unit,    "unit",        4, INIT,    /* Unit of serial.device to use */
  170. cmd_volume,    "volume",    3, INIT,    /* set volume            */
  171. cmd_wait,    "wait",        4, SCRIPT|NONREXX, /* wait for a host string    */
  172. cmd_wb,        "wbcolors",    3, INIT,    /* use WB colors        */
  173. cmd_wrap,    "wrap",        4, INIT|SCRIPT,    /* turn wrap on or off        */
  174. cmd_xbeep,    "xbeep",    4, INIT|SCRIPT,    /* Beep at end of xfer        */
  175. cmd_xproto,    "xprotocol",    5, INIT|SCRIPT,    /* Xfer Protocol        */
  176. cmd_xr,        "xr",        2, SCRIPT,    /* xmodem receive file        */
  177. cmd_xs,        "xs",        2, SCRIPT,    /* xmodem send file        */
  178. cmd_null,    NULL,        0, 0     /* mark the end of the list    */
  179. };
  180.  
  181. char *xprotos[] = {    /* Order *must* be same as corresponding p_xproto values */
  182.     "ascii", "xmodem", "xmodemcrc", "kermit" };
  183.  
  184. /*   NB: The structures referenced in the structure may be found in
  185. ** init.c */
  186. extern struct filecmd {
  187.     char mo;    /* Mode            */
  188.     char se;    /* Send            */
  189.     char re;    /* Receive        */
  190.     char kg;    /* Kermit Get        */
  191.     char kb;    /* Kermit Bye        */
  192.     char ca;    /* Capture or Capturing */
  193.     char nl;
  194. } filecmd_chars;
  195.  
  196. extern struct mode_cmd {
  197.     char as;    /* ascii mode        */
  198.     char xm;    /* xmodem mode        */
  199.     char xmc;    /* xmodem crc mode    */
  200.     char ke;    /* kermit mode        */
  201.     char nl;
  202. } modecmd_chars;
  203.  
  204. extern struct baducmd {
  205.     char b03;    /* 0300            */
  206.     char b12;    /* 1200            */
  207.     char b24;    /* 2400            */
  208.     char b48;    /* 4800            */
  209.     char b96;    /* 9600            */
  210.     char bnl;
  211. } baudcmd_chars;
  212.  
  213. extern struct parcmd {
  214.     char no;    /* NOne            */
  215.     char ma;    /* MArk            */
  216.     char sp;    /* SPace        */
  217.     char ev;    /* EVen            */
  218.     char od;    /* ODd            */
  219.     char st;    /* STrip        */
  220.     char nl;
  221. } parcmd_chars;
  222.  
  223. extern struct commcmd {
  224.     char nl0;    /* Baud Sub-Item    */
  225.     char nl1;    /* Parity Sub-Item    */
  226.     char nl2;    /* Xfer mode Sub-Item    */
  227.     char sh;    /* Shared item        */
  228.     char nl;
  229. } commcmd_chars;
  230.  
  231. extern struct modcmd {
  232.     char im;    /* IMage        */
  233.     char tx;    /* TeXt            */
  234.     char cn;    /* CoNvert        */
  235.     char ac;    /* AutoChop        */
  236.     char nl;
  237. } modcmd_chars;
  238.  
  239. extern struct scrcmd {
  240.     char em;    /* Execute Macro    */
  241.     char ab;    /* Abort Macro        */
  242.     char rx;    /* AREXX Macro        */
  243.     char nl;
  244. } scrcmd_chars;
  245.  
  246. extern struct {
  247.     char sb;    /* Send Break    */
  248.     char hu;    /* Hang Up    */
  249.     char cd;    /* Change Dir    */
  250.     char cs;    /* Clear Screen    */
  251.     char ec;    /* ECho        */
  252.     char wr;    /* WRap        */
  253.     char nk;    /* Num Key    */
  254.     char ac;    /* App Cur    */
  255.     char bs;    /* BS<->DEL    */
  256.     char xb;    /* Beep at end of Xfer    */
  257.     char mu;    /* Mouse up events    */
  258.     char md;    /* Mouse down events    */
  259.     char nl;
  260. } utilcmd_chars;
  261.  
  262. static struct SHORT_CUTS shortkeys[] = {    /* Short-cut keys */
  263.     /* File items: */
  264.     "se", &(filecmd_chars.se),        /* Send file            */
  265.     "re", &(filecmd_chars.re),        /* Receive file            */
  266.     "kb", &(filecmd_chars.kb),        /* kermit bye (for server)    */
  267.     "kg", &(filecmd_chars.kg),        /* kermit get (for server)    */
  268.     "cap", &(filecmd_chars.ca),        /* Capture            */
  269.     /* Mode items:    */
  270.     "asc", &(modecmd_chars.as),        /* ascii mode            */
  271.     "xmc", &(modecmd_chars.xmc),    /* xmodemcrc mode        */
  272.     "xm", &(modecmd_chars.xm),        /* xmodem mode            */
  273.     "ke", &(modecmd_chars.ke),        /* kermit mode            */
  274.     /* Comm items:    */
  275.     "share", &(commcmd_chars.sh),    /* Shared            */
  276.     "300", &(baudcmd_chars.b03),    /* Set Baud Rate        */
  277.     "1200", &(baudcmd_chars.b12),    /* Set Baud Rate        */
  278.     "2400", &(baudcmd_chars.b24),    /* Set Baud Rate        */
  279.     "4800", &(baudcmd_chars.b48),    /* Set Baud Rate        */
  280.     "9600", &(baudcmd_chars.b96),    /* Set Baud Rate        */
  281.     "none", &(parcmd_chars.no),        /* Set Parity            */
  282.     "mark", &(parcmd_chars.ma),        /* Set Parity            */
  283.     "space", &(parcmd_chars.sp),    /* Set Parity            */
  284.     "even", &(parcmd_chars.ev),        /* Set Parity            */
  285.     "odd", &(parcmd_chars.od),        /* Set Parity            */
  286.     "strip", &(parcmd_chars.st),    /* Strip parity            */
  287.     "image", &(modcmd_chars.im),    /* KERMIT transfer mode        */
  288.     "text", &(modcmd_chars.tx),        /* KERMIT transfer mode        */
  289.     "convert", &(modcmd_chars.cn),    /* KERMIT transfer mode        */
  290.     "autochop", &(modcmd_chars.ac),    /* XMODEM autochop        */
  291.     /* Script items:    */
  292.     "execute", &(scrcmd_chars.em),    /* execute macro        */
  293.     "abort", &(scrcmd_chars.ab),    /* abort macro            */
  294.     "rx", &(scrcmd_chars.rx),        /* rexx macro            */
  295.     /* Util items: */
  296.     "sb", &(utilcmd_chars.sb),        /* send break            */
  297.     "hang", &(utilcmd_chars.hu),    /* hang up            */
  298.     "cd", &(utilcmd_chars.cd),        /* change directory        */
  299.     "clear", &(utilcmd_chars.cs),    /* clear screen            */
  300.     "ech", &(utilcmd_chars.ec),        /* turn echo on or off        */
  301.     "wrap", &(utilcmd_chars.wr),    /* turn wrap on or off        */
  302.     "numkey", &(utilcmd_chars.nk),    /* turn numeric kpad on/off    */
  303.     "app", &(utilcmd_chars.ac),        /* turn app. cursor on/off    */
  304.     "con", &(utilcmd_chars.bs),        /* convert bs to del        */
  305.     "swap", &(utilcmd_chars.bs),    /* Swap BS and DEL        */
  306.     "xbeep", &(utilcmd_chars.xb),    /* Beep at end of xfer        */
  307.     "mouseup", &(utilcmd_chars.mu),    /* Mouse up events        */
  308.     "mousedn", &(utilcmd_chars.md),    /* Mouse dn events        */
  309.     NULL, NULL
  310. };
  311.  
  312. int cmd_from_script;            /* != 0 iff cmd from a script    */
  313.  
  314.  
  315. /********************************************************************/
  316. /* checks char to see if match with on string or wait_string        */
  317. /* if on string match oncmd gets executed imediately,            */
  318. /* if wait_string match script_wait is set.                */
  319. /********************************************************************/
  320.  
  321. chk_script(c)
  322. char c;
  323. {
  324.     if (on_string[0] != '\0') {
  325.     if (on_string[onpos] == c) {
  326.         onpos++;
  327.         if (onpos == onsize) {
  328.         on_match = TRUE;
  329.         do_script_cmd(ONCOMMAND);
  330.         on_match = FALSE;
  331.         on_string[0] = '\0';
  332.         on_cmd[0] = '\0';
  333.         onpos = 0;
  334.         return(0);
  335.         }
  336.     }
  337.     else onpos = 0;
  338.     }
  339.     if (wait_string[0] != '\0') {
  340.        if (wait_string[waitpos] != c) {
  341.         waitpos = 0;
  342.         return(0);
  343.     }
  344.     waitpos++;
  345.     if (waitpos != waitsize) return(0);
  346.     wait_string[0] = '\0';
  347.     script_wait = FALSE;
  348.     }
  349. }
  350.  
  351. script_start(file)
  352. char *file;
  353. {
  354.     char *sfile = NULL;
  355.  
  356.     if (strlen(file) == 0 || *file == '#') return(0);
  357.     if ((sf = fopen(file, "r")) == NULL) {
  358.         sfile = AllocMem((LONG)(strlen(file)+3), MEMF_PUBLIC|MEMF_CLEAR);
  359.         strcpy(sfile, "S:");
  360.         strcat(sfile, file);
  361.         if((sf = fopen(sfile, "r")) == NULL) {
  362.         InfoMsg2Line("Can't open script file",file);
  363.         return(0);
  364.         }
  365.     }
  366.     script_on = TRUE;
  367.     script_wait = FALSE;
  368.     wait_string[0] = '\0';
  369.     on_string[0] = '\0';
  370.     on_match = FALSE;
  371.     lbase = NULL;
  372.     if(sfile)
  373.     FreeMem(sfile, (LONG)strlen(file)+3);
  374. }
  375.  
  376. /* return pointer to next word. set l to size of the word */
  377.  
  378. char *next_wrd(s,l)
  379. char *s;
  380. int *l;
  381. {
  382.     char *p;
  383.  
  384.     while(*s && (*s == ' ' || *s == '\t')) s++;
  385.     p = s;
  386.     while(*s && (*s != ' ' && *s != '\t')) s++;
  387.     *l = s-p;
  388.     return(p);
  389. }
  390.  
  391. exe_cmd(p,l)
  392. register char *p;
  393. int l;
  394. {
  395.     int i, l2, cmdrc = CMDOK;
  396.     register struct COMMAND *cmd;
  397.  
  398.     /* downcase the command */
  399.     for (i=0; i<l; i++) p[i] |= ' ';
  400.  
  401.     errmsg[0] = '\0';
  402.  
  403.     /* now search for it */
  404.     for (cmd = commands; cmd->func != cmd_null; cmd++) {
  405.     int validfrom = cmd->validfrom;
  406.  
  407.     if(*p != cmd->cname[0])
  408.         continue;
  409.  
  410.     l2 = strlen(cmd->cname);
  411.     if(l >= cmd->minlen && l <= l2
  412.       && strncmp(p, cmd->cname, l) == 0) {
  413.         if( (!doing_init && (validfrom == INIT))
  414.         ||  (((validfrom & NONREXX)  == NONREXX)  &&  CmdFromRexx)
  415.         ||  (((validfrom & REXXONLY) == REXXONLY) && !CmdFromRexx) )
  416.         return(CMDBS);
  417.  
  418.         cmd_from_script = 1;
  419.         cmdrc = (*(cmd->func))(next_wrd(p+l, &l));
  420.         cmd_from_script = 0;
  421.         if(errmsg[0])
  422.         if(doing_init) {
  423.             puts("Init:");
  424.             puts(errmsg);
  425.         } else
  426.             InfoMsg2Line("Script:", errmsg);
  427.         return(cmdrc);
  428.     }
  429.     }
  430. #if AREXX
  431.     if(implied_rexx == 0 && RexxSysBase != NULL) {
  432.     implied_rexx = 1;
  433.     cmdrc = cmd_rx(p);
  434.     implied_rexx = 0;
  435.     return(cmdrc);
  436.     }
  437. #endif /* AREXX */
  438.  
  439.     if (doing_init) {
  440.     puts("Init: unknown command:");
  441.     puts(p);
  442.     } else
  443.     InfoMsg2Line("Script - unknown command:",p);
  444.  
  445.     return(CMDNF);
  446. }
  447.  
  448. struct LABEL *find_label(lname)
  449. char *lname;
  450. {
  451.     struct LABEL *label;
  452.  
  453.     label = lbase;
  454.     while(label != NULL) {
  455.     if (strcmp(label->name, lname) == 0) return (label);
  456.     label = label->next;
  457.     }
  458.     return(NULL);
  459. }
  460.  
  461. do_script_cmd(stat)
  462. int stat;
  463. {
  464.     int len,l;
  465.     char line[256];
  466.     char *p;
  467.  
  468.     /* if ON command is matched and we were    */
  469.     /* doing a DELAY then abort the delay timer,*/
  470.     /* except if on_cmd was just a SEND.    */
  471.     if (stat == ONCOMMAND) {
  472.     strcpy(line,on_cmd);
  473.     p = next_wrd(line,&l);
  474.     if (*p != 's' && script_wait == WAIT_TIMER)  {
  475.         if(!CheckIO((struct IORequest *)&Script_Timer))
  476.         AbortIO((struct IORequest *)&Script_Timer);
  477.         Wait (1L << Script_Timer_Port->mp_SigBit);
  478.         WaitIO((struct IORequest *)&Script_Timer);
  479.  
  480.         /* script will proceed after on command    */
  481.         script_wait = FALSE;
  482.     }
  483.     exe_cmd(p,l);
  484.     return(0);
  485.     }
  486.     script_wait = FALSE;
  487.  
  488.     if(CmdFromRexx)
  489.     return 0;
  490.  
  491.     while(fgets(line,256,sf) != NULL) {
  492.        len = strlen(line);
  493.        line[--len] = '\0';
  494.        p = next_wrd(&line[0], &l);
  495.        if (*(p + l - 1) == ':') {        /* its a label */
  496.        *(p + l - 1) = '\0';
  497.        if (find_label(p) == NULL) {        /* it's a new label */
  498.         if (lbase == NULL)  {        /* it's the first label */
  499.             labels = lbase = (struct LABEL *)
  500.             malloc(sizeof (struct LABEL));
  501.         }
  502.         else {
  503.             labels->next = (struct LABEL *)
  504.             malloc(sizeof (struct LABEL));
  505.             labels = labels->next;
  506.         }
  507.         labels->pos  = ftell(sf);
  508.         labels->name = malloc(l);
  509.         labels->next = NULL;
  510.         strcpy(labels->name, p);
  511.         if (stat == GOTOLABEL && strcmp(p, golabel) == 0)
  512.               stat = NEXTCOMMAND;
  513.         }
  514.         p = next_wrd(p+l+1, &l);
  515.     }   /* end of it's a label */
  516.     if (stat == GOTOLABEL || *p == '#')
  517.         continue;
  518.     if (*p)
  519.         exe_cmd(p,l);
  520.     return(0);
  521.     }            /* end of while */
  522.     if (stat == GOTOLABEL)
  523.     InfoMsg2Line("Script: label not found:",golabel);
  524.     exit_script();
  525.     if(script_files_todo > 0) {
  526.     script_files_todo--;
  527.     script_start(*(script_files++));
  528.     }
  529. }
  530.  
  531. exit_script()
  532. {
  533.     if (script_wait == WAIT_TIMER) {    /* timer not done yet */
  534.     if(!CheckIO((struct IORequest *)&Script_Timer))
  535.         AbortIO((struct IORequest *)&Script_Timer); /* so abort it */
  536.     Wait (1L << Script_Timer_Port->mp_SigBit); /* Wait for the sig */
  537.     WaitIO((struct IORequest *)&Script_Timer); /* Get my reply back */
  538.     }
  539.     InfoMsg1Line("Script: terminated");
  540.     script_on = FALSE;
  541.     script_wait = TRUE;
  542.     on_match = FALSE;
  543.     wait_string[0] = '\0';
  544.     on_string[0] = '\0';
  545.     on_cmd[0] = '\0';
  546.     fclose(sf);
  547.     sf = NULL;
  548.     if (reqwinup && ((reqwindow->Flags) & WINDOWACTIVE))
  549.     ActivateWindow(mywindow);
  550.     return 0;
  551. }
  552.  
  553. /* remove quotes terminate string & return pointer to start */
  554.  
  555. char *tostring(ptr)
  556. char *ptr;
  557. {
  558.     register char *s1, *s2;
  559.  
  560.     if(*ptr == '\0')
  561.     return ptr;
  562.  
  563.     s1 = ptr;
  564.     if (*ptr == '"') {
  565.     while(*ptr++) {
  566.         if(*ptr == '"')
  567.         if(*(ptr+1) == '"')
  568.             ptr++;
  569.         else
  570.             break;
  571.     }
  572.     /*   Only 2 ways out: encounter an single " or hit \0. */
  573.     if (*ptr == '"')
  574.         *ptr = '\0';
  575.     ptr = s2 = ++s1;
  576.     while(*s2) {
  577.         switch(*s2) {
  578.         case '"':
  579.         if(*(s2+1) == '"')
  580.             *s1++ = *s2++;
  581.         break;
  582.         case '^':
  583.         if(*(s2+1) == '^')
  584.             *s1++ = *s2++;
  585.         else
  586.             *s1++ = ((*++s2) | ' ') - 96;
  587.         break;
  588.         default:
  589.         *s1++ = *s2;
  590.         break;
  591.         }
  592.         s2++;
  593.     }
  594.     *s1 = '\0';
  595.     return(ptr);
  596.     }
  597.     if (*s1 == '^') {
  598.     *s1 = (*(s1+1)|' ')-96;
  599.     *(s1+1) = '\0';
  600.     return(s1);
  601.     }
  602.     *(s1+1) = '\0';
  603.     return(s1);
  604. }
  605.  
  606. /***************************** SCRIPT COMMANDS ********************/
  607.  
  608. cmd_goto(lname)
  609. char *lname;
  610. {
  611.     struct LABEL *label;
  612.                 /* if on_cmd was a goto kill wait state */
  613.     if (on_match) { wait_string[0] = '\0'; script_wait = FALSE; }
  614.     if ((label = find_label(lname)) == NULL) {    /* is it forward */
  615.     strcpy(golabel,lname);
  616.     do_script_cmd(GOTOLABEL);
  617.     }
  618.     else {
  619.     fseek(sf,(long)(label->pos),0);
  620.     }
  621.     return 0;
  622. }
  623.  
  624. cmd_send(str)
  625. char *str;
  626. {
  627.     register char *p = tostring(str);
  628.     int i, len = strlen(p);
  629.  
  630.     if(p_echo)
  631.     for(i = 0; i < len; i++) {
  632.         doremote(*p);
  633.         sendchar(*(p++));
  634.     }
  635.     else
  636.     sendstring(p);
  637.     return 0;
  638. }
  639.  
  640. cmd_wait(str)
  641. char *str;
  642. {
  643.     int waitstrsize = sizeof(wait_string) - 1;
  644.  
  645.     str = tostring(str);
  646.     strncpy(wait_string, str, waitstrsize);
  647.     wait_string[waitstrsize] = '\0';
  648.     waitsize = strlen(wait_string);
  649.     script_wait = WAIT_STRING;
  650.     return 0;
  651. }
  652.  
  653. cmd_on(str)
  654. char *str;
  655. {
  656.    char *p;
  657.  
  658.     p = tostring(str);
  659.     if( (onsize = strlen(p)) == 0) {
  660.     on_string[0] = '\0';
  661.     on_cmd[0] = '\0';
  662.     } else {
  663.     int onstrsize = sizeof(on_string) - 1,
  664.         oncmdsize = sizeof(on_cmd) - 1,
  665.         len;
  666.  
  667.     strncpy(on_string, p, onstrsize);
  668.     on_string[onstrsize] = '\0';
  669.     p = next_wrd(p+onsize+1, &len);
  670.     strncpy(on_cmd, p, oncmdsize);
  671.     on_cmd[oncmdsize] = '\0';
  672.     }
  673.     return 0;
  674. }
  675.  
  676. cmd_delay(seconds)
  677. char *seconds;
  678. {
  679.     script_wait = WAIT_TIMER;
  680.     Script_Timer.tr_time.tv_secs = atoi(seconds);
  681.     Script_Timer.tr_time.tv_micro = 0;
  682.     SendIO((struct IORequest *)&Script_Timer.tr_node);
  683.     return 0;
  684. }
  685.  
  686. cmd_exit(option)
  687. char *option;
  688. {
  689.     char *p;
  690.     int  l;
  691.  
  692.     if (doing_init)
  693.     return 0;
  694.  
  695.     if (*option) {
  696.     p = next_wrd(option,&l);
  697.     *(p+l) = '\000';
  698.     if  (strcmp(p,"vt100") == 0 || strcmp(p,"VT100") == 0)
  699.         cleanup("Exit vt100 from script",0);
  700.     exit_script();
  701.     script_start(p);
  702.     }
  703.     else {
  704.     exit_script();
  705.     if(script_files_todo > 0) {
  706.         script_files_todo--;
  707.         script_start(*(script_files++));
  708.     }
  709.     }
  710.     return 0;
  711. }
  712.  
  713. cmd_ext(parms)
  714. char *parms;
  715. {
  716.     struct ExternalXfer *cexp;
  717.     int i, j, len, nxfer, ci_strcmp(), cmdrc = CMDOK;
  718.     char *p, temp[80], bound, *send, *dn;
  719.     unsigned long mem_type = MEMF_PUBLIC | MEMF_CLEAR;
  720.  
  721.     parms = next_wrd(parms, &len);    /* Step to start of display name */
  722.     if(len <= 0) {    /* No next word...error */
  723.     strcpy(errmsg, "No display name for EXT command.");
  724.     return CMDFAIL;
  725.     }
  726.  
  727.     dn = parms;        /* Remember start of display name        */
  728.     parms += len;    /* Step to end of word                */
  729.     *(parms++) = '\0';    /* Mark end of display name and step beyond it    */
  730.     if(len > DNMAXLEN) {
  731.     *(dn+DNMAXLEN) = '\0';
  732.     sprintf(temp, "Display name more than %d chars, 1st %d used in EXT %s",
  733.         DNMAXLEN, DNMAXLEN, dn);
  734.     if(doing_init) {
  735.         puts("Init:");
  736.         puts(temp);
  737.     } else
  738.         InfoMsg2Line("Script:", temp);
  739.     cmdrc = CMDWARN;
  740.     }
  741.  
  742.     parms = next_wrd(parms, &len);    /* Step to start of SEND cmd */
  743.  
  744.     /* Find a matching ExternalXfer structure based on display name */
  745.     for(i = 0; i < NumExts; i++) {
  746.     if(ci_strcmp(ExtXfer[i]->downname, dn) == 0)
  747.         if(len > 0)    /* Replace this entry */
  748.         break;
  749.         else {    /* remove this entry from the list */
  750.         struct ExternalXfer *p = ExtXfer[i];
  751.         FreeMem(p->dispname, (long)(strlen(p->dispname)+1));
  752.         FreeMem(p->downname, (long)(strlen(p->downname)+1));
  753.         FreeMem(p->send, (long)(strlen(p->send)+1));
  754.         FreeMem(p->receive, (long)(strlen(p->receive)+1));
  755.         FreeMem(p, (long)sizeof(struct ExternalXfer));
  756.         ExtXfer[i] = NULL;
  757.         for(j = i+1; j < NumExts; j++)
  758.             ExtXfer[j-1] = ExtXfer[j];
  759.         NumExts--;
  760.         if(!doing_init)
  761.             InitFileItems();
  762.         return CMDOK;
  763.         }
  764.     }
  765.     nxfer = i;            /* Remember index of match or where to put new... */
  766.     cexp = ExtXfer[nxfer];    /* ...and its location. */
  767.  
  768.     bound = *(parms++);    /* Remember starting quote for SEND command and step over it */
  769.     if((p = index(parms, bound)) == NULL) {
  770.     sprintf(errmsg, "No ending quote for SEND cmd in EXT %s", dn);
  771.     return CMDFAIL;
  772.     }
  773.     *p = '\0';        /* Replace ending quote with NULL */
  774.     send = parms;    /* Remember start of SEND cmd... */
  775.     parms = ++p;    /* ...and step over the NULL */
  776.  
  777.     parms = next_wrd(parms, &len);    /* Step to start of RECEIVE cmd */
  778.     if(len <= 0) {
  779.     sprintf(errmsg, "No RECEIVE command for EXT %s", dn);
  780.     return CMDFAIL;
  781.     }
  782.     bound = *(parms++);
  783.     if((p =index(parms, bound)) == NULL) {
  784.     sprintf(errmsg, "No ending quote for RECEIVE cmd in EXT %s", dn);
  785.     return CMDFAIL;
  786.     }
  787.     *p = '\0';
  788.  
  789.     if(cexp) {    /* changing a current entry */
  790.     FreeMem(cexp->dispname, (long)(strlen(cexp->dispname)+1));
  791.     FreeMem(cexp->downname, (long)(strlen(cexp->downname)+1));
  792.     FreeMem(cexp->send, (long)(strlen(cexp->send)+1));
  793.     FreeMem(cexp->receive, (long)(strlen(cexp->receive)+1));
  794.     cexp->cmdkey = '\0';
  795.     } else if(nxfer >= EXTMAX) {
  796.     sprintf(errmsg, "EXT %s would add more than %d external protocols",
  797.         dn, EXTMAX);
  798.     return CMDFAIL;
  799.     } else {
  800.     cexp = (struct ExternalXfer *)
  801.         AllocMem((long)sizeof(struct ExternalXfer), mem_type);
  802.     ExtXfer[nxfer] = cexp;
  803.     NumExts++;
  804.     }
  805.  
  806.     /* Initialize the new ExternalXfer entry.  Leave room in dispname for
  807.     ** a checkmark (2 character widths). */
  808.     len = strlen(dn);
  809.     cexp->dispname = (char *)AllocMem((long)len+1, mem_type);
  810.     strcpy(cexp->dispname, dn);
  811.     cexp->downname = (char *)AllocMem((long)len+1, mem_type);
  812.     for(i = 0; i < len; i++)
  813.     cexp->downname[i] = dn[i] | ' ';
  814.     cexp->send = (char *)AllocMem((long)strlen(send)+1, mem_type);
  815.     strcpy(cexp->send, send);
  816.     cexp->receive = (char *)AllocMem((long)strlen(parms)+1, mem_type);
  817.     strcpy(cexp->receive, parms);
  818.  
  819.     if(!doing_init)
  820.     InitFileItems();
  821.     return cmdrc;
  822. }
  823.  
  824. cmd_ks(file)
  825. char *file;
  826. {
  827.     char name[MAXGADSTR], *p;
  828.  
  829.     if(file)
  830.     strcpy(name, file);
  831.     else
  832.     name[0] = '\0';
  833.  
  834.     if(file == NULL || *file == '\0' || !cmd_from_script) {
  835.     req("Kermit Send:",name,1);
  836.     p = name;
  837.     if(file && !cmd_from_script)
  838.         strcpy(file, name);
  839.     } else
  840.     p = file;
  841.     multi_xfer(p, doksend, 1);
  842.     return CMDOK;
  843. }
  844.  
  845. cmd_kr(file)
  846. char *file;
  847. {
  848.     char name[80];
  849.  
  850.     name[0] = '\0';
  851.  
  852.     multi_xfer(name, dokreceive, 0);
  853.     return CMDOK;
  854. }
  855.  
  856. cmd_kg(file)
  857. char *file;
  858. {
  859.     char name[MAXGADSTR], *p;
  860.  
  861.     if(file)
  862.     strcpy(name, file);
  863.     else
  864.     name[0] = '\0';
  865.  
  866.     server = TRUE;
  867.     if(file == NULL || *file == '\0' || !cmd_from_script) {
  868.     req("Kermit GET remote file(s):", name, 1);
  869.     p = name;
  870.     if(file && !cmd_from_script)
  871.         strcpy(file, name);
  872.     } else
  873.     p = file;
  874.     multi_xfer(p, dokreceive, 0);
  875.     return CMDOK;
  876. }
  877.  
  878. cmd_kb()
  879. {
  880.     saybye();
  881.     return CMDOK;
  882. }
  883.  
  884. cmd_recf(file)
  885. char *file;
  886. {
  887.     int cmdrc = CMDOK;
  888.  
  889.     switch(p_xproto) {
  890.     case 0:    /* Ascii */
  891.     do_capture(file);
  892.     break;
  893.     case 1:    /* Xmodem */
  894.     case 2:    /* XmodemCRC */
  895.     if(p_parity > 0) {
  896.         InfoMsg1Line("Parity setting prevents XMODEM receive.");
  897.         break;
  898.     }
  899.     cmd_xr(file);
  900.     break;
  901.     case 3:    /* Kermit */
  902.     cmd_kr(file);
  903.     break;
  904.     default:
  905.     if(p_xproto > MODEMAX + NumExts - 1)
  906.         cmd_kr(file);
  907.     else
  908.         cmdrc = do_ext(ExtXfer[p_xproto-MODEMAX],
  909.                ExtXfer[p_xproto-MODEMAX]->receive,
  910.                file);
  911.     }
  912.     return cmdrc;
  913. }
  914.  
  915. cmd_sendf(file)
  916. char *file;
  917. {
  918.     int cmdrc = CMDOK;
  919.  
  920.     switch(p_xproto) {
  921.     case 0:    /* Ascii */
  922.     do_send(file);
  923.     break;
  924.     case 1:    /* Xmodem */
  925.     case 2:    /* XmodemCRC */
  926.     if(p_parity > 0) {
  927.         InfoMsg1Line("Parity setting prevents XMODEM send.");
  928.         cmdrc = CMDFAIL;
  929.         break;
  930.     }
  931.     cmd_xs(file);
  932.     break;
  933.     case 3:    /* Kermit */
  934.     cmd_ks(file);
  935.     break;
  936.     default:
  937.     if(p_xproto > MODEMAX + NumExts - 1)
  938.         cmd_ks(file);
  939.     else
  940.         cmdrc = do_ext(ExtXfer[p_xproto-MODEMAX],
  941.                ExtXfer[p_xproto-MODEMAX]->send,
  942.                file);
  943.     }
  944.     return cmdrc;
  945. }
  946.  
  947. cmd_xs(file)
  948. char *file;
  949. {
  950.     char name[MAXGADSTR], *p;
  951.  
  952.     if(file)
  953.     strcpy(name, file);
  954.     else
  955.     name[0] = '\0';
  956.  
  957.     if(file == NULL || *file == '\0' || !cmd_from_script) {
  958.     req("Xmodem Send:",name,1);
  959.     p = name;
  960.     if(file && !cmd_from_script)
  961.         strcpy(file, name);
  962.     } else
  963.     p = file;
  964.     multi_xfer(p, XMODEM_Send_File, 1);
  965.     return CMDOK;
  966. }
  967.  
  968. cmd_xr(file)
  969. char *file;
  970. {
  971.     char name[MAXGADSTR], *p;
  972.  
  973.     if(file)
  974.     strcpy(name, file);
  975.     else
  976.     name[0] = '\0';
  977.  
  978.     if(file == NULL || *file == '\0' || !cmd_from_script) {
  979.     req("Xmodem Receive:",name,1);
  980.     p = name;
  981.     if(file && !cmd_from_script)
  982.         strcpy(file, name);
  983.     } else
  984.     p = file;
  985.     multi_xfer(p, XMODEM_Read_File, 1);
  986.     return CMDOK;
  987. }
  988.  
  989. cmd_cd(name)
  990. char *name;
  991. {
  992.     set_dir(name);
  993.     return CMDOK;
  994. }
  995.  
  996. cmd_sb(str)
  997. char *str;
  998. {
  999.     sendbreak();
  1000.     return CMDOK;
  1001. }
  1002.  
  1003. cmd_baud(rate)
  1004. char *rate;
  1005. {
  1006.     int i = atoi(rate),
  1007.     cmdrc = CMDOK;
  1008.  
  1009.     switch( i ) {
  1010.     case  300:
  1011.     case 1200:
  1012.     case 2400:
  1013.     case 4800:
  1014.     case 9600:
  1015.     if (doing_init) p_baud = i;
  1016.     else        setserbaud(i, TRUE);
  1017.     break;
  1018.  
  1019.     default:
  1020.     strcpy(errmsg, "Invalid baud rate: ");
  1021.     strcat(errmsg, rate);
  1022.     cmdrc = CMDFAIL;
  1023.     break;
  1024.     }
  1025.     return cmdrc;
  1026. }
  1027.  
  1028. cmd_parity(par)
  1029. char *par;
  1030. {
  1031.     int i;
  1032.  
  1033.     switch( *par|' ' ) {
  1034.     case 'n': i =  0; break;
  1035.     case 'm': i =  1; break;
  1036.     case 's': i =  2; break;
  1037.     case 'e': i =  3; break;
  1038.     case 'o': i =  4; break;
  1039.  
  1040.     default:
  1041.     strcpy(errmsg, "Init: invalid parity: ");
  1042.     strcat(errmsg, par);
  1043.     return CMDFAIL;
  1044.     }
  1045.     p_parity = i;
  1046.     if (doing_init == 0)
  1047.     redocomm();
  1048.     return CMDOK;
  1049. }
  1050.  
  1051. #if AREXX
  1052. cmd_rx(cmd)
  1053. char    *cmd;
  1054. {
  1055.     int    cmdrc = CMDOK,
  1056.     ret = do_rx(cmd, implied_rexx);
  1057.     char *msg = NULL;
  1058.  
  1059.     errmsg[0] = '\0';
  1060.     if(ret) {
  1061.     cmdrc = CMDFAIL;
  1062.     if(doing_init)
  1063.         printf("Init:\n%s\n", rexxerrmsgs[ret]);
  1064.     else
  1065.         InfoMsg2Line("Script:", rexxerrmsgs[ret]);
  1066.     }
  1067.     return cmdrc;
  1068. }
  1069. #else
  1070. cmd_rx(cmd)
  1071. char    *cmd;
  1072. {
  1073.     char *msg = "AREXX not compiled into this version.";
  1074.  
  1075.     if(doing_init)
  1076.     printf("Init:\n%s\n", msg);
  1077.     else
  1078.     InfoMsg2Line("Script:", msg);
  1079.     return CMDFAIL;
  1080. }
  1081. #endif
  1082.  
  1083. cmd_bt(breaklength)
  1084. char *breaklength;
  1085. {
  1086.     p_break = atol(breaklength);
  1087.     if (doing_init)
  1088.     return CMDOK;
  1089.  
  1090.     AbortIO((struct IORequest *)Read_Request);
  1091.     Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit);
  1092.     WaitIO((struct IORequest *)Read_Request);
  1093.     Read_Request->io_BrkTime = Write_Request->io_BrkTime = p_break;
  1094.     setparams();
  1095.     return CMDOK;
  1096. }
  1097.  
  1098. cmd_kmaxpk(pks)
  1099. char *pks;
  1100. {
  1101.     int i = atoi(pks),
  1102.     cmdrc = CMDOK;
  1103.  
  1104.     if(i <= MAXLONGPKS)
  1105.     p_kmaxpack = i;
  1106.     else {
  1107.     sprintf(errmsg, "Kermit packet size too big: %d", pks);
  1108.     cmdrc = CMDFAIL;
  1109.     }
  1110.     return cmdrc;
  1111. }
  1112.  
  1113. cmd_mode(tmode)
  1114. char *tmode;
  1115. {
  1116.     switch (*tmode|' ') {
  1117.     case 'i':
  1118.     p_mode = 0;
  1119.     break;
  1120.  
  1121.     case 'c':
  1122.     p_mode = 1;
  1123.     break;
  1124.  
  1125.     default:
  1126.     strcpy(errmsg, "Init: invalid transfer mode: ");
  1127.     strcat(errmsg, tmode);
  1128.     return CMDFAIL;
  1129.     }
  1130.     if (doing_init == 0)
  1131.     redocomm();
  1132.     return CMDOK;
  1133. }
  1134.  
  1135. cmd_as(file)
  1136. char *file;
  1137. {
  1138.     do_send(file);
  1139.     return CMDOK;
  1140. }
  1141.  
  1142. cmd_cap(file)
  1143. char *file;
  1144. {
  1145.     do_capture(file);
  1146.     return CMDOK;
  1147. }
  1148.  
  1149. cmd_beep(dummy)
  1150. char    *dummy;
  1151. {
  1152.     if (p_volume == 0)
  1153.     DisplayBeep(NULL);
  1154.     else {
  1155.     BeginIO((struct IORequest *)&Audio_Request);
  1156.     WaitIO((struct IORequest *)&Audio_Request);
  1157.     }
  1158.     return CMDOK;
  1159. }
  1160.  
  1161. void setvar(par,typ,var)
  1162. char    *par;
  1163. int    typ,*var;
  1164. {
  1165.     int i;
  1166.  
  1167.     switch (typ) {
  1168.     case 0: /* ON/OFF or YES/NO */
  1169.     case 1: /* not case */
  1170.     if ((par[1]|' ') == 'n' || (par[0]|' ') == 'y') *var = 1-typ;
  1171.     else                        *var = typ;
  1172.     break;
  1173.  
  1174.     case 2: /* read hex number */
  1175.     if (sscanf(par,"%x",&i) == 1) *var = i;
  1176.  
  1177.     break;
  1178.  
  1179.     case 3: /* read decimal number */
  1180.     if (sscanf(par,"%d",&i) == 1) *var = i;
  1181.     break;
  1182.     }
  1183. }
  1184.  
  1185. cmd_ac(par)
  1186. char *par;
  1187. {
  1188.     setvar(par,0,&p_autochop);
  1189.     if (doing_init == 0)
  1190.     redoutil();
  1191.     return CMDOK;
  1192. }
  1193.  
  1194. cmd_echo(par)
  1195. char    *par;
  1196. {
  1197.     setvar(par,0,&p_echo);
  1198.     if (doing_init == 0)
  1199.     redoutil();
  1200.     return CMDOK;
  1201. }
  1202.  
  1203. cmd_wrap(par)
  1204. char    *par;
  1205. {
  1206.     setvar(par,0,&p_wrap);
  1207.     if (doing_init == 0)
  1208.     redoutil();
  1209.     return CMDOK;
  1210. }
  1211.  
  1212. cmd_share(parm)
  1213. char *parm;
  1214. {
  1215.     int oldval = p_shared;
  1216.  
  1217.     setvar(parm, 0, &p_shared);
  1218.  
  1219.     if(Read_Request && (oldval ^ p_shared)) {
  1220.     /* Port is going from shared->exclusive or vice-versa.  Close it and
  1221.     ** re-open */
  1222.     if(!CheckIO((struct IORequest *)Read_Request))
  1223.         AbortIO((struct IORequest *)Read_Request);
  1224.     Wait (1L <<mySerPort->mp_SigBit);
  1225.     WaitIO((struct IORequest *)Read_Request);
  1226.     CloseDevice((struct IORequest *)Read_Request);
  1227.     if(p_shared)
  1228.         Read_Request->io_SerFlags |= SERF_SHARED;
  1229.     else
  1230.         Read_Request->io_SerFlags &= (-1L ^ SERF_SHARED);
  1231.     if(OpenDevice(mysername,(LONG)p_unit,(struct IORequest *)Read_Request,NULL))
  1232.         cleanup("Can't re-open Read device",0);
  1233.     InitCommItems();
  1234.     setparams();
  1235.     }
  1236.     return CMDOK;
  1237. }
  1238.  
  1239. cmd_xbeep(par)
  1240. char    *par;
  1241. {
  1242.     setvar(par,0,&p_xbeep);
  1243.     if (doing_init == 0)
  1244.     redoutil();
  1245.     return CMDOK;
  1246. }
  1247.  
  1248. cmd_xproto(par)
  1249. char    *par;
  1250. {
  1251.     int i, len, save, cmdrc = CMDOK;
  1252.  
  1253.     next_wrd(par, &len);
  1254.  
  1255.     p_xproto = MODEMAX + 1;    /* Establish an out of bounds default */
  1256.  
  1257.     if(len) {
  1258.     par[len] = '\0';
  1259.  
  1260.     /* downcase the parameter */
  1261.     for(i = 0; i < len; i++) par[i] |= ' ';
  1262.  
  1263.     for(i = 0; i < MODEMAX; i++)
  1264.         if(strcmp(par, &(*(xprotos[i]))) == 0) {
  1265.         p_xproto = i;
  1266.         break;
  1267.         }
  1268.     }
  1269.     if(p_xproto >= MODEMAX) {
  1270.     /* Not a built-in protocol...check the defined external protocols */
  1271.     p_xproto = 0;
  1272.     if(len > DNMAXLEN) {
  1273.         save = *(par+DNMAXLEN);
  1274.         *(par+DNMAXLEN) = '\0';
  1275.     }
  1276.     for(i = 0; i < NumExts; i++) {
  1277.         if(strcmp(par, ExtXfer[i]->downname) == 0) {
  1278.         p_xproto = MODEMAX + i;
  1279.         break;
  1280.         }
  1281.     }
  1282.  
  1283.     if(p_xproto == 0) {
  1284.         p_xproto = MODEMAX - 1;
  1285.         if(len > DNMAXLEN)
  1286.         *(par+DNMAXLEN) = save;
  1287.         sprintf(errmsg, "XPROTO beginning \"%.10s\" unknown, %s used",
  1288.             par, &(*(xprotos[p_xproto])));
  1289.         cmdrc = CMDFAIL;
  1290.     }
  1291.     }
  1292.     if(!doing_init)
  1293.     redofile();
  1294.     return cmdrc;
  1295. }
  1296.  
  1297. cmd_numkey(par)
  1298. char    *par;
  1299. {
  1300.     setvar(par,1,&p_keyapp);
  1301.     if (doing_init == 0)
  1302.     redoutil();
  1303.     return CMDOK;
  1304. }
  1305.  
  1306. cmd_appcur(par)
  1307. char    *par;
  1308. {
  1309.     setvar(par,0,&p_curapp);
  1310.     if (doing_init == 0)
  1311.     redoutil();
  1312.     return CMDOK;
  1313. }
  1314.  
  1315. cmd_swap(par)
  1316. char    *par;
  1317. {
  1318.     setvar(par,0,&p_bs_del);
  1319.     if (doing_init == 0)
  1320.     redoutil();    /* Calls InitUtilItems which does swap_bs_del() */
  1321.     else {
  1322.         swap_bs_del();    /* Setup keys[] properly... */
  1323.         swap_bs_del();    /* ...for new mode        */
  1324.     }
  1325.     return CMDOK;
  1326. }
  1327.  
  1328. cmd_bkg(par)
  1329. char    *par;
  1330. {
  1331.     setvar(par,2,&p_background);
  1332.     return CMDOK;
  1333. }
  1334.  
  1335. cmd_bold(par)
  1336. char    *par;
  1337. {
  1338.     setvar(par,2,&p_bold);
  1339.     return CMDOK;
  1340. }
  1341.  
  1342. cmd_buf(par)
  1343. char    *par;
  1344. {
  1345.     setvar(par,3,&p_buffer);
  1346.     return CMDOK;
  1347. }
  1348.  
  1349. cmd_cursor(par)
  1350. char    *par;
  1351. {
  1352.     setvar(par,2,&p_cursor);
  1353.     return CMDOK;
  1354. }
  1355.  
  1356. cmd_depth(par)
  1357. char    *par;
  1358. {
  1359.     setvar(par,3,&p_depth);
  1360.     return CMDOK;
  1361. }
  1362.  
  1363. cmd_device(par)
  1364. char    *par;
  1365. {
  1366.     int    len, cmdrc = CMDOK;
  1367.     char    temp[80];
  1368.  
  1369.     next_wrd(par, &len);
  1370.     if(len > SERNAMESIZE) {
  1371.     printf(temp, "Init:\nDevice parm too long, %s used", SERIALNAME);
  1372.     strcpy(mysername, SERIALNAME);
  1373.     cmdrc = CMDFAIL;
  1374.     } else
  1375.     strcpy(mysername, par);
  1376.     return cmdrc;
  1377. }
  1378.  
  1379. cmd_display(str)
  1380. char    *str;
  1381. {
  1382.     register char *p;
  1383.  
  1384.     for(p = tostring(str); *p; p++)
  1385.     doremote(*p);
  1386.  
  1387.     return CMDOK;
  1388. }
  1389.  
  1390. cmd_fore(par)
  1391. char    *par;
  1392. {
  1393.     setvar(par,2,&p_foreground);
  1394.     return CMDOK;
  1395. }
  1396.  
  1397. #if AREXX
  1398. /*   This routine *depends* on the fact that the FORWARD command is only
  1399. ** valid from AREXX.  It then assumes that it can open RXSNAME.
  1400. **/
  1401. cmd_fwd(par)
  1402. char *par;
  1403. {
  1404.     int i;
  1405.  
  1406.     if(ForwardPortName != NULL) {
  1407.     FreeMem(ForwardPortName, (LONG)strlen(ForwardPortName) + 1);
  1408.     ForwardPortName = NULL;
  1409.     }
  1410.  
  1411.     forwarding = 0;
  1412.  
  1413.     if(RexxSysBase == NULL) {
  1414.     RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME, 0L);
  1415.     if( (i = makerexxport()) != 0) {
  1416.         strcpy(errmsg, rexxerrmsgs[i]);
  1417.         return CMDFAIL;
  1418.     }
  1419.     }
  1420.  
  1421.     if(par && *par) {
  1422.     if(ForwardPortName = AllocMem((LONG)strlen(par)+1,
  1423.                 MEMF_PUBLIC | MEMF_CLEAR)) {
  1424.         strcpy(ForwardPortName, par);
  1425.         forwarding = 1;
  1426.     } else {
  1427.         strcpy(errmsg, "Can't allocate memory for an AREXX forward port");
  1428.         return CMDFAIL;
  1429.     }
  1430.     }
  1431.  
  1432.     return CMDOK;
  1433. }
  1434. #else
  1435. cmd_fwd(par)
  1436. {
  1437.     return CMDFAIL;
  1438. }
  1439. #endif /* AREXX */
  1440.  
  1441. cmd_font(par)
  1442. char    *par;
  1443. {
  1444.     char temp[80];
  1445.     int  len, cmdrc = CMDOK;
  1446.  
  1447.     next_wrd(par, &len);
  1448.  
  1449.     temp[0] = '\0';
  1450.  
  1451.     /*  myfontname has been initialized from p_font in InitDefaults() in
  1452.     ** init.c */
  1453.  
  1454.     if(!len) {
  1455.     sprintf(temp, "Init:\nNo font specified, \"%s\" used", myfontname);
  1456.     cmdrc = CMDWARN;
  1457.     } else {
  1458.     if(*par && len) {
  1459.         if(len < MAXFONTVARLEN) {
  1460.             par[len] = '\0';
  1461.         strcpy(myfontname, par);
  1462.         strcat(myfontname,FONTSUFFIX);
  1463.         } else {
  1464.         sprintf(temp, "Init:\nFont specification too long, \"%s\" used",
  1465.             myfontname);
  1466.         cmdrc = CMDWARN;
  1467.         }
  1468.         }
  1469.     }
  1470.     myattr.ta_Name = (STRPTR)myfontname;
  1471.     if(*temp)
  1472.     puts(temp);
  1473.     return cmdrc;
  1474. }
  1475.  
  1476. cmd_fonts(par)
  1477. char    *par;
  1478. {
  1479.     char temp[80];
  1480.     int  len, size, cmdrc = CMDOK;
  1481.  
  1482.     next_wrd(par, &len);
  1483.  
  1484.     temp[0] = '\0';
  1485.  
  1486.     /*  myfontname has been initialized from p_font in InitDefaults() in
  1487.     ** init.c */
  1488.  
  1489.     if(!len) {
  1490.     strcpy(temp, "Init:\nNo font size specified, \"8\" used");
  1491.     cmdrc = CMDWARN;
  1492.     } else {
  1493.     if(*par && len) {
  1494.         size = atoi(par);
  1495.         if(size > 0)
  1496.         myattr.ta_YSize = size;
  1497.         else {
  1498.             myattr.ta_YSize = 8;
  1499.         sprintf(temp, "Init:\nFont size \"%s\" invalid, \"8\" used",
  1500.             par);
  1501.         cmdrc = CMDWARN;
  1502.         }
  1503.         }
  1504.     }
  1505.     if(*temp)
  1506.     puts(temp);
  1507.     return cmdrc;
  1508. }
  1509.  
  1510. cmd_inter(par)
  1511. char    *par;
  1512. {
  1513.     if(strcmp(par, "asis") == 0)
  1514.     p_interlace = 2;
  1515.     else
  1516.     setvar(par,0,&p_interlace);
  1517.     return CMDOK;
  1518. }
  1519.  
  1520. cmd_mouse(par)
  1521. char *par;
  1522. {
  1523.     switch (par[0]|' ') {
  1524.     case 'b':
  1525.         p_mouse_up = p_mouse_down = 1;        /* send both    */
  1526.         break;
  1527.  
  1528.     case 'o':
  1529.         p_mouse_up = p_mouse_down = 0;        /* mouse off    */
  1530.         break;
  1531.  
  1532.     case 'u':
  1533.         p_mouse_up = 1;                /* up only      */
  1534.         p_mouse_down = 0;
  1535.         break;
  1536.  
  1537.     case 'd':                    /* down only    */
  1538.         p_mouse_down = 1;
  1539.         p_mouse_up = 0;
  1540.         break;
  1541.     default:
  1542.         return CMDFAIL;
  1543.     }
  1544.     return CMDOK;
  1545. }
  1546.  
  1547. cmd_msg(par)
  1548. char *par;
  1549. {
  1550.     register char *p, *s;
  1551.     int newline = 1;        /* Whether we need to scroll */
  1552.  
  1553.     for(s = p = tostring(par); *p; p++) {
  1554.     if(*p == '\n') {
  1555.         *p = '\0';
  1556.         InfoMsgNoScroll(s);
  1557.         ScrollInfoMsg(1);
  1558.         newline = 0;
  1559.         s = p + 1;
  1560.     } else if(*p == '\r') {
  1561.         *p = '\0';
  1562.         InfoMsgNoScroll(s);
  1563.         newline = 0;
  1564.         s = p + 1;
  1565.     } else
  1566.         newline = 1;
  1567.     }
  1568.     if(*s)
  1569.     InfoMsgNoScroll(s);
  1570.  
  1571.     if(newline)
  1572.     ScrollInfoMsg(1);
  1573.     return CMDOK;
  1574. }
  1575.  
  1576. cmd_lines(par)
  1577. char    *par;
  1578. {
  1579.     setvar(par,3,&p_lines);
  1580.     return CMDOK;
  1581. }
  1582.  
  1583. cmd_screen(par)
  1584. char    *par;
  1585. {
  1586.     if ((par[0]|' ') == 'w') p_screen = 0;
  1587.     else             p_screen = 1;
  1588.     return CMDOK;
  1589. }
  1590.  
  1591. cmd_unit(par)
  1592. char    *par;
  1593. {
  1594.     setvar(par, 3, &p_unit);
  1595.     return CMDOK;
  1596. }
  1597.  
  1598. cmd_wb(par)
  1599. char    *par;
  1600. {
  1601.     setvar(par,0,&p_wbcolors);
  1602.     return CMDOK;
  1603. }
  1604.  
  1605. cmd_short(par)    /* Set keyboard shortcuts */
  1606. char    *par;
  1607. {
  1608.     int    i, l, l2;
  1609.     register char *p = par;
  1610.     
  1611.     /* downcase the next word */
  1612.     for (i=0; p[i] && (p[i] != ' ') && (p[i] != '\t'); i++)
  1613.     p[i] |= ' ';
  1614.     l = i;
  1615.     
  1616.     /*   Find the command name.  If found set the shortcut key to the
  1617.     ** user's value.  If no value then set the key to ' ' to indicate no
  1618.     ** shortcut available. */
  1619.     for(i = 0; shortkeys[i].cname != NULL; i++) {
  1620.     l2 = strlen(shortkeys[i].cname);
  1621.     if (l >= l2 && strncmp(p, shortkeys[i].cname, l2) == 0) {
  1622.         for( ; p[l] && ((p[l] == ' ') || (p[l] == '\t')) ; l++)
  1623.         ;
  1624.         if(p[l])
  1625.         *(shortkeys[i].pos) = p[l];
  1626.         else
  1627.         *(shortkeys[i].pos) = ' ';
  1628.         return CMDOK;
  1629.     }
  1630.     }
  1631.  
  1632.     /* Not a "normal" item so try an ExternalXfer item */
  1633.     p = next_wrd(par, &l);
  1634.     if(l > 0) {
  1635.     *(p+l) = '\0';
  1636.     for(i = 0; i < NumExts; i++)
  1637.         if(strcmp(p, ExtXfer[i]->downname) == 0) {
  1638.         p = next_wrd(p+l+1, &l);
  1639.         if(l <= 0)
  1640.             break;
  1641.         ExtXfer[i]->cmdkey = *p;
  1642.         return CMDOK;
  1643.         }
  1644.     }
  1645.  
  1646.     sprintf(errmsg, "Unknown shortcut: %s", par);
  1647.     return CMDFAIL;
  1648. }
  1649.  
  1650. cmd_strip(par)
  1651. char    *par;
  1652. {
  1653.     setvar(par,0,&p_strip);
  1654.     return CMDOK;
  1655. }
  1656.  
  1657. cmd_key(par)
  1658. char    *par;
  1659. {
  1660.     int i;
  1661.  
  1662.     if (sscanf(par,"%x",&i) == 1)
  1663.     p_keyscript = (char)(i & 0x7f);
  1664.     return CMDOK;
  1665. }
  1666.  
  1667. cmd_volume(par)
  1668. char    *par;
  1669. {
  1670.     setvar(par,3,&p_volume);
  1671.     return CMDOK;
  1672. }
  1673.  
  1674. cmd_conv(par)
  1675. char    *par;
  1676. {
  1677.     setvar(par,0,&p_convert);
  1678.     if (doing_init == 0)
  1679.     redoutil();
  1680.     return CMDOK;
  1681. }
  1682.  
  1683. cmd_fnc(par)
  1684. char    *par;
  1685. {
  1686.     char    *s;
  1687.     int     l;
  1688.     int     i = atoi(par);
  1689.  
  1690.     s = par;
  1691.     if (*s) s = next_wrd(s,&l);        /* skip key number */
  1692.     if (*s) s = next_wrd(s+l+1,&l);    /* point at desired string */
  1693.     if (*s) s = tostring(s);        /* convert the string */
  1694.     if(*par == 'm') {    /* Mouse prefix */
  1695.     p_f[10] = malloc(strlen(s) + 1);
  1696.     strcpy(p_f[10], s);
  1697.     } else if (*s && i > 0 && i < 21) {
  1698.     if (i > 10) {
  1699.         p_F[i-11] = malloc(strlen(s)+1);
  1700.         strcpy(p_F[i-11],s);
  1701.     }
  1702.     else {
  1703.         p_f[i-1] = malloc(strlen(s)+1);
  1704.         strcpy(p_f[i-1],s);
  1705.     }
  1706.     }
  1707.     return CMDOK;
  1708. }
  1709.  
  1710. cmd_null(dummy)
  1711. char *dummy;
  1712. {
  1713.     return CMDOK;
  1714. }
  1715.  
  1716. /* Case-insensitive strcmp() */
  1717. ci_strcmp(p1, p2)
  1718. char *p1, *p2;
  1719. {
  1720.     while( *p1 && ((*p1 | ' ') == (*p2 | ' ')) ) {
  1721.     ++p1;
  1722.     ++p2;
  1723.     }
  1724.     return(*p1 != *p2);
  1725. }
  1726.  
  1727. do_ext(exp, pgmname, file)
  1728. struct ExternalXfer *exp;
  1729. char *pgmname, *file;
  1730. {
  1731.     char *local = "@LOCAL",
  1732.      *remote = "@REMOTE",
  1733.      *command,
  1734.      localfn[MAXGADSTR],
  1735.      remotefn[MAXGADSTR],
  1736.      *p,
  1737.      *p1;
  1738.     int len = 0,
  1739.     locallen = strlen(local),
  1740.     remotelen = strlen(remote);
  1741.  
  1742.     if(file)
  1743.     strcpy(localfn, file);
  1744.     else
  1745.     localfn[0] = '\0';
  1746.     remotefn[0] = '\0';
  1747.  
  1748.     /* Get the initial length of the command then go through the user's
  1749.     ** command string looking for @LOCAL and @REMOTE.  When we encounter one of
  1750.     ** these strings then, if we don't already have the appropriate filename,
  1751.     ** we'll put up a requester asking for it.  Whether we put up the requester
  1752.     ** or not we must still account for the length of the replacement filename
  1753.     ** so that when we AllocMem() for the command we'll only get what we need.
  1754.     */
  1755.     len = strlen(pgmname) + 1;
  1756.     for(p = pgmname; *p; p++) {
  1757.     if(*p == '@')
  1758.         if(strncmp(p+1, local+1, locallen-1) == 0) {
  1759.         if(!cmd_from_script || localfn[0] == '\0')
  1760.             req("Local file name:", localfn, 1);
  1761.         if(!localfn[0])    /* No filename specified */
  1762.             return CMDFAIL;
  1763.         if(file && !cmd_from_script)
  1764.             strcpy(file, localfn);
  1765.         len += strlen(localfn);
  1766.         len -= locallen;
  1767.         p += locallen;
  1768.         } else if(strncmp(p+1, remote+1, remotelen-1) == 0) {
  1769.         req("Remote file name:", remotefn, 1);
  1770.         if(!remotefn[0])    /* No filename specified */
  1771.             return CMDFAIL;
  1772.         len += strlen(remotefn);
  1773.         len -= remotelen;
  1774.         p += remotelen;
  1775.         }
  1776.     }    /* for p = pgmname */
  1777.  
  1778.     /* Allocate space for the command and copy the command string to it
  1779.     ** replacing @LOCAL and @REMOTE with localfn and remotefn, respectively */
  1780.     command = AllocMem((long)len, MEMF_PUBLIC | MEMF_CLEAR);
  1781.     if(localfn[0] || remotefn[0]) {
  1782.     for(p = pgmname, p1 = p; *p; p++) {
  1783.         if(strncmp(p, local, locallen) == 0) {
  1784.         strncat(command, p1, p - p1);
  1785.         strcat(command, localfn);
  1786.         p += locallen;
  1787.         p1 = p;
  1788.         } else if(strncmp(p, remote, remotelen) == 0) {
  1789.         strncat(command, p1, p - p1);
  1790.         strcat(command, remotefn);
  1791.         p += remotelen;
  1792.         p1 = p;
  1793.         }
  1794.     }
  1795.     strcat(command, p1);    /* Don't forget the tail of the command! */
  1796.     } else strcpy(command, pgmname);
  1797.  
  1798.     /* Close down VT100's use of the serial port */
  1799.     if(!CheckIO((struct IORequest *)Read_Request))
  1800.     AbortIO((struct IORequest *)Read_Request);
  1801.     Wait (1L <<mySerPort->mp_SigBit);
  1802.     WaitIO((struct IORequest *)Read_Request);
  1803.     if(!p_shared)
  1804.     CloseDevice((struct IORequest *)Read_Request);
  1805.  
  1806.     Execute(command, 0L, 0L);    /* Invoke the external xfer pgm */
  1807.     FreeMem(command, (long)len);
  1808.     if(!p_shared && OpenDevice(mysername,(LONG)p_unit,(struct IORequest *)Read_Request,NULL))
  1809.     cleanup("Can't re-open Read device",0);
  1810.     setparams();
  1811.     if(p_xbeep)
  1812.     cmd_beep(0L);
  1813.     return CMDOK;
  1814. }
  1815.