--- /dev/null
+#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 */
--- /dev/null
+#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(¯oname,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 */