BSD 4_4_Lite1 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 25 Nov 1992 05:33:21 +0000 (21:33 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 25 Nov 1992 05:33:21 +0000 (21:33 -0800)
Work on file usr/src/contrib/kermit-5A.188/ckuus5.c
Work on file usr/src/contrib/kermit-5A.188/ckuus6.c
Work on file usr/src/contrib/kermit-5A.188/ckuus7.c
Work on file usr/src/contrib/kermit-5A.188/ckuusr.c
Work on file usr/src/contrib/kermit-5A.188/ckuusr.h

Synthesized-from: CSRG/cd2/4.4BSD-Lite1

usr/src/contrib/kermit-5A.188/ckuus5.c [new file with mode: 0644]
usr/src/contrib/kermit-5A.188/ckuus6.c [new file with mode: 0644]
usr/src/contrib/kermit-5A.188/ckuus7.c [new file with mode: 0644]
usr/src/contrib/kermit-5A.188/ckuusr.c [new file with mode: 0644]
usr/src/contrib/kermit-5A.188/ckuusr.h [new file with mode: 0644]

diff --git a/usr/src/contrib/kermit-5A.188/ckuus5.c b/usr/src/contrib/kermit-5A.188/ckuus5.c
new file mode 100644 (file)
index 0000000..5b24c33
--- /dev/null
@@ -0,0 +1,3753 @@
+#ifndef NOICP
+
+/*  C K U U S 5 --  "User Interface" for Unix Kermit, part 5  */
+/*
+  Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
+  Columbia University Center for Computing Activities.
+  First released January 1985.
+  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
+  York.  Permission is granted to any individual or institution to use this
+  software as long as it is not sold for profit.  This copyright notice must be
+  retained.  This software may not be included in commercial products without
+  written permission of Columbia University.
+*/
+
+/* Includes */
+
+#include "ckcdeb.h"
+#include "ckcasc.h"
+#include "ckcker.h"
+#include "ckuusr.h"
+#include "ckcnet.h"
+#ifndef NOCSETS
+#include "ckcxla.h"
+#endif /* NOCSETS */
+#ifdef MAC
+#include "ckmasm.h"
+#endif /* MAC */
+
+/* For formatted screens, "more?" prompting, etc. */
+
+#define SCRNLEN 21                     /* Screen length */
+#define SCRNWID 79                     /* Screen width */
+
+#ifdef FT18
+#define isxdigit(c) isdigit(c)
+#endif /* FT18 */
+
+#ifdef MAC                             /* Internal MAC file routines */
+#define feof mac_feof
+#define rewind mac_rewind
+#define fgets mac_fgets
+#define fopen mac_fopen
+#define fclose mac_fclose
+
+int mac_feof();
+void mac_rewind();
+char *mac_fgets();
+FILE *mac_fopen();
+int mac_fclose();
+#endif /* MAC */
+
+/* External variables */
+
+extern int carrier, cdtimo, local, backgrd, bgset, sosi, suspend,
+  displa, binary, deblog, escape, xargs, flow, cmdmsk,
+  duplex, ckxech, pktlog, seslog, tralog, what,
+  keep, warn, tlevel, cwdf, nfuncs, unkcs, msgflg,
+  mdmtyp, zincnt, cmask, rcflag, success, xitsta, pflag, lf_opts, tnlm, tn_nlm;
+
+extern char *ccntab[];
+
+#ifndef NOFRILLS
+extern int en_cwd, en_del, en_dir, en_fin, en_bye,
+  en_get, en_hos, en_sen, en_set, en_spa, en_typ, en_who;
+#endif /* NOFRILLS */
+extern long vernum;
+extern int srvtim, srvdis, incase, inecho, intime, insilence, nvars, verwho;
+extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav,
+ *cknetv, *clcmds;
+extern char *connv, *dialv, *loginv, *nvlook();
+
+#ifndef NOSCRIPT
+extern int secho;
+#endif /* NOSCRIPT */
+
+#ifndef NODIAL
+extern int nmdm;
+extern struct keytab mdmtab[];
+#endif /* NODIAL */
+
+#ifdef NETCONN
+extern int tn_init, network, ttnproto;
+#endif /* NETCONN */
+
+#ifdef OS2
+extern int tt_type, tt_arrow, tt_keypad, tt_wrap;
+#endif /* OS2 */
+extern int tt_crd;
+
+#ifndef NOCSETS
+extern int language, nfilc, tcsr, tcsl;
+extern struct keytab fcstab[];
+#ifndef MAC
+extern struct keytab ttcstab[];
+#endif /* MAC */
+#endif /* NOCSETS */
+
+extern int atcapr,
+  atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
+  attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; 
+
+extern long speed;
+
+extern char *DIRCMD, *PWDCMD, *DELCMD;
+#ifndef NOXMIT
+extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
+extern char xmitbuf[];
+#endif /* NOXMIT */
+
+extern char **xargv, *versio, *ckxsys, *dftty, *cmarg, *lp;
+
+#ifdef DCMDBUF
+extern char *cmdbuf, *atmbuf;          /* Command buffers */
+#ifndef NOSPL
+extern char *savbuf;                   /* Command buffers */
+#endif /* NOSPL */
+#else
+extern char cmdbuf[], atmbuf[];                /* Command buffers */
+#ifndef NOSPL
+extern char savbuf[];                  /* Command buffers */
+#endif /* NOSPL */
+#endif /* DCMDBUF */
+
+extern char toktab[], ttname[], psave[];
+extern CHAR sstate;
+extern int cmflgs, techo, terror, repars, ncmd;
+extern struct keytab cmdtab[];
+
+#ifndef MAC
+#ifndef NOSETKEY
+KEY *keymap;
+MACRO *macrotab;
+#endif /* NOSETKEY */
+#endif /* MAC */
+
+#ifndef NOSPL
+extern struct mtab *mactab;
+extern struct keytab vartab[], fnctab[];
+extern int cmdlvl, maclvl, nmac, mecho, merror;
+#endif /* NOSPL */
+
+FILE *tfile[MAXTAKE];                  /* TAKE file stack */
+char *tfnam[MAXTAKE];
+
+#ifndef NOSPL
+/* Local declarations */
+
+int nulcmd = 0;                        /* Flag for next cmd to be ignored */
+
+/* Definitions for built-in macros */
+
+/* First, the single line macros, installed with addmac()... */
+
+/* IBM-LINEMODE macro */
+char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none";
+
+/* FATAL macro */
+char *m_fat = "if def \\%1 echo \\%1, if not = \\v(local) 0 hangup, stop 1";
+
+#ifdef COMMENT
+/*
+  Long macro definitions were formerly done like this.  But some compilers
+  cannot handle continued string constants, others cannot handle string
+  constants that are this long.  So these definitions have been broken up
+  into pieces and put into arrays, see below.
+*/
+char *m_forx = "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,\
+ass _floop { _getargs,\
+define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,\
+\\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},\
+def break goto bot, def continue goto inc,\
+do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)";
+
+char *m_while = "if def _wloop ass \\%9 \\fdef(_wloop),\
+ass _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},\
+def break goto wbot, def continue goto wtest,\
+do _wloop,assign _wloop \\fcont(\\%9)";
+
+char *m_xif = "ass \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},\
+do _ify,ass _ify \\fcont(\\%9)";
+#endif /* COMMENT */
+
+/* Now the multiline macros, defined with addmmac()... */
+
+/* FOR macro */
+char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
+"define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,",
+"\\%6,:inc,incr \\\\\\%1 \\%4,goto top,:bot,_putargs},",
+"def break goto bot, def continue goto inc,",
+"do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
+""};
+#ifdef COMMENT
+/*
+  This one didn't work right.  When an interior loop finished executing,
+  the definition of the enclosing loop was restored, but the new definition
+  could be in a different location in memory, so its macro execution pointer
+  could (and usually was) pointing at garbage.
+*/
+char *old_for_def[] = { "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,",
+"ass _floop { _getargs,",
+"define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,",
+"\\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},",
+"def break goto bot, def continue goto inc,",
+"do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)",
+""};
+#endif /* COMMENT */
+
+/* WHILE macro */
+char *whil_def[] = { "_assign _whi\\v(cmdlevel) {_getargs,",
+":wtest,\\%1,\\%2,goto wtest,:wbot,_putargs},",
+"def break goto wbot, def continue goto wtest,",
+"do _whi\\v(cmdlevel),_assign _whi\\v(cmdlevel)",
+""};
+#ifdef COMMENT
+/*
+  Same deal as FOR loop...
+*/
+char *old_whil_def[] = { "if def _wloop asg \\%9 \\fdef(_wloop),",
+"asg _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},",
+"def break goto wbot, def continue goto wtest,",
+"do _wloop,assign _wloop \\fcont(\\%9)",
+""};
+#endif /* COMMENT */
+
+/* XIF macro */
+char *xif_def[] = {
+"_assign _if\\v(cmdlevel) {_getargs,\\%1,_putargs},",
+"do _if\\v(cmdlevel),_assign _if\\v(cmdlevel)",
+""};
+#ifdef COMMENT
+/* Same deal */
+char *old_xif_def[] = {
+"asg \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},",
+"do _ify,ass _ify \\fcont(\\%9)",
+""};
+#endif /* COMMENT */
+
+/* Variables declared here for use by other ckuus*.c modules */
+/* Space is allocated here to save room in ckuusr.c */
+
+#ifdef DCMDBUF
+struct cmdptr *cmdstk;
+int *ifcmd, *count, *iftest;
+#else
+struct cmdptr cmdstk[CMDSTKL];
+int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL];
+#endif /* DCMDBUF */
+
+char *m_arg[MACLEVEL][NARGS];
+char *g_var[GVARS], *macp[MACLEVEL], *mrval[MACLEVEL];
+int macargc[MACLEVEL];
+char *macx[MACLEVEL];
+extern char varnam[];
+
+char **a_ptr[27];                      /* Array pointers, for arrays a-z */
+int a_dim[27];                         /* Dimensions for each array */
+
+char inpbuf[INPBUFSIZ] = { NUL };      /* Buffer for INPUT and REINPUT */
+char inpbufa[2] = { NUL, NUL };                /* Null terminators for INPUT buffer */
+char inchar[2] = { NUL, NUL };         /* Last character that was INPUT */
+int  incount = 0;                      /* INPUT character count */
+
+char lblbuf[50];                       /* Buffer for labels */
+#endif /* NOSPL */
+
+#ifdef DCMDBUF
+char *line;                            /* Character buffer for anything */
+#else
+char line[LINBUFSIZ];
+#endif /* DCMDBUF */
+
+#ifdef CK_CURSES
+#ifndef TRMBUFL
+#define TRMBUFL 1024
+#endif /* TRMBUFL */
+#ifdef DCMDBUF
+char *trmbuf;                          /* Character buffer for termcap */
+#else
+char trmbuf[TRMBUFL];
+#endif /* DCMDBUF */
+#endif /* CK_CURSES */
+
+extern char pktfil[],
+#ifdef DEBUG
+  debfil[],
+#endif /* DEBUG */
+#ifdef TLOG
+  trafil[],
+#endif /* TLOG */
+  sesfil[],
+  cmdstr[];
+#ifndef NOFRILLS
+extern int rmailf, rprintf;            /* REMOTE MAIL & PRINT items */
+extern char optbuf[];
+#endif /* NOFRILLS */
+
+char *homdir = "";                     /* Pointer to home directory string */
+
+char tmpbuf[50], *tp;                  /* Temporary buffer */
+char numbuf[20];                       /* Buffer for numeric strings. */
+char kermrc[100];                      /* Name of initialization file */
+int noinit = 0;                                /* Flag for skipping init file */
+
+#ifndef NOSPL
+_PROTOTYP( static long expon, (long, long) );
+_PROTOTYP( static long gcd, (long, long) );
+_PROTOTYP( static long fact, (long) );
+int                                    /* Initialize macro data structures. */
+macini() {            /* Allocate mactab and preset the first element. */
+    if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX)))
+       return(-1);
+    mactab[0].kwd = NULL;
+    mactab[0].mval = NULL;
+    mactab[0].flgs = 0;
+    return(0);
+}
+#endif /* NOSPL */
+
+/*  C M D I N I  --  Initialize the interactive command parser  */
+VOID
+cmdini() {
+    int i, x, y, z;
+#ifndef NOSPL
+/*
+  On stack in case of recursion!
+*/
+    char vnambuf[VNAML];               /* Buffer for variable names */
+#endif /* NOSPL */
+
+#ifndef MAC
+#ifndef NOSETKEY                       /* Allocate & initialize the keymap */
+    if (!(keymap = (KEY *) malloc(sizeof(KEY)*KMSIZE)))
+      fatal("cmdini: no memory for keymap");
+    if (!(macrotab = (MACRO *) malloc(sizeof(MACRO)*KMSIZE)))
+      fatal("cmdini: no memory for macrotab");
+    for ( i = 0; i < KMSIZE; i++ ) {
+       keymap[i] = i;
+       macrotab[i] = NULL;
+    }
+#ifdef OS2
+    keymapinit();
+#endif /* OS2 */
+#endif /* NOSETKEY */
+#endif /* MAC */
+
+#ifdef DCMDBUF
+    if (cmsetup() < 0) fatal("Can't allocate command buffers!");
+#ifndef NOSPL
+    if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL)))
+       fatal("cmdini: no memory for cmdstk");
+    if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL)))
+       fatal("cmdini: no memory for ifcmd");
+    if (!(count = (int *) malloc(sizeof(int)*CMDSTKL)))
+       fatal("cmdini: no memory for count");
+    if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL)))
+       fatal("cmdini: no memory for iftest");
+#endif /* NOSPL */
+#ifdef CK_CURSES
+/*
+  Termcap buffer for fullscreen display, UNIX only.  VMS does it another way.
+  The fullscreen display is not supported on AOS/VS or OS-9, etc, yet, and
+  the Mac has its own built-in fullscreen display.
+*/
+#ifdef UNIX
+    if (!(trmbuf = malloc(TRMBUFL+1)))
+       fatal("cmdini: no memory for termcap buffer");
+#endif /* UNIX */
+#endif /* CK_CURSES */
+    if (!(line = malloc(LINBUFSIZ)))
+       fatal("cmdini: no memory for line");
+#endif /* DCMDBUF */
+
+#ifndef NOSPL
+    if (macini() < 0) fatal("Can't allocate macro buffers!");
+#endif /* NOSPL */
+
+#ifdef AMIGA
+    if (tlevel < 0)    
+      concb(escape);
+#endif /* AMIGA */
+
+#ifndef NOSPL
+    cmdlvl = 0;                                /* Start at command level 0 */
+    cmdstk[cmdlvl].src = CMD_KB;
+    cmdstk[cmdlvl].lvl = 0;
+#endif /* NOSPL */
+
+    tlevel = -1;                       /* Take file level = keyboard */
+    for (i = 0; i < MAXTAKE; i++)      /* Initialize command file names */
+      tfnam[i] = NULL;
+
+#ifdef MAC 
+    cmsetp("Mac-Kermit>");             /* Set default prompt */
+#else
+    cmsetp("C-Kermit>");               /* Set default prompt */
+#endif /* MAC */
+
+#ifndef NOSPL
+    initmac();                         /* Initialize macro table */
+/* Add one-line macros */
+    addmac("ibm-linemode",m_ibm);      /* Add built-in macros. */
+    addmac("fatal",m_fat);             /* FATAL macro. */
+/* Add multiline macros */
+    addmmac("_forx",for_def);          /* FOR macro. */
+    addmmac("_xif",xif_def);           /* XIF macro. */
+    addmmac("_while",whil_def);                /* WHILE macro. */
+/* Fill in command line argument vector */
+    sprintf(vnambuf,"\\&@[%d]",xargs);         /* Command line argument vector */
+    y = arraynam(vnambuf,&x,&z);       /* goes in array \&@[] */
+    if (y > -1) {
+       dclarray((char)x,z);            /* Declare the array */
+       for (i = 0; i < xargs; i++) {   /* Fill it */
+           sprintf(vnambuf,"\\&@[%d]",i);
+           addmac(vnambuf,xargv[i]);
+       }
+    }
+    *vnambuf = NUL;
+#endif /* NOSPL */
+
+/* Get our home directory now.  This needed in lots of places. */
+
+    homdir = zhome();
+
+/* If skipping init file ('-Y' on Kermit command line), return now. */
+
+    if (noinit) return;
+
+#ifdef OS2
+/*
+  The -y init file must be fully specified or in the current directory.
+  KERMRC is looked for via INIT, PATH and DPATH in that order.  Finally, our
+  own executable file path is taken and the .EXE suffix is replaced by .INI
+  and this is tried as initialization file.
+*/
+    if (rcflag) {
+       strcpy(line, kermrc);
+    } else {
+       _searchenv(kermrc,"INIT",line);
+       if (line[0] == 0)
+         _searchenv(kermrc,"PATH",line);
+       if (line[0] == 0)
+         _searchenv(kermrc,"DPATH",line);
+       if (line[0] == 0) {
+           char *pgmptr = GetLoadPath();
+           if (pgmptr) {
+             lp = strrchr(pgmptr, '.');
+             strncpy(line, pgmptr, lp - pgmptr);
+             strcpy(line + (lp - pgmptr), ".ini");
+           }
+       }
+    }
+    if ((tfile[0] = fopen(line,"r")) != NULL) {
+        tlevel = 0;
+       if (tfnam[tlevel] = malloc(strlen(line)+1))
+         strcpy(tfnam[tlevel],line);
+#ifndef NOSPL
+       cmdlvl++;
+       cmdstk[cmdlvl].src = CMD_TF;
+       cmdstk[cmdlvl].lvl = tlevel;
+       ifcmd[cmdlvl] = 0;
+       iftest[cmdlvl] = 0;
+       count[cmdlvl] = 0;
+#endif /* NOSPL */
+        debug(F110,"init file",line,0);
+    } else {
+        debug(F100,"no init file","",0);
+    }
+#else /* not OS2 */
+    lp = line;
+    lp[0] = '\0';
+#ifdef GEMDOS
+    zkermini(line,rcflag, kermrc);
+#else
+#ifdef VMS
+    zkermini(line,LINBUFSIZ,kermrc);
+#else /* not VMS */
+    if (rcflag) {                      /* If init file name from cmd line */
+       strcpy(lp,kermrc);              /* use it */
+    } else {                           /* otherwise */
+       if (homdir) {                   /* look in home directory for it */
+           strcpy(lp,homdir);
+           if (lp[0] == '/') strcat(lp,"/");
+       }
+       strcat(lp,kermrc);              /* and use the default name */
+    }
+#endif /* VMS */
+#endif /* GEMDOS */
+
+#ifdef AMIGA
+    reqoff();                          /* disable requestors */
+#endif /* AMIGA */
+
+    debug(F110,"ini file is",line,0);
+    if ((tfile[0] = fopen(line,"r")) != NULL) {
+       tlevel = 0;
+       if (tfnam[tlevel] = malloc(strlen(line)+1))
+         strcpy(tfnam[tlevel],line);
+#ifndef NOSPL
+       cmdlvl++;
+       ifcmd[cmdlvl] = 0;
+       iftest[cmdlvl] = 0;
+       count[cmdlvl] = 0;
+       debug(F101,"open ok","",cmdlvl);
+       cmdstk[cmdlvl].src = CMD_TF;
+       cmdstk[cmdlvl].lvl = tlevel;
+#endif /* NOSPL */
+       debug(F110,"init file",line,0);
+    }
+    if (homdir && (tlevel < 0)) {
+       strcpy(lp,kermrc);
+       if ((tfile[0] = fopen(line,"r")) != NULL) {
+           tlevel = 0;
+       if (tfnam[tlevel] = malloc(strlen(line)+1))
+         strcpy(tfnam[tlevel],line);
+#ifndef NOSPL
+           cmdlvl++;
+           cmdstk[cmdlvl].src = CMD_TF;
+           cmdstk[cmdlvl].lvl = tlevel;
+           ifcmd[cmdlvl] = 0;
+           iftest[cmdlvl] = 0;
+           count[cmdlvl] = 0;
+#endif /* NOSPL */
+       }
+    }
+#endif /* OS2 */
+#ifdef AMIGA
+    reqpop();                          /* Restore requestors */
+#endif /* AMIGA */
+}
+
+#ifndef NOSPL
+/*
+  G E T N C M
+
+  Get next command from current macro definition.
+
+  Moved to a separate routine in edit 181 to allow multiline GET
+  to work when issued in a macro.
+
+  Command is copied into string pointed to by argument s, max length n.
+  Returns:
+   0 if a string was copied, -1 if there was no string to copy.
+*/
+int
+getncm(s,n) char *s; int n; {
+    int y, kp = 0, pp = 0;
+    char *s2;
+    
+    s2 = s;
+    *s = NUL;                          /* Copy next cmd to command buffer. */
+    
+    debug(F111,"getncm",s,n);
+
+    for (y = 0;
+        macp[maclvl] && *macp[maclvl] && y < n;
+        y++, s++, macp[maclvl]++) {
+       
+       *s = *macp[maclvl];             /* Get next character */
+       debug(F000,"char","",*s);
+/*
+  Allow braces around macro definition to prevent commas from being turned to
+  end-of-lines and also treat any commas within parens as text so that
+  multiple-argument functions won't cause the command to break prematurely.
+*/
+       if (*s == '{') kp++;            /* Count braces */
+       if (*s == '}') kp--;
+       if (*s == '(') pp++;            /* Count parentheses. */
+       if (*s == ')') pp--;
+       if (*s == ',' && pp <= 0 && kp <= 0) {
+           macp[maclvl]++;
+           debug(F110,"next cmd",s,0);
+           kp = pp = 0;
+           break;
+       }
+    }                                  /* Reached end. */
+    if (*s2 == NUL) {                  /* If nothing was copied, */
+       debug(F100,"getncm eom","",0);
+       popclvl();                      /* pop command level. */
+       return(-1);
+    } else {                           /* otherwise, tack CR onto end */
+       *s++ = CR;
+       *s = '\0';
+       if (mecho && pflag)
+         printf("%s\n",s2);
+       debug(F101,"getncm returns ptr to",s2,0);
+    }
+    return(0);
+}
+#endif /* NOSPL */
+
+/*
+  G E T N C T
+
+  Get next command from current TAKE file.
+
+  Moved to a separate routine in edit 181 to allow multiline GET
+  to work when issued in a macro.
+
+  Command is copied into string pointed to by argument s, max length n.
+  Returns:
+   0 if a string was copied,
+  -1 on EOF,
+  -2 on malloc failure
+  -3 if line not properly terminated
+*/
+int
+getnct(s,n) char *s; int n; {
+    int i, j;
+    char c, *s2, *lp, *lp2;
+
+    s2 = s;                            /* Remember original pointer */
+
+    debug(F101,"getnct","",n);
+    if (!(lp2 = (char *) malloc(n+1))) { /* Get a temporary buffer */
+       debug(F101,"getnct malloc failure","",0);
+       return(-2);
+    }
+    lp = lp2;                          /* Make a working pointer */
+                                       /* (lp2 must not change!) */
+
+    while (1) {                                /* Loop to read lines from file */
+    
+       if (fgets(lp2,n,tfile[tlevel]) == NULL) { /* EOF */
+           free(lp2);                  /* Free temporary storage */
+           *s = NUL;                   /* Make destination be empty */
+           return(-1);                 /* Return failure code */
+       }
+       debug(F110,"Line from TAKE file",lp2,0); /* Got a line */
+       if (techo && pflag)             /* If TAKE ECHO ON, */
+         printf("%s",lp2);             /* echo it. */
+
+       lp = lp2;                       /* Make a working pointer */
+
+/* Trim trailing whitespace */
+
+       j = strlen(lp2) - 1;            /* Position of line terminator */
+       if (j < 0) j = 0;
+       c = lp2[j];                     /* Value of line terminator */
+       if (c < LF || c > CR) {         /* It's not a terminator */
+           debug(F111,"getnct bad line",lp2,c);
+           if (feof(tfile[tlevel]) && j > 0 && j < n) {
+               printf("Warning: Last line of TAKE file lacks terminator\n");
+               c = lp2[++j] = '\n';
+           } else return(-3);
+       }
+       for (i = j - 1; i > -1; i--)    /* Back up over spaces and tabs */
+         if (lp2[i] != SP && lp2[i] != HT && lp2[i] != NUL)
+           break;
+       lp2[i+1] = c;                   /* Move after last nonblank char */
+       lp2[i+2] = NUL;                 /* Terminate the string */
+       while (*s++ = *lp++) {          /* Copy result to target buffer */
+           if (--n < 2) {
+               printf("?Command too long, maximum length: %d.\n",CMDBL);
+               free(lp2);
+               return(dostop());
+           }
+
+/* Check for trailing comment, " ;" or " #" */
+
+           if ((s > s2 + 1) &&
+               (*(s-1) == ';' || *(s-1) == '#') &&
+               (*(s-2) == SP  || *(s-2) == HT)) {
+               debug(F100,"Trailing comment","",0);
+               s -= 2;                 /* Got one, back up buffer pointer */
+               n += 2;                 /* and adjust free space count. */
+               while ((s >= s2)        /* Trim whitespace again. */
+                      && (*s == SP || *s == HT))
+                 s--, n++;
+               s++;                    /* Point after last character */
+               *s++ = c;               /* Put back line terminator */
+               *s++ = NUL;             /* and string terminator */
+               n -= 3;                 /* Adjust free count */
+               debug(F110,"Comment trimmed & terminated",s2,0);
+               break;
+           }
+       }
+
+/* Check whether this line is continued */
+
+       debug(F000,"Last char in line","",*(s-3));
+       if (*(s - 3) != CMDQ && *(s - 3) != '-') /* Line continued? */
+         break;                                 /* No, done. */
+       s -= 3;                                  /* No, back up pointer */
+       debug(F100,"Got continue char","",0);    /* and continue */
+    }
+    untab(s2);                         /* Done, convert tabs to spaces */
+    free(lp2);                         /* Free temporary storage */
+    return(0);                         /* Return success */
+}
+
+/*  P A R S E R  --  Top-level interactive command parser.  */
+/*
+  Call with:
+    m = 0 for normal behavior: keep parsing and executing commands
+          until an action command is parsed, then return with a
+          Kermit start-state as the value of this function.
+    m = 1 to parse only one command, can also be used to call parser()
+          recursively.
+    m = 2 to read but do not execute one command.
+  In all cases, parser() returns:
+    0     if no Kermit protocol action required
+    > 0   with a Kermit protocol start-state.
+    < 0   upon error.
+*/
+int
+parser(m) int m; {
+    int tfcode, xx, yy, zz;            /* Workers */
+
+#ifndef NOSPL
+    int inlevel;                       /* Level we were called at */
+#endif /* NOSPL */
+    char *cbp;                         /* Command buffer pointer */
+#ifdef MAC
+    extern char *lfiles;               /* Fake extern cast */
+#endif /* MAC */
+
+#ifdef AMIGA
+    reqres();                  /* restore AmigaDOS requestors */
+#endif /* AMIGA */
+
+    what = W_COMMAND;          /* Now we're parsing commands. */
+#ifndef NOSPL
+    if (cmdlvl == 0)           /* If at top (interactive) level, */
+#else
+    if (tlevel < 0)
+#endif /* NOSPL */
+      concb((char)escape);     /* put console in cbreak mode. */
+
+#ifndef NOSPL
+    ifcmd[0] = 0;              /* Command-level related variables */
+    iftest[0] = 0;             /* initialize variables at top level */
+    count[0] = 0;              /* of stack... */
+    inlevel = cmdlvl;          /* Current macro level */
+    debug(F101,"&parser entry maclvl","",maclvl);
+    debug(F101,"&parser entry inlevel","",inlevel);
+    debug(F101,"&parser entry tlevel","",tlevel);
+    debug(F101,"&parser entry cmdlvl","",cmdlvl);
+    debug(F101,"&parser entry m","",m);
+#endif /* NOSPL */
+
+/*
+  sstate becomes nonzero when a command has been parsed that requires some
+  action from the protocol module.  Any non-protocol actions, such as local
+  directory listing or terminal emulation, are invoked directly from below.
+*/
+#ifdef COMMENT
+    if (local && pflag)                        /* Just returned from connect? */
+      printf("\n");
+#endif /* COMMENT */
+    sstate = 0;                                /* Start with no start state. */
+#ifndef NOFRILLS
+    rmailf = rprintf = 0;              /* MAIL and PRINT modifiers for SEND */
+    *optbuf = NUL;                     /* MAIL and PRINT options */
+#endif /* NOFRILLS */
+    while (sstate == 0) {              /* Parse cmds until action requested */
+       debug(F100,"top of parse loop","",0);
+
+    /* Take requested action if there was an error in the previous command */
+
+#ifndef MAC
+       conint(trap,stptrap);           /* In case we were just fg'd */
+       bgchk();                        /* Check background status */
+#endif /* MAC */
+
+       debug(F101,"tlevel","",tlevel);
+#ifndef NOSPL                          /* In case we just reached top level */
+       debug(F101,"cmdlvl","",cmdlvl);
+       if (cmdlvl == 0) concb((char)escape);
+#else
+       if (tlevel < 0) concb((char)escape);
+#endif /* NOSPL */
+
+#ifndef NOSPL
+       if (success == 0) {
+           if (cmdstk[cmdlvl].src == CMD_TF && terror) {
+               printf("Command error: take file terminated.\n");
+               popclvl();
+               if (cmdlvl == 0) return(0);
+           }
+           if (cmdstk[cmdlvl].src == CMD_MD && merror) {
+               printf("Command error: macro terminated.\n");
+               popclvl();
+               if (m && (cmdlvl < inlevel))
+                 return((int) sstate);
+           }
+       }
+
+       nulcmd = (m == 2);
+#else
+       if (success == 0 && tlevel > -1 && terror) {
+           printf("Command error: take file terminated.\n");
+           popclvl();
+           cmini(ckxech);              /* Clear the cmd buffer. */
+           if (tlevel < 0)             /* Just popped out of cmd files? */
+             return(0);                /* End of init file or whatever. */
+       }
+#endif /* NOSPL */
+
+#ifdef MAC
+       /* Check for TAKE initiated by menu. */
+       if ((tlevel == -1) && lfiles)
+           startlfile();
+#endif /* MAC */
+
+        /* If in TAKE file, check for EOF */
+#ifndef NOSPL
+#ifdef MAC
+       if
+#else
+       while
+#endif /* MAC */
+         ((cmdstk[cmdlvl].src == CMD_TF)  /* If end of take file */
+              && (tlevel > -1)
+              && feof(tfile[tlevel])) {
+           popclvl();                  /* pop command level */
+           cmini(ckxech);              /* and clear the cmd buffer. */
+           if (cmdlvl == 0)            /* Just popped out of all cmd files? */
+             return(0);                /* End of init file or whatever. */
+       }
+#ifdef MAC
+       miniparser(1);
+       if (sstate == 'a') {            /* if cmd-. cancel */
+           debug(F100, "parser: cancel take due to sstate", "", sstate);
+           sstate = '\0';
+           dostop();
+           return(0);                  /* End of init file or whatever. */
+       }
+#endif /*  MAC */
+
+#else /* NOSPL */
+       if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
+           popclvl();                  /* Pop up one level. */
+           cmini(ckxech);              /* and clear the cmd buffer. */
+           if (tlevel < 0)             /* Just popped out of cmd files? */
+             return(0);                /* End of init file or whatever. */
+       }
+#endif /* NOSPL */
+
+#ifndef NOSPL
+        if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
+           debug(F100,"parser macro","",0);
+           maclvl = cmdstk[cmdlvl].lvl; /* Get current level */
+           debug(F101,"parser maclvl","",maclvl);
+           cbp = cmdbuf;               /* Copy next cmd to command buffer. */
+           *cbp = NUL;
+           if (*savbuf) {              /* In case then-part of 'if' command */
+               strcpy(cbp,savbuf);     /* was saved, restore it. */
+               *savbuf = '\0';
+           } else {                    /* Else get next cmd from macro def */
+               if (getncm(cbp,CMDBL) < 0) {
+                   if (m && (cmdlvl < inlevel))
+                     return((int) sstate);
+                   else /* if (!m) */ continue;
+               }
+           }
+           debug(F110,"cmdbuf from macro",cmdbuf,0);
+
+       } else if (cmdstk[cmdlvl].src == CMD_TF)
+#else
+         if (tlevel > -1)  
+#endif /* NOSPL */
+         {
+#ifndef NOSPL
+           if (*savbuf) {              /* In case THEN-part of IF command */
+               strcpy(cmdbuf,savbuf);  /* was saved, restore it. */
+               *savbuf = '\0';
+           } else
+#endif /* NOSPL */
+
+             /* Get next line from TAKE file */
+
+             if ((tfcode = getnct(cmdbuf,CMDBL)) < 0) {
+                 if (tfcode < -1) {    /* Error */
+                     printf("?Error in TAKE command file: %s\n",
+                            (tfcode == -2) ? "Memory allocation failure" :
+                            "Line too long or contains NUL characters"
+                            );
+                     popclvl();
+                 }
+                 continue;             /* -1 means EOF */
+             }     
+
+        /* If interactive, get next command from user. */
+
+       } else {                        /* User types it in. */
+           if (pflag) prompt(xxstring);
+           cmini(ckxech);
+       }
+
+        /* Now know where next command is coming from. Parse and execute it. */
+
+       repars = 1;                     /* 1 = command needs parsing */
+       displa = 0;                     /* Assume no file transfer display */
+
+       while (repars) {                /* Parse this cmd until entered. */
+           debug(F101,"parser top of while loop","",0);
+           cmres();                    /* Reset buffer pointers. */
+           xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring);
+           debug(F101,"top-level cmkey2","",xx);
+           if (xx == -5) {
+               yy = chktok(toktab);
+               debug(F101,"top-level cmkey token","",yy);
+               ungword();
+               switch (yy) {
+#ifndef NOPUSH
+                 case '!': xx = XXSHE; break; /* Shell escape */
+#endif /* NOPUSH */
+                 case '#': xx = XXCOM; break; /* Comment */
+                 case ';': xx = XXCOM; break; /* Comment */
+#ifndef NOSPL
+                 case ':': xx = XXLBL; break; /* GOTO label */
+#endif /* NOSPL */
+#ifndef NOPUSH
+                  case '@': xx = XXSHE; break; /* Shell (DCL) escape */
+#endif /* NOPUSH */
+                 default: 
+                   printf("\n?Invalid - %s\n",cmdbuf);
+                   xx = -2;
+               }
+           }
+
+#ifndef NOSPL
+            /* Special handling for IF..ELSE */
+
+           if (ifcmd[cmdlvl])          /* Count stmts after IF */
+             ifcmd[cmdlvl]++;
+           if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM)
+             ifcmd[cmdlvl] = 0;
+
+           /* Execute the command and take action based on return code. */
+
+           if (nulcmd) {               /* Ignoring this command? */
+               xx = XXCOM;             /* Make this command a comment. */
+           }
+#endif /* NOSPL */
+
+           zz = docmd(xx);     /* Parse rest of command & execute. */
+           debug(F101,"docmd returns","",zz);
+#ifdef MAC
+           if (tlevel > -1) {
+               if (sstate == 'a') {    /* if cmd-. cancel */
+                   debug(F110, "parser: cancel take, sstate:", "a", 0);
+                   sstate = '\0';
+                   dostop();
+                   return(0);          /* End of init file or whatever. */
+               }
+           }
+#endif /* MAC */
+           switch (zz) {
+               case -4:                /* EOF (e.g. on redirected stdin) */
+                   doexit(GOOD_EXIT,xitsta); /* ...exit successfully */
+               case -1:                /* Reparse needed */
+                   repars = 1;         /* Just set reparse flag and  */
+                   continue;
+               case -6:                /* Invalid command given w/no args */
+               case -2:                /* Invalid command given w/args */
+#ifdef COMMENT
+#ifndef NOSPL
+                   /* This is going to be really ugly... */
+                   yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */
+                   if (yy > -1) {                  /* If it's there */
+                       if (zz == -2) {             /* insert "do" */
+                           char *mp;
+                           mp = malloc((int)strlen(cmdbuf) + 5);
+                           if (!mp) {
+                               printf("?malloc error 1\n");
+                               return(-2);
+                           }
+                           sprintf(mp,"do %s ",cmdbuf);
+                           strcpy(cmdbuf,mp);
+                           free(mp);
+                       } else sprintf(cmdbuf,"do %s %c",atmbuf, CR);
+                       if (ifcmd[cmdlvl] == 2) /* This one doesn't count! */
+                         ifcmd[cmdlvl]--;
+                       debug(F111,"stuff cmdbuf",cmdbuf,zz);
+                       repars = 1;     /* go for reparse */
+                       continue;
+                   } else {
+                       char *p;
+                       int n;
+                       p = cmdbuf;
+                       lp = line;     
+                       n = LINBUFSIZ;
+                       if (cmflgs == 0) printf("\n");
+                       if (xxstring(p,&lp,&n) > -1) 
+                         printf("?Invalid: %s\n",line);
+                       else
+                         printf("?Invalid: %s\n",cmdbuf);
+                   } /* (fall thru...) */
+#else
+                   printf("?Invalid: %s\n",cmdbuf);
+#endif /* NOSPL */
+#else
+                   printf("?Invalid: %s\n",cmdbuf);
+#endif /* COMMENT */
+
+               case -9:                /* Bad, error message already done */
+                   success = 0;
+                   debug(F110,"top-level cmkey failed",cmdbuf,0);
+                   if (pflag == 0)     /* if background, terminate */
+                     fatal("Kermit command error in background execution");
+                   cmini(ckxech);      /* (fall thru) */
+
+               case -3:                /* Empty command OK at top level */
+                   repars = 0;         /* Don't need to reparse. */
+                   continue;           /* Go back and get another command. */
+
+               default:                /* Command was successful. */
+#ifndef NOSPL
+                   debug(F101,"parser preparing to continue","",maclvl);
+#endif /* NOSPL */
+                   repars = 0;         /* Don't need to reparse. */
+                   continue;           /* Go back and get another command. */
+               }
+       }
+#ifndef NOSPL
+       debug(F101,"parser breaks out of while loop","",maclvl);
+       if (m && (cmdlvl < inlevel))  return((int) sstate);
+#endif /* NOSPL */
+    }
+
+/* Got an action command, return start state. */
+#ifdef COMMENT
+    /* This is done in ckcpro.w instead, no need to do it twice. */
+    /* Interrupts off only if remote */
+    if (!local) connoi();
+#endif /* COMMENT */
+    return((int) sstate);
+}
+
+#ifndef NOSPL
+/* OUTPUT command */
+
+int                                    /* This could easily become a macro */
+#ifdef CK_ANSIC
+xxout(char c)
+#else
+xxout(c) char c; 
+#endif /* CK_ANSIC */
+/* xxout */ {                          /* Function to output a character. */
+    debug(F101,"xxout","",c);
+    if (local)                         /* If in local mode */
+      return(ttoc(c));                 /* then to the external line */
+    else return(conoc(c));             /* otherwise to the console. */
+}
+
+/* Returns 0 on failure, 1 on success */
+
+int
+dooutput(s) char *s; {
+    int x, y, quote;
+
+    if (local) {                       /* Condition external line */
+       y = ttvt(speed,flow);
+       if (y < 0) return(0);
+    }
+    quote = 0;                         /* Initialize backslash (\) quote */
+
+#ifdef COMMENT
+/* This is done automatically in ttopen() now... */
+#ifdef TNCODE
+    if (network && ttnproto == NP_TELNET) /* If telnet connection, */
+      if (!tn_init++) tn_ini();           /* initialize it if necessary */
+#endif /* TNCODE */
+#endif /* COMMENT */
+    while (x = *s++) {                 /* Loop through the string */
+       y = 0;                          /* Error code, 0 = no error. */
+       if (x == CMDQ) {                /* Look for \b or \B in string */
+            quote++;                   /* Got \ */
+           continue;                   /* Get next character */
+       } else if (quote) {             /* This character is quoted */
+           if (quote == 1 && (x == 'b' || x == 'B')) { /* If \b or \B */
+               debug(F100,"OUTPUT BREAK","",0);
+               ttsndb();               /* send BREAK signal */
+               quote = 0;              /* Turn off quote flag */
+               continue;               /* and not the b or B */
+#ifdef CK_LBRK
+           } else if (quote == 1 && (x == 'l' || x == 'L')) { /* \l or \L */
+               debug(F100,"OUTPUT Long BREAK","",0);
+               ttsndlb();              /* send Long BREAK signal */
+               quote = 0;              /* Turn off quote flag */
+               continue;               /* and not the l or L */
+#endif /* CK_LBRK */
+           } else {                    /* if \ not followed by b or B */
+               y = xxout(dopar(CMDQ)); /* output the backslash. */
+               quote = 0;              /* Turn off quote flag */
+           }
+       } else quote = 0;               /* Turn off quote flag */
+       y = xxout(dopar((char)x));      /* Output this character */
+       if (y < 0) {
+           printf("output error.\n");
+           return(0);
+       }
+       if (x == '\015') {              /* User typed carriage return */
+           if (tnlm                    /* If TERMINAL NEWLINE-MODE is ON */
+#ifdef TNCODE
+               || (network &&          /* Or we have a network connection */
+                   ttnproto == NP_TELNET && /* using TELNET protocol */
+                   tn_nlm              /* and TELNET NEWLINE-MODE is ON */
+                   )
+#endif /* TNCODE */
+               )
+             xxout(dopar('\012'));     /* Send LF too (CR => CRLF) */
+       }
+       if (seslog && duplex)
+         if (zchout(ZSFILE,(char)x) < 0) seslog = 0;
+    }
+    return(1);
+}
+#endif /* NOSPL */
+
+
+/* Display version herald and initial prompt */
+
+VOID
+herald() {
+    int x = 0;
+    if (bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1;
+    debug(F101,"herald","",backgrd);
+    if (x == 0)
+#ifdef datageneral
+      printf("%s,%s\nType ? or HELP for help\n",versio,ckxsys);
+#else
+      printf("%s,%s\n\rType ? or HELP for help\n",versio,ckxsys);
+#endif /* datageneral */
+}
+#ifndef NOSPL
+/*  M L O O K  --  Lookup the macro name in the macro table  */
+/*
+ Call this way:  v = mlook(table,word,n);
+   table - a 'struct mtab' table.
+   word  - the target string to look up in the table.
+   n     - the number of elements in the table.
+ The keyword table must be arranged in ascending alphabetical order, and
+ all letters must be lowercase.
+ Returns the table index, 0 or greater, if the name was found, or:
+  -3 if nothing to look up (target was null),
+  -2 if ambiguous,
+  -1 if not found.
+ A match is successful if the target matches a keyword exactly, or if
+ the target is a prefix of exactly one keyword.  It is ambiguous if the
+ target matches two or more keywords from the table.
+*/
+int
+mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; {
+    int i, v, cmdlen;
+/* Lowercase & get length of target, if it's null return code -3. */
+    if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
+/* Not null, look it up */
+    for (i = 0; i < n-1; i++) {
+        if (!strcmp(table[i].kwd,cmd) ||
+           ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
+             strncmp(table[i+1].kwd,cmd,cmdlen))) {
+                return(i);
+             }
+        if (v) return(-2);
+    }   
+/* Last (or only) element */
+    if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
+        return(n-1);
+    } else return(-1);
+}
+
+/* mxlook is like mlook, but an exact full-length match is required */
+
+int
+mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
+    int i, cmdlen;
+    if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
+    for (i = 0; i < n; i++)
+      if (((int)strlen(table[i].kwd) == cmdlen) &&
+         (!strncmp(table[i].kwd,cmd,cmdlen))) return(i);
+    return(-1);
+}
+
+/*
+  This routine is for the benefit of those compilers that can't handle
+  long string constants or continued lines within them.  Long predefined
+  macros like FOR, WHILE, and XIF have their contents broken up into
+  arrays of string pointers.  This routine concatenates them back into a
+  single string again, and then calls the real addmac() routine to enter
+  the definition into the macro table.
+*/
+int
+addmmac(nam,s) char *nam, *s[]; {      /* Add a multiline macro definition */
+    int i, x, y; char *p;
+    x = 0;                             /* Length counter */
+    for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */
+       debug(F111,"addmmac line",s[i],y);      
+       x += y;
+    }
+    debug(F101,"addmmac lines","",i);
+    debug(F101,"addmmac loop exit","",y);
+    debug(F111,"addmmac length",nam,x);
+    if (x < 0) return(-1);
+
+    p = malloc(x+1);                   /* Allocate space for all of it. */
+    if (!p) {
+       printf("?addmmac malloc error: %s\n",nam);
+       debug(F110,"addmmac malloc error",nam,0);
+       return(-1);
+    }
+    *p = '\0';                         /* Start off with null string. */
+    for (i = 0; *s[i]; i++)            /* Concatenate them all together. */
+      strcat(p,s[i]);
+    y = (int)strlen(p);                        /* Final precaution. */
+    debug(F111,"addmmac constructed string",p,y);
+    if (y == x) {
+       y = addmac(nam,p);              /* Add result to the macro table. */
+    } else {
+       debug(F100,"addmmac length mismatch","",0);
+       printf("\n!addmmac internal error!\n");
+       y = -1;
+    }
+    free(p);                           /* Free the temporary copy. */
+    return(y); 
+}
+
+/* Here is the real addmac routine. */
+
+int
+addmac(nam,def) char *nam, *def; {     /* Add a macro to the macro table */
+    int i, x, y, z, namlen, deflen;
+    char *p, c;
+
+    if (!nam) return(-1);
+    namlen = (int)strlen(nam);         /* Get argument lengths */
+    debug(F111,"addmac nam",nam,namlen);
+    if (!def) {                                /* Watch out for null pointer */
+       deflen = 0;
+       debug(F111,"addmac def","(null pointer)",deflen);
+    } else {
+       deflen = (int)strlen(def);
+       debug(F111,"addmac def",def,deflen);
+    }
+    if (deflen < 0) return(-1);                /* strlen() failure, fail. */
+    if (namlen < 1) return(-1);                /* No name given, fail. */
+
+    if (*nam == CMDQ) nam++;           /* Backslash quote? */
+    if (*nam == '%') {                 /* Yes, if it's a variable name, */
+       delmac(nam);                    /* Delete any old value. */
+       if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */
+       if (deflen < 1) {               /* Null definition */
+           p = NULL;                   /* Better not malloc or strcpy! */
+       } else {                        /* A substantial definition */
+           p = malloc(deflen + 1);     /* Allocate space for it */
+           if (!p) {
+               printf("?addmac malloc error 2\n");
+               return(-1);
+           } else strcpy(p,def);       /* Copy definition into new space */
+       }
+
+       /* Now p points to the definition, or is a null pointer */
+
+       if (p)
+         debug(F110,"addmac p",p,0);
+       else
+         debug(F110,"addmac p","(null pointer)",0);
+
+       if (c >= '0' && c <= '9') {     /* Digit variable */
+           if (maclvl < 0) {           /* Are we calling or in a macro? */
+               g_var[c] = p;           /* No, it's a global "top level" one */
+               debug(F101,"addmac numeric global maclvl","",maclvl);
+           } else {                    /* Yes, it's a macro argument */
+               m_arg[maclvl][c - '0'] = p;
+               debug(F101,"addmac macro arg maclvl","",maclvl);
+           }
+       } else {                        /* It's a global variable */
+           if (c < 33 || c > GVARS) return(-1);
+           if (isupper(c)) c = tolower(c);
+           g_var[c] = p;               /* Put pointer in global-var table */
+           debug(F100,"addmac global","",0);
+       }
+       return(0);
+    } else if (*nam == '&') {          /* An array reference? */
+       char **q;
+       if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */
+         return(-1);                   /* return -1. */
+       if (chkarray(x,z) < 0)          /* If array not declared or */
+         return(-2);                   /* subscript out of range, ret -2 */
+       delmac(nam);                    /* Delete any current definition. */
+       x -= 96;                        /* Convert name letter to index. */
+       if ((q = a_ptr[x]) == NULL)     /* If array not declared, */
+         return(-3);                   /* return -3. */
+       if (deflen > 0) {
+           if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */
+               printf("addmac macro error 7: %s\n",nam);
+               return(-4);             /* for new def, return -4 on fail. */
+           }
+           strcpy(p,def);              /* Copy definition into new space. */
+       } else p = NULL;
+       q[z] = p;                       /* Store pointer to it. */
+       return(0);                      /* Done. */
+    } else debug(F110,"addmac macro def",nam,0);
+
+/* Not a macro argument or a variable, so it's a macro definition */
+
+    lower(nam);                                /* Lowercase the name */
+    if (mxlook(mactab,nam,nmac) > -1)  /* Look up, requiring exact match */
+      delmac(nam);                     /* if it's there, delete it. */
+    debug(F111,"addmac table size",nam,nmac);
+    for (y = 0;                                /* Find the alphabetical slot */
+        y < MAC_MAX && mactab[y].kwd != NULL && strcmp(nam,mactab[y].kwd) > 0;
+        y++) ;
+    if (y == MAC_MAX) {                        /* No more room. */
+       debug(F101,"addmac table overflow","",y);
+       return(-1);
+    } else debug(F111,"addmac position",nam,y);
+    if (mactab[y].kwd != NULL) {       /* Must insert */
+       for (i = nmac; i > y; i--) {    /* Move the rest down one slot */
+           mactab[i].kwd = mactab[i-1].kwd;
+           mactab[i].mval = mactab[i-1].mval;
+           mactab[i].flgs = mactab[i-1].flgs;
+       }
+    }
+    p = malloc(namlen + 1);            /* Allocate space for name */
+    if (!p) {
+       printf("?addmac malloc error 3: %s\n",nam);
+       return(-1);
+    }
+    strcpy(p,nam);                     /* Copy name into new space */
+    mactab[y].kwd = p;                 /* Add pointer to table */
+
+    if (deflen > 0) {                  /* Same deal for definition */
+       p = malloc(deflen + 1);         /* but watch out for null pointer */
+       if (p == NULL) {
+           printf("?addmac malloc error 5: %s\n", nam);
+           free(mactab[y].kwd);
+           mactab[y].kwd = NULL;
+           return(-1);
+       } else strcpy(p,def);           /* Copy the definition */
+    } else p = NULL;
+    mactab[y].mval = p;
+    mactab[y].flgs = 0;
+    nmac++;                            /* Count this macro */
+    return(y);
+}
+
+int
+delmac(nam) char *nam; {               /* Delete the named macro */
+    int i, x, z;
+    char *p, c;
+
+    if (!nam) return(0);               /* Watch out for null pointer */
+    debug(F110,"delmac nam",nam,0);
+    if (*nam == CMDQ) nam++;
+    if (*nam == '%') {                 /* If it's a variable name */
+       if (!(c = *(nam+1))) return(0); /* Get variable name letter or digit */
+       p = (char *)0;                  /* Initialize value pointer */
+       if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
+           p = m_arg[maclvl][c - '0']; /* Get pointer from macro-arg table */
+           m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */
+       } else {                        /* It's a global variable */
+           if (c < 33 || c > GVARS) return(0);
+           p = g_var[c];               /* Get pointer from global-var table */
+           g_var[c] = NULL;            /* Zero the table entry */
+       }
+       if (p) {
+           debug(F110,"delmac def",p,0);
+           free(p);                    /* Free the storage */
+       } else debug(F110,"delmac def","(null pointer)",0);
+       return(0);
+    }
+           
+    if (*nam == '&') {                 /* An array reference? */
+       char **q;
+       if (arraynam(nam,&x,&z) < 0)    /* If syntax is bad */
+         return(-1);                   /* return -1. */
+       x -= 96;                        /* Convert name to number. */
+       if ((q = a_ptr[x]) == NULL)     /* If array not declared, */
+         return(-2);                   /* return -2. */
+       if (z > a_dim[x])               /* If subscript out of range, */
+         return(-3);                   /* return -3. */
+       if (q[z]) {                     /* If there is an old value, */
+           debug(F110,"delman def",q[z],0);
+           free(q[z]);                 /* delete it. */
+           q[z] = NULL;
+       } else debug(F110,"delmac def","(null pointer)",0);
+    }
+
+   /* Not a variable or an array, so it must be a macro. */
+
+    if ((x = mlook(mactab,nam,nmac)) < 0) { /* Look it up */
+       debug(F111,"delmac mlook",nam,x);
+       return(x);
+    }
+    if (mactab[x].kwd)                 /* Free the storage for the name */
+      free(mactab[x].kwd);
+    if (mactab[x].mval)                        /* and for the definition */
+      free(mactab[x].mval);
+
+    for (i = x; i < nmac; i++) {       /* Now move up the others. */
+       mactab[i].kwd = mactab[i+1].kwd;
+       mactab[i].mval = mactab[i+1].mval;
+       mactab[i].flgs = mactab[i+1].flgs;
+    }
+    nmac--;                            /* One less macro */
+    mactab[nmac].kwd = NULL;           /* Delete last item from table */
+    mactab[nmac].mval = NULL;
+    mactab[nmac].flgs = 0;
+    return(0);
+}
+
+VOID
+initmac() {                            /* Init macro & variable tables */
+    int i, j;
+
+    nmac = 0;                          /* No macros */
+    for (i = 0; i < MAC_MAX; i++) {    /* Initialize the macro table */
+       mactab[i].kwd = NULL;
+       mactab[i].mval = NULL;
+       mactab[i].flgs = 0;
+    }
+    for (i = 0; i < MACLEVEL; i++) {   /* Init the macro argument tables */
+       mrval[i] = NULL;
+       for (j = 0; j < 10; j++) {
+           m_arg[i][j] = NULL;
+       }
+    }
+    for (i = 0; i < GVARS; i++) {      /* And the global variables table */
+       g_var[i] = NULL;
+    }
+    for (i = 0; i < 26; i++) {         /* And the table of arrays */
+       a_ptr[i] = (char **) NULL;      /* Null pointer for each */
+       a_dim[i] = 0;                   /* and a dimension of zero */
+    }
+}
+
+int
+popclvl() {                            /* Pop command level, return cmdlvl */
+    if (cmdlvl < 1) {                  /* If we're already at top level */
+       cmdlvl = 0;                     /* just make sure all the */
+       tlevel = -1;                    /* stack pointers are set right */
+       maclvl = -1;                    /* and return */
+    } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */
+       if (tlevel > -1) {              /* Yes, */
+           if (tfnam[tlevel]) {
+               free(tfnam[tlevel]);
+               tfnam[tlevel] = NULL;
+           }
+           fclose(tfile[tlevel--]);    /* close it and pop take level */
+           cmdlvl--;                   /* pop command level */
+       } else tlevel = -1;
+    } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
+       if (maclvl > -1) {              /* Yes, */
+           debug(F111,"popclvl before",macx[maclvl],maclvl);
+           macp[maclvl] = "";          /* set macro pointer to null string */
+           *cmdbuf = '\0';             /* clear the command buffer */
+           if (mrval[maclvl+1]) {      /* Free any deeper return values. */
+               free(mrval[maclvl+1]);
+               mrval[maclvl+1] = NULL;
+           }
+           maclvl--;                   /* pop macro level */
+           cmdlvl--;                   /* and command level */
+           debug(F111,"popclvl after ",
+                 macx[maclvl] ? macx[maclvl] : "",maclvl);
+       } else maclvl = -1;
+    }
+#ifndef MAC
+    if (cmdlvl < 1) {                  /* If back at top level */
+       conint(trap,stptrap);           /* Fix interrupts */
+       bgchk();                        /* Check background status */
+       concb((char)escape);            /* Go into cbreak mode */
+    }
+#endif /* MAC */
+    return(cmdlvl < 1 ? 0 : cmdlvl);   /* Return command level */
+}
+#else /* No script programming language */
+int popclvl() {                                /* Just close current take file. */
+    if (tlevel > -1) {                 /* if any... */
+       if (tfnam[tlevel]) {
+           free(tfnam[tlevel]);
+           tfnam[tlevel] = NULL;
+       }
+       fclose(tfile[tlevel--]);
+    }
+    if (tlevel == -1) {                        /* And if back at top level */
+       conint(trap,stptrap);           /* check and set interrupts */
+        bgchk();                       /* and background status */
+        concb((char)escape);           /* and go back into cbreak mode. */
+    }
+    return(tlevel + 1);
+}
+#endif /* NOSPL */
+
+/* STOP - get back to C-Kermit prompt, no matter where from. */
+
+int
+dostop() {
+    while ( popclvl() )  ;     /* Pop all macros & take files */
+#ifndef NOSPL
+    while (cmpop() > -1) ;     /* And all recursive cmd pkg invocations */
+#endif /* NOSPL */
+    cmini(ckxech);             /* Clear the command buffer. */
+    return(0);
+}
+
+
+/* Close the given log */
+
+int
+doclslog(x) int x; {
+    int y;
+    switch (x) {
+#ifdef DEBUG
+       case LOGD:
+           if (deblog == 0) {
+               printf("?Debugging log wasn't open\n");
+               return(0);
+           }
+           *debfil = '\0';
+           deblog = 0;
+           return(zclose(ZDFILE));
+#endif /* DEBUG */
+
+       case LOGP:
+           if (pktlog == 0) {
+               printf("?Packet log wasn't open\n");
+               return(0);
+           }
+           *pktfil = '\0';
+           pktlog = 0;
+           return(zclose(ZPFILE));
+       case LOGS:
+           if (seslog == 0) {
+               printf("?Session log wasn't open\n");
+               return(0);
+           }
+           *sesfil = '\0';
+           seslog = 0;
+           return(zclose(ZSFILE));
+#ifdef TLOG
+       case LOGT:
+           if (tralog == 0) {
+               printf("?Transaction log wasn't open\n");
+               return(0);
+           }
+           *trafil = '\0';
+           tralog = 0;
+           return(zclose(ZTFILE));
+#endif /* TLOG */
+#ifndef NOSPL
+          case LOGW:                   /* WRITE file */
+         case LOGR:                    /* READ file */
+           y = (x == LOGR) ? ZRFILE : ZWFILE;
+           if (chkfn(y) < 1)           /* If no file to close */
+             return(1);                /* succeed silently. */
+           return(zclose(y));          /* Otherwise, close the file. */
+#endif /* NOSPL */
+
+       default:
+           printf("\n?Unexpected log designator - %ld\n", x);
+           return(0);
+       }
+}
+
+#ifndef NOSERVER
+#ifndef NOFRILLS
+static char *nm[] = { "disabled", "enabled" };
+#endif /* NOFRILLS */
+#endif /* NOSERVER */
+
+static int slc = 0;                    /* Screen line count */
+
+#ifndef NOSHOW
+#ifndef NOFRILLS
+#define xxdiff(v,sys) strncmp(v,sys,strlen(sys))
+VOID
+shover() {
+    printf("\nVersions:\n %s\n Numeric: %ld",versio,vernum);
+    if (verwho) printf("-%d",verwho);
+    printf(xxdiff(ckxv,ckxsys) ? "\n %s for%s\n" : "\n %s\n",ckxv,ckxsys);
+    printf(xxdiff(ckzv,ckzsys) ? " %s for%s\n" : " %s\n",ckzv,ckzsys);
+    printf(" %s\n",protv);
+    printf(" %s\n",fnsv);
+    printf(" %s\n %s\n",cmdv,userv);
+#ifndef NOCSETS
+    printf(" %s\n",xlav);
+#endif /* NOCSETS */
+#ifndef MAC
+    printf(" %s\n",connv);
+#endif /* MAC */
+#ifndef NODIAL
+    printf(" %s\n",dialv);
+#endif /* NODIAL */
+#ifndef NOSCRIPT
+    printf(" %s\n",loginv);
+#endif /* NOSCRIPT */
+#ifdef NETCONN
+    printf(" %s\n",cknetv);
+#endif /* NETCONN */
+    printf("\n");
+}
+
+VOID
+shofea() {
+#ifdef OS2
+#ifdef M_I286
+    printf("\nOS/2 16-bit.\n");
+#else
+    printf("\nOS/2 32-bit.\n");
+#endif /* M_I286 */
+#endif /* OS2 */
+    printf("\nSpecial features:\n");
+#ifdef NETCONN
+    printf(" Network support (type SHOW NET for further info)\n");
+#endif /* NETCONN */
+#ifndef NOCSETS
+    printf(" Latin-1 (West European) character-set translation\n");
+#ifdef LATIN2
+    printf(" Latin-2 (East European) character-set translation\n");
+#endif /* LATIN2 */
+#ifdef CYRILLIC
+    printf(" Cyrillic (Russian, Ukrainian, etc) character-set translation\n");
+#endif /* CYRILLIC */
+#ifdef KANJI
+    printf(" Kanji (Japanese) character-set translation\n");
+#endif /* KANJI */
+#endif /* NOCSETS */
+
+#ifdef CK_CURSES
+    printf(" Fullscreen file transfer display\n");
+#endif /* CK_CURSES */
+
+    printf("\nFeatures not included:\n");
+#ifndef CK_CURSES
+#ifndef MAC
+    printf(" No fullscreen file transfer display\n");
+#endif /* MAC */
+#endif /* CK_CURSES */
+#ifdef NOSERVER
+    printf(" No server mode\n");
+#endif /* NOSERVER */
+#ifdef NODEBUG
+    printf(" No debugging\n");
+#endif /* NODEBUG */
+#ifdef NOTLOG
+    printf(" No transaction log\n");
+#endif /* NOTLOG */
+#ifdef NOHELP
+    printf(" No built-in help\n");
+#endif /* NOHELP */
+#ifndef NETCONN
+    printf(" No network support\n");
+#endif /* NETCONN */
+#ifdef NOMSEND
+    printf(" No MSEND command\n");
+#endif /* NOMSEND */
+#ifdef NODIAL
+    printf(" No DIAL command\n");
+#else
+#ifdef MINIDIAL
+    printf(" DIAL command for modems other than Hayes, CCITT, and Unknown\n");
+#endif /* MINIDIAL */
+#endif /* NODIAL */
+#ifdef NOXMIT
+    printf(" No TRANSMIT command\n");
+#endif /* NOXMIT */
+#ifdef NOSCRIPT
+    printf(" No SCRIPT command\n");
+#endif /* NOSCRIPT */
+#ifdef NOSPL
+    printf(" No script programming features\n");
+#endif /* NOSPL */
+#ifdef NOCSETS
+    printf(" No character-set translation\n");
+#else
+#ifndef LATIN2
+    printf(" No Latin-2 character-set translation\n");
+#endif /* LATIN2 */
+#ifdef NOCYRIL
+    printf(" No Cyrillic character-set translation\n");
+#endif /* NOCYRIL */
+#ifndef KANJI
+    printf(" No Kanji character-set translation\n");
+#endif /* KANJI */
+#endif /* NOCSETS */
+#ifdef NOCMDL
+    printf(" No command-line arguments\n");
+#endif /* NOCMDL */
+#ifdef NOFRILLS
+    printf(" No frills\n");
+#endif /* NOFRILLS */
+#ifdef NOPUSH
+    printf(" No escape to system\n");
+#endif /* NOPUSH */
+#ifdef NOJC
+#ifdef UNIX
+    printf(" No UNIX job control\n");
+#endif /* UNIX */
+#endif /* NOJC */
+#ifdef NOSETKEY
+    printf(" No SET KEY command\n");
+#endif /* NOSETKEY */
+#ifdef NOESCSEQ
+    printf(" No ANSI escape sequence recognition\n");
+#endif /* NOESCSEQ */
+#ifndef PARSENSE
+    printf(" No automatic parity detection\n");
+#endif /* PARSENSE */
+/*
+  Print all of Kermit's compile-time options, as well as C preprocessor
+  predefined symbols that might affect us...
+*/
+    printf("\nCompiler options:\n");
+#ifdef DEBUG
+#ifdef IFDEBUG
+    prtopt(" IFDEBUG");
+#else
+    prtopt(" DEBUG");
+#endif /* IFDEBUG */
+#endif /* DEBUG */
+#ifdef TLOG
+    prtopt(" TLOG");
+#endif /* TLOG */
+#ifdef NODIAL
+    prtopt(" NODIAL");
+#endif /* NODIAL */
+#ifdef MINIDIAL
+    prtopt(" MINIDIAL");
+#endif /* MINIDIAL */
+#ifdef DYNAMIC
+    prtopt(" DYNAMIC");
+#endif /* IFDEBUG */
+#ifndef NOSPL
+    sprintf(line," CMDDEP=%d",CMDDEP);
+    prtopt(line);
+#endif /* NOSPL */
+#ifdef UNIX
+    prtopt(" UNIX");
+#endif /* UNIX */
+#ifdef VMS
+    prtopt(" VMS");
+#endif /* VMS */
+#ifdef vms
+    prtopt(" vms");
+#endif /* vms */
+#ifdef VMSSHARE
+    prtopt(" VMSSHARE");
+#endif /* VMSSHARE */
+#ifdef datageneral
+    prtopt(" datageneral");
+#endif /* datageneral */
+#ifdef apollo
+    prtopt(" apollo");
+#endif /* apollo */
+#ifdef aegis
+    prtopt(" aegis");
+#endif /* aegis */
+#ifdef A986
+    prtopt(" A986");
+#endif /* A986 */
+#ifdef AMIGA
+    prtopt(" AMIGA");
+#endif /* AMIGA */
+#ifdef CONVEX9
+    prtopt(" CONVEX9");
+#endif /* CONVEX9 */
+#ifdef MAC
+    prtopt(" MAC");
+#endif /* MAC */
+#ifdef AUX
+    prtopt(" AUX");
+#endif /* AUX */
+#ifdef OS2
+    prtopt(" OS2");
+#endif /* OS2 */
+#ifdef OS9
+    prtopt(" OS9");
+#endif /* OS9 */
+#ifdef MSDOS
+    prtopt(" MSDOS");
+#endif /* MSDOS */
+#ifdef DIRENT
+    prtopt(" DIRENT");
+#endif /* DIRENT */
+#ifdef SDIRENT
+    prtopt(" SDIRENT");
+#endif /* SDIRENT */
+#ifdef NDIR
+    prtopt(" NDIR");
+#endif /* NDIR */
+#ifdef XNDIR
+    prtopt(" XNDIR");
+#endif /* XNDIR */
+#ifdef MATCHDOT
+    prtopt(" MATCHDOT");
+#endif /* MATCHDOT */
+#ifdef SAVEDUID
+    prtopt(" SAVEDUID");
+#endif /* SAVEDUID */
+#ifdef NOCCTRAP
+    prtopt(" NOCCTRAP");
+#endif /* NOCCTRAP */
+#ifdef SUNX25
+    prtopt(" SUNX25");
+#endif /* SUNX25 */
+#ifdef DECNET
+    prtopt(" DECNET");
+#endif /* DECNET */
+#ifdef ATT7300
+    prtopt(" ATT7300");
+#endif /* ATT7300 */
+#ifdef ATT6300
+    prtopt(" ATT6300");
+#endif /* ATT6300 */
+#ifdef HDBUUCP
+    prtopt(" HDBUUCP");
+#endif /* HDBUUCP */
+#ifdef NOUUCP
+    prtopt(" NOUUCP");
+#endif /* NOUUCP */
+#ifdef LONGFN
+    prtopt(" LONGFN");
+#endif /* LONGFN */
+#ifdef RDCHK
+    prtopt(" RDCHK");
+#endif /* RDCHK */
+#ifdef NAP
+    prtopt(" NAP");
+#endif /* NAP */
+#ifdef NAPHACK
+    prtopt(" NAPHACK");
+#endif /* NAPHACK */
+#ifdef NOIEXTEN
+    prtopt(" NOIEXTEN");
+#endif /* NOIEXTEN */
+#ifdef EXCELAN
+    prtopt(" EXCELAN");
+#endif /* EXCELAN */
+#ifdef PARAMH
+    prtopt(" PARAMH");
+#endif /* PARAMH */
+#ifdef INTERLAN
+    prtopt(" INTERLAN");
+#endif /* INTERLAN */
+#ifdef NOFILEH
+    prtopt(" NOFILEH");
+#endif /* NOFILEH */
+#ifdef NOSYSIOCTLH
+    prtopt(" NOSYSIOCTLH");
+#endif /* NOSYSIOCTLH */
+#ifdef DCLPOPEN
+    prtopt(" DCLPOPEN");
+#endif /* DCLPOPEN */
+#ifdef NOSETBUF
+    prtopt(" NOSETBUF");
+#endif /* NOSETBUF */
+#ifdef NOFDZERO
+    prtopt(" NOFDZERO");
+#endif /* NOFDZERO */
+#ifdef NOPOPEN
+    prtopt(" NOPOPEN");
+#endif /* NOPOPEN */
+#ifdef NOPARTIAL
+    prtopt(" NOPARTIAL");
+#endif /* NOPARTIAL */
+#ifdef NOSETREU
+    prtopt(" NOSETREU");
+#endif /* NOSETREU */
+#ifdef _POSIX_SOURCE
+    prtopt(" _POSIX_SOURCE");
+#endif /* _POSIX_SOURCE */
+#ifdef LCKDIR
+    prtopt(" LCKDIR");
+#endif /* LCKDIR */
+#ifdef ACUCNTRL
+    prtopt(" ACUCNTRL");
+#endif /* ACUCNTRL */
+#ifdef BSD4
+    prtopt(" BSD4");
+#endif /* BSD4 */
+#ifdef BSD44
+    prtopt(" BSD44");
+#endif /* BSD44 */
+#ifdef BSD41
+    prtopt(" BSD41");
+#endif /* BSD41 */
+#ifdef BSD43
+    prtopt(" BSD43");
+#endif /* BSD43 */
+#ifdef BSD29
+    prtopt(" BSD29");
+#endif /* BSD29 */
+#ifdef V7
+    prtopt(" V7");
+#endif /* V7 */
+#ifdef AIX370
+    prtopt(" AIX370");
+#endif /* AIX370 */
+#ifdef RTAIX
+    prtopt(" RTAIX");
+#endif /* RTAIX */
+#ifdef HPUX
+    prtopt(" HPUX");
+#endif /* HPUX */
+#ifdef HPUXPRE65
+    prtopt(" HPUXPRE65");
+#endif /* HPUXPRE65 */
+#ifdef DGUX
+    prtopt(" DGUX");
+#endif /* DGUX */
+#ifdef DGUX430
+    prtopt(" DGUX430");
+#endif /* DGUX430 */
+#ifdef DGUX540
+    prtopt(" DGUX540");
+#endif /* DGUX540 */
+#ifdef sony_news
+    prtopt(" sony_news");
+#endif /* sony_news */
+#ifdef CIE
+    prtopt(" CIE");
+#endif /* CIE */
+#ifdef XENIX
+    prtopt(" XENIX");
+#endif /* XENIX */
+#ifdef SCO_XENIX
+    prtopt(" SCO_XENIX");
+#endif /* SCO_XENIX */
+#ifdef ISIII
+    prtopt(" ISIII");
+#endif /* ISIII */
+#ifdef I386IX
+    prtopt(" I386IX");
+#endif /* I386IX */
+#ifdef RTU
+    prtopt(" RTU");
+#endif /* RTU */
+#ifdef PROVX1
+    prtopt(" PROVX1");
+#endif /* PROVX1 */
+#ifdef TOWER1
+    prtopt(" TOWER1");
+#endif /* TOWER1 */
+#ifdef UTEK
+    prtopt(" UTEK");
+#endif /* UTEK */
+#ifdef ZILOG
+    prtopt(" ZILOG");
+#endif /* ZILOG */
+#ifdef TRS16
+    prtopt(" TRS16");
+#endif /* TRS16 */
+#ifdef MINIX
+    prtopt(" MINIX");
+#endif /* MINIX */
+#ifdef C70
+    prtopt(" C70");
+#endif /* C70 */
+#ifdef AIXPS2
+    prtopt(" AIXPS2");
+#endif /* AIXPS2 */
+#ifdef AIXRS
+    prtopt(" AIXRS");
+#endif /* AIXRS */
+#ifdef UTSV
+    prtopt(" UTSV");
+#endif /* UTSV */
+#ifdef ATTSV
+    prtopt(" ATTSV");
+#endif /* ATTSV */
+#ifdef SVR3
+    prtopt(" SVR3");
+#endif /* SVR3 */
+#ifdef SVR4
+    prtopt(" SVR4");
+#endif /* SVR4 */
+#ifdef DELL_SVR4
+    prtopt(" DELL_SVR4");
+#endif /* DELL_SVR4 */
+#ifdef ICL_SVR4
+    prtopt(" ICL_SVR4");
+#endif /* ICL_SVR4 */
+#ifdef OSF
+    prtopt(" OSF");
+#endif /* OSF */
+#ifdef PTX
+    prtopt(" PTX");
+#endif /* PTX */
+#ifdef POSIX
+    prtopt(" POSIX");
+#endif /* POSIX */
+#ifdef SOLARIS
+    prtopt(" SOLARIS");
+#endif /* SOLARIS */
+#ifdef SUNOS4
+    prtopt(" SUNOS4");
+#endif /* SUNOS4 */
+#ifdef SUN4S5
+    prtopt(" SUN4S5");
+#endif /* SUN4S5 */
+#ifdef ENCORE
+    prtopt(" ENCORE");
+#endif /* ENCORE */
+#ifdef ultrix
+    prtopt(" ultrix");
+#endif
+#ifdef sxaE50
+    prtopt(" sxaE50");
+#endif
+#ifdef mips
+    prtopt(" mips");
+#endif
+#ifdef MIPS
+    prtopt(" MIPS");
+#endif
+#ifdef vax
+    prtopt(" vax");
+#endif
+#ifdef VAX
+    prtopt(" VAX");
+#endif
+#ifdef sun
+    prtopt(" sun");
+#endif
+#ifdef sun3
+    prtopt(" sun3");
+#endif
+#ifdef sun386
+    prtopt(" sun386");
+#endif
+#ifdef _SUN
+    prtopt(" _SUN");
+#endif
+#ifdef sun4
+    prtopt(" sun4");
+#endif
+#ifdef sparc
+    prtopt(" sparc");
+#endif
+#ifdef NEXT
+    prtopt(" NEXT");
+#endif
+#ifdef NeXT
+    prtopt(" NeXT");
+#endif
+#ifdef sgi
+    prtopt(" sgi");
+#endif
+#ifdef M_SYS5
+    prtopt(" M_SYS5");
+#endif
+#ifdef __SYSTEM_FIVE
+    prtopt(" __SYSTEM_FIVE");
+#endif
+#ifdef sysV
+    prtopt(" sysV");
+#endif
+#ifdef M_XENIX                         /* SCO Xenix V and UNIX/386 */
+    prtopt(" M_XENIX");
+#endif 
+#ifdef M_UNIX
+    prtopt(" M_UNIX");
+#endif
+#ifdef M_I386
+    prtopt(" M_I386");
+#endif
+#ifdef _M_I386
+    prtopt(" _M_I386");
+#endif
+#ifdef i386
+    prtopt(" i386");
+#endif
+#ifdef i286
+    prtopt(" i286");
+#endif
+#ifdef M_I286
+    prtopt(" M_I286");
+#endif
+#ifdef mc68000
+    prtopt(" mc68000");
+#endif
+#ifdef mc68010
+    prtopt(" mc68010");
+#endif
+#ifdef mc68020
+    prtopt(" mc68020");
+#endif
+#ifdef mc68030
+    prtopt(" mc68030");
+#endif
+#ifdef mc68040
+    prtopt(" mc68040");
+#endif
+#ifdef M_68000
+    prtopt(" M_68000");
+#endif
+#ifdef M_68010
+    prtopt(" M_68010");
+#endif
+#ifdef M_68020
+    prtopt(" M_68020");
+#endif
+#ifdef M_68030
+    prtopt(" M_68030");
+#endif
+#ifdef M_68040
+    prtopt(" M_68040");
+#endif
+#ifdef m68k
+    prtopt(" m68k");
+#endif
+#ifdef m88k
+    prtopt(" m88k");
+#endif
+#ifdef pdp11
+    prtopt(" pdp11");
+#endif
+#ifdef iAPX
+    prtopt(" iAPX");
+#endif
+#ifdef __hp9000s800
+    prtopt(" __hp9000s800");
+#endif
+#ifdef __hp9000s500
+    prtopt(" __hp9000s500");
+#endif
+#ifdef __hp9000s300
+    prtopt(" __hp9000s300");
+#endif
+#ifdef __hp9000s200
+    prtopt(" __hp9000s200");
+#endif
+#ifdef AIX
+    prtopt(" AIX");
+#endif
+#ifdef _AIXFS
+    prtopt(" _AIXFS");
+#endif
+#ifdef u370
+    prtopt(" u370");
+#endif
+#ifdef u3b
+    prtopt(" u3b");
+#endif
+#ifdef u3b2
+    prtopt(" u3b2");
+#endif
+#ifdef multimax
+    prtopt(" multimax");
+#endif
+#ifdef balance
+    prtopt(" balance");
+#endif
+#ifdef ibmrt
+    prtopt(" ibmrt");
+#endif
+#ifdef _IBMRT
+    prtopt(" _IBMRT");
+#endif
+#ifdef ibmrs6000
+    prtopt(" ibmrs6000");
+#endif
+#ifdef _AIX
+    prtopt(" _AIX");
+#endif /* _AIX */
+#ifdef _IBMR2
+    prtopt(" _IBMR2");
+#endif
+#ifdef __STRICT_BSD__
+    prtopt(" __STRICT_BSD__");
+#endif
+#ifdef __STRICT_ANSI__
+    prtopt(" __STRICT_ANSI__");
+#endif
+#ifdef _ANSI_C_SOURCE
+    prtopt(" _ANSI_C_SOURCE");
+#endif
+#ifdef __STDC__
+    prtopt(" __STDC__");
+#endif
+#ifdef __GNUC__                                /* gcc in ansi mode */
+    prtopt(" __GNUC__");
+#endif
+#ifdef GNUC                            /* gcc in traditional mode */
+    prtopt(" GNUC");
+#endif
+#ifdef CK_ANSIC
+    prtopt(" CK_ANSIC");
+#endif
+#ifdef CK_ANSILIBS
+    prtopt(" CK_ANSILIBS");
+#endif
+#ifdef _XOPEN_SOURCE
+    prtopt(" _XOPEN_SOURCE");
+#endif
+#ifdef _ALL_SOURCE
+    prtopt(" _ALL_SOURCE");
+#endif
+#ifdef _SC_JOB_CONTROL
+    prtopt(" _SC_JOB_CONTROL");
+#endif
+#ifdef _POSIX_JOB_CONTROL
+    prtopt(" _POSIX_JOB_CONTROL");
+#endif
+#ifdef SVR3JC
+    prtopt(" SVR3JC");
+#endif
+#ifdef _386BSD
+    prtopt(" _386BSD");
+#endif
+#ifdef _BSD
+    prtopt(" _BSD");
+#endif
+#ifdef TERMIOX
+    prtopt(" TERMIOX");
+#endif /* TERMIOX */
+#ifdef STERMIOX
+    prtopt(" STERMIOX");
+#endif /* STERMIOX */
+#ifdef CK_CURSES
+    prtopt(" CK_CURSES");
+#endif /* CK_CURSES */
+#ifdef CK_DTRCD
+    prtopt(" CK_DTRCD");
+#endif /* CK_DTRCD */
+#ifdef CK_DTRCTS
+    prtopt(" CK_DTRCTS");
+#endif /* CK_DTRCTS */
+#ifdef CK_RTSCTS
+    prtopt(" CK_RTSCTS");
+#endif /* CK_RTSCTS */
+    prtopt((char *)0);
+    printf("\n\n");
+}
+#endif /* NOFRILLS */
+#endif /* NOSHOW */
+
+#ifdef VMS
+int
+sholbl() {
+    printf("VMS Labeled File Features:\n");
+    printf(" acl %s (ACL info %s)\n",
+          lf_opts & LBL_ACL ? "on " : "off",
+          lf_opts & LBL_ACL ? "preserved" : "discarded");
+    printf(" backup-date %s (backup date/time %s)\n",
+          lf_opts & LBL_BCK ? "on " : "off",
+          lf_opts & LBL_BCK ? "preserved" : "discarded");
+    printf(" name %s (original filename %s)\n",
+          lf_opts & LBL_NAM ? "on " : "off",
+          lf_opts & LBL_NAM ? "preserved" : "discarded");
+    printf(" owner %s (original file owner id %s)\n",
+          lf_opts & LBL_OWN ? "on " : "off",
+          lf_opts & LBL_OWN ? "preserved" : "discarded");
+    printf(" path %s (original file's disk:[directory] %s)\n",
+          lf_opts & LBL_PTH ? "on " : "off",
+          lf_opts & LBL_PTH ? "preserved" : "discarded");
+}
+#endif /* VMS */
+
+#ifndef NOSHOW
+VOID
+shotcs(cs1,cs2) int cs1, cs2; {                /* Show terminal character set */
+#ifndef NOCSETS
+#ifndef MAC
+    int y;
+    char *s;
+#ifdef CK_ANSIC
+    int gettcs(int, int);
+#else
+    int gettcs();
+#endif /* CK_ANSIC */
+
+    printf(" Terminal character-set");
+    if (cs1 == cs2) {
+       printf(": transparent\n");
+    } else {
+       s = "unknown";
+       for (y = 0; y <= nfilc; y++)    /* Look up name in keyword table */
+         if (ttcstab[y].kwval == cs2) {
+             if (ttcstab[y].flgs & CM_INV) /* Skip synonyms */
+               continue;
+             s = ttcstab[y].kwd;
+             break;
+         }
+       printf("s:\n   Remote: %s\n   Local:  ",s);
+       s = "unknown";
+       for (y = 0; y <= nfilc; y++)
+         if (ttcstab[y].kwval == cs1) {
+               if (ttcstab[y].flgs & CM_INV) /* Skip synonyms */
+                 continue;
+               s = ttcstab[y].kwd;
+             break;
+         }
+       printf("%s",s);
+       if (cs2 != cs1) {
+           switch(gettcs(cs2,cs1)) {
+             case TC_USASCII:  s = "ascii";        break;
+             case TC_1LATIN:   s = "latin1-iso";   break;
+             case TC_2LATIN:   s = "latin2-iso";   break;
+             case TC_CYRILL:   s = "cyrillic-iso"; break;
+             case TC_JEUC:     s = "japanese-euc"; break;
+             default:          s = "transparent";  break;
+           }
+           printf("\n   Via:    %s\n",s);
+       }
+    }
+#endif /* MAC */
+#endif /* NOCSETS */
+}
+#endif /* NOSHOW */
+
+#ifndef NOSHOW
+int
+doshow(x) int x; {
+    int y, i; long zz;
+    char *s;
+
+#ifndef NOSETKEY
+    if (x == SHKEY) {                  /* SHOW KEY */
+       int c;
+       KEY ch;
+       CHAR *s;
+
+       if ((y = cmcfm()) < 0) return(y);           
+#ifdef MAC
+       printf("Not implemented\n");
+       return(0);
+#else /* Not MAC */
+       printf(" Press key: ");
+#ifdef UNIX
+#ifdef NOSETBUF
+       fflush(stdout);
+#endif /* NOSETBUF */
+#endif /* UNIX */
+       conbin((char)escape);           /* Put terminal in binary mode */
+       c = congks(0);                  /* Get character or scan code */
+       concb((char)escape);            /* Restore terminal to cbreak mode */
+       if (c < 0) {                    /* Check for error */
+           printf("?Error reading key\n");
+           return(0);
+       }
+#ifndef OS2
+/*
+  Do NOT mask when it can be a raw scan code, perhaps > 255
+*/
+       c &= cmdmsk;                    /* Apply command mask */
+#endif /* OS2 */
+       printf("\n Key code \\%d => ",c);
+        if (macrotab[c]) {             /* See if there's a macro */
+           printf("String: ");         /* If so, display its definition */
+            s = macrotab[c];
+           while (ch = *s++)
+             if (ch < 32 || ch == 127
+/*
+  Systems whose native character sets have graphic characters in C1...
+*/
+#ifndef NEXT                           /* NeXT */
+#ifndef AUX                            /* Macintosh */
+#ifndef XENIX                          /* IBM PC */
+#ifndef OS2                            /* IBM PC */
+                 || (ch > 127 && ch < 160)
+#endif /* OS2 */
+#endif /* XENIX */
+#endif /* AUX */
+#endif /* NEXT */
+                 )
+                printf("\\{%d}",ch);   /* Display control characters */
+             else putchar((char) ch);  /* in backslash notation */
+           printf("\n");
+        } else {                       /* No macro, show single character */
+           printf("Character: ");
+           ch = keymap[c];
+           if (ch < 32 || ch == 127 || ch > 255
+#ifndef NEXT
+#ifndef AUX
+#ifndef XENIX
+#ifndef OS2
+                 || (ch > 127 && ch < 160)
+#endif /* OS2 */
+#endif /* XENIX */
+#endif /* AUX */
+#endif /* NEXT */
+               )
+             printf("\\%d",(unsigned int) ch);
+           else printf("%c \\%d",ch,(unsigned int) ch);
+       }
+       if (ch == (KEY) c)
+         printf(" (self, no translation)\n");
+       else printf("\n");
+       return(1);
+#endif /* MAC */
+    }
+#endif /* NOSETKEY */
+
+#ifndef NOSPL
+    if (x == SHMAC) {                  /* SHOW MACRO */
+       x = cmfld("Macro name, or carriage return to see them all","",&s,
+                 NULL);
+       if (x == -3)                    /* This means they want see all */
+         *line = '\0';
+       else if (x < 0)                 /* Otherwise negative = parse error */
+         return(x);
+       else                            /* 0 or greater */
+         strcpy(line,s);               /* means they typed something */
+       if ((y = cmcfm()) < 0) return(y); /* Get confirmation */
+       if (*line) {
+           slc = 0;                    /* Initial SHO MAC line number */
+           x = mlook(mactab,s,nmac);   /* Look up what they typed */
+           switch (x) {
+             case -3:                  /* Nothing to look up */
+               return(0);
+             case -1:                  /* Not found */
+               printf("%s - not found\n",s);
+               return(0);
+             case -2:                  /* Ambiguous, matches more than one */
+               y = (int)strlen(line);
+               slc = 1;
+               for (x = 0; x < nmac; x++)
+                 if (!strncmp(mactab[x].kwd,line,y))
+                   if (shomac(mactab[x].kwd,mactab[x].mval) < 0) break;
+               return(1);
+             default:                  /* Matches one exactly */
+               shomac(mactab[x].kwd,mactab[x].mval);
+               return(1);
+           }
+       } else {                        /* They want to see them all */
+           printf("Macros:\n");
+           slc = 1;
+           for (y = 0; y < nmac; y++)
+             if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break;
+           return(1);
+       }
+    }
+#endif /* NOSPL */
+
+/*
+  Other SHOW commands only have two fields.  Get command confirmation here,
+  then handle with big switch() statement.
+*/
+    if ((y = cmcfm()) < 0) return(y);
+    switch (x) {
+
+#ifdef SUNX25
+        case SHPAD:
+            shopad();
+            break;
+#endif /* SUNX25 */
+
+#ifdef NETCONN
+       case SHNET:
+           shonet();
+           break;
+#endif /* NETCONN */
+
+       case SHPAR:
+           shopar();
+           break;
+        case SHATT:
+           shoatt();
+           break;
+#ifndef NOSPL
+       case SHCOU:
+           printf(" %d\n",count[cmdlvl]);
+           break;
+#endif /* NOSPL */
+
+#ifndef NOSERVER
+        case SHSER:                    /* Show Server */
+#ifndef NOFRILLS
+           printf("Function           Status:\n");
+           printf(" GET                %s\n",nm[en_get]);
+           printf(" SEND               %s\n",nm[en_sen]);          
+           printf(" REMOTE CD/CWD      %s\n",nm[en_cwd]);
+           printf(" REMOTE DELETE      %s\n",nm[en_del]);
+           printf(" REMOTE DIRECTORY   %s\n",nm[en_dir]);
+           printf(" REMOTE HOST        %s\n",nm[en_hos]);          
+           printf(" REMOTE SET         %s\n",nm[en_set]);          
+           printf(" REMOTE SPACE       %s\n",nm[en_spa]);          
+           printf(" REMOTE TYPE        %s\n",nm[en_typ]);          
+           printf(" REMOTE WHO         %s\n",nm[en_who]);
+           printf(" BYE                %s\n",nm[en_bye]);
+            printf(" FINISH             %s\n",nm[en_fin]);
+#endif /* NOFRILLS */
+           printf("Server timeout: %d\n",srvtim);
+           printf("Server display: %s\n\n", srvdis ? "on" : "off");
+           break;
+#endif /* NOSERVER */
+
+        case SHSTA:                    /* Status of last command */
+           printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
+           return(0);                  /* Don't change it */
+
+#ifdef MAC
+       case SHSTK: {                   /* Stack for MAC debugging */
+           long sp;
+
+           sp = -1;
+           loadA0 ((char *)&sp);       /* set destination address */
+           SPtoaA0();                  /* move SP to destination */
+           printf("Stack at 0x%x\n", sp);
+           show_queue();               /* more debugging */
+           break; 
+       }
+#endif /* MAC */
+
+       case SHTER:
+           printf(" Command bytesize:  %d bits\n",
+                  (cmdmsk == 0377) ? 8 : 7);
+           printf(" Terminal bytesize: %d bits\n",
+                  (cmask == 0377) ? 8 : 7);
+#ifdef OS2
+           printf(" Terminal type: %s\n",
+                  (tt_type == TT_VT102) ? "VT102" : "VT52");
+
+#endif /* OS2 */
+           printf(" Terminal echo: %s\n", duplex ? "local" : "remote");
+           printf(" Terminal locking-shift: %s\n", sosi ? "on" : "off");
+           printf(" Terminal newline-mode:  %s\n", tnlm ? "on" : "off");
+           printf(" Terminal cr-display:    %s\n",
+                  tt_crd ? "crlf" : "normal");
+#ifdef OS2
+/* Should show cursor and colors here too... */
+           printf(" Terminal arrow-keys:    %s\n",
+                  tt_arrow ? "cursor" : "application");
+           printf(" Terminal keypad-mode:   %s\n",
+                  tt_keypad ? "numeric" : "application");
+           printf(" Terminal wrap:          %s\n", tt_wrap ? "on" : "off");
+#endif /* OS2 */
+
+#ifndef NOCSETS
+           shotcs(tcsl,tcsr);
+#endif /* NOCSETS */
+           printf(" CONNECT-mode escape character: %d (Ctrl-%c, %s)\n",
+            escape,ctl(escape),(escape == 127 ? "DEL" : ccntab[escape]));
+#ifdef UNIX
+           printf(" Suspend: %s\n", suspend ? "on" : "off");
+#endif /* UNIX */
+           break;
+
+#ifndef NOFRILLS
+       case SHVER:
+           shover();
+           break;
+#endif /* NOFRILLS */
+#ifndef NOSPL
+       case SHBUI:                     /* Built-in variables */
+           i = 0;
+           for (y = 0; y < nvars; y++) {
+               printf(" \\v(%s) = %s\n",vartab[y].kwd,nvlook(vartab[y].kwd));
+               if (++i > SCRNLEN) {    /* More than a screenful... */
+                   if (!askmore())
+                     break;
+                   else
+                     i = 0;
+               }
+           }
+            break;
+
+       case SHFUN:                     /* Functions */
+           for (y = 0; y < nfuncs; y++)
+             printf(" \\f%s()\n",fnctab[y].kwd);
+           break;
+
+        case SHVAR:                    /* Global variables */
+           x = 0;                      /* Variable count */
+           slc = 1;                    /* Screen line count for "more?" */
+           for (y = 33; y < GVARS; y++)
+             if (g_var[y]) {
+                 if (x++ == 0) printf("Global variables:\n");
+                 sprintf(line," \\%%%c",y);
+                 if (shomac(line,g_var[y]) < 0) break;
+             }
+           if (!x) printf(" No variables defined\n");
+           break;
+
+        case SHARG:                    /* Args */
+           if (maclvl > -1) {
+               printf("Macro arguments at level %d\n",maclvl);
+               for (y = 0; y < 10; y++)
+                 if (m_arg[maclvl][y])
+                   printf(" \\%%%d = %s\n",y,m_arg[maclvl][y]);
+           } else {
+               printf(" No macro arguments at top level\n");
+           }
+           break;
+
+        case SHARR:                    /* Arrays */
+           x = 0;
+           for (y = 0; y < 27; y++)
+             if (a_ptr[y]) {
+                 if (x == 0) printf("Declared arrays:\n");
+                 x = 1;
+                 printf(" \\&%c[%d]\n",(y == 0) ? 64 : y + 96, a_dim[y]);
+             }
+           if (!x) printf(" No arrays declared\n");
+           break;
+#endif /* NOSPL */
+
+       case SHPRO:                     /* Protocol parameters */
+           shoparp();
+           printf("\n");
+           break;
+
+       case SHCOM:                     /* Communication parameters */
+           printf("\n");
+           shoparc();
+#ifndef NODIAL
+           printf("\n");
+#ifdef NETCONN
+           if (!network)
+#endif /* NETCONN */
+             shodial();
+#endif /* NODIAL */
+           printf("\n");
+           shomdm();
+           printf("\n");
+           break;
+
+       case SHFIL:                     /* File parameters */
+           shoparf();
+           printf("\n");
+           break;
+
+#ifndef NOCSETS
+       case SHLNG:                     /* Languages */
+           shoparl();
+           break;
+#endif /* NOCSETS */
+
+#ifndef NOSPL
+       case SHSCR:                     /* Scripts */
+           printf(" Take  Echo:     %s\n", techo  ? "On" : "Off");
+           printf(" Take  Error:    %s\n", terror ? "On" : "Off");
+           printf(" Macro Echo:     %s\n", mecho  ? "On" : "Off");
+           printf(" Macro Error:    %s\n", merror ? "On" : "Off");
+           printf(" Input Case:     %s\n", incase ? "Observe" : "Ignore");
+           printf(" Input Echo:     %s\n", inecho ? "On" : "Off");
+            printf(" Input Silence:  %d\n", insilence);
+           printf(" Input Timeout:  %s\n", intime ? "Quit" : "Proceed");
+#ifndef NOSCRIPT
+           printf(" Script Echo:    %s\n", secho  ? "On" : "Off");
+#endif /* NOSCRIPT */
+           break;
+#endif /* NOSPL */
+
+#ifndef NOXMIT
+         case SHXMI:
+           printf(" File type: %s\n", binary ? "binary" : "text");
+#ifndef NOCSETS
+           shotcs(tcsl,tcsr);
+#endif /* NOCSETS */
+           printf(" Terminal echo: %s\n", duplex ? "local" : "remote");
+            printf(" Transmit EOF: ");
+           if (*xmitbuf == NUL) {
+               printf("none\n");
+           } else {
+               char *p;
+               p = xmitbuf;
+               while (*p) {
+                   if (*p < SP)
+                     printf("^%c",ctl(*p));
+                   else
+                     printf("%c",*p);
+                   p++;
+               }
+               printf("\n");
+           }
+           if (xmitf)
+             printf(" Transmit Fill: %d (fill character for blank lines)\n",
+                  xmitf);
+           else printf(" Transmit Fill: none\n");
+           printf(" Transmit Linefeed: %s\n",
+                  xmitl ? "on (send linefeeds too)" : "off");
+           if (xmitp) 
+             printf(" Transmit Prompt: %d (host line end character)\n",xmitp);
+           else printf(" Transmit Prompt: none\n");
+           printf(" Transmit Echo: %s\n",
+                  xmitx ? "on" : "off");
+           printf(" Transmit Locking-Shift: %s\n",xmits ? "on" : "off");
+           printf(" Transmit Pause: %d milliseconds\n", xmitw);
+           break;
+#endif /* NOXMIT */
+
+         case SHMOD:                   /* SHOW MODEM */
+           shmdmlin();
+           printf("\n");
+           shomdm();
+           break;
+
+#ifndef MAC
+          case SHDFLT:
+           zsyscmd(PWDCMD);
+            break;
+#endif /* MAC */
+
+          case SHESC:
+           printf(" Escape character: Ctrl-%c (ASCII %d, %s)\r\n",
+              ctl(escape), escape, (escape == 127 ? "DEL" : ccntab[escape]));
+           break;
+
+#ifndef NODIAL
+         case SHDIA:
+           shmdmlin();
+           printf(", speed: ");
+           if ((zz = ttgspd()) < 0) {
+               printf("unknown\n");
+           } else {
+               if (zz == 8880) printf("75/1200\n"); else printf("%ld\n",zz);
+           }
+           doshodial();
+           if (carrier == CAR_OFF) s = "off";
+           else if (carrier == CAR_ON) s = "on";
+           else if (carrier == CAR_AUT) s = "auto";
+           else s = "unknown";
+           printf(" Carrier: %s", s);
+           if (carrier == CAR_ON) {
+               if (cdtimo) printf(", timeout: %d sec", cdtimo);
+               else printf(", timeout: none");
+           }
+           if (local
+#ifdef NETCONN
+               && !network
+#endif /* NETCONN */
+               ) {
+               printf("\n%s modem signals:\n",ttname);
+               shomdm();
+           } else printf("\n");
+           break;
+#endif /* NODIAL */
+
+#ifdef VMS
+       case SHLBL:                     /* Labeled file info */
+           sholbl();
+           break;
+#endif /* VMS */           
+
+       case SHCSE:                     /* Character sets */
+#ifdef NOCSETS
+           printf(
+" Character set translation is not supported in this version of C-Kermit\n");
+#else
+           shocharset();
+            printf("\n Unknown-Char-Set: %s\n",
+                  unkcs ? "Keep" : "Discard");
+           shotcs(tcsl,tcsr);
+           printf("\n");
+#endif /* NOCSETS */
+           break;
+
+#ifndef NOFRILLS
+         case SHFEA:                   /* Features */
+           shofea();
+           break;
+#endif /* NOFRILLS */
+
+       default:
+           printf("\nNothing to show...\n");
+           return(-2);
+    }
+    return(success = 1);
+}
+
+VOID
+shmdmlin() {                           /* Briefly show modem & line */
+    int i;
+#ifndef NODIAL
+#ifndef MINIDIAL
+    extern int tbmodel;
+    _PROTOTYP( char * gtbmodel, (void) );
+#endif /* MINIDIAL */
+#endif /* NODIAL */
+    if (local)
+      printf(" Line: %s, Modem: ",ttname);
+    else
+      printf(" Communication device not yet selected with SET LINE\n Modem: ");
+#ifndef NODIAL
+    for (i = 0; i < nmdm; i++) {
+       if (mdmtab[i].kwval == mdmtyp) {
+           printf("%s",mdmtab[i].kwd);
+           break;
+       }
+    }
+#ifndef MINIDIAL
+    if (tbmodel) printf(" (%s)",gtbmodel()); /* Telebit model info */
+#endif /* MINIDIAL */
+#else
+    printf("(disabled)");
+#endif /* NODIAL */
+}
+#endif /* NOSHOW */
+
+#ifdef GEMDOS
+isxdigit(c) int c; {
+    return(isdigit(c) ||
+          (c >= 'a' && c <= 'f') ||
+          (c >= 'A' && c <= 'F'));
+}
+#endif /* GEMDOS */
+
+#ifndef NOSHOW
+#ifndef NOSPL
+int                                    /* SHO MACROS */
+shomac(s1, s2) char *s1, *s2; {
+    int x, n, pp;
+    pp = 0;                            /* Parenthesis counter */
+
+    if (!s1)
+      return(0);
+    else
+      printf("\n%s = ",s1);            /* Print blank line and macro name */
+    slc++;                             /* Count the line */
+    n = (int)strlen(s1) + 4;           /* Width of current line */
+    if (!s2) s2 = "(null definition)";
+
+    while (x = *s2++) {                        /* Loop thru definition */
+       if (x == '(') pp++;             /* Treat commas within parens */
+       if (x == ')') pp--;             /* as ordinary text */
+       if (pp < 0) pp = 0;             /* Outside parens, */
+       if (x == ',' && pp == 0) {      /* comma becomes comma-dash-NL. */
+           putchar(',');
+           putchar('-');
+           x = '\n';
+       }
+       putchar(x);                     /* Output the character */
+       if (x == '\n') {                /* If it was a newline */
+#ifdef UNIX
+#ifdef NOSETBUF
+           fflush(stdout);
+#endif /* NOSETBUF */
+#endif /* UNIX */
+           putchar(' ');               /* Indent the next line 1 space */
+           while(*s2 == ' ') s2++;     /* skip past leading blanks */
+           n = 2;                      /* restart the character counter */
+           slc++;                      /* and increment the line counter. */
+       } else if (++n > SCRNWID) {     /* If line is too wide */
+           putchar('-');               /* output a dash */
+           putchar(NL);                /* and a newline */
+#ifdef UNIX
+#ifdef NOSETBUF
+           fflush(stdout);
+#endif /* NOSETBUF */
+#endif /* UNIX */
+           n = 1;                      /* and restart the char counter */
+           slc++;                      /* and increment the line counter */
+       }
+       if (n < 3 && slc > SCRNLEN) {   /* If new line and screen is full */
+           if (!askmore()) return(-1); /* ask if they want more. */
+           n = 1;                      /* They do, start a new line */
+           slc = 0;                    /* and restart line counter */
+       }
+    }
+    putchar(NL);                       /* End of definition */
+    if (++slc > SCRNLEN) {
+       if (!askmore()) return(-1);
+       slc = 0;
+    }
+    return(0);
+}
+#endif /* NOSPL */
+#endif /* NOSHOW */
+
+#ifndef NOSHOW
+int
+shoatt() {
+    printf("Attributes: %s\n", atcapr ? "On" : "Off");
+    if (!atcapr) return(0);
+    printf(" Blocksize: %s\n", atblki ? "On" : "Off");
+    printf(" Date: %s\n", atdati ? "On" : "Off");
+    printf(" Disposition: %s\n", atdisi ? "On" : "Off");
+    printf(" Encoding (Character Set): %s\n", atenci ? "On" : "Off");
+    printf(" Length: %s\n", atleni ? "On" : "Off");
+    printf(" Type (text/binary): %s\n", attypi ? "On" : "Off");
+    printf(" System ID: %s\n", atsidi ? "On" : "Off");
+    printf(" System Info: %s\n", atsysi ? "On" : "Off");
+    return(0);
+}
+#endif /* NOSHOW */
+
+#ifndef NOSPL
+/* Evaluate an arithmetic expression. */
+/* Code adapted from ev, by Howie Kaye of Columbia U & others. */
+
+static int xerror;
+static char *cp;
+static long tokval;
+static char curtok;
+static long expval;
+
+#define LONGBITS (8*sizeof (long))
+#define NUMBER 'N'
+#define EOT 'E'
+
+/*
+ Replacement for strchr() and index(), neither of which seem to be universal.
+*/
+
+static char *
+#ifdef CK_ANSIC
+windex(char * s, char c)
+#else
+windex(s,c) char *s, c;
+#endif /* CK_ANSIC */
+/* windex */ {
+    while (*s != NUL && *s != c) s++;
+    if (*s == c) return(s); else return(NULL);
+}
+
+/*
+ g e t t o k
+
+ Returns the next token.  If token is a NUMBER, sets tokval appropriately.
+*/
+static char
+gettok() {
+    while (isspace(*cp)) cp++ ;
+    switch(*cp) {
+      case '$':                                /* ??? */
+      case '+':                                /* Add */
+      case '-':                                /* Subtract or Negate */
+      case '@':                                /* Greatest Common Divisor */
+      case '*':                                /* Multiply */
+      case '/':                                /* Divide */
+      case '%':                                /* Modulus */
+      case '<':                                /* Left shift */
+      case '>':                                /* Right shift */
+      case '&':                                /* And */
+      case '|':                                /* Or */
+      case '#':                                /* Exclusive Or */
+      case '~':                                /* Not */
+      case '^':                                /* Exponent */
+      case '!':                                /* Factorial */
+      case '(':                                /* Parens for grouping */
+      case ')': return(*cp++);         /* operator, just return it */
+      case '\n':
+      case '\0': return(EOT);          /* end of line, return that */
+    }
+    if (isxdigit(*cp)) {               /* digit, must be a number */
+       char tbuf[80],*tp;              /* buffer to accumulate number */
+       int radix = 10;                 /* default radix */
+       for (tp=tbuf; isxdigit(*cp); cp++)
+         *tp++ = isupper(*cp) ? tolower(*cp) : *cp;
+       *tp = '\0';                     /* end number */
+       switch(isupper(*cp) ? tolower(*cp) : *cp) { /* examine break char */
+         case 'h':
+         case 'x': radix = 16; cp++; break; /* if radix signifier... */
+         case 'o':
+         case 'q': radix = 8; cp++; break;
+         case 't': radix = 2; cp++; break;
+       }
+       for (tp=tbuf,tokval=0; *tp != '\0'; tp++)  {
+           int dig;
+           dig = *tp - '0';            /* convert number */
+           if (dig > 10) dig -= 'a'-'0'-10;
+           if (dig >= radix) {
+               xerror = 1;
+               if (cmdlvl == 0)
+                 printf("invalid digit '%c' in number\n",*tp);
+               return(NUMBER);
+           }
+           tokval = radix*tokval + dig;
+       }
+       return(NUMBER);
+    }
+    if (cmdlvl == 0)
+      printf("Invalid character '%c' in input\n",*cp);
+    xerror = 1;
+    cp++;
+    return(gettok());
+}
+
+static long
+#ifdef CK_ANSIC
+expon(long x, long y)
+#else
+expon(x,y) long x,y;
+#endif /* CK_ANSIC */
+/* expon */ {
+    long result = 1;
+    int sign = 1;
+    if (y < 0) return(0);
+    if (x < 0) {
+       x = -x;
+       if (y & 1) sign = -1;
+    }
+    while (y != 0) {
+       if (y & 1) result *= x;
+       y >>= 1;
+       if (y != 0) x *= x;
+  }
+  return(result * sign);
+}
+
+/*
+ * factor ::= simple | simple ^ factor
+ *
+ */
+_PROTOTYP( static VOID simple, (void) );
+
+static VOID
+factor() {
+    long oldval;
+    simple();
+    if (curtok == '^') {
+       oldval = expval;
+       curtok = gettok();
+       factor();
+       expval = expon(oldval,expval);
+    }
+}
+
+/*
+ * termp ::= NULL | {*,/,%,&} factor termp
+ *
+ */
+static VOID
+termp() {
+    while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
+       long oldval;
+       char op;
+       op = curtok;
+       curtok = gettok();              /* skip past operator */
+       oldval = expval;
+       factor();
+       switch(op) {
+         case '*': expval = oldval * expval; break;
+         case '/':
+           if (expval == 0) expval = -1; /* don't divide by 0 */
+           else expval = oldval / expval; break;
+         case '%': expval = oldval % expval; break;
+         case '&': expval = oldval & expval; break;
+       }
+    }
+}
+
+static long
+#ifdef CK_ANSIC
+fact(long x)
+#else
+fact(x) long x;
+#endif /* CK_ANSIC */
+/* fact */ {                           /* factorial */
+    long result = 1;
+    while (x > 1)
+      result *= x--;
+    return(result);
+}
+
+/*
+ * term ::= factor termp
+ *
+ */
+static VOID
+term() {
+    factor();
+    termp();
+}
+
+static long
+#ifdef CK_ANSIC
+gcd(long x, long y)
+#else
+gcd(x,y) long x,y;
+#endif /* CK_ANSIC */
+/* gcd */ {                            /* Greatest Common Divisor */
+    int nshift = 0;
+    if (x < 0) x = -x;
+    if (y < 0) y = -y;                 /* validate arguments */
+    if (x == 0 || y == 0) return(x + y);    /* this is bogus */
+    
+    while (!((x & 1) | (y & 1))) {     /* get rid of powers of 2 */
+       nshift++;
+       x >>= 1;
+       y >>= 1;
+    }
+    while (x != 1 && y != 1 && x != 0 && y != 0) {
+       while (!(x & 1)) x >>= 1;       /* eliminate unnecessary */
+       while (!(y & 1)) y >>= 1;       /* powers of 2 */
+       if (x < y) {                    /* force x to be larger */
+           long t;
+           t = x;
+           x = y;
+           y = t;
+       }
+       x -= y;
+    }
+    if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
+    else return((long) 1 << nshift);   /* else gcd is 1 */
+}
+
+/*
+ * exprp ::= NULL | {+,-,|,...} term exprp
+ *
+ */
+static VOID
+exprp() {
+    while (windex("+-|<>#@",curtok) != NULL) {
+       long oldval;
+       char op;
+       op = curtok;
+       curtok = gettok();              /* skip past operator */
+       oldval = expval;
+       term();
+       switch(op) {
+         case '+' : expval = oldval + expval; break;
+         case '-' : expval = oldval - expval; break;
+         case '|' : expval = oldval | expval; break;
+         case '#' : expval = oldval ^ expval; break;
+         case '@' : expval = gcd(oldval,expval); break;
+         case '<' : expval = oldval << expval; break;
+         case '>' : expval = oldval >> expval; break;
+       }
+    }
+}
+
+/*
+ * expr ::= term exprp
+ *
+ */
+static VOID
+expr() {
+    term();
+    exprp();
+}
+
+static long
+xparse() {
+    curtok = gettok();
+    expr();
+#ifdef COMMENT
+    if (curtok == '$') {
+       curtok = gettok();
+       if (curtok != NUMBER) {
+           if (cmdlvl == 0) printf("illegal radix\n");
+           return(0);
+       }
+       curtok = gettok();
+    }
+#endif /* COMMENT */
+    if (curtok != EOT) {
+       if (cmdlvl == 0)
+         printf("extra characters after expression\n");
+       xerror = 1;
+    }
+    return(expval);
+}
+
+char *
+evala(s) char *s; {
+    char *p;                           /* Return pointer */
+    long v;                            /* Numeric value */
+
+    xerror = 0;                                /* Start out with no error */
+    cp = s;                            /* Make the argument global */
+    v = xparse();                      /* Parse the string */
+    p = numbuf;                                /* Convert long number to string */
+    sprintf(p,"%ld",v);
+    return(xerror ? "" : p);           /* Return empty string on error */
+}
+
+/*
+ * simplest ::= NUMBER | ( expr )
+ *
+ */
+static VOID
+simplest() {
+    if (curtok == NUMBER) expval = tokval;
+    else if (curtok == '(') {
+       curtok = gettok();              /* skip over paren */
+       expr();
+       if (curtok != ')') {
+           if (cmdlvl == 0) printf("missing right parenthesis\n");
+           xerror = 1;
+       }
+    }
+    else {
+       if (cmdlvl == 0) printf("operator unexpected\n");
+       xerror = 1;
+    }
+    curtok = gettok();
+}
+
+/*
+ * simpler ::= simplest | simplest !
+ *
+ */
+static VOID
+simpler() {
+    simplest();
+    if (curtok == '!') {
+       curtok = gettok();
+       expval = fact(expval);
+    }
+}
+
+/*
+ * simple ::= {-,~} simpler | simpler
+ *
+ */
+
+static VOID
+simple() {
+    if (curtok == '-' || curtok == '~') {
+       int op = curtok;
+       curtok = gettok();              /* skip over - sign */
+       simpler();                      /* parse the factor again */
+       expval = op == '-' ? -expval : ~expval;
+    } else simpler();
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+/*  D C L A R R A Y  --  Declare an array  */
+
+int                                    /* Declare an array of size n */
+#ifdef CK_ANSIC
+dclarray(char a, int n)
+#else
+dclarray(a,n) char a; int n;
+#endif /* CK_ANSIC */
+/* dclarray */ {
+    char **p; int i, n2;
+
+    if (a > 63 && a < 96) a += 32;     /* Convert to lowercase */
+    if (a < 96 || a > 122) return(-1); /* Verify name */
+    a -= 96;                           /* Convert name to number */
+    if ((p = a_ptr[a]) != NULL) {      /* Delete old array of same name */
+       n2 = a_dim[a];
+       for (i = 0; i <= n2; i++)       /* First delete its elements */
+         if (p[i]) free(p[i]);
+       free(a_ptr[a]);                 /* Then the element list */
+       a_ptr[a] = (char **) NULL;      /* Remove pointer to element list */
+       a_dim[a] = 0;                   /* Set dimension at zero. */
+    }
+    if (n == 0) return(0);             /* If dimension 0, just deallocate. */
+
+    p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
+    if (p == NULL) return(-1);         /* Check */
+    a_ptr[a] = p;                      /* Save pointer to member list */
+    a_dim[a] = n;                      /* Save dimension */
+    for (i = 0; i <= n; i++)           /* Initialize members to null */
+      p[i] = NULL;
+    return(0);
+}
+
+/*  A R R A Y N A M  --  Parse an array name  */
+
+/*
+  Call with pointer to string that starts with the array reference.
+  String may begin with either \& or just &.
+  On success,
+    Returns letter ID (always lowercase) in argument c,
+      which can also be accent grave (` = 96; '@' is converted to grave);
+    Dimension or subscript in argument n;
+    IMPORTANT: These arguments must be provided by the caller as addresses
+    of ints (not chars), for example:
+      char *s; int x, y;
+      arraynam(s,&x,&y);
+  On failure, returns a negative number, with args n and c set to zero.
+*/
+int
+arraynam(ss,c,n) char *ss; int *c; int *n; {
+    int i, y, pp;
+    char x;
+    char *s, *p, *sx, *vnp;
+    char vnbuf[VNAML+1];               /* On stack to allow for */
+    char ssbuf[VNAML+1];               /* recursive calls... */
+    char sxbuf[VNAML+1];
+
+    *c = *n = 0;                       /* Initialize return values */
+    for (i = 0; i < (int)strlen(ss); i++) /* Check length */
+      if (ss[i] == ']')
+       break;
+    if (i > VNAML) {
+       printf("?Array reference too long - %s\n",ss);
+       return(-9);
+    }
+    strncpy(vnbuf,ss,VNAML);
+    vnp = vnbuf;
+    if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++;
+    if (*vnp != '&') {
+       printf("?Not an array - %s\n",vnbuf);
+       return(-9);
+    }
+    x = *(vnp + 1);                    /* Fold case of array name */
+    /* We don't use isupper & tolower here on purpose because these */
+    /* would produce undesired effects with accented letters. */
+    if (x > 63 && x < 91) x  = *(vnp +1) = x + 32;
+    if ((x < 96) || (x > 122) || (*(vnp+2) != '[')) {
+       printf("?Invalid format for array name - %s\n",vnbuf);
+       return(-9);
+    }
+    *c = x;                            /* Return the array name */
+    s = vnp+3;                         /* Get dimension */
+    p = ssbuf;    
+    pp = 1;                            /* Bracket counter */
+    for (i = 0; i < VNAML && *s != NUL; i++) { /* Copy up to ] */
+       if (*s == '[') pp++;
+       if (*s == ']' && --pp == 0) break;
+       *p++ = *s++;
+    }
+    if (*s != ']') {
+       printf("?No closing bracket on array dimension - %s\n",vnbuf);
+       return(-9);
+    }
+    *p = NUL;                          /* Terminate subscript with null */
+    p = ssbuf;                         /* Point to beginning of subscript */
+    sx = sxbuf;                                /* Where to put expanded subscript */
+    y = VNAML-1;
+    xxstring(p,&sx,&y);                        /* Convert variables, etc. */
+    if (!chknum(sxbuf)) {              /* Make sure it's all digits */
+       printf("?Array dimension or subscript must be numeric - %s\n",sxbuf);
+       return(-9);
+    }
+    if ((y = atoi(sxbuf)) < 0) {
+        if (cmflgs == 0) printf("\n");
+        printf("?Array dimension or subscript must be positive or zero - %s\n",
+              sxbuf);
+       return(-9);
+    }
+    *n = y;                            /* Return the subscript or dimension */
+    return(0);
+}
+
+int
+chkarray(a,i) int a, i; {              /* Check if array is declared */
+    int x;                             /* and if subscript is in range */
+    if (a == 64) a = 96;               /* Convert atsign to grave accent */
+    x = a - 96;                                /* Values must be in range 96-122 */
+    if (x < 0 || x > 26) return(-2);   /* Not in range */
+    if (a_ptr[x] == NULL) return(-1);  /* Not declared */
+    if (i > a_dim[x]) return(-2);      /* Declared but out of range. */
+    return(a_dim[x]);                  /* All ok, return dimension */
+}
+
+char *
+arrayval(a,i) int a, i; {              /* Return value of \&a[i] */
+    int x; char **p;                   /* (possibly NULL) */
+
+    if (a == 64) a = 96;               /* Convert atsign to grave accent */
+    x = a - 96;                                /* Values must be in range 96-122 */
+    if (x < 0 || x > 26) return(NULL); /* Not in range */
+    if ((p = a_ptr[x]) == NULL)                /* Array not declared */
+      return(NULL);
+    if (i > a_dim[x])                  /* Subscript out of range. */
+      return(NULL);
+    return(p[i]);                      /* All ok, return pointer to value. */
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+/*  P A R S E V A R  --  Parse a variable name or array reference.  */
+/*
+ Call with:
+   s  = pointer to candidate variable name or array reference.
+   *c = address of integer in which to return variable ID.
+   *i = address of integer in which to return array subscript.
+ Returns:
+   -2:  syntax error in variable name or array reference.
+    1:  successful parse of a simple variable, with ID in c.
+    2:  successful parse of an array reference, w/ID in c and subscript in i.
+*/
+int
+parsevar(s,c,i) char *s; int *c, *i; {
+    char *p;
+    int x,y,z;
+
+    p = s;
+    if (*s == CMDQ) s++;               /* Point after backslash */
+
+    if (*s != '%' && *s != '&') {      /* Make sure it's % or & */
+       printf("?Not a variable name - %s\n",p);
+       return(-9);
+    }
+    if ((int)strlen(s) < 2) {
+       printf("?Incomplete variable name - %s\n",p);
+       return(-9);
+    }
+    if (*s == '%' && *(s+2) != '\0') {
+       printf("?Only one character after '%%' in variable name, please\n");
+       return(-9);
+    }
+    if (*s == '&' && *(s+2) != '[') {
+       printf("?Array subscript expected - %s\n",p);
+       return(-9);
+    }
+    if (*s == '%') {                   /* Simple variable. */
+       y = *(s+1);                     /* Get variable ID letter/char */
+       if (isupper(y)) y -= ('a'-'A'); /* Convert upper to lower case */
+       *c = y;                         /* Set the return values. */
+       *i = -1;                        /* No array subscript. */
+       return(1);                      /* Return 1 = simple variable */
+    }
+    if (*s == '&') {                   /* Array reference. */
+       if (arraynam(s,&x,&z) < 0) { /* Go parse it. */
+           printf("?Invalid array reference - %s\n",p);
+           return(-9);
+       }
+       if (chkarray(x,z) < 0) {        /* Check if declared, etc. */
+           printf("?Array not declared or subscript out of range\n");
+           return(-9);
+       }
+       *c = x;                         /* Return array letter */
+       *i = z;                         /* and subscript. */
+       return(2);
+    }    
+    return(-2);                                /* None of the above. */
+}
+
+#define VALN 20
+
+/* Get the numeric value of a variable */
+/*
+  Call with pointer to variable name, pointer to int for return value.
+  Returns:
+    0 on success with second arg containing the value.
+   -1 on failure (bad variable syntax, variable not defined or not numeric).
+*/
+int
+varval(s,v) char *s; int *v; {
+    char valbuf[VALN+1];               /* s is pointer to variable name */
+    char *p;
+    int y;
+
+    p = valbuf;                                /* Expand variable into valbuf. */
+    y = VALN;
+    if (xxstring(s,&p,&y) < 0) return(-1);
+    p = valbuf;                                /* Make sure value is numeric */
+    if (!chknum(p)) return(-1);
+    *v = atoi(p);                      /* Convert numeric string to int */
+    return(0);    
+}
+
+/* Increment or decrement a variable */
+/* Returns -1 on failure, 0 on success, with 4th argument set to result */
+
+int
+incvar(s,x,z,r) char *s; int x, z, *r; { /* Increment a numeric variable */
+    char valbuf[VALN+1];               /* s is pointer to variable name */
+                                       /* x is amount to increment by */
+    int n;                             /* z != 0 means add */
+                                       /* z = 0 means subtract */
+
+    if (varval(s,&n) < 0)              /* Convert numeric string to int */
+      return(-1);
+    if (z)                             /* Increment it by the given amount */
+      n += x;
+    else                               /* or decrement as requested. */
+      n -= x;
+    sprintf(valbuf,"%d",n);            /* Convert back to numeric string */
+    addmac(s,valbuf);                  /* Replace old variable */
+    *r = n;                            /* Return the integer value */
+    return(0);
+}
+#endif /* NOSPL */
+
+/* Functions moved here from ckuusr.c to even out the module sizes... */
+
+#ifndef NOSPL                          /* Need xwords() function to break */
+#define XWORDS                         /* string up into words. */
+#endif /* NOSPL */
+#ifndef NODIAL
+#ifndef XWORDS
+#define XWORDS
+#endif /* XWORDS */
+#endif /* NODIAL */
+
+#ifdef XWORDS
+/*
+  Breaks string s up into a list of up to max words.
+  Pointers to each word go into the array list[].
+  If list is NULL, then they are added to the macro table.
+*/
+
+VOID
+xwords(s,max,list) char *s; int max; char *list[]; {
+    char *p;
+    int b, k, y, z;
+#ifndef NOSPL
+    int macro;
+    macro = (list == NULL);
+    debug(F101,"xwords macro","",macro);
+#endif /* NOSPL */
+
+    p = s;                             /* Pointer to beginning of string */
+    b = 0;                             /* Flag for outer brace removal */
+    k = 0;                             /* Flag for in-word */
+    y = 0;                             /* Brace nesting level */
+    z = 0;                             /* Argument counter, 0 thru max */
+
+    while (1) {                                /* Go thru argument list */
+       if (!s || (*s == '\0')) {       /* No more characters? */
+           if (k != 0) {
+               if (z == max) break;    /* Only go up to max. */
+               z++;                    /* Count it. */
+#ifndef NOSPL
+               if (macro) {
+                   varnam[1] = z + '0'; /* Assign last argument */
+                   addmac(varnam,p);
+               } else
+#endif /* NOSPL */
+                 list[z] = p;
+               break;                  /* And get out. */
+           } else break;
+       } 
+       if (k == 0 && (*s == SP || *s == HT)) { /* Eat leading blanks */
+           s++;
+           continue;
+       } else if (*s == '{') {         /* An opening brace */
+           if (k == 0 && y == 0) {     /* If leading brace */
+               p = s+1;                /* point past it */
+               b = 1;                  /* and flag that we did this */
+           }
+           k = 1;                      /* Flag that we're in a word */
+           y++;                        /* Count the brace. */
+       } else if (*s == '}') {         /* A closing brace. */
+           y--;                        /* Count it. */
+           if (y == 0 && b != 0) {     /* If it matches the leading brace */
+               *s = SP;                /* change it to a space */
+               b = 0;                  /* and we're not in braces any more */
+           } else if (y < 0) k = 1;    /* otherwise just start a new word. */
+       } else if (*s != SP && *s != HT) { /* Nonspace means we're in a word */
+           if (k == 0) p = s;          /* Mark the beginning */
+           k = 1;                      /* Set in-word flag */
+       }
+       /* If we're not inside a braced quantity, and we are in a word, and */
+       /* we have hit whitespace, then we have an argument to assign. */
+       if ((y < 1) && (k != 0) && (*s == SP || *s == HT)) { 
+           *s = '\0';                  /* terminate the arg with null */
+           k = 0;                      /* say we're not in a word any more */
+           y = 0;                      /* start braces off clean again */
+           if (z == max) break;        /* Only go up to max. */
+           z++;                        /* count this arg */
+#ifndef NOSPL
+           if (macro) {
+               varnam[1] = z + '0';    /* compute its name */
+               addmac(varnam,p);       /* add it to the macro table */
+           } else
+#endif /* NOSPL */
+             list[z] = p;
+           p = s+1;
+       }
+       s++;                            /* Point past this character */
+    }
+    if ((z == 0) && (y > 1)) {         /* Extra closing brace(s) at end */
+       z++;
+#ifndef NOSPL
+       if (macro) {
+           varnam[1] = z + '0';        /* compute its name */
+           addmac(varnam,p);           /* Add rest of line to last arg */
+       } else
+#endif /* NOSPL */
+         list[z] = p;
+    }
+#ifndef NOSPL
+    if (macro) macargc[maclvl] = z + 1;        /* Set \v(argc) variable */
+#endif /* NOSPL */
+    return;
+}
+#endif /* XWORDS */
+
+#ifndef NOSPL
+/* D O D O  --  Do a macro */
+
+/*
+  Call with x = macro table index, s = pointer to arguments.
+  Returns 0 on failure, 1 on success.
+*/
+
+int
+dodo(x,s) int x; char *s; {
+    int y;
+
+    debug(F101,"dodo maclvl","",maclvl);
+    if (++maclvl > MACLEVEL) {         /* Make sure we have storage */
+        debug(F101,"dodo maclvl too deep","",maclvl);
+       --maclvl;
+       printf("Macros nested too deeply\n");
+       return(0);
+    }
+    macp[maclvl] = mactab[x].mval;     /* Point to the macro body */ 
+    macx[maclvl] = mactab[x].mval;     /* Remember where the beginning is */
+    debug(F111,"do macro",macp[maclvl],maclvl);
+
+    cmdlvl++;                          /* Entering a new command level */
+    if (cmdlvl > CMDSTKL) {            /* Too many macros + TAKE files? */
+        debug(F101,"dodo cmdlvl too deep","",cmdlvl);
+       cmdlvl--;
+       printf("?TAKE files and DO commands nested too deeply\n");
+       return(0);
+    }
+#ifdef VMS
+    conres();                          /* So Ctrl-C, etc, will work. */
+#endif /* VMS */
+    ifcmd[cmdlvl] = 0;
+    iftest[cmdlvl] = 0;
+    count[cmdlvl] = 0;
+    cmdstk[cmdlvl].src = CMD_MD;       /* Say we're in a macro */
+    cmdstk[cmdlvl].lvl = maclvl;       /* and remember the macro level */
+    mrval[maclvl] = NULL;              /* Initialize return value */
+
+    debug(F110,"do macro",mactab[x].kwd,0);
+
+/* Clear old %0..%9 arguments */
+
+    addmac("%0",mactab[x].kwd);                /* Define %0 = name of macro */
+    varnam[0] = '%';
+    varnam[2] = '\0';
+    for (y = 1; y < 10; y++) {         /* Clear args %1..%9 */
+       varnam[1] = y + '0';
+       delmac(varnam);
+    }  
+
+/* Assign the new args one word per arg, allowing braces to group words */
+
+    xwords(s,9,NULL);
+    return(1);
+}
+
+/* Insert "literal" quote around each comma-separated command to prevent */
+/* its premature expansion.  Only do this if object command is surrounded */
+/* by braces. */
+
+static char* flit = "\\flit(";
+
+int
+litcmd(src,dest) char **src, **dest; {
+    int bc = 0, pp = 0;
+    char *s, *lp, *ss;
+
+    s = *src;
+    lp = *dest;
+
+    while (*s == SP) s++;              /* strip extra leading spaces */
+    if (*s == '{') {
+
+        pp = 0;                                /* paren counter */
+       bc = 1;                         /* count leading brace */
+       *lp++ = *s++;                   /* copy it */
+       while (*s == SP) s++;           /* strip interior leading spaces */
+       ss = flit;                      /* point to "\flit(" */
+       while (*lp++ = *ss++) ;         /* copy it */
+       lp--;                           /* back up over null */
+       while (*s) {                    /* go thru rest of text */
+           ss = flit;                  /* point back to start of "\flit(" */
+           if (*s == '{') bc++;        /* count brackets */
+           if (*s == '(') pp++;        /* and parens */
+           if (*s == ')') pp--;
+           if (*s == '}') {            /* Closing brace. */
+               if (--bc == 0) {        /* Final one? */
+                   *lp++ = ')';        /* Add closing paren for "\flit()" */
+                   *lp++ = *s++;
+                   break;
+               }
+           }
+           if (*s == ',' && pp == 0) { /* comma not inside of parens */
+               *lp++ = ')';            /* closing ) of \flit( */
+               *lp++ = ',';            /* insert the comma */
+               while (*lp++ = *ss++) ; /* start new "\flit(" */
+               lp--;                   /* back up over null */
+               s++;                    /* skip over comma in source string */
+               while (*s++ == SP);     /* eat leading spaces again. */
+               s--;                    /* back up over nonspace */
+               continue;
+           }
+            *lp++ = *s++;              /* Copy anything but comma here. */
+        }
+       *lp = NUL;
+    } else {                           /* No brackets around, */
+       while (*lp++ = *s++) ;          /* just copy. */
+       lp--;
+    }
+    *src = s;
+    *dest = lp;
+    if (bc) return(-1);
+    else return(0);
+}
+#endif /* NOSPL */
+
+int
+docd() {                               /* Do the CD command */
+    int x;
+    char *s;
+
+#ifdef GEMDOS
+    if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
+                  NULL)) < 0 )
+#else
+    if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
+                  xxstring)) < 0 )
+#endif /* GEMDOS */
+      return(x);
+    if (x == 2) {
+       printf("?Wildcards not allowed in directory name\n");
+       return(-9);
+    }
+    strcpy(line,s);                    /* Make a safe copy */
+    s = line;
+    if ((x = cmcfm()) < 0)             /* Get confirmation */
+      return(x);
+    if (! zchdir(s)) {
+       cwdf = 0;
+       perror(s);
+    } else cwdf = 1;
+#ifdef OS2
+    printf("%s\n", zgtdir());
+#else /* Not OS2 */
+#ifndef MAC
+    zsyscmd(PWDCMD);                   /* assume this works... */
+#endif /* MAC */
+#endif /* OS2 */
+    return(cwdf);
+}
+
+VOID
+fixcmd() {                     /* Fix command parser after interruption */
+    dostop();                  /* Back to top level (also calls conint()). */
+    bgchk();                   /* Check background status */
+    if (*psave) {              /* If old prompt saved, */
+       cmsetp(psave);          /* restore it. */
+       *psave = NUL;
+    }
+    success = 0;               /* Tell parser last command failed */
+}
+
+VOID
+prtopt(s) char *s; {                   /* Print an option */
+    static int x = 0;                  /* (used by SHOW VER) */
+    int y;                             /* Does word wrap. */
+    if (!s) { x = 0; return; }         /* Call with null pointer to */
+    y = (int)strlen(s);                        /* reset horizontal position. */
+    x += y;
+    if (x > 79) {
+       printf("\n%s",s);
+       x = y;
+    } else printf("%s",s);
+}
+
+#endif /* NOICP */
diff --git a/usr/src/contrib/kermit-5A.188/ckuus6.c b/usr/src/contrib/kermit-5A.188/ckuus6.c
new file mode 100644 (file)
index 0000000..0c683d5
--- /dev/null
@@ -0,0 +1,1877 @@
+#ifndef NOICP
+/*  C K U U S 6 --  "User Interface" for Unix Kermit (Part 6)  */
+
+/*
+  Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
+  Columbia University Center for Computing Activities.
+  First released January 1985.
+  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
+  York.  Permission is granted to any individual or institution to use this
+  software as long as it is not sold for profit.  This copyright notice must be
+  retained.  This software may not be included in commercial products without
+  written permission of Columbia University.
+*/
+
+/* Includes */
+#include "ckcdeb.h"
+#include "ckcasc.h"
+#include "ckcker.h"
+#include "ckuusr.h"
+#include "ckcxla.h"
+#include "ckcnet.h"                    /* Network symbols */
+#ifdef datageneral
+#define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
+#endif /* datageneral */
+
+#ifdef MAC                             /* internal MAC file routines */
+#define feof mac_feof
+#define rewind mac_rewind
+#define fgets mac_fgets
+#define fopen mac_fopen
+#define fclose mac_fclose
+
+int mac_feof();
+void mac_rewind();
+char *mac_fgets();
+FILE *mac_fopen();
+int mac_fclose();
+#endif /* MAC */
+
+/* External Kermit Variables, see ckmain.c for description. */
+extern int size, rpsiz, urpsiz, local, stdinf, sndsrc, xitsta,
+  displa, binary, parity, escape, xargc, flow,
+  turn, duplex, nfils, ckxech, pktlog, seslog, tralog, stdouf,
+  turnch, dfloc, keep, maxrps, warn, cnflg, tlevel, pflag, msgflg,
+  mdmtyp, zincnt, fblksiz, frecl, frecfm, atcapr, atdiso, verwho, quiet;
+extern int repars, terror, techo;
+extern long vernum, speed;
+extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv;
+extern char *dialv, *loginv, *for_def[], *whil_def[], *xif_def[];
+extern char *ckxsys, *ckzsys, *cmarg, *cmarg2, **xargv;
+extern char *DIRCMD, *PWDCMD, *DELCMD, *WHOCMD, ttname[], filnam[];
+extern CHAR sstate;
+extern char *zinptr;
+
+#ifndef NOMSEND                                /* Multiple SEND */
+extern char *msfiles[];
+#endif /* NOMSEND */
+extern char fspec[];                   /* Most recent filespec */
+
+/* Declarations from cmd package */
+#ifdef DCMDBUF
+extern char *cmdbuf, *atmbuf;          /* Command buffers */
+#else
+extern char cmdbuf[], atmbuf[];                /* Command buffers */
+#endif /* DCMDBUF */
+
+#ifndef NOSPL
+extern struct mtab *mactab;
+extern int nmac;
+#endif /* NOSPL */
+
+/* Declarations from ck?fio.c module */
+extern int backgrd, bgset;             /* Kermit executing in background */
+#ifdef COMMENT
+/*
+  These must be on stack!
+*/
+#ifndef NOSPL
+extern char vnambuf[];                 /* Buffer for variable names */
+extern char *vnp;                      /* Pointer to same */
+#endif /* NOSPL */
+#endif /* COMMENT */
+
+extern char psave[];                   /* For saving & restoring prompt */
+extern char tmpbuf[], *tp;             /* Temporary buffer */
+
+/* Keyword tables specific to this module */
+
+/* Modem signal table */
+
+struct keytab mstab[] = {
+#ifdef COMMENT
+/* The forms preceded by backslash are for MS-DOS Kermit compatibility. */
+/* But... \dsr doesn't work because \d = decimal constant introducer */
+    "\\cd",  BM_DCD, CM_INV,           /* Carrier Detect */
+    "\\cts", BM_CTS, CM_INV,           /* Clear To Send  */
+    "\\dsr", BM_DSR, CM_INV,           /* Data Set Ready */
+    "\\ri",  BM_RNG, CM_INV,           /* Ring Indicator */
+#endif /* COMMENT */
+    "cd",    BM_DCD, 0,                        /* Carrier Detect */
+    "cts",   BM_CTS, 0,                        /* Clear To Send  */
+    "dsr",   BM_DSR, 0,                        /* Data Set Ready */
+    "ri",    BM_RNG, 0                 /* Ring Indicator */
+};
+int nms = (sizeof(mstab) / sizeof(struct keytab));
+
+#ifndef NOSPL
+struct keytab opntab[] = {
+#ifndef NOPUSH
+    "!read",  XYFZ_Y, 0,
+    "!write", XYFZ_X, 0,
+#endif /* NOPUSH */
+    "append", XYFZ_A, 0,
+    "read",   XYFZ_O, 0,
+    "write",  XYFZ_N, 0
+};
+int nopn = (sizeof(opntab) / sizeof(struct keytab));
+
+struct keytab iftab[] = {              /* IF commands */
+    "<",          XXIFLT, 0,
+    "=",          XXIFAE, 0,
+    ">",          XXIFGT, 0,
+    "background", XXIFBG, 0,
+    "count",      XXIFCO, 0,
+    "defined",    XXIFDE, 0,
+#ifdef COMMENT
+    "eof",        XXIFEO, 0,
+#endif /* COMMENT */
+    "equal",      XXIFEQ, 0,
+    "error",      XXIFFA, CM_INV,
+    "exist",      XXIFEX, 0,
+    "failure",    XXIFFA, 0,
+    "foreground", XXIFFG, 0,
+    "llt",        XXIFLL, 0,
+    "lgt",        XXIFLG, 0,
+    "not",        XXIFNO, 0,
+    "numeric",    XXIFNU, 0,
+    "success",    XXIFSU, 0
+};
+int nif = (sizeof(iftab) / sizeof(struct keytab));
+#endif /* NOSPL */
+
+/* Variables and symbols local to this module */
+#ifndef NODIAL 
+char *dialnum = (char *)0;             /* Remember DIAL number for REDIAL */
+extern char * dialdir;                 /* Dial directory file name */
+extern FILE * dialfd;                  /* Dial directory file descriptor */
+#endif /* NODIAL */
+
+#ifndef NOSPL
+int ifc,                               /* IF case */
+    not = 0,                           /* Flag for IF NOT */
+    ifargs;                            /* Count of IF condition words */
+char ifcond[100];                      /* IF condition text */
+char *ifcp;                            /* Pointer to IF condition text */
+#ifdef DCMDBUF
+extern int *ifcmd, *count, *iftest;
+#else
+extern int ifcmd[];                    /* Last command was IF */
+extern int iftest[];                   /* Last IF was true */
+extern int count[];                    /* For IF COUNT, one for each cmdlvl */
+#endif /* DCMDBUF */
+#endif /* NOSPL */
+
+#ifdef DCMDBUF
+extern char *line;                     /* Character buffer for anything */
+#else
+extern char line[];
+#endif /* DCMDBUF */
+extern char *lp;                       /* Pointer to line buffer */
+
+int cwdf = 0;                          /* CWD has been done */
+
+extern int en_cwd, en_del, en_dir, en_fin, /* Flags for ENABLE/DISABLE */
+   en_get, en_hos, en_sen, en_set, en_spa, en_typ, en_who, en_bye;
+
+extern FILE *tfile[];                  /* File pointers for TAKE command */
+extern char *tfnam[];                  /* Names of TAKE files */
+
+extern int success;                    /* Command success/failure flag */
+
+#ifndef NOSPL
+extern int                             /* SET INPUT parameters. */
+  incase;
+extern int maclvl;                     /* Macro to execute */
+extern char *macx[];                   /* Index of current macro */
+extern char *mrval[];                  /* Macro return value */
+extern char *macp[];                   /* Pointer to macro */
+extern int macargc[];                  /* ARGC from macro invocation */
+
+extern char *m_arg[MACLEVEL][NARGS];   /* Stack of macro arguments */
+extern char *g_var[];                  /* Global variables %a, %b, etc */
+#ifdef DCMDBUF
+extern struct cmdptr *cmdstk;          /* The command stack itself */
+#else
+extern struct cmdptr cmdstk[];         /* The command stack itself */
+#endif /* DCMDBUF */
+extern int cmdlvl;                     /* Current position in command stack */
+#endif /* NOSPL */
+
+#define xsystem(s) zsyscmd(s)
+
+static int x, y, z = 0;
+static char *s, *p;
+
+/*  X X S T R C M P  --  Caseless string comparison  */
+/*
+  Call with pointers to the two strings, s1 and s2, and a length, n.
+  Compares up to n characters of the two strings and returns:
+    1 if s1 > t1
+    0 if s1 = s2
+   -1 if s1 < t1
+*/
+int
+xxstrcmp(s1,s2,n) char *s1, *s2; int n; { /* Caseless string comparison. */
+    char t1, t2;                       
+
+    if (!s1) s1 = "";                  /* Watch out for null pointers. */
+    if (!s2) s2 = "";
+    while (n--) {
+       t1 = *s1++;                     /* Get next character from each. */
+       if (isupper(t1)) t1 = tolower(t1);
+       t2 = *s2++;
+       if (isupper(t2)) t2 = tolower(t2);
+       if (t1 < t2) return(-1);        /* s1 < s2 */
+       if (t1 > t2) return(1);         /* s1 > s2 */
+    }
+    return(0);                         /* They're equal */
+}
+
+#ifndef NOSPL
+
+/* Do the ASK, ASKQ, GETOK, and READ commands */
+
+#ifndef NOFRILLS
+   extern struct keytab yesno[];
+   extern int nyesno;
+#endif /* NOFRILLS */
+
+int
+doask(cx) int cx; {
+
+    if (cx != XXGOK) {                 /* Get variable name */
+       if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
+           if (y == -3) {
+               printf("?Variable name required\n");
+               return(-9);
+           } else return(y);
+       }
+       strcpy(line,s);                 /* Make a copy. */
+       lp = line;
+       if ((y = parsevar(s,&x,&z)) < 0)  /* Check to make sure it's a */
+         return(y);                      /* variable name. */
+    }
+    if (cx == XXREA) {                 /* READ command */
+       if ((y = cmcfm()) < 0)          /* Get confirmation */
+         return(y);
+       if (chkfn(ZRFILE) < 1) {        /* File open? */
+           printf("?Read file not open\n");
+           return(0);
+       }
+       s = line+VNAML+1;               /* Where to read into. */
+       y = zsinl(ZRFILE, s, LINBUFSIZ - VNAML - 1); /* Read a line. */
+       debug(F111,"read zsinl",s,y);
+       if (y < 0) {                    /* On EOF or other error, */
+           zclose(ZRFILE);             /* close the file, */
+           delmac(lp);                 /* delete the variable, */
+           return(success = 0);        /* and return failure. */
+       } else {                        /* Read was OK. */
+           success = (addmac(lp,s) < 0 ? 0 : 1); /* Define the variable */
+            debug(F111,"read addmac",lp,success);
+           return(success);            /* Return success. */
+       }
+    }
+
+    /* ASK, ASKQ, or GETOK */
+
+    if ((y = cmtxt("Prompt, enclose in { braces } to preserve\n\
+leading and trailing spaces, precede question mark with backslash (\\).",
+                  cx == XXGOK ? "{ Yes or no? }" : "",
+                  &p,xxstring)) < 0) return(y);
+
+    cmsavp(psave,80);                  /* Save old prompt */
+    if (*p == '{') {                   /* New prompt enclosed in braces? */
+       x = (int)strlen(p) - 1;         /* Yes, strip them. */
+       if (p[x] == '}') {
+           p[x] = NUL;
+           p++;
+       }
+    }
+    cmsetp(p);                         /* Make new prompt */
+    if (cx == XXASKQ) {                        /* For ASKQ, */
+       concb((char)escape);            /* put console in cbreak mode */
+       cmini(0);                       /* and no-echo mode. */
+    } else {                           /* For others, regular echoing. */
+       cmini(ckxech);
+    }
+    x = -1;                            /* This means to reparse. */
+reprompt:
+    if (pflag) prompt(xxstring);       /* Issue prompt. */
+    if (cx == XXGOK) {
+#ifndef NOFRILLS
+       x = cmkey(yesno,nyesno,"","",xxstring); /* GETOK uses keyword table */
+       if (x < 0) {                    /* Parse error */
+           if (x == -3) {              /* No answer? */
+               printf("Please respond Yes or No\n"); /* Make them answer */
+               cmini(ckxech);
+           }
+           goto reprompt;
+       }
+       if ((y = cmcfm()) < 0)          /* Get confirmation */
+         goto reprompt;
+       cmsetp(psave);                  /* Restore prompt */
+       return(x);                      /* Return success or failure */
+#else
+       ;
+#endif /* NOFRILLS */
+    } else {                           /* ASK or ASKQ */
+       while (x == -1) {               /* Prompt till they answer */
+           x = cmtxt("Please respond.\n\
+ Type \\? to include a question mark in your response.","",&s,NULL);
+           debug(F111," cmtxt",s,x);
+       }
+       if (cx == XXASKQ)               /* ASKQ must echo CRLF here */
+         printf("\r\n");
+       if (x < 0) {                    /* If cmtxt parse error, */
+           cmsetp(psave);              /* restore original prompt */
+           return(x);                  /* and return cmtxt's error code. */
+       }
+       if (*s == NUL) {                /* If user typed a bare CR, */
+           cmsetp(psave);              /* Restore old prompt, */
+           delmac(lp);                 /* delete variable if it exists, */
+           return(success = 1);        /* and return. */
+       }
+       y = addmac(lp,s);               /* Add it to the macro table. */
+       debug(F111,"ask addmac",lp,y);
+       cmsetp(psave);                  /* Restore old prompt. */
+       return(success = y < 0 ? 0 : 1);
+    }
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+int
+doincr(cx) int cx; {                   /* INCREMENT, DECREMENT */
+    char vnambuf[VNAML];               /* Buffer for variable names */
+
+    if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
+       if (y == -3) {
+           printf("?Variable name required\n");
+           return(-9);
+       } else return(y);
+    }
+    if (*s != CMDQ) {
+        *vnambuf = CMDQ;
+       strncpy(vnambuf+1,s,VNAML-1);
+    } else strncpy(vnambuf,s,VNAML);
+
+    if ((y = parsevar(vnambuf,&x,&z)) < 0)
+      return(y);
+
+    if ((y = cmnum("by amount","1",10,&x,xxstring)) < 0) return(y);
+    if ((y = cmcfm()) < 0) return(y);
+
+    z = (cx == XXINC ? 1 : 0);         /* Increment or decrement? */
+
+    if (incvar(vnambuf,x,z,&y) < 0) {
+       printf("?Variable %s not defined or not numeric\n",vnambuf);
+       return(success = 0);
+    }
+    return(success = 1);
+}
+#endif /* NOSPL */
+
+
+/* Do the (_)DEFINE and (_)ASSIGN commands */
+
+#ifndef NOSPL
+int
+dodef(cx) int cx; {
+    char vnambuf[VNAML];               /* Buffer for variable names */
+    char *vnp;                         /* Pointer to same */
+    if (cx == XXDFX || cx == XXASX) 
+      y = cmfld("Macro or variable name","",&s,xxstring); /* eval var name */
+    else 
+      y = cmfld("Macro or variable name","",&s,NULL);     /* don't evaluate */
+    if (y < 0) {
+       if (y == -3) {
+           printf("?Variable name required\n");
+           return(-9);
+       } else return(y);
+    }
+    debug(F110,"dodef",s,0);
+    strcpy(vnambuf,s);
+    vnp = vnambuf;
+    if (vnambuf[0] == CMDQ && (vnambuf[1] == '%' || vnambuf[1] == '&')) vnp++;
+    if (*vnp == '%' || *vnp == '&') {
+       if ((y = parsevar(vnp,&x,&z)) < 0) return(y);
+       debug(F101,"dodef","",x);
+       if (y == 1) {                   /* Simple variable */
+           if ((y = cmtxt("Definition of variable","",&s,NULL)) < 0)
+             return(y);
+           debug(F110,"xxdef var name",vnp,0);
+           debug(F110,"xxdef var def",s,0);
+       } else if (y == 2) {            /* Array element */
+           if ((y = arraynam(s,&x,&z)) < 0) return(y);
+           if (x == 96) {
+               printf("?Argument vector array is read-only\n");
+               return(-9);
+           }
+           if (chkarray(x,z) < 0) return(-2);
+           if ((y = cmtxt("Definition of array element","",&s,NULL)) < 0)
+             return(y);
+           debug(F110,"xxdef array ref",vnp,0);
+           debug(F110,"xxdef array def",s,0);
+       }
+    } else {                           /* Macro */
+       if ((y = cmtxt("Definition of macro","",&s,NULL)) < 0) return(y);
+       debug(F110,"xxdef macro name",vnp,0);
+       debug(F110,"xxdef macro def",s,0);
+       if (*s == '{') {                /* Allow macro def to be bracketed. */
+           s++;                        /* If it is, remove the brackets. */
+           y = (int)strlen(s);         /* FOR command depends on this! */
+           if (y > 0 && s[y-1] == '}') s[y-1] = NUL;
+       }
+    }
+    if (*s == NUL) {                   /* No arg given, undefine */
+       delmac(vnp);                    /* silently... */
+       return(success = 1);            /* even if it doesn't exist... */
+    } 
+
+    /* Defining a new macro or variable */
+
+    if (cx == XXASS || cx == XXASX) {  /* ASSIGN rather than DEFINE? */
+       int t;
+       t = LINBUFSIZ-1;
+       lp = line;                      /* If so, expand its value now */
+       xxstring(s,&lp,&t);
+       s = line;
+    }
+    debug(F111,"calling addmac",s,(int)strlen(s));
+
+    y = addmac(vnp,s);                 /* Add it to the appropriate table. */
+    if (y < 0) {
+       printf("?%s failed\n",(cx == XXASS || cx == XXASX) ?
+              "ASSIGN" : "DEFINE");
+       return(success = 0);
+    }
+    return(success = 1);
+}
+#endif /* NOSPL */
+
+
+#ifndef NODIAL
+extern struct keytab partab[];
+/*
+   L U D I A L  --  Lookup up dialing directory entry.
+  
+   Call with string to look up and file descriptor of open dialing directory
+   file.  On success, returns pointer to phone number and sets speed
+   and parity according to the directory entry.  On failure, returns the NULL
+   pointer.
+*/
+char *
+ludial(s,f) char *s; FILE *f; {
+    int n, n1, n2, i, t;               /* Workers */
+    long xspeed = -1L, x2;             /* Speed to set from directory entry */
+    int xparity = -1;                  /* Parity to set ...*/
+    char *info[5];                     /* Array of words from entry */
+
+    if (!s || !f) return(NULL);                /* Validate arguments */
+    if ((n1 = strlen(s)) < 1)
+      return(NULL);
+/*
+  We make one or two passes.  The first pass searches for an exact match.
+  If it fails, the second pass searches for the first entry of which the
+  search string is an abbreviation.  Of course this could be done in one
+  pass, but it was safer to add a couple lines for the for-loop than to
+  totally rearrange the code at the last minute.  (Edit 186)
+*/
+    for (i = 0; i < 2; i++) {          /* Do this twice */
+       debug(F101,"ludial pass","",i+1);
+       rewind(f);                      /* Go to beginning of directory file */
+       while (1) {
+           if (fgets(line,LINBUFSIZ,f) == NULL) { /* Read a line */
+               if (i == 0)             /* EOF */
+                 break;                /* If first pass, start second pass */
+               if (!backgrd && !quiet) /* If second pass, give message */
+                 printf(" %s not in %s\n",s,dialdir);
+               debug(F110,"ludial fails",s,0);
+               return(NULL);
+           }
+           n = strlen(line);           /* Strip terminator(s) */
+           while ((n > 0) && (line[n-1] < '!'))
+             line[--n] = NUL;
+           debug(F111,"ludial",line,n);
+
+           info[0] = NULL; info[1] = NULL; info[2] = NULL;
+           info[3] = NULL; info[4] = NULL;
+
+           xwords(line,4,info);        /* Get the words. */
+           if (info[1]) {              /* First word. */
+               if ((n2 = (int) strlen(info[1])) < 1) /* Its length */
+                 continue;             /* If no first word, keep looking. */
+
+               if (n2 < n1)            /* If directory entry name shorter */
+                 continue;             /* than search name, then no match. */
+               if (i == 0 && n2 != n1) /* Require exact match on first pass */
+                 continue;
+               if (xxstrcmp(s,info[1],n1)) /* Caseless string comparison */
+                 continue;             /* up to length of search name */
+               if (!backgrd && !quiet)
+                 printf(" From dialing directory %s: %s=%s\n",
+                        dialdir,info[1],info[2]);
+               if (info[3]) {          /* Third word = speed */
+                   if (*info[3] != '=') { /* "=" means don't change it */
+                       xspeed = atol(info[3]);
+                       x2 = xspeed / 10L;
+                       if (x2 > 0) {
+                           if (ttsspd((int) x2) < 0)
+                             printf("\n Can't set speed to %s\n",info[3]);
+                           else 
+                             speed = xspeed;
+                       }
+                   }
+               }
+               if (info[4]) {          /* 4th word = parity */
+                   if (*info[4] != '=') { /* "=" means don't change it */
+                       if ((xparity = lookup(partab,info[4],5,&t)) > -1)
+                         parity = xparity;
+                   }
+               }
+               return(info[2]);        /* Return 2nd word = phone number */
+           }
+       }
+    }
+}
+
+int
+dodial(cx) int cx; {                   /* DIAL or REDIAL */
+    if (cx == XXRED) {                 /* REDIAL or... */
+       if ((y = cmcfm()) < 0) return(y);
+       if (dialnum) {
+           s = dialnum;
+       } else {
+           printf("?No DIAL command given yet\n");
+           return(-9);
+       }
+    } else if (cx == XXDIAL) {         /* DIAL command */
+       char *s2;
+       if (dialdir && *dialdir)
+         s2 = "Number to dial or entry from dial directory";
+       else
+         s2 = "Number to dial";
+       if ((x = cmtxt(s2,"",&s,xxstring)) < 0)
+         return(x);
+       if (s == NULL || (int)strlen(s) == 0) {
+           printf("?You must specify a number to dial\n");
+           return(-9);
+       }
+       if (dialfd) {                   /* Have dialing directory? */
+           if (s2 = ludial(s,dialfd))  /* Look up in dialing directory */
+             s = s2;                   /* Make substitution if found */
+       }
+       if (dialnum) free(dialnum);     /* Make copy for REDIAL */
+       dialnum = malloc((int)strlen(s) + 1);
+       if (dialnum) strcpy(dialnum,s);
+    } else return(-2);
+#ifdef VMS
+    conres();                          /* So Ctrl-C/Y will work */
+#endif /* VMS */
+    success = ckdial(s);               /* Try to dial */
+#ifdef OS2
+    ttres();
+#endif /* OS2 */
+#ifdef VMS
+    concb((char)escape);               /* Back to command parsing mode */
+#endif /* VMS */
+    return(success);
+}
+#endif /* NODIAL */
+
+#ifndef MAC
+int                                    /* Do the DIRECTORY command */
+dodir() {
+    char *dc;
+#ifdef VMS
+    if ((x = cmtxt("Directory/file specification","",&s,xxstring)) < 0)
+      return(x);
+    /* now do this the same as a shell command - helps with LAT  */
+    conres();                          /* make console normal */
+    lp = line;
+    if (!(dc = getenv("CK_DIR"))) dc = DIRCMD;
+    sprintf(lp,"%s %s",dc,s);
+    debug(F110,"Directory string: ", line, 0);
+    xsystem(lp);
+    return(success = 0);
+#else
+#ifdef AMIGA
+    if ((x = cmtxt("Directory/file specification","",&s,xxstring)) < 0)
+      return(x);
+#else
+#ifdef datageneral
+    if ((x = cmtxt("Directory/file specification","+",&s,xxstring)) < 0)
+      return(x);
+#else /* General Case */
+    if ((x = cmdir("Directory/file specification","",&s,xxstring)) < 0)
+      if (x != -3) return(x);
+    strcpy(tmpbuf,s);
+    if ((y = cmcfm()) < 0) return(y);
+    s = tmpbuf;
+#endif /* datageneral */
+#endif /* AMIGA */
+    /* General case again */
+    lp = line;
+    if (!(dc = getenv("CK_DIR"))) dc = DIRCMD;
+    sprintf(lp,"%s %s",dc,s);
+    xsystem(line);
+    return(success = 1);               /* who cares... */
+#endif /* VMS */
+}
+#endif /* MAC */
+
+#ifndef NOFRILLS
+/* Do the ENABLE and DISABLE commands */
+
+int
+doenable(cx,x) int cx, x; {
+    y = ((cx == XXENA) ? 1 : 0);
+    switch (x) {
+      case EN_ALL:
+       en_cwd = en_del = en_dir = en_fin = en_get = y;
+       en_sen = en_set = en_spa = en_typ = en_who = y;
+#ifndef datageneral
+        en_bye = y;
+#endif /* datageneral */
+
+#ifndef NOPUSH
+       en_hos = y;
+#endif /* NOPUSH */
+       break;
+      case EN_BYE:
+#ifndef datageneral
+/*
+  In Data General AOS/VS Kermit can't log out its superior process.
+*/
+        en_bye = y;
+#endif /* datageneral */
+       break;
+      case EN_CWD:
+       en_cwd = y;
+       break;
+      case EN_DEL:
+       en_del = y;
+       break;
+      case EN_DIR:
+       en_dir = y;
+       break;
+      case EN_FIN:
+       en_fin = y;
+       break;
+      case EN_GET:
+       en_get = y;
+       break;
+#ifndef NOPUSH
+      case EN_HOS:
+       en_hos = y;
+       break;
+#endif /* NOPUSH */
+      case EN_SEN:
+       en_sen = y;
+       break;
+      case EN_SET:
+       en_set = y;
+       break;
+      case EN_SPA:
+       en_spa = y;
+       break;
+      case EN_TYP:
+       en_typ = y;
+       break;
+      case EN_WHO:
+       en_who = y;
+       break;
+      default:
+       return(-2);
+    }
+    return(1);
+}
+#endif /* NOFRILLS */
+
+#ifndef NOFRILLS
+int
+dodel() {                              /* DELETE */
+    long zl;
+    if ((x = cmifi("File(s) to delete","",&s,&y,xxstring)) < 0) {
+       if (x == -3) {
+           printf("?A file specification is required\n");
+           return(-9);
+       } else return(x);
+    }
+#ifdef MAC
+    strcpy(line,s);
+#else
+    strncpy(tmpbuf,s,50);              /* Make a safe copy of the name. */
+    debug(F110,"xxdel tmpbuf",s,0);
+    sprintf(line,"%s %s",DELCMD,s);    /* Construct the system command. */
+#endif /* MAC */
+    debug(F110,"xxdel line",line,0);
+    if ((y = cmcfm()) < 0) return(y);  /* Confirm the user's command. */
+#ifdef VMS
+    conres();
+#endif /* VMS */
+#ifdef MAC
+    s = line;
+    success = (zdelet(line) == 0);
+#else
+    s = tmpbuf;
+    xsystem(line);                     /* Let the system do it. */
+    zl = zchki(tmpbuf);
+    success = (zl == -1L);
+#endif /* MAC */
+    if (msgflg)
+      printf("%s - %sdeleted\n",s, success ? "" : "not ");
+    return(success);
+}
+#endif /* NOFRILLS */
+
+#ifndef NOSPL                          /* The ELSE command */
+int
+doelse() {
+    if (!ifcmd[cmdlvl]) {
+       printf("?ELSE doesn't follow IF\n");
+       return(-2);
+    }
+#ifdef COMMENT
+/*
+  Wrong.  This prevents IF..ELSE IF...ELSE IF...ELSE IF...ELSE...
+  from working.
+*/
+    ifcmd[cmdlvl] = 0;
+#endif /* COMMENT */
+    if (!iftest[cmdlvl]) {             /* If IF was false do ELSE part */
+       if (maclvl > -1) {              /* In macro, */
+           pushcmd();                  /* save rest of command. */
+       } else if (tlevel > -1) {       /* In take file, */
+           pushcmd();                  /* save rest of command. */
+       } else {                        /* If interactive, */
+           cmini(ckxech);              /* just start a new command */
+           printf("\n");               /* (like in MS-DOS Kermit) */
+           if (pflag) prompt(xxstring);
+       }
+    } else {                           /* Condition is false */
+       if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0)
+         return(y);                    /* Gobble up rest of line */
+    }
+    return(0);
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+int
+dofor() {                              /* The FOR command. */
+    int fx, fy, fz;                    /* loop variables */
+    char *ap;                          /* macro argument pointer */
+
+    if ((y = cmfld("Variable name","",&s,NULL)) < 0) { /* Get variable name */
+       if (y == -3) {
+           printf("?Variable name required\n");
+           return(-9);
+       } else return(y);
+    }
+    if ((y = parsevar(s,&x,&z)) < 0)   /* Check it. */
+      return(y);
+
+    lp = line;                         /* Build a copy of the command */
+    strcpy(lp,"_forx ");
+    lp += (int)strlen(line);           /* "_for" macro. */
+    ap = lp;                           /* Save pointer to macro args. */
+
+    if (*s == CMDQ) s++;               /* Skip past backslash if any. */
+    while (*lp++ = *s++) ;             /* copy it */
+    lp--; *lp++ = SP;                  /* add a space */
+
+    if ((y = cmnum("initial value","",10,&fx,xxstring)) < 0) {
+       if (y == -3) return(-2);
+       else return(y);
+    }
+    s = atmbuf;                                /* Copy the atom buffer */
+    if ((int)strlen(s) < 1) goto badfor;
+    while (*lp++ = *s++) ;             /* (what they actually typed) */
+    lp--; *lp++ = SP;
+
+    if ((y = cmnum("final value","",10,&fy,xxstring)) < 0) {
+       if (y == -3) return(-2);
+       else return(y);
+    }
+    s = atmbuf;                                /* Same deal */
+    if ((int)strlen(s) < 1) goto badfor;
+    while (*lp++ = *s++) ;
+    lp--; *lp++ = SP;
+
+    if ((y = cmnum("increment","1",10,&fz,xxstring)) < 0) {
+       if (y == -3) return(-2);
+       else return(y);
+    }
+    sprintf(tmpbuf,"%d ",fz);
+    s = atmbuf;                                /* same deal */
+    if ((int)strlen(s) < 1) goto badfor;
+    while (*lp++ = *s++) ;
+    lp--; *lp++ = SP;
+
+    /* Insert the appropriate comparison operator */
+    if (fz < 0)
+      *lp++ = '<';
+    else
+      *lp++ = '>';
+    *lp++ = SP;
+
+    if ((y = cmtxt("Command to execute","",&s,NULL)) < 0) return(y);
+    if ((int)strlen(s) < 1) return(-2);
+    
+    if (litcmd(&s,&lp) < 0) {
+       printf("?Unbalanced brackets\n");
+       return(0);
+    }
+    if (fz == 0) {
+       printf("?Zero increment not allowed\n");
+       return(0);
+    }
+    x = mlook(mactab,"_forx",nmac);    /* Look up FOR macro definition */
+    if (x < 0) {                       /* Not there? */
+       addmmac("_forx",for_def);       /* Put it back. */
+       if ((x = mlook(mactab,"_forx",nmac)) < 0) { /* Look it up again. */
+           printf("?FOR macro definition gone!\n"); /* Shouldn't happen. */
+           return(success = 0);
+       }
+    }
+    debug(F110,"FOR command",line,0);
+    return(success = dodo(x,ap));      /* Execute the FOR macro. */
+
+badfor: printf("?Incomplete FOR command\n");
+    return(-2);
+}
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+/* Do the BUG command */
+
+int
+dobug() {
+    printf("\n%s,%s\n Numeric: %ld",versio,ckxsys,vernum);
+    if (verwho) printf("-%d",verwho);
+    printf("\nTo report C-Kermit bugs, send e-mail to:\n");
+    printf(" Info-Kermit@columbia.edu (Internet)\n");
+    printf(" KERMIT@CUVMA (EARN/BITNET)\n");
+    printf(" ...!uunet!columbia.edu!info-kermit (Usenet)\n");
+    printf("Or write to:\n Kermit Development\n Columbia University\n");
+    printf(" Center for Computing Activities\n 612 W 115 Street\n");
+    printf(" New York, NY 10025 USA\nOr call:\n (212) 854-5126 (USA)\n\n");
+#ifndef NOSHOW
+#ifndef NOFRILLS
+    printf(
+"Before reporting problems, please use the SHOW VERSION and SHOW FEATURES\n");
+    printf(
+"commands to get detailed program version and configuration information.\n\n");
+#endif /* NOFRILLS */
+#endif /* NOSHOW */
+    return(1);
+}
+#endif /* NOFRILLS */
+
+#ifndef NOSPL
+int
+dopaus(cx) int cx; {
+    /* Both should take not only secs but also hh:mm:ss as argument. */
+    if (cx == XXWAI)
+      y = cmnum("seconds to wait","1",10,&x,xxstring);
+    else if (cx == XXPAU)
+      y = cmnum("seconds to pause","1",10,&x,xxstring);
+    else
+      y = cmnum("milliseconds to sleep","100",10,&x,xxstring);
+    if (y < 0) return(y);
+    if (x < 0) x = 0;
+    switch (cx) {
+      case XXPAU:                      /* PAUSE */
+      case XXMSL:                      /* MSLEEP */
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+      case XXWAI:                      /* WAIT */
+       z = 0;                          /* Modem signal mask */
+       while (1) {                     /* Read zero or more signal names */
+           y = cmkey(mstab,nms,"modem signal","",xxstring);
+           if (y == -3) break;         /* -3 means they typed CR */
+           if (y < 0) return(y);       /* Other negatives are errors */
+           z |= y;                     /* OR the bit into the signal mask */
+       }
+       break;
+
+      default:                         /* Shouldn't happen */
+       return(-2);
+    }
+
+/* Command is entered, now do it. */
+
+    if (cx == XXMSL) {                 /* Millisecond sleep */
+       msleep(x);
+       return(success = 1);
+    }
+    while (x--) {                      /* Sleep loop */
+       int mdmsig;
+       if (y = conchk()) {             /* Did they type something? */
+           while (y--) coninc(0);      /* Yes, gobble it up */
+           break;                      /* And quit PAUSing or WAITing */
+       }
+       if (cx == XXWAI && z != 0) {
+           mdmsig = ttgmdm();
+           if (mdmsig < 0) return(success = 0);
+           if ((mdmsig & z) == z) return(success = 1);
+       }
+       sleep(1);                       /* No interrupt, sleep one second */
+    }
+    if (cx == XXWAI) success = 0;
+    else success = (x == -1);          /* Set SUCCESS/FAILURE for PAUSE. */
+    return(0);
+}
+#endif /* NOSPL */
+
+
+#ifndef NOFRILLS
+int
+dorenam() {
+    if ((x = cmifi("File to rename","",&s,&y,xxstring)) < 0) {
+       if (x == -3) {
+           printf("?Name of existing file required\n");
+           return(-9);
+       } else return(x);
+    }
+    if (y) {                           /* No wildcards allowed */
+       printf("\n?Please specify a single file\n");
+       return(-9);
+    }
+    strcpy(line,s);                    /* Make a safe copy of the old name */
+    p = line + (int)strlen(line) + 2;  /* Place for new name */
+    if ((x = cmofi("New name","",&s,xxstring)) < 0) { /* Get new name */
+       if (x == -3) {
+           printf("?New name for file required\n");
+           return(-9);
+       } else return(x);
+    }
+    strcpy(p,s);                       /* Make a safe copy of the new name */
+    if ((y = cmcfm()) < 0) return(y);
+#ifdef VMS
+    conres();                          /* Let Ctrl-C work. */
+#endif /* VMS */
+    return(zrename(line,p));
+}
+#endif /* NOFRILLS */
+
+
+#ifndef NOSPL
+
+/* Do the RETURN command */
+
+int
+doreturn(s) char *s; {
+    int x; char *p;
+    if (maclvl < 0) {
+       printf("\n?Can't return from level %d\n",maclvl);
+       return(success = 0);
+    }
+    lp = line;                         /* Expand return value now */
+    x = LINBUFSIZ-1;
+    if (xxstring(s,&lp,&x) > -1) {
+       s = line;
+    }
+    x = (int)strlen(s);                        /* Is there a return value? */
+    if (x) {                           /* Yes */
+       p = malloc(x+2);                /* Allocate a place to keep it */
+       if (p) {                        /* Did we get a place? */
+           strcpy(p, s);               /* Yes, copy the string into it. */
+           mrval[maclvl] = p;          /* Make return value point to it. */
+       } else {                        /* No, could not get space. */
+           mrval[maclvl] = NULL;       /* Return null pointer. */
+           x = 0;                      /* Set failure return code. */
+       }
+    } else mrval[maclvl] = NULL;       /* Blank return code */
+#undef FORRET
+/*
+  If we are in a FOR, WHILE, or XIF command list, also copy the return value
+  two levels up.  (But this doesn't work, so forget it.)
+*/
+#ifdef FORRET
+    if (maclvl > 1) {
+       if (!strncmp(m_arg[maclvl][0],"_for",4) ||
+           !strncmp(m_arg[maclvl][0],"_whi",4) ||
+           !strncmp(m_arg[maclvl][0],"_xif",4)) {
+           mrval[maclvl-2] = p;
+       }
+    }
+#endif /* FORRET */
+    popclvl();                         /* Pop command level */
+
+#ifdef DEBUG
+    if (mrval[maclvl+1])
+      debug(F111,"&return",mrval[maclvl+1],maclvl);
+    else debug(F111,"&return","NULL",maclvl);
+#endif /* DEBUG */
+    return(success = x ? 1 : 0);       /* Return status code */        
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+/* Do the OPEN command */
+
+int
+doopen()  {                            /* OPEN { append, read, write } */
+    int x, y, z; char *s;
+    static struct filinfo fcb;         /* (must be static) */
+    if ((x = cmkey(opntab,nopn,"mode","",xxstring)) < 0) {
+       if (x == -3) {
+           printf("?Mode required\n");
+           return(-9);
+       } else return(x);
+    }
+    switch (x) {
+      case XYFZ_O:                     /* Old file (READ) */
+       if (chkfn(ZRFILE) > 0) {
+           printf("?Read file already open\n");
+           return(-2);
+       }
+       if ((z = cmifi("File to read","",&s,&y,xxstring)) < 0) {
+           if (z == -3) {
+               printf("?Input filename required\n");
+               return(-9);
+           } else return(z);
+       }
+       if (y) {                                /* No wildcards allowed */
+           printf("\n?Please specify a single file\n");
+           return(-2);
+       }
+       strcpy(line,s);
+       if ((int)strlen(line) < 1) return(-2);
+       if ((y = cmcfm()) < 0) return(y);
+       return(success = zopeni(ZRFILE,line));
+
+#ifndef MAC
+#ifndef NOPUSH
+      case XYFZ_Y:                     /* Pipe/Process (READ) */
+       if (chkfn(ZRFILE) > 0) {
+           printf("?Read file already open\n");
+           return(-2);
+       }
+        if ((y = cmtxt("System command to read from","",&s,xxstring)) < 0) {
+           if (y == -3) {
+               printf("?Command name required\n");
+               return(-9);
+           } else return(y);
+       }
+       strcpy(line,s);
+       if ((int)strlen(line) < 1) return(-2);
+       if ((y = cmcfm()) < 0) return(y);
+       return(success = zxcmd(ZRFILE,line));
+
+      case XYFZ_X:                     /* Write to pipe */
+       if (chkfn(ZWFILE) > 0) {
+           printf("?Write file already open\n");
+           return(-2);
+       }
+        if ((y = cmtxt("System command to write to","",&s,xxstring)) < 0) {
+           if (y == -3) {
+               printf("?Command name required\n");
+               return(-9);
+           } else return(y);
+       }
+       strcpy(line,s);
+       if ((int)strlen(line) < 1) return(-2);
+       if ((y = cmcfm()) < 0) return(y);
+       success = zxcmd(ZWFILE,line);
+       if (!success && msgflg)
+         printf("Can't open process for writing: %s\n",line);
+       return(success);
+#endif /* NOPUSH */
+#endif /* MAC */
+
+      case XYFZ_N:                     /* New file (WRITE) */
+      case XYFZ_A:                     /* (APPEND) */
+       if ((z = cmofi("Name of local file to create","",&s,xxstring)) < 0) {
+           if (z == -3) {
+               printf("?Filename required\n");
+               return(-9);
+           } else return(z);
+       }
+       if (chkfn(ZWFILE) > 0) {
+           printf("?Write/Append file already open\n");
+           return(-2);
+       }
+        fcb.bs = fcb.cs = fcb.rl = fcb.fmt = fcb.org = fcb.cc = fcb.typ = 0;
+       fcb.lblopts = 0;
+       fcb.dsp = x;                    /* Create or Append */
+       strcpy(line,s);
+       if ((int)strlen(line) < 1) return(-2);
+       if ((y = cmcfm()) < 0) return(y);
+       return(success = zopeno(ZWFILE,line,NULL,&fcb));
+
+      default:
+       printf("?Not implemented");
+       return(-2);
+    }
+}
+#endif /* NOSPL */
+
+/* Finish parsing and do the GET command */
+
+int
+doget() {
+    int x;
+    char *cbp;
+
+    cmarg2 = "";                       /* Initialize as-name to nothing */
+    x = 0;
+#ifdef NOFRILLS
+    if (*cmarg == NUL) {
+       printf("?Remote filespec required\n");
+       return(-3);
+    }
+#else
+/*
+  If remote file name omitted, get foreign and local names separately.
+  But multine GET is allowed only if NOFRILLS is not defined.
+*/
+    if (*cmarg == NUL) {
+       if (tlevel > -1
+#ifndef NOSPL
+           && cmdstk[cmdlvl].src == CMD_TF
+#endif /* NOSPL */
+           ) {
+
+/* Input is from a command file. */
+
+           /* Read 2nd line of GET command */
+
+           if (getnct(cmdbuf,CMDBL) < 0) {
+               printf("Command file ends prematurely in multiline GET\n");
+               popclvl();
+               return(-9);
+           }
+           cmres();                    /* Parse it */
+           if ((x = cmtxt("Oofa","",&s,xxstring)) < 0)
+             return(x);
+           if (*s == '{') {            /* Strip enclosing braces */
+               x = (int)strlen(s);
+               if (s[x-1] == '}') {
+                   s[x-1] = NUL;
+                   s++;
+               }
+           }
+           strcpy(line,s);             /* Make a safe copy */
+           cmarg = line;               /* Point to remote filename */
+           if (*cmarg == NUL) {        /* Make sure there is one */
+               printf("Remote filename missing in multiline GET\n");
+               return(-9);
+           }
+           lp = line + strlen(line) + 1; /* Place for as-name */
+
+           /* And third line... */
+
+           cmarg2 = "";                /* Assume no as-name */
+           if (getnct(cmdbuf,CMDBL) < 0) { /* Get next line */
+               popclvl();              /* There isn't one. */
+           } else {                    /* There is... */
+               if (*cmdbuf >= ' ') {   /* Parse as output filename */
+                   cmres();
+                   if ((x = cmofi("Mupeen",cmarg,&s,xxstring)) < 0)
+                     return(x);
+                   strcpy(lp,s);       /* Make a safe copy */
+                   cmarg2 = lp;        /* Point as-name pointer at it */
+               }
+           }
+            x = 0;                     /* Return code OK */
+
+#ifndef NOSPL
+/* Reading commands from a macro definition */
+
+       } else if (cmdlvl > 0 && cmdstk[cmdlvl].src == CMD_MD) {
+
+           /* Read second line of GET command */
+
+           cbp = cmdbuf;
+           if (getncm(cbp,CMDBL) < 0) {
+               printf("Macro definition ends prematurely in multiline GET\n");
+               return(-9);
+           }
+           cmres();
+           if ((x = cmtxt("Oofa","",&s,xxstring)) < 0) return(x);
+           if (*s == NUL) {            /* Make sure we got something */
+               printf("Remote filename missing in multiline GET\n");
+               return(-9);
+           }
+           if (*s == '{') {            /* Strip enclosing braces */
+               x = (int)strlen(s);
+               if (s[x-1] == '}') {
+                   s[x-1] = NUL;
+                   s++;
+               }
+           }
+           strcpy(line,s);             /* Copy filename to safe place */
+           cmarg = line;               /* Point to it */
+           x = strlen(line);           /* Get its length */
+           lp = line + x + 1;          /* Where to put the next bit */
+           y = LINBUFSIZ - x - 1;      /* Room left for next bit */
+
+           /* And third line... */
+
+           cmarg2 = "";                /* Assume no as-name */
+           if (getncm(lp,y) > -1 && *lp >= ' ') { /* Read next line */
+               x = strlen(lp);
+               if (lp[x-1] == CR) lp[x-1] = NUL; /* Remove CR */
+               cbp = cmdbuf;           /* Interpret the line */
+               *cbp = NUL;             /* ... */
+               y = CMDBL;              /* into the command buffer */
+               xxstring(lp,&cbp,&y);
+               if (*cmdbuf) {          /* If we have something */
+                   cmres();            /* parse it as an output filename */
+                   strcat(cmdbuf," ");
+                   if ((x = cmofi("Mupeen","",&s,NULL)) < 0)
+                     return(x);
+                   strcpy(lp,s);       /* Copy the name to safe place */
+                   cmarg2 = lp;        /* and make as-name pointer */
+               }
+           }
+            x = 0;                     /* Return code OK */
+#endif /* NOSPL */
+        } else {                       /* Input is from terminal */
+           cmsavp(psave,80);
+           cmsetp(" Remote file specification: "); /* Make new one */
+           cmini(ckxech);
+           x = -1;
+           if (pflag) prompt(xxstring);
+           while (x == -1) {           /* Prompt till they answer */
+               x = cmtxt("Name of remote file(s)","",&cmarg,xxstring);
+               debug(F111," cmtxt",cmarg,x);
+           }
+           if (x < 0) {
+               cmsetp(psave);
+               return(x);
+           }
+           if (*cmarg == NUL) {        /* If user types a bare CR, */
+               printf("(cancelled)\n"); /* Forget about this. */
+               cmsetp(psave);          /* Restore old prompt, */
+               return(0);              /* and return. */
+           }
+           if (*cmarg == '{') {        /* Strip enclosing braces */
+               x = (int)strlen(cmarg);
+               if (cmarg[x-1] == '}') {
+                   cmarg[x-1] = NUL;
+                   cmarg++;
+               }
+           }
+           strcpy(line,cmarg);         /* Make a safe copy */
+           cmarg = line;
+           cmsetp(" Local name to store it under: "); /* New prompt */
+           cmini(ckxech);
+           x = -1;
+           if (pflag) prompt(xxstring);
+           while (x == -1) {           /* Again, parse till answered */
+               x = cmofi("Local file name","",&cmarg2,xxstring);
+           }
+           if (x < 0) {                /* Parse error */
+               if (x == -3) {          /* CR = cancel */
+                   printf("(cancelled)\n"); /* Print message */
+                   x = 0;              /* Avoid further messages */
+               }
+               cmsetp(psave);          /* Restore prompt */
+               return(x);
+           }       
+           x = -1;                     /* Get confirmation. */
+           while (x == -1) x = cmcfm();
+           cmsetp(psave);              /* Restore old prompt. */
+        }
+    }
+#endif /* NOFRILLS */
+    if (x == 0) {                      /* Good return from cmtxt or cmcfm, */
+       debug(F110,"xxget cmarg",cmarg,0);
+       strncpy(fspec,cmarg,FSPECL);
+       debug(F111,"xxget fspec",fspec,FSPECL);
+       sstate = 'r';                   /* Set start state. */
+       if (local) {
+           displa = 1;
+           ttflui();
+       }
+    }
+    return(x);
+}
+
+#ifndef NOSPL
+
+int
+dogta(cx) int cx; {
+    int i; char c; char mbuf[4]; char *p;
+
+    if ((y = cmcfm()) < 0)
+      return(y);
+    if (cx == XXGTA)
+      debug(F101,"_getargs maclvl","",maclvl);
+    else if (cx == XXPTA)
+      debug(F101,"_putargs maclvl","",maclvl);
+    else
+      return(-2);
+    if (maclvl < 1)
+      return(success = 0);
+
+#ifdef COMMENT
+#ifdef NEXT
+/* 
+  For some reason, this routine makes Kermit core dump on the next after
+  it returns to docmd().  It works fine, as the debug log shows, but when
+  docmd returns, it gets a memory fault.
+*/
+    else return(1);
+#endif /* NEXT */
+#endif /* COMMENT */
+
+    mbuf[0] = '%'; mbuf[1] = '0'; mbuf[2] = '\0'; /* Argument name buf */
+    for (i = 0; i < 10; i++) {         /* For all args */
+       c = (char) i + '0';             /* Make name */
+       mbuf[1] = c;                    /* Insert digit */
+       if (cx == XXGTA) {              /* Get arg from level-minus-2 */
+           if (maclvl == 1) p = g_var[c]; /* If at level 1 use globals 0..9 */
+           else p = m_arg[maclvl-2][i]; /* Otherwise they're on the stack */
+           if (!p) {
+               debug(F111,"_getarg p","(null pointer)",i);
+           } else debug(F111,"_getarg p",p,i);
+           addmac(mbuf,p);
+       } else if (cx == XXPTA) {       /* Put args level+2 */
+#ifndef MAC
+           connoi();                   /* Turn off interrupts. */
+#endif /* MAC */
+           maclvl -= 2;                /* This is gross.. */
+           p = m_arg[maclvl+2][i];
+           if (p)
+             debug(F111,"_putarg m_arg[maclvl+2][i]",p,i);
+           else
+             debug(F111,"_putarg m_arg[maclvl+2][i]","(null pointer)",i);
+           addmac(mbuf,m_arg[maclvl+2][i]);
+           maclvl += 2;
+#ifndef MAC
+           conint(trap,stptrap);       /* Restore interrupts */
+#endif /* MAC */
+       } else return(success = 0);
+    }
+    debug(F101,"_get/putarg exit","",i);
+    debug(F101,"_get/putarg exit maclvl","",maclvl);
+    return(success = 1);
+}
+#endif /* NOSPL */
+
+
+#ifndef NOSPL
+/* Do the GOTO command */
+
+int
+dogoto(s) char *s; {
+    int i, j, x, y;
+    char tmplbl[50], *lp;
+
+    debug(F101,"goto cmdlvl","",cmdlvl);
+    debug(F101,"goto maclvl","",maclvl);
+    debug(F101,"goto tlevel","",tlevel);
+    debug(F110,"goto before conversion",s,0);
+    y = (int)strlen(s);
+    if (*s != ':') {                   /* If the label mentioned */
+       for (i = y; i > 0; i--) {       /* does not begin with a colon, */
+           s[i] = s[i-1];              /* then insert one. */
+       }                               /* Also, convert to lowercase. */
+       s[0] = ':';
+       s[++y] = '\0';
+    }
+    debug(F111,"goto after conversion",s,y);
+    if (s[1] == '.' || s[1] == SP || s[1] == NUL) {
+       printf("?Bad label syntax - '%s'\n",s);
+       return(success = 0);
+    }
+    if (cmdlvl == 0) {
+       printf("?Sorry, GOTO only works in a command file or macro\n");
+       return(success = 0);
+    }
+    while (cmdlvl > 0) {               /* Only works inside macros & files */
+       if (cmdstk[cmdlvl].src == CMD_MD) { /* GOTO inside macro */
+           int i, m, flag;
+           char *xp, *tp;
+
+           lp = macx[maclvl];
+           m = (int)strlen(lp) - y + 1;
+           debug(F111,"goto in macro",lp,m);
+
+           flag = 1;                   /* flag for valid label position */
+           for (i = 0; i < m; i++,lp++) { /* search for label in macro body */
+               if (*lp == ',') {       /* Really should also watch out */
+                   flag = 1;           /* for braces here...  Commas in */
+                   continue;           /* in braces are not really commas */
+               }
+               if (flag) {             /* If in valid label position */
+                   if (*lp == SP)      /* eat leading spaces */
+                     continue;
+                   if (*lp != ':') {   /* Look for label introducer */
+                       flag = 0;       /* this isn't it */
+                       continue;       /* keep looking */
+                   }
+               }
+               if (!flag)              /* We don't have a label */
+                 continue;             /*  so keep looking... */
+               xp = lp; tp = tmplbl;   /* Copy the label from the macro */
+               j = 0;                  /* to make it null-terminated */
+               while (*tp = *xp) {
+                   if (j++ > 50) break;  /* j = length of word from macro */
+                   if (*tp < 33 || *tp == ',') /* Look for end of word */
+                     break;
+                   else tp++, xp++;    /* Next character */
+               }
+               *tp = '\0';             /* In case we stopped early */
+               /* Now do caseless string comparison, using longest length */
+               debug(F111,"macro GOTO label",s,y);
+               debug(F111,"macro target label",tmplbl,j);
+               if (!xxstrcmp(s,tmplbl,(y > j) ? y : j))
+                 break;
+               else flag = 0;
+           }
+           if (i == m) {               /* didn't find the label */
+               debug(F101,"goto failed at cmdlvl","",cmdlvl);
+               if (!popclvl()) {       /* pop up to next higher level */
+                   printf("?Label '%s' not found\n",s); /* if none */
+                   return(0);          /* quit */
+               } else continue;        /* otherwise look again */
+           }
+           debug(F110,"goto found macro label",lp,0);
+           macp[maclvl] = lp;          /* set macro buffer pointer */
+           return(1);
+       } else if (cmdstk[cmdlvl].src == CMD_TF) {
+           x = 0;                      /* GOTO issued in take file */
+           rewind(tfile[tlevel]);      /* Search file from beginning */
+           while (! feof(tfile[tlevel])) {
+               if (fgets(line,LINBUFSIZ,tfile[tlevel]) == NULL) /* Get line */
+                 break;                /* If no more, done, label not found */
+               lp = line;              /* Got line */
+               while (*lp == SP || *lp == HT)
+                 lp++;                 /* Strip leading whitespace */
+               if (*lp != ':') continue; /* Check for label introducer */
+               tp = lp;                /* Get end of word */
+               j = 0;
+               while (*tp) {           /* And null-terminate it */
+                   if (*tp < 33) {
+                       *tp = '\0';
+                       break;
+                   } else tp++, j++;
+               }
+               if (!xxstrcmp(lp,s,(y > j) ? y : j)) { /* Caseless compare */
+                   x = 1;              /* Got it */
+                   break;              /* done. */
+               }
+           }
+           if (x == 0) {               /* If not found, print message */
+               debug(F101,"goto failed at cmdlvl","",cmdlvl);
+               if (!popclvl()) {       /* pop up to next higher level */
+                   printf("?Label '%s' not found\n",s);        /* if none */
+                   return(0);          /* quit */
+               } else continue;        /* otherwise look again */
+           }
+           return(x);                  /* Send back return code */
+       }
+    }
+    printf("?Stack problem in GOTO %s\n",s); /* Shouldn't see this */
+    return(0);
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+/* Finish parsing and do the IF, XIF, and WHILE commands */
+
+int
+doif(cx) int cx; {
+    int x, y, z; char *s, *p;
+
+    not = 0;                           /* Flag for whether "NOT" was seen */
+    z = 0;                             /* Initial IF condition */
+    ifargs = 0;                                /* Count of IF condition words */
+
+ifagain:
+    if ((ifc = cmkey(iftab,nif,"","",xxstring)) < 0) { /* If what?... */
+       if (ifc == -3) {
+           printf("?Condition required\n");
+           return(-9);
+       } else return(ifc);
+    }
+    switch (ifc) {                     /* set z = 1 for true, 0 for false */
+      case XXIFNO:                     /* IF NOT */
+       not ^= 1;                       /* So NOT NOT NOT ... will work */
+       ifargs++;
+       goto ifagain;
+      case XXIFSU:                     /* IF SUCCESS */
+       z = ( success != 0 );
+       debug(F101,"if success","",z);
+       ifargs += 1;
+       break;
+      case XXIFFA:                     /* IF FAILURE */
+       z = ( success == 0 );
+       debug(F101,"if failure","",z);
+       ifargs += 1;
+       break;
+      case XXIFDE:                     /* IF DEFINED */
+       if ((x = cmfld("Macro or variable name","",&s,NULL)) < 0) {
+           if (x == -3) return(-2);
+           else return(x);
+       }
+#ifdef COMMENT
+       strcpy(line,s);                 /* Make a copy */
+        if ((int)strlen(line) < 1) return(-2);
+       lp = line;
+       if (line[0] == CMDQ && (line[1] == '%' || line[1] == '&')) lp++;
+       if (*lp == '%') {               /* Is it a variable? */
+           x = *(lp + 1);              /* Fold case */
+           if (isupper(x)) *(lp + 1) = tolower(x);
+           if (x >= '0' && x <= '9' && maclvl > -1) /* Digit is macro arg */
+             z = ( (m_arg[maclvl][x - '0'] != (char *)0)
+                  && (int)strlen(m_arg[maclvl][x - '0']) != 0);
+           else                        /* Otherwise it's a global variable */
+             z = ( (g_var[x] != (char *)0)
+                  &&  (int)strlen(g_var[x]) != 0 );
+       } else if (*lp == '&') {        /* Array reference */
+           int cc, nn;
+           if (arraynam(lp,&cc,&nn) < 0)
+             z = 0;
+           else z = (arrayval(cc,nn) == NULL ? 0 : 1);
+       }
+#else
+        if ((int)strlen(s) < 1) return(-2);
+       z = 0;                          /* Assume failure. */
+       if (*s == CMDQ) {               /* Object begins with backslash. */
+           char c;
+           c = s[1];                   /* Character following backslash */
+           if (c) {
+               c = islower(c) ? toupper(c) : c;
+               if (c == '%' ||         /* Simple variable */
+                   c == '&' ||         /* Array element */
+                   c == '$' ||         /* Environment variable */
+                   c == 'V' ||         /* Builtin named variable */
+                   c == 'M' ||         /* Macro name */
+                   c == 'F') {         /* Builtin function */
+                   int t;              /* Let xxstring() evaluate it */
+                   t = LINBUFSIZ-1;    /* This lets us test \v(xxx) */
+                   lp = line;          /* and even \f...(xxx) */
+                   xxstring(s,&lp,&t);
+                   t = strlen(line);
+                   debug(F111,"IF DEF",line,t);
+                   z = t > 0;
+               }
+           } 
+       } 
+#endif /* COMMENT */
+       else {                  /* Otherwise it's a macro name */
+           z = ( mxlook(mactab,s,nmac) > -1 ); /* Look for exact match */
+       }
+       debug(F111,"if defined",s,z);
+       ifargs += 2;
+       break;
+
+      case XXIFBG:                     /* IF BACKGROUND */
+      case XXIFFG:                     /* IF FOREGROUND */    
+       bgchk();                        /* Check background status */
+       if (ifc == XXIFFG)              /* Foreground */
+         z = pflag ? 1 : 0;
+        else z = pflag ? 0 : 1;                /* Background */
+       ifargs += 1;
+       break;
+
+      case XXIFCO:                     /* IF COUNT */
+       z = ( --count[cmdlvl] > 0 );
+       debug(F101,"if count","",z);
+       ifargs += 1;
+       break;
+
+      case XXIFEX:                     /* IF EXIST */
+       if ((x = cmfld("File","",&s,xxstring)) < 0) {
+           if (x == -3) {
+               printf("?Filename required\n");
+               return(-9);
+           } else return(x);
+       }
+       z = ( zchki(s) > -1L );
+       debug(F101,"if exist","",z);
+       ifargs += 2;
+       break;
+
+      case XXIFEQ:                     /* IF EQUAL (string comparison) */
+      case XXIFLL:                     /* IF Lexically Less Than */
+      case XXIFLG:                     /* If Lexically Greater Than */
+       if ((x = cmfld("first word or variable name","",&s,xxstring)) < 0) {
+           if (x == -3) {
+               printf("?Text required\n");
+               return(-9);
+           } else return(x);
+       }
+       x = (int)strlen(s);
+       if (x > LINBUFSIZ-1) {
+           printf("?IF: strings too long\n");
+           return(-2);
+       }
+       lp = line;                      /* lp points to first string */
+       strcpy(lp,s);
+       if ((y = cmfld("second word or variable name","",&s,xxstring)) < 0) {
+           if (y == -3) {
+               printf("?Text required\n");
+               return(-9);
+           } else return(y);
+       }
+       y = (int)strlen(s);
+       if (x + y + 2 > LINBUFSIZ) {
+           printf("?IF: strings too long\n");
+           return(-2);
+       }
+       tp = lp + y + 2;                /* tp points to second string */
+       strcpy(tp,s);
+       if (incase)                     /* INPUT CASE OBSERVE */
+         x = strcmp(lp,tp);
+       else                            /* INPUT CASE IGNORE */
+         x = xxstrcmp(lp,tp,(y > x) ? y : x); /* Use longest length */
+       debug(F101,"IF comparison","",x);
+       switch (ifc) {
+         case XXIFEQ:                  /* IF EQUAL (string comparison) */
+           z = (x == 0);
+           break;
+         case XXIFLL:                  /* IF Lexically Less Than */
+           z = (x < 0);
+           break;
+         case XXIFLG:                  /* If Lexically Greater Than */
+           z = (x > 0);
+           break;
+       }
+       ifargs += 3;
+       break;
+
+      case XXIFAE:                     /* IF (arithmetically) = */
+      case XXIFLT:                     /* IF (arithmetically) < */
+      case XXIFGT: {                   /* IF (arithmetically) > */
+       /* Really should use longs here... */
+       /* But cmnum parses ints. */
+       int n1, n2;
+       x = cmfld("first number or variable name","",&s,xxstring);
+       if (x == -3) {
+           printf("?Quantity required\n");
+           return(-9);
+       }
+       if (x < 0) return(x);
+       debug(F101,"xxifgt cmfld","",x);
+       lp = line;
+       strcpy(lp,s);
+       debug(F110,"xxifgt exp1",lp,0);
+       if (!xxstrcmp(lp,"count",5)) {
+           n1 = count[cmdlvl];
+       } else if (!xxstrcmp(lp,"version",7)) {
+           n1 = (int) vernum;
+       } else if (!xxstrcmp(lp,"argc",4)) {
+           n1 = (int) macargc[maclvl];
+       } else {
+           if (!chknum(lp)) return(-2);
+           n1 = atoi(lp);
+       }
+       y = cmfld("second number or variable name","",&s,xxstring);
+       if (y == -3) {
+           printf("?Quantity required\n");
+           return(-9);
+       }
+       if (y < 0) return(y);
+        if ((int)strlen(s) < 1) return(-2);
+       x = (int)strlen(lp);
+       tp = line + x + 2;
+       strcpy(tp,s);
+       debug(F110,"xxifgt exp2",tp,0);
+       if (!xxstrcmp(tp,"count",5)) {
+           n2 = count[cmdlvl];
+       } else if (!xxstrcmp(tp,"version",7)) {
+           n2 = (int) vernum;
+       } else if (!xxstrcmp(tp,"argc",4)) {
+           n2 = (int) macargc[maclvl];
+       } else {
+           if (!chknum(tp)) return(-2);
+           n2 = atoi(tp);
+       }
+       debug(F101,"xxifft ifc","",ifc);
+       z = ((n1 <  n2 && ifc == XXIFLT)
+         || (n1 == n2 && ifc == XXIFAE)
+         || (n1 >  n2 && ifc == XXIFGT));
+       debug(F101,"xxifft n1","",n1);
+       debug(F101,"xxifft n2","",n2);
+       debug(F101,"xxifft z","",z);
+       ifargs += 3;
+       break; }
+
+      case XXIFNU:                     /* IF NUMERIC */
+       x = cmfld("variable name or constant","",&s,xxstring);
+       if (x == -3) {
+           printf("?Quantity required\n");
+           return(-9);
+       }
+       if (x < 0) return(x);
+       debug(F111,"xxifnu cmfld",s,x);
+       lp = line;
+       strcpy(lp,s);
+       debug(F110,"xxifnu quantity",lp,0);
+        z = chknum(lp);
+        debug(F101,"xxifnu chknum","",z);
+       ifargs += 2;
+       break;
+
+      default:                         /* Shouldn't happen */
+       return(-2);
+    }
+
+    switch (cx) {                      /* Separate handling for IF and XIF */
+
+      case XXIF:                       /* This is IF... */
+       ifcmd[cmdlvl] = 1;              /* We just completed an IF command */
+       if (not) z = !z;                /* Handle NOT here */
+       if (z) {                        /* Condition is true */
+           iftest[cmdlvl] = 1;         /* Remember that IF succeeded */
+           if (maclvl > -1) {          /* In macro, */
+               pushcmd();              /* save rest of command. */
+           } else if (tlevel > -1) {   /* In take file, */
+               debug(F100, "doif: pushing command", "", 0);
+               pushcmd();              /* save rest of command. */
+           } else {                    /* If interactive, */
+               cmini(ckxech);          /* just start a new command */
+               printf("\n");           /* (like in MS-DOS Kermit) */
+               if (pflag) prompt(xxstring);
+           }
+       } else {                        /* Condition is false */
+           iftest[cmdlvl] = 0;         /* Remember command failed. */
+           if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0)
+             return(y);                /* Gobble up rest of line */
+       }
+       return(0);
+
+      case XXIFX: {                    /* This is XIF (Extended IF) */
+         char *p;
+         char e[5];
+         int i;
+         if ((y = cmtxt("Object command","",&s,NULL)) < 0)
+           return(y);                  /* Get object command. */
+         p = s;
+         lp = line;
+         if (litcmd(&p,&lp) < 0) {     /* Insert quotes in THEN-part */
+             return(-2);
+         }
+         if (!z) {                     /* Use ELSE-part, if any */
+             lp = line;                /* Write over THEN part. */
+             *lp = NUL;
+             while (*p == SP) p++;     /* Strip trailing spaces */
+             if (*p) {                 /* At end? */
+                 for (i = 0; i < 4; i++) e[i] = *p++; /* No, check for ELSE */
+                 if (xxstrcmp(e,"else",4)) return(-2); /* No, syntax error */
+                 if (litcmd(&p,&lp) < 0) { /* Insert quotes */
+                     return(-2);
+                 }
+                 while (*p == SP) p++; /* Strip trailing spaces */
+                 if (*p) return(-2);   /* Should be nothing here. */
+             }
+         }
+         if (line[0]) {
+             x = mlook(mactab,"_xif",nmac); /* get index of "_xif" macro. */
+             if (x < 0) {                      /* Not there? */
+                 addmmac("_xif",xif_def);      /* Put it back. */
+                 if (mlook(mactab,"_xif",nmac) < 0) { /* Look it up again. */
+                     printf("?XIF macro gone!\n");
+                     return(success = 0);
+                 }
+             }
+             dodo(x,line);             /* Do the XIF macro */
+         }
+         return(0);
+      }
+      case XXWHI: {                    /* WHILE Command */
+         p = cmdbuf;                   /* Capture IF condition */
+         ifcond[0] = NUL;              /* from command buffer */
+         while (*p == SP) p++;
+         while (*p != SP) p++;
+         ifcp = ifcond;
+         strcpy(ifcp,"{ \\flit(if not ");
+         ifcp += (int)strlen(ifcp);
+         while (*p != '{' && *p != NUL) *ifcp++ = *p++;
+         p = " goto wbot) } ";
+         while (*ifcp++ = *p++) ;
+         debug(F110,"WHILE cmd",ifcond,0);
+
+         if ((y = cmtxt("Object command","",&s,NULL)) < 0)
+           return(y);                  /* Get object command. */
+         p = s;
+         lp = line;
+         if (litcmd(&p,&lp) < 0) {     /* Insert quotes in object command */
+             return(-2);
+         }
+         debug(F110,"WHILE body",line,0);
+         if (line[0]) {
+             char *p;
+             x = mlook(mactab,"_while",nmac); /* index of "_while" macro. */
+             if (x < 0) {              /* Not there? */
+                 addmmac("_while",whil_def); /* Put it back. */
+                 if (mlook(mactab,"_while",nmac) < 0) { /* Look it up again */
+                     printf("?WHILE macro definition gone!\n");
+                     return(success = 0);
+                 }
+             }
+             p = malloc((int)strlen(ifcond) + (int)strlen(line) + 2);
+             if (p) {
+                 strcpy(p,ifcond);
+                 strcat(p,line);
+                 debug(F110,"WHILE dodo",p,0);
+                 dodo(x,p);
+                 free(p);
+             } else {
+                 printf("?Can't allocate storage for WHILE command");
+                 return(success = 0);
+             }
+         }
+         return(0);
+      }
+      default:
+       return(-2);
+    }
+}
+#endif /* NOSPL */
+
+/* Set up a TAKE command file */
+
+int
+dotake(s) char *s; {
+    if ((tfile[++tlevel] = fopen(s,"r")) == NULL) {
+       perror(s);
+       debug(F110,"Failure to open",s,0);
+       success = 0;
+       tlevel--;
+    } else {
+#ifdef VMS
+       conres();                       /* So Ctrl-C will work */
+#endif /* VMS */
+#ifndef NOSPL
+       cmdlvl++;                       /* Entering a new command level */
+       if (cmdlvl > CMDSTKL) {
+           cmdlvl--;
+           printf("?TAKE files and/or DO commands nested too deeply\n");
+           return(success = 0);
+       }
+       if (tfnam[tlevel]) free(tfnam[tlevel]); /* Copy the filename */
+       if (tfnam[tlevel] = malloc(strlen(s) + 1))
+         strcpy(tfnam[tlevel],s);
+       ifcmd[cmdlvl] = 0;              /* Set variables for this cmd file */
+       iftest[cmdlvl] = 0;
+       count[cmdlvl] = 0;
+       cmdstk[cmdlvl].src = CMD_TF;    /* Say we're in a TAKE file */
+       cmdstk[cmdlvl].lvl = tlevel;    /* nested at this level */
+#endif /* NOSPL */
+    }
+    return(1);
+}
+#endif /* NOICP */
diff --git a/usr/src/contrib/kermit-5A.188/ckuus7.c b/usr/src/contrib/kermit-5A.188/ckuus7.c
new file mode 100644 (file)
index 0000000..6b35604
--- /dev/null
@@ -0,0 +1,2114 @@
+#ifndef NOICP
+
+/*  C K U U S 7 --  "User Interface" for Unix Kermit, part 7  */
+/*
+  Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
+  Columbia University Center for Computing Activities.
+  First released January 1985.
+  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
+  York.  Permission is granted to any individual or institution to use this
+  software as long as it is not sold for profit.  This copyright notice must be
+  retained.  This software may not be included in commercial products without
+  written permission of Columbia University.
+*/
+/*
+  This file created from parts of ckuus3.c, which became to big for
+  Mark Williams Coherent compiler to handle.
+*/
+
+/*
+  Definitions here supersede those from system include files.
+*/
+#include "ckcdeb.h"                    /* Debugging & compiler things */
+#include "ckcasc.h"                    /* ASCII character symbols */
+#include "ckcker.h"                    /* Kermit application definitions */
+#include "ckcxla.h"                    /* Character set translation */
+#include "ckcnet.h"                    /* Network symbols */
+#include "ckuusr.h"                    /* User interface symbols */
+\f
+static int x, y = 0, z;
+static char *s;
+
+static int mdmsav = -1;                        /* Save modem type around network */
+static int oldplex = -1;               /* Duplex holder around network */
+
+extern int success, nfilp, fmask, fncnv, frecl, nfttyp, binary, warn, msgflg;
+extern int cmask, maxrps, wslotr, bigsbsiz, bigrbsiz, urpsiz, rpsiz, spsiz;
+extern int spsizr, spsizf, maxsps, spmax, pflag, bctr, npad, timef, timint;
+extern int pkttim, rtimo, local, nfils, displa, atcapr, nettype, escape;
+extern int mdmtyp, duplex, dfloc, network, cdtimo, fncact, mypadn;
+extern int tnlm, sosi, tlevel, lf_opts, backgrd, flow, fdispla;
+extern int
+  atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
+  attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; 
+
+extern long speed;
+
+extern CHAR sstate, eol, seol, stchr, mystch, mypadc, padch;
+
+extern char *cmarg, *cmarg2, *dftty;
+
+extern char tmpbuf[], *tp, *lp;                /* Temporary buffer & pointers */
+#ifndef NOFRILLS
+extern char optbuf[];                  /* Buffer for MAIL or PRINT options */
+extern int rprintf;                    /* REMOTE PRINT flag */
+#endif /* NOFRILLS */
+extern char ttname[];
+
+extern struct keytab onoff[], filtab[], fttab[], rltab[];
+extern int nrlt;
+
+#ifdef DCMDBUF
+extern char *atxbuf;                   /* Atom buffer */
+extern char *cmdbuf;                   /* Command buffer */
+extern char *line;                     /* Character buffer for anything */
+#ifdef CK_CURSES
+/* This needs cleaning up... */
+#ifdef UNIX
+extern char *trmbuf;                   /* Termcap buffer */
+#endif /* UNIX */
+#ifdef OS2
+extern char *trmbuf;                   /* Termcap buffer */
+#endif /* OS2 */
+#ifdef OSK
+extern char *trmbuf;                   /* Termcap buffer */
+#endif /* OSK */
+#ifdef AMIGA
+extern char *trmbuf;                   /* Termcap buffer */
+#endif /* AMIGA */
+#endif /* CK_CURSES */
+#else
+extern char atxbuf[];                  /* Atom buffer */
+extern char cmdbuf[];                  /* Command buffer */
+extern char line[];                    /* Character buffer for anything */
+#ifdef CK_CURSES
+#ifdef UNIX
+extern char trmbuf[];                  /* Termcap buffer */
+#endif /* UNIX */
+#endif /* CK_CURSES */
+#endif /* DCMDBUF */
+
+#ifndef NOCSETS
+extern struct keytab fcstab[];         /* For 'set file character-set' */
+extern struct keytab ttcstab[];
+extern int nfilc, fcharset, ntermc, tcsr, tcsl;
+#endif /* NOCSETS */
+
+#ifndef NOSPL
+extern int cmdlvl;                     /* Overall command level */
+#endif /* NOSPL */
+
+#ifdef TNCODE
+extern int tn_init;
+#endif /* TNCODE */
+
+#ifdef SUNX25
+extern int revcall, closgr, cudata, nx25, npadx3;
+extern char udata[MAXCUDATA];
+extern CHAR padparms[MAXPADPARMS+1];
+extern struct keytab x25tab[], padx3tab[];
+#endif /* SUNX25 */
+
+#ifdef CK_CURSES
+#ifndef VMS
+_PROTOTYP(int tgetent,(char *, char *));
+#endif /* VMS */
+#endif /* CK_CURSES */
+
+#ifndef NODIAL
+extern int dialhng, dialtmo, dialksp, dialdpy, dialmnp, dialmhu;
+extern int mdmspd;
+extern char *dialini, *dialdir, *dialcmd, *dialnpr;
+extern FILE * dialfd;
+
+
+struct keytab dialtab[] = {
+    "dial-command", XYDDIA, 0,
+    "directory", XYDDIR, 0,
+    "display", XYDDPY, 0,
+    "hangup",  XYDHUP, 0,
+    "init-string", XYDINI, 0,
+    "kermit-spoof", XYDKSP, 0,
+    "mnp-enable", XYDMNP, 0,
+#ifdef MDMHUP
+    "modem-hangup", XYDMHU, 0,
+#endif /* MDMHUP */
+    "prefix", XYDNPR, 0,
+    "speed-matching", XYDSPD, 0,
+    "timeout", XYDTMO, 0
+};
+int ndial = (sizeof(dialtab) / sizeof(struct keytab));
+#endif /* NODIAL */
+
+#ifndef NOXMIT
+/* set transmit */
+#define XMITF 0
+#define XMITL 1
+#define XMITP 2
+#define XMITE 3
+#define XMITX 4
+#define XMITS 5
+#define XMITW 6
+
+#ifndef NOXMIT
+#define XMBUFL 50
+extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
+char xmitbuf[XMBUFL+1] = { NUL };      /* TRANSMIT eof string */
+#endif /* NOXMIT */
+
+struct keytab xmitab[] = {
+    "echo",     XMITX, 0,
+    "eof",      XMITE, 0,
+    "fill",     XMITF, 0,
+    "linefeed", XMITL, 0,
+    "locking-shift", XMITS, 0,
+    "pause",    XMITW, 0,
+    "prompt",   XMITP, 0
+};
+int nxmit = (sizeof(xmitab) / sizeof(struct keytab));
+#endif /* NOXMIT */
+
+/* For SET FILE COLLISION */
+/* Some of the following may be possible for some C-Kermit implementations */
+/* but not others.  Those that are not possible for your implementation */
+/* should be ifdef'd out. */
+
+struct keytab colxtab[] = { /* SET FILE COLLISION options */
+    "append",    XYFX_A, 0,  /* append to old file */
+#ifdef COMMENT
+    "ask",       XYFX_Q, 0,  /* ask what to do (not implemented) */
+#endif
+    "backup",    XYFX_B, 0,  /* rename old file */
+    "discard",   XYFX_D, 0,  /* don't accept new file */
+    "no-supersede", XYFX_D, CM_INV, /* ditto (MSK compatibility) */
+    "overwrite", XYFX_X, 0,  /* overwrite the old file == file warning off */
+    "rename",    XYFX_R, 0,  /* rename the incoming file == file warning on */
+    "update",    XYFX_U, 0,  /* replace if newer */
+};
+int ncolx = (sizeof(colxtab) / sizeof(struct keytab));
+
+static struct keytab rfiltab[] = {     /* for REMOTE SET FILE */
+    "collision",     XYFILX, 0,
+    "record-length", XYFILR, 0,
+    "type",          XYFILT, 0
+};
+int nrfilp = (sizeof(rfiltab) / sizeof(struct keytab));
+
+struct keytab fntab[] = {              /* File naming */
+    "converted", 1, 0,
+    "literal",   0, 0
+};
+
+/* Terminal parameters table */
+struct keytab trmtab[] = {
+#ifdef OS2
+    "arrow-keys",    XYTARR, 0,
+#endif /* OS2 */
+    "bytesize",      XYTBYT, 0,
+#ifndef NOCSETS
+    "character-set", XYTCS,  0,
+#endif /* NOCSETS */
+#ifdef OS2
+    "color",         XYTCOL, 0,
+#endif /* OS2 */
+    "cr-display",    XYTCRD, 0,
+#ifdef OS2
+    "cursor",        XYTCUR, 0,
+#endif /* OS2 */
+    "echo",          XYTEC,  0,
+#ifdef OS2
+    "keypad-mode",   XYTKPD, 0,
+#endif /* OS2 */
+    "locking-shift", XYTSO,  0,
+    "newline-mode",  XYTNL,  0
+#ifdef OS2
+,   "type",          XYTTYP, 0,
+    "wrap",          XYTWRP, 0
+#endif /* OS2 */
+};
+int ntrm = (sizeof(trmtab) / sizeof(struct keytab));
+
+struct keytab crdtab[] = {             /* Carriage-return display */
+    "crlf",        1, 0,
+    "normal",      0, 0
+};
+extern int tt_crd;                     /* Carriage-return display variable */
+
+#ifdef OS2
+/*
+  OS/2 serial communication devices.
+*/
+struct keytab os2devtab[] = {
+    "1",    1, CM_INV,                 /* Invisible synonyms, like */
+    "2",    2, CM_INV,                 /* "set port 1" */
+    "3",    3, CM_INV,
+    "4",    4, CM_INV,
+    "5",    5, CM_INV,
+    "6",    6, CM_INV,
+    "7",    7, CM_INV,
+    "8",    8, CM_INV,
+    "com1", 1, 0,                      /* Real device names */
+    "com2", 2, 0,
+    "com3", 3, 0,
+    "com4", 4, 0,
+    "com5", 5, 0,
+    "com6", 6, 0,
+    "com7", 7, 0,
+    "com8", 7, 0
+};
+int nos2dev = (sizeof(os2devtab) / sizeof(struct keytab));
+
+/*
+  Terminal parameters that can be set by SET commands.
+  Used by the ck?con.c terminal emulator code.  
+  For now, only use for OS/2.  Should add these for Macintosh.
+*/
+int tt_arrow = 1;                      /* Arrow key mode */
+int tt_keypad = 0;                     /* Keypad mode */
+int tt_wrap = 1;                       /* Autowrap */
+int tt_type = TT_VT102;                        /* Terminal type */
+int tt_cursor = 0;                     /* Cursor type */
+#endif /* OS2 */
+
+#ifdef OS2
+struct keytab akmtab[] = {             /* Arrow key mode */
+    "application", 1, 0,
+    "cursor",      0, 0
+};
+struct keytab kpmtab[] = {             /* Keypad mode */
+    "application", 0, 0,
+    "numeric",     1, 0
+};
+
+struct keytab ttycoltab[] = {          /* Items to be colored */
+    "help",        4, 0,               /* Help screen */
+    "normal",      0, 0,               /* Normal screen text */
+    "reverse",     1, 0,               /* Reverse video */
+    "status",      3, 0,               /* Status line */
+    "underlined",  2, 0                        /* Underlined text */
+};
+int ncolors = 5;
+
+struct keytab ttyclrtab[] = {          /* Colors */
+    "black",       0, 0,
+    "blue",        1, 0,
+    "brown",       6, 0,
+    "cyan",        3, 0,
+    "dgray",       8, 0,
+    "green",       2, 0,
+    "lblue",       9, 0,
+    "lcyan",      11, 0,
+    "lgray",       7, 0,
+    "lgreen",     10, 0,
+    "lmagenta",   13, 0,
+    "lred",       12, 0,
+    "magenta",     5, 0,
+    "red",         4, 0,
+    "white",      15, 0,
+    "yellow",     14, 0
+};
+int nclrs = 16;
+
+struct keytab ttycurtab[] = {
+    "full",        2, 0,
+    "half",        1, 0,
+    "underline",   0, 0
+};
+int ncursors = 3;
+#endif /* OS2 */
+
+#ifdef OS2
+struct keytab ttyptab[] = {
+#ifdef COMMENT
+/*
+  Not supported yet...
+  The idea is to let the console driver handle the escape sequences.
+*/
+    "none",    TT_NONE,  0,
+#endif /* COMMENT */
+#ifdef OS2PM
+    "tek4014", TT_TEK40, 0,
+#endif /* OS2PM */
+    "vt102",   TT_VT102, 0,
+    "vt52",    TT_VT52,  0
+};
+int nttyp = 2;
+#endif /* OS2 */
+
+/* #ifdef VMS */
+struct keytab fbtab[] = {              /* Binary record types for VMS */
+    "fixed",     XYFT_B, 0,            /* Fixed is normal for binary */
+    "undefined", XYFT_U, 0             /* Undefined if they ask for it */
+};
+int nfbtyp = (sizeof(fbtab) / sizeof(struct keytab));
+/* #endif */
+
+#ifdef VMS
+struct keytab lbltab[] = {             /* Labeled File info */
+    "acl",         LBL_ACL, 0,
+    "backup-date", LBL_BCK, 0,
+    "name",        LBL_NAM, 0,
+    "owner",       LBL_OWN, 0,
+    "path",        LBL_PTH, 0
+};
+int nlblp = (sizeof(lbltab) / sizeof(struct keytab));
+#endif /* VMS */
+
+struct keytab fdtab[] = {              /* SET FILE DISPLAY options */
+#ifdef MAC                             /* Macintosh */
+    "fullscreen", XYFD_R, 0,           /* Full-screen but not curses */
+    "none",   XYFD_N, 0,
+    "off",    XYFD_N, CM_INV,
+    "on",     XYFD_R, CM_INV,
+    "quiet",  XYFD_N, CM_INV
+
+#else                                  /* Not Mac */
+    "crt", XYFD_S, 0,                  /* CRT display */
+#ifdef CK_CURSES
+#ifdef COMMENT
+    "curses",     XYFD_C, CM_INV,      /* Full-screen, curses */
+#endif /* COMMENT */
+    "fullscreen", XYFD_C, 0,           /* Full-screen, whatever the method */
+#endif /* CK_CURSES */
+    "none",   XYFD_N, 0,               /* No display */
+    "off",    XYFD_N, CM_INV,          /* Ditto */
+    "on",     XYFD_R, CM_INV,          /* On = Serial */
+    "quiet",  XYFD_N, CM_INV,          /* No display */
+    "serial", XYFD_R, 0                        /* Serial */
+#endif /* MAC */
+};
+int nfdtab = (sizeof(fdtab) / sizeof(struct keytab));
+
+struct keytab rsrtab[] = {             /* For REMOTE SET RECEIVE */
+    "packet-length", XYLEN, 0,
+    "timeout", XYTIMO, 0
+};
+int nrsrtab = (sizeof(rsrtab) / sizeof(struct keytab));
+
+/* Send/Receive Parameters */
+struct keytab srtab[] = {
+    "end-of-packet", XYEOL, 0,
+    "packet-length", XYLEN, 0,
+    "pad-character", XYPADC, 0,
+    "padding", XYNPAD, 0,
+    "start-of-packet", XYMARK, 0,
+    "timeout", XYTIMO, 0
+};
+int nsrtab = (sizeof(srtab) / sizeof(struct keytab));
+
+/* REMOTE SET */
+
+struct keytab rmstab[] = {
+    "attributes",  XYATTR, 0,
+    "block-check", XYCHKT, 0,
+    "file",        XYFILE, 0,
+    "incomplete",  XYIFD,  0,
+    "receive",     XYRECV, 0,
+    "retry",       XYRETR, 0,
+    "server",      XYSERV, 0,
+    "transfer",    XYXFER, 0,
+    "window",      XYWIND, 0
+};
+int nrms = (sizeof(rmstab) / sizeof(struct keytab));
+
+struct keytab attrtab[] = {
+    "all",           AT_XALL, 0,
+#ifdef COMMENT
+    "blocksize",     AT_BLKS, 0,       /* not used */
+#endif /* COMMENT */
+    "character-set", AT_ENCO, 0,
+    "date",          AT_DATE, 0,
+    "disposition",   AT_DISP, 0,
+    "encoding",      AT_ENCO, CM_INV,
+    "length",        AT_LENK, 0,
+    "off",           AT_ALLN, 0,
+    "on",            AT_ALLY, 0,
+#ifdef COMMENT
+    "os-specific",   AT_SYSP, 0,       /* not used by UNIX or VMS */
+#endif /* COMMENT */
+    "system-id",     AT_SYSI, 0,
+    "type",          AT_FTYP, 0,
+};
+int natr = (sizeof(attrtab) / sizeof(struct keytab)); /* how many attributes */
+
+#ifndef NOSPL
+extern int indef, intime, incase, inecho, insilence;
+struct keytab inptab [] = {            /* SET INPUT parameters */
+    "case",            IN_CAS, 0,
+    "default-timeout", IN_DEF, CM_INV,
+    "echo",            IN_ECH, 0,
+    "silence",         IN_SIL, 0,
+    "timeout-action",  IN_TIM, 0
+};
+int ninp = (sizeof(inptab) / sizeof(struct keytab));
+
+struct keytab intimt[] = {             /* SET INPUT TIMEOUT parameters */
+    "proceed", 0, 0,                   /* 0 = proceed */
+    "quit",    1, 0                    /* 1 = quit */
+};
+
+struct keytab incast[] = {             /* SET INPUT CASE parameters */
+    "ignore",  0, 0,                   /* 0 = ignore */
+    "observe", 1, 0                    /* 1 = observe */
+};
+#endif /* NOSPL */
+\f
+/* The following routines broken out of doprm() to give compilers a break. */
+
+/*  S E T O N  --  Parse on/off (default on), set parameter to result  */
+int
+seton(prm) int *prm; {
+    int x, y;
+    if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
+    if ((x = cmcfm()) < 0) return(x);
+    *prm = y;
+    return(1);
+}
+/*  S E T N U M  --  Set parameter to result of cmnum() parse.  */
+/*
+ Call with pointer to integer variable to be set,
+   x = number from cnum parse, y = return code from cmnum,
+   max = maximum value to accept, -1 if no maximum.
+ Returns -9 on failure, after printing a message, or 1 on success.
+*/
+int
+setnum(prm,x,y,max) int x, y, *prm, max; {
+    extern int cmflgs;
+    debug(F101,"setnum","",y);
+    if (y == -3) {
+       printf("\n?Value required\n");
+       return(-9);
+    }
+    if (y == -2) {
+       printf("%s?Not a number: %s\n",cmflgs == 1 ? "" : "\n", atxbuf);
+       return(-9);
+    }
+    if (y < 0) return(y);
+    if (max > -1 && x > max) {
+       printf("?Sorry, %d is the maximum\n",max);
+       return(-9);
+    }
+    if ((y = cmcfm()) < 0) return(y);
+    *prm = x;
+    return(1);
+}
+/*  S E T C C  --  Set parameter to an ASCII control character value.  */
+int
+setcc(prm,x,y) int x, y, *prm; {
+    if (y == -3) {
+       printf("\n?Value required\n");
+       return(-3);
+    }
+    if (y < 0) return(y);
+    if ((x > 037) && (x != 0177)) {
+       printf("\n?Not in ASCII control range - %d\n",x);
+       return(-2);
+    }
+    if ((y = cmcfm()) < 0) return(y);
+    *prm = x;
+    return(1);
+}
+
+#ifndef NODIAL
+_PROTOTYP(static int dialstr,(char **, char *));
+/*
+  Parse a DIAL-related string, stripping enclosing braces, if any.
+*/
+static int
+dialstr(p,msg) char **p; char *msg; {
+    int x;
+    if ((x = cmtxt(msg, "", &s, xxstring)) < 0)
+      return(x);
+    if (*s == '{') {                   /* Strip enclosing braces, if any */
+       x = strlen(s);
+       if (s[x-1] == '}') {
+           s[x-1] = NUL;
+           s++;
+       }
+    }
+    if (*p) {                          /* Free any previous string. */
+       free(*p);
+       *p = (char *) 0;
+    }  
+    if ((x = strlen(s)) > 0) {
+       *p = malloc(x + 1);             /* Allocate space for it */
+       strcpy(*p,s);                   /* and make a safe copy. */
+    } else *p = (char *) 0;
+    return(success = 1);
+}
+
+int                                    /* Set DIAL command options */
+setdial() {
+    if ((y = cmkey(dialtab,ndial,"","",xxstring)) < 0) return(y);
+    switch (y) {
+      case XYDHUP:                     /* DIAL HANGUP */
+       return(success = seton(&dialhng));
+      case XYDINI:                     /* DIAL INIT-STRING */
+       return(dialstr(&dialini,"Modem dialer initialization string"));
+      case XYDNPR:                     /* DIAL NUMBER-PREFIX */
+       return(dialstr(&dialnpr,"Modem dialer telephone number prefix"));
+      case XYDDIA:                     /* DIAL DIAL-COMMAND */
+       x = cmtxt("Dialing command for modem,\n\
+ include \"%s\" to stand for phone number,\n\
+ for example, \"set dial dial-command ATDT%s\\13\"",
+                 "",
+                 &s,
+                 xxstring);
+       if (x < 0 && x != -3)           /* Handle parse errors */
+         return(x);
+       y = x = strlen(s);              /* Get length of text */
+       if (x > 0 && *s == '{') {       /* Strip enclosing braces, */
+           if (s[x-1] == '}') {        /* if any. */
+               s[x-1] = NUL;
+               s++;
+               y -= 2;
+           }
+       }
+       if (y > 0) {                    /* If there is any text (left), */
+           for (x = 0; x < y; x++) {   /* make sure they included "%s" */
+               if (s[x] != '%') continue;
+               if (s[x+1] == 's') break;
+           }
+           if (x == y) {
+               printf(
+"?Dial-command must contain \"%cs\" for phone number.\n",'%');
+               return(-9);
+           }
+       }
+       if (dialcmd) {                  /* Free any previous string. */
+           free(dialcmd);
+           dialcmd = (char *) 0;
+       }       
+       if (y > 0) {
+           dialcmd = malloc(y + 1);    /* Allocate space for it */
+           strcpy(dialcmd,s);          /* and make a safe copy. */
+       }
+       return(success = 1);
+      case XYDKSP:                     /* DIAL KERMIT-SPOOF */
+       return(success = seton(&dialksp));
+      case XYDTMO:                     /* DIAL TIMEOUT */
+       y = cmnum("Seconds to wait for call completion","0",10,&x,xxstring);
+       return(success = setnum(&dialtmo,x,y,10000));
+      case XYDDPY:                     /* DIAL DISPLAY */
+       return(success = seton(&dialdpy));
+      case XYDSPD:                     /* DIAL SPEED-MATCHING */
+                                       /* used to be speed-changing */
+       if ((y = seton(&mdmspd)) < 0) return(y);
+#ifdef COMMENT
+       mdmspd = 1 - mdmspd;            /* so here we reverse the meaning */
+#endif /* COMMENT */
+       return(success = 1);
+      case XYDMNP:                     /* DIAL MNP-ENABLE */
+       return(success = seton(&dialmnp));
+#ifdef MDMHUP
+      case XYDMHU:                     /* DIAL MODEM-HANGUP */
+       return(success = seton(&dialmhu));
+#endif /* MDMHUP */
+      case XYDDIR:                     /* DIAL DIRECTORY */
+       if ((y = cmifi("Name of dialing directory file","",&s,&y,
+                      xxstring)) < 0) {
+           if (y == -3) {
+               if (dialdir) free(dialdir);     /* Free any previous storage */
+               dialdir = NULL;
+               return(success = 1);
+           } else return(y);
+       }
+       if (y) {
+           printf("?Wildcards not allowed\n");
+           return(-9);
+       }
+       strcpy(line,s);                 /* Make safe copy of dial string */
+       if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
+       if (dialdir) free(dialdir);     /* Free previous filename storage */
+       if (dialfd) {                   /* Close previous file, if any */
+           fclose(dialfd);
+           dialfd = NULL;
+       }
+       s = line;                       /* Point back to dial string */
+       if (s == NULL || *s == NUL) {   /* If no name given */
+           dialdir = NULL;             /* remove the name string */
+           return(success = 1);
+       } else if ((dialdir = malloc(strlen(s)+1)) == NULL) {
+           return(success = 0);        /* Can't malloc storage for name */
+       } else {                        /* Have storage for name */
+           strcpy(dialdir,s);          /* Copy string into new storage */
+           if ((dialfd = fopen(dialdir,"r")) == NULL) { /* Open the file */
+               perror(dialdir);        /* Can't, print message saying why */
+               success = 0;            /* We didn't succeed */
+               return(-9);             /* Fail, message already printed */
+           }
+           return(success = 1);        /* Everything is OK */
+       }
+
+      default:
+       printf("?Unexpected SET DIAL parameter\n");
+       return(-2);
+    }
+}
+#endif /* NODIAL */
+
+int
+setfil(rmsflg) int rmsflg; {
+    if (rmsflg) {
+       if ((y = cmkey(rfiltab,nrfilp,"Remote file parameter","",
+                      xxstring)) < 0) {
+           if (y == -3) {
+               printf("?Remote file parameter required\n");
+               return(-9);
+           } else return(y);
+       }
+    } else {
+       if ((y = cmkey(filtab,nfilp,"File parameter","",xxstring)) < 0)
+         return(y);
+    }
+    switch (y) {
+#ifdef COMMENT                         /* Not needed */
+      case XYFILB:                     /* Blocksize */
+       sprintf(tmpbuf,"%d",DBLKSIZ);
+       if ((y = cmnum("file block size",tmpbuf,10,&z,xxstring)) < 0)
+         return(y);
+       if ((x = cmcfm()) < 0) return(x);
+       if (rmsflg) {
+           sprintf(tmpbuf,"%d",z);
+           sstate = setgen('S', "311", tmpbuf, "");
+           return((int) sstate);
+       } else {
+           fblksiz = z;
+           return(success = 1);
+       }
+#endif /* COMMENT */
+
+      case XYFILS:                     /* Byte size */
+       if ((y = cmnum("file byte size (7 or 8)","8",10,&z,xxstring)) < 0)
+         return(y);
+       if (z != 7 && z != 8) {
+           printf("\n?The choices are 7 and 8\n");
+           return(0);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       if (z == 7) fmask = 0177;
+       else if (z == 8) fmask = 0377;
+       return(success = 1);
+
+#ifndef NOCSETS
+      case XYFILC:                     /* Character set */
+       if ((x = cmkey(fcstab,nfilc,"local file code","ascii", xxstring)) < 0)
+         return(x);
+       if ((z = cmcfm()) < 0) return(z);
+       fcharset = x;
+       return(success = 1);
+#endif /* NOCSETS */
+
+      case XYFILD:                     /* Display */
+       if ((x = cmkey(fdtab,nfdtab,"file transfer display style","",
+                      xxstring)) < 0)
+         return(x);
+       if ((z = cmcfm()) < 0) return(z);
+#ifdef CK_CURSES
+       if (x == XYFD_C) {
+#ifdef VMS
+           lp = line;
+#else
+           lp = trmbuf;
+#endif /* VMS */
+#ifndef MYCURSES
+           s = getenv("TERM");
+           if (tgetent(lp,s) < 1) {
+#ifdef VMS
+               printf("Sorry, terminal type not supported: %s\n",s);
+#else
+               printf("Sorry, terminal type unknown: %s\n",s);
+#endif /* VMS */
+               return(success = 0);
+           }
+#endif /* MYCURSES */
+           line[0] = '\0';
+       }
+#endif /* CK_CURSES */
+       fdispla = x;                    /* It's OK. */
+       return(success = 1);
+
+      case XYFILN:                     /* Names */
+       if ((x = cmkey(fntab,2,"how to handle filenames","converted",
+                      xxstring)) < 0)
+         return(x);
+       if ((z = cmcfm()) < 0) return(z);
+       fncnv = x;
+       return(success = 1);
+
+      case XYFILR:                     /* Record length */
+       sprintf(tmpbuf,"%d",DLRECL);
+       if ((y = cmnum("file record length",tmpbuf,10,&z,xxstring)) < 0)
+         return(y);
+       if ((x = cmcfm()) < 0) return(x);
+       if (rmsflg) {
+           sprintf(tmpbuf,"%d",z);
+           sstate = setgen('S', "312", tmpbuf, "");
+           return((int) sstate);
+       } else {
+           frecl = z;
+           return(success = 1);
+       }
+
+#ifdef COMMENT
+      case XYFILO:                     /* Organization */
+       if ((x = cmkey(forgtab,nforg,"file organization","sequential",
+                      xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       if (rmsflg) {
+           sprintf(tmpbuf,"%d",x);
+           sstate = setgen('S', "314", tmpbuf, "");
+           return((int) sstate);
+       } else {
+           forg = x;
+           return(success = 1);
+       }       
+#endif /* COMMENT */
+
+#ifdef COMMENT                         /* Not needed */
+      case XYFILF:                     /* Format */
+       if ((x = cmkey(frectab,nfrec,"file record format","stream",
+                      xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       if (rmsflg) {
+           sprintf(tmpbuf,"%d",x);
+           sstate = setgen('S', "313", tmpbuf, "");
+           return((int) sstate);
+       } else {
+           frecfm = x;
+           return(success = 1);
+       }
+#endif /* COMMENT */
+
+#ifdef COMMENT
+      case XYFILP:                     /* Printer carriage control */
+       if ((x = cmkey(fcctab,nfcc,"file carriage control","newline",
+                      xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       if (rmsflg) {
+           sprintf(tmpbuf,"%d",x);
+           sstate = setgen('S', "315", tmpbuf, "");
+           return((int) sstate);
+       } else {
+           fcctrl = x;
+           return(success = 1);
+       }       
+#endif /* COMMENT */
+
+      case XYFILT:                     /* Type */
+       if ((x = cmkey(fttab,nfttyp,"type of file","text",xxstring)) < 0)
+         return(x);
+#ifdef COMMENT
+       if ((y = cmnum("file byte size (7 or 8)","8",10,&z,xxstring)) < 0)
+         return(y);
+       if (z != 7 && z != 8) {
+           printf("\n?The choices are 7 and 8\n");
+           return(0);
+       }
+#endif /* COMMENT */
+
+#ifdef VMS
+        /* Allow VMS users to choose record format for binary files */
+        if ((x == XYFT_B) && (rmsflg == 0)) {
+           if ((x = cmkey(fbtab,nfbtyp,"VMS record format","fixed",
+                          xxstring)) < 0)
+             return(x);
+       }
+#endif /* VMS */
+       if ((y = cmcfm()) < 0) return(y);
+       if (rmsflg) {
+           sstate = setgen('S', "300", x ? "1" : "0", "");
+           return((int) sstate);
+       } else {
+           binary = x;
+#ifdef COMMENT
+           if (z == 7) fmask = 0177;
+           else if (z == 8) fmask = 0377;
+#endif /* COMMENT */
+           return(success = 1);
+       }
+
+      case XYFILX:                     /* Collision Action */
+       if ((x = cmkey(colxtab,ncolx,"Filename collision action","backup",
+                      xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       fncact = x;
+       if (rmsflg) {
+           sprintf(tmpbuf,"%d",fncact);
+           sstate = setgen('S', "302", tmpbuf, "");
+           return((int) sstate);
+       } else {
+           if (fncact == XYFX_R) warn = 1; /* SET FILE WARNING implications */
+           if (fncact == XYFX_X) warn = 0; /* ... */
+           return(success = 1);
+       }
+
+      case XYFILW:                     /* Warning/Write-Protect */
+       seton(&warn);
+       if (warn)
+         fncact = XYFX_R;
+       else
+         fncact = XYFX_X;
+       return(success = 1);
+
+#ifdef VMS
+      case XYFILL:                     /* LABELED FILE parameters */
+       if ((x = cmkey(lbltab,nlblp,"VMS labeled file feature","",
+                      xxstring)) < 0)
+         return(x);
+       if ((success = seton(&y)) < 0)
+         return(success);
+       if (y)                          /* Set or reset the selected bit */
+         lf_opts |= x;                 /* in the options bitmask. */
+       else
+         lf_opts &= ~x;
+       return(success);
+#endif /* VMS */
+
+      case XYFILI:                     /* INCOMPLETE */
+       return(doprm(XYIFD,rmsflg));
+
+      default:
+       printf("?unexpected file parameter\n");
+       return(-2);
+    }
+}
+
+int
+settrm() {
+    if ((y = cmkey(trmtab,ntrm,"","",xxstring)) < 0) return(y);
+#ifdef MAC
+    printf("\n?Sorry, not implemented yet.  Please use the Settings menu.\n");
+    return(-9);
+#else
+    switch (y) {
+      case XYTBYT:                     /* SET TERMINAL BYTESIZE */
+       if ((y = cmnum("bytesize for terminal connection","8",10,&x,
+                      xxstring)) < 0)
+         return(y);
+       if (x != 7 && x != 8) {
+           printf("\n?The choices are 7 and 8\n");
+           return(success = 0);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       if (x == 7) cmask = 0177;
+       else if (x == 8) cmask = 0377;
+        return(success = 1);
+
+      case XYTSO:                      /* SET TERMINAL LOCKING-SHIFT */
+       return(success = seton(&sosi));
+
+      case XYTNL:                      /* SET TERMINAL NEWLINE-MODE */
+       return(success = seton(&tnlm)); 
+
+#ifdef OS2
+      case XYTCOL:                     /* SET TERMINAL COLOR */
+       if ((x = cmkey(ttycoltab,ncolors,"","normal",xxstring)) < 0) {
+           return(x);
+        } else {
+           extern int colornormal, colorreverse, colorunderline,
+             colorstatus, colorhelp, scrninitialised;
+           int fg, bg;
+           if ((fg = cmkey(ttyclrtab,nclrs,
+                           "foreground color","black",xxstring)) < 0)
+             return(fg);
+           if ((bg = cmkey(ttyclrtab,nclrs,
+                           "background color","cyan",xxstring)) < 0)
+             return(bg);
+           if ((y = cmcfm()) < 0)
+             return(y);
+           switch (x) {
+             case 0:
+               colornormal = fg | bg << 4;
+               break;
+             case 1:
+               colorreverse = fg | bg << 4;
+               break;
+             case 2:
+               colorunderline = fg | bg << 4;
+               break;
+             case 3:
+               colorstatus = fg | bg << 4;
+               break;
+             case 4:
+               colorhelp = fg | bg << 4;
+               break;
+             default:
+               printf("%s - invalid\n",cmdbuf);
+               return(-9);
+               break;
+           }
+           scrninitialised = 0;
+        }
+       return(success = 1);
+
+      case XYTCUR:                     /* SET TERMINAL CURSOR */
+       if ((x = cmkey(ttycurtab,ncursors,"","underline",xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0) return(y);
+        tt_cursor = x;
+       return(success = 1);
+
+      case XYTTYP:                     /* SET TERMINAL TYPE */
+       if ((x = cmkey(ttyptab,nttyp,"","vt102",xxstring)) < 0) return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       tt_type = x;
+       return(success = 1);
+
+      case XYTARR:                     /* SET TERMINAL ARROW-KEYS */
+       if ((x = cmkey(akmtab,2,"","",xxstring)) < 0) return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       tt_arrow = x;                   /* 0 = application, 1 = cursor */
+       return(success = 1);
+
+      case XYTKPD:                     /* SET TERMINAL KEYPAD-MODE */
+       if ((x = cmkey(kpmtab,2,"","",xxstring)) < 0) return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       tt_keypad = x;                  /* 0 = application, 1 = numeric */
+       return(success = 1);
+
+      case XYTWRP:                     /* SET TERMINAL WRAP */
+       seton(&tt_wrap);
+       return(success = 1);    
+#endif /* OS2 */
+
+#ifndef NOCSETS
+      case XYTCS:                      /* SET TERMINAL CHARACTER-SET */
+       /* set terminal character-set <remote> <local> */
+       if ((x = cmkey(ttcstab,ntermc,
+                      "remote terminal character-set","",xxstring)) < 0) 
+         return(x);
+       if (x == FC_TRANSP) {           /* TRANSPARENT? */
+           if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
+           tcsr = tcsl = FC_USASCII;   /* Make them both the same */
+           return(success = 1);
+       }
+
+/* Not transparent, so get local set to translate it into */
+
+       s = "";                         /* Make current file char set */
+       for (y = 0; y <= nfilc; y++)    /* be the default... */
+         if (fcstab[y].kwval == fcharset) {
+             s = fcstab[y].kwd;
+             break;
+           }
+       if ((y = cmkey(fcstab,nfilc,
+                      "local character-set",s,xxstring)) < 0)
+         return(y);
+       if ((z = cmcfm()) < 0) return(z); /* Confirm the command */
+       tcsr = x;                       /* Remote character set */
+       tcsl = y;                       /* Local character set */
+       return(success = 1);
+#endif /* NOCSETS */
+
+      case XYTEC:                      /* SET TERMINAL ECHO */
+       if ((x = cmkey(rltab,nrlt,"which side echos during CONNECT",
+                      "remote", xxstring)) < 0) return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       duplex = x;
+       return(success = 1); 
+
+      case XYTCRD:                     /* SET TERMINAL CR-DISPLAY */
+       if ((x = cmkey(crdtab,2,"", "normal", xxstring)) < 0) return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       tt_crd = x;
+       return(success = 1); 
+
+      default:                         /* Shouldn't get here. */
+       return(-2);
+    }    
+#endif /* MAC */
+}
+
+int                                    /* SET SEND/RECEIVE */
+setsr(xx, rmsflg) int xx; int rmsflg; {
+    if (xx == XYRECV)
+       strcpy(line,"Parameter for inbound packets");
+    else
+       strcpy(line,"Parameter for outbound packets");
+    if (rmsflg) {
+       if ((y = cmkey(rsrtab,nrsrtab,line,"",xxstring)) < 0) {
+           if (y == -3) {
+               printf("?Remote receive parameter required\n");
+               return(-9);
+           } else return(y);
+       }
+    } else {
+       if ((y = cmkey(srtab,nsrtab,line,"",xxstring)) < 0) return(y);
+    }
+    switch (y) {
+      case XYEOL:
+       y = cmnum("Decimal ASCII code for packet terminator","13",10,&x,
+                 xxstring);
+       if ((y = setcc(&z,x,y)) < 0) return(y);
+       if (xx == XYRECV) eol = z; else seol = z;
+       return(success = y);
+      case XYLEN:
+       y = cmnum("Maximum number of characters in a packet","90",10,&x,
+                 xxstring);
+       if (xx == XYRECV) {             /* Receive... */
+           if ((y = setnum(&z,x,y,maxrps)) < 0)
+             return(y);
+           if (z < 10) {
+               printf("Sorry, 10 is the minimum\n");
+               return(-9);
+           }
+           if (rmsflg) {
+               tp = tmpbuf;
+               sprintf(tp,"%d",z);
+               sstate = setgen('S', "401", tp, "");
+               return((int) sstate);
+           } else {
+               if (z > MAXRP) z = MAXRP;
+               y = adjpkl(z,wslotr,bigrbsiz);
+               if (y != z) {
+                   urpsiz = y;
+                   if (
+#ifndef NOSPL
+                       cmdlvl == 0
+#else
+                       tlevel < 0
+#endif /* NOSPL */
+                       )
+                     if (msgflg) printf(
+" Adjusting receive packet-length to %d for %d window slots\n",
+                        y, wslotr);
+               }
+               urpsiz = y;
+               rpsiz =  (y > 94) ? 94 : y;
+           }
+       } else {                        /* Send... */
+           if ((y = setnum(&z,x,y,maxsps)) < 0)
+             return(y);
+           if (z < 10) {
+               printf("Sorry, 10 is the minimum\n");
+               return(-9);
+           }
+           if (z > MAXSP) z = MAXSP;
+           spsiz = z;                  /* Set it */
+           y = adjpkl(spsiz,wslotr,bigsbsiz);
+           if (y != spsiz &&
+#ifndef NOSPL
+               cmdlvl == 0
+#else
+               tlevel < 0
+#endif /* NOSPL */
+               )
+             if (msgflg)
+               printf("Adjusting packet size to %d for %d window slots\n",
+                    y,wslotr);
+           spsiz = spmax = spsizr = y; /* Set it and flag that it was set */
+           spsizf = 1;                 /* to allow overriding Send-Init. */
+       }
+       if (pflag &&
+#ifndef NOSPL
+           cmdlvl == 0
+#else
+           tlevel < 0
+#endif /* NOSPL */
+           ) {
+           if (z > 94 && msgflg) {
+               printf("Extended-length packets requested.\n");
+               if (bctr < 2 && z > 200) printf("\
+Remember to SET BLOCK 2 or 3 for long packets.\n");
+           }
+           if (speed <= 0L) speed = ttgspd();
+#ifdef COMMENT
+/*
+  Kermit does this now itself.
+*/
+           if (speed <= 0L && z > 200 && msgflg) {
+               printf("\
+Make sure your timeout interval is long enough for %d-byte packets.\n",z);
+           }
+#endif /* COMMENT */
+       }
+       return(success = y);
+
+      case XYMARK:
+       y = cmnum("Code for packet-start character","1",10,&x,xxstring);
+#ifdef UNIX
+/*
+  Printable start-of-packet works for UNIX and VMS only!
+*/
+       if ((y = setnum(&z,x,y,126)) < 0) return(y);
+#else
+#ifdef VMS
+       if ((y = setnum(&z,x,y,126)) < 0) return(y);
+#else
+       if ((y = setcc(&z,x,y)) < 0) return(y);
+#endif /* VMS */
+#endif /* UNIX */
+       if (xx == XYRECV) stchr = z; else mystch = z;
+       return(success = y);
+
+
+      case XYNPAD:                     /* PADDING */
+       y = cmnum("How many padding characters for inbound packets","0",10,&x,
+                 xxstring);
+       if ((y = setnum(&z,x,y,94)) < 0) return(y);
+       if (xx == XYRECV) mypadn = z; else npad = z;
+       return(success = y);
+      case XYPADC:                     /* PAD-CHARACTER */
+       y = cmnum("Decimal ASCII code for packet padding character","0",10,&x,
+                 xxstring);
+       if ((y = setcc(&z,x,y)) < 0) return(y);
+       if (xx == XYRECV) mypadc = z; else padch = z;
+       return(success = y);
+      case XYTIMO:                     /* TIMEOUT */
+       if (xx == XYRECV) {
+           char buf[16];               /* Construct default */
+           sprintf(buf,"%d",URTIME);
+           y = cmnum("Packet timeout interval",buf,10,&x,xxstring);
+           if ((y = setnum(&z,x,y,94)) < 0) return(y);
+
+           if (rmsflg) {               /* REMOTE SET RECEIVE TIMEOUT */
+               tp = tmpbuf;            /*   Tell Kermit server what */
+               sprintf(tp,"%d",z);     /*   timeout to ask me to use. */
+               sstate = setgen('S', "402", tp, "");
+               return((int) sstate);
+           } else {                    /* SET RECEIVE TIMEOUT */
+               pkttim = z;             /*   Value to put in my negotiation */
+           }                           /*   packet for other Kermit to use */
+
+       } else {                        /* SET SEND TIMEOUT */
+           y = cmnum("Packet timeout interval","",10,&x,xxstring);
+           if (y == -3) {              /* They cancelled a previous */
+               x = DMYTIM;             /* SET SEND command, so restore */
+               y = 0;                  /* the default */
+               timef = 0;              /* and turn off the override flag */
+           } else {                    /* They gave a number */
+               timef = 1;              /* so turn on the override flag */
+           }
+           if ((y = setnum(&z,x,y,94)) < 0)
+             return(y);
+           timint = rtimo = z;         /* Override value for me to use */
+       }
+       return(success = 1);
+
+      default:
+       return(-2);
+    }                                  /* End of SET SEND/RECEIVE... */
+}
+
+#ifndef NOXMIT
+int
+setxmit() {
+    if ((y = cmkey(xmitab,nxmit,"","",xxstring)) < 0) return(y);
+    switch (y) {
+      case XMITE:                      /* EOF */
+       y = cmtxt("Characters to send at end of file,\n\
+ Use backslash codes for control characters","",&s,xxstring);
+       if (y < 0) return(y);
+       if ((int)strlen(s) > XMBUFL) {
+           printf("?Too many characters, %d maximum\n",XMBUFL);
+           return(-2);
+       }
+       strcpy(xmitbuf,s);
+       return(success = 1);
+
+      case XMITF:                      /* Fill */
+       y = cmnum("Numeric code for blank-line fill character","0",10,&x,
+                 xxstring);
+       if ((y = setnum(&z,x,y,127)) < 0) return(y);
+       xmitf = z;
+       return(success = 1);
+      case XMITL:                      /* Linefeed */
+        return(success = seton(&xmitl));
+      case XMITS:                      /* Locking-Shift */
+        return(success = seton(&xmits));
+      case XMITP:                      /* Prompt */
+       y = cmnum("Numeric code for host's prompt character, 0 for none",
+                 "10",10,&x,xxstring);
+       if ((y = setnum(&z,x,y,127)) < 0) return(y);
+       xmitp = z;
+       return(success = 1);
+      case XMITX:                      /* Echo */
+        return(success = seton(&xmitx));
+      case XMITW:                      /* Pause */
+       y = cmnum("Number of milliseconds to pause between binary characters\n\
+or text lines during transmission","0",10,&x,xxstring);
+       if ((y = setnum(&z,x,y,1000)) < 0) return(y);
+       xmitw = z;
+       return(success = 1);
+      default:
+       return(-2);
+    }
+}
+#endif /* NOXMIT */
+\f
+/*  D O R M T  --  Do a remote command  */
+#ifdef ATTSV
+#ifndef aegis
+#ifndef datageneral
+#define CK_NEED_SIG
+#endif /* datageneral */
+#endif /* aegis */
+#endif /* ATTSV */
+
+VOID rmsg() {
+    if (pflag)
+      printf(
+#ifdef CK_NEEDSIG
+
+       " Type your escape character, %s, followed by X or E to cancel.\n",
+       dbchr(escape)
+#else
+       " Press the X or E key to cancel.\n"
+#endif /* CK_NEEDSIG */
+      );
+}
+
+int
+dormt(xx) int xx; {
+    int x, y, retcode;
+    char *s, sbuf[50], *s2;
+
+    if (xx < 0) return(xx);
+
+    if (xx == XZSET) {                 /* REMOTE SET */
+       if ((y = cmkey(rmstab,nrms,"","",xxstring)) < 0) {
+           if (y == -3) {
+               printf("?Parameter name required\n");
+               return(-9);
+           } else return(y);
+       }
+       return(doprm(y,1));
+    }
+
+    switch (xx) {                      /* Others... */
+case XZCWD:                            /* CWD */
+    if ((x = cmtxt("Remote directory name","",&s,xxstring)) < 0) return(x);
+    debug(F111,"XZCWD: ",s,x);
+    *sbuf = NUL;
+    s2 = sbuf;
+
+/* The following is commented out, because there is practically no */
+/* computer in the world that requires a password for directory changing. */
+/* (The DEC-20 was the only one, and they're mostly all gone.) */
+#ifdef DIRPWDPR
+    if (*s != NUL) {                   /* If directory name given, */
+                                       /* get password on separate line. */
+        if (tlevel > -1) {             /* From take file... */
+           if (fgets(sbuf,50,tfile[tlevel]) == NULL)
+               fatal("take file ends prematurely in 'remote cwd'");
+           debug(F110," pswd from take file",s2,0);
+           for (x = (int)strlen(sbuf);
+                x > 0 && (sbuf[x-1] == NL || sbuf[x-1] == CR);
+                x--)
+               sbuf[x-1] = '\0';
+        } else {                       /* From terminal... */
+           printf(" Password: ");              /* get a password */
+#ifdef OS2
+           while (((x = isatty(0) ? coninc(0) :
+                    getchar()) != NL) && (x != CR)) {     /* with no echo */
+#else
+           while (((x = getchar()) != NL) && (x != CR)) { /* with no echo */
+#endif /* OS2 */
+               if ((x &= 0177) == '?') {
+                   printf("? Password of remote directory\n Password: ");
+                   s2 = sbuf;
+                   *sbuf = NUL;
+               }
+               else if (x == ESC)      /* Mini command line editor... */
+                   putchar(BEL);
+               else if (x == BS || x == 0177)
+                   s2--;
+               else if (x == 025) {    /* Ctrl-U */
+                   s2 = sbuf;
+                   *sbuf = NUL;
+               }
+               else
+                   *s2++ = x;
+            }
+           *s2 = NUL;
+           putchar('\n');
+        }
+        s2 = sbuf;
+    } else s2 = "";
+#endif /* DIRPWDPR */
+
+    debug(F110," password",s2,0);
+    sstate = setgen('C',s,s2,"");
+    retcode = 0;
+    break;
+
+case XZDEL:                            /* Delete */
+    if ((x = cmtxt("Name of remote file(s) to delete","",&s,xxstring)) < 0) {
+       if (x == -3) {
+           printf("?Name of remote file(s) required\n");
+           return(-9);
+       } else return(x);
+    }
+    if (local) ttflui();               /* If local, flush tty input buffer */
+    retcode = sstate = rfilop(s,'E');
+    break;
+case XZDIR:                            /* Directory */
+    if ((x = cmtxt("Remote directory or file specification","",&s,
+                  xxstring)) < 0)
+       return(x);
+    if (local) ttflui();               /* If local, flush tty input buffer */
+    rmsg();
+    retcode = sstate = setgen('D',s,"","");
+    break;
+case XZHLP:                            /* Help */
+    if ((x = cmcfm()) < 0) return(x);
+    sstate = setgen('H',"","","");
+    retcode = 0;
+    break; 
+
+#ifndef NOPUSH
+case XZHOS:                            /* Host */
+    if ((x = cmtxt("Command for remote system","",&cmarg,xxstring)) < 0)
+      return(x);
+    if ((int)strlen(cmarg) < 1)  {
+       if (x == -3) {
+           printf("?Remote host command required\n");
+           return(-9);
+       } else return(x);
+    }
+    rmsg();
+    retcode = sstate = 'c';
+    break; 
+#endif /* NOPUSH */
+
+#ifndef NOFRILLS
+case XZKER:
+    if ((x = cmtxt("Command for remote Kermit","",&cmarg,xxstring)) < 0)
+      return(x);
+    if ((int)strlen(cmarg) < 1)  {
+       if (x == -3) {
+           printf("?Remote Kermit command required\n");
+           return(-9);
+       } else return(x);
+    }
+    retcode = sstate = 'k';
+    rmsg();
+    break; 
+
+case XZLGI: {                          /* Login */
+    char *p1, *p2, *p3;
+    if ((x = cmfld("User ID","",&s,xxstring)) < 0) return(x);
+    if ((p1 = malloc((int)strlen(s) + 1)) == NULL) {
+       printf("Internal error: malloc\n");
+       return(-2);
+    } else strcpy(p1,s);
+    if ((x = cmfld("Password","",&s,xxstring)) < 0) return(x);
+    if ((p2 = malloc((int)strlen(s) + 1)) == NULL) {
+       printf("Internal error: malloc\n");
+       return(-2);
+    } else strcpy(p2,s);
+    if ((x = cmtxt("Account or carriage return","",
+                  &s,xxstring)) < 0 && x != -3)
+       return(x);
+    if ((p3 = malloc((int)strlen(s) + 1)) == NULL) {
+       printf("Internal error: malloc\n");
+       return(-2);
+    } else strcpy(p3,s);
+    sstate = setgen('I',p1,p2,p3);
+    if (p3) free(p3);
+    if (p2) free(p2);
+    if (p1) free(p1);
+    retcode = 0;
+    break; 
+}
+
+case XZLGO:                            /* Logout */
+    if ((x = cmcfm()) < 0) return(x);
+    sstate = setgen('I',"","","");
+    retcode = 0;
+    break; 
+
+case XZPRI:                            /* Print */
+    if (!atdiso || !atcapr) {          /* Disposition attribute off? */
+       printf("?Disposition Attribute is Off\n");
+       return(-2);
+    }
+    cmarg = "";
+    cmarg2 = "";
+    if ((x = cmifi("Local file(s) to print on remote printer","",&s,&y,
+                  xxstring)) < 0) {
+       if (x == -3) {
+           printf("?Name of local file(s) required\n");
+           return(-9);
+       }
+       return(x);
+    }
+    strcpy(line,s);                    /* Make a safe copy of filename */
+    *optbuf = NUL;                     /* Wipe out any old options */
+    if ((x = cmtxt("Options for remote print command","",&s,xxstring)) < 0)
+      return(x);
+    strcpy(optbuf,s);                  /* Make a safe copy of options */
+    if ((int)strlen(optbuf) > 94) {    /* Make sure this is legal */
+       printf("?Option string too long\n");
+       return(-9);
+    }
+    nfils = -1;                                /* Expand file list internally */
+    cmarg = line;                      /* Point to file list. */
+    rprintf = 1;                       /* REMOTE PRINT modifier for SEND */
+    sstate = 's';                      /* Set start state to SEND */
+    if (local) displa = 1;
+    retcode = 0;
+    break;
+#endif /* NOFRILLS */
+       
+case XZSPA:                            /* Space */
+    if ((x = cmtxt("Confirm, or remote directory name","",&s,xxstring)) < 0)
+      return(x);
+    retcode = sstate = setgen('U',s,"","");
+    break;
+    
+#ifndef NOFRILLS
+case XZTYP:                            /* Type */
+    if ((x = cmtxt("Remote file specification","",&s,xxstring)) < 0)
+      return(x);
+    if ((int)strlen(s) < 1) {
+       printf("?Remote filename required\n");
+        return(-9);    
+    }
+    rmsg();
+    retcode = sstate = rfilop(s,'T');
+    break;
+#endif /* NOFRILLS */
+#ifndef NOFRILLS
+case XZWHO:
+    if ((x = cmtxt("Remote user name, or carriage return","",&s,xxstring)) < 0)
+       return(x);
+    retcode = sstate = setgen('W',s,"","");
+    break;
+#endif /* NOFRILLS */
+default:
+        if ((x = cmcfm()) < 0) return(x);
+        printf("?Not implemented - %s\n",cmdbuf);
+        return(-2);
+    }
+    if (local) ttflui();               /* If local, flush tty input buffer */
+    return(retcode);
+}
+/*  R F I L O P  --  Remote File Operation  */
+CHAR
+#ifdef CK_ANSIC
+rfilop(char * s, char t)
+#else
+rfilop(s,t) char *s, t; 
+#endif /* CK_ANSIC */
+/* rfilop */ {
+    if (*s == NUL) {
+       printf("?File specification required\n");
+       return((CHAR) 0);
+    }
+    debug(F111,"rfilop",s,t);
+    return(setgen(t,s,"",""));
+}
+
+#ifdef SUNX25
+int
+setx25() {
+    if ((y = cmkey(x25tab,nx25,"X.25 call options","",xxstring)) < 0)
+      return(y);
+    switch (y) {
+      case XYUDAT:
+       if ((z = cmkey(onoff,2,"X.25 call user data","",xxstring))
+           < 0) return(z);
+       if (z == 0) {
+           if ((z = cmcfm()) < 0) return(z);
+           cudata = 0;             /* disable call user data */
+           return (success = 1);
+       }
+       if ((x = cmtxt("X.25 call user data string","",&s,xxstring)) < 0)
+         return(x);
+       if ((int)strlen(s) == 0) {
+           return (-3);
+       } else if ((int)strlen(s) > MAXCUDATA) {
+           printf("?The length must be > 0 and <= %d\n",MAXCUDATA);
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       strcpy(udata,s);
+       cudata = 1;                     /* X.25 call user data specified */
+       return (success = 1);
+      case XYCLOS:
+       if ((z = cmkey(onoff,2,"X.25 closed user group call","",xxstring))
+           < 0) return(z);
+       if (z == 0) {
+           if ((z = cmcfm()) < 0) return(z);
+           closgr = -1;                /* disable closed user group */
+           return (success = 1);
+       }
+       if ((y = cmnum("0 <= cug index >= 99","",10,&x,xxstring)) < 0)
+         return(y);
+       if (x < 0 || x > 99) {
+           printf("?The choices are 0 <= cug index >= 99\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       closgr = x;                     /* closed user group selected */
+       return (success = 1);
+
+      case XYREVC:
+       if((z = cmkey(onoff,2,"X.25 reverse charge call","",xxstring)) < 0)
+         return(z);
+       if ((x = cmcfm()) < 0) return(x);
+       revcall = z;
+       return (success = 1);
+    }
+}
+
+int
+setpadp() {
+    if ((y = cmkey(padx3tab,npadx3,"PAD X.3 parameter name","",xxstring)) < 0)
+      return(y);
+    x = y;
+    switch (x) {
+      case PAD_BREAK_CHARACTER:
+       if ((y = cmnum("PAD break character value","",10,&z,xxstring)) < 0)
+         return(y);
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+      case PAD_ESCAPE:
+       if ((y = cmnum("PAD escape","",10,&z,xxstring)) < 0) return(y);
+       if (z != 0 && z != 1) {
+           printf("?The choices are 0 or 1\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+      case PAD_ECHO:
+       if ((y = cmnum("PAD echo","",10,&z,xxstring)) < 0) return(y);
+       if (z != 0 && z != 1) {
+           printf("?The choices are 0 or 1\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+      case PAD_DATA_FORWARD_CHAR:
+       if ((y = cmnum("PAD data forward char","",10,&z,xxstring)) < 0)
+         return(y);
+       if (z != 0 && z != 2) {
+           printf("?The choices are 0 or 2\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+      case PAD_DATA_FORWARD_TIMEOUT:
+       if ((y = cmnum("PAD data forward timeout","",10,&z,xxstring)) < 0)
+           return(y);
+       if (z < 0 || z > 255) {
+           printf("?The choices are 0 or 1 <= timeout <= 255\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+      case PAD_FLOW_CONTROL_BY_PAD:
+       if ((y = cmnum("PAD pad flow control","",10,&z,xxstring)) < 0)
+         return(y);
+       if (z != 0 && z != 1) {
+           printf("?The choices are 0 or 1\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+      case PAD_SUPPRESSION_OF_SIGNALS:
+       if ((y = cmnum("PAD service","",10,&z,xxstring)) < 0) return(y);
+       if (z != 0 && z != 1) {
+           printf("?The choices are 0 or 1\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_BREAK_ACTION:
+       if ((y = cmnum("PAD break action","",10,&z,xxstring)) < 0) return(y);
+       if (z != 0 && z != 1 && z != 2 && z != 5 && z != 8 && z != 21) {
+           printf("?The choices are 0, 1, 2, 5, 8 or 21\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_SUPPRESSION_OF_DATA:
+       if ((y = cmnum("PAD data delivery","",10,&z,xxstring)) < 0) return(y);
+       if (z != 0 && z != 1) {
+           printf("?The choices are 0 or 1\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_PADDING_AFTER_CR:
+       if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
+       if (z < 0 || z > 7) {
+           printf("?The choices are 0 or 1 <= crpad <= 7\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_LINE_FOLDING:
+       if ((y = cmnum("PAD linefold","",10,&z,xxstring)) < 0) return(y);
+       if (z < 0 || z > 255) {
+           printf("?The choices are 0 or 1 <= linefold <= 255\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_LINE_SPEED:
+       if ((y = cmnum("PAD baudrate","",10,&z,xxstring)) < 0) return(y);
+       if (z < 0 || z > 18) {
+           printf("?The choices are 0 <= baudrate <= 18\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_FLOW_CONTROL_BY_USER:
+       if ((y = cmnum("PAD terminal flow control","",10,&z,xxstring)) < 0)
+           return(y);
+       if (z != 0 && z != 1) {
+           printf("?The choices are 0 or 1\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_LF_AFTER_CR:
+       if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
+       if (z < 0 || z == 3 || z > 7) {
+           printf("?The choices are 0, 1, 2, 4, 5, 6 or 7\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_PADDING_AFTER_LF:
+       if ((y = cmnum("PAD lfpad","",10,&z,xxstring)) < 0) return(y);
+       if (z < 0 || z > 7) {
+           printf("?The choices are 0 or 1 <= lfpad <= 7\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_EDITING:
+       if ((y = cmnum("PAD edit control","",10,&z,xxstring)) < 0) return(y);
+       if (z != 0 && z != 1) {
+           printf("?The choices are 0 or 1\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_CHAR_DELETE_CHAR:
+       if ((y = cmnum("PAD char delete char","",10,&z,xxstring)) < 0)
+           return(y);
+       if (z < 0 || z > 127) {
+           printf("?The choices are 0 or 1 <= chardelete <= 127\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_BUFFER_DELETE_CHAR:
+       if ((y = cmnum("PAD buffer delete char","",10,&z,xxstring)) < 0)
+           return(y);
+       if (z < 0 || z > 127) {
+           printf("?The choices are 0 or 1 <= bufferdelte <= 127\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+
+      case PAD_BUFFER_DISPLAY_CHAR:
+       if ((y = cmnum("PAD display line char","",10,&z,xxstring)) < 0)
+           return(y);
+       if (z < 0 || z > 127) {
+           printf("?The choices are 0 or 1 <= displayline <= 127\n");
+           return(-2);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       break;
+    }
+    padparms[x] = z;
+    return(success = 1);
+}
+#endif /* SUNX25 */ 
+
+int
+setat(rmsflg) int rmsflg; {
+    int xx;
+    if ((y = cmkey(attrtab,natr,"File Attribute packets","",xxstring)) < 0)
+      return(y);    
+    if (y == AT_XALL) {                        /* ATTRIBUTES ALL ON or ALL OFF */
+       if ((z = seton(&xx)) < 0) return(z);
+       if (rmsflg) {
+           printf("Sorry, command not available\n");
+           return(-9);
+       } else {
+           atenci = xx;                /* Encoding in */
+           atenco = xx;                /* Encoding out */
+           atdati = xx;                /* Date in */
+           atdato = xx;                /* Date out */
+           atdisi = xx;                /* Disposition in/out */
+           atdiso = xx;
+           atleni = xx;                /* Length in/out (both kinds) */
+           atleno = xx;
+           atblki = xx;                /* Blocksize in/out */
+           atblko = xx;
+           attypi = xx;                /* File type in/out */
+           attypo = xx;
+           atsidi = xx;                /* System ID in/out */
+           atsido = xx;
+           atsysi = xx;                /* System-dependent params in/out */
+           atsyso = xx;
+       }
+       return(z);
+    } else if (y == AT_ALLY || y == AT_ALLN) { /* ATTRIBUTES ON or OFF */
+       if ((x = cmcfm()) < 0) return(x);
+       atcapr = (y == AT_ALLY) ? 1 : 0;
+       if (rmsflg) {
+           sstate = setgen('S', "132", atcapr ? "1" : "0", "");
+           return((int) sstate);
+       } else return(success = 1);
+    }
+    /* Otherwise, it's an individual attribute that wants turning off/on */
+
+    if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
+    if ((x = cmcfm()) < 0) return(x);
+
+/* There are better ways to do this... */
+/* The real problem is that we're not separating the in and out cases */
+/* and so we have to arbitrarily pick the "in" case, i.e tell the remote */
+/* server to ignore incoming attributes of the specified type, rather */
+/* than telling it not to send them.  The protocol does not (yet) define */
+/* codes for "in-and-out-at-the-same-time". */
+
+    switch(y) {
+      case AT_DISP:
+       if (rmsflg) {
+           sstate = setgen('S', "142", z ? "1" : "0", "");
+           return((int) sstate);
+       }
+       atdisi = atdiso = z; break;
+      case AT_ENCO:
+       if (rmsflg) {
+           sstate = setgen('S', "141", z ? "1" : "0", "");
+           return((int) sstate);
+       }
+       atenci = atenco = z; break;
+      case AT_DATE:
+       if (rmsflg) {
+           sstate = setgen('S', "135", z ? "1" : "0", "");
+           return((int) sstate);
+       }
+       atdati = atdato = z; break;
+      case AT_LENB:
+      case AT_LENK:
+       if (rmsflg) {
+           sstate = setgen('S', "133", z ? "1" : "0", "");
+           return((int) sstate);
+       }
+       atleni = atleno = z; break;
+      case AT_BLKS:
+       if (rmsflg) {
+           sstate = setgen('S', "139", z ? "1" : "0", "");
+           return((int) sstate);
+       }
+       atblki = atblko = z; break;
+      case AT_FTYP:
+       if (rmsflg) {
+           sstate = setgen('S', "134", z ? "1" : "0", "");
+           return((int) sstate);
+       }
+       attypi = attypo = z; break;
+      case AT_SYSI:
+       if (rmsflg) {
+           sstate = setgen('S', "145", z ? "1" : "0", "");
+           return((int) sstate);
+       }
+       atsidi = atsido = z; break;
+      case AT_SYSP:
+       if (rmsflg) {
+           sstate = setgen('S', "147", z ? "1" : "0", "");
+           return((int) sstate);
+       }
+       atsysi = atsyso = z; break;
+      default:
+       printf("?Not available\n");
+       return(-2);
+    }
+    return(1);
+}
+
+#ifndef NOSPL
+int
+setinp() {
+    if ((y = cmkey(inptab,ninp,"","",xxstring)) < 0) return(y);
+    switch (y) {
+      case IN_DEF:                     /* SET INPUT DEFAULT-TIMEOUT */
+       z = cmnum("Positive number","",10,&x,xxstring);
+       return(success = setnum(&indef,x,z,94));
+      case IN_TIM:                     /* SET INPUT TIMEOUT-ACTION */
+       if ((z = cmkey(intimt,2,"","",xxstring)) < 0) return(z);
+       if ((x = cmcfm()) < 0) return(x);
+       intime = z;
+       return(success = 1);
+      case IN_CAS:                     /* SET INPUT CASE */
+       if ((z = cmkey(incast,2,"","",xxstring)) < 0) return(z);
+       if ((x = cmcfm()) < 0) return(x);
+       incase = z;
+       return(success = 1);
+      case IN_ECH:                     /* SET INPUT ECHO */
+       return(success = seton(&inecho));
+      case IN_SIL:                     /* SET INPUT SILENCE */
+       z = cmnum("Positive number","",10,&x,xxstring);
+       return(success = setnum(&insilence,x,z,-1));
+    }
+    return(0);
+}
+#endif /* NOSPL */
+
+/*
+  setlin -- parse name of and then open a communication device.
+  Call with:
+    xx == XXLINE for a serial (tty) line, XXHOST for a network host,
+    zz == 0 means if user doesn't give a device name, continue current
+            active connection (if any);
+    zz != 0 means if user doesn't give a device name, then close the
+            current connection and restore the default communication device.
+*/
+int
+setlin(xx, zz) int xx, zz; {
+    if (xx == XYHOST) {                        /* SET HOST <hostname> */
+#ifndef NETCONN
+        printf("?Network connections not supported\n");
+       return(-9);
+#else
+       if (
+           (nettype != NET_DEC) &&
+           (nettype != NET_SX25) &&
+            (nettype != NET_TCPB)) {
+           printf("?Network type not supported\n");
+           return(-9);
+         }
+       if (nettype != NET_TCPB) {      /* Not a TCP/IP connection */
+                                       /* Just get a text string */
+           if ((x = cmtxt( zz ? 
+   "Network host name,\n or carriage return to close an open connection" :
+   "Network host name,\n or carriage return to resume an open connection",
+                          "",&s,xxstring)) < 0)
+             return(x);
+
+       } else {                        /* TCP/IP connection... */
+
+           /* Parse for host and service separately. */
+
+           if ((x = cmfld( zz ?
+   "IP host name or number,\n or carriage return to close an open connection" :
+   "IP host name or number,\n or carriage return to resume an open connection",
+                          "",&s,xxstring)) < 0) {
+               if (x != -3)            /* Parse error */
+                 return(x);            /* return it */
+               else if (!zz)           /* No hostname given */
+                 return(1);            /* and none required, */
+           }                           /* continue current connection. */
+           if (*s) {                   /* If they gave a host name... */
+               strcpy(line,s);         /* make a copy */
+               /* Check for "host:service" */
+               for ( ; (*s != '\0') && (*s != ':'); s++) ;
+
+               /* If no service given, let them type one now. */
+
+               if (!*s) {
+                   if ((x = cmfld(
+    "TCP service name or number,\n or carriage return for telnet (23)",
+                                  "23",&s,xxstring)) < 0 && x != -3)
+                     return(x);
+                   if (*s) {           /* If they gave a service, */
+                       strcat(line,":"); /* concatenate it to the hostname */
+                       strcat(line,s); /* separated by a colon, because */
+                   }                   /* this is how ttopen() wants it. */
+               }
+               if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
+               s = line;
+           }
+       }
+
+       /* New connection wanted. */
+
+       ttflui();                       /* Clear away buffered up junk */
+       ttclos(0);                      /* Close old connection, if any */
+       if (oldplex > -1)               /* Restore duplex setting. */
+         duplex = oldplex;
+       if (*s) {                       /* They gave a hostname */
+           x = 1;                      /* Network connection always local */
+           mdmsav = mdmtyp;            /* Remember old modem type */
+           mdmtyp = -nettype;          /* Special code for network */
+           if (nettype == NET_TCPB) {  /* For TCP/IP telnet connections */
+               oldplex = duplex;       /* Remember previous duplex */
+               duplex = 0;             /* Set full duplex and let */
+         }                             /* negotiations change if necessary. */
+       } else {                        /* They just said "set host" */
+           if (network && msgflg)
+             printf(" Closing connection\n");
+           s = dftty;                  /* So go back to normal */
+           x = dfloc;                  /* default tty, location, */
+           network = 0;                /* No more network connection. */
+           duplex = oldplex;           /* Restore old duplex setting. */
+           if (mdmtyp < 0) {           /* Switching from net to async? */
+               if (mdmsav > -1)        /* Restore modem type from last */
+                 mdmtyp = mdmsav;      /* SET MODEM command, if any. */
+               else
+                 mdmtyp = 0;
+           }
+       }
+#endif /* NETCONN */
+    }
+
+/* Serial tty device, possibly modem, connection... */
+
+    if (xx == XYLINE) {                        /* SET LINE */
+#ifdef OS2                             /* or SET PORT */
+       if ((x = cmkey(os2devtab,nos2dev,"serial communication device name",
+                      "com1", xxstring)) < 0) {
+           debug(F101,"OS2 SET PORT x","",x);
+           if (x != -9) return(x);
+           s = atxbuf;                 /* Doesn't match keyword */
+           if (*s == '_') s++;         /* Secret notation for file handle */
+           else return(-9);
+       } else if (x >= 1 && x <= 8) {  /* Regular COM port */
+           s = os2devtab[x+7].kwd;     /* Use its real name */
+       } else s = atxbuf;              /* Something else, believe it */
+#else
+       if ((x = cmtxt("Communication device name",dftty,&s,xxstring)) < 0)
+         return(x);
+#endif /* OS2 */
+
+       if (local) ttflui();            /* Clear away buffered up junk */
+       ttclos(0);                      /* Close old line, if any was open */
+       if (*s) {                       /* They gave a device name */
+           x = -1;                     /* Let ttopen decide about it */
+       } else {                        /* They just said "set line" */
+           s = dftty;                  /* so go back to normal tty */
+           x = dfloc;                  /* and mode. */
+       }
+       if (mdmtyp < 0) {               /* Switching from net to async? */
+           if (mdmsav > -1)            /* Restore modem type from last */
+             mdmtyp = mdmsav;          /* SET MODEM command, if any. */
+           else
+             mdmtyp = 0;
+           mdmsav = -1;
+       }
+       if (oldplex > -1) {             /* Restore previous duplex setting. */
+           duplex = oldplex;
+           oldplex = -1;
+       }
+       network = 0;                    /* No more network. */
+    }
+#ifdef COMMENT
+/*
+  The following is removed, not so much because it's a horrible hack, but
+  because it only works if the SET FLOW command was given *before* the SET
+  LINE command, whereas normally these commands can be given in any order.
+*/
+#ifdef NEXT
+/*
+  This is a horrible hack, but it's nice for users.  On the NeXT, you select
+  RTS/CTS hardware flow control not by system calls, but by referring to the
+  device with a different name.  If the user has asked for RTS/CTS flow
+  control on a NeXT, but used the non-RTS/CTS device name in the SET LINE
+  command, we make the appropriate substitute here.  I wonder how much bigger
+  this section of code will grow as the years go by... 
+*/
+    if ((flow == FLO_RTSC) &&          /* RTS/CTS flow control selected */
+       strcmp(s,dftty)) {              /*  ...on external port? */
+       y = strlen(s);                  /* Yes, insert "f" as next-to-last */
+       if (s[y-2] != 'f') {            /* character in device name if not */
+           strcpy(line,s);             /* already there... */
+           line[y] = line[y-1];        /* So /dev/cua => /dev/cufa, etc. */
+           line[y-1] = 'f';
+           line[y+1] = '\0';
+           s = line;
+       }
+    }
+#endif /* NEXT */
+#endif /* COMMENT */
+
+    if ((y = ttopen(s,&x,mdmtyp,cdtimo)) < 0 ) { /* Open the new line */
+       if (y == -2) {
+           printf("?Timed out, no carrier.\n");
+           printf("Try SET CARRIER OFF and SET LINE again, or else\n");
+           printf("SET MODEM, SET LINE, and then DIAL.\n");
+       } else if (y == -3) {
+           printf("Sorry, access to lock denied: %s\n",s);
+       } else if (y == -4) {
+           printf("Sorry, access to device denied: %s\n",s);
+       } else if (y == -5) {
+#ifdef VMS
+           printf("Sorry, device is in use or otherwise unavailable: %s\n",s);
+#else
+           printf("Sorry, device is in use: %s\n",s);
+#endif /* VMS */
+        } else {                       /* Other error. */
+#ifndef VMS
+           if (errno) {
+               tp = tmpbuf;
+               sprintf(tp,"Sorry, can't open connection: %s",s);
+               perror(tp);
+           } else
+#endif /* VMS */
+             printf("Sorry, can't open connection: %s\n",s);
+       }    
+       local = dfloc;                  /* Go back to normal */
+#ifndef MAC
+       strcpy(ttname,dftty);           /* Restore default tty name */
+#endif /* MAC */
+       speed = ttgspd();
+       network = 0;                    /* No network connection active */
+       return(success = 0);            /* Return failure */
+    }
+    if (x > -1) local = x;             /* Opened ok, set local/remote. */
+    network = (mdmtyp < 0);            /* Remember connection type. */
+#ifdef TNCODE
+    if (network) tn_init = 0;          /* Say telnet not init'd yet. */
+#endif /* TNCODE */
+    strcpy(ttname,s);                  /* Copy name into real place. */
+    speed = ttgspd();                  /* Get the current speed. */
+    debug(F111,"set line ",ttname,local);
+#ifdef NETCONN
+#ifdef SUNX25
+    if (nettype == NET_SX25) duplex = 1; /* Duplex half */
+#endif /* SUNX25 */
+#endif /* NETCONN */
+    return(success = 1);
+}
+#endif /* NOICP */
diff --git a/usr/src/contrib/kermit-5A.188/ckuusr.c b/usr/src/contrib/kermit-5A.188/ckuusr.c
new file mode 100644 (file)
index 0000000..1fc7650
--- /dev/null
@@ -0,0 +1,2032 @@
+char *userv = "User Interface 5A(092), 23 Nov 92";
+
+/*  C K U U S R --  "User Interface" for Unix Kermit (Part 1)  */
+
+/*
+  Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
+  Columbia University Center for Computing Activities.
+  First released January 1985.
+  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
+  York.  Permission is granted to any individual or institution to use this
+  software as long as it is not sold for profit.  This copyright notice must be
+  retained.  This software may not be included in commercial products without
+  written permission of Columbia University.
+*/
+
+/*
+  NOTE: Because of the massive additions in functionality, and therefore
+  the increase in the number of commands, much code was moved from here to
+  the two new modules, ckuus4.c and ckuus5.c.  This module now contains only
+  the top-level command keyword table, the SET command keyword table, and
+  the top-level interactive command parser/dispatcher.  ckuus3.c contains the
+  rest of the SET and REMOTE command parsers; ckuus2.c contains the help
+  command parser and help text strings, and ckuus4.c and ckuus5.c contain
+  miscellaneous pieces that logically belong in the ckuusr.c file but had to
+  be moved because of size problems with some C compilers / linkers.
+  Later...  as the other modules became too large, a ckuus6.c was created.
+  Still later...  ckuus7.c.
+  Also: ckuusy.c contains the UNIX-style command-line interface;
+  ckuusx.c contains routines needed by both the command-line interface and
+  the interactive command parser.
+*/
+
+/*
+ The ckuus*.c modules depend on the existence of C library features like fopen,
+ fgets, feof, (f)printf, argv/argc, etc.  Other functions that are likely to
+ vary among Unix implementations -- like setting terminal modes or interrupts
+ -- are invoked via calls to functions that are defined in the system-
+ dependent modules, ck?[ft]io.c.  The command line parser processes any
+ arguments found on the command line, as passed to main() via argv/argc.  The
+ interactive parser uses the facilities of the cmd package (developed for this
+ program, but usable by any program).  Any command parser may be substituted
+ for this one.  The only requirements for the Kermit command parser are these:
+
+1. Set parameters via global variables like duplex, speed, ttname, etc.  See
+   ckmain.c for the declarations and descriptions of these variables.
+
+2. If a command can be executed without the use of Kermit protocol, then
+   execute the command directly and set the variable sstate to 0. Examples
+   include 'set' commands, local directory listings, the 'connect' command.
+
+3. If a command requires the Kermit protocol, set the following variables:
+
+    sstate                             string data
+      'x' (enter server mode)            (none)
+      'r' (send a 'get' command)         cmarg, cmarg2
+      'v' (enter receive mode)           cmarg2
+      'g' (send a generic command)       cmarg
+      's' (send files)                   nfils, cmarg & cmarg2 OR cmlist
+      'c' (send a remote host command)   cmarg
+
+    cmlist is an array of pointers to strings.
+    cmarg, cmarg2 are pointers to strings.
+    nfils is an integer.
+
+    cmarg can be a filename string (possibly wild), or
+       a pointer to a prefabricated generic command string, or
+       a pointer to a host command string.
+    cmarg2 is the name to send a single file under, or
+       the name under which to store an incoming file; must not be wild.
+       If it's the name for receiving, a null value means to store the
+       file under the name it arrives with.
+    cmlist is a list of nonwild filenames, such as passed via argv.
+    nfils is an integer, interpreted as follows:
+      -1: filespec (possibly wild) in cmarg, must be expanded internally.
+       0: send from stdin (standard input).
+      >0: number of files to send, from cmlist.
+
+ The screen() function is used to update the screen during file transfer.
+ The tlog() function writes to a transaction log.
+ The debug() function writes to a debugging log.
+ The intmsg() and chkint() functions provide the user i/o for interrupting
+   file transfers.
+*/
+
+#ifndef NOICP
+/* Includes */
+#include "ckcdeb.h"
+#include "ckcasc.h"
+#include "ckcker.h"
+#include "ckuusr.h"
+#include "ckcxla.h"
+#include "ckcnet.h"                    /* Network symbols */
+#ifdef datageneral
+#include <packets:common.h>
+#define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
+#endif /* datageneral */
+
+/* External Kermit Variables, see ckmain.c for description. */
+extern int size, local, sndsrc, xitsta, server, displa, binary, msgflg, 
+  escape, duplex, nfils, quiet, tlevel, pflag, zincnt, atcapr, atdiso, verwho;
+extern long vernum;
+extern char *versio;
+extern char *ckxsys, *cmarg, *cmarg2, **cmlist;
+#ifndef NOHELP
+extern char *introtxt[];
+#endif /* NOHELP */
+extern char *PWDCMD, *WHOCMD, *TYPCMD;
+extern char ttname[];
+#ifndef NOFRILLS
+extern int rmailf;                     /* MAIL command items */
+extern char optbuf[];
+#endif /* NOFRILLS */
+extern CHAR sstate;
+
+#ifdef NETCONN
+extern int network;                    /* Have active network connection */
+#endif /* NETCONN */
+
+#ifndef NOMSEND                                /* Multiple SEND */
+extern char *msfiles[];
+#endif /* NOMSEND */
+extern char fspec[];                   /* Most recent filespec */
+
+#ifndef NOCSETS
+extern int nfilc;
+extern struct keytab fcstab[];
+#endif /* NOCSETS */
+
+int rcflag = 0;                                /* Pointer to home directory string */
+int repars,                            /* Reparse needed */
+    techo = 0,                         /* Take echo */
+    terror = 0;                                /* Take error action, 1 = quit */
+#ifndef NOSCRIPT
+int secho = 1;
+#endif /* NOSCRIPT */
+
+#ifndef NOXMIT
+/* Variables for TRANSMIT command */
+
+int xmitx = 1;                 /* Whether to echo during TRANSMIT */
+int xmitf = 0;                 /* Character to fill empty lines */
+int xmitl = 0;                 /* 0 = Don't send linefeed too */
+int xmitp = LF;                        /* Host line prompt */
+int xmits = 0;                 /* Use shift-in/shift-out, 0 = no */
+int xmitw = 0;                 /* Milliseconds to pause during TRANSMIT */
+#endif /* NOXMIT */
+
+/* Declarations from ck?fio.c module */
+extern char *SPACMD, *SPACM2;          /* SPACE commands */
+/* Command-oriented items */
+
+#ifdef DCMDBUF
+extern char *cmdbuf;                   /* Command buffers */
+extern char *atmbuf;
+extern char *line;                     /* Character buffer for anything */
+extern int *ifcmd;
+#else
+extern char cmdbuf[];                  /* Command buffers */
+extern char atmbuf[];
+extern char line[];                    /* Character buffer for anything */
+extern int ifcmd[];
+#endif /* DCMDBUF */
+
+char *lp;                              /* Pointer to line buffer */
+
+#ifndef NOSPL
+extern char inpbuf[];                  /* Buffer for INPUT and REINPUT */
+char *inpbp = inpbuf;                  /* And pointer to same */
+extern char lblbuf[];                  /* Buffer for labels */
+#endif /* NOSPL */
+
+char psave[80] = { NUL };              /* For saving & restoring prompt */
+
+extern char tmpbuf[];                  /* Temporary buffer */
+extern int success;                    /* Command success/failure flag */
+
+#ifndef NOSPL
+int                                    /* SET INPUT parameters. */
+  indef = 5,                           /* 5 seconds default timeout */
+  intime = 0,                          /* 0 = proceed */
+  incase = 0,                          /* 0 = ignore */
+  inecho = 1,                          /* 1 = echo on */
+  insilence = 0;                       /* 0 = no silence constraint */
+int maclvl = -1;                       /* Macro nesting level */
+int mecho = 0;                         /* Macro echo, 0 = don't */
+int merror = 0;                                /* Macro error action */
+char varnam[6];                                /* For variable names */
+extern int macargc[];                  /* ARGC from macro invocation */
+
+extern char *m_arg[MACLEVEL][NARGS];   /* Stack of macro arguments */
+extern char **a_ptr[];                 /* Array pointers */
+extern int a_dim[];                    /* Array dimensions */
+
+#ifdef DCMDBUF
+extern struct cmdptr *cmdstk;          /* The command stack itself */
+#else
+extern struct cmdptr cmdstk[];         /* The command stack itself */
+#endif /* DCMDBUF */
+extern int cmdlvl;                     /* Current position in command stack */
+#endif /* NOSPL */
+
+static int x, y, z = 0;                        /* Local workers */
+static char *s;
+
+#define xsystem(s) zsyscmd(s)
+
+/* Top-Level Interactive Command Keyword Table */
+struct keytab cmdtab[] = {
+#ifndef NOPUSH
+    "!",          XXSHE, CM_INV,       /* shell escape */
+#endif /* NOPUSH */
+    "#",          XXCOM, CM_INV,       /* comment */
+#ifndef NOSPL
+    ":",           XXLBL, CM_INV,      /* label */
+#endif /* NOSPL */
+#ifndef NOPUSH
+    "@",           XXSHE, CM_INV,      /* DCL escape */
+#endif /* NOPUSH */
+#ifndef NOSPL
+    "asg",         XXASS, CM_INV,       /* invisible synonym for assign */
+    "ask",         XXASK, 0,           /* ask */
+    "askq",        XXASKQ,0,            /* ask quietly */
+    "assign",      XXASS, 0,            /* assign */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    "bug",         XXBUG, 0,           /* bug report instructions */
+#endif /* NOFRILLS */
+    "bye",         XXBYE, 0,           /* bye to remote server */
+    "c",           XXCON, CM_INV|CM_ABR, /* invisible synonym for connect */
+#ifndef NOFRILLS
+    "cat",         XXTYP, CM_INV,      /* display a local file */
+#endif /* NOFRILLS */
+    "cd",          XXCWD, 0,           /* change directory */
+    "check",       XXCHK, 0,           /* check for a feature */
+#ifndef NOFRILLS
+    "clear",       XXCLE, 0,           /* clear input buffer */
+#endif /* NOFRILLS */
+    "close",      XXCLO, 0,            /* close a log file */
+#ifdef NOFRILLS
+    "comment",     XXCOM, CM_INV,      /* comment */
+#else
+    "comment",     XXCOM, 0,           /* comment */
+#endif /* NOFRILLS */
+    "connect",     XXCON, 0,           /* connect to remote system */
+    "cwd",        XXCWD, CM_INV,       /* invisisble synonym for cd */
+#ifndef NOSPL
+    "dcl",         XXDCL, CM_INV,      /* declare an array */
+    "declare",     XXDCL, 0,           /* declare an array */
+    "decrement",   XXDEC, 0,           /* decrement a numeric variable */
+    "define",      XXDEF, 0,           /* define a macro */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    "delete",      XXDEL, 0,           /* delete a file */
+#endif /* NOFRILLS */
+#ifndef NODIAL
+    "dial",       XXDIAL,0,            /* dial a phone number */
+#endif /* NODIAL */
+#ifndef MAC
+    "directory",   XXDIR, 0,           /* directory of files */
+#endif /* MAC */
+#ifndef NOFRILLS
+    "disable",     XXDIS, 0,           /* disable server function */
+#endif /* NOFRILLS */
+#ifndef NOSPL
+    "do",          XXDO,  0,           /* execute a macro */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    "e-packet",    XXERR, CM_INV,      /* Send an Error packet */
+#endif /* NOFRILLS */
+    "echo",        XXECH, 0,           /* echo argument */
+#ifndef NOSPL
+    "else",        XXELS, CM_INV,      /* ELSE part of IF statement */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    "enable",      XXENA, 0,           /* ENABLE a server function */
+#endif /* NOFRILLS */
+#ifndef NOSPL
+    "end",         XXEND, 0,           /* END command file or macro */
+#endif /* NOSPL */
+    "ex",          XXEXI, CM_INV|CM_ABR, /* Let "ex" still be EXIT */
+    "exit",       XXEXI, 0,            /* exit the program */
+    "extproc",     XXCOM, CM_INV,       /* dummy command */
+    "finish",      XXFIN, 0,           /* FINISH */
+#ifndef NOSPL
+    "for",         XXFOR, 0,           /* FOR loop */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+#ifndef MAC
+    "fot",        XXDIR, CM_INV,       /* "fot" = "dir" (for Chris) */
+#endif /* MAC */
+#endif /* NOFRILLS */
+    "g",           XXGET, CM_INV|CM_ABR, /* Invisible abbreviation for GET */
+#ifndef NOSPL
+    "ge",          XXGET, CM_INV|CM_ABR, /* Ditto */
+#endif /* NOSPL */
+    "get",         XXGET, 0,           /* GET */
+#ifndef NOSPL
+#ifndef NOFRILLS
+    "getok",       XXGOK, 0,           /* GETOK (ask for Yes/No) */
+#endif /* NOFRILLS */
+#endif /* NOSPL */
+#ifndef NOSPL
+    "goto",        XXGOTO,0,           /* goto label in take file or macro */
+#endif /* NOSPL */
+    "hangup",      XXHAN, 0,           /* hangup dialed phone connection */
+    "help",       XXHLP, 0,            /* display help text */
+#ifndef NOSPL
+    "i",           XXINP, CM_INV|CM_ABR, /* invisible synonym for INPUT */
+    "if",          XXIF,  0,           /* if (condition) command */
+    "in",          XXINP, CM_INV|CM_ABR, /* invisible synonym for INPUT */
+    "increment",   XXINC, 0,           /* increment a numeric variable */
+    "input",       XXINP, 0,           /* input string from comm line */
+#endif /* NOSPL */
+#ifndef NOHELP
+     "introduction", XXINT, 0,         /* Print introductory text */
+#endif /* NOHELP */
+#ifndef NOFRILLS
+    "l",           XXLOG, CM_INV|CM_ABR,/* invisible synonym for log */
+#endif /* NOFRILLS */
+    "log",        XXLOG, 0,            /* open a log file */
+#ifndef NOFRILLS
+#ifndef MAC
+    "ls",          XXDIR, CM_INV,      /* invisible synonym for directory */
+#endif /* MAC */
+    "mail",        XXMAI, 0,           /* mail file to user */
+    "man",         XXHLP, CM_INV,       /* Synonym for help */
+#endif /* NOFRILLS */
+#ifndef NOMSEND
+    "mget",        XXGET, CM_INV,      /* MGET = GET */
+#endif /* NOMSEND */
+#ifndef NOSPL
+    "mpause",      XXMSL, CM_INV,      /* Millisecond sleep */
+#endif /* NOSPL */
+#ifndef NOMSEND
+    "ms",          XXMSE, CM_INV|CM_ABR,
+    "msend",       XXMSE, 0,           /* Multiple SEND */
+#endif /* NOMSEND */
+#ifndef NOSPL
+    "msleep",      XXMSL, 0,           /* Millisecond sleep */
+#endif /* NOSPL */
+#ifndef NOMSEND
+    "mput",        XXMSE, CM_INV,      /* MPUT = MSEND */
+#endif /* NOMSEND */
+#ifndef NOFRILLS
+    "mv",          XXREN, CM_INV,      /* rename a local file */
+#endif /* NOFRILLS */
+#ifndef NOSPL
+    "o",           XXOUT, CM_INV|CM_ABR,/* invisible synonym for OUTPUT */
+    "open",        XXOPE, 0,           /* open file for reading or writing */
+    "output",      XXOUT, 0,           /* output string to comm line */
+#endif /* NOSPL */
+#ifdef SUNX25
+    "pad",         XXPAD, 0,            /* PAD commands */
+#endif /* SUNX25 */
+#ifndef NOSPL
+    "pause",       XXPAU, 0,           /* sleep for specified interval */
+#ifdef TCPSOCKET
+    "ping",        XXPNG, 0,           /* PING (for TCP/IP) */
+#endif /* TCPSOCKET */
+    "pop",         XXEND, CM_INV,      /* allow POP as synonym for END */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    "print",       XXPRI, 0,           /* PRINT */
+#ifndef NOPUSH
+    "pu",          XXSHE, CM_INV,      /* PU = PUSH */
+    "push",        XXSHE, 0,           /* PUSH command (like RUN, !) */
+#endif /* NOPUSH */
+    "put",        XXSEN, CM_INV,       /* PUT = SEND */
+#ifndef MAC
+    "pwd",         XXPWD, 0,            /* print working directory */
+#endif /* MAC */
+#endif /* NOFRILLS */
+    "quit",       XXQUI, 0,            /* quit from program = exit */
+    "r",           XXREC, CM_INV,      /* invisible synonym for receive */
+#ifndef NOSPL
+    "read",        XXREA, 0,            /* read */
+#endif /* NOSPL */
+    "receive",    XXREC, 0,            /* receive files */
+#ifndef NODIAL
+    "redial",      XXRED, 0,           /* redial */
+#endif /* NODIAL */
+#ifndef NOSPL
+    "reinput",     XXREI, 0,            /* reinput */
+#endif /* NOSPL */
+    "remote",     XXREM, 0,            /* send generic command to server */
+#ifndef NOFRILLS
+    "rename",      XXREN, 0,           /* rename a local file */
+    "replay",      XXTYP, CM_INV,      /* replay (for now, just type) */
+#endif /* NOFRILLS */
+#ifndef NOSPL
+    "return",      XXRET, 0,           /* return from function */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    "rm",          XXDEL, CM_INV,      /* invisible synonym for delete */
+#endif /* NOFRILLS */
+#ifndef NOPUSH
+    "run",         XXSHE, 0,           /* run a program or command */
+#endif /* NOPUSH */
+    "s",           XXSEN, CM_INV|CM_ABR, /* invisible synonym for send */
+#ifndef NOSCRIPT
+    "script",     XXLOGI,0,            /* execute a uucp-style script */
+#endif /* NOSCRIPT */
+    "send",       XXSEN, 0,            /* send files */
+#ifndef NOSERVER
+    "server",     XXSER, 0,            /* be a server */
+#endif /* NOSERVER */
+    "set",        XXSET, 0,            /* set parameters */
+#ifndef NOSHOW
+    "show",       XXSHO, 0,            /* show parameters */
+#endif /* NOSHOW */
+#ifndef NOSPL
+#ifndef NOFRILLS
+    "sleep",       XXPAU, CM_INV,      /* sleep for specified interval */
+#endif /* NOFRILLS */
+#endif /* NOSPL */
+#ifndef MAC
+#ifndef NOFRILLS
+    "sp",          XXSPA, CM_INV|CM_ABR,
+    "spa",         XXSPA, CM_INV|CM_ABR,
+#endif /* NOFRILLS */
+    "space",       XXSPA, 0,           /* show available disk space */
+#endif /* MAC */
+#ifndef NOFRILLS
+#ifndef NOPUSH
+    "spawn",       XXSHE, CM_INV,      /* synonym for PUSH, RUN */
+#endif /* NOPUSH */
+#endif /* NOFRILLS */
+    "statistics",  XXSTA, 0,           /* display file transfer stats */
+#ifndef NOSPL
+    "stop",        XXSTO, 0,           /* stop all take files */
+#endif /* NOSPL */
+#ifndef NOJC
+    "suspend",     XXSUS, 0,           /* Suspend */
+#endif /* NOJC */
+    "take",       XXTAK, 0,            /* take commands from file */
+#ifndef NOFRILLS
+#ifdef NETCONN
+    "telnet",      XXTEL, 0,           /* telnet */
+#endif /* NETCONN */
+    "test",        XXTES, CM_INV,      /* (for testing) */
+#endif /* NOFRILLS */
+#ifndef NOCSETS
+    "translate",   XXXLA, 0,           /* translate local file char sets */
+#endif
+#ifndef NOXMIT
+    "transmit",    XXTRA, 0,           /* raw upload file */
+#endif /* NOXMIT */
+#ifndef NOFRILLS
+    "type",        XXTYP, 0,           /* display a local file */
+#endif /* NOFRILLS */
+    "version",     XXVER, 0            /* version number display */
+#ifndef NOSPL
+,   "wait",        XXWAI, 0            /* wait (like pause) */
+,   "while",       XXWHI, 0            /* while */
+#endif /* NOSPL */
+#ifndef MAC
+#ifndef NOFRILLS
+,   "who",         XXWHO, 0            /* who */
+#endif /* NOFRILLS */
+#endif /* MAC */
+#ifndef NOSPL
+,   "write",       XXWRI, 0            /* write */
+,   "xif",         XXIFX, 0            /* Extended IF */
+#endif /* NOSPL */
+#ifndef NOCSETS
+,   "xlate",       XXXLA, CM_INV       /* translate local file char sets */
+#endif
+#ifndef NOXMIT
+,   "xmit",        XXTRA, CM_INV       /* raw upload file */
+#endif /* NOXMIT */
+,   "z",           XXSUS, CM_INV       /* Suspend */
+#ifndef NOSPL
+,   "_assign",     XXASX, CM_INV       /* used internally by FOR, etc */
+,   "_define",     XXDFX, CM_INV       /* used internally by FOR, etc */
+,   "_getargs",    XXGTA, CM_INV        /* used internally by FOR, etc */
+,   "_putargs",    XXPTA, CM_INV        /* used internally by FOR, etc */
+#endif /* NOSPL */
+};
+int ncmd = (sizeof(cmdtab) / sizeof(struct keytab));
+
+char toktab[] = {
+#ifndef NOPUSH
+    '!',                               /* Shell escape */
+#endif /* NOPUSH */
+    '#',                               /* Comment */
+    ';',                               /* Comment */
+#ifndef NOSPL
+    ':',                               /* Label */
+#endif /* NOSPL */
+#ifndef NOPUSH
+    '@',                               /* DCL escape */
+#endif /* NOPUSH */
+    '\0'                               /* End of this string */
+};
+
+#ifndef NOSPL
+#ifndef NOFRILLS
+struct keytab yesno[] = {
+    "no",    0, 0,
+    "ok",    1, 0,
+    "yes",   1, 0
+};
+int nyesno = (sizeof(yesno) / sizeof(struct keytab));
+#endif /* NOFRILLS */
+#endif /* NOSPL */
+
+/* Parameter keyword table */
+struct keytab prmtab[] = {
+    "attributes",       XYATTR,  0,
+    "b",               XYBACK,  CM_INV|CM_ABR,
+    "ba",              XYBACK,  CM_INV|CM_ABR,
+    "background",       XYBACK,  0,
+    "baud",            XYSPEE,  CM_INV,
+    "block-check",     XYCHKT,  0,
+#ifdef DYNAMIC
+    "buffers",          XYBUF,   0,
+#endif /* DYNAMIC */
+#ifndef MAC
+    "carrier",          XYCARR,  0,
+#endif /* MAC */
+#ifndef NOSPL
+    "case",             XYCASE,  0,
+#endif /* NOSPL */
+    "command",          XYCMD,   0,
+#ifndef NOSPL
+    "count",            XYCOUN,  0,
+#endif /* NOSPL */
+    "d",               XYDELA,  CM_INV|CM_ABR,
+    "de",              XYDELA,  CM_INV|CM_ABR,
+    "debug",            XYDEBU,  CM_INV,
+#ifdef VMS
+    "default",          XYDFLT,  0,
+#else
+#ifndef MAC
+    "default",          XYDFLT,  CM_INV,
+#endif /* MAC */
+#endif /* VMS */
+    "delay",           XYDELA,  0,
+#ifndef NODIAL
+    "dial",             XYDIAL,  0,
+#endif /* NODIAL */
+    "duplex",          XYDUPL,  0,
+    "escape-character", XYESC,   0,
+    "file",            XYFILE,  0,
+    "flow-control",    XYFLOW,  0,
+    "handshake",       XYHAND,  0,
+#ifdef NETCONN
+    "host",             XYHOST,  0,
+#endif /* NETCONN */
+    "incomplete",      XYIFD,   CM_INV,
+#ifndef NOSPL
+    "i",               XYINPU,  CM_INV|CM_ABR,
+    "in",              XYINPU,  CM_INV|CM_ABR,
+    "input",            XYINPU,  0,
+#ifndef MAC
+#ifndef NOSETKEY
+    "key",             XYKEY,   0,
+#endif /* NOSETKEY */
+#endif /* MAC */
+#endif /* NOSPL */
+    "l",                XYLINE,  CM_INV|CM_ABR,
+#ifndef NOCSETS
+    "language",         XYLANG,  0,
+#endif /* NOCSETS */
+    "line",             XYLINE,  0,
+    "local-echo",      XYLCLE,  CM_INV,
+#ifndef NOSPL
+    "macro",            XYMACR,  0,
+#endif /* NOSPL */
+#ifdef COMMENT
+#ifdef VMS
+    "messages",         XYMSGS,  0,
+#endif /* VMS */
+#endif /* COMMENT */
+#ifndef NODIAL
+    "modem-dialer",    XYMODM,  0,
+#endif
+#ifdef NETCONN
+    "network",          XYNET,   0,
+#endif /* NETCONN */
+#ifdef SUNX25
+    "pad",              XYPAD,   0,
+#endif /* SUNX25 */
+    "parity",          XYPARI,  0,
+    "port",             XYLINE,  CM_INV,
+#ifndef NOFRILLS
+    "prompt",          XYPROM,  0,
+#endif /* NOFRILLS */
+    "quiet",           XYQUIE,  0,
+    "receive",          XYRECV,  0,
+    "retry-limit",      XYRETR,  0,
+#ifndef NOSCRIPT
+    "script",          XYSCRI,  0,
+#endif /* NOSCRIPT */
+    "send",             XYSEND,  0,
+#ifndef NOSERVER
+    "server",           XYSERV,  0,
+#endif /* NOSERVER */
+#ifdef UNIX
+    "session-log",      XYSESS,  0,
+#endif /* UNIX */
+    "speed",           XYSPEE,  0,
+#ifndef NOJC
+    "suspend",          XYSUSP,  0,
+#endif /* NOJC */
+    "take",             XYTAKE,  0,
+#ifdef TNCODE
+    "telnet",           XYTEL,   0,
+#endif /* TNCODE */
+    "terminal",         XYTERM,  0,
+    "transfer",         XYXFER,  0,
+#ifndef NOXMIT
+    "transmit",         XYXMIT,  0,
+#endif /* NOXMIT */
+#ifndef NOCSETS
+    "unknown-char-set", XYUNCS,  0,
+#endif /* NOCSETS */
+    "window-size",      XYWIND,  0
+#ifdef UNIX
+,   "wildcard-expansion", XYWILD, 0
+#endif /* UNIX */
+#ifdef SUNX25
+,   "x.25",             XYX25,   0,
+    "x25",              XYX25,   CM_INV
+#endif /* SUNX25 */
+#ifndef NOCSETS
+,   "xfer",             XYXFER,  CM_INV
+#endif /* NOCSETS */
+#ifndef NOXMIT
+,   "xmit",             XYXMIT,  CM_INV
+#endif /* NOXMIT */
+};
+int nprm = (sizeof(prmtab) / sizeof(struct keytab)); /* How many parameters */
+/* Table of networks */
+#ifdef NETCONN
+struct keytab netcmd[] = {
+#ifdef DECNET
+    "decnet",        NET_DEC,  0,
+#endif /* DECNET */
+#ifdef NPIPE
+    "named-pipe",    NET_PIPE, 0,
+#endif /* NPIPE */
+#ifdef TCPSOCKET
+    "tcp/ip",        NET_TCPB, 0
+#endif /* TCPSOCKET */
+#ifdef SUNX25
+,   "x",            NET_SX25, CM_INV|CM_ABR,
+    "x.25",         NET_SX25, 0,
+    "x25",          NET_SX25, CM_INV
+#endif /* SUNX25 */
+};
+int nnets = (sizeof(netcmd) / sizeof(struct keytab)); /* How many networks */
+#endif /* NETCONN */
+
+/* Remote Command Table */
+struct keytab remcmd[] = {
+    "cd",        XZCWD, 0,
+    "cwd",       XZCWD, CM_INV,
+    "delete",    XZDEL, 0,
+    "directory", XZDIR, 0,
+    "help",      XZHLP, 0,
+#ifndef NOPUSH
+    "host",      XZHOS, 0,
+#endif /* NOPUSH */
+#ifndef NOFRILLS
+    "kermit",    XZKER, 0,
+    "login",     XZLGI, 0,
+    "logout",    XZLGO, 0,
+    "print",     XZPRI, 0,
+#endif /* NOFRILLS */
+    "set",       XZSET, 0,
+    "space",    XZSPA, 0
+#ifndef NOFRILLS
+,   "type",     XZTYP, 0,
+    "who",      XZWHO, 0
+#endif /* NOFRILLS */
+};
+int nrmt = (sizeof(remcmd) / sizeof(struct keytab));
+struct keytab logtab[] = {
+#ifdef DEBUG
+    "debugging",    LOGD, 0,
+#endif /* DEBUG */
+    "packets",     LOGP, 0,
+    "session",      LOGS, 0
+#ifdef TLOG
+,   "transactions", LOGT, 0
+#endif /* TLOG */
+};
+int nlog = (sizeof(logtab) / sizeof(struct keytab));
+struct keytab writab[] = {
+#ifndef NOSPL
+    "append-file",     LOGW, CM_INV,
+#endif /* NOSPL */
+    "debug-log",       LOGD, 0,
+    "error",           LOGE, 0,
+#ifndef NOSPL
+    "file",            LOGW, 0,
+#endif /* NOSPL */
+    "packet-log",      LOGP, 0,
+    "screen",          LOGX, 0,
+    "session-log",     LOGS, 0,
+    "sys$output",      LOGX, CM_INV,
+    "transaction-log", LOGT, 0
+};
+int nwri = (sizeof(writab) / sizeof(struct keytab));
+
+#define CLR_DEV  1
+#define CLR_INP  2
+
+static struct keytab clrtab[] = {      /* Keywords for CLEAR command */
+#ifndef NOSPL
+    "both",          CLR_DEV|CLR_INP, 0,
+#endif /* NOSPL */
+    "device-buffer", CLR_DEV,         0,
+#ifndef NOSPL
+    "input-buffer",  CLR_INP,         0
+#endif /* NOSPL */
+};
+int nclear = (sizeof(clrtab) / sizeof(struct keytab));
+
+struct keytab clstab[] = {             /* Keywords for CLOSE command */
+#ifndef NOSPL
+    "append-file",     LOGW, CM_INV,
+#endif /* NOSPL */
+#ifdef DEBUG
+    "debug-log",       LOGD, 0,
+#endif /* DEBUG */
+    "packet-log",      LOGP, 0,
+#ifndef NOSPL
+    "read-file",       LOGR, 0,
+#endif /* NOSPL */
+    "session-log",     LOGS, 0
+#ifdef TLOG
+,   "transaction-log", LOGT, 0
+#endif /* TLOG */
+#ifndef NOSPL
+,   "write-file",      LOGW, 0
+#endif /* NOSPL */
+};
+int ncls = (sizeof(clstab) / sizeof(struct keytab));
+
+/* SHOW command arguments */
+struct keytab shotab[] = {
+#ifndef NOSPL
+    "arguments", SHARG, 0,
+    "arrays", SHARR, 0,
+#endif /* NOSPL */
+    "attributes", SHATT, 0,
+    "character-sets", SHCSE, 0,
+    "communications", SHCOM, 0,
+#ifndef NOSPL
+    "count", SHCOU, 0,
+#endif /* NOSPL */
+#ifdef VMS
+    "default", SHDFLT, 0,
+#else
+    "default", SHDFLT, CM_INV,
+#endif /* VMS */
+#ifndef NODIAL
+    "dial", SHDIA, 0,
+#endif /* NODIAL */
+    "escape", SHESC, 0,
+    "features", SHFEA, 0,
+    "file", SHFIL, 0,
+#ifndef NOSPL
+    "functions", SHFUN, 0,
+    "globals", SHVAR, 0,
+#endif /* NOSPL */
+#ifndef NOSETKEY
+    "key", SHKEY, 0,
+#endif /* NOSETKEY */
+#ifdef VMS
+    "labeled-file-info", SHLBL, 0,
+#endif /* VMS */
+#ifndef NOCSETS
+    "languages", SHLNG, 0,
+#endif /* NOCSETS */
+#ifndef NOSPL
+    "macros", SHMAC, 0,
+#endif /* NOSPL */
+    "modem-signals", SHMOD, 0,
+    "network", SHNET, 0,
+#ifdef SUNX25
+    "pad", SHPAD, 0,
+#endif /* SUNX25 */
+    "parameters", SHPAR, CM_INV,
+    "protocol", SHPRO, 0,
+#ifndef NOSPL
+    "scripts", SHSCR, 0,
+#endif /* NOSPL */
+#ifndef NOSERVER
+    "server", SHSER, 0,
+#endif /* NOSERVER */
+    "status", SHSTA, 0,
+#ifdef MAC
+    "stack", SHSTK, 0,                 /* debugging */
+#endif /* MAC */
+    "terminal", SHTER, 0
+#ifndef NOXMIT
+,   "transmit", SHXMI, 0
+#endif /* NOXMIT */
+#ifndef NOSPL
+,   "variables", SHBUI, 0
+#endif /* NOSPL */
+#ifndef NOFRILLS
+,   "versions", SHVER, 0
+#endif /* NOFRILLS */
+#ifndef NOXMIT
+,   "xmit", SHXMI, CM_INV
+#endif /* NOXMIT */
+};
+int nsho = (sizeof(shotab) / sizeof(struct keytab));
+
+#ifdef SUNX25
+struct keytab padtab[] = {              /* PAD commands */
+    "clear",      XYPADL, 0,
+    "interrupt",  XYPADI, 0,
+    "reset",      XYPADR, 0,
+    "status",     XYPADS, 0
+};
+int npadc = (sizeof(padtab) / sizeof(struct keytab));
+#endif /* SUNX25 */
+
+struct keytab enatab[] = {             /* ENABLE commands */
+    "all",        EN_ALL,  0,
+#ifndef datageneral
+    "bye",        EN_BYE,  0,
+#endif /* datageneral */
+    "cd",         EN_CWD,  0,
+    "cwd",        EN_CWD,  CM_INV,
+    "delete",     EN_DEL,  0,
+    "directory",  EN_DIR,  0,
+    "finish",     EN_FIN,  0,
+    "get",        EN_GET,  0,
+    "host",       EN_HOS,  0,
+    "send",       EN_SEN,  0,
+    "set",        EN_SET,  0,
+    "space",      EN_SPA,  0,
+    "type",       EN_TYP,  0,
+    "who",        EN_WHO,  0
+};
+int nena = (sizeof(enatab) / sizeof(struct keytab));
+
+#ifndef NOSPL
+#ifdef COMMENT
+struct mtab mactab[MAC_MAX] = {                /* Preinitialized macro table */
+    NULL, NULL, 0
+};
+#else
+struct mtab *mactab;                   /* Dynamically allocated macro table */
+#endif /* COMMENT */
+int nmac = 0;
+
+struct keytab mackey[MAC_MAX];         /* Macro names as command keywords */
+#endif /* NOSPL */
+
+/* Forward declarations of functions */
+
+_PROTOTYP (int doask,   ( int  ) );
+_PROTOTYP (int dodef,   ( int  ) );
+_PROTOTYP (int dodel,   ( void ) );
+_PROTOTYP (int dodial,  ( int  ) );
+_PROTOTYP (int dodir,   ( void ) );
+_PROTOTYP (int doelse,  ( void ) );
+_PROTOTYP (int dofor,   ( void ) );
+_PROTOTYP (int dogta,   ( int  ) );
+_PROTOTYP (int doincr,  ( int  ) );
+_PROTOTYP (int dopaus,  ( int  ) );
+_PROTOTYP (int doping,  ( void ) );
+_PROTOTYP (int dorenam, ( void ) );
+
+#ifdef TCPSOCKET
+int
+doping() {
+    char *p;
+    int x;
+
+    if (network)                       /* If we have a current connection */
+      strcpy(line,ttname);             /* get the host name */
+    else *line = '\0';                 /* as default host to be pinged. */
+    for (p = line; *p; p++)            /* Remove ":service" from end. */
+      if (*p == ':') { *p = '\0'; break; }
+    if ((x = cmtxt("IP host name or number", line, &s, xxstring)) < 0)
+      return(x);
+/* Construct PING command */
+#ifdef VMS
+#ifdef MULTINET                                /* TGV MultiNet */
+    sprintf(line,"multinet ping %s /num=1",s);
+#else
+    sprintf(line,"ping %s 56 1",s);    /* Other VMS TCP/IP's */
+#endif /* MULTINET */
+#else                                  /* Not VMS */
+    sprintf(line,"ping %s",s);
+#endif /* VMS */
+    conres();                          /* Make console normal  */
+#ifdef DEC_TCPIP
+    printf("\n");                      /* Prevent prompt-stomping */
+#endif /* DEC_TCPIP */
+    x = zshcmd(line);
+    concb((char)escape);
+    return(success = 1);               /* We don't know the status */
+}
+#endif /* TCPSOCKET */
+
+/*  D O C M D  --  Do a command  */
+/*
+ Returns:
+   -2: user typed an illegal command
+   -1: reparse needed
+    0: parse was successful (even tho command may have failed).
+*/ 
+int
+docmd(cx) int cx; {
+
+    debug(F101,"docmd entry, cx","",cx);
+
+/*
+  Massive switch() broken up into many smaller ones, for the benefit of
+  compilers that run out of space when trying to handle large switch
+  statements.
+*/
+    switch (cx) {
+      case -4:                 /* EOF */
+#ifdef OSK
+       if (msgflg)  printf("\n");
+#else
+       if (msgflg)  printf("\r\n");
+#endif /* OSK */
+         doexit(GOOD_EXIT,xitsta);
+      case -3:                         /* Null command */
+       return(0);
+      case -9:                         /* Like -2, but errmsg already done */
+      case -1:                         /* Reparse needed */
+       return(cx);
+      case -6:                         /* Special */
+      case -2:                         /* Error, maybe */
+#ifndef NOSPL
+/*
+  Maybe they typed a macro name.  Let's look it up and see.
+*/
+       if (cx == -6)                   /* If they typed CR */
+         strcat(cmdbuf,"\015");        /*  add it back to command buffer. */
+       if (ifcmd[cmdlvl] == 2)         /* Watch out for IF commands. */
+         ifcmd[cmdlvl]--;
+       repars = 1;                     /* Force reparse */
+       cmres();
+       cx = XXDO;                      /* Try DO command */
+#else
+       return(cx);
+#endif /* NOSPL */
+      default:
+       break;
+    }
+#ifndef NOSPL
+/* Copy macro args from/to two levels up, used internally by _floop et al. */
+    if (cx == XXGTA || cx == XXPTA) {  /* _GETARGS, _PUTARGS */
+       int x;
+       debug(F101,"docmd XXGTA","",XXGTA);
+       debug(F101,"docmd cx","",cx);
+       debug(F101,"docmd XXGTA maclvl","",maclvl);
+       x = dogta(cx);
+       debug(F101,"docmd dogta returns","",x);
+       debug(F101,"docmd dogta maclvl","",maclvl);
+       return(x);
+    }
+#endif /* NOSPL */
+
+#ifndef NOSPL
+/* ASK, ASKQ, READ */
+    if (cx == XXASK || cx == XXASKQ || cx == XXREA) {
+       return(doask(cx));
+    }
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+    if (cx == XXBUG) {                 /* BUG */
+       if ((x = cmcfm()) < 0) return(x);
+       return(dobug());
+    }
+#endif /* NOFRILLS */
+
+    if (cx == XXBYE) {                 /* BYE */
+       if ((x = cmcfm()) < 0) return(x);
+       sstate = setgen('L',"","","");
+       if (local) ttflui();            /* If local, flush tty input buffer */
+       return(0);
+    } 
+
+#ifndef NOFRILLS
+    if (cx == XXCLE) {                 /* CLEAR */
+       if ((x = cmkey(clrtab,nclear,"buffer(s) to clear",
+#ifdef NOSPL
+                 "device-buffer"
+#else
+                 "both"
+#endif /* NOSPL */
+                 ,xxstring)) < 0) return(x);
+       if ((y = cmcfm()) < 0) return(y);
+
+       /* Clear device input buffer if requested */
+       y = (x & CLR_DEV) ? ttflui() : 0;
+#ifndef NOSPL
+       /* Clear INPUT command buffer if requested */
+       if (x & CLR_INP) {
+           for (x = 0; x < INPBUFSIZ; x++)
+             inpbuf[x] = 0;
+           inpbp = inpbuf;
+       }
+#endif /* NOSPL */
+       return(success = (y == 0));
+    }
+#endif /* NOFRILLS */
+
+    if (cx == XXCOM) {                 /* COMMENT */
+       if ((x = cmtxt("Text of comment line","",&s,NULL)) < 0)
+         return(x);
+       /* Don't change SUCCESS flag for this one */
+       return(0);
+    } 
+
+    if (cx == XXCON) {                 /* CONNECT */
+       if ((x = cmcfm()) < 0)
+         return(x);
+       return(success = doconect());
+    }
+
+    if (cx == XXCWD)                   /* CWD */
+      return(success = docd());
+
+    if (cx == XXCHK)                   /* CHECK */
+      return(success = dochk());
+
+    if (cx == XXCLO) {                 /* CLOSE */
+       x = cmkey(clstab,ncls,"Which log or file to close","",xxstring);
+       if (x == -3) {
+           printf("?You must say which file or log\n");
+           return(-9);
+       }
+       if (x < 0) return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       y = doclslog(x);
+       success = (y == 1);
+       return(success);
+    }
+
+#ifndef NOSPL
+    if (cx == XXDEC || cx == XXINC)    /* DECREMENT, INCREMENT */
+      return(doincr(cx));
+#endif /* NOSPL */
+
+#ifndef NOSPL
+    if (cx == XXDEF || cx == XXASS || cx == XXASX || cx == XXDFX)
+      return(dodef(cx));               /* DEFINE, ASSIGN */
+#endif /* NOSPL */
+
+#ifndef NOSPL    
+    if (cx == XXDCL) {                 /* DECLARE an array */
+       if ((y = cmfld("Array name","",&s,NULL)) < 0) {
+           if (y == -3) {
+               printf("?Array name required\n");
+               return(-9);
+           } else return(y);
+       }
+       if ((y = arraynam(s,&x,&z)) < 0) return(y);
+       if ((y = cmcfm()) < 0) return(y);
+       if (dclarray((char)x,z) < 0) {
+           printf("?Declare failed\n");
+           return(success = 0);
+       }
+       return(success = 1);
+    }
+#endif /* NOSPL */
+
+
+#ifndef NODIAL
+    if (cx == XXRED || cx == XXDIAL)   /* DIAL or REDIAL */
+      return(dodial(cx));
+#endif /* NODIAL */
+#ifndef NOFRILLS
+    if (cx == XXDEL)                   /* DELETE */
+      return(dodel());
+#endif /* NOFRILLS */
+
+#ifndef MAC
+    if (cx == XXDIR)                   /* DIRECTORY */
+      return(dodir());
+#endif /* MAC */
+#ifndef NOSPL
+    if (cx == XXELS)                   /* ELSE */
+      return(doelse());
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+    if (cx == XXENA || cx == XXDIS) {  /* ENABLE, DISABLE */
+       s = (cx == XXENA) ?
+         "Server function to enable" :
+           "Server function to disable";
+
+       if ((x = cmkey(enatab,nena,s,"",xxstring)) < 0) {
+           if (x == -3) {
+               printf("?Name of server function required\n");
+               return(-9);
+           } else return(x);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+       return(doenable(cx,x));
+    }
+#endif /* NOFRILLS */
+
+#ifndef NOSPL
+    if (cx == XXRET) {                 /* RETURN */
+       if (cmdlvl == 0) {              /* At top level, nothing happens... */
+           if ((x = cmcfm()) < 0)
+             return(x);
+           return(success = 1);
+       } else if (cmdstk[cmdlvl].src == CMD_TF) { /* In TAKE file, like POP */
+           if ((x = cmtxt("optional return value","",&s,NULL)) < 0)
+             return(x);                /* Allow trailing text, but ignore. */
+           if ((x = cmcfm()) < 0)
+             return(x);
+           popclvl();                  /* pop command level */
+           return(success = 1);        /* always succeeds */
+       } else if (cmdstk[cmdlvl].src == CMD_MD) { /* Within macro */  
+           if ((x = cmtxt("optional return value","",&s,NULL)) < 0)
+             return(x);
+           return(doreturn(s));        /* Trailing text is return value. */
+       } else return(-2);
+    }
+#endif /* NOSPL */
+
+#ifndef NOSPL
+    if (cx == XXDO) {                  /* DO (a macro) */
+       if (nmac == 0) {
+           printf("\n?No macros defined\n");
+           return(-2);
+       }
+       for (y = 0; y < nmac; y++) {    /* copy the macro table */
+           mackey[y].kwd = mactab[y].kwd; /* into a regular keyword table */
+           mackey[y].kwval = y;        /* with value = pointer to macro tbl */
+           mackey[y].flgs = mactab[y].flgs;
+       }
+       /* parse name as keyword */
+       if ((x = cmkey(mackey,nmac,"macro","",xxstring)) < 0) {
+           if (x == -3) {
+               printf("?Macro name required\n");
+               return(-9);
+           } else return(x);
+       }
+       if ((y = cmtxt("optional arguments","",&s,xxstring)) < 0)
+         return(y);                    /* get args */
+       return(dodo(x,s) < 1 ? (success = 0) : 1);
+    }
+#endif /* NOSPL */
+
+    if (cx == XXECH) {                 /* ECHO */
+       if ((x = cmtxt("Material to be echoed","",&s,xxstring)) < 0)
+         return(x);
+       if (*s == '{') {                /* Strip enclosing braces */
+           x = (int)strlen(s);
+           if (s[x-1] == '}') {
+               s[x-1] = NUL;
+               s++;
+           }
+       }
+       printf("%s\n",s);
+       return(1);                      /* Always succeeds */
+    }
+
+#ifndef NOSPL
+    if (cx == XXOPE)                   /* OPEN */
+      return(doopen());
+#endif /* NOSPL */
+
+#ifndef NOSPL
+    if (cx == XXOUT) {                 /* OUTPUT */
+       if ((x = cmtxt("Text to be output","",&s,NULL)) < 0)
+         return(x);
+       debug(F110,"OUTPUT 1",s,0);
+       if (*s == '{') {                /* Strip enclosing braces, */
+           x = (int)strlen(s);         /* if any. */
+           if (s[x-1] == '}') {
+               s[x-1] = NUL;
+               s++;
+           }
+       }
+       debug(F110,"OUTPUT 2",s,0);
+       for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \B, \L to \\B, \\L */
+           if (x > 0 &&
+               (s[x] == 'B' || s[x] == 'b' || s[x] == 'L' || s[x] == 'l'))
+             if ((x == 1 && s[x-1] == CMDQ) ||
+                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ))
+               line[y++] = CMDQ;
+           line[y] = s[x];
+       }
+       line[y++] = '\0';               /* Now expand variables, etc. */
+       debug(F110,"OUTPUT 3",line,0);
+       s = line+y+1;
+       x = LINBUFSIZ - strlen(line) - 1;
+       debug(F101,"OUTPUT size","",x);
+       if (xxstring(line,&s,&x) < 0)
+         return(success = 0);
+       s = line+y+1;
+       debug(F110,"OUTPUT 4",s,0);
+       return(success = dooutput(s));
+    }
+#endif /* NOSPL */
+
+#ifdef SUNX25
+    if (cx == XXPAD) {                 /* PAD commands */
+       x = cmkey(padtab,npadc,"PAD command","",xxstring);
+       if (x == -3) {
+           printf("?You must specify a PAD command to execute\n");
+           return(-2);
+       }
+       if (x < 0) return(x);
+    
+       switch (x) {
+         case XYPADL: 
+           if (x25stat() < 0)
+             printf("Sorry, you must 'set network' & 'set host' first\r\n");
+           else {
+               x25clear();
+               initpad();
+           }
+           break;
+         case XYPADS:
+           if (x25stat() < 0)
+             printf("Not connected\r\n");
+           else {
+               extern int linkid, lcn;
+               conol("Connected thru ");
+               conol(ttname);
+               printf(", Link id %d, Logical channel number %d\r\n",
+                      linkid,lcn);
+           }
+           break;
+         case XYPADR:
+           if (x25stat() < 0)
+             printf("Sorry, you must 'set network' & 'set host' first\r\n");
+           else
+             x25reset(0,0);
+           break;
+         case XYPADI:
+           if (x25stat() < 0)
+             printf("Sorry, you must 'set network' & 'set host' first\r\n");
+           else 
+             x25intr(0);
+       }
+       return(0);
+}
+#endif /* SUNX25 */
+
+#ifndef NOSPL
+    if (cx == XXPAU || cx == XXWAI || cx == XXMSL) /* PAUSE, WAIT, etc */
+      return(dopaus(cx));
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+    if (cx == XXPRI) {
+       if ((x = cmifi("File to print","",&s,&y,xxstring)) < 0) {
+           if (x == -3) {
+               printf("?A file specification is required\n");
+               return(-9);
+           } else return(x);
+       }
+       if (y != 0) {
+           printf("?Wildcards not allowed\n");
+           return(-9);
+       }
+       strcpy(line,s);
+       if ((x = cmtxt("Local print command options, or carriage return","",&s,
+                      xxstring)) < 0) return(x);
+       return(success = (zprint(s,line) == 0) ? 1 : 0);
+    }
+
+#ifdef TCPSOCKET
+    if (cx == XXPNG)                   /* PING an IP host */
+      return(doping());
+#endif /* TCPSOCKET */
+
+#ifndef MAC
+    if (cx == XXPWD) {                 /* PWD */
+       if ((x = cmcfm()) < 0) return(x);
+       xsystem(PWDCMD);
+       return(success = 1);            /* blind faith */
+    }
+#endif /* MAC */
+#endif /* NOFRILLS */
+
+    if (cx == XXQUI || cx == XXEXI) {  /* EXIT, QUIT */
+       if ((y = cmnum("exit status code","",10,&x,xxstring)) < 0) {
+           if (y == -3)
+             x = xitsta;
+           else return(y);
+       }
+       if ((y = cmcfm()) < 0) return(y);
+#ifdef VMS
+       doexit(GOOD_EXIT,x);
+#else
+#ifdef OSK
+/* Returning any codes here makes the OS-9 shell print an error message. */
+       doexit(GOOD_EXIT,-1);
+#else
+#ifdef datageneral
+        doexit(GOOD_EXIT,x);
+#else
+       doexit(x,-1);
+#endif /* datageneral */
+#endif /* OSK */
+#endif /* VMS */
+    }
+
+#ifndef NOFRILLS
+    if (cx == XXERR) {                 /* ERROR */
+       if ((x = cmcfm()) < 0) return(x);
+       ttflui();
+       sstate = 'a';
+       return(0);
+    }
+#endif /* NOFRILLS */
+
+    if (cx == XXFIN) {                 /* FINISH */
+       if ((x = cmcfm()) < 0) return(x);
+       sstate = setgen('F',"","","");
+       if (local) ttflui();            /* If local, flush tty input buffer */
+       return(0);
+    }
+
+#ifndef NOSPL
+    if (cx == XXFOR)                   /* FOR loop */
+      return(dofor());
+#endif /* NOSPL */
+
+    if (cx == XXGET) {                 /* GET */
+       x = cmtxt("Name of remote file(s), or carriage return","",&cmarg,
+                 xxstring);
+#ifndef NOFRILLS
+       if ((x == -2) || (x == -1)) return(x);
+#else
+       if (x < 0) return(x);
+#endif /* NOFRILLS */
+       if (*cmarg == '{') {            /* Strip any enclosing braces */
+           x = (int)strlen(cmarg);     /* This allows preservation of */
+           if (cmarg[x-1] == '}') {    /* leading and/or trailing */
+               cmarg[x-1] = NUL;       /* spaces. */
+               cmarg++;
+           }
+       }
+       x = doget();
+#ifdef MAC
+       if (sstate == 'r')
+           scrcreate();
+#endif /* MAC */
+       return(x);
+    }
+
+#ifndef NOSPL
+#ifndef NOFRILLS
+    if (cx == XXGOK) {                 /* GETOK */
+       return(success = doask(cx));
+    }
+#endif /* NOFRILLS */
+#endif /* NOSPL */
+
+    if (cx == XXHLP) {                 /* HELP */
+#ifdef NOHELP
+       return(dohlp(XXHLP));        
+#else
+       x = cmkey2(cmdtab,ncmd,"C-Kermit command","help",toktab,xxstring);
+       debug(F101,"HELP command x","",x);
+       if (x == -5) {
+           y = chktok(toktab);
+           debug(F101,"top-level cmkey token","",y);
+           ungword();
+           switch (y) {
+#ifndef NOPUSH
+             case '!': x = XXSHE; break;
+#endif /* NOPUSH */
+             case '#': x = XXCOM; break;
+             case ';': x = XXCOM; break;
+#ifndef NOSPL
+             case ':': x = XXLBL; break;
+#endif /* NOSPL */
+             case '&': x = XXECH; break;
+             default:
+               printf("\n?Invalid - %s\n",cmdbuf);
+               x = -2;
+           }
+       }
+       return(dohlp(x));
+#endif /* NOHELP */
+    }
+#ifndef NOHELP
+    if (cx == XXINT)                   /* INTRO */
+      return(hmsga(introtxt));
+#endif /* NOHELP */
+
+    if (cx == XXHAN) {                 /* HANGUP */
+       if ((x = cmcfm()) < 0) return(x);
+#ifndef NODIAL
+       if ((x = mdmhup()) < 1)
+#endif /* NODIAL */
+         x = (tthang() > -1);
+       return(success = x);
+    }
+
+#ifndef NOSPL
+    if (cx == XXGOTO) {                        /* GOTO */
+/* Note, here we don't set SUCCESS/FAILURE flag */
+       if ((y = cmfld("label","",&s,xxstring)) < 0) {
+           if (y == -3) {
+               printf("?Label name required\n");
+               return(-9);
+           } else return(y);
+       }
+       strcpy(lblbuf,s);
+       if ((x = cmcfm()) < 0) return(x);
+       s = lblbuf;
+       return(dogoto(s));
+    }
+#endif /* NOSPL */
+
+#ifndef NOSPL
+/* IF, Extended IF, WHILE */
+    if (cx == XXIF || cx == XXIFX || cx == XXWHI) {
+       return(doif(cx));
+    }
+#endif /* NOSPL */
+
+#ifndef NOSPL
+    if (cx == XXINP || cx == XXREI) {  /* INPUT and REINPUT */
+       y = cmnum("seconds to wait for input","1",10,&x,xxstring);
+       if (y < 0) {
+           return(y);
+       }
+       if (x <= 0) x = 1;
+       if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
+         return(y);
+#ifdef COMMENT
+/*
+  Now it's ok -- null argument means wait for any character.
+*/
+       if (*s == '\0') {
+           printf("?Text required\n");
+           return(-9);
+       }
+#endif /* COMMENT */
+       if (*s == '{') {
+           y = (int)strlen(s);
+           if (s[y-1] == '}') {
+               s[y-1] = NUL;
+               s++;
+           }
+       }
+       if (cx == XXINP) {              /* INPUT */
+           debug(F110,"calling doinput",s,0);
+           success = doinput(x,s);     /* Go try to input the search string */
+       } else {                        /* REINPUT */
+           debug(F110,"xxrei line",s,0);
+           success = doreinp(x,s);
+       }
+       if (intime && !success) {       /* TIMEOUT-ACTION = QUIT? */
+           popclvl();                  /* If so, pop command level. */
+           if (pflag && cmdlvl == 0) {
+               if (cx == XXINP) printf("?Input timed out\n");
+               if (cx == XXREI) printf("?Reinput failed\n");
+           }
+       }
+       return(success);                /* Return do(re)input's return code */
+    }
+#endif /* NOSPL */
+
+#ifndef NOSPL
+    if (cx == XXLBL) {                 /* LABEL */
+       if ((x = cmfld("label","",&s,xxstring)) < 0) {
+           if (x == -3) {
+               printf("?Label name required\n");
+               return(-9);
+           } else return(x);
+       }
+       if ((x = cmcfm()) < 0) return(x);
+       return(0);
+    }
+#endif /* NOSPL */
+
+    if (cx == XXLOG) {                 /* LOG */
+       x = cmkey(logtab,nlog,"What to log","",xxstring);
+       if (x == -3) {
+           printf("?Type of log required\n");
+           return(-9);
+       }
+       if (x < 0) return(x);
+       x = dolog(x);
+       if (x < 0)
+         return(x);
+       else
+         return(success = x);
+    }
+#ifndef NOSCRIPT
+    if (cx == XXLOGI) {                        /* UUCP-style script */
+       if ((x = cmtxt("expect-send expect-send ...","",&s,xxstring)) < 0)
+         return(x);
+#ifdef VMS
+       conres();                       /* For Ctrl-C to work... */
+#endif /* VMS */
+       return(success = dologin(s));   /* Return 1=completed, 0=failed */
+    }
+#endif /* NOSCRIPT */
+    if (cx == XXREC) {                 /* RECEIVE */
+       cmarg2 = "";
+       x = cmofi("Name under which to store the file, or CR","",&s,
+                 xxstring);
+       if ((x == -1) || (x == -2)) return(x);
+       if ((x = cmcfm()) < 0) return(x);
+       strcpy(line,s);
+       cmarg2 = line;
+       debug(F111,"cmofi cmarg2",cmarg2,x);
+       sstate = 'v';
+#ifdef MAC
+       scrcreate();
+#endif /* MAC */
+       if (local) displa = 1;
+       return(0);
+    }
+    if (cx == XXREM) {                 /* REMOTE */
+       x = cmkey(remcmd,nrmt,"Remote Kermit server command","",xxstring);
+       if (x == -3) {
+           printf("?You must specify a command for the remote server\n");
+           return(-9);
+       }
+       return(dormt(x));
+    }
+
+#ifndef NOFRILLS
+    if (cx == XXREN)                   /* RENAME */
+      return(dorenam());
+#endif /* NOFRILLS */
+
+    if (cx == XXSEN || cx == XXMAI) {  /* SEND, MAIL */
+       cmarg = cmarg2 = "";
+       if ((x = cmifi("File(s) to send","",&s,&y,xxstring)) < 0) {
+           if (x == -3) {
+               printf("?A file specification is required\n");
+               return(-9);
+           } else return(x);
+       }
+       nfils = -1;                     /* Files come from internal list. */
+       strcpy(line,s);                 /* Save copy of string just parsed. */
+       strncpy(fspec,s,FSPECL);        /* and here for \v(filespec) */
+       if (cx == XXSEN) {              /* SEND command */
+           debug(F101,"Send: wild","",y);
+           if (y == 0) {
+               if ((x = cmtxt("Name to send it with","",&cmarg2,
+                              xxstring)) < 0)
+                 return(x);
+           } else {
+               if ((x = cmcfm()) < 0) return(x);
+           }
+           cmarg = line;               /* File to send */
+           debug(F110,"Sending:",cmarg,0);
+           if (*cmarg2 != '\0') debug(F110," as:",cmarg2,0);
+       } else {                        /* MAIL */
+#ifndef NOFRILLS
+           if (!atdiso || !atcapr) {   /* Disposition attribute off? */
+               printf("?Disposition Attribute is Off\n");
+               return(-2);
+           }
+           debug(F101,"Mail: wild","",y);
+           *optbuf = NUL;              /* Wipe out any old options */
+           if ((x = cmtxt("Address to mail to","",&s,xxstring)) < 0)
+             return(x);
+           if ((int)strlen(s) == 0) {
+               printf("?Address required\n");
+               return(-9);
+           }
+           strcpy(optbuf,s);
+           if ((int)strlen(optbuf) > 94) { /* Ensure legal size */
+               printf("?Option string too long\n");
+               return(-2);
+           }
+           cmarg = line;               /* File to send */
+           debug(F110,"Mailing:",cmarg,0);
+           debug(F110,"To:",optbuf,0);
+           rmailf = 1;                 /* MAIL modifier flag for SEND */
+#else
+           printf("?Sorry, MAIL feature not configured.\n");
+           return(-2);
+#endif /* NOFRILLS */
+       }
+       sstate = 's';                   /* Set start state to SEND */
+#ifdef MAC
+       scrcreate();
+#endif /* MAC */
+       if (local) {                    /* If in local mode, */
+           displa = 1;                 /* turn on file transfer display */
+#ifdef COMMENT
+/* Redundant -- this is done later in sipkt() */
+           ttflui();                   /* and flush tty input buffer. */
+#endif /* COMMENT */
+       }
+       return(0);
+    }
+#ifndef NOMSEND
+    if (cx == XXMSE) {                 /* MSEND command */
+       nfils = 0;                      /* Like getting a list of */
+       lp = line;                      /* files on the command line */
+       while (1) {
+           char *p;
+           if ((x = cmifi("Names of files to send, separated by spaces","",
+                          &s,&y,xxstring)) < 0) {
+               if (x == -3) {
+                   if (nfils <= 0) {
+                       printf("?A file specification is required\n");
+                       return(-9);
+                   } else break;
+               }
+               return(x);
+           }
+           msfiles[nfils++] = lp;      /* Got one, count it, point to it, */
+           p = lp;                     /* remember pointer, */
+           while (*lp++ = *s++) ;      /* and copy it into buffer */
+           debug(F111,"msfiles",msfiles[nfils-1],nfils-1);
+           if (nfils == 1) *fspec = NUL; /* Take care of \v(filespec) */
+           if (((int)strlen(fspec) + (int)strlen(p) + 1) < FSPECL) {
+               strcat(fspec,p);
+               strcat(fspec," ");
+           }
+       }
+       cmlist = msfiles;               /* Point cmlist to pointer array */
+       cmarg2 = "";                    /* No internal expansion list (yet) */
+       sndsrc = nfils;                 /* Filenames come from cmlist */
+       sstate = 's';                   /* Set start state to SEND */
+#ifdef MAC
+       scrcreate();
+#endif /* MAC */
+       if (local) {                    /* If in local mode, */
+           displa = 1;                 /* turn on file transfer display */
+           ttflui();                   /* and flush tty input buffer. */
+       }
+       return(0);
+    }
+#endif /* NOMSEND */
+
+#ifndef NOSERVER
+    if (cx == XXSER) {                 /* SERVER */
+       if ((x = cmcfm()) < 0) return(x);
+       sstate = 'x';
+#ifdef MAC
+       scrcreate();
+#endif /* MAC */
+       if (local) displa = 1;
+#ifdef AMIGA
+       reqoff();                       /* No DOS requestors while server */
+#endif /* AMIGA */
+    return(0);
+    }
+#endif /* NOSERVER */
+
+    if (cx == XXSET) {                 /* SET command */
+       x = cmkey(prmtab,nprm,"Parameter","",xxstring);
+       if (x == -3) {
+           printf("?You must specify a parameter to set\n");
+           return(-9);
+       }
+       if (x < 0) return(x);
+       /* have to set success separately for each item in doprm()... */
+       /* actually not really, could have just had doprm return 0 or 1 */
+       /* and set success here... */
+       y = doprm(x,0);
+       if (y == -3) {
+           printf("?More fields required\n");
+           return(-9);
+       } else return(y);
+    }
+
+#ifndef NOPUSH
+    if (cx == XXSHE) {                 /* SHELL (system) command */
+       if (cmtxt("System command to execute","",&s,xxstring) < 0)
+         return(-1);
+       conres();                       /* Make console normal  */
+       x = zshcmd(s);
+       concb((char)escape);
+       return(success = x);
+    }
+#endif /* NOPUSH */
+
+#ifndef NOSHOW
+    if (cx == XXSHO) {                 /* SHOW */
+       x = cmkey(shotab,nsho,"","parameters",xxstring);
+       if (x < 0) return(x);
+       return(doshow(x));
+    }
+#endif /* NOSHOW */
+#ifndef MAC
+    if (cx == XXSPA) {                 /* SPACE */
+#ifdef datageneral
+       /* AOS/VS can take an argument after its "space" command. */
+       if ((x = cmtxt("Confirm, or local directory name","",&s,xxstring)) < 0)
+         return(x);
+       if (*s == NUL) xsystem(SPACMD);
+       else {
+           sprintf(line,"space %s",s);
+           xsystem(line);
+       }
+#else
+#ifdef OS2
+       if ((x = cmtxt("Press Enter for current disk,\n\
+ or specify a disk letter like A:","",&s,xxstring)) < 0)
+         return(x);
+       if (*s == NUL) {                /* Current disk */
+           printf(" Free space: %ldK\n", zdskspace(0)/1024L);
+       } else {
+           int drive = toupper(*s);
+           printf(" Drive %c: %ldK free\n", drive, 
+                  zdskspace(drive - 'A' + 1) / 1024L);
+       }
+#else
+#ifdef UNIX
+#ifdef COMMENT
+       if ((x = cmtxt("Confirm for current disk,\n\
+ or specify a disk device or directory","",&s,xxstring)) < 0)
+         return(x);
+#else
+       x = cmdir("Confirm for current disk,\n\
+ or specify a disk device or directory","",&s,xxstring);
+       if (x == -3)
+         s = "";
+       else if (x < 0)
+         return(x);
+       if ((x = cmcfm()) < 0) return(x);
+#endif /* COMMENT */
+       if (*s == NUL) {                /* Current disk */
+           xsystem(SPACMD);
+       } else {                        /* Specified disk */
+           sprintf(line,"%s %s",SPACM2,s);
+           xsystem(line);
+       }
+#else
+       if ((x = cmcfm()) < 0) return(x);
+       xsystem(SPACMD);
+#endif /* UNIX */
+#endif /* OS2 */
+#endif /* datageneral */
+       return(success = 1);            /* Pretend it worked */
+    }
+#endif /* MAC */
+    if (cx == XXSTA) {                 /* STATISTICS */
+       if ((x = cmcfm()) < 0) return(x);
+       return(success = dostat());
+    }
+
+    if (cx == XXSTO || cx == XXEND) {  /* STOP, END, or POP */
+       if ((y = cmnum("exit status code","0",10,&x,xxstring)) < 0)
+         return(y);
+       if ((y = cmtxt("Message to print","",&s,xxstring)) < 0)
+         return(y);
+       if (*s == '{') {                /* Strip any enclosing braces */
+           x = (int)strlen(s);
+           if (s[x-1] == '}') {
+               s[x-1] = NUL;
+               s++;
+           }
+       }
+       if (*s) printf("%s\n",s);
+       if (cx == XXSTO) dostop(); else popclvl(); 
+       return(success = (x == 0));
+    }
+
+    if (cx == XXSUS) {                 /* SUSPEND */
+       if ((y = cmcfm()) < 0) return(y);
+#ifdef NOJC
+       printf("Sorry, this version of Kermit cannot be suspended\n");
+#else
+       stptrap(0);
+#endif /* NOJC */
+       return(0);
+    }
+
+    if (cx == XXTAK) {                 /* TAKE */
+       if (tlevel > MAXTAKE-1) {
+           printf("?Take files nested too deeply\n");
+           return(-2);
+       }
+       if ((y = cmifi("C-Kermit command file","",&s,&x,xxstring)) < 0) { 
+           if (y == -3) {
+               printf("?A file name is required\n");
+               return(-9);
+           } else return(y);
+       }
+       if (x != 0) {
+           printf("?Wildcards not allowed in command file name\n");
+           return(-9);
+       }
+       strcpy(line,s);
+       if ((y = cmcfm()) < 0) return(y);
+       return(success = dotake(line));
+    }
+#ifdef NETCONN
+    if (cx == XXTEL) {                 /* TELNET */
+       if ((y = setlin(XYHOST,0)) < 0) return(y);
+       return (success = (y == 0) ? 0 : doconect());
+    }
+#endif /* NETCONN */
+
+#ifndef NOXMIT
+    if (cx == XXTRA) {                 /* TRANSMIT */
+       if ((x = cmifi("File to transmit","",&s,&y,xxstring)) < 0) {
+           if (x == -3) {
+               printf("?Name of an existing file\n");
+               return(-9);
+           } else return(x);
+       }
+       if (y != 0) {
+           printf("?Only a single file may be transmitted\n");
+           return(-2);
+       }
+       strcpy(line,s);                 /* Save copy of string just parsed. */
+       if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
+       debug(F111,"calling transmit",line,xmitp);
+       return(success = transmit(line,(char)xmitp)); /* Do the command */
+    }
+#endif /* NOXMIT */
+
+#ifndef NOFRILLS
+    if (cx == XXTYP) {                 /* TYPE */
+#ifndef MAC
+       char *tc;
+#endif /* MAC */
+       if ((x = cmifi("File to type","",&s,&y,xxstring)) < 0) {
+           if (x == -3) {
+               printf("?Name of an existing file\n");
+               return(-9);
+           } else return(x);
+       }
+       if (y != 0) {
+           printf("?A single file please\n");
+           return(-2);
+       }
+#ifndef MAC
+       if (!(tc = getenv("CK_TYPE"))) tc = TYPCMD;
+       sprintf(line,"%s %s",tc,s);
+       if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
+       xsystem(line);
+       return(success = 1);
+#else
+       strcpy(line,s);
+       if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
+       return(success = dotype(line));
+#endif /* MAC */
+    }
+#endif /* NOFRILLS */
+
+#ifndef NOFRILLS
+    if (cx == XXTES) {                 /* TEST */
+       /* Fill this in with whatever is being tested... */
+       if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
+
+#ifndef NOSPL
+#ifdef COMMENT
+       { int d, i, j;                  /* Dump all arrays */
+         char c, **p;
+         for (i = 0; i < 27; i++) {
+             p = a_ptr[i];
+             d = a_dim[i];
+             c = (i == 0) ? 64 : i + 96;
+             if (d && p) {
+                 fprintf(stderr,"&%c[%d]\n",c,d);
+                 for (j = 0; j <= d; j++) {
+                     if (p[j]) {
+                         fprintf(stderr,"  &%c[%2d] = [%s]\n",c,j,p[j]);
+                     }
+                 }       
+             }
+         }
+      }
+#else /* Not COMMENT */
+       printf("cmdlvl = %d, tlevel = %d, maclvl = %d\n",cmdlvl,tlevel,maclvl);
+       if (maclvl < 0) {
+           printf("%s\n",
+            "Call me from inside a macro and I'll dump the argument stack");
+           return(0);
+       }
+       printf("Macro level: %d, ARGC = %d\n     ",maclvl,macargc[maclvl]);
+       for (y = 0; y < 10; y++) printf("%7d",y);
+       for (x = 0; x <= maclvl; x++) {
+           printf("\n%2d:  ",x);
+           for (y = 0; y < 10; y++) {
+               s = m_arg[x][y];
+               printf("%7s",s ? s : "(none)");
+           }
+       }
+       printf("\n");
+#endif /* COMMENT */
+#endif /* NOSPL */
+       return(0);
+    }
+#endif /* NOFRILLS */
+
+#ifndef NOCSETS
+    if (cx == XXXLA) {    /* TRANSLATE <ifn> from-cs to-cs <ofn> */
+       int incs, outcs;
+       if ((x = cmifi("File to translate","",&s,&y,xxstring)) < 0) {
+           if (x == -3) {
+               printf("?Name of an existing file\n");
+               return(-9);
+           } else return(x);
+       }
+       if (y != 0) {
+           printf("?A single file please\n");
+           return(-2);
+       }
+       strcpy(line,s);                 /* Save copy of string just parsed. */
+
+       if ((incs = cmkey(fcstab,nfilc,"from character-set","",xxstring)) < 0)
+         return(incs);
+       if ((outcs = cmkey(fcstab,nfilc,"to character-set","",xxstring)) < 0)
+         return(outcs);
+       if ((x = cmofi("output file",CTTNAM,&s,xxstring)) < 0) return(x);
+       strncpy(tmpbuf,s,50);
+       if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
+       return(success = xlate(line,tmpbuf,incs,outcs)); /* Execute it */
+    }
+#endif /* NOCSETS */
+
+    if (cx == XXVER) {                 /* VERSION */
+       if ((y = cmcfm()) < 0) return(y);
+       printf("%s,%s\n Numeric: %ld",versio,ckxsys,vernum);
+       if (verwho) printf("-%d\n",verwho); else printf("\n");
+       return(success = 1);
+    }
+
+#ifndef MAC
+#ifndef NOFRILLS
+    if (cx == XXWHO) {                 /* WHO */
+       char *wc;
+#ifdef datageneral
+        xsystem(WHOCMD);
+#else
+       if ((y = cmtxt("user name","",&s,xxstring)) < 0) return(y);
+       if (!(wc = getenv("CK_WHO"))) wc = WHOCMD;
+       sprintf(line,"%s %s",wc,s);
+       xsystem(line);
+#endif /* datageneral */
+       return(success = 1);
+    }
+#endif /* NOFRILLS */
+#endif /* MAC */
+
+#ifndef NOFRILLS
+    if (cx == XXWRI) {                 /* WRITE */
+       if ((x = cmkey(writab,nwri,"to file or log","",xxstring)) < 0) {
+           if (x == -3) printf("?Write to what?\n");
+           return(x);
+       }
+       if ((y = cmtxt("text","",&s,xxstring)) < 0) return(y);
+       if (*s == '{') {                /* Strip enclosing braces */
+           y = (int)strlen(s);
+           if (s[y-1] == '}') {
+               s[y-1] = NUL;
+               s++;
+           }
+       }
+       switch (x) {
+         case LOGD: y = ZDFILE; break;
+         case LOGP: y = ZPFILE; break;
+         case LOGS: y = ZSFILE; break;
+         case LOGT: y = ZTFILE; break;
+#ifndef NOSPL
+         case LOGW: y = ZWFILE; break;
+#endif /* NOSPL */
+         case LOGX:
+         case LOGE:
+
+#ifndef MAC
+           if (x == LOGE) fprintf(stderr,"%s",s);
+           else
+#endif /* MAC */
+             printf("%s",s);
+           if (
+#ifndef NOSPL
+               cmdlvl == 0
+#else
+               tlevel == -1
+#endif /* NOSPL */
+               )
+#ifndef MAC
+             if (x == LOGE) fprintf(stderr,"\n");
+             else
+#endif /* MAC */
+               printf("\n");
+           return(success = 1);
+         default: return(-2);
+       }
+       if ((x = zsout(y,s)) < 0)
+         printf("?File or log not open\n");
+       return(success = (x == 0) ? 1 : 0);
+    }
+#endif /* NOFRILLS */
+
+    debug(F101,"docmd unk arg","",cx);
+    return(-2);                                /* None of the above. */
+} /* end of docmnd() */
+
+#endif /* NOICP */
diff --git a/usr/src/contrib/kermit-5A.188/ckuusr.h b/usr/src/contrib/kermit-5A.188/ckuusr.h
new file mode 100644 (file)
index 0000000..144c307
--- /dev/null
@@ -0,0 +1,582 @@
+/*  C K U U S R . H  --  Symbol definitions for C-Kermit ckuus*.c modules  */
+/*
+  Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
+  Columbia University Center for Computing Activities.
+  First released January 1985.
+  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
+  York.  Permission is granted to any individual or institution to use this
+  software as long as it is not sold for profit.  This copyright notice must be
+  retained.  This software may not be included in commercial products without
+  written permission of Columbia University.
+*/
+#ifndef CKUUSR_H
+#define CKUUSR_H
+
+#include "ckucmd.h"                    /* Get symbols from command package */
+/* Sizes of things */
+
+#define FSPECL 300                     /* Max length for MSEND/GET string */
+#define VNAML 20                       /* Max length for variable name */
+#define FORDEPTH 10                    /* Maximum depth of nested FOR loops */
+#define GVARS 126                      /* Highest global var allowed */
+#define MAXTAKE 30                     /* Maximum nesting of TAKE files */
+#define MACLEVEL 50                    /* Maximum nesting for macros */
+#define NARGS 10                       /* Max number of macro arguments */
+#define LINBUFSIZ CMDBL+10             /* Size of line[] buffer */
+#define INPBUFSIZ 257                  /* Size of INPUT buffer */
+#define CMDSTKL ( MACLEVEL + MAXTAKE + 2) /* Command stack depth */
+#define MAC_MAX 256                    /* Maximum number of macros */
+#define MSENDMAX 100                   /* Number of filespecs for MSEND */
+
+struct cmdptr {                                /* Command stack structure */
+    int src;                           /* Command Source */
+    int lvl;                           /* Current TAKE or DO level */
+};
+
+struct mtab {                          /* Macro table, like keyword table */
+    char *kwd;                         /* But with pointers for vals */
+    char *mval;                                /* instead of ints. */
+    short flgs;
+};
+
+/* Name of C-Kermit program initialization file. */
+
+#ifdef vms
+#define KERMRC "CKERMIT.INI"
+#else
+#ifdef OS2
+#define KERMRC "ckermit.ini"
+#else
+#ifdef UNIX
+#define KERMRC ".kermrc"
+#else
+#ifdef OSK
+#define KERMRC ".kermrc"
+#else
+#define KERMRC "CKERMIT.INI"
+#endif /* OSK */
+#endif /* UNIX */
+#endif /* OS2 */
+#endif /* vms */
+
+/* Includes */
+
+#ifdef MINIX
+/* why? */
+#include <sys/types.h>
+#endif /* MINIX */
+
+/* Symbols for command source */
+
+#define CMD_KB 0                       /* KeyBoard or standard input */
+#define CMD_TF 1                       /* TAKE command File */
+#define CMD_MD 2                       /* Macro Definition */
+
+/* Top Level Commands */
+/* Values associated with top-level commands must be 0 or greater. */
+#define XXBYE   0      /* BYE */
+#define XXCLE   1      /* CLEAR */
+#define XXCLO   2      /* CLOSE */
+#define XXCON   3      /* CONNECT */
+#define XXCPY   4      /* COPY */
+#define XXCWD   5      /* CWD (Change Working Directory) */
+#define XXDEF  6       /* DEFINE (a command macro) */
+#define XXDEL   7      /* (Local) DELETE */
+#define XXDIR   8      /* (Local) DIRECTORY */
+#define XXDIS   9      /* DISABLE <-- changed from DISCONNECT! */
+#define XXECH  10      /* ECHO */
+#define XXEXI  11      /* EXIT */
+#define XXFIN  12      /* FINISH */
+#define XXGET  13      /* GET */
+#define XXHLP  14      /* HELP */
+#define XXINP  15      /* INPUT */
+#define XXLOC  16      /* LOCAL */
+#define XXLOG  17      /* LOG */
+#define XXMAI  18      /* MAIL */
+#define XXMOU  19      /* (Local) MOUNT */
+#define XXMSG  20      /* (Local) MESSAGE */
+#define XXOUT  21      /* OUTPUT */
+#define XXPAU  22      /* PAUSE */
+#define XXPRI  23      /* (Local) PRINT */
+#define XXQUI  24      /* QUIT */
+#define XXREC  25      /* RECEIVE */
+#define XXREM  26      /* REMOTE */
+#define XXREN  27      /* (Local) RENAME */
+#define XXSEN  28      /* SEND */
+#define XXSER  29      /* SERVER */
+#define XXSET  30      /* SET */
+#define XXSHE  31      /* Command for SHELL */
+#define XXSHO  32      /* SHOW */
+#define XXSPA  33      /* (Local) SPACE */
+#define XXSTA  34      /* STATISTICS */
+#define XXSUB  35      /* (Local) SUBMIT */
+#define XXTAK  36      /* TAKE */
+#define XXTRA  37      /* TRANSMIT */
+#define XXTYP  38      /* (Local) TYPE */
+#define XXWHO  39      /* (Local) WHO */
+#define XXDIAL 40      /* (Local) DIAL */
+#define XXLOGI 41      /* (Local) SCRIPT */
+#define XXCOM  42      /* Comment */
+#define XXHAN  43       /* HANGUP */
+#define XXXLA  44      /* TRANSLATE */
+#define XXIF   45      /* IF */
+#define XXLBL  46       /* label */
+#define XXGOTO 47      /* GOTO */
+#define XXEND  48       /* END */
+#define XXSTO  49       /* STOP */
+#define XXDO   50       /* DO */
+#define XXPWD  51       /* PWD */
+#define XXTES  52       /* TEST */
+#define XXASK  53       /* ASK */
+#define XXASKQ 54       /* ASKQ */
+#define XXASS  55       /* ASSIGN */
+#define XXREI  56       /* REINPUT */
+#define XXINC  57       /* INCREMENT */
+#define XXDEC  59       /* DECREMENT */
+#define XXELS  60       /* ELSE */
+#define XXEXE  61      /* EXECUTE */
+#define XXWAI  62      /* WAIT */
+#define XXVER  63       /* VERSION */
+#define XXENA  64       /* ENABLE */
+#define XXWRI  65       /* WRITE */
+#define XXCLS  66       /* CLS (clear screen) */
+#define XXRET  67      /* RETURN */
+#define XXOPE  68       /* OPEN */
+#define XXREA  69      /* READ */
+#define XXON   70       /* ON */
+#define XXDCL  71       /* DECLARE */
+#define XXBEG  72       /* BEGIN (not used) */
+#define XXFOR  72       /* FOR */
+#define XXWHI  73       /* WHILE */
+#define XXIFX  74       /* Extended IF */
+#define XXCMS  75       /* SEND from command output (not yet) */
+#define XXCMR  76       /* RECEIVE to a command's input (not yet) */
+#define XXCMG  77       /* GET to a command's input (not yet) */
+#define XXSUS  78       /* SUSPEND */
+#define XXERR  79       /* ERROR */
+#define XXMSE  80       /* MSEND */
+#define XXBUG  81       /* BUG */
+#define XXPAD  82       /* PAD (as in X.25 PAD) SUNX25 */
+#define XXRED  83       /* REDIAL */
+#define XXGTA  84      /* _getargs (invisible internal) */
+#define XXPTA  85      /* _putargs (invisible internal) */
+#define XXGOK  86       /* GETOK - Ask for YES/NO */
+#define XXTEL  87      /* TELNET */
+#define XXASX  88      /* _ASSIGN (evaluates var name) */
+#define XXDFX  89      /* _DEFINE (evaluates var name) */
+#define XXPNG  90      /* PING (for TCP/IP) */
+#define XXINT  91       /* INTRODUCTION */
+#define XXCHK  92      /* CHECK (a feature) */
+#define XXMSL  93       /* MSLEEP, MPAUSE (millisecond sleep) */
+
+/* IF conditions */
+
+#define  XXIFCO 0       /* IF COUNT */
+#define  XXIFER 1       /* IF ERRORLEVEL */
+#define  XXIFEX 2       /* IF EXIST */
+#define  XXIFFA 3       /* IF FAILURE */
+#define  XXIFSU 4       /* IF SUCCESS */
+#define  XXIFNO 5       /* IF NOT */
+#define  XXIFDE 6       /* IF DEFINED */
+#define  XXIFEQ 7      /* IF EQUAL (strings) */
+#define  XXIFAE 8       /* IF = (numbers) */
+#define  XXIFLT 9       /* IF < (numbers) */
+#define  XXIFGT 10      /* IF > (numbers) */
+#define  XXIFLL 11      /* IF Lexically Less Than (strings) */
+#define  XXIFLG 12      /* IF Lexically Greater Than (strings) */
+#define  XXIFEO 13      /* IF EOF (READ file) */
+#define  XXIFBG 14      /* IF BACKGROUND */
+#define  XXIFNU 15     /* IF NUMERIC */
+#define  XXIFFG 16      /* IF FOREGROUND */
+
+/* SET parameters */
+#define XYBREA  0      /* BREAK simulation */
+#define XYCHKT  1      /* Block check type */
+#define XYDEBU  2      /* Debugging */
+#define XYDELA  3      /* Delay */
+#define XYDUPL  4      /* Duplex */
+#define XYEOL   5      /* End-Of-Line (packet terminator) */
+#define XYESC   6      /* Escape character */
+#define XYFILE  7      /* File Parameters */
+                       /* (this space available) */
+#define XYFLOW  9      /* Flow Control */
+#define XYHAND 10      /* Handshake */
+#define XYIFD  11      /* Incomplete File Disposition */
+#define XYIMAG 12      /* "Image Mode" */
+#define XYINPU 13      /* INPUT command parameters */
+#define XYLEN  14      /* Maximum packet length to send */
+#define XYLINE 15      /* Communication line to use */
+#define XYLOG  16      /* Log file */
+#define XYMARK 17      /* Start of Packet mark */
+#define XYNPAD 18      /* Amount of padding */
+#define XYPADC 19      /* Pad character */
+#define XYPARI 20      /* Parity */
+#define XYPAUS 21      /* Interpacket pause */
+#define XYPROM 22      /* Program prompt string */
+#define XYQBIN 23      /* 8th-bit prefix */
+#define XYQCTL 24      /* Control character prefix */
+#define XYREPT 25      /* Repeat count prefix */
+#define XYRETR 26      /* Retry limit */
+#define XYSPEE 27      /* Line speed (baud rate) */
+#define XYTACH 28      /* Character to be doubled */
+#define XYTIMO 29      /* Timeout interval */
+#define XYMODM 30      /* Modem type */
+#define XYSEND 31      /* SEND parameters, used with some of the above */
+#define XYRECV 32      /* RECEIVE parameters, ditto */
+#define XYTERM 33      /* Terminal parameters */
+#define   XYTBYT 0      /*  Terminal Bytesize (7 or 8) */
+#define   XYTTYP 1      /*  Terminal Type */
+#define     TT_NONE  0 /*    NONE */
+#define     TT_VT52  1 /*    DEC VT-52  */
+#define     TT_VT100 2 /*    DEC VT-100 */
+#define     TT_VT102 3 /*    DEC VT-102 */
+#define     TT_VT220 4 /*    DEC VT-220 */
+#define     TT_VT320 5 /*    DEC VT-320 */
+#define     TT_TEK40 6 /*    Tektronix 401x */
+#define   XYTCS  2      /*  Terminal Character Set */
+#define   XYTSO  3     /*  Terminal Shift-In/Shift-Out */
+#define   XYTNL  4      /*  Terminal newline mode */
+#define   XYTCOL 5      /*  Terminal colors */
+#define   XYTEC  6     /*  Terminal echo = duplex = local-echo */
+#define   XYTCUR 7     /*  Terminal cursor */
+#define   XYTARR 8     /*  Terminal arrow-key mode */
+#define   XYTKPD 9      /*  Terminal keypad mode */
+#define   XYTWRP 10     /*  Terminal wrap */
+#define   XYTCRD 11    /*  Terminal CR-display */
+#define XYATTR 34       /* Attribute packets */
+#define XYSERV 35      /* Server parameters */
+#define   XYSERT 0      /*  Server timeout   */
+#define   XYSERD 1     /*  Server display   */
+#define XYWIND 36       /* Window size */
+#define XYXFER 37       /* Transfer */
+#define XYLANG 38       /* Language */
+#define XYCOUN 39       /* Count */
+#define XYTAKE 40       /* Take */ 
+#define XYUNCS 41       /* Unknown-character-set */
+#define XYKEY  42       /* Key */
+#define XYMACR 43       /* Macro */
+#define XYHOST 44       /* Hostname on network */
+#define XYNET  45       /* Type of Network */
+#define XYCARR 46      /* Carrier */
+#define XYXMIT 47       /* Transmit */
+#define XYDIAL 48       /* Dial options */
+#define  XYDHUP  0     /*   Dial Hangup */
+#define  XYDINI  1      /*   Dial Initialization string */
+#define  XYDKSP  2      /*   Dial Kermit-Spoof */
+#define  XYDTMO  3      /*   Dial Timeout */
+#define  XYDDPY  4      /*   Dial Display */
+#define  XYDSPD  5      /*   Dial Speed matching */
+#define  XYDMNP  6     /*   Dial MNP negotiation enabled */
+#define  XYDV32  7     /*   Dial V.32 mode enabled */
+#define  XYDV42  8     /*   Dial V.42 mode enabled */
+#define  XYDV42B 9     /*   Dial V.42bis mode enabled */
+#define  XYDDIR 10     /*   Dial directory */
+#define  XYDDIA 11     /*   Dial dial-command */
+#define  XYDMHU 12     /*   Dial modem-hangup */
+#define  XYDNPR 13      /*   Dial number-prefix */
+#define XYSESS 49       /* SET SESSION options */
+#define XYBUF  50       /* Buffer length */
+#define XYBACK 51      /* Background */
+#define XYDFLT 52       /* Default */
+#define XYDOUB 53      /* Double */
+#define XYCMD  54       /* Command */
+#define XYCASE 55       /* Case */
+#define XYCOMP 56       /* Compression */
+#define XYX25  57       /* X.25 parameter (SUNX25) */
+#define XYPAD  58       /* X.3 PAD parameter (SUNX25) */
+#define XYWILD 59       /* Wildcard expansion method */
+#define XYSUSP 60       /* Suspend */
+#define XYMAIL 61      /* Mail-Command */
+#define XYPRIN 62      /* Print-Command */
+#define XYQUIE 63      /* Quiet */
+#define XYLCLE 64      /* Local-echo */
+#define XYSCRI 65      /* SCRIPT command paramaters */
+#define XYMSGS 66       /* MESSAGEs ON/OFF */
+#define XYTEL  67       /* TELNET parameters */
+#define  CK_TN_EC 0    /*  TELNET ECHO */
+#define  CK_TN_TT 1    /*  TELNET TERMINAL-TYPE */
+#define  CK_TN_NL 2     /*  TELNET NEWLINE-MODE */
+
+/* #ifdef SUNX25 */
+/* PAD command parameters */
+
+#define XYPADL 0        /* clear virtual call */
+#define XYPADS 1        /* status of virtual call */
+#define XYPADR 2        /* reset of virtual call */
+#define XYPADI 3        /* send an interrupt packet */
+
+/* Used with XYX25... */
+#define XYUDAT 0       /* X.25 call user data */
+#define XYCLOS 1       /* X.25 closed user group call */
+#define XYREVC 2       /* X.25 reverse charge call */
+/* #endif */ /* SUNX25 */
+
+/* SHOW command symbols */
+
+#define SHPAR 0                                /* Parameters */
+#define SHVER 1                                /* Versions */
+#define SHCOM 2                                /* Communications */
+#define SHPRO 3                                /* Protocol */
+#define SHFIL 4                                /* File */
+#define SHLNG 5                                /* Language */
+#define SHCOU 6                                /* Count */
+#define SHMAC 7                                /* Macros */
+#define SHKEY 8                                /* Key */
+#define SHSCR 9                                /* Scripts */
+#define SHSPD 10                       /* Speed */
+#define SHSTA 11                       /* Status */
+#define SHSER 12                       /* Server */
+#define SHXMI 13                       /* Transmit */
+#define SHATT 14                       /* Attributes */
+#define SHMOD 15                       /* Modem */
+#define SHDFLT 16                      /* Default (as in VMS) */
+#define SHVAR 17                       /* Show global variables */
+#define SHARG 18                       /* Show macro arguments */
+#define SHARR 19                       /* Show arrays */
+#define SHBUI 20                       /* Show builtin variables */
+#define SHFUN 21                       /* Show functions */
+#define SHPAD 22                       /* Show (X.25) PAD */
+#define SHTER 23                       /* Show terminal settings */
+#define SHESC 24                       /* Show escape character */
+#define SHDIA 25                       /* Show DIAL parameters */
+#define SHNET 26                       /* Show network parameters */
+#define SHLBL 27                       /* Show VMS labeled file parameters */
+#define SHSTK 28                       /* Show stack, MAC debugging */
+#define SHCSE 29                       /* Show character sets */
+#define SHFEA 30                       /* Show features */
+
+/* REMOTE command symbols */
+#define XZCPY  0       /* Copy */
+#define XZCWD  1       /* Change Working Directory */
+#define XZDEL  2       /* Delete */
+#define XZDIR  3       /* Directory */
+#define XZHLP  4       /* Help */
+#define XZHOS  5       /* Host */
+#define XZKER  6       /* Kermit */
+#define XZLGI  7       /* Login */
+#define XZLGO  8       /* Logout */
+#define XZMAI  9       /* Mail <-- wrong, this should be top-level */
+#define XZMOU 10       /* Mount */
+#define XZMSG 11       /* Message */
+#define XZPRI 12       /* Print */
+#define XZREN 13       /* Rename */
+#define XZSET 14       /* Set */
+#define XZSPA 15       /* Space */
+#define XZSUB 16       /* Submit */
+#define XZTYP 17       /* Type */
+#define XZWHO 18       /* Who */
+/* SET INPUT command parameters */
+
+#define IN_DEF  0                      /* Default timeout */
+#define IN_TIM  1                      /* Timeout action */
+#define IN_CAS  2                      /* Case (matching) */
+#define IN_ECH  3                      /* Echo */
+#define IN_SIL  4                      /* Silence */
+
+/* ENABLE/DISABLE command parameters */
+
+#define EN_ALL  0                      /* All */
+#define EN_CWD  1                      /* CD/CWD */
+#define EN_DIR  2                      /* Directory */
+#define EN_FIN  3                      /* FINISH */
+#define EN_GET  4                      /* Get */
+#define EN_HOS  5                      /* Host command */
+#define EN_KER  6                      /* Kermit command */
+#define EN_LOG  7                      /* Login */
+#define EN_SEN  8                      /* Send */
+#define EN_SET  9                      /* Set */
+#define EN_SPA 10                      /* Space */
+#define EN_TYP 11                      /* Type */
+#define EN_WHO 12                      /* Who/Finger */
+#define EN_DEL 13                      /* Delete */
+#define EN_BYE 14                      /* BYE (as opposed to FINISH) */
+
+/* Symbols for logs */
+#define LOGD 0         /* Debugging */
+#define LOGP 1          /* Packets */
+#define LOGS 2          /* Session */
+#define LOGT 3          /* Transaction */
+#define LOGX 4          /* Screen */
+#define LOGR 5         /* The "OPEN read file */
+#define LOGW 6          /* The "OPEN" write/append file */
+#define LOGE 7         /* Error (e.g. stderr) */
+
+/* Symbols for builtin variables */
+
+#define VN_ARGC 0                      /* ARGC */
+#define VN_COUN 1                      /* COUNT */
+#define VN_DATE 2                      /* DATE */
+#define VN_DIRE 3                      /* DIRECTORY */
+#define VN_ERRO 4                      /* ERRORLEVEL */
+#define VN_TIME 5                      /* TIME */
+#define VN_VERS 6                      /* VERSION */
+#define VN_IBUF 7                      /* INPUT buffer */
+#define VN_SUCC 8                      /* SUCCESS flag */
+#define VN_LINE 9                      /* LINE */
+#define VN_ARGS 10                     /* Program command-line arg count */
+#define VN_SYST 11                     /* System type */
+#define VN_SYSV 12                     /* System version */
+#define VN_RET  13                     /* RETURN value */
+#define VN_FILE 14                     /* Most recent filespec */
+#define VN_NDAT 15                     /* Numeric date yyyy/mm/dd */
+#define VN_HOME 16                     /* Home directory */
+#define VN_SPEE 17                     /* Transmission speed */
+#define VN_HOST 18                     /* Host name */
+#define VN_TTYF 19                     /* TTY file descriptor (UNIX only) */
+#define VN_PROG 20                     /* Program name */
+#define VN_NTIM 21                     /* NTIME */
+#define VN_FFC  22                     /* Characters in last file xferred */
+#define VN_TFC  23                     /* Chars in last file group xferred */
+#define VN_CPU  24                     /* CPU type */
+#define VN_CMDL 25                     /* Command level */
+#define VN_DAY  26                      /* Day of week, string */
+#define VN_NDAY 27                      /* Day of week, numeric */
+#define VN_LCL  28                     /* Local (vs) remote mode */
+#define VN_CMDS 29                     /* Command source */
+#define VN_CMDF 30                     /* Command file name */
+#define VN_MAC  31                     /* Macro name */
+#define VN_EXIT 32                     /* Exit status */
+#define VN_ICHR 33                     /* INPUT character */
+#define VN_ICNT 34                     /* INPUT count */
+
+/* Symbols for builtin functions */
+
+#define FNARGS 6                       /* Maximum number of function args */
+
+#define FN_IND 0                       /* Index (of string 1 in string 2) */
+#define FN_LEN 1                       /* Length (of string) */
+#define FN_LIT 2                       /* Literal (don't expand the string) */
+#define FN_LOW 3                       /* Lower (convert to lowercase) */
+#define FN_MAX 4                       /* Max (maximum) */
+#define FN_MIN 5                       /* Min (minimum) */
+#define FN_MOD 6                       /* Mod (modulus) */
+#define FN_EVA 7                       /* Eval (evaluate arith expression) */
+#define FN_SUB 8                       /* Substr (substring) */
+#define FN_UPP 9                       /* Upper (convert to uppercase) */
+#define FN_REV 10                      /* Reverse (a string) */
+#define FN_REP 11                      /* Repeat (a string) */
+#define FN_EXE 12                      /* Execute (a macro) */
+#define FN_VAL 13                      /* Return value (of a macro) */
+#define FN_LPA 14                      /* LPAD (left pad) */
+#define FN_RPA 15                      /* RPAD (right pad) */
+#define FN_DEF 16                      /* Definition of a macro, unexpanded */
+#define FN_CON 17                      /* Contents of a variable, ditto */
+#define FN_FIL 18                       /* File list */
+#define FN_FC  19                      /* File count */
+#define FN_CHR 20                      /* Character (like BASIC CHR$()) */
+#define FN_RIG 21                      /* Right (like BASIC RIGHT$()) */
+#define FN_COD 22                      /* Code value of character */
+
+/* ANSI-style prototypes for user interface functions */
+
+_PROTOTYP( int parser, ( int ) );
+_PROTOTYP( int xxstring, (char *, char **, int *) );
+_PROTOTYP( int yystring, (char *, char **) );
+_PROTOTYP( int xxstrcmp, (char *, char *, int) );
+_PROTOTYP( int xxout, (char) );
+_PROTOTYP( int getncm, (char *, int) );
+_PROTOTYP( int getnct, (char *, int) );
+_PROTOTYP( VOID bgchk, (void) );
+_PROTOTYP( char * fneval, (char *, char * [], int ) );
+_PROTOTYP( char * nvlook, (char *) );
+_PROTOTYP( char * arrayval, (int, int) );
+_PROTOTYP( int arraynam, (char *, int *, int *) );
+_PROTOTYP( char * bldlen, (char *, char *) );
+_PROTOTYP( int chkarray, (int, int) );
+_PROTOTYP( int dclarray, (char, int) );
+_PROTOTYP( int parsevar, (char *, int *, int *) );
+_PROTOTYP( int macini, (void) );
+_PROTOTYP( VOID initmac, (void) );
+_PROTOTYP( int delmac, (char *) );
+_PROTOTYP( int addmac, (char *, char *) );
+_PROTOTYP( int addmmac, (char *, char *[]) );
+_PROTOTYP( int dobug, (void) );
+_PROTOTYP( int docd, (void) );
+_PROTOTYP( int doclslog, (int) );
+_PROTOTYP( int docmd, (int) );
+_PROTOTYP( int doconect, (void) );
+_PROTOTYP( int dodo, (int, char *) );
+_PROTOTYP( int doenable, (int, int) );
+_PROTOTYP( int doget, (void) );
+_PROTOTYP( int dogoto, (char *) );
+_PROTOTYP( int dohlp, (int) );
+_PROTOTYP( int dohrmt, (int) );
+_PROTOTYP( int doif, (int) );
+_PROTOTYP( int doinput, (int, char *) );
+_PROTOTYP( int doreinp, (int, char *) );
+_PROTOTYP( int dolog, (int) );
+_PROTOTYP( int dologin, (char *) );
+_PROTOTYP( int doopen, (void) );
+_PROTOTYP( int dooutput, (char *) );
+_PROTOTYP( int doprm, (int, int) );
+_PROTOTYP( int doreturn, (char *) );
+_PROTOTYP( int dormt, (int) );
+_PROTOTYP( int doshow, (int) );
+_PROTOTYP( int doshodial, (void) );
+_PROTOTYP( int dostat, (void) );
+_PROTOTYP( int dostop, (void) );
+_PROTOTYP( int dotype, (char *) );
+_PROTOTYP( int transmit, (char *, char) );
+_PROTOTYP( int xlate, (char *, char *, int, int) );
+_PROTOTYP( int litcmd, (char **, char **) );
+_PROTOTYP( int incvar, (char *, int, int, int *) );
+_PROTOTYP( int ckdial, (char *) );
+_PROTOTYP( char * getdws, (int) );
+_PROTOTYP( char * getdcs, (int) );
+_PROTOTYP( int hmsg, (char *) );
+_PROTOTYP( int hmsga, (char * []) );
+_PROTOTYP( int mlook, (struct mtab [], char *, int) );
+_PROTOTYP( int mxlook, (struct mtab [], char *, int) );
+_PROTOTYP( VOID prtopt, (char *) );
+_PROTOTYP( CHAR rfilop, (char *, char) );
+_PROTOTYP( int setcc, (int *, int, int) );
+_PROTOTYP( int setnum, (int *, int, int, int) );
+_PROTOTYP( int seton, (int *) );
+_PROTOTYP( VOID shmdmlin, (void) );
+_PROTOTYP( int shoatt, (void) );
+_PROTOTYP( VOID shocharset, (void) );
+_PROTOTYP( int shomac, (char *, char *) );
+_PROTOTYP( VOID shopar, (void) );
+_PROTOTYP( VOID shoparc, (void) );
+_PROTOTYP( VOID shoparc, (void) );
+_PROTOTYP( VOID shoparf, (void) );
+_PROTOTYP( VOID shoparp, (void) );
+#ifndef NOCSETS
+_PROTOTYP( VOID shoparl, (void) );
+#endif /* NOCSETS */
+_PROTOTYP( VOID shodial, (void) );
+_PROTOTYP( VOID shomdm, (void) );
+_PROTOTYP( VOID shonet, (void) );
+_PROTOTYP( VOID shover, (void) );
+_PROTOTYP( int pktopn, (char *,int) );
+_PROTOTYP( int traopn, (char *,int) );
+_PROTOTYP( int sesopn, (char *,int) );
+_PROTOTYP( int debopn, (char *,int) );
+_PROTOTYP( char * parnam, (char) );
+_PROTOTYP( int popclvl, (void) );
+_PROTOTYP( int varval, (char *, int *) );
+_PROTOTYP( char * evala, (char *) );
+_PROTOTYP( int setat, (int) );
+_PROTOTYP( int setinp, (void) );
+_PROTOTYP( int setlin, (int, int) );
+_PROTOTYP( int setdial, (void) );
+_PROTOTYP( int setfil, (int) );
+_PROTOTYP( int settrm, (void) );
+_PROTOTYP( int setsr, (int, int) );
+_PROTOTYP( int setxmit, (void) );
+_PROTOTYP( int set_key, (void) );
+_PROTOTYP( int dochk, (void) );
+_PROTOTYP( char *ludial, (char *, FILE *) );
+_PROTOTYP( VOID xwords, (char *, int, char *[]) );
+_PROTOTYP( VOID shotcs, (int, int) );
+_PROTOTYP( char *hhmmss, (long x) );
+#endif /* CKUUSR_H */
+
+/* End of ckuusr.h */