1 #ifdef SSHTEST
2 #define SSHBUILTIN
3 #endif /* SSHTEST */
4 
5 #include "ckcsym.h"
6 char *userv = "User Interface 9.0.315, 14 Sep 2021";
7 
8 /*  C K U U S R --  "User Interface" for C-Kermit (Part 1)  */
9 
10 /*
11   Authors:
12     Frank da Cruz <fdc@columbia.edu>,
13       The Kermit Project, New York City
14     Jeffrey E Altman <jaltman@secure-endpoints.com>
15       Secure Endpoints Inc., New York City
16 
17   Copyright (C) 1985, 2021,
18     Trustees of Columbia University in the City of New York.
19     All rights reserved.  See the C-Kermit COPYING.TXT file or the
20     copyright text in the ckcmai.c module for disclaimer and permissions.
21 */
22 
23 /*
24   Originally the entire user interface was in one module, ckuusr.c.  Over
25   the years it has been split into many modules: ckuus2.c, ckuus3.c, ...,
26   ckuus7.c.  ckuus2.c contains the HELP command parser and help-text strings;
27   ckuusy.c contains the UNIX-style command-line interface; ckuusx.c contains
28   routines needed by both the command-line interface and the interactive
29   command parser.
30 */
31 
32 /*
33   The ckuus*.c modules depend on the existence of C library features like
34   fopen, fgets, feof, (f)printf, argv/argc, etc.  Other functions that are
35   likely to vary among different platforms -- like setting terminal modes or
36   interrupts -- are invoked via calls to functions that are defined in the
37   platform-dependent modules, ck?[ft]io.c.  The command line parser processes
38   any arguments found on the command line, as passed to main() via argv/argc.
39   The interactive parser uses the facilities of the cmd package (developed for
40   this program, but usable by any program).  Any command parser may be
41   substituted for this one.  The only requirements for the Kermit command
42   parser are these:
43 
44   . Set parameters via global variables like duplex, speed, ttname, etc.  See
45     ckcmai.c for the declarations and descriptions of these variables.
46 
47   . If a command can be executed without the use of Kermit protocol, then
48     execute the command directly and set the variable sstate to 0. Examples
49     include 'set' commands, local directory listings, the 'connect' command.
50 
51   . If a command requires the Kermit protocol, set the following variables:
52 
53      sstate                             string data
54        'x' (enter server mode)            (none)
55        'r' (send a 'get' command)         cmarg, cmarg2
56        'v' (enter receive mode)           cmarg2
57        'g' (send a generic command)       cmarg
58        's' (send files)                   nfils, cmarg & cmarg2 OR cmlist
59        'c' (send a remote host command)   cmarg
60 
61      cmlist is an array of pointers to strings.
62      cmarg, cmarg2 are pointers to strings.
63      nfils is an integer.
64 
65      cmarg can be a filename string (possibly wild), or
66 	a pointer to a prefabricated generic command string, or
67 	a pointer to a host command string.
68      cmarg2 is an "as-name" - the name to send file(s) under, or
69 	the name under which to store incoming file(s); must not be wild.
70 	A null or empty value means to use the file's own name.
71      cmlist is a list of filenames, such as passed via argv.
72      nfils is an integer, interpreted as follows:
73        -1: filespec (possibly wild) in cmarg, must be expanded internally.
74 	0: send from stdin (standard input).
75        >0: number of files to send, from cmlist.
76 
77   The screen() function is used to update the screen during file transfer.
78   The tlog() function writes to a transaction log.
79   The debug() function writes to a debugging log.
80   The intmsg() and chkint() functions provide the user i/o for interrupting
81     file transfers.
82 */
83 
84 /* Includes */
85 
86 #ifdef MULTINET
87 #define MULTINET_OLD_STYLE		/* Leave select prototype undefined */
88 #endif /* MULTINET */
89 
90 #include "ckcdeb.h"
91 #include "ckcasc.h"
92 #include "ckcker.h"
93 #include "ckcnet.h"			/* Network symbols */
94 #include "ckuusr.h"
95 #include "ckcxla.h"
96 
97 int g_fncact = -1;			/* Needed for NOICP builds */
98 int noinit = 0;				/* Flag for skipping init file */
99 int nscanfile = SCANFILEBUF;
100 
101 int rcdactive = 0;			/* RCD active */
102 int keepallchars = 0;			/* See cmfld() */
103 
104 int locus = 1;				/* Current LOCUS is LOCAL */
105 #ifdef OS2
106 int autolocus = 2;			/* Automatic LOCUS switching: ASK */
107 #else /* OS2 */
108 int autolocus = 1;			/* Automatic LOCUS switching enabled */
109 #endif /* OS2 */
110 
111 #ifndef NOICP
112 #ifdef CKLEARN
113 #ifdef VMS
114 #include <time.h>			/* For CKLEARN */
115 #endif /* VMS */
116 #endif /* CKLEARN */
117 #ifdef OS2
118 #ifndef NT
119 #define INCL_NOPM
120 #define INCL_VIO			/* Needed for ckocon.h */
121 #include <os2.h>
122 #undef COMMENT
123 #else
124 #define APIRET ULONG
125 #include <windows.h>
126 #include <tapi.h>
127 #include "cknwin.h"
128 #include "ckntap.h"			/* CK_TAPI definition */
129 #endif /* NT */
130 #include "ckowin.h"
131 #include "ckocon.h"
132 extern int tcp_avail;
133 extern bool viewonly;
134 extern int k95stdout;
135 extern int tt_scroll;
136 #ifndef NOTERM
137 extern tt_status[VNUM];
138 #endif /* NOTERM */
139 #include "ckossh.h"
140 #ifdef KUI
141 #include "ikui.h"
142 #endif /* KUI */
143 #endif /* OS2 */
144 
145 int optlines = 0;
146 int didsetlin = 0;
147 
148 #ifdef NEWFTP
149 extern int ftpget, ftpisopen(), doftpres();
150 _PROTOTYP(int doftptyp,(int));
151 _PROTOTYP(VOID doftpglobaltype,(int));
152 #endif /* NEWFTP */
153 
154 #ifdef VMS
155 extern int batch;
156 #endif /* VMS */
157 
158 #ifdef datageneral
159 #include <packets:common.h>
160 #define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
161 #endif /* datageneral */
162 
163 extern int xcmdsrc, hints, cmflgs, whyclosed;
164 
165 int isinternal = 0;                     /* Flag for internally-defined macro */
166 
167 char * hlptok = NULL;
168 
169 #ifdef CK_TTGWSIZ			/* Whether to use more-prompting */
170 int xaskmore = 1;			/* Momentary setting */
171 int saveask  = 1;			/* Permanent setting */
172 #else
173 int xaskmore = 0;
174 int saveask  = 0;
175 #endif /* CK_TTGWSIZ */
176 
177 #ifndef NOCSETS
178 extern int nfilc;
179 extern struct keytab fcstab[];
180 extern int fcharset;
181 #endif /* NOCSETS */
182 
183 char * g_pswd = NULL;
184 int g_pcpt = -1;
185 int g_pflg = -1;
186 
187 extern int cmd_rows, cmd_cols;
188 
189 #ifdef CKROOT
190 extern int ckrooterr;
191 #endif /* CKROOT */
192 
193 extern int inserver, filepeek;
194 
195 #ifdef CKLEARN
196 FILE * learnfp = NULL;
197 char * learnfile = NULL;
198 int learning = 0;
199 #endif /* CKLEARN */
200 
201 #ifndef NOXFER
202 extern int atcapr, atdiso, nfils, moving, protocol, sendmode, epktflg, size,
203   sndsrc, server, displa, fncnv, fnspath, fnrpath, xfermode, urpsiz,
204   spsizf, spsiz, spsizr, spmax, wslotr, prefixing, fncact, reliable,
205   setreliable;
206 
207 #ifdef IKSDCONF
208 extern int iksdcf;
209 #endif /* IKSDCONF */
210 
211 #ifdef CK_LOGIN
212 extern int isguest;
213 #endif /* CK_LOGIN */
214 
215 extern CK_OFF_T sendstart;
216 
217 extern char *cmarg, *cmarg2, **cmlist, *dftty;
218 
219 extern struct keytab fntab[]; extern int nfntab;
220 extern struct ck_p ptab[NPROTOS];
221 
222 int sndcmd = 0;		/* Last command was a SEND-class command. */
223 
224 int g_xfermode = -1;
225 int g_proto  = -1;
226 int g_urpsiz = -1;
227 int g_spsizf = -1;
228 int g_spsiz  = -1;
229 int g_spsizr = -1;
230 int g_spmax  = -1;
231 int g_wslotr = -1;
232 int g_prefixing = -1;
233 int g_fncnv  = -1;
234 int g_fnspath = -1;
235 int g_fnrpath = -1;
236 int g_fnact  = -1;
237 int g_displa = -1;
238 int g_spath  = -1;
239 int g_rpath  = -1;
240 char * g_sfilter = NULL;
241 char * g_rfilter = NULL;
242 
243 extern int patterns;
244 #ifdef PATTERNS
245 extern char *txtpatterns[], *binpatterns[];
246 int g_patterns = -1;
247 #endif /* PATTERNS */
248 int g_skipbup = -1;
249 
250 #ifdef PIPESEND
251 extern int usepipes, pipesend;
252 extern char * sndfilter;
253 #endif /* PIPESEND */
254 
255 #ifndef NOSPL
256 extern int sndxlo, sndxhi, sndxin;
257 #endif /* NOSPL */
258 
259 extern char fspec[];			/* Most recent filespec */
260 extern int fspeclen;			/* Length of fspec[] buffer */
261 
262 #ifndef NOFRILLS
263 extern int rmailf;			/* MAIL command items */
264 extern char optbuf[];
265 #endif /* NOFRILLS */
266 
267 extern int
268   en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
269   en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
270   en_mkd, en_rmd, en_asg;
271 
272 #ifndef NOMSEND				/* Multiple SEND */
273 extern char *msfiles[];
274 int filesinlist = 0;			/* And ADD ... */
275 extern struct filelist * filehead;
276 extern struct filelist * filetail;
277 extern struct filelist * filenext;
278 extern int addlist;
279 #endif /* NOMSEND */
280 
281 static struct keytab addtab[] = {
282 #ifdef PATTERNS
283     { "binary-patterns", ADD_BIN, 0 },
284 #endif /* PATTERNS */
285 #ifndef NOMSEND
286     { "send-list", ADD_SND, 0 },
287 #endif /* NOMSEND */
288 #ifdef PATTERNS
289     { "text-patterns", ADD_TXT, 0 },
290 #endif /* PATTERNS */
291     { "", 0, 0 }
292 };
293 static int naddtab = sizeof(addtab)/sizeof(struct keytab) - 1;
294 
295 #ifndef NOCSETS
296 struct keytab assoctab[] = {
297     { "file-character-set",     ASSOC_FC, 0 },
298     { "transfer-character-set", ASSOC_TC, 0 },
299     { "xfer-character-set",     ASSOC_TC, CM_INV }
300 };
301 static int nassoc = sizeof(assoctab)/sizeof(struct keytab);
302 extern int afcset[MAXFCSETS+1];		/* Character-set associations */
303 extern int axcset[MAXTCSETS+1];
304 #endif /* NOCSETS */
305 
306 #ifndef ADDCMD
307 #ifndef NOMSEND
308 #define ADDCMD
309 #endif /* NOMSEND */
310 #ifndef ADDCMD
311 #ifdef PATTERNS
312 #define ADDCMD
313 #endif /* PATTERNS */
314 #endif /* ADDCMD */
315 #endif /* ADDCMD */
316 #endif /* NOXFER */
317 
318 /* External Kermit Variables, see ckmain.c for description. */
319 
320 extern xx_strp xxstring;
321 extern long xvernum;
322 
323 extern int local, xitsta, binary, msgflg, escape, duplex, quiet, tlevel,
324   pflag, zincnt, ckxech, carrier, what, nopush, haveline, bye_active;
325 #ifdef TNCODE
326 extern int debses;
327 extern char tn_msg[];
328 #endif /* TNCODE */
329 
330 int sleepcan = 1;
331 int g_binary = -1;
332 int g_recursive = -1;
333 int g_matchdot = -1;
334 extern int nolinks;
335 
336 extern long vernum;
337 extern char *versio, *copyright[];
338 extern char *ckxsys;
339 #ifndef NOHELP
340 extern char *introtxt[];
341 extern char *newstxt[];
342 #endif /* NOHELP */
343 
344 #ifndef OS2
345 #ifndef UNIX
346 extern char *PWDCMD;
347 #endif /* UNIX */
348 extern char *WHOCMD;
349 #endif /* OS2 */
350 
351 extern char ttname[];
352 
353 extern CHAR sstate;
354 
355 extern int network;			/* Have active network connection */
356 extern int nettype;			/* Type of network */
357 extern int ttnproto;                    /* NET_TCPB protocol */
358 
359 #ifndef NODIAL
360 extern int dialsta, dialatmo, dialcon, dialcq; /* DIAL status, etc. */
361 #endif /* NODIAL */
362 
363 #ifdef CK_APC
364 extern int apcactive, apcstatus;
365 #endif /* CK_APC */
366 
367 #ifndef NOPUSH
368 #ifndef NOFRILLS
369 extern char editor[];
370 extern char editopts[];
371 extern char editfile[];
372 #endif /* NOFRILLS */
373 #endif /* NOPUSH */
374 
375 #ifdef BROWSER
376 extern char browser[];			/* Web browser application */
377 extern char browsopts[];		/* Web browser options */
378 extern char browsurl[];			/* Most recent URL */
379 #endif /* BROWSER */
380 #ifndef NOFTP
381 char ftpapp[CKMAXPATH+1] = { NUL, NUL }; /* ftp executable */
382 char ftpopts[128] = { NUL, NUL };	/* ftp command-line options */
383 #endif /* NOFTP */
384 extern struct keytab onoff[];		/* On/Off keyword table */
385 
386 #ifdef CK_TMPDIR
387 int f_tmpdir = 0;			/* Directory changed temporarily */
388 char savdir[TMPDIRLEN];			/* For saving current directory */
389 #endif /* CK_TMPDIR */
390 
391 int activecmd = -1;			/* Keyword index of active command */
392 int doconx = -1;			/* CONNECT-class command active */
393 int ooflag = 0;				/* User-settable on/off flag */
394 
395 int rcflag = 0;				/* Pointer to home directory string */
396 int repars,				/* Reparse needed */
397     techo = 0;				/* Take echo */
398 int secho = 1;				/* SCRIPT echo */
399 
400 int xitwarn =			/* Warn about open connection on exit */
401 #ifdef NOWARN
402 0
403 #else
404 1
405 #endif /* NOWARN */
406 ;
407 
408 struct keytab onoffsw[] = {
409     { "/off", 0, 0 },
410     { "/on",  1, 0 }
411 };
412 
413 #ifdef CKEXEC
414 struct keytab redirsw[] = {
415     { "/redirect", 1, 0 }
416 };
417 #endif /* CKEXEC */
418 
419 #ifndef NOXMIT
420 /* Variables for TRANSMIT command */
421 
422 int xmitx = 1;			/* Whether to echo during TRANSMIT */
423 int xmitf = 0;			/* Character to fill empty lines */
424 int xmitl = 0;			/* 0 = Don't send linefeed too */
425 int xmitp = LF;			/* Host line prompt */
426 int xmits = 0;			/* Use shift-in/shift-out, 0 = no */
427 int xmitw = 0;			/* Milliseconds to pause during TRANSMIT */
428 int xmitt = 1;			/* Seconds to wait for each char to echo */
429 int xmita = 1;			/* Action upon timeout */
430 
431 #define XMI_BIN 1
432 #define XMI_TXT 2
433 #define XMI_CMD 3
434 #define XMI_TRA 4
435 #define XMI_VRB 5
436 #define XMI_QUI 6
437 #define XMI_NOW 7
438 #define XMI_NOE 8
439 
440 static struct keytab xmitsw[] = {	/* TRANSMIT command options */
441     { "/binary",          XMI_BIN, 0 },
442 #ifdef PIPESEND
443     { "/command",         XMI_CMD, CM_INV|CM_PSH },
444 #endif /* PIPESEND */
445     { "/noecho",          XMI_NOE, 0 },
446     { "/nowait",          XMI_NOW, 0 },
447 #ifdef PIPESEND
448     { "/pipe",            XMI_CMD, 0 },
449 #endif /* PIPESEND */
450 #ifdef COMMENT
451     { "/quiet",           XMI_QUI, 0 },
452 #endif /* COMMENT */
453     { "/text",            XMI_TXT, 0 },
454     { "/transparent",     XMI_TRA, 0 },
455 #ifdef COMMENT
456     { "/verbose",         XMI_VRB, 0 },
457 #endif /* COMMENT */
458     { "", 0, 0 }
459 };
460 #define NXMITSW sizeof(xmitsw)/sizeof(struct keytab) - 1
461 static int nxmitsw = NXMITSW;
462 
463 #endif /* NOXMIT */
464 
465 /* Declarations from ck?fio.c module */
466 
467 extern char *SPACMD, *SPACM2;		/* SPACE commands */
468 
469 /* Command-oriented items */
470 
471 #ifdef DCMDBUF
472 extern char *cmdbuf;			/* Command buffers */
473 extern char *atmbuf;
474 extern char *line;			/* Character buffer for anything */
475 extern char *tmpbuf;			/* Short temporary string buffer */
476 extern int *ifcmd;
477 extern int *intime;
478 extern int *inpcas;
479 #else
480 extern char cmdbuf[];			/* Command buffers */
481 extern char atmbuf[];
482 extern char line[];			/* Character buffer for anything */
483 extern char tmpbuf[];			/* Temporary buffer */
484 extern int ifcmd[];
485 extern int intime[];
486 extern int inpcas[];
487 #endif /* DCMDBUF */
488 
489 #ifndef NOSPL
490 extern char * prstring[];
491 #endif /* NOSPL */
492 
493 char *lp;				/* Pointer to line buffer */
494 
495 #ifndef NOSPL
496 int vareval = 1;			/* Evaluation method */
497 int unkmacro = 0;			/* Flag for in ON_UNKNOWN_COMMAND */
498 int oldeval = 0;
499 char evalbuf[33];			/* EVALUATE result */
500 extern char * inpbuf;			/* Buffer for INPUT and REINPUT */
501 char *inpbp;				/* And pointer to same */
502 int m_found;				/* MINPUT result */
503 int i_active = 0;			/* INPUT command is active */
504 char *ms[MINPMAX];			/* Pointers to MINPUT strings */
505 static int mpinited = 0;		/* Flag they have been initialized */
506 static int mp[MINPMAX];			/* and MINPUT flags */
507 extern int fndiags, fnerror, fnsuccess;	/* Function diagnostics */
508 #ifndef NOSEXP
509 char * lastsexp = NULL;			/* S-Expressions */
510 char * sexpval = NULL;
511 int sexpecho = SET_AUTO;
512 #endif /* NOSEXP */
513 #endif /* NOSPL */
514 
515 char psave[PROMPTL] = { NUL };		/* For saving & restoring prompt */
516 
517 extern int success;			/* Command success/failure flag */
518 extern int cmdlvl;			/* Current position in command stack */
519 
520 #ifndef NOSPL
521 int					/* SET INPUT parameters. */
522 /* Note, INPUT TIMEOUT, intime[], is on the command-level stack. */
523   inbufsize = 0,			/* INPUT buffer size */
524   indef = 1,				/* default timeout, seconds */
525   inecho = 1,				/* 1 = echo on */
526   inautodl = 0,				/* INPUT autodownload */
527   inintr = 1,				/* INPUT interrupion allowed */
528   insilence = 0;			/* 0 = no silence constraint */
529 
530 #ifdef CKFLOAT
531 CKFLOAT inscale = 1.0;			/* Timeout scale factor */
532 #endif	/* CKFLOAT */
533 
534 #ifdef OS2
535 int interm = 1;				/* Terminal emulator displays input */
536 #endif /* OS2 */
537 int maclvl = -1;			/* Macro nesting level */
538 int mecho = 0;				/* Macro echo, 0 = don't */
539 char varnam[6];				/* For variable names */
540 extern int macargc[];			/* ARGC from macro invocation */
541 
542 extern char *m_arg[MACLEVEL][NARGS];	/* Stack of macro arguments */
543 extern char *mrval[];
544 
545 extern char **a_ptr[];			/* Array pointers */
546 extern int a_dim[];			/* Array dimensions */
547 extern int a_link[];
548 
549 #ifdef DCMDBUF
550 extern struct cmdptr *cmdstk;		/* The command stack itself */
551 #else
552 extern struct cmdptr cmdstk[];		/* The command stack itself */
553 #endif /* DCMDBUF */
554 
555 long ck_alarm = 0;			/* SET ALARM value */
556 char alrm_date[24] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ' };
557 char alrm_time[24] = { ' ',' ',' ',' ',' ',' ',' ' };
558 
559 struct keytab inputsw[] = {
560     { "/clear",   INPSW_CLR, 0 },
561     { "/count",   INPSW_COU, CM_ARG },
562     { "/nomatch", INPSW_NOM, 0 },
563     { "/nowrap",  INPSW_NOW, 0 }
564 };
565 static int ninputsw = sizeof(inputsw)/sizeof(struct keytab);
566 
567 /* The following should be reconciled with the above */
568 
569 #ifdef COMMENT				/* INPUT switches not used yet... */
570 static struct keytab inswtab[] = {
571 #ifdef COMMENT
572     { "/assign",       IN_ASG, CM_ARG },
573 #endif /* COMMENT */
574     { "/autodownload", IN_ADL, CM_ARG },
575     { "/case",         IN_CAS, CM_ARG },
576     { "/echo",         IN_ECH, CM_ARG },
577     { "/interrupts",   IN_NOI, CM_ARG },
578     { "/silence",      IN_SIL, CM_ARG },
579 #ifdef COMMENT
580     { "/pattern",      IN_PAT, CM_ARG },
581 #endif /* COMMENT */
582     { "", 0, 0 }
583 };
584 static int ninswtab = (sizeof(inswtab) / sizeof(struct keytab)) - 1;
585 #endif /* COMMENT */
586 
587 
588 #endif /* NOSPL */
589 
590 static int x, y, z = 0;			/* Local workers */
591 static char *s;
592 
593 #ifdef CK_MINPUT
594 static char c1chars[] = {		/* C1 control chars escept NUL */
595     001,002,003,004,005,006,007,010,011,012,013,014,015,016,017,020,
596     021,022,023,024,025,026,027,030,031,032,033,034,035,036,037
597 };
598 #endif /* CK_MINPUT */
599 
600 #define xsystem(s) zsyscmd(s)
601 
602 /* Top-Level Interactive Command Keyword Table */
603 /* Keywords must be in lowercase and in alphabetical order. */
604 
605 struct keytab cmdtab[] = {
606 #ifndef NOPUSH
607     { "!",	   XXSHE, CM_INV|CM_PSH }, /* Shell escape */
608 #else
609     { "!",	   XXNOTAV, CM_INV|CM_PSH },
610 #endif /* NOPUSH */
611     { "#",    	   XXCOM, CM_INV },	/* Comment */
612 #ifndef NOSPL
613     { "(",           XXSEXP,CM_INV },	/* S-Expression */
614     { ".",           XXDEF, CM_INV },	/* Assignment */
615     { ":",           XXLBL, CM_INV },	/* Label */
616 #endif /* NOSPL */
617 #ifdef CK_REDIR
618 #ifndef NOPUSH
619     { "<",           XXFUN, CM_INV|CM_PSH }, /* REDIRECT */
620 #else
621     { "<",           XXNOTAV, CM_INV|CM_PSH }, /* REDIRECT */
622 #endif /* NOPUSH */
623 #endif /* CK_REDIR */
624 #ifndef NOPUSH
625     { "@",           XXSHE, CM_INV|CM_PSH }, /* DCL escape */
626 #else
627     { "@",           XXNOTAV, CM_INV|CM_PSH }, /* DCL escape */
628 #endif /* NOPUSH */
629 
630 #ifdef CK_RECALL
631     { "^",           XXREDO,CM_INV|CM_NOR }, /* Synonym for REDO */
632 #endif /* CK_RECALL */
633 #ifndef NOSPL
634     { "_asg",        XXASX,   CM_INV },	/* Used internally by FOR, etc */
635     { "_assign",     XXASX,   CM_INV },	/* Used internally by FOR, etc */
636     { "_decrement",  XX_DECR, CM_INV },
637     { "_define",     XXDFX,   CM_INV },	/* Used internally by FOR, etc */
638     { "_evaluate",   XX_EVAL, CM_INV },
639     { "_forward",    XXXFWD,  CM_INV },	/* Used internally by SWITCH   */
640     { "_getargs",    XXGTA,   CM_INV },	/* Used internally by FOR, etc */
641     { "_increment",  XX_INCR, CM_INV },
642     { "_putargs",    XXPTA,   CM_INV },	/* Used internally by FOR, etc */
643     { "_undefine",   XXUNDFX, CM_INV },
644 #endif /* NOSPL */
645 
646     { "about",       XXVER,   CM_INV },	/* Synonym for VERSION */
647 #ifndef NOSPL
648 #ifdef NEWFTP
649     { "account",     XXACCT,  CM_INV }, /* (FTP) Account */
650 #endif /* NEWFTP */
651 #ifdef ADDCMD
652     { "add",         XXADD, 0 },	/* ADD */
653 #endif /* ADDCMD */
654 #ifndef NODIAL
655     { "answer",      XXANSW, CM_LOC },	/* ANSWER the phone */
656 #else
657     { "answer",      XXNOTAV, CM_INV|CM_LOC }, /* ANSWER the phone */
658 #endif /* NODIAL */
659     { "apc",         XXAPC, 0 },	/* Application Program Command */
660 #ifndef NOSPL
661     { "array",       XXARRAY, 0 },	/* Array operations */
662 #endif /* NOSPL */
663     { "ascii",       XXASC, CM_INV },	/* == SET FILE TYPE TEXT */
664     { "asg",         XXASS, CM_INV },	/* Invisible synonym for ASSIGN */
665     { "ask",         XXASK, 0 },	/* ASK for text, assign to variable */
666     { "askq",        XXASKQ,0 },	/* ASK quietly (no echo) */
667 #ifndef NOSPL
668     { "ass",         XXASS, CM_INV|CM_ABR }, /* ASSIGN */
669     { "assert",      XXASSER, CM_INV },	/* ASSERT */
670     { "assign",      XXASS, 0 },	/* ASSIGN */
671 #endif /* NOSPL */
672 #ifndef NOXFER
673 #ifndef NOCSETS
674     { "associate",   XXASSOC, 0 },	/* ASSOCIATE */
675 #else
676     { "associate",   XXNOTAV, CM_INV },	/* ASSOCIATE */
677 #endif /* NOCSETS */
678 #endif /* NOXFER */
679 #ifdef CK_KERBEROS
680 #ifdef CK_AUTHENTICATION
681     { "authenticate",XXAUTH, 0 },	/* Authentication */
682 #else
683     { "authenticate",XXAUTH, CM_INV },
684 #endif /* CK_AUTHENTICATION */
685 #endif /* CK_KERBEROS */
686 #endif /* NOSPL */
687 #ifndef NOFRILLS
688     { "back",        XXBACK, 0 },	/* BACK to previous directory */
689 #else
690     { "back",        XXNOTAV,CM_INV },
691 #endif /* NOFRILLS */
692     { "beep",        XXBEEP,CM_INV },	/* BEEP */
693 #ifndef NOXFER
694     { "binary",      XXBIN, CM_INV },	/* == SET FILE TYPE BINARY */
695 #endif /* NOXFER */
696 #ifndef NOFRILLS
697     { "bug",         XXBUG, CM_INV },	/* BUG report instructions */
698 #else
699     { "bug",         XXNOTAV, CM_INV },
700 #endif /* NOFRILLS */
701 #ifdef BROWSER
702     { "browse",      XXBROWS, CM_PSH|CM_LOC }, /* BROWSE (start browser) */
703 #else
704     { "browse",      XXNOTAV, CM_INV|CM_PSH|CM_LOC },
705 #endif /* BROWSER */
706 #ifndef NOXFER
707     { "bye",         XXBYE, 0 },	/* BYE to remote server */
708 #endif /* NOXFER */
709 #ifndef NOLOCAL
710     { "c",           XXCON, CM_INV|CM_ABR|CM_LOC }, /* (CONNECT) */
711 #endif /* NOLOCAL */
712 #ifndef NOFRILLS
713     { "cat",         XXCAT, CM_INV },	/* Invisible synonym for TYPE */
714 #endif /* NOFRILLS */
715 #ifndef NOSPL
716 
717 #ifndef NOXFER
718     { "cautious",    XXCAU, CM_INV },
719 #endif /* NOXFER */
720 
721 #endif /* NOSPL */
722 
723     { "cd",          XXCWD, 0 },	/* Change Directory */
724     { "cdup",        XXCDUP, CM_INV },	/* Change Directory Up */
725 
726 #ifndef NOXFER
727 #ifdef PIPESEND
728     { "cget",        XXCGET, CM_INV|CM_PSH }, /* CGET */
729 #else
730     { "cget",        XXNOTAV, CM_INV|CM_PSH }, /* CGET */
731 #endif /* PIPESEND */
732 #endif /* NOXFER */
733     { "ch",          XXCHK,   CM_INV|CM_ABR },
734     { "change",      XXCHG,   0 },	/* CHANGE strings in file 2013-04-18 */
735     { "check",       XXCHK,   0 },	/* CHECK for a feature */
736 #ifdef CK_PERMS
737 #ifdef UNIX
738     { "chmod",       XXCHMOD, 0 },	/* CHMOD */
739 #else
740     { "chmod",       XXNOTAV, CM_INV },
741 #endif /* UNIX */
742 #else
743     { "chmod",       XXNOTAV, CM_INV },
744 #endif /* CK_PERMS */
745 #ifdef CKROOT
746     { "chroot",      XXCHRT,  CM_INV },	/* CHROOT */
747 #endif /* CKROOT */
748     { "ckermit",     XXKERMI, CM_INV },	/* CKERMIT (like KERMIT) */
749     { "cl",          XXCLO,   CM_ABR|CM_INV },
750 #ifndef NOFRILLS
751     { "clear",       XXCLE, 0 },	/* CLEAR input and/or device buffer */
752 #else
753     { "clear",       XXNOTAV, CM_INV },
754 #endif /* NOFRILLS */
755     { "close",	     XXCLO, 0 },	/* CLOSE a log or other file */
756     { "cls",         XXCLS, CM_INV },	/* Clear Screen (CLS) */
757     { "comment",     XXCOM, CM_INV },	/* Introduce a comment */
758 #ifndef NOLOCAL
759     { "connect",     XXCON, CM_LOC },	/* Begin terminal connection */
760 #else
761     { "connect",     XXNOTAV, CM_LOC },
762 #endif /* NOLOCAL */
763     { "continue",    XXCONT,  CM_INV },	/* CONTINUE */
764 #ifndef NOFRILLS
765 #ifdef ZCOPY
766     { "co",          XXCPY, CM_INV|CM_ABR },
767     { "cop",         XXCPY, CM_INV|CM_ABR },
768     { "copy",        XXCPY, 0 },	/* COPY a file */
769 #else
770     { "copy",        XXNOTAV, CM_INV },
771 #endif /* ZCOPY */
772     { "copyright",   XXCPR, CM_INV },	/* COPYRIGHT */
773 #ifdef ZCOPY
774     { "cp",          XXCPY, CM_INV },	/* COPY a file */
775 #endif /* ZCOPY */
776 #ifndef NOLOCAL
777 #ifndef OS2
778     { "cq",          XXCQ, CM_INV|CM_LOC }, /* CQ (connect quietly) */
779 #endif /* OS2 */
780 #endif /* NOLOCAL */
781 #ifndef NOXFER
782 #ifdef PIPESEND
783     { "creceive",    XXCREC,CM_INV|CM_PSH }, /* RECEIVE to a command */
784     { "csend",       XXCSEN,CM_INV|CM_PSH }, /* SEND from command */
785 #else
786     { "creceive",    XXNOTAV,CM_INV|CM_PSH },
787     { "csend",       XXNOTAV,CM_INV|CM_PSH },
788 #endif /* PIPESEND */
789 #endif /* NOXFER */
790 #endif /* NOFRILLS */
791 
792     { "cwd",	     XXCWD,   CM_INV },	/* Traditional synonym for cd */
793 
794 #ifndef NOSPL
795     { "date",        XXDATE,  0 },	/* DATE */
796     { "dcl",         XXDCL,   CM_INV },	/* DECLARE an array (see ARRAY) */
797     { "debug",       XXDEBUG, 0 },	/* Print a debugging msg [9.0]  */
798     { "declare",     XXDCL,   CM_INV },	/* DECLARE an array (see ARRAY) */
799     { "decrement",   XXDEC,   0 },	/* DECREMENT a numeric variable */
800     { "define",      XXDEF,   0 },	/* DEFINE a macro or variable   */
801 #else
802     { "date",        XXNOTAV, CM_INV },
803     { "dcl",         XXNOTAV, CM_INV },
804     { "declare",     XXNOTAV, CM_INV },
805     { "decrement",   XXNOTAV, CM_INV },
806     { "define",      XXNOTAV, CM_INV },
807 #endif /* NOSPL */
808 
809 #ifndef NOFRILLS
810     { "delete",      XXDEL, 0 },	/* DELETE a file */
811 #else
812     { "delete",      XXNOTAV, CM_INV },
813 #endif /* NOFRILLS */
814 
815 #ifndef NODIAL
816     { "dial",        XXDIAL,  CM_LOC },	/* DIAL a phone number */
817 #else
818     { "dial",        XXNOTAV, CM_INV|CM_LOC },
819 #endif /* NODIAL */
820 
821 #ifdef NT
822     { "dialer",      XXDIALER, CM_INV }, /* K95 Dialer */
823 #endif /* NT */
824 
825     { "directory",   XXDIR, 0 },	/* DIRECTORY of files */
826 
827 #ifndef NOFRILLS
828 #ifndef NOSERVER
829     { "disable",     XXDIS, 0 },	/* DISABLE a server function */
830 #else
831     { "disable",     XXNOTAV, CM_INV },
832 #endif /* NOSERVER */
833 #endif /* NOFRILLS */
834 
835 #ifndef NOSPL
836     { "do",          XXDO,  0 },	/* DO (execute) a macro */
837 #else
838     { "do",          XXNOTAV, CM_INV },
839 #endif /* NOSPL */
840 
841     { "e",           XXEXI, CM_INV|CM_ABR },
842 
843 #ifndef NOFRILLS
844 #ifndef NOXFER
845     { "e-packet",    XXERR, CM_INV },	/* Send an Error-Packet */
846 #endif /* NOXFER */
847 #endif /* NOFRILLS */
848 
849     { "echo",        XXECH, 0 },	/* ECHO text */
850 
851 #ifndef NOFRILLS
852 #ifndef NOPUSH
853     { "edit",        XXEDIT, CM_PSH },	/* EDIT */
854 #else
855     { "edit",        XXNOTAV, CM_INV|CM_PSH }, /* EDIT */
856 #endif /* NOPUSH */
857 #endif /* NOFRILLS */
858 
859     { "eightbit",    XXEIGHT, CM_INV },	/* EIGHTBIT */
860 
861 #ifndef NOSPL
862     { "else",        XXELS, CM_INV },	/* ELSE part of IF statement */
863 #else
864     { "else",        XXNOTAV, CM_INV },	/* ELSE part of IF statement */
865 #endif /* NOSPL */
866 
867 #ifndef NOSERVER
868 #ifndef NOFRILLS
869     { "enable",      XXENA,  0 },	/* ENABLE a server function */
870 #else
871     { "enable",      XXNOTAV, CM_INV },
872 #endif /* NOFRILLS */
873 #endif /* NOSERVER */
874 
875 #ifndef NOSPL
876     { "end",         XXEND,  0 },	/* END command file or macro */
877 #else
878     { "end",         XXNOTAV, CM_INV },
879 #endif /* NOSPL */
880 
881     { "erase",       XXDEL, CM_INV },	/* Synonym for DELETE */
882 
883 #ifndef NOSPL
884     { "evaluate",    XXEVAL, 0 },	/* EVALUATE */
885 #else
886     { "evaluate",    XXNOTAV, CM_INV },
887 #endif /* NOSPL */
888 
889     { "ex",          XXEXI, CM_INV|CM_ABR }, /* Let "ex" still be EXIT */
890 
891 #ifdef CKEXEC
892     { "exec",        XXEXEC, CM_INV|CM_LOC }, /* exec() */
893 #else
894     { "exec",        XXNOTAV, CM_INV|CM_LOC },
895 #endif /* CKEXEC */
896 
897     { "exit",	   XXEXI, 0 },		/* EXIT from C-Kermit */
898     { "extended-options", XXXOPTS,CM_INV|CM_HLP }, /* Extended-Options */
899 
900 #ifdef OS2
901     { "extproc",     XXCOM, CM_INV },	/* Dummy command for OS/2 */
902 #endif /* OS2 */
903 
904 #ifndef NOXFER
905     { "f",           XXFIN, CM_INV|CM_ABR }, /* Invisible abbrev for FIN */
906 #endif /* NOXFER */
907 
908 #ifndef NOSPL
909     { "fail",        XXFAIL, CM_INV },	/* FAIL */
910 
911 #ifndef NOXFER
912     { "fast",        XXFAST, CM_INV },
913 #endif /* NOXFER */
914 
915 #ifdef CKCHANNELIO
916     { "fclose",      XXF_CL, CM_INV },	/* FCLOSE */
917     { "fcount",      XXF_CO, CM_INV },	/* FCOUNT */
918     { "fflush",      XXF_FL, CM_INV },	/* FFLUSH */
919 #endif /* CKCHANNELIO */
920 
921 #ifndef NOXFER
922     { "fi",          XXFIN, CM_INV|CM_ABR }, /* FINISH */
923 #endif /* NOXFER */
924 
925 #ifdef CKCHANNELIO
926     { "file",        XXFILE, 0 },	/* FILE */
927 #endif /* CKCHANNELIO */
928 #endif /* NOSPL */
929 
930 #ifndef NOXFER
931     { "fin",         XXFIN, CM_INV|CM_ABR }, /* FINISH */
932 #endif /* NOXFER */
933 
934 #ifndef UNIXOROSK
935     { "find",        XXGREP, 0 },	/* FIND (grep) */
936 #else
937     { "find",        XXGREP,CM_INV },
938 #endif /* UNIXOROSK */
939 
940 #ifndef NOXFER
941     { "finish",      XXFIN, 0 },	/* FINISH */
942 #endif /* NOXFER */
943 
944 #ifdef TCPSOCKET
945     { "firewall",    XXFIREW, CM_INV|CM_HLP },
946 #endif /* TCPSOCKET */
947 
948 #ifdef CKCHANNELIO
949     { "flist",       XXF_LI, CM_INV },	/* FLIST */
950     { "fopen",       XXF_OP, CM_INV },	/* FOPEN */
951 #endif /* CKCHANNELIO */
952 
953 #ifndef NOSPL
954     { "fo",          XXFOR, CM_INV|CM_ABR }, /* Invisible abbrev for... */
955     { "for",         XXFOR, 0 },	/* FOR loop */
956     { "forward",     XXFWD, CM_INV },	/* FORWARD */
957 #endif /* NOSPL */
958 #ifndef NOFRILLS
959     { "fot",	   XXDIR, CM_INV },	/* "fot" = "dir" (for Chris) */
960 #endif /* NOFRILLS */
961 
962 #ifdef CKCHANNELIO
963     { "fread",      XXF_RE, CM_INV },	/* FREAD */
964     { "frewind",    XXF_RW, CM_INV },	/* FREWIND */
965     { "fseek",      XXF_SE, CM_INV },	/* FSEEK */
966     { "fstatus",    XXF_ST, CM_INV },	/* FSTATUS */
967 #endif /* CKCHANNELIO */
968 
969 #ifdef TCPSOCKET
970 #ifndef NOFTP
971 #ifdef SYSFTP
972 #ifndef NOPUSH
973     { "ftp",	   XXFTP,   CM_INV|CM_PSH|CM_LOC }, /* System FTP */
974 #else
975     { "ftp",	   XXNOTAV, CM_INV|CM_PSH|CM_LOC },
976 #endif /* NOPUSH */
977 #else  /* SYSFTP */
978     { "ftp",	   XXFTP,   0 },	/* Built-in FTP */
979 #endif /* SYSFTP */
980 #else  /* NOFTP */
981     { "ftp",	   XXNOTAV, CM_INV },	/* No FTP */
982 #endif /* NOFTP */
983 #endif /* TCPSOCKET */
984 
985 #ifndef NOSPL
986     { "function",    XXFUNC, CM_INV|CM_HLP }, /* (for HELP FUNCTION) */
987 #endif /* NOSPL */
988 
989 #ifdef CKCHANNELIO
990     { "fwrite",      XXF_WR, CM_INV },	/* FWRITE */
991 #endif /* CKCHANNELIO */
992 
993 #ifndef NOXFER
994     { "g",           XXGET, CM_INV|CM_ABR }, /* Invisible abbrev for GET */
995 #ifndef NOSPL
996     { "ge",          XXGET, CM_INV|CM_ABR }, /* Ditto */
997 #endif /* NOSPL */
998     { "get",         XXGET, 0 },	/* GET */
999 #endif /* NOXFER */
1000 #ifndef NOSPL
1001     { "getc",        XXGETC, 0 },	/* GETC */
1002 #ifdef OS2
1003     { "getkeycode",  XXGETK, 0 },	/* GETKEYCODE */
1004 #endif /* OS2 */
1005 #ifndef NOFRILLS
1006     { "getok",       XXGOK, 0 },	/* GETOK (ask for Yes/No/OK) */
1007 #endif /* NOFRILLS */
1008 #endif /* NOSPL */
1009 #ifndef NOSPL
1010     { "goto",        XXGOTO,0 },	/* GOTO label in take file or macro */
1011 #endif /* NOSPL */
1012 #ifdef UNIXOROSK
1013     { "grep",        XXGREP,0 },	/* GREP (find) */
1014 #else
1015     { "grep",        XXGREP,CM_INV },	/* GREP (find) */
1016 #endif /* UNIXOROSK */
1017     { "h",           XXHLP, CM_INV|CM_ABR }, /* Invisible synonym for HELP */
1018     { "he",          XXHLP, CM_INV|CM_ABR }, /* Invisible synonym for HELP */
1019 #ifndef NOFRILLS
1020     { "head",        XXHEAD, 0 },
1021 #endif /* NOFRILLS */
1022 #ifndef NOLOCAL
1023     { "hangup",      XXHAN, CM_LOC },	/* HANGUP the connection */
1024 #endif /* NOLOCAL */
1025     { "hdirectory",  XXHDIR,  CM_INV },	/* DIR sorted by size biggest first */
1026     { "HELP",        XXHLP, 0 },	/* Display HELP text */
1027 #ifndef NOHTTP
1028 #ifdef TCPSOCKET
1029     { "http",        XXHTTP, 0 },	/* HTTP operations */
1030 #endif /* TCPSOCKET */
1031 #endif /* NOHTTP */
1032 #ifndef NOSPL
1033     { "i",           XXINP, CM_INV|CM_ABR }, /* Invisible synonym for INPUT */
1034     { "if",          XXIF,  0 },	     /* IF ( condition ) command */
1035 #ifdef TCPSOCKET
1036     { "iksd",        XXIKSD, CM_INV },	     /* Make connection to IKSD */
1037 #else
1038     { "iksd",        XXNOTAV, CM_INV },
1039 #endif /* TCPSOCKET */
1040     { "in",          XXINP, CM_INV|CM_ABR }, /* Invisible synonym for INPUT */
1041     { "increment",   XXINC, 0 },	/* Increment a numeric variable */
1042     { "input",       XXINP, 0 },	/* INPUT text from comm device */
1043 #endif /* NOSPL */
1044 
1045 #ifndef NOHELP
1046     { "int",         XXINT, CM_INV|CM_ABR },
1047     { "intr",        XXINT, CM_INV|CM_ABR },
1048     { "INTRO",       XXINT, 0 },
1049     { "introduction",XXINT, CM_INV },	/* Print introductory text */
1050 #else
1051     { "intro",       XXNOTAV, CM_INV },
1052     { "introduction",XXNOTAV, CM_INV },
1053 #endif /* NOHELP */
1054 
1055 #ifdef OS2
1056     { "k95",         XXKERMI, CM_INV },	/* Hmmm what's this... */
1057 #endif /* OS2 */
1058 
1059 #ifndef NOSPL
1060     { "kcd",         XXKCD,   0      },
1061 #endif /* NOSPL */
1062 
1063     { "kermit",      XXKERMI, CM_INV },
1064 
1065 #ifdef OS2
1066 #ifndef NOKVERBS
1067     { "kverb",       XXKVRB, CM_INV|CM_HLP }, /* Keyboard verb */
1068 #endif /* NOKVERBS */
1069 #endif /* OS2 */
1070 
1071 #ifndef NOFRILLS
1072     { "l",           XXLOG, CM_INV|CM_ABR }, /* Invisible synonym for log */
1073 #endif /* NOFRILLS */
1074 
1075     { "lcd",         XXLCWD, CM_INV },
1076     { "lcdup",       XXLCDU, CM_INV },
1077     { "lcwd",        XXLCWD, CM_INV },
1078     { "ldelete",     XXLDEL, CM_INV },
1079     { "ldirectory",  XXLDIR, CM_INV },
1080 
1081 #ifdef CKLEARN
1082     { "learn",       XXLEARN, 0 },	/* LEARN - automatic script writing */
1083 #else
1084     { "learn",       XXNOTAV, CM_INV },
1085 #endif /* CKLEARN */
1086 
1087     { "li",          XXLNOUT, CM_INV|CM_ABR },
1088     { "LICENSE",     XXCPR, 0 },	/* LICENSE */
1089 
1090 #ifndef NOSPL
1091     { "lineout",     XXLNOUT, 0 },	/* LINEOUT = OUTPUT + eol */
1092 #endif /* NOSPL */
1093 
1094 #ifdef NT
1095     { "link",        XXLINK, 0 },       /* LINK source destination */
1096 #endif /* NT */
1097 
1098     { "lmkdir",      XXLMKD, CM_INV },
1099     { "lmv",         XXLREN, CM_INV },
1100 
1101 #ifndef NOFRILLS
1102     { "lo",          XXLOG,  CM_INV|CM_ABR }, /* Invisible synonym for log */
1103 #endif /* NOFRILLS */
1104 
1105 #ifndef NOSPL
1106     { "local",       XXLOCAL, CM_INV },	/* LOCAL variable declaration */
1107 #else
1108     { "local",       XXNOTAV, CM_INV },
1109 #endif /* NOSPL */
1110 
1111     { "locus",       XXLOCU, CM_INV|CM_HLP }, /* "help locus" */
1112 
1113     { "log",  	     XXLOG, 0 },	/* Open a log file */
1114 
1115     { "login",       XXLOGIN,  0 },	/* (REMOTE) LOGIN to server or IKSD */
1116     { "logout",      XXLOGOUT, 0 },	/* LOGOUT from server or IKSD */
1117 
1118 #ifndef NOFRILLS
1119 #ifndef NODIAL
1120     { "lookup",      XXLOOK,  0 },	/* LOOKUP */
1121 #else
1122     { "lookup",      XXNOTAV, CM_INV },
1123 #endif /* NODIAL */
1124 
1125     { "lpwd",        XXLPWD, CM_INV },
1126     { "lrename",     XXLREN, CM_INV },
1127     { "lrmdir",      XXLRMD, CM_INV },
1128 
1129 #ifdef UNIXOROSK
1130     { "ls",          XXLS,  CM_INV|CM_PSH }, /* UNIX ls command */
1131 #else
1132     { "ls",          XXDIR, CM_INV },	/* Invisible synonym for DIR */
1133 #endif /* UNIXOROSK */
1134 #ifndef NOXFER
1135     { "mail",        XXMAI, 0 },	/* Send a file as e-mail */
1136 #endif /* NOXFER */
1137 #ifndef NOHELP
1138     { "manual",      XXMAN, CM_PSH },	/* MAN(UAL) */
1139 #else
1140     { "manual",      XXNOTAV, CM_INV|CM_PSH },
1141 #endif /* NOHELP */
1142 #endif /* NOFRILLS */
1143 #ifdef CK_MKDIR
1144     { "md",          XXMKDIR, CM_INV },	/* Synonym for MKDIR */
1145 #endif /* CK_MKDIR */
1146     { "message",     XXMSG, 0 },	/* Print debugging message */
1147 #ifdef CK_MINPUT
1148     { "minput",      XXMINP, 0 },	/* MINPUT */
1149 #else
1150     { "minput",      XXNOTAV, CM_INV },
1151 #endif /* CK_MINPUT */
1152 #ifndef NOMSEND
1153     { "mget",        XXMGET, 0 },	/* MGET */
1154 #else
1155     { "mget",        XXNOTAV, CM_INV },
1156 #endif /* NOMSEND */
1157 #ifdef CK_MKDIR
1158     { "mkdir",       XXMKDIR, 0 },	/* MKDIR */
1159 #else
1160     { "mkdir",       XXNOTAV, CM_INV },
1161 #endif /* CK_MKDIR */
1162 
1163 #ifndef NOXFER
1164 #ifndef NOMSEND
1165     { "mmove",       XXMMOVE, 0 },	/* MMOVE */
1166 #else
1167     { "mmove",       XXNOTAV, CM_INV },
1168 #endif /* NOMSEND */
1169 #endif /* NOXFER */
1170 
1171 #ifndef NOFRILLS
1172     { "more",        XXMORE, CM_INV },	/* MORE */
1173 #endif /* NOFRILLS */
1174 
1175 #ifdef OLDMOVE
1176 #ifndef NOXFER
1177     { "move",        XXMOVE, 0 },	/* MOVE = SEND /DELETE */
1178 #endif /* NOXFER */
1179 #else
1180     { "move",        XXREN, CM_INV },	/* MOVE = RENAME */
1181 #endif /* OLDMOVE */
1182 
1183 #ifndef NOSPL
1184     { "mpause",      XXMSL, CM_INV },	/* Millisecond sleep */
1185 #else
1186     { "mpause",      XXNOTAV, CM_INV },
1187 #endif /* NOSPL */
1188 
1189 #ifndef NOXFER
1190 #ifndef NOMSEND
1191     { "mput",        XXMSE, CM_INV },	/* MPUT = MSEND */
1192     { "ms",          XXMSE, CM_INV|CM_ABR },
1193     { "msend",       XXMSE, 0 },	/* Multiple SEND */
1194 #else
1195     { "mput",        XXNOTAV, CM_INV },
1196     { "msend",       XXNOTAV, CM_INV },
1197 #endif /* NOMSEND */
1198 #endif /* NOXFER */
1199     { "msg",         XXMSG, CM_INV },	/* Print debugging message */
1200 #ifndef NOSPL
1201     { "msleep",      XXMSL, 0 },	/* Millisecond sleep */
1202 #else
1203     { "msleep",      XXNOTAV, CM_INV },
1204 #endif /* NOSPL */
1205 #ifndef NOFRILLS
1206     { "mv",          XXREN, CM_INV },	/* Synonym for rename */
1207 #endif /* NOFRILLS */
1208 #ifndef NOHELP
1209     { "news",        XXNEW, CM_INV },	/* Display NEWS of new features */
1210 #else
1211     { "news",        XXNOTAV, CM_INV },
1212 #endif /* NOHELP */
1213     { "nolocal",     XXNLCL, CM_INV },	/* Disable SET LINE / SET HOST */
1214     { "nopush",      XXNPSH, CM_INV },	/* Disable PUSH command/features */
1215 #ifdef OS2
1216     { "noscroll",    XXNSCR, CM_INV },  /* Disable scroll operations */
1217 #endif /* OS2 */
1218 #ifndef NOSPL
1219     { "o",           XXOUT, CM_INV|CM_ABR }, /* Invisible synonym for OUTPUT */
1220     { "open",        XXOPE, 0 },	/* OPEN file for reading or writing */
1221 #else
1222     { "open",        XXOPE, CM_INV },	/* OPEN */
1223 #endif /* NOSPL */
1224 #ifndef NOHELP
1225     { "options",     XXOPTS,CM_INV|CM_HLP }, /* Options */
1226 #endif /* NOHELP */
1227     { "orientation", XXORIE, 0 },
1228 #ifndef NOSPL
1229     { "output",      XXOUT, 0 },	/* OUTPUT text to comm device */
1230 #else
1231     { "output",      XXNOTAV, CM_INV },
1232 #endif /* NOSPL */
1233 #ifdef ANYX25
1234 #ifndef IBMX25
1235     { "pad",         XXPAD, CM_LOC },	/* X.3 PAD commands */
1236 #endif /* IBMX25 */
1237 #endif /* ANYX25 */
1238 
1239 #ifdef NEWFTP
1240     { "passive",     XXPASV, CM_INV },	/* (FTP) PASSIVE */
1241 #endif /* NEWFTP */
1242 
1243 #ifndef NOHELP
1244     { "patterns",    XXPAT,CM_INV|CM_HLP }, /* Pattern syntax */
1245 #endif /* NOHELP */
1246 
1247 #ifndef NOSPL
1248     { "pause",       XXPAU, 0 },	/* Sleep for specified interval */
1249 #else
1250     { "pause",       XXNOTAV, CM_INV },
1251 #endif /* NOSPL */
1252 #ifndef NODIAL
1253     { "pdial",       XXPDIA,  CM_LOC },	/* PDIAL (partial dial) */
1254 #else
1255     { "pdial",       XXNOTAV, CM_INV|CM_LOC },
1256 #endif /* NODIAL */
1257 #ifdef TCPSOCKET
1258 #ifndef NOPUSH
1259     { "ping",        XXPNG, CM_INV|CM_PSH|CM_LOC }, /* PING */
1260 #else
1261     { "ping",        XXNOTAV, CM_INV|CM_PSH|CM_LOC },
1262 #endif /* NOPUSH */
1263 #endif /* TCPSOCKET */
1264 #ifdef NETCMD
1265 #ifndef NOPUSH
1266     { "pipe",        XXPIPE, CM_PSH },	/* PIPE */
1267 #else
1268     { "pipe",        XXNOTAV, CM_INV|CM_PSH }, /* PIPE */
1269 #endif /* NOPUSH */
1270 #endif /* NETCMD */
1271 
1272 #ifndef NOSPL
1273     { "pop",         XXEND, CM_INV },	/* Invisible synonym for END */
1274 #endif /* NOSPL */
1275 #ifndef NOFRILLS
1276     { "print",       XXPRI, 0 },	/* PRINT a file locally */
1277 #endif /* NOFRILLS */
1278 
1279     { "prompt",      XXPROMP, CM_INV },	/* Go interactive (from script) */
1280 
1281 #ifndef NOXFER
1282 #ifdef CK_RESEND
1283     { "psend",       XXPSEN, CM_INV },	/* PSEND */
1284 #else
1285     { "psend",       XXNOTAV, CM_INV },
1286 #endif /* CK_RESEND */
1287 #endif /* NOXFER */
1288 
1289 #ifdef NETPTY
1290     { "pty",         XXPTY, CM_PSH },	/* PTY */
1291 #else
1292     { "pty",         XXNOTAV, CM_INV|CM_PSH },
1293 #endif /* NETPTY */
1294 
1295 #ifndef NOPUSH
1296     { "pu",          XXSHE, CM_INV|CM_ABR|CM_PSH }, /* PU = PUSH */
1297 #endif /* NOPUSH */
1298 
1299 #ifdef CKPURGE
1300     { "purge",       XXPURGE, 0 },	/* PURGE (real) */
1301 #else
1302 #ifdef VMS
1303     { "purge",       XXPURGE, 0 },	/* PURGE (fake) */
1304 #else
1305     { "purge",       XXNOTAV, CM_INV },
1306 #endif /* VMS */
1307 #endif /* CKPURGE */
1308 
1309 #ifndef NOPUSH
1310     { "push",        XXSHE, CM_PSH },	/* PUSH command (like RUN, !) */
1311 #else
1312     { "push",        XXNOTAV, CM_INV|CM_PSH },
1313 #endif /* NOPUSH */
1314 
1315 #ifndef NOXFER
1316     { "put",         XXSEN, CM_INV },	/* PUT = SEND */
1317 #endif /* NOXFER */
1318 
1319 #ifdef UNIX
1320 #ifndef NOPUTENV
1321     { "putenv",      XXPUTE, CM_INV },	/* PUTENV */
1322 #endif	/* NOPUTENV */
1323 #endif	/* UNIX */
1324 
1325     { "pwd",         XXPWD, 0 },	/* Print Working Directory */
1326     { "q",           XXQUI, CM_INV|CM_ABR }, /* Invisible synonym for QUIT */
1327 
1328 #ifndef NOXFER
1329     { "query",       XXRQUE,CM_INV },	/* (= REMOTE QUERY) */
1330 #endif /* NOXFER */
1331 
1332     { "quit",        XXQUI, 0 },	/* QUIT from program = EXIT */
1333 
1334 #ifndef NOXFER
1335     { "r",           XXREC, CM_INV|CM_ABR }, /* Inv synonym for RECEIVE */
1336 #endif /* NOXFER */
1337 
1338 #ifndef NOXFER
1339     { "rasg",        XXRASG, CM_INV },	/* REMOTE ASSIGN */
1340     { "rassign",     XXRASG, CM_INV },	/* ditto */
1341     { "rcd",         XXRCWD, CM_INV },	/* REMOTE CD */
1342     { "rcdup",       XXRCDUP,CM_INV },	/* REMOTE CD */
1343     { "rcopy",       XXRCPY, CM_INV },	/* REMOTE COPY */
1344     { "rcwd",        XXRCWD, CM_INV },	/* REMOTE CWD */
1345     { "rdelete",     XXRDEL, CM_INV },	/* REMOTE DELETE */
1346     { "rdirectory",  XXRDIR, CM_INV },	/* REMODE DIRECTORY */
1347 #endif /* NOXFER */
1348 
1349 #ifndef NOSPL
1350     { "read",        XXREA, 0 },	/* READ a line from a file */
1351 #else
1352     { "read",        XXNOTAV, CM_INV },
1353 #endif /* NOSPL */
1354 
1355 #ifndef NOXFER
1356     { "receive",     XXREC, 0 },	/* RECEIVE files */
1357 #endif /* NOXFER */
1358 
1359 #ifndef NODIAL
1360     { "red",         XXRED, CM_INV|CM_ABR|CM_LOC }, /* Inv syn for REDIAL */
1361     { "redi",        XXRED, CM_INV|CM_ABR|CM_LOC }, /* ditto */
1362     { "redial",      XXRED, CM_LOC },	/* REDIAL last DIAL number */
1363 #else
1364     { "red",         XXNOTAV, CM_INV|CM_LOC },
1365     { "redi",        XXNOTAV, CM_INV|CM_LOC },
1366     { "redial",      XXNOTAV, CM_INV|CM_LOC },
1367 #endif /* NODIAL */
1368 
1369 #ifdef CK_REDIR
1370 #ifdef OS2
1371 #ifndef NOPUSH
1372     { "redirect",    XXFUN, CM_INV|CM_PSH }, /* REDIRECT */
1373 #else
1374     { "redirect",    XXNOTAV, CM_INV|CM_PSH },
1375 #endif /* NOPUSH */
1376 #else /* OS2 */
1377 #ifndef NOPUSH
1378     { "redirect",    XXFUN, CM_PSH },	/* REDIRECT */
1379 #else
1380     { "redirect",    XXNOTAV, CM_INV|CM_PSH },
1381 #endif /* NOPUSH */
1382 #endif /* OS2 */
1383 #endif /* CK_REDIR */
1384 
1385 #ifdef CK_RECALL
1386     { "redo",        XXREDO,  CM_NOR },	/* REDO */
1387 #else
1388     { "redo",        XXNOTAV, CM_INV },
1389 #endif /* CK_RECALL */
1390 
1391 #ifndef NOXFER
1392 #ifdef CK_RESEND
1393     { "reget",       XXREGET, 0 },	/* REGET */
1394 #else
1395     { "reget",       XXNOTAV, CM_INV },
1396 #endif /* CK_RESEND */
1397 #endif /* NOXFER */
1398 
1399 #ifndef NOSPL
1400     { "reinput",     XXREI, CM_INV },	/* REINPUT (from INPUT buffer) */
1401 #else
1402     { "reinput",     XXNOTAV, CM_INV },
1403 #endif /* NOSPL */
1404 
1405 #ifndef NOXFER
1406 #ifdef ADDCMD
1407     { "rem",         XXREM, CM_INV|CM_ABR },
1408     { "remo",        XXREM, CM_INV|CM_ABR },
1409 #endif /* ADDCMD */
1410     { "remote",	     XXREM, 0 },	/* Send REMOTE command to server */
1411 #endif /* NOXFER */
1412 
1413 #ifdef ADDCMD
1414     { "remove",      XXREMV,0 },	/* REMOVE (something from a list) */
1415 #else
1416     { "remove",      XXNOTAV, CM_INV },
1417 #endif /* ADDCMD */
1418 
1419 #ifndef NOFRILLS
1420 #ifndef NORENAME
1421     { "rename",      XXREN, 0 },	/* RENAME a local file */
1422 #else
1423     { "rename",      XXNOTAV, CM_INV },
1424 #endif /* NORENAME */
1425     { "replay",      XXTYP, CM_INV },	/* REPLAY (for now, just type) */
1426 #endif /* NOFRILLS */
1427 
1428 #ifndef NOXFER
1429 #ifdef CK_RESEND
1430     { "rep",         XXTYP, CM_INV|CM_ABR },  /* REPLAY abbreviation */
1431     { "reput",       XXRSEN, CM_INV },	      /* REPUT = RESEND */
1432     { "res",         XXRSEN, CM_INV|CM_ABR }, /* RESEND */
1433     { "rese",        XXRSEN, CM_INV|CM_ABR }, /* RESEND */
1434     { "resend",      XXRSEN, 0 },	/* RESEND */
1435 #else
1436     { "reput",       XXNOTAV, CM_INV },
1437     { "res",         XXNOTAV, CM_INV },
1438     { "rese",        XXNOTAV, CM_INV },
1439     { "resend",      XXNOTAV, CM_INV },
1440 #endif /* CK_RESEND */
1441 #endif /* NOXFER */
1442 
1443     { "reset",       XXRESET, CM_INV },	/* RESET */
1444 
1445 #ifdef CK_RESEND
1446 #ifndef NOSPL
1447     { "ret",         XXRET, CM_INV|CM_ABR },
1448 #endif /* NOSPL */
1449 #endif /* CK_RESEND */
1450 
1451 #ifndef NOXFER
1452     { "retrieve",    XXRETR, CM_INV },	/* RETRIEVE */
1453 #endif /* NOXFER */
1454 
1455 #ifndef NOSPL
1456     { "return",      XXRET, 0 },	/* RETURN from a function */
1457 #else
1458     { "return",      XXNOTAV, CM_INV },
1459 #endif /* NOSPL */
1460 
1461 #ifndef NOXFER
1462     { "rexit",       XXRXIT, CM_INV },	/* REMOTE EXIT */
1463 #endif /* NOXFER */
1464 
1465 #ifdef CK_REXX
1466 #ifndef NOPUSH
1467     { "rexx",        XXREXX, CM_PSH },	/* Execute a Rexx command */
1468 #else
1469     { "rexx",        XXNOTAV, CM_INV|CM_PSH },
1470 #endif /* NOPUSH */
1471 #endif /* CK_REXX */
1472 
1473 #ifndef NOXFER
1474     { "rhelp",       XXRHLP, CM_INV },	/* REMOTE HELP */
1475     { "rhost",       XXRHOS, CM_INV },	/* REMOTE HOST */
1476     { "rkermit",     XXRKER, CM_INV },	/* REMOTE KERMIT */
1477 #endif /* NOXFER */
1478 
1479 #ifdef TCPSOCKET
1480     { "rlogin",      XXRLOG, CM_LOC },	/* Make an Rlogin connection */
1481 #else
1482     { "rlogin",      XXNOTAV, CM_INV|CM_LOC },
1483 #endif /* TCPSOCKET */
1484 
1485 #ifndef NOFRILLS
1486     { "rm",          XXDEL, CM_INV },	/* Invisible synonym for delete */
1487 #endif /* NOFRILLS */
1488 
1489 #ifdef CK_MKDIR
1490     { "rmdir",       XXRMDIR, 0 },	/* RMDIR */
1491 #else
1492     { "rmdir",       XXNOTAV, CM_INV },
1493 #endif /* CK_MKDIR */
1494 
1495 #ifndef NOXFER
1496     { "rmessage",    XXRMSG, CM_INV },	/* REMOTE MESSAGE */
1497     { "rmkdir",      XXRMKD, CM_INV },	/* REMOTE MKDIR */
1498     { "rmsg",        XXRMSG, CM_INV },	/* REMOTE MESSAGE */
1499 #ifndef NOSPL
1500     { "robust",      XXROB,  CM_INV },
1501 #else
1502     { "robust",      XXNOTAV, CM_INV },
1503 #endif /* NOSPL */
1504     { "rprint",      XXRPRI, CM_INV },  /* REMOTE PRINT */
1505     { "rpwd",        XXRPWD, CM_INV },	/* REMOTE PWD */
1506     { "rquery",      XXRQUE, CM_INV },	/* REMOTE QUERY */
1507 #endif /* NOXFER */
1508 
1509 #ifdef CK_RECALL
1510     { "rr",          XXREDO, CM_INV|CM_NOR },
1511 #endif /* CK_RECALL */
1512 
1513 #ifndef NOXFER
1514     { "rrename",    XXRREN, CM_INV },	/* REMOTE RENAME */
1515     { "rrmdir",     XXRRMD, CM_INV },	/* REMOTE REMDIR */
1516     { "rset",       XXRSET, CM_INV },	/* REMOTE SET */
1517     { "rspace",     XXRSPA, CM_INV },	/* REMOTE SPACE */
1518     { "rtype",      XXRTYP, CM_INV },	/* REMOTE TYPE */
1519 #endif /* NOXFER */
1520 
1521 #ifndef NOPUSH
1522     { "run",         XXSHE, CM_PSH },	/* RUN a program or command */
1523 #else
1524     { "run",         XXNOTAV, CM_INV|CM_PSH },
1525 #endif /* NOPUSH */
1526 
1527 #ifndef NOXFER
1528     { "rwho",        XXRWHO, CM_INV },	/* REMOTE WHO */
1529     { "s",           XXSEN, CM_INV|CM_ABR }, /* Invisible synonym for send */
1530 #endif /* NOXFER */
1531 
1532 #ifndef NOSETKEY
1533 #ifdef OS2
1534     { "save",	   XXSAVE, 0 },		/* SAVE something */
1535 #else
1536     { "save",	   XXSAVE, CM_INV },
1537 #endif /* OS2 */
1538 #else
1539     { "save",	   XXNOTAV, CM_INV },
1540 #endif /* NOSETKEY */
1541 
1542 #ifndef NOSCRIPT
1543     { "sc", 	   XXLOGI, CM_INV|CM_ABR|CM_LOC },
1544     { "scr",	   XXLOGI, CM_INV|CM_ABR|CM_LOC },
1545 #endif /* NOSCRIPT */
1546     { "screen",      XXSCRN, 0 },	/* SCREEN actions */
1547 #ifndef NOSCRIPT
1548     { "script",	   XXLOGI, CM_LOC },	/* Expect-Send-style script line */
1549 #else
1550     { "script",	   XXNOTAV, CM_INV|CM_LOC },
1551 #endif /* NOSCRIPT */
1552 
1553     { "search",    XXGREP,CM_INV },	/* Synonym for GREP and FIND */
1554 
1555 #ifndef NOXFER
1556     { "send",	   XXSEN, 0 },		/* Send (a) file(s) */
1557 #ifndef NOSERVER
1558     { "server",	   XXSER, 0 },		/* Be a SERVER */
1559 #else
1560     { "server",	   XXNOTAV, CM_INV },
1561 #endif /* NOSERVER */
1562 #endif /* NOXFER */
1563 
1564     { "set",	   XXSET, 0 },		/* SET parameters */
1565 
1566 #ifndef NOSPL
1567 #ifndef NOSEXP
1568     { "sexpression", XXSEXP, CM_INV|CM_HLP }, /* SEXPR */
1569 #endif /* NOSEXP */
1570 
1571 #ifdef SFTP_BUILTIN
1572     { "sftp",        XXSFTP, 0 },   /* SFTP */
1573 #endif /* SFTP_BUILTIN */
1574 
1575 #ifndef NOSHOW
1576     { "sh",          XXSHO, CM_INV|CM_ABR }, /* SHOW parameters */
1577 #endif /* NOSHOW */
1578     { "shift",       XXSHIFT, 0 },	/* SHIFT args */
1579 #else
1580     { "shift",       XXNOTAV, CM_INV },
1581 #endif /* NOSPL */
1582 
1583 #ifndef NOSHOW
1584     { "show", 	   XXSHO, 0 },		/* SHOW parameters */
1585 #else
1586     { "show", 	   XXNOTAV, CM_INV },
1587 #endif /* NOSHOW */
1588 
1589 #ifdef NEWFTP
1590     { "site",        XXSITE, CM_INV },	/* (FTP) SITE */
1591 #endif /* NEWFTP */
1592 
1593 #ifdef SSHBUILTIN
1594     { "skermit",   XXSKRM, 0 },     /* SKERMIT */
1595 #endif /* SSHBUILTIN */
1596 
1597 #ifndef NOSPL
1598 #ifndef NOFRILLS
1599     { "sleep",       XXPAU, CM_INV },	/* SLEEP for specified interval */
1600 #endif /* NOFRILLS */
1601 #endif /* NOSPL */
1602 
1603 #ifndef NOSPL
1604     { "sort",        XXSORT, CM_INV },	/* (see ARRAY) */
1605 #else
1606     { "sort",        XXNOTAV, CM_INV },
1607 #endif /* NOSPL */
1608 
1609 #ifndef MAC
1610 #ifndef NOFRILLS
1611     { "sp",          XXSPA, CM_INV|CM_ABR },
1612     { "spa",         XXSPA, CM_INV|CM_ABR },
1613 #endif /* NOFRILLS */
1614     { "space",       XXSPA, 0 },	/* Show available disk SPACE */
1615 #endif /* MAC */
1616 
1617 #ifndef NOFRILLS
1618 #ifndef NOPUSH
1619     { "spawn",       XXSHE, CM_INV|CM_PSH }, /* Synonym for PUSH, RUN */
1620 #else
1621     { "spawn",       XXNOTAV, CM_INV|CM_PSH }, /* Synonym for PUSH, RUN */
1622 #endif /* NOPUSH */
1623 #endif /* NOFRILLS */
1624 
1625 #ifdef ANYSSH
1626     { "ssh",         XXSSH, 0 },
1627 #endif /* ANYSSH */
1628 
1629 #ifndef NOXFER
1630     { "sta",         XXSTA, CM_INV|CM_ABR },
1631     { "stat",        XXSTA, CM_INV|CM_ABR },
1632     { "statistics",  XXSTA, 0 },	/* Display file transfer stats */
1633 #endif /* NOXFER */
1634 
1635     { "status",      XXSTATUS,0 },	/* Show status of previous command */
1636 
1637 #ifndef NOSPL
1638     { "stop",        XXSTO,   0 },	/* STOP all take files and macros */
1639     { "succeed",     XXSUCC,  CM_INV },	/* SUCCEED */
1640 #else
1641     { "stop",        XXNOTAV, CM_INV },
1642     { "succeed",     XXNOTAV, CM_INV },
1643 #endif /* NOSPL */
1644 
1645 #ifndef NOFRILLS
1646     { "SUPPORT",     XXBUG, 0 },	/* Tech support instructions */
1647 #else
1648     { "support",     XXNOTAV, CM_INV },
1649 #endif /* NOFRILLS */
1650 
1651 #ifndef NOJC
1652     { "suspend",     XXSUS, CM_PSH },	/* SUSPEND C-Kermit (UNIX only) */
1653 #else
1654     { "suspend",     XXNOTAV, CM_INV|CM_PSH },
1655 #endif /* NOJC */
1656 
1657 #ifndef NOSPL
1658     { "switch",      XXSWIT, 0 },	/* SWITCH */
1659 #else
1660     { "switch",      XXNOTAV, CM_INV },
1661 #endif /* NOSPL */
1662 
1663 #ifdef CK_TAPI
1664     { "ta",	   XXTAK, CM_INV|CM_ABR }, /* (because of TAPI) */
1665 #endif /* CK_TAPI */
1666 
1667 #ifndef NOFRILLS
1668     { "tail",        XXTAIL, 0 },	/* Display end of a local file */
1669 #endif /* NOFRILLS */
1670 
1671     { "take",	   XXTAK, 0 },		/* TAKE commands from a file */
1672 
1673 #ifdef CK_TAPI
1674     { "tapi",	   XXTAPI, CM_LOC },	/* Microsoft TAPI commands */
1675 #else
1676     { "tapi",	   XXNOTAV, CM_INV|CM_LOC },
1677 #endif /* CK_TAPI */
1678 
1679 #ifndef NOFRILLS
1680 #ifdef TCPSOCKET
1681     { "tel",         XXTEL, CM_INV|CM_ABR|CM_LOC },
1682     { "telnet",      XXTEL, CM_LOC },	/* TELNET (TCP/IP only) */
1683     { "telopt",      XXTELOP, CM_INV },	/* TELOPT (ditto) */
1684 #else
1685     { "tel",         XXNOTAV, CM_INV|CM_LOC },
1686     { "telnet",      XXNOTAV, CM_INV|CM_LOC },
1687     { "telopt",      XXNOTAV, CM_INV },
1688 #endif /* TCPSOCKET */
1689 #ifdef OS2
1690     { "terminal",    XXTERM, CM_INV|CM_LOC }, /* == SET TERMINAL TYPE */
1691 #else
1692     { "terminal",    XXTERM, CM_INV },
1693 #endif /* OS2 */
1694 #endif /* NOFRILLS */
1695 #ifndef NOXFER
1696     { "text",        XXASC, CM_INV },	/* == SET FILE TYPE TEXT */
1697 #endif /* NOXFER */
1698     { "touch",       XXTOUC, 0 },	/* TOUCH */
1699 #ifndef NOSPL
1700     { "trace",       XXTRACE, 0 },	/* TRACE */
1701 #else
1702     { "trace",       XXNOTAV, CM_INV },
1703 #endif /* NOSPL */
1704 
1705 #ifndef NOCSETS
1706     { "translate",   XXXLA, 0 },	/* TRANSLATE local file char sets */
1707 #else
1708     { "translate",   XXNOTAV, CM_INV },
1709 #endif /* NOCSETS */
1710 
1711 #ifndef NOXMIT
1712     { "transmit",    XXTRA, 0 },	/* Send (upload) a file, no protocol */
1713 #else
1714     { "transmit",    XXNOTAV, CM_INV },
1715 #endif /* NOXMIT */
1716 
1717 #ifndef NOFRILLS
1718     { "type",        XXTYP, 0 },	/* Display a local file */
1719 #endif /* NOFRILLS */
1720 
1721 #ifndef NOSPL
1722     { "undcl",       XXUNDCL, CM_INV },
1723     { "undeclare",   XXUNDCL, 0 },	/* UNDECLARE an array */
1724     { "undefine",    XXUNDEF, 0 },	/* UNDEFINE a variable or macro */
1725 #else
1726     { "undcl",       XXNOTAV, CM_INV },
1727     { "undeclare",   XXNOTAV, CM_INV },
1728     { "undefine",    XXNOTAV, CM_INV },
1729 #endif /* NOSPL */
1730 
1731 #ifdef NEWFTP
1732     { "user",        XXUSER,  CM_INV }, /* (FTP) USER */
1733 #endif /* NEWFTP */
1734 
1735     { "version",     XXVER, 0 },	/* VERSION-number display */
1736 
1737 #ifdef OS2
1738     { "viewonly",    XXVIEW, CM_LOC },	/* VIEWONLY Terminal Mode */
1739 #endif /* OS2 */
1740 
1741     { "void",        XXVOID, 0 },	/* VOID */
1742 
1743 #ifndef NOSPL
1744     { "wait",        XXWAI, 0 },	/* WAIT */
1745 #else
1746     { "wait",        XXNOTAV, CM_INV },
1747 #endif /* NOSPL */
1748 
1749     { "wdirectory",  XXWDIR,  CM_INV },	/* Like TOPS-20, reverse chron order */
1750     { "wermit",      XXKERMI, CM_INV },
1751 
1752 #ifndef NOXFER
1753     { "where",       XXWHERE, 0 },	/* WHERE (did my file go?) */
1754 #endif /* NOXFER */
1755 
1756 #ifndef NOSPL
1757     { "while",       XXWHI, 0 },	/* WHILE loop */
1758 #else
1759     { "while",       XXNOTAV, CM_INV },
1760 #endif /* NOSPL */
1761 
1762 #ifndef OS2
1763 #ifndef MAC
1764 #ifndef NOFRILLS
1765     { "who",         XXWHO, CM_PSH },	/* WHO's logged in? */
1766 #endif /* NOFRILLS */
1767 #endif /* MAC */
1768 #endif /* OS2 */
1769 
1770 #ifndef NOHELP
1771     { "wildcards",   XXWILD,CM_INV|CM_HLP }, /* Wildcard syntax */
1772 #endif /* NOHELP */
1773 
1774 #ifndef NOSPL
1775     { "wr",          XXWRI, CM_INV|CM_ABR },
1776     { "wri",         XXWRI, CM_INV|CM_ABR },
1777     { "writ",        XXWRI, CM_INV|CM_ABR },
1778     { "write",       XXWRI, 0 },	/* WRITE characters to a file */
1779     { "write-line",  XXWRL, CM_INV },	/* WRITE a line to a file */
1780     { "writeln",     XXWRL, CM_INV },	/* Pascalisch synonym for write-line */
1781 #else
1782     { "wr",          XXNOTAV, CM_INV },
1783     { "wri",         XXNOTAV, CM_INV },
1784     { "writ",        XXNOTAV, CM_INV },
1785     { "write",       XXNOTAV, CM_INV },
1786     { "write-line",  XXNOTAV, CM_INV },
1787     { "writeln",     XXNOTAV, CM_INV },
1788 #endif /* NOSPL */
1789 
1790 #ifndef NOFRILLS
1791     { "xecho",       XXXECH,0 },	/* XECHO */
1792 #endif /* NOFRILLS */
1793 
1794 #ifndef NOSPL
1795     { "xif",         XXIFX, CM_INV },	/* Extended IF command (obsolete) */
1796 #else
1797     { "xif",         XXNOTAV, CM_INV },
1798 #endif /* NOSPL */
1799 
1800 #ifndef NOCSETS
1801     { "xlate",       XXXLA, CM_INV },	/* Synonym for TRANSLATE */
1802 #else
1803     { "xlate",       XXNOTAV, CM_INV },
1804 #endif /* NOCSETS */
1805 
1806 #ifndef NOXMIT
1807     { "xm",          XXTRA, CM_INV|CM_ABR }, /* Avoid conflict with XMESSAGE */
1808 #else
1809     { "xm",          XXNOTAV, CM_INV|CM_ABR }, /* Synonym for TRANSMIT */
1810 #endif /* NOXMIT */
1811 
1812     { "xmessage",    XXXMSG, 0 },	/* Print debugging message */
1813 
1814 #ifndef NOXMIT
1815     { "xmit",        XXTRA, CM_INV },	/* Synonym for TRANSMIT */
1816 #else
1817     { "xmit",        XXNOTAV, CM_INV },
1818 #endif /* NOXMIT */
1819 
1820     { "xmsg",    XXXMSG, CM_INV },	/* Synonym for XMESSAGE */
1821 
1822 #ifndef OS2
1823 #ifndef NOJC
1824     { "z",           XXSUS, CM_INV|CM_PSH }, /* Synonym for SUSPEND */
1825 #else
1826     { "z",           XXNOTAV, CM_INV|CM_PSH },
1827 #endif /* NOJC */
1828 #endif /* OS2 */
1829 
1830 #ifndef NOSPL
1831     { "{",           XXMACRO, CM_INV },	/* Immediate macro */
1832 #endif /* NOSPL */
1833     { "", 0, 0 }
1834 };
1835 int ncmd = (sizeof(cmdtab) / sizeof(struct keytab)) - 1;
1836 
1837 /* NOTE: Tokens must also be entered above into cmdtab[]. */
1838 
1839 char toktab[] = {
1840 #ifndef NOPUSH
1841     '!',				/* Shell escape */
1842 #endif /* NOPUSH */
1843     '#',				/* Comment */
1844 #ifndef NOSPL
1845     '(',				/* S-Expression */
1846     '.',				/* Assignment */
1847 #endif /* NOSPL */
1848     ';',				/* Comment */
1849 #ifndef NOSPL
1850     ':',				/* Label */
1851 #endif /* NOSPL */
1852 #ifndef NOPUSH
1853 #ifdef CK_REDIR
1854     '<',				/* REDIRECT */
1855 #endif /* CK_REDIR */
1856     '@',				/* DCL escape */
1857 #endif /* NOPUSH */
1858 #ifdef CK_RECALL
1859     '^',				/* Command recall */
1860 #endif /* CK_RECALL */
1861 #ifndef NOSPL
1862     '{',				/* Immediate macro */
1863 #endif /* NOSPL */
1864     '\0'				/* End of this string */
1865 };
1866 int xxdot = 0;				/* Used with "." token */
1867 
1868 struct keytab yesno[] = {		/* Yes/No keyword table */
1869     { "no",    0, 0 },
1870     { "ok",    1, 0 },
1871     { "yes",   1, 0 }
1872 };
1873 int nyesno = (sizeof(yesno) / sizeof(struct keytab));
1874 
1875 /* Save keyword table */
1876 
1877 struct keytab savtab[] = {
1878 #ifdef OS2
1879     { "command",  XSCMD, 0 },
1880 #else
1881 #ifdef CK_RECALL
1882     { "command",  XSCMD, 0 },
1883 #endif /* CK_RECALL */
1884 #endif /* OS2 */
1885 #ifndef NOSETKEY
1886     { "keymap",   XSKEY, 0 },
1887 #endif /* NOSETKEY */
1888 #ifdef OS2
1889     { "terminal", XSTERM, 0 },
1890 #endif /* OS2 */
1891     { "", 0, 0 }
1892 };
1893 int nsav = (sizeof(savtab) / sizeof(struct keytab)) - 1;
1894 
1895 /* Parameter keyword table */
1896 
1897 struct keytab prmtab[] = {
1898     { "alarm",            XYALRM,  0 },
1899 #ifdef COMMENT				/* SET ANSWER not implemented yet */
1900 #ifndef NODIAL
1901     { "answer",           XYANSWER,0 },
1902 #endif /* NODIAL */
1903 #endif /* COMMENT */
1904     { "ask-timer",        XYTIMER, 0 },
1905 #ifndef NOXFER
1906     { "attributes",       XYATTR,  0 },
1907 #endif /* NOXFER */
1908 #ifdef CK_AUTHENTICATION
1909     { "authentication",   XYAUTH,  0 },
1910 #else  /* CK_AUTHENTICATION */
1911 #ifdef CK_SSL
1912     { "authentication",   XYAUTH,  0 },
1913 #endif /* CK_SSL */
1914 #endif /* CK_AUTHENTICATION */
1915     { "b",		  XYBACK,  CM_INV|CM_ABR|CM_PSH },
1916     { "ba",		  XYBACK,  CM_INV|CM_ABR|CM_PSH },
1917 #ifdef VMS
1918     { "background",       XYBACK,  CM_INV|CM_PSH },
1919     { "batch",            XYBACK,  CM_PSH },
1920 #else
1921     { "background",       XYBACK,  CM_PSH },
1922     { "batch",            XYBACK,  CM_INV|CM_PSH },
1923 #endif /* VMS */
1924 #ifndef NOLOCAL
1925     { "baud",	          XYSPEE,  CM_INV|CM_LOC },
1926 #endif /* NOLOCAL */
1927     { "bell",             XYBELL,  0 },
1928 #ifndef NOXFER
1929     { "block-check",  	  XYCHKT,  0 },
1930 #endif /* NOXFER */
1931 #ifdef OS2
1932 #ifdef BPRINT
1933     { "bprinter",         XYBDCP,  CM_INV },
1934 #endif /* BPRINT */
1935 #endif /*  OS2 */
1936 #ifdef BROWSER
1937     { "browser",          XYBROWSE,CM_PSH|CM_LOC },
1938 #endif /* BROWSER */
1939 #ifndef NOXFER
1940 #ifdef DYNAMIC
1941     { "buffers",          XYBUF,   0 },
1942 #endif /* DYNAMIC */
1943 #endif /* NOXFER */
1944 #ifndef NOLOCAL
1945 #ifndef MAC
1946     { "carrier-watch",    XYCARR,  CM_LOC },
1947 #endif /* MAC */
1948 #endif /* NOLOCAL */
1949 #ifndef NOSPL
1950     { "case",             XYCASE,  0 },
1951 #endif /* NOSPL */
1952     { "cd",               XYCD,    0 },
1953 #ifndef NOXFER
1954     { "cl",               XYCLEAR, CM_INV|CM_ABR },
1955     { "cle",              XYCLEAR, CM_INV|CM_ABR },
1956     { "clea",             XYCLEAR, CM_INV|CM_ABR },
1957     { "clear",            XYCLEAR, CM_INV|CM_ABR },
1958     { "clear-channel",    XYCLEAR, 0 },
1959     { "clearchannel",     XYCLEAR, CM_INV },
1960 #endif /* NOXFER */
1961 #ifndef NOLOCAL
1962     { "close-on-disconnect", XYDISC, CM_INV|CM_LOC },
1963 #endif /* NOLOCAL */
1964     { "cmd",              XYCMD,   CM_INV },
1965     { "command",          XYCMD,   0 },
1966 #ifdef CK_SPEED
1967     { "con",              XYQCTL,  CM_INV|CM_ABR },
1968 #endif /* CK_SPEED */
1969     { "console",          XYCMD,   CM_INV },
1970 #ifdef CK_SPEED
1971     { "control-character",XYQCTL,  0 },
1972 #endif /* CK_SPEED */
1973 #ifndef NOSPL
1974     { "count",            XYCOUN,  0 },
1975 #endif /* NOSPL */
1976 #ifndef NOXFER
1977     { "d",		  XYDELA,  CM_INV|CM_ABR },
1978     { "de",		  XYDELA,  CM_INV|CM_ABR },
1979 #endif /* NOXFER */
1980     { "debug",            XYDEBU,  0 },
1981 #ifdef VMS
1982     { "default",          XYDFLT,  0 },
1983 #else
1984 #ifndef MAC
1985     { "default",          XYDFLT,  CM_INV },
1986 #endif /* MAC */
1987 #endif /* VMS */
1988 #ifndef NOXFER
1989     { "delay",	    	  XYDELA,  0 },
1990     { "destination",	  XYDEST,  0 },
1991 #endif /* NOXFER */
1992 #ifndef NODIAL
1993     { "di",		  XYDIAL,  CM_INV|CM_ABR|CM_LOC },
1994     { "dia",		  XYDIAL,  CM_INV|CM_ABR|CM_LOC },
1995     { "dial",             XYDIAL,  CM_LOC },
1996 #endif /* NODIAL */
1997 #ifdef OS2
1998     { "dialer",		  XYDLR,   CM_INV },
1999 #endif /* OS2 */
2000 #ifndef NOLOCAL
2001     { "disconnect",       XYDISC,  CM_LOC },
2002     { "duplex",	    	  XYDUPL,  CM_LOC },
2003 #endif /* NOLOCAL */
2004 #ifndef NOPUSH
2005 #ifndef NOFRILLS
2006     { "editor",           XYEDIT,  CM_PSH },
2007 #endif /*  NOFRILLS */
2008 #endif /* NOPUSH */
2009 #ifdef CK_CTRLZ
2010     { "eof",              XYEOF,   CM_INV },
2011 #endif /* CK_CTRLZ */
2012 #ifndef NOLOCAL
2013     { "escape-character", XYESC,   CM_LOC },
2014 #endif /* NOLOCAL */
2015 #ifndef NOSPL
2016     { "evaluate",         XYEVAL,  CM_INV },
2017 #endif /* NOSPL */
2018     { "exit",		  XYEXIT,  0 },
2019 #ifndef NOXFER
2020 #ifdef CK_XYZ
2021 #ifndef NOPUSH
2022 #ifndef XYZ_INTERNAL
2023     { "external-protocol",XYEXTRN, 0 },
2024 #endif	/* XYZ_INTERNAL */
2025 #endif	/* NOPUSH */
2026 #endif	/* CK_XYZ */
2027     { "f-ack-bug",        XYFACKB, CM_INV },
2028     { "f-ack-path",       XYFACKP, CM_INV },
2029 #endif /* NOXFER */
2030     { "file", 	  	  XYFILE,  0 },
2031     { "fl",           	  XYFLOW,  CM_INV|CM_ABR },
2032 #ifndef NOSPL
2033     { "flag",             XYFLAG,  0 },
2034 #endif /* NOSPL */
2035 #ifdef TCPSOCKET
2036 #ifndef SYSFTP
2037 #ifndef NOFTP
2038     { "ft",   	          XYFTPX,  CM_INV|CM_ABR },
2039     { "ftp",  	          XYFTPX,  0 },
2040 #endif /* NOFTP */
2041 #endif /* SYSFTP */
2042 #endif /* TCPSOCKET */
2043 #ifdef BROWSER
2044     { "ftp-client",       XYFTP,   CM_PSH },
2045 #endif /* BROWSER */
2046     { "flow-control", 	  XYFLOW,  0 },
2047 #ifndef NOSPL
2048     { "function",         XYFUNC,  0 },
2049 #endif /* NOSPL */
2050 #ifdef NEWFTP
2051     { "get-put-remote",   XYGPR,   0 },
2052 #endif /* NEWFTP */
2053 #ifdef KUI
2054     { "gui",              XYGUI,   0 },
2055 #endif /* KUI */
2056     { "handshake",    	  XYHAND,  0 },
2057     { "hints",            XYHINTS, 0 },
2058 #ifdef NETCONN
2059     { "host",             XYHOST,  CM_LOC },
2060 #endif /* NETCONN */
2061 #ifndef NOSPL
2062     { "i",		  XYINPU,  CM_INV|CM_ABR },
2063 #endif /* NOSPL */
2064 #ifdef IKSD
2065     { "iks",              XYIKS,   0 },
2066 #else
2067     { "iks",              XYIKS,   CM_INV },
2068 #endif /* IKSD */
2069 #ifndef NOSPL
2070     { "in",		  XYINPU,  CM_INV|CM_ABR },
2071 #endif /* NOSPL */
2072 #ifndef NOXFER
2073     { "incomplete",   	  XYIFD,   CM_INV },
2074 #endif /* NOXFER */
2075 #ifndef NOSPL
2076     { "input",            XYINPU,  0 },
2077 #endif /* NOSPL */
2078 #ifndef NOSETKEY
2079     { "key",		  XYKEY,   0 },
2080 #endif /* NOSETKEY */
2081     { "l",                XYLINE,  CM_INV|CM_ABR },
2082 #ifndef NOCSETS
2083     { "language",         XYLANG,  0 },
2084 #endif /* NOCSETS */
2085 #ifndef NOLOCAL
2086     { "line",             XYLINE,  CM_LOC },
2087     { "local-echo",	  XYLCLE,  CM_INV|CM_LOC },
2088 #endif /* NOLOCAL */
2089 #ifdef HAVE_LOCALE
2090     { "locale",           XYLOCALE,0 },
2091 #endif /* HAVE_LOCALE */
2092 #ifdef LOCUS
2093     { "locus",            XYLOCUS, 0 },
2094 #endif /* LOCUS */
2095 #ifndef NOSPL
2096     { "login",		  XYLOGIN, CM_LOC },
2097 #endif /* NOSPL */
2098 #ifndef NOSPL
2099     { "macro",            XYMACR,  0 },
2100 #endif /* NOSPL */
2101     { "match",            XYMATCH, 0 },
2102 #ifdef COMMENT
2103 #ifdef VMS
2104     { "messages",         XYMSGS,  0 },
2105 #endif /* VMS */
2106 #endif /* COMMENT */
2107 #ifndef NODIAL
2108     { "modem",		  XYMODM,  CM_LOC },
2109 #endif /* NODIAL */
2110 #ifndef NOLOCAL
2111 #ifdef OS2MOUSE
2112     { "mouse",		  XYMOUSE, 0 },
2113 #endif /* OS2MOUSE */
2114 #endif /* NOLOCAL */
2115 #ifdef OS2
2116     { "mskermit",         XYMSK,   0 },
2117 #endif /* OS2 */
2118 #ifdef NETCONN
2119     { "network",          XYNET,   CM_LOC },
2120 #endif /* NETCONN */
2121 #ifndef NOSPL
2122     { "output",           XYOUTP,  0 },
2123 #endif /* NOSPL */
2124     { "options",          XYOPTS,  0 },
2125     { "pause",            XYSLEEP, CM_INV },
2126 #ifdef ANYX25
2127 #ifndef IBMX25
2128     { "pad",              XYPAD,   CM_LOC },
2129 #endif /* IBMX25 */
2130 #endif /* ANYX25 */
2131     { "parity",	    	  XYPARI,  0 },
2132 #ifndef NOLOCAL
2133 #ifdef OS2
2134     { "port",             XYLINE,  CM_LOC },
2135 #else
2136     { "port",             XYLINE,  CM_INV|CM_LOC },
2137 #endif /* OS2 */
2138 #endif /* NOLOCAL */
2139 #ifndef NOFRILLS
2140     { "pr",   	    	  XYPROM,  CM_INV|CM_ABR },
2141     { "printer",          XYPRTR,  0 },
2142 #endif /* NOFRILLS */
2143 #ifdef OS2
2144     { "priority",         XYPRTY,  0 },
2145 #endif /* OS2 */
2146 #ifdef CK_SPEED
2147     { "prefixing",        XYPREFIX, 0 },
2148 #endif /* CK_SPEED */
2149 #ifndef NOFRILLS
2150     { "prompt",	    	  XYPROM,  0 },
2151 #endif /* NOFRILLS */
2152 #ifndef NOXFER
2153     { "protocol",	  XYPROTO, 0 },
2154 #endif /* NOXFER */
2155     { "q",		  XYQUIE,  CM_INV|CM_ABR },
2156 #ifndef NOXFER
2157     { "q8flag",           XYQ8FLG, CM_INV },
2158 #endif /* NOXFER */
2159 #ifdef QNX
2160     { "qnx-port-lock",    XYQNXPL, 0 },
2161 #else
2162     { "qnx-port-lock",    XYQNXPL, CM_INV },
2163 #endif /* QNX */
2164     { "quiet",		  XYQUIE,  0 },
2165 #ifndef NOXFER
2166     { "rec",              XYRECV,  CM_INV|CM_ABR },
2167     { "receive",          XYRECV,  0 },
2168     { "recv",             XYRECV,  CM_INV },
2169 #endif /* NOXFER */
2170     { "reliable",         XYRELY,  0 },
2171     { "rename",           XY_REN,  0 },
2172 #ifndef NOXFER
2173     { "repeat",           XYREPT,  0 },
2174     { "retry-limit",      XYRETR,  0 },
2175 #endif /* NOXFER */
2176 #ifdef CKROOT
2177     { "root",             XYROOT,  0 },
2178 #endif /* CKROOT */
2179 #ifndef NOSCRIPT
2180     { "script",		  XYSCRI,  CM_LOC },
2181 #endif /* NOSCRIPT */
2182 #ifndef NOXFER
2183     { "send",             XYSEND,  0 },
2184 #ifndef NOLOCAL
2185 #ifndef NOSERVER
2186     { "ser",              XYSERV,  CM_INV|CM_ABR },
2187 #endif /* NOSERVER */
2188 #endif /* NOXFER */
2189     { "serial",           XYSERIAL,CM_LOC },
2190 #endif /* NOLOCAL */
2191 #ifndef NOSERVER
2192     { "server",           XYSERV,  0 },
2193 #endif /* NOSERVER */
2194 #ifdef SESLIMIT
2195 #ifndef NOLOCAL
2196     { "session-l",        XYSESS,  CM_INV|CM_ABR },
2197 #endif /* NOLOCAL */
2198     { "session-limit",    XYLIMIT, CM_INV|CM_LOC }, /* Session Limit */
2199 #endif /* SESLIMIT */
2200 
2201 #ifndef NOLOCAL
2202     { "session-log",      XYSESS,  CM_LOC },
2203 #endif /* NOLOCAL */
2204 
2205 #ifndef NOSPL
2206 #ifndef NOSEXP
2207     { "sexpression",      XYSEXP,  CM_INV },
2208 #endif /* NOSEXP */
2209 #endif /* NOSPL */
2210 
2211     { "sleep",            XYSLEEP, 0 },
2212 
2213 #ifndef NOLOCAL
2214     { "speed",	          XYSPEE,  CM_LOC },
2215 #endif /* NOLOCAL */
2216 
2217 #ifdef ANYSSH
2218     { "ssh",	          XYSSH,   0 },
2219 #endif /* ANYSSH */
2220 
2221 #ifndef NOSPL
2222     { "startup-file",     XYSTARTUP, CM_INV },
2223 #endif /* NOSPL */
2224 
2225 #ifndef NOLOCAL
2226 #ifdef HWPARITY
2227     { "stop-bits",        XYSTOP, CM_LOC },
2228 #else
2229 #ifdef TN_COMPORT
2230     { "stop-bits",        XYSTOP, CM_LOC },
2231 #endif /* TN_COMPORT */
2232 #endif /* HWPARITY */
2233 #endif /* NOLOCAL */
2234 
2235 #ifndef NOXFER
2236 #ifdef STREAMING
2237     { "streaming",        XYSTREAM, 0 },
2238 #endif /* STREAMING */
2239 #endif /* NOXFER */
2240 
2241 #ifndef NOJC
2242     { "suspend",          XYSUSP,  CM_PSH },
2243 #endif /* NOJC */
2244 #ifdef CKSYSLOG
2245     { "syslog",           XYSYSL,  CM_INV },
2246 #endif /* CKSYSLOG */
2247     { "take",             XYTAKE,  0 },
2248 
2249 #ifdef CK_TAPI
2250     { "tapi",             XYTAPI,  CM_LOC },
2251 #endif /* CK_TAPI */
2252 
2253 #ifndef NOTCPOPTS
2254 #ifdef TCPSOCKET
2255     { "tcp",              XYTCP,   CM_LOC },
2256 #endif /* TCPSOCKET */
2257 #endif /* NOTCPOPTS */
2258 
2259 #ifdef TNCODE
2260     { "tel",              XYTEL,   CM_INV|CM_ABR },
2261     { "telnet",           XYTEL,   0 },
2262     { "telopt",           XYTELOP, 0 },
2263 #endif /* TNCODE */
2264 
2265 #ifndef NOSPL
2266     { "temp-directory",   XYTMPDIR,0 },
2267 #endif /* NOSPL */
2268 
2269 #ifndef NOLOCAL
2270     { "terminal",         XYTERM,  CM_LOC },
2271 #endif /* NOLOCAL */
2272 
2273 #ifdef OS2
2274     { "title",		  XYTITLE, CM_LOC },
2275 #endif /* OS2 */
2276 #ifndef NOSPL
2277     { "tmp-directory",    XYTMPDIR,CM_INV },
2278 #endif /* NOSPL */
2279 #ifdef TLOG
2280     { "transaction-log",  XYTLOG,  0 },
2281 #endif /* TLOG */
2282 #ifndef NOXFER
2283     { "transfer",         XYXFER,  0 },
2284 #endif /* NOXFER */
2285 #ifndef NOXMIT
2286     { "transmit",         XYXMIT,  0 },
2287 #endif /* NOXMIT */
2288 #ifndef NOXFER
2289 #ifndef NOCSETS
2290     { "unknown-char-set", XYUNCS,  0 },
2291 #endif /* NOCSETS */
2292 #ifndef NOSPL
2293     { "variable-evaluation", XYVAREV, CM_INV },
2294 #endif	/* NOSPL */
2295 #endif /* NOXFER */
2296     { "wait",             XYSLEEP, CM_INV },
2297 #ifndef NOPUSH
2298 #ifdef UNIX
2299     { "wildcard-expansion", XYWILD, 0 },
2300 #endif /* UNIX */
2301 #endif /* NOPUSH */
2302 #ifdef NT
2303     { "w",                XYWIND,  CM_INV|CM_ABR },
2304     { "wi",               XYWIND,  CM_INV|CM_ABR },
2305     { "win",              XYWIND,  CM_INV|CM_ABR },
2306 #endif /* NT */
2307     { "window-size",      XYWIND,  0 },
2308 #ifdef NT
2309     { "win95",            XYWIN95, 0 },
2310 #endif /* NT */
2311 #ifdef ANYX25
2312     { "x.25",             XYX25,   CM_LOC },
2313     { "x25",              XYX25,   CM_INV|CM_LOC },
2314 #endif /* ANYX25 */
2315     { "xfer",             XYXFER,  CM_INV },
2316 #ifndef NOXMIT
2317     { "xmit",             XYXMIT,  CM_INV },
2318 #endif /* NOXMIT */
2319     { "", 0, 0 }
2320 };
2321 int nprm = (sizeof(prmtab) / sizeof(struct keytab)) - 1; /* How many */
2322 
2323 struct keytab scntab[] = {		/* Screen commands */
2324     { "clear",   SCN_CLR, 0 },
2325     { "cleol",   SCN_CLE, 0 },
2326     { "move-to", SCN_MOV, 0 }
2327 };
2328 int nscntab = (sizeof(scntab) / sizeof(struct keytab)); /* How many */
2329 
2330 #ifdef ANYSSH				/* SSH command table */
2331 #ifdef SSHBUILTIN
2332 int    ssh_pf_lcl_n = 0,
2333        ssh_pf_rmt_n = 0;
2334 struct ssh_pf ssh_pf_lcl[32] = { 0, NULL, 0 }; /* SSH Port Forwarding */
2335 struct ssh_pf ssh_pf_rmt[32] = { 0, NULL, 0 }; /* structs... */
2336 extern char * ssh_hst, * ssh_cmd, * ssh_prt;
2337 extern int    ssh_ver,   ssh_xfw;
2338 char * ssh_tmpuid = NULL, *ssh_tmpcmd = NULL, *ssh_tmpport = NULL,
2339      * ssh_tmpstr = NULL;
2340 
2341 int
2342  sshk_type = SSHKT_2D,			/* SSH KEY CREATE /TYPE:x */
2343  sshk_bits = 1024,			/* SSH KEY CREATE /BITS:n */
2344  sshk_din  = SKDF_OSSH,			/* SSH KEY DISPLAY /IN-FORMAT: */
2345  sshk_dout = SKDF_OSSH;			/* SSH KEY DISPLAY /OUT-FORMAT: */
2346 
2347 char
2348  * sshk1_comment = NULL,		/* SSH V1 COMMENT */
2349  * sshkp_old = NULL,			/* Old key passphrase */
2350  * sshkp_new = NULL,			/* New key passphrase */
2351  * sshkc_pass = NULL,			/* KEY CREATE /PASS:xxx */
2352  * sshkc_comm = NULL,			/* KEY CREATE /V1-RSA-COMMENT:xxx */
2353  * sshd_file = NULL,			/* DISPLAY file */
2354  * sshk_file = NULL;			/* SSH CREATE KEY file */
2355 
2356 static struct keytab sshclr[] = {
2357     { "local-port-forward",  SSHC_LPF, 0 },
2358     { "remote-port-forward", SSHC_RPF, 0 },
2359     { "", 0, 0 }
2360 };
2361 static int nsshclr = (sizeof(sshclr) / sizeof(struct keytab)) - 1;
2362 
2363 struct keytab sshopnsw[] = {
2364     { "/command",        SSHSW_CMD, CM_ARG },
2365     { "/password",       SSHSW_PWD, CM_ARG },
2366     { "/subsystem",      SSHSW_SUB, CM_ARG },
2367     { "/user",           SSHSW_USR, CM_ARG },
2368     { "/version",        SSHSW_VER, CM_ARG },
2369     { "/x11-forwarding", SSHSW_X11, CM_ARG },
2370     { "", 0, 0 }
2371 };
2372 int nsshopnsw = (sizeof(sshopnsw) / sizeof(struct keytab)) - 1;
2373 
2374 static struct keytab sshkwtab[] = {
2375     { "add",                 XSSH_ADD, 0 },
2376     { "agent",               XSSH_AGT, 0 },
2377     { "clear",               XSSH_CLR, 0 },
2378     { "forward-local-port",  XSSH_FLP, CM_INV },
2379     { "forward-remote-port", XSSH_FRP, CM_INV },
2380     { "key",                 XSSH_KEY, 0 },
2381     { "open",                XSSH_OPN, 0 },
2382     { "v2",                  XSSH_V2,  0 },
2383     { "", 0, 0 }
2384 };
2385 static int nsshcmd = (sizeof(sshkwtab) / sizeof(struct keytab)) - 1;
2386 
2387 static struct keytab ssh2tab[] = {
2388     { "rekey", XSSH2_RKE, 0 },
2389     { "", 0, 0 }
2390 };
2391 static int nssh2tab = (sizeof(ssh2tab) / sizeof(struct keytab));
2392 
2393 static struct keytab addfwd[] = {	/* SET SSH ADD command table */
2394     { "local-port-forward",  SSHF_LCL, 0 },
2395     { "remote-port-forward", SSHF_RMT, 0 },
2396     { "", 0, 0 }
2397 };
2398 static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
2399 
2400 static struct keytab sshagent[] = {	/* SET SSH AGENT command table */
2401     { "add",    SSHA_ADD, 0 },
2402     { "delete", SSHA_DEL, 0 },
2403     { "list",   SSHA_LST, 0 },
2404     { "", 0, 0 }
2405 };
2406 static int nsshagent = (sizeof(sshagent) / sizeof(struct keytab)) - 1;
2407 
2408 static struct keytab sshagtsw[] = {	/* SET SSH AGENT LIST switch table */
2409     { "/fingerprint", SSHASW_FP, 0 },
2410     { "", 0, 0 }
2411 };
2412 static int nsshagtsw = (sizeof(sshagtsw) / sizeof(struct keytab)) - 1;
2413 
2414 static struct keytab sshkey[] = {	/* SET SSH KEY command table */
2415     { "change-passphrase",  SSHK_PASS, 0 },
2416     { "create",             SSHK_CREA, 0 },
2417     { "display",            SSHK_DISP, 0 },
2418     { "v1",                 SSHK_V1,   0 },
2419     { "", 0, 0 }
2420 };
2421 static int nsshkey = (sizeof(sshkey) / sizeof(struct keytab)) - 1;
2422 
2423 static struct keytab sshkv1[] = {	/* SET SSH KEY V1 command table */
2424     { "set-comment",  1, 0 }
2425 };
2426 
2427 static struct keytab sshkpsw[] = {	/* SET SSH KEY PASSPHRASE table */
2428     { "/new-passphrase",  2, CM_ARG },
2429     { "/old-passphrase",  1, CM_ARG }
2430 };
2431 
2432 static struct keytab sshkcrea[] = {	/* SSH KEY CREATE table */
2433     { "/bits",           SSHKC_BI, CM_ARG },
2434     { "/passphrase",     SSHKC_PP, CM_ARG },
2435     { "/type",           SSHKC_TY, CM_ARG },
2436     { "/v1-rsa-comment", SSHKC_1R, CM_ARG }
2437 };
2438 static int nsshkcrea = (sizeof(sshkcrea) / sizeof(struct keytab));
2439 
2440 static struct keytab sshkcty[] = {	/* SSH KEY CREATE /TYPE:xxx */
2441     { "srp",    SSHKT_SRP, 0 },
2442     { "v1-rsa", SSHKT_1R, 0 },
2443     { "v2-dsa", SSHKT_2D, 0 },
2444     { "v2-rsa", SSHKT_2R, 0 }
2445 };
2446 static int nsshkcty = (sizeof(sshkcty) / sizeof(struct keytab));
2447 
2448 static struct keytab sshdswi[] = {	/* SET SSH KEY DISPLAY /switches */
2449     { "/format", SSHKD_OUT, CM_ARG }
2450 };
2451 static int nsshdswi = (sizeof(sshdswi) / sizeof(struct keytab));
2452 
2453 #ifdef COMMENT
2454 static struct keytab sshdifmt[] = {	/* SSH KEY DISPLAY /IN-FORMAT: */
2455     { "openssh", SKDF_OSSH, 0 },
2456     { "ssh.com", SKDF_SSHC, 0 }
2457 };
2458 static int nsshdifmt = (sizeof(sshdifmt) / sizeof(struct keytab));
2459 #endif /* COMMENT */
2460 
2461 static struct keytab sshdofmt[] = {	/* SSH KEY DISPLAY /IN-FORMAT: */
2462     { "fingerprint", SKDF_FING, 0 },
2463     { "ietf",        SKDF_IETF, 0 },
2464     { "openssh",     SKDF_OSSH, 0 },
2465     { "ssh.com",     SKDF_SSHC, 0 }
2466 };
2467 static int nsshdofmt = (sizeof(sshdofmt) / sizeof(struct keytab));
2468 
2469 static struct keytab sshkermit[] = { /* SKERMIT */
2470     { "open",       SKRM_OPN, 0 }
2471 };
2472 static int nsshkermit = (sizeof(sshkermit) / sizeof(struct keytab));
2473 
2474 struct keytab sshkrmopnsw[] = {
2475     { "/password",       SSHSW_PWD, CM_ARG },
2476     { "/user",           SSHSW_USR, CM_ARG },
2477     { "/version",        SSHSW_VER, CM_ARG },
2478     { "", 0, 0 }
2479 };
2480 int nsshkrmopnsw = (sizeof(sshkrmopnsw) / sizeof(struct keytab)) - 1;
2481 #endif /* SSHBUILTIN */
2482 
2483 #ifdef SFTP_BUILTIN
2484 static struct keytab sftpkwtab[] = {    /* SFTP */
2485     {  "cd",        SFTP_CD,    0 },
2486     {  "chgrp",     SFTP_CHGRP, 0 },
2487     {  "chmod",     SFTP_CHMOD, 0 },
2488     {  "chown",     SFTP_CHOWN, 0 },
2489     {  "delete",    SFTP_RM,    0 },
2490     {  "dir",       SFTP_DIR,   0 },
2491     {  "get",       SFTP_GET,   0 },
2492     {  "mkdir",     SFTP_MKDIR, 0 },
2493     {  "open",      SFTP_OPN,   0 },
2494     {  "put",       SFTP_PUT,   0 },
2495     {  "pwd",       SFTP_PWD,   0 },
2496     {  "rename",    SFTP_REN,   0 },
2497     {  "rm",        SFTP_RM,    CM_INV },
2498     {  "rmdir",     SFTP_RMDIR, 0 },
2499     {  "symlink",   SFTP_LINK,  0 },
2500     {  "version",   SFTP_VER,   0 }
2501 };
2502 static int nsftpkwtab = (sizeof(sftpkwtab) / sizeof(struct keytab));
2503 #endif /* SFTP_BUILTIN */
2504 #endif /* ANYSSH */
2505 
2506 #ifdef NETCONN
2507 struct keytab netkey[] = {		/* SET NETWORK table */
2508     { "directory", XYNET_D,  0 },
2509     { "type",      XYNET_T,  0 }
2510 };
2511 int nnetkey = (sizeof(netkey) / sizeof(struct keytab));
2512 
2513 struct keytab netcmd[] = {
2514 /*
2515   These are the network types.
2516 */
2517 #ifdef NETCMD
2518     { "command",       NET_CMD,  CM_INV }, /* Command */
2519 #endif /* NETCMD */
2520 
2521 #ifdef DECNET				/* DECnet / PATHWORKS */
2522     { "decnet",        NET_DEC,  0 },
2523 #endif /* DECNET */
2524 
2525 #ifdef NETDLL
2526     { "dll",           NET_DLL,  CM_INV }, /* DLL to be loaded */
2527 #endif /* NETDLL */
2528 
2529 #ifdef NETFILE
2530     { "file",           NET_FILE, CM_INV }, /* FILE (real crude) */
2531 #endif /* NETFILE */
2532 
2533 #ifdef NPIPE				/* Named Pipes */
2534     { "named-pipe",     NET_PIPE,  0 },
2535 #endif /* NPIPE */
2536 
2537 #ifdef CK_NETBIOS
2538     { "netbios",        NET_BIOS,  0 },	/* NETBIOS */
2539 #endif /* CK_NETBIOS */
2540 
2541 #ifdef DECNET				/* DECnet / PATHWORKS (alias) */
2542     { "pathworks",     NET_DEC,  CM_INV },
2543 #endif /* DECNET */
2544 
2545 #ifdef NETCMD
2546     { "pipe",          NET_CMD,  0 },	/* Pipe */
2547 #endif /* NETCMD */
2548 
2549 #ifdef NETPTY
2550     { "pseudoterminal",NET_PTY, 0 },	/* Pseudoterminal */
2551 #endif /* NETPTY */
2552 
2553 #ifdef NETPTY
2554     { "pty",          NET_PTY,  CM_INV }, /* Inv syn for pseudoterm */
2555 #endif /* NETPTY */
2556 
2557 #ifdef SSHBUILTIN
2558     { "ssh",          NET_SSH,  0 },
2559 #endif /* SSHBUILTIN */
2560 
2561 #ifdef SUPERLAT
2562     { "superlat",     NET_SLAT, 0 },	/* Meridian Technologies' SuperLAT */
2563 #endif /* SUPERLAT */
2564 
2565 #ifdef TCPSOCKET			/* TCP/IP sockets library */
2566     { "tcp/ip",       NET_TCPB, 0 },
2567 #endif /* TCPSOCKET */
2568 #ifdef SUPERLAT
2569     { "tes32",        NET_SLAT, 0 },	/* Emulux TES32 */
2570 #endif /* SUPERLAT */
2571 #ifdef ANYX25				/* X.25 */
2572 #ifdef SUNX25
2573     { "x",            NET_SX25, CM_INV|CM_ABR },
2574     { "x.25",         NET_SX25, 0 },
2575     { "x25",          NET_SX25, CM_INV },
2576 #else
2577 #ifdef STRATUSX25
2578     { "x",            NET_VX25, CM_INV|CM_ABR },
2579     { "x.25",         NET_VX25, 0 },
2580     { "x25",          NET_VX25, CM_INV },
2581 #endif /* STRATUSX25 */
2582 #endif /* SUNX25 */
2583 #ifdef IBMX25
2584     { "x",            NET_IX25, CM_INV|CM_ABR },
2585     { "x.25",         NET_IX25, CM_INV },
2586     { "x25",          NET_IX25, CM_INV },
2587 #endif /* IBMX25 */
2588 #ifdef HPX25
2589     { "x",            NET_IX25, CM_INV|CM_ABR },
2590     { "x.25",         NET_IX25, 0 },
2591     { "x25",          NET_IX25, CM_INV },
2592 #endif /* HPX25 */
2593 #endif /* ANYX25 */
2594     { "", 0, 0 }
2595 };
2596 int nnets = (sizeof(netcmd) / sizeof(struct keytab));
2597 
2598 #ifndef NOTCPOPTS
2599 #ifdef TCPSOCKET
2600 
2601 /* TCP options */
2602 
2603 struct keytab tcpopt[] = {
2604     { "address",   XYTCP_ADDRESS, 0 },
2605 #ifdef CK_DNS_SRV
2606     { "dns-service-records", XYTCP_DNS_SRV, 0 },
2607 #endif /* CK_DNS_SRV */
2608 #ifdef SO_DONTROUTE
2609     { "dontroute",   XYTCP_DONTROUTE, 0 },
2610 #endif /* SO_DONTROUTE */
2611 #ifndef NOHTTP
2612     { "http-proxy", XYTCP_HTTP_PROXY, 0 },
2613 #endif /* NOHTTP */
2614 #ifdef SO_KEEPALIVE
2615     { "keepalive", XYTCP_KEEPALIVE, 0 },
2616 #endif /* SO_KEEPALIVE */
2617 #ifdef SO_LINGER
2618     { "linger", XYTCP_LINGER, 0 },
2619 #endif /* SO_LINGER */
2620 #ifdef TCP_NODELAY
2621     { "nagle",  XYTCP_NAGLE,    CM_INV },
2622     { "nodelay", XYTCP_NODELAY, 0 },
2623 #endif /* TCP_NODELAY */
2624     { "reverse-dns-lookup", XYTCP_RDNS, 0 },
2625 #ifdef SO_RCVBUF
2626     { "recvbuf", XYTCP_RECVBUF, 0 },
2627 #endif /* SO_RCVBUF */
2628 #ifdef SO_SNDBUF
2629     { "sendbuf", XYTCP_SENDBUF, 0 },
2630 #endif /* SO_SNDBUF */
2631 #ifdef NT
2632 #ifdef CK_SOCKS
2633     { "socks-server", XYTCP_SOCKS_SVR, 0 },
2634 #endif /* CK_SOCKS */
2635 #endif /* NT */
2636 #ifdef VMS
2637 #ifdef DEC_TCPIP
2638     { "ucx-port-bug", XYTCP_UCX, 0 },
2639 #endif /* DEC_TCPIP */
2640 #endif /* VMS */
2641     { "",0,0 }
2642 };
2643 int ntcpopt = (sizeof(tcpopt) / sizeof(struct keytab));
2644 #endif /* TCPSOCKET */
2645 #endif /* NOTCPOPTS */
2646 #endif /* NETCONN */
2647 
2648 #ifdef OS2
2649 /* K95 Manual Chapter Table -- Keep these two tables in sync! */
2650 
2651 static char * linktbl[] = {		/* Internal links in k95.htm */
2652     "#top",				/* 00 */
2653     "#what",				/* 01 */
2654     "#install",				/* 02 */
2655     "#start",				/* 03 */
2656     "#dialer",				/* 04 */
2657     "#entries",				/* 05 */
2658     "#command",				/* 06 */
2659     "#terminal",			/* 07 */
2660     "#transfer",			/* 08 */
2661     "#hostmode"				/* 09 */
2662 };
2663 
2664 static struct keytab chaptbl[] = {
2665     { "Command-Screen",     6, 0 },
2666     { "Contents",           0, 0 },
2667     { "Dialer-Entries",     5, 0 },
2668     { "File-Transfer",      8, 0 },
2669     { "Getting-Started",    3, 0 },
2670     { "Host-Mode",          9, 0 },
2671     { "Installation",       2, 0 },
2672     { "Terminal-Emulation", 7, 0 },
2673     { "Using-The-Dialer",   4, 0 },
2674     { "What-Is-K95",        1, 0 },
2675     { "",                   0, 0 }
2676 };
2677 static int nchaptbl = (sizeof(chaptbl) / sizeof(struct keytab) - 1);
2678 #endif /* OS2 */
2679 
2680 #ifndef NOXFER
2681 /* Remote Command Table */
2682 
2683 struct keytab remcmd[] = {
2684 #ifndef NOSPL
2685     { "as",        XZASG, CM_INV|CM_ABR },
2686     { "asg",       XZASG, CM_INV },
2687     { "assign",    XZASG, 0 },
2688 #endif /* NOSPL */
2689     { "cd",        XZCWD, 0 },
2690     { "cdup",      XZCDU, CM_INV },
2691     { "copy",      XZCPY, 0 },
2692     { "cwd",       XZCWD, CM_INV },
2693     { "delete",    XZDEL, 0 },
2694     { "directory", XZDIR, 0 },
2695     { "e",         XZXIT, CM_ABR|CM_INV },
2696     { "erase",     XZDEL, CM_INV },
2697     { "exit",      XZXIT, 0 },
2698     { "help",      XZHLP, 0 },
2699 #ifndef NOPUSH
2700     { "host",      XZHOS, 0 },
2701 #endif /* NOPUSH */
2702 #ifndef NOFRILLS
2703     { "kermit",    XZKER, 0 },
2704     { "l",         XZLGI, CM_ABR|CM_INV },
2705     { "lo",        XZLGI, CM_ABR|CM_INV },
2706     { "log",       XZLGI, CM_ABR|CM_INV },
2707     { "login",     XZLGI, 0 },
2708     { "logout",    XZLGO, 0 },
2709     { "message",   XZMSG, 0 },
2710     { "mkdir",     XZMKD, 0 },
2711     { "print",     XZPRI, 0 },
2712 #endif /* NOFRILLS */
2713     { "pwd",       XZPWD, 0 },
2714 #ifndef NOSPL
2715     { "query",	   XZQUE, 0 },
2716 #endif /* NOSPL */
2717     { "rename",    XZREN, 0 },
2718     { "rmdir",     XZRMD, 0 },
2719     { "set",       XZSET, 0 },
2720     { "space",	   XZSPA, 0 },
2721 #ifndef NOFRILLS
2722     { "type",      XZTYP, 0 },
2723     { "who",       XZWHO, 0 },
2724 #endif /* NOFRILLS */
2725     { "", 0, 0}
2726 };
2727 int nrmt = (sizeof(remcmd) / sizeof(struct keytab)) - 1;
2728 #endif /* NOXFER */
2729 
2730 struct keytab logtab[] = {
2731 #ifdef CKLOGDIAL
2732     { "connections",  LOGM, CM_INV },
2733     { "cx",           LOGM, 0 },
2734 #endif /* CKLOGDIAL */
2735 #ifdef DEBUG
2736     { "debugging",    LOGD, 0 },
2737 #endif /* DEBUG */
2738     { "packets",      LOGP, 0 },
2739 #ifndef NOLOCAL
2740     { "session",      LOGS, 0 },
2741 #endif /* NOLOCAL */
2742 #ifdef TLOG
2743     { "transactions", LOGT, 0 },
2744 #endif /* TLOG */
2745     { "", 0, 0 }
2746 };
2747 int nlog = (sizeof(logtab) / sizeof(struct keytab)) - 1;
2748 
2749 struct keytab writab[] = {
2750 #ifndef NOSPL
2751     { "append-file",     LOGW, CM_INV },
2752 #endif /* NOSPL */
2753     { "debug-log",       LOGD, 0 },
2754     { "error",           LOGE, 0 },
2755 #ifndef NOSPL
2756     { "file",            LOGW, 0 },
2757 #endif /* NOSPL */
2758     { "packet-log",      LOGP, 0 },
2759     { "screen",          LOGX, 0 },
2760 #ifndef NOLOCAL
2761     { "session-log",     LOGS, 0 },
2762 #endif /* NOLOCAL */
2763     { "sys$output",      LOGX, CM_INV },
2764     { "t",               LOGT, CM_ABR|CM_INV }, /* Because of a typo in */
2765     { "tr",              LOGT, CM_ABR|CM_INV }, /* the book... */
2766     { "tra",             LOGT, CM_ABR|CM_INV },
2767     { "tran",            LOGT, CM_ABR|CM_INV },
2768     { "trans",           LOGT, CM_ABR|CM_INV },
2769     { "transa",          LOGT, CM_ABR|CM_INV },
2770     { "transac",         LOGT, CM_ABR|CM_INV },
2771     { "transact",        LOGT, CM_ABR|CM_INV },
2772     { "transacti",       LOGT, CM_ABR|CM_INV },
2773     { "transactio",      LOGT, CM_ABR|CM_INV },
2774     { "transaction",     LOGT, CM_ABR|CM_INV },
2775     { "transaction-log", LOGT, 0 },
2776     { "transactions",    LOGT, CM_INV }
2777 };
2778 int nwri = (sizeof(writab) / sizeof(struct keytab));
2779 
2780 static struct keytab clrtab[] = {	/* Keywords for CLEAR command */
2781 #ifndef NOSPL
2782     { "alarm",            CLR_ALR,         0 },
2783 #ifdef CK_APC
2784     { "apc",              CLR_APC,         0 },
2785 #endif /* CK_APC */
2786 #ifdef PATTERNS
2787     { "binary-patterns",  CLR_BIN,         0 },
2788 #endif /* PATTERNS */
2789     { "both",             CLR_DEV|CLR_INP, CM_INV },
2790 #endif /* NOSPL */
2791 #ifdef OS2
2792     { "command-screen",   CLR_CMD,         0 },
2793 #endif /* OS2 */
2794 #ifndef NOSPL
2795     { "device",           CLR_DEV,         CM_INV|CM_ABR },
2796     { "device-and-input", CLR_DEV|CLR_INP, 0 },
2797 #endif /* NOSPL */
2798     { "device-buffer",    CLR_DEV,         0 },
2799 #ifndef NODIAL
2800     { "dial-status",      CLR_DIA,	 0 },
2801 #endif /* NODIAL */
2802 #ifndef NOSPL
2803     { "input-buffer",     CLR_INP,         0 },
2804 #endif /* NOSPL */
2805     { "keyboard-buffer",  CLR_KBD,         0 },
2806     { "send-list",        CLR_SFL,         0 },
2807 #ifdef OS2
2808     { "scr",              CLR_SCL,         CM_INV|CM_ABR },
2809 #endif /* OS2 */
2810     { "screen",           CLR_SCR,         0 },
2811 #ifdef OS2
2812     { "scrollback",       CLR_SCL,         CM_INV },
2813     { "terminal-screen",  CLR_TRM,         0 },
2814 #endif /* OS2 */
2815 #ifdef PATTERNS
2816     { "text-patterns",    CLR_TXT,         0 },
2817 #endif /* PATTERNS */
2818     { "", 0, 0 }
2819 };
2820 int nclear = (sizeof(clrtab) / sizeof(struct keytab)) - 1;
2821 
2822 struct keytab clstab[] = {		/* Keywords for CLOSE command */
2823 #ifndef NOSPL
2824     { "!read",           LOGR, CM_INV },
2825     { "!write",          LOGW, CM_INV },
2826 #ifndef NOPUSH
2827 #endif /* NOPUSH */
2828 #endif /* NOSPL */
2829 #ifndef NOSPL
2830     { "append-file",     LOGW, CM_INV },
2831 #endif /* NOSPL */
2832 #ifndef NOLOCAL
2833     { "connection",      9999, 0 },
2834 #endif /* NOLOCAL */
2835 #ifdef CKLOGDIAL
2836     { "cx-log",          LOGM, 0 },
2837 #endif /* CKLOGDIAL */
2838 #ifdef DEBUG
2839     { "debug-log",       LOGD, 0 },
2840 #endif /* DEBUG */
2841     { "host",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2842     { "line",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2843     { "p",               LOGP, CM_INV|CM_ABR },
2844     { "packet-log",      LOGP, 0 },
2845     { "port",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2846 #ifndef NOSPL
2847     { "read-file",       LOGR, 0 },
2848 #endif /* NOSPL */
2849 #ifndef NOLOCAL
2850     { "session-log",     LOGS, 0 },
2851 #endif /* NOLOCAL */
2852 #ifdef TLOG
2853     { "t",               LOGT, CM_ABR|CM_INV }, /* Because of a typo in */
2854     { "tr",              LOGT, CM_ABR|CM_INV }, /* the book... */
2855     { "tra",             LOGT, CM_ABR|CM_INV },
2856     { "tran",            LOGT, CM_ABR|CM_INV },
2857     { "trans",           LOGT, CM_ABR|CM_INV },
2858     { "transa",          LOGT, CM_ABR|CM_INV },
2859     { "transac",         LOGT, CM_ABR|CM_INV },
2860     { "transact",        LOGT, CM_ABR|CM_INV },
2861     { "transacti",       LOGT, CM_ABR|CM_INV },
2862     { "transactio",      LOGT, CM_ABR|CM_INV },
2863     { "transaction",     LOGT, CM_ABR|CM_INV },
2864     { "transaction-log", LOGT, 0 },
2865     { "transactions",    LOGT, CM_INV },
2866 #endif /* TLOG */
2867 #ifndef NOSPL
2868     { "write-file",      LOGW, 0 },
2869 #endif /* NOSPL */
2870     { "", 0, 0 }
2871 };
2872 int ncls = (sizeof(clstab) / sizeof(struct keytab)) - 1;
2873 
2874 /* SHOW command arguments */
2875 
2876 #ifndef NOSHOW
2877 struct keytab shotab[] = {
2878 #ifndef NOSPL
2879     { "alarm",        SHALRM, 0 },
2880     { "arg",          SHARG, CM_INV|CM_ABR },
2881     { "arguments",    SHARG, 0 },
2882     { "args",         SHARG, CM_INV },
2883     { "arrays",       SHARR, 0 },
2884 #endif /* NOSPL */
2885 
2886 #ifndef NOCSETS
2887     { "associations", SHASSOC, 0 },
2888 #endif /* NOCSETS */
2889 
2890 #ifndef NOXFER
2891     { "attributes",   SHATT, 0 },
2892 #endif /* NOXFER */
2893 
2894 #ifdef CK_AUTHENTICATION
2895     { "authentication", SHOAUTH, CM_INV },
2896 #endif /* CK_AUTHENTICATION */
2897 
2898 #ifndef NOPUSH
2899 #ifdef BROWSER
2900     { "browser",      SHBROWSE, CM_PSH|CM_LOC },
2901 #endif /*  BROWSER */
2902 #endif /* NOPUSH */
2903     { "cd",           SHCD, 0 },
2904     { "character-sets", SHCSE, 0 },
2905     { "cmd",          SHCMD, CM_INV },
2906 #ifndef NOLOCAL
2907     { "com",          SHCOM, CM_INV|CM_ABR },
2908     { "comm",         SHCOM, CM_INV|CM_ABR },
2909     { "communications", SHCOM, 0 },
2910 #endif /* NOLOCAL */
2911     { "command",      SHCMD, 0 },
2912     { "connection",   SHCONNX, 0 },
2913 #ifdef CK_SPEED
2914     { "control-prefixing", SHCTL, 0 },
2915 #endif /* CK_SPEED */
2916 #ifdef CKLOGDIAL
2917     { "cx",           SHCONNX, CM_INV },
2918 #endif /* CKLOGDIAL */
2919 #ifndef NOSPL
2920     { "count",        SHCOU, 0 },
2921 #endif /* NOSPL */
2922     { "d",            SHDIA, CM_INV|CM_ABR },
2923 #ifdef VMS
2924     { "default",      SHDFLT, 0 },
2925 #else
2926     { "default",      SHDFLT, CM_INV },
2927 #endif /* VMS */
2928 #ifndef NODIAL
2929     { "dial",         SHDIA, CM_LOC },
2930 #endif /* NODIAL */
2931     { "double/ignore",SHDBL, 0 },
2932 #ifndef NOPUSH
2933 #ifndef NOFRILLS
2934     { "editor",       SHEDIT, CM_PSH },
2935 #endif /*  NOFRILLS */
2936 #endif /* NOPUSH */
2937 #ifndef NOLOCAL
2938     { "escape",       SHESC, CM_LOC },
2939 #endif /* NOLOCAL */
2940     { "exit",         SHEXI, 0 },
2941     { "extended-options", SHXOPT, CM_INV },
2942     { "features",     SHFEA, 0 },
2943     { "file",         SHFIL, 0 },
2944 #ifndef NOLOCAL
2945     { "flow-control", SHOFLO, 0 },
2946 #endif /* NOLOCAL */
2947 #ifdef BROWSER
2948     { "ftp",          SHOFTP, CM_PSH|CM_LOC },
2949 #else
2950 #ifndef NOFTP
2951 #ifndef SYSFTP
2952 #ifdef TCPSOCKET
2953     { "ftp",          SHOFTP, 0 },	/* (built-in ftp) */
2954 #endif /* TCPSOCKET */
2955 #endif /* SYSFTP */
2956 #endif /* NOFTP */
2957 #endif /* BROWSER */
2958 #ifndef NOSPL
2959     { "functions",    SHFUN, 0 },
2960     { "globals",      SHVAR, 0 },
2961 #endif /* NOSPL */
2962 #ifdef KUI
2963     { "gui",          SHOGUI, 0 },
2964 #endif /* KUI */
2965 #ifdef CK_RECALL
2966     { "history",      SHHISTORY, 0 },
2967 #endif /* CK_RECALL */
2968     { "ignore/double",SHDBL, CM_INV },
2969     { "iksd",         SHOIKS, CM_INV },
2970 #ifndef NOSPL
2971     { "input",        SHINP, 0 },
2972 #endif /* NOSPL */
2973 #ifndef NOSETKEY
2974     { "k",            SHKEY, CM_INV|CM_ABR },
2975     { "key",          SHKEY, 0 },
2976 #ifndef NOKVERBS
2977     { "kverbs",       SHKVB, 0 },
2978 #endif /* NOKVERBS */
2979 #endif /* NOSETKEY */
2980 #ifdef CK_LABELED
2981     { "labeled-file-info", SHLBL, 0 },
2982 #endif /* CK_LABELED */
2983 #ifndef NOCSETS
2984     { "languages",    SHLNG, 0 },
2985 #ifndef NO_LOCALE
2986     { "locale",       SHOLOC,0 },
2987 #endif /* NO_LOCALE */
2988 #endif /* NOCSETS */
2989     { "log",          SHLOG, CM_INV|CM_ABR },
2990     { "logs",         SHLOG, 0 },
2991 #ifndef NOSPL
2992     { "macros",       SHMAC, 0 },
2993 #endif /* NOSPL */
2994 #ifndef NODIAL
2995     { "modem",        SHMOD, CM_LOC },
2996 #else
2997     { "modem-signals",SHCOM, CM_INV|CM_LOC },
2998 #endif /* NODIAL */
2999 #ifndef NOLOCAL
3000 #ifdef OS2MOUSE
3001     { "mouse",        SHMOU, CM_LOC },
3002 #endif /* OS2MOUSE */
3003 #endif /* NOLOCAL */
3004 #ifdef NETCONN
3005     { "network",      SHNET, CM_LOC },
3006 #else
3007     { "network",      SHNET, CM_INV|CM_LOC },
3008 #endif /* NETCONN */
3009     { "options",      SHOPTS, 0 },
3010 #ifndef NOSPL
3011     { "output",       SHOUTP, CM_INV },
3012 #endif /* NOSPL */
3013 #ifdef ANYX25
3014 #ifndef IBMX25
3015     { "pad",          SHPAD,  CM_LOC },
3016 #endif /* IBMX25 */
3017 #endif /* ANYX25 */
3018     { "parameters",   SHPAR,  CM_INV },
3019 #ifdef PATTERNS
3020     { "patterns",     SHOPAT, 0 },
3021 #endif /* PATTERNS */
3022     { "printer",      SHPRT,  0 },
3023 #ifdef CK_SPEED
3024     { "prefixing",    SHCTL,  CM_INV },
3025 #endif /* CK_SPEED */
3026 #ifndef NOXFER
3027     { "protocol",     SHPRO,  0 },
3028 #endif /* NOXFER */
3029     { "rename",       SHOREN, 0 },
3030 #ifndef NOSPL
3031     { "scripts",      SHSCR,  CM_LOC },
3032 #endif /* NOSPL */
3033     { "send-list",    SHSFL,  0 },
3034 #ifndef NOSERVER
3035     { "server",       SHSER,  0 },
3036 #endif /* NOSERVER */
3037 #ifndef NOSEXP
3038     { "sexpression",  SHSEXP, 0 },
3039 #endif /* NOSEXP */
3040 #ifdef ANYSSH
3041     { "ssh",          SHOSSH, 0 },
3042 #endif /* ANYSSH */
3043     { "stack",        SHSTK,  0 },
3044     { "status",       SHSTA,  0 },
3045 #ifdef STREAMING
3046     { "streaming",    SHOSTR, 0 },
3047 #endif /* STREAMING */
3048 #ifndef NOLOCAL
3049 #ifdef OS2
3050     { "tabs",          SHTAB, CM_INV|CM_LOC },
3051 #endif /* OS2 */
3052 #ifdef CK_TAPI
3053     { "tapi",          SHTAPI, CM_LOC },
3054     { "tapi-comm",     SHTAPI_C, CM_INV|CM_LOC },
3055     { "tapi-location", SHTAPI_L, CM_INV|CM_LOC },
3056     { "tapi-modem",    SHTAPI_M, CM_INV|CM_LOC },
3057 #endif /* CK_TAPI */
3058     { "tcp",           SHTCP,  CM_LOC },
3059 #ifdef TNCODE
3060     { "tel",           SHTEL,  CM_INV|CM_ABR },
3061     { "telnet",        SHTEL,  0 },
3062     { "telopt",        SHTOPT, 0 },
3063     { "temp-directory", SHOTMPDIR, 0 },
3064 #endif /* TNCODE */
3065     { "terminal",      SHTER,  CM_LOC },
3066 #endif /* NOLOCAL */
3067 #ifndef NOSPL
3068     { "tmp-directory", SHOTMPDIR, CM_INV },
3069 #endif /* NOSPL */
3070 #ifndef NOXMIT
3071     { "tr",            SHXMI, CM_INV|CM_ABR },
3072     { "tra",           SHXMI, CM_INV|CM_ABR },
3073     { "tran",          SHXMI, CM_INV|CM_ABR },
3074     { "trans",         SHXMI, CM_INV|CM_ABR },
3075 #endif /* NOXMIT */
3076 #ifndef NOXFER
3077     { "transfer",      SHOXFER, 0 },
3078 #endif /* NOXFER */
3079 #ifndef NOXMIT
3080     { "transmit",      SHXMI, 0 },
3081 #endif /* NOXMIT */
3082 #ifdef CK_TRIGGER
3083     { "trigger",       SHTRIG, CM_LOC },
3084 #endif /* CK_TRIGGER */
3085 #ifndef NOSETKEY
3086 #ifndef NOKVERBS
3087 #ifdef OS2
3088     { "udk",           SHUDK, CM_LOC },
3089 #endif /* OS2 */
3090 #endif /* NOKVERBS */
3091 #endif /* NOSETKEY */
3092 #ifndef NOSPL
3093     { "variables",     SHBUI, 0 },
3094 #endif /* NOSPL */
3095 #ifndef NOFRILLS
3096     { "versions",      SHVER, 0 },
3097 #endif /* NOFRILLS */
3098 #ifdef OS2
3099     { "vscrn",         SHVSCRN, CM_INV|CM_LOC },
3100 #endif /* OS2 */
3101     { "xfer",          SHOXFER,  CM_INV },
3102 #ifndef NOXMIT
3103     { "xmit",          SHXMI,    CM_INV },
3104 #endif /* NOXMIT */
3105     { "", 0, 0 }
3106 };
3107 int nsho = (sizeof(shotab) / sizeof(struct keytab)) - 1;
3108 #endif /* NOSHOW */
3109 
3110 #ifdef ANYX25
3111 #ifndef IBMX25
3112 struct keytab padtab[] = {              /* PAD commands */
3113     { "clear",      XYPADL, 0 },
3114     { "interrupt",  XYPADI, 0 },
3115     { "reset",      XYPADR, 0 },
3116     { "status",     XYPADS, 0 }
3117 };
3118 int npadc = (sizeof(padtab) / sizeof(struct keytab));
3119 #endif /* IBMX25 */
3120 #endif /* ANYX25 */
3121 
3122 #ifndef NOSERVER
3123 static struct keytab kmstab[] = {
3124     { "both",    3, 0 },
3125     { "local",   1, 0 },
3126     { "remote",  2, 0 }
3127 };
3128 
3129 static struct keytab enatab[] = {	/* ENABLE commands */
3130     { "all",        EN_ALL,  0 },
3131 #ifndef NOSPL
3132     { "as",         EN_ASG,  CM_INV|CM_ABR },
3133     { "asg",        EN_ASG,  CM_INV },
3134     { "assign",     EN_ASG,  0 },
3135 #endif /* NOSPL */
3136 #ifndef datageneral
3137     { "bye",        EN_BYE,  0 },
3138 #endif /* datageneral */
3139     { "cd",         EN_CWD,  0 },
3140 #ifdef ZCOPY
3141     { "copy",       EN_CPY,  0 },
3142 #endif /* ZCOPY */
3143     { "cwd",        EN_CWD,  CM_INV },
3144     { "delete",     EN_DEL,  0 },
3145     { "directory",  EN_DIR,  0 },
3146     { "enable",     EN_ENA,  CM_INV },
3147     { "exit",       EN_XIT,  0 },
3148     { "finish",     EN_FIN,  0 },
3149     { "get",        EN_GET,  0 },
3150     { "host",       EN_HOS,  0 },
3151     { "mail",       EN_MAI,  0 },
3152     { "mkdir",      EN_MKD,  0 },
3153     { "print",      EN_PRI,  0 },
3154 #ifndef NOSPL
3155     { "query",      EN_QUE,  0 },
3156 #endif /* NOSPL */
3157     { "rename",     EN_REN,  0 },
3158     { "retrieve",   EN_RET,  CM_INV },
3159     { "rmdir",      EN_RMD,  0 },
3160     { "send",       EN_SEN,  0 },
3161     { "set",        EN_SET,  0 },
3162     { "space",      EN_SPA,  0 },
3163     { "type",       EN_TYP,  0 },
3164     { "who",        EN_WHO,  0 }
3165 };
3166 static int nena = (sizeof(enatab) / sizeof(struct keytab));
3167 #endif /* NOSERVER */
3168 
3169 struct keytab txtbin[] = {
3170     { "all",        2, 0 },
3171     { "binary",     1, 0 },
3172     { "text",       0, 0 }
3173 };
3174 
3175 #ifndef NOXFER
3176 static struct keytab sndtab[] = {	/* SEND command options */
3177     { "/after",           SND_AFT, CM_ARG },
3178 #ifndef NOSPL
3179     { "/array",           SND_ARR, CM_ARG },
3180 #endif /* NOSPL */
3181     { "/as-name",         SND_ASN, CM_ARG },
3182     { "/b",               SND_BIN, CM_INV|CM_ABR },
3183     { "/before",          SND_BEF, CM_ARG },
3184     { "/binary",          SND_BIN, 0 },
3185 #ifdef CALIBRATE
3186     { "/c",               SND_CMD, CM_INV|CM_ABR },
3187     { "/calibrate",       SND_CAL, CM_INV|CM_ARG },
3188 #endif /* CALIBRATE */
3189     { "/command",         SND_CMD, CM_PSH },
3190     { "/delete",          SND_DEL, 0 },
3191 #ifdef UNIXOROSK
3192     { "/dotfiles",        SND_DOT, 0 },
3193 #endif /* UNIXOROSK */
3194     { "/except",          SND_EXC, CM_ARG },
3195 #ifdef PIPESEND
3196     { "/filter",          SND_FLT, CM_ARG|CM_PSH },
3197 #endif /* PIPESEND */
3198     { "/filenames",       SND_NAM, CM_ARG },
3199 #ifdef CKSYMLINK
3200     { "/followlinks",	  SND_LNK, 0 },
3201 #endif /* CKSYMLINK */
3202 #ifdef VMS
3203     { "/image",           SND_IMG, 0 },
3204 #else
3205     { "/image",           SND_BIN, CM_INV },
3206 #endif /* VMS */
3207 #ifdef CK_LABELED
3208     { "/labeled",         SND_LBL, 0 },
3209 #endif /* CK_LABELED */
3210     { "/larger-than",     SND_LAR, CM_ARG },
3211     { "/listfile",        SND_FIL, CM_ARG },
3212 #ifndef NOFRILLS
3213     { "/mail",            SND_MAI, CM_ARG },
3214 #endif /* NOFRILLS */
3215 #ifdef CK_TMPDIR
3216     { "/move-to",         SND_MOV, CM_ARG },
3217 #endif /* CK_TMPDIR */
3218     { "/nobackupfiles",   SND_NOB, 0 },
3219 #ifdef UNIXOROSK
3220     { "/nodotfiles",      SND_NOD, 0 },
3221 #endif /* UNIXOROSK */
3222 #ifdef CKSYMLINK
3223     { "/nofollowlinks",	  SND_NLK, 0 },
3224 #endif /* CKSYMLINK */
3225     { "/not-after",       SND_NAF, CM_ARG },
3226     { "/not-before",      SND_NBE, CM_ARG },
3227     { "/pathnames",       SND_PTH, CM_ARG },
3228     { "/print",           SND_PRI, CM_ARG },
3229 #ifdef CK_XYZ
3230     { "/protocol",        SND_PRO, CM_ARG },
3231 #else
3232     { "/protocol",        SND_PRO, CM_ARG|CM_INV },
3233 #endif /* CK_XYZ */
3234     { "/quiet",           SND_SHH, 0 },
3235     { "/recover",         SND_RES, 0 },
3236 #ifdef RECURSIVE
3237 /* Systems where we do recursion */
3238     { "/recursive",       SND_REC, 0 },
3239 #else
3240 #ifdef VMS
3241 /* Systems that do recursion themselves without our assistance */
3242 /* if we give them the right kind of wildcard */
3243     { "/recursive",       SND_REC, 0 },
3244 #else
3245 #ifdef datageneral
3246     { "/recursive",       SND_REC, 0 },
3247 #else
3248     { "/recursive",       SND_REC, CM_INV },
3249 #endif /* datageneral */
3250 #endif /* VMS */
3251 #endif /* RECURSIVE */
3252     { "/rename-to",       SND_REN, CM_ARG },
3253     { "/since",           SND_AFT, CM_INV|CM_ARG },
3254     { "/smaller-than",    SND_SMA, CM_ARG },
3255     { "/starting-at",     SND_STA, CM_ARG },
3256 #ifndef NOFRILLS
3257     { "/su",              SND_ASN, CM_ARG|CM_INV|CM_ABR },
3258     { "/sub",             SND_ASN, CM_ARG|CM_INV|CM_ABR },
3259     { "/subject",         SND_ASN, CM_ARG },
3260 #endif /* NOFRILLS */
3261 #ifdef RECURSIVE
3262     { "/subdirectories",  SND_REC, CM_INV },
3263 #endif /* RECURSIVE */
3264     { "/text",            SND_TXT, 0 },
3265     { "/transparent",     SND_XPA, 0 },
3266     { "/type",            SND_TYP, CM_ARG }
3267 };
3268 #define NSNDTAB sizeof(sndtab)/sizeof(struct keytab)
3269 static int nsndtab = NSNDTAB;
3270 
3271 #ifndef NOMSEND
3272 static struct keytab msndtab[] = {	/* MSEND options */
3273     { "/after",           SND_AFT, CM_ARG },
3274     { "/before",          SND_BEF, CM_ARG },
3275     { "/binary",          SND_BIN, 0 },
3276     { "/delete",          SND_DEL, 0 },
3277     { "/except",          SND_EXC, CM_ARG },
3278     { "/filenames",       SND_NAM, CM_ARG },
3279 #ifdef CKSYMLINK
3280     { "/followlinks",	  SND_LNK, 0 },
3281 #endif /* CKSYMLINK */
3282 #ifdef VMS
3283     { "/image",           SND_IMG, 0 },
3284 #else
3285     { "/image",           SND_BIN, CM_INV },
3286 #endif /* VMS */
3287 #ifdef CK_LABELED
3288     { "/labeled",         SND_LBL, 0 },
3289 #endif /* CK_LABELED */
3290     { "/larger-than",     SND_LAR, CM_ARG },
3291     { "/list",            SND_FIL, CM_ARG },
3292 #ifndef NOFRILLS
3293     { "/mail",            SND_MAI, CM_ARG },
3294 #endif /* NOFRILLS */
3295 #ifdef CK_TMPDIR
3296     { "/move-to",         SND_MOV, CM_ARG },
3297 #endif /* CK_TMPDIR */
3298 #ifdef CKSYMLINK
3299     { "/nofollowlinks",	SND_NLK, 0 },
3300 #endif /* CKSYMLINK */
3301     { "/not-after",       SND_NAF, CM_ARG },
3302     { "/not-before",      SND_NBE, CM_ARG },
3303     { "/pathnames",       SND_PTH, CM_ARG },
3304     { "/print",           SND_PRI, CM_ARG },
3305 #ifdef CK_XYZ
3306     { "/protocol",        SND_PRO, CM_ARG },
3307 #endif /* CK_XYZ */
3308     { "/quiet",           SND_SHH, 0 },
3309     { "/recover",         SND_RES, 0 },
3310     { "/rename-to",       SND_REN, CM_ARG },
3311     { "/since",           SND_AFT, CM_INV|CM_ARG },
3312     { "/smaller-than",    SND_SMA, CM_ARG },
3313     { "/starting-at",     SND_STA, CM_ARG },
3314 #ifndef NOFRILLS
3315     { "/subject",         SND_ASN, CM_ARG },
3316 #endif /* NOFRILLS */
3317     { "/text",            SND_TXT, 0 },
3318     { "/transparent",     SND_XPA, 0 },
3319     { "/type",            SND_TYP, CM_ARG }
3320 };
3321 #define NMSNDTAB sizeof(msndtab)/sizeof(struct keytab)
3322 static int nmsndtab = NMSNDTAB;
3323 #endif /* NOMSEND */
3324 #endif /* NOXFER */
3325 
3326 /* CONNECT command switches */
3327 
3328 #define CONN_II  0	/* Idle interval */
3329 #define CONN_IS  1	/* Idle string */
3330 #define CONN_IL  2	/* Idle limit */
3331 #define CONN_NV  3	/* Non-Verbose */
3332 #define CONN_TL  4	/* Time limit */
3333 #define CONN_TS  5	/* Trigger string */
3334 #define CONN_AS  6	/* Asynchronous */
3335 #define CONN_SY  7	/* Synchronous */
3336 #define CONN_MAX 7	/* Number of CONNECT switches */
3337 
3338 #ifndef NOLOCAL
3339 static struct keytab conntab[] = {
3340 #ifdef OS2
3341     { "/asynchronous",    CONN_AS, CM_INV },
3342 #endif /* OS2 */
3343 #ifdef XLIMITS
3344     { "/idle-interval",   CONN_II, CM_ARG },
3345     { "/idle-limit",      CONN_IL, CM_ARG },
3346     { "/idle-string",     CONN_IS, CM_ARG },
3347     { "/quietly",         CONN_NV, CM_INV },
3348 #else
3349     { "/quietly",         CONN_NV, 0 },
3350 #endif /* XLIMITS */
3351 #ifdef OS2
3352     { "/synchronous",     CONN_SY, CM_INV },
3353 #endif /* OS2 */
3354 #ifdef XLIMITS
3355     { "/time-limit",      CONN_TL, CM_ARG },
3356 #endif /* XLIMITS */
3357 #ifdef CK_TRIGGER
3358     { "/trigger",         CONN_TS, CM_ARG },
3359 #endif /* CK_TRIGGER */
3360     { "",0,0 }
3361 };
3362 #define NCONNTAB sizeof(conntab)/sizeof(struct keytab)
3363 static int nconntab = NCONNTAB;
3364 #endif /* NOLOCAL */
3365 
3366 #ifndef NOXFER
3367 static struct keytab stattab[] = {	/* STATISTICS command switches */
3368     { "/brief",   1, 0 },
3369     { "/verbose", 0, 0 }
3370 };
3371 #endif /* NOXFER */
3372 
3373 #ifndef NOSPL
3374 #ifdef COMMENT
3375 struct mtab mactab[MAC_MAX] = {		/* Preinitialized macro table */
3376     { NULL, NULL, 0 }
3377 };
3378 #else
3379 struct mtab *mactab;			/* Dynamically allocated macro table */
3380 #endif /* COMMENT */
3381 int nmac = 0;
3382 
3383 struct keytab mackey[MAC_MAX];		/* Macro names as command keywords */
3384 #endif /* NOSPL */
3385 
3386 #ifndef NOSPL
3387 #ifdef  OS2
3388 struct keytab beeptab[] = {		/* Beep options */
3389     { "error", BP_FAIL, 0 },
3390     { "information", BP_NOTE, 0 },
3391     { "warning", BP_WARN, 0 }
3392 };
3393 int nbeeptab = sizeof(beeptab)/sizeof(struct keytab);
3394 
3395 /* CLEAR COMMMAND-SCREEN options */
3396 
3397 #define CLR_C_ALL 0
3398 #define CLR_C_BOL 1
3399 #define CLR_C_BOS 2
3400 #define CLR_C_EOL 3
3401 #define CLR_C_EOS 4
3402 #define CLR_C_LIN 5
3403 #define CLR_C_SCR 6
3404 
3405 struct keytab clrcmdtab[] = {
3406     { "all",        CLR_C_ALL, 0 },
3407     { "bol",        CLR_C_BOL, 0 },
3408     { "bos",        CLR_C_BOS, 0 },
3409     { "eol",        CLR_C_EOL, 0 },
3410     { "eos",        CLR_C_EOS, 0 },
3411     { "line",       CLR_C_LIN, 0 },
3412     { "scrollback", CLR_C_SCR, 0 }
3413 };
3414 int nclrcmd = sizeof(clrcmdtab)/sizeof(struct keytab);
3415 #endif /* OS2 */
3416 #endif /* NOSPL */
3417 
3418 #ifdef COMMENT
3419 /* Not used at present */
3420 static struct keytab pagetab[] = {
3421     { "/more",   1, CM_INV },
3422     { "/nopage", 0, 0 },
3423     { "/page",   1, 0 }
3424 };
3425 int npagetab = sizeof(pagetab)/sizeof(struct keytab);
3426 #endif /* COMMENT */
3427 
3428 #define TYP_NOP  0			/* /NOPAGE */
3429 #define TYP_PAG  1			/* /PAGE */
3430 #define TYP_HEA  2			/* /HEAD:n */
3431 #define TYP_TAI  3			/* /TAIL:n */
3432 #define TYP_PAT  4			/* /MATCH:pattern */
3433 #define TYP_WID  5			/* /WIDTH:cols */
3434 #define TYP_COU  6			/* /COUNT */
3435 #define TYP_OUT  7			/* /OUTPUT:file */
3436 #define TYP_PFX  8			/* /PREFIX:string */
3437 #ifdef UNICODE
3438 #define TYP_XIN  9			/* /TRANSLATE-FROM:charset */
3439 #define TYP_XUT 10			/* /TRANSLATE-TO:charset */
3440 #define TYP_XPA 11			/* /TRANSPARENT */
3441 #endif /* UNICODE */
3442 #ifdef KUI
3443 #define TYP_GUI 12			/* /GUI:title */
3444 #define TYP_HIG 13			/* /HEIGHT:rows */
3445 #endif /* KUI */
3446 #define TYP_NUM 14			/* /NUMBER */
3447 
3448 static struct keytab typetab[] = {	/* TYPE command switches */
3449     { "/count",          TYP_COU, 0 },
3450 #ifdef UNICODE
3451     { "/character-set",  TYP_XIN, CM_ARG },
3452 #endif /* UNICODE */
3453 #ifdef KUI
3454     { "/gui",            TYP_GUI, CM_ARG },
3455 #endif /* KUI */
3456     { "/head",           TYP_HEA, CM_ARG },
3457 #ifdef KUI
3458     { "/height",         TYP_HIG, CM_ARG },
3459 #endif /* KUI */
3460     { "/match",          TYP_PAT, CM_ARG },
3461 #ifdef CK_TTGWSIZ
3462     { "/more",           TYP_PAG, CM_INV },
3463     { "/nopage",         TYP_NOP, 0 },
3464     { "/number",         TYP_NUM, 0 },
3465     { "/output",         TYP_OUT, CM_ARG },
3466     { "/page",           TYP_PAG, 0 },
3467 #endif /* CK_TTGWSIZ */
3468     { "/prefix",         TYP_PFX, CM_ARG },
3469     { "/tail",           TYP_TAI, CM_ARG },
3470 #ifdef UNICODE
3471     { "/translate-to",   TYP_XUT, CM_ARG },
3472     { "/transparent",    TYP_XPA, 0 },
3473 #endif /* UNICODE */
3474     { "/width",          TYP_WID, CM_ARG },
3475 #ifdef UNICODE
3476     { "/xlate-to",       TYP_XUT, CM_INV|CM_ARG },
3477 #endif /* UNICODE */
3478     { "", 0, 0 }
3479 };
3480 int ntypetab = sizeof(typetab)/sizeof(struct keytab) - 1;
3481 
3482 int typ_page = -1;			/* TYPE /[NO]PAGE default */
3483 int typ_wid  = -1;
3484 
3485 #ifndef NOSPL
3486 #define TRA_ALL 999			/* TRACE command */
3487 #define TRA_ASG 0
3488 #define TRA_CMD 1
3489 
3490 int tra_asg = 0;
3491 int tra_cmd = 0;
3492 
3493 static struct keytab tracetab[] = {	/* TRACE options */
3494     { "all",            TRA_ALL, 0 },
3495     { "assignments",    TRA_ASG, 0 },
3496     { "command-level",  TRA_CMD, 0 }
3497 };
3498 static int ntracetab = sizeof(tracetab)/sizeof(struct keytab);
3499 #endif /* NOSPL */
3500 
3501 #ifndef NOSHOW
3502 VOID
showtypopts()3503 showtypopts() {
3504     printf(" TYPE ");
3505     if (typ_page > -1) {
3506 	prtopt(&optlines,typ_page ? "/PAGE" : "/NOPAGE");
3507     } else
3508       prtopt(&optlines,"(no options set)");
3509     if (typ_wid > -1) {
3510 	ckmakmsg(tmpbuf,TMPBUFSIZ,"/WIDTH:",ckitoa(typ_wid),NULL,NULL);
3511 	prtopt(&optlines,tmpbuf);
3512     }
3513     prtopt(&optlines,"");
3514 }
3515 #endif /* NOSHOW */
3516 
3517 #ifdef LOCUS
3518 /* isauto == 1 if locus is being switched automatically */
3519 
3520 VOID
setlocus(x,isauto)3521 setlocus(x, isauto) int x, isauto; {
3522     extern int quitting;
3523     if (x) x = 1;
3524     if (x && locus) return;
3525     if (!x && !locus) return;
3526     /* Get here if it actually needs to be changed */
3527 #ifdef OS2
3528     if (isauto &&			/* Automatically switching */
3529 	!quitting &&			/* not exiting */
3530 	autolocus == 2) {		/* and AUTOLOCUS is set to ASK */
3531 	char locmsg[300];
3532 	ckmakmsg(locmsg,300,
3533 		 "Switching Locus to ",
3534 		 x ? "LOCAL" : "REMOTE",
3535 		 " for file management commands\n"
3536                  "such as CD, DIRECTORY, DELETE, RENAME.  Type HELP SET\n"
3537                  "LOCUS at the K-95> prompt for further info.  Use the\n"
3538 #ifdef KUI
3539                   "Actions menu or SET LOCUS command to disable automatic\n"
3540                   "Locus switching or to disable these queries.",
3541 #else /* KUI */
3542                   "SET LOCUS command to disable automatic locus switching\n"
3543                   "or to disable these queries.",
3544 #endif /* KUI */
3545                   NULL);
3546 	if (uq_ok(locmsg,"OK to switch Locus?",3,NULL,1)) {
3547 	    locus = x;
3548 #ifdef KUI
3549 	    KuiSetProperty(KUI_LOCUS,x,0);
3550 #endif /* KUI */
3551 	    return;
3552 	}
3553     } else {
3554 #endif /* OS2 */
3555         if (isauto && msgflg && !quitting)
3556           printf("Switching LOCUS for file-management commands to %s %s.\n",
3557 		 x ? "LOCAL" : "REMOTE",
3558 		 "(HELP LOCUS for info)"
3559 		 );
3560 	locus = x;
3561 #ifdef OS2
3562 #ifdef KUI
3563 	KuiSetProperty(KUI_LOCUS,x,0);
3564 #endif /* KUI */
3565     }
3566 #endif /* OS2 */
3567 }
3568 
3569 VOID
setautolocus(x)3570 setautolocus(x) int x; {
3571     autolocus = x;
3572 #ifdef KUI
3573     KuiSetProperty(KUI_AUTO_LOCUS,x,0);
3574 #endif /* KUI */
3575 }
3576 #endif /* LOCUS */
3577 
3578 int
settypopts()3579 settypopts() {				/* Set TYPE option defaults */
3580     int xp = -1;
3581     int c, getval;
3582     while (1) {
3583 	if ((y = cmswi(typetab,ntypetab,"Switch","",xxstring)) < 0) {
3584 	    if (y == -3)
3585 	      break;
3586 	    else
3587 	      return(y);
3588 	}
3589 	c = cmgbrk();
3590 	if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
3591 	    printf("?This switch does not take an argument\n");
3592 	    return(-9);
3593 	}
3594 	switch (y) {
3595 	  case TYP_NOP: xp = 0; break;
3596 	  case TYP_PAG: xp = 1; break;
3597 	  case TYP_WID:
3598 	    if (getval)
3599 	      if ((x = cmnum("Column at which to truncate",
3600 			     ckitoa(cmd_cols),10,&y,xxstring)) < 0)
3601 		return(x);
3602 	    typ_wid = y;
3603 	    break;
3604 
3605           default:
3606 	    printf("?Sorry, this option can not be set\n");
3607 	    return(-9);
3608 	}
3609     }
3610     if ((x = cmcfm()) < 0)		/* Get confirmation */
3611       return(x);
3612     if (xp > -1) typ_page = xp;		/* Confirmed, save defaults */
3613     return(success = 1);
3614 }
3615 
3616 _PROTOTYP (char * getbasename, ( char * ) );
3617 
3618 /* Forward declarations of functions local to this module */
3619 
3620 #ifdef UNIX
3621 _PROTOTYP (int douchmod, ( void ) );
3622 #endif /* UNIX */
3623 #ifdef CKPURGE
3624 _PROTOTYP (int dopurge,  ( void ) );
3625 #endif /* CKPURGE */
3626 #ifndef NOSPL
3627 _PROTOTYP (int doundef,  ( int  ) );
3628 _PROTOTYP (int doask,    ( int  ) );
3629 _PROTOTYP (int dodef,    ( int  ) );
3630 _PROTOTYP (int doelse,   ( void ) );
3631 _PROTOTYP (int dofor,    ( void ) );
3632 #endif /* NOSPL  */
3633 #ifndef NODIAL
3634 _PROTOTYP (int dodial,   ( int  ) );
3635 #endif /* NODIAL */
3636 _PROTOTYP (int dodel,    ( void ) );
3637 _PROTOTYP (int dopaus,   ( int  ) );
3638 #ifndef NOPUSH
3639 #ifdef TCPSOCKET
3640 _PROTOTYP (int doping,   ( void ) );
3641 _PROTOTYP (int doftp,    ( void ) );
3642 #endif /* TCPSOCKET */
3643 #endif /* NOPUSH */
3644 #ifndef NORENAME
3645 #ifndef NOFRILLS
3646 _PROTOTYP (int dorenam,  ( void ) );
3647 #endif /* NOFRILLS */
3648 #endif /* NORENAME */
3649 #ifdef ZCOPY
3650 _PROTOTYP (int docopy,   ( void ) );
3651 #endif /* ZCOPY */
3652 #ifdef NT
3653 _PROTOTYP (int dolink,   ( void ));
3654 #endif /* NT */
3655 #ifdef CK_REXX
3656 _PROTOTYP (int dorexx,   ( void ) );
3657 #endif /* CK_REXX */
3658 
3659 #ifdef TNCODE
3660 static struct keytab telcmd[] = {
3661     { "abort", TN_ABORT, CM_INV },	/* Emotionally toned - don't show */
3662     { "ao",    TN_AO,    0 },
3663     { "ayt",   TN_AYT,   0 },
3664     { "break", BREAK,    0 },
3665     { "cancel",TN_ABORT, 0 },
3666     { "dmark", TN_DM,    0 },
3667     { "do",    DO,       0 },
3668     { "dont",  DONT,     0 },
3669     { "ec",    TN_EC,    0 },
3670     { "el",    TN_EL,    0 },
3671     { "eof",   TN_EOF,   0 },
3672     { "eor",   TN_EOR,   0 },
3673 #ifdef CK_KERBEROS
3674 #ifdef KRB5
3675 #define TN_FWD 1
3676     { "forward", TN_FWD, CM_INV },
3677 #endif /* KRB5 */
3678 #endif /* CK_KERBEROS */
3679     { "ga",    TN_GA,    0 },
3680     { "ip",    TN_IP,    0 },
3681     { "nop",   TN_NOP,   0 },
3682     { "sak",   TN_SAK,   CM_INV },
3683     { "sb",    SB,       0 },
3684     { "se",    SE,       0 },
3685     { "susp",  TN_SUSP,  0 },
3686     { "will",  WILL,     0 },
3687     { "wont",  WONT,     0 }
3688 };
3689 static int ntelcmd = (sizeof(telcmd) / sizeof(struct keytab));
3690 
3691 static struct keytab tnopts[] = {
3692 #ifdef CK_AUTHENTICATION
3693     { "auth",   TELOPT_AUTHENTICATION,   0 },
3694 #else
3695     { "auth",   TELOPT_AUTHENTICATION,   CM_INV },
3696 #endif /* CK_AUTHENTICATION */
3697     { "binary", TELOPT_BINARY, 0 },
3698 #ifdef TN_COMPORT
3699     { "c",      TELOPT_COMPORT, CM_INV|CM_ABR},
3700     { "co",     TELOPT_COMPORT, CM_INV|CM_ABR},
3701     { "com",    TELOPT_COMPORT, CM_INV|CM_ABR},
3702     { "com-port-control", TELOPT_COMPORT, 0 },
3703     { "comport-control", TELOPT_COMPORT, CM_INV},
3704 #else  /* TN_COMPORT */
3705     { "com-port-control", TELOPT_COMPORT, CM_INV },
3706     { "comport-control", TELOPT_COMPORT, CM_INV},
3707 #endif /* TN_COMPORT */
3708     { "echo", TELOPT_ECHO, 0 },
3709 #ifdef CK_ENCRYPTION
3710     { "encrypt", TELOPT_ENCRYPTION, 0 },
3711 #else
3712     { "encrypt", TELOPT_ENCRYPTION, CM_INV },
3713 #endif /* CK_ENCRYPTION */
3714 #ifdef CK_FORWARD_X
3715     { "forward-x", TELOPT_FORWARD_X, 0 },
3716 #else
3717     { "forward-x", TELOPT_FORWARD_X, CM_INV },
3718 #endif /* CK_FORWARD_X */
3719 #ifdef IKS_OPTION
3720     { "kermit", TELOPT_KERMIT, 0 },
3721 #else
3722     { "kermit", TELOPT_KERMIT, CM_INV },
3723 #endif /* IKS_OPTION */
3724     { "lflow",  TELOPT_LFLOW, CM_INV },
3725     { "logout", TELOPT_LOGOUT, CM_INV },
3726 #ifdef CK_NAWS
3727     { "naws", TELOPT_NAWS, 0 },
3728 #else
3729     { "naws", TELOPT_NAWS, CM_INV },
3730 #endif /* CK_NAWS */
3731 #ifdef CK_ENVIRONMENT
3732     { "new-environment", TELOPT_NEWENVIRON,  0 },
3733 #else
3734     { "new-environment", TELOPT_NEWENVIRON,  CM_INV },
3735 #endif /* CK_ENVIRONMENT */
3736     { "pragma-heartbeat",TELOPT_PRAGMA_HEARTBEAT,  CM_INV },
3737     { "pragma-logon",    TELOPT_PRAGMA_LOGON,  CM_INV },
3738     { "pragma-sspi",     TELOPT_SSPI_LOGON,  CM_INV },
3739     { "sak",   TELOPT_IBM_SAK, CM_INV },
3740 #ifdef CK_SNDLOC
3741     { "send-location",   TELOPT_SNDLOC,  0 },
3742 #else
3743     { "send-location",   TELOPT_SNDLOC,  CM_INV },
3744 #endif /* CK_SNDLOC */
3745     { "sga", TELOPT_SGA, 0 },
3746 #ifdef CK_SSL
3747     { "start-tls",       TELOPT_START_TLS,  0 },
3748 #else
3749     { "start-tls",       TELOPT_START_TLS,  CM_INV },
3750 #endif /* CK_SSL */
3751     { "ttype", TELOPT_TTYPE, 0 },
3752 #ifdef CK_ENVIRONMENT
3753     { "xdisplay-location", TELOPT_XDISPLOC, 0 },
3754 #else
3755     { "xdisplay-location", TELOPT_XDISPLOC, CM_INV },
3756 #endif /* CK_ENVIRONMENT */
3757     { "", 0, 0 }
3758 };
3759 static int ntnopts = (sizeof(tnopts) / sizeof(struct keytab)) - 1;
3760 
3761 static struct keytab tnsbopts[] = {
3762 #ifdef CK_NAWS
3763     { "naws", TELOPT_NAWS, 0 },
3764 #endif /* CK_NAWS */
3765     { "", 0, 0 }
3766 };
3767 static int ntnsbopts = (sizeof(tnsbopts) / sizeof(struct keytab)) - 1;
3768 #endif /* TNCODE */
3769 
3770 #ifdef TCPSOCKET
3771 #ifndef NOPUSH
3772 #ifdef SYSFTP
3773 int
doftp()3774 doftp() {				/* (External) FTP command */
3775     char *p, *f;			/* (See doxftp() for internal one) */
3776     int x;
3777 
3778     if (network)			/* If we have a current connection */
3779       ckstrncpy(line,ttname,LINBUFSIZ);	/* get the host name */
3780     else *line = '\0';			/* as default host */
3781     for (p = line; *p; p++)		/* Remove ":service" from end. */
3782       if (*p == ':') { *p = '\0'; break; }
3783     if ((x = cmtxt("IP host name or number", line, &s, xxstring)) < 0)
3784       return(x);
3785     if (nopush) {
3786         printf("?Sorry, FTP command disabled\n");
3787         return(success = 0);
3788     }
3789 /* Construct FTP command */
3790 #ifdef VMS
3791 #ifdef MULTINET				/* TGV MultiNet */
3792     ckmakmsg(line,LINBUFSIZ,"multinet ftp ",s,NULL,NULL);
3793 #else
3794     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3795 #endif /* MULTINET */
3796 #else					/* Not VMS */
3797 #ifdef OS2ORUNIX
3798 #ifndef NOFTP
3799     f = ftpapp;
3800     if (!f) f = "";
3801     if (!f[0]) f = "ftp";
3802     ckmakmsg(line,LINBUFSIZ,f," ",s,NULL);
3803 #ifdef OS2
3804     p = line + strlen(ftpapp);
3805     while (p != line) {
3806         if (*p == '/') *p = '\\';
3807         p--;
3808     }
3809 #endif /* OS2 */
3810 #else /* NOFTP */
3811     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3812 #endif /* NOFTP */
3813 #else /* OS2ORUNIX */
3814     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3815 #endif /* OS2ORUNIX */
3816 #endif /* VMS */
3817     conres();				/* Make console normal  */
3818 #ifdef DEC_TCPIP
3819     printf("\n");			/* Prevent prompt-stomping */
3820 #endif /* DEC_TCPIP */
3821     x = zshcmd(line);
3822     concb((char)escape);
3823     return(success = x);
3824 }
3825 #endif /* SYSFTP */
3826 
3827 int
doping()3828 doping() {				/* PING command */
3829     char *p;				/* just runs ping program */
3830     int x;
3831 
3832     if (network)			/* If we have a current connection */
3833       ckstrncpy(line,ttname,LINBUFSIZ);	/* get the host name */
3834     else *line = '\0';			/* as default host to be pinged. */
3835     for (p = line; *p; p++)		/* Remove ":service" from end. */
3836       if (*p == ':') { *p = '\0'; break; }
3837     if ((x = cmtxt("IP host name or number", line, &s, xxstring)) < 0)
3838       return(x);
3839     if (nopush) {
3840         printf("?Sorry, PING command disabled\n");
3841         return(success = 0);
3842     }
3843 
3844     /* Construct PING command */
3845 #ifdef VMS
3846 #ifdef MULTINET				/* TGV MultiNet */
3847     ckmakmsg(line,LINBUFSIZ,"multinet ping ",s," /num=1",NULL);
3848 #else
3849     ckmakmsg(line,LINBUFSIZ,"ping ",s," 56 1",NULL); /* Other VMS TCP/IP's */
3850 #endif /* MULTINET */
3851 #else					/* Not VMS */
3852     ckmakmsg(line,LINBUFSIZ,"ping ",s,NULL,NULL);
3853 #endif /* VMS */
3854     conres();				/* Make console normal  */
3855 #ifdef DEC_TCPIP
3856     printf("\n");			/* Prevent prompt-stomping */
3857 #endif /* DEC_TCPIP */
3858     x = zshcmd(line);
3859     concb((char)escape);
3860     return(success = x);
3861 }
3862 #endif /* NOPUSH */
3863 #endif /* TCPSOCKET */
3864 
3865 static VOID
doend(x)3866 doend(x) int x; {
3867 #ifndef NOSPL
3868     /* Pop from all FOR/WHILE/XIF/SWITCH's */
3869     debug(F101,"doend maclvl 1","",maclvl);
3870     while ((maclvl > 0) &&
3871 	   (m_arg[maclvl-1][0]) &&
3872 	   (cmdstk[cmdlvl].src == CMD_MD) &&
3873 	   (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
3874 	    !strncmp(m_arg[maclvl-1][0],"_for",4) ||
3875 	    !strncmp(m_arg[maclvl-1][0],"_whi",4) ||
3876 	    !strncmp(m_arg[maclvl-1][0],"_swi",4))) {
3877 	debug(F110,"END popping",m_arg[maclvl-1][0],0);
3878 	dogta(XXPTA);			/* Put args back */
3879 	popclvl();			/* Pop up two levels */
3880 	popclvl();
3881 	debug(F101,"doend maclvl 2","",maclvl);
3882     }
3883     if (maclvl > -1) {
3884 	if (mrval[maclvl])		/* Free previous retval if any */
3885 	  free(mrval[maclvl]);
3886 	mrval[maclvl] = malloc(16);	/* Room for up to 15 digits */
3887 	if (mrval[maclvl])		/* Record current retval */
3888 	  ckmakmsg(mrval[maclvl],16,ckitoa(x),NULL,NULL,NULL);
3889     }
3890 #endif /* NOSPL */
3891     popclvl();				/* Now pop out of macro or TAKE file */
3892 #ifndef NOSPL
3893 #ifdef DEBUG
3894     if (deblog) {
3895 	debug(F101,"END maclvl 3","",maclvl);
3896 	debug(F111,"END mrval[maclvl]",mrval[maclvl],maclvl);
3897 	debug(F111,"END mrval[maclvl+1]",mrval[maclvl+1],maclvl+1);
3898     }
3899 #endif /* DEBUG */
3900 #endif /* NOSPL */
3901 }
3902 
3903 #ifdef CKROOT
3904 int
dochroot()3905 dochroot() {
3906     if ((x = cmdir("Name of new root directory","",&s,xxstring)) < 0) {
3907 	if (x == -3) {
3908 	    printf("?Directory name required\n");
3909 	    return(-9);
3910 	}
3911 	return(x);
3912     }
3913     ckstrncpy(line,s,LINBUFSIZ);
3914     s = line;
3915     if ((x = cmcfm()) < 0) return(x);
3916     s = brstrip(s);
3917     x = zsetroot(s);
3918     if (x < 0) {
3919 	char * m = NULL;
3920 	switch (x) {
3921 	  case -1:
3922 	  case -2: m = "Not a directory"; break;
3923 	  case -3: m = "Internal error"; break;
3924 	  case -4: m = "Access denied"; break;
3925 	  case -5: m = "Off limits"; break;
3926 	}
3927 	if (m) printf("%s: \"%s\"\n", m, s);
3928 	return(m ? -9 : -2);
3929     } else {
3930 	nopush = 1;
3931 	return(success = 1);
3932     }
3933 }
3934 #endif /* CKROOT */
3935 
3936 #ifndef NOXFER
3937 static char * asnbuf = NULL;		/* As-name buffer pointer */
3938 
3939 char sndxnam[] = { "_array_x_" };	/* (with replaceable x!) */
3940 
3941 /*
3942   The new SEND command, replacing BSEND, CSEND, PSEND, etc etc.
3943   Call with cx = top-level keyword value.  Returns:
3944     < 0  On parse error.
3945     0    On other type of failure (e.g. requested operation not allowed).
3946     1    On success with sstate set to 's' so protocol will begin.
3947 */
3948 
3949 /*  D O X S E N D  --  Parse SEND and related commands with switches  */
3950 
3951 int
doxsend(cx)3952 doxsend(cx) int cx; {
3953     int c, i, n, wild, confirmed = 0;	/* Workers */
3954     int x, y;				/* of the world... */
3955     int getval = 0;			/* Whether to get switch value */
3956     extern char * snd_move;		/* Directory to move sent files to */
3957     extern char * snd_rename;		/* What to rename sent files to */
3958     extern char * filefile;		/* File containing filenames to send */
3959     extern int xfiletype;		/* Send only text (or binary) files */
3960     extern struct keytab pathtab[];	/* PATHNAMES option keywords */
3961     extern int npathtab;		/* How many of them */
3962     extern int recursive;		/* Recursive directory traversal */
3963     extern int rprintf;			/* REMOTE PRINT flag */
3964     extern int fdispla;			/* TRANSFER DISPLAY setting */
3965     extern int skipbup;			/* Skip backup files when sending */
3966     struct stringint pv[SND_MAX+1];	/* Temporary array for switch values */
3967     struct FDB sf, sw, fl, cm;		/* FDBs for each parse function */
3968     int mlist = 0;			/* Flag for MSEND or MMOVE */
3969     char * m;				/* For making help messages */
3970     extern struct keytab protos[];	/* File transfer protocols */
3971     extern int xfrxla, g_xfrxla, nprotos;
3972     extern char sndbefore[], sndafter[], *sndexcept[]; /* Selection criteria */
3973     extern char sndnbefore[], sndnafter[];
3974     extern CK_OFF_T sndsmaller, sndlarger, calibrate;
3975 #ifndef NOSPL
3976     int range[2];			/* Array range */
3977     char ** ap = NULL;			/* Array pointer */
3978     int arrayx = -1;			/* Array index */
3979 #endif /* NOSPL */
3980 
3981 #ifdef NEWFTP
3982     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
3983 	if (cx == XXMAI) {
3984 	    printf("?Sorry, No MAIL with FTP\n");
3985 	    return(-9);
3986 	}
3987 	return(doftpput(cx,0));
3988     }
3989 #endif /* NEWFTP */
3990 
3991     for (i = 0; i <= SND_MAX; i++) {	/* Initialize switch values */
3992 	pv[i].sval = NULL;		/* to null pointers */
3993 	pv[i].ival = -1;		/* and -1 int values */
3994 	pv[i].wval = (CK_OFF_T)-1;	/* and -1 wide values */
3995     }
3996 #ifndef NOSPL
3997     range[0] = -1;
3998     range[1] = -1;
3999     sndxin = -1;			/* Array index */
4000 #endif /* NOSPL */
4001     sndarray = NULL;			/* Array pointer */
4002 
4003 #ifdef UNIXOROSK
4004     g_matchdot = matchdot;		/* Match dot files */
4005 #endif /* UNIXOROSK */
4006     g_recursive = recursive;		/* Recursive sending */
4007     recursive = 0;			/* Save global value, set local */
4008     debug(F101,"xsend entry fncnv","",fncnv);
4009 
4010     /* Preset switch values based on top-level command that called us */
4011 
4012     switch (cx) {
4013       case XXMSE:			/* MSEND */
4014 	mlist = 1; break;
4015       case XXCSEN:			/* CSEND */
4016 	pv[SND_CMD].ival = 1; break;
4017       case XXMMOVE:			/* MMOVE */
4018 	mlist = 1;
4019       case XXMOVE:			/* MOVE */
4020 	pv[SND_DEL].ival = 1; break;
4021       case XXRSEN:			/* RESEND */
4022 	pv[SND_BIN].ival = 1;		/* Implies /BINARY */
4023 	pv[SND_RES].ival = 1; break;
4024       case XXMAI:			/* MAIL */
4025 	pv[SND_MAI].ival = 1; break;
4026     }
4027 
4028     /* Set up chained parse functions... */
4029 
4030     cmfdbi(&sw,				/* First FDB - command switches */
4031 	   _CMKEY,			/* fcode */
4032 	   "Filename, or switch",	/* hlpmsg */
4033 	   "",				/* default */
4034 	   "",				/* addtl string data */
4035 #ifdef NOMSEND
4036 	   nsndtab,			/* addtl numeric data 1: tbl size */
4037 #else
4038 	   mlist ? nmsndtab : nsndtab,	/* addtl numeric data 1: tbl size */
4039 #endif /* NOMSEND */
4040 	   4,				/* addtl numeric data 2: 4 = cmswi */
4041 	   xxstring,			/* Processing function */
4042 #ifdef NOMSEND
4043 	   sndtab,			/* Keyword table */
4044 #else
4045 	   mlist ? msndtab : sndtab,
4046 #endif /* NOMSEND */
4047 	   &sf				/* Pointer to next FDB */
4048 	   );
4049     cmfdbi(&sf,				/* 2nd FDB - file to send */
4050 	   _CMIFI,			/* fcode */
4051 	   "File(s) to send",		/* hlpmsg */
4052 	   "",				/* default */
4053 	   "",				/* addtl string data */
4054 	   nolinks,			/* addtl numeric data 1 */
4055 	   0,				/* addtl numeric data 2 */
4056 	   xxstring,
4057 	   NULL,
4058 	   mlist ? &cm : &fl
4059 	   );
4060     cmfdbi(&fl,				/* 3rd FDB - command to send from */
4061 	   _CMFLD,			/* fcode */
4062 	   "Command",			/* hlpmsg */
4063 	   "",				/* default */
4064 	   "",				/* addtl string data */
4065 	   0,				/* addtl numeric data 1 */
4066 	   0,				/* addtl numeric data 2 */
4067 	   xxstring,
4068 	   NULL,
4069 	   &cm
4070 	   );
4071     cmfdbi(&cm,				/* 4th FDB - Confirmation */
4072 	   _CMCFM,			/* fcode */
4073 	   "",				/* hlpmsg */
4074 	   "",				/* default */
4075 	   "",				/* addtl string data */
4076 	   0,				/* addtl numeric data 1 */
4077 	   0,				/* addtl numeric data 2 */
4078 	   NULL,
4079 	   NULL,
4080 	   NULL
4081 	   );
4082 
4083     while (1) {				/* Parse 0 or more switches */
4084 	x = cmfdb(&sw);			/* Parse something */
4085 	debug(F101,"xsend cmfdb","",x);
4086 	if (x < 0)			/* Error */
4087 	  goto xsendx;			/* or reparse needed */
4088 	if (cmresult.fcode != _CMKEY)	/* Break out if not a switch */
4089 	  break;
4090 /*
4091   They gave a switch, but let's see how they terminated it.
4092   If they ended it with : or =, then we must parse a value.
4093   If they ended it with anything else, then we must NOT parse a value.
4094 */
4095 	c = cmgbrk();			/* Get break character */
4096 	getval = (c == ':' || c == '='); /* to see how they ended the switch */
4097 	if (getval && !(cmresult.kflags & CM_ARG)) {
4098 	    printf("?This switch does not take arguments\n");
4099 	    x = -9;
4100 	    goto xsendx;
4101 	}
4102 	if (!getval && (cmgkwflgs() & CM_ARG)) {
4103 	    printf("?This switch requires an argument\n");
4104 	    x = -9;
4105 	    goto xsendx;
4106 	}
4107 	n = cmresult.nresult;		/* Numeric result = switch value */
4108 	debug(F101,"xsend switch","",n);
4109 
4110 	switch (n) {			/* Process the switch */
4111 	  case SND_CMD:			/* These take no args */
4112 	    if (nopush) {
4113 		printf("?Sorry, system command access is disabled\n");
4114 		x = -9;
4115 		goto xsendx;
4116 	    }
4117 #ifdef PIPESEND
4118 	    else if (sndfilter) {
4119 		printf(
4120 "?Sorry, no SEND /COMMAND or CSEND when SEND FILTER selected\n");
4121 		x = -9;
4122 		goto xsendx;
4123 	    }
4124 #endif /* PIPESEND */
4125 	    sw.hlpmsg = "Command, or switch"; /* Change help message */
4126 	    pv[n].ival = 1;		/* Just set the flag */
4127 	    pv[SND_ARR].ival = 0;
4128 	    break;
4129 
4130 	  case SND_REC:			/* /RECURSIVE */
4131 	    recursive = 2;		/* Set the real variable */
4132 	    pv[SND_PTH].ival = PATH_REL; /* Give them relative pathnames */
4133 	    pv[n].ival = 1;		/* Just set the flag */
4134 	    break;
4135 
4136 	  case SND_RES:			/* /RECOVER (resend) */
4137 	    pv[SND_ARR].ival = 0;
4138 	    pv[SND_BIN].ival = 1;	/* Implies /BINARY */
4139 	  case SND_NOB:			/* /NOBACKUP */
4140 	  case SND_DEL:			/* /DELETE */
4141 	  case SND_SHH:			/* /QUIET */
4142 	    pv[n].ival = 1;		/* Just set the flag */
4143 	    break;
4144 
4145 #ifdef UNIXOROSK
4146 /* Like recursive, these are set immediately because they affect cmifi() */
4147 	  case SND_DOT:			/* /DOTFILES */
4148 	    matchdot = 1;
4149 	    break;
4150 	  case SND_NOD:			/* /NODOTFILES */
4151 	    matchdot = 0;
4152 	    break;
4153 #endif /* UNIXOROSK */
4154 
4155 	  /* File transfer modes - each undoes the others */
4156 
4157 	  case SND_BIN:			/* Binary */
4158 	  case SND_TXT:			/* Text */
4159 	  case SND_IMG:			/* Image */
4160 	  case SND_LBL:			/* Labeled */
4161 	    pv[SND_BIN].ival = 0;
4162 	    pv[SND_TXT].ival = 0;
4163 	    pv[SND_IMG].ival = 0;
4164 	    pv[SND_LBL].ival = 0;
4165 	    pv[n].ival = 1;
4166 	    break;
4167 
4168 #ifdef CKSYMLINK
4169 	  case SND_LNK:
4170 	  case SND_NLK:
4171 	    nolinks = (n == SND_NLK) ? 2 : 0;
4172 	    cmfdbi(&sf,			/* Redo cmifi() */
4173 		   _CMIFI,		/* fcode */
4174 		   "File(s) to send",	/* hlpmsg */
4175 		   "",			/* default */
4176 		   "",			/* addtl string data */
4177 		   nolinks,		/* addtl numeric data 1 */
4178 		   0,			/* addtl numeric data 2 */
4179 		   xxstring,
4180 		   NULL,
4181 		   mlist ? &cm : &fl
4182 		   );
4183 	    break;
4184 #endif /* CKSYMLINK */
4185 
4186 	  case SND_EXC:			/* Excludes */
4187 	    if (!getval) break;
4188 	    if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
4189 		if (x == -3) {
4190 		    printf("?Pattern required\n");
4191 		    x = -9;
4192 		}
4193 		goto xsendx;
4194 	    }
4195 	    if (pv[n].sval) free(pv[n].sval);
4196 	    y = strlen(s);
4197 	    if (y > 256) {
4198 		printf("?Pattern too long - 256 max\n");
4199 		x = -9;
4200 		goto xsendx;
4201 	    }
4202 	    pv[n].sval = malloc(y+1);
4203 	    if (pv[n].sval) {
4204 		strcpy(pv[n].sval,s);	/* safe */
4205 		pv[n].ival = 1;
4206 	    }
4207 	    break;
4208 
4209 	  case SND_MOV:			/* MOVE after */
4210 	  case SND_REN:			/* RENAME after */
4211 	    if (!getval) break;
4212 	    if ((x = cmfld(n == SND_MOV ?
4213 	   "device and/or directory for source file after sending" :
4214 	   "new name for source file after sending",
4215 			   "",
4216 			   &s,
4217 			   n == SND_MOV ? xxstring : NULL
4218 			   )) < 0) {
4219 		if (x == -3) {
4220 		    printf("%s\n", n == SND_MOV ?
4221 			   "?Destination required" :
4222 			   "?New name required"
4223 			   );
4224 		    x = -9;
4225 		}
4226 		goto xsendx;
4227 	    }
4228 	    if (pv[n].sval) free(pv[n].sval);
4229 	    s = brstrip(s);
4230 	    y = strlen(s);
4231 	    if (y > 0) {
4232 		pv[n].sval = malloc(y+1);
4233 		if (pv[n].sval) {
4234 		    strcpy(pv[n].sval,s); /* safe */
4235 		    pv[n].ival = 1;
4236 		}
4237 	    }
4238 	    break;
4239 
4240 	  case SND_SMA:			/* Smaller / larger than */
4241 	  case SND_LAR: {
4242 	      CK_OFF_T w;
4243 	      if (!getval) break;
4244 	      if ((x = cmnumw("Size in bytes","0",10,&w,xxstring)) < 0)
4245 		goto xsendx;
4246 	      pv[n].wval = w;
4247 	      break;
4248 	  }
4249 	  case SND_AFT:			/* Send /AFTER:date-time */
4250 	  case SND_BEF:			/* Send /BEFORE:date-time */
4251 	  case SND_NAF:			/* Send /NOT-AFTER:date-time */
4252 	  case SND_NBE:			/* Send /NOT-BEFORE:date-time */
4253 	    if (!getval) break;
4254 	    if ((x = cmdate("File date-time","",&s,0,xxstring)) < 0) {
4255 		if (x == -3) {
4256 		    printf("?Date-time required\n");
4257 		    x = -9;
4258 		}
4259 		goto xsendx;
4260 	    }
4261 	    if (pv[n].sval) free(pv[n].sval);
4262 	    pv[n].sval = malloc((int)strlen(s)+1);
4263 	    if (pv[n].sval) {
4264 		strcpy(pv[n].sval,s);	/* safe */
4265 		pv[n].ival = 1;
4266 	    }
4267 	    break;
4268 
4269 	  case SND_MAI:			/* Send as mail (= MAIL) */
4270 #ifdef IKSD
4271 	    if (inserver && !ENABLED(en_mai)) {
4272 		printf("?Sorry, sending files as mail is disabled\n");
4273 		return(-9);
4274 	    }
4275 #endif /* IKSD */
4276 	    pv[n].ival = 1;
4277 	    if (!getval) break;
4278 	    if ((x = cmfld("e-mail address","",&s,xxstring)) < 0) {
4279 		if (x == -3) {
4280 		    printf("?address required\n");
4281 		    x = -9;
4282 		}
4283 		goto xsendx;
4284 	    }
4285 	    s = brstrip(s);
4286 	    if (pv[n].sval) free(pv[n].sval);
4287 	    pv[n].sval = malloc((int)strlen(s)+1);
4288 	    if (pv[n].sval)
4289 	      strcpy(pv[n].sval,s);	/* safe */
4290 	    break;
4291 
4292 	  case SND_PRI:			/* Send to be printed (REMOTE PRINT) */
4293 #ifdef IKSD
4294 	    if (inserver && !ENABLED(en_mai)) {
4295 		printf("?Sorry, sending files for printing is disabled\n");
4296 		return(-9);
4297 	    }
4298 #endif /* IKSD */
4299 	    pv[n].ival = 1;
4300 	    if (!getval) break;
4301 	    if ((x = cmfld("Print options","",&s,xxstring)) < 0)
4302 	      if (x != -3) goto xsendx;
4303 	    s = brstrip(s);
4304 	    if (pv[n].sval) free(pv[n].sval);
4305 	    pv[n].sval = malloc((int)strlen(s)+1);
4306 	    if (pv[n].sval)
4307 	      strcpy(pv[n].sval,s);	/* safe */
4308 	    break;
4309 
4310 	  case SND_ASN:			/* As-name */
4311 	    debug(F101,"xsend /as-name getval","",getval);
4312 	    if (!getval) break;
4313 	    if ((x = cmfld("Name to send under","",&s,NULL)) < 0) {
4314 		if (x == -3) {
4315 		    printf("?name required\n");
4316 		    x = -9;
4317 		}
4318 		goto xsendx;
4319 	    }
4320 	    s = brstrip(s);
4321 	    if ((y = strlen(s)) > 0) {
4322 		if (pv[n].sval) free(pv[n].sval);
4323 		pv[n].sval = malloc(y+1);
4324 		if (pv[n].sval) {
4325 		    strcpy(pv[n].sval,s); /* safe */
4326 		    pv[n].ival = 1;
4327 		}
4328 	    }
4329 	    break;
4330 
4331 	  case SND_STA: {		/* Starting position (= PSEND) */
4332 	      CK_OFF_T w;
4333 	      if (!getval) break;
4334 	      if ((x = cmnumw("0-based position","0",10,&w,xxstring)) < 0)
4335 		goto xsendx;
4336 	      pv[n].wval = w;
4337 	      break;
4338 	  }
4339 	  case SND_PRO:			/* Protocol to use */
4340 	    if (!getval) break;
4341 	    if ((x = cmkey(protos,nprotos,"File-transfer protocol","",
4342 			   xxstring)) < 0) {
4343 		if (x == -3) {
4344 		    printf("?name of protocol required\n");
4345 		    x = -9;
4346 		}
4347 		goto xsendx;
4348 	    }
4349 	    pv[n].ival = x;
4350 	    break;
4351 
4352 #ifdef PIPESEND
4353 	  case SND_FLT:			/* Filter */
4354 	    debug(F101,"xsend /filter getval","",getval);
4355 	    if (!getval) break;
4356 	    if ((x = cmfld("Filter program to send through","",&s,NULL)) < 0) {
4357 		if (x == -3)
4358 		  s = "";
4359 		else
4360 		  goto xsendx;
4361 	    }
4362 	    if (*s) s = brstrip(s);
4363 	    y = strlen(s);
4364 	    for (x = 0; x < y; x++) {	/* Make sure they included "\v(...)" */
4365 		if (s[x] != '\\') continue;
4366 		if (s[x+1] == 'v') break;
4367 	    }
4368 	    if (x == y) {
4369 		printf(
4370 		"?Filter must contain a replacement variable for filename.\n"
4371 		       );
4372 		x = -9;
4373 		goto xsendx;
4374 	    }
4375 	    pv[n].ival = 1;
4376 	    if (pv[n].sval) {
4377 		free(pv[n].sval);
4378 		pv[n].sval = NULL;
4379 	    }
4380 	    if ((y = strlen(s)) > 0) {
4381 		if ((pv[n].sval = malloc(y+1)))
4382 		  strcpy(pv[n].sval,s);	/* safe */
4383 	    }
4384 	    break;
4385 #endif /* PIPESEND */
4386 
4387 	  case SND_PTH:			/* Pathnames */
4388 	    if (!getval) {
4389 		pv[n].ival = PATH_REL;
4390 		break;
4391 	    }
4392 	    if ((x = cmkey(pathtab,npathtab,"","absolute",xxstring)) < 0)
4393 	      goto xsendx;
4394 	    pv[n].ival = x;
4395 	    break;
4396 
4397 	  case SND_NAM:			/* Filenames */
4398 	    if (!getval) break;
4399 	    if ((x = cmkey(fntab,nfntab,"","converted",xxstring)) < 0)
4400 	      goto xsendx;
4401 	    debug(F101,"xsend /filenames","",x);
4402 	    pv[n].ival = x;
4403 	    break;
4404 
4405 #ifdef CALIBRATE
4406           case SND_CAL: {		/* /CALIBRATE */
4407 	      CK_OFF_T w;
4408 	      if (getval) {
4409 		  if ((x = cmnumw("number of Kbytes to send",
4410 				  "1024",10,&w,xxstring)) < 0)
4411 		    goto xsendx;
4412 	      } else
4413 		w = (CK_OFF_T)1024;
4414 	      pv[n].wval = w;
4415 	      pv[SND_ARR].ival = 0;
4416 	      break;
4417 	  }
4418 #endif /* CALIBRATE */
4419 
4420 	  case SND_FIL:			/* Name of file containing filnames */
4421 	    if (!getval) break;
4422 	    if ((x = cmifi("Name of file containing list of filenames",
4423 			       "",&s,&y,xxstring)) < 0) {
4424 		if (x == -3) {
4425 		    printf("?Filename required\n");
4426 		    x = -9;
4427 		}
4428 		goto xsendx;
4429 	    } else if (y) {
4430 		printf("?Wildcards not allowed\n");
4431 		x = -9;
4432 		goto xsendx;
4433 	    }
4434 	    if (pv[n].sval)
4435 	      free(pv[n].sval);
4436 	    if (s) if (*s) {
4437 		if ((pv[n].sval = malloc((int)strlen(s)+1))) {
4438 		    strcpy(pv[n].sval,s);
4439 		    pv[n].ival = 1;
4440 		    pv[SND_ARR].ival = 0;
4441 		}
4442 	    }
4443 	    break;
4444 
4445 #ifndef NOSPL
4446 	  case SND_ARR:			/* SEND /ARRAY: */
4447 	    if (!getval) break;
4448 	    ap = NULL;
4449 	    if ((x = cmfld("Array name (a single letter will do)",
4450 			   "",
4451 			   &s,
4452 			   NULL
4453 			   )) < 0) {
4454 		if (x == -3)
4455 		  break;
4456 		else
4457 		  return(x);
4458 	    }
4459 	    if ((x = arraybounds(s,&(range[0]),&(range[1]))) < 0) {
4460 		printf("?Bad array: %s\n",s);
4461 		return(-9);
4462 	    }
4463 	    if (!(ap = a_ptr[x])) {
4464 		printf("?No such array: %s\n",s);
4465 		return(-9);
4466 	    }
4467 	    pv[n].ival = 1;
4468 	    pv[SND_CMD].ival = 0;	/* Undo any conflicting ones... */
4469 	    pv[SND_RES].ival = 0;
4470 	    pv[SND_CAL].ival = 0;
4471 	    pv[SND_FIL].ival = 0;
4472 	    arrayx = x;
4473 	    break;
4474 #endif /* NOSPL */
4475 
4476 	  case SND_XPA:			/* /TRANSPARENT */
4477 	    pv[n].ival = 1;
4478 	    break;
4479 
4480 	  case SND_TYP:			/* Only files of given type */
4481 	    if (!getval) break;
4482 	    if ((x = cmkey(txtbin,3,"","all",xxstring)) < 0)
4483 	      goto xsendx;
4484 	    pv[n].ival = (x == 2) ? -1 : x;
4485 	    break;
4486 
4487 	  default:
4488 	    printf("?Unexpected switch value - %d\n",cmresult.nresult);
4489 	    x = -9;
4490 	    goto xsendx;
4491 	}
4492     }
4493     debug(F101,"xsend cmresult fcode","",cmresult.fcode);
4494 
4495 #ifdef COMMENT
4496     /* List switch parsing results in debug log */
4497     for (i = 0; i <= SND_MAX; i++) {
4498 	ckmakmsg(line,LINBUFSIZ,"xsend switch ",ckitoa(i),NULL,NULL);
4499 	debug(F111,line, pv[i].sval, pv[i].ival);
4500     }
4501 #endif /* COMMENT */
4502 
4503 /* Now we have all switches, plus maybe a filename or command, or nothing */
4504 
4505 #ifdef PIPESEND
4506     if (protocol != PROTO_K && pv[SND_CMD].ival > 0) {
4507 	printf("?Sorry, %s works only with Kermit protocol\n",
4508 	       (cx == XXCSEN) ? "CSEND" : "SEND /COMMAND");
4509 	x = -9;
4510 	goto xsendx;
4511     }
4512     if (pv[SND_RES].ival > 0 ||	/* /RECOVER */
4513 	pv[SND_STA].wval > 0) {	/* or /STARTING */
4514 	if (sndfilter || pv[SND_FLT].ival > 0) {
4515 	    printf("?Sorry, no /RECOVER or /START if SEND FILTER selected\n");
4516 	    x = -9;
4517 	    goto xsendx;
4518 	}
4519     }
4520 #endif /* PIPESEND */
4521 
4522     cmarg = "";
4523     cmarg2 = "";
4524     line[0] = NUL;
4525     s = line;
4526     wild = 0;
4527 
4528     switch (cmresult.fcode) {		/* How did we get out of switch loop */
4529       case _CMIFI:			/* Input filename */
4530 	ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
4531 	if (pv[SND_ARR].ival > 0)
4532 	  cmarg2 = line;
4533 	else
4534 	  wild = cmresult.nresult;	/* Wild flag */
4535 	if (!recursive && !wild)
4536 	  nolinks = 0;
4537 	break;
4538       case _CMFLD:			/* Field */
4539 	/* Only allowed with /COMMAND and /ARRAY */
4540 	if (pv[SND_CMD].ival < 1 && pv[SND_ARR].ival < 1) {
4541 #ifdef CKROOT
4542 	    if (ckrooterr)
4543 	      printf("?Off limits: %s\n",cmresult.sresult);
4544 	    else
4545 #endif /* CKROOT */
4546 	      printf("?%s - \"%s\"\n",
4547 		   iswild(cmresult.sresult) ?
4548 		   "No files match" : "File not found",
4549 		   cmresult.sresult
4550 		   );
4551 	    x = -9;
4552 	    goto xsendx;
4553 	}
4554 	ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
4555 	if (pv[SND_ARR].ival > 0)
4556 	  cmarg2 = line;
4557 	break;
4558       case _CMCFM:			/* Confirmation */
4559 	/* s = ""; */
4560 	confirmed = 1;
4561 	break;
4562       default:
4563 	printf("?Unexpected function code: %d\n",cmresult.fcode);
4564 	x = -9;
4565 	goto xsendx;
4566     }
4567     debug(F110,"xsend string",s,0);
4568     debug(F101,"xsend confirmed","",confirmed);
4569 
4570     /* Save and change protocol and transfer mode */
4571     /* Global values are restored in main parse loop */
4572 
4573     g_proto = protocol;			/* Save current global protocol */
4574     g_urpsiz = urpsiz;
4575     g_spsizf = spsizf;
4576     g_spsiz = spsiz;
4577     g_spsizr = spsizr;
4578     g_spmax = spmax;
4579     g_wslotr = wslotr;
4580     g_prefixing = prefixing;
4581     g_fncact = fncact;
4582     g_fncnv = fncnv;
4583     g_fnspath = fnspath;
4584     g_fnrpath = fnrpath;
4585     g_xfrxla = xfrxla;
4586 
4587     if (pv[SND_PRO].ival > -1) {	/* Change according to switch */
4588 	protocol = pv[SND_PRO].ival;
4589         if (ptab[protocol].rpktlen > -1) /* copied from initproto() */
4590             urpsiz = ptab[protocol].rpktlen;
4591         if (ptab[protocol].spktflg > -1)
4592             spsizf = ptab[protocol].spktflg;
4593         if (ptab[protocol].spktlen > -1) {
4594             spsiz = ptab[protocol].spktlen;
4595             if (spsizf)
4596 	      spsizr = spmax = spsiz;
4597         }
4598         if (ptab[protocol].winsize > -1)
4599             wslotr = ptab[protocol].winsize;
4600         if (ptab[protocol].prefix > -1)
4601             prefixing = ptab[protocol].prefix;
4602         if (ptab[protocol].fnca > -1)
4603             fncact  = ptab[protocol].fnca;
4604         if (ptab[protocol].fncn > -1)
4605             fncnv   = ptab[protocol].fncn;
4606         if (ptab[protocol].fnsp > -1)
4607             fnspath = ptab[protocol].fnsp;
4608         if (ptab[protocol].fnrp > -1)
4609             fnrpath = ptab[protocol].fnrp;
4610     }
4611     debug(F101,"xsend protocol","",protocol);
4612 
4613     if (pv[SND_NOB].ival > -1) {	/* /NOBACKUP (skip backup file) */
4614 	g_skipbup = skipbup;
4615 	skipbup = 1;
4616     }
4617     if (pv[SND_REC].ival > 0)		/* /RECURSIVE */
4618       recursive = 2;
4619 
4620     if (pv[SND_TYP].ival > -1) {	/* /TYPE */
4621 	xfiletype = pv[SND_TYP].ival;
4622 	if (xfiletype == 2)
4623 	  xfiletype = -1;
4624     }
4625     g_binary = binary;			/* Save global transfer mode */
4626 #ifdef PATTERNS
4627     g_patterns = patterns;		/* Save FILE PATTERNS setting */
4628 #endif /* PATTERNS */
4629     if (pv[SND_BIN].ival > 0) {		/* Change according to switch */
4630 	/* If they said /BINARY they mean /BINARY */
4631 	patterns = 0;			/* So no pattern-based switching */
4632 	g_xfermode = xfermode;		/* or automatic transfer mode */
4633 	xfermode = XMODE_M;
4634 	binary = XYFT_B;
4635 	debug(F101,"doxsend /BINARY xfermode","",xfermode);
4636     } else if (pv[SND_TXT].ival > 0) {	/* Ditto for /TEXT */
4637 	patterns = 0;
4638 	g_xfermode = xfermode;
4639 	xfermode = XMODE_M;
4640 	binary = XYFT_T;
4641 	debug(F101,"doxsend /TEXT xfermode","",xfermode);
4642     } else if (pv[SND_IMG].ival > 0) {
4643 #ifdef VMS
4644 	binary = XYFT_I;
4645 #else
4646 	binary = XYFT_B;
4647 #endif /* VMS */
4648     }
4649 #ifdef CK_LABELED
4650     else if (pv[SND_LBL].ival > 0) {
4651 	binary = XYFT_L;
4652     }
4653 #endif /* CK_LABELED */
4654     debug(F101,"xsend binary","",binary);
4655 
4656     if (pv[SND_XPA].ival > 0)		/* /TRANSPARENT */
4657       xfrxla = 0;			/* Don't translate character sets */
4658 
4659     /* Check for legal combinations of switches, filenames, etc */
4660 
4661 #ifdef PIPESEND
4662     if (pv[SND_CMD].ival > 0) {	/* COMMAND - strip any braces */
4663 	debug(F110,"SEND /COMMAND before stripping",s,0);
4664 	s = brstrip(s);
4665 	debug(F110,"SEND /COMMAND after stripping",s,0);
4666 	if (!*s) {
4667 	    printf("?Sorry, a command to send from is required\n");
4668 	    x = -9;
4669 	    goto xsendx;
4670 	}
4671 	cmarg = s;
4672     }
4673 #endif /* PIPESEND */
4674 
4675 /* Set up /MOVE and /RENAME */
4676 
4677     if (pv[SND_DEL].ival > 0 &&
4678 	(pv[SND_MOV].ival > 0 || pv[SND_REN].ival > 0)) {
4679 	printf("?Sorry, /DELETE conflicts with /MOVE or /RENAME\n");
4680 	x = -9;
4681 	goto xsendx;
4682     }
4683 #ifdef CK_TMPDIR
4684     if (pv[SND_MOV].ival > 0) {
4685 	int len;
4686 	char * p = pv[SND_MOV].sval;
4687 #ifdef CK_LOGIN
4688 	if (isguest) {
4689 	    printf("?Sorry, /MOVE-TO not available to guests\n");
4690 	    x = -9;
4691 	    goto xsendx;
4692 	}
4693 #endif /* CK_LOGIN */
4694 	len = strlen(p);
4695 	if (!isdir(p)) {		/* Check directory */
4696 #ifdef CK_MKDIR
4697 	    char * s = NULL;
4698 	    s = (char *)malloc(len + 4);
4699 	    if (s) {
4700 		strcpy(s,p);		/* safe */
4701 #ifdef datageneral
4702 		if (s[len-1] != ':') { s[len++] = ':'; s[len] = NUL; }
4703 #else
4704 		if (s[len-1] != '/') { s[len++] = '/'; s[len] = NUL; }
4705 #endif /* datageneral */
4706 		s[len++] = 'X';
4707 		s[len] = NUL;
4708 		x = zmkdir(s);
4709 		free(s);
4710 		if (x < 0) {
4711 		    printf("?Can't create \"%s\"\n",p);
4712 		    x = -9;
4713 		    goto xsendx;
4714 		}
4715 	    }
4716 #else
4717 	    printf("?Directory \"%s\" not found\n",p);
4718 	    x = -9;
4719 	    goto xsendx;
4720 #endif /* CK_MKDIR */
4721 	}
4722         zfnqfp(p,LINBUFSIZ,tmpbuf);
4723 	makestr(&snd_move,tmpbuf);
4724     }
4725 #endif /* CK_TMPDIR */
4726 
4727     if (pv[SND_REN].ival > 0) {		/* /RENAME */
4728 	char * p = pv[SND_REN].sval;
4729 #ifdef CK_LOGIN
4730 	if (isguest) {
4731 	    printf("?Sorry, /RENAME-TO not available to guests\n");
4732 	    x = -9;
4733 	    goto xsendx;
4734 	}
4735 #endif /* CK_LOGIN */
4736 	if (!p) p = "";
4737 	if (!*p) {
4738 	    printf("?New name required for /RENAME\n");
4739 	    x = -9;
4740 	    goto xsendx;
4741 	}
4742 	p = brstrip(p);
4743 #ifndef NOSPL
4744     /* If name given is wild, rename string must contain variables */
4745 	if (wild) {
4746 	    char * s = tmpbuf;
4747 	    x = TMPBUFSIZ;
4748 	    zzstring(p,&s,&x);
4749 	    if (!strcmp(tmpbuf,p)) {
4750 		printf(
4751     "?/RENAME for file group must contain variables such as \\v(filename)\n"
4752 		       );
4753 		x = -9;
4754 		goto xsendx;
4755 	    }
4756 	}
4757 #endif /* NOSPL */
4758 	makestr(&snd_rename,p);
4759     }
4760 
4761 /* Handle /RECOVER and /START */
4762 
4763 #ifdef CK_RESEND
4764     if (pv[SND_RES].ival > 0 && binary != XYFT_B && !filepeek
4765 #ifdef PATTERNS
4766 	&& !patterns
4767 #else
4768 #ifdef VMS
4769 /* VMS sets text/binary automatically later when it opens the file */
4770 	&& 0
4771 #endif /* VMS */
4772 #endif /* PATTERNS */
4773 	) {
4774 	printf("?Sorry, /BINARY required\n");
4775 	x = -9;
4776 	goto xsendx;
4777     }
4778     if (pv[SND_STA].wval > 0) {		/* /START */
4779 	if (wild) {
4780 	    printf("?Sorry, wildcards not permitted with /START\n");
4781 	    x = -9;
4782 	    goto xsendx;
4783 	}
4784 	if (sizeof(int) < 4) {
4785 	    printf("?Sorry, this command needs at least 32-bit integers\n");
4786 	    x = -9;
4787 	    goto xsendx;
4788 	}
4789 #ifdef CK_XYZ
4790 	if (protocol != PROTO_K) {
4791 	    printf("?Sorry, SEND /START works only with Kermit protocol\n");
4792 	    x = -9;
4793 	    goto xsendx;
4794 	}
4795 #endif /* CK_XYZ */
4796     }
4797 #ifdef CK_XYZ
4798     if (pv[SND_RES].ival > 0) {
4799 	if (protocol != PROTO_K && protocol != PROTO_Z) {
4800 	    printf(
4801     "Sorry, /RECOVER is possible only with Kermit or ZMODEM protocol\n"
4802 		   );
4803 	    x = -9;
4804 	    goto xsendx;
4805 	}
4806     }
4807 #endif /* CK_XYZ */
4808 #endif /* CK_RESEND */
4809 
4810     if (protocol == PROTO_K) {
4811 	if ((pv[SND_MAI].ival > 0 ||	/* MAIL */
4812 	     pv[SND_PRI].ival > 0 ||	/* PRINT */
4813 	     pv[SND_RES].ival > 0	/* RESEND */
4814 	     ) &&
4815 	    (!atdiso || !atcapr)) {	/* Disposition attribute off? */
4816 	    printf("?Sorry, ATTRIBUTE DISPOSITION must be ON\n");
4817 	    x = -9;
4818 	    goto xsendx;
4819 	}
4820     }
4821 
4822 #ifdef CK_XYZ
4823     if (wild && (protocol == PROTO_X || protocol == PROTO_XC)) {
4824 	printf(
4825 "Sorry, you can only send one file at a time with XMODEM protocol\n"
4826 	       );
4827 	x = -9;
4828 	goto xsendx;
4829     }
4830 #endif /* CK_XYZ */
4831 
4832     if (!confirmed) {			/* CR not typed yet, get more fields */
4833 	char *m;
4834 	if (mlist) {			/* MSEND or MMOVE */
4835 	    nfils = 0;			/* We already have the first one */
4836 #ifndef NOMSEND
4837 	    msfiles[nfils++] = line;	/* Store pointer */
4838 	    lp = line + (int)strlen(line) + 1; /* Point past it */
4839 	    debug(F111,"xsend msend",msfiles[nfils-1],nfils-1);
4840 	    while (1) {			/* Get more filenames */
4841 		char *p;
4842 		if ((x = cmifi("Names of files to send, separated by spaces",
4843 			       "", &s,&y,xxstring)) < 0) {
4844 		    if (x != -3)
4845 		      goto xsendx;
4846 		    if ((x = cmcfm()) < 0)
4847 		      goto xsendx;
4848 		    break;
4849 		}
4850 		msfiles[nfils++] = lp;	/* Got one, count it, point to it, */
4851 		p = lp;			/* remember pointer, */
4852 		while ((*lp++ = *s++))	/* and copy it into buffer */
4853 		  if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
4854 		      printf("?MSEND list too long\n");
4855 		      line[0] = NUL;
4856 		      x = -9;
4857 		      goto xsendx;
4858 		  }
4859 		debug(F111,"xsend msend",msfiles[nfils-1],nfils-1);
4860 		if (nfils == 1) fspec[0] = NUL; /* Take care of \v(filespec) */
4861 #ifdef ZFNQFP
4862 		zfnqfp(p,TMPBUFSIZ,tmpbuf);
4863 		p = tmpbuf;
4864 #endif /* ZFNQFP */
4865 		if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
4866 		    strcat(fspec,p);	/* safe */
4867 		    strcat(fspec," ");	/* safe */
4868 		} else
4869 #ifdef COMMENT
4870 		  printf("WARNING - \\v(filespec) buffer overflow\n");
4871 #else
4872 		  debug(F101,"doxsend filespec buffer overflow","",0);
4873 #endif /* COMMENT */
4874 	    }
4875 #endif /* NOMSEND */
4876 	} else {			/* Regular SEND */
4877 	    char *p; int y;
4878 	    nfils = -1;
4879 	    if (pv[SND_MAI].ival > 0)
4880 	      m = (pv[SND_MAI].sval) ?
4881 		"e-mail address (optional)" :
4882 		  "e-mail address (required)";
4883 	    else if (pv[SND_PRI].ival > 0)
4884 	      m = "printer options (optional)";
4885 	    else if (wild)
4886 	      m =
4887 "\nOptional as-name template containing replacement variables \
4888 like \\v(filename)";
4889 	    else
4890 	      m = "Optional name to send it with";
4891 	    if ((x = cmtxt(m,"",&p,NULL)) < 0)
4892 	      goto xsendx;
4893 	    if (!p) p = "";
4894 	    if (*p) {			/* If some text was given... */
4895 		p = brstrip(p);		/* Replace /AS-NAME: value if any */
4896 		if ((y = strlen(p)) > 0) {
4897                     if (pv[SND_MAI].ival > 0) {
4898                         makestr(&pv[SND_MAI].sval, p);
4899                     } else {
4900 			if (pv[SND_ASN].sval) free(pv[SND_ASN].sval);
4901 			pv[SND_ASN].sval = malloc(y+1);
4902 			if (pv[SND_ASN].sval) {
4903 			    strcpy(pv[SND_ASN].sval,p);	/* safe */
4904 			    pv[SND_ASN].ival = 1;
4905 			}
4906 		    }
4907 		}
4908 	    }
4909 	}
4910     }
4911     /* Set cmarg2 from as-name, however we got it. */
4912 
4913     if (pv[SND_ASN].ival > 0 && pv[SND_ASN].sval && !*cmarg2) {
4914 	int x;
4915 	x = strlen(line);
4916 	ckstrncpy(line+x+2,pv[SND_ASN].sval,LINBUFSIZ-x-1);
4917 	cmarg2 = line+x+2;
4918 	debug(F110,"doxsend cmarg2",cmarg2,0);
4919     }
4920 
4921 #ifndef NOFRILLS
4922     if ((pv[SND_MAI].ival > 0) && (pv[SND_PRI].ival > 0)) {
4923 	printf("Sorry, /MAIL and /PRINT are conflicting options\n");
4924 	x = -9;
4925 	goto xsendx;
4926     }
4927     n = 0;				/* /MAIL or /PRINT? */
4928     if (pv[SND_MAI].ival > 0)
4929       n = SND_MAI;
4930     else if (pv[SND_PRI].ival > 0)
4931       n = SND_PRI;
4932     if (n) {				/* Yes... */
4933 #ifdef DEBUG
4934 	char * p;
4935 	if (n == SND_MAI)
4936 	  p = "/MAIL";
4937 	else
4938 	  p = "/PRINT";
4939 	debug(F111,"xsend",p,n);
4940 #endif /* DEBUG */
4941 #ifdef CK_XYZ
4942 	if (protocol != PROTO_K) {
4943 	    printf("Sorry, %s available only with Kermit protocol\n",
4944 		   (n == SND_MAI) ? "/MAIL" : "/PRINT"
4945 		   );
4946 	    x = -9;
4947 	    goto xsendx;
4948 	}
4949 #endif /* CK_XYZ */
4950 	debug(F101,"xsend print/mail wild","",wild);
4951 	*optbuf = NUL;			/* Wipe out any old options */
4952 	s = pv[n].sval;			/* mail address or print switch val */
4953 	if (!s) s = "";
4954 	debug(F110,"doxsend mail address or printer options",s,0);
4955 	if (n == SND_MAI && !*s) {
4956 	    printf("?E-mail address required\n");
4957 	    x = -9;
4958 	    goto xsendx;
4959 	} else if ((int)strlen(s) > 94) { /* Ensure legal size */
4960 	    printf("?%s too long\n",
4961 		   (n == SND_MAI) ?
4962 		   "E-mail address" :
4963 		   "Print option string"
4964 		   );
4965 	    x = -9;
4966 	    goto xsendx;
4967 	}
4968 	ckstrncpy(optbuf,s,OPTBUFLEN);	/* OK, copy to option buffer */
4969 	cmarg = line;			/* File to send */
4970 	if (n == SND_MAI) {
4971 	    debug(F110,"xsend mailing",cmarg,0);
4972 	    debug(F110,"xsend address:",optbuf,0);
4973 	    rmailf = 1;
4974 	} else {
4975 	    debug(F110,"xsend printing",cmarg,0);
4976 	    debug(F110,"xsend options",optbuf,0);
4977 	    rprintf = 1;
4978 	}
4979     }
4980 #endif /* NOFRILLS */
4981 
4982 #ifdef CALIBRATE
4983     if (pv[SND_CAL].wval > 0) {		/* Handle /CALIBRATE */
4984 	if (confirmed) {
4985 	    calibrate = pv[SND_CAL].wval * (CK_OFF_T)1024;
4986 	    sndsrc = -9;
4987 	    nfils = 1;
4988 	    wild = 0;
4989 #ifndef NOMSEND
4990 	    addlist = 0;
4991 #endif /* NOMSEND */
4992 	    ckstrncpy(line,"CALIBRATION",LINBUFSIZ);
4993 	    s = cmarg = line;
4994 	    if (!cmarg2) cmarg2 = "";
4995 	    debug(F110,"doxsend cmarg2 calibrate",cmarg2,0);
4996 	} else if (line[0]) {
4997 	    calibrate = 0;
4998 	    pv[SND_CAL].ival = 0;
4999 	    pv[SND_CAL].wval = 0;
5000 	}
5001     }
5002 #endif /* CALIBRATE */
5003 
5004     if (pv[SND_FIL].ival > 0) {
5005 	if (confirmed && !calibrate) {
5006 	    if (zopeni(ZMFILE,pv[SND_FIL].sval) < 1) {
5007 		debug(F110,"xsend can't open",pv[SND_FIL].sval,0);
5008 		printf("?Failure to open %s\n",filefile);
5009 		x = -9;
5010 		goto xsendx;
5011 	    }
5012 	    makestr(&filefile,pv[SND_FIL].sval); /* Open, remember name */
5013 	    debug(F110,"xsend opened",filefile,0);
5014 	    wild = 1;
5015 	}
5016     }
5017 
5018     /* SEND alone... */
5019 
5020 #ifndef NOSPL
5021     if (confirmed && pv[SND_ARR].ival > 0) {
5022 	if (!*cmarg2) {
5023 	    sndxnam[7] = (char)((arrayx == 1) ? 64 : arrayx + ARRAYBASE);
5024 	    cmarg2 = sndxnam;
5025 	}
5026 	cmarg = "";
5027 	goto sendend;
5028     }
5029 #endif /* NOSPL */
5030 
5031     if (confirmed && !line[0] && !filefile && !calibrate) {
5032 #ifndef NOMSEND
5033 	if (filehead) {			/* OK if we have a SEND-LIST */
5034 	    nfils = filesinlist;
5035 	    sndsrc = nfils;		/* Like MSEND */
5036 	    addlist = 1;		/* But using a different list... */
5037 	    filenext = filehead;
5038 	    goto sendend;
5039 	}
5040 #endif /* NOMSEND */
5041 	printf("?Filename required but not given\n");
5042 	x = -9;
5043 	goto xsendx;
5044     }
5045 
5046     /* Not send-list or array */
5047 
5048 #ifndef NOMSEND
5049     addlist = 0;			/* Don't use SEND-LIST. */
5050     filenext = NULL;
5051 #endif /* NOMSEND */
5052 
5053     if (mlist) {			/* MSEND or MMOVE */
5054 #ifndef NOMSEND
5055 	cmlist = msfiles;		/* List of files to send */
5056 	sndsrc = nfils;
5057 	cmarg2 = "";
5058 	sendstart = (CK_OFF_T)0;
5059 #endif /* NOMSEND */
5060 #ifdef PIPESEND
5061 	pipesend = 0;
5062 #endif /* PIPESEND */
5063     } else if (filefile) {		/* File contains list of filenames */
5064 	s = "";
5065 	cmarg = "";
5066 	cmarg2 = "";
5067 	line[0] = NUL;
5068 	nfils = 1;
5069 	sndsrc = 1;
5070 
5071     } else if (!calibrate && pv[SND_ARR].ival < 1 && pv[SND_CMD].ival < 1) {
5072 
5073 	nfils = sndsrc = -1;	/* Not MSEND, MMOVE, /LIST, or /ARRAY */
5074 	if (				/* or /COMMAND */
5075 
5076 #ifndef NOFRILLS
5077 	    !rmailf && !rprintf		/* Not MAIL or PRINT */
5078 #else
5079 	    1
5080 #endif /* NOFRILLS */
5081 	    ) {
5082 	    CK_OFF_T y = (CK_OFF_T)1;
5083 	    if (!wild)
5084 	      y = zchki(s);
5085 	    if (y < (CK_OFF_T)0) {
5086 		printf("?Read access denied - \"%s\"\n", s);
5087 		x = -9;
5088 		goto xsendx;
5089 	    }
5090 	    if (s != line)		/* We might already have done this. */
5091 	      ckstrncpy(line,s,LINBUFSIZ); /* Copy of string just parsed. */
5092 	    else
5093 	      debug(F110,"doxsend line=s",line,0);
5094 	    cmarg = line;		/* File to send */
5095 	}
5096 	zfnqfp(cmarg,fspeclen,fspec);
5097     }
5098     if (!mlist) {			/* For all but MSEND... */
5099 #ifdef PIPESEND
5100 	if (pv[SND_CMD].ival > 0)	/* /COMMAND sets pipesend flag */
5101 	  pipesend = 1;
5102 	debug(F101,"xsend /COMMAND pipesend","",pipesend);
5103 	if (pipesend && filefile) {
5104 	    printf("?Invalid switch combination\n");
5105 	    x = -9;
5106 	    goto xsendx;
5107 	}
5108 #endif /* PIPESEND */
5109 
5110 #ifndef NOSPL
5111     /* If as-name given and filespec is wild, as-name must contain variables */
5112 	debug(F111,"doxsend cmarg2 wild",cmarg2,wild);
5113 	if (wild && *cmarg2) {
5114 	    char * s = tmpbuf;
5115 	    x = TMPBUFSIZ;
5116 	    zzstring(cmarg2,&s,&x);
5117 	    if (!strcmp(tmpbuf,cmarg2)) {
5118 		printf(
5119     "?As-name for file group must contain variables such as \\v(filename)\n"
5120 		       );
5121 		x = -9;
5122 		goto xsendx;
5123 	    }
5124 	}
5125 #endif /* NOSPL */
5126 
5127     /* Strip braces from as-name */
5128 	debug(F110,"xsend cmarg2 before stripping",cmarg2,0);
5129 	cmarg2 = brstrip(cmarg2);
5130 	debug(F110,"xsend filename",cmarg,0);
5131 	debug(F110,"xsend as-name",cmarg2,0);
5132 
5133     /* Copy as-name to a safe place */
5134 
5135 	if (asnbuf) {
5136 	    free(asnbuf);
5137 	    asnbuf = NULL;
5138 	}
5139 	if ((y = strlen(cmarg2)) > 0) {
5140 	    asnbuf = (char *) malloc(y + 1);
5141 	    if (asnbuf) {
5142 		strcpy(asnbuf,cmarg2);	/* safe */
5143 		cmarg2 = asnbuf;
5144 	    } else cmarg2 = "";
5145 	}
5146 
5147 #ifdef CK_RESEND
5148 	debug(F111,"xsend pv[SND_STA].ival","",pv[SND_STA].ival);
5149 	if (pv[SND_STA].wval > (CK_OFF_T)-1) { /* /START position */
5150 	    if (wild) {
5151 		printf("?/STARTING-AT may not be used with multiple files.\n");
5152 		x = -9;
5153 		goto xsendx;
5154 	    } else
5155 	      sendstart = pv[SND_STA].wval;
5156 	} else
5157 	  sendstart = (CK_OFF_T)0;
5158 	debug(F101,"xsend /STARTING","",sendstart);
5159 #endif /* CK_RESEND */
5160     }
5161 
5162 sendend:				/* Common successful exit */
5163     moving = 0;
5164     if (pv[SND_SHH].ival > 0) {		/* SEND /QUIET... */
5165 	g_displa = fdispla;
5166 	fdispla = 0;
5167 	debug(F101,"xsend display","",fdispla);
5168     }
5169 
5170 #ifndef NOSPL				/* SEND /ARRAY... */
5171     if (pv[SND_ARR].ival > 0) {
5172 	if (!ap) { x = -2; goto xsendx; } /* (shouldn't happen) */
5173 	if (range[0] == -1)		/* If low end of range not specified */
5174 	  range[0] = 1;			/* default to 1 */
5175 	if (range[1] == -1)		/* If high not specified */
5176 	  range[1] = a_dim[arrayx];	/* default to size of array */
5177 	if ((range[0] < 0) ||		/* Check range */
5178 	    (range[0] > a_dim[arrayx]) ||
5179 	    (range[1] < range[0]) ||
5180 	    (range[1] > a_dim[arrayx])) {
5181 	    printf("?Bad array range - [%d:%d]\n",range[0],range[1]);
5182 	    x = -9;
5183 	    goto xsendx;
5184 	}
5185 	sndarray = ap;			/* Array pointer */
5186 	sndxin = arrayx;		/* Array index */
5187 	sndxlo = range[0];		/* Array range */
5188 	sndxhi = range[1];
5189 	sndxnam[7] = (char)((sndxin == 1) ? 64 : sndxin + ARRAYBASE);
5190 
5191 #ifdef COMMENT
5192 	printf("SENDING FROM ARRAY: &%c[]...\n", /* debugging */
5193 	       (sndxin == 1) ? 64 : sndxin + ARRAYBASE);
5194 	printf("Lo=%d\nHi=%d\n", sndxlo, sndxhi);
5195 	printf("cmarg=[%s]\ncmarg2=[%s]\n", cmarg, cmarg2);
5196 	while ((x = agnbyte()) > -1) {
5197 	    putchar((char)x);
5198 	}
5199 	return(1);
5200 #endif /* COMMENT */
5201     }
5202 #endif /* NOSPL */
5203 
5204     if (pv[SND_ARR].ival < 1) {		/* File selection & disposition... */
5205 
5206 	if (pv[SND_DEL].ival > 0)	/* /DELETE was specified */
5207 	  moving = 1;
5208 	debug(F101,"xsend /DELETE","",moving);
5209 	if (pv[SND_AFT].ival > 0)	/* Copy SEND criteria */
5210 	  ckstrncpy(sndafter,pv[SND_AFT].sval,19);
5211 	if (pv[SND_BEF].ival > 0)
5212 	  ckstrncpy(sndbefore,pv[SND_BEF].sval,19);
5213 	if (pv[SND_NAF].ival > 0)
5214 	  ckstrncpy(sndnafter,pv[SND_NAF].sval,19);
5215 	if (pv[SND_NBE].ival > 0)
5216 	  ckstrncpy(sndnbefore,pv[SND_NBE].sval,19);
5217 	if (pv[SND_EXC].ival > 0)
5218 	  makelist(pv[SND_EXC].sval,sndexcept,NSNDEXCEPT);
5219 	if (pv[SND_SMA].wval > (CK_OFF_T)-1)
5220 	  sndsmaller = pv[SND_SMA].wval;
5221 	if (pv[SND_LAR].wval > (CK_OFF_T)-1)
5222 	  sndlarger = pv[SND_LAR].wval;
5223 	if (pv[SND_NAM].ival > -1) {
5224 	    g_fncnv = fncnv;		/* Save global value */
5225 	    fncnv = pv[SND_NAM].ival;
5226 	    debug(F101,"xsend fncnv","",fncnv);
5227 	}
5228 	if (pv[SND_PTH].ival > -1) {
5229 	    g_spath = fnspath;		/* Save global values */
5230 	    fnspath = pv[SND_PTH].ival;
5231 #ifndef NZLTOR
5232 	    if (fnspath != PATH_OFF) {
5233 		g_fncnv = fncnv;	/* Bad bad... */
5234 		fncnv = XYFN_C;
5235 	    }
5236 #endif /* NZLTOR */
5237 	    debug(F101,"xsend fnspath","",fnspath);
5238 	    debug(F101,"xsend fncnv","",fncnv);
5239 	}
5240     }
5241 
5242 #ifdef PIPESEND
5243     if (pv[SND_FLT].ival > 0) {
5244 	makestr(&sndfilter,pv[SND_FLT].sval);
5245 	debug(F110,"xsend /FILTER", sndfilter, 0);
5246     }
5247 #endif /* PIPESEND */
5248 
5249 #ifdef CK_APC
5250 /* MOVE not allowed in APCs */
5251     if (moving &&
5252 	(apcactive == APC_LOCAL || apcactive == APC_REMOTE)
5253 	&& !(apcstatus & APC_UNCH))
5254       return(success = 0);
5255 #endif /* CK_APC */
5256 #ifdef IKS_OPTION
5257     if (
5258 #ifdef CK_XYZ
5259         protocol == PROTO_K &&
5260 #endif /* CK_XYZ */
5261         !iks_wait(KERMIT_REQ_START,1)) {
5262         printf("?A Kermit Server is not available to process this command.\n");
5263         printf("?Start a RECEIVE command to complement this command.\n");
5264     }
5265 #endif /* IKS_OPTION */
5266 
5267 #ifdef IKSD
5268 #ifdef CK_LOGIN
5269     if (moving && inserver && isguest) {
5270         printf("?File deletion not allowed for guests.\n");
5271 	return(-9);
5272     }
5273 #endif /* CK_LOGIN */
5274 #endif /* IKSD */
5275 
5276     sstate = 's';			/* Set start state to SEND */
5277     sndcmd = 1;
5278 #ifdef CK_RESEND
5279     if (pv[SND_RES].ival > 0)		/* Send sendmode appropriately */
5280       sendmode = SM_RESEND;
5281     else if (pv[SND_STA].ival > 0)
5282       sendmode = SM_PSEND;
5283     else
5284 #endif /* CK_RESEND */
5285     if (mlist)
5286       sendmode = SM_MSEND;
5287     else
5288       sendmode = SM_SEND;
5289 #ifdef MAC
5290     what = W_SEND;
5291     scrcreate();
5292 #endif /* MAC */
5293     if (local && pv[SND_SHH].ival != 0) { /* If in local mode, */
5294 	displa = 1;			/* turn on file transfer display */
5295     }
5296     x = 0;
5297 
5298   xsendx:				/* Common exit, including failure */
5299     debug(F101,"doxsend sndsrc","",sndsrc);
5300     for (i = 0; i <= SND_MAX; i++) {	/* Free malloc'd memory */
5301 	if (pv[i].sval)
5302 	  free(pv[i].sval);
5303     }
5304     return(x);
5305 }
5306 #endif /* NOXFER */
5307 
5308 #ifndef NOLOCAL
5309 /*  D O X C O N N  --  CONNECT command parsing with switches */
5310 
5311 #ifdef XLIMITS
5312 #define XLIMORTRIGGER
5313 #else
5314 #ifdef CK_TRIGGER
5315 #define XLIMORTRIGGER
5316 #endif /* CK_TRIGGER */
5317 #endif /*  XLIMITS */
5318 
5319 #ifdef CKTIDLE
5320 int tt_idlelimit = 0;			/* Terminal idle limit */
5321 int tt_idleact = IDLE_RET;		/* Terminal idle action */
5322 #endif /* CKTIDLE */
5323 
5324 #ifdef OS2				/* K95 only: */
5325 extern int
5326   tt_idlesnd_tmo;			/*   Idle interval */
5327 int tt_timelimit = 0;			/*   Time limit, 0 = none */
5328 extern char *				/* Parse results - strings: */
5329   tt_idlesnd_str;			/*   Idle string */
5330 #endif /* OS2 */
5331 
5332 #ifdef CK_TRIGGER
5333 extern char *tt_trigger[];
5334 extern CHAR *tt_trmatch[];
5335 extern char *triggerval;
5336 static char *g_tt_trigger[TRIGGERS];
5337 #endif /* CK_TRIGGER */
5338 
5339 #ifdef OS2
5340 static int g_tt_idlesnd_tmo, g_tt_timelimit; /* For saving and restoring */
5341 static int g_tt_idlelimit, g_tt_saved = 0;
5342 static char * g_tt_idlesnd_str;		/* global settings */
5343 #endif /* OS2 */
5344 
5345 static struct stringint pv[CONN_MAX+1];
5346 
5347 VOID
resconn()5348 resconn() {
5349     int i;
5350 
5351 #ifdef OS2
5352     if ( g_tt_saved ) {
5353         tt_idlelimit   = g_tt_idlelimit;
5354         tt_idlesnd_tmo = g_tt_idlesnd_tmo;
5355         tt_timelimit   = g_tt_timelimit;
5356         tt_idlesnd_str = g_tt_idlesnd_str;
5357         g_tt_saved = 0;
5358     }
5359 #endif /* OS2 */
5360 
5361 #ifdef CK_TRIGGER
5362     for (i = 0; i < TRIGGERS; i++)
5363       tt_trigger[i] = g_tt_trigger[i];
5364 #endif /* CK_TRIGGER */
5365 
5366     for (i = 0; i <= CONN_MAX; i++) {	/* Free malloc'd memory */
5367 	if (pv[i].sval)
5368 	  free(pv[i].sval);
5369         pv[i].sval = NULL;
5370     }
5371 }
5372 
5373 int
doxconn(cx)5374 doxconn(cx) int cx; {
5375     int c, i, n;			/* Workers */
5376     int x, y;
5377     int getval = 0;			/* Whether to get switch value */
5378     int async = 0;                      /* Make an async connect */
5379     struct FDB sw, cm;			/* FDBs for each parse function */
5380     extern FILE * tfile[];
5381     extern char * macp[];
5382 
5383 #ifdef OS2
5384     g_tt_idlesnd_tmo = tt_idlesnd_tmo;	/* Save global settings */
5385     g_tt_timelimit   = tt_timelimit;
5386     g_tt_idlelimit   = tt_idlelimit;
5387     g_tt_idlesnd_str = tt_idlesnd_str;
5388     g_tt_saved = 1;
5389 #endif /* OS2 */
5390 
5391 #ifdef CK_TRIGGER
5392     if (!tt_trigger[0]) {		/* First initialization */
5393 	for (i = 1; i < TRIGGERS; i++)
5394 	  tt_trigger[i] = NULL;
5395     }
5396     for (i = 0; i < TRIGGERS; i++)
5397       g_tt_trigger[i] = tt_trigger[i];
5398     if (triggerval) {
5399 	free(triggerval);
5400 	triggerval = NULL;
5401     }
5402 #endif /* CK_TRIGGER */
5403 
5404     for (i = 0; i <= CONN_MAX; i++) {	/* Initialize switch values */
5405 	pv[i].sval = NULL;		/* to null pointers */
5406 	pv[i].ival = -1;		/* and -1 int values */
5407 	pv[i].wval = (CK_OFF_T)-1;
5408     }
5409     if (cx == XXCQ)			/* CQ == CONNECT /QUIETLY */
5410       pv[CONN_NV].ival = 1;
5411 
5412     /* Set up chained parse functions... */
5413 
5414     cmfdbi(&sw,				/* First FDB - command switches */
5415 	   _CMKEY,			/* fcode */
5416 	   "Switch",			/* hlpmsg */
5417 	   "",				/* default */
5418 	   "",				/* addtl string data */
5419 	   nconntab,			/* addtl numeric data 1: tbl size */
5420 	   4,				/* addtl numeric data 2: 4 = cmswi */
5421 	   xxstring,			/* Processing function */
5422 	   conntab,			/* Keyword table */
5423 	   &cm				/* Pointer to next FDB */
5424 	   );
5425     cmfdbi(&cm,				/* 2nd FDB - Confirmation */
5426 	   _CMCFM,			/* fcode */
5427 	   "",				/* hlpmsg */
5428 	   "",				/* default */
5429 	   "",				/* addtl string data */
5430 	   0,				/* addtl numeric data 1 */
5431 	   0,				/* addtl numeric data 2 */
5432 	   NULL,
5433 	   NULL,
5434 	   NULL
5435 	   );
5436 
5437     while (1) {				/* Parse 0 or more switches */
5438 	x = cmfdb(&sw);			/* Parse switch or confirmation */
5439 	debug(F101,"doxconn cmfdb","",x);
5440 	if (x < 0) {			/* Error */
5441 	    if (x == -9 || x == -2)
5442 	      printf("?No switches match - \"%s\"\n",atmbuf);
5443 	    goto xconnx;		/* or reparse needed */
5444 	}
5445 	if (cmresult.fcode != _CMKEY)	/* Break out if not a switch */
5446 	  break;
5447 	c = cmgbrk();			/* Get break character */
5448 	getval = (c == ':' || c == '='); /* to see how they ended the switch */
5449 	if (getval && !(cmresult.kflags & CM_ARG)) {
5450 	    printf("?This switch does not take arguments\n");
5451 	    x = -9;
5452 	    goto xconnx;
5453 	}
5454 	if (!getval && (cmgkwflgs() & CM_ARG)) {
5455 	    printf("?This switch requires an argument\n");
5456 	    return(-9);
5457 	}
5458 	n = cmresult.nresult;		/* Numeric result = switch value */
5459 	debug(F101,"doxconn switch","",n);
5460 
5461 	switch (n) {			/* Process the switch */
5462 #ifdef OS2
5463 	  case CONN_AS:			/* Asynchronous */
5464             pv[CONN_AS].ival = 1;
5465             pv[CONN_SY].ival = 0;
5466             break;
5467           case CONN_SY:                 /* Synchronous */
5468             pv[CONN_SY].ival = 1;
5469             pv[CONN_AS].ival = 0;
5470             break;
5471 #endif /* OS2 */
5472 	  case CONN_NV:			/* Non-verbal */
5473 	    pv[n].ival = 1;
5474 	    break;
5475 #ifdef XLIMITS
5476 	  case CONN_II:			/* Idle-interval */
5477 	  case CONN_IL:			/* Idle-limit */
5478 	  case CONN_TL:			/* Time-limit */
5479 	    if (!getval) break;
5480 	    if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
5481 	      goto xconnx;
5482 	    pv[n].ival = y;
5483 	    break;
5484 	  case CONN_IS:			/* Idle-string */
5485 #endif /* XLIMITS */
5486 #ifdef CK_TRIGGER
5487 	  case CONN_TS:			/* Trigger-string */
5488 #endif /* CK_TRIGGER */
5489 #ifdef XLIMORTRIGGER
5490 	    if (!getval) break;
5491 	    if ((x = cmfld("String (enclose in braces if it contains spaces)",
5492 			   "",&s,xxstring)) < 0) {
5493 		if (x == -3) {
5494 		    printf("?String required\n");
5495 		    x = -9;
5496 		}
5497 		goto xconnx;
5498 	    }
5499 	    if (n != CONN_TS)
5500 	      s = brstrip(s);
5501 	    if ((y = strlen(s)) > 0) {
5502 		if (pv[n].sval) free(pv[n].sval);
5503 		pv[n].sval = malloc(y+1);
5504 		if (pv[n].sval) {
5505 		    strcpy(pv[n].sval,s); /* safe */
5506 		    pv[n].ival = 1;
5507 		}
5508 	    }
5509 	    break;
5510 #endif /* XLIMORTRIGGER */
5511 	  default:
5512 	    printf("?Unexpected switch value - %d\n",cmresult.nresult);
5513 	    x = -9;
5514 	    goto xconnx;
5515 	}
5516     }
5517     debug(F101,"doxconn cmresult.fcode","",cmresult.fcode);
5518     if (cmresult.fcode != _CMCFM) {
5519 	printf("?Unexpected function code: %d\n",cmresult.fcode);
5520 	x = -9;
5521 	goto xconnx;
5522     }
5523 
5524     /* Command was confirmed so we can pre-pop command level. */
5525     /* This is so CONNECT module won't think we're executing a script */
5526     /* if CONNECT was the final command in the script. */
5527 
5528     if (cmdlvl > 0)
5529       prepop();
5530 
5531 #ifdef OS2				/* Make results available globally */
5532     if (pv[CONN_IL].ival > -1)		/* Idle limit */
5533       tt_idlelimit = pv[CONN_IL].ival;
5534     if (pv[CONN_II].ival > -1)		/* Idle limit */
5535       tt_idlesnd_tmo = pv[CONN_II].ival;
5536     if (pv[CONN_IS].sval)		/* Idle string */
5537       if (tt_idlesnd_str = (char *)malloc((int)strlen(pv[CONN_IS].sval)+1))
5538 	strcpy(tt_idlesnd_str,pv[CONN_IS].sval); /* safe */
5539     if (pv[CONN_TL].ival > -1)		/* Session limit */
5540       tt_timelimit = pv[CONN_TL].ival;
5541     async = (pv[CONN_AS].ival > 0 ||
5542              pv[CONN_SY].ival <= 0 && cmdlvl == 0) ? 1 : 0;
5543 #endif /* OS2 */
5544 
5545 #ifdef CK_TRIGGER
5546     if (pv[CONN_TS].sval)		/* Trigger strings */
5547       makelist(pv[CONN_TS].sval,tt_trigger,TRIGGERS);
5548     for (i = 0; i < TRIGGERS; i++)	/* Trigger match pointers */
5549       tt_trmatch[i] = NULL;
5550     if (triggerval) {			/* Reset trigger value */
5551 	free(triggerval);
5552 	triggerval = NULL;
5553     }
5554 #endif /* CK_TRIGGER */
5555 
5556 #ifdef SSHCMD
5557 /*
5558   2010/03/01...
5559   The previous connection was through the external ssh client and now, with
5560   that connection closed, the user says "connect" and expects a new connection
5561   to be made to the same host, because that's how all the other connection
5562   methods work, so (and this is quite a hack)...
5563 */
5564     if (!ckstrcmp("ssh ",ttname,4,0)) {	/* Previous "host" was "ssh blah" */
5565 	_PROTOTYP (int redossh, ( void ) );
5566 	extern int ttyfd;
5567 	if (ttyfd < 0) {		/* And connection is no longer open */
5568 	    int xx;
5569 	    xx = redossh();		/* So redo the SSH connection */
5570 	    if (xx < 0) return(xx);
5571 	    goto xconnx;
5572 	}
5573     }
5574 #endif	/* SSHCMD */
5575     x = doconect((pv[CONN_NV].ival > 0) ? 1 : 0, async);
5576     {
5577 	int xx;
5578 	debug(F101,"doxconn doconect returns","",x);
5579 	if ((xx = ttchk()) < 0) dologend();
5580 	debug(F101,"doxconn ttchk returns","",xx);
5581     }
5582 
5583 #ifdef CK_TRIGGER
5584     debug(F111,"doxconn doconect triggerval",triggerval,x);
5585 #endif /* CK_TRIGGER */
5586 
5587   xconnx:
5588     /* Back from CONNECT -- Restore global settings */
5589 
5590     if (!async)
5591       resconn();
5592 
5593     success = (x > 0) ? 1 : 0;
5594     return(x);
5595 }
5596 #endif /* NOLOCAL */
5597 
5598 #ifdef ADDCMD
5599 /* cx == XXADD or XXREMV */
5600 /* fc == ADD_BIN or ADD_TXT */
5601 static int
doadd(cx,fc)5602 doadd(cx,fc) int cx, fc; {
5603 #ifdef PATTERNS
5604     char * tmp[FTPATTERNS];
5605     char **p = NULL;
5606     int i, j, k, n = 0, x = 0, last;
5607 
5608 #endif /* PATTERNS */
5609     if (cx != XXADD && cx != XXREMV) {
5610 	printf("?Unexpected function code: %d\n",cx);
5611 	return(-9);
5612     }
5613 #ifdef PATTERNS
5614     while (n < FTPATTERNS) {		/* Collect new patterns */
5615 	tmp[n] = NULL;
5616 	if ((x = cmfld("Pattern","",&s,xxstring)) < 0)
5617 	  break;
5618 	ckstrncpy(line,s,LINBUFSIZ);
5619 	s = brstrip(line);
5620 	makestr(&(tmp[n++]),s);
5621     }
5622     if (x == -3)
5623       x = cmcfm();
5624     if (x < 0)
5625       goto xdoadd;
5626     p = (fc == ADD_BIN) ? binpatterns : txtpatterns; /* Which list */
5627     last = 0;
5628     for (i = 0; i < FTPATTERNS; i++) { /* Find last one in list */
5629 	if (!p[i]) {
5630 	    last = i;
5631 	    break;
5632 	}
5633     }
5634     if (cx == XXADD) {			/* Adding */
5635 	if (last + n > FTPATTERNS) {	/* Check if too many */
5636 	    printf("?Too many patterns - %d is the maximum\n", FTPATTERNS);
5637 	    goto xdoadd;
5638 	}
5639         for (i = 0; i < n; i++) {        /* Copy in the new ones. */
5640           for (j = 0, x = 0; x == 0 && j < last ; j++ )
5641             x = !ckstrcmp(tmp[i],p[j],-1,filecase); /* match */
5642           if (x == 0)
5643             makestr(&(p[last++]),tmp[i]);
5644         }
5645         makestr(&(p[last]),NULL);	/* Null-terminate the list */
5646         x = 1;
5647         goto xdoadd;                    /* Done */
5648     } else if (cx == XXREMV) {		/* Remove something(s) */
5649 	int j, k;
5650 	if (last == 0)			        /* List is empty */
5651 	  goto xdoadd;			        /* Nothing to remove */
5652 	for (i = 0; i < n; i++) {	        /* i = Patterns they typed */
5653 	    for (j = 0; j < last; j++) {        /* j = Patterns in list */
5654 		/* Change this to ckstrcmp()... */
5655 		if (filecase)
5656                   x = !ckstrcmp(tmp[i],p[j],-1,filecase); /* match */
5657 		else
5658 		  x = ckstrcmp(tmp[i],p[j],-1,0); /* Case-independent match */
5659 		if (x) {	    	        /* This one matches */
5660 		    makestr(&(p[j]),NULL);      /* Free it */
5661 		    for (k = j; k < last; k++)  /* Move the rest up */
5662 		      p[k] = p[k+1];
5663 		    p[k] = NULL;	        /* Erase last one */
5664 		    if (!p[k])
5665 		      break;
5666 		}
5667 	    }
5668 	}
5669     }
5670   xdoadd:				/* Common exit */
5671     for (i = 0; i < n; i++)
5672       if (tmp[i])
5673 	free(tmp[i]);
5674     return(x);
5675 #endif /* PATTERNS */
5676 }
5677 
5678 /* ADD SEND-LIST */
5679 
5680 static int
addsend(cx)5681 addsend(cx) int cx; {
5682 #ifndef NOMSEND
5683     extern struct keytab fttab[];
5684     extern int nfttyp;
5685     struct filelist * flp;
5686     char * fmode = "";
5687     int xmode = 0;
5688     int xbinary = 0;
5689 #endif /* NOMSEND */
5690 
5691 #ifdef NOMSEND
5692     printf("?Sorry, ADD/REMOVE SEND-LIST not available.\n");
5693     return(-9);
5694 #endif /* NOMSEND */
5695     if (cx == XXREMV) {
5696 	printf("?Sorry, REMOVE SEND-LIST not implemented yet.\n");
5697 	return(-9);
5698     }
5699 #ifndef NOMSEND
5700 #ifndef XYZ_INTERNAL
5701     if (protocol != PROTO_K) {
5702        printf("?Sorry, ADD SEND-LIST does not work with external protocols\n");
5703        return(-9);
5704     }
5705 #endif /* XYZ_INTERNAL */
5706 
5707     x = cmifi("File specification to add","", &s,&y,xxstring);
5708     if (x < 0) {
5709 	if (x == -3) {
5710 	    printf("?A file specification is required\n");
5711 	    return(-9);
5712 	} else
5713 	  return(x);
5714     }
5715     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
5716     s = tmpbuf;
5717     if (filesinlist == 0)		/* Take care of \v(filespec) */
5718       fspec[0] = NUL;
5719     zfnqfp(s,LINBUFSIZ,line);
5720     s = line;
5721     if (((int)strlen(fspec) + (int)strlen(s) + 1) < fspeclen) {
5722 	strcat(fspec,s);		/* safe */
5723 	strcat(fspec," ");		/* safe */
5724     } else
5725       printf("WARNING - \\v(filespec) buffer overflow\n");
5726 
5727 
5728     xbinary = binary;
5729     if ((patterns || filepeek)		/* FILE PATTERNS or SCAN is ON */
5730 #ifdef CK_LABELED
5731 	&& binary != XYFT_L		/* And not if FILE TYPE LABELED */
5732 #endif /* CK_LABELED */
5733 #ifdef VMS
5734 	&& binary != XYFT_I		/* or FILE TYPE IMAGE */
5735 #endif /* VMS */
5736 	) {
5737 	int k, x;
5738 	x = -1;
5739 	k = scanfile(line,&x,nscanfile);
5740 	if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
5741     }
5742     fmode = gfmode(xbinary,0);
5743     if ((x = cmkey(fttab,nfttyp,
5744 		   "type of file transfer", fmode, xxstring)) < 0)
5745       return(x);
5746     xmode = x;
5747 
5748     cmarg2 = "";
5749     if ((x = cmfld(y ?
5750   "\nAs-name template containing replacement variables such as \\v(filename)" :
5751   "Name to send it with", "",&s,NULL)) < 0)
5752       if (x != -3)
5753 	return(x);
5754 #ifndef NOSPL
5755     if (y && *s) {
5756 	char * p = tmpbuf;
5757 	x = TMPBUFSIZ;
5758 	zzstring(s,&p,&x);
5759 	if (!strcmp(tmpbuf,s)) {
5760 	    printf(
5761   "?As-name for file group must contain variables such as \\v(filename)\n"
5762 		   );
5763 	    return(-9);
5764 	}
5765     }
5766 #endif /* NOSPL */
5767     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
5768     cmarg2 = tmpbuf;
5769 
5770     if ((x = cmcfm()) < 0)
5771       return(x);
5772     flp = (struct filelist *) malloc(sizeof(struct filelist));
5773     if (flp) {
5774 	if (filetail)
5775 	  filetail->fl_next = flp;
5776 	filetail = flp;
5777 	if (!filehead)
5778 	  filehead = flp;
5779 	x = (int) strlen(line);	/* Length of filename */
5780 	s = (char *) malloc(x + 1);
5781 	if (s) {
5782 	    strcpy(s,line);		/* safe */
5783 	    flp->fl_name = s;
5784 	    flp->fl_mode = xmode;
5785 	    x = (int) strlen(cmarg2);	/* Length of as-name */
5786 	    if (x < 1) {
5787 		flp->fl_alias = NULL;
5788 	    } else {
5789 		s = (char *) malloc(x + 1);
5790 		if (s) {
5791 		    strcpy(s,cmarg2);	/* safe */
5792 		    flp->fl_alias = s;
5793 		} else {
5794 		    printf("Sorry, can't allocate space for as-name");
5795 		    return(-9);
5796 		}
5797 	    }
5798 	    flp->fl_next = NULL;
5799 	    filesinlist++;		/* Count this node */
5800 	    return(success = 1);	/* Finished adding this node */
5801 	} else {
5802 	    printf("Sorry, can't allocate space for name");
5803 	    return(-9);
5804 	}
5805     } else {
5806 	printf("Sorry, can't allocate file list node");
5807 	return(-9);
5808     }
5809 #endif /* NOMSEND */
5810 }
5811 #endif /* ADDCMD */
5812 
5813 #ifndef NOHTTP				/* HTTP ops... */
5814 #ifdef TCPSOCKET
5815 #define HTTP_GET 0			/* GET */
5816 #define HTTP_PUT 1			/* PUT */
5817 #define HTTP_POS 2			/* POST */
5818 #define HTTP_IDX 3			/* INDEX */
5819 #define HTTP_HED 4                      /* HEAD */
5820 #define HTTP_DEL 5                      /* DELETE */
5821 #define HTTP_CON 6                      /* CONNECT */
5822 #define HTTP_OPN 7                      /* OPEN */
5823 #define HTTP_CLS 8                      /* CLOSE */
5824 
5825 static struct keytab httptab[] = {
5826     { "close",   HTTP_CLS, 0 },
5827     { "connect", HTTP_CON, 0 },
5828     { "delete",  HTTP_DEL, 0 },
5829     { "get",     HTTP_GET, 0 },
5830     { "head",    HTTP_HED, 0 },
5831     { "index",   HTTP_IDX, 0 },
5832     { "open",    HTTP_OPN, 0 },
5833     { "put",     HTTP_PUT, 0 },
5834     { "post",    HTTP_POS, 0 }
5835 };
5836 static int nhttptab = sizeof(httptab)/sizeof(struct keytab);
5837 
5838 /* HTTP switches */
5839 #define HT_SW_AG 0			/* /AGENT */
5840 #define HT_SW_HD 1			/* /HEADER */
5841 #define HT_SW_US 2			/* /USER */
5842 #define HT_SW_PW 3			/* /PASSWORD */
5843 #define HT_SW_AR 4                      /* /ARRAY */
5844 #define HT_SW_TP 5                      /* /TOSCREEN */
5845 
5846 static struct keytab httpswtab[] = {
5847     { "/agent",    HT_SW_AG, CM_ARG },
5848 #ifndef NOSPL
5849     { "/array",    HT_SW_AR, CM_ARG },
5850 #endif /* NOSPL */
5851     { "/header",   HT_SW_HD, CM_ARG },
5852     { "/password", HT_SW_PW, CM_ARG },
5853     { "/toscreen", HT_SW_TP, 0 },
5854     { "/user",     HT_SW_US, CM_ARG },
5855     { "", 0, 0 }
5856 };
5857 static int nhttpswtab = sizeof(httpswtab)/sizeof(struct keytab) - 1;
5858 
5859 /* HTTP PUT/POST switches */
5860 #define HT_PP_MT 0			/* /MIME-TYPE */
5861 
5862 static struct keytab httpptab[] = {
5863     { "/mime-type", HT_PP_MT, CM_ARG },
5864     { "", 0, 0 }
5865 };
5866 static int nhttpptab = sizeof(httpptab)/sizeof(struct keytab) - 1;
5867 
5868 #define HTTP_MAXHDR 8
5869 
5870 static int
xdohttp(action,lfile,rf,dfile,agent,hdr,user,pass,mime,array,type)5871 xdohttp(action, lfile, rf, dfile, agent, hdr, user, pass, mime, array, type)
5872     int action;
5873     char *lfile, *rf, *dfile, *agent, *hdr, *user, *pass, *mime, array;
5874     int type;
5875 /* xdohttp */ {
5876     int i, rc = 0;
5877     char * hdrlist[HTTP_MAXHDR];
5878     char rfile[CKMAXPATH+1];
5879     extern int httpfd;
5880 
5881     /* Check for a valid state to execute the command */
5882     if (inserver) {
5883         printf("?The HTTP command may not be used from the IKS\r\n");
5884     } else if (httpfd == -1) {
5885         if (http_reopen() < 0)
5886 	  printf("?No connection\n");
5887         else
5888 	  rc = 1;
5889     } else {
5890 	rc = 1;
5891     }
5892 
5893     /* If the command is not valid, exit with failure */
5894     if (rc == 0)
5895         return(success = 0);
5896 
5897     if (action != HTTP_CON && rf[0] != '/') {
5898         rfile[0] = '/';
5899         ckstrncpy(&rfile[1],rf,CKMAXPATH);
5900     } else {
5901         ckstrncpy(rfile,rf,CKMAXPATH);
5902     }
5903     for (i = 0; i < HTTP_MAXHDR; i++)	/* Initialize header list */
5904       hdrlist[i] = NULL;
5905     makelist(hdr,hdrlist,HTTP_MAXHDR);	/* Make header list */
5906 
5907 #ifdef BETADEBUG
5908     for (i = 0; i < nhttptab; i++)	/* Find action keyword */
5909       if (httptab[i].kwval == action)
5910 	break;
5911     if (i == nhttptab) {		/* Shouldn't happen... */
5912 	printf("?Invalid action - %d\n",action);
5913 	return(0);			/* Failure */
5914     }
5915 
5916     printf("HTTP action:  %s\n",httptab[i].kwd);
5917     printf(" Agent:       %s\n",agent ? agent : "(null)");
5918 
5919     if (hdrlist[1]) {
5920 	printf(" Header list: 1. %s\n",hdrlist[0]);
5921 	for (i = 1; i < HTTP_MAXHDR && hdrlist[i]; i++)
5922 	  printf("%15d. %s\n",i+1,hdrlist[i]);
5923     } else
5924       printf(" Header:      %s\n",hdrlist[0] ? hdrlist[0] : "(null)");
5925 
5926     printf(" User:        %s\n",user ? user : "(null)");
5927 #ifdef COMMENT
5928     printf(" Password:    %s\n",pass ? pass : "(null)");
5929 #endif /* COMMENT */
5930 
5931 #ifndef NOSPL
5932     if (array)
5933       printf(" Array:       \\%%%c[]\n", array);
5934     else
5935       printf(" Array:       (none)\n");
5936 #endif /* NOSPL */
5937 
5938     if (action == HTTP_PUT || action == HTTP_POS)
5939       printf(" Mime-type:   %s\n",mime ? mime : "(null)");
5940 
5941     printf(" Local file:  %s\n",lfile ? lfile : "(null)");
5942     printf(" Remote file: %s\n",rfile ? rfile : "(null)");
5943     printf(" Destination file: %s\n",dfile ? dfile : "(null)");
5944 #endif /* BETADEBUG */
5945 
5946     /* The http_xxxx() functions return 0 on success, -1 on failure */
5947     switch (action) {
5948       case HTTP_CON: {
5949 	  extern int ttyfd;
5950 	  rc = http_connect(httpfd,agent,hdrlist,user,pass,array,rfile);
5951 	  break;
5952       }
5953       case HTTP_DEL:
5954         rc = http_delete(agent,hdrlist,user,pass,array,rfile);
5955         break;
5956       case HTTP_GET:
5957         rc = http_get(agent,hdrlist,user,pass,array,lfile,rfile,type);
5958         break;
5959       case HTTP_HED:
5960         rc = http_head(agent,hdrlist,user,pass,array,lfile,rfile,type);
5961         break;
5962       case HTTP_PUT:
5963         rc = http_put(agent,hdrlist,mime,user,pass,array,lfile,rfile,dfile,
5964 		      type);
5965         break;
5966       case HTTP_POS:
5967         rc = http_post(agent,hdrlist,mime,user,pass,array,lfile,rfile,dfile,
5968 		       type);
5969         break;
5970       case HTTP_IDX:
5971         rc = http_index(agent,hdrlist,user,pass,array,lfile,rfile,type);
5972         break;
5973       default:
5974         rc = -1;
5975     }
5976     return(rc == 0 ? 1 : 0);	        /* Success is set by caller */
5977 }
5978 #endif /* TCPSOCKET */
5979 #endif /* NOHTTP */
5980 
5981 #ifndef NOSPL				/* ARRAY ops... */
5982 static struct keytab arraytab[] = {
5983     { "clear",     ARR_CLR, 0 },
5984     { "copy",      ARR_CPY, 0 },
5985     { "dcl",       ARR_DCL, CM_INV },
5986     { "declare",   ARR_DCL, 0 },
5987     { "destroy",   ARR_DST, CM_INV },
5988     { "equate",    ARR_EQU, CM_INV },
5989     { "link",      ARR_EQU, 0 },
5990     { "resize",    ARR_RSZ, 0 },
5991     { "set",       ARR_SET, 0 },
5992 #ifndef NOSHOW
5993     { "show",      ARR_SHO, 0 },
5994 #endif /* NOSHOW */
5995     { "sort",      ARR_SRT, 0 },
5996     { "undeclare", ARR_DST, 0 },
5997     { "", 0, 0 }
5998 };
5999 static int narraytab = sizeof(arraytab)/sizeof(struct keytab) - 1;
6000 
6001 #ifdef CKLEARN
6002 static struct keytab learnswi[] = {
6003     { "/close",    2, 0 },
6004     { "/off",      0, 0 },
6005     { "/on",       1, 0 }
6006 };
6007 #endif /* CKLEARN */
6008 
6009 int
arrayitoa(x)6010 arrayitoa(x) int x; {			/* Array index to array letter */
6011     if (x == 1)
6012       return(64);
6013     else if (x < 0 || x > (122 - ARRAYBASE))
6014       return(-1);
6015     else
6016       return(x + ARRAYBASE);
6017 }
6018 
6019 int
arrayatoi(c)6020 arrayatoi(c) int c; {			/* Array letter to array index */
6021     if (c == 64)
6022       c = 96;
6023     if (c > 63 && c < 91)
6024       c += 32;
6025     if (c < ARRAYBASE || c > 122)
6026       return(-1);
6027     return(c - ARRAYBASE);
6028 }
6029 
6030 static int				/* Declare an array */
dodcl(cx)6031 dodcl(cx) int cx; {
6032     int i, n, v, lo, hi, rc = 0;
6033     int isdynamic = 0;
6034     char tmpbuf[64];
6035     char ** p = NULL;
6036     char tmp[64];			/* Local temporary string buffer */
6037     if ((y = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6038 	if (y == -3) {
6039 	    printf("?Array name required\n");
6040 	    return(-9);
6041 	} else return(y);
6042     }
6043     ckstrncpy(line,s,LINBUFSIZ);
6044     s = line;
6045     x = arraybounds(s,&lo,&hi);		/* Check syntax and get bounds */
6046     debug(F111,"dodcl arraybounds",s,x);
6047     if (x < 0) {			/* Error - Maybe it's a variable */
6048 	char * p;			/* whose value is an array name */
6049 	int n;
6050 	p = tmpbuf;
6051 	n = 63;
6052 	p[0] = NUL;
6053 	if (s[0] == CMDQ && s[1] == '&')
6054 	  s++;
6055 	if (zzstring(s,&p,&n) > -1) {
6056 	    s = tmpbuf;
6057 	    x = arraybounds(s,&lo,&hi);
6058 	    debug(F111,"dodcl arraybounds 2",s,x);
6059 	}
6060 	if (x < 0) {
6061 	    printf("?Bad array name - \"%s\"\n",s);
6062 	    return(-9);
6063 	}
6064     }
6065     debug(F101,"dodcl hi","",hi);
6066     debug(F101,"dodcl lo","",lo);
6067     debug(F101,"dodcl lo+1","",lo+1);
6068 
6069     if (lo == -1 && hi == -1) {		/* Have good array name and bounds */
6070 	isdynamic = 1;
6071 	n = CMDBL / 5;
6072     } else if (hi > -1) {
6073 	printf("?Segment notation not allowed in array declarations\n");
6074 	return(-9);
6075     } else if ((lo+1) < 0) {
6076 	debug(F101,"dodcl underflow","",lo+1);
6077         printf("?Dimension underflow\n");
6078         return(-9);
6079     } else
6080       n = lo;
6081     x = arrayitoa(x);
6082     if (cx == XXUNDCL) {
6083 	n = 0;
6084 	v = 0;
6085 	if ((y = cmcfm()) < 0)
6086 	  return(y);
6087     } else {
6088 	p = (char **)malloc(sizeof(char **)*(n+1));
6089 	if (!p) {
6090 	    printf("?Memory allocation error\n");
6091 	    return(-9);
6092 	}
6093 	v = 0;				/* Highest initialized member */
6094 	p[0] = NULL;			/* Element 0 */
6095 	keepallchars = 1;
6096 	while (n > 0 && v < n) {	/* Parse initializers */
6097 	    p[v+1] = NULL;
6098 	    ckmakxmsg(tmp,
6099 		      64,
6100 		      "Initial value for \\&",
6101 		      ckctoa((char)x),
6102 		      "[",
6103 		      ckitoa(v+1),
6104 		      "]",
6105 		      NULL,NULL,NULL,NULL,NULL,NULL,NULL
6106 		      );
6107 
6108 	    rc = cmfld((char *)tmp,"",&s,xxstring); /* Get field */
6109 	    if (rc < 0) {		/* Error... */
6110 		if (rc == -3) {		/* Empty element */
6111 		    if (cmflgs == 1)	/* because end of line? */
6112 		      break;		/* Yes, done initializing */
6113 		    else		/* No, it's just empty */
6114 		      continue;		/* Go on to next one. */
6115 		} else {		/* Other parse error */
6116 		    goto dclx;		/* Go free temp pointers */
6117 		}
6118 	    }
6119 	    rc = 1;
6120 	    if (v == 0 && !strcmp(s,"=")) /* Skip the = sign. */
6121 	      continue;
6122 	    s = brstrip(s);		/* Strip any braces */
6123 	    makestr(&(p[++v]),s);
6124 	}
6125 	keepallchars = 0;
6126 	if ((y = cmtxt("Carriage return to confirm","",&s,NULL)) < 0)
6127 	  return(y);
6128 	if (isdynamic)
6129 	  n = v;
6130     }
6131     if (dclarray((char)x,n) < 0) {	/* Declare the array */
6132 	printf("?Declare failed\n");
6133 	goto dclx;
6134     }
6135     for (i = 1; i <= v; i++) {		/* Add any initial values */
6136 	tmp[0] = '&';
6137 	ckmakmsg(&tmp[1],63,ckctoa((char)x),"[",ckitoa(i),"]");
6138 	if (addmac(tmp,p[i]) < 0) {
6139 	    printf("Array initialization error: %s %s\n",tmp,p[i]);
6140 	    rc = -9;
6141 	    goto dclx;
6142 	}
6143     }
6144   dclx:
6145     if (p) {
6146 	for (i = 1; i <= v; i++)
6147 	  if (p[i]) free(p[i]);
6148 	free((char *)p);
6149     }
6150     debug(F101,"DCL rc","",rc);
6151     return(success = rc);
6152 }
6153 
6154 static int
rszarray()6155 rszarray() {
6156     int i, x, y, n, lo, hi, islink = -1;
6157     char c, * s, ** ap = NULL;
6158     if ((x = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6159 	if (x == -3) {
6160 	    printf("?Array name required\n");
6161 	    return(-9);
6162 	} else return(x);
6163     }
6164     ckstrncpy(line,s,LINBUFSIZ);	/* Make safe copy of name */
6165     s = line;
6166     x = arraybounds(s,&lo,&hi);
6167     if (x < 0) {			/* Parse the name, get index */
6168 	printf("?Bad array reference - \"%s\"\n", s);
6169 	return(-9);
6170     }
6171     if (lo < 0 && hi < 0) {
6172 	y = cmnum("New size","",10,&lo,xxstring);
6173 	if (y < 0) {
6174 	    if (y == -3)
6175 	      printf("?New size required\n");
6176 	    return(y);
6177 	}
6178     }
6179     if ((y = cmcfm()) < 0)
6180       return(y);
6181     if (a_link[x] > -1) {		/* Link? */
6182 	islink = x;			/* Yes follow it */
6183 	x = a_link[x];			/* and remember */
6184     }
6185     if (!a_ptr[x]) {
6186 	printf("?Array not declared - \"%s\"\n", s);
6187 	return(-9);
6188     }
6189     if (lo < 0) {
6190 	printf("?New size required\n");
6191 	return(-9);
6192     }
6193     if (hi > -1) {
6194 	printf("?Array segments not allowed for this operation\n");
6195 	return(-9);
6196     }
6197     c = arrayitoa(x);			/* Get array letter */
6198     if (c == '@') {			/* Argument vector array off limits */
6199 	printf("?Sorry, \\&@[] is read-only\n");
6200 	return(-9);
6201     }
6202     if (lo == 0) {			/* If new size is 0... */
6203 	dclarray(c,0);			/* Undeclare the array */
6204 	return(success = 1);
6205     }
6206     n = a_dim[x];			/* Current size */
6207     ap = (char **) malloc((lo+1) * sizeof(char *)); /* New array */
6208     y = (n < lo) ? n : lo;
6209     for (i = 0; i <= y; i++)		/* Copy the part that fits */
6210       ap[i] = a_ptr[x][i];
6211     if (n < lo) {			/* If original array smaller */
6212 	for (; i <= lo; i++)		/* initialize extra elements in */
6213 	  ap[i] = NULL;			/* new array to NULL. */
6214     } else if (n > lo) {		/* If new array smaller */
6215 	for (; i <= lo; i++)		/* deallocate leftover elements */
6216 	  makestr(&(a_ptr[x][i]),NULL);	/* from original array. */
6217     }
6218     free((char *)a_ptr[x]);		/* Free original array list */
6219     a_ptr[x] = ap;			/* Replace with new one */
6220     a_dim[x] = lo;			/* Record the new dimension */
6221     if (islink > -1) {			/* Was this a link? */
6222 	a_ptr[islink] = ap;		/* If so point to the resized array */
6223 	a_dim[islink] = lo;
6224     } else {				/* If not are there links to here? */
6225 	for (i = 0; i < (int) 'z' - ARRAYBASE; i++) { /* Any linked arrays? */
6226 	    if (i != x && a_link[i] == x) {     /* Find and update them */
6227 		a_ptr[i] = ap;
6228 		a_dim[i] = lo;
6229 	    }
6230 	}
6231     }
6232     return(success = 1);
6233 }
6234 
6235 static int
copyarray()6236 copyarray() {
6237     int i, j, x1, lo1, hi1, x2, lo2, hi2, whole = 0;
6238     char c1, c2, * a1, * a2;
6239     if ((y = cmfld("Name of source array","",&s,NULL)) < 0)
6240       return(y);
6241     ckstrncpy(line,s,LINBUFSIZ);
6242     a1 = line;
6243     if ((x1 = arraybounds(a1,&lo1,&hi1)) < 0) {
6244 	printf("?Bad array reference - \"%s\"\n", a1);
6245 	return(-9);
6246     } else if (!a_ptr[x1]) {
6247 	printf("?Array not declared - \"%s\"\n", a1);
6248 	return(-9);
6249     }
6250     c1 = arrayitoa(x1);
6251 
6252     if ((y = cmfld("Name of destination array","",&s,NULL)) < 0)
6253       return(y);
6254     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
6255     a2 = tmpbuf;
6256     if ((x2 = arraybounds(a2,&lo2,&hi2)) < 0) {
6257 	printf("?Bad array reference - \"%s\"\n", a2);
6258 	return(-9);
6259     }
6260     c2 = arrayitoa(x2);
6261 
6262     if ((x = cmcfm()) < 0)
6263       return(x);
6264 
6265     if (c2 == '@') {			/* Argument vector array off limits */
6266 	printf("?Sorry, \\&@[] is read-only\n");
6267 	return(-9);
6268     }
6269     if (lo1 < 0 && lo2 < 0 && hi1 < 0 && hi2 < 0) /* Special case for */
6270       whole = 1;			          /* whole array... */
6271 
6272     if (lo1 < 0) lo1 = whole ? 0 : 1;	/* Supply lower bound of source */
6273     if (hi1 < 0) hi1 = a_dim[x1];	/* Supply upper bound of source */
6274     if (lo2 < 0) lo2 = whole ? 0 : 1;	/* Lower bound of target */
6275     if (hi2 < 0) hi2 = lo2 + hi1 - lo1;	/* Upper bound of target */
6276     if (a_ptr[x2]) {			/* Target array is already declared? */
6277 	if (hi2 > a_dim[x2])		/* If upper bound out of range */
6278 	  hi2 = a_dim[x2];		/* shrink to fit */
6279     } else {				/* Otherwise... */
6280 	x2 = dclarray(c2, hi2);		/* declare the target array */
6281     }
6282     for (i = lo1, j = lo2; i <= hi1 && j <= hi2; i++,j++) { /* Copy */
6283 	makestr(&(a_ptr[x2][j]),a_ptr[x1][i]);
6284     }
6285     return(success = 1);
6286 }
6287 
6288 static int				/* Undeclare an array */
unarray()6289 unarray() {
6290     int x, y, n, rc = 0;
6291     char c, * s;
6292 
6293     if ((y = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6294 	if (y == -3) {
6295 	    printf("?Array name required\n");
6296 	    return(-9);
6297 	} else return(y);
6298     }
6299     ckstrncpy(line,s,LINBUFSIZ);	/* Make safe copy of name */
6300     s = line;
6301     if ((y = cmcfm()) < 0)
6302       return(y);
6303     if ((x = arraybounds(s,&y,&n)) < 0) { /* Parse the name, get index */
6304 	printf("?Bad array reference - \"%s\"\n", s);
6305 	return(-9);
6306     }
6307     if (y > 0 || n > 0) {
6308 	printf("?Partial arrays can not be destroyed\n");
6309 	return(-9);
6310     }
6311     c = arrayitoa(x);			/* Get array letter */
6312     if (a_ptr[x]) {			/* If array is declared */
6313 	if (c == '@') {			/* Argument vector array off limits */
6314 	    printf("?Sorry, \\&@[] is read-only\n");
6315 	    return(-9);
6316 	}
6317 	rc = dclarray(c,-1);		/* Undeclare the array */
6318     } else				/* It wasn't declared */
6319       rc = 1;
6320     if (rc > -1) {			/* Set return code and success */
6321 	success = 1;
6322 	rc = 1;
6323     } else {
6324 	success = 0;
6325 	printf("?Failed - destroy \"\\&%c[]\"\n", c);
6326 	rc = -9;
6327     }
6328     return(rc);
6329 }
6330 
6331 static int
clrarray(cx)6332 clrarray(cx) int cx; {
6333     int i, x, lo, hi;
6334     char c, * s, * val = NULL;
6335 
6336     if ((x = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6337 	if (x == -3) {
6338 	    printf("?Array name required\n");
6339 	    return(-9);
6340 	} else return(x);
6341     }
6342     ckstrncpy(line,s,LINBUFSIZ);	/* Make safe copy of name */
6343     s = line;
6344     if (cx == ARR_SET) {		/* SET */
6345 	if ((x = cmtxt("Value","",&val,xxstring)) < 0)
6346 	  return(x);
6347 	ckstrncpy(tmpbuf,val,TMPBUFSIZ); /* Value to set */
6348 	val = tmpbuf;
6349 	if (!*val) val = NULL;
6350     } else if ((x = cmcfm()) < 0)	/* CLEAR */
6351       return(x);
6352 
6353     if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Parse the name */
6354 	printf("?Bad array reference - \"%s\"\n", s);
6355 	return(-9);
6356     }
6357     c = arrayitoa(x);			/* Get array letter */
6358     if (!a_ptr[x]) {			/* If array is declared */
6359 	printf("?Array %s is not declared\n", s);
6360 	return(-9);
6361     } else if (c == '@') {		/* Argument vector array off limits */
6362 	printf("?Sorry, \\&@[] is read-only\n");
6363 	return(-9);
6364     }
6365     if (lo < 0) lo = 0;
6366     if (hi < 0) hi = a_dim[x];
6367     for (i = lo; i <= hi; i++)		/* Clear/Set selected range */
6368       makestr(&(a_ptr[x][i]),val);
6369 
6370     return(success = 1);
6371 }
6372 
6373 extern char **aa_ptr[CMDSTKL][28];
6374 extern int aa_dim[CMDSTKL][28];
6375 
6376 static int				/* Create symbolic link to an array */
linkarray()6377 linkarray() {
6378     int i = 0, x, y, lo, hi, flag = 0;
6379     char c, * s, * p;
6380 
6381     if ((x = cmfld("Array name not currently in use","",&s,NULL)) < 0) {
6382 	if (x == -3) {
6383 	    printf("?Array name required\n");
6384 	    return(-9);
6385 	} else return(x);
6386     }
6387     ckstrncpy(line,s,LINBUFSIZ);	/* Make safe copy of link name */
6388     s = line;
6389     if ((x = cmfld("Name of existing array","",&p,xxstring)) < 0) {
6390 	if (x == -3) {
6391 	    printf("?Array name required\n");
6392 	    return(-9);
6393 	} else return(x);
6394     }
6395     ckstrncpy(tmpbuf,p,TMPBUFSIZ);	/* Make safe copy of array name */
6396     p = tmpbuf;
6397     if ((x = cmcfm()) < 0)
6398       return(x);
6399 
6400     if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Parse the link name */
6401 	printf("?Bad array reference - \"%s\"\n", s);
6402 	return(-9);
6403     }
6404     if (a_ptr[x]) {			/* Must not already exist */
6405 	c = arrayitoa(x);
6406 	printf("?Array already exists: \\&%c[]\n", c);
6407 	return(-9);
6408     }
6409     if (lo > -1 || hi > -1) {
6410 	printf("?Sorry, whole arrays only: %s\n",s);
6411 	return(-9);
6412     }
6413     if ((y = arraybounds(p,&lo,&hi)) < 0) { /* Parse the array name */
6414 	printf("?Bad array reference - \"%s\"\n", s);
6415 	return(-9);
6416     }
6417     if (lo > -1 || hi > -1) {
6418 	printf("?Sorry, whole arrays only: %s\n",p);
6419 	return(-9);
6420     }
6421     if (x == y) {
6422 	for (i = cmdlvl; i >= 0; i--)
6423 	  if (aa_ptr[i][x]) {
6424 	      flag++;
6425 	      break;
6426 	  }
6427     }
6428     if (flag) {
6429 	a_ptr[x] = aa_ptr[i][y];	/* Link to saved copy */
6430 	a_dim[x] = aa_dim[i][y];
6431     } else {				/* Otherwise... */
6432 	c = arrayitoa(y);		/* Check if it's declared */
6433 	if (!a_ptr[y]) {
6434 	    printf("?Array is not declared: \\&%c[]\n", c);
6435 	    return(-9);
6436 	}
6437 	if (a_link[y] > -1) {		/* And if it's a link itself */
6438 	    printf("?Links to links not allowed: \\&%c[]\n", c);
6439 	    return(-9);
6440 	}
6441 	a_ptr[x] = a_ptr[y];		/* All OK, make the link */
6442 	a_dim[x] = a_dim[y];
6443     }
6444     a_link[x] = y;
6445     return(success = 1);
6446 }
6447 #endif /* NOSPL */
6448 
6449 #ifndef NOCSETS
6450 static char * dcsetname = NULL;
6451 
6452 /* Get Display Character-Set Name */
6453 
6454 char *
getdcset()6455 getdcset() {
6456     char * s;
6457     int y;
6458 #ifdef PCFONTS
6459     extern int tt_font, ntermfont;
6460     extern struct keytab term_font[];
6461 #endif /* PCFONTS */
6462 
6463     s = "";
6464 #ifdef OS2
6465     y = os2getcp();			/* Default is current code page */
6466     switch (y) {
6467       case 437: s = "cp437"; break;
6468       case 850: s = "cp850"; break;
6469       case 852: s = "cp852"; break;
6470       case 857: s = "cp857"; break;
6471       case 858: s = "cp858"; break;
6472       case 862: s = "cp862"; break;
6473       case 866: s = "cp866"; break;
6474       case 869: s = "cp869"; break;
6475       case 1250: s = "cp1250"; break;
6476       case 1251: s = "cp1251"; break;
6477       case 1252: s = "cp1252"; break;
6478       case 1253: s = "cp1253"; break;
6479       case 1254: s = "cp1254"; break;
6480       case 1255: s = "cp1255"; break;
6481       case 1256: s = "cp1256"; break;
6482       case 1257: s = "cp1257"; break;
6483       case 1258: s = "cp1258"; break;
6484     }
6485 #ifdef PCFONTS
6486 /*
6487    If the user has loaded a font with SET TERMINAL FONT then we want
6488    to change the default code page to the font that was loaded.
6489 */
6490     if (tt_font != TTF_ROM) {
6491 	for (y = 0; y < ntermfont; y++ ) {
6492 	    if (term_font[y].kwval == tt_font) {
6493 		s = term_font[y].kwd;
6494 		break;
6495 	    }
6496 	}
6497     }
6498 #endif /* PCFONTS */
6499 #else /* OS2 */
6500 #ifdef COMMENT
6501     /* Hack not needed as of C-Kermit 7.1 */
6502     if (fcharset == FC_1LATIN) {
6503 	s = "latin1-iso";		/* Hack to avoid reporting "cp1252" */
6504     } else {				/* Report current file character set */
6505 #endif /* COMMENT */
6506 	for (y = 0; y <= nfilc; y++)
6507 	  if (fcstab[y].kwval == fcharset) {
6508 	      s = fcstab[y].kwd;
6509 	      break;
6510 	  }
6511 #ifdef COMMENT
6512     }
6513 #endif /* COMMENT */
6514 #endif /* OS2 */
6515     makestr(&dcsetname,s);		/* Return stable pointer */
6516     return((char *)dcsetname);
6517 }
6518 #endif /* NOCSETS */
6519 
6520 #ifndef NOFRILLS
6521 static int
doclear()6522 doclear() {
6523     if ((x = cmkey(clrtab,nclear,"item to clear",
6524 #ifdef NOSPL
6525 		   "device-buffer"
6526 #else
6527 		   "device-and-input"
6528 #endif /* NOSPL */
6529 		   ,xxstring)) < 0) return(x);
6530 #ifndef NOSPL
6531 #ifdef OS2
6532     if (x == CLR_CMD || x == CLR_TRM) {
6533 	if ((z = cmkey(clrcmdtab,nclrcmd,"how much screen to clear\n",
6534 		       "all",xxstring)) < 0)
6535 	  return(z);
6536     }
6537 #endif /* OS2 */
6538 #endif /* NOSPL */
6539     if ((y = cmcfm()) < 0)
6540       return(y);
6541 
6542     /* Clear device input buffer if requested */
6543     y = (x & CLR_DEV) ? ttflui() : 0;
6544 
6545     if (x & CLR_SCR)			/* CLEAR SCREEN */
6546       y = ck_cls();			/* (= SCREEN CLEAR = CLS) */
6547 
6548     if (x & CLR_KBD) {			/* CLEAR KEYBOARD */
6549 	int n;
6550 	n = conchk();
6551 	y = 0;
6552 	while (n-- > 0 && (y = coninc(0) > -1))
6553 	  ;
6554 	y = (y > -1) ? 0 : -1;
6555     }
6556 
6557 #ifndef NOSPL
6558     /* Clear INPUT command buffer if requested */
6559     if (x & CLR_INP) {
6560 	for (z = 0; z < inbufsize; z++)
6561 	  inpbuf[z] = NUL;
6562 	inpbp = inpbuf;
6563 	y = 0;
6564     }
6565 #ifdef CK_APC
6566     if (x & CLR_APC) {
6567 	debug(F101,"Executing CLEAR APC","",apcactive);
6568 	apcactive = 0;
6569 	y = 0;
6570     }
6571 #endif /* CK_APC */
6572     if (x & CLR_ALR) {
6573 	setalarm(0L);
6574 	y = 0;
6575     }
6576 #endif /* NOSPL */
6577 
6578 #ifdef PATTERNS
6579     if (x & (CLR_TXT|CLR_BIN)) {
6580 	int i;
6581 	for (i = 0; i < FTPATTERNS; i++) {
6582 	    if (x & CLR_TXT)
6583 	      makestr(&txtpatterns[i],NULL);
6584 	    if (x & CLR_BIN)
6585 	      makestr(&binpatterns[i],NULL);
6586 	}
6587 	y = 0;
6588     }
6589 #endif /* PATTERNS */
6590 
6591 #ifndef NODIAL
6592     if (x & CLR_DIA) {
6593 	dialsta = DIA_UNK;
6594 	y = 0;
6595     }
6596 #endif /* NODIAL */
6597 
6598 #ifndef NOMSEND
6599     if (x & CLR_SFL) {			/* CLEAR SEND-LIST */
6600 	if (filehead) {
6601 	    struct filelist * flp, * next;
6602 	    flp = filehead;
6603 	    while (flp) {
6604 		if (flp->fl_name)
6605 		  free(flp->fl_name);
6606 		if (flp->fl_alias)
6607 		  free(flp->fl_alias);
6608 		next = flp->fl_next;
6609 		free((char *)flp);
6610 		flp = next;
6611 	    }
6612 	}
6613 	filesinlist = 0;
6614 	filehead = NULL;
6615 	filetail = NULL;
6616 	addlist = 0;
6617 	y = 0;
6618     }
6619 #endif /* NOMSEND */
6620 
6621 #ifdef OS2
6622 #ifndef NOLOCAL
6623     switch (x) {
6624       case CLR_SCL:
6625 	clearscrollback(VTERM);
6626 	break;
6627       case CLR_CMD:
6628 	switch ( z ) {
6629 	  case CLR_C_ALL:
6630 	    clear();
6631 	    break;
6632 	  case CLR_C_BOS:
6633 	    clrboscr_escape(VCMD,SP);
6634 	    break;
6635 	  case CLR_C_BOL:
6636 	    clrbol_escape(VCMD,SP);
6637 	    break;
6638 	  case CLR_C_EOL:
6639 	    clrtoeoln(VCMD,SP);
6640 	    break;
6641 	  case CLR_C_EOS:
6642 	    clreoscr_escape(VCMD,SP);
6643 	    break;
6644 	  case CLR_C_LIN:
6645 	    clrline_escape(VCMD,SP);
6646 	    break;
6647 	  case CLR_C_SCR:
6648 	    clearscrollback(VCMD);
6649 	    break;
6650 	default:
6651 	    printf("Not implemented yet, sorry.\n");
6652 	    break;
6653 	}
6654 	break;
6655 
6656 #ifndef NOTERM
6657       case CLR_TRM:
6658 	 switch ( z ) {
6659 	  case CLR_C_ALL:
6660 	     if (VscrnGetBufferSize(VTERM) > 0 ) {
6661 		 VscrnScroll(VTERM, UPWARD, 0,
6662 			     VscrnGetHeight(VTERM)-(tt_status[VTERM]?2:1),
6663 			     VscrnGetHeight(VTERM) -
6664 			     (tt_status[VTERM]?1:0), TRUE, SP
6665 			     );
6666 		 cleartermscreen(VTERM);
6667 	     }
6668 	     break;
6669 	  case CLR_C_BOS:
6670 	    clrboscr_escape(VTERM,SP);
6671 	    break;
6672 	  case CLR_C_BOL:
6673 	    clrbol_escape(VTERM,SP);
6674 	    break;
6675 	  case CLR_C_EOL:
6676 	    clrtoeoln(VTERM,SP);
6677 	    break;
6678 	  case CLR_C_EOS:
6679 	    clreoscr_escape(VTERM,SP);
6680 	    break;
6681 	  case CLR_C_LIN:
6682 	    clrline_escape(VTERM,SP);
6683 	    break;
6684 	 case CLR_C_SCR:
6685 	     clearscrollback(VTERM);
6686 	     break;
6687 	 default:
6688 	     printf("Not implemented yet, sorry.\n");
6689 	     break;
6690 	}
6691 	break;
6692 #endif /* NOTERM */
6693     }
6694     y = 0;
6695 #endif /* NOLOCAL */
6696 #endif /* OS2 */
6697     return(success = (y == 0));
6698 }
6699 #endif /* NOFRILLS */
6700 
6701 #ifndef NOSPL
6702 static int
doeval(cx)6703 doeval(cx) int cx; {
6704     char *p;
6705     char vnambuf[VNAML], * vnp = NULL;	/* These must be on the stack */
6706     if (!oldeval) {
6707 	if ((y = cmfld("Variable name","",&s,
6708 		       ((cx == XX_EVAL) ? xxstring : NULL))) < 0) {
6709 	    if (y == -3) {
6710 		printf("?Variable name required\n");
6711 		return(-9);
6712 	    } else return(y);
6713 	}
6714 	ckstrncpy(vnambuf,s,VNAML);	/* Make a copy. */
6715 	vnp = vnambuf;
6716 	if (vnambuf[0] == CMDQ &&
6717 	    (vnambuf[1] == '%' || vnambuf[1] == '&'))
6718 	  vnp++;
6719 	y = 0;
6720 	if (*vnp == '%' || *vnp == '&') {
6721 	    if ((y = parsevar(vnp,&x,&z)) < 0)
6722 	      return(y);
6723 	}
6724     }
6725     if ((x = cmtxt("Integer arithmetic expression","",&s,xxstring)) < 0)
6726       return(x);
6727     p = evala(s);
6728     if (!p) p = "";
6729     if (oldeval && *p)
6730       printf("%s\n", p);
6731     ckstrncpy(evalbuf,p,32);
6732     if (!oldeval)
6733       return(success = addmac(vnambuf,p));
6734     else
6735       return(success = *p ? 1 : 0);
6736 }
6737 #endif /* NOSPL */
6738 
6739 #ifdef TNCODE
6740 static int
dotelopt()6741 dotelopt() {
6742     if ((x = cmkey(telcmd, ntelcmd, "TELNET command", "", xxstring)) < 0 )
6743       return(x);
6744     switch (x) {
6745       case WILL:
6746       case WONT:
6747       case DO:
6748       case DONT:
6749 	if ((y = cmkey(tnopts,ntnopts,"TELNET option","",xxstring)) < 0)
6750 	  return(y);
6751 	if ((z = cmcfm()) < 0) return(z);
6752 
6753 	switch (x) {
6754 	  case WILL:
6755 	    if (TELOPT_UNANSWERED_WILL(y))
6756 	      return(success = 0);
6757 	    break;
6758 	  case WONT:
6759 	    if (TELOPT_UNANSWERED_WONT(y))
6760 	      return(success = 0);
6761 	    break;
6762 	  case DO:
6763 	    if (TELOPT_UNANSWERED_DO(y))
6764 	      return(success = 0);
6765 	    break;
6766 	  case DONT:
6767 	    if (TELOPT_UNANSWERED_DONT(y))
6768 	      return(success = 0);
6769 	    break;
6770 	}
6771 	if (local) {
6772 	    success = ((tn_sopt(x,y) > -1) ? 1 : 0);
6773 	} else {
6774 	    printf("ff%02x%02x\n",x,y);
6775 	    success = 1;
6776 	}
6777 	if (success) {
6778 	    switch (x) {
6779 	      case WILL:
6780 		TELOPT_UNANSWERED_WILL(y) = 1;
6781 		break;
6782 	      case WONT:
6783 		if ( TELOPT_ME(y) )
6784 		  TELOPT_UNANSWERED_WONT(y) = 1;
6785 		break;
6786 	      case DO:
6787 		TELOPT_UNANSWERED_DO(y) = 1;
6788 		break;
6789 	      case DONT:
6790 		if ( TELOPT_ME(y) )
6791 		  TELOPT_UNANSWERED_DONT(y) = 1;
6792 		break;
6793 	    }
6794 	    if (tn_wait("XXTELOP") < 0) {
6795 		tn_push();
6796 		success = 0;
6797 	    }
6798 	}
6799 	return(success);
6800       case SB:
6801 	if ((y=cmkey(tnsbopts,ntnsbopts,"TELNET option","",xxstring)) < 0)
6802 	  return(y);
6803 	switch (y) {
6804 	  case TELOPT_NAWS:
6805 	    /* Some compilers require switch() to have at least 1 case */
6806 #ifdef CK_NAWS
6807 	    TELOPT_SB(TELOPT_NAWS).naws.x = 0;
6808 	    TELOPT_SB(TELOPT_NAWS).naws.y = 0;
6809 	    if (local)
6810 	      return(success = ((tn_snaws() > -1) ? 1 : 0));
6811 	    else
6812 	      return(success = 0);
6813 #else
6814 	    return(success = 0);
6815 #endif /* CK_NAWS */
6816 	}
6817         return(success = 0);
6818 
6819 #ifdef CK_KERBEROS
6820 #ifdef KRB5
6821       case TN_FWD:
6822         success = (kerberos5_forward() == AUTH_SUCCESS);
6823         return(success);
6824 #endif /* KRB5 */
6825 #endif /* CK_KERBEROS */
6826 
6827       default:
6828 	if ((z = cmcfm()) < 0) return(z);
6829 #ifndef NOLOCAL
6830 	if (local) {
6831 	    CHAR temp[3];
6832 	    if (network && IS_TELNET()) { /* TELNET */
6833 		temp[0] = (CHAR) IAC;
6834 		temp[1] = x;
6835 		temp[2] = NUL;
6836 		success = (ttol((CHAR *)temp,2) > -1 ? 1 : 0);
6837 		if (tn_deb || debses || deblog) {
6838 		    /* TN_MSG_LEN is in ckctel.h */
6839 		    ckmakmsg(tn_msg,256,"TELNET SENT ",TELCMD(x),NULL,NULL);
6840 		    debug(F101,tn_msg,"",x);
6841 		    if (debses || tn_deb) tn_debug(tn_msg);
6842 		}
6843 		return(success);
6844 	    }
6845             return(success = 0);
6846 	} else {
6847 #endif /* NOLOCAL */
6848 	    printf("ff%02x\n",x);
6849 	    return(success = 1);
6850 #ifndef NOLOCAL
6851 	}
6852 #endif /* NOLOCAL */
6853     }
6854 }
6855 #endif /* TNCODE */
6856 
6857 
6858 #ifndef NOPUSH
6859 #ifndef NOFRILLS
6860 static int
doedit()6861 doedit() {
6862 #ifdef OS2
6863     char * p = NULL;
6864 #endif /* OS2 */
6865     if (!editor[0]) {
6866 	s = getenv("EDITOR");
6867 	if (s) ckstrncpy(editor,s,CKMAXPATH);
6868 	editor[CKMAXPATH] = NUL;
6869 	if (!editor[0]) {
6870 	    printf("?Editor not defined - use SET EDITOR to define\n");
6871 	    return(-9);
6872 	}
6873     }
6874     ckstrncpy(tmpbuf,editfile,TMPBUFSIZ);
6875 /*
6876   cmiofi() lets us parse the name of an existing file, or the name of
6877   a nonexistent file to be created.
6878 */
6879     x = cmiofi("File to edit", (char *)tmpbuf, &s, &y, xxstring);
6880     debug(F111,"edit",s,x);
6881     if (x < 0 && x != -3)
6882       return(x);
6883     if (x == -3) {
6884 	tmpbuf[0] = NUL;
6885     } else {
6886 	ckstrncpy(tmpbuf,s,TMPBUFSIZ);
6887     }
6888     if ((z = cmcfm()) < 0) return(z);
6889     if (y) {
6890 	printf("?A single file please\n");
6891 	return(-9);
6892     }
6893     if (nopush) {
6894 	printf("?Sorry, editing not allowed\n");
6895 	return(success = 0);
6896     }
6897     if (tmpbuf[0]) {
6898     /* Get full path in case we change directories between EDIT commands */
6899 	zfnqfp(tmpbuf, CKMAXPATH, editfile);
6900 	editfile[CKMAXPATH] = NUL;
6901 #ifdef OS2
6902 	p = editfile;			/* Flip the stupid slashes */
6903 	while (*p) {
6904 	    if (*p == '/') *p = '\\';
6905 	    p++;
6906 	}
6907 #endif /* OS2 */
6908     } else
6909       editfile[0] = NUL;
6910     if (editfile[0]) {
6911 	if (zchki(editfile) < (CK_OFF_T)0 && zchko(editfile) < 0) {
6912 	    printf("?Access denied: %s\n",editfile);
6913 	    return(-9);
6914 	}
6915     }
6916     x = 0;
6917     if (editopts[0]) {
6918 #ifdef OS2
6919 	x = ckindex("%1",(char *)editopts,0,0,1);
6920 	if (x > 0)
6921 	  editopts[x] = 's';
6922 	else
6923 #endif /* OS2 */
6924 	  x = ckindex("%s",(char *)editopts,0,0,1);
6925     }
6926     if (((int)strlen(editopts) + (int)strlen(editfile) + 1) < TMPBUFSIZ) {
6927 	if (x)
6928 	  sprintf(tmpbuf,editopts,editfile);
6929 	else
6930 	  sprintf(tmpbuf,"%s %s",editopts,editfile);
6931     }
6932     s = line;
6933     ckmakmsg(s,LINBUFSIZ,editor," ",tmpbuf,NULL);
6934 #ifdef OS2
6935     p = s + strlen(editor);		/* And again with the slashes */
6936     while (p != s) {
6937 	if (*p == '/') *p = '\\';
6938 	p--;
6939     }
6940 #endif /* OS2 */
6941     conres();
6942     x = zshcmd(s);
6943     concb((char)escape);
6944     return(x);
6945 }
6946 #endif /* NOFRILLS */
6947 #endif /* NOPUSH */
6948 
6949 #ifdef BROWSER
6950 static int
dobrowse()6951 dobrowse() {
6952 #ifdef OS2
6953     char * p = NULL;
6954 #endif /* OS2 */
6955     if (nopush) {
6956 	printf("?Sorry, browsing not allowed\n");
6957 	return(success = 0);
6958     }
6959 #ifndef NT
6960     /* Windows lets the Shell Execute the URL if no Browser is defined */
6961     if (!browser[0]) {
6962 	s = getenv("BROWSER");
6963 	if (s) ckstrncpy(browser,s,CKMAXPATH);
6964 	browser[CKMAXPATH] = NUL;
6965 	if (!browser[0]) {
6966 	    printf("?Browser not defined - use SET BROWSER to define\n");
6967 	    return(-9);
6968 	}
6969     }
6970 #endif /* NT */
6971     ckstrncpy(tmpbuf,browsurl,TMPBUFSIZ);
6972     if ((x = cmtxt("URL",(char *)browsurl,&s,xxstring)) < 0)
6973       return(x);
6974     ckstrncpy(browsurl,s,4096);
6975     x = 0;
6976     if (browsopts[0]) {
6977 #ifdef OS2
6978 	x = ckindex("%1",(char *)browsopts,0,0,1);
6979 	if (x > 0)
6980 	  browsopts[x] = 's';
6981 	else
6982 #endif /* OS2 */
6983 	  x = ckindex("%s",(char *)browsopts,0,0,1);
6984     }
6985     if (((int)strlen(browsopts) + (int)strlen(browsurl) + 1) < TMPBUFSIZ) {
6986 	if (x)
6987 	  sprintf(tmpbuf,browsopts,browsurl);
6988 	else
6989 	  sprintf(tmpbuf,"%s %s",browsopts,browsurl);
6990     }
6991 #ifdef NT
6992     if (!browser[0])
6993       return(success = Win32ShellExecute(browsurl));
6994 #endif /* NT */
6995     s = line;
6996     ckmakmsg(s,LINBUFSIZ,browser," ",tmpbuf,NULL);
6997 #ifdef OS2
6998     p = line + strlen(browser);		/* Flip slashes */
6999     while (p != line) {
7000 	if (*p == '/') *p = '\\';
7001 	p--;
7002     }
7003 #endif /* OS2 */
7004     conres();
7005     x = zshcmd(s);
7006     concb((char)escape);
7007     return(x);
7008 }
7009 #endif /* BROWSER */
7010 
7011 #ifdef CK_RECALL
7012 static int
doredo()7013 doredo() {			/* Find a previous cmd and redo it */
7014     extern int on_recall, in_recall;
7015     int x;
7016     char * p;
7017 
7018     if ((x = cmtxt(
7019 "pattern, or first few characters of a previous command",
7020 		   "*",&s,xxstring)) < 0)
7021       return(x);
7022     ckstrncpy(line,s,LINBUFSIZ);
7023     x = strlen(s);
7024     s = line;
7025     if (*s == '{') {			/* Braces disable adding * to end */
7026 	if (s[x-1] == '}') {
7027 	    s[x-1] = NUL;
7028 	    s++;
7029 	    x--;
7030 	}
7031     } else {				/* No braces, add * to end. */
7032 	s[x] = '*';
7033 	s[x+1] = NUL;
7034     }
7035 
7036     while (x > 0 && s[x] == '*' && s[x-1] == '*') s[x--] = NUL;
7037 
7038     if (!on_recall || !in_recall) {
7039 	printf("?Sorry, command recall can't be used now.\n");
7040 	return(-9);
7041     }
7042     if ((p = cmgetcmd(s))) {		/* Look for it history buffer */
7043 	ckmakmsg(cmdbuf,CMDBL,p,"\r",NULL,NULL); /* Copy to command buffer */
7044 	if (!quiet)			/* Echo it */
7045 	  printf("%s\n",cmdbuf);
7046 	cmaddnext();			/* Force re-add to history buffer */
7047 	return(cmflgs = -1);		/* Force reparse */
7048     } else {
7049 	printf("?Sorry - \"%s\" not found\n", s);
7050 	return(-9);
7051     }
7052 }
7053 #endif /* CK_RECALL */
7054 
7055 #ifndef NOXFER
7056 #ifndef NOCSETS
7057 static int
doassoc()7058 doassoc()  {				/* ASSOCIATE */
7059     extern struct keytab tcstab[];
7060     extern int ntcs;
7061     if ((x = cmkey(assoctab, nassoc, "", "", xxstring)) < 0 )
7062       return(x);
7063 
7064     switch (x) {			/* Associate what? */
7065 
7066       case ASSOC_TC:			/* Transfer character-set... */
7067 	if ((x = cmkey(tcstab, ntcs,
7068 		       "transfer character-set name","",xxstring)) < 0)
7069 	  return(x);
7070 	if ((y = cmkey(fcstab, nfilc,
7071 		       "with file character-set","", xxstring)) < 0)
7072 	  if (y != -3)
7073 	    return(y);
7074 	if ((z = cmcfm()) < 0)
7075 	  return(z);
7076 	axcset[x] = y;
7077 	return(success = 1);
7078 
7079       case ASSOC_FC:			/* File character-set... */
7080 	if ((x = cmkey(fcstab, nfilc,
7081 		       "file character-set name","",xxstring)) < 0)
7082 	  return(x);
7083 	if ((y = cmkey(tcstab, ntcs,
7084 		       "with transfer character-set","", xxstring)) < 0)
7085 	  if (y != -3)
7086 	    return(y);
7087 	if ((z = cmcfm()) < 0)
7088 	  return(z);
7089 	afcset[x] = y;
7090 	return(success = 1);
7091 
7092       default:
7093 	return(-2);
7094     }
7095 }
7096 #endif /* NOCSETS */
7097 #endif /* NOXFER */
7098 
7099 #ifndef NOHELP
7100 static int
domanual()7101 domanual() {
7102 #ifdef OS2
7103     if ((x = cmcfm()) < 0)
7104       return(x);
7105     if (nopush) {
7106 	printf("?Sorry, access to system commands is disabled.\n");
7107 	return(-9);
7108     }
7109     y = mxlook(mactab,"manual",nmac);
7110     if (y > -1) {
7111 	z = maclvl;			/* Save the current maclvl */
7112 	dodo(y,NULL,cmdstk[cmdlvl].ccflgs); /* Run the macro */
7113 	while (maclvl > z) {
7114 	    debug(F101,"XXMAN loop maclvl 1","",maclvl);
7115 	    sstate = (CHAR) parser(1);
7116 	    debug(F101,"XXMAN loop maclvl 2","",maclvl);
7117 	    if (sstate) proto();
7118 	}
7119 	debug(F101,"XXMAN loop exit maclvl","",maclvl);
7120 	return(success);
7121     }
7122     return(success = 0);
7123 #else
7124     if ((x = cmtxt(
7125 #ifdef UNIX
7126 		   "Carriage return to confirm the command, or manual topic",
7127 #else
7128 		   "Carriage return to confirm the command, or help topic",
7129 #endif /* UNIX */
7130 		   "kermit",
7131 		   &s,
7132 		   xxstring
7133 		   )
7134 	 ) < 0)
7135       return(x);
7136 #endif /* OS2 */
7137 
7138 #ifdef UNIX
7139     ckmakmsg(tmpbuf,TMPBUFSIZ,"man ",s,NULL,NULL);
7140 #else
7141     ckmakmsg(tmpbuf,TMPBUFSIZ,"help ",s,NULL,NULL);
7142 #endif /* UNIX */
7143     debug(F110,"MANUAL",tmpbuf,0);
7144     if (nopush) {
7145 	printf("?Sorry, access to system commands is disabled.\n");
7146 	return(-9);
7147     } else {
7148 	conres();			/* Restore the console */
7149 	success = zshcmd(tmpbuf);
7150 	concb((char)escape);		/* Restore CBREAK mode */
7151 	return(success);
7152     }
7153 }
7154 #endif /* NOHELP */
7155 
7156 #ifndef NOHTTP
7157 #ifdef TCPSOCKET
7158 static struct keytab sslswtab[] = {
7159     { "/ssl", 1, 0 },
7160     { "/tls", 1, 0 }
7161 };
7162 
7163 #ifndef NOURL
7164 struct urldata http_url = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
7165 #endif /* NOURL */
7166 
7167 static int
dohttp()7168 dohttp() {				/* HTTP */
7169     struct FDB sw, kw, fi;
7170     int n, getval, allinone = 0;
7171     char c, * p;
7172     char rdns[128];
7173 
7174     char * http_agent = NULL;		/* Parse results */
7175     char * http_hdr   = NULL;
7176     char * http_user  = NULL;
7177     char * http_pass  = NULL;
7178     char * http_mime  = NULL;
7179     char * http_lfile = NULL;
7180     char * http_rfile = NULL;
7181     char * http_dfile = NULL;
7182     char   http_array = NUL;
7183     int    http_action = -1;
7184 
7185     char * http_host = NULL;
7186     char * http_srv  = NULL;
7187     int    http_ssl  = 0;
7188 
7189     static char * http_d_agent = NULL;
7190     static char * http_d_user = NULL;
7191     static char * http_d_pass = NULL;
7192 
7193     static int    http_d_type = 0;
7194     int           http_type = http_d_type;
7195 
7196 #ifdef OS2
7197     p = "Kermit 95";			/* Default user agent */
7198 #else
7199     p = "C-Kermit";
7200 #endif /* OS2 */
7201     makestr(&http_agent,p);
7202     makestr(&http_mime,"text/HTML");	/* MIME type default */
7203     rdns[0] = '\0';
7204 
7205     cmfdbi(&sw,				/* 1st FDB - general switches */
7206        _CMKEY,				/* fcode */
7207        "OPEN, CLOSE, GET, HEAD, PUT, INDEX, or POST,\n or switch", /* hlpmsg */
7208        "",				/* default */
7209        "",				/* addtl string data */
7210        nhttpswtab,			/* addtl numeric data 1: tbl size */
7211        4,				/* addtl numeric data 2: 4 = cmswi */
7212        xxstring,			/* Processing function */
7213        httpswtab,			/* Keyword table */
7214        &kw				/* Pointer to next FDB */
7215        );
7216     cmfdbi(&kw,				/* 2nd FDB - commands */
7217        _CMKEY,				/* fcode */
7218        "Command",			/* hlpmsg */
7219        "",				/* default */
7220        "",				/* addtl string data */
7221        nhttptab,			/* addtl numeric data 1: tbl size */
7222        0,				/* addtl numeric data 2: 0 = keyword */
7223        xxstring,			/* Processing function */
7224        httptab,				/* Keyword table */
7225        NULL				/* Pointer to next FDB */
7226        );
7227 
7228     while (1) {
7229 	x = cmfdb(&sw);			/* Parse something */
7230 	if (x < 0)			/* Error */
7231 	  goto xhttp;
7232 	n = cmresult.nresult;
7233 	if (cmresult.fdbaddr == &kw)	/* Command - exit this loop */
7234 	  break;
7235 	c = cmgbrk();			/* Switch... */
7236 	getval = (c == ':' || c == '=');
7237 	x = -9;
7238 	if (getval && !(cmgkwflgs() & CM_ARG)) {
7239 	    printf("?This switch does not take an argument\n");
7240 	    goto xhttp;
7241 	}
7242 	switch (cmresult.nresult) {	/* Handle each switch */
7243           case HT_SW_TP:                /* /TOSCREEN */
7244             http_type = 1;
7245             break;
7246 	  case HT_SW_AG:		/* /AGENT */
7247 	    if (getval) {
7248 		if ((x = cmfld("User agent",p,&s,xxstring)) < 0)
7249 		  goto xhttp;
7250 	    } else {
7251 		s = p;
7252 	    }
7253 	    makestr(&http_agent,s);
7254 	    break;
7255 	  case HT_SW_HD:		/* /HEADER */
7256 	    s = NULL;
7257 	    if (getval) {
7258 		if ((x = cmfld("Header line","",&s,xxstring)) < 0) {
7259 		    if (x == -3)
7260 		      s = NULL;
7261 		    else
7262 		      goto xhttp;
7263 		}
7264 	    }
7265 	    makestr(&http_hdr,s);
7266 	    break;
7267 	  case HT_SW_US:		/* /USER */
7268 	    s = NULL;
7269 	    if (getval) {
7270 		if ((x = cmfld("User ID","",&s,xxstring)) < 0) {
7271                   if (x == -3)
7272                     s = "";
7273                   else
7274 		    goto xhttp;
7275                 }
7276 	    }
7277 	    makestr(&http_user,s);
7278 	    break;
7279 	  case HT_SW_PW:		/* /PASSWORD */
7280 	    debok = 0;
7281 	    s = NULL;
7282 	    if (getval) {
7283 		if ((x = cmfld("Password","",&s,xxstring)) < 0)
7284 		  goto xhttp;
7285 	    }
7286 	    makestr(&http_pass,s);
7287 	    break;
7288 #ifndef NOSPL
7289 	  case HT_SW_AR: {		/* /ARRAY: */
7290 	      char * s2, array = NUL;
7291 	      if (!getval) {
7292 		  printf("?This switch requires an argument\n");
7293 		  x = -9;
7294 		  goto xhttp;
7295 	      }
7296 	      if ((x = cmfld("Array name (a single letter will do)",
7297 			     "",
7298 			     &s,
7299 			     NULL
7300 			     )) < 0) {
7301 		  if (x == -3) {
7302 		      printf("?Array name required\n");
7303 		      x = -9;
7304 		      goto xhttp;
7305 		  } else
7306 		    goto xhttp;
7307 	      }
7308 	      if (!*s) {
7309 		  printf("?Array name required\n");
7310 		  x = -9;
7311 		  goto xhttp;
7312 	      }
7313 	      s2 = s;
7314 	      if (*s == CMDQ) s++;
7315 	      if (*s == '&') s++;
7316 	      if (!isalpha(*s)) {
7317 		  printf("?Bad array name - \"%s\"\n",s2);
7318 		  x = -9;
7319 		  goto xhttp;
7320 	      }
7321 	      array = *s++;
7322 	      if (isupper(array))
7323 		array = tolower(array);
7324 	      if (*s && (*s != '[' || *(s+1) != ']')) {
7325 		  printf("?Bad array name - \"%s\"\n",s2);
7326 		  http_array = NUL;
7327 		  x = -9;
7328 		  goto xhttp;
7329 	      }
7330 	      http_array = array;
7331 	      break;
7332 	  }
7333 #endif /* NOSPL */
7334 	  default:
7335 	    x = -2;
7336 	    goto xhttp;
7337 	}
7338     }
7339     http_action = n;			/* Save the action */
7340     if (http_action == HTTP_PUT || http_action == HTTP_POS) {
7341 	cmfdbi(&sw,			/* 1st FDB - switch */
7342 	       _CMKEY,			/* fcode */
7343 	       "Local filename\n Or switch", /* help */
7344 	       "",			/* default */
7345 	       "",			/* addtl string data */
7346 	       nhttpptab,		/* keyword table size */
7347 	       4,			/* addtl numeric data 2: 4 = cmswi */
7348 	       xxstring,		/* Processing function */
7349 	       httpptab,		/* Keyword table */
7350 	       &fi			/* Pointer to next FDB */
7351 	       );
7352 	cmfdbi(&fi,			/* 2nd FDB - filename */
7353 	       _CMIFI,			/* fcode */
7354 	       "Local filename",	/* hlpmsg */
7355 	       "",			/* default */
7356 	       "",			/* addtl string data */
7357 	       0,			/* addtl numeric data 1 */
7358 	       0,			/* addtl numeric data 2 */
7359 	       xxstring,
7360 	       NULL,
7361 	       NULL
7362 	       );
7363 	while (1) {
7364 	    x = cmfdb(&sw);
7365 	    if (x < 0)
7366 	      goto xhttp;		/* Free any malloc'd temp strings */
7367 	    n = cmresult.nresult;
7368 	    if (cmresult.fcode != _CMKEY)
7369 	      break;
7370 	    c = cmgbrk();		/* Switch... */
7371 	    getval = (c == ':' || c == '=');
7372 	    if (getval && !(cmgkwflgs() & CM_ARG)) {
7373 		printf("?This switch does not take an argument\n");
7374 		x = -9;
7375 		goto xhttp;
7376 	    }
7377 	    switch (n) {
7378 	      case HT_PP_MT:
7379 		s = "text/HTML";
7380 		if (getval) {
7381 		    if ((x = cmfld("MIME type",
7382 				   "text/HTML",&s,xxstring)) < 0)
7383 		      goto xhttp;
7384 		}
7385 		makestr(&http_mime,s);
7386 		break;
7387 	      default:
7388 		x = -2;
7389 		goto xhttp;
7390 	    }
7391 	}
7392 	makestr(&http_lfile,cmresult.sresult);
7393 	n = ckindex("/",http_lfile,-1,1,0);
7394 	if (n)
7395 	  p = &http_lfile[n];
7396 	else
7397 	  p = http_lfile;
7398 	if ((x = cmfld("URL or remote filename",p,&s,xxstring)) < 0) {
7399           if (x == -3) {
7400             printf("?%s what?\n",(http_action == HTTP_PUT) ? "Put" : "Post");
7401             x = -9;
7402           }
7403           goto xhttp;
7404         }
7405 	if (!*s) s = NULL;
7406 	makestr(&http_rfile,s);
7407 
7408 	if ((x = cmtxt("Response filename","",&s,xxstring)) < 0) {
7409           if (x != -3)
7410             goto xhttp;
7411         }
7412         if (*s)
7413           makestr(&http_dfile,s);
7414     }
7415     switch (http_action) {
7416       case HTTP_DEL:			/* DELETE */
7417 	if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7418           if (x == -3) {
7419             printf("?Delete what?\n");
7420             x = -9;
7421           }
7422           goto xhttp;
7423         }
7424 	makestr(&http_rfile,s);
7425 	break;
7426       case HTTP_CON:			/* CONNECT */
7427         if ((x = cmfld("Remote host[:port]","",&s,xxstring)) < 0) {
7428           if (x == -3) {
7429             printf("?Remote host[:port] is required\n");
7430             x = -9;
7431           }
7432           goto xhttp;
7433         }
7434 	makestr(&http_rfile,s);
7435 	break;
7436       case HTTP_HED: {			/* HEAD */
7437 	  char buf[CKMAXPATH+1];
7438 	  if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7439 	      if (x == -3) {
7440 		  printf("?Head of what?\n");
7441 		  x = -9;
7442 	      }
7443 	      goto xhttp;
7444 	  }
7445 	  makestr(&http_rfile,s);
7446 
7447 	  if (http_array || http_type) { /* Default result filename */
7448 	      p = "";			 /* None if /ARRAY or /TOSCREEN */
7449 	  } else {
7450 	      n = ckindex("/",http_rfile,-1,1,0); /* Otherwise strip path */
7451 	      if (n)		                  /* and add ".head" */
7452 		p = &http_rfile[n];
7453 	      else
7454 		p = http_rfile;
7455 	      ckmakmsg(buf,CKMAXPATH,p,".head",NULL,NULL);
7456 	      p = buf;
7457 	  }
7458 	  if ((x = cmofi("Local filename",p,&s,xxstring)) < 0) {
7459 	      if (x != -3)
7460 		goto xhttp;
7461 	  }
7462 	  makestr(&http_lfile,s);
7463 	  break;
7464       }
7465       case HTTP_GET:			/* GET */
7466       case HTTP_IDX: {			/* INDEX */
7467 	  extern int wildena;
7468 	  int tmp;
7469 	  char * lfile = "";
7470 	  if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7471 	      if (x == -3) {
7472 		  printf("?Get what?\n");
7473 		  x = -9;
7474 	      }
7475 	      goto xhttp;
7476 	  }
7477 	  makestr(&http_rfile,s);
7478 	  if (http_action == HTTP_GET && !http_type)
7479 	    zstrip(http_rfile,&lfile);
7480 	  /* URLs often contain question marks or other metacharacters */
7481 	  /* cmofi() doesn't like them */
7482 	  tmp = wildena;
7483 	  wildena = 0;
7484 	  if ((x = cmofi("Local filename",lfile,&s,xxstring)) < 0) {
7485 	      wildena = tmp;
7486 	      if (x != -3)
7487 		goto xhttp;
7488 	  }
7489 	  wildena = tmp;
7490 	  makestr(&http_lfile,s);
7491 	  break;
7492       }
7493       case HTTP_OPN: {
7494 	  int sslswitch = 0;
7495 #ifdef CK_SSL
7496 	  struct FDB sw, fl;
7497 	  cmfdbi(&sw,
7498 		 _CMKEY,		/* fcode */
7499 		 "IP host name or address, or switch", /* hlpmsg */
7500 		 "",			/* default */
7501 		 "",			/* addtl string data */
7502 		 2,			/* addtl numeric data 1: tbl size */
7503 		 4,			/* addtl numeric data 2: 4 = cmswi */
7504 		 xxstring,		/* Processing function */
7505 		 sslswtab,		/* Keyword table */
7506 		 &fl			/* Pointer to next FDB */
7507 		 );
7508 	  cmfdbi(&fl,			/* 2nd FDB - host */
7509 		 _CMFLD,		/* fcode */
7510 		 "",			/* hlpmsg */
7511 		 "",			/* default */
7512 		 "",			/* addtl string data */
7513 		 0,			/* addtl numeric data 1 */
7514 		 0,			/* addtl numeric data 2 */
7515 		 xxstring,
7516 		 NULL,
7517 		 NULL
7518 		 );
7519 	  x = cmfdb(&sw);		/* Parse switch or host */
7520 	  if (x < 0)			/* Error */
7521 	    goto xhttp;
7522 	  if (cmresult.fcode == _CMFLD) { /* Host */
7523 	      s = cmresult.sresult;	  /* Set up expected pointer */
7524 	      goto havehost;              /* Go parse rest of command */
7525 	  }
7526 	  sslswitch = 1;		/* /SSL or /TLS switch - set flag */
7527 #endif /* CK_SSL */
7528 
7529 	  /* Parse host */
7530 
7531 	  if ((x = cmfld("URL, hostname, or ip-address","",&s,xxstring)) < 0) {
7532 	      if (x == -3) {
7533 		  printf("?Open what?\n");
7534 		  x = -9;
7535 	      }
7536 	      goto xhttp;
7537 	  }
7538 
7539 	havehost:			/* Come here with s -> host */
7540 #ifdef CK_URL
7541 	  x = urlparse(s,&http_url);	/* Was a URL given? */
7542 	  if (x < 1) {			/* Not a URL */
7543 #endif /* CK_URL */
7544 	      makestr(&http_host,s);
7545 	      if ((x =
7546 		   cmfld("Service name or port number",
7547 			 sslswitch ? "https" : "http",&s,xxstring)) < 0)
7548 		goto xhttp;
7549 	      else
7550 		makestr(&http_srv,s);
7551 #ifdef CK_URL
7552 	  } else if (ckstrcmp(http_url.svc,"http",-1,0) && /* Non-HTTP URL */
7553 		     ckstrcmp(http_url.svc,"https",-1,0)) {
7554 	      printf("?Non-HTTP URL\n");
7555 	      x = -9;
7556 	      goto xhttp;
7557 	  } else {			/* Have HTTP URL */
7558 	      makestr(&http_srv, http_url.svc);
7559 	      makestr(&http_user,http_url.usr);
7560 	      makestr(&http_pass,http_url.psw);
7561 	      makestr(&http_host,http_url.hos);
7562 	      if (http_url.por)
7563 		makestr(&http_srv,http_url.por);
7564 	      makestr(&http_rfile,http_url.pth);
7565 	  }
7566 	  if (http_rfile) {		/* Open, GET, and Close */
7567 	      printf("?Directory/file path not allowed in HTTP OPEN URL\n");
7568 	      x = -9;
7569 	      goto xhttp;
7570 	  }
7571 	  if (!ckstrcmp("https",http_srv,-1,0) || sslswitch ||
7572 	      !ckstrcmp("443",http_srv,-1,0))
7573 	    http_ssl = 1;
7574 #endif /* CK_URL */
7575 	  break;
7576       }
7577       case HTTP_CLS:
7578         break;
7579     }
7580     if ((x = cmcfm()) < 0)
7581       goto xhttp;
7582 
7583     if (http_action == HTTP_OPN) {
7584         x = (http_open(http_host,http_srv,http_ssl,rdns,128,http_agent) == 0);
7585         if (x) {
7586             if (!quiet) {
7587               if (rdns[0])
7588                 printf("Connected to %s [%s]\r\n",http_host,rdns);
7589               else
7590                 printf("Connected to %s\r\n",http_host);
7591             }
7592             if (http_agent) {
7593                 if (http_d_agent)
7594 		  free(http_d_agent);
7595                 http_d_agent = http_agent;
7596                 http_agent = NULL;
7597             }
7598             if (http_user) {
7599                 if (http_d_user)
7600 		  free(http_d_user);
7601                 http_d_user = http_user;
7602                 http_user = NULL;
7603             }
7604             if (http_pass) {
7605                 if (http_d_pass) {
7606                     memset(http_d_pass,0,strlen(http_d_pass));
7607                     free(http_d_pass);
7608                 }
7609                 http_d_pass = http_pass;
7610                 http_pass = NULL;
7611             }
7612             http_d_type = http_type;
7613         } else {
7614             if (!quiet)
7615 	      printf("?HTTP Connection failed.\r\n");
7616         }
7617     } else if (http_action == HTTP_CLS) {
7618         if (http_d_agent) {
7619             free(http_d_agent);
7620             http_d_agent = NULL;
7621         }
7622         if (http_d_user) {
7623             free(http_d_user);
7624             http_d_user = NULL;
7625         }
7626         if (http_d_pass) {
7627             memset(http_d_pass,0,strlen(http_d_pass));
7628             free(http_d_pass);
7629             http_d_pass = NULL;
7630         }
7631         http_d_type = 0;
7632         x = (http_close() == 0);
7633     }
7634     if ((http_action != HTTP_CLS) &&
7635 	(http_action != HTTP_CON) && http_rfile) { /* Remote file is URL? */
7636 
7637 	/* All-in-one actions when a URL is given... */
7638 
7639 #ifdef CK_URL
7640 	if (urlparse(http_rfile,&http_url) > 0) { /* Have URL? */
7641 	    if (ckstrcmp(http_url.svc,"http",-1,0) && /* It's an HTTP URL? */
7642 		ckstrcmp(http_url.svc,"https",-1,0)) {
7643 		printf("?Non-HTTP URL\n");
7644 		x = -9;
7645 		goto xhttp;
7646 	    } else {			/* Yes, collect the pieces */
7647 		makestr(&http_srv, http_url.svc);
7648 		makestr(&http_user,http_url.usr);
7649 		makestr(&http_pass,http_url.psw);
7650 		makestr(&http_host,http_url.hos);
7651 		if (http_url.por)
7652 		  makestr(&http_srv,http_url.por);
7653 		makestr(&http_rfile,http_url.pth);
7654 	    }
7655 	    if (!http_rfile) {		/* Still have a path? */
7656                 makestr(&http_rfile,"/");
7657 	    }
7658 	    if (!ckstrcmp("https",http_srv,-1,0) || /* Check for SSL/TLS */
7659 		!ckstrcmp("443",http_srv,-1,0))
7660 	      http_ssl = 1;
7661 	    if (http_isconnected())	/* Close any open HTTP connection */
7662 	      http_close();
7663 	    if (http_pass == NULL && http_d_pass != NULL)
7664 	      makestr(&http_pass,http_d_pass);
7665 	    x = (http_open(http_host,
7666 			   http_srv,http_ssl,rdns,128,http_d_agent) == 0);
7667 	    if (x < 0) {
7668 		x = 0;
7669 		goto xhttp;
7670 	    }
7671 	    allinone = 1;
7672 	}
7673 #endif /* CK_URL */
7674         if (http_pass == NULL && http_d_pass != NULL)
7675 	  makestr(&http_pass,http_d_pass);
7676 
7677 	if (http_action == HTTP_OPN && allinone) {
7678 	    http_action = HTTP_GET;
7679 	}
7680         x = xdohttp(http_action,
7681                     http_lfile,
7682 		    http_rfile,
7683                     http_dfile,
7684 		    http_agent ? http_agent : http_d_agent,
7685 		    http_hdr,
7686 		    http_user  ? http_user  : http_d_user,
7687 		    http_pass  ? http_pass  : http_d_pass,
7688 		    http_mime,
7689 		    http_array,
7690 		    http_type
7691 		    );
7692 	if (allinone)
7693 	  x = (http_close() == 0);
7694     }
7695 
7696   xhttp:
7697     if (http_agent) free(http_agent);
7698     if (http_hdr)   free(http_hdr);
7699     if (http_user)  free(http_user);
7700     if (http_pass) {
7701         memset(http_pass,0,strlen(http_pass));
7702         free(http_pass);
7703     }
7704     if (http_mime)  free(http_mime);
7705     if (http_lfile) free(http_lfile);
7706     if (http_rfile) free(http_rfile);
7707     if (http_dfile) free(http_dfile);
7708     if (http_host)  free(http_host);
7709     if (http_srv)   free(http_srv);
7710 
7711     if (x > -1)
7712       success = x;
7713     return(x);
7714 }
7715 #endif /* TCPSOCKET */
7716 #endif /* NOHTTP */
7717 
7718 
7719 #ifndef NOSPL
7720 static int
dotrace()7721 dotrace() {
7722     int on = 1;
7723     struct FDB sw, kw;
7724     cmfdbi(&sw,				/* 1st FDB - switch */
7725 	   _CMKEY,			/* fcode */
7726 	   "Trace object;\n Or switch", /* help */
7727 	   "",				/* default */
7728 	   "",				/* addtl string data */
7729 	   2,				/* keyword table size */
7730 	   4,				/* addtl numeric data 2: 4 = cmswi */
7731 	   xxstring,			/* Processing function */
7732 	   onoffsw,			/* Keyword table */
7733 	   &kw				/* Pointer to next FDB */
7734 	   );
7735     cmfdbi(&kw,				/* 2nd FDB - Trace object */
7736 	   _CMKEY,			/* fcode */
7737 	   "Trace object",		/* help */
7738 	   "all",			/* default */
7739 	   "",				/* addtl string data */
7740 	   ntracetab,			/* keyword table size */
7741 	   0,				/* addtl numeric data 2: 0 = keyword */
7742 	   xxstring,			/* Processing function */
7743 	   tracetab,			/* Keyword table */
7744 	   NULL				/* Pointer to next FDB */
7745 	   );
7746     if ((x = cmfdb(&sw)) < 0)
7747       return(x);
7748     if (cmresult.fdbaddr == &sw) {
7749 	on = cmresult.nresult;
7750 	if ((x = cmkey(tracetab, ntracetab,"","all",xxstring)) < 0)
7751 	  return(x);
7752     } else {
7753 	x = cmresult.nresult;
7754     }
7755     if ((y = cmcfm()) < 0)
7756       return(y);
7757 
7758     switch (x) {
7759       case TRA_ASG:
7760 	tra_asg = on;
7761 	break;
7762       case TRA_CMD:
7763 	tra_cmd = on;
7764 	break;
7765       case TRA_ALL:
7766 	tra_asg = on;
7767 	tra_cmd = on;
7768 	break;
7769       default:
7770 	return(-2);
7771     }
7772     printf("TRACE %s\n", on ? "ON" : "OFF");
7773     return(success = 1);
7774 }
7775 #endif /* NOSPL */
7776 
7777 
7778 static int
doprompt()7779 doprompt() {
7780     extern int xcmdsrc;
7781     if ((x = cmtxt("Optional message","",&s,xxstring)) < 0)
7782       return(x);
7783 #ifdef NOSPL
7784     printf("?Sorry, PROMPT requires script programming language\n");
7785     return(-9);
7786 #else
7787     debug(F101,"Prompt cmdlvl","",cmdlvl);
7788     cmdlvl++;
7789     if (cmdlvl > CMDSTKL) {
7790 	printf("?Command stack overflow: %d\n",cmdlvl);
7791 	cmdlvl--;
7792 	return(-9);
7793     }
7794     xcmdsrc = CMD_KB;
7795     cmdstk[cmdlvl].src = CMD_KB;	/* Say we're at the prompt */
7796     cmdstk[cmdlvl].lvl = 0;
7797     cmdstk[cmdlvl].ccflgs = cmdstk[cmdlvl-1].ccflgs;
7798     if (tra_cmd)
7799       printf("[%d] +P: \"(prompt)\"\n",cmdlvl);
7800     concb((char)escape);
7801     if (!quiet)
7802       printf(
7803 "(Recursive command prompt: Resume script with CONTINUE, STOP to stop...)\n"
7804             );
7805     if (*s) {				/* If prompt given */
7806 	makestr(&(prstring[cmdlvl-1]),cmgetp()); /* Save current prompt */
7807 	cmsetp(s);			/* Set new one */
7808     }
7809     return(success = 1);
7810 #endif /* NOSPL */
7811 }
7812 
7813 #ifdef CKLEARN
7814 VOID
learncmd(s)7815 learncmd(s) char *s; {			/* Record commands in learned script */
7816     char buf[64];
7817     int i, k;
7818     if (learnfp && learning) {		/* Only if open and on */
7819 	k = ckstrncpy(buf,s,64);
7820 	for (i = 0; i < k; i++) {	/* Get top-level command keyword */
7821 	    if (buf[i] <= SP) {
7822 		buf[i] = NUL;
7823 		break;
7824 	    }
7825 	}
7826 	k = lookup(cmdtab,buf,ncmd,NULL); /* Look it up */
7827 	if (k == XXCON || k == XXLEARN)	  /* Don't record CONNECT or LEARN */
7828 	  return;
7829 	if (k == XXTEL) {
7830 	    fputs("SET HOST /NETWORK:TCP",learnfp);
7831 	    fputs(&s[i],learnfp);
7832 	    fputs(" TELNET /TELNET",learnfp);
7833 	    fputs("\nIF FAIL STOP 1 Connection failed\n",learnfp);
7834 	} else {
7835 	    fputs(s,learnfp);
7836 	    fputs("\n",learnfp);
7837 	}
7838     }
7839 }
7840 #endif /* CKLEARN */
7841 
7842 
7843 #ifdef SSHCMD
7844 /*
7845   2010/03/01...
7846   Reopen a connection that was made with an external ssh client
7847   after it has been closed.
7848  */
7849 int
redossh()7850 redossh() {
7851     int x, netsave;
7852     x = nettype;
7853     debug(F111,"redossh nettype",ttname,nettype);
7854     if ((y = setlin(XXSSH,0,1)) < 0) {
7855 	if (errno)
7856 	  printf("?%s\n",ck_errstr());
7857 	else
7858 	  return(y);
7859 	nettype = x;			/* Failed, restore net type. */
7860 	success = 0;
7861 	return(y);
7862     }
7863     netsave = x;
7864     return(y);
7865 }
7866 #endif	/* SSHCMD */
7867 
7868 /*
7869   Like hmsga() in ckuus2.c but takes a single substitution parameter, s2,
7870   which replaces every occurrence of "%s" in the first argument.
7871   Added to print text containing the copyright year, so the year doesn't
7872   have to be hardwired into lots of scattered text strings.
7873 */
7874 int                                     /* Print an array of lines, */
7875 #ifdef CK_ANSIC
hmsgaa(char * s[],char * s2)7876 hmsgaa(char *s[], char *s2)		/* pausing at end of each screen. */
7877 #else
7878 hmsgaa(s,s2) char *s[]; char *s2;
7879 #endif	/* CK_ANSIC */
7880 {
7881     extern int hmtopline;
7882 #ifdef OS2
7883     extern int tt_rows[], tt_cols[];
7884 #else /* OS2 */
7885     extern int tt_rows, tt_cols;
7886 #endif /* OS2 */
7887     int x, y, i, j, k, n;
7888     if ((x = cmcfm()) < 0) return(x);
7889 
7890 #ifdef CK_TTGWSIZ
7891 #ifdef OS2
7892     ttgcwsz();
7893 #else /* OS2 */
7894     /* Check whether window size changed */
7895     if (ttgwsiz() > 0) {
7896         if (tt_rows > 0 && tt_cols > 0) {
7897             cmd_rows = tt_rows;
7898             cmd_cols = tt_cols;
7899         }
7900     }
7901 #endif /* OS2 */
7902 #endif /* CK_TTGWSIZ */
7903 
7904     printf("\n");                       /* Start off with a blank line */
7905     n = (hmtopline > 0) ? hmtopline : 1; /* Line counter */
7906     for (i = 0; *s[i]; i++) {
7907         printf((char *)s[i],s2);	/* Print a line. */
7908 	printf("\n");
7909         y = (int)strlen(s[i]);
7910         k = 1;
7911         for (j = 0; j < y; j++)         /* See how many newlines were */
7912           if (s[i][j] == '\n') k++;     /* in the string... */
7913         n += k;
7914         if (n > (cmd_rows - 3) && *s[i+1]) /* After a screenful, give them */
7915           if (!askmore()) return(0);    /* a "more?" prompt. */
7916           else n = 0;
7917     }
7918     printf("\n");
7919     return(0);
7920 }
7921 
7922 /*  I S I N T E R N A L M A C R O  -- April 2017  */
7923 
7924 int
isinternalmacro(x)7925 isinternalmacro(x) int x; {          /* Test if macro is internally defined */
7926     char * m;
7927     char * tags[] = { "_whi", "_for", "_sw_", "_if_" };
7928     int i, internal = 0;
7929 
7930     m = mactab[x].kwd;
7931 
7932 #ifdef COMMENT
7933     /* Good idea but this flag is not set for _whi2, etc */
7934     internal = ((cmdstk[cmdlvl].ccflgs & CF_IMAC) ? 1 : 0);
7935     debug(F111,"isinternalmacro",m,internal);
7936     return(internal);
7937 #endif  /* COMMENT */
7938 
7939     debug(F101,"isinternalmacro x","",x);
7940     if (*m != '_') {
7941         debug(F110," not internal",m,0);
7942         return(0);
7943     }
7944     if (!m) m = "";
7945     if (*m) {
7946         debug(F110," macro name",m,0);
7947         internal = ckindex(m,"|_while|_forx|_forz|_xif|_switx|",0,0,0);
7948         debug(F111," internal macro","A",internal);
7949         if (!internal) {
7950             int i, j, n, len = 0;
7951             n = -1;
7952             for (i = 0; i < sizeof(* tags); i++) {
7953                 if (ckindex(tags[i],m,0,0,0)) {
7954                     n = i;
7955                     break;
7956                 }
7957             }
7958             debug(F111," tags index",tags[n],n);
7959             if (n > -1) {
7960                 char * tag = tags[i];
7961                 len = (int)strlen(tag);
7962                 debug(F111," tag len",tag,len);
7963                 for (i = len; m[i]; i++) {
7964                     debug(F101," loop i","",i);
7965                     debug(F000," char","",m[i]);
7966                     if (!isdigit(m[i])) {
7967                         internal = 0;
7968                         break;
7969                     } else {
7970                         internal = 1;
7971                     }
7972                 }
7973             }
7974             debug(F101," internal macro","B",internal);
7975         }
7976     }
7977     return(internal);
7978 }
7979 
7980 /*  N E W E R R M S G  -- New error message routine, April 2017  */
7981 
7982 #define ERRMSGBUFSIZ 320
7983 static char errmsgbuf[ERRMSGBUFSIZ] = { '\0' };
7984 
newerrmsg(s)7985 VOID newerrmsg(s) char *s; {
7986     char * tmperrbuf[ERRMSGBUFSIZ];
7987 
7988     extern char lasttakeline[];
7989     extern char *tfnam[];
7990     extern int tfblockstart[];
7991     extern int tlevel;
7992     int len1, len2, len3, len4, len5;
7993     char * buf = errmsgbuf;
7994     char * takefile = getbasename(tfnam[tlevel]);
7995     char nbuf[20];
7996     char * lineno = nbuf;
7997     int x;
7998 
7999     debug(F110,"newerrmsg",s,0);
8000     ckstrncpy(nbuf,ckitoa(tfblockstart[tlevel]),20);
8001     lineno = (char *)nbuf;
8002 
8003     if (!s) s = "";
8004     if (!*s) s = "Syntax error";
8005 
8006     if (tlevel < 0) {
8007         printf("?%s\n",s);
8008         return;
8009     }
8010     len1 = (int)strlen(s);
8011     len2 = (int)strlen(takefile);
8012     len3 = (int)strlen(lineno);
8013     len4 = (int)strlen((char *)lasttakeline);
8014     len5 = len1 + len2 + len3 + 12;
8015 
8016     x = 80 - len5;         /* Free space for beginning of offending command */
8017     if (x > len4) {        /* Free space is greater than command length */
8018 #ifdef HAVE_SNPRINTF
8019         snprintf((char *)tmperrbuf,ERRMSGBUFSIZ,"?%s[%s]: \"%s\": %s\n",
8020                takefile,
8021                lineno,
8022                (char *)lasttakeline,
8023                s
8024                );
8025 #else
8026         sprintf((char *)tmperrbuf,"?%s[%s]: \"%s\": %s\n",
8027                takefile,
8028                lineno,
8029                (char *)lasttakeline,
8030                s
8031                );
8032 #endif  /* HAVE_SNPRINTF */
8033 
8034     } else if (x > 40) {
8035         char c;
8036         c = lasttakeline[x];
8037         lasttakeline[x] = NUL;
8038 #ifdef HAVE_SNPRINTF
8039         snprintf((char *)tmperrbuf,ERRMSGBUFSIZ,"?%s[%s]: \"%s...\": %s\n",
8040                takefile, lineno, (char *)lasttakeline, s);
8041 #else
8042         sprintf((char *)tmperrbuf,"?%s[%s]: \"%s...\": %s\n",
8043                takefile, lineno, (char *)lasttakeline, s);
8044 #endif  /* HAVE_SNPRINTF */
8045         lasttakeline[x] = c;
8046     } else {
8047         char c;
8048         if (len4 > 74) {
8049             x = 74 - (len2 + len3 + 8);
8050             c = lasttakeline[x];
8051             lasttakeline[x] = NUL;
8052 #ifdef HAVE_SNPRINTF
8053             snprintf((char *)tmperrbuf,ERRMSGBUFSIZ,
8054                 "?%s[%s]: \"%s...\":\n Error: %s\n",
8055                 takefile, lineno, (char *)lasttakeline, s);
8056 #else
8057             sprintf((char *)tmperrbuf,"?%s[%s]: \"%s...\":\n Error: %s\n",
8058                    takefile, lineno, (char *)lasttakeline, s);
8059 
8060 #endif  /* HAVE_SNPRINTF */
8061             lasttakeline[x] = c;
8062         } else {
8063 #ifdef HAVE_SNPRINTF
8064             snprintf((char *)tmperrbuf,ERRMSGBUFSIZ,
8065                      "?%s[%s]: \"%s\":\n %s\n",
8066                      takefile, lineno, (char *)lasttakeline, s);
8067 #else
8068             sprintf((char *)tmperrbuf,"?%s[%s]: \"%s\":\n %s\n",
8069                    takefile, lineno, (char *)lasttakeline, s);
8070 #endif  /* HAVE_SNPRINTF */
8071         }
8072     }
8073   xnewerrmsg:
8074     /* Print the message only if it's not the same as the last one */
8075     if (ckstrcmp((char *)errmsgbuf,(char *)tmperrbuf,ERRMSGBUFSIZ,1)) {
8076         ckstrncpy((char *)errmsgbuf,(char *)tmperrbuf,ERRMSGBUFSIZ);
8077         printf("%s",(char *)errmsgbuf);
8078     }
8079     return;
8080 }
8081 
8082 /*  D O C M D  --  Do a command  */
8083 
8084 /*
8085  Returns:
8086    -2: user typed an illegal command
8087    -1: reparse needed
8088     0: parse was successful (even tho command may have failed).
8089 */
8090 #ifdef DEBUG
8091 int cmdstats[256] = { -1, -1 };
8092 #endif /* DEBUG */
8093 
8094 int
docmd(cx)8095 docmd(cx) int cx; {
8096     extern int nolocal, cmkwflgs;
8097 
8098     debug(F101,"docmd entry, cx","",cx);
8099     activecmd = cx;
8100     doconx = ((activecmd == XXCON)  || (activecmd == XXTEL) ||
8101 	      (activecmd == XXRLOG) || (activecmd == XXPIPE) ||
8102               (activecmd == XXIKSD) || (activecmd == XXPTY));
8103 /*
8104   Originally all commands were handled with a big switch() statement,
8105   but eventually this started blowing up compilers.  Now we have a series
8106   of separate if statements and small switches, with the commands that are
8107   most commonly executed in scripts and loops coming first, to speed up
8108   compute-bound scripts.
8109 */
8110 
8111 #ifdef DEBUG
8112     if (cmdstats[0] == -1) {		/* Count commands */
8113 	int i;				/* for tuning... */
8114 	for (i = 0; i < 256; i++)
8115 	  cmdstats[i] = 0;
8116     }
8117 #endif /* DEBUG */
8118 
8119     switch (cx) {
8120       case -4:				/* EOF */
8121 #ifdef OSK
8122 	if (msgflg)  printf("\n");
8123 #else
8124 	if (msgflg)  printf("\r\n");
8125 #endif /* OSK */
8126 	  doexit(GOOD_EXIT,xitsta);
8127       case -3:				/* Null command */
8128 	return(0);
8129       case -9:				/* Like -2, but errmsg already done */
8130       case -1:				/* Reparse needed */
8131 	return(cx);
8132       case -6:				/* Special */
8133       case -2:				/* Error, maybe */
8134 
8135 #ifndef NOSPL
8136 /*
8137   Maybe they typed a macro name.  Let's look it up and see.
8138 */
8139 	if (cx == -6)			/* If they typed CR */
8140 	  ckstrncat(cmdbuf,"\015",CMDBL); /*  add it back to command buffer. */
8141 	if (ifcmd[cmdlvl] == 2)		/* Watch out for IF commands. */
8142 	  ifcmd[cmdlvl]--;
8143 	repars = 1;			/* Force reparse */
8144 	cmres();
8145 	cx = XXDO;			/* Try DO command */
8146 #else
8147 	return(cx);
8148 #endif /* NOSPL */
8149       default:
8150 	if (cx < 0)
8151 	  return(cx);
8152 	break;
8153     }
8154 #ifdef DEBUG
8155     if (cx < 256)
8156       cmdstats[cx]++;
8157 #endif /* DEBUG */
8158 
8159     if ((cmkwflgs & CM_PSH)
8160 #ifndef NOPUSH
8161 	&& nopush
8162 #endif /* NOPUSH */
8163 	) {
8164 	printf("?Access to system disabled\n");
8165 	return(-9);
8166     }
8167     if ((cmkwflgs & CM_LOC)
8168 #ifndef NOLOCAL
8169 	&& nolocal
8170 #endif /* NOLOCAL */
8171 	) {
8172 	printf("?Connections disabled\n");
8173 	return(-9);
8174     }
8175 
8176 #ifndef NOSPL
8177     /* Used in FOR loops */
8178 
8179     if (cx == XX_INCR || cx == XXINC  || /* _INCREMENT, INCREMENT */
8180 	cx == XX_DECR || cx == XXDEC)	 /* _DECREMENT, DECREMENT */
8181       return(doincr(cx));
8182 
8183     /* Define (or change the definition of) a macro or variable */
8184 
8185     if (cx == XXUNDEF || cx == XXUNDFX) {
8186 #ifdef IKSD
8187 	if (inserver && !ENABLED(en_asg)) {
8188 	    printf("?Sorry, DEFINE/ASSIGN disabled\n");
8189 	    return(-9);
8190 	}
8191 #endif /* IKSD */
8192 	return(doundef(cx));		/* [_]UNDEFINE */
8193     }
8194     if (cx == XXDEF || cx == XXASS ||
8195 	cx == XXDFX || cx == XXASX) {
8196 #ifdef IKSD
8197 	if (inserver && !ENABLED(en_asg)) {
8198 	    printf("?Sorry, DEFINE/ASSIGN disabled\n");
8199 	    return(-9);
8200 	}
8201 #endif /* IKSD */
8202 	if (atmbuf[0] == '.' && !atmbuf[1]) /* "." entered as keyword */
8203 	  xxdot = 1;			/* i.e. with space after it... */
8204 	return(dodef(cx));		/* DEFINE, ASSIGN, etc... */
8205     }
8206 
8207     /* IF, WHILE, and friends  */
8208 
8209     if (cx == XXIF || cx == XXIFX || cx == XXWHI || cx == XXASSER) {
8210 	return(doif(cx));
8211     }
8212     if (cx == XXSWIT) {			/* SWITCH */
8213 	return(doswitch());
8214     }
8215 
8216     /* GOTO, FORWARD, and _FORWARD (used internally by FOR, WHILE, etc) */
8217 
8218     if (cx == XXGOTO || cx == XXFWD || cx == XXXFWD) { /* GOTO or FORWARD */
8219 	/* Note, here we don't set SUCCESS/FAILURE flag */
8220 #ifdef COMMENT
8221 	if ((y = cmfld("label","",&s,xxstring)) < 0) {
8222 	    if (y == -3) {
8223 		if (cx != XXXFWD) {
8224 		    printf("?Label name required\n");
8225 		    return(-9);
8226 		}
8227 	    } else
8228 	      return(y);
8229 	}
8230 	ckstrncpy(tmpbuf,s,TMPBUFSIZ);
8231 	if ((x = cmcfm()) < 0) return(x);
8232 #else
8233 	if ((y = cmtxt("label","",&s,xxstring)) < 0) {
8234 	    if (y == -3) {
8235 		if (cx != XXXFWD) {
8236 		    printf("?GOTO: Label name required: \"%s\" \"%s\"\n",
8237 			   atmbuf,
8238 			   cmdbuf);
8239 		    return(-9);
8240 		}
8241 	    } else
8242 	      return(y);
8243 	}
8244 	ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
8245 #endif /* COMMENT */
8246 	s = tmpbuf;
8247 	debug(F111,"GOTO target",s,cx);
8248 	return(dogoto(s,cx));
8249     }
8250     if (cx == XXDO || cx == XXMACRO) {	/* DO (a macro) */
8251 	char mnamebuf[16];		/* (buffer for controlled temp name) */
8252 	struct FDB kw, fl;
8253 	int mx;				/* Macro index (on stack!) */
8254 
8255 	debug(F101,"XXMACRO 0",line,cx);
8256 	if (cx == XXDO) {
8257 	    if (nmac == 0) {
8258 		printf("\n?No macros defined\n");
8259 		return(-9);
8260 	    }
8261 	    for (y = 0; y < nmac; y++) { /* copy the macro table into a */
8262 		mackey[y].kwd = mactab[y].kwd; /* regular keyword table */
8263 		mackey[y].kwval = y;	/* with value = pointer to macro tbl */
8264 		mackey[y].flgs = mactab[y].flgs;
8265 	    }
8266 	    cmfdbi(&kw,			/* First FDB - macro name */
8267 		   _CMKEY,		/* fcode */
8268 		   "Macro",		/* hlpmsg */
8269 		   "",			/* default */
8270 		   "",			/* addtl string data */
8271 		   nmac,		/* addtl numeric data 1: tbl size */
8272 		   0,			/* addtl numeric data 2: 0 = cmkey */
8273 		   xxstring,		/* Processing function */
8274 		   mackey,		/* Keyword table */
8275 		   &fl			/* Pointer to next FDB */
8276 		   );
8277 	    cmfdbi(&fl,			/* 2nd FDB - for "{" */
8278 		   _CMFLD,		/* fcode */
8279 		   "",			/* hlpmsg */
8280 		   "",
8281 		   "",			/* addtl string data */
8282 		   0,			/* addtl numeric data 1 */
8283 		   0,			/* addtl numeric data 2 */
8284 		   xxstring,
8285 		   NULL,
8286 		   NULL
8287 		   );
8288 	    x = cmfdb(&kw);		/* Parse something */
8289 	    if (x < 0) {		/* Error */
8290 		if (x == -3) {
8291 		    printf("?Macro name required\n");
8292 		    return(-9);
8293 		} else
8294 		  return(x);
8295 	    }
8296 	    if (cmresult.fcode == _CMKEY) {
8297 		extern int mtchanged;
8298 		char * macroname = NULL;
8299 
8300 	    /* In case args include an \fexec() that changes the macro table */
8301 
8302 		mx = x;			/* Save macro index on stack */
8303 		mtchanged = 0;		/* Mark state of macro table */
8304 		makestr(&macroname,mactab[mx].kwd); /* Save name */
8305 
8306 /*
8307   Prior to C-Kermit 9.0.304 Dev.22, April 23, 2017, cmtxt() was called in
8308   all cases with zzstring.  But this fouled up the identification of macro
8309   arguments when their values contained grouping characters such as
8310   doublequotes and braces.  Now we defer the evaluation of the macro
8311   arguments until after the arguments themselves have been correctly
8312   identified.  An exception is made for the internal macros that implement
8313   the FOR, WHILE, IF, and SWITCH commands.
8314 */
8315                 if (isinternalmacro(x)) {
8316                     debug(F100,"DO parser internal macro","",0);
8317                     if ((y = cmtxt("optional arguments","",&s,zzstring)) < 0)
8318                       return(y);		/* Get macro args */
8319                 } else {
8320                     debug(F100,"DO parser normal macro","",0);
8321                     if ((y = cmtxt("optional arguments","",&s,NULL)) < 0)
8322                       return(y);		/* Get macro args */
8323                 }
8324 		if (mtchanged) {	/* Macro table changed? */
8325 		    mx = mlook(mactab,macroname,nmac); /* Look up name again */
8326 		}
8327 		if (macroname)
8328 		  free(macroname);
8329 
8330 		return(dodo(mx,s,cmdstk[cmdlvl].ccflgs) < 1 ?
8331 		       (success = 0) : 1);
8332 	    }
8333 	    ckstrncpy(line,cmresult.sresult,LINBUFSIZ);	/* _CMFLD */
8334 	    if (atmbuf[0] == '{') {
8335 		if ((y = cmcfm()) < 0)
8336 		  return(y);
8337 	    }
8338 	} else {			/* XXMACRO ("immediate macro") */
8339 	    int k = 0;
8340 	    line[k++] = '{';
8341 	    line[k++] = SP;
8342 	    line[k] = NUL;
8343 	    debug(F111,"XXMACRO A",line,k);
8344 	    if ((y = cmtxt("Braced list of commands","",&s,xxstring)) < 0)
8345 	      return(y);
8346 	    k = ckstrncpy(line+k,s,LINBUFSIZ-k);
8347 	    debug(F111,"XXMACRO B",line,k);
8348 	}
8349 	x = strlen(line);
8350 	if ((line[0] == '{' && line[x-1] != '}') || line[0] == '}')
8351 	  return(-2);
8352 	if (line[0] != '{' && line[x-1] != '}') {
8353 	    /* Unknown command.  If ON_UNKNOWN_COMMAND macro is defined, */
8354 	    /* parse args and then execute it, but only if it is not */
8355 	    /* already active. */
8356 	    int k = -1;
8357 	    if (!unkmacro) {
8358 		k = mxlook(mactab,"on_unknown_command",nmac);
8359 	    }
8360 	    if (k > -1) {
8361 		ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
8362 		z = maclvl;		/* Save the current maclvl */
8363 		if ((y = cmtxt("text","",&s,xxstring)) < 0)
8364 		  return(y);
8365 		ckstrncat(tmpbuf," ",TMPBUFSIZ);
8366 		ckstrncat(tmpbuf,s,TMPBUFSIZ);
8367 		unkmacro = 1;
8368 		debug(F110,"ON_UNKNOWN_COMMAND",s,0);
8369 		dodo(k,tmpbuf,cmdstk[cmdlvl].ccflgs); /* Run the macro */
8370 		while (maclvl > z) {
8371 		    sstate = (CHAR) parser(1);
8372 		    if (sstate) proto();
8373 		}
8374 		debug(F101,"UNKMAC loop exit maclvl","",maclvl);
8375 		unkmacro = 0;
8376 		return(success);
8377 	    }
8378             if (x > 0)
8379 	      printf("?Not a command or macro name: \"%s\"\n",line);
8380             else
8381 	      printf("?Not a command or macro name.\n");
8382 	    return(-9);
8383 	}
8384 	s = brstrip(line);
8385 	sprintf(mnamebuf," ..tmp:%03d",cmdlvl);	/* safe (16) */
8386 	x = addmac(mnamebuf,s);
8387 	return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs) < 1 ? (success = 0) : 1);
8388     }
8389 
8390     if (cx == XXLBL) {			/* LABEL */
8391 	if ((x = cmfld("label","",&s,xxstring)) < 0) {
8392 	    if (x == -3) {
8393 #ifdef COMMENT
8394 		printf("?LABEL: Label name required: \"%s\"\n", cmdbuf);
8395 		return(-9);
8396 #else
8397 		s = "";
8398 #endif /* COMMENT */
8399 	    } else return(x);
8400 
8401 	}
8402 	debug(F111,"LABEL",s,x);
8403 	if ((x = cmcfm()) < 0) return(x);
8404 	return(0);
8405     }
8406 
8407     if (cx == XXEVAL || cx == XX_EVAL) /* _EVALUATE,  EVALUATE  */
8408       return(doeval(cx));
8409 
8410 #ifndef NOSEXP
8411     if (cx == XXSEXP) {			/* Lisp-like S-Expression */
8412 	struct stringarray * q;
8413 	char /* *p, *r, */ *tmp, *m;
8414 	int i, k, n, quote = 0, contd = 0, size = 0, len = 0;
8415 	extern int sexprc, sexppv;
8416 
8417 	tmp = tmpbuf;			/* Buffer to collect SEXP */
8418 	tmpbuf[0] = NUL;		/* Clear it */
8419 	size = TMPBUFSIZ;		/* Capacity of buffer */
8420 	sexprc = -1;			/* Assume bad input */
8421 	n = 0;				/* Paren balance counter */
8422 
8423 	while (1) {			/* Allow SEXP on multiple lines */
8424 	    m = contd ?
8425 	      "Continuation of S-Expression" :
8426 		"S-Expression (\"help sexp\" for details)";
8427 	    x = cmtxt(m,"",&s,xxstring);
8428 	    if (x < 0)
8429 	      return(x);
8430 	    if (!*s)			/* Needed for (=) and (:) */
8431 	      s = cmdbuf+1;		/* I can't explain why. */
8432 	    k = ckmakmsg(tmp, size, contd ? " " : "(", s, NULL, NULL);
8433 	    if (k < 1) {
8434 		printf("?SEXP too long - %d max\n",TMPBUFSIZ);
8435 		return(-9);
8436 	    }
8437 	    debug(F111,contd ? "sexp contd" : "sexp",s,k);
8438 
8439 	    for (i = len; i < len+k; i++) { /* Check balance  */
8440 		if (!quote && tmpbuf[i] == CMDQ) {
8441 		    quote = 1;
8442 		    continue;
8443 		}
8444 		if (quote) {
8445 		    quote = 0;
8446 		    continue;
8447 		}
8448 		if (tmpbuf[i] == '(')
8449 		  n++;
8450 		else if (tmpbuf[i] == ')')
8451 		  n--;
8452 	    }
8453 	    if (n == 0) {		/* Break when balanced */
8454 		break;
8455 	    }
8456 	    if (n < 0) {		/* Too many right parens */
8457 		printf("?Unbalanced S-Expression: \"%s\"\n",tmpbuf);
8458 		return(-9);
8459 	    }
8460 	    contd++;			/* Need more right parens */
8461 	    cmini(ckxech);		/* so keep parsing */
8462 	    tmp += k;			/* adjust buffer pointer */
8463 	    size -= k;			/* and capacity */
8464 	    len += k;			/* and length so far */
8465 	}
8466 	s = tmpbuf;
8467 	makestr(&lastsexp,s);
8468 	q = cksplit(1,SEXPMAX,s,NULL,NULL,8,0,0,0); /* Precheck for > 1 SEXP */
8469 	debug(F101,"sexp split","",q->a_size);
8470 
8471 	if (q->a_size == 1) {		/* We should get exactly one back */
8472 	    char * result, * dosexp();
8473 	    sexprc = 0;			/* Reset out-of-band return code */
8474 	    result = dosexp(s);		/* Get result */
8475 	    debug(F111,"sexp result",result,sexprc);
8476 	    if (sexprc == 0) {		/* Success */
8477 		/* Echo the result if desired */
8478 		if ((!xcmdsrc && sexpecho != SET_OFF) || sexpecho == SET_ON)
8479                   if (result) if (*result)
8480                     printf(" %s\n",result);
8481 		makestr(&sexpval,result);
8482 		success = sexppv > -1 ? sexppv : 1;
8483 		return(success);
8484 	    }
8485 	}
8486 	if (sexprc < 0)
8487 	  printf("?Invalid S-Expression: \"%s\"\n",lastsexp);
8488 	return(-9);
8489     }
8490 #endif /* NOSEXP */
8491 
8492 #endif /* NOSPL */
8493 
8494     if (cx == XXECH || cx == XXXECH || cx == XXVOID
8495 #ifndef NOSPL
8496 	|| cx == XXAPC
8497 #endif /* NOSPL */
8498 	) {				/* ECHO or APC */
8499 	if ((x = cmtxt((cx == XXECH || cx == XXXECH) ?
8500 		       "Text to be echoed" :
8501 		       ((cx == XXVOID) ? "Text" :
8502 			"Application Program Command text"),
8503 		       "",
8504 		       &s,
8505 		       xxstring
8506 		       )
8507 	     ) < 0)
8508 	  return(x);
8509 	if (!s) s = "";
8510 #ifdef COMMENT
8511 /* This is to preserve the pre-8.0 behavior but it's too confusing */
8512 	x = strlen(s);
8513 	x = (x > 1) ? ((s[0] == '"' && s[x-1] == '"') ? 1 : 0) : 0;
8514 #endif /* COMMENT */
8515 	s = brstrip(s);			/* Strip braces and doublequotes */
8516 	if (cx == XXECH) {		/* ECHO */
8517 #ifndef NOSPL
8518 	    if (!fndiags || fnsuccess) {
8519 #endif /* NOSPL */
8520 #ifdef COMMENT
8521 		/* The "if (x)" business preserves previous behavior */
8522 		/* by putting back the doublequotes if they were included. */
8523 		if (x)
8524 		  printf("\"%s\"\n",s);
8525 		else
8526 #endif /* COMMENT */
8527 		  printf("%s\n",s);
8528 #ifndef NOSPL
8529 	    }
8530 #endif /* NOSPL */
8531 	} else if (cx == XXXECH) {	/* XECHO */
8532 	    if (x)
8533 	      printf("\"%s\"",s);
8534 	    else
8535 	      printf("%s",s);
8536 #ifdef UNIX
8537 	    fflush(stdout);
8538 #endif /* UNIX */
8539 	} else if (cx == XXAPC) {	/* APC */
8540 #ifdef CK_APC
8541 	    if (apcactive == APC_LOCAL ||
8542 		(apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
8543 	      return(success = 0);
8544 #endif /* CK_APC */
8545 	    if (!local) {
8546 		printf("%c_%s%c\\",ESC,s,ESC);
8547 #ifdef UNIX
8548 		fflush(stdout);
8549 #endif /* UNIX */
8550 
8551 	    } else {			/* Local mode - have connection */
8552 #ifndef NOSPL
8553 		if (ckmakxmsg(tmpbuf,	/* Form APC string in buffer */
8554 			      TMPBUFSIZ,
8555 			      ckctoa((char)ESC),
8556 			      ckctoa('_'),
8557 			      s,
8558 			      ckctoa((char)ESC),
8559 			      ckctoa('\\'),
8560 			      NULL,NULL,NULL,NULL,NULL,NULL,NULL
8561 			      ) > 0)
8562 		  return(success = dooutput(tmpbuf, XXOUT));
8563 		printf("?Too long\n");
8564 		return(-9);
8565 #else
8566 		printf("%c_%s%c\\",ESC,s,ESC);
8567 #endif /* NOSPL */
8568 	    }
8569 	}
8570 	return(success = 1);
8571     }
8572 
8573 #ifndef NOSPL
8574 /* Copy macro args from/to two levels up, used internally by _floop et al. */
8575     if (cx == XXGTA || cx == XXPTA) {	/* _GETARGS, _PUTARGS */
8576 	int x;
8577 	debug(F101,"docmd XXGTA","",XXGTA);
8578 	debug(F101,"docmd cx","",cx);
8579 	debug(F101,"docmd XXGTA maclvl","",maclvl);
8580 	x = dogta(cx);
8581 	debug(F101,"docmd dogta returns","",x);
8582 	debug(F101,"docmd dogta maclvl","",maclvl);
8583 	return(x);
8584     }
8585 #endif /* NOSPL */
8586 
8587 #ifndef NOSPL
8588 #ifdef CKCHANNELIO
8589     if (cx == XXFILE)
8590       return(dofile(cx));
8591     else if (cx == XXF_RE || cx == XXF_WR || cx == XXF_OP ||
8592 	     cx == XXF_CL || cx == XXF_SE || cx == XXF_RW ||
8593 	     cx == XXF_FL || cx == XXF_LI || cx == XXF_ST || cx == XXF_CO)
8594       return(dofile(cx));
8595 #endif /* CKCHANNELIO */
8596 
8597 /* ASK, ASKQ, READ */
8598     if (cx == XXASK  || cx == XXASKQ || cx == XXREA ||
8599 	cx == XXRDBL || cx == XXGETC || cx == XXGETK) {
8600 	return(doask(cx));
8601     }
8602 #endif /* NOSPL */
8603 
8604 #ifndef NOFRILLS
8605 #ifndef NOHELP
8606     if (cx == XXBUG) {			/* BUG */
8607 	if ((x = cmcfm()) < 0) return(x);
8608 	return(dobug());
8609     }
8610 #endif	/* NOHELP */
8611 #endif	/* NOFRILLS */
8612 
8613 #ifndef NOXFER
8614     if (cx == XXBYE) {			/* BYE */
8615 	extern int ftp_cmdlin;
8616 	if ((x = cmcfm()) < 0) return(x);
8617 
8618 #ifdef NEWFTP
8619 	if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
8620 	    extern int stayflg, ftp_fai;
8621 	    success = ftpbye();
8622 	    if (ftp_cmdlin && !stayflg && !local)
8623 	      doexit(ftp_fai ? BAD_EXIT : GOOD_EXIT,-1);
8624 	    else
8625 	      return(success);
8626 	}
8627 #endif /* NEWFTP */
8628 
8629 	if (!local) {
8630 	    printf("?No connection - use EXIT to quit.\n");
8631 	    return(-9);
8632 	}
8633 
8634 #ifdef CK_XYZ
8635 	if (protocol != PROTO_K) {
8636 	    printf("?Sorry, BYE only works with Kermit protocol\n");
8637 	    return(-9);
8638 	}
8639 #endif /* CK_XYZ */
8640 
8641 #ifdef IKS_OPTION
8642         if (
8643 #ifdef CK_XYZ
8644             protocol == PROTO_K &&
8645 #endif /* CK_XYZ */
8646             !iks_wait(KERMIT_REQ_START,1)) {
8647 	    printf(
8648 	     "?A Kermit Server is not available to process this command\n");
8649 	    return(-9);			/* Correct the return code */
8650         }
8651 #endif /* IKS_OPTION */
8652 
8653 	bye_active = 1;
8654 	sstate = setgen('L',"","","");
8655 	if (local) ttflui();		/* If local, flush tty input buffer */
8656 	return(0);
8657     }
8658 #endif /* NOXFER */
8659 
8660     if (cx == XXBEEP) {			/* BEEP */
8661         int x;
8662 #ifdef OS2
8663 	int y;
8664         if ((y = cmkey(beeptab, nbeeptab, "which kind of beep", "information",
8665 		       xxstring)) < 0 )
8666 	  return (y);
8667     	if ((x = cmcfm()) < 0) return(x);
8668         bleep((short)y);		/* y is one of the BP_ values */
8669 #else  /* OS2 */
8670     	if ((x = cmcfm()) < 0) return(x);
8671 #ifndef NOSPL
8672         bleep(BP_NOTE);
8673 #else
8674 	putchar('\07');
8675 #endif /* NOSPL */
8676 #endif /* OS2 */
8677         return(0);
8678     }
8679 
8680 #ifndef NOFRILLS
8681     if (cx == XXCLE)			/* CLEAR */
8682       return(success = doclear());
8683 #endif /* NOFRILLS */
8684 
8685     if (cx == XXCOM) {			/* COMMENT */
8686 	if ((x = cmtxt("Text of comment line","",&s,NULL)) < 0)
8687 	  return(x);
8688 	/* Don't change SUCCESS flag for this one */
8689 	return(0);
8690     }
8691 
8692 #ifndef NOLOCAL
8693     if (cx == XXCON || cx == XXCQ)	/* CONNECT or CONNECT /QUIETLY */
8694       return(doxconn(cx));
8695 #endif /* NOLOCAL */
8696 
8697 #ifndef NOFRILLS
8698 #ifdef ZCOPY
8699     if (cx == XXCPY) {			/* COPY a file */
8700 #ifdef IKSD
8701 	if (inserver && !ENABLED(en_cpy)) {
8702 	    printf("?Sorry, COPY is disabled\n");
8703 	    return(-9);
8704 	}
8705 #endif /* IKSD */
8706 #ifdef CK_APC
8707 	if (apcactive == APC_LOCAL ||
8708 	    (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
8709 	    )
8710 	  return(success = 0);
8711 #endif /* CK_APC */
8712 	return(docopy());
8713     }
8714 #endif /* ZCOPY */
8715 #ifdef NT
8716     if ( cx == XXLINK ) {
8717 #ifdef IKSD
8718         if (inserver && !ENABLED(en_cpy)) {
8719             printf("?Sorry, LINK (COPY) is disabled\n");
8720             return(-9);
8721         }
8722 #endif /* IKSD */
8723 #ifdef CK_APC
8724         if (apcactive == APC_LOCAL ||
8725             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
8726             )
8727           return(success = 0);
8728 #endif /* CK_APC */
8729         return(dolink());
8730     }
8731 #endif /* NT */
8732 #endif /* NOFRILLS */
8733 
8734     /* CD and friends */
8735     if (cx == XXCWD  || cx == XXCDUP || cx == XXBACK ||
8736 	cx == XXLCWD || cx == XXLCDU || cx == XXKCD) {
8737 #ifdef LOCUS
8738 	if (!locus) {
8739 	    if (cx == XXCWD) {
8740 #ifdef NOXFER
8741                 return(-2);
8742 #else
8743                 return(dormt(XZCWD));
8744 #endif /* NOXFER */
8745 	    } else if (cx == XXCDUP) {
8746 #ifdef NOXFER
8747                 return(-2);
8748 #else
8749                 return(dormt(XZCDU));
8750 #endif /* NOXFER */
8751             }
8752 	}
8753 #endif /* LOCUS */
8754 #ifdef IKSD
8755 	if (inserver && !ENABLED(en_cwd)) {
8756 	    printf("?Sorry, changing directories is disabled\n");
8757 	    return(-9);
8758 	}
8759 #endif /* IKSD */
8760 	return(success = docd(cx));
8761     }
8762 
8763     if (cx == XXCHK)			/* CHECK */
8764       return(success = dochk());
8765 
8766     if (cx == XXCLO) {			/* CLOSE */
8767 	x = cmkey(clstab,ncls,"\"CONNECTION\", or log or file to close",
8768 		  "connection",xxstring);
8769 	if (x == -3) {
8770 	    printf("?You must say which file or log\n");
8771 	    return(-9);
8772 	}
8773 	if (x < 0) return(x);
8774 	if ((y = cmcfm()) < 0) return(y);
8775 #ifndef NOLOCAL
8776 	if (x == 9999) {		/* CLOSE CONNECTION */
8777 	    x = clsconnx(0);
8778 	    switch (x) {
8779 	      case 0:
8780 		if (msgflg) printf("?Connection was not open\n");
8781 	      case -1:
8782 		return(0);
8783 	      case 1:
8784 		whyclosed = WC_CLOS;
8785 		return(1);
8786 	    }
8787 	    return(0);
8788 	}
8789 #endif /* NOLOCAL */
8790 	y = doclslog(x);
8791 	success = (y == 1);
8792 	return(success);
8793     }
8794 
8795 #ifndef NOSPL
8796     if (cx == XXDCL || cx == XXUNDCL) {	/* DECLARE an array */
8797 	return(dodcl(cx));
8798     }
8799 #endif /* NOSPL */
8800 
8801 #ifndef NODIAL
8802     if (cx == XXRED  || cx == XXDIAL || cx == XXPDIA ||
8803 	cx == XXANSW || cx == XXLOOK) { /* DIAL, REDIAL etc */
8804 #ifdef VMS
8805 	extern int batch;
8806 #else
8807 #ifdef UNIXOROSK
8808 	extern int backgrd;
8809 #endif /* UNIXOROSK */
8810 #endif /* VMS */
8811 	x = dodial(cx);
8812 	debug(F101,"dodial returns","",x);
8813 	if ((cx == XXDIAL || cx == XXRED || cx == XXANSW) &&
8814 	    (x > 0) &&			/* If DIAL or REDIAL succeeded */
8815 	    (dialsta != DIA_PART) &&	/* and it wasn't partial */
8816 	    (dialcon > 0)) {
8817 	    if ((dialcon == 1 ||	/* And DIAL CONNECT is ON, */
8818 		((dialcon == 2) &&	/* or DIAL CONNECT is AUTO */
8819 		 !xcmdsrc		/* and we're at top level... */
8820 #ifdef VMS
8821 		 && !batch		/* Not if running from batch */
8822 #else
8823 #ifdef UNIXOROSK
8824 		 && !backgrd		/* Not if running in background */
8825 #endif /* UNIXOROSK */
8826 #endif /* VMS */
8827 		 ))) /* Or AUTO */
8828 	      x = doconect(dialcq,	/* Then also CONNECT */
8829                            cmdlvl == 0 ? 1 : 0
8830 			   );
8831 	    if (ttchk() < 0)
8832 	      dologend();
8833 	}
8834 	return(success = x);
8835     }
8836 #endif /* NODIAL */
8837 
8838 #ifndef NOPUSH
8839 #ifdef CK_REXX
8840     if (cx == XXREXX) {			/* REXX */
8841         extern int nopush;
8842         if ( nopush )
8843           return(success=0);
8844         return(dorexx());
8845     }
8846 #endif /* CK_REXX */
8847 #endif /* NOPUSH */
8848 
8849 #ifndef NOFRILLS
8850     if (cx == XXDEL || cx == XXLDEL) {	/* DELETE */
8851 #ifdef LOCUS
8852 	if (!locus && cx != XXLDEL) {
8853 #ifdef NOXFER
8854 	    return(-2);
8855 #else
8856 	    return(dormt(XZDEL));
8857 #endif /* NOXFER */
8858         }
8859 #endif /* LOCUS */
8860 #ifdef IKSD
8861 	if (inserver && (!ENABLED(en_del)
8862 #ifdef CK_LOGIN
8863 			 || isguest
8864 #endif /* CK_LOGIN */
8865 			 )) {
8866 	    printf("?Sorry, DELETE is disabled\n");
8867 	    return(-9);
8868 	}
8869 #endif /* IKSD */
8870 #ifdef CK_APC
8871 	if ((apcactive == APC_LOCAL) ||
8872 	    ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8873 	  return(success = 0);
8874 #endif /* CK_APC */
8875 	return(dodel());
8876     }
8877 #endif /* NOFRILLS */
8878 
8879     if (cx == XXTOUC)			/* TOUCH */
8880       return(dodir(cx));
8881     if (cx == XXCHG)			/* CHANGE */
8882       return(dodir(cx));
8883 
8884     /* DIRECTORY commands */
8885 
8886     if (cx == XXDIR  || cx == XXLS || cx == XXLDIR ||
8887 	cx == XXWDIR || cx == XXHDIR) {
8888 #ifdef LOCUS
8889 	if (!locus && cx != XXLDIR) {
8890 #ifdef NOXFER
8891 	    return(-2);
8892 #else
8893 	    return(dormt(XZDIR));
8894 #endif /* NOXFER */
8895         }
8896 #endif /* LOCUS */
8897 #ifdef IKSD
8898 	if (inserver && !ENABLED(en_dir)) {
8899 	    printf("?Sorry, DIRECTORY is disabled\n");
8900 	    return(-9);
8901 	}
8902 #endif /* IKSD */
8903 	return(dodir(cx));
8904     }
8905 
8906 #ifndef NOSPL
8907     if (cx == XXELS)			/* ELSE */
8908       return(doelse());
8909 #endif /* NOSPL */
8910 
8911 #ifndef NOSERVER
8912 #ifndef NOFRILLS
8913     if (cx == XXENA || cx == XXDIS) {	/* ENABLE, DISABLE */
8914 	s = (cx == XXENA) ?
8915 	  "Server function to enable" :
8916 	    "Server function to disable";
8917 
8918 	if ((x = cmkey(enatab,nena,s,"",xxstring)) < 0) {
8919 	    if (x == -3) {
8920 		printf("?Name of server function required\n");
8921 		return(-9);
8922 	    } else return(x);
8923 	}
8924 	if ((y = cmkey(kmstab,3,"mode","both",xxstring)) < 0) {
8925 	    if (y == -3) {
8926 		printf("?Please specify remote, local, or both\n");
8927 		return(-9);
8928 	    } else return(y);
8929 	}
8930 	if (cx == XXDIS)		/* Disabling, not enabling */
8931 	  y = 3 - y;
8932 	if ((z = cmcfm()) < 0) return(z);
8933 #ifdef CK_APC
8934 	if ((apcactive == APC_LOCAL) ||
8935 	    ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8936 	  return(success = 0);
8937 #endif /* CK_APC */
8938 #ifdef IKSD
8939         /* This may seem like it duplicates the work in doenable()  */
8940         /* but this code returns failure whereas doenable() returns */
8941         /* success.                                                 */
8942         if (inserver &&
8943 #ifdef IKSDCONF
8944             iksdcf &&
8945 #endif /* IKSDCONF */
8946             (x == EN_HOS || x == EN_PRI || x == EN_MAI || x == EN_WHO ||
8947               isguest))
8948             return(success = 0);
8949 #endif /* IKSD */
8950 	return(doenable(y,x));
8951     }
8952 #endif /* NOFRILLS */
8953 #endif /* NOSERVER */
8954 
8955 #ifndef NOSPL
8956     if (cx == XXRET) {			/* RETURN */
8957 	if ((x = cmtxt("Optional return value","",&s,NULL)) < 0)
8958 	  return(x);
8959 	s = brstrip(s);			/* Strip braces */
8960 	if (cmdlvl == 0)		/* At top level, nothing happens... */
8961 	  return(success = 1);
8962 	switch (cmdstk[cmdlvl].src) {	/* Action depends on command source */
8963 	  case CMD_TF:			/* Command file */
8964 	    popclvl();			/* Pop command level */
8965 	    return(success = 1);	/* always succeeds */
8966 	  case CMD_MD:			/* Macro */
8967 	  case CMD_KB:			/* Prompt */
8968 	    return(doreturn(s));	/* Trailing text is return value. */
8969 	  default:			/* Shouldn't happen */
8970 	    return(-2);
8971 	}
8972     }
8973 #endif /* NOSPL */
8974 
8975 #ifndef NOSPL
8976     if (cx == XXOPE)			/* OPEN */
8977       return(doopen());
8978 #endif /* NOSPL */
8979 
8980 #ifndef NOSPL
8981     if (cx == XXOUT || cx == XXLNOUT) {	/* OUTPUT or LINEOUT */
8982 	if ((x = cmtxt("Text to be output","",&s,NULL)) < 0)
8983 	  return(x);
8984 #ifdef CK_APC
8985 	if ((apcactive == APC_LOCAL) ||
8986 	    ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8987 	  return(success = 0);
8988 #endif /* CK_APC */
8989 	debug(F110,"OUTPUT 1",s,0);
8990 	s = brstrip(s);			/* Strip enclosing braces, */
8991 	debug(F110,"OUTPUT 2",s,0);
8992 /*
8993   I don't think I could ever fully explain this in a million years...
8994   We have read the user's string without calling the variable-expander
8995   function.  Now, before we call it, we have to double backslashes that
8996   appear before \N, \B, \L, and \ itself, so the expander function will
8997   reduce them back to single backslashes, so when we call dooutput()...
8998   But it's more complicated than that.
8999 */
9000 	if (cmdgquo()) {		/* Only if COMMAND QUOTING ON ... */
9001 	    for (x = 0, y = 0; s[x]; x++, y++) {
9002 		if (s[x] == CMDQ) {
9003 		    char c = s[x+1];
9004 		    if (c == 'n' || c == 'N' ||
9005 			c == 'b' || c == 'B' ||
9006 			c == 'l' || c == 'L' ||
9007 			c == CMDQ)
9008 		      line[y++] = CMDQ;
9009 		}
9010 		line[y] = s[x];
9011 	    }
9012 	    line[y++] = '\0';		/* Now expand variables, etc. */
9013 	    debug(F110,"OUTPUT 3",line,0);
9014 	    s = line+y+1;
9015 	    x = LINBUFSIZ - (int) strlen(line) - 1;
9016 	    debug(F101,"OUTPUT size","",x);
9017 	    if (zzstring(line,&s,&x) < 0)
9018 	      return(success = 0);
9019 	    s = line+y+1;
9020 	    debug(F110,"OUTPUT 4",s,0);
9021 	}
9022 	success = dooutput(s,cx);
9023 	return(success);
9024     }
9025 #endif /* NOSPL */
9026 
9027 #ifdef ANYX25
9028 #ifndef IBMX25
9029     if (cx == XXPAD) {			/* PAD commands */
9030 	x = cmkey(padtab,npadc,"PAD command","",xxstring);
9031 	if (x == -3) {
9032 	    printf("?You must specify a PAD command to execute\n");
9033 	    return(-9);
9034 	}
9035 	if (x < 0) return(x);
9036 
9037 	switch (x) {
9038 	  case XYPADL:
9039 	    if (x25stat() < 0)
9040 	      printf("Sorry, you must 'set network' & 'set host' first\r\n");
9041 	    else {
9042 		x25clear();
9043 		initpad();
9044 	    }
9045 	    break;
9046 	  case XYPADS:
9047 	    if (x25stat() < 0)
9048 	      printf("Not connected\r\n");
9049 	    else {
9050 		extern int linkid, lcn;
9051 		conol("Connected thru ");
9052 		conol(ttname);
9053 		printf(", Link id %d, Logical channel number %d\r\n",
9054 		       linkid,lcn);
9055 	    }
9056 	    break;
9057 	  case XYPADR:
9058 	    if (x25stat() < 0)
9059 	      printf("Sorry, you must 'set network' & 'set host' first\r\n");
9060 	    else
9061 	      x25reset(0,0);
9062 	    break;
9063 	  case XYPADI:
9064 	    if (x25stat() < 0)
9065 	      printf("Sorry, you must 'set network' & 'set host' first\r\n");
9066 	    else
9067 	      x25intr(0);
9068 	}
9069 	return(0);
9070     }
9071 #endif /* IBMX25 */
9072 #endif /* ANYX25 */
9073 
9074 #ifndef NOSPL
9075     if (cx == XXPAU || cx == XXWAI || cx == XXMSL) /* PAUSE, WAIT, etc */
9076       return(dopaus(cx));
9077 #endif /* NOSPL */
9078 
9079 #ifndef NOFRILLS
9080     if (cx == XXPRI) {
9081 #ifdef IKSD
9082 #ifdef CK_LOGIN
9083 	if (inserver && (isguest || !ENABLED(en_pri))) {
9084 	    printf("?Sorry, printing is disabled\n");
9085 	    return(-9);
9086 	}
9087 #endif /* CK_LOGIN */
9088 #endif /* IKSD */
9089 	if ((x = cmifi("File to print","",&s,&y,xxstring)) < 0) {
9090 	    if (x == -3) {
9091 		printf("?A file specification is required\n");
9092 		return(-9);
9093 	    } else return(x);
9094 	}
9095 	if (y != 0) {
9096 	    printf("?Wildcards not allowed\n");
9097 	    return(-9);
9098 	}
9099 	ckstrncpy(line,s,LINBUFSIZ);
9100 	s = "";
9101 #ifndef NT
9102 	if ((x = cmtxt("Local print command options, or carriage return","",&s,
9103 		       xxstring)) < 0)
9104 	  return(x);
9105 #endif /* NT */
9106 	if ((x = cmcfm()) < 0)
9107 	  return(x);
9108 	return(success = (zprint(s,line) == 0) ? 1 : 0);
9109     }
9110 #endif /* NOFRILLS */
9111 
9112 #ifdef TCPSOCKET
9113 #ifndef NOPUSH
9114     if (cx == XXPNG) 			/* PING an IP host */
9115       return(doping());
9116 #endif /* NOPUSH */
9117 
9118 #ifndef NOFTP
9119     if (cx == XXFTP)			/* FTP */
9120 #ifdef SYSFTP
9121 #ifndef NOPUSH
9122       return(doftp());			/* Just runs system's ftp program */
9123 #else
9124       return(-2);
9125 #endif /* NOPUSH */
9126 #else
9127     return(doxftp());
9128 #endif /* SYSFTP */
9129 #endif /* NOFTP */
9130 #endif /* TCPSOCKET */
9131 
9132     if (cx == XXPWD || cx == XXLPWD) {	/* PWD */
9133 #ifdef OS2
9134 	char *pwp;
9135 #endif /* OS2 */
9136 	if ((x = cmcfm()) < 0)
9137 	  return(x);
9138 #ifdef LOCUS
9139 	if (!locus && cx != XXLPWD) {
9140 #ifdef NOXFER
9141 	    return(-2);
9142 #else
9143 	    return(dormt(XZPWD));
9144 #endif /* NOXFER */
9145         }
9146 #endif /* LOCUS */
9147 
9148 #ifndef MAC
9149 #ifndef OS2
9150 #ifdef UNIX
9151 	printf("%s\n",zgtdir());
9152 #else
9153 	xsystem(PWDCMD);
9154 #endif /* UNIX */
9155 	return(success = 1);		/* Blind faith */
9156 #else  /* OS2 */
9157 	if (pwp = zgtdir()) {
9158 	    if (*pwp) {
9159 #ifdef NT
9160 		line[0] = NUL;
9161 		ckGetLongPathName(pwp,line,LINBUFSIZ);
9162 		line[LINBUFSIZ-1] = NUL;
9163 		tmpbuf[0] = NUL;
9164 		GetShortPathName(pwp,tmpbuf,TMPBUFSIZ);
9165 		tmpbuf[TMPBUFSIZ-1] = NUL;
9166 		pwp = line;
9167 		if (!strcmp(line,tmpbuf)) {
9168 #endif /* NT */
9169 		    printf("%s\n",pwp);
9170 #ifdef NT
9171 		} else {
9172 		    printf("  Long name:  %s\n",line);
9173 		    printf("  Short name: %s\n",tmpbuf);
9174 		}
9175 #endif /* NT */
9176 	    }
9177 	    return(success = ((int)strlen(pwp) > 0));
9178 	} else return(success = 0);
9179 #endif /* OS2 */
9180 #else  /* MAC */
9181 	if (pwp = zgtdir()) {
9182 	    printf("%s\n",pwp);
9183 	    return(success = ((int)strlen(pwp) > 0));
9184 	} else return(success = 0);
9185 #endif /* MAC */
9186     }
9187 
9188     if (cx == XXQUI || cx == XXEXI) {	/* EXIT, QUIT */
9189 	extern int quitting;
9190 
9191 	if ((y = cmnum("exit status code",ckitoa(xitsta),10,&x,xxstring)) < 0)
9192 	  return(y);
9193 	if ((y = cmtxt("Optional EXIT message","",&s,xxstring)) < 0)
9194 	  return(y);
9195 	s = brstrip(s);
9196 	ckstrncpy(line,s,LINBUFSIZ);
9197 
9198 	if (!hupok(0))			/* Check if connection still open */
9199 	  return(success = 0);
9200 
9201 	if (line[0]) {			/* Print EXIT message if given */
9202 	    extern int exitmsg;
9203 	    switch (exitmsg) {
9204 	      case 0: break;
9205 	      case 1: printf("%s\n",(char *)line); break;
9206 	      case 2: fprintf(stderr,"%s\n",(char *)line); break;
9207 	    }
9208 	}
9209 	quitting = 1;			/* Flag that we are quitting. */
9210 
9211 #ifdef VMS
9212 	doexit(GOOD_EXIT,x);
9213 #else
9214 #ifdef OSK
9215 /* Returning any codes here makes the OS-9 shell print an error message. */
9216 	doexit(GOOD_EXIT,-1);
9217 #else
9218 #ifdef datageneral
9219         doexit(GOOD_EXIT,x);
9220 #else
9221 	doexit(x,-1);
9222 #endif /* datageneral */
9223 #endif /* OSK */
9224 #endif /* VMS */
9225     }
9226 
9227 #ifndef NOXFER
9228 #ifndef NOFRILLS
9229     if (cx == XXERR) {			/* ERROR */
9230 #ifdef CK_XYZ
9231 	if (protocol != PROTO_K) {
9232 	    printf("Sorry, E-PACKET only works with Kermit protocol\n");
9233 	    return(-9);
9234 	}
9235 #endif /* CK_XYZ */
9236 	if ((x = cmcfm()) < 0) return(x);
9237 	ttflui();
9238 	epktflg = 1;
9239 	sstate = 'a';
9240 	return(0);
9241     }
9242 #endif /* NOFRILLS */
9243 
9244     if (cx == XXFIN) {			/* FINISH */
9245 #ifdef NEWFTP
9246 	if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9247 	  return(ftpbye());
9248 #endif /* NEWFTP */
9249 #ifdef CK_XYZ
9250 	if (protocol != PROTO_K) {
9251 	    printf("Sorry, FINISH only works with Kermit protocol\n");
9252 	    return(-9);
9253 	}
9254 #endif /* CK_XYZ */
9255 	if ((x = cmcfm()) < 0) return(x);
9256 
9257 #ifdef IKS_OPTION
9258         if (
9259 #ifdef CK_XYZ
9260             protocol == PROTO_K &&
9261 #endif /* CK_XYZ */
9262             !iks_wait(KERMIT_REQ_START,1)) {
9263 	    printf(
9264               "?A Kermit Server is not available to process this command\n");
9265 	    return(-9);			/* Correct the return code */
9266         }
9267 #endif /* IKS_OPTION */
9268 
9269 	sstate = setgen('F',"","","");
9270 	if (local) ttflui();		/* If local, flush tty input buffer */
9271 	return(0);
9272     }
9273 #endif /* NOXFER */
9274 
9275 #ifndef NOSPL
9276     if (cx == XXFOR)			/* FOR loop */
9277       return(dofor());
9278 #endif /* NOSPL */
9279 
9280 #ifndef NOXFER
9281     /* GET MGET REGET RETRIEVE etc */
9282     if (cx == XXGET || cx == XXMGET || cx == XXREGET || cx == XXRETR) {
9283 #ifdef IKSD
9284 	if (inserver && !ENABLED(en_sen)) {
9285 	    printf("?Sorry, reception of files is disabled\n");
9286 	    return(-9);
9287 	}
9288 #endif /* IKSD */
9289 	return(doxget(cx));
9290     }
9291 #endif /* NOXFER */
9292 
9293 #ifndef NOSPL
9294 #ifndef NOFRILLS
9295     if (cx == XXGOK) {			/* GETOK */
9296 	return(success = doask(cx));
9297     }
9298 #endif /* NOFRILLS */
9299 #endif /* NOSPL */
9300 
9301     if (cx == XXHLP) {			/* HELP */
9302 #ifdef NOHELP
9303 	return(dohlp(XXHLP));
9304 #else
9305 	x = cmkey2(cmdtab,
9306 		   ncmd,"\nCommand or topic","help",toktab,xxstring,1+2+8);
9307 	debug(F111,"HELP command x",cmdbuf,x);
9308 	if (x == -5) {
9309 	    y = chktok(toktab);
9310 	    debug(F101,"HELP cmkey token","",y);
9311 	    /* ungword(); */
9312 	    switch (y) {
9313 #ifndef NOPUSH
9314 	      case '!':
9315 	      case '@': x = XXSHE; break;
9316 	      case '<': x = XXFUN; break;
9317 #endif /* NOPUSH */
9318 	      case '#': x = XXCOM; break;
9319 	      case ';': x = XXCOM; break;
9320 #ifndef NOSPL
9321               case '.': x = XXDEF; break;
9322 	      case ':': x = XXLBL; break;
9323 #ifndef NOSEXP
9324 	      case '(': x = XXSEXP; break;
9325 #endif /* NOSEXP */
9326 #endif /* NOSPL */
9327 #ifdef CK_RECALL
9328 	      case '^': x = XXREDO; break;
9329 #endif	/* CK_RECALL */
9330 	      default:
9331 		printf("\n?Not a valid command or token - %s\n",cmdbuf);
9332 		x = -2;
9333 	    }
9334 	}
9335 	makestr(&hlptok,atmbuf);
9336 	debug(F111,"HELP token",hlptok,x);
9337 	return(dohlp(x));
9338 #endif /* NOHELP */
9339     }
9340 
9341 #ifndef NOHELP
9342     if (cx == XXINT)			/* INTRO */
9343       return(hmsga(introtxt));
9344     if (cx == XXNEW) {			/* NEWS */
9345 	int x;
9346 	extern char * k_info_dir;
9347 	x = hmsga(newstxt);
9348 	return(x);
9349     }
9350 
9351 #ifdef OS2ONLY
9352     if (cx == XXUPD) {			/* View UPDATE file */
9353         extern char exedir[];
9354         char * pTopic;
9355         char updstr[2048];
9356         if ((x = cmtxt("topic name","",&pTopic,xxstring)) < 0)
9357             return x;
9358 #ifdef COMMENT
9359 	sprintf(updstr,
9360 		"start view %s\\docs\\k2.inf+%s\\docs\\using_ck.inf+\
9361 %s\\docs\\dialing.inf+%s\\docs\\modems.inf %s",
9362 		exedir,exedir,exedir,exedir,pTopic
9363 		);
9364 #else
9365 	if (ckmakxmsg(updstr,
9366 		     2048,
9367 		     "start view ",
9368 		     exedir,
9369 		     "\\docs\\k2.inf+",
9370 		     exedir,
9371 		     "\\docs\\using_ck.inf+",
9372 		     exedir,
9373 		     "\\docs\\dialing.inf+",
9374 		     exedir,
9375 		     "\\docs\\modems.inf ",
9376 		     pTopic,
9377 		     NULL,
9378 		     NULL
9379 		     ) > 0)
9380 #endif /* COMMENT */
9381 	  system(updstr);
9382         return(success = 1);
9383     }
9384 #endif /* OS2ONLY */
9385 #endif /* NOHELP */
9386 
9387 #ifndef NOLOCAL
9388     if (cx == XXHAN) {			/* HANGUP */
9389 	if ((x = cmcfm()) < 0) return(x);
9390 #ifdef NEWFTP
9391 	if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
9392 	  return(success = ftpbye());
9393 #endif /* NEWFTP */
9394 #ifndef NODIAL
9395 	if ((x = mdmhup()) < 1) {
9396 	    debug(F101,"HANGUP mdmup","",x);
9397 #endif /* NODIAL */
9398 	    x = tthang();
9399 	    debug(F101,"HANGUP tthang","",x);
9400 	    x = (x > -1);
9401 #ifndef NODIAL
9402 	}
9403 	dialsta = DIA_UNK;
9404 #endif /* NODIAL */
9405 	whyclosed = WC_CLOS;
9406 	ttchk();			/* In case of CLOSE-ON-DISCONNECT */
9407 	dologend();
9408 #ifdef OS2
9409 	if (x)
9410 	  DialerSend(OPT_KERMIT_HANGUP, 0);
9411 #endif /* OS2 */
9412 	if (x) haveline = 0;
9413 	return(success = x);
9414     }
9415 #endif /* NOLOCAL */
9416 
9417 #ifndef NOSPL
9418     /* INPUT, REINPUT, and MINPUT */
9419 
9420     if (cx == XXINP || cx == XXREI || cx == XXMINP) {
9421 	long zz;
9422 	int flags = 0, incount = 0;
9423 	extern int itsapattern, isjoin, isinbuflen;
9424 	int c, getval;
9425 
9426 	struct FDB sw, nu, fl;
9427 	int fc, havetime = 0;
9428 	char * m;
9429 
9430 	if (cx == XXREI) {
9431 	    m = "Timeout in seconds (ignored)";
9432 	} else {
9433 	    m = "Seconds to wait for input,\n or time of day hh:mm:ss,\
9434  or switch";
9435 	}
9436 	cmfdbi(&sw,			/* First FDB - command switches */
9437 	       _CMKEY,			/* fcode */
9438 	       m,			/* helpmsg */
9439 	       ckitoa(indef),		/* default */
9440 	       "",			/* addtl string data */
9441 	       ninputsw,		/* addtl numeric data 1: tbl size */
9442 	       4,			/* addtl numeric data 2: 4 = cmswi */
9443 	       xxstring,		/* Processing function */
9444 	       inputsw,			/* Keyword table */
9445 	       &nu			/* Pointer to next FDB */
9446 	       );
9447 	cmfdbi(&nu,
9448 	       _CMNUM,			/* Number */
9449 	       m,			/* Help message */
9450 	       ckitoa(indef),		/* default */
9451 	       "",			/* N/A */
9452 	       10,			/* Radix = 10 */
9453 	       0,			/* N/A */
9454 	       xxstring,		/* Processing function */
9455 	       NULL,			/* N/A */
9456 	       &fl			/* Next */
9457 	       );
9458 	cmfdbi(&fl,			/* Time of day hh:mm:ss */
9459 	       _CMFLD,			/* fcode */
9460 	       "",			/* hlpmsg */
9461 	       "",
9462 	       "",			/* addtl string data */
9463 	       0,			/* addtl numeric data 1 */
9464 	       0,			/* addtl numeric data 2 */
9465 	       xxstring,
9466 	       NULL,
9467 	       NULL
9468 	       );
9469 	fc = (cx == XXREI) ? cmfdb(&nu) : cmfdb(&sw); /* Parse something */
9470 
9471 	for (y = 0; y < MINPMAX; y++) {	/* Initialize search strings */
9472 	    mp[y] = 0;			/* Assume it's not a pattern */
9473 	    if (!mpinited) {
9474 		ms[y] = NULL;
9475 	    }
9476 	    if (ms[y]) {
9477 		free(ms[y]);		/* Free old strings, if any */
9478 		ms[y] = NULL;
9479 	    }
9480 	}
9481 	mpinited = 1;
9482 	while (!havetime) {
9483 	    if (fc < 0) {		/* Error */
9484 		if (fc == -3) {
9485 		    printf("?Syntax error in INPUT-class command\n");
9486 		    return(-9);
9487 		} else
9488 		  return(fc);
9489 	    }
9490 	    switch (cmresult.fcode) {
9491 	      case _CMKEY:		/* Switch */
9492 		c = cmgbrk();
9493 		if ((getval = (c == ':' || c == '=')) &&
9494 		    !(cmgkwflgs() & CM_ARG)) {
9495 		    printf("?This switch does not take an argument\n");
9496 		    return(-9);
9497 		}
9498 		if (getval && cmresult.nresult == INPSW_COU) {
9499 		    if ((y = cmnum("Number of bytes to read",
9500 				   "",10,&x,xxstring)) < 0)
9501 		      return(y);
9502 		    incount = x;
9503 		}
9504 		flags |= cmresult.nresult;
9505 		fc = cmfdb(&sw);	/* Maybe parse more switches */
9506 		continue;
9507 
9508 	      case _CMNUM:		/* Seconds to time out */
9509 		x = cmresult.nresult;
9510 #ifdef CKFLOAT
9511 		if (inscale != 1.0)	/* Scale */
9512 		  x *= inscale;
9513 #endif	/* CKFLOAT */
9514 		havetime++;
9515 		break;
9516 
9517 	      case _CMFLD:
9518 		zz = tod2sec(atmbuf);	/* Convert to secs since midnight */
9519 		if (zz < 0L) {
9520 		    printf("?Number, expression, or time of day required\n");
9521 		    return(-9);
9522 		} else {
9523 		    char now[32];	/* Current time */
9524 		    char *p;
9525 		    long tnow;
9526 		    p = now;
9527 		    ztime(&p);
9528 		    tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
9529 		    if (zz < tnow)	/* User's time before now */
9530 		      zz += 86400L;	/* So make it tomorrow */
9531 		    zz -= tnow;		/* Seconds from now. */
9532 		    if (zz > -1L) {
9533 			x = zz;
9534 			if (zz != (long) x) {
9535 			    printf(
9536 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
9537 );
9538 			    return(-9);
9539 			}
9540 		    }
9541 		    havetime++;
9542 		}
9543 		break;
9544 	      default:
9545 		printf("?Internal error\n");
9546 		return(-9);
9547 	    }
9548 	}
9549 	/* Now parse the search text */
9550 
9551 #ifdef CK_MINPUT
9552 	if (cx == XXMINP) {		/* MINPUT */
9553 	    int i, k = 0, n = 0;
9554 	    struct stringarray * q;
9555 	    keepallchars = 1;
9556 	    while (k < MINPMAX) {
9557 		if ((y = cmfld("String or pattern","",&s,xxstring)) < 0) {
9558 		    if (y == -3) {
9559 			if ((y = cmcfm()) < 0)
9560 			  return(y);
9561 			break;
9562 		    } else {
9563 			return(y);
9564 		    }
9565 		}
9566 		debug(F111,"MINPUT field",s,k);
9567 		if (isjoin) {
9568 		    if ((q = cksplit(1,0,s," ",(char *)c1chars,3,0,0,0))) {
9569 			char ** ap = q->a_head;
9570 			n = q->a_size;
9571 			debug(F101,"minput cksplit size","",n);
9572 			for (i = 1; i <= n && k < MINPMAX; i++) {
9573 			    if (!ap[i]) /* Add non-empty elements */
9574 			      continue;
9575 			    if (!*(ap[i]))
9576 			      continue;
9577 			    makestr(&(ms[k]),ap[i]);
9578 			    debug(F111,"MINPUT JOIN",ms[k],k);
9579 			    k++;
9580 			}
9581 		    }
9582 		} else {
9583 		    if (s) if (*s) {
9584 			makestr(&(ms[k]),brstrip(s));
9585 			if (itsapattern) mp[k] = 1;
9586 			debug(F111,"MINPUT",ms[k],itsapattern);
9587 			k++;
9588 		    }
9589 		}
9590 	    }
9591 	    keepallchars = 0;
9592 	} else {
9593 #endif /* CK_MINPUT */
9594 
9595 	    /* INPUT or REINPUT */
9596 
9597 	    if (flags & INPSW_COU) {
9598 		if ((y = cmcfm()) < 0)
9599 		  return(y);
9600 	    } else {
9601 		if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
9602 		  return(y);
9603 	    }
9604 	    mp[0] = itsapattern ? 1 : 0;
9605 	    makestr(&(ms[0]),brstrip(s));
9606 	    ms[1] = NULL;
9607 
9608 #ifdef CK_MINPUT
9609 	}
9610 #endif /* CK_MINPUT */
9611 
9612 	if (incount > 0)		/* No searching if /COUNT: given */
9613 	  makestr(&(ms[0]),NULL);
9614 
9615 	if (cx == XXINP || cx == XXMINP) { /* Not REINPUT... */
9616 	    i_active = 1;
9617 	    /* Go try to input the search string */
9618 	    success = doinput(x,ms,mp,flags,incount);
9619 	    i_active = 0;
9620 	} else {			/* REINPUT */
9621 	    success = doreinp(x,ms[0],itsapattern);
9622 	}
9623 	if (intime[cmdlvl] && !success) { /* TIMEOUT-ACTION = QUIT? */
9624 	    popclvl();			/* If so, pop command level. */
9625 	    if (pflag && cmdlvl == 0) {
9626 		if (cx == XXINP)  printf("?INPUT timed out\n");
9627 		if (cx == XXMINP) printf("?MINPUT timed out\n");
9628 		if (cx == XXREI)  printf("?REINPUT failed\n");
9629 	    }
9630 	}
9631 	return(success);		/* Return do(re)input's return code */
9632     }
9633 
9634 #endif /* NOSPL */
9635 
9636     if (cx == XXLOG) {			/* LOG */
9637 	x = cmkey(logtab,nlog,"What to log","",xxstring);
9638 	if (x == -3) {
9639 	    printf("?Type of log required\n");
9640 	    return(-9);
9641 	}
9642 	if (x < 0) return(x);
9643 	x = dolog(x);
9644 	if (x < 0)
9645 	  return(x);
9646 	else
9647 	  return(success = x);
9648     }
9649 
9650     if (cx == XXLOGIN) {		/* (REMOTE) LOGIN */
9651 #ifdef NEWFTP
9652 	if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9653 	  return(success = doftpusr());
9654 #endif /* NEWFTP */
9655 #ifdef IKSD
9656 	if (inserver) {
9657 	    printf("?Already logged in\n");
9658 	    return(-9);
9659 	} else
9660 #endif /* IKSD */
9661 	{
9662 #ifdef NOXFER
9663 	    return(-2);
9664 #else
9665 	    return(dormt(XZLGI));
9666 #endif /* NOXFER */
9667 	}
9668     }
9669     if (cx == XXLOGOUT) {		/* (REMOTE) LOGOUT */
9670 #ifdef NEWFTP
9671 	if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9672 	  return(success = doftpres());
9673 #endif /* NEWFTP */
9674 
9675 #ifdef IKSD
9676         if (inserver) {
9677 	    if ((x = cmcfm()) < 0)
9678 	      return(x);
9679 	    doexit(GOOD_EXIT,xitsta);
9680 	} else
9681 #endif /* IKSD */
9682 	if (!local || (network && ttchk() < 0)) {
9683 	    printf("?No connection.\n");
9684 	    return(-9);
9685 	} else {
9686 #ifdef NOXFER
9687 	    return(-2);
9688 #else
9689 	    return(dormt(XZLGO));
9690 #endif /* NOXFER */
9691 	}
9692     }
9693 
9694 #ifndef NOSCRIPT
9695     if (cx == XXLOGI) {			/* UUCP-style script */
9696 	if ((x = cmtxt("expect-send expect-send ...","",&s,xxstring)) < 0)
9697 	  return(x);
9698 #ifdef CK_APC
9699 	if ((apcactive == APC_LOCAL) ||
9700 	    ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9701 	  return(success = 0);
9702 #endif /* CK_APC */
9703 #ifdef VMS
9704 	conres();			/* For Ctrl-C to work... */
9705 #endif /* VMS */
9706 	return(success = dologin(s));	/* Return 1=completed, 0=failed */
9707     }
9708 #endif /* NOSCRIPT */
9709 
9710 #ifndef NOXFER
9711 #ifdef PIPESEND
9712     if (cx == XXCREC) {			/* CRECEIVE */
9713 	if (protocol != PROTO_K) {
9714 	    printf("?Sorry, CRECEIVE works only with Kermit protocol\n");
9715 	    return(-9);
9716 	} else
9717 	  return(doxget(cx));
9718     }
9719     if (cx == XXCGET) {			/* CGET */
9720 	return(doxget(cx));
9721     }
9722 #endif /* PIPESEND */
9723 
9724     if (cx == XXREC)			/* RECEIVE */
9725       return(doxget(cx));
9726 #endif /* NOXFER */
9727 
9728 #ifndef NOXFER
9729     if (cx == XXREM) {			/* REMOTE */
9730 #ifdef NEWFTP
9731 	if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9732 	  return(doftprmt(0,0));
9733 #endif /* NEWFTP */
9734 #ifdef CK_XYZ
9735 	if (protocol != PROTO_K) {
9736 	    printf("Sorry, REMOTE commands only work with Kermit protocol\n");
9737 	    return(-9);
9738 	}
9739 #endif /* CK_XYZ */
9740 	x = cmkey(remcmd,nrmt,"Remote Kermit server command","",xxstring);
9741 	if (x == -3) {
9742 	    printf("?You must specify a command for the remote server\n");
9743 	    return(-9);
9744 	}
9745 	return(dormt(x));
9746     }
9747 #endif /* NOXFER */
9748 
9749 #ifndef NORENAME
9750 #ifndef NOFRILLS
9751     if (cx == XXREN || cx == XXLREN) {	/* RENAME */
9752 #ifdef LOCUS
9753 	if (!locus && cx != XXLREN) {
9754 #ifdef NOXFER
9755 	    return(-2);
9756 #else
9757 	    return(dormt(XZREN));
9758 #endif /* NOXFER */
9759         }
9760 #endif /* LOCUS */
9761 #ifdef IKSD
9762 	if (inserver && (!ENABLED(en_ren)
9763 #ifdef CK_LOGIN
9764 			 || isguest
9765 #endif /* CK_LOGIN */
9766 			 )) {
9767 	    printf("?Sorry, renaming of files is disabled\n");
9768 	    return(-9);
9769 	}
9770 #endif /* IKSD */
9771 #ifdef CK_APC
9772 	if ((apcactive == APC_LOCAL) ||
9773 	    ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9774 	  return(success = 0);
9775 #endif /* CK_APC */
9776 	return(dorenam());
9777     }
9778 #endif /* NOFRILLS */
9779 #endif /* NORENAME */
9780 
9781     if (cx == XXEIGHT) {		/* EIGHTBIT */
9782 	extern int parity, cmask, cmdmsk;
9783 	if ((x = cmcfm()) < 0)
9784 	  return(x);
9785 	parity = 0;
9786 	cmask = 0xff;
9787 	cmdmsk = 0xff;
9788 	return(success = 1);
9789     }
9790 
9791 #ifndef NOXFER
9792 /* SEND, CSEND, MOVE, MAIL, and RESEND use the new common code */
9793 
9794     if (cx == XXSEN			/* SEND */
9795 #ifdef PIPESEND
9796 	|| cx == XXCSEN			/* CSEND */
9797 #endif /* PIPESEND */
9798 	|| cx == XXMOVE			/* MOVE */
9799 	|| cx == XXMAI			/* MAIL */
9800 #ifdef CK_RESEND
9801 	|| cx == XXRSEN			/* RESEND */
9802 #endif /* CK_RESEND */
9803 	) {
9804 #ifdef IKSD
9805 	if (inserver && !ENABLED(en_get)) {
9806 	    printf("?Sorry, sending files is disabled\n");
9807 	    return(-9);
9808 	}
9809 #endif /* IKSD */
9810 	return(doxsend(cx));
9811     }
9812 
9813 /* PSEND, ADD, and REMOVE use special parsing */
9814 
9815 #ifdef ADDCMD
9816     /* ADD and REMOVE */
9817     if (cx == XXADD || cx == XXREMV) {
9818 	char * m;
9819 	m = (cx == XXADD) ? "Add to which list?" : "Remove from which list?";
9820 	x = cmkey(addtab,naddtab,m,"",xxstring);
9821 	if (x < 0)
9822 	  return(x);
9823 #ifndef NOMSEND
9824 	if (x == ADD_SND)
9825 	  return(addsend(cx));
9826 	else
9827 #endif /* NOMSEND */
9828 	  return(doadd(cx,x));
9829     }
9830 #endif /* ADDCMD */
9831 
9832 #ifdef CK_RESEND
9833     if (cx == XXPSEN) {			/* PSEND */
9834 	int seekto = 0;			/* FIX THIS */
9835 
9836 	cmarg = cmarg2 = "";
9837 	x = cmifi("File to partially send", "", &s, &y, xxstring);
9838 	if (x < 0) {
9839 	    if (x == -3) {
9840 		printf("?A file specification is required\n");
9841 		return(-9);
9842 	    } else return(x);
9843 	}
9844 	nfils = -1;			/* Files come from internal list. */
9845 #ifndef NOMSEND
9846         addlist = 0;			/* Don't use SEND-LIST. */
9847         filenext = NULL;
9848 #endif /* NOMSEND */
9849 	ckstrncpy(line,s,LINBUFSIZ);	/* Save copy of string just parsed. */
9850 	debug(F110,"PSEND line",line,0);
9851 	if (y != 0) {
9852 	    printf("?Sorry, wildcards not permitted in this command\n");
9853 	    return(-9);
9854 	}
9855 	if (sizeof(int) < 4) {
9856 	    printf("?Sorry, this command needs 32-bit integers\n");
9857 	    return(-9);
9858 	}
9859 	x = cmnum("starting position (byte number)",
9860 		  "",10,&seekto,xxstring);
9861 	if (x < 0)
9862 	  return(x);
9863 	zfnqfp(s,fspeclen,fspec);	/* Get full path */
9864 	if ((x = cmtxt("Name to send it with","",&s,NULL)) < 0)
9865 	  return(x);
9866 	ckstrncpy(tmpbuf,s,TMPBUFSIZ);
9867 
9868 #ifdef IKSD
9869 	if (inserver && !ENABLED(en_get)) {
9870 	    printf("?Sorry, sending files is disabled\n");
9871 	    return(-9);
9872 	}
9873 #endif /* IKSD */
9874 #ifdef PIPESEND
9875 	if (sndfilter) {
9876 	    printf("?Sorry, no PSEND while SEND FILTER selected\n");
9877 	    return(-9);
9878 	}
9879 #endif /* PIPESEND */
9880 #ifdef CK_XYZ
9881 	if ((protocol == PROTO_X || protocol == PROTO_XC)) {
9882 	    printf("Sorry, PSEND works only with Kermit protocol\n");
9883 	    return(-9);
9884 	}
9885 #endif /* CK_XYZ */
9886 
9887 	cmarg2 = brstrip(tmpbuf);	/* Strip braces */
9888 	cmarg = line;			/* File to send */
9889 	debug(F110,"PSEND filename",cmarg,0);
9890 	debug(F110,"PSEND as-name",cmarg2,0);
9891 	sendstart = seekto;
9892 	sstate = 's';			/* Set start state to SEND */
9893 #ifndef NOMSEND
9894 	addlist = 0;
9895 	filenext = NULL;
9896 #endif /* NOMSEND */
9897 	sendmode = SM_PSEND;
9898 #ifdef MAC
9899 	what = W_SEND;
9900 	scrcreate();
9901 #endif /* MAC */
9902 	if (local) {			/* If in local mode, */
9903 	    displa = 1;			/* enable file transfer display */
9904 	}
9905 	return(0);
9906     }
9907 #endif /* CK_RESEND */
9908 #endif /* NOXFER */
9909 
9910 #ifndef NOXFER
9911 #ifndef NOMSEND
9912     if (cx == XXMSE || cx == XXMMOVE) {
9913 #ifdef NEWFTP
9914 	if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9915 	  return(doftpput(cx,0));
9916 #endif /* NEWFTP */
9917 #ifdef CK_XYZ
9918 	if (protocol == PROTO_X || protocol == PROTO_XC) {
9919 	    printf(
9920 "Sorry, you can only send one file at a time with XMODEM protocol\n"
9921 		   );
9922 	    return(-9);
9923 	}
9924 #endif /* CK_XYZ */
9925         return(doxsend(cx));
9926     }
9927 
9928 #ifdef COMMENT				/* (moved to doxsend) */
9929     if (cx == XXMSE || cx == XXMMOVE) {	/* MSEND and MMOVE commands */
9930 	nfils = 0;			/* Like getting a list of */
9931 	lp = line;			/* files on the command line */
9932 	addlist = 0;			/* Do not use SEND-LIST */
9933 	filenext = NULL;		/* Ditto ! */
9934 
9935 	while (1) {
9936 	    char *p;
9937 	    if ((x = cmifi("Names of files to send, separated by spaces","",
9938 			   &s,&y,xxstring)) < 0) {
9939 		if (x == -3) {
9940 		    if (nfils <= 0) {
9941 			printf("?A file specification is required\n");
9942 			return(-9);
9943 		    } else break;
9944 		}
9945 		return(x);
9946 	    }
9947 	    msfiles[nfils++] = lp;	/* Got one, count it, point to it, */
9948 	    p = lp;			/* remember pointer, */
9949 	    while (*lp++ = *s++)	/* and copy it into buffer */
9950 	      if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
9951 		  printf("?MSEND list too long\n");
9952 		  line[0] = NUL;
9953 		  return(-9);
9954 	      }
9955 	    debug(F111,"msfiles",msfiles[nfils-1],nfils-1);
9956 	    if (nfils == 1) *fspec = NUL; /* Take care of \v(filespec) */
9957 #ifdef ZFNQFP
9958 	    zfnqfp(p,TMPBUFSIZ,tmpbuf);
9959 	    p = tmpbuf;
9960 #endif /* ZFNQFP */
9961 	    if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
9962 		strcat(fspec,p);	/* safe */
9963 		strcat(fspec," ");	/* safe */
9964 	    } else printf("WARNING - \\v(filespec) buffer overflow\n");
9965 	}
9966 	cmlist = msfiles;		/* Point cmlist to pointer array */
9967 	cmarg2 = "";			/* No internal expansion list (yet) */
9968 	sndsrc = nfils;			/* Filenames come from cmlist */
9969 	sendmode = SM_MSEND;		/* Remember this kind of SENDing */
9970 	sstate = 's';			/* Set start state for SEND */
9971 	if (cx == XXMMOVE)		/* If MMOVE'ing, */
9972 	  moving = 1;			/*  set this flag. */
9973 #ifdef MAC
9974 	what = W_SEND;
9975 	scrcreate();
9976 #endif /* MAC */
9977 	if (local) {			/* If in local mode, */
9978 	    displa = 1;			/* turn on file transfer display */
9979 	    ttflui();			/* and flush tty input buffer. */
9980 	}
9981 	return(0);
9982     }
9983 #endif /* COMMENT */
9984 #endif /* NOMSEND */
9985 #endif /* NOXFER */
9986 
9987 #ifndef NOSERVER
9988     if (cx == XXSER) {			/* SERVER */
9989 #ifdef CK_XYZ
9990 	if (protocol != PROTO_K) {
9991 	    printf("Sorry, SERVER only works with Kermit protocol\n");
9992 	    return(-9);
9993 	}
9994 #endif /* CK_XYZ */
9995 #ifdef COMMENT
9996 /*
9997   Parse for time limit, but since we don't use it yet,
9998   the parsing is commented out.
9999 */
10000 	x_ifnum = 1;			/* Turn off internal complaints */
10001 	y = cmnum("optional time limit, seconds, or time of day as hh:mm:ss",
10002 		  "0", 10, &x, xxstring
10003 		  );
10004 	x_ifnum = 0;
10005 	if (y < 0) {
10006 	    if (y == -2) {		/* Invalid number or expression */
10007 		zz = tod2sec(atmbuf);	/* Convert to secs since midnight */
10008 		if (zz < 0L) {
10009 		    printf("?Number, expression, or time of day required\n");
10010 		    return(-9);
10011 		} else {
10012 		    char now[32];	/* Current time */
10013 		    char *p;
10014 		    long tnow;
10015 		    p = now;
10016 		    ztime(&p);
10017 		    tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
10018 		    if (zz < tnow)	/* User's time before now */
10019 		      zz += 86400L;	/* So make it tomorrow */
10020 		    zz -= tnow;		/* Seconds from now. */
10021 		}
10022 	    } else
10023 	      return(y);
10024 	}
10025 	if (zz > -1L) {
10026 	    x = zz;
10027 	    if (zz != (long) x) {
10028 		printf(
10029 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
10030 		       );
10031 		return(-9);
10032 	    }
10033 	}
10034 	if (x < 0)
10035 	  x = 0;
10036 #endif /* COMMENT */
10037 
10038 	if ((x = cmcfm()) < 0) return(x);
10039 	sstate = 'x';
10040 #ifdef MAC
10041 	what = W_RECV;
10042 	scrcreate();
10043 #endif /* MAC */
10044 	if (local) displa = 1;
10045 #ifdef AMIGA
10046 	reqoff();			/* No DOS requestors while server */
10047 #endif /* AMIGA */
10048 	return(0);
10049     }
10050 #endif /* NOSERVER */
10051 
10052     if (cx == XXSAVE) {			/* SAVE command */
10053 	x = cmkey(savtab,nsav,"option","keymap",xxstring);
10054 	if (x == -3) {
10055 	    printf("?You must specify an option to save\n");
10056 	    return(-9);
10057 	}
10058 	if (x < 0) return(x);
10059 	/* have to set success separately for each item in doprm()... */
10060 	/* actually not really, could have just had doprm return 0 or 1 */
10061 	/* and set success here... */
10062 	y = dosave(x);
10063 	if (y == -3) {
10064 	    printf("?More fields required\n");
10065 	    return(-9);
10066 	} else return(y);
10067     }
10068 
10069     if (cx == XXSET) {			/* SET command */
10070 	x = cmkey(prmtab,nprm,"Parameter","",xxstring);
10071 	if (x == -3) {
10072 	    printf("?You must specify a parameter to set\n");
10073 	    return(-9);
10074 	}
10075 	if (x < 0) return(x);
10076 	/* have to set success separately for each item in doprm()... */
10077 	/* actually not really, could have just had doprm return 0 or 1 */
10078 	/* and set success here... */
10079 	y = doprm(x,0);
10080 	if (y == -3) {
10081 	    printf("?More fields required\n");
10082 	    return(-9);
10083 	} else return(y);
10084     }
10085 
10086 #ifndef NOPUSH
10087     if (cx == XXSHE			/* SHELL (system) command */
10088 	|| cx == XXEXEC			/* exec() */
10089 	) {
10090 	int rx = 0;
10091 	char * p = NULL;
10092 	int i /* ,n */ ;
10093 #ifdef UNIXOROSK
10094 	char * args[256];
10095 #endif /* UNIXOROSK */
10096 
10097 #ifdef IKSD
10098 	if (inserver && (nopush || !ENABLED(en_hos))) {
10099 	    printf("?Sorry, host command access is disabled\n");
10100 	    return(-9);
10101 	}
10102 #endif /* IKSD */
10103 
10104 #ifdef CKEXEC
10105 	if (cx == XXEXEC) {		/* EXEC (overlay ourselves) */
10106 	    struct FDB sw, fl;
10107 	    cmfdbi(&sw,			/* First FDB - command switches */
10108 		   _CMKEY,		/* fcode */
10109 		   "Command to overlay C-Kermit\n or switch", /* hlpmsg */
10110 		   "",			/* default */
10111 		   "",			/* addtl string data */
10112 		   1,			/* addtl numeric data 1: tbl size */
10113 		   4,			/* addtl numeric data 2: 4 = cmswi */
10114 		   xxstring,		/* Processing function */
10115 		   redirsw,		/* Keyword table */
10116 		   &fl			/* Pointer to next FDB */
10117 		   );
10118 	    cmfdbi(&fl,			/* 2nd FDB - command to exec */
10119 		   _CMFLD,		/* fcode */
10120 		   "Command to overlay C-Kermit", /* hlpmsg */
10121 		   "",			/* default */
10122 		   "",			/* addtl string data */
10123 		   0,			/* addtl numeric data 1 */
10124 		   0,			/* addtl numeric data 2 */
10125 		   xxstring,
10126 		   NULL,
10127 		   NULL			/* No more after this */
10128 		   );
10129 	    while (1) {
10130 		x = cmfdb(&sw);		/* Parse something */
10131 		debug(F101,"exec cmfdb","",x);
10132 		if (x < 0)
10133 		  return(x);
10134 		/* Generalize this if we add more switches */
10135 		if (cmresult.fcode == _CMKEY) {
10136 		    rx = 1;
10137 		    continue;
10138 		}
10139 		if (cmresult.fcode == _CMFLD)
10140 		  break;
10141 		return(-2);
10142 	    }
10143 	    ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
10144 	    if (!tmpbuf[0]) {
10145 		printf("?Command required\n");
10146 		return(-9);
10147 	    }
10148 	    p = brstrip(tmpbuf);
10149 	    args[0] = NULL;		/* Set argv[0] to it */
10150 	    makestr(&args[0],p);
10151 	    for (i = 1; i < 255; i++) {	/* Get arguments for command */
10152 		if ((x = cmfld("Argument","",&s,xxstring)) < 0) {
10153 		    if (x == -3) {
10154 			if ((x = cmcfm()) < 0)
10155 			  return(x);
10156 			break;
10157 		    } else
10158 		      return(x);
10159 		}
10160 		args[i] = NULL;
10161 		s = brstrip(s);
10162 		makestr(&args[i],s);
10163 	    }
10164 	    args[i] = NULL;
10165 	} else {
10166 #endif /* CKEXEC */
10167 	    if ((x = cmtxt("System command to execute","",&s,xxstring)) < 0)
10168 	      return(x);
10169 #ifdef CKEXEC
10170 	}
10171 #endif /* CKEXEC */
10172         if (nopush)
10173           return(success = 0);
10174 #ifdef CK_APC
10175 	if (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10176 	  return(success = 0);
10177 #endif /* CK_APC */
10178 	conres();			/* Make console normal  */
10179 #ifdef OS2
10180 	if (!(s && *s)) {
10181 	    os2push();
10182             return(success = 1);
10183 	} else
10184 #endif /* OS2 */
10185 	  if (cx == XXSHE) {
10186 	      x = zshcmd(s);
10187 	      debug(F101,"RUN zshcmd code","",x);
10188 	      concb((char)escape);
10189 	      return(success = x);
10190 #ifdef CKEXEC
10191 	  } else {
10192 #ifdef DEBUG
10193 	      if (deblog) {
10194 		  debug(F111,"EXEC cmd",p,0);
10195 		  for (i = 0; i < 256 && args[i]; i++)
10196 		    debug(F111,"EXEC arg",args[i],i);
10197 	      }
10198 #endif /* DEBUG */
10199 	      if (p) {
10200 		  z_exec(p,args,rx);	/* Overlay ourself */
10201 		  debug(F100,"EXEC fails","",0);
10202 		  concb((char)escape);	/* In case it returns */
10203 	      }
10204 	      return(success = 0);
10205 #endif /* CKEXEC */
10206 	  }
10207     }
10208 
10209 #ifdef CK_REDIR
10210     if (cx == XXFUN) {			/* REDIRECT */
10211 #ifdef CK_APC
10212 	if ((apcactive == APC_LOCAL) ||
10213 	    ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
10214 	  return(success = 0);
10215 #endif /* CK_APC */
10216 	ckmakmsg(tmpbuf,
10217 		 TMPBUFSIZ,
10218 		 "Local command to run,\n",
10219 		 "with its standard input/output redirected to ",
10220 		 local ? ttname : "the communications connection",
10221 		 "\n"
10222 		 );
10223 	if ((x = cmtxt(tmpbuf,"",&s,xxstring)) < 0)
10224 	  return(x);
10225         if (nopush) {
10226             printf("?REDIRECT disabled\n");
10227             return(success=0);
10228         }
10229 	if (!local) {
10230 	    printf("?SET LINE or SET HOST required first\n");
10231 	    return(-9);
10232 	}
10233 	if (!*s) {
10234 	    printf("?REDIRECT requires a command to redirect\n");
10235 	    return(-9);
10236 	}
10237 	return(success = ttruncmd(s));
10238     }
10239 #endif /* CK_REDIR */
10240 #endif /* NOPUSH */
10241 
10242 #ifndef NOSHOW
10243     if (cx == XXSHO) {			/* SHOW */
10244 	x = cmkey(shotab,nsho,"","parameters",xxstring);
10245 	if (x < 0) return(x);
10246 	return(doshow(x));
10247     }
10248 #endif /* NOSHOW */
10249 
10250 #ifndef MAC
10251     if (cx == XXSPA) {			/* SPACE */
10252 #ifdef IKSD
10253 	if (inserver && !ENABLED(en_spa)) {
10254 	    printf("?Sorry, SPACE command disabled\n");
10255 	    return(-9);
10256 	}
10257 #endif /* IKSD */
10258 #ifdef datageneral
10259 	/* AOS/VS can take an argument after its "space" command. */
10260 	if ((x = cmtxt("Confirm, or local directory name","",&s,xxstring)) < 0)
10261 	  return(x);
10262 	if (nopush) {
10263 	    printf("?Sorry, SPACE command disabled\n");
10264 	    return(-9);
10265 	} else if (*s == NUL) {
10266 	    xsystem(SPACMD);
10267 	} else {
10268 	    ckmakmsg(line,LINBUFSIZ,"space ",s,NULL,NULL);
10269 	    xsystem(line);
10270 	}
10271 #else
10272 #ifdef OS2
10273 	if ((x = cmtxt("Press Enter for current disk,\n\
10274  or specify a disk letter like A:","",&s,xxstring)) < 0)
10275 	  return(x);
10276 	if (*s == NUL) {		/* Current disk */
10277             unsigned long space = zdskspace(0);
10278             if (space > 0 && space < 1024)
10279               printf(" Free space: unknown\n");
10280             else
10281 	      printf(" Free space: %ldK\n", space/1024L);
10282 	} else {
10283 	    int drive = toupper(*s);
10284             unsigned long space = zdskspace(drive - 'A' + 1);
10285             if (space > 0 && space < 1024)
10286               printf(" Drive %c: unknown free\n");
10287             else
10288               printf(" Drive %c: %ldK free\n", drive,space / 1024L);
10289 	}
10290 #else
10291 #ifdef UNIXOROSK
10292 	x = cmdir("Confirm for current disk,\n\
10293  or specify a disk device or directory","",&s,xxstring);
10294 	if (x == -3)
10295 	  s = "";
10296 	else if (x < 0)
10297 	  return(x);
10298         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
10299         s = tmpbuf;
10300 	if ((x = cmcfm()) < 0) return(x);
10301 	if (nopush) {
10302 	    printf("?Sorry, SPACE command disabled\n");
10303 	    return(-9);
10304 	}
10305 	if (!*s) {			/* Current disk */
10306 	    xsystem(SPACMD);
10307 	} else {			/* Specified disk */
10308 	    ckmakmsg(line,LINBUFSIZ,SPACM2," ",s,NULL);
10309 	    xsystem(line);
10310 	}
10311 #else
10312 	if ((x = cmcfm()) < 0) return(x);
10313 	if (nopush) {
10314 	    printf("?Sorry, SPACE command disabled\n");
10315 	    return(-9);
10316 	}
10317 	xsystem(SPACMD);
10318 #endif /* UNIXOROSK */
10319 #endif /* OS2 */
10320 #endif /* datageneral */
10321 	return(success = 1);		/* Pretend it worked */
10322     }
10323 #endif /* MAC */
10324 
10325 #ifndef NOXFER
10326     if (cx == XXSTA) {			/* STATISTICS */
10327 	if ((x = cmkey(stattab,2,"Carriage return, or option",
10328 		       "/brief",xxstring)) < 0)
10329 	  return(x);
10330 	if ((y = cmcfm()) < 0) return(y);
10331 	return(success = dostat(x));
10332     }
10333 #endif /* NOXFER */
10334 
10335     if (cx == XXSTO || cx == XXEND) {	/* STOP, END, or POP */
10336 	if ((y = cmnum("exit status code","0",10,&x,xxstring)) < 0)
10337 	  return(y);
10338 	if ((y = cmtxt("Message to print","",&s,xxstring)) < 0)
10339 	  return(y);
10340 	s = brstrip(s);
10341 	if (*s) printf("%s\n",s);
10342 	if (cx == XXSTO) {
10343 	    dostop();
10344 	} else {
10345 	    doend(x);
10346 	}
10347 	return(success = (x == 0));
10348     }
10349     if (cx == XXSUS) {			/* SUSPEND */
10350 	if ((y = cmcfm()) < 0) return(y);
10351 #ifdef NOJC
10352 	printf("Sorry, this version of Kermit cannot be suspended\n");
10353 #else
10354 #ifdef IKSD
10355 	if (inserver) {
10356 	    printf("?Sorry, IKSD can not be suspended\n");
10357 	    return(-9);
10358 	} else
10359 #endif /* IKSD */
10360 	  if (nopush) {
10361 	    printf("?Sorry, access to system is disabled\n");
10362 	    return(-9);
10363 	}
10364 	stptrap(0);
10365 #endif /* NOJC */
10366 	return(0);
10367     }
10368 
10369     if (cx == XXTAK) {			/* TAKE */
10370 	char * scriptenv = NULL;
10371 #ifdef OS2
10372         char * GetAppData(int);
10373 	extern char startupdir[],exedir[],inidir[];
10374 	char * keymapenv = NULL;
10375         char * appdata0 = NULL, *appdata1 = NULL;
10376 	int xx;
10377 #define TAKEPATHLEN 4096
10378 #else /* OS2 */
10379 #define TAKEPATHLEN 1024
10380 #endif /* OS2 */
10381 	char takepath[TAKEPATHLEN];
10382 
10383 	if (tlevel >= MAXTAKE-1) {
10384 	    printf("?Take files nested too deeply\n");
10385 	    return(-9);
10386 	}
10387 #ifdef OS2
10388 #ifdef NT
10389 	scriptenv = getenv("K95SCRIPTS");
10390 	keymapenv = getenv("K95KEYMAPS");
10391         makestr(&appdata0,(char *)GetAppData(0));
10392         makestr(&appdata1,(char *)GetAppData(1));
10393 #else /* NT */
10394 	scriptenv = getenv("K2SCRIPTS");
10395 	keymapenv = getenv("K2KEYMAPS");
10396 #endif /* NT */
10397 #endif /* OS2 */
10398 
10399 	if (!scriptenv)			/* Let this work for Unix etc too */
10400 	  scriptenv = getenv("CK_SCRIPTS"); /* Use this if defined */
10401 #ifndef OS2
10402 	if (!scriptenv)			/* Otherwise use home directory */
10403 	  scriptenv = homepath();
10404 #endif /* OS2 */
10405 	if (!scriptenv)
10406 	  scriptenv = "";
10407 	ckstrncpy(takepath,scriptenv,TAKEPATHLEN);
10408 	debug(F110,"TAKE initial takepath",takepath,0);
10409 
10410 #ifdef OS2
10411 	if (!keymapenv)
10412 	  keymapenv = getenv("CK_KEYMAPS");
10413 	if (!keymapenv)
10414 	  keymapenv = "";
10415 
10416 	ckstrncat(takepath,
10417 		  (scriptenv && scriptenv[strlen(scriptenv)-1]==';')?"":";",
10418 		  TAKEPATHLEN
10419 		  );
10420 	ckstrncat(takepath,keymapenv?keymapenv:"",TAKEPATHLEN);
10421 	ckstrncat(takepath,
10422 		  (keymapenv && keymapenv[strlen(keymapenv)-1]==';')?"":";",
10423 		  TAKEPATHLEN
10424 		  );
10425 	ckstrncat(takepath,startupdir,TAKEPATHLEN);
10426 	ckstrncat(takepath,";",TAKEPATHLEN);
10427 	ckstrncat(takepath,startupdir,TAKEPATHLEN);
10428 	ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10429 	ckstrncat(takepath,startupdir,TAKEPATHLEN);
10430 	ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10431 
10432 	ckstrncat(takepath,appdata1,TAKEPATHLEN);
10433 	ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
10434 	ckstrncat(takepath,appdata1,TAKEPATHLEN);
10435 	ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
10436 	ckstrncat(takepath,appdata1,TAKEPATHLEN);
10437 	ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
10438 
10439 	ckstrncat(takepath,appdata0,TAKEPATHLEN);
10440 	ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
10441 	ckstrncat(takepath,appdata0,TAKEPATHLEN);
10442 	ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
10443 	ckstrncat(takepath,appdata0,TAKEPATHLEN);
10444 	ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
10445 
10446 	ckstrncat(takepath,inidir,TAKEPATHLEN);
10447 	ckstrncat(takepath,";",TAKEPATHLEN);
10448 	ckstrncat(takepath,inidir,TAKEPATHLEN);
10449 	ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10450 	ckstrncat(takepath,inidir,TAKEPATHLEN);
10451 	ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10452 
10453 	ckstrncat(takepath,zhome(),TAKEPATHLEN);
10454 	ckstrncat(takepath,";",TAKEPATHLEN);
10455 	ckstrncat(takepath,zhome(),TAKEPATHLEN);
10456 	ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10457 	ckstrncat(takepath,zhome(),TAKEPATHLEN);
10458 	ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10459 
10460 	ckstrncat(takepath,exedir,TAKEPATHLEN);
10461 	ckstrncat(takepath,";",TAKEPATHLEN);
10462 	ckstrncat(takepath,exedir,TAKEPATHLEN);
10463 	ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10464 	ckstrncat(takepath,exedir,TAKEPATHLEN);
10465 	ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10466 #endif /* OS2 */
10467 	debug(F110,"TAKE final takepath",takepath,0);
10468 
10469 	if ((y = cmifip("Commands from file",
10470 			"",&s,&x,0,takepath,xxstring)) < 0) {
10471 	    if (y == -3) {
10472 		printf("?A file name is required\n");
10473 		return(-9);
10474 	    } else
10475 	      return(y);
10476 	}
10477 	if (x != 0) {
10478 	    printf("?Wildcards not allowed in command file name\n");
10479 	    return(-9);
10480 	}
10481 	ckstrncpy(line,s,LINBUFSIZ);
10482 	debug(F110,"TAKE file",s,0);
10483 	if (isdir(s)) {
10484 	    printf("?Can't execute a directory - \"%s\"\n", s);
10485 	    return(-9);
10486 	}
10487 #ifndef NOTAKEARGS
10488 	{
10489 	    char * p;
10490 	    x = strlen(line);
10491 	    debug(F111,"TAKE args",line,x);
10492 	    p = line + x + 1;
10493 	    if ((y = cmtxt("Optional arguments","",&s,xxstring)) < 0)
10494 	      return(y);
10495 	    if (*s) {			/* Args given? */
10496 		ckstrncpy(p,s,LINBUFSIZ-x-1);
10497 #ifdef ZFNQFP
10498 		zfnqfp(line,TMPBUFSIZ,tmpbuf);
10499 		s = tmpbuf;
10500 #else
10501 		s = line;
10502 #endif /* ZFNQFP */
10503 		debug(F110,"TAKE filename",s,0);
10504 		x = strlen(s);
10505 		debug(F101,"TAKE new len",s,x);
10506 
10507 #ifdef COMMENT
10508 /*
10509   This was added in C-Kermit 7.0 to allow args to be passed from the TAKE
10510   command to the command file.  But it overwrites the current argument vector,
10511   which is at best surprising, and at worst unsafe.
10512 */
10513 		addmac("%0",s);		/* Define %0 = name of file */
10514 		varnam[0] = '%';
10515 		varnam[2] = '\0';
10516 		debug(F110,"take arg 0",s,0);
10517 		debug(F110,"take args",p,0);
10518 		for (y = 1; y < 10; y++) { /* Clear current args %1..%9 */
10519 		    varnam[1] = (char) (y + '0');
10520 		    delmac(varnam,0);
10521 		}
10522 		xwords(p,MAXARGLIST,NULL,0); /* Assign new args */
10523 		debug(F110,"take args",p,0);
10524 #else
10525 /*
10526   This method is used in 8.0.  If the TAKE command includes arguments, we
10527   insert an intermediate temporary macro between the current level; we pass
10528   the arguments to the macro and then the macro TAKEs the command file.
10529   If the user Ctrl-C's out of the TAKE file, some temporary macro definitions
10530   and other small malloc'd bits might be left behind.
10531 */
10532 		{
10533 		    char * q = NULL;
10534 		    char * r = NULL;
10535 		    int k, m;
10536 		    m = maclvl;
10537 		    q = (char *)malloc(x+24);
10538 		    if (q) {
10539 			r = (char *)malloc(x+24);
10540 			if (r) {
10541 			    sprintf(q,"_file[%s](%d)",s,cmdlvl); /* safe */
10542 			    sprintf(r,"take %s",s); /* safe */
10543 			    k = addmac(q,r);
10544 			    if (k > -1) {
10545 				dodo(k,p,0);
10546 				while (maclvl > m) {
10547 				    sstate = (CHAR) parser(1);
10548 				    if (sstate) proto();
10549 				}
10550 			    }
10551 			    k = delmac(q,0);
10552 			    free(q);
10553 			    free(r);
10554 			    return(success);
10555 			}
10556 		    }
10557 		}
10558 		return(success = 0);
10559 #endif /* COMMENT */
10560 	    }
10561 	}
10562 #else
10563 	if ((y = cmcfm()) < 0) return(y);
10564 #endif /* NOTAKEARGS */
10565 	return(success = dotake(line));
10566     }
10567 
10568 #ifndef NOLOCAL
10569 #ifdef OS2
10570     if (cx == XXVIEW) {			/* VIEW Only Terminal mode */
10571 	viewonly = TRUE;
10572 	success = doconect(0, 0);
10573 	viewonly = FALSE;
10574 	return success;
10575     }
10576 #endif /* OS2 */
10577 
10578 #ifdef NETCONN
10579     if (cx == XXTEL || cx == XXIKSD) {	/* TELNET */
10580 	int x,z;
10581 #ifdef OS2
10582     if (!tcp_avail) {
10583         printf("?Sorry, either TCP/IP is not available on this system or\n\
10584 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
10585         success = 0;
10586         return(-9);
10587     } else
10588 #endif /* OS2 */
10589       {
10590 	  x = nettype;			/* Save net type in case of failure */
10591 	  z = ttnproto;			/* Save protocol in case of failure */
10592 	  nettype = NET_TCPB;
10593 	  ttnproto = (cx == XXTEL) ? NP_TELNET : NP_KERMIT;
10594 	  if ((y = setlin(XYHOST,0,1)) <= 0) {
10595               nettype = x;		/* Failed, restore net type. */
10596               ttnproto = z;		/* and protocol */
10597               success = 0;
10598 	  }
10599 	  didsetlin++;
10600         }
10601 	return(y);
10602     }
10603 
10604 #ifndef PTYORPIPE
10605 #ifdef NETCMD
10606 #define PTYORPIPE
10607 #else
10608 #ifdef NETPTY
10609 #define PTYORPIPE
10610 #endif /* NETPTY */
10611 #endif /* NETCMD */
10612 #endif /* PTYORPIPE */
10613 
10614 #ifdef PTYORPIPE
10615     if (cx == XXPIPE || cx == XXPTY) {	/* PIPE or PTY */
10616 	int x;
10617 	extern int netsave;
10618 	x = nettype;			/* Save net type in case of failure */
10619 	nettype = (cx == XXPIPE) ? NET_CMD : NET_PTY;
10620 	if ((y = setlin(XYHOST,0,1)) < 0) {
10621 	    nettype = x;		/* Failed, restore net type. */
10622 	    ttnproto = z;		/* and protocol */
10623 	    success = 0;
10624 	}
10625 	didsetlin++;
10626 	netsave = x;
10627 	return(y);
10628     }
10629 #endif /* PTYORPIPE */
10630 
10631 #ifdef ANYSSH
10632     if (cx == XXSSH) {			/* SSH (Secure Shell) */
10633 	extern int netsave;
10634 #ifdef SSHBUILTIN
10635 	int k, x, havehost = 0, trips = 0;
10636         int    tmpver = -1, tmpxfw = -1;
10637 #ifndef SSHTEST
10638         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
10639         extern int sl_ssh_ver, sl_ssh_ver_saved;
10640 #endif /* SSHTEST */
10641         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
10642         extern char * slmsg;
10643 	extern char uidbuf[], sl_uidbuf[];
10644         extern char pwbuf[], * g_pswd;
10645         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
10646 	struct FDB sw, kw, fl;
10647 
10648         if (ssh_tmpstr)
10649 	  memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
10650         makestr(&ssh_tmpstr,NULL);
10651         makestr(&ssh_tmpuid,NULL);
10652         makestr(&ssh_tmpcmd,NULL);
10653         makestr(&ssh_tmpport,NULL);
10654 
10655 	cmfdbi(&kw,			/* 1st FDB - commands */
10656 	       _CMKEY,			/* fcode */
10657 	       "host [ port ],\n or action",	/* hlpmsg */
10658 	       "",			/* default */
10659 	       "",			/* addtl string data */
10660 	       nsshcmd,			/* addtl numeric data 1: tbl size */
10661 	       0,			/* addtl numeric data 2: 0 = keyword */
10662 	       xxstring,		/* Processing function */
10663 	       sshkwtab,		/* Keyword table */
10664 	       &fl			/* Pointer to next FDB */
10665 	       );
10666 	cmfdbi(&fl,			/* Host */
10667 	       _CMFLD,			/* fcode */
10668 	       "",			/* hlpmsg */
10669 	       "",			/* default */
10670 	       "",			/* addtl string data */
10671 	       0,			/* addtl numeric data 1 */
10672 	       0,			/* addtl numeric data 2 */
10673 	       xxstring,
10674 	       NULL,
10675 	       NULL
10676 	       );
10677 
10678 	x = cmfdb(&kw);
10679 	if (x == -3) {
10680 	    printf("?ssh what?\n");
10681 	    return(-9);
10682 	}
10683 	if (x < 0)
10684 	  return(x);
10685 	havehost = 0;
10686 	if (cmresult.fcode == _CMFLD) {
10687 	    havehost = 1;
10688 	    ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
10689 	    cmresult.nresult = XSSH_OPN;
10690 	}
10691 	switch (cmresult.nresult) {	/* SSH keyword */
10692 	  case XSSH_OPN:		/* SSH OPEN */
10693 	    if (!havehost) {
10694 		if ((x = cmfld("Host","",&s,xxstring)) < 0)
10695 		  return(x);
10696 		ckstrncpy(line,s,LINBUFSIZ);
10697 	    }
10698 	    /* Parse [ port ] [ switches ] */
10699 	    cmfdbi(&kw,			/* Switches */
10700 		   _CMKEY,
10701 		   "Port number or service name,\nor switch",
10702 		   "",
10703 		   "",
10704 		   nsshopnsw,
10705 		   4,
10706 		   xxstring,
10707 		   sshopnsw,
10708 		   &fl
10709 		   );
10710 	    cmfdbi(&fl,			/* Port number or service name */
10711 		   _CMFLD,
10712 		   "",
10713 		   "",
10714 		   "",
10715 		   0,
10716 		   0,
10717 		   xxstring,
10718 		   NULL,
10719 		   NULL
10720 		   );
10721 	    trips = 0;			/* Explained below */
10722 	    while (1) {			/* Parse port and switches */
10723 		x = cmfdb(&kw);		/* Get a field */
10724 		if (x == -3)		/* User typed CR so quit from loop */
10725 		  break;
10726 		if (x < 0)		/* Other parse error, pass it back */
10727 		  return(x);
10728 		switch (cmresult.fcode) { /* Field or Keyword? */
10729                   case _CMFLD:		  /* Field */
10730                     makestr(&ssh_tmpport,cmresult.sresult);
10731 		    break;
10732 		  case _CMKEY:		/* Keyword */
10733 		    switch (cmresult.nresult) {	/* Which one? */
10734 		      case SSHSW_USR:	        /* /USER: */
10735 			if (!cmgbrk()) {
10736 			    printf("?This switch requires an argument\n");
10737 			    return(-9);
10738 			}
10739 			if ((y = cmfld("Username","",&s,xxstring)) < 0)
10740 			  return(y);
10741 			s = brstrip(s);
10742 			makestr(&ssh_tmpuid,s);
10743 			break;
10744                       case SSHSW_PWD:
10745 			if (!cmgbrk()) {
10746 			    printf("?This switch requires an argument\n");
10747 			    return(-9);
10748 			}
10749 			debok = 0;
10750 			if ((x = cmfld("Password","",&s,xxstring)) < 0) {
10751 			    if (x == -3) {
10752 				makestr(&ssh_tmpstr,"");
10753 			    } else {
10754 				return(x);
10755 			    }
10756 			} else {
10757 			    s = brstrip(s);
10758 			    if ((x = (int)strlen(s)) > PWBUFL) {
10759 				makestr(&slmsg,"Internal error");
10760 				printf("?Sorry, too long - max = %d\n",PWBUFL);
10761 				return(-9);
10762 			    }
10763 			    makestr(&ssh_tmpstr,s);
10764 			}
10765 			break;
10766 
10767 		      case SSHSW_VER:
10768 			if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
10769 			  return(x);
10770 			if (z < 1 || z > 2) {
10771 			    printf("?Out of range: %d\n",z);
10772 			    return(-9);
10773 			}
10774                         tmpver = z;
10775 			break;
10776 		      case SSHSW_CMD:
10777 		      case SSHSW_SUB:
10778 			if ((x = cmfld("Text","",&s,xxstring)) < 0)
10779 			  return(x);
10780                         makestr(&ssh_tmpcmd,s);
10781 			ssh_cas = (cmresult.nresult == SSHSW_SUB);
10782 			break;
10783 		      case SSHSW_X11:
10784 			if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
10785 			  return(x);
10786                         tmpxfw = x;
10787 			break;
10788 		      default:
10789 		        return(-2);
10790 		    }
10791 		}
10792 		if (trips++ == 0) {	/* After first time through */
10793 		    cmfdbi(&kw,		/* only parse switches, not port. */
10794 			   _CMKEY,
10795 			   "Switch",
10796 			   "",
10797 			   "",
10798 			   nsshopnsw,
10799 			   4,
10800 			   xxstring,
10801 			   sshopnsw,
10802 			   NULL
10803 			   );
10804 		}
10805 	    }
10806 	    if ((x = cmcfm()) < 0)	/* Get confirmation */
10807 	      return(x);
10808             if (clskconnx(1) < 0) {	/* Close current Kermit connection */
10809               if ( ssh_tmpstr ) {
10810                   memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
10811                   makestr(&ssh_tmpstr,NULL);
10812               }
10813               return(success = 0);
10814             }
10815 	    makestr(&ssh_hst,line);	/* Stash everything */
10816 	    if (ssh_tmpuid) {
10817                 if (!sl_uid_saved) {
10818                     ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
10819                     sl_uid_saved = 1;
10820                 }
10821 		ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
10822 		makestr(&ssh_tmpuid,NULL);
10823 	    }
10824             if (ssh_tmpport) {
10825                 makestr(&ssh_prt,ssh_tmpport);
10826                 makestr(&ssh_tmpport,NULL);
10827             } else
10828                 makestr(&ssh_prt,NULL);
10829 
10830             if (ssh_tmpcmd) {
10831                 makestr(&ssh_cmd,brstrip(ssh_tmpcmd));
10832                 makestr(&ssh_tmpcmd,NULL);
10833             } else
10834                 makestr(&ssh_cmd,NULL);
10835 
10836             if (tmpver > -1) {
10837 #ifndef SSHTEST
10838                 if (!sl_ssh_ver_saved) {
10839                     sl_ssh_ver = ssh_ver;
10840                     sl_ssh_ver_saved = 1;
10841                 }
10842 #endif /* SSHTEST */
10843                 ssh_ver = tmpver;
10844             }
10845             if (tmpxfw > -1) {
10846 #ifndef SSHTEST
10847                 if (!sl_ssh_xfw_saved) {
10848                     sl_ssh_xfw = ssh_xfw;
10849                     sl_ssh_xfw_saved = 1;
10850                 }
10851 #endif /* SSHTEST */
10852                 ssh_xfw = tmpxfw;
10853             }
10854 	    if (ssh_tmpstr) {
10855 		if (ssh_tmpstr[0]) {
10856 		    ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
10857 		    pwflg = 1;
10858 		    pwcrypt = 0;
10859 		} else
10860 		  pwflg = 0;
10861 		makestr(&ssh_tmpstr,NULL);
10862 	    }
10863 	    nettype = NET_SSH;
10864 	    if (mdmsav < 0)
10865 	      mdmsav = mdmtyp;
10866 	    mdmtyp = -nettype;
10867 	    x = 1;
10868 
10869 #ifndef NOSPL
10870             makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
10871             g_pflg = pwflg;                     /* and flag */
10872             g_pcpt = pwcrypt;
10873 #endif /* NOSPL */
10874 
10875 	    /* Line parameter to ttopen() is ignored */
10876 	    debug(F110,"SSH line",line,0);
10877 	    k = ttopen(line,&x,mdmtyp, 0);
10878 	    if (k < 0) {
10879 		printf("?Unable to connect to %s\n",ssh_hst);
10880 		mdmtyp = mdmsav;
10881                 slrestor();
10882 		return(success = 0);
10883 	    }
10884 	    duplex = 0;             /* Remote echo */
10885 	    ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
10886 	    debug(F110,"ssh ttname",ttname,0);
10887 	    makestr(&slmsg,NULL);	/* No SET LINE error message */
10888 	    cxtype = CXT_SSH;
10889 #ifndef NODIAL
10890 	    dialsta = DIA_UNK;
10891 #endif /* NODIAL */
10892 	    success = 1;		/* SET LINE succeeded */
10893 	    network = 1;		/* Network connection (not serial) */
10894 	    local = 1;			/* Local mode (not remote) */
10895 	    if ((reliable != SET_OFF || !setreliable))
10896 	      reliable = SET_ON;	/* Transport is reliable end to end */
10897 #ifdef OS2
10898             DialerSend(OPT_KERMIT_CONNECT, 0);
10899 #endif /* OS2 */
10900 	    setflow();			/* Set appropriate flow control */
10901 
10902 	    haveline = 1;
10903 #ifdef CKLOGDIAL
10904 #ifdef NETCONN
10905 	    dolognet();
10906 #endif /* NETCONN */
10907 #endif /* CKLOGDIAL */
10908 
10909 #ifndef NOSPL
10910 	    if (local) {
10911 		if (nmac) {		/* Any macros defined? */
10912 		    int k;		/* Yes */
10913 		    k = mlook(mactab,"on_open",nmac); /* Look this up */
10914 		    if (k >= 0) {	              /* If found, */
10915 			if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
10916 			  parser(1);		      /* and execute it */
10917 		    }
10918 		}
10919 	    }
10920 #endif /* NOSPL */
10921 #ifdef LOCUS
10922 	    if (autolocus)
10923 		setlocus(1,1);
10924 #endif /* LOCUS */
10925 
10926 	/* Command was confirmed so we can pre-pop command level. */
10927 	/* This is so CONNECT module won't think we're executing a */
10928 	/* script if CONNECT was the final command in the script. */
10929 	    if (cmdlvl > 0)
10930 	      prepop();
10931 	    success = doconect(0,cmdlvl == 0 ? 1 : 0);
10932 	    if (ttchk() < 0)
10933 	      dologend();
10934 	    return(success);
10935 
10936 	  case XSSH_CLR:
10937 	    if ((y = cmkey(sshclr,nsshclr,"","", xxstring)) < 0) {
10938 	        if (y == -3) {
10939 		    printf("?clear what?\n");
10940 		    return(-9);
10941 		}
10942 	        return(y);
10943 	    }
10944 	    if ((x = cmcfm()) < 0)
10945 	      return(x);
10946 	    switch (y) {
10947 	      case SSHC_LPF:
10948                 ssh_pf_lcl_n = 0;
10949 		break;
10950 	      case SSHC_RPF:
10951 		ssh_pf_rmt_n = 0;
10952 		break;
10953 	      default:
10954 		return(-2);
10955 	    }
10956             return(success = 1);	/* or whatever */
10957 
10958 	  case XSSH_AGT: {		/* SSH AGENT */
10959 	      int doeach = 0;
10960 	      if ((y = cmkey(sshagent,nsshagent,"","",xxstring)) < 0)
10961 		return(y);
10962 	      switch (y) {
10963 		case SSHA_ADD:		/* SSH AGENT ADD ... */
10964 		  if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
10965 #ifndef SSHTEST
10966 		      if (x == -3)	/* No name given */
10967 			doeach = 1;	/* so do them all */
10968 		      else
10969 #endif /* SSHTEST */
10970 			return(x);
10971 		  }
10972 		  ckstrncpy(line,s,LINBUFSIZ);
10973 		  if ((x = cmcfm()) < 0)
10974 		    return(x);
10975 #ifdef SSHTEST
10976 		  x = 0;
10977 #else
10978 		  if (doeach) {
10979                       int i;
10980                       x = 0;
10981                       for (i = 0; i < ssh_idf_n; i++)
10982 			x += ssh_agent_add_file(ssh_idf[i]);
10983 		  } else
10984 		    x = ssh_agent_add_file(line);
10985 #endif /* SSHTEST */
10986 		  return(success = (x == 0));
10987 
10988 		case SSHA_DEL: {	/* SSH AGENT DELETE ... */
10989 		    int doall = 0;
10990 		    if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
10991 #ifndef SSHTEST
10992 			if (x == -3)	/* No name given */
10993 			  doall = 1;	/* so do them all */
10994 			else
10995 #endif /* SSHTEST */
10996 			  return(x);
10997 		    }
10998 		    ckstrncpy(line,s,LINBUFSIZ);
10999 		    if ((x = cmcfm()) < 0)
11000 		      return(x);
11001 #ifdef SSHTEST
11002 		    x = 0;
11003 #else
11004 		    if (doall)
11005 		      x = ssh_agent_delete_all();
11006 		    else
11007 		      x = ssh_agent_delete_file(line);
11008 #endif /* SSHTEST */
11009 		    return(success = (x == 0));
11010 		}
11011 		case SSHA_LST: {
11012 		    int fingerprint = 0;
11013 		    if ((y = cmswi(sshagtsw,nsshagtsw,"","",xxstring)) < 0) {
11014 			if (y != -3)
11015 			  return(y);
11016 		    } else if (cmgbrk() > SP) {
11017 			printf("?This switch does not take an argument\n");
11018 			return(-9);
11019 		    } else if (y == SSHASW_FP) {
11020 			fingerprint = 1;
11021 		    }
11022 		    if ((x = cmcfm()) < 0)
11023 		      return(x);
11024 #ifdef SSHTEST
11025 		    return(success = 1);
11026 #else
11027 		    return(success =
11028 			   (ssh_agent_list_identities(fingerprint) == 0));
11029 #endif /* SSHTEST */
11030 		}
11031 		default:
11032 		  return(-2);
11033 	      }
11034 	  }
11035 	  case XSSH_ADD: {		/* SSH ADD */
11036 	      /* ssh add { local, remote } port host port */
11037 	      int cx, i, j, k;
11038 	      char * h;
11039 	      if ((cx = cmkey(addfwd,naddfwd,"","", xxstring)) < 0)
11040 		return(cx);
11041 	      if ((x = cmnum((cx == SSHF_LCL) ?
11042 			     "Local port number" : "Remote port number",
11043 			     "",10,&j,xxstring)) < 0)
11044 		return(x);
11045 	      if ((x = cmfld("Host","",&s,xxstring)) < 0)
11046 		return(x);
11047 	      makestr(&h,s);
11048 	      if ((x = cmnum("Port","",10,&k,xxstring)) < 0)
11049 		return(x);
11050 	      if ((x = cmcfm()) < 0)
11051 		return(x);
11052 
11053 	      switch(cx) {
11054 		case SSHF_LCL:
11055 		   if (ssh_pf_lcl_n == 32) {
11056 		       printf(
11057 "?Maximum number of local port forwardings already specified\n"
11058 			     );
11059 		       free(h);
11060 		       return(success = 0);
11061 		  }
11062 		  ssh_pf_lcl[ssh_pf_lcl_n].p1 = j;
11063 		  makestr(&(ssh_pf_lcl[ssh_pf_lcl_n].host),h);
11064 		  makestr(&h,NULL);
11065 		  ssh_pf_lcl[ssh_pf_lcl_n].p2 = k;
11066 		  ssh_pf_lcl_n++;
11067 		  break;
11068 		case SSHF_RMT:
11069 		  if (ssh_pf_rmt_n == 32) {
11070 		      printf(
11071 "?Maximum number of remote port forwardings already specified\n"
11072 			    );
11073 		      free(h);
11074 		      return(success = 0);
11075 		  }
11076 		  ssh_pf_rmt[ssh_pf_rmt_n].p1 = j;
11077 		  makestr(&(ssh_pf_rmt[ssh_pf_rmt_n].host),h);
11078 		  makestr(&h,NULL);
11079 		  ssh_pf_rmt[ssh_pf_rmt_n].p2 = k;
11080 		  ssh_pf_rmt_n++;
11081 	      }
11082 	      return(success = 1);
11083 	  }
11084 	  /* Not supporting arbitrary forwarding yet */
11085 	  case XSSH_FLP:		/* SSH FORWARD-LOCAL-PORT */
11086 	  case XSSH_FRP: {		/* SSH FORWARD-REMOTE-PORT */
11087 	      int li_port = 0;
11088 	      int to_port = 0;
11089 	      char * fw_host = NULL;
11090 	      int n;
11091               if ((x = cmnum(cmresult.nresult == XSSH_FLP ?
11092                               "local-port":"remote-port",
11093                               "",10,&li_port,xxstring)) < 0)
11094                   return(x);
11095               if (li_port < 1 || li_port > 65535) {
11096                   printf("?Out range - min: 1, max: 65535\n");
11097                   return(-9);
11098               }
11099 	      if ((x = cmfld("host",ssh_hst?ssh_hst:"",&s,xxstring)) < 0)
11100 		return(x);
11101               n = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
11102               fw_host = tmpbuf;
11103               if ((x = cmnum("host-port",ckuitoa(li_port),10,
11104                               &to_port,xxstring)) < 0)
11105                   return(x);
11106               if (to_port < 1 || to_port > 65535) {
11107                   printf("?Out range - min: 1, max: 65535\n");
11108                   return(-9);
11109               }
11110 	      if ((x = cmcfm()) < 0)
11111 		return(x);
11112 	      switch (cmresult.nresult) {
11113                 case XSSH_FLP:	/* SSH FORWARD-LOCAL-PORT */
11114 #ifndef SSHTEST
11115                   ssh_fwd_local_port(li_port,fw_host,to_port);
11116 #endif /* SSHTEST */
11117 		  return(success = 1);
11118 		case XSSH_FRP:	/* SSH FORWARD-REMOTE-PORT */
11119 #ifndef SSHTEST
11120                   ssh_fwd_remote_port(li_port,fw_host,to_port);
11121 #endif /* SSHTEST */
11122 		  return(success = 1);
11123 	      }
11124 	      return(success = 1);
11125 	  }
11126 	case XSSH_V2:		/* SSH V2 */
11127 	  if ((cx = cmkey(ssh2tab,nssh2tab,"","", xxstring)) < 0)
11128 	    return(cx);
11129 	  switch (cx) {
11130 	    case XSSH2_RKE:
11131 	      if ((x = cmcfm()) < 0)
11132 		return(x);
11133 #ifndef SSHTEST
11134 	      ssh_v2_rekey();
11135 #endif /* SSHTEST */
11136 	      return(success = 1);
11137 	    default:
11138 	      return(-2);
11139 	  }
11140 	case XSSH_KEY:
11141 	  if ((cx = cmkey(sshkey,nsshkey,"","", xxstring)) < 0)
11142 	    return(cx);
11143 	  switch (cx) {
11144 	    case SSHK_PASS: {	/* Change passphrase */
11145 	      char * oldp = NULL, * newp = NULL;
11146 	      struct FDB df, sw;
11147 	      cmfdbi(&sw,
11148 		     _CMKEY,		/* fcode */
11149 		     "Filename, or switch", /* hlpmsg */
11150 		     "",		/* default */
11151 		     "",		/* addtl string data */
11152 		     2,			/* addtl numeric data 1: tbl size */
11153 		     4,			/* addtl numeric data 2: 4 = cmswi */
11154 		     xxstring,		/* Processing function */
11155 		     sshkpsw,		/* Keyword table */
11156 		     &df		/* Pointer to next FDB */
11157 		     );
11158 	      cmfdbi(&df,		/* 2nd FDB - file for display */
11159 		     _CMIFI,		/* output file */
11160 		     "",		/* hlpmsg */
11161 		     "",		/* default */
11162 		     "",		/* addtl string data */
11163 		     0,			/* addtl numeric data 1 */
11164 		     0,			/* addtl numeric data 2 */
11165 		     xxstring,
11166 		     NULL,
11167 		     NULL
11168 		     );
11169 	      line[0] = NUL;
11170 
11171 	      while (1) {
11172 		  x = cmfdb(&sw);
11173 		  if (x == -3) break;
11174 		  if (x < 0)
11175 		    return(x);
11176 		  if (cmresult.fcode != _CMKEY)
11177 		    break;
11178 		  if (!cmgbrk()) {
11179 		      printf("?This switch requires an argument\n");
11180 		      return(-9);
11181 		  }
11182 		  if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
11183 		    return(y);
11184 		  switch (cmresult.nresult) {
11185 		    case 1:		/* Old */
11186 		      makestr(&oldp,s);
11187 		      break;
11188 		    case 2:		/* New */
11189 		      makestr(&newp,s);
11190 		  }
11191 	      }
11192 	      if (cmresult.fcode == _CMIFI) { /* Filename */
11193 		  ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
11194 		  if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
11195 		    ckstrncpy(line,tmpbuf,LINBUFSIZ);
11196 	      }
11197 	      if ((x = cmcfm()) < 0) return(x);
11198 
11199 #ifndef SSHTEST
11200 	      x = sshkey_change_passphrase(line[0] ? line : NULL,
11201 					     oldp, newp);
11202 #endif /* SSHTEST */
11203 	      makestr(&oldp,NULL);
11204 	      makestr(&newp,NULL);
11205 	      success = (x == 0);
11206 	      return(success);
11207 	    }
11208 	    case SSHK_CREA: {	/* SSH KEY CREATE /switches... */
11209 	      int bits = 1024, keytype = SSHKT_2R;
11210 	      char * pass = NULL, * comment = NULL;
11211 	      struct FDB df, sw;
11212 
11213               /*
11214                * char * sshkey_default_file(int keytype)
11215                * will provide the default filename for a given keytype
11216                * is it possible to have the default value for the 2nd
11217                * FDB set and changed when a /TYPE switch is provided?
11218                * Would this allow for tab completion of the filename?
11219                */
11220 	      cmfdbi(&sw,
11221 		     _CMKEY,		/* fcode */
11222 		     "Filename, or switch", /* hlpmsg */
11223 		     "",		/* default */
11224 		     "",		/* addtl string data */
11225 		     nsshkcrea,		/* addtl numeric data 1: tbl size */
11226 		     4,			/* addtl numeric data 2: 4 = cmswi */
11227 		     xxstring,		/* Processing function */
11228 		     sshkcrea,		/* Keyword table */
11229 		     &df		/* Pointer to next FDB */
11230 		     );
11231 	      cmfdbi(&df,		/* 2nd FDB - file for display */
11232 		     _CMOFI,		/* output file */
11233 		     "",		/* hlpmsg */
11234 		     "",		/* default */
11235 		     "",		/* addtl string data */
11236 		     0,			/* addtl numeric data 1 */
11237 		     0,			/* addtl numeric data 2 */
11238 		     xxstring,
11239 		     NULL,
11240 		     NULL
11241 		     );
11242 	      line[0] = NUL;
11243 
11244 	      while (1) {
11245 		  x = cmfdb(&sw);
11246 		  if (x == -3) break;
11247 		  if (x < 0)
11248 		    return(x);
11249 		  if (cmresult.fcode != _CMKEY)
11250 		    break;
11251 		  if (!cmgbrk()) {
11252 		      printf("?This switch requires an argument\n");
11253 		      return(-9);
11254 		  }
11255 		  switch (cmresult.nresult) {
11256 		    case SSHKC_BI:	/* /BITS:n */
11257 		      if ((y = cmnum("","1024",10,&z,xxstring)) < 0)
11258 			return(y);
11259 		      if (z < 512 || z > 4096) {
11260 			  printf("?Out range - min: 512, max: 4096\n");
11261 			  return(-9);
11262 		      }
11263 		      bits = z;
11264 		      break;
11265 		    case SSHKC_PP:	/* /PASSPHRASE:blah */
11266 		      if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
11267 			return(y);
11268 		      makestr(&pass,s);
11269 		      break;
11270 		    case SSHKC_TY:	/* /TYPE:keyword */
11271 		      if ((y = cmkey(sshkcty,nsshkcty,"",
11272 				     "v2-rsa",xxstring)) < 0)
11273 			return(y);
11274 		      keytype = y;
11275 		      break;
11276 		    case SSHKC_1R:	/* /COMMENT */
11277 		      if ((y = cmfld("Text","",&s,xxstring)) < 0)
11278 			return(y);
11279 		      makestr(&comment,s);
11280 		      break;
11281 		  }
11282 	      }
11283 	      if (cmresult.fcode == _CMOFI) { /* Filename */
11284                   if (cmresult.sresult) {
11285                       ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
11286                       if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
11287                           ckstrncpy(line,tmpbuf,LINBUFSIZ);
11288 		  }
11289 	      }
11290 	      if ((y = cmcfm()) < 0) /* Confirm */
11291 		return(y);
11292 #ifndef SSHTEST
11293 	      x = sshkey_create(line[0] ? line : NULL,
11294 				bits, pass, keytype, comment);
11295 	      if (pass)
11296 		memset(pass,0,strlen(pass));
11297 #endif /* SSHTEST */
11298 	      makestr(&pass,NULL);
11299 	      makestr(&comment,NULL);
11300 	      return(success = (x == 0));
11301 	    }
11302 	    case SSHK_DISP: {	/* SSH KEY DISPLAY /switches... */
11303 	      char c;
11304 	      int infmt = 0, outfmt = 0;
11305 	      struct FDB df, sw;
11306 	      cmfdbi(&sw,
11307 		     _CMKEY,		/* fcode */
11308 		     "Filename, or switch", /* hlpmsg */
11309 		     "",		/* default */
11310 		     "",		/* addtl string data */
11311 		     nsshdswi,		/* addtl numeric data 1: tbl size */
11312 		     4,			/* addtl numeric data 2: 4 = cmswi */
11313 		     xxstring,		/* Processing function */
11314 		     sshdswi,		/* Keyword table */
11315 		     &df		/* Pointer to next FDB */
11316 		     );
11317 	      cmfdbi(&df,		/* 2nd FDB - file for display */
11318 		     _CMIFI,		/* fcode */
11319 		     "",		/* hlpmsg */
11320 		     "",		/* default */
11321 		     "",		/* addtl string data */
11322 		     0,			/* addtl numeric data 1 */
11323 		     0,			/* addtl numeric data 2 */
11324 		     xxstring,
11325 		     NULL,
11326 		     NULL
11327 		     );
11328 	      line[0] = NUL;
11329 
11330 	      while (1) {
11331 		  x = cmfdb(&sw);
11332 		  if (x == -3) break;
11333 		  if (x < 0)
11334 		    return(x);
11335 		  if (cmresult.fcode != _CMKEY)
11336 		    break;
11337 		  if (!cmgbrk()) {
11338 		      printf("?This switch requires an argument\n");
11339 		      return(-9);
11340 		  }
11341 		  switch (cmresult.nresult) {
11342 #ifdef COMMENT
11343 		    case SSHKD_IN:	/* /IN-FORMAT: */
11344 		      if ((y = cmkey(sshdifmt,nsshdifmt,
11345 				     "","",xxstring)) < 0)
11346 			return(y);
11347 		      infmt = y;
11348 		      break;
11349 #endif /* COMMENT */
11350 		    case SSHKD_OUT:	/* /FORMAT: */
11351 		      if ((y = cmkey(sshdofmt,nsshdofmt,
11352 				     "","",xxstring)) < 0)
11353 			return(y);
11354 		      outfmt = y;
11355 		      break;
11356 		  }
11357 	      }
11358 	      if (cmresult.fcode == _CMIFI) { /* Filename */
11359 		  ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
11360 		  if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
11361 		    ckstrncpy(line,tmpbuf,LINBUFSIZ);
11362 	      }
11363 #ifdef COMMENT
11364 	      if (!line[0]) {
11365 		  printf("?Key filename required\n");
11366 		  return(-9);
11367 	      }
11368 #endif /* COMMENT */
11369 	      if ((y = cmcfm()) < 0) /* Confirm */
11370 		return(y);
11371 #ifndef SSHTEST
11372 	      switch (outfmt) {
11373 		case SKDF_OSSH:
11374                   /* 2nd param is optional passphrase */
11375 		  x = sshkey_display_public(line[0] ? line : NULL, NULL);
11376 		  break;
11377 		case SKDF_SSHC:
11378                   /* 2nd param is optional passphrase */
11379 		  x = sshkey_display_public_as_ssh2(line[0] ? line : NULL,
11380 						    NULL);
11381 		  break;
11382 		case SKDF_IETF:
11383 		  x = sshkey_display_fingerprint(line[0] ? line : NULL, 1);
11384 		  break;
11385 		case SKDF_FING:
11386 		  x = sshkey_display_fingerprint(line[0] ? line : NULL, 0);
11387 		  break;
11388 	      }
11389 #endif /* SSHTEST */
11390 	      return(success = (x == 0));
11391 	    }
11392 	    case SSHK_V1:		/* SSH KEY V1 SET-COMMENT */
11393 	      if ((x = cmkey(sshkv1,1,"","set-comment", xxstring)) < 0)
11394 		return(x);
11395 	      if (x != 1) return(-2);
11396 	      if ((x = cmifi("Key file name","",&s,&y,xxstring)) < 0) {
11397 		  if (x == -3) {
11398 		      printf("?Name of key file required\n");
11399 		      return(-9);
11400 		  }
11401 	      }
11402 	      ckstrncpy(line,s,LINBUFSIZ);
11403 	      if ((x = cmtxt("Comment text","",&s,xxstring)) < 0)
11404 		return(x);
11405 #ifndef SSHTEST
11406 	      x = sshkey_v1_change_comment(line,  /* filename */
11407 					   s,     /* new comment */
11408 					   NULL   /* passphrase */
11409 					   );
11410 #endif /* SSHTEST */
11411 	      success = (x == 0);
11412 	      return(success);
11413 	  }
11414 	  default:
11415 	    return(-2);
11416 	}
11417 #else  /* SSHBUILTIN */
11418 #ifdef SSHCMD
11419 	x = nettype;
11420 	if ((y = setlin(XXSSH,0,1)) < 0) {
11421 	    if (errno)
11422 	      printf("?%s\n",ck_errstr());
11423             else
11424 #ifdef COMMENT
11425 	    /* This isn't right either because it catches command editing */
11426 	      printf("?Sorry, pseudoterminal open failed\n");
11427             if (hints)
11428 	      printf("Hint: Try \"ssh -t %s\"\n",line);
11429 #else
11430 	      return(y);
11431 #endif /* COMMENT */
11432 	    nettype = x;		/* Failed, restore net type. */
11433 	    ttnproto = z;		/* and protocol */
11434 	    success = 0;
11435 	}
11436 	didsetlin++;
11437 	netsave = x;
11438 	return(y);
11439 #endif /* SSHCMD */
11440 #endif /* SSHBUILTIN */
11441     }
11442 #endif /* ANYSSH */
11443 
11444 #ifdef SSHBUILTIN
11445     if (cx == XXSKRM) {			/* SKERMIT (Secure Shell Kermit) */
11446 	extern int netsave;
11447 	int k, x, havehost = 0, trips = 0;
11448         int    tmpver = -1, tmpxfw = -1;
11449 #ifndef SSHTEST
11450         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
11451         extern int sl_ssh_ver, sl_ssh_ver_saved;
11452 #endif /* SSHTEST */
11453         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
11454         extern char * slmsg;
11455 	extern char uidbuf[], sl_uidbuf[];
11456         extern char pwbuf[], * g_pswd;
11457         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
11458 	struct FDB sw, kw, fl;
11459 
11460         if (ssh_tmpstr)
11461 	  memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11462         makestr(&ssh_tmpstr,NULL);
11463         makestr(&ssh_tmpuid,NULL);
11464         makestr(&ssh_tmpcmd,NULL);
11465         makestr(&ssh_tmpport,NULL);
11466 
11467 	cmfdbi(&kw,			/* 1st FDB - commands */
11468 	       _CMKEY,			/* fcode */
11469 	       "host [ port ],\n or action", /* hlpmsg */
11470 	       "",			/* default */
11471 	       "",			/* addtl string data */
11472 	       nsshkermit,		/* addtl numeric data 1: tbl size */
11473 	       0,			/* addtl numeric data 2: 0 = keyword */
11474 	       xxstring,		/* Processing function */
11475 	       sshkermit,		/* Keyword table */
11476 	       &fl			/* Pointer to next FDB */
11477 	       );
11478 	cmfdbi(&fl,			/* Host */
11479 	       _CMFLD,			/* fcode */
11480 	       "",			/* hlpmsg */
11481 	       "",			/* default */
11482 	       "",			/* addtl string data */
11483 	       0,			/* addtl numeric data 1 */
11484 	       0,			/* addtl numeric data 2 */
11485 	       xxstring,
11486 	       NULL,
11487 	       NULL
11488 	       );
11489 
11490 	x = cmfdb(&kw);
11491 	if (x == -3) {
11492 	    printf("?skermit what?\n");
11493 	    return(-9);
11494 	}
11495 	if (x < 0)
11496 	  return(x);
11497 	havehost = 0;
11498 	if (cmresult.fcode == _CMFLD) {
11499 	    havehost = 1;
11500 	    ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
11501 	    cmresult.nresult = SKRM_OPN;
11502 	}
11503 	switch (cmresult.nresult) {	/* SSH keyword */
11504 	  case SKRM_OPN:		/* SSH OPEN */
11505 	    if (!havehost) {
11506 		if ((x = cmfld("Host","",&s,xxstring)) < 0)
11507 		  return(x);
11508 		ckstrncpy(line,s,LINBUFSIZ);
11509 	    }
11510 	    /* Parse [ port ] [ switches ] */
11511 	    cmfdbi(&kw,			/* Switches */
11512 		   _CMKEY,
11513 		   "Port number or service name,\nor switch",
11514 		   "",
11515 		   "",
11516 		   nsshkrmopnsw,
11517 		   4,
11518 		   xxstring,
11519 		   sshkrmopnsw,
11520 		   &fl
11521 		   );
11522 	    cmfdbi(&fl,			/* Port number or service name */
11523 		   _CMFLD,
11524 		   "",
11525 		   "",
11526 		   "",
11527 		   0,
11528 		   0,
11529 		   xxstring,
11530 		   NULL,
11531 		   NULL
11532 		   );
11533 	    trips = 0;			/* Explained below */
11534 	    while (1) {			/* Parse port and switches */
11535 		x = cmfdb(&kw);		/* Get a field */
11536 		if (x == -3)		/* User typed CR so quit from loop */
11537 		  break;
11538 		if (x < 0)		/* Other parse error, pass it back */
11539 		  return(x);
11540 		switch (cmresult.fcode) { /* Field or Keyword? */
11541                   case _CMFLD:		  /* Field */
11542                     makestr(&ssh_tmpport,cmresult.sresult);
11543 		    break;
11544 		  case _CMKEY:		/* Keyword */
11545 		    switch (cmresult.nresult) {	/* Which one? */
11546 		      case SSHSW_USR:	        /* /USER: */
11547 			if (!cmgbrk()) {
11548 			    printf("?This switch requires an argument\n");
11549 			    return(-9);
11550 			}
11551 			if ((y = cmfld("Username","",&s,xxstring)) < 0)
11552 			  return(y);
11553 			s = brstrip(s);
11554 			makestr(&ssh_tmpuid,s);
11555 			break;
11556                       case SSHSW_PWD:
11557 			if (!cmgbrk()) {
11558 			    printf("?This switch requires an argument\n");
11559 			    return(-9);
11560 			}
11561 			debok = 0;
11562 			if ((x = cmfld("Password","",&s,xxstring)) < 0) {
11563 			    if (x == -3) {
11564 				makestr(&ssh_tmpstr,"");
11565 			    } else {
11566 				return(x);
11567 			    }
11568 			} else {
11569 			    s = brstrip(s);
11570 			    if ((x = (int)strlen(s)) > PWBUFL) {
11571 				makestr(&slmsg,"Internal error");
11572 				printf("?Sorry, too long - max = %d\n",PWBUFL);
11573 				return(-9);
11574 			    }
11575 			    makestr(&ssh_tmpstr,s);
11576 			}
11577 			break;
11578 
11579                     case SSHSW_VER:
11580 			if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
11581 			  return(x);
11582 			if (z < 1 || z > 2) {
11583 			    printf("?Out of range: %d\n",z);
11584 			    return(-9);
11585 			}
11586                         tmpver = z;
11587 			break;
11588                     default:
11589                         return(-2);
11590 		    }
11591                   }
11592 		if (trips++ == 0) {	/* After first time through */
11593 		    cmfdbi(&kw,		/* only parse switches, not port. */
11594 			   _CMKEY,
11595 			   "Switch",
11596 			   "",
11597 			   "",
11598 			   nsshkrmopnsw,
11599 			   4,
11600 			   xxstring,
11601 			   sshkrmopnsw,
11602 			   NULL
11603 			   );
11604 		}
11605 	    }
11606 	    if ((x = cmcfm()) < 0)	/* Get confirmation */
11607 	      return(x);
11608               if (clskconnx(1) < 0) {	/* Close current Kermit connection */
11609                   if ( ssh_tmpstr ) {
11610                       memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11611                       makestr(&ssh_tmpstr,NULL);
11612                   }
11613                   return(success = 0);
11614               }
11615               makestr(&ssh_hst,line);	/* Stash everything */
11616               if (ssh_tmpuid) {
11617                   if (!sl_uid_saved) {
11618                       ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
11619                       sl_uid_saved = 1;
11620                   }
11621                   ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
11622                   makestr(&ssh_tmpuid,NULL);
11623               }
11624               if (ssh_tmpport) {
11625                   makestr(&ssh_prt,ssh_tmpport);
11626                   makestr(&ssh_tmpport,NULL);
11627               } else
11628                   makestr(&ssh_prt,NULL);
11629 
11630               /* Set the Subsystem to Kermit */
11631               ssh_cas = 1;
11632               makestr(&ssh_cmd,"kermit");
11633 
11634               if (tmpver > -1) {
11635 #ifndef SSHTEST
11636                   if (!sl_ssh_ver_saved) {
11637                       sl_ssh_ver = ssh_ver;
11638                       sl_ssh_ver_saved = 1;
11639                   }
11640 #endif /* SSHTEST */
11641                   ssh_ver = tmpver;
11642               }
11643               /* Disable X11 Forwarding */
11644 #ifndef SSHTEST
11645               if (!sl_ssh_xfw_saved) {
11646                   sl_ssh_xfw = ssh_xfw;
11647                   sl_ssh_xfw_saved = 1;
11648               }
11649 #endif /* SSHTEST */
11650               ssh_xfw = 0;
11651 
11652               if (ssh_tmpstr) {
11653                   if (ssh_tmpstr[0]) {
11654                       ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
11655                       pwflg = 1;
11656                       pwcrypt = 0;
11657                   } else
11658                       pwflg = 0;
11659                   makestr(&ssh_tmpstr,NULL);
11660               }
11661               nettype = NET_SSH;
11662               if (mdmsav < 0)
11663                   mdmsav = mdmtyp;
11664               mdmtyp = -nettype;
11665               x = 1;
11666 
11667 #ifndef NOSPL
11668             makestr(&g_pswd,pwbuf);	/* Save global pwbuf */
11669             g_pflg = pwflg;		/* and flag */
11670             g_pcpt = pwcrypt;
11671 #endif /* NOSPL */
11672 
11673 	    /* Line parameter to ttopen() is ignored */
11674 	    k = ttopen(line,&x,mdmtyp, 0);
11675 	    if (k < 0) {
11676 		printf("?Unable to connect to %s\n",ssh_hst);
11677 		mdmtyp = mdmsav;
11678                 slrestor();
11679 		return(success = 0);
11680 	    }
11681 	    duplex = 0;             /* Remote echo */
11682 	    ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
11683 	    debug(F110,"ssh ttname",ttname,0);
11684 	    makestr(&slmsg,NULL);	/* No SET LINE error message */
11685 	    cxtype = CXT_SSH;
11686 #ifndef NODIAL
11687 	    dialsta = DIA_UNK;
11688 #endif /* NODIAL */
11689 	    success = 1;		/* SET LINE succeeded */
11690 	    network = 1;		/* Network connection (not serial) */
11691 	    local = 1;			/* Local mode (not remote) */
11692 	    if ((reliable != SET_OFF || !setreliable))
11693 	      reliable = SET_ON;	/* Transport is reliable end to end */
11694 #ifdef OS2
11695             DialerSend(OPT_KERMIT_CONNECT, 0);
11696 #endif /* OS2 */
11697 	    setflow();			/* Set appropriate flow control */
11698 
11699 	    haveline = 1;
11700 #ifdef CKLOGDIAL
11701 #ifdef NETCONN
11702 	    dolognet();
11703 #endif /* NETCONN */
11704 #endif /* CKLOGDIAL */
11705 
11706 #ifndef NOSPL
11707 	    if (local) {
11708 		if (nmac) {		/* Any macros defined? */
11709 		    int k;		/* Yes */
11710 		    k = mlook(mactab,"on_open",nmac); /* Look this up */
11711 		    if (k >= 0) {	              /* If found, */
11712 			if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
11713 			  parser(1);		      /* and execute it */
11714 		    }
11715 		}
11716 	    }
11717 #endif /* NOSPL */
11718 #ifdef LOCUS
11719 	    if (autolocus)
11720 		setlocus(1,1);
11721 #endif /* LOCUS */
11722 
11723 	/* Command was confirmed so we can pre-pop command level. */
11724 	/* This is so CONNECT module won't think we're executing a */
11725 	/* script if CONNECT was the final command in the script. */
11726 	    if (cmdlvl > 0)
11727 	      prepop();
11728 	    return(success = 1);
11729 
11730 	  default:
11731 	    return(-2);
11732 	}
11733     }
11734 #endif /* SSHBUILTIN */
11735 
11736 #ifdef SFTP_BUILTIN
11737     if (cx == XXSFTP) {			/* SFTP (Secure Shell File Transfer) */
11738 	extern int netsave;
11739 	int k, x, havehost = 0, trips = 0;
11740         int    tmpver = -1, tmpxfw = -1;
11741 #ifndef SSHTEST
11742         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
11743         extern int sl_ssh_ver, sl_ssh_ver_saved;
11744 #endif /* SSHTEST */
11745         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
11746         extern char * slmsg;
11747 	extern char uidbuf[], sl_uidbuf[];
11748         extern char pwbuf[], * g_pswd;
11749         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
11750 	struct FDB sw, kw, fl;
11751 
11752         if (ssh_tmpstr)
11753 	  memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11754         makestr(&ssh_tmpstr,NULL);
11755         makestr(&ssh_tmpuid,NULL);
11756         makestr(&ssh_tmpcmd,NULL);
11757         makestr(&ssh_tmpport,NULL);
11758 
11759 	cmfdbi(&kw,			/* 1st FDB - commands */
11760 	       _CMKEY,			/* fcode */
11761 	       "host [ port ],\n or action", /* hlpmsg */
11762 	       "",			/* default */
11763 	       "",			/* addtl string data */
11764 	       nsftpkwtab,		/* addtl numeric data 1: tbl size */
11765 	       0,			/* addtl numeric data 2: 0 = keyword */
11766 	       xxstring,		/* Processing function */
11767 	       sftpkwtab,		/* Keyword table */
11768 	       &fl			/* Pointer to next FDB */
11769 	       );
11770 	cmfdbi(&fl,			/* Host */
11771 	       _CMFLD,			/* fcode */
11772 	       "",			/* hlpmsg */
11773 	       "",			/* default */
11774 	       "",			/* addtl string data */
11775 	       0,			/* addtl numeric data 1 */
11776 	       0,			/* addtl numeric data 2 */
11777 	       xxstring,
11778 	       NULL,
11779 	       NULL
11780 	       );
11781 
11782 	x = cmfdb(&kw);
11783 	if (x == -3) {
11784 	    printf("?sftp what?\n");
11785 	    return(-9);
11786 	}
11787 	if (x < 0)
11788 	  return(x);
11789 	havehost = 0;
11790 	if (cmresult.fcode == _CMFLD) {
11791 	    havehost = 1;
11792 	    ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
11793 	    cmresult.nresult = SFTP_OPN;
11794 	}
11795 	switch (cmresult.nresult) {	/* SFTP keyword */
11796 	  case SFTP_OPN:		/* SFTP OPEN */
11797 	    if (!havehost) {
11798 		if ((x = cmfld("Host","",&s,xxstring)) < 0)
11799 		  return(x);
11800 		ckstrncpy(line,s,LINBUFSIZ);
11801 	    }
11802 	    /* Parse [ port ] [ switches ] */
11803 	    cmfdbi(&kw,			/* Switches */
11804 		   _CMKEY,
11805 		   "Port number or service name,\nor switch",
11806 		   "",
11807 		   "",
11808 		   nsshkrmopnsw,
11809 		   4,
11810 		   xxstring,
11811 		   sshkrmopnsw,
11812 		   &fl
11813 		   );
11814 	    cmfdbi(&fl,			/* Port number or service name */
11815 		   _CMFLD,
11816 		   "",
11817 		   "",
11818 		   "",
11819 		   0,
11820 		   0,
11821 		   xxstring,
11822 		   NULL,
11823 		   NULL
11824 		   );
11825 	    trips = 0;			/* Explained below */
11826 	    while (1) {			/* Parse port and switches */
11827 		x = cmfdb(&kw);		/* Get a field */
11828 		if (x == -3)		/* User typed CR so quit from loop */
11829 		  break;
11830 		if (x < 0)		/* Other parse error, pass it back */
11831 		  return(x);
11832 		switch (cmresult.fcode) { /* Field or Keyword? */
11833                   case _CMFLD:		  /* Field */
11834                     makestr(&ssh_tmpport,cmresult.sresult);
11835 		    break;
11836 		  case _CMKEY:		/* Keyword */
11837 		    switch (cmresult.nresult) {	/* Which one? */
11838 		      case SSHSW_USR:	        /* /USER: */
11839 			if (!cmgbrk()) {
11840 			    printf("?This switch requires an argument\n");
11841 			    return(-9);
11842 			}
11843 			if ((y = cmfld("Username","",&s,xxstring)) < 0)
11844 			  return(y);
11845 			s = brstrip(s);
11846 			makestr(&ssh_tmpuid,s);
11847 			break;
11848                       case SSHSW_PWD:
11849 			if (!cmgbrk()) {
11850 			    printf("?This switch requires an argument\n");
11851 			    return(-9);
11852 			}
11853 			debok = 0;
11854 			if ((x = cmfld("Password","",&s,xxstring)) < 0) {
11855 			    if (x == -3) {
11856 				makestr(&ssh_tmpstr,"");
11857 			    } else {
11858 				return(x);
11859 			    }
11860 			} else {
11861 			    s = brstrip(s);
11862 			    if ((x = (int)strlen(s)) > PWBUFL) {
11863 				makestr(&slmsg,"Internal error");
11864 				printf("?Sorry, too long - max = %d\n",PWBUFL);
11865 				return(-9);
11866 			    }
11867 			    makestr(&ssh_tmpstr,s);
11868 			}
11869 			break;
11870 
11871                     case SSHSW_VER:
11872 			if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
11873 			  return(x);
11874 			if (z < 1 || z > 2) {
11875 			    printf("?Out of range: %d\n",z);
11876 			    return(-9);
11877 			}
11878                         tmpver = z;
11879 			break;
11880                     default:
11881                         return(-2);
11882 		    }
11883 		}
11884 		if (trips++ == 0) {	/* After first time through */
11885 		    cmfdbi(&kw,		/* only parse switches, not port. */
11886 			   _CMKEY,
11887 			   "Switch",
11888 			   "",
11889 			   "",
11890 			   nsshkrmopnsw,
11891 			   4,
11892 			   xxstring,
11893 			   sshkrmopnsw,
11894 			   NULL
11895 			   );
11896 		}
11897 	    }
11898 	    if ((x = cmcfm()) < 0)	/* Get confirmation */
11899 	      return(x);
11900               if (clskconnx(1) < 0) {	/* Close current Kermit connection */
11901                   if ( ssh_tmpstr ) {
11902                       memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11903                       makestr(&ssh_tmpstr,NULL);
11904                   }
11905                   return(success = 0);
11906               }
11907               makestr(&ssh_hst,line);	/* Stash everything */
11908               if (ssh_tmpuid) {
11909                   if (!sl_uid_saved) {
11910                       ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
11911                       sl_uid_saved = 1;
11912                   }
11913                   ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
11914                   makestr(&ssh_tmpuid,NULL);
11915               }
11916               if (ssh_tmpport) {
11917                   makestr(&ssh_prt,ssh_tmpport);
11918                   makestr(&ssh_tmpport,NULL);
11919               } else
11920                   makestr(&ssh_prt,NULL);
11921 
11922               /* Set the Subsystem to Kermit */
11923               ssh_cas = 1;
11924               makestr(&ssh_cmd,"sftp");
11925 
11926               if (tmpver > -1) {
11927 #ifndef SSHTEST
11928                   if (!sl_ssh_ver_saved) {
11929                       sl_ssh_ver = ssh_ver;
11930                       sl_ssh_ver_saved = 1;
11931                   }
11932 #endif /* SSHTEST */
11933                   ssh_ver = tmpver;
11934               }
11935               /* Disable X11 Forwarding */
11936 #ifndef SSHTEST
11937               if (!sl_ssh_xfw_saved) {
11938                   sl_ssh_xfw = ssh_xfw;
11939                   sl_ssh_xfw_saved = 1;
11940               }
11941 #endif /* SSHTEST */
11942               ssh_xfw = 0;
11943 
11944               if (ssh_tmpstr) {
11945                   if (ssh_tmpstr[0]) {
11946                       ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
11947                       pwflg = 1;
11948                       pwcrypt = 0;
11949                   } else
11950                       pwflg = 0;
11951                   makestr(&ssh_tmpstr,NULL);
11952               }
11953               nettype = NET_SSH;
11954               if (mdmsav < 0)
11955                   mdmsav = mdmtyp;
11956               mdmtyp = -nettype;
11957               x = 1;
11958 
11959 #ifndef NOSPL
11960             makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
11961             g_pflg = pwflg;                     /* and flag */
11962             g_pcpt = pwcrypt;
11963 #endif /* NOSPL */
11964 
11965 	    /* Line parameter to ttopen() is ignored */
11966 	    k = ttopen(line,&x,mdmtyp, 0);
11967 	    if (k < 0) {
11968 		printf("?Unable to connect to %s\n",ssh_hst);
11969 		mdmtyp = mdmsav;
11970                 slrestor();
11971 		return(success = 0);
11972 	    }
11973 	    duplex = 0;             /* Remote echo */
11974 	    ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
11975 	    debug(F110,"ssh ttname",ttname,0);
11976 	    makestr(&slmsg,NULL);	/* No SET LINE error message */
11977 	    cxtype = CXT_SSH;
11978 #ifndef NODIAL
11979 	    dialsta = DIA_UNK;
11980 #endif /* NODIAL */
11981 	    success = 1;		/* SET LINE succeeded */
11982 	    network = 1;		/* Network connection (not serial) */
11983 	    local = 1;			/* Local mode (not remote) */
11984 	    if ((reliable != SET_OFF || !setreliable))
11985 	      reliable = SET_ON;	/* Transport is reliable end to end */
11986 #ifdef OS2
11987             DialerSend(OPT_KERMIT_CONNECT, 0);
11988 #endif /* OS2 */
11989 	    setflow();			/* Set appropriate flow control */
11990 
11991 	    haveline = 1;
11992 #ifdef CKLOGDIAL
11993 #ifdef NETCONN
11994 	    dolognet();
11995 #endif /* NETCONN */
11996 #endif /* CKLOGDIAL */
11997 
11998 #ifndef NOSPL
11999 	    if (local) {
12000 		if (nmac) {		/* Any macros defined? */
12001 		    int k;		/* Yes */
12002 		    k = mlook(mactab,"on_open",nmac); /* Look this up */
12003 		    if (k >= 0) {	              /* If found, */
12004 			if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
12005 			  parser(1);		      /* and execute it */
12006 		    }
12007 		}
12008 	    }
12009 #endif /* NOSPL */
12010 #ifdef LOCUS
12011 	    if (autolocus)
12012 		setlocus(1,1);
12013 #endif /* LOCUS */
12014 
12015 	/* Command was confirmed so we can pre-pop command level. */
12016 	/* This is so CONNECT module won't think we're executing a */
12017 	/* script if CONNECT was the final command in the script. */
12018 	    if (cmdlvl > 0)
12019 	      prepop();
12020 
12021             success = sftp_do_init();
12022 	    return(success = 1);
12023 
12024 	  case SFTP_CD:
12025 	  case SFTP_CHGRP:
12026 	  case SFTP_CHMOD:
12027 	  case SFTP_CHOWN:
12028 	  case SFTP_RM:
12029 	  case SFTP_DIR:
12030 	  case SFTP_GET:
12031 	  case SFTP_MKDIR:
12032 	  case SFTP_PUT:
12033 	  case SFTP_PWD:
12034 	  case SFTP_REN:
12035 	  case SFTP_RMDIR:
12036 	  case SFTP_LINK:
12037 	  case SFTP_VER:
12038 	    if ((y = cmtxt("command parameters","",&s,xxstring)) < 0)
12039 	      return(y);
12040 	    if (ssh_tchk() < 0 || !ssh_cas || strcmp(ssh_cmd,"sftp")) {
12041 		printf("?Not connected to SFTP Service\n");
12042 		return(success = 0);
12043 	    }
12044 	    success = sftp_do_cmd(cmresult.nresult,s);
12045 	    return(success);
12046 	  default:
12047 	    return(-2);
12048 	}
12049     }
12050 #endif /* SFTP_BUILTIN */
12051 
12052     if (cx == XXRLOG) {			/* RLOGIN */
12053 #ifdef RLOGCODE
12054 	int x,z;
12055 #ifdef OS2
12056 	if (!tcp_avail) {
12057 	    printf("?Sorry, either TCP/IP is not available on this system or\n\
12058 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
12059 		   );
12060 	    success = 0;
12061 	    return(-9);
12062 	} else {
12063 #endif /* OS2 */
12064 	    x = nettype;		/* Save net type in case of failure */
12065 	    z = ttnproto;		/* Save protocol in case of failure */
12066 	    nettype = NET_TCPB;
12067 	    ttnproto = NP_RLOGIN;
12068 	    if ((y = setlin(XYHOST,0,1)) <= 0) {
12069 		nettype = x;		/* Failed, restore net type. */
12070 		ttnproto = z;		/* and protocol */
12071 		success = 0;
12072 	    }
12073 	    didsetlin++;
12074 #ifdef OS2
12075 	}
12076 #endif /* OS2 */
12077 	return(y);
12078 #else
12079 	printf("?Sorry, RLOGIN is not configured in this copy of C-Kermit.\n");
12080 	return(-9);
12081 #endif /* RLOGCODE */
12082     }
12083 #endif /* NETCONN */
12084 #endif /* NOLOCAL */
12085 
12086 #ifndef NOXMIT
12087     if (cx == XXTRA) {			/* TRANSMIT */
12088 	extern int xfrxla;
12089 	int i, n, xpipe = 0, xbinary = 0, xxlate = 1, xxnowait = 0, getval;
12090 	int xxecho = 0;
12091 	int scan = 1;
12092 	char c;
12093 	struct FDB sf, sw, tx;		/* FDBs for parse functions */
12094 #ifndef NOCSETS
12095 	extern int tcs_transp;		/* Term charset is transparent */
12096 #else
12097 	int tcs_transp = 1;
12098 #endif /* NOCSETS */
12099 
12100 #ifdef COMMENT
12101 	xbinary = binary;		/* Default text/binary mode */
12102 #else
12103 	xbinary = 0;			/* Default is text */
12104 #endif /* COMMENT */
12105 	xxecho = xmitx;
12106 
12107 	cmfdbi(&sw,			/* First FDB - command switches */
12108 	       _CMKEY,			/* fcode */
12109 	       "Filename, or switch",	/* hlpmsg */
12110 	       "",			/* default */
12111 	       "",			/* addtl string data */
12112 	       nxmitsw,			/* addtl numeric data 1: tbl size */
12113 	       4,			/* addtl numeric data 2: 4 = cmswi */
12114 	       xxstring,		/* Processing function */
12115 	       xmitsw,			/* Keyword table */
12116 	       &sf			/* Pointer to next FDB */
12117 	       );
12118 	cmfdbi(&sf,			/* 2nd FDB - file to send */
12119 	       _CMIFI,			/* fcode */
12120 	       "File to transmit",	/* hlpmsg */
12121 	       "",			/* default */
12122 	       "",			/* addtl string data */
12123 	       0,			/* addtl numeric data 1 */
12124 	       0,			/* addtl numeric data 2 */
12125 	       xxstring,
12126 	       NULL,
12127 #ifdef PIPESEND
12128 	       &tx
12129 #else
12130 	       NULL
12131 #endif /* PIPESEND */
12132 	       );
12133 #ifdef PIPESEND
12134         cmfdbi(&tx,
12135 	       _CMTXT,			/* fcode */
12136 	       "Command",		/* hlpmsg */
12137 	       "",			/* default */
12138 	       "",			/* addtl string data */
12139 	       0,			/* addtl numeric data 1 */
12140 	       0,			/* addtl numeric data 2 */
12141 	       xxstring,
12142 	       NULL,
12143 	       NULL
12144 	       );
12145 #endif /* PIPESEND */
12146 
12147 	while (1) {
12148 	    x = cmfdb(&sw);
12149 	    if (x < 0)
12150 	      return(x);
12151 	    if (cmresult.fcode != _CMKEY)
12152 	      break;
12153 	    c = cmgbrk();		/* Have switch, get break character */
12154 	    if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12155 		printf("?This switch does not take an argument\n");
12156 		return(-9);
12157 	    }
12158 	    if (!getval && (cmgkwflgs() & CM_ARG)) {
12159 		printf("?This switch requires an argument\n");
12160 		return(-9);
12161 	    }
12162 	    n = cmresult.nresult;	/* Numeric result = switch ID */
12163 	    switch (n) {		/* Process the switch */
12164 #ifdef PIPESEND
12165 	      case XMI_CMD:		/* Transmit from a command */
12166 		if (nopush) {
12167 		    printf("?Sorry, system command access is disabled\n");
12168 		    return(-9);
12169 		}
12170 		sw.hlpmsg = "Command, or switch"; /* Change help message */
12171 		xpipe = 1;		/* (No way to undo this one) */
12172 		break;
12173 #endif /* PIPESEND */
12174 
12175 	      case XMI_BIN:		/* Binary */
12176 		xbinary = 1;
12177 		xxlate = 0;		/* Don't translate charsets */
12178 		scan = 0;
12179 		break;
12180 
12181 	      case XMI_TXT:		/* Text */
12182 		xbinary = 0;
12183 		xxlate = !tcs_transp;	/* Translate if TERM CHAR not TRANSP */
12184 		scan = 0;
12185 		break;
12186 
12187 	      case XMI_TRA:		/* Transparent text */
12188 		xbinary = 0;
12189 		xxlate = 0;		/* But don't translate charsets */
12190 		scan = 0;
12191 		break;
12192 
12193 #ifdef COMMENT
12194 	      case XMI_VRB:		/* /VERBOSE */
12195 	      case XMI_QUI:		/* /QUIET */
12196 		break;			/* (not implemented yet) */
12197 #endif /* COMMENT */
12198 
12199 	      case XMI_NOW:		/* /NOWAIT */
12200 		xxnowait = 1;
12201 		break;
12202 
12203 	      case XMI_NOE:		/* /NOWAIT */
12204 		xxecho = 0;
12205 		break;
12206 
12207 	      default:
12208 		return(-2);
12209 	    }
12210 
12211 	}
12212 	if (cmresult.fcode != _CMIFI && cmresult.fcode != _CMTXT)
12213 	  return(-2);
12214 	ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Filename */
12215 	if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
12216 	  ckstrncpy(line,tmpbuf,LINBUFSIZ);
12217 	s = line;
12218 	if ((y = cmcfm()) < 0)		/* Confirm */
12219 	  return(y);
12220 #ifdef CK_APC
12221 	if ((apcactive == APC_LOCAL) ||
12222 	    ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
12223 	  return(success = 0);
12224 #endif /* CK_APC */
12225 	if (cmresult.nresult != 0) {
12226 	    printf("?Only a single file may be transmitted\n");
12227 	    return(-9);
12228 	}
12229 #ifdef PIPESEND
12230 	if (xpipe) {
12231 	    s = brstrip(s);
12232 	    if (!*s) {
12233 		printf("?Sorry, a command to send from is required\n");
12234 		return(-9);
12235 	    }
12236 	    pipesend = 1;
12237 	}
12238 #endif /* PIPESEND */
12239 
12240 	if (scan && (filepeek
12241 #ifndef NOXFER
12242 		     || patterns
12243 #endif /* NOXFER */
12244 		     )) {		/* If user didn't specify type */
12245 	    int k, x;			      /* scan the file to see */
12246 	    x = -1;
12247 	    k = scanfile(s,&x,nscanfile);
12248 	    if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
12249 	}
12250 	if (!xfrxla) xxlate = 0;
12251 	success = transmit(s,
12252 			   (char) (xxnowait ? '\0' : (char)xmitp),
12253 			   xxlate,
12254 			   xbinary,
12255 			   xxecho
12256 			   );
12257 	return(success);
12258     }
12259 #endif /* NOXMIT */
12260 
12261 #ifndef NOFRILLS
12262     if (cx == XXTYP  || cx == XXCAT || cx == XXMORE ||
12263 	cx == XXHEAD || cx == XXTAIL) {
12264 	int paging = 0, havename = 0, head = 0, width = 0;
12265 	int height = 0, count = 0;
12266 	char pfxbuf[64], * prefix = NULL;
12267 	char outfile[CKMAXPATH+1];
12268 	struct FDB sf, sw;
12269 	char * pat = NULL;
12270 	int incs = 0, outcs = 0, cset = -1, number = 0;
12271 #ifdef UNICODE
12272         char * tocs = "";
12273 	extern int fileorder;
12274 #ifdef OS2
12275 #ifdef NT
12276 	char guibuf[128], * gui_title = NULL;
12277 	int  gui = 0;
12278 #endif /* NT */
12279 #ifndef NOCSETS
12280 	extern int tcsr, tcsl;
12281 #endif /* NOCSETS */
12282 #endif /* OS2 */
12283 #endif /* UNICODE */
12284 
12285 	outfile[0] = NUL;
12286 
12287 	if (cx == XXMORE)
12288 	  paging = 1;
12289 	else if (cx == XXCAT)
12290 	  paging = 0;
12291 	else
12292 	  paging = (typ_page < 0) ? xaskmore : typ_page;
12293 	if (paging < 0)
12294 	  paging = saveask;
12295 
12296 	if (cx == XXHEAD) {
12297 	    head = 10;
12298 	    cx = XXTYP;
12299 	} else if (cx == XXTAIL) {
12300 	    head = -10;
12301 	    cx = XXTYP;
12302 	}
12303 
12304 #ifdef IKSD
12305 	if (inserver && !ENABLED(en_typ)) {
12306 	    printf("?Sorry, TYPE command disabled\n");
12307 	    return(-9);
12308 	}
12309 #endif /* IKSD */
12310 
12311 	cmfdbi(&sw,			/* 2nd FDB - optional /PAGE switch */
12312 	       _CMKEY,			/* fcode */
12313 	       "Filename or switch",	/* hlpmsg */
12314 	       "",			/* default */
12315 	       "",			/* addtl string data */
12316 	       ntypetab,		/* addtl numeric data 1: tbl size */
12317 	       4,			/* addtl numeric data 2: 4 = cmswi */
12318 	       xxstring,		/* Processing function */
12319 	       typetab,			/* Keyword table */
12320 	       &sf			/* Pointer to next FDB */
12321 	       );
12322 	cmfdbi(&sf,			/* 1st FDB - file to type */
12323 	       _CMIFI,			/* fcode */
12324 	       "",			/* hlpmsg */
12325 	       "",			/* default */
12326 	       "",			/* addtl string data */
12327 	       0,			/* addtl numeric data 1 */
12328 	       0,			/* addtl numeric data 2 */
12329 	       xxstring,
12330 	       NULL,
12331 	       NULL
12332 	       );
12333 
12334 	while (!havename) {
12335 	    x = cmfdb(&sw);		/* Parse something */
12336 	    debug(F101,"type cmfdb","",x);
12337 	    debug(F101,"type cmresult.fcode","",cmresult.fcode);
12338 	    debug(F101,"type cmresult.nresult","",cmresult.nresult);
12339 	    if (x < 0) {			/* Error */
12340 		if (x == -3) {
12341 		    x = -9;
12342 		    printf("?Filename required\n");
12343 		}
12344 		return(x);
12345 	    } else if (cmresult.fcode == _CMKEY) {
12346 		char c; int getval;
12347 		c = cmgbrk();
12348 		getval = (c == ':' || c == '=');
12349 		if (getval && !(cmgkwflgs() & CM_ARG)) {
12350 		    printf("?This switch does not take an argument\n");
12351 		    return(-9);
12352 		}
12353 #ifdef COMMENT
12354 		if (!getval && (cmgkwflgs() & CM_ARG)) {
12355 		    printf("?This switch requires an argument\n");
12356 		    /* Not if it has a default! */
12357 		    return(-9);
12358 		}
12359 #endif /* COMMENT */
12360 		switch (cmresult.nresult) {
12361 #ifdef CK_TTGWSIZ
12362 		  case TYP_PAG:
12363 		    paging = 1;
12364 		    break;
12365 
12366 		  case TYP_NOP:
12367 		    paging = 0;
12368 		    break;
12369 #endif /* CK_TTGWSIZ */
12370 
12371 		  case TYP_COU:
12372 		    paging = 0;
12373 		    count = 1;
12374 		    break;
12375 
12376 		  case TYP_HEA:
12377 		  case TYP_TAI:
12378 		    y = 10;
12379 		    if (getval)
12380 		      if ((x = cmnum("Number of lines",
12381 				     "10",10,&y,xxstring)) < 0)
12382 			return(x);
12383 		    head = (cmresult.nresult == TYP_TAI) ? -y : y;
12384 		    break;
12385 
12386 		  case TYP_WID:
12387 		    y = typ_wid > -1 ? typ_wid : cmd_cols;
12388 		    if (getval)
12389 		      if ((x = cmnum("Column at which to truncate",
12390 				     ckitoa(y),10,&y,xxstring)) < 0)
12391 			return(x);
12392 		    width = y;
12393 		    break;
12394 
12395 #ifdef KUI
12396 		  case TYP_HIG:
12397 		    if (getval)
12398 		      if ((x = cmnum("Height of GUI dialog",
12399 				     ckitoa(y),10,&y,xxstring)) < 0)
12400 			return(x);
12401 		    height = y;
12402 		    break;
12403 #endif /* KUI */
12404 
12405 		  case TYP_PAT:
12406 		    if (!getval && (cmgkwflgs() & CM_ARG)) {
12407 			printf("?This switch requires an argument\n");
12408 			return(-9);
12409 		    }
12410 		    if ((x = cmfld("pattern","",&s,xxstring)) < 0)
12411 		      return(x);
12412 		    ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12413 		    pat = tmpbuf;
12414 		    break;
12415 
12416 		  case TYP_PFX:
12417 		    if (!getval && (cmgkwflgs() & CM_ARG)) {
12418 			printf("?This switch requires an argument\n");
12419 			return(-9);
12420 		    }
12421 		    if ((x = cmfld("prefix for each line","",&s,xxstring)) < 0)
12422 		      return(x);
12423 		    if ((int)strlen(s) > 63) {
12424 			printf("?Too long - 63 max\n");
12425 			return(-9);
12426 		    }
12427 		    ckstrncpy(pfxbuf,s,64);
12428 		    prefix = brstrip(pfxbuf);
12429 		    number = 0;
12430 		    break;
12431 
12432 #ifdef KUI
12433 		  case TYP_GUI:
12434 		    if (!getval && (cmgkwflgs() & CM_ARG)) {
12435 			printf("?This switch requires an argument\n");
12436 			return(-9);
12437 		    }
12438 		    if ((x = cmfld("Dialog box title","",&s,xxstring)) < 0) {
12439 			if (x != -3)
12440 			  return(x);
12441 		    } else {
12442 			if ((int)strlen(s) > 127) {
12443 			    printf("?Too long - 127 max\n");
12444 			    return(-9);
12445 			}
12446 			ckstrncpy(guibuf,s,128);
12447 			gui_title = brstrip(guibuf);
12448 		    }
12449 		    gui = 1;
12450 		    break;
12451 #endif /* KUI */
12452 
12453 		  case TYP_NUM:		/* /NUMBER */
12454 		    number = 1;
12455 		    prefix = NULL;
12456 		    break;
12457 
12458 #ifdef UNICODE
12459 		  case TYP_XPA:		/* /TRANSPARENT */
12460 		    incs = 0;
12461 		    cset = 0;
12462 		    outcs = -1;
12463 		    break;
12464 
12465 		  case TYP_XIN:		/* /CHARACTER-SET: */
12466 		    if (!getval && (cmgkwflgs() & CM_ARG)) {
12467 			printf("?This switch requires an argument\n");
12468 			return(-9);
12469 		    }
12470 		    if ((incs = cmkey(fcstab,nfilc,
12471 				      "character-set name","",xxstring)) < 0) {
12472 			if (incs == -3)	/* Note: No default */
12473 			  incs = -2;
12474 			return(incs);
12475 		    }
12476 		    cset = incs;
12477 		    break;
12478 
12479 		  case TYP_XUT:		/* /TRANSLATE-TO: */
12480 		    if (!getval && (cmgkwflgs() & CM_ARG)) {
12481 			printf("?This switch requires an argument\n");
12482 			return(-9);
12483 		    }
12484 #ifdef OS2
12485 		    if (!inserver && !k95stdout) {
12486 			tocs = "ucs2";
12487 		    } else {
12488 #ifdef CKOUNI
12489 			tocs = rlookup(txrtab,ntxrtab,tcsl);
12490 #else /* CKOUNI */
12491 			extern struct keytab ttcstab[];
12492 			extern int ntxrtab;
12493 			tocs = rlookup(ttcstab,ntermc,tocs);
12494 			if (!tocs)
12495 			  tocs = getdcset();
12496 #endif /* CKOUNI */
12497                     }
12498 #else /* OS2 */
12499 		    tocs = getdcset();
12500 #endif /* OS2 */
12501 		    if ((outcs = cmkey(fcstab,nfilc,
12502 				       "character-set",tocs,xxstring)) < 0)
12503 		      return(outcs);
12504 		    break;
12505 #endif /* UNICODE */
12506 		  case TYP_OUT:
12507 		    if ((x = cmofi("File for result lines","",
12508 				   &s,xxstring)) < 0)
12509 		      return(x);
12510 		    ckstrncpy(outfile,s,CKMAXPATH);
12511 		    break;
12512 		}
12513 	    } else if (cmresult.fcode == _CMIFI)
12514 	      havename = 1;
12515 	    else
12516 	      return(-2);
12517 	}
12518 	if (havename) {
12519 	    ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
12520 	    y = cmresult.nresult;
12521 	} else {
12522 	    if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
12523 		if (x == -3) {
12524 		    printf("?Name of an existing file required\n");
12525 		    return(-9);
12526 		} else return(x);
12527 	    }
12528 	    ckstrncpy(line,s,LINBUFSIZ);
12529 	}
12530 	if (y != 0) {
12531 	    printf("?A single file please\n");
12532 	    return(-9);
12533 	}
12534 #ifdef KUI
12535 	if ( outfile[0] && gui ) {
12536 	    printf("?/GUI and /OUTPUT are incompatible\n");
12537 	    return(-9);
12538 	}
12539 #endif /* KUI */
12540 
12541 	if ((y = cmcfm()) < 0)		/* Confirm the command */
12542 	  return(y);
12543 
12544 #ifdef UNICODE
12545 	fileorder = -1;
12546 	if (cset < 0 && filepeek) {	/* If no charset switches given */
12547 	    int k, x = -1;
12548 	    k = scanfile(line,&x,nscanfile); /* Call file analyzer */
12549 	    debug(F111,"type scanfile",line,k);
12550 	    debug(F101,"type scanfile flag","",x);
12551 	    switch(k) {
12552 	      case FT_UTF8:		/* which can detect UTF-8... */
12553 		cset = 0;
12554 		incs = FC_UTF8;
12555 		break;
12556 	      case FT_UCS2:		/* and UCS-2... */
12557 		cset = 0;
12558 		incs = FC_UCS2;
12559 		fileorder = x;		/* even if there is no BOM. */
12560 		debug(F101,"type fileorder","",fileorder);
12561 		break;
12562 	    }
12563 	}
12564 #ifdef OS2
12565         if (cset < 0) {			/* If input charset still not known */
12566 #ifdef CKOUNI
12567             tocs = rlookup(txrtab,ntxrtab,tcsl);
12568 #else /* CKOUNI */
12569             extern struct keytab ttcstab[];
12570             extern int ntxrtab;
12571             tocs = rlookup(ttcstab,ntermc,incs);
12572             if (!tocs)
12573 	      tocs = getdcset();
12574 #endif /* CKOUNI */
12575             incs = lookup(fcstab,tocs,nfilc,&x);
12576         }
12577 #endif /* OS2 */
12578 
12579         if (outcs == 0 && incs != 0) {	/* Supply default target charset */
12580 	    int x = 0;			/* if switch not given. */
12581 	    tocs = getdcset();
12582 	    outcs = lookup(fcstab,tocs,nfilc,&x);
12583 	}
12584 #else  /* !UNICODE */
12585 	if (cset < 0) incs = outcs = 0;
12586 #endif /* UNICODE */
12587 
12588 	if (outfile[0] && paging)	/* This combination makes no sense */
12589 	  paging = 0;			/* so turn off paging */
12590 
12591 #ifdef KUI
12592 	/* No paging when dialog is used */
12593 	if ( gui && paging )
12594 	  paging = 0;
12595 
12596 	if ( !gui && height ) {
12597 	    printf("?The /HEIGHT switch is not supported without /GUI\n");
12598 	    return(-9);
12599 	}
12600 #endif /* KUI */
12601 
12602 	if (count) paging = -1;
12603 	debug(F111,"type",line,paging);
12604 #ifdef KUI
12605 	if ( gui ) {
12606 	    s = (char *)1;    /* ok, its an ugly hack */
12607 	    if (gui_text_popup_create(gui_title ?
12608 				      gui_title : line, height,width) < 0) {
12609 		printf("?/GUI not supported on this system\n");
12610 		gui = 0;
12611 		return(-9);
12612 	    }
12613 	    width = 0;
12614 	} else
12615 #endif /* KUI */
12616 	  s = outfile;
12617 	success =
12618 	  dotype(line,paging,0,head,pat,width,prefix,incs,outcs,s,number);
12619 	return(success);
12620     }
12621 #endif /* NOFRILLS */
12622 
12623 #ifndef NOCSETS
12624     if (cx == XXXLA) {			/* TRANSLATE file's charset */
12625 	_PROTOTYP (int doxlate, ( void ) );
12626 	return(doxlate());
12627     }
12628 #endif /* NOCSETS */
12629 
12630     if (cx == XXVER) {			/* VERSION */
12631 	int n = 0;
12632 	extern char * ck_patch, * ck_s_test;
12633 #ifdef COMMENT
12634 	extern int hmtopline;
12635 #endif /* COMMENT */
12636 	if ((y = cmcfm()) < 0)
12637           return(y);
12638 
12639 #ifdef CK_64BIT
12640 	printf("\n%s, for%s (64-bit)\n Numeric: %ld",versio,ckxsys,vernum);
12641 #else
12642 	printf("\n%s, for%s\n Numeric: %ld",versio,ckxsys,vernum);
12643 #endif	/* CK_64BIT */
12644 	printf("\n\n");
12645         printf("Authors:\n");
12646 	printf(" Frank da Cruz, the Kermit Project %s\n",
12647                "<fdc@kermitproject.org>"
12648 	       );
12649         printf(" Jeffrey Eric Altman, Secure Endpoints, Inc. %s\n",
12650 	       "<jaltman@secure-endpoints.com>"
12651 	       );
12652 	printf(" Contributions from many others.\n");
12653 	n = 7;
12654 	if (*ck_s_test) {
12655 	    printf("\nTHIS IS A TEST VERSION, NOT FOR PRODUCTION USE.\n");
12656 	    n += 2;
12657 	}
12658 	if (*ck_patch) {
12659 	    printf(" Patches: %s\n", ck_patch);
12660 	    n++;
12661 	}
12662 	printf(" Type COPYRIGHT for copyright and license.\n\n");
12663 #ifdef OS2
12664 #ifdef COMMENT
12665 	shoreg();
12666 #endif /* COMMENT */
12667 #else
12668 #ifdef COMMENT
12669 	hmtopline = n+1;
12670 	hmsga(copyright);
12671 	hmtopline = 0;
12672 #endif /* COMMENT */
12673 #endif /* OS2 */
12674 	return(success = 1);
12675     }
12676 
12677     if (cx == XXCPR) {			/* COPYRIGHT or LICENSE */
12678         _PROTOTYP( int hmsgaa, (char * [], char *) );
12679         extern char * ck_cryear;
12680 	if ((y = cmcfm()) < 0)
12681           return(y);
12682 	hmsgaa(copyright,ck_cryear);
12683 	return(success = 1);
12684     }
12685 
12686 #ifndef MAC				/* Only for multiuser systems */
12687 #ifndef OS2
12688 #ifndef NOFRILLS
12689     if (cx == XXWHO) {			/* WHO */
12690 	char *wc;
12691 #ifdef IKSD
12692 	if (inserver && !ENABLED(en_who)) {
12693 	    printf("?Sorry, WHO command disabled\n");
12694 	    return(-9);
12695 	}
12696 #endif /* IKSD */
12697 #ifdef datageneral
12698 	if ((z = cmcfm()) < 0) return(z);
12699 	if (nopush) {
12700 	    printf("?Sorry, who not allowed\n");
12701 	    return(success = 0);
12702 	}
12703         xsystem(WHOCMD);
12704 #else
12705 	if ((y = cmtxt("user name","",&s,xxstring)) < 0) return(y);
12706         if (nopush) {
12707 	    printf("?Sorry, WHO command disabled\n");
12708 	    return(success = 0);
12709 	}
12710 	if (!(wc = getenv("CK_WHO"))) wc = WHOCMD;
12711 	if (wc)
12712 	  if ((int) strlen(wc) > 0) {
12713 	      ckmakmsg(line,LINBUFSIZ,wc," ",s,NULL);
12714 	      xsystem(line);
12715 	  }
12716 #endif /* datageneral */
12717 	return(success = 1);
12718     }
12719 #endif /* NOFRILLS */
12720 #endif /* OS2 */
12721 #endif /* MAC */
12722 
12723 #ifndef NOFRILLS
12724     if (cx == XXWRI || cx == XXWRL || cx == XXWRBL) { /* WRITE */
12725 	int x,y;			/* On stack in case of \fexec() */
12726 	if ((x = cmkey(writab,nwri,"to file or log","",xxstring)) < 0) {
12727 	    if (x == -3) printf("?Write to what?\n");
12728 	    return(x);
12729 	}
12730 	if ((y = cmtxt("text","",&s,xxstring)) < 0) return(y);
12731 	s = brstrip(s);
12732 	switch (x) {
12733 	  case LOGD: y = ZDFILE; break;
12734 	  case LOGP: y = ZPFILE; break;
12735 #ifndef NOLOCAL
12736 	  case LOGS: y = ZSFILE; break;
12737 #endif /* NOLOCAL */
12738 	  case LOGT: y = ZTFILE; break;
12739 #ifndef NOSPL
12740 	  case LOGW: y = ZWFILE; break;
12741 #endif /* NOSPL */
12742 	  case LOGX:			/* SCREEN (stdout) */
12743 	  case LOGE:			/* ERROR  (stderr) */
12744 	    if (x == LOGE) {
12745 		debug(F110,
12746 		      (cx == XXWRL) ? "WRITELN ERROR" : "WRITE ERROR", s,0);
12747 		fprintf(stderr,"%s%s",s,(cx == XXWRL) ? "\n" : "");
12748 	    } else {
12749 		debug(F110,
12750 		      (cx == XXWRL) ? "WRITELN SCREEN" : "WRITE SCREEN", s,0);
12751 		printf("%s%s",s,(cx == XXWRL) ? "\n" : "");
12752 	    }
12753 	    return(success = 1);
12754 	  default: return(-2);
12755 	}
12756 	if (chkfn(y) > 0) {
12757 	    x = (cx == XXWRI) ? zsout(y,s) : zsoutl(y,s);
12758 	    debug(F111,"WRITE",
12759 		  (cx == XXWRI) ? "zsout" : "zsoutl",
12760 		  x);
12761 	    if (x < 0) printf("?Write error\n");
12762 	} else {
12763 	    x = -1;
12764 	    printf("?File or log not open\n");
12765 	}
12766 	debug(F101,"WRITE x","",x);
12767 	return(success = (x == 0) ? 1 : 0);
12768     }
12769 #endif /* NOFRILLS */
12770 
12771 #ifndef NOXFER
12772     if (cx == XXASC || cx == XXBIN) {
12773 	if ((x = cmcfm()) < 0) return(x);
12774 #ifdef NEWFTP
12775 /*
12776   Make C-Kermit work like other ftp clients, where
12777   the ASCII (TEXT) and BINARY commands are global settings.
12778 */
12779 	if (ftpisopen()) {
12780 	    doftpglobaltype((cx == XXASC) ? XYFT_T : XYFT_B);
12781 	    /* Fall thru--the command it should apply to both FTP and Kermit */
12782 	    /* return(success = 1); */
12783 	}
12784 #endif /* NEWFTP */
12785 
12786 	xfermode = XMODE_M;		/* Set manual Kermit transfer mode */
12787 	binary = (cx == XXASC) ? XYFT_T : XYFT_B;
12788 	return(success = 1);
12789     }
12790 #endif /* NOXFER */
12791 
12792     if (cx == XXCLS) {
12793 	if ((x = cmcfm()) < 0) return(x);
12794 	y = ck_cls();
12795 	return(success = (y > -1) ? 1 : 0);
12796     }
12797 
12798 #ifdef CK_MKDIR
12799     if (cx == XXMKDIR || cx == XXLMKD) {
12800 	char *p;
12801 #ifdef LOCUS
12802 	if (!locus && cx != XXLMKD) {
12803 #ifdef NOXFER
12804 	    return(-2);
12805 #else
12806 	    return(dormt(XZMKD));
12807 #endif /* NOXFER */
12808         }
12809 #endif /* LOCUS */
12810 #ifdef IKSD
12811 	if (inserver && !ENABLED(en_mkd)) {
12812 	    printf("?Sorry, directory creation is disabled\n");
12813 	    return(-9);
12814 	}
12815 #endif /* IKSD */
12816 	if ((x = cmfld("Name for new directory","",&s,xxstring)) < 0) {
12817 	    if (x != -3) {
12818 		return(x);
12819 	    } else {
12820 		printf("?Directory name required\n");
12821 		return(-9);
12822 	    }
12823 	}
12824 	ckstrncpy(line,s,LINBUFSIZ);
12825 	s = line;
12826 	if ((x = cmcfm()) < 0) return(x);
12827 	s = brstrip(s);
12828 	bgchk();			/* Set msgflg */
12829 	x = ckmkdir(0,s,&p,msgflg,0);
12830 #ifdef COMMENT
12831 	if (msgflg && x == 0)
12832 	  printf("?Directory already exists\n");
12833 #endif /* COMMENT */
12834 	return(success = (x < 0) ? 0 : 1);
12835     }
12836     if (cx == XXRMDIR || cx == XXLRMD) { /* RMDIR */
12837 	char *p;
12838 #ifdef LOCUS
12839 	if (!locus && cx != XXLRMD) {
12840 #ifdef NOXFER
12841 	    return(-2);
12842 #else
12843 	    return(dormt(XZRMD));
12844 #endif /* NOXFER */
12845         }
12846 #endif /* LOCUS */
12847 #ifdef IKSD
12848 	if (inserver && !ENABLED(en_rmd)) {
12849 	    printf("?Sorry, directory removal is disabled\n");
12850 	    return(-9);
12851 	}
12852 #endif /* IKSD */
12853 	if ((x = cmdir("Name of directory to be removed","",&s,xxstring)) < 0)
12854 	  return(x);
12855 	ckstrncpy(line,s,LINBUFSIZ);
12856 	s = line;
12857 	if ((x = cmcfm()) < 0) return(x);
12858 	s = brstrip(s);
12859 	x = ckmkdir(1,s,&p,msgflg,0);
12860 	return(success = (x < 0) ? 0 : 1);
12861     }
12862 #endif /* CK_MKDIR */
12863 
12864 #ifdef TNCODE
12865     if (cx == XXTELOP)
12866       return(dotelopt());
12867 #endif /* TNCODE */
12868 
12869 #ifndef NOPUSH
12870     if (cx == XXNPSH) {
12871 	if ((z = cmcfm()) < 0) return(z);
12872         nopush = 1;
12873 #ifndef NOSERVER
12874         en_hos = 0;
12875 #endif /* NOSERVER */
12876 #ifdef PIPESEND
12877 	usepipes = 0;
12878 #endif /* PIPESEND */
12879         return(success = 1);
12880     }
12881 #endif /* NOPUSH */
12882 
12883 #ifdef OS2
12884     if (cx == XXNSCR) {
12885 	if ((z = cmcfm()) < 0) return(z);
12886         tt_scroll = 0;
12887         return(success = 1);
12888     }
12889 #endif /* OS2 */
12890 
12891 #ifndef NOSPL
12892     if (cx == XXLOCAL)			/* LOCAL variable declarations */
12893       return(success = dolocal());
12894 #endif /* NOSPL */
12895 
12896     if (cx == XXKERMI) {		/* The KERMIT command */
12897 	char * list[65];
12898 	extern char **xargv;
12899 	extern int xargc;
12900 	int i;
12901 	if ((y = cmtxt("kermit command-line arguments, -h for help",
12902 		       "",&s,xxstring)) < 0)
12903 	  return(y);
12904 	ckstrncpy(line,"kermit ",LINBUFSIZ);
12905 	ckstrncat(line,s,LINBUFSIZ-8);
12906 	xwords(line,64,list,0);
12907 	for (i = 1; i < 64; i++) {
12908 	    if (!list[i])
12909 	      break;
12910 	}
12911 	i--;
12912 	xargc = i;
12913 	xargv = list;
12914 	xargv++;
12915 	sstate = cmdlin();
12916 	if (sstate) {
12917 	    extern int justone;
12918 	    debug(F000,"KERMIT sstate","",sstate);
12919 	    justone = 1;		/* Force return to command mode */
12920 	    proto();			/* after protocol */
12921 	    return(success);
12922 	} else {
12923 	    debug(F101,"KERMIT sstate","",sstate);
12924 	    return(success = 1);	/* Not exactly right, but... */
12925 	}
12926     }
12927     if (cx == XXDATE) {			/* DATE command */
12928 	extern char cmdatebuf[], * cmdatemsg;
12929 
12930 #ifndef COMMENT
12931 	char * dp;
12932 	if ((y = cmtxt("date and/or time, or carriage return for current",
12933 		       "",&s,xxstring)) < 0)
12934 	  return(y);
12935 	s = brstrip(s);
12936 	dp = cmcvtdate(s,1);
12937 	if (!dp) {
12938 	    printf("?%s\n",cmdatemsg ? cmdatemsg : "Date conversion error");
12939 	    success = 0;
12940 	} else {
12941 	    printf("%s\n",dp);
12942 	    success = 1;
12943 	}
12944 #else
12945 	/* This works fine but messes up my "dates" torture-test script */
12946 
12947 	if ((x = cmdate("Date and/or time, or carriage return for current",
12948 			"",&s,0,xxstring)) < 0) {
12949 	    return(x);
12950 	} else {
12951 	    printf("%s\n",cmdatebuf);
12952 	    success = 1;
12953 	}
12954 #endif /* COMMENT */
12955 	return(success);
12956     }
12957 #ifndef NOPUSH
12958 #ifndef NOFRILLS
12959     if (cx == XXEDIT)
12960       return(doedit());
12961 #endif /* NOFRILLS */
12962 #endif /* NOPUSH */
12963 
12964 #ifdef BROWSER				/* Defined only ifndef NOPUSH */
12965     if (cx == XXBROWS)
12966       return(dobrowse());
12967 #endif /* BROWSER */
12968 
12969 #ifdef CK_TAPI
12970     if (cx == XXTAPI) {			/* Microsoft TAPI */
12971 	return (success = dotapi());
12972     }
12973 #endif /* CK_TAPI */
12974 
12975 #ifndef NOXFER
12976     if (cx == XXWHERE) {
12977 	extern char * rfspec, * sfspec, * srfspec, * rrfspec;
12978 	if ((x = cmcfm()) < 0) return(x);
12979 	printf("\nFile most recently...\n\n");
12980 	printf("  Sent:       %s\n",   sfspec ? sfspec : "(none)");
12981 	if (sfspec && srfspec) {
12982 	    printf("  Stored as:  %s\n",   srfspec);
12983 	    printf("\n");
12984 	}
12985 	printf("  Received:   %s\n",   rrfspec ? rrfspec : "(none)");
12986 	if (rfspec && rrfspec)
12987 	printf("  Stored as:  %s\n",   rfspec);
12988 	printf(
12989 "\nIf the full path is not shown, then the file is probably in your current\n"
12990 	       );
12991 	printf(
12992 "directory or your download directory (if any - SHOW FILE to find out).\n\n"
12993 	       );
12994 	return(success = 1);
12995     }
12996 #endif /* NOXFER */
12997 
12998 #ifdef CK_RECALL
12999     if (cx == XXREDO)
13000       return(doredo());
13001 #endif /* CK_RECALL */
13002 
13003 #ifdef CKROOT
13004     if (cx == XXCHRT)			/* Change Kermit's root directory */
13005       return(dochroot());
13006 #endif /* CKROOT */
13007 
13008 #ifdef CK_KERBEROS
13009     if (cx == XXAUTH) {			/* KERBEROS */
13010 	x = cp_auth();			/* Parse it */
13011 #ifdef IKSD
13012         if (inserver) {
13013             printf("?Command disabled in IKSD.\r\n");
13014             return(success = 0);
13015         }
13016 #endif /* IKSD */
13017 	if (x < 0)			/* Pass parse errors back */
13018 	  return(x);
13019 	return(success = doauth(cx));
13020     }
13021 #endif /* CK_KERBEROS */
13022 
13023 #ifndef NOLOCAL
13024     if (cx == XXTERM) {
13025 	return(settrmtyp());
13026     }
13027 #endif /* NOLOCAL */
13028 
13029     if (cx == XXSTATUS) {
13030 	if ((x = cmcfm()) < 0) return(x);
13031 	printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
13032 	return(0);			/* Don't change it */
13033     }
13034 
13035     if (cx == XXFAIL) {
13036 	if ((x = cmcfm()) < 0) return(x);
13037 	return(success = 0);
13038     }
13039 
13040     if (cx == XXSUCC) {
13041 	if ((x = cmcfm()) < 0) return(x);
13042 	return(success = 1);
13043     }
13044 
13045     if (cx == XXNLCL) {
13046 	extern int nolocal;
13047 	if ((x = cmcfm()) < 0) return(x);
13048 	nolocal = 1;
13049 	return(success = 1);
13050     }
13051 
13052 #ifndef NOXFER
13053     if (cx == XXRASG)			/* Shortcuts for REMOTE commands */
13054       return(dormt(XZASG));
13055     if (cx == XXRCWD)
13056       return(dormt(XZCWD));
13057     if (cx == XXRCPY)
13058       return(dormt(XZCPY));
13059     if (cx == XXRDEL)
13060       return(dormt(XZDEL));
13061     if (cx == XXRDIR)
13062       return(dormt(XZDIR));
13063     if (cx == XXRXIT)
13064       return(dormt(XZXIT));
13065     if (cx == XXRHLP)
13066       return(dormt(XZHLP));
13067     if (cx == XXRHOS)
13068       return(dormt(XZHOS));
13069     if (cx == XXRKER)
13070       return(dormt(XZKER));
13071     if (cx == XXRPWD)
13072       return(dormt(XZPWD));
13073     if (cx == XXRQUE)
13074       return(dormt(XZQUE));
13075     if (cx == XXRREN)
13076       return(dormt(XZREN));
13077     if (cx == XXRMKD)
13078       return(dormt(XZMKD));
13079     if (cx == XXRMSG)
13080       return(dormt(XZMSG));
13081     if (cx == XXRRMD)
13082       return(dormt(XZRMD));
13083     if (cx == XXRSET)
13084       return(dormt(XZSET));
13085     if (cx == XXRSPA)
13086       return(dormt(XZSPA));
13087     if (cx == XXRTYP)
13088       return(dormt(XZTYP));
13089     if (cx == XXRWHO)
13090       return(dormt(XZWHO));
13091     if (cx == XXRCDUP)
13092       return(dormt(XZCDU));
13093     if (cx == XXRPRI)
13094       return(dormt(XZPRI));
13095 #endif /* NOXFER */
13096 
13097     if (cx == XXRESET) {		/* RESET */
13098 	if ((x = cmcfm()) < 0)
13099 	  return(x);
13100 	concb((char)escape);		/* Make command echoing to normal */
13101 	doclean(0);			/* Close all files */
13102 	return(success = 1);
13103     }
13104 
13105 #ifndef NOXFER
13106 #ifndef NOCSETS
13107     if (cx == XXASSOC)			/* ASSOCIATE */
13108       return(doassoc());
13109 #endif /* NOCSETS */
13110 #endif /* NOXFER */
13111 
13112 #ifndef NOSPL
13113     if (cx == XXSHIFT) {		/* SHIFT */
13114 	if ((y = cmnum("Number of arguments to shift","1",10,&x,xxstring)) < 0)
13115 	  return(y);
13116 	if ((z = cmcfm()) < 0)
13117 	  return(z);
13118 	return(success = doshift(x));
13119     }
13120 #endif /* NOSPL */
13121 
13122 #ifndef NOHELP
13123     if (cx == XXMAN)
13124       return(domanual());
13125 #endif /* NOHELP */
13126 
13127 #ifndef NOSPL
13128     if (cx == XXSORT)			/* SORT an array */
13129       return(dosort());
13130 #endif /* NOSPL */
13131 
13132     if (cx == XXPURGE) {
13133 #ifdef IKSD
13134 	if (inserver && (!ENABLED(en_del)
13135 #ifdef CK_LOGIN
13136                           || isguest
13137 #endif /* CK_LOGIN */
13138 			 )) {
13139 	    printf("?Sorry, DELETE is disabled\n");
13140 	    return(-9);
13141 	}
13142 #endif /* IKSD */
13143 #ifdef CK_APC
13144 	if ((apcactive == APC_LOCAL) ||
13145 	    ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
13146 	  return(success = 0);
13147 #endif /* CK_APC */
13148 #ifdef CKPURGE
13149         return(dopurge());
13150 #else
13151 #ifdef VMS
13152 	if ((x = cmtxt("optional switches followed by filespec",
13153 		       "",&s,xxstring)) < 0)
13154 	  return(x);
13155 	if (nopush) {
13156 	    printf("?Sorry, DCL access is disabled\n");
13157 	    return(-9);
13158 	}
13159 	ckstrncpy(line,s,LINBUFSIZ);
13160 	s = line;
13161 	x = mlook(mactab,"purge",nmac);
13162 	return(success = dodo(x,s,cmdstk[cmdlvl].ccflgs));
13163 #else
13164 	return(-2);
13165 #endif /* VMS */
13166 #endif /* CKPURGE */
13167     }
13168 
13169 #ifndef NOSPL
13170     if (cx == XXFAST) {
13171 	if ((x = cmcfm()) < 0) return(x);
13172 	x = mlook(mactab,"fast",nmac);
13173 	return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
13174     }
13175     if (cx == XXCAU) {
13176 	if ((x = cmcfm()) < 0) return(x);
13177 	x = mlook(mactab,"cautious",nmac);
13178 	return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
13179     }
13180     if (cx == XXROB) {
13181 	if ((x = cmcfm()) < 0) return(x);
13182 	x = mlook(mactab,"robust",nmac);
13183 	return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
13184     }
13185 #endif /* NOSPL */
13186 
13187     if (cx == XXSCRN) {			/* SCREEN */
13188 	int row, col;
13189 	if ((x = cmkey(scntab, nscntab,"screen action","", xxstring)) < 0)
13190 	  return(x);
13191 	switch (x) {			/* MOVE-TO (cursor position) */
13192 	  case SCN_MOV:
13193 	    if ((y = cmnum("Row (1-based)","",10,&z,xxstring)) < 0)
13194 	      return(y);
13195 	    row = z;
13196 	    y = cmnum("Column (1-based)","1",10,&z,xxstring);
13197 	    if (y < 0)
13198 	      return(y);
13199 	    col = z;
13200 	    if ((y = cmcfm()) < 0)
13201 	      return(y);
13202 	    if (row < 0 || col < 0) {
13203 		printf("?Row and Column must be 1 or greater\n");
13204 		return(-9);
13205 	    }
13206 	    if (cmd_rows > 0 && row > cmd_rows)
13207 	      row = cmd_rows;
13208 	    if (cmd_cols > 0 && col > cmd_cols)
13209 	      col = cmd_cols;
13210 	    y = ck_curpos(row,col);
13211 	    return(success = (y > -1) ? 1 : 0);
13212 
13213 	  case SCN_CLR:			/* CLEAR */
13214 	    if ((y = cmcfm()) < 0)
13215 	      return(y);
13216 	    debug(F100,"screen calling ck_cls()","",0);
13217 	    y = ck_cls();
13218 	    return(success = (y > -1) ? 1 : 0);
13219 
13220 	  case SCN_CLE:			/* CLEOL */
13221 	    if ((y = cmcfm()) < 0)
13222 	      return(y);
13223 	    y = ck_cleol();
13224 	    return(success = (y > -1) ? 1 : 0);
13225 	}
13226     }
13227 
13228 #ifndef NOHTTP
13229 #ifdef TCPSOCKET
13230     if (cx == XXHTTP)
13231       return(dohttp());
13232 #endif /* TCPSOCKET */
13233 #endif /* NOHTTP */
13234 
13235 #ifndef NOSPL
13236     if (cx == XXARRAY) {		/* ARRAY */
13237 #ifndef NOSHOW
13238 	extern int showarray();
13239 #endif /* NOSHOW */
13240 	if ((x = cmkey(arraytab, narraytab,"Array operation","",xxstring)) < 0)
13241 	  return(x);
13242 	switch (x) {
13243 	  case ARR_DCL:
13244 	    return(dodcl(XXDCL));
13245 	  case ARR_SRT:
13246 	    return(dosort());
13247 #ifndef NOSHOW
13248 	  case ARR_SHO:
13249 	    return(showarray());
13250 #endif /* NOSHOW */
13251 	  case ARR_CPY:
13252 	    return(copyarray());
13253 	  case ARR_SET:
13254 	  case ARR_CLR:
13255 	    return(clrarray(x));
13256 	  case ARR_DST:
13257 	    return(unarray());
13258 	  case ARR_RSZ:
13259 	    return(rszarray());
13260 	  case ARR_EQU:
13261 	    return(linkarray());
13262 
13263 	  default:
13264 	    printf("?Sorry, not implemented yet - \"%s\"\n",cmdbuf);
13265 	    return(-9);
13266 	}
13267     }
13268     if (cx == XXTRACE)			/* TRACE */
13269       return(dotrace());
13270 #endif /* NOSPL */
13271 
13272 #ifdef CK_PERMS
13273 #ifdef UNIX
13274     if (cx == XXCHMOD)
13275       return(douchmod());		/* Do Unix chmod */
13276 #endif /* UNIX */
13277 #endif /* CK_PERMS */
13278 
13279     if (cx == XXPROMP)
13280       return(doprompt());
13281 
13282     if (cx == XXGREP)
13283       return(dogrep());
13284 
13285     if (cx == XXDEBUG) {		/* DEBUG */
13286 #ifndef DEBUG
13287 	int dummy = 0;
13288 	return(seton(&dummy));
13289 #else
13290 	return(seton(&deblog));
13291 #endif /* DEBUG */
13292     }
13293     if (cx == XXMSG || cx == XXXMSG) {	/* MESSAGE */
13294 	extern int debmsg;		/* Script debugging messages */
13295 	if ((x = cmtxt("Message to print if SET DEBUG MESSAGE is ON or STDERR",
13296 		 "",&s,xxstring)) < 0)
13297 	  return(x);
13298 	if (!s)				/* Watch out for null result */
13299 	  s = "";			/* Make it an empty string */
13300 	else 				/* Not null */
13301 	  s = brstrip(s);		/* Strip braces and doublequotes */
13302 	switch (debmsg) {		/* Not debugging - don't print */
13303 	  case 0:
13304 	    break;
13305 	  case 1:
13306 	    printf("%s",s);		/* Print to stdout */
13307 	    if (cx == XXMSG) printf("\n");
13308 	    break;
13309 	  case 2:
13310 	    fprintf(stderr,"%s",s);	/* Ditto but print to stderr */
13311 	    if (cx == XXMSG) fprintf(stderr,"\n");
13312 	    break;
13313 	}
13314 	return(0);			/* Return without affecting SUCCESS */
13315     }
13316 
13317 #ifdef CKLEARN
13318     if (cx == XXLEARN) {		/* LEARN */
13319 	struct FDB of, sw, cm;
13320 	int closing = 0, off = 0, on = 0, confirmed = 0;
13321 	char c;
13322 
13323 	cmfdbi(&sw,			/* 2nd FDB - optional /PAGE switch */
13324 	       _CMKEY,			/* fcode */
13325 	       "Script file name, or switch", /* hlpmsg */
13326 	       "",			/* default */
13327 	       "",			/* addtl string data */
13328 	       3,			/* addtl numeric data 1: tbl size */
13329 	       4,			/* addtl numeric data 2: 4 = cmswi */
13330 	       xxstring,		/* Processing function */
13331 	       learnswi,		/* Keyword table */
13332 	       &of			/* Pointer to next FDB */
13333 	       );
13334 	cmfdbi(&of,_CMOFI,"","","",0,0,xxstring,NULL,&cm);
13335 	cmfdbi(&cm,_CMCFM,"","","",0,0,NULL,NULL,NULL);
13336 	line[0] = NUL;
13337 
13338 	while (!confirmed) {
13339 	    x = cmfdb(&sw);		/* Parse something */
13340 	    if (x < 0)
13341 	      return(x);
13342 	    switch (cmresult.fcode) {	/* What was it? */
13343 	      case _CMOFI:		/* Output file name */
13344 		ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
13345 		break;
13346 	      case _CMKEY:		/* Switch */
13347 		c = cmgbrk();
13348 		if ((c == ':' || c == '=') && !(cmgkwflgs() & CM_ARG)) {
13349 		    printf("?This switch does not take an argument\n");
13350 		    return(-9);
13351 		}
13352 		switch (cmresult.nresult) {
13353 		  case 2:		/* /CLOSE */
13354 		    closing = 1;	/* Fall thru on purpose */
13355 		  case 0:		/* /OFF */
13356 		    off = 1;
13357 		    on = 0;
13358 		    break;
13359 		  case 1:		/* /ON */
13360 		    on = 1;
13361 		    off = 0;
13362 		    break;
13363 		}
13364 		break;
13365 	      case _CMCFM:		/* Confirmation */
13366 		confirmed++;
13367 		break;
13368 	    }
13369 	}
13370 	if (closing) {
13371 	    if (learnfp) {
13372 		fclose(learnfp);
13373 		learnfp = NULL;
13374 	    }
13375 	    makestr(&learnfile,NULL);
13376 	}
13377 	if (line[0]) {
13378 	    if (!on && !off)
13379 	      on = 1;
13380 	    if (learnfp) {
13381 		fclose(learnfp);
13382 		learnfp = NULL;
13383 	    }
13384 	    makestr(&learnfile,line);
13385 	    if (learnfile) {
13386 		char * modes = "w";
13387 		learnfp = fopen(learnfile,modes);
13388 		if (!learnfp) {
13389 		    debug(F110,"LEARN file open error",learnfile,0);
13390 		    perror(learnfile);
13391 		    return(-9);
13392 		} else {
13393 #ifdef ZFNQFP
13394 		    if (zfnqfp(learnfile,TMPBUFSIZ,tmpbuf))
13395 		      makestr(&learnfile,tmpbuf);
13396 #endif /* ZFNQFP */
13397 		    debug(F110,"LEARN file open ok",learnfile,0);
13398 		    if (!quiet) {
13399 			printf("Recording to %s...\n\n",learnfile);
13400 			printf(
13401 " WARNING: If you type your password during script recording, it will appear\n\
13402  in the file.  Be sure to edit it or take other appropriate precautions.\n\n"
13403 			       );
13404 		    }
13405 		    fputs(  "; Scriptfile: ",learnfp);
13406 		    fputs(learnfile,learnfp);
13407 		    fputs("\n; Directory:  ",learnfp);
13408 		    fputs(zgtdir(),learnfp);
13409 		    fputs("\n; Recorded:   ",learnfp);
13410 		    fputs(ckdate(),learnfp);
13411 		    fputs("\n",learnfp);
13412 		}
13413 	    }
13414 	}
13415 	if (on) {
13416 	    learning = 1;
13417 	} else if (off) {
13418 	    learning = 0;
13419 	}
13420 	debug(F101,"LEARN learning","",learning);
13421 	return(success = 1);
13422     }
13423 #endif /* CKLEARN */
13424 
13425 #ifdef NEWFTP
13426     if (cx == XXUSER || cx == XXACCT) {
13427 	if (!ftpisopen()) {
13428 	    printf("?FTP connection is not open\n");
13429 	    return(-9);
13430 	}
13431 	return(success = (cx == XXUSER) ? doftpusr() : doftpacct());
13432     }
13433     if (cx == XXSITE || cx == XXPASV) {
13434 	if (!ftpisopen()) {
13435 	    printf("?FTP connection is not open\n");
13436 	    return(-9);
13437 	}
13438 	return(success = (cx == XXSITE) ? doftpsite() : dosetftppsv());
13439     }
13440 #endif /* NEWFTP */
13441 
13442     if (cx == XXORIE) {			/* ORIENTATION */
13443 	extern char * myname;
13444 	int i, y, n = 0;
13445         char * s, *p, vbuf[32];
13446 	char * vars[16];       char * legend[16];
13447 
13448 	if ((y = cmcfm()) < 0)
13449 	  return(y);
13450 
13451 	printf("\nProgram name:\n  %s\n\n",myname);
13452 	n += 4;
13453 
13454 #ifdef NT
13455 	vars[0] = "home";      legend[0] = "Your home directory";
13456 	vars[1] = "directory"; legend[1] = "K95's current directory";
13457 	vars[2] = "exedir";    legend[2] = "K95 Program directory";
13458 	vars[3] = "inidir";    legend[3] = "K95 Initialization file directory";
13459 	vars[4] = "startup";   legend[4] = "Current directory when started";
13460 
13461         vars[5] = "common";
13462         legend[5] = "K95 data for all users and K95SITE.INI file";
13463 
13464         vars[6] = "personal";  legend[6] = "Your personal data directory tree";
13465         vars[7] = "desktop";   legend[7] = "Your deskop directory tree";
13466 
13467         vars[8] = "appdata";
13468         legend[8] = "Your personal K95 data tree and K95CUSTOM.INI file";
13469 
13470         vars[9] = "download";  legend[9] = "Your K95 download directory";
13471         vars[10] = "tmpdir";   legend[10] = "Your TEMP directory";
13472 	vars[11] = NULL;       legend[11] = NULL;
13473 
13474 	for (i = 0; i < 16 && vars[i]; i++) {
13475 	    printf("%s:\n",legend[i]);
13476 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13477 	    ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
13478 	    printf("  Variable:   %s\n",vbuf);
13479 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13480 	    y = TMPBUFSIZ;
13481 	    s = tmpbuf;
13482 	    zzstring(vbuf,&s,&y);
13483 	    line[0] = NUL;
13484 	    ckGetLongPathName(tmpbuf,line,LINBUFSIZ);
13485 	    printf("  Long name:  %s\n",line);
13486 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13487 	    line[0] = NUL;
13488 	    GetShortPathName(tmpbuf,line,LINBUFSIZ);
13489 	    printf("  Short name: %s\n",line);
13490 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13491             printf("\n");
13492 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13493 	}
13494 #else  /* NT */
13495 
13496 	vars[0] = "home";      legend[0] = "Your home directory";
13497 	vars[1] = "directory"; legend[1] = "Kermit's current directory";
13498 	vars[2] = "exedir";    legend[2] = "Kermit's program directory";
13499 	vars[3] = "inidir";    legend[3] = "Initialization file directory";
13500 	vars[4] = "startup";   legend[4] = "Current directory when started";
13501 	vars[5] = "download";  legend[5] = "Kermit download directory";
13502 	vars[6] = NULL;	       legend[6] = NULL;
13503 
13504 	for (i = 0; i < 16 && vars[i]; i++) {
13505 	    printf("%s:\n",legend[i]);
13506 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13507 	    ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
13508 	    printf("  Variable: %s\n",vbuf);
13509 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13510 	    y = TMPBUFSIZ;
13511 	    s = tmpbuf;
13512 	    zzstring(vbuf,&s,&y);
13513             printf("  Value:    %s\n",tmpbuf);
13514 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13515             printf("\n");
13516 	    if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13517 	}
13518 #endif /* NT */
13519 	return(success = 1);
13520     }
13521 
13522 #ifdef NT
13523     if (cx == XXDIALER) {
13524         StartDialer();
13525         return(success = 1);
13526     }
13527 #endif /* NT */
13528 
13529     if (cx == XXCONT) {			/* CONTINUE */
13530 	if ((x = cmcfm()) < 0)
13531 	  return(x);
13532 	if (!xcmdsrc) {			/* At prompt: continue script */
13533 	    if (cmdlvl > 0)
13534 	      popclvl();		/* Pop command level */
13535 	    return(success = 1);	/* always succeeds */
13536 #ifndef NOSPL
13537 	} else {			/* In script: whatever... */
13538 	    x = mlook(mactab,"continue",nmac);
13539 	    /* Don't set success */
13540 	    return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
13541 #endif /* NOSPL */
13542 	}
13543     }
13544 #ifdef UNIX
13545 #ifndef NOPUTENV
13546 /*
13547   NOTE: Syntax is PUTENV name value, not PUTENV name=value.
13548   I could check for this but it would be too much magic.
13549 */
13550     if (cx == XXPUTE) {			/* PUTENV */
13551         char * t = tmpbuf;		/* Create or alter environment var */
13552 	char * s1 = NULL, * s2 = NULL;
13553 	if ((x = cmfld("Variable name","",&s,xxstring)) < 0)
13554           return(x);
13555 	if (s) if (s == "") s = NULL;
13556 	(VOID) makestr(&s1,s);
13557 	if (s && !s1) {
13558 	    printf("?PUTENV - memory allocation failure\n");
13559 	    return(-9);
13560 	}
13561 	if ((x = cmtxt("Value","",&s,xxstring)) < 0)
13562 	  return(x);
13563 	if (s) if (s == "") s = NULL;
13564 	(VOID) makestr(&s2,s);
13565 	success = doputenv(s1,s2);
13566 	(VOID) makestr(&s1,NULL);
13567 	(VOID) makestr(&s2,NULL);
13568 	return(success);
13569     }
13570 #endif	/* NOPUTENV */
13571 #endif	/* UNIX */
13572 
13573     if (cx == XXNOTAV) {		/* Command in table not available */
13574 	ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
13575 	if ((x = cmtxt("Rest of command","",&s,NULL)) < 0)
13576 	  return(x);
13577 	printf("Sorry, \"%s\" not configured in this version of Kermit.\n",
13578 	       tmpbuf
13579 	       );
13580 	return(success = 0);
13581     }
13582     return(-2);				/* None of the above */
13583 
13584 } /* end of docmd() */
13585 
13586 #endif /* NOICP */
13587