applied 030_fix-if-else.patch
authorIan Beckwith <ianb@erislabs.net>
Wed, 12 May 2010 00:20:05 +0000 (01:20 +0100)
committerIan Beckwith <ianb@erislabs.net>
Wed, 12 May 2010 00:20:05 +0000 (01:20 +0100)
.pc/030_fix-if-else.patch/.timestamp [new file with mode: 0644]
.pc/030_fix-if-else.patch/ckuus6.c [new file with mode: 0644]
.pc/030_fix-if-else.patch/ckuusr.c [new file with mode: 0644]
.pc/applied-patches
ckuus6.c
ckuusr.c

diff --git a/.pc/030_fix-if-else.patch/.timestamp b/.pc/030_fix-if-else.patch/.timestamp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/.pc/030_fix-if-else.patch/ckuus6.c b/.pc/030_fix-if-else.patch/ckuus6.c
new file mode 100644 (file)
index 0000000..5dcd828
--- /dev/null
@@ -0,0 +1,10878 @@
+#include "ckcsym.h"
+#ifndef NOICP
+
+/*  C K U U S 6 --  "User Interface" for Unix Kermit (Part 6)  */
+
+/*
+  Authors:
+    Frank da Cruz <fdc@columbia.edu>,
+      The Kermit Project, Columbia University, New York City
+    Jeffrey E Altman <jaltman@secure-endpoints.com>
+      Secure Endpoints Inc., New York City
+
+  Copyright (C) 1985, 2004,
+    Trustees of Columbia University in the City of New York.
+    All rights reserved.  See the C-Kermit COPYING.TXT file or the
+    copyright text in the ckcmai.c module for disclaimer and permissions.
+*/
+
+/* Includes */
+
+#include "ckcdeb.h"
+#include "ckcasc.h"
+#include "ckcker.h"
+#include "ckuusr.h"
+#include "ckcxla.h"
+#include "ckcnet.h"                     /* Network symbols */
+#include <signal.h>
+
+#ifdef VMS
+#ifndef TCPSOCKET
+#include <errno.h>
+#endif /* TCPSOCKET */
+#endif /* VMS */
+
+#ifdef datageneral
+#define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
+#endif /* datageneral */
+
+#ifdef QNX6
+#define readblock kreadblock
+#endif /* QNX6 */
+
+/* External Kermit Variables, see ckmain.c for description. */
+
+extern xx_strp xxstring;
+
+extern int local, xitsta, binary, parity, escape, flow, cmd_rows, turn,
+  turnch, duplex, ckxech, seslog, dfloc, cnflg, tlevel, pflag, msgflg, mdmtyp,
+  zincnt, quiet, repars, techo, network, nzxopts, what, filepeek, recursive;
+
+extern int xaskmore, tt_rows, tt_cols, cmd_cols, g_matchdot, diractive,
+  xcmdsrc, nscanfile, reliable, nolinks;
+
+#ifdef VMSORUNIX
+extern int zgfs_dir, zgfs_link;
+#endif /* VMSORUNIX */
+
+#ifdef CK_IFRO
+  extern int remonly;
+#endif /* CK_IFRO */
+
+#ifdef OS2
+extern int StartedFromDialer ;
+extern int vmode;
+extern int k95stdout;
+#ifndef NT
+#define INCL_NOPM
+#define INCL_VIO                        /* Needed for ckocon.h */
+#include <os2.h>
+#undef COMMENT
+#else
+#define APIRET ULONG
+#include <windows.h>
+#include <tapi.h>
+#include "ckntap.h"
+#endif /* NT */
+#include "ckocon.h"
+#endif /* OS2 */
+
+extern long vernum, speed;
+extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv;
+extern char *dialv, *loginv, *for_def[], *whil_def[], *xif_def[], *sw_def[];
+extern char *foz_def[];
+extern char *ckxsys, *ckzsys;
+#ifndef OS2
+extern char *DIRCMD;
+#ifndef UNIX
+extern char *DELCMD;
+#endif /* UNIX */
+#endif /* OS2 */
+extern char ttname[], filnam[];
+extern CHAR sstate, feol;
+extern char *zinptr;
+
+#ifdef UNIX
+extern char ** mtchs;                   /* zxpand() file list */
+#endif /* UNIX */
+
+#ifndef NOXFER
+extern int oopts, omode, oname, opath;  /* O-Packet options */
+
+extern int stdinf, sndsrc, size, rpsiz, urpsiz, fncnv, fnrpath, displa,
+  stdouf, isguest, pktlog, nfils, keep, maxrps, fblksiz, frecl, frecfm,
+  atcapr, atdiso, spsizf, spsiz, spsizr, spmax, wslotr, prefixing,
+  fncact, fnspath, nprotos, g_proto, g_urpsiz, g_spsizf,
+  g_spsiz, g_spsizr, g_spmax, g_wslotr, g_prefixing, g_fncact, g_fncnv,
+  g_fnspath, g_fnrpath, xfrxla, g_xfrxla;
+
+extern char *cmarg, *cmarg2;
+
+#ifndef NOMSEND                         /* Multiple SEND */
+extern char *msfiles[];
+#endif /* NOMSEND */
+extern char fspec[];                    /* Most recent filespec */
+extern int fspeclen;
+
+#ifdef CK_TMPDIR
+extern int f_tmpdir;                    /* Directory changed temporarily */
+extern char savdir[];                   /* For saving current directory */
+#endif /* CK_TMPDIR */
+
+extern struct keytab protos[];          /* File transfer protocols */
+extern struct ck_p ptab[NPROTOS];
+#endif /* NOXFER */
+
+#ifdef DCMDBUF                          /* Declarations from cmd package */
+extern char *cmdbuf, *atmbuf;           /* Command buffers */
+#else
+extern char cmdbuf[], atmbuf[];         /* Command buffers */
+#endif /* DCMDBUF */
+
+extern int nopush;
+
+#ifndef NOSPL
+int askflag = 0;                        /* ASK-class command active */
+extern char **a_ptr[];
+extern int a_dim[];
+extern char **m_xarg[];
+extern int n_xarg[];
+extern struct mtab *mactab;
+extern int nmac;
+extern long ck_alarm;
+extern char alrm_date[], alrm_time[];
+extern int x_ifnum;
+#endif /* NOSPL */
+
+extern int inserver;                    /* I am IKSD */
+extern int backgrd;                     /* Kermit executing in background */
+extern char psave[];                    /* For saving & restoring prompt */
+extern char *tp;                        /* Temporary buffer */
+
+int readblock = 4096;                   /* READ buffer size */
+CHAR * readbuf = NULL;                  /* Pointer to read buffer */
+int readsize = 0;                       /* Number of chars actually read */
+int getcmd = 0;                         /* GET-class command was given */
+
+extern int zchkod, zchkid;
+
+struct keytab deltab[] = {              /* DELETE Command Options */
+    { "/all",           DEL_ALL,  CM_INV },
+    { "/after",         DEL_AFT,  CM_ARG },
+    { "/ask",           DEL_ASK,  0 },
+    { "/before",        DEL_BEF,  CM_ARG },
+    { "/directories",   DEL_DIR,  0 },
+    { "/dotfiles",      DEL_DOT,  0 },
+    { "/except",        DEL_EXC,  CM_ARG },
+    { "/heading",       DEL_HDG,  0 },
+    { "/l",             DEL_LIS,  CM_INV|CM_ABR },
+    { "/larger-than",   DEL_LAR,  CM_ARG },
+    { "/list",          DEL_LIS,  0 },
+    { "/log",           DEL_LIS,  CM_INV },
+    { "/noask",         DEL_NAS,  0 },
+    { "/nodotfiles",    DEL_NOD,  0 },
+    { "/noheading",     DEL_NOH,  0 },
+    { "/nol",           DEL_NOL,  CM_INV|CM_ABR },
+    { "/nolist",        DEL_NOL,  0 },
+    { "/nolog",         DEL_NOL,  CM_INV },
+    { "/nopage",        DEL_NOP,  0 },
+    { "/not-after",     DEL_NAF,  CM_ARG },
+    { "/not-before",    DEL_NBF,  CM_ARG },
+    { "/not-since",     DEL_NAF,  CM_INV|CM_ARG },
+    { "/page",          DEL_PAG,  0 },
+    { "/quiet",         DEL_QUI,  CM_INV },
+    { "/recursive",     DEL_REC,  0 },
+    { "/simulate",      DEL_SIM,  0 },
+    { "/since",         DEL_AFT,  CM_ARG|CM_INV },
+    { "/smaller-than",  DEL_SMA,  CM_ARG },
+    { "/summary",       DEL_SUM,  0 },
+    { "/tree",          DEL_ALL,  0 },
+    { "/type",          DEL_TYP,  CM_ARG },
+    { "/verbose",       DEL_VRB,  CM_INV }
+};
+int ndeltab = sizeof(deltab)/sizeof(struct keytab);
+
+/* /QUIET-/VERBOSE (/LIST-/NOLIST) (/LOG-/NOLOG) table */
+
+struct keytab qvswtab[] = {
+    { "/l",           DEL_LIS,  CM_INV|CM_ABR },
+    { "/list",        DEL_LIS,  0 },
+    { "/log",         DEL_LIS,  CM_INV },
+    { "/nol",         DEL_NOL,  CM_INV|CM_ABR },
+    { "/nolist",      DEL_NOL,  0 },
+    { "/nolog",       DEL_NOL,  CM_INV },
+    { "/quiet",       DEL_QUI,  CM_INV },
+    { "/verbose",     DEL_VRB,  CM_INV }
+};
+int nqvswtab = sizeof(qvswtab)/sizeof(struct keytab);
+
+struct keytab copytab[] = {
+    { "/append",      998,      0 },
+#ifndef NOSPL
+    { "/fromb64",     997,      0 },
+#endif /* NOSPL */
+    { "/l",           DEL_LIS,  CM_INV|CM_ABR },
+    { "/list",        DEL_LIS,  0 },
+    { "/log",         DEL_LIS,  CM_INV },
+    { "/nol",         DEL_NOL,  CM_INV|CM_ABR },
+    { "/nolist",      DEL_NOL,  0 },
+    { "/nolog",       DEL_NOL,  CM_INV },
+    { "/quiet",       DEL_QUI,  CM_INV },
+    { "/swap-bytes",  999,      0 },
+#ifndef NOSPL
+    { "/tob64",       996,      0 },
+#endif /* NOSPL */
+    { "/verbose",     DEL_VRB,  CM_INV }
+};
+int ncopytab = sizeof(copytab)/sizeof(struct keytab);
+
+#ifndef NOXFER
+static struct keytab gettab[] = {       /* GET options */
+    { "/as-name",         SND_ASN, CM_ARG },
+    { "/binary",          SND_BIN, 0 },
+#ifdef CALIBRATE
+    { "/calibrate",       SND_CAL, CM_INV },
+#endif /* CALIBRATE */
+#ifdef PIPESEND
+    { "/command",         SND_CMD, CM_PSH },
+#endif /* PIPESEND */
+    { "/delete",          SND_DEL, 0 },
+    { "/except",          SND_EXC, CM_ARG },
+    { "/filenames",       SND_NAM, CM_ARG },
+#ifdef PIPESEND
+    { "/filter",          SND_FLT, CM_ARG|CM_PSH },
+#endif /* PIPESEND */
+#ifdef VMS
+    { "/image",           SND_IMG, 0 },
+    { "/labeled",         SND_LBL, 0 },
+#else
+    { "/image",           SND_BIN, CM_INV },
+#endif /* VMS */
+#ifdef CK_TMPDIR
+    { "/move-to",         SND_MOV, CM_ARG },
+#endif /* CK_TMPDIR */
+    { "/pathnames",       SND_PTH, CM_ARG },
+    { "/pipes",           SND_PIP, CM_ARG|CM_PSH },
+    { "/quiet",           SND_SHH, 0 },
+#ifdef CK_RESEND
+    { "/recover",         SND_RES, 0 },
+#endif /* CK_RESEND */
+    { "/recursive",       SND_REC, 0 },
+    { "/rename-to",       SND_REN, CM_ARG },
+#ifdef COMMENT
+    { "/smaller-than",    SND_SMA, CM_ARG },
+#endif /* COMMENT */
+    { "/subdirectories",  SND_REC, CM_INV },
+    { "/text",            SND_TXT, 0 },
+    { "/transparent",     SND_XPA, 0 }
+};
+#define NGETTAB sizeof(gettab)/sizeof(struct keytab)
+static int ngettab = NGETTAB;
+
+static struct keytab rcvtab[] = {       /* RECEIVE options */
+    { "/as-name",         SND_ASN, CM_ARG },
+    { "/binary",          SND_BIN, 0 },
+#ifdef CALIBRATE
+    { "/calibrate",       SND_CAL, CM_INV },
+#endif /* CALIBRATE */
+#ifdef PIPESEND
+    { "/command",         SND_CMD, CM_PSH },
+#endif /* PIPESEND */
+    { "/except",          SND_EXC, CM_ARG },
+    { "/filenames",       SND_NAM, CM_ARG },
+#ifdef PIPESEND
+    { "/filter",          SND_FLT, CM_ARG|CM_PSH },
+#endif /* PIPESEND */
+#ifdef VMS
+    { "/image",           SND_IMG, 0 },
+    { "/labeled",         SND_LBL, 0 },
+#else
+    { "/image",           SND_BIN, CM_INV },
+#endif /* VMS */
+#ifdef CK_TMPDIR
+    { "/move-to",         SND_MOV, CM_ARG },
+#endif /* CK_TMPDIR */
+    { "/pathnames",       SND_PTH, CM_ARG },
+    { "/pipes",           SND_PIP, CM_ARG|CM_PSH },
+#ifdef CK_XYZ
+    { "/protocol",        SND_PRO, CM_ARG },
+#else
+    { "/protocol",        SND_PRO, CM_ARG|CM_INV },
+#endif /* CK_XYZ */
+    { "/quiet",           SND_SHH, 0 },
+    { "/recursive",       SND_REC, 0 },
+    { "/rename-to",       SND_REN, CM_ARG },
+    { "/text",            SND_TXT, 0 },
+    { "/transparent",     SND_XPA, 0 }
+};
+#define NRCVTAB sizeof(rcvtab)/sizeof(struct keytab)
+static int nrcvtab = NRCVTAB;
+#endif /* NOXFER */
+
+/* WAIT table */
+
+#define WAIT_FIL 997
+#define WAIT_MDM 998
+
+struct keytab waittab[] = {
+    { "cd",            BM_DCD,   CM_INV }, /* (Carrier Detect) */
+    { "cts",           BM_CTS,   CM_INV }, /* (Clear To Send)  */
+    { "dsr",           BM_DSR,   CM_INV }, /* (Data Set Ready) */
+    { "file",          WAIT_FIL, 0 },      /* New category selector keywords */
+    { "modem-signals", WAIT_MDM, 0 },      /* ... */
+    { "ri",            BM_RNG,   CM_INV }  /* (Ring Indicator) */
+};
+int nwaittab = (sizeof(waittab) / sizeof(struct keytab));
+
+/* Modem signal table */
+
+struct keytab mstab[] = {
+    { "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));
+
+#define WF_MOD 1
+#define WF_DEL 2
+#define WF_CRE 3
+
+struct keytab wfswi[] = {               /* WAIT FILE switches */
+    { "creation",     WF_CRE, 0 },      /* Wait for file to be created */
+    { "deletion",     WF_DEL, 0 },      /* Wait for file to be deleted */
+    { "modification", WF_MOD, 0 }       /* Wait for file to be modified */
+};
+int nwfswi = (sizeof(wfswi) / sizeof(struct keytab));
+
+#ifndef NOSPL
+struct keytab asgtab[] = {              /* Assignment operators for "." */
+    { "::=", 2, 0 },                    /* ASSIGN and EVALUATE */
+    { ":=",  1, 0 },                    /* ASSIGN */
+    { "=",   0, 0 }                     /* DEFINE */
+};
+int nasgtab = (sizeof(asgtab) / sizeof(struct keytab));
+
+struct keytab opntab[] = {
+#ifndef NOPUSH
+    { "!read",  OPN_PI_R, CM_INV },
+    { "!write", OPN_PI_W, CM_INV },
+#endif /* NOPUSH */
+    { "append", OPN_FI_A, 0 },
+    { "host",   OPN_NET,  0 },
+#ifdef OS2
+    { "line",   OPN_SER,  CM_INV },
+    { "port",   OPN_SER,  0 },
+#else
+    { "line",   OPN_SER,  0 },
+    { "port",   OPN_SER,  CM_INV },
+#endif /* OS2 */
+    { "read",   OPN_FI_R, 0 },
+    { "write",  OPN_FI_W, 0 }
+};
+int nopn = (sizeof(opntab) / sizeof(struct keytab));
+
+/* 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 */
+#define  XXIFDI 17      /* IF DIRECTORY */
+#define  XXIFNE 18      /* IF NEWER */
+#define  XXIFRO 19      /* IF REMOTE-ONLY */
+#define  XXIFAL 20      /* IF ALARM */
+#define  XXIFSD 21      /* IF STARTED-FROM-DIALER */
+#define  XXIFTR 22      /* IF TRUE */
+#define  XXIFNT 23      /* IF FALSE */
+#define  XXIFTM 24      /* IF TERMINAL-MACRO */
+#define  XXIFEM 25      /* IF EMULATION */
+#define  XXIFOP 26      /* IF OPEN */
+#define  XXIFLE 27      /* IF <= */
+#define  XXIFGE 28      /* IF >= */
+#define  XXIFIP 29      /* IF INPATH */
+#define  XXIFTA 30      /* IF TAPI */
+#define  XXIFMA 31      /* IF MATCH */
+#define  XXIFFL 32      /* IF FLAG */
+#define  XXIFAB 33      /* IF ABSOLUTE */
+#define  XXIFAV 34      /* IF AVAILABLE */
+#define  XXIFAT 35      /* IF ASKTIMEOUT */
+#define  XXIFRD 36      /* IF READABLE */
+#define  XXIFWR 37      /* IF WRITEABLE */
+#define  XXIFAN 38      /* IF ... AND ... */
+#define  XXIFOR 39      /* IF ... OR ... */
+#define  XXIFLP 40      /* IF left parenthesis */
+#define  XXIFRP 41      /* IF right parenthesis */
+#define  XXIFNQ 42      /* IF != (== "NOT =") */
+#define  XXIFQU 43      /* IF QUIET */
+#define  XXIFCK 44      /* IF C-KERMIT */
+#define  XXIFK9 45      /* IF K-95 */
+#define  XXIFMS 46      /* IF MS-KERMIT */
+#define  XXIFWI 47      /* IF WILD */
+#define  XXIFLO 48      /* IF LOCAL */
+#define  XXIFCM 49      /* IF COMMAND */
+#define  XXIFFP 50      /* IF FLOAT */
+#define  XXIFIK 51      /* IF IKS */
+#define  XXIFKB 52      /* IF KBHIT */
+#define  XXIFKG 53      /* IF KERBANG */
+#define  XXIFVE 54      /* IF VERSION */
+#define  XXIFDC 55      /* IF DECLARED */
+#define  XXIFGU 56      /* IF GUI */
+
+struct keytab iftab[] = {               /* IF commands */
+    { "!",          XXIFNO, 0 },
+    { "!=",         XXIFNQ, 0 },
+    { "&&",         XXIFAN, 0 },
+    { "(",          XXIFLP, 0 },
+    { ")",          XXIFRP, 0 },
+    { "<",          XXIFLT, 0 },
+    { "<=",         XXIFLE, 0 },
+    { "=",          XXIFAE, 0 },
+    { "==",         XXIFAE, CM_INV },
+    { ">",          XXIFGT, 0 },
+    { ">=",         XXIFGE, 0 },
+    { "absolute",   XXIFAB, 0 },
+    { "alarm",      XXIFAL, 0 },
+    { "and",        XXIFAN, 0 },
+    { "asktimeout", XXIFAT, 0 },
+    { "available",  XXIFAV, 0 },
+    { "background", XXIFBG, 0 },
+    { "c-kermit",   XXIFCK, 0 },
+    { "command",    XXIFCM, 0 },
+    { "count",      XXIFCO, 0 },
+    { "dcl",        XXIFDC, CM_INV },
+    { "declared",   XXIFDC, 0 },
+    { "defined",    XXIFDE, 0 },
+#ifdef CK_TMPDIR
+    { "directory",  XXIFDI, 0 },
+#endif /* CK_TMPDIR */
+    { "emulation",  XXIFEM, 0 },
+#ifdef COMMENT
+    { "eof",        XXIFEO, 0 },
+#endif /* COMMENT */
+    { "equal",      XXIFEQ, 0 },
+    { "error",      XXIFFA, CM_INV },
+    { "exist",      XXIFEX, 0 },
+    { "failure",    XXIFFA, 0 },
+    { "false",      XXIFNT, 0 },
+    { "flag",       XXIFFL, 0 },
+#ifdef CKFLOAT
+    { "float",      XXIFFP, 0 },
+#endif /* CKFLOAT */
+    { "foreground", XXIFFG, 0 },
+#ifdef OS2
+    { "gui",        XXIFGU, 0 },
+#else
+    { "gui",        XXIFGU, CM_INV },
+#endif /* OS2 */
+#ifdef IKSD
+    { "iksd",       XXIFIK, 0 },
+#else
+    { "iksd",       XXIFIK, CM_INV },
+#endif /* IKSD */
+    { "integer",    XXIFNU, CM_INV },
+    { "k-95",       XXIFK9, 0 },
+    { "kbhit",      XXIFKB, 0 },
+#ifdef UNIX
+    { "kerbang",    XXIFKG, 0 },
+#else
+    { "kerbang",    XXIFKG, CM_INV },
+#endif /* UNIX */
+    { "lgt",        XXIFLG, 0 },
+    { "llt",        XXIFLL, 0 },
+    { "local",      XXIFLO, 0 },
+    { "match",      XXIFMA, 0 },
+    { "ms-kermit",  XXIFMS, CM_INV },
+#ifdef ZFCDAT
+    { "newer",      XXIFNE, 0 },
+#endif /* ZFCDAT */
+    { "not",        XXIFNO, 0 },
+    { "numeric",    XXIFNU, 0 },
+    { "ok",         XXIFSU, CM_INV },
+    { "open",       XXIFOP, 0 },
+    { "or",         XXIFOR, 0 },
+    { "quiet",      XXIFQU, 0 },
+    { "readable",   XXIFRD, 0 },
+    { "remote-only",XXIFRO, 0 },
+    { "started-from-dialer",XXIFSD, CM_INV },
+    { "success",    XXIFSU, 0 },
+    { "tapi",       XXIFTA, 0 },
+#ifdef OS2
+    { "terminal-macro", XXIFTM, 0 },
+#else
+    { "terminal-macro", XXIFTM, CM_INV },
+#endif /* OS2 */
+    { "true",       XXIFTR, 0 },
+    { "version",    XXIFVE, 0 },
+    { "wild",       XXIFWI, 0 },
+    { "writeable",  XXIFWR, 0 },
+    { "||",         XXIFOR, 0 },
+    { "", 0, 0 }
+};
+int nif = (sizeof(iftab) / sizeof(struct keytab)) - 1;
+
+struct keytab iotab[] = {               /* Keywords for IF OPEN */
+    { "!read-file",      ZRFILE, CM_INV },
+    { "!write-file",     ZWFILE, CM_INV },
+    { "append-file",     ZWFILE, CM_INV },
+    { "connection",      8888,   0 },
+#ifdef CKLOGDIAL
+    { "cx-log",          7777,   0 },
+#endif /* CKLOGDIAL */
+    { "debug-log",       ZDFILE, 0 },
+    { "error",           9999,   0 },
+    { "packet-log",      ZPFILE, 0 },
+    { "read-file",       ZRFILE, 0 },
+    { "screen",          ZSTDIO, 0 },
+    { "session-log",     ZSFILE, 0 },
+    { "transaction-log", ZTFILE, 0 },
+    { "write-file",      ZWFILE, 0 }
+};
+int niot = (sizeof(iotab) / sizeof(struct keytab));
+#endif /* NOSPL */
+
+/* Variables and prototypes */
+
+#ifdef NETCONN
+extern int nnetdir;                     /* How many network directories */
+#endif /* NETCONN */
+#ifdef CK_SECURITY
+_PROTOTYP(int ck_krb4_is_installed,(void));
+_PROTOTYP(int ck_krb5_is_installed,(void));
+_PROTOTYP(int ck_ntlm_is_installed,(void));
+_PROTOTYP(int ck_srp_is_installed,(void));
+_PROTOTYP(int ck_ssleay_is_installed,(void));
+_PROTOTYP(int ck_ssh_is_installed,(void));
+_PROTOTYP(int ck_crypt_is_installed,(void));
+#else
+#define ck_krb4_is_installed() (0)
+#define ck_krb5_is_installed() (0)
+#define ck_ntlm_is_installed() (0)
+#define ck_srp_is_installed() (0)
+#define ck_ssleay_is_installed() (0)
+#define ck_ssh_is_installed() (0)
+#define ck_crypt_is_installed() (0)
+#endif /* CK_SECURITY */
+
+#define AV_KRB4   1
+#define AV_KRB5   2
+#define AV_NTLM   3
+#define AV_SRP    4
+#define AV_SSL    5
+#define AV_CRYPTO 6
+#define AV_SSH    7
+
+struct keytab availtab[] = {             /* Available authentication types */
+    { "crypto",     AV_CRYPTO, CM_INV }, /* and encryption */
+    { "encryption", AV_CRYPTO, 0 },
+    { "k4",         AV_KRB4,   CM_INV },
+    { "k5",         AV_KRB5,   CM_INV },
+    { "kerberos4",  AV_KRB4,   0 },
+    { "kerberos5",  AV_KRB5,   0 },
+    { "krb4",       AV_KRB4,   CM_INV },
+    { "krb5",       AV_KRB5,   CM_INV },
+    { "ntlm",       AV_NTLM,   0 },
+    { "srp",        AV_SRP,    0 },
+    { "ssh",        AV_SSH,    0 },
+    { "ssl",        AV_SSL,    0 },
+    { "tls",        AV_SSL,    0 },
+    { "",           0,         0 }
+};
+int availtabn = sizeof(availtab)/sizeof(struct keytab)-1;
+
+#ifndef NODIAL
+_PROTOTYP(static int ddcvt, (char *, FILE *, int) );
+_PROTOTYP(static int dncvt, (int, int, int, int) );
+_PROTOTYP(char * getdname, (void) );
+
+static int partial  = 0;                /* For partial dial */
+static char *dscopy = NULL;
+int dialtype = -1;
+
+char *dialnum = (char *)0;              /* Remember DIAL number for REDIAL */
+int dirline = 0;                        /* Dial directory line number */
+extern char * dialdir[];                /* Dial directory file names */
+extern int dialdpy;                     /* DIAL DISPLAY on/off */
+extern int ndialdir;                    /* How many dial directories */
+extern int ntollfree;                   /* Toll-free call info */
+extern int ndialpxx;                    /* List of PBX exchanges */
+extern char *dialtfc[];
+char * matchpxx = NULL;                 /* PBX exchange that matched */
+extern int nlocalac;                    /* Local area-code list */
+extern char * diallcac[];
+extern int tttapi;
+#ifdef CK_TAPI
+extern int tapiconv;                    /* TAPI Conversions */
+extern int tapipass;                    /* TAPI Passthrough */
+#endif /* CK_TAPI */
+extern int dialatmo;
+extern char * dialnpr, * dialsfx;
+extern char * dialixp, * dialixs, * dialmac;
+extern char * dialldp, * diallds, * dialtfp;
+extern char * dialpxi, * dialpxo, * diallac;
+extern char * diallcp, * diallcs, * diallcc;
+extern char * dialpxx[];
+
+extern int dialcnf;                     /* DIAL CONFIRMATION */
+int dialfld = 0;                        /* DIAL FORCE-LONG-DISTANCE */
+int dialsrt = 1;                        /* DIAL SORT ON */
+int dialrstr = 6;                       /* DIAL RESTRICTION */
+int dialtest = 0;                       /* DIAL TEST */
+int dialcount = 0;                      /* \v(dialcount) */
+
+extern int dialsta;                     /* Dial status */
+int dialrtr = -1,                       /* Dial retries */
+    dialint = 10;                       /* Dial retry interval */
+extern long dialcapas;                  /* Modem capabilities */
+extern int dialcvt;                     /* DIAL CONVERT-DIRECTORY */
+#endif /* NODIAL */
+
+#ifndef NOSPL
+#define IFCONDLEN 256
+int ifc,                                /* IF case */
+    not = 0,                            /* Flag for IF NOT */
+    ifargs = 0;                         /* Count of IF condition words */
+char ifcond[IFCONDLEN];                 /* IF condition text */
+char *ifcp;                             /* Pointer to IF condition text */
+#ifdef DCMDBUF
+extern int
+ *ifcmd,  *count,  *iftest, *intime,
+ *inpcas, *takerr, *merror, *xquiet;
+#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 */
+extern int intime[];                    /* Ditto for other stackables... */
+extern int inpcas[];
+extern int takerr[];
+extern int merror[];
+extern int xquiet[];
+#endif /* DCMDBUF */
+#else
+extern int takerr[];
+#endif /* NOSPL */
+
+#ifdef DCMDBUF
+extern char *line;                      /* Character buffer for anything */
+extern char *tmpbuf;
+#else
+extern char line[], tmpbuf[];
+#endif /* DCMDBUF */
+extern char *lp;                        /* Pointer to line buffer */
+
+int cwdf = 0;                           /* CWD has been done */
+
+/* Flags for ENABLE/DISABLE */
+extern int en_cwd, en_cpy, en_del, en_dir, en_fin,
+   en_get, en_hos, en_ren, en_sen, en_set, en_spa, en_typ, en_who, en_bye,
+   en_asg, en_que, en_ret, en_mai, en_pri, en_mkd, en_rmd, en_xit, en_ena;
+
+extern FILE *tfile[];                   /* File pointers for TAKE command */
+extern char *tfnam[];                   /* Names of TAKE files */
+extern int tfline[];                    /* TAKE-file line number */
+
+extern int success;                     /* Command success/failure flag */
+extern int cmdlvl;                      /* Current position in command stack */
+
+#ifndef NOSPL
+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 */
+
+#ifdef COMMENT
+extern char *m_line[];
+#endif /* COMMENT */
+
+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 */
+#endif /* NOSPL */
+
+#define xsystem(s) zsyscmd(s)
+
+static int x, y, z = 0;
+static char *s, *p;
+
+#ifdef OS2
+_PROTOTYP( int os2settitle, (char *, int) );
+#endif /* OS2 */
+
+extern struct keytab yesno[], onoff[], fntab[];
+extern int nyesno, nfntab;
+
+#ifndef NOSPL
+
+/* Do the ASK, ASKQ, GETOK, and READ commands */
+
+int asktimedout = 0;
+
+#define ASK_PUP 1
+#define ASK_TMO 2
+#define ASK_GUI 3
+#define ASK_QUI 4
+#define ASK_DEF 5
+
+static struct keytab asktab[] = {
+    {  "/default", ASK_DEF, CM_ARG },
+    {  "/gui",     ASK_GUI,      
+#ifdef KUI
+           0
+#else /* KUI */
+           CM_INV
+#endif /* KUI */
+    },
+    { "/popup",    ASK_PUP,   
+#ifdef OS2
+           0
+#else /* OS2 */
+           CM_INV
+#endif /* OS2 */
+    },
+    { "/quiet",    ASK_QUI, 0 },
+    { "/timeout",  ASK_TMO, CM_ARG },
+    { "", 0, 0 }
+};
+static int nasktab = sizeof(asktab)/sizeof(struct keytab)-1;
+
+int
+doask(cx) int cx; {
+    extern int cmflgs, asktimer, timelimit;
+#ifdef CK_RECALL
+    extern int on_recall;
+#endif /* CK_RECALL */
+    int popupflg = 0;
+    int guiflg = 0;
+    int nomsg = 0;
+    int mytimer = 0;
+#ifdef CK_APC
+    extern int apcactive, apcstatus;
+#endif /* CK_APC */
+
+    char dfbuf[1024];                  /* Buffer for default answer */
+    char * dfanswer = NULL;            /* Pointer to it */
+
+    char vnambuf[VNAML+1];              /* Buffer for variable names */
+    char *vnp = NULL;                   /* Pointer to same */
+    
+    dfbuf[0] = NUL;
+    vnambuf[0] = NUL;
+
+#ifdef CK_APC
+    if ( apcactive != APC_INACTIVE && (apcstatus & APC_NOINP) ) {
+        return(success = 0);
+    }
+#endif /* CK_APC */
+
+    mytimer = asktimer;                 /* Inherit global ASK timer */
+
+    if (cx == XXASK || cx == XXASKQ) {
+        struct FDB sw, fl;
+        int getval;
+        char c;
+        if (cx == XXASKQ)               /* Don't log ASKQ response */
+          debok = 0;
+        cmfdbi(&sw,                     /* First FDB - command switches */
+               _CMKEY,                  /* fcode */
+               "Variable name or switch",
+               "",                      /* default */
+               "",                      /* addtl string data */
+               nasktab,                 /* addtl numeric data 1: tbl size */
+               4,                       /* addtl numeric data 2: 4 = cmswi */
+               xxstring,                /* Processing function */
+               asktab,                  /* Keyword table */
+               &fl                      /* Pointer to next FDB */
+               );
+        cmfdbi(&fl,                     /* Anything that doesn't match */
+               _CMFLD,                  /* fcode */
+               "",                      /* hlpmsg */
+               "",                      /* default */
+               "",                      /* addtl string data */
+               0,                       /* addtl numeric data 1 */
+               0,                       /* addtl numeric data 2 */
+               NULL,
+               NULL,
+               NULL
+               );
+        while (1) {                     /* Parse 0 or more switches */
+            x = cmfdb(&sw);             /* Parse something */
+            if (x < 0)
+              return(x);
+            if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
+              break;
+            c = cmgbrk();
+            if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+                printf("?This switch does not take an argument\n");
+                return(-9);
+            }
+            if (!getval && (cmgkwflgs() & CM_ARG)) {
+                printf("?This switch requires an argument\n");
+                return(-9);
+            }
+            switch (cmresult.nresult) {
+             case ASK_QUI:
+               nomsg = 1;
+               break;
+              case ASK_PUP:
+                popupflg = 1;
+                break;
+             case ASK_GUI:
+               guiflg = 1;
+               break;
+              case ASK_TMO: {
+                  if ((y = cmnum("seconds","1",10,&x,xxstring)) < 0)
+                    return(y);
+                  if (x < 0)
+                    x = 0;
+                  mytimer = x;
+                  break;
+              }
+              case ASK_DEF: {
+                  if ((y = cmfld("Text to supply if reply is empty",
+                                "",&s,xxstring)) < 0)
+                    return(y);
+                 ckstrncpy(dfbuf,s,1024);
+                 dfanswer = dfbuf;
+                  break;
+              }
+              default: return(-2);
+            }
+        }
+        /* Have variable name, make copy. */
+        ckstrncpy(vnambuf,cmresult.sresult,VNAML);
+        vnp = vnambuf;
+        if (vnambuf[0] == CMDQ &&
+            (vnambuf[1] == '%' || vnambuf[1] == '&'))
+          vnp++;
+        y = 0;
+        if (*vnp == '%' || *vnp == '&') {
+            if ((y = parsevar(vnp,&x,&z)) < 0)
+              return(y);
+        }
+    } else if (cx != XXGOK && cx != XXRDBL) { /* Get variable name */
+        if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
+            if (y == -3) {
+                printf("?Variable name required\n");
+                return(-9);
+            } else return(y);
+        }
+        ckstrncpy(vnambuf,s,VNAML);     /* Make a copy. */
+        vnp = vnambuf;
+        if (vnambuf[0] == CMDQ &&
+            (vnambuf[1] == '%' || vnambuf[1] == '&'))
+          vnp++;
+        y = 0;
+        if (*vnp == '%' || *vnp == '&') {
+            if ((y = parsevar(vnp,&x,&z)) < 0)
+              return(y);
+        }
+    }
+    if (cx == XXREA || cx == XXRDBL) {  /* READ or READBLOCK command */
+        if ((y = cmcfm()) < 0)          /* Get confirmation */
+          return(y);
+        if (chkfn(ZRFILE) < 1) {        /* File open? */
+            printf("?Read file not open\n");
+            return(success = 0);
+        }
+        if (!(s = (char *)readbuf)) {           /* Where to read into. */
+            printf("?Oops, no READ buffer!\n");
+            return(success = 0);
+        }
+        y = zsinl(ZRFILE, s, readblock); /* Read a line. */
+        debug(F111,"read zsinl",s,y);
+        if (y < 0) {                    /* On EOF or other error, */
+            zclose(ZRFILE);             /* close the file, */
+            delmac(vnp,0);              /* delete the variable, */
+            return(success = 0);        /* and return failure. */
+        } else {                        /* Read was OK. */
+            readsize = (int) strlen(s);
+            success = (addmac(vnp,s) < 0 ? 0 : 1); /* Define variable */
+            debug(F111,"read addmac",vnp,success);
+            return(success);            /* Return success. */
+        }
+    }
+
+    /* ASK, ASKQ, GETOK, or GETC */
+
+    if (cx == XXGOK) {                 /* GETOK can take switches */
+        struct FDB sw, fl;
+        int getval;
+        char c;
+        cmfdbi(&sw,                     /* First FDB - command switches */
+               _CMKEY,                  /* fcode */
+               "Variable name or question prompt",
+               "",                      /* default */
+               "",                      /* addtl string data */
+               nasktab,                 /* addtl numeric data 1: tbl size */
+               4,                       /* addtl numeric data 2: 4 = cmswi */
+               xxstring,                /* Processing function */
+               asktab,                  /* Keyword table */
+               &fl                      /* Pointer to next FDB */
+               );
+        cmfdbi(&fl,                     /* Anything that doesn't match */
+               _CMTXT,                  /* fcode */
+               "",                      /* hlpmsg */
+               "",                      /* default */
+               "",                      /* addtl string data */
+               0,                       /* addtl numeric data 1 */
+               0,                       /* addtl numeric data 2 */
+               NULL,
+               NULL,
+               NULL
+               );
+        while (1) {                     /* Parse 0 or more switches */
+            x = cmfdb(&sw);             /* Parse something */
+            if (x < 0)
+              return(x);
+            if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
+              break;
+            c = cmgbrk();
+            if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+                printf("?This switch does not take an argument\n");
+                return(-9);
+            }
+            if (!getval && (cmgkwflgs() & CM_ARG)) {
+                printf("?This switch requires an argument\n");
+                return(-9);
+            }
+            switch (cmresult.nresult) {
+              case ASK_PUP:
+                popupflg = 1;
+                break;
+             case ASK_GUI:
+               guiflg = 1;
+               break;
+              case ASK_TMO: {
+                  if ((y = cmnum("seconds","1",10,&x,xxstring)) < 0)
+                    return(y);
+                  if (x < 0)
+                    x = 0;
+                  mytimer = x;
+                  break;
+              }
+              case ASK_DEF: {
+                  if ((y = cmfld("Text to supply if reply is empty",
+                                "",&s,xxstring)) < 0)
+                    return(y);
+                 ckstrncpy(dfbuf,s,1024);
+                 dfanswer = dfbuf;
+                  break;
+              }
+             case ASK_QUI:
+               nomsg = 1;
+               break;
+              default: return(-2);
+            }
+       }
+       p = cmresult.sresult;
+    } else
+      if ((y = cmtxt(
+"Prompt,\n\
+ enclose in { braces } or \" quotes \" to preserve leading and trailing\n\
+ spaces, precede question mark with backslash (\\).",
+                   "",&p,xxstring)) < 0)
+        return(y);
+
+    if (!p) p = "";
+#ifndef NOLOCAL
+#ifdef OS2
+    if (popupflg) {                     /* Popup requested */
+        int len = -1;
+        ckstrncpy(tmpbuf,brstrip(p),TMPBUFSIZ);
+        p = tmpbuf;
+        if (cx == XXASK || cx == XXASKQ) {
+            if (cx == XXASK)
+              len = popup_readtext(vmode,NULL,p,line,LINBUFSIZ,mytimer);
+            else
+              len = popup_readpass(vmode,NULL,p,line,LINBUFSIZ,mytimer);
+            asktimedout = ( len < 0 && mytimer );
+        } else if (cx == XXGOK) {
+           printf("?Sorry, GETOK /POPUP not implemented yet\n");
+           timelimit = 0;
+           return(-9);
+       }
+        if (len >= 0) {
+           y = addmac(vnp,(char *)line); /* Add it to the macro table. */
+        } else if ( asktimedout && dfanswer ) {
+            y = addmac(vnp,dfanswer);      /* Add it to the macro table. */
+            asktimedout = 0;
+            len = 0;
+        }
+        timelimit = 0;
+        return(success = ((len >= 0) && (y >= 0)) && !asktimedout);
+    }
+#ifdef KUI
+    if (guiflg) {                       /* GUI requested */
+        int rc, n;
+       char * s1;
+       s1 = tmpbuf;
+       n = TMPBUFSIZ-1;
+       zzstring(brstrip(p),&s1,&n);
+        p = tmpbuf;
+        if (cx == XXASK || cx == XXASKQ) {
+            rc = gui_txt_dialog(NULL,p,(cx == XXASK),
+                                line,LINBUFSIZ,dfanswer,mytimer);
+            asktimedout = (rc == -1 && mytimer);
+            if (rc == 1) {
+                y = addmac(vnp,(char *)line); /* Add it to the macro table. */
+            } else if ( asktimedout && dfanswer ) {
+                y = addmac(vnp,dfanswer); /* Add default to macro table. */
+                asktimedout = 0;
+                rc = 1;
+            }
+           timelimit = 0;
+           return(success = (rc == 1 && (y >= 0)) && !asktimedout);
+       } else if (cx == XXGOK) {
+           int x;
+           x = lookup(yesno,dfanswer,nyesno,NULL);
+           if (x != 1) x = 2;
+           rc = uq_ok(NULL, p, 3, NULL, x);
+           return(success = (rc == 1));
+       }
+    }
+#endif /* KUI */
+#endif /* OS2 */
+#endif /* NOLOCAL */
+
+    concb((char)escape);                /* Enter CBREAK mode */
+    cmsavp(psave,PROMPTL);              /* Save old prompt */
+    cmsetp(brstrip(p));                 /* Make new prompt */
+reprompt:
+    if (cx == XXASKQ) {                 /* For ASKQ, */
+        cmini(0);                       /* no-echo mode. */
+    } else {                            /* For others, regular echoing. */
+        cmini(ckxech);
+    }
+    askflag = 1;
+    x = -1;                             /* This means to reparse. */
+    cmflgs = 0;
+    if (pflag)
+      prompt(xxstring);                 /* Issue prompt. */
+
+    asktimedout = 0;                    /* Handle timed responses. */
+    timelimit = mytimer;
+reparse:
+    cmres();
+    if (cx == XXGOK) {                  /* GETOK */
+#ifdef CK_RECALL
+        on_recall = 0;
+#endif /* CK_RECALL */
+        askflag = 0;
+       /* GETOK uses keyword table */
+        x = cmkey(yesno,nyesno,"",dfanswer,xxstring);
+        if (x < 0) {                    /* Parse error */
+            if (x == -10) {
+               char * ds;
+               ds = dfanswer ? dfanswer : "No";
+               if (!nomsg)
+                 printf("?Timed out, assuming \"%s\"",ds);
+               printf("\n");
+                asktimedout = 1;
+               x = lookup(yesno,ds,nyesno,NULL);
+               if (x != 1) x = 0;
+                goto gokdone;
+            } else if (x == -3) {       /* No answer? */
+                printf("Please respond Yes or No\n"); /* Make them answer */
+                cmini(ckxech);
+                goto reprompt;
+            } else if (x == -1) {
+                goto reparse;
+            } else
+              goto reprompt;
+        }
+        if (cmcfm() < 0)                /* Get confirmation */
+          goto reparse;
+  gokdone:
+        askflag = 0;
+        cmsetp(psave);                  /* Restore prompt */
+#ifdef VMS
+        if (cmdlvl > 0)                 /* In VMS and not at top level, */
+          conres();                     /*  restore console again. */
+#endif /* VMS */
+        timelimit = 0;
+        return(x);                      /* Return success or failure */
+    } else if (cx == XXGETC             /* GETC */
+#ifdef OS2
+               || cx == XXGETK          /* or GETKEYCODE */
+#endif /* OS2 */
+               ) {                      /* GETC */
+        char tmp[16];
+        conbin((char)escape);           /* Put keyboard in raw mode */
+#ifndef NOSETKEY
+#ifdef OS2
+        if (cx == XXGETK) {             /* GETKEYCODE */
+            extern int os2gks;
+            int t;
+            t = os2gks;                 /* Turn off kverb recognition */
+            os2gks = 0;
+            x = congks(timelimit);      /* Read a key event, blocking */
+            os2gks = t;                 /* Put back kverb recognition */
+        } else                          /* GETC */
+#endif /* OS2 */
+#endif /* NOSETKEY */
+        {
+            debug(F101,"GETC conchk","",conchk());
+            x = coninc(timelimit);      /* Just read one character */
+            debug(F101,"GETC coninc","",x);
+        }
+        concb((char)escape);            /* Put keyboard back in cbreak mode */
+        if (x > -1) {
+            if (xcmdsrc == 0)
+              printf("\r\n");
+#ifdef OS2
+            if (cx == XXGETK) {         /* GETKEYCODE */
+                sprintf(tmp,"%d",x);    /* SAFE */
+            } else {
+#endif /* OS2 */
+                tmp[0] = (char) (x & 0xff);
+                tmp[1] = NUL;
+#ifdef OS2
+            }
+#endif /* OS2 */
+            y = addmac(vnp,tmp);        /* Add it to the macro table. */
+            debug(F111,"getc/getk addmac",vnp,y);
+        } else y = -1;
+        cmsetp(psave);                  /* Restore old prompt. */
+        if (x < -1) {
+            asktimedout = 1;
+            if (!quiet && !nomsg)
+              printf("?Timed out");
+           printf("\n");
+        }
+        timelimit = 0;
+        return(success = ((y < 0 ? 0 : 1) && (asktimedout == 0)));
+    } else {                            /* ASK or ASKQ */
+#ifdef CK_RECALL
+        on_recall = 0;
+#endif /* CK_RECALL */
+        y = cmdgquo();                  /* Get current quoting */
+        cmdsquo(0);                     /* Turn off quoting */
+        while (x == -1) {               /* Prompt till they answer */
+            x = cmtxt("Please respond.",dfanswer,&s,NULL);
+            debug(F111,"ASK cmtxt",s,x);
+            cmres();
+        }
+        cmdsquo(y);                     /* Restore previous quoting */
+        if (cx == XXASKQ)               /* ASKQ must echo CRLF here */
+          printf("\r\n");
+       if (x == -10 && dfanswer) {     /* Don't fail on timeout if */
+           s = dfanswer;               /* a default was specified */
+           asktimedout = 0;            /* and don't fail */
+           x = 0;
+       }
+        if (x < 0) {                    /* If cmtxt parse error, */
+            cmsetp(psave);              /* restore original prompt */
+#ifdef VMS
+            if (cmdlvl > 0)             /* In VMS and not at top level, */
+              conres();                 /*  restore console again. */
+#endif /* VMS */
+            if (x == -10) {            /* Timed out with no response */
+               if (!nomsg)
+                 printf("?Timed out");
+               printf("\n");
+                asktimedout = 1;
+               if (dfanswer)           /* Supply default answer if any */
+                 s = dfanswer;
+                success = x = 0;       /* (was "x = -9;") */
+            }
+            timelimit = 0;
+            return(x);                  /* and return cmtxt's error code. */
+        }
+        if (!s || *s == NUL) {         /* If user typed a bare CR, */
+            cmsetp(psave);              /* Restore old prompt, */
+            delmac(vnp,0);              /* delete variable if it exists, */
+#ifdef VMS
+            if (cmdlvl > 0)             /* In VMS and not at top level, */
+              conres();                 /*  restore console again. */
+#endif /* VMS */
+            timelimit = 0;
+            return(success = 1);        /* and return. */
+        }
+        y = addmac(vnp,s);              /* Add it to the macro table. */
+        debug(F111,"ask addmac",vnp,y);
+        cmsetp(psave);                  /* Restore old prompt. */
+#ifdef VMS
+        if (cmdlvl > 0)                 /* In VMS and not at top level, */
+          conres();                     /*  restore console again. */
+#endif /* VMS */
+        timelimit = 0;
+        return(success = (y < 0 ? 0 : 1) && (asktimedout == 0));
+    }
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+int
+doincr(cx) int cx; {                    /* INCREMENT, DECREMENT */
+    char vnambuf[VNAML+1];              /* Buffer for variable names */
+    int eval = 0;
+    eval = (cx == XX_DECR || cx == XX_INCR);
+
+    if ((y = cmfld("Variable name","",&s, eval ? xxstring : NULL)) < 0) {
+        if (y == -3) {
+            printf("?Variable name required\n");
+            return(-9);
+        } else return(y);
+    }
+    ckstrncpy(vnambuf,s,VNAML);
+    if ((y = cmnum("by amount","1",10,&x,xxstring)) < 0)
+      return(y);
+    if ((y = cmcfm()) < 0)
+      return(y);
+
+    z = (cx == XX_INCR || cx == XXINC) ? 1 : 0; /* Increment or decrement? */
+
+    if (incvar(vnambuf,x,z) < 0) {
+        printf("?Variable %s not defined or not numeric\n",vnambuf);
+        return(success = 0);
+    }
+    return(success = 1);
+}
+
+/* Used by doundef() */
+static int
+xxundef(s,verbose,simulate) char * s; int verbose, simulate; {
+    int rc = 0;
+    if (!s) return(0);
+    if (*s == CMDQ && *(s+1) == '%') {
+        char c = *(s+2), * p = NULL;
+        if (c >= '0' && c <= '9') {
+            if (maclvl < 0)
+              p = g_var[c];
+            else
+              p = m_arg[maclvl][c - '0'];
+        } else {
+            if (isupper(c)) c += ('a'-'A');
+            if (c >= 'a' && c <= 'z')
+              p = g_var[c];
+        }
+        if (!p) return(-1);
+    }
+    if (verbose)
+      printf(" %s ",s);
+    if (simulate) {
+        printf("(SELECTED)\n");
+    } else if ((x = delmac(s,1)) > -1) { /* Full name required */
+        rc = 1;
+        if (verbose) printf("(OK)\n");
+    } else if (verbose)
+      printf("(FAILED)\n");
+    return(rc);
+}
+
+/* Do the (_)DEFINE, (_)ASSIGN, and UNDEFINE commands */
+
+#define UND_MAT 1
+#define UND_VRB 2
+#define UND_EXC 3
+#define UND_SIM 3
+
+static struct keytab undefswi[] = {
+    { "/list",     UND_VRB, 0 },
+#ifdef COMMENT
+    { "/except",   UND_EXC, CM_ARG },
+#endif /* COMMENT */
+    { "/matching", UND_MAT, 0 },
+    { "/simulate", UND_SIM, 0 },
+    { "/verbose",  UND_VRB, CM_INV }
+};
+static int nundefswi = sizeof(undefswi) / sizeof(struct keytab);
+
+#define UNDEFMAX 64
+static char ** undeflist = NULL;
+int
+doundef(cx) int cx; {                   /* UNDEF, _UNDEF */
+    int i, j, n, rc = 0, arraymsg = 0;
+    int domatch = 0, verbose = 0, errors = 0, simulate = 0, flag = 0;
+    char *vnp, vnbuf[4];
+#ifdef COMMENT
+    char *except = NULL;
+#endif /* COMMENT */
+    struct FDB sw, fl;
+    int getval;
+    char c;
+
+    if (!undeflist) {                   /* Allocate list if necessary */
+        undeflist = (char **)malloc(UNDEFMAX * sizeof(char *));
+        if (!undeflist) {
+            printf("?Memory allocation failure\n");
+            return(-9);
+        }
+        for (i = 0; i < UNDEFMAX; i++)
+          undeflist[i] = NULL;
+    }
+    cmfdbi(&sw,                         /* First FDB - command switches */
+           _CMKEY,                      /* fcode */
+           "Variable name or switch",
+           "",                          /* default */
+           "",                          /* addtl string data */
+           nundefswi,                   /* addtl numeric data 1: tbl size */
+           4,                           /* addtl numeric data 2: 4 = cmswi */
+           xxstring,                    /* Processing function */
+           undefswi,                    /* Keyword table */
+           &fl                          /* Pointer to next FDB */
+           );
+    cmfdbi(&fl,                         /* Anything that doesn't match */
+           _CMFLD,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           (cx == XXUNDEF) ? NULL : xxstring,
+           NULL,
+           NULL
+           );
+    while (1) {                         /* Parse 0 or more switches */
+        x = cmfdb(&sw);                 /* Parse something */
+        if (x < 0)
+          return(x);
+        if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
+          break;
+        c = cmgbrk();
+        if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+            printf("?This switch does not take an argument\n");
+            return(-9);
+        }
+        switch (cmresult.nresult) {
+          case UND_MAT: domatch  = 1; break;
+          case UND_SIM: simulate = 1; /* fall thru on purpose */
+          case UND_VRB: verbose  = 1; break;
+
+#ifdef COMMENT
+          case UND_EXC:
+            if (!getval) break;
+            if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
+                if (x == -3) {
+                    printf("?Pattern required\n");
+                    x = -9;
+                }
+                goto xgetx;
+            }
+            makestr(&except,cmresult.sresult);
+            break;
+#endif /* COMMENT */
+
+          default:
+            return(-2);
+        }
+    }
+    n = 0;
+    makestr(&(undeflist[n++]),cmresult.sresult);
+    for (i = 1; i < UNDEFMAX; i++) {
+        x = cmfld("Macro or variable name","",&s,
+                  ((cx == XXUNDEF) ? NULL : xxstring)
+                  );
+        if (x == -3) {
+            if ((y = cmcfm()) < 0)
+              return(y);
+            break;
+        } else if (y < 0) {
+            return(y);
+        }
+        makestr(&(undeflist[n++]),s);
+    }
+    /* Now we have a list of n variables or patterns to undefine */
+
+    for (i = 0; i < n; i++) {
+        flag = 0;
+        if (!(vnp = undeflist[i]))
+          continue;
+        if (vnp[0] == CMDQ && (vnp[1] == '%' || vnp[1] == '&')) {
+            flag++;
+            vnp++;
+        }
+        if (!domatch) {                 /* Pattern match not requested */
+            if (flag) {
+                if ((y = parsevar(vnp,&x,&z)) < 0) {
+                    vnp--;
+                    if (verbose) printf(" %s...error\n",vnp);
+                    continue;
+                }
+                vnp--;
+            }
+            x = xxundef(vnp,verbose,simulate);
+            if (x > -1) {
+                if (!x && !simulate) errors++;
+                rc += x;
+            }
+            continue;
+        }
+        /* Pattern match requested */
+
+        if (!flag) {                    /* It's a macro */
+            for (j = 0; j < nmac; j++) {
+                if (ckmatch(vnp,mactab[j].kwd,0,1)) {
+                    x = xxundef(mactab[j].kwd,verbose,simulate);
+                    if (x > -1) {
+                        rc += x;
+                        if (!x) errors++;
+                    }
+                    if (!simulate)
+                      j--;              /* Because mactab shifted up */
+                }
+            }
+        } else if (vnp[0] == '%') {     /* It's a \%x variable */
+            vnbuf[0] = CMDQ;
+            vnbuf[1] = '%';
+            vnbuf[3] = NUL;
+            for (j = '0'; j <= 'z'; j++) { /* 0..9 a..z */
+                vnbuf[2] = j;
+                if (ckmatch(vnp,&vnbuf[1],0,1)) {
+                    x = xxundef(vnbuf,verbose,simulate);
+                    if (x > -1) {
+                        if (!x) errors++;
+                        rc += x;
+                    }
+                }
+                if (j == '9') j = (int)'a' - 1; /* 9 -> a */
+            }
+        } else if (vnp[0] == '&') {
+            if (!arraymsg && !quiet) {
+                printf("?UNDEFINE /MATCH can't be used with arrays.\n");
+                printf("(Type HELP ARRAY to see other methods.)\n");
+            }
+            arraymsg++;
+            errors++;
+        }
+    }
+    if (verbose)
+      printf("undefined: %d, errors: %d\n",rc,errors);
+
+    for (i = 0; i < UNDEFMAX; i++) {    /* Check them all */
+        if (undeflist[i]) {             /* in case we were interrupted */
+            free(undeflist[i]);         /* previously... */
+            undeflist[i] = NULL;
+        }
+    }
+    return(success = (errors == 0) ? 1 : 0);
+}
+
+int
+dodef(cx) int cx; {
+    extern int xxdot;
+    extern char ppvnambuf[];
+    int doeval = 0;
+    char vnambuf[VNAML+1];              /* Buffer for variable names */
+    char *vnp;                          /* Pointer to same */
+    int k, mydot;
+    mydot = xxdot;                      /* Copy */
+    xxdot = 0;                          /* and reset */
+/*
+  In case we got here from a command that begins like ".\%a", cmkey() has
+  already evaluated \%a, but we don't want that, so we retrieve the variable
+  name from a special pre-evaluation buffer in the command module, and we
+  undo the "unget word" that would be done because of the token, because if
+  the variable was defined, it will unget its value rather than its name.
+*/
+    s = NULL;
+
+    if (mydot && ppvnambuf[0] == '.' && ppvnambuf[1]) {
+        s = ppvnambuf+1;
+        unungw();
+    }
+    if (!s) {
+        if (cx == XXDFX || cx == XXASX)
+          /* Evaluate variable name */
+          y = cmfld("Macro or variable name","",&s,xxstring);
+        else
+          /* Don't evaluate the variable name */
+          y = cmfld("Macro or variable name","",&s,NULL);
+        if (y < 0) {
+            if (y == -3) {
+                printf("?Variable name required\n");
+                return(-9);
+            } else return(y);
+        }
+    }
+    k = strlen(s);
+    if (k > VNAML) {
+        printf("?Name too long: \"%s\"\n",s);
+        return(-9);
+    }
+    ckstrncpy(vnambuf,s,VNAML);
+    vnambuf[VNAML] = NUL;
+    vnp = vnambuf;
+    if (vnambuf[0] == CMDQ && (vnambuf[1] == '%' || vnambuf[1] == '&')) vnp++;
+    if (*vnp == '%' || *vnp == '&') {
+        if ((y = parsevar(vnp,&x,&z)) < 0) return(y);
+#ifdef COMMENT
+        if (cx == XXUNDEF) {            /* Undefine */
+            if ((y = cmtxt("Text to be ignored","",&s,NULL)) < 0) return(y);
+            delmac(vnp,0);
+            return(success = 1);
+        }
+#endif /* COMMENT */
+        debug(F101,"dodef parsevar x","",x);
+        if (mydot) {
+            if ((doeval = cmkey(asgtab,nasgtab,"operator","=",NULL)) < 0)
+              return(doeval);
+            if (doeval > 0)             /* Type of assignment */
+              cx = XXASS;
+        }
+        if (y == 1) {                   /* Simple variable */
+            if ((y = cmtxt("Definition of variable","",&s,NULL)) < 0)
+              return(y);
+            s = brstrip(s);
+            debug(F110,"xxdef var name",vnp,0);
+            debug(F110,"xxdef var def",s,0);
+        } else if (y == 2) {            /* Array element */
+            if ((y = arraynam(vnp,&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 */
+#ifdef COMMENT
+        if (cx == XXUNDEF) {            /* Undefine */
+            if ((y = cmtxt("Text to be ignored","",&s,NULL)) < 0) return(y);
+            delmac(vnp,0);
+            return(success = 1);
+        }
+#endif /* COMMENT */
+        if (mydot) {
+            if ((doeval = cmkey(asgtab,nasgtab,"operator","=",NULL)) < 0)
+              return(doeval);
+            if (doeval > 0)
+              cx = XXASS;
+        }
+        if ((y = cmtxt("Definition of macro","",&s,NULL)) < 0) return(y);
+#ifdef DEBUG
+        if (deblog) {
+            debug(F110,"xxdef macro name",vnp,0);
+            debug(F010,"xxdef macro def",s,0);
+        }
+#endif /* DEBUG */
+        s = brstrip(s);
+    }
+    if (*s == NUL) {                    /* No arg given, undefine */
+        delmac(vnp,1);                  /* 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 */
+        zzstring(s,&lp,&t);
+        s = line;
+    }
+    if (doeval == 2) {                  /* Arithmetic evaluation wanted too? */
+        ckstrncpy(line,evala(s),LINBUFSIZ);
+        line[LINBUFSIZ] = NUL;
+    }
+    /* 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);
+    } else if (cx == XXASX || cx == XXDFX) /* For _ASG or _DEF, */
+      return(1);                           /* don't change success variable */
+    else
+      return(success = 1);
+}
+#endif /* NOSPL */
+
+
+#ifndef NODIAL
+/*
+   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 number of matches found, with numbers stored
+   in an array accessible via getdnum().
+*/
+static char *dn_p[MAXDNUMS + 1];        /* Dial Number pointers */
+static char *dn_p2[MAXDNUMS + 1];       /* Converted dial number pointers */
+static int dn_x[MAXDNUMS + 1];          /* Type of call */
+static int dncount = 0;
+char * d_name = NULL;                   /* Dial name pointer */
+
+char *                                  /* Get dial directory entry name */
+getdname() {
+    return(d_name ? d_name : "");
+}
+
+char *
+getdnum(n) int n; {                     /* Get dial number n from directory */
+    if (n < 0 || n > dncount || n > MAXDNUMS)
+      return("");
+    else
+      return(dn_p[n]);
+}
+
+char *                  /* Check area code for spurious leading digit */
+chk_ac(i,buf) int i; char buf[]; {
+    char *p;
+    if (!buf)
+      return("");
+    p = (char *) buf;                   /* Country we are calling: */
+    if (i ==  44 ||                     /* UK */
+        i ==  49 ||                     /* Germany */
+        i ==  39 ||                     /* Italy */
+        i ==  31 ||                     /* Netherlands */
+        i == 351 ||                     /* Portugal */
+        i ==  55 ||                     /* Brazil */
+        i == 972 ||                     /* Israel */
+        i ==  41 ||                     /* Switzerland */
+        i ==  43 ||                     /* Austria */
+        i ==  42 ||                     /* Czech Republic */
+        i ==  36 ||                     /* Hungary */
+        i ==  30 ||                     /* Greece */
+        i == 352 ||                     /* Luxembourg */
+        i ==  48 ||                     /* Poland */
+        i ==  27 ||                     /* South Africa */
+        i ==  33 ||                     /* France (as of 1997) */
+        i ==  358                       /* Finland (ditto) */
+        ) {
+        if (buf[0] == '0')
+          p++;
+    }
+    return(p);
+}
+
+/* Call Is Long Distance -- Expand this to cover 10-digit local dialing etc */
+/*
+   src  = area code of caller
+   dest = area code of callee
+   Returns:
+     0 if call is local
+     1 if call is long distance
+     2 if call is local but area code must be dialed anyway
+*/
+static int
+callisld(src, dest) char * src, * dest; {
+    int i;
+    if (dialfld)                        /* Force long distance? */
+      return(1);
+    if (!strcmp(src,dest)) {            /* Area codes are the same */
+        for (i = 0; i < nlocalac; i++)  /* Is AC in the lc-area-codes list? */
+          if (!strcmp(src,diallcac[i]))
+            return(2);                  /* Yes so must be dialed */
+        return(0);                      /* No so don't dial it. */
+    }
+    for (i = 0; i < nlocalac; i++)      /* ACs not the same so look in list */
+      if (!strcmp(dest,diallcac[i]))    /* Match */
+        return(2);                      /* So local call with area code */
+    return(1);                          /* Not local so long-distance */
+}
+
+char pdsfx[64] = { NUL, NUL };
+
+#ifndef NOSPL
+static char *
+xdial(s) char *s; {                     /* Run dial string thru macro */
+    int x, m;
+    if (!dialmac)                       /* Dial macro name given? */
+      return(NULL);
+    if ((x = mxlook(mactab,dialmac,nmac)) < 0) /* Is the macro defined? */
+      return(NULL);
+    m = maclvl;
+    x = dodo(x,s,0);                    /* Set up the macro */
+    if (x > 0) {
+        while (maclvl > m)              /* Execute the parser */
+          parser(1);
+        return(mrval[maclvl+1]);        /* Return the result */
+    }
+    return(NULL);
+}
+#endif /* NOSPL */
+
+static int
+dncvt(k,cx, prefix, suffix)
+    int k, cx, prefix, suffix; {        /* Dial Number Convert */
+    int i, j, n, what;                  /* cx is top-level command index */
+    char *ss;                           /* prefix - add prefixes? */
+    char *p, *p2, *pxo;                 /* suffix - add suffixes? */
+    char *lac;
+    char *npr;
+    char *sfx;
+    /* char *psfx; */
+    char ccbuf[128];
+    int cc;
+    char acbuf[24];
+    char *acptr;
+    char outbuf[256];
+/*
+  First pass for strict (punctuation-based) interpretation.
+  If it fails, we try the looser (length-based) one.
+*/
+    dialtype = -1;
+    what = 0;                           /* Type of call */
+    s = dn_p[k];                        /* Number to be converted. */
+    debug(F111,"dncvt",s,k);
+    if (dn_p2[k]) {
+        free(dn_p2[k]);
+        dn_p2[k] = NULL;
+    }
+    if (!s) {
+        printf("Error - No phone number to convert\n");
+        return(-1);
+    }
+    if ((int)strlen(s) > 200) {
+        ckstrncpy(outbuf,s,40);
+        printf("?Too long: \"%s...\"\n",outbuf);
+        return(-1);
+    }
+    npr = (prefix && dialnpr) ? dialnpr : "";
+    sfx = (suffix && dialsfx) ? dialsfx : "";
+    /* if (partial) psfx = dialsfx ? dialsfx : ""; */
+    pxo = (prefix && dialpxo) ? dialpxo : "";
+    lac = diallac ? diallac : "";       /* Local area code */
+
+    outbuf[0] = NUL;                    /* Initialize conversion buffer */
+    ss = s;                             /* Remember original string */
+
+    if (*s != '+') {                    /* Literal number */
+        dn_x[k] = DN_UNK;               /* Sort key is "unknown". */
+        ckmakmsg(outbuf,256,            /* Sandwich it between */
+                 pxo,npr,s,sfx          /* DIAL PREFIX and SUFFIX */
+                );
+#ifdef CK_TAPI
+        if (tttapi &&                   /* TAPI does its own conversions */
+            !tapipass &&                /* if not in passthru mode */
+            tapiconv == CK_AUTO ||      /* and TAPI conversions are AUTO */
+            tapiconv == CK_ON           /* OR if TAPI conversions are ON */
+            ) {
+            char * p = NULL;
+            dialtype = -2;
+            if (!cktapiConvertPhoneNumber(dn_p[k], &p))
+              return(-1);
+            makestr(&dn_p2[k], p);
+            if (p) free(p);
+            return(0);
+        } else
+#endif /* CK_TAPI */
+          makestr(&dn_p2[k], outbuf);   /* Not TAPI */
+        dialtype = what;
+        return(0);                      /* Done. */
+    }
+    i = 0;                              /* Portable number */
+    s++;                                /* Tiptoe past the plus sign */
+    ccbuf[0] = NUL;                     /* Do country code first */
+
+    if (!diallcc) {                     /* Do we know our own? */
+        if (cx != XXLOOK)
+          printf("Error - prior SET DIAL COUNTRY-CODE command required\n");
+        return(-1);
+    }
+
+    /* Parse the number */
+
+    while (1) {                         /* Get the country code */
+        while (*s == HT || *s == SP)
+          s++;
+        if (!s)                         /* Not in standard format */
+          break;
+        if (*s == '(') {                /* Beginning of area code  */
+            s++;                        /* Skip past parenthesis   */
+            ccbuf[i] = NUL;             /* End of country code */
+            if (!s) {                   /* Check for end of string */
+                printf("Error - phone number ends prematurely: \"%s\"\n",ss);
+                return(-1);
+            }
+            break;
+        } else {                        /* Collect country code */
+            if (isdigit(*s))
+              ccbuf[i++] = *s;          /* copy this character */
+            s++;
+            if (!*s || i > 127)         /* watch out for memory leak */
+              break;
+        }
+    }
+    cc = atoi(ccbuf);                   /* Numeric version of country code */
+
+    i = 0;                              /* Now get area code */
+    acbuf[0] = NUL;                     /* Initialize area-code buffer */
+    acptr = acbuf;                      /* and pointer. */
+    while (1) {
+        while (*s == HT || *s == SP)    /* Ignore whitespace */
+          s++;
+        if (!s)                         /* String finished */
+          break;
+        if (*s == ')') {                /* End of area code  */
+            s++;                        /* Skip past parenthesis   */
+            acbuf[i] = NUL;             /* Terminate area-code buffer */
+            break;
+        } else {                        /* Part of area code */
+            if (isdigit(*s))            /* If it's a digit, */
+              acbuf[i++] = *s;          /* copy this character */
+            s++;                        /* Point to next */
+            if (!*s || i > 23)          /* Watch out for overflow */
+              break;
+        }
+    }
+
+/*
+   Here we strip any leading 0 for countries that we know have
+   0 as a long-distance prefix and do not have any area codes that
+   start with 0 (formerly also ditto for "9" in Finland...)
+*/
+    i = atoi(ccbuf);
+    acptr = chk_ac(i,acbuf);
+
+    while (*s == HT || *s == SP)        /* Skip whitespace */
+      s++;
+
+/* printf("S=[%s], ACPTR=[%s]\n",s,acptr); */
+
+    if (*s && *acptr) {                 /* Area code was delimited */
+
+        while (*s == '-' || *s == '.')  /* Skip past gratuitious punctuation */
+          s++;
+        if (!*s) s--;                   /* But not to end of string */
+
+        if (strcmp(diallcc,ccbuf)) {    /* Out of country? */
+            if (!dialixp) {             /* Need intl-prefix */
+                if (cx != XXLOOK)
+                  printf("Error - No international dialing prefix defined\n");
+                return(-1);
+            }
+            what = dn_x[k] = DN_INTL;
+            p  = (prefix && dialixp) ? dialixp : ""; /* Intl-prefix */
+            p2 = (suffix && dialixs) ? dialixs : ""; /* Intl-suffix */
+
+            /* Form the final phone number */
+#ifdef COMMENT
+            sprintf(pdsfx,"%s%s",p2,sfx); /* UNSAFE */
+            sprintf(outbuf,
+                    "%s%s%s%s%s%s%s%s",
+                    pxo,npr,p,ccbuf,acptr,s,p2,sfx
+                    );
+#else
+            ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL);
+            ckmakxmsg(outbuf,256,pxo,npr,p,ccbuf,acptr,s,p2,sfx,
+                      NULL,NULL,NULL,NULL);
+#endif /* COMMENT */
+
+        } else if ((x = callisld(lac,acptr)) >= 1) { /* In-country LD */
+            if (!diallac && cx != XXLOOK) { /* Don't know my own area code */
+                if (cc == 1)
+                  printf("WARNING - Prior SET DIAL AREA-CODE needed\n");
+            }
+            if (x == 2) {               /* Local call with area code */
+                what = dn_x[k] = DN_LOCAL;      /* Local-call */
+                p  = (prefix && diallcp) ? diallcp : ""; /* local-prefix */
+                p2 = (suffix && diallcs) ? diallcs : ""; /* local-suffix */
+            } else {
+                what = dn_x[k] = DN_LONG;       /* Long-distance */
+                for (i = 0; i < ntollfree; i++) { /* But toll-free too? */
+                    if (!strcmp(acptr,dialtfc[i])) {
+                        what = dn_x[k] = DN_FREE;
+                        break;
+                    }
+                }
+                if (what == DN_FREE) {  /* Toll-free call */
+                    p = (prefix && dialtfp) ? dialtfp :
+                        ((prefix && dialldp) ? dialldp : "");
+                    p2 = "";            /* no suffix */
+                } else {                        /* normal long distance */
+                    p  = (prefix && dialldp) ? dialldp : ""; /* ld-prefix */
+                    p2 = (suffix && diallds) ? diallds : ""; /* ld-suffix */
+                }
+            }
+            /* Form the number to be dialed */
+#ifdef COMMENT
+            sprintf(outbuf,"%s%s%s%s%s%s%s",
+                    pxo,npr,p,acptr,s,p2,sfx
+                    );
+            sprintf(pdsfx,"%s%s",p2,sfx);
+#else
+            ckmakxmsg(outbuf,256,
+                      pxo,npr,p,acptr,s,p2,sfx,
+                      NULL,NULL,NULL,NULL,NULL);
+            ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL);
+#endif /* COMMENT */
+        } else {                        /* Same country, same area code */
+            what = dn_x[k] = DN_LOCAL;  /* So it's a local call. */
+            if (!prefix || !(dialpxo || ndialpxx)) { /* Not dialing from PBX */
+                p  = (prefix && diallcp) ? diallcp : ""; /* local-prefix */
+                p2 = (suffix && diallcs) ? diallcs : ""; /* local-suffix */
+#ifdef COMMENT
+                if (x == 2)
+                  sprintf(outbuf,"%s%s%s%s%s%s",npr,p,acptr,s,p2,sfx);
+                else
+                  sprintf(outbuf,"%s%s%s%s%s",npr,p,s,p2,sfx);
+                sprintf(pdsfx,"%s%s",p2,sfx);
+#else
+                if (x == 2)
+                  ckmakxmsg(outbuf,256,
+                            npr,p,acptr,s,p2,sfx,
+                            NULL,NULL,NULL,NULL,NULL,NULL);
+                else
+                  ckmakxmsg(outbuf,256,
+                            npr,p,s,p2,sfx,
+                            NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+                ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL);
+#endif /* COMMENT */
+
+            } else {                    /* Dialing from a PBX and not TAPI */
+                if (ndialpxx) {         /* Is it internal? */
+#ifdef COMMENT
+                    i = (int) strlen(dialpxx);
+                    j = (int) strlen(s);
+                    x = -1;
+                    if (j > i)
+                      x = ckstrcmp(dialpxx,s,i,0);
+#else
+                    int kx;
+                    x = -1;
+                    j = (int) strlen(s);
+                    for (kx = 0; kx < ndialpxx; kx++) {
+                        i = (int) strlen(dialpxx[kx]);
+                        if (j > i)
+                          if (!(x = ckstrcmp(dialpxx[kx],s,i,0)))
+                            break;
+                    }
+#endif /* COMMENT */
+                    if (!x) {
+                        char * icp, buf[32];
+                        makestr(&matchpxx,dialpxx[kx]);
+                        debug(F111,"dncvt matchpxx",matchpxx,kx);
+                        what = dn_x[kx] = DN_INTERN;   /* Internal call. */
+                        s += i;
+                        /* Internal-call prefix */
+                        icp = dialpxi;
+#ifndef NOSPL
+                        if (icp) {
+                            if (*icp == '\\') {
+                                char c, *bp;
+                                int n;
+                                c = *(icp+1);
+                                if (isupper(c)) c = tolower(c);
+                                if (c == 'v' || c == 'f') {
+                                    n = 32;
+                                    bp = buf;
+                                    zzstring(icp,&bp,&n);
+                                    icp = buf;
+                                }
+                            }
+                        }
+#endif /* NOSPL */
+                        p = (prefix && icp) ? icp : "";
+#ifdef COMMENT
+                        sprintf(outbuf,"%s%s%s%s",npr,p,s,sfx);
+#else
+                        ckmakmsg(outbuf,256,npr,p,s,sfx);
+#endif /* COMMENT */
+                    } else {            /* External local call */
+                        /* local-prefix */
+                        p  = (prefix && diallcp) ? diallcp : "";
+                        /* local-suffix */
+                        p2 = (prefix && diallcs) ? diallcs : "";
+#ifdef COMMENT
+                        if (x == 2)
+                          sprintf(outbuf,"%s%s%s%s%s%s%s",
+                                  dialpxo ? dialpxo : "",
+                                  npr,p,acptr,s,p2,sfx);
+                        else
+                          sprintf(outbuf,
+                                  "%s%s%s%s%s%s",
+                                  dialpxo ? dialpxo : "",
+                                  npr,p,s,p2,sfx
+                                  );
+#else
+                        if (x == 2)
+                          ckmakxmsg(outbuf, 256,
+                                   dialpxo ? dialpxo : "",
+                                   npr,p,acptr,s,p2,sfx,
+                                   NULL,NULL,NULL,NULL,NULL);
+                        else
+                          ckmakxmsg(outbuf, 256,
+                                    dialpxo ? dialpxo : "",
+                                    npr,p,s,p2,sfx,
+                                    NULL,NULL,NULL,NULL,NULL,NULL);
+#endif /* COMMENT */
+                    }
+                }
+            }
+        }
+
+    } else {                            /* Area code was not delimited */
+
+        char xbuf[256];                 /* Comparison based only on length */
+        char ybuf[256];
+        int x, j;
+
+        s = ss;
+
+        for (i = 0; i < 255; i++) {
+            if (!*s) break;
+            while (!isdigit(*s)) {      /* Pay attention only to digits */
+                s++;
+                if (!*s) break;
+            }
+            xbuf[i] = *s++;
+        }
+        xbuf[i] = NUL;
+
+        x = 1;                          /* Assume LD */
+        n = 0;
+        if (!dialfld) {                 /* If LD not forced */
+            for (j = 0; j < nlocalac; j++) { /* check local AC list? */
+                ckmakmsg(ybuf,256,diallcc,diallcac[j],NULL,NULL);
+                n = (int) strlen(ybuf);
+                if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0)) {
+                    x = 2;
+                    break;
+                }
+            }
+            if (x == 1) {               /* Or exact match with local CC+AC? */
+                ckmakmsg(ybuf,256,diallcc,lac,NULL,NULL);
+                n = (int) strlen(ybuf);
+                if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0))
+                  x = 0;
+            }
+        }
+        if (x == 0 || x == 2) {         /* Local call */
+            int xx,kx;                  /* Begin 1 Dec 2001... */
+            /* Account for PBX internal calls */
+            if (ndialpxx) {
+                xx = -1;
+                j = (int) strlen(ybuf);
+                for (kx = 0; kx < ndialpxx; kx++) {
+                    i = (int) strlen(dialpxx[kx]);
+                    if (j >= i)
+                      if (!(xx = ckstrcmp(dialpxx[kx],&xbuf[j],i,0)))
+                        break;
+                }
+            }
+            if (!xx) {
+                char * icp, buf[32];
+                makestr(&matchpxx,dialpxx[kx]);
+                debug(F111,"dncvt matchpxx",matchpxx,kx);
+                what = dn_x[kx] = DN_INTERN; /* Internal call. */
+                s = xbuf + j + i;
+                icp = dialpxi;          /* Internal-call prefix */
+#ifndef NOSPL
+                if (icp) {
+                    if (*icp == '\\') {
+                        char c, *bp;
+                        int n;
+                        c = *(icp+1);
+                        if (isupper(c)) c = tolower(c);
+                        if (c == 'v' || c == 'f') {
+                            n = 32;
+                            bp = buf;
+                            zzstring(icp,&bp,&n);
+                            icp = buf;
+                        }
+                    }
+                }
+#endif /* NOSPL */
+                p = (prefix && icp) ? icp : "";
+                ckmakmsg(outbuf,256,npr,p,s,sfx);
+                /* End 1 Dec 2001... */
+
+            } else {                    /* Not PBX internal */
+
+                dn_x[k] = DN_LOCAL;
+                p = (prefix && diallcp) ? diallcp : "";
+                p2 = (suffix && diallcs) ? diallcs : "";
+                s = (char *) (xbuf + ((x == 0) ? n : (int)strlen(diallcc)));
+                ckmakxmsg(outbuf,256,
+                          pxo,npr,p,s,p2,sfx,
+                          NULL,NULL,NULL,NULL,NULL,NULL);
+                ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL);
+            }
+        } else {                        /* Not local */
+            n = ckstrncpy(ybuf,diallcc,256);
+            if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0)) { /* Long distance */
+                dn_x[k] = DN_LONG;
+                p = (prefix && dialldp) ? dialldp : "";
+                p2 = (suffix && diallds) ? diallds : "";
+                s = xbuf + n;
+                while (*s == '-' || *s == '.')
+                  s++;
+#ifdef COMMENT
+                sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,s,p2,sfx);
+                sprintf(pdsfx,"%s%s",p2,sfx);
+#else
+                ckmakxmsg(outbuf,256,
+                          pxo,npr,p,s,p2,sfx,
+                         NULL,NULL,NULL,NULL,NULL,NULL);
+                ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL);
+#endif /* COMMENT */
+            } else {
+                dn_x[k] = DN_INTL;      /* International */
+                if (!dialixp) {
+                    if (cx != XXLOOK) {
+                        printf(
+                          "Error - No international dialing prefix defined\n"
+                               );
+                        return(-1);
+                    }
+                }
+                p = (prefix && dialixp) ? dialixp : "";
+                p2 = (suffix && dialixs) ? dialixs : "";
+#ifdef COMMENT
+                sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,xbuf,p2,sfx);
+                sprintf(pdsfx,"%s%s",p2,sfx);
+#else
+                ckmakxmsg(outbuf,256,
+                          pxo,npr,p,xbuf,p2,sfx,
+                          NULL,NULL,NULL,NULL,NULL,NULL);
+                ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL);
+#endif /* COMMENT */
+            }
+        }
+    }
+#ifdef CK_TAPI
+    if (tttapi &&                       /* TAPI performs the conversions */
+        !tapipass &&
+        tapiconv == CK_AUTO ||
+        tapiconv == CK_ON
+        ) {
+        p = NULL;
+        dialtype = -2;
+        if (!cktapiConvertPhoneNumber(dn_p[k],&p))
+          return(-1);
+        makestr(&dn_p2[k], p);
+        if (p) free(p);
+        return(0);
+    } else {
+#endif /* CK_TAPI */
+        makestr(&dn_p2[k], outbuf);
+#ifdef CK_TAPI
+    }
+#endif /* CK_TAPI */
+    dialtype = what;
+    return(0);
+}
+
+static int
+ddcvt(s, f, n) char * s; FILE * f; int n; { /* Dial Directory Convert */
+    char linebuf[1024], *s2;            /* Buffers and pointers */
+#ifdef VMS
+    char * temp = NULL;
+#endif /* VMS */
+    char *info[8];                      /* Pointers to words from entry */
+    FILE * f2 = NULL;
+    int x, rc;
+    rc = -1;
+
+    debug(F110,"ddcvt file",s,0);
+
+    if (!s || !f)                       /* No filename or file */
+      return(-1);
+    if (!*s)
+
+    fclose(f);
+    znewn(s,&s2);                       /* s2 = address of static buffer */
+    debug(F110,"ddcvt newname",s2,0);
+
+#ifdef VMS
+    /* In VMS, znewn() returns the same file name with a new version number */
+    makestr(&temp,s);                   /* Swap - otherwise the new */
+    s = s2;                             /* version has the older version */
+    s2 = temp;                          /* number... */
+    debug(F110,"ddcvt after swap s",s,0);
+    debug(F110,"ddcvt after swap s2",s2,0);
+    makestr(&(dialdir[n]),s);           /* New file gets new version number */
+    debug(F110,"ddcvt after makestr s2",s2,0);
+    debug(F111,"ddcvt dialdir[n]",dialdir[n],n);
+#else
+    if (zrename(s,s2) < 0) {            /* Not VMS - rename old file */
+        perror(s2);                     /* to new (wierd) name. */
+        goto ddexit;
+    }
+#endif /* VMS */
+    debug(F110,"ddcvt s2 (old)",s2,0);
+    if ((f = fopen(s2,"r")) == NULL) {  /* Reopen old file with wierd name */
+        debug(F110,"ddcvt s2 open error",ck_errstr(),0);
+        dirline = 0;                    /* (or in VMS, old version) */
+        perror(s2);
+        goto ddexit;
+    }
+    debug(F110,"ddcvt fopen(s2) OK",s2,0);
+
+    debug(F110,"ddcvt s (new)",s,0);
+    if ((f2 = fopen(s,"w")) == NULL) {  /* Create new file with old name */
+        debug(F110,"ddcvt s open error",ck_errstr(),0);
+        perror(s);                      /* (or in VMS, new version) */
+        goto ddexit;
+    }
+    debug(F110,"ddcvt fopen(s) OK",s,0);
+
+    printf("\nSaving old directory as %s.\nConverting %s...",s2,s);
+    fprintf(f2,"; %s - Kermit dialing directory\n", s);
+    fprintf(f2,"%-16s %-20s ; %5s %-6s ; %s\n",
+               "; Name","Number","Speed","Parity","Comment"
+               );
+
+    while (1) {
+        linebuf[0] = NUL;               /* Read a line */
+        if (fgets(linebuf,1023,f) == NULL)
+          break;
+        debug(F110,"ddcvt linebuf",linebuf,0);
+        if (!linebuf[0]) {              /* Empty line */
+            fprintf(f2,"\n");
+            continue;
+        }
+        x = (int) strlen(linebuf);      /* Strip line terminator, */
+        while (x-- > 0) {               /* if any. */
+            if (linebuf[x] <= SP)
+              linebuf[x] = NUL;
+            else
+              break;
+        }
+        xwords(linebuf,5,info,1);       /* Parse it the old way */
+        for (x = 1; x < 6; x++)
+          if (!info[x]) info[x] = "";
+        fprintf(f2,"%-16s %-20s ; %5s %-6s %s\n",
+               info[1],info[2],info[3],info[4],info[5]
+               );
+    }
+    printf(" OK\n\n");
+    rc = 0;                             /* Success */
+  ddexit:
+    if (f) fclose(f);
+    if (f2) fclose(f2);
+#ifdef VMS
+    if (temp) free(temp);
+#endif /* VMS */
+    return(rc);
+}
+
+int                                     /* s = name to look up   */
+#ifdef CK_ANSIC                         /* cx = index of command */
+ludial(char *s, int cx)                 /* (DIAL, LOOKUP, etc)   */
+#else
+ludial(s, cx) char *s; int cx;
+#endif /* CK_ANSIC */
+/* ludial */ {
+
+    int dd, n1, n2, n3, i, j, t;        /* Workers */
+    int olddir, newdir, oldentry, newentry;
+    int pass = 0;
+    int oldflg = 0;
+    int ambiguous = 0;                  /* Flag for lookup was ambiguous */
+    char *info[7];                      /* Pointers to words from entry */
+    char *pp;                           /* Pointer to element of array */
+    FILE * f;
+    char *line;                         /* File input buffer */
+
+/* #define LUDEBUG */
+
+#ifdef LUDEBUG
+int zz = 1;
+#endif /* LUDEBUG */
+
+    if (!s || ndialdir < 1)             /* Validate arguments */
+      return(-1);
+
+    if ((n1 = (int) strlen(s)) < 1)     /* Length of string to look up */
+      return(-1);
+
+    if (!(line = malloc(1024)))         /* Allocate input buffer */
+      return(-1);
+
+#ifdef LUDEBUG
+if (zz) printf("LUDIAL 1 s[%s], n1=%d\n",s,n1);
+#endif /* LUDEBUG */
+
+    pass = 0;
+  lu_again:
+    f = NULL;                           /* Dial directory file descriptor */
+    t = dncount = 0;                    /* Dial-number match count */
+    dd = 0;                             /* Directory counter */
+    olddir = 0;
+    newdir = 0;
+/*
+  We need to recognize both old- and new-style directories.
+  But we can't allow old-style and new-style entries in the same
+  directory because there is no way to tell for sure the difference between
+  an old-style entry like this:
+
+    foo  5551212  9600
+
+  and a new-style literal entry like this:
+
+    foo  555 9600
+
+  I.e. is the "9600" a speed, or part of the phone number?
+*/
+    while (1) {                         /* We make one pass */
+        if (!f) {                       /* Directory not open */
+            if (dd >= ndialdir)         /* No directories left? */
+              break;                    /* Done. */
+            debug(F111,"ludial dialdir[dd]",dialdir[dd],dd);
+            if ((f = fopen(dialdir[dd],"r")) == NULL) { /* Open it */
+                perror(dialdir[dd]);    /* Can't, print message saying why */
+                if (line) {
+                    free(line);
+                    line = NULL;
+                }
+                dd++;                   /* Go on to next one, if any... */
+                continue;
+            }
+            dirline = 0;                /* Directory file line number */
+            if (dialdpy && !pass)
+              printf("Opening: %s...\n",dialdir[dd]);
+            dd++;
+            if (!oldflg) olddir = 0;
+            newdir = 0;
+        }
+        oldentry = 0;
+        newentry = 0;
+        line[0] = NUL;
+        if (getnct(line,1023,f,1) < 0) { /* Read a line */
+            if (f) {                    /* f can be clobbered! */
+                fclose(f);              /* Close the file */
+                f = NULL;               /* Indicate next one needs opening */
+                oldflg = 0;
+            }
+            continue;
+        }
+        if (!line[0])                   /* Empty line */
+          continue;
+#ifdef LUDEBUG
+if (zz) printf("LUDIAL 2 s[%s]\n",s);
+#endif /* LUDEBUG */
+
+        /* Make a copy and parse it the old way */
+        /* A copy is needed because xwords() pokes NULs into the string */
+
+        if ((pp = malloc((int)strlen(line) + 1))) {
+            strcpy(pp,line);            /* safe */
+            xwords(pp,5,info,0);        /* Parse it the old way */
+
+#ifdef LUDEBUG
+if (zz) printf("LUDIAL 3 s[%s]\n",s);
+#endif /* LUDEBUG */
+
+            if (!info[1])
+              continue;
+            if (*info[1] == ';') {      /* If full-line comment, */
+                newdir = 1;             /* (only new directories have them) */
+                continue;               /* keep reading. */
+            }
+            if (!info[2])
+              continue;
+            if (*info[2] == '+')
+              newentry = 1;
+            if (info[4]) {
+                if ((*info[4] == '=') ||
+                    !ckstrcmp(info[4],"none", 4,0) ||
+                    !ckstrcmp(info[4],"even", 4,0) ||
+                    !ckstrcmp(info[4],"space",5,0) ||
+                    !ckstrcmp(info[4],"mark", 4,0) ||
+                    !ckstrcmp(info[4],"odd",  3,0)
+                    )
+                  oldentry = 1;
+            }
+        }
+        if (pp) {
+            free(pp);
+            pp = NULL;
+        }
+
+        /* Check consistency */
+
+        if ((oldentry || olddir) && (newentry || newdir)) {
+            printf(
+"\nERROR: You seem to have old- and new-format entries mixed in your\n");
+            printf(
+"dialing directory.  You'll have to edit it by hand to convert it to the\n");
+#ifndef NOHELP
+            printf("new format.  Type HELP DIAL for further information.\n\n");
+#else
+            printf("new format.\n\n");
+#endif /* NOHELP */
+            if (line) {
+                free(line);
+                line = NULL;
+            }
+            return(-1);
+        }
+        if (!olddir && oldentry) {
+            int convert = 0;
+            olddir = 1;
+            if (dialcvt == 2) {         /* 2 == ASK */
+                sprintf(tmpbuf,
+"WARNING: Old-style dialing directory detected:\n%s", line);
+               convert = uq_ok(tmpbuf,
+                               "Shall I convert it for you? ",3,NULL,0);
+            } else
+              convert = dialcvt;
+            if (convert) {
+                debug(F111,"ludial calling ddcvt",dialdir[dd-1],dd);
+                if (ddcvt(dialdir[dd-1],f,dd-1) < 0) {
+                    debug(F111,"ludial ddcvt failed",dialdir[dd-1],dd);
+                    oldflg = 1;
+                    printf(
+"  Sorry, can't convert.");
+                    printf(
+"  Will ignore speed and parity fields, continuing...\n\n");
+                } else {
+                    olddir = newdir = 0;
+                    debug(F111,"ludial ddcvt ok",dialdir[dd-1],dd);
+                }
+                dd--;
+                f = NULL;
+                continue;
+            } else {
+                if (dialcvt == 2)
+                  printf(
+"  OK, will ignore speed and parity fields, continuing...\n\n");
+                olddir = 1;
+            }
+        }
+
+#ifdef LUDEBUG
+if (zz) printf("LUDIAL XX s[%s], n1=%d\n",s,n1);
+#endif /* LUDEBUG */
+
+        /* Now parse again for real */
+
+        if (oldentry)                   /* Parse it the old way */
+          xwords(line,5,info,0);
+        else                            /* Parse it the new way */
+          xwords(line,2,info,1);
+
+#ifdef LUDEBUG
+if (zz) printf("LUDIAL YY s[%s], n1=%d\n",s,n1);
+if (zz) printf("%s [%s]\n",info[1],info[2]);
+#endif /* LUDEBUG */
+
+        if (info[1]) {                  /* First word is entry name */
+            if ((n3 = (int) strlen(info[1])) < 1) /* Its length */
+              continue;                 /* If no first word, keep reading. */
+            if (n3 < n1)                /* Search name is longer */
+              continue;                 /* Can't possibly match */
+            if (ambiguous && n3 != n1)
+              continue;
+
+#ifdef LUDEBUG
+if (zz) printf("MATCHING: [%s] [%s], n1=%d\n",s,info[1],n1);
+#endif /* LUDEBUG */
+
+            if (ckstrcmp(s,info[1],n1,0)) /* Caseless string comparison */
+              continue;
+
+#ifdef LUDEBUG
+if (zz) printf("MATCH OK: [%s] [%s], n1=%d\n",s,info[1],n1);
+#endif /* LUDEBUG */
+
+            if (!info[2])               /* No phone number given */
+              continue;
+            if ((n2 = (int) strlen(info[2])) < 1) /* Length of phone number */
+              continue;                 /* Ignore empty phone numbers */
+
+            /* Got one */
+
+            if (!(pp = (char *)malloc(n2 + 1))) { /* Allocate storage for it */
+                printf("?internal error - ludial malloc 1\n");
+                if (line) {
+                    free(line);
+                    line = NULL;
+                }
+                dncount = 0;
+                return(-1);
+            }
+            strcpy(pp,info[2]);         /* safe */
+
+            if (dncount > MAXDNUMS) {
+                printf("Warning: %d matches found, %d max\n",
+                       dncount,
+                       MAXDNUMS
+                       );
+                dncount = MAXDNUMS;
+                break;
+            }
+            dn_p[dncount++] = pp;       /* Add pointer to array. */
+            if (dncount == 1) {         /* First one... */
+                if (d_name) free(d_name);
+                if (!(d_name = (char *)malloc(n3 + 1))) { /* Save its name */
+                    printf("?internal error - ludial malloc 2\n");
+                    if (line) {
+                        free(line);
+                        line = NULL;
+                    }
+                    dncount = 0;
+                    return(-1);
+                }
+                t = n3;                 /* And its length */
+                strcpy(d_name,info[1]); /* safe */
+            } else {                    /* Second or subsequent one */
+
+#ifdef LUDEBUG
+                if (zz)
+                  printf("d_name=[%s],info[1]=%s,t=[%d]\n",d_name,info[1],t);
+#endif /* LUDEBUG */
+
+                if ((int) strlen(info[1]) == t) /* Lengths compare */
+                  if (!ckstrcmp(d_name,info[1],t,0)) /* Caseless compare OK */
+                    continue;
+
+                /* Name given by user matches entries with different names */
+
+                if (ambiguous)          /* Been here before */
+                  break;
+
+                ambiguous = 1;          /* Now an exact match is required */
+                for (j = 0; j < dncount; j++) { /* Clean out previous list */
+                    if (dn_p[j]) {
+                        free(dn_p[j]);
+                        dn_p[j] = NULL;
+                    }
+                }
+                pass++;                 /* Second pass... */
+                goto lu_again;          /* Do it all over again. */
+            }
+        }
+    }
+    if (line) free(line);
+    if (dncount == 0 && ambiguous) {
+        printf(" Lookup: \"%s\" - ambiguous%s\n",
+               s,
+               cx == XXLOOK ? "" : " - dialing skipped"
+               );
+        return(-2);
+    }
+    return(dncount);
+}
+
+char *
+pncvt(s) char *s; {                     /* Phone number conversion */
+    char *p = NULL;                     /* (just a wrapper for dncvt() */
+    char *q = NULL;
+    static char pnbuf[128];
+    makestr(&p,dn_p[0]);                /* Save these in case they are */
+    makestr(&q,dn_p2[0]);               /* being used */
+    makestr(&dn_p[0],s);                /* Copy the argument string to here */
+    dncvt(0,XXLOOK,1,1);                /* Convert it */
+    if (!dn_p2[0])                      /* Put result where can return it */
+      pnbuf[0] = NUL;
+    else
+      ckstrncpy(pnbuf,dn_p2[0],127);
+    makestr(&dn_p[0],p);                /* Restore these */
+    makestr(&dn_p2[0],q);
+    makestr(&p,NULL);                   /* Free these */
+    makestr(&q,NULL);
+    return((char *)pnbuf);
+}
+
+int
+dodial(cx) int cx; {                    /* DIAL or REDIAL */
+    int i = 0, x = 0;                   /* Workers */
+    int sparity = -1;                   /* For saving global parity value */
+    int previous = 0;
+    int len = 0;
+    int literal = 0;
+    int flowsave;
+    int lufound = 0;                    /* Did any lookup succeed? */
+    int prefix = 1;
+    int postfix = 1;
+    int wasalpha = 0;
+    int xredial = 0;
+    int braces = 0;
+
+    char *p = NULL, *s3 = NULL, * sav = NULL;
+    int j = 0, t = 0, n = 0;
+    int xretries, xlcc;
+
+    debug(F101,"dodial cx","",cx);
+    debug(F111,"dodial diallcc",diallcc,diallcc);
+
+    xretries = dialrtr;                 /* If retries not set, */
+    if (diallcc) {                      /* choose default based on */
+        xlcc = atoi(diallcc);           /* local country code. */
+        if (xretries < 0) {
+            switch (xlcc) {
+              case 1: xretries = 10; break; /* No restrictions in NANP */
+                /* Add other country codes here */
+                /* that are known to have no restrictions on redialing. */
+              default: xretries = 1;
+            }
+        }
+    }
+    if (cx == XXPDIA) {                 /* Shortcut... */
+        cx = XXDIAL;
+        partial = 1;
+        debug(F100,"PDIAL sets partial=1","",0);
+        postfix = 0;                    /* Do not add postfix */
+    } else {
+        partial = 0;
+        debug(F100,"DIAL sets partial=0","",0);
+    }
+    previous = dialsta;                 /* Status of previous call, if any */
+    if (previous == DIA_PART) {
+        prefix = 0;                     /* do not add prefix */
+    }
+    s = NULL;                           /* Initialize user's dial string */
+    if (cx == XXRED) {                  /* REDIAL or... */
+        if ((y = cmcfm()) < 0)
+          return(y);
+    } else if (cx == XXANSW) {          /* ANSWER or ... */
+        if ((y = cmnum("timeout (seconds)","0",10,&x,xxstring)) < 0)
+          return(y);
+        dialatmo = x;
+        if ((y = cmcfm()) < 0)
+          return(y);
+    } else {                            /* DIAL or LOOKUP */
+        if (ndialdir > 0)
+          s3 = "Number to dial or entry from dial directory";
+        else
+          s3 = "Number to dial";
+        if ((x = cmtxt(s3, dialnum ? dialnum : "",&s,xxstring)) < 0)
+          return(x);
+        if (s) {
+            len = (int) strlen(s);
+            ckstrncpy(tmpbuf,s,TMPBUFSIZ); /* Save literal copy */
+#ifdef COMMENT
+            if (len > 1) {              /* Strip outer braces if given */
+                if (*s == '{') {
+                    if (s[len-1] == '}') {
+                        s[len-1] = NUL;
+                        s++;
+                        len -= 2;
+                    }
+                }
+            }
+#else
+            s = brstrip(s);             /* Strip outer braces or quotes */
+#endif /* COMMENT */
+        }
+    }
+
+    if (cx != XXLOOK) {                 /* Not LOOKUP */
+#ifdef IKSD
+        if (inserver) {
+            printf("Sorry, dialing is disabled.\r\n");
+            return(success = 0);
+        }
+#endif /* IKSD */
+#ifdef CK_TAPI
+        if (tttapi && !tapipass) {
+          ;                             /* Skip the modem test if TAPI */
+        } else
+#endif /* CK_TAPI */
+        if (mdmtyp < 1 && !dialtest) {
+            if (network
+#ifdef TN_COMPORT
+                 && !istncomport()
+#endif /* TN_COMPORT */
+                 )
+              printf("Please SET HOST first, and then SET MODEM TYPE\n");
+            else
+              printf("Sorry, you must SET MODEM TYPE first\n");
+            dialsta = DIA_NOMO;
+            return(success = 0);
+        }
+        if (!local && !dialtest) {
+            printf("Sorry, you must SET %s or SET HOST first\n",
+#ifdef OS2
+                   "PORT"
+#else
+                   "LINE"
+#endif /* OS2 */
+                   );
+            dialsta = DIA_NOLI;
+            return(success = 0);
+        }
+        if ((!network 
+#ifdef TN_COMPORT
+              || istncomport()
+#endif /* TN_COMPORT */
+              ) && !dialtest &&
+#ifdef CK_TAPI
+             !tttapi &&
+#endif /* CK_TAPI */
+            (speed < 0L)
+#ifdef UNIX
+            && (strcmp(ttname,"/dev/null"))
+#else
+#ifdef OSK
+            && (strcmp(ttname,"/nil"))
+#endif /* OSK */
+#endif /* UNIX */
+            ) {
+            printf("\nSorry, you must SET SPEED first\n");
+            dialsta = DIA_NOSP;
+            return(success = 0);
+        }
+    }
+    if (cx != XXANSW) {
+        for (j = 0; j < MAXDNUMS; j++) { /* Initialize dial-number list */
+            if (!dialnum) {             /* First time dialing */
+                dn_p[j] = NULL;         /* initialize all pointers. */
+                dn_p2[j] = NULL;
+            } else if (dn_p[j]) {       /* Not the first time, */
+                free(dn_p[j]);          /* free previous, if any, */
+                dn_p[j] = NULL;         /* then set to NULL. */
+                if (dn_p2[j])
+                  free(dn_p2[j]);
+                dn_p2[j] = NULL;
+            } else break;               /* Already NULL */
+        }
+        if (len == 0)
+          s = NULL;
+        if (!s)
+          s = dialnum;
+        if (!s) {
+            if (cx == XXLOOK)
+              printf("?Lookup what?\n");
+            else
+              printf("%s\n", (cx == XXRED) ?
+                   "?No DIAL command given yet" :
+                   "?You must specify a number to dial"
+                   );
+            return(-9);
+        }
+
+    /* Now we have the "raw" dial or lookup string and s is not NULL */
+
+        makestr(&dscopy,s);             /* Put it in a safe place */
+        s = dscopy;
+        n = 0;
+
+        debug(F111,"dodial",s,ndialdir);
+
+        wasalpha = 0;
+        if (isalpha(*s)) {
+            wasalpha = 1;
+            if (ndialdir > 0) {         /* Do we have a dialing directory? */
+                n = ludial(s,cx);       /* Look up what the user typed */
+                if (n == 0)
+                  printf(" Lookup: \"%s\" - not found%s\n",
+                         s,
+                         cx == XXLOOK ? "" : " - dialing as given\n"
+                         );
+            }
+            debug(F101,"dodial",s,n);
+            if (n < 0 && cx != XXLOOK) { /* Error out if they wanted to dial */
+                if (n == -1)            /* -2 means ludial already gave msg */
+                  printf(" Lookup: fatal error - dialing skipped\n");
+                dialsta = DIA_DIR;
+                return(-9);
+            }
+            if (n > 0)                  /* A successful lookup */
+              lufound = 1;
+        } else if (*s == '=') {         /* If number starts with = sign */
+            s++;                        /* strip it */
+            literal = 1;                /* remember this */
+            while (*s == SP) s++;       /* and then also any leading spaces */
+        } else if (tmpbuf[0] == '{' && tmpbuf[1] == '{') {
+            makelist(tmpbuf,dn_p,MAXDNUMS);
+            makestr(&dscopy,tmpbuf);
+            s = tmpbuf;
+            for (n = 0; n < MAXDNUMS; n++) /* (have to count how many) */
+              if (!dn_p[n]) break;
+            braces = 1;
+        }
+        if (cx == XXLOOK && !wasalpha && !braces) {
+            /* We've been told to lookup a number or a quoted name */
+            char *p;
+            n = 0;
+            p = literal ? s : pncvt(dscopy);
+            if (!p) p = "";
+            if (*p) {
+                printf("%s  => %s\n", dscopy, p);
+                return(success = 1);
+            } else {
+                printf("?Bad phone number\n");
+                return(success = 0);
+            }
+        }
+        /* Save DIAL or successful LOOKUP string for future DIAL or REDIAL */
+        /* But don't save pieces of partial dial ... */
+
+        debug(F101,"DIAL save dialnum partial","",partial);
+        debug(F101,"DIAL save dialnum previous","",previous);
+        if ((cx == XXDIAL && partial == 0 && previous != DIA_PART) ||
+            (cx == XXLOOK && n > 0)) {
+            makestr(&dialnum,dscopy);
+            if (!quiet && dscopy && !dialnum)
+              printf("WARNING - memory allocation failure: redial number\n");
+        }
+        if (n > 0) {
+            if (!quiet && !backgrd && !braces /* && dialdpy */ ) {
+                if (!strcmp(d_name,s))
+                  printf(" Lookup: \"%s\" - exact match\n",s);
+                else
+                  printf(" Lookup: \"%s\" - uniquely matches \"%s\"\n",
+                         s,
+                         d_name
+                         );
+            }
+            if ((cx == XXLOOK) ||
+                ((n > 1) && !quiet && !backgrd /* && dialdpy */ )) {
+                printf(" %d telephone number%sfound for \"%s\"%s\n",
+                       n,
+                       (n == 1) ? " " : "s ",
+                       s,
+                       (n > 0) ? ":" : "."
+                       );
+                s3 = getdname();
+            }
+            for (i = 0; i < n; i++) {   /* Convert */
+                dn_x[i] = -1;
+                if (dncvt(i,cx,prefix,postfix) < 0) {
+                    if (cx != XXLOOK) {
+                        dialsta = DIA_DIR;
+                        return(-9);
+                    }
+                }
+            }
+            if (dialsrt && n > 1) {     /* Sort into optimal order */
+                for (i = 0; i < n-1; i++) {
+                    for (j = i+1; j < n; j++) {
+                        if (dn_x[j] < dn_x[i]) {
+                            t = dn_x[j];
+                            dn_x[j] = dn_x[i];
+                            dn_x[i] = t;
+                            p = dn_p[j];
+                            dn_p[j] = dn_p[i];
+                            dn_p[i] = p;
+                            p = dn_p2[j];
+                            dn_p2[j] = dn_p2[i];
+                            dn_p2[i] = p;
+                        }
+                    }
+                }
+            }
+            if ((cx == XXLOOK) ||
+                ((n > 1) && !quiet && !backgrd /* && dialdpy */ )) {
+                int nn = n;
+#ifndef NOSPL
+                char * p;
+#endif /* NOSPL */
+                if (cx != XXLOOK)
+                  if (n > 12) nn = 12;
+                for (i = 0; i < nn; i++) {
+                    printf("%3d. %-12s  %-20s =>  %-20s  (%d)\n",i+1,
+                           s3, dn_p[i],
+                           dn_p2[i] ? dn_p2[i] : "(processing failed)",
+                           dn_x[i]
+                           );
+                }
+                if (cx != XXLOOK && n != nn)
+                  printf("And %d more...\n", n - nn);
+            }
+        } else if (n == 0) {            /* Not found in directory */
+            makestr(&(dn_p[0]),literal ? s : dscopy);
+            makestr(&d_name,literal ? s : dscopy);
+            dncount = 1;
+            n = 1;
+            if (dncvt(0,cx,prefix,postfix) < 0) { /* In case they typed a */
+                dialsta = DIA_DIR;      /* portable-format number ... */
+                return(-9);
+            }
+        }
+
+#ifndef NONET
+#ifdef NETCONN
+        /* It's not good that the networks directory depends on NOT-NODIAL.. */
+        if (cx == XXLOOK && dscopy) {   /* Networks here too... */
+            extern char *nh_p[], *nh_p2[], *n_name;
+            extern char *nh_px[4][MAXDNUMS+1];
+            n = -1;
+            if (nnetdir > 0) {          /* Do we have a network directory? */
+                dirline = 0;
+                n = lunet(dscopy);      /* Look up what the user typed */
+            }
+            if (n > -1) {
+                int k;
+                if (n > 0)              /* A successful lookup */
+                  lufound = 1;
+                if (cx == XXLOOK && n == 0)
+                  printf(" Lookup: \"%s\" - not found\n",dscopy);
+                else
+                  printf("%s %d network entr%s found for \"%s\"%s\n",
+                         cx == XXLOOK ? " Lookup:" : "",
+                         n,
+                         (n == 1) ? "y" : "ies",
+                         dscopy,
+                         (n > 0) ? ":" : "."
+                         );
+
+                for (i = 0; i < n; i++) {
+
+                    printf("%3d. %-12s => %-9s %s",
+                           i+1,n_name,nh_p2[i],nh_p[i]);
+                    for (k = 0; k < 4; k++) {
+                        if (nh_px[k][i]) {
+                            printf(" %s",nh_px[k][i]);
+                        } else
+                          break;
+                    }
+                    printf("\n");
+                }
+            }
+        }
+#endif /* NETCONN */
+#endif /* NONET */
+        if (cx == XXLOOK)
+          return(success = lufound);
+    } /* cx != XXANSW */
+
+#ifdef VMS
+    conres();                   /* So Ctrl-C/Y will work */
+#endif /* VMS */
+/*
+  Some modems do not react well to parity.  Also, if we are dialing through a
+  TCP/IP TELNET modem server, parity can be fatally misinterpreted as TELNET
+  negotiations.
+
+  This should work even if the user interrupts the DIAL command, because the
+  DIAL module has its own interrupt handler.  BUT... if, for some reason, a
+  dialing device actually *requires* parity (e.g. CCITT V.25bis says that even
+  parity should be used), this might prevent successful dialing.  For that
+  reason, we don't do this for V.25bis modems.
+*/
+    sparity = parity;                   /* Save current parity */
+    if ((dialcapas & CKD_V25) == 0)     /* If not V.25bis...  */
+      parity = 0;                       /* Set parity to NONE */
+
+    flowsave = flow;
+/*
+  These modems use some kind of screwy flow control while in command mode,
+  and do not present CTS as they should.  So if RTS/CTS is set (or even if
+  it isn't) disable flow control during dialing.
+*/
+#ifndef MINIDIAL
+    if (mdmtyp == n_ATT1910 || mdmtyp == n_ATT1900) {
+        flow = FLO_NONE;                /* This is not enough */
+#ifdef CK_TTSETFLOW
+        ttsetflow(FLO_NONE);            /* Really turn it off */
+#endif /* CK_TTSETFLOW */
+    }
+#endif /* MINIDIAL */
+    if (!network
+#ifdef TN_COMPORT
+        || istncomport()
+#endif /* TN_COMPORT */
+         ) {
+        int x;
+        if ((x = ttgmdm()) > -1) {
+            if (!x && msgflg) {
+                printf(
+"WARNING - No modem signals detected.  Is your modem turned on?  If not,\n\
+use Ctrl-C to interrupt dialing, turn on your modem, then %s.\n",
+                       cx == XXANSW ?
+                       "ANSWER again" :
+                       "REDIAL"
+                       );
+            }
+            if (flow == FLO_RTSC) {
+                if (!(x & BM_CTS)) {
+                    if (msgflg)
+                      printf(
+"WARNING - SET FLOW RTS/CTS is in effect but modem's CTS signal is off.\n\
+Disabling flow control temporarily %s...\n",
+                             cx == XXANSW ?
+                             "while waiting for call" :
+                             "during dialing"
+                             );
+                    flow = FLO_NONE;
+                }
+            }
+        }
+    }
+    if (cx == XXANSW) {                 /* ANSWER */
+        success = ckdial("",0,0,1,0);
+        goto dialfin;
+    }
+
+/* Edit 192 adds the ability to dial repeatedly. */
+
+    i = 0;
+    dialcount = 0;
+    do {
+        if (i > 0) printf("\nDial attempt %d of %d...\n", i+1, xretries);
+        dialcount = i+1;
+        success = 0;
+        /* And the ability to dial alternate numbers. */
+        /* Loop to dial each in a list of numbers for the same name... */
+        for (j = 0; j < n && !success; j++) { /* until one answers. */
+            s = dn_p2[j];               /* Next number in list */
+            if (dn_x[j] >= dialrstr) {  /* Dial restriction */
+                printf("Restricted: %s, skipping...\n",dn_p[j]);
+                continue;
+            }
+            xredial = (i == 0 && j == 0) ? 0 : 1;
+            if (!s) s = dn_p[j];
+
+#ifndef NOSPL
+            sav = s;
+            p = xdial(s);               /* Apply DIAL macro now */
+            if (p) s = p;
+#endif /* NOSPL */
+
+           /* Dial confirmation */
+           /* NOTE: the uq_xxx() calls allow for a GUI dialog */
+
+            if (i == 0 && dialcnf) {
+               char msgbuf[128];
+               ckmakmsg(msgbuf,128,"Dialing ",s,NULL,NULL);
+               x = uq_ok(msgbuf,"Is this number correct? ",3,NULL,0);
+                if (!x) {
+
+#ifndef COMMENT
+                   x = uq_txt(         /* Allow GUI dialog */
+#ifdef OS2
+" Please enter the correct number,\r\n or press Enter to skip.",
+#else
+" Please enter the correct number,\r\n or press Return to skip.",
+#endif /* OS2 */
+                              "Corrected phone number: ",
+                               1,
+                              NULL,
+                              atmbuf,
+                              ATMBL,
+                               s,
+                               DEFAULT_UQ_TIMEOUT
+                               );
+                   if (x && atmbuf[0]) { /* They gave a new one */
+                       s = atmbuf;
+                       makestr(&(dn_p2[j]), s);
+                   }                   
+
+#else  /* COMMENT */
+
+#ifdef CK_RECALL
+                    extern int on_recall;
+#endif /* CK_RECALL */
+                    cmsavp(psave,PROMPTL);
+                    cmsetp(
+#ifdef OS2
+" Please enter the correct number,\r\n or press Enter to skip: "
+#else
+" Please enter the correct number,\r\n or press Return to skip: "
+#endif /* OS2 */
+                           );
+                    cmini(ckxech);
+                    x = -1;
+                    if (pflag) prompt(NULL);
+#ifdef CK_RECALL
+                    on_recall = 0;
+#endif /* CK_RECALL */
+                    y = cmdgquo();
+                    cmdsquo(0);
+                    while (x < 0) {
+                        x = cmtxt("Corrected phone number","",&s,NULL);
+                        cmres();
+                    }
+                    if ((int) strlen(s) < 1) {
+                        cmsetp(psave);
+                        continue;
+                    }
+                    makestr(&(dn_p2[j]), s);
+                    cmdsquo(y);
+                    cmsetp(psave);
+#endif /* COMMENT */
+                }
+            }
+            if (dialtest) {             /* Just testing */
+                if (i + j == 0)
+                  printf("\nTESTING...\n");
+                if (dialmac)
+                  printf(" Number: \"%s\" => \"%s\"\n",sav,s);
+                else
+                  printf(" Number: \"%s\"\n",s);
+                dialsta = DIA_BUSY;
+                success = 0;
+            } else {
+                what |= W_DIALING;
+                success = ckdial(s,i,j,partial ? 3 : 0, xredial); /* Dial it */
+                what &= ~(W_DIALING);
+                if (!success) {
+                    if (dialsta < 8 ||  /* Break out if unrecoverable error */
+                        dialsta  == DIA_INTR ||
+                        dialsta  == DIA_ERR  ||
+                        previous == DIA_PART
+                        )
+                      break;
+                }
+            }
+        }
+        if (success)                    /* Succeeded, leave the outer loop */
+          break;
+        if (dialsta < 8 ||              /* Break out if unrecoverable error */
+            dialsta == DIA_INTR ||      /* Interrupted */
+            dialsta == DIA_NODT ||      /* No dialtone */
+            dialsta == DIA_NOAC ||      /* Access forbidden */
+            dialsta == DIA_BLCK ||      /* Blacklisted */
+            dialsta == DIA_DIR  ||      /* Dialing directory error */
+            dialsta == DIA_ERR  ||      /* Modem command error */
+            previous == DIA_PART)
+          break;
+        if (++i >= xretries)            /* Break out if too many tries */
+          break;
+        if (!backgrd && !quiet) {
+            if (dialint > 5)
+              printf(
+"\nWill redial in %d second%s- press any key to redial immediately.\n",
+                     dialint,
+                     dialint == 1 ? " " : "s "
+                     );
+            printf("Ctrl-C to cancel...\n");
+        }
+        x = dialint;                    /* Redial interval */
+        while (x-- > 0) {
+            if ((y = conchk()) > 0) {   /* Did they type something? */
+                while (y--) coninc(0);  /* Yes, absorb it */
+                break;                  /* And wake up */
+            }
+            sleep(1);                   /* No interrupt, sleep a sec */
+        }
+    } while (!success);
+
+  dialfin:
+
+    if (cx != XXLOOK) {
+        if (!success)
+          bleep((short) BP_FAIL);
+        else if (!quiet)
+          bleep((short) BP_NOTE);
+#ifdef OS2
+        setint();                       /* Fix OS/2 interrupts */
+#endif /* OS2 */
+        if (sparity > -1)
+          parity = sparity;             /* Restore parity if we saved it */
+        flow = flowsave;
+#ifdef OS2
+        ttres();                        /* Restore DIAL device */
+#endif /* OS2 */
+#ifdef VMS
+        concb((char)escape);            /* Restore console */
+#endif /* VMS */
+#ifdef OS2
+        {                               /* Set session title */
+            char * p, name[72];         /* in window list. */
+            char * q;
+            if (cx == XXANSW) {
+                q = "Incoming call";
+            } else {
+                if (d_name)
+                  q = d_name;
+                else if (dialnum)
+                  q = dialnum;
+                else if (ttname[0])
+                  q = ttname;
+                else q = "";
+            }
+            p = name;
+            if (success) {
+                strncpy(name,q,48);
+                while (*p) {            /* Uppercase it for emphasis. */
+                    if (islower(*p))
+                      *p = toupper(*p);
+                    p++;
+                }
+            } else
+              name[0] = NUL ;
+            os2settitle((char *) name, TRUE);
+        }
+#endif /* OS2 */
+    }
+    if (cx != XXLOOK) {
+        if (success) {
+            if (reliable == SET_AUTO) { /* It's not a reliable connection. */
+                reliable = SET_OFF;
+                debug(F101,"dodial reliable","",reliable);
+            }
+        } else {
+#ifndef NOHINTS
+            extern int hints;
+            if (hints && !quiet && dialsta != 9) { /* 9 == User interrupted */
+                extern int dialmhu, dialhng, dialdpy;
+                extern char * dialmsg[];
+                printf("\n*************************\n");
+                printf("DIAL-class command failed.\n");
+                printf("Modem type:  %s\n", gmdmtyp());
+                printf("Device:      %s\n", ttname);
+                printf("Speed:       %ld\n", speed);
+                printf("Dial status: %d",dialsta);
+                if (dialsta < 35 && dialmsg[dialsta])
+                  printf(" [%s]",dialmsg[dialsta]);
+                printf("\n");
+                if (dialsta == DIA_TIMO ||
+                    dialsta == DIA_NRDY ||
+                   (dialsta > 13 && dialsta != DIA_BUSY && dialsta != DIA_NOAN)
+                    ) {
+                    switch (dialsta) {
+                      case DIA_TIMO:
+                        printf(
+" . SET DIAL TIMEOUT to a greater value and try again.\n"
+                               );
+                        break;
+                      case DIA_NRSP:
+                      case DIA_NRDY:
+                      case DIA_NOIN:
+                        printf(
+" . Is the modem turned on?\n"
+                               );
+                        printf(
+" . Are you using the right communication port?\n"
+                               );
+                        break;
+                      case DIA_NODT:
+                        printf(
+" . Is the modem connected to the telephone line?\n"
+                               );
+                    }
+                    if (mdmtyp == n_GENERIC) {
+                        printf(
+" . Please choose a specific modem type with SET MODEM TYPE and try again.\n"
+                               );
+                        printf(
+"    SET MODEM TYPE ? to see the list of known modem types.\n"
+                               );
+                    } else {
+                        printf(
+" . Are you sure you have chosen the appropriate modem type?\n"
+                               );
+                    }
+                    if (speed > 19200L) {
+                        printf(
+" . Maybe the interface speed (%ld) is too fast:\n", speed
+                               );
+                        printf(
+"    SET SPEED to a lower speed and try again.\n"
+                               );
+                        printf(
+"    SET SPEED ? to see the list of valid speeds.\n"
+                               );
+                    }
+                    if (dialhng) {
+                        if (dialmhu)
+                          printf(
+" . SET MODEM HANGUP-METHOD RS232 and try again.\n"
+                                 );
+                        else
+                          printf(
+" . SET MODEM HANGUP-METHOD MODEM-COMMAND and try again.\n"
+                                 );
+                        printf(
+" . If that doesn't work, try again with SET DIAL HANGUP OFF.\n"
+                               );
+                    } else {
+                        printf(
+" . Give a HANGUP or SET DIAL HANGUP ON command and try again.\n"
+                               );
+                    }
+                    if (!dialdpy)
+                      printf(
+" . Use SET DIAL DISPLAY ON to watch the dialog between Kermit and modem.\n"
+                             );
+                }
+#ifndef NOSHOW
+                printf(
+" . SHOW COMMUNICATIONS, SHOW MODEM, SHOW DIAL to see current settings.\n"
+                       );
+#endif /* NOSHOW */
+
+#ifndef NOHELP
+                printf(
+" . HELP SET MODEM, HELP SET DIAL, and HELP DIAL for more information.\n"
+                       );
+#endif /* NOHELP */
+                printf("(Use SET HINTS OFF to suppress future hints.)\n");
+                printf("*************************\n\n");
+            }
+#endif /* NOHINTS */
+        }
+    }
+    return(success);
+}
+#endif /* NODIAL */
+
+/*  D O T Y P E  --  Type (display) a file with various options...  */
+
+#ifdef BIGBUFOK
+#define TYPBUFL 16384
+#else
+#define TYPBUFL 256
+#endif /* BIGBUFOK */
+
+int typ_lines = 0;                      /* \v(ty_ln) */
+int typ_mtchs = 0;                      /* \v(ty_lm) */
+static int typ_int = 0;                 /* Flag if TYPE interrupted */
+
+#ifdef UNICODE
+extern int fcharset, fileorder, byteorder, ucsorder;
+#define TYPXBUFL TYPBUFL+TYPBUFL+TYPBUFL+4
+static char * mp = NULL;
+static char * mbuf = NULL;
+static long xn = 0L;
+
+static int
+#ifdef CK_ANSIC
+storechar(char c)
+#else
+storechar(c) char c;
+#endif /* CK_ANSIC */
+{
+    if (!mp) return(-1);
+    if (++xn > TYPXBUFL)
+      return(-1);
+    debug(F111,"storechar xn",ckitoa((int)c),xn);
+    *mp++ = c;
+    return(0);
+}
+#endif /* UNICODE */
+
+static FILE * ofp = NULL;               /* For /OUTPUT: file */
+
+static int
+typeline(buf,len,outcs,ofp) char * buf; int len, outcs; FILE * ofp; {
+    register int i;
+
+    debug(F011,"typeline buf",buf,len);
+    /* debug(F101,"typeline outcs","",outcs); */
+
+#ifdef OS2
+#ifndef NOLOCAL
+#ifdef UNICODE
+    /* In K95 only, the buffer is guaranteed to be in UCS-2 if outcs >= 0. */
+    /* Len is its length in bytes.  There is no line terminator. */
+    /* outcs is the file character-set number (FC_xxx) of the target set */
+    /* that was requested by the user. */
+    if (!inserver && !k95stdout) {
+        extern int wherex[], wherey[];
+        extern unsigned char colorcmd;
+
+        VscrnWrtUCS2StrAtt( VCMD, (unsigned short *)buf, len/2,
+                           wherey[VCMD], wherex[VCMD], &colorcmd);
+        printf("\r\n");
+        return(0);
+    }
+#endif /* UNICODE */
+#endif /* NOLOCAL */
+#endif /* OS2 */
+
+/* In Unix, VMS, etc, the line has already been converted to the desired  */
+/* character-set, if one was given.  OR... on all platforms, including in */
+/* K95, we don't know the character set.  In either case we dump the line */
+/* byte by byte in case it contains NULs (printf() would truncate). */
+
+#ifdef COMMENT
+    for (i = 0; i < len; i++)
+      putchar(buf[i]);
+#else
+    for (i = 0; i < len; i++) {
+        if (ofp == stdout) {
+            putchar(buf[i]);
+        } else {
+            putc(buf[i],ofp);
+        }
+    }
+#endif /* COMMENT */
+
+#ifdef IKSD
+    if (inserver) {
+#ifdef UNICODE
+        if (outcs == FC_UCS2) {
+            if (ofp == stdout) {
+                putchar(NUL);
+            } else {
+                putc(NUL,ofp);
+            }
+        }
+#endif /* UNICODE */
+        if (ofp == stdout) {
+            putchar('\r');
+        } else {
+            putc('\r',ofp);
+        }
+    }
+#endif /* IKSD */
+#ifdef UNICODE
+    if (outcs == FC_UCS2) {
+        if (ofp == stdout) {
+            putchar(NUL);
+        } else {
+            putc(NUL,ofp);
+        }
+    }
+#endif /* UNICODE */
+    if (ofp == stdout) {
+        putchar('\n');
+    } else {
+        putc('\n',ofp);
+    }
+    fflush(stdout);
+    return(0);
+}
+
+static int                              /* Get translated line */
+typegetline(incs, outcs, buf, n) int incs, outcs, n; char * buf; {
+    int x = 0, c0, c1, len = 0, count = 0, eof = 0, xlate = 0;
+#ifdef UNICODE
+    int xxn = -1;
+    int yyn = -9;
+    xn = 0L;
+
+#ifdef DEBUG
+    if (deblog && typ_lines == 0) {
+        debug(F101,"typegetline incs","",incs);
+        debug(F101,"typegetline outcs","",outcs);
+        debug(F101,"typegetline feol","",feol);
+        debug(F101,"typegetline byteorder","",byteorder);
+        debug(F101,"typegetline ucsorder ","",ucsorder);
+        debug(F111,"typegetline fileorder","1",fileorder);
+    }
+#endif /* DEBUG */
+
+    if (incs < 0)                       /* Shouldn't happen */
+      return(-2);
+
+    if (outcs == -1)                    /* Can happen */
+      outcs = incs;
+
+    if (incs != outcs || incs == FC_UCS2) { /* See if we should translate */
+        xlate = 1;
+        if (!mbuf) {                    /* Allocate buffer if not allocated */
+            mbuf = (char *)malloc(TYPXBUFL+1); /* yet */
+            if (!mbuf) {
+                printf("WARNING: Translation buffer allocation failure.\n");
+                printf("Translation will be skipped...\n");
+                xlate = 0;
+            }
+        }
+    }
+    if (xlate) {                        /* Translating... */
+        mp = mbuf;                      /* Reset working buffer pointer */
+/*
+  Here we call xgnbyte() in a loop, having it return UCS-2 bytes.  In K95, we
+  use UCS-2 directly.  Elsewhere, we feed the UCS-2 bytes into xpnbyte() to
+  convert them to the desired target character set.  But since we are using
+  UCS-2, we have several sources for confusion: (1) xgnbyte() might return in
+  LE or BE byte order, with no explicit indication of what the order is; but
+  (2) xpnbyte() wants BE; but (3) Windows wants LE.
+*/
+        while (1) {
+            if (typ_int)                /* Quit if interrupted */
+              return(0);
+            c0 = xgnbyte(FC_UCS2,incs,NULL); /* Convert to UCS-2 */
+            debug(F000,"typegetline c0","",c0);
+            if (c0 < 0) {               /* EOF */
+                eof++;
+                break;
+            }
+            c1 = xgnbyte(FC_UCS2,incs,NULL); /* Convert to UCS-2 */
+            debug(F000,"typegetline c1","",c1);
+            if (c1 < 0) {               /* EOF */
+                eof++;
+                break;
+            }
+#ifdef DEBUG
+            if (deblog && typ_lines == 0) {
+                if (count == 0) /* Check fileorder after BOM */
+                  debug(F111,"typegetline fileorder","2",fileorder);
+            }
+#endif /* DEBUG */
+
+#ifdef COMMENT
+/* Now we have the two UCS-2 bytes.  Which order are they in? */
+
+            if (fileorder > 0) {        /* Little Endian */
+                int t;                  /* So swap them */
+                debug(F100,"typegetline swapping","",0);
+                t = c1;
+                c1 = c0;
+                c0 = t;
+            }
+#endif /* COMMENT */
+            if (c0 == 0 && c1 == 0x0D)  /* Now see if we have EOL */
+              yyn = xn;
+
+            if (c0 == 0 && c1 == 0x0A)  /* Now see if we have EOL */
+              xxn = xn;
+
+            count++;                    /* Count byte */
+
+/* Give the two bytes to xpnbyte() in BE order */
+
+            if ((x = xpnbyte(c0,TC_UCS2,outcs,storechar)) < 0) return(-1);
+            if ((x = xpnbyte(c1,TC_UCS2,outcs,storechar)) < 0) return(-1);
+
+            if (xxn > -1) {             /* Have end of line? */
+                xn = xxn;
+                if (yyn == xxn - 2)     /* Adjust for CRLF */
+                  xn = yyn;
+                break;                  /* And break out of loop. */
+            }
+        }
+        mbuf[xn] = NUL;
+        if (xn > n)                     /* Can truncate here... */
+          xn = n;
+        memcpy(buf,mbuf,xn);
+        debug(F011,"typegetline xlate",buf,xn);
+        return((eof && (xn == 0)) ? -1 : xn);
+    }
+#endif /* UNICODE */
+#ifdef COMMENT
+    /* We can't use this because, stupidly, zsinl() doesn't return a length. */
+    /* It could be changed but then we'd have to change all ck?fio.c modules */
+    x = zsinl(ZIFILE,buf,n);
+#else
+    /* So instead, we copy zsinl() to here... */
+    /* But note: This does not necessarily handle UCS-2 alignment properly;  */
+    /* that's what the code in the first section of this routine is for. */
+    /* But it does tolerate files that contain NULs. */
+    {
+        int a;
+        char *s;
+
+        s = buf;
+        a = -1;                         /* Current character, none yet. */
+        debug(F101,"typegetline zsinl simulation","",n);
+        while (n--) {                   /* Up to given length */
+#ifdef COMMENT
+            int old = 0;
+            if (feol)                   /* Previous character */
+              old = a;
+#endif /* COMMENT */
+            if (zchin(ZIFILE,&a) < 0) { /* Read a character from the file */
+                debug(F101,"typegetline zchin fail","",count);
+                if (count == 0)
+                  x = -1;               /* EOF or other error */
+                break;
+            } else
+              count++;
+            if (feol) {                 /* Single-character line terminator */
+                if (a == feol)
+                  break;
+            } else {                    /* CRLF line terminator */
+#ifdef COMMENT
+/* Debug log shows that in Windows, <CR><LF> is returned as <LF>. */
+/* Apparently we're not reading the file in binary mode. */
+
+                if (a == '\015')        /* CR, get next character */
+                  continue;
+                if (old == '\015') {    /* Previous character was CR */
+                    if (a == '\012') {  /* This one is LF, so we have a line */
+                        break;
+                    } else {            /* Not LF, deposit CR */
+                        *s++ = '\015';
+                        n--;
+                        len++;
+                    }
+                }
+#else
+                if (a == LF) {
+                    if (s[len] == CR) { /* This probably won't happen */
+                        s[len] = NUL;
+                        s--;
+                        len--;
+                    }
+                    break;
+                }
+#endif /* COMMENT */
+            }
+            *s = a;                     /* Deposit character */
+            s++;
+            len++;
+        }
+        *s = '\0';                      /* Terminate the string */
+    }
+#endif /* COMMENT */
+    return(x < 0 ? -1 : len);
+}
+
+
+#ifndef MAC
+SIGTYP
+#ifdef CK_ANSIC
+tytrap(int foo)                         /* TYPE interrupt trap */
+#else
+tytrap(foo) int foo;
+#endif /* CK_ANSIC */
+/* tytrap */ {
+#ifdef __EMX__
+    signal(SIGINT, SIG_ACK);
+#endif
+    debug(F100,"type tytrap SIGINT","",0);
+    typ_int = 1;                        /* (Need arg for ANSI C) */
+    SIGRETURN;
+}
+#endif /* MAC */
+
+int
+dotype(file, paging, first, head, pat, width, prefix, incs, outcs, outfile, z)
+    char * file, * pat, * prefix; int paging, first, head, width, incs, outcs;
+    char * outfile; int z;
+/* dotype */ {
+    extern long ffc;
+    char buf[TYPBUFL+2];
+    char * s = NULL;
+    int rc = 1, lines = 0, ucs2 = 0;
+    char ** tail = NULL;
+    int * tlen = NULL;
+    int tailing = 0, counting = 0;
+    int x, c, n, i, j, k = 0;
+    int number = 0, save, len, pfxlen = 0, evalpfx = 1;
+#ifdef UNICODE
+    int ucsbom_sav;
+    extern int ucsbom;
+#endif /* UNICODE */
+#ifdef NT
+    int gui = 0;
+#endif /* NT */
+
+#ifndef MAC
+#ifdef OS2
+#ifdef NT
+    SIGTYP (* oldsig)(int);             /* For saving old interrupt trap. */
+#else /* NT */
+    SIGTYP (* volatile oldsig)(int);
+#endif /* NT */
+#else /* OS2 */
+    SIGTYP (* oldsig)();
+#endif /* OS2 */
+#endif /* MAC */
+
+#ifdef KUI
+    if (outfile == (char *)1) {
+        gui = 1;
+        outfile = "";
+    }
+#endif /* KUI */
+
+    if (!file) file = "";
+    if (!*file) return(-2);
+
+    if (ofp != stdout) {                /* In case of previous interruption */
+        if (ofp) fclose(ofp);
+        ofp = stdout;
+    }
+    if (!outfile) outfile = "";
+    if (outfile[0]) {
+        ofp = fopen(outfile,"w");       /* Open output file */
+        if (!ofp) {
+            printf("?Can't open output file %s: %s\n",outfile,ck_errstr());
+            ofp = stdout;
+            return(-9);
+        }
+    }
+    number = z;
+    if (number && prefix) prefix = NULL;
+
+#ifdef UNICODE
+    ucsbom_sav = ucsbom;                /* We are not creating a file */
+    ucsbom = 0;                         /* Do not use BOM bytes */
+#endif /* UNICODE */
+
+    typ_int = 0;
+
+    save = binary;                      /* Save file type */
+
+    debug(F101,"dotype incs","",incs);
+    debug(F101,"dotype outcs","",outcs);
+
+#ifdef UNICODE
+    debug(F111,"dotype fileorder","A",fileorder);
+#ifdef OS2
+    if (!inserver && !k95stdout)
+      outcs = FC_UCS2;
+#endif /* OS2 */
+
+    if (outcs == FC_UCS2)               /* Output is UCS-2? */
+      ucs2 = 1;
+    if (fileorder < 0)
+      fileorder = ucsorder;
+    debug(F111,"dotype fileorder","B",fileorder);
+#endif /* UNICODE */
+
+#ifdef CK_TTGWSIZ
+#ifdef OS2
+    ttgcwsz();
+#else /* OS2 */
+    /* Check whether window size changed */
+    if (ttgwsiz() > 0) {
+        if (tt_rows > 0 && tt_cols > 0) {
+            cmd_rows = tt_rows;
+            cmd_cols = tt_cols;
+            debug(F101,"dotype cmd_rows","",cmd_rows);
+            debug(F101,"dotype cmd_cols","",cmd_cols);
+        }
+    }
+#endif /* OS2 */
+#endif /* CK_TTGWSIZ */
+
+    if (prefix)
+      pfxlen = strlen(prefix);
+
+    if (paging < 0) {                   /* Count only, don't print */
+        counting = 1;
+        prefix = NULL;
+        width = 0;
+        paging = 0;
+    }
+    if (ucs2)                           /* Crude... */
+      width *= 2;
+
+#ifdef OS2
+    if (*file) {
+        ckstrncpy(buf, file, TYPBUFL);  /* Change / to \. */
+        p = buf;
+        while (*p) {
+            if (*p == '/') *p = '\\';
+            p++;
+        }
+        file = buf;
+    } else {
+        rc = 0;
+        goto xdotype;
+    }
+#endif /* OS2 */
+
+    if (zchki(file) == -2) {            /* It's a directory */
+        debug(F111,"dotype zchki failure",file,-2);
+        if (xcmdsrc == 0) {
+            printf("?Not a regular file: \"%s\"\n",file);
+            rc = -9;
+        } else
+          rc = 0;
+        goto xdotype;
+    }
+    if (!zopeni(ZIFILE, file)) {        /* Not a directory, open it */
+        debug(F111,"dotype zopeni failure",file,0);
+        if (xcmdsrc == 0) {
+            printf("?Can't open file: \"%s\"\n",file);
+            rc = -9;
+        } else
+          rc = 0;
+        goto xdotype;
+    }
+
+#ifndef AMIGA
+#ifndef MAC
+    errno = 0;
+    oldsig = signal(SIGINT, tytrap);    /* Save current interrupt trap. */
+    debug(F111,"type SIGINT trap set",ckitoa(errno),oldsig);
+#endif /* MAC */
+#endif /* AMIGA */
+
+    if (paging > -1)                    /* More-prompting */
+      xaskmore = paging;
+
+    binary = 0;
+
+    if (head < 0) {                     /* "tail" was requested */
+        tailing = 1;                    /* Set flag */
+        head = 0 - head;                /* Get absolute number of lines */
+        if (!counting) {
+            tail = (char **) malloc(head * sizeof(char *)); /* Allocate list */
+            if (!tail) {
+                printf("?Memory allocation failure\n");
+                goto xdotype;
+
+            }
+            tlen = (int *) malloc(head * sizeof(int));
+            if (!tlen) {
+                printf("?Memory allocation failure\n");
+                goto xdotype;
+
+            }
+            for (i = 0; i < head; i++) { /* Initialize each pointer in list. */
+                tail[i] = NULL;
+                tlen[i] = 0;
+            }
+        }
+    }
+    typ_lines = 0;
+    typ_mtchs = 0;
+
+#ifdef UNICODE
+    if (outcs > -1 && (incs != outcs || incs == FC_UCS2)) { /* Translating? */
+        ffc = 0L;
+        initxlate(incs,outcs);          /* Set up translation functions */
+    } else
+#endif /* UNICODE */
+      outcs = -1;                       /* Means we don't know the charset */
+
+    debug(F101,"dotype ffc","",ffc);
+    debug(F101,"dotype outcs 2","",outcs);
+#ifdef UNICODE
+    debug(F111,"dotype fileorder","C",fileorder);
+#endif /* UNICODE */
+
+    /* Allow the buffer to contain NULs */
+
+    for (n = first;
+         (len = typegetline(incs,outcs,buf,TYPBUFL)) > -1;
+         lines++
+         ) {
+        debug(F011,"dotype line",buf,len);
+#ifndef MAC
+        if (typ_int) {                  /* Interrupted? */
+            typ_int = 0;
+            debug(F101,"type interrupted line","",lines);
+            printf("^C...\n");          /* Print message */
+            if (ofp != stdout) {        /* Close any output file */
+                if (ofp) fclose(ofp);
+                ofp = stdout;
+            }
+            goto xxdotype;
+        }
+#endif /* MAC */
+        typ_lines++;                    /* For \v(ty_ln) */
+        if (pat)                        /* Matching? */
+          if (!ckmatch(pat,buf,1,1+4))  /* Line matches pattern? */
+            continue;                   /* No, skip it */
+        typ_mtchs++;
+
+        if (head > 0 && !tailing && lines == head) /* Handle /HEAD:n */
+          break;
+
+        buf[TYPBUFL+1] = NUL;           /* Just in case... */
+        if (prefix) {                   /* Add specified prefix to each line */
+            char pbuf[64];
+            char * pp;
+            pp = prefix;
+#ifndef NOSPL
+            if (evalpfx) {              /* Prefix is a variable? */
+                int n = 63;             /* Maybe - evaluate it and see */
+                char * p = pbuf;
+                zzstring(prefix,&p,&n); /* If there is no change */
+                if (!strcmp(prefix,pbuf)) { /* it's not a variable */
+                    evalpfx = 0;        /* So don't do this again. */
+                } else {                /* It was a variable */
+                    pp = pbuf;          /* So substitute its value */
+                    pfxlen = 63 - n;    /* and get its new length */
+                }
+            }
+#endif /* NOSPL */
+            if (len + pfxlen + 2 < TYPBUFL) {
+                /* Shift right to make room for prefix */
+                memcpy((char *)line+pfxlen,(char *)buf,len);
+                lset((char *)line,pp,pfxlen,SP);
+                debug(F110,"dotype prefix",line,pfxlen);
+                len += pfxlen;
+                memcpy((char *)buf,(char *)line,len);
+            }
+        } else if (number) {            /* Line numbers */
+            int x;
+            sprintf(line,"%4d. ",typ_lines);
+            x = strlen(line);
+            len += x;
+            if (len < LINBUFSIZ) {
+                memcpy((char *)&line[x],(char *)buf,len);
+                memcpy((char *)buf,(char *)line,len);
+            }
+        }
+        if (width > 0 && width <= TYPBUFL) { /* Truncate at given width. */
+            char * obuf = line;         /* But to do that first we must */
+            int i,k,z;                  /* expand tabs; assume every 8 cols. */
+            line[0] = NUL;
+            for (i = 0, k = 0; i < width; k++) { /* Character loop... */
+                if (!buf[k])            /* No more chars in this line, done. */
+                  break;
+                if (buf[k] != '\t') {   /* If it's not a tab */
+                    if (i >= LINBUFSIZ) /* Check for overflow */
+                      break;
+                    obuf[i++] = buf[k]; /* and then deposit it. */
+                    obuf[i] = NUL;      /* Keep it null-terminated */
+                    continue;
+                }
+                z = 8 - (i % 8);        /* It's a tab, expand it. */
+                if (z == 0) z = 8;
+                for (j = 0; j < z && i < LINBUFSIZ; j++) {
+#ifdef UNICODE
+                    if (ucs2 && !ucsorder)
+                      obuf[i++] = NUL;
+#endif /* UNICODE */
+                    obuf[i++] = ' ';
+#ifdef UNICODE
+                    if (ucs2 && ucsorder)
+                      obuf[i++] = NUL;
+#endif /* UNICODE */
+                }
+                obuf[i++] = NUL;
+                obuf[i] = NUL;
+            }
+            obuf[width] = NUL;          /* Now truncate at given width. */
+#ifdef COMMENT
+            /* This doesn't work for UCS-2 because it contains NULs */
+            ckstrncpy(buf,obuf,TYPBUFL); /* and copy it back (again?) */
+#else
+            memcpy((char *)buf,(char *)obuf,i); /* Copy it back */
+#endif /* COMMENT */
+            len = (i > width) ? width : i; /* Spare us another strlen()... */
+        }
+        if (tailing) {                  /* If /TAIL:n... */
+            k = lines % head;           /* save this line in circular buffer */
+            if (!counting) {
+                if (tail[k]) free(tail[k]);
+                tail[k] = malloc(len+2);
+                if (!tail[k]) {
+                    printf("?Memory allocation failure\n");
+                    goto xdotype;
+                }
+                memcpy(tail[k],buf,len);
+                tlen[k] = len;
+                continue;
+            }
+        }
+        if (counting)                   /* If only counting */
+          continue;                     /* we're done with this line */
+
+        if (paging) {                   /* Displaying this line... */
+            int u;
+            u = len;                    /* Length in BYTES */
+            if (ucs2)                   /* If outputting in UCS-2 */
+              u /= 2;                   /* convert length to CHARACTERS */
+            x = (u / cmd_cols) + 1;     /* Crudely allow for wrap */
+            if (cmd_rows > 0 && cmd_cols > 0)
+              n += x;                   /* This assumes terminal will wrap */
+        }
+#ifdef KUI
+        if ( gui ) {
+            int i;
+            unsigned short * uch = (unsigned short *)buf;
+            for ( i=0; i<len/2; i++)
+                gui_text_popup_append(uch[i]);
+                       gui_text_popup_append(CR);
+                       gui_text_popup_append(LF);
+        } 
+        else
+#endif /* KUI */
+        typeline(buf,len,outcs,ofp);    /* Print line, length based */
+#ifdef CK_TTGWSIZ
+        debug(F101,"dotype n","",n);
+        if (paging > 0 && ofp == stdout) { /* Pause at end of screen */
+            if (cmd_rows > 0 && cmd_cols > 0) {
+                if (n > cmd_rows - 3) {
+                    if (!askmore())
+                      goto xdotype;
+                    else
+                      n = 0;
+                }
+            }
+        }
+#endif /* CK_TTGWSIZ */
+    }
+
+  xdotype:
+    if (counting) {
+        fprintf(ofp,
+                "%s: %d line%s\n",file,typ_lines,typ_lines == 1 ? "" : "s");
+        if (pat)
+          fprintf(ofp,
+                  "%s: %d match%s\n",pat,typ_mtchs,typ_mtchs == 1 ? "" : "es");
+        goto xxdotype;
+    }
+    if (tailing && tail) {              /* Typing tail of file? */
+        if (lines < head) {             /* Yes, show the lines we saved */
+            k = 0;                      /* Show all lines */
+        } else {                        /* More lines than tail number */
+            lines = k;                  /* Last line to show */
+            k++;                        /* First line to show */
+            if (k >= head)
+              k = 0;
+        }
+        n = first;                      /* Output line counter */
+        for (i = k ;; i++) {            /* Loop thru circular buffer */
+#ifndef MAC
+            if (typ_int) {              /* Interrupted? */
+                printf("^C...\n");      /* Print message */
+                goto xxdotype;
+            }
+#endif /* MAC */
+            j = i % head;               /* Index of this line */
+            s = tail[j];                /* Point to line to display */
+            if (!s)                     /* (shouldn't happen...) */
+              break;
+            if (paging) {               /* Crudely allow for line wrap */
+                x = tlen[j];
+                if (ucs2) x /= 2;
+                x = x / cmd_cols + 1;
+                if (cmd_rows > 0 && cmd_cols > 0)
+                  n += x;
+            }
+            typeline(s,tlen[j],outcs,ofp); /* Display this line */
+            if (paging && ofp == stdout) { /* Pause at end of screen */
+                if (cmd_rows > 0 && cmd_cols > 0) {
+                    if (n > cmd_rows - 3) {
+                        if (!askmore())
+                          break;
+                        else
+                          n = 0;
+                    }
+                }
+            }
+            tail[j] = NULL;
+            free(s);                    /* Free the line */
+            if (i % head == lines)      /* When to stop */
+              break;
+        }
+        free((char *)tail);             /* Free the list */
+        tail = NULL;
+        if (tlen) free((char *)tlen);
+        tlen = NULL;
+    }
+
+/* Come here when finished or on SIGINT */
+
+  xxdotype:
+#ifndef AMIGA
+#ifndef MAC
+    signal(SIGINT,oldsig);              /* Put old signal action back. */
+#endif /* MAC */
+#endif /* AMIGA */
+    if (tailing && tail) {
+        for (i = 0; i < head; i++) {    /* Free each line. */
+            if (tail[i])
+              free(tail[i]);
+        }
+        free((char *)tail);             /* Free list pointer */
+        if (tlen)
+          free((char *)tlen);
+    }
+    x = zclose(ZIFILE);                 /* Done, close the input file */
+    if (ofp != stdout) {                /* Close any output file */
+        if (ofp) fclose(ofp);
+        ofp = stdout;
+    }
+    binary = save;                      /* Restore text/binary mode */
+#ifdef UNICODE
+    ucsbom = ucsbom_sav;                /* Restore BOM usage */
+#endif /* UNICODE */
+
+#ifdef KUI
+    if ( gui )
+        gui_text_popup_wait(-1);        /* Wait for user to close the dialog */
+#endif /* KUI */
+    return(rc);
+}
+
+/* GREP command */
+
+#define GREP_CASE  0                    /* /CASE */
+#define GREP_COUN  1                    /* /COUNT */
+#define GREP_DOTF  2                    /* /DOTFILES */
+#define GREP_NAME  3                    /* /NAMEONLY */
+#define GREP_NOBK  4                    /* /NOBACKUP */
+#define GREP_NODO  5                    /* /NODOTFILES */
+#define GREP_NOLI  6                    /* /NOLIST */
+#define GREP_NOMA  7                    /* /INVERT = /NOMATCH */
+#define GREP_NOPA  8                    /* /NOPAGE */
+#define GREP_NUMS  9                    /* /LINENUMBERS */
+#define GREP_PAGE 10                    /* /PAGE */
+#define GREP_RECU 11                    /* /RECURSIVE */
+#define GREP_TYPE 12                    /* /TYPE: */
+#define GREP_OUTP 13                    /* /OUTPUTFILE: */
+
+static struct keytab greptab[] = {
+    { "/count",        GREP_COUN, CM_ARG },
+    { "/dotfiles",     GREP_DOTF, 0 },
+    { "/linenumbers",  GREP_NUMS, 0 },
+    { "/nameonly",     GREP_NAME, 0 },
+    { "/nobackupfiles",GREP_NOBK, 0 },
+    { "/nocase",       GREP_CASE, 0 },
+    { "/nodotfiles",   GREP_NODO, 0 },
+    { "/nolist",       GREP_NOLI, 0 },
+    { "/nomatch",      GREP_NOMA, 0 },
+    { "/nopage",       GREP_NOPA, 0 },
+    { "/output",       GREP_OUTP, CM_ARG },
+    { "/page",         GREP_PAGE, 0 },
+    { "/quiet",        GREP_NOLI, CM_INV },
+#ifdef RECURSIVE
+    { "/recursive",    GREP_RECU, 0 },
+#endif /* RECURSIVE */
+    { "/type",         GREP_TYPE, CM_ARG },
+    { "", 0, 0 }
+};
+static int ngreptab =  sizeof(greptab)/sizeof(struct keytab)-1;
+
+int
+dogrep() {
+    int match, x, y, fc, getval, mc = 0, count = 0, bigcount = 0;
+    int fline = 0, sline = 0, wild = 0, len = 0;
+    int xmode = -1, scan = 0;
+    char c, name[CKMAXPATH+1], outfile[CKMAXPATH+1], *p, *s, *cv = NULL;
+    FILE * fp = NULL;
+
+    int                                 /* Switch values and defaults */
+      gr_coun = 0,
+      gr_name = 0,
+      gr_nobk = 0,
+      gr_case = 1,
+      gr_noli = 0,
+      gr_noma = 0,
+      gr_nums = 0,
+      gr_page = xaskmore;
+
+    struct FDB sw, fl;
+
+    g_matchdot = matchdot;              /* Save global matchdot setting */
+    outfile[0] = NUL;
+
+    if (ofp != stdout) {                /* In case of previous interruption */
+        if (ofp) fclose(ofp);
+        ofp = stdout;
+    }
+    cmfdbi(&sw,                         /* First FDB - command switches */
+           _CMKEY,                      /* fcode */
+           "String or pattern to search for, or switch",
+           "",                          /* default */
+           "",                          /* addtl string data */
+           ngreptab,                    /* addtl numeric data 1: tbl size */
+           4,                           /* addtl numeric data 2: 4 = cmswi */
+           xxstring,                    /* Processing function */
+           greptab,                     /* Keyword table */
+           &fl                          /* Pointer to next FDB */
+           );
+    cmfdbi(&fl,                         /* Anything that doesn't match */
+           _CMFLD,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,                   /* xxstring */
+           NULL,
+           NULL
+           );
+    while (1) {                         /* Parse 0 or more switches */
+        x = cmfdb(&sw);                 /* Parse something */
+        if (x < 0)
+          return(x);
+        if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
+          break;
+        c = cmgbrk();
+        if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+            printf("?This switch does not take an argument\n");
+            return(-9);
+        }
+        if ((cmresult.nresult != GREP_COUN) && !getval &&
+            (cmgkwflgs() & CM_ARG)) {
+            printf("?This switch requires an argument\n");
+            return(-9);
+        }
+        switch (cmresult.nresult) {
+          case GREP_COUN: {
+              gr_coun++;
+              if (getval) {
+                  if ((x = cmfld("Variable for result","",&s,NULL)) < 0)
+                    return(x);
+                  makestr(&cv,s);
+              }
+              break;
+          }
+          case GREP_CASE: gr_case=0; break;
+          case GREP_NAME: gr_name++; gr_noli=0; break;
+          case GREP_NOBK: gr_nobk++; break;
+          case GREP_NOLI: gr_noli++; gr_name=0; gr_nums=0; break;
+          case GREP_NOMA: gr_noma++; break;
+          case GREP_NOPA: gr_page=0; break;
+          case GREP_NUMS: gr_nums++; gr_noli=0; break;
+          case GREP_PAGE: gr_page++; gr_noli=0; break;
+          case GREP_NODO:
+            matchdot = 0;
+            break;
+          case GREP_DOTF:
+            matchdot = 1;
+            break;
+#ifdef RECURSIVE
+          case GREP_RECU:
+            recursive = 1;
+            break;
+#endif /* RECURSIVE */
+          case GREP_TYPE: {
+              extern struct keytab txtbin[];
+              if ((x = cmkey(txtbin,3,"","",xxstring)) < 0)
+                return(x);
+              if (x == 2) {             /* ALL */
+                  xmode = -1;
+              } else {                  /* TEXT or BINARY only */
+                  xmode = x;
+                  scan = 1;
+              }
+              break;
+          }
+          case GREP_OUTP:               /* Send output to file */
+            if ((x = cmofi("File for GREP'd lines","",&s,xxstring)) < 0)
+              return(x);
+            ckstrncpy(outfile,s,CKMAXPATH);
+            break;
+        }
+    }
+    if (outfile[0]) {
+        ofp = fopen(outfile,"w");       /* Open output file */
+        if (!ofp) {
+            printf("?Can't open output file %s: %s\n",outfile,ck_errstr());
+            ofp = stdout;
+            return(-9);
+        }
+        gr_page = 0;
+    }
+    s = cmresult.sresult;
+    s = brstrip(s);                     /* Strip braces from pattern */
+    if (!*s) {
+        printf("?Pattern required\n");
+        return(-9);
+    }
+    ckstrncpy(tmpbuf,s,TMPBUFSIZ);      /* Save pattern */
+    if ((x = cmifi("File(s) to search","",&s,&wild,xxstring)) < 0) {
+        if (x == -3) {
+            printf("?File specification required\n");
+            x = -9;
+        }
+        return(x);
+    }
+    s = brstrip(s);                     /* Strip braces from filename */
+#ifndef ZXREWIND
+    ckstrncpy(line,s,LINBUFSIZ);
+#endif /* ZXREWIND */
+    if ((y = cmcfm()) < 0)
+      return(y);
+
+    if (gr_page > -1)
+      xaskmore = gr_page;               /* Paging... */
+
+    p = tmpbuf;                         /* Point to pattern */
+#ifdef COMMENT
+/* Now this is done in ckmatch */
+    if (*p == '^') {                    /* '^' anchors pattern to beginning */
+        p++;
+    } else if (*p != '*') {             /* Otherwise prepend implied '*' */
+        tmpbuf[0] = '*';
+        p = tmpbuf;
+    }
+    x = strlen(p);                      /* Get length of result */
+    if (x > 0 && x < TMPBUFSIZ) {       /* '$' at end anchors pattern to end */
+        if (p[x-1] == '$') {
+            p[x-1] = NUL;
+        } else if (p[x-1] != '*') {
+            p[x] = '*';
+            p[x+1] = NUL;
+        }
+    }
+#endif /* COMMENT */
+    debug(F111,"grep pat",p,x);
+
+#ifdef ZXREWIND
+    fc = zxrewind();                    /* Rewind the file list */
+#else
+    {
+        int flags = ZX_FILONLY;         /* Expand file list */
+        if (matchdot)  flags |= ZX_MATCHDOT;
+        if (recursive) flags |= ZX_RECURSE;
+        fc = nzxpand(line,flags);
+    }
+#endif /* ZXREWIND */
+#ifdef UNIX
+    sh_sort(mtchs,NULL,fc,0,0,filecase);
+#endif /* UNIX */
+
+    debug(F101,"grep cmd_rows","",cmd_rows);
+    debug(F101,"grep cmd_cols","",cmd_cols);
+
+    while (1) {                         /* Loop for each file */
+        znext(name);                    /* Get next file */
+        if (!name[0])                   /* No more, done */
+          break;
+        if (gr_nobk)                    /* Skipping backup files? */
+          if (ckmatch("*.~[1-9]*~",name,1,1)) /* Backup file? */
+            continue;                   /* Yes, skip */
+        if (scan) {                     /* /TYPE: given? */
+            switch (scanfile(name,&y,nscanfile)) { /* Yes, scan the file */
+              case FT_BIN:
+                if (xmode != 1)
+                  continue;
+                break;
+              case FT_TEXT:
+              case FT_7BIT:
+              case FT_8BIT:
+#ifdef UNICODE
+              case FT_UTF8:
+              case FT_UCS2:
+#endif /* UNICODE */
+                if (xmode != 0)
+                  continue;
+            }
+        }
+        fp = fopen(name,"r");           /* Open */
+        if (!fp)                        /* Can't */
+          continue;                     /* Skip */
+        count = 0;                      /* Match count, this file */
+        fline = 0;                      /* Line count, this file */
+        while (1) {                     /* Loop for each line */
+            if (fgets(line,LINBUFSIZ,fp) == NULL) { /* Get next line */
+                fclose(fp);
+                fp = NULL;
+               debug(F100,"GREP EOF","",0);
+                break;
+            }
+            fline++;                    /* Count this line */
+            line[LINBUFSIZ] = NUL;      /* Make sure it's terminated */
+           debug(F111,"GREP",line,fline);
+            len = (int)strlen(line);    /* Get length */
+            while (len > 0 && (line[len-1] == '\n' || line[len-1] == '\r'))
+              line[--len] = NUL;        /* Chop off terminators */
+            match = ckmatch(p,line,gr_case,1+4); /* Match against pattern */
+            if (gr_noma)                /* Invert match sense if requested */
+              match = !match;
+            if (match) {                /* Have a matching line */
+                mc++;                   /* Total match count */
+                count++;                /* Match count this file */
+                if (gr_name) {          /* Don't care how many lines match */
+                    fclose(fp);         /* Close the file */
+                    fp = NULL;          /* and quit the line-reading loop. */
+                    break;
+                }
+                if (gr_coun || gr_noli) /* Not listing each line */
+                  continue;             /* so don't print anything now. */
+                if (wild) {            /* If searching multiple files */
+                    fprintf(ofp,"%s:",name); /* print filename. */
+                    len += (int)strlen(name) + 1;
+                }
+                if (gr_nums) {          /* If line numbers wanted */
+                    char nbuf[32];
+                    len += ckmakmsg(nbuf,32,ckitoa(fline),":",NULL,NULL);
+                    fprintf(ofp,"%s",nbuf);
+                }
+                if (cmd_rows > 0 && cmd_cols > 0)
+                  sline += (len / cmd_cols) + 1;
+                fprintf(ofp,"%s\n",line); /* Print the line. */
+                if (sline > cmd_rows - 3) {
+                    if (!askmore()) goto xgrep; else sline = 0;
+                }
+            }
+        }
+        if (!gr_noli) {                        /* If not not listing... */
+            x = 0;
+            if (gr_coun) {              /* Show match count only */
+                fprintf(ofp,"%s:%d\n",name,count);
+                x++;
+            } else if (gr_name && count > 0) { /* Show name only */
+                fprintf(ofp,"%s\n",name);
+                x++;
+            }
+            if (x > 0) {
+                if (++sline > cmd_rows - 3) {
+                    if (!askmore()) goto xgrep; else sline = 0;
+                }
+            }
+        }
+        bigcount += count;              /* Overall count */
+    }
+  xgrep:
+#ifndef NOSPL
+    if (gr_coun && cv) {                /* /COUNT:blah */
+        addmac(cv,ckitoa(bigcount));    /* set the variable */
+        makestr(&cv,NULL);              /* free this */
+    }
+#endif /* NOSPL */
+    if (fp) fclose(fp);                 /* close input file if still open */
+    if (ofp != stdout) {                /* Close any output file */
+        if (ofp) fclose(ofp);
+        ofp = stdout;
+    }
+    return(success = mc ? 1 : 0);
+}
+
+/* System-independent directory */
+
+static char ** dirlist = NULL;
+static int ndirlist = 0;
+
+static VOID
+freedirlist() {
+    if (dirlist) {
+        int i;
+        for (i = 0; i < ndirlist; i++) {
+            if (dirlist[i])
+              free(dirlist[i]);
+        }
+        free((char *)dirlist);
+        dirlist = NULL;
+    }
+    ndirlist = 0;
+}
+
+static struct keytab dirswtab[] = {     /* DIRECTORY command switches */
+    { "/after",       DIR_AFT, CM_ARG },
+    { "/all",         DIR_ALL, 0 },
+#ifndef NOSPL
+    { "/array",       DIR_ARR, CM_ARG },
+#endif /* NOSPL */
+    { "/ascending",   DIR_ASC, 0 },
+    { "/backup",      DIR_BUP, 0 },
+    { "/before",      DIR_BEF, CM_ARG },
+    { "/brief",       DIR_BRF, 0 },
+    { "/descending",  DIR_DSC, CM_INV },
+    { "/directories", DIR_DIR, 0 },
+    { "/dotfiles",    DIR_DOT, 0 },
+    { "/englishdate", DIR_DAT, 0 },
+    { "/except",      DIR_EXC, CM_ARG },
+    { "/files",       DIR_FIL, 0 },
+    { "/heading",     DIR_HDG, 0 },
+    { "/isodate",     DIR_ISO, 0 },
+    { "/larger-than", DIR_LAR, CM_ARG },
+#ifdef CKSYMLINK
+    { "/followlinks", DIR_LNK, 0 },
+#endif /* CKSYMLINK */
+    { "/message",     DIR_MSG, CM_ARG },
+    { "/nobackupfiles",DIR_NOB, 0 },
+    { "/nodotfiles",  DIR_NOD, 0 },
+#ifdef CKSYMLINK
+    { "/nofollowlinks",DIR_NLK, 0 },
+#endif /* CKSYMLINK */
+    { "/noheading",   DIR_NOH, 0 },
+    { "/nomessage",   DIR_NOM, 0 },
+#ifdef CK_TTGWSIZ
+    { "/nopage",      DIR_NOP, 0 },
+#endif /* CK_TTGWSIZ */
+#ifdef RECURSIVE
+    { "/norecursive", DIR_NOR, 0 },
+#else
+#ifdef VMS
+    { "/norecursive", DIR_NOR, 0 },
+#else
+#ifdef datageneral
+    { "/norecursive", DIR_NOR, 0 },
+#endif /* datageneral */
+#endif /* VMS */
+#endif /* RECURSIVE */
+    { "/nosort",      DIR_NOS, 0 },
+    { "/not-after",   DIR_NAF, CM_ARG },
+    { "/not-before",  DIR_NBF, CM_ARG },
+    { "/not-since",   DIR_NAF, CM_INV|CM_ARG },
+    { "/noxfermode",  DIR_NOT, 0 },
+    { "/output",      DIR_OUT, CM_ARG },
+#ifdef CK_TTGWSIZ
+    { "/page",        DIR_PAG, 0 },
+#endif /* CK_TTGWSIZ */
+#ifdef RECURSIVE
+    { "/recursive",   DIR_REC, 0 },
+#else
+#ifdef VMS
+    { "/recursive",   DIR_REC, 0 },
+#else
+#ifdef datageneral
+    { "/recursive",   DIR_REC, 0 },
+#endif /* datageneral */
+#endif /* VMS */
+#endif /* RECURSIVE */
+    { "/reverse",     DIR_DSC, 0 },
+    { "/since",       DIR_AFT, CM_ARG|CM_INV },
+    { "/smaller-than",DIR_SMA, CM_ARG },
+    { "/sort",        DIR_SRT, CM_ARG },
+    { "/summary",     DIR_SUM, 0 },
+    { "/type",        DIR_BIN, CM_ARG },
+    { "/xfermode",    DIR_TYP, 0 },
+    { "/verbose",     DIR_VRB, 0 },
+    { "",0,0 }
+};
+static int ndirswtab = (sizeof(dirswtab) / sizeof(struct keytab)) - 1;
+
+static struct keytab dirsort[] = {      /* DIRECTORY /SORT: options */
+    { "date",         DIRS_DT, 0 },
+    { "name",         DIRS_NM, 0 },
+    { "size",         DIRS_SZ, 0 }
+};
+static int ndirsort = (sizeof(dirsort) / sizeof(struct keytab));
+
+static int dir_date = -1;               /* Option defaults (-1 means none) */
+static int dir_page = -1;
+static int dir_verb =  1;
+static int dir_msg  = -1;
+#ifdef VMS
+static int dir_sort = -1;               /* Names are already sorted in VMS */
+static int dir_rvrs = -1;
+#else
+static int dir_sort =  1;               /* Sort by default */
+static int dir_rvrs =  0;               /* Not in reverse */
+#endif /* VMS */
+static int dir_skey = DIRS_NM;          /* By name */
+#ifdef RECURSIVE
+static int dir_recu = -1;
+#endif /* RECURSIVE */
+static int dir_mode = -1;
+static int dir_show = -1;               /* Show all files by default */
+int dir_dots =  -1;                    /* Except dot files */
+int dir_back =  1;
+int dir_head =  0;
+static char * dirmsg = NULL;
+static int dirmsglen = 0;
+
+#ifndef NOSHOW
+VOID
+showdiropts() {
+    int x = 0;
+    extern int optlines;
+    prtopt(&optlines,"DIRECTORY");
+    if (dir_show > 0) {
+        prtopt(&optlines,(dir_show == 1) ? "/FILES" :
+               ((dir_show == 2) ? "/DIRECTORIES" : "/ALL"));
+        x++;
+    } else {
+        prtopt(&optlines,"/ALL");
+        x++;
+    }
+    if (dir_verb > -1) {
+        prtopt(&optlines,dir_verb ? "/VERBOSE" : "/BRIEF");
+        x++;
+    }
+    if (dir_page > -1) {
+        prtopt(&optlines,dir_page ? "/PAGE" : "/NOPAGE");
+        x++;
+    }
+    if (dir_date > -1) {
+        prtopt(&optlines,dir_date ? "/ENGLISHDATE" : "/ISODATE");
+        x++;
+    }
+    if (dir_dots > -1) {
+        prtopt(&optlines,dir_dots ? "/DOTFILES" : "/NODOTFILES");
+        x++;
+    }
+    if (dir_back > -1) {
+        prtopt(&optlines,dir_back ? "/BACKUP" : "/NOBACKUP");
+        x++;
+    }
+    if (dir_head > -1) {
+        prtopt(&optlines,dir_head ? "/HEADING" : "/NOHEADING");
+        x++;
+    }
+#ifdef RECURSIVE
+    if (dir_recu > -1) {
+        prtopt(&optlines,dir_recu ? "/RECURSIVE" : "/NORECURSIVE");
+        x++;
+    }
+#endif /* RECURSIVE */
+    if (dir_mode > -1) {
+        prtopt(&optlines,dir_mode ? "/XFERMODE" : "/NOXFERMODE");
+        x++;
+    }
+    if (dir_sort == 0) {
+        x++;
+        prtopt(&optlines,"/NOSORT ");
+    } else if (dir_sort > 0) {
+        x++;
+        if (dir_skey == DIRS_NM) s = "/SORT:NAME";
+        else if (dir_skey == DIRS_SZ) s = "/SORT:SIZE";
+        else if (dir_skey == DIRS_DT) s = "/SORT:DATE";
+        prtopt(&optlines,s);
+    }
+    if (dir_rvrs > -1) {
+        prtopt(&optlines,dir_rvrs ? "/REVERSE" : "/ASCENDING");
+        x++;
+    }
+    if (dir_msg > -1) {
+        if (dir_msg == 0) {
+            prtopt(&optlines,"/NOMESSAGE");
+        } else {
+            ckmakmsg(tmpbuf,TMPBUFSIZ,"/MESSAGE:{",dirmsg,"}",NULL);
+            prtopt(&optlines,tmpbuf);
+        }
+        x++;
+    }
+    if (!x) prtopt(&optlines,"(no options set)");
+    prtopt(&optlines,"");
+}
+#endif /* NOSHOW */
+
+int
+setdiropts() {                          /* Set DIRECTORY option defaults */
+    int xb = -1, xv = -1, xp = -1, xd = -1, xh = -1, xf = -1;
+    int xk = -1, xr = -1, xs = -1, xx = -1, xm = -1, xa = -1, xg = -1;
+    int getval;
+    char c;
+    while (1) {
+        if ((y = cmswi(dirswtab,ndirswtab,"Switch","",xxstring)) < 0) {
+            if (y == -3)
+              break;
+            else
+              return(y);
+        }
+        c = cmgbrk();
+        if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+            printf("?This switch does not take an argument\n");
+            return(-9);
+        }
+        if (!getval && (cmgkwflgs() & CM_ARG)) {
+            printf("?This switch requires an argument\n");
+            return(-9);
+        }
+        switch (y) {
+          case DIR_BRF: xv = 0; break;
+          case DIR_VRB: xv = 1; break;
+          case DIR_PAG: xp = 1; break;
+          case DIR_NOP: xp = 0; break;
+          case DIR_ISO: xd = 0; break;
+          case DIR_DAT: xd = 1; break;
+          case DIR_HDG: xh = 1; break;
+          case DIR_NOH: xh = 0; break;
+          case DIR_DOT: xf = 1; break;
+          case DIR_NOD: xf = 0; break;
+          case DIR_ALL: xa = 3; break;
+          case DIR_DIR: xa = 2; break;
+          case DIR_FIL: xa = 1; break;
+          case DIR_SRT:
+            x = DIRS_NM;
+            if (getval)
+              if ((x = cmkey(dirsort,ndirsort,"Sort key","name",xxstring)) < 0)
+                return(x);
+            xk = x;
+            xs = 1;
+            break;
+          case DIR_NOS: xs = 0; break;
+          case DIR_ASC: xx = 0; break;
+          case DIR_DSC: xx = 1; break;
+          case DIR_REC: xr = 1; break;
+          case DIR_NOR: xr = 0; break;
+          case DIR_TYP: xm = 1; break;
+          case DIR_NOT: xm = 0; break;
+          case DIR_BUP: xb = 1; break;
+          case DIR_NOB: xb = 0; break;
+          case DIR_NOM: xg = 0; break;
+          case DIR_MSG:
+            if (getval)
+              if ((x = cmfld("Message to append to each line",
+                             "",
+                             &s,
+                             xxstring
+                             )) < 0)
+                return(x);
+            xg = 1;
+            ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
+            break;
+          default:
+            printf("?This option can not be set\n");
+            return(-9);
+        }
+    }
+    if ((x = cmcfm()) < 0)              /* Get confirmation */
+      return(x);
+    if (xv > -1) dir_verb = xv;         /* Confirmed, save defaults */
+    if (xp > -1) dir_page = xp;
+    if (xd > -1) dir_date = xd;
+    if (xh > -1) dir_head = xh;
+    if (xs > -1) dir_sort = xs;
+    if (xk > -1) dir_skey = xk;
+    if (xx > -1) dir_rvrs = xx;
+    if (xf > -1) dir_dots = xf;
+    if (xa > -1) dir_show = xa;
+    if (xm > -1) dir_mode = xm;
+    if (xb > -1) dir_back = xb;
+#ifdef RECURSIVE
+    if (xr > -1) dir_recu = xr;
+#endif /* RECURSIVE */
+    if (xg > -1) dir_msg  = xg;
+    if (xg > 0)
+      makestr(&dirmsg,tmpbuf);
+    return(success = 1);
+}
+
+int
+domydir() {                             /* Internal DIRECTORY command */
+    extern char *months[];
+#ifdef VMS
+    _PROTOTYP( char * zrelname, (char *,char *) );
+    char * cdp = NULL;
+#endif /* VMS */
+
+    char name[CKMAXPATH+1], outfile[CKMAXPATH+1], *p = NULL, c = NUL;
+    char linebuf[CKMAXPATH+256];
+    char * mstr = NULL, * dstr = NULL, * s2 = NULL;
+    long len = 0, ndirs = 0, nfiles = 0, nbytes = 0, nmatches = 0;
+    int verbose = 0, wild = 0, page = 0, n = 0, engdate = 0, summary = 0;
+    int heading = 0, xsort = 0, reverse = 0, sortby = 0, msg = 0;
+    int k, i = 0, x = 0, nx = 0, skey = 0, dlen = 0, itsadir = 0;
+    int show = 3, xfermod = 0, backup = 1, rc = 0, getval = 0;
+    int fs = 0;
+    int multiple = 0;
+    int cmifn1 = 1, cmifn2 = 0;
+    long minsize = -1L, maxsize = -1L;
+    struct FDB sw, fi, fl;
+    char dbuf[32], xbuf[32];
+
+#ifndef NOSPL
+    char array = NUL;
+    char ** ap = NULL;
+#endif /* NOSPL */
+    char
+      * dir_aft = NULL,
+      * dir_bef = NULL,
+      * dir_naf = NULL,
+      * dir_nbf = NULL,
+      * dir_exc = NULL;
+    char * xlist[16];
+
+    g_matchdot = matchdot;              /* Save global matchdot setting */
+    nolinks = 2;                        /* (it should already be 2) */
+    outfile[0] = NUL;                   /* No output file yet */
+
+    if (ofp != stdout) {                /* In case of previous interruption */
+        if (ofp) fclose(ofp);
+        ofp = stdout;
+    }
+    for (i = 0; i < 16; i++) xlist[i] = NULL;
+
+    name[0] = NUL;
+    freedirlist();                      /* In case not freed last time */
+    page      = dir_page > -1 ? dir_page : xaskmore; /* Set option defaults */
+    engdate   = dir_date > -1 ? dir_date : 0;
+    verbose   = dir_verb > -1 ? dir_verb : 1;
+    heading   = dir_head > -1 ? dir_head : 0;
+    xsort     = dir_sort > -1 ? dir_sort : 0;
+    sortby    = dir_skey > -1 ? dir_skey : 0;
+    reverse   = dir_rvrs > -1 ? dir_rvrs : 0;
+    msg       = dir_msg  > -1 ? dir_msg  : 0;
+#ifdef UNIXOROSK
+    if (dir_dots > -1) matchdot = dir_dots;
+#endif /* UNIXOROSK */
+    xfermod   = dir_mode > -1 ? dir_mode : 0;
+    backup    = dir_back > -1 ? dir_back : 1;
+#ifdef RECURSIVE
+    recursive = dir_recu > -1 ? dir_recu : 0;
+#endif /* RECURSIVE */
+    show      = dir_show > -1 ? dir_show : 3;
+
+#ifdef CK_TTGWSIZ
+#ifdef OS2
+    ttgcwsz();                          /* Screen length for more-prompting */
+#else /* OS2 */
+    /* Check whether window size changed */
+    if (ttgwsiz() > 0) {
+        if (tt_rows > 0 && tt_cols > 0) {
+            cmd_rows = tt_rows;
+            cmd_cols = tt_cols;
+        }
+    }
+#endif /* OS2 */
+#endif /* CK_TTGWSIZ */
+
+    diractive = 1;
+    cmifn1 = nolinks | 1;               /* 1 = files or directories */
+    cmifn2 = 0;                         /* 0 = not directories only */
+
+  again:
+
+    cmfdbi(&sw,                         /* First FDB - command switches */
+           _CMKEY,                      /* fcode */
+           "Enter or Return to confirm the command, or\n\
+ file specification, or switch",
+           "",                          /* default */
+           "",                          /* addtl string data */
+           ndirswtab,                   /* addtl numeric data 1: tbl size */
+           4,                           /* addtl numeric data 2: 4 = cmswi */
+           xxstring,                    /* Processing function */
+           dirswtab,                    /* Keyword table */
+           &fi                          /* Pointer to next FDB */
+           );
+    cmfdbi(&fi,                         /* 2nd FDB - filespec to match */
+           _CMIFI,                      /* fcode */
+           "File specification",        /* hlpmsg */
+#ifdef datageneral
+           "+",                         /* Default filespec is wildcard */
+#else                                   /* that matches all files... */
+#ifdef VMS
+           "*.*",
+#else
+           "*",
+#endif /* VMS */
+#endif /* datageneral */
+           "",                          /* addtl string data */
+           cmifn1,
+           cmifn2,                      /* 1 = only dirs; 0 files or dirs */
+           xxstring,
+           NULL,
+           &fl
+           );
+    cmfdbi(&fl,                         /* Anything that doesn't match */
+           _CMFLD,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,
+           NULL,
+           NULL
+           );
+    while (1) {                         /* Parse 0 or more switches */
+        x = cmfdb(&sw);                 /* Parse something */
+        debug(F101,"domydir cmfdb","",x);
+        if (x < 0)
+          return(x);
+        if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
+          break;
+        c = cmgbrk();
+        if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+            printf("?This switch does not take an argument\n");
+            return(-9);
+        }
+        if (!getval && (cmgkwflgs() & CM_ARG)) {
+            printf("?This switch requires an argument\n");
+            return(-9);
+        }
+        switch (k = cmresult.nresult) {
+          case DIR_BRF: verbose = 0; break;
+          case DIR_VRB: verbose = 1; break;
+#ifdef CK_TTGWSIZ
+          case DIR_PAG: page = 1;    break;
+          case DIR_NOP: page = 0;    break;
+#endif /* CK_TTGWSIZ */
+          case DIR_ISO: engdate = 0; break;
+          case DIR_DAT: engdate = 1; break;
+          case DIR_HDG: heading = 1; break;
+          case DIR_NOH: heading = 0; break;
+#ifdef UNIXOROSK
+          case DIR_DOT: matchdot = 1; break;
+          case DIR_NOD: matchdot = 0; break;
+#endif /* UNIXOROSK */
+          case DIR_ALL:
+            show = 3;
+            cmifn1 |= 1;
+            cmifn2 = 0;
+            goto again;
+          case DIR_DIR:
+            show = 2;
+            cmifn1 |= 1;
+            cmifn2 = 1;
+            goto again;
+          case DIR_FIL:
+            show = 1;
+            cmifn1 &= ~(1);
+            cmifn2 = 0;
+            goto again;
+          case DIR_SRT:
+            x = DIRS_NM;
+            if (c == ':' || c == '=')
+              if ((x = cmkey(dirsort,ndirsort,"Sort key","name",xxstring)) < 0)
+                return(x);
+            xsort = 1;
+            sortby = x;
+            break;
+
+          case DIR_BUP: backup  = 1; fs++;   break;
+          case DIR_NOB: backup  = 0; fs++;   break;
+
+          case DIR_NOS: xsort = 0;     break;
+          case DIR_ASC: reverse = 0;   break;
+          case DIR_DSC: reverse = 1;   break;
+#ifdef RECURSIVE
+          case DIR_REC: recursive = 1; diractive = 1; break;
+          case DIR_NOR: recursive = 0; diractive = 0; break;
+#endif /* RECURSIVE */
+          case DIR_TYP: xfermod = 1;   break;
+          case DIR_NOT: xfermod = 0;   break;
+
+#ifdef CKSYMLINK
+          case DIR_LNK:                 /* Follow links */
+            nolinks = 0;
+            cmifn1 &= ~(2);
+            goto again;
+          case DIR_NLK:                 /* Don't follow links */
+            nolinks = 2;
+            cmifn1 &= ~(2);
+            goto again;
+#endif /* CKSYMLINK */
+
+          case DIR_NOM: msg     = 0;   break;
+          case DIR_MSG:
+            if (c == ':' || c == '=')
+              if ((x = cmfld("Message to append to each line",
+                             "",
+                             &s,
+                             xxstring
+                             )) < 0)
+                return(x);
+            msg = 1;
+            ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
+            break;
+
+          case DIR_SMA:
+          case DIR_LAR:
+            if (!getval) break;
+            if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0)
+              return(x);
+            fs++;
+            show = 1;
+            switch (cmresult.nresult) {
+              case DIR_SMA: minsize = y; break;
+              case DIR_LAR: maxsize = y; break;
+            }
+            break;
+
+#ifndef NOSPL
+          case DIR_ARR:
+            if (c != ':' && c != '=') {
+                printf("?Array name required\n");
+                return(-9);
+            }
+            if ((x = cmfld("Array name (a single letter will do)",
+                           "",
+                           &s,
+                           NULL
+                           )) < 0) {
+                if (x == -3) {
+                    printf("?Array name required\n");
+                    return(-9);
+                } else
+                  return(x);
+            }
+            if (!*s) {
+                printf("?Array name required\n");
+                return(-9);
+            }
+            s2 = s;
+            if (*s == CMDQ) s++;
+            if (*s == '&') s++;
+            if (!isalpha(*s)) {
+                printf("?Bad array name - \"%s\"\n",s2);
+                return(-9);
+            }
+            array = *s++;
+            if (isupper(array)) array = tolower(array);
+            if (*s && (*s != '[' || *(s+1) != ']')) {
+                printf("?Bad array name - \"%s\"\n",s2);
+                return(-9);
+            }
+            break;
+#endif /* NOSPL */
+          case DIR_AFT:
+          case DIR_BEF:
+          case DIR_NAF:
+          case DIR_NBF:
+            if (!getval) break;
+            if ((x = cmdate("File-time","",&s,0,xxstring)) < 0) {
+                if (x == -3) {
+                    printf("?Date-time required\n");
+                    rc = -9;
+                } else
+                  rc = x;
+                goto xdomydir;
+            }
+            fs++;
+            switch (k) {
+              case DIR_AFT: makestr(&dir_aft,s); break;
+              case DIR_BEF: makestr(&dir_bef,s); break;
+              case DIR_NAF: makestr(&dir_naf,s); break;
+              case DIR_NBF: makestr(&dir_nbf,s); break;
+            }
+            break;
+          case DIR_EXC:
+            if (!getval) break;
+            if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
+                if (x == -3) {
+                    printf("?Pattern required\n");
+                    rc = -9;
+                } else
+                  rc = x;
+                goto xdomydir;
+            }
+            fs++;
+            makestr(&dir_exc,s);
+            break;
+
+          case DIR_SUM:
+            summary = 1; break;
+
+          case DIR_BIN: {
+              extern struct keytab txtbin[];
+              extern int xfiletype;
+              if (!getval) break;
+              if ((x = cmkey(txtbin,3,"","all",xxstring)) < 0) {
+                  rc = x;
+                  goto xdomydir;
+              }
+              if (x == 2) {
+                  xfiletype = -1;
+              } else {
+                  xfiletype = x;
+                  fs = 1;
+              }
+              break;
+          }
+          case DIR_OUT:
+            if ((x = cmofi("File for directory listing","",&s,xxstring)) < 0)
+              return(x);
+            ckstrncpy(outfile,s,CKMAXPATH+1);
+            break;
+
+          default:
+            printf("?Sorry, not implemented yet - \"%s\"\n", atmbuf);
+            goto xdomydir;
+        }
+    }
+    ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Safe copy of filespec */
+
+/* ^^^ START MULTIPLE */
+    
+    while (1) {
+       x = cmfld("Another filespec or Enter","",&s,xxstring);
+       if (x == -3)
+         break;
+       if (x < 0)
+         return(x);
+       ckstrncat(line,",",LINBUFSIZ);
+       ckstrncat(line,s,LINBUFSIZ);
+       multiple++;
+    }
+    ckmakmsg(tmpbuf,TMPBUFSIZ,"{",line,"}",NULL);
+    ckstrncpy(line,tmpbuf,LINBUFSIZ);
+    cmresult.nresult = 1;
+    cmresult.fcode = _CMIFI;
+
+/* ^^^ END MULTIPLE */
+
+    s = line;
+
+    if ((x = cmcfm()) < 0)              /* Get confirmation */
+      return(x);
+    if (cmresult.fcode != _CMIFI) {     /* Nothing matched */
+        char * m;
+        if (*s == '/')
+#ifdef UNIXOROSK
+          m = "does not match switch or name of accessible file";
+#else
+#ifdef OS2
+          m = "does not match switch or name of accessible file";
+#else
+          m = "no switches match";
+#endif /* OS2 */
+#endif /* UNIXOROSX */
+        else
+          m = "not found or not accessible";
+        printf("\"%s\" - %s\n",s,m);
+        rc = -9;
+        goto xdomydir;
+    }
+    wild = cmresult.nresult;            /* Wildcard was given? */
+    debug(F111,"domydir cmifi2",s,wild);
+
+    if (outfile[0]) {
+        ofp = fopen(outfile,"w");       /* Open output file */
+        if (!ofp) {
+            printf("?Can't open output file %s: %s\n",outfile,ck_errstr());
+            ofp = stdout;
+            return(-9);
+        }
+        page = 0;
+    }
+
+#ifdef OS2
+    if (!wild) {
+        if (zchki(s) == -2) {           /* Found a directory */
+            p = s + (int)strlen(s) - 1; /* Yes */
+            if (*p == '\\' || *p == '/')
+              strcat(s, "*");
+            else if (*p == ':')
+              strcat(s, "./*");
+            else
+              strcat(s, "/*");
+            wild = 1;                   /* Now it's wild */
+        }
+    }
+#else
+    if (!wild) if (isdir(s)) {          /* Is it a directory? */
+        p = s + (int)strlen(s) - 1;     /* Yes */
+#ifdef VMS
+        {
+            /* Convert from FOO.DIR;1 to [x.FOO] if necessary */
+            char buf[CKMAXPATH+1];
+            debug(F000,"domydir directory 0",s,*p);
+            if (cvtdir(s,buf,CKMAXPATH) > 0)
+              ckstrncpy(line,buf,LINBUFSIZ);
+        }
+#endif /* VMS */
+        debug(F000,"domydir directory 1",s,*p);
+#ifdef VMS
+        if (*p == ']' || *p == '>' || *p == ':')
+          strcat(s, "*.*");
+#else
+#ifdef datageneral
+        if (*p == ':')
+          strcat(s, "+");
+        else
+          strcat(s, ":+");
+#else
+#ifdef STRATUS
+        if (*p == '>')
+          strcat(s, "*");
+        else
+          strcat(s, ">*");
+#endif /* STRATUS */
+#endif /* datageneral */
+#endif /* VMS */
+        wild = 1;                       /* Now it's wild */
+        debug(F000,"domydir directory 2",s,*p);
+    }
+#endif /* OS2 */
+
+#ifdef ZXREWIND
+/* cmifi() already called nzxpand so we can just re-use the same list. */
+    if (!multiple) {
+       x = zxrewind();                 /* Rewind the list */
+       debug(F111,"domydir zxrewind",s,x);
+    } else {
+#endif /* ZXREWIND */
+       nzxopts = (show == ZX_DIRONLY) ? ZX_DIRONLY :
+         (show == ZX_FILONLY ? ZX_FILONLY : 0);
+       if (matchdot)  nzxopts |= ZX_MATCHDOT;
+       if (recursive) nzxopts |= ZX_RECURSE;
+       x = nzxpand(s,nzxopts);             /* Expand file list */
+       debug(F111,"domydir nzxpand",s,x);
+#ifdef ZXREWIND
+    }
+#endif /* ZXREWIND */
+
+#ifndef NOSPL
+    if (array) {
+        int n, xx;
+        n = (x < 0) ? 0 : x;
+        if ((xx = dclarray(array,n)) < 0) {
+            printf("?Array declaration failure\n");
+            rc = -9;
+            goto xdomydir;
+        }
+        array = xx;
+        ap = a_ptr[array];
+        if (n < 1) {
+            rc = 0;
+            goto xdomydir;
+        }
+    } else
+#endif /* NOSPL */
+      if (x < 1) {
+#ifdef CKROOT
+          extern int ckrooterr;
+          if (ckrooterr)
+            printf("?Off limits: %s\n",s);
+          else
+#endif /* CKROOT */
+            if (x == 0 && isdir(s))
+              printf("?Empty directory - \"%s\"\n", s);
+            else
+              printf("?%s %s match - \"%s\"\n",
+                     (x == 0) ? "No" : "Too many",
+                     (show == 2) ? "directories" : "files",
+                     s
+                     );
+          rc = -9;
+          goto xdomydir;
+    }
+    nx = x;                             /* Remember how many files */
+
+    if (msg) {
+        makestr(&dirmsg,tmpbuf);
+        dirmsglen = strlen(tmpbuf);
+    }
+
+#ifdef VMS
+    cdp = zgtdir();                     /* Get current directory */
+    debug(F110,"domydir VMS zgtdir",cdp,0);
+#endif /* VMS */
+
+    if (xsort && verbose) {             /* If sorting, allocate space */
+        if (!(dirlist = (char **) malloc((x + 1) * sizeof(char **)))) {
+            if (!quiet) {
+                printf("* Warning: Failure to allocate memory for sorting.\n");
+                printf("* Will proceed without sorting...\n");
+            }
+            xsort = 0;
+        }
+        debug(F101,"domydir sort malloc","",xsort);
+    }
+
+    /* Display the listing */
+
+#ifndef NOSPL
+    if (array)                          /* Storing instead of printing */
+      heading = 0;
+#endif /* NOSPL */
+
+    if (heading) {                      /* If /HEADING print heading */
+        zfnqfp(s,TMPBUFSIZ,tmpbuf);
+        fprintf(ofp,"\nDirectory of %s\n\n",tmpbuf);
+        n += 3;
+    }
+    if (page > -1)                      /* Paging */
+      xaskmore = page;
+
+    if (!verbose) {                     /* /BRIEF */
+        if (outfile[0]) {               /* To file  */
+            int k = 0;
+            znext(name);
+            while (name[0]) {           /* One line per file */
+                k++;
+                if (fs) if (fileselect(name,
+                                       dir_aft,dir_bef,dir_naf,dir_nbf,
+                                       minsize,maxsize,!backup,16,xlist) < 1) {
+                    znext(name);
+                    continue;
+                }
+                fprintf(ofp,"%s\n",name);
+                znext(name);
+            }
+            if (heading)
+              fprintf(ofp,"Files: %d\n\n",k);
+            rc = 1;
+            goto xdomydir;
+        } else {
+            rc = filhelp(x,"","",n,0);
+            if (rc < 0)
+              goto xdomydir;
+            if (heading && rc > 0)
+              fprintf(ofp,"Files: %d\n\n",x); /* (Might scroll a line or 2) */
+            rc = 1;
+            goto xdomydir;
+        }
+    }
+    ndirs = nfiles = nbytes = 0L;       /* Initialize counters */
+
+    if (dir_exc)                        /* Have exception list? */
+      makelist(dir_exc,xlist,16);      /* Yes, convert to array */
+
+    diractive = 1;
+    znext(name);                        /* Get next file */
+    while (name[0]) {                   /* Loop for each file */
+        if (fs) if (fileselect(name,
+                       dir_aft,dir_bef,dir_naf,dir_nbf,
+                       minsize,maxsize,!backup,16,xlist) < 1) {
+            znext(name);
+            continue;
+        }
+        len = zgetfs(name);             /* Get file length */
+        debug(F111,"domydir zgetfs",name,len);
+#ifdef VMSORUNIX
+        itsadir = zgfs_dir;             /* See if it's a directory */
+#else
+        itsadir = (len == -2 || isdir(name));
+#endif /* VMSOUNIX */
+        debug(F111,"domydir itsadir",name,itsadir);
+        if ((itsadir && (show == 1)) || (!itsadir && (show == 2))) {
+            znext(name);
+            continue;
+        }
+        /* Get here when we know we have selected this file */
+
+        nmatches ++;
+        if (itsadir) {                  /* Accumulate totals for summary */
+            ndirs++;
+        } else {
+            nfiles++;
+            nbytes += len;
+        }
+        if (summary) {                  /* Summary only, no detail */
+            znext(name);
+            continue;
+        }
+#ifndef NOSPL
+        if (array) {
+            debug(F111,"domydir array",name,nfiles);
+            if (ap)
+              makestr(&(ap[nmatches]),name);
+            znext(name);
+            continue;
+        }
+#endif /* NOSPL */
+
+/*
+  NOTE: The sprintf's in this routine should be safe.  They involve
+  permission strings, date/time strings, and filenames, all of which have
+  known maximum lengths; none of these items is input from users.  The
+  destination buffers are large enough to hold maximum sizes for any and
+  all items.
+*/
+        dstr = zfcdat(name);            /* Get modification date/time */
+        debug(F111,"domydir zcfdat",dstr,0);
+        if (!dstr) dstr = "";
+        {
+/*
+  Note that zfcdat() always returns "" or yyyymmdd hh:mm:ss, so any warnings
+  about possible out-of-bounds dstr[] array refs do not apply.  This block of
+  code is to stifle the warnings and also allows for any out-of-spec
+  zfcdat() implementations.
+*/
+            int x;
+            char * p = "00000000 00:00:00";
+            x = ckstrncpy(xbuf,dstr,32);
+            if (x < 17) ckstrncpy(&xbuf[x],p+x,32-x);
+            dstr = xbuf;
+        }
+        if (engdate) {                  /* English date requested? */
+            short month, day, year, hour, minute, seconds;
+            month = (dstr[4]-48)*10 + (dstr[5]-48);
+            mstr  = (month > 0 && month <= 12) ? months[month-1] : "xxx";
+            day   = (dstr[6]-48)*10 + (dstr[7]-48);
+            year  = (((dstr[0]-48)*10 +
+                      (dstr[1]-48))*10 +
+                      (dstr[2]-48))*10 +
+                      (dstr[3]-48);
+            hour  = (dstr[9]-48)*10 + (dstr[10]-48);
+            minute = (dstr[12]-48)*10 + (dstr[13]-48);
+            seconds = (dstr[15]-48)*10 + (dstr[16]-48);
+            sprintf(dbuf,               /* SAFE */
+                    "%2d-%s-%4d %02d:%02d:%02d",
+                    day,mstr,year,hour,minute,seconds
+                    );
+            dstr = dbuf;
+        } else {                        /* ISO date */
+            dbuf[0] = dstr[0];          /* yyyy */
+            dbuf[1] = dstr[1];
+            dbuf[2] = dstr[2];
+            dbuf[3] = dstr[3];
+            dbuf[4] = '-';
+            dbuf[5] = dstr[4];          /* mm (numeric) */
+            dbuf[6] = dstr[5];
+            dbuf[7] = '-';
+            dbuf[8] = dstr[6];          /* dd */
+            dbuf[9] = dstr[7];
+            strcpy(dbuf+10,dstr+8);     /* hh:mm:ss */
+            dstr = dbuf;
+        }
+        dlen = strlen(dbuf);            /* Length of date */
+        name[CKMAXPATH] = NUL;
+#ifdef CK_PERMS
+#ifdef VMSORUNIX
+        p = ziperm(name);               /* Get permissions */
+        debug(F110,"ziperm perms",p,0);
+#else
+        p = zgperm(name);
+        debug(F110,"zgperm perms",p,0);
+#endif /* VMSORUNIX */
+#else
+        p = NULL;
+        debug(F110,"NULL perms",p,0);
+#endif /* CK_PERMS */
+
+#ifdef VMS
+        /* Get relative name to save space -- VMS fullnames are long... */
+        ckstrncpy(name,zrelname(name,cdp),CKMAXPATH);
+#endif /* VMS */
+
+        if (itsadir && len < 0) {       /* Directory */
+#ifdef VMS
+            sprintf(linebuf,"%-22s%-10s  %s  %s",p,"<DIR>",dstr,name);
+#else
+            if (p)
+              sprintf(linebuf,"%10s%-10s  %s  %s",p,"<DIR>",dstr,name);
+            else
+              sprintf(linebuf,"%-10s  %s  %s", "<DIR>", dstr, name);
+#endif /* VMS */
+        } else {                        /* Regular file */
+#ifdef VMS
+            sprintf(linebuf,"%-22s%10ld  %s  %s", p, len, dstr, name);
+#else
+            if (p)
+              sprintf(linebuf,"%10s%10ld  %s  %s", p, len, dstr, name);
+            else
+              sprintf(linebuf,"%10ld  %s  %s", len, dstr, name);
+#endif /* VMS */
+        }
+#ifdef UNIX
+#ifdef CKSYMLINK
+        if (zgfs_link) {
+            int n, m;
+            extern char linkname[];
+            n = strlen(linebuf);
+            m = strlen(linkname) + n;
+            if (m < CKMAXPATH + 58)
+              strcpy(linebuf+n, " -> "); /* safe (checked) */
+            if (m + 4 < CKMAXPATH - 58)
+              strcpy(linebuf+n+4, linkname); /* safe (checked) */
+        } else
+#endif /* CKSYMLINK */
+#endif /* UNIX */
+        if (xfermod) {                  /* Show transfer mode */
+            int i, x, y;
+            char * s = "";
+            y = -1;
+            x = scanfile(name,&y,nscanfile);
+            switch (x) {
+              case FT_TEXT: s = " (T)"; break;
+              case FT_7BIT: s = " (T)(7BIT)"; break;
+              case FT_8BIT: s = " (T)(8BIT)"; break;
+#ifdef UNICODE
+              case FT_UTF8: s = " (T)(UTF8)"; break;
+              case FT_UCS2:
+                s = y ? " (T)(UCS2LE)" : " (T)(UCS2BE)";
+                break;
+#endif /* UNICODE */
+              case FT_BIN:  s = " (B)"; break;
+            }
+            if (!*s) {
+                s = binary ? " (B)" : " (T)";
+            }
+            if (*s) {
+                int n;
+                n = strlen(linebuf);
+                if (n + 4 < CKMAXPATH - 58)
+                  strcpy(linebuf+n, s); /* safe (checked) */
+            }
+        }
+        if (msg && dirmsg) {
+            int n;
+            n = strlen(linebuf);
+            if (n + dirmsglen + 2 < CKMAXPATH)
+              sprintf((char *)(linebuf+n)," %s", dirmsg); /* SAFE */
+        }
+        if (xsort) {                    /* Sorting - save line */
+            i = strlen(linebuf);
+            if ((ndirlist >= nx) ||
+                !(dirlist[ndirlist] = (char *)malloc(i+1))) {
+                printf("?Memory allocation error - try /NOSORT\n");
+                rc = -9;
+                goto xdomydir;
+            }
+            strcpy(dirlist[ndirlist],linebuf); /* safe */
+            ndirlist++;
+        }
+        znext(name);                    /* Peek ahead to next file */
+
+        if (!xsort) {
+            fprintf(ofp,"%s\n",linebuf);
+            if (page && (name[0] || heading)) { /* If /PAGE */
+                if (cmd_cols > 0) {
+                    int x = strlen(linebuf);
+                    int y;
+                    y = (x % cmd_cols) ? 1 : 0;
+                    n += x / cmd_cols + y;
+                } else {
+                    n++;
+                }
+#ifdef CK_TTGWSIZ
+                if (n > (cmd_rows - 3)) { /* Do more-prompting */
+                    if (!askmore()) {
+                        rc = 0;
+                        goto xdomydir;
+                    } else
+                      n = 0;
+                }
+#endif /* CK_TTGWSIZ */
+            }
+        }
+    }
+#ifndef NOSPL
+    if (array) {
+        if (ap)
+          makestr(&(ap[0]),ckitoa(nmatches));
+        rc = 1;
+        goto xdomydir;
+    }
+#endif /* NOSPL */
+    if (xsort) {
+        skey = 0;
+#ifdef VMS
+        switch (sortby) {
+          case DIRS_NM: skey = dlen + 35; break;
+          case DIRS_DT: skey = 33; break;
+          case DIRS_SZ: skey = 21;
+        }
+#else
+        if (p) {
+            switch (sortby) {
+              case DIRS_NM: skey = dlen + 24; break;
+              case DIRS_DT: skey = 22; break;
+              case DIRS_SZ: skey = 10;
+            }
+        } else {
+            switch (sortby) {
+              case DIRS_NM: skey = dlen + 14; break;
+              case DIRS_DT: skey = 12; break;
+              case DIRS_SZ: skey = 0;
+            }
+        }
+#endif /* VMS */
+        sh_sort(dirlist,NULL,ndirlist,skey,reverse,filecase);
+        for (i = 0; i < ndirlist; i++) {
+            fprintf(ofp,"%s\n",dirlist[i]);
+            if (page && (i < ndirlist -1 || heading)) { /* If /PAGE */
+                if (cmd_cols > 0) {
+                    int x = strlen(dirlist[i]);
+                    int y;
+                    y = (x % cmd_cols) ? 1 : 0;
+                    n += ((int)strlen(dirlist[i]) / cmd_cols) + y;
+                } else {
+                    n++;
+                }
+#ifdef CK_TTGWSIZ
+                if (n > (cmd_rows - 3)) { /* Do more-prompting */
+                    if (!askmore()) {
+                        rc = 0;
+                        goto xdomydir;
+                    } else
+                      n = 0;
+                }
+#endif /* CK_TTGWSIZ */
+            }
+        }
+    }
+
+    if (heading || summary) {
+#ifdef CKFLOAT
+        CKFLOAT gm;
+#endif /* CKFLOAT */
+        fprintf(ofp,"\n%ld director%s, %ld file%s, %ld byte%s",
+               ndirs,
+               (ndirs == 1) ? "y" : "ies",
+               nfiles,
+               (nfiles == 1) ? "" : "s",
+               nbytes,
+               (nbytes == 1) ? "" : "s"
+               );
+#ifdef CKFLOAT
+        gm = ((CKFLOAT) nbytes ) / 1000000.0;
+        if (gm > 1000.0)
+          fprintf(ofp," (%0.2fGB)",(gm / 1000.0));
+        else if (gm >= 0.01)
+          fprintf(ofp," (%0.2fMB)",gm);
+#endif /* CKFLOAD */
+        fprintf(ofp,"\n\n");
+    }
+  xdomydir:
+    if (g_matchdot > -1) {
+        matchdot = g_matchdot;          /* Restore these... */
+        g_matchdot = -1;
+    }
+    freedirlist();
+    if (ofp != stdout) {                /* Close any output file */
+        if (ofp) fclose(ofp);
+        ofp = stdout;
+    }
+    if (rc > 0)
+      success = 1;
+    return(rc);
+}
+
+int
+dodir(cx) int cx; {                     /* Do the DIRECTORY command */
+    char *dc , *msg;
+
+#ifdef OS2
+    return(domydir());
+#else /* OS2 */
+    if (nopush
+#ifdef DOMYDIR                          /* Builds that domydir() by default */
+        || (cx == XXDIR || cx == XXLDIR)
+#endif /* DOMYDIR */
+        )
+      return(domydir());                /* Built-in directory command */
+
+    /* Use the system's directory command. */
+
+    msg = (cx == XXLS) ?
+      "Arguments for ls" :
+        "Directory and/or file specification";
+    if ((x = cmtxt(msg,"",&s,xxstring)) < 0)
+      return(x);
+
+    ckstrncpy(tmpbuf,s,TMPBUFSIZ);      /* Copy the filespec */
+    s = tmpbuf;
+
+    if ((y = cmcfm()) < 0) return(y);
+
+    lp = line;
+    if (!(dc = getenv("CK_DIR")))
+      dc = DIRCMD;
+    ckmakmsg(lp,LINBUFSIZ,dc," ",s,NULL);
+    debug(F110,"DIR",line,0);
+#ifdef VMS
+    conres();
+#endif /* VMS */
+    x = zshcmd(line);
+#ifdef VMS
+    concb((char)escape);
+#endif /* VMS */
+    return(success = (x < 1) ? 0 : 1);
+#endif /* OS2 */
+}
+
+#ifndef NOSERVER
+#ifndef NOFRILLS
+/* Do the ENABLE and DISABLE commands */
+
+int
+doenable(y,x) int y, x; {
+#ifdef CK_LOGIN
+    if (isguest)                        /* IKSD: Don't let guests */
+      return(0);                        /* enable anything that's disabled */
+#endif /* CK_LOGIN */
+    switch (x) {
+      case EN_ALL:
+        en_cwd = en_cpy = en_del = en_dir = en_fin = en_get = y;
+        en_ren = en_sen = en_set = en_spa = en_typ = en_ret = y;
+        if (!inserver)
+          en_who = en_mai = en_pri = y;
+        en_mkd = en_rmd = y;
+        en_xit = y;
+#ifndef datageneral
+        en_bye = y;
+#endif /* datageneral */
+#ifndef NOPUSH
+        if (!nopush && !inserver)
+          en_hos = y;
+#endif /* NOPUSH */
+#ifndef NOSPL
+        en_asg = en_que = y;
+#endif /* NOSPL */
+        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_CPY:
+        en_cpy = y;
+        break;
+      case EN_CWD:
+        en_cwd = y;
+#ifdef IKSD
+        if (inserver && y == 0) {
+            fnrpath = PATH_OFF;
+            fnspath = PATH_OFF;
+        }
+#endif /* IKSD */
+        break;
+      case EN_DEL:                      /* Deleting of files */
+        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:
+        if (!nopush)
+         en_hos = y;
+        break;
+#endif /* NOPUSH */
+      case EN_REN:
+        en_ren = y;
+        break;
+      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;
+#ifndef NOSPL
+      case EN_ASG:
+        en_asg = y;
+        break;
+      case EN_QUE:
+        en_que = y;
+        break;
+#endif /* NOSPL */
+      case EN_RET:
+        en_del = y;
+        break;
+      case EN_MAI:
+#ifdef CK_LOGIN
+        if (isguest && y) {
+            printf("?Sorry, not valid for guests\n");
+            return(-9);
+        }
+#endif /* CK_LOGIN */
+        en_mai = y;
+        break;
+      case EN_PRI:
+#ifdef CK_LOGIN
+        if (isguest && y) {
+            printf("?Sorry, not valid for guests\n");
+            return(-9);
+        }
+#endif /* CK_LOGIN */
+        en_pri = y;
+        break;
+      case EN_MKD:
+        en_mkd = y;
+        break;
+      case EN_RMD:
+        en_rmd = y;
+        break;
+      case EN_XIT:
+        en_xit = y;
+        break;
+      case EN_ENA:
+        if (((y & 1) && !(en_ena & 1)) ||
+            ((y & 2) && !(en_ena & 2))) {
+            printf("?Sorry, DISABLE ENABLE can not be undone\n");
+            return(-9);
+        } else {
+            en_ena = y;
+            break;
+        }
+      default:
+        return(-2);
+    }
+    return(1);
+}
+#endif /* NOFRILLS */
+#endif /* NOSERVER */
+
+#ifndef NOFRILLS
+
+static int del_lis = 0;
+static int del_dot = 0;
+static int del_hdg = 0;
+static int del_pag = -1;
+static int del_ask = 0;
+
+#ifndef NOSHOW
+VOID
+showdelopts() {
+    int x = 0;
+    extern int optlines;
+    prtopt(&optlines,"");
+    prtopt(&optlines,"DELETE");
+    if (del_ask > -1) {
+        prtopt(&optlines, del_ask ? "/ASK" : "/NOASK");
+        x++;
+    }
+#ifdef UNIXOROSK
+    if (del_dot > -1) {
+        prtopt(&optlines, del_dot ? "/DOTFILES" : "/NODOTFILES");
+        x++;
+    }
+#endif /* UNIXOROSK */
+    if (del_lis > -1) {
+        prtopt(&optlines, del_lis ? "/LIST" : "/NOLIST");
+        x++;
+    }
+    if (del_hdg > -1) {
+        prtopt(&optlines, del_hdg ? "/HEADING" : "/NOHEADING");
+        x++;
+    }
+#ifndef CK_TTGWSIZ
+    if (del_pag > -1) {
+        prtopt(&optlines, del_pag ? "/PAGE" : "/NOPAGE");
+        x++;
+    }
+#endif /* CK_TTGWSIZ */
+    if (!x) prtopt(&optlines,"(no options set)");
+    prtopt(&optlines,"");
+}
+#endif /* NOSHOW */
+
+
+int
+setdelopts() {
+    int x_lis = -1, x_pag = -1, x_dot = -1, x_hdg = -1, x_ask = -1;
+    int getval = 0;
+    char c;
+    while (1) {
+        if ((y = cmswi(deltab,ndeltab,"Switch","",xxstring)) < 0) {
+            if (y == -3)
+              break;
+            else
+              return(y);
+        }
+        c = cmgbrk();
+        if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+            printf("?This switch does not take an argument\n");
+            return(-9);
+        }
+        if (!getval && (cmgkwflgs() & CM_ARG)) {
+            printf("?This switch requires an argument\n");
+            return(-9);
+        }
+        switch (y) {
+          case DEL_DOT:
+            x_dot = 1;
+            break;
+          case DEL_NOD:
+            x_dot = 0;
+            break;
+          case DEL_HDG:
+            x_hdg = 1;
+            break;
+          case DEL_LIS:
+            x_lis = 1;
+            break;
+          case DEL_NOL:
+            x_lis = 0;
+            break;
+#ifndef CK_TTGWSIZ
+          case DEL_PAG:
+            x_pag = 1;
+            break;
+          case DEL_NOP:
+            x_pag = 0;
+            break;
+#endif /* CK_TTGWSIZ */
+          case DEL_QUI:
+            x_lis = 0;
+            break;
+          case DEL_VRB:
+            x_lis = 1;
+            break;
+          case DEL_ASK:
+            x_ask = 1;
+            break;
+          case DEL_NAS:
+            x_ask = 0;
+            break;
+          default:
+            printf("?Sorry, this option can not be set\n");
+            return(-9);
+        }
+    }
+    if ((x = cmcfm()) < 0)              /* Get confirmation */
+      return(x);
+    if (x_pag > -1) del_pag = x_pag;
+    if (x_dot > -1) del_dot = x_dot;
+    if (x_hdg > -1) del_hdg = x_hdg;
+    if (x_lis > -1) del_lis = x_lis;
+    if (x_ask > -1) del_ask = x_ask;
+    return(success = 1);
+}
+
+#ifdef OS2
+static char ** xmtchs = NULL;
+static int xmtchn = 0;
+#endif /* OS2 */
+
+int
+dodel() {                               /* DELETE */
+    int i, j, k, x;
+    int fs = 0;                         /* Need to call fileselect() */
+    int len = 0;
+    int bad = 0;
+    int getval = 0, asking = 0;
+    int simulate = 0, rc = 0;
+    long minsize = -1L, maxsize = -1L;
+    int havename = 0, confirmed = 0;
+    int qflag = 0;
+    int summary = 0;
+    int deldirs = 0;
+    int deltree = 0;
+    int itsadir = 0;
+    int argisdir = 0;
+    int xmode = -1, scan = 0, skip = 0;
+#ifdef COMMENT
+    int pass = 0;
+#endif /* COMMENT */
+    char c;
+    char * deldef = "";
+    char safebuf[CKMAXPATH+1];
+    struct FDB sw, fi, fl;
+    char
+      * del_aft = NULL,
+      * del_bef = NULL,
+      * del_naf = NULL,
+      * del_nbf = NULL,
+      * del_exc = NULL;
+    int
+      x_lis = 0,
+      /* x_dot = -1, */
+      x_hdg = 0;
+
+    char * dxlist[8];
+
+    for (i = 0; i < 8; i++) dxlist[i] = NULL;
+
+    g_matchdot = matchdot;
+
+    if (del_lis > -1) x_lis    = del_lis;
+    if (del_dot > -1) matchdot = del_dot;
+    if (del_hdg > -1) x_hdg    = del_hdg;
+    if (del_pag > -1) xaskmore = del_pag;
+    if (del_ask > -1) asking   = del_ask;
+
+    diractive = 1;
+    nolinks = 2;                        /* By default don't follow links */
+
+    cmfdbi(&sw,                         /* First FDB - command switches */
+           _CMKEY,                      /* fcode */
+           "File specification;\n or switch",
+           "",                          /* default */
+           "",                          /* addtl string data */
+           ndeltab,                     /* addtl numeric data 1: tbl size */
+           4,                           /* addtl numeric data 2: 4 = cmswi */
+           xxstring,                    /* Processing function */
+           deltab,                      /* Keyword table */
+           &fi                          /* Pointer to next FDB */
+           );
+    cmfdbi(&fl,                         /* Anything that doesn't match */
+           _CMFLD,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,
+           NULL,
+           NULL
+           );
+  again:
+    cmfdbi(&fi,                         /* 2nd FDB - file to delete */
+           _CMIFI,                      /* fcode */
+           "File(s) to delete",         /* hlpmsg */
+           deldef,                      /* default */
+           "",                          /* addtl string data */
+           nolinks | deldirs,           /* 0 = files, 1 = files or dirs */
+           0,                           /* 1 = dirs only */
+           xxstring,
+           NULL,
+           &fl
+           );
+    while (!havename && !confirmed) {
+        x = cmfdb(&sw);                 /* Parse something */
+        if (x < 0) {                    /* Error */
+            if (x == -3)
+              break;
+            if (x == -2 || x == -9)
+              printf("?Does not match switch or filename: \"%s\"\n",atmbuf);
+            return(x);
+        }
+        if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
+          break;
+        c = cmgbrk();                   /* Get break character */
+        if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+            printf("?This switch does not take an argument\n");
+            rc = -9;
+            goto xdelete;
+        }
+        if (!getval && (cmgkwflgs() & CM_ARG)) {
+            printf("?This switch requires an argument\n");
+            rc = -9;
+            goto xdelete;
+        }
+        switch (k = cmresult.nresult) {
+          case DEL_AFT:
+          case DEL_BEF:
+          case DEL_NAF:
+          case DEL_NBF:
+            if (!getval) break;
+            if ((x = cmdate("File-time","",&s,0,xxstring)) < 0) {
+                if (x == -3) {
+                    printf("?Date-time required\n");
+                    x = -9;
+                } else
+                  rc = x;
+                goto xdelete;
+            }
+            fs++;
+            deltree = 0;
+            switch (k) {
+              case DEL_AFT: makestr(&del_aft,s); break;
+              case DEL_BEF: makestr(&del_bef,s); break;
+              case DEL_NAF: makestr(&del_naf,s); break;
+              case DEL_NBF: makestr(&del_nbf,s); break;
+            }
+            break;
+          case DEL_DOT:
+            matchdot = 1;
+            break;
+          case DEL_NOD:
+            matchdot = 0;
+            break;
+          case DEL_ALL:
+            fs = 0;
+#ifdef VMS
+            deldef = "*.*";             /* UNIX, Windows, OS/2 */
+#else
+#ifdef datageneral
+            deldef = "+";               /* AOS/VS */
+#else
+            deldef = "*";               /* UNIX, Windows, OS/2, VMS... */
+#endif /* datageneral */
+#endif /* VMS */
+            deltree = 1;
+            nolinks = 2;
+            matchdot = 1;
+            recursive = 1;              /* Fall through purposely... */
+          case DEL_DIR:
+            deldirs = 1;
+            goto again;
+          case DEL_EXC:
+            if (!getval) break;
+            if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
+                if (x == -3) {
+                    printf("?Pattern required\n");
+                    x = -9;
+                } else
+                  rc = x;
+                goto xdelete;
+            }
+            fs++;
+            deltree = 0;
+            makestr(&del_exc,s);
+            break;
+          case DEL_HDG:
+            x_hdg = 1;
+            break;
+#ifdef RECURSIVE
+          case DEL_REC:
+            recursive = 1;
+            break;
+#endif /* RECURSIVE */
+          case DEL_LIS:
+            x_lis = 1;
+            break;
+          case DEL_SUM:
+            summary = 1;
+            x_lis = 0;
+            x_hdg = 1;
+            break;
+          case DEL_NOL:
+            x_lis = 0;
+            break;
+#ifndef CK_TTGWSIZ
+          case DEL_PAG:
+            xaskmore = 1;
+            break;
+          case DEL_NOP:
+            xaskmore = 0;
+            break;
+#endif /* CK_TTGWSIZ */
+          case DEL_QUI:
+            qflag = 1;
+            x_lis = 0;
+            break;
+          case DEL_VRB:
+            x_lis = 1;
+            break;
+
+          case DEL_SMA:
+          case DEL_LAR:
+            if (!getval) break;
+            if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0)
+              return(x);
+            fs++;
+            deltree = 0;
+            switch (cmresult.nresult) {
+              case DEL_SMA: minsize = y; break;
+              case DEL_LAR: maxsize = y; break;
+            }
+            break;
+
+          case DEL_SIM:
+            simulate = 1;
+            x_lis = 1;
+            break;
+          case DEL_ASK:
+            asking = 1;
+            break;
+          case DEL_NAS:
+            asking = 0;
+            break;
+          case DEL_TYP: {
+              extern struct keytab txtbin[];
+              if (!getval) break;
+              if ((x = cmkey(txtbin,3,"","",xxstring)) < 0)
+                return(x);
+              if (x == 2) {             /* ALL */
+                  xmode = -1;
+              } else {                  /* TEXT or BINARY only */
+                  xmode = x;
+                  scan = 1;
+              }
+              break;
+          }
+          default:
+            printf("?Not implemented yet - \"%s\"\n",atmbuf);
+            return(-9);
+        }
+    }
+    if (qflag && (cmresult.fcode == _CMFLD)) {
+        if ((x = cmcfm()) < 0)
+          return(x);
+        else
+          return(success = 0);
+    }
+    if (cmresult.fcode != _CMIFI) {
+        if (*atmbuf) {
+           int x;
+            if (iswild(atmbuf) && nzxpand(atmbuf,nzxopts) == 0)
+              printf("?No files match: %s\n",atmbuf);
+            else if ((x = zchki(atmbuf)) == -1)
+             printf("?File not found: %s\n",atmbuf);
+           else if (x == -2)
+             printf("?Not a regular file: %s\n",atmbuf);
+           else
+              /* printf("?Not a deletable file: %s\n",atmbuf); */
+              goto tryanyway;
+        } else {
+            printf("?A file specification is required\n");
+        }
+        return(-9);
+    }
+  tryanyway:
+    ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ); /* Safe copy of filespec */
+    if (deldirs) {
+        ckstrncpy(safebuf,cmresult.sresult,CKMAXPATH);
+#ifdef VMSORUNIX
+        len = zgetfs(tmpbuf);           /* Is it a directory name? */
+        argisdir = zgfs_dir;            /* Then because of how zxpand() */
+        if (argisdir && zgfs_link)      /* works, we have to add it to */
+          argisdir = 0;                 /* the list. */
+        if (itsadir)
+          len = -2;
+#else
+        len = zchki(tmpbuf);
+        if (len < 0)
+          argisdir = isdir(tmpbuf);
+#endif /* VMSORUNIX */
+    }
+    debug(F110,"DELETE file",tmpbuf,0);
+    if ((x = cmcfm()) < 0)
+      return(x);
+
+#ifdef IKSD
+#ifdef CK_LOGIN
+    if (inserver && isguest) {
+        printf("?Sorry, DELETE unavailable to guests\n");
+        return(-9);
+    }
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+
+#ifndef OS2ORUNIX
+    if (simulate) {
+        printf("?Sorry, /SIMULATE not implemented on this platform\n");
+        return(-9);
+    }
+#endif /* OS2ORUNIX */
+
+#ifdef COMMENT
+    /* (not needed) */
+    if (!iswild(tmpbuf)) {
+        char *m;
+        errno = 0;
+        x = zchki(tmpbuf);
+        if (x < 0) {
+            switch (x) {
+              case -2: m = "Not a regular file"; break;
+              case -1: m = "File not found or not accessible"; break;
+              default: m = errno ? ck_errstr() : "Can't delete";
+            }
+            printf("?%s: \"%s\"\n",m,tmpbuf);
+            return(-9);
+        }
+    }
+#endif /* COMMENT */
+
+    makelist(del_exc,dxlist,8);
+
+/* tmpbuf[] has the name - now do any needed conversions on it */
+
+#ifdef OS2
+    {   /* Lower level functions change / to \, not good for CMD.EXE. */
+        char *p = tmpbuf;
+        while (*p) {                    /* Change them back to \ */
+            if (*p == '/') *p = '\\';
+            p++;
+        }
+    }
+#endif /* OS2 */
+
+#ifdef VMS
+    if (iswild(tmpbuf)) {
+#ifdef COMMENT
+        /* Does not handle '.' as version separator */
+        char *p = tmpbuf;
+        x = 0;
+        while (*p) {
+            if (*p == ';') {
+                x = 1;
+                break;
+            } else
+              p++;
+        }
+        if (!x) ckstrncat(tmpbuf,";*",TMPBUFSIZ);
+#else
+        j = 0; x = 0;                   /* for end_dot and number of dots */
+        i = strlen(tmpbuf);
+        if (tmpbuf[i] == ';') {
+            ckstrncat(tmpbuf,"0",TMPBUFSIZ);
+        } else {
+            if (tmpbuf[i--] == '.')
+              j++;
+            for (; i >= 0; i--) {
+                if (tmpbuf[i] == ';' || tmpbuf[i] == ':' ||
+                    tmpbuf[i] == ']' || tmpbuf[i] == '>')
+                  break;
+                else if (tmpbuf[i] == '.')
+                  x++;
+            }
+            if (tmpbuf[i] != ';') {     /* dot may have been used */
+                if (j) {                /* last char is dot */
+                  if (x)                /* second is version separator */
+                    ckstrncat(tmpbuf,"0",TMPBUFSIZ);
+                  else                  /* 'foo.' */
+                    ckstrncat(tmpbuf,";0",TMPBUFSIZ);
+                } else if (x == 1)      /* lacking a version separator */
+                  ckstrncat(tmpbuf,";0",TMPBUFSIZ);
+                else if (x == 0)        /* x == 2 has a version */
+                  ckstrncat(tmpbuf,".*;0",TMPBUFSIZ);
+            }
+        }
+#endif /* COMMENT */
+    }
+#endif /* VMS */
+
+    debug(F110,"dodel tmpbuf",tmpbuf,0); /* Filename */
+
+#ifndef OS2ORUNIX                       /* No built-in DELETE code... */
+    /* Construct system command. */
+    ckmakmsg(line,LINBUFSIZ,DELCMD," ",tmpbuf,NULL);
+#else
+#ifdef VMS
+    if (asking) {                       /* Maybe overwrite in VMS */
+        if (x_lis)                      /* if options are needed... */
+          ckmakmsg(line,LINBUFSIZ,DELCMD," /confirm/log ",tmpbuf,NULL);
+        else
+          ckmakmsg(line,LINBUFSIZ,DELCMD," /confirm ",tmpbuf,NULL);
+    } else if (x_lis)
+      ckmakmsg(line,LINBUFSIZ,DELCMD," /log ",tmpbuf,NULL);
+    conres();
+#endif /* VMS */
+
+    debug(F110,"dodel line",line,0);
+#endif /* OS2ORUNIX */
+
+#ifdef MAC
+    success = (zdelet(tmpbuf) == 0);
+
+#else  /* !MAC ... */
+
+#ifdef OS2ORUNIX
+    {
+        int filespace = 0;
+        int count = 0;
+        int lines = 0;
+        int n = 0;
+
+        s = tmpbuf;
+
+#ifdef CK_TTGWSIZ
+#ifdef OS2
+        ttgcwsz();
+#else /* OS2 */
+        /* Check whether window size changed */
+        if (ttgwsiz() > 0) {
+            if (tt_rows > 0 && tt_cols > 0) {
+                cmd_rows = tt_rows;
+                cmd_cols = tt_cols;
+            }
+        }
+#endif /* OS2 */
+#endif /* CK_TTGWSIZ */
+
+        if (x_hdg > 0 && !summary) {
+            printf("Deleting %s...%s\n", s, simulate ? " (SIMULATION)" : "");
+            n += 2;
+        }
+#ifdef ZXREWIND
+        z = zxrewind();                 /* Rewind file list */
+#else
+        if (!deldirs)
+          nzxopts = ZX_FILONLY;
+        if (recursive) nzxopts |= ZX_RECURSE;
+        if (matchdot)  nzxopts |= ZX_MATCHDOT;
+        errno = 0;
+        z = nzxpand(s,nzxopts);         /* Expand file list */
+#endif /* ZXREWIND */
+        debug(F111,"dodel",s,z);
+
+        /* If deleting directories, sort in reverse order */
+        /* so we delete the files first, then the directory. */
+
+#ifdef OS2
+        /* In K95, we have no mtchs array, nor any control over */
+        /* the order in which znext() returns filenames, so we  */
+        /* must copy the array and sort it. */
+        {
+            int i;
+            if (xmtchs) {               /* Free previous list in case */
+                debug(F101,"dodel freeing previous list","",xmtchn);
+                for (i = 0; i < xmtchn; i++) /* it wasn't freed last time. */
+                  if (xmtchs[i])
+                    free(xmtchs[i]);
+                free(xmtchs);
+            }
+            xmtchn = 0;
+            xmtchs = (char **)malloc(z * (sizeof(char **))); /* Make new one */
+            if (!xmtchs) {
+                printf("?Memory allocation failure\n");
+                return(-9);
+            }
+            for (i = 0; i < z; i++) {
+                xmtchs[i] = NULL;
+                znext(tmpbuf);
+                if (!*tmpbuf)
+                  break;
+                makestr(&(xmtchs[i]),tmpbuf);
+                if (!xmtchs[i]) {
+                    printf("?Memory allocation failure\n");
+                    xmtchn = i - 1;
+                    rc = -9;
+                    goto xdelete;
+                }
+                /* debug(F111,"dodel add",xmtchs[i],i); */
+            }
+            xmtchn = i;
+            debug(F101,"dodel xmtchn","",xmtchn);
+            sh_sort(xmtchs,NULL,z,0,deldirs,0);
+        }
+#else
+#ifdef UNIX
+        sh_sort(mtchs,NULL,z,0,deldirs,filecase);
+#endif /* UNIX */
+#endif /* OS2 */
+
+        if (z > 0) {
+            int i;
+#ifdef OS2
+            int ix = 0;
+#endif /* OS2 */
+            success = 1;
+            if (x_hdg > 0)
+              printf("\n");
+
+            while (
+#ifdef OS2
+                   ix < xmtchn
+#else
+                   1
+#endif /* OS2 */
+                   ) {                  /* Loop for all files */
+#ifdef OS2
+                ckstrncpy(tmpbuf,xmtchs[ix++],TMPBUFSIZ);
+#else
+                znext(tmpbuf);          /* Get next file */
+#endif /* OS2 */
+                if (!*tmpbuf) {         /* No more */
+                    if (deldirs && recursive && argisdir) {
+                        ckstrncpy(tmpbuf,safebuf,TMPBUFSIZ);
+                        argisdir = 0;   /* (only do this once) */
+                    } else
+                      break;
+                }
+                skip = 0;
+                if (!deltree) {
+                    if (fs)
+                      if (fileselect(tmpbuf,
+                                     del_aft,del_bef,del_naf,del_nbf,
+                                     minsize,maxsize,0,8,dxlist) < 1) {
+                          skip++;
+                      }
+                }
+                if (!skip && scan && itsadir) {
+                    skip++;
+                }
+                if (!skip && scan) {
+                      switch (scanfile(tmpbuf,&y,nscanfile)) {
+                      case FT_BIN:
+                        if (xmode != 1)
+                          skip++;
+                        break;
+                      case FT_TEXT:
+                      case FT_7BIT:
+                      case FT_8BIT:
+#ifdef UNICODE
+                      case FT_UTF8:
+                      case FT_UCS2:
+#endif /* UNICODE */
+                        if (xmode != 0)
+                          skip++;
+                    }
+                }
+                if (!skip && asking) {
+                    int x;
+                    ckmakmsg(line,LINBUFSIZ," Delete ",tmpbuf,"? ",NULL);
+                    x = getyesno(line,3);
+                    switch (x) {
+                      case 0: continue;           /* no */
+                      case 1: break;              /* yes */
+                      case 2: goto xdelete;       /* quit */
+                      case 3: asking = 0; break;  /* go */
+                    }
+                }
+#ifdef VMSORUNIX
+                len = zgetfs(tmpbuf);   /* Get length and accessibility */
+                itsadir = zgfs_dir;
+                if (itsadir && zgfs_link) { /* Treat links to directories */
+                    itsadir = 0;        /* as regular files */
+                    if (scan)           /* But not if /TYPE: was given */
+                      skip++;
+                }
+                if (itsadir)            /* (emulate non-Unix code) */
+                  len = -2;
+#else
+                len = zchki(tmpbuf);    /* Get accessibility */
+                if (len < 0)            /* See if it's a directory */
+                  itsadir = isdir(tmpbuf);
+#endif /* VMSORUNIX */
+
+                if (skip) {
+#ifdef COMMENT                          /* Too verbose */
+                    if (x_lis > 0) {
+                        lines++;
+                        printf(" %s (SKIPPED)\n",tmpbuf);
+#ifdef CK_TTGWSIZ
+                        if (++n > cmd_rows - 3)
+                          if (!askmore()) goto xdelete; else n = 0;
+#endif /* CK_TTGWSIZ */
+                    }
+#endif /* COMMENT */
+                    continue;
+                }
+
+                debug(F111,"DELETE len",tmpbuf,len);
+                if (simulate) {
+                    filespace += len;
+                    count++;
+                    if (x_lis > 0) {
+                        lines++;
+                        printf(" %s (SELECTED)\n",tmpbuf);
+                        if (++n > cmd_rows - 3) {
+                            int xx;
+                            xx = askmore();
+                            if (!xx) goto xdelete; else n = 0;
+                        }
+                    }
+                } else if (len >= 0 || !itsadir) { /* Regular file */
+                    zdelet(tmpbuf);                /* or symlink, etc... */
+                    if (zchki(tmpbuf) < 0) {
+                        filespace += len;
+                        count++;
+                        if (x_lis > 0) {
+                            lines++;
+                            printf(" %s (OK)\n",tmpbuf);
+                            if (++n > cmd_rows - 3)
+                              if (!askmore()) goto xdelete; else n = 0;
+                        }
+                    } else {
+                        bad++;
+                        success = 0;
+                        if (x_lis > 0) {
+                            lines++;
+                            printf(" %s (FAILED: %s)\n",tmpbuf,ck_errstr());
+                            if (++n > cmd_rows - 3)
+                              if (!askmore()) goto xdelete; else n = 0;
+                        }
+                    }
+                } else if (/* pass > 0 && */ deldirs && itsadir) {
+                    /* It's a directory */
+                    if (zrmdir(tmpbuf) > -1) { /* Only works if empty */
+                        count++;
+                        if (x_lis > 0) {
+                            lines++;
+                            printf(" %s (OK)\n",tmpbuf);
+                            if (++n > cmd_rows - 3)
+                              if (!askmore()) goto xdelete; else n = 0;
+                        }
+                    } else {
+                        success = 0;
+                        if (x_lis > 0) {
+                            lines++;
+                            printf(" %s (FAILED: %s)\n",
+                                   tmpbuf,
+                                   ck_errstr());
+                            if (++n > cmd_rows - 3)
+                              if (!askmore()) goto xdelete; else n = 0;
+                        }
+                    }
+                } else if (x_lis > 0) {
+                    lines++;
+                    if (isdir(tmpbuf))
+                      printf(" %s (FAILED: directory)\n",tmpbuf);
+                    else
+                      printf(" %s (FAILED: not a regular file)\n",tmpbuf);
+                    if (++n > cmd_rows - 3)
+                      if (!askmore()) goto xdelete; else n = 0;
+                }
+            }
+            if (x_hdg > 0) {
+                if (lines > 0)
+                  printf("\n");
+                if (++n > cmd_rows - 3)
+                  if (!askmore()) goto xdelete; else n = 0;
+                printf("%d file%s %sdeleted, %d byte%s %sfreed%s\n",
+                       count,
+                       count != 1 ? "s" : "",
+                       simulate ? "would be " : "",
+                       filespace,
+                       filespace != 1 ? "s" : "",
+                       simulate ? "would be " : "",
+                       simulate ? " (maybe)" : ""
+                       );
+            }
+            if (!x_lis && !success && !quiet) {
+                printf("?DELETE failed for %d file%s \
+(use DELETE /LIST to see details)\n",
+                       bad, bad == 1 ? "" : "s"
+                       );
+            }
+        } else if (x_lis > 0) {
+            if (errno)
+              printf("?%s: %s\n",ck_errstr(), tmpbuf);
+            else
+              printf("?Can't delete: %s\n",tmpbuf);
+        }
+    }
+#else /* OS2ORUNIX */
+#ifndef VMS                             /* Others - let the system do it. */
+    xsystem(line);
+    x = nzxpand(tmpbuf,nzxopts);
+    success = (x > 0) ? 0 : 1;
+    if (x_hdg > 0)
+      printf("%s - %sdeleted\n", tmpbuf, success ? "" : "not ");
+#else
+    if (asking)
+      printf("\n");
+    x = xsystem(line);                  /* zshcmd returns 1 for success */
+    success = (x > 0) ? 1 : 0;
+    if (x_hdg > 0 && !asking)
+      printf("%s - %sdeleted\n", tmpbuf, success ? "" : "not ");
+    concb((char)escape);
+#endif /* VMS */
+#endif /* OS2ORUNIX */
+#endif /* MAC */
+  xdelete:
+    if (g_matchdot > -1) {
+        matchdot = g_matchdot;          /* Restore these... */
+        g_matchdot = -1;
+    }
+#ifdef OS2
+    if (xmtchs) {
+        int i;
+        debug(F101,"dodel freeing list","",xmtchn);
+        for (i = 0; i < xmtchn; i++)
+          if (xmtchs[i]) free(xmtchs[i]);
+        free(xmtchs);
+        xmtchs = NULL;
+        xmtchn = 0;
+    }
+#endif /* OS2 */
+    debug(F101,"dodel result","",rc);
+    return((rc < 0) ? rc : success);
+}
+#endif /* NOFRILLS */
+
+#ifndef NOSPL                           /* The ELSE command */
+_PROTOTYP( VOID pushqcmd, (char *) );
+
+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 || tlevel > -1) { /* In macro or command file */
+            debug(F100,"doelse pushing","",0);
+#ifdef COMMENT
+            pushcmd(NULL);              /* save rest of command. */
+#else
+            /* This fixes certain obscure problems */
+            /* but breaks many other constructions that must work. */
+            pushqcmd(NULL);
+#endif /* COMMENT */
+        } 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
+doswitch() {
+    char *lp, *ap;                      /* Macro argument pointer */
+    int len = 0, x, y, pp = 0;
+    char brbuf[3];
+
+    /* Get variable name */
+
+    tmpbuf[0] = NUL;
+    brbuf[0] = '{';
+    brbuf[1] = '}';
+    brbuf[2] = NUL;
+
+    y = cmfld("Variable name","",&s,xxstring);
+    debug(F111,"doswitch cmfld",s,y);
+    if (y < 0) {
+        if (y == -3)                   /* Because brstrip() writes */
+          s = brbuf;                   /* into its argument. */
+        else
+          return(y);
+    }
+    debug(F110,"doswitch A",s,0);
+    if (!strcmp(s,"(")) {
+        pp++;
+        if ((y = cmfld("Variable name","",&s,xxstring)) < 0) {
+            if (y == -3)
+              s = brbuf;
+            else
+              return(y);
+           debug(F110,"doswitch B",s,0);
+        }
+    }
+    len = ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
+    if (tmpbuf[0] == CMDQ) {
+        if (chkvar(s) < 1) {
+            printf("?Variable name required\n");
+            return(-9);
+        }
+    }
+    if (pp > 0) {                       /* If open paren given parse closing */
+        if ((y = cmfld("Closing parenthesis","",&s,NULL)) < 0)
+          return(y);
+        if (strcmp(atmbuf,")")) {
+            printf("?Closing parenthesis required\n");
+            return(-9);
+        }
+    }
+    lp = line;
+    x = ckstrncpy(lp,"_switx ",LINBUFSIZ); /* _switx + space */
+    lp += x;
+    ap = lp;
+    debug(F010,"SWITCH a",line,0);
+
+#ifdef COMMENT
+    x = ckmakmsg(lp,LINBUFSIZ-x,tmpbuf," ",NULL,NULL); /* variable name + SP */
+#else
+    {                                   /* variable name + SP */
+        char * p = tmpbuf;
+       if (len > 0) {
+           if (tmpbuf[0] == '(' && tmpbuf[len-1] == ')') {
+               tmpbuf[len-1] = NUL;
+               p++;
+           }
+        }
+        x = ckmakmsg(lp,LINBUFSIZ-x,"{",brstrip(p),"}"," ");
+    }
+#endif /* COMMENT */
+    debug(F010,"SWITCH b",line,0);
+    lp += x;
+
+    /* Get body */
+
+    if ((y = cmtxt("series of cases","",&s,NULL)) < 0) return(y);
+    if ((y = (int)strlen(s)) < 1) return(-2);
+    if (s[0] != '{' && s[y-1] != '}') { /* Supply braces if missing */
+        ckmakmsg(tmpbuf,TMPBUFSIZ,"{ ",s," }",NULL);
+        s = tmpbuf;
+    }
+    if (litcmd(&s,&lp,(LINBUFSIZ - (lp - (char *)line) - 2)) < 0) {
+        printf("?Unbalanced braces\n");
+        return(0);
+    }
+    debug(F010,"SWITCH c",line,0);
+
+    x = mlook(mactab,"_switx",nmac);    /* Look up SWITCH macro definition */
+    if (x < 0) {                        /* Not there? */
+        addmmac("_switx",sw_def);       /* Put it back. */
+        if ((x = mlook(mactab,"_switx",nmac)) < 0) { /* Look it up again. */
+            printf("?SWITCH macro definition gone!\n"); /* Shouldn't happen. */
+            return(success = 0);
+        }
+    }
+    debug(F010,"SWITCH command",line,0); /* Execute the SWITCH macro. */
+    success = dodo(x,ap,cmdstk[cmdlvl].ccflgs | CF_IMAC);
+    debug(F101,"SWITCH status","",success);
+    return(success);
+}
+
+int
+dofor() {                               /* The FOR command. */
+    int i, fx, fy, fz;                  /* loop variables */
+    char *ap, *di;                      /* macro argument pointer */
+    int pp = 0;                         /* Paren level */
+    int mustquote = 0;
+
+    for (i = 0; i < 2; i++) {
+        if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
+            if (y == -3) {
+                printf("?Variable name required\n");
+                return(-9);
+            } else
+              return(y);
+        }
+        if (strcmp(s,"("))
+          break;
+        pp++;
+    }
+#ifdef COMMENT
+    if ((y = parsevar(s,&x,&z)) < 0)    /* Check variable. */
+      return(y);
+#else
+    if (*s == CMDQ)                     /* If loop variable starts with */
+      mustquote++;                      /* backslash, mustquote is > 0. */
+#endif /* COMMENT */
+
+    lp = line;                          /* Build a copy of the command */
+    ckstrncpy(lp,"_forx ",LINBUFSIZ);
+    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);
+    }
+    debug(F101,"dofor fx","",fx);
+    s = atmbuf;                         /* Copy the atom buffer */
+
+    if ((int)strlen(s) < 1) goto badfor;
+/*
+  In edit 192, we change the loop variables to be evaluated at loop entry,
+  not each time through the loop.  This was required in order to allow
+  \v(argc) to be used as a loop variable, or in a loop-variable expression.
+  Thus, we can't have FOR loops that modify their own exit conditions by
+  changing the final value or the increment.  The problem with \v(argc) was
+  that it is on the macro stack; after entry into the _forx macro, it is at
+  the wrong place.
+*/
+    sprintf(tmpbuf,"%d",fx);            /* (SAFE) Substitute actual value */
+    s = tmpbuf;
+    while ((*lp++ = *s++)) ;            /* (what they actually typed) */
+    lp--; *lp++ = SP;
+#ifdef DEBUG
+    *lp = NUL;
+    debug(F110,"FOR A",line,0);
+#endif /* DEBUG */
+
+    if ((y = cmnum("final value","",10,&fy,xxstring)) < 0) {
+        if (y == -3) return(-2);
+        else return(y);
+    }
+    debug(F101,"dofor fy","",fy);
+    s = atmbuf;                         /* Same deal */
+    if ((int)strlen(s) < 1)
+      goto badfor;
+
+    sprintf(tmpbuf,"%d",fy);            /* SAFE */
+    s = tmpbuf;
+    while ((*lp++ = *s++)) ;
+    lp--;
+    *lp++ = SP;
+#ifdef DEBUG
+    *lp = NUL;
+    debug(F110,"FOR B",line,0);
+#endif /* DEBUG */
+
+    x_ifnum = 1;                        /* Increment or parenthesis */
+    di = (fx < fy) ? "1" : "-1";        /* Default increment */
+    if ((y = cmnum("increment",di,10,&fz,xxstring)) < 0) {
+        debug(F111,"dofor increment",atmbuf,y);
+        x_ifnum = 0;
+        if (y == -3) {                  /* Premature termination */
+            return(-2);
+        } else if (y == -2) {           /* Maybe closing paren */
+            if (!strcmp(atmbuf,")")) {
+                pp--;                   /* Count it */
+                s = di;                 /* supply default interval */
+                fz = atoi(s);
+            } else                      /* Not closing paren, invalid */
+              return(y);
+        } else                          /* Other error */
+          return(y);
+    } else {                            /* Number */
+        x_ifnum = 0;
+        debug(F101,"dofor fz","",fz);
+        s = atmbuf;                     /* Use it */
+    }
+    if ((int)strlen(s) < 1)
+      goto badfor;
+
+    sprintf(tmpbuf,"%d",fz);            /* (SAFE) Same deal */
+    s = tmpbuf;
+    while ((*lp++ = *s++)) ;
+    lp--; *lp++ = SP;
+
+#ifdef DEBUG
+    *lp = NUL;
+    debug(F110,"FOR C",line,0);
+#endif /* DEBUG */
+
+    /* Insert the appropriate comparison operator */
+    if (fz < 0)
+      *lp++ = '<';
+    else
+      *lp++ = '>';
+    *lp++ = SP;
+
+#ifdef DEBUG
+    *lp = NUL;
+    debug(F110,"FOR D",line,0);
+#endif /* DEBUG */
+
+    if (pp > 0) {                       /* If open paren given parse closing */
+        if ((y = cmfld("Closing parenthesis","",&s,NULL)) < 0)
+          return(y);
+        if (strcmp(atmbuf,")")) {
+            printf("?Closing parenthesis required\n");
+            return(-9);
+        }
+    }
+    if ((y = cmtxt("Command to execute","",&s,NULL)) < 0) return(y);
+    if ((y = (int)strlen(s)) < 1) return(-2);
+    if (s[0] != '{' && s[y-1] != '}') { /* Supply braces if missing */
+        ckmakmsg(tmpbuf,TMPBUFSIZ,"{ ",s," }",NULL);
+        s = tmpbuf;
+    }
+    if (litcmd(&s,&lp,(LINBUFSIZ - (lp - (char *)line) - 2)) < 0) {
+        printf("?Unbalanced braces\n");
+        return(0);
+    }
+#ifdef DEBUG
+    *lp = NUL;
+    debug(F110,"FOR E",line,0);
+#endif /* DEBUG */
+
+#ifdef COMMENT
+/* Too strict */
+    if (fz == 0) {
+        printf("?Zero increment not allowed\n");
+        return(0);
+    }
+#endif /* COMMENT */
+/*
+  In version 8.0 we decided to allow macro names anyplace a numeric-valed
+  variable could appear.  But this caused trouble for the FOR loops because
+  the quoting in for_def[] assumed a \%i-style loop variable.  We account
+  for this here in the if (mustquote)...else logic by invoking separate
+  FOR macro definitions in the two cases.
+*/
+    if (mustquote) {                    /* \%i-style loop variable */
+        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");
+                return(success = 0);
+            }
+        }
+    } else {                            /* Loop variable is a macro */
+        x = mlook(mactab,"_forz",nmac);
+        if (x < 0) {
+            addmmac("_forz",foz_def);
+            if ((x = mlook(mactab,"_forz",nmac)) < 0) {
+                printf("?FOR macro definition gone!\n");
+                return(success = 0);
+            }
+        }
+    }
+    debug(F010,"FOR command",line,0);   /* Execute the FOR macro. */
+    return(success = dodo(x,ap,cmdstk[cmdlvl].ccflgs | CF_IMAC));
+
+badfor:
+    printf("?Incomplete FOR command\n");
+    return(-2);
+}
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+/* Do the BUG command */
+
+int
+dobug() {
+    int n;
+    char * s = "";
+    extern char * k_info_dir;
+
+    if (k_info_dir)
+      s = k_info_dir;
+
+#ifdef COMMENT
+    printf("\n%s,%s\n Numeric: %ld",versio,ckxsys,vernum);
+#endif /* COMMENT */
+    printf(
+"\nBefore requesting technical support from Columbia U., please consult:\n\n"
+           );
+    n = 7;
+#ifdef OS2
+    printf(" . Your \"Kermit 95\" user manual (use the MANUAL command).\n");
+    printf(" . The technical reference manual, \"Using C-Kermit\".\n");
+    n += 2;
+#else
+    printf(" . The book \"Using C-Kermit\" (type HELP for more info).\n");
+    n += 1;
+#endif /* OS2 */
+
+    printf(" . Your own organization's support staff, if any.\n");
+    printf(
+" . The comp.protocols.kermit.misc newsgroup.\n");
+    printf(
+" . The Kermit support website, http://www.columbia.edu/kermit/support.html \n"
+           );
+    printf(
+
+" . The Kermit FAQ, http://www.columbia.edu/kermit/newfaq.html \n");
+#ifdef OS2
+    printf(
+" . The Kermit 95 FAQ, http://www.columbia.edu/kermit/k95faq.html \n");
+    n++;
+#endif /* OS2 */
+
+    printf(
+" . The C-Kermit FAQ, http://www.columbia.edu/kermit/ckfaq.html \n");
+    n += 4;
+    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+    printf("\n\
+If you still need help or have a bug to report after consulting these sources,"
+           );
+    printf("\nsend e-mail to:\n\n");
+    n += 2;
+    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+    printf("  mailto:kermit-support@columbia.edu\n\n");
+    n += 1;
+    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+    printf("Or contact us by post:\n\n");
+    printf(
+"  Kermit, Columbia University, 612 W 115 Street, New York NY  10025, USA\n\n"
+           );
+    n += 1;
+    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+    printf("Or by fax at +1 (212) 662-6442.\n\n");
+    n += 1;
+    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+#ifdef COMMENT
+    printf("Telephone support is available too:\n\n");
+    n += 1;
+    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+    printf(
+    "  +1 (212) 854-5126, from anywhere, $25.00 USD per call, MC/Visa\n\n");
+    n += 1;
+    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+#endif /* COMMENT */
+#ifndef NOSHOW
+#ifndef NOFRILLS
+    printf(
+"Before reporting problems, please use the SHOW FEATURES command\n");
+    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+    printf(
+"to get detailed program version and configuration information.\n\n");
+#endif /* NOFRILLS */
+#endif /* NOSHOW */
+    return(1);
+}
+#endif /* NOFRILLS */
+
+#ifndef NOSPL
+
+/*  T O D 2 S E C  --  Convert time of day as hh:mm:ss to secs since midnite */
+/*
+  Call with a string hh:mm or hh:mm:ss.
+  Returns a 0 to 86400 on success, or a negative number on failure.
+*/
+long
+tod2sec(t) char * t; {
+    long t2;
+    long hh = 0L, mm = 0L, ss = 0L;
+
+    if (!t) t = "";
+    if (!*t)
+      return(-3L);
+    debug(F110,"tod2sec",t,0);
+
+    if (isdigit(*t))                    /* Get hours from argument */
+      hh = *t++ - '0';
+    else
+      return(-1L);
+    if (isdigit(*t))
+      hh = hh * 10 + *t++ - '0';
+#ifdef COMMENT
+    if (hh > 24L)
+      return(-1L);
+#endif /* COMMENT */
+    if (*t == ':')
+      t++;
+    else if (!*t)
+      goto xtod2sec;
+    else
+      return(-1L);
+
+    if (isdigit(*t))                    /* Minutes */
+      mm = *t++ - '0';
+    else
+      return(-1L);
+    if (isdigit(*t))
+      mm = mm * 10 + *t++ - '0';
+    if (mm > 60L)
+      return(-1L);
+    if (*t == ':')
+      t++;
+    else if (!*t)
+      goto xtod2sec;
+    else
+      return(-1L);
+
+    if (isdigit(*t))                    /* Seconds */
+      ss = *t++ - '0';
+    else
+      return(-1L);
+    if (isdigit(*t))
+      ss = ss * 10 + *t++ - '0';
+    if (ss > 60L)
+      return(-1L);
+
+    if (*t > 32)                        /* No trailing junk allowed */
+      return(-1L);
+
+  xtod2sec:
+
+    t2 = hh * 3600L + mm * 60L + ss;    /* Seconds since midnight from arg */
+    debug(F101,"tod2sec t2","",t2);
+
+    return(t2);
+}
+
+int waitinterval = 1;
+
+#ifdef OLDWAIT
+#undef OLDWAIT
+#endif /* OLDWAIT */
+
+int kbchar = NUL;
+
+int
+dopaus(cx) int cx; {
+    long zz;
+    extern int sleepcan;
+
+#ifdef OLDWAIT
+    zz = -1L;
+    x_ifnum = 1;                        /* Turn off internal complaints */
+    if (cx == XXWAI)
+      y = cmnum("seconds to wait, or time of day hh:mm:ss","1",10,&x,xxstring);
+    else if (cx == XXPAU)
+      y = cmnum("seconds to pause, or time of day hh:mm:ss",
+                "1",10,&x,xxstring);
+    else
+      y = cmnum("milliseconds to sleep, or time of day hh:mm:ss",
+                "100",10,&x,xxstring);
+    x_ifnum = 0;
+    if (y < 0) {
+        if (y == -2) {                  /* Invalid number or expression */
+            char *p = tmpbuf;           /* Retrieve string from atmbuf */
+            int n = TMPBUFSIZ;
+            *p = NUL;
+            zzstring(atmbuf,&p,&n);     /* Evaluate in case it's a variable */
+            zz = tod2sec(tmpbuf);       /* Convert to secs since midnight */
+            if (zz < 0L) {
+                printf("?Number, expression, or time of day required\n");
+                return(-9);
+            } else {
+                char now[32];           /* Current time */
+                char *p;
+                long tnow;
+                p = now;
+                ztime(&p);
+                tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
+                if (zz < tnow)          /* User's time before now */
+                  zz += 86400L;         /* So make it tomorrow */
+                zz -= tnow;             /* Seconds from now. */
+            }
+        } else
+          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 */
+        }
+        if ((y = cmcfm()) < 0) return(y);
+        break;
+
+      default:                          /* Shouldn't happen */
+        return(-2);
+    }
+
+/* Command is entered, now do it. */
+
+    if (zz > -1L) {                     /* Time of day given? */
+        x = zz;
+        if (zz != (long) x) {
+            printf(
+"Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
+                   );
+            return(-9);
+        }
+    }
+    if (cx == XXMSL) {                  /* Millisecond sleep */
+        msleep(zz < 0 ? x : x * 1000);
+        return(success = 1);
+    }
+    if (cx == XXPAU && !sleepcan) {     /* SLEEP CANCELLATION is OFF */
+        sleep(x);
+        return(success = 1);
+    }
+
+    /* WAIT, or else SLEEP with cancellation allowed... */
+
+    do {                                /* Sleep loop */
+        int mdmsig;
+        if (sleepcan) {                 /* Keyboard cancellation allowed? */
+            if (y = conchk()) {         /* Did they type something? */
+#ifdef COMMENT
+                while (y--) coninc(0);  /* Yes, gobble it all up */
+#else
+                /* There is a debate over whether PAUSE should absorb    */
+                /* its cancelling character(s).  There are several       */
+                /* reasons why it should gobble at least one character:  */
+                /* (1) MS-DOS Kermit does it                             */
+                /* (2) if not, subsequent PAUSE commands will terminate  */
+                /*     immediately                                       */
+                /* (3) if not, subsequent ASK commands will use it as    */
+                /*     valid input.  If \13, then it will get no input   */
+                /* (4) if not, then the character appears on the command */
+                /*     line after all enclosing macros are complete.     */
+                kbchar = coninc(0);     /* Gobble one up */
+#endif /* COMMENT */
+                break;                  /* And quit PAUSing or WAITing */
+            }
+        }
+        if (cx == XXWAI) {              /* WAIT (z == modem signal mask) */
+            debug(F101,"WAIT x","",x);
+            if (z > 0) {                /* Looking for any modem signals? */
+                mdmsig = ttgmdm();      /* Yes, get them */
+                if (mdmsig < 0)         /* Failed */
+                  return(success = 0);
+                if ((mdmsig & z) == z)  /* Got what we wanted? */
+                  return(success = 1);  /* Succeed */
+            }
+            if (x == 0)                 /* WAIT 0 and didn't get our signals */
+              break;
+        }
+        sleep(1);                       /* No interrupt, sleep one second */
+    } while (--x > 0);
+
+    if (cx == XXWAI)                    /* If WAIT and loop exhausted */
+      success = (z == 0);               /* Fail. */
+    else                                /*  */
+      success = (x == 0);               /* Set SUCCESS/FAILURE for PAUSE. */
+    return(success);
+
+#else  /* New code uses chained FDBs and allows FILE waits... */
+
+    char * m = "";                      /* Help message */
+    struct FDB nu, fl;                  /* Parse function descriptor blocks */
+    int filewait = 0;
+    int mdmsig = 0, fs = 0;
+    char filedate[32];
+
+    kbchar = 0;
+
+    switch (cx) {
+      case XXWAI: m = "seconds to wait, or time of day hh:mm:ss"; break;
+      case XXPAU: m = "seconds to pause, or time of day hh:mm:ss"; break;
+      case XXMSL: m = "milliseconds to sleep, or time of day hh:mm:ss"; break;
+    }
+    zz = -1L;
+    cmfdbi(&nu,
+           _CMNUM,                      /* Number */
+           m,                           /* Help message */
+           (cx == XXMSL) ? "100" : "1", /* Default */
+           "",                          /* N/A */
+           0,                           /* N/A */
+           0,                           /* N/A */
+           xxstring,                    /* Processing function */
+           NULL,                        /* N/A */
+           &fl                          /* Next */
+           );
+    cmfdbi(&fl,                         /* Time of day */
+           _CMFLD,                      /* Field */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,                    /* processing func */
+           NULL,                        /* N/A */
+           NULL                         /* No next */
+           );
+    x = cmfdb(&nu);                     /* Parse a number or a field */
+    if (x < 0) {
+        if (x == -3)
+          x = -2;
+        return(x);
+    }
+    switch (cmresult.fcode) {
+      case _CMNUM:                      /* Number */
+        x = cmresult.nresult;
+        break;
+      case _CMFLD:                      /* Field */
+        zz = tod2sec(cmresult.sresult); /* Convert to secs since midnight */
+        if (zz < 0L) {
+            printf("?Number, expression, or time of day required\n");
+            return(-9);
+        } else {
+            char now[32];               /* Current time */
+            char *p;
+            long tnow;
+            p = now;
+            ztime(&p);
+            tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
+            if (zz < tnow)              /* User's time before now */
+              zz += 86400L;             /* So make it tomorrow */
+            zz -= tnow;         /* Seconds from now. */
+        }
+    }
+    debug(F101,"PAUSE/WAIT/MSLEEP zz","",zz);
+    switch (cx) {
+      case XXPAU:                       /* PAUSE */
+      case XXMSL:                       /* MSLEEP */
+        if ((y = cmcfm()) < 0) return(y);
+        break;
+      case XXWAI:                       /* WAIT */
+        z = 0;                          /* Modem signal mask */
+        y = cmkey(waittab,nwaittab,"","",xxstring);
+        if (y < 0) {
+            if (y == -3) {
+                if ((y = cmcfm()) < 0)
+                  return(y);
+                break;
+            } else
+              return(y);
+        }
+        if (y == WAIT_FIL) {            /* FILE */
+            int wild = 0;
+            if ((z = cmkey(wfswi,nwfswi,"event","",xxstring)) < 0)
+              return(z);
+            filewait = z;
+            if (filewait == WF_MOD || filewait == WF_DEL)
+              z = cmifi("Filename","",&s,&wild,xxstring);
+            else
+              z = cmfld("Filename","",&s,xxstring);
+            if (z < 0)
+              return(z);
+            if (wild || ((filewait == WF_CRE) && iswild(s))) {
+                printf("?Wildcards not valid here\n");
+                return(-9);
+            }
+            ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+            if ((z = cmcfm()) < 0)
+              return(z);
+            break;
+        } else if (y != WAIT_MDM) {     /* A modem signal */
+            z |= y;                     /* OR the bit into the signal mask */
+        }
+        if (!filewait) {                /* Modem signals... */
+            while (1) {                 /* Get 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 */
+            }
+            if ((y = cmcfm()) < 0) return(y);
+            break;
+        }
+
+      default:                          /* Shouldn't happen */
+        return(-2);
+    } /* switch (cx) */
+
+/* Command is entered, now do it. */
+
+    if (zz > -1L) {                     /* Time of day given? */
+        x = zz;
+        if (zz != (long) x) {
+            printf(
+"Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
+                   );
+            return(-9);
+        }
+    }
+    if (sleepcan)
+      concb((char)escape);              /* Ensure single-char wakeup */
+
+    if (cx == XXMSL) {                  /* Millisecond sleep */
+        msleep(zz < 0 ? x : x * 1000);
+        return(success = 1);
+    }
+    if (cx == XXPAU && !sleepcan) {     /* SLEEP CANCELLATION is OFF */
+        sleep(x);
+        return(success = 1);
+    }
+    if (filewait) {                     /* FILE... */
+        fs = zchki(tmpbuf);             /* Check if file exists */
+        switch (filewait) {
+          case WF_DEL:
+            if (fs == -1)
+              return(success = 1);
+            break;
+          case WF_MOD:
+            if (fs == -1) {
+                printf("?File does not exit: %s\n",tmpbuf);
+                return(-9);
+            }
+            s = zfcdat(tmpbuf);         /* Get current modification date */
+            if (!s) s = "";
+            if (ckstrncpy(filedate,s,32) != 17) {
+                printf("?Can't get modification time: %s\n",tmpbuf);
+                return(-9);
+            }
+            break;
+          case WF_CRE:
+            if (fs > -1)
+              return(success = 1);
+            break;
+        }
+    }
+    do {                                /* Polling loop */
+        if (sleepcan) {                 /* Keyboard cancellation allowed? */
+            if ((y = conchk()) > 0) {   /* Did they type something? */
+                kbchar = coninc(0);     /* Yes, get first char they typed */
+                debug(F000,"WAIT kbchar","",kbchar);
+#ifdef COMMENT
+                while (--y > 0)         /* Gobble the rest up */
+                  coninc(0);
+#endif /* COMMENT */
+                return(success = 0);    /* And quit PAUSing or WAITing */
+            }
+        }
+        if (filewait == 0) {
+            if (cx == XXWAI) {          /* WAIT for modem signals */
+                if (z != 0) {
+                    mdmsig = ttgmdm();  /* Get them. */
+                    debug(F101,"WAIT ttgmdm","",mdmsig);
+                    if (mdmsig < 0)     /* Failure to get them? */
+                      return(success = 0); /* Fail. */
+                    if ((mdmsig & z) == z) /* Got desired ones? */
+                      return(success = 1); /* Succeed. */
+                } else if (x == 0)
+                  return(success = 0);
+            }
+        } else {                        /* FILE... */
+            fs = zchki(tmpbuf);         /* Get file status */
+            if (filewait == WF_MOD) {   /* Wait for modification */
+                if (fs == -1)           /* Failure to get status */
+                  return(success = 0);  /* so WAIT fails. */
+                s = zfcdat(tmpbuf);     /* Get current modification time */
+                if (!s) s = "";         /* And compare with the time */
+                if (strcmp(s,filedate)) /* when the WAIT started */
+                  return(success = 1);
+            } else if (filewait == WF_DEL) { /* Wait for deletion */
+                if (fs == -1)           /* If file doesn't exist, */
+                  return(success = 1);  /* succeed. */
+            } else if (filewait == WF_CRE) { /* Wait for creation */
+                if (fs != -1)           /* If file exists */
+                  return(success = 1);  /* succeed. */
+            }
+        }
+        if (x < 1)                      /* SLEEP/WAIT/PAUSE 0 */
+          break;
+        sleep(waitinterval);            /* No interrupt, sleep */
+        x -= waitinterval;              /* Deduct sleep time */
+    } while (x > 0);
+
+    if (cx == XXWAI)                    /* WAIT time expired */
+      success = (z == 0);               /* Succeed if no modem signals */
+    else                                /* For SLEEP or PAUSE, success */
+      success = (x == 0);               /* depends on whether it was */
+    return(success);                    /* interrupted from the keyboard. */
+#endif /* OLDWAIT */
+}
+#endif /* NOSPL */
+
+#ifdef OS2ORUNIX
+_PROTOTYP(int zcmpfn,(char *, char *));
+#endif /* OS2ORUNIX */
+
+#ifndef NOFRILLS
+#ifdef NT
+int 
+dolink() {
+    /* Parse a file or a directory name */
+    int i, x, z, listing = 0, havename = 0, wild = 0, rc = 1;
+    struct FDB sw, fi;
+
+    cmfdbi(&sw,                         /* 2nd FDB - optional /PAGE switch */
+           _CMKEY,                      /* fcode */
+           "Filename or switch",        /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           nqvswtab,                    /* addtl numeric data 1: tbl size */
+           4,                           /* addtl numeric data 2: 4 = cmswi */
+           xxstring,                    /* Processing function */
+           qvswtab,                     /* Keyword table */
+           &fi                          /* Pointer to next FDB */
+           );
+
+    cmfdbi(&fi,                         /* 1st FDB - file to type */
+           _CMIFI,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           3,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,
+           NULL,
+           NULL
+           );
+
+    while (!havename) {
+        x = cmfdb(&sw);                 /* Parse something */
+        if (x < 0)                      /* Error */
+          return(x);
+        switch (cmresult.fcode) {
+          case _CMKEY:
+            switch (cmresult.nresult) {
+              case DEL_LIS:
+              case DEL_VRB:
+                listing = 1;
+                break;
+              case DEL_NOL:
+              case DEL_QUI:
+                listing = 0;
+                break;
+            }
+            break;
+          case _CMIFI:
+            s = cmresult.sresult;
+            havename = 1;
+            break;
+          default:
+            return(-2);
+        }
+    }
+    wild = cmresult.nresult;            /* Source specification wild? */
+
+    ckstrncpy(line,s,LINBUFSIZ);        /* Make a safe copy of source name */
+    s = line;
+
+    if (!wild)
+      wild = iswild(line);
+
+    p = tmpbuf;                         /* Place for new name */
+    if ((x = cmofi(wild ? "Target directory" : "New name",
+                   "",&s,xxstring)) < 0) { /* Get new name */
+        if (x == -3) {
+            printf("?%s required\n", wild ? "Target directory" : "New name");
+            return(-9);
+        } else return(x);
+    }
+    ckstrncpy(p,s,TMPBUFSIZ);           /* Make a safe copy of the new name */
+    if ((y = cmcfm()) < 0) return(y);
+
+    if (!wild) {                        /* Just one */
+        if (listing) printf("%s => %s ",line,p);
+        if (zlink(line,p) < 0) {
+            if (listing) printf("(FAILED: %s\n",ck_errstr());
+            rc = 0;
+        } else {
+            if (listing) printf("(OK)\n");
+        }
+        return(success = rc);
+    }
+    if (!isdir(p)) {                    /* Multiple */
+        printf(                         /* if target is not a directory */
+"?Multiple source files not allowed if target is not a directory.\n");
+        return(-9);
+    }
+#ifdef COMMENT
+    else {                              /* Show full path of target */
+        char buf[CKMAXPATH];            /* (too much) */
+        if (zfnqfp(p,CKMAXPATH,buf))
+          ckstrncpy(tmpbuf,buf,TMPBUFSIZ);
+    }
+#endif /* COMMENT */
+
+#ifdef VMS
+    conres();                           /* Let Ctrl-C work. */
+#endif /* VMS */
+    debug(F110,"dolink line",line,0);
+
+#ifdef ZXREWIND
+    z = zxrewind();                     /* Rewind file list */
+#else
+    z = nzxpand(s,0);                   /* Expand file list */
+#endif /* ZXREWIND */
+    debug(F111,"dolink p",p,z);
+
+#ifdef UNIX
+    if (wild && z > 1)
+      sh_sort(mtchs,NULL,z,0,0,filecase); /* Alphabetize the filename list */
+#endif /* UNIX */
+
+    while (z-- > 0) {
+        if (!(z == 0 && !wild))
+          znext(line);
+        if (!line[0])
+          break;
+        if (listing) printf("%s => %s ",line,p);
+        if (zlink(line,p) < 0) {
+            if (listing) printf("(FAILED: %s\n",ck_errstr());
+            rc = 0;
+        } else {
+            if (listing) printf("(OK)\n");
+        }
+    }
+#ifdef VMS
+    concb((char)escape);
+#endif /* VMS */
+    return(success = rc);
+}
+#endif /* NT */
+
+#ifdef ZCOPY
+int
+docopy() {
+    int i, x, listing = 0, nolist = 0, havename = 0;
+    struct FDB sw, fi;
+    int targetisdir = 0;
+    int targetlen = 0;
+    int swapping = 0;
+    int appending = 0;
+    int fromb64 = 0;
+    int tob64 = 0;
+    int wild = 0;
+    int rc = 1;
+
+    cmfdbi(&sw,                         /* 2nd FDB - optional /PAGE switch */
+           _CMKEY,                      /* fcode */
+           "Filename or switch",        /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           ncopytab,                    /* addtl numeric data 1: tbl size */
+           4,                           /* addtl numeric data 2: 4 = cmswi */
+           xxstring,                    /* Processing function */
+           copytab,                     /* Keyword table */
+           &fi                          /* Pointer to next FDB */
+           );
+    cmfdbi(&fi,                         /* 1st FDB - file to type */
+           _CMIFI,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,
+           NULL,
+           NULL
+           );
+
+    while (!havename) {
+        x = cmfdb(&sw);                 /* Parse something */
+        if (x < 0)                      /* Error */
+          return(x);
+        switch (cmresult.fcode) {
+          case _CMKEY:
+            switch (cmresult.nresult) {
+              case DEL_LIS:
+              case DEL_VRB:
+               nolist = 0;
+                listing = 1;
+                break;
+              case DEL_NOL:
+              case DEL_QUI:
+               nolist = 1;
+                listing = 0;
+                break;
+              case 999:
+                swapping = 1;
+                break;
+              case 998:
+                appending = 1;
+                break;
+#ifndef NOSPL
+              case 997:
+                fromb64 = 1;
+                break;
+              case 996:
+                tob64 = 1;
+                break;
+#endif /* NOSPL */
+            }
+            break;
+          case _CMIFI:
+            s = cmresult.sresult;
+            havename = 1;
+            break;
+          default:
+            return(-2);
+        }
+    }
+    wild = cmresult.nresult;
+    ckstrncpy(line,s,LINBUFSIZ);        /* Make a safe copy of source name */
+    s = line;
+    p = tmpbuf;                         /* Place for new name */
+
+    /* Get destination name */
+    if ((x = cmofi("destination name and/or directory",
+#ifdef UNIX
+                   "."
+#else
+                   ""
+#endif /* UNIX */
+                   ,&s,xxstring)) < 0) {
+        if (x == -3) {
+            printf("?Name for destination file required\n");
+            return(-9);
+        } else return(x);
+    }
+    ckstrncpy(p,s,TMPBUFSIZ);           /* Safe copy of destination name */
+    if ((y = cmcfm()) < 0) return(y);
+    if (appending && swapping) {
+        printf("?Sorry, /APPEND and /SWAP conflict\n");
+        return(-9);
+    }
+#ifdef COMMENT
+/*
+  This unreasonably prevented "COPY /APPEND *.* bifile" from concatenating
+  a bunch of files into one big file.
+*/
+    if (appending && wild) {
+        printf("?Sorry, /APPEND can be used only with single files\n");
+        return(-9);
+    }
+#endif /* COMMENT */
+    targetisdir = isdir(p);
+    x = strlen(p);
+    if (targetisdir) {
+#ifdef UNIXOROSK
+        if (p[x-1] != '/') {
+            ckstrncat(p,"/",TMPBUFSIZ);
+            x++;
+        }
+#else
+#ifdef OS2
+        if (p[x-1] != '/') {
+            ckstrncat(p,"/",TMPBUFSIZ);
+            x++;
+        }
+#else
+#ifdef STRATUS
+        if (p[x-1] != '>') {
+            ckstrncat(p,">",TMPBUFSIZ);
+            x++;
+        }
+#else
+#ifdef datageneral
+        if (p[x-1] != ':') {
+            ckstrncat(p,":",TMPBUFSIZ);
+            x++;
+        }
+#else
+        if (p[x-1] != '/') {
+            ckstrncat(p,"/",TMPBUFSIZ);
+            x++;
+        }
+#endif /* datageneral */
+#endif /* STRATUS */
+#endif /* OS2 */
+#endif /* UNIXOROSK */
+    }
+    targetlen = x;
+
+    if (!appending) {                  /* If /APPEND not given */
+       if (wild && !targetisdir) {     /* No wildcards allowed */
+           printf(                     /* if target is not a directory */
+"?Multiple source files not allowed if target is not a directory.\n");
+           return(-9);
+       }
+    }
+
+#ifdef VMS
+    conres();                           /* Let Ctrl-C work. */
+#endif /* VMS */
+    debug(F110,"docopy line",line,0);
+    debug(F110,"docopy p",p,0);
+
+#ifdef ZXREWIND
+    z = zxrewind();                     /* Rewind file list */
+#else
+    z = nzxpand(s,0);                   /* Expand file list */
+#endif /* ZXREWIND */
+
+#ifdef UNIX
+    if (wild)
+      sh_sort(mtchs,NULL,z,0,0,filecase); /* Alphabetize the filename list */
+#endif /* UNIX */
+
+#ifdef IKSD
+    if (!targetisdir && zchki(p) > -1) { /* Destination file exists? */
+        if (inserver && (!ENABLED(en_del)
+#ifdef CK_LOGIN
+                         || isguest
+#endif /* CK_LOGIN */
+                         )) {
+            printf("?Sorry, overwriting existing files is disabled\n");
+            return(-9);
+        }
+    }
+#endif /* IKSD */
+
+    if (tob64 && fromb64) {             /* To and from B64 = no conversion */
+        tob64 = 0;
+        fromb64 = 0;
+    }
+    debug(F110,"COPY dest",p,0);
+
+    while (z > 0) {
+
+        znext(line);
+        if (!line[0])
+          break;
+
+        errno = 0;                      /* Reset errno */
+
+        if (listing) printf("%s => %s ",line,p);
+
+        /* Straight copy */
+        if (!swapping && !appending && !fromb64 && !tob64) {
+            debug(F110,"COPY zcopy",line,0);
+
+            if ((x = zcopy(line,p)) < 0) { /* Let zcopy() do it. */
+                switch (x) {
+                  case -2:
+                   if (listing)
+                     printf("(FAILED: Not a regular file)\n");
+                   else if (!nolist)
+                     printf("?Not a regular file - %s\n",line);
+                    rc = 0;
+                    break;
+                  case -3:
+                   if (listing)
+                     printf("(FAILED: Not found or not accessible)\n");
+                   else if (!nolist)
+                     printf("?Not found or not accessible - %s\n",line);
+                    rc = 0;
+                    break;
+                  case -4:
+                   if (listing)
+                     printf("(FAILED: Permission denied)\n");
+                   else if (!nolist)
+                     printf("?Permission denied - %s\n",line);
+                    rc = 0;
+                    break;
+                  case -5:
+                   if (listing)
+                     printf("(Source and destination are the same file)\n");
+                   else if (!nolist)
+                     printf(
+                         "?Source and destination are the same file - %s\n",
+                         line
+                         );
+                    break;
+                  case -6:
+                   if (listing)
+                     printf("(FAILED: Input/Output error)\n");
+                   else if (!nolist)
+                     printf("?Input/Output error - %s\n",line);
+                    rc = 0;
+                    break;
+                  case -7:
+                   if (listing)
+                     printf("(FAILED: %s - %s)\n",p,ck_errstr());
+                   else if (!nolist)
+                     printf("?%s - %s\n",ck_errstr(),p);
+                    rc = 0;
+                    break;
+                  default:
+                   if (listing)
+                     printf("(FAILED: %s)\n",ck_errstr());
+                   else if (!nolist)
+                     printf("?%s\n",ck_errstr());
+                    rc = 0;
+                }
+            } else {
+                if (listing) printf("(OK)\n");
+            }
+
+        } else {                        /* Special options */
+
+            int prev, y, x = 0;         /* Variables needed for them */
+            int i, t;
+            char ibuf[100];
+            char obuf[200];
+            FILE * in = NULL;
+            FILE * out = NULL;
+
+            if ((in = fopen(line,"r")) == NULL) { /* Open input file */
+                if (listing)
+                 printf("(FAILED: %s)\n",ck_errstr());
+               else if (!nolist)
+                 printf("?%s - %s)\n",ck_errstr(),line);
+                rc = 0;
+                continue;
+            }
+            if (targetisdir) {          /* Target is directory */
+                char * buf = NULL;      /* so append this filename to it */
+                zstrip(line,&buf);
+                p[targetlen] = NUL;
+                if (buf)
+                  ckstrncat(p,buf,TMPBUFSIZ);
+            }
+#ifdef OS2ORUNIX
+            if (zcmpfn(line,p)) {       /* Input and output are same file? */
+                if (listing)
+                  printf("(FAILED: Source and destination identical)\n");
+               else if (!nolist)
+                  printf("?Source and destination identical - %s\n", line); 
+                rc = 0;
+                continue;
+            }
+#endif /* OS2ORUNIX */
+            if ((out = fopen(p, (appending ? "a" : "w"))) == NULL) {
+                fclose(in);
+                if (listing)
+                 printf("(FAILED: %s - %s)\n",p,ck_errstr());
+               else if (!nolist)
+                 printf("?%s - %s\n",p,ck_errstr());
+                rc = 0;
+                continue;
+            }
+#ifndef NOSPL
+            if (tob64) {                /* Converting to Base-64 */
+
+                debug(F110,"COPY tob64",line,0);
+
+                while (1) {             /* Loop... */
+                    prev = x;
+                    if ((x = fread(ibuf,1,54,in)) < 1) { /* EOF */
+                        if (listing)
+                          printf("(OK)\n");
+                        break;
+                    }
+                    if (prev % 3) {
+                        if (listing)
+                          printf("(FAILED: Phase error at %d)\n",prev);
+                       else if (!nolist)
+                          printf("?Phase error at %d\n",prev);
+                        rc = 0;
+                        break;
+                    }
+                    if (swapping) {
+                        if (x & 1) {
+                            if (listing)
+                              printf("(FAILED: Swap error)\n");
+                           else if (!nolist)
+                             printf("?Swap error\n");
+                            rc = 0;
+                            break;
+                        }
+                        for (i = 0; i < x; i+=2) {
+                            t = ibuf[i];
+                            ibuf[i] = ibuf[i+1];
+                            ibuf[i+1] = t;
+                        }
+                    }
+                    if ((y = b8tob64(ibuf,x,obuf,180)) < 0) {
+                        if (listing)
+                          printf("(FAILED: Encoding error)\n");
+                       else if (!nolist)
+                         printf("?Encoding error\n");
+                        rc = 0;
+                        break;
+                    }
+                    fprintf(out,"%s\n",obuf);
+                }
+
+            } else if (fromb64) {       /* Converting from Base 64 */
+
+                debug(F110,"COPY fromb64",line,0);
+
+                if ((out = fopen(p,appending ? "a" : "w")) == NULL) {
+                    fclose(in);
+                    if (listing)
+                     printf("(FAILED: %s - %s)\n",p,ck_errstr());
+                   else if (!nolist)
+                     printf("?%s - %s\n",p,ck_errstr());
+                    rc = 0;
+                    continue;
+                }
+                x = 1;
+                while (x) {
+                    x = fread(ibuf,1,80,in);
+                    if ((y = b64tob8(ibuf,x,obuf,80)) < 0) {
+                        if (listing)
+                          printf("(FAILED: Decoding error)\n");
+                       else if (!nolist)
+                         printf("?Decoding error\n");
+                        rc = 0;
+                        break;
+                    }
+                    if (swapping) {
+                        if (x & 1) {
+                            if (listing)
+                              printf("(FAILED: Swap error)\n");
+                           else if (!nolist)
+                             printf("?Swap error\n");
+                            rc = 0;
+                            break;
+                        }
+                        for (i = 0; i < y; i+=2) {
+                            t = obuf[i];
+                            obuf[i] = obuf[i+1];
+                            obuf[i+1] = t;
+                        }
+                    }
+                    if (y > 0) {
+                        if (fwrite(obuf,1,y,out) < 1) {
+                            if (listing)
+                              printf("(FAILED: %s - %s)\n",p,ck_errstr());
+                           else if (!nolist)
+                             printf("?%s - %s\n",p,ck_errstr());
+                            rc = 0;
+                            break;
+                        }
+                    }
+                }
+
+            } else
+#endif /* NOSPL */
+
+            if (swapping) {             /* Swapping bytes */
+
+                CHAR c[3];
+                c[2] = NUL;
+
+                debug(F110,"COPY swapping",line,0);
+
+                while (1) {
+                    x = fread((char *)c,1,2,in);
+                    if (x < 1) {
+                        if (listing)
+                          printf("(OK)\n");
+                        break;
+                    } else if (x == 1) {
+                        c[1] = c[0];
+                        c[0] = NUL;
+                        printf(
+                            "(WARNING: Odd byte count)");
+                        if (!listing) printf("\n");
+                    }
+                    if (fprintf(out,"%c%c",c[1],c[0]) == EOF) {
+                        if (listing)
+                          printf("(FAILED: %s - %s)\n",p,ck_errstr());
+                       else if (!nolist)
+                          printf("?%s - %s\n",p,ck_errstr());
+                        rc = 0;
+                        break;
+                    }
+                }
+
+            } else if (appending) {     /* Appending to target file */
+
+                char c;
+
+                debug(F110,"COPY appending",line,0);
+
+                while (1) {
+                    x = fread(&c,1,1,in);
+                    if (x < 1) {
+                        if (listing)
+                          printf("(OK)\n");
+                        break;
+                    }
+                    if (fwrite(&c,1,1,out) < 1) {
+                        if (listing)
+                          printf("(FAILED: %s - %s)\n",p,ck_errstr());
+                       else if (!nolist)
+                          printf("?%s - %s\n",p,ck_errstr());
+                        rc = 0;
+                        break;
+                    }
+                }
+            }
+            if (out) fclose(out);
+            if (in) fclose(in);
+        }
+#ifdef VMSORUNIX
+        concb((char)escape);
+#endif /* VMSORUNIX */
+    }
+    if (rc > -1) success = rc;
+    return(rc);
+}
+#endif /* ZCOPY */
+#endif /* NOFRILLS */
+
+#ifndef NORENAME
+#ifndef NOFRILLS
+#ifdef ZRENAME
+int
+dorenam() {
+    /* Parse a file or a directory name */
+    int i, x, z, listing = 0, havename = 0, wild = 0, rc = 1;
+    int nolist = 0;
+    struct FDB sw, fi;
+
+    cmfdbi(&sw,                         /* 2nd FDB - optional /PAGE switch */
+           _CMKEY,                      /* fcode */
+           "Filename or switch",        /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           nqvswtab,                    /* addtl numeric data 1: tbl size */
+           4,                           /* addtl numeric data 2: 4 = cmswi */
+           xxstring,                    /* Processing function */
+           qvswtab,                     /* Keyword table */
+           &fi                          /* Pointer to next FDB */
+           );
+
+    cmfdbi(&fi,                         /* 1st FDB - file to type */
+           _CMIFI,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           3,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,
+           NULL,
+           NULL
+           );
+
+    while (!havename) {
+        x = cmfdb(&sw);                 /* Parse something */
+        if (x < 0)                      /* Error */
+          return(x);
+        switch (cmresult.fcode) {
+          case _CMKEY:
+            switch (cmresult.nresult) {
+              case DEL_LIS:
+              case DEL_VRB:
+                listing = 1;
+                break;
+              case DEL_NOL:
+              case DEL_QUI:
+               nolist = 1;
+                listing = 0;
+                break;
+            }
+            break;
+          case _CMIFI:
+            s = cmresult.sresult;
+            havename = 1;
+            break;
+          default:
+            return(-2);
+        }
+    }
+    wild = cmresult.nresult;            /* Source specification wild? */
+
+    ckstrncpy(line,s,LINBUFSIZ);        /* Make a safe copy of source name */
+    s = line;
+
+    if (!wild)
+      wild = iswild(line);
+
+    p = tmpbuf;                         /* Place for new name */
+    if ((x = cmofi(wild ? "Target directory" : "New name",
+                   "",&s,xxstring)) < 0) { /* Get new name */
+        if (x == -3) {
+            printf("?%s required\n", wild ? "Target directory" : "New name");
+            return(-9);
+        } else return(x);
+    }
+    ckstrncpy(p,s,TMPBUFSIZ);           /* Make a safe copy of the new name */
+    if ((y = cmcfm()) < 0) return(y);
+
+    if (!wild) {                        /* Just one */
+        if (listing) printf("%s => %s ",line,p);
+        if (zrename(line,p) < 0) {
+            if (listing)
+             printf("(FAILED: %s)\n",ck_errstr());
+           else if (!nolist)
+             printf("?%s\n",ck_errstr());
+            rc = 0;
+        } else {
+            if (listing) printf("(OK)\n");
+        }
+        return(success = rc);
+    }
+    if (!isdir(p)) {                    /* Multiple */
+        printf(                         /* if target is not a directory */
+"?Multiple source files not allowed if target is not a directory.\n");
+        return(-9);
+    }
+#ifdef COMMENT
+    else {                              /* Show full path of target */
+        char buf[CKMAXPATH];            /* (too much) */
+        if (zfnqfp(p,CKMAXPATH,buf))
+          ckstrncpy(tmpbuf,buf,TMPBUFSIZ);
+    }
+#endif /* COMMENT */
+
+#ifdef VMS
+    conres();                           /* Let Ctrl-C work. */
+#endif /* VMS */
+    debug(F110,"dorename line",line,0);
+
+#ifdef ZXREWIND
+    z = zxrewind();                     /* Rewind file list */
+#else
+    z = nzxpand(s,0);                   /* Expand file list */
+#endif /* ZXREWIND */
+    debug(F111,"dorename p",p,z);
+
+#ifdef UNIX
+    if (wild && z > 1)
+      sh_sort(mtchs,NULL,z,0,0,filecase); /* Alphabetize the filename list */
+#endif /* UNIX */
+
+/*
+  Note: COPY, RENAME, DELETE and similar commands should have options to
+  stop or proceed when they are operating on multiple files and the operation
+  fails.
+*/
+    while (z-- > 0) {
+        if (!(z == 0 && !wild))
+          znext(line);
+        if (!line[0])
+          break;
+        if (listing) printf("%s => %s ",line,p);
+        if (zrename(line,p) < 0) {
+            if (listing)
+             printf("(FAILED: %s)\n",ck_errstr());
+           else if (!nolist)
+             printf("?%s - %s\n",ck_errstr(),line);
+            rc = 0;
+        } else {
+            if (listing) printf("(OK)\n");
+        }
+    }
+#ifdef VMS
+    concb((char)escape);
+#endif /* VMS */
+    return(success = rc);
+}
+#endif /* ZRENAME */
+#endif /* NOFRILLS */
+#endif /* NORENAME */
+
+#ifndef NOSPL
+
+/* Do the RETURN command */
+
+int
+doreturn(s) char *s; {
+    int x;
+    extern int tra_asg;
+    char * line, * lp;
+
+    if (cmdlvl < 1) {
+        printf("\n?Can't return from level %d\n",maclvl);
+        return(success = 0);
+    }
+    line = malloc(LINBUFSIZ);
+    if (line == NULL)
+      return(success = 0);
+    lp = line;                          /* Expand return value now */
+    x = LINBUFSIZ-1;
+    if (!s) s = "";
+    debug(F110,"RETURN s",s,0);
+    if (zzstring(s,&lp,&x) > -1) {
+        s = line;
+        debug(F110,"RETURN zzstring",s,0);
+    }
+
+    /* Pop from all FOR/WHILE/SWITCH/XIFs */
+    while ((maclvl > 0) &&
+           (m_arg[maclvl-1][0]) &&
+           (cmdstk[cmdlvl].src == CMD_MD) &&
+           (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
+            !strncmp(m_arg[maclvl-1][0],"_for",4) ||
+            !strncmp(m_arg[maclvl-1][0],"_swi",4) ||
+            !strncmp(m_arg[maclvl-1][0],"_whi",4))) {
+        debug(F111,"RETURN IF/FOR/WHI/SWI pop",m_arg[maclvl-1][0],maclvl);
+        dogta(XXPTA);                   /* Put args back */
+        popclvl();                      /* Pop up two levels */
+        popclvl();
+    }
+    if (tra_asg) {                      /* If tracing show return value */
+        if (*s)
+          printf("<<< %s: \"%s\"\n", m_arg[maclvl][0], s);
+        else
+          printf("<<< %s: (null)\n", m_arg[maclvl][0]);
+    }
+    popclvl();                          /* Pop from enclosing TAKE or macro */
+    debug(F111,"RETURN tolevel",s,maclvl);
+    if (!s) s = "";
+    if (!*s) s = NULL;
+    makestr(&(mrval[maclvl+1]),s);      /* Set the RETURN value */
+    free(line);
+    return(success = 1);                /* Macro succeeds if we RETURN */
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+/* Do the OPEN command */
+
+int
+doopen()  {                             /* OPEN { append, read, write } */
+    int x, y, z = 0; 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 OPN_FI_R:                    /* 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);
+        }
+        ckstrncpy(line,s,LINBUFSIZ);
+        if ((int)strlen(line) < 1) return(-2);
+        if ((z = cmnum("buffer size","4096",10,&y,xxstring)) < 0)
+          return(z);
+        if (y < 1) {
+            printf("?Positive number required\n");
+            return(-9);
+        }
+        if ((z = cmcfm()) < 0) return(z);
+        readblock = y;
+        if (readbuf)
+          free((char *)readbuf);
+        if (!(readbuf = (CHAR *) malloc(readblock+1))) {
+            printf("?Can't allocate read buffer\n");
+            return(-9);
+        }
+        return(success = zopeni(ZRFILE,line));
+
+#ifndef MAC
+#ifndef NOPUSH
+      case OPN_PI_R:                    /* Pipe/Process (!READ) */
+        if (nopush) {
+            printf("?Read from pipe disabled\n");
+            return(success=0);
+        }
+        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);
+        }
+        ckstrncpy(line,brstrip(s),LINBUFSIZ);
+        if (!line[0]) return(-2);
+        if ((y = cmcfm()) < 0) return(y);
+        if (!readbuf) {
+            if (!(readbuf = (CHAR *) malloc(readblock+1))) {
+                printf("?Can't allocate read buffer\n");
+                return(-9);
+            }
+        }
+        return(success = zxcmd(ZRFILE,line));
+
+      case OPN_PI_W:                    /* Write to pipe */
+        if (nopush) {
+            printf("?Write to pipe disabled\n");
+            return(success=0);
+        }
+        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);
+        }
+        ckstrncpy(line,brstrip(s),LINBUFSIZ);
+        if (!line[0]) 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 OPN_FI_W:                    /* New file (WRITE) */
+      case OPN_FI_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 (z == 2) {
+            printf("?Sorry, %s is a directory name\n",s);
+            return(-9);
+        }
+        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 == OPN_FI_W) ? XYFZ_N : XYFZ_A; /* Create or Append */
+        ckstrncpy(line,s,LINBUFSIZ);
+        if ((int)strlen(line) < 1) return(-2);
+        if ((y = cmcfm()) < 0) return(y);
+        return(success = zopeno(ZWFILE,line,NULL,&fcb));
+
+#ifndef NOLOCAL
+      case OPN_SER:                     /* OPEN PORT or LINE */
+      case OPN_NET: {                   /* OPEN HOST */
+          extern int didsetlin, ttnproto;
+          if (x == OPN_NET) {
+              z = ttnproto;
+              ttnproto = NP_NONE;
+          }
+          if ((y = setlin((x == OPN_SER) ? XYLINE : XYHOST, 1, 0)) < 0) {
+              if (x == OPN_NET)
+                ttnproto = z;
+              success = 0;
+          }
+          didsetlin++;
+          return(y);
+      }
+#endif /* NOLOCAL */
+
+      default:
+        printf("?Not implemented");
+        return(-2);
+    }
+}
+#endif /* NOSPL */
+
+#ifndef NOXFER
+/*  D O X G E T  --  GET command parser with switches  */
+
+#ifdef CK_LABELED
+int g_lf_opts = -1;
+extern int lf_opts;
+#endif /* CK_LABELED */
+
+int
+doxget(cx) int cx; {
+    extern int                          /* External variables we need */
+#ifdef RECURSIVE
+      recursive,
+#endif /* RECURSIVE */
+      xfermode, fdispla, protocol, usepipes,
+      g_binary, g_xfermode, g_displa, g_rpath, g_usepipes;
+    extern char * rcv_move;             /* Directory to move new files to */
+    extern char * rcv_rename;           /* What to rename new files to */
+    extern char * rcvexcept[];          /* RECEIVE / GET exception list */
+    int opkt  =  0;                     /* Flag for O-Packet needed */
+
+#ifdef PIPESEND
+    extern int pipesend;
+    extern char * rcvfilter;
+#endif /* PIPESEND */
+    extern struct keytab rpathtab[];
+    extern int nrpathtab;
+    extern long calibrate;
+    int asname = 0;                     /* Flag for have as-name */
+    int konly = 0;                      /* Kermit-only function */
+    int c, i, n, confirmed = 0;         /* Workers */
+    int getval = 0;                     /* Whether to get switch value */
+    int rcvcmd = 0;                     /* Whether it is the RECEIVE command */
+    int mget = 0;                       /* Whether it is the MGET command */
+    struct stringint {                  /* Temporary array for switch values */
+        char * sval;
+        int ival;
+    } pv[SND_MAX+1];
+    struct FDB sw, fl, cm;              /* FDBs for each parse function */
+    char * cmdstr = "this command";
+
+#ifdef NEWFTP
+    if (cx == XXGET || cx == XXREGET || cx == XXMGET || cx == XXRETR) {
+        extern int ftpget;
+        extern int ftpisopen();
+        if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
+          return(doftpget(cx,0));
+    }
+#endif /* NEWFTP */
+
+    debug(F101,"xget cx","",cx);
+
+    oopts = -1;
+    omode = -1;
+
+    for (i = 0; i <= SND_MAX; i++) {    /* Initialize switch values */
+        pv[i].sval = NULL;
+        pv[i].ival = -1;
+    }
+    /* Preset switch values based on top-level command that called us */
+
+    switch (cx) {
+      case XXREC:                       /* RECEIVE */
+        cmdstr = "RECEIVE";
+        rcvcmd = 1; break;
+      case XXGET:                       /* GET */
+        cmdstr = "GET";
+        konly = 1;
+        break;
+#ifdef CK_RESEND
+      case XXREGET:                     /* REGET */
+        cmdstr = "REGET";
+        konly = 1;
+        pv[SND_BIN].ival = 1;           /* Implies /BINARY */
+        pv[SND_RES].ival = 1; break;
+#endif /* CK_RESEND */
+      case XXRETR:                      /* RETRIEVE */
+        cmdstr = "RETRIEVE";
+        konly = 1;
+        pv[SND_DEL].ival = 1; break;
+#ifdef PIPESEND
+      case XXCREC:                      /* CRECEIVE */
+        cmdstr = "CRECEIVE";
+        konly = 1;
+        rcvcmd = 1;
+        pv[SND_CMD].ival = 1; break;
+      case XXCGET:                      /* CGET */
+        cmdstr = "CGET";
+        konly = 1;
+        pv[SND_CMD].ival = 1; break;
+#endif /* PIPESEND */
+#ifndef NOMGET
+      case XXMGET:                      /* MGET */
+        cmdstr = "MGET";
+        konly = 1;
+        mget = 1; break;
+#endif /* NOMGET */
+    }
+    debug(F111,"xget rcvcmd",cmdstr,rcvcmd);
+    debug(F101,"xget konly","",konly);
+
+#ifdef CK_XYZ
+    if (!rcvcmd && protocol != PROTO_K) {
+        printf("?Sorry, %s works only with Kermit protocol\n",cmdstr);
+        return(-9);
+    }
+#endif /* CK_XYZ */
+
+    /* Set up chained parse functions... */
+
+    cmfdbi(&sw,                         /* First FDB - command switches */
+           _CMKEY,                      /* fcode */
+           rcvcmd ?
+           "Optional name/template to store incoming files under, or switch" :
+           "Remote filename, or switch", /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           rcvcmd ? nrcvtab : ngettab,  /* addtl numeric data 1: tbl size */
+           4,                           /* addtl numeric data 2: 4 = cmswi */
+           xxstring,                    /* Processing function */
+           rcvcmd ? rcvtab : gettab,    /* Keyword table */
+           &fl                          /* Pointer to next FDB */
+           );
+    if (rcvcmd || mget)                 /* RECEIVE or MGET */
+      cmfdbi(&fl,
+           _CMTXT,                      /* fcode */
+           rcvcmd ?                     /* hlpmsg */
+             "Output filename or Command" : /* Output filename */
+             "File(s) to GET",              /* Files we are asking for */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+#ifdef CK_XYZ
+           (protocol == PROTO_X || protocol == PROTO_XC) ?
+             xxstring :
+             (rcvcmd ? (xx_strp)0  : xxstring)
+#else
+           rcvcmd ? (xx_strp)0  : xxstring /* Processing function */
+#endif /* CK_XYZ */
+             ,
+           NULL,
+           &cm
+           );
+    else
+      cmfdbi(&fl,                       /* Remote filename or command */
+           _CMFLD,                      /* fcode */
+           "Remote filename",           /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,
+           NULL,
+           &cm
+           );
+    cmfdbi(&cm,                         /* Confirmation */
+           _CMCFM,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           NULL,
+           NULL,
+           NULL
+           );
+
+    /* (See doxsend() for fuller commentary) */
+
+    while (1) {                         /* Parse 0 or more switches */
+        x = cmfdb(&sw);                 /* Parse something */
+        debug(F101,"xget cmfdb","",x);
+        if (x < 0)                      /* Error */
+          goto xgetx;                   /* or reparse needed */
+        if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
+          break;
+        c = cmgbrk();                   /* Get break character */
+        if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+            printf("?This switch does not take an argument\n");
+            x = -9;
+            goto xgetx;
+        }
+        if (!getval && (cmgkwflgs() & CM_ARG)) {
+            printf("?This switch requires an argument\n");
+            x = -9;
+            goto xgetx;
+        }
+        n = cmresult.nresult;           /* Numeric result = switch value */
+        debug(F101,"xget switch","",n);
+
+        switch (n) {                    /* Process the switch */
+#ifdef PIPESEND
+          case SND_CMD:                 /* These take no args */
+            if (nopush) {
+                printf("?Sorry, system command access is disabled\n");
+                x = -9;
+                goto xgetx;
+            } else if (rcvfilter) {
+                printf(
+"?Sorry, no GET /COMMAND when RECEIVE FILTER selected\n");
+                x = -9;
+                goto xgetx;
+            }
+            if (rcvcmd)
+              sw.hlpmsg = "Command, or switch"; /* Change help message */
+            /* Fall thru... */
+#endif /* PIPESEND */
+
+          case SND_REC:                 /* /RECURSIVE */
+            pv[SND_PTH].ival = PATH_REL; /* Implies relative pathnames */
+            pv[n].ival = 1;             /* Set the recursive flag */
+            break;
+
+          case SND_RES:                 /* /RECOVER */
+            pv[SND_BIN].ival = 1;       /* Implies /BINARY */
+            pv[n].ival = 1;             /* Set the resend flag */
+            break;
+
+          case SND_DEL:                 /* /DELETE */
+          case SND_SHH:                 /* /QUIET */
+          case SND_CAL:                 /* /CALIBRATE */
+          case SND_XPA:                 /* /TRANSPARENT */
+            pv[n].ival = 1;             /* Just set the appropriate flag */
+            break;
+
+          case SND_PIP:                 /* /PIPES:{ON,OFF} */
+            if (!getval) {
+                pv[n].ival = 1;
+                break;
+            }
+            if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
+              goto xgetx;
+            if (!nopush)
+              pv[n].ival = x;
+            break;
+
+          /* File transfer modes - each undoes the others */
+
+          case SND_BIN:                 /* Binary */
+          case SND_TXT:                 /* Text */
+          case SND_IMG:                 /* Image */
+          case SND_LBL:                 /* Labeled */
+            pv[SND_BIN].ival = 0;       /* Unset all */
+            pv[SND_TXT].ival = 0;
+            pv[SND_IMG].ival = 0;
+            pv[SND_LBL].ival = 0;
+            pv[n].ival = 1;             /* Set the requested one */
+            break;
+
+          case SND_EXC:                 /* Excludes */
+            if (!getval) break;
+            if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
+                if (x == -3) {
+                    printf("?Pattern required\n");
+                    x = -9;
+                }
+                goto xgetx;
+            }
+            if (pv[n].sval) free(pv[n].sval);
+            y = strlen(s);
+            if (y > 256) {
+                printf("?Pattern too long - 256 max\n");
+                x = -9;
+                goto xgetx;
+            }
+            pv[n].sval = malloc(y+1);
+            if (pv[n].sval) {
+                strcpy(pv[n].sval,s);   /* safe */
+                pv[n].ival = 1;
+            }
+            break;
+
+#ifdef COMMENT
+          /* Not implemented */
+          case SND_PRI:                 /* GET to printer */
+            pv[n].ival = 1;
+            if (!getval) break;
+            if ((x = cmfld("Print options","",&s,xxstring)) < 0)
+              goto xgetx;
+            pv[n].sval = malloc((int)strlen(s)+1);
+            if (pv[n].sval)
+              strcpy(pv[n].sval,s);     /* safe */
+            break;
+#endif /* COMMENT */
+
+          case SND_MOV:                 /* MOVE after */
+          case SND_REN:                 /* RENAME after */
+            if (!getval) break;
+            if ((x = cmfld(n == SND_MOV ?
+           "device and/or directory for source file after sending" :
+           "new name for source file after sending",
+                           "",
+                           &s,
+                           n == SND_MOV ? xxstring : NULL
+                           )) < 0) {
+                if (x == -3) {
+                    printf("%s\n", n == SND_MOV ?
+                           "?Destination required" :
+                           "?New name required"
+                           );
+                    x = -9;
+                }
+                goto xgetx;
+            }
+            if (pv[n].sval) {
+                free(pv[n].sval);
+                pv[n].sval = NULL;
+            }
+            s = brstrip(s);
+            y = strlen(s);
+            if (y > 0) {
+                pv[n].sval = malloc(y+1);
+                if (pv[n].sval) {
+                    strcpy(pv[n].sval,s); /* safe */
+                    pv[n].ival = 1;
+                }
+            }
+            break;
+
+          case SND_ASN:                 /* As-name */
+            if (!getval) break;
+            if (mget) {
+                printf("?Sorry, as-name not allowed with MGET\n");
+                x = -9;
+                goto xgetx;
+            }
+            if ((x = cmfld("Name to store it under","",&s,NULL)) < 0)
+              goto xgetx;
+            s = brstrip(s);
+            if ((y = strlen(s)) > 0) {
+                if (pv[n].sval) free(pv[n].sval);
+                pv[n].sval = malloc(y+1);
+                if (pv[n].sval) {
+                    strcpy(pv[n].sval,s); /* safe */
+                    pv[n].ival = 1;
+                }
+            }
+            break;
+
+#ifdef PIPESEND
+          case SND_FLT:                 /* Filter */
+            debug(F101,"xget /filter getval","",getval);
+            if (!getval) break;
+            if ((x = cmfld("Filter program to receive through",
+                           "",&s,NULL)) < 0) {
+                if (x == -3)
+                  s = "";
+                else
+                  goto xgetx;
+            }
+            if (*s) s = brstrip(s);
+            y = strlen(s);
+            for (x = 0; x < y; x++) {   /* Make sure they included "\v(...)" */
+                if (s[x] != '\\') continue;
+                if (s[x+1] == 'v') break;
+            }
+            if (x == y) {
+                printf(
+                "?Filter must contain a replacement variable for filename.\n"
+                       );
+                x = -9;
+                goto xgetx;
+            }
+            pv[n].ival = 1;
+            if (pv[n].sval) {
+                free(pv[n].sval);
+                pv[n].sval = NULL;
+            }
+            if ((y = strlen(s)) > 0) {
+                if ((pv[n].sval = malloc(y+1)))
+                  strcpy(pv[n].sval,s); /* safe */
+            }
+            break;
+#endif /* PIPESEND */
+
+          case SND_PTH:                 /* Pathnames */
+            if (!getval) {
+                pv[n].ival = PATH_REL;
+                break;
+            }
+            if ((x = cmkey(rpathtab,nrpathtab,"","on",xxstring)) < 0)
+              goto xgetx;
+            pv[n].ival = x;             /* Ditto */
+            break;
+
+          case SND_NAM:                 /* Filenames */
+            if (!getval) break;
+            if ((x = cmkey(fntab,nfntab,"","converted",xxstring)) < 0)
+              goto xgetx;
+            pv[n].ival = x;
+            break;
+
+          case SND_PRO:                 /* Protocol to use */
+            if (!getval) break;
+            if ((x = cmkey(protos,nprotos,"File-transfer protocol","",
+                           xxstring)) < 0) {
+                if (x == -3)
+                  x = 0;
+                else
+                  goto xgetx;
+            }
+            debug(F111,"xget /proto",atmbuf,x);
+            pv[n].ival = x;
+            if (konly && x != PROTO_K) {
+                printf(
+"?Sorry, this command works only with Kermit protocol\n"
+                       );
+                x = -9;
+                goto xgetx;
+            }
+            break;
+
+          default:
+            printf("?Unexpected switch value - %d\n",cmresult.nresult);
+            x = -9;
+            goto xgetx;
+        }
+    }
+    debug(F101,"xget cmresult fcode","",cmresult.fcode);
+
+    cmarg = line;                       /* Initialize string pointers */
+    cmarg2 = tmpbuf;
+    asname = 0;
+    line[0] = NUL;                      /* and buffers. */
+    tmpbuf[0] = NUL;
+
+    switch (cmresult.fcode) {           /* How did we get out of switch loop */
+      case _CMFLD:                      /* (3) Remote filespec */
+        ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
+        break;
+      case _CMTXT:                      /* (4) As-name */
+        if (rcvcmd) {
+            ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
+            if ((int)strlen(tmpbuf) > 0)
+              asname = 1;
+        } else {
+            ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
+        }
+      case _CMCFM:                      /* (6) Confirmation */
+        confirmed = 1;
+        break;
+      default:
+        printf("?Unexpected function code: %d\n",cmresult.fcode);
+        x = -9;
+        goto xgetx;
+    }
+    debug(F110,"xget string",cmarg,0);
+    debug(F101,"xget confirmed","",confirmed);
+
+    cmarg = brstrip(cmarg);             /* Strip any braces */
+
+    if (!confirmed) {                   /* CR not typed yet, get more fields */
+        if (pv[SND_CMD].ival > 0) {
+            debug(F100,"xget calling cmtxt","",0);
+            x = cmtxt("Local command to pipe into","",&s,NULL);
+            if (x < 0 && x != -3) goto xgetx;
+            if (x != -3) {
+                ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+                asname = 1;
+            }
+        } else if (!rcvcmd) {
+#ifdef VMS
+            /* cmofi() fails if you give it a directory name */
+            x = cmfld("Name or directory for incoming file","",&s,NULL);
+            debug(F111,"xget cmfld",s,x);
+#else
+            x = cmofi("Name or directory for incoming file","",&s,NULL);
+            debug(F111,"xget cmofi",s,x);
+#endif /* VMS */
+            if (x < 0 && x != -3) goto xgetx;
+            if (x != -3) {
+                ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+                if ((x = cmcfm()) < 0) goto xgetx;
+                asname = 1;
+            }
+        }
+    }
+    /* Arrive here with cmarg and cmarg2 all set */
+
+    debug(F111,"xget asname",cmarg2,asname);
+    if (!asname) {
+        if (pv[SND_ASN].sval)
+          ckstrncpy(tmpbuf,pv[SND_ASN].sval,TMPBUFSIZ);
+        else
+          tmpbuf[0] = NUL;
+    }
+    cmarg2 = brstrip(cmarg2);           /* Strip outer braces if any. */
+    debug(F110,"xget cmarg",cmarg,0);
+    debug(F110,"xget cmarg2",cmarg2,0);
+
+    if (!*cmarg &&
+        (cx == XXGET || cx == XXREGET || cx == XXCGET || cx == XXMGET)) {
+        printf("?A remote file specification is required\n");
+        x = -9;
+        goto xgetx;
+    }
+#ifdef PIPESEND
+    if (pv[SND_CMD].ival > 0) {         /* /COMMAND sets pipesend flag */
+        x = -9;
+        if (!*cmarg2) {
+            printf("?Command required\n");
+            goto xgetx;
+        } else if (nopush) {
+            printf("?Sorry, system command access is disabled\n");
+            goto xgetx;
+        } else if (rcvfilter) {
+            printf("?Sorry, no GET /COMMAND while RECEIVE FILTER selected\n");
+            goto xgetx;
+        } else
+          pipesend = 1;
+    }
+    debug(F101,"xget /COMMAND pipesend","",pipesend);
+#endif /* PIPESEND */
+
+#ifdef CK_RESEND
+    if (pv[SND_RES].ival > 0) {         /* REGET or GET /RECOVER */
+#ifdef RECURSIVE
+        if (pv[SND_REC].ival > 0) {     /* RECURSIVE */
+#ifdef COMMENT
+            printf("?Unsupported option combination: /RECOVER /RECURSIVE\n");
+            x = -9;
+            goto xgetx;
+#else
+            opkt = 1;
+#endif /* COMMENT */
+        }
+#endif /* RECURSIVE */
+        if (pv[SND_DEL].ival > 0) {     /* /DELETE */
+#ifdef COMMENT
+            printf("?Unsupported option combination: /RECOVER /DELETE\n");
+            x = -9;
+            goto xgetx;
+#else
+            opkt = 1;
+#endif /* COMMENT */
+        }
+    }
+#endif /* CK_RESEND */
+
+    if (pv[SND_EXC].ival > 0)           /* /EXCEPT */
+      makelist(pv[SND_EXC].sval,rcvexcept,NSNDEXCEPT);
+
+#ifdef IKS_OPTION
+    if (!rcvcmd
+#ifdef CK_XYZ
+         && protocol == PROTO_K
+#endif /* CK_XYZ */
+         ) {
+        if (!iks_wait(KERMIT_REQ_START,1)) {
+            printf(
+              "?A Kermit Server is not available to process this command\n");
+            x = -9;                     /* correct the return code */
+            goto xgetx;
+        }
+    }
+#endif /* IKS_OPTION */
+
+#ifdef CK_XYZ
+    {
+        int po, pg;                     /* (for clarity) */
+        po = pv[SND_PRO].ival;          /* /PROTOCOL option */
+        pg = protocol;                  /* Protocol global  */
+        if ((rcvcmd && !*cmarg2) &&     /* If no as-name was given */
+            /* and /PROTOCOL is XMODEM or global protocol is XMODEM... */
+            ((po <  0 && (pg == PROTO_X || pg == PROTO_XC)) ||
+             (po > -1 && (po == PROTO_X || po == PROTO_XC)))
+            ) {
+            printf(
+"Sorry, you must specify a name when receiving a file with XMODEM protocol\n"
+                   );
+            x = -9;
+            goto xgetx;
+        }
+    }
+#endif /* CK_XYZ */
+
+#ifdef RECURSIVE
+    if (pv[SND_REC].ival > 0) {         /* RECURSIVE */
+        recursive = 1;
+        pv[SND_PTH].ival = PATH_REL;    /* Implies relative pathnames too */
+    }
+#endif /* RECURSIVE */
+
+    if (pv[SND_PIP].ival > -1) {
+        g_usepipes = usepipes;
+        usepipes = pv[SND_PIP].ival;
+    }
+
+    /* Save global protocol parameters */
+
+    g_proto = protocol;
+#ifdef CK_LABELED
+    g_lf_opts = lf_opts;                /* Save labeled transfer options */
+#endif /* CK_LABELED */
+    g_urpsiz = urpsiz;                  /* Receive packet length */
+    g_spsizf = spsizf;                  /* Send packet length flag */
+    g_spsiz = spsiz;                    /* Send packet length */
+    g_spsizr = spsizr;                  /* etc etc */
+    g_spmax = spmax;
+    g_wslotr = wslotr;
+    g_prefixing = prefixing;
+    g_fncact = fncact;
+    g_fncnv = fncnv;
+    g_fnspath = fnspath;
+    g_fnrpath = fnrpath;
+    g_xfrxla = xfrxla;
+
+    if (pv[SND_PRO].ival > -1) {        /* Change according to switch */
+        protocol = pv[SND_PRO].ival;
+        if (ptab[protocol].rpktlen > -1)   /* copied from initproto() */
+            urpsiz = ptab[protocol].rpktlen;
+        if (ptab[protocol].spktflg > -1)
+            spsizf = ptab[protocol].spktflg;
+        if (ptab[protocol].spktlen > -1) {
+            spsiz = ptab[protocol].spktlen;
+            if (spsizf)
+                spsizr = spmax = spsiz;
+        }
+        if (ptab[protocol].winsize > -1)
+            wslotr = ptab[protocol].winsize;
+        if (ptab[protocol].prefix > -1)
+            prefixing = ptab[protocol].prefix;
+        if (ptab[protocol].fnca > -1)
+            fncact  = ptab[protocol].fnca;
+        if (ptab[protocol].fncn > -1)
+            fncnv   = ptab[protocol].fncn;
+        if (ptab[protocol].fnsp > -1)
+            fnspath = ptab[protocol].fnsp;
+        if (ptab[protocol].fnrp > -1)
+            fnrpath = ptab[protocol].fnrp;
+    }
+    debug(F101,"xget protocol","",protocol);
+    debug(F111,"xget cmarg2",cmarg2,xfermode);
+
+    g_xfermode = xfermode;
+    g_binary = binary;
+    if (pv[SND_BIN].ival > 0) {         /* Change according to switch */
+        xfermode = XMODE_M;
+        binary = XYFT_B;                /* FILE TYPE BINARY */
+        omode = GMOD_BIN;               /* O-Packet mode */
+        debug(F101,"doxget /BINARY xfermode","",xfermode);
+    } else if (pv[SND_TXT].ival > 0) {  /* Ditto for /TEXT */
+        xfermode = XMODE_M;
+        binary = XYFT_T;
+        omode = GMOD_TXT;
+        debug(F101,"doxget /TEXT xfermode","",xfermode);
+    } else if (pv[SND_IMG].ival > 0) {
+        xfermode = XMODE_M;
+#ifdef VMS
+        binary = XYFT_I;
+#else
+        binary = XYFT_B;
+#endif /* VMS */
+        omode = GMOD_TXT;
+        debug(F101,"doxget /IMAGE xfermode","",xfermode);
+    }
+#ifdef CK_LABELED
+    else if (pv[SND_LBL].ival > 0) {
+        xfermode = XMODE_M;
+        binary = XYFT_L;
+        omode = GMOD_LBL;
+        debug(F101,"doxget /LABELED xfermode","",xfermode);
+    }
+#endif /* CK_LABELED */
+    debug(F101,"xget binary","",binary);
+    debug(F101,"xget omode","",omode);
+
+    if (pv[SND_XPA].ival > 0)           /* /TRANSPARENT */
+      xfrxla = 0;                       /* Don't translate character sets */
+
+#ifdef PIPESEND
+    if (pv[SND_FLT].ival > 0)
+      makestr(&rcvfilter,pv[SND_FLT].sval);
+#endif /* PIPESEND */
+
+#ifdef CK_TMPDIR
+    if (pv[SND_MOV].ival > 0) {
+        int len;
+        char * p = pv[SND_MOV].sval;
+#ifdef CK_LOGIN
+        if (isguest) {
+            printf("?Sorry, /MOVE-TO not available to guests\n");
+            x = -9;
+            goto xgetx;
+        }
+#endif /* CK_LOGIN */
+        len = strlen(p);
+        if (!isdir(p)) {                /* Check directory */
+#ifdef CK_MKDIR
+            char * s = NULL;
+            s = (char *)malloc(len + 4);
+            if (s) {
+                strcpy(s,p);            /* safe */
+#ifdef datageneral
+                if (s[len-1] != ':') { s[len++] = ':'; s[len] = NUL; }
+#else
+                if (s[len-1] != '/') { s[len++] = '/'; s[len] = NUL; }
+#endif /* datageneral */
+                s[len++] = 'X';
+                s[len] = NUL;
+                x = zmkdir(s);
+                free(s);
+                if (x < 0) {
+                    printf("?Can't create \"%s\"\n",p);
+                    x = -9;
+                    goto xgetx;
+                }
+            }
+#else
+            printf("?Directory \"%s\" not found\n",p);
+            x = -9;
+            goto xgetx;
+#endif /* CK_MKDIR */
+        }
+        zfnqfp(p,LINBUFSIZ,line);
+        makestr(&rcv_move,line);
+    }
+#endif /* CK_TMPDIR */
+
+    if (pv[SND_REN].ival > 0) {         /* /RENAME-TO:name */
+        char * p = pv[SND_REN].sval;
+#ifdef CK_LOGIN
+        if (isguest) {
+            printf("?Sorry, /RENAME-TO not available to guests\n");
+            x = -9;
+            goto xgetx;
+        }
+#endif /* CK_LOGIN */
+        if (!p) p = "";
+        if (!*p) {
+            printf("?New name required for /RENAME\n");
+            x = -9;
+            goto xgetx;
+        }
+        p = brstrip(p);
+        makestr(&rcv_rename,p);
+        debug(F110,"xget rcv_rename","",0);
+    }
+
+#ifdef CALIBRATE
+    if (pv[SND_CAL].ival > 0)
+      calibrate = 1L;
+#endif /* CALIBRATE */
+    g_displa = fdispla;
+    if (pv[SND_SHH].ival > 0)
+      fdispla = 0;
+    debug(F101,"xget display","",fdispla);
+
+    if (pv[SND_NAM].ival > -1) {        /* /FILENAMES */
+        g_fncnv = fncnv;                /* Save global value */
+        fncnv = pv[SND_NAM].ival;
+        debug(F101,"xsend fncnv","",fncnv);
+        /* We should also handle O packet filename option here */
+        /* but we don't really need to since WHATAMI already handles it */
+    }
+    if (pv[SND_PTH].ival > -1) {        /* PATHNAMES */
+        g_rpath = fnrpath;              /* Save global values */
+        fnrpath = pv[SND_PTH].ival;
+        debug(F101,"xsend fnrpath","",fnrpath);
+#ifndef NZLTOR
+        if (fnrpath != PATH_OFF) {
+            g_fncnv = fncnv;
+            fncnv = XYFN_L;
+            debug(F101,"xsend fncnv","",fncnv);
+        }
+        /* We should also handle O packet pathname option here */
+        /* but we don't really need to since WHATAMI already handles it */
+#endif /* NZLTOR */
+    }
+
+    /* Set protocol start state */
+
+    if (opkt) {                         /* Extended GET Options*/
+        sstate = (CHAR) 'o';
+        oopts = 0;
+        if (pv[SND_DEL].ival > 0) oopts |= GOPT_DEL; /* GET /DELETE */
+        if (pv[SND_RES].ival > 0) oopts |= GOPT_RES; /* GET /RECOVER */
+        if (pv[SND_REC].ival > 0) oopts |= GOPT_REC; /* GET /RECURSIVE */
+    } else if (rcvcmd)
+      sstate = (CHAR) 'v';              /* RECEIVE or CRECEIVE */
+    else if (pv[SND_DEL].ival > 0)
+      sstate = (CHAR) 'h';              /* GET /DELETE (= RETRIEVE) */
+    else if (pv[SND_RES].ival > 0)
+      sstate = (CHAR) 'j';              /* GET /RECOVER (= REGET) */
+    else
+      sstate = (CHAR) 'r';              /* Regular GET */
+    getcmd = 1;
+    debug(F000,"xget sstate","",sstate);
+#ifdef MAC
+    what = W_RECV;
+    scrcreate();
+#endif /* MAC */
+    if (local) {
+        if (pv[SND_SHH].ival != 0)
+          displa = 1;
+        ttflui();
+    }
+    x = 0;
+#ifdef PIPESEND
+    if (pipesend)
+      goto xgetx;
+#endif /* PIPESEND */
+
+#ifdef CK_TMPDIR
+/*
+  cmarg2 is also allowed to be a device or directory name;
+  even the name of a directory that doesn't exist.
+*/
+    y = strlen(cmarg2);
+    debug(F111,"xget strlen(cmarg2)",cmarg2,y);
+    if ((y > 0) &&
+#ifdef OS2
+        ((isalpha(cmarg2[0]) &&
+         cmarg2[1] == ':' &&
+         cmarg2[2] == NUL) ||
+        (cmarg[y-1] == '/' || cmarg[y-1] == '\\') ||
+        isdir(cmarg2))
+#else
+#ifdef UNIXOROSK
+        (cmarg2[y-1] == '/' || isdir(cmarg2))
+#else
+#ifdef VMS
+        (cmarg2[y-1] == ']' || cmarg2[y-1] == '>' || isdir(cmarg2))
+#else
+#ifdef STRATUS
+        (cmarg2[y-1] == '>' || isdir(cmarg2))
+#else
+#ifdef datageneral
+        (cmarg2[y-1] == ':' || cmarg[0] == ':' || isdir(cmarg2))
+#else
+        isdir(cmarg2)
+#endif /* datageneral */
+#endif /* STRATUS */
+#endif /* VMS */
+#endif /* UNIXOROSK */
+#endif /* OS2 */
+        ) {
+        debug(F110,"doxget RECEIVE cmarg2 disk or dir",cmarg2,0);
+        if (!f_tmpdir) {
+            int x;
+            s = zgtdir();
+            if (s) {
+                ckstrncpy(savdir,s,TMPDIRLEN); /* remember old disk/dir */
+                f_tmpdir = 1;   /* and that we did this */
+            } else {
+                printf("?Can't get current directory\n");
+                cmarg2 = "";
+                f_tmpdir = 0;
+                x = -9;
+                goto xgetx;
+            }
+#ifdef CK_MKDIR
+            x = zchki(cmarg2);          /* Does as-name exist? */
+            if (x == -1) {              /* Doesn't exist */
+                char * p = NULL;        /* Try to create it */
+                x = strlen(cmarg2);
+                if ((p = (char *)malloc(x+4))) {
+                    sprintf(p,"%s%s",cmarg2,"x.x"); /* SAFE (prechecked) */
+                    x = zmkdir(p);
+                    free(p);
+                    if (x < 0) {
+                        printf("?Can't create %s\n",cmarg2);
+                        x = -9;
+                        goto xgetx;
+                    }
+                }
+            }
+#endif /* CK_MKDIR */
+            if (!zchdir(cmarg2)) {      /* change to given disk/directory, */
+                printf("?Can't access %s\n",cmarg2);
+                x = -9;
+                goto xgetx;
+            }
+            cmarg2 = "";
+        }
+    }
+#endif /* CK_TMPDIR */
+
+    ckstrncpy(fspec,cmarg,CKMAXPATH);   /* Note - this is a REMOTE filespec */
+    debug(F111,"xget fspec",fspec,fspeclen);
+    debug(F110,"xget cmarg2",cmarg2,0);
+
+  xgetx:
+    for (i = 0; i < SND_MAX; i++)
+      if (pv[i].sval)
+        free(pv[i].sval);
+    return(x);
+}
+#endif /* NOXFER */
+
+#ifndef NOSPL
+
+/*
+  D O G T A  --  Do _GETARGS or _PUTARGS Command.
+
+  Used by XIF, FOR, WHILE, and SWITCH, each of which are implemented as
+  2-level macros; the first level defines the macro, the second runs it.
+  This routine hides the fact that they are macros by importing the
+  macro arguments (if any) from two levels up, to make them available
+  in the IF, FOR, SWITCH, and WHILE commands themselves; for example as
+  loop indices, etc, and within the IF/FOR/WHILE/SWITCH body itself.
+  _PUTARGS is in case we changed any of these variables or used SHIFT
+  on them, so the new values won't be lost as we pop up the stack.
+*/
+int
+dogta(cx) int cx; {
+    int i, n;
+    char c, *p,  mbuf[4];
+    extern int topargc, cmdint;
+    extern char ** topxarg;
+
+    if ((y = cmcfm()) < 0)
+      return(y);
+    debug(F101,"dogta cx","",cx);
+    debug(F101,"dogta maclvl","",maclvl);
+    if (cx == XXGTA) {
+        debug(F101,"dogta _GETARGS maclvl","",maclvl);
+    } else if (cx == XXPTA) {
+        debug(F101,"dogta _PUTARGS maclvl","",maclvl);
+    } else {
+        return(-2);
+    }
+    if (maclvl < 1)
+      return(success = 0);
+
+    /* Make new copies of macro arguments /%0..9 */
+
+    mbuf[0] = '%'; mbuf[1] = '0'; mbuf[2] = NUL; /* Argument name buf */
+
+    if (cx == XXPTA) {                  /* Go NOINT because _PUTARGS */
+        if (cmdint)                     /* temporarily changes maclvl. */
+          connoi();                     /* Interrupts OFF. */
+    }
+    for (i = 0; i < 10; i++) {          /* For all args */
+        c = (char) (i + '0');           /* Make name */
+        mbuf[1] = (char) 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 */
+            addmac(mbuf,p);
+#ifdef COMMENT
+            if (maclvl > 1)
+              makestr(&(m_line[maclvl]),m_line[maclvl-2]);
+#endif /* COMMENT */
+        } else if (cx == XXPTA) {       /* Put args level+2 */
+            maclvl -= 2;                /* This is gross, it's because we're */
+            addmac(mbuf,m_arg[maclvl+2][i]); /* adding macros two levels up */
+            maclvl += 2;                     /* and addmac() uses maclvl. */
+            count[cmdlvl - 2]  = count[cmdlvl];
+            intime[cmdlvl - 2] = intime[cmdlvl];
+            inpcas[cmdlvl - 2] = inpcas[cmdlvl];
+            takerr[cmdlvl - 2] = takerr[cmdlvl];
+            merror[cmdlvl - 2] = merror[cmdlvl];
+            xquiet[cmdlvl - 2] = xquiet[cmdlvl];
+        } else return(success = 0);     /* Bad call to this routine */
+    }
+    if (cx == XXPTA) {                  /* Restore interrupts if we */
+        if (cmdint)                     /* turned them off above. */
+          conint(trap,stptrap);
+    }
+    /* Now take care of the argument vector array \&_[], \v(return), */
+    /* and \v(argc) by just copying the pointers. */
+
+    if (cx == XXGTA) {                  /* GETARGS from 2 levels up */
+        if (maclvl == 1) {
+            a_ptr[0] = topxarg;         /* \&_[] array */
+            a_dim[0] = topargc - 1;     /* Dimension doesn't include [0] */
+            m_xarg[maclvl] = topxarg;
+            n_xarg[maclvl] = topargc;   /* But \v(argc) does include \%0 */
+            macargc[maclvl] = topargc;
+            makestr(&(mrval[maclvl+1]),mrval[0]); /* (see vnlook()) */
+        } else {
+            a_ptr[0] = m_xarg[maclvl-2];
+            a_dim[0] = n_xarg[maclvl-2];
+            m_xarg[maclvl] = m_xarg[maclvl-2];
+            n_xarg[maclvl] = n_xarg[maclvl-2];
+            macargc[maclvl] = n_xarg[maclvl-2];
+            makestr(&(mrval[maclvl+1]),mrval[maclvl-1]); /* (see vnlook()) */
+
+        }
+    } else {                            /* PUTARGS 2 levels up */
+        if (maclvl > 1) {
+            a_ptr[0] = m_xarg[maclvl];
+            m_xarg[maclvl-2] = m_xarg[maclvl];
+            a_dim[0] = n_xarg[maclvl];
+            n_xarg[maclvl-2] = n_xarg[maclvl];
+            macargc[maclvl-2] = n_xarg[maclvl];
+        }
+    }
+    return(1);                  /* Internal command - don't change success */
+}
+#endif /* NOSPL */
+
+#ifndef NOSPL
+/*
+  Do the GOTO and [_]FORWARD commands.
+  s = Label to search for, cx = function code: XXGOTO, XXFWD, or XXXFWD.
+*/
+#ifdef BIGBUFOK
+#define LBLMAXLEN 255                   /* Max label length */
+#else
+#define LBLMAXLEN 63
+#endif /* BIGBUFOK */
+
+int
+dogoto(s, cx) char *s; int cx; {
+    int i, j, x, y, z, bc;
+    int empty = 0, stopflg = 0;
+    char * cmd;                         /* Name of this command */
+    char tmplbl[LBLMAXLEN+1], *lp;      /* Current label from command stream */
+    char tmp2[LBLMAXLEN+1];             /* SWITCH label conversion buffer */
+    char tmp3[LBLMAXLEN+1];             /* Target label */
+
+    stopflg = (cx == XXXFWD);           /* _FORWARD (used in SWITCH) */
+    bc = 0;                             /* Brace counter */
+
+    cmd = (cx == XXGOTO) ? "GOTO" : ((cx == XXFWD) ? "FORWARD" : "_FORWARD");
+    if (!s) s = "";
+    if (!*s) empty = 1;
+
+#ifdef DEBUG
+    if (deblog) {
+        debug(F111,"GOTO command",cmd,cx);
+        debug(F101,"GOTO cmdlvl","",cmdlvl);
+        debug(F101,"GOTO maclvl","",maclvl);
+        debug(F101,"GOTO tlevel","",tlevel);
+        debug(F111,"GOTO target",s,empty);
+    }
+#endif /* DEBUG */
+    debug(F110,cmd,s,0);
+    ckstrncpy(tmp3+1,s,LBLMAXLEN-1);
+    s = tmp3+1;
+    if (*s != ':') {                    /* Make copy of label */
+        tmp3[0] = ':';                  /* guaranteed to start with ":" */
+        s--;
+    }
+    if (!stopflg && !empty) {
+        if (s[1] == '.' || s[1] == SP || s[1] == NUL) {
+            printf("?Bad label syntax - '%s'\n",s);
+            return(success = 0);
+        }
+    }
+    if (cmdlvl == 0) {
+        printf("?Sorry, %s only works in a command file or macro\n",cmd);
+        return(success = 0);
+    }
+    y = strlen(s);                      /* y = length of target label */
+    debug(F111,cmd,s,y);
+
+    while (cmdlvl > 0) {                /* As long as not at top level... */
+        if (cmdstk[cmdlvl].src == CMD_MD) { /* GOTO inside macro */
+            int i, m, flag;
+            char *xp, *tp;
+
+            /* GOTO: rewind the macro; FORWARD: start at current position */
+
+            lp = (cx == XXGOTO) ? macx[maclvl] : macp[maclvl];
+            m = (int)strlen(lp) - y + 1;
+            debug(F010,"GOTO in macro",lp,0);
+
+            flag = 1;                   /* flag for valid label position */
+            for (i = 0; i < m; i++,lp++) { /* search for label in macro body */
+                if (*lp == '{')         /* But only at this level */
+                  bc++;                 /* Anything inside braces is off */
+                else if (*lp == '}')    /* limits. */
+                  bc--;
+                if (stopflg && bc > 0)  /* This is good for SWITCH */
+                  continue;             /* but interferes with WHILE, etc. */
+                if (*lp == ',') {
+                    flag = 1;
+                    continue;
+                }
+                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++ > LBLMAXLEN) /* j = length of word from macro */
+                      break;
+#ifdef COMMENT
+                    if (*tp < 33 || *tp == ',') /* Look for end of word */
+#else
+                    if (!*tp || *tp == ',')     /* Look for end of word */
+#endif /* COMMENT */
+                      break;
+                    else tp++, xp++;    /* Next character */
+                }
+                *tp = NUL;              /* 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 (stopflg) {          /* Allow variables as SWITCH labels */
+                    int n = LBLMAXLEN - 1;
+                    char * p = tmp2;
+                    zzstring(tmplbl,&p,&n);
+                    ckstrncpy(tmplbl,tmp2,LBLMAXLEN);
+                    tmp2[49] = NUL;
+                }
+                debug(F111,"GOTO s",s,y);
+                debug(F111,"GOTO tmplbl",tmplbl,j);
+                debug(F101,"GOTO empty",ckitoa(stopflg),empty);
+
+                if (empty) {              /* Empty target */
+                   z = (!strcmp(s,":") && /* String is empty */
+                        /* and Label is ":" or ":*"... */
+                        (!strcmp(tmplbl,":") || !strcmp(tmplbl,":*")))
+                       ? 0 : 1;
+                   debug(F111,"GOTO","A",z);
+                } else if (stopflg) {
+                    z = ckmatch(tmplbl,s,inpcas[cmdlvl],1) ? 0 : 1;
+                   debug(F111,"GOTO","B",z);
+                } else {
+                    z = (stopflg && inpcas[cmdlvl]) ?
+                      strcmp(s,tmplbl) :
+                        ckstrcmp(s,tmplbl,(y > j) ? y : j, 0);
+                   debug(F111,"GOTO","C",z);
+                }
+                if (!z) {
+                    break;
+                } else if (stopflg &&
+                         !ckstrcmp(":default",tmplbl,(8 > j) ? 8 : j, 0)) {
+                    debug(F100,"GOTO DEFAULT","",0);
+                    break;
+                } else {
+                    flag = 0;
+                }
+            }
+            debug(F111,"GOTO macro i",cmd,i);
+            debug(F111,"GOTO macro m",cmd,m);
+            if (i >= m) {               /* Didn't find the label */
+                debug(F101,"GOTO failed cmdlvl","",cmdlvl);
+#ifdef COMMENT
+               /* MOVED TO AFTER POPCLVL ABOUT 20 LINES DOWN 5 AUG 2002 */
+                  if (stopflg)
+                  return(0);
+#endif /* COMMENT */
+                if ((maclvl > 0) &&
+                       (m_arg[maclvl-1][0]) &&
+                       (cmdstk[cmdlvl].src == CMD_MD) &&
+                       (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
+                        !strncmp(m_arg[maclvl-1][0],"_for",4) ||
+                        !strncmp(m_arg[maclvl-1][0],"_swi",4) ||
+                        !strncmp(m_arg[maclvl-1][0],"_whi",4))) {
+                    dogta(XXPTA);       /* Restore args */
+                    debug(F101,"GOTO in XIF/FOR/WHI/SWI popping","",cmdlvl);
+                    popclvl();          /* Pop an extra level */
+                }
+                debug(F101,"GOTO popping","",cmdlvl);
+                if (!popclvl()) {       /* pop up to next higher level */
+                    printf("?Label '%s' not found\n",s); /* if none */
+                    return(0);          /* Quit */
+                } else if (stopflg) {  /* SWITCH no case label match */
+                   return(0);          /* and no DEFAULT lable. */
+               } else {
+                   continue;        /* otherwise look again */
+               }
+            }
+            debug(F110,"GOTO found macro label",tmplbl,0);
+            macp[maclvl] = lp;          /* set macro buffer pointer */
+            return(1);
+        } else if (cmdstk[cmdlvl].src == CMD_TF) {
+            x = 0;                      /* GOTO issued in take file */
+            debug(F111,"GOTO in TAKE file",cmd,cx);
+            if (cx == XXGOTO) {         /* If GOTO, but not FORWARD, */
+                rewind(tfile[tlevel]);  /* search file from beginning */
+                tfline[tlevel] = 0;
+            }
+            while (! feof(tfile[tlevel])) {
+#ifdef COMMENT
+/* This is wrong - it lets us jump to labels inside inferior blocks */
+                tfline[tlevel]++;
+                if (fgets(line,LINBUFSIZ,tfile[tlevel]) == NULL) /* Get line */
+#else
+                if (getnct(line,LINBUFSIZ,tfile[tlevel],0) < 0)
+#endif /* COMMENT */
+                  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 */
+                while (*(lp+1) == SP) { /* Remove space between : and name */
+                    *(lp+1) = ':';
+                    lp++;               /* Strip leading whitespace */
+                }
+                tp = lp;                /* Get end of word */
+                j = 0;
+                while (*tp) {           /* And null-terminate it */
+                    if (*tp < 33) {
+                        *tp = NUL;
+                        break;
+                    } else tp++, j++;
+                }
+                if (!ckstrcmp(lp,s,(y > j) ? y : j,0)) { /* Caseless compare */
+                    x = 1;              /* Got it */
+                    break;              /* done. */
+                } else if (stopflg &&
+                           !ckstrcmp(":default",tmplbl,(8 > j) ? 8 : j,0)) {
+                    x = 1;
+                    break;
+                }
+            }
+            if (x == 0) {               /* If not found, print message */
+                debug(F101,"GOTO failed at cmdlvl","",cmdlvl);
+                if (stopflg)
+                  return(0);
+                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 */
+
+/* Finish parsing and do the IF, XIF, and WHILE commands */
+
+#ifndef NOSPL
+
+/*  C H K V A R  --  Check (if it's a) Variable  */
+
+
+#ifdef OLDCHKVAR
+/*
+  Crude and disgusting, but needed for OS/2, DOS, and Windows, where filenames
+  have backslashes in them.  How do we know if a backslash in a filename is a
+  directory separator, or if it's a Kermit backslash?  This routine does a
+  rough syntax check of the next few characters and if it looks like it MIGHT
+  be a variable, then it tries to evaluate it, and if the result is not empty,
+  we say it's a variable, although sometimes it might not be -- some cases are
+  truly ambiguous.  For example there might a DOS directory called \%a, and
+  we also have a variable with the same name.  This is all for the sake of not
+  having to tell PC users that they have to double all backslashes in file
+  and directory names.
+*/
+#else
+/*
+  Somewhat less crude & disgusting.  The previous method was nondeterministic
+  and (worse) it interfered with macro argument passing.  So now we only
+  check the syntax of backslash-items to see if they are variables, but we
+  do NOT check their values.
+*/
+#endif /* OLDCHKVAR */
+/*
+  Call with a string pointer pointing at the backslash of the purported
+  variable.  Returns 1 if it has the syntax of a variable, 0 if not.
+*/
+int
+chkvar(s) char *s; {
+    int z = 0;                          /* Return code - assume failure. */
+    if (!s) s = "";                     /* Watch our for null pointers. */
+    if (!*s) return(0);                 /* Empty arg so not a variable. */
+    if (*s == CMDQ) {                   /* Object begins with backslash. */
+        char c;
+        c = s[1];                       /* Character following backslash. */
+        if (c) {
+            int t = 0;
+            if (c == CMDQ)              /* Quoted backslash */
+              return(1);
+            c = (char) (islower(c) ? toupper(c) : c); /* Otherwise... */
+            if (c == '%') {             /* Simple variable */
+#ifdef OLDCHKVAR
+                t = 1;
+#else
+                return(1);
+#endif /* OLDCHKVAR */
+            } else if (c == '&') {      /* Array */
+                if (!s[2]) return(0);
+                if (s[3] == '[')
+                  t = ckindex("]",s,4,0,1);
+#ifndef OLDCHKVAR
+                return((t > 0) ? 1 : 0);
+#endif /* OLDCHKVAR */
+            } else if (c == '$' ||      /* Environment variable */
+                       c == 'V' ||      /* Built-in variable */
+                       c == 'M') {      /* Macro name */
+                t = (s[2] == '(');
+#ifndef OLDCHKVAR
+                return((t > 0) ? 1 : 0);
+#endif /* OLDCHKVAR */
+            } else if (c == 'F') {      /* Function reference */
+                /* Don't actually call it - it might have side effects */
+                int x;
+                if ((x = ckindex("(",s,3,0,1))) /* Just check syntax */
+                  if ((x = ckindex(")",s,x,0,1)))
+                    z = 1;
+                /* Insert a better syntax check here if necessary */
+            }
+#ifdef OLDCHKVAR
+            if (t) {
+                t = 255;                /* This lets us test \v(xxx) */
+                lp = line;              /* and even \f...(xxx) */
+                zzstring(s,&lp,&t);     /* Evaluate it, whatever it is. */
+                t = strlen(line);       /* Get its length. */
+                debug(F111,"chkvar",line,t);
+                z = t > 0;              /* If length > 0, it's defined */
+            }
+#endif /* OLDCHKVAR */
+        }
+    }
+    return(z);
+}
+
+/*  B O O L E X P  --  Evaluate a Boolean expression  */
+
+#define BOOLLEN 1024
+static char boolval[BOOLLEN];
+
+int
+boolexp(cx) int cx; {
+    int x, y, z; char *s, *p;
+    int parens = 0, pcount = 0, ecount = 0;
+    char *q, *bx;
+    struct FDB kw, nu;
+#ifdef FNFLOAT
+    struct FDB fl;
+    CKFLOAT f1 = 0.0, f2 = 0.0;
+    int f1flag = 0, f2flag = 0;
+#endif /* FNFLOAT */
+#ifdef OS2
+    extern int keymac;
+#endif /* OS2 */
+
+    not = 0;                            /* Flag for whether "NOT" was seen */
+    z = 0;                              /* Initial IF condition */
+    ifargs = 0;                         /* Count of IF condition words */
+    bx = boolval;                       /* Initialize boolean value */
+    *bx = NUL;
+
+  ifagain:
+    cmfdbi(&kw,                         /* First FDB - command switches */
+           _CMKEY,                      /* fcode */
+           "Number, numeric-valued variable, Boolean expression, or keyword",
+           "",                          /* default */
+           "",                          /* addtl string data */
+           nif,                         /* addtl numeric data 1: tbl size */
+           0,                           /* addtl numeric data 2: 4 = silent */
+           xxstring,                    /* Processing function */
+           iftab,                       /* Keyword table */
+           &nu                          /* Pointer to next FDB */
+           );
+    cmfdbi(&nu,                         /* 2nd FDB - An integer */
+           _CMNUM,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* Default */
+           "",                          /* addtl string data */
+           0,
+           0,
+           xxstring,
+           NULL,
+#ifdef FNFLOAT
+           &fl
+#else
+           NULL
+#endif /* FNFLOAT */
+           );
+#ifdef FNFLOAT
+    cmfdbi(&fl,                         /* A floating-point number */
+           _CMFLD,                      /* fcode */
+           "",                          /* hlpmsg */
+           "",                          /* default */
+           "",                          /* addtl string data */
+           0,                           /* addtl numeric data 1 */
+           0,                           /* addtl numeric data 2 */
+           xxstring,
+           NULL,
+           NULL
+           );
+#endif /* FNFLOAT */
+    x = cmfdb(&kw);                     /* Parse a keyword or a number */
+    debug(F111,"boolval cmfdb","",x);
+    if (x < 0) {
+        if (x == -3)
+          x = -2;
+        return(x);
+    }
+    debug(F111,"boolval switch","",cmresult.fcode);
+    switch (cmresult.fcode) {           /* What did we get? */
+#ifdef FNFLOAT
+      case _CMFLD:                      /* A "field" */
+        if (isfloat(cmresult.sresult,0)) { /* A floating-point number? */
+            f1 = floatval;              /* Yes, get its value */
+            f1flag = 1;                 /* remember we did this */
+            ifc = 9999;                 /* Set special "if-code" */
+        } else
+          return(-2);
+#endif /* FNFLOAT */
+      case _CMNUM:                      /* A number... */
+        ifc = 9999;                     /* Set special "if-code" */
+        break;
+      case _CMKEY:                      /* A keyword */
+        ifc = cmresult.nresult;         /* Get if-code */
+        break;
+      default:
+        return(-2);
+    }
+    switch (ifc) {                      /* set z = 1 for true, 0 for false */
+      case 9999:                        /* Number */
+#ifdef FNFLOAT
+        if (f1flag) {
+            z = (f1 == 0.0) ? 0 : 1;
+        } else
+#endif /* FNFLOAT */
+        z = (cmresult.nresult == 0) ? 0 : 1;
+        break;
+      case XXIFLP:                      /* Left paren */
+        if (pcount == 0 && ifargs > 0)
+          return(-2);
+        parens = 1;
+        pcount++;
+        ifargs++;
+        *bx++ = '(';
+        goto ifagain;
+      case XXIFRP:                      /* Right paren */
+        if (!parens)
+          return(-2);
+        if (--pcount < 0)
+          return(-2);
+        ifargs++;
+        *bx++ = ')';
+        *bx = NUL;
+        if (pcount == 0)
+          goto ifend;
+        goto ifagain;
+      case XXIFAN:                      /* AND (&&) */
+        ifargs++;
+        if (!ecount)
+          return(-2);
+        *bx++ = '&';
+        goto ifagain;
+      case XXIFOR:                      /* OR (||) */
+        ifargs++;
+        if (!ecount)
+          return(-2);
+        *bx++ = '|';
+        goto ifagain;
+      case XXIFNO:                      /* IF NOT [ NOT [ NOT ... ] ] */
+        if (bx > boolval) {             /* evala() doesn't like cascaded */
+            if (*(bx-1) == '!') {       /* unary operators... */
+                *(bx-1) = NUL;          /* So here, two wrongs make a right. */
+                bx--;
+            } else {
+                *bx++ = '!';
+            }
+        } else {
+            *bx++ = '!';
+        }
+        ifargs++;
+        goto ifagain;
+      case XXIFTR:                      /* IF TRUE */
+        z = 1;
+        debug(F101,"if true","",z);
+        ifargs += 1;
+        break;
+      case XXIFNT:                      /* IF FALSE */
+        z = 0;
+        debug(F101,"if true","",z);
+        ifargs += 1;
+        break;
+      case XXIFSU:                      /* IF SUCCESS */
+        z = ( success != 0 ) ? 1 : 0;
+        debug(F101,"if success","",z);
+        ifargs += 1;
+        break;
+      case XXIFFA:                      /* IF FAILURE */
+        z = ( success == 0 ) ? 1 : 0;
+        debug(F101,"if failure","",z);
+        ifargs += 1;
+        break;
+
+      case XXIFDE:                      /* IF DEFINED */
+        if ((x = cmfld("Macro or variable name","",&s,NULL)) < 0)
+          return((x == -3) ? -2 : x);
+
+        if (*s == CMDQ) {
+            char * lp;
+            char line[256];
+            int t, x;
+            if (*(s+1) == 'f' || *(s+1) == 'F') { /* Built-in function */
+                extern struct keytab fnctab[];
+                extern int nfuncs;
+                ckstrncpy(line,s+2,256);
+                if (line[0]) {
+                    lp = ckstrchr(line,'(');
+                    if (lp) *lp = NUL;
+                    x = lookup(fnctab,line,nfuncs,&t);
+                    z = x > -1;
+                }
+                debug(F111,"if defined function",line,z);
+            } else if (*(s+1) == 'v' || *(s+1) == 'V') { /* 8.0.200 */
+                extern struct keytab vartab[];
+                extern int nvars;
+                z = 0;
+                if (*(s+2) == '(') {
+                    ckstrncpy(line,s+3,256);
+                    if (line[0]) {
+                        lp = ckstrchr(line,')');
+                        if (lp) *lp = NUL;
+                        x = lookup(vartab,line,nvars,&t);
+                        z = x > -1;
+                       if (z) {        /* 8.0.203 */
+                           int t;      /* It must have a value to succeed */
+                           t = 255;    /* as in C-Kermit 6.0 and 7.0 */
+                           lp = line;  /* (this was broken in 8.0.200-201) */
+                           zzstring(s,&lp,&t);
+                           t = strlen(line);
+                           z = line[0] ? 1 : 0;
+                       }
+                    }
+                }
+                debug(F111,"if defined variable",line,z);
+            } else {
+                z = chkvar(s);          /* Starts with backslash */
+                if (z > 0) {            /* Yes... */
+                    t = 255;            /* than buffer so if zzstring fails  */
+                    lp = line;          /* check for that -- overflow means */
+                    line[0] = NUL;      /* the quantity is defined. */
+                    x = zzstring(s,&lp,&t);
+                    if ((x < 0 && t != 255) || !line[0])
+                      z = 0;
+                    debug(F111,"if defined zzstring",line,z);
+                    debug(F101,"if defined zzstring t","",t);
+                }
+            }
+        } else {
+            z = (mxlook(mactab,s,nmac) > -1); /* Look for exact match */
+        }
+        debug(F111,"if defined final",s,z);
+        ifargs += 2;
+        break;
+
+      case XXIFDC: {                    /* IF DECLARED */
+          char * lp;
+          char line[32];
+          int j, k, t, x;
+          if ((x = cmfld("Array name","",&s,NULL)) < 0)
+            return((x == -3) ? -2 : x);
+          if (*s == CMDQ) {
+              if (*(s+1) != '&') {
+                  t = 31;
+                  lp = line;
+                  line[0] = NUL;
+                  x = zzstring(s,&lp,&t);
+                  s = line;
+              }
+          }
+          z = 0;
+          if ((x = arraybounds(s,&j,&k)) > -1) {
+              if (a_ptr[x]) {
+                  if (j < 1)
+                    z = 1;
+                  else if (j <= a_dim[x])
+                    z = 1;
+                  if (z == 1 && k > a_dim[x])
+                    z = 0;
+              }
+          }
+          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 );
+        if (cx == XXWHI) count[cmdlvl] += 2; /* Don't ask... */
+        debug(F101,"if count","",z);
+        ifargs += 1;
+        break;
+
+      case XXIFEX:                      /* IF EXIST */
+#ifdef CK_TMPDIR
+      case XXIFDI:                      /* IF DIRECTORY */
+#endif /* CK_TMPDIR */
+      case XXIFAB:                      /* IF ABSOLUTE */
+        if ((x = cmfld(
+                       ((ifc == XXIFDI) ? "Directory name" : "File"),
+                       "",&s,
+#ifdef OS2
+                       NULL             /* This allows \'s in filenames */
+#else
+                       xxstring
+#endif /* OS2 */
+                       )) < 0) {
+            if (x == -3) {
+                extern int cmflgs;
+                if (cmflgs == 1) {
+                    printf("?File or directory name required\n");
+                    return(-9);
+                }
+            } else return(x);
+        }
+        s = brstrip(s);
+        if (ifc == XXIFAB) {
+            z = isabsolute(s);
+        } else if (ifc == XXIFEX) {
+            z = (zgetfs(s) > -1L);
+            debug(F101,"if exist 1","",z);
+#ifdef OS2
+            if (!z) {                   /* File not found. */
+                int t;                  /* Try expanding variables */
+                t = LINBUFSIZ-1;        /* and looking again. */
+                lp = line;
+                zzstring(s,&lp,&t);
+                s = line;
+                z = ( zchki(s) > -1L );
+                debug(F101,"if exist 2","",z);
+            }
+#endif /* OS2 */
+#ifdef CK_TMPDIR
+        } else {
+#ifdef VMS
+            z = (zchki(s) == -2)
+#else
+/* Because this doesn't catch $DISK1:[FOO]BLAH.DIR;1 */
+            z = isdir(s)
+#ifdef OS2
+              || (isalpha(s[0]) && s[1] == ':' && s[2] == NUL)
+#endif /* OS2 */
+#endif /* VMS */
+              ;
+            debug(F101,"if directory 1","",z);
+
+            if (!z) {                  /* File not found. */
+                int t;                  /* Try expanding variables */
+                t = LINBUFSIZ-1;        /* and looking again. */
+                lp = line;
+                zzstring(s,&lp,&t);
+                s = line;
+                z = isdir(s)
+#ifdef OS2
+                  || (isalpha(s[0]) && s[1] == ':' && s[2] == NUL)
+#endif /* OS2 */
+                    ;
+                debug(F101,"if directory 2","",z);
+            }
+#endif /* CK_TMPDIR */
+        }
+        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);
+        }
+        s = brstrip(s);                 /* Strip braces */
+        x = (int)strlen(s);
+        if (x > LINBUFSIZ-1) {
+            printf("?IF: strings too long\n");
+            return(-2);
+        }
+        lp = line;                      /* lp points to first string */
+        ckstrncpy(line,s,LINBUFSIZ);
+        if ((y = cmfld("second word or variable name","",&s,xxstring)) < 0) {
+            if (y == -3) {
+                printf("?Text required\n");
+                return(-9);
+            } else return(y);
+        }
+        s = brstrip(s);
+        y = (int)strlen(s);
+        if (x + y + 2 > LINBUFSIZ) {
+            printf("?IF: strings too long\n");
+            return(-2);
+        }
+        tp = lp + x + 2;                /* tp points to second string */
+        strcpy(tp,s);                   /* safe (checked) */
+        x = ckstrcmp(lp,tp,-1,inpcas[cmdlvl]); /* Use longest length */
+        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;
+        }
+        debug(F101,"IF EQ result","",z);
+        ifargs += 3;
+        break;
+
+      case XXIFVE:                      /* IF VERSION */
+      case XXIFAE:                      /* IF (arithmetically) = */
+      case XXIFNQ:                      /* IF != (not arithmetically equal) */
+      case XXIFLT:                      /* IF <  */
+      case XXIFLE:                      /* IF <= */
+      case XXIFGE:                      /* IF >= */
+      case XXIFGT: {                    /* IF >  */
+
+        /* Really should use longs here... */
+        /* But cmnum parses ints. */
+        int xx, n1 = 0, n2 = 0;
+        if (ifc == XXIFVE) {
+            n1 = (int) vernum;
+        } else {
+            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);
+            ckstrncpy(line,s,LINBUFSIZ);
+            lp = brstrip(line);
+            debug(F110,"xxifgt exp1",lp,0);
+
+/* The following bit is for compatibility with old versions of MS-DOS Kermit */
+
+            if (!ckstrcmp(lp,"count",5,0)) {
+                n1 = count[cmdlvl];
+            } else if (!ckstrcmp(lp,"version",7,0)) {
+                n1 = (int) vernum;
+            } else if (!ckstrcmp(lp,"argc",4,0)) {
+                n1 = (int) macargc[maclvl];
+            } else {
+
+/* End of compatibility bit */
+
+#ifdef FNFLOAT
+                if (isfloat(lp,0) > 1) { /* Allow floating-point comparisons */
+                    f1 = floatval;
+                    f1flag = 1;
+                } else
+#endif /* FNFLOAT */
+                  if (chknum(lp)) {
+                      n1 = atoi(lp);
+                  } else {              /* Check for arithmetic expression */
+                      q = evala(lp);    /* cmnum() does this but ... */
+                      if (chknum(q))    /* we're not using cmnum(). */
+                        n1 = atoi(q);
+                      else
+                        return(-2);
+                  }
+            }
+        }
+        y = cmfld("number or variable name","",&s,xxstring);
+        if (y == -3) {
+            printf("?Quantity required\n");
+            return(-9);
+        }
+        if (y < 0) return(y);
+        s = brstrip(s);
+        if (!*s) return(-2);
+        if (ifc == XXIFVE) {
+            tp = line;
+        } else {
+            x = (int)strlen(lp);
+            tp = line + x + 2;
+        }
+        ckstrncpy(tp,s,LINBUFSIZ-x-2);
+        debug(F110,"xxifgt exp2",tp,0);
+        if (!ckstrcmp(tp,"count",5,0)) {
+            n2 = count[cmdlvl];
+        } else if (!ckstrcmp(tp,"version",7,0)) {
+            n2 = (int) vernum;
+        } else if (!ckstrcmp(tp,"argc",4,0)) {
+            n2 = (int) macargc[maclvl];
+        } else {
+#ifdef FNFLOAT
+            if (isfloat(tp,0) > 1) {
+                f2 = floatval;
+                f2flag = 1;
+            } else
+#endif /* FNFLOAT */
+            if (chknum(tp)) {
+                n2 = atoi(tp);
+            } else {
+                q = evala(tp);
+                if (chknum(q))
+                  n2 = atoi(q);
+                else
+                  return(-2);
+            }
+        }
+        xx = (ifc == XXIFVE) ? XXIFGE : ifc;
+
+#ifdef FNFLOAT
+        if (f1flag && !f2flag) {
+            f2 = (CKFLOAT)n2;
+            f2flag = 1;
+        }
+        if (f2flag && !f1flag)
+          f1 = (CKFLOAT)n1;
+        if (f1flag)
+          z = ((f1 <  f2 && xx == XXIFLT)
+               || (f1 != f2 && xx == XXIFNQ)
+               || (f1 <= f2 && xx == XXIFLE)
+               || (f1 == f2 && xx == XXIFAE)
+               || (f1 >= f2 && xx == XXIFGE)
+               || (f1 >  f2 && xx == XXIFGT));
+        else
+#endif /* FNFLOAT */
+          z = ((n1 <  n2 && xx == XXIFLT)
+               || (n1 != n2 && xx == XXIFNQ)
+               || (n1 <= n2 && xx == XXIFLE)
+               || (n1 == n2 && xx == XXIFAE)
+               || (n1 >= n2 && xx == XXIFGE)
+               || (n1 >  n2 && xx == XXIFGT));
+        debug(F101,"xxifge z","",z);
+        if (ifc == XXIFVE)
+          ifargs += 2;
+        else
+          ifargs += 3;
+        break;
+      }
+
+      case XXIFNU:                      /* IF NUMERIC */
+        x = cmfld("variable name or constant","",&s,NULL);
+        if (x == -3) {
+            extern int cmflgs;
+            if (cmflgs == 1) {
+                printf("?Quantity required\n");
+                return(-9);
+            }
+        } else if (x < 0)
+          return(x);
+        x = LINBUFSIZ-1;
+        lp = line;
+        zzstring(s,&lp,&x);
+        lp = line;
+        debug(F110,"xxifnu quantity",lp,0);
+        z = chknum(lp);
+#ifdef COMMENT
+/*
+  This works, but it's not wise -- IF NUMERIC is mostly used to see if a
+  string really does contain only numeric characters.  If they want to force
+  evaluation, they can use \feval() on the argument string.
+*/
+        if (!z) {                       /* Not a number */
+            x_ifnum = 1;                /* Avoid "eval" error messages */
+            q = evala(lp);              /* Maybe it's an expression */
+            z = chknum(q);              /* that evaluates to a number */
+            x_ifnum = 0;                /* Put eval messages back to normal */
+            if (z) debug(F110,"xxifnu exp",lp,0);
+        }
+#endif /* COMMENT */
+        debug(F101,"xxifnu chknum","",z);
+        ifargs += 2;
+        break;
+
+#ifdef ZFCDAT
+      case XXIFNE: {                    /* IF NEWER */
+        char d1[20], * d2;              /* Buffers for 2 dates */
+        if ((z = cmifi("First file","",&s,&y,xxstring)) < 0)
+          return(z);
+        ckstrncpy(d1,zfcdat(s),20);
+        if ((z = cmifi("Second file","",&s,&y,xxstring)) < 0)
+          return(z);
+        d2 = zfcdat(s);
+        if ((int)strlen(d1) != 17 || (int)strlen(d2) != 17) {
+            printf("?Failure to get file date\n");
+            return(-9);
+        }
+        debug(F110,"xxifnewer d1",d1,0);
+        debug(F110,"xxifnewer d2",d2,0);
+        z = (strcmp(d1,d2) > 0) ? 1 : 0;
+        debug(F101,"xxifnewer","",z);
+        ifargs += 2;
+        break;
+      }
+#endif /* ZFCDAT */
+
+#ifdef CK_IFRO
+      case XXIFRO:                      /* REMOTE-ONLY advisory */
+        ifargs++;
+#ifdef NOLOCAL
+        z = 1;
+#else
+        z = remonly;
+#endif /* NOLOCAL */
+        break;
+#endif /* CK_IFRO */
+
+      case XXIFAL:                      /* ALARM */
+        ifargs++;
+        debug(F101,"IF ALARM ck_alarm","",ck_alarm);
+        debug(F110,"IF ALARM alrm_date",alrm_date,0);
+        debug(F110,"IF ALARM alrm_time",alrm_time,0);
+
+        if (ck_alarm < 1L || alrm_date[0] < '0' || alrm_time[0] < '0') {
+            z = 0;                      /* ALARM not SET */
+            break;                      /* so IF ALARM fails */
+        }
+        /* Get current date and time */
+        ckstrncpy(tmpbuf,ckcvtdate("",1),TMPBUFSIZ);
+        s = tmpbuf;
+        s[8] = NUL;
+        z = (int) strncmp(tmpbuf,alrm_date,8); /* Compare dates */
+        debug(F101,"IF ALARM date z","",z);
+        if (z == 0) {                   /* Dates are the same */
+            /* Compare times */
+            z = (tod2sec(tmpbuf+9) >= atol(alrm_time)) ? 1 : -1;
+            debug(F101,"IF ALARM time z","",z);
+        }
+        tmpbuf[0] = NUL;                /* z >= 0 if alarm is passed */
+        z = ((z >= 0) ? 1 : 0);         /* z <  0 otherwise */
+        debug(F101,"IF ALARM final z","",z);
+        break;
+
+      case XXIFOP:                      /* IF OPEN */
+        if ((x = cmkey(iotab,niot,"file or log","",xxstring)) < 0)
+          return(x);
+        if (x == 9999 || x == ZSTDIO) {
+            bgchk();                    /* Check background status */
+            z = pflag ? 1 : 0;
+        } else if (x == 8888) {
+            z = local ? ttchk() > -1 : 0;
+#ifdef CKLOGDIAL
+        } else if (x == 7777) {
+            extern int dialog;
+            z = dialog ? 1 : 0;
+#endif /* CKLOGDIAL */
+        } else
+          z = (chkfn(x) > 0) ? 1 : 0;
+        ifargs += 1;
+        break;
+
+      case XXIFSD:                      /* Started-From-Dialer */
+#ifdef OS2
+        z = StartedFromDialer;
+#else
+        z = 0;
+#endif /* OS2 */
+        break;
+
+      case XXIFTM:                      /* Terminal-Macro */
+#ifdef OS2
+        z = cmdstk[cmdlvl].ccflgs & CF_KMAC;
+#else
+        z = 0;
+#endif /* OS2 */
+        break;
+
+      case XXIFEM:                      /* Emulation is active */
+#ifdef OS2
+        z = 1;
+#else
+        z = 0;
+#endif /* OS2 */
+        break;
+
+      case XXIFIK:                      /* Running as IKSD? */
+        z = inserver;
+        break;
+
+      case XXIFTA:                      /* Connection is TAPI */
+        z = 0;
+#ifndef NODIAL
+#ifdef CK_TAPI
+        if (local && !network && tttapi)
+          z = 1;
+#endif /* CK_TAPI */
+#endif /* NODIAL */
+        break;
+
+      case XXIFMA:                      /* IF MATCH */
+        x = cmfld("String or variable","",&s,xxstring);
+        if (x == -3) {
+            extern int cmflgs;
+            if (cmflgs == 1) {
+                printf("?String required\n");
+                return(-9);
+            }
+        } else if (x < 0)
+          return(x);
+        ckstrncpy(line,s,LINBUFSIZ);
+        s = brstrip(line);
+        debug(F110,"xxifma string",line,0);
+        x = cmfld("Pattern","",&p,xxstring);
+        if (x == -3) {
+            extern int cmflgs;
+            if (cmflgs == 1) {
+                printf("?Pattern required\n");
+                return(-9);
+            }
+        } else if (x < 0)
+          return(x);
+        ckstrncpy(tmpbuf,p,TMPBUFSIZ);
+        p = brstrip(tmpbuf);
+        debug(F110,"xxifma pattern",tmpbuf,0);
+        z = ckmatch(p,s,inpcas[cmdlvl],1);
+        break;
+
+      case XXIFFL: {                    /* IF FLAG */
+          extern int ooflag;
+          z = ooflag;
+          break;
+      }
+      case XXIFAV: {                    /* IF AVAILABLE */
+          if ((x = cmkey(availtab,availtabn,"","",xxstring)) < 0)
+            return(x);
+          switch (x) {
+            case AV_KRB4:
+              z = ck_krb4_is_installed();
+              break;
+            case AV_KRB5:
+              z = ck_krb5_is_installed();
+              break;
+            case AV_SRP:
+              z = ck_srp_is_installed();
+              break;
+            case AV_SSL:
+              z = ck_ssleay_is_installed();
+              break;
+            case AV_NTLM:
+              z = ck_ntlm_is_installed();
+              break;
+            case AV_CRYPTO:
+              z = ck_crypt_is_installed();
+              break;
+            case AV_SSH:
+              z = ck_ssh_is_installed();
+              break;
+            default:
+              z = 0;
+          }
+          break;
+      }
+      case XXIFAT:                      /* IF ASKTIMEOUT */
+        z = asktimedout;
+        break;
+
+      case XXIFRD:                      /* IF READABLE */
+      case XXIFWR:                      /* IF WRITEABLE */
+        if ((x = cmfld("File or directory name",
+                       "",
+                       &s,
+#ifdef OS2
+                       NULL             /* This allows \'s in filenames */
+#else
+                       xxstring
+#endif /* OS2 */
+                       )) < 0) {
+            if (x == -3) {
+                extern int cmflgs;
+                if (cmflgs == 1) {
+                    printf("?File or directory name required\n");
+                    return(-9);
+                }
+            } else return(x);
+        }
+        s = brstrip(s);
+/*
+  zchk[io]() do not do what we want here for directories, so we set
+  a global flag telling it to behave specially in this case.  Othewise
+  we'd have to change the API and change all ck?fio.c modules accordingly.
+*/
+        y = 0;                          /* Try-again control */
+#ifdef OS2
+  ifrdagain:
+#endif /* OS2 */
+        if (ifc == XXIFRD) {            /* IF READABLE */
+            zchkid = 1;
+            z = zchki(s) > -1;
+            zchkid = 0;
+        } else if (ifc == XXIFWR) {     /* IF WRITEABLE */
+            zchkod = 1;
+            z = zchko(s) > -1;
+            zchkod = 0;
+        }
+#ifdef OS2
+        if (!z && !y) {                 /* File not found. */
+            int t;                      /* Try expanding variables */
+            t = LINBUFSIZ-1;            /* and looking again. */
+            lp = line;
+            zzstring(s,&lp,&t);
+            s = line;
+            z = zchko(s) > -1;
+            y++;
+            goto ifrdagain;
+        }
+#endif /* OS2 */
+        ifargs += 2;
+        break;
+      case XXIFQU:                      /* IF QUIET */
+        z = quiet ? 1 : 0;
+        debug(F101,"if quiet","",z);
+        ifargs += 1;
+        break;
+
+      case XXIFWI:                      /* WILD */
+        if ((x = cmfld("File specification","",&s,xxstring)) < 0) return(x);
+        z = iswild(s);
+        break;
+
+      case XXIFCK:                      /* C-KERMIT */
+#ifdef OS2
+        z = 0;
+#else
+        z = 1;
+#endif /* OS2 */
+        break;
+
+      case XXIFK9:                      /* K-95 */
+#ifdef OS2
+        z = 1;
+#else
+        z = 0;
+#endif /* OS2 */
+        break;
+
+      case XXIFGU:                      /* GUI */
+#ifdef KUI
+        z = 1;
+#else
+        z = 0;
+#endif /* KUI */
+        break;
+
+      case XXIFMS:                      /* MS-KERMIT */
+        z = 0;
+        break;
+
+      case XXIFLO:                      /* IF LOCAL */
+        z = local ? 1 : 0;
+        break;
+
+      case XXIFCM: {                    /* IF COMMAND */
+          extern struct keytab cmdtab[];
+          extern int ncmd;
+          if ((x = cmfld("Word","",&s,xxstring)) < 0)
+            return(x);
+          z = lookup(cmdtab,s,ncmd,&y);
+          z = (z == -2 || z > -1) ? 1 : 0;
+          break;
+      }
+#ifdef CKFLOAT
+      case XXIFFP:                      /* IF FLOAT */
+        if ((x = cmfld("Number","",&s,xxstring)) < 0)
+          if (x != -3)                  /* e.g. empty variable */
+            return(x);
+        z = isfloat(s,0);
+        break;
+#endif /* CKFLOAT */
+
+      case XXIFKB:                      /* KBHIT */
+        z = conchk();
+        if (z < 0) z = 0;
+        if (z > 1) z = 1;
+        break;
+
+      case XXIFKG: {                    /* KERBANG */
+          extern int cfilef;
+          z = (xcmdsrc == 0) ? 0 : cfilef;
+          break;
+      }
+
+      default:                          /* Shouldn't happen */
+        return(-2);
+    } /* end of switch */
+
+    if (z)
+      *bx++ = '1';
+    else
+      *bx++ = '0';
+    *bx = NUL;
+    if (bx > boolval + BOOLLEN - 2) {
+        printf("?Boolean expression too long");
+        return(-9);
+    }
+    ecount++;                           /* Expression counter */
+    debug(F101,"boolexp parens","",parens);
+    debug(F101,"boolexp pcount","",pcount);
+    if (parens && pcount > 0)
+      goto ifagain;
+
+  ifend:                                /* No more - done */
+    *bx = NUL;
+    z = atoi(evalx(boolval));
+    debug(F111,"boolexp boolval",boolval,z);
+    return(z);
+}
+
+/*  D O I F  --  Do the IF command  */
+
+int
+doif(cx) int cx; {
+    int x, y, z; char *s, *p;
+    char *q;
+#ifdef OS2
+    extern int keymac;
+#endif /* OS2 */
+
+    debug(F101,"doif cx","",cx);
+
+    z = boolexp(cx);                    /* Evaluate the condition(s) */
+    debug(F010,"doif cmdbuf",cmdbuf,0);
+    debug(F101,"doif boolexp","",z);
+    if (z < 0)
+      return(z);
+
+    if (cx == XXIF) {                   /* Allow IF to have XIF semantics. */
+        char * p;
+        p = cmpeek();
+        if (!p) p = "";
+        while (*p) {
+            if (*p == SP || *p == HT)
+              p++;
+            else
+              break;
+        }
+        if (*p == '{')
+          cx = XXIFX;
+    }
+    switch (cx) {                       /* Separate handling for IF and XIF */
+
+      case XXASSER:                     /* And ASSERT */
+        if ((x = cmcfm()) < 0)
+          return(x);
+        return(success = z);
+
+      case XXIF:                        /* This is IF... */
+        ifcmd[cmdlvl] = 1;              /* We just completed an IF command */
+        debug(F101,"doif condition","",z);
+        if (z) {                        /* Condition is true */
+            iftest[cmdlvl] = 1;         /* Remember that IF succeeded */
+            if (maclvl > -1) {          /* In macro, */
+                pushcmd(NULL);          /* save rest of command. */
+            } else if (tlevel > -1) {   /* In take file, */
+                debug(F100, "doif: pushing command", "", 0);
+                pushcmd(NULL);          /* 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;
+          debug(F110,"doif THEN part",s,-54);
+          if (litcmd(&p,&lp,LINBUFSIZ - 1) < 0) { /* Quote THEN-part */
+              return(-2);
+          }
+          debug(F111,"doif THEN part 2",line,z);
+
+          while (*p == SP) p++;         /* Strip trailing spaces */
+          ifcmd[cmdlvl] = 0;            /* Assume ELSE part in same line */
+          iftest[cmdlvl] = z ? 1 : 0;
+          if (*p) {                     /* At end? */
+              if (!z) {                 /* No, use ELSE-part, if any */
+                  for (i = 0; i < 4; i++) e[i] = *p++;
+                  if (ckstrcmp(e,"else",4,0)) /* See if we have an ELSE */
+                    return(-2);         /* Something else - error. */
+                  debug(F010,"doif ELSE line 1",p,0);
+                  while (*p == SP) p++; /* Skip spaces */
+                  if (*p != '{') {      /* Brace ELSE part if necessary */
+                      ckmakmsg(tmpbuf,TMPBUFSIZ,"{",p," }",NULL);
+                      p = tmpbuf;
+                      debug(F010,"doif ELSE line 2",p,0);
+                  }
+                  lp = line;            /* Write over THEN part... */
+                  *lp = NUL;            /* with ELSE part. */
+                  if (litcmd(&p,&lp,LINBUFSIZ - 2) < 0) {
+                      return(-2);
+                  }
+                  while (*p == SP) p++; /* Strip trailing spaces */
+                  if (*p) return(-2);   /* Should be nothing here. */
+                  debug(F010,"doif ELSE line 3",line,0);
+              }
+          } else {                      /* At end, treat like an IF command */
+              if (!z) line[0] = NUL;    /* Condition not true and no ELSE */
+              ifcmd[cmdlvl] = 1;        /* Allow ELSE on next line */
+              debug(F101,"IF condition","",z);
+          }
+          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,cmdstk[cmdlvl].ccflgs | CF_IMAC);
+          }
+          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;
+          ifcp += ckstrncpy(ifcp,"{ \\flit(if ( not ",IFCONDLEN);
+#ifdef COMMENT
+/*
+  This doesn't work because it breaks on the first left brace, which does
+  not necessarily start the command list, e.g. "while equal \%a {\35}".
+*/
+          while (*p != '{' && *p != NUL) *ifcp++ = *p++;
+          p = " ) goto _..bot) } ";
+          while (*ifcp++ = *p++) ;
+#else
+/*
+  The command parser sets cmbptr to the spot where it left off parsing in
+  the command buffer.
+*/
+          {
+              extern char * cmbptr;
+              if (cmbptr) {
+                  while (p < cmbptr && *p != NUL)
+                    *ifcp++ = *p++;
+                  p = " ) goto _..bot) } ";
+                  while ((*ifcp++ = *p++)) ;
+              } else {
+                  printf("?Internal error parsing WHILE condition\n");
+                  return(-9);
+              }
+          }
+#endif /* COMMENT */
+
+          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,LINBUFSIZ - 2) < 0) { /* Quote object command */
+              return(-2);
+          }
+          debug(F101,"WHILE body",line,-54);
+          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);     /* safe (prechecked) */
+                  strcat(p,line);       /* safe (prechecked) */
+                  debug(F010,"WHILE dodo",p,0);
+                  dodo(x,p,cmdstk[cmdlvl].ccflgs | CF_IMAC);
+                  free(p);
+                  p = NULL;
+              } 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; {
+#ifndef NOSPL
+    extern int tra_cmd;
+#endif /* NOSPL */
+#ifndef NOLOCAL
+#ifdef OS2
+    extern int term_io;
+    int term_io_sav = term_io;
+#endif /* OS2 */
+#endif /* NOLOCAL */
+    int slen;
+
+    debug(F110,"dotake",s,0);
+    if (!s) s = "";
+    if (!*s) return(success = 0);
+    slen = strlen(s);
+    debug(F101,"dotake len","",slen);
+
+    if ((tfile[++tlevel] = fopen(s,"r")) == NULL) {
+        perror(s);
+        debug(F110,"dotake fail",s,0);
+        tlevel--;
+        return(success = 0);
+    } else {
+        tfline[tlevel] = 0;             /* Line counter */
+#ifdef VMS
+        conres();                       /* So Ctrl-C will work */
+#endif /* VMS */
+#ifndef NOLOCAL
+#ifdef OS2
+        term_io = 0;                    /* Disable Terminal Emulator I/O */
+#endif /* OS2 */
+#endif /* NOLOCAL */
+#ifndef NOSPL
+        cmdlvl++;                       /* Entering a new command level */
+        debug(F111,"CMD +F",s,cmdlvl);
+        debug(F101,"dotake cmdlvl","",cmdlvl);
+        debug(F101,"dotake tlevel","",tlevel);
+        if (cmdlvl > CMDSTKL) {
+            debug(F100,"dotake stack overflow","",0);
+            cmdlvl--;
+            debug(F111,"CMD*-F",s,cmdlvl);
+            fclose(tfile[tlevel--]);
+            printf("?TAKE files and/or DO commands nested too deeply\n");
+            return(success = 0);
+        }
+        if (tfnam[tlevel]) {            /* Copy the filename */
+            free(tfnam[tlevel]);
+            tfnam[tlevel] = NULL;
+        }
+        if ((tfnam[tlevel] = malloc(strlen(s) + 1))) {
+            strcpy(tfnam[tlevel],s);    /* safe */
+        } else {
+            printf("?Memory allocation failure\n");
+            return(success = 0);
+        }
+        ifcmd[cmdlvl] = 0;              /* Set variables for this cmd file */
+        iftest[cmdlvl] = 0;
+        count[cmdlvl]  = count[cmdlvl-1];  /* Inherit this */
+        intime[cmdlvl] = intime[cmdlvl-1]; /* Inherit this */
+        inpcas[cmdlvl] = inpcas[cmdlvl-1]; /* Inherit this */
+        takerr[cmdlvl] = takerr[cmdlvl-1]; /* Inherit this */
+        merror[cmdlvl] = merror[cmdlvl-1]; /* Inherit this */
+        xquiet[cmdlvl] = quiet;
+        xcmdsrc = CMD_TF;
+        cmdstk[cmdlvl].src = CMD_TF;    /* Say we're in a TAKE file */
+        cmdstk[cmdlvl].lvl = tlevel;    /* nested at this level */
+        cmdstk[cmdlvl].ccflgs = cmdstk[cmdlvl-1].ccflgs;
+#else
+        takerr[tlevel] = takerr[tlevel-1]; /* Inherit this */
+#endif /* NOSPL */
+    }
+#ifndef NOSPL
+    if (tra_cmd)
+      printf("[%d] +F: \"%s\"\n",cmdlvl,s);
+#endif /* NOSPL */
+#ifndef NOLOCAL
+#ifdef OS2
+    term_io = term_io_sav;
+#endif /* OS2 */
+#endif /* NOLOCAL */
+    return(1);
+}
+#endif /* NOICP */
diff --git a/.pc/030_fix-if-else.patch/ckuusr.c b/.pc/030_fix-if-else.patch/ckuusr.c
new file mode 100644 (file)
index 0000000..8545f89
--- /dev/null
@@ -0,0 +1,13121 @@
+#ifdef SSHTEST
+#define SSHBUILTIN
+#endif /* SSHTEST */
+
+#include "ckcsym.h"
+char *userv = "User Interface 8.0.278, 12 Mar 2004";
+
+/*  C K U U S R --  "User Interface" for C-Kermit (Part 1)  */
+
+/*
+  Authors:
+    Frank da Cruz <fdc@columbia.edu>,
+      The Kermit Project, Columbia University, New York City
+    Jeffrey E Altman <jaltman@secure-endpoints.com>
+      Secure Endpoints Inc., New York City
+
+  Copyright (C) 1985, 2004,
+    Trustees of Columbia University in the City of New York.
+    All rights reserved.  See the C-Kermit COPYING.TXT file or the
+    copyright text in the ckcmai.c module for disclaimer and permissions.
+*/
+
+/*
+  Originally the entire user interface was in one module, ckuusr.c.  Over
+  the years it has been split into many modules: ckuus2.c, ckuus3.c, ...,
+  ckuus7.c.  ckuus2.c contains the HELP command parser and help-text strings;
+  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 different platforms -- 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:
+
+  . Set parameters via global variables like duplex, speed, ttname, etc.  See
+    ckmain.c for the declarations and descriptions of these variables.
+
+  . 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.
+
+  . 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 an "as-name" - the name to send file(s) under, or
+       the name under which to store incoming file(s); must not be wild.
+       A null or empty value means to use the file's own name.
+     cmlist is a list of 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.
+*/
+
+/* Includes */
+
+#ifdef MULTINET
+#define MULTINET_OLD_STYLE             /* Leave select prototype undefined */
+#endif /* MULTINET */
+
+#include "ckcdeb.h"
+#include "ckcasc.h"
+#include "ckcker.h"
+#include "ckcnet.h"                    /* Network symbols */
+#include "ckuusr.h"
+#include "ckcxla.h"
+
+int g_fncact = -1;                     /* Needed for NOICP builds */
+int noinit = 0;                                /* Flag for skipping init file */
+int nscanfile = SCANFILEBUF;
+
+int rcdactive = 0;                     /* RCD active */
+int keepallchars = 0;                  /* See cmfld() */
+
+int locus = 1;                         /* Current LOCUS is LOCAL */
+#ifdef OS2
+int autolocus = 2;                     /* Automatic LOCUS switching: ASK */
+#else /* OS2 */
+int autolocus = 1;                     /* Automatic LOCUS switching enabled */
+#endif /* OS2 */
+
+#ifndef NOICP
+#ifdef CKLEARN
+#ifdef VMS
+#include <time.h>                      /* For CKLEARN */
+#endif /* VMS */
+#endif /* CKLEARN */
+#ifdef OS2
+#ifndef NT
+#define INCL_NOPM
+#define INCL_VIO                       /* Needed for ckocon.h */
+#include <os2.h>
+#undef COMMENT
+#else
+#define APIRET ULONG
+#include <windows.h>
+#include <tapi.h>
+#include "cknwin.h"
+#include "ckntap.h"                    /* CK_TAPI definition */
+#endif /* NT */
+#include "ckowin.h"
+#include "ckocon.h"
+extern int tcp_avail;
+extern bool viewonly;
+extern int k95stdout;
+extern int tt_scroll;
+#ifndef NOTERM
+extern tt_status[VNUM];
+#endif /* NOTERM */
+int display_demo = 1;
+#include "ckossh.h"
+#ifdef KUI
+#include "ikui.h"
+#endif /* KUI */
+#endif /* OS2 */
+
+int optlines = 0;
+int didsetlin = 0;
+
+#ifdef NEWFTP
+extern int ftpget, ftpisopen(), doftpres();
+_PROTOTYP(int doftptyp,(int));
+#endif /* NEWFTP */
+
+#ifdef VMS
+extern int batch;
+#endif /* VMS */
+
+#ifdef datageneral
+#include <packets:common.h>
+#define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
+#endif /* datageneral */
+
+extern int xcmdsrc, hints, cmflgs, whyclosed;
+
+char * hlptok = NULL;
+
+#ifdef CK_TTGWSIZ                      /* Whether to use more-prompting */
+int xaskmore = 1;                      /* Momentary setting */
+int saveask  = 1;                      /* Permanent setting */
+#else
+int xaskmore = 0;
+int saveask  = 0;
+#endif /* CK_TTGWSIZ */
+
+#ifndef NOCSETS
+extern int nfilc;
+extern struct keytab fcstab[];
+extern int fcharset;
+#endif /* NOCSETS */
+
+char * g_pswd = NULL;
+int g_pcpt = -1;
+int g_pflg = -1;
+
+extern int cmd_rows, cmd_cols;
+
+#ifdef CKROOT
+extern int ckrooterr;
+#endif /* CKROOT */
+
+extern int inserver, filepeek;
+
+#ifdef CKLEARN
+FILE * learnfp = NULL;
+char * learnfile = NULL;
+int learning = 0;
+#endif /* CKLEARN */
+
+#ifndef NOXFER
+extern int atcapr, atdiso, nfils, moving, protocol, sendmode, epktflg, size,
+  sndsrc, server, displa, fncnv, fnspath, fnrpath, xfermode, urpsiz,
+  spsizf, spsiz, spsizr, spmax, wslotr, prefixing, fncact, reliable,
+  setreliable;
+
+#ifdef IKSDCONF
+extern int iksdcf;
+#endif /* IKSDCONF */
+
+#ifdef CK_LOGIN
+extern int isguest;
+#endif /* CK_LOGIN */
+
+extern long sendstart;
+
+extern char *cmarg, *cmarg2, **cmlist, *dftty;
+
+extern struct keytab fntab[]; extern int nfntab;
+extern struct ck_p ptab[NPROTOS];
+
+int sndcmd = 0;                /* Last command was a SEND-class command. */
+
+int g_xfermode = -1;
+int g_proto  = -1;
+int g_urpsiz = -1;
+int g_spsizf = -1;
+int g_spsiz  = -1;
+int g_spsizr = -1;
+int g_spmax  = -1;
+int g_wslotr = -1;
+int g_prefixing = -1;
+int g_fncnv  = -1;
+int g_fnspath = -1;
+int g_fnrpath = -1;
+int g_fnact  = -1;
+int g_displa = -1;
+int g_spath  = -1;
+int g_rpath  = -1;
+char * g_sfilter = NULL;
+char * g_rfilter = NULL;
+
+extern int patterns;
+#ifdef PATTERNS
+extern char *txtpatterns[], *binpatterns[];
+int g_patterns = -1;
+#endif /* PATTERNS */
+int g_skipbup = -1;
+
+#ifdef PIPESEND
+extern int usepipes, pipesend;
+extern char * sndfilter;
+#endif /* PIPESEND */
+
+#ifndef NOSPL
+extern int sndxlo, sndxhi, sndxin;
+#endif /* NOSPL */
+
+extern char fspec[];                   /* Most recent filespec */
+extern int fspeclen;                   /* Length of fspec[] buffer */
+
+#ifndef NOFRILLS
+extern int rmailf;                     /* MAIL command items */
+extern char optbuf[];
+#endif /* NOFRILLS */
+
+extern int
+  en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
+  en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
+  en_mkd, en_rmd, en_asg;
+
+#ifndef NOMSEND                                /* Multiple SEND */
+extern char *msfiles[];
+int filesinlist = 0;                   /* And ADD ... */
+extern struct filelist * filehead;
+extern struct filelist * filetail;
+extern struct filelist * filenext;
+extern int addlist;
+#endif /* NOMSEND */
+
+static struct keytab addtab[] = {
+#ifdef PATTERNS
+    { "binary-patterns", ADD_BIN, 0 },
+#endif /* PATTERNS */
+#ifndef NOMSEND
+    { "send-list", ADD_SND, 0 },
+#endif /* NOMSEND */
+#ifdef PATTERNS
+    { "text-patterns", ADD_TXT, 0 },
+#endif /* PATTERNS */
+    { "", 0, 0 }
+};
+static int naddtab = sizeof(addtab)/sizeof(struct keytab) - 1;
+
+#ifndef NOCSETS
+struct keytab assoctab[] = {
+    { "file-character-set",     ASSOC_FC, 0 },
+    { "transfer-character-set", ASSOC_TC, 0 },
+    { "xfer-character-set",     ASSOC_TC, CM_INV }
+};
+static int nassoc = sizeof(assoctab)/sizeof(struct keytab);
+extern int afcset[MAXFCSETS+1];                /* Character-set associations */
+extern int axcset[MAXTCSETS+1];
+#endif /* NOCSETS */
+
+#ifndef ADDCMD
+#ifndef NOMSEND
+#define ADDCMD
+#endif /* NOMSEND */
+#ifndef ADDCMD
+#ifdef PATTERNS
+#define ADDCMD
+#endif /* PATTERNS */
+#endif /* ADDCMD */
+#endif /* ADDCMD */
+#endif /* NOXFER */
+
+/* External Kermit Variables, see ckmain.c for description. */
+
+extern xx_strp xxstring;
+extern long xvernum;
+
+extern int local, xitsta, binary, msgflg, escape, duplex, quiet, tlevel,
+  pflag, zincnt, ckxech, carrier, what, nopush, haveline, bye_active;
+#ifdef TNCODE
+extern int debses;
+extern char tn_msg[];
+#endif /* TNCODE */
+
+int sleepcan = 1;
+int g_binary = -1;
+int g_recursive = -1;
+int g_matchdot = -1;
+extern int nolinks;
+
+extern long vernum;
+extern char *versio, *copyright[];
+extern char *ckxsys;
+#ifndef NOHELP
+extern char *introtxt[];
+extern char *newstxt[];
+#endif /* NOHELP */
+
+#ifndef OS2
+#ifndef UNIX
+extern char *PWDCMD;
+#endif /* UNIX */
+extern char *WHOCMD;
+#endif /* OS2 */
+
+extern char ttname[];
+
+extern CHAR sstate;
+
+extern int network;                    /* Have active network connection */
+extern int nettype;                    /* Type of network */
+extern int ttnproto;                    /* NET_TCPB protocol */
+
+#ifndef NODIAL
+extern int dialsta, dialatmo, dialcon, dialcq; /* DIAL status, etc. */
+#endif /* NODIAL */
+
+#ifdef CK_APC
+extern int apcactive, apcstatus;
+#endif /* CK_APC */
+
+#ifndef NOPUSH
+#ifndef NOFRILLS
+extern char editor[];
+extern char editopts[];
+extern char editfile[];
+#endif /* NOFRILLS */
+#endif /* NOPUSH */
+
+#ifdef BROWSER
+extern char browser[];                 /* Web browser application */
+extern char browsopts[];               /* Web browser options */
+extern char browsurl[];                        /* Most recent URL */
+#endif /* BROWSER */
+#ifndef NOFTP
+char ftpapp[CKMAXPATH+1] = { NUL, NUL }; /* ftp executable */
+char ftpopts[128] = { NUL, NUL };      /* ftp command-line options */
+#endif /* NOFTP */
+extern struct keytab onoff[];          /* On/Off keyword table */
+
+#ifdef CK_TMPDIR
+int f_tmpdir = 0;                      /* Directory changed temporarily */
+char savdir[TMPDIRLEN];                        /* For saving current directory */
+#endif /* CK_TMPDIR */
+
+int activecmd = -1;                    /* Keyword index of active command */
+int doconx = -1;                       /* CONNECT-class command active */
+int ooflag = 0;                                /* User-settable on/off flag */
+
+int rcflag = 0;                                /* Pointer to home directory string */
+int repars,                            /* Reparse needed */
+    techo = 0;                         /* Take echo */
+int secho = 1;                         /* SCRIPT echo */
+
+int xitwarn =                  /* Warn about open connection on exit */
+#ifdef NOWARN
+0
+#else
+1
+#endif /* NOWARN */
+;
+
+struct keytab onoffsw[] = {
+    { "/off", 0, 0 },
+    { "/on",  1, 0 }
+};
+
+#ifdef CKEXEC
+struct keytab redirsw[] = {
+    { "/redirect", 1, 0 }
+};
+#endif /* CKEXEC */
+
+#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 */
+int xmitt = 1;                 /* Seconds to wait for each char to echo */
+int xmita = 1;                 /* Action upon timeout */
+
+#define XMI_BIN 1
+#define XMI_TXT 2
+#define XMI_CMD 3
+#define XMI_TRA 4
+#define XMI_VRB 5
+#define XMI_QUI 6
+#define XMI_NOW 7
+#define XMI_NOE 8
+
+static struct keytab xmitsw[] = {      /* TRANSMIT command options */
+    { "/binary",          XMI_BIN, 0 },
+#ifdef PIPESEND
+    { "/command",         XMI_CMD, CM_INV|CM_PSH },
+#endif /* PIPESEND */
+    { "/noecho",          XMI_NOE, 0 },
+    { "/nowait",          XMI_NOW, 0 },
+#ifdef PIPESEND
+    { "/pipe",            XMI_CMD, 0 },
+#endif /* PIPESEND */
+#ifdef COMMENT
+    { "/quiet",           XMI_QUI, 0 },
+#endif /* COMMENT */
+    { "/text",            XMI_TXT, 0 },
+    { "/transparent",     XMI_TRA, 0 },
+#ifdef COMMENT
+    { "/verbose",         XMI_VRB, 0 },
+#endif /* COMMENT */
+    { "", 0, 0 }
+};
+#define NXMITSW sizeof(xmitsw)/sizeof(struct keytab) - 1
+static int nxmitsw = NXMITSW;
+
+#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 char *tmpbuf;                   /* Short temporary string buffer */
+extern int *ifcmd;
+extern int *intime;
+extern int *inpcas;
+#else
+extern char cmdbuf[];                  /* Command buffers */
+extern char atmbuf[];
+extern char line[];                    /* Character buffer for anything */
+extern char tmpbuf[];                  /* Temporary buffer */
+extern int ifcmd[];
+extern int intime[];
+extern int inpcas[];
+#endif /* DCMDBUF */
+
+#ifndef NOSPL
+extern char * prstring[];
+#endif /* NOSPL */
+
+char *lp;                              /* Pointer to line buffer */
+
+#ifndef NOSPL
+int unkmacro = 0;                      /* Flag for in ON_UNKNOWN_COMMAND */
+int oldeval = 0;
+char evalbuf[33];                      /* EVALUATE result */
+extern char * inpbuf;                  /* Buffer for INPUT and REINPUT */
+char *inpbp;                           /* And pointer to same */
+extern char lblbuf[];                  /* Buffer for labels */
+int m_found;                           /* MINPUT result */
+int i_active = 0;                      /* INPUT command is active */
+char *ms[MINPMAX];                     /* Pointers to MINPUT strings */
+static int mp[MINPMAX];                        /* and flags */
+extern int fndiags, fnerror, fnsuccess;        /* Function diagnostics */
+#ifndef NOSEXP
+char * lastsexp = NULL;                        /* S-Expressions */
+char * sexpval = NULL;
+int sexpecho = SET_AUTO;
+#endif /* NOSEXP */
+#endif /* NOSPL */
+
+char psave[PROMPTL] = { NUL };         /* For saving & restoring prompt */
+
+extern int success;                    /* Command success/failure flag */
+extern int cmdlvl;                     /* Current position in command stack */
+
+#ifndef NOSPL
+int                                    /* SET INPUT parameters. */
+/* Note, INPUT TIMEOUT, intime[], is on the command-level stack. */
+  inbufsize = 0,                       /* INPUT buffer size */
+  indef = 1,                           /* default timeout, seconds */
+  inecho = 1,                          /* 1 = echo on */
+  inautodl = 0,                                /* INPUT autodownload */
+  inintr = 1,                          /* INPUT interrupion allowed */
+  innomatch = 0,                       /* INPUT /NOMATCH */
+  insilence = 0;                       /* 0 = no silence constraint */
+
+#ifdef CKFLOAT
+CKFLOAT inscale = 1.0;                 /* Timeout scale factor */
+#endif /* CKFLOAT */
+
+#ifdef OS2
+int interm = 1;                                /* Terminal emulator displays input */
+#endif /* OS2 */
+int maclvl = -1;                       /* Macro nesting level */
+int mecho = 0;                         /* Macro echo, 0 = don't */
+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 *mrval[];
+
+extern char **a_ptr[];                 /* Array pointers */
+extern int a_dim[];                    /* Array dimensions */
+extern int a_link[];
+
+#ifdef DCMDBUF
+extern struct cmdptr *cmdstk;          /* The command stack itself */
+#else
+extern struct cmdptr cmdstk[];         /* The command stack itself */
+#endif /* DCMDBUF */
+
+long ck_alarm = 0;                     /* SET ALARM value */
+char alrm_date[24] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ' };
+char alrm_time[24] = { ' ',' ',' ',' ',' ',' ',' ' };
+
+#define INPSW_NOM 1
+struct keytab inputsw[] = {
+    { "/nomatch", INPSW_NOM, 0 }
+};
+static int ninputsw = sizeof(inputsw)/sizeof(struct keytab);
+
+#endif /* NOSPL */
+
+static int x, y, z = 0;                        /* Local workers */
+static char *s;
+
+#ifdef CK_MINPUT
+static char c1chars[] = {              /* C1 control chars escept NUL */
+    001,002,003,004,005,006,007,010,011,012,013,014,015,016,017,020,
+    021,022,023,024,025,026,027,030,031,032,033,034,035,036,037
+};
+#endif /* CK_MINPUT */
+
+#define xsystem(s) zsyscmd(s)
+
+/* Top-Level Interactive Command Keyword Table */
+/* Keywords must be in lowercase and in alphabetical order. */
+
+struct keytab cmdtab[] = {
+#ifndef NOPUSH
+    { "!",        XXSHE, CM_INV|CM_PSH }, /* Shell escape */
+#else
+    { "!",        XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOPUSH */
+    { "#",        XXCOM, CM_INV },     /* Comment */
+#ifndef NOSPL
+    { "(",           XXSEXP,CM_INV },  /* S-Expression */
+    { ".",           XXDEF, CM_INV },  /* Assignment */
+    { ":",           XXLBL, CM_INV },  /* Label */
+#endif /* NOSPL */
+#ifdef CK_REDIR
+#ifndef NOPUSH
+    { "<",           XXFUN, CM_INV|CM_PSH }, /* REDIRECT */
+#else
+    { "<",           XXNOTAV, CM_INV|CM_PSH }, /* REDIRECT */
+#endif /* NOPUSH */
+#endif /* CK_REDIR */
+#ifndef NOPUSH
+    { "@",           XXSHE, CM_INV|CM_PSH }, /* DCL escape */
+#else
+    { "@",           XXNOTAV, CM_INV|CM_PSH }, /* DCL escape */
+#endif /* NOPUSH */
+
+#ifdef CK_RECALL
+    { "^",           XXREDO,CM_INV|CM_NOR }, /* Synonym for REDO */
+#endif /* CK_RECALL */
+#ifndef NOSPL
+    { "_asg",        XXASX,   CM_INV },        /* Used internally by FOR, etc */
+    { "_assign",     XXASX,   CM_INV },        /* Used internally by FOR, etc */
+    { "_decrement",  XX_DECR, CM_INV },
+    { "_define",     XXDFX,   CM_INV },        /* Used internally by FOR, etc */
+    { "_evaluate",   XX_EVAL, CM_INV },
+    { "_forward",    XXXFWD,  CM_INV },        /* Used internally by SWITCH   */
+    { "_getargs",    XXGTA,   CM_INV },        /* Used internally by FOR, etc */
+    { "_increment",  XX_INCR, CM_INV },
+    { "_putargs",    XXPTA,   CM_INV },        /* Used internally by FOR, etc */
+    { "_undefine",   XXUNDFX, CM_INV },
+#endif /* NOSPL */
+
+    { "about",       XXVER,   CM_INV },        /* Synonym for VERSION */
+#ifndef NOSPL
+#ifdef NEWFTP
+    { "account",     XXACCT,  CM_INV }, /* (FTP) Account */
+#endif /* NEWFTP */
+#ifdef ADDCMD
+    { "add",         XXADD, 0 },       /* ADD */
+#endif /* ADDCMD */
+#ifndef NODIAL
+    { "answer",      XXANSW, CM_LOC }, /* ANSWER the phone */
+#else
+    { "answer",      XXNOTAV, CM_INV|CM_LOC }, /* ANSWER the phone */
+#endif /* NODIAL */
+    { "apc",         XXAPC, 0 },       /* Application Program Command */
+#ifndef NOSPL
+    { "array",       XXARRAY, 0 },     /* Array operations */
+#endif /* NOSPL */
+    { "ascii",       XXASC, CM_INV },  /* == SET FILE TYPE TEXT */
+    { "asg",         XXASS, CM_INV },  /* Invisible synonym for ASSIGN */
+    { "ask",         XXASK, 0 },       /* ASK for text, assign to variable */
+    { "askq",        XXASKQ,0 },       /* ASK quietly (no echo) */
+#ifndef NOSPL
+    { "ass",         XXASS, CM_INV|CM_ABR }, /* ASSIGN */
+    { "assert",      XXASSER, CM_INV },        /* ASSERT */
+    { "assign",      XXASS, 0 },       /* ASSIGN */
+#endif /* NOSPL */
+#ifndef NOXFER
+#ifndef NOCSETS
+    { "associate",   XXASSOC, 0 },     /* ASSOCIATE */
+#else
+    { "associate",   XXNOTAV, CM_INV },        /* ASSOCIATE */
+#endif /* NOCSETS */
+#endif /* NOXFER */
+#ifdef CK_KERBEROS
+#ifdef CK_AUTHENTICATION
+    { "authenticate",XXAUTH, 0 },      /* Authentication */
+#else
+    { "authenticate",XXAUTH, CM_INV },
+#endif /* CK_AUTHENTICATION */
+#endif /* CK_KERBEROS */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    { "back",        XXBACK, 0 },      /* BACK to previous directory */
+#else
+    { "back",        XXNOTAV,CM_INV },
+#endif /* NOFRILLS */
+    { "beep",        XXBEEP,CM_INV },  /* BEEP */
+#ifndef NOXFER
+    { "binary",      XXBIN, CM_INV },  /* == SET FILE TYPE BINARY */
+#endif /* NOXFER */
+#ifndef NOFRILLS
+    { "bug",         XXBUG, CM_INV },  /* BUG report instructions */
+#else
+    { "bug",         XXNOTAV, CM_INV },
+#endif /* NOFRILLS */
+#ifdef BROWSER
+    { "browse",      XXBROWS, CM_PSH|CM_LOC }, /* BROWSE (start browser) */
+#else
+    { "browse",      XXNOTAV, CM_INV|CM_PSH|CM_LOC },
+#endif /* BROWSER */
+#ifndef NOXFER
+    { "bye",         XXBYE, 0 },       /* BYE to remote server */
+#endif /* NOXFER */
+#ifndef NOLOCAL
+    { "c",           XXCON, CM_INV|CM_ABR|CM_LOC }, /* (CONNECT) */
+#endif /* NOLOCAL */
+#ifndef NOFRILLS
+    { "cat",         XXCAT, CM_INV },  /* Invisible synonym for TYPE */
+#endif /* NOFRILLS */
+#ifndef NOSPL
+
+#ifndef NOXFER
+    { "cautious",    XXCAU, CM_INV },
+#endif /* NOXFER */
+
+#endif /* NOSPL */
+
+    { "cd",          XXCWD, 0 },       /* Change Directory */
+    { "cdup",        XXCDUP, CM_INV }, /* Change Directory Up */
+
+#ifndef NOXFER
+#ifdef PIPESEND
+    { "cget",        XXCGET, CM_INV|CM_PSH }, /* CGET */
+#else
+    { "cget",        XXNOTAV, CM_INV|CM_PSH }, /* CGET */
+#endif /* PIPESEND */
+#endif /* NOXFER */
+    { "ch",          XXCHK,   CM_INV|CM_ABR },
+    { "check",       XXCHK,   0 },     /* CHECK for a feature */
+#ifdef CK_PERMS
+#ifdef UNIX
+    { "chmod",       XXCHMOD, 0 },     /* CHMOD */
+#else
+    { "chmod",       XXNOTAV, CM_INV },
+#endif /* UNIX */
+#else
+    { "chmod",       XXNOTAV, CM_INV },
+#endif /* CK_PERMS */
+#ifdef CKROOT
+    { "chroot",      XXCHRT,  CM_INV },        /* CHROOT */
+#endif /* CKROOT */
+    { "ckermit",     XXKERMI, CM_INV },        /* CKERMIT (like KERMIT) */
+    { "cl",          XXCLO,   CM_ABR|CM_INV },
+#ifndef NOFRILLS
+    { "clear",       XXCLE, 0 },       /* CLEAR input and/or device buffer */
+#else
+    { "clear",       XXNOTAV, CM_INV },
+#endif /* NOFRILLS */
+    { "close",      XXCLO, 0 },        /* CLOSE a log or other file */
+    { "cls",         XXCLS, CM_INV },  /* Clear Screen (CLS) */
+    { "comment",     XXCOM, CM_INV },  /* Introduce a comment */
+#ifndef NOLOCAL
+    { "connect",     XXCON, CM_LOC },  /* Begin terminal connection */
+#else
+    { "connect",     XXNOTAV, CM_LOC },
+#endif /* NOLOCAL */
+    { "continue",    XXCONT,  CM_INV },        /* CONTINUE */
+#ifndef NOFRILLS
+#ifdef ZCOPY
+    { "co",          XXCPY, CM_INV|CM_ABR },
+    { "cop",         XXCPY, CM_INV|CM_ABR },
+    { "copy",        XXCPY, 0 },       /* COPY a file */
+#else
+    { "copy",        XXNOTAV, CM_INV },
+#endif /* ZCOPY */
+    { "copyright",   XXCPR, CM_INV },  /* COPYRIGHT */
+#ifdef ZCOPY
+    { "cp",          XXCPY, CM_INV },  /* COPY a file */
+#endif /* ZCOPY */
+#ifndef NOLOCAL
+#ifndef OS2
+    { "cq",          XXCQ, CM_INV|CM_LOC }, /* CQ (connect quietly) */
+#endif /* OS2 */
+#endif /* NOLOCAL */
+#ifndef NOXFER
+#ifdef PIPESEND
+    { "creceive",    XXCREC,CM_INV|CM_PSH }, /* RECEIVE to a command */
+    { "csend",       XXCSEN,CM_INV|CM_PSH }, /* SEND from command */
+#else
+    { "creceive",    XXNOTAV,CM_INV|CM_PSH },
+    { "csend",       XXNOTAV,CM_INV|CM_PSH },
+#endif /* PIPESEND */
+#endif /* NOXFER */
+#endif /* NOFRILLS */
+
+    { "cwd",        XXCWD,   CM_INV }, /* Traditional synonym for cd */
+
+#ifndef NOSPL
+    { "date",        XXDATE,  0 },     /* DATE */
+    { "dcl",         XXDCL,   CM_INV },        /* DECLARE an array (see ARRAY) */
+    { "debug",       XXDEBUG, CM_INV },
+    { "declare",     XXDCL,   CM_INV },        /* DECLARE an array (see ARRAY) */
+    { "decrement",   XXDEC,   0 },     /* DECREMENT a numeric variable */
+    { "define",      XXDEF,   0 },     /* DEFINE a macro or variable */
+#else
+    { "date",        XXNOTAV, CM_INV },
+    { "dcl",         XXNOTAV, CM_INV },
+    { "declare",     XXNOTAV, CM_INV },
+    { "decrement",   XXNOTAV, CM_INV },
+    { "define",      XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+    { "delete",      XXDEL, 0 },       /* DELETE a file */
+#else
+    { "delete",      XXNOTAV, CM_INV },
+#endif /* NOFRILLS */
+
+#ifndef NODIAL
+    { "dial",        XXDIAL,  CM_LOC },        /* DIAL a phone number */
+#else
+    { "dial",        XXNOTAV, CM_INV|CM_LOC },
+#endif /* NODIAL */
+
+#ifdef NT
+    { "dialer",      XXDIALER, CM_INV }, /* K95 Dialer */
+#endif /* NT */
+
+    { "directory",   XXDIR, 0 },       /* DIRECTORY of files */
+
+#ifndef NOFRILLS
+#ifndef NOSERVER
+    { "disable",     XXDIS, 0 },       /* DISABLE a server function */
+#else
+    { "disable",     XXNOTAV, CM_INV },
+#endif /* NOSERVER */
+#endif /* NOFRILLS */
+
+#ifndef NOSPL
+    { "do",          XXDO,  0 },       /* DO (execute) a macro */
+#else
+    { "do",          XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+    { "e",           XXEXI, CM_INV|CM_ABR },
+
+#ifndef NOFRILLS
+#ifndef NOXFER
+    { "e-packet",    XXERR, CM_INV },  /* Send an Error-Packet */
+#endif /* NOXFER */
+#endif /* NOFRILLS */
+
+    { "echo",        XXECH, 0 },       /* ECHO text */
+
+#ifndef NOFRILLS
+#ifndef NOPUSH
+    { "edit",        XXEDIT, CM_PSH }, /* EDIT */
+#else
+    { "edit",        XXNOTAV, CM_INV|CM_PSH }, /* EDIT */
+#endif /* NOPUSH */
+#endif /* NOFRILLS */
+
+    { "eightbit",    XXEIGHT, CM_INV },        /* EIGHTBIT */
+
+#ifndef NOSPL
+    { "else",        XXELS, CM_INV },  /* ELSE part of IF statement */
+#else
+    { "else",        XXNOTAV, CM_INV },        /* ELSE part of IF statement */
+#endif /* NOSPL */
+
+#ifndef NOSERVER
+#ifndef NOFRILLS
+    { "enable",      XXENA,  0 },      /* ENABLE a server function */
+#else
+    { "enable",      XXNOTAV, CM_INV },
+#endif /* NOFRILLS */
+#endif /* NOSERVER */
+
+#ifndef NOSPL
+    { "end",         XXEND,  0 },      /* END command file or macro */
+#else
+    { "end",         XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+    { "erase",       XXDEL, CM_INV },  /* Synonym for DELETE */
+
+#ifndef NOSPL
+    { "evaluate",    XXEVAL, 0 },      /* EVALUATE */
+#else
+    { "evaluate",    XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+    { "ex",          XXEXI, CM_INV|CM_ABR }, /* Let "ex" still be EXIT */
+
+#ifdef CKEXEC
+    { "exec",        XXEXEC, CM_INV|CM_LOC }, /* exec() */
+#else
+    { "exec",        XXNOTAV, CM_INV|CM_LOC },
+#endif /* CKEXEC */
+
+    { "exit",     XXEXI, 0 },          /* EXIT from C-Kermit */
+    { "extended-options", XXXOPTS,CM_INV|CM_HLP }, /* Extended-Options */
+
+#ifdef OS2
+    { "extproc",     XXCOM, CM_INV },  /* Dummy command for OS/2 */
+#endif /* OS2 */
+
+#ifndef NOXFER
+    { "f",           XXFIN, CM_INV|CM_ABR }, /* Invisible abbrev for FIN */
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    { "fail",        XXFAIL, CM_INV }, /* FAIL */
+
+#ifndef NOXFER
+    { "fast",        XXFAST, CM_INV },
+#endif /* NOXFER */
+
+#ifdef CKCHANNELIO
+    { "fclose",      XXF_CL, CM_INV }, /* FCLOSE */
+    { "fcount",      XXF_CO, CM_INV }, /* FCOUNT */
+    { "fflush",      XXF_FL, CM_INV }, /* FFLUSH */
+#endif /* CKCHANNELIO */
+
+#ifndef NOXFER
+    { "fi",          XXFIN, CM_INV|CM_ABR }, /* FINISH */
+#endif /* NOXFER */
+
+#ifdef CKCHANNELIO
+    { "file",        XXFILE, 0 },      /* FILE */
+#endif /* CKCHANNELIO */
+#endif /* NOSPL */
+
+#ifndef NOXFER
+    { "fin",         XXFIN, CM_INV|CM_ABR }, /* FINISH */
+#endif /* NOXFER */
+
+#ifndef UNIXOROSK
+    { "find",        XXGREP, 0 },      /* FIND (grep) */
+#else
+    { "find",        XXGREP,CM_INV },
+#endif /* UNIXOROSK */
+
+#ifndef NOXFER
+    { "finish",      XXFIN, 0 },       /* FINISH */
+#endif /* NOXFER */
+
+#ifdef TCPSOCKET
+    { "firewall",    XXFIREW, CM_INV|CM_HLP },
+#endif /* TCPSOCKET */
+
+#ifdef CKCHANNELIO
+    { "flist",       XXF_LI, CM_INV }, /* FLIST */
+    { "fopen",       XXF_OP, CM_INV }, /* FOPEN */
+#endif /* CKCHANNELIO */
+
+#ifndef NOSPL
+    { "fo",          XXFOR, CM_INV|CM_ABR }, /* Invisible abbrev for... */
+    { "for",         XXFOR, 0 },       /* FOR loop */
+    { "forward",     XXFWD, CM_INV },  /* FORWARD */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    { "fot",      XXDIR, CM_INV },     /* "fot" = "dir" (for Chris) */
+#endif /* NOFRILLS */
+
+#ifdef CKCHANNELIO
+    { "fread",      XXF_RE, CM_INV },  /* FREAD */
+    { "frewind",    XXF_RW, CM_INV },  /* FREWIND */
+    { "fseek",      XXF_SE, CM_INV },  /* FSEEK */
+    { "fstatus",    XXF_ST, CM_INV },  /* FSTATUS */
+#endif /* CKCHANNELIO */
+
+#ifdef TCPSOCKET
+#ifndef NOFTP
+#ifdef SYSFTP
+#ifndef NOPUSH
+    { "ftp",      XXFTP,   CM_INV|CM_PSH|CM_LOC }, /* System FTP */
+#else
+    { "ftp",      XXNOTAV, CM_INV|CM_PSH|CM_LOC },
+#endif /* NOPUSH */
+#else  /* SYSFTP */
+    { "ftp",      XXFTP,   0 },        /* Built-in FTP */
+#endif /* SYSFTP */
+#else  /* NOFTP */
+    { "ftp",      XXNOTAV, CM_INV },   /* No FTP */
+#endif /* NOFTP */
+#endif /* TCPSOCKET */
+
+#ifndef NOSPL
+    { "function",    XXFUNC, CM_INV|CM_HLP }, /* (for HELP FUNCTION) */
+#endif /* NOSPL */
+
+#ifdef CKCHANNELIO
+    { "fwrite",      XXF_WR, CM_INV }, /* FWRITE */
+#endif /* CKCHANNELIO */
+
+#ifndef NOXFER
+    { "g",           XXGET, CM_INV|CM_ABR }, /* Invisible abbrev for GET */
+#ifndef NOSPL
+    { "ge",          XXGET, CM_INV|CM_ABR }, /* Ditto */
+#endif /* NOSPL */
+    { "get",         XXGET, 0 },       /* GET */
+#endif /* NOXFER */
+#ifndef NOSPL
+    { "getc",        XXGETC, 0 },      /* GETC */
+#ifdef OS2
+    { "getkeycode",  XXGETK, 0 },      /* GETKEYCODE */
+#endif /* OS2 */
+#ifndef NOFRILLS
+    { "getok",       XXGOK, 0 },       /* GETOK (ask for Yes/No/OK) */
+#endif /* NOFRILLS */
+#endif /* NOSPL */
+#ifndef NOSPL
+    { "goto",        XXGOTO,0 },       /* GOTO label in take file or macro */
+#endif /* NOSPL */
+#ifdef UNIXOROSK
+    { "grep",        XXGREP,0 },       /* GREP (find) */
+#else
+    { "grep",        XXGREP,CM_INV },  /* GREP (find) */
+#endif /* UNIXOROSK */
+    { "h",           XXHLP, CM_INV|CM_ABR }, /* Invisible synonym for HELP */
+    { "he",          XXHLP, CM_INV|CM_ABR }, /* Invisible synonym for HELP */
+#ifndef NOFRILLS
+    { "head",        XXHEAD, 0 },
+#endif /* NOFRILLS */
+#ifndef NOLOCAL
+    { "hangup",      XXHAN, CM_LOC },  /* HANGUP the connection */
+#endif /* NOLOCAL */
+    { "HELP",        XXHLP, 0 },       /* Display HELP text */
+#ifndef NOHTTP
+#ifdef TCPSOCKET
+    { "http",        XXHTTP, 0 },      /* HTTP operations */
+#endif /* TCPSOCKET */
+#endif /* NOHTTP */
+#ifndef NOSPL
+    { "i",           XXINP, CM_INV|CM_ABR }, /* Invisible synonym for INPUT */
+    { "if",          XXIF,  0 },            /* IF ( condition ) command */
+#ifdef TCPSOCKET
+    { "iksd",        XXIKSD, CM_INV },      /* Make connection to IKSD */
+#else
+    { "iksd",        XXNOTAV, CM_INV },
+#endif /* TCPSOCKET */
+    { "in",          XXINP, CM_INV|CM_ABR }, /* Invisible synonym for INPUT */
+    { "increment",   XXINC, 0 },       /* Increment a numeric variable */
+    { "input",       XXINP, 0 },       /* INPUT text from comm device */
+#endif /* NOSPL */
+
+#ifndef NOHELP
+    { "int",         XXINT, CM_INV|CM_ABR },
+    { "intr",        XXINT, CM_INV|CM_ABR },
+    { "INTRO",       XXINT, 0 },
+    { "introduction",XXINT, CM_INV },  /* Print introductory text */
+#else
+    { "intro",       XXNOTAV, CM_INV },
+    { "introduction",XXNOTAV, CM_INV },
+#endif /* NOHELP */
+
+#ifdef OS2
+    { "k95",         XXKERMI, CM_INV },        /* Hmmm what's this... */
+#endif /* OS2 */
+
+#ifndef NOSPL
+    { "kcd",         XXKCD,   0      },
+#endif /* NOSPL */
+
+    { "kermit",      XXKERMI, CM_INV },
+
+#ifdef OS2
+#ifndef NOKVERBS
+    { "kverb",       XXKVRB, CM_INV|CM_HLP }, /* Keyboard verb */
+#endif /* NOKVERBS */
+#endif /* OS2 */
+
+#ifndef NOFRILLS
+    { "l",           XXLOG, CM_INV|CM_ABR }, /* Invisible synonym for log */
+#endif /* NOFRILLS */
+
+    { "lcd",         XXLCWD, CM_INV },
+    { "lcdup",       XXLCDU, CM_INV },
+    { "lcwd",        XXLCWD, CM_INV },
+    { "ldelete",     XXLDEL, CM_INV },
+    { "ldirectory",  XXLDIR, CM_INV },
+
+#ifdef CKLEARN
+    { "learn",       XXLEARN, 0 },     /* LEARN - automatic script writing */
+#else
+    { "learn",       XXNOTAV, CM_INV },
+#endif /* CKLEARN */
+
+    { "li",          XXLNOUT, CM_INV|CM_ABR },
+    { "LICENSE",     XXCPR, 0 },       /* LICENSE */
+
+#ifndef NOSPL
+    { "lineout",     XXLNOUT, 0 },     /* LINEOUT = OUTPUT + eol */
+#endif /* NOSPL */
+
+#ifdef NT
+    { "link",        XXLINK, 0 },       /* LINK source destination */
+#endif /* NT */
+
+    { "lmkdir",      XXLMKD, CM_INV },
+
+#ifndef NOFRILLS
+    { "lo",          XXLOG,  CM_INV|CM_ABR }, /* Invisible synonym for log */
+#endif /* NOFRILLS */
+
+#ifndef NOSPL
+    { "local",       XXLOCAL, CM_INV },        /* LOCAL variable declaration */
+#else
+    { "local",       XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+    { "log",        XXLOG, 0 },        /* Open a log file */
+
+    { "login",       XXLOGIN,  0 },    /* (REMOTE) LOGIN to server or IKSD */
+    { "logout",      XXLOGOUT, 0 },    /* LOGOUT from server or IKSD */
+
+#ifndef NOFRILLS
+#ifndef NODIAL
+    { "lookup",      XXLOOK,  0 },     /* LOOKUP */
+#else
+    { "lookup",      XXNOTAV, CM_INV },
+#endif /* NODIAL */
+
+    { "lpwd",        XXLPWD, CM_INV },
+    { "lrename",     XXLREN, CM_INV },
+    { "lrmdir",      XXLRMD, CM_INV },
+
+#ifdef UNIXOROSK
+    { "ls",          XXLS,  CM_INV|CM_PSH }, /* UNIX ls command */
+#else
+    { "ls",          XXDIR, CM_INV },  /* Invisible synonym for DIR */
+#endif /* UNIXOROSK */
+#ifndef NOXFER
+    { "mail",        XXMAI, 0 },       /* Send a file as e-mail */
+#endif /* NOXFER */
+#ifndef NOHELP
+    { "manual",      XXMAN, CM_PSH },  /* MAN(UAL) */
+#else
+    { "manual",      XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOHELP */
+#endif /* NOFRILLS */
+#ifdef CK_MKDIR
+    { "md",          XXMKDIR, CM_INV },        /* Synonym for MKDIR */
+#endif /* CK_MKDIR */
+#ifdef CK_MINPUT
+    { "minput",      XXMINP, 0 },      /* MINPUT */
+#else
+    { "minput",      XXNOTAV, CM_INV },
+#endif /* CK_MINPUT */
+#ifndef NOMSEND
+    { "mget",        XXMGET, 0 },      /* MGET */
+#else
+    { "mget",        XXNOTAV, CM_INV },
+#endif /* NOMSEND */
+#ifdef CK_MKDIR
+    { "mkdir",       XXMKDIR, 0 },     /* MKDIR */
+#else
+    { "mkdir",       XXNOTAV, CM_INV },
+#endif /* CK_MKDIR */
+
+#ifndef NOXFER
+#ifndef NOMSEND
+    { "mmove",       XXMMOVE, 0 },     /* MMOVE */
+#else
+    { "mmove",       XXNOTAV, CM_INV },
+#endif /* NOMSEND */
+#endif /* NOXFER */
+
+#ifndef NOFRILLS
+    { "more",        XXMORE, CM_INV }, /* MORE */
+#endif /* NOFRILLS */
+
+#ifndef NOXFER
+    { "move",        XXMOVE, 0 },      /* MOVE  */
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    { "mpause",      XXMSL, CM_INV },  /* Millisecond sleep */
+#else
+    { "mpause",      XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOXFER
+#ifndef NOMSEND
+    { "mput",        XXMSE, CM_INV },  /* MPUT = MSEND */
+    { "ms",          XXMSE, CM_INV|CM_ABR },
+    { "msend",       XXMSE, 0 },       /* Multiple SEND */
+#else
+    { "mput",        XXNOTAV, CM_INV },
+    { "msend",       XXNOTAV, CM_INV },
+#endif /* NOMSEND */
+#endif /* NOXFER */
+#ifndef NOSPL
+    { "msleep",      XXMSL, 0 },       /* Millisecond sleep */
+#else
+    { "msleep",      XXNOTAV, CM_INV },
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    { "mv",          XXREN, CM_INV },  /* Synonym for rename */
+#endif /* NOFRILLS */
+#ifndef NOHELP
+    { "news",        XXNEW, CM_INV },  /* Display NEWS of new features */
+#else
+    { "news",        XXNOTAV, CM_INV },
+#endif /* NOHELP */
+    { "nolocal",     XXNLCL, CM_INV }, /* Disable SET LINE / SET HOST */
+    { "nopush",      XXNPSH, CM_INV }, /* Disable PUSH command/features */
+#ifdef OS2
+    { "noscroll",    XXNSCR, CM_INV },  /* Disable scroll operations */
+#endif /* OS2 */
+#ifndef NOSPL
+    { "o",           XXOUT, CM_INV|CM_ABR }, /* Invisible synonym for OUTPUT */
+    { "open",        XXOPE, 0 },       /* OPEN file for reading or writing */
+#else
+    { "open",        XXOPE, CM_INV },  /* OPEN */
+#endif /* NOSPL */
+#ifndef NOHELP
+    { "options",     XXOPTS,CM_INV|CM_HLP }, /* Options */
+#endif /* NOHELP */
+    { "orientation", XXORIE, 0 },
+#ifndef NOSPL
+    { "output",      XXOUT, 0 },       /* OUTPUT text to comm device */
+#else
+    { "output",      XXNOTAV, CM_INV },
+#endif /* NOSPL */
+#ifdef ANYX25
+#ifndef IBMX25
+    { "pad",         XXPAD, CM_LOC },  /* X.3 PAD commands */
+#endif /* IBMX25 */
+#endif /* ANYX25 */
+
+#ifdef NEWFTP
+    { "passive",     XXPASV, CM_INV }, /* (FTP) PASSIVE */
+#endif /* NEWFTP */
+
+#ifndef NOHELP
+    { "patterns",    XXPAT,CM_INV|CM_HLP }, /* Pattern syntax */
+#endif /* NOHELP */
+
+#ifndef NOSPL
+    { "pause",       XXPAU, 0 },       /* Sleep for specified interval */
+#else
+    { "pause",       XXNOTAV, CM_INV },
+#endif /* NOSPL */
+#ifndef NODIAL
+    { "pdial",       XXPDIA,  CM_LOC },        /* PDIAL (partial dial) */
+#else
+    { "pdial",       XXNOTAV, CM_INV|CM_LOC },
+#endif /* NODIAL */
+#ifdef TCPSOCKET
+#ifndef NOPUSH
+    { "ping",        XXPNG, CM_INV|CM_PSH|CM_LOC }, /* PING */
+#else
+    { "ping",        XXNOTAV, CM_INV|CM_PSH|CM_LOC },
+#endif /* NOPUSH */
+#endif /* TCPSOCKET */
+#ifdef NETCMD
+#ifndef NOPUSH
+    { "pipe",        XXPIPE, CM_PSH }, /* PIPE */
+#else
+    { "pipe",        XXNOTAV, CM_INV|CM_PSH }, /* PIPE */
+#endif /* NOPUSH */
+#endif /* NETCMD */
+
+#ifndef NOSPL
+    { "pop",         XXEND, CM_INV },  /* Invisible synonym for END */
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    { "print",       XXPRI, 0 },       /* PRINT a file locally */
+#endif /* NOFRILLS */
+
+    { "prompt",      XXPROMP, CM_INV },        /* Go interactive (from script) */
+
+#ifndef NOXFER
+#ifdef CK_RESEND
+    { "psend",       XXPSEN, CM_INV }, /* PSEND */
+#else
+    { "psend",       XXNOTAV, CM_INV },
+#endif /* CK_RESEND */
+#endif /* NOXFER */
+
+#ifdef NETPTY
+    { "pty",         XXPTY, CM_PSH },  /* PTY */
+#else
+    { "pty",         XXNOTAV, CM_INV|CM_PSH },
+#endif /* NETPTY */
+
+#ifndef NOPUSH
+    { "pu",          XXSHE, CM_INV|CM_ABR|CM_PSH }, /* PU = PUSH */
+#endif /* NOPUSH */
+
+#ifdef CKPURGE
+    { "purge",       XXPURGE, 0 },     /* PURGE (real) */
+#else
+#ifdef VMS
+    { "purge",       XXPURGE, 0 },     /* PURGE (fake) */
+#else
+    { "purge",       XXNOTAV, CM_INV },
+#endif /* VMS */
+#endif /* CKPURGE */
+
+#ifndef NOPUSH
+    { "push",        XXSHE, CM_PSH },  /* PUSH command (like RUN, !) */
+#else
+    { "push",        XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOPUSH */
+
+#ifndef NOXFER
+    { "put",         XXSEN, CM_INV },  /* PUT = SEND */
+#endif /* NOXFER */
+
+    { "pwd",         XXPWD, 0 },       /* Print Working Directory */
+    { "q",           XXQUI, CM_INV|CM_ABR }, /* Invisible synonym for QUIT */
+
+#ifndef NOXFER
+    { "query",       XXRQUE,CM_INV },  /* (= REMOTE QUERY) */
+#endif /* NOXFER */
+
+    { "quit",        XXQUI, 0 },       /* QUIT from program = EXIT */
+
+#ifndef NOXFER
+    { "r",           XXREC, CM_INV|CM_ABR }, /* Inv synonym for RECEIVE */
+#endif /* NOXFER */
+
+#ifndef NOXFER
+    { "rasg",        XXRASG, CM_INV }, /* REMOTE ASSIGN */
+    { "rassign",     XXRASG, CM_INV }, /* ditto */
+    { "rcd",         XXRCWD, CM_INV }, /* REMOTE CD */
+    { "rcdup",       XXRCDUP,CM_INV }, /* REMOTE CD */
+    { "rcopy",       XXRCPY, CM_INV }, /* REMOTE COPY */
+    { "rcwd",        XXRCWD, CM_INV }, /* REMOTE CWD */
+    { "rdelete",     XXRDEL, CM_INV }, /* REMOTE DELETE */
+    { "rdirectory",  XXRDIR, CM_INV }, /* REMODE DIRECTORY */
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    { "read",        XXREA, 0 },       /* READ a line from a file */
+#else
+    { "read",        XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOXFER
+    { "receive",     XXREC, 0 },       /* RECEIVE files */
+#endif /* NOXFER */
+
+#ifndef NODIAL
+    { "red",         XXRED, CM_INV|CM_ABR|CM_LOC }, /* Inv syn for REDIAL */
+    { "redi",        XXRED, CM_INV|CM_ABR|CM_LOC }, /* ditto */
+    { "redial",      XXRED, CM_LOC },  /* REDIAL last DIAL number */
+#else
+    { "red",         XXNOTAV, CM_INV|CM_LOC },
+    { "redi",        XXNOTAV, CM_INV|CM_LOC },
+    { "redial",      XXNOTAV, CM_INV|CM_LOC },
+#endif /* NODIAL */
+
+#ifdef CK_REDIR
+#ifdef OS2
+#ifndef NOPUSH
+    { "redirect",    XXFUN, CM_INV|CM_PSH }, /* REDIRECT */
+#else
+    { "redirect",    XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOPUSH */
+#else /* OS2 */
+#ifndef NOPUSH
+    { "redirect",    XXFUN, CM_PSH },  /* REDIRECT */
+#else
+    { "redirect",    XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOPUSH */
+#endif /* OS2 */
+#endif /* CK_REDIR */
+
+#ifdef CK_RECALL
+    { "redo",        XXREDO,  CM_NOR },        /* REDO */
+#else
+    { "redo",        XXNOTAV, CM_INV },
+#endif /* CK_RECALL */
+
+#ifndef NOXFER
+#ifdef CK_RESEND
+    { "reget",       XXREGET, 0 },     /* REGET */
+#else
+    { "reget",       XXNOTAV, CM_INV },
+#endif /* CK_RESEND */
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    { "reinput",     XXREI, CM_INV },  /* REINPUT (from INPUT buffer) */
+#else
+    { "reinput",     XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOXFER
+#ifdef ADDCMD
+    { "rem",         XXREM, CM_INV|CM_ABR },
+    { "remo",        XXREM, CM_INV|CM_ABR },
+#endif /* ADDCMD */
+    { "remote",             XXREM, 0 },        /* Send REMOTE command to server */
+#endif /* NOXFER */
+
+#ifdef ADDCMD
+    { "remove",      XXREMV,0 },       /* REMOVE (something from a list) */
+#else
+    { "remove",      XXNOTAV, CM_INV },
+#endif /* ADDCMD */
+
+#ifndef NOFRILLS
+#ifndef NORENAME
+    { "rename",      XXREN, 0 },       /* RENAME a local file */
+#else
+    { "rename",      XXNOTAV, CM_INV },
+#endif /* NORENAME */
+    { "replay",      XXTYP, CM_INV },  /* REPLAY (for now, just type) */
+#endif /* NOFRILLS */
+
+#ifndef NOXFER
+#ifdef CK_RESEND
+    { "res",         XXRSEN, CM_INV|CM_ABR }, /* RESEND */
+    { "rese",        XXRSEN, CM_INV|CM_ABR }, /* RESEND */
+    { "resend",      XXRSEN, 0 },      /* RESEND */
+#else
+    { "res",         XXNOTAV, CM_INV },
+    { "rese",        XXNOTAV, CM_INV },
+    { "resend",      XXNOTAV, CM_INV },
+#endif /* CK_RESEND */
+#endif /* NOXFER */
+
+    { "reset",       XXRESET, CM_INV },        /* RESET */
+
+#ifdef CK_RESEND
+#ifndef NOSPL
+    { "ret",         XXRET, CM_INV|CM_ABR },
+#endif /* NOSPL */
+#endif /* CK_RESEND */
+
+#ifndef NOXFER
+    { "retrieve",    XXRETR, CM_INV }, /* RETRIEVE */
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    { "return",      XXRET, 0 },       /* RETURN from a function */
+#else
+    { "return",      XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOXFER
+    { "rexit",       XXRXIT, CM_INV }, /* REMOTE EXIT */
+#endif /* NOXFER */
+
+#ifdef CK_REXX
+#ifndef NOPUSH
+    { "rexx",        XXREXX, CM_PSH }, /* Execute a Rexx command */
+#else
+    { "rexx",        XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOPUSH */
+#endif /* CK_REXX */
+
+#ifndef NOXFER
+    { "rhelp",       XXRHLP, CM_INV }, /* REMOTE HELP */
+    { "rhost",       XXRHOS, CM_INV }, /* REMOTE HOST */
+    { "rkermit",     XXRKER, CM_INV }, /* REMOTE KERMIT */
+#endif /* NOXFER */
+
+#ifdef TCPSOCKET
+    { "rlogin",      XXRLOG, CM_LOC }, /* Make an Rlogin connection */
+#else
+    { "rlogin",      XXNOTAV, CM_INV|CM_LOC },
+#endif /* TCPSOCKET */
+
+#ifndef NOFRILLS
+    { "rm",          XXDEL, CM_INV },  /* Invisible synonym for delete */
+#endif /* NOFRILLS */
+
+#ifdef CK_MKDIR
+    { "rmdir",       XXRMDIR, 0 },     /* RMDIR */
+#else
+    { "rmdir",       XXNOTAV, CM_INV },
+#endif /* CK_MKDIR */
+
+#ifndef NOXFER
+    { "rmkdir",      XXRMKD, CM_INV }, /* REMOTE MKDIR */
+#ifndef NOSPL
+    { "robust",      XXROB,  CM_INV },
+#else
+    { "robust",      XXNOTAV, CM_INV },
+#endif /* NOSPL */
+    { "rprint",      XXRPRI, CM_INV },  /* REMOTE PRINT */
+    { "rpwd",        XXRPWD, CM_INV }, /* REMOTE PWD */
+    { "rquery",      XXRQUE, CM_INV }, /* REMOTE QUERY */
+#endif /* NOXFER */
+
+#ifdef CK_RECALL
+    { "rr",          XXREDO, CM_INV|CM_NOR },
+#endif /* CK_RECALL */
+
+#ifndef NOXFER
+    { "rrename",    XXRREN, CM_INV },  /* REMOTE RENAME */
+    { "rrmdir",     XXRRMD, CM_INV },  /* REMOTE REMDIR */
+    { "rset",       XXRSET, CM_INV },  /* REMOTE SET */
+    { "rspace",     XXRSPA, CM_INV },  /* REMOTE SPACE */
+    { "rtype",      XXRTYP, CM_INV },  /* REMOTE TYPE */
+#endif /* NOXFER */
+
+#ifndef NOPUSH
+    { "run",         XXSHE, CM_PSH },  /* RUN a program or command */
+#else
+    { "run",         XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOPUSH */
+
+#ifndef NOXFER
+    { "rwho",        XXRWHO, CM_INV }, /* REMOTE WHO */
+    { "s",           XXSEN, CM_INV|CM_ABR }, /* Invisible synonym for send */
+#endif /* NOXFER */
+
+#ifndef NOSETKEY
+#ifdef OS2
+    { "save",     XXSAVE, 0 },         /* SAVE something */
+#else
+    { "save",     XXSAVE, CM_INV },
+#endif /* OS2 */
+#else
+    { "save",     XXNOTAV, CM_INV },
+#endif /* NOSETKEY */
+
+#ifndef NOSCRIPT
+    { "sc",       XXLOGI, CM_INV|CM_ABR|CM_LOC },
+    { "scr",      XXLOGI, CM_INV|CM_ABR|CM_LOC },
+#endif /* NOSCRIPT */
+    { "screen",      XXSCRN, 0 },      /* SCREEN actions */
+#ifndef NOSCRIPT
+    { "script",           XXLOGI, CM_LOC },    /* Expect-Send-style script line */
+#else
+    { "script",           XXNOTAV, CM_INV|CM_LOC },
+#endif /* NOSCRIPT */
+
+    { "search",    XXGREP,CM_INV },    /* Synonym for GREP and FIND */
+
+#ifndef NOXFER
+    { "send",     XXSEN, 0 },          /* Send (a) file(s) */
+#ifndef NOSERVER
+    { "server",           XXSER, 0 },          /* Be a SERVER */
+#else
+    { "server",           XXNOTAV, CM_INV },
+#endif /* NOSERVER */
+#endif /* NOXFER */
+
+    { "set",      XXSET, 0 },          /* SET parameters */
+
+#ifndef NOSPL
+#ifndef NOSEXP
+    { "sexpression", XXSEXP, CM_INV|CM_HLP }, /* SEXPR */
+#endif /* NOSEXP */
+
+#ifdef SFTP_BUILTIN
+    { "sftp",        XXSFTP, 0 },   /* SFTP */
+#endif /* SFTP_BUILTIN */
+
+#ifndef NOSHOW
+    { "sh",          XXSHO, CM_INV|CM_ABR }, /* SHOW parameters */
+#endif /* NOSHOW */
+    { "shift",       XXSHIFT, 0 },     /* SHIFT args */
+#else
+    { "shift",       XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOSHOW
+    { "show",     XXSHO, 0 },          /* SHOW parameters */
+#else
+    { "show",     XXNOTAV, CM_INV },
+#endif /* NOSHOW */
+
+#ifdef NEWFTP
+    { "site",        XXSITE, CM_INV }, /* (FTP) SITE */
+#endif /* NEWFTP */
+
+#ifdef SSHBUILTIN
+    { "skermit",   XXSKRM, 0 },     /* SKERMIT */
+#endif /* SSHBUILTIN */
+
+#ifndef NOSPL
+#ifndef NOFRILLS
+    { "sleep",       XXPAU, CM_INV },  /* SLEEP for specified interval */
+#endif /* NOFRILLS */
+#endif /* NOSPL */
+
+#ifndef NOSPL
+    { "sort",        XXSORT, CM_INV }, /* (see ARRAY) */
+#else
+    { "sort",        XXNOTAV, CM_INV },
+#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|CM_PSH }, /* Synonym for PUSH, RUN */
+#else
+    { "spawn",       XXNOTAV, CM_INV|CM_PSH }, /* Synonym for PUSH, RUN */
+#endif /* NOPUSH */
+#endif /* NOFRILLS */
+
+#ifdef ANYSSH
+    { "ssh",         XXSSH, 0 },
+#endif /* ANYSSH */
+
+#ifndef NOXFER
+    { "sta",         XXSTA, CM_INV|CM_ABR },
+    { "stat",        XXSTA, CM_INV|CM_ABR },
+    { "statistics",  XXSTA, 0 },       /* Display file transfer stats */
+#endif /* NOXFER */
+
+    { "status",      XXSTATUS,0 },     /* Show status of previous command */
+
+#ifndef NOSPL
+    { "stop",        XXSTO,   0 },     /* STOP all take files and macros */
+    { "succeed",     XXSUCC,  CM_INV },        /* SUCCEED */
+#else
+    { "stop",        XXNOTAV, CM_INV },
+    { "succeed",     XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+    { "SUPPORT",     XXBUG, 0 },       /* Tech support instructions */
+#else
+    { "support",     XXNOTAV, CM_INV },
+#endif /* NOFRILLS */
+
+#ifndef NOJC
+    { "suspend",     XXSUS, CM_PSH },  /* SUSPEND C-Kermit (UNIX only) */
+#else
+    { "suspend",     XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOJC */
+
+#ifndef NOSPL
+    { "switch",      XXSWIT, 0 },      /* SWITCH */
+#else
+    { "switch",      XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifdef CK_TAPI
+    { "ta",       XXTAK, CM_INV|CM_ABR }, /* (because of TAPI) */
+#endif /* CK_TAPI */
+
+#ifndef NOFRILLS
+    { "tail",        XXTAIL, 0 },      /* Display end of a local file */
+#endif /* NOFRILLS */
+
+    { "take",     XXTAK, 0 },          /* TAKE commands from a file */
+
+#ifdef CK_TAPI
+    { "tapi",     XXTAPI, CM_LOC },    /* Microsoft TAPI commands */
+#else
+    { "tapi",     XXNOTAV, CM_INV|CM_LOC },
+#endif /* CK_TAPI */
+
+#ifndef NOFRILLS
+#ifdef TCPSOCKET
+    { "tel",         XXTEL, CM_INV|CM_ABR|CM_LOC },
+    { "telnet",      XXTEL, CM_LOC },  /* TELNET (TCP/IP only) */
+    { "telopt",      XXTELOP, CM_INV },        /* TELOPT (ditto) */
+#else
+    { "tel",         XXNOTAV, CM_INV|CM_LOC },
+    { "telnet",      XXNOTAV, CM_INV|CM_LOC },
+    { "telopt",      XXNOTAV, CM_INV },
+#endif /* TCPSOCKET */
+#ifdef OS2
+    { "terminal",    XXTERM, CM_INV|CM_LOC }, /* == SET TERMINAL TYPE */
+#else
+    { "terminal",    XXTERM, CM_INV },
+#endif /* OS2 */
+#endif /* NOFRILLS */
+#ifndef NOXFER
+    { "text",        XXASC, CM_INV },  /* == SET FILE TYPE TEXT */
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    { "trace",       XXTRACE, 0 },     /* TRACE */
+#else
+    { "trace",       XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOCSETS
+    { "translate",   XXXLA, 0 },       /* TRANSLATE local file char sets */
+#else
+    { "translate",   XXNOTAV, CM_INV },
+#endif /* NOCSETS */
+
+#ifndef NOXMIT
+    { "transmit",    XXTRA, 0 },       /* Send (upload) a file, no protocol */
+#else
+    { "transmit",    XXNOTAV, CM_INV },
+#endif /* NOXMIT */
+
+#ifndef NOFRILLS
+    { "type",        XXTYP, 0 },       /* Display a local file */
+#endif /* NOFRILLS */
+
+#ifndef NOSPL
+    { "undcl",       XXUNDCL, CM_INV },
+    { "undeclare",   XXUNDCL, 0 },     /* UNDECLARE an array */
+    { "undefine",    XXUNDEF, 0 },     /* UNDEFINE a variable or macro */
+#else
+    { "undcl",       XXNOTAV, CM_INV },
+    { "undeclare",   XXNOTAV, CM_INV },
+    { "undefine",    XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifdef NEWFTP
+    { "user",        XXUSER,  CM_INV }, /* (FTP) USER */
+#endif /* NEWFTP */
+
+    { "version",     XXVER, 0 },       /* VERSION-number display */
+
+#ifdef OS2
+    { "viewonly",    XXVIEW, CM_LOC }, /* VIEWONLY Terminal Mode */
+#endif /* OS2 */
+
+    { "void",        XXVOID, 0 },      /* VOID */
+
+#ifndef NOSPL
+    { "wait",        XXWAI, 0 },       /* WAIT */
+#else
+    { "wait",        XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+    { "wermit",      XXKERMI, CM_INV },
+
+#ifndef NOXFER
+    { "where",       XXWHERE, 0 },     /* WHERE (did my file go?) */
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    { "while",       XXWHI, 0 },       /* WHILE loop */
+#else
+    { "while",       XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef OS2
+#ifndef MAC
+#ifndef NOFRILLS
+    { "who",         XXWHO, CM_PSH },  /* WHO's logged in? */
+#endif /* NOFRILLS */
+#endif /* MAC */
+#endif /* OS2 */
+
+#ifndef NOHELP
+    { "wildcards",   XXWILD,CM_INV|CM_HLP }, /* Wildcard syntax */
+#endif /* NOHELP */
+
+#ifndef NOSPL
+    { "wr",          XXWRI, CM_INV|CM_ABR },
+    { "wri",         XXWRI, CM_INV|CM_ABR },
+    { "writ",        XXWRI, CM_INV|CM_ABR },
+    { "write",       XXWRI, 0 },       /* WRITE characters to a file */
+    { "write-line",  XXWRL, CM_INV },  /* WRITE a line to a file */
+    { "writeln",     XXWRL, CM_INV },  /* Pascalisch synonym for write-line */
+#else
+    { "wr",          XXNOTAV, CM_INV },
+    { "wri",         XXNOTAV, CM_INV },
+    { "writ",        XXNOTAV, CM_INV },
+    { "write",       XXNOTAV, CM_INV },
+    { "write-line",  XXNOTAV, CM_INV },
+    { "writeln",     XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+    { "xecho",       XXXECH,0 },       /* XECHO */
+#endif /* NOFRILLS */
+
+#ifndef NOSPL
+    { "xif",         XXIFX, CM_INV },  /* Extended IF command (obsolete) */
+#else
+    { "xif",         XXNOTAV, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOCSETS
+    { "xlate",       XXXLA, CM_INV },  /* Synonym for TRANSLATE */
+#else
+    { "xlate",       XXNOTAV, CM_INV },
+#endif /* NOCSETS */
+
+#ifndef NOXMIT
+    { "xmit",        XXTRA, CM_INV },  /* Synonym for TRANSMIT */
+#else
+    { "xmit",        XXNOTAV, CM_INV },
+#endif /* NOXMIT */
+
+#ifndef OS2
+#ifndef NOJC
+    { "z",           XXSUS, CM_INV|CM_PSH }, /* Synonym for SUSPEND */
+#else
+    { "z",           XXNOTAV, CM_INV|CM_PSH },
+#endif /* NOJC */
+#endif /* OS2 */
+
+#ifndef NOSPL
+    { "{",           XXMACRO, CM_INV },        /* Immediate macro */
+#endif /* NOSPL */
+    { "", 0, 0 }
+};
+int ncmd = (sizeof(cmdtab) / sizeof(struct keytab)) - 1;
+
+/* NOTE: Tokens must also be entered above into cmdtab[]. */
+
+char toktab[] = {
+#ifndef NOPUSH
+    '!',                               /* Shell escape */
+#endif /* NOPUSH */
+    '#',                               /* Comment */
+#ifndef NOSPL
+    '(',                               /* S-Expression */
+    '.',                               /* Assignment */
+#endif /* NOSPL */
+    ';',                               /* Comment */
+#ifndef NOSPL
+    ':',                               /* Label */
+#endif /* NOSPL */
+#ifndef NOPUSH
+#ifdef CK_REDIR
+    '<',                               /* REDIRECT */
+#endif /* CK_REDIR */
+    '@',                               /* DCL escape */
+#endif /* NOPUSH */
+#ifdef CK_RECALL
+    '^',                               /* Command recall */
+#endif /* CK_RECALL */
+#ifndef NOSPL
+    '{',                               /* Immediate macro */
+#endif /* NOSPL */
+    '\0'                               /* End of this string */
+};
+int xxdot = 0;                         /* Used with "." token */
+
+struct keytab yesno[] = {              /* Yes/No keyword table */
+    { "no",    0, 0 },
+    { "ok",    1, 0 },
+    { "yes",   1, 0 }
+};
+int nyesno = (sizeof(yesno) / sizeof(struct keytab));
+
+/* Save keyword table */
+
+struct keytab savtab[] = {
+#ifdef OS2
+    { "command",  XSCMD, 0 },
+#else
+#ifdef CK_RECALL
+    { "command",  XSCMD, 0 },
+#endif /* CK_RECALL */
+#endif /* OS2 */
+#ifndef NOSETKEY
+    { "keymap",   XSKEY, 0 },
+#endif /* NOSETKEY */
+#ifdef OS2
+    { "terminal", XSTERM, 0 },
+#endif /* OS2 */
+    { "", 0, 0 }
+};
+int nsav = (sizeof(savtab) / sizeof(struct keytab)) - 1;
+
+/* Parameter keyword table */
+
+struct keytab prmtab[] = {
+    { "alarm",            XYALRM,  0 },
+#ifdef COMMENT                         /* SET ANSWER not implemented yet */
+#ifndef NODIAL
+    { "answer",           XYANSWER,0 },
+#endif /* NODIAL */
+#endif /* COMMENT */
+    { "ask-timer",        XYTIMER, 0 },
+#ifndef NOXFER
+    { "attributes",       XYATTR,  0 },
+#endif /* NOXFER */
+#ifdef CK_AUTHENTICATION
+    { "authentication",   XYAUTH,  0 },
+#else  /* CK_AUTHENTICATION */
+#ifdef CK_SSL
+    { "authentication",   XYAUTH,  0 },
+#endif /* CK_SSL */
+#endif /* CK_AUTHENTICATION */
+    { "b",               XYBACK,  CM_INV|CM_ABR|CM_PSH },
+    { "ba",              XYBACK,  CM_INV|CM_ABR|CM_PSH },
+#ifdef VMS
+    { "background",       XYBACK,  CM_INV|CM_PSH },
+    { "batch",            XYBACK,  CM_PSH },
+#else
+    { "background",       XYBACK,  CM_PSH },
+    { "batch",            XYBACK,  CM_INV|CM_PSH },
+#endif /* VMS */
+#ifndef NOLOCAL
+    { "baud",            XYSPEE,  CM_INV|CM_LOC },
+#endif /* NOLOCAL */
+    { "bell",             XYBELL,  0 },
+#ifndef NOXFER
+    { "block-check",     XYCHKT,  0 },
+#endif /* NOXFER */
+#ifdef OS2
+#ifdef BPRINT
+    { "bprinter",         XYBDCP,  CM_INV },
+#endif /* BPRINT */
+#endif /*  OS2 */
+#ifdef BROWSER
+    { "browser",          XYBROWSE,CM_PSH|CM_LOC },
+#endif /* BROWSER */
+#ifndef NOXFER
+#ifdef DYNAMIC
+    { "buffers",          XYBUF,   0 },
+#endif /* DYNAMIC */
+#endif /* NOXFER */
+#ifndef NOLOCAL
+#ifndef MAC
+    { "carrier-watch",    XYCARR,  CM_LOC },
+#endif /* MAC */
+#endif /* NOLOCAL */
+#ifndef NOSPL
+    { "case",             XYCASE,  0 },
+#endif /* NOSPL */
+    { "cd",               XYCD,    0 },
+#ifndef NOXFER
+    { "cl",               XYCLEAR, CM_INV|CM_ABR },
+    { "cle",              XYCLEAR, CM_INV|CM_ABR },
+    { "clea",             XYCLEAR, CM_INV|CM_ABR },
+    { "clear",            XYCLEAR, CM_INV|CM_ABR },
+    { "clear-channel",    XYCLEAR, 0 },
+    { "clearchannel",     XYCLEAR, CM_INV },
+#endif /* NOXFER */
+#ifndef NOLOCAL
+    { "close-on-disconnect", XYDISC, CM_INV|CM_LOC },
+#endif /* NOLOCAL */
+    { "cmd",              XYCMD,   CM_INV },
+    { "command",          XYCMD,   0 },
+#ifdef CK_SPEED
+    { "con",              XYQCTL,  CM_INV|CM_ABR },
+#endif /* CK_SPEED */
+    { "console",          XYCMD,   CM_INV },
+#ifdef CK_SPEED
+    { "control-character",XYQCTL,  0 },
+#endif /* CK_SPEED */
+#ifndef NOSPL
+    { "count",            XYCOUN,  0 },
+#endif /* NOSPL */
+#ifndef NOXFER
+    { "d",               XYDELA,  CM_INV|CM_ABR },
+    { "de",              XYDELA,  CM_INV|CM_ABR },
+#endif /* NOXFER */
+    { "debug",            XYDEBU,  0 },
+#ifdef VMS
+    { "default",          XYDFLT,  0 },
+#else
+#ifndef MAC
+    { "default",          XYDFLT,  CM_INV },
+#endif /* MAC */
+#endif /* VMS */
+#ifndef NOXFER
+    { "delay",           XYDELA,  0 },
+    { "destination",     XYDEST,  0 },
+#endif /* NOXFER */
+#ifndef NODIAL
+    { "di",              XYDIAL,  CM_INV|CM_ABR|CM_LOC },
+    { "dia",             XYDIAL,  CM_INV|CM_ABR|CM_LOC },
+    { "dial",             XYDIAL,  CM_LOC },
+#endif /* NODIAL */
+#ifdef OS2
+    { "dialer",                  XYDLR,   CM_INV },
+#endif /* OS2 */
+#ifndef NOLOCAL
+    { "disconnect",       XYDISC,  CM_LOC },
+    { "duplex",                  XYDUPL,  CM_LOC },
+#endif /* NOLOCAL */
+#ifndef NOPUSH
+#ifndef NOFRILLS
+    { "editor",           XYEDIT,  CM_PSH },
+#endif /*  NOFRILLS */
+#endif /* NOPUSH */
+#ifdef CK_CTRLZ
+    { "eof",              XYEOF,   CM_INV },
+#endif /* CK_CTRLZ */
+#ifndef NOLOCAL
+    { "escape-character", XYESC,   CM_LOC },
+#endif /* NOLOCAL */
+#ifndef NOSPL
+    { "evaluate",         XYEVAL,  CM_INV },
+#endif /* NOSPL */
+    { "exit",            XYEXIT,  0 },
+#ifndef NOXFER
+    { "f-ack-bug",        XYFACKB, CM_INV },
+    { "f-ack-path",       XYFACKP, CM_INV },
+#endif /* NOXFER */
+    { "file",            XYFILE,  0 },
+    { "fl",              XYFLOW,  CM_INV|CM_ABR },
+#ifndef NOSPL
+    { "flag",             XYFLAG,  0 },
+#endif /* NOSPL */
+#ifdef TCPSOCKET
+#ifndef SYSFTP
+#ifndef NOFTP
+    { "ft",              XYFTPX,  CM_INV|CM_ABR },
+    { "ftp",             XYFTPX,  0 },
+#endif /* NOFTP */
+#endif /* SYSFTP */
+#endif /* TCPSOCKET */
+#ifdef BROWSER
+    { "ftp-client",       XYFTP,   CM_PSH },
+#endif /* BROWSER */
+    { "flow-control",    XYFLOW,  0 },
+#ifndef NOSPL
+    { "function",         XYFUNC,  0 },
+#endif /* NOSPL */
+#ifdef NEWFTP
+    { "get-put-remote",   XYGPR,   0 },
+#endif /* NEWFTP */
+#ifdef KUI
+    { "gui",              XYGUI,   0 },
+#endif /* KUI */
+    { "handshake",       XYHAND,  0 },
+    { "hints",            XYHINTS, 0 },
+#ifdef NETCONN
+    { "host",             XYHOST,  CM_LOC },
+#endif /* NETCONN */
+#ifndef NOSPL
+    { "i",               XYINPU,  CM_INV|CM_ABR },
+#endif /* NOSPL */
+#ifdef IKSD
+    { "iks",              XYIKS,   0 },
+#else
+    { "iks",              XYIKS,   CM_INV },
+#endif /* IKSD */
+#ifndef NOSPL
+    { "in",              XYINPU,  CM_INV|CM_ABR },
+#endif /* NOSPL */
+#ifndef NOXFER
+    { "incomplete",      XYIFD,   CM_INV },
+#endif /* NOXFER */
+#ifndef NOSPL
+    { "input",            XYINPU,  0 },
+#endif /* NOSPL */
+#ifndef NOSETKEY
+    { "key",             XYKEY,   0 },
+#endif /* NOSETKEY */
+    { "l",                XYLINE,  CM_INV|CM_ABR },
+#ifndef NOCSETS
+    { "language",         XYLANG,  0 },
+#endif /* NOCSETS */
+#ifndef NOLOCAL
+    { "line",             XYLINE,  CM_LOC },
+    { "local-echo",      XYLCLE,  CM_INV|CM_LOC },
+#endif /* NOLOCAL */
+#ifdef LOCUS
+    { "locus",            XYLOCUS, 0 },
+#endif /* LOCUS */
+#ifndef NOSPL
+    { "login",           XYLOGIN, CM_LOC },
+#endif /* NOSPL */
+#ifndef NOSPL
+    { "macro",            XYMACR,  0 },
+#endif /* NOSPL */
+    { "match",            XYMATCH, 0 },
+#ifdef COMMENT
+#ifdef VMS
+    { "messages",         XYMSGS,  0 },
+#endif /* VMS */
+#endif /* COMMENT */
+#ifndef NODIAL
+    { "modem",           XYMODM,  CM_LOC },
+#endif /* NODIAL */
+#ifndef NOLOCAL
+#ifdef OS2MOUSE
+    { "mouse",           XYMOUSE, 0 },
+#endif /* OS2MOUSE */
+#endif /* NOLOCAL */
+#ifdef OS2
+    { "mskermit",         XYMSK,   0 },
+#endif /* OS2 */
+#ifdef NETCONN
+    { "network",          XYNET,   CM_LOC },
+#endif /* NETCONN */
+#ifndef NOSPL
+    { "output",           XYOUTP,  0 },
+#endif /* NOSPL */
+    { "options",          XYOPTS,  0 },
+    { "pause",            XYSLEEP, CM_INV },
+#ifdef ANYX25
+#ifndef IBMX25
+    { "pad",              XYPAD,   CM_LOC },
+#endif /* IBMX25 */
+#endif /* ANYX25 */
+    { "parity",                  XYPARI,  0 },
+#ifndef NOLOCAL
+#ifdef OS2
+    { "port",             XYLINE,  CM_LOC },
+#else
+    { "port",             XYLINE,  CM_INV|CM_LOC },
+#endif /* OS2 */
+#endif /* NOLOCAL */
+#ifndef NOFRILLS
+    { "pr",              XYPROM,  CM_INV|CM_ABR },
+    { "printer",          XYPRTR,  0 },
+#endif /* NOFRILLS */
+#ifdef OS2
+    { "priority",         XYPRTY,  0 },
+#endif /* OS2 */
+#ifdef CK_SPEED
+    { "prefixing",        XYPREFIX, 0 },
+#endif /* CK_SPEED */
+#ifndef NOFRILLS
+    { "prompt",                  XYPROM,  0 },
+#endif /* NOFRILLS */
+#ifndef NOXFER
+    { "protocol",        XYPROTO, 0 },
+#endif /* NOXFER */
+    { "q",               XYQUIE,  CM_INV|CM_ABR },
+#ifndef NOXFER
+    { "q8flag",           XYQ8FLG, CM_INV },
+#endif /* NOXFER */
+#ifdef QNX
+    { "qnx-port-lock",    XYQNXPL, 0 },
+#else
+    { "qnx-port-lock",    XYQNXPL, CM_INV },
+#endif /* QNX */
+    { "quiet",           XYQUIE,  0 },
+#ifndef NOXFER
+    { "rec",              XYRECV,  CM_INV|CM_ABR },
+    { "receive",          XYRECV,  0 },
+    { "recv",             XYRECV,  CM_INV },
+#endif /* NOXFER */
+    { "reliable",         XYRELY,  0 },
+#ifndef NOXFER
+    { "repeat",           XYREPT,  0 },
+    { "retry-limit",      XYRETR,  0 },
+#endif /* NOXFER */
+#ifdef CKROOT
+    { "root",             XYROOT,  0 },
+#endif /* CKROOT */
+#ifndef NOSCRIPT
+    { "script",                  XYSCRI,  CM_LOC },
+#endif /* NOSCRIPT */
+#ifndef NOXFER
+    { "send",             XYSEND,  0 },
+#ifndef NOLOCAL
+#ifndef NOSERVER
+    { "ser",              XYSERV,  CM_INV|CM_ABR },
+#endif /* NOSERVER */
+#endif /* NOXFER */
+    { "serial",           XYSERIAL,CM_LOC },
+#endif /* NOLOCAL */
+#ifndef NOSERVER
+    { "server",           XYSERV,  0 },
+#endif /* NOSERVER */
+#ifdef SESLIMIT
+#ifndef NOLOCAL
+    { "session-l",        XYSESS,  CM_INV|CM_ABR },
+#endif /* NOLOCAL */
+    { "session-limit",    XYLIMIT, CM_INV|CM_LOC }, /* Session Limit */
+#endif /* SESLIMIT */
+
+#ifndef NOLOCAL
+    { "session-log",      XYSESS,  CM_LOC },
+#endif /* NOLOCAL */
+
+#ifndef NOSPL
+#ifndef NOSEXP
+    { "sexpression",      XYSEXP,  CM_INV },
+#endif /* NOSEXP */
+#endif /* NOSPL */
+
+    { "sleep",            XYSLEEP, 0 },
+
+#ifndef NOLOCAL
+    { "speed",           XYSPEE,  CM_LOC },
+#endif /* NOLOCAL */
+
+#ifdef ANYSSH
+    { "ssh",             XYSSH,   0 },
+#endif /* ANYSSH */
+
+#ifndef NOSPL
+    { "startup-file",     XYSTARTUP, CM_INV },
+#endif /* NOSPL */
+
+#ifndef NOLOCAL
+#ifdef HWPARITY
+    { "stop-bits",        XYSTOP, CM_LOC },
+#else
+#ifdef TN_COMPORT
+    { "stop-bits",        XYSTOP, CM_LOC },
+#endif /* TN_COMPORT */
+#endif /* HWPARITY */
+#endif /* NOLOCAL */
+
+#ifndef NOXFER
+#ifdef STREAMING
+    { "streaming",        XYSTREAM, 0 },
+#endif /* STREAMING */
+#endif /* NOXFER */
+
+#ifndef NOJC
+    { "suspend",          XYSUSP,  CM_PSH },
+#endif /* NOJC */
+#ifdef CKSYSLOG
+    { "syslog",           XYSYSL,  CM_INV },
+#endif /* CKSYSLOG */
+    { "take",             XYTAKE,  0 },
+
+#ifdef CK_TAPI
+    { "tapi",             XYTAPI,  CM_LOC },
+#endif /* CK_TAPI */
+
+#ifndef NOTCPOPTS
+#ifdef TCPSOCKET
+    { "tcp",              XYTCP,   CM_LOC },
+#endif /* TCPSOCKET */
+#endif /* NOTCPOPTS */
+
+#ifdef TNCODE
+    { "tel",              XYTEL,   CM_INV|CM_ABR },
+    { "telnet",           XYTEL,   0 },
+    { "telopt",           XYTELOP, 0 },
+#endif /* TNCODE */
+
+#ifndef NOSPL
+    { "temp-directory",   XYTMPDIR,0 },
+#endif /* NOSPL */
+
+#ifndef NOLOCAL
+    { "terminal",         XYTERM,  CM_LOC },
+#endif /* NOLOCAL */
+
+#ifdef OS2
+    { "title",           XYTITLE, CM_LOC },
+#endif /* OS2 */
+#ifdef TLOG
+    { "transaction-log",  XYTLOG,  0 },
+#endif /* TLOG */
+#ifndef NOXFER
+    { "transfer",         XYXFER,  0 },
+#endif /* NOXFER */
+#ifndef NOXMIT
+    { "transmit",         XYXMIT,  0 },
+#endif /* NOXMIT */
+#ifndef NOXFER
+#ifndef NOCSETS
+    { "unknown-char-set", XYUNCS,  0 },
+#endif /* NOCSETS */
+#endif /* NOXFER */
+    { "wait",             XYSLEEP, CM_INV },
+#ifndef NOPUSH
+#ifdef UNIX
+    { "wildcard-expansion", XYWILD, 0 },
+#endif /* UNIX */
+#endif /* NOPUSH */
+#ifdef NT
+    { "w",                XYWIND,  CM_INV|CM_ABR },
+    { "wi",               XYWIND,  CM_INV|CM_ABR },
+    { "win",              XYWIND,  CM_INV|CM_ABR },
+#endif /* NT */
+    { "window-size",      XYWIND,  0 },
+#ifdef NT
+    { "win95",            XYWIN95, 0 },
+#endif /* NT */
+#ifdef ANYX25
+    { "x.25",             XYX25,   CM_LOC },
+    { "x25",              XYX25,   CM_INV|CM_LOC },
+#endif /* ANYX25 */
+    { "xfer",             XYXFER,  CM_INV },
+#ifndef NOXMIT
+    { "xmit",             XYXMIT,  CM_INV },
+#endif /* NOXMIT */
+    { "", 0, 0 }
+};
+int nprm = (sizeof(prmtab) / sizeof(struct keytab)) - 1; /* How many */
+
+struct keytab scntab[] = {             /* Screen commands */
+    { "clear",   SCN_CLR, 0 },
+    { "cleol",   SCN_CLE, 0 },
+    { "move-to", SCN_MOV, 0 }
+};
+int nscntab = (sizeof(scntab) / sizeof(struct keytab)); /* How many */
+
+#ifdef ANYSSH                          /* SSH command table */
+#ifdef SSHBUILTIN
+int    ssh_pf_lcl_n = 0,
+       ssh_pf_rmt_n = 0;
+struct ssh_pf ssh_pf_lcl[32] = { 0, NULL, 0 }; /* SSH Port Forwarding */
+struct ssh_pf ssh_pf_rmt[32] = { 0, NULL, 0 }; /* structs... */
+extern char * ssh_hst, * ssh_cmd, * ssh_prt;
+extern int    ssh_ver,   ssh_xfw;
+char * ssh_tmpuid = NULL, *ssh_tmpcmd = NULL, *ssh_tmpport = NULL,
+     * ssh_tmpstr = NULL;
+
+int
+ sshk_type = SSHKT_2D,                 /* SSH KEY CREATE /TYPE:x */
+ sshk_bits = 1024,                     /* SSH KEY CREATE /BITS:n */
+ sshk_din  = SKDF_OSSH,                        /* SSH KEY DISPLAY /IN-FORMAT: */
+ sshk_dout = SKDF_OSSH;                        /* SSH KEY DISPLAY /OUT-FORMAT: */
+
+char
+ * sshk1_comment = NULL,               /* SSH V1 COMMENT */
+ * sshkp_old = NULL,                   /* Old key passphrase */
+ * sshkp_new = NULL,                   /* New key passphrase */
+ * sshkc_pass = NULL,                  /* KEY CREATE /PASS:xxx */
+ * sshkc_comm = NULL,                  /* KEY CREATE /V1-RSA-COMMENT:xxx */
+ * sshd_file = NULL,                   /* DISPLAY file */
+ * sshk_file = NULL;                   /* SSH CREATE KEY file */
+
+static struct keytab sshclr[] = {
+    { "local-port-forward",  SSHC_LPF, 0 },
+    { "remote-port-forward", SSHC_RPF, 0 },
+    { "", 0, 0 }
+};
+static int nsshclr = (sizeof(sshclr) / sizeof(struct keytab)) - 1;
+
+struct keytab sshopnsw[] = {
+    { "/command",        SSHSW_CMD, CM_ARG },
+    { "/password",       SSHSW_PWD, CM_ARG },
+    { "/subsystem",      SSHSW_SUB, CM_ARG },
+    { "/user",           SSHSW_USR, CM_ARG },
+    { "/version",        SSHSW_VER, CM_ARG },
+    { "/x11-forwarding", SSHSW_X11, CM_ARG },
+    { "", 0, 0 }
+};
+int nsshopnsw = (sizeof(sshopnsw) / sizeof(struct keytab)) - 1;
+
+static struct keytab sshkwtab[] = {
+    { "add",                 XSSH_ADD, 0 },
+    { "agent",               XSSH_AGT, 0 },
+    { "clear",               XSSH_CLR, 0 },
+    { "forward-local-port",  XSSH_FLP, CM_INV },
+    { "forward-remote-port", XSSH_FRP, CM_INV },
+    { "key",                 XSSH_KEY, 0 },
+    { "open",                XSSH_OPN, 0 },
+    { "v2",                  XSSH_V2,  0 },
+    { "", 0, 0 }
+};
+static int nsshcmd = (sizeof(sshkwtab) / sizeof(struct keytab)) - 1;
+
+static struct keytab ssh2tab[] = {
+    { "rekey", XSSH2_RKE, 0 },
+    { "", 0, 0 }
+};
+static int nssh2tab = (sizeof(ssh2tab) / sizeof(struct keytab));
+
+static struct keytab addfwd[] = {      /* SET SSH ADD command table */
+    { "local-port-forward",  SSHF_LCL, 0 },
+    { "remote-port-forward", SSHF_RMT, 0 },
+    { "", 0, 0 }
+};
+static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
+
+static struct keytab sshagent[] = {    /* SET SSH AGENT command table */
+    { "add",    SSHA_ADD, 0 },
+    { "delete", SSHA_DEL, 0 },
+    { "list",   SSHA_LST, 0 },
+    { "", 0, 0 }
+};
+static int nsshagent = (sizeof(sshagent) / sizeof(struct keytab)) - 1;
+
+static struct keytab sshagtsw[] = {    /* SET SSH AGENT LIST switch table */
+    { "/fingerprint", SSHASW_FP, 0 },
+    { "", 0, 0 }
+};
+static int nsshagtsw = (sizeof(sshagtsw) / sizeof(struct keytab)) - 1;
+
+static struct keytab sshkey[] = {      /* SET SSH KEY command table */
+    { "change-passphrase",  SSHK_PASS, 0 },
+    { "create",             SSHK_CREA, 0 },
+    { "display",            SSHK_DISP, 0 },
+    { "v1",                 SSHK_V1,   0 },
+    { "", 0, 0 }
+};
+static int nsshkey = (sizeof(sshkey) / sizeof(struct keytab)) - 1;
+
+static struct keytab sshkv1[] = {      /* SET SSH KEY V1 command table */
+    { "set-comment",  1, 0 }
+};
+
+static struct keytab sshkpsw[] = {     /* SET SSH KEY PASSPHRASE table */
+    { "/new-passphrase",  2, CM_ARG },
+    { "/old-passphrase",  1, CM_ARG }
+};
+
+static struct keytab sshkcrea[] = {    /* SSH KEY CREATE table */
+    { "/bits",           SSHKC_BI, CM_ARG },
+    { "/passphrase",     SSHKC_PP, CM_ARG },
+    { "/type",           SSHKC_TY, CM_ARG },
+    { "/v1-rsa-comment", SSHKC_1R, CM_ARG }
+};
+static int nsshkcrea = (sizeof(sshkcrea) / sizeof(struct keytab));
+
+static struct keytab sshkcty[] = {     /* SSH KEY CREATE /TYPE:xxx */
+    { "srp",    SSHKT_SRP, 0 },
+    { "v1-rsa", SSHKT_1R, 0 },
+    { "v2-dsa", SSHKT_2D, 0 },
+    { "v2-rsa", SSHKT_2R, 0 }
+};
+static int nsshkcty = (sizeof(sshkcty) / sizeof(struct keytab));
+
+static struct keytab sshdswi[] = {     /* SET SSH KEY DISPLAY /switches */
+    { "/format", SSHKD_OUT, CM_ARG }
+};
+static int nsshdswi = (sizeof(sshdswi) / sizeof(struct keytab));
+
+#ifdef COMMENT
+static struct keytab sshdifmt[] = {    /* SSH KEY DISPLAY /IN-FORMAT: */
+    { "openssh", SKDF_OSSH, 0 },
+    { "ssh.com", SKDF_SSHC, 0 }
+};
+static int nsshdifmt = (sizeof(sshdifmt) / sizeof(struct keytab));
+#endif /* COMMENT */
+
+static struct keytab sshdofmt[] = {    /* SSH KEY DISPLAY /IN-FORMAT: */
+    { "fingerprint", SKDF_FING, 0 },
+    { "ietf",        SKDF_IETF, 0 },
+    { "openssh",     SKDF_OSSH, 0 },
+    { "ssh.com",     SKDF_SSHC, 0 }
+};
+static int nsshdofmt = (sizeof(sshdofmt) / sizeof(struct keytab));
+
+static struct keytab sshkermit[] = { /* SKERMIT */
+    { "open",       SKRM_OPN, 0 }
+};
+static int nsshkermit = (sizeof(sshkermit) / sizeof(struct keytab));
+
+struct keytab sshkrmopnsw[] = {
+    { "/password",       SSHSW_PWD, CM_ARG },
+    { "/user",           SSHSW_USR, CM_ARG },
+    { "/version",        SSHSW_VER, CM_ARG },
+    { "", 0, 0 }
+};
+int nsshkrmopnsw = (sizeof(sshkrmopnsw) / sizeof(struct keytab)) - 1;
+#endif /* SSHBUILTIN */
+
+#ifdef SFTP_BUILTIN
+static struct keytab sftpkwtab[] = {    /* SFTP */
+    {  "cd",        SFTP_CD,    0 },
+    {  "chgrp",     SFTP_CHGRP, 0 },
+    {  "chmod",     SFTP_CHMOD, 0 },
+    {  "chown",     SFTP_CHOWN, 0 },
+    {  "delete",    SFTP_RM,    0 },
+    {  "dir",       SFTP_DIR,   0 },
+    {  "get",       SFTP_GET,   0 },
+    {  "mkdir",     SFTP_MKDIR, 0 },
+    {  "open",      SFTP_OPN,   0 },
+    {  "put",       SFTP_PUT,   0 },
+    {  "pwd",       SFTP_PWD,   0 },
+    {  "rename",    SFTP_REN,   0 },
+    {  "rm",        SFTP_RM,    CM_INV },
+    {  "rmdir",     SFTP_RMDIR, 0 },
+    {  "symlink",   SFTP_LINK,  0 },
+    {  "version",   SFTP_VER,   0 }
+};
+static int nsftpkwtab = (sizeof(sftpkwtab) / sizeof(struct keytab));
+#endif /* SFTP_BUILTIN */
+#endif /* ANYSSH */
+
+#ifdef NETCONN
+struct keytab netkey[] = {             /* SET NETWORK table */
+    { "directory", XYNET_D,  0 },
+    { "type",      XYNET_T,  0 }
+};
+int nnetkey = (sizeof(netkey) / sizeof(struct keytab));
+
+struct keytab netcmd[] = {
+/*
+  These are the network types.
+*/
+#ifdef NETCMD
+    { "command",       NET_CMD,  CM_INV }, /* Command */
+#endif /* NETCMD */
+
+#ifdef DECNET                          /* DECnet / PATHWORKS */
+    { "decnet",        NET_DEC,  0 },
+#endif /* DECNET */
+
+#ifdef NETDLL
+    { "dll",           NET_DLL,  CM_INV }, /* DLL to be loaded */
+#endif /* NETDLL */
+
+#ifdef NETFILE
+    { "file",           NET_FILE, CM_INV }, /* FILE (real crude) */
+#endif /* NETFILE */
+
+#ifdef NPIPE                           /* Named Pipes */
+    { "named-pipe",     NET_PIPE,  0 },
+#endif /* NPIPE */
+
+#ifdef CK_NETBIOS
+    { "netbios",        NET_BIOS,  0 },        /* NETBIOS */
+#endif /* CK_NETBIOS */
+
+#ifdef DECNET                          /* DECnet / PATHWORKS (alias) */
+    { "pathworks",     NET_DEC,  CM_INV },
+#endif /* DECNET */
+
+#ifdef NETCMD
+    { "pipe",          NET_CMD,  0 },  /* Pipe */
+#endif /* NETCMD */
+
+#ifdef NETPTY
+    { "pseudoterminal",NET_PTY, 0 },   /* Pseudoterminal */
+#endif /* NETPTY */
+
+#ifdef NETPTY
+    { "pty",          NET_PTY,  CM_INV }, /* Inv syn for pseudoterm */
+#endif /* NETPTY */
+
+#ifdef SSHBUILTIN
+    { "ssh",          NET_SSH,  0 },
+#endif /* SSHBUILTIN */
+
+#ifdef SUPERLAT
+    { "superlat",     NET_SLAT, 0 },   /* Meridian Technologies' SuperLAT */
+#endif /* SUPERLAT */
+
+#ifdef TCPSOCKET                       /* TCP/IP sockets library */
+    { "tcp/ip",       NET_TCPB, 0 },
+#endif /* TCPSOCKET */
+#ifdef SUPERLAT
+    { "tes32",        NET_SLAT, 0 },   /* Emulux TES32 */
+#endif /* SUPERLAT */
+#ifdef ANYX25                          /* X.25 */
+#ifdef SUNX25
+    { "x",            NET_SX25, CM_INV|CM_ABR },
+    { "x.25",         NET_SX25, 0 },
+    { "x25",          NET_SX25, CM_INV },
+#else
+#ifdef STRATUSX25
+    { "x",            NET_VX25, CM_INV|CM_ABR },
+    { "x.25",         NET_VX25, 0 },
+    { "x25",          NET_VX25, CM_INV },
+#endif /* STRATUSX25 */
+#endif /* SUNX25 */
+#ifdef IBMX25
+    { "x",            NET_IX25, CM_INV|CM_ABR },
+    { "x.25",         NET_IX25, CM_INV },
+    { "x25",          NET_IX25, CM_INV },
+#endif /* IBMX25 */
+#ifdef HPX25
+    { "x",            NET_IX25, CM_INV|CM_ABR },
+    { "x.25",         NET_IX25, 0 },
+    { "x25",          NET_IX25, CM_INV },
+#endif /* HPX25 */
+#endif /* ANYX25 */
+    { "", 0, 0 }
+};
+int nnets = (sizeof(netcmd) / sizeof(struct keytab));
+
+#ifndef NOTCPOPTS
+#ifdef TCPSOCKET
+
+/* TCP options */
+
+struct keytab tcpopt[] = {
+    { "address",   XYTCP_ADDRESS, 0 },
+#ifdef CK_DNS_SRV
+    { "dns-service-records", XYTCP_DNS_SRV, 0 },
+#endif /* CK_DNS_SRV */
+#ifdef SO_DONTROUTE
+    { "dontroute",   XYTCP_DONTROUTE, 0 },
+#endif /* SO_DONTROUTE */
+#ifndef NOHTTP
+    { "http-proxy", XYTCP_HTTP_PROXY, 0 },
+#endif /* NOHTTP */
+#ifdef SO_KEEPALIVE
+    { "keepalive", XYTCP_KEEPALIVE, 0 },
+#endif /* SO_KEEPALIVE */
+#ifdef SO_LINGER
+    { "linger", XYTCP_LINGER, 0 },
+#endif /* SO_LINGER */
+#ifdef TCP_NODELAY
+    { "nagle",  XYTCP_NAGLE,    CM_INV },
+    { "nodelay", XYTCP_NODELAY, 0 },
+#endif /* TCP_NODELAY */
+    { "reverse-dns-lookup", XYTCP_RDNS, 0 },
+#ifdef SO_RCVBUF
+    { "recvbuf", XYTCP_RECVBUF, 0 },
+#endif /* SO_RCVBUF */
+#ifdef SO_SNDBUF
+    { "sendbuf", XYTCP_SENDBUF, 0 },
+#endif /* SO_SNDBUF */
+#ifdef NT
+#ifdef CK_SOCKS
+    { "socks-server", XYTCP_SOCKS_SVR, 0 },
+#endif /* CK_SOCKS */
+#endif /* NT */
+#ifdef VMS
+#ifdef DEC_TCPIP
+    { "ucx-port-bug", XYTCP_UCX, 0 },
+#endif /* DEC_TCPIP */
+#endif /* VMS */
+    { "",0,0 }
+};
+int ntcpopt = (sizeof(tcpopt) / sizeof(struct keytab));
+#endif /* TCPSOCKET */
+#endif /* NOTCPOPTS */
+#endif /* NETCONN */
+
+#ifdef OS2
+/* K95 Manual Chapter Table -- Keep these two tables in sync! */
+
+static char * linktbl[] = {            /* Internal links in k95.htm */
+    "#top",                            /* 00 */
+    "#what",                           /* 01 */
+    "#install",                                /* 02 */
+    "#start",                          /* 03 */
+    "#dialer",                         /* 04 */
+    "#entries",                                /* 05 */
+    "#command",                                /* 06 */
+    "#terminal",                       /* 07 */
+    "#transfer",                       /* 08 */
+    "#hostmode"                                /* 09 */
+};
+
+static struct keytab chaptbl[] = {
+    { "Command-Screen",     6, 0 },
+    { "Contents",           0, 0 },
+    { "Dialer-Entries",     5, 0 },
+    { "File-Transfer",      8, 0 },
+    { "Getting-Started",    3, 0 },
+    { "Host-Mode",          9, 0 },
+    { "Installation",       2, 0 },
+    { "Terminal-Emulation", 7, 0 },
+    { "Using-The-Dialer",   4, 0 },
+    { "What-Is-K95",        1, 0 },
+    { "",                   0, 0 }
+};
+static int nchaptbl = (sizeof(chaptbl) / sizeof(struct keytab) - 1);
+#endif /* OS2 */
+
+#ifndef NOXFER
+/* Remote Command Table */
+
+struct keytab remcmd[] = {
+#ifndef NOSPL
+    { "as",        XZASG, CM_INV|CM_ABR },
+    { "asg",       XZASG, CM_INV },
+    { "assign",    XZASG, 0 },
+#endif /* NOSPL */
+    { "cd",        XZCWD, 0 },
+    { "cdup",      XZCDU, CM_INV },
+    { "copy",      XZCPY, 0 },
+    { "cwd",       XZCWD, CM_INV },
+    { "delete",    XZDEL, 0 },
+    { "directory", XZDIR, 0 },
+    { "e",         XZXIT, CM_ABR|CM_INV },
+    { "erase",     XZDEL, CM_INV },
+    { "exit",      XZXIT, 0 },
+    { "help",      XZHLP, 0 },
+#ifndef NOPUSH
+    { "host",      XZHOS, 0 },
+#endif /* NOPUSH */
+#ifndef NOFRILLS
+    { "kermit",    XZKER, 0 },
+    { "l",         XZLGI, CM_ABR|CM_INV },
+    { "lo",        XZLGI, CM_ABR|CM_INV },
+    { "log",       XZLGI, CM_ABR|CM_INV },
+    { "login",     XZLGI, 0 },
+    { "logout",    XZLGO, 0 },
+    { "mkdir",     XZMKD, 0 },
+    { "print",     XZPRI, 0 },
+#endif /* NOFRILLS */
+    { "pwd",       XZPWD, 0 },
+#ifndef NOSPL
+    { "query",    XZQUE, 0 },
+#endif /* NOSPL */
+    { "rename",    XZREN, 0 },
+    { "rmdir",     XZRMD, 0 },
+    { "set",       XZSET, 0 },
+    { "space",    XZSPA, 0 },
+#ifndef NOFRILLS
+    { "type",      XZTYP, 0 },
+    { "who",       XZWHO, 0 },
+#endif /* NOFRILLS */
+    { "", 0, 0}
+};
+int nrmt = (sizeof(remcmd) / sizeof(struct keytab)) - 1;
+#endif /* NOXFER */
+
+struct keytab logtab[] = {
+#ifdef CKLOGDIAL
+    { "connections",  LOGM, CM_INV },
+    { "cx",           LOGM, 0 },
+#endif /* CKLOGDIAL */
+#ifdef DEBUG
+    { "debugging",    LOGD, 0 },
+#endif /* DEBUG */
+    { "packets",      LOGP, 0 },
+#ifndef NOLOCAL
+    { "session",      LOGS, 0 },
+#endif /* NOLOCAL */
+#ifdef TLOG
+    { "transactions", LOGT, 0 },
+#endif /* TLOG */
+    { "", 0, 0 }
+};
+int nlog = (sizeof(logtab) / sizeof(struct keytab)) - 1;
+
+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 },
+#ifndef NOLOCAL
+    { "session-log",     LOGS, 0 },
+#endif /* NOLOCAL */
+    { "sys$output",      LOGX, CM_INV },
+    { "t",               LOGT, CM_ABR|CM_INV }, /* Because of a typo in */
+    { "tr",              LOGT, CM_ABR|CM_INV }, /* the book... */
+    { "tra",             LOGT, CM_ABR|CM_INV },
+    { "tran",            LOGT, CM_ABR|CM_INV },
+    { "trans",           LOGT, CM_ABR|CM_INV },
+    { "transa",          LOGT, CM_ABR|CM_INV },
+    { "transac",         LOGT, CM_ABR|CM_INV },
+    { "transact",        LOGT, CM_ABR|CM_INV },
+    { "transacti",       LOGT, CM_ABR|CM_INV },
+    { "transactio",      LOGT, CM_ABR|CM_INV },
+    { "transaction",     LOGT, CM_ABR|CM_INV },
+    { "transaction-log", LOGT, 0 },
+    { "transactions",    LOGT, CM_INV }
+};
+int nwri = (sizeof(writab) / sizeof(struct keytab));
+
+#ifdef COMMENT                         /* INPUT switches not used yet... */
+static struct keytab inswtab[] = {
+#ifdef COMMENT
+    { "/assign",       IN_ASG, CM_ARG },
+#endif /* COMMENT */
+    { "/autodownload", IN_ADL, CM_ARG },
+    { "/case",         IN_CAS, CM_ARG },
+    { "/echo",         IN_ECH, CM_ARG },
+    { "/interrupts",   IN_NOI, CM_ARG },
+    { "/silence",      IN_SIL, CM_ARG },
+#ifdef COMMENT
+    { "/pattern",      IN_PAT, CM_ARG },
+#endif /* COMMENT */
+    { "", 0, 0 }
+};
+static int ninswtab = (sizeof(inswtab) / sizeof(struct keytab)) - 1;
+#endif /* COMMENT */
+
+static struct keytab clrtab[] = {      /* Keywords for CLEAR command */
+#ifndef NOSPL
+    { "alarm",            CLR_ALR,         0 },
+#ifdef CK_APC
+    { "apc",              CLR_APC,         0 },
+#endif /* CK_APC */
+#ifdef PATTERNS
+    { "binary-patterns",  CLR_BIN,         0 },
+#endif /* PATTERNS */
+    { "both",             CLR_DEV|CLR_INP, CM_INV },
+#endif /* NOSPL */
+#ifdef OS2
+    { "command-screen",   CLR_CMD,         0 },
+#endif /* OS2 */
+#ifndef NOSPL
+    { "device",           CLR_DEV,         CM_INV|CM_ABR },
+    { "device-and-input", CLR_DEV|CLR_INP, 0 },
+#endif /* NOSPL */
+    { "device-buffer",    CLR_DEV,         0 },
+#ifndef NODIAL
+    { "dial-status",      CLR_DIA,      0 },
+#endif /* NODIAL */
+#ifndef NOSPL
+    { "input-buffer",     CLR_INP,         0 },
+#endif /* NOSPL */
+    { "keyboard-buffer",  CLR_KBD,         0 },
+    { "send-list",        CLR_SFL,         0 },
+#ifdef OS2
+    { "scr",              CLR_SCL,         CM_INV|CM_ABR },
+#endif /* OS2 */
+    { "screen",           CLR_SCR,         0 },
+#ifdef OS2
+    { "scrollback",       CLR_SCL,         CM_INV },
+    { "terminal-screen",  CLR_TRM,         0 },
+#endif /* OS2 */
+#ifdef PATTERNS
+    { "text-patterns",    CLR_TXT,         0 },
+#endif /* PATTERNS */
+    { "", 0, 0 }
+};
+int nclear = (sizeof(clrtab) / sizeof(struct keytab)) - 1;
+
+struct keytab clstab[] = {             /* Keywords for CLOSE command */
+#ifndef NOSPL
+    { "!read",           LOGR, CM_INV },
+    { "!write",          LOGW, CM_INV },
+#ifndef NOPUSH
+#endif /* NOPUSH */
+#endif /* NOSPL */
+#ifndef NOSPL
+    { "append-file",     LOGW, CM_INV },
+#endif /* NOSPL */
+#ifndef NOLOCAL
+    { "connection",      9999, 0 },
+#endif /* NOLOCAL */
+#ifdef CKLOGDIAL
+    { "cx-log",          LOGM, 0 },
+#endif /* CKLOGDIAL */
+#ifdef DEBUG
+    { "debug-log",       LOGD, 0 },
+#endif /* DEBUG */
+    { "host",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
+    { "line",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
+    { "p",               LOGP, CM_INV|CM_ABR },
+    { "packet-log",      LOGP, 0 },
+    { "port",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
+#ifndef NOSPL
+    { "read-file",       LOGR, 0 },
+#endif /* NOSPL */
+#ifndef NOLOCAL
+    { "session-log",     LOGS, 0 },
+#endif /* NOLOCAL */
+#ifdef TLOG
+    { "t",               LOGT, CM_ABR|CM_INV }, /* Because of a typo in */
+    { "tr",              LOGT, CM_ABR|CM_INV }, /* the book... */
+    { "tra",             LOGT, CM_ABR|CM_INV },
+    { "tran",            LOGT, CM_ABR|CM_INV },
+    { "trans",           LOGT, CM_ABR|CM_INV },
+    { "transa",          LOGT, CM_ABR|CM_INV },
+    { "transac",         LOGT, CM_ABR|CM_INV },
+    { "transact",        LOGT, CM_ABR|CM_INV },
+    { "transacti",       LOGT, CM_ABR|CM_INV },
+    { "transactio",      LOGT, CM_ABR|CM_INV },
+    { "transaction",     LOGT, CM_ABR|CM_INV },
+    { "transaction-log", LOGT, 0 },
+    { "transactions",    LOGT, CM_INV },
+#endif /* TLOG */
+#ifndef NOSPL
+    { "write-file",      LOGW, 0 },
+#endif /* NOSPL */
+    { "", 0, 0 }
+};
+int ncls = (sizeof(clstab) / sizeof(struct keytab)) - 1;
+
+/* SHOW command arguments */
+
+#ifndef NOSHOW
+struct keytab shotab[] = {
+#ifndef NOSPL
+    { "alarm",        SHALRM, 0 },
+    { "arg",          SHARG, CM_INV|CM_ABR },
+    { "arguments",    SHARG, 0 },
+    { "args",         SHARG, CM_INV },
+    { "arrays",       SHARR, 0 },
+#endif /* NOSPL */
+
+#ifndef NOCSETS
+    { "associations", SHASSOC, 0 },
+#endif /* NOCSETS */
+
+#ifndef NOXFER
+    { "attributes",   SHATT, 0 },
+#endif /* NOXFER */
+
+#ifdef CK_AUTHENTICATION
+    { "authentication", SHOAUTH, CM_INV },
+#endif /* CK_AUTHENTICATION */
+
+#ifndef NOPUSH
+#ifdef BROWSER
+    { "browser",      SHBROWSE, CM_PSH|CM_LOC },
+#endif /*  BROWSER */
+#endif /* NOPUSH */
+    { "cd",           SHCD, 0 },
+    { "character-sets", SHCSE, 0 },
+    { "cmd",          SHCMD, CM_INV },
+#ifndef NOLOCAL
+    { "com",          SHCOM, CM_INV|CM_ABR },
+    { "comm",         SHCOM, CM_INV|CM_ABR },
+    { "communications", SHCOM, 0 },
+#endif /* NOLOCAL */
+    { "command",      SHCMD, 0 },
+    { "connection",   SHCONNX, 0 },
+#ifdef CK_SPEED
+    { "control-prefixing", SHCTL, 0 },
+#endif /* CK_SPEED */
+#ifdef CKLOGDIAL
+    { "cx",           SHCONNX, CM_INV },
+#endif /* CKLOGDIAL */
+#ifndef NOSPL
+    { "count",        SHCOU, 0 },
+#endif /* NOSPL */
+    { "d",            SHDIA, CM_INV|CM_ABR },
+#ifdef VMS
+    { "default",      SHDFLT, 0 },
+#else
+    { "default",      SHDFLT, CM_INV },
+#endif /* VMS */
+#ifndef NODIAL
+    { "dial",         SHDIA, CM_LOC },
+#endif /* NODIAL */
+    { "double/ignore",SHDBL, 0 },
+#ifndef NOPUSH
+#ifndef NOFRILLS
+    { "editor",       SHEDIT, CM_PSH },
+#endif /*  NOFRILLS */
+#endif /* NOPUSH */
+#ifndef NOLOCAL
+    { "escape",       SHESC, CM_LOC },
+#endif /* NOLOCAL */
+    { "exit",         SHEXI, 0 },
+    { "extended-options", SHXOPT, CM_INV },
+    { "features",     SHFEA, 0 },
+    { "file",         SHFIL, 0 },
+#ifndef NOLOCAL
+    { "flow-control", SHOFLO, 0 },
+#endif /* NOLOCAL */
+#ifdef BROWSER
+    { "ftp",          SHOFTP, CM_PSH|CM_LOC },
+#else
+#ifndef NOFTP
+#ifndef SYSFTP
+#ifdef TCPSOCKET
+    { "ftp",          SHOFTP, 0 },     /* (built-in ftp) */
+#endif /* TCPSOCKET */
+#endif /* SYSFTP */
+#endif /* NOFTP */
+#endif /* BROWSER */
+#ifndef NOSPL
+    { "functions",    SHFUN, 0 },
+    { "globals",      SHVAR, 0 },
+#endif /* NOSPL */
+#ifdef KUI
+    { "gui",          SHOGUI, 0 },
+#endif /* KUI */
+#ifdef CK_RECALL
+    { "history",      SHHISTORY, 0 },
+#endif /* CK_RECALL */
+    { "ignore/double",SHDBL, CM_INV },
+    { "iksd",         SHOIKS, CM_INV },
+#ifndef NOSPL
+    { "input",        SHINP, 0 },
+#endif /* NOSPL */
+#ifndef NOSETKEY
+    { "k",            SHKEY, CM_INV|CM_ABR },
+    { "key",          SHKEY, 0 },
+#ifndef NOKVERBS
+    { "kverbs",       SHKVB, 0 },
+#endif /* NOKVERBS */
+#endif /* NOSETKEY */
+#ifdef CK_LABELED
+    { "labeled-file-info", SHLBL, 0 },
+#endif /* CK_LABELED */
+#ifndef NOCSETS
+    { "languages",    SHLNG, 0 },
+#endif /* NOCSETS */
+    { "logs",         SHLOG, 0 },
+#ifndef NOSPL
+    { "macros",       SHMAC, 0 },
+#endif /* NOSPL */
+#ifndef NODIAL
+    { "modem",        SHMOD, CM_LOC },
+#else
+    { "modem-signals",SHCOM, CM_INV|CM_LOC },
+#endif /* NODIAL */
+#ifndef NOLOCAL
+#ifdef OS2MOUSE
+    { "mouse",        SHMOU, CM_LOC },
+#endif /* OS2MOUSE */
+#endif /* NOLOCAL */
+#ifdef NETCONN
+    { "network",      SHNET, CM_LOC },
+#else
+    { "network",      SHNET, CM_INV|CM_LOC },
+#endif /* NETCONN */
+    { "options",      SHOPTS, 0 },
+#ifndef NOSPL
+    { "output",       SHOUTP, CM_INV },
+#endif /* NOSPL */
+#ifdef ANYX25
+#ifndef IBMX25
+    { "pad",          SHPAD,  CM_LOC },
+#endif /* IBMX25 */
+#endif /* ANYX25 */
+    { "parameters",   SHPAR,  CM_INV },
+#ifdef PATTERNS
+    { "patterns",     SHOPAT, 0 },
+#endif /* PATTERNS */
+    { "printer",      SHPRT,  0 },
+#ifdef CK_SPEED
+    { "prefixing",    SHCTL,  CM_INV },
+#endif /* CK_SPEED */
+#ifndef NOXFER
+    { "protocol",     SHPRO,  0 },
+#endif /* NOXFER */
+#ifndef NOSPL
+    { "scripts",      SHSCR,  CM_LOC },
+#endif /* NOSPL */
+    { "send-list",    SHSFL,  0 },
+#ifndef NOSERVER
+    { "server",       SHSER,  0 },
+#endif /* NOSERVER */
+#ifndef NOSEXP
+    { "sexpression",  SHSEXP, 0 },
+#endif /* NOSEXP */
+#ifdef ANYSSH
+    { "ssh",          SHOSSH, 0 },
+#endif /* ANYSSH */
+    { "stack",        SHSTK,  0 },
+    { "status",       SHSTA,  0 },
+#ifdef STREAMING
+    { "streaming",    SHOSTR, 0 },
+#endif /* STREAMING */
+#ifndef NOLOCAL
+#ifdef OS2
+    { "tabs",          SHTAB, CM_INV|CM_LOC },
+#endif /* OS2 */
+#ifdef CK_TAPI
+    { "tapi",          SHTAPI, CM_LOC },
+    { "tapi-comm",     SHTAPI_C, CM_INV|CM_LOC },
+    { "tapi-location", SHTAPI_L, CM_INV|CM_LOC },
+    { "tapi-modem",    SHTAPI_M, CM_INV|CM_LOC },
+#endif /* CK_TAPI */
+    { "tcp",           SHTCP,  CM_LOC },
+#ifdef TNCODE
+    { "tel",           SHTEL,  CM_INV|CM_ABR },
+    { "telnet",        SHTEL,  0 },
+    { "telopt",        SHTOPT, 0 },
+#endif /* TNCODE */
+    { "terminal",      SHTER,  CM_LOC },
+#endif /* NOLOCAL */
+#ifndef NOXMIT
+    { "tr",            SHXMI, CM_INV|CM_ABR },
+    { "tra",           SHXMI, CM_INV|CM_ABR },
+    { "tran",          SHXMI, CM_INV|CM_ABR },
+    { "trans",         SHXMI, CM_INV|CM_ABR },
+#endif /* NOXMIT */
+#ifndef NOXFER
+    { "transfer",      SHOXFER, 0 },
+#endif /* NOXFER */
+#ifndef NOXMIT
+    { "transmit",      SHXMI, 0 },
+#endif /* NOXMIT */
+#ifdef CK_TRIGGER
+    { "trigger",       SHTRIG, CM_LOC },
+#endif /* CK_TRIGGER */
+#ifndef NOSETKEY
+#ifndef NOKVERBS
+#ifdef OS2
+    { "udk",           SHUDK, CM_LOC },
+#endif /* OS2 */
+#endif /* NOKVERBS */
+#endif /* NOSETKEY */
+#ifndef NOSPL
+    { "variables",     SHBUI, 0 },
+#endif /* NOSPL */
+#ifndef NOFRILLS
+    { "versions",      SHVER, 0 },
+#endif /* NOFRILLS */
+#ifdef OS2
+    { "vscrn",         SHVSCRN, CM_INV|CM_LOC },
+#endif /* OS2 */
+    { "xfer",          SHOXFER,  CM_INV },
+#ifndef NOXMIT
+    { "xmit",          SHXMI,    CM_INV },
+#endif /* NOXMIT */
+    { "", 0, 0 }
+};
+int nsho = (sizeof(shotab) / sizeof(struct keytab)) - 1;
+#endif /* NOSHOW */
+
+#ifdef ANYX25
+#ifndef IBMX25
+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 /* IBMX25 */
+#endif /* ANYX25 */
+
+#ifndef NOSERVER
+static struct keytab kmstab[] = {
+    { "both",    3, 0 },
+    { "local",   1, 0 },
+    { "remote",  2, 0 }
+};
+
+static struct keytab enatab[] = {      /* ENABLE commands */
+    { "all",        EN_ALL,  0 },
+#ifndef NOSPL
+    { "as",         EN_ASG,  CM_INV|CM_ABR },
+    { "asg",        EN_ASG,  CM_INV },
+    { "assign",     EN_ASG,  0 },
+#endif /* NOSPL */
+#ifndef datageneral
+    { "bye",        EN_BYE,  0 },
+#endif /* datageneral */
+    { "cd",         EN_CWD,  0 },
+#ifdef ZCOPY
+    { "copy",       EN_CPY,  0 },
+#endif /* ZCOPY */
+    { "cwd",        EN_CWD,  CM_INV },
+    { "delete",     EN_DEL,  0 },
+    { "directory",  EN_DIR,  0 },
+    { "enable",     EN_ENA,  CM_INV },
+    { "exit",       EN_XIT,  0 },
+    { "finish",     EN_FIN,  0 },
+    { "get",        EN_GET,  0 },
+    { "host",       EN_HOS,  0 },
+    { "mail",       EN_MAI,  0 },
+    { "mkdir",      EN_MKD,  0 },
+    { "print",      EN_PRI,  0 },
+#ifndef NOSPL
+    { "query",      EN_QUE,  0 },
+#endif /* NOSPL */
+    { "rename",     EN_REN,  0 },
+    { "retrieve",   EN_RET,  CM_INV },
+    { "rmdir",      EN_RMD,  0 },
+    { "send",       EN_SEN,  0 },
+    { "set",        EN_SET,  0 },
+    { "space",      EN_SPA,  0 },
+    { "type",       EN_TYP,  0 },
+    { "who",        EN_WHO,  0 }
+};
+static int nena = (sizeof(enatab) / sizeof(struct keytab));
+#endif /* NOSERVER */
+
+struct keytab txtbin[] = {
+    { "all",        2, 0 },
+    { "binary",     1, 0 },
+    { "text",       0, 0 }
+};
+
+#ifndef NOXFER
+static struct keytab sndtab[] = {      /* SEND command options */
+    { "/after",           SND_AFT, CM_ARG },
+#ifndef NOSPL
+    { "/array",           SND_ARR, CM_ARG },
+#endif /* NOSPL */
+    { "/as-name",         SND_ASN, CM_ARG },
+    { "/b",               SND_BIN, CM_INV|CM_ABR },
+    { "/before",          SND_BEF, CM_ARG },
+    { "/binary",          SND_BIN, 0 },
+#ifdef CALIBRATE
+    { "/c",               SND_CMD, CM_INV|CM_ABR },
+    { "/calibrate",       SND_CAL, CM_INV|CM_ARG },
+#endif /* CALIBRATE */
+    { "/command",         SND_CMD, CM_PSH },
+    { "/delete",          SND_DEL, 0 },
+#ifdef UNIXOROSK
+    { "/dotfiles",        SND_DOT, 0 },
+#endif /* UNIXOROSK */
+    { "/except",          SND_EXC, CM_ARG },
+#ifdef PIPESEND
+    { "/filter",          SND_FLT, CM_ARG|CM_PSH },
+#endif /* PIPESEND */
+    { "/filenames",       SND_NAM, CM_ARG },
+#ifdef CKSYMLINK
+    { "/followlinks",    SND_LNK, 0 },
+#endif /* CKSYMLINK */
+#ifdef VMS
+    { "/image",           SND_IMG, 0 },
+#else
+    { "/image",           SND_BIN, CM_INV },
+#endif /* VMS */
+#ifdef CK_LABELED
+    { "/labeled",         SND_LBL, 0 },
+#endif /* CK_LABELED */
+    { "/larger-than",     SND_LAR, CM_ARG },
+    { "/listfile",        SND_FIL, CM_ARG },
+#ifndef NOFRILLS
+    { "/mail",            SND_MAI, CM_ARG },
+#endif /* NOFRILLS */
+#ifdef CK_TMPDIR
+    { "/move-to",         SND_MOV, CM_ARG },
+#endif /* CK_TMPDIR */
+    { "/nobackupfiles",   SND_NOB, 0 },
+#ifdef UNIXOROSK
+    { "/nodotfiles",      SND_NOD, 0 },
+#endif /* UNIXOROSK */
+#ifdef CKSYMLINK
+    { "/nofollowlinks",          SND_NLK, 0 },
+#endif /* CKSYMLINK */
+    { "/not-after",       SND_NAF, CM_ARG },
+    { "/not-before",      SND_NBE, CM_ARG },
+    { "/pathnames",       SND_PTH, CM_ARG },
+    { "/print",           SND_PRI, CM_ARG },
+#ifdef CK_XYZ
+    { "/protocol",        SND_PRO, CM_ARG },
+#else
+    { "/protocol",        SND_PRO, CM_ARG|CM_INV },
+#endif /* CK_XYZ */
+    { "/quiet",           SND_SHH, 0 },
+    { "/recover",         SND_RES, 0 },
+#ifdef RECURSIVE
+/* Systems where we do recursion */
+    { "/recursive",       SND_REC, 0 },
+#else
+#ifdef VMS
+/* Systems that do recursion themselves without our assistance */
+/* if we give them the right kind of wildcard */
+    { "/recursive",       SND_REC, 0 },
+#else
+#ifdef datageneral
+    { "/recursive",       SND_REC, 0 },
+#else
+    { "/recursive",       SND_REC, CM_INV },
+#endif /* datageneral */
+#endif /* VMS */
+#endif /* RECURSIVE */
+    { "/rename-to",       SND_REN, CM_ARG },
+    { "/since",           SND_AFT, CM_INV|CM_ARG },
+    { "/smaller-than",    SND_SMA, CM_ARG },
+    { "/starting-at",     SND_STA, CM_ARG },
+#ifndef NOFRILLS
+    { "/su",              SND_ASN, CM_ARG|CM_INV|CM_ABR },
+    { "/sub",             SND_ASN, CM_ARG|CM_INV|CM_ABR },
+    { "/subject",         SND_ASN, CM_ARG },
+#endif /* NOFRILLS */
+#ifdef RECURSIVE
+    { "/subdirectories",  SND_REC, CM_INV },
+#endif /* RECURSIVE */
+    { "/text",            SND_TXT, 0 },
+    { "/transparent",     SND_XPA, 0 },
+    { "/type",            SND_TYP, CM_ARG }
+};
+#define NSNDTAB sizeof(sndtab)/sizeof(struct keytab)
+static int nsndtab = NSNDTAB;
+
+#ifndef NOMSEND
+static struct keytab msndtab[] = {     /* MSEND options */
+    { "/after",           SND_AFT, CM_ARG },
+    { "/before",          SND_BEF, CM_ARG },
+    { "/binary",          SND_BIN, 0 },
+    { "/delete",          SND_DEL, 0 },
+    { "/except",          SND_EXC, CM_ARG },
+    { "/filenames",       SND_NAM, CM_ARG },
+#ifdef CKSYMLINK
+    { "/followlinks",    SND_LNK, 0 },
+#endif /* CKSYMLINK */
+#ifdef VMS
+    { "/image",           SND_IMG, 0 },
+#else
+    { "/image",           SND_BIN, CM_INV },
+#endif /* VMS */
+#ifdef CK_LABELED
+    { "/labeled",         SND_LBL, 0 },
+#endif /* CK_LABELED */
+    { "/larger-than",     SND_LAR, CM_ARG },
+    { "/list",            SND_FIL, CM_ARG },
+#ifndef NOFRILLS
+    { "/mail",            SND_MAI, CM_ARG },
+#endif /* NOFRILLS */
+#ifdef CK_TMPDIR
+    { "/move-to",         SND_MOV, CM_ARG },
+#endif /* CK_TMPDIR */
+#ifdef CKSYMLINK
+    { "/nofollowlinks",        SND_NLK, 0 },
+#endif /* CKSYMLINK */
+    { "/not-after",       SND_NAF, CM_ARG },
+    { "/not-before",      SND_NBE, CM_ARG },
+    { "/pathnames",       SND_PTH, CM_ARG },
+    { "/print",           SND_PRI, CM_ARG },
+#ifdef CK_XYZ
+    { "/protocol",        SND_PRO, CM_ARG },
+#endif /* CK_XYZ */
+    { "/quiet",           SND_SHH, 0 },
+    { "/recover",         SND_RES, 0 },
+    { "/rename-to",       SND_REN, CM_ARG },
+    { "/since",           SND_AFT, CM_INV|CM_ARG },
+    { "/smaller-than",    SND_SMA, CM_ARG },
+    { "/starting-at",     SND_STA, CM_ARG },
+#ifndef NOFRILLS
+    { "/subject",         SND_ASN, CM_ARG },
+#endif /* NOFRILLS */
+    { "/text",            SND_TXT, 0 },
+    { "/transparent",     SND_XPA, 0 },
+    { "/type",            SND_TYP, CM_ARG }
+};
+#define NMSNDTAB sizeof(msndtab)/sizeof(struct keytab)
+static int nmsndtab = NMSNDTAB;
+#endif /* NOMSEND */
+#endif /* NOXFER */
+
+/* CONNECT command switches */
+
+#define CONN_II  0     /* Idle interval */
+#define CONN_IS  1     /* Idle string */
+#define CONN_IL  2     /* Idle limit */
+#define CONN_NV  3     /* Non-Verbose */
+#define CONN_TL  4     /* Time limit */
+#define CONN_TS  5     /* Trigger string */
+#define CONN_AS  6     /* Asynchronous */
+#define CONN_SY  7     /* Synchronous */
+#define CONN_MAX 7     /* Number of CONNECT switches */
+
+#ifndef NOLOCAL
+static struct keytab conntab[] = {
+#ifdef OS2
+    { "/asynchronous",    CONN_AS, CM_INV },
+#endif /* OS2 */
+#ifdef XLIMITS
+    { "/idle-interval",   CONN_II, CM_ARG },
+    { "/idle-limit",      CONN_IL, CM_ARG },
+    { "/idle-string",     CONN_IS, CM_ARG },
+    { "/quietly",         CONN_NV, CM_INV },
+#else
+    { "/quietly",         CONN_NV, 0 },
+#endif /* XLIMITS */
+#ifdef OS2
+    { "/synchronous",     CONN_SY, CM_INV },
+#endif /* OS2 */
+#ifdef XLIMITS
+    { "/time-limit",      CONN_TL, CM_ARG },
+#endif /* XLIMITS */
+#ifdef CK_TRIGGER
+    { "/trigger",         CONN_TS, CM_ARG },
+#endif /* CK_TRIGGER */
+    { "",0,0 }
+};
+#define NCONNTAB sizeof(conntab)/sizeof(struct keytab)
+static int nconntab = NCONNTAB;
+#endif /* NOLOCAL */
+
+#ifndef NOXFER
+static struct keytab stattab[] = {     /* STATISTICS command switches */
+    { "/brief",   1, 0 },
+    { "/verbose", 0, 0 }
+};
+#endif /* NOXFER */
+
+#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 */
+
+#ifndef NOSPL
+#ifdef  OS2
+struct keytab beeptab[] = {            /* Beep options */
+    { "error", BP_FAIL, 0 },
+    { "information", BP_NOTE, 0 },
+    { "warning", BP_WARN, 0 }
+};
+int nbeeptab = sizeof(beeptab)/sizeof(struct keytab);
+
+/* CLEAR COMMMAND-SCREEN options */
+
+#define CLR_C_ALL 0
+#define CLR_C_BOL 1
+#define CLR_C_BOS 2
+#define CLR_C_EOL 3
+#define CLR_C_EOS 4
+#define CLR_C_LIN 5
+#define CLR_C_SCR 6
+
+struct keytab clrcmdtab[] = {
+    { "all",        CLR_C_ALL, 0 },
+    { "bol",        CLR_C_BOL, 0 },
+    { "bos",        CLR_C_BOS, 0 },
+    { "eol",        CLR_C_EOL, 0 },
+    { "eos",        CLR_C_EOS, 0 },
+    { "line",       CLR_C_LIN, 0 },
+    { "scrollback", CLR_C_SCR, 0 }
+};
+int nclrcmd = sizeof(clrcmdtab)/sizeof(struct keytab);
+#endif /* OS2 */
+#endif /* NOSPL */
+
+#ifdef COMMENT
+/* Not used at present */
+static struct keytab pagetab[] = {
+    { "/more",   1, CM_INV },
+    { "/nopage", 0, 0 },
+    { "/page",   1, 0 }
+};
+int npagetab = sizeof(pagetab)/sizeof(struct keytab);
+#endif /* COMMENT */
+
+#define TYP_NOP  0                     /* /NOPAGE */
+#define TYP_PAG  1                     /* /PAGE */
+#define TYP_HEA  2                     /* /HEAD:n */
+#define TYP_TAI  3                     /* /TAIL:n */
+#define TYP_PAT  4                     /* /MATCH:pattern */
+#define TYP_WID  5                     /* /WIDTH:cols */
+#define TYP_COU  6                     /* /COUNT */
+#define TYP_OUT  7                     /* /OUTPUT:file */
+#define TYP_PFX  8                     /* /PREFIX:string */
+#ifdef UNICODE
+#define TYP_XIN  9                     /* /TRANSLATE-FROM:charset */
+#define TYP_XUT 10                     /* /TRANSLATE-TO:charset */
+#define TYP_XPA 11                     /* /TRANSPARENT */
+#endif /* UNICODE */
+#ifdef KUI
+#define TYP_GUI 12                     /* /GUI:title */
+#define TYP_HIG 13                     /* /HEIGHT:rows */
+#endif /* KUI */
+#define TYP_NUM 14                     /* /NUMBER */
+
+static struct keytab typetab[] = {     /* TYPE command switches */
+    { "/count",          TYP_COU, 0 },
+#ifdef UNICODE
+    { "/character-set",  TYP_XIN, CM_ARG },
+#endif /* UNICODE */
+#ifdef KUI
+    { "/gui",            TYP_GUI, CM_ARG },
+#endif /* KUI */
+    { "/head",           TYP_HEA, CM_ARG },
+#ifdef KUI
+    { "/height",         TYP_HIG, CM_ARG },
+#endif /* KUI */
+    { "/match",          TYP_PAT, CM_ARG },
+#ifdef CK_TTGWSIZ
+    { "/more",           TYP_PAG, CM_INV },
+    { "/nopage",         TYP_NOP, 0 },
+    { "/number",         TYP_NUM, 0 },
+    { "/output",         TYP_OUT, CM_ARG },
+    { "/page",           TYP_PAG, 0 },
+#endif /* CK_TTGWSIZ */
+    { "/prefix",         TYP_PFX, CM_ARG },
+    { "/tail",           TYP_TAI, CM_ARG },
+#ifdef UNICODE
+    { "/translate-to",   TYP_XUT, CM_ARG },
+    { "/transparent",    TYP_XPA, 0 },
+#endif /* UNICODE */
+    { "/width",          TYP_WID, CM_ARG },
+#ifdef UNICODE
+    { "/xlate-to",       TYP_XUT, CM_INV|CM_ARG },
+#endif /* UNICODE */
+    { "", 0, 0 }
+};
+int ntypetab = sizeof(typetab)/sizeof(struct keytab) - 1;
+
+int typ_page = -1;                     /* TYPE /[NO]PAGE default */
+int typ_wid  = -1;
+
+#ifndef NOSPL
+#define TRA_ALL 999                    /* TRACE command */
+#define TRA_ASG 0
+#define TRA_CMD 1
+
+int tra_asg = 0;
+int tra_cmd = 0;
+
+static struct keytab tracetab[] = {    /* TRACE options */
+    { "all",            TRA_ALL, 0 },
+    { "assignments",    TRA_ASG, 0 },
+    { "command-level",  TRA_CMD, 0 }
+};
+static int ntracetab = sizeof(tracetab)/sizeof(struct keytab);
+#endif /* NOSPL */
+
+#ifndef NOSHOW
+VOID
+showtypopts() {
+    printf(" TYPE ");
+    if (typ_page > -1) {
+       prtopt(&optlines,typ_page ? "/PAGE" : "/NOPAGE");
+    } else
+      prtopt(&optlines,"(no options set)");
+    if (typ_wid > -1) {
+       ckmakmsg(tmpbuf,TMPBUFSIZ,"/WIDTH:",ckitoa(typ_wid),NULL,NULL);
+       prtopt(&optlines,tmpbuf);
+    }
+    prtopt(&optlines,"");
+}
+#endif /* NOSHOW */
+
+#ifdef LOCUS
+/* isauto == 1 if locus is being switched automatically */
+
+VOID
+setlocus(x, isauto) int x, isauto; {
+    extern int quitting;
+    if (x) x = 1;
+    if (x && locus) return;
+    if (!x && !locus) return;
+    /* Get here if it actually needs to be changed */
+#ifdef OS2
+    if (isauto &&                      /* Automatically switching */
+       !quitting &&                    /* not exiting */
+       autolocus == 2) {               /* and AUTOLOCUS is set to ASK */
+       char locmsg[300];
+       ckmakmsg(locmsg,300,
+                "Switching Locus to ",
+                x ? "LOCAL" : "REMOTE",
+                " for file management commands\n"
+                 "such as CD, DIRECTORY, DELETE, RENAME.  Type HELP SET\n"
+                 "LOCUS at the K-95> prompt for further info.  Use the\n"
+#ifdef KUI
+                  "Actions menu or SET LOCUS command to disable automatic\n"
+                  "Locus switching or to disable these queries.",
+#else /* KUI */
+                  "SET LOCUS command to disable automatic locus switching\n"
+                  "or to disable these queries.",
+#endif /* KUI */
+                  NULL);
+       if (uq_ok(locmsg,"OK to switch Locus?",3,NULL,1)) {
+           locus = x;
+#ifdef KUI
+           KuiSetProperty(KUI_LOCUS,x,0);
+#endif /* KUI */
+           return;
+       }
+    } else {
+#endif /* OS2 */
+        if (isauto && msgflg && !quitting)
+          printf("Switching LOCUS for file-management commands to %s.\n",
+                x ? "LOCAL" : "REMOTE"
+                );
+       locus = x;
+#ifdef OS2
+#ifdef KUI
+       KuiSetProperty(KUI_LOCUS,x,0);
+#endif /* KUI */
+    }
+#endif /* OS2 */
+}
+
+VOID
+setautolocus(x) int x; {
+    autolocus = x;
+#ifdef KUI
+    KuiSetProperty(KUI_AUTO_LOCUS,x,0);
+#endif /* KUI */
+}
+#endif /* LOCUS */
+
+int
+settypopts() {                         /* Set TYPE option defaults */
+    int xp = -1;
+    int c, getval;
+    while (1) {
+       if ((y = cmswi(typetab,ntypetab,"Switch","",xxstring)) < 0) {
+           if (y == -3)
+             break;
+           else
+             return(y);
+       }
+       c = cmgbrk();
+       if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+           printf("?This switch does not take an argument\n");
+           return(-9);
+       }
+       switch (y) {
+         case TYP_NOP: xp = 0; break;
+         case TYP_PAG: xp = 1; break;
+         case TYP_WID:
+           if (getval)
+             if ((x = cmnum("Column at which to truncate",
+                            ckitoa(cmd_cols),10,&y,xxstring)) < 0)
+               return(x);
+           typ_wid = y;
+           break;
+
+          default:
+           printf("?Sorry, this option can not be set\n");
+           return(-9);
+       }
+    }
+    if ((x = cmcfm()) < 0)             /* Get confirmation */
+      return(x);
+    if (xp > -1) typ_page = xp;                /* Confirmed, save defaults */
+    return(success = 1);
+}
+
+/* Forward declarations of functions local to this module */
+
+#ifdef UNIX
+_PROTOTYP (int douchmod, ( void ) );
+#endif /* UNIX */
+#ifdef CKPURGE
+_PROTOTYP (int dopurge,  ( void ) );
+#endif /* CKPURGE */
+#ifndef NOSPL
+_PROTOTYP (int doundef,  ( int  ) );
+_PROTOTYP (int doask,    ( int  ) );
+_PROTOTYP (int dodef,    ( int  ) );
+_PROTOTYP (int doelse,   ( void ) );
+_PROTOTYP (int dofor,    ( void ) );
+_PROTOTYP (int doincr,   ( int  ) );
+#endif /* NOSPL  */
+#ifndef NODIAL
+_PROTOTYP (int dodial,   ( int  ) );
+#endif /* NODIAL */
+_PROTOTYP (int dodel,    ( void ) );
+_PROTOTYP (int dopaus,   ( int  ) );
+#ifndef NOPUSH
+#ifdef TCPSOCKET
+_PROTOTYP (int doping,   ( void ) );
+_PROTOTYP (int doftp,    ( void ) );
+#endif /* TCPSOCKET */
+#endif /* NOPUSH */
+#ifndef NORENAME
+#ifndef NOFRILLS
+_PROTOTYP (int dorenam,  ( void ) );
+#endif /* NOFRILLS */
+#endif /* NORENAME */
+#ifdef ZCOPY
+_PROTOTYP (int docopy,   ( void ) );
+#endif /* ZCOPY */
+#ifdef NT
+_PROTOTYP (int dolink,   ( void ));
+#endif /* NT */
+#ifdef CK_REXX
+_PROTOTYP (int dorexx,   ( void ) );
+#endif /* CK_REXX */
+
+#ifdef TNCODE
+static struct keytab telcmd[] = {
+    { "abort", TN_ABORT, CM_INV },     /* Emotionally toned - don't show */
+    { "ao",    TN_AO,    0 },
+    { "ayt",   TN_AYT,   0 },
+    { "break", BREAK,    0 },
+    { "cancel",TN_ABORT, 0 },
+    { "dmark", TN_DM,    0 },
+    { "do",    DO,       0 },
+    { "dont",  DONT,     0 },
+    { "ec",    TN_EC,    0 },
+    { "el",    TN_EL,    0 },
+    { "eof",   TN_EOF,   0 },
+    { "eor",   TN_EOR,   0 },
+#ifdef CK_KERBEROS
+#ifdef KRB5
+#define TN_FWD 1
+    { "forward", TN_FWD, CM_INV },
+#endif /* KRB5 */
+#endif /* CK_KERBEROS */
+    { "ga",    TN_GA,    0 },
+    { "ip",    TN_IP,    0 },
+    { "nop",   TN_NOP,   0 },
+    { "sak",   TN_SAK,   CM_INV },
+    { "sb",    SB,       0 },
+    { "se",    SE,       0 },
+    { "susp",  TN_SUSP,  0 },
+    { "will",  WILL,     0 },
+    { "wont",  WONT,     0 }
+};
+static int ntelcmd = (sizeof(telcmd) / sizeof(struct keytab));
+
+static struct keytab tnopts[] = {
+#ifdef CK_AUTHENTICATION
+    { "auth",   TELOPT_AUTHENTICATION,   0 },
+#else
+    { "auth",   TELOPT_AUTHENTICATION,   CM_INV },
+#endif /* CK_AUTHENTICATION */
+    { "binary", TELOPT_BINARY, 0 },
+#ifdef TN_COMPORT
+    { "c",      TELOPT_COMPORT, CM_INV|CM_ABR},
+    { "co",     TELOPT_COMPORT, CM_INV|CM_ABR},
+    { "com",    TELOPT_COMPORT, CM_INV|CM_ABR},
+    { "com-port-control", TELOPT_COMPORT, 0 },
+    { "comport-control", TELOPT_COMPORT, CM_INV},
+#else  /* TN_COMPORT */
+    { "com-port-control", TELOPT_COMPORT, CM_INV },
+    { "comport-control", TELOPT_COMPORT, CM_INV},
+#endif /* TN_COMPORT */
+    { "echo", TELOPT_ECHO, 0 },
+#ifdef CK_ENCRYPTION
+    { "encrypt", TELOPT_ENCRYPTION, 0 },
+#else
+    { "encrypt", TELOPT_ENCRYPTION, CM_INV },
+#endif /* CK_ENCRYPTION */
+#ifdef CK_FORWARD_X
+    { "forward-x", TELOPT_FORWARD_X, 0 },
+#else
+    { "forward-x", TELOPT_FORWARD_X, CM_INV },
+#endif /* CK_FORWARD_X */
+#ifdef IKS_OPTION
+    { "kermit", TELOPT_KERMIT, 0 },
+#else
+    { "kermit", TELOPT_KERMIT, CM_INV },
+#endif /* IKS_OPTION */
+    { "lflow",  TELOPT_LFLOW, CM_INV },
+    { "logout", TELOPT_LOGOUT, CM_INV },
+#ifdef CK_NAWS
+    { "naws", TELOPT_NAWS, 0 },
+#else
+    { "naws", TELOPT_NAWS, CM_INV },
+#endif /* CK_NAWS */
+#ifdef CK_ENVIRONMENT
+    { "new-environment", TELOPT_NEWENVIRON,  0 },
+#else
+    { "new-environment", TELOPT_NEWENVIRON,  CM_INV },
+#endif /* CK_ENVIRONMENT */
+    { "pragma-heartbeat",TELOPT_PRAGMA_HEARTBEAT,  CM_INV },
+    { "pragma-logon",    TELOPT_PRAGMA_LOGON,  CM_INV },
+    { "pragma-sspi",     TELOPT_SSPI_LOGON,  CM_INV },
+    { "sak",   TELOPT_IBM_SAK, CM_INV },
+#ifdef CK_SNDLOC
+    { "send-location",   TELOPT_SNDLOC,  0 },
+#else
+    { "send-location",   TELOPT_SNDLOC,  CM_INV },
+#endif /* CK_SNDLOC */
+    { "sga", TELOPT_SGA, 0 },
+#ifdef CK_SSL
+    { "start-tls",       TELOPT_START_TLS,  0 },
+#else
+    { "start-tls",       TELOPT_START_TLS,  CM_INV },
+#endif /* CK_SSL */
+    { "ttype", TELOPT_TTYPE, 0 },
+#ifdef CK_ENVIRONMENT
+    { "xdisplay-location", TELOPT_XDISPLOC, 0 },
+#else
+    { "xdisplay-location", TELOPT_XDISPLOC, CM_INV },
+#endif /* CK_ENVIRONMENT */
+    { "", 0, 0 }
+};
+static int ntnopts = (sizeof(tnopts) / sizeof(struct keytab)) - 1;
+
+static struct keytab tnsbopts[] = {
+#ifdef CK_NAWS
+    { "naws", TELOPT_NAWS, 0 },
+#endif /* CK_NAWS */
+    { "", 0, 0 }
+};
+static int ntnsbopts = (sizeof(tnsbopts) / sizeof(struct keytab)) - 1;
+#endif /* TNCODE */
+
+#ifdef TCPSOCKET
+#ifndef NOPUSH
+#ifdef SYSFTP
+int
+doftp() {                              /* (External) FTP command */
+    char *p, *f;                       /* (See doxftp() for internal one) */
+    int x;
+
+    if (network)                       /* If we have a current connection */
+      ckstrncpy(line,ttname,LINBUFSIZ);        /* get the host name */
+    else *line = '\0';                 /* as default host */
+    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);
+    if (nopush) {
+        printf("?Sorry, FTP command disabled\n");
+        return(success = 0);
+    }
+/* Construct FTP command */
+#ifdef VMS
+#ifdef MULTINET                                /* TGV MultiNet */
+    ckmakmsg(line,LINBUFSIZ,"multinet ftp ",s,NULL,NULL);
+#else
+    ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
+#endif /* MULTINET */
+#else                                  /* Not VMS */
+#ifdef OS2ORUNIX
+#ifndef NOFTP
+    f = ftpapp;
+    if (!f) f = "";
+    if (!f[0]) f = "ftp";
+    ckmakmsg(line,LINBUFSIZ,f," ",s,NULL);
+#ifdef OS2
+    p = line + strlen(ftpapp);
+    while (p != line) {
+        if (*p == '/') *p = '\\';
+        p--;
+    }
+#endif /* OS2 */
+#else /* NOFTP */
+    ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
+#endif /* NOFTP */
+#else /* OS2ORUNIX */
+    ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
+#endif /* OS2ORUNIX */
+#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 = x);
+}
+#endif /* SYSFTP */
+
+int
+doping() {                             /* PING command */
+    char *p;                           /* just runs ping program */
+    int x;
+
+    if (network)                       /* If we have a current connection */
+      ckstrncpy(line,ttname,LINBUFSIZ);        /* 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);
+    if (nopush) {
+        printf("?Sorry, PING command disabled\n");
+        return(success = 0);
+    }
+
+    /* Construct PING command */
+#ifdef VMS
+#ifdef MULTINET                                /* TGV MultiNet */
+    ckmakmsg(line,LINBUFSIZ,"multinet ping ",s," /num=1",NULL);
+#else
+    ckmakmsg(line,LINBUFSIZ,"ping ",s," 56 1",NULL); /* Other VMS TCP/IP's */
+#endif /* MULTINET */
+#else                                  /* Not VMS */
+    ckmakmsg(line,LINBUFSIZ,"ping ",s,NULL,NULL);
+#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 = x);
+}
+#endif /* NOPUSH */
+#endif /* TCPSOCKET */
+
+static VOID
+doend(x) int x; {
+#ifndef NOSPL
+    /* Pop from all FOR/WHILE/XIF/SWITCH's */
+    debug(F101,"doend maclvl 1","",maclvl);
+    while ((maclvl > 0) &&
+          (m_arg[maclvl-1][0]) &&
+          (cmdstk[cmdlvl].src == CMD_MD) &&
+          (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
+           !strncmp(m_arg[maclvl-1][0],"_for",4) ||
+           !strncmp(m_arg[maclvl-1][0],"_whi",4) ||
+           !strncmp(m_arg[maclvl-1][0],"_swi",4))) {
+       debug(F110,"END popping",m_arg[maclvl-1][0],0);
+       dogta(XXPTA);                   /* Put args back */
+       popclvl();                      /* Pop up two levels */
+       popclvl();
+       debug(F101,"doend maclvl 2","",maclvl);
+    }
+    if (maclvl > -1) {
+       if (mrval[maclvl])              /* Free previous retval if any */
+         free(mrval[maclvl]);
+       mrval[maclvl] = malloc(16);     /* Room for up to 15 digits */
+       if (mrval[maclvl])              /* Record current retval */
+         ckmakmsg(mrval[maclvl],16,ckitoa(x),NULL,NULL,NULL);
+    }
+#endif /* NOSPL */
+    popclvl();                         /* Now pop out of macro or TAKE file */
+#ifndef NOSPL
+#ifdef DEBUG
+    if (deblog) {
+       debug(F101,"END maclvl 3","",maclvl);
+       debug(F111,"END mrval[maclvl]",mrval[maclvl],maclvl);
+       debug(F111,"END mrval[maclvl+1]",mrval[maclvl+1],maclvl+1);
+    }
+#endif /* DEBUG */
+#endif /* NOSPL */
+}
+
+#ifdef CKROOT
+int
+dochroot() {
+    if ((x = cmdir("Name of new root directory","",&s,xxstring)) < 0) {
+       if (x == -3) {
+           printf("?Directory name required\n");
+           return(-9);
+       }
+       return(x);
+    }
+    ckstrncpy(line,s,LINBUFSIZ);
+    s = line;
+    if ((x = cmcfm()) < 0) return(x);
+    s = brstrip(s);
+    x = zsetroot(s);
+    if (x < 0) {
+       char * m = NULL;
+       switch (x) {
+         case -1:
+         case -2: m = "Not a directory"; break;
+         case -3: m = "Internal error"; break;
+         case -4: m = "Access denied"; break;
+         case -5: m = "Off limits"; break;
+       }
+       if (m) printf("%s: \"%s\"\n", m, s);
+       return(m ? -9 : -2);
+    } else {
+       nopush = 1;
+       return(success = 1);
+    }
+}
+#endif /* CKROOT */
+
+#ifndef NOXFER
+static char * asnbuf = NULL;           /* As-name buffer pointer */
+
+char sndxnam[] = { "_array_x_" };      /* (with replaceable x!) */
+
+/*
+  The new SEND command, replacing BSEND, CSEND, PSEND, etc etc.
+  Call with cx = top-level keyword value.  Returns:
+    < 0  On parse error.
+    0    On other type of failure (e.g. requested operation not allowed).
+    1    On success with sstate set to 's' so protocol will begin.
+*/
+
+/*  D O X S E N D  --  Parse SEND and related commands with switches  */
+
+int
+doxsend(cx) int cx; {
+    int c, i, n, wild, confirmed = 0;  /* Workers */
+    int x, y;                          /* of the world... */
+    int getval = 0;                    /* Whether to get switch value */
+    extern char * snd_move;            /* Directory to move sent files to */
+    extern char * snd_rename;          /* What to rename sent files to */
+    extern char * filefile;            /* File containing filenames to send */
+    extern int xfiletype;              /* Send only text (or binary) files */
+    extern struct keytab pathtab[];    /* PATHNAMES option keywords */
+    extern int npathtab;               /* How many of them */
+    extern int recursive;              /* Recursive directory traversal */
+    extern int rprintf;                        /* REMOTE PRINT flag */
+    extern int fdispla;                        /* TRANSFER DISPLAY setting */
+    extern int skipbup;                        /* Skip backup files when sending */
+    struct stringint {                 /* Temporary array for switch values */
+       char * sval;
+       int ival;
+    } pv[SND_MAX+1];
+    struct FDB sf, sw, fl, cm;         /* FDBs for each parse function */
+    int mlist = 0;                     /* Flag for MSEND or MMOVE */
+    char * m;                          /* For making help messages */
+    extern struct keytab protos[];     /* File transfer protocols */
+    extern int xfrxla, g_xfrxla, nprotos;
+    extern char sndbefore[], sndafter[], *sndexcept[]; /* Selection criteria */
+    extern char sndnbefore[], sndnafter[];
+    extern long sndsmaller, sndlarger, calibrate;
+#ifndef NOSPL
+    int range[2];                      /* Array range */
+    char ** ap = NULL;                 /* Array pointer */
+    int arrayx = -1;                   /* Array index */
+#endif /* NOSPL */
+
+#ifdef NEWFTP
+    if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
+       if (cx == XXMAI) {
+           printf("?Sorry, No MAIL with FTP\n");
+           return(-9);
+       }
+       return(doftpput(cx,0));
+    }
+#endif /* NEWFTP */
+
+    for (i = 0; i <= SND_MAX; i++) {   /* Initialize switch values */
+       pv[i].sval = NULL;              /* to null pointers */
+       pv[i].ival = -1;                /* and -1 int values */
+    }
+#ifndef NOSPL
+    range[0] = -1;
+    range[1] = -1;
+    sndxin = -1;                       /* Array index */
+#endif /* NOSPL */
+    sndarray = NULL;                   /* Array pointer */
+
+#ifdef UNIXOROSK
+    g_matchdot = matchdot;             /* Match dot files */
+#endif /* UNIXOROSK */
+    g_recursive = recursive;           /* Recursive sending */
+    recursive = 0;                     /* Save global value, set local */
+    debug(F101,"xsend entry fncnv","",fncnv);
+
+    /* Preset switch values based on top-level command that called us */
+
+    switch (cx) {
+      case XXMSE:                      /* MSEND */
+       mlist = 1; break;
+      case XXCSEN:                     /* CSEND */
+       pv[SND_CMD].ival = 1; break;
+      case XXMMOVE:                    /* MMOVE */
+       mlist = 1;
+      case XXMOVE:                     /* MOVE */
+       pv[SND_DEL].ival = 1; break;
+      case XXRSEN:                     /* RESEND */
+       pv[SND_BIN].ival = 1;           /* Implies /BINARY */
+       pv[SND_RES].ival = 1; break;
+      case XXMAI:                      /* MAIL */
+       pv[SND_MAI].ival = 1; break;
+    }
+
+    /* Set up chained parse functions... */
+
+    cmfdbi(&sw,                                /* First FDB - command switches */
+          _CMKEY,                      /* fcode */
+          "Filename, or switch",       /* hlpmsg */
+          "",                          /* default */
+          "",                          /* addtl string data */
+#ifdef NOMSEND
+          nsndtab,                     /* addtl numeric data 1: tbl size */
+#else
+          mlist ? nmsndtab : nsndtab,  /* addtl numeric data 1: tbl size */
+#endif /* NOMSEND */
+          4,                           /* addtl numeric data 2: 4 = cmswi */
+          xxstring,                    /* Processing function */
+#ifdef NOMSEND
+          sndtab,                      /* Keyword table */
+#else
+          mlist ? msndtab : sndtab,
+#endif /* NOMSEND */
+          &sf                          /* Pointer to next FDB */
+          );
+    cmfdbi(&sf,                                /* 2nd FDB - file to send */
+          _CMIFI,                      /* fcode */
+          "File(s) to send",           /* hlpmsg */
+          "",                          /* default */
+          "",                          /* addtl string data */
+          nolinks,                     /* addtl numeric data 1 */
+          0,                           /* addtl numeric data 2 */
+          xxstring,
+          NULL,
+          mlist ? &cm : &fl
+          );
+    cmfdbi(&fl,                                /* 3rd FDB - command to send from */
+          _CMFLD,                      /* fcode */
+          "Command",                   /* hlpmsg */
+          "",                          /* default */
+          "",                          /* addtl string data */
+          0,                           /* addtl numeric data 1 */
+          0,                           /* addtl numeric data 2 */
+          xxstring,
+          NULL,
+          &cm
+          );
+    cmfdbi(&cm,                                /* 4th FDB - Confirmation */
+          _CMCFM,                      /* fcode */
+          "",                          /* hlpmsg */
+          "",                          /* default */
+          "",                          /* addtl string data */
+          0,                           /* addtl numeric data 1 */
+          0,                           /* addtl numeric data 2 */
+          NULL,
+          NULL,
+          NULL
+          );
+
+    while (1) {                                /* Parse 0 or more switches */
+       x = cmfdb(&sw);                 /* Parse something */
+       debug(F101,"xsend cmfdb","",x);
+       if (x < 0)                      /* Error */
+         goto xsendx;                  /* or reparse needed */
+       if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
+         break;
+/*
+  They gave a switch, but let's see how they terminated it.
+  If they ended it with : or =, then we must parse a value.
+  If they ended it with anything else, then we must NOT parse a value.
+*/
+       c = cmgbrk();                   /* Get break character */
+       getval = (c == ':' || c == '='); /* to see how they ended the switch */
+       if (getval && !(cmresult.kflags & CM_ARG)) {
+           printf("?This switch does not take arguments\n");
+           x = -9;
+           goto xsendx;
+       }
+       if (!getval && (cmgkwflgs() & CM_ARG)) {
+           printf("?This switch requires an argument\n");
+           x = -9;
+           goto xsendx;
+       }
+       n = cmresult.nresult;           /* Numeric result = switch value */
+       debug(F101,"xsend switch","",n);
+
+       switch (n) {                    /* Process the switch */
+         case SND_CMD:                 /* These take no args */
+           if (nopush) {
+               printf("?Sorry, system command access is disabled\n");
+               x = -9;
+               goto xsendx;
+           }
+#ifdef PIPESEND
+           else if (sndfilter) {
+               printf(
+"?Sorry, no SEND /COMMAND or CSEND when SEND FILTER selected\n");
+               x = -9;
+               goto xsendx;
+           }
+#endif /* PIPESEND */
+           sw.hlpmsg = "Command, or switch"; /* Change help message */
+           pv[n].ival = 1;             /* Just set the flag */
+           pv[SND_ARR].ival = 0;
+           break;
+
+         case SND_REC:                 /* /RECURSIVE */
+           recursive = 2;              /* Set the real variable */
+           pv[SND_PTH].ival = PATH_REL; /* Give them relative pathnames */
+           pv[n].ival = 1;             /* Just set the flag */
+           break;
+
+         case SND_RES:                 /* /RECOVER (resend) */
+           pv[SND_ARR].ival = 0;
+           pv[SND_BIN].ival = 1;       /* Implies /BINARY */
+         case SND_NOB:                 /* /NOBACKUP */
+         case SND_DEL:                 /* /DELETE */
+         case SND_SHH:                 /* /QUIET */
+           pv[n].ival = 1;             /* Just set the flag */
+           break;
+
+#ifdef UNIXOROSK
+/* Like recursive, these are set immediately because they affect cmifi() */
+         case SND_DOT:                 /* /DOTFILES */
+           matchdot = 1;
+           break;
+         case SND_NOD:                 /* /NODOTFILES */
+           matchdot = 0;
+           break;
+#endif /* UNIXOROSK */
+
+         /* File transfer modes - each undoes the others */
+
+         case SND_BIN:                 /* Binary */
+         case SND_TXT:                 /* Text */
+         case SND_IMG:                 /* Image */
+         case SND_LBL:                 /* Labeled */
+           pv[SND_BIN].ival = 0;
+           pv[SND_TXT].ival = 0;
+           pv[SND_IMG].ival = 0;
+           pv[SND_LBL].ival = 0;
+           pv[n].ival = 1;
+           break;
+
+#ifdef CKSYMLINK
+         case SND_LNK:
+         case SND_NLK:
+           nolinks = (n == SND_NLK) ? 2 : 0;
+           cmfdbi(&sf,                 /* Redo cmifi() */
+                  _CMIFI,              /* fcode */
+                  "File(s) to send",   /* hlpmsg */
+                  "",                  /* default */
+                  "",                  /* addtl string data */
+                  nolinks,             /* addtl numeric data 1 */
+                  0,                   /* addtl numeric data 2 */
+                  xxstring,
+                  NULL,
+                  mlist ? &cm : &fl
+                  );
+           break;
+#endif /* CKSYMLINK */
+
+         case SND_EXC:                 /* Excludes */
+           if (!getval) break;
+           if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
+               if (x == -3) {
+                   printf("?Pattern required\n");
+                   x = -9;
+               }
+               goto xsendx;
+           }
+           if (pv[n].sval) free(pv[n].sval);
+           y = strlen(s);
+           if (y > 256) {
+               printf("?Pattern too long - 256 max\n");
+               x = -9;
+               goto xsendx;
+           }
+           pv[n].sval = malloc(y+1);
+           if (pv[n].sval) {
+               strcpy(pv[n].sval,s);   /* safe */
+               pv[n].ival = 1;
+           }
+           break;
+
+         case SND_MOV:                 /* MOVE after */
+         case SND_REN:                 /* RENAME after */
+           if (!getval) break;
+           if ((x = cmfld(n == SND_MOV ?
+          "device and/or directory for source file after sending" :
+          "new name for source file after sending",
+                          "",
+                          &s,
+                          n == SND_MOV ? xxstring : NULL
+                          )) < 0) {
+               if (x == -3) {
+                   printf("%s\n", n == SND_MOV ?
+                          "?Destination required" :
+                          "?New name required"
+                          );
+                   x = -9;
+               }
+               goto xsendx;
+           }
+           if (pv[n].sval) free(pv[n].sval);
+           s = brstrip(s);
+           y = strlen(s);
+           if (y > 0) {
+               pv[n].sval = malloc(y+1);
+               if (pv[n].sval) {
+                   strcpy(pv[n].sval,s); /* safe */
+                   pv[n].ival = 1;
+               }
+           }
+           break;
+
+         case SND_SMA:                 /* Smaller / larger than */
+         case SND_LAR:
+           if (!getval) break;
+           if ((x = cmnum("Size in bytes","0",10,&y,xxstring)) < 0)
+             goto xsendx;
+           pv[n].ival = y;
+           break;
+
+         case SND_AFT:                 /* Send /AFTER:date-time */
+         case SND_BEF:                 /* Send /BEFORE:date-time */
+         case SND_NAF:                 /* Send /NOT-AFTER:date-time */
+         case SND_NBE:                 /* Send /NOT-BEFORE:date-time */
+           if (!getval) break;
+           if ((x = cmdate("File date-time","",&s,0,xxstring)) < 0) {
+               if (x == -3) {
+                   printf("?Date-time required\n");
+                   x = -9;
+               }
+               goto xsendx;
+           }
+           if (pv[n].sval) free(pv[n].sval);
+           pv[n].sval = malloc((int)strlen(s)+1);
+           if (pv[n].sval) {
+               strcpy(pv[n].sval,s);   /* safe */
+               pv[n].ival = 1;
+           }
+           break;
+
+         case SND_MAI:                 /* Send as mail (= MAIL) */
+#ifdef IKSD
+           if (inserver && !ENABLED(en_mai)) {
+               printf("?Sorry, sending files as mail is disabled\n");
+               return(-9);
+           }
+#endif /* IKSD */
+           pv[n].ival = 1;
+           if (!getval) break;
+           if ((x = cmfld("e-mail address","",&s,xxstring)) < 0) {
+               if (x == -3) {
+                   printf("?address required\n");
+                   x = -9;
+               }
+               goto xsendx;
+           }
+           s = brstrip(s);
+           if (pv[n].sval) free(pv[n].sval);
+           pv[n].sval = malloc((int)strlen(s)+1);
+           if (pv[n].sval)
+             strcpy(pv[n].sval,s);     /* safe */
+           break;
+
+         case SND_PRI:                 /* Send to be printed (REMOTE PRINT) */
+#ifdef IKSD
+           if (inserver && !ENABLED(en_mai)) {
+               printf("?Sorry, sending files for printing is disabled\n");
+               return(-9);
+           }
+#endif /* IKSD */
+           pv[n].ival = 1;
+           if (!getval) break;
+           if ((x = cmfld("Print options","",&s,xxstring)) < 0)
+             if (x != -3) goto xsendx;
+           s = brstrip(s);
+           if (pv[n].sval) free(pv[n].sval);
+           pv[n].sval = malloc((int)strlen(s)+1);
+           if (pv[n].sval)
+             strcpy(pv[n].sval,s);     /* safe */
+           break;
+
+         case SND_ASN:                 /* As-name */
+           debug(F101,"xsend /as-name getval","",getval);
+           if (!getval) break;
+           if ((x = cmfld("Name to send under","",&s,NULL)) < 0) {
+               if (x == -3) {
+                   printf("?name required\n");
+                   x = -9;
+               }
+               goto xsendx;
+           }
+           s = brstrip(s);
+           if ((y = strlen(s)) > 0) {
+               if (pv[n].sval) free(pv[n].sval);
+               pv[n].sval = malloc(y+1);
+               if (pv[n].sval) {
+                   strcpy(pv[n].sval,s); /* safe */
+                   pv[n].ival = 1;
+               }
+           }
+           break;
+
+         case SND_STA:                 /* Starting position (= PSEND) */
+           if (!getval) break;
+           if ((x = cmnum("0-based position","0",10,&y,xxstring)) < 0)
+             goto xsendx;
+           pv[n].ival = y;
+           break;
+
+         case SND_PRO:                 /* Protocol to use */
+           if (!getval) break;
+           if ((x = cmkey(protos,nprotos,"File-transfer protocol","",
+                          xxstring)) < 0) {
+               if (x == -3) {
+                   printf("?name of protocol required\n");
+                   x = -9;
+               }
+               goto xsendx;
+           }
+           pv[n].ival = x;
+           break;
+
+#ifdef PIPESEND
+         case SND_FLT:                 /* Filter */
+           debug(F101,"xsend /filter getval","",getval);
+           if (!getval) break;
+           if ((x = cmfld("Filter program to send through","",&s,NULL)) < 0) {
+               if (x == -3)
+                 s = "";
+               else
+                 goto xsendx;
+           }
+           if (*s) s = brstrip(s);
+           y = strlen(s);
+           for (x = 0; x < y; x++) {   /* Make sure they included "\v(...)" */
+               if (s[x] != '\\') continue;
+               if (s[x+1] == 'v') break;
+           }
+           if (x == y) {
+               printf(
+               "?Filter must contain a replacement variable for filename.\n"
+                      );
+               x = -9;
+               goto xsendx;
+           }
+           pv[n].ival = 1;
+           if (pv[n].sval) {
+               free(pv[n].sval);
+               pv[n].sval = NULL;
+           }
+           if ((y = strlen(s)) > 0) {
+               if ((pv[n].sval = malloc(y+1)))
+                 strcpy(pv[n].sval,s); /* safe */
+           }
+           break;
+#endif /* PIPESEND */
+
+         case SND_PTH:                 /* Pathnames */
+           if (!getval) {
+               pv[n].ival = PATH_REL;
+               break;
+           }
+           if ((x = cmkey(pathtab,npathtab,"","absolute",xxstring)) < 0)
+             goto xsendx;
+           pv[n].ival = x;
+           break;
+
+         case SND_NAM:                 /* Filenames */
+           if (!getval) break;
+           if ((x = cmkey(fntab,nfntab,"","converted",xxstring)) < 0)
+             goto xsendx;
+           debug(F101,"xsend /filenames","",x);
+           pv[n].ival = x;
+           break;
+
+#ifdef CALIBRATE
+          case SND_CAL:                        /* /CALIBRATE */
+           if (getval) {
+               if ((x = cmnum("number of Kbytes to send",
+                          "1024",10,&y,xxstring)) < 0)
+                 goto xsendx;
+           } else
+             y = 1024;
+           pv[n].ival = y;
+           pv[SND_ARR].ival = 0;
+           break;
+#endif /* CALIBRATE */
+
+         case SND_FIL:                 /* Name of file containing filnames */
+           if (!getval) break;
+           if ((x = cmifi("Name of file containing list of filenames",
+                              "",&s,&y,xxstring)) < 0) {
+               if (x == -3) {
+                   printf("?Filename required\n");
+                   x = -9;
+               }
+               goto xsendx;
+           } else if (y) {
+               printf("?Wildcards not allowed\n");
+               x = -9;
+               goto xsendx;
+           }
+           if (pv[n].sval)
+             free(pv[n].sval);
+           if (s) if (*s) {
+               if ((pv[n].sval = malloc((int)strlen(s)+1))) {
+                   strcpy(pv[n].sval,s);
+                   pv[n].ival = 1;
+                   pv[SND_ARR].ival = 0;
+               }
+           }
+           break;
+
+#ifndef NOSPL
+         case SND_ARR:                 /* SEND /ARRAY: */
+           if (!getval) break;
+           ap = NULL;
+           if ((x = cmfld("Array name (a single letter will do)",
+                          "",
+                          &s,
+                          NULL
+                          )) < 0) {
+               if (x == -3)
+                 break;
+               else
+                 return(x);
+           }
+           if ((x = arraybounds(s,&(range[0]),&(range[1]))) < 0) {
+               printf("?Bad array: %s\n",s);
+               return(-9);
+           }
+           if (!(ap = a_ptr[x])) {
+               printf("?No such array: %s\n",s);
+               return(-9);
+           }
+           pv[n].ival = 1;
+           pv[SND_CMD].ival = 0;       /* Undo any conflicting ones... */
+           pv[SND_RES].ival = 0;
+           pv[SND_CAL].ival = 0;
+           pv[SND_FIL].ival = 0;
+           arrayx = x;
+           break;
+#endif /* NOSPL */
+
+         case SND_XPA:                 /* /TRANSPARENT */
+           pv[n].ival = 1;
+           break;
+
+         case SND_TYP:                 /* Only files of given type */
+           if (!getval) break;
+           if ((x = cmkey(txtbin,3,"","all",xxstring)) < 0)
+             goto xsendx;
+           pv[n].ival = (x == 2) ? -1 : x;
+           break;
+
+         default:
+           printf("?Unexpected switch value - %d\n",cmresult.nresult);
+           x = -9;
+           goto xsendx;
+       }
+    }
+    debug(F101,"xsend cmresult fcode","",cmresult.fcode);
+
+#ifdef COMMENT
+    /* List switch parsing results in debug log */
+    for (i = 0; i <= SND_MAX; i++) {
+       ckmakmsg(line,LINBUFSIZ,"xsend switch ",ckitoa(i),NULL,NULL);
+       debug(F111,line, pv[i].sval, pv[i].ival);
+    }
+#endif /* COMMENT */
+
+/* Now we have all switches, plus maybe a filename or command, or nothing */
+
+#ifdef PIPESEND
+    if (protocol != PROTO_K && pv[SND_CMD].ival > 0) {
+       printf("?Sorry, %s works only with Kermit protocol\n",
+              (cx == XXCSEN) ? "CSEND" : "SEND /COMMAND");
+       x = -9;
+       goto xsendx;
+    }
+    if (pv[SND_RES].ival > 0 ||        /* /RECOVER */
+       pv[SND_STA].ival > 0) { /* or /STARTING */
+       if (sndfilter || pv[SND_FLT].ival > 0) {
+           printf("?Sorry, no /RECOVER or /START if SEND FILTER selected\n");
+           x = -9;
+           goto xsendx;
+       }
+    }
+#endif /* PIPESEND */
+
+    cmarg = "";
+    cmarg2 = "";
+    line[0] = NUL;
+    s = line;
+    wild = 0;
+
+    switch (cmresult.fcode) {          /* How did we get out of switch loop */
+      case _CMIFI:                     /* Input filename */
+       ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
+       if (pv[SND_ARR].ival > 0)
+         cmarg2 = line;
+       else
+         wild = cmresult.nresult;      /* Wild flag */
+       if (!recursive && !wild)
+         nolinks = 0;
+       break;
+      case _CMFLD:                     /* Field */
+       /* Only allowed with /COMMAND and /ARRAY */
+       if (pv[SND_CMD].ival < 1 && pv[SND_ARR].ival < 1) {
+#ifdef CKROOT
+           if (ckrooterr)
+             printf("?Off limits: %s\n",cmresult.sresult);
+           else
+#endif /* CKROOT */
+             printf("?%s - \"%s\"\n",
+                  iswild(cmresult.sresult) ?
+                  "No files match" : "File not found",
+                  cmresult.sresult
+                  );
+           x = -9;
+           goto xsendx;
+       }
+       ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
+       if (pv[SND_ARR].ival > 0)
+         cmarg2 = line;
+       break;
+      case _CMCFM:                     /* Confirmation */
+       /* s = ""; */
+       confirmed = 1;
+       break;
+      default:
+       printf("?Unexpected function code: %d\n",cmresult.fcode);
+       x = -9;
+       goto xsendx;
+    }
+    debug(F110,"xsend string",s,0);
+    debug(F101,"xsend confirmed","",confirmed);
+
+    /* Save and change protocol and transfer mode */
+    /* Global values are restored in main parse loop */
+
+    g_proto = protocol;                        /* Save current global protocol */
+    g_urpsiz = urpsiz;
+    g_spsizf = spsizf;
+    g_spsiz = spsiz;
+    g_spsizr = spsizr;
+    g_spmax = spmax;
+    g_wslotr = wslotr;
+    g_prefixing = prefixing;
+    g_fncact = fncact;
+    g_fncnv = fncnv;
+    g_fnspath = fnspath;
+    g_fnrpath = fnrpath;
+    g_xfrxla = xfrxla;
+
+    if (pv[SND_PRO].ival > -1) {       /* Change according to switch */
+       protocol = pv[SND_PRO].ival;
+        if (ptab[protocol].rpktlen > -1) /* copied from initproto() */
+            urpsiz = ptab[protocol].rpktlen;
+        if (ptab[protocol].spktflg > -1)
+            spsizf = ptab[protocol].spktflg;
+        if (ptab[protocol].spktlen > -1) {
+            spsiz = ptab[protocol].spktlen;
+            if (spsizf)
+             spsizr = spmax = spsiz;
+        }
+        if (ptab[protocol].winsize > -1)
+            wslotr = ptab[protocol].winsize;
+        if (ptab[protocol].prefix > -1)
+            prefixing = ptab[protocol].prefix;
+        if (ptab[protocol].fnca > -1)
+            fncact  = ptab[protocol].fnca;
+        if (ptab[protocol].fncn > -1)
+            fncnv   = ptab[protocol].fncn;
+        if (ptab[protocol].fnsp > -1)
+            fnspath = ptab[protocol].fnsp;
+        if (ptab[protocol].fnrp > -1)
+            fnrpath = ptab[protocol].fnrp;
+    }
+    debug(F101,"xsend protocol","",protocol);
+
+    if (pv[SND_NOB].ival > -1) {       /* /NOBACKUP (skip backup file) */
+       g_skipbup = skipbup;
+       skipbup = 1;
+    }
+    if (pv[SND_REC].ival > 0)          /* /RECURSIVE */
+      recursive = 2;
+
+    if (pv[SND_TYP].ival > -1) {       /* /TYPE */
+       xfiletype = pv[SND_TYP].ival;
+       if (xfiletype == 2)
+         xfiletype = -1;
+    }
+    g_binary = binary;                 /* Save global transfer mode */
+#ifdef PATTERNS
+    g_patterns = patterns;             /* Save FILE PATTERNS setting */
+#endif /* PATTERNS */
+    if (pv[SND_BIN].ival > 0) {                /* Change according to switch */
+       /* If they said /BINARY they mean /BINARY */
+       patterns = 0;                   /* So no pattern-based switching */
+       g_xfermode = xfermode;          /* or automatic transfer mode */
+       xfermode = XMODE_M;
+       binary = XYFT_B;
+       debug(F101,"doxsend /BINARY xfermode","",xfermode);
+    } else if (pv[SND_TXT].ival > 0) { /* Ditto for /TEXT */
+       patterns = 0;
+       g_xfermode = xfermode;
+       xfermode = XMODE_M;
+       binary = XYFT_T;
+       debug(F101,"doxsend /TEXT xfermode","",xfermode);
+    } else if (pv[SND_IMG].ival > 0) {
+#ifdef VMS
+       binary = XYFT_I;
+#else
+       binary = XYFT_B;
+#endif /* VMS */
+    }
+#ifdef CK_LABELED
+    else if (pv[SND_LBL].ival > 0) {
+       binary = XYFT_L;
+    }
+#endif /* CK_LABELED */
+    debug(F101,"xsend binary","",binary);
+
+    if (pv[SND_XPA].ival > 0)          /* /TRANSPARENT */
+      xfrxla = 0;                      /* Don't translate character sets */
+
+    /* Check for legal combinations of switches, filenames, etc */
+
+#ifdef PIPESEND
+    if (pv[SND_CMD].ival > 0) {        /* COMMAND - strip any braces */
+       debug(F110,"SEND /COMMAND before stripping",s,0);
+       s = brstrip(s);
+       debug(F110,"SEND /COMMAND after stripping",s,0);
+       if (!*s) {
+           printf("?Sorry, a command to send from is required\n");
+           x = -9;
+           goto xsendx;
+       }
+       cmarg = s;
+    }
+#endif /* PIPESEND */
+
+/* Set up /MOVE and /RENAME */
+
+    if (pv[SND_DEL].ival > 0 &&
+       (pv[SND_MOV].ival > 0 || pv[SND_REN].ival > 0)) {
+       printf("?Sorry, /DELETE conflicts with /MOVE or /RENAME\n");
+       x = -9;
+       goto xsendx;
+    }
+#ifdef CK_TMPDIR
+    if (pv[SND_MOV].ival > 0) {
+       int len;
+       char * p = pv[SND_MOV].sval;
+#ifdef CK_LOGIN
+       if (isguest) {
+           printf("?Sorry, /MOVE-TO not available to guests\n");
+           x = -9;
+           goto xsendx;
+       }
+#endif /* CK_LOGIN */
+       len = strlen(p);
+       if (!isdir(p)) {                /* Check directory */
+#ifdef CK_MKDIR
+           char * s = NULL;
+           s = (char *)malloc(len + 4);
+           if (s) {
+               strcpy(s,p);            /* safe */
+#ifdef datageneral
+               if (s[len-1] != ':') { s[len++] = ':'; s[len] = NUL; }
+#else
+               if (s[len-1] != '/') { s[len++] = '/'; s[len] = NUL; }
+#endif /* datageneral */
+               s[len++] = 'X';
+               s[len] = NUL;
+               x = zmkdir(s);
+               free(s);
+               if (x < 0) {
+                   printf("?Can't create \"%s\"\n",p);
+                   x = -9;
+                   goto xsendx;
+               }
+           }
+#else
+           printf("?Directory \"%s\" not found\n",p);
+           x = -9;
+           goto xsendx;
+#endif /* CK_MKDIR */
+       }
+        zfnqfp(p,LINBUFSIZ,tmpbuf);
+       makestr(&snd_move,tmpbuf);
+    }
+#endif /* CK_TMPDIR */
+
+    if (pv[SND_REN].ival > 0) {                /* /RENAME */
+       char * p = pv[SND_REN].sval;
+#ifdef CK_LOGIN
+       if (isguest) {
+           printf("?Sorry, /RENAME-TO not available to guests\n");
+           x = -9;
+           goto xsendx;
+       }
+#endif /* CK_LOGIN */
+       if (!p) p = "";
+       if (!*p) {
+           printf("?New name required for /RENAME\n");
+           x = -9;
+           goto xsendx;
+       }
+       p = brstrip(p);
+#ifndef NOSPL
+    /* If name given is wild, rename string must contain variables */
+       if (wild) {
+           char * s = tmpbuf;
+           x = TMPBUFSIZ;
+           zzstring(p,&s,&x);
+           if (!strcmp(tmpbuf,p)) {
+               printf(
+    "?/RENAME for file group must contain variables such as \\v(filename)\n"
+                      );
+               x = -9;
+               goto xsendx;
+           }
+       }
+#endif /* NOSPL */
+       makestr(&snd_rename,p);
+    }
+
+/* Handle /RECOVER and /START */
+
+#ifdef CK_RESEND
+    if (pv[SND_RES].ival > 0 && binary != XYFT_B && !filepeek
+#ifdef PATTERNS
+       && !patterns
+#else
+#ifdef VMS
+/* VMS sets text/binary automatically later when it opens the file */
+       && 0
+#endif /* VMS */
+#endif /* PATTERNS */
+       ) {
+       printf("?Sorry, /BINARY required\n");
+       x = -9;
+       goto xsendx;
+    }
+    if (pv[SND_STA].ival > 0) {                /* /START */
+       if (wild) {
+           printf("?Sorry, wildcards not permitted with /START\n");
+           x = -9;
+           goto xsendx;
+       }
+       if (sizeof(int) < 4) {
+           printf("?Sorry, this command needs 32-bit integers\n");
+           x = -9;
+           goto xsendx;
+       }
+#ifdef CK_XYZ
+       if (protocol != PROTO_K) {
+           printf("?Sorry, SEND /START works only with Kermit protocol\n");
+           x = -9;
+           goto xsendx;
+       }
+#endif /* CK_XYZ */
+    }
+#ifdef CK_XYZ
+    if (pv[SND_RES].ival > 0) {
+       if (protocol != PROTO_K && protocol != PROTO_Z) {
+           printf(
+    "Sorry, /RECOVER is possible only with Kermit or ZMODEM protocol\n"
+                  );
+           x = -9;
+           goto xsendx;
+       }
+    }
+#endif /* CK_XYZ */
+#endif /* CK_RESEND */
+
+    if (protocol == PROTO_K) {
+       if ((pv[SND_MAI].ival > 0 ||    /* MAIL */
+            pv[SND_PRI].ival > 0 ||    /* PRINT */
+            pv[SND_RES].ival > 0       /* RESEND */
+            ) &&
+           (!atdiso || !atcapr)) {     /* Disposition attribute off? */
+           printf("?Sorry, ATTRIBUTE DISPOSITION must be ON\n");
+           x = -9;
+           goto xsendx;
+       }
+    }
+
+#ifdef CK_XYZ
+    if (wild && (protocol == PROTO_X || protocol == PROTO_XC)) {
+       printf(
+"Sorry, you can only send one file at a time with XMODEM protocol\n"
+              );
+       x = -9;
+       goto xsendx;
+    }
+#endif /* CK_XYZ */
+
+    if (!confirmed) {                  /* CR not typed yet, get more fields */
+       char *m;
+       if (mlist) {                    /* MSEND or MMOVE */
+           nfils = 0;                  /* We already have the first one */
+#ifndef NOMSEND
+           msfiles[nfils++] = line;    /* Store pointer */
+           lp = line + (int)strlen(line) + 1; /* Point past it */
+           debug(F111,"xsend msend",msfiles[nfils-1],nfils-1);
+           while (1) {                 /* Get more filenames */
+               char *p;
+               if ((x = cmifi("Names of files to send, separated by spaces",
+                              "", &s,&y,xxstring)) < 0) {
+                   if (x != -3)
+                     goto xsendx;
+                   if ((x = cmcfm()) < 0)
+                     goto xsendx;
+                   break;
+               }
+               msfiles[nfils++] = lp;  /* Got one, count it, point to it, */
+               p = lp;                 /* remember pointer, */
+               while ((*lp++ = *s++))  /* and copy it into buffer */
+                 if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
+                     printf("?MSEND list too long\n");
+                     line[0] = NUL;
+                     x = -9;
+                     goto xsendx;
+                 }
+               debug(F111,"xsend msend",msfiles[nfils-1],nfils-1);
+               if (nfils == 1) fspec[0] = NUL; /* Take care of \v(filespec) */
+#ifdef ZFNQFP
+               zfnqfp(p,TMPBUFSIZ,tmpbuf);
+               p = tmpbuf;
+#endif /* ZFNQFP */
+               if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
+                   strcat(fspec,p);    /* safe */
+                   strcat(fspec," ");  /* safe */
+               } else
+#ifdef COMMENT
+                 printf("WARNING - \\v(filespec) buffer overflow\n");
+#else
+                 debug(F101,"doxsend filespec buffer overflow","",0);
+#endif /* COMMENT */
+           }
+#endif /* NOMSEND */
+       } else {                        /* Regular SEND */
+           char *p; int y;
+           nfils = -1;
+           if (pv[SND_MAI].ival > 0)
+             m = (pv[SND_MAI].sval) ?
+               "e-mail address (optional)" :
+                 "e-mail address (required)";
+           else if (pv[SND_PRI].ival > 0)
+             m = "printer options (optional)";
+           else if (wild)
+             m =
+"\nOptional as-name template containing replacement variables \
+like \\v(filename)";
+           else
+             m = "Optional name to send it with";
+           if ((x = cmtxt(m,"",&p,NULL)) < 0)
+             goto xsendx;
+           if (!p) p = "";
+           if (*p) {                   /* If some text was given... */
+               p = brstrip(p);         /* Replace /AS-NAME: value if any */
+               if ((y = strlen(p)) > 0) {
+                    if (pv[SND_MAI].ival > 0) {
+                        makestr(&pv[SND_MAI].sval, p);
+                    } else {
+                       if (pv[SND_ASN].sval) free(pv[SND_ASN].sval);
+                       pv[SND_ASN].sval = malloc(y+1);
+                       if (pv[SND_ASN].sval) {
+                           strcpy(pv[SND_ASN].sval,p); /* safe */
+                           pv[SND_ASN].ival = 1;
+                       }
+                   }
+               }
+           }
+       }
+    }
+    /* Set cmarg2 from as-name, however we got it. */
+
+    if (pv[SND_ASN].ival > 0 && pv[SND_ASN].sval && !*cmarg2) {
+       int x;
+       x = strlen(line);
+       ckstrncpy(line+x+2,pv[SND_ASN].sval,LINBUFSIZ-x-1);
+       cmarg2 = line+x+2;
+       debug(F110,"doxsend cmarg2",cmarg2,0);
+    }
+
+#ifndef NOFRILLS
+    if ((pv[SND_MAI].ival > 0) && (pv[SND_PRI].ival > 0)) {
+       printf("Sorry, /MAIL and /PRINT are conflicting options\n");
+       x = -9;
+       goto xsendx;
+    }
+    n = 0;                             /* /MAIL or /PRINT? */
+    if (pv[SND_MAI].ival > 0)
+      n = SND_MAI;
+    else if (pv[SND_PRI].ival > 0)
+      n = SND_PRI;
+    if (n) {                           /* Yes... */
+#ifdef DEBUG
+       char * p;
+       if (n == SND_MAI)
+         p = "/MAIL";
+       else
+         p = "/PRINT";
+       debug(F111,"xsend",p,n);
+#endif /* DEBUG */
+#ifdef CK_XYZ
+       if (protocol != PROTO_K) {
+           printf("Sorry, %s available only with Kermit protocol\n",
+                  (n == SND_MAI) ? "/MAIL" : "/PRINT"
+                  );
+           x = -9;
+           goto xsendx;
+       }
+#endif /* CK_XYZ */
+       debug(F101,"xsend print/mail wild","",wild);
+       *optbuf = NUL;                  /* Wipe out any old options */
+       s = pv[n].sval;                 /* mail address or print switch val */
+       if (!s) s = "";
+       debug(F110,"doxsend mail address or printer options",s,0);
+       if (n == SND_MAI && !*s) {
+           printf("?E-mail address required\n");
+           x = -9;
+           goto xsendx;
+       } else if ((int)strlen(s) > 94) { /* Ensure legal size */
+           printf("?%s too long\n",
+                  (n == SND_MAI) ?
+                  "E-mail address" :
+                  "Print option string"
+                  );
+           x = -9;
+           goto xsendx;
+       }
+       ckstrncpy(optbuf,s,OPTBUFLEN);  /* OK, copy to option buffer */
+       cmarg = line;                   /* File to send */
+       if (n == SND_MAI) {
+           debug(F110,"xsend mailing",cmarg,0);
+           debug(F110,"xsend address:",optbuf,0);
+           rmailf = 1;
+       } else {
+           debug(F110,"xsend printing",cmarg,0);
+           debug(F110,"xsend options",optbuf,0);
+           rprintf = 1;
+       }
+    }
+#endif /* NOFRILLS */
+
+#ifdef CALIBRATE
+    if (pv[SND_CAL].ival > 0) {                /* Handle /CALIBRATE */
+       if (confirmed) {
+           calibrate = pv[SND_CAL].ival * 1024L;
+           sndsrc = -9;
+           nfils = 1;
+           wild = 0;
+#ifndef NOMSEND
+           addlist = 0;
+#endif /* NOMSEND */
+           ckstrncpy(line,"CALIBRATION",LINBUFSIZ);
+           s = cmarg = line;
+           if (!cmarg2) cmarg2 = "";
+           debug(F110,"doxsend cmarg2 calibrate",cmarg2,0);
+       } else if (line[0]) {
+           calibrate = 0L;
+           pv[SND_CAL].ival = 0L;
+       }
+    }
+#endif /* CALIBRATE */
+
+    if (pv[SND_FIL].ival > 0) {
+       if (confirmed && !calibrate) {
+           if (zopeni(ZMFILE,pv[SND_FIL].sval) < 1) {
+               debug(F110,"xsend can't open",pv[SND_FIL].sval,0);
+               printf("?Failure to open %s\n",filefile);
+               x = -9;
+               goto xsendx;
+           }
+           makestr(&filefile,pv[SND_FIL].sval); /* Open, remember name */
+           debug(F110,"xsend opened",filefile,0);
+           wild = 1;
+       }
+    }
+
+    /* SEND alone... */
+
+#ifndef NOSPL
+    if (confirmed && pv[SND_ARR].ival > 0) {
+       if (!*cmarg2) {
+           sndxnam[7] = (char)((arrayx == 1) ? 64 : arrayx + ARRAYBASE);
+           cmarg2 = sndxnam;
+       }
+       cmarg = "";
+       goto sendend;
+    }
+#endif /* NOSPL */
+
+    if (confirmed && !line[0] && !filefile && !calibrate) {
+#ifndef NOMSEND
+       if (filehead) {                 /* OK if we have a SEND-LIST */
+           nfils = filesinlist;
+           sndsrc = nfils;             /* Like MSEND */
+           addlist = 1;                /* But using a different list... */
+           filenext = filehead;
+           goto sendend;
+       }
+#endif /* NOMSEND */
+       printf("?Filename required but not given\n");
+       x = -9;
+       goto xsendx;
+    }
+
+    /* Not send-list or array */
+
+#ifndef NOMSEND
+    addlist = 0;                       /* Don't use SEND-LIST. */
+    filenext = NULL;
+#endif /* NOMSEND */
+
+    if (mlist) {                       /* MSEND or MMOVE */
+#ifndef NOMSEND
+       cmlist = msfiles;               /* List of files to send */
+       sndsrc = nfils;
+       cmarg2 = "";
+       sendstart = 0L;
+#endif /* NOMSEND */
+#ifdef PIPESEND
+       pipesend = 0;
+#endif /* PIPESEND */
+    } else if (filefile) {             /* File contains list of filenames */
+       s = "";
+       cmarg = "";
+       cmarg2 = "";
+       line[0] = NUL;
+       nfils = 1;
+       sndsrc = 1;
+
+    } else if (!calibrate && pv[SND_ARR].ival < 1 && pv[SND_CMD].ival < 1) {
+
+       nfils = sndsrc = -1;    /* Not MSEND, MMOVE, /LIST, or /ARRAY */
+       if (                            /* or /COMMAND */
+
+#ifndef NOFRILLS
+           !rmailf && !rprintf         /* Not MAIL or PRINT */
+#else
+           1
+#endif /* NOFRILLS */
+           ) {
+           int y = 1;
+           if (!wild)
+             y = zchki(s);
+           if (y < 0) {
+               printf("?Read access denied - \"%s\"\n", s);
+               x = -9;
+               goto xsendx;
+           }
+           if (s != line)              /* We might already have done this. */
+             ckstrncpy(line,s,LINBUFSIZ); /* Copy of string just parsed. */
+           else
+             debug(F110,"doxsend line=s",line,0);
+           cmarg = line;               /* File to send */
+       }
+       zfnqfp(cmarg,fspeclen,fspec);
+    }
+    if (!mlist) {                      /* For all but MSEND... */
+#ifdef PIPESEND
+       if (pv[SND_CMD].ival > 0)       /* /COMMAND sets pipesend flag */
+         pipesend = 1;
+       debug(F101,"xsend /COMMAND pipesend","",pipesend);
+       if (pipesend && filefile) {
+           printf("?Invalid switch combination\n");
+           x = -9;
+           goto xsendx;
+       }
+#endif /* PIPESEND */
+
+#ifndef NOSPL
+    /* If as-name given and filespec is wild, as-name must contain variables */
+       debug(F111,"doxsend cmarg2 wild",cmarg2,wild);
+       if (wild && *cmarg2) {
+           char * s = tmpbuf;
+           x = TMPBUFSIZ;
+           zzstring(cmarg2,&s,&x);
+           if (!strcmp(tmpbuf,cmarg2)) {
+               printf(
+    "?As-name for file group must contain variables such as \\v(filename)\n"
+                      );
+               x = -9;
+               goto xsendx;
+           }
+       }
+#endif /* NOSPL */
+
+    /* Strip braces from as-name */
+       debug(F110,"xsend cmarg2 before stripping",cmarg2,0);
+       cmarg2 = brstrip(cmarg2);
+       debug(F110,"xsend filename",cmarg,0);
+       debug(F110,"xsend as-name",cmarg2,0);
+
+    /* Copy as-name to a safe place */
+
+       if (asnbuf) {
+           free(asnbuf);
+           asnbuf = NULL;
+       }
+       if ((y = strlen(cmarg2)) > 0) {
+           asnbuf = (char *) malloc(y + 1);
+           if (asnbuf) {
+               strcpy(asnbuf,cmarg2);  /* safe */
+               cmarg2 = asnbuf;
+           } else cmarg2 = "";
+       }
+
+#ifdef CK_RESEND
+       debug(F111,"xsend pv[SND_STA].ival","",pv[SND_STA].ival);
+       if (pv[SND_STA].ival > -1) {    /* /START position */
+           if (wild) {
+               printf("?/STARTING-AT may not be used with multiple files.\n");
+               x = -9;
+               goto xsendx;
+           } else
+             sendstart = pv[SND_STA].ival;
+       } else
+         sendstart = 0L;
+       debug(F101,"xsend /STARTING","",sendstart);
+#endif /* CK_RESEND */
+    }
+
+sendend:                               /* Common successful exit */
+    moving = 0;
+    if (pv[SND_SHH].ival > 0) {                /* SEND /QUIET... */
+       g_displa = fdispla;
+       fdispla = 0;
+       debug(F101,"xsend display","",fdispla);
+    }
+
+#ifndef NOSPL                          /* SEND /ARRAY... */
+    if (pv[SND_ARR].ival > 0) {
+       if (!ap) { x = -2; goto xsendx; } /* (shouldn't happen) */
+       if (range[0] == -1)             /* If low end of range not specified */
+         range[0] = 1;                 /* default to 1 */
+       if (range[1] == -1)             /* If high not specified */
+         range[1] = a_dim[arrayx];     /* default to size of array */
+       if ((range[0] < 0) ||           /* Check range */
+           (range[0] > a_dim[arrayx]) ||
+           (range[1] < range[0]) ||
+           (range[1] > a_dim[arrayx])) {
+           printf("?Bad array range - [%d:%d]\n",range[0],range[1]);
+           x = -9;
+           goto xsendx;
+       }
+       sndarray = ap;                  /* Array pointer */
+       sndxin = arrayx;                /* Array index */
+       sndxlo = range[0];              /* Array range */
+       sndxhi = range[1];
+       sndxnam[7] = (char)((sndxin == 1) ? 64 : sndxin + ARRAYBASE);
+
+#ifdef COMMENT
+       printf("SENDING FROM ARRAY: &%c[]...\n", /* debugging */
+              (sndxin == 1) ? 64 : sndxin + ARRAYBASE);
+       printf("Lo=%d\nHi=%d\n", sndxlo, sndxhi);
+       printf("cmarg=[%s]\ncmarg2=[%s]\n", cmarg, cmarg2);
+       while ((x = agnbyte()) > -1) {
+           putchar((char)x);
+       }
+       return(1);
+#endif /* COMMENT */
+    }
+#endif /* NOSPL */
+
+    if (pv[SND_ARR].ival < 1) {                /* File selection & disposition... */
+
+       if (pv[SND_DEL].ival > 0)       /* /DELETE was specified */
+         moving = 1;
+       debug(F101,"xsend /DELETE","",moving);
+       if (pv[SND_AFT].ival > 0)       /* Copy SEND criteria */
+         ckstrncpy(sndafter,pv[SND_AFT].sval,19);
+       if (pv[SND_BEF].ival > 0)
+         ckstrncpy(sndbefore,pv[SND_BEF].sval,19);
+       if (pv[SND_NAF].ival > 0)
+         ckstrncpy(sndnafter,pv[SND_NAF].sval,19);
+       if (pv[SND_NBE].ival > 0)
+         ckstrncpy(sndnbefore,pv[SND_NBE].sval,19);
+       if (pv[SND_EXC].ival > 0)
+         makelist(pv[SND_EXC].sval,sndexcept,NSNDEXCEPT);
+       if (pv[SND_SMA].ival > -1)
+         sndsmaller = pv[SND_SMA].ival;
+       if (pv[SND_LAR].ival > -1)
+         sndlarger = pv[SND_LAR].ival;
+       if (pv[SND_NAM].ival > -1) {
+           g_fncnv = fncnv;            /* Save global value */
+           fncnv = pv[SND_NAM].ival;
+           debug(F101,"xsend fncnv","",fncnv);
+       }
+       if (pv[SND_PTH].ival > -1) {
+           g_spath = fnspath;          /* Save global values */
+           fnspath = pv[SND_PTH].ival;
+#ifndef NZLTOR
+           if (fnspath != PATH_OFF) {
+               g_fncnv = fncnv;        /* Bad bad... */
+               fncnv = XYFN_C;
+           }
+#endif /* NZLTOR */
+           debug(F101,"xsend fnspath","",fnspath);
+           debug(F101,"xsend fncnv","",fncnv);
+       }
+    }
+
+#ifdef PIPESEND
+    if (pv[SND_FLT].ival > 0) {
+       makestr(&sndfilter,pv[SND_FLT].sval);
+       debug(F110,"xsend /FILTER", sndfilter, 0);
+    }
+#endif /* PIPESEND */
+
+#ifdef CK_APC
+/* MOVE not allowed in APCs */
+    if (moving &&
+       (apcactive == APC_LOCAL || apcactive == APC_REMOTE)
+       && !(apcstatus & APC_UNCH))
+      return(success = 0);
+#endif /* CK_APC */
+#ifdef IKS_OPTION
+    if (
+#ifdef CK_XYZ
+        protocol == PROTO_K &&
+#endif /* CK_XYZ */
+        !iks_wait(KERMIT_REQ_START,1)) {
+        printf("?A Kermit Server is not available to process this command.\n");
+        printf("?Start a RECEIVE command to complement this command.\n");
+    }
+#endif /* IKS_OPTION */
+
+#ifdef IKSD
+#ifdef CK_LOGIN
+    if (moving && inserver && isguest) {
+        printf("?File deletion not allowed for guests.\n");
+       return(-9);
+    }
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+
+    sstate = 's';                      /* Set start state to SEND */
+    sndcmd = 1;
+#ifdef CK_RESEND
+    if (pv[SND_RES].ival > 0)          /* Send sendmode appropriately */
+      sendmode = SM_RESEND;
+    else if (pv[SND_STA].ival > 0)
+      sendmode = SM_PSEND;
+    else
+#endif /* CK_RESEND */
+    if (mlist)
+      sendmode = SM_MSEND;
+    else
+      sendmode = SM_SEND;
+#ifdef MAC
+    what = W_SEND;
+    scrcreate();
+#endif /* MAC */
+    if (local && pv[SND_SHH].ival != 0) { /* If in local mode, */
+       displa = 1;                     /* turn on file transfer display */
+    }
+    x = 0;
+
+  xsendx:                              /* Common exit, including failure */
+    debug(F101,"doxsend sndsrc","",sndsrc);
+    for (i = 0; i <= SND_MAX; i++) {   /* Free malloc'd memory */
+       if (pv[i].sval)
+         free(pv[i].sval);
+    }
+    return(x);
+}
+#endif /* NOXFER */
+
+#ifndef NOLOCAL
+/*  D O X C O N N  --  CONNECT command parsing with switches */
+
+#ifdef XLIMITS
+#define XLIMORTRIGGER
+#else
+#ifdef CK_TRIGGER
+#define XLIMORTRIGGER
+#endif /* CK_TRIGGER */
+#endif /*  XLIMITS */
+
+#ifdef CKTIDLE
+int tt_idlelimit = 0;                  /* Terminal idle limit */
+int tt_idleact = IDLE_RET;             /* Terminal idle action */
+#endif /* CKTIDLE */
+
+#ifdef OS2                             /* K95 only: */
+extern int
+  tt_idlesnd_tmo;                      /*   Idle interval */
+int tt_timelimit = 0;                  /*   Time limit, 0 = none */
+extern char *                          /* Parse results - strings: */
+  tt_idlesnd_str;                      /*   Idle string */
+#endif /* OS2 */
+
+#ifdef CK_TRIGGER
+extern char *tt_trigger[];
+extern CHAR *tt_trmatch[];
+extern char *triggerval;
+static char *g_tt_trigger[TRIGGERS];
+#endif /* CK_TRIGGER */
+
+#ifdef OS2
+static int g_tt_idlesnd_tmo, g_tt_timelimit; /* For saving and restoring */
+static int g_tt_idlelimit, g_tt_saved = 0;
+static char * g_tt_idlesnd_str;                /* global settings */
+#endif /* OS2 */
+
+static struct stringint {              /* Temporary array for switch values */
+    char * sval;
+    int ival;
+} pv[CONN_MAX+1];
+
+VOID
+resconn() {
+    int i;
+
+#ifdef OS2
+    if ( g_tt_saved ) {
+        tt_idlelimit   = g_tt_idlelimit;
+        tt_idlesnd_tmo = g_tt_idlesnd_tmo;
+        tt_timelimit   = g_tt_timelimit;
+        tt_idlesnd_str = g_tt_idlesnd_str;
+        g_tt_saved = 0;
+    }
+#endif /* OS2 */
+
+#ifdef CK_TRIGGER
+    for (i = 0; i < TRIGGERS; i++)
+      tt_trigger[i] = g_tt_trigger[i];
+#endif /* CK_TRIGGER */
+
+    for (i = 0; i <= CONN_MAX; i++) {  /* Free malloc'd memory */
+       if (pv[i].sval)
+         free(pv[i].sval);
+        pv[i].sval = NULL;
+    }
+}
+
+int
+doxconn(cx) int cx; {
+    int c, i, n;                       /* Workers */
+    int x, y;
+    int getval = 0;                    /* Whether to get switch value */
+    int async = 0;                      /* Make an async connect */
+    struct FDB sw, cm;                 /* FDBs for each parse function */
+    extern FILE * tfile[];
+    extern char * macp[];
+
+#ifdef OS2
+    g_tt_idlesnd_tmo = tt_idlesnd_tmo; /* Save global settings */
+    g_tt_timelimit   = tt_timelimit;
+    g_tt_idlelimit   = tt_idlelimit;
+    g_tt_idlesnd_str = tt_idlesnd_str;
+    g_tt_saved = 1;
+#endif /* OS2 */
+
+#ifdef CK_TRIGGER
+    if (!tt_trigger[0]) {              /* First initialization */
+       for (i = 1; i < TRIGGERS; i++)
+         tt_trigger[i] = NULL;
+    }
+    for (i = 0; i < TRIGGERS; i++)
+      g_tt_trigger[i] = tt_trigger[i];
+    if (triggerval) {
+       free(triggerval);
+       triggerval = NULL;
+    }
+#endif /* CK_TRIGGER */
+
+    for (i = 0; i <= CONN_MAX; i++) {  /* Initialize switch values */
+       pv[i].sval = NULL;              /* to null pointers */
+       pv[i].ival = -1;                /* and -1 int values */
+    }
+    if (cx == XXCQ)                    /* CQ == CONNECT /QUIETLY */
+      pv[CONN_NV].ival = 1;
+
+    /* Set up chained parse functions... */
+
+    cmfdbi(&sw,                                /* First FDB - command switches */
+          _CMKEY,                      /* fcode */
+          "Switch",                    /* hlpmsg */
+          "",                          /* default */
+          "",                          /* addtl string data */
+          nconntab,                    /* addtl numeric data 1: tbl size */
+          4,                           /* addtl numeric data 2: 4 = cmswi */
+          xxstring,                    /* Processing function */
+          conntab,                     /* Keyword table */
+          &cm                          /* Pointer to next FDB */
+          );
+    cmfdbi(&cm,                                /* 2nd FDB - Confirmation */
+          _CMCFM,                      /* fcode */
+          "",                          /* hlpmsg */
+          "",                          /* default */
+          "",                          /* addtl string data */
+          0,                           /* addtl numeric data 1 */
+          0,                           /* addtl numeric data 2 */
+          NULL,
+          NULL,
+          NULL
+          );
+
+    while (1) {                                /* Parse 0 or more switches */
+       x = cmfdb(&sw);                 /* Parse switch or confirmation */
+       debug(F101,"doxconn cmfdb","",x);
+       if (x < 0) {                    /* Error */
+           if (x == -9 || x == -2)
+             printf("?No switches match - \"%s\"\n",atmbuf);
+           goto xconnx;                /* or reparse needed */
+       }
+       if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
+         break;
+       c = cmgbrk();                   /* Get break character */
+       getval = (c == ':' || c == '='); /* to see how they ended the switch */
+       if (getval && !(cmresult.kflags & CM_ARG)) {
+           printf("?This switch does not take arguments\n");
+           x = -9;
+           goto xconnx;
+       }
+       if (!getval && (cmgkwflgs() & CM_ARG)) {
+           printf("?This switch requires an argument\n");
+           return(-9);
+       }
+       n = cmresult.nresult;           /* Numeric result = switch value */
+       debug(F101,"doxconn switch","",n);
+
+       switch (n) {                    /* Process the switch */
+#ifdef OS2
+         case CONN_AS:                 /* Asynchronous */
+            pv[CONN_AS].ival = 1;
+            pv[CONN_SY].ival = 0;
+            break;
+          case CONN_SY:                 /* Synchronous */
+            pv[CONN_SY].ival = 1;
+            pv[CONN_AS].ival = 0;
+            break;
+#endif /* OS2 */
+         case CONN_NV:                 /* Non-verbal */
+           pv[n].ival = 1;
+           break;
+#ifdef XLIMITS
+         case CONN_II:                 /* Idle-interval */
+         case CONN_IL:                 /* Idle-limit */
+         case CONN_TL:                 /* Time-limit */
+           if (!getval) break;
+           if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
+             goto xconnx;
+           pv[n].ival = y;
+           break;
+         case CONN_IS:                 /* Idle-string */
+#endif /* XLIMITS */
+#ifdef CK_TRIGGER
+         case CONN_TS:                 /* Trigger-string */
+#endif /* CK_TRIGGER */
+#ifdef XLIMORTRIGGER
+           if (!getval) break;
+           if ((x = cmfld("String (enclose in braces if it contains spaces)",
+                          "",&s,xxstring)) < 0) {
+               if (x == -3) {
+                   printf("?String required\n");
+                   x = -9;
+               }
+               goto xconnx;
+           }
+           if (n != CONN_TS)
+             s = brstrip(s);
+           if ((y = strlen(s)) > 0) {
+               if (pv[n].sval) free(pv[n].sval);
+               pv[n].sval = malloc(y+1);
+               if (pv[n].sval) {
+                   strcpy(pv[n].sval,s); /* safe */
+                   pv[n].ival = 1;
+               }
+           }
+           break;
+#endif /* XLIMORTRIGGER */
+         default:
+           printf("?Unexpected switch value - %d\n",cmresult.nresult);
+           x = -9;
+           goto xconnx;
+       }
+    }
+    debug(F101,"doxconn cmresult.fcode","",cmresult.fcode);
+    if (cmresult.fcode != _CMCFM) {
+       printf("?Unexpected function code: %d\n",cmresult.fcode);
+       x = -9;
+       goto xconnx;
+    }
+
+    /* Command was confirmed so we can pre-pop command level. */
+    /* This is so CONNECT module won't think we're executing a script */
+    /* if CONNECT was the final command in the script. */
+
+    if (cmdlvl > 0)
+      prepop();
+
+#ifdef OS2                             /* Make results available globally */
+    if (pv[CONN_IL].ival > -1)         /* Idle limit */
+      tt_idlelimit = pv[CONN_IL].ival;
+    if (pv[CONN_II].ival > -1)         /* Idle limit */
+      tt_idlesnd_tmo = pv[CONN_II].ival;
+    if (pv[CONN_IS].sval)              /* Idle string */
+      if (tt_idlesnd_str = (char *)malloc((int)strlen(pv[CONN_IS].sval)+1))
+       strcpy(tt_idlesnd_str,pv[CONN_IS].sval); /* safe */
+    if (pv[CONN_TL].ival > -1)         /* Session limit */
+      tt_timelimit = pv[CONN_TL].ival;
+    async = (pv[CONN_AS].ival > 0 ||
+             pv[CONN_SY].ival <= 0 && cmdlvl == 0) ? 1 : 0;
+#endif /* OS2 */
+
+#ifdef CK_TRIGGER
+    if (pv[CONN_TS].sval)              /* Trigger strings */
+      makelist(pv[CONN_TS].sval,tt_trigger,TRIGGERS);
+    for (i = 0; i < TRIGGERS; i++)     /* Trigger match pointers */
+      tt_trmatch[i] = NULL;
+    if (triggerval) {                  /* Reset trigger value */
+       free(triggerval);
+       triggerval = NULL;
+    }
+#endif /* CK_TRIGGER */
+
+    x = doconect((pv[CONN_NV].ival > 0) ? 1 : 0, async);
+    {
+       int xx;
+       debug(F101,"doxconn doconect returns","",x);
+       if ((xx = ttchk()) < 0) dologend();
+       debug(F101,"doxconn ttchk returns","",xx);
+    }
+
+#ifdef CK_TRIGGER
+    debug(F111,"doxconn doconect triggerval",triggerval,x);
+#endif /* CK_TRIGGER */
+
+  xconnx:
+    /* Back from CONNECT -- Restore global settings */
+
+    if (!async)
+      resconn();
+
+    success = (x > 0) ? 1 : 0;
+    return(x);
+}
+#endif /* NOLOCAL */
+
+#ifdef ADDCMD
+/* cx == XXADD or XXREMV */
+/* fc == ADD_BIN or ADD_TXT */
+static int
+doadd(cx,fc) int cx, fc; {
+#ifdef PATTERNS
+    char * tmp[FTPATTERNS];
+    char **p = NULL;
+    int i, j, k, n = 0, x = 0, last;
+
+#endif /* PATTERNS */
+    if (cx != XXADD && cx != XXREMV) {
+       printf("?Unexpected function code: %d\n",cx);
+       return(-9);
+    }
+#ifdef PATTERNS
+    while (n < FTPATTERNS) {           /* Collect new patterns */
+       tmp[n] = NULL;
+       if ((x = cmfld("Pattern","",&s,xxstring)) < 0)
+         break;
+       ckstrncpy(line,s,LINBUFSIZ);
+       s = brstrip(line);
+       makestr(&(tmp[n++]),s);
+    }
+    if (x == -3)
+      x = cmcfm();
+    if (x < 0)
+      goto xdoadd;
+    p = (fc == ADD_BIN) ? binpatterns : txtpatterns; /* Which list */
+    last = 0;
+    for (i = 0; i < FTPATTERNS; i++) { /* Find last one in list */
+       if (!p[i]) {
+           last = i;
+           break;
+       }
+    }
+    if (cx == XXADD) {                 /* Adding */
+       if (last + n > FTPATTERNS) {    /* Check if too many */
+           printf("?Too many patterns - %d is the maximum\n", FTPATTERNS);
+           goto xdoadd;
+       }
+        for (i = 0; i < n; i++) {        /* Copy in the new ones. */
+          for (j = 0, x = 0; x == 0 && j < last ; j++ )
+            x = !ckstrcmp(tmp[i],p[j],-1,filecase); /* match */
+          if (x == 0)
+            makestr(&(p[last++]),tmp[i]);
+        }
+        makestr(&(p[last]),NULL);      /* Null-terminate the list */
+        x = 1;
+        goto xdoadd;                    /* Done */
+    } else if (cx == XXREMV) {         /* Remove something(s) */
+       int j, k;
+       if (last == 0)                          /* List is empty */
+         goto xdoadd;                          /* Nothing to remove */
+       for (i = 0; i < n; i++) {               /* i = Patterns they typed */
+           for (j = 0; j < last; j++) {        /* j = Patterns in list */
+               /* Change this to ckstrcmp()... */
+               if (filecase)
+                  x = !ckstrcmp(tmp[i],p[j],-1,filecase); /* match */
+               else
+                 x = ckstrcmp(tmp[i],p[j],-1,0); /* Case-independent match */
+               if (x) {                        /* This one matches */
+                   makestr(&(p[j]),NULL);      /* Free it */
+                   for (k = j; k < last; k++)  /* Move the rest up */
+                     p[k] = p[k+1];
+                   p[k] = NULL;                /* Erase last one */
+                   if (!p[k])
+                     break;
+               }
+           }
+       }
+    }
+  xdoadd:                              /* Common exit */
+    for (i = 0; i < n; i++)
+      if (tmp[i])
+       free(tmp[i]);
+    return(x);
+#endif /* PATTERNS */
+}
+
+/* ADD SEND-LIST */
+
+static int
+addsend(cx) int cx; {
+#ifndef NOMSEND
+    extern struct keytab fttab[];
+    extern int nfttyp;
+    struct filelist * flp;
+    char * fmode = "";
+    int xmode = 0;
+    int xbinary = 0;
+#endif /* NOMSEND */
+
+#ifdef NOMSEND
+    printf("?Sorry, ADD/REMOVE SEND-LIST not available.\n");
+    return(-9);
+#endif /* NOMSEND */
+    if (cx == XXREMV) {
+       printf("?Sorry, REMOVE SEND-LIST not implemented yet.\n");
+       return(-9);
+    }
+#ifndef NOMSEND
+#ifndef XYZ_INTERNAL
+    if (protocol != PROTO_K) {
+       printf("?Sorry, ADD SEND-LIST does not work with external protocols\n");
+       return(-9);
+    }
+#endif /* XYZ_INTERNAL */
+
+    x = cmifi("File specification to add","", &s,&y,xxstring);
+    if (x < 0) {
+       if (x == -3) {
+           printf("?A file specification is required\n");
+           return(-9);
+       } else
+         return(x);
+    }
+    ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+    s = tmpbuf;
+    if (filesinlist == 0)              /* Take care of \v(filespec) */
+      fspec[0] = NUL;
+    zfnqfp(s,LINBUFSIZ,line);
+    s = line;
+    if (((int)strlen(fspec) + (int)strlen(s) + 1) < fspeclen) {
+       strcat(fspec,s);                /* safe */
+       strcat(fspec," ");              /* safe */
+    } else
+      printf("WARNING - \\v(filespec) buffer overflow\n");
+
+
+    xbinary = binary;
+    if ((patterns || filepeek)         /* FILE PATTERNS or SCAN is ON */
+#ifdef CK_LABELED
+       && binary != XYFT_L             /* And not if FILE TYPE LABELED */
+#endif /* CK_LABELED */
+#ifdef VMS
+       && binary != XYFT_I             /* or FILE TYPE IMAGE */
+#endif /* VMS */
+       ) {
+       int k, x;
+       x = -1;
+       k = scanfile(line,&x,nscanfile);
+       if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
+    }
+    fmode = gfmode(xbinary,0);
+    if ((x = cmkey(fttab,nfttyp,
+                  "type of file transfer", fmode, xxstring)) < 0)
+      return(x);
+    xmode = x;
+
+    cmarg2 = "";
+    if ((x = cmfld(y ?
+  "\nAs-name template containing replacement variables such as \\v(filename)" :
+  "Name to send it with", "",&s,NULL)) < 0)
+      if (x != -3)
+       return(x);
+#ifndef NOSPL
+    if (y && *s) {
+       char * p = tmpbuf;
+       x = TMPBUFSIZ;
+       zzstring(s,&p,&x);
+       if (!strcmp(tmpbuf,s)) {
+           printf(
+  "?As-name for file group must contain variables such as \\v(filename)\n"
+                  );
+           return(-9);
+       }
+    }
+#endif /* NOSPL */
+    ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+    cmarg2 = tmpbuf;
+
+    if ((x = cmcfm()) < 0)
+      return(x);
+    flp = (struct filelist *) malloc(sizeof(struct filelist));
+    if (flp) {
+       if (filetail)
+         filetail->fl_next = flp;
+       filetail = flp;
+       if (!filehead)
+         filehead = flp;
+       x = (int) strlen(line); /* Length of filename */
+       s = (char *) malloc(x + 1);
+       if (s) {
+           strcpy(s,line);             /* safe */
+           flp->fl_name = s;
+           flp->fl_mode = xmode;
+           x = (int) strlen(cmarg2);   /* Length of as-name */
+           if (x < 1) {
+               flp->fl_alias = NULL;
+           } else {
+               s = (char *) malloc(x + 1);
+               if (s) {
+                   strcpy(s,cmarg2);   /* safe */
+                   flp->fl_alias = s;
+               } else {
+                   printf("Sorry, can't allocate space for as-name");
+                   return(-9);
+               }
+           }
+           flp->fl_next = NULL;
+           filesinlist++;              /* Count this node */
+           return(success = 1);        /* Finished adding this node */
+       } else {
+           printf("Sorry, can't allocate space for name");
+           return(-9);
+       }
+    } else {
+       printf("Sorry, can't allocate file list node");
+       return(-9);
+    }
+#endif /* NOMSEND */
+}
+#endif /* ADDCMD */
+
+#ifndef NOHTTP                         /* HTTP ops... */
+#ifdef TCPSOCKET
+#define HTTP_GET 0                     /* GET */
+#define HTTP_PUT 1                     /* PUT */
+#define HTTP_POS 2                     /* POST */
+#define HTTP_IDX 3                     /* INDEX */
+#define HTTP_HED 4                      /* HEAD */
+#define HTTP_DEL 5                      /* DELETE */
+#define HTTP_CON 6                      /* CONNECT */
+#define HTTP_OPN 7                      /* OPEN */
+#define HTTP_CLS 8                      /* CLOSE */
+
+static struct keytab httptab[] = {
+    { "close",   HTTP_CLS, 0 },
+    { "connect", HTTP_CON, 0 },
+    { "delete",  HTTP_DEL, 0 },
+    { "get",     HTTP_GET, 0 },
+    { "head",    HTTP_HED, 0 },
+    { "index",   HTTP_IDX, 0 },
+    { "open",    HTTP_OPN, 0 },
+    { "put",     HTTP_PUT, 0 },
+    { "post",    HTTP_POS, 0 }
+};
+static int nhttptab = sizeof(httptab)/sizeof(struct keytab);
+
+/* HTTP switches */
+#define HT_SW_AG 0                     /* /AGENT */
+#define HT_SW_HD 1                     /* /HEADER */
+#define HT_SW_US 2                     /* /USER */
+#define HT_SW_PW 3                     /* /PASSWORD */
+#define HT_SW_AR 4                      /* /ARRAY */
+#define HT_SW_TP 5                      /* /TOSCREEN */
+
+static struct keytab httpswtab[] = {
+    { "/agent",    HT_SW_AG, CM_ARG },
+#ifndef NOSPL
+    { "/array",    HT_SW_AR, CM_ARG },
+#endif /* NOSPL */
+    { "/header",   HT_SW_HD, CM_ARG },
+    { "/password", HT_SW_PW, CM_ARG },
+    { "/toscreen", HT_SW_TP, 0 },
+    { "/user",     HT_SW_US, CM_ARG },
+    { "", 0, 0 }
+};
+static int nhttpswtab = sizeof(httpswtab)/sizeof(struct keytab) - 1;
+
+/* HTTP PUT/POST switches */
+#define HT_PP_MT 0                     /* /MIME-TYPE */
+
+static struct keytab httpptab[] = {
+    { "/mime-type", HT_PP_MT, CM_ARG },
+    { "", 0, 0 }
+};
+static int nhttpptab = sizeof(httpptab)/sizeof(struct keytab) - 1;
+
+#define HTTP_MAXHDR 8
+
+static int
+xdohttp(action, lfile, rf, dfile, agent, hdr, user, pass, mime, array, type)
+    int action;
+    char *lfile, *rf, *dfile, *agent, *hdr, *user, *pass, *mime, array;
+    int type;
+/* xdohttp */ {
+    int i, rc = 0;
+    char * hdrlist[HTTP_MAXHDR];
+    char rfile[CKMAXPATH+1];
+    extern int httpfd;
+
+    /* Check for a valid state to execute the command */
+    if (inserver) {
+        printf("?The HTTP command may not be used from the IKS\r\n");
+    } else if (httpfd == -1) {
+        if (http_reopen() < 0)
+         printf("?No connection\n");
+        else
+         rc = 1;
+    } else {
+       rc = 1;
+    }
+
+    /* If the command is not valid, exit with failure */
+    if (rc == 0)
+        return(success = 0);
+
+    if (action != HTTP_CON && rf[0] != '/') {
+        rfile[0] = '/';
+        ckstrncpy(&rfile[1],rf,CKMAXPATH);
+    } else {
+        ckstrncpy(rfile,rf,CKMAXPATH);
+    }
+    for (i = 0; i < HTTP_MAXHDR; i++)  /* Initialize header list */
+      hdrlist[i] = NULL;
+    makelist(hdr,hdrlist,HTTP_MAXHDR); /* Make header list */
+
+#ifdef BETADEBUG
+    for (i = 0; i < nhttptab; i++)     /* Find action keyword */
+      if (httptab[i].kwval == action)
+       break;
+    if (i == nhttptab) {               /* Shouldn't happen... */
+       printf("?Invalid action - %d\n",action);
+       return(0);                      /* Failure */
+    }
+
+    printf("HTTP action:  %s\n",httptab[i].kwd);
+    printf(" Agent:       %s\n",agent ? agent : "(null)");
+
+    if (hdrlist[1]) {
+       printf(" Header list: 1. %s\n",hdrlist[0]);
+       for (i = 1; i < HTTP_MAXHDR && hdrlist[i]; i++)
+         printf("%15d. %s\n",i+1,hdrlist[i]);
+    } else
+      printf(" Header:      %s\n",hdrlist[0] ? hdrlist[0] : "(null)");
+
+    printf(" User:        %s\n",user ? user : "(null)");
+#ifdef COMMENT
+    printf(" Password:    %s\n",pass ? pass : "(null)");
+#endif /* COMMENT */
+
+#ifndef NOSPL
+    if (array)
+      printf(" Array:       \\%%%c[]\n", array);
+    else
+      printf(" Array:       (none)\n");
+#endif /* NOSPL */
+
+    if (action == HTTP_PUT || action == HTTP_POS)
+      printf(" Mime-type:   %s\n",mime ? mime : "(null)");
+
+    printf(" Local file:  %s\n",lfile ? lfile : "(null)");
+    printf(" Remote file: %s\n",rfile ? rfile : "(null)");
+    printf(" Destination file: %s\n",dfile ? dfile : "(null)");
+#endif /* BETADEBUG */
+
+    /* The http_xxxx() functions return 0 on success, -1 on failure */
+    switch (action) {
+      case HTTP_CON: {
+         extern int ttyfd;
+         rc = http_connect(httpfd,agent,hdrlist,user,pass,array,rfile);
+         break;
+      }
+      case HTTP_DEL:
+        rc = http_delete(agent,hdrlist,user,pass,array,rfile);
+        break;
+      case HTTP_GET:
+        rc = http_get(agent,hdrlist,user,pass,array,lfile,rfile,type);
+        break;
+      case HTTP_HED:
+        rc = http_head(agent,hdrlist,user,pass,array,lfile,rfile,type);
+        break;
+      case HTTP_PUT:
+        rc = http_put(agent,hdrlist,mime,user,pass,array,lfile,rfile,dfile,
+                     type);
+        break;
+      case HTTP_POS:
+        rc = http_post(agent,hdrlist,mime,user,pass,array,lfile,rfile,dfile,
+                      type);
+        break;
+      case HTTP_IDX:
+        rc = http_index(agent,hdrlist,user,pass,array,lfile,rfile,type);
+        break;
+      default:
+        rc = -1;
+    }
+    return(rc == 0 ? 1 : 0);           /* Success is set by caller */
+}
+#endif /* TCPSOCKET */
+#endif /* NOHTTP */
+
+#ifndef NOSPL                          /* ARRAY ops... */
+static struct keytab arraytab[] = {
+    { "clear",     ARR_CLR, 0 },
+    { "copy",      ARR_CPY, 0 },
+    { "dcl",       ARR_DCL, CM_INV },
+    { "declare",   ARR_DCL, 0 },
+    { "destroy",   ARR_DST, CM_INV },
+    { "equate",    ARR_EQU, CM_INV },
+    { "link",      ARR_EQU, 0 },
+    { "resize",    ARR_RSZ, 0 },
+    { "set",       ARR_SET, 0 },
+#ifndef NOSHOW
+    { "show",      ARR_SHO, 0 },
+#endif /* NOSHOW */
+    { "sort",      ARR_SRT, 0 },
+    { "undeclare", ARR_DST, 0 },
+    { "", 0, 0 }
+};
+static int narraytab = sizeof(arraytab)/sizeof(struct keytab) - 1;
+
+#ifdef CKLEARN
+static struct keytab learnswi[] = {
+    { "/close",    2, 0 },
+    { "/off",      0, 0 },
+    { "/on",       1, 0 }
+};
+#endif /* CKLEARN */
+
+int
+arrayitoa(x) int x; {                  /* Array index to array letter */
+    if (x == 1)
+      return(64);
+    else if (x < 0 || x > (122 - ARRAYBASE))
+      return(-1);
+    else
+      return(x + ARRAYBASE);
+}
+
+int
+arrayatoi(c) int c; {                  /* Array letter to array index */
+    if (c == 64)
+      c = 96;
+    if (c > 63 && c < 91)
+      c += 32;
+    if (c < ARRAYBASE || c > 122)
+      return(-1);
+    return(c - ARRAYBASE);
+}
+
+static int                             /* Declare an array */
+dodcl(cx) int cx; {
+    int i, n, v, lo, hi, rc = 0;
+    int isdynamic = 0;
+    char tmpbuf[64];
+    char ** p = NULL;
+    char tmp[64];                      /* Local temporary string buffer */
+    if ((y = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
+       if (y == -3) {
+           printf("?Array name required\n");
+           return(-9);
+       } else return(y);
+    }
+    ckstrncpy(line,s,LINBUFSIZ);
+    s = line;
+    x = arraybounds(s,&lo,&hi);                /* Check syntax and get bounds */
+    debug(F111,"dodcl arraybounds",s,x);
+    if (x < 0) {                       /* Error - Maybe it's a variable */
+       char * p;                       /* whose value is an array name */
+       int n;
+       p = tmpbuf;
+       n = 63;
+       p[0] = NUL;
+       if (s[0] == CMDQ && s[1] == '&')
+         s++;
+       if (zzstring(s,&p,&n) > -1) {
+           s = tmpbuf;
+           x = arraybounds(s,&lo,&hi);
+           debug(F111,"dodcl arraybounds 2",s,x);
+       }
+       if (x < 0) {
+           printf("?Bad array name - \"%s\"\n",s);
+           return(-9);
+       }
+    }
+    debug(F101,"dodcl hi","",hi);
+    debug(F101,"dodcl lo","",lo);
+    debug(F101,"dodcl lo+1","",lo+1);
+
+    if (lo == -1 && hi == -1) {                /* Have good array name and bounds */
+       isdynamic = 1;
+       n = CMDBL / 5;
+    } else if (hi > -1) {
+       printf("?Segment notation not allowed in array declarations\n");
+       return(-9);
+    } else if ((lo+1) < 0) {
+       debug(F101,"dodcl underflow","",lo+1);
+        printf("?Dimension underflow\n");
+        return(-9);
+    } else
+      n = lo;
+    x = arrayitoa(x);
+    if (cx == XXUNDCL) {
+       n = 0;
+       v = 0;
+       if ((y = cmcfm()) < 0)
+         return(y);
+    } else {
+       p = (char **)malloc(sizeof(char **)*(n+1));
+       if (!p) {
+           printf("?Memory allocation error\n");
+           return(-9);
+       }
+       v = 0;                          /* Highest initialized member */
+       p[0] = NULL;                    /* Element 0 */
+       keepallchars = 1;
+       while (n > 0 && v < n) {        /* Parse initializers */
+           p[v+1] = NULL;
+           ckmakxmsg(tmp,
+                     64,
+                     "Initial value for \\&",
+                     ckctoa((char)x),
+                     "[",
+                     ckitoa(v+1),
+                     "]",
+                     NULL,NULL,NULL,NULL,NULL,NULL,NULL
+                     );
+           if ((rc = cmfld((char *)tmp,"",&s,xxstring)) < 0) { /* Get field */
+               if (rc == -3)           /* If answer is empty, we're done */
+                 break;
+               else                    /* Parse error, free temp pointers */
+                 goto dclx;
+           }
+           rc = 1;
+           if (v == 0 && !strcmp(s,"=")) /* Skip the = sign. */
+             continue;
+           s = brstrip(s);             /* Strip any braces */
+           makestr(&(p[++v]),s);
+       }
+       keepallchars = 0;
+       if ((y = cmtxt("Carriage return to confirm","",&s,NULL)) < 0)
+         return(y);
+       if (isdynamic)
+         n = v;
+    }
+    if (dclarray((char)x,n) < 0) {     /* Declare the array */
+       printf("?Declare failed\n");
+       goto dclx;
+    }
+    for (i = 1; i <= v; i++) {         /* Add any initial values */
+       tmp[0] = '&';
+       ckmakmsg(&tmp[1],63,ckctoa((char)x),"[",ckitoa(i),"]");
+       if (addmac(tmp,p[i]) < 0) {
+           printf("Array initialization error: %s %s\n",tmp,p[i]);
+           rc = -9;
+           goto dclx;
+       }
+    }
+  dclx:
+    if (p) {
+       for (i = 1; i <= v; i++)
+         if (p[i]) free(p[i]);
+       free((char *)p);
+    }
+    debug(F101,"DCL rc","",rc);
+    return(success = rc);
+}
+
+static int
+rszarray() {
+    int i, x, y, n, lo, hi, islink = -1;
+    char c, * s, ** ap = NULL;
+    if ((x = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
+       if (x == -3) {
+           printf("?Array name required\n");
+           return(-9);
+       } else return(x);
+    }
+    ckstrncpy(line,s,LINBUFSIZ);       /* Make safe copy of name */
+    s = line;
+    x = arraybounds(s,&lo,&hi);
+    if (x < 0) {                       /* Parse the name, get index */
+       printf("?Bad array reference - \"%s\"\n", s);
+       return(-9);
+    }
+    if (lo < 0 && hi < 0) {
+       y = cmnum("New size","",10,&lo,xxstring);
+       if (y < 0) {
+           if (y == -3)
+             printf("?New size required\n");
+           return(y);
+       }
+    }
+    if ((y = cmcfm()) < 0)
+      return(y);
+    if (a_link[x] > -1) {              /* Link? */
+       islink = x;                     /* Yes follow it */
+       x = a_link[x];                  /* and remember */
+    }
+    if (!a_ptr[x]) {
+       printf("?Array not declared - \"%s\"\n", s);
+       return(-9);
+    }
+    if (lo < 0) {
+       printf("?New size required\n");
+       return(-9);
+    }
+    if (hi > -1) {
+       printf("?Array segments not allowed for this operation\n");
+       return(-9);
+    }
+    c = arrayitoa(x);                  /* Get array letter */
+    if (c == '@') {                    /* Argument vector array off limits */
+       printf("?Sorry, \\&@[] is read-only\n");
+       return(-9);
+    }
+    if (lo == 0) {                     /* If new size is 0... */
+       dclarray(c,0);                  /* Undeclare the array */
+       return(success = 1);
+    }
+    n = a_dim[x];                      /* Current size */
+    ap = (char **) malloc((lo+1) * sizeof(char *)); /* New array */
+    y = (n < lo) ? n : lo;
+    for (i = 0; i <= y; i++)           /* Copy the part that fits */
+      ap[i] = a_ptr[x][i];
+    if (n < lo) {                      /* If original array smaller */
+       for (; i <= lo; i++)            /* initialize extra elements in */
+         ap[i] = NULL;                 /* new array to NULL. */
+    } else if (n > lo) {               /* If new array smaller */
+       for (; i <= lo; i++)            /* deallocate leftover elements */
+         makestr(&(a_ptr[x][i]),NULL); /* from original array. */
+    }
+    free((char *)a_ptr[x]);            /* Free original array list */
+    a_ptr[x] = ap;                     /* Replace with new one */
+    a_dim[x] = lo;                     /* Record the new dimension */
+    if (islink > -1) {                 /* Was this a link? */
+       a_ptr[islink] = ap;             /* If so point to the resized array */
+       a_dim[islink] = lo;
+    } else {                           /* If not are there links to here? */
+       for (i = 0; i < (int) 'z' - ARRAYBASE; i++) { /* Any linked arrays? */
+           if (i != x && a_link[i] == x) {     /* Find and update them */
+               a_ptr[i] = ap;
+               a_dim[i] = lo;
+           }
+       }
+    }
+    return(success = 1);
+}
+
+static int
+copyarray() {
+    int i, j, x1, lo1, hi1, x2, lo2, hi2, whole = 0;
+    char c1, c2, * a1, * a2;
+    if ((y = cmfld("Name of source array","",&s,NULL)) < 0)
+      return(y);
+    ckstrncpy(line,s,LINBUFSIZ);
+    a1 = line;
+    if ((x1 = arraybounds(a1,&lo1,&hi1)) < 0) {
+       printf("?Bad array reference - \"%s\"\n", a1);
+       return(-9);
+    } else if (!a_ptr[x1]) {
+       printf("?Array not declared - \"%s\"\n", a1);
+       return(-9);
+    }
+    c1 = arrayitoa(x1);
+
+    if ((y = cmfld("Name of destination array","",&s,NULL)) < 0)
+      return(y);
+    ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+    a2 = tmpbuf;
+    if ((x2 = arraybounds(a2,&lo2,&hi2)) < 0) {
+       printf("?Bad array reference - \"%s\"\n", a2);
+       return(-9);
+    }
+    c2 = arrayitoa(x2);
+
+    if ((x = cmcfm()) < 0)
+      return(x);
+
+    if (c2 == '@') {                   /* Argument vector array off limits */
+       printf("?Sorry, \\&@[] is read-only\n");
+       return(-9);
+    }
+    if (lo1 < 0 && lo2 < 0 && hi1 < 0 && hi2 < 0) /* Special case for */
+      whole = 1;                                 /* whole array... */
+
+    if (lo1 < 0) lo1 = whole ? 0 : 1;  /* Supply lower bound of source */
+    if (hi1 < 0) hi1 = a_dim[x1];      /* Supply upper bound of source */
+    if (lo2 < 0) lo2 = whole ? 0 : 1;  /* Lower bound of target */
+    if (hi2 < 0) hi2 = lo2 + hi1 - lo1;        /* Upper bound of target */
+    if (a_ptr[x2]) {                   /* Target array is already declared? */
+       if (hi2 > a_dim[x2])            /* If upper bound out of range */
+         hi2 = a_dim[x2];              /* shrink to fit */
+    } else {                           /* Otherwise... */
+       x2 = dclarray(c2, hi2);         /* declare the target array */
+    }
+    for (i = lo1, j = lo2; i <= hi1 && j <= hi2; i++,j++) { /* Copy */
+       makestr(&(a_ptr[x2][j]),a_ptr[x1][i]);
+    }
+    return(success = 1);
+}
+
+static int                             /* Undeclare an array */
+unarray() {
+    int x, y, n, rc = 0;
+    char c, * s;
+
+    if ((y = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
+       if (y == -3) {
+           printf("?Array name required\n");
+           return(-9);
+       } else return(y);
+    }
+    ckstrncpy(line,s,LINBUFSIZ);       /* Make safe copy of name */
+    s = line;
+    if ((y = cmcfm()) < 0)
+      return(y);
+    if ((x = arraybounds(s,&y,&n)) < 0) { /* Parse the name, get index */
+       printf("?Bad array reference - \"%s\"\n", s);
+       return(-9);
+    }
+    if (y > 0 || n > 0) {
+       printf("?Partial arrays can not be destroyed\n");
+       return(-9);
+    }
+    c = arrayitoa(x);                  /* Get array letter */
+    if (a_ptr[x]) {                    /* If array is declared */
+       if (c == '@') {                 /* Argument vector array off limits */
+           printf("?Sorry, \\&@[] is read-only\n");
+           return(-9);
+       }
+       rc = dclarray(c,0);             /* Undeclare the array */
+    } else                             /* It wasn't declared */
+      rc = 1;
+    if (rc > -1) {                     /* Set return code and success */
+       success = 1;
+       rc = 1;
+    } else {
+       success = 0;
+       printf("?Failed - destroy \"\\&%c[]\"\n", c);
+       rc = -9;
+    }
+    return(rc);
+}
+
+static int
+clrarray(cx) int cx; {
+    int i, x, lo, hi;
+    char c, * s, * val = NULL;
+
+    if ((x = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
+       if (x == -3) {
+           printf("?Array name required\n");
+           return(-9);
+       } else return(x);
+    }
+    ckstrncpy(line,s,LINBUFSIZ);       /* Make safe copy of name */
+    s = line;
+    if (cx == ARR_SET) {               /* SET */
+       if ((x = cmtxt("Value","",&val,xxstring)) < 0)
+         return(x);
+       ckstrncpy(tmpbuf,val,TMPBUFSIZ); /* Value to set */
+       val = tmpbuf;
+       if (!*val) val = NULL;
+    } else if ((x = cmcfm()) < 0)      /* CLEAR */
+      return(x);
+
+    if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Parse the name */
+       printf("?Bad array reference - \"%s\"\n", s);
+       return(-9);
+    }
+    c = arrayitoa(x);                  /* Get array letter */
+    if (!a_ptr[x]) {                   /* If array is declared */
+       printf("?Array %s is not declared\n", s);
+       return(-9);
+    } else if (c == '@') {             /* Argument vector array off limits */
+       printf("?Sorry, \\&@[] is read-only\n");
+       return(-9);
+    }
+    if (lo < 0) lo = 0;
+    if (hi < 0) hi = a_dim[x];
+    for (i = lo; i <= hi; i++)         /* Clear/Set selected range */
+      makestr(&(a_ptr[x][i]),val);
+
+    return(success = 1);
+}
+
+extern char **aa_ptr[CMDSTKL][28];
+extern int aa_dim[CMDSTKL][28];
+
+static int                             /* Create symbolic link to an array */
+linkarray() {
+    int i = 0, x, y, lo, hi, flag = 0;
+    char c, * s, * p;
+
+    if ((x = cmfld("Array name not currently in use","",&s,NULL)) < 0) {
+       if (x == -3) {
+           printf("?Array name required\n");
+           return(-9);
+       } else return(x);
+    }
+    ckstrncpy(line,s,LINBUFSIZ);       /* Make safe copy of link name */
+    s = line;
+    if ((x = cmfld("Name of existing array","",&p,xxstring)) < 0) {
+       if (x == -3) {
+           printf("?Array name required\n");
+           return(-9);
+       } else return(x);
+    }
+    ckstrncpy(tmpbuf,p,TMPBUFSIZ);     /* Make safe copy of array name */
+    p = tmpbuf;
+    if ((x = cmcfm()) < 0)
+      return(x);
+
+    if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Parse the link name */
+       printf("?Bad array reference - \"%s\"\n", s);
+       return(-9);
+    }
+    if (a_ptr[x]) {                    /* Must not already exist */
+       c = arrayitoa(x);
+       printf("?Array already exists: \\&%c[]\n", c);
+       return(-9);
+    }
+    if (lo > -1 || hi > -1) {
+       printf("?Sorry, whole arrays only: %s\n",s);
+       return(-9);
+    }
+    if ((y = arraybounds(p,&lo,&hi)) < 0) { /* Parse the array name */
+       printf("?Bad array reference - \"%s\"\n", s);
+       return(-9);
+    }
+    if (lo > -1 || hi > -1) {
+       printf("?Sorry, whole arrays only: %s\n",p);
+       return(-9);
+    }
+    if (x == y) {
+       for (i = cmdlvl; i >= 0; i--)
+         if (aa_ptr[i][x]) {
+             flag++;
+             break;
+         }
+    }
+    if (flag) {
+       a_ptr[x] = aa_ptr[i][y];        /* Link to saved copy */
+       a_dim[x] = aa_dim[i][y];
+    } else {                           /* Otherwise... */
+       c = arrayitoa(y);               /* Check if it's declared */
+       if (!a_ptr[y]) {
+           printf("?Array is not declared: \\&%c[]\n", c);
+           return(-9);
+       }
+       if (a_link[y] > -1) {           /* And if it's a link itself */
+           printf("?Links to links not allowed: \\&%c[]\n", c);
+           return(-9);
+       }
+       a_ptr[x] = a_ptr[y];            /* All OK, make the link */
+       a_dim[x] = a_dim[y];
+    }
+    a_link[x] = y;
+    return(success = 1);
+}
+#endif /* NOSPL */
+
+#ifndef NOCSETS
+static char * dcsetname = NULL;
+
+/* Get Display Character-Set Name */
+
+char *
+getdcset() {
+    char * s;
+    int y;
+#ifdef PCFONTS
+    extern int tt_font, ntermfont;
+    extern struct keytab term_font[];
+#endif /* PCFONTS */
+
+    s = "";
+#ifdef OS2
+    y = os2getcp();                    /* Default is current code page */
+    switch (y) {
+      case 437: s = "cp437"; break;
+      case 850: s = "cp850"; break;
+      case 852: s = "cp852"; break;
+      case 857: s = "cp857"; break;
+      case 858: s = "cp858"; break;
+      case 862: s = "cp862"; break;
+      case 866: s = "cp866"; break;
+      case 869: s = "cp869"; break;
+      case 1250: s = "cp1250"; break;
+      case 1251: s = "cp1251"; break;
+      case 1252: s = "cp1252"; break;
+      case 1253: s = "cp1253"; break;
+      case 1254: s = "cp1254"; break;
+      case 1255: s = "cp1255"; break;
+      case 1256: s = "cp1256"; break;
+      case 1257: s = "cp1257"; break;
+      case 1258: s = "cp1258"; break;
+    }
+#ifdef PCFONTS
+/*
+   If the user has loaded a font with SET TERMINAL FONT then we want
+   to change the default code page to the font that was loaded.
+*/
+    if (tt_font != TTF_ROM) {
+       for (y = 0; y < ntermfont; y++ ) {
+           if (term_font[y].kwval == tt_font) {
+               s = term_font[y].kwd;
+               break;
+           }
+       }
+    }
+#endif /* PCFONTS */
+#else /* OS2 */
+#ifdef COMMENT
+    /* Hack not needed as of C-Kermit 7.1 */
+    if (fcharset == FC_1LATIN) {
+       s = "latin1-iso";               /* Hack to avoid reporting "cp1252" */
+    } else {                           /* Report current file character set */
+#endif /* COMMENT */
+       for (y = 0; y <= nfilc; y++)
+         if (fcstab[y].kwval == fcharset) {
+             s = fcstab[y].kwd;
+             break;
+         }
+#ifdef COMMENT
+    }
+#endif /* COMMENT */
+#endif /* OS2 */
+    makestr(&dcsetname,s);             /* Return stable pointer */
+    return((char *)dcsetname);
+}
+#endif /* NOCSETS */
+
+#ifndef NOFRILLS
+static int
+doclear() {
+    if ((x = cmkey(clrtab,nclear,"item to clear",
+#ifdef NOSPL
+                  "device-buffer"
+#else
+                  "device-and-input"
+#endif /* NOSPL */
+                  ,xxstring)) < 0) return(x);
+#ifndef NOSPL
+#ifdef OS2
+    if (x == CLR_CMD || x == CLR_TRM) {
+       if ((z = cmkey(clrcmdtab,nclrcmd,"how much screen to clear\n",
+                      "all",xxstring)) < 0)
+         return(z);
+    }
+#endif /* OS2 */
+#endif /* NOSPL */
+    if ((y = cmcfm()) < 0)
+      return(y);
+
+    /* Clear device input buffer if requested */
+    y = (x & CLR_DEV) ? ttflui() : 0;
+
+    if (x & CLR_SCR)                   /* CLEAR SCREEN */
+      y = ck_cls();                    /* (= SCREEN CLEAR = CLS) */
+
+    if (x & CLR_KBD) {                 /* CLEAR KEYBOARD */
+       int n;
+       n = conchk();
+       y = 0;
+       while (n-- > 0 && (y = coninc(0) > -1))
+         ;
+       y = (y > -1) ? 0 : -1;
+    }
+
+#ifndef NOSPL
+    /* Clear INPUT command buffer if requested */
+    if (x & CLR_INP) {
+       for (z = 0; z < inbufsize; z++)
+         inpbuf[z] = NUL;
+       inpbp = inpbuf;
+       y = 0;
+    }
+#ifdef CK_APC
+    if (x & CLR_APC) {
+       debug(F101,"Executing CLEAR APC","",apcactive);
+       apcactive = 0;
+       y = 0;
+    }
+#endif /* CK_APC */
+    if (x & CLR_ALR) {
+       setalarm(0L);
+       y = 0;
+    }
+#endif /* NOSPL */
+
+#ifdef PATTERNS
+    if (x & (CLR_TXT|CLR_BIN)) {
+       int i;
+       for (i = 0; i < FTPATTERNS; i++) {
+           if (x & CLR_TXT)
+             makestr(&txtpatterns[i],NULL);
+           if (x & CLR_BIN)
+             makestr(&binpatterns[i],NULL);
+       }
+       y = 0;
+    }
+#endif /* PATTERNS */
+
+#ifndef NODIAL
+    if (x & CLR_DIA) {
+       dialsta = DIA_UNK;
+       y = 0;
+    }
+#endif /* NODIAL */
+
+#ifndef NOMSEND
+    if (x & CLR_SFL) {                 /* CLEAR SEND-LIST */
+       if (filehead) {
+           struct filelist * flp, * next;
+           flp = filehead;
+           while (flp) {
+               if (flp->fl_name)
+                 free(flp->fl_name);
+               if (flp->fl_alias)
+                 free(flp->fl_alias);
+               next = flp->fl_next;
+               free((char *)flp);
+               flp = next;
+           }
+       }
+       filesinlist = 0;
+       filehead = NULL;
+       filetail = NULL;
+       addlist = 0;
+       y = 0;
+    }
+#endif /* NOMSEND */
+
+#ifdef OS2
+#ifndef NOLOCAL
+    switch (x) {
+      case CLR_SCL:
+       clearscrollback(VTERM);
+       break;
+      case CLR_CMD:
+       switch ( z ) {
+         case CLR_C_ALL:
+           clear();
+           break;
+         case CLR_C_BOS:
+           clrboscr_escape(VCMD,SP);
+           break;
+         case CLR_C_BOL:
+           clrbol_escape(VCMD,SP);
+           break;
+         case CLR_C_EOL:
+           clrtoeoln(VCMD,SP);
+           break;
+         case CLR_C_EOS:
+           clreoscr_escape(VCMD,SP);
+           break;
+         case CLR_C_LIN:
+           clrline_escape(VCMD,SP);
+           break;
+         case CLR_C_SCR:
+           clearscrollback(VCMD);
+           break;
+       default:
+           printf("Not implemented yet, sorry.\n");
+           break;
+       }
+       break;
+
+#ifndef NOTERM
+      case CLR_TRM:
+        switch ( z ) {
+         case CLR_C_ALL:
+            if (VscrnGetBufferSize(VTERM) > 0 ) {
+                VscrnScroll(VTERM, UPWARD, 0,
+                            VscrnGetHeight(VTERM)-(tt_status[VTERM]?2:1),
+                            VscrnGetHeight(VTERM) -
+                            (tt_status[VTERM]?1:0), TRUE, SP
+                            );
+                cleartermscreen(VTERM);
+            }
+            break;
+         case CLR_C_BOS:
+           clrboscr_escape(VTERM,SP);
+           break;
+         case CLR_C_BOL:
+           clrbol_escape(VTERM,SP);
+           break;
+         case CLR_C_EOL:
+           clrtoeoln(VTERM,SP);
+           break;
+         case CLR_C_EOS:
+           clreoscr_escape(VTERM,SP);
+           break;
+         case CLR_C_LIN:
+           clrline_escape(VTERM,SP);
+           break;
+        case CLR_C_SCR:
+            clearscrollback(VTERM);
+            break;
+        default:
+            printf("Not implemented yet, sorry.\n");
+            break;
+       }
+       break;
+#endif /* NOTERM */
+    }
+    y = 0;
+#endif /* NOLOCAL */
+#endif /* OS2 */
+    return(success = (y == 0));
+}
+#endif /* NOFRILLS */
+
+#ifndef NOSPL
+static int
+doeval(cx) int cx; {
+    char *p;
+    char vnambuf[VNAML], * vnp = NULL; /* These must be on the stack */
+    if (!oldeval) {
+       if ((y = cmfld("Variable name","",&s,
+                      ((cx == XX_EVAL) ? xxstring : NULL))) < 0) {
+           if (y == -3) {
+               printf("?Variable name required\n");
+               return(-9);
+           } else return(y);
+       }
+       ckstrncpy(vnambuf,s,VNAML);     /* Make a copy. */
+       vnp = vnambuf;
+       if (vnambuf[0] == CMDQ &&
+           (vnambuf[1] == '%' || vnambuf[1] == '&'))
+         vnp++;
+       y = 0;
+       if (*vnp == '%' || *vnp == '&') {
+           if ((y = parsevar(vnp,&x,&z)) < 0)
+             return(y);
+       }
+    }
+    if ((x = cmtxt("Integer arithmetic expression","",&s,xxstring)) < 0)
+      return(x);
+    p = evala(s);
+    if (!p) p = "";
+    if (oldeval && *p)
+      printf("%s\n", p);
+    ckstrncpy(evalbuf,p,32);
+    if (!oldeval)
+      return(success = addmac(vnambuf,p));
+    else
+      return(success = *p ? 1 : 0);
+}
+#endif /* NOSPL */
+
+#ifdef TNCODE
+static int
+dotelopt() {
+    if ((x = cmkey(telcmd, ntelcmd, "TELNET command", "", xxstring)) < 0 )
+      return(x);
+    switch (x) {
+      case WILL:
+      case WONT:
+      case DO:
+      case DONT:
+       if ((y = cmkey(tnopts,ntnopts,"TELNET option","",xxstring)) < 0)
+         return(y);
+       if ((z = cmcfm()) < 0) return(z);
+
+       switch (x) {
+         case WILL:
+           if (TELOPT_UNANSWERED_WILL(y))
+             return(success = 0);
+           break;
+         case WONT:
+           if (TELOPT_UNANSWERED_WONT(y))
+             return(success = 0);
+           break;
+         case DO:
+           if (TELOPT_UNANSWERED_DO(y))
+             return(success = 0);
+           break;
+         case DONT:
+           if (TELOPT_UNANSWERED_DONT(y))
+             return(success = 0);
+           break;
+       }
+       if (local) {
+           success = ((tn_sopt(x,y) > -1) ? 1 : 0);
+       } else {
+           printf("ff%02x%02x\n",x,y);
+           success = 1;
+       }
+       if (success) {
+           switch (x) {
+             case WILL:
+               TELOPT_UNANSWERED_WILL(y) = 1;
+               break;
+             case WONT:
+               if ( TELOPT_ME(y) )
+                 TELOPT_UNANSWERED_WONT(y) = 1;
+               break;
+             case DO:
+               TELOPT_UNANSWERED_DO(y) = 1;
+               break;
+             case DONT:
+               if ( TELOPT_ME(y) )
+                 TELOPT_UNANSWERED_DONT(y) = 1;
+               break;
+           }
+           if (tn_wait("XXTELOP") < 0) {
+               tn_push();
+               success = 0;
+           }
+       }
+       return(success);
+      case SB:
+       if ((y=cmkey(tnsbopts,ntnsbopts,"TELNET option","",xxstring)) < 0)
+         return(y);
+       switch (y) {
+         case TELOPT_NAWS:
+           /* Some compilers require switch() to have at least 1 case */
+#ifdef CK_NAWS
+           TELOPT_SB(TELOPT_NAWS).naws.x = 0;
+           TELOPT_SB(TELOPT_NAWS).naws.y = 0;
+           if (local)
+             return(success = ((tn_snaws() > -1) ? 1 : 0));
+           else
+             return(success = 0);
+#else
+           return(success = 0);
+#endif /* CK_NAWS */
+       }
+        return(success = 0);
+
+#ifdef CK_KERBEROS
+#ifdef KRB5
+      case TN_FWD:
+        success = (kerberos5_forward() == AUTH_SUCCESS);
+        return(success);
+#endif /* KRB5 */
+#endif /* CK_KERBEROS */
+
+      default:
+       if ((z = cmcfm()) < 0) return(z);
+#ifndef NOLOCAL
+       if (local) {
+           CHAR temp[3];
+           if (network && IS_TELNET()) { /* TELNET */
+               temp[0] = (CHAR) IAC;
+               temp[1] = x;
+               temp[2] = NUL;
+               success = (ttol((CHAR *)temp,2) > -1 ? 1 : 0);
+               if (tn_deb || debses || deblog) {
+                   /* TN_MSG_LEN is in ckctel.h */
+                   ckmakmsg(tn_msg,256,"TELNET SENT ",TELCMD(x),NULL,NULL);
+                   debug(F101,tn_msg,"",x);
+                   if (debses || tn_deb) tn_debug(tn_msg);
+               }
+               return(success);
+           }
+            return(success = 0);
+       } else {
+#endif /* NOLOCAL */
+           printf("ff%02x\n",x);
+           return(success = 1);
+#ifndef NOLOCAL
+       }
+#endif /* NOLOCAL */
+    }
+}
+#endif /* TNCODE */
+
+
+#ifndef NOPUSH
+#ifndef NOFRILLS
+static int
+doedit() {
+#ifdef OS2
+    char * p = NULL;
+#endif /* OS2 */
+    if (!editor[0]) {
+       s = getenv("EDITOR");
+       if (s) ckstrncpy(editor,s,CKMAXPATH);
+       editor[CKMAXPATH] = NUL;
+       if (!editor[0]) {
+           printf("?Editor not defined - use SET EDITOR to define\n");
+           return(-9);
+       }
+    }
+    ckstrncpy(tmpbuf,editfile,TMPBUFSIZ);
+/*
+  cmiofi() lets us parse the name of an existing file, or the name of
+  a nonexistent file to be created.
+*/
+    x = cmiofi("File to edit", (char *)tmpbuf, &s, &y, xxstring);
+    if (x < 0) {
+       if (x == -9) {
+           if (zchko(s) < 0) {
+               printf("Can't create \"%s\"\n",s);
+               return(x);
+           }
+       } else if (x != -3)
+         return(x);
+    }
+    if (x == -3)
+      tmpbuf[0] = NUL;
+    else {
+       ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+       if (iswild((char *)tmpbuf)) {
+           printf("?A single file please\n");
+           return(-9);
+       }
+    }
+    if ((z = cmcfm()) < 0) return(z);
+    if (nopush) {
+       printf("?Sorry, editing not allowed\n");
+       return(success = 0);
+    }
+    if (tmpbuf[0]) {
+    /* Get full path in case we change directories between EDIT commands */
+       zfnqfp(tmpbuf, CKMAXPATH, editfile);
+       editfile[CKMAXPATH] = NUL;
+#ifdef OS2
+       p = editfile;                   /* Flip the stupid slashes */
+       while (*p) {
+           if (*p == '/') *p = '\\';
+           p++;
+       }
+#endif /* OS2 */
+    } else
+      editfile[0] = NUL;
+    x = 0;
+    if (editopts[0]) {
+#ifdef OS2
+       x = ckindex("%1",(char *)editopts,0,0,1);
+       if (x > 0)
+         editopts[x] = 's';
+       else
+#endif /* OS2 */
+         x = ckindex("%s",(char *)editopts,0,0,1);
+    }
+    if (((int)strlen(editopts) + (int)strlen(editfile) + 1) < TMPBUFSIZ) {
+       if (x)
+         sprintf(tmpbuf,editopts,editfile);
+       else
+         sprintf(tmpbuf,"%s %s",editopts,editfile);
+    }
+    s = line;
+    ckmakmsg(s,LINBUFSIZ,editor," ",tmpbuf,NULL);
+#ifdef OS2
+    p = s + strlen(editor);            /* And again with the slashes */
+    while (p != s) {
+       if (*p == '/') *p = '\\';
+       p--;
+    }
+#endif /* OS2 */
+    conres();
+    x = zshcmd(s);
+    concb((char)escape);
+    return(x);
+}
+#endif /* NOFRILLS */
+#endif /* NOPUSH */
+
+#ifdef BROWSER
+static int
+dobrowse() {
+#ifdef OS2
+    char * p = NULL;
+#endif /* OS2 */
+    if (nopush) {
+       printf("?Sorry, browsing not allowed\n");
+       return(success = 0);
+    }
+#ifndef NT
+    /* Windows lets the Shell Execute the URL if no Browser is defined */
+    if (!browser[0]) {
+       s = getenv("BROWSER");
+       if (s) ckstrncpy(browser,s,CKMAXPATH);
+       browser[CKMAXPATH] = NUL;
+       if (!browser[0]) {
+           printf("?Browser not defined - use SET BROWSER to define\n");
+           return(-9);
+       }
+    }
+#endif /* NT */
+    ckstrncpy(tmpbuf,browsurl,TMPBUFSIZ);
+    if ((x = cmtxt("URL",(char *)browsurl,&s,xxstring)) < 0)
+      return(x);
+    ckstrncpy(browsurl,s,4096);
+    x = 0;
+    if (browsopts[0]) {
+#ifdef OS2
+       x = ckindex("%1",(char *)browsopts,0,0,1);
+       if (x > 0)
+         browsopts[x] = 's';
+       else
+#endif /* OS2 */
+         x = ckindex("%s",(char *)browsopts,0,0,1);
+    }
+    if (((int)strlen(browsopts) + (int)strlen(browsurl) + 1) < TMPBUFSIZ) {
+       if (x)
+         sprintf(tmpbuf,browsopts,browsurl);
+       else
+         sprintf(tmpbuf,"%s %s",browsopts,browsurl);
+    }
+#ifdef NT
+    if (!browser[0])
+      return(success = Win32ShellExecute(browsurl));
+#endif /* NT */
+    s = line;
+    ckmakmsg(s,LINBUFSIZ,browser," ",tmpbuf,NULL);
+#ifdef OS2
+    p = line + strlen(browser);                /* Flip slashes */
+    while (p != line) {
+       if (*p == '/') *p = '\\';
+       p--;
+    }
+#endif /* OS2 */
+    conres();
+    x = zshcmd(s);
+    concb((char)escape);
+    return(x);
+}
+#endif /* BROWSER */
+
+#ifdef CK_RECALL
+static int
+doredo() {                     /* Find a previous cmd and redo it */
+    extern int on_recall, in_recall;
+    int x;
+    char * p;
+
+    if ((x = cmtxt(
+"pattern, or first few characters of a previous command",
+                  "*",&s,xxstring)) < 0)
+      return(x);
+    ckstrncpy(line,s,LINBUFSIZ);
+    x = strlen(s);
+    s = line;
+    if (*s == '{') {                   /* Braces disable adding * to end */
+       if (s[x-1] == '}') {
+           s[x-1] = NUL;
+           s++;
+           x--;
+       }
+    } else {                           /* No braces, add * to end. */
+       s[x] = '*';
+       s[x+1] = NUL;
+    }
+
+    while (x > 0 && s[x] == '*' && s[x-1] == '*') s[x--] = NUL;
+
+    if (!on_recall || !in_recall) {
+       printf("?Sorry, command recall can't be used now.\n");
+       return(-9);
+    }
+    if ((p = cmgetcmd(s))) {           /* Look for it history buffer */
+       ckmakmsg(cmdbuf,CMDBL,p,"\r",NULL,NULL); /* Copy to command buffer */
+       if (!quiet)                     /* Echo it */
+         printf("%s\n",cmdbuf);
+       cmaddnext();                    /* Force re-add to history buffer */
+       return(cmflgs = -1);            /* Force reparse */
+    } else {
+       printf("?Sorry - \"%s\" not found\n", s);
+       return(-9);
+    }
+}
+#endif /* CK_RECALL */
+
+#ifndef NOXFER
+#ifndef NOCSETS
+static int
+doassoc()  {                           /* ASSOCIATE */
+    extern struct keytab tcstab[];
+    extern int ntcs;
+    if ((x = cmkey(assoctab, nassoc, "", "", xxstring)) < 0 )
+      return(x);
+
+    switch (x) {                       /* Associate what? */
+
+      case ASSOC_TC:                   /* Transfer character-set... */
+       if ((x = cmkey(tcstab, ntcs,
+                      "transfer character-set name","",xxstring)) < 0)
+         return(x);
+       if ((y = cmkey(fcstab, nfilc,
+                      "with file character-set","", xxstring)) < 0)
+         if (y != -3)
+           return(y);
+       if ((z = cmcfm()) < 0)
+         return(z);
+       axcset[x] = y;
+       return(success = 1);
+
+      case ASSOC_FC:                   /* File character-set... */
+       if ((x = cmkey(fcstab, nfilc,
+                      "file character-set name","",xxstring)) < 0)
+         return(x);
+       if ((y = cmkey(tcstab, ntcs,
+                      "with transfer character-set","", xxstring)) < 0)
+         if (y != -3)
+           return(y);
+       if ((z = cmcfm()) < 0)
+         return(z);
+       afcset[x] = y;
+       return(success = 1);
+
+      default:
+       return(-2);
+    }
+}
+#endif /* NOCSETS */
+#endif /* NOXFER */
+
+#ifndef NOHELP
+static int
+domanual() {
+#ifdef OS2
+    if ((x = cmcfm()) < 0)
+      return(x);
+    if (nopush) {
+       printf("?Sorry, access to system commands is disabled.\n");
+       return(-9);
+    }
+    y = mxlook(mactab,"manual",nmac);
+    if (y > -1) {
+       z = maclvl;                     /* Save the current maclvl */
+       dodo(y,NULL,cmdstk[cmdlvl].ccflgs); /* Run the macro */
+       while (maclvl > z) {
+           debug(F101,"XXMAN loop maclvl 1","",maclvl);
+           sstate = (CHAR) parser(1);
+           debug(F101,"XXMAN loop maclvl 2","",maclvl);
+           if (sstate) proto();
+       }
+       debug(F101,"XXMAN loop exit maclvl","",maclvl);
+       return(success);
+    }
+    return(success = 0);
+#else
+    if ((x = cmtxt(
+#ifdef UNIX
+                  "Carriage return to confirm the command, or manual topic",
+#else
+                  "Carriage return to confirm the command, or help topic",
+#endif /* UNIX */
+                  "kermit",
+                  &s,
+                  xxstring
+                  )
+        ) < 0)
+      return(x);
+#endif /* OS2 */
+
+#ifdef UNIX
+    ckmakmsg(tmpbuf,TMPBUFSIZ,"man ",s,NULL,NULL);
+#else
+    ckmakmsg(tmpbuf,TMPBUFSIZ,"help ",s,NULL,NULL);
+#endif /* UNIX */
+    debug(F110,"MANUAL",tmpbuf,0);
+    if (nopush) {
+       printf("?Sorry, access to system commands is disabled.\n");
+       return(-9);
+    } else {
+       conres();                       /* Restore the console */
+       success = zshcmd(tmpbuf);
+       concb((char)escape);            /* Restore CBREAK mode */
+       return(success);
+    }
+}
+#endif /* NOHELP */
+
+#ifndef NOHTTP
+#ifdef TCPSOCKET
+static struct keytab sslswtab[] = {
+    { "/ssl", 1, 0 },
+    { "/tls", 1, 0 }
+};
+
+#ifndef NOURL
+struct urldata http_url = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+#endif /* NOURL */
+
+static int
+dohttp() {                             /* HTTP */
+    struct FDB sw, kw, fi;
+    int n, getval, allinone = 0;
+    char c, * p;
+    char rdns[128];
+
+    char * http_agent = NULL;          /* Parse results */
+    char * http_hdr   = NULL;
+    char * http_user  = NULL;
+    char * http_pass  = NULL;
+    char * http_mime  = NULL;
+    char * http_lfile = NULL;
+    char * http_rfile = NULL;
+    char * http_dfile = NULL;
+    char   http_array = NUL;
+    int    http_action = -1;
+
+    char * http_host = NULL;
+    char * http_srv  = NULL;
+    int    http_ssl  = 0;
+
+    static char * http_d_agent = NULL;
+    static char * http_d_user = NULL;
+    static char * http_d_pass = NULL;
+
+    static int    http_d_type = 0;
+    int           http_type = http_d_type;
+
+#ifdef OS2
+    p = "Kermit 95";                   /* Default user agent */
+#else
+    p = "C-Kermit";
+#endif /* OS2 */
+    makestr(&http_agent,p);
+    makestr(&http_mime,"text/HTML");   /* MIME type default */
+    rdns[0] = '\0';
+
+    cmfdbi(&sw,                                /* 1st FDB - general switches */
+       _CMKEY,                         /* fcode */
+       "OPEN, CLOSE, GET, HEAD, PUT, INDEX, or POST,\n or switch", /* hlpmsg */
+       "",                             /* default */
+       "",                             /* addtl string data */
+       nhttpswtab,                     /* addtl numeric data 1: tbl size */
+       4,                              /* addtl numeric data 2: 4 = cmswi */
+       xxstring,                       /* Processing function */
+       httpswtab,                      /* Keyword table */
+       &kw                             /* Pointer to next FDB */
+       );
+    cmfdbi(&kw,                                /* 2nd FDB - commands */
+       _CMKEY,                         /* fcode */
+       "Command",                      /* hlpmsg */
+       "",                             /* default */
+       "",                             /* addtl string data */
+       nhttptab,                       /* addtl numeric data 1: tbl size */
+       0,                              /* addtl numeric data 2: 0 = keyword */
+       xxstring,                       /* Processing function */
+       httptab,                                /* Keyword table */
+       NULL                            /* Pointer to next FDB */
+       );
+
+    while (1) {
+       x = cmfdb(&sw);                 /* Parse something */
+       if (x < 0)                      /* Error */
+         goto xhttp;
+       n = cmresult.nresult;
+       if (cmresult.fdbaddr == &kw)    /* Command - exit this loop */
+         break;
+       c = cmgbrk();                   /* Switch... */
+       getval = (c == ':' || c == '=');
+       x = -9;
+       if (getval && !(cmgkwflgs() & CM_ARG)) {
+           printf("?This switch does not take an argument\n");
+           goto xhttp;
+       }
+       switch (cmresult.nresult) {     /* Handle each switch */
+          case HT_SW_TP:                /* /TOSCREEN */
+            http_type = 1;
+            break;
+         case HT_SW_AG:                /* /AGENT */
+           if (getval) {
+               if ((x = cmfld("User agent",p,&s,xxstring)) < 0)
+                 goto xhttp;
+           } else {
+               s = p;
+           }
+           makestr(&http_agent,s);
+           break;
+         case HT_SW_HD:                /* /HEADER */
+           s = NULL;
+           if (getval) {
+               if ((x = cmfld("Header line","",&s,xxstring)) < 0) {
+                   if (x == -3)
+                     s = NULL;
+                   else
+                     goto xhttp;
+               }
+           }
+           makestr(&http_hdr,s);
+           break;
+         case HT_SW_US:                /* /USER */
+           s = NULL;
+           if (getval) {
+               if ((x = cmfld("User ID","",&s,xxstring)) < 0) {
+                  if (x == -3)
+                    s = "";
+                  else
+                   goto xhttp;
+                }
+           }
+           makestr(&http_user,s);
+           break;
+         case HT_SW_PW:                /* /PASSWORD */
+           debok = 0;
+           s = NULL;
+           if (getval) {
+               if ((x = cmfld("Password","",&s,xxstring)) < 0)
+                 goto xhttp;
+           }
+           makestr(&http_pass,s);
+           break;
+#ifndef NOSPL
+         case HT_SW_AR: {              /* /ARRAY: */
+             char * s2, array = NUL;
+             if (!getval) {
+                 printf("?This switch requires an argument\n");
+                 x = -9;
+                 goto xhttp;
+             }
+             if ((x = cmfld("Array name (a single letter will do)",
+                            "",
+                            &s,
+                            NULL
+                            )) < 0) {
+                 if (x == -3) {
+                     printf("?Array name required\n");
+                     x = -9;
+                     goto xhttp;
+                 } else
+                   goto xhttp;
+             }
+             if (!*s) {
+                 printf("?Array name required\n");
+                 x = -9;
+                 goto xhttp;
+             }
+             s2 = s;
+             if (*s == CMDQ) s++;
+             if (*s == '&') s++;
+             if (!isalpha(*s)) {
+                 printf("?Bad array name - \"%s\"\n",s2);
+                 x = -9;
+                 goto xhttp;
+             }
+             array = *s++;
+             if (isupper(array))
+               array = tolower(array);
+             if (*s && (*s != '[' || *(s+1) != ']')) {
+                 printf("?Bad array name - \"%s\"\n",s2);
+                 http_array = NUL;
+                 x = -9;
+                 goto xhttp;
+             }
+             http_array = array;
+             break;
+         }
+#endif /* NOSPL */
+         default:
+           x = -2;
+           goto xhttp;
+       }
+    }
+    http_action = n;                   /* Save the action */
+    if (http_action == HTTP_PUT || http_action == HTTP_POS) {
+       cmfdbi(&sw,                     /* 1st FDB - switch */
+              _CMKEY,                  /* fcode */
+              "Local filename\n Or switch", /* help */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              nhttpptab,               /* keyword table size */
+              4,                       /* addtl numeric data 2: 4 = cmswi */
+              xxstring,                /* Processing function */
+              httpptab,                /* Keyword table */
+              &fi                      /* Pointer to next FDB */
+              );
+       cmfdbi(&fi,                     /* 2nd FDB - filename */
+              _CMIFI,                  /* fcode */
+              "Local filename",        /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              0,                       /* addtl numeric data 1 */
+              0,                       /* addtl numeric data 2 */
+              xxstring,
+              NULL,
+              NULL
+              );
+       while (1) {
+           x = cmfdb(&sw);
+           if (x < 0)
+             goto xhttp;               /* Free any malloc'd temp strings */
+           n = cmresult.nresult;
+           if (cmresult.fcode != _CMKEY)
+             break;
+           c = cmgbrk();               /* Switch... */
+           getval = (c == ':' || c == '=');
+           if (getval && !(cmgkwflgs() & CM_ARG)) {
+               printf("?This switch does not take an argument\n");
+               x = -9;
+               goto xhttp;
+           }
+           switch (n) {
+             case HT_PP_MT:
+               s = "text/HTML";
+               if (getval) {
+                   if ((x = cmfld("MIME type",
+                                  "text/HTML",&s,xxstring)) < 0)
+                     goto xhttp;
+               }
+               makestr(&http_mime,s);
+               break;
+             default:
+               x = -2;
+               goto xhttp;
+           }
+       }
+       makestr(&http_lfile,cmresult.sresult);
+       n = ckindex("/",http_lfile,-1,1,0);
+       if (n)
+         p = &http_lfile[n];
+       else
+         p = http_lfile;
+       if ((x = cmfld("URL or remote filename",p,&s,xxstring)) < 0) {
+          if (x == -3) {
+            printf("?%s what?\n",(http_action == HTTP_PUT) ? "Put" : "Post");
+            x = -9;
+          }
+          goto xhttp;
+        }
+       if (!*s) s = NULL;
+       makestr(&http_rfile,s);
+
+       if ((x = cmtxt("Response filename","",&s,xxstring)) < 0) {
+          if (x != -3)
+            goto xhttp;
+        }
+        if (*s)
+          makestr(&http_dfile,s);
+    }
+    switch (http_action) {
+      case HTTP_DEL:                   /* DELETE */
+       if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
+          if (x == -3) {
+            printf("?Delete what?\n");
+            x = -9;
+          }
+          goto xhttp;
+        }
+       makestr(&http_rfile,s);
+       break;
+      case HTTP_CON:                   /* CONNECT */
+        if ((x = cmfld("Remote host[:port]","",&s,xxstring)) < 0) {
+          if (x == -3) {
+            printf("?Remote host[:port] is required\n");
+            x = -9;
+          }
+          goto xhttp;
+        }
+       makestr(&http_rfile,s);
+       break;
+      case HTTP_HED: {                 /* HEAD */
+         char buf[CKMAXPATH+1];
+         if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
+             if (x == -3) {
+                 printf("?Head of what?\n");
+                 x = -9;
+             }
+             goto xhttp;
+         }
+         makestr(&http_rfile,s);
+
+         if (http_array || http_type) { /* Default result filename */
+             p = "";                    /* None if /ARRAY or /TOSCREEN */
+         } else {
+             n = ckindex("/",http_rfile,-1,1,0); /* Otherwise strip path */
+             if (n)                              /* and add ".head" */
+               p = &http_rfile[n];
+             else
+               p = http_rfile;
+             ckmakmsg(buf,CKMAXPATH,p,".head",NULL,NULL);
+             p = buf;
+         }
+         if ((x = cmofi("Local filename",p,&s,xxstring)) < 0) {
+             if (x != -3)
+               goto xhttp;
+         }
+         makestr(&http_lfile,s);
+         break;
+      }
+      case HTTP_GET:                   /* GET */
+      case HTTP_IDX: {                 /* INDEX */
+         char * lfile = "";
+         if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
+             if (x == -3) {
+                 printf("?Get what?\n");
+                 x = -9;
+             }
+             goto xhttp;
+         }
+         makestr(&http_rfile,s);
+         if (http_action == HTTP_GET && !http_type)
+           zstrip(http_rfile,&lfile);
+         if ((x = cmofi("Local filename",lfile,&s,xxstring)) < 0)
+           if (x != -3)
+             goto xhttp;
+         makestr(&http_lfile,s);
+         break;
+      }
+      case HTTP_OPN: {
+         int sslswitch = 0;
+#ifdef CK_SSL
+         struct FDB sw, fl;
+         cmfdbi(&sw,
+                _CMKEY,                /* fcode */
+                "IP host name or address, or switch", /* hlpmsg */
+                "",                    /* default */
+                "",                    /* addtl string data */
+                2,                     /* addtl numeric data 1: tbl size */
+                4,                     /* addtl numeric data 2: 4 = cmswi */
+                xxstring,              /* Processing function */
+                sslswtab,              /* Keyword table */
+                &fl                    /* Pointer to next FDB */
+                );
+         cmfdbi(&fl,                   /* 2nd FDB - host */
+                _CMFLD,                /* fcode */
+                "",                    /* hlpmsg */
+                "",                    /* default */
+                "",                    /* addtl string data */
+                0,                     /* addtl numeric data 1 */
+                0,                     /* addtl numeric data 2 */
+                xxstring,
+                NULL,
+                NULL
+                );
+         x = cmfdb(&sw);               /* Parse switch or host */
+         if (x < 0)                    /* Error */
+           goto xhttp;
+         if (cmresult.fcode == _CMFLD) { /* Host */
+             s = cmresult.sresult;       /* Set up expected pointer */
+             goto havehost;              /* Go parse rest of command */
+         }
+         sslswitch = 1;                /* /SSL or /TLS switch - set flag */
+#endif /* CK_SSL */
+
+         /* Parse host */
+
+         if ((x = cmfld("URL, hostname, or ip-address","",&s,xxstring)) < 0) {
+             if (x == -3) {
+                 printf("?Open what?\n");
+                 x = -9;
+             }
+             goto xhttp;
+         }
+
+       havehost:                       /* Come here with s -> host */
+#ifdef CK_URL
+         x = urlparse(s,&http_url);    /* Was a URL given? */
+         if (x < 1) {                  /* Not a URL */
+#endif /* CK_URL */
+             makestr(&http_host,s);
+             if ((x =
+                  cmfld("Service name or port number",
+                        sslswitch ? "https" : "http",&s,xxstring)) < 0)
+               goto xhttp;
+             else
+               makestr(&http_srv,s);
+#ifdef CK_URL
+         } else if (ckstrcmp(http_url.svc,"http",-1,0) && /* Non-HTTP URL */
+                    ckstrcmp(http_url.svc,"https",-1,0)) {
+             printf("?Non-HTTP URL\n");
+             x = -9;
+             goto xhttp;
+         } else {                      /* Have HTTP URL */
+             makestr(&http_srv, http_url.svc);
+             makestr(&http_user,http_url.usr);
+             makestr(&http_pass,http_url.psw);
+             makestr(&http_host,http_url.hos);
+             if (http_url.por)
+               makestr(&http_srv,http_url.por);
+             makestr(&http_rfile,http_url.pth);
+         }
+         if (http_rfile) {             /* Open, GET, and Close */
+             printf("?Directory/file path not allowed in HTTP OPEN URL\n");
+             x = -9;
+             goto xhttp;
+         }
+         if (!ckstrcmp("https",http_srv,-1,0) || sslswitch ||
+             !ckstrcmp("443",http_srv,-1,0))
+           http_ssl = 1;
+#endif /* CK_URL */
+         break;
+      }
+      case HTTP_CLS:
+        break;
+    }
+    if ((x = cmcfm()) < 0)
+      goto xhttp;
+
+    if (http_action == HTTP_OPN) {
+        x = (http_open(http_host,http_srv,http_ssl,rdns,128,http_agent) == 0);
+        if (x) {
+            if (!quiet) {
+              if (rdns[0])
+                printf("Connected to %s [%s]\r\n",http_host,rdns);
+              else
+                printf("Connected to %s\r\n",http_host);
+            }
+            if (http_agent) {
+                if (http_d_agent)
+                 free(http_d_agent);
+                http_d_agent = http_agent;
+                http_agent = NULL;
+            }
+            if (http_user) {
+                if (http_d_user)
+                 free(http_d_user);
+                http_d_user = http_user;
+                http_user = NULL;
+            }
+            if (http_pass) {
+                if (http_d_pass) {
+                    memset(http_d_pass,0,strlen(http_d_pass));
+                    free(http_d_pass);
+                }
+                http_d_pass = http_pass;
+                http_pass = NULL;
+            }
+            http_d_type = http_type;
+        } else {
+            if (!quiet)
+             printf("?HTTP Connection failed.\r\n");
+        }
+    } else if (http_action == HTTP_CLS) {
+        if (http_d_agent) {
+            free(http_d_agent);
+            http_d_agent = NULL;
+        }
+        if (http_d_user) {
+            free(http_d_user);
+            http_d_user = NULL;
+        }
+        if (http_d_pass) {
+            memset(http_d_pass,0,strlen(http_d_pass));
+            free(http_d_pass);
+            http_d_pass = NULL;
+        }
+        http_d_type = 0;
+        x = (http_close() == 0);
+    }
+    if ((http_action != HTTP_CLS) &&
+       (http_action != HTTP_CON) && http_rfile) { /* Remote file is URL? */
+
+       /* All-in-one actions when a URL is given... */
+
+#ifdef CK_URL
+       if (urlparse(http_rfile,&http_url) > 0) { /* Have URL? */
+           if (ckstrcmp(http_url.svc,"http",-1,0) && /* It's an HTTP URL? */
+               ckstrcmp(http_url.svc,"https",-1,0)) {
+               printf("?Non-HTTP URL\n");
+               x = -9;
+               goto xhttp;
+           } else {                    /* Yes, collect the pieces */
+               makestr(&http_srv, http_url.svc);
+               makestr(&http_user,http_url.usr);
+               makestr(&http_pass,http_url.psw);
+               makestr(&http_host,http_url.hos);
+               if (http_url.por)
+                 makestr(&http_srv,http_url.por);
+               makestr(&http_rfile,http_url.pth);
+           }
+           if (!http_rfile) {          /* Still have a path? */
+                makestr(&http_rfile,"/");
+           }
+           if (!ckstrcmp("https",http_srv,-1,0) || /* Check for SSL/TLS */
+               !ckstrcmp("443",http_srv,-1,0))
+             http_ssl = 1;
+           if (http_isconnected())     /* Close any open HTTP connection */
+             http_close();
+           if (http_pass == NULL && http_d_pass != NULL)
+             makestr(&http_pass,http_d_pass);
+           x = (http_open(http_host,
+                          http_srv,http_ssl,rdns,128,http_d_agent) == 0);
+           if (x < 0) {
+               x = 0;
+               goto xhttp;
+           }
+           allinone = 1;
+       }
+#endif /* CK_URL */
+        if (http_pass == NULL && http_d_pass != NULL)
+         makestr(&http_pass,http_d_pass);
+
+       if (http_action == HTTP_OPN && allinone) {
+           http_action = HTTP_GET;
+       }
+        x = xdohttp(http_action,
+                    http_lfile,
+                   http_rfile,
+                    http_dfile,
+                   http_agent ? http_agent : http_d_agent,
+                   http_hdr,
+                   http_user  ? http_user  : http_d_user,
+                   http_pass  ? http_pass  : http_d_pass,
+                   http_mime,
+                   http_array,
+                   http_type
+                   );
+       if (allinone)
+         x = (http_close() == 0);
+    }
+
+  xhttp:
+    if (http_agent) free(http_agent);
+    if (http_hdr)   free(http_hdr);
+    if (http_user)  free(http_user);
+    if (http_pass) {
+        memset(http_pass,0,strlen(http_pass));
+        free(http_pass);
+    }
+    if (http_mime)  free(http_mime);
+    if (http_lfile) free(http_lfile);
+    if (http_rfile) free(http_rfile);
+    if (http_dfile) free(http_dfile);
+    if (http_host)  free(http_host);
+    if (http_srv)   free(http_srv);
+
+    if (x > -1)
+      success = x;
+    return(x);
+}
+#endif /* TCPSOCKET */
+#endif /* NOHTTP */
+
+
+#ifndef NOSPL
+static int
+dotrace() {
+    int on = 1;
+    struct FDB sw, kw;
+    cmfdbi(&sw,                                /* 1st FDB - switch */
+          _CMKEY,                      /* fcode */
+          "Trace object;\n Or switch", /* help */
+          "",                          /* default */
+          "",                          /* addtl string data */
+          2,                           /* keyword table size */
+          4,                           /* addtl numeric data 2: 4 = cmswi */
+          xxstring,                    /* Processing function */
+          onoffsw,                     /* Keyword table */
+          &kw                          /* Pointer to next FDB */
+          );
+    cmfdbi(&kw,                                /* 2nd FDB - Trace object */
+          _CMKEY,                      /* fcode */
+          "Trace object",              /* help */
+          "all",                       /* default */
+          "",                          /* addtl string data */
+          ntracetab,                   /* keyword table size */
+          0,                           /* addtl numeric data 2: 0 = keyword */
+          xxstring,                    /* Processing function */
+          tracetab,                    /* Keyword table */
+          NULL                         /* Pointer to next FDB */
+          );
+    if ((x = cmfdb(&sw)) < 0)
+      return(x);
+    if (cmresult.fdbaddr == &sw) {
+       on = cmresult.nresult;
+       if ((x = cmkey(tracetab, ntracetab,"","all",xxstring)) < 0)
+         return(x);
+    } else {
+       x = cmresult.nresult;
+    }
+    if ((y = cmcfm()) < 0)
+      return(y);
+
+    switch (x) {
+      case TRA_ASG:
+       tra_asg = on;
+       break;
+      case TRA_CMD:
+       tra_cmd = on;
+       break;
+      case TRA_ALL:
+       tra_asg = on;
+       tra_cmd = on;
+       break;
+      default:
+       return(-2);
+    }
+    printf("TRACE %s\n", on ? "ON" : "OFF");
+    return(success = 1);
+}
+#endif /* NOSPL */
+
+
+static int
+doprompt() {
+    extern int xcmdsrc;
+    if ((x = cmtxt("Optional message","",&s,xxstring)) < 0)
+      return(x);
+#ifdef NOSPL
+    printf("?Sorry, PROMPT requires script programming language\n");
+    return(-9);
+#else
+    debug(F101,"Prompt cmdlvl","",cmdlvl);
+    cmdlvl++;
+    if (cmdlvl > CMDSTKL) {
+       printf("?Command stack overflow: %d\n",cmdlvl);
+       cmdlvl--;
+       return(-9);
+    }
+    xcmdsrc = CMD_KB;
+    cmdstk[cmdlvl].src = CMD_KB;       /* Say we're at the prompt */
+    cmdstk[cmdlvl].lvl = 0;
+    cmdstk[cmdlvl].ccflgs = cmdstk[cmdlvl-1].ccflgs;
+    if (tra_cmd)
+      printf("[%d] +P: \"(prompt)\"\n",cmdlvl);
+    concb((char)escape);
+    if (!quiet)
+      printf(
+"(Recursive command prompt: Resume script with CONTINUE, STOP to stop...)\n"
+            );
+    if (*s) {                          /* If prompt given */
+       makestr(&(prstring[cmdlvl-1]),cmgetp()); /* Save current prompt */
+       cmsetp(s);                      /* Set new one */
+    }
+    return(success = 1);
+#endif /* NOSPL */
+}
+
+#ifdef CKLEARN
+VOID
+learncmd(s) char *s; {                 /* Record commands in learned script */
+    char buf[64];
+    int i, k;
+    if (learnfp && learning) {         /* Only if open and on */
+       k = ckstrncpy(buf,s,64);
+       for (i = 0; i < k; i++) {       /* Get top-level command keyword */
+           if (buf[i] <= SP) {
+               buf[i] = NUL;
+               break;
+           }
+       }
+       k = lookup(cmdtab,buf,ncmd,NULL); /* Look it up */
+       if (k == XXCON || k == XXLEARN)   /* Don't record CONNECT or LEARN */
+         return;
+       if (k == XXTEL) {
+           fputs("SET HOST /NETWORK:TCP",learnfp);
+           fputs(&s[i],learnfp);
+           fputs(" TELNET /TELNET",learnfp);
+           fputs("\nIF FAIL STOP 1 Connection failed\n",learnfp);
+       } else {
+           fputs(s,learnfp);
+           fputs("\n",learnfp);
+       }
+    }
+}
+#endif /* CKLEARN */
+
+
+/*  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).
+*/
+#ifdef DEBUG
+int cmdstats[256] = { -1, -1 };
+#endif /* DEBUG */
+
+int
+docmd(cx) int cx; {
+    extern int nolocal, cmkwflgs;
+
+    debug(F101,"docmd entry, cx","",cx);
+    activecmd = cx;
+    doconx = ((activecmd == XXCON)  || (activecmd == XXTEL) ||
+             (activecmd == XXRLOG) || (activecmd == XXPIPE) ||
+              (activecmd == XXIKSD) || (activecmd == XXPTY));
+/*
+  Originally all commands were handled with a big switch() statement,
+  but eventually this started blowing up compilers.  Now we have a series
+  of separate if statements and small switches, with the commands that are
+  most commonly executed in scipts and loops coming first, to speed up
+  compute-bound scripts.
+  */
+
+#ifdef DEBUG
+    if (cmdstats[0] == -1) {           /* Count commands */
+       int i;                          /* for tuning... */
+       for (i = 0; i < 256; i++)
+         cmdstats[i] = 0;
+    }
+#endif /* DEBUG */
+
+    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 */
+         ckstrncat(cmdbuf,"\015",CMDBL); /*  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:
+       if (cx < 0)
+         return(cx);
+       break;
+    }
+#ifdef DEBUG
+    if (cx < 256)
+      cmdstats[cx]++;
+#endif /* DEBUG */
+
+    if ((cmkwflgs & CM_PSH)
+#ifndef NOPUSH
+       && nopush
+#endif /* NOPUSH */
+       ) {
+       printf("?Access to system disabled\n");
+       return(-9);
+    }
+    if ((cmkwflgs & CM_LOC)
+#ifndef NOLOCAL
+       && nolocal
+#endif /* NOLOCAL */
+       ) {
+       printf("?Connections disabled\n");
+       return(-9);
+    }
+
+#ifndef NOSPL
+    /* Used in FOR loops */
+
+    if (cx == XX_INCR || cx == XXINC  || /* _INCREMENT, INCREMENT */
+       cx == XX_DECR || cx == XXDEC)    /* _DECREMENT, DECREMENT */
+      return(doincr(cx));
+
+    /* Define (or change the definition of) a macro or variable */
+
+    if (cx == XXUNDEF || cx == XXUNDFX) {
+#ifdef IKSD
+       if (inserver && !ENABLED(en_asg)) {
+           printf("?Sorry, DEFINE/ASSIGN disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+       return(doundef(cx));            /* [_]UNDEFINE */
+    }
+    if (cx == XXDEF || cx == XXASS ||
+       cx == XXDFX || cx == XXASX) {
+#ifdef IKSD
+       if (inserver && !ENABLED(en_asg)) {
+           printf("?Sorry, DEFINE/ASSIGN disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+       if (atmbuf[0] == '.' && !atmbuf[1]) /* "." entered as keyword */
+         xxdot = 1;                    /* i.e. with space after it... */
+       return(dodef(cx));              /* DEFINE, ASSIGN, etc... */
+    }
+
+    /* IF, WHILE, and friends  */
+
+    if (cx == XXIF || cx == XXIFX || cx == XXWHI || cx == XXASSER) {
+       return(doif(cx));
+    }
+    if (cx == XXSWIT) {                        /* SWITCH */
+       return(doswitch());
+    }
+
+    /* GOTO, FORWARD, and _FORWARD (used internally by FOR, WHILE, etc) */
+
+    if (cx == XXGOTO || cx == XXFWD || cx == XXXFWD) { /* GOTO or FORWARD */
+       /* Note, here we don't set SUCCESS/FAILURE flag */
+#ifdef COMMENT
+       if ((y = cmfld("label","",&s,xxstring)) < 0) {
+           if (y == -3) {
+               if (cx != XXXFWD) {
+                   printf("?Label name required\n");
+                   return(-9);
+               }
+           } else
+             return(y);
+       }
+       ckstrncpy(lblbuf,s,LBLSIZ);
+       if ((x = cmcfm()) < 0) return(x);
+#else
+       if ((y = cmtxt("label","",&s,xxstring)) < 0) {
+           if (y == -3) {
+               if (cx != XXXFWD) {
+                   printf("?GOTO: Label name required: \"%s\" \"%s\"\n",
+                          atmbuf,
+                          cmdbuf);
+                   return(-9);
+               }
+           } else
+             return(y);
+       }
+       ckstrncpy(lblbuf,brstrip(s),LBLSIZ);
+#endif /* COMMENT */
+       s = lblbuf;
+       debug(F111,"GOTO target",s,cx);
+       return(dogoto(s,cx));
+    }
+    if (cx == XXDO || cx == XXMACRO) { /* DO (a macro) */
+       char mnamebuf[16];              /* (buffer for controlled temp name) */
+       struct FDB kw, fl;
+       int mx;                         /* Macro index (on stack!) */
+
+       debug(F101,"XXMACRO 0",line,cx);
+       if (cx == XXDO) {
+           if (nmac == 0) {
+               printf("\n?No macros defined\n");
+               return(-9);
+           }
+           for (y = 0; y < nmac; y++) { /* copy the macro table into a */
+               mackey[y].kwd = mactab[y].kwd; /* regular keyword table */
+               mackey[y].kwval = y;    /* with value = pointer to macro tbl */
+               mackey[y].flgs = mactab[y].flgs;
+           }
+           cmfdbi(&kw,                 /* First FDB - macro name */
+                  _CMKEY,              /* fcode */
+                  "Macro",             /* hlpmsg */
+                  "",                  /* default */
+                  "",                  /* addtl string data */
+                  nmac,                /* addtl numeric data 1: tbl size */
+                  0,                   /* addtl numeric data 2: 0 = cmkey */
+                  xxstring,            /* Processing function */
+                  mackey,              /* Keyword table */
+                  &fl                  /* Pointer to next FDB */
+                  );
+           cmfdbi(&fl,                 /* 2nd FDB - for "{" */
+                  _CMFLD,              /* fcode */
+                  "",                  /* hlpmsg */
+                  "",
+                  "",                  /* addtl string data */
+                  0,                   /* addtl numeric data 1 */
+                  0,                   /* addtl numeric data 2 */
+                  xxstring,
+                  NULL,
+                  NULL
+                  );
+           x = cmfdb(&kw);             /* Parse something */
+           if (x < 0) {                /* Error */
+               if (x == -3) {
+                   printf("?Macro name required\n");
+                   return(-9);
+               } else
+                 return(x);
+           }
+           if (cmresult.fcode == _CMKEY) {
+               extern int mtchanged;
+               char * macroname = NULL;
+
+           /* In case args include an \fexec() that changes the macro table */
+
+               mx = x;                 /* Save macro index on stack */
+               mtchanged = 0;          /* Mark state of macro table */
+               makestr(&macroname,mactab[mx].kwd); /* Save name */
+
+               if ((y = cmtxt("optional arguments","",&s,xxstring)) < 0)
+                 return(y);            /* Get macro args */
+
+               if (mtchanged) {        /* Macro table changed? */
+                   mx = mlook(mactab,macroname,nmac); /* Look up name again */
+               }
+               if (macroname)
+                 free(macroname);
+
+               return(dodo(mx,s,cmdstk[cmdlvl].ccflgs) < 1 ?
+                      (success = 0) : 1);
+           }
+           ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* _CMFLD */
+           if (atmbuf[0] == '{') {
+               if ((y = cmcfm()) < 0)
+                 return(y);
+           }
+       } else {                        /* XXMACRO ("immediate macro") */
+           int k = 0;
+           line[k++] = '{';
+           line[k++] = SP;
+           line[k] = NUL;
+           debug(F111,"XXMACRO A",line,k);
+           /* Defer evaluation of variables until the commands are exec'd */
+           if ((y = cmtxt("Braced list of commands","",&s,NULL)) < 0)
+             return(y);
+           k = ckstrncpy(line+k,s,LINBUFSIZ-k);
+           debug(F111,"XXMACRO B",line,k);
+       }
+       x = strlen(line);
+       if ((line[0] == '{' && line[x-1] != '}') || line[0] == '}')
+         return(-2);
+       if (line[0] != '{' && line[x-1] != '}') {
+           /* Unknown command.  If ON_UNKNOWN_COMMAND macro is defined, */
+           /* parse args and then execute it, but only if it is not */
+           /* already active. */
+           int k = -1;
+           if (!unkmacro) {
+               k = mxlook(mactab,"on_unknown_command",nmac);
+           }
+           if (k > -1) {
+               ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
+               z = maclvl;             /* Save the current maclvl */
+               if ((y = cmtxt("text","",&s,xxstring)) < 0)
+                 return(y);
+               ckstrncat(tmpbuf," ",TMPBUFSIZ);
+               ckstrncat(tmpbuf,s,TMPBUFSIZ);
+               unkmacro = 1;
+               debug(F110,"ON_UNKNOWN_COMMAND",s,0);
+               dodo(k,tmpbuf,cmdstk[cmdlvl].ccflgs); /* Run the macro */
+               while (maclvl > z) {
+                   sstate = (CHAR) parser(1);
+                   if (sstate) proto();
+               }
+               debug(F101,"UNKMAC loop exit maclvl","",maclvl);
+               unkmacro = 0;
+               return(success);
+           }
+            if (x > 0)
+             printf("?Not a command or macro name: \"%s\"\n",line);
+            else
+             printf("?Not a command or macro name.\n");
+           return(-9);
+       }
+       s = brstrip(line);
+       sprintf(mnamebuf," ..tmp:%03d",cmdlvl); /* safe (16) */
+       x = addmac(mnamebuf,s);
+       return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs) < 1 ? (success = 0) : 1);
+    }
+
+    if (cx == XXLBL) {                 /* LABEL */
+       if ((x = cmfld("label","",&s,xxstring)) < 0) {
+           if (x == -3) {
+#ifdef COMMENT
+               printf("?LABEL: Label name required: \"%s\"\n", cmdbuf);
+               return(-9);
+#else
+               s = "";
+#endif /* COMMENT */
+           } else return(x);
+
+       }
+       debug(F111,"LABEL",s,x);
+       if ((x = cmcfm()) < 0) return(x);
+       return(0);
+    }
+
+    if (cx == XXEVAL || cx == XX_EVAL) /* _EVALUATE,  EVALUATE  */
+      return(doeval(cx));
+
+#ifndef NOSEXP
+    if (cx == XXSEXP) {                        /* Lisp-like S-Expression */
+       struct stringarray * q;
+       char /* *p, *r, */ *tmp, *m;
+       int i, k, n, quote = 0, contd = 0, size = 0, len = 0;
+       extern int sexprc, sexppv;
+
+       tmp = tmpbuf;                   /* Buffer to collect SEXP */
+       tmpbuf[0] = NUL;                /* Clear it */
+       size = TMPBUFSIZ;               /* Capacity of buffer */
+       sexprc = -1;                    /* Assume bad input */
+       n = 0;                          /* Paren balance counter */
+
+       while (1) {                     /* Allow SEXP on multiple lines */
+           m = contd ?
+             "Continuation of S-Expression" :
+               "S-Expression (\"help sexp\" for details)";
+           x = cmtxt(m,"",&s,xxstring);
+           if (x < 0)
+             return(x);
+           if (!*s)                    /* Needed for (=) and (:) */
+             s = atmbuf;
+           k = ckmakmsg(tmp, size, contd ? " " : "(", s, NULL, NULL);
+           if (k < 1) {
+               printf("?SEXP too long - %d max\n",TMPBUFSIZ);
+               return(-9);
+           }
+           debug(F111,contd ? "sexp contd" : "sexp",s,k);
+
+           for (i = len; i < len+k; i++) { /* Check balance  */
+               if (!quote && tmpbuf[i] == CMDQ) {
+                   quote = 1;
+                   continue;
+               }
+               if (quote) {
+                   quote = 0;
+                   continue;
+               }
+               if (tmpbuf[i] == '(')
+                 n++;
+               else if (tmpbuf[i] == ')')
+                 n--;
+           }
+           if (n == 0) {               /* Break when balanced */
+               break;
+           }
+           if (n < 0) {                /* Too many right parens */
+               printf("?Unbalanced S-Expression: \"%s\"\n",tmpbuf);
+               return(-9);
+           }
+           contd++;                    /* Need more right parens */
+           cmini(ckxech);              /* so keep parsing */
+           tmp += k;                   /* adjust buffer pointer */
+           size -= k;                  /* and capacity */
+           len += k;                   /* and length so far */
+       }
+       s = tmpbuf;
+       makestr(&lastsexp,s);
+       q = cksplit(1,SEXPMAX,s,NULL,NULL,8,0,0); /* Precheck for > 1 SEXP */
+       debug(F101,"sexp split","",q->a_size);
+
+       if (q->a_size == 1) {           /* We should get exactly one back */
+           char * result, * dosexp();
+           sexprc = 0;                 /* Reset out-of-band return code */
+           result = dosexp(s);         /* Get result */
+           debug(F111,"sexp result",result,sexprc);
+           if (sexprc == 0) {          /* Success */
+               /* Echo the result if desired */
+               if ((!xcmdsrc && sexpecho != SET_OFF) || sexpecho == SET_ON)
+                 printf(" %s\n",result ? result : "");
+               makestr(&sexpval,result);
+               success = sexppv > -1 ? sexppv : 1;
+               return(success);
+           }
+       }
+       if (sexprc < 0)
+         printf("?Invalid S-Expression: \"%s\"\n",lastsexp);
+       return(-9);
+    }
+#endif /* NOSEXP */
+
+#endif /* NOSPL */
+
+    if (cx == XXECH || cx == XXXECH || cx == XXVOID
+#ifndef NOSPL
+       || cx == XXAPC
+#endif /* NOSPL */
+       ) {                             /* ECHO or APC */
+       if ((x = cmtxt((cx == XXECH || cx == XXXECH) ?
+                      "Text to be echoed" :
+                      ((cx == XXVOID) ? "Text" :
+                       "Application Program Command text"),
+                      "",
+                      &s,
+                      xxstring
+                      )
+            ) < 0)
+         return(x);
+       if (!s) s = "";
+#ifdef COMMENT
+/* This is to preserver the pre-8.0 behavior but it's too confusing */
+       x = strlen(s);
+       x = (x > 1) ? ((s[0] == '"' && s[x-1] == '"') ? 1 : 0) : 0;
+#endif /* COMMENT */
+       s = brstrip(s);                 /* Strip braces and doublequotes */
+       if (cx == XXECH) {              /* ECHO */
+#ifndef NOSPL
+           if (!fndiags || fnsuccess) {
+#endif /* NOSPL */
+#ifdef COMMENT
+               /* The "if (x)" business preserves previous behavior */
+               /* by putting back the doublequotes if they were included. */
+               if (x)
+                 printf("\"%s\"\n",s);
+               else
+#endif /* COMMENT */
+                 printf("%s\n",s);
+#ifndef NOSPL
+           }
+#endif /* NOSPL */
+       } else if (cx == XXXECH) {      /* XECHO */
+           if (x)
+             printf("\"%s\"",s);
+           else
+             printf("%s",s);
+#ifdef UNIX
+           fflush(stdout);
+#endif /* UNIX */
+       } else if (cx == XXAPC) {       /* APC */
+#ifdef CK_APC
+           if (apcactive == APC_LOCAL ||
+               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
+             return(success = 0);
+#endif /* CK_APC */
+           if (!local) {
+               printf("%c_%s%c\\",ESC,s,ESC);
+#ifdef UNIX
+               fflush(stdout);
+#endif /* UNIX */
+
+           } else {                    /* Local mode - have connection */
+#ifndef NOSPL
+               if (ckmakxmsg(tmpbuf,   /* Form APC string in buffer */
+                             TMPBUFSIZ,
+                             ckctoa((char)ESC),
+                             ckctoa('_'),
+                             s,
+                             ckctoa((char)ESC),
+                             ckctoa('\\'),
+                             NULL,NULL,NULL,NULL,NULL,NULL,NULL
+                             ) > 0)
+                 return(success = dooutput(tmpbuf, XXOUT));
+               printf("?Too long\n");
+               return(-9);
+#else
+               printf("%c_%s%c\\",ESC,s,ESC);
+#endif /* NOSPL */
+           }
+       }
+       return(success = 1);
+    }
+
+#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
+#ifdef CKCHANNELIO
+    if (cx == XXFILE)
+      return(dofile(cx));
+    else if (cx == XXF_RE || cx == XXF_WR || cx == XXF_OP ||
+            cx == XXF_CL || cx == XXF_SE || cx == XXF_RW ||
+            cx == XXF_FL || cx == XXF_LI || cx == XXF_ST || cx == XXF_CO)
+      return(dofile(cx));
+#endif /* CKCHANNELIO */
+
+/* ASK, ASKQ, READ */
+    if (cx == XXASK  || cx == XXASKQ || cx == XXREA ||
+       cx == XXRDBL || cx == XXGETC || cx == XXGETK) {
+       return(doask(cx));
+    }
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+    if (cx == XXBUG) {                 /* BUG */
+       if ((x = cmcfm()) < 0) return(x);
+       return(dobug());
+    }
+#endif /* NOFRILLS */
+
+#ifndef NOXFER
+    if (cx == XXBYE) {                 /* BYE */
+       extern int ftp_cmdlin;
+       if ((x = cmcfm()) < 0) return(x);
+
+#ifdef NEWFTP
+       if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
+           extern int stayflg, ftp_fai;
+           success = ftpbye();
+           if (ftp_cmdlin && !stayflg && !local)
+             doexit(ftp_fai ? BAD_EXIT : GOOD_EXIT,-1);
+           else
+             return(success);
+       }
+#endif /* NEWFTP */
+
+       if (!local) {
+           printf("?No connection - use EXIT to quit.\n");
+           return(-9);
+       }
+
+#ifdef CK_XYZ
+       if (protocol != PROTO_K) {
+           printf("?Sorry, BYE only works with Kermit protocol\n");
+           return(-9);
+       }
+#endif /* CK_XYZ */
+
+#ifdef IKS_OPTION
+        if (
+#ifdef CK_XYZ
+            protocol == PROTO_K &&
+#endif /* CK_XYZ */
+            !iks_wait(KERMIT_REQ_START,1)) {
+           printf(
+            "?A Kermit Server is not available to process this command\n");
+           return(-9);                 /* Correct the return code */
+        }
+#endif /* IKS_OPTION */
+
+       bye_active = 1;
+       sstate = setgen('L',"","","");
+       if (local) ttflui();            /* If local, flush tty input buffer */
+       return(0);
+    }
+#endif /* NOXFER */
+
+    if (cx == XXBEEP) {                        /* BEEP */
+        int x;
+#ifdef OS2
+       int y;
+        if ((y = cmkey(beeptab, nbeeptab, "which kind of beep", "information",
+                      xxstring)) < 0 )
+         return (y);
+       if ((x = cmcfm()) < 0) return(x);
+        bleep((short)y);               /* y is one of the BP_ values */
+#else  /* OS2 */
+       if ((x = cmcfm()) < 0) return(x);
+#ifndef NOSPL
+        bleep(BP_NOTE);
+#else
+       putchar('\07');
+#endif /* NOSPL */
+#endif /* OS2 */
+        return(0);
+    }
+
+#ifndef NOFRILLS
+    if (cx == XXCLE)                   /* CLEAR */
+      return(success = doclear());
+#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);
+    }
+
+#ifndef NOLOCAL
+    if (cx == XXCON || cx == XXCQ)     /* CONNECT or CONNECT /QUIETLY */
+      return(doxconn(cx));
+#endif /* NOLOCAL */
+
+#ifndef NOFRILLS
+#ifdef ZCOPY
+    if (cx == XXCPY) {                 /* COPY a file */
+#ifdef IKSD
+       if (inserver && !ENABLED(en_cpy)) {
+           printf("?Sorry, COPY is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+#ifdef CK_APC
+       if (apcactive == APC_LOCAL ||
+           (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
+           )
+         return(success = 0);
+#endif /* CK_APC */
+       return(docopy());
+    }
+#endif /* ZCOPY */
+#ifdef NT
+    if ( cx == XXLINK ) {
+#ifdef IKSD
+        if (inserver && !ENABLED(en_cpy)) {
+            printf("?Sorry, LINK (COPY) is disabled\n");
+            return(-9);
+        }
+#endif /* IKSD */
+#ifdef CK_APC
+        if (apcactive == APC_LOCAL ||
+            (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
+            )
+          return(success = 0);
+#endif /* CK_APC */
+        return(dolink());
+    }
+#endif /* NT */
+#endif /* NOFRILLS */
+
+    /* CD and friends */
+    if (cx == XXCWD  || cx == XXCDUP || cx == XXBACK ||
+       cx == XXLCWD || cx == XXLCDU || cx == XXKCD) {
+#ifdef LOCUS
+       if (!locus) {
+           if (cx == XXCWD) {
+#ifdef NOXFER
+                return(-2);
+#else
+                return(dormt(XZCWD));
+#endif /* NOXFER */
+           } else if (cx == XXCDUP) {
+#ifdef NOXFER
+                return(-2);
+#else
+                return(dormt(XZCDU));
+#endif /* NOXFER */
+            }
+       }
+#endif /* LOCUS */
+#ifdef IKSD
+       if (inserver && !ENABLED(en_cwd)) {
+           printf("?Sorry, changing directories is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+       return(success = docd(cx));
+    }
+
+    if (cx == XXCHK)                   /* CHECK */
+      return(success = dochk());
+
+    if (cx == XXCLO) {                 /* CLOSE */
+       x = cmkey(clstab,ncls,"\"CONNECTION\", or log or file to close",
+                 "connection",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);
+#ifndef NOLOCAL
+       if (x == 9999) {                /* CLOSE CONNECTION */
+           x = clsconnx(0);
+           switch (x) {
+             case 0:
+               if (msgflg) printf("?Connection was not open\n");
+             case -1:
+               return(0);
+             case 1:
+               whyclosed = WC_CLOS;
+               return(1);
+           }
+           return(0);
+       }
+#endif /* NOLOCAL */
+       y = doclslog(x);
+       success = (y == 1);
+       return(success);
+    }
+
+#ifndef NOSPL
+    if (cx == XXDCL || cx == XXUNDCL) {        /* DECLARE an array */
+       return(dodcl(cx));
+    }
+#endif /* NOSPL */
+
+#ifndef NODIAL
+    if (cx == XXRED  || cx == XXDIAL || cx == XXPDIA ||
+       cx == XXANSW || cx == XXLOOK) { /* DIAL, REDIAL etc */
+#ifdef VMS
+       extern int batch;
+#else
+#ifdef UNIXOROSK
+       extern int backgrd;
+#endif /* UNIXOROSK */
+#endif /* VMS */
+       x = dodial(cx);
+       debug(F101,"dodial returns","",x);
+       if ((cx == XXDIAL || cx == XXRED || cx == XXANSW) &&
+           (x > 0) &&                  /* If DIAL or REDIAL succeeded */
+           (dialsta != DIA_PART) &&    /* and it wasn't partial */
+           (dialcon > 0)) {
+           if ((dialcon == 1 ||        /* And DIAL CONNECT is ON, */
+               ((dialcon == 2) &&      /* or DIAL CONNECT is AUTO */
+                !xcmdsrc               /* and we're at top level... */
+#ifdef VMS
+                && !batch              /* Not if running from batch */
+#else
+#ifdef UNIXOROSK
+                && !backgrd            /* Not if running in background */
+#endif /* UNIXOROSK */
+#endif /* VMS */
+                ))) /* Or AUTO */
+             x = doconect(dialcq,      /* Then also CONNECT */
+                           cmdlvl == 0 ? 1 : 0
+                          );
+           if (ttchk() < 0)
+             dologend();
+       }
+       return(success = x);
+    }
+#endif /* NODIAL */
+
+#ifndef NOPUSH
+#ifdef CK_REXX
+    if (cx == XXREXX) {                        /* REXX */
+        extern int nopush;
+        if ( nopush )
+          return(success=0);
+        return(dorexx());
+    }
+#endif /* CK_REXX */
+#endif /* NOPUSH */
+
+#ifndef NOFRILLS
+    if (cx == XXDEL || cx == XXLDEL) { /* DELETE */
+#ifdef LOCUS
+       if (!locus && cx != XXLDEL) {
+#ifdef NOXFER
+           return(-2);
+#else
+           return(dormt(XZDEL));
+#endif /* NOXFER */
+        }
+#endif /* LOCUS */
+#ifdef IKSD
+       if (inserver && (!ENABLED(en_del)
+#ifdef CK_LOGIN
+                        || isguest
+#endif /* CK_LOGIN */
+                        )) {
+           printf("?Sorry, DELETE is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+#ifdef CK_APC
+       if ((apcactive == APC_LOCAL) ||
+           ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
+         return(success = 0);
+#endif /* CK_APC */
+       return(dodel());
+    }
+#endif /* NOFRILLS */
+
+    if (cx == XXDIR || cx == XXLS || cx == XXLDIR) { /* DIRECTORY or LS */
+#ifdef LOCUS
+       if (!locus && cx != XXLDIR) {
+#ifdef NOXFER
+           return(-2);
+#else
+           return(dormt(XZDIR));
+#endif /* NOXFER */
+        }
+#endif /* LOCUS */
+#ifdef IKSD
+       if (inserver && !ENABLED(en_dir)) {
+           printf("?Sorry, DIRECTORY is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+       return(dodir(cx));
+    }
+
+#ifndef NOSPL
+    if (cx == XXELS)                   /* ELSE */
+      return(doelse());
+#endif /* NOSPL */
+
+#ifndef NOSERVER
+#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 = cmkey(kmstab,3,"mode","both",xxstring)) < 0) {
+           if (y == -3) {
+               printf("?Please specify remote, local, or both\n");
+               return(-9);
+           } else return(y);
+       }
+       if (cx == XXDIS)                /* Disabling, not enabling */
+         y = 3 - y;
+       if ((z = cmcfm()) < 0) return(z);
+#ifdef CK_APC
+       if ((apcactive == APC_LOCAL) ||
+           ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
+         return(success = 0);
+#endif /* CK_APC */
+#ifdef IKSD
+        /* This may seem like it duplicates the work in doenable()  */
+        /* but this code returns failure whereas doenable() returns */
+        /* success.                                                 */
+        if (inserver &&
+#ifdef IKSDCONF
+            iksdcf &&
+#endif /* IKSDCONF */
+            (x == EN_HOS || x == EN_PRI || x == EN_MAI || x == EN_WHO ||
+              isguest))
+            return(success = 0);
+#endif /* IKSD */
+       return(doenable(y,x));
+    }
+#endif /* NOFRILLS */
+#endif /* NOSERVER */
+
+#ifndef NOSPL
+    if (cx == XXRET) {                 /* RETURN */
+       if ((x = cmtxt("Optional return value","",&s,NULL)) < 0)
+         return(x);
+       s = brstrip(s);                 /* Strip braces */
+       if (cmdlvl == 0)                /* At top level, nothing happens... */
+         return(success = 1);
+       switch (cmdstk[cmdlvl].src) {   /* Action depends on command source */
+         case CMD_TF:                  /* Command file */
+           popclvl();                  /* Pop command level */
+           return(success = 1);        /* always succeeds */
+         case CMD_MD:                  /* Macro */
+         case CMD_KB:                  /* Prompt */
+           return(doreturn(s));        /* Trailing text is return value. */
+         default:                      /* Shouldn't happen */
+           return(-2);
+       }
+    }
+#endif /* NOSPL */
+
+#ifndef NOSPL
+    if (cx == XXOPE)                   /* OPEN */
+      return(doopen());
+#endif /* NOSPL */
+
+#ifndef NOSPL
+    if (cx == XXOUT || cx == XXLNOUT) {        /* OUTPUT or LINEOUT */
+       if ((x = cmtxt("Text to be output","",&s,NULL)) < 0)
+         return(x);
+#ifdef CK_APC
+       if ((apcactive == APC_LOCAL) ||
+           ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
+         return(success = 0);
+#endif /* CK_APC */
+       debug(F110,"OUTPUT 1",s,0);
+       s = brstrip(s);                 /* Strip enclosing braces, */
+       debug(F110,"OUTPUT 2",s,0);
+/*
+  I don't think I could ever fully explain this in a million years...
+  We have read the user's string without calling the variable-expander
+  function.  Now, before we call it, we have to double backslashes that
+  appear before \N, \B, \L, and \ itself, so the expander function will
+  reduce them back to single backslashes, so when we call dooutput()...
+  But it's more complicated than that.
+*/
+       if (cmdgquo()) {                /* Only if COMMAND QUOTING ON ... */
+           for (x = 0, y = 0; s[x]; x++, y++) {
+               if (s[x] == CMDQ) {
+                   char c = s[x+1];
+                   if (c == 'n' || c == 'N' ||
+                       c == 'b' || c == 'B' ||
+                       c == 'l' || c == 'L' ||
+                       c == 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 - (int) strlen(line) - 1;
+           debug(F101,"OUTPUT size","",x);
+           if (zzstring(line,&s,&x) < 0)
+             return(success = 0);
+           s = line+y+1;
+           debug(F110,"OUTPUT 4",s,0);
+       }
+       success = dooutput(s,cx);
+       return(success);
+    }
+#endif /* NOSPL */
+
+#ifdef ANYX25
+#ifndef IBMX25
+    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(-9);
+       }
+       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 /* IBMX25 */
+#endif /* ANYX25 */
+
+#ifndef NOSPL
+    if (cx == XXPAU || cx == XXWAI || cx == XXMSL) /* PAUSE, WAIT, etc */
+      return(dopaus(cx));
+#endif /* NOSPL */
+
+#ifndef NOFRILLS
+    if (cx == XXPRI) {
+#ifdef IKSD
+#ifdef CK_LOGIN
+       if (inserver && (isguest || !ENABLED(en_pri))) {
+           printf("?Sorry, printing is disabled\n");
+           return(-9);
+       }
+#endif /* CK_LOGIN */
+#endif /* IKSD */
+       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);
+       }
+       ckstrncpy(line,s,LINBUFSIZ);
+       s = "";
+#ifndef NT
+       if ((x = cmtxt("Local print command options, or carriage return","",&s,
+                      xxstring)) < 0)
+         return(x);
+#endif /* NT */
+       if ((x = cmcfm()) < 0)
+         return(x);
+       return(success = (zprint(s,line) == 0) ? 1 : 0);
+    }
+#endif /* NOFRILLS */
+
+#ifdef TCPSOCKET
+#ifndef NOPUSH
+    if (cx == XXPNG)                   /* PING an IP host */
+      return(doping());
+#endif /* NOPUSH */
+
+#ifndef NOFTP
+    if (cx == XXFTP)                   /* FTP */
+#ifdef SYSFTP
+#ifndef NOPUSH
+      return(doftp());                 /* Just runs system's ftp program */
+#else
+      return(-2);
+#endif /* NOPUSH */
+#else
+    return(doxftp());
+#endif /* SYSFTP */
+#endif /* NOFTP */
+#endif /* TCPSOCKET */
+
+    if (cx == XXPWD || cx == XXLPWD) { /* PWD */
+#ifdef OS2
+       char *pwp;
+#endif /* OS2 */
+       if ((x = cmcfm()) < 0)
+         return(x);
+#ifdef LOCUS
+       if (!locus && cx != XXLPWD) {
+#ifdef NOXFER
+           return(-2);
+#else
+           return(dormt(XZPWD));
+#endif /* NOXFER */
+        }
+#endif /* LOCUS */
+
+#ifndef MAC
+#ifndef OS2
+#ifdef UNIX
+       printf("%s\n",zgtdir());
+#else
+       xsystem(PWDCMD);
+#endif /* UNIX */
+       return(success = 1);            /* Blind faith */
+#else  /* OS2 */
+       if (pwp = zgtdir()) {
+           if (*pwp) {
+#ifdef NT
+               line[0] = NUL;
+               ckGetLongPathName(pwp,line,LINBUFSIZ);
+               line[LINBUFSIZ-1] = NUL;
+               tmpbuf[0] = NUL;
+               GetShortPathName(pwp,tmpbuf,TMPBUFSIZ);
+               tmpbuf[TMPBUFSIZ-1] = NUL;
+               pwp = line;
+               if (!strcmp(line,tmpbuf)) {
+#endif /* NT */
+                   printf("%s\n",pwp);
+#ifdef NT
+               } else {
+                   printf("  Long name:  %s\n",line);
+                   printf("  Short name: %s\n",tmpbuf);
+               }            
+#endif /* NT */
+           }
+           return(success = ((int)strlen(pwp) > 0));
+       } else return(success = 0);
+#endif /* OS2 */
+#else  /* MAC */
+       if (pwp = zgtdir()) {
+           printf("%s\n",pwp);
+           return(success = ((int)strlen(pwp) > 0));
+       } else return(success = 0);
+#endif /* MAC */
+    }
+
+    if (cx == XXQUI || cx == XXEXI) {  /* EXIT, QUIT */
+       extern int quitting;
+
+       if ((y = cmnum("exit status code",ckitoa(xitsta),10,&x,xxstring)) < 0)
+         return(y);
+       if ((y = cmtxt("Optional EXIT message","",&s,xxstring)) < 0)
+         return(y);
+       s = brstrip(s);
+       ckstrncpy(line,s,LINBUFSIZ);
+
+       if (!hupok(0))                  /* Check if connection still open */
+         return(success = 0);
+
+       if (line[0])                    /* Print EXIT message if given */
+         printf("%s\n",(char *)line);
+
+       quitting = 1;                   /* Flag that we are quitting. */
+
+#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 NOXFER
+#ifndef NOFRILLS
+    if (cx == XXERR) {                 /* ERROR */
+#ifdef CK_XYZ
+       if (protocol != PROTO_K) {
+           printf("Sorry, E-PACKET only works with Kermit protocol\n");
+           return(-9);
+       }
+#endif /* CK_XYZ */
+       if ((x = cmcfm()) < 0) return(x);
+       ttflui();
+       epktflg = 1;
+       sstate = 'a';
+       return(0);
+    }
+#endif /* NOFRILLS */
+
+    if (cx == XXFIN) {                 /* FINISH */
+#ifdef NEWFTP
+       if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
+         return(ftpbye());
+#endif /* NEWFTP */
+#ifdef CK_XYZ
+       if (protocol != PROTO_K) {
+           printf("Sorry, FINISH only works with Kermit protocol\n");
+           return(-9);
+       }
+#endif /* CK_XYZ */
+       if ((x = cmcfm()) < 0) return(x);
+
+#ifdef IKS_OPTION
+        if (
+#ifdef CK_XYZ
+            protocol == PROTO_K &&
+#endif /* CK_XYZ */
+            !iks_wait(KERMIT_REQ_START,1)) {
+           printf(
+              "?A Kermit Server is not available to process this command\n");
+           return(-9);                 /* Correct the return code */
+        }
+#endif /* IKS_OPTION */
+
+       sstate = setgen('F',"","","");
+       if (local) ttflui();            /* If local, flush tty input buffer */
+       return(0);
+    }
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    if (cx == XXFOR)                   /* FOR loop */
+      return(dofor());
+#endif /* NOSPL */
+
+#ifndef NOXFER
+    /* GET MGET REGET RETRIEVE etc */
+    if (cx == XXGET || cx == XXMGET || cx == XXREGET || cx == XXRETR) {
+#ifdef IKSD
+       if (inserver && !ENABLED(en_sen)) {
+           printf("?Sorry, reception of files is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+       return(doxget(cx));
+    }
+#endif /* NOXFER */
+
+#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,"\nCommand or topic","help",toktab,xxstring,3);
+       debug(F101,"HELP command x","",x);
+       if (x == -5) {
+           y = chktok(toktab);
+           debug(F101,"HELP 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 = XXDEF; break;
+             case ':': x = XXLBL; break;
+#ifndef NOSEXP
+             case '(': x = XXSEXP; break;
+#endif /* NOSEXP */
+#endif /* NOSPL */
+             case '&': x = XXECH; break;
+             default:
+               printf("\n?Invalid - %s\n",cmdbuf);
+               x = -2;
+           }
+       }
+       makestr(&hlptok,atmbuf);
+       debug(F111,"HELP token",hlptok,x);
+       return(dohlp(x));
+#endif /* NOHELP */
+    }
+
+#ifndef NOHELP
+    if (cx == XXINT)                   /* INTRO */
+      return(hmsga(introtxt));
+    if (cx == XXNEW) {                 /* NEWS */
+       int x;
+       extern char * k_info_dir;
+       x = hmsga(newstxt);
+       return(x);
+    }
+
+#ifdef OS2ONLY
+    if (cx == XXUPD) {                 /* View UPDATE file */
+        extern char exedir[];
+        char * pTopic;
+        char updstr[2048];
+        if ((x = cmtxt("topic name","",&pTopic,xxstring)) < 0)
+            return x;
+#ifdef COMMENT
+       sprintf(updstr,
+               "start view %s\\docs\\k2.inf+%s\\docs\\using_ck.inf+\
+%s\\docs\\dialing.inf+%s\\docs\\modems.inf %s",
+               exedir,exedir,exedir,exedir,pTopic
+               );
+#else
+       if (ckmakxmsg(updstr,
+                    2048,
+                    "start view ",
+                    exedir,
+                    "\\docs\\k2.inf+",
+                    exedir,
+                    "\\docs\\using_ck.inf+",
+                    exedir,
+                    "\\docs\\dialing.inf+",
+                    exedir,
+                    "\\docs\\modems.inf ",
+                    pTopic,
+                    NULL,
+                    NULL
+                    ) > 0)
+#endif /* COMMENT */
+         system(updstr);
+        return(success = 1);
+    }
+#endif /* OS2ONLY */
+#endif /* NOHELP */
+
+#ifndef NOLOCAL
+    if (cx == XXHAN) {                 /* HANGUP */
+       if ((x = cmcfm()) < 0) return(x);
+#ifdef NEWFTP
+       if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
+         return(success = ftpbye());
+#endif /* NEWFTP */
+#ifndef NODIAL
+       if ((x = mdmhup()) < 1) {
+           debug(F101,"HANGUP mdmup","",x);
+#endif /* NODIAL */
+           x = tthang();
+           debug(F101,"HANGUP tthang","",x);
+           x = (x > -1);
+#ifndef NODIAL
+       }
+       dialsta = DIA_UNK;
+#endif /* NODIAL */
+       whyclosed = WC_CLOS;
+       ttchk();                        /* In case of CLOSE-ON-DISCONNECT */
+       dologend();
+#ifdef OS2
+       if (x)
+         DialerSend(OPT_KERMIT_HANGUP, 0);
+#endif /* OS2 */
+       if (x) haveline = 0;
+       return(success = x);
+    }
+#endif /* NOLOCAL */
+
+#ifndef NOSPL
+    /* INPUT, REINPUT, and MINPUT */
+
+    if (cx == XXINP || cx == XXREI || cx == XXMINP) {
+       long zz;
+       extern int ispattern, isjoin;
+
+       struct FDB sw, nu, fl;
+       int fc, havetime = 0;
+       char * m;
+
+       if (cx == XXREI) {
+           m = "Timeout in seconds (ignored)";
+       } else {
+           m = "Seconds to wait for input,\n or time of day hh:mm:ss, \
+ or switch";
+       }
+       innomatch = 0;                  /* Initialize switch value(s) */
+
+       cmfdbi(&sw,                     /* First FDB - command switches */
+              _CMKEY,                  /* fcode */
+              m,                       /* helpmsg */
+              ckitoa(indef),           /* default */
+              "",                      /* addtl string data */
+              ninputsw,                /* addtl numeric data 1: tbl size */
+              4,                       /* addtl numeric data 2: 4 = cmswi */
+              xxstring,                /* Processing function */
+              inputsw,                 /* Keyword table */
+              &nu                      /* Pointer to next FDB */
+              );
+       cmfdbi(&nu,
+              _CMNUM,                  /* Number */
+              m,                       /* Help message */
+              ckitoa(indef),           /* default */
+              "",                      /* N/A */
+              10,                      /* Radix = 10 */
+              0,                       /* N/A */
+              xxstring,                /* Processing function */
+              NULL,                    /* N/A */
+              &fl                      /* Next */
+              );
+       cmfdbi(&fl,                     /* Time of day hh:mm:ss */
+              _CMFLD,                  /* fcode */
+              "",                      /* hlpmsg */
+              "",
+              "",                      /* addtl string data */
+              0,                       /* addtl numeric data 1 */
+              0,                       /* addtl numeric data 2 */
+              xxstring,
+              NULL,
+              NULL
+              );
+       fc = (cx == XXREI) ? cmfdb(&nu) : cmfdb(&sw); /* Parse something */
+
+       while (!havetime) {
+           if (fc < 0) {               /* Error */
+               if (fc == -3) {
+                   printf("?Syntax error in INPUT-class command\n");
+                   return(-9);
+               } else
+                 return(fc);
+           }
+           switch (cmresult.fcode) {
+             case _CMKEY:              /* Switch */
+               if (cmresult.nresult == INPSW_NOM) /* /NOMATCH */
+                 innomatch = 1;
+               m = "Seconds to wait for input,\n or time of day hh:mm:ss";
+               cmfdbi(&nu,_CMNUM,m,"","",10,0,xxstring,NULL,&fl);
+               cmfdbi(&fl,_CMFLD,"","","",0,0,xxstring,NULL,NULL);
+               fc = cmfdb(&nu);        /* Parse something */
+               continue;
+
+             case _CMNUM:              /* Seconds to time out */
+               x = cmresult.nresult;
+#ifdef CKFLOAT
+               if (inscale != 1.0)     /* Scale */
+                 x *= inscale;         
+#endif /* CKFLOAT */
+               havetime++;
+               break;
+
+             case _CMFLD:
+               zz = tod2sec(atmbuf);   /* Convert to secs since midnight */
+               if (zz < 0L) {
+                   printf("?Number, expression, or time of day required\n");
+                   return(-9);
+               } else {
+                   char now[32];       /* Current time */
+                   char *p;
+                   long tnow;
+                   p = now;
+                   ztime(&p);
+                   tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
+                   if (zz < tnow)      /* User's time before now */
+                     zz += 86400L;     /* So make it tomorrow */
+                   zz -= tnow;         /* Seconds from now. */
+                   if (zz > -1L) {
+                       x = zz;
+                       if (zz != (long) x) {
+                           printf(
+"Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
+);
+                           return(-9);
+                       }
+                   }
+                   havetime++;
+               }
+               break;
+             default:          
+               printf("?Internal error\n");
+               return(-9);
+           }
+       }
+       /* Now parse the search text */
+
+#ifdef CK_MINPUT
+       for (y = 0; y < MINPMAX; y++) { /* Initialize strings */
+           mp[y] = 0;                  /* Assume it's not a pattern */
+           if (ms[y]) {
+               free(ms[y]);            /* Free old strings, if any */
+               ms[y] = NULL;
+           }
+       }
+       if (cx == XXMINP) {             /* MINPUT */
+           int i, k = 0, n = 0;
+           struct stringarray * q;
+           keepallchars = 1;
+           while (k < MINPMAX) {
+               if ((y = cmfld("String or pattern","",&s,xxstring)) < 0) {
+                   if (y == -3) {
+                       if ((y = cmcfm()) < 0)
+                         return(y);
+                       break;
+                   } else {
+                       return(y);
+                   }
+               }
+               debug(F111,"MINPUT field",s,k);
+               if (isjoin) {
+                   if ((q = cksplit(1,0,s," ",(char *)c1chars,3,0,0))) {
+                       char ** ap = q->a_head;
+                       n = q->a_size;
+                       debug(F101,"minput cksplit size","",n);
+                       for (i = 1; i <= n && k < MINPMAX; i++) {
+                           if (!ap[i]) /* Add non-empty elements */
+                             continue;
+                           if (!*(ap[i]))
+                             continue;
+                           makestr(&(ms[k]),ap[i]);
+                           debug(F111,"MINPUT JOIN",ms[k],k);
+                           k++;
+                       }
+                   }
+               } else {
+                   if (s) if (*s) {
+                       makestr(&(ms[k]),brstrip(s));
+                       if (ispattern) mp[k] = 1;
+                       debug(F111,"MINPUT",ms[k],ispattern);
+                       k++;
+                   }
+               }
+           }
+           keepallchars = 0;
+       } else {
+#endif /* CK_MINPUT */
+
+           /* INPUT or REINPUT */
+
+           if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
+             return(y);
+           mp[0] = ispattern ? 1 : 0;
+           makestr(&(ms[0]),brstrip(s));
+           ms[1] = NULL;
+
+#ifdef CK_MINPUT
+       }
+#endif /* CK_MINPUT */
+
+#ifdef COMMENT
+       printf("/NOMATCH=%d\n",innomatch);
+       printf("Timeout=%d\n",x);
+       return(1);
+#endif /* COMMENT */
+
+       if (cx == XXINP || cx == XXMINP) { /* Not REINPUT... */
+           i_active = 1;
+           /* Go try to input the search string */
+           success = doinput(x,ms,mp,innomatch);
+           i_active = 0;
+       } else {                        /* REINPUT */
+           success = doreinp(x,ms[0],ispattern);
+       }
+       if (intime[cmdlvl] && !success) { /* TIMEOUT-ACTION = QUIT? */
+           popclvl();                  /* If so, pop command level. */
+           if (pflag && cmdlvl == 0) {
+               if (cx == XXINP)  printf("?INPUT timed out\n");
+               if (cx == XXMINP) printf("?MINPUT timed out\n");
+               if (cx == XXREI)  printf("?REINPUT failed\n");
+           }
+       }
+       return(success);                /* Return do(re)input's return code */
+    }
+
+#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);
+    }
+
+    if (cx == XXLOGIN) {               /* (REMOTE) LOGIN */
+#ifdef NEWFTP
+       if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
+         return(success = doftpusr());
+#endif /* NEWFTP */
+#ifdef IKSD
+       if (inserver) {
+           printf("?Already logged in\n");
+           return(-9);
+       } else
+#endif /* IKSD */
+       {
+#ifdef NOXFER
+           return(-2);
+#else
+           return(dormt(XZLGI));
+#endif /* NOXFER */
+       }
+    }
+    if (cx == XXLOGOUT) {              /* (REMOTE) LOGOUT */
+#ifdef NEWFTP
+       if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
+         return(success = doftpres());
+#endif /* NEWFTP */
+
+#ifdef IKSD
+        if (inserver) {
+           if ((x = cmcfm()) < 0)
+             return(x);
+           doexit(GOOD_EXIT,xitsta);
+       } else
+#endif /* IKSD */
+       if (!local || (network && ttchk() < 0)) {
+           printf("?No connection.\n");
+           return(-9);
+       } else {
+#ifdef NOXFER
+           return(-2);
+#else
+           return(dormt(XZLGO));
+#endif /* NOXFER */
+       }
+    }
+
+#ifndef NOSCRIPT
+    if (cx == XXLOGI) {                        /* UUCP-style script */
+       if ((x = cmtxt("expect-send expect-send ...","",&s,xxstring)) < 0)
+         return(x);
+#ifdef CK_APC
+       if ((apcactive == APC_LOCAL) ||
+           ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
+         return(success = 0);
+#endif /* CK_APC */
+#ifdef VMS
+       conres();                       /* For Ctrl-C to work... */
+#endif /* VMS */
+       return(success = dologin(s));   /* Return 1=completed, 0=failed */
+    }
+#endif /* NOSCRIPT */
+
+#ifndef NOXFER
+#ifdef PIPESEND
+    if (cx == XXCREC) {                        /* CRECEIVE */
+       if (protocol != PROTO_K) {
+           printf("?Sorry, CRECEIVE works only with Kermit protocol\n");
+           return(-9);
+       } else
+         return(doxget(cx));
+    }
+    if (cx == XXCGET) {                        /* CGET */
+       return(doxget(cx));
+    }
+#endif /* PIPESEND */
+
+    if (cx == XXREC)                   /* RECEIVE */
+      return(doxget(cx));
+#endif /* NOXFER */
+
+#ifndef NOXFER
+    if (cx == XXREM) {                 /* REMOTE */
+#ifdef NEWFTP
+       if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
+         return(doftprmt(0,0));
+#endif /* NEWFTP */
+#ifdef CK_XYZ
+       if (protocol != PROTO_K) {
+           printf("Sorry, REMOTE commands only work with Kermit protocol\n");
+           return(-9);
+       }
+#endif /* CK_XYZ */
+       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));
+    }
+#endif /* NOXFER */
+
+#ifndef NORENAME
+#ifndef NOFRILLS
+    if (cx == XXREN || cx == XXLREN) { /* RENAME */
+#ifdef LOCUS
+       if (!locus && cx != XXLREN) {
+#ifdef NOXFER
+           return(-2);
+#else
+           return(dormt(XZREN));
+#endif /* NOXFER */
+        }
+#endif /* LOCUS */
+#ifdef IKSD
+       if (inserver && (!ENABLED(en_ren)
+#ifdef CK_LOGIN
+                        || isguest
+#endif /* CK_LOGIN */
+                        )) {
+           printf("?Sorry, renaming of files is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+#ifdef CK_APC
+       if ((apcactive == APC_LOCAL) ||
+           ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
+         return(success = 0);
+#endif /* CK_APC */
+       return(dorenam());
+    }
+#endif /* NOFRILLS */
+#endif /* NORENAME */
+
+    if (cx == XXEIGHT) {               /* EIGHTBIT */
+       extern int parity, cmask, cmdmsk;
+       if ((x = cmcfm()) < 0)
+         return(x);
+       parity = 0;
+       cmask = 0xff;
+       cmdmsk = 0xff;
+       return(success = 1);
+    }
+
+#ifndef NOXFER
+/* SEND, CSEND, MOVE, MAIL, and RESEND use the new common code */
+
+    if (cx == XXSEN                    /* SEND */
+#ifdef PIPESEND
+       || cx == XXCSEN                 /* CSEND */
+#endif /* PIPESEND */
+       || cx == XXMOVE                 /* MOVE */
+       || cx == XXMAI                  /* MAIL */
+#ifdef CK_RESEND
+       || cx == XXRSEN                 /* RESEND */
+#endif /* CK_RESEND */
+       ) {
+#ifdef IKSD
+       if (inserver && !ENABLED(en_get)) {
+           printf("?Sorry, sending files is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+       return(doxsend(cx));
+    }
+
+/* PSEND, ADD, and REMOVE use special parsing */
+
+#ifdef ADDCMD
+    /* ADD and REMOVE */
+    if (cx == XXADD || cx == XXREMV) {
+       char * m;
+       m = (cx == XXADD) ? "Add to which list?" : "Remove from which list?";
+       x = cmkey(addtab,naddtab,m,"",xxstring);
+       if (x < 0)
+         return(x);
+#ifndef NOMSEND
+       if (x == ADD_SND)
+         return(addsend(cx));
+       else
+#endif /* NOMSEND */
+         return(doadd(cx,x));
+    }
+#endif /* ADDCMD */
+
+#ifdef CK_RESEND
+    if (cx == XXPSEN) {                        /* PSEND */
+       int seekto = 0;
+
+       cmarg = cmarg2 = "";
+       x = cmifi("File to partially send", "", &s, &y, xxstring);
+       if (x < 0) {
+           if (x == -3) {
+               printf("?A file specification is required\n");
+               return(-9);
+           } else return(x);
+       }
+       nfils = -1;                     /* Files come from internal list. */
+#ifndef NOMSEND
+        addlist = 0;                   /* Don't use SEND-LIST. */
+        filenext = NULL;
+#endif /* NOMSEND */
+       ckstrncpy(line,s,LINBUFSIZ);    /* Save copy of string just parsed. */
+       debug(F110,"PSEND line",line,0);
+       if (y != 0) {
+           printf("?Sorry, wildcards not permitted in this command\n");
+           return(-9);
+       }
+       if (sizeof(int) < 4) {
+           printf("?Sorry, this command needs 32-bit integers\n");
+           return(-9);
+       }
+       x = cmnum("starting position (byte number)",
+                 "",10,&seekto,xxstring);
+       if (x < 0)
+         return(x);
+       zfnqfp(s,fspeclen,fspec);       /* Get full path */
+       if ((x = cmtxt("Name to send it with","",&s,NULL)) < 0)
+         return(x);
+       ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+
+#ifdef IKSD
+       if (inserver && !ENABLED(en_get)) {
+           printf("?Sorry, sending files is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+#ifdef PIPESEND
+       if (sndfilter) {
+           printf("?Sorry, no PSEND while SEND FILTER selected\n");
+           return(-9);
+       }
+#endif /* PIPESEND */
+#ifdef CK_XYZ
+       if ((protocol == PROTO_X || protocol == PROTO_XC)) {
+           printf("Sorry, PSEND works only with Kermit protocol\n");
+           return(-9);
+       }
+#endif /* CK_XYZ */
+
+       cmarg2 = brstrip(tmpbuf);       /* Strip braces */
+       cmarg = line;                   /* File to send */
+       debug(F110,"PSEND filename",cmarg,0);
+       debug(F110,"PSEND as-name",cmarg2,0);
+       sendstart = seekto;
+       sstate = 's';                   /* Set start state to SEND */
+#ifndef NOMSEND
+       addlist = 0;
+       filenext = NULL;
+#endif /* NOMSEND */
+       sendmode = SM_PSEND;
+#ifdef MAC
+       what = W_SEND;
+       scrcreate();
+#endif /* MAC */
+       if (local) {                    /* If in local mode, */
+           displa = 1;                 /* enable file transfer display */
+       }
+       return(0);
+    }
+#endif /* CK_RESEND */
+#endif /* NOXFER */
+
+#ifndef NOXFER
+#ifndef NOMSEND
+    if (cx == XXMSE || cx == XXMMOVE) {
+#ifdef NEWFTP
+       if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
+         return(doftpput(cx,0));
+#endif /* NEWFTP */
+#ifdef CK_XYZ
+       if (protocol == PROTO_X || protocol == PROTO_XC) {
+           printf(
+"Sorry, you can only send one file at a time with XMODEM protocol\n"
+                  );
+           return(-9);
+       }
+#endif /* CK_XYZ */
+        return(doxsend(cx));
+    }
+
+#ifdef COMMENT                         /* (moved to doxsend) */
+    if (cx == XXMSE || cx == XXMMOVE) {        /* MSEND and MMOVE commands */
+       nfils = 0;                      /* Like getting a list of */
+       lp = line;                      /* files on the command line */
+       addlist = 0;                    /* Do not use SEND-LIST */
+       filenext = NULL;                /* Ditto ! */
+
+       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 */
+             if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
+                 printf("?MSEND list too long\n");
+                 line[0] = NUL;
+                 return(-9);
+             }
+           debug(F111,"msfiles",msfiles[nfils-1],nfils-1);
+           if (nfils == 1) *fspec = NUL; /* Take care of \v(filespec) */
+#ifdef ZFNQFP
+           zfnqfp(p,TMPBUFSIZ,tmpbuf);
+           p = tmpbuf;
+#endif /* ZFNQFP */
+           if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
+               strcat(fspec,p);        /* safe */
+               strcat(fspec," ");      /* safe */
+           } else printf("WARNING - \\v(filespec) buffer overflow\n");
+       }
+       cmlist = msfiles;               /* Point cmlist to pointer array */
+       cmarg2 = "";                    /* No internal expansion list (yet) */
+       sndsrc = nfils;                 /* Filenames come from cmlist */
+       sendmode = SM_MSEND;            /* Remember this kind of SENDing */
+       sstate = 's';                   /* Set start state for SEND */
+       if (cx == XXMMOVE)              /* If MMOVE'ing, */
+         moving = 1;                   /*  set this flag. */
+#ifdef MAC
+       what = W_SEND;
+       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 /* COMMENT */
+#endif /* NOMSEND */
+#endif /* NOXFER */
+
+#ifndef NOSERVER
+    if (cx == XXSER) {                 /* SERVER */
+#ifdef CK_XYZ
+       if (protocol != PROTO_K) {
+           printf("Sorry, SERVER only works with Kermit protocol\n");
+           return(-9);
+       }
+#endif /* CK_XYZ */
+#ifdef COMMENT
+/*
+  Parse for time limit, but since we don't use it yet,
+  the parsing is commented out.
+*/
+       x_ifnum = 1;                    /* Turn off internal complaints */
+       y = cmnum("optional time limit, seconds, or time of day as hh:mm:ss",
+                 "0", 10, &x, xxstring
+                 );
+       x_ifnum = 0;
+       if (y < 0) {
+           if (y == -2) {              /* Invalid number or expression */
+               zz = tod2sec(atmbuf);   /* Convert to secs since midnight */
+               if (zz < 0L) {
+                   printf("?Number, expression, or time of day required\n");
+                   return(-9);
+               } else {
+                   char now[32];       /* Current time */
+                   char *p;
+                   long tnow;
+                   p = now;
+                   ztime(&p);
+                   tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
+                   if (zz < tnow)      /* User's time before now */
+                     zz += 86400L;     /* So make it tomorrow */
+                   zz -= tnow;         /* Seconds from now. */
+               }
+           } else
+             return(y);
+       }
+       if (zz > -1L) {
+           x = zz;
+           if (zz != (long) x) {
+               printf(
+"Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
+                      );
+               return(-9);
+           }
+       }
+       if (x < 0)
+         x = 0;
+#endif /* COMMENT */
+
+       if ((x = cmcfm()) < 0) return(x);
+       sstate = 'x';
+#ifdef MAC
+       what = W_RECV;
+       scrcreate();
+#endif /* MAC */
+       if (local) displa = 1;
+#ifdef AMIGA
+       reqoff();                       /* No DOS requestors while server */
+#endif /* AMIGA */
+       return(0);
+    }
+#endif /* NOSERVER */
+
+    if (cx == XXSAVE) {                        /* SAVE command */
+       x = cmkey(savtab,nsav,"option","keymap",xxstring);
+       if (x == -3) {
+           printf("?You must specify an option to save\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 = dosave(x);
+       if (y == -3) {
+           printf("?More fields required\n");
+           return(-9);
+       } else return(y);
+    }
+
+    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 */
+       || cx == XXEXEC                 /* exec() */
+       ) {
+       int rx = 0;
+       char * p = NULL;
+       int i /* ,n */ ;
+#ifdef UNIXOROSK
+       char * args[256];
+#endif /* UNIXOROSK */
+
+#ifdef IKSD
+       if (inserver && (nopush || !ENABLED(en_hos))) {
+           printf("?Sorry, host command access is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+
+#ifdef CKEXEC
+       if (cx == XXEXEC) {             /* EXEC (overlay ourselves) */
+           struct FDB sw, fl;
+           cmfdbi(&sw,                 /* First FDB - command switches */
+                  _CMKEY,              /* fcode */
+                  "Command to overlay C-Kermit\n or switch", /* hlpmsg */
+                  "",                  /* default */
+                  "",                  /* addtl string data */
+                  1,                   /* addtl numeric data 1: tbl size */
+                  4,                   /* addtl numeric data 2: 4 = cmswi */
+                  xxstring,            /* Processing function */
+                  redirsw,             /* Keyword table */
+                  &fl                  /* Pointer to next FDB */
+                  );
+           cmfdbi(&fl,                 /* 2nd FDB - command to exec */
+                  _CMFLD,              /* fcode */
+                  "Command to overlay C-Kermit", /* hlpmsg */
+                  "",                  /* default */
+                  "",                  /* addtl string data */
+                  0,                   /* addtl numeric data 1 */
+                  0,                   /* addtl numeric data 2 */
+                  xxstring,
+                  NULL,
+                  NULL                 /* No more after this */
+                  );
+           while (1) {
+               x = cmfdb(&sw);         /* Parse something */
+               debug(F101,"exec cmfdb","",x);
+               if (x < 0)
+                 return(x);
+               /* Generalize this if we add more switches */
+               if (cmresult.fcode == _CMKEY) {
+                   rx = 1;
+                   continue;
+               }
+               if (cmresult.fcode == _CMFLD)
+                 break;
+               return(-2);
+           }
+           ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
+           if (!tmpbuf[0]) {
+               printf("?Command required\n");
+               return(-9);
+           }
+           p = brstrip(tmpbuf);
+           args[0] = NULL;             /* Set argv[0] to it */
+           makestr(&args[0],p);
+           for (i = 1; i < 255; i++) { /* Get arguments for command */
+               if ((x = cmfld("Argument","",&s,xxstring)) < 0) {
+                   if (x == -3) {
+                       if ((x = cmcfm()) < 0)
+                         return(x);
+                       break;
+                   } else
+                     return(x);
+               }
+               args[i] = NULL;
+               s = brstrip(s);
+               makestr(&args[i],s);
+           }
+           args[i] = NULL;
+       } else {
+#endif /* CKEXEC */
+           if ((x = cmtxt("System command to execute","",&s,xxstring)) < 0)
+             return(x);
+#ifdef CKEXEC
+       }
+#endif /* CKEXEC */
+        if (nopush)
+          return(success = 0);
+#ifdef CK_APC
+       if (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
+         return(success = 0);
+#endif /* CK_APC */
+       conres();                       /* Make console normal  */
+#ifdef OS2
+       if (!(s && *s)) {
+           os2push();
+            return(success = 1);
+       } else
+#endif /* OS2 */
+         if (cx == XXSHE) {
+             x = zshcmd(s);
+             debug(F101,"RUN zshcmd code","",x);
+             concb((char)escape);
+             return(success = x);
+#ifdef CKEXEC
+         } else {
+#ifdef DEBUG
+             if (deblog) {
+                 debug(F111,"EXEC cmd",p,0);
+                 for (i = 0; i < 256 && args[i]; i++)
+                   debug(F111,"EXEC arg",args[i],i);
+             }
+#endif /* DEBUG */
+             if (p) {
+                 z_exec(p,args,rx);    /* Overlay ourself */
+                 debug(F100,"EXEC fails","",0);
+                 concb((char)escape);  /* In case it returns */
+             }
+             return(success = 0);
+#endif /* CKEXEC */
+         }
+    }
+
+#ifdef CK_REDIR
+    if (cx == XXFUN) {                 /* REDIRECT */
+#ifdef CK_APC
+       if ((apcactive == APC_LOCAL) ||
+           ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
+         return(success = 0);
+#endif /* CK_APC */
+       ckmakmsg(tmpbuf,
+                TMPBUFSIZ,
+                "Local command to run,\n",
+                "with its standard input/output redirected to ",
+                local ? ttname : "the communications connection",
+                "\n"
+                );
+       if ((x = cmtxt(tmpbuf,"",&s,xxstring)) < 0)
+         return(x);
+        if (nopush) {
+            printf("?REDIRECT disabled\n");
+            return(success=0);
+        }
+       if (!local) {
+           printf("?SET LINE or SET HOST required first\n");
+           return(-9);
+       }
+       if (!*s) {
+           printf("?REDIRECT requires a command to redirect\n");
+           return(-9);
+       }
+       return(success = ttruncmd(s));
+    }
+#endif /* CK_REDIR */
+#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 IKSD
+       if (inserver && !ENABLED(en_spa)) {
+           printf("?Sorry, SPACE command disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+#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 (nopush) {
+           printf("?Sorry, SPACE command disabled\n");
+           return(-9);
+       } else if (*s == NUL) {
+           xsystem(SPACMD);
+       } else {
+           ckmakmsg(line,LINBUFSIZ,"space ",s,NULL,NULL);
+           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 */
+            unsigned long space = zdskspace(0);
+            if (space > 0 && space < 1024)
+              printf(" Free space: unknown\n");
+            else
+             printf(" Free space: %ldK\n", space/1024L);
+       } else {
+           int drive = toupper(*s);
+            unsigned long space = zdskspace(drive - 'A' + 1);
+            if (space > 0 && space < 1024)
+              printf(" Drive %c: unknown free\n");
+            else
+              printf(" Drive %c: %ldK free\n", drive,space / 1024L);
+       }
+#else
+#ifdef UNIXOROSK
+       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);
+        ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+        s = tmpbuf;
+       if ((x = cmcfm()) < 0) return(x);
+       if (nopush) {
+           printf("?Sorry, SPACE command disabled\n");
+           return(-9);
+       }
+       if (!*s) {                      /* Current disk */
+           xsystem(SPACMD);
+       } else {                        /* Specified disk */
+           ckmakmsg(line,LINBUFSIZ,SPACM2," ",s,NULL);
+           xsystem(line);
+       }
+#else
+       if ((x = cmcfm()) < 0) return(x);
+       if (nopush) {
+           printf("?Sorry, SPACE command disabled\n");
+           return(-9);
+       }
+       xsystem(SPACMD);
+#endif /* UNIXOROSK */
+#endif /* OS2 */
+#endif /* datageneral */
+       return(success = 1);            /* Pretend it worked */
+    }
+#endif /* MAC */
+
+#ifndef NOXFER
+    if (cx == XXSTA) {                 /* STATISTICS */
+       if ((x = cmkey(stattab,2,"Carriage return, or option",
+                      "/brief",xxstring)) < 0)
+         return(x);
+       if ((y = cmcfm()) < 0) return(y);
+       return(success = dostat(x));
+    }
+#endif /* NOXFER */
+
+    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);
+       s = brstrip(s);
+       if (*s) printf("%s\n",s);
+       if (cx == XXSTO) {
+           dostop();
+       } else {
+           doend(x);
+       }
+       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
+#ifdef IKSD
+       if (inserver) {
+           printf("?Sorry, IKSD can not be suspended\n");
+           return(-9);
+       } else
+#endif /* IKSD */
+         if (nopush) {
+           printf("?Sorry, access to system is disabled\n");
+           return(-9);
+       }
+       stptrap(0);
+#endif /* NOJC */
+       return(0);
+    }
+
+    if (cx == XXTAK) {                 /* TAKE */
+       char * scriptenv = NULL;        
+#ifdef OS2
+        char * GetAppData(int);
+       extern char startupdir[],exedir[],inidir[];
+       char * keymapenv = NULL;
+        char * appdata0 = NULL, *appdata1 = NULL;
+       int xx;
+#define TAKEPATHLEN 4096
+#else /* OS2 */
+#define TAKEPATHLEN 1024
+#endif /* OS2 */
+       char takepath[TAKEPATHLEN];
+
+       if (tlevel >= MAXTAKE-1) {
+           printf("?Take files nested too deeply\n");
+           return(-9);
+       }
+#ifdef OS2
+#ifdef NT
+       scriptenv = getenv("K95SCRIPTS");
+       keymapenv = getenv("K95KEYMAPS");
+        makestr(&appdata0,(char *)GetAppData(0));
+        makestr(&appdata1,(char *)GetAppData(1));
+#else /* NT */
+       scriptenv = getenv("K2SCRIPTS");
+       keymapenv = getenv("K2KEYMAPS");
+#endif /* NT */
+#endif /* OS2 */
+
+       if (!scriptenv)                 /* Let this work for Unix etc too */
+         scriptenv = getenv("CK_SCRIPTS"); /* Use this if defined */
+#ifndef OS2
+       if (!scriptenv)                 /* Otherwise use home directory */
+         scriptenv = homepath();
+#endif /* OS2 */
+       if (!scriptenv)
+         scriptenv = "";
+       ckstrncpy(takepath,scriptenv,TAKEPATHLEN);
+       debug(F110,"TAKE initial takepath",takepath,0);
+
+#ifdef OS2
+       if (!keymapenv)
+         keymapenv = getenv("CK_KEYMAPS");
+       if (!keymapenv)
+         keymapenv = "";
+
+       ckstrncat(takepath,
+                 (scriptenv && scriptenv[strlen(scriptenv)-1]==';')?"":";",
+                 TAKEPATHLEN
+                 );
+       ckstrncat(takepath,keymapenv?keymapenv:"",TAKEPATHLEN);
+       ckstrncat(takepath,
+                 (keymapenv && keymapenv[strlen(keymapenv)-1]==';')?"":";",
+                 TAKEPATHLEN
+                 );
+       ckstrncat(takepath,startupdir,TAKEPATHLEN);
+       ckstrncat(takepath,";",TAKEPATHLEN);
+       ckstrncat(takepath,startupdir,TAKEPATHLEN);
+       ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
+       ckstrncat(takepath,startupdir,TAKEPATHLEN);
+       ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
+
+       ckstrncat(takepath,appdata1,TAKEPATHLEN);
+       ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
+       ckstrncat(takepath,appdata1,TAKEPATHLEN);
+       ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
+       ckstrncat(takepath,appdata1,TAKEPATHLEN);
+       ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
+
+       ckstrncat(takepath,appdata0,TAKEPATHLEN);
+       ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
+       ckstrncat(takepath,appdata0,TAKEPATHLEN);
+       ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
+       ckstrncat(takepath,appdata0,TAKEPATHLEN);
+       ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
+
+       ckstrncat(takepath,inidir,TAKEPATHLEN);
+       ckstrncat(takepath,";",TAKEPATHLEN);
+       ckstrncat(takepath,inidir,TAKEPATHLEN);
+       ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
+       ckstrncat(takepath,inidir,TAKEPATHLEN);
+       ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
+
+       ckstrncat(takepath,zhome(),TAKEPATHLEN);
+       ckstrncat(takepath,";",TAKEPATHLEN);
+       ckstrncat(takepath,zhome(),TAKEPATHLEN);
+       ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
+       ckstrncat(takepath,zhome(),TAKEPATHLEN);
+       ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
+
+       ckstrncat(takepath,exedir,TAKEPATHLEN);
+       ckstrncat(takepath,";",TAKEPATHLEN);
+       ckstrncat(takepath,exedir,TAKEPATHLEN);
+       ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
+       ckstrncat(takepath,exedir,TAKEPATHLEN);
+       ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
+#endif /* OS2 */
+       debug(F110,"TAKE final takepath",takepath,0);
+
+       if ((y = cmifip("Commands from file",
+                       "",&s,&x,0,takepath,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);
+       }
+       ckstrncpy(line,s,LINBUFSIZ);
+       debug(F110,"TAKE file",s,0);
+       if (isdir(s)) {
+           printf("?Can't execute a directory - \"%s\"\n", s);
+           return(-9);
+       }
+#ifndef NOTAKEARGS
+       {
+           char * p;
+           x = strlen(line);
+           debug(F111,"TAKE args",line,x);
+           p = line + x + 1;
+           if ((y = cmtxt("Optional arguments","",&s,xxstring)) < 0)
+             return(y);
+           if (*s) {                   /* Args given? */
+               ckstrncpy(p,s,LINBUFSIZ-x-1);
+#ifdef ZFNQFP
+               zfnqfp(line,TMPBUFSIZ,tmpbuf);
+               s = tmpbuf;
+#else
+               s = line;
+#endif /* ZFNQFP */
+               debug(F110,"TAKE filename",s,0);
+               x = strlen(s);
+               debug(F101,"TAKE new len",s,x);
+
+#ifdef COMMENT
+/*
+  This was added in C-Kermit 7.0 to allow args to be passed from the TAKE
+  command to the command file.  But it overwrites the current argument vector,
+  which is at best surprising, and at worst unsafe.
+*/
+               addmac("%0",s);         /* Define %0 = name of file */
+               varnam[0] = '%';
+               varnam[2] = '\0';
+               debug(F110,"take arg 0",s,0);
+               debug(F110,"take args",p,0);
+               for (y = 1; y < 10; y++) { /* Clear current args %1..%9 */
+                   varnam[1] = (char) (y + '0');
+                   delmac(varnam,0);
+               }
+               xwords(p,MAXARGLIST,NULL,0); /* Assign new args */
+               debug(F110,"take args",p,0);
+#else
+/*
+  This method is used in 8.0.  If the TAKE command includes arguments, we
+  insert an intermediate temporary macro between the current level; we pass
+  the arguments to the macro and then the macro TAKEs the command file.
+  If the user Ctrl-C's out of the TAKE file, some temporary macro definitions
+  and other small malloc'd bits might be left behind.
+*/
+               {
+                   char * q = NULL;
+                   char * r = NULL;
+                   int k, m;
+                   m = maclvl;
+                   q = (char *)malloc(x+24);
+                   if (q) {
+                       r = (char *)malloc(x+24);
+                       if (r) {
+                           sprintf(q,"_file[%s](%d)",s,cmdlvl); /* safe */
+                           sprintf(r,"take %s",s); /* safe */
+                           k = addmac(q,r);
+                           if (k > -1) {
+                               dodo(k,p,0);
+                               while (maclvl > m) {
+                                   sstate = (CHAR) parser(1);
+                                   if (sstate) proto();
+                               }
+                           }
+                           k = delmac(q,0);
+                           free(q);
+                           free(r);
+                           return(success);
+                       }
+                   }
+               }
+               return(success = 0);
+#endif /* COMMENT */
+           }
+       }
+#else
+       if ((y = cmcfm()) < 0) return(y);
+#endif /* NOTAKEARGS */
+       return(success = dotake(line));
+    }
+
+#ifndef NOLOCAL
+#ifdef OS2
+    if (cx == XXVIEW) {                        /* VIEW Only Terminal mode */
+       viewonly = TRUE;
+       success = doconect(0, 0);
+       viewonly = FALSE;
+       return success;
+    }
+#endif /* OS2 */
+
+#ifdef NETCONN
+    if (cx == XXTEL || cx == XXIKSD) { /* TELNET */
+       int x,z;
+#ifdef OS2
+    if (!tcp_avail) {
+        printf("?Sorry, either TCP/IP is not available on this system or\n\
+necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
+        success = 0;
+        return(-9);
+    } else
+#endif /* OS2 */
+      {
+         x = nettype;                  /* Save net type in case of failure */
+         z = ttnproto;                 /* Save protocol in case of failure */
+         nettype = NET_TCPB;
+         ttnproto = (cx == XXTEL) ? NP_TELNET : NP_KERMIT;
+         if ((y = setlin(XYHOST,0,1)) <= 0) {
+              nettype = x;             /* Failed, restore net type. */
+              ttnproto = z;            /* and protocol */
+              success = 0;
+         }
+         didsetlin++;
+        }
+       return(y);
+    }
+
+#ifndef PTYORPIPE
+#ifdef NETCMD
+#define PTYORPIPE
+#else
+#ifdef NETPTY
+#define PTYORPIPE
+#endif /* NETPTY */
+#endif /* NETCMD */
+#endif /* PTYORPIPE */
+
+#ifdef PTYORPIPE
+    if (cx == XXPIPE || cx == XXPTY) { /* PIPE or PTY */
+       int x;
+       extern int netsave;
+       x = nettype;                    /* Save net type in case of failure */
+       nettype = (cx == XXPIPE) ? NET_CMD : NET_PTY;
+       if ((y = setlin(XYHOST,0,1)) < 0) {
+           nettype = x;                /* Failed, restore net type. */
+           ttnproto = z;               /* and protocol */
+           success = 0;
+       }
+       didsetlin++;
+       netsave = x;
+       return(y);
+    }
+#endif /* PTYORPIPE */
+
+#ifdef ANYSSH
+    if (cx == XXSSH) {                 /* SSH (Secure Shell) */
+       extern int netsave;
+#ifdef SSHBUILTIN
+       int k, x, havehost = 0, trips = 0;
+        int    tmpver = -1, tmpxfw = -1;
+#ifndef SSHTEST
+        extern int sl_ssh_xfw, sl_ssh_xfw_saved;
+        extern int sl_ssh_ver, sl_ssh_ver_saved;
+#endif /* SSHTEST */
+        extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
+        extern char * slmsg;
+       extern char uidbuf[], sl_uidbuf[];
+        extern char pwbuf[], * g_pswd;
+        extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
+       struct FDB sw, kw, fl;
+
+        if (ssh_tmpstr)
+         memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
+        makestr(&ssh_tmpstr,NULL);
+        makestr(&ssh_tmpuid,NULL);
+        makestr(&ssh_tmpcmd,NULL);
+        makestr(&ssh_tmpport,NULL);
+
+       cmfdbi(&kw,                     /* 1st FDB - commands */
+              _CMKEY,                  /* fcode */
+              "host [ port ],\n or action",    /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              nsshcmd,                 /* addtl numeric data 1: tbl size */
+              0,                       /* addtl numeric data 2: 0 = keyword */
+              xxstring,                /* Processing function */
+              sshkwtab,                /* Keyword table */
+              &fl                      /* Pointer to next FDB */
+              );
+       cmfdbi(&fl,                     /* Host */
+              _CMFLD,                  /* fcode */
+              "",                      /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              0,                       /* addtl numeric data 1 */
+              0,                       /* addtl numeric data 2 */
+              xxstring,
+              NULL,
+              NULL
+              );
+
+       x = cmfdb(&kw);
+       if (x == -3) {
+           printf("?ssh what?\n");
+           return(-9);
+       }
+       if (x < 0)
+         return(x);
+       havehost = 0;
+       if (cmresult.fcode == _CMFLD) {
+           havehost = 1;
+           ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
+           cmresult.nresult = XSSH_OPN;
+       }
+       switch (cmresult.nresult) {     /* SSH keyword */
+         case XSSH_OPN:                /* SSH OPEN */
+           if (!havehost) {
+               if ((x = cmfld("Host","",&s,xxstring)) < 0)
+                 return(x);
+               ckstrncpy(line,s,LINBUFSIZ);
+           }
+           /* Parse [ port ] [ switches ] */
+           cmfdbi(&kw,                 /* Switches */
+                  _CMKEY,
+                  "Port number or service name,\nor switch",
+                  "",
+                  "",
+                  nsshopnsw,
+                  4,
+                  xxstring,
+                  sshopnsw,
+                  &fl
+                  );
+           cmfdbi(&fl,                 /* Port number or service name */
+                  _CMFLD,
+                  "",
+                  "",
+                  "",
+                  0,
+                  0,
+                  xxstring,
+                  NULL,
+                  NULL
+                  );
+           trips = 0;                  /* Explained below */
+           while (1) {                 /* Parse port and switches */
+               x = cmfdb(&kw);         /* Get a field */
+               if (x == -3)            /* User typed CR so quit from loop */
+                 break;
+               if (x < 0)              /* Other parse error, pass it back */
+                 return(x);
+               switch (cmresult.fcode) { /* Field or Keyword? */
+                  case _CMFLD:           /* Field */
+                    makestr(&ssh_tmpport,cmresult.sresult);
+                   break;
+                 case _CMKEY:          /* Keyword */
+                   switch (cmresult.nresult) { /* Which one? */
+                     case SSHSW_USR:           /* /USER: */
+                       if (!cmgbrk()) {
+                           printf("?This switch requires an argument\n");
+                           return(-9);
+                       }
+                       if ((y = cmfld("Username","",&s,xxstring)) < 0)
+                         return(y);
+                       s = brstrip(s);
+                       makestr(&ssh_tmpuid,s);
+                       break;
+                      case SSHSW_PWD:
+                       if (!cmgbrk()) {
+                           printf("?This switch requires an argument\n");
+                           return(-9);
+                       }
+                       debok = 0;
+                       if ((x = cmfld("Password","",&s,xxstring)) < 0) {
+                           if (x == -3) {
+                               makestr(&ssh_tmpstr,"");
+                           } else {
+                               return(x);
+                           }
+                       } else {
+                           s = brstrip(s);
+                           if ((x = (int)strlen(s)) > PWBUFL) {
+                               makestr(&slmsg,"Internal error");
+                               printf("?Sorry, too long - max = %d\n",PWBUFL);
+                               return(-9);
+                           }
+                           makestr(&ssh_tmpstr,s);
+                       }
+                       break;
+
+                     case SSHSW_VER:
+                       if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
+                         return(x);
+                       if (z < 1 || z > 2) {
+                           printf("?Out of range: %d\n",z);
+                           return(-9);
+                       }
+                        tmpver = z;
+                       break;
+                     case SSHSW_CMD:
+                     case SSHSW_SUB:
+                       if ((x = cmfld("Text","",&s,xxstring)) < 0)
+                         return(x);
+                        makestr(&ssh_tmpcmd,s);
+                       ssh_cas = (cmresult.nresult == SSHSW_SUB);
+                       break;
+                     case SSHSW_X11:
+                       if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
+                         return(x);
+                        tmpxfw = x;
+                       break;
+                     default:
+                       return(-2);
+                   }
+               }
+               if (trips++ == 0) {     /* After first time through */
+                   cmfdbi(&kw,         /* only parse switches, not port. */
+                          _CMKEY,
+                          "Switch",
+                          "",
+                          "",
+                          nsshopnsw,
+                          4,
+                          xxstring,
+                          sshopnsw,
+                          NULL
+                          );
+               }
+           }
+           if ((x = cmcfm()) < 0)      /* Get confirmation */
+             return(x);
+            if (clskconnx(1) < 0) {    /* Close current Kermit connection */
+              if ( ssh_tmpstr ) {
+                  memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
+                  makestr(&ssh_tmpstr,NULL);
+              }
+              return(success = 0);
+            }
+           makestr(&ssh_hst,line);     /* Stash everything */
+           if (ssh_tmpuid) {
+                if (!sl_uid_saved) {
+                    ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
+                    sl_uid_saved = 1;
+                }
+               ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
+               makestr(&ssh_tmpuid,NULL);
+           }
+            if (ssh_tmpport) {
+                makestr(&ssh_prt,ssh_tmpport);
+                makestr(&ssh_tmpport,NULL);
+            } else
+                makestr(&ssh_prt,NULL);
+
+            if (ssh_tmpcmd) {
+                makestr(&ssh_cmd,brstrip(ssh_tmpcmd));
+                makestr(&ssh_tmpcmd,NULL);
+            } else
+                makestr(&ssh_cmd,NULL);
+
+            if (tmpver > -1) {
+#ifndef SSHTEST
+                if (!sl_ssh_ver_saved) {
+                    sl_ssh_ver = ssh_ver;
+                    sl_ssh_ver_saved = 1;
+                }
+#endif /* SSHTEST */
+                ssh_ver = tmpver;
+            }
+            if (tmpxfw > -1) {
+#ifndef SSHTEST
+                if (!sl_ssh_xfw_saved) {
+                    sl_ssh_xfw = ssh_xfw;
+                    sl_ssh_xfw_saved = 1;
+                }
+#endif /* SSHTEST */
+                ssh_xfw = tmpxfw;
+            }
+           if (ssh_tmpstr) {
+               if (ssh_tmpstr[0]) {
+                   ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
+                   pwflg = 1;
+                   pwcrypt = 0;
+               } else
+                 pwflg = 0;
+               makestr(&ssh_tmpstr,NULL);
+           }
+           nettype = NET_SSH;
+           if (mdmsav < 0)
+             mdmsav = mdmtyp;
+           mdmtyp = -nettype;
+           x = 1;
+
+#ifndef NOSPL
+            makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
+            g_pflg = pwflg;                     /* and flag */
+            g_pcpt = pwcrypt;
+#endif /* NOSPL */
+
+           /* Line parameter to ttopen() is ignored */
+           k = ttopen(line,&x,mdmtyp, 0);
+           if (k < 0) {
+               printf("?Unable to connect to %s\n",ssh_hst);
+               mdmtyp = mdmsav;
+                slrestor();
+               return(success = 0);
+           }
+           duplex = 0;             /* Remote echo */
+           ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
+           debug(F110,"ssh ttname",ttname,0);
+           makestr(&slmsg,NULL);       /* No SET LINE error message */
+           cxtype = CXT_SSH;
+#ifndef NODIAL
+           dialsta = DIA_UNK;
+#endif /* NODIAL */
+           success = 1;                /* SET LINE succeeded */
+           network = 1;                /* Network connection (not serial) */
+           local = 1;                  /* Local mode (not remote) */
+           if ((reliable != SET_OFF || !setreliable))
+             reliable = SET_ON;        /* Transport is reliable end to end */
+#ifdef OS2
+            DialerSend(OPT_KERMIT_CONNECT, 0);
+#endif /* OS2 */
+           setflow();                  /* Set appropriate flow control */
+
+           haveline = 1;
+#ifdef CKLOGDIAL
+#ifdef NETCONN
+           dolognet();
+#endif /* NETCONN */
+#endif /* CKLOGDIAL */
+
+#ifndef NOSPL
+           if (local) {
+               if (nmac) {             /* Any macros defined? */
+                   int k;              /* Yes */
+                   k = mlook(mactab,"on_open",nmac); /* Look this up */
+                   if (k >= 0) {                     /* If found, */
+                       if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
+                         parser(1);                  /* and execute it */
+                   }
+               }
+           }
+#endif /* NOSPL */
+#ifdef LOCUS           
+           if (autolocus)
+               setlocus(1,1);
+#endif /* LOCUS */
+
+       /* Command was confirmed so we can pre-pop command level. */
+       /* This is so CONNECT module won't think we're executing a */
+       /* script if CONNECT was the final command in the script. */
+           if (cmdlvl > 0)
+             prepop();
+           success = doconect(0,cmdlvl == 0 ? 1 : 0);
+           if (ttchk() < 0)
+             dologend();
+           return(success);
+
+         case XSSH_CLR:
+           if ((y = cmkey(sshclr,nsshclr,"","", xxstring)) < 0) {
+               if (y == -3) {
+                   printf("?clear what?\n");
+                   return(-9);
+               }
+               return(y);
+           }
+           if ((x = cmcfm()) < 0)
+             return(x);
+           switch (y) {
+             case SSHC_LPF:
+                ssh_pf_lcl_n = 0;
+               break;
+             case SSHC_RPF:
+               ssh_pf_rmt_n = 0;
+               break;
+             default:
+               return(-2);
+           }
+            return(success = 1);       /* or whatever */
+
+         case XSSH_AGT: {              /* SSH AGENT */
+             int doeach = 0;
+             if ((y = cmkey(sshagent,nsshagent,"","",xxstring)) < 0)
+               return(y);
+             switch (y) {
+               case SSHA_ADD:          /* SSH AGENT ADD ... */
+                 if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
+#ifndef SSHTEST
+                     if (x == -3)      /* No name given */
+                       doeach = 1;     /* so do them all */
+                     else
+#endif /* SSHTEST */
+                       return(x);
+                 }
+                 ckstrncpy(line,s,LINBUFSIZ);
+                 if ((x = cmcfm()) < 0)
+                   return(x);
+#ifdef SSHTEST
+                 x = 0;
+#else
+                 if (doeach) {
+                      int i;
+                      x = 0;
+                      for (i = 0; i < ssh_idf_n; i++)
+                       x += ssh_agent_add_file(ssh_idf[i]);
+                 } else
+                   x = ssh_agent_add_file(line);
+#endif /* SSHTEST */
+                 return(success = (x == 0));
+
+               case SSHA_DEL: {        /* SSH AGENT DELETE ... */
+                   int doall = 0;
+                   if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
+#ifndef SSHTEST
+                       if (x == -3)    /* No name given */
+                         doall = 1;    /* so do them all */
+                       else
+#endif /* SSHTEST */
+                         return(x);
+                   }
+                   ckstrncpy(line,s,LINBUFSIZ);
+                   if ((x = cmcfm()) < 0)
+                     return(x);
+#ifdef SSHTEST
+                   x = 0;
+#else
+                   if (doall)
+                     x = ssh_agent_delete_all();
+                   else
+                     x = ssh_agent_delete_file(line);
+#endif /* SSHTEST */
+                   return(success = (x == 0));
+               }
+               case SSHA_LST: {
+                   int fingerprint = 0;
+                   if ((y = cmswi(sshagtsw,nsshagtsw,"","",xxstring)) < 0) {
+                       if (y != -3)
+                         return(y);
+                   } else if (cmgbrk() > SP) {
+                       printf("?This switch does not take an argument\n");
+                       return(-9);
+                   } else if (y == SSHASW_FP) {
+                       fingerprint = 1;
+                   }
+                   if ((x = cmcfm()) < 0)
+                     return(x);
+#ifdef SSHTEST
+                   return(success = 1);
+#else
+                   return(success =
+                          (ssh_agent_list_identities(fingerprint) == 0));
+#endif /* SSHTEST */
+               }
+               default:
+                 return(-2);
+             }
+         }
+         case XSSH_ADD: {              /* SSH ADD */
+             /* ssh add { local, remote } port host port */
+             int cx, i, j, k;
+             char * h;
+             if ((cx = cmkey(addfwd,naddfwd,"","", xxstring)) < 0)
+               return(cx);
+             if ((x = cmnum((cx == SSHF_LCL) ?
+                            "Local port number" : "Remote port number",
+                            "",10,&j,xxstring)) < 0)
+               return(x);
+             if ((x = cmfld("Host","",&s,xxstring)) < 0)
+               return(x);
+             makestr(&h,s);
+             if ((x = cmnum("Port","",10,&k,xxstring)) < 0)
+               return(x);
+             if ((x = cmcfm()) < 0)
+               return(x);
+
+             switch(cx) {
+               case SSHF_LCL:
+                  if (ssh_pf_lcl_n == 32) {
+                      printf(
+"?Maximum number of local port forwardings already specified\n"
+                            );
+                      free(h);
+                      return(success = 0);
+                 }
+                 ssh_pf_lcl[ssh_pf_lcl_n].p1 = j;
+                 makestr(&(ssh_pf_lcl[ssh_pf_lcl_n].host),h);
+                 makestr(&h,NULL);
+                 ssh_pf_lcl[ssh_pf_lcl_n].p2 = k;
+                 ssh_pf_lcl_n++;
+                 break;
+               case SSHF_RMT:
+                 if (ssh_pf_rmt_n == 32) {
+                     printf(
+"?Maximum number of remote port forwardings already specified\n"
+                           );
+                     free(h);
+                     return(success = 0);
+                 }
+                 ssh_pf_rmt[ssh_pf_rmt_n].p1 = j;
+                 makestr(&(ssh_pf_rmt[ssh_pf_rmt_n].host),h);
+                 makestr(&h,NULL);
+                 ssh_pf_rmt[ssh_pf_rmt_n].p2 = k;
+                 ssh_pf_rmt_n++;
+             }
+             return(success = 1);
+         }
+         /* Not supporting arbitrary forwarding yet */
+         case XSSH_FLP:                /* SSH FORWARD-LOCAL-PORT */
+         case XSSH_FRP: {              /* SSH FORWARD-REMOTE-PORT */
+             int li_port = 0;
+             int to_port = 0;
+             char * fw_host = NULL;
+             int n;
+              if ((x = cmnum(cmresult.nresult == XSSH_FLP ?
+                              "local-port":"remote-port",
+                              "",10,&li_port,xxstring)) < 0)
+                  return(x);
+              if (li_port < 1 || li_port > 65535) {
+                  printf("?Out range - min: 1, max: 65535\n");
+                  return(-9);
+              }
+             if ((x = cmfld("host",ssh_hst?ssh_hst:"",&s,xxstring)) < 0)
+               return(x);
+              n = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+              fw_host = tmpbuf;
+              if ((x = cmnum("host-port",ckuitoa(li_port),10,
+                              &to_port,xxstring)) < 0)
+                  return(x);
+              if (to_port < 1 || to_port > 65535) {
+                  printf("?Out range - min: 1, max: 65535\n");
+                  return(-9);
+              }
+             if ((x = cmcfm()) < 0)
+               return(x);
+             switch (cmresult.nresult) {
+                case XSSH_FLP: /* SSH FORWARD-LOCAL-PORT */
+#ifndef SSHTEST
+                  ssh_fwd_local_port(li_port,fw_host,to_port);
+#endif /* SSHTEST */
+                 return(success = 1);
+               case XSSH_FRP:  /* SSH FORWARD-REMOTE-PORT */
+#ifndef SSHTEST
+                  ssh_fwd_remote_port(li_port,fw_host,to_port);
+#endif /* SSHTEST */
+                 return(success = 1);
+             }
+             return(success = 1);
+         }
+       case XSSH_V2:           /* SSH V2 */
+         if ((cx = cmkey(ssh2tab,nssh2tab,"","", xxstring)) < 0)
+           return(cx);
+         switch (cx) {
+           case XSSH2_RKE:
+             if ((x = cmcfm()) < 0)
+               return(x);
+#ifndef SSHTEST
+             ssh_v2_rekey();
+#endif /* SSHTEST */
+             return(success = 1);
+           default:
+             return(-2);
+         }
+       case XSSH_KEY:
+         if ((cx = cmkey(sshkey,nsshkey,"","", xxstring)) < 0)
+           return(cx);
+         switch (cx) {
+           case SSHK_PASS: {   /* Change passphrase */
+             char * oldp = NULL, * newp = NULL;
+             struct FDB df, sw;
+             cmfdbi(&sw,
+                    _CMKEY,            /* fcode */
+                    "Filename, or switch", /* hlpmsg */
+                    "",                /* default */
+                    "",                /* addtl string data */
+                    2,                 /* addtl numeric data 1: tbl size */
+                    4,                 /* addtl numeric data 2: 4 = cmswi */
+                    xxstring,          /* Processing function */
+                    sshkpsw,           /* Keyword table */
+                    &df                /* Pointer to next FDB */
+                    );
+             cmfdbi(&df,               /* 2nd FDB - file for display */
+                    _CMIFI,            /* output file */
+                    "",                /* hlpmsg */
+                    "",                /* default */
+                    "",                /* addtl string data */
+                    0,                 /* addtl numeric data 1 */
+                    0,                 /* addtl numeric data 2 */
+                    xxstring,
+                    NULL,
+                    NULL
+                    );
+             line[0] = NUL;
+
+             while (1) {
+                 x = cmfdb(&sw);
+                 if (x == -3) break;
+                 if (x < 0)
+                   return(x);
+                 if (cmresult.fcode != _CMKEY)
+                   break;
+                 if (!cmgbrk()) {
+                     printf("?This switch requires an argument\n");
+                     return(-9);
+                 }
+                 if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
+                   return(y);
+                 switch (cmresult.nresult) {
+                   case 1:             /* Old */
+                     makestr(&oldp,s);
+                     break;
+                   case 2:             /* New */
+                     makestr(&newp,s);
+                 }
+             }
+             if (cmresult.fcode == _CMIFI) { /* Filename */
+                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
+                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
+                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
+             }
+             if ((x = cmcfm()) < 0) return(x);
+
+#ifndef SSHTEST
+             x = sshkey_change_passphrase(line[0] ? line : NULL,
+                                            oldp, newp);
+#endif /* SSHTEST */
+             makestr(&oldp,NULL);
+             makestr(&newp,NULL);
+             success = (x == 0);
+             return(success);
+           }
+           case SSHK_CREA: {   /* SSH KEY CREATE /switches... */
+             int bits = 1024, keytype = SSHKT_2R;
+             char * pass = NULL, * comment = NULL;
+             struct FDB df, sw;
+
+              /*
+               * char * sshkey_default_file(int keytype) 
+               * will provide the default filename for a given keytype
+               * is it possible to have the default value for the 2nd
+               * FDB set and changed when a /TYPE switch is provided?
+               * Would this allow for tab completion of the filename?
+               */
+             cmfdbi(&sw,
+                    _CMKEY,            /* fcode */
+                    "Filename, or switch", /* hlpmsg */
+                    "",                /* default */
+                    "",                /* addtl string data */
+                    nsshkcrea,         /* addtl numeric data 1: tbl size */
+                    4,                 /* addtl numeric data 2: 4 = cmswi */
+                    xxstring,          /* Processing function */
+                    sshkcrea,          /* Keyword table */
+                    &df                /* Pointer to next FDB */
+                    );
+             cmfdbi(&df,               /* 2nd FDB - file for display */
+                    _CMOFI,            /* output file */
+                    "",                /* hlpmsg */
+                    "",                /* default */
+                    "",                /* addtl string data */
+                    0,                 /* addtl numeric data 1 */
+                    0,                 /* addtl numeric data 2 */
+                    xxstring,
+                    NULL,
+                    NULL
+                    );
+             line[0] = NUL;
+
+             while (1) {
+                 x = cmfdb(&sw);
+                 if (x == -3) break;
+                 if (x < 0)
+                   return(x);
+                 if (cmresult.fcode != _CMKEY)
+                   break;
+                 if (!cmgbrk()) {
+                     printf("?This switch requires an argument\n");
+                     return(-9);
+                 }
+                 switch (cmresult.nresult) {
+                   case SSHKC_BI:      /* /BITS:n */
+                     if ((y = cmnum("","1024",10,&z,xxstring)) < 0)
+                       return(y);
+                     if (z < 512 || z > 4096) {
+                         printf("?Out range - min: 512, max: 4096\n");
+                         return(-9);
+                     }
+                     bits = z;
+                     break;
+                   case SSHKC_PP:      /* /PASSPHRASE:blah */
+                     if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
+                       return(y);
+                     makestr(&pass,s);
+                     break;
+                   case SSHKC_TY:      /* /TYPE:keyword */
+                     if ((y = cmkey(sshkcty,nsshkcty,"",
+                                    "v2-rsa",xxstring)) < 0)
+                       return(y);
+                     keytype = y;
+                     break;
+                   case SSHKC_1R:      /* /COMMENT */
+                     if ((y = cmfld("Text","",&s,xxstring)) < 0)
+                       return(y);
+                     makestr(&comment,s);
+                     break;
+                 }
+             }
+             if (cmresult.fcode == _CMOFI) { /* Filename */
+                  if (cmresult.sresult) {
+                      ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
+                      if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
+                          ckstrncpy(line,tmpbuf,LINBUFSIZ);
+                 }
+             }
+             if ((y = cmcfm()) < 0) /* Confirm */
+               return(y);
+#ifndef SSHTEST
+             x = sshkey_create(line[0] ? line : NULL,
+                               bits, pass, keytype, comment);
+             if (pass)
+               memset(pass,0,strlen(pass));
+#endif /* SSHTEST */
+             makestr(&pass,NULL);
+             makestr(&comment,NULL);
+             return(success = (x == 0));
+           }
+           case SSHK_DISP: {   /* SSH KEY DISPLAY /switches... */
+             char c;
+             int infmt = 0, outfmt = 0;
+             struct FDB df, sw;
+             cmfdbi(&sw,
+                    _CMKEY,            /* fcode */
+                    "Filename, or switch", /* hlpmsg */
+                    "",                /* default */
+                    "",                /* addtl string data */
+                    nsshdswi,          /* addtl numeric data 1: tbl size */
+                    4,                 /* addtl numeric data 2: 4 = cmswi */
+                    xxstring,          /* Processing function */
+                    sshdswi,           /* Keyword table */
+                    &df                /* Pointer to next FDB */
+                    );
+             cmfdbi(&df,               /* 2nd FDB - file for display */
+                    _CMIFI,            /* fcode */
+                    "",                /* hlpmsg */
+                    "",                /* default */
+                    "",                /* addtl string data */
+                    0,                 /* addtl numeric data 1 */
+                    0,                 /* addtl numeric data 2 */
+                    xxstring,
+                    NULL,
+                    NULL
+                    );
+             line[0] = NUL;
+
+             while (1) {
+                 x = cmfdb(&sw);
+                 if (x == -3) break;
+                 if (x < 0)
+                   return(x);
+                 if (cmresult.fcode != _CMKEY)
+                   break;
+                 if (!cmgbrk()) {
+                     printf("?This switch requires an argument\n");
+                     return(-9);
+                 }
+                 switch (cmresult.nresult) {
+#ifdef COMMENT
+                   case SSHKD_IN:      /* /IN-FORMAT: */
+                     if ((y = cmkey(sshdifmt,nsshdifmt,
+                                    "","",xxstring)) < 0)
+                       return(y);
+                     infmt = y;
+                     break;
+#endif /* COMMENT */
+                   case SSHKD_OUT:     /* /FORMAT: */
+                     if ((y = cmkey(sshdofmt,nsshdofmt,
+                                    "","",xxstring)) < 0)
+                       return(y);
+                     outfmt = y;
+                     break;
+                 }
+             }
+             if (cmresult.fcode == _CMIFI) { /* Filename */
+                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
+                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
+                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
+             }
+#ifdef COMMENT
+             if (!line[0]) {
+                 printf("?Key filename required\n");
+                 return(-9);
+             }
+#endif /* COMMENT */
+             if ((y = cmcfm()) < 0) /* Confirm */
+               return(y);
+#ifndef SSHTEST
+             switch (outfmt) {
+               case SKDF_OSSH:
+                  /* 2nd param is optional passphrase */
+                 x = sshkey_display_public(line[0] ? line : NULL, NULL);
+                 break;
+               case SKDF_SSHC:
+                  /* 2nd param is optional passphrase */
+                 x = sshkey_display_public_as_ssh2(line[0] ? line : NULL,
+                                                   NULL);
+                 break;
+               case SKDF_IETF:
+                 x = sshkey_display_fingerprint(line[0] ? line : NULL, 1);
+                 break;
+               case SKDF_FING:
+                 x = sshkey_display_fingerprint(line[0] ? line : NULL, 0);
+                 break;
+             }
+#endif /* SSHTEST */
+             return(success = (x == 0));
+           }
+           case SSHK_V1:               /* SSH KEY V1 SET-COMMENT */
+             if ((x = cmkey(sshkv1,1,"","set-comment", xxstring)) < 0)
+               return(x);
+             if (x != 1) return(-2);
+             if ((x = cmifi("Key file name","",&s,&y,xxstring)) < 0) {
+                 if (x == -3) {
+                     printf("?Name of key file required\n");
+                     return(-9);
+                 }
+             }
+             ckstrncpy(line,s,LINBUFSIZ);
+             if ((x = cmtxt("Comment text","",&s,xxstring)) < 0)
+               return(x);
+#ifndef SSHTEST
+             x = sshkey_v1_change_comment(line,  /* filename */
+                                          s,     /* new comment */
+                                          NULL   /* passphrase */
+                                          );
+#endif /* SSHTEST */
+             success = (x == 0);
+             return(success);
+         }
+         default:
+           return(-2);
+       }
+#else  /* SSHBUILTIN */
+#ifdef SSHCMD
+       x = nettype;
+       if ((y = setlin(XXSSH,0,1)) < 0) {
+           if (errno)
+             printf("?%s\n",ck_errstr());
+            else
+#ifdef COMMENT
+           /* This isn't right either because it catches command editing */
+             printf("?Sorry, pseudoterminal open failed\n");
+            if (hints)
+             printf("Hint: Try \"ssh -t %s\"\n",line);
+#else
+             return(y);
+#endif /* COMMENT */
+           nettype = x;                /* Failed, restore net type. */
+           ttnproto = z;               /* and protocol */
+           success = 0;
+       }
+       didsetlin++;
+       netsave = x;
+       return(y);
+#endif /* SSHCMD */
+#endif /* SSHBUILTIN */
+    }
+#endif /* ANYSSH */
+
+#ifdef SSHBUILTIN
+    if (cx == XXSKRM) {                        /* SKERMIT (Secure Shell Kermit) */
+       extern int netsave;
+       int k, x, havehost = 0, trips = 0;
+        int    tmpver = -1, tmpxfw = -1;
+#ifndef SSHTEST
+        extern int sl_ssh_xfw, sl_ssh_xfw_saved;
+        extern int sl_ssh_ver, sl_ssh_ver_saved;
+#endif /* SSHTEST */
+        extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
+        extern char * slmsg;
+       extern char uidbuf[], sl_uidbuf[];
+        extern char pwbuf[], * g_pswd;
+        extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
+       struct FDB sw, kw, fl;
+
+        if (ssh_tmpstr)
+         memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
+        makestr(&ssh_tmpstr,NULL);
+        makestr(&ssh_tmpuid,NULL);
+        makestr(&ssh_tmpcmd,NULL);
+        makestr(&ssh_tmpport,NULL);
+
+       cmfdbi(&kw,                     /* 1st FDB - commands */
+              _CMKEY,                  /* fcode */
+              "host [ port ],\n or action", /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              nsshkermit,              /* addtl numeric data 1: tbl size */
+              0,                       /* addtl numeric data 2: 0 = keyword */
+              xxstring,                /* Processing function */
+              sshkermit,               /* Keyword table */
+              &fl                      /* Pointer to next FDB */
+              );
+       cmfdbi(&fl,                     /* Host */
+              _CMFLD,                  /* fcode */
+              "",                      /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              0,                       /* addtl numeric data 1 */
+              0,                       /* addtl numeric data 2 */
+              xxstring,
+              NULL,
+              NULL
+              );
+
+       x = cmfdb(&kw);
+       if (x == -3) {
+           printf("?skermit what?\n");
+           return(-9);
+       }
+       if (x < 0)
+         return(x);
+       havehost = 0;
+       if (cmresult.fcode == _CMFLD) {
+           havehost = 1;
+           ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
+           cmresult.nresult = SKRM_OPN;
+       }
+       switch (cmresult.nresult) {     /* SSH keyword */
+         case SKRM_OPN:                /* SSH OPEN */
+           if (!havehost) {
+               if ((x = cmfld("Host","",&s,xxstring)) < 0)
+                 return(x);
+               ckstrncpy(line,s,LINBUFSIZ);
+           }
+           /* Parse [ port ] [ switches ] */
+           cmfdbi(&kw,                 /* Switches */
+                  _CMKEY,
+                  "Port number or service name,\nor switch",
+                  "",
+                  "",
+                  nsshkrmopnsw,
+                  4,
+                  xxstring,
+                  sshkrmopnsw,
+                  &fl
+                  );
+           cmfdbi(&fl,                 /* Port number or service name */
+                  _CMFLD,
+                  "",
+                  "",
+                  "",
+                  0,
+                  0,
+                  xxstring,
+                  NULL,
+                  NULL
+                  );
+           trips = 0;                  /* Explained below */
+           while (1) {                 /* Parse port and switches */
+               x = cmfdb(&kw);         /* Get a field */
+               if (x == -3)            /* User typed CR so quit from loop */
+                 break;
+               if (x < 0)              /* Other parse error, pass it back */
+                 return(x);
+               switch (cmresult.fcode) { /* Field or Keyword? */
+                  case _CMFLD:           /* Field */
+                    makestr(&ssh_tmpport,cmresult.sresult);
+                   break;
+                 case _CMKEY:          /* Keyword */
+                   switch (cmresult.nresult) { /* Which one? */
+                     case SSHSW_USR:           /* /USER: */
+                       if (!cmgbrk()) {
+                           printf("?This switch requires an argument\n");
+                           return(-9);
+                       }
+                       if ((y = cmfld("Username","",&s,xxstring)) < 0)
+                         return(y);
+                       s = brstrip(s);
+                       makestr(&ssh_tmpuid,s);
+                       break;
+                      case SSHSW_PWD:
+                       if (!cmgbrk()) {
+                           printf("?This switch requires an argument\n");
+                           return(-9);
+                       }
+                       debok = 0;
+                       if ((x = cmfld("Password","",&s,xxstring)) < 0) {
+                           if (x == -3) {
+                               makestr(&ssh_tmpstr,"");
+                           } else {
+                               return(x);
+                           }
+                       } else {
+                           s = brstrip(s);
+                           if ((x = (int)strlen(s)) > PWBUFL) {
+                               makestr(&slmsg,"Internal error");
+                               printf("?Sorry, too long - max = %d\n",PWBUFL);
+                               return(-9);
+                           }
+                           makestr(&ssh_tmpstr,s);
+                       }
+                       break;
+
+                    case SSHSW_VER:
+                       if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
+                         return(x);
+                       if (z < 1 || z > 2) {
+                           printf("?Out of range: %d\n",z);
+                           return(-9);
+                       }
+                        tmpver = z;
+                       break;
+                    default:
+                        return(-2);
+                   }
+                  }
+               if (trips++ == 0) {     /* After first time through */
+                   cmfdbi(&kw,         /* only parse switches, not port. */
+                          _CMKEY,
+                          "Switch",
+                          "",
+                          "",
+                          nsshkrmopnsw,
+                          4,
+                          xxstring,
+                          sshkrmopnsw,
+                          NULL
+                          );
+               }
+           }
+           if ((x = cmcfm()) < 0)      /* Get confirmation */
+             return(x);
+              if (clskconnx(1) < 0) {  /* Close current Kermit connection */
+                  if ( ssh_tmpstr ) {
+                      memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
+                      makestr(&ssh_tmpstr,NULL);
+                  }
+                  return(success = 0);
+              }
+              makestr(&ssh_hst,line);  /* Stash everything */
+              if (ssh_tmpuid) {
+                  if (!sl_uid_saved) {
+                      ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
+                      sl_uid_saved = 1;
+                  }
+                  ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
+                  makestr(&ssh_tmpuid,NULL);
+              }
+              if (ssh_tmpport) {
+                  makestr(&ssh_prt,ssh_tmpport);
+                  makestr(&ssh_tmpport,NULL);
+              } else
+                  makestr(&ssh_prt,NULL);
+
+              /* Set the Subsystem to Kermit */
+              ssh_cas = 1;
+              makestr(&ssh_cmd,"kermit");
+
+              if (tmpver > -1) {
+#ifndef SSHTEST
+                  if (!sl_ssh_ver_saved) {
+                      sl_ssh_ver = ssh_ver;
+                      sl_ssh_ver_saved = 1;
+                  }
+#endif /* SSHTEST */
+                  ssh_ver = tmpver;
+              }
+              /* Disable X11 Forwarding */
+#ifndef SSHTEST
+              if (!sl_ssh_xfw_saved) {
+                  sl_ssh_xfw = ssh_xfw;
+                  sl_ssh_xfw_saved = 1;
+              }
+#endif /* SSHTEST */
+              ssh_xfw = 0;
+
+              if (ssh_tmpstr) {
+                  if (ssh_tmpstr[0]) {
+                      ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
+                      pwflg = 1;
+                      pwcrypt = 0;
+                  } else
+                      pwflg = 0;
+                  makestr(&ssh_tmpstr,NULL);
+              }
+              nettype = NET_SSH;
+              if (mdmsav < 0)
+                  mdmsav = mdmtyp;
+              mdmtyp = -nettype;
+              x = 1;
+
+#ifndef NOSPL
+            makestr(&g_pswd,pwbuf);    /* Save global pwbuf */
+            g_pflg = pwflg;            /* and flag */
+            g_pcpt = pwcrypt;
+#endif /* NOSPL */
+
+           /* Line parameter to ttopen() is ignored */
+           k = ttopen(line,&x,mdmtyp, 0);
+           if (k < 0) {
+               printf("?Unable to connect to %s\n",ssh_hst);
+               mdmtyp = mdmsav;
+                slrestor();
+               return(success = 0);
+           }
+           duplex = 0;             /* Remote echo */
+           ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
+           debug(F110,"ssh ttname",ttname,0);
+           makestr(&slmsg,NULL);       /* No SET LINE error message */
+           cxtype = CXT_SSH;
+#ifndef NODIAL
+           dialsta = DIA_UNK;
+#endif /* NODIAL */
+           success = 1;                /* SET LINE succeeded */
+           network = 1;                /* Network connection (not serial) */
+           local = 1;                  /* Local mode (not remote) */
+           if ((reliable != SET_OFF || !setreliable))
+             reliable = SET_ON;        /* Transport is reliable end to end */
+#ifdef OS2
+            DialerSend(OPT_KERMIT_CONNECT, 0);
+#endif /* OS2 */
+           setflow();                  /* Set appropriate flow control */
+
+           haveline = 1;
+#ifdef CKLOGDIAL
+#ifdef NETCONN
+           dolognet();
+#endif /* NETCONN */
+#endif /* CKLOGDIAL */
+
+#ifndef NOSPL
+           if (local) {
+               if (nmac) {             /* Any macros defined? */
+                   int k;              /* Yes */
+                   k = mlook(mactab,"on_open",nmac); /* Look this up */
+                   if (k >= 0) {                     /* If found, */
+                       if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
+                         parser(1);                  /* and execute it */
+                   }
+               }
+           }
+#endif /* NOSPL */
+#ifdef LOCUS           
+           if (autolocus)
+               setlocus(1,1);
+#endif /* LOCUS */
+
+       /* Command was confirmed so we can pre-pop command level. */
+       /* This is so CONNECT module won't think we're executing a */
+       /* script if CONNECT was the final command in the script. */
+           if (cmdlvl > 0)
+             prepop();
+           return(success = 1);
+
+         default:
+           return(-2);
+       }
+    }
+#endif /* SSHBUILTIN */
+
+#ifdef SFTP_BUILTIN
+    if (cx == XXSFTP) {                        /* SFTP (Secure Shell File Transfer) */
+       extern int netsave;
+       int k, x, havehost = 0, trips = 0;
+        int    tmpver = -1, tmpxfw = -1;
+#ifndef SSHTEST
+        extern int sl_ssh_xfw, sl_ssh_xfw_saved;
+        extern int sl_ssh_ver, sl_ssh_ver_saved;
+#endif /* SSHTEST */
+        extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
+        extern char * slmsg;
+       extern char uidbuf[], sl_uidbuf[];
+        extern char pwbuf[], * g_pswd;
+        extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
+       struct FDB sw, kw, fl;
+
+        if (ssh_tmpstr)
+         memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
+        makestr(&ssh_tmpstr,NULL);
+        makestr(&ssh_tmpuid,NULL);
+        makestr(&ssh_tmpcmd,NULL);
+        makestr(&ssh_tmpport,NULL);
+
+       cmfdbi(&kw,                     /* 1st FDB - commands */
+              _CMKEY,                  /* fcode */
+              "host [ port ],\n or action", /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              nsftpkwtab,              /* addtl numeric data 1: tbl size */
+              0,                       /* addtl numeric data 2: 0 = keyword */
+              xxstring,                /* Processing function */
+              sftpkwtab,               /* Keyword table */
+              &fl                      /* Pointer to next FDB */
+              );
+       cmfdbi(&fl,                     /* Host */
+              _CMFLD,                  /* fcode */
+              "",                      /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              0,                       /* addtl numeric data 1 */
+              0,                       /* addtl numeric data 2 */
+              xxstring,
+              NULL,
+              NULL
+              );
+
+       x = cmfdb(&kw);
+       if (x == -3) {
+           printf("?sftp what?\n");
+           return(-9);
+       }
+       if (x < 0)
+         return(x);
+       havehost = 0;
+       if (cmresult.fcode == _CMFLD) {
+           havehost = 1;
+           ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
+           cmresult.nresult = SFTP_OPN;
+       }
+       switch (cmresult.nresult) {     /* SFTP keyword */
+         case SFTP_OPN:                /* SFTP OPEN */
+           if (!havehost) {
+               if ((x = cmfld("Host","",&s,xxstring)) < 0)
+                 return(x);
+               ckstrncpy(line,s,LINBUFSIZ);
+           }
+           /* Parse [ port ] [ switches ] */
+           cmfdbi(&kw,                 /* Switches */
+                  _CMKEY,
+                  "Port number or service name,\nor switch",
+                  "",
+                  "",
+                  nsshkrmopnsw,
+                  4,
+                  xxstring,
+                  sshkrmopnsw,
+                  &fl
+                  );
+           cmfdbi(&fl,                 /* Port number or service name */
+                  _CMFLD,
+                  "",
+                  "",
+                  "",
+                  0,
+                  0,
+                  xxstring,
+                  NULL,
+                  NULL
+                  );
+           trips = 0;                  /* Explained below */
+           while (1) {                 /* Parse port and switches */
+               x = cmfdb(&kw);         /* Get a field */
+               if (x == -3)            /* User typed CR so quit from loop */
+                 break;
+               if (x < 0)              /* Other parse error, pass it back */
+                 return(x);
+               switch (cmresult.fcode) { /* Field or Keyword? */
+                  case _CMFLD:           /* Field */
+                    makestr(&ssh_tmpport,cmresult.sresult);
+                   break;
+                 case _CMKEY:          /* Keyword */
+                   switch (cmresult.nresult) { /* Which one? */
+                     case SSHSW_USR:           /* /USER: */
+                       if (!cmgbrk()) {
+                           printf("?This switch requires an argument\n");
+                           return(-9);
+                       }
+                       if ((y = cmfld("Username","",&s,xxstring)) < 0)
+                         return(y);
+                       s = brstrip(s);
+                       makestr(&ssh_tmpuid,s);
+                       break;
+                      case SSHSW_PWD:
+                       if (!cmgbrk()) {
+                           printf("?This switch requires an argument\n");
+                           return(-9);
+                       }
+                       debok = 0;
+                       if ((x = cmfld("Password","",&s,xxstring)) < 0) {
+                           if (x == -3) {
+                               makestr(&ssh_tmpstr,"");
+                           } else {
+                               return(x);
+                           }
+                       } else {
+                           s = brstrip(s);
+                           if ((x = (int)strlen(s)) > PWBUFL) {
+                               makestr(&slmsg,"Internal error");
+                               printf("?Sorry, too long - max = %d\n",PWBUFL);
+                               return(-9);
+                           }
+                           makestr(&ssh_tmpstr,s);
+                       }
+                       break;
+
+                    case SSHSW_VER:
+                       if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
+                         return(x);
+                       if (z < 1 || z > 2) {
+                           printf("?Out of range: %d\n",z);
+                           return(-9);
+                       }
+                        tmpver = z;
+                       break;
+                    default:
+                        return(-2);
+                   }
+               }
+               if (trips++ == 0) {     /* After first time through */
+                   cmfdbi(&kw,         /* only parse switches, not port. */
+                          _CMKEY,
+                          "Switch",
+                          "",
+                          "",
+                          nsshkrmopnsw,
+                          4,
+                          xxstring,
+                          sshkrmopnsw,
+                          NULL
+                          );
+               }
+           }
+           if ((x = cmcfm()) < 0)      /* Get confirmation */
+             return(x);
+              if (clskconnx(1) < 0) {  /* Close current Kermit connection */
+                  if ( ssh_tmpstr ) {
+                      memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
+                      makestr(&ssh_tmpstr,NULL);
+                  }
+                  return(success = 0);
+              }
+              makestr(&ssh_hst,line);  /* Stash everything */
+              if (ssh_tmpuid) {
+                  if (!sl_uid_saved) {
+                      ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
+                      sl_uid_saved = 1;
+                  }
+                  ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
+                  makestr(&ssh_tmpuid,NULL);
+              }
+              if (ssh_tmpport) {
+                  makestr(&ssh_prt,ssh_tmpport);
+                  makestr(&ssh_tmpport,NULL);
+              } else
+                  makestr(&ssh_prt,NULL);
+
+              /* Set the Subsystem to Kermit */
+              ssh_cas = 1;
+              makestr(&ssh_cmd,"sftp");
+
+              if (tmpver > -1) {
+#ifndef SSHTEST
+                  if (!sl_ssh_ver_saved) {
+                      sl_ssh_ver = ssh_ver;
+                      sl_ssh_ver_saved = 1;
+                  }
+#endif /* SSHTEST */
+                  ssh_ver = tmpver;
+              }
+              /* Disable X11 Forwarding */
+#ifndef SSHTEST
+              if (!sl_ssh_xfw_saved) {
+                  sl_ssh_xfw = ssh_xfw;
+                  sl_ssh_xfw_saved = 1;
+              }
+#endif /* SSHTEST */
+              ssh_xfw = 0;
+
+              if (ssh_tmpstr) {
+                  if (ssh_tmpstr[0]) {
+                      ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
+                      pwflg = 1;
+                      pwcrypt = 0;
+                  } else
+                      pwflg = 0;
+                  makestr(&ssh_tmpstr,NULL);
+              }
+              nettype = NET_SSH;
+              if (mdmsav < 0)
+                  mdmsav = mdmtyp;
+              mdmtyp = -nettype;
+              x = 1;
+
+#ifndef NOSPL
+            makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
+            g_pflg = pwflg;                     /* and flag */
+            g_pcpt = pwcrypt;
+#endif /* NOSPL */
+
+           /* Line parameter to ttopen() is ignored */
+           k = ttopen(line,&x,mdmtyp, 0);
+           if (k < 0) {
+               printf("?Unable to connect to %s\n",ssh_hst);
+               mdmtyp = mdmsav;
+                slrestor();
+               return(success = 0);
+           }
+           duplex = 0;             /* Remote echo */
+           ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
+           debug(F110,"ssh ttname",ttname,0);
+           makestr(&slmsg,NULL);       /* No SET LINE error message */
+           cxtype = CXT_SSH;
+#ifndef NODIAL
+           dialsta = DIA_UNK;
+#endif /* NODIAL */
+           success = 1;                /* SET LINE succeeded */
+           network = 1;                /* Network connection (not serial) */
+           local = 1;                  /* Local mode (not remote) */
+           if ((reliable != SET_OFF || !setreliable))
+             reliable = SET_ON;        /* Transport is reliable end to end */
+#ifdef OS2
+            DialerSend(OPT_KERMIT_CONNECT, 0);
+#endif /* OS2 */
+           setflow();                  /* Set appropriate flow control */
+
+           haveline = 1;
+#ifdef CKLOGDIAL
+#ifdef NETCONN
+           dolognet();
+#endif /* NETCONN */
+#endif /* CKLOGDIAL */
+
+#ifndef NOSPL
+           if (local) {
+               if (nmac) {             /* Any macros defined? */
+                   int k;              /* Yes */
+                   k = mlook(mactab,"on_open",nmac); /* Look this up */
+                   if (k >= 0) {                     /* If found, */
+                       if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
+                         parser(1);                  /* and execute it */
+                   }
+               }
+           }
+#endif /* NOSPL */
+#ifdef LOCUS           
+           if (autolocus)
+               setlocus(1,1);
+#endif /* LOCUS */
+
+       /* Command was confirmed so we can pre-pop command level. */
+       /* This is so CONNECT module won't think we're executing a */
+       /* script if CONNECT was the final command in the script. */
+           if (cmdlvl > 0)
+             prepop();
+
+            success = sftp_do_init();
+           return(success = 1);
+
+         case SFTP_CD:
+         case SFTP_CHGRP:
+         case SFTP_CHMOD:
+         case SFTP_CHOWN:
+         case SFTP_RM:
+         case SFTP_DIR:
+         case SFTP_GET:
+         case SFTP_MKDIR:
+         case SFTP_PUT:
+         case SFTP_PWD:
+         case SFTP_REN:
+         case SFTP_RMDIR:
+         case SFTP_LINK:
+         case SFTP_VER:
+           if ((y = cmtxt("command parameters","",&s,xxstring)) < 0) 
+             return(y);
+           if (ssh_tchk() < 0 || !ssh_cas || strcmp(ssh_cmd,"sftp")) {
+               printf("?Not connected to SFTP Service\n");
+               return(success = 0);
+           }
+           success = sftp_do_cmd(cmresult.nresult,s);
+           return(success);
+         default:
+           return(-2);
+       }
+    }
+#endif /* SFTP_BUILTIN */
+
+    if (cx == XXRLOG) {                        /* RLOGIN */
+#ifdef RLOGCODE
+       int x,z;
+#ifdef OS2
+       if (!tcp_avail) {
+           printf("?Sorry, either TCP/IP is not available on this system or\n\
+necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
+                  );
+           success = 0;
+           return(-9);
+       } else {
+#endif /* OS2 */
+           x = nettype;                /* Save net type in case of failure */
+           z = ttnproto;               /* Save protocol in case of failure */
+           nettype = NET_TCPB;
+           ttnproto = NP_RLOGIN;
+           if ((y = setlin(XYHOST,0,1)) <= 0) {
+               nettype = x;            /* Failed, restore net type. */
+               ttnproto = z;           /* and protocol */
+               success = 0;
+           }
+           didsetlin++;
+#ifdef OS2
+       }
+#endif /* OS2 */
+       return(y);
+#else
+       printf("?Sorry, RLOGIN is not configured in this copy of C-Kermit.\n");
+       return(-9);
+#endif /* RLOGCODE */
+    }
+#endif /* NETCONN */
+#endif /* NOLOCAL */
+
+#ifndef NOXMIT
+    if (cx == XXTRA) {                 /* TRANSMIT */
+       extern int xfrxla;
+       int i, n, xpipe = 0, xbinary = 0, xxlate = 1, xxnowait = 0, getval;
+       int xxecho = 0;
+       int scan = 1;
+       char c;
+       struct FDB sf, sw, tx;          /* FDBs for parse functions */
+#ifndef NOCSETS
+       extern int tcs_transp;          /* Term charset is transparent */
+#else
+       int tcs_transp = 1;
+#endif /* NOCSETS */
+
+#ifdef COMMENT
+       xbinary = binary;               /* Default text/binary mode */
+#else
+       xbinary = 0;                    /* Default is text */
+#endif /* COMMENT */
+       xxecho = xmitx;
+
+       cmfdbi(&sw,                     /* First FDB - command switches */
+              _CMKEY,                  /* fcode */
+              "Filename, or switch",   /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              nxmitsw,                 /* addtl numeric data 1: tbl size */
+              4,                       /* addtl numeric data 2: 4 = cmswi */
+              xxstring,                /* Processing function */
+              xmitsw,                  /* Keyword table */
+              &sf                      /* Pointer to next FDB */
+              );
+       cmfdbi(&sf,                     /* 2nd FDB - file to send */
+              _CMIFI,                  /* fcode */
+              "File to transmit",      /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              0,                       /* addtl numeric data 1 */
+              0,                       /* addtl numeric data 2 */
+              xxstring,
+              NULL,
+#ifdef PIPESEND
+              &tx
+#else
+              NULL
+#endif /* PIPESEND */
+              );
+#ifdef PIPESEND
+        cmfdbi(&tx,
+              _CMTXT,                  /* fcode */
+              "Command",               /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              0,                       /* addtl numeric data 1 */
+              0,                       /* addtl numeric data 2 */
+              xxstring,
+              NULL,
+              NULL
+              );
+#endif /* PIPESEND */
+
+       while (1) {
+           x = cmfdb(&sw);
+           if (x < 0)
+             return(x);
+           if (cmresult.fcode != _CMKEY)
+             break;
+           c = cmgbrk();               /* Have switch, get break character */
+           if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
+               printf("?This switch does not take an argument\n");
+               return(-9);
+           }
+           if (!getval && (cmgkwflgs() & CM_ARG)) {
+               printf("?This switch requires an argument\n");
+               return(-9);
+           }
+           n = cmresult.nresult;       /* Numeric result = switch ID */
+           switch (n) {                /* Process the switch */
+#ifdef PIPESEND
+             case XMI_CMD:             /* Transmit from a command */
+               if (nopush) {
+                   printf("?Sorry, system command access is disabled\n");
+                   return(-9);
+               }
+               sw.hlpmsg = "Command, or switch"; /* Change help message */
+               xpipe = 1;              /* (No way to undo this one) */
+               break;
+#endif /* PIPESEND */
+
+             case XMI_BIN:             /* Binary */
+               xbinary = 1;
+               xxlate = 0;             /* Don't translate charsets */
+               scan = 0;
+               break;
+
+             case XMI_TXT:             /* Text */
+               xbinary = 0;
+               xxlate = !tcs_transp;   /* Translate if TERM CHAR not TRANSP */
+               scan = 0;
+               break;
+
+             case XMI_TRA:             /* Transparent text */
+               xbinary = 0;
+               xxlate = 0;             /* But don't translate charsets */
+               scan = 0;
+               break;
+
+#ifdef COMMENT
+             case XMI_VRB:             /* /VERBOSE */
+             case XMI_QUI:             /* /QUIET */
+               break;                  /* (not implemented yet) */
+#endif /* COMMENT */
+
+             case XMI_NOW:             /* /NOWAIT */
+               xxnowait = 1;
+               break;
+
+             case XMI_NOE:             /* /NOWAIT */
+               xxecho = 0;
+               break;
+
+             default:
+               return(-2);
+           }
+
+       }
+       if (cmresult.fcode != _CMIFI && cmresult.fcode != _CMTXT)
+         return(-2);
+       ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Filename */
+       if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
+         ckstrncpy(line,tmpbuf,LINBUFSIZ);
+       s = line;
+       if ((y = cmcfm()) < 0)          /* Confirm */
+         return(y);
+#ifdef CK_APC
+       if ((apcactive == APC_LOCAL) ||
+           ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
+         return(success = 0);
+#endif /* CK_APC */
+       if (cmresult.nresult != 0) {
+           printf("?Only a single file may be transmitted\n");
+           return(-9);
+       }
+#ifdef PIPESEND
+       if (xpipe) {
+           s = brstrip(s);
+           if (!*s) {
+               printf("?Sorry, a command to send from is required\n");
+               return(-9);
+           }
+           pipesend = 1;
+       }
+#endif /* PIPESEND */
+
+       if (scan && (filepeek
+#ifndef NOXFER
+                    || patterns
+#endif /* NOXFER */
+                    )) {               /* If user didn't specify type */
+           int k, x;                         /* scan the file to see */
+           x = -1;
+           k = scanfile(s,&x,nscanfile);
+           if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
+       }
+       if (!xfrxla) xxlate = 0;
+       success = transmit(s,
+                          (char) (xxnowait ? '\0' : (char)xmitp),
+                          xxlate,
+                          xbinary,
+                          xxecho
+                          );
+       return(success);
+    }
+#endif /* NOXMIT */
+
+#ifndef NOFRILLS
+    if (cx == XXTYP  || cx == XXCAT || cx == XXMORE ||
+       cx == XXHEAD || cx == XXTAIL) {
+       int paging = 0, havename = 0, head = 0, width = 0;
+       int height = 0, count = 0;
+       char pfxbuf[64], * prefix = NULL;
+       char outfile[CKMAXPATH+1];
+       struct FDB sf, sw;
+       char * pat = NULL;
+       int incs = 0, outcs = 0, cset = -1, number = 0;
+#ifdef UNICODE
+        char * tocs = "";
+       extern int fileorder;
+#ifdef OS2
+#ifdef NT
+       char guibuf[128], * gui_title = NULL;
+       int  gui = 0;
+#endif /* NT */
+#ifndef NOCSETS
+       extern int tcsr, tcsl;
+#endif /* NOCSETS */
+#endif /* OS2 */
+#endif /* UNICODE */
+
+       outfile[0] = NUL;
+
+       if (cx == XXMORE)
+         paging = 1;
+       else if (cx == XXCAT)
+         paging = 0;
+       else
+         paging = (typ_page < 0) ? xaskmore : typ_page;
+       if (paging < 0)
+         paging = saveask;
+
+       if (cx == XXHEAD) {
+           head = 10;
+           cx = XXTYP;
+       } else if (cx == XXTAIL) {
+           head = -10;
+           cx = XXTYP;
+       }
+
+#ifdef IKSD
+       if (inserver && !ENABLED(en_typ)) {
+           printf("?Sorry, TYPE command disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+
+       cmfdbi(&sw,                     /* 2nd FDB - optional /PAGE switch */
+              _CMKEY,                  /* fcode */
+              "Filename or switch",    /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              ntypetab,                /* addtl numeric data 1: tbl size */
+              4,                       /* addtl numeric data 2: 4 = cmswi */
+              xxstring,                /* Processing function */
+              typetab,                 /* Keyword table */
+              &sf                      /* Pointer to next FDB */
+              );
+       cmfdbi(&sf,                     /* 1st FDB - file to type */
+              _CMIFI,                  /* fcode */
+              "",                      /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              0,                       /* addtl numeric data 1 */
+              0,                       /* addtl numeric data 2 */
+              xxstring,
+              NULL,
+              NULL
+              );
+
+       while (!havename) {
+           x = cmfdb(&sw);             /* Parse something */
+           debug(F101,"type cmfdb","",x);
+           debug(F101,"type cmresult.fcode","",cmresult.fcode);
+           debug(F101,"type cmresult.nresult","",cmresult.nresult);
+           if (x < 0) {                        /* Error */
+               if (x == -3) {
+                   x = -9;
+                   printf("?Filename required\n");
+               }
+               return(x);
+           } else if (cmresult.fcode == _CMKEY) {
+               char c; int getval;
+               c = cmgbrk();
+               getval = (c == ':' || c == '=');
+               if (getval && !(cmgkwflgs() & CM_ARG)) {
+                   printf("?This switch does not take an argument\n");
+                   return(-9);
+               }
+#ifdef COMMENT
+               if (!getval && (cmgkwflgs() & CM_ARG)) {
+                   printf("?This switch requires an argument\n");
+                   /* Not if it has a default! */
+                   return(-9);
+               }
+#endif /* COMMENT */
+               switch (cmresult.nresult) {
+#ifdef CK_TTGWSIZ
+                 case TYP_PAG:
+                   paging = 1;
+                   break;
+
+                 case TYP_NOP:
+                   paging = 0;
+                   break;
+#endif /* CK_TTGWSIZ */
+
+                 case TYP_COU:
+                   paging = 0;
+                   count = 1;
+                   break;
+
+                 case TYP_HEA:
+                 case TYP_TAI:
+                   y = 10;
+                   if (getval)
+                     if ((x = cmnum("Number of lines",
+                                    "10",10,&y,xxstring)) < 0)
+                       return(x);
+                   head = (cmresult.nresult == TYP_TAI) ? -y : y;
+                   break;
+
+                 case TYP_WID:
+                   y = typ_wid > -1 ? typ_wid : cmd_cols;
+                   if (getval)
+                     if ((x = cmnum("Column at which to truncate",
+                                    ckitoa(y),10,&y,xxstring)) < 0)
+                       return(x);
+                   width = y;
+                   break;
+
+#ifdef KUI
+                 case TYP_HIG:
+                   if (getval)
+                     if ((x = cmnum("Height of GUI dialog",
+                                    ckitoa(y),10,&y,xxstring)) < 0)
+                       return(x);
+                   height = y;
+                   break;
+#endif /* KUI */
+
+                 case TYP_PAT:
+                   if (!getval && (cmgkwflgs() & CM_ARG)) {
+                       printf("?This switch requires an argument\n");
+                       return(-9);
+                   }
+                   if ((x = cmfld("pattern","",&s,xxstring)) < 0)
+                     return(x);
+                   ckstrncpy(tmpbuf,s,TMPBUFSIZ);
+                   pat = tmpbuf;
+                   break;
+
+                 case TYP_PFX:
+                   if (!getval && (cmgkwflgs() & CM_ARG)) {
+                       printf("?This switch requires an argument\n");
+                       return(-9);
+                   }
+                   if ((x = cmfld("prefix for each line","",&s,xxstring)) < 0)
+                     return(x);
+                   if ((int)strlen(s) > 63) {
+                       printf("?Too long - 63 max\n");
+                       return(-9);
+                   }
+                   ckstrncpy(pfxbuf,s,64);
+                   prefix = brstrip(pfxbuf);
+                   number = 0;
+                   break;
+
+#ifdef KUI
+                 case TYP_GUI:
+                   if (!getval && (cmgkwflgs() & CM_ARG)) {
+                       printf("?This switch requires an argument\n");
+                       return(-9);
+                   }
+                   if ((x = cmfld("Dialog box title","",&s,xxstring)) < 0) {
+                       if (x != -3)
+                         return(x);
+                   } else {
+                       if ((int)strlen(s) > 127) {
+                           printf("?Too long - 127 max\n");
+                           return(-9);
+                       }
+                       ckstrncpy(guibuf,s,128);
+                       gui_title = brstrip(guibuf);
+                   }
+                   gui = 1;
+                   break;
+#endif /* KUI */
+
+                 case TYP_NUM:         /* /NUMBER */
+                   number = 1;
+                   prefix = NULL;
+                   break;
+
+#ifdef UNICODE
+                 case TYP_XPA:         /* /TRANSPARENT */
+                   incs = 0;
+                   cset = 0;
+                   outcs = -1;
+                   break;
+
+                 case TYP_XIN:         /* /CHARACTER-SET: */
+                   if (!getval && (cmgkwflgs() & CM_ARG)) {
+                       printf("?This switch requires an argument\n");
+                       return(-9);
+                   }
+                   if ((incs = cmkey(fcstab,nfilc,
+                                     "character-set name","",xxstring)) < 0) {
+                       if (incs == -3) /* Note: No default */
+                         incs = -2;
+                       return(incs);
+                   }
+                   cset = incs;
+                   break;
+
+                 case TYP_XUT:         /* /TRANSLATE-TO: */
+                   if (!getval && (cmgkwflgs() & CM_ARG)) {
+                       printf("?This switch requires an argument\n");
+                       return(-9);
+                   }
+#ifdef OS2
+                   if (!inserver && !k95stdout) {
+                       tocs = "ucs2";
+                   } else {
+#ifdef CKOUNI
+                       tocs = rlookup(txrtab,ntxrtab,tcsl);
+#else /* CKOUNI */
+                       extern struct keytab ttcstab[];
+                       extern int ntxrtab;
+                       tocs = rlookup(ttcstab,ntermc,tocs);
+                       if (!tocs)
+                         tocs = getdcset();
+#endif /* CKOUNI */
+                    }
+#else /* OS2 */
+                   tocs = getdcset();
+#endif /* OS2 */
+                   if ((outcs = cmkey(fcstab,nfilc,
+                                      "character-set",tocs,xxstring)) < 0)
+                     return(outcs);
+                   break;
+#endif /* UNICODE */
+                 case TYP_OUT:
+                   if ((x = cmofi("File for result lines","",
+                                  &s,xxstring)) < 0)
+                     return(x);
+                   ckstrncpy(outfile,s,CKMAXPATH);
+                   break;
+               }
+           } else if (cmresult.fcode == _CMIFI)
+             havename = 1;
+           else
+             return(-2);
+       }
+       if (havename) {
+           ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
+           y = cmresult.nresult;
+       } else {
+           if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
+               if (x == -3) {
+                   printf("?Name of an existing file required\n");
+                   return(-9);
+               } else return(x);
+           }
+           ckstrncpy(line,s,LINBUFSIZ);
+       }
+       if (y != 0) {
+           printf("?A single file please\n");
+           return(-9);
+       }
+#ifdef KUI
+       if ( outfile[0] && gui ) {
+           printf("?/GUI and /OUTPUT are incompatible\n");
+           return(-9);
+       }
+#endif /* KUI */
+
+       if ((y = cmcfm()) < 0)          /* Confirm the command */
+         return(y);
+
+#ifdef UNICODE
+       fileorder = -1;
+       if (cset < 0 && filepeek) {     /* If no charset switches given */
+           int k, x = -1;
+           k = scanfile(line,&x,nscanfile); /* Call file analyzer */
+           debug(F111,"type scanfile",line,k);
+           debug(F101,"type scanfile flag","",x);
+           switch(k) {
+             case FT_UTF8:             /* which can detect UTF-8... */
+               cset = 0;
+               incs = FC_UTF8;
+               break;
+             case FT_UCS2:             /* and UCS-2... */
+               cset = 0;
+               incs = FC_UCS2;
+               fileorder = x;          /* even if there is no BOM. */
+               debug(F101,"type fileorder","",fileorder);
+               break;
+           }
+       }
+#ifdef OS2
+        if (cset < 0) {                        /* If input charset still not known */
+#ifdef CKOUNI
+            tocs = rlookup(txrtab,ntxrtab,tcsl);
+#else /* CKOUNI */
+            extern struct keytab ttcstab[];
+            extern int ntxrtab;
+            tocs = rlookup(ttcstab,ntermc,incs);
+            if (!tocs)
+             tocs = getdcset();
+#endif /* CKOUNI */
+            incs = lookup(fcstab,tocs,nfilc,&x);
+        }
+#endif /* OS2 */
+
+        if (outcs == 0 && incs != 0) { /* Supply default target charset */
+           int x = 0;                  /* if switch not given. */
+           tocs = getdcset();
+           outcs = lookup(fcstab,tocs,nfilc,&x);
+       }
+#else  /* !UNICODE */
+       if (cset < 0) incs = outcs = 0;
+#endif /* UNICODE */
+
+       if (outfile[0] && paging)       /* This combination makes no sense */
+         paging = 0;                   /* so turn off paging */
+
+#ifdef KUI
+       /* No paging when dialog is used */
+       if ( gui && paging )
+         paging = 0;
+
+       if ( !gui && height ) {
+           printf("?The /HEIGHT switch is not supported without /GUI\n");
+           return(-9);
+       }
+#endif /* KUI */
+
+       if (count) paging = -1;
+       debug(F111,"type",line,paging);
+#ifdef KUI
+       if ( gui ) {
+           s = (char *)1;    /* ok, its an ugly hack */
+           if (gui_text_popup_create(gui_title ?
+                                     gui_title : line, height,width) < 0) {
+               printf("?/GUI not supported on this system\n");
+               gui = 0;
+               return(-9);
+           }
+           width = 0;
+       } else
+#endif /* KUI */
+         s = outfile;
+       success =
+         dotype(line,paging,0,head,pat,width,prefix,incs,outcs,s,number);
+       return(success);
+    }
+#endif /* NOFRILLS */
+
+#ifndef NOCSETS
+    if (cx == XXXLA) {                 /* TRANSLATE file's charset */
+       _PROTOTYP (int doxlate, ( void ) );
+       return(doxlate());
+    }
+#endif /* NOCSETS */
+
+    if (cx == XXVER) {                 /* VERSION */
+       int n = 0;
+       extern char * ck_patch, * ck_s_test;
+#ifdef COMMENT
+       extern int hmtopline;
+#endif /* COMMENT */
+       if ((y = cmcfm()) < 0)
+          return(y);
+
+       printf("\n%s, for%s\n Numeric: %ld",versio,ckxsys,vernum);
+       printf("\n\n");
+        printf("Authors:\n");
+       printf(" Frank da Cruz, Columbia University\n");
+        printf(" Jeffrey Eric Altman, Secure Endpoints, Inc. %s\n",
+              "<jaltman@secure-endpoints.com>"
+              );
+       printf(" Contributions from many others.\n");
+       n = 7;
+       if (*ck_s_test) {
+           printf("\nTHIS IS A TEST VERSION, NOT FOR PRODUCTION USE.\n");
+           n += 2;
+       }
+       if (*ck_patch) {
+           printf(" Patches: %s\n", ck_patch);
+           n++;
+       }
+       printf(" Type COPYRIGHT for copyright and license.\n\n");
+#ifdef OS2
+       shoreg();
+#else
+#ifdef COMMENT
+       hmtopline = n+1;
+       hmsga(copyright);
+       hmtopline = 0;
+#endif /* COMMENT */
+#endif /* OS2 */
+       return(success = 1);
+    }
+
+    if (cx == XXCPR) {                 /* COPYRIGHT or LICENSE */
+       if ((y = cmcfm()) < 0)
+          return(y);
+#ifdef OS2
+       if (inserver) {                 /* Free WIKSD */
+           extern char * wiksdcpr[];
+           hmsga(wiksdcpr);
+       } else
+#endif /* OS2 */
+         hmsga(copyright);
+       return(success = 1);
+    }
+
+#ifndef MAC                            /* Only for multiuser systems */
+#ifndef OS2
+#ifndef NOFRILLS
+    if (cx == XXWHO) {                 /* WHO */
+       char *wc;
+#ifdef IKSD
+       if (inserver && !ENABLED(en_who)) {
+           printf("?Sorry, WHO command disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+#ifdef datageneral
+       if ((z = cmcfm()) < 0) return(z);
+       if (nopush) {
+           printf("?Sorry, who not allowed\n");
+           return(success = 0);
+       }
+        xsystem(WHOCMD);
+#else
+       if ((y = cmtxt("user name","",&s,xxstring)) < 0) return(y);
+        if (nopush) {
+           printf("?Sorry, WHO command disabled\n");
+           return(success = 0);
+       }
+       if (!(wc = getenv("CK_WHO"))) wc = WHOCMD;
+       if (wc)
+         if ((int) strlen(wc) > 0) {
+             ckmakmsg(line,LINBUFSIZ,wc," ",s,NULL);
+             xsystem(line);
+         }
+#endif /* datageneral */
+       return(success = 1);
+    }
+#endif /* NOFRILLS */
+#endif /* OS2 */
+#endif /* MAC */
+
+#ifndef NOFRILLS
+    if (cx == XXWRI || cx == XXWRL || cx == XXWRBL) { /* WRITE */
+       int x,y;                        /* On stack in case of \fexec() */
+       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);
+       s = brstrip(s);
+       switch (x) {
+         case LOGD: y = ZDFILE; break;
+         case LOGP: y = ZPFILE; break;
+#ifndef NOLOCAL
+         case LOGS: y = ZSFILE; break;
+#endif /* NOLOCAL */
+         case LOGT: y = ZTFILE; break;
+#ifndef NOSPL
+         case LOGW: y = ZWFILE; break;
+#endif /* NOSPL */
+         case LOGX:                    /* SCREEN (stdout) */
+         case LOGE:                    /* ERROR  (stderr) */
+           if (x == LOGE) {
+               debug(F110,
+                     (cx == XXWRL) ? "WRITELN ERROR" : "WRITE ERROR", s,0);
+               fprintf(stderr,"%s%s",s,(cx == XXWRL) ? "\n" : "");
+           } else {
+               debug(F110,
+                     (cx == XXWRL) ? "WRITELN SCREEN" : "WRITE SCREEN", s,0);
+               printf("%s%s",s,(cx == XXWRL) ? "\n" : "");
+           }
+           return(success = 1);
+         default: return(-2);
+       }
+       if (chkfn(y) > 0) {
+           x = (cx == XXWRI) ? zsout(y,s) : zsoutl(y,s);
+           if (x < 0) printf("?Write error\n");
+       } else {
+           x = -1;
+           printf("?File or log not open\n");
+       }
+       return(success = (x == 0) ? 1 : 0);
+    }
+#endif /* NOFRILLS */
+
+#ifndef NOXFER
+    if (cx == XXASC || cx == XXBIN) {
+       if ((x = cmcfm()) < 0) return(x);
+#ifdef NEWFTP
+       if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
+         return(success = doftptyp((cx == XXASC) ? 0 : 1));
+#endif /* NEWFTP */
+       binary = (cx == XXASC) ? XYFT_T : XYFT_B;
+       return(success = 1);
+    }
+#endif /* NOXFER */
+
+    if (cx == XXCLS) {
+       if ((x = cmcfm()) < 0) return(x);
+       y = ck_cls();
+       return(success = (y > -1) ? 1 : 0);
+    }
+
+#ifdef CK_MKDIR
+    if (cx == XXMKDIR || cx == XXLMKD) {
+       char *p;
+#ifdef LOCUS
+       if (!locus && cx != XXLMKD) {
+#ifdef NOXFER
+           return(-2);
+#else
+           return(dormt(XZMKD));
+#endif /* NOXFER */
+        }
+#endif /* LOCUS */
+#ifdef IKSD
+       if (inserver && !ENABLED(en_mkd)) {
+           printf("?Sorry, directory creation is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+       if ((x = cmfld("Name for new directory","",&s,xxstring)) < 0) {
+           if (x != -3) {
+               return(x);
+           } else {
+               printf("?Directory name required\n");
+               return(-9);
+           }
+       }
+       ckstrncpy(line,s,LINBUFSIZ);
+       s = line;
+       if ((x = cmcfm()) < 0) return(x);
+       s = brstrip(s);
+       bgchk();                        /* Set msgflg */
+       x = ckmkdir(0,s,&p,msgflg,0);
+#ifdef COMMENT
+       if (msgflg && x == 0)
+         printf("?Directory already exists\n");
+#endif /* COMMENT */
+       return(success = (x < 0) ? 0 : 1);
+    }
+    if (cx == XXRMDIR || cx == XXLRMD) { /* RMDIR */
+       char *p;
+#ifdef LOCUS
+       if (!locus && cx != XXLRMD) {
+#ifdef NOXFER
+           return(-2);
+#else
+           return(dormt(XZRMD));
+#endif /* NOXFER */
+        }
+#endif /* LOCUS */
+#ifdef IKSD
+       if (inserver && !ENABLED(en_rmd)) {
+           printf("?Sorry, directory removal is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+       if ((x = cmdir("Name of directory to be removed","",&s,xxstring)) < 0)
+         return(x);
+       ckstrncpy(line,s,LINBUFSIZ);
+       s = line;
+       if ((x = cmcfm()) < 0) return(x);
+       s = brstrip(s);
+       x = ckmkdir(1,s,&p,msgflg,0);
+       return(success = (x < 0) ? 0 : 1);
+    }
+#endif /* CK_MKDIR */
+
+#ifdef TNCODE
+    if (cx == XXTELOP)
+      return(dotelopt());
+#endif /* TNCODE */
+
+#ifndef NOPUSH
+    if (cx == XXNPSH) {
+       if ((z = cmcfm()) < 0) return(z);
+        nopush = 1;
+#ifndef NOSERVER
+        en_hos = 0;
+#endif /* NOSERVER */
+#ifdef PIPESEND
+       usepipes = 0;
+#endif /* PIPESEND */
+        return(success = 1);
+    }
+#endif /* NOPUSH */
+
+#ifdef OS2
+    if (cx == XXNSCR) {
+       if ((z = cmcfm()) < 0) return(z);
+        tt_scroll = 0;
+        return(success = 1);
+    }
+#endif /* OS2 */
+
+#ifndef NOSPL
+    if (cx == XXLOCAL)                 /* LOCAL variable declarations */
+      return(success = dolocal());
+#endif /* NOSPL */
+
+    if (cx == XXKERMI) {               /* The KERMIT command */
+       char * list[65];
+       extern char **xargv;
+       extern int xargc;
+       int i;
+       if ((y = cmtxt("kermit command-line arguments, -h for help",
+                      "",&s,xxstring)) < 0)
+         return(y);
+       ckstrncpy(line,"kermit ",LINBUFSIZ);
+       ckstrncat(line,s,LINBUFSIZ-8);
+       xwords(line,64,list,0);
+       for (i = 1; i < 64; i++) {
+           if (!list[i])
+             break;
+       }
+       i--;
+       xargc = i;
+       xargv = list;
+       xargv++;
+       sstate = cmdlin();
+       if (sstate) {
+           extern int justone;
+           debug(F000,"KERMIT sstate","",sstate);
+           justone = 1;                /* Force return to command mode */
+           proto();                    /* after protocol */
+           return(success);
+       } else {
+           debug(F101,"KERMIT sstate","",sstate);
+           return(success = 1);        /* Not exactly right, but... */
+       }
+    }
+    if (cx == XXDATE) {                        /* DATE command */
+       extern char cmdatebuf[], * cmdatemsg;
+
+#ifndef COMMENT
+       char * dp;
+       if ((y = cmtxt("date and/or time, or carriage return for current",
+                      "",&s,xxstring)) < 0)
+         return(y);
+       s = brstrip(s);
+       dp = cmcvtdate(s,1);
+       if (!dp) {
+           printf("?%s\n",cmdatemsg ? cmdatemsg : "Date conversion error");
+           success = 0;
+       } else {
+           printf("%s\n",dp);
+           success = 1;
+       }
+#else
+       /* This works fine but messes up my "dates" torture-test script */
+
+       if ((x = cmdate("Date and/or time, or carriage return for current",
+                       "",&s,0,xxstring)) < 0) {
+           return(x);
+       } else {
+           printf("%s\n",cmdatebuf);
+           success = 1;
+       }
+#endif /* COMMENT */
+       return(success);
+    }
+#ifndef NOPUSH
+#ifndef NOFRILLS
+    if (cx == XXEDIT)
+      return(doedit());
+#endif /* NOFRILLS */
+#endif /* NOPUSH */
+
+#ifdef BROWSER                         /* Defined only ifndef NOPUSH */
+    if (cx == XXBROWS)
+      return(dobrowse());
+#endif /* BROWSER */
+
+#ifdef CK_TAPI
+    if (cx == XXTAPI) {                        /* Microsoft TAPI */
+       return (success = dotapi());
+    }
+#endif /* CK_TAPI */
+
+#ifndef NOXFER
+    if (cx == XXWHERE) {
+       extern char * rfspec, * sfspec, * srfspec, * rrfspec;
+       if ((x = cmcfm()) < 0) return(x);
+       printf("\nFile most recently...\n\n");
+       printf("  Sent:       %s\n",   sfspec ? sfspec : "(none)");
+       if (sfspec && srfspec) {
+           printf("  Stored as:  %s\n",   srfspec);
+           printf("\n");
+       }
+       printf("  Received:   %s\n",   rrfspec ? rrfspec : "(none)");
+       if (rfspec && rrfspec)
+       printf("  Stored as:  %s\n",   rfspec);
+       printf(
+"\nIf the full path is not shown, then the file is probably in your current\n"
+              );
+       printf(
+"directory or your download directory (if any - SHOW FILE to find out).\n\n"
+              );
+       return(success = 1);
+    }
+#endif /* NOXFER */
+
+#ifdef CK_RECALL
+    if (cx == XXREDO)
+      return(doredo());
+#endif /* CK_RECALL */
+
+#ifdef CKROOT
+    if (cx == XXCHRT)                  /* Change Kermit's root directory */
+      return(dochroot());
+#endif /* CKROOT */
+
+#ifdef CK_KERBEROS
+    if (cx == XXAUTH) {                        /* KERBEROS */
+       x = cp_auth();                  /* Parse it */
+#ifdef IKSD
+        if (inserver) {
+            printf("?Command disabled in IKSD.\r\n");
+            return(success = 0);
+        }
+#endif /* IKSD */
+       if (x < 0)                      /* Pass parse errors back */
+         return(x);
+       return(success = doauth(cx));
+    }
+#endif /* CK_KERBEROS */
+
+#ifndef NOLOCAL
+    if (cx == XXTERM) {
+       return(settrmtyp());
+    }
+#endif /* NOLOCAL */
+
+    if (cx == XXSTATUS) {
+       if ((x = cmcfm()) < 0) return(x);
+       printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
+       return(0);                      /* Don't change it */
+    }
+
+    if (cx == XXFAIL) {
+       if ((x = cmcfm()) < 0) return(x);
+       return(success = 0);
+    }
+
+    if (cx == XXSUCC) {
+       if ((x = cmcfm()) < 0) return(x);
+       return(success = 1);
+    }
+
+    if (cx == XXNLCL) {
+       extern int nolocal;
+       if ((x = cmcfm()) < 0) return(x);
+       nolocal = 1;
+       return(success = 1);
+    }
+
+#ifndef NOXFER
+    if (cx == XXRASG)                  /* Shortcuts for REMOTE commands */
+      return(dormt(XZASG));
+    if (cx == XXRCWD)
+      return(dormt(XZCWD));
+    if (cx == XXRCPY)
+      return(dormt(XZCPY));
+    if (cx == XXRDEL)
+      return(dormt(XZDEL));
+    if (cx == XXRDIR)
+      return(dormt(XZDIR));
+    if (cx == XXRXIT)
+      return(dormt(XZXIT));
+    if (cx == XXRHLP)
+      return(dormt(XZHLP));
+    if (cx == XXRHOS)
+      return(dormt(XZHOS));
+    if (cx == XXRKER)
+      return(dormt(XZKER));
+    if (cx == XXRPWD)
+      return(dormt(XZPWD));
+    if (cx == XXRQUE)
+      return(dormt(XZQUE));
+    if (cx == XXRREN)
+      return(dormt(XZREN));
+    if (cx == XXRMKD)
+      return(dormt(XZMKD));
+    if (cx == XXRRMD)
+      return(dormt(XZRMD));
+    if (cx == XXRSET)
+      return(dormt(XZSET));
+    if (cx == XXRSPA)
+      return(dormt(XZSPA));
+    if (cx == XXRTYP)
+      return(dormt(XZTYP));
+    if (cx == XXRWHO)
+      return(dormt(XZWHO));
+    if (cx == XXRCDUP)
+      return(dormt(XZCDU));
+    if (cx == XXRPRI)
+      return(dormt(XZPRI));
+#endif /* NOXFER */
+
+    if (cx == XXRESET) {               /* RESET */
+       if ((x = cmcfm()) < 0)
+         return(x);
+       doclean(0);                     /* Close all files */
+       return(success = 1);
+    }
+
+#ifndef NOXFER
+#ifndef NOCSETS
+    if (cx == XXASSOC)                 /* ASSOCIATE */
+      return(doassoc());
+#endif /* NOCSETS */
+#endif /* NOXFER */
+
+#ifndef NOSPL
+    if (cx == XXSHIFT) {               /* SHIFT */
+       if ((y = cmnum("Number of arguments to shift","1",10,&x,xxstring)) < 0)
+         return(y);
+       if ((z = cmcfm()) < 0)
+         return(z);
+       return(success = doshift(x));
+    }
+#endif /* NOSPL */
+
+#ifndef NOHELP
+    if (cx == XXMAN)
+      return(domanual());
+#endif /* NOHELP */
+
+#ifndef NOSPL
+    if (cx == XXSORT)                  /* SORT an array */
+      return(dosort());
+#endif /* NOSPL */
+
+    if (cx == XXPURGE) {
+#ifdef IKSD
+       if (inserver && (!ENABLED(en_del)
+#ifdef CK_LOGIN
+                          || isguest
+#endif /* CK_LOGIN */
+                        )) {
+           printf("?Sorry, DELETE is disabled\n");
+           return(-9);
+       }
+#endif /* IKSD */
+#ifdef CK_APC
+       if ((apcactive == APC_LOCAL) ||
+           ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
+         return(success = 0);
+#endif /* CK_APC */
+#ifdef CKPURGE
+        return(dopurge());
+#else
+#ifdef VMS
+       if ((x = cmtxt("optional switches followed by filespec",
+                      "",&s,xxstring)) < 0)
+         return(x);
+       if (nopush) {
+           printf("?Sorry, DCL access is disabled\n");
+           return(-9);
+       }
+       ckstrncpy(line,s,LINBUFSIZ);
+       s = line;
+       x = mlook(mactab,"purge",nmac);
+       return(success = dodo(x,s,cmdstk[cmdlvl].ccflgs));
+#else
+       return(-2);
+#endif /* VMS */
+#endif /* CKPURGE */
+    }
+
+#ifndef NOSPL
+    if (cx == XXFAST) {
+       if ((x = cmcfm()) < 0) return(x);
+       x = mlook(mactab,"fast",nmac);
+       return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
+    }
+    if (cx == XXCAU) {
+       if ((x = cmcfm()) < 0) return(x);
+       x = mlook(mactab,"cautious",nmac);
+       return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
+    }
+    if (cx == XXROB) {
+       if ((x = cmcfm()) < 0) return(x);
+       x = mlook(mactab,"robust",nmac);
+       return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
+    }
+#endif /* NOSPL */
+
+    if (cx == XXSCRN) {                        /* SCREEN */
+       int row, col;
+       if ((x = cmkey(scntab, nscntab,"screen action","", xxstring)) < 0)
+         return(x);
+       switch (x) {                    /* MOVE-TO (cursor position) */
+         case SCN_MOV:
+           if ((y = cmnum("Row (1-based)","",10,&z,xxstring)) < 0)
+             return(y);
+           row = z;
+           y = cmnum("Column (1-based)","1",10,&z,xxstring);
+           if (y < 0)
+             return(y);
+           col = z;
+           if ((y = cmcfm()) < 0)
+             return(y);
+           if (row < 0 || col < 0) {
+               printf("?Row and Column must be 1 or greater\n");
+               return(-9);
+           }
+           if (cmd_rows > 0 && row > cmd_rows)
+             row = cmd_rows;
+           if (cmd_cols > 0 && col > cmd_cols)
+             col = cmd_cols;
+           y = ck_curpos(row,col);
+           return(success = (y > -1) ? 1 : 0);
+
+         case SCN_CLR:                 /* CLEAR */
+           if ((y = cmcfm()) < 0)
+             return(y);
+           debug(F100,"screen calling ck_cls()","",0);
+           y = ck_cls();
+           return(success = (y > -1) ? 1 : 0);
+
+         case SCN_CLE:                 /* CLEOL */
+           if ((y = cmcfm()) < 0)
+             return(y);
+           y = ck_cleol();
+           return(success = (y > -1) ? 1 : 0);
+       }
+    }
+
+#ifndef NOHTTP
+#ifdef TCPSOCKET
+    if (cx == XXHTTP)
+      return(dohttp());
+#endif /* TCPSOCKET */
+#endif /* NOHTTP */
+
+#ifndef NOSPL
+    if (cx == XXARRAY) {               /* ARRAY */
+#ifndef NOSHOW
+       extern int showarray();
+#endif /* NOSHOW */
+       if ((x = cmkey(arraytab, narraytab,"Array operation","",xxstring)) < 0)
+         return(x);
+       switch (x) {
+         case ARR_DCL:
+           return(dodcl(XXDCL));
+         case ARR_SRT:
+           return(dosort());
+#ifndef NOSHOW
+         case ARR_SHO:
+           return(showarray());
+#endif /* NOSHOW */
+         case ARR_CPY:
+           return(copyarray());
+         case ARR_SET:
+         case ARR_CLR:
+           return(clrarray(x));
+         case ARR_DST:
+           return(unarray());
+         case ARR_RSZ:
+           return(rszarray());
+         case ARR_EQU:
+           return(linkarray());
+
+         default:
+           printf("?Sorry, not implemented yet - \"%s\"\n",cmdbuf);
+           return(-9);
+       }
+    }
+    if (cx == XXTRACE)
+      return(dotrace());
+#endif /* NOSPL */
+
+#ifdef CK_PERMS
+#ifdef UNIX
+    if (cx == XXCHMOD)
+      return(douchmod());              /* Do Unix chmod */
+#endif /* UNIX */
+#endif /* CK_PERMS */
+
+    if (cx == XXPROMP)
+      return(doprompt());
+
+    if (cx == XXGREP)
+      return(dogrep());
+
+    if (cx == XXDEBUG) {               /* DEBUG */
+#ifndef DEBUG
+       int dummy = 0;
+       return(seton(&dummy));
+#else
+       return(seton(&deblog));
+#endif /* DEBUG */
+    }
+
+#ifdef CKLEARN
+    if (cx == XXLEARN) {               /* LEARN */
+       struct FDB of, sw, cm;
+       int closing = 0, off = 0, on = 0, confirmed = 0;
+       char c;
+
+       cmfdbi(&sw,                     /* 2nd FDB - optional /PAGE switch */
+              _CMKEY,                  /* fcode */
+              "Script file name, or switch", /* hlpmsg */
+              "",                      /* default */
+              "",                      /* addtl string data */
+              3,                       /* addtl numeric data 1: tbl size */
+              4,                       /* addtl numeric data 2: 4 = cmswi */
+              xxstring,                /* Processing function */
+              learnswi,                /* Keyword table */
+              &of                      /* Pointer to next FDB */
+              );
+       cmfdbi(&of,_CMOFI,"","","",0,0,xxstring,NULL,&cm);
+       cmfdbi(&cm,_CMCFM,"","","",0,0,NULL,NULL,NULL);
+       line[0] = NUL;
+
+       while (!confirmed) {
+           x = cmfdb(&sw);             /* Parse something */
+           if (x < 0)
+             return(x);
+           switch (cmresult.fcode) {   /* What was it? */
+             case _CMOFI:              /* Output file name */
+               ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
+               break;
+             case _CMKEY:              /* Switch */
+               c = cmgbrk();
+               if ((c == ':' || c == '=') && !(cmgkwflgs() & CM_ARG)) {
+                   printf("?This switch does not take an argument\n");
+                   return(-9);
+               }
+               switch (cmresult.nresult) {
+                 case 2:               /* /CLOSE */
+                   closing = 1;        /* Fall thru on purpose */
+                 case 0:               /* /OFF */
+                   off = 1;
+                   on = 0;
+                   break;
+                 case 1:               /* /ON */
+                   on = 1;
+                   off = 0;
+                   break;
+               }
+               break;
+             case _CMCFM:              /* Confirmation */
+               confirmed++;
+               break;
+           }
+       }
+       if (closing) {
+           if (learnfp) {
+               fclose(learnfp);
+               learnfp = NULL;
+           }
+           makestr(&learnfile,NULL);
+       }
+       if (line[0]) {
+           if (!on && !off)
+             on = 1;
+           if (learnfp) {
+               fclose(learnfp);
+               learnfp = NULL;
+           }
+           makestr(&learnfile,line);
+           if (learnfile) {
+               char * modes = "w";
+               learnfp = fopen(learnfile,modes);
+               if (!learnfp) {
+                   debug(F110,"LEARN file open error",learnfile,0);
+                   perror(learnfile);
+                   return(-9);
+               } else {
+#ifdef ZFNQFP
+                   if (zfnqfp(learnfile,TMPBUFSIZ,tmpbuf))
+                     makestr(&learnfile,tmpbuf);
+#endif /* ZFNQFP */
+                   debug(F110,"LEARN file open ok",learnfile,0);
+                   if (!quiet) {
+                       printf("Recording to %s...\n\n",learnfile);
+                       printf(
+" WARNING: If you type your password during script recording, it will appear\n\
+ in the file.  Be sure to edit it or take other appropriate precautions.\n\n"
+                              );
+                   }
+                   fputs(  "; Scriptfile: ",learnfp);
+                   fputs(learnfile,learnfp);
+                   fputs("\n; Directory:  ",learnfp);
+                   fputs(zgtdir(),learnfp);
+                   fputs("\n; Recorded:   ",learnfp);
+                   fputs(ckdate(),learnfp);
+                   fputs("\n",learnfp);
+               }
+           }
+       }
+       if (on) {
+           learning = 1;
+       } else if (off) {
+           learning = 0;
+       }
+       debug(F101,"LEARN learning","",learning);
+       return(success = 1);
+    }
+#endif /* CKLEARN */
+
+#ifdef NEWFTP
+    if (cx == XXUSER || cx == XXACCT) {
+       if (!ftpisopen()) {
+           printf("?FTP connection is not open\n");
+           return(-9);
+       }
+       return(success = (cx == XXUSER) ? doftpusr() : doftpacct());
+    }
+    if (cx == XXSITE || cx == XXPASV) {
+       if (!ftpisopen()) {
+           printf("?FTP connection is not open\n");
+           return(-9);
+       }
+       return(success = (cx == XXSITE) ? doftpsite() : dosetftppsv());
+    }
+#endif /* NEWFTP */
+
+    if (cx == XXORIE) {                        /* ORIENTATION */
+       extern char * myname;
+       int i, y, n = 0;
+        char * s, *p, vbuf[32];
+       char * vars[16];       char * legend[16];
+
+       if ((y = cmcfm()) < 0)
+         return(y);
+
+       printf("\nProgram name:\n  %s\n\n",myname);
+       n += 4;
+
+#ifdef NT
+       vars[0] = "home";      legend[0] = "Your home directory";
+       vars[1] = "directory"; legend[1] = "K95's current directory";
+       vars[2] = "exedir";    legend[2] = "K95 Program directory";
+       vars[3] = "inidir";    legend[3] = "K95 Initialization file directory";
+       vars[4] = "startup";   legend[4] = "Current directory when started";
+       
+        vars[5] = "common";
+        legend[5] = "K95 data for all users and K95SITE.INI file";
+       
+        vars[6] = "personal";  legend[6] = "Your personal data directory tree";
+        vars[7] = "desktop";   legend[7] = "Your deskop directory tree";
+       
+        vars[8] = "appdata";
+        legend[8] = "Your personal K95 data tree and K95CUSTOM.INI file";
+       
+        vars[9] = "download";  legend[9] = "Your K95 download directory";
+        vars[10] = "tmpdir";   legend[10] = "Your TEMP directory";
+       vars[11] = NULL;       legend[11] = NULL;
+
+       for (i = 0; i < 16 && vars[i]; i++) {
+           printf("%s:\n",legend[i]);
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+           ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
+           printf("  Variable:   %s\n",vbuf);
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+           y = TMPBUFSIZ;
+           s = tmpbuf;
+           zzstring(vbuf,&s,&y);
+           line[0] = NUL;
+           ckGetLongPathName(tmpbuf,line,LINBUFSIZ);
+           printf("  Long name:  %s\n",line);
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+           line[0] = NUL;
+           GetShortPathName(tmpbuf,line,LINBUFSIZ);
+           printf("  Short name: %s\n",line);
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+            printf("\n");
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+       }
+#else  /* NT */
+
+       vars[0] = "home";      legend[0] = "Your home directory";
+       vars[1] = "directory"; legend[1] = "Kermit's current directory";
+       vars[2] = "exedir";    legend[2] = "Kermit's program directory";
+       vars[3] = "inidir";    legend[3] = "Initialization file directory";
+       vars[4] = "startup";   legend[4] = "Current directory when started";
+       vars[5] = "download";  legend[5] = "Kermit download directory";
+       vars[6] = NULL;        legend[6] = NULL;
+
+       for (i = 0; i < 16 && vars[i]; i++) {
+           printf("%s:\n",legend[i]);
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+           ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
+           printf("  Variable: %s\n",vbuf);
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+           y = TMPBUFSIZ;
+           s = tmpbuf;
+           zzstring(vbuf,&s,&y);
+            printf("  Value:    %s\n",tmpbuf);
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+            printf("\n");
+           if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
+       }
+#endif /* NT */
+       return(success = 1);
+    }
+
+#ifdef NT
+    if (cx == XXDIALER) {
+        StartDialer();
+        return(success = 1);
+    }
+#endif /* NT */
+
+    if (cx == XXCONT) {                        /* CONTINUE */
+       if ((x = cmcfm()) < 0)
+         return(x);
+       if (!xcmdsrc) {                 /* At prompt: continue script */
+           if (cmdlvl > 0)
+             popclvl();                /* Pop command level */
+           return(success = 1);        /* always succeeds */
+#ifndef NOSPL
+       } else {                        /* In script: whatever... */
+           x = mlook(mactab,"continue",nmac);
+           /* Don't set success */
+           return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
+#endif /* NOSPL */
+       }
+    }
+    if (cx == XXNOTAV) {               /* Command in table not available */
+       ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
+       if ((x = cmtxt("Rest of command","",&s,NULL)) < 0)
+         return(x);
+       printf("Sorry, \"%s\" not configured in this version of Kermit.\n",
+              tmpbuf
+              );
+       return(success = 0);
+    }
+    return(-2);                                /* None of the above */
+
+} /* end of docmd() */
+
+#endif /* NOICP */
index 4220079..d705a33 100644 (file)
@@ -1,2 +1,3 @@
 010_makefile-destdir-support.patch
 020_man-hyphen-quoting.patch
+030_fix-if-else.patch
index 5dcd828..a5abf19 100644 (file)
--- a/ckuus6.c
+++ b/ckuus6.c
@@ -6607,7 +6607,7 @@ doelse() {
     if (!iftest[cmdlvl]) {              /* If IF was false do ELSE part */
         if (maclvl > -1 || tlevel > -1) { /* In macro or command file */
             debug(F100,"doelse pushing","",0);
-#ifdef COMMENT
+#ifndef COMMENT
             pushcmd(NULL);              /* save rest of command. */
 #else
             /* This fixes certain obscure problems */
index 8545f89..882c0d4 100644 (file)
--- a/ckuusr.c
+++ b/ckuusr.c
@@ -7983,8 +7983,7 @@ docmd(cx) int cx; {
            line[k++] = SP;
            line[k] = NUL;
            debug(F111,"XXMACRO A",line,k);
-           /* Defer evaluation of variables until the commands are exec'd */
-           if ((y = cmtxt("Braced list of commands","",&s,NULL)) < 0)
+           if ((y = cmtxt("Braced list of commands","",&s,xxstring)) < 0)
              return(y);
            k = ckstrncpy(line+k,s,LINBUFSIZ-k);
            debug(F111,"XXMACRO B",line,k);