dh_installchangelogs: adjust to use ckc301.txt. changelog: explain -O1 usage
[ckermit.git] / ckuusr.c
1 #ifdef SSHTEST
2 #define SSHBUILTIN
3 #endif /* SSHTEST */
4
5 #include "ckcsym.h"
6 char *userv = "User Interface 9.0.299, 9 Jun 2011";
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, Columbia University, New York City
14     Jeffrey E Altman <jaltman@secure-endpoints.com>
15       Secure Endpoints Inc., New York City
16
17   Copyright (C) 1985, 2011,
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   system- 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 int display_demo = 1;
140 #include "ckossh.h"
141 #ifdef KUI
142 #include "ikui.h"
143 #endif /* KUI */
144 #endif /* OS2 */
145
146 int optlines = 0;
147 int didsetlin = 0;
148
149 #ifdef NEWFTP
150 extern int ftpget, ftpisopen(), doftpres();
151 _PROTOTYP(int doftptyp,(int));
152 _PROTOTYP(VOID doftpglobaltype,(int));
153 #endif /* NEWFTP */
154
155 #ifdef VMS
156 extern int batch;
157 #endif /* VMS */
158
159 #ifdef datageneral
160 #include <packets:common.h>
161 #define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
162 #endif /* datageneral */
163
164 extern int xcmdsrc, hints, cmflgs, whyclosed;
165
166 char * hlptok = NULL;
167
168 #ifdef CK_TTGWSIZ                       /* Whether to use more-prompting */
169 int xaskmore = 1;                       /* Momentary setting */
170 int saveask  = 1;                       /* Permanent setting */
171 #else
172 int xaskmore = 0;
173 int saveask  = 0;
174 #endif /* CK_TTGWSIZ */
175
176 #ifndef NOCSETS
177 extern int nfilc;
178 extern struct keytab fcstab[];
179 extern int fcharset;
180 #endif /* NOCSETS */
181
182 char * g_pswd = NULL;
183 int g_pcpt = -1;
184 int g_pflg = -1;
185
186 extern int cmd_rows, cmd_cols;
187
188 #ifdef CKROOT
189 extern int ckrooterr;
190 #endif /* CKROOT */
191
192 extern int inserver, filepeek;
193
194 #ifdef CKLEARN
195 FILE * learnfp = NULL;
196 char * learnfile = NULL;
197 int learning = 0;
198 #endif /* CKLEARN */
199
200 #ifndef NOXFER
201 extern int atcapr, atdiso, nfils, moving, protocol, sendmode, epktflg, size,
202   sndsrc, server, displa, fncnv, fnspath, fnrpath, xfermode, urpsiz,
203   spsizf, spsiz, spsizr, spmax, wslotr, prefixing, fncact, reliable,
204   setreliable;
205
206 #ifdef IKSDCONF
207 extern int iksdcf;
208 #endif /* IKSDCONF */
209
210 #ifdef CK_LOGIN
211 extern int isguest;
212 #endif /* CK_LOGIN */
213
214 extern CK_OFF_T sendstart;
215
216 extern char *cmarg, *cmarg2, **cmlist, *dftty;
217
218 extern struct keytab fntab[]; extern int nfntab;
219 extern struct ck_p ptab[NPROTOS];
220
221 int sndcmd = 0;         /* Last command was a SEND-class command. */
222
223 int g_xfermode = -1;
224 int g_proto  = -1;
225 int g_urpsiz = -1;
226 int g_spsizf = -1;
227 int g_spsiz  = -1;
228 int g_spsizr = -1;
229 int g_spmax  = -1;
230 int g_wslotr = -1;
231 int g_prefixing = -1;
232 int g_fncnv  = -1;
233 int g_fnspath = -1;
234 int g_fnrpath = -1;
235 int g_fnact  = -1;
236 int g_displa = -1;
237 int g_spath  = -1;
238 int g_rpath  = -1;
239 char * g_sfilter = NULL;
240 char * g_rfilter = NULL;
241
242 extern int patterns;
243 #ifdef PATTERNS
244 extern char *txtpatterns[], *binpatterns[];
245 int g_patterns = -1;
246 #endif /* PATTERNS */
247 int g_skipbup = -1;
248
249 #ifdef PIPESEND
250 extern int usepipes, pipesend;
251 extern char * sndfilter;
252 #endif /* PIPESEND */
253
254 #ifndef NOSPL
255 extern int sndxlo, sndxhi, sndxin;
256 #endif /* NOSPL */
257
258 extern char fspec[];                    /* Most recent filespec */
259 extern int fspeclen;                    /* Length of fspec[] buffer */
260
261 #ifndef NOFRILLS
262 extern int rmailf;                      /* MAIL command items */
263 extern char optbuf[];
264 #endif /* NOFRILLS */
265
266 extern int
267   en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
268   en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
269   en_mkd, en_rmd, en_asg;
270
271 #ifndef NOMSEND                         /* Multiple SEND */
272 extern char *msfiles[];
273 int filesinlist = 0;                    /* And ADD ... */
274 extern struct filelist * filehead;
275 extern struct filelist * filetail;
276 extern struct filelist * filenext;
277 extern int addlist;
278 #endif /* NOMSEND */
279
280 static struct keytab addtab[] = {
281 #ifdef PATTERNS
282     { "binary-patterns", ADD_BIN, 0 },
283 #endif /* PATTERNS */
284 #ifndef NOMSEND
285     { "send-list", ADD_SND, 0 },
286 #endif /* NOMSEND */
287 #ifdef PATTERNS
288     { "text-patterns", ADD_TXT, 0 },
289 #endif /* PATTERNS */
290     { "", 0, 0 }
291 };
292 static int naddtab = sizeof(addtab)/sizeof(struct keytab) - 1;
293
294 #ifndef NOCSETS
295 struct keytab assoctab[] = {
296     { "file-character-set",     ASSOC_FC, 0 },
297     { "transfer-character-set", ASSOC_TC, 0 },
298     { "xfer-character-set",     ASSOC_TC, CM_INV }
299 };
300 static int nassoc = sizeof(assoctab)/sizeof(struct keytab);
301 extern int afcset[MAXFCSETS+1];         /* Character-set associations */
302 extern int axcset[MAXTCSETS+1];
303 #endif /* NOCSETS */
304
305 #ifndef ADDCMD
306 #ifndef NOMSEND
307 #define ADDCMD
308 #endif /* NOMSEND */
309 #ifndef ADDCMD
310 #ifdef PATTERNS
311 #define ADDCMD
312 #endif /* PATTERNS */
313 #endif /* ADDCMD */
314 #endif /* ADDCMD */
315 #endif /* NOXFER */
316
317 /* External Kermit Variables, see ckmain.c for description. */
318
319 extern xx_strp xxstring;
320 extern long xvernum;
321
322 extern int local, xitsta, binary, msgflg, escape, duplex, quiet, tlevel,
323   pflag, zincnt, ckxech, carrier, what, nopush, haveline, bye_active;
324 #ifdef TNCODE
325 extern int debses;
326 extern char tn_msg[];
327 #endif /* TNCODE */
328
329 int sleepcan = 1;
330 int g_binary = -1;
331 int g_recursive = -1;
332 int g_matchdot = -1;
333 extern int nolinks;
334
335 extern long vernum;
336 extern char *versio, *copyright[];
337 extern char *ckxsys;
338 #ifndef NOHELP
339 extern char *introtxt[];
340 extern char *newstxt[];
341 #endif /* NOHELP */
342
343 #ifndef OS2
344 #ifndef UNIX
345 extern char *PWDCMD;
346 #endif /* UNIX */
347 extern char *WHOCMD;
348 #endif /* OS2 */
349
350 extern char ttname[];
351
352 extern CHAR sstate;
353
354 extern int network;                     /* Have active network connection */
355 extern int nettype;                     /* Type of network */
356 extern int ttnproto;                    /* NET_TCPB protocol */
357
358 #ifndef NODIAL
359 extern int dialsta, dialatmo, dialcon, dialcq; /* DIAL status, etc. */
360 #endif /* NODIAL */
361
362 #ifdef CK_APC
363 extern int apcactive, apcstatus;
364 #endif /* CK_APC */
365
366 #ifndef NOPUSH
367 #ifndef NOFRILLS
368 extern char editor[];
369 extern char editopts[];
370 extern char editfile[];
371 #endif /* NOFRILLS */
372 #endif /* NOPUSH */
373
374 #ifdef BROWSER
375 extern char browser[];                  /* Web browser application */
376 extern char browsopts[];                /* Web browser options */
377 extern char browsurl[];                 /* Most recent URL */
378 #endif /* BROWSER */
379 #ifndef NOFTP
380 char ftpapp[CKMAXPATH+1] = { NUL, NUL }; /* ftp executable */
381 char ftpopts[128] = { NUL, NUL };       /* ftp command-line options */
382 #endif /* NOFTP */
383 extern struct keytab onoff[];           /* On/Off keyword table */
384
385 #ifdef CK_TMPDIR
386 int f_tmpdir = 0;                       /* Directory changed temporarily */
387 char savdir[TMPDIRLEN];                 /* For saving current directory */
388 #endif /* CK_TMPDIR */
389
390 int activecmd = -1;                     /* Keyword index of active command */
391 int doconx = -1;                        /* CONNECT-class command active */
392 int ooflag = 0;                         /* User-settable on/off flag */
393
394 int rcflag = 0;                         /* Pointer to home directory string */
395 int repars,                             /* Reparse needed */
396     techo = 0;                          /* Take echo */
397 int secho = 1;                          /* SCRIPT echo */
398
399 int xitwarn =                   /* Warn about open connection on exit */
400 #ifdef NOWARN
401 0
402 #else
403 1
404 #endif /* NOWARN */
405 ;
406
407 struct keytab onoffsw[] = {
408     { "/off", 0, 0 },
409     { "/on",  1, 0 }
410 };
411
412 #ifdef CKEXEC
413 struct keytab redirsw[] = {
414     { "/redirect", 1, 0 }
415 };
416 #endif /* CKEXEC */
417
418 #ifndef NOXMIT
419 /* Variables for TRANSMIT command */
420
421 int xmitx = 1;                  /* Whether to echo during TRANSMIT */
422 int xmitf = 0;                  /* Character to fill empty lines */
423 int xmitl = 0;                  /* 0 = Don't send linefeed too */
424 int xmitp = LF;                 /* Host line prompt */
425 int xmits = 0;                  /* Use shift-in/shift-out, 0 = no */
426 int xmitw = 0;                  /* Milliseconds to pause during TRANSMIT */
427 int xmitt = 1;                  /* Seconds to wait for each char to echo */
428 int xmita = 1;                  /* Action upon timeout */
429
430 #define XMI_BIN 1
431 #define XMI_TXT 2
432 #define XMI_CMD 3
433 #define XMI_TRA 4
434 #define XMI_VRB 5
435 #define XMI_QUI 6
436 #define XMI_NOW 7
437 #define XMI_NOE 8
438
439 static struct keytab xmitsw[] = {       /* TRANSMIT command options */
440     { "/binary",          XMI_BIN, 0 },
441 #ifdef PIPESEND
442     { "/command",         XMI_CMD, CM_INV|CM_PSH },
443 #endif /* PIPESEND */
444     { "/noecho",          XMI_NOE, 0 },
445     { "/nowait",          XMI_NOW, 0 },
446 #ifdef PIPESEND
447     { "/pipe",            XMI_CMD, 0 },
448 #endif /* PIPESEND */
449 #ifdef COMMENT
450     { "/quiet",           XMI_QUI, 0 },
451 #endif /* COMMENT */
452     { "/text",            XMI_TXT, 0 },
453     { "/transparent",     XMI_TRA, 0 },
454 #ifdef COMMENT
455     { "/verbose",         XMI_VRB, 0 },
456 #endif /* COMMENT */
457     { "", 0, 0 }
458 };
459 #define NXMITSW sizeof(xmitsw)/sizeof(struct keytab) - 1
460 static int nxmitsw = NXMITSW;
461
462 #endif /* NOXMIT */
463
464 /* Declarations from ck?fio.c module */
465
466 extern char *SPACMD, *SPACM2;           /* SPACE commands */
467
468 /* Command-oriented items */
469
470 #ifdef DCMDBUF
471 extern char *cmdbuf;                    /* Command buffers */
472 extern char *atmbuf;
473 extern char *line;                      /* Character buffer for anything */
474 extern char *tmpbuf;                    /* Short temporary string buffer */
475 extern int *ifcmd;
476 extern int *intime;
477 extern int *inpcas;
478 #else
479 extern char cmdbuf[];                   /* Command buffers */
480 extern char atmbuf[];
481 extern char line[];                     /* Character buffer for anything */
482 extern char tmpbuf[];                   /* Temporary buffer */
483 extern int ifcmd[];
484 extern int intime[];
485 extern int inpcas[];
486 #endif /* DCMDBUF */
487
488 #ifndef NOSPL
489 extern char * prstring[];
490 #endif /* NOSPL */
491
492 char *lp;                               /* Pointer to line buffer */
493
494 #ifndef NOSPL
495 int vareval = 1;                        /* Evaluation method */
496 int unkmacro = 0;                       /* Flag for in ON_UNKNOWN_COMMAND */
497 int oldeval = 0;
498 char evalbuf[33];                       /* EVALUATE result */
499 extern char * inpbuf;                   /* Buffer for INPUT and REINPUT */
500 char *inpbp;                            /* And pointer to same */
501 int m_found;                            /* MINPUT result */
502 int i_active = 0;                       /* INPUT command is active */
503 char *ms[MINPMAX];                      /* Pointers to MINPUT strings */
504 static int mpinited = 0;                /* Flag they have been initialized */
505 static int mp[MINPMAX];                 /* and MINPUT flags */
506 extern int fndiags, fnerror, fnsuccess; /* Function diagnostics */
507 #ifndef NOSEXP
508 char * lastsexp = NULL;                 /* S-Expressions */
509 char * sexpval = NULL;
510 int sexpecho = SET_AUTO;
511 #endif /* NOSEXP */
512 #endif /* NOSPL */
513
514 char psave[PROMPTL] = { NUL };          /* For saving & restoring prompt */
515
516 extern int success;                     /* Command success/failure flag */
517 extern int cmdlvl;                      /* Current position in command stack */
518
519 #ifndef NOSPL
520 int                                     /* SET INPUT parameters. */
521 /* Note, INPUT TIMEOUT, intime[], is on the command-level stack. */
522   inbufsize = 0,                        /* INPUT buffer size */
523   indef = 1,                            /* default timeout, seconds */
524   inecho = 1,                           /* 1 = echo on */
525   inautodl = 0,                         /* INPUT autodownload */
526   inintr = 1,                           /* INPUT interrupion allowed */
527   insilence = 0;                        /* 0 = no silence constraint */
528
529 #ifdef CKFLOAT
530 CKFLOAT inscale = 1.0;                  /* Timeout scale factor */
531 #endif  /* CKFLOAT */
532
533 #ifdef OS2
534 int interm = 1;                         /* Terminal emulator displays input */
535 #endif /* OS2 */
536 int maclvl = -1;                        /* Macro nesting level */
537 int mecho = 0;                          /* Macro echo, 0 = don't */
538 char varnam[6];                         /* For variable names */
539 extern int macargc[];                   /* ARGC from macro invocation */
540
541 extern char *m_arg[MACLEVEL][NARGS];    /* Stack of macro arguments */
542 extern char *mrval[];
543
544 extern char **a_ptr[];                  /* Array pointers */
545 extern int a_dim[];                     /* Array dimensions */
546 extern int a_link[];
547
548 #ifdef DCMDBUF
549 extern struct cmdptr *cmdstk;           /* The command stack itself */
550 #else
551 extern struct cmdptr cmdstk[];          /* The command stack itself */
552 #endif /* DCMDBUF */
553
554 long ck_alarm = 0;                      /* SET ALARM value */
555 char alrm_date[24] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ' };
556 char alrm_time[24] = { ' ',' ',' ',' ',' ',' ',' ' };
557
558 struct keytab inputsw[] = {
559     { "/clear",   INPSW_CLR, 0 },
560     { "/count",   INPSW_COU, CM_ARG },
561     { "/nomatch", INPSW_NOM, 0 },
562     { "/nowrap",  INPSW_NOW, 0 }
563 };
564 static int ninputsw = sizeof(inputsw)/sizeof(struct keytab);
565
566 /* The following should be reconciled with the above */
567
568 #ifdef COMMENT                          /* INPUT switches not used yet... */
569 static struct keytab inswtab[] = {
570 #ifdef COMMENT
571     { "/assign",       IN_ASG, CM_ARG },
572 #endif /* COMMENT */
573     { "/autodownload", IN_ADL, CM_ARG },
574     { "/case",         IN_CAS, CM_ARG },
575     { "/echo",         IN_ECH, CM_ARG },
576     { "/interrupts",   IN_NOI, CM_ARG },
577     { "/silence",      IN_SIL, CM_ARG },
578 #ifdef COMMENT
579     { "/pattern",      IN_PAT, CM_ARG },
580 #endif /* COMMENT */
581     { "", 0, 0 }
582 };
583 static int ninswtab = (sizeof(inswtab) / sizeof(struct keytab)) - 1;
584 #endif /* COMMENT */
585
586
587 #endif /* NOSPL */
588
589 static int x, y, z = 0;                 /* Local workers */
590 static char *s;
591
592 #ifdef CK_MINPUT
593 static char c1chars[] = {               /* C1 control chars escept NUL */
594     001,002,003,004,005,006,007,010,011,012,013,014,015,016,017,020,
595     021,022,023,024,025,026,027,030,031,032,033,034,035,036,037
596 };
597 #endif /* CK_MINPUT */
598
599 #define xsystem(s) zsyscmd(s)
600
601 /* Top-Level Interactive Command Keyword Table */
602 /* Keywords must be in lowercase and in alphabetical order. */
603
604 struct keytab cmdtab[] = {
605 #ifndef NOPUSH
606     { "!",         XXSHE, CM_INV|CM_PSH }, /* Shell escape */
607 #else
608     { "!",         XXNOTAV, CM_INV|CM_PSH },
609 #endif /* NOPUSH */
610     { "#",         XXCOM, CM_INV },     /* Comment */
611 #ifndef NOSPL
612     { "(",           XXSEXP,CM_INV },   /* S-Expression */
613     { ".",           XXDEF, CM_INV },   /* Assignment */
614     { ":",           XXLBL, CM_INV },   /* Label */
615 #endif /* NOSPL */
616 #ifdef CK_REDIR
617 #ifndef NOPUSH
618     { "<",           XXFUN, CM_INV|CM_PSH }, /* REDIRECT */
619 #else
620     { "<",           XXNOTAV, CM_INV|CM_PSH }, /* REDIRECT */
621 #endif /* NOPUSH */
622 #endif /* CK_REDIR */
623 #ifndef NOPUSH
624     { "@",           XXSHE, CM_INV|CM_PSH }, /* DCL escape */
625 #else
626     { "@",           XXNOTAV, CM_INV|CM_PSH }, /* DCL escape */
627 #endif /* NOPUSH */
628
629 #ifdef CK_RECALL
630     { "^",           XXREDO,CM_INV|CM_NOR }, /* Synonym for REDO */
631 #endif /* CK_RECALL */
632 #ifndef NOSPL
633     { "_asg",        XXASX,   CM_INV }, /* Used internally by FOR, etc */
634     { "_assign",     XXASX,   CM_INV }, /* Used internally by FOR, etc */
635     { "_decrement",  XX_DECR, CM_INV },
636     { "_define",     XXDFX,   CM_INV }, /* Used internally by FOR, etc */
637     { "_evaluate",   XX_EVAL, CM_INV },
638     { "_forward",    XXXFWD,  CM_INV }, /* Used internally by SWITCH   */
639     { "_getargs",    XXGTA,   CM_INV }, /* Used internally by FOR, etc */
640     { "_increment",  XX_INCR, CM_INV },
641     { "_putargs",    XXPTA,   CM_INV }, /* Used internally by FOR, etc */
642     { "_undefine",   XXUNDFX, CM_INV },
643 #endif /* NOSPL */
644
645     { "about",       XXVER,   CM_INV }, /* Synonym for VERSION */
646 #ifndef NOSPL
647 #ifdef NEWFTP
648     { "account",     XXACCT,  CM_INV }, /* (FTP) Account */
649 #endif /* NEWFTP */
650 #ifdef ADDCMD
651     { "add",         XXADD, 0 },        /* ADD */
652 #endif /* ADDCMD */
653 #ifndef NODIAL
654     { "answer",      XXANSW, CM_LOC },  /* ANSWER the phone */
655 #else
656     { "answer",      XXNOTAV, CM_INV|CM_LOC }, /* ANSWER the phone */
657 #endif /* NODIAL */
658     { "apc",         XXAPC, 0 },        /* Application Program Command */
659 #ifndef NOSPL
660     { "array",       XXARRAY, 0 },      /* Array operations */
661 #endif /* NOSPL */
662     { "ascii",       XXASC, CM_INV },   /* == SET FILE TYPE TEXT */
663     { "asg",         XXASS, CM_INV },   /* Invisible synonym for ASSIGN */
664     { "ask",         XXASK, 0 },        /* ASK for text, assign to variable */
665     { "askq",        XXASKQ,0 },        /* ASK quietly (no echo) */
666 #ifndef NOSPL
667     { "ass",         XXASS, CM_INV|CM_ABR }, /* ASSIGN */
668     { "assert",      XXASSER, CM_INV }, /* ASSERT */
669     { "assign",      XXASS, 0 },        /* ASSIGN */
670 #endif /* NOSPL */
671 #ifndef NOXFER
672 #ifndef NOCSETS
673     { "associate",   XXASSOC, 0 },      /* ASSOCIATE */
674 #else
675     { "associate",   XXNOTAV, CM_INV }, /* ASSOCIATE */
676 #endif /* NOCSETS */
677 #endif /* NOXFER */
678 #ifdef CK_KERBEROS
679 #ifdef CK_AUTHENTICATION
680     { "authenticate",XXAUTH, 0 },       /* Authentication */
681 #else
682     { "authenticate",XXAUTH, CM_INV },
683 #endif /* CK_AUTHENTICATION */
684 #endif /* CK_KERBEROS */
685 #endif /* NOSPL */
686 #ifndef NOFRILLS
687     { "back",        XXBACK, 0 },       /* BACK to previous directory */
688 #else
689     { "back",        XXNOTAV,CM_INV },
690 #endif /* NOFRILLS */
691     { "beep",        XXBEEP,CM_INV },   /* BEEP */
692 #ifndef NOXFER
693     { "binary",      XXBIN, CM_INV },   /* == SET FILE TYPE BINARY */
694 #endif /* NOXFER */
695 #ifndef NOFRILLS
696     { "bug",         XXBUG, CM_INV },   /* BUG report instructions */
697 #else
698     { "bug",         XXNOTAV, CM_INV },
699 #endif /* NOFRILLS */
700 #ifdef BROWSER
701     { "browse",      XXBROWS, CM_PSH|CM_LOC }, /* BROWSE (start browser) */
702 #else
703     { "browse",      XXNOTAV, CM_INV|CM_PSH|CM_LOC },
704 #endif /* BROWSER */
705 #ifndef NOXFER
706     { "bye",         XXBYE, 0 },        /* BYE to remote server */
707 #endif /* NOXFER */
708 #ifndef NOLOCAL
709     { "c",           XXCON, CM_INV|CM_ABR|CM_LOC }, /* (CONNECT) */
710 #endif /* NOLOCAL */
711 #ifndef NOFRILLS
712     { "cat",         XXCAT, CM_INV },   /* Invisible synonym for TYPE */
713 #endif /* NOFRILLS */
714 #ifndef NOSPL
715
716 #ifndef NOXFER
717     { "cautious",    XXCAU, CM_INV },
718 #endif /* NOXFER */
719
720 #endif /* NOSPL */
721
722     { "cd",          XXCWD, 0 },        /* Change Directory */
723     { "cdup",        XXCDUP, CM_INV },  /* Change Directory Up */
724
725 #ifndef NOXFER
726 #ifdef PIPESEND
727     { "cget",        XXCGET, CM_INV|CM_PSH }, /* CGET */
728 #else
729     { "cget",        XXNOTAV, CM_INV|CM_PSH }, /* CGET */
730 #endif /* PIPESEND */
731 #endif /* NOXFER */
732     { "ch",          XXCHK,   CM_INV|CM_ABR },
733     { "check",       XXCHK,   0 },      /* CHECK for a feature */
734 #ifdef CK_PERMS
735 #ifdef UNIX
736     { "chmod",       XXCHMOD, 0 },      /* CHMOD */
737 #else
738     { "chmod",       XXNOTAV, CM_INV },
739 #endif /* UNIX */
740 #else
741     { "chmod",       XXNOTAV, CM_INV },
742 #endif /* CK_PERMS */
743 #ifdef CKROOT
744     { "chroot",      XXCHRT,  CM_INV }, /* CHROOT */
745 #endif /* CKROOT */
746     { "ckermit",     XXKERMI, CM_INV }, /* CKERMIT (like KERMIT) */
747     { "cl",          XXCLO,   CM_ABR|CM_INV },
748 #ifndef NOFRILLS
749     { "clear",       XXCLE, 0 },        /* CLEAR input and/or device buffer */
750 #else
751     { "clear",       XXNOTAV, CM_INV },
752 #endif /* NOFRILLS */
753     { "close",       XXCLO, 0 },        /* CLOSE a log or other file */
754     { "cls",         XXCLS, CM_INV },   /* Clear Screen (CLS) */
755     { "comment",     XXCOM, CM_INV },   /* Introduce a comment */
756 #ifndef NOLOCAL
757     { "connect",     XXCON, CM_LOC },   /* Begin terminal connection */
758 #else
759     { "connect",     XXNOTAV, CM_LOC },
760 #endif /* NOLOCAL */
761     { "continue",    XXCONT,  CM_INV }, /* CONTINUE */
762 #ifndef NOFRILLS
763 #ifdef ZCOPY
764     { "co",          XXCPY, CM_INV|CM_ABR },
765     { "cop",         XXCPY, CM_INV|CM_ABR },
766     { "copy",        XXCPY, 0 },        /* COPY a file */
767 #else
768     { "copy",        XXNOTAV, CM_INV },
769 #endif /* ZCOPY */
770     { "copyright",   XXCPR, CM_INV },   /* COPYRIGHT */
771 #ifdef ZCOPY
772     { "cp",          XXCPY, CM_INV },   /* COPY a file */
773 #endif /* ZCOPY */
774 #ifndef NOLOCAL
775 #ifndef OS2
776     { "cq",          XXCQ, CM_INV|CM_LOC }, /* CQ (connect quietly) */
777 #endif /* OS2 */
778 #endif /* NOLOCAL */
779 #ifndef NOXFER
780 #ifdef PIPESEND
781     { "creceive",    XXCREC,CM_INV|CM_PSH }, /* RECEIVE to a command */
782     { "csend",       XXCSEN,CM_INV|CM_PSH }, /* SEND from command */
783 #else
784     { "creceive",    XXNOTAV,CM_INV|CM_PSH },
785     { "csend",       XXNOTAV,CM_INV|CM_PSH },
786 #endif /* PIPESEND */
787 #endif /* NOXFER */
788 #endif /* NOFRILLS */
789
790     { "cwd",         XXCWD,   CM_INV }, /* Traditional synonym for cd */
791
792 #ifndef NOSPL
793     { "date",        XXDATE,  0 },      /* DATE */
794     { "dcl",         XXDCL,   CM_INV }, /* DECLARE an array (see ARRAY) */
795     { "debug",       XXDEBUG, 0 },      /* Print a debugging msg [9.0]  */
796     { "declare",     XXDCL,   CM_INV }, /* DECLARE an array (see ARRAY) */
797     { "decrement",   XXDEC,   0 },      /* DECREMENT a numeric variable */
798     { "define",      XXDEF,   0 },      /* DEFINE a macro or variable   */
799 #else
800     { "date",        XXNOTAV, CM_INV },
801     { "dcl",         XXNOTAV, CM_INV },
802     { "declare",     XXNOTAV, CM_INV },
803     { "decrement",   XXNOTAV, CM_INV },
804     { "define",      XXNOTAV, CM_INV },
805 #endif /* NOSPL */
806
807 #ifndef NOFRILLS
808     { "delete",      XXDEL, 0 },        /* DELETE a file */
809 #else
810     { "delete",      XXNOTAV, CM_INV },
811 #endif /* NOFRILLS */
812
813 #ifndef NODIAL
814     { "dial",        XXDIAL,  CM_LOC }, /* DIAL a phone number */
815 #else
816     { "dial",        XXNOTAV, CM_INV|CM_LOC },
817 #endif /* NODIAL */
818
819 #ifdef NT
820     { "dialer",      XXDIALER, CM_INV }, /* K95 Dialer */
821 #endif /* NT */
822
823     { "directory",   XXDIR, 0 },        /* DIRECTORY of files */
824
825 #ifndef NOFRILLS
826 #ifndef NOSERVER
827     { "disable",     XXDIS, 0 },        /* DISABLE a server function */
828 #else
829     { "disable",     XXNOTAV, CM_INV },
830 #endif /* NOSERVER */
831 #endif /* NOFRILLS */
832
833 #ifndef NOSPL
834     { "do",          XXDO,  0 },        /* DO (execute) a macro */
835 #else
836     { "do",          XXNOTAV, CM_INV },
837 #endif /* NOSPL */
838
839     { "e",           XXEXI, CM_INV|CM_ABR },
840
841 #ifndef NOFRILLS
842 #ifndef NOXFER
843     { "e-packet",    XXERR, CM_INV },   /* Send an Error-Packet */
844 #endif /* NOXFER */
845 #endif /* NOFRILLS */
846
847     { "echo",        XXECH, 0 },        /* ECHO text */
848
849 #ifndef NOFRILLS
850 #ifndef NOPUSH
851     { "edit",        XXEDIT, CM_PSH },  /* EDIT */
852 #else
853     { "edit",        XXNOTAV, CM_INV|CM_PSH }, /* EDIT */
854 #endif /* NOPUSH */
855 #endif /* NOFRILLS */
856
857     { "eightbit",    XXEIGHT, CM_INV }, /* EIGHTBIT */
858
859 #ifndef NOSPL
860     { "else",        XXELS, CM_INV },   /* ELSE part of IF statement */
861 #else
862     { "else",        XXNOTAV, CM_INV }, /* ELSE part of IF statement */
863 #endif /* NOSPL */
864
865 #ifndef NOSERVER
866 #ifndef NOFRILLS
867     { "enable",      XXENA,  0 },       /* ENABLE a server function */
868 #else
869     { "enable",      XXNOTAV, CM_INV },
870 #endif /* NOFRILLS */
871 #endif /* NOSERVER */
872
873 #ifndef NOSPL
874     { "end",         XXEND,  0 },       /* END command file or macro */
875 #else
876     { "end",         XXNOTAV, CM_INV },
877 #endif /* NOSPL */
878
879     { "erase",       XXDEL, CM_INV },   /* Synonym for DELETE */
880
881 #ifndef NOSPL
882     { "evaluate",    XXEVAL, 0 },       /* EVALUATE */
883 #else
884     { "evaluate",    XXNOTAV, CM_INV },
885 #endif /* NOSPL */
886
887     { "ex",          XXEXI, CM_INV|CM_ABR }, /* Let "ex" still be EXIT */
888
889 #ifdef CKEXEC
890     { "exec",        XXEXEC, CM_INV|CM_LOC }, /* exec() */
891 #else
892     { "exec",        XXNOTAV, CM_INV|CM_LOC },
893 #endif /* CKEXEC */
894
895     { "exit",      XXEXI, 0 },          /* EXIT from C-Kermit */
896     { "extended-options", XXXOPTS,CM_INV|CM_HLP }, /* Extended-Options */
897
898 #ifdef OS2
899     { "extproc",     XXCOM, CM_INV },   /* Dummy command for OS/2 */
900 #endif /* OS2 */
901
902 #ifndef NOXFER
903     { "f",           XXFIN, CM_INV|CM_ABR }, /* Invisible abbrev for FIN */
904 #endif /* NOXFER */
905
906 #ifndef NOSPL
907     { "fail",        XXFAIL, CM_INV },  /* FAIL */
908
909 #ifndef NOXFER
910     { "fast",        XXFAST, CM_INV },
911 #endif /* NOXFER */
912
913 #ifdef CKCHANNELIO
914     { "fclose",      XXF_CL, CM_INV },  /* FCLOSE */
915     { "fcount",      XXF_CO, CM_INV },  /* FCOUNT */
916     { "fflush",      XXF_FL, CM_INV },  /* FFLUSH */
917 #endif /* CKCHANNELIO */
918
919 #ifndef NOXFER
920     { "fi",          XXFIN, CM_INV|CM_ABR }, /* FINISH */
921 #endif /* NOXFER */
922
923 #ifdef CKCHANNELIO
924     { "file",        XXFILE, 0 },       /* FILE */
925 #endif /* CKCHANNELIO */
926 #endif /* NOSPL */
927
928 #ifndef NOXFER
929     { "fin",         XXFIN, CM_INV|CM_ABR }, /* FINISH */
930 #endif /* NOXFER */
931
932 #ifndef UNIXOROSK
933     { "find",        XXGREP, 0 },       /* FIND (grep) */
934 #else
935     { "find",        XXGREP,CM_INV },
936 #endif /* UNIXOROSK */
937
938 #ifndef NOXFER
939     { "finish",      XXFIN, 0 },        /* FINISH */
940 #endif /* NOXFER */
941
942 #ifdef TCPSOCKET
943     { "firewall",    XXFIREW, CM_INV|CM_HLP },
944 #endif /* TCPSOCKET */
945
946 #ifdef CKCHANNELIO
947     { "flist",       XXF_LI, CM_INV },  /* FLIST */
948     { "fopen",       XXF_OP, CM_INV },  /* FOPEN */
949 #endif /* CKCHANNELIO */
950
951 #ifndef NOSPL
952     { "fo",          XXFOR, CM_INV|CM_ABR }, /* Invisible abbrev for... */
953     { "for",         XXFOR, 0 },        /* FOR loop */
954     { "forward",     XXFWD, CM_INV },   /* FORWARD */
955 #endif /* NOSPL */
956 #ifndef NOFRILLS
957     { "fot",       XXDIR, CM_INV },     /* "fot" = "dir" (for Chris) */
958 #endif /* NOFRILLS */
959
960 #ifdef CKCHANNELIO
961     { "fread",      XXF_RE, CM_INV },   /* FREAD */
962     { "frewind",    XXF_RW, CM_INV },   /* FREWIND */
963     { "fseek",      XXF_SE, CM_INV },   /* FSEEK */
964     { "fstatus",    XXF_ST, CM_INV },   /* FSTATUS */
965 #endif /* CKCHANNELIO */
966
967 #ifdef TCPSOCKET
968 #ifndef NOFTP
969 #ifdef SYSFTP
970 #ifndef NOPUSH
971     { "ftp",       XXFTP,   CM_INV|CM_PSH|CM_LOC }, /* System FTP */
972 #else
973     { "ftp",       XXNOTAV, CM_INV|CM_PSH|CM_LOC },
974 #endif /* NOPUSH */
975 #else  /* SYSFTP */
976     { "ftp",       XXFTP,   0 },        /* Built-in FTP */
977 #endif /* SYSFTP */
978 #else  /* NOFTP */
979     { "ftp",       XXNOTAV, CM_INV },   /* No FTP */
980 #endif /* NOFTP */
981 #endif /* TCPSOCKET */
982
983 #ifndef NOSPL
984     { "function",    XXFUNC, CM_INV|CM_HLP }, /* (for HELP FUNCTION) */
985 #endif /* NOSPL */
986
987 #ifdef CKCHANNELIO
988     { "fwrite",      XXF_WR, CM_INV },  /* FWRITE */
989 #endif /* CKCHANNELIO */
990
991 #ifndef NOXFER
992     { "g",           XXGET, CM_INV|CM_ABR }, /* Invisible abbrev for GET */
993 #ifndef NOSPL
994     { "ge",          XXGET, CM_INV|CM_ABR }, /* Ditto */
995 #endif /* NOSPL */
996     { "get",         XXGET, 0 },        /* GET */
997 #endif /* NOXFER */
998 #ifndef NOSPL
999     { "getc",        XXGETC, 0 },       /* GETC */
1000 #ifdef OS2
1001     { "getkeycode",  XXGETK, 0 },       /* GETKEYCODE */
1002 #endif /* OS2 */
1003 #ifndef NOFRILLS
1004     { "getok",       XXGOK, 0 },        /* GETOK (ask for Yes/No/OK) */
1005 #endif /* NOFRILLS */
1006 #endif /* NOSPL */
1007 #ifndef NOSPL
1008     { "goto",        XXGOTO,0 },        /* GOTO label in take file or macro */
1009 #endif /* NOSPL */
1010 #ifdef UNIXOROSK
1011     { "grep",        XXGREP,0 },        /* GREP (find) */
1012 #else
1013     { "grep",        XXGREP,CM_INV },   /* GREP (find) */
1014 #endif /* UNIXOROSK */
1015     { "h",           XXHLP, CM_INV|CM_ABR }, /* Invisible synonym for HELP */
1016     { "he",          XXHLP, CM_INV|CM_ABR }, /* Invisible synonym for HELP */
1017 #ifndef NOFRILLS
1018     { "head",        XXHEAD, 0 },
1019 #endif /* NOFRILLS */
1020 #ifndef NOLOCAL
1021     { "hangup",      XXHAN, CM_LOC },   /* HANGUP the connection */
1022 #endif /* NOLOCAL */
1023     { "hdirectory",  XXHDIR,  CM_INV }, /* DIR sorted by size biggest first */
1024     { "HELP",        XXHLP, 0 },        /* Display HELP text */
1025 #ifndef NOHTTP
1026 #ifdef TCPSOCKET
1027     { "http",        XXHTTP, 0 },       /* HTTP operations */
1028 #endif /* TCPSOCKET */
1029 #endif /* NOHTTP */
1030 #ifndef NOSPL
1031     { "i",           XXINP, CM_INV|CM_ABR }, /* Invisible synonym for INPUT */
1032     { "if",          XXIF,  0 },             /* IF ( condition ) command */
1033 #ifdef TCPSOCKET
1034     { "iksd",        XXIKSD, CM_INV },       /* Make connection to IKSD */
1035 #else
1036     { "iksd",        XXNOTAV, CM_INV },
1037 #endif /* TCPSOCKET */
1038     { "in",          XXINP, CM_INV|CM_ABR }, /* Invisible synonym for INPUT */
1039     { "increment",   XXINC, 0 },        /* Increment a numeric variable */
1040     { "input",       XXINP, 0 },        /* INPUT text from comm device */
1041 #endif /* NOSPL */
1042
1043 #ifndef NOHELP
1044     { "int",         XXINT, CM_INV|CM_ABR },
1045     { "intr",        XXINT, CM_INV|CM_ABR },
1046     { "INTRO",       XXINT, 0 },
1047     { "introduction",XXINT, CM_INV },   /* Print introductory text */
1048 #else
1049     { "intro",       XXNOTAV, CM_INV },
1050     { "introduction",XXNOTAV, CM_INV },
1051 #endif /* NOHELP */
1052
1053 #ifdef OS2
1054     { "k95",         XXKERMI, CM_INV }, /* Hmmm what's this... */
1055 #endif /* OS2 */
1056
1057 #ifndef NOSPL
1058     { "kcd",         XXKCD,   0      },
1059 #endif /* NOSPL */
1060
1061     { "kermit",      XXKERMI, CM_INV },
1062
1063 #ifdef OS2
1064 #ifndef NOKVERBS
1065     { "kverb",       XXKVRB, CM_INV|CM_HLP }, /* Keyboard verb */
1066 #endif /* NOKVERBS */
1067 #endif /* OS2 */
1068
1069 #ifndef NOFRILLS
1070     { "l",           XXLOG, CM_INV|CM_ABR }, /* Invisible synonym for log */
1071 #endif /* NOFRILLS */
1072
1073     { "lcd",         XXLCWD, CM_INV },
1074     { "lcdup",       XXLCDU, CM_INV },
1075     { "lcwd",        XXLCWD, CM_INV },
1076     { "ldelete",     XXLDEL, CM_INV },
1077     { "ldirectory",  XXLDIR, CM_INV },
1078
1079 #ifdef CKLEARN
1080     { "learn",       XXLEARN, 0 },      /* LEARN - automatic script writing */
1081 #else
1082     { "learn",       XXNOTAV, CM_INV },
1083 #endif /* CKLEARN */
1084
1085     { "li",          XXLNOUT, CM_INV|CM_ABR },
1086     { "LICENSE",     XXCPR, 0 },        /* LICENSE */
1087
1088 #ifndef NOSPL
1089     { "lineout",     XXLNOUT, 0 },      /* LINEOUT = OUTPUT + eol */
1090 #endif /* NOSPL */
1091
1092 #ifdef NT
1093     { "link",        XXLINK, 0 },       /* LINK source destination */
1094 #endif /* NT */
1095
1096     { "lmkdir",      XXLMKD, CM_INV },
1097     { "lmv",         XXLREN, CM_INV },
1098
1099 #ifndef NOFRILLS
1100     { "lo",          XXLOG,  CM_INV|CM_ABR }, /* Invisible synonym for log */
1101 #endif /* NOFRILLS */
1102
1103 #ifndef NOSPL
1104     { "local",       XXLOCAL, CM_INV }, /* LOCAL variable declaration */
1105 #else
1106     { "local",       XXNOTAV, CM_INV },
1107 #endif /* NOSPL */
1108
1109     { "locus",       XXLOCU, CM_INV|CM_HLP }, /* "help locus" */
1110
1111     { "log",         XXLOG, 0 },        /* Open a log file */
1112
1113     { "login",       XXLOGIN,  0 },     /* (REMOTE) LOGIN to server or IKSD */
1114     { "logout",      XXLOGOUT, 0 },     /* LOGOUT from server or IKSD */
1115
1116 #ifndef NOFRILLS
1117 #ifndef NODIAL
1118     { "lookup",      XXLOOK,  0 },      /* LOOKUP */
1119 #else
1120     { "lookup",      XXNOTAV, CM_INV },
1121 #endif /* NODIAL */
1122
1123     { "lpwd",        XXLPWD, CM_INV },
1124     { "lrename",     XXLREN, CM_INV },
1125     { "lrmdir",      XXLRMD, CM_INV },
1126
1127 #ifdef UNIXOROSK
1128     { "ls",          XXLS,  CM_INV|CM_PSH }, /* UNIX ls command */
1129 #else
1130     { "ls",          XXDIR, CM_INV },   /* Invisible synonym for DIR */
1131 #endif /* UNIXOROSK */
1132 #ifndef NOXFER
1133     { "mail",        XXMAI, 0 },        /* Send a file as e-mail */
1134 #endif /* NOXFER */
1135 #ifndef NOHELP
1136     { "manual",      XXMAN, CM_PSH },   /* MAN(UAL) */
1137 #else
1138     { "manual",      XXNOTAV, CM_INV|CM_PSH },
1139 #endif /* NOHELP */
1140 #endif /* NOFRILLS */
1141 #ifdef CK_MKDIR
1142     { "md",          XXMKDIR, CM_INV }, /* Synonym for MKDIR */
1143 #endif /* CK_MKDIR */
1144     { "message",     XXMSG, 0 },        /* Print debugging message */
1145 #ifdef CK_MINPUT
1146     { "minput",      XXMINP, 0 },       /* MINPUT */
1147 #else
1148     { "minput",      XXNOTAV, CM_INV },
1149 #endif /* CK_MINPUT */
1150 #ifndef NOMSEND
1151     { "mget",        XXMGET, 0 },       /* MGET */
1152 #else
1153     { "mget",        XXNOTAV, CM_INV },
1154 #endif /* NOMSEND */
1155 #ifdef CK_MKDIR
1156     { "mkdir",       XXMKDIR, 0 },      /* MKDIR */
1157 #else
1158     { "mkdir",       XXNOTAV, CM_INV },
1159 #endif /* CK_MKDIR */
1160
1161 #ifndef NOXFER
1162 #ifndef NOMSEND
1163     { "mmove",       XXMMOVE, 0 },      /* MMOVE */
1164 #else
1165     { "mmove",       XXNOTAV, CM_INV },
1166 #endif /* NOMSEND */
1167 #endif /* NOXFER */
1168
1169 #ifndef NOFRILLS
1170     { "more",        XXMORE, CM_INV },  /* MORE */
1171 #endif /* NOFRILLS */
1172
1173 #ifndef NOXFER
1174     { "move",        XXMOVE, 0 },       /* MOVE  */
1175 #endif /* NOXFER */
1176
1177 #ifndef NOSPL
1178     { "mpause",      XXMSL, CM_INV },   /* Millisecond sleep */
1179 #else
1180     { "mpause",      XXNOTAV, CM_INV },
1181 #endif /* NOSPL */
1182
1183 #ifndef NOXFER
1184 #ifndef NOMSEND
1185     { "mput",        XXMSE, CM_INV },   /* MPUT = MSEND */
1186     { "ms",          XXMSE, CM_INV|CM_ABR },
1187     { "msend",       XXMSE, 0 },        /* Multiple SEND */
1188 #else
1189     { "mput",        XXNOTAV, CM_INV },
1190     { "msend",       XXNOTAV, CM_INV },
1191 #endif /* NOMSEND */
1192 #endif /* NOXFER */
1193     { "msg",         XXMSG, CM_INV },   /* Print debugging message */
1194 #ifndef NOSPL
1195     { "msleep",      XXMSL, 0 },        /* Millisecond sleep */
1196 #else
1197     { "msleep",      XXNOTAV, CM_INV },
1198 #endif /* NOSPL */
1199 #ifndef NOFRILLS
1200     { "mv",          XXREN, CM_INV },   /* Synonym for rename */
1201 #endif /* NOFRILLS */
1202 #ifndef NOHELP
1203     { "news",        XXNEW, CM_INV },   /* Display NEWS of new features */
1204 #else
1205     { "news",        XXNOTAV, CM_INV },
1206 #endif /* NOHELP */
1207     { "nolocal",     XXNLCL, CM_INV },  /* Disable SET LINE / SET HOST */
1208     { "nopush",      XXNPSH, CM_INV },  /* Disable PUSH command/features */
1209 #ifdef OS2
1210     { "noscroll",    XXNSCR, CM_INV },  /* Disable scroll operations */
1211 #endif /* OS2 */
1212 #ifndef NOSPL
1213     { "o",           XXOUT, CM_INV|CM_ABR }, /* Invisible synonym for OUTPUT */
1214     { "open",        XXOPE, 0 },        /* OPEN file for reading or writing */
1215 #else
1216     { "open",        XXOPE, CM_INV },   /* OPEN */
1217 #endif /* NOSPL */
1218 #ifndef NOHELP
1219     { "options",     XXOPTS,CM_INV|CM_HLP }, /* Options */
1220 #endif /* NOHELP */
1221     { "orientation", XXORIE, 0 },
1222 #ifndef NOSPL
1223     { "output",      XXOUT, 0 },        /* OUTPUT text to comm device */
1224 #else
1225     { "output",      XXNOTAV, CM_INV },
1226 #endif /* NOSPL */
1227 #ifdef ANYX25
1228 #ifndef IBMX25
1229     { "pad",         XXPAD, CM_LOC },   /* X.3 PAD commands */
1230 #endif /* IBMX25 */
1231 #endif /* ANYX25 */
1232
1233 #ifdef NEWFTP
1234     { "passive",     XXPASV, CM_INV },  /* (FTP) PASSIVE */
1235 #endif /* NEWFTP */
1236
1237 #ifndef NOHELP
1238     { "patterns",    XXPAT,CM_INV|CM_HLP }, /* Pattern syntax */
1239 #endif /* NOHELP */
1240
1241 #ifndef NOSPL
1242     { "pause",       XXPAU, 0 },        /* Sleep for specified interval */
1243 #else
1244     { "pause",       XXNOTAV, CM_INV },
1245 #endif /* NOSPL */
1246 #ifndef NODIAL
1247     { "pdial",       XXPDIA,  CM_LOC }, /* PDIAL (partial dial) */
1248 #else
1249     { "pdial",       XXNOTAV, CM_INV|CM_LOC },
1250 #endif /* NODIAL */
1251 #ifdef TCPSOCKET
1252 #ifndef NOPUSH
1253     { "ping",        XXPNG, CM_INV|CM_PSH|CM_LOC }, /* PING */
1254 #else
1255     { "ping",        XXNOTAV, CM_INV|CM_PSH|CM_LOC },
1256 #endif /* NOPUSH */
1257 #endif /* TCPSOCKET */
1258 #ifdef NETCMD
1259 #ifndef NOPUSH
1260     { "pipe",        XXPIPE, CM_PSH },  /* PIPE */
1261 #else
1262     { "pipe",        XXNOTAV, CM_INV|CM_PSH }, /* PIPE */
1263 #endif /* NOPUSH */
1264 #endif /* NETCMD */
1265
1266 #ifndef NOSPL
1267     { "pop",         XXEND, CM_INV },   /* Invisible synonym for END */
1268 #endif /* NOSPL */
1269 #ifndef NOFRILLS
1270     { "print",       XXPRI, 0 },        /* PRINT a file locally */
1271 #endif /* NOFRILLS */
1272
1273     { "prompt",      XXPROMP, CM_INV }, /* Go interactive (from script) */
1274
1275 #ifndef NOXFER
1276 #ifdef CK_RESEND
1277     { "psend",       XXPSEN, CM_INV },  /* PSEND */
1278 #else
1279     { "psend",       XXNOTAV, CM_INV },
1280 #endif /* CK_RESEND */
1281 #endif /* NOXFER */
1282
1283 #ifdef NETPTY
1284     { "pty",         XXPTY, CM_PSH },   /* PTY */
1285 #else
1286     { "pty",         XXNOTAV, CM_INV|CM_PSH },
1287 #endif /* NETPTY */
1288
1289 #ifndef NOPUSH
1290     { "pu",          XXSHE, CM_INV|CM_ABR|CM_PSH }, /* PU = PUSH */
1291 #endif /* NOPUSH */
1292
1293 #ifdef CKPURGE
1294     { "purge",       XXPURGE, 0 },      /* PURGE (real) */
1295 #else
1296 #ifdef VMS
1297     { "purge",       XXPURGE, 0 },      /* PURGE (fake) */
1298 #else
1299     { "purge",       XXNOTAV, CM_INV },
1300 #endif /* VMS */
1301 #endif /* CKPURGE */
1302
1303 #ifndef NOPUSH
1304     { "push",        XXSHE, CM_PSH },   /* PUSH command (like RUN, !) */
1305 #else
1306     { "push",        XXNOTAV, CM_INV|CM_PSH },
1307 #endif /* NOPUSH */
1308
1309 #ifndef NOXFER
1310     { "put",         XXSEN, CM_INV },   /* PUT = SEND */
1311 #endif /* NOXFER */
1312
1313 #ifdef UNIX
1314 #ifndef NOPUTENV
1315     { "putenv",      XXPUTE, CM_INV },  /* PUTENV */
1316 #endif  /* NOPUTENV */
1317 #endif  /* UNIX */
1318
1319     { "pwd",         XXPWD, 0 },        /* Print Working Directory */
1320     { "q",           XXQUI, CM_INV|CM_ABR }, /* Invisible synonym for QUIT */
1321
1322 #ifndef NOXFER
1323     { "query",       XXRQUE,CM_INV },   /* (= REMOTE QUERY) */
1324 #endif /* NOXFER */
1325
1326     { "quit",        XXQUI, 0 },        /* QUIT from program = EXIT */
1327
1328 #ifndef NOXFER
1329     { "r",           XXREC, CM_INV|CM_ABR }, /* Inv synonym for RECEIVE */
1330 #endif /* NOXFER */
1331
1332 #ifndef NOXFER
1333     { "rasg",        XXRASG, CM_INV },  /* REMOTE ASSIGN */
1334     { "rassign",     XXRASG, CM_INV },  /* ditto */
1335     { "rcd",         XXRCWD, CM_INV },  /* REMOTE CD */
1336     { "rcdup",       XXRCDUP,CM_INV },  /* REMOTE CD */
1337     { "rcopy",       XXRCPY, CM_INV },  /* REMOTE COPY */
1338     { "rcwd",        XXRCWD, CM_INV },  /* REMOTE CWD */
1339     { "rdelete",     XXRDEL, CM_INV },  /* REMOTE DELETE */
1340     { "rdirectory",  XXRDIR, CM_INV },  /* REMODE DIRECTORY */
1341 #endif /* NOXFER */
1342
1343 #ifndef NOSPL
1344     { "read",        XXREA, 0 },        /* READ a line from a file */
1345 #else
1346     { "read",        XXNOTAV, CM_INV },
1347 #endif /* NOSPL */
1348
1349 #ifndef NOXFER
1350     { "receive",     XXREC, 0 },        /* RECEIVE files */
1351 #endif /* NOXFER */
1352
1353 #ifndef NODIAL
1354     { "red",         XXRED, CM_INV|CM_ABR|CM_LOC }, /* Inv syn for REDIAL */
1355     { "redi",        XXRED, CM_INV|CM_ABR|CM_LOC }, /* ditto */
1356     { "redial",      XXRED, CM_LOC },   /* REDIAL last DIAL number */
1357 #else
1358     { "red",         XXNOTAV, CM_INV|CM_LOC },
1359     { "redi",        XXNOTAV, CM_INV|CM_LOC },
1360     { "redial",      XXNOTAV, CM_INV|CM_LOC },
1361 #endif /* NODIAL */
1362
1363 #ifdef CK_REDIR
1364 #ifdef OS2
1365 #ifndef NOPUSH
1366     { "redirect",    XXFUN, CM_INV|CM_PSH }, /* REDIRECT */
1367 #else
1368     { "redirect",    XXNOTAV, CM_INV|CM_PSH },
1369 #endif /* NOPUSH */
1370 #else /* OS2 */
1371 #ifndef NOPUSH
1372     { "redirect",    XXFUN, CM_PSH },   /* REDIRECT */
1373 #else
1374     { "redirect",    XXNOTAV, CM_INV|CM_PSH },
1375 #endif /* NOPUSH */
1376 #endif /* OS2 */
1377 #endif /* CK_REDIR */
1378
1379 #ifdef CK_RECALL
1380     { "redo",        XXREDO,  CM_NOR }, /* REDO */
1381 #else
1382     { "redo",        XXNOTAV, CM_INV },
1383 #endif /* CK_RECALL */
1384
1385 #ifndef NOXFER
1386 #ifdef CK_RESEND
1387     { "reget",       XXREGET, 0 },      /* REGET */
1388 #else
1389     { "reget",       XXNOTAV, CM_INV },
1390 #endif /* CK_RESEND */
1391 #endif /* NOXFER */
1392
1393 #ifndef NOSPL
1394     { "reinput",     XXREI, CM_INV },   /* REINPUT (from INPUT buffer) */
1395 #else
1396     { "reinput",     XXNOTAV, CM_INV },
1397 #endif /* NOSPL */
1398
1399 #ifndef NOXFER
1400 #ifdef ADDCMD
1401     { "rem",         XXREM, CM_INV|CM_ABR },
1402     { "remo",        XXREM, CM_INV|CM_ABR },
1403 #endif /* ADDCMD */
1404     { "remote",      XXREM, 0 },        /* Send REMOTE command to server */
1405 #endif /* NOXFER */
1406
1407 #ifdef ADDCMD
1408     { "remove",      XXREMV,0 },        /* REMOVE (something from a list) */
1409 #else
1410     { "remove",      XXNOTAV, CM_INV },
1411 #endif /* ADDCMD */
1412
1413 #ifndef NOFRILLS
1414 #ifndef NORENAME
1415     { "rename",      XXREN, 0 },        /* RENAME a local file */
1416 #else
1417     { "rename",      XXNOTAV, CM_INV },
1418 #endif /* NORENAME */
1419     { "replay",      XXTYP, CM_INV },   /* REPLAY (for now, just type) */
1420 #endif /* NOFRILLS */
1421
1422 #ifndef NOXFER
1423 #ifdef CK_RESEND
1424     { "rep",         XXTYP, CM_INV|CM_ABR },  /* REPLAY abbreviation */
1425     { "reput",       XXRSEN, CM_INV },        /* REPUT = RESEND */
1426     { "res",         XXRSEN, CM_INV|CM_ABR }, /* RESEND */
1427     { "rese",        XXRSEN, CM_INV|CM_ABR }, /* RESEND */
1428     { "resend",      XXRSEN, 0 },       /* RESEND */
1429 #else
1430     { "reput",       XXNOTAV, CM_INV },
1431     { "res",         XXNOTAV, CM_INV },
1432     { "rese",        XXNOTAV, CM_INV },
1433     { "resend",      XXNOTAV, CM_INV },
1434 #endif /* CK_RESEND */
1435 #endif /* NOXFER */
1436
1437     { "reset",       XXRESET, CM_INV }, /* RESET */
1438
1439 #ifdef CK_RESEND
1440 #ifndef NOSPL
1441     { "ret",         XXRET, CM_INV|CM_ABR },
1442 #endif /* NOSPL */
1443 #endif /* CK_RESEND */
1444
1445 #ifndef NOXFER
1446     { "retrieve",    XXRETR, CM_INV },  /* RETRIEVE */
1447 #endif /* NOXFER */
1448
1449 #ifndef NOSPL
1450     { "return",      XXRET, 0 },        /* RETURN from a function */
1451 #else
1452     { "return",      XXNOTAV, CM_INV },
1453 #endif /* NOSPL */
1454
1455 #ifndef NOXFER
1456     { "rexit",       XXRXIT, CM_INV },  /* REMOTE EXIT */
1457 #endif /* NOXFER */
1458
1459 #ifdef CK_REXX
1460 #ifndef NOPUSH
1461     { "rexx",        XXREXX, CM_PSH },  /* Execute a Rexx command */
1462 #else
1463     { "rexx",        XXNOTAV, CM_INV|CM_PSH },
1464 #endif /* NOPUSH */
1465 #endif /* CK_REXX */
1466
1467 #ifndef NOXFER
1468     { "rhelp",       XXRHLP, CM_INV },  /* REMOTE HELP */
1469     { "rhost",       XXRHOS, CM_INV },  /* REMOTE HOST */
1470     { "rkermit",     XXRKER, CM_INV },  /* REMOTE KERMIT */
1471 #endif /* NOXFER */
1472
1473 #ifdef TCPSOCKET
1474     { "rlogin",      XXRLOG, CM_LOC },  /* Make an Rlogin connection */
1475 #else
1476     { "rlogin",      XXNOTAV, CM_INV|CM_LOC },
1477 #endif /* TCPSOCKET */
1478
1479 #ifndef NOFRILLS
1480     { "rm",          XXDEL, CM_INV },   /* Invisible synonym for delete */
1481 #endif /* NOFRILLS */
1482
1483 #ifdef CK_MKDIR
1484     { "rmdir",       XXRMDIR, 0 },      /* RMDIR */
1485 #else
1486     { "rmdir",       XXNOTAV, CM_INV },
1487 #endif /* CK_MKDIR */
1488
1489 #ifndef NOXFER
1490     { "rmessage",    XXRMSG, CM_INV },  /* REMOTE MESSAGE */
1491     { "rmkdir",      XXRMKD, CM_INV },  /* REMOTE MKDIR */
1492     { "rmsg",        XXRMSG, CM_INV },  /* REMOTE MESSAGE */
1493 #ifndef NOSPL
1494     { "robust",      XXROB,  CM_INV },
1495 #else
1496     { "robust",      XXNOTAV, CM_INV },
1497 #endif /* NOSPL */
1498     { "rprint",      XXRPRI, CM_INV },  /* REMOTE PRINT */
1499     { "rpwd",        XXRPWD, CM_INV },  /* REMOTE PWD */
1500     { "rquery",      XXRQUE, CM_INV },  /* REMOTE QUERY */
1501 #endif /* NOXFER */
1502
1503 #ifdef CK_RECALL
1504     { "rr",          XXREDO, CM_INV|CM_NOR },
1505 #endif /* CK_RECALL */
1506
1507 #ifndef NOXFER
1508     { "rrename",    XXRREN, CM_INV },   /* REMOTE RENAME */
1509     { "rrmdir",     XXRRMD, CM_INV },   /* REMOTE REMDIR */
1510     { "rset",       XXRSET, CM_INV },   /* REMOTE SET */
1511     { "rspace",     XXRSPA, CM_INV },   /* REMOTE SPACE */
1512     { "rtype",      XXRTYP, CM_INV },   /* REMOTE TYPE */
1513 #endif /* NOXFER */
1514
1515 #ifndef NOPUSH
1516     { "run",         XXSHE, CM_PSH },   /* RUN a program or command */
1517 #else
1518     { "run",         XXNOTAV, CM_INV|CM_PSH },
1519 #endif /* NOPUSH */
1520
1521 #ifndef NOXFER
1522     { "rwho",        XXRWHO, CM_INV },  /* REMOTE WHO */
1523     { "s",           XXSEN, CM_INV|CM_ABR }, /* Invisible synonym for send */
1524 #endif /* NOXFER */
1525
1526 #ifndef NOSETKEY
1527 #ifdef OS2
1528     { "save",      XXSAVE, 0 },         /* SAVE something */
1529 #else
1530     { "save",      XXSAVE, CM_INV },
1531 #endif /* OS2 */
1532 #else
1533     { "save",      XXNOTAV, CM_INV },
1534 #endif /* NOSETKEY */
1535
1536 #ifndef NOSCRIPT
1537     { "sc",        XXLOGI, CM_INV|CM_ABR|CM_LOC },
1538     { "scr",       XXLOGI, CM_INV|CM_ABR|CM_LOC },
1539 #endif /* NOSCRIPT */
1540     { "screen",      XXSCRN, 0 },       /* SCREEN actions */
1541 #ifndef NOSCRIPT
1542     { "script",    XXLOGI, CM_LOC },    /* Expect-Send-style script line */
1543 #else
1544     { "script",    XXNOTAV, CM_INV|CM_LOC },
1545 #endif /* NOSCRIPT */
1546
1547     { "search",    XXGREP,CM_INV },     /* Synonym for GREP and FIND */
1548
1549 #ifndef NOXFER
1550     { "send",      XXSEN, 0 },          /* Send (a) file(s) */
1551 #ifndef NOSERVER
1552     { "server",    XXSER, 0 },          /* Be a SERVER */
1553 #else
1554     { "server",    XXNOTAV, CM_INV },
1555 #endif /* NOSERVER */
1556 #endif /* NOXFER */
1557
1558     { "set",       XXSET, 0 },          /* SET parameters */
1559
1560 #ifndef NOSPL
1561 #ifndef NOSEXP
1562     { "sexpression", XXSEXP, CM_INV|CM_HLP }, /* SEXPR */
1563 #endif /* NOSEXP */
1564
1565 #ifdef SFTP_BUILTIN
1566     { "sftp",        XXSFTP, 0 },   /* SFTP */
1567 #endif /* SFTP_BUILTIN */
1568
1569 #ifndef NOSHOW
1570     { "sh",          XXSHO, CM_INV|CM_ABR }, /* SHOW parameters */
1571 #endif /* NOSHOW */
1572     { "shift",       XXSHIFT, 0 },      /* SHIFT args */
1573 #else
1574     { "shift",       XXNOTAV, CM_INV },
1575 #endif /* NOSPL */
1576
1577 #ifndef NOSHOW
1578     { "show",      XXSHO, 0 },          /* SHOW parameters */
1579 #else
1580     { "show",      XXNOTAV, CM_INV },
1581 #endif /* NOSHOW */
1582
1583 #ifdef NEWFTP
1584     { "site",        XXSITE, CM_INV },  /* (FTP) SITE */
1585 #endif /* NEWFTP */
1586
1587 #ifdef SSHBUILTIN
1588     { "skermit",   XXSKRM, 0 },     /* SKERMIT */
1589 #endif /* SSHBUILTIN */
1590
1591 #ifndef NOSPL
1592 #ifndef NOFRILLS
1593     { "sleep",       XXPAU, CM_INV },   /* SLEEP for specified interval */
1594 #endif /* NOFRILLS */
1595 #endif /* NOSPL */
1596
1597 #ifndef NOSPL
1598     { "sort",        XXSORT, CM_INV },  /* (see ARRAY) */
1599 #else
1600     { "sort",        XXNOTAV, CM_INV },
1601 #endif /* NOSPL */
1602
1603 #ifndef MAC
1604 #ifndef NOFRILLS
1605     { "sp",          XXSPA, CM_INV|CM_ABR },
1606     { "spa",         XXSPA, CM_INV|CM_ABR },
1607 #endif /* NOFRILLS */
1608     { "space",       XXSPA, 0 },        /* Show available disk SPACE */
1609 #endif /* MAC */
1610
1611 #ifndef NOFRILLS
1612 #ifndef NOPUSH
1613     { "spawn",       XXSHE, CM_INV|CM_PSH }, /* Synonym for PUSH, RUN */
1614 #else
1615     { "spawn",       XXNOTAV, CM_INV|CM_PSH }, /* Synonym for PUSH, RUN */
1616 #endif /* NOPUSH */
1617 #endif /* NOFRILLS */
1618
1619 #ifdef ANYSSH
1620     { "ssh",         XXSSH, 0 },
1621 #endif /* ANYSSH */
1622
1623 #ifndef NOXFER
1624     { "sta",         XXSTA, CM_INV|CM_ABR },
1625     { "stat",        XXSTA, CM_INV|CM_ABR },
1626     { "statistics",  XXSTA, 0 },        /* Display file transfer stats */
1627 #endif /* NOXFER */
1628
1629     { "status",      XXSTATUS,0 },      /* Show status of previous command */
1630
1631 #ifndef NOSPL
1632     { "stop",        XXSTO,   0 },      /* STOP all take files and macros */
1633     { "succeed",     XXSUCC,  CM_INV }, /* SUCCEED */
1634 #else
1635     { "stop",        XXNOTAV, CM_INV },
1636     { "succeed",     XXNOTAV, CM_INV },
1637 #endif /* NOSPL */
1638
1639 #ifndef NOFRILLS
1640     { "SUPPORT",     XXBUG, 0 },        /* Tech support instructions */
1641 #else
1642     { "support",     XXNOTAV, CM_INV },
1643 #endif /* NOFRILLS */
1644
1645 #ifndef NOJC
1646     { "suspend",     XXSUS, CM_PSH },   /* SUSPEND C-Kermit (UNIX only) */
1647 #else
1648     { "suspend",     XXNOTAV, CM_INV|CM_PSH },
1649 #endif /* NOJC */
1650
1651 #ifndef NOSPL
1652     { "switch",      XXSWIT, 0 },       /* SWITCH */
1653 #else
1654     { "switch",      XXNOTAV, CM_INV },
1655 #endif /* NOSPL */
1656
1657 #ifdef CK_TAPI
1658     { "ta",        XXTAK, CM_INV|CM_ABR }, /* (because of TAPI) */
1659 #endif /* CK_TAPI */
1660
1661 #ifndef NOFRILLS
1662     { "tail",        XXTAIL, 0 },       /* Display end of a local file */
1663 #endif /* NOFRILLS */
1664
1665     { "take",      XXTAK, 0 },          /* TAKE commands from a file */
1666
1667 #ifdef CK_TAPI
1668     { "tapi",      XXTAPI, CM_LOC },    /* Microsoft TAPI commands */
1669 #else
1670     { "tapi",      XXNOTAV, CM_INV|CM_LOC },
1671 #endif /* CK_TAPI */
1672
1673 #ifndef NOFRILLS
1674 #ifdef TCPSOCKET
1675     { "tel",         XXTEL, CM_INV|CM_ABR|CM_LOC },
1676     { "telnet",      XXTEL, CM_LOC },   /* TELNET (TCP/IP only) */
1677     { "telopt",      XXTELOP, CM_INV }, /* TELOPT (ditto) */
1678 #else
1679     { "tel",         XXNOTAV, CM_INV|CM_LOC },
1680     { "telnet",      XXNOTAV, CM_INV|CM_LOC },
1681     { "telopt",      XXNOTAV, CM_INV },
1682 #endif /* TCPSOCKET */
1683 #ifdef OS2
1684     { "terminal",    XXTERM, CM_INV|CM_LOC }, /* == SET TERMINAL TYPE */
1685 #else
1686     { "terminal",    XXTERM, CM_INV },
1687 #endif /* OS2 */
1688 #endif /* NOFRILLS */
1689 #ifndef NOXFER
1690     { "text",        XXASC, CM_INV },   /* == SET FILE TYPE TEXT */
1691 #endif /* NOXFER */
1692     { "touch",       XXTOUC, 0 },       /* TOUCH */
1693 #ifndef NOSPL
1694     { "trace",       XXTRACE, 0 },      /* TRACE */
1695 #else
1696     { "trace",       XXNOTAV, CM_INV },
1697 #endif /* NOSPL */
1698
1699 #ifndef NOCSETS
1700     { "translate",   XXXLA, 0 },        /* TRANSLATE local file char sets */
1701 #else
1702     { "translate",   XXNOTAV, CM_INV },
1703 #endif /* NOCSETS */
1704
1705 #ifndef NOXMIT
1706     { "transmit",    XXTRA, 0 },        /* Send (upload) a file, no protocol */
1707 #else
1708     { "transmit",    XXNOTAV, CM_INV },
1709 #endif /* NOXMIT */
1710
1711 #ifndef NOFRILLS
1712     { "type",        XXTYP, 0 },        /* Display a local file */
1713 #endif /* NOFRILLS */
1714
1715 #ifndef NOSPL
1716     { "undcl",       XXUNDCL, CM_INV },
1717     { "undeclare",   XXUNDCL, 0 },      /* UNDECLARE an array */
1718     { "undefine",    XXUNDEF, 0 },      /* UNDEFINE a variable or macro */
1719 #else
1720     { "undcl",       XXNOTAV, CM_INV },
1721     { "undeclare",   XXNOTAV, CM_INV },
1722     { "undefine",    XXNOTAV, CM_INV },
1723 #endif /* NOSPL */
1724
1725 #ifdef NEWFTP
1726     { "user",        XXUSER,  CM_INV }, /* (FTP) USER */
1727 #endif /* NEWFTP */
1728
1729     { "version",     XXVER, 0 },        /* VERSION-number display */
1730
1731 #ifdef OS2
1732     { "viewonly",    XXVIEW, CM_LOC },  /* VIEWONLY Terminal Mode */
1733 #endif /* OS2 */
1734
1735     { "void",        XXVOID, 0 },       /* VOID */
1736
1737 #ifndef NOSPL
1738     { "wait",        XXWAI, 0 },        /* WAIT */
1739 #else
1740     { "wait",        XXNOTAV, CM_INV },
1741 #endif /* NOSPL */
1742
1743     { "wdirectory",  XXWDIR,  CM_INV }, /* Like TOPS-20, reverse chron order */
1744     { "wermit",      XXKERMI, CM_INV },
1745
1746 #ifndef NOXFER
1747     { "where",       XXWHERE, 0 },      /* WHERE (did my file go?) */
1748 #endif /* NOXFER */
1749
1750 #ifndef NOSPL
1751     { "while",       XXWHI, 0 },        /* WHILE loop */
1752 #else
1753     { "while",       XXNOTAV, CM_INV },
1754 #endif /* NOSPL */
1755
1756 #ifndef OS2
1757 #ifndef MAC
1758 #ifndef NOFRILLS
1759     { "who",         XXWHO, CM_PSH },   /* WHO's logged in? */
1760 #endif /* NOFRILLS */
1761 #endif /* MAC */
1762 #endif /* OS2 */
1763
1764 #ifndef NOHELP
1765     { "wildcards",   XXWILD,CM_INV|CM_HLP }, /* Wildcard syntax */
1766 #endif /* NOHELP */
1767
1768 #ifndef NOSPL
1769     { "wr",          XXWRI, CM_INV|CM_ABR },
1770     { "wri",         XXWRI, CM_INV|CM_ABR },
1771     { "writ",        XXWRI, CM_INV|CM_ABR },
1772     { "write",       XXWRI, 0 },        /* WRITE characters to a file */
1773     { "write-line",  XXWRL, CM_INV },   /* WRITE a line to a file */
1774     { "writeln",     XXWRL, CM_INV },   /* Pascalisch synonym for write-line */
1775 #else
1776     { "wr",          XXNOTAV, CM_INV },
1777     { "wri",         XXNOTAV, CM_INV },
1778     { "writ",        XXNOTAV, CM_INV },
1779     { "write",       XXNOTAV, CM_INV },
1780     { "write-line",  XXNOTAV, CM_INV },
1781     { "writeln",     XXNOTAV, CM_INV },
1782 #endif /* NOSPL */
1783
1784 #ifndef NOFRILLS
1785     { "xecho",       XXXECH,0 },        /* XECHO */
1786 #endif /* NOFRILLS */
1787
1788 #ifndef NOSPL
1789     { "xif",         XXIFX, CM_INV },   /* Extended IF command (obsolete) */
1790 #else
1791     { "xif",         XXNOTAV, CM_INV },
1792 #endif /* NOSPL */
1793
1794 #ifndef NOCSETS
1795     { "xlate",       XXXLA, CM_INV },   /* Synonym for TRANSLATE */
1796 #else
1797     { "xlate",       XXNOTAV, CM_INV },
1798 #endif /* NOCSETS */
1799
1800 #ifndef NOXMIT
1801     { "xm",          XXTRA, CM_INV|CM_ABR }, /* Avoid conflict with XMESSAGE */
1802 #else
1803     { "xm",          XXNOTAV, CM_INV|CM_ABR }, /* Synonym for TRANSMIT */
1804 #endif /* NOXMIT */
1805
1806     { "xmessage",    XXXMSG, 0 },       /* Print debugging message */
1807
1808 #ifndef NOXMIT
1809     { "xmit",        XXTRA, CM_INV },   /* Synonym for TRANSMIT */
1810 #else
1811     { "xmit",        XXNOTAV, CM_INV },
1812 #endif /* NOXMIT */
1813
1814 #ifndef OS2
1815 #ifndef NOJC
1816     { "z",           XXSUS, CM_INV|CM_PSH }, /* Synonym for SUSPEND */
1817 #else
1818     { "z",           XXNOTAV, CM_INV|CM_PSH },
1819 #endif /* NOJC */
1820 #endif /* OS2 */
1821
1822 #ifndef NOSPL
1823     { "{",           XXMACRO, CM_INV }, /* Immediate macro */
1824 #endif /* NOSPL */
1825     { "", 0, 0 }
1826 };
1827 int ncmd = (sizeof(cmdtab) / sizeof(struct keytab)) - 1;
1828
1829 /* NOTE: Tokens must also be entered above into cmdtab[]. */
1830
1831 char toktab[] = {
1832 #ifndef NOPUSH
1833     '!',                                /* Shell escape */
1834 #endif /* NOPUSH */
1835     '#',                                /* Comment */
1836 #ifndef NOSPL
1837     '(',                                /* S-Expression */
1838     '.',                                /* Assignment */
1839 #endif /* NOSPL */
1840     ';',                                /* Comment */
1841 #ifndef NOSPL
1842     ':',                                /* Label */
1843 #endif /* NOSPL */
1844 #ifndef NOPUSH
1845 #ifdef CK_REDIR
1846     '<',                                /* REDIRECT */
1847 #endif /* CK_REDIR */
1848     '@',                                /* DCL escape */
1849 #endif /* NOPUSH */
1850 #ifdef CK_RECALL
1851     '^',                                /* Command recall */
1852 #endif /* CK_RECALL */
1853 #ifndef NOSPL
1854     '{',                                /* Immediate macro */
1855 #endif /* NOSPL */
1856     '\0'                                /* End of this string */
1857 };
1858 int xxdot = 0;                          /* Used with "." token */
1859
1860 struct keytab yesno[] = {               /* Yes/No keyword table */
1861     { "no",    0, 0 },
1862     { "ok",    1, 0 },
1863     { "yes",   1, 0 }
1864 };
1865 int nyesno = (sizeof(yesno) / sizeof(struct keytab));
1866
1867 /* Save keyword table */
1868
1869 struct keytab savtab[] = {
1870 #ifdef OS2
1871     { "command",  XSCMD, 0 },
1872 #else
1873 #ifdef CK_RECALL
1874     { "command",  XSCMD, 0 },
1875 #endif /* CK_RECALL */
1876 #endif /* OS2 */
1877 #ifndef NOSETKEY
1878     { "keymap",   XSKEY, 0 },
1879 #endif /* NOSETKEY */
1880 #ifdef OS2
1881     { "terminal", XSTERM, 0 },
1882 #endif /* OS2 */
1883     { "", 0, 0 }
1884 };
1885 int nsav = (sizeof(savtab) / sizeof(struct keytab)) - 1;
1886
1887 /* Parameter keyword table */
1888
1889 struct keytab prmtab[] = {
1890     { "alarm",            XYALRM,  0 },
1891 #ifdef COMMENT                          /* SET ANSWER not implemented yet */
1892 #ifndef NODIAL
1893     { "answer",           XYANSWER,0 },
1894 #endif /* NODIAL */
1895 #endif /* COMMENT */
1896     { "ask-timer",        XYTIMER, 0 },
1897 #ifndef NOXFER
1898     { "attributes",       XYATTR,  0 },
1899 #endif /* NOXFER */
1900 #ifdef CK_AUTHENTICATION
1901     { "authentication",   XYAUTH,  0 },
1902 #else  /* CK_AUTHENTICATION */
1903 #ifdef CK_SSL
1904     { "authentication",   XYAUTH,  0 },
1905 #endif /* CK_SSL */
1906 #endif /* CK_AUTHENTICATION */
1907     { "b",                XYBACK,  CM_INV|CM_ABR|CM_PSH },
1908     { "ba",               XYBACK,  CM_INV|CM_ABR|CM_PSH },
1909 #ifdef VMS
1910     { "background",       XYBACK,  CM_INV|CM_PSH },
1911     { "batch",            XYBACK,  CM_PSH },
1912 #else
1913     { "background",       XYBACK,  CM_PSH },
1914     { "batch",            XYBACK,  CM_INV|CM_PSH },
1915 #endif /* VMS */
1916 #ifndef NOLOCAL
1917     { "baud",             XYSPEE,  CM_INV|CM_LOC },
1918 #endif /* NOLOCAL */
1919     { "bell",             XYBELL,  0 },
1920 #ifndef NOXFER
1921     { "block-check",      XYCHKT,  0 },
1922 #endif /* NOXFER */
1923 #ifdef OS2
1924 #ifdef BPRINT
1925     { "bprinter",         XYBDCP,  CM_INV },
1926 #endif /* BPRINT */
1927 #endif /*  OS2 */
1928 #ifdef BROWSER
1929     { "browser",          XYBROWSE,CM_PSH|CM_LOC },
1930 #endif /* BROWSER */
1931 #ifndef NOXFER
1932 #ifdef DYNAMIC
1933     { "buffers",          XYBUF,   0 },
1934 #endif /* DYNAMIC */
1935 #endif /* NOXFER */
1936 #ifndef NOLOCAL
1937 #ifndef MAC
1938     { "carrier-watch",    XYCARR,  CM_LOC },
1939 #endif /* MAC */
1940 #endif /* NOLOCAL */
1941 #ifndef NOSPL
1942     { "case",             XYCASE,  0 },
1943 #endif /* NOSPL */
1944     { "cd",               XYCD,    0 },
1945 #ifndef NOXFER
1946     { "cl",               XYCLEAR, CM_INV|CM_ABR },
1947     { "cle",              XYCLEAR, CM_INV|CM_ABR },
1948     { "clea",             XYCLEAR, CM_INV|CM_ABR },
1949     { "clear",            XYCLEAR, CM_INV|CM_ABR },
1950     { "clear-channel",    XYCLEAR, 0 },
1951     { "clearchannel",     XYCLEAR, CM_INV },
1952 #endif /* NOXFER */
1953 #ifndef NOLOCAL
1954     { "close-on-disconnect", XYDISC, CM_INV|CM_LOC },
1955 #endif /* NOLOCAL */
1956     { "cmd",              XYCMD,   CM_INV },
1957     { "command",          XYCMD,   0 },
1958 #ifdef CK_SPEED
1959     { "con",              XYQCTL,  CM_INV|CM_ABR },
1960 #endif /* CK_SPEED */
1961     { "console",          XYCMD,   CM_INV },
1962 #ifdef CK_SPEED
1963     { "control-character",XYQCTL,  0 },
1964 #endif /* CK_SPEED */
1965 #ifndef NOSPL
1966     { "count",            XYCOUN,  0 },
1967 #endif /* NOSPL */
1968 #ifndef NOXFER
1969     { "d",                XYDELA,  CM_INV|CM_ABR },
1970     { "de",               XYDELA,  CM_INV|CM_ABR },
1971 #endif /* NOXFER */
1972     { "debug",            XYDEBU,  0 },
1973 #ifdef VMS
1974     { "default",          XYDFLT,  0 },
1975 #else
1976 #ifndef MAC
1977     { "default",          XYDFLT,  CM_INV },
1978 #endif /* MAC */
1979 #endif /* VMS */
1980 #ifndef NOXFER
1981     { "delay",            XYDELA,  0 },
1982     { "destination",      XYDEST,  0 },
1983 #endif /* NOXFER */
1984 #ifndef NODIAL
1985     { "di",               XYDIAL,  CM_INV|CM_ABR|CM_LOC },
1986     { "dia",              XYDIAL,  CM_INV|CM_ABR|CM_LOC },
1987     { "dial",             XYDIAL,  CM_LOC },
1988 #endif /* NODIAL */
1989 #ifdef OS2
1990     { "dialer",           XYDLR,   CM_INV },
1991 #endif /* OS2 */
1992 #ifndef NOLOCAL
1993     { "disconnect",       XYDISC,  CM_LOC },
1994     { "duplex",           XYDUPL,  CM_LOC },
1995 #endif /* NOLOCAL */
1996 #ifndef NOPUSH
1997 #ifndef NOFRILLS
1998     { "editor",           XYEDIT,  CM_PSH },
1999 #endif /*  NOFRILLS */
2000 #endif /* NOPUSH */
2001 #ifdef CK_CTRLZ
2002     { "eof",              XYEOF,   CM_INV },
2003 #endif /* CK_CTRLZ */
2004 #ifndef NOLOCAL
2005     { "escape-character", XYESC,   CM_LOC },
2006 #endif /* NOLOCAL */
2007 #ifndef NOSPL
2008     { "evaluate",         XYEVAL,  CM_INV },
2009 #endif /* NOSPL */
2010     { "exit",             XYEXIT,  0 },
2011 #ifndef NOXFER
2012 #ifdef CK_XYZ
2013 #ifndef NOPUSH
2014 #ifndef XYZ_INTERNAL
2015     { "external-protocol",XYEXTRN, 0 },
2016 #endif  /* XYZ_INTERNAL */
2017 #endif  /* NOPUSH */
2018 #endif  /* CK_XYZ */
2019     { "f-ack-bug",        XYFACKB, CM_INV },
2020     { "f-ack-path",       XYFACKP, CM_INV },
2021 #endif /* NOXFER */
2022     { "file",             XYFILE,  0 },
2023     { "fl",               XYFLOW,  CM_INV|CM_ABR },
2024 #ifndef NOSPL
2025     { "flag",             XYFLAG,  0 },
2026 #endif /* NOSPL */
2027 #ifdef TCPSOCKET
2028 #ifndef SYSFTP
2029 #ifndef NOFTP
2030     { "ft",               XYFTPX,  CM_INV|CM_ABR },
2031     { "ftp",              XYFTPX,  0 },
2032 #endif /* NOFTP */
2033 #endif /* SYSFTP */
2034 #endif /* TCPSOCKET */
2035 #ifdef BROWSER
2036     { "ftp-client",       XYFTP,   CM_PSH },
2037 #endif /* BROWSER */
2038     { "flow-control",     XYFLOW,  0 },
2039 #ifndef NOSPL
2040     { "function",         XYFUNC,  0 },
2041 #endif /* NOSPL */
2042 #ifdef NEWFTP
2043     { "get-put-remote",   XYGPR,   0 },
2044 #endif /* NEWFTP */
2045 #ifdef KUI
2046     { "gui",              XYGUI,   0 },
2047 #endif /* KUI */
2048     { "handshake",        XYHAND,  0 },
2049     { "hints",            XYHINTS, 0 },
2050 #ifdef NETCONN
2051     { "host",             XYHOST,  CM_LOC },
2052 #endif /* NETCONN */
2053 #ifndef NOSPL
2054     { "i",                XYINPU,  CM_INV|CM_ABR },
2055 #endif /* NOSPL */
2056 #ifdef IKSD
2057     { "iks",              XYIKS,   0 },
2058 #else
2059     { "iks",              XYIKS,   CM_INV },
2060 #endif /* IKSD */
2061 #ifndef NOSPL
2062     { "in",               XYINPU,  CM_INV|CM_ABR },
2063 #endif /* NOSPL */
2064 #ifndef NOXFER
2065     { "incomplete",       XYIFD,   CM_INV },
2066 #endif /* NOXFER */
2067 #ifndef NOSPL
2068     { "input",            XYINPU,  0 },
2069 #endif /* NOSPL */
2070 #ifndef NOSETKEY
2071     { "key",              XYKEY,   0 },
2072 #endif /* NOSETKEY */
2073     { "l",                XYLINE,  CM_INV|CM_ABR },
2074 #ifndef NOCSETS
2075     { "language",         XYLANG,  0 },
2076 #endif /* NOCSETS */
2077 #ifndef NOLOCAL
2078     { "line",             XYLINE,  CM_LOC },
2079     { "local-echo",       XYLCLE,  CM_INV|CM_LOC },
2080 #endif /* NOLOCAL */
2081 #ifdef LOCUS
2082     { "locus",            XYLOCUS, 0 },
2083 #endif /* LOCUS */
2084 #ifndef NOSPL
2085     { "login",            XYLOGIN, CM_LOC },
2086 #endif /* NOSPL */
2087 #ifndef NOSPL
2088     { "macro",            XYMACR,  0 },
2089 #endif /* NOSPL */
2090     { "match",            XYMATCH, 0 },
2091 #ifdef COMMENT
2092 #ifdef VMS
2093     { "messages",         XYMSGS,  0 },
2094 #endif /* VMS */
2095 #endif /* COMMENT */
2096 #ifndef NODIAL
2097     { "modem",            XYMODM,  CM_LOC },
2098 #endif /* NODIAL */
2099 #ifndef NOLOCAL
2100 #ifdef OS2MOUSE
2101     { "mouse",            XYMOUSE, 0 },
2102 #endif /* OS2MOUSE */
2103 #endif /* NOLOCAL */
2104 #ifdef OS2
2105     { "mskermit",         XYMSK,   0 },
2106 #endif /* OS2 */
2107 #ifdef NETCONN
2108     { "network",          XYNET,   CM_LOC },
2109 #endif /* NETCONN */
2110 #ifndef NOSPL
2111     { "output",           XYOUTP,  0 },
2112 #endif /* NOSPL */
2113     { "options",          XYOPTS,  0 },
2114     { "pause",            XYSLEEP, CM_INV },
2115 #ifdef ANYX25
2116 #ifndef IBMX25
2117     { "pad",              XYPAD,   CM_LOC },
2118 #endif /* IBMX25 */
2119 #endif /* ANYX25 */
2120     { "parity",           XYPARI,  0 },
2121 #ifndef NOLOCAL
2122 #ifdef OS2
2123     { "port",             XYLINE,  CM_LOC },
2124 #else
2125     { "port",             XYLINE,  CM_INV|CM_LOC },
2126 #endif /* OS2 */
2127 #endif /* NOLOCAL */
2128 #ifndef NOFRILLS
2129     { "pr",               XYPROM,  CM_INV|CM_ABR },
2130     { "printer",          XYPRTR,  0 },
2131 #endif /* NOFRILLS */
2132 #ifdef OS2
2133     { "priority",         XYPRTY,  0 },
2134 #endif /* OS2 */
2135 #ifdef CK_SPEED
2136     { "prefixing",        XYPREFIX, 0 },
2137 #endif /* CK_SPEED */
2138 #ifndef NOFRILLS
2139     { "prompt",           XYPROM,  0 },
2140 #endif /* NOFRILLS */
2141 #ifndef NOXFER
2142     { "protocol",         XYPROTO, 0 },
2143 #endif /* NOXFER */
2144     { "q",                XYQUIE,  CM_INV|CM_ABR },
2145 #ifndef NOXFER
2146     { "q8flag",           XYQ8FLG, CM_INV },
2147 #endif /* NOXFER */
2148 #ifdef QNX
2149     { "qnx-port-lock",    XYQNXPL, 0 },
2150 #else
2151     { "qnx-port-lock",    XYQNXPL, CM_INV },
2152 #endif /* QNX */
2153     { "quiet",            XYQUIE,  0 },
2154 #ifndef NOXFER
2155     { "rec",              XYRECV,  CM_INV|CM_ABR },
2156     { "receive",          XYRECV,  0 },
2157     { "recv",             XYRECV,  CM_INV },
2158 #endif /* NOXFER */
2159     { "reliable",         XYRELY,  0 },
2160     { "rename",           XY_REN,  0 },
2161 #ifndef NOXFER
2162     { "repeat",           XYREPT,  0 },
2163     { "retry-limit",      XYRETR,  0 },
2164 #endif /* NOXFER */
2165 #ifdef CKROOT
2166     { "root",             XYROOT,  0 },
2167 #endif /* CKROOT */
2168 #ifndef NOSCRIPT
2169     { "script",           XYSCRI,  CM_LOC },
2170 #endif /* NOSCRIPT */
2171 #ifndef NOXFER
2172     { "send",             XYSEND,  0 },
2173 #ifndef NOLOCAL
2174 #ifndef NOSERVER
2175     { "ser",              XYSERV,  CM_INV|CM_ABR },
2176 #endif /* NOSERVER */
2177 #endif /* NOXFER */
2178     { "serial",           XYSERIAL,CM_LOC },
2179 #endif /* NOLOCAL */
2180 #ifndef NOSERVER
2181     { "server",           XYSERV,  0 },
2182 #endif /* NOSERVER */
2183 #ifdef SESLIMIT
2184 #ifndef NOLOCAL
2185     { "session-l",        XYSESS,  CM_INV|CM_ABR },
2186 #endif /* NOLOCAL */
2187     { "session-limit",    XYLIMIT, CM_INV|CM_LOC }, /* Session Limit */
2188 #endif /* SESLIMIT */
2189
2190 #ifndef NOLOCAL
2191     { "session-log",      XYSESS,  CM_LOC },
2192 #endif /* NOLOCAL */
2193
2194 #ifndef NOSPL
2195 #ifndef NOSEXP
2196     { "sexpression",      XYSEXP,  CM_INV },
2197 #endif /* NOSEXP */
2198 #endif /* NOSPL */
2199
2200     { "sleep",            XYSLEEP, 0 },
2201
2202 #ifndef NOLOCAL
2203     { "speed",            XYSPEE,  CM_LOC },
2204 #endif /* NOLOCAL */
2205
2206 #ifdef ANYSSH
2207     { "ssh",              XYSSH,   0 },
2208 #endif /* ANYSSH */
2209
2210 #ifndef NOSPL
2211     { "startup-file",     XYSTARTUP, CM_INV },
2212 #endif /* NOSPL */
2213
2214 #ifndef NOLOCAL
2215 #ifdef HWPARITY
2216     { "stop-bits",        XYSTOP, CM_LOC },
2217 #else
2218 #ifdef TN_COMPORT
2219     { "stop-bits",        XYSTOP, CM_LOC },
2220 #endif /* TN_COMPORT */
2221 #endif /* HWPARITY */
2222 #endif /* NOLOCAL */
2223
2224 #ifndef NOXFER
2225 #ifdef STREAMING
2226     { "streaming",        XYSTREAM, 0 },
2227 #endif /* STREAMING */
2228 #endif /* NOXFER */
2229
2230 #ifndef NOJC
2231     { "suspend",          XYSUSP,  CM_PSH },
2232 #endif /* NOJC */
2233 #ifdef CKSYSLOG
2234     { "syslog",           XYSYSL,  CM_INV },
2235 #endif /* CKSYSLOG */
2236     { "take",             XYTAKE,  0 },
2237
2238 #ifdef CK_TAPI
2239     { "tapi",             XYTAPI,  CM_LOC },
2240 #endif /* CK_TAPI */
2241
2242 #ifndef NOTCPOPTS
2243 #ifdef TCPSOCKET
2244     { "tcp",              XYTCP,   CM_LOC },
2245 #endif /* TCPSOCKET */
2246 #endif /* NOTCPOPTS */
2247
2248 #ifdef TNCODE
2249     { "tel",              XYTEL,   CM_INV|CM_ABR },
2250     { "telnet",           XYTEL,   0 },
2251     { "telopt",           XYTELOP, 0 },
2252 #endif /* TNCODE */
2253
2254 #ifndef NOSPL
2255     { "temp-directory",   XYTMPDIR,0 },
2256 #endif /* NOSPL */
2257
2258 #ifndef NOLOCAL
2259     { "terminal",         XYTERM,  CM_LOC },
2260 #endif /* NOLOCAL */
2261
2262 #ifdef OS2
2263     { "title",            XYTITLE, CM_LOC },
2264 #endif /* OS2 */
2265 #ifdef TLOG
2266     { "transaction-log",  XYTLOG,  0 },
2267 #endif /* TLOG */
2268 #ifndef NOXFER
2269     { "transfer",         XYXFER,  0 },
2270 #endif /* NOXFER */
2271 #ifndef NOXMIT
2272     { "transmit",         XYXMIT,  0 },
2273 #endif /* NOXMIT */
2274 #ifndef NOXFER
2275 #ifndef NOCSETS
2276     { "unknown-char-set", XYUNCS,  0 },
2277 #endif /* NOCSETS */
2278 #ifndef NOSPL
2279     { "variable-evaluation", XYVAREV, CM_INV },
2280 #endif  /* NOSPL */
2281 #endif /* NOXFER */
2282     { "wait",             XYSLEEP, CM_INV },
2283 #ifndef NOPUSH
2284 #ifdef UNIX
2285     { "wildcard-expansion", XYWILD, 0 },
2286 #endif /* UNIX */
2287 #endif /* NOPUSH */
2288 #ifdef NT
2289     { "w",                XYWIND,  CM_INV|CM_ABR },
2290     { "wi",               XYWIND,  CM_INV|CM_ABR },
2291     { "win",              XYWIND,  CM_INV|CM_ABR },
2292 #endif /* NT */
2293     { "window-size",      XYWIND,  0 },
2294 #ifdef NT
2295     { "win95",            XYWIN95, 0 },
2296 #endif /* NT */
2297 #ifdef ANYX25
2298     { "x.25",             XYX25,   CM_LOC },
2299     { "x25",              XYX25,   CM_INV|CM_LOC },
2300 #endif /* ANYX25 */
2301     { "xfer",             XYXFER,  CM_INV },
2302 #ifndef NOXMIT
2303     { "xmit",             XYXMIT,  CM_INV },
2304 #endif /* NOXMIT */
2305     { "", 0, 0 }
2306 };
2307 int nprm = (sizeof(prmtab) / sizeof(struct keytab)) - 1; /* How many */
2308
2309 struct keytab scntab[] = {              /* Screen commands */
2310     { "clear",   SCN_CLR, 0 },
2311     { "cleol",   SCN_CLE, 0 },
2312     { "move-to", SCN_MOV, 0 }
2313 };
2314 int nscntab = (sizeof(scntab) / sizeof(struct keytab)); /* How many */
2315
2316 #ifdef ANYSSH                           /* SSH command table */
2317 #ifdef SSHBUILTIN
2318 int    ssh_pf_lcl_n = 0,
2319        ssh_pf_rmt_n = 0;
2320 struct ssh_pf ssh_pf_lcl[32] = { 0, NULL, 0 }; /* SSH Port Forwarding */
2321 struct ssh_pf ssh_pf_rmt[32] = { 0, NULL, 0 }; /* structs... */
2322 extern char * ssh_hst, * ssh_cmd, * ssh_prt;
2323 extern int    ssh_ver,   ssh_xfw;
2324 char * ssh_tmpuid = NULL, *ssh_tmpcmd = NULL, *ssh_tmpport = NULL,
2325      * ssh_tmpstr = NULL;
2326
2327 int
2328  sshk_type = SSHKT_2D,                  /* SSH KEY CREATE /TYPE:x */
2329  sshk_bits = 1024,                      /* SSH KEY CREATE /BITS:n */
2330  sshk_din  = SKDF_OSSH,                 /* SSH KEY DISPLAY /IN-FORMAT: */
2331  sshk_dout = SKDF_OSSH;                 /* SSH KEY DISPLAY /OUT-FORMAT: */
2332
2333 char
2334  * sshk1_comment = NULL,                /* SSH V1 COMMENT */
2335  * sshkp_old = NULL,                    /* Old key passphrase */
2336  * sshkp_new = NULL,                    /* New key passphrase */
2337  * sshkc_pass = NULL,                   /* KEY CREATE /PASS:xxx */
2338  * sshkc_comm = NULL,                   /* KEY CREATE /V1-RSA-COMMENT:xxx */
2339  * sshd_file = NULL,                    /* DISPLAY file */
2340  * sshk_file = NULL;                    /* SSH CREATE KEY file */
2341
2342 static struct keytab sshclr[] = {
2343     { "local-port-forward",  SSHC_LPF, 0 },
2344     { "remote-port-forward", SSHC_RPF, 0 },
2345     { "", 0, 0 }
2346 };
2347 static int nsshclr = (sizeof(sshclr) / sizeof(struct keytab)) - 1;
2348
2349 struct keytab sshopnsw[] = {
2350     { "/command",        SSHSW_CMD, CM_ARG },
2351     { "/password",       SSHSW_PWD, CM_ARG },
2352     { "/subsystem",      SSHSW_SUB, CM_ARG },
2353     { "/user",           SSHSW_USR, CM_ARG },
2354     { "/version",        SSHSW_VER, CM_ARG },
2355     { "/x11-forwarding", SSHSW_X11, CM_ARG },
2356     { "", 0, 0 }
2357 };
2358 int nsshopnsw = (sizeof(sshopnsw) / sizeof(struct keytab)) - 1;
2359
2360 static struct keytab sshkwtab[] = {
2361     { "add",                 XSSH_ADD, 0 },
2362     { "agent",               XSSH_AGT, 0 },
2363     { "clear",               XSSH_CLR, 0 },
2364     { "forward-local-port",  XSSH_FLP, CM_INV },
2365     { "forward-remote-port", XSSH_FRP, CM_INV },
2366     { "key",                 XSSH_KEY, 0 },
2367     { "open",                XSSH_OPN, 0 },
2368     { "v2",                  XSSH_V2,  0 },
2369     { "", 0, 0 }
2370 };
2371 static int nsshcmd = (sizeof(sshkwtab) / sizeof(struct keytab)) - 1;
2372
2373 static struct keytab ssh2tab[] = {
2374     { "rekey", XSSH2_RKE, 0 },
2375     { "", 0, 0 }
2376 };
2377 static int nssh2tab = (sizeof(ssh2tab) / sizeof(struct keytab));
2378
2379 static struct keytab addfwd[] = {       /* SET SSH ADD command table */
2380     { "local-port-forward",  SSHF_LCL, 0 },
2381     { "remote-port-forward", SSHF_RMT, 0 },
2382     { "", 0, 0 }
2383 };
2384 static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
2385
2386 static struct keytab sshagent[] = {     /* SET SSH AGENT command table */
2387     { "add",    SSHA_ADD, 0 },
2388     { "delete", SSHA_DEL, 0 },
2389     { "list",   SSHA_LST, 0 },
2390     { "", 0, 0 }
2391 };
2392 static int nsshagent = (sizeof(sshagent) / sizeof(struct keytab)) - 1;
2393
2394 static struct keytab sshagtsw[] = {     /* SET SSH AGENT LIST switch table */
2395     { "/fingerprint", SSHASW_FP, 0 },
2396     { "", 0, 0 }
2397 };
2398 static int nsshagtsw = (sizeof(sshagtsw) / sizeof(struct keytab)) - 1;
2399
2400 static struct keytab sshkey[] = {       /* SET SSH KEY command table */
2401     { "change-passphrase",  SSHK_PASS, 0 },
2402     { "create",             SSHK_CREA, 0 },
2403     { "display",            SSHK_DISP, 0 },
2404     { "v1",                 SSHK_V1,   0 },
2405     { "", 0, 0 }
2406 };
2407 static int nsshkey = (sizeof(sshkey) / sizeof(struct keytab)) - 1;
2408
2409 static struct keytab sshkv1[] = {       /* SET SSH KEY V1 command table */
2410     { "set-comment",  1, 0 }
2411 };
2412
2413 static struct keytab sshkpsw[] = {      /* SET SSH KEY PASSPHRASE table */
2414     { "/new-passphrase",  2, CM_ARG },
2415     { "/old-passphrase",  1, CM_ARG }
2416 };
2417
2418 static struct keytab sshkcrea[] = {     /* SSH KEY CREATE table */
2419     { "/bits",           SSHKC_BI, CM_ARG },
2420     { "/passphrase",     SSHKC_PP, CM_ARG },
2421     { "/type",           SSHKC_TY, CM_ARG },
2422     { "/v1-rsa-comment", SSHKC_1R, CM_ARG }
2423 };
2424 static int nsshkcrea = (sizeof(sshkcrea) / sizeof(struct keytab));
2425
2426 static struct keytab sshkcty[] = {      /* SSH KEY CREATE /TYPE:xxx */
2427     { "srp",    SSHKT_SRP, 0 },
2428     { "v1-rsa", SSHKT_1R, 0 },
2429     { "v2-dsa", SSHKT_2D, 0 },
2430     { "v2-rsa", SSHKT_2R, 0 }
2431 };
2432 static int nsshkcty = (sizeof(sshkcty) / sizeof(struct keytab));
2433
2434 static struct keytab sshdswi[] = {      /* SET SSH KEY DISPLAY /switches */
2435     { "/format", SSHKD_OUT, CM_ARG }
2436 };
2437 static int nsshdswi = (sizeof(sshdswi) / sizeof(struct keytab));
2438
2439 #ifdef COMMENT
2440 static struct keytab sshdifmt[] = {     /* SSH KEY DISPLAY /IN-FORMAT: */
2441     { "openssh", SKDF_OSSH, 0 },
2442     { "ssh.com", SKDF_SSHC, 0 }
2443 };
2444 static int nsshdifmt = (sizeof(sshdifmt) / sizeof(struct keytab));
2445 #endif /* COMMENT */
2446
2447 static struct keytab sshdofmt[] = {     /* SSH KEY DISPLAY /IN-FORMAT: */
2448     { "fingerprint", SKDF_FING, 0 },
2449     { "ietf",        SKDF_IETF, 0 },
2450     { "openssh",     SKDF_OSSH, 0 },
2451     { "ssh.com",     SKDF_SSHC, 0 }
2452 };
2453 static int nsshdofmt = (sizeof(sshdofmt) / sizeof(struct keytab));
2454
2455 static struct keytab sshkermit[] = { /* SKERMIT */
2456     { "open",       SKRM_OPN, 0 }
2457 };
2458 static int nsshkermit = (sizeof(sshkermit) / sizeof(struct keytab));
2459
2460 struct keytab sshkrmopnsw[] = {
2461     { "/password",       SSHSW_PWD, CM_ARG },
2462     { "/user",           SSHSW_USR, CM_ARG },
2463     { "/version",        SSHSW_VER, CM_ARG },
2464     { "", 0, 0 }
2465 };
2466 int nsshkrmopnsw = (sizeof(sshkrmopnsw) / sizeof(struct keytab)) - 1;
2467 #endif /* SSHBUILTIN */
2468
2469 #ifdef SFTP_BUILTIN
2470 static struct keytab sftpkwtab[] = {    /* SFTP */
2471     {  "cd",        SFTP_CD,    0 },
2472     {  "chgrp",     SFTP_CHGRP, 0 },
2473     {  "chmod",     SFTP_CHMOD, 0 },
2474     {  "chown",     SFTP_CHOWN, 0 },
2475     {  "delete",    SFTP_RM,    0 },
2476     {  "dir",       SFTP_DIR,   0 },
2477     {  "get",       SFTP_GET,   0 },
2478     {  "mkdir",     SFTP_MKDIR, 0 },
2479     {  "open",      SFTP_OPN,   0 },
2480     {  "put",       SFTP_PUT,   0 },
2481     {  "pwd",       SFTP_PWD,   0 },
2482     {  "rename",    SFTP_REN,   0 },
2483     {  "rm",        SFTP_RM,    CM_INV },
2484     {  "rmdir",     SFTP_RMDIR, 0 },
2485     {  "symlink",   SFTP_LINK,  0 },
2486     {  "version",   SFTP_VER,   0 }
2487 };
2488 static int nsftpkwtab = (sizeof(sftpkwtab) / sizeof(struct keytab));
2489 #endif /* SFTP_BUILTIN */
2490 #endif /* ANYSSH */
2491
2492 #ifdef NETCONN
2493 struct keytab netkey[] = {              /* SET NETWORK table */
2494     { "directory", XYNET_D,  0 },
2495     { "type",      XYNET_T,  0 }
2496 };
2497 int nnetkey = (sizeof(netkey) / sizeof(struct keytab));
2498
2499 struct keytab netcmd[] = {
2500 /*
2501   These are the network types.
2502 */
2503 #ifdef NETCMD
2504     { "command",       NET_CMD,  CM_INV }, /* Command */
2505 #endif /* NETCMD */
2506
2507 #ifdef DECNET                           /* DECnet / PATHWORKS */
2508     { "decnet",        NET_DEC,  0 },
2509 #endif /* DECNET */
2510
2511 #ifdef NETDLL
2512     { "dll",           NET_DLL,  CM_INV }, /* DLL to be loaded */
2513 #endif /* NETDLL */
2514
2515 #ifdef NETFILE
2516     { "file",           NET_FILE, CM_INV }, /* FILE (real crude) */
2517 #endif /* NETFILE */
2518
2519 #ifdef NPIPE                            /* Named Pipes */
2520     { "named-pipe",     NET_PIPE,  0 },
2521 #endif /* NPIPE */
2522
2523 #ifdef CK_NETBIOS
2524     { "netbios",        NET_BIOS,  0 }, /* NETBIOS */
2525 #endif /* CK_NETBIOS */
2526
2527 #ifdef DECNET                           /* DECnet / PATHWORKS (alias) */
2528     { "pathworks",     NET_DEC,  CM_INV },
2529 #endif /* DECNET */
2530
2531 #ifdef NETCMD
2532     { "pipe",          NET_CMD,  0 },   /* Pipe */
2533 #endif /* NETCMD */
2534
2535 #ifdef NETPTY
2536     { "pseudoterminal",NET_PTY, 0 },    /* Pseudoterminal */
2537 #endif /* NETPTY */
2538
2539 #ifdef NETPTY
2540     { "pty",          NET_PTY,  CM_INV }, /* Inv syn for pseudoterm */
2541 #endif /* NETPTY */
2542
2543 #ifdef SSHBUILTIN
2544     { "ssh",          NET_SSH,  0 },
2545 #endif /* SSHBUILTIN */
2546
2547 #ifdef SUPERLAT
2548     { "superlat",     NET_SLAT, 0 },    /* Meridian Technologies' SuperLAT */
2549 #endif /* SUPERLAT */
2550
2551 #ifdef TCPSOCKET                        /* TCP/IP sockets library */
2552     { "tcp/ip",       NET_TCPB, 0 },
2553 #endif /* TCPSOCKET */
2554 #ifdef SUPERLAT
2555     { "tes32",        NET_SLAT, 0 },    /* Emulux TES32 */
2556 #endif /* SUPERLAT */
2557 #ifdef ANYX25                           /* X.25 */
2558 #ifdef SUNX25
2559     { "x",            NET_SX25, CM_INV|CM_ABR },
2560     { "x.25",         NET_SX25, 0 },
2561     { "x25",          NET_SX25, CM_INV },
2562 #else
2563 #ifdef STRATUSX25
2564     { "x",            NET_VX25, CM_INV|CM_ABR },
2565     { "x.25",         NET_VX25, 0 },
2566     { "x25",          NET_VX25, CM_INV },
2567 #endif /* STRATUSX25 */
2568 #endif /* SUNX25 */
2569 #ifdef IBMX25
2570     { "x",            NET_IX25, CM_INV|CM_ABR },
2571     { "x.25",         NET_IX25, CM_INV },
2572     { "x25",          NET_IX25, CM_INV },
2573 #endif /* IBMX25 */
2574 #ifdef HPX25
2575     { "x",            NET_IX25, CM_INV|CM_ABR },
2576     { "x.25",         NET_IX25, 0 },
2577     { "x25",          NET_IX25, CM_INV },
2578 #endif /* HPX25 */
2579 #endif /* ANYX25 */
2580     { "", 0, 0 }
2581 };
2582 int nnets = (sizeof(netcmd) / sizeof(struct keytab));
2583
2584 #ifndef NOTCPOPTS
2585 #ifdef TCPSOCKET
2586
2587 /* TCP options */
2588
2589 struct keytab tcpopt[] = {
2590     { "address",   XYTCP_ADDRESS, 0 },
2591 #ifdef CK_DNS_SRV
2592     { "dns-service-records", XYTCP_DNS_SRV, 0 },
2593 #endif /* CK_DNS_SRV */
2594 #ifdef SO_DONTROUTE
2595     { "dontroute",   XYTCP_DONTROUTE, 0 },
2596 #endif /* SO_DONTROUTE */
2597 #ifndef NOHTTP
2598     { "http-proxy", XYTCP_HTTP_PROXY, 0 },
2599 #endif /* NOHTTP */
2600 #ifdef SO_KEEPALIVE
2601     { "keepalive", XYTCP_KEEPALIVE, 0 },
2602 #endif /* SO_KEEPALIVE */
2603 #ifdef SO_LINGER
2604     { "linger", XYTCP_LINGER, 0 },
2605 #endif /* SO_LINGER */
2606 #ifdef TCP_NODELAY
2607     { "nagle",  XYTCP_NAGLE,    CM_INV },
2608     { "nodelay", XYTCP_NODELAY, 0 },
2609 #endif /* TCP_NODELAY */
2610     { "reverse-dns-lookup", XYTCP_RDNS, 0 },
2611 #ifdef SO_RCVBUF
2612     { "recvbuf", XYTCP_RECVBUF, 0 },
2613 #endif /* SO_RCVBUF */
2614 #ifdef SO_SNDBUF
2615     { "sendbuf", XYTCP_SENDBUF, 0 },
2616 #endif /* SO_SNDBUF */
2617 #ifdef NT
2618 #ifdef CK_SOCKS
2619     { "socks-server", XYTCP_SOCKS_SVR, 0 },
2620 #endif /* CK_SOCKS */
2621 #endif /* NT */
2622 #ifdef VMS
2623 #ifdef DEC_TCPIP
2624     { "ucx-port-bug", XYTCP_UCX, 0 },
2625 #endif /* DEC_TCPIP */
2626 #endif /* VMS */
2627     { "",0,0 }
2628 };
2629 int ntcpopt = (sizeof(tcpopt) / sizeof(struct keytab));
2630 #endif /* TCPSOCKET */
2631 #endif /* NOTCPOPTS */
2632 #endif /* NETCONN */
2633
2634 #ifdef OS2
2635 /* K95 Manual Chapter Table -- Keep these two tables in sync! */
2636
2637 static char * linktbl[] = {             /* Internal links in k95.htm */
2638     "#top",                             /* 00 */
2639     "#what",                            /* 01 */
2640     "#install",                         /* 02 */
2641     "#start",                           /* 03 */
2642     "#dialer",                          /* 04 */
2643     "#entries",                         /* 05 */
2644     "#command",                         /* 06 */
2645     "#terminal",                        /* 07 */
2646     "#transfer",                        /* 08 */
2647     "#hostmode"                         /* 09 */
2648 };
2649
2650 static struct keytab chaptbl[] = {
2651     { "Command-Screen",     6, 0 },
2652     { "Contents",           0, 0 },
2653     { "Dialer-Entries",     5, 0 },
2654     { "File-Transfer",      8, 0 },
2655     { "Getting-Started",    3, 0 },
2656     { "Host-Mode",          9, 0 },
2657     { "Installation",       2, 0 },
2658     { "Terminal-Emulation", 7, 0 },
2659     { "Using-The-Dialer",   4, 0 },
2660     { "What-Is-K95",        1, 0 },
2661     { "",                   0, 0 }
2662 };
2663 static int nchaptbl = (sizeof(chaptbl) / sizeof(struct keytab) - 1);
2664 #endif /* OS2 */
2665
2666 #ifndef NOXFER
2667 /* Remote Command Table */
2668
2669 struct keytab remcmd[] = {
2670 #ifndef NOSPL
2671     { "as",        XZASG, CM_INV|CM_ABR },
2672     { "asg",       XZASG, CM_INV },
2673     { "assign",    XZASG, 0 },
2674 #endif /* NOSPL */
2675     { "cd",        XZCWD, 0 },
2676     { "cdup",      XZCDU, CM_INV },
2677     { "copy",      XZCPY, 0 },
2678     { "cwd",       XZCWD, CM_INV },
2679     { "delete",    XZDEL, 0 },
2680     { "directory", XZDIR, 0 },
2681     { "e",         XZXIT, CM_ABR|CM_INV },
2682     { "erase",     XZDEL, CM_INV },
2683     { "exit",      XZXIT, 0 },
2684     { "help",      XZHLP, 0 },
2685 #ifndef NOPUSH
2686     { "host",      XZHOS, 0 },
2687 #endif /* NOPUSH */
2688 #ifndef NOFRILLS
2689     { "kermit",    XZKER, 0 },
2690     { "l",         XZLGI, CM_ABR|CM_INV },
2691     { "lo",        XZLGI, CM_ABR|CM_INV },
2692     { "log",       XZLGI, CM_ABR|CM_INV },
2693     { "login",     XZLGI, 0 },
2694     { "logout",    XZLGO, 0 },
2695     { "message",   XZMSG, 0 },
2696     { "mkdir",     XZMKD, 0 },
2697     { "print",     XZPRI, 0 },
2698 #endif /* NOFRILLS */
2699     { "pwd",       XZPWD, 0 },
2700 #ifndef NOSPL
2701     { "query",     XZQUE, 0 },
2702 #endif /* NOSPL */
2703     { "rename",    XZREN, 0 },
2704     { "rmdir",     XZRMD, 0 },
2705     { "set",       XZSET, 0 },
2706     { "space",     XZSPA, 0 },
2707 #ifndef NOFRILLS
2708     { "type",      XZTYP, 0 },
2709     { "who",       XZWHO, 0 },
2710 #endif /* NOFRILLS */
2711     { "", 0, 0}
2712 };
2713 int nrmt = (sizeof(remcmd) / sizeof(struct keytab)) - 1;
2714 #endif /* NOXFER */
2715
2716 struct keytab logtab[] = {
2717 #ifdef CKLOGDIAL
2718     { "connections",  LOGM, CM_INV },
2719     { "cx",           LOGM, 0 },
2720 #endif /* CKLOGDIAL */
2721 #ifdef DEBUG
2722     { "debugging",    LOGD, 0 },
2723 #endif /* DEBUG */
2724     { "packets",      LOGP, 0 },
2725 #ifndef NOLOCAL
2726     { "session",      LOGS, 0 },
2727 #endif /* NOLOCAL */
2728 #ifdef TLOG
2729     { "transactions", LOGT, 0 },
2730 #endif /* TLOG */
2731     { "", 0, 0 }
2732 };
2733 int nlog = (sizeof(logtab) / sizeof(struct keytab)) - 1;
2734
2735 struct keytab writab[] = {
2736 #ifndef NOSPL
2737     { "append-file",     LOGW, CM_INV },
2738 #endif /* NOSPL */
2739     { "debug-log",       LOGD, 0 },
2740     { "error",           LOGE, 0 },
2741 #ifndef NOSPL
2742     { "file",            LOGW, 0 },
2743 #endif /* NOSPL */
2744     { "packet-log",      LOGP, 0 },
2745     { "screen",          LOGX, 0 },
2746 #ifndef NOLOCAL
2747     { "session-log",     LOGS, 0 },
2748 #endif /* NOLOCAL */
2749     { "sys$output",      LOGX, CM_INV },
2750     { "t",               LOGT, CM_ABR|CM_INV }, /* Because of a typo in */
2751     { "tr",              LOGT, CM_ABR|CM_INV }, /* the book... */
2752     { "tra",             LOGT, CM_ABR|CM_INV },
2753     { "tran",            LOGT, CM_ABR|CM_INV },
2754     { "trans",           LOGT, CM_ABR|CM_INV },
2755     { "transa",          LOGT, CM_ABR|CM_INV },
2756     { "transac",         LOGT, CM_ABR|CM_INV },
2757     { "transact",        LOGT, CM_ABR|CM_INV },
2758     { "transacti",       LOGT, CM_ABR|CM_INV },
2759     { "transactio",      LOGT, CM_ABR|CM_INV },
2760     { "transaction",     LOGT, CM_ABR|CM_INV },
2761     { "transaction-log", LOGT, 0 },
2762     { "transactions",    LOGT, CM_INV }
2763 };
2764 int nwri = (sizeof(writab) / sizeof(struct keytab));
2765
2766 static struct keytab clrtab[] = {       /* Keywords for CLEAR command */
2767 #ifndef NOSPL
2768     { "alarm",            CLR_ALR,         0 },
2769 #ifdef CK_APC
2770     { "apc",              CLR_APC,         0 },
2771 #endif /* CK_APC */
2772 #ifdef PATTERNS
2773     { "binary-patterns",  CLR_BIN,         0 },
2774 #endif /* PATTERNS */
2775     { "both",             CLR_DEV|CLR_INP, CM_INV },
2776 #endif /* NOSPL */
2777 #ifdef OS2
2778     { "command-screen",   CLR_CMD,         0 },
2779 #endif /* OS2 */
2780 #ifndef NOSPL
2781     { "device",           CLR_DEV,         CM_INV|CM_ABR },
2782     { "device-and-input", CLR_DEV|CLR_INP, 0 },
2783 #endif /* NOSPL */
2784     { "device-buffer",    CLR_DEV,         0 },
2785 #ifndef NODIAL
2786     { "dial-status",      CLR_DIA,       0 },
2787 #endif /* NODIAL */
2788 #ifndef NOSPL
2789     { "input-buffer",     CLR_INP,         0 },
2790 #endif /* NOSPL */
2791     { "keyboard-buffer",  CLR_KBD,         0 },
2792     { "send-list",        CLR_SFL,         0 },
2793 #ifdef OS2
2794     { "scr",              CLR_SCL,         CM_INV|CM_ABR },
2795 #endif /* OS2 */
2796     { "screen",           CLR_SCR,         0 },
2797 #ifdef OS2
2798     { "scrollback",       CLR_SCL,         CM_INV },
2799     { "terminal-screen",  CLR_TRM,         0 },
2800 #endif /* OS2 */
2801 #ifdef PATTERNS
2802     { "text-patterns",    CLR_TXT,         0 },
2803 #endif /* PATTERNS */
2804     { "", 0, 0 }
2805 };
2806 int nclear = (sizeof(clrtab) / sizeof(struct keytab)) - 1;
2807
2808 struct keytab clstab[] = {              /* Keywords for CLOSE command */
2809 #ifndef NOSPL
2810     { "!read",           LOGR, CM_INV },
2811     { "!write",          LOGW, CM_INV },
2812 #ifndef NOPUSH
2813 #endif /* NOPUSH */
2814 #endif /* NOSPL */
2815 #ifndef NOSPL
2816     { "append-file",     LOGW, CM_INV },
2817 #endif /* NOSPL */
2818 #ifndef NOLOCAL
2819     { "connection",      9999, 0 },
2820 #endif /* NOLOCAL */
2821 #ifdef CKLOGDIAL
2822     { "cx-log",          LOGM, 0 },
2823 #endif /* CKLOGDIAL */
2824 #ifdef DEBUG
2825     { "debug-log",       LOGD, 0 },
2826 #endif /* DEBUG */
2827     { "host",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2828     { "line",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2829     { "p",               LOGP, CM_INV|CM_ABR },
2830     { "packet-log",      LOGP, 0 },
2831     { "port",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2832 #ifndef NOSPL
2833     { "read-file",       LOGR, 0 },
2834 #endif /* NOSPL */
2835 #ifndef NOLOCAL
2836     { "session-log",     LOGS, 0 },
2837 #endif /* NOLOCAL */
2838 #ifdef TLOG
2839     { "t",               LOGT, CM_ABR|CM_INV }, /* Because of a typo in */
2840     { "tr",              LOGT, CM_ABR|CM_INV }, /* the book... */
2841     { "tra",             LOGT, CM_ABR|CM_INV },
2842     { "tran",            LOGT, CM_ABR|CM_INV },
2843     { "trans",           LOGT, CM_ABR|CM_INV },
2844     { "transa",          LOGT, CM_ABR|CM_INV },
2845     { "transac",         LOGT, CM_ABR|CM_INV },
2846     { "transact",        LOGT, CM_ABR|CM_INV },
2847     { "transacti",       LOGT, CM_ABR|CM_INV },
2848     { "transactio",      LOGT, CM_ABR|CM_INV },
2849     { "transaction",     LOGT, CM_ABR|CM_INV },
2850     { "transaction-log", LOGT, 0 },
2851     { "transactions",    LOGT, CM_INV },
2852 #endif /* TLOG */
2853 #ifndef NOSPL
2854     { "write-file",      LOGW, 0 },
2855 #endif /* NOSPL */
2856     { "", 0, 0 }
2857 };
2858 int ncls = (sizeof(clstab) / sizeof(struct keytab)) - 1;
2859
2860 /* SHOW command arguments */
2861
2862 #ifndef NOSHOW
2863 struct keytab shotab[] = {
2864 #ifndef NOSPL
2865     { "alarm",        SHALRM, 0 },
2866     { "arg",          SHARG, CM_INV|CM_ABR },
2867     { "arguments",    SHARG, 0 },
2868     { "args",         SHARG, CM_INV },
2869     { "arrays",       SHARR, 0 },
2870 #endif /* NOSPL */
2871
2872 #ifndef NOCSETS
2873     { "associations", SHASSOC, 0 },
2874 #endif /* NOCSETS */
2875
2876 #ifndef NOXFER
2877     { "attributes",   SHATT, 0 },
2878 #endif /* NOXFER */
2879
2880 #ifdef CK_AUTHENTICATION
2881     { "authentication", SHOAUTH, CM_INV },
2882 #endif /* CK_AUTHENTICATION */
2883
2884 #ifndef NOPUSH
2885 #ifdef BROWSER
2886     { "browser",      SHBROWSE, CM_PSH|CM_LOC },
2887 #endif /*  BROWSER */
2888 #endif /* NOPUSH */
2889     { "cd",           SHCD, 0 },
2890     { "character-sets", SHCSE, 0 },
2891     { "cmd",          SHCMD, CM_INV },
2892 #ifndef NOLOCAL
2893     { "com",          SHCOM, CM_INV|CM_ABR },
2894     { "comm",         SHCOM, CM_INV|CM_ABR },
2895     { "communications", SHCOM, 0 },
2896 #endif /* NOLOCAL */
2897     { "command",      SHCMD, 0 },
2898     { "connection",   SHCONNX, 0 },
2899 #ifdef CK_SPEED
2900     { "control-prefixing", SHCTL, 0 },
2901 #endif /* CK_SPEED */
2902 #ifdef CKLOGDIAL
2903     { "cx",           SHCONNX, CM_INV },
2904 #endif /* CKLOGDIAL */
2905 #ifndef NOSPL
2906     { "count",        SHCOU, 0 },
2907 #endif /* NOSPL */
2908     { "d",            SHDIA, CM_INV|CM_ABR },
2909 #ifdef VMS
2910     { "default",      SHDFLT, 0 },
2911 #else
2912     { "default",      SHDFLT, CM_INV },
2913 #endif /* VMS */
2914 #ifndef NODIAL
2915     { "dial",         SHDIA, CM_LOC },
2916 #endif /* NODIAL */
2917     { "double/ignore",SHDBL, 0 },
2918 #ifndef NOPUSH
2919 #ifndef NOFRILLS
2920     { "editor",       SHEDIT, CM_PSH },
2921 #endif /*  NOFRILLS */
2922 #endif /* NOPUSH */
2923 #ifndef NOLOCAL
2924     { "escape",       SHESC, CM_LOC },
2925 #endif /* NOLOCAL */
2926     { "exit",         SHEXI, 0 },
2927     { "extended-options", SHXOPT, CM_INV },
2928     { "features",     SHFEA, 0 },
2929     { "file",         SHFIL, 0 },
2930 #ifndef NOLOCAL
2931     { "flow-control", SHOFLO, 0 },
2932 #endif /* NOLOCAL */
2933 #ifdef BROWSER
2934     { "ftp",          SHOFTP, CM_PSH|CM_LOC },
2935 #else
2936 #ifndef NOFTP
2937 #ifndef SYSFTP
2938 #ifdef TCPSOCKET
2939     { "ftp",          SHOFTP, 0 },      /* (built-in ftp) */
2940 #endif /* TCPSOCKET */
2941 #endif /* SYSFTP */
2942 #endif /* NOFTP */
2943 #endif /* BROWSER */
2944 #ifndef NOSPL
2945     { "functions",    SHFUN, 0 },
2946     { "globals",      SHVAR, 0 },
2947 #endif /* NOSPL */
2948 #ifdef KUI
2949     { "gui",          SHOGUI, 0 },
2950 #endif /* KUI */
2951 #ifdef CK_RECALL
2952     { "history",      SHHISTORY, 0 },
2953 #endif /* CK_RECALL */
2954     { "ignore/double",SHDBL, CM_INV },
2955     { "iksd",         SHOIKS, CM_INV },
2956 #ifndef NOSPL
2957     { "input",        SHINP, 0 },
2958 #endif /* NOSPL */
2959 #ifndef NOSETKEY
2960     { "k",            SHKEY, CM_INV|CM_ABR },
2961     { "key",          SHKEY, 0 },
2962 #ifndef NOKVERBS
2963     { "kverbs",       SHKVB, 0 },
2964 #endif /* NOKVERBS */
2965 #endif /* NOSETKEY */
2966 #ifdef CK_LABELED
2967     { "labeled-file-info", SHLBL, 0 },
2968 #endif /* CK_LABELED */
2969 #ifndef NOCSETS
2970     { "languages",    SHLNG, 0 },
2971 #endif /* NOCSETS */
2972     { "logs",         SHLOG, 0 },
2973 #ifndef NOSPL
2974     { "macros",       SHMAC, 0 },
2975 #endif /* NOSPL */
2976 #ifndef NODIAL
2977     { "modem",        SHMOD, CM_LOC },
2978 #else
2979     { "modem-signals",SHCOM, CM_INV|CM_LOC },
2980 #endif /* NODIAL */
2981 #ifndef NOLOCAL
2982 #ifdef OS2MOUSE
2983     { "mouse",        SHMOU, CM_LOC },
2984 #endif /* OS2MOUSE */
2985 #endif /* NOLOCAL */
2986 #ifdef NETCONN
2987     { "network",      SHNET, CM_LOC },
2988 #else
2989     { "network",      SHNET, CM_INV|CM_LOC },
2990 #endif /* NETCONN */
2991     { "options",      SHOPTS, 0 },
2992 #ifndef NOSPL
2993     { "output",       SHOUTP, CM_INV },
2994 #endif /* NOSPL */
2995 #ifdef ANYX25
2996 #ifndef IBMX25
2997     { "pad",          SHPAD,  CM_LOC },
2998 #endif /* IBMX25 */
2999 #endif /* ANYX25 */
3000     { "parameters",   SHPAR,  CM_INV },
3001 #ifdef PATTERNS
3002     { "patterns",     SHOPAT, 0 },
3003 #endif /* PATTERNS */
3004     { "printer",      SHPRT,  0 },
3005 #ifdef CK_SPEED
3006     { "prefixing",    SHCTL,  CM_INV },
3007 #endif /* CK_SPEED */
3008 #ifndef NOXFER
3009     { "protocol",     SHPRO,  0 },
3010 #endif /* NOXFER */
3011     { "rename",       SHOREN, 0 },
3012 #ifndef NOSPL
3013     { "scripts",      SHSCR,  CM_LOC },
3014 #endif /* NOSPL */
3015     { "send-list",    SHSFL,  0 },
3016 #ifndef NOSERVER
3017     { "server",       SHSER,  0 },
3018 #endif /* NOSERVER */
3019 #ifndef NOSEXP
3020     { "sexpression",  SHSEXP, 0 },
3021 #endif /* NOSEXP */
3022 #ifdef ANYSSH
3023     { "ssh",          SHOSSH, 0 },
3024 #endif /* ANYSSH */
3025     { "stack",        SHSTK,  0 },
3026     { "status",       SHSTA,  0 },
3027 #ifdef STREAMING
3028     { "streaming",    SHOSTR, 0 },
3029 #endif /* STREAMING */
3030 #ifndef NOLOCAL
3031 #ifdef OS2
3032     { "tabs",          SHTAB, CM_INV|CM_LOC },
3033 #endif /* OS2 */
3034 #ifdef CK_TAPI
3035     { "tapi",          SHTAPI, CM_LOC },
3036     { "tapi-comm",     SHTAPI_C, CM_INV|CM_LOC },
3037     { "tapi-location", SHTAPI_L, CM_INV|CM_LOC },
3038     { "tapi-modem",    SHTAPI_M, CM_INV|CM_LOC },
3039 #endif /* CK_TAPI */
3040     { "tcp",           SHTCP,  CM_LOC },
3041 #ifdef TNCODE
3042     { "tel",           SHTEL,  CM_INV|CM_ABR },
3043     { "telnet",        SHTEL,  0 },
3044     { "telopt",        SHTOPT, 0 },
3045 #endif /* TNCODE */
3046     { "terminal",      SHTER,  CM_LOC },
3047 #endif /* NOLOCAL */
3048 #ifndef NOXMIT
3049     { "tr",            SHXMI, CM_INV|CM_ABR },
3050     { "tra",           SHXMI, CM_INV|CM_ABR },
3051     { "tran",          SHXMI, CM_INV|CM_ABR },
3052     { "trans",         SHXMI, CM_INV|CM_ABR },
3053 #endif /* NOXMIT */
3054 #ifndef NOXFER
3055     { "transfer",      SHOXFER, 0 },
3056 #endif /* NOXFER */
3057 #ifndef NOXMIT
3058     { "transmit",      SHXMI, 0 },
3059 #endif /* NOXMIT */
3060 #ifdef CK_TRIGGER
3061     { "trigger",       SHTRIG, CM_LOC },
3062 #endif /* CK_TRIGGER */
3063 #ifndef NOSETKEY
3064 #ifndef NOKVERBS
3065 #ifdef OS2
3066     { "udk",           SHUDK, CM_LOC },
3067 #endif /* OS2 */
3068 #endif /* NOKVERBS */
3069 #endif /* NOSETKEY */
3070 #ifndef NOSPL
3071     { "variables",     SHBUI, 0 },
3072 #endif /* NOSPL */
3073 #ifndef NOFRILLS
3074     { "versions",      SHVER, 0 },
3075 #endif /* NOFRILLS */
3076 #ifdef OS2
3077     { "vscrn",         SHVSCRN, CM_INV|CM_LOC },
3078 #endif /* OS2 */
3079     { "xfer",          SHOXFER,  CM_INV },
3080 #ifndef NOXMIT
3081     { "xmit",          SHXMI,    CM_INV },
3082 #endif /* NOXMIT */
3083     { "", 0, 0 }
3084 };
3085 int nsho = (sizeof(shotab) / sizeof(struct keytab)) - 1;
3086 #endif /* NOSHOW */
3087
3088 #ifdef ANYX25
3089 #ifndef IBMX25
3090 struct keytab padtab[] = {              /* PAD commands */
3091     { "clear",      XYPADL, 0 },
3092     { "interrupt",  XYPADI, 0 },
3093     { "reset",      XYPADR, 0 },
3094     { "status",     XYPADS, 0 }
3095 };
3096 int npadc = (sizeof(padtab) / sizeof(struct keytab));
3097 #endif /* IBMX25 */
3098 #endif /* ANYX25 */
3099
3100 #ifndef NOSERVER
3101 static struct keytab kmstab[] = {
3102     { "both",    3, 0 },
3103     { "local",   1, 0 },
3104     { "remote",  2, 0 }
3105 };
3106
3107 static struct keytab enatab[] = {       /* ENABLE commands */
3108     { "all",        EN_ALL,  0 },
3109 #ifndef NOSPL
3110     { "as",         EN_ASG,  CM_INV|CM_ABR },
3111     { "asg",        EN_ASG,  CM_INV },
3112     { "assign",     EN_ASG,  0 },
3113 #endif /* NOSPL */
3114 #ifndef datageneral
3115     { "bye",        EN_BYE,  0 },
3116 #endif /* datageneral */
3117     { "cd",         EN_CWD,  0 },
3118 #ifdef ZCOPY
3119     { "copy",       EN_CPY,  0 },
3120 #endif /* ZCOPY */
3121     { "cwd",        EN_CWD,  CM_INV },
3122     { "delete",     EN_DEL,  0 },
3123     { "directory",  EN_DIR,  0 },
3124     { "enable",     EN_ENA,  CM_INV },
3125     { "exit",       EN_XIT,  0 },
3126     { "finish",     EN_FIN,  0 },
3127     { "get",        EN_GET,  0 },
3128     { "host",       EN_HOS,  0 },
3129     { "mail",       EN_MAI,  0 },
3130     { "mkdir",      EN_MKD,  0 },
3131     { "print",      EN_PRI,  0 },
3132 #ifndef NOSPL
3133     { "query",      EN_QUE,  0 },
3134 #endif /* NOSPL */
3135     { "rename",     EN_REN,  0 },
3136     { "retrieve",   EN_RET,  CM_INV },
3137     { "rmdir",      EN_RMD,  0 },
3138     { "send",       EN_SEN,  0 },
3139     { "set",        EN_SET,  0 },
3140     { "space",      EN_SPA,  0 },
3141     { "type",       EN_TYP,  0 },
3142     { "who",        EN_WHO,  0 }
3143 };
3144 static int nena = (sizeof(enatab) / sizeof(struct keytab));
3145 #endif /* NOSERVER */
3146
3147 struct keytab txtbin[] = {
3148     { "all",        2, 0 },
3149     { "binary",     1, 0 },
3150     { "text",       0, 0 }
3151 };
3152
3153 #ifndef NOXFER
3154 static struct keytab sndtab[] = {       /* SEND command options */
3155     { "/after",           SND_AFT, CM_ARG },
3156 #ifndef NOSPL
3157     { "/array",           SND_ARR, CM_ARG },
3158 #endif /* NOSPL */
3159     { "/as-name",         SND_ASN, CM_ARG },
3160     { "/b",               SND_BIN, CM_INV|CM_ABR },
3161     { "/before",          SND_BEF, CM_ARG },
3162     { "/binary",          SND_BIN, 0 },
3163 #ifdef CALIBRATE
3164     { "/c",               SND_CMD, CM_INV|CM_ABR },
3165     { "/calibrate",       SND_CAL, CM_INV|CM_ARG },
3166 #endif /* CALIBRATE */
3167     { "/command",         SND_CMD, CM_PSH },
3168     { "/delete",          SND_DEL, 0 },
3169 #ifdef UNIXOROSK
3170     { "/dotfiles",        SND_DOT, 0 },
3171 #endif /* UNIXOROSK */
3172     { "/except",          SND_EXC, CM_ARG },
3173 #ifdef PIPESEND
3174     { "/filter",          SND_FLT, CM_ARG|CM_PSH },
3175 #endif /* PIPESEND */
3176     { "/filenames",       SND_NAM, CM_ARG },
3177 #ifdef CKSYMLINK
3178     { "/followlinks",     SND_LNK, 0 },
3179 #endif /* CKSYMLINK */
3180 #ifdef VMS
3181     { "/image",           SND_IMG, 0 },
3182 #else
3183     { "/image",           SND_BIN, CM_INV },
3184 #endif /* VMS */
3185 #ifdef CK_LABELED
3186     { "/labeled",         SND_LBL, 0 },
3187 #endif /* CK_LABELED */
3188     { "/larger-than",     SND_LAR, CM_ARG },
3189     { "/listfile",        SND_FIL, CM_ARG },
3190 #ifndef NOFRILLS
3191     { "/mail",            SND_MAI, CM_ARG },
3192 #endif /* NOFRILLS */
3193 #ifdef CK_TMPDIR
3194     { "/move-to",         SND_MOV, CM_ARG },
3195 #endif /* CK_TMPDIR */
3196     { "/nobackupfiles",   SND_NOB, 0 },
3197 #ifdef UNIXOROSK
3198     { "/nodotfiles",      SND_NOD, 0 },
3199 #endif /* UNIXOROSK */
3200 #ifdef CKSYMLINK
3201     { "/nofollowlinks",   SND_NLK, 0 },
3202 #endif /* CKSYMLINK */
3203     { "/not-after",       SND_NAF, CM_ARG },
3204     { "/not-before",      SND_NBE, CM_ARG },
3205     { "/pathnames",       SND_PTH, CM_ARG },
3206     { "/print",           SND_PRI, CM_ARG },
3207 #ifdef CK_XYZ
3208     { "/protocol",        SND_PRO, CM_ARG },
3209 #else
3210     { "/protocol",        SND_PRO, CM_ARG|CM_INV },
3211 #endif /* CK_XYZ */
3212     { "/quiet",           SND_SHH, 0 },
3213     { "/recover",         SND_RES, 0 },
3214 #ifdef RECURSIVE
3215 /* Systems where we do recursion */
3216     { "/recursive",       SND_REC, 0 },
3217 #else
3218 #ifdef VMS
3219 /* Systems that do recursion themselves without our assistance */
3220 /* if we give them the right kind of wildcard */
3221     { "/recursive",       SND_REC, 0 },
3222 #else
3223 #ifdef datageneral
3224     { "/recursive",       SND_REC, 0 },
3225 #else
3226     { "/recursive",       SND_REC, CM_INV },
3227 #endif /* datageneral */
3228 #endif /* VMS */
3229 #endif /* RECURSIVE */
3230     { "/rename-to",       SND_REN, CM_ARG },
3231     { "/since",           SND_AFT, CM_INV|CM_ARG },
3232     { "/smaller-than",    SND_SMA, CM_ARG },
3233     { "/starting-at",     SND_STA, CM_ARG },
3234 #ifndef NOFRILLS
3235     { "/su",              SND_ASN, CM_ARG|CM_INV|CM_ABR },
3236     { "/sub",             SND_ASN, CM_ARG|CM_INV|CM_ABR },
3237     { "/subject",         SND_ASN, CM_ARG },
3238 #endif /* NOFRILLS */
3239 #ifdef RECURSIVE
3240     { "/subdirectories",  SND_REC, CM_INV },
3241 #endif /* RECURSIVE */
3242     { "/text",            SND_TXT, 0 },
3243     { "/transparent",     SND_XPA, 0 },
3244     { "/type",            SND_TYP, CM_ARG }
3245 };
3246 #define NSNDTAB sizeof(sndtab)/sizeof(struct keytab)
3247 static int nsndtab = NSNDTAB;
3248
3249 #ifndef NOMSEND
3250 static struct keytab msndtab[] = {      /* MSEND options */
3251     { "/after",           SND_AFT, CM_ARG },
3252     { "/before",          SND_BEF, CM_ARG },
3253     { "/binary",          SND_BIN, 0 },
3254     { "/delete",          SND_DEL, 0 },
3255     { "/except",          SND_EXC, CM_ARG },
3256     { "/filenames",       SND_NAM, CM_ARG },
3257 #ifdef CKSYMLINK
3258     { "/followlinks",     SND_LNK, 0 },
3259 #endif /* CKSYMLINK */
3260 #ifdef VMS
3261     { "/image",           SND_IMG, 0 },
3262 #else
3263     { "/image",           SND_BIN, CM_INV },
3264 #endif /* VMS */
3265 #ifdef CK_LABELED
3266     { "/labeled",         SND_LBL, 0 },
3267 #endif /* CK_LABELED */
3268     { "/larger-than",     SND_LAR, CM_ARG },
3269     { "/list",            SND_FIL, CM_ARG },
3270 #ifndef NOFRILLS
3271     { "/mail",            SND_MAI, CM_ARG },
3272 #endif /* NOFRILLS */
3273 #ifdef CK_TMPDIR
3274     { "/move-to",         SND_MOV, CM_ARG },
3275 #endif /* CK_TMPDIR */
3276 #ifdef CKSYMLINK
3277     { "/nofollowlinks", SND_NLK, 0 },
3278 #endif /* CKSYMLINK */
3279     { "/not-after",       SND_NAF, CM_ARG },
3280     { "/not-before",      SND_NBE, CM_ARG },
3281     { "/pathnames",       SND_PTH, CM_ARG },
3282     { "/print",           SND_PRI, CM_ARG },
3283 #ifdef CK_XYZ
3284     { "/protocol",        SND_PRO, CM_ARG },
3285 #endif /* CK_XYZ */
3286     { "/quiet",           SND_SHH, 0 },
3287     { "/recover",         SND_RES, 0 },
3288     { "/rename-to",       SND_REN, CM_ARG },
3289     { "/since",           SND_AFT, CM_INV|CM_ARG },
3290     { "/smaller-than",    SND_SMA, CM_ARG },
3291     { "/starting-at",     SND_STA, CM_ARG },
3292 #ifndef NOFRILLS
3293     { "/subject",         SND_ASN, CM_ARG },
3294 #endif /* NOFRILLS */
3295     { "/text",            SND_TXT, 0 },
3296     { "/transparent",     SND_XPA, 0 },
3297     { "/type",            SND_TYP, CM_ARG }
3298 };
3299 #define NMSNDTAB sizeof(msndtab)/sizeof(struct keytab)
3300 static int nmsndtab = NMSNDTAB;
3301 #endif /* NOMSEND */
3302 #endif /* NOXFER */
3303
3304 /* CONNECT command switches */
3305
3306 #define CONN_II  0      /* Idle interval */
3307 #define CONN_IS  1      /* Idle string */
3308 #define CONN_IL  2      /* Idle limit */
3309 #define CONN_NV  3      /* Non-Verbose */
3310 #define CONN_TL  4      /* Time limit */
3311 #define CONN_TS  5      /* Trigger string */
3312 #define CONN_AS  6      /* Asynchronous */
3313 #define CONN_SY  7      /* Synchronous */
3314 #define CONN_MAX 7      /* Number of CONNECT switches */
3315
3316 #ifndef NOLOCAL
3317 static struct keytab conntab[] = {
3318 #ifdef OS2
3319     { "/asynchronous",    CONN_AS, CM_INV },
3320 #endif /* OS2 */
3321 #ifdef XLIMITS
3322     { "/idle-interval",   CONN_II, CM_ARG },
3323     { "/idle-limit",      CONN_IL, CM_ARG },
3324     { "/idle-string",     CONN_IS, CM_ARG },
3325     { "/quietly",         CONN_NV, CM_INV },
3326 #else
3327     { "/quietly",         CONN_NV, 0 },
3328 #endif /* XLIMITS */
3329 #ifdef OS2
3330     { "/synchronous",     CONN_SY, CM_INV },
3331 #endif /* OS2 */
3332 #ifdef XLIMITS
3333     { "/time-limit",      CONN_TL, CM_ARG },
3334 #endif /* XLIMITS */
3335 #ifdef CK_TRIGGER
3336     { "/trigger",         CONN_TS, CM_ARG },
3337 #endif /* CK_TRIGGER */
3338     { "",0,0 }
3339 };
3340 #define NCONNTAB sizeof(conntab)/sizeof(struct keytab)
3341 static int nconntab = NCONNTAB;
3342 #endif /* NOLOCAL */
3343
3344 #ifndef NOXFER
3345 static struct keytab stattab[] = {      /* STATISTICS command switches */
3346     { "/brief",   1, 0 },
3347     { "/verbose", 0, 0 }
3348 };
3349 #endif /* NOXFER */
3350
3351 #ifndef NOSPL
3352 #ifdef COMMENT
3353 struct mtab mactab[MAC_MAX] = {         /* Preinitialized macro table */
3354     { NULL, NULL, 0 }
3355 };
3356 #else
3357 struct mtab *mactab;                    /* Dynamically allocated macro table */
3358 #endif /* COMMENT */
3359 int nmac = 0;
3360
3361 struct keytab mackey[MAC_MAX];          /* Macro names as command keywords */
3362 #endif /* NOSPL */
3363
3364 #ifndef NOSPL
3365 #ifdef  OS2
3366 struct keytab beeptab[] = {             /* Beep options */
3367     { "error", BP_FAIL, 0 },
3368     { "information", BP_NOTE, 0 },
3369     { "warning", BP_WARN, 0 }
3370 };
3371 int nbeeptab = sizeof(beeptab)/sizeof(struct keytab);
3372
3373 /* CLEAR COMMMAND-SCREEN options */
3374
3375 #define CLR_C_ALL 0
3376 #define CLR_C_BOL 1
3377 #define CLR_C_BOS 2
3378 #define CLR_C_EOL 3
3379 #define CLR_C_EOS 4
3380 #define CLR_C_LIN 5
3381 #define CLR_C_SCR 6
3382
3383 struct keytab clrcmdtab[] = {
3384     { "all",        CLR_C_ALL, 0 },
3385     { "bol",        CLR_C_BOL, 0 },
3386     { "bos",        CLR_C_BOS, 0 },
3387     { "eol",        CLR_C_EOL, 0 },
3388     { "eos",        CLR_C_EOS, 0 },
3389     { "line",       CLR_C_LIN, 0 },
3390     { "scrollback", CLR_C_SCR, 0 }
3391 };
3392 int nclrcmd = sizeof(clrcmdtab)/sizeof(struct keytab);
3393 #endif /* OS2 */
3394 #endif /* NOSPL */
3395
3396 #ifdef COMMENT
3397 /* Not used at present */
3398 static struct keytab pagetab[] = {
3399     { "/more",   1, CM_INV },
3400     { "/nopage", 0, 0 },
3401     { "/page",   1, 0 }
3402 };
3403 int npagetab = sizeof(pagetab)/sizeof(struct keytab);
3404 #endif /* COMMENT */
3405
3406 #define TYP_NOP  0                      /* /NOPAGE */
3407 #define TYP_PAG  1                      /* /PAGE */
3408 #define TYP_HEA  2                      /* /HEAD:n */
3409 #define TYP_TAI  3                      /* /TAIL:n */
3410 #define TYP_PAT  4                      /* /MATCH:pattern */
3411 #define TYP_WID  5                      /* /WIDTH:cols */
3412 #define TYP_COU  6                      /* /COUNT */
3413 #define TYP_OUT  7                      /* /OUTPUT:file */
3414 #define TYP_PFX  8                      /* /PREFIX:string */
3415 #ifdef UNICODE
3416 #define TYP_XIN  9                      /* /TRANSLATE-FROM:charset */
3417 #define TYP_XUT 10                      /* /TRANSLATE-TO:charset */
3418 #define TYP_XPA 11                      /* /TRANSPARENT */
3419 #endif /* UNICODE */
3420 #ifdef KUI
3421 #define TYP_GUI 12                      /* /GUI:title */
3422 #define TYP_HIG 13                      /* /HEIGHT:rows */
3423 #endif /* KUI */
3424 #define TYP_NUM 14                      /* /NUMBER */
3425
3426 static struct keytab typetab[] = {      /* TYPE command switches */
3427     { "/count",          TYP_COU, 0 },
3428 #ifdef UNICODE
3429     { "/character-set",  TYP_XIN, CM_ARG },
3430 #endif /* UNICODE */
3431 #ifdef KUI
3432     { "/gui",            TYP_GUI, CM_ARG },
3433 #endif /* KUI */
3434     { "/head",           TYP_HEA, CM_ARG },
3435 #ifdef KUI
3436     { "/height",         TYP_HIG, CM_ARG },
3437 #endif /* KUI */
3438     { "/match",          TYP_PAT, CM_ARG },
3439 #ifdef CK_TTGWSIZ
3440     { "/more",           TYP_PAG, CM_INV },
3441     { "/nopage",         TYP_NOP, 0 },
3442     { "/number",         TYP_NUM, 0 },
3443     { "/output",         TYP_OUT, CM_ARG },
3444     { "/page",           TYP_PAG, 0 },
3445 #endif /* CK_TTGWSIZ */
3446     { "/prefix",         TYP_PFX, CM_ARG },
3447     { "/tail",           TYP_TAI, CM_ARG },
3448 #ifdef UNICODE
3449     { "/translate-to",   TYP_XUT, CM_ARG },
3450     { "/transparent",    TYP_XPA, 0 },
3451 #endif /* UNICODE */
3452     { "/width",          TYP_WID, CM_ARG },
3453 #ifdef UNICODE
3454     { "/xlate-to",       TYP_XUT, CM_INV|CM_ARG },
3455 #endif /* UNICODE */
3456     { "", 0, 0 }
3457 };
3458 int ntypetab = sizeof(typetab)/sizeof(struct keytab) - 1;
3459
3460 int typ_page = -1;                      /* TYPE /[NO]PAGE default */
3461 int typ_wid  = -1;
3462
3463 #ifndef NOSPL
3464 #define TRA_ALL 999                     /* TRACE command */
3465 #define TRA_ASG 0
3466 #define TRA_CMD 1
3467
3468 int tra_asg = 0;
3469 int tra_cmd = 0;
3470
3471 static struct keytab tracetab[] = {     /* TRACE options */
3472     { "all",            TRA_ALL, 0 },
3473     { "assignments",    TRA_ASG, 0 },
3474     { "command-level",  TRA_CMD, 0 }
3475 };
3476 static int ntracetab = sizeof(tracetab)/sizeof(struct keytab);
3477 #endif /* NOSPL */
3478
3479 #ifndef NOSHOW
3480 VOID
3481 showtypopts() {
3482     printf(" TYPE ");
3483     if (typ_page > -1) {
3484         prtopt(&optlines,typ_page ? "/PAGE" : "/NOPAGE");
3485     } else
3486       prtopt(&optlines,"(no options set)");
3487     if (typ_wid > -1) {
3488         ckmakmsg(tmpbuf,TMPBUFSIZ,"/WIDTH:",ckitoa(typ_wid),NULL,NULL);
3489         prtopt(&optlines,tmpbuf);
3490     }
3491     prtopt(&optlines,"");
3492 }
3493 #endif /* NOSHOW */
3494
3495 #ifdef LOCUS
3496 /* isauto == 1 if locus is being switched automatically */
3497
3498 VOID
3499 setlocus(x, isauto) int x, isauto; {
3500     extern int quitting;
3501     if (x) x = 1;
3502     if (x && locus) return;
3503     if (!x && !locus) return;
3504     /* Get here if it actually needs to be changed */
3505 #ifdef OS2
3506     if (isauto &&                       /* Automatically switching */
3507         !quitting &&                    /* not exiting */
3508         autolocus == 2) {               /* and AUTOLOCUS is set to ASK */
3509         char locmsg[300];
3510         ckmakmsg(locmsg,300,
3511                  "Switching Locus to ",
3512                  x ? "LOCAL" : "REMOTE",
3513                  " for file management commands\n"
3514                  "such as CD, DIRECTORY, DELETE, RENAME.  Type HELP SET\n"
3515                  "LOCUS at the K-95> prompt for further info.  Use the\n"
3516 #ifdef KUI
3517                   "Actions menu or SET LOCUS command to disable automatic\n"
3518                   "Locus switching or to disable these queries.",
3519 #else /* KUI */
3520                   "SET LOCUS command to disable automatic locus switching\n"
3521                   "or to disable these queries.",
3522 #endif /* KUI */
3523                   NULL);
3524         if (uq_ok(locmsg,"OK to switch Locus?",3,NULL,1)) {
3525             locus = x;
3526 #ifdef KUI
3527             KuiSetProperty(KUI_LOCUS,x,0);
3528 #endif /* KUI */
3529             return;
3530         }
3531     } else {
3532 #endif /* OS2 */
3533         if (isauto && msgflg && !quitting)
3534           printf("Switching LOCUS for file-management commands to %s %s.\n",
3535                  x ? "LOCAL" : "REMOTE",
3536                  "(HELP LOCUS for info)"
3537                  );
3538         locus = x;
3539 #ifdef OS2
3540 #ifdef KUI
3541         KuiSetProperty(KUI_LOCUS,x,0);
3542 #endif /* KUI */
3543     }
3544 #endif /* OS2 */
3545 }
3546
3547 VOID
3548 setautolocus(x) int x; {
3549     autolocus = x;
3550 #ifdef KUI
3551     KuiSetProperty(KUI_AUTO_LOCUS,x,0);
3552 #endif /* KUI */
3553 }
3554 #endif /* LOCUS */
3555
3556 int
3557 settypopts() {                          /* Set TYPE option defaults */
3558     int xp = -1;
3559     int c, getval;
3560     while (1) {
3561         if ((y = cmswi(typetab,ntypetab,"Switch","",xxstring)) < 0) {
3562             if (y == -3)
3563               break;
3564             else
3565               return(y);
3566         }
3567         c = cmgbrk();
3568         if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
3569             printf("?This switch does not take an argument\n");
3570             return(-9);
3571         }
3572         switch (y) {
3573           case TYP_NOP: xp = 0; break;
3574           case TYP_PAG: xp = 1; break;
3575           case TYP_WID:
3576             if (getval)
3577               if ((x = cmnum("Column at which to truncate",
3578                              ckitoa(cmd_cols),10,&y,xxstring)) < 0)
3579                 return(x);
3580             typ_wid = y;
3581             break;
3582
3583           default:
3584             printf("?Sorry, this option can not be set\n");
3585             return(-9);
3586         }
3587     }
3588     if ((x = cmcfm()) < 0)              /* Get confirmation */
3589       return(x);
3590     if (xp > -1) typ_page = xp;         /* Confirmed, save defaults */
3591     return(success = 1);
3592 }
3593
3594 /* Forward declarations of functions local to this module */
3595
3596 #ifdef UNIX
3597 _PROTOTYP (int douchmod, ( void ) );
3598 #endif /* UNIX */
3599 #ifdef CKPURGE
3600 _PROTOTYP (int dopurge,  ( void ) );
3601 #endif /* CKPURGE */
3602 #ifndef NOSPL
3603 _PROTOTYP (int doundef,  ( int  ) );
3604 _PROTOTYP (int doask,    ( int  ) );
3605 _PROTOTYP (int dodef,    ( int  ) );
3606 _PROTOTYP (int doelse,   ( void ) );
3607 _PROTOTYP (int dofor,    ( void ) );
3608 #endif /* NOSPL  */
3609 #ifndef NODIAL
3610 _PROTOTYP (int dodial,   ( int  ) );
3611 #endif /* NODIAL */
3612 _PROTOTYP (int dodel,    ( void ) );
3613 _PROTOTYP (int dopaus,   ( int  ) );
3614 #ifndef NOPUSH
3615 #ifdef TCPSOCKET
3616 _PROTOTYP (int doping,   ( void ) );
3617 _PROTOTYP (int doftp,    ( void ) );
3618 #endif /* TCPSOCKET */
3619 #endif /* NOPUSH */
3620 #ifndef NORENAME
3621 #ifndef NOFRILLS
3622 _PROTOTYP (int dorenam,  ( void ) );
3623 #endif /* NOFRILLS */
3624 #endif /* NORENAME */
3625 #ifdef ZCOPY
3626 _PROTOTYP (int docopy,   ( void ) );
3627 #endif /* ZCOPY */
3628 #ifdef NT
3629 _PROTOTYP (int dolink,   ( void ));
3630 #endif /* NT */
3631 #ifdef CK_REXX
3632 _PROTOTYP (int dorexx,   ( void ) );
3633 #endif /* CK_REXX */
3634
3635 #ifdef TNCODE
3636 static struct keytab telcmd[] = {
3637     { "abort", TN_ABORT, CM_INV },      /* Emotionally toned - don't show */
3638     { "ao",    TN_AO,    0 },
3639     { "ayt",   TN_AYT,   0 },
3640     { "break", BREAK,    0 },
3641     { "cancel",TN_ABORT, 0 },
3642     { "dmark", TN_DM,    0 },
3643     { "do",    DO,       0 },
3644     { "dont",  DONT,     0 },
3645     { "ec",    TN_EC,    0 },
3646     { "el",    TN_EL,    0 },
3647     { "eof",   TN_EOF,   0 },
3648     { "eor",   TN_EOR,   0 },
3649 #ifdef CK_KERBEROS
3650 #ifdef KRB5
3651 #define TN_FWD 1
3652     { "forward", TN_FWD, CM_INV },
3653 #endif /* KRB5 */
3654 #endif /* CK_KERBEROS */
3655     { "ga",    TN_GA,    0 },
3656     { "ip",    TN_IP,    0 },
3657     { "nop",   TN_NOP,   0 },
3658     { "sak",   TN_SAK,   CM_INV },
3659     { "sb",    SB,       0 },
3660     { "se",    SE,       0 },
3661     { "susp",  TN_SUSP,  0 },
3662     { "will",  WILL,     0 },
3663     { "wont",  WONT,     0 }
3664 };
3665 static int ntelcmd = (sizeof(telcmd) / sizeof(struct keytab));
3666
3667 static struct keytab tnopts[] = {
3668 #ifdef CK_AUTHENTICATION
3669     { "auth",   TELOPT_AUTHENTICATION,   0 },
3670 #else
3671     { "auth",   TELOPT_AUTHENTICATION,   CM_INV },
3672 #endif /* CK_AUTHENTICATION */
3673     { "binary", TELOPT_BINARY, 0 },
3674 #ifdef TN_COMPORT
3675     { "c",      TELOPT_COMPORT, CM_INV|CM_ABR},
3676     { "co",     TELOPT_COMPORT, CM_INV|CM_ABR},
3677     { "com",    TELOPT_COMPORT, CM_INV|CM_ABR},
3678     { "com-port-control", TELOPT_COMPORT, 0 },
3679     { "comport-control", TELOPT_COMPORT, CM_INV},
3680 #else  /* TN_COMPORT */
3681     { "com-port-control", TELOPT_COMPORT, CM_INV },
3682     { "comport-control", TELOPT_COMPORT, CM_INV},
3683 #endif /* TN_COMPORT */
3684     { "echo", TELOPT_ECHO, 0 },
3685 #ifdef CK_ENCRYPTION
3686     { "encrypt", TELOPT_ENCRYPTION, 0 },
3687 #else
3688     { "encrypt", TELOPT_ENCRYPTION, CM_INV },
3689 #endif /* CK_ENCRYPTION */
3690 #ifdef CK_FORWARD_X
3691     { "forward-x", TELOPT_FORWARD_X, 0 },
3692 #else
3693     { "forward-x", TELOPT_FORWARD_X, CM_INV },
3694 #endif /* CK_FORWARD_X */
3695 #ifdef IKS_OPTION
3696     { "kermit", TELOPT_KERMIT, 0 },
3697 #else
3698     { "kermit", TELOPT_KERMIT, CM_INV },
3699 #endif /* IKS_OPTION */
3700     { "lflow",  TELOPT_LFLOW, CM_INV },
3701     { "logout", TELOPT_LOGOUT, CM_INV },
3702 #ifdef CK_NAWS
3703     { "naws", TELOPT_NAWS, 0 },
3704 #else
3705     { "naws", TELOPT_NAWS, CM_INV },
3706 #endif /* CK_NAWS */
3707 #ifdef CK_ENVIRONMENT
3708     { "new-environment", TELOPT_NEWENVIRON,  0 },
3709 #else
3710     { "new-environment", TELOPT_NEWENVIRON,  CM_INV },
3711 #endif /* CK_ENVIRONMENT */
3712     { "pragma-heartbeat",TELOPT_PRAGMA_HEARTBEAT,  CM_INV },
3713     { "pragma-logon",    TELOPT_PRAGMA_LOGON,  CM_INV },
3714     { "pragma-sspi",     TELOPT_SSPI_LOGON,  CM_INV },
3715     { "sak",   TELOPT_IBM_SAK, CM_INV },
3716 #ifdef CK_SNDLOC
3717     { "send-location",   TELOPT_SNDLOC,  0 },
3718 #else
3719     { "send-location",   TELOPT_SNDLOC,  CM_INV },
3720 #endif /* CK_SNDLOC */
3721     { "sga", TELOPT_SGA, 0 },
3722 #ifdef CK_SSL
3723     { "start-tls",       TELOPT_START_TLS,  0 },
3724 #else
3725     { "start-tls",       TELOPT_START_TLS,  CM_INV },
3726 #endif /* CK_SSL */
3727     { "ttype", TELOPT_TTYPE, 0 },
3728 #ifdef CK_ENVIRONMENT
3729     { "xdisplay-location", TELOPT_XDISPLOC, 0 },
3730 #else
3731     { "xdisplay-location", TELOPT_XDISPLOC, CM_INV },
3732 #endif /* CK_ENVIRONMENT */
3733     { "", 0, 0 }
3734 };
3735 static int ntnopts = (sizeof(tnopts) / sizeof(struct keytab)) - 1;
3736
3737 static struct keytab tnsbopts[] = {
3738 #ifdef CK_NAWS
3739     { "naws", TELOPT_NAWS, 0 },
3740 #endif /* CK_NAWS */
3741     { "", 0, 0 }
3742 };
3743 static int ntnsbopts = (sizeof(tnsbopts) / sizeof(struct keytab)) - 1;
3744 #endif /* TNCODE */
3745
3746 #ifdef TCPSOCKET
3747 #ifndef NOPUSH
3748 #ifdef SYSFTP
3749 int
3750 doftp() {                               /* (External) FTP command */
3751     char *p, *f;                        /* (See doxftp() for internal one) */
3752     int x;
3753
3754     if (network)                        /* If we have a current connection */
3755       ckstrncpy(line,ttname,LINBUFSIZ); /* get the host name */
3756     else *line = '\0';                  /* as default host */
3757     for (p = line; *p; p++)             /* Remove ":service" from end. */
3758       if (*p == ':') { *p = '\0'; break; }
3759     if ((x = cmtxt("IP host name or number", line, &s, xxstring)) < 0)
3760       return(x);
3761     if (nopush) {
3762         printf("?Sorry, FTP command disabled\n");
3763         return(success = 0);
3764     }
3765 /* Construct FTP command */
3766 #ifdef VMS
3767 #ifdef MULTINET                         /* TGV MultiNet */
3768     ckmakmsg(line,LINBUFSIZ,"multinet ftp ",s,NULL,NULL);
3769 #else
3770     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3771 #endif /* MULTINET */
3772 #else                                   /* Not VMS */
3773 #ifdef OS2ORUNIX
3774 #ifndef NOFTP
3775     f = ftpapp;
3776     if (!f) f = "";
3777     if (!f[0]) f = "ftp";
3778     ckmakmsg(line,LINBUFSIZ,f," ",s,NULL);
3779 #ifdef OS2
3780     p = line + strlen(ftpapp);
3781     while (p != line) {
3782         if (*p == '/') *p = '\\';
3783         p--;
3784     }
3785 #endif /* OS2 */
3786 #else /* NOFTP */
3787     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3788 #endif /* NOFTP */
3789 #else /* OS2ORUNIX */
3790     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3791 #endif /* OS2ORUNIX */
3792 #endif /* VMS */
3793     conres();                           /* Make console normal  */
3794 #ifdef DEC_TCPIP
3795     printf("\n");                       /* Prevent prompt-stomping */
3796 #endif /* DEC_TCPIP */
3797     x = zshcmd(line);
3798     concb((char)escape);
3799     return(success = x);
3800 }
3801 #endif /* SYSFTP */
3802
3803 int
3804 doping() {                              /* PING command */
3805     char *p;                            /* just runs ping program */
3806     int x;
3807
3808     if (network)                        /* If we have a current connection */
3809       ckstrncpy(line,ttname,LINBUFSIZ); /* get the host name */
3810     else *line = '\0';                  /* as default host to be pinged. */
3811     for (p = line; *p; p++)             /* Remove ":service" from end. */
3812       if (*p == ':') { *p = '\0'; break; }
3813     if ((x = cmtxt("IP host name or number", line, &s, xxstring)) < 0)
3814       return(x);
3815     if (nopush) {
3816         printf("?Sorry, PING command disabled\n");
3817         return(success = 0);
3818     }
3819
3820     /* Construct PING command */
3821 #ifdef VMS
3822 #ifdef MULTINET                         /* TGV MultiNet */
3823     ckmakmsg(line,LINBUFSIZ,"multinet ping ",s," /num=1",NULL);
3824 #else
3825     ckmakmsg(line,LINBUFSIZ,"ping ",s," 56 1",NULL); /* Other VMS TCP/IP's */
3826 #endif /* MULTINET */
3827 #else                                   /* Not VMS */
3828     ckmakmsg(line,LINBUFSIZ,"ping ",s,NULL,NULL);
3829 #endif /* VMS */
3830     conres();                           /* Make console normal  */
3831 #ifdef DEC_TCPIP
3832     printf("\n");                       /* Prevent prompt-stomping */
3833 #endif /* DEC_TCPIP */
3834     x = zshcmd(line);
3835     concb((char)escape);
3836     return(success = x);
3837 }
3838 #endif /* NOPUSH */
3839 #endif /* TCPSOCKET */
3840
3841 static VOID
3842 doend(x) int x; {
3843 #ifndef NOSPL
3844     /* Pop from all FOR/WHILE/XIF/SWITCH's */
3845     debug(F101,"doend maclvl 1","",maclvl);
3846     while ((maclvl > 0) &&
3847            (m_arg[maclvl-1][0]) &&
3848            (cmdstk[cmdlvl].src == CMD_MD) &&
3849            (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
3850             !strncmp(m_arg[maclvl-1][0],"_for",4) ||
3851             !strncmp(m_arg[maclvl-1][0],"_whi",4) ||
3852             !strncmp(m_arg[maclvl-1][0],"_swi",4))) {
3853         debug(F110,"END popping",m_arg[maclvl-1][0],0);
3854         dogta(XXPTA);                   /* Put args back */
3855         popclvl();                      /* Pop up two levels */
3856         popclvl();
3857         debug(F101,"doend maclvl 2","",maclvl);
3858     }
3859     if (maclvl > -1) {
3860         if (mrval[maclvl])              /* Free previous retval if any */
3861           free(mrval[maclvl]);
3862         mrval[maclvl] = malloc(16);     /* Room for up to 15 digits */
3863         if (mrval[maclvl])              /* Record current retval */
3864           ckmakmsg(mrval[maclvl],16,ckitoa(x),NULL,NULL,NULL);
3865     }
3866 #endif /* NOSPL */
3867     popclvl();                          /* Now pop out of macro or TAKE file */
3868 #ifndef NOSPL
3869 #ifdef DEBUG
3870     if (deblog) {
3871         debug(F101,"END maclvl 3","",maclvl);
3872         debug(F111,"END mrval[maclvl]",mrval[maclvl],maclvl);
3873         debug(F111,"END mrval[maclvl+1]",mrval[maclvl+1],maclvl+1);
3874     }
3875 #endif /* DEBUG */
3876 #endif /* NOSPL */
3877 }
3878
3879 #ifdef CKROOT
3880 int
3881 dochroot() {
3882     if ((x = cmdir("Name of new root directory","",&s,xxstring)) < 0) {
3883         if (x == -3) {
3884             printf("?Directory name required\n");
3885             return(-9);
3886         }
3887         return(x);
3888     }
3889     ckstrncpy(line,s,LINBUFSIZ);
3890     s = line;
3891     if ((x = cmcfm()) < 0) return(x);
3892     s = brstrip(s);
3893     x = zsetroot(s);
3894     if (x < 0) {
3895         char * m = NULL;
3896         switch (x) {
3897           case -1:
3898           case -2: m = "Not a directory"; break;
3899           case -3: m = "Internal error"; break;
3900           case -4: m = "Access denied"; break;
3901           case -5: m = "Off limits"; break;
3902         }
3903         if (m) printf("%s: \"%s\"\n", m, s);
3904         return(m ? -9 : -2);
3905     } else {
3906         nopush = 1;
3907         return(success = 1);
3908     }
3909 }
3910 #endif /* CKROOT */
3911
3912 #ifndef NOXFER
3913 static char * asnbuf = NULL;            /* As-name buffer pointer */
3914
3915 char sndxnam[] = { "_array_x_" };       /* (with replaceable x!) */
3916
3917 /*
3918   The new SEND command, replacing BSEND, CSEND, PSEND, etc etc.
3919   Call with cx = top-level keyword value.  Returns:
3920     < 0  On parse error.
3921     0    On other type of failure (e.g. requested operation not allowed).
3922     1    On success with sstate set to 's' so protocol will begin.
3923 */
3924
3925 /*  D O X S E N D  --  Parse SEND and related commands with switches  */
3926
3927 int
3928 doxsend(cx) int cx; {
3929     int c, i, n, wild, confirmed = 0;   /* Workers */
3930     int x, y;                           /* of the world... */
3931     int getval = 0;                     /* Whether to get switch value */
3932     extern char * snd_move;             /* Directory to move sent files to */
3933     extern char * snd_rename;           /* What to rename sent files to */
3934     extern char * filefile;             /* File containing filenames to send */
3935     extern int xfiletype;               /* Send only text (or binary) files */
3936     extern struct keytab pathtab[];     /* PATHNAMES option keywords */
3937     extern int npathtab;                /* How many of them */
3938     extern int recursive;               /* Recursive directory traversal */
3939     extern int rprintf;                 /* REMOTE PRINT flag */
3940     extern int fdispla;                 /* TRANSFER DISPLAY setting */
3941     extern int skipbup;                 /* Skip backup files when sending */
3942     struct stringint pv[SND_MAX+1];     /* Temporary array for switch values */
3943     struct FDB sf, sw, fl, cm;          /* FDBs for each parse function */
3944     int mlist = 0;                      /* Flag for MSEND or MMOVE */
3945     char * m;                           /* For making help messages */
3946     extern struct keytab protos[];      /* File transfer protocols */
3947     extern int xfrxla, g_xfrxla, nprotos;
3948     extern char sndbefore[], sndafter[], *sndexcept[]; /* Selection criteria */
3949     extern char sndnbefore[], sndnafter[];
3950     extern CK_OFF_T sndsmaller, sndlarger, calibrate;
3951 #ifndef NOSPL
3952     int range[2];                       /* Array range */
3953     char ** ap = NULL;                  /* Array pointer */
3954     int arrayx = -1;                    /* Array index */
3955 #endif /* NOSPL */
3956
3957 #ifdef NEWFTP
3958     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
3959         if (cx == XXMAI) {
3960             printf("?Sorry, No MAIL with FTP\n");
3961             return(-9);
3962         }
3963         return(doftpput(cx,0));
3964     }
3965 #endif /* NEWFTP */
3966
3967     for (i = 0; i <= SND_MAX; i++) {    /* Initialize switch values */
3968         pv[i].sval = NULL;              /* to null pointers */
3969         pv[i].ival = -1;                /* and -1 int values */
3970         pv[i].wval = (CK_OFF_T)-1;      /* and -1 wide values */
3971     }
3972 #ifndef NOSPL
3973     range[0] = -1;
3974     range[1] = -1;
3975     sndxin = -1;                        /* Array index */
3976 #endif /* NOSPL */
3977     sndarray = NULL;                    /* Array pointer */
3978
3979 #ifdef UNIXOROSK
3980     g_matchdot = matchdot;              /* Match dot files */
3981 #endif /* UNIXOROSK */
3982     g_recursive = recursive;            /* Recursive sending */
3983     recursive = 0;                      /* Save global value, set local */
3984     debug(F101,"xsend entry fncnv","",fncnv);
3985
3986     /* Preset switch values based on top-level command that called us */
3987
3988     switch (cx) {
3989       case XXMSE:                       /* MSEND */
3990         mlist = 1; break;
3991       case XXCSEN:                      /* CSEND */
3992         pv[SND_CMD].ival = 1; break;
3993       case XXMMOVE:                     /* MMOVE */
3994         mlist = 1;
3995       case XXMOVE:                      /* MOVE */
3996         pv[SND_DEL].ival = 1; break;
3997       case XXRSEN:                      /* RESEND */
3998         pv[SND_BIN].ival = 1;           /* Implies /BINARY */
3999         pv[SND_RES].ival = 1; break;
4000       case XXMAI:                       /* MAIL */
4001         pv[SND_MAI].ival = 1; break;
4002     }
4003
4004     /* Set up chained parse functions... */
4005
4006     cmfdbi(&sw,                         /* First FDB - command switches */
4007            _CMKEY,                      /* fcode */
4008            "Filename, or switch",       /* hlpmsg */
4009            "",                          /* default */
4010            "",                          /* addtl string data */
4011 #ifdef NOMSEND
4012            nsndtab,                     /* addtl numeric data 1: tbl size */
4013 #else
4014            mlist ? nmsndtab : nsndtab,  /* addtl numeric data 1: tbl size */
4015 #endif /* NOMSEND */
4016            4,                           /* addtl numeric data 2: 4 = cmswi */
4017            xxstring,                    /* Processing function */
4018 #ifdef NOMSEND
4019            sndtab,                      /* Keyword table */
4020 #else
4021            mlist ? msndtab : sndtab,
4022 #endif /* NOMSEND */
4023            &sf                          /* Pointer to next FDB */
4024            );
4025     cmfdbi(&sf,                         /* 2nd FDB - file to send */
4026            _CMIFI,                      /* fcode */
4027            "File(s) to send",           /* hlpmsg */
4028            "",                          /* default */
4029            "",                          /* addtl string data */
4030            nolinks,                     /* addtl numeric data 1 */
4031            0,                           /* addtl numeric data 2 */
4032            xxstring,
4033            NULL,
4034            mlist ? &cm : &fl
4035            );
4036     cmfdbi(&fl,                         /* 3rd FDB - command to send from */
4037            _CMFLD,                      /* fcode */
4038            "Command",                   /* hlpmsg */
4039            "",                          /* default */
4040            "",                          /* addtl string data */
4041            0,                           /* addtl numeric data 1 */
4042            0,                           /* addtl numeric data 2 */
4043            xxstring,
4044            NULL,
4045            &cm
4046            );
4047     cmfdbi(&cm,                         /* 4th FDB - Confirmation */
4048            _CMCFM,                      /* fcode */
4049            "",                          /* hlpmsg */
4050            "",                          /* default */
4051            "",                          /* addtl string data */
4052            0,                           /* addtl numeric data 1 */
4053            0,                           /* addtl numeric data 2 */
4054            NULL,
4055            NULL,
4056            NULL
4057            );
4058
4059     while (1) {                         /* Parse 0 or more switches */
4060         x = cmfdb(&sw);                 /* Parse something */
4061         debug(F101,"xsend cmfdb","",x);
4062         if (x < 0)                      /* Error */
4063           goto xsendx;                  /* or reparse needed */
4064         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
4065           break;
4066 /*
4067   They gave a switch, but let's see how they terminated it.
4068   If they ended it with : or =, then we must parse a value.
4069   If they ended it with anything else, then we must NOT parse a value.
4070 */
4071         c = cmgbrk();                   /* Get break character */
4072         getval = (c == ':' || c == '='); /* to see how they ended the switch */
4073         if (getval && !(cmresult.kflags & CM_ARG)) {
4074             printf("?This switch does not take arguments\n");
4075             x = -9;
4076             goto xsendx;
4077         }
4078         if (!getval && (cmgkwflgs() & CM_ARG)) {
4079             printf("?This switch requires an argument\n");
4080             x = -9;
4081             goto xsendx;
4082         }
4083         n = cmresult.nresult;           /* Numeric result = switch value */
4084         debug(F101,"xsend switch","",n);
4085
4086         switch (n) {                    /* Process the switch */
4087           case SND_CMD:                 /* These take no args */
4088             if (nopush) {
4089                 printf("?Sorry, system command access is disabled\n");
4090                 x = -9;
4091                 goto xsendx;
4092             }
4093 #ifdef PIPESEND
4094             else if (sndfilter) {
4095                 printf(
4096 "?Sorry, no SEND /COMMAND or CSEND when SEND FILTER selected\n");
4097                 x = -9;
4098                 goto xsendx;
4099             }
4100 #endif /* PIPESEND */
4101             sw.hlpmsg = "Command, or switch"; /* Change help message */
4102             pv[n].ival = 1;             /* Just set the flag */
4103             pv[SND_ARR].ival = 0;
4104             break;
4105
4106           case SND_REC:                 /* /RECURSIVE */
4107             recursive = 2;              /* Set the real variable */
4108             pv[SND_PTH].ival = PATH_REL; /* Give them relative pathnames */
4109             pv[n].ival = 1;             /* Just set the flag */
4110             break;
4111
4112           case SND_RES:                 /* /RECOVER (resend) */
4113             pv[SND_ARR].ival = 0;
4114             pv[SND_BIN].ival = 1;       /* Implies /BINARY */
4115           case SND_NOB:                 /* /NOBACKUP */
4116           case SND_DEL:                 /* /DELETE */
4117           case SND_SHH:                 /* /QUIET */
4118             pv[n].ival = 1;             /* Just set the flag */
4119             break;
4120
4121 #ifdef UNIXOROSK
4122 /* Like recursive, these are set immediately because they affect cmifi() */
4123           case SND_DOT:                 /* /DOTFILES */
4124             matchdot = 1;
4125             break;
4126           case SND_NOD:                 /* /NODOTFILES */
4127             matchdot = 0;
4128             break;
4129 #endif /* UNIXOROSK */
4130
4131           /* File transfer modes - each undoes the others */
4132
4133           case SND_BIN:                 /* Binary */
4134           case SND_TXT:                 /* Text */
4135           case SND_IMG:                 /* Image */
4136           case SND_LBL:                 /* Labeled */
4137             pv[SND_BIN].ival = 0;
4138             pv[SND_TXT].ival = 0;
4139             pv[SND_IMG].ival = 0;
4140             pv[SND_LBL].ival = 0;
4141             pv[n].ival = 1;
4142             break;
4143
4144 #ifdef CKSYMLINK
4145           case SND_LNK:
4146           case SND_NLK:
4147             nolinks = (n == SND_NLK) ? 2 : 0;
4148             cmfdbi(&sf,                 /* Redo cmifi() */
4149                    _CMIFI,              /* fcode */
4150                    "File(s) to send",   /* hlpmsg */
4151                    "",                  /* default */
4152                    "",                  /* addtl string data */
4153                    nolinks,             /* addtl numeric data 1 */
4154                    0,                   /* addtl numeric data 2 */
4155                    xxstring,
4156                    NULL,
4157                    mlist ? &cm : &fl
4158                    );
4159             break;
4160 #endif /* CKSYMLINK */
4161
4162           case SND_EXC:                 /* Excludes */
4163             if (!getval) break;
4164             if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
4165                 if (x == -3) {
4166                     printf("?Pattern required\n");
4167                     x = -9;
4168                 }
4169                 goto xsendx;
4170             }
4171             if (pv[n].sval) free(pv[n].sval);
4172             y = strlen(s);
4173             if (y > 256) {
4174                 printf("?Pattern too long - 256 max\n");
4175                 x = -9;
4176                 goto xsendx;
4177             }
4178             pv[n].sval = malloc(y+1);
4179             if (pv[n].sval) {
4180                 strcpy(pv[n].sval,s);   /* safe */
4181                 pv[n].ival = 1;
4182             }
4183             break;
4184
4185           case SND_MOV:                 /* MOVE after */
4186           case SND_REN:                 /* RENAME after */
4187             if (!getval) break;
4188             if ((x = cmfld(n == SND_MOV ?
4189            "device and/or directory for source file after sending" :
4190            "new name for source file after sending",
4191                            "",
4192                            &s,
4193                            n == SND_MOV ? xxstring : NULL
4194                            )) < 0) {
4195                 if (x == -3) {
4196                     printf("%s\n", n == SND_MOV ?
4197                            "?Destination required" :
4198                            "?New name required"
4199                            );
4200                     x = -9;
4201                 }
4202                 goto xsendx;
4203             }
4204             if (pv[n].sval) free(pv[n].sval);
4205             s = brstrip(s);
4206             y = strlen(s);
4207             if (y > 0) {
4208                 pv[n].sval = malloc(y+1);
4209                 if (pv[n].sval) {
4210                     strcpy(pv[n].sval,s); /* safe */
4211                     pv[n].ival = 1;
4212                 }
4213             }
4214             break;
4215
4216           case SND_SMA:                 /* Smaller / larger than */
4217           case SND_LAR: {
4218               CK_OFF_T w;
4219               if (!getval) break;
4220               if ((x = cmnumw("Size in bytes","0",10,&w,xxstring)) < 0)
4221                 goto xsendx;
4222               pv[n].wval = w;
4223               break;
4224           }
4225           case SND_AFT:                 /* Send /AFTER:date-time */
4226           case SND_BEF:                 /* Send /BEFORE:date-time */
4227           case SND_NAF:                 /* Send /NOT-AFTER:date-time */
4228           case SND_NBE:                 /* Send /NOT-BEFORE:date-time */
4229             if (!getval) break;
4230             if ((x = cmdate("File date-time","",&s,0,xxstring)) < 0) {
4231                 if (x == -3) {
4232                     printf("?Date-time required\n");
4233                     x = -9;
4234                 }
4235                 goto xsendx;
4236             }
4237             if (pv[n].sval) free(pv[n].sval);
4238             pv[n].sval = malloc((int)strlen(s)+1);
4239             if (pv[n].sval) {
4240                 strcpy(pv[n].sval,s);   /* safe */
4241                 pv[n].ival = 1;
4242             }
4243             break;
4244
4245           case SND_MAI:                 /* Send as mail (= MAIL) */
4246 #ifdef IKSD
4247             if (inserver && !ENABLED(en_mai)) {
4248                 printf("?Sorry, sending files as mail is disabled\n");
4249                 return(-9);
4250             }
4251 #endif /* IKSD */
4252             pv[n].ival = 1;
4253             if (!getval) break;
4254             if ((x = cmfld("e-mail address","",&s,xxstring)) < 0) {
4255                 if (x == -3) {
4256                     printf("?address required\n");
4257                     x = -9;
4258                 }
4259                 goto xsendx;
4260             }
4261             s = brstrip(s);
4262             if (pv[n].sval) free(pv[n].sval);
4263             pv[n].sval = malloc((int)strlen(s)+1);
4264             if (pv[n].sval)
4265               strcpy(pv[n].sval,s);     /* safe */
4266             break;
4267
4268           case SND_PRI:                 /* Send to be printed (REMOTE PRINT) */
4269 #ifdef IKSD
4270             if (inserver && !ENABLED(en_mai)) {
4271                 printf("?Sorry, sending files for printing is disabled\n");
4272                 return(-9);
4273             }
4274 #endif /* IKSD */
4275             pv[n].ival = 1;
4276             if (!getval) break;
4277             if ((x = cmfld("Print options","",&s,xxstring)) < 0)
4278               if (x != -3) goto xsendx;
4279             s = brstrip(s);
4280             if (pv[n].sval) free(pv[n].sval);
4281             pv[n].sval = malloc((int)strlen(s)+1);
4282             if (pv[n].sval)
4283               strcpy(pv[n].sval,s);     /* safe */
4284             break;
4285
4286           case SND_ASN:                 /* As-name */
4287             debug(F101,"xsend /as-name getval","",getval);
4288             if (!getval) break;
4289             if ((x = cmfld("Name to send under","",&s,NULL)) < 0) {
4290                 if (x == -3) {
4291                     printf("?name required\n");
4292                     x = -9;
4293                 }
4294                 goto xsendx;
4295             }
4296             s = brstrip(s);
4297             if ((y = strlen(s)) > 0) {
4298                 if (pv[n].sval) free(pv[n].sval);
4299                 pv[n].sval = malloc(y+1);
4300                 if (pv[n].sval) {
4301                     strcpy(pv[n].sval,s); /* safe */
4302                     pv[n].ival = 1;
4303                 }
4304             }
4305             break;
4306
4307           case SND_STA: {               /* Starting position (= PSEND) */
4308               CK_OFF_T w;
4309               if (!getval) break;
4310               if ((x = cmnumw("0-based position","0",10,&w,xxstring)) < 0)
4311                 goto xsendx;
4312               pv[n].wval = w;
4313               break;
4314           }
4315           case SND_PRO:                 /* Protocol to use */
4316             if (!getval) break;
4317             if ((x = cmkey(protos,nprotos,"File-transfer protocol","",
4318                            xxstring)) < 0) {
4319                 if (x == -3) {
4320                     printf("?name of protocol required\n");
4321                     x = -9;
4322                 }
4323                 goto xsendx;
4324             }
4325             pv[n].ival = x;
4326             break;
4327
4328 #ifdef PIPESEND
4329           case SND_FLT:                 /* Filter */
4330             debug(F101,"xsend /filter getval","",getval);
4331             if (!getval) break;
4332             if ((x = cmfld("Filter program to send through","",&s,NULL)) < 0) {
4333                 if (x == -3)
4334                   s = "";
4335                 else
4336                   goto xsendx;
4337             }
4338             if (*s) s = brstrip(s);
4339             y = strlen(s);
4340             for (x = 0; x < y; x++) {   /* Make sure they included "\v(...)" */
4341                 if (s[x] != '\\') continue;
4342                 if (s[x+1] == 'v') break;
4343             }
4344             if (x == y) {
4345                 printf(
4346                 "?Filter must contain a replacement variable for filename.\n"
4347                        );
4348                 x = -9;
4349                 goto xsendx;
4350             }
4351             pv[n].ival = 1;
4352             if (pv[n].sval) {
4353                 free(pv[n].sval);
4354                 pv[n].sval = NULL;
4355             }
4356             if ((y = strlen(s)) > 0) {
4357                 if ((pv[n].sval = malloc(y+1)))
4358                   strcpy(pv[n].sval,s); /* safe */
4359             }
4360             break;
4361 #endif /* PIPESEND */
4362
4363           case SND_PTH:                 /* Pathnames */
4364             if (!getval) {
4365                 pv[n].ival = PATH_REL;
4366                 break;
4367             }
4368             if ((x = cmkey(pathtab,npathtab,"","absolute",xxstring)) < 0)
4369               goto xsendx;
4370             pv[n].ival = x;
4371             break;
4372
4373           case SND_NAM:                 /* Filenames */
4374             if (!getval) break;
4375             if ((x = cmkey(fntab,nfntab,"","converted",xxstring)) < 0)
4376               goto xsendx;
4377             debug(F101,"xsend /filenames","",x);
4378             pv[n].ival = x;
4379             break;
4380
4381 #ifdef CALIBRATE
4382           case SND_CAL: {               /* /CALIBRATE */
4383               CK_OFF_T w;
4384               if (getval) {
4385                   if ((x = cmnumw("number of Kbytes to send",
4386                                   "1024",10,&w,xxstring)) < 0)
4387                     goto xsendx;
4388               } else
4389                 w = (CK_OFF_T)1024;
4390               pv[n].wval = w;
4391               pv[SND_ARR].ival = 0;
4392               break;
4393           }
4394 #endif /* CALIBRATE */
4395
4396           case SND_FIL:                 /* Name of file containing filnames */
4397             if (!getval) break;
4398             if ((x = cmifi("Name of file containing list of filenames",
4399                                "",&s,&y,xxstring)) < 0) {
4400                 if (x == -3) {
4401                     printf("?Filename required\n");
4402                     x = -9;
4403                 }
4404                 goto xsendx;
4405             } else if (y) {
4406                 printf("?Wildcards not allowed\n");
4407                 x = -9;
4408                 goto xsendx;
4409             }
4410             if (pv[n].sval)
4411               free(pv[n].sval);
4412             if (s) if (*s) {
4413                 if ((pv[n].sval = malloc((int)strlen(s)+1))) {
4414                     strcpy(pv[n].sval,s);
4415                     pv[n].ival = 1;
4416                     pv[SND_ARR].ival = 0;
4417                 }
4418             }
4419             break;
4420
4421 #ifndef NOSPL
4422           case SND_ARR:                 /* SEND /ARRAY: */
4423             if (!getval) break;
4424             ap = NULL;
4425             if ((x = cmfld("Array name (a single letter will do)",
4426                            "",
4427                            &s,
4428                            NULL
4429                            )) < 0) {
4430                 if (x == -3)
4431                   break;
4432                 else
4433                   return(x);
4434             }
4435             if ((x = arraybounds(s,&(range[0]),&(range[1]))) < 0) {
4436                 printf("?Bad array: %s\n",s);
4437                 return(-9);
4438             }
4439             if (!(ap = a_ptr[x])) {
4440                 printf("?No such array: %s\n",s);
4441                 return(-9);
4442             }
4443             pv[n].ival = 1;
4444             pv[SND_CMD].ival = 0;       /* Undo any conflicting ones... */
4445             pv[SND_RES].ival = 0;
4446             pv[SND_CAL].ival = 0;
4447             pv[SND_FIL].ival = 0;
4448             arrayx = x;
4449             break;
4450 #endif /* NOSPL */
4451
4452           case SND_XPA:                 /* /TRANSPARENT */
4453             pv[n].ival = 1;
4454             break;
4455
4456           case SND_TYP:                 /* Only files of given type */
4457             if (!getval) break;
4458             if ((x = cmkey(txtbin,3,"","all",xxstring)) < 0)
4459               goto xsendx;
4460             pv[n].ival = (x == 2) ? -1 : x;
4461             break;
4462
4463           default:
4464             printf("?Unexpected switch value - %d\n",cmresult.nresult);
4465             x = -9;
4466             goto xsendx;
4467         }
4468     }
4469     debug(F101,"xsend cmresult fcode","",cmresult.fcode);
4470
4471 #ifdef COMMENT
4472     /* List switch parsing results in debug log */
4473     for (i = 0; i <= SND_MAX; i++) {
4474         ckmakmsg(line,LINBUFSIZ,"xsend switch ",ckitoa(i),NULL,NULL);
4475         debug(F111,line, pv[i].sval, pv[i].ival);
4476     }
4477 #endif /* COMMENT */
4478
4479 /* Now we have all switches, plus maybe a filename or command, or nothing */
4480
4481 #ifdef PIPESEND
4482     if (protocol != PROTO_K && pv[SND_CMD].ival > 0) {
4483         printf("?Sorry, %s works only with Kermit protocol\n",
4484                (cx == XXCSEN) ? "CSEND" : "SEND /COMMAND");
4485         x = -9;
4486         goto xsendx;
4487     }
4488     if (pv[SND_RES].ival > 0 || /* /RECOVER */
4489         pv[SND_STA].wval > 0) { /* or /STARTING */
4490         if (sndfilter || pv[SND_FLT].ival > 0) {
4491             printf("?Sorry, no /RECOVER or /START if SEND FILTER selected\n");
4492             x = -9;
4493             goto xsendx;
4494         }
4495     }
4496 #endif /* PIPESEND */
4497
4498     cmarg = "";
4499     cmarg2 = "";
4500     line[0] = NUL;
4501     s = line;
4502     wild = 0;
4503
4504     switch (cmresult.fcode) {           /* How did we get out of switch loop */
4505       case _CMIFI:                      /* Input filename */
4506         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
4507         if (pv[SND_ARR].ival > 0)
4508           cmarg2 = line;
4509         else
4510           wild = cmresult.nresult;      /* Wild flag */
4511         if (!recursive && !wild)
4512           nolinks = 0;
4513         break;
4514       case _CMFLD:                      /* Field */
4515         /* Only allowed with /COMMAND and /ARRAY */
4516         if (pv[SND_CMD].ival < 1 && pv[SND_ARR].ival < 1) {
4517 #ifdef CKROOT
4518             if (ckrooterr)
4519               printf("?Off limits: %s\n",cmresult.sresult);
4520             else
4521 #endif /* CKROOT */
4522               printf("?%s - \"%s\"\n",
4523                    iswild(cmresult.sresult) ?
4524                    "No files match" : "File not found",
4525                    cmresult.sresult
4526                    );
4527             x = -9;
4528             goto xsendx;
4529         }
4530         ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
4531         if (pv[SND_ARR].ival > 0)
4532           cmarg2 = line;
4533         break;
4534       case _CMCFM:                      /* Confirmation */
4535         /* s = ""; */
4536         confirmed = 1;
4537         break;
4538       default:
4539         printf("?Unexpected function code: %d\n",cmresult.fcode);
4540         x = -9;
4541         goto xsendx;
4542     }
4543     debug(F110,"xsend string",s,0);
4544     debug(F101,"xsend confirmed","",confirmed);
4545
4546     /* Save and change protocol and transfer mode */
4547     /* Global values are restored in main parse loop */
4548
4549     g_proto = protocol;                 /* Save current global protocol */
4550     g_urpsiz = urpsiz;
4551     g_spsizf = spsizf;
4552     g_spsiz = spsiz;
4553     g_spsizr = spsizr;
4554     g_spmax = spmax;
4555     g_wslotr = wslotr;
4556     g_prefixing = prefixing;
4557     g_fncact = fncact;
4558     g_fncnv = fncnv;
4559     g_fnspath = fnspath;
4560     g_fnrpath = fnrpath;
4561     g_xfrxla = xfrxla;
4562
4563     if (pv[SND_PRO].ival > -1) {        /* Change according to switch */
4564         protocol = pv[SND_PRO].ival;
4565         if (ptab[protocol].rpktlen > -1) /* copied from initproto() */
4566             urpsiz = ptab[protocol].rpktlen;
4567         if (ptab[protocol].spktflg > -1)
4568             spsizf = ptab[protocol].spktflg;
4569         if (ptab[protocol].spktlen > -1) {
4570             spsiz = ptab[protocol].spktlen;
4571             if (spsizf)
4572               spsizr = spmax = spsiz;
4573         }
4574         if (ptab[protocol].winsize > -1)
4575             wslotr = ptab[protocol].winsize;
4576         if (ptab[protocol].prefix > -1)
4577             prefixing = ptab[protocol].prefix;
4578         if (ptab[protocol].fnca > -1)
4579             fncact  = ptab[protocol].fnca;
4580         if (ptab[protocol].fncn > -1)
4581             fncnv   = ptab[protocol].fncn;
4582         if (ptab[protocol].fnsp > -1)
4583             fnspath = ptab[protocol].fnsp;
4584         if (ptab[protocol].fnrp > -1)
4585             fnrpath = ptab[protocol].fnrp;
4586     }
4587     debug(F101,"xsend protocol","",protocol);
4588
4589     if (pv[SND_NOB].ival > -1) {        /* /NOBACKUP (skip backup file) */
4590         g_skipbup = skipbup;
4591         skipbup = 1;
4592     }
4593     if (pv[SND_REC].ival > 0)           /* /RECURSIVE */
4594       recursive = 2;
4595
4596     if (pv[SND_TYP].ival > -1) {        /* /TYPE */
4597         xfiletype = pv[SND_TYP].ival;
4598         if (xfiletype == 2)
4599           xfiletype = -1;
4600     }
4601     g_binary = binary;                  /* Save global transfer mode */
4602 #ifdef PATTERNS
4603     g_patterns = patterns;              /* Save FILE PATTERNS setting */
4604 #endif /* PATTERNS */
4605     if (pv[SND_BIN].ival > 0) {         /* Change according to switch */
4606         /* If they said /BINARY they mean /BINARY */
4607         patterns = 0;                   /* So no pattern-based switching */
4608         g_xfermode = xfermode;          /* or automatic transfer mode */
4609         xfermode = XMODE_M;
4610         binary = XYFT_B;
4611         debug(F101,"doxsend /BINARY xfermode","",xfermode);
4612     } else if (pv[SND_TXT].ival > 0) {  /* Ditto for /TEXT */
4613         patterns = 0;
4614         g_xfermode = xfermode;
4615         xfermode = XMODE_M;
4616         binary = XYFT_T;
4617         debug(F101,"doxsend /TEXT xfermode","",xfermode);
4618     } else if (pv[SND_IMG].ival > 0) {
4619 #ifdef VMS
4620         binary = XYFT_I;
4621 #else
4622         binary = XYFT_B;
4623 #endif /* VMS */
4624     }
4625 #ifdef CK_LABELED
4626     else if (pv[SND_LBL].ival > 0) {
4627         binary = XYFT_L;
4628     }
4629 #endif /* CK_LABELED */
4630     debug(F101,"xsend binary","",binary);
4631
4632     if (pv[SND_XPA].ival > 0)           /* /TRANSPARENT */
4633       xfrxla = 0;                       /* Don't translate character sets */
4634
4635     /* Check for legal combinations of switches, filenames, etc */
4636
4637 #ifdef PIPESEND
4638     if (pv[SND_CMD].ival > 0) { /* COMMAND - strip any braces */
4639         debug(F110,"SEND /COMMAND before stripping",s,0);
4640         s = brstrip(s);
4641         debug(F110,"SEND /COMMAND after stripping",s,0);
4642         if (!*s) {
4643             printf("?Sorry, a command to send from is required\n");
4644             x = -9;
4645             goto xsendx;
4646         }
4647         cmarg = s;
4648     }
4649 #endif /* PIPESEND */
4650
4651 /* Set up /MOVE and /RENAME */
4652
4653     if (pv[SND_DEL].ival > 0 &&
4654         (pv[SND_MOV].ival > 0 || pv[SND_REN].ival > 0)) {
4655         printf("?Sorry, /DELETE conflicts with /MOVE or /RENAME\n");
4656         x = -9;
4657         goto xsendx;
4658     }
4659 #ifdef CK_TMPDIR
4660     if (pv[SND_MOV].ival > 0) {
4661         int len;
4662         char * p = pv[SND_MOV].sval;
4663 #ifdef CK_LOGIN
4664         if (isguest) {
4665             printf("?Sorry, /MOVE-TO not available to guests\n");
4666             x = -9;
4667             goto xsendx;
4668         }
4669 #endif /* CK_LOGIN */
4670         len = strlen(p);
4671         if (!isdir(p)) {                /* Check directory */
4672 #ifdef CK_MKDIR
4673             char * s = NULL;
4674             s = (char *)malloc(len + 4);
4675             if (s) {
4676                 strcpy(s,p);            /* safe */
4677 #ifdef datageneral
4678                 if (s[len-1] != ':') { s[len++] = ':'; s[len] = NUL; }
4679 #else
4680                 if (s[len-1] != '/') { s[len++] = '/'; s[len] = NUL; }
4681 #endif /* datageneral */
4682                 s[len++] = 'X';
4683                 s[len] = NUL;
4684                 x = zmkdir(s);
4685                 free(s);
4686                 if (x < 0) {
4687                     printf("?Can't create \"%s\"\n",p);
4688                     x = -9;
4689                     goto xsendx;
4690                 }
4691             }
4692 #else
4693             printf("?Directory \"%s\" not found\n",p);
4694             x = -9;
4695             goto xsendx;
4696 #endif /* CK_MKDIR */
4697         }
4698         zfnqfp(p,LINBUFSIZ,tmpbuf);
4699         makestr(&snd_move,tmpbuf);
4700     }
4701 #endif /* CK_TMPDIR */
4702
4703     if (pv[SND_REN].ival > 0) {         /* /RENAME */
4704         char * p = pv[SND_REN].sval;
4705 #ifdef CK_LOGIN
4706         if (isguest) {
4707             printf("?Sorry, /RENAME-TO not available to guests\n");
4708             x = -9;
4709             goto xsendx;
4710         }
4711 #endif /* CK_LOGIN */
4712         if (!p) p = "";
4713         if (!*p) {
4714             printf("?New name required for /RENAME\n");
4715             x = -9;
4716             goto xsendx;
4717         }
4718         p = brstrip(p);
4719 #ifndef NOSPL
4720     /* If name given is wild, rename string must contain variables */
4721         if (wild) {
4722             char * s = tmpbuf;
4723             x = TMPBUFSIZ;
4724             zzstring(p,&s,&x);
4725             if (!strcmp(tmpbuf,p)) {
4726                 printf(
4727     "?/RENAME for file group must contain variables such as \\v(filename)\n"
4728                        );
4729                 x = -9;
4730                 goto xsendx;
4731             }
4732         }
4733 #endif /* NOSPL */
4734         makestr(&snd_rename,p);
4735     }
4736
4737 /* Handle /RECOVER and /START */
4738
4739 #ifdef CK_RESEND
4740     if (pv[SND_RES].ival > 0 && binary != XYFT_B && !filepeek
4741 #ifdef PATTERNS
4742         && !patterns
4743 #else
4744 #ifdef VMS
4745 /* VMS sets text/binary automatically later when it opens the file */
4746         && 0
4747 #endif /* VMS */
4748 #endif /* PATTERNS */
4749         ) {
4750         printf("?Sorry, /BINARY required\n");
4751         x = -9;
4752         goto xsendx;
4753     }
4754     if (pv[SND_STA].wval > 0) {         /* /START */
4755         if (wild) {
4756             printf("?Sorry, wildcards not permitted with /START\n");
4757             x = -9;
4758             goto xsendx;
4759         }
4760         if (sizeof(int) < 4) {
4761             printf("?Sorry, this command needs at least 32-bit integers\n");
4762             x = -9;
4763             goto xsendx;
4764         }
4765 #ifdef CK_XYZ
4766         if (protocol != PROTO_K) {
4767             printf("?Sorry, SEND /START works only with Kermit protocol\n");
4768             x = -9;
4769             goto xsendx;
4770         }
4771 #endif /* CK_XYZ */
4772     }
4773 #ifdef CK_XYZ
4774     if (pv[SND_RES].ival > 0) {
4775         if (protocol != PROTO_K && protocol != PROTO_Z) {
4776             printf(
4777     "Sorry, /RECOVER is possible only with Kermit or ZMODEM protocol\n"
4778                    );
4779             x = -9;
4780             goto xsendx;
4781         }
4782     }
4783 #endif /* CK_XYZ */
4784 #endif /* CK_RESEND */
4785
4786     if (protocol == PROTO_K) {
4787         if ((pv[SND_MAI].ival > 0 ||    /* MAIL */
4788              pv[SND_PRI].ival > 0 ||    /* PRINT */
4789              pv[SND_RES].ival > 0       /* RESEND */
4790              ) &&
4791             (!atdiso || !atcapr)) {     /* Disposition attribute off? */
4792             printf("?Sorry, ATTRIBUTE DISPOSITION must be ON\n");
4793             x = -9;
4794             goto xsendx;
4795         }
4796     }
4797
4798 #ifdef CK_XYZ
4799     if (wild && (protocol == PROTO_X || protocol == PROTO_XC)) {
4800         printf(
4801 "Sorry, you can only send one file at a time with XMODEM protocol\n"
4802                );
4803         x = -9;
4804         goto xsendx;
4805     }
4806 #endif /* CK_XYZ */
4807
4808     if (!confirmed) {                   /* CR not typed yet, get more fields */
4809         char *m;
4810         if (mlist) {                    /* MSEND or MMOVE */
4811             nfils = 0;                  /* We already have the first one */
4812 #ifndef NOMSEND
4813             msfiles[nfils++] = line;    /* Store pointer */
4814             lp = line + (int)strlen(line) + 1; /* Point past it */
4815             debug(F111,"xsend msend",msfiles[nfils-1],nfils-1);
4816             while (1) {                 /* Get more filenames */
4817                 char *p;
4818                 if ((x = cmifi("Names of files to send, separated by spaces",
4819                                "", &s,&y,xxstring)) < 0) {
4820                     if (x != -3)
4821                       goto xsendx;
4822                     if ((x = cmcfm()) < 0)
4823                       goto xsendx;
4824                     break;
4825                 }
4826                 msfiles[nfils++] = lp;  /* Got one, count it, point to it, */
4827                 p = lp;                 /* remember pointer, */
4828                 while ((*lp++ = *s++))  /* and copy it into buffer */
4829                   if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
4830                       printf("?MSEND list too long\n");
4831                       line[0] = NUL;
4832                       x = -9;
4833                       goto xsendx;
4834                   }
4835                 debug(F111,"xsend msend",msfiles[nfils-1],nfils-1);
4836                 if (nfils == 1) fspec[0] = NUL; /* Take care of \v(filespec) */
4837 #ifdef ZFNQFP
4838                 zfnqfp(p,TMPBUFSIZ,tmpbuf);
4839                 p = tmpbuf;
4840 #endif /* ZFNQFP */
4841                 if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
4842                     strcat(fspec,p);    /* safe */
4843                     strcat(fspec," ");  /* safe */
4844                 } else
4845 #ifdef COMMENT
4846                   printf("WARNING - \\v(filespec) buffer overflow\n");
4847 #else
4848                   debug(F101,"doxsend filespec buffer overflow","",0);
4849 #endif /* COMMENT */
4850             }
4851 #endif /* NOMSEND */
4852         } else {                        /* Regular SEND */
4853             char *p; int y;
4854             nfils = -1;
4855             if (pv[SND_MAI].ival > 0)
4856               m = (pv[SND_MAI].sval) ?
4857                 "e-mail address (optional)" :
4858                   "e-mail address (required)";
4859             else if (pv[SND_PRI].ival > 0)
4860               m = "printer options (optional)";
4861             else if (wild)
4862               m =
4863 "\nOptional as-name template containing replacement variables \
4864 like \\v(filename)";
4865             else
4866               m = "Optional name to send it with";
4867             if ((x = cmtxt(m,"",&p,NULL)) < 0)
4868               goto xsendx;
4869             if (!p) p = "";
4870             if (*p) {                   /* If some text was given... */
4871                 p = brstrip(p);         /* Replace /AS-NAME: value if any */
4872                 if ((y = strlen(p)) > 0) {
4873                     if (pv[SND_MAI].ival > 0) {
4874                         makestr(&pv[SND_MAI].sval, p);
4875                     } else {
4876                         if (pv[SND_ASN].sval) free(pv[SND_ASN].sval);
4877                         pv[SND_ASN].sval = malloc(y+1);
4878                         if (pv[SND_ASN].sval) {
4879                             strcpy(pv[SND_ASN].sval,p); /* safe */
4880                             pv[SND_ASN].ival = 1;
4881                         }
4882                     }
4883                 }
4884             }
4885         }
4886     }
4887     /* Set cmarg2 from as-name, however we got it. */
4888
4889     if (pv[SND_ASN].ival > 0 && pv[SND_ASN].sval && !*cmarg2) {
4890         int x;
4891         x = strlen(line);
4892         ckstrncpy(line+x+2,pv[SND_ASN].sval,LINBUFSIZ-x-1);
4893         cmarg2 = line+x+2;
4894         debug(F110,"doxsend cmarg2",cmarg2,0);
4895     }
4896
4897 #ifndef NOFRILLS
4898     if ((pv[SND_MAI].ival > 0) && (pv[SND_PRI].ival > 0)) {
4899         printf("Sorry, /MAIL and /PRINT are conflicting options\n");
4900         x = -9;
4901         goto xsendx;
4902     }
4903     n = 0;                              /* /MAIL or /PRINT? */
4904     if (pv[SND_MAI].ival > 0)
4905       n = SND_MAI;
4906     else if (pv[SND_PRI].ival > 0)
4907       n = SND_PRI;
4908     if (n) {                            /* Yes... */
4909 #ifdef DEBUG
4910         char * p;
4911         if (n == SND_MAI)
4912           p = "/MAIL";
4913         else
4914           p = "/PRINT";
4915         debug(F111,"xsend",p,n);
4916 #endif /* DEBUG */
4917 #ifdef CK_XYZ
4918         if (protocol != PROTO_K) {
4919             printf("Sorry, %s available only with Kermit protocol\n",
4920                    (n == SND_MAI) ? "/MAIL" : "/PRINT"
4921                    );
4922             x = -9;
4923             goto xsendx;
4924         }
4925 #endif /* CK_XYZ */
4926         debug(F101,"xsend print/mail wild","",wild);
4927         *optbuf = NUL;                  /* Wipe out any old options */
4928         s = pv[n].sval;                 /* mail address or print switch val */
4929         if (!s) s = "";
4930         debug(F110,"doxsend mail address or printer options",s,0);
4931         if (n == SND_MAI && !*s) {
4932             printf("?E-mail address required\n");
4933             x = -9;
4934             goto xsendx;
4935         } else if ((int)strlen(s) > 94) { /* Ensure legal size */
4936             printf("?%s too long\n",
4937                    (n == SND_MAI) ?
4938                    "E-mail address" :
4939                    "Print option string"
4940                    );
4941             x = -9;
4942             goto xsendx;
4943         }
4944         ckstrncpy(optbuf,s,OPTBUFLEN);  /* OK, copy to option buffer */
4945         cmarg = line;                   /* File to send */
4946         if (n == SND_MAI) {
4947             debug(F110,"xsend mailing",cmarg,0);
4948             debug(F110,"xsend address:",optbuf,0);
4949             rmailf = 1;
4950         } else {
4951             debug(F110,"xsend printing",cmarg,0);
4952             debug(F110,"xsend options",optbuf,0);
4953             rprintf = 1;
4954         }
4955     }
4956 #endif /* NOFRILLS */
4957
4958 #ifdef CALIBRATE
4959     if (pv[SND_CAL].wval > 0) {         /* Handle /CALIBRATE */
4960         if (confirmed) {
4961             calibrate = pv[SND_CAL].wval * (CK_OFF_T)1024;
4962             sndsrc = -9;
4963             nfils = 1;
4964             wild = 0;
4965 #ifndef NOMSEND
4966             addlist = 0;
4967 #endif /* NOMSEND */
4968             ckstrncpy(line,"CALIBRATION",LINBUFSIZ);
4969             s = cmarg = line;
4970             if (!cmarg2) cmarg2 = "";
4971             debug(F110,"doxsend cmarg2 calibrate",cmarg2,0);
4972         } else if (line[0]) {
4973             calibrate = 0;
4974             pv[SND_CAL].ival = 0;
4975             pv[SND_CAL].wval = 0;
4976         }
4977     }
4978 #endif /* CALIBRATE */
4979
4980     if (pv[SND_FIL].ival > 0) {
4981         if (confirmed && !calibrate) {
4982             if (zopeni(ZMFILE,pv[SND_FIL].sval) < 1) {
4983                 debug(F110,"xsend can't open",pv[SND_FIL].sval,0);
4984                 printf("?Failure to open %s\n",filefile);
4985                 x = -9;
4986                 goto xsendx;
4987             }
4988             makestr(&filefile,pv[SND_FIL].sval); /* Open, remember name */
4989             debug(F110,"xsend opened",filefile,0);
4990             wild = 1;
4991         }
4992     }
4993
4994     /* SEND alone... */
4995
4996 #ifndef NOSPL
4997     if (confirmed && pv[SND_ARR].ival > 0) {
4998         if (!*cmarg2) {
4999             sndxnam[7] = (char)((arrayx == 1) ? 64 : arrayx + ARRAYBASE);
5000             cmarg2 = sndxnam;
5001         }
5002         cmarg = "";
5003         goto sendend;
5004     }
5005 #endif /* NOSPL */
5006
5007     if (confirmed && !line[0] && !filefile && !calibrate) {
5008 #ifndef NOMSEND
5009         if (filehead) {                 /* OK if we have a SEND-LIST */
5010             nfils = filesinlist;
5011             sndsrc = nfils;             /* Like MSEND */
5012             addlist = 1;                /* But using a different list... */
5013             filenext = filehead;
5014             goto sendend;
5015         }
5016 #endif /* NOMSEND */
5017         printf("?Filename required but not given\n");
5018         x = -9;
5019         goto xsendx;
5020     }
5021
5022     /* Not send-list or array */
5023
5024 #ifndef NOMSEND
5025     addlist = 0;                        /* Don't use SEND-LIST. */
5026     filenext = NULL;
5027 #endif /* NOMSEND */
5028
5029     if (mlist) {                        /* MSEND or MMOVE */
5030 #ifndef NOMSEND
5031         cmlist = msfiles;               /* List of files to send */
5032         sndsrc = nfils;
5033         cmarg2 = "";
5034         sendstart = (CK_OFF_T)0;
5035 #endif /* NOMSEND */
5036 #ifdef PIPESEND
5037         pipesend = 0;
5038 #endif /* PIPESEND */
5039     } else if (filefile) {              /* File contains list of filenames */
5040         s = "";
5041         cmarg = "";
5042         cmarg2 = "";
5043         line[0] = NUL;
5044         nfils = 1;
5045         sndsrc = 1;
5046
5047     } else if (!calibrate && pv[SND_ARR].ival < 1 && pv[SND_CMD].ival < 1) {
5048
5049         nfils = sndsrc = -1;    /* Not MSEND, MMOVE, /LIST, or /ARRAY */
5050         if (                            /* or /COMMAND */
5051
5052 #ifndef NOFRILLS
5053             !rmailf && !rprintf         /* Not MAIL or PRINT */
5054 #else
5055             1
5056 #endif /* NOFRILLS */
5057             ) {
5058             CK_OFF_T y = (CK_OFF_T)1;
5059             if (!wild)
5060               y = zchki(s);
5061             if (y < (CK_OFF_T)0) {
5062                 printf("?Read access denied - \"%s\"\n", s);
5063                 x = -9;
5064                 goto xsendx;
5065             }
5066             if (s != line)              /* We might already have done this. */
5067               ckstrncpy(line,s,LINBUFSIZ); /* Copy of string just parsed. */
5068             else
5069               debug(F110,"doxsend line=s",line,0);
5070             cmarg = line;               /* File to send */
5071         }
5072         zfnqfp(cmarg,fspeclen,fspec);
5073     }
5074     if (!mlist) {                       /* For all but MSEND... */
5075 #ifdef PIPESEND
5076         if (pv[SND_CMD].ival > 0)       /* /COMMAND sets pipesend flag */
5077           pipesend = 1;
5078         debug(F101,"xsend /COMMAND pipesend","",pipesend);
5079         if (pipesend && filefile) {
5080             printf("?Invalid switch combination\n");
5081             x = -9;
5082             goto xsendx;
5083         }
5084 #endif /* PIPESEND */
5085
5086 #ifndef NOSPL
5087     /* If as-name given and filespec is wild, as-name must contain variables */
5088         debug(F111,"doxsend cmarg2 wild",cmarg2,wild);
5089         if (wild && *cmarg2) {
5090             char * s = tmpbuf;
5091             x = TMPBUFSIZ;
5092             zzstring(cmarg2,&s,&x);
5093             if (!strcmp(tmpbuf,cmarg2)) {
5094                 printf(
5095     "?As-name for file group must contain variables such as \\v(filename)\n"
5096                        );
5097                 x = -9;
5098                 goto xsendx;
5099             }
5100         }
5101 #endif /* NOSPL */
5102
5103     /* Strip braces from as-name */
5104         debug(F110,"xsend cmarg2 before stripping",cmarg2,0);
5105         cmarg2 = brstrip(cmarg2);
5106         debug(F110,"xsend filename",cmarg,0);
5107         debug(F110,"xsend as-name",cmarg2,0);
5108
5109     /* Copy as-name to a safe place */
5110
5111         if (asnbuf) {
5112             free(asnbuf);
5113             asnbuf = NULL;
5114         }
5115         if ((y = strlen(cmarg2)) > 0) {
5116             asnbuf = (char *) malloc(y + 1);
5117             if (asnbuf) {
5118                 strcpy(asnbuf,cmarg2);  /* safe */
5119                 cmarg2 = asnbuf;
5120             } else cmarg2 = "";
5121         }
5122
5123 #ifdef CK_RESEND
5124         debug(F111,"xsend pv[SND_STA].ival","",pv[SND_STA].ival);
5125         if (pv[SND_STA].wval > (CK_OFF_T)-1) { /* /START position */
5126             if (wild) {
5127                 printf("?/STARTING-AT may not be used with multiple files.\n");
5128                 x = -9;
5129                 goto xsendx;
5130             } else
5131               sendstart = pv[SND_STA].wval;
5132         } else
5133           sendstart = (CK_OFF_T)0;
5134         debug(F101,"xsend /STARTING","",sendstart);
5135 #endif /* CK_RESEND */
5136     }
5137
5138 sendend:                                /* Common successful exit */
5139     moving = 0;
5140     if (pv[SND_SHH].ival > 0) {         /* SEND /QUIET... */
5141         g_displa = fdispla;
5142         fdispla = 0;
5143         debug(F101,"xsend display","",fdispla);
5144     }
5145
5146 #ifndef NOSPL                           /* SEND /ARRAY... */
5147     if (pv[SND_ARR].ival > 0) {
5148         if (!ap) { x = -2; goto xsendx; } /* (shouldn't happen) */
5149         if (range[0] == -1)             /* If low end of range not specified */
5150           range[0] = 1;                 /* default to 1 */
5151         if (range[1] == -1)             /* If high not specified */
5152           range[1] = a_dim[arrayx];     /* default to size of array */
5153         if ((range[0] < 0) ||           /* Check range */
5154             (range[0] > a_dim[arrayx]) ||
5155             (range[1] < range[0]) ||
5156             (range[1] > a_dim[arrayx])) {
5157             printf("?Bad array range - [%d:%d]\n",range[0],range[1]);
5158             x = -9;
5159             goto xsendx;
5160         }
5161         sndarray = ap;                  /* Array pointer */
5162         sndxin = arrayx;                /* Array index */
5163         sndxlo = range[0];              /* Array range */
5164         sndxhi = range[1];
5165         sndxnam[7] = (char)((sndxin == 1) ? 64 : sndxin + ARRAYBASE);
5166
5167 #ifdef COMMENT
5168         printf("SENDING FROM ARRAY: &%c[]...\n", /* debugging */
5169                (sndxin == 1) ? 64 : sndxin + ARRAYBASE);
5170         printf("Lo=%d\nHi=%d\n", sndxlo, sndxhi);
5171         printf("cmarg=[%s]\ncmarg2=[%s]\n", cmarg, cmarg2);
5172         while ((x = agnbyte()) > -1) {
5173             putchar((char)x);
5174         }
5175         return(1);
5176 #endif /* COMMENT */
5177     }
5178 #endif /* NOSPL */
5179
5180     if (pv[SND_ARR].ival < 1) {         /* File selection & disposition... */
5181
5182         if (pv[SND_DEL].ival > 0)       /* /DELETE was specified */
5183           moving = 1;
5184         debug(F101,"xsend /DELETE","",moving);
5185         if (pv[SND_AFT].ival > 0)       /* Copy SEND criteria */
5186           ckstrncpy(sndafter,pv[SND_AFT].sval,19);
5187         if (pv[SND_BEF].ival > 0)
5188           ckstrncpy(sndbefore,pv[SND_BEF].sval,19);
5189         if (pv[SND_NAF].ival > 0)
5190           ckstrncpy(sndnafter,pv[SND_NAF].sval,19);
5191         if (pv[SND_NBE].ival > 0)
5192           ckstrncpy(sndnbefore,pv[SND_NBE].sval,19);
5193         if (pv[SND_EXC].ival > 0)
5194           makelist(pv[SND_EXC].sval,sndexcept,NSNDEXCEPT);
5195         if (pv[SND_SMA].wval > (CK_OFF_T)-1)
5196           sndsmaller = pv[SND_SMA].wval;
5197         if (pv[SND_LAR].wval > (CK_OFF_T)-1)
5198           sndlarger = pv[SND_LAR].wval;
5199         if (pv[SND_NAM].ival > -1) {
5200             g_fncnv = fncnv;            /* Save global value */
5201             fncnv = pv[SND_NAM].ival;
5202             debug(F101,"xsend fncnv","",fncnv);
5203         }
5204         if (pv[SND_PTH].ival > -1) {
5205             g_spath = fnspath;          /* Save global values */
5206             fnspath = pv[SND_PTH].ival;
5207 #ifndef NZLTOR
5208             if (fnspath != PATH_OFF) {
5209                 g_fncnv = fncnv;        /* Bad bad... */
5210                 fncnv = XYFN_C;
5211             }
5212 #endif /* NZLTOR */
5213             debug(F101,"xsend fnspath","",fnspath);
5214             debug(F101,"xsend fncnv","",fncnv);
5215         }
5216     }
5217
5218 #ifdef PIPESEND
5219     if (pv[SND_FLT].ival > 0) {
5220         makestr(&sndfilter,pv[SND_FLT].sval);
5221         debug(F110,"xsend /FILTER", sndfilter, 0);
5222     }
5223 #endif /* PIPESEND */
5224
5225 #ifdef CK_APC
5226 /* MOVE not allowed in APCs */
5227     if (moving &&
5228         (apcactive == APC_LOCAL || apcactive == APC_REMOTE)
5229         && !(apcstatus & APC_UNCH))
5230       return(success = 0);
5231 #endif /* CK_APC */
5232 #ifdef IKS_OPTION
5233     if (
5234 #ifdef CK_XYZ
5235         protocol == PROTO_K &&
5236 #endif /* CK_XYZ */
5237         !iks_wait(KERMIT_REQ_START,1)) {
5238         printf("?A Kermit Server is not available to process this command.\n");
5239         printf("?Start a RECEIVE command to complement this command.\n");
5240     }
5241 #endif /* IKS_OPTION */
5242
5243 #ifdef IKSD
5244 #ifdef CK_LOGIN
5245     if (moving && inserver && isguest) {
5246         printf("?File deletion not allowed for guests.\n");
5247         return(-9);
5248     }
5249 #endif /* CK_LOGIN */
5250 #endif /* IKSD */
5251
5252     sstate = 's';                       /* Set start state to SEND */
5253     sndcmd = 1;
5254 #ifdef CK_RESEND
5255     if (pv[SND_RES].ival > 0)           /* Send sendmode appropriately */
5256       sendmode = SM_RESEND;
5257     else if (pv[SND_STA].ival > 0)
5258       sendmode = SM_PSEND;
5259     else
5260 #endif /* CK_RESEND */
5261     if (mlist)
5262       sendmode = SM_MSEND;
5263     else
5264       sendmode = SM_SEND;
5265 #ifdef MAC
5266     what = W_SEND;
5267     scrcreate();
5268 #endif /* MAC */
5269     if (local && pv[SND_SHH].ival != 0) { /* If in local mode, */
5270         displa = 1;                     /* turn on file transfer display */
5271     }
5272     x = 0;
5273
5274   xsendx:                               /* Common exit, including failure */
5275     debug(F101,"doxsend sndsrc","",sndsrc);
5276     for (i = 0; i <= SND_MAX; i++) {    /* Free malloc'd memory */
5277         if (pv[i].sval)
5278           free(pv[i].sval);
5279     }
5280     return(x);
5281 }
5282 #endif /* NOXFER */
5283
5284 #ifndef NOLOCAL
5285 /*  D O X C O N N  --  CONNECT command parsing with switches */
5286
5287 #ifdef XLIMITS
5288 #define XLIMORTRIGGER
5289 #else
5290 #ifdef CK_TRIGGER
5291 #define XLIMORTRIGGER
5292 #endif /* CK_TRIGGER */
5293 #endif /*  XLIMITS */
5294
5295 #ifdef CKTIDLE
5296 int tt_idlelimit = 0;                   /* Terminal idle limit */
5297 int tt_idleact = IDLE_RET;              /* Terminal idle action */
5298 #endif /* CKTIDLE */
5299
5300 #ifdef OS2                              /* K95 only: */
5301 extern int
5302   tt_idlesnd_tmo;                       /*   Idle interval */
5303 int tt_timelimit = 0;                   /*   Time limit, 0 = none */
5304 extern char *                           /* Parse results - strings: */
5305   tt_idlesnd_str;                       /*   Idle string */
5306 #endif /* OS2 */
5307
5308 #ifdef CK_TRIGGER
5309 extern char *tt_trigger[];
5310 extern CHAR *tt_trmatch[];
5311 extern char *triggerval;
5312 static char *g_tt_trigger[TRIGGERS];
5313 #endif /* CK_TRIGGER */
5314
5315 #ifdef OS2
5316 static int g_tt_idlesnd_tmo, g_tt_timelimit; /* For saving and restoring */
5317 static int g_tt_idlelimit, g_tt_saved = 0;
5318 static char * g_tt_idlesnd_str;         /* global settings */
5319 #endif /* OS2 */
5320
5321 static struct stringint pv[CONN_MAX+1];
5322
5323 VOID
5324 resconn() {
5325     int i;
5326
5327 #ifdef OS2
5328     if ( g_tt_saved ) {
5329         tt_idlelimit   = g_tt_idlelimit;
5330         tt_idlesnd_tmo = g_tt_idlesnd_tmo;
5331         tt_timelimit   = g_tt_timelimit;
5332         tt_idlesnd_str = g_tt_idlesnd_str;
5333         g_tt_saved = 0;
5334     }
5335 #endif /* OS2 */
5336
5337 #ifdef CK_TRIGGER
5338     for (i = 0; i < TRIGGERS; i++)
5339       tt_trigger[i] = g_tt_trigger[i];
5340 #endif /* CK_TRIGGER */
5341
5342     for (i = 0; i <= CONN_MAX; i++) {   /* Free malloc'd memory */
5343         if (pv[i].sval)
5344           free(pv[i].sval);
5345         pv[i].sval = NULL;
5346     }
5347 }
5348
5349 int
5350 doxconn(cx) int cx; {
5351     int c, i, n;                        /* Workers */
5352     int x, y;
5353     int getval = 0;                     /* Whether to get switch value */
5354     int async = 0;                      /* Make an async connect */
5355     struct FDB sw, cm;                  /* FDBs for each parse function */
5356     extern FILE * tfile[];
5357     extern char * macp[];
5358
5359 #ifdef OS2
5360     g_tt_idlesnd_tmo = tt_idlesnd_tmo;  /* Save global settings */
5361     g_tt_timelimit   = tt_timelimit;
5362     g_tt_idlelimit   = tt_idlelimit;
5363     g_tt_idlesnd_str = tt_idlesnd_str;
5364     g_tt_saved = 1;
5365 #endif /* OS2 */
5366
5367 #ifdef CK_TRIGGER
5368     if (!tt_trigger[0]) {               /* First initialization */
5369         for (i = 1; i < TRIGGERS; i++)
5370           tt_trigger[i] = NULL;
5371     }
5372     for (i = 0; i < TRIGGERS; i++)
5373       g_tt_trigger[i] = tt_trigger[i];
5374     if (triggerval) {
5375         free(triggerval);
5376         triggerval = NULL;
5377     }
5378 #endif /* CK_TRIGGER */
5379
5380     for (i = 0; i <= CONN_MAX; i++) {   /* Initialize switch values */
5381         pv[i].sval = NULL;              /* to null pointers */
5382         pv[i].ival = -1;                /* and -1 int values */
5383         pv[i].wval = (CK_OFF_T)-1;
5384     }
5385     if (cx == XXCQ)                     /* CQ == CONNECT /QUIETLY */
5386       pv[CONN_NV].ival = 1;
5387
5388     /* Set up chained parse functions... */
5389
5390     cmfdbi(&sw,                         /* First FDB - command switches */
5391            _CMKEY,                      /* fcode */
5392            "Switch",                    /* hlpmsg */
5393            "",                          /* default */
5394            "",                          /* addtl string data */
5395            nconntab,                    /* addtl numeric data 1: tbl size */
5396            4,                           /* addtl numeric data 2: 4 = cmswi */
5397            xxstring,                    /* Processing function */
5398            conntab,                     /* Keyword table */
5399            &cm                          /* Pointer to next FDB */
5400            );
5401     cmfdbi(&cm,                         /* 2nd FDB - Confirmation */
5402            _CMCFM,                      /* fcode */
5403            "",                          /* hlpmsg */
5404            "",                          /* default */
5405            "",                          /* addtl string data */
5406            0,                           /* addtl numeric data 1 */
5407            0,                           /* addtl numeric data 2 */
5408            NULL,
5409            NULL,
5410            NULL
5411            );
5412
5413     while (1) {                         /* Parse 0 or more switches */
5414         x = cmfdb(&sw);                 /* Parse switch or confirmation */
5415         debug(F101,"doxconn cmfdb","",x);
5416         if (x < 0) {                    /* Error */
5417             if (x == -9 || x == -2)
5418               printf("?No switches match - \"%s\"\n",atmbuf);
5419             goto xconnx;                /* or reparse needed */
5420         }
5421         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
5422           break;
5423         c = cmgbrk();                   /* Get break character */
5424         getval = (c == ':' || c == '='); /* to see how they ended the switch */
5425         if (getval && !(cmresult.kflags & CM_ARG)) {
5426             printf("?This switch does not take arguments\n");
5427             x = -9;
5428             goto xconnx;
5429         }
5430         if (!getval && (cmgkwflgs() & CM_ARG)) {
5431             printf("?This switch requires an argument\n");
5432             return(-9);
5433         }
5434         n = cmresult.nresult;           /* Numeric result = switch value */
5435         debug(F101,"doxconn switch","",n);
5436
5437         switch (n) {                    /* Process the switch */
5438 #ifdef OS2
5439           case CONN_AS:                 /* Asynchronous */
5440             pv[CONN_AS].ival = 1;
5441             pv[CONN_SY].ival = 0;
5442             break;
5443           case CONN_SY:                 /* Synchronous */
5444             pv[CONN_SY].ival = 1;
5445             pv[CONN_AS].ival = 0;
5446             break;
5447 #endif /* OS2 */
5448           case CONN_NV:                 /* Non-verbal */
5449             pv[n].ival = 1;
5450             break;
5451 #ifdef XLIMITS
5452           case CONN_II:                 /* Idle-interval */
5453           case CONN_IL:                 /* Idle-limit */
5454           case CONN_TL:                 /* Time-limit */
5455             if (!getval) break;
5456             if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
5457               goto xconnx;
5458             pv[n].ival = y;
5459             break;
5460           case CONN_IS:                 /* Idle-string */
5461 #endif /* XLIMITS */
5462 #ifdef CK_TRIGGER
5463           case CONN_TS:                 /* Trigger-string */
5464 #endif /* CK_TRIGGER */
5465 #ifdef XLIMORTRIGGER
5466             if (!getval) break;
5467             if ((x = cmfld("String (enclose in braces if it contains spaces)",
5468                            "",&s,xxstring)) < 0) {
5469                 if (x == -3) {
5470                     printf("?String required\n");
5471                     x = -9;
5472                 }
5473                 goto xconnx;
5474             }
5475             if (n != CONN_TS)
5476               s = brstrip(s);
5477             if ((y = strlen(s)) > 0) {
5478                 if (pv[n].sval) free(pv[n].sval);
5479                 pv[n].sval = malloc(y+1);
5480                 if (pv[n].sval) {
5481                     strcpy(pv[n].sval,s); /* safe */
5482                     pv[n].ival = 1;
5483                 }
5484             }
5485             break;
5486 #endif /* XLIMORTRIGGER */
5487           default:
5488             printf("?Unexpected switch value - %d\n",cmresult.nresult);
5489             x = -9;
5490             goto xconnx;
5491         }
5492     }
5493     debug(F101,"doxconn cmresult.fcode","",cmresult.fcode);
5494     if (cmresult.fcode != _CMCFM) {
5495         printf("?Unexpected function code: %d\n",cmresult.fcode);
5496         x = -9;
5497         goto xconnx;
5498     }
5499
5500     /* Command was confirmed so we can pre-pop command level. */
5501     /* This is so CONNECT module won't think we're executing a script */
5502     /* if CONNECT was the final command in the script. */
5503
5504     if (cmdlvl > 0)
5505       prepop();
5506
5507 #ifdef OS2                              /* Make results available globally */
5508     if (pv[CONN_IL].ival > -1)          /* Idle limit */
5509       tt_idlelimit = pv[CONN_IL].ival;
5510     if (pv[CONN_II].ival > -1)          /* Idle limit */
5511       tt_idlesnd_tmo = pv[CONN_II].ival;
5512     if (pv[CONN_IS].sval)               /* Idle string */
5513       if (tt_idlesnd_str = (char *)malloc((int)strlen(pv[CONN_IS].sval)+1))
5514         strcpy(tt_idlesnd_str,pv[CONN_IS].sval); /* safe */
5515     if (pv[CONN_TL].ival > -1)          /* Session limit */
5516       tt_timelimit = pv[CONN_TL].ival;
5517     async = (pv[CONN_AS].ival > 0 ||
5518              pv[CONN_SY].ival <= 0 && cmdlvl == 0) ? 1 : 0;
5519 #endif /* OS2 */
5520
5521 #ifdef CK_TRIGGER
5522     if (pv[CONN_TS].sval)               /* Trigger strings */
5523       makelist(pv[CONN_TS].sval,tt_trigger,TRIGGERS);
5524     for (i = 0; i < TRIGGERS; i++)      /* Trigger match pointers */
5525       tt_trmatch[i] = NULL;
5526     if (triggerval) {                   /* Reset trigger value */
5527         free(triggerval);
5528         triggerval = NULL;
5529     }
5530 #endif /* CK_TRIGGER */
5531
5532 #ifdef SSHCMD
5533 /*
5534   2010/03/01...
5535   The previous connection was through the external ssh client and now, with
5536   that connection closed, the user says "connect" and expects a new connection
5537   to be made to the same host, because that's how all the other connection
5538   methods work, so (and this is quite a hack)...
5539 */
5540     if (!ckstrcmp("ssh ",ttname,4,0)) { /* Previous "host" was "ssh blah" */
5541         _PROTOTYP (int redossh, ( void ) );
5542         extern int ttyfd;
5543         if (ttyfd < 0) {                /* And connection is no longer open */
5544             int xx;
5545             xx = redossh();             /* So redo the SSH connection */
5546             if (xx < 0) return(xx);
5547             goto xconnx;
5548         }
5549     }
5550 #endif  /* SSHCMD */
5551     x = doconect((pv[CONN_NV].ival > 0) ? 1 : 0, async);
5552     {
5553         int xx;
5554         debug(F101,"doxconn doconect returns","",x);
5555         if ((xx = ttchk()) < 0) dologend();
5556         debug(F101,"doxconn ttchk returns","",xx);
5557     }
5558
5559 #ifdef CK_TRIGGER
5560     debug(F111,"doxconn doconect triggerval",triggerval,x);
5561 #endif /* CK_TRIGGER */
5562
5563   xconnx:
5564     /* Back from CONNECT -- Restore global settings */
5565
5566     if (!async)
5567       resconn();
5568
5569     success = (x > 0) ? 1 : 0;
5570     return(x);
5571 }
5572 #endif /* NOLOCAL */
5573
5574 #ifdef ADDCMD
5575 /* cx == XXADD or XXREMV */
5576 /* fc == ADD_BIN or ADD_TXT */
5577 static int
5578 doadd(cx,fc) int cx, fc; {
5579 #ifdef PATTERNS
5580     char * tmp[FTPATTERNS];
5581     char **p = NULL;
5582     int i, j, k, n = 0, x = 0, last;
5583
5584 #endif /* PATTERNS */
5585     if (cx != XXADD && cx != XXREMV) {
5586         printf("?Unexpected function code: %d\n",cx);
5587         return(-9);
5588     }
5589 #ifdef PATTERNS
5590     while (n < FTPATTERNS) {            /* Collect new patterns */
5591         tmp[n] = NULL;
5592         if ((x = cmfld("Pattern","",&s,xxstring)) < 0)
5593           break;
5594         ckstrncpy(line,s,LINBUFSIZ);
5595         s = brstrip(line);
5596         makestr(&(tmp[n++]),s);
5597     }
5598     if (x == -3)
5599       x = cmcfm();
5600     if (x < 0)
5601       goto xdoadd;
5602     p = (fc == ADD_BIN) ? binpatterns : txtpatterns; /* Which list */
5603     last = 0;
5604     for (i = 0; i < FTPATTERNS; i++) { /* Find last one in list */
5605         if (!p[i]) {
5606             last = i;
5607             break;
5608         }
5609     }
5610     if (cx == XXADD) {                  /* Adding */
5611         if (last + n > FTPATTERNS) {    /* Check if too many */
5612             printf("?Too many patterns - %d is the maximum\n", FTPATTERNS);
5613             goto xdoadd;
5614         }
5615         for (i = 0; i < n; i++) {        /* Copy in the new ones. */
5616           for (j = 0, x = 0; x == 0 && j < last ; j++ )
5617             x = !ckstrcmp(tmp[i],p[j],-1,filecase); /* match */
5618           if (x == 0)
5619             makestr(&(p[last++]),tmp[i]);
5620         }
5621         makestr(&(p[last]),NULL);       /* Null-terminate the list */
5622         x = 1;
5623         goto xdoadd;                    /* Done */
5624     } else if (cx == XXREMV) {          /* Remove something(s) */
5625         int j, k;
5626         if (last == 0)                          /* List is empty */
5627           goto xdoadd;                          /* Nothing to remove */
5628         for (i = 0; i < n; i++) {               /* i = Patterns they typed */
5629             for (j = 0; j < last; j++) {        /* j = Patterns in list */
5630                 /* Change this to ckstrcmp()... */
5631                 if (filecase)
5632                   x = !ckstrcmp(tmp[i],p[j],-1,filecase); /* match */
5633                 else
5634                   x = ckstrcmp(tmp[i],p[j],-1,0); /* Case-independent match */
5635                 if (x) {                        /* This one matches */
5636                     makestr(&(p[j]),NULL);      /* Free it */
5637                     for (k = j; k < last; k++)  /* Move the rest up */
5638                       p[k] = p[k+1];
5639                     p[k] = NULL;                /* Erase last one */
5640                     if (!p[k])
5641                       break;
5642                 }
5643             }
5644         }
5645     }
5646   xdoadd:                               /* Common exit */
5647     for (i = 0; i < n; i++)
5648       if (tmp[i])
5649         free(tmp[i]);
5650     return(x);
5651 #endif /* PATTERNS */
5652 }
5653
5654 /* ADD SEND-LIST */
5655
5656 static int
5657 addsend(cx) int cx; {
5658 #ifndef NOMSEND
5659     extern struct keytab fttab[];
5660     extern int nfttyp;
5661     struct filelist * flp;
5662     char * fmode = "";
5663     int xmode = 0;
5664     int xbinary = 0;
5665 #endif /* NOMSEND */
5666
5667 #ifdef NOMSEND
5668     printf("?Sorry, ADD/REMOVE SEND-LIST not available.\n");
5669     return(-9);
5670 #endif /* NOMSEND */
5671     if (cx == XXREMV) {
5672         printf("?Sorry, REMOVE SEND-LIST not implemented yet.\n");
5673         return(-9);
5674     }
5675 #ifndef NOMSEND
5676 #ifndef XYZ_INTERNAL
5677     if (protocol != PROTO_K) {
5678        printf("?Sorry, ADD SEND-LIST does not work with external protocols\n");
5679        return(-9);
5680     }
5681 #endif /* XYZ_INTERNAL */
5682
5683     x = cmifi("File specification to add","", &s,&y,xxstring);
5684     if (x < 0) {
5685         if (x == -3) {
5686             printf("?A file specification is required\n");
5687             return(-9);
5688         } else
5689           return(x);
5690     }
5691     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
5692     s = tmpbuf;
5693     if (filesinlist == 0)               /* Take care of \v(filespec) */
5694       fspec[0] = NUL;
5695     zfnqfp(s,LINBUFSIZ,line);
5696     s = line;
5697     if (((int)strlen(fspec) + (int)strlen(s) + 1) < fspeclen) {
5698         strcat(fspec,s);                /* safe */
5699         strcat(fspec," ");              /* safe */
5700     } else
5701       printf("WARNING - \\v(filespec) buffer overflow\n");
5702
5703
5704     xbinary = binary;
5705     if ((patterns || filepeek)          /* FILE PATTERNS or SCAN is ON */
5706 #ifdef CK_LABELED
5707         && binary != XYFT_L             /* And not if FILE TYPE LABELED */
5708 #endif /* CK_LABELED */
5709 #ifdef VMS
5710         && binary != XYFT_I             /* or FILE TYPE IMAGE */
5711 #endif /* VMS */
5712         ) {
5713         int k, x;
5714         x = -1;
5715         k = scanfile(line,&x,nscanfile);
5716         if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
5717     }
5718     fmode = gfmode(xbinary,0);
5719     if ((x = cmkey(fttab,nfttyp,
5720                    "type of file transfer", fmode, xxstring)) < 0)
5721       return(x);
5722     xmode = x;
5723
5724     cmarg2 = "";
5725     if ((x = cmfld(y ?
5726   "\nAs-name template containing replacement variables such as \\v(filename)" :
5727   "Name to send it with", "",&s,NULL)) < 0)
5728       if (x != -3)
5729         return(x);
5730 #ifndef NOSPL
5731     if (y && *s) {
5732         char * p = tmpbuf;
5733         x = TMPBUFSIZ;
5734         zzstring(s,&p,&x);
5735         if (!strcmp(tmpbuf,s)) {
5736             printf(
5737   "?As-name for file group must contain variables such as \\v(filename)\n"
5738                    );
5739             return(-9);
5740         }
5741     }
5742 #endif /* NOSPL */
5743     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
5744     cmarg2 = tmpbuf;
5745
5746     if ((x = cmcfm()) < 0)
5747       return(x);
5748     flp = (struct filelist *) malloc(sizeof(struct filelist));
5749     if (flp) {
5750         if (filetail)
5751           filetail->fl_next = flp;
5752         filetail = flp;
5753         if (!filehead)
5754           filehead = flp;
5755         x = (int) strlen(line); /* Length of filename */
5756         s = (char *) malloc(x + 1);
5757         if (s) {
5758             strcpy(s,line);             /* safe */
5759             flp->fl_name = s;
5760             flp->fl_mode = xmode;
5761             x = (int) strlen(cmarg2);   /* Length of as-name */
5762             if (x < 1) {
5763                 flp->fl_alias = NULL;
5764             } else {
5765                 s = (char *) malloc(x + 1);
5766                 if (s) {
5767                     strcpy(s,cmarg2);   /* safe */
5768                     flp->fl_alias = s;
5769                 } else {
5770                     printf("Sorry, can't allocate space for as-name");
5771                     return(-9);
5772                 }
5773             }
5774             flp->fl_next = NULL;
5775             filesinlist++;              /* Count this node */
5776             return(success = 1);        /* Finished adding this node */
5777         } else {
5778             printf("Sorry, can't allocate space for name");
5779             return(-9);
5780         }
5781     } else {
5782         printf("Sorry, can't allocate file list node");
5783         return(-9);
5784     }
5785 #endif /* NOMSEND */
5786 }
5787 #endif /* ADDCMD */
5788
5789 #ifndef NOHTTP                          /* HTTP ops... */
5790 #ifdef TCPSOCKET
5791 #define HTTP_GET 0                      /* GET */
5792 #define HTTP_PUT 1                      /* PUT */
5793 #define HTTP_POS 2                      /* POST */
5794 #define HTTP_IDX 3                      /* INDEX */
5795 #define HTTP_HED 4                      /* HEAD */
5796 #define HTTP_DEL 5                      /* DELETE */
5797 #define HTTP_CON 6                      /* CONNECT */
5798 #define HTTP_OPN 7                      /* OPEN */
5799 #define HTTP_CLS 8                      /* CLOSE */
5800
5801 static struct keytab httptab[] = {
5802     { "close",   HTTP_CLS, 0 },
5803     { "connect", HTTP_CON, 0 },
5804     { "delete",  HTTP_DEL, 0 },
5805     { "get",     HTTP_GET, 0 },
5806     { "head",    HTTP_HED, 0 },
5807     { "index",   HTTP_IDX, 0 },
5808     { "open",    HTTP_OPN, 0 },
5809     { "put",     HTTP_PUT, 0 },
5810     { "post",    HTTP_POS, 0 }
5811 };
5812 static int nhttptab = sizeof(httptab)/sizeof(struct keytab);
5813
5814 /* HTTP switches */
5815 #define HT_SW_AG 0                      /* /AGENT */
5816 #define HT_SW_HD 1                      /* /HEADER */
5817 #define HT_SW_US 2                      /* /USER */
5818 #define HT_SW_PW 3                      /* /PASSWORD */
5819 #define HT_SW_AR 4                      /* /ARRAY */
5820 #define HT_SW_TP 5                      /* /TOSCREEN */
5821
5822 static struct keytab httpswtab[] = {
5823     { "/agent",    HT_SW_AG, CM_ARG },
5824 #ifndef NOSPL
5825     { "/array",    HT_SW_AR, CM_ARG },
5826 #endif /* NOSPL */
5827     { "/header",   HT_SW_HD, CM_ARG },
5828     { "/password", HT_SW_PW, CM_ARG },
5829     { "/toscreen", HT_SW_TP, 0 },
5830     { "/user",     HT_SW_US, CM_ARG },
5831     { "", 0, 0 }
5832 };
5833 static int nhttpswtab = sizeof(httpswtab)/sizeof(struct keytab) - 1;
5834
5835 /* HTTP PUT/POST switches */
5836 #define HT_PP_MT 0                      /* /MIME-TYPE */
5837
5838 static struct keytab httpptab[] = {
5839     { "/mime-type", HT_PP_MT, CM_ARG },
5840     { "", 0, 0 }
5841 };
5842 static int nhttpptab = sizeof(httpptab)/sizeof(struct keytab) - 1;
5843
5844 #define HTTP_MAXHDR 8
5845
5846 static int
5847 xdohttp(action, lfile, rf, dfile, agent, hdr, user, pass, mime, array, type)
5848     int action;
5849     char *lfile, *rf, *dfile, *agent, *hdr, *user, *pass, *mime, array;
5850     int type;
5851 /* xdohttp */ {
5852     int i, rc = 0;
5853     char * hdrlist[HTTP_MAXHDR];
5854     char rfile[CKMAXPATH+1];
5855     extern int httpfd;
5856
5857     /* Check for a valid state to execute the command */
5858     if (inserver) {
5859         printf("?The HTTP command may not be used from the IKS\r\n");
5860     } else if (httpfd == -1) {
5861         if (http_reopen() < 0)
5862           printf("?No connection\n");
5863         else
5864           rc = 1;
5865     } else {
5866         rc = 1;
5867     }
5868
5869     /* If the command is not valid, exit with failure */
5870     if (rc == 0)
5871         return(success = 0);
5872
5873     if (action != HTTP_CON && rf[0] != '/') {
5874         rfile[0] = '/';
5875         ckstrncpy(&rfile[1],rf,CKMAXPATH);
5876     } else {
5877         ckstrncpy(rfile,rf,CKMAXPATH);
5878     }
5879     for (i = 0; i < HTTP_MAXHDR; i++)   /* Initialize header list */
5880       hdrlist[i] = NULL;
5881     makelist(hdr,hdrlist,HTTP_MAXHDR);  /* Make header list */
5882
5883 #ifdef BETADEBUG
5884     for (i = 0; i < nhttptab; i++)      /* Find action keyword */
5885       if (httptab[i].kwval == action)
5886         break;
5887     if (i == nhttptab) {                /* Shouldn't happen... */
5888         printf("?Invalid action - %d\n",action);
5889         return(0);                      /* Failure */
5890     }
5891
5892     printf("HTTP action:  %s\n",httptab[i].kwd);
5893     printf(" Agent:       %s\n",agent ? agent : "(null)");
5894
5895     if (hdrlist[1]) {
5896         printf(" Header list: 1. %s\n",hdrlist[0]);
5897         for (i = 1; i < HTTP_MAXHDR && hdrlist[i]; i++)
5898           printf("%15d. %s\n",i+1,hdrlist[i]);
5899     } else
5900       printf(" Header:      %s\n",hdrlist[0] ? hdrlist[0] : "(null)");
5901
5902     printf(" User:        %s\n",user ? user : "(null)");
5903 #ifdef COMMENT
5904     printf(" Password:    %s\n",pass ? pass : "(null)");
5905 #endif /* COMMENT */
5906
5907 #ifndef NOSPL
5908     if (array)
5909       printf(" Array:       \\%%%c[]\n", array);
5910     else
5911       printf(" Array:       (none)\n");
5912 #endif /* NOSPL */
5913
5914     if (action == HTTP_PUT || action == HTTP_POS)
5915       printf(" Mime-type:   %s\n",mime ? mime : "(null)");
5916
5917     printf(" Local file:  %s\n",lfile ? lfile : "(null)");
5918     printf(" Remote file: %s\n",rfile ? rfile : "(null)");
5919     printf(" Destination file: %s\n",dfile ? dfile : "(null)");
5920 #endif /* BETADEBUG */
5921
5922     /* The http_xxxx() functions return 0 on success, -1 on failure */
5923     switch (action) {
5924       case HTTP_CON: {
5925           extern int ttyfd;
5926           rc = http_connect(httpfd,agent,hdrlist,user,pass,array,rfile);
5927           break;
5928       }
5929       case HTTP_DEL:
5930         rc = http_delete(agent,hdrlist,user,pass,array,rfile);
5931         break;
5932       case HTTP_GET:
5933         rc = http_get(agent,hdrlist,user,pass,array,lfile,rfile,type);
5934         break;
5935       case HTTP_HED:
5936         rc = http_head(agent,hdrlist,user,pass,array,lfile,rfile,type);
5937         break;
5938       case HTTP_PUT:
5939         rc = http_put(agent,hdrlist,mime,user,pass,array,lfile,rfile,dfile,
5940                       type);
5941         break;
5942       case HTTP_POS:
5943         rc = http_post(agent,hdrlist,mime,user,pass,array,lfile,rfile,dfile,
5944                        type);
5945         break;
5946       case HTTP_IDX:
5947         rc = http_index(agent,hdrlist,user,pass,array,lfile,rfile,type);
5948         break;
5949       default:
5950         rc = -1;
5951     }
5952     return(rc == 0 ? 1 : 0);            /* Success is set by caller */
5953 }
5954 #endif /* TCPSOCKET */
5955 #endif /* NOHTTP */
5956
5957 #ifndef NOSPL                           /* ARRAY ops... */
5958 static struct keytab arraytab[] = {
5959     { "clear",     ARR_CLR, 0 },
5960     { "copy",      ARR_CPY, 0 },
5961     { "dcl",       ARR_DCL, CM_INV },
5962     { "declare",   ARR_DCL, 0 },
5963     { "destroy",   ARR_DST, CM_INV },
5964     { "equate",    ARR_EQU, CM_INV },
5965     { "link",      ARR_EQU, 0 },
5966     { "resize",    ARR_RSZ, 0 },
5967     { "set",       ARR_SET, 0 },
5968 #ifndef NOSHOW
5969     { "show",      ARR_SHO, 0 },
5970 #endif /* NOSHOW */
5971     { "sort",      ARR_SRT, 0 },
5972     { "undeclare", ARR_DST, 0 },
5973     { "", 0, 0 }
5974 };
5975 static int narraytab = sizeof(arraytab)/sizeof(struct keytab) - 1;
5976
5977 #ifdef CKLEARN
5978 static struct keytab learnswi[] = {
5979     { "/close",    2, 0 },
5980     { "/off",      0, 0 },
5981     { "/on",       1, 0 }
5982 };
5983 #endif /* CKLEARN */
5984
5985 int
5986 arrayitoa(x) int x; {                   /* Array index to array letter */
5987     if (x == 1)
5988       return(64);
5989     else if (x < 0 || x > (122 - ARRAYBASE))
5990       return(-1);
5991     else
5992       return(x + ARRAYBASE);
5993 }
5994
5995 int
5996 arrayatoi(c) int c; {                   /* Array letter to array index */
5997     if (c == 64)
5998       c = 96;
5999     if (c > 63 && c < 91)
6000       c += 32;
6001     if (c < ARRAYBASE || c > 122)
6002       return(-1);
6003     return(c - ARRAYBASE);
6004 }
6005
6006 static int                              /* Declare an array */
6007 dodcl(cx) int cx; {
6008     int i, n, v, lo, hi, rc = 0;
6009     int isdynamic = 0;
6010     char tmpbuf[64];
6011     char ** p = NULL;
6012     char tmp[64];                       /* Local temporary string buffer */
6013     if ((y = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6014         if (y == -3) {
6015             printf("?Array name required\n");
6016             return(-9);
6017         } else return(y);
6018     }
6019     ckstrncpy(line,s,LINBUFSIZ);
6020     s = line;
6021     x = arraybounds(s,&lo,&hi);         /* Check syntax and get bounds */
6022     debug(F111,"dodcl arraybounds",s,x);
6023     if (x < 0) {                        /* Error - Maybe it's a variable */
6024         char * p;                       /* whose value is an array name */
6025         int n;
6026         p = tmpbuf;
6027         n = 63;
6028         p[0] = NUL;
6029         if (s[0] == CMDQ && s[1] == '&')
6030           s++;
6031         if (zzstring(s,&p,&n) > -1) {
6032             s = tmpbuf;
6033             x = arraybounds(s,&lo,&hi);
6034             debug(F111,"dodcl arraybounds 2",s,x);
6035         }
6036         if (x < 0) {
6037             printf("?Bad array name - \"%s\"\n",s);
6038             return(-9);
6039         }
6040     }
6041     debug(F101,"dodcl hi","",hi);
6042     debug(F101,"dodcl lo","",lo);
6043     debug(F101,"dodcl lo+1","",lo+1);
6044
6045     if (lo == -1 && hi == -1) {         /* Have good array name and bounds */
6046         isdynamic = 1;
6047         n = CMDBL / 5;
6048     } else if (hi > -1) {
6049         printf("?Segment notation not allowed in array declarations\n");
6050         return(-9);
6051     } else if ((lo+1) < 0) {
6052         debug(F101,"dodcl underflow","",lo+1);
6053         printf("?Dimension underflow\n");
6054         return(-9);
6055     } else
6056       n = lo;
6057     x = arrayitoa(x);
6058     if (cx == XXUNDCL) {
6059         n = 0;
6060         v = 0;
6061         if ((y = cmcfm()) < 0)
6062           return(y);
6063     } else {
6064         p = (char **)malloc(sizeof(char **)*(n+1));
6065         if (!p) {
6066             printf("?Memory allocation error\n");
6067             return(-9);
6068         }
6069         v = 0;                          /* Highest initialized member */
6070         p[0] = NULL;                    /* Element 0 */
6071         keepallchars = 1;
6072         while (n > 0 && v < n) {        /* Parse initializers */
6073             p[v+1] = NULL;
6074             ckmakxmsg(tmp,
6075                       64,
6076                       "Initial value for \\&",
6077                       ckctoa((char)x),
6078                       "[",
6079                       ckitoa(v+1),
6080                       "]",
6081                       NULL,NULL,NULL,NULL,NULL,NULL,NULL
6082                       );
6083             
6084             rc = cmfld((char *)tmp,"",&s,xxstring); /* Get field */
6085             if (rc < 0) {               /* Error... */
6086                 if (rc == -3) {         /* Empty element */
6087                     if (cmflgs == 1)    /* because end of line? */
6088                       break;            /* Yes, done initializing */
6089                     else                /* No, it's just empty */
6090                       continue;         /* Go on to next one. */
6091                 } else {                /* Other parse error */
6092                     goto dclx;          /* Go free temp pointers */
6093                 }
6094             }
6095             rc = 1;
6096             if (v == 0 && !strcmp(s,"=")) /* Skip the = sign. */
6097               continue;
6098             s = brstrip(s);             /* Strip any braces */
6099             makestr(&(p[++v]),s);
6100         }
6101         keepallchars = 0;
6102         if ((y = cmtxt("Carriage return to confirm","",&s,NULL)) < 0)
6103           return(y);
6104         if (isdynamic)
6105           n = v;
6106     }
6107     if (dclarray((char)x,n) < 0) {      /* Declare the array */
6108         printf("?Declare failed\n");
6109         goto dclx;
6110     }
6111     for (i = 1; i <= v; i++) {          /* Add any initial values */
6112         tmp[0] = '&';
6113         ckmakmsg(&tmp[1],63,ckctoa((char)x),"[",ckitoa(i),"]");
6114         if (addmac(tmp,p[i]) < 0) {
6115             printf("Array initialization error: %s %s\n",tmp,p[i]);
6116             rc = -9;
6117             goto dclx;
6118         }
6119     }
6120   dclx:
6121     if (p) {
6122         for (i = 1; i <= v; i++)
6123           if (p[i]) free(p[i]);
6124         free((char *)p);
6125     }
6126     debug(F101,"DCL rc","",rc);
6127     return(success = rc);
6128 }
6129
6130 static int
6131 rszarray() {
6132     int i, x, y, n, lo, hi, islink = -1;
6133     char c, * s, ** ap = NULL;
6134     if ((x = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6135         if (x == -3) {
6136             printf("?Array name required\n");
6137             return(-9);
6138         } else return(x);
6139     }
6140     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of name */
6141     s = line;
6142     x = arraybounds(s,&lo,&hi);
6143     if (x < 0) {                        /* Parse the name, get index */
6144         printf("?Bad array reference - \"%s\"\n", s);
6145         return(-9);
6146     }
6147     if (lo < 0 && hi < 0) {
6148         y = cmnum("New size","",10,&lo,xxstring);
6149         if (y < 0) {
6150             if (y == -3)
6151               printf("?New size required\n");
6152             return(y);
6153         }
6154     }
6155     if ((y = cmcfm()) < 0)
6156       return(y);
6157     if (a_link[x] > -1) {               /* Link? */
6158         islink = x;                     /* Yes follow it */
6159         x = a_link[x];                  /* and remember */
6160     }
6161     if (!a_ptr[x]) {
6162         printf("?Array not declared - \"%s\"\n", s);
6163         return(-9);
6164     }
6165     if (lo < 0) {
6166         printf("?New size required\n");
6167         return(-9);
6168     }
6169     if (hi > -1) {
6170         printf("?Array segments not allowed for this operation\n");
6171         return(-9);
6172     }
6173     c = arrayitoa(x);                   /* Get array letter */
6174     if (c == '@') {                     /* Argument vector array off limits */
6175         printf("?Sorry, \\&@[] is read-only\n");
6176         return(-9);
6177     }
6178     if (lo == 0) {                      /* If new size is 0... */
6179         dclarray(c,0);                  /* Undeclare the array */
6180         return(success = 1);
6181     }
6182     n = a_dim[x];                       /* Current size */
6183     ap = (char **) malloc((lo+1) * sizeof(char *)); /* New array */
6184     y = (n < lo) ? n : lo;
6185     for (i = 0; i <= y; i++)            /* Copy the part that fits */
6186       ap[i] = a_ptr[x][i];
6187     if (n < lo) {                       /* If original array smaller */
6188         for (; i <= lo; i++)            /* initialize extra elements in */
6189           ap[i] = NULL;                 /* new array to NULL. */
6190     } else if (n > lo) {                /* If new array smaller */
6191         for (; i <= lo; i++)            /* deallocate leftover elements */
6192           makestr(&(a_ptr[x][i]),NULL); /* from original array. */
6193     }
6194     free((char *)a_ptr[x]);             /* Free original array list */
6195     a_ptr[x] = ap;                      /* Replace with new one */
6196     a_dim[x] = lo;                      /* Record the new dimension */
6197     if (islink > -1) {                  /* Was this a link? */
6198         a_ptr[islink] = ap;             /* If so point to the resized array */
6199         a_dim[islink] = lo;
6200     } else {                            /* If not are there links to here? */
6201         for (i = 0; i < (int) 'z' - ARRAYBASE; i++) { /* Any linked arrays? */
6202             if (i != x && a_link[i] == x) {     /* Find and update them */
6203                 a_ptr[i] = ap;
6204                 a_dim[i] = lo;
6205             }
6206         }
6207     }
6208     return(success = 1);
6209 }
6210
6211 static int
6212 copyarray() {
6213     int i, j, x1, lo1, hi1, x2, lo2, hi2, whole = 0;
6214     char c1, c2, * a1, * a2;
6215     if ((y = cmfld("Name of source array","",&s,NULL)) < 0)
6216       return(y);
6217     ckstrncpy(line,s,LINBUFSIZ);
6218     a1 = line;
6219     if ((x1 = arraybounds(a1,&lo1,&hi1)) < 0) {
6220         printf("?Bad array reference - \"%s\"\n", a1);
6221         return(-9);
6222     } else if (!a_ptr[x1]) {
6223         printf("?Array not declared - \"%s\"\n", a1);
6224         return(-9);
6225     }
6226     c1 = arrayitoa(x1);
6227
6228     if ((y = cmfld("Name of destination array","",&s,NULL)) < 0)
6229       return(y);
6230     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
6231     a2 = tmpbuf;
6232     if ((x2 = arraybounds(a2,&lo2,&hi2)) < 0) {
6233         printf("?Bad array reference - \"%s\"\n", a2);
6234         return(-9);
6235     }
6236     c2 = arrayitoa(x2);
6237
6238     if ((x = cmcfm()) < 0)
6239       return(x);
6240
6241     if (c2 == '@') {                    /* Argument vector array off limits */
6242         printf("?Sorry, \\&@[] is read-only\n");
6243         return(-9);
6244     }
6245     if (lo1 < 0 && lo2 < 0 && hi1 < 0 && hi2 < 0) /* Special case for */
6246       whole = 1;                                  /* whole array... */
6247
6248     if (lo1 < 0) lo1 = whole ? 0 : 1;   /* Supply lower bound of source */
6249     if (hi1 < 0) hi1 = a_dim[x1];       /* Supply upper bound of source */
6250     if (lo2 < 0) lo2 = whole ? 0 : 1;   /* Lower bound of target */
6251     if (hi2 < 0) hi2 = lo2 + hi1 - lo1; /* Upper bound of target */
6252     if (a_ptr[x2]) {                    /* Target array is already declared? */
6253         if (hi2 > a_dim[x2])            /* If upper bound out of range */
6254           hi2 = a_dim[x2];              /* shrink to fit */
6255     } else {                            /* Otherwise... */
6256         x2 = dclarray(c2, hi2);         /* declare the target array */
6257     }
6258     for (i = lo1, j = lo2; i <= hi1 && j <= hi2; i++,j++) { /* Copy */
6259         makestr(&(a_ptr[x2][j]),a_ptr[x1][i]);
6260     }
6261     return(success = 1);
6262 }
6263
6264 static int                              /* Undeclare an array */
6265 unarray() {
6266     int x, y, n, rc = 0;
6267     char c, * s;
6268
6269     if ((y = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6270         if (y == -3) {
6271             printf("?Array name required\n");
6272             return(-9);
6273         } else return(y);
6274     }
6275     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of name */
6276     s = line;
6277     if ((y = cmcfm()) < 0)
6278       return(y);
6279     if ((x = arraybounds(s,&y,&n)) < 0) { /* Parse the name, get index */
6280         printf("?Bad array reference - \"%s\"\n", s);
6281         return(-9);
6282     }
6283     if (y > 0 || n > 0) {
6284         printf("?Partial arrays can not be destroyed\n");
6285         return(-9);
6286     }
6287     c = arrayitoa(x);                   /* Get array letter */
6288     if (a_ptr[x]) {                     /* If array is declared */
6289         if (c == '@') {                 /* Argument vector array off limits */
6290             printf("?Sorry, \\&@[] is read-only\n");
6291             return(-9);
6292         }
6293         rc = dclarray(c,-1);            /* Undeclare the array */
6294     } else                              /* It wasn't declared */
6295       rc = 1;
6296     if (rc > -1) {                      /* Set return code and success */
6297         success = 1;
6298         rc = 1;
6299     } else {
6300         success = 0;
6301         printf("?Failed - destroy \"\\&%c[]\"\n", c);
6302         rc = -9;
6303     }
6304     return(rc);
6305 }
6306
6307 static int
6308 clrarray(cx) int cx; {
6309     int i, x, lo, hi;
6310     char c, * s, * val = NULL;
6311
6312     if ((x = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6313         if (x == -3) {
6314             printf("?Array name required\n");
6315             return(-9);
6316         } else return(x);
6317     }
6318     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of name */
6319     s = line;
6320     if (cx == ARR_SET) {                /* SET */
6321         if ((x = cmtxt("Value","",&val,xxstring)) < 0)
6322           return(x);
6323         ckstrncpy(tmpbuf,val,TMPBUFSIZ); /* Value to set */
6324         val = tmpbuf;
6325         if (!*val) val = NULL;
6326     } else if ((x = cmcfm()) < 0)       /* CLEAR */
6327       return(x);
6328
6329     if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Parse the name */
6330         printf("?Bad array reference - \"%s\"\n", s);
6331         return(-9);
6332     }
6333     c = arrayitoa(x);                   /* Get array letter */
6334     if (!a_ptr[x]) {                    /* If array is declared */
6335         printf("?Array %s is not declared\n", s);
6336         return(-9);
6337     } else if (c == '@') {              /* Argument vector array off limits */
6338         printf("?Sorry, \\&@[] is read-only\n");
6339         return(-9);
6340     }
6341     if (lo < 0) lo = 0;
6342     if (hi < 0) hi = a_dim[x];
6343     for (i = lo; i <= hi; i++)          /* Clear/Set selected range */
6344       makestr(&(a_ptr[x][i]),val);
6345
6346     return(success = 1);
6347 }
6348
6349 extern char **aa_ptr[CMDSTKL][28];
6350 extern int aa_dim[CMDSTKL][28];
6351
6352 static int                              /* Create symbolic link to an array */
6353 linkarray() {
6354     int i = 0, x, y, lo, hi, flag = 0;
6355     char c, * s, * p;
6356
6357     if ((x = cmfld("Array name not currently in use","",&s,NULL)) < 0) {
6358         if (x == -3) {
6359             printf("?Array name required\n");
6360             return(-9);
6361         } else return(x);
6362     }
6363     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of link name */
6364     s = line;
6365     if ((x = cmfld("Name of existing array","",&p,xxstring)) < 0) {
6366         if (x == -3) {
6367             printf("?Array name required\n");
6368             return(-9);
6369         } else return(x);
6370     }
6371     ckstrncpy(tmpbuf,p,TMPBUFSIZ);      /* Make safe copy of array name */
6372     p = tmpbuf;
6373     if ((x = cmcfm()) < 0)
6374       return(x);
6375
6376     if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Parse the link name */
6377         printf("?Bad array reference - \"%s\"\n", s);
6378         return(-9);
6379     }
6380     if (a_ptr[x]) {                     /* Must not already exist */
6381         c = arrayitoa(x);
6382         printf("?Array already exists: \\&%c[]\n", c);
6383         return(-9);
6384     }
6385     if (lo > -1 || hi > -1) {
6386         printf("?Sorry, whole arrays only: %s\n",s);
6387         return(-9);
6388     }
6389     if ((y = arraybounds(p,&lo,&hi)) < 0) { /* Parse the array name */
6390         printf("?Bad array reference - \"%s\"\n", s);
6391         return(-9);
6392     }
6393     if (lo > -1 || hi > -1) {
6394         printf("?Sorry, whole arrays only: %s\n",p);
6395         return(-9);
6396     }
6397     if (x == y) {
6398         for (i = cmdlvl; i >= 0; i--)
6399           if (aa_ptr[i][x]) {
6400               flag++;
6401               break;
6402           }
6403     }
6404     if (flag) {
6405         a_ptr[x] = aa_ptr[i][y];        /* Link to saved copy */
6406         a_dim[x] = aa_dim[i][y];
6407     } else {                            /* Otherwise... */
6408         c = arrayitoa(y);               /* Check if it's declared */
6409         if (!a_ptr[y]) {
6410             printf("?Array is not declared: \\&%c[]\n", c);
6411             return(-9);
6412         }
6413         if (a_link[y] > -1) {           /* And if it's a link itself */
6414             printf("?Links to links not allowed: \\&%c[]\n", c);
6415             return(-9);
6416         }
6417         a_ptr[x] = a_ptr[y];            /* All OK, make the link */
6418         a_dim[x] = a_dim[y];
6419     }
6420     a_link[x] = y;
6421     return(success = 1);
6422 }
6423 #endif /* NOSPL */
6424
6425 #ifndef NOCSETS
6426 static char * dcsetname = NULL;
6427
6428 /* Get Display Character-Set Name */
6429
6430 char *
6431 getdcset() {
6432     char * s;
6433     int y;
6434 #ifdef PCFONTS
6435     extern int tt_font, ntermfont;
6436     extern struct keytab term_font[];
6437 #endif /* PCFONTS */
6438
6439     s = "";
6440 #ifdef OS2
6441     y = os2getcp();                     /* Default is current code page */
6442     switch (y) {
6443       case 437: s = "cp437"; break;
6444       case 850: s = "cp850"; break;
6445       case 852: s = "cp852"; break;
6446       case 857: s = "cp857"; break;
6447       case 858: s = "cp858"; break;
6448       case 862: s = "cp862"; break;
6449       case 866: s = "cp866"; break;
6450       case 869: s = "cp869"; break;
6451       case 1250: s = "cp1250"; break;
6452       case 1251: s = "cp1251"; break;
6453       case 1252: s = "cp1252"; break;
6454       case 1253: s = "cp1253"; break;
6455       case 1254: s = "cp1254"; break;
6456       case 1255: s = "cp1255"; break;
6457       case 1256: s = "cp1256"; break;
6458       case 1257: s = "cp1257"; break;
6459       case 1258: s = "cp1258"; break;
6460     }
6461 #ifdef PCFONTS
6462 /*
6463    If the user has loaded a font with SET TERMINAL FONT then we want
6464    to change the default code page to the font that was loaded.
6465 */
6466     if (tt_font != TTF_ROM) {
6467         for (y = 0; y < ntermfont; y++ ) {
6468             if (term_font[y].kwval == tt_font) {
6469                 s = term_font[y].kwd;
6470                 break;
6471             }
6472         }
6473     }
6474 #endif /* PCFONTS */
6475 #else /* OS2 */
6476 #ifdef COMMENT
6477     /* Hack not needed as of C-Kermit 7.1 */
6478     if (fcharset == FC_1LATIN) {
6479         s = "latin1-iso";               /* Hack to avoid reporting "cp1252" */
6480     } else {                            /* Report current file character set */
6481 #endif /* COMMENT */
6482         for (y = 0; y <= nfilc; y++)
6483           if (fcstab[y].kwval == fcharset) {
6484               s = fcstab[y].kwd;
6485               break;
6486           }
6487 #ifdef COMMENT
6488     }
6489 #endif /* COMMENT */
6490 #endif /* OS2 */
6491     makestr(&dcsetname,s);              /* Return stable pointer */
6492     return((char *)dcsetname);
6493 }
6494 #endif /* NOCSETS */
6495
6496 #ifndef NOFRILLS
6497 static int
6498 doclear() {
6499     if ((x = cmkey(clrtab,nclear,"item to clear",
6500 #ifdef NOSPL
6501                    "device-buffer"
6502 #else
6503                    "device-and-input"
6504 #endif /* NOSPL */
6505                    ,xxstring)) < 0) return(x);
6506 #ifndef NOSPL
6507 #ifdef OS2
6508     if (x == CLR_CMD || x == CLR_TRM) {
6509         if ((z = cmkey(clrcmdtab,nclrcmd,"how much screen to clear\n",
6510                        "all",xxstring)) < 0)
6511           return(z);
6512     }
6513 #endif /* OS2 */
6514 #endif /* NOSPL */
6515     if ((y = cmcfm()) < 0)
6516       return(y);
6517
6518     /* Clear device input buffer if requested */
6519     y = (x & CLR_DEV) ? ttflui() : 0;
6520
6521     if (x & CLR_SCR)                    /* CLEAR SCREEN */
6522       y = ck_cls();                     /* (= SCREEN CLEAR = CLS) */
6523
6524     if (x & CLR_KBD) {                  /* CLEAR KEYBOARD */
6525         int n;
6526         n = conchk();
6527         y = 0;
6528         while (n-- > 0 && (y = coninc(0) > -1))
6529           ;
6530         y = (y > -1) ? 0 : -1;
6531     }
6532
6533 #ifndef NOSPL
6534     /* Clear INPUT command buffer if requested */
6535     if (x & CLR_INP) {
6536         for (z = 0; z < inbufsize; z++)
6537           inpbuf[z] = NUL;
6538         inpbp = inpbuf;
6539         y = 0;
6540     }
6541 #ifdef CK_APC
6542     if (x & CLR_APC) {
6543         debug(F101,"Executing CLEAR APC","",apcactive);
6544         apcactive = 0;
6545         y = 0;
6546     }
6547 #endif /* CK_APC */
6548     if (x & CLR_ALR) {
6549         setalarm(0L);
6550         y = 0;
6551     }
6552 #endif /* NOSPL */
6553
6554 #ifdef PATTERNS
6555     if (x & (CLR_TXT|CLR_BIN)) {
6556         int i;
6557         for (i = 0; i < FTPATTERNS; i++) {
6558             if (x & CLR_TXT)
6559               makestr(&txtpatterns[i],NULL);
6560             if (x & CLR_BIN)
6561               makestr(&binpatterns[i],NULL);
6562         }
6563         y = 0;
6564     }
6565 #endif /* PATTERNS */
6566
6567 #ifndef NODIAL
6568     if (x & CLR_DIA) {
6569         dialsta = DIA_UNK;
6570         y = 0;
6571     }
6572 #endif /* NODIAL */
6573
6574 #ifndef NOMSEND
6575     if (x & CLR_SFL) {                  /* CLEAR SEND-LIST */
6576         if (filehead) {
6577             struct filelist * flp, * next;
6578             flp = filehead;
6579             while (flp) {
6580                 if (flp->fl_name)
6581                   free(flp->fl_name);
6582                 if (flp->fl_alias)
6583                   free(flp->fl_alias);
6584                 next = flp->fl_next;
6585                 free((char *)flp);
6586                 flp = next;
6587             }
6588         }
6589         filesinlist = 0;
6590         filehead = NULL;
6591         filetail = NULL;
6592         addlist = 0;
6593         y = 0;
6594     }
6595 #endif /* NOMSEND */
6596
6597 #ifdef OS2
6598 #ifndef NOLOCAL
6599     switch (x) {
6600       case CLR_SCL:
6601         clearscrollback(VTERM);
6602         break;
6603       case CLR_CMD:
6604         switch ( z ) {
6605           case CLR_C_ALL:
6606             clear();
6607             break;
6608           case CLR_C_BOS:
6609             clrboscr_escape(VCMD,SP);
6610             break;
6611           case CLR_C_BOL:
6612             clrbol_escape(VCMD,SP);
6613             break;
6614           case CLR_C_EOL:
6615             clrtoeoln(VCMD,SP);
6616             break;
6617           case CLR_C_EOS:
6618             clreoscr_escape(VCMD,SP);
6619             break;
6620           case CLR_C_LIN:
6621             clrline_escape(VCMD,SP);
6622             break;
6623           case CLR_C_SCR:
6624             clearscrollback(VCMD);
6625             break;
6626         default:
6627             printf("Not implemented yet, sorry.\n");
6628             break;
6629         }
6630         break;
6631
6632 #ifndef NOTERM
6633       case CLR_TRM:
6634          switch ( z ) {
6635           case CLR_C_ALL:
6636              if (VscrnGetBufferSize(VTERM) > 0 ) {
6637                  VscrnScroll(VTERM, UPWARD, 0,
6638                              VscrnGetHeight(VTERM)-(tt_status[VTERM]?2:1),
6639                              VscrnGetHeight(VTERM) -
6640                              (tt_status[VTERM]?1:0), TRUE, SP
6641                              );
6642                  cleartermscreen(VTERM);
6643              }
6644              break;
6645           case CLR_C_BOS:
6646             clrboscr_escape(VTERM,SP);
6647             break;
6648           case CLR_C_BOL:
6649             clrbol_escape(VTERM,SP);
6650             break;
6651           case CLR_C_EOL:
6652             clrtoeoln(VTERM,SP);
6653             break;
6654           case CLR_C_EOS:
6655             clreoscr_escape(VTERM,SP);
6656             break;
6657           case CLR_C_LIN:
6658             clrline_escape(VTERM,SP);
6659             break;
6660          case CLR_C_SCR:
6661              clearscrollback(VTERM);
6662              break;
6663          default:
6664              printf("Not implemented yet, sorry.\n");
6665              break;
6666         }
6667         break;
6668 #endif /* NOTERM */
6669     }
6670     y = 0;
6671 #endif /* NOLOCAL */
6672 #endif /* OS2 */
6673     return(success = (y == 0));
6674 }
6675 #endif /* NOFRILLS */
6676
6677 #ifndef NOSPL
6678 static int
6679 doeval(cx) int cx; {
6680     char *p;
6681     char vnambuf[VNAML], * vnp = NULL;  /* These must be on the stack */
6682     if (!oldeval) {
6683         if ((y = cmfld("Variable name","",&s,
6684                        ((cx == XX_EVAL) ? xxstring : NULL))) < 0) {
6685             if (y == -3) {
6686                 printf("?Variable name required\n");
6687                 return(-9);
6688             } else return(y);
6689         }
6690         ckstrncpy(vnambuf,s,VNAML);     /* Make a copy. */
6691         vnp = vnambuf;
6692         if (vnambuf[0] == CMDQ &&
6693             (vnambuf[1] == '%' || vnambuf[1] == '&'))
6694           vnp++;
6695         y = 0;
6696         if (*vnp == '%' || *vnp == '&') {
6697             if ((y = parsevar(vnp,&x,&z)) < 0)
6698               return(y);
6699         }
6700     }
6701     if ((x = cmtxt("Integer arithmetic expression","",&s,xxstring)) < 0)
6702       return(x);
6703     p = evala(s);
6704     if (!p) p = "";
6705     if (oldeval && *p)
6706       printf("%s\n", p);
6707     ckstrncpy(evalbuf,p,32);
6708     if (!oldeval)
6709       return(success = addmac(vnambuf,p));
6710     else
6711       return(success = *p ? 1 : 0);
6712 }
6713 #endif /* NOSPL */
6714
6715 #ifdef TNCODE
6716 static int
6717 dotelopt() {
6718     if ((x = cmkey(telcmd, ntelcmd, "TELNET command", "", xxstring)) < 0 )
6719       return(x);
6720     switch (x) {
6721       case WILL:
6722       case WONT:
6723       case DO:
6724       case DONT:
6725         if ((y = cmkey(tnopts,ntnopts,"TELNET option","",xxstring)) < 0)
6726           return(y);
6727         if ((z = cmcfm()) < 0) return(z);
6728
6729         switch (x) {
6730           case WILL:
6731             if (TELOPT_UNANSWERED_WILL(y))
6732               return(success = 0);
6733             break;
6734           case WONT:
6735             if (TELOPT_UNANSWERED_WONT(y))
6736               return(success = 0);
6737             break;
6738           case DO:
6739             if (TELOPT_UNANSWERED_DO(y))
6740               return(success = 0);
6741             break;
6742           case DONT:
6743             if (TELOPT_UNANSWERED_DONT(y))
6744               return(success = 0);
6745             break;
6746         }
6747         if (local) {
6748             success = ((tn_sopt(x,y) > -1) ? 1 : 0);
6749         } else {
6750             printf("ff%02x%02x\n",x,y);
6751             success = 1;
6752         }
6753         if (success) {
6754             switch (x) {
6755               case WILL:
6756                 TELOPT_UNANSWERED_WILL(y) = 1;
6757                 break;
6758               case WONT:
6759                 if ( TELOPT_ME(y) )
6760                   TELOPT_UNANSWERED_WONT(y) = 1;
6761                 break;
6762               case DO:
6763                 TELOPT_UNANSWERED_DO(y) = 1;
6764                 break;
6765               case DONT:
6766                 if ( TELOPT_ME(y) )
6767                   TELOPT_UNANSWERED_DONT(y) = 1;
6768                 break;
6769             }
6770             if (tn_wait("XXTELOP") < 0) {
6771                 tn_push();
6772                 success = 0;
6773             }
6774         }
6775         return(success);
6776       case SB:
6777         if ((y=cmkey(tnsbopts,ntnsbopts,"TELNET option","",xxstring)) < 0)
6778           return(y);
6779         switch (y) {
6780           case TELOPT_NAWS:
6781             /* Some compilers require switch() to have at least 1 case */
6782 #ifdef CK_NAWS
6783             TELOPT_SB(TELOPT_NAWS).naws.x = 0;
6784             TELOPT_SB(TELOPT_NAWS).naws.y = 0;
6785             if (local)
6786               return(success = ((tn_snaws() > -1) ? 1 : 0));
6787             else
6788               return(success = 0);
6789 #else
6790             return(success = 0);
6791 #endif /* CK_NAWS */
6792         }
6793         return(success = 0);
6794
6795 #ifdef CK_KERBEROS
6796 #ifdef KRB5
6797       case TN_FWD:
6798         success = (kerberos5_forward() == AUTH_SUCCESS);
6799         return(success);
6800 #endif /* KRB5 */
6801 #endif /* CK_KERBEROS */
6802
6803       default:
6804         if ((z = cmcfm()) < 0) return(z);
6805 #ifndef NOLOCAL
6806         if (local) {
6807             CHAR temp[3];
6808             if (network && IS_TELNET()) { /* TELNET */
6809                 temp[0] = (CHAR) IAC;
6810                 temp[1] = x;
6811                 temp[2] = NUL;
6812                 success = (ttol((CHAR *)temp,2) > -1 ? 1 : 0);
6813                 if (tn_deb || debses || deblog) {
6814                     /* TN_MSG_LEN is in ckctel.h */
6815                     ckmakmsg(tn_msg,256,"TELNET SENT ",TELCMD(x),NULL,NULL);
6816                     debug(F101,tn_msg,"",x);
6817                     if (debses || tn_deb) tn_debug(tn_msg);
6818                 }
6819                 return(success);
6820             }
6821             return(success = 0);
6822         } else {
6823 #endif /* NOLOCAL */
6824             printf("ff%02x\n",x);
6825             return(success = 1);
6826 #ifndef NOLOCAL
6827         }
6828 #endif /* NOLOCAL */
6829     }
6830 }
6831 #endif /* TNCODE */
6832
6833
6834 #ifndef NOPUSH
6835 #ifndef NOFRILLS
6836 static int
6837 doedit() {
6838 #ifdef OS2
6839     char * p = NULL;
6840 #endif /* OS2 */
6841     if (!editor[0]) {
6842         s = getenv("EDITOR");
6843         if (s) ckstrncpy(editor,s,CKMAXPATH);
6844         editor[CKMAXPATH] = NUL;
6845         if (!editor[0]) {
6846             printf("?Editor not defined - use SET EDITOR to define\n");
6847             return(-9);
6848         }
6849     }
6850     ckstrncpy(tmpbuf,editfile,TMPBUFSIZ);
6851 /*
6852   cmiofi() lets us parse the name of an existing file, or the name of
6853   a nonexistent file to be created.
6854 */
6855     x = cmiofi("File to edit", (char *)tmpbuf, &s, &y, xxstring);
6856     debug(F111,"edit",s,x);
6857     if (x < 0 && x != -3)
6858       return(x);
6859     if (x == -3) {
6860         tmpbuf[0] = NUL;
6861     } else {
6862         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
6863     }
6864     if ((z = cmcfm()) < 0) return(z);
6865     if (y) {
6866         printf("?A single file please\n");
6867         return(-9);
6868     }
6869     if (nopush) {
6870         printf("?Sorry, editing not allowed\n");
6871         return(success = 0);
6872     }
6873     if (tmpbuf[0]) {
6874     /* Get full path in case we change directories between EDIT commands */
6875         zfnqfp(tmpbuf, CKMAXPATH, editfile);
6876         editfile[CKMAXPATH] = NUL;
6877 #ifdef OS2
6878         p = editfile;                   /* Flip the stupid slashes */
6879         while (*p) {
6880             if (*p == '/') *p = '\\';
6881             p++;
6882         }
6883 #endif /* OS2 */
6884     } else
6885       editfile[0] = NUL;
6886     if (editfile[0]) {
6887         if (zchki(editfile) < (CK_OFF_T)0 && zchko(editfile) < 0) {
6888             printf("?Access denied: %s\n",editfile);
6889             return(-9);
6890         }
6891     }
6892     x = 0;
6893     if (editopts[0]) {
6894 #ifdef OS2
6895         x = ckindex("%1",(char *)editopts,0,0,1);
6896         if (x > 0)
6897           editopts[x] = 's';
6898         else
6899 #endif /* OS2 */
6900           x = ckindex("%s",(char *)editopts,0,0,1);
6901     }
6902     if (((int)strlen(editopts) + (int)strlen(editfile) + 1) < TMPBUFSIZ) {
6903         if (x)
6904           sprintf(tmpbuf,editopts,editfile);
6905         else
6906           sprintf(tmpbuf,"%s %s",editopts,editfile);
6907     }
6908     s = line;
6909     ckmakmsg(s,LINBUFSIZ,editor," ",tmpbuf,NULL);
6910 #ifdef OS2
6911     p = s + strlen(editor);             /* And again with the slashes */
6912     while (p != s) {
6913         if (*p == '/') *p = '\\';
6914         p--;
6915     }
6916 #endif /* OS2 */
6917     conres();
6918     x = zshcmd(s);
6919     concb((char)escape);
6920     return(x);
6921 }
6922 #endif /* NOFRILLS */
6923 #endif /* NOPUSH */
6924
6925 #ifdef BROWSER
6926 static int
6927 dobrowse() {
6928 #ifdef OS2
6929     char * p = NULL;
6930 #endif /* OS2 */
6931     if (nopush) {
6932         printf("?Sorry, browsing not allowed\n");
6933         return(success = 0);
6934     }
6935 #ifndef NT
6936     /* Windows lets the Shell Execute the URL if no Browser is defined */
6937     if (!browser[0]) {
6938         s = getenv("BROWSER");
6939         if (s) ckstrncpy(browser,s,CKMAXPATH);
6940         browser[CKMAXPATH] = NUL;
6941         if (!browser[0]) {
6942             printf("?Browser not defined - use SET BROWSER to define\n");
6943             return(-9);
6944         }
6945     }
6946 #endif /* NT */
6947     ckstrncpy(tmpbuf,browsurl,TMPBUFSIZ);
6948     if ((x = cmtxt("URL",(char *)browsurl,&s,xxstring)) < 0)
6949       return(x);
6950     ckstrncpy(browsurl,s,4096);
6951     x = 0;
6952     if (browsopts[0]) {
6953 #ifdef OS2
6954         x = ckindex("%1",(char *)browsopts,0,0,1);
6955         if (x > 0)
6956           browsopts[x] = 's';
6957         else
6958 #endif /* OS2 */
6959           x = ckindex("%s",(char *)browsopts,0,0,1);
6960     }
6961     if (((int)strlen(browsopts) + (int)strlen(browsurl) + 1) < TMPBUFSIZ) {
6962         if (x)
6963           sprintf(tmpbuf,browsopts,browsurl);
6964         else
6965           sprintf(tmpbuf,"%s %s",browsopts,browsurl);
6966     }
6967 #ifdef NT
6968     if (!browser[0])
6969       return(success = Win32ShellExecute(browsurl));
6970 #endif /* NT */
6971     s = line;
6972     ckmakmsg(s,LINBUFSIZ,browser," ",tmpbuf,NULL);
6973 #ifdef OS2
6974     p = line + strlen(browser);         /* Flip slashes */
6975     while (p != line) {
6976         if (*p == '/') *p = '\\';
6977         p--;
6978     }
6979 #endif /* OS2 */
6980     conres();
6981     x = zshcmd(s);
6982     concb((char)escape);
6983     return(x);
6984 }
6985 #endif /* BROWSER */
6986
6987 #ifdef CK_RECALL
6988 static int
6989 doredo() {                      /* Find a previous cmd and redo it */
6990     extern int on_recall, in_recall;
6991     int x;
6992     char * p;
6993
6994     if ((x = cmtxt(
6995 "pattern, or first few characters of a previous command",
6996                    "*",&s,xxstring)) < 0)
6997       return(x);
6998     ckstrncpy(line,s,LINBUFSIZ);
6999     x = strlen(s);
7000     s = line;
7001     if (*s == '{') {                    /* Braces disable adding * to end */
7002         if (s[x-1] == '}') {
7003             s[x-1] = NUL;
7004             s++;
7005             x--;
7006         }
7007     } else {                            /* No braces, add * to end. */
7008         s[x] = '*';
7009         s[x+1] = NUL;
7010     }
7011
7012     while (x > 0 && s[x] == '*' && s[x-1] == '*') s[x--] = NUL;
7013
7014     if (!on_recall || !in_recall) {
7015         printf("?Sorry, command recall can't be used now.\n");
7016         return(-9);
7017     }
7018     if ((p = cmgetcmd(s))) {            /* Look for it history buffer */
7019         ckmakmsg(cmdbuf,CMDBL,p,"\r",NULL,NULL); /* Copy to command buffer */
7020         if (!quiet)                     /* Echo it */
7021           printf("%s\n",cmdbuf);
7022         cmaddnext();                    /* Force re-add to history buffer */
7023         return(cmflgs = -1);            /* Force reparse */
7024     } else {
7025         printf("?Sorry - \"%s\" not found\n", s);
7026         return(-9);
7027     }
7028 }
7029 #endif /* CK_RECALL */
7030
7031 #ifndef NOXFER
7032 #ifndef NOCSETS
7033 static int
7034 doassoc()  {                            /* ASSOCIATE */
7035     extern struct keytab tcstab[];
7036     extern int ntcs;
7037     if ((x = cmkey(assoctab, nassoc, "", "", xxstring)) < 0 )
7038       return(x);
7039
7040     switch (x) {                        /* Associate what? */
7041
7042       case ASSOC_TC:                    /* Transfer character-set... */
7043         if ((x = cmkey(tcstab, ntcs,
7044                        "transfer character-set name","",xxstring)) < 0)
7045           return(x);
7046         if ((y = cmkey(fcstab, nfilc,
7047                        "with file character-set","", xxstring)) < 0)
7048           if (y != -3)
7049             return(y);
7050         if ((z = cmcfm()) < 0)
7051           return(z);
7052         axcset[x] = y;
7053         return(success = 1);
7054
7055       case ASSOC_FC:                    /* File character-set... */
7056         if ((x = cmkey(fcstab, nfilc,
7057                        "file character-set name","",xxstring)) < 0)
7058           return(x);
7059         if ((y = cmkey(tcstab, ntcs,
7060                        "with transfer character-set","", xxstring)) < 0)
7061           if (y != -3)
7062             return(y);
7063         if ((z = cmcfm()) < 0)
7064           return(z);
7065         afcset[x] = y;
7066         return(success = 1);
7067
7068       default:
7069         return(-2);
7070     }
7071 }
7072 #endif /* NOCSETS */
7073 #endif /* NOXFER */
7074
7075 #ifndef NOHELP
7076 static int
7077 domanual() {
7078 #ifdef OS2
7079     if ((x = cmcfm()) < 0)
7080       return(x);
7081     if (nopush) {
7082         printf("?Sorry, access to system commands is disabled.\n");
7083         return(-9);
7084     }
7085     y = mxlook(mactab,"manual",nmac);
7086     if (y > -1) {
7087         z = maclvl;                     /* Save the current maclvl */
7088         dodo(y,NULL,cmdstk[cmdlvl].ccflgs); /* Run the macro */
7089         while (maclvl > z) {
7090             debug(F101,"XXMAN loop maclvl 1","",maclvl);
7091             sstate = (CHAR) parser(1);
7092             debug(F101,"XXMAN loop maclvl 2","",maclvl);
7093             if (sstate) proto();
7094         }
7095         debug(F101,"XXMAN loop exit maclvl","",maclvl);
7096         return(success);
7097     }
7098     return(success = 0);
7099 #else
7100     if ((x = cmtxt(
7101 #ifdef UNIX
7102                    "Carriage return to confirm the command, or manual topic",
7103 #else
7104                    "Carriage return to confirm the command, or help topic",
7105 #endif /* UNIX */
7106                    "kermit",
7107                    &s,
7108                    xxstring
7109                    )
7110          ) < 0)
7111       return(x);
7112 #endif /* OS2 */
7113
7114 #ifdef UNIX
7115     ckmakmsg(tmpbuf,TMPBUFSIZ,"man ",s,NULL,NULL);
7116 #else
7117     ckmakmsg(tmpbuf,TMPBUFSIZ,"help ",s,NULL,NULL);
7118 #endif /* UNIX */
7119     debug(F110,"MANUAL",tmpbuf,0);
7120     if (nopush) {
7121         printf("?Sorry, access to system commands is disabled.\n");
7122         return(-9);
7123     } else {
7124         conres();                       /* Restore the console */
7125         success = zshcmd(tmpbuf);
7126         concb((char)escape);            /* Restore CBREAK mode */
7127         return(success);
7128     }
7129 }
7130 #endif /* NOHELP */
7131
7132 #ifndef NOHTTP
7133 #ifdef TCPSOCKET
7134 static struct keytab sslswtab[] = {
7135     { "/ssl", 1, 0 },
7136     { "/tls", 1, 0 }
7137 };
7138
7139 #ifndef NOURL
7140 struct urldata http_url = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
7141 #endif /* NOURL */
7142
7143 static int
7144 dohttp() {                              /* HTTP */
7145     struct FDB sw, kw, fi;
7146     int n, getval, allinone = 0;
7147     char c, * p;
7148     char rdns[128];
7149
7150     char * http_agent = NULL;           /* Parse results */
7151     char * http_hdr   = NULL;
7152     char * http_user  = NULL;
7153     char * http_pass  = NULL;
7154     char * http_mime  = NULL;
7155     char * http_lfile = NULL;
7156     char * http_rfile = NULL;
7157     char * http_dfile = NULL;
7158     char   http_array = NUL;
7159     int    http_action = -1;
7160
7161     char * http_host = NULL;
7162     char * http_srv  = NULL;
7163     int    http_ssl  = 0;
7164
7165     static char * http_d_agent = NULL;
7166     static char * http_d_user = NULL;
7167     static char * http_d_pass = NULL;
7168
7169     static int    http_d_type = 0;
7170     int           http_type = http_d_type;
7171
7172 #ifdef OS2
7173     p = "Kermit 95";                    /* Default user agent */
7174 #else
7175     p = "C-Kermit";
7176 #endif /* OS2 */
7177     makestr(&http_agent,p);
7178     makestr(&http_mime,"text/HTML");    /* MIME type default */
7179     rdns[0] = '\0';
7180
7181     cmfdbi(&sw,                         /* 1st FDB - general switches */
7182        _CMKEY,                          /* fcode */
7183        "OPEN, CLOSE, GET, HEAD, PUT, INDEX, or POST,\n or switch", /* hlpmsg */
7184        "",                              /* default */
7185        "",                              /* addtl string data */
7186        nhttpswtab,                      /* addtl numeric data 1: tbl size */
7187        4,                               /* addtl numeric data 2: 4 = cmswi */
7188        xxstring,                        /* Processing function */
7189        httpswtab,                       /* Keyword table */
7190        &kw                              /* Pointer to next FDB */
7191        );
7192     cmfdbi(&kw,                         /* 2nd FDB - commands */
7193        _CMKEY,                          /* fcode */
7194        "Command",                       /* hlpmsg */
7195        "",                              /* default */
7196        "",                              /* addtl string data */
7197        nhttptab,                        /* addtl numeric data 1: tbl size */
7198        0,                               /* addtl numeric data 2: 0 = keyword */
7199        xxstring,                        /* Processing function */
7200        httptab,                         /* Keyword table */
7201        NULL                             /* Pointer to next FDB */
7202        );
7203
7204     while (1) {
7205         x = cmfdb(&sw);                 /* Parse something */
7206         if (x < 0)                      /* Error */
7207           goto xhttp;
7208         n = cmresult.nresult;
7209         if (cmresult.fdbaddr == &kw)    /* Command - exit this loop */
7210           break;
7211         c = cmgbrk();                   /* Switch... */
7212         getval = (c == ':' || c == '=');
7213         x = -9;
7214         if (getval && !(cmgkwflgs() & CM_ARG)) {
7215             printf("?This switch does not take an argument\n");
7216             goto xhttp;
7217         }
7218         switch (cmresult.nresult) {     /* Handle each switch */
7219           case HT_SW_TP:                /* /TOSCREEN */
7220             http_type = 1;
7221             break;
7222           case HT_SW_AG:                /* /AGENT */
7223             if (getval) {
7224                 if ((x = cmfld("User agent",p,&s,xxstring)) < 0)
7225                   goto xhttp;
7226             } else {
7227                 s = p;
7228             }
7229             makestr(&http_agent,s);
7230             break;
7231           case HT_SW_HD:                /* /HEADER */
7232             s = NULL;
7233             if (getval) {
7234                 if ((x = cmfld("Header line","",&s,xxstring)) < 0) {
7235                     if (x == -3)
7236                       s = NULL;
7237                     else
7238                       goto xhttp;
7239                 }
7240             }
7241             makestr(&http_hdr,s);
7242             break;
7243           case HT_SW_US:                /* /USER */
7244             s = NULL;
7245             if (getval) {
7246                 if ((x = cmfld("User ID","",&s,xxstring)) < 0) {
7247                   if (x == -3)
7248                     s = "";
7249                   else
7250                     goto xhttp;
7251                 }
7252             }
7253             makestr(&http_user,s);
7254             break;
7255           case HT_SW_PW:                /* /PASSWORD */
7256             debok = 0;
7257             s = NULL;
7258             if (getval) {
7259                 if ((x = cmfld("Password","",&s,xxstring)) < 0)
7260                   goto xhttp;
7261             }
7262             makestr(&http_pass,s);
7263             break;
7264 #ifndef NOSPL
7265           case HT_SW_AR: {              /* /ARRAY: */
7266               char * s2, array = NUL;
7267               if (!getval) {
7268                   printf("?This switch requires an argument\n");
7269                   x = -9;
7270                   goto xhttp;
7271               }
7272               if ((x = cmfld("Array name (a single letter will do)",
7273                              "",
7274                              &s,
7275                              NULL
7276                              )) < 0) {
7277                   if (x == -3) {
7278                       printf("?Array name required\n");
7279                       x = -9;
7280                       goto xhttp;
7281                   } else
7282                     goto xhttp;
7283               }
7284               if (!*s) {
7285                   printf("?Array name required\n");
7286                   x = -9;
7287                   goto xhttp;
7288               }
7289               s2 = s;
7290               if (*s == CMDQ) s++;
7291               if (*s == '&') s++;
7292               if (!isalpha(*s)) {
7293                   printf("?Bad array name - \"%s\"\n",s2);
7294                   x = -9;
7295                   goto xhttp;
7296               }
7297               array = *s++;
7298               if (isupper(array))
7299                 array = tolower(array);
7300               if (*s && (*s != '[' || *(s+1) != ']')) {
7301                   printf("?Bad array name - \"%s\"\n",s2);
7302                   http_array = NUL;
7303                   x = -9;
7304                   goto xhttp;
7305               }
7306               http_array = array;
7307               break;
7308           }
7309 #endif /* NOSPL */
7310           default:
7311             x = -2;
7312             goto xhttp;
7313         }
7314     }
7315     http_action = n;                    /* Save the action */
7316     if (http_action == HTTP_PUT || http_action == HTTP_POS) {
7317         cmfdbi(&sw,                     /* 1st FDB - switch */
7318                _CMKEY,                  /* fcode */
7319                "Local filename\n Or switch", /* help */
7320                "",                      /* default */
7321                "",                      /* addtl string data */
7322                nhttpptab,               /* keyword table size */
7323                4,                       /* addtl numeric data 2: 4 = cmswi */
7324                xxstring,                /* Processing function */
7325                httpptab,                /* Keyword table */
7326                &fi                      /* Pointer to next FDB */
7327                );
7328         cmfdbi(&fi,                     /* 2nd FDB - filename */
7329                _CMIFI,                  /* fcode */
7330                "Local filename",        /* hlpmsg */
7331                "",                      /* default */
7332                "",                      /* addtl string data */
7333                0,                       /* addtl numeric data 1 */
7334                0,                       /* addtl numeric data 2 */
7335                xxstring,
7336                NULL,
7337                NULL
7338                );
7339         while (1) {
7340             x = cmfdb(&sw);
7341             if (x < 0)
7342               goto xhttp;               /* Free any malloc'd temp strings */
7343             n = cmresult.nresult;
7344             if (cmresult.fcode != _CMKEY)
7345               break;
7346             c = cmgbrk();               /* Switch... */
7347             getval = (c == ':' || c == '=');
7348             if (getval && !(cmgkwflgs() & CM_ARG)) {
7349                 printf("?This switch does not take an argument\n");
7350                 x = -9;
7351                 goto xhttp;
7352             }
7353             switch (n) {
7354               case HT_PP_MT:
7355                 s = "text/HTML";
7356                 if (getval) {
7357                     if ((x = cmfld("MIME type",
7358                                    "text/HTML",&s,xxstring)) < 0)
7359                       goto xhttp;
7360                 }
7361                 makestr(&http_mime,s);
7362                 break;
7363               default:
7364                 x = -2;
7365                 goto xhttp;
7366             }
7367         }
7368         makestr(&http_lfile,cmresult.sresult);
7369         n = ckindex("/",http_lfile,-1,1,0);
7370         if (n)
7371           p = &http_lfile[n];
7372         else
7373           p = http_lfile;
7374         if ((x = cmfld("URL or remote filename",p,&s,xxstring)) < 0) {
7375           if (x == -3) {
7376             printf("?%s what?\n",(http_action == HTTP_PUT) ? "Put" : "Post");
7377             x = -9;
7378           }
7379           goto xhttp;
7380         }
7381         if (!*s) s = NULL;
7382         makestr(&http_rfile,s);
7383
7384         if ((x = cmtxt("Response filename","",&s,xxstring)) < 0) {
7385           if (x != -3)
7386             goto xhttp;
7387         }
7388         if (*s)
7389           makestr(&http_dfile,s);
7390     }
7391     switch (http_action) {
7392       case HTTP_DEL:                    /* DELETE */
7393         if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7394           if (x == -3) {
7395             printf("?Delete what?\n");
7396             x = -9;
7397           }
7398           goto xhttp;
7399         }
7400         makestr(&http_rfile,s);
7401         break;
7402       case HTTP_CON:                    /* CONNECT */
7403         if ((x = cmfld("Remote host[:port]","",&s,xxstring)) < 0) {
7404           if (x == -3) {
7405             printf("?Remote host[:port] is required\n");
7406             x = -9;
7407           }
7408           goto xhttp;
7409         }
7410         makestr(&http_rfile,s);
7411         break;
7412       case HTTP_HED: {                  /* HEAD */
7413           char buf[CKMAXPATH+1];
7414           if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7415               if (x == -3) {
7416                   printf("?Head of what?\n");
7417                   x = -9;
7418               }
7419               goto xhttp;
7420           }
7421           makestr(&http_rfile,s);
7422
7423           if (http_array || http_type) { /* Default result filename */
7424               p = "";                    /* None if /ARRAY or /TOSCREEN */
7425           } else {
7426               n = ckindex("/",http_rfile,-1,1,0); /* Otherwise strip path */
7427               if (n)                              /* and add ".head" */
7428                 p = &http_rfile[n];
7429               else
7430                 p = http_rfile;
7431               ckmakmsg(buf,CKMAXPATH,p,".head",NULL,NULL);
7432               p = buf;
7433           }
7434           if ((x = cmofi("Local filename",p,&s,xxstring)) < 0) {
7435               if (x != -3)
7436                 goto xhttp;
7437           }
7438           makestr(&http_lfile,s);
7439           break;
7440       }
7441       case HTTP_GET:                    /* GET */
7442       case HTTP_IDX: {                  /* INDEX */
7443           extern int wildena;
7444           int tmp;
7445           char * lfile = "";
7446           if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7447               if (x == -3) {
7448                   printf("?Get what?\n");
7449                   x = -9;
7450               }
7451               goto xhttp;
7452           }
7453           makestr(&http_rfile,s);
7454           if (http_action == HTTP_GET && !http_type)
7455             zstrip(http_rfile,&lfile);
7456           /* URLs often contain question marks or other metacharacters */
7457           /* cmofi() doesn't like them */
7458           tmp = wildena;
7459           wildena = 0;
7460           if ((x = cmofi("Local filename",lfile,&s,xxstring)) < 0) {
7461               wildena = tmp;
7462               if (x != -3)
7463                 goto xhttp;
7464           }
7465           wildena = tmp;
7466           makestr(&http_lfile,s);
7467           break;
7468       }
7469       case HTTP_OPN: {
7470           int sslswitch = 0;
7471 #ifdef CK_SSL
7472           struct FDB sw, fl;
7473           cmfdbi(&sw,
7474                  _CMKEY,                /* fcode */
7475                  "IP host name or address, or switch", /* hlpmsg */
7476                  "",                    /* default */
7477                  "",                    /* addtl string data */
7478                  2,                     /* addtl numeric data 1: tbl size */
7479                  4,                     /* addtl numeric data 2: 4 = cmswi */
7480                  xxstring,              /* Processing function */
7481                  sslswtab,              /* Keyword table */
7482                  &fl                    /* Pointer to next FDB */
7483                  );
7484           cmfdbi(&fl,                   /* 2nd FDB - host */
7485                  _CMFLD,                /* fcode */
7486                  "",                    /* hlpmsg */
7487                  "",                    /* default */
7488                  "",                    /* addtl string data */
7489                  0,                     /* addtl numeric data 1 */
7490                  0,                     /* addtl numeric data 2 */
7491                  xxstring,
7492                  NULL,
7493                  NULL
7494                  );
7495           x = cmfdb(&sw);               /* Parse switch or host */
7496           if (x < 0)                    /* Error */
7497             goto xhttp;
7498           if (cmresult.fcode == _CMFLD) { /* Host */
7499               s = cmresult.sresult;       /* Set up expected pointer */
7500               goto havehost;              /* Go parse rest of command */
7501           }
7502           sslswitch = 1;                /* /SSL or /TLS switch - set flag */
7503 #endif /* CK_SSL */
7504
7505           /* Parse host */
7506
7507           if ((x = cmfld("URL, hostname, or ip-address","",&s,xxstring)) < 0) {
7508               if (x == -3) {
7509                   printf("?Open what?\n");
7510                   x = -9;
7511               }
7512               goto xhttp;
7513           }
7514
7515         havehost:                       /* Come here with s -> host */
7516 #ifdef CK_URL
7517           x = urlparse(s,&http_url);    /* Was a URL given? */
7518           if (x < 1) {                  /* Not a URL */
7519 #endif /* CK_URL */
7520               makestr(&http_host,s);
7521               if ((x =
7522                    cmfld("Service name or port number",
7523                          sslswitch ? "https" : "http",&s,xxstring)) < 0)
7524                 goto xhttp;
7525               else
7526                 makestr(&http_srv,s);
7527 #ifdef CK_URL
7528           } else if (ckstrcmp(http_url.svc,"http",-1,0) && /* Non-HTTP URL */
7529                      ckstrcmp(http_url.svc,"https",-1,0)) {
7530               printf("?Non-HTTP URL\n");
7531               x = -9;
7532               goto xhttp;
7533           } else {                      /* Have HTTP URL */
7534               makestr(&http_srv, http_url.svc);
7535               makestr(&http_user,http_url.usr);
7536               makestr(&http_pass,http_url.psw);
7537               makestr(&http_host,http_url.hos);
7538               if (http_url.por)
7539                 makestr(&http_srv,http_url.por);
7540               makestr(&http_rfile,http_url.pth);
7541           }
7542           if (http_rfile) {             /* Open, GET, and Close */
7543               printf("?Directory/file path not allowed in HTTP OPEN URL\n");
7544               x = -9;
7545               goto xhttp;
7546           }
7547           if (!ckstrcmp("https",http_srv,-1,0) || sslswitch ||
7548               !ckstrcmp("443",http_srv,-1,0))
7549             http_ssl = 1;
7550 #endif /* CK_URL */
7551           break;
7552       }
7553       case HTTP_CLS:
7554         break;
7555     }
7556     if ((x = cmcfm()) < 0)
7557       goto xhttp;
7558
7559     if (http_action == HTTP_OPN) {
7560         x = (http_open(http_host,http_srv,http_ssl,rdns,128,http_agent) == 0);
7561         if (x) {
7562             if (!quiet) {
7563               if (rdns[0])
7564                 printf("Connected to %s [%s]\r\n",http_host,rdns);
7565               else
7566                 printf("Connected to %s\r\n",http_host);
7567             }
7568             if (http_agent) {
7569                 if (http_d_agent)
7570                   free(http_d_agent);
7571                 http_d_agent = http_agent;
7572                 http_agent = NULL;
7573             }
7574             if (http_user) {
7575                 if (http_d_user)
7576                   free(http_d_user);
7577                 http_d_user = http_user;
7578                 http_user = NULL;
7579             }
7580             if (http_pass) {
7581                 if (http_d_pass) {
7582                     memset(http_d_pass,0,strlen(http_d_pass));
7583                     free(http_d_pass);
7584                 }
7585                 http_d_pass = http_pass;
7586                 http_pass = NULL;
7587             }
7588             http_d_type = http_type;
7589         } else {
7590             if (!quiet)
7591               printf("?HTTP Connection failed.\r\n");
7592         }
7593     } else if (http_action == HTTP_CLS) {
7594         if (http_d_agent) {
7595             free(http_d_agent);
7596             http_d_agent = NULL;
7597         }
7598         if (http_d_user) {
7599             free(http_d_user);
7600             http_d_user = NULL;
7601         }
7602         if (http_d_pass) {
7603             memset(http_d_pass,0,strlen(http_d_pass));
7604             free(http_d_pass);
7605             http_d_pass = NULL;
7606         }
7607         http_d_type = 0;
7608         x = (http_close() == 0);
7609     }
7610     if ((http_action != HTTP_CLS) &&
7611         (http_action != HTTP_CON) && http_rfile) { /* Remote file is URL? */
7612
7613         /* All-in-one actions when a URL is given... */
7614
7615 #ifdef CK_URL
7616         if (urlparse(http_rfile,&http_url) > 0) { /* Have URL? */
7617             if (ckstrcmp(http_url.svc,"http",-1,0) && /* It's an HTTP URL? */
7618                 ckstrcmp(http_url.svc,"https",-1,0)) {
7619                 printf("?Non-HTTP URL\n");
7620                 x = -9;
7621                 goto xhttp;
7622             } else {                    /* Yes, collect the pieces */
7623                 makestr(&http_srv, http_url.svc);
7624                 makestr(&http_user,http_url.usr);
7625                 makestr(&http_pass,http_url.psw);
7626                 makestr(&http_host,http_url.hos);
7627                 if (http_url.por)
7628                   makestr(&http_srv,http_url.por);
7629                 makestr(&http_rfile,http_url.pth);
7630             }
7631             if (!http_rfile) {          /* Still have a path? */
7632                 makestr(&http_rfile,"/");
7633             }
7634             if (!ckstrcmp("https",http_srv,-1,0) || /* Check for SSL/TLS */
7635                 !ckstrcmp("443",http_srv,-1,0))
7636               http_ssl = 1;
7637             if (http_isconnected())     /* Close any open HTTP connection */
7638               http_close();
7639             if (http_pass == NULL && http_d_pass != NULL)
7640               makestr(&http_pass,http_d_pass);
7641             x = (http_open(http_host,
7642                            http_srv,http_ssl,rdns,128,http_d_agent) == 0);
7643             if (x < 0) {
7644                 x = 0;
7645                 goto xhttp;
7646             }
7647             allinone = 1;
7648         }
7649 #endif /* CK_URL */
7650         if (http_pass == NULL && http_d_pass != NULL)
7651           makestr(&http_pass,http_d_pass);
7652
7653         if (http_action == HTTP_OPN && allinone) {
7654             http_action = HTTP_GET;
7655         }
7656         x = xdohttp(http_action,
7657                     http_lfile,
7658                     http_rfile,
7659                     http_dfile,
7660                     http_agent ? http_agent : http_d_agent,
7661                     http_hdr,
7662                     http_user  ? http_user  : http_d_user,
7663                     http_pass  ? http_pass  : http_d_pass,
7664                     http_mime,
7665                     http_array,
7666                     http_type
7667                     );
7668         if (allinone)
7669           x = (http_close() == 0);
7670     }
7671
7672   xhttp:
7673     if (http_agent) free(http_agent);
7674     if (http_hdr)   free(http_hdr);
7675     if (http_user)  free(http_user);
7676     if (http_pass) {
7677         memset(http_pass,0,strlen(http_pass));
7678         free(http_pass);
7679     }
7680     if (http_mime)  free(http_mime);
7681     if (http_lfile) free(http_lfile);
7682     if (http_rfile) free(http_rfile);
7683     if (http_dfile) free(http_dfile);
7684     if (http_host)  free(http_host);
7685     if (http_srv)   free(http_srv);
7686
7687     if (x > -1)
7688       success = x;
7689     return(x);
7690 }
7691 #endif /* TCPSOCKET */
7692 #endif /* NOHTTP */
7693
7694
7695 #ifndef NOSPL
7696 static int
7697 dotrace() {
7698     int on = 1;
7699     struct FDB sw, kw;
7700     cmfdbi(&sw,                         /* 1st FDB - switch */
7701            _CMKEY,                      /* fcode */
7702            "Trace object;\n Or switch", /* help */
7703            "",                          /* default */
7704            "",                          /* addtl string data */
7705            2,                           /* keyword table size */
7706            4,                           /* addtl numeric data 2: 4 = cmswi */
7707            xxstring,                    /* Processing function */
7708            onoffsw,                     /* Keyword table */
7709            &kw                          /* Pointer to next FDB */
7710            );
7711     cmfdbi(&kw,                         /* 2nd FDB - Trace object */
7712            _CMKEY,                      /* fcode */
7713            "Trace object",              /* help */
7714            "all",                       /* default */
7715            "",                          /* addtl string data */
7716            ntracetab,                   /* keyword table size */
7717            0,                           /* addtl numeric data 2: 0 = keyword */
7718            xxstring,                    /* Processing function */
7719            tracetab,                    /* Keyword table */
7720            NULL                         /* Pointer to next FDB */
7721            );
7722     if ((x = cmfdb(&sw)) < 0)
7723       return(x);
7724     if (cmresult.fdbaddr == &sw) {
7725         on = cmresult.nresult;
7726         if ((x = cmkey(tracetab, ntracetab,"","all",xxstring)) < 0)
7727           return(x);
7728     } else {
7729         x = cmresult.nresult;
7730     }
7731     if ((y = cmcfm()) < 0)
7732       return(y);
7733
7734     switch (x) {
7735       case TRA_ASG:
7736         tra_asg = on;
7737         break;
7738       case TRA_CMD:
7739         tra_cmd = on;
7740         break;
7741       case TRA_ALL:
7742         tra_asg = on;
7743         tra_cmd = on;
7744         break;
7745       default:
7746         return(-2);
7747     }
7748     printf("TRACE %s\n", on ? "ON" : "OFF");
7749     return(success = 1);
7750 }
7751 #endif /* NOSPL */
7752
7753
7754 static int
7755 doprompt() {
7756     extern int xcmdsrc;
7757     if ((x = cmtxt("Optional message","",&s,xxstring)) < 0)
7758       return(x);
7759 #ifdef NOSPL
7760     printf("?Sorry, PROMPT requires script programming language\n");
7761     return(-9);
7762 #else
7763     debug(F101,"Prompt cmdlvl","",cmdlvl);
7764     cmdlvl++;
7765     if (cmdlvl > CMDSTKL) {
7766         printf("?Command stack overflow: %d\n",cmdlvl);
7767         cmdlvl--;
7768         return(-9);
7769     }
7770     xcmdsrc = CMD_KB;
7771     cmdstk[cmdlvl].src = CMD_KB;        /* Say we're at the prompt */
7772     cmdstk[cmdlvl].lvl = 0;
7773     cmdstk[cmdlvl].ccflgs = cmdstk[cmdlvl-1].ccflgs;
7774     if (tra_cmd)
7775       printf("[%d] +P: \"(prompt)\"\n",cmdlvl);
7776     concb((char)escape);
7777     if (!quiet)
7778       printf(
7779 "(Recursive command prompt: Resume script with CONTINUE, STOP to stop...)\n"
7780             );
7781     if (*s) {                           /* If prompt given */
7782         makestr(&(prstring[cmdlvl-1]),cmgetp()); /* Save current prompt */
7783         cmsetp(s);                      /* Set new one */
7784     }
7785     return(success = 1);
7786 #endif /* NOSPL */
7787 }
7788
7789 #ifdef CKLEARN
7790 VOID
7791 learncmd(s) char *s; {                  /* Record commands in learned script */
7792     char buf[64];
7793     int i, k;
7794     if (learnfp && learning) {          /* Only if open and on */
7795         k = ckstrncpy(buf,s,64);
7796         for (i = 0; i < k; i++) {       /* Get top-level command keyword */
7797             if (buf[i] <= SP) {
7798                 buf[i] = NUL;
7799                 break;
7800             }
7801         }
7802         k = lookup(cmdtab,buf,ncmd,NULL); /* Look it up */
7803         if (k == XXCON || k == XXLEARN)   /* Don't record CONNECT or LEARN */
7804           return;
7805         if (k == XXTEL) {
7806             fputs("SET HOST /NETWORK:TCP",learnfp);
7807             fputs(&s[i],learnfp);
7808             fputs(" TELNET /TELNET",learnfp);
7809             fputs("\nIF FAIL STOP 1 Connection failed\n",learnfp);
7810         } else {
7811             fputs(s,learnfp);
7812             fputs("\n",learnfp);
7813         }
7814     }
7815 }
7816 #endif /* CKLEARN */
7817
7818
7819 #ifdef SSHCMD
7820 /*
7821   2010/03/01...
7822   Reopen a connection that was made with an external ssh client
7823   after it has been closed.
7824  */
7825 int
7826 redossh() {
7827     int x, netsave;
7828     x = nettype;
7829     debug(F111,"redossh nettype",ttname,nettype);
7830     if ((y = setlin(XXSSH,0,1)) < 0) {
7831         if (errno)
7832           printf("?%s\n",ck_errstr());
7833         else
7834           return(y);
7835         nettype = x;                    /* Failed, restore net type. */
7836         success = 0;
7837         return(y);
7838     }
7839     netsave = x;
7840     return(y);
7841 }
7842 #endif  /* SSHCMD */
7843
7844 /*
7845   Like hmsga() in ckuus2.c but takes a single substitution parameter, s2,
7846   which replaces every occurrence of "%s" in the first argument.
7847   Added to print text containing the copyright year, so the year doesn't 
7848   have to be hardwired into lots of scattered text strings.
7849 */
7850 int                                     /* Print an array of lines, */
7851 #ifdef CK_ANSIC
7852 hmsgaa(char *s[], char *s2)             /* pausing at end of each screen. */
7853 #else
7854 hmsgaa(s,s2) char *s[]; char *s2;
7855 #endif  /* CK_ANSIC */
7856 {
7857     extern int hmtopline;
7858 #ifdef OS2
7859     extern int tt_rows[], tt_cols[];
7860 #else /* OS2 */
7861     extern int tt_rows, tt_cols;
7862 #endif /* OS2 */
7863     int x, y, i, j, k, n;
7864     if ((x = cmcfm()) < 0) return(x);
7865
7866 #ifdef CK_TTGWSIZ
7867 #ifdef OS2
7868     ttgcwsz();
7869 #else /* OS2 */
7870     /* Check whether window size changed */
7871     if (ttgwsiz() > 0) {
7872         if (tt_rows > 0 && tt_cols > 0) {
7873             cmd_rows = tt_rows;
7874             cmd_cols = tt_cols;
7875         }
7876     }
7877 #endif /* OS2 */
7878 #endif /* CK_TTGWSIZ */
7879
7880     printf("\n");                       /* Start off with a blank line */
7881     n = (hmtopline > 0) ? hmtopline : 1; /* Line counter */
7882     for (i = 0; *s[i]; i++) {
7883         printf((char *)s[i],s2);        /* Print a line. */
7884         printf("\n");
7885         y = (int)strlen(s[i]);
7886         k = 1;
7887         for (j = 0; j < y; j++)         /* See how many newlines were */
7888           if (s[i][j] == '\n') k++;     /* in the string... */
7889         n += k;
7890         if (n > (cmd_rows - 3) && *s[i+1]) /* After a screenful, give them */
7891           if (!askmore()) return(0);    /* a "more?" prompt. */
7892           else n = 0;
7893     }
7894     printf("\n");
7895     return(0);
7896 }
7897
7898 /*  D O C M D  --  Do a command  */
7899
7900 /*
7901  Returns:
7902    -2: user typed an illegal command
7903    -1: reparse needed
7904     0: parse was successful (even tho command may have failed).
7905 */
7906 #ifdef DEBUG
7907 int cmdstats[256] = { -1, -1 };
7908 #endif /* DEBUG */
7909
7910 int
7911 docmd(cx) int cx; {
7912     extern int nolocal, cmkwflgs;
7913
7914     debug(F101,"docmd entry, cx","",cx);
7915     activecmd = cx;
7916     doconx = ((activecmd == XXCON)  || (activecmd == XXTEL) ||
7917               (activecmd == XXRLOG) || (activecmd == XXPIPE) ||
7918               (activecmd == XXIKSD) || (activecmd == XXPTY));
7919 /*
7920   Originally all commands were handled with a big switch() statement,
7921   but eventually this started blowing up compilers.  Now we have a series
7922   of separate if statements and small switches, with the commands that are
7923   most commonly executed in scipts and loops coming first, to speed up
7924   compute-bound scripts.
7925   */
7926
7927 #ifdef DEBUG
7928     if (cmdstats[0] == -1) {            /* Count commands */
7929         int i;                          /* for tuning... */
7930         for (i = 0; i < 256; i++)
7931           cmdstats[i] = 0;
7932     }
7933 #endif /* DEBUG */
7934
7935     switch (cx) {
7936       case -4:                          /* EOF */
7937 #ifdef OSK
7938         if (msgflg)  printf("\n");
7939 #else
7940         if (msgflg)  printf("\r\n");
7941 #endif /* OSK */
7942           doexit(GOOD_EXIT,xitsta);
7943       case -3:                          /* Null command */
7944         return(0);
7945       case -9:                          /* Like -2, but errmsg already done */
7946       case -1:                          /* Reparse needed */
7947         return(cx);
7948       case -6:                          /* Special */
7949       case -2:                          /* Error, maybe */
7950
7951 #ifndef NOSPL
7952 /*
7953   Maybe they typed a macro name.  Let's look it up and see.
7954 */
7955         if (cx == -6)                   /* If they typed CR */
7956           ckstrncat(cmdbuf,"\015",CMDBL); /*  add it back to command buffer. */
7957         if (ifcmd[cmdlvl] == 2)         /* Watch out for IF commands. */
7958           ifcmd[cmdlvl]--;
7959         repars = 1;                     /* Force reparse */
7960         cmres();
7961         cx = XXDO;                      /* Try DO command */
7962 #else
7963         return(cx);
7964 #endif /* NOSPL */
7965       default:
7966         if (cx < 0)
7967           return(cx);
7968         break;
7969     }
7970 #ifdef DEBUG
7971     if (cx < 256)
7972       cmdstats[cx]++;
7973 #endif /* DEBUG */
7974
7975     if ((cmkwflgs & CM_PSH)
7976 #ifndef NOPUSH
7977         && nopush
7978 #endif /* NOPUSH */
7979         ) {
7980         printf("?Access to system disabled\n");
7981         return(-9);
7982     }
7983     if ((cmkwflgs & CM_LOC)
7984 #ifndef NOLOCAL
7985         && nolocal
7986 #endif /* NOLOCAL */
7987         ) {
7988         printf("?Connections disabled\n");
7989         return(-9);
7990     }
7991
7992 #ifndef NOSPL
7993     /* Used in FOR loops */
7994
7995     if (cx == XX_INCR || cx == XXINC  || /* _INCREMENT, INCREMENT */
7996         cx == XX_DECR || cx == XXDEC)    /* _DECREMENT, DECREMENT */
7997       return(doincr(cx));
7998
7999     /* Define (or change the definition of) a macro or variable */
8000
8001     if (cx == XXUNDEF || cx == XXUNDFX) {
8002 #ifdef IKSD
8003         if (inserver && !ENABLED(en_asg)) {
8004             printf("?Sorry, DEFINE/ASSIGN disabled\n");
8005             return(-9);
8006         }
8007 #endif /* IKSD */
8008         return(doundef(cx));            /* [_]UNDEFINE */
8009     }
8010     if (cx == XXDEF || cx == XXASS ||
8011         cx == XXDFX || cx == XXASX) {
8012 #ifdef IKSD
8013         if (inserver && !ENABLED(en_asg)) {
8014             printf("?Sorry, DEFINE/ASSIGN disabled\n");
8015             return(-9);
8016         }
8017 #endif /* IKSD */
8018         if (atmbuf[0] == '.' && !atmbuf[1]) /* "." entered as keyword */
8019           xxdot = 1;                    /* i.e. with space after it... */
8020         return(dodef(cx));              /* DEFINE, ASSIGN, etc... */
8021     }
8022
8023     /* IF, WHILE, and friends  */
8024
8025     if (cx == XXIF || cx == XXIFX || cx == XXWHI || cx == XXASSER) {
8026         return(doif(cx));
8027     }
8028     if (cx == XXSWIT) {                 /* SWITCH */
8029         return(doswitch());
8030     }
8031
8032     /* GOTO, FORWARD, and _FORWARD (used internally by FOR, WHILE, etc) */
8033
8034     if (cx == XXGOTO || cx == XXFWD || cx == XXXFWD) { /* GOTO or FORWARD */
8035         /* Note, here we don't set SUCCESS/FAILURE flag */
8036 #ifdef COMMENT
8037         if ((y = cmfld("label","",&s,xxstring)) < 0) {
8038             if (y == -3) {
8039                 if (cx != XXXFWD) {
8040                     printf("?Label name required\n");
8041                     return(-9);
8042                 }
8043             } else
8044               return(y);
8045         }
8046         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
8047         if ((x = cmcfm()) < 0) return(x);
8048 #else
8049         if ((y = cmtxt("label","",&s,xxstring)) < 0) {
8050             if (y == -3) {
8051                 if (cx != XXXFWD) {
8052                     printf("?GOTO: Label name required: \"%s\" \"%s\"\n",
8053                            atmbuf,
8054                            cmdbuf);
8055                     return(-9);
8056                 }
8057             } else
8058               return(y);
8059         }
8060         ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
8061 #endif /* COMMENT */
8062         s = tmpbuf;
8063         debug(F111,"GOTO target",s,cx);
8064         return(dogoto(s,cx));
8065     }
8066     if (cx == XXDO || cx == XXMACRO) {  /* DO (a macro) */
8067         char mnamebuf[16];              /* (buffer for controlled temp name) */
8068         struct FDB kw, fl;
8069         int mx;                         /* Macro index (on stack!) */
8070
8071         debug(F101,"XXMACRO 0",line,cx);
8072         if (cx == XXDO) {
8073             if (nmac == 0) {
8074                 printf("\n?No macros defined\n");
8075                 return(-9);
8076             }
8077             for (y = 0; y < nmac; y++) { /* copy the macro table into a */
8078                 mackey[y].kwd = mactab[y].kwd; /* regular keyword table */
8079                 mackey[y].kwval = y;    /* with value = pointer to macro tbl */
8080                 mackey[y].flgs = mactab[y].flgs;
8081             }
8082             cmfdbi(&kw,                 /* First FDB - macro name */
8083                    _CMKEY,              /* fcode */
8084                    "Macro",             /* hlpmsg */
8085                    "",                  /* default */
8086                    "",                  /* addtl string data */
8087                    nmac,                /* addtl numeric data 1: tbl size */
8088                    0,                   /* addtl numeric data 2: 0 = cmkey */
8089                    xxstring,            /* Processing function */
8090                    mackey,              /* Keyword table */
8091                    &fl                  /* Pointer to next FDB */
8092                    );
8093             cmfdbi(&fl,                 /* 2nd FDB - for "{" */
8094                    _CMFLD,              /* fcode */
8095                    "",                  /* hlpmsg */
8096                    "",
8097                    "",                  /* addtl string data */
8098                    0,                   /* addtl numeric data 1 */
8099                    0,                   /* addtl numeric data 2 */
8100                    xxstring,
8101                    NULL,
8102                    NULL
8103                    );
8104             x = cmfdb(&kw);             /* Parse something */
8105             if (x < 0) {                /* Error */
8106                 if (x == -3) {
8107                     printf("?Macro name required\n");
8108                     return(-9);
8109                 } else
8110                   return(x);
8111             }
8112             if (cmresult.fcode == _CMKEY) {
8113                 extern int mtchanged;
8114                 char * macroname = NULL;
8115
8116             /* In case args include an \fexec() that changes the macro table */
8117
8118                 mx = x;                 /* Save macro index on stack */
8119                 mtchanged = 0;          /* Mark state of macro table */
8120                 makestr(&macroname,mactab[mx].kwd); /* Save name */
8121
8122                 if ((y = cmtxt("optional arguments","",&s,xxstring)) < 0)
8123                   return(y);            /* Get macro args */
8124
8125                 if (mtchanged) {        /* Macro table changed? */
8126                     mx = mlook(mactab,macroname,nmac); /* Look up name again */
8127                 }
8128                 if (macroname)
8129                   free(macroname);
8130
8131                 return(dodo(mx,s,cmdstk[cmdlvl].ccflgs) < 1 ?
8132                        (success = 0) : 1);
8133             }
8134             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* _CMFLD */
8135             if (atmbuf[0] == '{') {
8136                 if ((y = cmcfm()) < 0)
8137                   return(y);
8138             }
8139         } else {                        /* XXMACRO ("immediate macro") */
8140             int k = 0;
8141             line[k++] = '{';
8142             line[k++] = SP;
8143             line[k] = NUL;
8144             debug(F111,"XXMACRO A",line,k);
8145             if ((y = cmtxt("Braced list of commands","",&s,xxstring)) < 0)
8146               return(y);
8147             k = ckstrncpy(line+k,s,LINBUFSIZ-k);
8148             debug(F111,"XXMACRO B",line,k);
8149         }
8150         x = strlen(line);
8151         if ((line[0] == '{' && line[x-1] != '}') || line[0] == '}')
8152           return(-2);
8153         if (line[0] != '{' && line[x-1] != '}') {
8154             /* Unknown command.  If ON_UNKNOWN_COMMAND macro is defined, */
8155             /* parse args and then execute it, but only if it is not */
8156             /* already active. */
8157             int k = -1;
8158             if (!unkmacro) {
8159                 k = mxlook(mactab,"on_unknown_command",nmac);
8160             }
8161             if (k > -1) {
8162                 ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
8163                 z = maclvl;             /* Save the current maclvl */
8164                 if ((y = cmtxt("text","",&s,xxstring)) < 0)
8165                   return(y);
8166                 ckstrncat(tmpbuf," ",TMPBUFSIZ);
8167                 ckstrncat(tmpbuf,s,TMPBUFSIZ);
8168                 unkmacro = 1;
8169                 debug(F110,"ON_UNKNOWN_COMMAND",s,0);
8170                 dodo(k,tmpbuf,cmdstk[cmdlvl].ccflgs); /* Run the macro */
8171                 while (maclvl > z) {
8172                     sstate = (CHAR) parser(1);
8173                     if (sstate) proto();
8174                 }
8175                 debug(F101,"UNKMAC loop exit maclvl","",maclvl);
8176                 unkmacro = 0;
8177                 return(success);
8178             }
8179             if (x > 0)
8180               printf("?Not a command or macro name: \"%s\"\n",line);
8181             else
8182               printf("?Not a command or macro name.\n");
8183             return(-9);
8184         }
8185         s = brstrip(line);
8186         sprintf(mnamebuf," ..tmp:%03d",cmdlvl); /* safe (16) */
8187         x = addmac(mnamebuf,s);
8188         return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs) < 1 ? (success = 0) : 1);
8189     }
8190
8191     if (cx == XXLBL) {                  /* LABEL */
8192         if ((x = cmfld("label","",&s,xxstring)) < 0) {
8193             if (x == -3) {
8194 #ifdef COMMENT
8195                 printf("?LABEL: Label name required: \"%s\"\n", cmdbuf);
8196                 return(-9);
8197 #else
8198                 s = "";
8199 #endif /* COMMENT */
8200             } else return(x);
8201
8202         }
8203         debug(F111,"LABEL",s,x);
8204         if ((x = cmcfm()) < 0) return(x);
8205         return(0);
8206     }
8207
8208     if (cx == XXEVAL || cx == XX_EVAL) /* _EVALUATE,  EVALUATE  */
8209       return(doeval(cx));
8210
8211 #ifndef NOSEXP
8212     if (cx == XXSEXP) {                 /* Lisp-like S-Expression */
8213         struct stringarray * q;
8214         char /* *p, *r, */ *tmp, *m;
8215         int i, k, n, quote = 0, contd = 0, size = 0, len = 0;
8216         extern int sexprc, sexppv;
8217
8218         tmp = tmpbuf;                   /* Buffer to collect SEXP */
8219         tmpbuf[0] = NUL;                /* Clear it */
8220         size = TMPBUFSIZ;               /* Capacity of buffer */
8221         sexprc = -1;                    /* Assume bad input */
8222         n = 0;                          /* Paren balance counter */
8223
8224         while (1) {                     /* Allow SEXP on multiple lines */
8225             m = contd ?
8226               "Continuation of S-Expression" :
8227                 "S-Expression (\"help sexp\" for details)";
8228             x = cmtxt(m,"",&s,xxstring);
8229             if (x < 0)
8230               return(x);
8231             if (!*s)                    /* Needed for (=) and (:) */
8232               s = cmdbuf+1;             /* I can't explain why. */
8233             k = ckmakmsg(tmp, size, contd ? " " : "(", s, NULL, NULL);
8234             if (k < 1) {
8235                 printf("?SEXP too long - %d max\n",TMPBUFSIZ);
8236                 return(-9);
8237             }
8238             debug(F111,contd ? "sexp contd" : "sexp",s,k);
8239
8240             for (i = len; i < len+k; i++) { /* Check balance  */
8241                 if (!quote && tmpbuf[i] == CMDQ) {
8242                     quote = 1;
8243                     continue;
8244                 }
8245                 if (quote) {
8246                     quote = 0;
8247                     continue;
8248                 }
8249                 if (tmpbuf[i] == '(')
8250                   n++;
8251                 else if (tmpbuf[i] == ')')
8252                   n--;
8253             }
8254             if (n == 0) {               /* Break when balanced */
8255                 break;
8256             }
8257             if (n < 0) {                /* Too many right parens */
8258                 printf("?Unbalanced S-Expression: \"%s\"\n",tmpbuf);
8259                 return(-9);
8260             }
8261             contd++;                    /* Need more right parens */
8262             cmini(ckxech);              /* so keep parsing */
8263             tmp += k;                   /* adjust buffer pointer */
8264             size -= k;                  /* and capacity */
8265             len += k;                   /* and length so far */
8266         }
8267         s = tmpbuf;
8268         makestr(&lastsexp,s);
8269         q = cksplit(1,SEXPMAX,s,NULL,NULL,8,0,0); /* Precheck for > 1 SEXP */
8270         debug(F101,"sexp split","",q->a_size);
8271
8272         if (q->a_size == 1) {           /* We should get exactly one back */
8273             char * result, * dosexp();
8274             sexprc = 0;                 /* Reset out-of-band return code */
8275             result = dosexp(s);         /* Get result */
8276             debug(F111,"sexp result",result,sexprc);
8277             if (sexprc == 0) {          /* Success */
8278                 /* Echo the result if desired */
8279                 if ((!xcmdsrc && sexpecho != SET_OFF) || sexpecho == SET_ON)
8280                   printf(" %s\n",result ? result : "");
8281                 makestr(&sexpval,result);
8282                 success = sexppv > -1 ? sexppv : 1;
8283                 return(success);
8284             }
8285         }
8286         if (sexprc < 0)
8287           printf("?Invalid S-Expression: \"%s\"\n",lastsexp);
8288         return(-9);
8289     }
8290 #endif /* NOSEXP */
8291
8292 #endif /* NOSPL */
8293
8294     if (cx == XXECH || cx == XXXECH || cx == XXVOID
8295 #ifndef NOSPL
8296         || cx == XXAPC
8297 #endif /* NOSPL */
8298         ) {                             /* ECHO or APC */
8299         if ((x = cmtxt((cx == XXECH || cx == XXXECH) ?
8300                        "Text to be echoed" :
8301                        ((cx == XXVOID) ? "Text" :
8302                         "Application Program Command text"),
8303                        "",
8304                        &s,
8305                        xxstring
8306                        )
8307              ) < 0)
8308           return(x);
8309         if (!s) s = "";
8310 #ifdef COMMENT
8311 /* This is to preserve the pre-8.0 behavior but it's too confusing */
8312         x = strlen(s);
8313         x = (x > 1) ? ((s[0] == '"' && s[x-1] == '"') ? 1 : 0) : 0;
8314 #endif /* COMMENT */
8315         s = brstrip(s);                 /* Strip braces and doublequotes */
8316         if (cx == XXECH) {              /* ECHO */
8317 #ifndef NOSPL
8318             if (!fndiags || fnsuccess) {
8319 #endif /* NOSPL */
8320 #ifdef COMMENT
8321                 /* The "if (x)" business preserves previous behavior */
8322                 /* by putting back the doublequotes if they were included. */
8323                 if (x)
8324                   printf("\"%s\"\n",s);
8325                 else
8326 #endif /* COMMENT */
8327                   printf("%s\n",s);
8328 #ifndef NOSPL
8329             }
8330 #endif /* NOSPL */
8331         } else if (cx == XXXECH) {      /* XECHO */
8332             if (x)
8333               printf("\"%s\"",s);
8334             else
8335               printf("%s",s);
8336 #ifdef UNIX
8337             fflush(stdout);
8338 #endif /* UNIX */
8339         } else if (cx == XXAPC) {       /* APC */
8340 #ifdef CK_APC
8341             if (apcactive == APC_LOCAL ||
8342                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
8343               return(success = 0);
8344 #endif /* CK_APC */
8345             if (!local) {
8346                 printf("%c_%s%c\\",ESC,s,ESC);
8347 #ifdef UNIX
8348                 fflush(stdout);
8349 #endif /* UNIX */
8350
8351             } else {                    /* Local mode - have connection */
8352 #ifndef NOSPL
8353                 if (ckmakxmsg(tmpbuf,   /* Form APC string in buffer */
8354                               TMPBUFSIZ,
8355                               ckctoa((char)ESC),
8356                               ckctoa('_'),
8357                               s,
8358                               ckctoa((char)ESC),
8359                               ckctoa('\\'),
8360                               NULL,NULL,NULL,NULL,NULL,NULL,NULL
8361                               ) > 0)
8362                   return(success = dooutput(tmpbuf, XXOUT));
8363                 printf("?Too long\n");
8364                 return(-9);
8365 #else
8366                 printf("%c_%s%c\\",ESC,s,ESC);
8367 #endif /* NOSPL */
8368             }
8369         }
8370         return(success = 1);
8371     }
8372
8373 #ifndef NOSPL
8374 /* Copy macro args from/to two levels up, used internally by _floop et al. */
8375     if (cx == XXGTA || cx == XXPTA) {   /* _GETARGS, _PUTARGS */
8376         int x;
8377         debug(F101,"docmd XXGTA","",XXGTA);
8378         debug(F101,"docmd cx","",cx);
8379         debug(F101,"docmd XXGTA maclvl","",maclvl);
8380         x = dogta(cx);
8381         debug(F101,"docmd dogta returns","",x);
8382         debug(F101,"docmd dogta maclvl","",maclvl);
8383         return(x);
8384     }
8385 #endif /* NOSPL */
8386
8387 #ifndef NOSPL
8388 #ifdef CKCHANNELIO
8389     if (cx == XXFILE)
8390       return(dofile(cx));
8391     else if (cx == XXF_RE || cx == XXF_WR || cx == XXF_OP ||
8392              cx == XXF_CL || cx == XXF_SE || cx == XXF_RW ||
8393              cx == XXF_FL || cx == XXF_LI || cx == XXF_ST || cx == XXF_CO)
8394       return(dofile(cx));
8395 #endif /* CKCHANNELIO */
8396
8397 /* ASK, ASKQ, READ */
8398     if (cx == XXASK  || cx == XXASKQ || cx == XXREA ||
8399         cx == XXRDBL || cx == XXGETC || cx == XXGETK) {
8400         return(doask(cx));
8401     }
8402 #endif /* NOSPL */
8403
8404 #ifndef NOFRILLS
8405 #ifndef NOHELP
8406     if (cx == XXBUG) {                  /* BUG */
8407         if ((x = cmcfm()) < 0) return(x);
8408         return(dobug());
8409     }
8410 #endif  /* NOHELP */
8411 #endif  /* NOFRILLS */
8412
8413 #ifndef NOXFER
8414     if (cx == XXBYE) {                  /* BYE */
8415         extern int ftp_cmdlin;
8416         if ((x = cmcfm()) < 0) return(x);
8417
8418 #ifdef NEWFTP
8419         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
8420             extern int stayflg, ftp_fai;
8421             success = ftpbye();
8422             if (ftp_cmdlin && !stayflg && !local)
8423               doexit(ftp_fai ? BAD_EXIT : GOOD_EXIT,-1);
8424             else
8425               return(success);
8426         }
8427 #endif /* NEWFTP */
8428
8429         if (!local) {
8430             printf("?No connection - use EXIT to quit.\n");
8431             return(-9);
8432         }
8433
8434 #ifdef CK_XYZ
8435         if (protocol != PROTO_K) {
8436             printf("?Sorry, BYE only works with Kermit protocol\n");
8437             return(-9);
8438         }
8439 #endif /* CK_XYZ */
8440
8441 #ifdef IKS_OPTION
8442         if (
8443 #ifdef CK_XYZ
8444             protocol == PROTO_K &&
8445 #endif /* CK_XYZ */
8446             !iks_wait(KERMIT_REQ_START,1)) {
8447             printf(
8448              "?A Kermit Server is not available to process this command\n");
8449             return(-9);                 /* Correct the return code */
8450         }
8451 #endif /* IKS_OPTION */
8452
8453         bye_active = 1;
8454         sstate = setgen('L',"","","");
8455         if (local) ttflui();            /* If local, flush tty input buffer */
8456         return(0);
8457     }
8458 #endif /* NOXFER */
8459
8460     if (cx == XXBEEP) {                 /* BEEP */
8461         int x;
8462 #ifdef OS2
8463         int y;
8464         if ((y = cmkey(beeptab, nbeeptab, "which kind of beep", "information",
8465                        xxstring)) < 0 )
8466           return (y);
8467         if ((x = cmcfm()) < 0) return(x);
8468         bleep((short)y);                /* y is one of the BP_ values */
8469 #else  /* OS2 */
8470         if ((x = cmcfm()) < 0) return(x);
8471 #ifndef NOSPL
8472         bleep(BP_NOTE);
8473 #else
8474         putchar('\07');
8475 #endif /* NOSPL */
8476 #endif /* OS2 */
8477         return(0);
8478     }
8479
8480 #ifndef NOFRILLS
8481     if (cx == XXCLE)                    /* CLEAR */
8482       return(success = doclear());
8483 #endif /* NOFRILLS */
8484
8485     if (cx == XXCOM) {                  /* COMMENT */
8486         if ((x = cmtxt("Text of comment line","",&s,NULL)) < 0)
8487           return(x);
8488         /* Don't change SUCCESS flag for this one */
8489         return(0);
8490     }
8491
8492 #ifndef NOLOCAL
8493     if (cx == XXCON || cx == XXCQ)      /* CONNECT or CONNECT /QUIETLY */
8494       return(doxconn(cx));
8495 #endif /* NOLOCAL */
8496
8497 #ifndef NOFRILLS
8498 #ifdef ZCOPY
8499     if (cx == XXCPY) {                  /* COPY a file */
8500 #ifdef IKSD
8501         if (inserver && !ENABLED(en_cpy)) {
8502             printf("?Sorry, COPY is disabled\n");
8503             return(-9);
8504         }
8505 #endif /* IKSD */
8506 #ifdef CK_APC
8507         if (apcactive == APC_LOCAL ||
8508             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
8509             )
8510           return(success = 0);
8511 #endif /* CK_APC */
8512         return(docopy());
8513     }
8514 #endif /* ZCOPY */
8515 #ifdef NT
8516     if ( cx == XXLINK ) {
8517 #ifdef IKSD
8518         if (inserver && !ENABLED(en_cpy)) {
8519             printf("?Sorry, LINK (COPY) is disabled\n");
8520             return(-9);
8521         }
8522 #endif /* IKSD */
8523 #ifdef CK_APC
8524         if (apcactive == APC_LOCAL ||
8525             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
8526             )
8527           return(success = 0);
8528 #endif /* CK_APC */
8529         return(dolink());
8530     }
8531 #endif /* NT */
8532 #endif /* NOFRILLS */
8533
8534     /* CD and friends */
8535     if (cx == XXCWD  || cx == XXCDUP || cx == XXBACK ||
8536         cx == XXLCWD || cx == XXLCDU || cx == XXKCD) {
8537 #ifdef LOCUS
8538         if (!locus) {
8539             if (cx == XXCWD) {
8540 #ifdef NOXFER
8541                 return(-2);
8542 #else
8543                 return(dormt(XZCWD));
8544 #endif /* NOXFER */
8545             } else if (cx == XXCDUP) {
8546 #ifdef NOXFER
8547                 return(-2);
8548 #else
8549                 return(dormt(XZCDU));
8550 #endif /* NOXFER */
8551             }
8552         }
8553 #endif /* LOCUS */
8554 #ifdef IKSD
8555         if (inserver && !ENABLED(en_cwd)) {
8556             printf("?Sorry, changing directories is disabled\n");
8557             return(-9);
8558         }
8559 #endif /* IKSD */
8560         return(success = docd(cx));
8561     }
8562
8563     if (cx == XXCHK)                    /* CHECK */
8564       return(success = dochk());
8565
8566     if (cx == XXCLO) {                  /* CLOSE */
8567         x = cmkey(clstab,ncls,"\"CONNECTION\", or log or file to close",
8568                   "connection",xxstring);
8569         if (x == -3) {
8570             printf("?You must say which file or log\n");
8571             return(-9);
8572         }
8573         if (x < 0) return(x);
8574         if ((y = cmcfm()) < 0) return(y);
8575 #ifndef NOLOCAL
8576         if (x == 9999) {                /* CLOSE CONNECTION */
8577             x = clsconnx(0);
8578             switch (x) {
8579               case 0:
8580                 if (msgflg) printf("?Connection was not open\n");
8581               case -1:
8582                 return(0);
8583               case 1:
8584                 whyclosed = WC_CLOS;
8585                 return(1);
8586             }
8587             return(0);
8588         }
8589 #endif /* NOLOCAL */
8590         y = doclslog(x);
8591         success = (y == 1);
8592         return(success);
8593     }
8594
8595 #ifndef NOSPL
8596     if (cx == XXDCL || cx == XXUNDCL) { /* DECLARE an array */
8597         return(dodcl(cx));
8598     }
8599 #endif /* NOSPL */
8600
8601 #ifndef NODIAL
8602     if (cx == XXRED  || cx == XXDIAL || cx == XXPDIA ||
8603         cx == XXANSW || cx == XXLOOK) { /* DIAL, REDIAL etc */
8604 #ifdef VMS
8605         extern int batch;
8606 #else
8607 #ifdef UNIXOROSK
8608         extern int backgrd;
8609 #endif /* UNIXOROSK */
8610 #endif /* VMS */
8611         x = dodial(cx);
8612         debug(F101,"dodial returns","",x);
8613         if ((cx == XXDIAL || cx == XXRED || cx == XXANSW) &&
8614             (x > 0) &&                  /* If DIAL or REDIAL succeeded */
8615             (dialsta != DIA_PART) &&    /* and it wasn't partial */
8616             (dialcon > 0)) {
8617             if ((dialcon == 1 ||        /* And DIAL CONNECT is ON, */
8618                 ((dialcon == 2) &&      /* or DIAL CONNECT is AUTO */
8619                  !xcmdsrc               /* and we're at top level... */
8620 #ifdef VMS
8621                  && !batch              /* Not if running from batch */
8622 #else
8623 #ifdef UNIXOROSK
8624                  && !backgrd            /* Not if running in background */
8625 #endif /* UNIXOROSK */
8626 #endif /* VMS */
8627                  ))) /* Or AUTO */
8628               x = doconect(dialcq,      /* Then also CONNECT */
8629                            cmdlvl == 0 ? 1 : 0
8630                            );
8631             if (ttchk() < 0)
8632               dologend();
8633         }
8634         return(success = x);
8635     }
8636 #endif /* NODIAL */
8637
8638 #ifndef NOPUSH
8639 #ifdef CK_REXX
8640     if (cx == XXREXX) {                 /* REXX */
8641         extern int nopush;
8642         if ( nopush )
8643           return(success=0);
8644         return(dorexx());
8645     }
8646 #endif /* CK_REXX */
8647 #endif /* NOPUSH */
8648
8649 #ifndef NOFRILLS
8650     if (cx == XXDEL || cx == XXLDEL) {  /* DELETE */
8651 #ifdef LOCUS
8652         if (!locus && cx != XXLDEL) {
8653 #ifdef NOXFER
8654             return(-2);
8655 #else
8656             return(dormt(XZDEL));
8657 #endif /* NOXFER */
8658         }
8659 #endif /* LOCUS */
8660 #ifdef IKSD
8661         if (inserver && (!ENABLED(en_del)
8662 #ifdef CK_LOGIN
8663                          || isguest
8664 #endif /* CK_LOGIN */
8665                          )) {
8666             printf("?Sorry, DELETE is disabled\n");
8667             return(-9);
8668         }
8669 #endif /* IKSD */
8670 #ifdef CK_APC
8671         if ((apcactive == APC_LOCAL) ||
8672             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8673           return(success = 0);
8674 #endif /* CK_APC */
8675         return(dodel());
8676     }
8677 #endif /* NOFRILLS */
8678
8679     if (cx == XXTOUC)                   /* TOUCH */
8680       return(dodir(cx));
8681
8682     /* DIRECTORY commands */
8683
8684     if (cx == XXDIR  || cx == XXLS || cx == XXLDIR ||
8685         cx == XXWDIR || cx == XXHDIR) {
8686 #ifdef LOCUS
8687         if (!locus && cx != XXLDIR) {
8688 #ifdef NOXFER
8689             return(-2);
8690 #else
8691             return(dormt(XZDIR));
8692 #endif /* NOXFER */
8693         }
8694 #endif /* LOCUS */
8695 #ifdef IKSD
8696         if (inserver && !ENABLED(en_dir)) {
8697             printf("?Sorry, DIRECTORY is disabled\n");
8698             return(-9);
8699         }
8700 #endif /* IKSD */
8701         return(dodir(cx));
8702     }
8703
8704 #ifndef NOSPL
8705     if (cx == XXELS)                    /* ELSE */
8706       return(doelse());
8707 #endif /* NOSPL */
8708
8709 #ifndef NOSERVER
8710 #ifndef NOFRILLS
8711     if (cx == XXENA || cx == XXDIS) {   /* ENABLE, DISABLE */
8712         s = (cx == XXENA) ?
8713           "Server function to enable" :
8714             "Server function to disable";
8715
8716         if ((x = cmkey(enatab,nena,s,"",xxstring)) < 0) {
8717             if (x == -3) {
8718                 printf("?Name of server function required\n");
8719                 return(-9);
8720             } else return(x);
8721         }
8722         if ((y = cmkey(kmstab,3,"mode","both",xxstring)) < 0) {
8723             if (y == -3) {
8724                 printf("?Please specify remote, local, or both\n");
8725                 return(-9);
8726             } else return(y);
8727         }
8728         if (cx == XXDIS)                /* Disabling, not enabling */
8729           y = 3 - y;
8730         if ((z = cmcfm()) < 0) return(z);
8731 #ifdef CK_APC
8732         if ((apcactive == APC_LOCAL) ||
8733             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8734           return(success = 0);
8735 #endif /* CK_APC */
8736 #ifdef IKSD
8737         /* This may seem like it duplicates the work in doenable()  */
8738         /* but this code returns failure whereas doenable() returns */
8739         /* success.                                                 */
8740         if (inserver &&
8741 #ifdef IKSDCONF
8742             iksdcf &&
8743 #endif /* IKSDCONF */
8744             (x == EN_HOS || x == EN_PRI || x == EN_MAI || x == EN_WHO ||
8745               isguest))
8746             return(success = 0);
8747 #endif /* IKSD */
8748         return(doenable(y,x));
8749     }
8750 #endif /* NOFRILLS */
8751 #endif /* NOSERVER */
8752
8753 #ifndef NOSPL
8754     if (cx == XXRET) {                  /* RETURN */
8755         if ((x = cmtxt("Optional return value","",&s,NULL)) < 0)
8756           return(x);
8757         s = brstrip(s);                 /* Strip braces */
8758         if (cmdlvl == 0)                /* At top level, nothing happens... */
8759           return(success = 1);
8760         switch (cmdstk[cmdlvl].src) {   /* Action depends on command source */
8761           case CMD_TF:                  /* Command file */
8762             popclvl();                  /* Pop command level */
8763             return(success = 1);        /* always succeeds */
8764           case CMD_MD:                  /* Macro */
8765           case CMD_KB:                  /* Prompt */
8766             return(doreturn(s));        /* Trailing text is return value. */
8767           default:                      /* Shouldn't happen */
8768             return(-2);
8769         }
8770     }
8771 #endif /* NOSPL */
8772
8773 #ifndef NOSPL
8774     if (cx == XXOPE)                    /* OPEN */
8775       return(doopen());
8776 #endif /* NOSPL */
8777
8778 #ifndef NOSPL
8779     if (cx == XXOUT || cx == XXLNOUT) { /* OUTPUT or LINEOUT */
8780         if ((x = cmtxt("Text to be output","",&s,NULL)) < 0)
8781           return(x);
8782 #ifdef CK_APC
8783         if ((apcactive == APC_LOCAL) ||
8784             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8785           return(success = 0);
8786 #endif /* CK_APC */
8787         debug(F110,"OUTPUT 1",s,0);
8788         s = brstrip(s);                 /* Strip enclosing braces, */
8789         debug(F110,"OUTPUT 2",s,0);
8790 /*
8791   I don't think I could ever fully explain this in a million years...
8792   We have read the user's string without calling the variable-expander
8793   function.  Now, before we call it, we have to double backslashes that
8794   appear before \N, \B, \L, and \ itself, so the expander function will
8795   reduce them back to single backslashes, so when we call dooutput()...
8796   But it's more complicated than that.
8797 */
8798         if (cmdgquo()) {                /* Only if COMMAND QUOTING ON ... */
8799             for (x = 0, y = 0; s[x]; x++, y++) {
8800                 if (s[x] == CMDQ) {
8801                     char c = s[x+1];
8802                     if (c == 'n' || c == 'N' ||
8803                         c == 'b' || c == 'B' ||
8804                         c == 'l' || c == 'L' ||
8805                         c == CMDQ)
8806                       line[y++] = CMDQ;
8807                 }
8808                 line[y] = s[x];
8809             }
8810             line[y++] = '\0';           /* Now expand variables, etc. */
8811             debug(F110,"OUTPUT 3",line,0);
8812             s = line+y+1;
8813             x = LINBUFSIZ - (int) strlen(line) - 1;
8814             debug(F101,"OUTPUT size","",x);
8815             if (zzstring(line,&s,&x) < 0)
8816               return(success = 0);
8817             s = line+y+1;
8818             debug(F110,"OUTPUT 4",s,0);
8819         }
8820         success = dooutput(s,cx);
8821         return(success);
8822     }
8823 #endif /* NOSPL */
8824
8825 #ifdef ANYX25
8826 #ifndef IBMX25
8827     if (cx == XXPAD) {                  /* PAD commands */
8828         x = cmkey(padtab,npadc,"PAD command","",xxstring);
8829         if (x == -3) {
8830             printf("?You must specify a PAD command to execute\n");
8831             return(-9);
8832         }
8833         if (x < 0) return(x);
8834
8835         switch (x) {
8836           case XYPADL:
8837             if (x25stat() < 0)
8838               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8839             else {
8840                 x25clear();
8841                 initpad();
8842             }
8843             break;
8844           case XYPADS:
8845             if (x25stat() < 0)
8846               printf("Not connected\r\n");
8847             else {
8848                 extern int linkid, lcn;
8849                 conol("Connected thru ");
8850                 conol(ttname);
8851                 printf(", Link id %d, Logical channel number %d\r\n",
8852                        linkid,lcn);
8853             }
8854             break;
8855           case XYPADR:
8856             if (x25stat() < 0)
8857               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8858             else
8859               x25reset(0,0);
8860             break;
8861           case XYPADI:
8862             if (x25stat() < 0)
8863               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8864             else
8865               x25intr(0);
8866         }
8867         return(0);
8868     }
8869 #endif /* IBMX25 */
8870 #endif /* ANYX25 */
8871
8872 #ifndef NOSPL
8873     if (cx == XXPAU || cx == XXWAI || cx == XXMSL) /* PAUSE, WAIT, etc */
8874       return(dopaus(cx));
8875 #endif /* NOSPL */
8876
8877 #ifndef NOFRILLS
8878     if (cx == XXPRI) {
8879 #ifdef IKSD
8880 #ifdef CK_LOGIN
8881         if (inserver && (isguest || !ENABLED(en_pri))) {
8882             printf("?Sorry, printing is disabled\n");
8883             return(-9);
8884         }
8885 #endif /* CK_LOGIN */
8886 #endif /* IKSD */
8887         if ((x = cmifi("File to print","",&s,&y,xxstring)) < 0) {
8888             if (x == -3) {
8889                 printf("?A file specification is required\n");
8890                 return(-9);
8891             } else return(x);
8892         }
8893         if (y != 0) {
8894             printf("?Wildcards not allowed\n");
8895             return(-9);
8896         }
8897         ckstrncpy(line,s,LINBUFSIZ);
8898         s = "";
8899 #ifndef NT
8900         if ((x = cmtxt("Local print command options, or carriage return","",&s,
8901                        xxstring)) < 0)
8902           return(x);
8903 #endif /* NT */
8904         if ((x = cmcfm()) < 0)
8905           return(x);
8906         return(success = (zprint(s,line) == 0) ? 1 : 0);
8907     }
8908 #endif /* NOFRILLS */
8909
8910 #ifdef TCPSOCKET
8911 #ifndef NOPUSH
8912     if (cx == XXPNG)                    /* PING an IP host */
8913       return(doping());
8914 #endif /* NOPUSH */
8915
8916 #ifndef NOFTP
8917     if (cx == XXFTP)                    /* FTP */
8918 #ifdef SYSFTP
8919 #ifndef NOPUSH
8920       return(doftp());                  /* Just runs system's ftp program */
8921 #else
8922       return(-2);
8923 #endif /* NOPUSH */
8924 #else
8925     return(doxftp());
8926 #endif /* SYSFTP */
8927 #endif /* NOFTP */
8928 #endif /* TCPSOCKET */
8929
8930     if (cx == XXPWD || cx == XXLPWD) {  /* PWD */
8931 #ifdef OS2
8932         char *pwp;
8933 #endif /* OS2 */
8934         if ((x = cmcfm()) < 0)
8935           return(x);
8936 #ifdef LOCUS
8937         if (!locus && cx != XXLPWD) {
8938 #ifdef NOXFER
8939             return(-2);
8940 #else
8941             return(dormt(XZPWD));
8942 #endif /* NOXFER */
8943         }
8944 #endif /* LOCUS */
8945
8946 #ifndef MAC
8947 #ifndef OS2
8948 #ifdef UNIX
8949         printf("%s\n",zgtdir());
8950 #else
8951         xsystem(PWDCMD);
8952 #endif /* UNIX */
8953         return(success = 1);            /* Blind faith */
8954 #else  /* OS2 */
8955         if (pwp = zgtdir()) {
8956             if (*pwp) {
8957 #ifdef NT
8958                 line[0] = NUL;
8959                 ckGetLongPathName(pwp,line,LINBUFSIZ);
8960                 line[LINBUFSIZ-1] = NUL;
8961                 tmpbuf[0] = NUL;
8962                 GetShortPathName(pwp,tmpbuf,TMPBUFSIZ);
8963                 tmpbuf[TMPBUFSIZ-1] = NUL;
8964                 pwp = line;
8965                 if (!strcmp(line,tmpbuf)) {
8966 #endif /* NT */
8967                     printf("%s\n",pwp);
8968 #ifdef NT
8969                 } else {
8970                     printf("  Long name:  %s\n",line);
8971                     printf("  Short name: %s\n",tmpbuf);
8972                 }            
8973 #endif /* NT */
8974             }
8975             return(success = ((int)strlen(pwp) > 0));
8976         } else return(success = 0);
8977 #endif /* OS2 */
8978 #else  /* MAC */
8979         if (pwp = zgtdir()) {
8980             printf("%s\n",pwp);
8981             return(success = ((int)strlen(pwp) > 0));
8982         } else return(success = 0);
8983 #endif /* MAC */
8984     }
8985
8986     if (cx == XXQUI || cx == XXEXI) {   /* EXIT, QUIT */
8987         extern int quitting;
8988
8989         if ((y = cmnum("exit status code",ckitoa(xitsta),10,&x,xxstring)) < 0)
8990           return(y);
8991         if ((y = cmtxt("Optional EXIT message","",&s,xxstring)) < 0)
8992           return(y);
8993         s = brstrip(s);
8994         ckstrncpy(line,s,LINBUFSIZ);
8995
8996         if (!hupok(0))                  /* Check if connection still open */
8997           return(success = 0);
8998
8999         if (line[0])                    /* Print EXIT message if given */
9000           printf("%s\n",(char *)line);
9001
9002         quitting = 1;                   /* Flag that we are quitting. */
9003
9004 #ifdef VMS
9005         doexit(GOOD_EXIT,x);
9006 #else
9007 #ifdef OSK
9008 /* Returning any codes here makes the OS-9 shell print an error message. */
9009         doexit(GOOD_EXIT,-1);
9010 #else
9011 #ifdef datageneral
9012         doexit(GOOD_EXIT,x);
9013 #else
9014         doexit(x,-1);
9015 #endif /* datageneral */
9016 #endif /* OSK */
9017 #endif /* VMS */
9018     }
9019
9020 #ifndef NOXFER
9021 #ifndef NOFRILLS
9022     if (cx == XXERR) {                  /* ERROR */
9023 #ifdef CK_XYZ
9024         if (protocol != PROTO_K) {
9025             printf("Sorry, E-PACKET only works with Kermit protocol\n");
9026             return(-9);
9027         }
9028 #endif /* CK_XYZ */
9029         if ((x = cmcfm()) < 0) return(x);
9030         ttflui();
9031         epktflg = 1;
9032         sstate = 'a';
9033         return(0);
9034     }
9035 #endif /* NOFRILLS */
9036
9037     if (cx == XXFIN) {                  /* FINISH */
9038 #ifdef NEWFTP
9039         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9040           return(ftpbye());
9041 #endif /* NEWFTP */
9042 #ifdef CK_XYZ
9043         if (protocol != PROTO_K) {
9044             printf("Sorry, FINISH only works with Kermit protocol\n");
9045             return(-9);
9046         }
9047 #endif /* CK_XYZ */
9048         if ((x = cmcfm()) < 0) return(x);
9049
9050 #ifdef IKS_OPTION
9051         if (
9052 #ifdef CK_XYZ
9053             protocol == PROTO_K &&
9054 #endif /* CK_XYZ */
9055             !iks_wait(KERMIT_REQ_START,1)) {
9056             printf(
9057               "?A Kermit Server is not available to process this command\n");
9058             return(-9);                 /* Correct the return code */
9059         }
9060 #endif /* IKS_OPTION */
9061
9062         sstate = setgen('F',"","","");
9063         if (local) ttflui();            /* If local, flush tty input buffer */
9064         return(0);
9065     }
9066 #endif /* NOXFER */
9067
9068 #ifndef NOSPL
9069     if (cx == XXFOR)                    /* FOR loop */
9070       return(dofor());
9071 #endif /* NOSPL */
9072
9073 #ifndef NOXFER
9074     /* GET MGET REGET RETRIEVE etc */
9075     if (cx == XXGET || cx == XXMGET || cx == XXREGET || cx == XXRETR) {
9076 #ifdef IKSD
9077         if (inserver && !ENABLED(en_sen)) {
9078             printf("?Sorry, reception of files is disabled\n");
9079             return(-9);
9080         }
9081 #endif /* IKSD */
9082         return(doxget(cx));
9083     }
9084 #endif /* NOXFER */
9085
9086 #ifndef NOSPL
9087 #ifndef NOFRILLS
9088     if (cx == XXGOK) {                  /* GETOK */
9089         return(success = doask(cx));
9090     }
9091 #endif /* NOFRILLS */
9092 #endif /* NOSPL */
9093
9094     if (cx == XXHLP) {                  /* HELP */
9095 #ifdef NOHELP
9096         return(dohlp(XXHLP));
9097 #else
9098         x = cmkey2(cmdtab,
9099                    ncmd,"\nCommand or topic","help",toktab,xxstring,1+2+8);
9100         debug(F111,"HELP command x",cmdbuf,x);
9101         if (x == -5) {
9102             y = chktok(toktab);
9103             debug(F101,"HELP cmkey token","",y);
9104             /* ungword(); */
9105             switch (y) {
9106 #ifndef NOPUSH
9107               case '!':
9108               case '@': x = XXSHE; break;
9109               case '<': x = XXFUN; break;
9110 #endif /* NOPUSH */
9111               case '#': x = XXCOM; break;
9112               case ';': x = XXCOM; break;
9113 #ifndef NOSPL
9114               case '.': x = XXDEF; break;
9115               case ':': x = XXLBL; break;
9116 #ifndef NOSEXP
9117               case '(': x = XXSEXP; break;
9118 #endif /* NOSEXP */
9119 #endif /* NOSPL */
9120 #ifdef CK_RECALL
9121               case '^': x = XXREDO; break;
9122 #endif  /* CK_RECALL */
9123               case '&': x = XXECH; break; /* (what is this?) */
9124               default:
9125                 printf("\n?Invalid - %s\n",cmdbuf);
9126                 x = -2;
9127             }
9128         }
9129         makestr(&hlptok,atmbuf);
9130         debug(F111,"HELP token",hlptok,x);
9131         return(dohlp(x));
9132 #endif /* NOHELP */
9133     }
9134
9135 #ifndef NOHELP
9136     if (cx == XXINT)                    /* INTRO */
9137       return(hmsga(introtxt));
9138     if (cx == XXNEW) {                  /* NEWS */
9139         int x;
9140         extern char * k_info_dir;
9141         x = hmsga(newstxt);
9142         return(x);
9143     }
9144
9145 #ifdef OS2ONLY
9146     if (cx == XXUPD) {                  /* View UPDATE file */
9147         extern char exedir[];
9148         char * pTopic;
9149         char updstr[2048];
9150         if ((x = cmtxt("topic name","",&pTopic,xxstring)) < 0)
9151             return x;
9152 #ifdef COMMENT
9153         sprintf(updstr,
9154                 "start view %s\\docs\\k2.inf+%s\\docs\\using_ck.inf+\
9155 %s\\docs\\dialing.inf+%s\\docs\\modems.inf %s",
9156                 exedir,exedir,exedir,exedir,pTopic
9157                 );
9158 #else
9159         if (ckmakxmsg(updstr,
9160                      2048,
9161                      "start view ",
9162                      exedir,
9163                      "\\docs\\k2.inf+",
9164                      exedir,
9165                      "\\docs\\using_ck.inf+",
9166                      exedir,
9167                      "\\docs\\dialing.inf+",
9168                      exedir,
9169                      "\\docs\\modems.inf ",
9170                      pTopic,
9171                      NULL,
9172                      NULL
9173                      ) > 0)
9174 #endif /* COMMENT */
9175           system(updstr);
9176         return(success = 1);
9177     }
9178 #endif /* OS2ONLY */
9179 #endif /* NOHELP */
9180
9181 #ifndef NOLOCAL
9182     if (cx == XXHAN) {                  /* HANGUP */
9183         if ((x = cmcfm()) < 0) return(x);
9184 #ifdef NEWFTP
9185         if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
9186           return(success = ftpbye());
9187 #endif /* NEWFTP */
9188 #ifndef NODIAL
9189         if ((x = mdmhup()) < 1) {
9190             debug(F101,"HANGUP mdmup","",x);
9191 #endif /* NODIAL */
9192             x = tthang();
9193             debug(F101,"HANGUP tthang","",x);
9194             x = (x > -1);
9195 #ifndef NODIAL
9196         }
9197         dialsta = DIA_UNK;
9198 #endif /* NODIAL */
9199         whyclosed = WC_CLOS;
9200         ttchk();                        /* In case of CLOSE-ON-DISCONNECT */
9201         dologend();
9202 #ifdef OS2
9203         if (x)
9204           DialerSend(OPT_KERMIT_HANGUP, 0);
9205 #endif /* OS2 */
9206         if (x) haveline = 0;
9207         return(success = x);
9208     }
9209 #endif /* NOLOCAL */
9210
9211 #ifndef NOSPL
9212     /* INPUT, REINPUT, and MINPUT */
9213
9214     if (cx == XXINP || cx == XXREI || cx == XXMINP) {
9215         long zz;
9216         int flags = 0, incount = 0;
9217         extern int itsapattern, isjoin, isinbuflen;
9218         int c, getval;
9219
9220         struct FDB sw, nu, fl;
9221         int fc, havetime = 0;
9222         char * m;
9223
9224         if (cx == XXREI) {
9225             m = "Timeout in seconds (ignored)";
9226         } else {
9227             m = "Seconds to wait for input,\n or time of day hh:mm:ss,\
9228  or switch";
9229         }
9230         cmfdbi(&sw,                     /* First FDB - command switches */
9231                _CMKEY,                  /* fcode */
9232                m,                       /* helpmsg */
9233                ckitoa(indef),           /* default */
9234                "",                      /* addtl string data */
9235                ninputsw,                /* addtl numeric data 1: tbl size */
9236                4,                       /* addtl numeric data 2: 4 = cmswi */
9237                xxstring,                /* Processing function */
9238                inputsw,                 /* Keyword table */
9239                &nu                      /* Pointer to next FDB */
9240                );
9241         cmfdbi(&nu,
9242                _CMNUM,                  /* Number */
9243                m,                       /* Help message */
9244                ckitoa(indef),           /* default */
9245                "",                      /* N/A */
9246                10,                      /* Radix = 10 */
9247                0,                       /* N/A */
9248                xxstring,                /* Processing function */
9249                NULL,                    /* N/A */
9250                &fl                      /* Next */
9251                );
9252         cmfdbi(&fl,                     /* Time of day hh:mm:ss */
9253                _CMFLD,                  /* fcode */
9254                "",                      /* hlpmsg */
9255                "",
9256                "",                      /* addtl string data */
9257                0,                       /* addtl numeric data 1 */
9258                0,                       /* addtl numeric data 2 */
9259                xxstring,
9260                NULL,
9261                NULL
9262                );
9263         fc = (cx == XXREI) ? cmfdb(&nu) : cmfdb(&sw); /* Parse something */
9264
9265         for (y = 0; y < MINPMAX; y++) { /* Initialize search strings */
9266             mp[y] = 0;                  /* Assume it's not a pattern */
9267             if (!mpinited) {
9268                 ms[y] = NULL;
9269             }
9270             if (ms[y]) {
9271                 free(ms[y]);            /* Free old strings, if any */
9272                 ms[y] = NULL;
9273             }
9274         }
9275         mpinited = 1;
9276         while (!havetime) {
9277             if (fc < 0) {               /* Error */
9278                 if (fc == -3) {
9279                     printf("?Syntax error in INPUT-class command\n");
9280                     return(-9);
9281                 } else
9282                   return(fc);
9283             }
9284             switch (cmresult.fcode) {
9285               case _CMKEY:              /* Switch */
9286                 c = cmgbrk();
9287                 if ((getval = (c == ':' || c == '=')) &&
9288                     !(cmgkwflgs() & CM_ARG)) {
9289                     printf("?This switch does not take an argument\n");
9290                     return(-9);
9291                 }
9292                 if (getval && cmresult.nresult == INPSW_COU) {
9293                     if ((y = cmnum("Number of bytes to read",
9294                                    "",10,&x,xxstring)) < 0)
9295                       return(y);
9296                     incount = x;
9297                 }
9298                 flags |= cmresult.nresult;
9299                 fc = cmfdb(&sw);        /* Maybe parse more switches */
9300                 continue;
9301
9302               case _CMNUM:              /* Seconds to time out */
9303                 x = cmresult.nresult;
9304 #ifdef CKFLOAT
9305                 if (inscale != 1.0)     /* Scale */
9306                   x *= inscale;         
9307 #endif  /* CKFLOAT */
9308                 havetime++;
9309                 break;
9310
9311               case _CMFLD:
9312                 zz = tod2sec(atmbuf);   /* Convert to secs since midnight */
9313                 if (zz < 0L) {
9314                     printf("?Number, expression, or time of day required\n");
9315                     return(-9);
9316                 } else {
9317                     char now[32];       /* Current time */
9318                     char *p;
9319                     long tnow;
9320                     p = now;
9321                     ztime(&p);
9322                     tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
9323                     if (zz < tnow)      /* User's time before now */
9324                       zz += 86400L;     /* So make it tomorrow */
9325                     zz -= tnow;         /* Seconds from now. */
9326                     if (zz > -1L) {
9327                         x = zz;
9328                         if (zz != (long) x) {
9329                             printf(
9330 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
9331 );
9332                             return(-9);
9333                         }
9334                     }
9335                     havetime++;
9336                 }
9337                 break;
9338               default:          
9339                 printf("?Internal error\n");
9340                 return(-9);
9341             }
9342         }
9343         /* Now parse the search text */
9344
9345 #ifdef CK_MINPUT
9346         if (cx == XXMINP) {             /* MINPUT */
9347             int i, k = 0, n = 0;
9348             struct stringarray * q;
9349             keepallchars = 1;
9350             while (k < MINPMAX) {
9351                 if ((y = cmfld("String or pattern","",&s,xxstring)) < 0) {
9352                     if (y == -3) {
9353                         if ((y = cmcfm()) < 0)
9354                           return(y);
9355                         break;
9356                     } else {
9357                         return(y);
9358                     }
9359                 }
9360                 debug(F111,"MINPUT field",s,k);
9361                 if (isjoin) {
9362                     if ((q = cksplit(1,0,s," ",(char *)c1chars,3,0,0))) {
9363                         char ** ap = q->a_head;
9364                         n = q->a_size;
9365                         debug(F101,"minput cksplit size","",n);
9366                         for (i = 1; i <= n && k < MINPMAX; i++) {
9367                             if (!ap[i]) /* Add non-empty elements */
9368                               continue;
9369                             if (!*(ap[i]))
9370                               continue;
9371                             makestr(&(ms[k]),ap[i]);
9372                             debug(F111,"MINPUT JOIN",ms[k],k);
9373                             k++;
9374                         }
9375                     }
9376                 } else {
9377                     if (s) if (*s) {
9378                         makestr(&(ms[k]),brstrip(s));
9379                         if (itsapattern) mp[k] = 1;
9380                         debug(F111,"MINPUT",ms[k],itsapattern);
9381                         k++;
9382                     }
9383                 }
9384             }
9385             keepallchars = 0;
9386         } else {
9387 #endif /* CK_MINPUT */
9388
9389             /* INPUT or REINPUT */
9390
9391             if (flags & INPSW_COU) {
9392                 if ((y = cmcfm()) < 0)
9393                   return(y);
9394             } else {
9395                 if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
9396                   return(y);
9397             }
9398             mp[0] = itsapattern ? 1 : 0;
9399             makestr(&(ms[0]),brstrip(s));
9400             ms[1] = NULL;
9401
9402 #ifdef CK_MINPUT
9403         }
9404 #endif /* CK_MINPUT */
9405
9406         if (incount > 0)                /* No searching if /COUNT: given */
9407           makestr(&(ms[0]),NULL);
9408
9409         if (cx == XXINP || cx == XXMINP) { /* Not REINPUT... */
9410             i_active = 1;
9411             /* Go try to input the search string */
9412             success = doinput(x,ms,mp,flags,incount);
9413             i_active = 0;
9414         } else {                        /* REINPUT */
9415             success = doreinp(x,ms[0],itsapattern);
9416         }
9417         if (intime[cmdlvl] && !success) { /* TIMEOUT-ACTION = QUIT? */
9418             popclvl();                  /* If so, pop command level. */
9419             if (pflag && cmdlvl == 0) {
9420                 if (cx == XXINP)  printf("?INPUT timed out\n");
9421                 if (cx == XXMINP) printf("?MINPUT timed out\n");
9422                 if (cx == XXREI)  printf("?REINPUT failed\n");
9423             }
9424         }
9425         return(success);                /* Return do(re)input's return code */
9426     }
9427
9428 #endif /* NOSPL */
9429
9430     if (cx == XXLOG) {                  /* LOG */
9431         x = cmkey(logtab,nlog,"What to log","",xxstring);
9432         if (x == -3) {
9433             printf("?Type of log required\n");
9434             return(-9);
9435         }
9436         if (x < 0) return(x);
9437         x = dolog(x);
9438         if (x < 0)
9439           return(x);
9440         else
9441           return(success = x);
9442     }
9443
9444     if (cx == XXLOGIN) {                /* (REMOTE) LOGIN */
9445 #ifdef NEWFTP
9446         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9447           return(success = doftpusr());
9448 #endif /* NEWFTP */
9449 #ifdef IKSD
9450         if (inserver) {
9451             printf("?Already logged in\n");
9452             return(-9);
9453         } else
9454 #endif /* IKSD */
9455         {
9456 #ifdef NOXFER
9457             return(-2);
9458 #else
9459             return(dormt(XZLGI));
9460 #endif /* NOXFER */
9461         }
9462     }
9463     if (cx == XXLOGOUT) {               /* (REMOTE) LOGOUT */
9464 #ifdef NEWFTP
9465         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9466           return(success = doftpres());
9467 #endif /* NEWFTP */
9468
9469 #ifdef IKSD
9470         if (inserver) {
9471             if ((x = cmcfm()) < 0)
9472               return(x);
9473             doexit(GOOD_EXIT,xitsta);
9474         } else
9475 #endif /* IKSD */
9476         if (!local || (network && ttchk() < 0)) {
9477             printf("?No connection.\n");
9478             return(-9);
9479         } else {
9480 #ifdef NOXFER
9481             return(-2);
9482 #else
9483             return(dormt(XZLGO));
9484 #endif /* NOXFER */
9485         }
9486     }
9487
9488 #ifndef NOSCRIPT
9489     if (cx == XXLOGI) {                 /* UUCP-style script */
9490         if ((x = cmtxt("expect-send expect-send ...","",&s,xxstring)) < 0)
9491           return(x);
9492 #ifdef CK_APC
9493         if ((apcactive == APC_LOCAL) ||
9494             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9495           return(success = 0);
9496 #endif /* CK_APC */
9497 #ifdef VMS
9498         conres();                       /* For Ctrl-C to work... */
9499 #endif /* VMS */
9500         return(success = dologin(s));   /* Return 1=completed, 0=failed */
9501     }
9502 #endif /* NOSCRIPT */
9503
9504 #ifndef NOXFER
9505 #ifdef PIPESEND
9506     if (cx == XXCREC) {                 /* CRECEIVE */
9507         if (protocol != PROTO_K) {
9508             printf("?Sorry, CRECEIVE works only with Kermit protocol\n");
9509             return(-9);
9510         } else
9511           return(doxget(cx));
9512     }
9513     if (cx == XXCGET) {                 /* CGET */
9514         return(doxget(cx));
9515     }
9516 #endif /* PIPESEND */
9517
9518     if (cx == XXREC)                    /* RECEIVE */
9519       return(doxget(cx));
9520 #endif /* NOXFER */
9521
9522 #ifndef NOXFER
9523     if (cx == XXREM) {                  /* REMOTE */
9524 #ifdef NEWFTP
9525         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9526           return(doftprmt(0,0));
9527 #endif /* NEWFTP */
9528 #ifdef CK_XYZ
9529         if (protocol != PROTO_K) {
9530             printf("Sorry, REMOTE commands only work with Kermit protocol\n");
9531             return(-9);
9532         }
9533 #endif /* CK_XYZ */
9534         x = cmkey(remcmd,nrmt,"Remote Kermit server command","",xxstring);
9535         if (x == -3) {
9536             printf("?You must specify a command for the remote server\n");
9537             return(-9);
9538         }
9539         return(dormt(x));
9540     }
9541 #endif /* NOXFER */
9542
9543 #ifndef NORENAME
9544 #ifndef NOFRILLS
9545     if (cx == XXREN || cx == XXLREN) {  /* RENAME */
9546 #ifdef LOCUS
9547         if (!locus && cx != XXLREN) {
9548 #ifdef NOXFER
9549             return(-2);
9550 #else
9551             return(dormt(XZREN));
9552 #endif /* NOXFER */
9553         }
9554 #endif /* LOCUS */
9555 #ifdef IKSD
9556         if (inserver && (!ENABLED(en_ren)
9557 #ifdef CK_LOGIN
9558                          || isguest
9559 #endif /* CK_LOGIN */
9560                          )) {
9561             printf("?Sorry, renaming of files is disabled\n");
9562             return(-9);
9563         }
9564 #endif /* IKSD */
9565 #ifdef CK_APC
9566         if ((apcactive == APC_LOCAL) ||
9567             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9568           return(success = 0);
9569 #endif /* CK_APC */
9570         return(dorenam());
9571     }
9572 #endif /* NOFRILLS */
9573 #endif /* NORENAME */
9574
9575     if (cx == XXEIGHT) {                /* EIGHTBIT */
9576         extern int parity, cmask, cmdmsk;
9577         if ((x = cmcfm()) < 0)
9578           return(x);
9579         parity = 0;
9580         cmask = 0xff;
9581         cmdmsk = 0xff;
9582         return(success = 1);
9583     }
9584
9585 #ifndef NOXFER
9586 /* SEND, CSEND, MOVE, MAIL, and RESEND use the new common code */
9587
9588     if (cx == XXSEN                     /* SEND */
9589 #ifdef PIPESEND
9590         || cx == XXCSEN                 /* CSEND */
9591 #endif /* PIPESEND */
9592         || cx == XXMOVE                 /* MOVE */
9593         || cx == XXMAI                  /* MAIL */
9594 #ifdef CK_RESEND
9595         || cx == XXRSEN                 /* RESEND */
9596 #endif /* CK_RESEND */
9597         ) {
9598 #ifdef IKSD
9599         if (inserver && !ENABLED(en_get)) {
9600             printf("?Sorry, sending files is disabled\n");
9601             return(-9);
9602         }
9603 #endif /* IKSD */
9604         return(doxsend(cx));
9605     }
9606
9607 /* PSEND, ADD, and REMOVE use special parsing */
9608
9609 #ifdef ADDCMD
9610     /* ADD and REMOVE */
9611     if (cx == XXADD || cx == XXREMV) {
9612         char * m;
9613         m = (cx == XXADD) ? "Add to which list?" : "Remove from which list?";
9614         x = cmkey(addtab,naddtab,m,"",xxstring);
9615         if (x < 0)
9616           return(x);
9617 #ifndef NOMSEND
9618         if (x == ADD_SND)
9619           return(addsend(cx));
9620         else
9621 #endif /* NOMSEND */
9622           return(doadd(cx,x));
9623     }
9624 #endif /* ADDCMD */
9625
9626 #ifdef CK_RESEND
9627     if (cx == XXPSEN) {                 /* PSEND */
9628         int seekto = 0;                 /* FIX THIS */
9629
9630         cmarg = cmarg2 = "";
9631         x = cmifi("File to partially send", "", &s, &y, xxstring);
9632         if (x < 0) {
9633             if (x == -3) {
9634                 printf("?A file specification is required\n");
9635                 return(-9);
9636             } else return(x);
9637         }
9638         nfils = -1;                     /* Files come from internal list. */
9639 #ifndef NOMSEND
9640         addlist = 0;                    /* Don't use SEND-LIST. */
9641         filenext = NULL;
9642 #endif /* NOMSEND */
9643         ckstrncpy(line,s,LINBUFSIZ);    /* Save copy of string just parsed. */
9644         debug(F110,"PSEND line",line,0);
9645         if (y != 0) {
9646             printf("?Sorry, wildcards not permitted in this command\n");
9647             return(-9);
9648         }
9649         if (sizeof(int) < 4) {
9650             printf("?Sorry, this command needs 32-bit integers\n");
9651             return(-9);
9652         }
9653         x = cmnum("starting position (byte number)",
9654                   "",10,&seekto,xxstring);
9655         if (x < 0)
9656           return(x);
9657         zfnqfp(s,fspeclen,fspec);       /* Get full path */
9658         if ((x = cmtxt("Name to send it with","",&s,NULL)) < 0)
9659           return(x);
9660         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
9661
9662 #ifdef IKSD
9663         if (inserver && !ENABLED(en_get)) {
9664             printf("?Sorry, sending files is disabled\n");
9665             return(-9);
9666         }
9667 #endif /* IKSD */
9668 #ifdef PIPESEND
9669         if (sndfilter) {
9670             printf("?Sorry, no PSEND while SEND FILTER selected\n");
9671             return(-9);
9672         }
9673 #endif /* PIPESEND */
9674 #ifdef CK_XYZ
9675         if ((protocol == PROTO_X || protocol == PROTO_XC)) {
9676             printf("Sorry, PSEND works only with Kermit protocol\n");
9677             return(-9);
9678         }
9679 #endif /* CK_XYZ */
9680
9681         cmarg2 = brstrip(tmpbuf);       /* Strip braces */
9682         cmarg = line;                   /* File to send */
9683         debug(F110,"PSEND filename",cmarg,0);
9684         debug(F110,"PSEND as-name",cmarg2,0);
9685         sendstart = seekto;
9686         sstate = 's';                   /* Set start state to SEND */
9687 #ifndef NOMSEND
9688         addlist = 0;
9689         filenext = NULL;
9690 #endif /* NOMSEND */
9691         sendmode = SM_PSEND;
9692 #ifdef MAC
9693         what = W_SEND;
9694         scrcreate();
9695 #endif /* MAC */
9696         if (local) {                    /* If in local mode, */
9697             displa = 1;                 /* enable file transfer display */
9698         }
9699         return(0);
9700     }
9701 #endif /* CK_RESEND */
9702 #endif /* NOXFER */
9703
9704 #ifndef NOXFER
9705 #ifndef NOMSEND
9706     if (cx == XXMSE || cx == XXMMOVE) {
9707 #ifdef NEWFTP
9708         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9709           return(doftpput(cx,0));
9710 #endif /* NEWFTP */
9711 #ifdef CK_XYZ
9712         if (protocol == PROTO_X || protocol == PROTO_XC) {
9713             printf(
9714 "Sorry, you can only send one file at a time with XMODEM protocol\n"
9715                    );
9716             return(-9);
9717         }
9718 #endif /* CK_XYZ */
9719         return(doxsend(cx));
9720     }
9721
9722 #ifdef COMMENT                          /* (moved to doxsend) */
9723     if (cx == XXMSE || cx == XXMMOVE) { /* MSEND and MMOVE commands */
9724         nfils = 0;                      /* Like getting a list of */
9725         lp = line;                      /* files on the command line */
9726         addlist = 0;                    /* Do not use SEND-LIST */
9727         filenext = NULL;                /* Ditto ! */
9728
9729         while (1) {
9730             char *p;
9731             if ((x = cmifi("Names of files to send, separated by spaces","",
9732                            &s,&y,xxstring)) < 0) {
9733                 if (x == -3) {
9734                     if (nfils <= 0) {
9735                         printf("?A file specification is required\n");
9736                         return(-9);
9737                     } else break;
9738                 }
9739                 return(x);
9740             }
9741             msfiles[nfils++] = lp;      /* Got one, count it, point to it, */
9742             p = lp;                     /* remember pointer, */
9743             while (*lp++ = *s++)        /* and copy it into buffer */
9744               if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
9745                   printf("?MSEND list too long\n");
9746                   line[0] = NUL;
9747                   return(-9);
9748               }
9749             debug(F111,"msfiles",msfiles[nfils-1],nfils-1);
9750             if (nfils == 1) *fspec = NUL; /* Take care of \v(filespec) */
9751 #ifdef ZFNQFP
9752             zfnqfp(p,TMPBUFSIZ,tmpbuf);
9753             p = tmpbuf;
9754 #endif /* ZFNQFP */
9755             if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
9756                 strcat(fspec,p);        /* safe */
9757                 strcat(fspec," ");      /* safe */
9758             } else printf("WARNING - \\v(filespec) buffer overflow\n");
9759         }
9760         cmlist = msfiles;               /* Point cmlist to pointer array */
9761         cmarg2 = "";                    /* No internal expansion list (yet) */
9762         sndsrc = nfils;                 /* Filenames come from cmlist */
9763         sendmode = SM_MSEND;            /* Remember this kind of SENDing */
9764         sstate = 's';                   /* Set start state for SEND */
9765         if (cx == XXMMOVE)              /* If MMOVE'ing, */
9766           moving = 1;                   /*  set this flag. */
9767 #ifdef MAC
9768         what = W_SEND;
9769         scrcreate();
9770 #endif /* MAC */
9771         if (local) {                    /* If in local mode, */
9772             displa = 1;                 /* turn on file transfer display */
9773             ttflui();                   /* and flush tty input buffer. */
9774         }
9775         return(0);
9776     }
9777 #endif /* COMMENT */
9778 #endif /* NOMSEND */
9779 #endif /* NOXFER */
9780
9781 #ifndef NOSERVER
9782     if (cx == XXSER) {                  /* SERVER */
9783 #ifdef CK_XYZ
9784         if (protocol != PROTO_K) {
9785             printf("Sorry, SERVER only works with Kermit protocol\n");
9786             return(-9);
9787         }
9788 #endif /* CK_XYZ */
9789 #ifdef COMMENT
9790 /*
9791   Parse for time limit, but since we don't use it yet,
9792   the parsing is commented out.
9793 */
9794         x_ifnum = 1;                    /* Turn off internal complaints */
9795         y = cmnum("optional time limit, seconds, or time of day as hh:mm:ss",
9796                   "0", 10, &x, xxstring
9797                   );
9798         x_ifnum = 0;
9799         if (y < 0) {
9800             if (y == -2) {              /* Invalid number or expression */
9801                 zz = tod2sec(atmbuf);   /* Convert to secs since midnight */
9802                 if (zz < 0L) {
9803                     printf("?Number, expression, or time of day required\n");
9804                     return(-9);
9805                 } else {
9806                     char now[32];       /* Current time */
9807                     char *p;
9808                     long tnow;
9809                     p = now;
9810                     ztime(&p);
9811                     tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
9812                     if (zz < tnow)      /* User's time before now */
9813                       zz += 86400L;     /* So make it tomorrow */
9814                     zz -= tnow;         /* Seconds from now. */
9815                 }
9816             } else
9817               return(y);
9818         }
9819         if (zz > -1L) {
9820             x = zz;
9821             if (zz != (long) x) {
9822                 printf(
9823 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
9824                        );
9825                 return(-9);
9826             }
9827         }
9828         if (x < 0)
9829           x = 0;
9830 #endif /* COMMENT */
9831
9832         if ((x = cmcfm()) < 0) return(x);
9833         sstate = 'x';
9834 #ifdef MAC
9835         what = W_RECV;
9836         scrcreate();
9837 #endif /* MAC */
9838         if (local) displa = 1;
9839 #ifdef AMIGA
9840         reqoff();                       /* No DOS requestors while server */
9841 #endif /* AMIGA */
9842         return(0);
9843     }
9844 #endif /* NOSERVER */
9845
9846     if (cx == XXSAVE) {                 /* SAVE command */
9847         x = cmkey(savtab,nsav,"option","keymap",xxstring);
9848         if (x == -3) {
9849             printf("?You must specify an option to save\n");
9850             return(-9);
9851         }
9852         if (x < 0) return(x);
9853         /* have to set success separately for each item in doprm()... */
9854         /* actually not really, could have just had doprm return 0 or 1 */
9855         /* and set success here... */
9856         y = dosave(x);
9857         if (y == -3) {
9858             printf("?More fields required\n");
9859             return(-9);
9860         } else return(y);
9861     }
9862
9863     if (cx == XXSET) {                  /* SET command */
9864         x = cmkey(prmtab,nprm,"Parameter","",xxstring);
9865         if (x == -3) {
9866             printf("?You must specify a parameter to set\n");
9867             return(-9);
9868         }
9869         if (x < 0) return(x);
9870         /* have to set success separately for each item in doprm()... */
9871         /* actually not really, could have just had doprm return 0 or 1 */
9872         /* and set success here... */
9873         y = doprm(x,0);
9874         if (y == -3) {
9875             printf("?More fields required\n");
9876             return(-9);
9877         } else return(y);
9878     }
9879
9880 #ifndef NOPUSH
9881     if (cx == XXSHE                     /* SHELL (system) command */
9882         || cx == XXEXEC                 /* exec() */
9883         ) {
9884         int rx = 0;
9885         char * p = NULL;
9886         int i /* ,n */ ;
9887 #ifdef UNIXOROSK
9888         char * args[256];
9889 #endif /* UNIXOROSK */
9890
9891 #ifdef IKSD
9892         if (inserver && (nopush || !ENABLED(en_hos))) {
9893             printf("?Sorry, host command access is disabled\n");
9894             return(-9);
9895         }
9896 #endif /* IKSD */
9897
9898 #ifdef CKEXEC
9899         if (cx == XXEXEC) {             /* EXEC (overlay ourselves) */
9900             struct FDB sw, fl;
9901             cmfdbi(&sw,                 /* First FDB - command switches */
9902                    _CMKEY,              /* fcode */
9903                    "Command to overlay C-Kermit\n or switch", /* hlpmsg */
9904                    "",                  /* default */
9905                    "",                  /* addtl string data */
9906                    1,                   /* addtl numeric data 1: tbl size */
9907                    4,                   /* addtl numeric data 2: 4 = cmswi */
9908                    xxstring,            /* Processing function */
9909                    redirsw,             /* Keyword table */
9910                    &fl                  /* Pointer to next FDB */
9911                    );
9912             cmfdbi(&fl,                 /* 2nd FDB - command to exec */
9913                    _CMFLD,              /* fcode */
9914                    "Command to overlay C-Kermit", /* hlpmsg */
9915                    "",                  /* default */
9916                    "",                  /* addtl string data */
9917                    0,                   /* addtl numeric data 1 */
9918                    0,                   /* addtl numeric data 2 */
9919                    xxstring,
9920                    NULL,
9921                    NULL                 /* No more after this */
9922                    );
9923             while (1) {
9924                 x = cmfdb(&sw);         /* Parse something */
9925                 debug(F101,"exec cmfdb","",x);
9926                 if (x < 0)
9927                   return(x);
9928                 /* Generalize this if we add more switches */
9929                 if (cmresult.fcode == _CMKEY) {
9930                     rx = 1;
9931                     continue;
9932                 }
9933                 if (cmresult.fcode == _CMFLD)
9934                   break;
9935                 return(-2);
9936             }
9937             ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
9938             if (!tmpbuf[0]) {
9939                 printf("?Command required\n");
9940                 return(-9);
9941             }
9942             p = brstrip(tmpbuf);
9943             args[0] = NULL;             /* Set argv[0] to it */
9944             makestr(&args[0],p);
9945             for (i = 1; i < 255; i++) { /* Get arguments for command */
9946                 if ((x = cmfld("Argument","",&s,xxstring)) < 0) {
9947                     if (x == -3) {
9948                         if ((x = cmcfm()) < 0)
9949                           return(x);
9950                         break;
9951                     } else
9952                       return(x);
9953                 }
9954                 args[i] = NULL;
9955                 s = brstrip(s);
9956                 makestr(&args[i],s);
9957             }
9958             args[i] = NULL;
9959         } else {
9960 #endif /* CKEXEC */
9961             if ((x = cmtxt("System command to execute","",&s,xxstring)) < 0)
9962               return(x);
9963 #ifdef CKEXEC
9964         }
9965 #endif /* CKEXEC */
9966         if (nopush)
9967           return(success = 0);
9968 #ifdef CK_APC
9969         if (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
9970           return(success = 0);
9971 #endif /* CK_APC */
9972         conres();                       /* Make console normal  */
9973 #ifdef OS2
9974         if (!(s && *s)) {
9975             os2push();
9976             return(success = 1);
9977         } else
9978 #endif /* OS2 */
9979           if (cx == XXSHE) {
9980               x = zshcmd(s);
9981               debug(F101,"RUN zshcmd code","",x);
9982               concb((char)escape);
9983               return(success = x);
9984 #ifdef CKEXEC
9985           } else {
9986 #ifdef DEBUG
9987               if (deblog) {
9988                   debug(F111,"EXEC cmd",p,0);
9989                   for (i = 0; i < 256 && args[i]; i++)
9990                     debug(F111,"EXEC arg",args[i],i);
9991               }
9992 #endif /* DEBUG */
9993               if (p) {
9994                   z_exec(p,args,rx);    /* Overlay ourself */
9995                   debug(F100,"EXEC fails","",0);
9996                   concb((char)escape);  /* In case it returns */
9997               }
9998               return(success = 0);
9999 #endif /* CKEXEC */
10000           }
10001     }
10002
10003 #ifdef CK_REDIR
10004     if (cx == XXFUN) {                  /* REDIRECT */
10005 #ifdef CK_APC
10006         if ((apcactive == APC_LOCAL) ||
10007             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
10008           return(success = 0);
10009 #endif /* CK_APC */
10010         ckmakmsg(tmpbuf,
10011                  TMPBUFSIZ,
10012                  "Local command to run,\n",
10013                  "with its standard input/output redirected to ",
10014                  local ? ttname : "the communications connection",
10015                  "\n"
10016                  );
10017         if ((x = cmtxt(tmpbuf,"",&s,xxstring)) < 0)
10018           return(x);
10019         if (nopush) {
10020             printf("?REDIRECT disabled\n");
10021             return(success=0);
10022         }
10023         if (!local) {
10024             printf("?SET LINE or SET HOST required first\n");
10025             return(-9);
10026         }
10027         if (!*s) {
10028             printf("?REDIRECT requires a command to redirect\n");
10029             return(-9);
10030         }
10031         return(success = ttruncmd(s));
10032     }
10033 #endif /* CK_REDIR */
10034 #endif /* NOPUSH */
10035
10036 #ifndef NOSHOW
10037     if (cx == XXSHO) {                  /* SHOW */
10038         x = cmkey(shotab,nsho,"","parameters",xxstring);
10039         if (x < 0) return(x);
10040         return(doshow(x));
10041     }
10042 #endif /* NOSHOW */
10043
10044 #ifndef MAC
10045     if (cx == XXSPA) {                  /* SPACE */
10046 #ifdef IKSD
10047         if (inserver && !ENABLED(en_spa)) {
10048             printf("?Sorry, SPACE command disabled\n");
10049             return(-9);
10050         }
10051 #endif /* IKSD */
10052 #ifdef datageneral
10053         /* AOS/VS can take an argument after its "space" command. */
10054         if ((x = cmtxt("Confirm, or local directory name","",&s,xxstring)) < 0)
10055           return(x);
10056         if (nopush) {
10057             printf("?Sorry, SPACE command disabled\n");
10058             return(-9);
10059         } else if (*s == NUL) {
10060             xsystem(SPACMD);
10061         } else {
10062             ckmakmsg(line,LINBUFSIZ,"space ",s,NULL,NULL);
10063             xsystem(line);
10064         }
10065 #else
10066 #ifdef OS2
10067         if ((x = cmtxt("Press Enter for current disk,\n\
10068  or specify a disk letter like A:","",&s,xxstring)) < 0)
10069           return(x);
10070         if (*s == NUL) {                /* Current disk */
10071             unsigned long space = zdskspace(0);
10072             if (space > 0 && space < 1024)
10073               printf(" Free space: unknown\n");
10074             else
10075               printf(" Free space: %ldK\n", space/1024L);
10076         } else {
10077             int drive = toupper(*s);
10078             unsigned long space = zdskspace(drive - 'A' + 1);
10079             if (space > 0 && space < 1024)
10080               printf(" Drive %c: unknown free\n");
10081             else
10082               printf(" Drive %c: %ldK free\n", drive,space / 1024L);
10083         }
10084 #else
10085 #ifdef UNIXOROSK
10086         x = cmdir("Confirm for current disk,\n\
10087  or specify a disk device or directory","",&s,xxstring);
10088         if (x == -3)
10089           s = "";
10090         else if (x < 0)
10091           return(x);
10092         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
10093         s = tmpbuf;
10094         if ((x = cmcfm()) < 0) return(x);
10095         if (nopush) {
10096             printf("?Sorry, SPACE command disabled\n");
10097             return(-9);
10098         }
10099         if (!*s) {                      /* Current disk */
10100             xsystem(SPACMD);
10101         } else {                        /* Specified disk */
10102             ckmakmsg(line,LINBUFSIZ,SPACM2," ",s,NULL);
10103             xsystem(line);
10104         }
10105 #else
10106         if ((x = cmcfm()) < 0) return(x);
10107         if (nopush) {
10108             printf("?Sorry, SPACE command disabled\n");
10109             return(-9);
10110         }
10111         xsystem(SPACMD);
10112 #endif /* UNIXOROSK */
10113 #endif /* OS2 */
10114 #endif /* datageneral */
10115         return(success = 1);            /* Pretend it worked */
10116     }
10117 #endif /* MAC */
10118
10119 #ifndef NOXFER
10120     if (cx == XXSTA) {                  /* STATISTICS */
10121         if ((x = cmkey(stattab,2,"Carriage return, or option",
10122                        "/brief",xxstring)) < 0)
10123           return(x);
10124         if ((y = cmcfm()) < 0) return(y);
10125         return(success = dostat(x));
10126     }
10127 #endif /* NOXFER */
10128
10129     if (cx == XXSTO || cx == XXEND) {   /* STOP, END, or POP */
10130         if ((y = cmnum("exit status code","0",10,&x,xxstring)) < 0)
10131           return(y);
10132         if ((y = cmtxt("Message to print","",&s,xxstring)) < 0)
10133           return(y);
10134         s = brstrip(s);
10135         if (*s) printf("%s\n",s);
10136         if (cx == XXSTO) {
10137             dostop();
10138         } else {
10139             doend(x);
10140         }
10141         return(success = (x == 0));
10142     }
10143     if (cx == XXSUS) {                  /* SUSPEND */
10144         if ((y = cmcfm()) < 0) return(y);
10145 #ifdef NOJC
10146         printf("Sorry, this version of Kermit cannot be suspended\n");
10147 #else
10148 #ifdef IKSD
10149         if (inserver) {
10150             printf("?Sorry, IKSD can not be suspended\n");
10151             return(-9);
10152         } else
10153 #endif /* IKSD */
10154           if (nopush) {
10155             printf("?Sorry, access to system is disabled\n");
10156             return(-9);
10157         }
10158         stptrap(0);
10159 #endif /* NOJC */
10160         return(0);
10161     }
10162
10163     if (cx == XXTAK) {                  /* TAKE */
10164         char * scriptenv = NULL;        
10165 #ifdef OS2
10166         char * GetAppData(int);
10167         extern char startupdir[],exedir[],inidir[];
10168         char * keymapenv = NULL;
10169         char * appdata0 = NULL, *appdata1 = NULL;
10170         int xx;
10171 #define TAKEPATHLEN 4096
10172 #else /* OS2 */
10173 #define TAKEPATHLEN 1024
10174 #endif /* OS2 */
10175         char takepath[TAKEPATHLEN];
10176
10177         if (tlevel >= MAXTAKE-1) {
10178             printf("?Take files nested too deeply\n");
10179             return(-9);
10180         }
10181 #ifdef OS2
10182 #ifdef NT
10183         scriptenv = getenv("K95SCRIPTS");
10184         keymapenv = getenv("K95KEYMAPS");
10185         makestr(&appdata0,(char *)GetAppData(0));
10186         makestr(&appdata1,(char *)GetAppData(1));
10187 #else /* NT */
10188         scriptenv = getenv("K2SCRIPTS");
10189         keymapenv = getenv("K2KEYMAPS");
10190 #endif /* NT */
10191 #endif /* OS2 */
10192
10193         if (!scriptenv)                 /* Let this work for Unix etc too */
10194           scriptenv = getenv("CK_SCRIPTS"); /* Use this if defined */
10195 #ifndef OS2
10196         if (!scriptenv)                 /* Otherwise use home directory */
10197           scriptenv = homepath();
10198 #endif /* OS2 */
10199         if (!scriptenv)
10200           scriptenv = "";
10201         ckstrncpy(takepath,scriptenv,TAKEPATHLEN);
10202         debug(F110,"TAKE initial takepath",takepath,0);
10203
10204 #ifdef OS2
10205         if (!keymapenv)
10206           keymapenv = getenv("CK_KEYMAPS");
10207         if (!keymapenv)
10208           keymapenv = "";
10209
10210         ckstrncat(takepath,
10211                   (scriptenv && scriptenv[strlen(scriptenv)-1]==';')?"":";",
10212                   TAKEPATHLEN
10213                   );
10214         ckstrncat(takepath,keymapenv?keymapenv:"",TAKEPATHLEN);
10215         ckstrncat(takepath,
10216                   (keymapenv && keymapenv[strlen(keymapenv)-1]==';')?"":";",
10217                   TAKEPATHLEN
10218                   );
10219         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10220         ckstrncat(takepath,";",TAKEPATHLEN);
10221         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10222         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10223         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10224         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10225
10226         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10227         ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
10228         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10229         ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
10230         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10231         ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
10232
10233         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10234         ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
10235         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10236         ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
10237         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10238         ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
10239
10240         ckstrncat(takepath,inidir,TAKEPATHLEN);
10241         ckstrncat(takepath,";",TAKEPATHLEN);
10242         ckstrncat(takepath,inidir,TAKEPATHLEN);
10243         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10244         ckstrncat(takepath,inidir,TAKEPATHLEN);
10245         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10246
10247         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10248         ckstrncat(takepath,";",TAKEPATHLEN);
10249         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10250         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10251         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10252         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10253
10254         ckstrncat(takepath,exedir,TAKEPATHLEN);
10255         ckstrncat(takepath,";",TAKEPATHLEN);
10256         ckstrncat(takepath,exedir,TAKEPATHLEN);
10257         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10258         ckstrncat(takepath,exedir,TAKEPATHLEN);
10259         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10260 #endif /* OS2 */
10261         debug(F110,"TAKE final takepath",takepath,0);
10262
10263         if ((y = cmifip("Commands from file",
10264                         "",&s,&x,0,takepath,xxstring)) < 0) {
10265             if (y == -3) {
10266                 printf("?A file name is required\n");
10267                 return(-9);
10268             } else
10269               return(y);
10270         }
10271         if (x != 0) {
10272             printf("?Wildcards not allowed in command file name\n");
10273             return(-9);
10274         }
10275         ckstrncpy(line,s,LINBUFSIZ);
10276         debug(F110,"TAKE file",s,0);
10277         if (isdir(s)) {
10278             printf("?Can't execute a directory - \"%s\"\n", s);
10279             return(-9);
10280         }
10281 #ifndef NOTAKEARGS
10282         {
10283             char * p;
10284             x = strlen(line);
10285             debug(F111,"TAKE args",line,x);
10286             p = line + x + 1;
10287             if ((y = cmtxt("Optional arguments","",&s,xxstring)) < 0)
10288               return(y);
10289             if (*s) {                   /* Args given? */
10290                 ckstrncpy(p,s,LINBUFSIZ-x-1);
10291 #ifdef ZFNQFP
10292                 zfnqfp(line,TMPBUFSIZ,tmpbuf);
10293                 s = tmpbuf;
10294 #else
10295                 s = line;
10296 #endif /* ZFNQFP */
10297                 debug(F110,"TAKE filename",s,0);
10298                 x = strlen(s);
10299                 debug(F101,"TAKE new len",s,x);
10300
10301 #ifdef COMMENT
10302 /*
10303   This was added in C-Kermit 7.0 to allow args to be passed from the TAKE
10304   command to the command file.  But it overwrites the current argument vector,
10305   which is at best surprising, and at worst unsafe.
10306 */
10307                 addmac("%0",s);         /* Define %0 = name of file */
10308                 varnam[0] = '%';
10309                 varnam[2] = '\0';
10310                 debug(F110,"take arg 0",s,0);
10311                 debug(F110,"take args",p,0);
10312                 for (y = 1; y < 10; y++) { /* Clear current args %1..%9 */
10313                     varnam[1] = (char) (y + '0');
10314                     delmac(varnam,0);
10315                 }
10316                 xwords(p,MAXARGLIST,NULL,0); /* Assign new args */
10317                 debug(F110,"take args",p,0);
10318 #else
10319 /*
10320   This method is used in 8.0.  If the TAKE command includes arguments, we
10321   insert an intermediate temporary macro between the current level; we pass
10322   the arguments to the macro and then the macro TAKEs the command file.
10323   If the user Ctrl-C's out of the TAKE file, some temporary macro definitions
10324   and other small malloc'd bits might be left behind.
10325 */
10326                 {
10327                     char * q = NULL;
10328                     char * r = NULL;
10329                     int k, m;
10330                     m = maclvl;
10331                     q = (char *)malloc(x+24);
10332                     if (q) {
10333                         r = (char *)malloc(x+24);
10334                         if (r) {
10335                             sprintf(q,"_file[%s](%d)",s,cmdlvl); /* safe */
10336                             sprintf(r,"take %s",s); /* safe */
10337                             k = addmac(q,r);
10338                             if (k > -1) {
10339                                 dodo(k,p,0);
10340                                 while (maclvl > m) {
10341                                     sstate = (CHAR) parser(1);
10342                                     if (sstate) proto();
10343                                 }
10344                             }
10345                             k = delmac(q,0);
10346                             free(q);
10347                             free(r);
10348                             return(success);
10349                         }
10350                     }
10351                 }
10352                 return(success = 0);
10353 #endif /* COMMENT */
10354             }
10355         }
10356 #else
10357         if ((y = cmcfm()) < 0) return(y);
10358 #endif /* NOTAKEARGS */
10359         return(success = dotake(line));
10360     }
10361
10362 #ifndef NOLOCAL
10363 #ifdef OS2
10364     if (cx == XXVIEW) {                 /* VIEW Only Terminal mode */
10365         viewonly = TRUE;
10366         success = doconect(0, 0);
10367         viewonly = FALSE;
10368         return success;
10369     }
10370 #endif /* OS2 */
10371
10372 #ifdef NETCONN
10373     if (cx == XXTEL || cx == XXIKSD) {  /* TELNET */
10374         int x,z;
10375 #ifdef OS2
10376     if (!tcp_avail) {
10377         printf("?Sorry, either TCP/IP is not available on this system or\n\
10378 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
10379         success = 0;
10380         return(-9);
10381     } else
10382 #endif /* OS2 */
10383       {
10384           x = nettype;                  /* Save net type in case of failure */
10385           z = ttnproto;                 /* Save protocol in case of failure */
10386           nettype = NET_TCPB;
10387           ttnproto = (cx == XXTEL) ? NP_TELNET : NP_KERMIT;
10388           if ((y = setlin(XYHOST,0,1)) <= 0) {
10389               nettype = x;              /* Failed, restore net type. */
10390               ttnproto = z;             /* and protocol */
10391               success = 0;
10392           }
10393           didsetlin++;
10394         }
10395         return(y);
10396     }
10397
10398 #ifndef PTYORPIPE
10399 #ifdef NETCMD
10400 #define PTYORPIPE
10401 #else
10402 #ifdef NETPTY
10403 #define PTYORPIPE
10404 #endif /* NETPTY */
10405 #endif /* NETCMD */
10406 #endif /* PTYORPIPE */
10407
10408 #ifdef PTYORPIPE
10409     if (cx == XXPIPE || cx == XXPTY) {  /* PIPE or PTY */
10410         int x;
10411         extern int netsave;
10412         x = nettype;                    /* Save net type in case of failure */
10413         nettype = (cx == XXPIPE) ? NET_CMD : NET_PTY;
10414         if ((y = setlin(XYHOST,0,1)) < 0) {
10415             nettype = x;                /* Failed, restore net type. */
10416             ttnproto = z;               /* and protocol */
10417             success = 0;
10418         }
10419         didsetlin++;
10420         netsave = x;
10421         return(y);
10422     }
10423 #endif /* PTYORPIPE */
10424
10425 #ifdef ANYSSH
10426     if (cx == XXSSH) {                  /* SSH (Secure Shell) */
10427         extern int netsave;
10428 #ifdef SSHBUILTIN
10429         int k, x, havehost = 0, trips = 0;
10430         int    tmpver = -1, tmpxfw = -1;
10431 #ifndef SSHTEST
10432         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
10433         extern int sl_ssh_ver, sl_ssh_ver_saved;
10434 #endif /* SSHTEST */
10435         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
10436         extern char * slmsg;
10437         extern char uidbuf[], sl_uidbuf[];
10438         extern char pwbuf[], * g_pswd;
10439         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
10440         struct FDB sw, kw, fl;
10441
10442         if (ssh_tmpstr)
10443           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
10444         makestr(&ssh_tmpstr,NULL);
10445         makestr(&ssh_tmpuid,NULL);
10446         makestr(&ssh_tmpcmd,NULL);
10447         makestr(&ssh_tmpport,NULL);
10448
10449         cmfdbi(&kw,                     /* 1st FDB - commands */
10450                _CMKEY,                  /* fcode */
10451                "host [ port ],\n or action",    /* hlpmsg */
10452                "",                      /* default */
10453                "",                      /* addtl string data */
10454                nsshcmd,                 /* addtl numeric data 1: tbl size */
10455                0,                       /* addtl numeric data 2: 0 = keyword */
10456                xxstring,                /* Processing function */
10457                sshkwtab,                /* Keyword table */
10458                &fl                      /* Pointer to next FDB */
10459                );
10460         cmfdbi(&fl,                     /* Host */
10461                _CMFLD,                  /* fcode */
10462                "",                      /* hlpmsg */
10463                "",                      /* default */
10464                "",                      /* addtl string data */
10465                0,                       /* addtl numeric data 1 */
10466                0,                       /* addtl numeric data 2 */
10467                xxstring,
10468                NULL,
10469                NULL
10470                );
10471
10472         x = cmfdb(&kw);
10473         if (x == -3) {
10474             printf("?ssh what?\n");
10475             return(-9);
10476         }
10477         if (x < 0)
10478           return(x);
10479         havehost = 0;
10480         if (cmresult.fcode == _CMFLD) {
10481             havehost = 1;
10482             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
10483             cmresult.nresult = XSSH_OPN;
10484         }
10485         switch (cmresult.nresult) {     /* SSH keyword */
10486           case XSSH_OPN:                /* SSH OPEN */
10487             if (!havehost) {
10488                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
10489                   return(x);
10490                 ckstrncpy(line,s,LINBUFSIZ);
10491             }
10492             /* Parse [ port ] [ switches ] */
10493             cmfdbi(&kw,                 /* Switches */
10494                    _CMKEY,
10495                    "Port number or service name,\nor switch",
10496                    "",
10497                    "",
10498                    nsshopnsw,
10499                    4,
10500                    xxstring,
10501                    sshopnsw,
10502                    &fl
10503                    );
10504             cmfdbi(&fl,                 /* Port number or service name */
10505                    _CMFLD,
10506                    "",
10507                    "",
10508                    "",
10509                    0,
10510                    0,
10511                    xxstring,
10512                    NULL,
10513                    NULL
10514                    );
10515             trips = 0;                  /* Explained below */
10516             while (1) {                 /* Parse port and switches */
10517                 x = cmfdb(&kw);         /* Get a field */
10518                 if (x == -3)            /* User typed CR so quit from loop */
10519                   break;
10520                 if (x < 0)              /* Other parse error, pass it back */
10521                   return(x);
10522                 switch (cmresult.fcode) { /* Field or Keyword? */
10523                   case _CMFLD:            /* Field */
10524                     makestr(&ssh_tmpport,cmresult.sresult);
10525                     break;
10526                   case _CMKEY:          /* Keyword */
10527                     switch (cmresult.nresult) { /* Which one? */
10528                       case SSHSW_USR:           /* /USER: */
10529                         if (!cmgbrk()) {
10530                             printf("?This switch requires an argument\n");
10531                             return(-9);
10532                         }
10533                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
10534                           return(y);
10535                         s = brstrip(s);
10536                         makestr(&ssh_tmpuid,s);
10537                         break;
10538                       case SSHSW_PWD:
10539                         if (!cmgbrk()) {
10540                             printf("?This switch requires an argument\n");
10541                             return(-9);
10542                         }
10543                         debok = 0;
10544                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
10545                             if (x == -3) {
10546                                 makestr(&ssh_tmpstr,"");
10547                             } else {
10548                                 return(x);
10549                             }
10550                         } else {
10551                             s = brstrip(s);
10552                             if ((x = (int)strlen(s)) > PWBUFL) {
10553                                 makestr(&slmsg,"Internal error");
10554                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
10555                                 return(-9);
10556                             }
10557                             makestr(&ssh_tmpstr,s);
10558                         }
10559                         break;
10560
10561                       case SSHSW_VER:
10562                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
10563                           return(x);
10564                         if (z < 1 || z > 2) {
10565                             printf("?Out of range: %d\n",z);
10566                             return(-9);
10567                         }
10568                         tmpver = z;
10569                         break;
10570                       case SSHSW_CMD:
10571                       case SSHSW_SUB:
10572                         if ((x = cmfld("Text","",&s,xxstring)) < 0)
10573                           return(x);
10574                         makestr(&ssh_tmpcmd,s);
10575                         ssh_cas = (cmresult.nresult == SSHSW_SUB);
10576                         break;
10577                       case SSHSW_X11:
10578                         if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
10579                           return(x);
10580                         tmpxfw = x;
10581                         break;
10582                       default:
10583                         return(-2);
10584                     }
10585                 }
10586                 if (trips++ == 0) {     /* After first time through */
10587                     cmfdbi(&kw,         /* only parse switches, not port. */
10588                            _CMKEY,
10589                            "Switch",
10590                            "",
10591                            "",
10592                            nsshopnsw,
10593                            4,
10594                            xxstring,
10595                            sshopnsw,
10596                            NULL
10597                            );
10598                 }
10599             }
10600             if ((x = cmcfm()) < 0)      /* Get confirmation */
10601               return(x);
10602             if (clskconnx(1) < 0) {     /* Close current Kermit connection */
10603               if ( ssh_tmpstr ) {
10604                   memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
10605                   makestr(&ssh_tmpstr,NULL);
10606               }
10607               return(success = 0);
10608             }
10609             makestr(&ssh_hst,line);     /* Stash everything */
10610             if (ssh_tmpuid) {
10611                 if (!sl_uid_saved) {
10612                     ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
10613                     sl_uid_saved = 1;
10614                 }
10615                 ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
10616                 makestr(&ssh_tmpuid,NULL);
10617             }
10618             if (ssh_tmpport) {
10619                 makestr(&ssh_prt,ssh_tmpport);
10620                 makestr(&ssh_tmpport,NULL);
10621             } else
10622                 makestr(&ssh_prt,NULL);
10623
10624             if (ssh_tmpcmd) {
10625                 makestr(&ssh_cmd,brstrip(ssh_tmpcmd));
10626                 makestr(&ssh_tmpcmd,NULL);
10627             } else
10628                 makestr(&ssh_cmd,NULL);
10629
10630             if (tmpver > -1) {
10631 #ifndef SSHTEST
10632                 if (!sl_ssh_ver_saved) {
10633                     sl_ssh_ver = ssh_ver;
10634                     sl_ssh_ver_saved = 1;
10635                 }
10636 #endif /* SSHTEST */
10637                 ssh_ver = tmpver;
10638             }
10639             if (tmpxfw > -1) {
10640 #ifndef SSHTEST
10641                 if (!sl_ssh_xfw_saved) {
10642                     sl_ssh_xfw = ssh_xfw;
10643                     sl_ssh_xfw_saved = 1;
10644                 }
10645 #endif /* SSHTEST */
10646                 ssh_xfw = tmpxfw;
10647             }
10648             if (ssh_tmpstr) {
10649                 if (ssh_tmpstr[0]) {
10650                     ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
10651                     pwflg = 1;
10652                     pwcrypt = 0;
10653                 } else
10654                   pwflg = 0;
10655                 makestr(&ssh_tmpstr,NULL);
10656             }
10657             nettype = NET_SSH;
10658             if (mdmsav < 0)
10659               mdmsav = mdmtyp;
10660             mdmtyp = -nettype;
10661             x = 1;
10662
10663 #ifndef NOSPL
10664             makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
10665             g_pflg = pwflg;                     /* and flag */
10666             g_pcpt = pwcrypt;
10667 #endif /* NOSPL */
10668
10669             /* Line parameter to ttopen() is ignored */
10670             debug(F110,"SSH line",line,0);
10671             k = ttopen(line,&x,mdmtyp, 0);
10672             if (k < 0) {
10673                 printf("?Unable to connect to %s\n",ssh_hst);
10674                 mdmtyp = mdmsav;
10675                 slrestor();
10676                 return(success = 0);
10677             }
10678             duplex = 0;             /* Remote echo */
10679             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
10680             debug(F110,"ssh ttname",ttname,0);
10681             makestr(&slmsg,NULL);       /* No SET LINE error message */
10682             cxtype = CXT_SSH;
10683 #ifndef NODIAL
10684             dialsta = DIA_UNK;
10685 #endif /* NODIAL */
10686             success = 1;                /* SET LINE succeeded */
10687             network = 1;                /* Network connection (not serial) */
10688             local = 1;                  /* Local mode (not remote) */
10689             if ((reliable != SET_OFF || !setreliable))
10690               reliable = SET_ON;        /* Transport is reliable end to end */
10691 #ifdef OS2
10692             DialerSend(OPT_KERMIT_CONNECT, 0);
10693 #endif /* OS2 */
10694             setflow();                  /* Set appropriate flow control */
10695
10696             haveline = 1;
10697 #ifdef CKLOGDIAL
10698 #ifdef NETCONN
10699             dolognet();
10700 #endif /* NETCONN */
10701 #endif /* CKLOGDIAL */
10702
10703 #ifndef NOSPL
10704             if (local) {
10705                 if (nmac) {             /* Any macros defined? */
10706                     int k;              /* Yes */
10707                     k = mlook(mactab,"on_open",nmac); /* Look this up */
10708                     if (k >= 0) {                     /* If found, */
10709                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
10710                           parser(1);                  /* and execute it */
10711                     }
10712                 }
10713             }
10714 #endif /* NOSPL */
10715 #ifdef LOCUS            
10716             if (autolocus)
10717                 setlocus(1,1);
10718 #endif /* LOCUS */
10719
10720         /* Command was confirmed so we can pre-pop command level. */
10721         /* This is so CONNECT module won't think we're executing a */
10722         /* script if CONNECT was the final command in the script. */
10723             if (cmdlvl > 0)
10724               prepop();
10725             success = doconect(0,cmdlvl == 0 ? 1 : 0);
10726             if (ttchk() < 0)
10727               dologend();
10728             return(success);
10729
10730           case XSSH_CLR:
10731             if ((y = cmkey(sshclr,nsshclr,"","", xxstring)) < 0) {
10732                 if (y == -3) {
10733                     printf("?clear what?\n");
10734                     return(-9);
10735                 }
10736                 return(y);
10737             }
10738             if ((x = cmcfm()) < 0)
10739               return(x);
10740             switch (y) {
10741               case SSHC_LPF:
10742                 ssh_pf_lcl_n = 0;
10743                 break;
10744               case SSHC_RPF:
10745                 ssh_pf_rmt_n = 0;
10746                 break;
10747               default:
10748                 return(-2);
10749             }
10750             return(success = 1);        /* or whatever */
10751
10752           case XSSH_AGT: {              /* SSH AGENT */
10753               int doeach = 0;
10754               if ((y = cmkey(sshagent,nsshagent,"","",xxstring)) < 0)
10755                 return(y);
10756               switch (y) {
10757                 case SSHA_ADD:          /* SSH AGENT ADD ... */
10758                   if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
10759 #ifndef SSHTEST
10760                       if (x == -3)      /* No name given */
10761                         doeach = 1;     /* so do them all */
10762                       else
10763 #endif /* SSHTEST */
10764                         return(x);
10765                   }
10766                   ckstrncpy(line,s,LINBUFSIZ);
10767                   if ((x = cmcfm()) < 0)
10768                     return(x);
10769 #ifdef SSHTEST
10770                   x = 0;
10771 #else
10772                   if (doeach) {
10773                       int i;
10774                       x = 0;
10775                       for (i = 0; i < ssh_idf_n; i++)
10776                         x += ssh_agent_add_file(ssh_idf[i]);
10777                   } else
10778                     x = ssh_agent_add_file(line);
10779 #endif /* SSHTEST */
10780                   return(success = (x == 0));
10781
10782                 case SSHA_DEL: {        /* SSH AGENT DELETE ... */
10783                     int doall = 0;
10784                     if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
10785 #ifndef SSHTEST
10786                         if (x == -3)    /* No name given */
10787                           doall = 1;    /* so do them all */
10788                         else
10789 #endif /* SSHTEST */
10790                           return(x);
10791                     }
10792                     ckstrncpy(line,s,LINBUFSIZ);
10793                     if ((x = cmcfm()) < 0)
10794                       return(x);
10795 #ifdef SSHTEST
10796                     x = 0;
10797 #else
10798                     if (doall)
10799                       x = ssh_agent_delete_all();
10800                     else
10801                       x = ssh_agent_delete_file(line);
10802 #endif /* SSHTEST */
10803                     return(success = (x == 0));
10804                 }
10805                 case SSHA_LST: {
10806                     int fingerprint = 0;
10807                     if ((y = cmswi(sshagtsw,nsshagtsw,"","",xxstring)) < 0) {
10808                         if (y != -3)
10809                           return(y);
10810                     } else if (cmgbrk() > SP) {
10811                         printf("?This switch does not take an argument\n");
10812                         return(-9);
10813                     } else if (y == SSHASW_FP) {
10814                         fingerprint = 1;
10815                     }
10816                     if ((x = cmcfm()) < 0)
10817                       return(x);
10818 #ifdef SSHTEST
10819                     return(success = 1);
10820 #else
10821                     return(success =
10822                            (ssh_agent_list_identities(fingerprint) == 0));
10823 #endif /* SSHTEST */
10824                 }
10825                 default:
10826                   return(-2);
10827               }
10828           }
10829           case XSSH_ADD: {              /* SSH ADD */
10830               /* ssh add { local, remote } port host port */
10831               int cx, i, j, k;
10832               char * h;
10833               if ((cx = cmkey(addfwd,naddfwd,"","", xxstring)) < 0)
10834                 return(cx);
10835               if ((x = cmnum((cx == SSHF_LCL) ?
10836                              "Local port number" : "Remote port number",
10837                              "",10,&j,xxstring)) < 0)
10838                 return(x);
10839               if ((x = cmfld("Host","",&s,xxstring)) < 0)
10840                 return(x);
10841               makestr(&h,s);
10842               if ((x = cmnum("Port","",10,&k,xxstring)) < 0)
10843                 return(x);
10844               if ((x = cmcfm()) < 0)
10845                 return(x);
10846
10847               switch(cx) {
10848                 case SSHF_LCL:
10849                    if (ssh_pf_lcl_n == 32) {
10850                        printf(
10851 "?Maximum number of local port forwardings already specified\n"
10852                              );
10853                        free(h);
10854                        return(success = 0);
10855                   }
10856                   ssh_pf_lcl[ssh_pf_lcl_n].p1 = j;
10857                   makestr(&(ssh_pf_lcl[ssh_pf_lcl_n].host),h);
10858                   makestr(&h,NULL);
10859                   ssh_pf_lcl[ssh_pf_lcl_n].p2 = k;
10860                   ssh_pf_lcl_n++;
10861                   break;
10862                 case SSHF_RMT:
10863                   if (ssh_pf_rmt_n == 32) {
10864                       printf(
10865 "?Maximum number of remote port forwardings already specified\n"
10866                             );
10867                       free(h);
10868                       return(success = 0);
10869                   }
10870                   ssh_pf_rmt[ssh_pf_rmt_n].p1 = j;
10871                   makestr(&(ssh_pf_rmt[ssh_pf_rmt_n].host),h);
10872                   makestr(&h,NULL);
10873                   ssh_pf_rmt[ssh_pf_rmt_n].p2 = k;
10874                   ssh_pf_rmt_n++;
10875               }
10876               return(success = 1);
10877           }
10878           /* Not supporting arbitrary forwarding yet */
10879           case XSSH_FLP:                /* SSH FORWARD-LOCAL-PORT */
10880           case XSSH_FRP: {              /* SSH FORWARD-REMOTE-PORT */
10881               int li_port = 0;
10882               int to_port = 0;
10883               char * fw_host = NULL;
10884               int n;
10885               if ((x = cmnum(cmresult.nresult == XSSH_FLP ?
10886                               "local-port":"remote-port",
10887                               "",10,&li_port,xxstring)) < 0)
10888                   return(x);
10889               if (li_port < 1 || li_port > 65535) {
10890                   printf("?Out range - min: 1, max: 65535\n");
10891                   return(-9);
10892               }
10893               if ((x = cmfld("host",ssh_hst?ssh_hst:"",&s,xxstring)) < 0)
10894                 return(x);
10895               n = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
10896               fw_host = tmpbuf;
10897               if ((x = cmnum("host-port",ckuitoa(li_port),10,
10898                               &to_port,xxstring)) < 0)
10899                   return(x);
10900               if (to_port < 1 || to_port > 65535) {
10901                   printf("?Out range - min: 1, max: 65535\n");
10902                   return(-9);
10903               }
10904               if ((x = cmcfm()) < 0)
10905                 return(x);
10906               switch (cmresult.nresult) {
10907                 case XSSH_FLP:  /* SSH FORWARD-LOCAL-PORT */
10908 #ifndef SSHTEST
10909                   ssh_fwd_local_port(li_port,fw_host,to_port);
10910 #endif /* SSHTEST */
10911                   return(success = 1);
10912                 case XSSH_FRP:  /* SSH FORWARD-REMOTE-PORT */
10913 #ifndef SSHTEST
10914                   ssh_fwd_remote_port(li_port,fw_host,to_port);
10915 #endif /* SSHTEST */
10916                   return(success = 1);
10917               }
10918               return(success = 1);
10919           }
10920         case XSSH_V2:           /* SSH V2 */
10921           if ((cx = cmkey(ssh2tab,nssh2tab,"","", xxstring)) < 0)
10922             return(cx);
10923           switch (cx) {
10924             case XSSH2_RKE:
10925               if ((x = cmcfm()) < 0)
10926                 return(x);
10927 #ifndef SSHTEST
10928               ssh_v2_rekey();
10929 #endif /* SSHTEST */
10930               return(success = 1);
10931             default:
10932               return(-2);
10933           }
10934         case XSSH_KEY:
10935           if ((cx = cmkey(sshkey,nsshkey,"","", xxstring)) < 0)
10936             return(cx);
10937           switch (cx) {
10938             case SSHK_PASS: {   /* Change passphrase */
10939               char * oldp = NULL, * newp = NULL;
10940               struct FDB df, sw;
10941               cmfdbi(&sw,
10942                      _CMKEY,            /* fcode */
10943                      "Filename, or switch", /* hlpmsg */
10944                      "",                /* default */
10945                      "",                /* addtl string data */
10946                      2,                 /* addtl numeric data 1: tbl size */
10947                      4,                 /* addtl numeric data 2: 4 = cmswi */
10948                      xxstring,          /* Processing function */
10949                      sshkpsw,           /* Keyword table */
10950                      &df                /* Pointer to next FDB */
10951                      );
10952               cmfdbi(&df,               /* 2nd FDB - file for display */
10953                      _CMIFI,            /* output file */
10954                      "",                /* hlpmsg */
10955                      "",                /* default */
10956                      "",                /* addtl string data */
10957                      0,                 /* addtl numeric data 1 */
10958                      0,                 /* addtl numeric data 2 */
10959                      xxstring,
10960                      NULL,
10961                      NULL
10962                      );
10963               line[0] = NUL;
10964
10965               while (1) {
10966                   x = cmfdb(&sw);
10967                   if (x == -3) break;
10968                   if (x < 0)
10969                     return(x);
10970                   if (cmresult.fcode != _CMKEY)
10971                     break;
10972                   if (!cmgbrk()) {
10973                       printf("?This switch requires an argument\n");
10974                       return(-9);
10975                   }
10976                   if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
10977                     return(y);
10978                   switch (cmresult.nresult) {
10979                     case 1:             /* Old */
10980                       makestr(&oldp,s);
10981                       break;
10982                     case 2:             /* New */
10983                       makestr(&newp,s);
10984                   }
10985               }
10986               if (cmresult.fcode == _CMIFI) { /* Filename */
10987                   ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
10988                   if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
10989                     ckstrncpy(line,tmpbuf,LINBUFSIZ);
10990               }
10991               if ((x = cmcfm()) < 0) return(x);
10992
10993 #ifndef SSHTEST
10994               x = sshkey_change_passphrase(line[0] ? line : NULL,
10995                                              oldp, newp);
10996 #endif /* SSHTEST */
10997               makestr(&oldp,NULL);
10998               makestr(&newp,NULL);
10999               success = (x == 0);
11000               return(success);
11001             }
11002             case SSHK_CREA: {   /* SSH KEY CREATE /switches... */
11003               int bits = 1024, keytype = SSHKT_2R;
11004               char * pass = NULL, * comment = NULL;
11005               struct FDB df, sw;
11006
11007               /*
11008                * char * sshkey_default_file(int keytype) 
11009                * will provide the default filename for a given keytype
11010                * is it possible to have the default value for the 2nd
11011                * FDB set and changed when a /TYPE switch is provided?
11012                * Would this allow for tab completion of the filename?
11013                */
11014               cmfdbi(&sw,
11015                      _CMKEY,            /* fcode */
11016                      "Filename, or switch", /* hlpmsg */
11017                      "",                /* default */
11018                      "",                /* addtl string data */
11019                      nsshkcrea,         /* addtl numeric data 1: tbl size */
11020                      4,                 /* addtl numeric data 2: 4 = cmswi */
11021                      xxstring,          /* Processing function */
11022                      sshkcrea,          /* Keyword table */
11023                      &df                /* Pointer to next FDB */
11024                      );
11025               cmfdbi(&df,               /* 2nd FDB - file for display */
11026                      _CMOFI,            /* output file */
11027                      "",                /* hlpmsg */
11028                      "",                /* default */
11029                      "",                /* addtl string data */
11030                      0,                 /* addtl numeric data 1 */
11031                      0,                 /* addtl numeric data 2 */
11032                      xxstring,
11033                      NULL,
11034                      NULL
11035                      );
11036               line[0] = NUL;
11037
11038               while (1) {
11039                   x = cmfdb(&sw);
11040                   if (x == -3) break;
11041                   if (x < 0)
11042                     return(x);
11043                   if (cmresult.fcode != _CMKEY)
11044                     break;
11045                   if (!cmgbrk()) {
11046                       printf("?This switch requires an argument\n");
11047                       return(-9);
11048                   }
11049                   switch (cmresult.nresult) {
11050                     case SSHKC_BI:      /* /BITS:n */
11051                       if ((y = cmnum("","1024",10,&z,xxstring)) < 0)
11052                         return(y);
11053                       if (z < 512 || z > 4096) {
11054                           printf("?Out range - min: 512, max: 4096\n");
11055                           return(-9);
11056                       }
11057                       bits = z;
11058                       break;
11059                     case SSHKC_PP:      /* /PASSPHRASE:blah */
11060                       if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
11061                         return(y);
11062                       makestr(&pass,s);
11063                       break;
11064                     case SSHKC_TY:      /* /TYPE:keyword */
11065                       if ((y = cmkey(sshkcty,nsshkcty,"",
11066                                      "v2-rsa",xxstring)) < 0)
11067                         return(y);
11068                       keytype = y;
11069                       break;
11070                     case SSHKC_1R:      /* /COMMENT */
11071                       if ((y = cmfld("Text","",&s,xxstring)) < 0)
11072                         return(y);
11073                       makestr(&comment,s);
11074                       break;
11075                   }
11076               }
11077               if (cmresult.fcode == _CMOFI) { /* Filename */
11078                   if (cmresult.sresult) {
11079                       ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
11080                       if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
11081                           ckstrncpy(line,tmpbuf,LINBUFSIZ);
11082                   }
11083               }
11084               if ((y = cmcfm()) < 0) /* Confirm */
11085                 return(y);
11086 #ifndef SSHTEST
11087               x = sshkey_create(line[0] ? line : NULL,
11088                                 bits, pass, keytype, comment);
11089               if (pass)
11090                 memset(pass,0,strlen(pass));
11091 #endif /* SSHTEST */
11092               makestr(&pass,NULL);
11093               makestr(&comment,NULL);
11094               return(success = (x == 0));
11095             }
11096             case SSHK_DISP: {   /* SSH KEY DISPLAY /switches... */
11097               char c;
11098               int infmt = 0, outfmt = 0;
11099               struct FDB df, sw;
11100               cmfdbi(&sw,
11101                      _CMKEY,            /* fcode */
11102                      "Filename, or switch", /* hlpmsg */
11103                      "",                /* default */
11104                      "",                /* addtl string data */
11105                      nsshdswi,          /* addtl numeric data 1: tbl size */
11106                      4,                 /* addtl numeric data 2: 4 = cmswi */
11107                      xxstring,          /* Processing function */
11108                      sshdswi,           /* Keyword table */
11109                      &df                /* Pointer to next FDB */
11110                      );
11111               cmfdbi(&df,               /* 2nd FDB - file for display */
11112                      _CMIFI,            /* fcode */
11113                      "",                /* hlpmsg */
11114                      "",                /* default */
11115                      "",                /* addtl string data */
11116                      0,                 /* addtl numeric data 1 */
11117                      0,                 /* addtl numeric data 2 */
11118                      xxstring,
11119                      NULL,
11120                      NULL
11121                      );
11122               line[0] = NUL;
11123
11124               while (1) {
11125                   x = cmfdb(&sw);
11126                   if (x == -3) break;
11127                   if (x < 0)
11128                     return(x);
11129                   if (cmresult.fcode != _CMKEY)
11130                     break;
11131                   if (!cmgbrk()) {
11132                       printf("?This switch requires an argument\n");
11133                       return(-9);
11134                   }
11135                   switch (cmresult.nresult) {
11136 #ifdef COMMENT
11137                     case SSHKD_IN:      /* /IN-FORMAT: */
11138                       if ((y = cmkey(sshdifmt,nsshdifmt,
11139                                      "","",xxstring)) < 0)
11140                         return(y);
11141                       infmt = y;
11142                       break;
11143 #endif /* COMMENT */
11144                     case SSHKD_OUT:     /* /FORMAT: */
11145                       if ((y = cmkey(sshdofmt,nsshdofmt,
11146                                      "","",xxstring)) < 0)
11147                         return(y);
11148                       outfmt = y;
11149                       break;
11150                   }
11151               }
11152               if (cmresult.fcode == _CMIFI) { /* Filename */
11153                   ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
11154                   if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
11155                     ckstrncpy(line,tmpbuf,LINBUFSIZ);
11156               }
11157 #ifdef COMMENT
11158               if (!line[0]) {
11159                   printf("?Key filename required\n");
11160                   return(-9);
11161               }
11162 #endif /* COMMENT */
11163               if ((y = cmcfm()) < 0) /* Confirm */
11164                 return(y);
11165 #ifndef SSHTEST
11166               switch (outfmt) {
11167                 case SKDF_OSSH:
11168                   /* 2nd param is optional passphrase */
11169                   x = sshkey_display_public(line[0] ? line : NULL, NULL);
11170                   break;
11171                 case SKDF_SSHC:
11172                   /* 2nd param is optional passphrase */
11173                   x = sshkey_display_public_as_ssh2(line[0] ? line : NULL,
11174                                                     NULL);
11175                   break;
11176                 case SKDF_IETF:
11177                   x = sshkey_display_fingerprint(line[0] ? line : NULL, 1);
11178                   break;
11179                 case SKDF_FING:
11180                   x = sshkey_display_fingerprint(line[0] ? line : NULL, 0);
11181                   break;
11182               }
11183 #endif /* SSHTEST */
11184               return(success = (x == 0));
11185             }
11186             case SSHK_V1:               /* SSH KEY V1 SET-COMMENT */
11187               if ((x = cmkey(sshkv1,1,"","set-comment", xxstring)) < 0)
11188                 return(x);
11189               if (x != 1) return(-2);
11190               if ((x = cmifi("Key file name","",&s,&y,xxstring)) < 0) {
11191                   if (x == -3) {
11192                       printf("?Name of key file required\n");
11193                       return(-9);
11194                   }
11195               }
11196               ckstrncpy(line,s,LINBUFSIZ);
11197               if ((x = cmtxt("Comment text","",&s,xxstring)) < 0)
11198                 return(x);
11199 #ifndef SSHTEST
11200               x = sshkey_v1_change_comment(line,  /* filename */
11201                                            s,     /* new comment */
11202                                            NULL   /* passphrase */
11203                                            );
11204 #endif /* SSHTEST */
11205               success = (x == 0);
11206               return(success);
11207           }
11208           default:
11209             return(-2);
11210         }
11211 #else  /* SSHBUILTIN */
11212 #ifdef SSHCMD
11213         x = nettype;
11214         if ((y = setlin(XXSSH,0,1)) < 0) {
11215             if (errno)
11216               printf("?%s\n",ck_errstr());
11217             else
11218 #ifdef COMMENT
11219             /* This isn't right either because it catches command editing */
11220               printf("?Sorry, pseudoterminal open failed\n");
11221             if (hints)
11222               printf("Hint: Try \"ssh -t %s\"\n",line);
11223 #else
11224               return(y);
11225 #endif /* COMMENT */
11226             nettype = x;                /* Failed, restore net type. */
11227             ttnproto = z;               /* and protocol */
11228             success = 0;
11229         }
11230         didsetlin++;
11231         netsave = x;
11232         return(y);
11233 #endif /* SSHCMD */
11234 #endif /* SSHBUILTIN */
11235     }
11236 #endif /* ANYSSH */
11237
11238 #ifdef SSHBUILTIN
11239     if (cx == XXSKRM) {                 /* SKERMIT (Secure Shell Kermit) */
11240         extern int netsave;
11241         int k, x, havehost = 0, trips = 0;
11242         int    tmpver = -1, tmpxfw = -1;
11243 #ifndef SSHTEST
11244         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
11245         extern int sl_ssh_ver, sl_ssh_ver_saved;
11246 #endif /* SSHTEST */
11247         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
11248         extern char * slmsg;
11249         extern char uidbuf[], sl_uidbuf[];
11250         extern char pwbuf[], * g_pswd;
11251         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
11252         struct FDB sw, kw, fl;
11253
11254         if (ssh_tmpstr)
11255           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11256         makestr(&ssh_tmpstr,NULL);
11257         makestr(&ssh_tmpuid,NULL);
11258         makestr(&ssh_tmpcmd,NULL);
11259         makestr(&ssh_tmpport,NULL);
11260
11261         cmfdbi(&kw,                     /* 1st FDB - commands */
11262                _CMKEY,                  /* fcode */
11263                "host [ port ],\n or action", /* hlpmsg */
11264                "",                      /* default */
11265                "",                      /* addtl string data */
11266                nsshkermit,              /* addtl numeric data 1: tbl size */
11267                0,                       /* addtl numeric data 2: 0 = keyword */
11268                xxstring,                /* Processing function */
11269                sshkermit,               /* Keyword table */
11270                &fl                      /* Pointer to next FDB */
11271                );
11272         cmfdbi(&fl,                     /* Host */
11273                _CMFLD,                  /* fcode */
11274                "",                      /* hlpmsg */
11275                "",                      /* default */
11276                "",                      /* addtl string data */
11277                0,                       /* addtl numeric data 1 */
11278                0,                       /* addtl numeric data 2 */
11279                xxstring,
11280                NULL,
11281                NULL
11282                );
11283
11284         x = cmfdb(&kw);
11285         if (x == -3) {
11286             printf("?skermit what?\n");
11287             return(-9);
11288         }
11289         if (x < 0)
11290           return(x);
11291         havehost = 0;
11292         if (cmresult.fcode == _CMFLD) {
11293             havehost = 1;
11294             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
11295             cmresult.nresult = SKRM_OPN;
11296         }
11297         switch (cmresult.nresult) {     /* SSH keyword */
11298           case SKRM_OPN:                /* SSH OPEN */
11299             if (!havehost) {
11300                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
11301                   return(x);
11302                 ckstrncpy(line,s,LINBUFSIZ);
11303             }
11304             /* Parse [ port ] [ switches ] */
11305             cmfdbi(&kw,                 /* Switches */
11306                    _CMKEY,
11307                    "Port number or service name,\nor switch",
11308                    "",
11309                    "",
11310                    nsshkrmopnsw,
11311                    4,
11312                    xxstring,
11313                    sshkrmopnsw,
11314                    &fl
11315                    );
11316             cmfdbi(&fl,                 /* Port number or service name */
11317                    _CMFLD,
11318                    "",
11319                    "",
11320                    "",
11321                    0,
11322                    0,
11323                    xxstring,
11324                    NULL,
11325                    NULL
11326                    );
11327             trips = 0;                  /* Explained below */
11328             while (1) {                 /* Parse port and switches */
11329                 x = cmfdb(&kw);         /* Get a field */
11330                 if (x == -3)            /* User typed CR so quit from loop */
11331                   break;
11332                 if (x < 0)              /* Other parse error, pass it back */
11333                   return(x);
11334                 switch (cmresult.fcode) { /* Field or Keyword? */
11335                   case _CMFLD:            /* Field */
11336                     makestr(&ssh_tmpport,cmresult.sresult);
11337                     break;
11338                   case _CMKEY:          /* Keyword */
11339                     switch (cmresult.nresult) { /* Which one? */
11340                       case SSHSW_USR:           /* /USER: */
11341                         if (!cmgbrk()) {
11342                             printf("?This switch requires an argument\n");
11343                             return(-9);
11344                         }
11345                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
11346                           return(y);
11347                         s = brstrip(s);
11348                         makestr(&ssh_tmpuid,s);
11349                         break;
11350                       case SSHSW_PWD:
11351                         if (!cmgbrk()) {
11352                             printf("?This switch requires an argument\n");
11353                             return(-9);
11354                         }
11355                         debok = 0;
11356                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
11357                             if (x == -3) {
11358                                 makestr(&ssh_tmpstr,"");
11359                             } else {
11360                                 return(x);
11361                             }
11362                         } else {
11363                             s = brstrip(s);
11364                             if ((x = (int)strlen(s)) > PWBUFL) {
11365                                 makestr(&slmsg,"Internal error");
11366                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
11367                                 return(-9);
11368                             }
11369                             makestr(&ssh_tmpstr,s);
11370                         }
11371                         break;
11372
11373                     case SSHSW_VER:
11374                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
11375                           return(x);
11376                         if (z < 1 || z > 2) {
11377                             printf("?Out of range: %d\n",z);
11378                             return(-9);
11379                         }
11380                         tmpver = z;
11381                         break;
11382                     default:
11383                         return(-2);
11384                     }
11385                   }
11386                 if (trips++ == 0) {     /* After first time through */
11387                     cmfdbi(&kw,         /* only parse switches, not port. */
11388                            _CMKEY,
11389                            "Switch",
11390                            "",
11391                            "",
11392                            nsshkrmopnsw,
11393                            4,
11394                            xxstring,
11395                            sshkrmopnsw,
11396                            NULL
11397                            );
11398                 }
11399             }
11400             if ((x = cmcfm()) < 0)      /* Get confirmation */
11401               return(x);
11402               if (clskconnx(1) < 0) {   /* Close current Kermit connection */
11403                   if ( ssh_tmpstr ) {
11404                       memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11405                       makestr(&ssh_tmpstr,NULL);
11406                   }
11407                   return(success = 0);
11408               }
11409               makestr(&ssh_hst,line);   /* Stash everything */
11410               if (ssh_tmpuid) {
11411                   if (!sl_uid_saved) {
11412                       ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
11413                       sl_uid_saved = 1;
11414                   }
11415                   ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
11416                   makestr(&ssh_tmpuid,NULL);
11417               }
11418               if (ssh_tmpport) {
11419                   makestr(&ssh_prt,ssh_tmpport);
11420                   makestr(&ssh_tmpport,NULL);
11421               } else
11422                   makestr(&ssh_prt,NULL);
11423
11424               /* Set the Subsystem to Kermit */
11425               ssh_cas = 1;
11426               makestr(&ssh_cmd,"kermit");
11427
11428               if (tmpver > -1) {
11429 #ifndef SSHTEST
11430                   if (!sl_ssh_ver_saved) {
11431                       sl_ssh_ver = ssh_ver;
11432                       sl_ssh_ver_saved = 1;
11433                   }
11434 #endif /* SSHTEST */
11435                   ssh_ver = tmpver;
11436               }
11437               /* Disable X11 Forwarding */
11438 #ifndef SSHTEST
11439               if (!sl_ssh_xfw_saved) {
11440                   sl_ssh_xfw = ssh_xfw;
11441                   sl_ssh_xfw_saved = 1;
11442               }
11443 #endif /* SSHTEST */
11444               ssh_xfw = 0;
11445
11446               if (ssh_tmpstr) {
11447                   if (ssh_tmpstr[0]) {
11448                       ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
11449                       pwflg = 1;
11450                       pwcrypt = 0;
11451                   } else
11452                       pwflg = 0;
11453                   makestr(&ssh_tmpstr,NULL);
11454               }
11455               nettype = NET_SSH;
11456               if (mdmsav < 0)
11457                   mdmsav = mdmtyp;
11458               mdmtyp = -nettype;
11459               x = 1;
11460
11461 #ifndef NOSPL
11462             makestr(&g_pswd,pwbuf);     /* Save global pwbuf */
11463             g_pflg = pwflg;             /* and flag */
11464             g_pcpt = pwcrypt;
11465 #endif /* NOSPL */
11466
11467             /* Line parameter to ttopen() is ignored */
11468             k = ttopen(line,&x,mdmtyp, 0);
11469             if (k < 0) {
11470                 printf("?Unable to connect to %s\n",ssh_hst);
11471                 mdmtyp = mdmsav;
11472                 slrestor();
11473                 return(success = 0);
11474             }
11475             duplex = 0;             /* Remote echo */
11476             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
11477             debug(F110,"ssh ttname",ttname,0);
11478             makestr(&slmsg,NULL);       /* No SET LINE error message */
11479             cxtype = CXT_SSH;
11480 #ifndef NODIAL
11481             dialsta = DIA_UNK;
11482 #endif /* NODIAL */
11483             success = 1;                /* SET LINE succeeded */
11484             network = 1;                /* Network connection (not serial) */
11485             local = 1;                  /* Local mode (not remote) */
11486             if ((reliable != SET_OFF || !setreliable))
11487               reliable = SET_ON;        /* Transport is reliable end to end */
11488 #ifdef OS2
11489             DialerSend(OPT_KERMIT_CONNECT, 0);
11490 #endif /* OS2 */
11491             setflow();                  /* Set appropriate flow control */
11492
11493             haveline = 1;
11494 #ifdef CKLOGDIAL
11495 #ifdef NETCONN
11496             dolognet();
11497 #endif /* NETCONN */
11498 #endif /* CKLOGDIAL */
11499
11500 #ifndef NOSPL
11501             if (local) {
11502                 if (nmac) {             /* Any macros defined? */
11503                     int k;              /* Yes */
11504                     k = mlook(mactab,"on_open",nmac); /* Look this up */
11505                     if (k >= 0) {                     /* If found, */
11506                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
11507                           parser(1);                  /* and execute it */
11508                     }
11509                 }
11510             }
11511 #endif /* NOSPL */
11512 #ifdef LOCUS            
11513             if (autolocus)
11514                 setlocus(1,1);
11515 #endif /* LOCUS */
11516
11517         /* Command was confirmed so we can pre-pop command level. */
11518         /* This is so CONNECT module won't think we're executing a */
11519         /* script if CONNECT was the final command in the script. */
11520             if (cmdlvl > 0)
11521               prepop();
11522             return(success = 1);
11523
11524           default:
11525             return(-2);
11526         }
11527     }
11528 #endif /* SSHBUILTIN */
11529
11530 #ifdef SFTP_BUILTIN
11531     if (cx == XXSFTP) {                 /* SFTP (Secure Shell File Transfer) */
11532         extern int netsave;
11533         int k, x, havehost = 0, trips = 0;
11534         int    tmpver = -1, tmpxfw = -1;
11535 #ifndef SSHTEST
11536         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
11537         extern int sl_ssh_ver, sl_ssh_ver_saved;
11538 #endif /* SSHTEST */
11539         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
11540         extern char * slmsg;
11541         extern char uidbuf[], sl_uidbuf[];
11542         extern char pwbuf[], * g_pswd;
11543         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
11544         struct FDB sw, kw, fl;
11545
11546         if (ssh_tmpstr)
11547           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11548         makestr(&ssh_tmpstr,NULL);
11549         makestr(&ssh_tmpuid,NULL);
11550         makestr(&ssh_tmpcmd,NULL);
11551         makestr(&ssh_tmpport,NULL);
11552
11553         cmfdbi(&kw,                     /* 1st FDB - commands */
11554                _CMKEY,                  /* fcode */
11555                "host [ port ],\n or action", /* hlpmsg */
11556                "",                      /* default */
11557                "",                      /* addtl string data */
11558                nsftpkwtab,              /* addtl numeric data 1: tbl size */
11559                0,                       /* addtl numeric data 2: 0 = keyword */
11560                xxstring,                /* Processing function */
11561                sftpkwtab,               /* Keyword table */
11562                &fl                      /* Pointer to next FDB */
11563                );
11564         cmfdbi(&fl,                     /* Host */
11565                _CMFLD,                  /* fcode */
11566                "",                      /* hlpmsg */
11567                "",                      /* default */
11568                "",                      /* addtl string data */
11569                0,                       /* addtl numeric data 1 */
11570                0,                       /* addtl numeric data 2 */
11571                xxstring,
11572                NULL,
11573                NULL
11574                );
11575
11576         x = cmfdb(&kw);
11577         if (x == -3) {
11578             printf("?sftp what?\n");
11579             return(-9);
11580         }
11581         if (x < 0)
11582           return(x);
11583         havehost = 0;
11584         if (cmresult.fcode == _CMFLD) {
11585             havehost = 1;
11586             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
11587             cmresult.nresult = SFTP_OPN;
11588         }
11589         switch (cmresult.nresult) {     /* SFTP keyword */
11590           case SFTP_OPN:                /* SFTP OPEN */
11591             if (!havehost) {
11592                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
11593                   return(x);
11594                 ckstrncpy(line,s,LINBUFSIZ);
11595             }
11596             /* Parse [ port ] [ switches ] */
11597             cmfdbi(&kw,                 /* Switches */
11598                    _CMKEY,
11599                    "Port number or service name,\nor switch",
11600                    "",
11601                    "",
11602                    nsshkrmopnsw,
11603                    4,
11604                    xxstring,
11605                    sshkrmopnsw,
11606                    &fl
11607                    );
11608             cmfdbi(&fl,                 /* Port number or service name */
11609                    _CMFLD,
11610                    "",
11611                    "",
11612                    "",
11613                    0,
11614                    0,
11615                    xxstring,
11616                    NULL,
11617                    NULL
11618                    );
11619             trips = 0;                  /* Explained below */
11620             while (1) {                 /* Parse port and switches */
11621                 x = cmfdb(&kw);         /* Get a field */
11622                 if (x == -3)            /* User typed CR so quit from loop */
11623                   break;
11624                 if (x < 0)              /* Other parse error, pass it back */
11625                   return(x);
11626                 switch (cmresult.fcode) { /* Field or Keyword? */
11627                   case _CMFLD:            /* Field */
11628                     makestr(&ssh_tmpport,cmresult.sresult);
11629                     break;
11630                   case _CMKEY:          /* Keyword */
11631                     switch (cmresult.nresult) { /* Which one? */
11632                       case SSHSW_USR:           /* /USER: */
11633                         if (!cmgbrk()) {
11634                             printf("?This switch requires an argument\n");
11635                             return(-9);
11636                         }
11637                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
11638                           return(y);
11639                         s = brstrip(s);
11640                         makestr(&ssh_tmpuid,s);
11641                         break;
11642                       case SSHSW_PWD:
11643                         if (!cmgbrk()) {
11644                             printf("?This switch requires an argument\n");
11645                             return(-9);
11646                         }
11647                         debok = 0;
11648                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
11649                             if (x == -3) {
11650                                 makestr(&ssh_tmpstr,"");
11651                             } else {
11652                                 return(x);
11653                             }
11654                         } else {
11655                             s = brstrip(s);
11656                             if ((x = (int)strlen(s)) > PWBUFL) {
11657                                 makestr(&slmsg,"Internal error");
11658                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
11659                                 return(-9);
11660                             }
11661                             makestr(&ssh_tmpstr,s);
11662                         }
11663                         break;
11664
11665                     case SSHSW_VER:
11666                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
11667                           return(x);
11668                         if (z < 1 || z > 2) {
11669                             printf("?Out of range: %d\n",z);
11670                             return(-9);
11671                         }
11672                         tmpver = z;
11673                         break;
11674                     default:
11675                         return(-2);
11676                     }
11677                 }
11678                 if (trips++ == 0) {     /* After first time through */
11679                     cmfdbi(&kw,         /* only parse switches, not port. */
11680                            _CMKEY,
11681                            "Switch",
11682                            "",
11683                            "",
11684                            nsshkrmopnsw,
11685                            4,
11686                            xxstring,
11687                            sshkrmopnsw,
11688                            NULL
11689                            );
11690                 }
11691             }
11692             if ((x = cmcfm()) < 0)      /* Get confirmation */
11693               return(x);
11694               if (clskconnx(1) < 0) {   /* Close current Kermit connection */
11695                   if ( ssh_tmpstr ) {
11696                       memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11697                       makestr(&ssh_tmpstr,NULL);
11698                   }
11699                   return(success = 0);
11700               }
11701               makestr(&ssh_hst,line);   /* Stash everything */
11702               if (ssh_tmpuid) {
11703                   if (!sl_uid_saved) {
11704                       ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
11705                       sl_uid_saved = 1;
11706                   }
11707                   ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
11708                   makestr(&ssh_tmpuid,NULL);
11709               }
11710               if (ssh_tmpport) {
11711                   makestr(&ssh_prt,ssh_tmpport);
11712                   makestr(&ssh_tmpport,NULL);
11713               } else
11714                   makestr(&ssh_prt,NULL);
11715
11716               /* Set the Subsystem to Kermit */
11717               ssh_cas = 1;
11718               makestr(&ssh_cmd,"sftp");
11719
11720               if (tmpver > -1) {
11721 #ifndef SSHTEST
11722                   if (!sl_ssh_ver_saved) {
11723                       sl_ssh_ver = ssh_ver;
11724                       sl_ssh_ver_saved = 1;
11725                   }
11726 #endif /* SSHTEST */
11727                   ssh_ver = tmpver;
11728               }
11729               /* Disable X11 Forwarding */
11730 #ifndef SSHTEST
11731               if (!sl_ssh_xfw_saved) {
11732                   sl_ssh_xfw = ssh_xfw;
11733                   sl_ssh_xfw_saved = 1;
11734               }
11735 #endif /* SSHTEST */
11736               ssh_xfw = 0;
11737
11738               if (ssh_tmpstr) {
11739                   if (ssh_tmpstr[0]) {
11740                       ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
11741                       pwflg = 1;
11742                       pwcrypt = 0;
11743                   } else
11744                       pwflg = 0;
11745                   makestr(&ssh_tmpstr,NULL);
11746               }
11747               nettype = NET_SSH;
11748               if (mdmsav < 0)
11749                   mdmsav = mdmtyp;
11750               mdmtyp = -nettype;
11751               x = 1;
11752
11753 #ifndef NOSPL
11754             makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
11755             g_pflg = pwflg;                     /* and flag */
11756             g_pcpt = pwcrypt;
11757 #endif /* NOSPL */
11758
11759             /* Line parameter to ttopen() is ignored */
11760             k = ttopen(line,&x,mdmtyp, 0);
11761             if (k < 0) {
11762                 printf("?Unable to connect to %s\n",ssh_hst);
11763                 mdmtyp = mdmsav;
11764                 slrestor();
11765                 return(success = 0);
11766             }
11767             duplex = 0;             /* Remote echo */
11768             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
11769             debug(F110,"ssh ttname",ttname,0);
11770             makestr(&slmsg,NULL);       /* No SET LINE error message */
11771             cxtype = CXT_SSH;
11772 #ifndef NODIAL
11773             dialsta = DIA_UNK;
11774 #endif /* NODIAL */
11775             success = 1;                /* SET LINE succeeded */
11776             network = 1;                /* Network connection (not serial) */
11777             local = 1;                  /* Local mode (not remote) */
11778             if ((reliable != SET_OFF || !setreliable))
11779               reliable = SET_ON;        /* Transport is reliable end to end */
11780 #ifdef OS2
11781             DialerSend(OPT_KERMIT_CONNECT, 0);
11782 #endif /* OS2 */
11783             setflow();                  /* Set appropriate flow control */
11784
11785             haveline = 1;
11786 #ifdef CKLOGDIAL
11787 #ifdef NETCONN
11788             dolognet();
11789 #endif /* NETCONN */
11790 #endif /* CKLOGDIAL */
11791
11792 #ifndef NOSPL
11793             if (local) {
11794                 if (nmac) {             /* Any macros defined? */
11795                     int k;              /* Yes */
11796                     k = mlook(mactab,"on_open",nmac); /* Look this up */
11797                     if (k >= 0) {                     /* If found, */
11798                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
11799                           parser(1);                  /* and execute it */
11800                     }
11801                 }
11802             }
11803 #endif /* NOSPL */
11804 #ifdef LOCUS            
11805             if (autolocus)
11806                 setlocus(1,1);
11807 #endif /* LOCUS */
11808
11809         /* Command was confirmed so we can pre-pop command level. */
11810         /* This is so CONNECT module won't think we're executing a */
11811         /* script if CONNECT was the final command in the script. */
11812             if (cmdlvl > 0)
11813               prepop();
11814
11815             success = sftp_do_init();
11816             return(success = 1);
11817
11818           case SFTP_CD:
11819           case SFTP_CHGRP:
11820           case SFTP_CHMOD:
11821           case SFTP_CHOWN:
11822           case SFTP_RM:
11823           case SFTP_DIR:
11824           case SFTP_GET:
11825           case SFTP_MKDIR:
11826           case SFTP_PUT:
11827           case SFTP_PWD:
11828           case SFTP_REN:
11829           case SFTP_RMDIR:
11830           case SFTP_LINK:
11831           case SFTP_VER:
11832             if ((y = cmtxt("command parameters","",&s,xxstring)) < 0) 
11833               return(y);
11834             if (ssh_tchk() < 0 || !ssh_cas || strcmp(ssh_cmd,"sftp")) {
11835                 printf("?Not connected to SFTP Service\n");
11836                 return(success = 0);
11837             }
11838             success = sftp_do_cmd(cmresult.nresult,s);
11839             return(success);
11840           default:
11841             return(-2);
11842         }
11843     }
11844 #endif /* SFTP_BUILTIN */
11845
11846     if (cx == XXRLOG) {                 /* RLOGIN */
11847 #ifdef RLOGCODE
11848         int x,z;
11849 #ifdef OS2
11850         if (!tcp_avail) {
11851             printf("?Sorry, either TCP/IP is not available on this system or\n\
11852 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
11853                    );
11854             success = 0;
11855             return(-9);
11856         } else {
11857 #endif /* OS2 */
11858             x = nettype;                /* Save net type in case of failure */
11859             z = ttnproto;               /* Save protocol in case of failure */
11860             nettype = NET_TCPB;
11861             ttnproto = NP_RLOGIN;
11862             if ((y = setlin(XYHOST,0,1)) <= 0) {
11863                 nettype = x;            /* Failed, restore net type. */
11864                 ttnproto = z;           /* and protocol */
11865                 success = 0;
11866             }
11867             didsetlin++;
11868 #ifdef OS2
11869         }
11870 #endif /* OS2 */
11871         return(y);
11872 #else
11873         printf("?Sorry, RLOGIN is not configured in this copy of C-Kermit.\n");
11874         return(-9);
11875 #endif /* RLOGCODE */
11876     }
11877 #endif /* NETCONN */
11878 #endif /* NOLOCAL */
11879
11880 #ifndef NOXMIT
11881     if (cx == XXTRA) {                  /* TRANSMIT */
11882         extern int xfrxla;
11883         int i, n, xpipe = 0, xbinary = 0, xxlate = 1, xxnowait = 0, getval;
11884         int xxecho = 0;
11885         int scan = 1;
11886         char c;
11887         struct FDB sf, sw, tx;          /* FDBs for parse functions */
11888 #ifndef NOCSETS
11889         extern int tcs_transp;          /* Term charset is transparent */
11890 #else
11891         int tcs_transp = 1;
11892 #endif /* NOCSETS */
11893
11894 #ifdef COMMENT
11895         xbinary = binary;               /* Default text/binary mode */
11896 #else
11897         xbinary = 0;                    /* Default is text */
11898 #endif /* COMMENT */
11899         xxecho = xmitx;
11900
11901         cmfdbi(&sw,                     /* First FDB - command switches */
11902                _CMKEY,                  /* fcode */
11903                "Filename, or switch",   /* hlpmsg */
11904                "",                      /* default */
11905                "",                      /* addtl string data */
11906                nxmitsw,                 /* addtl numeric data 1: tbl size */
11907                4,                       /* addtl numeric data 2: 4 = cmswi */
11908                xxstring,                /* Processing function */
11909                xmitsw,                  /* Keyword table */
11910                &sf                      /* Pointer to next FDB */
11911                );
11912         cmfdbi(&sf,                     /* 2nd FDB - file to send */
11913                _CMIFI,                  /* fcode */
11914                "File to transmit",      /* hlpmsg */
11915                "",                      /* default */
11916                "",                      /* addtl string data */
11917                0,                       /* addtl numeric data 1 */
11918                0,                       /* addtl numeric data 2 */
11919                xxstring,
11920                NULL,
11921 #ifdef PIPESEND
11922                &tx
11923 #else
11924                NULL
11925 #endif /* PIPESEND */
11926                );
11927 #ifdef PIPESEND
11928         cmfdbi(&tx,
11929                _CMTXT,                  /* fcode */
11930                "Command",               /* hlpmsg */
11931                "",                      /* default */
11932                "",                      /* addtl string data */
11933                0,                       /* addtl numeric data 1 */
11934                0,                       /* addtl numeric data 2 */
11935                xxstring,
11936                NULL,
11937                NULL
11938                );
11939 #endif /* PIPESEND */
11940
11941         while (1) {
11942             x = cmfdb(&sw);
11943             if (x < 0)
11944               return(x);
11945             if (cmresult.fcode != _CMKEY)
11946               break;
11947             c = cmgbrk();               /* Have switch, get break character */
11948             if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
11949                 printf("?This switch does not take an argument\n");
11950                 return(-9);
11951             }
11952             if (!getval && (cmgkwflgs() & CM_ARG)) {
11953                 printf("?This switch requires an argument\n");
11954                 return(-9);
11955             }
11956             n = cmresult.nresult;       /* Numeric result = switch ID */
11957             switch (n) {                /* Process the switch */
11958 #ifdef PIPESEND
11959               case XMI_CMD:             /* Transmit from a command */
11960                 if (nopush) {
11961                     printf("?Sorry, system command access is disabled\n");
11962                     return(-9);
11963                 }
11964                 sw.hlpmsg = "Command, or switch"; /* Change help message */
11965                 xpipe = 1;              /* (No way to undo this one) */
11966                 break;
11967 #endif /* PIPESEND */
11968
11969               case XMI_BIN:             /* Binary */
11970                 xbinary = 1;
11971                 xxlate = 0;             /* Don't translate charsets */
11972                 scan = 0;
11973                 break;
11974
11975               case XMI_TXT:             /* Text */
11976                 xbinary = 0;
11977                 xxlate = !tcs_transp;   /* Translate if TERM CHAR not TRANSP */
11978                 scan = 0;
11979                 break;
11980
11981               case XMI_TRA:             /* Transparent text */
11982                 xbinary = 0;
11983                 xxlate = 0;             /* But don't translate charsets */
11984                 scan = 0;
11985                 break;
11986
11987 #ifdef COMMENT
11988               case XMI_VRB:             /* /VERBOSE */
11989               case XMI_QUI:             /* /QUIET */
11990                 break;                  /* (not implemented yet) */
11991 #endif /* COMMENT */
11992
11993               case XMI_NOW:             /* /NOWAIT */
11994                 xxnowait = 1;
11995                 break;
11996
11997               case XMI_NOE:             /* /NOWAIT */
11998                 xxecho = 0;
11999                 break;
12000
12001               default:
12002                 return(-2);
12003             }
12004
12005         }
12006         if (cmresult.fcode != _CMIFI && cmresult.fcode != _CMTXT)
12007           return(-2);
12008         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Filename */
12009         if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
12010           ckstrncpy(line,tmpbuf,LINBUFSIZ);
12011         s = line;
12012         if ((y = cmcfm()) < 0)          /* Confirm */
12013           return(y);
12014 #ifdef CK_APC
12015         if ((apcactive == APC_LOCAL) ||
12016             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
12017           return(success = 0);
12018 #endif /* CK_APC */
12019         if (cmresult.nresult != 0) {
12020             printf("?Only a single file may be transmitted\n");
12021             return(-9);
12022         }
12023 #ifdef PIPESEND
12024         if (xpipe) {
12025             s = brstrip(s);
12026             if (!*s) {
12027                 printf("?Sorry, a command to send from is required\n");
12028                 return(-9);
12029             }
12030             pipesend = 1;
12031         }
12032 #endif /* PIPESEND */
12033
12034         if (scan && (filepeek
12035 #ifndef NOXFER
12036                      || patterns
12037 #endif /* NOXFER */
12038                      )) {               /* If user didn't specify type */
12039             int k, x;                         /* scan the file to see */
12040             x = -1;
12041             k = scanfile(s,&x,nscanfile);
12042             if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
12043         }
12044         if (!xfrxla) xxlate = 0;
12045         success = transmit(s,
12046                            (char) (xxnowait ? '\0' : (char)xmitp),
12047                            xxlate,
12048                            xbinary,
12049                            xxecho
12050                            );
12051         return(success);
12052     }
12053 #endif /* NOXMIT */
12054
12055 #ifndef NOFRILLS
12056     if (cx == XXTYP  || cx == XXCAT || cx == XXMORE ||
12057         cx == XXHEAD || cx == XXTAIL) {
12058         int paging = 0, havename = 0, head = 0, width = 0;
12059         int height = 0, count = 0;
12060         char pfxbuf[64], * prefix = NULL;
12061         char outfile[CKMAXPATH+1];
12062         struct FDB sf, sw;
12063         char * pat = NULL;
12064         int incs = 0, outcs = 0, cset = -1, number = 0;
12065 #ifdef UNICODE
12066         char * tocs = "";
12067         extern int fileorder;
12068 #ifdef OS2
12069 #ifdef NT
12070         char guibuf[128], * gui_title = NULL;
12071         int  gui = 0;
12072 #endif /* NT */
12073 #ifndef NOCSETS
12074         extern int tcsr, tcsl;
12075 #endif /* NOCSETS */
12076 #endif /* OS2 */
12077 #endif /* UNICODE */
12078
12079         outfile[0] = NUL;
12080
12081         if (cx == XXMORE)
12082           paging = 1;
12083         else if (cx == XXCAT)
12084           paging = 0;
12085         else
12086           paging = (typ_page < 0) ? xaskmore : typ_page;
12087         if (paging < 0)
12088           paging = saveask;
12089
12090         if (cx == XXHEAD) {
12091             head = 10;
12092             cx = XXTYP;
12093         } else if (cx == XXTAIL) {
12094             head = -10;
12095             cx = XXTYP;
12096         }
12097
12098 #ifdef IKSD
12099         if (inserver && !ENABLED(en_typ)) {
12100             printf("?Sorry, TYPE command disabled\n");
12101             return(-9);
12102         }
12103 #endif /* IKSD */
12104
12105         cmfdbi(&sw,                     /* 2nd FDB - optional /PAGE switch */
12106                _CMKEY,                  /* fcode */
12107                "Filename or switch",    /* hlpmsg */
12108                "",                      /* default */
12109                "",                      /* addtl string data */
12110                ntypetab,                /* addtl numeric data 1: tbl size */
12111                4,                       /* addtl numeric data 2: 4 = cmswi */
12112                xxstring,                /* Processing function */
12113                typetab,                 /* Keyword table */
12114                &sf                      /* Pointer to next FDB */
12115                );
12116         cmfdbi(&sf,                     /* 1st FDB - file to type */
12117                _CMIFI,                  /* fcode */
12118                "",                      /* hlpmsg */
12119                "",                      /* default */
12120                "",                      /* addtl string data */
12121                0,                       /* addtl numeric data 1 */
12122                0,                       /* addtl numeric data 2 */
12123                xxstring,
12124                NULL,
12125                NULL
12126                );
12127
12128         while (!havename) {
12129             x = cmfdb(&sw);             /* Parse something */
12130             debug(F101,"type cmfdb","",x);
12131             debug(F101,"type cmresult.fcode","",cmresult.fcode);
12132             debug(F101,"type cmresult.nresult","",cmresult.nresult);
12133             if (x < 0) {                        /* Error */
12134                 if (x == -3) {
12135                     x = -9;
12136                     printf("?Filename required\n");
12137                 }
12138                 return(x);
12139             } else if (cmresult.fcode == _CMKEY) {
12140                 char c; int getval;
12141                 c = cmgbrk();
12142                 getval = (c == ':' || c == '=');
12143                 if (getval && !(cmgkwflgs() & CM_ARG)) {
12144                     printf("?This switch does not take an argument\n");
12145                     return(-9);
12146                 }
12147 #ifdef COMMENT
12148                 if (!getval && (cmgkwflgs() & CM_ARG)) {
12149                     printf("?This switch requires an argument\n");
12150                     /* Not if it has a default! */
12151                     return(-9);
12152                 }
12153 #endif /* COMMENT */
12154                 switch (cmresult.nresult) {
12155 #ifdef CK_TTGWSIZ
12156                   case TYP_PAG:
12157                     paging = 1;
12158                     break;
12159
12160                   case TYP_NOP:
12161                     paging = 0;
12162                     break;
12163 #endif /* CK_TTGWSIZ */
12164
12165                   case TYP_COU:
12166                     paging = 0;
12167                     count = 1;
12168                     break;
12169
12170                   case TYP_HEA:
12171                   case TYP_TAI:
12172                     y = 10;
12173                     if (getval)
12174                       if ((x = cmnum("Number of lines",
12175                                      "10",10,&y,xxstring)) < 0)
12176                         return(x);
12177                     head = (cmresult.nresult == TYP_TAI) ? -y : y;
12178                     break;
12179
12180                   case TYP_WID:
12181                     y = typ_wid > -1 ? typ_wid : cmd_cols;
12182                     if (getval)
12183                       if ((x = cmnum("Column at which to truncate",
12184                                      ckitoa(y),10,&y,xxstring)) < 0)
12185                         return(x);
12186                     width = y;
12187                     break;
12188
12189 #ifdef KUI
12190                   case TYP_HIG:
12191                     if (getval)
12192                       if ((x = cmnum("Height of GUI dialog",
12193                                      ckitoa(y),10,&y,xxstring)) < 0)
12194                         return(x);
12195                     height = y;
12196                     break;
12197 #endif /* KUI */
12198
12199                   case TYP_PAT:
12200                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12201                         printf("?This switch requires an argument\n");
12202                         return(-9);
12203                     }
12204                     if ((x = cmfld("pattern","",&s,xxstring)) < 0)
12205                       return(x);
12206                     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12207                     pat = tmpbuf;
12208                     break;
12209
12210                   case TYP_PFX:
12211                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12212                         printf("?This switch requires an argument\n");
12213                         return(-9);
12214                     }
12215                     if ((x = cmfld("prefix for each line","",&s,xxstring)) < 0)
12216                       return(x);
12217                     if ((int)strlen(s) > 63) {
12218                         printf("?Too long - 63 max\n");
12219                         return(-9);
12220                     }
12221                     ckstrncpy(pfxbuf,s,64);
12222                     prefix = brstrip(pfxbuf);
12223                     number = 0;
12224                     break;
12225
12226 #ifdef KUI
12227                   case TYP_GUI:
12228                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12229                         printf("?This switch requires an argument\n");
12230                         return(-9);
12231                     }
12232                     if ((x = cmfld("Dialog box title","",&s,xxstring)) < 0) {
12233                         if (x != -3)
12234                           return(x);
12235                     } else {
12236                         if ((int)strlen(s) > 127) {
12237                             printf("?Too long - 127 max\n");
12238                             return(-9);
12239                         }
12240                         ckstrncpy(guibuf,s,128);
12241                         gui_title = brstrip(guibuf);
12242                     }
12243                     gui = 1;
12244                     break;
12245 #endif /* KUI */
12246
12247                   case TYP_NUM:         /* /NUMBER */
12248                     number = 1;
12249                     prefix = NULL;
12250                     break;
12251
12252 #ifdef UNICODE
12253                   case TYP_XPA:         /* /TRANSPARENT */
12254                     incs = 0;
12255                     cset = 0;
12256                     outcs = -1;
12257                     break;
12258
12259                   case TYP_XIN:         /* /CHARACTER-SET: */
12260                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12261                         printf("?This switch requires an argument\n");
12262                         return(-9);
12263                     }
12264                     if ((incs = cmkey(fcstab,nfilc,
12265                                       "character-set name","",xxstring)) < 0) {
12266                         if (incs == -3) /* Note: No default */
12267                           incs = -2;
12268                         return(incs);
12269                     }
12270                     cset = incs;
12271                     break;
12272
12273                   case TYP_XUT:         /* /TRANSLATE-TO: */
12274                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12275                         printf("?This switch requires an argument\n");
12276                         return(-9);
12277                     }
12278 #ifdef OS2
12279                     if (!inserver && !k95stdout) {
12280                         tocs = "ucs2";
12281                     } else {
12282 #ifdef CKOUNI
12283                         tocs = rlookup(txrtab,ntxrtab,tcsl);
12284 #else /* CKOUNI */
12285                         extern struct keytab ttcstab[];
12286                         extern int ntxrtab;
12287                         tocs = rlookup(ttcstab,ntermc,tocs);
12288                         if (!tocs)
12289                           tocs = getdcset();
12290 #endif /* CKOUNI */
12291                     }
12292 #else /* OS2 */
12293                     tocs = getdcset();
12294 #endif /* OS2 */
12295                     if ((outcs = cmkey(fcstab,nfilc,
12296                                        "character-set",tocs,xxstring)) < 0)
12297                       return(outcs);
12298                     break;
12299 #endif /* UNICODE */
12300                   case TYP_OUT:
12301                     if ((x = cmofi("File for result lines","",
12302                                    &s,xxstring)) < 0)
12303                       return(x);
12304                     ckstrncpy(outfile,s,CKMAXPATH);
12305                     break;
12306                 }
12307             } else if (cmresult.fcode == _CMIFI)
12308               havename = 1;
12309             else
12310               return(-2);
12311         }
12312         if (havename) {
12313             ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
12314             y = cmresult.nresult;
12315         } else {
12316             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
12317                 if (x == -3) {
12318                     printf("?Name of an existing file required\n");
12319                     return(-9);
12320                 } else return(x);
12321             }
12322             ckstrncpy(line,s,LINBUFSIZ);
12323         }
12324         if (y != 0) {
12325             printf("?A single file please\n");
12326             return(-9);
12327         }
12328 #ifdef KUI
12329         if ( outfile[0] && gui ) {
12330             printf("?/GUI and /OUTPUT are incompatible\n");
12331             return(-9);
12332         }
12333 #endif /* KUI */
12334
12335         if ((y = cmcfm()) < 0)          /* Confirm the command */
12336           return(y);
12337
12338 #ifdef UNICODE
12339         fileorder = -1;
12340         if (cset < 0 && filepeek) {     /* If no charset switches given */
12341             int k, x = -1;
12342             k = scanfile(line,&x,nscanfile); /* Call file analyzer */
12343             debug(F111,"type scanfile",line,k);
12344             debug(F101,"type scanfile flag","",x);
12345             switch(k) {
12346               case FT_UTF8:             /* which can detect UTF-8... */
12347                 cset = 0;
12348                 incs = FC_UTF8;
12349                 break;
12350               case FT_UCS2:             /* and UCS-2... */
12351                 cset = 0;
12352                 incs = FC_UCS2;
12353                 fileorder = x;          /* even if there is no BOM. */
12354                 debug(F101,"type fileorder","",fileorder);
12355                 break;
12356             }
12357         }
12358 #ifdef OS2
12359         if (cset < 0) {                 /* If input charset still not known */
12360 #ifdef CKOUNI
12361             tocs = rlookup(txrtab,ntxrtab,tcsl);
12362 #else /* CKOUNI */
12363             extern struct keytab ttcstab[];
12364             extern int ntxrtab;
12365             tocs = rlookup(ttcstab,ntermc,incs);
12366             if (!tocs)
12367               tocs = getdcset();
12368 #endif /* CKOUNI */
12369             incs = lookup(fcstab,tocs,nfilc,&x);
12370         }
12371 #endif /* OS2 */
12372
12373         if (outcs == 0 && incs != 0) {  /* Supply default target charset */
12374             int x = 0;                  /* if switch not given. */
12375             tocs = getdcset();
12376             outcs = lookup(fcstab,tocs,nfilc,&x);
12377         }
12378 #else  /* !UNICODE */
12379         if (cset < 0) incs = outcs = 0;
12380 #endif /* UNICODE */
12381
12382         if (outfile[0] && paging)       /* This combination makes no sense */
12383           paging = 0;                   /* so turn off paging */
12384
12385 #ifdef KUI
12386         /* No paging when dialog is used */
12387         if ( gui && paging )
12388           paging = 0;
12389
12390         if ( !gui && height ) {
12391             printf("?The /HEIGHT switch is not supported without /GUI\n");
12392             return(-9);
12393         }
12394 #endif /* KUI */
12395
12396         if (count) paging = -1;
12397         debug(F111,"type",line,paging);
12398 #ifdef KUI
12399         if ( gui ) {
12400             s = (char *)1;    /* ok, its an ugly hack */
12401             if (gui_text_popup_create(gui_title ?
12402                                       gui_title : line, height,width) < 0) {
12403                 printf("?/GUI not supported on this system\n");
12404                 gui = 0;
12405                 return(-9);
12406             }
12407             width = 0;
12408         } else
12409 #endif /* KUI */
12410           s = outfile;
12411         success =
12412           dotype(line,paging,0,head,pat,width,prefix,incs,outcs,s,number);
12413         return(success);
12414     }
12415 #endif /* NOFRILLS */
12416
12417 #ifndef NOCSETS
12418     if (cx == XXXLA) {                  /* TRANSLATE file's charset */
12419         _PROTOTYP (int doxlate, ( void ) );
12420         return(doxlate());
12421     }
12422 #endif /* NOCSETS */
12423
12424     if (cx == XXVER) {                  /* VERSION */
12425         int n = 0;
12426         extern char * ck_patch, * ck_s_test;
12427 #ifdef COMMENT
12428         extern int hmtopline;
12429 #endif /* COMMENT */
12430         if ((y = cmcfm()) < 0)
12431           return(y);
12432
12433 #ifdef CK_64BIT
12434         printf("\n%s, for%s (64-bit)\n Numeric: %ld",versio,ckxsys,vernum);
12435 #else
12436         printf("\n%s, for%s\n Numeric: %ld",versio,ckxsys,vernum);
12437 #endif  /* CK_64BIT */
12438         printf("\n\n");
12439         printf("Authors:\n");
12440         printf(" Frank da Cruz, Columbia University\n");
12441         printf(" Jeffrey Eric Altman, Secure Endpoints, Inc. %s\n",
12442                "<jaltman@secure-endpoints.com>"
12443                );
12444         printf(" Contributions from many others.\n");
12445         n = 7;
12446         if (*ck_s_test) {
12447             printf("\nTHIS IS A TEST VERSION, NOT FOR PRODUCTION USE.\n");
12448             n += 2;
12449         }
12450         if (*ck_patch) {
12451             printf(" Patches: %s\n", ck_patch);
12452             n++;
12453         }
12454         printf(" Type COPYRIGHT for copyright and license.\n\n");
12455 #ifdef OS2
12456         shoreg();
12457 #else
12458 #ifdef COMMENT
12459         hmtopline = n+1;
12460         hmsga(copyright);
12461         hmtopline = 0;
12462 #endif /* COMMENT */
12463 #endif /* OS2 */
12464         return(success = 1);
12465     }
12466
12467     if (cx == XXCPR) {                  /* COPYRIGHT or LICENSE */
12468         _PROTOTYP( int hmsgaa, (char * [], char *) );
12469         extern char * ck_cryear;
12470         if ((y = cmcfm()) < 0)
12471           return(y);
12472         hmsgaa(copyright,ck_cryear);
12473         return(success = 1);
12474     }
12475
12476 #ifndef MAC                             /* Only for multiuser systems */
12477 #ifndef OS2
12478 #ifndef NOFRILLS
12479     if (cx == XXWHO) {                  /* WHO */
12480         char *wc;
12481 #ifdef IKSD
12482         if (inserver && !ENABLED(en_who)) {
12483             printf("?Sorry, WHO command disabled\n");
12484             return(-9);
12485         }
12486 #endif /* IKSD */
12487 #ifdef datageneral
12488         if ((z = cmcfm()) < 0) return(z);
12489         if (nopush) {
12490             printf("?Sorry, who not allowed\n");
12491             return(success = 0);
12492         }
12493         xsystem(WHOCMD);
12494 #else
12495         if ((y = cmtxt("user name","",&s,xxstring)) < 0) return(y);
12496         if (nopush) {
12497             printf("?Sorry, WHO command disabled\n");
12498             return(success = 0);
12499         }
12500         if (!(wc = getenv("CK_WHO"))) wc = WHOCMD;
12501         if (wc)
12502           if ((int) strlen(wc) > 0) {
12503               ckmakmsg(line,LINBUFSIZ,wc," ",s,NULL);
12504               xsystem(line);
12505           }
12506 #endif /* datageneral */
12507         return(success = 1);
12508     }
12509 #endif /* NOFRILLS */
12510 #endif /* OS2 */
12511 #endif /* MAC */
12512
12513 #ifndef NOFRILLS
12514     if (cx == XXWRI || cx == XXWRL || cx == XXWRBL) { /* WRITE */
12515         int x,y;                        /* On stack in case of \fexec() */
12516         if ((x = cmkey(writab,nwri,"to file or log","",xxstring)) < 0) {
12517             if (x == -3) printf("?Write to what?\n");
12518             return(x);
12519         }
12520         if ((y = cmtxt("text","",&s,xxstring)) < 0) return(y);
12521         s = brstrip(s);
12522         switch (x) {
12523           case LOGD: y = ZDFILE; break;
12524           case LOGP: y = ZPFILE; break;
12525 #ifndef NOLOCAL
12526           case LOGS: y = ZSFILE; break;
12527 #endif /* NOLOCAL */
12528           case LOGT: y = ZTFILE; break;
12529 #ifndef NOSPL
12530           case LOGW: y = ZWFILE; break;
12531 #endif /* NOSPL */
12532           case LOGX:                    /* SCREEN (stdout) */
12533           case LOGE:                    /* ERROR  (stderr) */
12534             if (x == LOGE) {
12535                 debug(F110,
12536                       (cx == XXWRL) ? "WRITELN ERROR" : "WRITE ERROR", s,0);
12537                 fprintf(stderr,"%s%s",s,(cx == XXWRL) ? "\n" : "");
12538             } else {
12539                 debug(F110,
12540                       (cx == XXWRL) ? "WRITELN SCREEN" : "WRITE SCREEN", s,0);
12541                 printf("%s%s",s,(cx == XXWRL) ? "\n" : "");
12542             }
12543             return(success = 1);
12544           default: return(-2);
12545         }
12546         if (chkfn(y) > 0) {
12547             x = (cx == XXWRI) ? zsout(y,s) : zsoutl(y,s);
12548             debug(F111,"WRITE",
12549                   (cx == XXWRI) ? "zsout" : "zsoutl",
12550                   x);
12551             if (x < 0) printf("?Write error\n");
12552         } else {
12553             x = -1;
12554             printf("?File or log not open\n");
12555         }
12556         debug(F101,"WRITE x","",x);
12557         return(success = (x == 0) ? 1 : 0);
12558     }
12559 #endif /* NOFRILLS */
12560
12561 #ifndef NOXFER
12562     if (cx == XXASC || cx == XXBIN) {
12563         if ((x = cmcfm()) < 0) return(x);
12564 #ifdef NEWFTP
12565 /*
12566   Make C-Kermit work like other ftp clients, where
12567   the ASCII (TEXT) and BINARY commands are global settings.
12568 */
12569         if (ftpisopen()) {
12570             doftpglobaltype((cx == XXASC) ? XYFT_T : XYFT_B);
12571             /* Fall thru--the command it should apply to both FTP and Kermit */
12572             /* return(success = 1); */
12573         }
12574 #endif /* NEWFTP */
12575
12576         xfermode = XMODE_M;             /* Set manual Kermit transfer mode */
12577         binary = (cx == XXASC) ? XYFT_T : XYFT_B;
12578         return(success = 1);
12579     }
12580 #endif /* NOXFER */
12581
12582     if (cx == XXCLS) {
12583         if ((x = cmcfm()) < 0) return(x);
12584         y = ck_cls();
12585         return(success = (y > -1) ? 1 : 0);
12586     }
12587
12588 #ifdef CK_MKDIR
12589     if (cx == XXMKDIR || cx == XXLMKD) {
12590         char *p;
12591 #ifdef LOCUS
12592         if (!locus && cx != XXLMKD) {
12593 #ifdef NOXFER
12594             return(-2);
12595 #else
12596             return(dormt(XZMKD));
12597 #endif /* NOXFER */
12598         }
12599 #endif /* LOCUS */
12600 #ifdef IKSD
12601         if (inserver && !ENABLED(en_mkd)) {
12602             printf("?Sorry, directory creation is disabled\n");
12603             return(-9);
12604         }
12605 #endif /* IKSD */
12606         if ((x = cmfld("Name for new directory","",&s,xxstring)) < 0) {
12607             if (x != -3) {
12608                 return(x);
12609             } else {
12610                 printf("?Directory name required\n");
12611                 return(-9);
12612             }
12613         }
12614         ckstrncpy(line,s,LINBUFSIZ);
12615         s = line;
12616         if ((x = cmcfm()) < 0) return(x);
12617         s = brstrip(s);
12618         bgchk();                        /* Set msgflg */
12619         x = ckmkdir(0,s,&p,msgflg,0);
12620 #ifdef COMMENT
12621         if (msgflg && x == 0)
12622           printf("?Directory already exists\n");
12623 #endif /* COMMENT */
12624         return(success = (x < 0) ? 0 : 1);
12625     }
12626     if (cx == XXRMDIR || cx == XXLRMD) { /* RMDIR */
12627         char *p;
12628 #ifdef LOCUS
12629         if (!locus && cx != XXLRMD) {
12630 #ifdef NOXFER
12631             return(-2);
12632 #else
12633             return(dormt(XZRMD));
12634 #endif /* NOXFER */
12635         }
12636 #endif /* LOCUS */
12637 #ifdef IKSD
12638         if (inserver && !ENABLED(en_rmd)) {
12639             printf("?Sorry, directory removal is disabled\n");
12640             return(-9);
12641         }
12642 #endif /* IKSD */
12643         if ((x = cmdir("Name of directory to be removed","",&s,xxstring)) < 0)
12644           return(x);
12645         ckstrncpy(line,s,LINBUFSIZ);
12646         s = line;
12647         if ((x = cmcfm()) < 0) return(x);
12648         s = brstrip(s);
12649         x = ckmkdir(1,s,&p,msgflg,0);
12650         return(success = (x < 0) ? 0 : 1);
12651     }
12652 #endif /* CK_MKDIR */
12653
12654 #ifdef TNCODE
12655     if (cx == XXTELOP)
12656       return(dotelopt());
12657 #endif /* TNCODE */
12658
12659 #ifndef NOPUSH
12660     if (cx == XXNPSH) {
12661         if ((z = cmcfm()) < 0) return(z);
12662         nopush = 1;
12663 #ifndef NOSERVER
12664         en_hos = 0;
12665 #endif /* NOSERVER */
12666 #ifdef PIPESEND
12667         usepipes = 0;
12668 #endif /* PIPESEND */
12669         return(success = 1);
12670     }
12671 #endif /* NOPUSH */
12672
12673 #ifdef OS2
12674     if (cx == XXNSCR) {
12675         if ((z = cmcfm()) < 0) return(z);
12676         tt_scroll = 0;
12677         return(success = 1);
12678     }
12679 #endif /* OS2 */
12680
12681 #ifndef NOSPL
12682     if (cx == XXLOCAL)                  /* LOCAL variable declarations */
12683       return(success = dolocal());
12684 #endif /* NOSPL */
12685
12686     if (cx == XXKERMI) {                /* The KERMIT command */
12687         char * list[65];
12688         extern char **xargv;
12689         extern int xargc;
12690         int i;
12691         if ((y = cmtxt("kermit command-line arguments, -h for help",
12692                        "",&s,xxstring)) < 0)
12693           return(y);
12694         ckstrncpy(line,"kermit ",LINBUFSIZ);
12695         ckstrncat(line,s,LINBUFSIZ-8);
12696         xwords(line,64,list,0);
12697         for (i = 1; i < 64; i++) {
12698             if (!list[i])
12699               break;
12700         }
12701         i--;
12702         xargc = i;
12703         xargv = list;
12704         xargv++;
12705         sstate = cmdlin();
12706         if (sstate) {
12707             extern int justone;
12708             debug(F000,"KERMIT sstate","",sstate);
12709             justone = 1;                /* Force return to command mode */
12710             proto();                    /* after protocol */
12711             return(success);
12712         } else {
12713             debug(F101,"KERMIT sstate","",sstate);
12714             return(success = 1);        /* Not exactly right, but... */
12715         }
12716     }
12717     if (cx == XXDATE) {                 /* DATE command */
12718         extern char cmdatebuf[], * cmdatemsg;
12719
12720 #ifndef COMMENT
12721         char * dp;
12722         if ((y = cmtxt("date and/or time, or carriage return for current",
12723                        "",&s,xxstring)) < 0)
12724           return(y);
12725         s = brstrip(s);
12726         dp = cmcvtdate(s,1);
12727         if (!dp) {
12728             printf("?%s\n",cmdatemsg ? cmdatemsg : "Date conversion error");
12729             success = 0;
12730         } else {
12731             printf("%s\n",dp);
12732             success = 1;
12733         }
12734 #else
12735         /* This works fine but messes up my "dates" torture-test script */
12736
12737         if ((x = cmdate("Date and/or time, or carriage return for current",
12738                         "",&s,0,xxstring)) < 0) {
12739             return(x);
12740         } else {
12741             printf("%s\n",cmdatebuf);
12742             success = 1;
12743         }
12744 #endif /* COMMENT */
12745         return(success);
12746     }
12747 #ifndef NOPUSH
12748 #ifndef NOFRILLS
12749     if (cx == XXEDIT)
12750       return(doedit());
12751 #endif /* NOFRILLS */
12752 #endif /* NOPUSH */
12753
12754 #ifdef BROWSER                          /* Defined only ifndef NOPUSH */
12755     if (cx == XXBROWS)
12756       return(dobrowse());
12757 #endif /* BROWSER */
12758
12759 #ifdef CK_TAPI
12760     if (cx == XXTAPI) {                 /* Microsoft TAPI */
12761         return (success = dotapi());
12762     }
12763 #endif /* CK_TAPI */
12764
12765 #ifndef NOXFER
12766     if (cx == XXWHERE) {
12767         extern char * rfspec, * sfspec, * srfspec, * rrfspec;
12768         if ((x = cmcfm()) < 0) return(x);
12769         printf("\nFile most recently...\n\n");
12770         printf("  Sent:       %s\n",   sfspec ? sfspec : "(none)");
12771         if (sfspec && srfspec) {
12772             printf("  Stored as:  %s\n",   srfspec);
12773             printf("\n");
12774         }
12775         printf("  Received:   %s\n",   rrfspec ? rrfspec : "(none)");
12776         if (rfspec && rrfspec)
12777         printf("  Stored as:  %s\n",   rfspec);
12778         printf(
12779 "\nIf the full path is not shown, then the file is probably in your current\n"
12780                );
12781         printf(
12782 "directory or your download directory (if any - SHOW FILE to find out).\n\n"
12783                );
12784         return(success = 1);
12785     }
12786 #endif /* NOXFER */
12787
12788 #ifdef CK_RECALL
12789     if (cx == XXREDO)
12790       return(doredo());
12791 #endif /* CK_RECALL */
12792
12793 #ifdef CKROOT
12794     if (cx == XXCHRT)                   /* Change Kermit's root directory */
12795       return(dochroot());
12796 #endif /* CKROOT */
12797
12798 #ifdef CK_KERBEROS
12799     if (cx == XXAUTH) {                 /* KERBEROS */
12800         x = cp_auth();                  /* Parse it */
12801 #ifdef IKSD
12802         if (inserver) {
12803             printf("?Command disabled in IKSD.\r\n");
12804             return(success = 0);
12805         }
12806 #endif /* IKSD */
12807         if (x < 0)                      /* Pass parse errors back */
12808           return(x);
12809         return(success = doauth(cx));
12810     }
12811 #endif /* CK_KERBEROS */
12812
12813 #ifndef NOLOCAL
12814     if (cx == XXTERM) {
12815         return(settrmtyp());
12816     }
12817 #endif /* NOLOCAL */
12818
12819     if (cx == XXSTATUS) {
12820         if ((x = cmcfm()) < 0) return(x);
12821         printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
12822         return(0);                      /* Don't change it */
12823     }
12824
12825     if (cx == XXFAIL) {
12826         if ((x = cmcfm()) < 0) return(x);
12827         return(success = 0);
12828     }
12829
12830     if (cx == XXSUCC) {
12831         if ((x = cmcfm()) < 0) return(x);
12832         return(success = 1);
12833     }
12834
12835     if (cx == XXNLCL) {
12836         extern int nolocal;
12837         if ((x = cmcfm()) < 0) return(x);
12838         nolocal = 1;
12839         return(success = 1);
12840     }
12841
12842 #ifndef NOXFER
12843     if (cx == XXRASG)                   /* Shortcuts for REMOTE commands */
12844       return(dormt(XZASG));
12845     if (cx == XXRCWD)
12846       return(dormt(XZCWD));
12847     if (cx == XXRCPY)
12848       return(dormt(XZCPY));
12849     if (cx == XXRDEL)
12850       return(dormt(XZDEL));
12851     if (cx == XXRDIR)
12852       return(dormt(XZDIR));
12853     if (cx == XXRXIT)
12854       return(dormt(XZXIT));
12855     if (cx == XXRHLP)
12856       return(dormt(XZHLP));
12857     if (cx == XXRHOS)
12858       return(dormt(XZHOS));
12859     if (cx == XXRKER)
12860       return(dormt(XZKER));
12861     if (cx == XXRPWD)
12862       return(dormt(XZPWD));
12863     if (cx == XXRQUE)
12864       return(dormt(XZQUE));
12865     if (cx == XXRREN)
12866       return(dormt(XZREN));
12867     if (cx == XXRMKD)
12868       return(dormt(XZMKD));
12869     if (cx == XXRMSG)
12870       return(dormt(XZMSG));
12871     if (cx == XXRRMD)
12872       return(dormt(XZRMD));
12873     if (cx == XXRSET)
12874       return(dormt(XZSET));
12875     if (cx == XXRSPA)
12876       return(dormt(XZSPA));
12877     if (cx == XXRTYP)
12878       return(dormt(XZTYP));
12879     if (cx == XXRWHO)
12880       return(dormt(XZWHO));
12881     if (cx == XXRCDUP)
12882       return(dormt(XZCDU));
12883     if (cx == XXRPRI)
12884       return(dormt(XZPRI));
12885 #endif /* NOXFER */
12886
12887     if (cx == XXRESET) {                /* RESET */
12888         if ((x = cmcfm()) < 0)
12889           return(x);
12890         concb((char)escape);            /* Make command echoing to normal */
12891         doclean(0);                     /* Close all files */
12892         return(success = 1);
12893     }
12894
12895 #ifndef NOXFER
12896 #ifndef NOCSETS
12897     if (cx == XXASSOC)                  /* ASSOCIATE */
12898       return(doassoc());
12899 #endif /* NOCSETS */
12900 #endif /* NOXFER */
12901
12902 #ifndef NOSPL
12903     if (cx == XXSHIFT) {                /* SHIFT */
12904         if ((y = cmnum("Number of arguments to shift","1",10,&x,xxstring)) < 0)
12905           return(y);
12906         if ((z = cmcfm()) < 0)
12907           return(z);
12908         return(success = doshift(x));
12909     }
12910 #endif /* NOSPL */
12911
12912 #ifndef NOHELP
12913     if (cx == XXMAN)
12914       return(domanual());
12915 #endif /* NOHELP */
12916
12917 #ifndef NOSPL
12918     if (cx == XXSORT)                   /* SORT an array */
12919       return(dosort());
12920 #endif /* NOSPL */
12921
12922     if (cx == XXPURGE) {
12923 #ifdef IKSD
12924         if (inserver && (!ENABLED(en_del)
12925 #ifdef CK_LOGIN
12926                           || isguest
12927 #endif /* CK_LOGIN */
12928                          )) {
12929             printf("?Sorry, DELETE is disabled\n");
12930             return(-9);
12931         }
12932 #endif /* IKSD */
12933 #ifdef CK_APC
12934         if ((apcactive == APC_LOCAL) ||
12935             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
12936           return(success = 0);
12937 #endif /* CK_APC */
12938 #ifdef CKPURGE
12939         return(dopurge());
12940 #else
12941 #ifdef VMS
12942         if ((x = cmtxt("optional switches followed by filespec",
12943                        "",&s,xxstring)) < 0)
12944           return(x);
12945         if (nopush) {
12946             printf("?Sorry, DCL access is disabled\n");
12947             return(-9);
12948         }
12949         ckstrncpy(line,s,LINBUFSIZ);
12950         s = line;
12951         x = mlook(mactab,"purge",nmac);
12952         return(success = dodo(x,s,cmdstk[cmdlvl].ccflgs));
12953 #else
12954         return(-2);
12955 #endif /* VMS */
12956 #endif /* CKPURGE */
12957     }
12958
12959 #ifndef NOSPL
12960     if (cx == XXFAST) {
12961         if ((x = cmcfm()) < 0) return(x);
12962         x = mlook(mactab,"fast",nmac);
12963         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12964     }
12965     if (cx == XXCAU) {
12966         if ((x = cmcfm()) < 0) return(x);
12967         x = mlook(mactab,"cautious",nmac);
12968         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12969     }
12970     if (cx == XXROB) {
12971         if ((x = cmcfm()) < 0) return(x);
12972         x = mlook(mactab,"robust",nmac);
12973         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12974     }
12975 #endif /* NOSPL */
12976
12977     if (cx == XXSCRN) {                 /* SCREEN */
12978         int row, col;
12979         if ((x = cmkey(scntab, nscntab,"screen action","", xxstring)) < 0)
12980           return(x);
12981         switch (x) {                    /* MOVE-TO (cursor position) */
12982           case SCN_MOV:
12983             if ((y = cmnum("Row (1-based)","",10,&z,xxstring)) < 0)
12984               return(y);
12985             row = z;
12986             y = cmnum("Column (1-based)","1",10,&z,xxstring);
12987             if (y < 0)
12988               return(y);
12989             col = z;
12990             if ((y = cmcfm()) < 0)
12991               return(y);
12992             if (row < 0 || col < 0) {
12993                 printf("?Row and Column must be 1 or greater\n");
12994                 return(-9);
12995             }
12996             if (cmd_rows > 0 && row > cmd_rows)
12997               row = cmd_rows;
12998             if (cmd_cols > 0 && col > cmd_cols)
12999               col = cmd_cols;
13000             y = ck_curpos(row,col);
13001             return(success = (y > -1) ? 1 : 0);
13002
13003           case SCN_CLR:                 /* CLEAR */
13004             if ((y = cmcfm()) < 0)
13005               return(y);
13006             debug(F100,"screen calling ck_cls()","",0);
13007             y = ck_cls();
13008             return(success = (y > -1) ? 1 : 0);
13009
13010           case SCN_CLE:                 /* CLEOL */
13011             if ((y = cmcfm()) < 0)
13012               return(y);
13013             y = ck_cleol();
13014             return(success = (y > -1) ? 1 : 0);
13015         }
13016     }
13017
13018 #ifndef NOHTTP
13019 #ifdef TCPSOCKET
13020     if (cx == XXHTTP)
13021       return(dohttp());
13022 #endif /* TCPSOCKET */
13023 #endif /* NOHTTP */
13024
13025 #ifndef NOSPL
13026     if (cx == XXARRAY) {                /* ARRAY */
13027 #ifndef NOSHOW
13028         extern int showarray();
13029 #endif /* NOSHOW */
13030         if ((x = cmkey(arraytab, narraytab,"Array operation","",xxstring)) < 0)
13031           return(x);
13032         switch (x) {
13033           case ARR_DCL:
13034             return(dodcl(XXDCL));
13035           case ARR_SRT:
13036             return(dosort());
13037 #ifndef NOSHOW
13038           case ARR_SHO:
13039             return(showarray());
13040 #endif /* NOSHOW */
13041           case ARR_CPY:
13042             return(copyarray());
13043           case ARR_SET:
13044           case ARR_CLR:
13045             return(clrarray(x));
13046           case ARR_DST:
13047             return(unarray());
13048           case ARR_RSZ:
13049             return(rszarray());
13050           case ARR_EQU:
13051             return(linkarray());
13052
13053           default:
13054             printf("?Sorry, not implemented yet - \"%s\"\n",cmdbuf);
13055             return(-9);
13056         }
13057     }
13058     if (cx == XXTRACE)                  /* TRACE */
13059       return(dotrace());
13060 #endif /* NOSPL */
13061
13062 #ifdef CK_PERMS
13063 #ifdef UNIX
13064     if (cx == XXCHMOD)
13065       return(douchmod());               /* Do Unix chmod */
13066 #endif /* UNIX */
13067 #endif /* CK_PERMS */
13068
13069     if (cx == XXPROMP)
13070       return(doprompt());
13071
13072     if (cx == XXGREP)
13073       return(dogrep());
13074
13075     if (cx == XXDEBUG) {                /* DEBUG */
13076 #ifndef DEBUG
13077         int dummy = 0;
13078         return(seton(&dummy));
13079 #else
13080         return(seton(&deblog));
13081 #endif /* DEBUG */
13082     }
13083     if (cx == XXMSG || cx == XXXMSG) {  /* MESSAGE */
13084         extern int debmsg;              /* Script debugging messages */
13085         if ((x = cmtxt("Message to print if SET DEBUG MESSAGE is ON or STDERR",
13086                  "",&s,xxstring)) < 0)
13087           return(x);
13088         if (!s)                         /* Watch out for null result */
13089           s = "";                       /* Make it an empty string */
13090         else                            /* Not null */
13091           s = brstrip(s);               /* Strip braces and doublequotes */
13092         switch (debmsg) {               /* Not debugging - don't print */
13093           case 0:
13094             break;
13095           case 1:
13096             printf("%s",s);             /* Print to stdout */
13097             if (cx == XXMSG) printf("\n");
13098             break;
13099           case 2:
13100             fprintf(stderr,"%s",s);     /* Ditto but print to stderr */
13101             if (cx == XXMSG) fprintf(stderr,"\n");
13102             break;
13103         }
13104         return(0);                      /* Return without affecting SUCCESS */
13105     }
13106
13107 #ifdef CKLEARN
13108     if (cx == XXLEARN) {                /* LEARN */
13109         struct FDB of, sw, cm;
13110         int closing = 0, off = 0, on = 0, confirmed = 0;
13111         char c;
13112
13113         cmfdbi(&sw,                     /* 2nd FDB - optional /PAGE switch */
13114                _CMKEY,                  /* fcode */
13115                "Script file name, or switch", /* hlpmsg */
13116                "",                      /* default */
13117                "",                      /* addtl string data */
13118                3,                       /* addtl numeric data 1: tbl size */
13119                4,                       /* addtl numeric data 2: 4 = cmswi */
13120                xxstring,                /* Processing function */
13121                learnswi,                /* Keyword table */
13122                &of                      /* Pointer to next FDB */
13123                );
13124         cmfdbi(&of,_CMOFI,"","","",0,0,xxstring,NULL,&cm);
13125         cmfdbi(&cm,_CMCFM,"","","",0,0,NULL,NULL,NULL);
13126         line[0] = NUL;
13127
13128         while (!confirmed) {
13129             x = cmfdb(&sw);             /* Parse something */
13130             if (x < 0)
13131               return(x);
13132             switch (cmresult.fcode) {   /* What was it? */
13133               case _CMOFI:              /* Output file name */
13134                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
13135                 break;
13136               case _CMKEY:              /* Switch */
13137                 c = cmgbrk();
13138                 if ((c == ':' || c == '=') && !(cmgkwflgs() & CM_ARG)) {
13139                     printf("?This switch does not take an argument\n");
13140                     return(-9);
13141                 }
13142                 switch (cmresult.nresult) {
13143                   case 2:               /* /CLOSE */
13144                     closing = 1;        /* Fall thru on purpose */
13145                   case 0:               /* /OFF */
13146                     off = 1;
13147                     on = 0;
13148                     break;
13149                   case 1:               /* /ON */
13150                     on = 1;
13151                     off = 0;
13152                     break;
13153                 }
13154                 break;
13155               case _CMCFM:              /* Confirmation */
13156                 confirmed++;
13157                 break;
13158             }
13159         }
13160         if (closing) {
13161             if (learnfp) {
13162                 fclose(learnfp);
13163                 learnfp = NULL;
13164             }
13165             makestr(&learnfile,NULL);
13166         }
13167         if (line[0]) {
13168             if (!on && !off)
13169               on = 1;
13170             if (learnfp) {
13171                 fclose(learnfp);
13172                 learnfp = NULL;
13173             }
13174             makestr(&learnfile,line);
13175             if (learnfile) {
13176                 char * modes = "w";
13177                 learnfp = fopen(learnfile,modes);
13178                 if (!learnfp) {
13179                     debug(F110,"LEARN file open error",learnfile,0);
13180                     perror(learnfile);
13181                     return(-9);
13182                 } else {
13183 #ifdef ZFNQFP
13184                     if (zfnqfp(learnfile,TMPBUFSIZ,tmpbuf))
13185                       makestr(&learnfile,tmpbuf);
13186 #endif /* ZFNQFP */
13187                     debug(F110,"LEARN file open ok",learnfile,0);
13188                     if (!quiet) {
13189                         printf("Recording to %s...\n\n",learnfile);
13190                         printf(
13191 " WARNING: If you type your password during script recording, it will appear\n\
13192  in the file.  Be sure to edit it or take other appropriate precautions.\n\n"
13193                                );
13194                     }
13195                     fputs(  "; Scriptfile: ",learnfp);
13196                     fputs(learnfile,learnfp);
13197                     fputs("\n; Directory:  ",learnfp);
13198                     fputs(zgtdir(),learnfp);
13199                     fputs("\n; Recorded:   ",learnfp);
13200                     fputs(ckdate(),learnfp);
13201                     fputs("\n",learnfp);
13202                 }
13203             }
13204         }
13205         if (on) {
13206             learning = 1;
13207         } else if (off) {
13208             learning = 0;
13209         }
13210         debug(F101,"LEARN learning","",learning);
13211         return(success = 1);
13212     }
13213 #endif /* CKLEARN */
13214
13215 #ifdef NEWFTP
13216     if (cx == XXUSER || cx == XXACCT) {
13217         if (!ftpisopen()) {
13218             printf("?FTP connection is not open\n");
13219             return(-9);
13220         }
13221         return(success = (cx == XXUSER) ? doftpusr() : doftpacct());
13222     }
13223     if (cx == XXSITE || cx == XXPASV) {
13224         if (!ftpisopen()) {
13225             printf("?FTP connection is not open\n");
13226             return(-9);
13227         }
13228         return(success = (cx == XXSITE) ? doftpsite() : dosetftppsv());
13229     }
13230 #endif /* NEWFTP */
13231
13232     if (cx == XXORIE) {                 /* ORIENTATION */
13233         extern char * myname;
13234         int i, y, n = 0;
13235         char * s, *p, vbuf[32];
13236         char * vars[16];       char * legend[16];
13237
13238         if ((y = cmcfm()) < 0)
13239           return(y);
13240
13241         printf("\nProgram name:\n  %s\n\n",myname);
13242         n += 4;
13243
13244 #ifdef NT
13245         vars[0] = "home";      legend[0] = "Your home directory";
13246         vars[1] = "directory"; legend[1] = "K95's current directory";
13247         vars[2] = "exedir";    legend[2] = "K95 Program directory";
13248         vars[3] = "inidir";    legend[3] = "K95 Initialization file directory";
13249         vars[4] = "startup";   legend[4] = "Current directory when started";
13250         
13251         vars[5] = "common";
13252         legend[5] = "K95 data for all users and K95SITE.INI file";
13253         
13254         vars[6] = "personal";  legend[6] = "Your personal data directory tree";
13255         vars[7] = "desktop";   legend[7] = "Your deskop directory tree";
13256         
13257         vars[8] = "appdata";
13258         legend[8] = "Your personal K95 data tree and K95CUSTOM.INI file";
13259         
13260         vars[9] = "download";  legend[9] = "Your K95 download directory";
13261         vars[10] = "tmpdir";   legend[10] = "Your TEMP directory";
13262         vars[11] = NULL;       legend[11] = NULL;
13263
13264         for (i = 0; i < 16 && vars[i]; i++) {
13265             printf("%s:\n",legend[i]);
13266             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13267             ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
13268             printf("  Variable:   %s\n",vbuf);
13269             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13270             y = TMPBUFSIZ;
13271             s = tmpbuf;
13272             zzstring(vbuf,&s,&y);
13273             line[0] = NUL;
13274             ckGetLongPathName(tmpbuf,line,LINBUFSIZ);
13275             printf("  Long name:  %s\n",line);
13276             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13277             line[0] = NUL;
13278             GetShortPathName(tmpbuf,line,LINBUFSIZ);
13279             printf("  Short name: %s\n",line);
13280             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13281             printf("\n");
13282             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13283         }
13284 #else  /* NT */
13285
13286         vars[0] = "home";      legend[0] = "Your home directory";
13287         vars[1] = "directory"; legend[1] = "Kermit's current directory";
13288         vars[2] = "exedir";    legend[2] = "Kermit's program directory";
13289         vars[3] = "inidir";    legend[3] = "Initialization file directory";
13290         vars[4] = "startup";   legend[4] = "Current directory when started";
13291         vars[5] = "download";  legend[5] = "Kermit download directory";
13292         vars[6] = NULL;        legend[6] = NULL;
13293
13294         for (i = 0; i < 16 && vars[i]; i++) {
13295             printf("%s:\n",legend[i]);
13296             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13297             ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
13298             printf("  Variable: %s\n",vbuf);
13299             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13300             y = TMPBUFSIZ;
13301             s = tmpbuf;
13302             zzstring(vbuf,&s,&y);
13303             printf("  Value:    %s\n",tmpbuf);
13304             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13305             printf("\n");
13306             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13307         }
13308 #endif /* NT */
13309         return(success = 1);
13310     }
13311
13312 #ifdef NT
13313     if (cx == XXDIALER) {
13314         StartDialer();
13315         return(success = 1);
13316     }
13317 #endif /* NT */
13318
13319     if (cx == XXCONT) {                 /* CONTINUE */
13320         if ((x = cmcfm()) < 0)
13321           return(x);
13322         if (!xcmdsrc) {                 /* At prompt: continue script */
13323             if (cmdlvl > 0)
13324               popclvl();                /* Pop command level */
13325             return(success = 1);        /* always succeeds */
13326 #ifndef NOSPL
13327         } else {                        /* In script: whatever... */
13328             x = mlook(mactab,"continue",nmac);
13329             /* Don't set success */
13330             return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
13331 #endif /* NOSPL */
13332         }
13333     }
13334 #ifdef UNIX
13335 #ifndef NOPUTENV
13336 /*
13337   NOTE: Syntax is PUTENV name value, not PUTENV name=value.
13338   I could check for this but it would be too much magic.
13339 */
13340     if (cx == XXPUTE) {                 /* PUTENV */
13341         char * t = tmpbuf;              /* Create or alter environment var */
13342         char * s1 = NULL, * s2 = NULL;
13343         if ((x = cmfld("Variable name","",&s,xxstring)) < 0)
13344           return(x);
13345         if (s) if (s == "") s = NULL;
13346         (VOID) makestr(&s1,s);
13347         if (s && !s1) {
13348             printf("?PUTENV - memory allocation failure\n");
13349             return(-9);
13350         }
13351         if ((x = cmtxt("Value","",&s,xxstring)) < 0)
13352           return(x);
13353         if (s) if (s == "") s = NULL;
13354         (VOID) makestr(&s2,s);
13355         success = doputenv(s1,s2);
13356         (VOID) makestr(&s1,NULL);
13357         (VOID) makestr(&s2,NULL);
13358         return(success);
13359     }
13360 #endif  /* NOPUTENV */
13361 #endif  /* UNIX */
13362
13363     if (cx == XXNOTAV) {                /* Command in table not available */
13364         ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
13365         if ((x = cmtxt("Rest of command","",&s,NULL)) < 0)
13366           return(x);
13367         printf("Sorry, \"%s\" not configured in this version of Kermit.\n",
13368                tmpbuf
13369                );
13370         return(success = 0);
13371     }
13372     return(-2);                         /* None of the above */
13373
13374 } /* end of docmd() */
13375
13376 #endif /* NOICP */