From 2788625b3cd3bff4a649667f38a3bcc52b71af24 Mon Sep 17 00:00:00 2001 From: Ian Beckwith Date: Wed, 12 May 2010 01:20:05 +0100 Subject: [PATCH] applied 030_fix-if-else.patch --- .pc/030_fix-if-else.patch/.timestamp | 0 .pc/030_fix-if-else.patch/ckuus6.c | 10878 +++++++++++++++++++++++++++ .pc/030_fix-if-else.patch/ckuusr.c | 13121 +++++++++++++++++++++++++++++++++ .pc/applied-patches | 1 + ckuus6.c | 2 +- ckuusr.c | 3 +- 6 files changed, 24002 insertions(+), 3 deletions(-) create mode 100644 .pc/030_fix-if-else.patch/.timestamp create mode 100644 .pc/030_fix-if-else.patch/ckuus6.c create mode 100644 .pc/030_fix-if-else.patch/ckuusr.c diff --git a/.pc/030_fix-if-else.patch/.timestamp b/.pc/030_fix-if-else.patch/.timestamp new file mode 100644 index 0000000..e69de29 diff --git a/.pc/030_fix-if-else.patch/ckuus6.c b/.pc/030_fix-if-else.patch/ckuus6.c new file mode 100644 index 0000000..5dcd828 --- /dev/null +++ b/.pc/030_fix-if-else.patch/ckuus6.c @@ -0,0 +1,10878 @@ +#include "ckcsym.h" +#ifndef NOICP + +/* C K U U S 6 -- "User Interface" for Unix Kermit (Part 6) */ + +/* + Authors: + Frank da Cruz , + The Kermit Project, Columbia University, New York City + Jeffrey E Altman + 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 + +#ifdef VMS +#ifndef TCPSOCKET +#include +#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 +#undef COMMENT +#else +#define APIRET ULONG +#include +#include +#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, is returned as . */ +/* 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 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,"",dstr,name); +#else + if (p) + sprintf(linebuf,"%10s%-10s %s %s",p,"",dstr,name); + else + sprintf(linebuf,"%-10s %s %s", "", dstr, name); +#endif /* VMS */ + } else { /* Regular file */ +#ifdef VMS + sprintf(linebuf,"%-22s%10ld %s %s", p, len, dstr, name); +#else + if (p) + sprintf(linebuf,"%10s%10ld %s %s", p, len, dstr, name); + else + sprintf(linebuf,"%10ld %s %s", len, dstr, name); +#endif /* VMS */ + } +#ifdef UNIX +#ifdef CKSYMLINK + if (zgfs_link) { + int n, m; + extern char linkname[]; + n = strlen(linebuf); + m = strlen(linkname) + n; + if (m < CKMAXPATH + 58) + strcpy(linebuf+n, " -> "); /* safe (checked) */ + if (m + 4 < CKMAXPATH - 58) + strcpy(linebuf+n+4, linkname); /* safe (checked) */ + } else +#endif /* CKSYMLINK */ +#endif /* UNIX */ + if (xfermod) { /* Show transfer mode */ + int i, x, y; + char * s = ""; + y = -1; + x = scanfile(name,&y,nscanfile); + switch (x) { + case FT_TEXT: s = " (T)"; break; + case FT_7BIT: s = " (T)(7BIT)"; break; + case FT_8BIT: s = " (T)(8BIT)"; break; +#ifdef UNICODE + case FT_UTF8: s = " (T)(UTF8)"; break; + case FT_UCS2: + s = y ? " (T)(UCS2LE)" : " (T)(UCS2BE)"; + break; +#endif /* UNICODE */ + case FT_BIN: s = " (B)"; break; + } + if (!*s) { + s = binary ? " (B)" : " (T)"; + } + if (*s) { + int n; + n = strlen(linebuf); + if (n + 4 < CKMAXPATH - 58) + strcpy(linebuf+n, s); /* safe (checked) */ + } + } + if (msg && dirmsg) { + int n; + n = strlen(linebuf); + if (n + dirmsglen + 2 < CKMAXPATH) + sprintf((char *)(linebuf+n)," %s", dirmsg); /* SAFE */ + } + if (xsort) { /* Sorting - save line */ + i = strlen(linebuf); + if ((ndirlist >= nx) || + !(dirlist[ndirlist] = (char *)malloc(i+1))) { + printf("?Memory allocation error - try /NOSORT\n"); + rc = -9; + goto xdomydir; + } + strcpy(dirlist[ndirlist],linebuf); /* safe */ + ndirlist++; + } + znext(name); /* Peek ahead to next file */ + + if (!xsort) { + fprintf(ofp,"%s\n",linebuf); + if (page && (name[0] || heading)) { /* If /PAGE */ + if (cmd_cols > 0) { + int x = strlen(linebuf); + int y; + y = (x % cmd_cols) ? 1 : 0; + n += x / cmd_cols + y; + } else { + n++; + } +#ifdef CK_TTGWSIZ + if (n > (cmd_rows - 3)) { /* Do more-prompting */ + if (!askmore()) { + rc = 0; + goto xdomydir; + } else + n = 0; + } +#endif /* CK_TTGWSIZ */ + } + } + } +#ifndef NOSPL + if (array) { + if (ap) + makestr(&(ap[0]),ckitoa(nmatches)); + rc = 1; + goto xdomydir; + } +#endif /* NOSPL */ + if (xsort) { + skey = 0; +#ifdef VMS + switch (sortby) { + case DIRS_NM: skey = dlen + 35; break; + case DIRS_DT: skey = 33; break; + case DIRS_SZ: skey = 21; + } +#else + if (p) { + switch (sortby) { + case DIRS_NM: skey = dlen + 24; break; + case DIRS_DT: skey = 22; break; + case DIRS_SZ: skey = 10; + } + } else { + switch (sortby) { + case DIRS_NM: skey = dlen + 14; break; + case DIRS_DT: skey = 12; break; + case DIRS_SZ: skey = 0; + } + } +#endif /* VMS */ + sh_sort(dirlist,NULL,ndirlist,skey,reverse,filecase); + for (i = 0; i < ndirlist; i++) { + fprintf(ofp,"%s\n",dirlist[i]); + if (page && (i < ndirlist -1 || heading)) { /* If /PAGE */ + if (cmd_cols > 0) { + int x = strlen(dirlist[i]); + int y; + y = (x % cmd_cols) ? 1 : 0; + n += ((int)strlen(dirlist[i]) / cmd_cols) + y; + } else { + n++; + } +#ifdef CK_TTGWSIZ + if (n > (cmd_rows - 3)) { /* Do more-prompting */ + if (!askmore()) { + rc = 0; + goto xdomydir; + } else + n = 0; + } +#endif /* CK_TTGWSIZ */ + } + } + } + + if (heading || summary) { +#ifdef CKFLOAT + CKFLOAT gm; +#endif /* CKFLOAT */ + fprintf(ofp,"\n%ld director%s, %ld file%s, %ld byte%s", + ndirs, + (ndirs == 1) ? "y" : "ies", + nfiles, + (nfiles == 1) ? "" : "s", + nbytes, + (nbytes == 1) ? "" : "s" + ); +#ifdef CKFLOAT + gm = ((CKFLOAT) nbytes ) / 1000000.0; + if (gm > 1000.0) + fprintf(ofp," (%0.2fGB)",(gm / 1000.0)); + else if (gm >= 0.01) + fprintf(ofp," (%0.2fMB)",gm); +#endif /* CKFLOAD */ + fprintf(ofp,"\n\n"); + } + xdomydir: + if (g_matchdot > -1) { + matchdot = g_matchdot; /* Restore these... */ + g_matchdot = -1; + } + freedirlist(); + if (ofp != stdout) { /* Close any output file */ + if (ofp) fclose(ofp); + ofp = stdout; + } + if (rc > 0) + success = 1; + return(rc); +} + +int +dodir(cx) int cx; { /* Do the DIRECTORY command */ + char *dc , *msg; + +#ifdef OS2 + return(domydir()); +#else /* OS2 */ + if (nopush +#ifdef DOMYDIR /* Builds that domydir() by default */ + || (cx == XXDIR || cx == XXLDIR) +#endif /* DOMYDIR */ + ) + return(domydir()); /* Built-in directory command */ + + /* Use the system's directory command. */ + + msg = (cx == XXLS) ? + "Arguments for ls" : + "Directory and/or file specification"; + if ((x = cmtxt(msg,"",&s,xxstring)) < 0) + return(x); + + ckstrncpy(tmpbuf,s,TMPBUFSIZ); /* Copy the filespec */ + s = tmpbuf; + + if ((y = cmcfm()) < 0) return(y); + + lp = line; + if (!(dc = getenv("CK_DIR"))) + dc = DIRCMD; + ckmakmsg(lp,LINBUFSIZ,dc," ",s,NULL); + debug(F110,"DIR",line,0); +#ifdef VMS + conres(); +#endif /* VMS */ + x = zshcmd(line); +#ifdef VMS + concb((char)escape); +#endif /* VMS */ + return(success = (x < 1) ? 0 : 1); +#endif /* OS2 */ +} + +#ifndef NOSERVER +#ifndef NOFRILLS +/* Do the ENABLE and DISABLE commands */ + +int +doenable(y,x) int y, x; { +#ifdef CK_LOGIN + if (isguest) /* IKSD: Don't let guests */ + return(0); /* enable anything that's disabled */ +#endif /* CK_LOGIN */ + switch (x) { + case EN_ALL: + en_cwd = en_cpy = en_del = en_dir = en_fin = en_get = y; + en_ren = en_sen = en_set = en_spa = en_typ = en_ret = y; + if (!inserver) + en_who = en_mai = en_pri = y; + en_mkd = en_rmd = y; + en_xit = y; +#ifndef datageneral + en_bye = y; +#endif /* datageneral */ +#ifndef NOPUSH + if (!nopush && !inserver) + en_hos = y; +#endif /* NOPUSH */ +#ifndef NOSPL + en_asg = en_que = y; +#endif /* NOSPL */ + break; + + case EN_BYE: +#ifndef datageneral +/* + In Data General AOS/VS Kermit can't log out its superior process. +*/ + en_bye = y; +#endif /* datageneral */ + break; + case EN_CPY: + en_cpy = y; + break; + case EN_CWD: + en_cwd = y; +#ifdef IKSD + if (inserver && y == 0) { + fnrpath = PATH_OFF; + fnspath = PATH_OFF; + } +#endif /* IKSD */ + break; + case EN_DEL: /* Deleting of files */ + en_del = y; + break; + case EN_DIR: + en_dir = y; + break; + case EN_FIN: + en_fin = y; + break; + case EN_GET: + en_get = y; + break; +#ifndef NOPUSH + case EN_HOS: + if (!nopush) + en_hos = y; + break; +#endif /* NOPUSH */ + case EN_REN: + en_ren = y; + break; + case EN_SEN: + en_sen = y; + break; + case EN_SET: + en_set = y; + break; + case EN_SPA: + en_spa = y; + break; + case EN_TYP: + en_typ = y; + break; + case EN_WHO: + en_who = y; + break; +#ifndef NOSPL + case EN_ASG: + en_asg = y; + break; + case EN_QUE: + en_que = y; + break; +#endif /* NOSPL */ + case EN_RET: + en_del = y; + break; + case EN_MAI: +#ifdef CK_LOGIN + if (isguest && y) { + printf("?Sorry, not valid for guests\n"); + return(-9); + } +#endif /* CK_LOGIN */ + en_mai = y; + break; + case EN_PRI: +#ifdef CK_LOGIN + if (isguest && y) { + printf("?Sorry, not valid for guests\n"); + return(-9); + } +#endif /* CK_LOGIN */ + en_pri = y; + break; + case EN_MKD: + en_mkd = y; + break; + case EN_RMD: + en_rmd = y; + break; + case EN_XIT: + en_xit = y; + break; + case EN_ENA: + if (((y & 1) && !(en_ena & 1)) || + ((y & 2) && !(en_ena & 2))) { + printf("?Sorry, DISABLE ENABLE can not be undone\n"); + return(-9); + } else { + en_ena = y; + break; + } + default: + return(-2); + } + return(1); +} +#endif /* NOFRILLS */ +#endif /* NOSERVER */ + +#ifndef NOFRILLS + +static int del_lis = 0; +static int del_dot = 0; +static int del_hdg = 0; +static int del_pag = -1; +static int del_ask = 0; + +#ifndef NOSHOW +VOID +showdelopts() { + int x = 0; + extern int optlines; + prtopt(&optlines,""); + prtopt(&optlines,"DELETE"); + if (del_ask > -1) { + prtopt(&optlines, del_ask ? "/ASK" : "/NOASK"); + x++; + } +#ifdef UNIXOROSK + if (del_dot > -1) { + prtopt(&optlines, del_dot ? "/DOTFILES" : "/NODOTFILES"); + x++; + } +#endif /* UNIXOROSK */ + if (del_lis > -1) { + prtopt(&optlines, del_lis ? "/LIST" : "/NOLIST"); + x++; + } + if (del_hdg > -1) { + prtopt(&optlines, del_hdg ? "/HEADING" : "/NOHEADING"); + x++; + } +#ifndef CK_TTGWSIZ + if (del_pag > -1) { + prtopt(&optlines, del_pag ? "/PAGE" : "/NOPAGE"); + x++; + } +#endif /* CK_TTGWSIZ */ + if (!x) prtopt(&optlines,"(no options set)"); + prtopt(&optlines,""); +} +#endif /* NOSHOW */ + + +int +setdelopts() { + int x_lis = -1, x_pag = -1, x_dot = -1, x_hdg = -1, x_ask = -1; + int getval = 0; + char c; + while (1) { + if ((y = cmswi(deltab,ndeltab,"Switch","",xxstring)) < 0) { + if (y == -3) + break; + else + return(y); + } + c = cmgbrk(); + if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) { + printf("?This switch does not take an argument\n"); + return(-9); + } + if (!getval && (cmgkwflgs() & CM_ARG)) { + printf("?This switch requires an argument\n"); + return(-9); + } + switch (y) { + case DEL_DOT: + x_dot = 1; + break; + case DEL_NOD: + x_dot = 0; + break; + case DEL_HDG: + x_hdg = 1; + break; + case DEL_LIS: + x_lis = 1; + break; + case DEL_NOL: + x_lis = 0; + break; +#ifndef CK_TTGWSIZ + case DEL_PAG: + x_pag = 1; + break; + case DEL_NOP: + x_pag = 0; + break; +#endif /* CK_TTGWSIZ */ + case DEL_QUI: + x_lis = 0; + break; + case DEL_VRB: + x_lis = 1; + break; + case DEL_ASK: + x_ask = 1; + break; + case DEL_NAS: + x_ask = 0; + break; + default: + printf("?Sorry, this option can not be set\n"); + return(-9); + } + } + if ((x = cmcfm()) < 0) /* Get confirmation */ + return(x); + if (x_pag > -1) del_pag = x_pag; + if (x_dot > -1) del_dot = x_dot; + if (x_hdg > -1) del_hdg = x_hdg; + if (x_lis > -1) del_lis = x_lis; + if (x_ask > -1) del_ask = x_ask; + return(success = 1); +} + +#ifdef OS2 +static char ** xmtchs = NULL; +static int xmtchn = 0; +#endif /* OS2 */ + +int +dodel() { /* DELETE */ + int i, j, k, x; + int fs = 0; /* Need to call fileselect() */ + int len = 0; + int bad = 0; + int getval = 0, asking = 0; + int simulate = 0, rc = 0; + long minsize = -1L, maxsize = -1L; + int havename = 0, confirmed = 0; + int qflag = 0; + int summary = 0; + int deldirs = 0; + int deltree = 0; + int itsadir = 0; + int argisdir = 0; + int xmode = -1, scan = 0, skip = 0; +#ifdef COMMENT + int pass = 0; +#endif /* COMMENT */ + char c; + char * deldef = ""; + char safebuf[CKMAXPATH+1]; + struct FDB sw, fi, fl; + char + * del_aft = NULL, + * del_bef = NULL, + * del_naf = NULL, + * del_nbf = NULL, + * del_exc = NULL; + int + x_lis = 0, + /* x_dot = -1, */ + x_hdg = 0; + + char * dxlist[8]; + + for (i = 0; i < 8; i++) dxlist[i] = NULL; + + g_matchdot = matchdot; + + if (del_lis > -1) x_lis = del_lis; + if (del_dot > -1) matchdot = del_dot; + if (del_hdg > -1) x_hdg = del_hdg; + if (del_pag > -1) xaskmore = del_pag; + if (del_ask > -1) asking = del_ask; + + diractive = 1; + nolinks = 2; /* By default don't follow links */ + + cmfdbi(&sw, /* First FDB - command switches */ + _CMKEY, /* fcode */ + "File specification;\n or switch", + "", /* default */ + "", /* addtl string data */ + ndeltab, /* addtl numeric data 1: tbl size */ + 4, /* addtl numeric data 2: 4 = cmswi */ + xxstring, /* Processing function */ + deltab, /* Keyword table */ + &fi /* Pointer to next FDB */ + ); + cmfdbi(&fl, /* Anything that doesn't match */ + _CMFLD, /* fcode */ + "", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + 0, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ + xxstring, + NULL, + NULL + ); + again: + cmfdbi(&fi, /* 2nd FDB - file to delete */ + _CMIFI, /* fcode */ + "File(s) to delete", /* hlpmsg */ + deldef, /* default */ + "", /* addtl string data */ + nolinks | deldirs, /* 0 = files, 1 = files or dirs */ + 0, /* 1 = dirs only */ + xxstring, + NULL, + &fl + ); + while (!havename && !confirmed) { + x = cmfdb(&sw); /* Parse something */ + if (x < 0) { /* Error */ + if (x == -3) + break; + if (x == -2 || x == -9) + printf("?Does not match switch or filename: \"%s\"\n",atmbuf); + return(x); + } + if (cmresult.fcode != _CMKEY) /* Break out if not a switch */ + break; + c = cmgbrk(); /* Get break character */ + if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) { + printf("?This switch does not take an argument\n"); + rc = -9; + goto xdelete; + } + if (!getval && (cmgkwflgs() & CM_ARG)) { + printf("?This switch requires an argument\n"); + rc = -9; + goto xdelete; + } + switch (k = cmresult.nresult) { + case DEL_AFT: + case DEL_BEF: + case DEL_NAF: + case DEL_NBF: + if (!getval) break; + if ((x = cmdate("File-time","",&s,0,xxstring)) < 0) { + if (x == -3) { + printf("?Date-time required\n"); + x = -9; + } else + rc = x; + goto xdelete; + } + fs++; + deltree = 0; + switch (k) { + case DEL_AFT: makestr(&del_aft,s); break; + case DEL_BEF: makestr(&del_bef,s); break; + case DEL_NAF: makestr(&del_naf,s); break; + case DEL_NBF: makestr(&del_nbf,s); break; + } + break; + case DEL_DOT: + matchdot = 1; + break; + case DEL_NOD: + matchdot = 0; + break; + case DEL_ALL: + fs = 0; +#ifdef VMS + deldef = "*.*"; /* UNIX, Windows, OS/2 */ +#else +#ifdef datageneral + deldef = "+"; /* AOS/VS */ +#else + deldef = "*"; /* UNIX, Windows, OS/2, VMS... */ +#endif /* datageneral */ +#endif /* VMS */ + deltree = 1; + nolinks = 2; + matchdot = 1; + recursive = 1; /* Fall through purposely... */ + case DEL_DIR: + deldirs = 1; + goto again; + case DEL_EXC: + if (!getval) break; + if ((x = cmfld("Pattern","",&s,xxstring)) < 0) { + if (x == -3) { + printf("?Pattern required\n"); + x = -9; + } else + rc = x; + goto xdelete; + } + fs++; + deltree = 0; + makestr(&del_exc,s); + break; + case DEL_HDG: + x_hdg = 1; + break; +#ifdef RECURSIVE + case DEL_REC: + recursive = 1; + break; +#endif /* RECURSIVE */ + case DEL_LIS: + x_lis = 1; + break; + case DEL_SUM: + summary = 1; + x_lis = 0; + x_hdg = 1; + break; + case DEL_NOL: + x_lis = 0; + break; +#ifndef CK_TTGWSIZ + case DEL_PAG: + xaskmore = 1; + break; + case DEL_NOP: + xaskmore = 0; + break; +#endif /* CK_TTGWSIZ */ + case DEL_QUI: + qflag = 1; + x_lis = 0; + break; + case DEL_VRB: + x_lis = 1; + break; + + case DEL_SMA: + case DEL_LAR: + if (!getval) break; + if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0) + return(x); + fs++; + deltree = 0; + switch (cmresult.nresult) { + case DEL_SMA: minsize = y; break; + case DEL_LAR: maxsize = y; break; + } + break; + + case DEL_SIM: + simulate = 1; + x_lis = 1; + break; + case DEL_ASK: + asking = 1; + break; + case DEL_NAS: + asking = 0; + break; + case DEL_TYP: { + extern struct keytab txtbin[]; + if (!getval) break; + if ((x = cmkey(txtbin,3,"","",xxstring)) < 0) + return(x); + if (x == 2) { /* ALL */ + xmode = -1; + } else { /* TEXT or BINARY only */ + xmode = x; + scan = 1; + } + break; + } + default: + printf("?Not implemented yet - \"%s\"\n",atmbuf); + return(-9); + } + } + if (qflag && (cmresult.fcode == _CMFLD)) { + if ((x = cmcfm()) < 0) + return(x); + else + return(success = 0); + } + if (cmresult.fcode != _CMIFI) { + if (*atmbuf) { + int x; + if (iswild(atmbuf) && nzxpand(atmbuf,nzxopts) == 0) + printf("?No files match: %s\n",atmbuf); + else if ((x = zchki(atmbuf)) == -1) + printf("?File not found: %s\n",atmbuf); + else if (x == -2) + printf("?Not a regular file: %s\n",atmbuf); + else + /* printf("?Not a deletable file: %s\n",atmbuf); */ + goto tryanyway; + } else { + printf("?A file specification is required\n"); + } + return(-9); + } + tryanyway: + ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ); /* Safe copy of filespec */ + if (deldirs) { + ckstrncpy(safebuf,cmresult.sresult,CKMAXPATH); +#ifdef VMSORUNIX + len = zgetfs(tmpbuf); /* Is it a directory name? */ + argisdir = zgfs_dir; /* Then because of how zxpand() */ + if (argisdir && zgfs_link) /* works, we have to add it to */ + argisdir = 0; /* the list. */ + if (itsadir) + len = -2; +#else + len = zchki(tmpbuf); + if (len < 0) + argisdir = isdir(tmpbuf); +#endif /* VMSORUNIX */ + } + debug(F110,"DELETE file",tmpbuf,0); + if ((x = cmcfm()) < 0) + return(x); + +#ifdef IKSD +#ifdef CK_LOGIN + if (inserver && isguest) { + printf("?Sorry, DELETE unavailable to guests\n"); + return(-9); + } +#endif /* CK_LOGIN */ +#endif /* IKSD */ + +#ifndef OS2ORUNIX + if (simulate) { + printf("?Sorry, /SIMULATE not implemented on this platform\n"); + return(-9); + } +#endif /* OS2ORUNIX */ + +#ifdef COMMENT + /* (not needed) */ + if (!iswild(tmpbuf)) { + char *m; + errno = 0; + x = zchki(tmpbuf); + if (x < 0) { + switch (x) { + case -2: m = "Not a regular file"; break; + case -1: m = "File not found or not accessible"; break; + default: m = errno ? ck_errstr() : "Can't delete"; + } + printf("?%s: \"%s\"\n",m,tmpbuf); + return(-9); + } + } +#endif /* COMMENT */ + + makelist(del_exc,dxlist,8); + +/* tmpbuf[] has the name - now do any needed conversions on it */ + +#ifdef OS2 + { /* Lower level functions change / to \, not good for CMD.EXE. */ + char *p = tmpbuf; + while (*p) { /* Change them back to \ */ + if (*p == '/') *p = '\\'; + p++; + } + } +#endif /* OS2 */ + +#ifdef VMS + if (iswild(tmpbuf)) { +#ifdef COMMENT + /* Does not handle '.' as version separator */ + char *p = tmpbuf; + x = 0; + while (*p) { + if (*p == ';') { + x = 1; + break; + } else + p++; + } + if (!x) ckstrncat(tmpbuf,";*",TMPBUFSIZ); +#else + j = 0; x = 0; /* for end_dot and number of dots */ + i = strlen(tmpbuf); + if (tmpbuf[i] == ';') { + ckstrncat(tmpbuf,"0",TMPBUFSIZ); + } else { + if (tmpbuf[i--] == '.') + j++; + for (; i >= 0; i--) { + if (tmpbuf[i] == ';' || tmpbuf[i] == ':' || + tmpbuf[i] == ']' || tmpbuf[i] == '>') + break; + else if (tmpbuf[i] == '.') + x++; + } + if (tmpbuf[i] != ';') { /* dot may have been used */ + if (j) { /* last char is dot */ + if (x) /* second is version separator */ + ckstrncat(tmpbuf,"0",TMPBUFSIZ); + else /* 'foo.' */ + ckstrncat(tmpbuf,";0",TMPBUFSIZ); + } else if (x == 1) /* lacking a version separator */ + ckstrncat(tmpbuf,";0",TMPBUFSIZ); + else if (x == 0) /* x == 2 has a version */ + ckstrncat(tmpbuf,".*;0",TMPBUFSIZ); + } + } +#endif /* COMMENT */ + } +#endif /* VMS */ + + debug(F110,"dodel tmpbuf",tmpbuf,0); /* Filename */ + +#ifndef OS2ORUNIX /* No built-in DELETE code... */ + /* Construct system command. */ + ckmakmsg(line,LINBUFSIZ,DELCMD," ",tmpbuf,NULL); +#else +#ifdef VMS + if (asking) { /* Maybe overwrite in VMS */ + if (x_lis) /* if options are needed... */ + ckmakmsg(line,LINBUFSIZ,DELCMD," /confirm/log ",tmpbuf,NULL); + else + ckmakmsg(line,LINBUFSIZ,DELCMD," /confirm ",tmpbuf,NULL); + } else if (x_lis) + ckmakmsg(line,LINBUFSIZ,DELCMD," /log ",tmpbuf,NULL); + conres(); +#endif /* VMS */ + + debug(F110,"dodel line",line,0); +#endif /* OS2ORUNIX */ + +#ifdef MAC + success = (zdelet(tmpbuf) == 0); + +#else /* !MAC ... */ + +#ifdef OS2ORUNIX + { + int filespace = 0; + int count = 0; + int lines = 0; + int n = 0; + + s = tmpbuf; + +#ifdef CK_TTGWSIZ +#ifdef OS2 + ttgcwsz(); +#else /* OS2 */ + /* Check whether window size changed */ + if (ttgwsiz() > 0) { + if (tt_rows > 0 && tt_cols > 0) { + cmd_rows = tt_rows; + cmd_cols = tt_cols; + } + } +#endif /* OS2 */ +#endif /* CK_TTGWSIZ */ + + if (x_hdg > 0 && !summary) { + printf("Deleting %s...%s\n", s, simulate ? " (SIMULATION)" : ""); + n += 2; + } +#ifdef ZXREWIND + z = zxrewind(); /* Rewind file list */ +#else + if (!deldirs) + nzxopts = ZX_FILONLY; + if (recursive) nzxopts |= ZX_RECURSE; + if (matchdot) nzxopts |= ZX_MATCHDOT; + errno = 0; + z = nzxpand(s,nzxopts); /* Expand file list */ +#endif /* ZXREWIND */ + debug(F111,"dodel",s,z); + + /* If deleting directories, sort in reverse order */ + /* so we delete the files first, then the directory. */ + +#ifdef OS2 + /* In K95, we have no mtchs array, nor any control over */ + /* the order in which znext() returns filenames, so we */ + /* must copy the array and sort it. */ + { + int i; + if (xmtchs) { /* Free previous list in case */ + debug(F101,"dodel freeing previous list","",xmtchn); + for (i = 0; i < xmtchn; i++) /* it wasn't freed last time. */ + if (xmtchs[i]) + free(xmtchs[i]); + free(xmtchs); + } + xmtchn = 0; + xmtchs = (char **)malloc(z * (sizeof(char **))); /* Make new one */ + if (!xmtchs) { + printf("?Memory allocation failure\n"); + return(-9); + } + for (i = 0; i < z; i++) { + xmtchs[i] = NULL; + znext(tmpbuf); + if (!*tmpbuf) + break; + makestr(&(xmtchs[i]),tmpbuf); + if (!xmtchs[i]) { + printf("?Memory allocation failure\n"); + xmtchn = i - 1; + rc = -9; + goto xdelete; + } + /* debug(F111,"dodel add",xmtchs[i],i); */ + } + xmtchn = i; + debug(F101,"dodel xmtchn","",xmtchn); + sh_sort(xmtchs,NULL,z,0,deldirs,0); + } +#else +#ifdef UNIX + sh_sort(mtchs,NULL,z,0,deldirs,filecase); +#endif /* UNIX */ +#endif /* OS2 */ + + if (z > 0) { + int i; +#ifdef OS2 + int ix = 0; +#endif /* OS2 */ + success = 1; + if (x_hdg > 0) + printf("\n"); + + while ( +#ifdef OS2 + ix < xmtchn +#else + 1 +#endif /* OS2 */ + ) { /* Loop for all files */ +#ifdef OS2 + ckstrncpy(tmpbuf,xmtchs[ix++],TMPBUFSIZ); +#else + znext(tmpbuf); /* Get next file */ +#endif /* OS2 */ + if (!*tmpbuf) { /* No more */ + if (deldirs && recursive && argisdir) { + ckstrncpy(tmpbuf,safebuf,TMPBUFSIZ); + argisdir = 0; /* (only do this once) */ + } else + break; + } + skip = 0; + if (!deltree) { + if (fs) + if (fileselect(tmpbuf, + del_aft,del_bef,del_naf,del_nbf, + minsize,maxsize,0,8,dxlist) < 1) { + skip++; + } + } + if (!skip && scan && itsadir) { + skip++; + } + if (!skip && scan) { + switch (scanfile(tmpbuf,&y,nscanfile)) { + case FT_BIN: + if (xmode != 1) + skip++; + break; + case FT_TEXT: + case FT_7BIT: + case FT_8BIT: +#ifdef UNICODE + case FT_UTF8: + case FT_UCS2: +#endif /* UNICODE */ + if (xmode != 0) + skip++; + } + } + if (!skip && asking) { + int x; + ckmakmsg(line,LINBUFSIZ," Delete ",tmpbuf,"? ",NULL); + x = getyesno(line,3); + switch (x) { + case 0: continue; /* no */ + case 1: break; /* yes */ + case 2: goto xdelete; /* quit */ + case 3: asking = 0; break; /* go */ + } + } +#ifdef VMSORUNIX + len = zgetfs(tmpbuf); /* Get length and accessibility */ + itsadir = zgfs_dir; + if (itsadir && zgfs_link) { /* Treat links to directories */ + itsadir = 0; /* as regular files */ + if (scan) /* But not if /TYPE: was given */ + skip++; + } + if (itsadir) /* (emulate non-Unix code) */ + len = -2; +#else + len = zchki(tmpbuf); /* Get accessibility */ + if (len < 0) /* See if it's a directory */ + itsadir = isdir(tmpbuf); +#endif /* VMSORUNIX */ + + if (skip) { +#ifdef COMMENT /* Too verbose */ + if (x_lis > 0) { + lines++; + printf(" %s (SKIPPED)\n",tmpbuf); +#ifdef CK_TTGWSIZ + if (++n > cmd_rows - 3) + if (!askmore()) goto xdelete; else n = 0; +#endif /* CK_TTGWSIZ */ + } +#endif /* COMMENT */ + continue; + } + + debug(F111,"DELETE len",tmpbuf,len); + if (simulate) { + filespace += len; + count++; + if (x_lis > 0) { + lines++; + printf(" %s (SELECTED)\n",tmpbuf); + if (++n > cmd_rows - 3) { + int xx; + xx = askmore(); + if (!xx) goto xdelete; else n = 0; + } + } + } else if (len >= 0 || !itsadir) { /* Regular file */ + zdelet(tmpbuf); /* or symlink, etc... */ + if (zchki(tmpbuf) < 0) { + filespace += len; + count++; + if (x_lis > 0) { + lines++; + printf(" %s (OK)\n",tmpbuf); + if (++n > cmd_rows - 3) + if (!askmore()) goto xdelete; else n = 0; + } + } else { + bad++; + success = 0; + if (x_lis > 0) { + lines++; + printf(" %s (FAILED: %s)\n",tmpbuf,ck_errstr()); + if (++n > cmd_rows - 3) + if (!askmore()) goto xdelete; else n = 0; + } + } + } else if (/* pass > 0 && */ deldirs && itsadir) { + /* It's a directory */ + if (zrmdir(tmpbuf) > -1) { /* Only works if empty */ + count++; + if (x_lis > 0) { + lines++; + printf(" %s (OK)\n",tmpbuf); + if (++n > cmd_rows - 3) + if (!askmore()) goto xdelete; else n = 0; + } + } else { + success = 0; + if (x_lis > 0) { + lines++; + printf(" %s (FAILED: %s)\n", + tmpbuf, + ck_errstr()); + if (++n > cmd_rows - 3) + if (!askmore()) goto xdelete; else n = 0; + } + } + } else if (x_lis > 0) { + lines++; + if (isdir(tmpbuf)) + printf(" %s (FAILED: directory)\n",tmpbuf); + else + printf(" %s (FAILED: not a regular file)\n",tmpbuf); + if (++n > cmd_rows - 3) + if (!askmore()) goto xdelete; else n = 0; + } + } + if (x_hdg > 0) { + if (lines > 0) + printf("\n"); + if (++n > cmd_rows - 3) + if (!askmore()) goto xdelete; else n = 0; + printf("%d file%s %sdeleted, %d byte%s %sfreed%s\n", + count, + count != 1 ? "s" : "", + simulate ? "would be " : "", + filespace, + filespace != 1 ? "s" : "", + simulate ? "would be " : "", + simulate ? " (maybe)" : "" + ); + } + if (!x_lis && !success && !quiet) { + printf("?DELETE failed for %d file%s \ +(use DELETE /LIST to see details)\n", + bad, bad == 1 ? "" : "s" + ); + } + } else if (x_lis > 0) { + if (errno) + printf("?%s: %s\n",ck_errstr(), tmpbuf); + else + printf("?Can't delete: %s\n",tmpbuf); + } + } +#else /* OS2ORUNIX */ +#ifndef VMS /* Others - let the system do it. */ + xsystem(line); + x = nzxpand(tmpbuf,nzxopts); + success = (x > 0) ? 0 : 1; + if (x_hdg > 0) + printf("%s - %sdeleted\n", tmpbuf, success ? "" : "not "); +#else + if (asking) + printf("\n"); + x = xsystem(line); /* zshcmd returns 1 for success */ + success = (x > 0) ? 1 : 0; + if (x_hdg > 0 && !asking) + printf("%s - %sdeleted\n", tmpbuf, success ? "" : "not "); + concb((char)escape); +#endif /* VMS */ +#endif /* OS2ORUNIX */ +#endif /* MAC */ + xdelete: + if (g_matchdot > -1) { + matchdot = g_matchdot; /* Restore these... */ + g_matchdot = -1; + } +#ifdef OS2 + if (xmtchs) { + int i; + debug(F101,"dodel freeing list","",xmtchn); + for (i = 0; i < xmtchn; i++) + if (xmtchs[i]) free(xmtchs[i]); + free(xmtchs); + xmtchs = NULL; + xmtchn = 0; + } +#endif /* OS2 */ + debug(F101,"dodel result","",rc); + return((rc < 0) ? rc : success); +} +#endif /* NOFRILLS */ + +#ifndef NOSPL /* The ELSE command */ +_PROTOTYP( VOID pushqcmd, (char *) ); + +int +doelse() { + if (!ifcmd[cmdlvl]) { + printf("?ELSE doesn't follow IF\n"); + return(-2); + } +#ifdef COMMENT +/* + Wrong. This prevents IF..ELSE IF...ELSE IF...ELSE IF...ELSE... + from working. +*/ + ifcmd[cmdlvl] = 0; +#endif /* COMMENT */ + if (!iftest[cmdlvl]) { /* If IF was false do ELSE part */ + if (maclvl > -1 || tlevel > -1) { /* In macro or command file */ + debug(F100,"doelse pushing","",0); +#ifdef COMMENT + pushcmd(NULL); /* save rest of command. */ +#else + /* This fixes certain obscure problems */ + /* but breaks many other constructions that must work. */ + pushqcmd(NULL); +#endif /* COMMENT */ + } else { /* If interactive, */ + cmini(ckxech); /* just start a new command */ + printf("\n"); /* (like in MS-DOS Kermit) */ + if (pflag) prompt(xxstring); + } + } else { /* Condition is false */ + if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0) + return(y); /* Gobble up rest of line */ + } + return(0); +} +#endif /* NOSPL */ + +#ifndef NOSPL +int +doswitch() { + char *lp, *ap; /* Macro argument pointer */ + int len = 0, x, y, pp = 0; + char brbuf[3]; + + /* Get variable name */ + + tmpbuf[0] = NUL; + brbuf[0] = '{'; + brbuf[1] = '}'; + brbuf[2] = NUL; + + y = cmfld("Variable name","",&s,xxstring); + debug(F111,"doswitch cmfld",s,y); + if (y < 0) { + if (y == -3) /* Because brstrip() writes */ + s = brbuf; /* into its argument. */ + else + return(y); + } + debug(F110,"doswitch A",s,0); + if (!strcmp(s,"(")) { + pp++; + if ((y = cmfld("Variable name","",&s,xxstring)) < 0) { + if (y == -3) + s = brbuf; + else + return(y); + debug(F110,"doswitch B",s,0); + } + } + len = ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ); + if (tmpbuf[0] == CMDQ) { + if (chkvar(s) < 1) { + printf("?Variable name required\n"); + return(-9); + } + } + if (pp > 0) { /* If open paren given parse closing */ + if ((y = cmfld("Closing parenthesis","",&s,NULL)) < 0) + return(y); + if (strcmp(atmbuf,")")) { + printf("?Closing parenthesis required\n"); + return(-9); + } + } + lp = line; + x = ckstrncpy(lp,"_switx ",LINBUFSIZ); /* _switx + space */ + lp += x; + ap = lp; + debug(F010,"SWITCH a",line,0); + +#ifdef COMMENT + x = ckmakmsg(lp,LINBUFSIZ-x,tmpbuf," ",NULL,NULL); /* variable name + SP */ +#else + { /* variable name + SP */ + char * p = tmpbuf; + if (len > 0) { + if (tmpbuf[0] == '(' && tmpbuf[len-1] == ')') { + tmpbuf[len-1] = NUL; + p++; + } + } + x = ckmakmsg(lp,LINBUFSIZ-x,"{",brstrip(p),"}"," "); + } +#endif /* COMMENT */ + debug(F010,"SWITCH b",line,0); + lp += x; + + /* Get body */ + + if ((y = cmtxt("series of cases","",&s,NULL)) < 0) return(y); + if ((y = (int)strlen(s)) < 1) return(-2); + if (s[0] != '{' && s[y-1] != '}') { /* Supply braces if missing */ + ckmakmsg(tmpbuf,TMPBUFSIZ,"{ ",s," }",NULL); + s = tmpbuf; + } + if (litcmd(&s,&lp,(LINBUFSIZ - (lp - (char *)line) - 2)) < 0) { + printf("?Unbalanced braces\n"); + return(0); + } + debug(F010,"SWITCH c",line,0); + + x = mlook(mactab,"_switx",nmac); /* Look up SWITCH macro definition */ + if (x < 0) { /* Not there? */ + addmmac("_switx",sw_def); /* Put it back. */ + if ((x = mlook(mactab,"_switx",nmac)) < 0) { /* Look it up again. */ + printf("?SWITCH macro definition gone!\n"); /* Shouldn't happen. */ + return(success = 0); + } + } + debug(F010,"SWITCH command",line,0); /* Execute the SWITCH macro. */ + success = dodo(x,ap,cmdstk[cmdlvl].ccflgs | CF_IMAC); + debug(F101,"SWITCH status","",success); + return(success); +} + +int +dofor() { /* The FOR command. */ + int i, fx, fy, fz; /* loop variables */ + char *ap, *di; /* macro argument pointer */ + int pp = 0; /* Paren level */ + int mustquote = 0; + + for (i = 0; i < 2; i++) { + if ((y = cmfld("Variable name","",&s,NULL)) < 0) { + if (y == -3) { + printf("?Variable name required\n"); + return(-9); + } else + return(y); + } + if (strcmp(s,"(")) + break; + pp++; + } +#ifdef COMMENT + if ((y = parsevar(s,&x,&z)) < 0) /* Check variable. */ + return(y); +#else + if (*s == CMDQ) /* If loop variable starts with */ + mustquote++; /* backslash, mustquote is > 0. */ +#endif /* COMMENT */ + + lp = line; /* Build a copy of the command */ + ckstrncpy(lp,"_forx ",LINBUFSIZ); + lp += (int)strlen(line); /* "_for" macro. */ + ap = lp; /* Save pointer to macro args. */ + + if (*s == CMDQ) s++; /* Skip past backslash if any. */ + while ((*lp++ = *s++)) ; /* copy it */ + lp--; *lp++ = SP; /* add a space */ + + if ((y = cmnum("initial value","",10,&fx,xxstring)) < 0) { + if (y == -3) return(-2); + else return(y); + } + debug(F101,"dofor fx","",fx); + s = atmbuf; /* Copy the atom buffer */ + + if ((int)strlen(s) < 1) goto badfor; +/* + In edit 192, we change the loop variables to be evaluated at loop entry, + not each time through the loop. This was required in order to allow + \v(argc) to be used as a loop variable, or in a loop-variable expression. + Thus, we can't have FOR loops that modify their own exit conditions by + changing the final value or the increment. The problem with \v(argc) was + that it is on the macro stack; after entry into the _forx macro, it is at + the wrong place. +*/ + sprintf(tmpbuf,"%d",fx); /* (SAFE) Substitute actual value */ + s = tmpbuf; + while ((*lp++ = *s++)) ; /* (what they actually typed) */ + lp--; *lp++ = SP; +#ifdef DEBUG + *lp = NUL; + debug(F110,"FOR A",line,0); +#endif /* DEBUG */ + + if ((y = cmnum("final value","",10,&fy,xxstring)) < 0) { + if (y == -3) return(-2); + else return(y); + } + debug(F101,"dofor fy","",fy); + s = atmbuf; /* Same deal */ + if ((int)strlen(s) < 1) + goto badfor; + + sprintf(tmpbuf,"%d",fy); /* SAFE */ + s = tmpbuf; + while ((*lp++ = *s++)) ; + lp--; + *lp++ = SP; +#ifdef DEBUG + *lp = NUL; + debug(F110,"FOR B",line,0); +#endif /* DEBUG */ + + x_ifnum = 1; /* Increment or parenthesis */ + di = (fx < fy) ? "1" : "-1"; /* Default increment */ + if ((y = cmnum("increment",di,10,&fz,xxstring)) < 0) { + debug(F111,"dofor increment",atmbuf,y); + x_ifnum = 0; + if (y == -3) { /* Premature termination */ + return(-2); + } else if (y == -2) { /* Maybe closing paren */ + if (!strcmp(atmbuf,")")) { + pp--; /* Count it */ + s = di; /* supply default interval */ + fz = atoi(s); + } else /* Not closing paren, invalid */ + return(y); + } else /* Other error */ + return(y); + } else { /* Number */ + x_ifnum = 0; + debug(F101,"dofor fz","",fz); + s = atmbuf; /* Use it */ + } + if ((int)strlen(s) < 1) + goto badfor; + + sprintf(tmpbuf,"%d",fz); /* (SAFE) Same deal */ + s = tmpbuf; + while ((*lp++ = *s++)) ; + lp--; *lp++ = SP; + +#ifdef DEBUG + *lp = NUL; + debug(F110,"FOR C",line,0); +#endif /* DEBUG */ + + /* Insert the appropriate comparison operator */ + if (fz < 0) + *lp++ = '<'; + else + *lp++ = '>'; + *lp++ = SP; + +#ifdef DEBUG + *lp = NUL; + debug(F110,"FOR D",line,0); +#endif /* DEBUG */ + + if (pp > 0) { /* If open paren given parse closing */ + if ((y = cmfld("Closing parenthesis","",&s,NULL)) < 0) + return(y); + if (strcmp(atmbuf,")")) { + printf("?Closing parenthesis required\n"); + return(-9); + } + } + if ((y = cmtxt("Command to execute","",&s,NULL)) < 0) return(y); + if ((y = (int)strlen(s)) < 1) return(-2); + if (s[0] != '{' && s[y-1] != '}') { /* Supply braces if missing */ + ckmakmsg(tmpbuf,TMPBUFSIZ,"{ ",s," }",NULL); + s = tmpbuf; + } + if (litcmd(&s,&lp,(LINBUFSIZ - (lp - (char *)line) - 2)) < 0) { + printf("?Unbalanced braces\n"); + return(0); + } +#ifdef DEBUG + *lp = NUL; + debug(F110,"FOR E",line,0); +#endif /* DEBUG */ + +#ifdef COMMENT +/* Too strict */ + if (fz == 0) { + printf("?Zero increment not allowed\n"); + return(0); + } +#endif /* COMMENT */ +/* + In version 8.0 we decided to allow macro names anyplace a numeric-valed + variable could appear. But this caused trouble for the FOR loops because + the quoting in for_def[] assumed a \%i-style loop variable. We account + for this here in the if (mustquote)...else logic by invoking separate + FOR macro definitions in the two cases. +*/ + if (mustquote) { /* \%i-style loop variable */ + x = mlook(mactab,"_forx",nmac); /* Look up FOR macro definition */ + if (x < 0) { /* Not there? */ + addmmac("_forx",for_def); /* Put it back. */ + if ((x = mlook(mactab,"_forx",nmac)) < 0) { /* Look it up again. */ + printf("?FOR macro definition gone!\n"); + return(success = 0); + } + } + } else { /* Loop variable is a macro */ + x = mlook(mactab,"_forz",nmac); + if (x < 0) { + addmmac("_forz",foz_def); + if ((x = mlook(mactab,"_forz",nmac)) < 0) { + printf("?FOR macro definition gone!\n"); + return(success = 0); + } + } + } + debug(F010,"FOR command",line,0); /* Execute the FOR macro. */ + return(success = dodo(x,ap,cmdstk[cmdlvl].ccflgs | CF_IMAC)); + +badfor: + printf("?Incomplete FOR command\n"); + return(-2); +} +#endif /* NOSPL */ + +#ifndef NOFRILLS +/* Do the BUG command */ + +int +dobug() { + int n; + char * s = ""; + extern char * k_info_dir; + + if (k_info_dir) + s = k_info_dir; + +#ifdef COMMENT + printf("\n%s,%s\n Numeric: %ld",versio,ckxsys,vernum); +#endif /* COMMENT */ + printf( +"\nBefore requesting technical support from Columbia U., please consult:\n\n" + ); + n = 7; +#ifdef OS2 + printf(" . Your \"Kermit 95\" user manual (use the MANUAL command).\n"); + printf(" . The technical reference manual, \"Using C-Kermit\".\n"); + n += 2; +#else + printf(" . The book \"Using C-Kermit\" (type HELP for more info).\n"); + n += 1; +#endif /* OS2 */ + + printf(" . Your own organization's support staff, if any.\n"); + printf( +" . The comp.protocols.kermit.misc newsgroup.\n"); + printf( +" . The Kermit support website, http://www.columbia.edu/kermit/support.html \n" + ); + printf( + +" . The Kermit FAQ, http://www.columbia.edu/kermit/newfaq.html \n"); +#ifdef OS2 + printf( +" . The Kermit 95 FAQ, http://www.columbia.edu/kermit/k95faq.html \n"); + n++; +#endif /* OS2 */ + + printf( +" . The C-Kermit FAQ, http://www.columbia.edu/kermit/ckfaq.html \n"); + n += 4; + if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; + printf("\n\ +If you still need help or have a bug to report after consulting these sources," + ); + printf("\nsend e-mail to:\n\n"); + n += 2; + if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; + printf(" mailto:kermit-support@columbia.edu\n\n"); + n += 1; + if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; + printf("Or contact us by post:\n\n"); + printf( +" Kermit, Columbia University, 612 W 115 Street, New York NY 10025, USA\n\n" + ); + n += 1; + if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; + printf("Or by fax at +1 (212) 662-6442.\n\n"); + n += 1; + if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; +#ifdef COMMENT + printf("Telephone support is available too:\n\n"); + n += 1; + if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; + printf( + " +1 (212) 854-5126, from anywhere, $25.00 USD per call, MC/Visa\n\n"); + n += 1; + if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; +#endif /* COMMENT */ +#ifndef NOSHOW +#ifndef NOFRILLS + printf( +"Before reporting problems, please use the SHOW FEATURES command\n"); + if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; + printf( +"to get detailed program version and configuration information.\n\n"); +#endif /* NOFRILLS */ +#endif /* NOSHOW */ + return(1); +} +#endif /* NOFRILLS */ + +#ifndef NOSPL + +/* T O D 2 S E C -- Convert time of day as hh:mm:ss to secs since midnite */ +/* + Call with a string hh:mm or hh:mm:ss. + Returns a 0 to 86400 on success, or a negative number on failure. +*/ +long +tod2sec(t) char * t; { + long t2; + long hh = 0L, mm = 0L, ss = 0L; + + if (!t) t = ""; + if (!*t) + return(-3L); + debug(F110,"tod2sec",t,0); + + if (isdigit(*t)) /* Get hours from argument */ + hh = *t++ - '0'; + else + return(-1L); + if (isdigit(*t)) + hh = hh * 10 + *t++ - '0'; +#ifdef COMMENT + if (hh > 24L) + return(-1L); +#endif /* COMMENT */ + if (*t == ':') + t++; + else if (!*t) + goto xtod2sec; + else + return(-1L); + + if (isdigit(*t)) /* Minutes */ + mm = *t++ - '0'; + else + return(-1L); + if (isdigit(*t)) + mm = mm * 10 + *t++ - '0'; + if (mm > 60L) + return(-1L); + if (*t == ':') + t++; + else if (!*t) + goto xtod2sec; + else + return(-1L); + + if (isdigit(*t)) /* Seconds */ + ss = *t++ - '0'; + else + return(-1L); + if (isdigit(*t)) + ss = ss * 10 + *t++ - '0'; + if (ss > 60L) + return(-1L); + + if (*t > 32) /* No trailing junk allowed */ + return(-1L); + + xtod2sec: + + t2 = hh * 3600L + mm * 60L + ss; /* Seconds since midnight from arg */ + debug(F101,"tod2sec t2","",t2); + + return(t2); +} + +int waitinterval = 1; + +#ifdef OLDWAIT +#undef OLDWAIT +#endif /* OLDWAIT */ + +int kbchar = NUL; + +int +dopaus(cx) int cx; { + long zz; + extern int sleepcan; + +#ifdef OLDWAIT + zz = -1L; + x_ifnum = 1; /* Turn off internal complaints */ + if (cx == XXWAI) + y = cmnum("seconds to wait, or time of day hh:mm:ss","1",10,&x,xxstring); + else if (cx == XXPAU) + y = cmnum("seconds to pause, or time of day hh:mm:ss", + "1",10,&x,xxstring); + else + y = cmnum("milliseconds to sleep, or time of day hh:mm:ss", + "100",10,&x,xxstring); + x_ifnum = 0; + if (y < 0) { + if (y == -2) { /* Invalid number or expression */ + char *p = tmpbuf; /* Retrieve string from atmbuf */ + int n = TMPBUFSIZ; + *p = NUL; + zzstring(atmbuf,&p,&n); /* Evaluate in case it's a variable */ + zz = tod2sec(tmpbuf); /* Convert to secs since midnight */ + if (zz < 0L) { + printf("?Number, expression, or time of day required\n"); + return(-9); + } else { + char now[32]; /* Current time */ + char *p; + long tnow; + p = now; + ztime(&p); + tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17); + if (zz < tnow) /* User's time before now */ + zz += 86400L; /* So make it tomorrow */ + zz -= tnow; /* Seconds from now. */ + } + } else + return(y); + } + if (x < 0) x = 0; + switch (cx) { + case XXPAU: /* PAUSE */ + case XXMSL: /* MSLEEP */ + if ((y = cmcfm()) < 0) return(y); + break; + case XXWAI: /* WAIT */ + z = 0; /* Modem signal mask */ + while (1) { /* Read zero or more signal names */ + y = cmkey(mstab,nms,"modem signal","",xxstring); + if (y == -3) break; /* -3 means they typed CR */ + if (y < 0) return(y); /* Other negatives are errors */ + z |= y; /* OR the bit into the signal mask */ + } + if ((y = cmcfm()) < 0) return(y); + break; + + default: /* Shouldn't happen */ + return(-2); + } + +/* Command is entered, now do it. */ + + if (zz > -1L) { /* Time of day given? */ + x = zz; + if (zz != (long) x) { + printf( +"Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n" + ); + return(-9); + } + } + if (cx == XXMSL) { /* Millisecond sleep */ + msleep(zz < 0 ? x : x * 1000); + return(success = 1); + } + if (cx == XXPAU && !sleepcan) { /* SLEEP CANCELLATION is OFF */ + sleep(x); + return(success = 1); + } + + /* WAIT, or else SLEEP with cancellation allowed... */ + + do { /* Sleep loop */ + int mdmsig; + if (sleepcan) { /* Keyboard cancellation allowed? */ + if (y = conchk()) { /* Did they type something? */ +#ifdef COMMENT + while (y--) coninc(0); /* Yes, gobble it all up */ +#else + /* There is a debate over whether PAUSE should absorb */ + /* its cancelling character(s). There are several */ + /* reasons why it should gobble at least one character: */ + /* (1) MS-DOS Kermit does it */ + /* (2) if not, subsequent PAUSE commands will terminate */ + /* immediately */ + /* (3) if not, subsequent ASK commands will use it as */ + /* valid input. If \13, then it will get no input */ + /* (4) if not, then the character appears on the command */ + /* line after all enclosing macros are complete. */ + kbchar = coninc(0); /* Gobble one up */ +#endif /* COMMENT */ + break; /* And quit PAUSing or WAITing */ + } + } + if (cx == XXWAI) { /* WAIT (z == modem signal mask) */ + debug(F101,"WAIT x","",x); + if (z > 0) { /* Looking for any modem signals? */ + mdmsig = ttgmdm(); /* Yes, get them */ + if (mdmsig < 0) /* Failed */ + return(success = 0); + if ((mdmsig & z) == z) /* Got what we wanted? */ + return(success = 1); /* Succeed */ + } + if (x == 0) /* WAIT 0 and didn't get our signals */ + break; + } + sleep(1); /* No interrupt, sleep one second */ + } while (--x > 0); + + if (cx == XXWAI) /* If WAIT and loop exhausted */ + success = (z == 0); /* Fail. */ + else /* */ + success = (x == 0); /* Set SUCCESS/FAILURE for PAUSE. */ + return(success); + +#else /* New code uses chained FDBs and allows FILE waits... */ + + char * m = ""; /* Help message */ + struct FDB nu, fl; /* Parse function descriptor blocks */ + int filewait = 0; + int mdmsig = 0, fs = 0; + char filedate[32]; + + kbchar = 0; + + switch (cx) { + case XXWAI: m = "seconds to wait, or time of day hh:mm:ss"; break; + case XXPAU: m = "seconds to pause, or time of day hh:mm:ss"; break; + case XXMSL: m = "milliseconds to sleep, or time of day hh:mm:ss"; break; + } + zz = -1L; + cmfdbi(&nu, + _CMNUM, /* Number */ + m, /* Help message */ + (cx == XXMSL) ? "100" : "1", /* Default */ + "", /* N/A */ + 0, /* N/A */ + 0, /* N/A */ + xxstring, /* Processing function */ + NULL, /* N/A */ + &fl /* Next */ + ); + cmfdbi(&fl, /* Time of day */ + _CMFLD, /* Field */ + "", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + 0, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ + xxstring, /* processing func */ + NULL, /* N/A */ + NULL /* No next */ + ); + x = cmfdb(&nu); /* Parse a number or a field */ + if (x < 0) { + if (x == -3) + x = -2; + return(x); + } + switch (cmresult.fcode) { + case _CMNUM: /* Number */ + x = cmresult.nresult; + break; + case _CMFLD: /* Field */ + zz = tod2sec(cmresult.sresult); /* Convert to secs since midnight */ + if (zz < 0L) { + printf("?Number, expression, or time of day required\n"); + return(-9); + } else { + char now[32]; /* Current time */ + char *p; + long tnow; + p = now; + ztime(&p); + tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17); + if (zz < tnow) /* User's time before now */ + zz += 86400L; /* So make it tomorrow */ + zz -= tnow; /* Seconds from now. */ + } + } + debug(F101,"PAUSE/WAIT/MSLEEP zz","",zz); + switch (cx) { + case XXPAU: /* PAUSE */ + case XXMSL: /* MSLEEP */ + if ((y = cmcfm()) < 0) return(y); + break; + case XXWAI: /* WAIT */ + z = 0; /* Modem signal mask */ + y = cmkey(waittab,nwaittab,"","",xxstring); + if (y < 0) { + if (y == -3) { + if ((y = cmcfm()) < 0) + return(y); + break; + } else + return(y); + } + if (y == WAIT_FIL) { /* FILE */ + int wild = 0; + if ((z = cmkey(wfswi,nwfswi,"event","",xxstring)) < 0) + return(z); + filewait = z; + if (filewait == WF_MOD || filewait == WF_DEL) + z = cmifi("Filename","",&s,&wild,xxstring); + else + z = cmfld("Filename","",&s,xxstring); + if (z < 0) + return(z); + if (wild || ((filewait == WF_CRE) && iswild(s))) { + printf("?Wildcards not valid here\n"); + return(-9); + } + ckstrncpy(tmpbuf,s,TMPBUFSIZ); + if ((z = cmcfm()) < 0) + return(z); + break; + } else if (y != WAIT_MDM) { /* A modem signal */ + z |= y; /* OR the bit into the signal mask */ + } + if (!filewait) { /* Modem signals... */ + while (1) { /* Get zero or more signal names */ + y = cmkey(mstab,nms,"modem signal","",xxstring); + if (y == -3) break; /* -3 means they typed CR */ + if (y < 0) return(y); /* Other negatives are errors */ + z |= y; /* OR the bit into the signal mask */ + } + if ((y = cmcfm()) < 0) return(y); + break; + } + + default: /* Shouldn't happen */ + return(-2); + } /* switch (cx) */ + +/* Command is entered, now do it. */ + + if (zz > -1L) { /* Time of day given? */ + x = zz; + if (zz != (long) x) { + printf( +"Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n" + ); + return(-9); + } + } + if (sleepcan) + concb((char)escape); /* Ensure single-char wakeup */ + + if (cx == XXMSL) { /* Millisecond sleep */ + msleep(zz < 0 ? x : x * 1000); + return(success = 1); + } + if (cx == XXPAU && !sleepcan) { /* SLEEP CANCELLATION is OFF */ + sleep(x); + return(success = 1); + } + if (filewait) { /* FILE... */ + fs = zchki(tmpbuf); /* Check if file exists */ + switch (filewait) { + case WF_DEL: + if (fs == -1) + return(success = 1); + break; + case WF_MOD: + if (fs == -1) { + printf("?File does not exit: %s\n",tmpbuf); + return(-9); + } + s = zfcdat(tmpbuf); /* Get current modification date */ + if (!s) s = ""; + if (ckstrncpy(filedate,s,32) != 17) { + printf("?Can't get modification time: %s\n",tmpbuf); + return(-9); + } + break; + case WF_CRE: + if (fs > -1) + return(success = 1); + break; + } + } + do { /* Polling loop */ + if (sleepcan) { /* Keyboard cancellation allowed? */ + if ((y = conchk()) > 0) { /* Did they type something? */ + kbchar = coninc(0); /* Yes, get first char they typed */ + debug(F000,"WAIT kbchar","",kbchar); +#ifdef COMMENT + while (--y > 0) /* Gobble the rest up */ + coninc(0); +#endif /* COMMENT */ + return(success = 0); /* And quit PAUSing or WAITing */ + } + } + if (filewait == 0) { + if (cx == XXWAI) { /* WAIT for modem signals */ + if (z != 0) { + mdmsig = ttgmdm(); /* Get them. */ + debug(F101,"WAIT ttgmdm","",mdmsig); + if (mdmsig < 0) /* Failure to get them? */ + return(success = 0); /* Fail. */ + if ((mdmsig & z) == z) /* Got desired ones? */ + return(success = 1); /* Succeed. */ + } else if (x == 0) + return(success = 0); + } + } else { /* FILE... */ + fs = zchki(tmpbuf); /* Get file status */ + if (filewait == WF_MOD) { /* Wait for modification */ + if (fs == -1) /* Failure to get status */ + return(success = 0); /* so WAIT fails. */ + s = zfcdat(tmpbuf); /* Get current modification time */ + if (!s) s = ""; /* And compare with the time */ + if (strcmp(s,filedate)) /* when the WAIT started */ + return(success = 1); + } else if (filewait == WF_DEL) { /* Wait for deletion */ + if (fs == -1) /* If file doesn't exist, */ + return(success = 1); /* succeed. */ + } else if (filewait == WF_CRE) { /* Wait for creation */ + if (fs != -1) /* If file exists */ + return(success = 1); /* succeed. */ + } + } + if (x < 1) /* SLEEP/WAIT/PAUSE 0 */ + break; + sleep(waitinterval); /* No interrupt, sleep */ + x -= waitinterval; /* Deduct sleep time */ + } while (x > 0); + + if (cx == XXWAI) /* WAIT time expired */ + success = (z == 0); /* Succeed if no modem signals */ + else /* For SLEEP or PAUSE, success */ + success = (x == 0); /* depends on whether it was */ + return(success); /* interrupted from the keyboard. */ +#endif /* OLDWAIT */ +} +#endif /* NOSPL */ + +#ifdef OS2ORUNIX +_PROTOTYP(int zcmpfn,(char *, char *)); +#endif /* OS2ORUNIX */ + +#ifndef NOFRILLS +#ifdef NT +int +dolink() { + /* Parse a file or a directory name */ + int i, x, z, listing = 0, havename = 0, wild = 0, rc = 1; + struct FDB sw, fi; + + cmfdbi(&sw, /* 2nd FDB - optional /PAGE switch */ + _CMKEY, /* fcode */ + "Filename or switch", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + nqvswtab, /* addtl numeric data 1: tbl size */ + 4, /* addtl numeric data 2: 4 = cmswi */ + xxstring, /* Processing function */ + qvswtab, /* Keyword table */ + &fi /* Pointer to next FDB */ + ); + + cmfdbi(&fi, /* 1st FDB - file to type */ + _CMIFI, /* fcode */ + "", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + 3, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ + xxstring, + NULL, + NULL + ); + + while (!havename) { + x = cmfdb(&sw); /* Parse something */ + if (x < 0) /* Error */ + return(x); + switch (cmresult.fcode) { + case _CMKEY: + switch (cmresult.nresult) { + case DEL_LIS: + case DEL_VRB: + listing = 1; + break; + case DEL_NOL: + case DEL_QUI: + listing = 0; + break; + } + break; + case _CMIFI: + s = cmresult.sresult; + havename = 1; + break; + default: + return(-2); + } + } + wild = cmresult.nresult; /* Source specification wild? */ + + ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy of source name */ + s = line; + + if (!wild) + wild = iswild(line); + + p = tmpbuf; /* Place for new name */ + if ((x = cmofi(wild ? "Target directory" : "New name", + "",&s,xxstring)) < 0) { /* Get new name */ + if (x == -3) { + printf("?%s required\n", wild ? "Target directory" : "New name"); + return(-9); + } else return(x); + } + ckstrncpy(p,s,TMPBUFSIZ); /* Make a safe copy of the new name */ + if ((y = cmcfm()) < 0) return(y); + + if (!wild) { /* Just one */ + if (listing) printf("%s => %s ",line,p); + if (zlink(line,p) < 0) { + if (listing) printf("(FAILED: %s\n",ck_errstr()); + rc = 0; + } else { + if (listing) printf("(OK)\n"); + } + return(success = rc); + } + if (!isdir(p)) { /* Multiple */ + printf( /* if target is not a directory */ +"?Multiple source files not allowed if target is not a directory.\n"); + return(-9); + } +#ifdef COMMENT + else { /* Show full path of target */ + char buf[CKMAXPATH]; /* (too much) */ + if (zfnqfp(p,CKMAXPATH,buf)) + ckstrncpy(tmpbuf,buf,TMPBUFSIZ); + } +#endif /* COMMENT */ + +#ifdef VMS + conres(); /* Let Ctrl-C work. */ +#endif /* VMS */ + debug(F110,"dolink line",line,0); + +#ifdef ZXREWIND + z = zxrewind(); /* Rewind file list */ +#else + z = nzxpand(s,0); /* Expand file list */ +#endif /* ZXREWIND */ + debug(F111,"dolink p",p,z); + +#ifdef UNIX + if (wild && z > 1) + sh_sort(mtchs,NULL,z,0,0,filecase); /* Alphabetize the filename list */ +#endif /* UNIX */ + + while (z-- > 0) { + if (!(z == 0 && !wild)) + znext(line); + if (!line[0]) + break; + if (listing) printf("%s => %s ",line,p); + if (zlink(line,p) < 0) { + if (listing) printf("(FAILED: %s\n",ck_errstr()); + rc = 0; + } else { + if (listing) printf("(OK)\n"); + } + } +#ifdef VMS + concb((char)escape); +#endif /* VMS */ + return(success = rc); +} +#endif /* NT */ + +#ifdef ZCOPY +int +docopy() { + int i, x, listing = 0, nolist = 0, havename = 0; + struct FDB sw, fi; + int targetisdir = 0; + int targetlen = 0; + int swapping = 0; + int appending = 0; + int fromb64 = 0; + int tob64 = 0; + int wild = 0; + int rc = 1; + + cmfdbi(&sw, /* 2nd FDB - optional /PAGE switch */ + _CMKEY, /* fcode */ + "Filename or switch", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + ncopytab, /* addtl numeric data 1: tbl size */ + 4, /* addtl numeric data 2: 4 = cmswi */ + xxstring, /* Processing function */ + copytab, /* Keyword table */ + &fi /* Pointer to next FDB */ + ); + cmfdbi(&fi, /* 1st FDB - file to type */ + _CMIFI, /* fcode */ + "", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + 0, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ + xxstring, + NULL, + NULL + ); + + while (!havename) { + x = cmfdb(&sw); /* Parse something */ + if (x < 0) /* Error */ + return(x); + switch (cmresult.fcode) { + case _CMKEY: + switch (cmresult.nresult) { + case DEL_LIS: + case DEL_VRB: + nolist = 0; + listing = 1; + break; + case DEL_NOL: + case DEL_QUI: + nolist = 1; + listing = 0; + break; + case 999: + swapping = 1; + break; + case 998: + appending = 1; + break; +#ifndef NOSPL + case 997: + fromb64 = 1; + break; + case 996: + tob64 = 1; + break; +#endif /* NOSPL */ + } + break; + case _CMIFI: + s = cmresult.sresult; + havename = 1; + break; + default: + return(-2); + } + } + wild = cmresult.nresult; + ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy of source name */ + s = line; + p = tmpbuf; /* Place for new name */ + + /* Get destination name */ + if ((x = cmofi("destination name and/or directory", +#ifdef UNIX + "." +#else + "" +#endif /* UNIX */ + ,&s,xxstring)) < 0) { + if (x == -3) { + printf("?Name for destination file required\n"); + return(-9); + } else return(x); + } + ckstrncpy(p,s,TMPBUFSIZ); /* Safe copy of destination name */ + if ((y = cmcfm()) < 0) return(y); + if (appending && swapping) { + printf("?Sorry, /APPEND and /SWAP conflict\n"); + return(-9); + } +#ifdef COMMENT +/* + This unreasonably prevented "COPY /APPEND *.* bifile" from concatenating + a bunch of files into one big file. +*/ + if (appending && wild) { + printf("?Sorry, /APPEND can be used only with single files\n"); + return(-9); + } +#endif /* COMMENT */ + targetisdir = isdir(p); + x = strlen(p); + if (targetisdir) { +#ifdef UNIXOROSK + if (p[x-1] != '/') { + ckstrncat(p,"/",TMPBUFSIZ); + x++; + } +#else +#ifdef OS2 + if (p[x-1] != '/') { + ckstrncat(p,"/",TMPBUFSIZ); + x++; + } +#else +#ifdef STRATUS + if (p[x-1] != '>') { + ckstrncat(p,">",TMPBUFSIZ); + x++; + } +#else +#ifdef datageneral + if (p[x-1] != ':') { + ckstrncat(p,":",TMPBUFSIZ); + x++; + } +#else + if (p[x-1] != '/') { + ckstrncat(p,"/",TMPBUFSIZ); + x++; + } +#endif /* datageneral */ +#endif /* STRATUS */ +#endif /* OS2 */ +#endif /* UNIXOROSK */ + } + targetlen = x; + + if (!appending) { /* If /APPEND not given */ + if (wild && !targetisdir) { /* No wildcards allowed */ + printf( /* if target is not a directory */ +"?Multiple source files not allowed if target is not a directory.\n"); + return(-9); + } + } + +#ifdef VMS + conres(); /* Let Ctrl-C work. */ +#endif /* VMS */ + debug(F110,"docopy line",line,0); + debug(F110,"docopy p",p,0); + +#ifdef ZXREWIND + z = zxrewind(); /* Rewind file list */ +#else + z = nzxpand(s,0); /* Expand file list */ +#endif /* ZXREWIND */ + +#ifdef UNIX + if (wild) + sh_sort(mtchs,NULL,z,0,0,filecase); /* Alphabetize the filename list */ +#endif /* UNIX */ + +#ifdef IKSD + if (!targetisdir && zchki(p) > -1) { /* Destination file exists? */ + if (inserver && (!ENABLED(en_del) +#ifdef CK_LOGIN + || isguest +#endif /* CK_LOGIN */ + )) { + printf("?Sorry, overwriting existing files is disabled\n"); + return(-9); + } + } +#endif /* IKSD */ + + if (tob64 && fromb64) { /* To and from B64 = no conversion */ + tob64 = 0; + fromb64 = 0; + } + debug(F110,"COPY dest",p,0); + + while (z > 0) { + + znext(line); + if (!line[0]) + break; + + errno = 0; /* Reset errno */ + + if (listing) printf("%s => %s ",line,p); + + /* Straight copy */ + if (!swapping && !appending && !fromb64 && !tob64) { + debug(F110,"COPY zcopy",line,0); + + if ((x = zcopy(line,p)) < 0) { /* Let zcopy() do it. */ + switch (x) { + case -2: + if (listing) + printf("(FAILED: Not a regular file)\n"); + else if (!nolist) + printf("?Not a regular file - %s\n",line); + rc = 0; + break; + case -3: + if (listing) + printf("(FAILED: Not found or not accessible)\n"); + else if (!nolist) + printf("?Not found or not accessible - %s\n",line); + rc = 0; + break; + case -4: + if (listing) + printf("(FAILED: Permission denied)\n"); + else if (!nolist) + printf("?Permission denied - %s\n",line); + rc = 0; + break; + case -5: + if (listing) + printf("(Source and destination are the same file)\n"); + else if (!nolist) + printf( + "?Source and destination are the same file - %s\n", + line + ); + break; + case -6: + if (listing) + printf("(FAILED: Input/Output error)\n"); + else if (!nolist) + printf("?Input/Output error - %s\n",line); + rc = 0; + break; + case -7: + if (listing) + printf("(FAILED: %s - %s)\n",p,ck_errstr()); + else if (!nolist) + printf("?%s - %s\n",ck_errstr(),p); + rc = 0; + break; + default: + if (listing) + printf("(FAILED: %s)\n",ck_errstr()); + else if (!nolist) + printf("?%s\n",ck_errstr()); + rc = 0; + } + } else { + if (listing) printf("(OK)\n"); + } + + } else { /* Special options */ + + int prev, y, x = 0; /* Variables needed for them */ + int i, t; + char ibuf[100]; + char obuf[200]; + FILE * in = NULL; + FILE * out = NULL; + + if ((in = fopen(line,"r")) == NULL) { /* Open input file */ + if (listing) + printf("(FAILED: %s)\n",ck_errstr()); + else if (!nolist) + printf("?%s - %s)\n",ck_errstr(),line); + rc = 0; + continue; + } + if (targetisdir) { /* Target is directory */ + char * buf = NULL; /* so append this filename to it */ + zstrip(line,&buf); + p[targetlen] = NUL; + if (buf) + ckstrncat(p,buf,TMPBUFSIZ); + } +#ifdef OS2ORUNIX + if (zcmpfn(line,p)) { /* Input and output are same file? */ + if (listing) + printf("(FAILED: Source and destination identical)\n"); + else if (!nolist) + printf("?Source and destination identical - %s\n", line); + rc = 0; + continue; + } +#endif /* OS2ORUNIX */ + if ((out = fopen(p, (appending ? "a" : "w"))) == NULL) { + fclose(in); + if (listing) + printf("(FAILED: %s - %s)\n",p,ck_errstr()); + else if (!nolist) + printf("?%s - %s\n",p,ck_errstr()); + rc = 0; + continue; + } +#ifndef NOSPL + if (tob64) { /* Converting to Base-64 */ + + debug(F110,"COPY tob64",line,0); + + while (1) { /* Loop... */ + prev = x; + if ((x = fread(ibuf,1,54,in)) < 1) { /* EOF */ + if (listing) + printf("(OK)\n"); + break; + } + if (prev % 3) { + if (listing) + printf("(FAILED: Phase error at %d)\n",prev); + else if (!nolist) + printf("?Phase error at %d\n",prev); + rc = 0; + break; + } + if (swapping) { + if (x & 1) { + if (listing) + printf("(FAILED: Swap error)\n"); + else if (!nolist) + printf("?Swap error\n"); + rc = 0; + break; + } + for (i = 0; i < x; i+=2) { + t = ibuf[i]; + ibuf[i] = ibuf[i+1]; + ibuf[i+1] = t; + } + } + if ((y = b8tob64(ibuf,x,obuf,180)) < 0) { + if (listing) + printf("(FAILED: Encoding error)\n"); + else if (!nolist) + printf("?Encoding error\n"); + rc = 0; + break; + } + fprintf(out,"%s\n",obuf); + } + + } else if (fromb64) { /* Converting from Base 64 */ + + debug(F110,"COPY fromb64",line,0); + + if ((out = fopen(p,appending ? "a" : "w")) == NULL) { + fclose(in); + if (listing) + printf("(FAILED: %s - %s)\n",p,ck_errstr()); + else if (!nolist) + printf("?%s - %s\n",p,ck_errstr()); + rc = 0; + continue; + } + x = 1; + while (x) { + x = fread(ibuf,1,80,in); + if ((y = b64tob8(ibuf,x,obuf,80)) < 0) { + if (listing) + printf("(FAILED: Decoding error)\n"); + else if (!nolist) + printf("?Decoding error\n"); + rc = 0; + break; + } + if (swapping) { + if (x & 1) { + if (listing) + printf("(FAILED: Swap error)\n"); + else if (!nolist) + printf("?Swap error\n"); + rc = 0; + break; + } + for (i = 0; i < y; i+=2) { + t = obuf[i]; + obuf[i] = obuf[i+1]; + obuf[i+1] = t; + } + } + if (y > 0) { + if (fwrite(obuf,1,y,out) < 1) { + if (listing) + printf("(FAILED: %s - %s)\n",p,ck_errstr()); + else if (!nolist) + printf("?%s - %s\n",p,ck_errstr()); + rc = 0; + break; + } + } + } + + } else +#endif /* NOSPL */ + + if (swapping) { /* Swapping bytes */ + + CHAR c[3]; + c[2] = NUL; + + debug(F110,"COPY swapping",line,0); + + while (1) { + x = fread((char *)c,1,2,in); + if (x < 1) { + if (listing) + printf("(OK)\n"); + break; + } else if (x == 1) { + c[1] = c[0]; + c[0] = NUL; + printf( + "(WARNING: Odd byte count)"); + if (!listing) printf("\n"); + } + if (fprintf(out,"%c%c",c[1],c[0]) == EOF) { + if (listing) + printf("(FAILED: %s - %s)\n",p,ck_errstr()); + else if (!nolist) + printf("?%s - %s\n",p,ck_errstr()); + rc = 0; + break; + } + } + + } else if (appending) { /* Appending to target file */ + + char c; + + debug(F110,"COPY appending",line,0); + + while (1) { + x = fread(&c,1,1,in); + if (x < 1) { + if (listing) + printf("(OK)\n"); + break; + } + if (fwrite(&c,1,1,out) < 1) { + if (listing) + printf("(FAILED: %s - %s)\n",p,ck_errstr()); + else if (!nolist) + printf("?%s - %s\n",p,ck_errstr()); + rc = 0; + break; + } + } + } + if (out) fclose(out); + if (in) fclose(in); + } +#ifdef VMSORUNIX + concb((char)escape); +#endif /* VMSORUNIX */ + } + if (rc > -1) success = rc; + return(rc); +} +#endif /* ZCOPY */ +#endif /* NOFRILLS */ + +#ifndef NORENAME +#ifndef NOFRILLS +#ifdef ZRENAME +int +dorenam() { + /* Parse a file or a directory name */ + int i, x, z, listing = 0, havename = 0, wild = 0, rc = 1; + int nolist = 0; + struct FDB sw, fi; + + cmfdbi(&sw, /* 2nd FDB - optional /PAGE switch */ + _CMKEY, /* fcode */ + "Filename or switch", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + nqvswtab, /* addtl numeric data 1: tbl size */ + 4, /* addtl numeric data 2: 4 = cmswi */ + xxstring, /* Processing function */ + qvswtab, /* Keyword table */ + &fi /* Pointer to next FDB */ + ); + + cmfdbi(&fi, /* 1st FDB - file to type */ + _CMIFI, /* fcode */ + "", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + 3, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ + xxstring, + NULL, + NULL + ); + + while (!havename) { + x = cmfdb(&sw); /* Parse something */ + if (x < 0) /* Error */ + return(x); + switch (cmresult.fcode) { + case _CMKEY: + switch (cmresult.nresult) { + case DEL_LIS: + case DEL_VRB: + listing = 1; + break; + case DEL_NOL: + case DEL_QUI: + nolist = 1; + listing = 0; + break; + } + break; + case _CMIFI: + s = cmresult.sresult; + havename = 1; + break; + default: + return(-2); + } + } + wild = cmresult.nresult; /* Source specification wild? */ + + ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy of source name */ + s = line; + + if (!wild) + wild = iswild(line); + + p = tmpbuf; /* Place for new name */ + if ((x = cmofi(wild ? "Target directory" : "New name", + "",&s,xxstring)) < 0) { /* Get new name */ + if (x == -3) { + printf("?%s required\n", wild ? "Target directory" : "New name"); + return(-9); + } else return(x); + } + ckstrncpy(p,s,TMPBUFSIZ); /* Make a safe copy of the new name */ + if ((y = cmcfm()) < 0) return(y); + + if (!wild) { /* Just one */ + if (listing) printf("%s => %s ",line,p); + if (zrename(line,p) < 0) { + if (listing) + printf("(FAILED: %s)\n",ck_errstr()); + else if (!nolist) + printf("?%s\n",ck_errstr()); + rc = 0; + } else { + if (listing) printf("(OK)\n"); + } + return(success = rc); + } + if (!isdir(p)) { /* Multiple */ + printf( /* if target is not a directory */ +"?Multiple source files not allowed if target is not a directory.\n"); + return(-9); + } +#ifdef COMMENT + else { /* Show full path of target */ + char buf[CKMAXPATH]; /* (too much) */ + if (zfnqfp(p,CKMAXPATH,buf)) + ckstrncpy(tmpbuf,buf,TMPBUFSIZ); + } +#endif /* COMMENT */ + +#ifdef VMS + conres(); /* Let Ctrl-C work. */ +#endif /* VMS */ + debug(F110,"dorename line",line,0); + +#ifdef ZXREWIND + z = zxrewind(); /* Rewind file list */ +#else + z = nzxpand(s,0); /* Expand file list */ +#endif /* ZXREWIND */ + debug(F111,"dorename p",p,z); + +#ifdef UNIX + if (wild && z > 1) + sh_sort(mtchs,NULL,z,0,0,filecase); /* Alphabetize the filename list */ +#endif /* UNIX */ + +/* + Note: COPY, RENAME, DELETE and similar commands should have options to + stop or proceed when they are operating on multiple files and the operation + fails. +*/ + while (z-- > 0) { + if (!(z == 0 && !wild)) + znext(line); + if (!line[0]) + break; + if (listing) printf("%s => %s ",line,p); + if (zrename(line,p) < 0) { + if (listing) + printf("(FAILED: %s)\n",ck_errstr()); + else if (!nolist) + printf("?%s - %s\n",ck_errstr(),line); + rc = 0; + } else { + if (listing) printf("(OK)\n"); + } + } +#ifdef VMS + concb((char)escape); +#endif /* VMS */ + return(success = rc); +} +#endif /* ZRENAME */ +#endif /* NOFRILLS */ +#endif /* NORENAME */ + +#ifndef NOSPL + +/* Do the RETURN command */ + +int +doreturn(s) char *s; { + int x; + extern int tra_asg; + char * line, * lp; + + if (cmdlvl < 1) { + printf("\n?Can't return from level %d\n",maclvl); + return(success = 0); + } + line = malloc(LINBUFSIZ); + if (line == NULL) + return(success = 0); + lp = line; /* Expand return value now */ + x = LINBUFSIZ-1; + if (!s) s = ""; + debug(F110,"RETURN s",s,0); + if (zzstring(s,&lp,&x) > -1) { + s = line; + debug(F110,"RETURN zzstring",s,0); + } + + /* Pop from all FOR/WHILE/SWITCH/XIFs */ + while ((maclvl > 0) && + (m_arg[maclvl-1][0]) && + (cmdstk[cmdlvl].src == CMD_MD) && + (!strncmp(m_arg[maclvl-1][0],"_xif",4) || + !strncmp(m_arg[maclvl-1][0],"_for",4) || + !strncmp(m_arg[maclvl-1][0],"_swi",4) || + !strncmp(m_arg[maclvl-1][0],"_whi",4))) { + debug(F111,"RETURN IF/FOR/WHI/SWI pop",m_arg[maclvl-1][0],maclvl); + dogta(XXPTA); /* Put args back */ + popclvl(); /* Pop up two levels */ + popclvl(); + } + if (tra_asg) { /* If tracing show return value */ + if (*s) + printf("<<< %s: \"%s\"\n", m_arg[maclvl][0], s); + else + printf("<<< %s: (null)\n", m_arg[maclvl][0]); + } + popclvl(); /* Pop from enclosing TAKE or macro */ + debug(F111,"RETURN tolevel",s,maclvl); + if (!s) s = ""; + if (!*s) s = NULL; + makestr(&(mrval[maclvl+1]),s); /* Set the RETURN value */ + free(line); + return(success = 1); /* Macro succeeds if we RETURN */ +} +#endif /* NOSPL */ + +#ifndef NOSPL +/* Do the OPEN command */ + +int +doopen() { /* OPEN { append, read, write } */ + int x, y, z = 0; char *s; + static struct filinfo fcb; /* (must be static) */ + if ((x = cmkey(opntab,nopn,"mode","",xxstring)) < 0) { + if (x == -3) { + printf("?Mode required\n"); + return(-9); + } else return(x); + } + switch (x) { + case OPN_FI_R: /* Old file (READ) */ + if (chkfn(ZRFILE) > 0) { + printf("?Read file already open\n"); + return(-2); + } + if ((z = cmifi("File to read","",&s,&y,xxstring)) < 0) { + if (z == -3) { + printf("?Input filename required\n"); + return(-9); + } else return(z); + } + if (y) { /* No wildcards allowed */ + printf("\n?Please specify a single file\n"); + return(-2); + } + ckstrncpy(line,s,LINBUFSIZ); + if ((int)strlen(line) < 1) return(-2); + if ((z = cmnum("buffer size","4096",10,&y,xxstring)) < 0) + return(z); + if (y < 1) { + printf("?Positive number required\n"); + return(-9); + } + if ((z = cmcfm()) < 0) return(z); + readblock = y; + if (readbuf) + free((char *)readbuf); + if (!(readbuf = (CHAR *) malloc(readblock+1))) { + printf("?Can't allocate read buffer\n"); + return(-9); + } + return(success = zopeni(ZRFILE,line)); + +#ifndef MAC +#ifndef NOPUSH + case OPN_PI_R: /* Pipe/Process (!READ) */ + if (nopush) { + printf("?Read from pipe disabled\n"); + return(success=0); + } + if (chkfn(ZRFILE) > 0) { + printf("?Read file already open\n"); + return(-2); + } + if ((y = cmtxt("System command to read from","",&s,xxstring)) < 0) { + if (y == -3) { + printf("?Command name required\n"); + return(-9); + } else return(y); + } + ckstrncpy(line,brstrip(s),LINBUFSIZ); + if (!line[0]) return(-2); + if ((y = cmcfm()) < 0) return(y); + if (!readbuf) { + if (!(readbuf = (CHAR *) malloc(readblock+1))) { + printf("?Can't allocate read buffer\n"); + return(-9); + } + } + return(success = zxcmd(ZRFILE,line)); + + case OPN_PI_W: /* Write to pipe */ + if (nopush) { + printf("?Write to pipe disabled\n"); + return(success=0); + } + if (chkfn(ZWFILE) > 0) { + printf("?Write file already open\n"); + return(-2); + } + if ((y = cmtxt("System command to write to","",&s,xxstring)) < 0) { + if (y == -3) { + printf("?Command name required\n"); + return(-9); + } else return(y); + } + ckstrncpy(line,brstrip(s),LINBUFSIZ); + if (!line[0]) return(-2); + if ((y = cmcfm()) < 0) return(y); + success = zxcmd(ZWFILE,line); + if (!success && msgflg) + printf("Can't open process for writing: %s\n",line); + return(success); +#endif /* NOPUSH */ +#endif /* MAC */ + + case OPN_FI_W: /* New file (WRITE) */ + case OPN_FI_A: /* (APPEND) */ + if ((z = cmofi("Name of local file to create","",&s,xxstring)) < 0) { + if (z == -3) { + printf("?Filename required\n"); + return(-9); + } else return(z); + } + if (z == 2) { + printf("?Sorry, %s is a directory name\n",s); + return(-9); + } + if (chkfn(ZWFILE) > 0) { + printf("?Write/Append file already open\n"); + return(-2); + } + fcb.bs = fcb.cs = fcb.rl = fcb.fmt = fcb.org = fcb.cc = fcb.typ = 0; + fcb.lblopts = 0; + fcb.dsp = (x == OPN_FI_W) ? XYFZ_N : XYFZ_A; /* Create or Append */ + ckstrncpy(line,s,LINBUFSIZ); + if ((int)strlen(line) < 1) return(-2); + if ((y = cmcfm()) < 0) return(y); + return(success = zopeno(ZWFILE,line,NULL,&fcb)); + +#ifndef NOLOCAL + case OPN_SER: /* OPEN PORT or LINE */ + case OPN_NET: { /* OPEN HOST */ + extern int didsetlin, ttnproto; + if (x == OPN_NET) { + z = ttnproto; + ttnproto = NP_NONE; + } + if ((y = setlin((x == OPN_SER) ? XYLINE : XYHOST, 1, 0)) < 0) { + if (x == OPN_NET) + ttnproto = z; + success = 0; + } + didsetlin++; + return(y); + } +#endif /* NOLOCAL */ + + default: + printf("?Not implemented"); + return(-2); + } +} +#endif /* NOSPL */ + +#ifndef NOXFER +/* D O X G E T -- GET command parser with switches */ + +#ifdef CK_LABELED +int g_lf_opts = -1; +extern int lf_opts; +#endif /* CK_LABELED */ + +int +doxget(cx) int cx; { + extern int /* External variables we need */ +#ifdef RECURSIVE + recursive, +#endif /* RECURSIVE */ + xfermode, fdispla, protocol, usepipes, + g_binary, g_xfermode, g_displa, g_rpath, g_usepipes; + extern char * rcv_move; /* Directory to move new files to */ + extern char * rcv_rename; /* What to rename new files to */ + extern char * rcvexcept[]; /* RECEIVE / GET exception list */ + int opkt = 0; /* Flag for O-Packet needed */ + +#ifdef PIPESEND + extern int pipesend; + extern char * rcvfilter; +#endif /* PIPESEND */ + extern struct keytab rpathtab[]; + extern int nrpathtab; + extern long calibrate; + int asname = 0; /* Flag for have as-name */ + int konly = 0; /* Kermit-only function */ + int c, i, n, confirmed = 0; /* Workers */ + int getval = 0; /* Whether to get switch value */ + int rcvcmd = 0; /* Whether it is the RECEIVE command */ + int mget = 0; /* Whether it is the MGET command */ + struct stringint { /* Temporary array for switch values */ + char * sval; + int ival; + } pv[SND_MAX+1]; + struct FDB sw, fl, cm; /* FDBs for each parse function */ + char * cmdstr = "this command"; + +#ifdef NEWFTP + if (cx == XXGET || cx == XXREGET || cx == XXMGET || cx == XXRETR) { + extern int ftpget; + extern int ftpisopen(); + if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) + return(doftpget(cx,0)); + } +#endif /* NEWFTP */ + + debug(F101,"xget cx","",cx); + + oopts = -1; + omode = -1; + + for (i = 0; i <= SND_MAX; i++) { /* Initialize switch values */ + pv[i].sval = NULL; + pv[i].ival = -1; + } + /* Preset switch values based on top-level command that called us */ + + switch (cx) { + case XXREC: /* RECEIVE */ + cmdstr = "RECEIVE"; + rcvcmd = 1; break; + case XXGET: /* GET */ + cmdstr = "GET"; + konly = 1; + break; +#ifdef CK_RESEND + case XXREGET: /* REGET */ + cmdstr = "REGET"; + konly = 1; + pv[SND_BIN].ival = 1; /* Implies /BINARY */ + pv[SND_RES].ival = 1; break; +#endif /* CK_RESEND */ + case XXRETR: /* RETRIEVE */ + cmdstr = "RETRIEVE"; + konly = 1; + pv[SND_DEL].ival = 1; break; +#ifdef PIPESEND + case XXCREC: /* CRECEIVE */ + cmdstr = "CRECEIVE"; + konly = 1; + rcvcmd = 1; + pv[SND_CMD].ival = 1; break; + case XXCGET: /* CGET */ + cmdstr = "CGET"; + konly = 1; + pv[SND_CMD].ival = 1; break; +#endif /* PIPESEND */ +#ifndef NOMGET + case XXMGET: /* MGET */ + cmdstr = "MGET"; + konly = 1; + mget = 1; break; +#endif /* NOMGET */ + } + debug(F111,"xget rcvcmd",cmdstr,rcvcmd); + debug(F101,"xget konly","",konly); + +#ifdef CK_XYZ + if (!rcvcmd && protocol != PROTO_K) { + printf("?Sorry, %s works only with Kermit protocol\n",cmdstr); + return(-9); + } +#endif /* CK_XYZ */ + + /* Set up chained parse functions... */ + + cmfdbi(&sw, /* First FDB - command switches */ + _CMKEY, /* fcode */ + rcvcmd ? + "Optional name/template to store incoming files under, or switch" : + "Remote filename, or switch", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + rcvcmd ? nrcvtab : ngettab, /* addtl numeric data 1: tbl size */ + 4, /* addtl numeric data 2: 4 = cmswi */ + xxstring, /* Processing function */ + rcvcmd ? rcvtab : gettab, /* Keyword table */ + &fl /* Pointer to next FDB */ + ); + if (rcvcmd || mget) /* RECEIVE or MGET */ + cmfdbi(&fl, + _CMTXT, /* fcode */ + rcvcmd ? /* hlpmsg */ + "Output filename or Command" : /* Output filename */ + "File(s) to GET", /* Files we are asking for */ + "", /* default */ + "", /* addtl string data */ + 0, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ +#ifdef CK_XYZ + (protocol == PROTO_X || protocol == PROTO_XC) ? + xxstring : + (rcvcmd ? (xx_strp)0 : xxstring) +#else + rcvcmd ? (xx_strp)0 : xxstring /* Processing function */ +#endif /* CK_XYZ */ + , + NULL, + &cm + ); + else + cmfdbi(&fl, /* Remote filename or command */ + _CMFLD, /* fcode */ + "Remote filename", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + 0, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ + xxstring, + NULL, + &cm + ); + cmfdbi(&cm, /* Confirmation */ + _CMCFM, /* fcode */ + "", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + 0, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ + NULL, + NULL, + NULL + ); + + /* (See doxsend() for fuller commentary) */ + + while (1) { /* Parse 0 or more switches */ + x = cmfdb(&sw); /* Parse something */ + debug(F101,"xget cmfdb","",x); + if (x < 0) /* Error */ + goto xgetx; /* or reparse needed */ + if (cmresult.fcode != _CMKEY) /* Break out if not a switch */ + break; + c = cmgbrk(); /* Get break character */ + if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) { + printf("?This switch does not take an argument\n"); + x = -9; + goto xgetx; + } + if (!getval && (cmgkwflgs() & CM_ARG)) { + printf("?This switch requires an argument\n"); + x = -9; + goto xgetx; + } + n = cmresult.nresult; /* Numeric result = switch value */ + debug(F101,"xget switch","",n); + + switch (n) { /* Process the switch */ +#ifdef PIPESEND + case SND_CMD: /* These take no args */ + if (nopush) { + printf("?Sorry, system command access is disabled\n"); + x = -9; + goto xgetx; + } else if (rcvfilter) { + printf( +"?Sorry, no GET /COMMAND when RECEIVE FILTER selected\n"); + x = -9; + goto xgetx; + } + if (rcvcmd) + sw.hlpmsg = "Command, or switch"; /* Change help message */ + /* Fall thru... */ +#endif /* PIPESEND */ + + case SND_REC: /* /RECURSIVE */ + pv[SND_PTH].ival = PATH_REL; /* Implies relative pathnames */ + pv[n].ival = 1; /* Set the recursive flag */ + break; + + case SND_RES: /* /RECOVER */ + pv[SND_BIN].ival = 1; /* Implies /BINARY */ + pv[n].ival = 1; /* Set the resend flag */ + break; + + case SND_DEL: /* /DELETE */ + case SND_SHH: /* /QUIET */ + case SND_CAL: /* /CALIBRATE */ + case SND_XPA: /* /TRANSPARENT */ + pv[n].ival = 1; /* Just set the appropriate flag */ + break; + + case SND_PIP: /* /PIPES:{ON,OFF} */ + if (!getval) { + pv[n].ival = 1; + break; + } + if ((x = cmkey(onoff,2,"","on",xxstring)) < 0) + goto xgetx; + if (!nopush) + pv[n].ival = x; + break; + + /* File transfer modes - each undoes the others */ + + case SND_BIN: /* Binary */ + case SND_TXT: /* Text */ + case SND_IMG: /* Image */ + case SND_LBL: /* Labeled */ + pv[SND_BIN].ival = 0; /* Unset all */ + pv[SND_TXT].ival = 0; + pv[SND_IMG].ival = 0; + pv[SND_LBL].ival = 0; + pv[n].ival = 1; /* Set the requested one */ + break; + + case SND_EXC: /* Excludes */ + if (!getval) break; + if ((x = cmfld("Pattern","",&s,xxstring)) < 0) { + if (x == -3) { + printf("?Pattern required\n"); + x = -9; + } + goto xgetx; + } + if (pv[n].sval) free(pv[n].sval); + y = strlen(s); + if (y > 256) { + printf("?Pattern too long - 256 max\n"); + x = -9; + goto xgetx; + } + pv[n].sval = malloc(y+1); + if (pv[n].sval) { + strcpy(pv[n].sval,s); /* safe */ + pv[n].ival = 1; + } + break; + +#ifdef COMMENT + /* Not implemented */ + case SND_PRI: /* GET to printer */ + pv[n].ival = 1; + if (!getval) break; + if ((x = cmfld("Print options","",&s,xxstring)) < 0) + goto xgetx; + pv[n].sval = malloc((int)strlen(s)+1); + if (pv[n].sval) + strcpy(pv[n].sval,s); /* safe */ + break; +#endif /* COMMENT */ + + case SND_MOV: /* MOVE after */ + case SND_REN: /* RENAME after */ + if (!getval) break; + if ((x = cmfld(n == SND_MOV ? + "device and/or directory for source file after sending" : + "new name for source file after sending", + "", + &s, + n == SND_MOV ? xxstring : NULL + )) < 0) { + if (x == -3) { + printf("%s\n", n == SND_MOV ? + "?Destination required" : + "?New name required" + ); + x = -9; + } + goto xgetx; + } + if (pv[n].sval) { + free(pv[n].sval); + pv[n].sval = NULL; + } + s = brstrip(s); + y = strlen(s); + if (y > 0) { + pv[n].sval = malloc(y+1); + if (pv[n].sval) { + strcpy(pv[n].sval,s); /* safe */ + pv[n].ival = 1; + } + } + break; + + case SND_ASN: /* As-name */ + if (!getval) break; + if (mget) { + printf("?Sorry, as-name not allowed with MGET\n"); + x = -9; + goto xgetx; + } + if ((x = cmfld("Name to store it under","",&s,NULL)) < 0) + goto xgetx; + s = brstrip(s); + if ((y = strlen(s)) > 0) { + if (pv[n].sval) free(pv[n].sval); + pv[n].sval = malloc(y+1); + if (pv[n].sval) { + strcpy(pv[n].sval,s); /* safe */ + pv[n].ival = 1; + } + } + break; + +#ifdef PIPESEND + case SND_FLT: /* Filter */ + debug(F101,"xget /filter getval","",getval); + if (!getval) break; + if ((x = cmfld("Filter program to receive through", + "",&s,NULL)) < 0) { + if (x == -3) + s = ""; + else + goto xgetx; + } + if (*s) s = brstrip(s); + y = strlen(s); + for (x = 0; x < y; x++) { /* Make sure they included "\v(...)" */ + if (s[x] != '\\') continue; + if (s[x+1] == 'v') break; + } + if (x == y) { + printf( + "?Filter must contain a replacement variable for filename.\n" + ); + x = -9; + goto xgetx; + } + pv[n].ival = 1; + if (pv[n].sval) { + free(pv[n].sval); + pv[n].sval = NULL; + } + if ((y = strlen(s)) > 0) { + if ((pv[n].sval = malloc(y+1))) + strcpy(pv[n].sval,s); /* safe */ + } + break; +#endif /* PIPESEND */ + + case SND_PTH: /* Pathnames */ + if (!getval) { + pv[n].ival = PATH_REL; + break; + } + if ((x = cmkey(rpathtab,nrpathtab,"","on",xxstring)) < 0) + goto xgetx; + pv[n].ival = x; /* Ditto */ + break; + + case SND_NAM: /* Filenames */ + if (!getval) break; + if ((x = cmkey(fntab,nfntab,"","converted",xxstring)) < 0) + goto xgetx; + pv[n].ival = x; + break; + + case SND_PRO: /* Protocol to use */ + if (!getval) break; + if ((x = cmkey(protos,nprotos,"File-transfer protocol","", + xxstring)) < 0) { + if (x == -3) + x = 0; + else + goto xgetx; + } + debug(F111,"xget /proto",atmbuf,x); + pv[n].ival = x; + if (konly && x != PROTO_K) { + printf( +"?Sorry, this command works only with Kermit protocol\n" + ); + x = -9; + goto xgetx; + } + break; + + default: + printf("?Unexpected switch value - %d\n",cmresult.nresult); + x = -9; + goto xgetx; + } + } + debug(F101,"xget cmresult fcode","",cmresult.fcode); + + cmarg = line; /* Initialize string pointers */ + cmarg2 = tmpbuf; + asname = 0; + line[0] = NUL; /* and buffers. */ + tmpbuf[0] = NUL; + + switch (cmresult.fcode) { /* How did we get out of switch loop */ + case _CMFLD: /* (3) Remote filespec */ + ckstrncpy(line,cmresult.sresult,LINBUFSIZ); + break; + case _CMTXT: /* (4) As-name */ + if (rcvcmd) { + ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ); + if ((int)strlen(tmpbuf) > 0) + asname = 1; + } else { + ckstrncpy(line,cmresult.sresult,LINBUFSIZ); + } + case _CMCFM: /* (6) Confirmation */ + confirmed = 1; + break; + default: + printf("?Unexpected function code: %d\n",cmresult.fcode); + x = -9; + goto xgetx; + } + debug(F110,"xget string",cmarg,0); + debug(F101,"xget confirmed","",confirmed); + + cmarg = brstrip(cmarg); /* Strip any braces */ + + if (!confirmed) { /* CR not typed yet, get more fields */ + if (pv[SND_CMD].ival > 0) { + debug(F100,"xget calling cmtxt","",0); + x = cmtxt("Local command to pipe into","",&s,NULL); + if (x < 0 && x != -3) goto xgetx; + if (x != -3) { + ckstrncpy(tmpbuf,s,TMPBUFSIZ); + asname = 1; + } + } else if (!rcvcmd) { +#ifdef VMS + /* cmofi() fails if you give it a directory name */ + x = cmfld("Name or directory for incoming file","",&s,NULL); + debug(F111,"xget cmfld",s,x); +#else + x = cmofi("Name or directory for incoming file","",&s,NULL); + debug(F111,"xget cmofi",s,x); +#endif /* VMS */ + if (x < 0 && x != -3) goto xgetx; + if (x != -3) { + ckstrncpy(tmpbuf,s,TMPBUFSIZ); + if ((x = cmcfm()) < 0) goto xgetx; + asname = 1; + } + } + } + /* Arrive here with cmarg and cmarg2 all set */ + + debug(F111,"xget asname",cmarg2,asname); + if (!asname) { + if (pv[SND_ASN].sval) + ckstrncpy(tmpbuf,pv[SND_ASN].sval,TMPBUFSIZ); + else + tmpbuf[0] = NUL; + } + cmarg2 = brstrip(cmarg2); /* Strip outer braces if any. */ + debug(F110,"xget cmarg",cmarg,0); + debug(F110,"xget cmarg2",cmarg2,0); + + if (!*cmarg && + (cx == XXGET || cx == XXREGET || cx == XXCGET || cx == XXMGET)) { + printf("?A remote file specification is required\n"); + x = -9; + goto xgetx; + } +#ifdef PIPESEND + if (pv[SND_CMD].ival > 0) { /* /COMMAND sets pipesend flag */ + x = -9; + if (!*cmarg2) { + printf("?Command required\n"); + goto xgetx; + } else if (nopush) { + printf("?Sorry, system command access is disabled\n"); + goto xgetx; + } else if (rcvfilter) { + printf("?Sorry, no GET /COMMAND while RECEIVE FILTER selected\n"); + goto xgetx; + } else + pipesend = 1; + } + debug(F101,"xget /COMMAND pipesend","",pipesend); +#endif /* PIPESEND */ + +#ifdef CK_RESEND + if (pv[SND_RES].ival > 0) { /* REGET or GET /RECOVER */ +#ifdef RECURSIVE + if (pv[SND_REC].ival > 0) { /* RECURSIVE */ +#ifdef COMMENT + printf("?Unsupported option combination: /RECOVER /RECURSIVE\n"); + x = -9; + goto xgetx; +#else + opkt = 1; +#endif /* COMMENT */ + } +#endif /* RECURSIVE */ + if (pv[SND_DEL].ival > 0) { /* /DELETE */ +#ifdef COMMENT + printf("?Unsupported option combination: /RECOVER /DELETE\n"); + x = -9; + goto xgetx; +#else + opkt = 1; +#endif /* COMMENT */ + } + } +#endif /* CK_RESEND */ + + if (pv[SND_EXC].ival > 0) /* /EXCEPT */ + makelist(pv[SND_EXC].sval,rcvexcept,NSNDEXCEPT); + +#ifdef IKS_OPTION + if (!rcvcmd +#ifdef CK_XYZ + && protocol == PROTO_K +#endif /* CK_XYZ */ + ) { + if (!iks_wait(KERMIT_REQ_START,1)) { + printf( + "?A Kermit Server is not available to process this command\n"); + x = -9; /* correct the return code */ + goto xgetx; + } + } +#endif /* IKS_OPTION */ + +#ifdef CK_XYZ + { + int po, pg; /* (for clarity) */ + po = pv[SND_PRO].ival; /* /PROTOCOL option */ + pg = protocol; /* Protocol global */ + if ((rcvcmd && !*cmarg2) && /* If no as-name was given */ + /* and /PROTOCOL is XMODEM or global protocol is XMODEM... */ + ((po < 0 && (pg == PROTO_X || pg == PROTO_XC)) || + (po > -1 && (po == PROTO_X || po == PROTO_XC))) + ) { + printf( +"Sorry, you must specify a name when receiving a file with XMODEM protocol\n" + ); + x = -9; + goto xgetx; + } + } +#endif /* CK_XYZ */ + +#ifdef RECURSIVE + if (pv[SND_REC].ival > 0) { /* RECURSIVE */ + recursive = 1; + pv[SND_PTH].ival = PATH_REL; /* Implies relative pathnames too */ + } +#endif /* RECURSIVE */ + + if (pv[SND_PIP].ival > -1) { + g_usepipes = usepipes; + usepipes = pv[SND_PIP].ival; + } + + /* Save global protocol parameters */ + + g_proto = protocol; +#ifdef CK_LABELED + g_lf_opts = lf_opts; /* Save labeled transfer options */ +#endif /* CK_LABELED */ + g_urpsiz = urpsiz; /* Receive packet length */ + g_spsizf = spsizf; /* Send packet length flag */ + g_spsiz = spsiz; /* Send packet length */ + g_spsizr = spsizr; /* etc etc */ + g_spmax = spmax; + g_wslotr = wslotr; + g_prefixing = prefixing; + g_fncact = fncact; + g_fncnv = fncnv; + g_fnspath = fnspath; + g_fnrpath = fnrpath; + g_xfrxla = xfrxla; + + if (pv[SND_PRO].ival > -1) { /* Change according to switch */ + protocol = pv[SND_PRO].ival; + if (ptab[protocol].rpktlen > -1) /* copied from initproto() */ + urpsiz = ptab[protocol].rpktlen; + if (ptab[protocol].spktflg > -1) + spsizf = ptab[protocol].spktflg; + if (ptab[protocol].spktlen > -1) { + spsiz = ptab[protocol].spktlen; + if (spsizf) + spsizr = spmax = spsiz; + } + if (ptab[protocol].winsize > -1) + wslotr = ptab[protocol].winsize; + if (ptab[protocol].prefix > -1) + prefixing = ptab[protocol].prefix; + if (ptab[protocol].fnca > -1) + fncact = ptab[protocol].fnca; + if (ptab[protocol].fncn > -1) + fncnv = ptab[protocol].fncn; + if (ptab[protocol].fnsp > -1) + fnspath = ptab[protocol].fnsp; + if (ptab[protocol].fnrp > -1) + fnrpath = ptab[protocol].fnrp; + } + debug(F101,"xget protocol","",protocol); + debug(F111,"xget cmarg2",cmarg2,xfermode); + + g_xfermode = xfermode; + g_binary = binary; + if (pv[SND_BIN].ival > 0) { /* Change according to switch */ + xfermode = XMODE_M; + binary = XYFT_B; /* FILE TYPE BINARY */ + omode = GMOD_BIN; /* O-Packet mode */ + debug(F101,"doxget /BINARY xfermode","",xfermode); + } else if (pv[SND_TXT].ival > 0) { /* Ditto for /TEXT */ + xfermode = XMODE_M; + binary = XYFT_T; + omode = GMOD_TXT; + debug(F101,"doxget /TEXT xfermode","",xfermode); + } else if (pv[SND_IMG].ival > 0) { + xfermode = XMODE_M; +#ifdef VMS + binary = XYFT_I; +#else + binary = XYFT_B; +#endif /* VMS */ + omode = GMOD_TXT; + debug(F101,"doxget /IMAGE xfermode","",xfermode); + } +#ifdef CK_LABELED + else if (pv[SND_LBL].ival > 0) { + xfermode = XMODE_M; + binary = XYFT_L; + omode = GMOD_LBL; + debug(F101,"doxget /LABELED xfermode","",xfermode); + } +#endif /* CK_LABELED */ + debug(F101,"xget binary","",binary); + debug(F101,"xget omode","",omode); + + if (pv[SND_XPA].ival > 0) /* /TRANSPARENT */ + xfrxla = 0; /* Don't translate character sets */ + +#ifdef PIPESEND + if (pv[SND_FLT].ival > 0) + makestr(&rcvfilter,pv[SND_FLT].sval); +#endif /* PIPESEND */ + +#ifdef CK_TMPDIR + if (pv[SND_MOV].ival > 0) { + int len; + char * p = pv[SND_MOV].sval; +#ifdef CK_LOGIN + if (isguest) { + printf("?Sorry, /MOVE-TO not available to guests\n"); + x = -9; + goto xgetx; + } +#endif /* CK_LOGIN */ + len = strlen(p); + if (!isdir(p)) { /* Check directory */ +#ifdef CK_MKDIR + char * s = NULL; + s = (char *)malloc(len + 4); + if (s) { + strcpy(s,p); /* safe */ +#ifdef datageneral + if (s[len-1] != ':') { s[len++] = ':'; s[len] = NUL; } +#else + if (s[len-1] != '/') { s[len++] = '/'; s[len] = NUL; } +#endif /* datageneral */ + s[len++] = 'X'; + s[len] = NUL; + x = zmkdir(s); + free(s); + if (x < 0) { + printf("?Can't create \"%s\"\n",p); + x = -9; + goto xgetx; + } + } +#else + printf("?Directory \"%s\" not found\n",p); + x = -9; + goto xgetx; +#endif /* CK_MKDIR */ + } + zfnqfp(p,LINBUFSIZ,line); + makestr(&rcv_move,line); + } +#endif /* CK_TMPDIR */ + + if (pv[SND_REN].ival > 0) { /* /RENAME-TO:name */ + char * p = pv[SND_REN].sval; +#ifdef CK_LOGIN + if (isguest) { + printf("?Sorry, /RENAME-TO not available to guests\n"); + x = -9; + goto xgetx; + } +#endif /* CK_LOGIN */ + if (!p) p = ""; + if (!*p) { + printf("?New name required for /RENAME\n"); + x = -9; + goto xgetx; + } + p = brstrip(p); + makestr(&rcv_rename,p); + debug(F110,"xget rcv_rename","",0); + } + +#ifdef CALIBRATE + if (pv[SND_CAL].ival > 0) + calibrate = 1L; +#endif /* CALIBRATE */ + g_displa = fdispla; + if (pv[SND_SHH].ival > 0) + fdispla = 0; + debug(F101,"xget display","",fdispla); + + if (pv[SND_NAM].ival > -1) { /* /FILENAMES */ + g_fncnv = fncnv; /* Save global value */ + fncnv = pv[SND_NAM].ival; + debug(F101,"xsend fncnv","",fncnv); + /* We should also handle O packet filename option here */ + /* but we don't really need to since WHATAMI already handles it */ + } + if (pv[SND_PTH].ival > -1) { /* PATHNAMES */ + g_rpath = fnrpath; /* Save global values */ + fnrpath = pv[SND_PTH].ival; + debug(F101,"xsend fnrpath","",fnrpath); +#ifndef NZLTOR + if (fnrpath != PATH_OFF) { + g_fncnv = fncnv; + fncnv = XYFN_L; + debug(F101,"xsend fncnv","",fncnv); + } + /* We should also handle O packet pathname option here */ + /* but we don't really need to since WHATAMI already handles it */ +#endif /* NZLTOR */ + } + + /* Set protocol start state */ + + if (opkt) { /* Extended GET Options*/ + sstate = (CHAR) 'o'; + oopts = 0; + if (pv[SND_DEL].ival > 0) oopts |= GOPT_DEL; /* GET /DELETE */ + if (pv[SND_RES].ival > 0) oopts |= GOPT_RES; /* GET /RECOVER */ + if (pv[SND_REC].ival > 0) oopts |= GOPT_REC; /* GET /RECURSIVE */ + } else if (rcvcmd) + sstate = (CHAR) 'v'; /* RECEIVE or CRECEIVE */ + else if (pv[SND_DEL].ival > 0) + sstate = (CHAR) 'h'; /* GET /DELETE (= RETRIEVE) */ + else if (pv[SND_RES].ival > 0) + sstate = (CHAR) 'j'; /* GET /RECOVER (= REGET) */ + else + sstate = (CHAR) 'r'; /* Regular GET */ + getcmd = 1; + debug(F000,"xget sstate","",sstate); +#ifdef MAC + what = W_RECV; + scrcreate(); +#endif /* MAC */ + if (local) { + if (pv[SND_SHH].ival != 0) + displa = 1; + ttflui(); + } + x = 0; +#ifdef PIPESEND + if (pipesend) + goto xgetx; +#endif /* PIPESEND */ + +#ifdef CK_TMPDIR +/* + cmarg2 is also allowed to be a device or directory name; + even the name of a directory that doesn't exist. +*/ + y = strlen(cmarg2); + debug(F111,"xget strlen(cmarg2)",cmarg2,y); + if ((y > 0) && +#ifdef OS2 + ((isalpha(cmarg2[0]) && + cmarg2[1] == ':' && + cmarg2[2] == NUL) || + (cmarg[y-1] == '/' || cmarg[y-1] == '\\') || + isdir(cmarg2)) +#else +#ifdef UNIXOROSK + (cmarg2[y-1] == '/' || isdir(cmarg2)) +#else +#ifdef VMS + (cmarg2[y-1] == ']' || cmarg2[y-1] == '>' || isdir(cmarg2)) +#else +#ifdef STRATUS + (cmarg2[y-1] == '>' || isdir(cmarg2)) +#else +#ifdef datageneral + (cmarg2[y-1] == ':' || cmarg[0] == ':' || isdir(cmarg2)) +#else + isdir(cmarg2) +#endif /* datageneral */ +#endif /* STRATUS */ +#endif /* VMS */ +#endif /* UNIXOROSK */ +#endif /* OS2 */ + ) { + debug(F110,"doxget RECEIVE cmarg2 disk or dir",cmarg2,0); + if (!f_tmpdir) { + int x; + s = zgtdir(); + if (s) { + ckstrncpy(savdir,s,TMPDIRLEN); /* remember old disk/dir */ + f_tmpdir = 1; /* and that we did this */ + } else { + printf("?Can't get current directory\n"); + cmarg2 = ""; + f_tmpdir = 0; + x = -9; + goto xgetx; + } +#ifdef CK_MKDIR + x = zchki(cmarg2); /* Does as-name exist? */ + if (x == -1) { /* Doesn't exist */ + char * p = NULL; /* Try to create it */ + x = strlen(cmarg2); + if ((p = (char *)malloc(x+4))) { + sprintf(p,"%s%s",cmarg2,"x.x"); /* SAFE (prechecked) */ + x = zmkdir(p); + free(p); + if (x < 0) { + printf("?Can't create %s\n",cmarg2); + x = -9; + goto xgetx; + } + } + } +#endif /* CK_MKDIR */ + if (!zchdir(cmarg2)) { /* change to given disk/directory, */ + printf("?Can't access %s\n",cmarg2); + x = -9; + goto xgetx; + } + cmarg2 = ""; + } + } +#endif /* CK_TMPDIR */ + + ckstrncpy(fspec,cmarg,CKMAXPATH); /* Note - this is a REMOTE filespec */ + debug(F111,"xget fspec",fspec,fspeclen); + debug(F110,"xget cmarg2",cmarg2,0); + + xgetx: + for (i = 0; i < SND_MAX; i++) + if (pv[i].sval) + free(pv[i].sval); + return(x); +} +#endif /* NOXFER */ + +#ifndef NOSPL + +/* + D O G T A -- Do _GETARGS or _PUTARGS Command. + + Used by XIF, FOR, WHILE, and SWITCH, each of which are implemented as + 2-level macros; the first level defines the macro, the second runs it. + This routine hides the fact that they are macros by importing the + macro arguments (if any) from two levels up, to make them available + in the IF, FOR, SWITCH, and WHILE commands themselves; for example as + loop indices, etc, and within the IF/FOR/WHILE/SWITCH body itself. + _PUTARGS is in case we changed any of these variables or used SHIFT + on them, so the new values won't be lost as we pop up the stack. +*/ +int +dogta(cx) int cx; { + int i, n; + char c, *p, mbuf[4]; + extern int topargc, cmdint; + extern char ** topxarg; + + if ((y = cmcfm()) < 0) + return(y); + debug(F101,"dogta cx","",cx); + debug(F101,"dogta maclvl","",maclvl); + if (cx == XXGTA) { + debug(F101,"dogta _GETARGS maclvl","",maclvl); + } else if (cx == XXPTA) { + debug(F101,"dogta _PUTARGS maclvl","",maclvl); + } else { + return(-2); + } + if (maclvl < 1) + return(success = 0); + + /* Make new copies of macro arguments /%0..9 */ + + mbuf[0] = '%'; mbuf[1] = '0'; mbuf[2] = NUL; /* Argument name buf */ + + if (cx == XXPTA) { /* Go NOINT because _PUTARGS */ + if (cmdint) /* temporarily changes maclvl. */ + connoi(); /* Interrupts OFF. */ + } + for (i = 0; i < 10; i++) { /* For all args */ + c = (char) (i + '0'); /* Make name */ + mbuf[1] = (char) c; /* Insert digit */ + if (cx == XXGTA) { /* Get arg from level-minus-2 */ + if (maclvl == 1) p = g_var[c]; /* If at level 1 use globals 0..9 */ + else p = m_arg[maclvl-2][i]; /* Otherwise they're on the stack */ + addmac(mbuf,p); +#ifdef COMMENT + if (maclvl > 1) + makestr(&(m_line[maclvl]),m_line[maclvl-2]); +#endif /* COMMENT */ + } else if (cx == XXPTA) { /* Put args level+2 */ + maclvl -= 2; /* This is gross, it's because we're */ + addmac(mbuf,m_arg[maclvl+2][i]); /* adding macros two levels up */ + maclvl += 2; /* and addmac() uses maclvl. */ + count[cmdlvl - 2] = count[cmdlvl]; + intime[cmdlvl - 2] = intime[cmdlvl]; + inpcas[cmdlvl - 2] = inpcas[cmdlvl]; + takerr[cmdlvl - 2] = takerr[cmdlvl]; + merror[cmdlvl - 2] = merror[cmdlvl]; + xquiet[cmdlvl - 2] = xquiet[cmdlvl]; + } else return(success = 0); /* Bad call to this routine */ + } + if (cx == XXPTA) { /* Restore interrupts if we */ + if (cmdint) /* turned them off above. */ + conint(trap,stptrap); + } + /* Now take care of the argument vector array \&_[], \v(return), */ + /* and \v(argc) by just copying the pointers. */ + + if (cx == XXGTA) { /* GETARGS from 2 levels up */ + if (maclvl == 1) { + a_ptr[0] = topxarg; /* \&_[] array */ + a_dim[0] = topargc - 1; /* Dimension doesn't include [0] */ + m_xarg[maclvl] = topxarg; + n_xarg[maclvl] = topargc; /* But \v(argc) does include \%0 */ + macargc[maclvl] = topargc; + makestr(&(mrval[maclvl+1]),mrval[0]); /* (see vnlook()) */ + } else { + a_ptr[0] = m_xarg[maclvl-2]; + a_dim[0] = n_xarg[maclvl-2]; + m_xarg[maclvl] = m_xarg[maclvl-2]; + n_xarg[maclvl] = n_xarg[maclvl-2]; + macargc[maclvl] = n_xarg[maclvl-2]; + makestr(&(mrval[maclvl+1]),mrval[maclvl-1]); /* (see vnlook()) */ + + } + } else { /* PUTARGS 2 levels up */ + if (maclvl > 1) { + a_ptr[0] = m_xarg[maclvl]; + m_xarg[maclvl-2] = m_xarg[maclvl]; + a_dim[0] = n_xarg[maclvl]; + n_xarg[maclvl-2] = n_xarg[maclvl]; + macargc[maclvl-2] = n_xarg[maclvl]; + } + } + return(1); /* Internal command - don't change success */ +} +#endif /* NOSPL */ + +#ifndef NOSPL +/* + Do the GOTO and [_]FORWARD commands. + s = Label to search for, cx = function code: XXGOTO, XXFWD, or XXXFWD. +*/ +#ifdef BIGBUFOK +#define LBLMAXLEN 255 /* Max label length */ +#else +#define LBLMAXLEN 63 +#endif /* BIGBUFOK */ + +int +dogoto(s, cx) char *s; int cx; { + int i, j, x, y, z, bc; + int empty = 0, stopflg = 0; + char * cmd; /* Name of this command */ + char tmplbl[LBLMAXLEN+1], *lp; /* Current label from command stream */ + char tmp2[LBLMAXLEN+1]; /* SWITCH label conversion buffer */ + char tmp3[LBLMAXLEN+1]; /* Target label */ + + stopflg = (cx == XXXFWD); /* _FORWARD (used in SWITCH) */ + bc = 0; /* Brace counter */ + + cmd = (cx == XXGOTO) ? "GOTO" : ((cx == XXFWD) ? "FORWARD" : "_FORWARD"); + if (!s) s = ""; + if (!*s) empty = 1; + +#ifdef DEBUG + if (deblog) { + debug(F111,"GOTO command",cmd,cx); + debug(F101,"GOTO cmdlvl","",cmdlvl); + debug(F101,"GOTO maclvl","",maclvl); + debug(F101,"GOTO tlevel","",tlevel); + debug(F111,"GOTO target",s,empty); + } +#endif /* DEBUG */ + debug(F110,cmd,s,0); + ckstrncpy(tmp3+1,s,LBLMAXLEN-1); + s = tmp3+1; + if (*s != ':') { /* Make copy of label */ + tmp3[0] = ':'; /* guaranteed to start with ":" */ + s--; + } + if (!stopflg && !empty) { + if (s[1] == '.' || s[1] == SP || s[1] == NUL) { + printf("?Bad label syntax - '%s'\n",s); + return(success = 0); + } + } + if (cmdlvl == 0) { + printf("?Sorry, %s only works in a command file or macro\n",cmd); + return(success = 0); + } + y = strlen(s); /* y = length of target label */ + debug(F111,cmd,s,y); + + while (cmdlvl > 0) { /* As long as not at top level... */ + if (cmdstk[cmdlvl].src == CMD_MD) { /* GOTO inside macro */ + int i, m, flag; + char *xp, *tp; + + /* GOTO: rewind the macro; FORWARD: start at current position */ + + lp = (cx == XXGOTO) ? macx[maclvl] : macp[maclvl]; + m = (int)strlen(lp) - y + 1; + debug(F010,"GOTO in macro",lp,0); + + flag = 1; /* flag for valid label position */ + for (i = 0; i < m; i++,lp++) { /* search for label in macro body */ + if (*lp == '{') /* But only at this level */ + bc++; /* Anything inside braces is off */ + else if (*lp == '}') /* limits. */ + bc--; + if (stopflg && bc > 0) /* This is good for SWITCH */ + continue; /* but interferes with WHILE, etc. */ + if (*lp == ',') { + flag = 1; + continue; + } + if (flag) { /* If in valid label position */ + if (*lp == SP) /* eat leading spaces */ + continue; + if (*lp != ':') { /* Look for label introducer */ + flag = 0; /* this isn't it */ + continue; /* keep looking */ + } + } + if (!flag) /* We don't have a label */ + continue; /* so keep looking... */ + xp = lp; tp = tmplbl; /* Copy the label from the macro */ + j = 0; /* to make it null-terminated */ + while ((*tp = *xp)) { + if (j++ > LBLMAXLEN) /* j = length of word from macro */ + break; +#ifdef COMMENT + if (*tp < 33 || *tp == ',') /* Look for end of word */ +#else + if (!*tp || *tp == ',') /* Look for end of word */ +#endif /* COMMENT */ + break; + else tp++, xp++; /* Next character */ + } + *tp = NUL; /* In case we stopped early */ + /* Now do caseless string comparison, using longest length */ + debug(F111,"macro GOTO label",s,y); + debug(F111,"macro target label",tmplbl,j); + if (stopflg) { /* Allow variables as SWITCH labels */ + int n = LBLMAXLEN - 1; + char * p = tmp2; + zzstring(tmplbl,&p,&n); + ckstrncpy(tmplbl,tmp2,LBLMAXLEN); + tmp2[49] = NUL; + } + debug(F111,"GOTO s",s,y); + debug(F111,"GOTO tmplbl",tmplbl,j); + debug(F101,"GOTO empty",ckitoa(stopflg),empty); + + if (empty) { /* Empty target */ + z = (!strcmp(s,":") && /* String is empty */ + /* and Label is ":" or ":*"... */ + (!strcmp(tmplbl,":") || !strcmp(tmplbl,":*"))) + ? 0 : 1; + debug(F111,"GOTO","A",z); + } else if (stopflg) { + z = ckmatch(tmplbl,s,inpcas[cmdlvl],1) ? 0 : 1; + debug(F111,"GOTO","B",z); + } else { + z = (stopflg && inpcas[cmdlvl]) ? + strcmp(s,tmplbl) : + ckstrcmp(s,tmplbl,(y > j) ? y : j, 0); + debug(F111,"GOTO","C",z); + } + if (!z) { + break; + } else if (stopflg && + !ckstrcmp(":default",tmplbl,(8 > j) ? 8 : j, 0)) { + debug(F100,"GOTO DEFAULT","",0); + break; + } else { + flag = 0; + } + } + debug(F111,"GOTO macro i",cmd,i); + debug(F111,"GOTO macro m",cmd,m); + if (i >= m) { /* Didn't find the label */ + debug(F101,"GOTO failed cmdlvl","",cmdlvl); +#ifdef COMMENT + /* MOVED TO AFTER POPCLVL ABOUT 20 LINES DOWN 5 AUG 2002 */ + if (stopflg) + return(0); +#endif /* COMMENT */ + if ((maclvl > 0) && + (m_arg[maclvl-1][0]) && + (cmdstk[cmdlvl].src == CMD_MD) && + (!strncmp(m_arg[maclvl-1][0],"_xif",4) || + !strncmp(m_arg[maclvl-1][0],"_for",4) || + !strncmp(m_arg[maclvl-1][0],"_swi",4) || + !strncmp(m_arg[maclvl-1][0],"_whi",4))) { + dogta(XXPTA); /* Restore args */ + debug(F101,"GOTO in XIF/FOR/WHI/SWI popping","",cmdlvl); + popclvl(); /* Pop an extra level */ + } + debug(F101,"GOTO popping","",cmdlvl); + if (!popclvl()) { /* pop up to next higher level */ + printf("?Label '%s' not found\n",s); /* if none */ + return(0); /* Quit */ + } else if (stopflg) { /* SWITCH no case label match */ + return(0); /* and no DEFAULT lable. */ + } else { + continue; /* otherwise look again */ + } + } + debug(F110,"GOTO found macro label",tmplbl,0); + macp[maclvl] = lp; /* set macro buffer pointer */ + return(1); + } else if (cmdstk[cmdlvl].src == CMD_TF) { + x = 0; /* GOTO issued in take file */ + debug(F111,"GOTO in TAKE file",cmd,cx); + if (cx == XXGOTO) { /* If GOTO, but not FORWARD, */ + rewind(tfile[tlevel]); /* search file from beginning */ + tfline[tlevel] = 0; + } + while (! feof(tfile[tlevel])) { +#ifdef COMMENT +/* This is wrong - it lets us jump to labels inside inferior blocks */ + tfline[tlevel]++; + if (fgets(line,LINBUFSIZ,tfile[tlevel]) == NULL) /* Get line */ +#else + if (getnct(line,LINBUFSIZ,tfile[tlevel],0) < 0) +#endif /* COMMENT */ + break; /* If no more, done, label not found */ + lp = line; /* Got line */ + while (*lp == SP || *lp == HT) + lp++; /* Strip leading whitespace */ + if (*lp != ':') continue; /* Check for label introducer */ + while (*(lp+1) == SP) { /* Remove space between : and name */ + *(lp+1) = ':'; + lp++; /* Strip leading whitespace */ + } + tp = lp; /* Get end of word */ + j = 0; + while (*tp) { /* And null-terminate it */ + if (*tp < 33) { + *tp = NUL; + break; + } else tp++, j++; + } + if (!ckstrcmp(lp,s,(y > j) ? y : j,0)) { /* Caseless compare */ + x = 1; /* Got it */ + break; /* done. */ + } else if (stopflg && + !ckstrcmp(":default",tmplbl,(8 > j) ? 8 : j,0)) { + x = 1; + break; + } + } + if (x == 0) { /* If not found, print message */ + debug(F101,"GOTO failed at cmdlvl","",cmdlvl); + if (stopflg) + return(0); + if (!popclvl()) { /* pop up to next higher level */ + printf("?Label '%s' not found\n",s); /* if none */ + return(0); /* quit */ + } else continue; /* otherwise look again */ + } + return(x); /* Send back return code */ + } + } + printf("?Stack problem in GOTO %s\n",s); /* Shouldn't see this */ + return(0); +} +#endif /* NOSPL */ + +/* Finish parsing and do the IF, XIF, and WHILE commands */ + +#ifndef NOSPL + +/* C H K V A R -- Check (if it's a) Variable */ + + +#ifdef OLDCHKVAR +/* + Crude and disgusting, but needed for OS/2, DOS, and Windows, where filenames + have backslashes in them. How do we know if a backslash in a filename is a + directory separator, or if it's a Kermit backslash? This routine does a + rough syntax check of the next few characters and if it looks like it MIGHT + be a variable, then it tries to evaluate it, and if the result is not empty, + we say it's a variable, although sometimes it might not be -- some cases are + truly ambiguous. For example there might a DOS directory called \%a, and + we also have a variable with the same name. This is all for the sake of not + having to tell PC users that they have to double all backslashes in file + and directory names. +*/ +#else +/* + Somewhat less crude & disgusting. The previous method was nondeterministic + and (worse) it interfered with macro argument passing. So now we only + check the syntax of backslash-items to see if they are variables, but we + do NOT check their values. +*/ +#endif /* OLDCHKVAR */ +/* + Call with a string pointer pointing at the backslash of the purported + variable. Returns 1 if it has the syntax of a variable, 0 if not. +*/ +int +chkvar(s) char *s; { + int z = 0; /* Return code - assume failure. */ + if (!s) s = ""; /* Watch our for null pointers. */ + if (!*s) return(0); /* Empty arg so not a variable. */ + if (*s == CMDQ) { /* Object begins with backslash. */ + char c; + c = s[1]; /* Character following backslash. */ + if (c) { + int t = 0; + if (c == CMDQ) /* Quoted backslash */ + return(1); + c = (char) (islower(c) ? toupper(c) : c); /* Otherwise... */ + if (c == '%') { /* Simple variable */ +#ifdef OLDCHKVAR + t = 1; +#else + return(1); +#endif /* OLDCHKVAR */ + } else if (c == '&') { /* Array */ + if (!s[2]) return(0); + if (s[3] == '[') + t = ckindex("]",s,4,0,1); +#ifndef OLDCHKVAR + return((t > 0) ? 1 : 0); +#endif /* OLDCHKVAR */ + } else if (c == '$' || /* Environment variable */ + c == 'V' || /* Built-in variable */ + c == 'M') { /* Macro name */ + t = (s[2] == '('); +#ifndef OLDCHKVAR + return((t > 0) ? 1 : 0); +#endif /* OLDCHKVAR */ + } else if (c == 'F') { /* Function reference */ + /* Don't actually call it - it might have side effects */ + int x; + if ((x = ckindex("(",s,3,0,1))) /* Just check syntax */ + if ((x = ckindex(")",s,x,0,1))) + z = 1; + /* Insert a better syntax check here if necessary */ + } +#ifdef OLDCHKVAR + if (t) { + t = 255; /* This lets us test \v(xxx) */ + lp = line; /* and even \f...(xxx) */ + zzstring(s,&lp,&t); /* Evaluate it, whatever it is. */ + t = strlen(line); /* Get its length. */ + debug(F111,"chkvar",line,t); + z = t > 0; /* If length > 0, it's defined */ + } +#endif /* OLDCHKVAR */ + } + } + return(z); +} + +/* B O O L E X P -- Evaluate a Boolean expression */ + +#define BOOLLEN 1024 +static char boolval[BOOLLEN]; + +int +boolexp(cx) int cx; { + int x, y, z; char *s, *p; + int parens = 0, pcount = 0, ecount = 0; + char *q, *bx; + struct FDB kw, nu; +#ifdef FNFLOAT + struct FDB fl; + CKFLOAT f1 = 0.0, f2 = 0.0; + int f1flag = 0, f2flag = 0; +#endif /* FNFLOAT */ +#ifdef OS2 + extern int keymac; +#endif /* OS2 */ + + not = 0; /* Flag for whether "NOT" was seen */ + z = 0; /* Initial IF condition */ + ifargs = 0; /* Count of IF condition words */ + bx = boolval; /* Initialize boolean value */ + *bx = NUL; + + ifagain: + cmfdbi(&kw, /* First FDB - command switches */ + _CMKEY, /* fcode */ + "Number, numeric-valued variable, Boolean expression, or keyword", + "", /* default */ + "", /* addtl string data */ + nif, /* addtl numeric data 1: tbl size */ + 0, /* addtl numeric data 2: 4 = silent */ + xxstring, /* Processing function */ + iftab, /* Keyword table */ + &nu /* Pointer to next FDB */ + ); + cmfdbi(&nu, /* 2nd FDB - An integer */ + _CMNUM, /* fcode */ + "", /* hlpmsg */ + "", /* Default */ + "", /* addtl string data */ + 0, + 0, + xxstring, + NULL, +#ifdef FNFLOAT + &fl +#else + NULL +#endif /* FNFLOAT */ + ); +#ifdef FNFLOAT + cmfdbi(&fl, /* A floating-point number */ + _CMFLD, /* fcode */ + "", /* hlpmsg */ + "", /* default */ + "", /* addtl string data */ + 0, /* addtl numeric data 1 */ + 0, /* addtl numeric data 2 */ + xxstring, + NULL, + NULL + ); +#endif /* FNFLOAT */ + x = cmfdb(&kw); /* Parse a keyword or a number */ + debug(F111,"boolval cmfdb","",x); + if (x < 0) { + if (x == -3) + x = -2; + return(x); + } + debug(F111,"boolval switch","",cmresult.fcode); + switch (cmresult.fcode) { /* What did we get? */ +#ifdef FNFLOAT + case _CMFLD: /* A "field" */ + if (isfloat(cmresult.sresult,0)) { /* A floating-point number? */ + f1 = floatval; /* Yes, get its value */ + f1flag = 1; /* remember we did this */ + ifc = 9999; /* Set special "if-code" */ + } else + return(-2); +#endif /* FNFLOAT */ + case _CMNUM: /* A number... */ + ifc = 9999; /* Set special "if-code" */ + break; + case _CMKEY: /* A keyword */ + ifc = cmresult.nresult; /* Get if-code */ + break; + default: + return(-2); + } + switch (ifc) { /* set z = 1 for true, 0 for false */ + case 9999: /* Number */ +#ifdef FNFLOAT + if (f1flag) { + z = (f1 == 0.0) ? 0 : 1; + } else +#endif /* FNFLOAT */ + z = (cmresult.nresult == 0) ? 0 : 1; + break; + case XXIFLP: /* Left paren */ + if (pcount == 0 && ifargs > 0) + return(-2); + parens = 1; + pcount++; + ifargs++; + *bx++ = '('; + goto ifagain; + case XXIFRP: /* Right paren */ + if (!parens) + return(-2); + if (--pcount < 0) + return(-2); + ifargs++; + *bx++ = ')'; + *bx = NUL; + if (pcount == 0) + goto ifend; + goto ifagain; + case XXIFAN: /* AND (&&) */ + ifargs++; + if (!ecount) + return(-2); + *bx++ = '&'; + goto ifagain; + case XXIFOR: /* OR (||) */ + ifargs++; + if (!ecount) + return(-2); + *bx++ = '|'; + goto ifagain; + case XXIFNO: /* IF NOT [ NOT [ NOT ... ] ] */ + if (bx > boolval) { /* evala() doesn't like cascaded */ + if (*(bx-1) == '!') { /* unary operators... */ + *(bx-1) = NUL; /* So here, two wrongs make a right. */ + bx--; + } else { + *bx++ = '!'; + } + } else { + *bx++ = '!'; + } + ifargs++; + goto ifagain; + case XXIFTR: /* IF TRUE */ + z = 1; + debug(F101,"if true","",z); + ifargs += 1; + break; + case XXIFNT: /* IF FALSE */ + z = 0; + debug(F101,"if true","",z); + ifargs += 1; + break; + case XXIFSU: /* IF SUCCESS */ + z = ( success != 0 ) ? 1 : 0; + debug(F101,"if success","",z); + ifargs += 1; + break; + case XXIFFA: /* IF FAILURE */ + z = ( success == 0 ) ? 1 : 0; + debug(F101,"if failure","",z); + ifargs += 1; + break; + + case XXIFDE: /* IF DEFINED */ + if ((x = cmfld("Macro or variable name","",&s,NULL)) < 0) + return((x == -3) ? -2 : x); + + if (*s == CMDQ) { + char * lp; + char line[256]; + int t, x; + if (*(s+1) == 'f' || *(s+1) == 'F') { /* Built-in function */ + extern struct keytab fnctab[]; + extern int nfuncs; + ckstrncpy(line,s+2,256); + if (line[0]) { + lp = ckstrchr(line,'('); + if (lp) *lp = NUL; + x = lookup(fnctab,line,nfuncs,&t); + z = x > -1; + } + debug(F111,"if defined function",line,z); + } else if (*(s+1) == 'v' || *(s+1) == 'V') { /* 8.0.200 */ + extern struct keytab vartab[]; + extern int nvars; + z = 0; + if (*(s+2) == '(') { + ckstrncpy(line,s+3,256); + if (line[0]) { + lp = ckstrchr(line,')'); + if (lp) *lp = NUL; + x = lookup(vartab,line,nvars,&t); + z = x > -1; + if (z) { /* 8.0.203 */ + int t; /* It must have a value to succeed */ + t = 255; /* as in C-Kermit 6.0 and 7.0 */ + lp = line; /* (this was broken in 8.0.200-201) */ + zzstring(s,&lp,&t); + t = strlen(line); + z = line[0] ? 1 : 0; + } + } + } + debug(F111,"if defined variable",line,z); + } else { + z = chkvar(s); /* Starts with backslash */ + if (z > 0) { /* Yes... */ + t = 255; /* than buffer so if zzstring fails */ + lp = line; /* check for that -- overflow means */ + line[0] = NUL; /* the quantity is defined. */ + x = zzstring(s,&lp,&t); + if ((x < 0 && t != 255) || !line[0]) + z = 0; + debug(F111,"if defined zzstring",line,z); + debug(F101,"if defined zzstring t","",t); + } + } + } else { + z = (mxlook(mactab,s,nmac) > -1); /* Look for exact match */ + } + debug(F111,"if defined final",s,z); + ifargs += 2; + break; + + case XXIFDC: { /* IF DECLARED */ + char * lp; + char line[32]; + int j, k, t, x; + if ((x = cmfld("Array name","",&s,NULL)) < 0) + return((x == -3) ? -2 : x); + if (*s == CMDQ) { + if (*(s+1) != '&') { + t = 31; + lp = line; + line[0] = NUL; + x = zzstring(s,&lp,&t); + s = line; + } + } + z = 0; + if ((x = arraybounds(s,&j,&k)) > -1) { + if (a_ptr[x]) { + if (j < 1) + z = 1; + else if (j <= a_dim[x]) + z = 1; + if (z == 1 && k > a_dim[x]) + z = 0; + } + } + break; + } + case XXIFBG: /* IF BACKGROUND */ + case XXIFFG: /* IF FOREGROUND */ + bgchk(); /* Check background status */ + if (ifc == XXIFFG) /* Foreground */ + z = pflag ? 1 : 0; + else z = pflag ? 0 : 1; /* Background */ + ifargs += 1; + break; + + case XXIFCO: /* IF COUNT */ + z = ( --count[cmdlvl] > 0 ); + if (cx == XXWHI) count[cmdlvl] += 2; /* Don't ask... */ + debug(F101,"if count","",z); + ifargs += 1; + break; + + case XXIFEX: /* IF EXIST */ +#ifdef CK_TMPDIR + case XXIFDI: /* IF DIRECTORY */ +#endif /* CK_TMPDIR */ + case XXIFAB: /* IF ABSOLUTE */ + if ((x = cmfld( + ((ifc == XXIFDI) ? "Directory name" : "File"), + "",&s, +#ifdef OS2 + NULL /* This allows \'s in filenames */ +#else + xxstring +#endif /* OS2 */ + )) < 0) { + if (x == -3) { + extern int cmflgs; + if (cmflgs == 1) { + printf("?File or directory name required\n"); + return(-9); + } + } else return(x); + } + s = brstrip(s); + if (ifc == XXIFAB) { + z = isabsolute(s); + } else if (ifc == XXIFEX) { + z = (zgetfs(s) > -1L); + debug(F101,"if exist 1","",z); +#ifdef OS2 + if (!z) { /* File not found. */ + int t; /* Try expanding variables */ + t = LINBUFSIZ-1; /* and looking again. */ + lp = line; + zzstring(s,&lp,&t); + s = line; + z = ( zchki(s) > -1L ); + debug(F101,"if exist 2","",z); + } +#endif /* OS2 */ +#ifdef CK_TMPDIR + } else { +#ifdef VMS + z = (zchki(s) == -2) +#else +/* Because this doesn't catch $DISK1:[FOO]BLAH.DIR;1 */ + z = isdir(s) +#ifdef OS2 + || (isalpha(s[0]) && s[1] == ':' && s[2] == NUL) +#endif /* OS2 */ +#endif /* VMS */ + ; + debug(F101,"if directory 1","",z); + + if (!z) { /* File not found. */ + int t; /* Try expanding variables */ + t = LINBUFSIZ-1; /* and looking again. */ + lp = line; + zzstring(s,&lp,&t); + s = line; + z = isdir(s) +#ifdef OS2 + || (isalpha(s[0]) && s[1] == ':' && s[2] == NUL) +#endif /* OS2 */ + ; + debug(F101,"if directory 2","",z); + } +#endif /* CK_TMPDIR */ + } + ifargs += 2; + break; + + case XXIFEQ: /* IF EQUAL (string comparison) */ + case XXIFLL: /* IF Lexically Less Than */ + case XXIFLG: /* If Lexically Greater Than */ + if ((x = cmfld("first word or variable name","",&s,xxstring)) < 0) { + if (x == -3) { + printf("?Text required\n"); + return(-9); + } else return(x); + } + s = brstrip(s); /* Strip braces */ + x = (int)strlen(s); + if (x > LINBUFSIZ-1) { + printf("?IF: strings too long\n"); + return(-2); + } + lp = line; /* lp points to first string */ + ckstrncpy(line,s,LINBUFSIZ); + if ((y = cmfld("second word or variable name","",&s,xxstring)) < 0) { + if (y == -3) { + printf("?Text required\n"); + return(-9); + } else return(y); + } + s = brstrip(s); + y = (int)strlen(s); + if (x + y + 2 > LINBUFSIZ) { + printf("?IF: strings too long\n"); + return(-2); + } + tp = lp + x + 2; /* tp points to second string */ + strcpy(tp,s); /* safe (checked) */ + x = ckstrcmp(lp,tp,-1,inpcas[cmdlvl]); /* Use longest length */ + switch (ifc) { + case XXIFEQ: /* IF EQUAL (string comparison) */ + z = (x == 0); + break; + case XXIFLL: /* IF Lexically Less Than */ + z = (x < 0); + break; + case XXIFLG: /* If Lexically Greater Than */ + z = (x > 0); + break; + } + debug(F101,"IF EQ result","",z); + ifargs += 3; + break; + + case XXIFVE: /* IF VERSION */ + case XXIFAE: /* IF (arithmetically) = */ + case XXIFNQ: /* IF != (not arithmetically equal) */ + case XXIFLT: /* IF < */ + case XXIFLE: /* IF <= */ + case XXIFGE: /* IF >= */ + case XXIFGT: { /* IF > */ + + /* Really should use longs here... */ + /* But cmnum parses ints. */ + int xx, n1 = 0, n2 = 0; + if (ifc == XXIFVE) { + n1 = (int) vernum; + } else { + x = cmfld("first number or variable name","",&s,xxstring); + if (x == -3) { + printf("?Quantity required\n"); + return(-9); + } + if (x < 0) return(x); + debug(F101,"xxifgt cmfld","",x); + ckstrncpy(line,s,LINBUFSIZ); + lp = brstrip(line); + debug(F110,"xxifgt exp1",lp,0); + +/* The following bit is for compatibility with old versions of MS-DOS Kermit */ + + if (!ckstrcmp(lp,"count",5,0)) { + n1 = count[cmdlvl]; + } else if (!ckstrcmp(lp,"version",7,0)) { + n1 = (int) vernum; + } else if (!ckstrcmp(lp,"argc",4,0)) { + n1 = (int) macargc[maclvl]; + } else { + +/* End of compatibility bit */ + +#ifdef FNFLOAT + if (isfloat(lp,0) > 1) { /* Allow floating-point comparisons */ + f1 = floatval; + f1flag = 1; + } else +#endif /* FNFLOAT */ + if (chknum(lp)) { + n1 = atoi(lp); + } else { /* Check for arithmetic expression */ + q = evala(lp); /* cmnum() does this but ... */ + if (chknum(q)) /* we're not using cmnum(). */ + n1 = atoi(q); + else + return(-2); + } + } + } + y = cmfld("number or variable name","",&s,xxstring); + if (y == -3) { + printf("?Quantity required\n"); + return(-9); + } + if (y < 0) return(y); + s = brstrip(s); + if (!*s) return(-2); + if (ifc == XXIFVE) { + tp = line; + } else { + x = (int)strlen(lp); + tp = line + x + 2; + } + ckstrncpy(tp,s,LINBUFSIZ-x-2); + debug(F110,"xxifgt exp2",tp,0); + if (!ckstrcmp(tp,"count",5,0)) { + n2 = count[cmdlvl]; + } else if (!ckstrcmp(tp,"version",7,0)) { + n2 = (int) vernum; + } else if (!ckstrcmp(tp,"argc",4,0)) { + n2 = (int) macargc[maclvl]; + } else { +#ifdef FNFLOAT + if (isfloat(tp,0) > 1) { + f2 = floatval; + f2flag = 1; + } else +#endif /* FNFLOAT */ + if (chknum(tp)) { + n2 = atoi(tp); + } else { + q = evala(tp); + if (chknum(q)) + n2 = atoi(q); + else + return(-2); + } + } + xx = (ifc == XXIFVE) ? XXIFGE : ifc; + +#ifdef FNFLOAT + if (f1flag && !f2flag) { + f2 = (CKFLOAT)n2; + f2flag = 1; + } + if (f2flag && !f1flag) + f1 = (CKFLOAT)n1; + if (f1flag) + z = ((f1 < f2 && xx == XXIFLT) + || (f1 != f2 && xx == XXIFNQ) + || (f1 <= f2 && xx == XXIFLE) + || (f1 == f2 && xx == XXIFAE) + || (f1 >= f2 && xx == XXIFGE) + || (f1 > f2 && xx == XXIFGT)); + else +#endif /* FNFLOAT */ + z = ((n1 < n2 && xx == XXIFLT) + || (n1 != n2 && xx == XXIFNQ) + || (n1 <= n2 && xx == XXIFLE) + || (n1 == n2 && xx == XXIFAE) + || (n1 >= n2 && xx == XXIFGE) + || (n1 > n2 && xx == XXIFGT)); + debug(F101,"xxifge z","",z); + if (ifc == XXIFVE) + ifargs += 2; + else + ifargs += 3; + break; + } + + case XXIFNU: /* IF NUMERIC */ + x = cmfld("variable name or constant","",&s,NULL); + if (x == -3) { + extern int cmflgs; + if (cmflgs == 1) { + printf("?Quantity required\n"); + return(-9); + } + } else if (x < 0) + return(x); + x = LINBUFSIZ-1; + lp = line; + zzstring(s,&lp,&x); + lp = line; + debug(F110,"xxifnu quantity",lp,0); + z = chknum(lp); +#ifdef COMMENT +/* + This works, but it's not wise -- IF NUMERIC is mostly used to see if a + string really does contain only numeric characters. If they want to force + evaluation, they can use \feval() on the argument string. +*/ + if (!z) { /* Not a number */ + x_ifnum = 1; /* Avoid "eval" error messages */ + q = evala(lp); /* Maybe it's an expression */ + z = chknum(q); /* that evaluates to a number */ + x_ifnum = 0; /* Put eval messages back to normal */ + if (z) debug(F110,"xxifnu exp",lp,0); + } +#endif /* COMMENT */ + debug(F101,"xxifnu chknum","",z); + ifargs += 2; + break; + +#ifdef ZFCDAT + case XXIFNE: { /* IF NEWER */ + char d1[20], * d2; /* Buffers for 2 dates */ + if ((z = cmifi("First file","",&s,&y,xxstring)) < 0) + return(z); + ckstrncpy(d1,zfcdat(s),20); + if ((z = cmifi("Second file","",&s,&y,xxstring)) < 0) + return(z); + d2 = zfcdat(s); + if ((int)strlen(d1) != 17 || (int)strlen(d2) != 17) { + printf("?Failure to get file date\n"); + return(-9); + } + debug(F110,"xxifnewer d1",d1,0); + debug(F110,"xxifnewer d2",d2,0); + z = (strcmp(d1,d2) > 0) ? 1 : 0; + debug(F101,"xxifnewer","",z); + ifargs += 2; + break; + } +#endif /* ZFCDAT */ + +#ifdef CK_IFRO + case XXIFRO: /* REMOTE-ONLY advisory */ + ifargs++; +#ifdef NOLOCAL + z = 1; +#else + z = remonly; +#endif /* NOLOCAL */ + break; +#endif /* CK_IFRO */ + + case XXIFAL: /* ALARM */ + ifargs++; + debug(F101,"IF ALARM ck_alarm","",ck_alarm); + debug(F110,"IF ALARM alrm_date",alrm_date,0); + debug(F110,"IF ALARM alrm_time",alrm_time,0); + + if (ck_alarm < 1L || alrm_date[0] < '0' || alrm_time[0] < '0') { + z = 0; /* ALARM not SET */ + break; /* so IF ALARM fails */ + } + /* Get current date and time */ + ckstrncpy(tmpbuf,ckcvtdate("",1),TMPBUFSIZ); + s = tmpbuf; + s[8] = NUL; + z = (int) strncmp(tmpbuf,alrm_date,8); /* Compare dates */ + debug(F101,"IF ALARM date z","",z); + if (z == 0) { /* Dates are the same */ + /* Compare times */ + z = (tod2sec(tmpbuf+9) >= atol(alrm_time)) ? 1 : -1; + debug(F101,"IF ALARM time z","",z); + } + tmpbuf[0] = NUL; /* z >= 0 if alarm is passed */ + z = ((z >= 0) ? 1 : 0); /* z < 0 otherwise */ + debug(F101,"IF ALARM final z","",z); + break; + + case XXIFOP: /* IF OPEN */ + if ((x = cmkey(iotab,niot,"file or log","",xxstring)) < 0) + return(x); + if (x == 9999 || x == ZSTDIO) { + bgchk(); /* Check background status */ + z = pflag ? 1 : 0; + } else if (x == 8888) { + z = local ? ttchk() > -1 : 0; +#ifdef CKLOGDIAL + } else if (x == 7777) { + extern int dialog; + z = dialog ? 1 : 0; +#endif /* CKLOGDIAL */ + } else + z = (chkfn(x) > 0) ? 1 : 0; + ifargs += 1; + break; + + case XXIFSD: /* Started-From-Dialer */ +#ifdef OS2 + z = StartedFromDialer; +#else + z = 0; +#endif /* OS2 */ + break; + + case XXIFTM: /* Terminal-Macro */ +#ifdef OS2 + z = cmdstk[cmdlvl].ccflgs & CF_KMAC; +#else + z = 0; +#endif /* OS2 */ + break; + + case XXIFEM: /* Emulation is active */ +#ifdef OS2 + z = 1; +#else + z = 0; +#endif /* OS2 */ + break; + + case XXIFIK: /* Running as IKSD? */ + z = inserver; + break; + + case XXIFTA: /* Connection is TAPI */ + z = 0; +#ifndef NODIAL +#ifdef CK_TAPI + if (local && !network && tttapi) + z = 1; +#endif /* CK_TAPI */ +#endif /* NODIAL */ + break; + + case XXIFMA: /* IF MATCH */ + x = cmfld("String or variable","",&s,xxstring); + if (x == -3) { + extern int cmflgs; + if (cmflgs == 1) { + printf("?String required\n"); + return(-9); + } + } else if (x < 0) + return(x); + ckstrncpy(line,s,LINBUFSIZ); + s = brstrip(line); + debug(F110,"xxifma string",line,0); + x = cmfld("Pattern","",&p,xxstring); + if (x == -3) { + extern int cmflgs; + if (cmflgs == 1) { + printf("?Pattern required\n"); + return(-9); + } + } else if (x < 0) + return(x); + ckstrncpy(tmpbuf,p,TMPBUFSIZ); + p = brstrip(tmpbuf); + debug(F110,"xxifma pattern",tmpbuf,0); + z = ckmatch(p,s,inpcas[cmdlvl],1); + break; + + case XXIFFL: { /* IF FLAG */ + extern int ooflag; + z = ooflag; + break; + } + case XXIFAV: { /* IF AVAILABLE */ + if ((x = cmkey(availtab,availtabn,"","",xxstring)) < 0) + return(x); + switch (x) { + case AV_KRB4: + z = ck_krb4_is_installed(); + break; + case AV_KRB5: + z = ck_krb5_is_installed(); + break; + case AV_SRP: + z = ck_srp_is_installed(); + break; + case AV_SSL: + z = ck_ssleay_is_installed(); + break; + case AV_NTLM: + z = ck_ntlm_is_installed(); + break; + case AV_CRYPTO: + z = ck_crypt_is_installed(); + break; + case AV_SSH: + z = ck_ssh_is_installed(); + break; + default: + z = 0; + } + break; + } + case XXIFAT: /* IF ASKTIMEOUT */ + z = asktimedout; + break; + + case XXIFRD: /* IF READABLE */ + case XXIFWR: /* IF WRITEABLE */ + if ((x = cmfld("File or directory name", + "", + &s, +#ifdef OS2 + NULL /* This allows \'s in filenames */ +#else + xxstring +#endif /* OS2 */ + )) < 0) { + if (x == -3) { + extern int cmflgs; + if (cmflgs == 1) { + printf("?File or directory name required\n"); + return(-9); + } + } else return(x); + } + s = brstrip(s); +/* + zchk[io]() do not do what we want here for directories, so we set + a global flag telling it to behave specially in this case. Othewise + we'd have to change the API and change all ck?fio.c modules accordingly. +*/ + y = 0; /* Try-again control */ +#ifdef OS2 + ifrdagain: +#endif /* OS2 */ + if (ifc == XXIFRD) { /* IF READABLE */ + zchkid = 1; + z = zchki(s) > -1; + zchkid = 0; + } else if (ifc == XXIFWR) { /* IF WRITEABLE */ + zchkod = 1; + z = zchko(s) > -1; + zchkod = 0; + } +#ifdef OS2 + if (!z && !y) { /* File not found. */ + int t; /* Try expanding variables */ + t = LINBUFSIZ-1; /* and looking again. */ + lp = line; + zzstring(s,&lp,&t); + s = line; + z = zchko(s) > -1; + y++; + goto ifrdagain; + } +#endif /* OS2 */ + ifargs += 2; + break; + case XXIFQU: /* IF QUIET */ + z = quiet ? 1 : 0; + debug(F101,"if quiet","",z); + ifargs += 1; + break; + + case XXIFWI: /* WILD */ + if ((x = cmfld("File specification","",&s,xxstring)) < 0) return(x); + z = iswild(s); + break; + + case XXIFCK: /* C-KERMIT */ +#ifdef OS2 + z = 0; +#else + z = 1; +#endif /* OS2 */ + break; + + case XXIFK9: /* K-95 */ +#ifdef OS2 + z = 1; +#else + z = 0; +#endif /* OS2 */ + break; + + case XXIFGU: /* GUI */ +#ifdef KUI + z = 1; +#else + z = 0; +#endif /* KUI */ + break; + + case XXIFMS: /* MS-KERMIT */ + z = 0; + break; + + case XXIFLO: /* IF LOCAL */ + z = local ? 1 : 0; + break; + + case XXIFCM: { /* IF COMMAND */ + extern struct keytab cmdtab[]; + extern int ncmd; + if ((x = cmfld("Word","",&s,xxstring)) < 0) + return(x); + z = lookup(cmdtab,s,ncmd,&y); + z = (z == -2 || z > -1) ? 1 : 0; + break; + } +#ifdef CKFLOAT + case XXIFFP: /* IF FLOAT */ + if ((x = cmfld("Number","",&s,xxstring)) < 0) + if (x != -3) /* e.g. empty variable */ + return(x); + z = isfloat(s,0); + break; +#endif /* CKFLOAT */ + + case XXIFKB: /* KBHIT */ + z = conchk(); + if (z < 0) z = 0; + if (z > 1) z = 1; + break; + + case XXIFKG: { /* KERBANG */ + extern int cfilef; + z = (xcmdsrc == 0) ? 0 : cfilef; + break; + } + + default: /* Shouldn't happen */ + return(-2); + } /* end of switch */ + + if (z) + *bx++ = '1'; + else + *bx++ = '0'; + *bx = NUL; + if (bx > boolval + BOOLLEN - 2) { + printf("?Boolean expression too long"); + return(-9); + } + ecount++; /* Expression counter */ + debug(F101,"boolexp parens","",parens); + debug(F101,"boolexp pcount","",pcount); + if (parens && pcount > 0) + goto ifagain; + + ifend: /* No more - done */ + *bx = NUL; + z = atoi(evalx(boolval)); + debug(F111,"boolexp boolval",boolval,z); + return(z); +} + +/* D O I F -- Do the IF command */ + +int +doif(cx) int cx; { + int x, y, z; char *s, *p; + char *q; +#ifdef OS2 + extern int keymac; +#endif /* OS2 */ + + debug(F101,"doif cx","",cx); + + z = boolexp(cx); /* Evaluate the condition(s) */ + debug(F010,"doif cmdbuf",cmdbuf,0); + debug(F101,"doif boolexp","",z); + if (z < 0) + return(z); + + if (cx == XXIF) { /* Allow IF to have XIF semantics. */ + char * p; + p = cmpeek(); + if (!p) p = ""; + while (*p) { + if (*p == SP || *p == HT) + p++; + else + break; + } + if (*p == '{') + cx = XXIFX; + } + switch (cx) { /* Separate handling for IF and XIF */ + + case XXASSER: /* And ASSERT */ + if ((x = cmcfm()) < 0) + return(x); + return(success = z); + + case XXIF: /* This is IF... */ + ifcmd[cmdlvl] = 1; /* We just completed an IF command */ + debug(F101,"doif condition","",z); + if (z) { /* Condition is true */ + iftest[cmdlvl] = 1; /* Remember that IF succeeded */ + if (maclvl > -1) { /* In macro, */ + pushcmd(NULL); /* save rest of command. */ + } else if (tlevel > -1) { /* In take file, */ + debug(F100, "doif: pushing command", "", 0); + pushcmd(NULL); /* save rest of command. */ + } else { /* If interactive, */ + cmini(ckxech); /* just start a new command */ + printf("\n"); /* (like in MS-DOS Kermit) */ + if (pflag) prompt(xxstring); + } + } else { /* Condition is false */ + iftest[cmdlvl] = 0; /* Remember command failed. */ + if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0) + return(y); /* Gobble up rest of line */ + } + return(0); + + case XXIFX: { /* This is XIF (Extended IF) */ + char *p; + char e[5]; + int i; + if ((y = cmtxt("Object command","",&s,NULL)) < 0) + return(y); /* Get object command. */ + p = s; + lp = line; + debug(F110,"doif THEN part",s,-54); + if (litcmd(&p,&lp,LINBUFSIZ - 1) < 0) { /* Quote THEN-part */ + return(-2); + } + debug(F111,"doif THEN part 2",line,z); + + while (*p == SP) p++; /* Strip trailing spaces */ + ifcmd[cmdlvl] = 0; /* Assume ELSE part in same line */ + iftest[cmdlvl] = z ? 1 : 0; + if (*p) { /* At end? */ + if (!z) { /* No, use ELSE-part, if any */ + for (i = 0; i < 4; i++) e[i] = *p++; + if (ckstrcmp(e,"else",4,0)) /* See if we have an ELSE */ + return(-2); /* Something else - error. */ + debug(F010,"doif ELSE line 1",p,0); + while (*p == SP) p++; /* Skip spaces */ + if (*p != '{') { /* Brace ELSE part if necessary */ + ckmakmsg(tmpbuf,TMPBUFSIZ,"{",p," }",NULL); + p = tmpbuf; + debug(F010,"doif ELSE line 2",p,0); + } + lp = line; /* Write over THEN part... */ + *lp = NUL; /* with ELSE part. */ + if (litcmd(&p,&lp,LINBUFSIZ - 2) < 0) { + return(-2); + } + while (*p == SP) p++; /* Strip trailing spaces */ + if (*p) return(-2); /* Should be nothing here. */ + debug(F010,"doif ELSE line 3",line,0); + } + } else { /* At end, treat like an IF command */ + if (!z) line[0] = NUL; /* Condition not true and no ELSE */ + ifcmd[cmdlvl] = 1; /* Allow ELSE on next line */ + debug(F101,"IF condition","",z); + } + if (line[0]) { + x = mlook(mactab,"_xif",nmac); /* Get index of "_xif" macro. */ + if (x < 0) { /* Not there? */ + addmmac("_xif",xif_def); /* Put it back. */ + if (mlook(mactab,"_xif",nmac) < 0) { /* Look it up again. */ + printf("?XIF macro gone!\n"); + return(success = 0); + } + } + dodo(x,line,cmdstk[cmdlvl].ccflgs | CF_IMAC); + } + return(0); + } + case XXWHI: { /* WHILE Command */ + p = cmdbuf; /* Capture IF condition */ + ifcond[0] = NUL; /* from command buffer */ + while (*p == SP) p++; + while (*p != SP) p++; + ifcp = ifcond; + ifcp += ckstrncpy(ifcp,"{ \\flit(if ( not ",IFCONDLEN); +#ifdef COMMENT +/* + This doesn't work because it breaks on the first left brace, which does + not necessarily start the command list, e.g. "while equal \%a {\35}". +*/ + while (*p != '{' && *p != NUL) *ifcp++ = *p++; + p = " ) goto _..bot) } "; + while (*ifcp++ = *p++) ; +#else +/* + The command parser sets cmbptr to the spot where it left off parsing in + the command buffer. +*/ + { + extern char * cmbptr; + if (cmbptr) { + while (p < cmbptr && *p != NUL) + *ifcp++ = *p++; + p = " ) goto _..bot) } "; + while ((*ifcp++ = *p++)) ; + } else { + printf("?Internal error parsing WHILE condition\n"); + return(-9); + } + } +#endif /* COMMENT */ + + debug(F110,"WHILE cmd",ifcond,0); + + if ((y = cmtxt("Object command","",&s,NULL)) < 0) + return(y); /* Get object command. */ + p = s; + lp = line; + if (litcmd(&p,&lp,LINBUFSIZ - 2) < 0) { /* Quote object command */ + return(-2); + } + debug(F101,"WHILE body",line,-54); + if (line[0]) { + char *p; + x = mlook(mactab,"_while",nmac); /* index of "_while" macro. */ + if (x < 0) { /* Not there? */ + addmmac("_while",whil_def); /* Put it back. */ + if (mlook(mactab,"_while",nmac) < 0) { /* Look it up again */ + printf("?WHILE macro definition gone!\n"); + return(success = 0); + } + } + p = malloc((int)strlen(ifcond) + (int)strlen(line) + 2); + if (p) { + strcpy(p,ifcond); /* safe (prechecked) */ + strcat(p,line); /* safe (prechecked) */ + debug(F010,"WHILE dodo",p,0); + dodo(x,p,cmdstk[cmdlvl].ccflgs | CF_IMAC); + free(p); + p = NULL; + } else { + printf("?Can't allocate storage for WHILE command"); + return(success = 0); + } + } + return(0); + } + default: + return(-2); + } +} +#endif /* NOSPL */ + +/* Set up a TAKE command file */ + +int +dotake(s) char *s; { +#ifndef NOSPL + extern int tra_cmd; +#endif /* NOSPL */ +#ifndef NOLOCAL +#ifdef OS2 + extern int term_io; + int term_io_sav = term_io; +#endif /* OS2 */ +#endif /* NOLOCAL */ + int slen; + + debug(F110,"dotake",s,0); + if (!s) s = ""; + if (!*s) return(success = 0); + slen = strlen(s); + debug(F101,"dotake len","",slen); + + if ((tfile[++tlevel] = fopen(s,"r")) == NULL) { + perror(s); + debug(F110,"dotake fail",s,0); + tlevel--; + return(success = 0); + } else { + tfline[tlevel] = 0; /* Line counter */ +#ifdef VMS + conres(); /* So Ctrl-C will work */ +#endif /* VMS */ +#ifndef NOLOCAL +#ifdef OS2 + term_io = 0; /* Disable Terminal Emulator I/O */ +#endif /* OS2 */ +#endif /* NOLOCAL */ +#ifndef NOSPL + cmdlvl++; /* Entering a new command level */ + debug(F111,"CMD +F",s,cmdlvl); + debug(F101,"dotake cmdlvl","",cmdlvl); + debug(F101,"dotake tlevel","",tlevel); + if (cmdlvl > CMDSTKL) { + debug(F100,"dotake stack overflow","",0); + cmdlvl--; + debug(F111,"CMD*-F",s,cmdlvl); + fclose(tfile[tlevel--]); + printf("?TAKE files and/or DO commands nested too deeply\n"); + return(success = 0); + } + if (tfnam[tlevel]) { /* Copy the filename */ + free(tfnam[tlevel]); + tfnam[tlevel] = NULL; + } + if ((tfnam[tlevel] = malloc(strlen(s) + 1))) { + strcpy(tfnam[tlevel],s); /* safe */ + } else { + printf("?Memory allocation failure\n"); + return(success = 0); + } + ifcmd[cmdlvl] = 0; /* Set variables for this cmd file */ + iftest[cmdlvl] = 0; + count[cmdlvl] = count[cmdlvl-1]; /* Inherit this */ + intime[cmdlvl] = intime[cmdlvl-1]; /* Inherit this */ + inpcas[cmdlvl] = inpcas[cmdlvl-1]; /* Inherit this */ + takerr[cmdlvl] = takerr[cmdlvl-1]; /* Inherit this */ + merror[cmdlvl] = merror[cmdlvl-1]; /* Inherit this */ + xquiet[cmdlvl] = quiet; + xcmdsrc = CMD_TF; + cmdstk[cmdlvl].src = CMD_TF; /* Say we're in a TAKE file */ + cmdstk[cmdlvl].lvl = tlevel; /* nested at this level */ + cmdstk[cmdlvl].ccflgs = cmdstk[cmdlvl-1].ccflgs; +#else + takerr[tlevel] = takerr[tlevel-1]; /* Inherit this */ +#endif /* NOSPL */ + } +#ifndef NOSPL + if (tra_cmd) + printf("[%d] +F: \"%s\"\n",cmdlvl,s); +#endif /* NOSPL */ +#ifndef NOLOCAL +#ifdef OS2 + term_io = term_io_sav; +#endif /* OS2 */ +#endif /* NOLOCAL */ + return(1); +} +#endif /* NOICP */ diff --git a/.pc/030_fix-if-else.patch/ckuusr.c b/.pc/030_fix-if-else.patch/ckuusr.c new file mode 100644 index 0000000..8545f89 --- /dev/null +++ b/.pc/030_fix-if-else.patch/ckuusr.c @@ -0,0 +1,13121 @@ +#ifdef SSHTEST +#define SSHBUILTIN +#endif /* SSHTEST */ + +#include "ckcsym.h" +char *userv = "User Interface 8.0.278, 12 Mar 2004"; + +/* C K U U S R -- "User Interface" for C-Kermit (Part 1) */ + +/* + Authors: + Frank da Cruz , + The Kermit Project, Columbia University, New York City + Jeffrey E Altman + 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 /* For CKLEARN */ +#endif /* VMS */ +#endif /* CKLEARN */ +#ifdef OS2 +#ifndef NT +#define INCL_NOPM +#define INCL_VIO /* Needed for ckocon.h */ +#include +#undef COMMENT +#else +#define APIRET ULONG +#include +#include +#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 +#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", + "" + ); + 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 */ diff --git a/.pc/applied-patches b/.pc/applied-patches index 4220079..d705a33 100644 --- a/.pc/applied-patches +++ b/.pc/applied-patches @@ -1,2 +1,3 @@ 010_makefile-destdir-support.patch 020_man-hyphen-quoting.patch +030_fix-if-else.patch diff --git a/ckuus6.c b/ckuus6.c index 5dcd828..a5abf19 100644 --- a/ckuus6.c +++ b/ckuus6.c @@ -6607,7 +6607,7 @@ doelse() { if (!iftest[cmdlvl]) { /* If IF was false do ELSE part */ if (maclvl > -1 || tlevel > -1) { /* In macro or command file */ debug(F100,"doelse pushing","",0); -#ifdef COMMENT +#ifndef COMMENT pushcmd(NULL); /* save rest of command. */ #else /* This fixes certain obscure problems */ diff --git a/ckuusr.c b/ckuusr.c index 8545f89..882c0d4 100644 --- a/ckuusr.c +++ b/ckuusr.c @@ -7983,8 +7983,7 @@ docmd(cx) int cx; { line[k++] = SP; line[k] = NUL; debug(F111,"XXMACRO A",line,k); - /* Defer evaluation of variables until the commands are exec'd */ - if ((y = cmtxt("Braced list of commands","",&s,NULL)) < 0) + if ((y = cmtxt("Braced list of commands","",&s,xxstring)) < 0) return(y); k = ckstrncpy(line+k,s,LINBUFSIZ-k); debug(F111,"XXMACRO B",line,k); -- 2.11.0