update changelog
[ckermit.git] / ckuusr.c
1 #ifdef SSHTEST
2 #define SSHBUILTIN
3 #endif /* SSHTEST */
4
5 #include "ckcsym.h"
6 char *userv = "User Interface 8.0.278, 12 Mar 2004";
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, 2004,
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     ckmain.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 #endif /* NEWFTP */
153
154 #ifdef VMS
155 extern int batch;
156 #endif /* VMS */
157
158 #ifdef datageneral
159 #include <packets:common.h>
160 #define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
161 #endif /* datageneral */
162
163 extern int xcmdsrc, hints, cmflgs, whyclosed;
164
165 char * hlptok = NULL;
166
167 #ifdef CK_TTGWSIZ                       /* Whether to use more-prompting */
168 int xaskmore = 1;                       /* Momentary setting */
169 int saveask  = 1;                       /* Permanent setting */
170 #else
171 int xaskmore = 0;
172 int saveask  = 0;
173 #endif /* CK_TTGWSIZ */
174
175 #ifndef NOCSETS
176 extern int nfilc;
177 extern struct keytab fcstab[];
178 extern int fcharset;
179 #endif /* NOCSETS */
180
181 char * g_pswd = NULL;
182 int g_pcpt = -1;
183 int g_pflg = -1;
184
185 extern int cmd_rows, cmd_cols;
186
187 #ifdef CKROOT
188 extern int ckrooterr;
189 #endif /* CKROOT */
190
191 extern int inserver, filepeek;
192
193 #ifdef CKLEARN
194 FILE * learnfp = NULL;
195 char * learnfile = NULL;
196 int learning = 0;
197 #endif /* CKLEARN */
198
199 #ifndef NOXFER
200 extern int atcapr, atdiso, nfils, moving, protocol, sendmode, epktflg, size,
201   sndsrc, server, displa, fncnv, fnspath, fnrpath, xfermode, urpsiz,
202   spsizf, spsiz, spsizr, spmax, wslotr, prefixing, fncact, reliable,
203   setreliable;
204
205 #ifdef IKSDCONF
206 extern int iksdcf;
207 #endif /* IKSDCONF */
208
209 #ifdef CK_LOGIN
210 extern int isguest;
211 #endif /* CK_LOGIN */
212
213 extern long sendstart;
214
215 extern char *cmarg, *cmarg2, **cmlist, *dftty;
216
217 extern struct keytab fntab[]; extern int nfntab;
218 extern struct ck_p ptab[NPROTOS];
219
220 int sndcmd = 0;         /* Last command was a SEND-class command. */
221
222 int g_xfermode = -1;
223 int g_proto  = -1;
224 int g_urpsiz = -1;
225 int g_spsizf = -1;
226 int g_spsiz  = -1;
227 int g_spsizr = -1;
228 int g_spmax  = -1;
229 int g_wslotr = -1;
230 int g_prefixing = -1;
231 int g_fncnv  = -1;
232 int g_fnspath = -1;
233 int g_fnrpath = -1;
234 int g_fnact  = -1;
235 int g_displa = -1;
236 int g_spath  = -1;
237 int g_rpath  = -1;
238 char * g_sfilter = NULL;
239 char * g_rfilter = NULL;
240
241 extern int patterns;
242 #ifdef PATTERNS
243 extern char *txtpatterns[], *binpatterns[];
244 int g_patterns = -1;
245 #endif /* PATTERNS */
246 int g_skipbup = -1;
247
248 #ifdef PIPESEND
249 extern int usepipes, pipesend;
250 extern char * sndfilter;
251 #endif /* PIPESEND */
252
253 #ifndef NOSPL
254 extern int sndxlo, sndxhi, sndxin;
255 #endif /* NOSPL */
256
257 extern char fspec[];                    /* Most recent filespec */
258 extern int fspeclen;                    /* Length of fspec[] buffer */
259
260 #ifndef NOFRILLS
261 extern int rmailf;                      /* MAIL command items */
262 extern char optbuf[];
263 #endif /* NOFRILLS */
264
265 extern int
266   en_cpy, en_cwd, en_del, en_dir, en_fin, en_get, en_bye, en_mai, en_pri,
267   en_hos, en_ren, en_sen, en_spa, en_set, en_typ, en_who, en_ret, en_xit,
268   en_mkd, en_rmd, en_asg;
269
270 #ifndef NOMSEND                         /* Multiple SEND */
271 extern char *msfiles[];
272 int filesinlist = 0;                    /* And ADD ... */
273 extern struct filelist * filehead;
274 extern struct filelist * filetail;
275 extern struct filelist * filenext;
276 extern int addlist;
277 #endif /* NOMSEND */
278
279 static struct keytab addtab[] = {
280 #ifdef PATTERNS
281     { "binary-patterns", ADD_BIN, 0 },
282 #endif /* PATTERNS */
283 #ifndef NOMSEND
284     { "send-list", ADD_SND, 0 },
285 #endif /* NOMSEND */
286 #ifdef PATTERNS
287     { "text-patterns", ADD_TXT, 0 },
288 #endif /* PATTERNS */
289     { "", 0, 0 }
290 };
291 static int naddtab = sizeof(addtab)/sizeof(struct keytab) - 1;
292
293 #ifndef NOCSETS
294 struct keytab assoctab[] = {
295     { "file-character-set",     ASSOC_FC, 0 },
296     { "transfer-character-set", ASSOC_TC, 0 },
297     { "xfer-character-set",     ASSOC_TC, CM_INV }
298 };
299 static int nassoc = sizeof(assoctab)/sizeof(struct keytab);
300 extern int afcset[MAXFCSETS+1];         /* Character-set associations */
301 extern int axcset[MAXTCSETS+1];
302 #endif /* NOCSETS */
303
304 #ifndef ADDCMD
305 #ifndef NOMSEND
306 #define ADDCMD
307 #endif /* NOMSEND */
308 #ifndef ADDCMD
309 #ifdef PATTERNS
310 #define ADDCMD
311 #endif /* PATTERNS */
312 #endif /* ADDCMD */
313 #endif /* ADDCMD */
314 #endif /* NOXFER */
315
316 /* External Kermit Variables, see ckmain.c for description. */
317
318 extern xx_strp xxstring;
319 extern long xvernum;
320
321 extern int local, xitsta, binary, msgflg, escape, duplex, quiet, tlevel,
322   pflag, zincnt, ckxech, carrier, what, nopush, haveline, bye_active;
323 #ifdef TNCODE
324 extern int debses;
325 extern char tn_msg[];
326 #endif /* TNCODE */
327
328 int sleepcan = 1;
329 int g_binary = -1;
330 int g_recursive = -1;
331 int g_matchdot = -1;
332 extern int nolinks;
333
334 extern long vernum;
335 extern char *versio, *copyright[];
336 extern char *ckxsys;
337 #ifndef NOHELP
338 extern char *introtxt[];
339 extern char *newstxt[];
340 #endif /* NOHELP */
341
342 #ifndef OS2
343 #ifndef UNIX
344 extern char *PWDCMD;
345 #endif /* UNIX */
346 extern char *WHOCMD;
347 #endif /* OS2 */
348
349 extern char ttname[];
350
351 extern CHAR sstate;
352
353 extern int network;                     /* Have active network connection */
354 extern int nettype;                     /* Type of network */
355 extern int ttnproto;                    /* NET_TCPB protocol */
356
357 #ifndef NODIAL
358 extern int dialsta, dialatmo, dialcon, dialcq; /* DIAL status, etc. */
359 #endif /* NODIAL */
360
361 #ifdef CK_APC
362 extern int apcactive, apcstatus;
363 #endif /* CK_APC */
364
365 #ifndef NOPUSH
366 #ifndef NOFRILLS
367 extern char editor[];
368 extern char editopts[];
369 extern char editfile[];
370 #endif /* NOFRILLS */
371 #endif /* NOPUSH */
372
373 #ifdef BROWSER
374 extern char browser[];                  /* Web browser application */
375 extern char browsopts[];                /* Web browser options */
376 extern char browsurl[];                 /* Most recent URL */
377 #endif /* BROWSER */
378 #ifndef NOFTP
379 char ftpapp[CKMAXPATH+1] = { NUL, NUL }; /* ftp executable */
380 char ftpopts[128] = { NUL, NUL };       /* ftp command-line options */
381 #endif /* NOFTP */
382 extern struct keytab onoff[];           /* On/Off keyword table */
383
384 #ifdef CK_TMPDIR
385 int f_tmpdir = 0;                       /* Directory changed temporarily */
386 char savdir[TMPDIRLEN];                 /* For saving current directory */
387 #endif /* CK_TMPDIR */
388
389 int activecmd = -1;                     /* Keyword index of active command */
390 int doconx = -1;                        /* CONNECT-class command active */
391 int ooflag = 0;                         /* User-settable on/off flag */
392
393 int rcflag = 0;                         /* Pointer to home directory string */
394 int repars,                             /* Reparse needed */
395     techo = 0;                          /* Take echo */
396 int secho = 1;                          /* SCRIPT echo */
397
398 int xitwarn =                   /* Warn about open connection on exit */
399 #ifdef NOWARN
400 0
401 #else
402 1
403 #endif /* NOWARN */
404 ;
405
406 struct keytab onoffsw[] = {
407     { "/off", 0, 0 },
408     { "/on",  1, 0 }
409 };
410
411 #ifdef CKEXEC
412 struct keytab redirsw[] = {
413     { "/redirect", 1, 0 }
414 };
415 #endif /* CKEXEC */
416
417 #ifndef NOXMIT
418 /* Variables for TRANSMIT command */
419
420 int xmitx = 1;                  /* Whether to echo during TRANSMIT */
421 int xmitf = 0;                  /* Character to fill empty lines */
422 int xmitl = 0;                  /* 0 = Don't send linefeed too */
423 int xmitp = LF;                 /* Host line prompt */
424 int xmits = 0;                  /* Use shift-in/shift-out, 0 = no */
425 int xmitw = 0;                  /* Milliseconds to pause during TRANSMIT */
426 int xmitt = 1;                  /* Seconds to wait for each char to echo */
427 int xmita = 1;                  /* Action upon timeout */
428
429 #define XMI_BIN 1
430 #define XMI_TXT 2
431 #define XMI_CMD 3
432 #define XMI_TRA 4
433 #define XMI_VRB 5
434 #define XMI_QUI 6
435 #define XMI_NOW 7
436 #define XMI_NOE 8
437
438 static struct keytab xmitsw[] = {       /* TRANSMIT command options */
439     { "/binary",          XMI_BIN, 0 },
440 #ifdef PIPESEND
441     { "/command",         XMI_CMD, CM_INV|CM_PSH },
442 #endif /* PIPESEND */
443     { "/noecho",          XMI_NOE, 0 },
444     { "/nowait",          XMI_NOW, 0 },
445 #ifdef PIPESEND
446     { "/pipe",            XMI_CMD, 0 },
447 #endif /* PIPESEND */
448 #ifdef COMMENT
449     { "/quiet",           XMI_QUI, 0 },
450 #endif /* COMMENT */
451     { "/text",            XMI_TXT, 0 },
452     { "/transparent",     XMI_TRA, 0 },
453 #ifdef COMMENT
454     { "/verbose",         XMI_VRB, 0 },
455 #endif /* COMMENT */
456     { "", 0, 0 }
457 };
458 #define NXMITSW sizeof(xmitsw)/sizeof(struct keytab) - 1
459 static int nxmitsw = NXMITSW;
460
461 #endif /* NOXMIT */
462
463 /* Declarations from ck?fio.c module */
464
465 extern char *SPACMD, *SPACM2;           /* SPACE commands */
466
467 /* Command-oriented items */
468
469 #ifdef DCMDBUF
470 extern char *cmdbuf;                    /* Command buffers */
471 extern char *atmbuf;
472 extern char *line;                      /* Character buffer for anything */
473 extern char *tmpbuf;                    /* Short temporary string buffer */
474 extern int *ifcmd;
475 extern int *intime;
476 extern int *inpcas;
477 #else
478 extern char cmdbuf[];                   /* Command buffers */
479 extern char atmbuf[];
480 extern char line[];                     /* Character buffer for anything */
481 extern char tmpbuf[];                   /* Temporary buffer */
482 extern int ifcmd[];
483 extern int intime[];
484 extern int inpcas[];
485 #endif /* DCMDBUF */
486
487 #ifndef NOSPL
488 extern char * prstring[];
489 #endif /* NOSPL */
490
491 char *lp;                               /* Pointer to line buffer */
492
493 #ifndef NOSPL
494 int unkmacro = 0;                       /* Flag for in ON_UNKNOWN_COMMAND */
495 int oldeval = 0;
496 char evalbuf[33];                       /* EVALUATE result */
497 extern char * inpbuf;                   /* Buffer for INPUT and REINPUT */
498 char *inpbp;                            /* And pointer to same */
499 extern char lblbuf[];                   /* Buffer for labels */
500 int m_found;                            /* MINPUT result */
501 int i_active = 0;                       /* INPUT command is active */
502 char *ms[MINPMAX];                      /* Pointers to MINPUT strings */
503 static int mp[MINPMAX];                 /* and flags */
504 extern int fndiags, fnerror, fnsuccess; /* Function diagnostics */
505 #ifndef NOSEXP
506 char * lastsexp = NULL;                 /* S-Expressions */
507 char * sexpval = NULL;
508 int sexpecho = SET_AUTO;
509 #endif /* NOSEXP */
510 #endif /* NOSPL */
511
512 char psave[PROMPTL] = { NUL };          /* For saving & restoring prompt */
513
514 extern int success;                     /* Command success/failure flag */
515 extern int cmdlvl;                      /* Current position in command stack */
516
517 #ifndef NOSPL
518 int                                     /* SET INPUT parameters. */
519 /* Note, INPUT TIMEOUT, intime[], is on the command-level stack. */
520   inbufsize = 0,                        /* INPUT buffer size */
521   indef = 1,                            /* default timeout, seconds */
522   inecho = 1,                           /* 1 = echo on */
523   inautodl = 0,                         /* INPUT autodownload */
524   inintr = 1,                           /* INPUT interrupion allowed */
525   innomatch = 0,                        /* INPUT /NOMATCH */
526   insilence = 0;                        /* 0 = no silence constraint */
527
528 #ifdef CKFLOAT
529 CKFLOAT inscale = 1.0;                  /* Timeout scale factor */
530 #endif  /* CKFLOAT */
531
532 #ifdef OS2
533 int interm = 1;                         /* Terminal emulator displays input */
534 #endif /* OS2 */
535 int maclvl = -1;                        /* Macro nesting level */
536 int mecho = 0;                          /* Macro echo, 0 = don't */
537 char varnam[6];                         /* For variable names */
538 extern int macargc[];                   /* ARGC from macro invocation */
539
540 extern char *m_arg[MACLEVEL][NARGS];    /* Stack of macro arguments */
541 extern char *mrval[];
542
543 extern char **a_ptr[];                  /* Array pointers */
544 extern int a_dim[];                     /* Array dimensions */
545 extern int a_link[];
546
547 #ifdef DCMDBUF
548 extern struct cmdptr *cmdstk;           /* The command stack itself */
549 #else
550 extern struct cmdptr cmdstk[];          /* The command stack itself */
551 #endif /* DCMDBUF */
552
553 long ck_alarm = 0;                      /* SET ALARM value */
554 char alrm_date[24] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ' };
555 char alrm_time[24] = { ' ',' ',' ',' ',' ',' ',' ' };
556
557 #define INPSW_NOM 1
558 struct keytab inputsw[] = {
559     { "/nomatch", INPSW_NOM, 0 }
560 };
561 static int ninputsw = sizeof(inputsw)/sizeof(struct keytab);
562
563 #endif /* NOSPL */
564
565 static int x, y, z = 0;                 /* Local workers */
566 static char *s;
567
568 #ifdef CK_MINPUT
569 static char c1chars[] = {               /* C1 control chars escept NUL */
570     001,002,003,004,005,006,007,010,011,012,013,014,015,016,017,020,
571     021,022,023,024,025,026,027,030,031,032,033,034,035,036,037
572 };
573 #endif /* CK_MINPUT */
574
575 #define xsystem(s) zsyscmd(s)
576
577 /* Top-Level Interactive Command Keyword Table */
578 /* Keywords must be in lowercase and in alphabetical order. */
579
580 struct keytab cmdtab[] = {
581 #ifndef NOPUSH
582     { "!",         XXSHE, CM_INV|CM_PSH }, /* Shell escape */
583 #else
584     { "!",         XXNOTAV, CM_INV|CM_PSH },
585 #endif /* NOPUSH */
586     { "#",         XXCOM, CM_INV },     /* Comment */
587 #ifndef NOSPL
588     { "(",           XXSEXP,CM_INV },   /* S-Expression */
589     { ".",           XXDEF, CM_INV },   /* Assignment */
590     { ":",           XXLBL, CM_INV },   /* Label */
591 #endif /* NOSPL */
592 #ifdef CK_REDIR
593 #ifndef NOPUSH
594     { "<",           XXFUN, CM_INV|CM_PSH }, /* REDIRECT */
595 #else
596     { "<",           XXNOTAV, CM_INV|CM_PSH }, /* REDIRECT */
597 #endif /* NOPUSH */
598 #endif /* CK_REDIR */
599 #ifndef NOPUSH
600     { "@",           XXSHE, CM_INV|CM_PSH }, /* DCL escape */
601 #else
602     { "@",           XXNOTAV, CM_INV|CM_PSH }, /* DCL escape */
603 #endif /* NOPUSH */
604
605 #ifdef CK_RECALL
606     { "^",           XXREDO,CM_INV|CM_NOR }, /* Synonym for REDO */
607 #endif /* CK_RECALL */
608 #ifndef NOSPL
609     { "_asg",        XXASX,   CM_INV }, /* Used internally by FOR, etc */
610     { "_assign",     XXASX,   CM_INV }, /* Used internally by FOR, etc */
611     { "_decrement",  XX_DECR, CM_INV },
612     { "_define",     XXDFX,   CM_INV }, /* Used internally by FOR, etc */
613     { "_evaluate",   XX_EVAL, CM_INV },
614     { "_forward",    XXXFWD,  CM_INV }, /* Used internally by SWITCH   */
615     { "_getargs",    XXGTA,   CM_INV }, /* Used internally by FOR, etc */
616     { "_increment",  XX_INCR, CM_INV },
617     { "_putargs",    XXPTA,   CM_INV }, /* Used internally by FOR, etc */
618     { "_undefine",   XXUNDFX, CM_INV },
619 #endif /* NOSPL */
620
621     { "about",       XXVER,   CM_INV }, /* Synonym for VERSION */
622 #ifndef NOSPL
623 #ifdef NEWFTP
624     { "account",     XXACCT,  CM_INV }, /* (FTP) Account */
625 #endif /* NEWFTP */
626 #ifdef ADDCMD
627     { "add",         XXADD, 0 },        /* ADD */
628 #endif /* ADDCMD */
629 #ifndef NODIAL
630     { "answer",      XXANSW, CM_LOC },  /* ANSWER the phone */
631 #else
632     { "answer",      XXNOTAV, CM_INV|CM_LOC }, /* ANSWER the phone */
633 #endif /* NODIAL */
634     { "apc",         XXAPC, 0 },        /* Application Program Command */
635 #ifndef NOSPL
636     { "array",       XXARRAY, 0 },      /* Array operations */
637 #endif /* NOSPL */
638     { "ascii",       XXASC, CM_INV },   /* == SET FILE TYPE TEXT */
639     { "asg",         XXASS, CM_INV },   /* Invisible synonym for ASSIGN */
640     { "ask",         XXASK, 0 },        /* ASK for text, assign to variable */
641     { "askq",        XXASKQ,0 },        /* ASK quietly (no echo) */
642 #ifndef NOSPL
643     { "ass",         XXASS, CM_INV|CM_ABR }, /* ASSIGN */
644     { "assert",      XXASSER, CM_INV }, /* ASSERT */
645     { "assign",      XXASS, 0 },        /* ASSIGN */
646 #endif /* NOSPL */
647 #ifndef NOXFER
648 #ifndef NOCSETS
649     { "associate",   XXASSOC, 0 },      /* ASSOCIATE */
650 #else
651     { "associate",   XXNOTAV, CM_INV }, /* ASSOCIATE */
652 #endif /* NOCSETS */
653 #endif /* NOXFER */
654 #ifdef CK_KERBEROS
655 #ifdef CK_AUTHENTICATION
656     { "authenticate",XXAUTH, 0 },       /* Authentication */
657 #else
658     { "authenticate",XXAUTH, CM_INV },
659 #endif /* CK_AUTHENTICATION */
660 #endif /* CK_KERBEROS */
661 #endif /* NOSPL */
662 #ifndef NOFRILLS
663     { "back",        XXBACK, 0 },       /* BACK to previous directory */
664 #else
665     { "back",        XXNOTAV,CM_INV },
666 #endif /* NOFRILLS */
667     { "beep",        XXBEEP,CM_INV },   /* BEEP */
668 #ifndef NOXFER
669     { "binary",      XXBIN, CM_INV },   /* == SET FILE TYPE BINARY */
670 #endif /* NOXFER */
671 #ifndef NOFRILLS
672     { "bug",         XXBUG, CM_INV },   /* BUG report instructions */
673 #else
674     { "bug",         XXNOTAV, CM_INV },
675 #endif /* NOFRILLS */
676 #ifdef BROWSER
677     { "browse",      XXBROWS, CM_PSH|CM_LOC }, /* BROWSE (start browser) */
678 #else
679     { "browse",      XXNOTAV, CM_INV|CM_PSH|CM_LOC },
680 #endif /* BROWSER */
681 #ifndef NOXFER
682     { "bye",         XXBYE, 0 },        /* BYE to remote server */
683 #endif /* NOXFER */
684 #ifndef NOLOCAL
685     { "c",           XXCON, CM_INV|CM_ABR|CM_LOC }, /* (CONNECT) */
686 #endif /* NOLOCAL */
687 #ifndef NOFRILLS
688     { "cat",         XXCAT, CM_INV },   /* Invisible synonym for TYPE */
689 #endif /* NOFRILLS */
690 #ifndef NOSPL
691
692 #ifndef NOXFER
693     { "cautious",    XXCAU, CM_INV },
694 #endif /* NOXFER */
695
696 #endif /* NOSPL */
697
698     { "cd",          XXCWD, 0 },        /* Change Directory */
699     { "cdup",        XXCDUP, CM_INV },  /* Change Directory Up */
700
701 #ifndef NOXFER
702 #ifdef PIPESEND
703     { "cget",        XXCGET, CM_INV|CM_PSH }, /* CGET */
704 #else
705     { "cget",        XXNOTAV, CM_INV|CM_PSH }, /* CGET */
706 #endif /* PIPESEND */
707 #endif /* NOXFER */
708     { "ch",          XXCHK,   CM_INV|CM_ABR },
709     { "check",       XXCHK,   0 },      /* CHECK for a feature */
710 #ifdef CK_PERMS
711 #ifdef UNIX
712     { "chmod",       XXCHMOD, 0 },      /* CHMOD */
713 #else
714     { "chmod",       XXNOTAV, CM_INV },
715 #endif /* UNIX */
716 #else
717     { "chmod",       XXNOTAV, CM_INV },
718 #endif /* CK_PERMS */
719 #ifdef CKROOT
720     { "chroot",      XXCHRT,  CM_INV }, /* CHROOT */
721 #endif /* CKROOT */
722     { "ckermit",     XXKERMI, CM_INV }, /* CKERMIT (like KERMIT) */
723     { "cl",          XXCLO,   CM_ABR|CM_INV },
724 #ifndef NOFRILLS
725     { "clear",       XXCLE, 0 },        /* CLEAR input and/or device buffer */
726 #else
727     { "clear",       XXNOTAV, CM_INV },
728 #endif /* NOFRILLS */
729     { "close",       XXCLO, 0 },        /* CLOSE a log or other file */
730     { "cls",         XXCLS, CM_INV },   /* Clear Screen (CLS) */
731     { "comment",     XXCOM, CM_INV },   /* Introduce a comment */
732 #ifndef NOLOCAL
733     { "connect",     XXCON, CM_LOC },   /* Begin terminal connection */
734 #else
735     { "connect",     XXNOTAV, CM_LOC },
736 #endif /* NOLOCAL */
737     { "continue",    XXCONT,  CM_INV }, /* CONTINUE */
738 #ifndef NOFRILLS
739 #ifdef ZCOPY
740     { "co",          XXCPY, CM_INV|CM_ABR },
741     { "cop",         XXCPY, CM_INV|CM_ABR },
742     { "copy",        XXCPY, 0 },        /* COPY a file */
743 #else
744     { "copy",        XXNOTAV, CM_INV },
745 #endif /* ZCOPY */
746     { "copyright",   XXCPR, CM_INV },   /* COPYRIGHT */
747 #ifdef ZCOPY
748     { "cp",          XXCPY, CM_INV },   /* COPY a file */
749 #endif /* ZCOPY */
750 #ifndef NOLOCAL
751 #ifndef OS2
752     { "cq",          XXCQ, CM_INV|CM_LOC }, /* CQ (connect quietly) */
753 #endif /* OS2 */
754 #endif /* NOLOCAL */
755 #ifndef NOXFER
756 #ifdef PIPESEND
757     { "creceive",    XXCREC,CM_INV|CM_PSH }, /* RECEIVE to a command */
758     { "csend",       XXCSEN,CM_INV|CM_PSH }, /* SEND from command */
759 #else
760     { "creceive",    XXNOTAV,CM_INV|CM_PSH },
761     { "csend",       XXNOTAV,CM_INV|CM_PSH },
762 #endif /* PIPESEND */
763 #endif /* NOXFER */
764 #endif /* NOFRILLS */
765
766     { "cwd",         XXCWD,   CM_INV }, /* Traditional synonym for cd */
767
768 #ifndef NOSPL
769     { "date",        XXDATE,  0 },      /* DATE */
770     { "dcl",         XXDCL,   CM_INV }, /* DECLARE an array (see ARRAY) */
771     { "debug",       XXDEBUG, CM_INV },
772     { "declare",     XXDCL,   CM_INV }, /* DECLARE an array (see ARRAY) */
773     { "decrement",   XXDEC,   0 },      /* DECREMENT a numeric variable */
774     { "define",      XXDEF,   0 },      /* DEFINE a macro or variable */
775 #else
776     { "date",        XXNOTAV, CM_INV },
777     { "dcl",         XXNOTAV, CM_INV },
778     { "declare",     XXNOTAV, CM_INV },
779     { "decrement",   XXNOTAV, CM_INV },
780     { "define",      XXNOTAV, CM_INV },
781 #endif /* NOSPL */
782
783 #ifndef NOFRILLS
784     { "delete",      XXDEL, 0 },        /* DELETE a file */
785 #else
786     { "delete",      XXNOTAV, CM_INV },
787 #endif /* NOFRILLS */
788
789 #ifndef NODIAL
790     { "dial",        XXDIAL,  CM_LOC }, /* DIAL a phone number */
791 #else
792     { "dial",        XXNOTAV, CM_INV|CM_LOC },
793 #endif /* NODIAL */
794
795 #ifdef NT
796     { "dialer",      XXDIALER, CM_INV }, /* K95 Dialer */
797 #endif /* NT */
798
799     { "directory",   XXDIR, 0 },        /* DIRECTORY of files */
800
801 #ifndef NOFRILLS
802 #ifndef NOSERVER
803     { "disable",     XXDIS, 0 },        /* DISABLE a server function */
804 #else
805     { "disable",     XXNOTAV, CM_INV },
806 #endif /* NOSERVER */
807 #endif /* NOFRILLS */
808
809 #ifndef NOSPL
810     { "do",          XXDO,  0 },        /* DO (execute) a macro */
811 #else
812     { "do",          XXNOTAV, CM_INV },
813 #endif /* NOSPL */
814
815     { "e",           XXEXI, CM_INV|CM_ABR },
816
817 #ifndef NOFRILLS
818 #ifndef NOXFER
819     { "e-packet",    XXERR, CM_INV },   /* Send an Error-Packet */
820 #endif /* NOXFER */
821 #endif /* NOFRILLS */
822
823     { "echo",        XXECH, 0 },        /* ECHO text */
824
825 #ifndef NOFRILLS
826 #ifndef NOPUSH
827     { "edit",        XXEDIT, CM_PSH },  /* EDIT */
828 #else
829     { "edit",        XXNOTAV, CM_INV|CM_PSH }, /* EDIT */
830 #endif /* NOPUSH */
831 #endif /* NOFRILLS */
832
833     { "eightbit",    XXEIGHT, CM_INV }, /* EIGHTBIT */
834
835 #ifndef NOSPL
836     { "else",        XXELS, CM_INV },   /* ELSE part of IF statement */
837 #else
838     { "else",        XXNOTAV, CM_INV }, /* ELSE part of IF statement */
839 #endif /* NOSPL */
840
841 #ifndef NOSERVER
842 #ifndef NOFRILLS
843     { "enable",      XXENA,  0 },       /* ENABLE a server function */
844 #else
845     { "enable",      XXNOTAV, CM_INV },
846 #endif /* NOFRILLS */
847 #endif /* NOSERVER */
848
849 #ifndef NOSPL
850     { "end",         XXEND,  0 },       /* END command file or macro */
851 #else
852     { "end",         XXNOTAV, CM_INV },
853 #endif /* NOSPL */
854
855     { "erase",       XXDEL, CM_INV },   /* Synonym for DELETE */
856
857 #ifndef NOSPL
858     { "evaluate",    XXEVAL, 0 },       /* EVALUATE */
859 #else
860     { "evaluate",    XXNOTAV, CM_INV },
861 #endif /* NOSPL */
862
863     { "ex",          XXEXI, CM_INV|CM_ABR }, /* Let "ex" still be EXIT */
864
865 #ifdef CKEXEC
866     { "exec",        XXEXEC, CM_INV|CM_LOC }, /* exec() */
867 #else
868     { "exec",        XXNOTAV, CM_INV|CM_LOC },
869 #endif /* CKEXEC */
870
871     { "exit",      XXEXI, 0 },          /* EXIT from C-Kermit */
872     { "extended-options", XXXOPTS,CM_INV|CM_HLP }, /* Extended-Options */
873
874 #ifdef OS2
875     { "extproc",     XXCOM, CM_INV },   /* Dummy command for OS/2 */
876 #endif /* OS2 */
877
878 #ifndef NOXFER
879     { "f",           XXFIN, CM_INV|CM_ABR }, /* Invisible abbrev for FIN */
880 #endif /* NOXFER */
881
882 #ifndef NOSPL
883     { "fail",        XXFAIL, CM_INV },  /* FAIL */
884
885 #ifndef NOXFER
886     { "fast",        XXFAST, CM_INV },
887 #endif /* NOXFER */
888
889 #ifdef CKCHANNELIO
890     { "fclose",      XXF_CL, CM_INV },  /* FCLOSE */
891     { "fcount",      XXF_CO, CM_INV },  /* FCOUNT */
892     { "fflush",      XXF_FL, CM_INV },  /* FFLUSH */
893 #endif /* CKCHANNELIO */
894
895 #ifndef NOXFER
896     { "fi",          XXFIN, CM_INV|CM_ABR }, /* FINISH */
897 #endif /* NOXFER */
898
899 #ifdef CKCHANNELIO
900     { "file",        XXFILE, 0 },       /* FILE */
901 #endif /* CKCHANNELIO */
902 #endif /* NOSPL */
903
904 #ifndef NOXFER
905     { "fin",         XXFIN, CM_INV|CM_ABR }, /* FINISH */
906 #endif /* NOXFER */
907
908 #ifndef UNIXOROSK
909     { "find",        XXGREP, 0 },       /* FIND (grep) */
910 #else
911     { "find",        XXGREP,CM_INV },
912 #endif /* UNIXOROSK */
913
914 #ifndef NOXFER
915     { "finish",      XXFIN, 0 },        /* FINISH */
916 #endif /* NOXFER */
917
918 #ifdef TCPSOCKET
919     { "firewall",    XXFIREW, CM_INV|CM_HLP },
920 #endif /* TCPSOCKET */
921
922 #ifdef CKCHANNELIO
923     { "flist",       XXF_LI, CM_INV },  /* FLIST */
924     { "fopen",       XXF_OP, CM_INV },  /* FOPEN */
925 #endif /* CKCHANNELIO */
926
927 #ifndef NOSPL
928     { "fo",          XXFOR, CM_INV|CM_ABR }, /* Invisible abbrev for... */
929     { "for",         XXFOR, 0 },        /* FOR loop */
930     { "forward",     XXFWD, CM_INV },   /* FORWARD */
931 #endif /* NOSPL */
932 #ifndef NOFRILLS
933     { "fot",       XXDIR, CM_INV },     /* "fot" = "dir" (for Chris) */
934 #endif /* NOFRILLS */
935
936 #ifdef CKCHANNELIO
937     { "fread",      XXF_RE, CM_INV },   /* FREAD */
938     { "frewind",    XXF_RW, CM_INV },   /* FREWIND */
939     { "fseek",      XXF_SE, CM_INV },   /* FSEEK */
940     { "fstatus",    XXF_ST, CM_INV },   /* FSTATUS */
941 #endif /* CKCHANNELIO */
942
943 #ifdef TCPSOCKET
944 #ifndef NOFTP
945 #ifdef SYSFTP
946 #ifndef NOPUSH
947     { "ftp",       XXFTP,   CM_INV|CM_PSH|CM_LOC }, /* System FTP */
948 #else
949     { "ftp",       XXNOTAV, CM_INV|CM_PSH|CM_LOC },
950 #endif /* NOPUSH */
951 #else  /* SYSFTP */
952     { "ftp",       XXFTP,   0 },        /* Built-in FTP */
953 #endif /* SYSFTP */
954 #else  /* NOFTP */
955     { "ftp",       XXNOTAV, CM_INV },   /* No FTP */
956 #endif /* NOFTP */
957 #endif /* TCPSOCKET */
958
959 #ifndef NOSPL
960     { "function",    XXFUNC, CM_INV|CM_HLP }, /* (for HELP FUNCTION) */
961 #endif /* NOSPL */
962
963 #ifdef CKCHANNELIO
964     { "fwrite",      XXF_WR, CM_INV },  /* FWRITE */
965 #endif /* CKCHANNELIO */
966
967 #ifndef NOXFER
968     { "g",           XXGET, CM_INV|CM_ABR }, /* Invisible abbrev for GET */
969 #ifndef NOSPL
970     { "ge",          XXGET, CM_INV|CM_ABR }, /* Ditto */
971 #endif /* NOSPL */
972     { "get",         XXGET, 0 },        /* GET */
973 #endif /* NOXFER */
974 #ifndef NOSPL
975     { "getc",        XXGETC, 0 },       /* GETC */
976 #ifdef OS2
977     { "getkeycode",  XXGETK, 0 },       /* GETKEYCODE */
978 #endif /* OS2 */
979 #ifndef NOFRILLS
980     { "getok",       XXGOK, 0 },        /* GETOK (ask for Yes/No/OK) */
981 #endif /* NOFRILLS */
982 #endif /* NOSPL */
983 #ifndef NOSPL
984     { "goto",        XXGOTO,0 },        /* GOTO label in take file or macro */
985 #endif /* NOSPL */
986 #ifdef UNIXOROSK
987     { "grep",        XXGREP,0 },        /* GREP (find) */
988 #else
989     { "grep",        XXGREP,CM_INV },   /* GREP (find) */
990 #endif /* UNIXOROSK */
991     { "h",           XXHLP, CM_INV|CM_ABR }, /* Invisible synonym for HELP */
992     { "he",          XXHLP, CM_INV|CM_ABR }, /* Invisible synonym for HELP */
993 #ifndef NOFRILLS
994     { "head",        XXHEAD, 0 },
995 #endif /* NOFRILLS */
996 #ifndef NOLOCAL
997     { "hangup",      XXHAN, CM_LOC },   /* HANGUP the connection */
998 #endif /* NOLOCAL */
999     { "HELP",        XXHLP, 0 },        /* Display HELP text */
1000 #ifndef NOHTTP
1001 #ifdef TCPSOCKET
1002     { "http",        XXHTTP, 0 },       /* HTTP operations */
1003 #endif /* TCPSOCKET */
1004 #endif /* NOHTTP */
1005 #ifndef NOSPL
1006     { "i",           XXINP, CM_INV|CM_ABR }, /* Invisible synonym for INPUT */
1007     { "if",          XXIF,  0 },             /* IF ( condition ) command */
1008 #ifdef TCPSOCKET
1009     { "iksd",        XXIKSD, CM_INV },       /* Make connection to IKSD */
1010 #else
1011     { "iksd",        XXNOTAV, CM_INV },
1012 #endif /* TCPSOCKET */
1013     { "in",          XXINP, CM_INV|CM_ABR }, /* Invisible synonym for INPUT */
1014     { "increment",   XXINC, 0 },        /* Increment a numeric variable */
1015     { "input",       XXINP, 0 },        /* INPUT text from comm device */
1016 #endif /* NOSPL */
1017
1018 #ifndef NOHELP
1019     { "int",         XXINT, CM_INV|CM_ABR },
1020     { "intr",        XXINT, CM_INV|CM_ABR },
1021     { "INTRO",       XXINT, 0 },
1022     { "introduction",XXINT, CM_INV },   /* Print introductory text */
1023 #else
1024     { "intro",       XXNOTAV, CM_INV },
1025     { "introduction",XXNOTAV, CM_INV },
1026 #endif /* NOHELP */
1027
1028 #ifdef OS2
1029     { "k95",         XXKERMI, CM_INV }, /* Hmmm what's this... */
1030 #endif /* OS2 */
1031
1032 #ifndef NOSPL
1033     { "kcd",         XXKCD,   0      },
1034 #endif /* NOSPL */
1035
1036     { "kermit",      XXKERMI, CM_INV },
1037
1038 #ifdef OS2
1039 #ifndef NOKVERBS
1040     { "kverb",       XXKVRB, CM_INV|CM_HLP }, /* Keyboard verb */
1041 #endif /* NOKVERBS */
1042 #endif /* OS2 */
1043
1044 #ifndef NOFRILLS
1045     { "l",           XXLOG, CM_INV|CM_ABR }, /* Invisible synonym for log */
1046 #endif /* NOFRILLS */
1047
1048     { "lcd",         XXLCWD, CM_INV },
1049     { "lcdup",       XXLCDU, CM_INV },
1050     { "lcwd",        XXLCWD, CM_INV },
1051     { "ldelete",     XXLDEL, CM_INV },
1052     { "ldirectory",  XXLDIR, CM_INV },
1053
1054 #ifdef CKLEARN
1055     { "learn",       XXLEARN, 0 },      /* LEARN - automatic script writing */
1056 #else
1057     { "learn",       XXNOTAV, CM_INV },
1058 #endif /* CKLEARN */
1059
1060     { "li",          XXLNOUT, CM_INV|CM_ABR },
1061     { "LICENSE",     XXCPR, 0 },        /* LICENSE */
1062
1063 #ifndef NOSPL
1064     { "lineout",     XXLNOUT, 0 },      /* LINEOUT = OUTPUT + eol */
1065 #endif /* NOSPL */
1066
1067 #ifdef NT
1068     { "link",        XXLINK, 0 },       /* LINK source destination */
1069 #endif /* NT */
1070
1071     { "lmkdir",      XXLMKD, CM_INV },
1072
1073 #ifndef NOFRILLS
1074     { "lo",          XXLOG,  CM_INV|CM_ABR }, /* Invisible synonym for log */
1075 #endif /* NOFRILLS */
1076
1077 #ifndef NOSPL
1078     { "local",       XXLOCAL, CM_INV }, /* LOCAL variable declaration */
1079 #else
1080     { "local",       XXNOTAV, CM_INV },
1081 #endif /* NOSPL */
1082
1083     { "log",         XXLOG, 0 },        /* Open a log file */
1084
1085     { "login",       XXLOGIN,  0 },     /* (REMOTE) LOGIN to server or IKSD */
1086     { "logout",      XXLOGOUT, 0 },     /* LOGOUT from server or IKSD */
1087
1088 #ifndef NOFRILLS
1089 #ifndef NODIAL
1090     { "lookup",      XXLOOK,  0 },      /* LOOKUP */
1091 #else
1092     { "lookup",      XXNOTAV, CM_INV },
1093 #endif /* NODIAL */
1094
1095     { "lpwd",        XXLPWD, CM_INV },
1096     { "lrename",     XXLREN, CM_INV },
1097     { "lrmdir",      XXLRMD, CM_INV },
1098
1099 #ifdef UNIXOROSK
1100     { "ls",          XXLS,  CM_INV|CM_PSH }, /* UNIX ls command */
1101 #else
1102     { "ls",          XXDIR, CM_INV },   /* Invisible synonym for DIR */
1103 #endif /* UNIXOROSK */
1104 #ifndef NOXFER
1105     { "mail",        XXMAI, 0 },        /* Send a file as e-mail */
1106 #endif /* NOXFER */
1107 #ifndef NOHELP
1108     { "manual",      XXMAN, CM_PSH },   /* MAN(UAL) */
1109 #else
1110     { "manual",      XXNOTAV, CM_INV|CM_PSH },
1111 #endif /* NOHELP */
1112 #endif /* NOFRILLS */
1113 #ifdef CK_MKDIR
1114     { "md",          XXMKDIR, CM_INV }, /* Synonym for MKDIR */
1115 #endif /* CK_MKDIR */
1116 #ifdef CK_MINPUT
1117     { "minput",      XXMINP, 0 },       /* MINPUT */
1118 #else
1119     { "minput",      XXNOTAV, CM_INV },
1120 #endif /* CK_MINPUT */
1121 #ifndef NOMSEND
1122     { "mget",        XXMGET, 0 },       /* MGET */
1123 #else
1124     { "mget",        XXNOTAV, CM_INV },
1125 #endif /* NOMSEND */
1126 #ifdef CK_MKDIR
1127     { "mkdir",       XXMKDIR, 0 },      /* MKDIR */
1128 #else
1129     { "mkdir",       XXNOTAV, CM_INV },
1130 #endif /* CK_MKDIR */
1131
1132 #ifndef NOXFER
1133 #ifndef NOMSEND
1134     { "mmove",       XXMMOVE, 0 },      /* MMOVE */
1135 #else
1136     { "mmove",       XXNOTAV, CM_INV },
1137 #endif /* NOMSEND */
1138 #endif /* NOXFER */
1139
1140 #ifndef NOFRILLS
1141     { "more",        XXMORE, CM_INV },  /* MORE */
1142 #endif /* NOFRILLS */
1143
1144 #ifndef NOXFER
1145     { "move",        XXMOVE, 0 },       /* MOVE  */
1146 #endif /* NOXFER */
1147
1148 #ifndef NOSPL
1149     { "mpause",      XXMSL, CM_INV },   /* Millisecond sleep */
1150 #else
1151     { "mpause",      XXNOTAV, CM_INV },
1152 #endif /* NOSPL */
1153
1154 #ifndef NOXFER
1155 #ifndef NOMSEND
1156     { "mput",        XXMSE, CM_INV },   /* MPUT = MSEND */
1157     { "ms",          XXMSE, CM_INV|CM_ABR },
1158     { "msend",       XXMSE, 0 },        /* Multiple SEND */
1159 #else
1160     { "mput",        XXNOTAV, CM_INV },
1161     { "msend",       XXNOTAV, CM_INV },
1162 #endif /* NOMSEND */
1163 #endif /* NOXFER */
1164 #ifndef NOSPL
1165     { "msleep",      XXMSL, 0 },        /* Millisecond sleep */
1166 #else
1167     { "msleep",      XXNOTAV, CM_INV },
1168 #endif /* NOSPL */
1169 #ifndef NOFRILLS
1170     { "mv",          XXREN, CM_INV },   /* Synonym for rename */
1171 #endif /* NOFRILLS */
1172 #ifndef NOHELP
1173     { "news",        XXNEW, CM_INV },   /* Display NEWS of new features */
1174 #else
1175     { "news",        XXNOTAV, CM_INV },
1176 #endif /* NOHELP */
1177     { "nolocal",     XXNLCL, CM_INV },  /* Disable SET LINE / SET HOST */
1178     { "nopush",      XXNPSH, CM_INV },  /* Disable PUSH command/features */
1179 #ifdef OS2
1180     { "noscroll",    XXNSCR, CM_INV },  /* Disable scroll operations */
1181 #endif /* OS2 */
1182 #ifndef NOSPL
1183     { "o",           XXOUT, CM_INV|CM_ABR }, /* Invisible synonym for OUTPUT */
1184     { "open",        XXOPE, 0 },        /* OPEN file for reading or writing */
1185 #else
1186     { "open",        XXOPE, CM_INV },   /* OPEN */
1187 #endif /* NOSPL */
1188 #ifndef NOHELP
1189     { "options",     XXOPTS,CM_INV|CM_HLP }, /* Options */
1190 #endif /* NOHELP */
1191     { "orientation", XXORIE, 0 },
1192 #ifndef NOSPL
1193     { "output",      XXOUT, 0 },        /* OUTPUT text to comm device */
1194 #else
1195     { "output",      XXNOTAV, CM_INV },
1196 #endif /* NOSPL */
1197 #ifdef ANYX25
1198 #ifndef IBMX25
1199     { "pad",         XXPAD, CM_LOC },   /* X.3 PAD commands */
1200 #endif /* IBMX25 */
1201 #endif /* ANYX25 */
1202
1203 #ifdef NEWFTP
1204     { "passive",     XXPASV, CM_INV },  /* (FTP) PASSIVE */
1205 #endif /* NEWFTP */
1206
1207 #ifndef NOHELP
1208     { "patterns",    XXPAT,CM_INV|CM_HLP }, /* Pattern syntax */
1209 #endif /* NOHELP */
1210
1211 #ifndef NOSPL
1212     { "pause",       XXPAU, 0 },        /* Sleep for specified interval */
1213 #else
1214     { "pause",       XXNOTAV, CM_INV },
1215 #endif /* NOSPL */
1216 #ifndef NODIAL
1217     { "pdial",       XXPDIA,  CM_LOC }, /* PDIAL (partial dial) */
1218 #else
1219     { "pdial",       XXNOTAV, CM_INV|CM_LOC },
1220 #endif /* NODIAL */
1221 #ifdef TCPSOCKET
1222 #ifndef NOPUSH
1223     { "ping",        XXPNG, CM_INV|CM_PSH|CM_LOC }, /* PING */
1224 #else
1225     { "ping",        XXNOTAV, CM_INV|CM_PSH|CM_LOC },
1226 #endif /* NOPUSH */
1227 #endif /* TCPSOCKET */
1228 #ifdef NETCMD
1229 #ifndef NOPUSH
1230     { "pipe",        XXPIPE, CM_PSH },  /* PIPE */
1231 #else
1232     { "pipe",        XXNOTAV, CM_INV|CM_PSH }, /* PIPE */
1233 #endif /* NOPUSH */
1234 #endif /* NETCMD */
1235
1236 #ifndef NOSPL
1237     { "pop",         XXEND, CM_INV },   /* Invisible synonym for END */
1238 #endif /* NOSPL */
1239 #ifndef NOFRILLS
1240     { "print",       XXPRI, 0 },        /* PRINT a file locally */
1241 #endif /* NOFRILLS */
1242
1243     { "prompt",      XXPROMP, CM_INV }, /* Go interactive (from script) */
1244
1245 #ifndef NOXFER
1246 #ifdef CK_RESEND
1247     { "psend",       XXPSEN, CM_INV },  /* PSEND */
1248 #else
1249     { "psend",       XXNOTAV, CM_INV },
1250 #endif /* CK_RESEND */
1251 #endif /* NOXFER */
1252
1253 #ifdef NETPTY
1254     { "pty",         XXPTY, CM_PSH },   /* PTY */
1255 #else
1256     { "pty",         XXNOTAV, CM_INV|CM_PSH },
1257 #endif /* NETPTY */
1258
1259 #ifndef NOPUSH
1260     { "pu",          XXSHE, CM_INV|CM_ABR|CM_PSH }, /* PU = PUSH */
1261 #endif /* NOPUSH */
1262
1263 #ifdef CKPURGE
1264     { "purge",       XXPURGE, 0 },      /* PURGE (real) */
1265 #else
1266 #ifdef VMS
1267     { "purge",       XXPURGE, 0 },      /* PURGE (fake) */
1268 #else
1269     { "purge",       XXNOTAV, CM_INV },
1270 #endif /* VMS */
1271 #endif /* CKPURGE */
1272
1273 #ifndef NOPUSH
1274     { "push",        XXSHE, CM_PSH },   /* PUSH command (like RUN, !) */
1275 #else
1276     { "push",        XXNOTAV, CM_INV|CM_PSH },
1277 #endif /* NOPUSH */
1278
1279 #ifndef NOXFER
1280     { "put",         XXSEN, CM_INV },   /* PUT = SEND */
1281 #endif /* NOXFER */
1282
1283     { "pwd",         XXPWD, 0 },        /* Print Working Directory */
1284     { "q",           XXQUI, CM_INV|CM_ABR }, /* Invisible synonym for QUIT */
1285
1286 #ifndef NOXFER
1287     { "query",       XXRQUE,CM_INV },   /* (= REMOTE QUERY) */
1288 #endif /* NOXFER */
1289
1290     { "quit",        XXQUI, 0 },        /* QUIT from program = EXIT */
1291
1292 #ifndef NOXFER
1293     { "r",           XXREC, CM_INV|CM_ABR }, /* Inv synonym for RECEIVE */
1294 #endif /* NOXFER */
1295
1296 #ifndef NOXFER
1297     { "rasg",        XXRASG, CM_INV },  /* REMOTE ASSIGN */
1298     { "rassign",     XXRASG, CM_INV },  /* ditto */
1299     { "rcd",         XXRCWD, CM_INV },  /* REMOTE CD */
1300     { "rcdup",       XXRCDUP,CM_INV },  /* REMOTE CD */
1301     { "rcopy",       XXRCPY, CM_INV },  /* REMOTE COPY */
1302     { "rcwd",        XXRCWD, CM_INV },  /* REMOTE CWD */
1303     { "rdelete",     XXRDEL, CM_INV },  /* REMOTE DELETE */
1304     { "rdirectory",  XXRDIR, CM_INV },  /* REMODE DIRECTORY */
1305 #endif /* NOXFER */
1306
1307 #ifndef NOSPL
1308     { "read",        XXREA, 0 },        /* READ a line from a file */
1309 #else
1310     { "read",        XXNOTAV, CM_INV },
1311 #endif /* NOSPL */
1312
1313 #ifndef NOXFER
1314     { "receive",     XXREC, 0 },        /* RECEIVE files */
1315 #endif /* NOXFER */
1316
1317 #ifndef NODIAL
1318     { "red",         XXRED, CM_INV|CM_ABR|CM_LOC }, /* Inv syn for REDIAL */
1319     { "redi",        XXRED, CM_INV|CM_ABR|CM_LOC }, /* ditto */
1320     { "redial",      XXRED, CM_LOC },   /* REDIAL last DIAL number */
1321 #else
1322     { "red",         XXNOTAV, CM_INV|CM_LOC },
1323     { "redi",        XXNOTAV, CM_INV|CM_LOC },
1324     { "redial",      XXNOTAV, CM_INV|CM_LOC },
1325 #endif /* NODIAL */
1326
1327 #ifdef CK_REDIR
1328 #ifdef OS2
1329 #ifndef NOPUSH
1330     { "redirect",    XXFUN, CM_INV|CM_PSH }, /* REDIRECT */
1331 #else
1332     { "redirect",    XXNOTAV, CM_INV|CM_PSH },
1333 #endif /* NOPUSH */
1334 #else /* OS2 */
1335 #ifndef NOPUSH
1336     { "redirect",    XXFUN, CM_PSH },   /* REDIRECT */
1337 #else
1338     { "redirect",    XXNOTAV, CM_INV|CM_PSH },
1339 #endif /* NOPUSH */
1340 #endif /* OS2 */
1341 #endif /* CK_REDIR */
1342
1343 #ifdef CK_RECALL
1344     { "redo",        XXREDO,  CM_NOR }, /* REDO */
1345 #else
1346     { "redo",        XXNOTAV, CM_INV },
1347 #endif /* CK_RECALL */
1348
1349 #ifndef NOXFER
1350 #ifdef CK_RESEND
1351     { "reget",       XXREGET, 0 },      /* REGET */
1352 #else
1353     { "reget",       XXNOTAV, CM_INV },
1354 #endif /* CK_RESEND */
1355 #endif /* NOXFER */
1356
1357 #ifndef NOSPL
1358     { "reinput",     XXREI, CM_INV },   /* REINPUT (from INPUT buffer) */
1359 #else
1360     { "reinput",     XXNOTAV, CM_INV },
1361 #endif /* NOSPL */
1362
1363 #ifndef NOXFER
1364 #ifdef ADDCMD
1365     { "rem",         XXREM, CM_INV|CM_ABR },
1366     { "remo",        XXREM, CM_INV|CM_ABR },
1367 #endif /* ADDCMD */
1368     { "remote",      XXREM, 0 },        /* Send REMOTE command to server */
1369 #endif /* NOXFER */
1370
1371 #ifdef ADDCMD
1372     { "remove",      XXREMV,0 },        /* REMOVE (something from a list) */
1373 #else
1374     { "remove",      XXNOTAV, CM_INV },
1375 #endif /* ADDCMD */
1376
1377 #ifndef NOFRILLS
1378 #ifndef NORENAME
1379     { "rename",      XXREN, 0 },        /* RENAME a local file */
1380 #else
1381     { "rename",      XXNOTAV, CM_INV },
1382 #endif /* NORENAME */
1383     { "replay",      XXTYP, CM_INV },   /* REPLAY (for now, just type) */
1384 #endif /* NOFRILLS */
1385
1386 #ifndef NOXFER
1387 #ifdef CK_RESEND
1388     { "res",         XXRSEN, CM_INV|CM_ABR }, /* RESEND */
1389     { "rese",        XXRSEN, CM_INV|CM_ABR }, /* RESEND */
1390     { "resend",      XXRSEN, 0 },       /* RESEND */
1391 #else
1392     { "res",         XXNOTAV, CM_INV },
1393     { "rese",        XXNOTAV, CM_INV },
1394     { "resend",      XXNOTAV, CM_INV },
1395 #endif /* CK_RESEND */
1396 #endif /* NOXFER */
1397
1398     { "reset",       XXRESET, CM_INV }, /* RESET */
1399
1400 #ifdef CK_RESEND
1401 #ifndef NOSPL
1402     { "ret",         XXRET, CM_INV|CM_ABR },
1403 #endif /* NOSPL */
1404 #endif /* CK_RESEND */
1405
1406 #ifndef NOXFER
1407     { "retrieve",    XXRETR, CM_INV },  /* RETRIEVE */
1408 #endif /* NOXFER */
1409
1410 #ifndef NOSPL
1411     { "return",      XXRET, 0 },        /* RETURN from a function */
1412 #else
1413     { "return",      XXNOTAV, CM_INV },
1414 #endif /* NOSPL */
1415
1416 #ifndef NOXFER
1417     { "rexit",       XXRXIT, CM_INV },  /* REMOTE EXIT */
1418 #endif /* NOXFER */
1419
1420 #ifdef CK_REXX
1421 #ifndef NOPUSH
1422     { "rexx",        XXREXX, CM_PSH },  /* Execute a Rexx command */
1423 #else
1424     { "rexx",        XXNOTAV, CM_INV|CM_PSH },
1425 #endif /* NOPUSH */
1426 #endif /* CK_REXX */
1427
1428 #ifndef NOXFER
1429     { "rhelp",       XXRHLP, CM_INV },  /* REMOTE HELP */
1430     { "rhost",       XXRHOS, CM_INV },  /* REMOTE HOST */
1431     { "rkermit",     XXRKER, CM_INV },  /* REMOTE KERMIT */
1432 #endif /* NOXFER */
1433
1434 #ifdef TCPSOCKET
1435     { "rlogin",      XXRLOG, CM_LOC },  /* Make an Rlogin connection */
1436 #else
1437     { "rlogin",      XXNOTAV, CM_INV|CM_LOC },
1438 #endif /* TCPSOCKET */
1439
1440 #ifndef NOFRILLS
1441     { "rm",          XXDEL, CM_INV },   /* Invisible synonym for delete */
1442 #endif /* NOFRILLS */
1443
1444 #ifdef CK_MKDIR
1445     { "rmdir",       XXRMDIR, 0 },      /* RMDIR */
1446 #else
1447     { "rmdir",       XXNOTAV, CM_INV },
1448 #endif /* CK_MKDIR */
1449
1450 #ifndef NOXFER
1451     { "rmkdir",      XXRMKD, CM_INV },  /* REMOTE MKDIR */
1452 #ifndef NOSPL
1453     { "robust",      XXROB,  CM_INV },
1454 #else
1455     { "robust",      XXNOTAV, CM_INV },
1456 #endif /* NOSPL */
1457     { "rprint",      XXRPRI, CM_INV },  /* REMOTE PRINT */
1458     { "rpwd",        XXRPWD, CM_INV },  /* REMOTE PWD */
1459     { "rquery",      XXRQUE, CM_INV },  /* REMOTE QUERY */
1460 #endif /* NOXFER */
1461
1462 #ifdef CK_RECALL
1463     { "rr",          XXREDO, CM_INV|CM_NOR },
1464 #endif /* CK_RECALL */
1465
1466 #ifndef NOXFER
1467     { "rrename",    XXRREN, CM_INV },   /* REMOTE RENAME */
1468     { "rrmdir",     XXRRMD, CM_INV },   /* REMOTE REMDIR */
1469     { "rset",       XXRSET, CM_INV },   /* REMOTE SET */
1470     { "rspace",     XXRSPA, CM_INV },   /* REMOTE SPACE */
1471     { "rtype",      XXRTYP, CM_INV },   /* REMOTE TYPE */
1472 #endif /* NOXFER */
1473
1474 #ifndef NOPUSH
1475     { "run",         XXSHE, CM_PSH },   /* RUN a program or command */
1476 #else
1477     { "run",         XXNOTAV, CM_INV|CM_PSH },
1478 #endif /* NOPUSH */
1479
1480 #ifndef NOXFER
1481     { "rwho",        XXRWHO, CM_INV },  /* REMOTE WHO */
1482     { "s",           XXSEN, CM_INV|CM_ABR }, /* Invisible synonym for send */
1483 #endif /* NOXFER */
1484
1485 #ifndef NOSETKEY
1486 #ifdef OS2
1487     { "save",      XXSAVE, 0 },         /* SAVE something */
1488 #else
1489     { "save",      XXSAVE, CM_INV },
1490 #endif /* OS2 */
1491 #else
1492     { "save",      XXNOTAV, CM_INV },
1493 #endif /* NOSETKEY */
1494
1495 #ifndef NOSCRIPT
1496     { "sc",        XXLOGI, CM_INV|CM_ABR|CM_LOC },
1497     { "scr",       XXLOGI, CM_INV|CM_ABR|CM_LOC },
1498 #endif /* NOSCRIPT */
1499     { "screen",      XXSCRN, 0 },       /* SCREEN actions */
1500 #ifndef NOSCRIPT
1501     { "script",    XXLOGI, CM_LOC },    /* Expect-Send-style script line */
1502 #else
1503     { "script",    XXNOTAV, CM_INV|CM_LOC },
1504 #endif /* NOSCRIPT */
1505
1506     { "search",    XXGREP,CM_INV },     /* Synonym for GREP and FIND */
1507
1508 #ifndef NOXFER
1509     { "send",      XXSEN, 0 },          /* Send (a) file(s) */
1510 #ifndef NOSERVER
1511     { "server",    XXSER, 0 },          /* Be a SERVER */
1512 #else
1513     { "server",    XXNOTAV, CM_INV },
1514 #endif /* NOSERVER */
1515 #endif /* NOXFER */
1516
1517     { "set",       XXSET, 0 },          /* SET parameters */
1518
1519 #ifndef NOSPL
1520 #ifndef NOSEXP
1521     { "sexpression", XXSEXP, CM_INV|CM_HLP }, /* SEXPR */
1522 #endif /* NOSEXP */
1523
1524 #ifdef SFTP_BUILTIN
1525     { "sftp",        XXSFTP, 0 },   /* SFTP */
1526 #endif /* SFTP_BUILTIN */
1527
1528 #ifndef NOSHOW
1529     { "sh",          XXSHO, CM_INV|CM_ABR }, /* SHOW parameters */
1530 #endif /* NOSHOW */
1531     { "shift",       XXSHIFT, 0 },      /* SHIFT args */
1532 #else
1533     { "shift",       XXNOTAV, CM_INV },
1534 #endif /* NOSPL */
1535
1536 #ifndef NOSHOW
1537     { "show",      XXSHO, 0 },          /* SHOW parameters */
1538 #else
1539     { "show",      XXNOTAV, CM_INV },
1540 #endif /* NOSHOW */
1541
1542 #ifdef NEWFTP
1543     { "site",        XXSITE, CM_INV },  /* (FTP) SITE */
1544 #endif /* NEWFTP */
1545
1546 #ifdef SSHBUILTIN
1547     { "skermit",   XXSKRM, 0 },     /* SKERMIT */
1548 #endif /* SSHBUILTIN */
1549
1550 #ifndef NOSPL
1551 #ifndef NOFRILLS
1552     { "sleep",       XXPAU, CM_INV },   /* SLEEP for specified interval */
1553 #endif /* NOFRILLS */
1554 #endif /* NOSPL */
1555
1556 #ifndef NOSPL
1557     { "sort",        XXSORT, CM_INV },  /* (see ARRAY) */
1558 #else
1559     { "sort",        XXNOTAV, CM_INV },
1560 #endif /* NOSPL */
1561
1562 #ifndef MAC
1563 #ifndef NOFRILLS
1564     { "sp",          XXSPA, CM_INV|CM_ABR },
1565     { "spa",         XXSPA, CM_INV|CM_ABR },
1566 #endif /* NOFRILLS */
1567     { "space",       XXSPA, 0 },        /* Show available disk SPACE */
1568 #endif /* MAC */
1569
1570 #ifndef NOFRILLS
1571 #ifndef NOPUSH
1572     { "spawn",       XXSHE, CM_INV|CM_PSH }, /* Synonym for PUSH, RUN */
1573 #else
1574     { "spawn",       XXNOTAV, CM_INV|CM_PSH }, /* Synonym for PUSH, RUN */
1575 #endif /* NOPUSH */
1576 #endif /* NOFRILLS */
1577
1578 #ifdef ANYSSH
1579     { "ssh",         XXSSH, 0 },
1580 #endif /* ANYSSH */
1581
1582 #ifndef NOXFER
1583     { "sta",         XXSTA, CM_INV|CM_ABR },
1584     { "stat",        XXSTA, CM_INV|CM_ABR },
1585     { "statistics",  XXSTA, 0 },        /* Display file transfer stats */
1586 #endif /* NOXFER */
1587
1588     { "status",      XXSTATUS,0 },      /* Show status of previous command */
1589
1590 #ifndef NOSPL
1591     { "stop",        XXSTO,   0 },      /* STOP all take files and macros */
1592     { "succeed",     XXSUCC,  CM_INV }, /* SUCCEED */
1593 #else
1594     { "stop",        XXNOTAV, CM_INV },
1595     { "succeed",     XXNOTAV, CM_INV },
1596 #endif /* NOSPL */
1597
1598 #ifndef NOFRILLS
1599     { "SUPPORT",     XXBUG, 0 },        /* Tech support instructions */
1600 #else
1601     { "support",     XXNOTAV, CM_INV },
1602 #endif /* NOFRILLS */
1603
1604 #ifndef NOJC
1605     { "suspend",     XXSUS, CM_PSH },   /* SUSPEND C-Kermit (UNIX only) */
1606 #else
1607     { "suspend",     XXNOTAV, CM_INV|CM_PSH },
1608 #endif /* NOJC */
1609
1610 #ifndef NOSPL
1611     { "switch",      XXSWIT, 0 },       /* SWITCH */
1612 #else
1613     { "switch",      XXNOTAV, CM_INV },
1614 #endif /* NOSPL */
1615
1616 #ifdef CK_TAPI
1617     { "ta",        XXTAK, CM_INV|CM_ABR }, /* (because of TAPI) */
1618 #endif /* CK_TAPI */
1619
1620 #ifndef NOFRILLS
1621     { "tail",        XXTAIL, 0 },       /* Display end of a local file */
1622 #endif /* NOFRILLS */
1623
1624     { "take",      XXTAK, 0 },          /* TAKE commands from a file */
1625
1626 #ifdef CK_TAPI
1627     { "tapi",      XXTAPI, CM_LOC },    /* Microsoft TAPI commands */
1628 #else
1629     { "tapi",      XXNOTAV, CM_INV|CM_LOC },
1630 #endif /* CK_TAPI */
1631
1632 #ifndef NOFRILLS
1633 #ifdef TCPSOCKET
1634     { "tel",         XXTEL, CM_INV|CM_ABR|CM_LOC },
1635     { "telnet",      XXTEL, CM_LOC },   /* TELNET (TCP/IP only) */
1636     { "telopt",      XXTELOP, CM_INV }, /* TELOPT (ditto) */
1637 #else
1638     { "tel",         XXNOTAV, CM_INV|CM_LOC },
1639     { "telnet",      XXNOTAV, CM_INV|CM_LOC },
1640     { "telopt",      XXNOTAV, CM_INV },
1641 #endif /* TCPSOCKET */
1642 #ifdef OS2
1643     { "terminal",    XXTERM, CM_INV|CM_LOC }, /* == SET TERMINAL TYPE */
1644 #else
1645     { "terminal",    XXTERM, CM_INV },
1646 #endif /* OS2 */
1647 #endif /* NOFRILLS */
1648 #ifndef NOXFER
1649     { "text",        XXASC, CM_INV },   /* == SET FILE TYPE TEXT */
1650 #endif /* NOXFER */
1651
1652 #ifndef NOSPL
1653     { "trace",       XXTRACE, 0 },      /* TRACE */
1654 #else
1655     { "trace",       XXNOTAV, CM_INV },
1656 #endif /* NOSPL */
1657
1658 #ifndef NOCSETS
1659     { "translate",   XXXLA, 0 },        /* TRANSLATE local file char sets */
1660 #else
1661     { "translate",   XXNOTAV, CM_INV },
1662 #endif /* NOCSETS */
1663
1664 #ifndef NOXMIT
1665     { "transmit",    XXTRA, 0 },        /* Send (upload) a file, no protocol */
1666 #else
1667     { "transmit",    XXNOTAV, CM_INV },
1668 #endif /* NOXMIT */
1669
1670 #ifndef NOFRILLS
1671     { "type",        XXTYP, 0 },        /* Display a local file */
1672 #endif /* NOFRILLS */
1673
1674 #ifndef NOSPL
1675     { "undcl",       XXUNDCL, CM_INV },
1676     { "undeclare",   XXUNDCL, 0 },      /* UNDECLARE an array */
1677     { "undefine",    XXUNDEF, 0 },      /* UNDEFINE a variable or macro */
1678 #else
1679     { "undcl",       XXNOTAV, CM_INV },
1680     { "undeclare",   XXNOTAV, CM_INV },
1681     { "undefine",    XXNOTAV, CM_INV },
1682 #endif /* NOSPL */
1683
1684 #ifdef NEWFTP
1685     { "user",        XXUSER,  CM_INV }, /* (FTP) USER */
1686 #endif /* NEWFTP */
1687
1688     { "version",     XXVER, 0 },        /* VERSION-number display */
1689
1690 #ifdef OS2
1691     { "viewonly",    XXVIEW, CM_LOC },  /* VIEWONLY Terminal Mode */
1692 #endif /* OS2 */
1693
1694     { "void",        XXVOID, 0 },       /* VOID */
1695
1696 #ifndef NOSPL
1697     { "wait",        XXWAI, 0 },        /* WAIT */
1698 #else
1699     { "wait",        XXNOTAV, CM_INV },
1700 #endif /* NOSPL */
1701
1702     { "wermit",      XXKERMI, CM_INV },
1703
1704 #ifndef NOXFER
1705     { "where",       XXWHERE, 0 },      /* WHERE (did my file go?) */
1706 #endif /* NOXFER */
1707
1708 #ifndef NOSPL
1709     { "while",       XXWHI, 0 },        /* WHILE loop */
1710 #else
1711     { "while",       XXNOTAV, CM_INV },
1712 #endif /* NOSPL */
1713
1714 #ifndef OS2
1715 #ifndef MAC
1716 #ifndef NOFRILLS
1717     { "who",         XXWHO, CM_PSH },   /* WHO's logged in? */
1718 #endif /* NOFRILLS */
1719 #endif /* MAC */
1720 #endif /* OS2 */
1721
1722 #ifndef NOHELP
1723     { "wildcards",   XXWILD,CM_INV|CM_HLP }, /* Wildcard syntax */
1724 #endif /* NOHELP */
1725
1726 #ifndef NOSPL
1727     { "wr",          XXWRI, CM_INV|CM_ABR },
1728     { "wri",         XXWRI, CM_INV|CM_ABR },
1729     { "writ",        XXWRI, CM_INV|CM_ABR },
1730     { "write",       XXWRI, 0 },        /* WRITE characters to a file */
1731     { "write-line",  XXWRL, CM_INV },   /* WRITE a line to a file */
1732     { "writeln",     XXWRL, CM_INV },   /* Pascalisch synonym for write-line */
1733 #else
1734     { "wr",          XXNOTAV, CM_INV },
1735     { "wri",         XXNOTAV, CM_INV },
1736     { "writ",        XXNOTAV, CM_INV },
1737     { "write",       XXNOTAV, CM_INV },
1738     { "write-line",  XXNOTAV, CM_INV },
1739     { "writeln",     XXNOTAV, CM_INV },
1740 #endif /* NOSPL */
1741
1742 #ifndef NOFRILLS
1743     { "xecho",       XXXECH,0 },        /* XECHO */
1744 #endif /* NOFRILLS */
1745
1746 #ifndef NOSPL
1747     { "xif",         XXIFX, CM_INV },   /* Extended IF command (obsolete) */
1748 #else
1749     { "xif",         XXNOTAV, CM_INV },
1750 #endif /* NOSPL */
1751
1752 #ifndef NOCSETS
1753     { "xlate",       XXXLA, CM_INV },   /* Synonym for TRANSLATE */
1754 #else
1755     { "xlate",       XXNOTAV, CM_INV },
1756 #endif /* NOCSETS */
1757
1758 #ifndef NOXMIT
1759     { "xmit",        XXTRA, CM_INV },   /* Synonym for TRANSMIT */
1760 #else
1761     { "xmit",        XXNOTAV, CM_INV },
1762 #endif /* NOXMIT */
1763
1764 #ifndef OS2
1765 #ifndef NOJC
1766     { "z",           XXSUS, CM_INV|CM_PSH }, /* Synonym for SUSPEND */
1767 #else
1768     { "z",           XXNOTAV, CM_INV|CM_PSH },
1769 #endif /* NOJC */
1770 #endif /* OS2 */
1771
1772 #ifndef NOSPL
1773     { "{",           XXMACRO, CM_INV }, /* Immediate macro */
1774 #endif /* NOSPL */
1775     { "", 0, 0 }
1776 };
1777 int ncmd = (sizeof(cmdtab) / sizeof(struct keytab)) - 1;
1778
1779 /* NOTE: Tokens must also be entered above into cmdtab[]. */
1780
1781 char toktab[] = {
1782 #ifndef NOPUSH
1783     '!',                                /* Shell escape */
1784 #endif /* NOPUSH */
1785     '#',                                /* Comment */
1786 #ifndef NOSPL
1787     '(',                                /* S-Expression */
1788     '.',                                /* Assignment */
1789 #endif /* NOSPL */
1790     ';',                                /* Comment */
1791 #ifndef NOSPL
1792     ':',                                /* Label */
1793 #endif /* NOSPL */
1794 #ifndef NOPUSH
1795 #ifdef CK_REDIR
1796     '<',                                /* REDIRECT */
1797 #endif /* CK_REDIR */
1798     '@',                                /* DCL escape */
1799 #endif /* NOPUSH */
1800 #ifdef CK_RECALL
1801     '^',                                /* Command recall */
1802 #endif /* CK_RECALL */
1803 #ifndef NOSPL
1804     '{',                                /* Immediate macro */
1805 #endif /* NOSPL */
1806     '\0'                                /* End of this string */
1807 };
1808 int xxdot = 0;                          /* Used with "." token */
1809
1810 struct keytab yesno[] = {               /* Yes/No keyword table */
1811     { "no",    0, 0 },
1812     { "ok",    1, 0 },
1813     { "yes",   1, 0 }
1814 };
1815 int nyesno = (sizeof(yesno) / sizeof(struct keytab));
1816
1817 /* Save keyword table */
1818
1819 struct keytab savtab[] = {
1820 #ifdef OS2
1821     { "command",  XSCMD, 0 },
1822 #else
1823 #ifdef CK_RECALL
1824     { "command",  XSCMD, 0 },
1825 #endif /* CK_RECALL */
1826 #endif /* OS2 */
1827 #ifndef NOSETKEY
1828     { "keymap",   XSKEY, 0 },
1829 #endif /* NOSETKEY */
1830 #ifdef OS2
1831     { "terminal", XSTERM, 0 },
1832 #endif /* OS2 */
1833     { "", 0, 0 }
1834 };
1835 int nsav = (sizeof(savtab) / sizeof(struct keytab)) - 1;
1836
1837 /* Parameter keyword table */
1838
1839 struct keytab prmtab[] = {
1840     { "alarm",            XYALRM,  0 },
1841 #ifdef COMMENT                          /* SET ANSWER not implemented yet */
1842 #ifndef NODIAL
1843     { "answer",           XYANSWER,0 },
1844 #endif /* NODIAL */
1845 #endif /* COMMENT */
1846     { "ask-timer",        XYTIMER, 0 },
1847 #ifndef NOXFER
1848     { "attributes",       XYATTR,  0 },
1849 #endif /* NOXFER */
1850 #ifdef CK_AUTHENTICATION
1851     { "authentication",   XYAUTH,  0 },
1852 #else  /* CK_AUTHENTICATION */
1853 #ifdef CK_SSL
1854     { "authentication",   XYAUTH,  0 },
1855 #endif /* CK_SSL */
1856 #endif /* CK_AUTHENTICATION */
1857     { "b",                XYBACK,  CM_INV|CM_ABR|CM_PSH },
1858     { "ba",               XYBACK,  CM_INV|CM_ABR|CM_PSH },
1859 #ifdef VMS
1860     { "background",       XYBACK,  CM_INV|CM_PSH },
1861     { "batch",            XYBACK,  CM_PSH },
1862 #else
1863     { "background",       XYBACK,  CM_PSH },
1864     { "batch",            XYBACK,  CM_INV|CM_PSH },
1865 #endif /* VMS */
1866 #ifndef NOLOCAL
1867     { "baud",             XYSPEE,  CM_INV|CM_LOC },
1868 #endif /* NOLOCAL */
1869     { "bell",             XYBELL,  0 },
1870 #ifndef NOXFER
1871     { "block-check",      XYCHKT,  0 },
1872 #endif /* NOXFER */
1873 #ifdef OS2
1874 #ifdef BPRINT
1875     { "bprinter",         XYBDCP,  CM_INV },
1876 #endif /* BPRINT */
1877 #endif /*  OS2 */
1878 #ifdef BROWSER
1879     { "browser",          XYBROWSE,CM_PSH|CM_LOC },
1880 #endif /* BROWSER */
1881 #ifndef NOXFER
1882 #ifdef DYNAMIC
1883     { "buffers",          XYBUF,   0 },
1884 #endif /* DYNAMIC */
1885 #endif /* NOXFER */
1886 #ifndef NOLOCAL
1887 #ifndef MAC
1888     { "carrier-watch",    XYCARR,  CM_LOC },
1889 #endif /* MAC */
1890 #endif /* NOLOCAL */
1891 #ifndef NOSPL
1892     { "case",             XYCASE,  0 },
1893 #endif /* NOSPL */
1894     { "cd",               XYCD,    0 },
1895 #ifndef NOXFER
1896     { "cl",               XYCLEAR, CM_INV|CM_ABR },
1897     { "cle",              XYCLEAR, CM_INV|CM_ABR },
1898     { "clea",             XYCLEAR, CM_INV|CM_ABR },
1899     { "clear",            XYCLEAR, CM_INV|CM_ABR },
1900     { "clear-channel",    XYCLEAR, 0 },
1901     { "clearchannel",     XYCLEAR, CM_INV },
1902 #endif /* NOXFER */
1903 #ifndef NOLOCAL
1904     { "close-on-disconnect", XYDISC, CM_INV|CM_LOC },
1905 #endif /* NOLOCAL */
1906     { "cmd",              XYCMD,   CM_INV },
1907     { "command",          XYCMD,   0 },
1908 #ifdef CK_SPEED
1909     { "con",              XYQCTL,  CM_INV|CM_ABR },
1910 #endif /* CK_SPEED */
1911     { "console",          XYCMD,   CM_INV },
1912 #ifdef CK_SPEED
1913     { "control-character",XYQCTL,  0 },
1914 #endif /* CK_SPEED */
1915 #ifndef NOSPL
1916     { "count",            XYCOUN,  0 },
1917 #endif /* NOSPL */
1918 #ifndef NOXFER
1919     { "d",                XYDELA,  CM_INV|CM_ABR },
1920     { "de",               XYDELA,  CM_INV|CM_ABR },
1921 #endif /* NOXFER */
1922     { "debug",            XYDEBU,  0 },
1923 #ifdef VMS
1924     { "default",          XYDFLT,  0 },
1925 #else
1926 #ifndef MAC
1927     { "default",          XYDFLT,  CM_INV },
1928 #endif /* MAC */
1929 #endif /* VMS */
1930 #ifndef NOXFER
1931     { "delay",            XYDELA,  0 },
1932     { "destination",      XYDEST,  0 },
1933 #endif /* NOXFER */
1934 #ifndef NODIAL
1935     { "di",               XYDIAL,  CM_INV|CM_ABR|CM_LOC },
1936     { "dia",              XYDIAL,  CM_INV|CM_ABR|CM_LOC },
1937     { "dial",             XYDIAL,  CM_LOC },
1938 #endif /* NODIAL */
1939 #ifdef OS2
1940     { "dialer",           XYDLR,   CM_INV },
1941 #endif /* OS2 */
1942 #ifndef NOLOCAL
1943     { "disconnect",       XYDISC,  CM_LOC },
1944     { "duplex",           XYDUPL,  CM_LOC },
1945 #endif /* NOLOCAL */
1946 #ifndef NOPUSH
1947 #ifndef NOFRILLS
1948     { "editor",           XYEDIT,  CM_PSH },
1949 #endif /*  NOFRILLS */
1950 #endif /* NOPUSH */
1951 #ifdef CK_CTRLZ
1952     { "eof",              XYEOF,   CM_INV },
1953 #endif /* CK_CTRLZ */
1954 #ifndef NOLOCAL
1955     { "escape-character", XYESC,   CM_LOC },
1956 #endif /* NOLOCAL */
1957 #ifndef NOSPL
1958     { "evaluate",         XYEVAL,  CM_INV },
1959 #endif /* NOSPL */
1960     { "exit",             XYEXIT,  0 },
1961 #ifndef NOXFER
1962     { "f-ack-bug",        XYFACKB, CM_INV },
1963     { "f-ack-path",       XYFACKP, CM_INV },
1964 #endif /* NOXFER */
1965     { "file",             XYFILE,  0 },
1966     { "fl",               XYFLOW,  CM_INV|CM_ABR },
1967 #ifndef NOSPL
1968     { "flag",             XYFLAG,  0 },
1969 #endif /* NOSPL */
1970 #ifdef TCPSOCKET
1971 #ifndef SYSFTP
1972 #ifndef NOFTP
1973     { "ft",               XYFTPX,  CM_INV|CM_ABR },
1974     { "ftp",              XYFTPX,  0 },
1975 #endif /* NOFTP */
1976 #endif /* SYSFTP */
1977 #endif /* TCPSOCKET */
1978 #ifdef BROWSER
1979     { "ftp-client",       XYFTP,   CM_PSH },
1980 #endif /* BROWSER */
1981     { "flow-control",     XYFLOW,  0 },
1982 #ifndef NOSPL
1983     { "function",         XYFUNC,  0 },
1984 #endif /* NOSPL */
1985 #ifdef NEWFTP
1986     { "get-put-remote",   XYGPR,   0 },
1987 #endif /* NEWFTP */
1988 #ifdef KUI
1989     { "gui",              XYGUI,   0 },
1990 #endif /* KUI */
1991     { "handshake",        XYHAND,  0 },
1992     { "hints",            XYHINTS, 0 },
1993 #ifdef NETCONN
1994     { "host",             XYHOST,  CM_LOC },
1995 #endif /* NETCONN */
1996 #ifndef NOSPL
1997     { "i",                XYINPU,  CM_INV|CM_ABR },
1998 #endif /* NOSPL */
1999 #ifdef IKSD
2000     { "iks",              XYIKS,   0 },
2001 #else
2002     { "iks",              XYIKS,   CM_INV },
2003 #endif /* IKSD */
2004 #ifndef NOSPL
2005     { "in",               XYINPU,  CM_INV|CM_ABR },
2006 #endif /* NOSPL */
2007 #ifndef NOXFER
2008     { "incomplete",       XYIFD,   CM_INV },
2009 #endif /* NOXFER */
2010 #ifndef NOSPL
2011     { "input",            XYINPU,  0 },
2012 #endif /* NOSPL */
2013 #ifndef NOSETKEY
2014     { "key",              XYKEY,   0 },
2015 #endif /* NOSETKEY */
2016     { "l",                XYLINE,  CM_INV|CM_ABR },
2017 #ifndef NOCSETS
2018     { "language",         XYLANG,  0 },
2019 #endif /* NOCSETS */
2020 #ifndef NOLOCAL
2021     { "line",             XYLINE,  CM_LOC },
2022     { "local-echo",       XYLCLE,  CM_INV|CM_LOC },
2023 #endif /* NOLOCAL */
2024 #ifdef LOCUS
2025     { "locus",            XYLOCUS, 0 },
2026 #endif /* LOCUS */
2027 #ifndef NOSPL
2028     { "login",            XYLOGIN, CM_LOC },
2029 #endif /* NOSPL */
2030 #ifndef NOSPL
2031     { "macro",            XYMACR,  0 },
2032 #endif /* NOSPL */
2033     { "match",            XYMATCH, 0 },
2034 #ifdef COMMENT
2035 #ifdef VMS
2036     { "messages",         XYMSGS,  0 },
2037 #endif /* VMS */
2038 #endif /* COMMENT */
2039 #ifndef NODIAL
2040     { "modem",            XYMODM,  CM_LOC },
2041 #endif /* NODIAL */
2042 #ifndef NOLOCAL
2043 #ifdef OS2MOUSE
2044     { "mouse",            XYMOUSE, 0 },
2045 #endif /* OS2MOUSE */
2046 #endif /* NOLOCAL */
2047 #ifdef OS2
2048     { "mskermit",         XYMSK,   0 },
2049 #endif /* OS2 */
2050 #ifdef NETCONN
2051     { "network",          XYNET,   CM_LOC },
2052 #endif /* NETCONN */
2053 #ifndef NOSPL
2054     { "output",           XYOUTP,  0 },
2055 #endif /* NOSPL */
2056     { "options",          XYOPTS,  0 },
2057     { "pause",            XYSLEEP, CM_INV },
2058 #ifdef ANYX25
2059 #ifndef IBMX25
2060     { "pad",              XYPAD,   CM_LOC },
2061 #endif /* IBMX25 */
2062 #endif /* ANYX25 */
2063     { "parity",           XYPARI,  0 },
2064 #ifndef NOLOCAL
2065 #ifdef OS2
2066     { "port",             XYLINE,  CM_LOC },
2067 #else
2068     { "port",             XYLINE,  CM_INV|CM_LOC },
2069 #endif /* OS2 */
2070 #endif /* NOLOCAL */
2071 #ifndef NOFRILLS
2072     { "pr",               XYPROM,  CM_INV|CM_ABR },
2073     { "printer",          XYPRTR,  0 },
2074 #endif /* NOFRILLS */
2075 #ifdef OS2
2076     { "priority",         XYPRTY,  0 },
2077 #endif /* OS2 */
2078 #ifdef CK_SPEED
2079     { "prefixing",        XYPREFIX, 0 },
2080 #endif /* CK_SPEED */
2081 #ifndef NOFRILLS
2082     { "prompt",           XYPROM,  0 },
2083 #endif /* NOFRILLS */
2084 #ifndef NOXFER
2085     { "protocol",         XYPROTO, 0 },
2086 #endif /* NOXFER */
2087     { "q",                XYQUIE,  CM_INV|CM_ABR },
2088 #ifndef NOXFER
2089     { "q8flag",           XYQ8FLG, CM_INV },
2090 #endif /* NOXFER */
2091 #ifdef QNX
2092     { "qnx-port-lock",    XYQNXPL, 0 },
2093 #else
2094     { "qnx-port-lock",    XYQNXPL, CM_INV },
2095 #endif /* QNX */
2096     { "quiet",            XYQUIE,  0 },
2097 #ifndef NOXFER
2098     { "rec",              XYRECV,  CM_INV|CM_ABR },
2099     { "receive",          XYRECV,  0 },
2100     { "recv",             XYRECV,  CM_INV },
2101 #endif /* NOXFER */
2102     { "reliable",         XYRELY,  0 },
2103 #ifndef NOXFER
2104     { "repeat",           XYREPT,  0 },
2105     { "retry-limit",      XYRETR,  0 },
2106 #endif /* NOXFER */
2107 #ifdef CKROOT
2108     { "root",             XYROOT,  0 },
2109 #endif /* CKROOT */
2110 #ifndef NOSCRIPT
2111     { "script",           XYSCRI,  CM_LOC },
2112 #endif /* NOSCRIPT */
2113 #ifndef NOXFER
2114     { "send",             XYSEND,  0 },
2115 #ifndef NOLOCAL
2116 #ifndef NOSERVER
2117     { "ser",              XYSERV,  CM_INV|CM_ABR },
2118 #endif /* NOSERVER */
2119 #endif /* NOXFER */
2120     { "serial",           XYSERIAL,CM_LOC },
2121 #endif /* NOLOCAL */
2122 #ifndef NOSERVER
2123     { "server",           XYSERV,  0 },
2124 #endif /* NOSERVER */
2125 #ifdef SESLIMIT
2126 #ifndef NOLOCAL
2127     { "session-l",        XYSESS,  CM_INV|CM_ABR },
2128 #endif /* NOLOCAL */
2129     { "session-limit",    XYLIMIT, CM_INV|CM_LOC }, /* Session Limit */
2130 #endif /* SESLIMIT */
2131
2132 #ifndef NOLOCAL
2133     { "session-log",      XYSESS,  CM_LOC },
2134 #endif /* NOLOCAL */
2135
2136 #ifndef NOSPL
2137 #ifndef NOSEXP
2138     { "sexpression",      XYSEXP,  CM_INV },
2139 #endif /* NOSEXP */
2140 #endif /* NOSPL */
2141
2142     { "sleep",            XYSLEEP, 0 },
2143
2144 #ifndef NOLOCAL
2145     { "speed",            XYSPEE,  CM_LOC },
2146 #endif /* NOLOCAL */
2147
2148 #ifdef ANYSSH
2149     { "ssh",              XYSSH,   0 },
2150 #endif /* ANYSSH */
2151
2152 #ifndef NOSPL
2153     { "startup-file",     XYSTARTUP, CM_INV },
2154 #endif /* NOSPL */
2155
2156 #ifndef NOLOCAL
2157 #ifdef HWPARITY
2158     { "stop-bits",        XYSTOP, CM_LOC },
2159 #else
2160 #ifdef TN_COMPORT
2161     { "stop-bits",        XYSTOP, CM_LOC },
2162 #endif /* TN_COMPORT */
2163 #endif /* HWPARITY */
2164 #endif /* NOLOCAL */
2165
2166 #ifndef NOXFER
2167 #ifdef STREAMING
2168     { "streaming",        XYSTREAM, 0 },
2169 #endif /* STREAMING */
2170 #endif /* NOXFER */
2171
2172 #ifndef NOJC
2173     { "suspend",          XYSUSP,  CM_PSH },
2174 #endif /* NOJC */
2175 #ifdef CKSYSLOG
2176     { "syslog",           XYSYSL,  CM_INV },
2177 #endif /* CKSYSLOG */
2178     { "take",             XYTAKE,  0 },
2179
2180 #ifdef CK_TAPI
2181     { "tapi",             XYTAPI,  CM_LOC },
2182 #endif /* CK_TAPI */
2183
2184 #ifndef NOTCPOPTS
2185 #ifdef TCPSOCKET
2186     { "tcp",              XYTCP,   CM_LOC },
2187 #endif /* TCPSOCKET */
2188 #endif /* NOTCPOPTS */
2189
2190 #ifdef TNCODE
2191     { "tel",              XYTEL,   CM_INV|CM_ABR },
2192     { "telnet",           XYTEL,   0 },
2193     { "telopt",           XYTELOP, 0 },
2194 #endif /* TNCODE */
2195
2196 #ifndef NOSPL
2197     { "temp-directory",   XYTMPDIR,0 },
2198 #endif /* NOSPL */
2199
2200 #ifndef NOLOCAL
2201     { "terminal",         XYTERM,  CM_LOC },
2202 #endif /* NOLOCAL */
2203
2204 #ifdef OS2
2205     { "title",            XYTITLE, CM_LOC },
2206 #endif /* OS2 */
2207 #ifdef TLOG
2208     { "transaction-log",  XYTLOG,  0 },
2209 #endif /* TLOG */
2210 #ifndef NOXFER
2211     { "transfer",         XYXFER,  0 },
2212 #endif /* NOXFER */
2213 #ifndef NOXMIT
2214     { "transmit",         XYXMIT,  0 },
2215 #endif /* NOXMIT */
2216 #ifndef NOXFER
2217 #ifndef NOCSETS
2218     { "unknown-char-set", XYUNCS,  0 },
2219 #endif /* NOCSETS */
2220 #endif /* NOXFER */
2221     { "wait",             XYSLEEP, CM_INV },
2222 #ifndef NOPUSH
2223 #ifdef UNIX
2224     { "wildcard-expansion", XYWILD, 0 },
2225 #endif /* UNIX */
2226 #endif /* NOPUSH */
2227 #ifdef NT
2228     { "w",                XYWIND,  CM_INV|CM_ABR },
2229     { "wi",               XYWIND,  CM_INV|CM_ABR },
2230     { "win",              XYWIND,  CM_INV|CM_ABR },
2231 #endif /* NT */
2232     { "window-size",      XYWIND,  0 },
2233 #ifdef NT
2234     { "win95",            XYWIN95, 0 },
2235 #endif /* NT */
2236 #ifdef ANYX25
2237     { "x.25",             XYX25,   CM_LOC },
2238     { "x25",              XYX25,   CM_INV|CM_LOC },
2239 #endif /* ANYX25 */
2240     { "xfer",             XYXFER,  CM_INV },
2241 #ifndef NOXMIT
2242     { "xmit",             XYXMIT,  CM_INV },
2243 #endif /* NOXMIT */
2244     { "", 0, 0 }
2245 };
2246 int nprm = (sizeof(prmtab) / sizeof(struct keytab)) - 1; /* How many */
2247
2248 struct keytab scntab[] = {              /* Screen commands */
2249     { "clear",   SCN_CLR, 0 },
2250     { "cleol",   SCN_CLE, 0 },
2251     { "move-to", SCN_MOV, 0 }
2252 };
2253 int nscntab = (sizeof(scntab) / sizeof(struct keytab)); /* How many */
2254
2255 #ifdef ANYSSH                           /* SSH command table */
2256 #ifdef SSHBUILTIN
2257 int    ssh_pf_lcl_n = 0,
2258        ssh_pf_rmt_n = 0;
2259 struct ssh_pf ssh_pf_lcl[32] = { 0, NULL, 0 }; /* SSH Port Forwarding */
2260 struct ssh_pf ssh_pf_rmt[32] = { 0, NULL, 0 }; /* structs... */
2261 extern char * ssh_hst, * ssh_cmd, * ssh_prt;
2262 extern int    ssh_ver,   ssh_xfw;
2263 char * ssh_tmpuid = NULL, *ssh_tmpcmd = NULL, *ssh_tmpport = NULL,
2264      * ssh_tmpstr = NULL;
2265
2266 int
2267  sshk_type = SSHKT_2D,                  /* SSH KEY CREATE /TYPE:x */
2268  sshk_bits = 1024,                      /* SSH KEY CREATE /BITS:n */
2269  sshk_din  = SKDF_OSSH,                 /* SSH KEY DISPLAY /IN-FORMAT: */
2270  sshk_dout = SKDF_OSSH;                 /* SSH KEY DISPLAY /OUT-FORMAT: */
2271
2272 char
2273  * sshk1_comment = NULL,                /* SSH V1 COMMENT */
2274  * sshkp_old = NULL,                    /* Old key passphrase */
2275  * sshkp_new = NULL,                    /* New key passphrase */
2276  * sshkc_pass = NULL,                   /* KEY CREATE /PASS:xxx */
2277  * sshkc_comm = NULL,                   /* KEY CREATE /V1-RSA-COMMENT:xxx */
2278  * sshd_file = NULL,                    /* DISPLAY file */
2279  * sshk_file = NULL;                    /* SSH CREATE KEY file */
2280
2281 static struct keytab sshclr[] = {
2282     { "local-port-forward",  SSHC_LPF, 0 },
2283     { "remote-port-forward", SSHC_RPF, 0 },
2284     { "", 0, 0 }
2285 };
2286 static int nsshclr = (sizeof(sshclr) / sizeof(struct keytab)) - 1;
2287
2288 struct keytab sshopnsw[] = {
2289     { "/command",        SSHSW_CMD, CM_ARG },
2290     { "/password",       SSHSW_PWD, CM_ARG },
2291     { "/subsystem",      SSHSW_SUB, CM_ARG },
2292     { "/user",           SSHSW_USR, CM_ARG },
2293     { "/version",        SSHSW_VER, CM_ARG },
2294     { "/x11-forwarding", SSHSW_X11, CM_ARG },
2295     { "", 0, 0 }
2296 };
2297 int nsshopnsw = (sizeof(sshopnsw) / sizeof(struct keytab)) - 1;
2298
2299 static struct keytab sshkwtab[] = {
2300     { "add",                 XSSH_ADD, 0 },
2301     { "agent",               XSSH_AGT, 0 },
2302     { "clear",               XSSH_CLR, 0 },
2303     { "forward-local-port",  XSSH_FLP, CM_INV },
2304     { "forward-remote-port", XSSH_FRP, CM_INV },
2305     { "key",                 XSSH_KEY, 0 },
2306     { "open",                XSSH_OPN, 0 },
2307     { "v2",                  XSSH_V2,  0 },
2308     { "", 0, 0 }
2309 };
2310 static int nsshcmd = (sizeof(sshkwtab) / sizeof(struct keytab)) - 1;
2311
2312 static struct keytab ssh2tab[] = {
2313     { "rekey", XSSH2_RKE, 0 },
2314     { "", 0, 0 }
2315 };
2316 static int nssh2tab = (sizeof(ssh2tab) / sizeof(struct keytab));
2317
2318 static struct keytab addfwd[] = {       /* SET SSH ADD command table */
2319     { "local-port-forward",  SSHF_LCL, 0 },
2320     { "remote-port-forward", SSHF_RMT, 0 },
2321     { "", 0, 0 }
2322 };
2323 static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
2324
2325 static struct keytab sshagent[] = {     /* SET SSH AGENT command table */
2326     { "add",    SSHA_ADD, 0 },
2327     { "delete", SSHA_DEL, 0 },
2328     { "list",   SSHA_LST, 0 },
2329     { "", 0, 0 }
2330 };
2331 static int nsshagent = (sizeof(sshagent) / sizeof(struct keytab)) - 1;
2332
2333 static struct keytab sshagtsw[] = {     /* SET SSH AGENT LIST switch table */
2334     { "/fingerprint", SSHASW_FP, 0 },
2335     { "", 0, 0 }
2336 };
2337 static int nsshagtsw = (sizeof(sshagtsw) / sizeof(struct keytab)) - 1;
2338
2339 static struct keytab sshkey[] = {       /* SET SSH KEY command table */
2340     { "change-passphrase",  SSHK_PASS, 0 },
2341     { "create",             SSHK_CREA, 0 },
2342     { "display",            SSHK_DISP, 0 },
2343     { "v1",                 SSHK_V1,   0 },
2344     { "", 0, 0 }
2345 };
2346 static int nsshkey = (sizeof(sshkey) / sizeof(struct keytab)) - 1;
2347
2348 static struct keytab sshkv1[] = {       /* SET SSH KEY V1 command table */
2349     { "set-comment",  1, 0 }
2350 };
2351
2352 static struct keytab sshkpsw[] = {      /* SET SSH KEY PASSPHRASE table */
2353     { "/new-passphrase",  2, CM_ARG },
2354     { "/old-passphrase",  1, CM_ARG }
2355 };
2356
2357 static struct keytab sshkcrea[] = {     /* SSH KEY CREATE table */
2358     { "/bits",           SSHKC_BI, CM_ARG },
2359     { "/passphrase",     SSHKC_PP, CM_ARG },
2360     { "/type",           SSHKC_TY, CM_ARG },
2361     { "/v1-rsa-comment", SSHKC_1R, CM_ARG }
2362 };
2363 static int nsshkcrea = (sizeof(sshkcrea) / sizeof(struct keytab));
2364
2365 static struct keytab sshkcty[] = {      /* SSH KEY CREATE /TYPE:xxx */
2366     { "srp",    SSHKT_SRP, 0 },
2367     { "v1-rsa", SSHKT_1R, 0 },
2368     { "v2-dsa", SSHKT_2D, 0 },
2369     { "v2-rsa", SSHKT_2R, 0 }
2370 };
2371 static int nsshkcty = (sizeof(sshkcty) / sizeof(struct keytab));
2372
2373 static struct keytab sshdswi[] = {      /* SET SSH KEY DISPLAY /switches */
2374     { "/format", SSHKD_OUT, CM_ARG }
2375 };
2376 static int nsshdswi = (sizeof(sshdswi) / sizeof(struct keytab));
2377
2378 #ifdef COMMENT
2379 static struct keytab sshdifmt[] = {     /* SSH KEY DISPLAY /IN-FORMAT: */
2380     { "openssh", SKDF_OSSH, 0 },
2381     { "ssh.com", SKDF_SSHC, 0 }
2382 };
2383 static int nsshdifmt = (sizeof(sshdifmt) / sizeof(struct keytab));
2384 #endif /* COMMENT */
2385
2386 static struct keytab sshdofmt[] = {     /* SSH KEY DISPLAY /IN-FORMAT: */
2387     { "fingerprint", SKDF_FING, 0 },
2388     { "ietf",        SKDF_IETF, 0 },
2389     { "openssh",     SKDF_OSSH, 0 },
2390     { "ssh.com",     SKDF_SSHC, 0 }
2391 };
2392 static int nsshdofmt = (sizeof(sshdofmt) / sizeof(struct keytab));
2393
2394 static struct keytab sshkermit[] = { /* SKERMIT */
2395     { "open",       SKRM_OPN, 0 }
2396 };
2397 static int nsshkermit = (sizeof(sshkermit) / sizeof(struct keytab));
2398
2399 struct keytab sshkrmopnsw[] = {
2400     { "/password",       SSHSW_PWD, CM_ARG },
2401     { "/user",           SSHSW_USR, CM_ARG },
2402     { "/version",        SSHSW_VER, CM_ARG },
2403     { "", 0, 0 }
2404 };
2405 int nsshkrmopnsw = (sizeof(sshkrmopnsw) / sizeof(struct keytab)) - 1;
2406 #endif /* SSHBUILTIN */
2407
2408 #ifdef SFTP_BUILTIN
2409 static struct keytab sftpkwtab[] = {    /* SFTP */
2410     {  "cd",        SFTP_CD,    0 },
2411     {  "chgrp",     SFTP_CHGRP, 0 },
2412     {  "chmod",     SFTP_CHMOD, 0 },
2413     {  "chown",     SFTP_CHOWN, 0 },
2414     {  "delete",    SFTP_RM,    0 },
2415     {  "dir",       SFTP_DIR,   0 },
2416     {  "get",       SFTP_GET,   0 },
2417     {  "mkdir",     SFTP_MKDIR, 0 },
2418     {  "open",      SFTP_OPN,   0 },
2419     {  "put",       SFTP_PUT,   0 },
2420     {  "pwd",       SFTP_PWD,   0 },
2421     {  "rename",    SFTP_REN,   0 },
2422     {  "rm",        SFTP_RM,    CM_INV },
2423     {  "rmdir",     SFTP_RMDIR, 0 },
2424     {  "symlink",   SFTP_LINK,  0 },
2425     {  "version",   SFTP_VER,   0 }
2426 };
2427 static int nsftpkwtab = (sizeof(sftpkwtab) / sizeof(struct keytab));
2428 #endif /* SFTP_BUILTIN */
2429 #endif /* ANYSSH */
2430
2431 #ifdef NETCONN
2432 struct keytab netkey[] = {              /* SET NETWORK table */
2433     { "directory", XYNET_D,  0 },
2434     { "type",      XYNET_T,  0 }
2435 };
2436 int nnetkey = (sizeof(netkey) / sizeof(struct keytab));
2437
2438 struct keytab netcmd[] = {
2439 /*
2440   These are the network types.
2441 */
2442 #ifdef NETCMD
2443     { "command",       NET_CMD,  CM_INV }, /* Command */
2444 #endif /* NETCMD */
2445
2446 #ifdef DECNET                           /* DECnet / PATHWORKS */
2447     { "decnet",        NET_DEC,  0 },
2448 #endif /* DECNET */
2449
2450 #ifdef NETDLL
2451     { "dll",           NET_DLL,  CM_INV }, /* DLL to be loaded */
2452 #endif /* NETDLL */
2453
2454 #ifdef NETFILE
2455     { "file",           NET_FILE, CM_INV }, /* FILE (real crude) */
2456 #endif /* NETFILE */
2457
2458 #ifdef NPIPE                            /* Named Pipes */
2459     { "named-pipe",     NET_PIPE,  0 },
2460 #endif /* NPIPE */
2461
2462 #ifdef CK_NETBIOS
2463     { "netbios",        NET_BIOS,  0 }, /* NETBIOS */
2464 #endif /* CK_NETBIOS */
2465
2466 #ifdef DECNET                           /* DECnet / PATHWORKS (alias) */
2467     { "pathworks",     NET_DEC,  CM_INV },
2468 #endif /* DECNET */
2469
2470 #ifdef NETCMD
2471     { "pipe",          NET_CMD,  0 },   /* Pipe */
2472 #endif /* NETCMD */
2473
2474 #ifdef NETPTY
2475     { "pseudoterminal",NET_PTY, 0 },    /* Pseudoterminal */
2476 #endif /* NETPTY */
2477
2478 #ifdef NETPTY
2479     { "pty",          NET_PTY,  CM_INV }, /* Inv syn for pseudoterm */
2480 #endif /* NETPTY */
2481
2482 #ifdef SSHBUILTIN
2483     { "ssh",          NET_SSH,  0 },
2484 #endif /* SSHBUILTIN */
2485
2486 #ifdef SUPERLAT
2487     { "superlat",     NET_SLAT, 0 },    /* Meridian Technologies' SuperLAT */
2488 #endif /* SUPERLAT */
2489
2490 #ifdef TCPSOCKET                        /* TCP/IP sockets library */
2491     { "tcp/ip",       NET_TCPB, 0 },
2492 #endif /* TCPSOCKET */
2493 #ifdef SUPERLAT
2494     { "tes32",        NET_SLAT, 0 },    /* Emulux TES32 */
2495 #endif /* SUPERLAT */
2496 #ifdef ANYX25                           /* X.25 */
2497 #ifdef SUNX25
2498     { "x",            NET_SX25, CM_INV|CM_ABR },
2499     { "x.25",         NET_SX25, 0 },
2500     { "x25",          NET_SX25, CM_INV },
2501 #else
2502 #ifdef STRATUSX25
2503     { "x",            NET_VX25, CM_INV|CM_ABR },
2504     { "x.25",         NET_VX25, 0 },
2505     { "x25",          NET_VX25, CM_INV },
2506 #endif /* STRATUSX25 */
2507 #endif /* SUNX25 */
2508 #ifdef IBMX25
2509     { "x",            NET_IX25, CM_INV|CM_ABR },
2510     { "x.25",         NET_IX25, CM_INV },
2511     { "x25",          NET_IX25, CM_INV },
2512 #endif /* IBMX25 */
2513 #ifdef HPX25
2514     { "x",            NET_IX25, CM_INV|CM_ABR },
2515     { "x.25",         NET_IX25, 0 },
2516     { "x25",          NET_IX25, CM_INV },
2517 #endif /* HPX25 */
2518 #endif /* ANYX25 */
2519     { "", 0, 0 }
2520 };
2521 int nnets = (sizeof(netcmd) / sizeof(struct keytab));
2522
2523 #ifndef NOTCPOPTS
2524 #ifdef TCPSOCKET
2525
2526 /* TCP options */
2527
2528 struct keytab tcpopt[] = {
2529     { "address",   XYTCP_ADDRESS, 0 },
2530 #ifdef CK_DNS_SRV
2531     { "dns-service-records", XYTCP_DNS_SRV, 0 },
2532 #endif /* CK_DNS_SRV */
2533 #ifdef SO_DONTROUTE
2534     { "dontroute",   XYTCP_DONTROUTE, 0 },
2535 #endif /* SO_DONTROUTE */
2536 #ifndef NOHTTP
2537     { "http-proxy", XYTCP_HTTP_PROXY, 0 },
2538 #endif /* NOHTTP */
2539 #ifdef SO_KEEPALIVE
2540     { "keepalive", XYTCP_KEEPALIVE, 0 },
2541 #endif /* SO_KEEPALIVE */
2542 #ifdef SO_LINGER
2543     { "linger", XYTCP_LINGER, 0 },
2544 #endif /* SO_LINGER */
2545 #ifdef TCP_NODELAY
2546     { "nagle",  XYTCP_NAGLE,    CM_INV },
2547     { "nodelay", XYTCP_NODELAY, 0 },
2548 #endif /* TCP_NODELAY */
2549     { "reverse-dns-lookup", XYTCP_RDNS, 0 },
2550 #ifdef SO_RCVBUF
2551     { "recvbuf", XYTCP_RECVBUF, 0 },
2552 #endif /* SO_RCVBUF */
2553 #ifdef SO_SNDBUF
2554     { "sendbuf", XYTCP_SENDBUF, 0 },
2555 #endif /* SO_SNDBUF */
2556 #ifdef NT
2557 #ifdef CK_SOCKS
2558     { "socks-server", XYTCP_SOCKS_SVR, 0 },
2559 #endif /* CK_SOCKS */
2560 #endif /* NT */
2561 #ifdef VMS
2562 #ifdef DEC_TCPIP
2563     { "ucx-port-bug", XYTCP_UCX, 0 },
2564 #endif /* DEC_TCPIP */
2565 #endif /* VMS */
2566     { "",0,0 }
2567 };
2568 int ntcpopt = (sizeof(tcpopt) / sizeof(struct keytab));
2569 #endif /* TCPSOCKET */
2570 #endif /* NOTCPOPTS */
2571 #endif /* NETCONN */
2572
2573 #ifdef OS2
2574 /* K95 Manual Chapter Table -- Keep these two tables in sync! */
2575
2576 static char * linktbl[] = {             /* Internal links in k95.htm */
2577     "#top",                             /* 00 */
2578     "#what",                            /* 01 */
2579     "#install",                         /* 02 */
2580     "#start",                           /* 03 */
2581     "#dialer",                          /* 04 */
2582     "#entries",                         /* 05 */
2583     "#command",                         /* 06 */
2584     "#terminal",                        /* 07 */
2585     "#transfer",                        /* 08 */
2586     "#hostmode"                         /* 09 */
2587 };
2588
2589 static struct keytab chaptbl[] = {
2590     { "Command-Screen",     6, 0 },
2591     { "Contents",           0, 0 },
2592     { "Dialer-Entries",     5, 0 },
2593     { "File-Transfer",      8, 0 },
2594     { "Getting-Started",    3, 0 },
2595     { "Host-Mode",          9, 0 },
2596     { "Installation",       2, 0 },
2597     { "Terminal-Emulation", 7, 0 },
2598     { "Using-The-Dialer",   4, 0 },
2599     { "What-Is-K95",        1, 0 },
2600     { "",                   0, 0 }
2601 };
2602 static int nchaptbl = (sizeof(chaptbl) / sizeof(struct keytab) - 1);
2603 #endif /* OS2 */
2604
2605 #ifndef NOXFER
2606 /* Remote Command Table */
2607
2608 struct keytab remcmd[] = {
2609 #ifndef NOSPL
2610     { "as",        XZASG, CM_INV|CM_ABR },
2611     { "asg",       XZASG, CM_INV },
2612     { "assign",    XZASG, 0 },
2613 #endif /* NOSPL */
2614     { "cd",        XZCWD, 0 },
2615     { "cdup",      XZCDU, CM_INV },
2616     { "copy",      XZCPY, 0 },
2617     { "cwd",       XZCWD, CM_INV },
2618     { "delete",    XZDEL, 0 },
2619     { "directory", XZDIR, 0 },
2620     { "e",         XZXIT, CM_ABR|CM_INV },
2621     { "erase",     XZDEL, CM_INV },
2622     { "exit",      XZXIT, 0 },
2623     { "help",      XZHLP, 0 },
2624 #ifndef NOPUSH
2625     { "host",      XZHOS, 0 },
2626 #endif /* NOPUSH */
2627 #ifndef NOFRILLS
2628     { "kermit",    XZKER, 0 },
2629     { "l",         XZLGI, CM_ABR|CM_INV },
2630     { "lo",        XZLGI, CM_ABR|CM_INV },
2631     { "log",       XZLGI, CM_ABR|CM_INV },
2632     { "login",     XZLGI, 0 },
2633     { "logout",    XZLGO, 0 },
2634     { "mkdir",     XZMKD, 0 },
2635     { "print",     XZPRI, 0 },
2636 #endif /* NOFRILLS */
2637     { "pwd",       XZPWD, 0 },
2638 #ifndef NOSPL
2639     { "query",     XZQUE, 0 },
2640 #endif /* NOSPL */
2641     { "rename",    XZREN, 0 },
2642     { "rmdir",     XZRMD, 0 },
2643     { "set",       XZSET, 0 },
2644     { "space",     XZSPA, 0 },
2645 #ifndef NOFRILLS
2646     { "type",      XZTYP, 0 },
2647     { "who",       XZWHO, 0 },
2648 #endif /* NOFRILLS */
2649     { "", 0, 0}
2650 };
2651 int nrmt = (sizeof(remcmd) / sizeof(struct keytab)) - 1;
2652 #endif /* NOXFER */
2653
2654 struct keytab logtab[] = {
2655 #ifdef CKLOGDIAL
2656     { "connections",  LOGM, CM_INV },
2657     { "cx",           LOGM, 0 },
2658 #endif /* CKLOGDIAL */
2659 #ifdef DEBUG
2660     { "debugging",    LOGD, 0 },
2661 #endif /* DEBUG */
2662     { "packets",      LOGP, 0 },
2663 #ifndef NOLOCAL
2664     { "session",      LOGS, 0 },
2665 #endif /* NOLOCAL */
2666 #ifdef TLOG
2667     { "transactions", LOGT, 0 },
2668 #endif /* TLOG */
2669     { "", 0, 0 }
2670 };
2671 int nlog = (sizeof(logtab) / sizeof(struct keytab)) - 1;
2672
2673 struct keytab writab[] = {
2674 #ifndef NOSPL
2675     { "append-file",     LOGW, CM_INV },
2676 #endif /* NOSPL */
2677     { "debug-log",       LOGD, 0 },
2678     { "error",           LOGE, 0 },
2679 #ifndef NOSPL
2680     { "file",            LOGW, 0 },
2681 #endif /* NOSPL */
2682     { "packet-log",      LOGP, 0 },
2683     { "screen",          LOGX, 0 },
2684 #ifndef NOLOCAL
2685     { "session-log",     LOGS, 0 },
2686 #endif /* NOLOCAL */
2687     { "sys$output",      LOGX, CM_INV },
2688     { "t",               LOGT, CM_ABR|CM_INV }, /* Because of a typo in */
2689     { "tr",              LOGT, CM_ABR|CM_INV }, /* the book... */
2690     { "tra",             LOGT, CM_ABR|CM_INV },
2691     { "tran",            LOGT, CM_ABR|CM_INV },
2692     { "trans",           LOGT, CM_ABR|CM_INV },
2693     { "transa",          LOGT, CM_ABR|CM_INV },
2694     { "transac",         LOGT, CM_ABR|CM_INV },
2695     { "transact",        LOGT, CM_ABR|CM_INV },
2696     { "transacti",       LOGT, CM_ABR|CM_INV },
2697     { "transactio",      LOGT, CM_ABR|CM_INV },
2698     { "transaction",     LOGT, CM_ABR|CM_INV },
2699     { "transaction-log", LOGT, 0 },
2700     { "transactions",    LOGT, CM_INV }
2701 };
2702 int nwri = (sizeof(writab) / sizeof(struct keytab));
2703
2704 #ifdef COMMENT                          /* INPUT switches not used yet... */
2705 static struct keytab inswtab[] = {
2706 #ifdef COMMENT
2707     { "/assign",       IN_ASG, CM_ARG },
2708 #endif /* COMMENT */
2709     { "/autodownload", IN_ADL, CM_ARG },
2710     { "/case",         IN_CAS, CM_ARG },
2711     { "/echo",         IN_ECH, CM_ARG },
2712     { "/interrupts",   IN_NOI, CM_ARG },
2713     { "/silence",      IN_SIL, CM_ARG },
2714 #ifdef COMMENT
2715     { "/pattern",      IN_PAT, CM_ARG },
2716 #endif /* COMMENT */
2717     { "", 0, 0 }
2718 };
2719 static int ninswtab = (sizeof(inswtab) / sizeof(struct keytab)) - 1;
2720 #endif /* COMMENT */
2721
2722 static struct keytab clrtab[] = {       /* Keywords for CLEAR command */
2723 #ifndef NOSPL
2724     { "alarm",            CLR_ALR,         0 },
2725 #ifdef CK_APC
2726     { "apc",              CLR_APC,         0 },
2727 #endif /* CK_APC */
2728 #ifdef PATTERNS
2729     { "binary-patterns",  CLR_BIN,         0 },
2730 #endif /* PATTERNS */
2731     { "both",             CLR_DEV|CLR_INP, CM_INV },
2732 #endif /* NOSPL */
2733 #ifdef OS2
2734     { "command-screen",   CLR_CMD,         0 },
2735 #endif /* OS2 */
2736 #ifndef NOSPL
2737     { "device",           CLR_DEV,         CM_INV|CM_ABR },
2738     { "device-and-input", CLR_DEV|CLR_INP, 0 },
2739 #endif /* NOSPL */
2740     { "device-buffer",    CLR_DEV,         0 },
2741 #ifndef NODIAL
2742     { "dial-status",      CLR_DIA,       0 },
2743 #endif /* NODIAL */
2744 #ifndef NOSPL
2745     { "input-buffer",     CLR_INP,         0 },
2746 #endif /* NOSPL */
2747     { "keyboard-buffer",  CLR_KBD,         0 },
2748     { "send-list",        CLR_SFL,         0 },
2749 #ifdef OS2
2750     { "scr",              CLR_SCL,         CM_INV|CM_ABR },
2751 #endif /* OS2 */
2752     { "screen",           CLR_SCR,         0 },
2753 #ifdef OS2
2754     { "scrollback",       CLR_SCL,         CM_INV },
2755     { "terminal-screen",  CLR_TRM,         0 },
2756 #endif /* OS2 */
2757 #ifdef PATTERNS
2758     { "text-patterns",    CLR_TXT,         0 },
2759 #endif /* PATTERNS */
2760     { "", 0, 0 }
2761 };
2762 int nclear = (sizeof(clrtab) / sizeof(struct keytab)) - 1;
2763
2764 struct keytab clstab[] = {              /* Keywords for CLOSE command */
2765 #ifndef NOSPL
2766     { "!read",           LOGR, CM_INV },
2767     { "!write",          LOGW, CM_INV },
2768 #ifndef NOPUSH
2769 #endif /* NOPUSH */
2770 #endif /* NOSPL */
2771 #ifndef NOSPL
2772     { "append-file",     LOGW, CM_INV },
2773 #endif /* NOSPL */
2774 #ifndef NOLOCAL
2775     { "connection",      9999, 0 },
2776 #endif /* NOLOCAL */
2777 #ifdef CKLOGDIAL
2778     { "cx-log",          LOGM, 0 },
2779 #endif /* CKLOGDIAL */
2780 #ifdef DEBUG
2781     { "debug-log",       LOGD, 0 },
2782 #endif /* DEBUG */
2783     { "host",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2784     { "line",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2785     { "p",               LOGP, CM_INV|CM_ABR },
2786     { "packet-log",      LOGP, 0 },
2787     { "port",            9999, CM_INV }, /* Synonym for CLOSE CONNECTION */
2788 #ifndef NOSPL
2789     { "read-file",       LOGR, 0 },
2790 #endif /* NOSPL */
2791 #ifndef NOLOCAL
2792     { "session-log",     LOGS, 0 },
2793 #endif /* NOLOCAL */
2794 #ifdef TLOG
2795     { "t",               LOGT, CM_ABR|CM_INV }, /* Because of a typo in */
2796     { "tr",              LOGT, CM_ABR|CM_INV }, /* the book... */
2797     { "tra",             LOGT, CM_ABR|CM_INV },
2798     { "tran",            LOGT, CM_ABR|CM_INV },
2799     { "trans",           LOGT, CM_ABR|CM_INV },
2800     { "transa",          LOGT, CM_ABR|CM_INV },
2801     { "transac",         LOGT, CM_ABR|CM_INV },
2802     { "transact",        LOGT, CM_ABR|CM_INV },
2803     { "transacti",       LOGT, CM_ABR|CM_INV },
2804     { "transactio",      LOGT, CM_ABR|CM_INV },
2805     { "transaction",     LOGT, CM_ABR|CM_INV },
2806     { "transaction-log", LOGT, 0 },
2807     { "transactions",    LOGT, CM_INV },
2808 #endif /* TLOG */
2809 #ifndef NOSPL
2810     { "write-file",      LOGW, 0 },
2811 #endif /* NOSPL */
2812     { "", 0, 0 }
2813 };
2814 int ncls = (sizeof(clstab) / sizeof(struct keytab)) - 1;
2815
2816 /* SHOW command arguments */
2817
2818 #ifndef NOSHOW
2819 struct keytab shotab[] = {
2820 #ifndef NOSPL
2821     { "alarm",        SHALRM, 0 },
2822     { "arg",          SHARG, CM_INV|CM_ABR },
2823     { "arguments",    SHARG, 0 },
2824     { "args",         SHARG, CM_INV },
2825     { "arrays",       SHARR, 0 },
2826 #endif /* NOSPL */
2827
2828 #ifndef NOCSETS
2829     { "associations", SHASSOC, 0 },
2830 #endif /* NOCSETS */
2831
2832 #ifndef NOXFER
2833     { "attributes",   SHATT, 0 },
2834 #endif /* NOXFER */
2835
2836 #ifdef CK_AUTHENTICATION
2837     { "authentication", SHOAUTH, CM_INV },
2838 #endif /* CK_AUTHENTICATION */
2839
2840 #ifndef NOPUSH
2841 #ifdef BROWSER
2842     { "browser",      SHBROWSE, CM_PSH|CM_LOC },
2843 #endif /*  BROWSER */
2844 #endif /* NOPUSH */
2845     { "cd",           SHCD, 0 },
2846     { "character-sets", SHCSE, 0 },
2847     { "cmd",          SHCMD, CM_INV },
2848 #ifndef NOLOCAL
2849     { "com",          SHCOM, CM_INV|CM_ABR },
2850     { "comm",         SHCOM, CM_INV|CM_ABR },
2851     { "communications", SHCOM, 0 },
2852 #endif /* NOLOCAL */
2853     { "command",      SHCMD, 0 },
2854     { "connection",   SHCONNX, 0 },
2855 #ifdef CK_SPEED
2856     { "control-prefixing", SHCTL, 0 },
2857 #endif /* CK_SPEED */
2858 #ifdef CKLOGDIAL
2859     { "cx",           SHCONNX, CM_INV },
2860 #endif /* CKLOGDIAL */
2861 #ifndef NOSPL
2862     { "count",        SHCOU, 0 },
2863 #endif /* NOSPL */
2864     { "d",            SHDIA, CM_INV|CM_ABR },
2865 #ifdef VMS
2866     { "default",      SHDFLT, 0 },
2867 #else
2868     { "default",      SHDFLT, CM_INV },
2869 #endif /* VMS */
2870 #ifndef NODIAL
2871     { "dial",         SHDIA, CM_LOC },
2872 #endif /* NODIAL */
2873     { "double/ignore",SHDBL, 0 },
2874 #ifndef NOPUSH
2875 #ifndef NOFRILLS
2876     { "editor",       SHEDIT, CM_PSH },
2877 #endif /*  NOFRILLS */
2878 #endif /* NOPUSH */
2879 #ifndef NOLOCAL
2880     { "escape",       SHESC, CM_LOC },
2881 #endif /* NOLOCAL */
2882     { "exit",         SHEXI, 0 },
2883     { "extended-options", SHXOPT, CM_INV },
2884     { "features",     SHFEA, 0 },
2885     { "file",         SHFIL, 0 },
2886 #ifndef NOLOCAL
2887     { "flow-control", SHOFLO, 0 },
2888 #endif /* NOLOCAL */
2889 #ifdef BROWSER
2890     { "ftp",          SHOFTP, CM_PSH|CM_LOC },
2891 #else
2892 #ifndef NOFTP
2893 #ifndef SYSFTP
2894 #ifdef TCPSOCKET
2895     { "ftp",          SHOFTP, 0 },      /* (built-in ftp) */
2896 #endif /* TCPSOCKET */
2897 #endif /* SYSFTP */
2898 #endif /* NOFTP */
2899 #endif /* BROWSER */
2900 #ifndef NOSPL
2901     { "functions",    SHFUN, 0 },
2902     { "globals",      SHVAR, 0 },
2903 #endif /* NOSPL */
2904 #ifdef KUI
2905     { "gui",          SHOGUI, 0 },
2906 #endif /* KUI */
2907 #ifdef CK_RECALL
2908     { "history",      SHHISTORY, 0 },
2909 #endif /* CK_RECALL */
2910     { "ignore/double",SHDBL, CM_INV },
2911     { "iksd",         SHOIKS, CM_INV },
2912 #ifndef NOSPL
2913     { "input",        SHINP, 0 },
2914 #endif /* NOSPL */
2915 #ifndef NOSETKEY
2916     { "k",            SHKEY, CM_INV|CM_ABR },
2917     { "key",          SHKEY, 0 },
2918 #ifndef NOKVERBS
2919     { "kverbs",       SHKVB, 0 },
2920 #endif /* NOKVERBS */
2921 #endif /* NOSETKEY */
2922 #ifdef CK_LABELED
2923     { "labeled-file-info", SHLBL, 0 },
2924 #endif /* CK_LABELED */
2925 #ifndef NOCSETS
2926     { "languages",    SHLNG, 0 },
2927 #endif /* NOCSETS */
2928     { "logs",         SHLOG, 0 },
2929 #ifndef NOSPL
2930     { "macros",       SHMAC, 0 },
2931 #endif /* NOSPL */
2932 #ifndef NODIAL
2933     { "modem",        SHMOD, CM_LOC },
2934 #else
2935     { "modem-signals",SHCOM, CM_INV|CM_LOC },
2936 #endif /* NODIAL */
2937 #ifndef NOLOCAL
2938 #ifdef OS2MOUSE
2939     { "mouse",        SHMOU, CM_LOC },
2940 #endif /* OS2MOUSE */
2941 #endif /* NOLOCAL */
2942 #ifdef NETCONN
2943     { "network",      SHNET, CM_LOC },
2944 #else
2945     { "network",      SHNET, CM_INV|CM_LOC },
2946 #endif /* NETCONN */
2947     { "options",      SHOPTS, 0 },
2948 #ifndef NOSPL
2949     { "output",       SHOUTP, CM_INV },
2950 #endif /* NOSPL */
2951 #ifdef ANYX25
2952 #ifndef IBMX25
2953     { "pad",          SHPAD,  CM_LOC },
2954 #endif /* IBMX25 */
2955 #endif /* ANYX25 */
2956     { "parameters",   SHPAR,  CM_INV },
2957 #ifdef PATTERNS
2958     { "patterns",     SHOPAT, 0 },
2959 #endif /* PATTERNS */
2960     { "printer",      SHPRT,  0 },
2961 #ifdef CK_SPEED
2962     { "prefixing",    SHCTL,  CM_INV },
2963 #endif /* CK_SPEED */
2964 #ifndef NOXFER
2965     { "protocol",     SHPRO,  0 },
2966 #endif /* NOXFER */
2967 #ifndef NOSPL
2968     { "scripts",      SHSCR,  CM_LOC },
2969 #endif /* NOSPL */
2970     { "send-list",    SHSFL,  0 },
2971 #ifndef NOSERVER
2972     { "server",       SHSER,  0 },
2973 #endif /* NOSERVER */
2974 #ifndef NOSEXP
2975     { "sexpression",  SHSEXP, 0 },
2976 #endif /* NOSEXP */
2977 #ifdef ANYSSH
2978     { "ssh",          SHOSSH, 0 },
2979 #endif /* ANYSSH */
2980     { "stack",        SHSTK,  0 },
2981     { "status",       SHSTA,  0 },
2982 #ifdef STREAMING
2983     { "streaming",    SHOSTR, 0 },
2984 #endif /* STREAMING */
2985 #ifndef NOLOCAL
2986 #ifdef OS2
2987     { "tabs",          SHTAB, CM_INV|CM_LOC },
2988 #endif /* OS2 */
2989 #ifdef CK_TAPI
2990     { "tapi",          SHTAPI, CM_LOC },
2991     { "tapi-comm",     SHTAPI_C, CM_INV|CM_LOC },
2992     { "tapi-location", SHTAPI_L, CM_INV|CM_LOC },
2993     { "tapi-modem",    SHTAPI_M, CM_INV|CM_LOC },
2994 #endif /* CK_TAPI */
2995     { "tcp",           SHTCP,  CM_LOC },
2996 #ifdef TNCODE
2997     { "tel",           SHTEL,  CM_INV|CM_ABR },
2998     { "telnet",        SHTEL,  0 },
2999     { "telopt",        SHTOPT, 0 },
3000 #endif /* TNCODE */
3001     { "terminal",      SHTER,  CM_LOC },
3002 #endif /* NOLOCAL */
3003 #ifndef NOXMIT
3004     { "tr",            SHXMI, CM_INV|CM_ABR },
3005     { "tra",           SHXMI, CM_INV|CM_ABR },
3006     { "tran",          SHXMI, CM_INV|CM_ABR },
3007     { "trans",         SHXMI, CM_INV|CM_ABR },
3008 #endif /* NOXMIT */
3009 #ifndef NOXFER
3010     { "transfer",      SHOXFER, 0 },
3011 #endif /* NOXFER */
3012 #ifndef NOXMIT
3013     { "transmit",      SHXMI, 0 },
3014 #endif /* NOXMIT */
3015 #ifdef CK_TRIGGER
3016     { "trigger",       SHTRIG, CM_LOC },
3017 #endif /* CK_TRIGGER */
3018 #ifndef NOSETKEY
3019 #ifndef NOKVERBS
3020 #ifdef OS2
3021     { "udk",           SHUDK, CM_LOC },
3022 #endif /* OS2 */
3023 #endif /* NOKVERBS */
3024 #endif /* NOSETKEY */
3025 #ifndef NOSPL
3026     { "variables",     SHBUI, 0 },
3027 #endif /* NOSPL */
3028 #ifndef NOFRILLS
3029     { "versions",      SHVER, 0 },
3030 #endif /* NOFRILLS */
3031 #ifdef OS2
3032     { "vscrn",         SHVSCRN, CM_INV|CM_LOC },
3033 #endif /* OS2 */
3034     { "xfer",          SHOXFER,  CM_INV },
3035 #ifndef NOXMIT
3036     { "xmit",          SHXMI,    CM_INV },
3037 #endif /* NOXMIT */
3038     { "", 0, 0 }
3039 };
3040 int nsho = (sizeof(shotab) / sizeof(struct keytab)) - 1;
3041 #endif /* NOSHOW */
3042
3043 #ifdef ANYX25
3044 #ifndef IBMX25
3045 struct keytab padtab[] = {              /* PAD commands */
3046     { "clear",      XYPADL, 0 },
3047     { "interrupt",  XYPADI, 0 },
3048     { "reset",      XYPADR, 0 },
3049     { "status",     XYPADS, 0 }
3050 };
3051 int npadc = (sizeof(padtab) / sizeof(struct keytab));
3052 #endif /* IBMX25 */
3053 #endif /* ANYX25 */
3054
3055 #ifndef NOSERVER
3056 static struct keytab kmstab[] = {
3057     { "both",    3, 0 },
3058     { "local",   1, 0 },
3059     { "remote",  2, 0 }
3060 };
3061
3062 static struct keytab enatab[] = {       /* ENABLE commands */
3063     { "all",        EN_ALL,  0 },
3064 #ifndef NOSPL
3065     { "as",         EN_ASG,  CM_INV|CM_ABR },
3066     { "asg",        EN_ASG,  CM_INV },
3067     { "assign",     EN_ASG,  0 },
3068 #endif /* NOSPL */
3069 #ifndef datageneral
3070     { "bye",        EN_BYE,  0 },
3071 #endif /* datageneral */
3072     { "cd",         EN_CWD,  0 },
3073 #ifdef ZCOPY
3074     { "copy",       EN_CPY,  0 },
3075 #endif /* ZCOPY */
3076     { "cwd",        EN_CWD,  CM_INV },
3077     { "delete",     EN_DEL,  0 },
3078     { "directory",  EN_DIR,  0 },
3079     { "enable",     EN_ENA,  CM_INV },
3080     { "exit",       EN_XIT,  0 },
3081     { "finish",     EN_FIN,  0 },
3082     { "get",        EN_GET,  0 },
3083     { "host",       EN_HOS,  0 },
3084     { "mail",       EN_MAI,  0 },
3085     { "mkdir",      EN_MKD,  0 },
3086     { "print",      EN_PRI,  0 },
3087 #ifndef NOSPL
3088     { "query",      EN_QUE,  0 },
3089 #endif /* NOSPL */
3090     { "rename",     EN_REN,  0 },
3091     { "retrieve",   EN_RET,  CM_INV },
3092     { "rmdir",      EN_RMD,  0 },
3093     { "send",       EN_SEN,  0 },
3094     { "set",        EN_SET,  0 },
3095     { "space",      EN_SPA,  0 },
3096     { "type",       EN_TYP,  0 },
3097     { "who",        EN_WHO,  0 }
3098 };
3099 static int nena = (sizeof(enatab) / sizeof(struct keytab));
3100 #endif /* NOSERVER */
3101
3102 struct keytab txtbin[] = {
3103     { "all",        2, 0 },
3104     { "binary",     1, 0 },
3105     { "text",       0, 0 }
3106 };
3107
3108 #ifndef NOXFER
3109 static struct keytab sndtab[] = {       /* SEND command options */
3110     { "/after",           SND_AFT, CM_ARG },
3111 #ifndef NOSPL
3112     { "/array",           SND_ARR, CM_ARG },
3113 #endif /* NOSPL */
3114     { "/as-name",         SND_ASN, CM_ARG },
3115     { "/b",               SND_BIN, CM_INV|CM_ABR },
3116     { "/before",          SND_BEF, CM_ARG },
3117     { "/binary",          SND_BIN, 0 },
3118 #ifdef CALIBRATE
3119     { "/c",               SND_CMD, CM_INV|CM_ABR },
3120     { "/calibrate",       SND_CAL, CM_INV|CM_ARG },
3121 #endif /* CALIBRATE */
3122     { "/command",         SND_CMD, CM_PSH },
3123     { "/delete",          SND_DEL, 0 },
3124 #ifdef UNIXOROSK
3125     { "/dotfiles",        SND_DOT, 0 },
3126 #endif /* UNIXOROSK */
3127     { "/except",          SND_EXC, CM_ARG },
3128 #ifdef PIPESEND
3129     { "/filter",          SND_FLT, CM_ARG|CM_PSH },
3130 #endif /* PIPESEND */
3131     { "/filenames",       SND_NAM, CM_ARG },
3132 #ifdef CKSYMLINK
3133     { "/followlinks",     SND_LNK, 0 },
3134 #endif /* CKSYMLINK */
3135 #ifdef VMS
3136     { "/image",           SND_IMG, 0 },
3137 #else
3138     { "/image",           SND_BIN, CM_INV },
3139 #endif /* VMS */
3140 #ifdef CK_LABELED
3141     { "/labeled",         SND_LBL, 0 },
3142 #endif /* CK_LABELED */
3143     { "/larger-than",     SND_LAR, CM_ARG },
3144     { "/listfile",        SND_FIL, CM_ARG },
3145 #ifndef NOFRILLS
3146     { "/mail",            SND_MAI, CM_ARG },
3147 #endif /* NOFRILLS */
3148 #ifdef CK_TMPDIR
3149     { "/move-to",         SND_MOV, CM_ARG },
3150 #endif /* CK_TMPDIR */
3151     { "/nobackupfiles",   SND_NOB, 0 },
3152 #ifdef UNIXOROSK
3153     { "/nodotfiles",      SND_NOD, 0 },
3154 #endif /* UNIXOROSK */
3155 #ifdef CKSYMLINK
3156     { "/nofollowlinks",   SND_NLK, 0 },
3157 #endif /* CKSYMLINK */
3158     { "/not-after",       SND_NAF, CM_ARG },
3159     { "/not-before",      SND_NBE, CM_ARG },
3160     { "/pathnames",       SND_PTH, CM_ARG },
3161     { "/print",           SND_PRI, CM_ARG },
3162 #ifdef CK_XYZ
3163     { "/protocol",        SND_PRO, CM_ARG },
3164 #else
3165     { "/protocol",        SND_PRO, CM_ARG|CM_INV },
3166 #endif /* CK_XYZ */
3167     { "/quiet",           SND_SHH, 0 },
3168     { "/recover",         SND_RES, 0 },
3169 #ifdef RECURSIVE
3170 /* Systems where we do recursion */
3171     { "/recursive",       SND_REC, 0 },
3172 #else
3173 #ifdef VMS
3174 /* Systems that do recursion themselves without our assistance */
3175 /* if we give them the right kind of wildcard */
3176     { "/recursive",       SND_REC, 0 },
3177 #else
3178 #ifdef datageneral
3179     { "/recursive",       SND_REC, 0 },
3180 #else
3181     { "/recursive",       SND_REC, CM_INV },
3182 #endif /* datageneral */
3183 #endif /* VMS */
3184 #endif /* RECURSIVE */
3185     { "/rename-to",       SND_REN, CM_ARG },
3186     { "/since",           SND_AFT, CM_INV|CM_ARG },
3187     { "/smaller-than",    SND_SMA, CM_ARG },
3188     { "/starting-at",     SND_STA, CM_ARG },
3189 #ifndef NOFRILLS
3190     { "/su",              SND_ASN, CM_ARG|CM_INV|CM_ABR },
3191     { "/sub",             SND_ASN, CM_ARG|CM_INV|CM_ABR },
3192     { "/subject",         SND_ASN, CM_ARG },
3193 #endif /* NOFRILLS */
3194 #ifdef RECURSIVE
3195     { "/subdirectories",  SND_REC, CM_INV },
3196 #endif /* RECURSIVE */
3197     { "/text",            SND_TXT, 0 },
3198     { "/transparent",     SND_XPA, 0 },
3199     { "/type",            SND_TYP, CM_ARG }
3200 };
3201 #define NSNDTAB sizeof(sndtab)/sizeof(struct keytab)
3202 static int nsndtab = NSNDTAB;
3203
3204 #ifndef NOMSEND
3205 static struct keytab msndtab[] = {      /* MSEND options */
3206     { "/after",           SND_AFT, CM_ARG },
3207     { "/before",          SND_BEF, CM_ARG },
3208     { "/binary",          SND_BIN, 0 },
3209     { "/delete",          SND_DEL, 0 },
3210     { "/except",          SND_EXC, CM_ARG },
3211     { "/filenames",       SND_NAM, CM_ARG },
3212 #ifdef CKSYMLINK
3213     { "/followlinks",     SND_LNK, 0 },
3214 #endif /* CKSYMLINK */
3215 #ifdef VMS
3216     { "/image",           SND_IMG, 0 },
3217 #else
3218     { "/image",           SND_BIN, CM_INV },
3219 #endif /* VMS */
3220 #ifdef CK_LABELED
3221     { "/labeled",         SND_LBL, 0 },
3222 #endif /* CK_LABELED */
3223     { "/larger-than",     SND_LAR, CM_ARG },
3224     { "/list",            SND_FIL, CM_ARG },
3225 #ifndef NOFRILLS
3226     { "/mail",            SND_MAI, CM_ARG },
3227 #endif /* NOFRILLS */
3228 #ifdef CK_TMPDIR
3229     { "/move-to",         SND_MOV, CM_ARG },
3230 #endif /* CK_TMPDIR */
3231 #ifdef CKSYMLINK
3232     { "/nofollowlinks", SND_NLK, 0 },
3233 #endif /* CKSYMLINK */
3234     { "/not-after",       SND_NAF, CM_ARG },
3235     { "/not-before",      SND_NBE, CM_ARG },
3236     { "/pathnames",       SND_PTH, CM_ARG },
3237     { "/print",           SND_PRI, CM_ARG },
3238 #ifdef CK_XYZ
3239     { "/protocol",        SND_PRO, CM_ARG },
3240 #endif /* CK_XYZ */
3241     { "/quiet",           SND_SHH, 0 },
3242     { "/recover",         SND_RES, 0 },
3243     { "/rename-to",       SND_REN, CM_ARG },
3244     { "/since",           SND_AFT, CM_INV|CM_ARG },
3245     { "/smaller-than",    SND_SMA, CM_ARG },
3246     { "/starting-at",     SND_STA, CM_ARG },
3247 #ifndef NOFRILLS
3248     { "/subject",         SND_ASN, CM_ARG },
3249 #endif /* NOFRILLS */
3250     { "/text",            SND_TXT, 0 },
3251     { "/transparent",     SND_XPA, 0 },
3252     { "/type",            SND_TYP, CM_ARG }
3253 };
3254 #define NMSNDTAB sizeof(msndtab)/sizeof(struct keytab)
3255 static int nmsndtab = NMSNDTAB;
3256 #endif /* NOMSEND */
3257 #endif /* NOXFER */
3258
3259 /* CONNECT command switches */
3260
3261 #define CONN_II  0      /* Idle interval */
3262 #define CONN_IS  1      /* Idle string */
3263 #define CONN_IL  2      /* Idle limit */
3264 #define CONN_NV  3      /* Non-Verbose */
3265 #define CONN_TL  4      /* Time limit */
3266 #define CONN_TS  5      /* Trigger string */
3267 #define CONN_AS  6      /* Asynchronous */
3268 #define CONN_SY  7      /* Synchronous */
3269 #define CONN_MAX 7      /* Number of CONNECT switches */
3270
3271 #ifndef NOLOCAL
3272 static struct keytab conntab[] = {
3273 #ifdef OS2
3274     { "/asynchronous",    CONN_AS, CM_INV },
3275 #endif /* OS2 */
3276 #ifdef XLIMITS
3277     { "/idle-interval",   CONN_II, CM_ARG },
3278     { "/idle-limit",      CONN_IL, CM_ARG },
3279     { "/idle-string",     CONN_IS, CM_ARG },
3280     { "/quietly",         CONN_NV, CM_INV },
3281 #else
3282     { "/quietly",         CONN_NV, 0 },
3283 #endif /* XLIMITS */
3284 #ifdef OS2
3285     { "/synchronous",     CONN_SY, CM_INV },
3286 #endif /* OS2 */
3287 #ifdef XLIMITS
3288     { "/time-limit",      CONN_TL, CM_ARG },
3289 #endif /* XLIMITS */
3290 #ifdef CK_TRIGGER
3291     { "/trigger",         CONN_TS, CM_ARG },
3292 #endif /* CK_TRIGGER */
3293     { "",0,0 }
3294 };
3295 #define NCONNTAB sizeof(conntab)/sizeof(struct keytab)
3296 static int nconntab = NCONNTAB;
3297 #endif /* NOLOCAL */
3298
3299 #ifndef NOXFER
3300 static struct keytab stattab[] = {      /* STATISTICS command switches */
3301     { "/brief",   1, 0 },
3302     { "/verbose", 0, 0 }
3303 };
3304 #endif /* NOXFER */
3305
3306 #ifndef NOSPL
3307 #ifdef COMMENT
3308 struct mtab mactab[MAC_MAX] = {         /* Preinitialized macro table */
3309     { NULL, NULL, 0 }
3310 };
3311 #else
3312 struct mtab *mactab;                    /* Dynamically allocated macro table */
3313 #endif /* COMMENT */
3314 int nmac = 0;
3315
3316 struct keytab mackey[MAC_MAX];          /* Macro names as command keywords */
3317 #endif /* NOSPL */
3318
3319 #ifndef NOSPL
3320 #ifdef  OS2
3321 struct keytab beeptab[] = {             /* Beep options */
3322     { "error", BP_FAIL, 0 },
3323     { "information", BP_NOTE, 0 },
3324     { "warning", BP_WARN, 0 }
3325 };
3326 int nbeeptab = sizeof(beeptab)/sizeof(struct keytab);
3327
3328 /* CLEAR COMMMAND-SCREEN options */
3329
3330 #define CLR_C_ALL 0
3331 #define CLR_C_BOL 1
3332 #define CLR_C_BOS 2
3333 #define CLR_C_EOL 3
3334 #define CLR_C_EOS 4
3335 #define CLR_C_LIN 5
3336 #define CLR_C_SCR 6
3337
3338 struct keytab clrcmdtab[] = {
3339     { "all",        CLR_C_ALL, 0 },
3340     { "bol",        CLR_C_BOL, 0 },
3341     { "bos",        CLR_C_BOS, 0 },
3342     { "eol",        CLR_C_EOL, 0 },
3343     { "eos",        CLR_C_EOS, 0 },
3344     { "line",       CLR_C_LIN, 0 },
3345     { "scrollback", CLR_C_SCR, 0 }
3346 };
3347 int nclrcmd = sizeof(clrcmdtab)/sizeof(struct keytab);
3348 #endif /* OS2 */
3349 #endif /* NOSPL */
3350
3351 #ifdef COMMENT
3352 /* Not used at present */
3353 static struct keytab pagetab[] = {
3354     { "/more",   1, CM_INV },
3355     { "/nopage", 0, 0 },
3356     { "/page",   1, 0 }
3357 };
3358 int npagetab = sizeof(pagetab)/sizeof(struct keytab);
3359 #endif /* COMMENT */
3360
3361 #define TYP_NOP  0                      /* /NOPAGE */
3362 #define TYP_PAG  1                      /* /PAGE */
3363 #define TYP_HEA  2                      /* /HEAD:n */
3364 #define TYP_TAI  3                      /* /TAIL:n */
3365 #define TYP_PAT  4                      /* /MATCH:pattern */
3366 #define TYP_WID  5                      /* /WIDTH:cols */
3367 #define TYP_COU  6                      /* /COUNT */
3368 #define TYP_OUT  7                      /* /OUTPUT:file */
3369 #define TYP_PFX  8                      /* /PREFIX:string */
3370 #ifdef UNICODE
3371 #define TYP_XIN  9                      /* /TRANSLATE-FROM:charset */
3372 #define TYP_XUT 10                      /* /TRANSLATE-TO:charset */
3373 #define TYP_XPA 11                      /* /TRANSPARENT */
3374 #endif /* UNICODE */
3375 #ifdef KUI
3376 #define TYP_GUI 12                      /* /GUI:title */
3377 #define TYP_HIG 13                      /* /HEIGHT:rows */
3378 #endif /* KUI */
3379 #define TYP_NUM 14                      /* /NUMBER */
3380
3381 static struct keytab typetab[] = {      /* TYPE command switches */
3382     { "/count",          TYP_COU, 0 },
3383 #ifdef UNICODE
3384     { "/character-set",  TYP_XIN, CM_ARG },
3385 #endif /* UNICODE */
3386 #ifdef KUI
3387     { "/gui",            TYP_GUI, CM_ARG },
3388 #endif /* KUI */
3389     { "/head",           TYP_HEA, CM_ARG },
3390 #ifdef KUI
3391     { "/height",         TYP_HIG, CM_ARG },
3392 #endif /* KUI */
3393     { "/match",          TYP_PAT, CM_ARG },
3394 #ifdef CK_TTGWSIZ
3395     { "/more",           TYP_PAG, CM_INV },
3396     { "/nopage",         TYP_NOP, 0 },
3397     { "/number",         TYP_NUM, 0 },
3398     { "/output",         TYP_OUT, CM_ARG },
3399     { "/page",           TYP_PAG, 0 },
3400 #endif /* CK_TTGWSIZ */
3401     { "/prefix",         TYP_PFX, CM_ARG },
3402     { "/tail",           TYP_TAI, CM_ARG },
3403 #ifdef UNICODE
3404     { "/translate-to",   TYP_XUT, CM_ARG },
3405     { "/transparent",    TYP_XPA, 0 },
3406 #endif /* UNICODE */
3407     { "/width",          TYP_WID, CM_ARG },
3408 #ifdef UNICODE
3409     { "/xlate-to",       TYP_XUT, CM_INV|CM_ARG },
3410 #endif /* UNICODE */
3411     { "", 0, 0 }
3412 };
3413 int ntypetab = sizeof(typetab)/sizeof(struct keytab) - 1;
3414
3415 int typ_page = -1;                      /* TYPE /[NO]PAGE default */
3416 int typ_wid  = -1;
3417
3418 #ifndef NOSPL
3419 #define TRA_ALL 999                     /* TRACE command */
3420 #define TRA_ASG 0
3421 #define TRA_CMD 1
3422
3423 int tra_asg = 0;
3424 int tra_cmd = 0;
3425
3426 static struct keytab tracetab[] = {     /* TRACE options */
3427     { "all",            TRA_ALL, 0 },
3428     { "assignments",    TRA_ASG, 0 },
3429     { "command-level",  TRA_CMD, 0 }
3430 };
3431 static int ntracetab = sizeof(tracetab)/sizeof(struct keytab);
3432 #endif /* NOSPL */
3433
3434 #ifndef NOSHOW
3435 VOID
3436 showtypopts() {
3437     printf(" TYPE ");
3438     if (typ_page > -1) {
3439         prtopt(&optlines,typ_page ? "/PAGE" : "/NOPAGE");
3440     } else
3441       prtopt(&optlines,"(no options set)");
3442     if (typ_wid > -1) {
3443         ckmakmsg(tmpbuf,TMPBUFSIZ,"/WIDTH:",ckitoa(typ_wid),NULL,NULL);
3444         prtopt(&optlines,tmpbuf);
3445     }
3446     prtopt(&optlines,"");
3447 }
3448 #endif /* NOSHOW */
3449
3450 #ifdef LOCUS
3451 /* isauto == 1 if locus is being switched automatically */
3452
3453 VOID
3454 setlocus(x, isauto) int x, isauto; {
3455     extern int quitting;
3456     if (x) x = 1;
3457     if (x && locus) return;
3458     if (!x && !locus) return;
3459     /* Get here if it actually needs to be changed */
3460 #ifdef OS2
3461     if (isauto &&                       /* Automatically switching */
3462         !quitting &&                    /* not exiting */
3463         autolocus == 2) {               /* and AUTOLOCUS is set to ASK */
3464         char locmsg[300];
3465         ckmakmsg(locmsg,300,
3466                  "Switching Locus to ",
3467                  x ? "LOCAL" : "REMOTE",
3468                  " for file management commands\n"
3469                  "such as CD, DIRECTORY, DELETE, RENAME.  Type HELP SET\n"
3470                  "LOCUS at the K-95> prompt for further info.  Use the\n"
3471 #ifdef KUI
3472                   "Actions menu or SET LOCUS command to disable automatic\n"
3473                   "Locus switching or to disable these queries.",
3474 #else /* KUI */
3475                   "SET LOCUS command to disable automatic locus switching\n"
3476                   "or to disable these queries.",
3477 #endif /* KUI */
3478                   NULL);
3479         if (uq_ok(locmsg,"OK to switch Locus?",3,NULL,1)) {
3480             locus = x;
3481 #ifdef KUI
3482             KuiSetProperty(KUI_LOCUS,x,0);
3483 #endif /* KUI */
3484             return;
3485         }
3486     } else {
3487 #endif /* OS2 */
3488         if (isauto && msgflg && !quitting)
3489           printf("Switching LOCUS for file-management commands to %s.\n",
3490                  x ? "LOCAL" : "REMOTE"
3491                  );
3492         locus = x;
3493 #ifdef OS2
3494 #ifdef KUI
3495         KuiSetProperty(KUI_LOCUS,x,0);
3496 #endif /* KUI */
3497     }
3498 #endif /* OS2 */
3499 }
3500
3501 VOID
3502 setautolocus(x) int x; {
3503     autolocus = x;
3504 #ifdef KUI
3505     KuiSetProperty(KUI_AUTO_LOCUS,x,0);
3506 #endif /* KUI */
3507 }
3508 #endif /* LOCUS */
3509
3510 int
3511 settypopts() {                          /* Set TYPE option defaults */
3512     int xp = -1;
3513     int c, getval;
3514     while (1) {
3515         if ((y = cmswi(typetab,ntypetab,"Switch","",xxstring)) < 0) {
3516             if (y == -3)
3517               break;
3518             else
3519               return(y);
3520         }
3521         c = cmgbrk();
3522         if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
3523             printf("?This switch does not take an argument\n");
3524             return(-9);
3525         }
3526         switch (y) {
3527           case TYP_NOP: xp = 0; break;
3528           case TYP_PAG: xp = 1; break;
3529           case TYP_WID:
3530             if (getval)
3531               if ((x = cmnum("Column at which to truncate",
3532                              ckitoa(cmd_cols),10,&y,xxstring)) < 0)
3533                 return(x);
3534             typ_wid = y;
3535             break;
3536
3537           default:
3538             printf("?Sorry, this option can not be set\n");
3539             return(-9);
3540         }
3541     }
3542     if ((x = cmcfm()) < 0)              /* Get confirmation */
3543       return(x);
3544     if (xp > -1) typ_page = xp;         /* Confirmed, save defaults */
3545     return(success = 1);
3546 }
3547
3548 /* Forward declarations of functions local to this module */
3549
3550 #ifdef UNIX
3551 _PROTOTYP (int douchmod, ( void ) );
3552 #endif /* UNIX */
3553 #ifdef CKPURGE
3554 _PROTOTYP (int dopurge,  ( void ) );
3555 #endif /* CKPURGE */
3556 #ifndef NOSPL
3557 _PROTOTYP (int doundef,  ( int  ) );
3558 _PROTOTYP (int doask,    ( int  ) );
3559 _PROTOTYP (int dodef,    ( int  ) );
3560 _PROTOTYP (int doelse,   ( void ) );
3561 _PROTOTYP (int dofor,    ( void ) );
3562 _PROTOTYP (int doincr,   ( int  ) );
3563 #endif /* NOSPL  */
3564 #ifndef NODIAL
3565 _PROTOTYP (int dodial,   ( int  ) );
3566 #endif /* NODIAL */
3567 _PROTOTYP (int dodel,    ( void ) );
3568 _PROTOTYP (int dopaus,   ( int  ) );
3569 #ifndef NOPUSH
3570 #ifdef TCPSOCKET
3571 _PROTOTYP (int doping,   ( void ) );
3572 _PROTOTYP (int doftp,    ( void ) );
3573 #endif /* TCPSOCKET */
3574 #endif /* NOPUSH */
3575 #ifndef NORENAME
3576 #ifndef NOFRILLS
3577 _PROTOTYP (int dorenam,  ( void ) );
3578 #endif /* NOFRILLS */
3579 #endif /* NORENAME */
3580 #ifdef ZCOPY
3581 _PROTOTYP (int docopy,   ( void ) );
3582 #endif /* ZCOPY */
3583 #ifdef NT
3584 _PROTOTYP (int dolink,   ( void ));
3585 #endif /* NT */
3586 #ifdef CK_REXX
3587 _PROTOTYP (int dorexx,   ( void ) );
3588 #endif /* CK_REXX */
3589
3590 #ifdef TNCODE
3591 static struct keytab telcmd[] = {
3592     { "abort", TN_ABORT, CM_INV },      /* Emotionally toned - don't show */
3593     { "ao",    TN_AO,    0 },
3594     { "ayt",   TN_AYT,   0 },
3595     { "break", BREAK,    0 },
3596     { "cancel",TN_ABORT, 0 },
3597     { "dmark", TN_DM,    0 },
3598     { "do",    DO,       0 },
3599     { "dont",  DONT,     0 },
3600     { "ec",    TN_EC,    0 },
3601     { "el",    TN_EL,    0 },
3602     { "eof",   TN_EOF,   0 },
3603     { "eor",   TN_EOR,   0 },
3604 #ifdef CK_KERBEROS
3605 #ifdef KRB5
3606 #define TN_FWD 1
3607     { "forward", TN_FWD, CM_INV },
3608 #endif /* KRB5 */
3609 #endif /* CK_KERBEROS */
3610     { "ga",    TN_GA,    0 },
3611     { "ip",    TN_IP,    0 },
3612     { "nop",   TN_NOP,   0 },
3613     { "sak",   TN_SAK,   CM_INV },
3614     { "sb",    SB,       0 },
3615     { "se",    SE,       0 },
3616     { "susp",  TN_SUSP,  0 },
3617     { "will",  WILL,     0 },
3618     { "wont",  WONT,     0 }
3619 };
3620 static int ntelcmd = (sizeof(telcmd) / sizeof(struct keytab));
3621
3622 static struct keytab tnopts[] = {
3623 #ifdef CK_AUTHENTICATION
3624     { "auth",   TELOPT_AUTHENTICATION,   0 },
3625 #else
3626     { "auth",   TELOPT_AUTHENTICATION,   CM_INV },
3627 #endif /* CK_AUTHENTICATION */
3628     { "binary", TELOPT_BINARY, 0 },
3629 #ifdef TN_COMPORT
3630     { "c",      TELOPT_COMPORT, CM_INV|CM_ABR},
3631     { "co",     TELOPT_COMPORT, CM_INV|CM_ABR},
3632     { "com",    TELOPT_COMPORT, CM_INV|CM_ABR},
3633     { "com-port-control", TELOPT_COMPORT, 0 },
3634     { "comport-control", TELOPT_COMPORT, CM_INV},
3635 #else  /* TN_COMPORT */
3636     { "com-port-control", TELOPT_COMPORT, CM_INV },
3637     { "comport-control", TELOPT_COMPORT, CM_INV},
3638 #endif /* TN_COMPORT */
3639     { "echo", TELOPT_ECHO, 0 },
3640 #ifdef CK_ENCRYPTION
3641     { "encrypt", TELOPT_ENCRYPTION, 0 },
3642 #else
3643     { "encrypt", TELOPT_ENCRYPTION, CM_INV },
3644 #endif /* CK_ENCRYPTION */
3645 #ifdef CK_FORWARD_X
3646     { "forward-x", TELOPT_FORWARD_X, 0 },
3647 #else
3648     { "forward-x", TELOPT_FORWARD_X, CM_INV },
3649 #endif /* CK_FORWARD_X */
3650 #ifdef IKS_OPTION
3651     { "kermit", TELOPT_KERMIT, 0 },
3652 #else
3653     { "kermit", TELOPT_KERMIT, CM_INV },
3654 #endif /* IKS_OPTION */
3655     { "lflow",  TELOPT_LFLOW, CM_INV },
3656     { "logout", TELOPT_LOGOUT, CM_INV },
3657 #ifdef CK_NAWS
3658     { "naws", TELOPT_NAWS, 0 },
3659 #else
3660     { "naws", TELOPT_NAWS, CM_INV },
3661 #endif /* CK_NAWS */
3662 #ifdef CK_ENVIRONMENT
3663     { "new-environment", TELOPT_NEWENVIRON,  0 },
3664 #else
3665     { "new-environment", TELOPT_NEWENVIRON,  CM_INV },
3666 #endif /* CK_ENVIRONMENT */
3667     { "pragma-heartbeat",TELOPT_PRAGMA_HEARTBEAT,  CM_INV },
3668     { "pragma-logon",    TELOPT_PRAGMA_LOGON,  CM_INV },
3669     { "pragma-sspi",     TELOPT_SSPI_LOGON,  CM_INV },
3670     { "sak",   TELOPT_IBM_SAK, CM_INV },
3671 #ifdef CK_SNDLOC
3672     { "send-location",   TELOPT_SNDLOC,  0 },
3673 #else
3674     { "send-location",   TELOPT_SNDLOC,  CM_INV },
3675 #endif /* CK_SNDLOC */
3676     { "sga", TELOPT_SGA, 0 },
3677 #ifdef CK_SSL
3678     { "start-tls",       TELOPT_START_TLS,  0 },
3679 #else
3680     { "start-tls",       TELOPT_START_TLS,  CM_INV },
3681 #endif /* CK_SSL */
3682     { "ttype", TELOPT_TTYPE, 0 },
3683 #ifdef CK_ENVIRONMENT
3684     { "xdisplay-location", TELOPT_XDISPLOC, 0 },
3685 #else
3686     { "xdisplay-location", TELOPT_XDISPLOC, CM_INV },
3687 #endif /* CK_ENVIRONMENT */
3688     { "", 0, 0 }
3689 };
3690 static int ntnopts = (sizeof(tnopts) / sizeof(struct keytab)) - 1;
3691
3692 static struct keytab tnsbopts[] = {
3693 #ifdef CK_NAWS
3694     { "naws", TELOPT_NAWS, 0 },
3695 #endif /* CK_NAWS */
3696     { "", 0, 0 }
3697 };
3698 static int ntnsbopts = (sizeof(tnsbopts) / sizeof(struct keytab)) - 1;
3699 #endif /* TNCODE */
3700
3701 #ifdef TCPSOCKET
3702 #ifndef NOPUSH
3703 #ifdef SYSFTP
3704 int
3705 doftp() {                               /* (External) FTP command */
3706     char *p, *f;                        /* (See doxftp() for internal one) */
3707     int x;
3708
3709     if (network)                        /* If we have a current connection */
3710       ckstrncpy(line,ttname,LINBUFSIZ); /* get the host name */
3711     else *line = '\0';                  /* as default host */
3712     for (p = line; *p; p++)             /* Remove ":service" from end. */
3713       if (*p == ':') { *p = '\0'; break; }
3714     if ((x = cmtxt("IP host name or number", line, &s, xxstring)) < 0)
3715       return(x);
3716     if (nopush) {
3717         printf("?Sorry, FTP command disabled\n");
3718         return(success = 0);
3719     }
3720 /* Construct FTP command */
3721 #ifdef VMS
3722 #ifdef MULTINET                         /* TGV MultiNet */
3723     ckmakmsg(line,LINBUFSIZ,"multinet ftp ",s,NULL,NULL);
3724 #else
3725     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3726 #endif /* MULTINET */
3727 #else                                   /* Not VMS */
3728 #ifdef OS2ORUNIX
3729 #ifndef NOFTP
3730     f = ftpapp;
3731     if (!f) f = "";
3732     if (!f[0]) f = "ftp";
3733     ckmakmsg(line,LINBUFSIZ,f," ",s,NULL);
3734 #ifdef OS2
3735     p = line + strlen(ftpapp);
3736     while (p != line) {
3737         if (*p == '/') *p = '\\';
3738         p--;
3739     }
3740 #endif /* OS2 */
3741 #else /* NOFTP */
3742     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3743 #endif /* NOFTP */
3744 #else /* OS2ORUNIX */
3745     ckmakmsg(line,LINBUFSIZ,"ftp ",s,NULL,NULL);
3746 #endif /* OS2ORUNIX */
3747 #endif /* VMS */
3748     conres();                           /* Make console normal  */
3749 #ifdef DEC_TCPIP
3750     printf("\n");                       /* Prevent prompt-stomping */
3751 #endif /* DEC_TCPIP */
3752     x = zshcmd(line);
3753     concb((char)escape);
3754     return(success = x);
3755 }
3756 #endif /* SYSFTP */
3757
3758 int
3759 doping() {                              /* PING command */
3760     char *p;                            /* just runs ping program */
3761     int x;
3762
3763     if (network)                        /* If we have a current connection */
3764       ckstrncpy(line,ttname,LINBUFSIZ); /* get the host name */
3765     else *line = '\0';                  /* as default host to be pinged. */
3766     for (p = line; *p; p++)             /* Remove ":service" from end. */
3767       if (*p == ':') { *p = '\0'; break; }
3768     if ((x = cmtxt("IP host name or number", line, &s, xxstring)) < 0)
3769       return(x);
3770     if (nopush) {
3771         printf("?Sorry, PING command disabled\n");
3772         return(success = 0);
3773     }
3774
3775     /* Construct PING command */
3776 #ifdef VMS
3777 #ifdef MULTINET                         /* TGV MultiNet */
3778     ckmakmsg(line,LINBUFSIZ,"multinet ping ",s," /num=1",NULL);
3779 #else
3780     ckmakmsg(line,LINBUFSIZ,"ping ",s," 56 1",NULL); /* Other VMS TCP/IP's */
3781 #endif /* MULTINET */
3782 #else                                   /* Not VMS */
3783     ckmakmsg(line,LINBUFSIZ,"ping ",s,NULL,NULL);
3784 #endif /* VMS */
3785     conres();                           /* Make console normal  */
3786 #ifdef DEC_TCPIP
3787     printf("\n");                       /* Prevent prompt-stomping */
3788 #endif /* DEC_TCPIP */
3789     x = zshcmd(line);
3790     concb((char)escape);
3791     return(success = x);
3792 }
3793 #endif /* NOPUSH */
3794 #endif /* TCPSOCKET */
3795
3796 static VOID
3797 doend(x) int x; {
3798 #ifndef NOSPL
3799     /* Pop from all FOR/WHILE/XIF/SWITCH's */
3800     debug(F101,"doend maclvl 1","",maclvl);
3801     while ((maclvl > 0) &&
3802            (m_arg[maclvl-1][0]) &&
3803            (cmdstk[cmdlvl].src == CMD_MD) &&
3804            (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
3805             !strncmp(m_arg[maclvl-1][0],"_for",4) ||
3806             !strncmp(m_arg[maclvl-1][0],"_whi",4) ||
3807             !strncmp(m_arg[maclvl-1][0],"_swi",4))) {
3808         debug(F110,"END popping",m_arg[maclvl-1][0],0);
3809         dogta(XXPTA);                   /* Put args back */
3810         popclvl();                      /* Pop up two levels */
3811         popclvl();
3812         debug(F101,"doend maclvl 2","",maclvl);
3813     }
3814     if (maclvl > -1) {
3815         if (mrval[maclvl])              /* Free previous retval if any */
3816           free(mrval[maclvl]);
3817         mrval[maclvl] = malloc(16);     /* Room for up to 15 digits */
3818         if (mrval[maclvl])              /* Record current retval */
3819           ckmakmsg(mrval[maclvl],16,ckitoa(x),NULL,NULL,NULL);
3820     }
3821 #endif /* NOSPL */
3822     popclvl();                          /* Now pop out of macro or TAKE file */
3823 #ifndef NOSPL
3824 #ifdef DEBUG
3825     if (deblog) {
3826         debug(F101,"END maclvl 3","",maclvl);
3827         debug(F111,"END mrval[maclvl]",mrval[maclvl],maclvl);
3828         debug(F111,"END mrval[maclvl+1]",mrval[maclvl+1],maclvl+1);
3829     }
3830 #endif /* DEBUG */
3831 #endif /* NOSPL */
3832 }
3833
3834 #ifdef CKROOT
3835 int
3836 dochroot() {
3837     if ((x = cmdir("Name of new root directory","",&s,xxstring)) < 0) {
3838         if (x == -3) {
3839             printf("?Directory name required\n");
3840             return(-9);
3841         }
3842         return(x);
3843     }
3844     ckstrncpy(line,s,LINBUFSIZ);
3845     s = line;
3846     if ((x = cmcfm()) < 0) return(x);
3847     s = brstrip(s);
3848     x = zsetroot(s);
3849     if (x < 0) {
3850         char * m = NULL;
3851         switch (x) {
3852           case -1:
3853           case -2: m = "Not a directory"; break;
3854           case -3: m = "Internal error"; break;
3855           case -4: m = "Access denied"; break;
3856           case -5: m = "Off limits"; break;
3857         }
3858         if (m) printf("%s: \"%s\"\n", m, s);
3859         return(m ? -9 : -2);
3860     } else {
3861         nopush = 1;
3862         return(success = 1);
3863     }
3864 }
3865 #endif /* CKROOT */
3866
3867 #ifndef NOXFER
3868 static char * asnbuf = NULL;            /* As-name buffer pointer */
3869
3870 char sndxnam[] = { "_array_x_" };       /* (with replaceable x!) */
3871
3872 /*
3873   The new SEND command, replacing BSEND, CSEND, PSEND, etc etc.
3874   Call with cx = top-level keyword value.  Returns:
3875     < 0  On parse error.
3876     0    On other type of failure (e.g. requested operation not allowed).
3877     1    On success with sstate set to 's' so protocol will begin.
3878 */
3879
3880 /*  D O X S E N D  --  Parse SEND and related commands with switches  */
3881
3882 int
3883 doxsend(cx) int cx; {
3884     int c, i, n, wild, confirmed = 0;   /* Workers */
3885     int x, y;                           /* of the world... */
3886     int getval = 0;                     /* Whether to get switch value */
3887     extern char * snd_move;             /* Directory to move sent files to */
3888     extern char * snd_rename;           /* What to rename sent files to */
3889     extern char * filefile;             /* File containing filenames to send */
3890     extern int xfiletype;               /* Send only text (or binary) files */
3891     extern struct keytab pathtab[];     /* PATHNAMES option keywords */
3892     extern int npathtab;                /* How many of them */
3893     extern int recursive;               /* Recursive directory traversal */
3894     extern int rprintf;                 /* REMOTE PRINT flag */
3895     extern int fdispla;                 /* TRANSFER DISPLAY setting */
3896     extern int skipbup;                 /* Skip backup files when sending */
3897     struct stringint {                  /* Temporary array for switch values */
3898         char * sval;
3899         int ival;
3900     } pv[SND_MAX+1];
3901     struct FDB sf, sw, fl, cm;          /* FDBs for each parse function */
3902     int mlist = 0;                      /* Flag for MSEND or MMOVE */
3903     char * m;                           /* For making help messages */
3904     extern struct keytab protos[];      /* File transfer protocols */
3905     extern int xfrxla, g_xfrxla, nprotos;
3906     extern char sndbefore[], sndafter[], *sndexcept[]; /* Selection criteria */
3907     extern char sndnbefore[], sndnafter[];
3908     extern long sndsmaller, sndlarger, calibrate;
3909 #ifndef NOSPL
3910     int range[2];                       /* Array range */
3911     char ** ap = NULL;                  /* Array pointer */
3912     int arrayx = -1;                    /* Array index */
3913 #endif /* NOSPL */
3914
3915 #ifdef NEWFTP
3916     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
3917         if (cx == XXMAI) {
3918             printf("?Sorry, No MAIL with FTP\n");
3919             return(-9);
3920         }
3921         return(doftpput(cx,0));
3922     }
3923 #endif /* NEWFTP */
3924
3925     for (i = 0; i <= SND_MAX; i++) {    /* Initialize switch values */
3926         pv[i].sval = NULL;              /* to null pointers */
3927         pv[i].ival = -1;                /* and -1 int values */
3928     }
3929 #ifndef NOSPL
3930     range[0] = -1;
3931     range[1] = -1;
3932     sndxin = -1;                        /* Array index */
3933 #endif /* NOSPL */
3934     sndarray = NULL;                    /* Array pointer */
3935
3936 #ifdef UNIXOROSK
3937     g_matchdot = matchdot;              /* Match dot files */
3938 #endif /* UNIXOROSK */
3939     g_recursive = recursive;            /* Recursive sending */
3940     recursive = 0;                      /* Save global value, set local */
3941     debug(F101,"xsend entry fncnv","",fncnv);
3942
3943     /* Preset switch values based on top-level command that called us */
3944
3945     switch (cx) {
3946       case XXMSE:                       /* MSEND */
3947         mlist = 1; break;
3948       case XXCSEN:                      /* CSEND */
3949         pv[SND_CMD].ival = 1; break;
3950       case XXMMOVE:                     /* MMOVE */
3951         mlist = 1;
3952       case XXMOVE:                      /* MOVE */
3953         pv[SND_DEL].ival = 1; break;
3954       case XXRSEN:                      /* RESEND */
3955         pv[SND_BIN].ival = 1;           /* Implies /BINARY */
3956         pv[SND_RES].ival = 1; break;
3957       case XXMAI:                       /* MAIL */
3958         pv[SND_MAI].ival = 1; break;
3959     }
3960
3961     /* Set up chained parse functions... */
3962
3963     cmfdbi(&sw,                         /* First FDB - command switches */
3964            _CMKEY,                      /* fcode */
3965            "Filename, or switch",       /* hlpmsg */
3966            "",                          /* default */
3967            "",                          /* addtl string data */
3968 #ifdef NOMSEND
3969            nsndtab,                     /* addtl numeric data 1: tbl size */
3970 #else
3971            mlist ? nmsndtab : nsndtab,  /* addtl numeric data 1: tbl size */
3972 #endif /* NOMSEND */
3973            4,                           /* addtl numeric data 2: 4 = cmswi */
3974            xxstring,                    /* Processing function */
3975 #ifdef NOMSEND
3976            sndtab,                      /* Keyword table */
3977 #else
3978            mlist ? msndtab : sndtab,
3979 #endif /* NOMSEND */
3980            &sf                          /* Pointer to next FDB */
3981            );
3982     cmfdbi(&sf,                         /* 2nd FDB - file to send */
3983            _CMIFI,                      /* fcode */
3984            "File(s) to send",           /* hlpmsg */
3985            "",                          /* default */
3986            "",                          /* addtl string data */
3987            nolinks,                     /* addtl numeric data 1 */
3988            0,                           /* addtl numeric data 2 */
3989            xxstring,
3990            NULL,
3991            mlist ? &cm : &fl
3992            );
3993     cmfdbi(&fl,                         /* 3rd FDB - command to send from */
3994            _CMFLD,                      /* fcode */
3995            "Command",                   /* hlpmsg */
3996            "",                          /* default */
3997            "",                          /* addtl string data */
3998            0,                           /* addtl numeric data 1 */
3999            0,                           /* addtl numeric data 2 */
4000            xxstring,
4001            NULL,
4002            &cm
4003            );
4004     cmfdbi(&cm,                         /* 4th FDB - Confirmation */
4005            _CMCFM,                      /* fcode */
4006            "",                          /* hlpmsg */
4007            "",                          /* default */
4008            "",                          /* addtl string data */
4009            0,                           /* addtl numeric data 1 */
4010            0,                           /* addtl numeric data 2 */
4011            NULL,
4012            NULL,
4013            NULL
4014            );
4015
4016     while (1) {                         /* Parse 0 or more switches */
4017         x = cmfdb(&sw);                 /* Parse something */
4018         debug(F101,"xsend cmfdb","",x);
4019         if (x < 0)                      /* Error */
4020           goto xsendx;                  /* or reparse needed */
4021         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
4022           break;
4023 /*
4024   They gave a switch, but let's see how they terminated it.
4025   If they ended it with : or =, then we must parse a value.
4026   If they ended it with anything else, then we must NOT parse a value.
4027 */
4028         c = cmgbrk();                   /* Get break character */
4029         getval = (c == ':' || c == '='); /* to see how they ended the switch */
4030         if (getval && !(cmresult.kflags & CM_ARG)) {
4031             printf("?This switch does not take arguments\n");
4032             x = -9;
4033             goto xsendx;
4034         }
4035         if (!getval && (cmgkwflgs() & CM_ARG)) {
4036             printf("?This switch requires an argument\n");
4037             x = -9;
4038             goto xsendx;
4039         }
4040         n = cmresult.nresult;           /* Numeric result = switch value */
4041         debug(F101,"xsend switch","",n);
4042
4043         switch (n) {                    /* Process the switch */
4044           case SND_CMD:                 /* These take no args */
4045             if (nopush) {
4046                 printf("?Sorry, system command access is disabled\n");
4047                 x = -9;
4048                 goto xsendx;
4049             }
4050 #ifdef PIPESEND
4051             else if (sndfilter) {
4052                 printf(
4053 "?Sorry, no SEND /COMMAND or CSEND when SEND FILTER selected\n");
4054                 x = -9;
4055                 goto xsendx;
4056             }
4057 #endif /* PIPESEND */
4058             sw.hlpmsg = "Command, or switch"; /* Change help message */
4059             pv[n].ival = 1;             /* Just set the flag */
4060             pv[SND_ARR].ival = 0;
4061             break;
4062
4063           case SND_REC:                 /* /RECURSIVE */
4064             recursive = 2;              /* Set the real variable */
4065             pv[SND_PTH].ival = PATH_REL; /* Give them relative pathnames */
4066             pv[n].ival = 1;             /* Just set the flag */
4067             break;
4068
4069           case SND_RES:                 /* /RECOVER (resend) */
4070             pv[SND_ARR].ival = 0;
4071             pv[SND_BIN].ival = 1;       /* Implies /BINARY */
4072           case SND_NOB:                 /* /NOBACKUP */
4073           case SND_DEL:                 /* /DELETE */
4074           case SND_SHH:                 /* /QUIET */
4075             pv[n].ival = 1;             /* Just set the flag */
4076             break;
4077
4078 #ifdef UNIXOROSK
4079 /* Like recursive, these are set immediately because they affect cmifi() */
4080           case SND_DOT:                 /* /DOTFILES */
4081             matchdot = 1;
4082             break;
4083           case SND_NOD:                 /* /NODOTFILES */
4084             matchdot = 0;
4085             break;
4086 #endif /* UNIXOROSK */
4087
4088           /* File transfer modes - each undoes the others */
4089
4090           case SND_BIN:                 /* Binary */
4091           case SND_TXT:                 /* Text */
4092           case SND_IMG:                 /* Image */
4093           case SND_LBL:                 /* Labeled */
4094             pv[SND_BIN].ival = 0;
4095             pv[SND_TXT].ival = 0;
4096             pv[SND_IMG].ival = 0;
4097             pv[SND_LBL].ival = 0;
4098             pv[n].ival = 1;
4099             break;
4100
4101 #ifdef CKSYMLINK
4102           case SND_LNK:
4103           case SND_NLK:
4104             nolinks = (n == SND_NLK) ? 2 : 0;
4105             cmfdbi(&sf,                 /* Redo cmifi() */
4106                    _CMIFI,              /* fcode */
4107                    "File(s) to send",   /* hlpmsg */
4108                    "",                  /* default */
4109                    "",                  /* addtl string data */
4110                    nolinks,             /* addtl numeric data 1 */
4111                    0,                   /* addtl numeric data 2 */
4112                    xxstring,
4113                    NULL,
4114                    mlist ? &cm : &fl
4115                    );
4116             break;
4117 #endif /* CKSYMLINK */
4118
4119           case SND_EXC:                 /* Excludes */
4120             if (!getval) break;
4121             if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
4122                 if (x == -3) {
4123                     printf("?Pattern required\n");
4124                     x = -9;
4125                 }
4126                 goto xsendx;
4127             }
4128             if (pv[n].sval) free(pv[n].sval);
4129             y = strlen(s);
4130             if (y > 256) {
4131                 printf("?Pattern too long - 256 max\n");
4132                 x = -9;
4133                 goto xsendx;
4134             }
4135             pv[n].sval = malloc(y+1);
4136             if (pv[n].sval) {
4137                 strcpy(pv[n].sval,s);   /* safe */
4138                 pv[n].ival = 1;
4139             }
4140             break;
4141
4142           case SND_MOV:                 /* MOVE after */
4143           case SND_REN:                 /* RENAME after */
4144             if (!getval) break;
4145             if ((x = cmfld(n == SND_MOV ?
4146            "device and/or directory for source file after sending" :
4147            "new name for source file after sending",
4148                            "",
4149                            &s,
4150                            n == SND_MOV ? xxstring : NULL
4151                            )) < 0) {
4152                 if (x == -3) {
4153                     printf("%s\n", n == SND_MOV ?
4154                            "?Destination required" :
4155                            "?New name required"
4156                            );
4157                     x = -9;
4158                 }
4159                 goto xsendx;
4160             }
4161             if (pv[n].sval) free(pv[n].sval);
4162             s = brstrip(s);
4163             y = strlen(s);
4164             if (y > 0) {
4165                 pv[n].sval = malloc(y+1);
4166                 if (pv[n].sval) {
4167                     strcpy(pv[n].sval,s); /* safe */
4168                     pv[n].ival = 1;
4169                 }
4170             }
4171             break;
4172
4173           case SND_SMA:                 /* Smaller / larger than */
4174           case SND_LAR:
4175             if (!getval) break;
4176             if ((x = cmnum("Size in bytes","0",10,&y,xxstring)) < 0)
4177               goto xsendx;
4178             pv[n].ival = y;
4179             break;
4180
4181           case SND_AFT:                 /* Send /AFTER:date-time */
4182           case SND_BEF:                 /* Send /BEFORE:date-time */
4183           case SND_NAF:                 /* Send /NOT-AFTER:date-time */
4184           case SND_NBE:                 /* Send /NOT-BEFORE:date-time */
4185             if (!getval) break;
4186             if ((x = cmdate("File date-time","",&s,0,xxstring)) < 0) {
4187                 if (x == -3) {
4188                     printf("?Date-time required\n");
4189                     x = -9;
4190                 }
4191                 goto xsendx;
4192             }
4193             if (pv[n].sval) free(pv[n].sval);
4194             pv[n].sval = malloc((int)strlen(s)+1);
4195             if (pv[n].sval) {
4196                 strcpy(pv[n].sval,s);   /* safe */
4197                 pv[n].ival = 1;
4198             }
4199             break;
4200
4201           case SND_MAI:                 /* Send as mail (= MAIL) */
4202 #ifdef IKSD
4203             if (inserver && !ENABLED(en_mai)) {
4204                 printf("?Sorry, sending files as mail is disabled\n");
4205                 return(-9);
4206             }
4207 #endif /* IKSD */
4208             pv[n].ival = 1;
4209             if (!getval) break;
4210             if ((x = cmfld("e-mail address","",&s,xxstring)) < 0) {
4211                 if (x == -3) {
4212                     printf("?address required\n");
4213                     x = -9;
4214                 }
4215                 goto xsendx;
4216             }
4217             s = brstrip(s);
4218             if (pv[n].sval) free(pv[n].sval);
4219             pv[n].sval = malloc((int)strlen(s)+1);
4220             if (pv[n].sval)
4221               strcpy(pv[n].sval,s);     /* safe */
4222             break;
4223
4224           case SND_PRI:                 /* Send to be printed (REMOTE PRINT) */
4225 #ifdef IKSD
4226             if (inserver && !ENABLED(en_mai)) {
4227                 printf("?Sorry, sending files for printing is disabled\n");
4228                 return(-9);
4229             }
4230 #endif /* IKSD */
4231             pv[n].ival = 1;
4232             if (!getval) break;
4233             if ((x = cmfld("Print options","",&s,xxstring)) < 0)
4234               if (x != -3) goto xsendx;
4235             s = brstrip(s);
4236             if (pv[n].sval) free(pv[n].sval);
4237             pv[n].sval = malloc((int)strlen(s)+1);
4238             if (pv[n].sval)
4239               strcpy(pv[n].sval,s);     /* safe */
4240             break;
4241
4242           case SND_ASN:                 /* As-name */
4243             debug(F101,"xsend /as-name getval","",getval);
4244             if (!getval) break;
4245             if ((x = cmfld("Name to send under","",&s,NULL)) < 0) {
4246                 if (x == -3) {
4247                     printf("?name required\n");
4248                     x = -9;
4249                 }
4250                 goto xsendx;
4251             }
4252             s = brstrip(s);
4253             if ((y = strlen(s)) > 0) {
4254                 if (pv[n].sval) free(pv[n].sval);
4255                 pv[n].sval = malloc(y+1);
4256                 if (pv[n].sval) {
4257                     strcpy(pv[n].sval,s); /* safe */
4258                     pv[n].ival = 1;
4259                 }
4260             }
4261             break;
4262
4263           case SND_STA:                 /* Starting position (= PSEND) */
4264             if (!getval) break;
4265             if ((x = cmnum("0-based position","0",10,&y,xxstring)) < 0)
4266               goto xsendx;
4267             pv[n].ival = y;
4268             break;
4269
4270           case SND_PRO:                 /* Protocol to use */
4271             if (!getval) break;
4272             if ((x = cmkey(protos,nprotos,"File-transfer protocol","",
4273                            xxstring)) < 0) {
4274                 if (x == -3) {
4275                     printf("?name of protocol required\n");
4276                     x = -9;
4277                 }
4278                 goto xsendx;
4279             }
4280             pv[n].ival = x;
4281             break;
4282
4283 #ifdef PIPESEND
4284           case SND_FLT:                 /* Filter */
4285             debug(F101,"xsend /filter getval","",getval);
4286             if (!getval) break;
4287             if ((x = cmfld("Filter program to send through","",&s,NULL)) < 0) {
4288                 if (x == -3)
4289                   s = "";
4290                 else
4291                   goto xsendx;
4292             }
4293             if (*s) s = brstrip(s);
4294             y = strlen(s);
4295             for (x = 0; x < y; x++) {   /* Make sure they included "\v(...)" */
4296                 if (s[x] != '\\') continue;
4297                 if (s[x+1] == 'v') break;
4298             }
4299             if (x == y) {
4300                 printf(
4301                 "?Filter must contain a replacement variable for filename.\n"
4302                        );
4303                 x = -9;
4304                 goto xsendx;
4305             }
4306             pv[n].ival = 1;
4307             if (pv[n].sval) {
4308                 free(pv[n].sval);
4309                 pv[n].sval = NULL;
4310             }
4311             if ((y = strlen(s)) > 0) {
4312                 if ((pv[n].sval = malloc(y+1)))
4313                   strcpy(pv[n].sval,s); /* safe */
4314             }
4315             break;
4316 #endif /* PIPESEND */
4317
4318           case SND_PTH:                 /* Pathnames */
4319             if (!getval) {
4320                 pv[n].ival = PATH_REL;
4321                 break;
4322             }
4323             if ((x = cmkey(pathtab,npathtab,"","absolute",xxstring)) < 0)
4324               goto xsendx;
4325             pv[n].ival = x;
4326             break;
4327
4328           case SND_NAM:                 /* Filenames */
4329             if (!getval) break;
4330             if ((x = cmkey(fntab,nfntab,"","converted",xxstring)) < 0)
4331               goto xsendx;
4332             debug(F101,"xsend /filenames","",x);
4333             pv[n].ival = x;
4334             break;
4335
4336 #ifdef CALIBRATE
4337           case SND_CAL:                 /* /CALIBRATE */
4338             if (getval) {
4339                 if ((x = cmnum("number of Kbytes to send",
4340                            "1024",10,&y,xxstring)) < 0)
4341                   goto xsendx;
4342             } else
4343               y = 1024;
4344             pv[n].ival = y;
4345             pv[SND_ARR].ival = 0;
4346             break;
4347 #endif /* CALIBRATE */
4348
4349           case SND_FIL:                 /* Name of file containing filnames */
4350             if (!getval) break;
4351             if ((x = cmifi("Name of file containing list of filenames",
4352                                "",&s,&y,xxstring)) < 0) {
4353                 if (x == -3) {
4354                     printf("?Filename required\n");
4355                     x = -9;
4356                 }
4357                 goto xsendx;
4358             } else if (y) {
4359                 printf("?Wildcards not allowed\n");
4360                 x = -9;
4361                 goto xsendx;
4362             }
4363             if (pv[n].sval)
4364               free(pv[n].sval);
4365             if (s) if (*s) {
4366                 if ((pv[n].sval = malloc((int)strlen(s)+1))) {
4367                     strcpy(pv[n].sval,s);
4368                     pv[n].ival = 1;
4369                     pv[SND_ARR].ival = 0;
4370                 }
4371             }
4372             break;
4373
4374 #ifndef NOSPL
4375           case SND_ARR:                 /* SEND /ARRAY: */
4376             if (!getval) break;
4377             ap = NULL;
4378             if ((x = cmfld("Array name (a single letter will do)",
4379                            "",
4380                            &s,
4381                            NULL
4382                            )) < 0) {
4383                 if (x == -3)
4384                   break;
4385                 else
4386                   return(x);
4387             }
4388             if ((x = arraybounds(s,&(range[0]),&(range[1]))) < 0) {
4389                 printf("?Bad array: %s\n",s);
4390                 return(-9);
4391             }
4392             if (!(ap = a_ptr[x])) {
4393                 printf("?No such array: %s\n",s);
4394                 return(-9);
4395             }
4396             pv[n].ival = 1;
4397             pv[SND_CMD].ival = 0;       /* Undo any conflicting ones... */
4398             pv[SND_RES].ival = 0;
4399             pv[SND_CAL].ival = 0;
4400             pv[SND_FIL].ival = 0;
4401             arrayx = x;
4402             break;
4403 #endif /* NOSPL */
4404
4405           case SND_XPA:                 /* /TRANSPARENT */
4406             pv[n].ival = 1;
4407             break;
4408
4409           case SND_TYP:                 /* Only files of given type */
4410             if (!getval) break;
4411             if ((x = cmkey(txtbin,3,"","all",xxstring)) < 0)
4412               goto xsendx;
4413             pv[n].ival = (x == 2) ? -1 : x;
4414             break;
4415
4416           default:
4417             printf("?Unexpected switch value - %d\n",cmresult.nresult);
4418             x = -9;
4419             goto xsendx;
4420         }
4421     }
4422     debug(F101,"xsend cmresult fcode","",cmresult.fcode);
4423
4424 #ifdef COMMENT
4425     /* List switch parsing results in debug log */
4426     for (i = 0; i <= SND_MAX; i++) {
4427         ckmakmsg(line,LINBUFSIZ,"xsend switch ",ckitoa(i),NULL,NULL);
4428         debug(F111,line, pv[i].sval, pv[i].ival);
4429     }
4430 #endif /* COMMENT */
4431
4432 /* Now we have all switches, plus maybe a filename or command, or nothing */
4433
4434 #ifdef PIPESEND
4435     if (protocol != PROTO_K && pv[SND_CMD].ival > 0) {
4436         printf("?Sorry, %s works only with Kermit protocol\n",
4437                (cx == XXCSEN) ? "CSEND" : "SEND /COMMAND");
4438         x = -9;
4439         goto xsendx;
4440     }
4441     if (pv[SND_RES].ival > 0 || /* /RECOVER */
4442         pv[SND_STA].ival > 0) { /* or /STARTING */
4443         if (sndfilter || pv[SND_FLT].ival > 0) {
4444             printf("?Sorry, no /RECOVER or /START if SEND FILTER selected\n");
4445             x = -9;
4446             goto xsendx;
4447         }
4448     }
4449 #endif /* PIPESEND */
4450
4451     cmarg = "";
4452     cmarg2 = "";
4453     line[0] = NUL;
4454     s = line;
4455     wild = 0;
4456
4457     switch (cmresult.fcode) {           /* How did we get out of switch loop */
4458       case _CMIFI:                      /* Input filename */
4459         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
4460         if (pv[SND_ARR].ival > 0)
4461           cmarg2 = line;
4462         else
4463           wild = cmresult.nresult;      /* Wild flag */
4464         if (!recursive && !wild)
4465           nolinks = 0;
4466         break;
4467       case _CMFLD:                      /* Field */
4468         /* Only allowed with /COMMAND and /ARRAY */
4469         if (pv[SND_CMD].ival < 1 && pv[SND_ARR].ival < 1) {
4470 #ifdef CKROOT
4471             if (ckrooterr)
4472               printf("?Off limits: %s\n",cmresult.sresult);
4473             else
4474 #endif /* CKROOT */
4475               printf("?%s - \"%s\"\n",
4476                    iswild(cmresult.sresult) ?
4477                    "No files match" : "File not found",
4478                    cmresult.sresult
4479                    );
4480             x = -9;
4481             goto xsendx;
4482         }
4483         ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
4484         if (pv[SND_ARR].ival > 0)
4485           cmarg2 = line;
4486         break;
4487       case _CMCFM:                      /* Confirmation */
4488         /* s = ""; */
4489         confirmed = 1;
4490         break;
4491       default:
4492         printf("?Unexpected function code: %d\n",cmresult.fcode);
4493         x = -9;
4494         goto xsendx;
4495     }
4496     debug(F110,"xsend string",s,0);
4497     debug(F101,"xsend confirmed","",confirmed);
4498
4499     /* Save and change protocol and transfer mode */
4500     /* Global values are restored in main parse loop */
4501
4502     g_proto = protocol;                 /* Save current global protocol */
4503     g_urpsiz = urpsiz;
4504     g_spsizf = spsizf;
4505     g_spsiz = spsiz;
4506     g_spsizr = spsizr;
4507     g_spmax = spmax;
4508     g_wslotr = wslotr;
4509     g_prefixing = prefixing;
4510     g_fncact = fncact;
4511     g_fncnv = fncnv;
4512     g_fnspath = fnspath;
4513     g_fnrpath = fnrpath;
4514     g_xfrxla = xfrxla;
4515
4516     if (pv[SND_PRO].ival > -1) {        /* Change according to switch */
4517         protocol = pv[SND_PRO].ival;
4518         if (ptab[protocol].rpktlen > -1) /* copied from initproto() */
4519             urpsiz = ptab[protocol].rpktlen;
4520         if (ptab[protocol].spktflg > -1)
4521             spsizf = ptab[protocol].spktflg;
4522         if (ptab[protocol].spktlen > -1) {
4523             spsiz = ptab[protocol].spktlen;
4524             if (spsizf)
4525               spsizr = spmax = spsiz;
4526         }
4527         if (ptab[protocol].winsize > -1)
4528             wslotr = ptab[protocol].winsize;
4529         if (ptab[protocol].prefix > -1)
4530             prefixing = ptab[protocol].prefix;
4531         if (ptab[protocol].fnca > -1)
4532             fncact  = ptab[protocol].fnca;
4533         if (ptab[protocol].fncn > -1)
4534             fncnv   = ptab[protocol].fncn;
4535         if (ptab[protocol].fnsp > -1)
4536             fnspath = ptab[protocol].fnsp;
4537         if (ptab[protocol].fnrp > -1)
4538             fnrpath = ptab[protocol].fnrp;
4539     }
4540     debug(F101,"xsend protocol","",protocol);
4541
4542     if (pv[SND_NOB].ival > -1) {        /* /NOBACKUP (skip backup file) */
4543         g_skipbup = skipbup;
4544         skipbup = 1;
4545     }
4546     if (pv[SND_REC].ival > 0)           /* /RECURSIVE */
4547       recursive = 2;
4548
4549     if (pv[SND_TYP].ival > -1) {        /* /TYPE */
4550         xfiletype = pv[SND_TYP].ival;
4551         if (xfiletype == 2)
4552           xfiletype = -1;
4553     }
4554     g_binary = binary;                  /* Save global transfer mode */
4555 #ifdef PATTERNS
4556     g_patterns = patterns;              /* Save FILE PATTERNS setting */
4557 #endif /* PATTERNS */
4558     if (pv[SND_BIN].ival > 0) {         /* Change according to switch */
4559         /* If they said /BINARY they mean /BINARY */
4560         patterns = 0;                   /* So no pattern-based switching */
4561         g_xfermode = xfermode;          /* or automatic transfer mode */
4562         xfermode = XMODE_M;
4563         binary = XYFT_B;
4564         debug(F101,"doxsend /BINARY xfermode","",xfermode);
4565     } else if (pv[SND_TXT].ival > 0) {  /* Ditto for /TEXT */
4566         patterns = 0;
4567         g_xfermode = xfermode;
4568         xfermode = XMODE_M;
4569         binary = XYFT_T;
4570         debug(F101,"doxsend /TEXT xfermode","",xfermode);
4571     } else if (pv[SND_IMG].ival > 0) {
4572 #ifdef VMS
4573         binary = XYFT_I;
4574 #else
4575         binary = XYFT_B;
4576 #endif /* VMS */
4577     }
4578 #ifdef CK_LABELED
4579     else if (pv[SND_LBL].ival > 0) {
4580         binary = XYFT_L;
4581     }
4582 #endif /* CK_LABELED */
4583     debug(F101,"xsend binary","",binary);
4584
4585     if (pv[SND_XPA].ival > 0)           /* /TRANSPARENT */
4586       xfrxla = 0;                       /* Don't translate character sets */
4587
4588     /* Check for legal combinations of switches, filenames, etc */
4589
4590 #ifdef PIPESEND
4591     if (pv[SND_CMD].ival > 0) { /* COMMAND - strip any braces */
4592         debug(F110,"SEND /COMMAND before stripping",s,0);
4593         s = brstrip(s);
4594         debug(F110,"SEND /COMMAND after stripping",s,0);
4595         if (!*s) {
4596             printf("?Sorry, a command to send from is required\n");
4597             x = -9;
4598             goto xsendx;
4599         }
4600         cmarg = s;
4601     }
4602 #endif /* PIPESEND */
4603
4604 /* Set up /MOVE and /RENAME */
4605
4606     if (pv[SND_DEL].ival > 0 &&
4607         (pv[SND_MOV].ival > 0 || pv[SND_REN].ival > 0)) {
4608         printf("?Sorry, /DELETE conflicts with /MOVE or /RENAME\n");
4609         x = -9;
4610         goto xsendx;
4611     }
4612 #ifdef CK_TMPDIR
4613     if (pv[SND_MOV].ival > 0) {
4614         int len;
4615         char * p = pv[SND_MOV].sval;
4616 #ifdef CK_LOGIN
4617         if (isguest) {
4618             printf("?Sorry, /MOVE-TO not available to guests\n");
4619             x = -9;
4620             goto xsendx;
4621         }
4622 #endif /* CK_LOGIN */
4623         len = strlen(p);
4624         if (!isdir(p)) {                /* Check directory */
4625 #ifdef CK_MKDIR
4626             char * s = NULL;
4627             s = (char *)malloc(len + 4);
4628             if (s) {
4629                 strcpy(s,p);            /* safe */
4630 #ifdef datageneral
4631                 if (s[len-1] != ':') { s[len++] = ':'; s[len] = NUL; }
4632 #else
4633                 if (s[len-1] != '/') { s[len++] = '/'; s[len] = NUL; }
4634 #endif /* datageneral */
4635                 s[len++] = 'X';
4636                 s[len] = NUL;
4637                 x = zmkdir(s);
4638                 free(s);
4639                 if (x < 0) {
4640                     printf("?Can't create \"%s\"\n",p);
4641                     x = -9;
4642                     goto xsendx;
4643                 }
4644             }
4645 #else
4646             printf("?Directory \"%s\" not found\n",p);
4647             x = -9;
4648             goto xsendx;
4649 #endif /* CK_MKDIR */
4650         }
4651         zfnqfp(p,LINBUFSIZ,tmpbuf);
4652         makestr(&snd_move,tmpbuf);
4653     }
4654 #endif /* CK_TMPDIR */
4655
4656     if (pv[SND_REN].ival > 0) {         /* /RENAME */
4657         char * p = pv[SND_REN].sval;
4658 #ifdef CK_LOGIN
4659         if (isguest) {
4660             printf("?Sorry, /RENAME-TO not available to guests\n");
4661             x = -9;
4662             goto xsendx;
4663         }
4664 #endif /* CK_LOGIN */
4665         if (!p) p = "";
4666         if (!*p) {
4667             printf("?New name required for /RENAME\n");
4668             x = -9;
4669             goto xsendx;
4670         }
4671         p = brstrip(p);
4672 #ifndef NOSPL
4673     /* If name given is wild, rename string must contain variables */
4674         if (wild) {
4675             char * s = tmpbuf;
4676             x = TMPBUFSIZ;
4677             zzstring(p,&s,&x);
4678             if (!strcmp(tmpbuf,p)) {
4679                 printf(
4680     "?/RENAME for file group must contain variables such as \\v(filename)\n"
4681                        );
4682                 x = -9;
4683                 goto xsendx;
4684             }
4685         }
4686 #endif /* NOSPL */
4687         makestr(&snd_rename,p);
4688     }
4689
4690 /* Handle /RECOVER and /START */
4691
4692 #ifdef CK_RESEND
4693     if (pv[SND_RES].ival > 0 && binary != XYFT_B && !filepeek
4694 #ifdef PATTERNS
4695         && !patterns
4696 #else
4697 #ifdef VMS
4698 /* VMS sets text/binary automatically later when it opens the file */
4699         && 0
4700 #endif /* VMS */
4701 #endif /* PATTERNS */
4702         ) {
4703         printf("?Sorry, /BINARY required\n");
4704         x = -9;
4705         goto xsendx;
4706     }
4707     if (pv[SND_STA].ival > 0) {         /* /START */
4708         if (wild) {
4709             printf("?Sorry, wildcards not permitted with /START\n");
4710             x = -9;
4711             goto xsendx;
4712         }
4713         if (sizeof(int) < 4) {
4714             printf("?Sorry, this command needs 32-bit integers\n");
4715             x = -9;
4716             goto xsendx;
4717         }
4718 #ifdef CK_XYZ
4719         if (protocol != PROTO_K) {
4720             printf("?Sorry, SEND /START works only with Kermit protocol\n");
4721             x = -9;
4722             goto xsendx;
4723         }
4724 #endif /* CK_XYZ */
4725     }
4726 #ifdef CK_XYZ
4727     if (pv[SND_RES].ival > 0) {
4728         if (protocol != PROTO_K && protocol != PROTO_Z) {
4729             printf(
4730     "Sorry, /RECOVER is possible only with Kermit or ZMODEM protocol\n"
4731                    );
4732             x = -9;
4733             goto xsendx;
4734         }
4735     }
4736 #endif /* CK_XYZ */
4737 #endif /* CK_RESEND */
4738
4739     if (protocol == PROTO_K) {
4740         if ((pv[SND_MAI].ival > 0 ||    /* MAIL */
4741              pv[SND_PRI].ival > 0 ||    /* PRINT */
4742              pv[SND_RES].ival > 0       /* RESEND */
4743              ) &&
4744             (!atdiso || !atcapr)) {     /* Disposition attribute off? */
4745             printf("?Sorry, ATTRIBUTE DISPOSITION must be ON\n");
4746             x = -9;
4747             goto xsendx;
4748         }
4749     }
4750
4751 #ifdef CK_XYZ
4752     if (wild && (protocol == PROTO_X || protocol == PROTO_XC)) {
4753         printf(
4754 "Sorry, you can only send one file at a time with XMODEM protocol\n"
4755                );
4756         x = -9;
4757         goto xsendx;
4758     }
4759 #endif /* CK_XYZ */
4760
4761     if (!confirmed) {                   /* CR not typed yet, get more fields */
4762         char *m;
4763         if (mlist) {                    /* MSEND or MMOVE */
4764             nfils = 0;                  /* We already have the first one */
4765 #ifndef NOMSEND
4766             msfiles[nfils++] = line;    /* Store pointer */
4767             lp = line + (int)strlen(line) + 1; /* Point past it */
4768             debug(F111,"xsend msend",msfiles[nfils-1],nfils-1);
4769             while (1) {                 /* Get more filenames */
4770                 char *p;
4771                 if ((x = cmifi("Names of files to send, separated by spaces",
4772                                "", &s,&y,xxstring)) < 0) {
4773                     if (x != -3)
4774                       goto xsendx;
4775                     if ((x = cmcfm()) < 0)
4776                       goto xsendx;
4777                     break;
4778                 }
4779                 msfiles[nfils++] = lp;  /* Got one, count it, point to it, */
4780                 p = lp;                 /* remember pointer, */
4781                 while ((*lp++ = *s++))  /* and copy it into buffer */
4782                   if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
4783                       printf("?MSEND list too long\n");
4784                       line[0] = NUL;
4785                       x = -9;
4786                       goto xsendx;
4787                   }
4788                 debug(F111,"xsend msend",msfiles[nfils-1],nfils-1);
4789                 if (nfils == 1) fspec[0] = NUL; /* Take care of \v(filespec) */
4790 #ifdef ZFNQFP
4791                 zfnqfp(p,TMPBUFSIZ,tmpbuf);
4792                 p = tmpbuf;
4793 #endif /* ZFNQFP */
4794                 if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
4795                     strcat(fspec,p);    /* safe */
4796                     strcat(fspec," ");  /* safe */
4797                 } else
4798 #ifdef COMMENT
4799                   printf("WARNING - \\v(filespec) buffer overflow\n");
4800 #else
4801                   debug(F101,"doxsend filespec buffer overflow","",0);
4802 #endif /* COMMENT */
4803             }
4804 #endif /* NOMSEND */
4805         } else {                        /* Regular SEND */
4806             char *p; int y;
4807             nfils = -1;
4808             if (pv[SND_MAI].ival > 0)
4809               m = (pv[SND_MAI].sval) ?
4810                 "e-mail address (optional)" :
4811                   "e-mail address (required)";
4812             else if (pv[SND_PRI].ival > 0)
4813               m = "printer options (optional)";
4814             else if (wild)
4815               m =
4816 "\nOptional as-name template containing replacement variables \
4817 like \\v(filename)";
4818             else
4819               m = "Optional name to send it with";
4820             if ((x = cmtxt(m,"",&p,NULL)) < 0)
4821               goto xsendx;
4822             if (!p) p = "";
4823             if (*p) {                   /* If some text was given... */
4824                 p = brstrip(p);         /* Replace /AS-NAME: value if any */
4825                 if ((y = strlen(p)) > 0) {
4826                     if (pv[SND_MAI].ival > 0) {
4827                         makestr(&pv[SND_MAI].sval, p);
4828                     } else {
4829                         if (pv[SND_ASN].sval) free(pv[SND_ASN].sval);
4830                         pv[SND_ASN].sval = malloc(y+1);
4831                         if (pv[SND_ASN].sval) {
4832                             strcpy(pv[SND_ASN].sval,p); /* safe */
4833                             pv[SND_ASN].ival = 1;
4834                         }
4835                     }
4836                 }
4837             }
4838         }
4839     }
4840     /* Set cmarg2 from as-name, however we got it. */
4841
4842     if (pv[SND_ASN].ival > 0 && pv[SND_ASN].sval && !*cmarg2) {
4843         int x;
4844         x = strlen(line);
4845         ckstrncpy(line+x+2,pv[SND_ASN].sval,LINBUFSIZ-x-1);
4846         cmarg2 = line+x+2;
4847         debug(F110,"doxsend cmarg2",cmarg2,0);
4848     }
4849
4850 #ifndef NOFRILLS
4851     if ((pv[SND_MAI].ival > 0) && (pv[SND_PRI].ival > 0)) {
4852         printf("Sorry, /MAIL and /PRINT are conflicting options\n");
4853         x = -9;
4854         goto xsendx;
4855     }
4856     n = 0;                              /* /MAIL or /PRINT? */
4857     if (pv[SND_MAI].ival > 0)
4858       n = SND_MAI;
4859     else if (pv[SND_PRI].ival > 0)
4860       n = SND_PRI;
4861     if (n) {                            /* Yes... */
4862 #ifdef DEBUG
4863         char * p;
4864         if (n == SND_MAI)
4865           p = "/MAIL";
4866         else
4867           p = "/PRINT";
4868         debug(F111,"xsend",p,n);
4869 #endif /* DEBUG */
4870 #ifdef CK_XYZ
4871         if (protocol != PROTO_K) {
4872             printf("Sorry, %s available only with Kermit protocol\n",
4873                    (n == SND_MAI) ? "/MAIL" : "/PRINT"
4874                    );
4875             x = -9;
4876             goto xsendx;
4877         }
4878 #endif /* CK_XYZ */
4879         debug(F101,"xsend print/mail wild","",wild);
4880         *optbuf = NUL;                  /* Wipe out any old options */
4881         s = pv[n].sval;                 /* mail address or print switch val */
4882         if (!s) s = "";
4883         debug(F110,"doxsend mail address or printer options",s,0);
4884         if (n == SND_MAI && !*s) {
4885             printf("?E-mail address required\n");
4886             x = -9;
4887             goto xsendx;
4888         } else if ((int)strlen(s) > 94) { /* Ensure legal size */
4889             printf("?%s too long\n",
4890                    (n == SND_MAI) ?
4891                    "E-mail address" :
4892                    "Print option string"
4893                    );
4894             x = -9;
4895             goto xsendx;
4896         }
4897         ckstrncpy(optbuf,s,OPTBUFLEN);  /* OK, copy to option buffer */
4898         cmarg = line;                   /* File to send */
4899         if (n == SND_MAI) {
4900             debug(F110,"xsend mailing",cmarg,0);
4901             debug(F110,"xsend address:",optbuf,0);
4902             rmailf = 1;
4903         } else {
4904             debug(F110,"xsend printing",cmarg,0);
4905             debug(F110,"xsend options",optbuf,0);
4906             rprintf = 1;
4907         }
4908     }
4909 #endif /* NOFRILLS */
4910
4911 #ifdef CALIBRATE
4912     if (pv[SND_CAL].ival > 0) {         /* Handle /CALIBRATE */
4913         if (confirmed) {
4914             calibrate = pv[SND_CAL].ival * 1024L;
4915             sndsrc = -9;
4916             nfils = 1;
4917             wild = 0;
4918 #ifndef NOMSEND
4919             addlist = 0;
4920 #endif /* NOMSEND */
4921             ckstrncpy(line,"CALIBRATION",LINBUFSIZ);
4922             s = cmarg = line;
4923             if (!cmarg2) cmarg2 = "";
4924             debug(F110,"doxsend cmarg2 calibrate",cmarg2,0);
4925         } else if (line[0]) {
4926             calibrate = 0L;
4927             pv[SND_CAL].ival = 0L;
4928         }
4929     }
4930 #endif /* CALIBRATE */
4931
4932     if (pv[SND_FIL].ival > 0) {
4933         if (confirmed && !calibrate) {
4934             if (zopeni(ZMFILE,pv[SND_FIL].sval) < 1) {
4935                 debug(F110,"xsend can't open",pv[SND_FIL].sval,0);
4936                 printf("?Failure to open %s\n",filefile);
4937                 x = -9;
4938                 goto xsendx;
4939             }
4940             makestr(&filefile,pv[SND_FIL].sval); /* Open, remember name */
4941             debug(F110,"xsend opened",filefile,0);
4942             wild = 1;
4943         }
4944     }
4945
4946     /* SEND alone... */
4947
4948 #ifndef NOSPL
4949     if (confirmed && pv[SND_ARR].ival > 0) {
4950         if (!*cmarg2) {
4951             sndxnam[7] = (char)((arrayx == 1) ? 64 : arrayx + ARRAYBASE);
4952             cmarg2 = sndxnam;
4953         }
4954         cmarg = "";
4955         goto sendend;
4956     }
4957 #endif /* NOSPL */
4958
4959     if (confirmed && !line[0] && !filefile && !calibrate) {
4960 #ifndef NOMSEND
4961         if (filehead) {                 /* OK if we have a SEND-LIST */
4962             nfils = filesinlist;
4963             sndsrc = nfils;             /* Like MSEND */
4964             addlist = 1;                /* But using a different list... */
4965             filenext = filehead;
4966             goto sendend;
4967         }
4968 #endif /* NOMSEND */
4969         printf("?Filename required but not given\n");
4970         x = -9;
4971         goto xsendx;
4972     }
4973
4974     /* Not send-list or array */
4975
4976 #ifndef NOMSEND
4977     addlist = 0;                        /* Don't use SEND-LIST. */
4978     filenext = NULL;
4979 #endif /* NOMSEND */
4980
4981     if (mlist) {                        /* MSEND or MMOVE */
4982 #ifndef NOMSEND
4983         cmlist = msfiles;               /* List of files to send */
4984         sndsrc = nfils;
4985         cmarg2 = "";
4986         sendstart = 0L;
4987 #endif /* NOMSEND */
4988 #ifdef PIPESEND
4989         pipesend = 0;
4990 #endif /* PIPESEND */
4991     } else if (filefile) {              /* File contains list of filenames */
4992         s = "";
4993         cmarg = "";
4994         cmarg2 = "";
4995         line[0] = NUL;
4996         nfils = 1;
4997         sndsrc = 1;
4998
4999     } else if (!calibrate && pv[SND_ARR].ival < 1 && pv[SND_CMD].ival < 1) {
5000
5001         nfils = sndsrc = -1;    /* Not MSEND, MMOVE, /LIST, or /ARRAY */
5002         if (                            /* or /COMMAND */
5003
5004 #ifndef NOFRILLS
5005             !rmailf && !rprintf         /* Not MAIL or PRINT */
5006 #else
5007             1
5008 #endif /* NOFRILLS */
5009             ) {
5010             int y = 1;
5011             if (!wild)
5012               y = zchki(s);
5013             if (y < 0) {
5014                 printf("?Read access denied - \"%s\"\n", s);
5015                 x = -9;
5016                 goto xsendx;
5017             }
5018             if (s != line)              /* We might already have done this. */
5019               ckstrncpy(line,s,LINBUFSIZ); /* Copy of string just parsed. */
5020             else
5021               debug(F110,"doxsend line=s",line,0);
5022             cmarg = line;               /* File to send */
5023         }
5024         zfnqfp(cmarg,fspeclen,fspec);
5025     }
5026     if (!mlist) {                       /* For all but MSEND... */
5027 #ifdef PIPESEND
5028         if (pv[SND_CMD].ival > 0)       /* /COMMAND sets pipesend flag */
5029           pipesend = 1;
5030         debug(F101,"xsend /COMMAND pipesend","",pipesend);
5031         if (pipesend && filefile) {
5032             printf("?Invalid switch combination\n");
5033             x = -9;
5034             goto xsendx;
5035         }
5036 #endif /* PIPESEND */
5037
5038 #ifndef NOSPL
5039     /* If as-name given and filespec is wild, as-name must contain variables */
5040         debug(F111,"doxsend cmarg2 wild",cmarg2,wild);
5041         if (wild && *cmarg2) {
5042             char * s = tmpbuf;
5043             x = TMPBUFSIZ;
5044             zzstring(cmarg2,&s,&x);
5045             if (!strcmp(tmpbuf,cmarg2)) {
5046                 printf(
5047     "?As-name for file group must contain variables such as \\v(filename)\n"
5048                        );
5049                 x = -9;
5050                 goto xsendx;
5051             }
5052         }
5053 #endif /* NOSPL */
5054
5055     /* Strip braces from as-name */
5056         debug(F110,"xsend cmarg2 before stripping",cmarg2,0);
5057         cmarg2 = brstrip(cmarg2);
5058         debug(F110,"xsend filename",cmarg,0);
5059         debug(F110,"xsend as-name",cmarg2,0);
5060
5061     /* Copy as-name to a safe place */
5062
5063         if (asnbuf) {
5064             free(asnbuf);
5065             asnbuf = NULL;
5066         }
5067         if ((y = strlen(cmarg2)) > 0) {
5068             asnbuf = (char *) malloc(y + 1);
5069             if (asnbuf) {
5070                 strcpy(asnbuf,cmarg2);  /* safe */
5071                 cmarg2 = asnbuf;
5072             } else cmarg2 = "";
5073         }
5074
5075 #ifdef CK_RESEND
5076         debug(F111,"xsend pv[SND_STA].ival","",pv[SND_STA].ival);
5077         if (pv[SND_STA].ival > -1) {    /* /START position */
5078             if (wild) {
5079                 printf("?/STARTING-AT may not be used with multiple files.\n");
5080                 x = -9;
5081                 goto xsendx;
5082             } else
5083               sendstart = pv[SND_STA].ival;
5084         } else
5085           sendstart = 0L;
5086         debug(F101,"xsend /STARTING","",sendstart);
5087 #endif /* CK_RESEND */
5088     }
5089
5090 sendend:                                /* Common successful exit */
5091     moving = 0;
5092     if (pv[SND_SHH].ival > 0) {         /* SEND /QUIET... */
5093         g_displa = fdispla;
5094         fdispla = 0;
5095         debug(F101,"xsend display","",fdispla);
5096     }
5097
5098 #ifndef NOSPL                           /* SEND /ARRAY... */
5099     if (pv[SND_ARR].ival > 0) {
5100         if (!ap) { x = -2; goto xsendx; } /* (shouldn't happen) */
5101         if (range[0] == -1)             /* If low end of range not specified */
5102           range[0] = 1;                 /* default to 1 */
5103         if (range[1] == -1)             /* If high not specified */
5104           range[1] = a_dim[arrayx];     /* default to size of array */
5105         if ((range[0] < 0) ||           /* Check range */
5106             (range[0] > a_dim[arrayx]) ||
5107             (range[1] < range[0]) ||
5108             (range[1] > a_dim[arrayx])) {
5109             printf("?Bad array range - [%d:%d]\n",range[0],range[1]);
5110             x = -9;
5111             goto xsendx;
5112         }
5113         sndarray = ap;                  /* Array pointer */
5114         sndxin = arrayx;                /* Array index */
5115         sndxlo = range[0];              /* Array range */
5116         sndxhi = range[1];
5117         sndxnam[7] = (char)((sndxin == 1) ? 64 : sndxin + ARRAYBASE);
5118
5119 #ifdef COMMENT
5120         printf("SENDING FROM ARRAY: &%c[]...\n", /* debugging */
5121                (sndxin == 1) ? 64 : sndxin + ARRAYBASE);
5122         printf("Lo=%d\nHi=%d\n", sndxlo, sndxhi);
5123         printf("cmarg=[%s]\ncmarg2=[%s]\n", cmarg, cmarg2);
5124         while ((x = agnbyte()) > -1) {
5125             putchar((char)x);
5126         }
5127         return(1);
5128 #endif /* COMMENT */
5129     }
5130 #endif /* NOSPL */
5131
5132     if (pv[SND_ARR].ival < 1) {         /* File selection & disposition... */
5133
5134         if (pv[SND_DEL].ival > 0)       /* /DELETE was specified */
5135           moving = 1;
5136         debug(F101,"xsend /DELETE","",moving);
5137         if (pv[SND_AFT].ival > 0)       /* Copy SEND criteria */
5138           ckstrncpy(sndafter,pv[SND_AFT].sval,19);
5139         if (pv[SND_BEF].ival > 0)
5140           ckstrncpy(sndbefore,pv[SND_BEF].sval,19);
5141         if (pv[SND_NAF].ival > 0)
5142           ckstrncpy(sndnafter,pv[SND_NAF].sval,19);
5143         if (pv[SND_NBE].ival > 0)
5144           ckstrncpy(sndnbefore,pv[SND_NBE].sval,19);
5145         if (pv[SND_EXC].ival > 0)
5146           makelist(pv[SND_EXC].sval,sndexcept,NSNDEXCEPT);
5147         if (pv[SND_SMA].ival > -1)
5148           sndsmaller = pv[SND_SMA].ival;
5149         if (pv[SND_LAR].ival > -1)
5150           sndlarger = pv[SND_LAR].ival;
5151         if (pv[SND_NAM].ival > -1) {
5152             g_fncnv = fncnv;            /* Save global value */
5153             fncnv = pv[SND_NAM].ival;
5154             debug(F101,"xsend fncnv","",fncnv);
5155         }
5156         if (pv[SND_PTH].ival > -1) {
5157             g_spath = fnspath;          /* Save global values */
5158             fnspath = pv[SND_PTH].ival;
5159 #ifndef NZLTOR
5160             if (fnspath != PATH_OFF) {
5161                 g_fncnv = fncnv;        /* Bad bad... */
5162                 fncnv = XYFN_C;
5163             }
5164 #endif /* NZLTOR */
5165             debug(F101,"xsend fnspath","",fnspath);
5166             debug(F101,"xsend fncnv","",fncnv);
5167         }
5168     }
5169
5170 #ifdef PIPESEND
5171     if (pv[SND_FLT].ival > 0) {
5172         makestr(&sndfilter,pv[SND_FLT].sval);
5173         debug(F110,"xsend /FILTER", sndfilter, 0);
5174     }
5175 #endif /* PIPESEND */
5176
5177 #ifdef CK_APC
5178 /* MOVE not allowed in APCs */
5179     if (moving &&
5180         (apcactive == APC_LOCAL || apcactive == APC_REMOTE)
5181         && !(apcstatus & APC_UNCH))
5182       return(success = 0);
5183 #endif /* CK_APC */
5184 #ifdef IKS_OPTION
5185     if (
5186 #ifdef CK_XYZ
5187         protocol == PROTO_K &&
5188 #endif /* CK_XYZ */
5189         !iks_wait(KERMIT_REQ_START,1)) {
5190         printf("?A Kermit Server is not available to process this command.\n");
5191         printf("?Start a RECEIVE command to complement this command.\n");
5192     }
5193 #endif /* IKS_OPTION */
5194
5195 #ifdef IKSD
5196 #ifdef CK_LOGIN
5197     if (moving && inserver && isguest) {
5198         printf("?File deletion not allowed for guests.\n");
5199         return(-9);
5200     }
5201 #endif /* CK_LOGIN */
5202 #endif /* IKSD */
5203
5204     sstate = 's';                       /* Set start state to SEND */
5205     sndcmd = 1;
5206 #ifdef CK_RESEND
5207     if (pv[SND_RES].ival > 0)           /* Send sendmode appropriately */
5208       sendmode = SM_RESEND;
5209     else if (pv[SND_STA].ival > 0)
5210       sendmode = SM_PSEND;
5211     else
5212 #endif /* CK_RESEND */
5213     if (mlist)
5214       sendmode = SM_MSEND;
5215     else
5216       sendmode = SM_SEND;
5217 #ifdef MAC
5218     what = W_SEND;
5219     scrcreate();
5220 #endif /* MAC */
5221     if (local && pv[SND_SHH].ival != 0) { /* If in local mode, */
5222         displa = 1;                     /* turn on file transfer display */
5223     }
5224     x = 0;
5225
5226   xsendx:                               /* Common exit, including failure */
5227     debug(F101,"doxsend sndsrc","",sndsrc);
5228     for (i = 0; i <= SND_MAX; i++) {    /* Free malloc'd memory */
5229         if (pv[i].sval)
5230           free(pv[i].sval);
5231     }
5232     return(x);
5233 }
5234 #endif /* NOXFER */
5235
5236 #ifndef NOLOCAL
5237 /*  D O X C O N N  --  CONNECT command parsing with switches */
5238
5239 #ifdef XLIMITS
5240 #define XLIMORTRIGGER
5241 #else
5242 #ifdef CK_TRIGGER
5243 #define XLIMORTRIGGER
5244 #endif /* CK_TRIGGER */
5245 #endif /*  XLIMITS */
5246
5247 #ifdef CKTIDLE
5248 int tt_idlelimit = 0;                   /* Terminal idle limit */
5249 int tt_idleact = IDLE_RET;              /* Terminal idle action */
5250 #endif /* CKTIDLE */
5251
5252 #ifdef OS2                              /* K95 only: */
5253 extern int
5254   tt_idlesnd_tmo;                       /*   Idle interval */
5255 int tt_timelimit = 0;                   /*   Time limit, 0 = none */
5256 extern char *                           /* Parse results - strings: */
5257   tt_idlesnd_str;                       /*   Idle string */
5258 #endif /* OS2 */
5259
5260 #ifdef CK_TRIGGER
5261 extern char *tt_trigger[];
5262 extern CHAR *tt_trmatch[];
5263 extern char *triggerval;
5264 static char *g_tt_trigger[TRIGGERS];
5265 #endif /* CK_TRIGGER */
5266
5267 #ifdef OS2
5268 static int g_tt_idlesnd_tmo, g_tt_timelimit; /* For saving and restoring */
5269 static int g_tt_idlelimit, g_tt_saved = 0;
5270 static char * g_tt_idlesnd_str;         /* global settings */
5271 #endif /* OS2 */
5272
5273 static struct stringint {               /* Temporary array for switch values */
5274     char * sval;
5275     int ival;
5276 } pv[CONN_MAX+1];
5277
5278 VOID
5279 resconn() {
5280     int i;
5281
5282 #ifdef OS2
5283     if ( g_tt_saved ) {
5284         tt_idlelimit   = g_tt_idlelimit;
5285         tt_idlesnd_tmo = g_tt_idlesnd_tmo;
5286         tt_timelimit   = g_tt_timelimit;
5287         tt_idlesnd_str = g_tt_idlesnd_str;
5288         g_tt_saved = 0;
5289     }
5290 #endif /* OS2 */
5291
5292 #ifdef CK_TRIGGER
5293     for (i = 0; i < TRIGGERS; i++)
5294       tt_trigger[i] = g_tt_trigger[i];
5295 #endif /* CK_TRIGGER */
5296
5297     for (i = 0; i <= CONN_MAX; i++) {   /* Free malloc'd memory */
5298         if (pv[i].sval)
5299           free(pv[i].sval);
5300         pv[i].sval = NULL;
5301     }
5302 }
5303
5304 int
5305 doxconn(cx) int cx; {
5306     int c, i, n;                        /* Workers */
5307     int x, y;
5308     int getval = 0;                     /* Whether to get switch value */
5309     int async = 0;                      /* Make an async connect */
5310     struct FDB sw, cm;                  /* FDBs for each parse function */
5311     extern FILE * tfile[];
5312     extern char * macp[];
5313
5314 #ifdef OS2
5315     g_tt_idlesnd_tmo = tt_idlesnd_tmo;  /* Save global settings */
5316     g_tt_timelimit   = tt_timelimit;
5317     g_tt_idlelimit   = tt_idlelimit;
5318     g_tt_idlesnd_str = tt_idlesnd_str;
5319     g_tt_saved = 1;
5320 #endif /* OS2 */
5321
5322 #ifdef CK_TRIGGER
5323     if (!tt_trigger[0]) {               /* First initialization */
5324         for (i = 1; i < TRIGGERS; i++)
5325           tt_trigger[i] = NULL;
5326     }
5327     for (i = 0; i < TRIGGERS; i++)
5328       g_tt_trigger[i] = tt_trigger[i];
5329     if (triggerval) {
5330         free(triggerval);
5331         triggerval = NULL;
5332     }
5333 #endif /* CK_TRIGGER */
5334
5335     for (i = 0; i <= CONN_MAX; i++) {   /* Initialize switch values */
5336         pv[i].sval = NULL;              /* to null pointers */
5337         pv[i].ival = -1;                /* and -1 int values */
5338     }
5339     if (cx == XXCQ)                     /* CQ == CONNECT /QUIETLY */
5340       pv[CONN_NV].ival = 1;
5341
5342     /* Set up chained parse functions... */
5343
5344     cmfdbi(&sw,                         /* First FDB - command switches */
5345            _CMKEY,                      /* fcode */
5346            "Switch",                    /* hlpmsg */
5347            "",                          /* default */
5348            "",                          /* addtl string data */
5349            nconntab,                    /* addtl numeric data 1: tbl size */
5350            4,                           /* addtl numeric data 2: 4 = cmswi */
5351            xxstring,                    /* Processing function */
5352            conntab,                     /* Keyword table */
5353            &cm                          /* Pointer to next FDB */
5354            );
5355     cmfdbi(&cm,                         /* 2nd FDB - Confirmation */
5356            _CMCFM,                      /* fcode */
5357            "",                          /* hlpmsg */
5358            "",                          /* default */
5359            "",                          /* addtl string data */
5360            0,                           /* addtl numeric data 1 */
5361            0,                           /* addtl numeric data 2 */
5362            NULL,
5363            NULL,
5364            NULL
5365            );
5366
5367     while (1) {                         /* Parse 0 or more switches */
5368         x = cmfdb(&sw);                 /* Parse switch or confirmation */
5369         debug(F101,"doxconn cmfdb","",x);
5370         if (x < 0) {                    /* Error */
5371             if (x == -9 || x == -2)
5372               printf("?No switches match - \"%s\"\n",atmbuf);
5373             goto xconnx;                /* or reparse needed */
5374         }
5375         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
5376           break;
5377         c = cmgbrk();                   /* Get break character */
5378         getval = (c == ':' || c == '='); /* to see how they ended the switch */
5379         if (getval && !(cmresult.kflags & CM_ARG)) {
5380             printf("?This switch does not take arguments\n");
5381             x = -9;
5382             goto xconnx;
5383         }
5384         if (!getval && (cmgkwflgs() & CM_ARG)) {
5385             printf("?This switch requires an argument\n");
5386             return(-9);
5387         }
5388         n = cmresult.nresult;           /* Numeric result = switch value */
5389         debug(F101,"doxconn switch","",n);
5390
5391         switch (n) {                    /* Process the switch */
5392 #ifdef OS2
5393           case CONN_AS:                 /* Asynchronous */
5394             pv[CONN_AS].ival = 1;
5395             pv[CONN_SY].ival = 0;
5396             break;
5397           case CONN_SY:                 /* Synchronous */
5398             pv[CONN_SY].ival = 1;
5399             pv[CONN_AS].ival = 0;
5400             break;
5401 #endif /* OS2 */
5402           case CONN_NV:                 /* Non-verbal */
5403             pv[n].ival = 1;
5404             break;
5405 #ifdef XLIMITS
5406           case CONN_II:                 /* Idle-interval */
5407           case CONN_IL:                 /* Idle-limit */
5408           case CONN_TL:                 /* Time-limit */
5409             if (!getval) break;
5410             if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
5411               goto xconnx;
5412             pv[n].ival = y;
5413             break;
5414           case CONN_IS:                 /* Idle-string */
5415 #endif /* XLIMITS */
5416 #ifdef CK_TRIGGER
5417           case CONN_TS:                 /* Trigger-string */
5418 #endif /* CK_TRIGGER */
5419 #ifdef XLIMORTRIGGER
5420             if (!getval) break;
5421             if ((x = cmfld("String (enclose in braces if it contains spaces)",
5422                            "",&s,xxstring)) < 0) {
5423                 if (x == -3) {
5424                     printf("?String required\n");
5425                     x = -9;
5426                 }
5427                 goto xconnx;
5428             }
5429             if (n != CONN_TS)
5430               s = brstrip(s);
5431             if ((y = strlen(s)) > 0) {
5432                 if (pv[n].sval) free(pv[n].sval);
5433                 pv[n].sval = malloc(y+1);
5434                 if (pv[n].sval) {
5435                     strcpy(pv[n].sval,s); /* safe */
5436                     pv[n].ival = 1;
5437                 }
5438             }
5439             break;
5440 #endif /* XLIMORTRIGGER */
5441           default:
5442             printf("?Unexpected switch value - %d\n",cmresult.nresult);
5443             x = -9;
5444             goto xconnx;
5445         }
5446     }
5447     debug(F101,"doxconn cmresult.fcode","",cmresult.fcode);
5448     if (cmresult.fcode != _CMCFM) {
5449         printf("?Unexpected function code: %d\n",cmresult.fcode);
5450         x = -9;
5451         goto xconnx;
5452     }
5453
5454     /* Command was confirmed so we can pre-pop command level. */
5455     /* This is so CONNECT module won't think we're executing a script */
5456     /* if CONNECT was the final command in the script. */
5457
5458     if (cmdlvl > 0)
5459       prepop();
5460
5461 #ifdef OS2                              /* Make results available globally */
5462     if (pv[CONN_IL].ival > -1)          /* Idle limit */
5463       tt_idlelimit = pv[CONN_IL].ival;
5464     if (pv[CONN_II].ival > -1)          /* Idle limit */
5465       tt_idlesnd_tmo = pv[CONN_II].ival;
5466     if (pv[CONN_IS].sval)               /* Idle string */
5467       if (tt_idlesnd_str = (char *)malloc((int)strlen(pv[CONN_IS].sval)+1))
5468         strcpy(tt_idlesnd_str,pv[CONN_IS].sval); /* safe */
5469     if (pv[CONN_TL].ival > -1)          /* Session limit */
5470       tt_timelimit = pv[CONN_TL].ival;
5471     async = (pv[CONN_AS].ival > 0 ||
5472              pv[CONN_SY].ival <= 0 && cmdlvl == 0) ? 1 : 0;
5473 #endif /* OS2 */
5474
5475 #ifdef CK_TRIGGER
5476     if (pv[CONN_TS].sval)               /* Trigger strings */
5477       makelist(pv[CONN_TS].sval,tt_trigger,TRIGGERS);
5478     for (i = 0; i < TRIGGERS; i++)      /* Trigger match pointers */
5479       tt_trmatch[i] = NULL;
5480     if (triggerval) {                   /* Reset trigger value */
5481         free(triggerval);
5482         triggerval = NULL;
5483     }
5484 #endif /* CK_TRIGGER */
5485
5486     x = doconect((pv[CONN_NV].ival > 0) ? 1 : 0, async);
5487     {
5488         int xx;
5489         debug(F101,"doxconn doconect returns","",x);
5490         if ((xx = ttchk()) < 0) dologend();
5491         debug(F101,"doxconn ttchk returns","",xx);
5492     }
5493
5494 #ifdef CK_TRIGGER
5495     debug(F111,"doxconn doconect triggerval",triggerval,x);
5496 #endif /* CK_TRIGGER */
5497
5498   xconnx:
5499     /* Back from CONNECT -- Restore global settings */
5500
5501     if (!async)
5502       resconn();
5503
5504     success = (x > 0) ? 1 : 0;
5505     return(x);
5506 }
5507 #endif /* NOLOCAL */
5508
5509 #ifdef ADDCMD
5510 /* cx == XXADD or XXREMV */
5511 /* fc == ADD_BIN or ADD_TXT */
5512 static int
5513 doadd(cx,fc) int cx, fc; {
5514 #ifdef PATTERNS
5515     char * tmp[FTPATTERNS];
5516     char **p = NULL;
5517     int i, j, k, n = 0, x = 0, last;
5518
5519 #endif /* PATTERNS */
5520     if (cx != XXADD && cx != XXREMV) {
5521         printf("?Unexpected function code: %d\n",cx);
5522         return(-9);
5523     }
5524 #ifdef PATTERNS
5525     while (n < FTPATTERNS) {            /* Collect new patterns */
5526         tmp[n] = NULL;
5527         if ((x = cmfld("Pattern","",&s,xxstring)) < 0)
5528           break;
5529         ckstrncpy(line,s,LINBUFSIZ);
5530         s = brstrip(line);
5531         makestr(&(tmp[n++]),s);
5532     }
5533     if (x == -3)
5534       x = cmcfm();
5535     if (x < 0)
5536       goto xdoadd;
5537     p = (fc == ADD_BIN) ? binpatterns : txtpatterns; /* Which list */
5538     last = 0;
5539     for (i = 0; i < FTPATTERNS; i++) { /* Find last one in list */
5540         if (!p[i]) {
5541             last = i;
5542             break;
5543         }
5544     }
5545     if (cx == XXADD) {                  /* Adding */
5546         if (last + n > FTPATTERNS) {    /* Check if too many */
5547             printf("?Too many patterns - %d is the maximum\n", FTPATTERNS);
5548             goto xdoadd;
5549         }
5550         for (i = 0; i < n; i++) {        /* Copy in the new ones. */
5551           for (j = 0, x = 0; x == 0 && j < last ; j++ )
5552             x = !ckstrcmp(tmp[i],p[j],-1,filecase); /* match */
5553           if (x == 0)
5554             makestr(&(p[last++]),tmp[i]);
5555         }
5556         makestr(&(p[last]),NULL);       /* Null-terminate the list */
5557         x = 1;
5558         goto xdoadd;                    /* Done */
5559     } else if (cx == XXREMV) {          /* Remove something(s) */
5560         int j, k;
5561         if (last == 0)                          /* List is empty */
5562           goto xdoadd;                          /* Nothing to remove */
5563         for (i = 0; i < n; i++) {               /* i = Patterns they typed */
5564             for (j = 0; j < last; j++) {        /* j = Patterns in list */
5565                 /* Change this to ckstrcmp()... */
5566                 if (filecase)
5567                   x = !ckstrcmp(tmp[i],p[j],-1,filecase); /* match */
5568                 else
5569                   x = ckstrcmp(tmp[i],p[j],-1,0); /* Case-independent match */
5570                 if (x) {                        /* This one matches */
5571                     makestr(&(p[j]),NULL);      /* Free it */
5572                     for (k = j; k < last; k++)  /* Move the rest up */
5573                       p[k] = p[k+1];
5574                     p[k] = NULL;                /* Erase last one */
5575                     if (!p[k])
5576                       break;
5577                 }
5578             }
5579         }
5580     }
5581   xdoadd:                               /* Common exit */
5582     for (i = 0; i < n; i++)
5583       if (tmp[i])
5584         free(tmp[i]);
5585     return(x);
5586 #endif /* PATTERNS */
5587 }
5588
5589 /* ADD SEND-LIST */
5590
5591 static int
5592 addsend(cx) int cx; {
5593 #ifndef NOMSEND
5594     extern struct keytab fttab[];
5595     extern int nfttyp;
5596     struct filelist * flp;
5597     char * fmode = "";
5598     int xmode = 0;
5599     int xbinary = 0;
5600 #endif /* NOMSEND */
5601
5602 #ifdef NOMSEND
5603     printf("?Sorry, ADD/REMOVE SEND-LIST not available.\n");
5604     return(-9);
5605 #endif /* NOMSEND */
5606     if (cx == XXREMV) {
5607         printf("?Sorry, REMOVE SEND-LIST not implemented yet.\n");
5608         return(-9);
5609     }
5610 #ifndef NOMSEND
5611 #ifndef XYZ_INTERNAL
5612     if (protocol != PROTO_K) {
5613        printf("?Sorry, ADD SEND-LIST does not work with external protocols\n");
5614        return(-9);
5615     }
5616 #endif /* XYZ_INTERNAL */
5617
5618     x = cmifi("File specification to add","", &s,&y,xxstring);
5619     if (x < 0) {
5620         if (x == -3) {
5621             printf("?A file specification is required\n");
5622             return(-9);
5623         } else
5624           return(x);
5625     }
5626     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
5627     s = tmpbuf;
5628     if (filesinlist == 0)               /* Take care of \v(filespec) */
5629       fspec[0] = NUL;
5630     zfnqfp(s,LINBUFSIZ,line);
5631     s = line;
5632     if (((int)strlen(fspec) + (int)strlen(s) + 1) < fspeclen) {
5633         strcat(fspec,s);                /* safe */
5634         strcat(fspec," ");              /* safe */
5635     } else
5636       printf("WARNING - \\v(filespec) buffer overflow\n");
5637
5638
5639     xbinary = binary;
5640     if ((patterns || filepeek)          /* FILE PATTERNS or SCAN is ON */
5641 #ifdef CK_LABELED
5642         && binary != XYFT_L             /* And not if FILE TYPE LABELED */
5643 #endif /* CK_LABELED */
5644 #ifdef VMS
5645         && binary != XYFT_I             /* or FILE TYPE IMAGE */
5646 #endif /* VMS */
5647         ) {
5648         int k, x;
5649         x = -1;
5650         k = scanfile(line,&x,nscanfile);
5651         if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
5652     }
5653     fmode = gfmode(xbinary,0);
5654     if ((x = cmkey(fttab,nfttyp,
5655                    "type of file transfer", fmode, xxstring)) < 0)
5656       return(x);
5657     xmode = x;
5658
5659     cmarg2 = "";
5660     if ((x = cmfld(y ?
5661   "\nAs-name template containing replacement variables such as \\v(filename)" :
5662   "Name to send it with", "",&s,NULL)) < 0)
5663       if (x != -3)
5664         return(x);
5665 #ifndef NOSPL
5666     if (y && *s) {
5667         char * p = tmpbuf;
5668         x = TMPBUFSIZ;
5669         zzstring(s,&p,&x);
5670         if (!strcmp(tmpbuf,s)) {
5671             printf(
5672   "?As-name for file group must contain variables such as \\v(filename)\n"
5673                    );
5674             return(-9);
5675         }
5676     }
5677 #endif /* NOSPL */
5678     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
5679     cmarg2 = tmpbuf;
5680
5681     if ((x = cmcfm()) < 0)
5682       return(x);
5683     flp = (struct filelist *) malloc(sizeof(struct filelist));
5684     if (flp) {
5685         if (filetail)
5686           filetail->fl_next = flp;
5687         filetail = flp;
5688         if (!filehead)
5689           filehead = flp;
5690         x = (int) strlen(line); /* Length of filename */
5691         s = (char *) malloc(x + 1);
5692         if (s) {
5693             strcpy(s,line);             /* safe */
5694             flp->fl_name = s;
5695             flp->fl_mode = xmode;
5696             x = (int) strlen(cmarg2);   /* Length of as-name */
5697             if (x < 1) {
5698                 flp->fl_alias = NULL;
5699             } else {
5700                 s = (char *) malloc(x + 1);
5701                 if (s) {
5702                     strcpy(s,cmarg2);   /* safe */
5703                     flp->fl_alias = s;
5704                 } else {
5705                     printf("Sorry, can't allocate space for as-name");
5706                     return(-9);
5707                 }
5708             }
5709             flp->fl_next = NULL;
5710             filesinlist++;              /* Count this node */
5711             return(success = 1);        /* Finished adding this node */
5712         } else {
5713             printf("Sorry, can't allocate space for name");
5714             return(-9);
5715         }
5716     } else {
5717         printf("Sorry, can't allocate file list node");
5718         return(-9);
5719     }
5720 #endif /* NOMSEND */
5721 }
5722 #endif /* ADDCMD */
5723
5724 #ifndef NOHTTP                          /* HTTP ops... */
5725 #ifdef TCPSOCKET
5726 #define HTTP_GET 0                      /* GET */
5727 #define HTTP_PUT 1                      /* PUT */
5728 #define HTTP_POS 2                      /* POST */
5729 #define HTTP_IDX 3                      /* INDEX */
5730 #define HTTP_HED 4                      /* HEAD */
5731 #define HTTP_DEL 5                      /* DELETE */
5732 #define HTTP_CON 6                      /* CONNECT */
5733 #define HTTP_OPN 7                      /* OPEN */
5734 #define HTTP_CLS 8                      /* CLOSE */
5735
5736 static struct keytab httptab[] = {
5737     { "close",   HTTP_CLS, 0 },
5738     { "connect", HTTP_CON, 0 },
5739     { "delete",  HTTP_DEL, 0 },
5740     { "get",     HTTP_GET, 0 },
5741     { "head",    HTTP_HED, 0 },
5742     { "index",   HTTP_IDX, 0 },
5743     { "open",    HTTP_OPN, 0 },
5744     { "put",     HTTP_PUT, 0 },
5745     { "post",    HTTP_POS, 0 }
5746 };
5747 static int nhttptab = sizeof(httptab)/sizeof(struct keytab);
5748
5749 /* HTTP switches */
5750 #define HT_SW_AG 0                      /* /AGENT */
5751 #define HT_SW_HD 1                      /* /HEADER */
5752 #define HT_SW_US 2                      /* /USER */
5753 #define HT_SW_PW 3                      /* /PASSWORD */
5754 #define HT_SW_AR 4                      /* /ARRAY */
5755 #define HT_SW_TP 5                      /* /TOSCREEN */
5756
5757 static struct keytab httpswtab[] = {
5758     { "/agent",    HT_SW_AG, CM_ARG },
5759 #ifndef NOSPL
5760     { "/array",    HT_SW_AR, CM_ARG },
5761 #endif /* NOSPL */
5762     { "/header",   HT_SW_HD, CM_ARG },
5763     { "/password", HT_SW_PW, CM_ARG },
5764     { "/toscreen", HT_SW_TP, 0 },
5765     { "/user",     HT_SW_US, CM_ARG },
5766     { "", 0, 0 }
5767 };
5768 static int nhttpswtab = sizeof(httpswtab)/sizeof(struct keytab) - 1;
5769
5770 /* HTTP PUT/POST switches */
5771 #define HT_PP_MT 0                      /* /MIME-TYPE */
5772
5773 static struct keytab httpptab[] = {
5774     { "/mime-type", HT_PP_MT, CM_ARG },
5775     { "", 0, 0 }
5776 };
5777 static int nhttpptab = sizeof(httpptab)/sizeof(struct keytab) - 1;
5778
5779 #define HTTP_MAXHDR 8
5780
5781 static int
5782 xdohttp(action, lfile, rf, dfile, agent, hdr, user, pass, mime, array, type)
5783     int action;
5784     char *lfile, *rf, *dfile, *agent, *hdr, *user, *pass, *mime, array;
5785     int type;
5786 /* xdohttp */ {
5787     int i, rc = 0;
5788     char * hdrlist[HTTP_MAXHDR];
5789     char rfile[CKMAXPATH+1];
5790     extern int httpfd;
5791
5792     /* Check for a valid state to execute the command */
5793     if (inserver) {
5794         printf("?The HTTP command may not be used from the IKS\r\n");
5795     } else if (httpfd == -1) {
5796         if (http_reopen() < 0)
5797           printf("?No connection\n");
5798         else
5799           rc = 1;
5800     } else {
5801         rc = 1;
5802     }
5803
5804     /* If the command is not valid, exit with failure */
5805     if (rc == 0)
5806         return(success = 0);
5807
5808     if (action != HTTP_CON && rf[0] != '/') {
5809         rfile[0] = '/';
5810         ckstrncpy(&rfile[1],rf,CKMAXPATH);
5811     } else {
5812         ckstrncpy(rfile,rf,CKMAXPATH);
5813     }
5814     for (i = 0; i < HTTP_MAXHDR; i++)   /* Initialize header list */
5815       hdrlist[i] = NULL;
5816     makelist(hdr,hdrlist,HTTP_MAXHDR);  /* Make header list */
5817
5818 #ifdef BETADEBUG
5819     for (i = 0; i < nhttptab; i++)      /* Find action keyword */
5820       if (httptab[i].kwval == action)
5821         break;
5822     if (i == nhttptab) {                /* Shouldn't happen... */
5823         printf("?Invalid action - %d\n",action);
5824         return(0);                      /* Failure */
5825     }
5826
5827     printf("HTTP action:  %s\n",httptab[i].kwd);
5828     printf(" Agent:       %s\n",agent ? agent : "(null)");
5829
5830     if (hdrlist[1]) {
5831         printf(" Header list: 1. %s\n",hdrlist[0]);
5832         for (i = 1; i < HTTP_MAXHDR && hdrlist[i]; i++)
5833           printf("%15d. %s\n",i+1,hdrlist[i]);
5834     } else
5835       printf(" Header:      %s\n",hdrlist[0] ? hdrlist[0] : "(null)");
5836
5837     printf(" User:        %s\n",user ? user : "(null)");
5838 #ifdef COMMENT
5839     printf(" Password:    %s\n",pass ? pass : "(null)");
5840 #endif /* COMMENT */
5841
5842 #ifndef NOSPL
5843     if (array)
5844       printf(" Array:       \\%%%c[]\n", array);
5845     else
5846       printf(" Array:       (none)\n");
5847 #endif /* NOSPL */
5848
5849     if (action == HTTP_PUT || action == HTTP_POS)
5850       printf(" Mime-type:   %s\n",mime ? mime : "(null)");
5851
5852     printf(" Local file:  %s\n",lfile ? lfile : "(null)");
5853     printf(" Remote file: %s\n",rfile ? rfile : "(null)");
5854     printf(" Destination file: %s\n",dfile ? dfile : "(null)");
5855 #endif /* BETADEBUG */
5856
5857     /* The http_xxxx() functions return 0 on success, -1 on failure */
5858     switch (action) {
5859       case HTTP_CON: {
5860           extern int ttyfd;
5861           rc = http_connect(httpfd,agent,hdrlist,user,pass,array,rfile);
5862           break;
5863       }
5864       case HTTP_DEL:
5865         rc = http_delete(agent,hdrlist,user,pass,array,rfile);
5866         break;
5867       case HTTP_GET:
5868         rc = http_get(agent,hdrlist,user,pass,array,lfile,rfile,type);
5869         break;
5870       case HTTP_HED:
5871         rc = http_head(agent,hdrlist,user,pass,array,lfile,rfile,type);
5872         break;
5873       case HTTP_PUT:
5874         rc = http_put(agent,hdrlist,mime,user,pass,array,lfile,rfile,dfile,
5875                       type);
5876         break;
5877       case HTTP_POS:
5878         rc = http_post(agent,hdrlist,mime,user,pass,array,lfile,rfile,dfile,
5879                        type);
5880         break;
5881       case HTTP_IDX:
5882         rc = http_index(agent,hdrlist,user,pass,array,lfile,rfile,type);
5883         break;
5884       default:
5885         rc = -1;
5886     }
5887     return(rc == 0 ? 1 : 0);            /* Success is set by caller */
5888 }
5889 #endif /* TCPSOCKET */
5890 #endif /* NOHTTP */
5891
5892 #ifndef NOSPL                           /* ARRAY ops... */
5893 static struct keytab arraytab[] = {
5894     { "clear",     ARR_CLR, 0 },
5895     { "copy",      ARR_CPY, 0 },
5896     { "dcl",       ARR_DCL, CM_INV },
5897     { "declare",   ARR_DCL, 0 },
5898     { "destroy",   ARR_DST, CM_INV },
5899     { "equate",    ARR_EQU, CM_INV },
5900     { "link",      ARR_EQU, 0 },
5901     { "resize",    ARR_RSZ, 0 },
5902     { "set",       ARR_SET, 0 },
5903 #ifndef NOSHOW
5904     { "show",      ARR_SHO, 0 },
5905 #endif /* NOSHOW */
5906     { "sort",      ARR_SRT, 0 },
5907     { "undeclare", ARR_DST, 0 },
5908     { "", 0, 0 }
5909 };
5910 static int narraytab = sizeof(arraytab)/sizeof(struct keytab) - 1;
5911
5912 #ifdef CKLEARN
5913 static struct keytab learnswi[] = {
5914     { "/close",    2, 0 },
5915     { "/off",      0, 0 },
5916     { "/on",       1, 0 }
5917 };
5918 #endif /* CKLEARN */
5919
5920 int
5921 arrayitoa(x) int x; {                   /* Array index to array letter */
5922     if (x == 1)
5923       return(64);
5924     else if (x < 0 || x > (122 - ARRAYBASE))
5925       return(-1);
5926     else
5927       return(x + ARRAYBASE);
5928 }
5929
5930 int
5931 arrayatoi(c) int c; {                   /* Array letter to array index */
5932     if (c == 64)
5933       c = 96;
5934     if (c > 63 && c < 91)
5935       c += 32;
5936     if (c < ARRAYBASE || c > 122)
5937       return(-1);
5938     return(c - ARRAYBASE);
5939 }
5940
5941 static int                              /* Declare an array */
5942 dodcl(cx) int cx; {
5943     int i, n, v, lo, hi, rc = 0;
5944     int isdynamic = 0;
5945     char tmpbuf[64];
5946     char ** p = NULL;
5947     char tmp[64];                       /* Local temporary string buffer */
5948     if ((y = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
5949         if (y == -3) {
5950             printf("?Array name required\n");
5951             return(-9);
5952         } else return(y);
5953     }
5954     ckstrncpy(line,s,LINBUFSIZ);
5955     s = line;
5956     x = arraybounds(s,&lo,&hi);         /* Check syntax and get bounds */
5957     debug(F111,"dodcl arraybounds",s,x);
5958     if (x < 0) {                        /* Error - Maybe it's a variable */
5959         char * p;                       /* whose value is an array name */
5960         int n;
5961         p = tmpbuf;
5962         n = 63;
5963         p[0] = NUL;
5964         if (s[0] == CMDQ && s[1] == '&')
5965           s++;
5966         if (zzstring(s,&p,&n) > -1) {
5967             s = tmpbuf;
5968             x = arraybounds(s,&lo,&hi);
5969             debug(F111,"dodcl arraybounds 2",s,x);
5970         }
5971         if (x < 0) {
5972             printf("?Bad array name - \"%s\"\n",s);
5973             return(-9);
5974         }
5975     }
5976     debug(F101,"dodcl hi","",hi);
5977     debug(F101,"dodcl lo","",lo);
5978     debug(F101,"dodcl lo+1","",lo+1);
5979
5980     if (lo == -1 && hi == -1) {         /* Have good array name and bounds */
5981         isdynamic = 1;
5982         n = CMDBL / 5;
5983     } else if (hi > -1) {
5984         printf("?Segment notation not allowed in array declarations\n");
5985         return(-9);
5986     } else if ((lo+1) < 0) {
5987         debug(F101,"dodcl underflow","",lo+1);
5988         printf("?Dimension underflow\n");
5989         return(-9);
5990     } else
5991       n = lo;
5992     x = arrayitoa(x);
5993     if (cx == XXUNDCL) {
5994         n = 0;
5995         v = 0;
5996         if ((y = cmcfm()) < 0)
5997           return(y);
5998     } else {
5999         p = (char **)malloc(sizeof(char **)*(n+1));
6000         if (!p) {
6001             printf("?Memory allocation error\n");
6002             return(-9);
6003         }
6004         v = 0;                          /* Highest initialized member */
6005         p[0] = NULL;                    /* Element 0 */
6006         keepallchars = 1;
6007         while (n > 0 && v < n) {        /* Parse initializers */
6008             p[v+1] = NULL;
6009             ckmakxmsg(tmp,
6010                       64,
6011                       "Initial value for \\&",
6012                       ckctoa((char)x),
6013                       "[",
6014                       ckitoa(v+1),
6015                       "]",
6016                       NULL,NULL,NULL,NULL,NULL,NULL,NULL
6017                       );
6018             if ((rc = cmfld((char *)tmp,"",&s,xxstring)) < 0) { /* Get field */
6019                 if (rc == -3)           /* If answer is empty, we're done */
6020                   break;
6021                 else                    /* Parse error, free temp pointers */
6022                   goto dclx;
6023             }
6024             rc = 1;
6025             if (v == 0 && !strcmp(s,"=")) /* Skip the = sign. */
6026               continue;
6027             s = brstrip(s);             /* Strip any braces */
6028             makestr(&(p[++v]),s);
6029         }
6030         keepallchars = 0;
6031         if ((y = cmtxt("Carriage return to confirm","",&s,NULL)) < 0)
6032           return(y);
6033         if (isdynamic)
6034           n = v;
6035     }
6036     if (dclarray((char)x,n) < 0) {      /* Declare the array */
6037         printf("?Declare failed\n");
6038         goto dclx;
6039     }
6040     for (i = 1; i <= v; i++) {          /* Add any initial values */
6041         tmp[0] = '&';
6042         ckmakmsg(&tmp[1],63,ckctoa((char)x),"[",ckitoa(i),"]");
6043         if (addmac(tmp,p[i]) < 0) {
6044             printf("Array initialization error: %s %s\n",tmp,p[i]);
6045             rc = -9;
6046             goto dclx;
6047         }
6048     }
6049   dclx:
6050     if (p) {
6051         for (i = 1; i <= v; i++)
6052           if (p[i]) free(p[i]);
6053         free((char *)p);
6054     }
6055     debug(F101,"DCL rc","",rc);
6056     return(success = rc);
6057 }
6058
6059 static int
6060 rszarray() {
6061     int i, x, y, n, lo, hi, islink = -1;
6062     char c, * s, ** ap = NULL;
6063     if ((x = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6064         if (x == -3) {
6065             printf("?Array name required\n");
6066             return(-9);
6067         } else return(x);
6068     }
6069     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of name */
6070     s = line;
6071     x = arraybounds(s,&lo,&hi);
6072     if (x < 0) {                        /* Parse the name, get index */
6073         printf("?Bad array reference - \"%s\"\n", s);
6074         return(-9);
6075     }
6076     if (lo < 0 && hi < 0) {
6077         y = cmnum("New size","",10,&lo,xxstring);
6078         if (y < 0) {
6079             if (y == -3)
6080               printf("?New size required\n");
6081             return(y);
6082         }
6083     }
6084     if ((y = cmcfm()) < 0)
6085       return(y);
6086     if (a_link[x] > -1) {               /* Link? */
6087         islink = x;                     /* Yes follow it */
6088         x = a_link[x];                  /* and remember */
6089     }
6090     if (!a_ptr[x]) {
6091         printf("?Array not declared - \"%s\"\n", s);
6092         return(-9);
6093     }
6094     if (lo < 0) {
6095         printf("?New size required\n");
6096         return(-9);
6097     }
6098     if (hi > -1) {
6099         printf("?Array segments not allowed for this operation\n");
6100         return(-9);
6101     }
6102     c = arrayitoa(x);                   /* Get array letter */
6103     if (c == '@') {                     /* Argument vector array off limits */
6104         printf("?Sorry, \\&@[] is read-only\n");
6105         return(-9);
6106     }
6107     if (lo == 0) {                      /* If new size is 0... */
6108         dclarray(c,0);                  /* Undeclare the array */
6109         return(success = 1);
6110     }
6111     n = a_dim[x];                       /* Current size */
6112     ap = (char **) malloc((lo+1) * sizeof(char *)); /* New array */
6113     y = (n < lo) ? n : lo;
6114     for (i = 0; i <= y; i++)            /* Copy the part that fits */
6115       ap[i] = a_ptr[x][i];
6116     if (n < lo) {                       /* If original array smaller */
6117         for (; i <= lo; i++)            /* initialize extra elements in */
6118           ap[i] = NULL;                 /* new array to NULL. */
6119     } else if (n > lo) {                /* If new array smaller */
6120         for (; i <= lo; i++)            /* deallocate leftover elements */
6121           makestr(&(a_ptr[x][i]),NULL); /* from original array. */
6122     }
6123     free((char *)a_ptr[x]);             /* Free original array list */
6124     a_ptr[x] = ap;                      /* Replace with new one */
6125     a_dim[x] = lo;                      /* Record the new dimension */
6126     if (islink > -1) {                  /* Was this a link? */
6127         a_ptr[islink] = ap;             /* If so point to the resized array */
6128         a_dim[islink] = lo;
6129     } else {                            /* If not are there links to here? */
6130         for (i = 0; i < (int) 'z' - ARRAYBASE; i++) { /* Any linked arrays? */
6131             if (i != x && a_link[i] == x) {     /* Find and update them */
6132                 a_ptr[i] = ap;
6133                 a_dim[i] = lo;
6134             }
6135         }
6136     }
6137     return(success = 1);
6138 }
6139
6140 static int
6141 copyarray() {
6142     int i, j, x1, lo1, hi1, x2, lo2, hi2, whole = 0;
6143     char c1, c2, * a1, * a2;
6144     if ((y = cmfld("Name of source array","",&s,NULL)) < 0)
6145       return(y);
6146     ckstrncpy(line,s,LINBUFSIZ);
6147     a1 = line;
6148     if ((x1 = arraybounds(a1,&lo1,&hi1)) < 0) {
6149         printf("?Bad array reference - \"%s\"\n", a1);
6150         return(-9);
6151     } else if (!a_ptr[x1]) {
6152         printf("?Array not declared - \"%s\"\n", a1);
6153         return(-9);
6154     }
6155     c1 = arrayitoa(x1);
6156
6157     if ((y = cmfld("Name of destination array","",&s,NULL)) < 0)
6158       return(y);
6159     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
6160     a2 = tmpbuf;
6161     if ((x2 = arraybounds(a2,&lo2,&hi2)) < 0) {
6162         printf("?Bad array reference - \"%s\"\n", a2);
6163         return(-9);
6164     }
6165     c2 = arrayitoa(x2);
6166
6167     if ((x = cmcfm()) < 0)
6168       return(x);
6169
6170     if (c2 == '@') {                    /* Argument vector array off limits */
6171         printf("?Sorry, \\&@[] is read-only\n");
6172         return(-9);
6173     }
6174     if (lo1 < 0 && lo2 < 0 && hi1 < 0 && hi2 < 0) /* Special case for */
6175       whole = 1;                                  /* whole array... */
6176
6177     if (lo1 < 0) lo1 = whole ? 0 : 1;   /* Supply lower bound of source */
6178     if (hi1 < 0) hi1 = a_dim[x1];       /* Supply upper bound of source */
6179     if (lo2 < 0) lo2 = whole ? 0 : 1;   /* Lower bound of target */
6180     if (hi2 < 0) hi2 = lo2 + hi1 - lo1; /* Upper bound of target */
6181     if (a_ptr[x2]) {                    /* Target array is already declared? */
6182         if (hi2 > a_dim[x2])            /* If upper bound out of range */
6183           hi2 = a_dim[x2];              /* shrink to fit */
6184     } else {                            /* Otherwise... */
6185         x2 = dclarray(c2, hi2);         /* declare the target array */
6186     }
6187     for (i = lo1, j = lo2; i <= hi1 && j <= hi2; i++,j++) { /* Copy */
6188         makestr(&(a_ptr[x2][j]),a_ptr[x1][i]);
6189     }
6190     return(success = 1);
6191 }
6192
6193 static int                              /* Undeclare an array */
6194 unarray() {
6195     int x, y, n, rc = 0;
6196     char c, * s;
6197
6198     if ((y = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6199         if (y == -3) {
6200             printf("?Array name required\n");
6201             return(-9);
6202         } else return(y);
6203     }
6204     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of name */
6205     s = line;
6206     if ((y = cmcfm()) < 0)
6207       return(y);
6208     if ((x = arraybounds(s,&y,&n)) < 0) { /* Parse the name, get index */
6209         printf("?Bad array reference - \"%s\"\n", s);
6210         return(-9);
6211     }
6212     if (y > 0 || n > 0) {
6213         printf("?Partial arrays can not be destroyed\n");
6214         return(-9);
6215     }
6216     c = arrayitoa(x);                   /* Get array letter */
6217     if (a_ptr[x]) {                     /* If array is declared */
6218         if (c == '@') {                 /* Argument vector array off limits */
6219             printf("?Sorry, \\&@[] is read-only\n");
6220             return(-9);
6221         }
6222         rc = dclarray(c,0);             /* Undeclare the array */
6223     } else                              /* It wasn't declared */
6224       rc = 1;
6225     if (rc > -1) {                      /* Set return code and success */
6226         success = 1;
6227         rc = 1;
6228     } else {
6229         success = 0;
6230         printf("?Failed - destroy \"\\&%c[]\"\n", c);
6231         rc = -9;
6232     }
6233     return(rc);
6234 }
6235
6236 static int
6237 clrarray(cx) int cx; {
6238     int i, x, lo, hi;
6239     char c, * s, * val = NULL;
6240
6241     if ((x = cmfld("Array name","",&s,NULL)) < 0) { /* Parse array name */
6242         if (x == -3) {
6243             printf("?Array name required\n");
6244             return(-9);
6245         } else return(x);
6246     }
6247     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of name */
6248     s = line;
6249     if (cx == ARR_SET) {                /* SET */
6250         if ((x = cmtxt("Value","",&val,xxstring)) < 0)
6251           return(x);
6252         ckstrncpy(tmpbuf,val,TMPBUFSIZ); /* Value to set */
6253         val = tmpbuf;
6254         if (!*val) val = NULL;
6255     } else if ((x = cmcfm()) < 0)       /* CLEAR */
6256       return(x);
6257
6258     if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Parse the name */
6259         printf("?Bad array reference - \"%s\"\n", s);
6260         return(-9);
6261     }
6262     c = arrayitoa(x);                   /* Get array letter */
6263     if (!a_ptr[x]) {                    /* If array is declared */
6264         printf("?Array %s is not declared\n", s);
6265         return(-9);
6266     } else if (c == '@') {              /* Argument vector array off limits */
6267         printf("?Sorry, \\&@[] is read-only\n");
6268         return(-9);
6269     }
6270     if (lo < 0) lo = 0;
6271     if (hi < 0) hi = a_dim[x];
6272     for (i = lo; i <= hi; i++)          /* Clear/Set selected range */
6273       makestr(&(a_ptr[x][i]),val);
6274
6275     return(success = 1);
6276 }
6277
6278 extern char **aa_ptr[CMDSTKL][28];
6279 extern int aa_dim[CMDSTKL][28];
6280
6281 static int                              /* Create symbolic link to an array */
6282 linkarray() {
6283     int i = 0, x, y, lo, hi, flag = 0;
6284     char c, * s, * p;
6285
6286     if ((x = cmfld("Array name not currently in use","",&s,NULL)) < 0) {
6287         if (x == -3) {
6288             printf("?Array name required\n");
6289             return(-9);
6290         } else return(x);
6291     }
6292     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of link name */
6293     s = line;
6294     if ((x = cmfld("Name of existing array","",&p,xxstring)) < 0) {
6295         if (x == -3) {
6296             printf("?Array name required\n");
6297             return(-9);
6298         } else return(x);
6299     }
6300     ckstrncpy(tmpbuf,p,TMPBUFSIZ);      /* Make safe copy of array name */
6301     p = tmpbuf;
6302     if ((x = cmcfm()) < 0)
6303       return(x);
6304
6305     if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Parse the link name */
6306         printf("?Bad array reference - \"%s\"\n", s);
6307         return(-9);
6308     }
6309     if (a_ptr[x]) {                     /* Must not already exist */
6310         c = arrayitoa(x);
6311         printf("?Array already exists: \\&%c[]\n", c);
6312         return(-9);
6313     }
6314     if (lo > -1 || hi > -1) {
6315         printf("?Sorry, whole arrays only: %s\n",s);
6316         return(-9);
6317     }
6318     if ((y = arraybounds(p,&lo,&hi)) < 0) { /* Parse the array name */
6319         printf("?Bad array reference - \"%s\"\n", s);
6320         return(-9);
6321     }
6322     if (lo > -1 || hi > -1) {
6323         printf("?Sorry, whole arrays only: %s\n",p);
6324         return(-9);
6325     }
6326     if (x == y) {
6327         for (i = cmdlvl; i >= 0; i--)
6328           if (aa_ptr[i][x]) {
6329               flag++;
6330               break;
6331           }
6332     }
6333     if (flag) {
6334         a_ptr[x] = aa_ptr[i][y];        /* Link to saved copy */
6335         a_dim[x] = aa_dim[i][y];
6336     } else {                            /* Otherwise... */
6337         c = arrayitoa(y);               /* Check if it's declared */
6338         if (!a_ptr[y]) {
6339             printf("?Array is not declared: \\&%c[]\n", c);
6340             return(-9);
6341         }
6342         if (a_link[y] > -1) {           /* And if it's a link itself */
6343             printf("?Links to links not allowed: \\&%c[]\n", c);
6344             return(-9);
6345         }
6346         a_ptr[x] = a_ptr[y];            /* All OK, make the link */
6347         a_dim[x] = a_dim[y];
6348     }
6349     a_link[x] = y;
6350     return(success = 1);
6351 }
6352 #endif /* NOSPL */
6353
6354 #ifndef NOCSETS
6355 static char * dcsetname = NULL;
6356
6357 /* Get Display Character-Set Name */
6358
6359 char *
6360 getdcset() {
6361     char * s;
6362     int y;
6363 #ifdef PCFONTS
6364     extern int tt_font, ntermfont;
6365     extern struct keytab term_font[];
6366 #endif /* PCFONTS */
6367
6368     s = "";
6369 #ifdef OS2
6370     y = os2getcp();                     /* Default is current code page */
6371     switch (y) {
6372       case 437: s = "cp437"; break;
6373       case 850: s = "cp850"; break;
6374       case 852: s = "cp852"; break;
6375       case 857: s = "cp857"; break;
6376       case 858: s = "cp858"; break;
6377       case 862: s = "cp862"; break;
6378       case 866: s = "cp866"; break;
6379       case 869: s = "cp869"; break;
6380       case 1250: s = "cp1250"; break;
6381       case 1251: s = "cp1251"; break;
6382       case 1252: s = "cp1252"; break;
6383       case 1253: s = "cp1253"; break;
6384       case 1254: s = "cp1254"; break;
6385       case 1255: s = "cp1255"; break;
6386       case 1256: s = "cp1256"; break;
6387       case 1257: s = "cp1257"; break;
6388       case 1258: s = "cp1258"; break;
6389     }
6390 #ifdef PCFONTS
6391 /*
6392    If the user has loaded a font with SET TERMINAL FONT then we want
6393    to change the default code page to the font that was loaded.
6394 */
6395     if (tt_font != TTF_ROM) {
6396         for (y = 0; y < ntermfont; y++ ) {
6397             if (term_font[y].kwval == tt_font) {
6398                 s = term_font[y].kwd;
6399                 break;
6400             }
6401         }
6402     }
6403 #endif /* PCFONTS */
6404 #else /* OS2 */
6405 #ifdef COMMENT
6406     /* Hack not needed as of C-Kermit 7.1 */
6407     if (fcharset == FC_1LATIN) {
6408         s = "latin1-iso";               /* Hack to avoid reporting "cp1252" */
6409     } else {                            /* Report current file character set */
6410 #endif /* COMMENT */
6411         for (y = 0; y <= nfilc; y++)
6412           if (fcstab[y].kwval == fcharset) {
6413               s = fcstab[y].kwd;
6414               break;
6415           }
6416 #ifdef COMMENT
6417     }
6418 #endif /* COMMENT */
6419 #endif /* OS2 */
6420     makestr(&dcsetname,s);              /* Return stable pointer */
6421     return((char *)dcsetname);
6422 }
6423 #endif /* NOCSETS */
6424
6425 #ifndef NOFRILLS
6426 static int
6427 doclear() {
6428     if ((x = cmkey(clrtab,nclear,"item to clear",
6429 #ifdef NOSPL
6430                    "device-buffer"
6431 #else
6432                    "device-and-input"
6433 #endif /* NOSPL */
6434                    ,xxstring)) < 0) return(x);
6435 #ifndef NOSPL
6436 #ifdef OS2
6437     if (x == CLR_CMD || x == CLR_TRM) {
6438         if ((z = cmkey(clrcmdtab,nclrcmd,"how much screen to clear\n",
6439                        "all",xxstring)) < 0)
6440           return(z);
6441     }
6442 #endif /* OS2 */
6443 #endif /* NOSPL */
6444     if ((y = cmcfm()) < 0)
6445       return(y);
6446
6447     /* Clear device input buffer if requested */
6448     y = (x & CLR_DEV) ? ttflui() : 0;
6449
6450     if (x & CLR_SCR)                    /* CLEAR SCREEN */
6451       y = ck_cls();                     /* (= SCREEN CLEAR = CLS) */
6452
6453     if (x & CLR_KBD) {                  /* CLEAR KEYBOARD */
6454         int n;
6455         n = conchk();
6456         y = 0;
6457         while (n-- > 0 && (y = coninc(0) > -1))
6458           ;
6459         y = (y > -1) ? 0 : -1;
6460     }
6461
6462 #ifndef NOSPL
6463     /* Clear INPUT command buffer if requested */
6464     if (x & CLR_INP) {
6465         for (z = 0; z < inbufsize; z++)
6466           inpbuf[z] = NUL;
6467         inpbp = inpbuf;
6468         y = 0;
6469     }
6470 #ifdef CK_APC
6471     if (x & CLR_APC) {
6472         debug(F101,"Executing CLEAR APC","",apcactive);
6473         apcactive = 0;
6474         y = 0;
6475     }
6476 #endif /* CK_APC */
6477     if (x & CLR_ALR) {
6478         setalarm(0L);
6479         y = 0;
6480     }
6481 #endif /* NOSPL */
6482
6483 #ifdef PATTERNS
6484     if (x & (CLR_TXT|CLR_BIN)) {
6485         int i;
6486         for (i = 0; i < FTPATTERNS; i++) {
6487             if (x & CLR_TXT)
6488               makestr(&txtpatterns[i],NULL);
6489             if (x & CLR_BIN)
6490               makestr(&binpatterns[i],NULL);
6491         }
6492         y = 0;
6493     }
6494 #endif /* PATTERNS */
6495
6496 #ifndef NODIAL
6497     if (x & CLR_DIA) {
6498         dialsta = DIA_UNK;
6499         y = 0;
6500     }
6501 #endif /* NODIAL */
6502
6503 #ifndef NOMSEND
6504     if (x & CLR_SFL) {                  /* CLEAR SEND-LIST */
6505         if (filehead) {
6506             struct filelist * flp, * next;
6507             flp = filehead;
6508             while (flp) {
6509                 if (flp->fl_name)
6510                   free(flp->fl_name);
6511                 if (flp->fl_alias)
6512                   free(flp->fl_alias);
6513                 next = flp->fl_next;
6514                 free((char *)flp);
6515                 flp = next;
6516             }
6517         }
6518         filesinlist = 0;
6519         filehead = NULL;
6520         filetail = NULL;
6521         addlist = 0;
6522         y = 0;
6523     }
6524 #endif /* NOMSEND */
6525
6526 #ifdef OS2
6527 #ifndef NOLOCAL
6528     switch (x) {
6529       case CLR_SCL:
6530         clearscrollback(VTERM);
6531         break;
6532       case CLR_CMD:
6533         switch ( z ) {
6534           case CLR_C_ALL:
6535             clear();
6536             break;
6537           case CLR_C_BOS:
6538             clrboscr_escape(VCMD,SP);
6539             break;
6540           case CLR_C_BOL:
6541             clrbol_escape(VCMD,SP);
6542             break;
6543           case CLR_C_EOL:
6544             clrtoeoln(VCMD,SP);
6545             break;
6546           case CLR_C_EOS:
6547             clreoscr_escape(VCMD,SP);
6548             break;
6549           case CLR_C_LIN:
6550             clrline_escape(VCMD,SP);
6551             break;
6552           case CLR_C_SCR:
6553             clearscrollback(VCMD);
6554             break;
6555         default:
6556             printf("Not implemented yet, sorry.\n");
6557             break;
6558         }
6559         break;
6560
6561 #ifndef NOTERM
6562       case CLR_TRM:
6563          switch ( z ) {
6564           case CLR_C_ALL:
6565              if (VscrnGetBufferSize(VTERM) > 0 ) {
6566                  VscrnScroll(VTERM, UPWARD, 0,
6567                              VscrnGetHeight(VTERM)-(tt_status[VTERM]?2:1),
6568                              VscrnGetHeight(VTERM) -
6569                              (tt_status[VTERM]?1:0), TRUE, SP
6570                              );
6571                  cleartermscreen(VTERM);
6572              }
6573              break;
6574           case CLR_C_BOS:
6575             clrboscr_escape(VTERM,SP);
6576             break;
6577           case CLR_C_BOL:
6578             clrbol_escape(VTERM,SP);
6579             break;
6580           case CLR_C_EOL:
6581             clrtoeoln(VTERM,SP);
6582             break;
6583           case CLR_C_EOS:
6584             clreoscr_escape(VTERM,SP);
6585             break;
6586           case CLR_C_LIN:
6587             clrline_escape(VTERM,SP);
6588             break;
6589          case CLR_C_SCR:
6590              clearscrollback(VTERM);
6591              break;
6592          default:
6593              printf("Not implemented yet, sorry.\n");
6594              break;
6595         }
6596         break;
6597 #endif /* NOTERM */
6598     }
6599     y = 0;
6600 #endif /* NOLOCAL */
6601 #endif /* OS2 */
6602     return(success = (y == 0));
6603 }
6604 #endif /* NOFRILLS */
6605
6606 #ifndef NOSPL
6607 static int
6608 doeval(cx) int cx; {
6609     char *p;
6610     char vnambuf[VNAML], * vnp = NULL;  /* These must be on the stack */
6611     if (!oldeval) {
6612         if ((y = cmfld("Variable name","",&s,
6613                        ((cx == XX_EVAL) ? xxstring : NULL))) < 0) {
6614             if (y == -3) {
6615                 printf("?Variable name required\n");
6616                 return(-9);
6617             } else return(y);
6618         }
6619         ckstrncpy(vnambuf,s,VNAML);     /* Make a copy. */
6620         vnp = vnambuf;
6621         if (vnambuf[0] == CMDQ &&
6622             (vnambuf[1] == '%' || vnambuf[1] == '&'))
6623           vnp++;
6624         y = 0;
6625         if (*vnp == '%' || *vnp == '&') {
6626             if ((y = parsevar(vnp,&x,&z)) < 0)
6627               return(y);
6628         }
6629     }
6630     if ((x = cmtxt("Integer arithmetic expression","",&s,xxstring)) < 0)
6631       return(x);
6632     p = evala(s);
6633     if (!p) p = "";
6634     if (oldeval && *p)
6635       printf("%s\n", p);
6636     ckstrncpy(evalbuf,p,32);
6637     if (!oldeval)
6638       return(success = addmac(vnambuf,p));
6639     else
6640       return(success = *p ? 1 : 0);
6641 }
6642 #endif /* NOSPL */
6643
6644 #ifdef TNCODE
6645 static int
6646 dotelopt() {
6647     if ((x = cmkey(telcmd, ntelcmd, "TELNET command", "", xxstring)) < 0 )
6648       return(x);
6649     switch (x) {
6650       case WILL:
6651       case WONT:
6652       case DO:
6653       case DONT:
6654         if ((y = cmkey(tnopts,ntnopts,"TELNET option","",xxstring)) < 0)
6655           return(y);
6656         if ((z = cmcfm()) < 0) return(z);
6657
6658         switch (x) {
6659           case WILL:
6660             if (TELOPT_UNANSWERED_WILL(y))
6661               return(success = 0);
6662             break;
6663           case WONT:
6664             if (TELOPT_UNANSWERED_WONT(y))
6665               return(success = 0);
6666             break;
6667           case DO:
6668             if (TELOPT_UNANSWERED_DO(y))
6669               return(success = 0);
6670             break;
6671           case DONT:
6672             if (TELOPT_UNANSWERED_DONT(y))
6673               return(success = 0);
6674             break;
6675         }
6676         if (local) {
6677             success = ((tn_sopt(x,y) > -1) ? 1 : 0);
6678         } else {
6679             printf("ff%02x%02x\n",x,y);
6680             success = 1;
6681         }
6682         if (success) {
6683             switch (x) {
6684               case WILL:
6685                 TELOPT_UNANSWERED_WILL(y) = 1;
6686                 break;
6687               case WONT:
6688                 if ( TELOPT_ME(y) )
6689                   TELOPT_UNANSWERED_WONT(y) = 1;
6690                 break;
6691               case DO:
6692                 TELOPT_UNANSWERED_DO(y) = 1;
6693                 break;
6694               case DONT:
6695                 if ( TELOPT_ME(y) )
6696                   TELOPT_UNANSWERED_DONT(y) = 1;
6697                 break;
6698             }
6699             if (tn_wait("XXTELOP") < 0) {
6700                 tn_push();
6701                 success = 0;
6702             }
6703         }
6704         return(success);
6705       case SB:
6706         if ((y=cmkey(tnsbopts,ntnsbopts,"TELNET option","",xxstring)) < 0)
6707           return(y);
6708         switch (y) {
6709           case TELOPT_NAWS:
6710             /* Some compilers require switch() to have at least 1 case */
6711 #ifdef CK_NAWS
6712             TELOPT_SB(TELOPT_NAWS).naws.x = 0;
6713             TELOPT_SB(TELOPT_NAWS).naws.y = 0;
6714             if (local)
6715               return(success = ((tn_snaws() > -1) ? 1 : 0));
6716             else
6717               return(success = 0);
6718 #else
6719             return(success = 0);
6720 #endif /* CK_NAWS */
6721         }
6722         return(success = 0);
6723
6724 #ifdef CK_KERBEROS
6725 #ifdef KRB5
6726       case TN_FWD:
6727         success = (kerberos5_forward() == AUTH_SUCCESS);
6728         return(success);
6729 #endif /* KRB5 */
6730 #endif /* CK_KERBEROS */
6731
6732       default:
6733         if ((z = cmcfm()) < 0) return(z);
6734 #ifndef NOLOCAL
6735         if (local) {
6736             CHAR temp[3];
6737             if (network && IS_TELNET()) { /* TELNET */
6738                 temp[0] = (CHAR) IAC;
6739                 temp[1] = x;
6740                 temp[2] = NUL;
6741                 success = (ttol((CHAR *)temp,2) > -1 ? 1 : 0);
6742                 if (tn_deb || debses || deblog) {
6743                     /* TN_MSG_LEN is in ckctel.h */
6744                     ckmakmsg(tn_msg,256,"TELNET SENT ",TELCMD(x),NULL,NULL);
6745                     debug(F101,tn_msg,"",x);
6746                     if (debses || tn_deb) tn_debug(tn_msg);
6747                 }
6748                 return(success);
6749             }
6750             return(success = 0);
6751         } else {
6752 #endif /* NOLOCAL */
6753             printf("ff%02x\n",x);
6754             return(success = 1);
6755 #ifndef NOLOCAL
6756         }
6757 #endif /* NOLOCAL */
6758     }
6759 }
6760 #endif /* TNCODE */
6761
6762
6763 #ifndef NOPUSH
6764 #ifndef NOFRILLS
6765 static int
6766 doedit() {
6767 #ifdef OS2
6768     char * p = NULL;
6769 #endif /* OS2 */
6770     if (!editor[0]) {
6771         s = getenv("EDITOR");
6772         if (s) ckstrncpy(editor,s,CKMAXPATH);
6773         editor[CKMAXPATH] = NUL;
6774         if (!editor[0]) {
6775             printf("?Editor not defined - use SET EDITOR to define\n");
6776             return(-9);
6777         }
6778     }
6779     ckstrncpy(tmpbuf,editfile,TMPBUFSIZ);
6780 /*
6781   cmiofi() lets us parse the name of an existing file, or the name of
6782   a nonexistent file to be created.
6783 */
6784     x = cmiofi("File to edit", (char *)tmpbuf, &s, &y, xxstring);
6785     if (x < 0) {
6786         if (x == -9) {
6787             if (zchko(s) < 0) {
6788                 printf("Can't create \"%s\"\n",s);
6789                 return(x);
6790             }
6791         } else if (x != -3)
6792           return(x);
6793     }
6794     if (x == -3)
6795       tmpbuf[0] = NUL;
6796     else {
6797         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
6798         if (iswild((char *)tmpbuf)) {
6799             printf("?A single file please\n");
6800             return(-9);
6801         }
6802     }
6803     if ((z = cmcfm()) < 0) return(z);
6804     if (nopush) {
6805         printf("?Sorry, editing not allowed\n");
6806         return(success = 0);
6807     }
6808     if (tmpbuf[0]) {
6809     /* Get full path in case we change directories between EDIT commands */
6810         zfnqfp(tmpbuf, CKMAXPATH, editfile);
6811         editfile[CKMAXPATH] = NUL;
6812 #ifdef OS2
6813         p = editfile;                   /* Flip the stupid slashes */
6814         while (*p) {
6815             if (*p == '/') *p = '\\';
6816             p++;
6817         }
6818 #endif /* OS2 */
6819     } else
6820       editfile[0] = NUL;
6821     x = 0;
6822     if (editopts[0]) {
6823 #ifdef OS2
6824         x = ckindex("%1",(char *)editopts,0,0,1);
6825         if (x > 0)
6826           editopts[x] = 's';
6827         else
6828 #endif /* OS2 */
6829           x = ckindex("%s",(char *)editopts,0,0,1);
6830     }
6831     if (((int)strlen(editopts) + (int)strlen(editfile) + 1) < TMPBUFSIZ) {
6832         if (x)
6833           sprintf(tmpbuf,editopts,editfile);
6834         else
6835           sprintf(tmpbuf,"%s %s",editopts,editfile);
6836     }
6837     s = line;
6838     ckmakmsg(s,LINBUFSIZ,editor," ",tmpbuf,NULL);
6839 #ifdef OS2
6840     p = s + strlen(editor);             /* And again with the slashes */
6841     while (p != s) {
6842         if (*p == '/') *p = '\\';
6843         p--;
6844     }
6845 #endif /* OS2 */
6846     conres();
6847     x = zshcmd(s);
6848     concb((char)escape);
6849     return(x);
6850 }
6851 #endif /* NOFRILLS */
6852 #endif /* NOPUSH */
6853
6854 #ifdef BROWSER
6855 static int
6856 dobrowse() {
6857 #ifdef OS2
6858     char * p = NULL;
6859 #endif /* OS2 */
6860     if (nopush) {
6861         printf("?Sorry, browsing not allowed\n");
6862         return(success = 0);
6863     }
6864 #ifndef NT
6865     /* Windows lets the Shell Execute the URL if no Browser is defined */
6866     if (!browser[0]) {
6867         s = getenv("BROWSER");
6868         if (s) ckstrncpy(browser,s,CKMAXPATH);
6869         browser[CKMAXPATH] = NUL;
6870         if (!browser[0]) {
6871             printf("?Browser not defined - use SET BROWSER to define\n");
6872             return(-9);
6873         }
6874     }
6875 #endif /* NT */
6876     ckstrncpy(tmpbuf,browsurl,TMPBUFSIZ);
6877     if ((x = cmtxt("URL",(char *)browsurl,&s,xxstring)) < 0)
6878       return(x);
6879     ckstrncpy(browsurl,s,4096);
6880     x = 0;
6881     if (browsopts[0]) {
6882 #ifdef OS2
6883         x = ckindex("%1",(char *)browsopts,0,0,1);
6884         if (x > 0)
6885           browsopts[x] = 's';
6886         else
6887 #endif /* OS2 */
6888           x = ckindex("%s",(char *)browsopts,0,0,1);
6889     }
6890     if (((int)strlen(browsopts) + (int)strlen(browsurl) + 1) < TMPBUFSIZ) {
6891         if (x)
6892           sprintf(tmpbuf,browsopts,browsurl);
6893         else
6894           sprintf(tmpbuf,"%s %s",browsopts,browsurl);
6895     }
6896 #ifdef NT
6897     if (!browser[0])
6898       return(success = Win32ShellExecute(browsurl));
6899 #endif /* NT */
6900     s = line;
6901     ckmakmsg(s,LINBUFSIZ,browser," ",tmpbuf,NULL);
6902 #ifdef OS2
6903     p = line + strlen(browser);         /* Flip slashes */
6904     while (p != line) {
6905         if (*p == '/') *p = '\\';
6906         p--;
6907     }
6908 #endif /* OS2 */
6909     conres();
6910     x = zshcmd(s);
6911     concb((char)escape);
6912     return(x);
6913 }
6914 #endif /* BROWSER */
6915
6916 #ifdef CK_RECALL
6917 static int
6918 doredo() {                      /* Find a previous cmd and redo it */
6919     extern int on_recall, in_recall;
6920     int x;
6921     char * p;
6922
6923     if ((x = cmtxt(
6924 "pattern, or first few characters of a previous command",
6925                    "*",&s,xxstring)) < 0)
6926       return(x);
6927     ckstrncpy(line,s,LINBUFSIZ);
6928     x = strlen(s);
6929     s = line;
6930     if (*s == '{') {                    /* Braces disable adding * to end */
6931         if (s[x-1] == '}') {
6932             s[x-1] = NUL;
6933             s++;
6934             x--;
6935         }
6936     } else {                            /* No braces, add * to end. */
6937         s[x] = '*';
6938         s[x+1] = NUL;
6939     }
6940
6941     while (x > 0 && s[x] == '*' && s[x-1] == '*') s[x--] = NUL;
6942
6943     if (!on_recall || !in_recall) {
6944         printf("?Sorry, command recall can't be used now.\n");
6945         return(-9);
6946     }
6947     if ((p = cmgetcmd(s))) {            /* Look for it history buffer */
6948         ckmakmsg(cmdbuf,CMDBL,p,"\r",NULL,NULL); /* Copy to command buffer */
6949         if (!quiet)                     /* Echo it */
6950           printf("%s\n",cmdbuf);
6951         cmaddnext();                    /* Force re-add to history buffer */
6952         return(cmflgs = -1);            /* Force reparse */
6953     } else {
6954         printf("?Sorry - \"%s\" not found\n", s);
6955         return(-9);
6956     }
6957 }
6958 #endif /* CK_RECALL */
6959
6960 #ifndef NOXFER
6961 #ifndef NOCSETS
6962 static int
6963 doassoc()  {                            /* ASSOCIATE */
6964     extern struct keytab tcstab[];
6965     extern int ntcs;
6966     if ((x = cmkey(assoctab, nassoc, "", "", xxstring)) < 0 )
6967       return(x);
6968
6969     switch (x) {                        /* Associate what? */
6970
6971       case ASSOC_TC:                    /* Transfer character-set... */
6972         if ((x = cmkey(tcstab, ntcs,
6973                        "transfer character-set name","",xxstring)) < 0)
6974           return(x);
6975         if ((y = cmkey(fcstab, nfilc,
6976                        "with file character-set","", xxstring)) < 0)
6977           if (y != -3)
6978             return(y);
6979         if ((z = cmcfm()) < 0)
6980           return(z);
6981         axcset[x] = y;
6982         return(success = 1);
6983
6984       case ASSOC_FC:                    /* File character-set... */
6985         if ((x = cmkey(fcstab, nfilc,
6986                        "file character-set name","",xxstring)) < 0)
6987           return(x);
6988         if ((y = cmkey(tcstab, ntcs,
6989                        "with transfer character-set","", xxstring)) < 0)
6990           if (y != -3)
6991             return(y);
6992         if ((z = cmcfm()) < 0)
6993           return(z);
6994         afcset[x] = y;
6995         return(success = 1);
6996
6997       default:
6998         return(-2);
6999     }
7000 }
7001 #endif /* NOCSETS */
7002 #endif /* NOXFER */
7003
7004 #ifndef NOHELP
7005 static int
7006 domanual() {
7007 #ifdef OS2
7008     if ((x = cmcfm()) < 0)
7009       return(x);
7010     if (nopush) {
7011         printf("?Sorry, access to system commands is disabled.\n");
7012         return(-9);
7013     }
7014     y = mxlook(mactab,"manual",nmac);
7015     if (y > -1) {
7016         z = maclvl;                     /* Save the current maclvl */
7017         dodo(y,NULL,cmdstk[cmdlvl].ccflgs); /* Run the macro */
7018         while (maclvl > z) {
7019             debug(F101,"XXMAN loop maclvl 1","",maclvl);
7020             sstate = (CHAR) parser(1);
7021             debug(F101,"XXMAN loop maclvl 2","",maclvl);
7022             if (sstate) proto();
7023         }
7024         debug(F101,"XXMAN loop exit maclvl","",maclvl);
7025         return(success);
7026     }
7027     return(success = 0);
7028 #else
7029     if ((x = cmtxt(
7030 #ifdef UNIX
7031                    "Carriage return to confirm the command, or manual topic",
7032 #else
7033                    "Carriage return to confirm the command, or help topic",
7034 #endif /* UNIX */
7035                    "kermit",
7036                    &s,
7037                    xxstring
7038                    )
7039          ) < 0)
7040       return(x);
7041 #endif /* OS2 */
7042
7043 #ifdef UNIX
7044     ckmakmsg(tmpbuf,TMPBUFSIZ,"man ",s,NULL,NULL);
7045 #else
7046     ckmakmsg(tmpbuf,TMPBUFSIZ,"help ",s,NULL,NULL);
7047 #endif /* UNIX */
7048     debug(F110,"MANUAL",tmpbuf,0);
7049     if (nopush) {
7050         printf("?Sorry, access to system commands is disabled.\n");
7051         return(-9);
7052     } else {
7053         conres();                       /* Restore the console */
7054         success = zshcmd(tmpbuf);
7055         concb((char)escape);            /* Restore CBREAK mode */
7056         return(success);
7057     }
7058 }
7059 #endif /* NOHELP */
7060
7061 #ifndef NOHTTP
7062 #ifdef TCPSOCKET
7063 static struct keytab sslswtab[] = {
7064     { "/ssl", 1, 0 },
7065     { "/tls", 1, 0 }
7066 };
7067
7068 #ifndef NOURL
7069 struct urldata http_url = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
7070 #endif /* NOURL */
7071
7072 static int
7073 dohttp() {                              /* HTTP */
7074     struct FDB sw, kw, fi;
7075     int n, getval, allinone = 0;
7076     char c, * p;
7077     char rdns[128];
7078
7079     char * http_agent = NULL;           /* Parse results */
7080     char * http_hdr   = NULL;
7081     char * http_user  = NULL;
7082     char * http_pass  = NULL;
7083     char * http_mime  = NULL;
7084     char * http_lfile = NULL;
7085     char * http_rfile = NULL;
7086     char * http_dfile = NULL;
7087     char   http_array = NUL;
7088     int    http_action = -1;
7089
7090     char * http_host = NULL;
7091     char * http_srv  = NULL;
7092     int    http_ssl  = 0;
7093
7094     static char * http_d_agent = NULL;
7095     static char * http_d_user = NULL;
7096     static char * http_d_pass = NULL;
7097
7098     static int    http_d_type = 0;
7099     int           http_type = http_d_type;
7100
7101 #ifdef OS2
7102     p = "Kermit 95";                    /* Default user agent */
7103 #else
7104     p = "C-Kermit";
7105 #endif /* OS2 */
7106     makestr(&http_agent,p);
7107     makestr(&http_mime,"text/HTML");    /* MIME type default */
7108     rdns[0] = '\0';
7109
7110     cmfdbi(&sw,                         /* 1st FDB - general switches */
7111        _CMKEY,                          /* fcode */
7112        "OPEN, CLOSE, GET, HEAD, PUT, INDEX, or POST,\n or switch", /* hlpmsg */
7113        "",                              /* default */
7114        "",                              /* addtl string data */
7115        nhttpswtab,                      /* addtl numeric data 1: tbl size */
7116        4,                               /* addtl numeric data 2: 4 = cmswi */
7117        xxstring,                        /* Processing function */
7118        httpswtab,                       /* Keyword table */
7119        &kw                              /* Pointer to next FDB */
7120        );
7121     cmfdbi(&kw,                         /* 2nd FDB - commands */
7122        _CMKEY,                          /* fcode */
7123        "Command",                       /* hlpmsg */
7124        "",                              /* default */
7125        "",                              /* addtl string data */
7126        nhttptab,                        /* addtl numeric data 1: tbl size */
7127        0,                               /* addtl numeric data 2: 0 = keyword */
7128        xxstring,                        /* Processing function */
7129        httptab,                         /* Keyword table */
7130        NULL                             /* Pointer to next FDB */
7131        );
7132
7133     while (1) {
7134         x = cmfdb(&sw);                 /* Parse something */
7135         if (x < 0)                      /* Error */
7136           goto xhttp;
7137         n = cmresult.nresult;
7138         if (cmresult.fdbaddr == &kw)    /* Command - exit this loop */
7139           break;
7140         c = cmgbrk();                   /* Switch... */
7141         getval = (c == ':' || c == '=');
7142         x = -9;
7143         if (getval && !(cmgkwflgs() & CM_ARG)) {
7144             printf("?This switch does not take an argument\n");
7145             goto xhttp;
7146         }
7147         switch (cmresult.nresult) {     /* Handle each switch */
7148           case HT_SW_TP:                /* /TOSCREEN */
7149             http_type = 1;
7150             break;
7151           case HT_SW_AG:                /* /AGENT */
7152             if (getval) {
7153                 if ((x = cmfld("User agent",p,&s,xxstring)) < 0)
7154                   goto xhttp;
7155             } else {
7156                 s = p;
7157             }
7158             makestr(&http_agent,s);
7159             break;
7160           case HT_SW_HD:                /* /HEADER */
7161             s = NULL;
7162             if (getval) {
7163                 if ((x = cmfld("Header line","",&s,xxstring)) < 0) {
7164                     if (x == -3)
7165                       s = NULL;
7166                     else
7167                       goto xhttp;
7168                 }
7169             }
7170             makestr(&http_hdr,s);
7171             break;
7172           case HT_SW_US:                /* /USER */
7173             s = NULL;
7174             if (getval) {
7175                 if ((x = cmfld("User ID","",&s,xxstring)) < 0) {
7176                   if (x == -3)
7177                     s = "";
7178                   else
7179                     goto xhttp;
7180                 }
7181             }
7182             makestr(&http_user,s);
7183             break;
7184           case HT_SW_PW:                /* /PASSWORD */
7185             debok = 0;
7186             s = NULL;
7187             if (getval) {
7188                 if ((x = cmfld("Password","",&s,xxstring)) < 0)
7189                   goto xhttp;
7190             }
7191             makestr(&http_pass,s);
7192             break;
7193 #ifndef NOSPL
7194           case HT_SW_AR: {              /* /ARRAY: */
7195               char * s2, array = NUL;
7196               if (!getval) {
7197                   printf("?This switch requires an argument\n");
7198                   x = -9;
7199                   goto xhttp;
7200               }
7201               if ((x = cmfld("Array name (a single letter will do)",
7202                              "",
7203                              &s,
7204                              NULL
7205                              )) < 0) {
7206                   if (x == -3) {
7207                       printf("?Array name required\n");
7208                       x = -9;
7209                       goto xhttp;
7210                   } else
7211                     goto xhttp;
7212               }
7213               if (!*s) {
7214                   printf("?Array name required\n");
7215                   x = -9;
7216                   goto xhttp;
7217               }
7218               s2 = s;
7219               if (*s == CMDQ) s++;
7220               if (*s == '&') s++;
7221               if (!isalpha(*s)) {
7222                   printf("?Bad array name - \"%s\"\n",s2);
7223                   x = -9;
7224                   goto xhttp;
7225               }
7226               array = *s++;
7227               if (isupper(array))
7228                 array = tolower(array);
7229               if (*s && (*s != '[' || *(s+1) != ']')) {
7230                   printf("?Bad array name - \"%s\"\n",s2);
7231                   http_array = NUL;
7232                   x = -9;
7233                   goto xhttp;
7234               }
7235               http_array = array;
7236               break;
7237           }
7238 #endif /* NOSPL */
7239           default:
7240             x = -2;
7241             goto xhttp;
7242         }
7243     }
7244     http_action = n;                    /* Save the action */
7245     if (http_action == HTTP_PUT || http_action == HTTP_POS) {
7246         cmfdbi(&sw,                     /* 1st FDB - switch */
7247                _CMKEY,                  /* fcode */
7248                "Local filename\n Or switch", /* help */
7249                "",                      /* default */
7250                "",                      /* addtl string data */
7251                nhttpptab,               /* keyword table size */
7252                4,                       /* addtl numeric data 2: 4 = cmswi */
7253                xxstring,                /* Processing function */
7254                httpptab,                /* Keyword table */
7255                &fi                      /* Pointer to next FDB */
7256                );
7257         cmfdbi(&fi,                     /* 2nd FDB - filename */
7258                _CMIFI,                  /* fcode */
7259                "Local filename",        /* hlpmsg */
7260                "",                      /* default */
7261                "",                      /* addtl string data */
7262                0,                       /* addtl numeric data 1 */
7263                0,                       /* addtl numeric data 2 */
7264                xxstring,
7265                NULL,
7266                NULL
7267                );
7268         while (1) {
7269             x = cmfdb(&sw);
7270             if (x < 0)
7271               goto xhttp;               /* Free any malloc'd temp strings */
7272             n = cmresult.nresult;
7273             if (cmresult.fcode != _CMKEY)
7274               break;
7275             c = cmgbrk();               /* Switch... */
7276             getval = (c == ':' || c == '=');
7277             if (getval && !(cmgkwflgs() & CM_ARG)) {
7278                 printf("?This switch does not take an argument\n");
7279                 x = -9;
7280                 goto xhttp;
7281             }
7282             switch (n) {
7283               case HT_PP_MT:
7284                 s = "text/HTML";
7285                 if (getval) {
7286                     if ((x = cmfld("MIME type",
7287                                    "text/HTML",&s,xxstring)) < 0)
7288                       goto xhttp;
7289                 }
7290                 makestr(&http_mime,s);
7291                 break;
7292               default:
7293                 x = -2;
7294                 goto xhttp;
7295             }
7296         }
7297         makestr(&http_lfile,cmresult.sresult);
7298         n = ckindex("/",http_lfile,-1,1,0);
7299         if (n)
7300           p = &http_lfile[n];
7301         else
7302           p = http_lfile;
7303         if ((x = cmfld("URL or remote filename",p,&s,xxstring)) < 0) {
7304           if (x == -3) {
7305             printf("?%s what?\n",(http_action == HTTP_PUT) ? "Put" : "Post");
7306             x = -9;
7307           }
7308           goto xhttp;
7309         }
7310         if (!*s) s = NULL;
7311         makestr(&http_rfile,s);
7312
7313         if ((x = cmtxt("Response filename","",&s,xxstring)) < 0) {
7314           if (x != -3)
7315             goto xhttp;
7316         }
7317         if (*s)
7318           makestr(&http_dfile,s);
7319     }
7320     switch (http_action) {
7321       case HTTP_DEL:                    /* DELETE */
7322         if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7323           if (x == -3) {
7324             printf("?Delete what?\n");
7325             x = -9;
7326           }
7327           goto xhttp;
7328         }
7329         makestr(&http_rfile,s);
7330         break;
7331       case HTTP_CON:                    /* CONNECT */
7332         if ((x = cmfld("Remote host[:port]","",&s,xxstring)) < 0) {
7333           if (x == -3) {
7334             printf("?Remote host[:port] is required\n");
7335             x = -9;
7336           }
7337           goto xhttp;
7338         }
7339         makestr(&http_rfile,s);
7340         break;
7341       case HTTP_HED: {                  /* HEAD */
7342           char buf[CKMAXPATH+1];
7343           if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7344               if (x == -3) {
7345                   printf("?Head of what?\n");
7346                   x = -9;
7347               }
7348               goto xhttp;
7349           }
7350           makestr(&http_rfile,s);
7351
7352           if (http_array || http_type) { /* Default result filename */
7353               p = "";                    /* None if /ARRAY or /TOSCREEN */
7354           } else {
7355               n = ckindex("/",http_rfile,-1,1,0); /* Otherwise strip path */
7356               if (n)                              /* and add ".head" */
7357                 p = &http_rfile[n];
7358               else
7359                 p = http_rfile;
7360               ckmakmsg(buf,CKMAXPATH,p,".head",NULL,NULL);
7361               p = buf;
7362           }
7363           if ((x = cmofi("Local filename",p,&s,xxstring)) < 0) {
7364               if (x != -3)
7365                 goto xhttp;
7366           }
7367           makestr(&http_lfile,s);
7368           break;
7369       }
7370       case HTTP_GET:                    /* GET */
7371       case HTTP_IDX: {                  /* INDEX */
7372           char * lfile = "";
7373           if ((x = cmfld("URL or remote source file","",&s,xxstring)) < 0) {
7374               if (x == -3) {
7375                   printf("?Get what?\n");
7376                   x = -9;
7377               }
7378               goto xhttp;
7379           }
7380           makestr(&http_rfile,s);
7381           if (http_action == HTTP_GET && !http_type)
7382             zstrip(http_rfile,&lfile);
7383           if ((x = cmofi("Local filename",lfile,&s,xxstring)) < 0)
7384             if (x != -3)
7385               goto xhttp;
7386           makestr(&http_lfile,s);
7387           break;
7388       }
7389       case HTTP_OPN: {
7390           int sslswitch = 0;
7391 #ifdef CK_SSL
7392           struct FDB sw, fl;
7393           cmfdbi(&sw,
7394                  _CMKEY,                /* fcode */
7395                  "IP host name or address, or switch", /* hlpmsg */
7396                  "",                    /* default */
7397                  "",                    /* addtl string data */
7398                  2,                     /* addtl numeric data 1: tbl size */
7399                  4,                     /* addtl numeric data 2: 4 = cmswi */
7400                  xxstring,              /* Processing function */
7401                  sslswtab,              /* Keyword table */
7402                  &fl                    /* Pointer to next FDB */
7403                  );
7404           cmfdbi(&fl,                   /* 2nd FDB - host */
7405                  _CMFLD,                /* fcode */
7406                  "",                    /* hlpmsg */
7407                  "",                    /* default */
7408                  "",                    /* addtl string data */
7409                  0,                     /* addtl numeric data 1 */
7410                  0,                     /* addtl numeric data 2 */
7411                  xxstring,
7412                  NULL,
7413                  NULL
7414                  );
7415           x = cmfdb(&sw);               /* Parse switch or host */
7416           if (x < 0)                    /* Error */
7417             goto xhttp;
7418           if (cmresult.fcode == _CMFLD) { /* Host */
7419               s = cmresult.sresult;       /* Set up expected pointer */
7420               goto havehost;              /* Go parse rest of command */
7421           }
7422           sslswitch = 1;                /* /SSL or /TLS switch - set flag */
7423 #endif /* CK_SSL */
7424
7425           /* Parse host */
7426
7427           if ((x = cmfld("URL, hostname, or ip-address","",&s,xxstring)) < 0) {
7428               if (x == -3) {
7429                   printf("?Open what?\n");
7430                   x = -9;
7431               }
7432               goto xhttp;
7433           }
7434
7435         havehost:                       /* Come here with s -> host */
7436 #ifdef CK_URL
7437           x = urlparse(s,&http_url);    /* Was a URL given? */
7438           if (x < 1) {                  /* Not a URL */
7439 #endif /* CK_URL */
7440               makestr(&http_host,s);
7441               if ((x =
7442                    cmfld("Service name or port number",
7443                          sslswitch ? "https" : "http",&s,xxstring)) < 0)
7444                 goto xhttp;
7445               else
7446                 makestr(&http_srv,s);
7447 #ifdef CK_URL
7448           } else if (ckstrcmp(http_url.svc,"http",-1,0) && /* Non-HTTP URL */
7449                      ckstrcmp(http_url.svc,"https",-1,0)) {
7450               printf("?Non-HTTP URL\n");
7451               x = -9;
7452               goto xhttp;
7453           } else {                      /* Have HTTP URL */
7454               makestr(&http_srv, http_url.svc);
7455               makestr(&http_user,http_url.usr);
7456               makestr(&http_pass,http_url.psw);
7457               makestr(&http_host,http_url.hos);
7458               if (http_url.por)
7459                 makestr(&http_srv,http_url.por);
7460               makestr(&http_rfile,http_url.pth);
7461           }
7462           if (http_rfile) {             /* Open, GET, and Close */
7463               printf("?Directory/file path not allowed in HTTP OPEN URL\n");
7464               x = -9;
7465               goto xhttp;
7466           }
7467           if (!ckstrcmp("https",http_srv,-1,0) || sslswitch ||
7468               !ckstrcmp("443",http_srv,-1,0))
7469             http_ssl = 1;
7470 #endif /* CK_URL */
7471           break;
7472       }
7473       case HTTP_CLS:
7474         break;
7475     }
7476     if ((x = cmcfm()) < 0)
7477       goto xhttp;
7478
7479     if (http_action == HTTP_OPN) {
7480         x = (http_open(http_host,http_srv,http_ssl,rdns,128,http_agent) == 0);
7481         if (x) {
7482             if (!quiet) {
7483               if (rdns[0])
7484                 printf("Connected to %s [%s]\r\n",http_host,rdns);
7485               else
7486                 printf("Connected to %s\r\n",http_host);
7487             }
7488             if (http_agent) {
7489                 if (http_d_agent)
7490                   free(http_d_agent);
7491                 http_d_agent = http_agent;
7492                 http_agent = NULL;
7493             }
7494             if (http_user) {
7495                 if (http_d_user)
7496                   free(http_d_user);
7497                 http_d_user = http_user;
7498                 http_user = NULL;
7499             }
7500             if (http_pass) {
7501                 if (http_d_pass) {
7502                     memset(http_d_pass,0,strlen(http_d_pass));
7503                     free(http_d_pass);
7504                 }
7505                 http_d_pass = http_pass;
7506                 http_pass = NULL;
7507             }
7508             http_d_type = http_type;
7509         } else {
7510             if (!quiet)
7511               printf("?HTTP Connection failed.\r\n");
7512         }
7513     } else if (http_action == HTTP_CLS) {
7514         if (http_d_agent) {
7515             free(http_d_agent);
7516             http_d_agent = NULL;
7517         }
7518         if (http_d_user) {
7519             free(http_d_user);
7520             http_d_user = NULL;
7521         }
7522         if (http_d_pass) {
7523             memset(http_d_pass,0,strlen(http_d_pass));
7524             free(http_d_pass);
7525             http_d_pass = NULL;
7526         }
7527         http_d_type = 0;
7528         x = (http_close() == 0);
7529     }
7530     if ((http_action != HTTP_CLS) &&
7531         (http_action != HTTP_CON) && http_rfile) { /* Remote file is URL? */
7532
7533         /* All-in-one actions when a URL is given... */
7534
7535 #ifdef CK_URL
7536         if (urlparse(http_rfile,&http_url) > 0) { /* Have URL? */
7537             if (ckstrcmp(http_url.svc,"http",-1,0) && /* It's an HTTP URL? */
7538                 ckstrcmp(http_url.svc,"https",-1,0)) {
7539                 printf("?Non-HTTP URL\n");
7540                 x = -9;
7541                 goto xhttp;
7542             } else {                    /* Yes, collect the pieces */
7543                 makestr(&http_srv, http_url.svc);
7544                 makestr(&http_user,http_url.usr);
7545                 makestr(&http_pass,http_url.psw);
7546                 makestr(&http_host,http_url.hos);
7547                 if (http_url.por)
7548                   makestr(&http_srv,http_url.por);
7549                 makestr(&http_rfile,http_url.pth);
7550             }
7551             if (!http_rfile) {          /* Still have a path? */
7552                 makestr(&http_rfile,"/");
7553             }
7554             if (!ckstrcmp("https",http_srv,-1,0) || /* Check for SSL/TLS */
7555                 !ckstrcmp("443",http_srv,-1,0))
7556               http_ssl = 1;
7557             if (http_isconnected())     /* Close any open HTTP connection */
7558               http_close();
7559             if (http_pass == NULL && http_d_pass != NULL)
7560               makestr(&http_pass,http_d_pass);
7561             x = (http_open(http_host,
7562                            http_srv,http_ssl,rdns,128,http_d_agent) == 0);
7563             if (x < 0) {
7564                 x = 0;
7565                 goto xhttp;
7566             }
7567             allinone = 1;
7568         }
7569 #endif /* CK_URL */
7570         if (http_pass == NULL && http_d_pass != NULL)
7571           makestr(&http_pass,http_d_pass);
7572
7573         if (http_action == HTTP_OPN && allinone) {
7574             http_action = HTTP_GET;
7575         }
7576         x = xdohttp(http_action,
7577                     http_lfile,
7578                     http_rfile,
7579                     http_dfile,
7580                     http_agent ? http_agent : http_d_agent,
7581                     http_hdr,
7582                     http_user  ? http_user  : http_d_user,
7583                     http_pass  ? http_pass  : http_d_pass,
7584                     http_mime,
7585                     http_array,
7586                     http_type
7587                     );
7588         if (allinone)
7589           x = (http_close() == 0);
7590     }
7591
7592   xhttp:
7593     if (http_agent) free(http_agent);
7594     if (http_hdr)   free(http_hdr);
7595     if (http_user)  free(http_user);
7596     if (http_pass) {
7597         memset(http_pass,0,strlen(http_pass));
7598         free(http_pass);
7599     }
7600     if (http_mime)  free(http_mime);
7601     if (http_lfile) free(http_lfile);
7602     if (http_rfile) free(http_rfile);
7603     if (http_dfile) free(http_dfile);
7604     if (http_host)  free(http_host);
7605     if (http_srv)   free(http_srv);
7606
7607     if (x > -1)
7608       success = x;
7609     return(x);
7610 }
7611 #endif /* TCPSOCKET */
7612 #endif /* NOHTTP */
7613
7614
7615 #ifndef NOSPL
7616 static int
7617 dotrace() {
7618     int on = 1;
7619     struct FDB sw, kw;
7620     cmfdbi(&sw,                         /* 1st FDB - switch */
7621            _CMKEY,                      /* fcode */
7622            "Trace object;\n Or switch", /* help */
7623            "",                          /* default */
7624            "",                          /* addtl string data */
7625            2,                           /* keyword table size */
7626            4,                           /* addtl numeric data 2: 4 = cmswi */
7627            xxstring,                    /* Processing function */
7628            onoffsw,                     /* Keyword table */
7629            &kw                          /* Pointer to next FDB */
7630            );
7631     cmfdbi(&kw,                         /* 2nd FDB - Trace object */
7632            _CMKEY,                      /* fcode */
7633            "Trace object",              /* help */
7634            "all",                       /* default */
7635            "",                          /* addtl string data */
7636            ntracetab,                   /* keyword table size */
7637            0,                           /* addtl numeric data 2: 0 = keyword */
7638            xxstring,                    /* Processing function */
7639            tracetab,                    /* Keyword table */
7640            NULL                         /* Pointer to next FDB */
7641            );
7642     if ((x = cmfdb(&sw)) < 0)
7643       return(x);
7644     if (cmresult.fdbaddr == &sw) {
7645         on = cmresult.nresult;
7646         if ((x = cmkey(tracetab, ntracetab,"","all",xxstring)) < 0)
7647           return(x);
7648     } else {
7649         x = cmresult.nresult;
7650     }
7651     if ((y = cmcfm()) < 0)
7652       return(y);
7653
7654     switch (x) {
7655       case TRA_ASG:
7656         tra_asg = on;
7657         break;
7658       case TRA_CMD:
7659         tra_cmd = on;
7660         break;
7661       case TRA_ALL:
7662         tra_asg = on;
7663         tra_cmd = on;
7664         break;
7665       default:
7666         return(-2);
7667     }
7668     printf("TRACE %s\n", on ? "ON" : "OFF");
7669     return(success = 1);
7670 }
7671 #endif /* NOSPL */
7672
7673
7674 static int
7675 doprompt() {
7676     extern int xcmdsrc;
7677     if ((x = cmtxt("Optional message","",&s,xxstring)) < 0)
7678       return(x);
7679 #ifdef NOSPL
7680     printf("?Sorry, PROMPT requires script programming language\n");
7681     return(-9);
7682 #else
7683     debug(F101,"Prompt cmdlvl","",cmdlvl);
7684     cmdlvl++;
7685     if (cmdlvl > CMDSTKL) {
7686         printf("?Command stack overflow: %d\n",cmdlvl);
7687         cmdlvl--;
7688         return(-9);
7689     }
7690     xcmdsrc = CMD_KB;
7691     cmdstk[cmdlvl].src = CMD_KB;        /* Say we're at the prompt */
7692     cmdstk[cmdlvl].lvl = 0;
7693     cmdstk[cmdlvl].ccflgs = cmdstk[cmdlvl-1].ccflgs;
7694     if (tra_cmd)
7695       printf("[%d] +P: \"(prompt)\"\n",cmdlvl);
7696     concb((char)escape);
7697     if (!quiet)
7698       printf(
7699 "(Recursive command prompt: Resume script with CONTINUE, STOP to stop...)\n"
7700             );
7701     if (*s) {                           /* If prompt given */
7702         makestr(&(prstring[cmdlvl-1]),cmgetp()); /* Save current prompt */
7703         cmsetp(s);                      /* Set new one */
7704     }
7705     return(success = 1);
7706 #endif /* NOSPL */
7707 }
7708
7709 #ifdef CKLEARN
7710 VOID
7711 learncmd(s) char *s; {                  /* Record commands in learned script */
7712     char buf[64];
7713     int i, k;
7714     if (learnfp && learning) {          /* Only if open and on */
7715         k = ckstrncpy(buf,s,64);
7716         for (i = 0; i < k; i++) {       /* Get top-level command keyword */
7717             if (buf[i] <= SP) {
7718                 buf[i] = NUL;
7719                 break;
7720             }
7721         }
7722         k = lookup(cmdtab,buf,ncmd,NULL); /* Look it up */
7723         if (k == XXCON || k == XXLEARN)   /* Don't record CONNECT or LEARN */
7724           return;
7725         if (k == XXTEL) {
7726             fputs("SET HOST /NETWORK:TCP",learnfp);
7727             fputs(&s[i],learnfp);
7728             fputs(" TELNET /TELNET",learnfp);
7729             fputs("\nIF FAIL STOP 1 Connection failed\n",learnfp);
7730         } else {
7731             fputs(s,learnfp);
7732             fputs("\n",learnfp);
7733         }
7734     }
7735 }
7736 #endif /* CKLEARN */
7737
7738
7739 /*  D O C M D  --  Do a command  */
7740
7741 /*
7742  Returns:
7743    -2: user typed an illegal command
7744    -1: reparse needed
7745     0: parse was successful (even tho command may have failed).
7746 */
7747 #ifdef DEBUG
7748 int cmdstats[256] = { -1, -1 };
7749 #endif /* DEBUG */
7750
7751 int
7752 docmd(cx) int cx; {
7753     extern int nolocal, cmkwflgs;
7754
7755     debug(F101,"docmd entry, cx","",cx);
7756     activecmd = cx;
7757     doconx = ((activecmd == XXCON)  || (activecmd == XXTEL) ||
7758               (activecmd == XXRLOG) || (activecmd == XXPIPE) ||
7759               (activecmd == XXIKSD) || (activecmd == XXPTY));
7760 /*
7761   Originally all commands were handled with a big switch() statement,
7762   but eventually this started blowing up compilers.  Now we have a series
7763   of separate if statements and small switches, with the commands that are
7764   most commonly executed in scipts and loops coming first, to speed up
7765   compute-bound scripts.
7766   */
7767
7768 #ifdef DEBUG
7769     if (cmdstats[0] == -1) {            /* Count commands */
7770         int i;                          /* for tuning... */
7771         for (i = 0; i < 256; i++)
7772           cmdstats[i] = 0;
7773     }
7774 #endif /* DEBUG */
7775
7776     switch (cx) {
7777       case -4:                          /* EOF */
7778 #ifdef OSK
7779         if (msgflg)  printf("\n");
7780 #else
7781         if (msgflg)  printf("\r\n");
7782 #endif /* OSK */
7783           doexit(GOOD_EXIT,xitsta);
7784       case -3:                          /* Null command */
7785         return(0);
7786       case -9:                          /* Like -2, but errmsg already done */
7787       case -1:                          /* Reparse needed */
7788         return(cx);
7789       case -6:                          /* Special */
7790       case -2:                          /* Error, maybe */
7791
7792 #ifndef NOSPL
7793 /*
7794   Maybe they typed a macro name.  Let's look it up and see.
7795 */
7796         if (cx == -6)                   /* If they typed CR */
7797           ckstrncat(cmdbuf,"\015",CMDBL); /*  add it back to command buffer. */
7798         if (ifcmd[cmdlvl] == 2)         /* Watch out for IF commands. */
7799           ifcmd[cmdlvl]--;
7800         repars = 1;                     /* Force reparse */
7801         cmres();
7802         cx = XXDO;                      /* Try DO command */
7803 #else
7804         return(cx);
7805 #endif /* NOSPL */
7806       default:
7807         if (cx < 0)
7808           return(cx);
7809         break;
7810     }
7811 #ifdef DEBUG
7812     if (cx < 256)
7813       cmdstats[cx]++;
7814 #endif /* DEBUG */
7815
7816     if ((cmkwflgs & CM_PSH)
7817 #ifndef NOPUSH
7818         && nopush
7819 #endif /* NOPUSH */
7820         ) {
7821         printf("?Access to system disabled\n");
7822         return(-9);
7823     }
7824     if ((cmkwflgs & CM_LOC)
7825 #ifndef NOLOCAL
7826         && nolocal
7827 #endif /* NOLOCAL */
7828         ) {
7829         printf("?Connections disabled\n");
7830         return(-9);
7831     }
7832
7833 #ifndef NOSPL
7834     /* Used in FOR loops */
7835
7836     if (cx == XX_INCR || cx == XXINC  || /* _INCREMENT, INCREMENT */
7837         cx == XX_DECR || cx == XXDEC)    /* _DECREMENT, DECREMENT */
7838       return(doincr(cx));
7839
7840     /* Define (or change the definition of) a macro or variable */
7841
7842     if (cx == XXUNDEF || cx == XXUNDFX) {
7843 #ifdef IKSD
7844         if (inserver && !ENABLED(en_asg)) {
7845             printf("?Sorry, DEFINE/ASSIGN disabled\n");
7846             return(-9);
7847         }
7848 #endif /* IKSD */
7849         return(doundef(cx));            /* [_]UNDEFINE */
7850     }
7851     if (cx == XXDEF || cx == XXASS ||
7852         cx == XXDFX || cx == XXASX) {
7853 #ifdef IKSD
7854         if (inserver && !ENABLED(en_asg)) {
7855             printf("?Sorry, DEFINE/ASSIGN disabled\n");
7856             return(-9);
7857         }
7858 #endif /* IKSD */
7859         if (atmbuf[0] == '.' && !atmbuf[1]) /* "." entered as keyword */
7860           xxdot = 1;                    /* i.e. with space after it... */
7861         return(dodef(cx));              /* DEFINE, ASSIGN, etc... */
7862     }
7863
7864     /* IF, WHILE, and friends  */
7865
7866     if (cx == XXIF || cx == XXIFX || cx == XXWHI || cx == XXASSER) {
7867         return(doif(cx));
7868     }
7869     if (cx == XXSWIT) {                 /* SWITCH */
7870         return(doswitch());
7871     }
7872
7873     /* GOTO, FORWARD, and _FORWARD (used internally by FOR, WHILE, etc) */
7874
7875     if (cx == XXGOTO || cx == XXFWD || cx == XXXFWD) { /* GOTO or FORWARD */
7876         /* Note, here we don't set SUCCESS/FAILURE flag */
7877 #ifdef COMMENT
7878         if ((y = cmfld("label","",&s,xxstring)) < 0) {
7879             if (y == -3) {
7880                 if (cx != XXXFWD) {
7881                     printf("?Label name required\n");
7882                     return(-9);
7883                 }
7884             } else
7885               return(y);
7886         }
7887         ckstrncpy(lblbuf,s,LBLSIZ);
7888         if ((x = cmcfm()) < 0) return(x);
7889 #else
7890         if ((y = cmtxt("label","",&s,xxstring)) < 0) {
7891             if (y == -3) {
7892                 if (cx != XXXFWD) {
7893                     printf("?GOTO: Label name required: \"%s\" \"%s\"\n",
7894                            atmbuf,
7895                            cmdbuf);
7896                     return(-9);
7897                 }
7898             } else
7899               return(y);
7900         }
7901         ckstrncpy(lblbuf,brstrip(s),LBLSIZ);
7902 #endif /* COMMENT */
7903         s = lblbuf;
7904         debug(F111,"GOTO target",s,cx);
7905         return(dogoto(s,cx));
7906     }
7907     if (cx == XXDO || cx == XXMACRO) {  /* DO (a macro) */
7908         char mnamebuf[16];              /* (buffer for controlled temp name) */
7909         struct FDB kw, fl;
7910         int mx;                         /* Macro index (on stack!) */
7911
7912         debug(F101,"XXMACRO 0",line,cx);
7913         if (cx == XXDO) {
7914             if (nmac == 0) {
7915                 printf("\n?No macros defined\n");
7916                 return(-9);
7917             }
7918             for (y = 0; y < nmac; y++) { /* copy the macro table into a */
7919                 mackey[y].kwd = mactab[y].kwd; /* regular keyword table */
7920                 mackey[y].kwval = y;    /* with value = pointer to macro tbl */
7921                 mackey[y].flgs = mactab[y].flgs;
7922             }
7923             cmfdbi(&kw,                 /* First FDB - macro name */
7924                    _CMKEY,              /* fcode */
7925                    "Macro",             /* hlpmsg */
7926                    "",                  /* default */
7927                    "",                  /* addtl string data */
7928                    nmac,                /* addtl numeric data 1: tbl size */
7929                    0,                   /* addtl numeric data 2: 0 = cmkey */
7930                    xxstring,            /* Processing function */
7931                    mackey,              /* Keyword table */
7932                    &fl                  /* Pointer to next FDB */
7933                    );
7934             cmfdbi(&fl,                 /* 2nd FDB - for "{" */
7935                    _CMFLD,              /* fcode */
7936                    "",                  /* hlpmsg */
7937                    "",
7938                    "",                  /* addtl string data */
7939                    0,                   /* addtl numeric data 1 */
7940                    0,                   /* addtl numeric data 2 */
7941                    xxstring,
7942                    NULL,
7943                    NULL
7944                    );
7945             x = cmfdb(&kw);             /* Parse something */
7946             if (x < 0) {                /* Error */
7947                 if (x == -3) {
7948                     printf("?Macro name required\n");
7949                     return(-9);
7950                 } else
7951                   return(x);
7952             }
7953             if (cmresult.fcode == _CMKEY) {
7954                 extern int mtchanged;
7955                 char * macroname = NULL;
7956
7957             /* In case args include an \fexec() that changes the macro table */
7958
7959                 mx = x;                 /* Save macro index on stack */
7960                 mtchanged = 0;          /* Mark state of macro table */
7961                 makestr(&macroname,mactab[mx].kwd); /* Save name */
7962
7963                 if ((y = cmtxt("optional arguments","",&s,xxstring)) < 0)
7964                   return(y);            /* Get macro args */
7965
7966                 if (mtchanged) {        /* Macro table changed? */
7967                     mx = mlook(mactab,macroname,nmac); /* Look up name again */
7968                 }
7969                 if (macroname)
7970                   free(macroname);
7971
7972                 return(dodo(mx,s,cmdstk[cmdlvl].ccflgs) < 1 ?
7973                        (success = 0) : 1);
7974             }
7975             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* _CMFLD */
7976             if (atmbuf[0] == '{') {
7977                 if ((y = cmcfm()) < 0)
7978                   return(y);
7979             }
7980         } else {                        /* XXMACRO ("immediate macro") */
7981             int k = 0;
7982             line[k++] = '{';
7983             line[k++] = SP;
7984             line[k] = NUL;
7985             debug(F111,"XXMACRO A",line,k);
7986             /* Defer evaluation of variables until the commands are exec'd */
7987             if ((y = cmtxt("Braced list of commands","",&s,NULL)) < 0)
7988               return(y);
7989             k = ckstrncpy(line+k,s,LINBUFSIZ-k);
7990             debug(F111,"XXMACRO B",line,k);
7991         }
7992         x = strlen(line);
7993         if ((line[0] == '{' && line[x-1] != '}') || line[0] == '}')
7994           return(-2);
7995         if (line[0] != '{' && line[x-1] != '}') {
7996             /* Unknown command.  If ON_UNKNOWN_COMMAND macro is defined, */
7997             /* parse args and then execute it, but only if it is not */
7998             /* already active. */
7999             int k = -1;
8000             if (!unkmacro) {
8001                 k = mxlook(mactab,"on_unknown_command",nmac);
8002             }
8003             if (k > -1) {
8004                 ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
8005                 z = maclvl;             /* Save the current maclvl */
8006                 if ((y = cmtxt("text","",&s,xxstring)) < 0)
8007                   return(y);
8008                 ckstrncat(tmpbuf," ",TMPBUFSIZ);
8009                 ckstrncat(tmpbuf,s,TMPBUFSIZ);
8010                 unkmacro = 1;
8011                 debug(F110,"ON_UNKNOWN_COMMAND",s,0);
8012                 dodo(k,tmpbuf,cmdstk[cmdlvl].ccflgs); /* Run the macro */
8013                 while (maclvl > z) {
8014                     sstate = (CHAR) parser(1);
8015                     if (sstate) proto();
8016                 }
8017                 debug(F101,"UNKMAC loop exit maclvl","",maclvl);
8018                 unkmacro = 0;
8019                 return(success);
8020             }
8021             if (x > 0)
8022               printf("?Not a command or macro name: \"%s\"\n",line);
8023             else
8024               printf("?Not a command or macro name.\n");
8025             return(-9);
8026         }
8027         s = brstrip(line);
8028         sprintf(mnamebuf," ..tmp:%03d",cmdlvl); /* safe (16) */
8029         x = addmac(mnamebuf,s);
8030         return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs) < 1 ? (success = 0) : 1);
8031     }
8032
8033     if (cx == XXLBL) {                  /* LABEL */
8034         if ((x = cmfld("label","",&s,xxstring)) < 0) {
8035             if (x == -3) {
8036 #ifdef COMMENT
8037                 printf("?LABEL: Label name required: \"%s\"\n", cmdbuf);
8038                 return(-9);
8039 #else
8040                 s = "";
8041 #endif /* COMMENT */
8042             } else return(x);
8043
8044         }
8045         debug(F111,"LABEL",s,x);
8046         if ((x = cmcfm()) < 0) return(x);
8047         return(0);
8048     }
8049
8050     if (cx == XXEVAL || cx == XX_EVAL) /* _EVALUATE,  EVALUATE  */
8051       return(doeval(cx));
8052
8053 #ifndef NOSEXP
8054     if (cx == XXSEXP) {                 /* Lisp-like S-Expression */
8055         struct stringarray * q;
8056         char /* *p, *r, */ *tmp, *m;
8057         int i, k, n, quote = 0, contd = 0, size = 0, len = 0;
8058         extern int sexprc, sexppv;
8059
8060         tmp = tmpbuf;                   /* Buffer to collect SEXP */
8061         tmpbuf[0] = NUL;                /* Clear it */
8062         size = TMPBUFSIZ;               /* Capacity of buffer */
8063         sexprc = -1;                    /* Assume bad input */
8064         n = 0;                          /* Paren balance counter */
8065
8066         while (1) {                     /* Allow SEXP on multiple lines */
8067             m = contd ?
8068               "Continuation of S-Expression" :
8069                 "S-Expression (\"help sexp\" for details)";
8070             x = cmtxt(m,"",&s,xxstring);
8071             if (x < 0)
8072               return(x);
8073             if (!*s)                    /* Needed for (=) and (:) */
8074               s = atmbuf;
8075             k = ckmakmsg(tmp, size, contd ? " " : "(", s, NULL, NULL);
8076             if (k < 1) {
8077                 printf("?SEXP too long - %d max\n",TMPBUFSIZ);
8078                 return(-9);
8079             }
8080             debug(F111,contd ? "sexp contd" : "sexp",s,k);
8081
8082             for (i = len; i < len+k; i++) { /* Check balance  */
8083                 if (!quote && tmpbuf[i] == CMDQ) {
8084                     quote = 1;
8085                     continue;
8086                 }
8087                 if (quote) {
8088                     quote = 0;
8089                     continue;
8090                 }
8091                 if (tmpbuf[i] == '(')
8092                   n++;
8093                 else if (tmpbuf[i] == ')')
8094                   n--;
8095             }
8096             if (n == 0) {               /* Break when balanced */
8097                 break;
8098             }
8099             if (n < 0) {                /* Too many right parens */
8100                 printf("?Unbalanced S-Expression: \"%s\"\n",tmpbuf);
8101                 return(-9);
8102             }
8103             contd++;                    /* Need more right parens */
8104             cmini(ckxech);              /* so keep parsing */
8105             tmp += k;                   /* adjust buffer pointer */
8106             size -= k;                  /* and capacity */
8107             len += k;                   /* and length so far */
8108         }
8109         s = tmpbuf;
8110         makestr(&lastsexp,s);
8111         q = cksplit(1,SEXPMAX,s,NULL,NULL,8,0,0); /* Precheck for > 1 SEXP */
8112         debug(F101,"sexp split","",q->a_size);
8113
8114         if (q->a_size == 1) {           /* We should get exactly one back */
8115             char * result, * dosexp();
8116             sexprc = 0;                 /* Reset out-of-band return code */
8117             result = dosexp(s);         /* Get result */
8118             debug(F111,"sexp result",result,sexprc);
8119             if (sexprc == 0) {          /* Success */
8120                 /* Echo the result if desired */
8121                 if ((!xcmdsrc && sexpecho != SET_OFF) || sexpecho == SET_ON)
8122                   printf(" %s\n",result ? result : "");
8123                 makestr(&sexpval,result);
8124                 success = sexppv > -1 ? sexppv : 1;
8125                 return(success);
8126             }
8127         }
8128         if (sexprc < 0)
8129           printf("?Invalid S-Expression: \"%s\"\n",lastsexp);
8130         return(-9);
8131     }
8132 #endif /* NOSEXP */
8133
8134 #endif /* NOSPL */
8135
8136     if (cx == XXECH || cx == XXXECH || cx == XXVOID
8137 #ifndef NOSPL
8138         || cx == XXAPC
8139 #endif /* NOSPL */
8140         ) {                             /* ECHO or APC */
8141         if ((x = cmtxt((cx == XXECH || cx == XXXECH) ?
8142                        "Text to be echoed" :
8143                        ((cx == XXVOID) ? "Text" :
8144                         "Application Program Command text"),
8145                        "",
8146                        &s,
8147                        xxstring
8148                        )
8149              ) < 0)
8150           return(x);
8151         if (!s) s = "";
8152 #ifdef COMMENT
8153 /* This is to preserver the pre-8.0 behavior but it's too confusing */
8154         x = strlen(s);
8155         x = (x > 1) ? ((s[0] == '"' && s[x-1] == '"') ? 1 : 0) : 0;
8156 #endif /* COMMENT */
8157         s = brstrip(s);                 /* Strip braces and doublequotes */
8158         if (cx == XXECH) {              /* ECHO */
8159 #ifndef NOSPL
8160             if (!fndiags || fnsuccess) {
8161 #endif /* NOSPL */
8162 #ifdef COMMENT
8163                 /* The "if (x)" business preserves previous behavior */
8164                 /* by putting back the doublequotes if they were included. */
8165                 if (x)
8166                   printf("\"%s\"\n",s);
8167                 else
8168 #endif /* COMMENT */
8169                   printf("%s\n",s);
8170 #ifndef NOSPL
8171             }
8172 #endif /* NOSPL */
8173         } else if (cx == XXXECH) {      /* XECHO */
8174             if (x)
8175               printf("\"%s\"",s);
8176             else
8177               printf("%s",s);
8178 #ifdef UNIX
8179             fflush(stdout);
8180 #endif /* UNIX */
8181         } else if (cx == XXAPC) {       /* APC */
8182 #ifdef CK_APC
8183             if (apcactive == APC_LOCAL ||
8184                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
8185               return(success = 0);
8186 #endif /* CK_APC */
8187             if (!local) {
8188                 printf("%c_%s%c\\",ESC,s,ESC);
8189 #ifdef UNIX
8190                 fflush(stdout);
8191 #endif /* UNIX */
8192
8193             } else {                    /* Local mode - have connection */
8194 #ifndef NOSPL
8195                 if (ckmakxmsg(tmpbuf,   /* Form APC string in buffer */
8196                               TMPBUFSIZ,
8197                               ckctoa((char)ESC),
8198                               ckctoa('_'),
8199                               s,
8200                               ckctoa((char)ESC),
8201                               ckctoa('\\'),
8202                               NULL,NULL,NULL,NULL,NULL,NULL,NULL
8203                               ) > 0)
8204                   return(success = dooutput(tmpbuf, XXOUT));
8205                 printf("?Too long\n");
8206                 return(-9);
8207 #else
8208                 printf("%c_%s%c\\",ESC,s,ESC);
8209 #endif /* NOSPL */
8210             }
8211         }
8212         return(success = 1);
8213     }
8214
8215 #ifndef NOSPL
8216 /* Copy macro args from/to two levels up, used internally by _floop et al. */
8217     if (cx == XXGTA || cx == XXPTA) {   /* _GETARGS, _PUTARGS */
8218         int x;
8219         debug(F101,"docmd XXGTA","",XXGTA);
8220         debug(F101,"docmd cx","",cx);
8221         debug(F101,"docmd XXGTA maclvl","",maclvl);
8222         x = dogta(cx);
8223         debug(F101,"docmd dogta returns","",x);
8224         debug(F101,"docmd dogta maclvl","",maclvl);
8225         return(x);
8226     }
8227 #endif /* NOSPL */
8228
8229 #ifndef NOSPL
8230 #ifdef CKCHANNELIO
8231     if (cx == XXFILE)
8232       return(dofile(cx));
8233     else if (cx == XXF_RE || cx == XXF_WR || cx == XXF_OP ||
8234              cx == XXF_CL || cx == XXF_SE || cx == XXF_RW ||
8235              cx == XXF_FL || cx == XXF_LI || cx == XXF_ST || cx == XXF_CO)
8236       return(dofile(cx));
8237 #endif /* CKCHANNELIO */
8238
8239 /* ASK, ASKQ, READ */
8240     if (cx == XXASK  || cx == XXASKQ || cx == XXREA ||
8241         cx == XXRDBL || cx == XXGETC || cx == XXGETK) {
8242         return(doask(cx));
8243     }
8244 #endif /* NOSPL */
8245
8246 #ifndef NOFRILLS
8247     if (cx == XXBUG) {                  /* BUG */
8248         if ((x = cmcfm()) < 0) return(x);
8249         return(dobug());
8250     }
8251 #endif /* NOFRILLS */
8252
8253 #ifndef NOXFER
8254     if (cx == XXBYE) {                  /* BYE */
8255         extern int ftp_cmdlin;
8256         if ((x = cmcfm()) < 0) return(x);
8257
8258 #ifdef NEWFTP
8259         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
8260             extern int stayflg, ftp_fai;
8261             success = ftpbye();
8262             if (ftp_cmdlin && !stayflg && !local)
8263               doexit(ftp_fai ? BAD_EXIT : GOOD_EXIT,-1);
8264             else
8265               return(success);
8266         }
8267 #endif /* NEWFTP */
8268
8269         if (!local) {
8270             printf("?No connection - use EXIT to quit.\n");
8271             return(-9);
8272         }
8273
8274 #ifdef CK_XYZ
8275         if (protocol != PROTO_K) {
8276             printf("?Sorry, BYE only works with Kermit protocol\n");
8277             return(-9);
8278         }
8279 #endif /* CK_XYZ */
8280
8281 #ifdef IKS_OPTION
8282         if (
8283 #ifdef CK_XYZ
8284             protocol == PROTO_K &&
8285 #endif /* CK_XYZ */
8286             !iks_wait(KERMIT_REQ_START,1)) {
8287             printf(
8288              "?A Kermit Server is not available to process this command\n");
8289             return(-9);                 /* Correct the return code */
8290         }
8291 #endif /* IKS_OPTION */
8292
8293         bye_active = 1;
8294         sstate = setgen('L',"","","");
8295         if (local) ttflui();            /* If local, flush tty input buffer */
8296         return(0);
8297     }
8298 #endif /* NOXFER */
8299
8300     if (cx == XXBEEP) {                 /* BEEP */
8301         int x;
8302 #ifdef OS2
8303         int y;
8304         if ((y = cmkey(beeptab, nbeeptab, "which kind of beep", "information",
8305                        xxstring)) < 0 )
8306           return (y);
8307         if ((x = cmcfm()) < 0) return(x);
8308         bleep((short)y);                /* y is one of the BP_ values */
8309 #else  /* OS2 */
8310         if ((x = cmcfm()) < 0) return(x);
8311 #ifndef NOSPL
8312         bleep(BP_NOTE);
8313 #else
8314         putchar('\07');
8315 #endif /* NOSPL */
8316 #endif /* OS2 */
8317         return(0);
8318     }
8319
8320 #ifndef NOFRILLS
8321     if (cx == XXCLE)                    /* CLEAR */
8322       return(success = doclear());
8323 #endif /* NOFRILLS */
8324
8325     if (cx == XXCOM) {                  /* COMMENT */
8326         if ((x = cmtxt("Text of comment line","",&s,NULL)) < 0)
8327           return(x);
8328         /* Don't change SUCCESS flag for this one */
8329         return(0);
8330     }
8331
8332 #ifndef NOLOCAL
8333     if (cx == XXCON || cx == XXCQ)      /* CONNECT or CONNECT /QUIETLY */
8334       return(doxconn(cx));
8335 #endif /* NOLOCAL */
8336
8337 #ifndef NOFRILLS
8338 #ifdef ZCOPY
8339     if (cx == XXCPY) {                  /* COPY a file */
8340 #ifdef IKSD
8341         if (inserver && !ENABLED(en_cpy)) {
8342             printf("?Sorry, COPY is disabled\n");
8343             return(-9);
8344         }
8345 #endif /* IKSD */
8346 #ifdef CK_APC
8347         if (apcactive == APC_LOCAL ||
8348             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
8349             )
8350           return(success = 0);
8351 #endif /* CK_APC */
8352         return(docopy());
8353     }
8354 #endif /* ZCOPY */
8355 #ifdef NT
8356     if ( cx == XXLINK ) {
8357 #ifdef IKSD
8358         if (inserver && !ENABLED(en_cpy)) {
8359             printf("?Sorry, LINK (COPY) is disabled\n");
8360             return(-9);
8361         }
8362 #endif /* IKSD */
8363 #ifdef CK_APC
8364         if (apcactive == APC_LOCAL ||
8365             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
8366             )
8367           return(success = 0);
8368 #endif /* CK_APC */
8369         return(dolink());
8370     }
8371 #endif /* NT */
8372 #endif /* NOFRILLS */
8373
8374     /* CD and friends */
8375     if (cx == XXCWD  || cx == XXCDUP || cx == XXBACK ||
8376         cx == XXLCWD || cx == XXLCDU || cx == XXKCD) {
8377 #ifdef LOCUS
8378         if (!locus) {
8379             if (cx == XXCWD) {
8380 #ifdef NOXFER
8381                 return(-2);
8382 #else
8383                 return(dormt(XZCWD));
8384 #endif /* NOXFER */
8385             } else if (cx == XXCDUP) {
8386 #ifdef NOXFER
8387                 return(-2);
8388 #else
8389                 return(dormt(XZCDU));
8390 #endif /* NOXFER */
8391             }
8392         }
8393 #endif /* LOCUS */
8394 #ifdef IKSD
8395         if (inserver && !ENABLED(en_cwd)) {
8396             printf("?Sorry, changing directories is disabled\n");
8397             return(-9);
8398         }
8399 #endif /* IKSD */
8400         return(success = docd(cx));
8401     }
8402
8403     if (cx == XXCHK)                    /* CHECK */
8404       return(success = dochk());
8405
8406     if (cx == XXCLO) {                  /* CLOSE */
8407         x = cmkey(clstab,ncls,"\"CONNECTION\", or log or file to close",
8408                   "connection",xxstring);
8409         if (x == -3) {
8410             printf("?You must say which file or log\n");
8411             return(-9);
8412         }
8413         if (x < 0) return(x);
8414         if ((y = cmcfm()) < 0) return(y);
8415 #ifndef NOLOCAL
8416         if (x == 9999) {                /* CLOSE CONNECTION */
8417             x = clsconnx(0);
8418             switch (x) {
8419               case 0:
8420                 if (msgflg) printf("?Connection was not open\n");
8421               case -1:
8422                 return(0);
8423               case 1:
8424                 whyclosed = WC_CLOS;
8425                 return(1);
8426             }
8427             return(0);
8428         }
8429 #endif /* NOLOCAL */
8430         y = doclslog(x);
8431         success = (y == 1);
8432         return(success);
8433     }
8434
8435 #ifndef NOSPL
8436     if (cx == XXDCL || cx == XXUNDCL) { /* DECLARE an array */
8437         return(dodcl(cx));
8438     }
8439 #endif /* NOSPL */
8440
8441 #ifndef NODIAL
8442     if (cx == XXRED  || cx == XXDIAL || cx == XXPDIA ||
8443         cx == XXANSW || cx == XXLOOK) { /* DIAL, REDIAL etc */
8444 #ifdef VMS
8445         extern int batch;
8446 #else
8447 #ifdef UNIXOROSK
8448         extern int backgrd;
8449 #endif /* UNIXOROSK */
8450 #endif /* VMS */
8451         x = dodial(cx);
8452         debug(F101,"dodial returns","",x);
8453         if ((cx == XXDIAL || cx == XXRED || cx == XXANSW) &&
8454             (x > 0) &&                  /* If DIAL or REDIAL succeeded */
8455             (dialsta != DIA_PART) &&    /* and it wasn't partial */
8456             (dialcon > 0)) {
8457             if ((dialcon == 1 ||        /* And DIAL CONNECT is ON, */
8458                 ((dialcon == 2) &&      /* or DIAL CONNECT is AUTO */
8459                  !xcmdsrc               /* and we're at top level... */
8460 #ifdef VMS
8461                  && !batch              /* Not if running from batch */
8462 #else
8463 #ifdef UNIXOROSK
8464                  && !backgrd            /* Not if running in background */
8465 #endif /* UNIXOROSK */
8466 #endif /* VMS */
8467                  ))) /* Or AUTO */
8468               x = doconect(dialcq,      /* Then also CONNECT */
8469                            cmdlvl == 0 ? 1 : 0
8470                            );
8471             if (ttchk() < 0)
8472               dologend();
8473         }
8474         return(success = x);
8475     }
8476 #endif /* NODIAL */
8477
8478 #ifndef NOPUSH
8479 #ifdef CK_REXX
8480     if (cx == XXREXX) {                 /* REXX */
8481         extern int nopush;
8482         if ( nopush )
8483           return(success=0);
8484         return(dorexx());
8485     }
8486 #endif /* CK_REXX */
8487 #endif /* NOPUSH */
8488
8489 #ifndef NOFRILLS
8490     if (cx == XXDEL || cx == XXLDEL) {  /* DELETE */
8491 #ifdef LOCUS
8492         if (!locus && cx != XXLDEL) {
8493 #ifdef NOXFER
8494             return(-2);
8495 #else
8496             return(dormt(XZDEL));
8497 #endif /* NOXFER */
8498         }
8499 #endif /* LOCUS */
8500 #ifdef IKSD
8501         if (inserver && (!ENABLED(en_del)
8502 #ifdef CK_LOGIN
8503                          || isguest
8504 #endif /* CK_LOGIN */
8505                          )) {
8506             printf("?Sorry, DELETE is disabled\n");
8507             return(-9);
8508         }
8509 #endif /* IKSD */
8510 #ifdef CK_APC
8511         if ((apcactive == APC_LOCAL) ||
8512             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8513           return(success = 0);
8514 #endif /* CK_APC */
8515         return(dodel());
8516     }
8517 #endif /* NOFRILLS */
8518
8519     if (cx == XXDIR || cx == XXLS || cx == XXLDIR) { /* DIRECTORY or LS */
8520 #ifdef LOCUS
8521         if (!locus && cx != XXLDIR) {
8522 #ifdef NOXFER
8523             return(-2);
8524 #else
8525             return(dormt(XZDIR));
8526 #endif /* NOXFER */
8527         }
8528 #endif /* LOCUS */
8529 #ifdef IKSD
8530         if (inserver && !ENABLED(en_dir)) {
8531             printf("?Sorry, DIRECTORY is disabled\n");
8532             return(-9);
8533         }
8534 #endif /* IKSD */
8535         return(dodir(cx));
8536     }
8537
8538 #ifndef NOSPL
8539     if (cx == XXELS)                    /* ELSE */
8540       return(doelse());
8541 #endif /* NOSPL */
8542
8543 #ifndef NOSERVER
8544 #ifndef NOFRILLS
8545     if (cx == XXENA || cx == XXDIS) {   /* ENABLE, DISABLE */
8546         s = (cx == XXENA) ?
8547           "Server function to enable" :
8548             "Server function to disable";
8549
8550         if ((x = cmkey(enatab,nena,s,"",xxstring)) < 0) {
8551             if (x == -3) {
8552                 printf("?Name of server function required\n");
8553                 return(-9);
8554             } else return(x);
8555         }
8556         if ((y = cmkey(kmstab,3,"mode","both",xxstring)) < 0) {
8557             if (y == -3) {
8558                 printf("?Please specify remote, local, or both\n");
8559                 return(-9);
8560             } else return(y);
8561         }
8562         if (cx == XXDIS)                /* Disabling, not enabling */
8563           y = 3 - y;
8564         if ((z = cmcfm()) < 0) return(z);
8565 #ifdef CK_APC
8566         if ((apcactive == APC_LOCAL) ||
8567             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8568           return(success = 0);
8569 #endif /* CK_APC */
8570 #ifdef IKSD
8571         /* This may seem like it duplicates the work in doenable()  */
8572         /* but this code returns failure whereas doenable() returns */
8573         /* success.                                                 */
8574         if (inserver &&
8575 #ifdef IKSDCONF
8576             iksdcf &&
8577 #endif /* IKSDCONF */
8578             (x == EN_HOS || x == EN_PRI || x == EN_MAI || x == EN_WHO ||
8579               isguest))
8580             return(success = 0);
8581 #endif /* IKSD */
8582         return(doenable(y,x));
8583     }
8584 #endif /* NOFRILLS */
8585 #endif /* NOSERVER */
8586
8587 #ifndef NOSPL
8588     if (cx == XXRET) {                  /* RETURN */
8589         if ((x = cmtxt("Optional return value","",&s,NULL)) < 0)
8590           return(x);
8591         s = brstrip(s);                 /* Strip braces */
8592         if (cmdlvl == 0)                /* At top level, nothing happens... */
8593           return(success = 1);
8594         switch (cmdstk[cmdlvl].src) {   /* Action depends on command source */
8595           case CMD_TF:                  /* Command file */
8596             popclvl();                  /* Pop command level */
8597             return(success = 1);        /* always succeeds */
8598           case CMD_MD:                  /* Macro */
8599           case CMD_KB:                  /* Prompt */
8600             return(doreturn(s));        /* Trailing text is return value. */
8601           default:                      /* Shouldn't happen */
8602             return(-2);
8603         }
8604     }
8605 #endif /* NOSPL */
8606
8607 #ifndef NOSPL
8608     if (cx == XXOPE)                    /* OPEN */
8609       return(doopen());
8610 #endif /* NOSPL */
8611
8612 #ifndef NOSPL
8613     if (cx == XXOUT || cx == XXLNOUT) { /* OUTPUT or LINEOUT */
8614         if ((x = cmtxt("Text to be output","",&s,NULL)) < 0)
8615           return(x);
8616 #ifdef CK_APC
8617         if ((apcactive == APC_LOCAL) ||
8618             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8619           return(success = 0);
8620 #endif /* CK_APC */
8621         debug(F110,"OUTPUT 1",s,0);
8622         s = brstrip(s);                 /* Strip enclosing braces, */
8623         debug(F110,"OUTPUT 2",s,0);
8624 /*
8625   I don't think I could ever fully explain this in a million years...
8626   We have read the user's string without calling the variable-expander
8627   function.  Now, before we call it, we have to double backslashes that
8628   appear before \N, \B, \L, and \ itself, so the expander function will
8629   reduce them back to single backslashes, so when we call dooutput()...
8630   But it's more complicated than that.
8631 */
8632         if (cmdgquo()) {                /* Only if COMMAND QUOTING ON ... */
8633             for (x = 0, y = 0; s[x]; x++, y++) {
8634                 if (s[x] == CMDQ) {
8635                     char c = s[x+1];
8636                     if (c == 'n' || c == 'N' ||
8637                         c == 'b' || c == 'B' ||
8638                         c == 'l' || c == 'L' ||
8639                         c == CMDQ)
8640                       line[y++] = CMDQ;
8641                 }
8642                 line[y] = s[x];
8643             }
8644             line[y++] = '\0';           /* Now expand variables, etc. */
8645             debug(F110,"OUTPUT 3",line,0);
8646             s = line+y+1;
8647             x = LINBUFSIZ - (int) strlen(line) - 1;
8648             debug(F101,"OUTPUT size","",x);
8649             if (zzstring(line,&s,&x) < 0)
8650               return(success = 0);
8651             s = line+y+1;
8652             debug(F110,"OUTPUT 4",s,0);
8653         }
8654         success = dooutput(s,cx);
8655         return(success);
8656     }
8657 #endif /* NOSPL */
8658
8659 #ifdef ANYX25
8660 #ifndef IBMX25
8661     if (cx == XXPAD) {                  /* PAD commands */
8662         x = cmkey(padtab,npadc,"PAD command","",xxstring);
8663         if (x == -3) {
8664             printf("?You must specify a PAD command to execute\n");
8665             return(-9);
8666         }
8667         if (x < 0) return(x);
8668
8669         switch (x) {
8670           case XYPADL:
8671             if (x25stat() < 0)
8672               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8673             else {
8674                 x25clear();
8675                 initpad();
8676             }
8677             break;
8678           case XYPADS:
8679             if (x25stat() < 0)
8680               printf("Not connected\r\n");
8681             else {
8682                 extern int linkid, lcn;
8683                 conol("Connected thru ");
8684                 conol(ttname);
8685                 printf(", Link id %d, Logical channel number %d\r\n",
8686                        linkid,lcn);
8687             }
8688             break;
8689           case XYPADR:
8690             if (x25stat() < 0)
8691               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8692             else
8693               x25reset(0,0);
8694             break;
8695           case XYPADI:
8696             if (x25stat() < 0)
8697               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8698             else
8699               x25intr(0);
8700         }
8701         return(0);
8702     }
8703 #endif /* IBMX25 */
8704 #endif /* ANYX25 */
8705
8706 #ifndef NOSPL
8707     if (cx == XXPAU || cx == XXWAI || cx == XXMSL) /* PAUSE, WAIT, etc */
8708       return(dopaus(cx));
8709 #endif /* NOSPL */
8710
8711 #ifndef NOFRILLS
8712     if (cx == XXPRI) {
8713 #ifdef IKSD
8714 #ifdef CK_LOGIN
8715         if (inserver && (isguest || !ENABLED(en_pri))) {
8716             printf("?Sorry, printing is disabled\n");
8717             return(-9);
8718         }
8719 #endif /* CK_LOGIN */
8720 #endif /* IKSD */
8721         if ((x = cmifi("File to print","",&s,&y,xxstring)) < 0) {
8722             if (x == -3) {
8723                 printf("?A file specification is required\n");
8724                 return(-9);
8725             } else return(x);
8726         }
8727         if (y != 0) {
8728             printf("?Wildcards not allowed\n");
8729             return(-9);
8730         }
8731         ckstrncpy(line,s,LINBUFSIZ);
8732         s = "";
8733 #ifndef NT
8734         if ((x = cmtxt("Local print command options, or carriage return","",&s,
8735                        xxstring)) < 0)
8736           return(x);
8737 #endif /* NT */
8738         if ((x = cmcfm()) < 0)
8739           return(x);
8740         return(success = (zprint(s,line) == 0) ? 1 : 0);
8741     }
8742 #endif /* NOFRILLS */
8743
8744 #ifdef TCPSOCKET
8745 #ifndef NOPUSH
8746     if (cx == XXPNG)                    /* PING an IP host */
8747       return(doping());
8748 #endif /* NOPUSH */
8749
8750 #ifndef NOFTP
8751     if (cx == XXFTP)                    /* FTP */
8752 #ifdef SYSFTP
8753 #ifndef NOPUSH
8754       return(doftp());                  /* Just runs system's ftp program */
8755 #else
8756       return(-2);
8757 #endif /* NOPUSH */
8758 #else
8759     return(doxftp());
8760 #endif /* SYSFTP */
8761 #endif /* NOFTP */
8762 #endif /* TCPSOCKET */
8763
8764     if (cx == XXPWD || cx == XXLPWD) {  /* PWD */
8765 #ifdef OS2
8766         char *pwp;
8767 #endif /* OS2 */
8768         if ((x = cmcfm()) < 0)
8769           return(x);
8770 #ifdef LOCUS
8771         if (!locus && cx != XXLPWD) {
8772 #ifdef NOXFER
8773             return(-2);
8774 #else
8775             return(dormt(XZPWD));
8776 #endif /* NOXFER */
8777         }
8778 #endif /* LOCUS */
8779
8780 #ifndef MAC
8781 #ifndef OS2
8782 #ifdef UNIX
8783         printf("%s\n",zgtdir());
8784 #else
8785         xsystem(PWDCMD);
8786 #endif /* UNIX */
8787         return(success = 1);            /* Blind faith */
8788 #else  /* OS2 */
8789         if (pwp = zgtdir()) {
8790             if (*pwp) {
8791 #ifdef NT
8792                 line[0] = NUL;
8793                 ckGetLongPathName(pwp,line,LINBUFSIZ);
8794                 line[LINBUFSIZ-1] = NUL;
8795                 tmpbuf[0] = NUL;
8796                 GetShortPathName(pwp,tmpbuf,TMPBUFSIZ);
8797                 tmpbuf[TMPBUFSIZ-1] = NUL;
8798                 pwp = line;
8799                 if (!strcmp(line,tmpbuf)) {
8800 #endif /* NT */
8801                     printf("%s\n",pwp);
8802 #ifdef NT
8803                 } else {
8804                     printf("  Long name:  %s\n",line);
8805                     printf("  Short name: %s\n",tmpbuf);
8806                 }            
8807 #endif /* NT */
8808             }
8809             return(success = ((int)strlen(pwp) > 0));
8810         } else return(success = 0);
8811 #endif /* OS2 */
8812 #else  /* MAC */
8813         if (pwp = zgtdir()) {
8814             printf("%s\n",pwp);
8815             return(success = ((int)strlen(pwp) > 0));
8816         } else return(success = 0);
8817 #endif /* MAC */
8818     }
8819
8820     if (cx == XXQUI || cx == XXEXI) {   /* EXIT, QUIT */
8821         extern int quitting;
8822
8823         if ((y = cmnum("exit status code",ckitoa(xitsta),10,&x,xxstring)) < 0)
8824           return(y);
8825         if ((y = cmtxt("Optional EXIT message","",&s,xxstring)) < 0)
8826           return(y);
8827         s = brstrip(s);
8828         ckstrncpy(line,s,LINBUFSIZ);
8829
8830         if (!hupok(0))                  /* Check if connection still open */
8831           return(success = 0);
8832
8833         if (line[0])                    /* Print EXIT message if given */
8834           printf("%s\n",(char *)line);
8835
8836         quitting = 1;                   /* Flag that we are quitting. */
8837
8838 #ifdef VMS
8839         doexit(GOOD_EXIT,x);
8840 #else
8841 #ifdef OSK
8842 /* Returning any codes here makes the OS-9 shell print an error message. */
8843         doexit(GOOD_EXIT,-1);
8844 #else
8845 #ifdef datageneral
8846         doexit(GOOD_EXIT,x);
8847 #else
8848         doexit(x,-1);
8849 #endif /* datageneral */
8850 #endif /* OSK */
8851 #endif /* VMS */
8852     }
8853
8854 #ifndef NOXFER
8855 #ifndef NOFRILLS
8856     if (cx == XXERR) {                  /* ERROR */
8857 #ifdef CK_XYZ
8858         if (protocol != PROTO_K) {
8859             printf("Sorry, E-PACKET only works with Kermit protocol\n");
8860             return(-9);
8861         }
8862 #endif /* CK_XYZ */
8863         if ((x = cmcfm()) < 0) return(x);
8864         ttflui();
8865         epktflg = 1;
8866         sstate = 'a';
8867         return(0);
8868     }
8869 #endif /* NOFRILLS */
8870
8871     if (cx == XXFIN) {                  /* FINISH */
8872 #ifdef NEWFTP
8873         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
8874           return(ftpbye());
8875 #endif /* NEWFTP */
8876 #ifdef CK_XYZ
8877         if (protocol != PROTO_K) {
8878             printf("Sorry, FINISH only works with Kermit protocol\n");
8879             return(-9);
8880         }
8881 #endif /* CK_XYZ */
8882         if ((x = cmcfm()) < 0) return(x);
8883
8884 #ifdef IKS_OPTION
8885         if (
8886 #ifdef CK_XYZ
8887             protocol == PROTO_K &&
8888 #endif /* CK_XYZ */
8889             !iks_wait(KERMIT_REQ_START,1)) {
8890             printf(
8891               "?A Kermit Server is not available to process this command\n");
8892             return(-9);                 /* Correct the return code */
8893         }
8894 #endif /* IKS_OPTION */
8895
8896         sstate = setgen('F',"","","");
8897         if (local) ttflui();            /* If local, flush tty input buffer */
8898         return(0);
8899     }
8900 #endif /* NOXFER */
8901
8902 #ifndef NOSPL
8903     if (cx == XXFOR)                    /* FOR loop */
8904       return(dofor());
8905 #endif /* NOSPL */
8906
8907 #ifndef NOXFER
8908     /* GET MGET REGET RETRIEVE etc */
8909     if (cx == XXGET || cx == XXMGET || cx == XXREGET || cx == XXRETR) {
8910 #ifdef IKSD
8911         if (inserver && !ENABLED(en_sen)) {
8912             printf("?Sorry, reception of files is disabled\n");
8913             return(-9);
8914         }
8915 #endif /* IKSD */
8916         return(doxget(cx));
8917     }
8918 #endif /* NOXFER */
8919
8920 #ifndef NOSPL
8921 #ifndef NOFRILLS
8922     if (cx == XXGOK) {                  /* GETOK */
8923         return(success = doask(cx));
8924     }
8925 #endif /* NOFRILLS */
8926 #endif /* NOSPL */
8927
8928     if (cx == XXHLP) {                  /* HELP */
8929 #ifdef NOHELP
8930         return(dohlp(XXHLP));
8931 #else
8932         x = cmkey2(cmdtab,ncmd,"\nCommand or topic","help",toktab,xxstring,3);
8933         debug(F101,"HELP command x","",x);
8934         if (x == -5) {
8935             y = chktok(toktab);
8936             debug(F101,"HELP cmkey token","",y);
8937             /* ungword(); */
8938             switch (y) {
8939 #ifndef NOPUSH
8940               case '!': x = XXSHE; break;
8941 #endif /* NOPUSH */
8942               case '#': x = XXCOM; break;
8943               case ';': x = XXCOM; break;
8944 #ifndef NOSPL
8945               case '.': x = XXDEF; break;
8946               case ':': x = XXLBL; break;
8947 #ifndef NOSEXP
8948               case '(': x = XXSEXP; break;
8949 #endif /* NOSEXP */
8950 #endif /* NOSPL */
8951               case '&': x = XXECH; break;
8952               default:
8953                 printf("\n?Invalid - %s\n",cmdbuf);
8954                 x = -2;
8955             }
8956         }
8957         makestr(&hlptok,atmbuf);
8958         debug(F111,"HELP token",hlptok,x);
8959         return(dohlp(x));
8960 #endif /* NOHELP */
8961     }
8962
8963 #ifndef NOHELP
8964     if (cx == XXINT)                    /* INTRO */
8965       return(hmsga(introtxt));
8966     if (cx == XXNEW) {                  /* NEWS */
8967         int x;
8968         extern char * k_info_dir;
8969         x = hmsga(newstxt);
8970         return(x);
8971     }
8972
8973 #ifdef OS2ONLY
8974     if (cx == XXUPD) {                  /* View UPDATE file */
8975         extern char exedir[];
8976         char * pTopic;
8977         char updstr[2048];
8978         if ((x = cmtxt("topic name","",&pTopic,xxstring)) < 0)
8979             return x;
8980 #ifdef COMMENT
8981         sprintf(updstr,
8982                 "start view %s\\docs\\k2.inf+%s\\docs\\using_ck.inf+\
8983 %s\\docs\\dialing.inf+%s\\docs\\modems.inf %s",
8984                 exedir,exedir,exedir,exedir,pTopic
8985                 );
8986 #else
8987         if (ckmakxmsg(updstr,
8988                      2048,
8989                      "start view ",
8990                      exedir,
8991                      "\\docs\\k2.inf+",
8992                      exedir,
8993                      "\\docs\\using_ck.inf+",
8994                      exedir,
8995                      "\\docs\\dialing.inf+",
8996                      exedir,
8997                      "\\docs\\modems.inf ",
8998                      pTopic,
8999                      NULL,
9000                      NULL
9001                      ) > 0)
9002 #endif /* COMMENT */
9003           system(updstr);
9004         return(success = 1);
9005     }
9006 #endif /* OS2ONLY */
9007 #endif /* NOHELP */
9008
9009 #ifndef NOLOCAL
9010     if (cx == XXHAN) {                  /* HANGUP */
9011         if ((x = cmcfm()) < 0) return(x);
9012 #ifdef NEWFTP
9013         if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
9014           return(success = ftpbye());
9015 #endif /* NEWFTP */
9016 #ifndef NODIAL
9017         if ((x = mdmhup()) < 1) {
9018             debug(F101,"HANGUP mdmup","",x);
9019 #endif /* NODIAL */
9020             x = tthang();
9021             debug(F101,"HANGUP tthang","",x);
9022             x = (x > -1);
9023 #ifndef NODIAL
9024         }
9025         dialsta = DIA_UNK;
9026 #endif /* NODIAL */
9027         whyclosed = WC_CLOS;
9028         ttchk();                        /* In case of CLOSE-ON-DISCONNECT */
9029         dologend();
9030 #ifdef OS2
9031         if (x)
9032           DialerSend(OPT_KERMIT_HANGUP, 0);
9033 #endif /* OS2 */
9034         if (x) haveline = 0;
9035         return(success = x);
9036     }
9037 #endif /* NOLOCAL */
9038
9039 #ifndef NOSPL
9040     /* INPUT, REINPUT, and MINPUT */
9041
9042     if (cx == XXINP || cx == XXREI || cx == XXMINP) {
9043         long zz;
9044         extern int ispattern, isjoin;
9045
9046         struct FDB sw, nu, fl;
9047         int fc, havetime = 0;
9048         char * m;
9049
9050         if (cx == XXREI) {
9051             m = "Timeout in seconds (ignored)";
9052         } else {
9053             m = "Seconds to wait for input,\n or time of day hh:mm:ss, \
9054  or switch";
9055         }
9056         innomatch = 0;                  /* Initialize switch value(s) */
9057
9058         cmfdbi(&sw,                     /* First FDB - command switches */
9059                _CMKEY,                  /* fcode */
9060                m,                       /* helpmsg */
9061                ckitoa(indef),           /* default */
9062                "",                      /* addtl string data */
9063                ninputsw,                /* addtl numeric data 1: tbl size */
9064                4,                       /* addtl numeric data 2: 4 = cmswi */
9065                xxstring,                /* Processing function */
9066                inputsw,                 /* Keyword table */
9067                &nu                      /* Pointer to next FDB */
9068                );
9069         cmfdbi(&nu,
9070                _CMNUM,                  /* Number */
9071                m,                       /* Help message */
9072                ckitoa(indef),           /* default */
9073                "",                      /* N/A */
9074                10,                      /* Radix = 10 */
9075                0,                       /* N/A */
9076                xxstring,                /* Processing function */
9077                NULL,                    /* N/A */
9078                &fl                      /* Next */
9079                );
9080         cmfdbi(&fl,                     /* Time of day hh:mm:ss */
9081                _CMFLD,                  /* fcode */
9082                "",                      /* hlpmsg */
9083                "",
9084                "",                      /* addtl string data */
9085                0,                       /* addtl numeric data 1 */
9086                0,                       /* addtl numeric data 2 */
9087                xxstring,
9088                NULL,
9089                NULL
9090                );
9091         fc = (cx == XXREI) ? cmfdb(&nu) : cmfdb(&sw); /* Parse something */
9092
9093         while (!havetime) {
9094             if (fc < 0) {               /* Error */
9095                 if (fc == -3) {
9096                     printf("?Syntax error in INPUT-class command\n");
9097                     return(-9);
9098                 } else
9099                   return(fc);
9100             }
9101             switch (cmresult.fcode) {
9102               case _CMKEY:              /* Switch */
9103                 if (cmresult.nresult == INPSW_NOM) /* /NOMATCH */
9104                   innomatch = 1;
9105                 m = "Seconds to wait for input,\n or time of day hh:mm:ss";
9106                 cmfdbi(&nu,_CMNUM,m,"","",10,0,xxstring,NULL,&fl);
9107                 cmfdbi(&fl,_CMFLD,"","","",0,0,xxstring,NULL,NULL);
9108                 fc = cmfdb(&nu);        /* Parse something */
9109                 continue;
9110
9111               case _CMNUM:              /* Seconds to time out */
9112                 x = cmresult.nresult;
9113 #ifdef CKFLOAT
9114                 if (inscale != 1.0)     /* Scale */
9115                   x *= inscale;         
9116 #endif  /* CKFLOAT */
9117                 havetime++;
9118                 break;
9119
9120               case _CMFLD:
9121                 zz = tod2sec(atmbuf);   /* Convert to secs since midnight */
9122                 if (zz < 0L) {
9123                     printf("?Number, expression, or time of day required\n");
9124                     return(-9);
9125                 } else {
9126                     char now[32];       /* Current time */
9127                     char *p;
9128                     long tnow;
9129                     p = now;
9130                     ztime(&p);
9131                     tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
9132                     if (zz < tnow)      /* User's time before now */
9133                       zz += 86400L;     /* So make it tomorrow */
9134                     zz -= tnow;         /* Seconds from now. */
9135                     if (zz > -1L) {
9136                         x = zz;
9137                         if (zz != (long) x) {
9138                             printf(
9139 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
9140 );
9141                             return(-9);
9142                         }
9143                     }
9144                     havetime++;
9145                 }
9146                 break;
9147               default:          
9148                 printf("?Internal error\n");
9149                 return(-9);
9150             }
9151         }
9152         /* Now parse the search text */
9153
9154 #ifdef CK_MINPUT
9155         for (y = 0; y < MINPMAX; y++) { /* Initialize strings */
9156             mp[y] = 0;                  /* Assume it's not a pattern */
9157             if (ms[y]) {
9158                 free(ms[y]);            /* Free old strings, if any */
9159                 ms[y] = NULL;
9160             }
9161         }
9162         if (cx == XXMINP) {             /* MINPUT */
9163             int i, k = 0, n = 0;
9164             struct stringarray * q;
9165             keepallchars = 1;
9166             while (k < MINPMAX) {
9167                 if ((y = cmfld("String or pattern","",&s,xxstring)) < 0) {
9168                     if (y == -3) {
9169                         if ((y = cmcfm()) < 0)
9170                           return(y);
9171                         break;
9172                     } else {
9173                         return(y);
9174                     }
9175                 }
9176                 debug(F111,"MINPUT field",s,k);
9177                 if (isjoin) {
9178                     if ((q = cksplit(1,0,s," ",(char *)c1chars,3,0,0))) {
9179                         char ** ap = q->a_head;
9180                         n = q->a_size;
9181                         debug(F101,"minput cksplit size","",n);
9182                         for (i = 1; i <= n && k < MINPMAX; i++) {
9183                             if (!ap[i]) /* Add non-empty elements */
9184                               continue;
9185                             if (!*(ap[i]))
9186                               continue;
9187                             makestr(&(ms[k]),ap[i]);
9188                             debug(F111,"MINPUT JOIN",ms[k],k);
9189                             k++;
9190                         }
9191                     }
9192                 } else {
9193                     if (s) if (*s) {
9194                         makestr(&(ms[k]),brstrip(s));
9195                         if (ispattern) mp[k] = 1;
9196                         debug(F111,"MINPUT",ms[k],ispattern);
9197                         k++;
9198                     }
9199                 }
9200             }
9201             keepallchars = 0;
9202         } else {
9203 #endif /* CK_MINPUT */
9204
9205             /* INPUT or REINPUT */
9206
9207             if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
9208               return(y);
9209             mp[0] = ispattern ? 1 : 0;
9210             makestr(&(ms[0]),brstrip(s));
9211             ms[1] = NULL;
9212
9213 #ifdef CK_MINPUT
9214         }
9215 #endif /* CK_MINPUT */
9216
9217 #ifdef COMMENT
9218         printf("/NOMATCH=%d\n",innomatch);
9219         printf("Timeout=%d\n",x);
9220         return(1);
9221 #endif  /* COMMENT */
9222
9223         if (cx == XXINP || cx == XXMINP) { /* Not REINPUT... */
9224             i_active = 1;
9225             /* Go try to input the search string */
9226             success = doinput(x,ms,mp,innomatch);
9227             i_active = 0;
9228         } else {                        /* REINPUT */
9229             success = doreinp(x,ms[0],ispattern);
9230         }
9231         if (intime[cmdlvl] && !success) { /* TIMEOUT-ACTION = QUIT? */
9232             popclvl();                  /* If so, pop command level. */
9233             if (pflag && cmdlvl == 0) {
9234                 if (cx == XXINP)  printf("?INPUT timed out\n");
9235                 if (cx == XXMINP) printf("?MINPUT timed out\n");
9236                 if (cx == XXREI)  printf("?REINPUT failed\n");
9237             }
9238         }
9239         return(success);                /* Return do(re)input's return code */
9240     }
9241
9242 #endif /* NOSPL */
9243
9244     if (cx == XXLOG) {                  /* LOG */
9245         x = cmkey(logtab,nlog,"What to log","",xxstring);
9246         if (x == -3) {
9247             printf("?Type of log required\n");
9248             return(-9);
9249         }
9250         if (x < 0) return(x);
9251         x = dolog(x);
9252         if (x < 0)
9253           return(x);
9254         else
9255           return(success = x);
9256     }
9257
9258     if (cx == XXLOGIN) {                /* (REMOTE) LOGIN */
9259 #ifdef NEWFTP
9260         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9261           return(success = doftpusr());
9262 #endif /* NEWFTP */
9263 #ifdef IKSD
9264         if (inserver) {
9265             printf("?Already logged in\n");
9266             return(-9);
9267         } else
9268 #endif /* IKSD */
9269         {
9270 #ifdef NOXFER
9271             return(-2);
9272 #else
9273             return(dormt(XZLGI));
9274 #endif /* NOXFER */
9275         }
9276     }
9277     if (cx == XXLOGOUT) {               /* (REMOTE) LOGOUT */
9278 #ifdef NEWFTP
9279         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9280           return(success = doftpres());
9281 #endif /* NEWFTP */
9282
9283 #ifdef IKSD
9284         if (inserver) {
9285             if ((x = cmcfm()) < 0)
9286               return(x);
9287             doexit(GOOD_EXIT,xitsta);
9288         } else
9289 #endif /* IKSD */
9290         if (!local || (network && ttchk() < 0)) {
9291             printf("?No connection.\n");
9292             return(-9);
9293         } else {
9294 #ifdef NOXFER
9295             return(-2);
9296 #else
9297             return(dormt(XZLGO));
9298 #endif /* NOXFER */
9299         }
9300     }
9301
9302 #ifndef NOSCRIPT
9303     if (cx == XXLOGI) {                 /* UUCP-style script */
9304         if ((x = cmtxt("expect-send expect-send ...","",&s,xxstring)) < 0)
9305           return(x);
9306 #ifdef CK_APC
9307         if ((apcactive == APC_LOCAL) ||
9308             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9309           return(success = 0);
9310 #endif /* CK_APC */
9311 #ifdef VMS
9312         conres();                       /* For Ctrl-C to work... */
9313 #endif /* VMS */
9314         return(success = dologin(s));   /* Return 1=completed, 0=failed */
9315     }
9316 #endif /* NOSCRIPT */
9317
9318 #ifndef NOXFER
9319 #ifdef PIPESEND
9320     if (cx == XXCREC) {                 /* CRECEIVE */
9321         if (protocol != PROTO_K) {
9322             printf("?Sorry, CRECEIVE works only with Kermit protocol\n");
9323             return(-9);
9324         } else
9325           return(doxget(cx));
9326     }
9327     if (cx == XXCGET) {                 /* CGET */
9328         return(doxget(cx));
9329     }
9330 #endif /* PIPESEND */
9331
9332     if (cx == XXREC)                    /* RECEIVE */
9333       return(doxget(cx));
9334 #endif /* NOXFER */
9335
9336 #ifndef NOXFER
9337     if (cx == XXREM) {                  /* REMOTE */
9338 #ifdef NEWFTP
9339         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9340           return(doftprmt(0,0));
9341 #endif /* NEWFTP */
9342 #ifdef CK_XYZ
9343         if (protocol != PROTO_K) {
9344             printf("Sorry, REMOTE commands only work with Kermit protocol\n");
9345             return(-9);
9346         }
9347 #endif /* CK_XYZ */
9348         x = cmkey(remcmd,nrmt,"Remote Kermit server command","",xxstring);
9349         if (x == -3) {
9350             printf("?You must specify a command for the remote server\n");
9351             return(-9);
9352         }
9353         return(dormt(x));
9354     }
9355 #endif /* NOXFER */
9356
9357 #ifndef NORENAME
9358 #ifndef NOFRILLS
9359     if (cx == XXREN || cx == XXLREN) {  /* RENAME */
9360 #ifdef LOCUS
9361         if (!locus && cx != XXLREN) {
9362 #ifdef NOXFER
9363             return(-2);
9364 #else
9365             return(dormt(XZREN));
9366 #endif /* NOXFER */
9367         }
9368 #endif /* LOCUS */
9369 #ifdef IKSD
9370         if (inserver && (!ENABLED(en_ren)
9371 #ifdef CK_LOGIN
9372                          || isguest
9373 #endif /* CK_LOGIN */
9374                          )) {
9375             printf("?Sorry, renaming of files is disabled\n");
9376             return(-9);
9377         }
9378 #endif /* IKSD */
9379 #ifdef CK_APC
9380         if ((apcactive == APC_LOCAL) ||
9381             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9382           return(success = 0);
9383 #endif /* CK_APC */
9384         return(dorenam());
9385     }
9386 #endif /* NOFRILLS */
9387 #endif /* NORENAME */
9388
9389     if (cx == XXEIGHT) {                /* EIGHTBIT */
9390         extern int parity, cmask, cmdmsk;
9391         if ((x = cmcfm()) < 0)
9392           return(x);
9393         parity = 0;
9394         cmask = 0xff;
9395         cmdmsk = 0xff;
9396         return(success = 1);
9397     }
9398
9399 #ifndef NOXFER
9400 /* SEND, CSEND, MOVE, MAIL, and RESEND use the new common code */
9401
9402     if (cx == XXSEN                     /* SEND */
9403 #ifdef PIPESEND
9404         || cx == XXCSEN                 /* CSEND */
9405 #endif /* PIPESEND */
9406         || cx == XXMOVE                 /* MOVE */
9407         || cx == XXMAI                  /* MAIL */
9408 #ifdef CK_RESEND
9409         || cx == XXRSEN                 /* RESEND */
9410 #endif /* CK_RESEND */
9411         ) {
9412 #ifdef IKSD
9413         if (inserver && !ENABLED(en_get)) {
9414             printf("?Sorry, sending files is disabled\n");
9415             return(-9);
9416         }
9417 #endif /* IKSD */
9418         return(doxsend(cx));
9419     }
9420
9421 /* PSEND, ADD, and REMOVE use special parsing */
9422
9423 #ifdef ADDCMD
9424     /* ADD and REMOVE */
9425     if (cx == XXADD || cx == XXREMV) {
9426         char * m;
9427         m = (cx == XXADD) ? "Add to which list?" : "Remove from which list?";
9428         x = cmkey(addtab,naddtab,m,"",xxstring);
9429         if (x < 0)
9430           return(x);
9431 #ifndef NOMSEND
9432         if (x == ADD_SND)
9433           return(addsend(cx));
9434         else
9435 #endif /* NOMSEND */
9436           return(doadd(cx,x));
9437     }
9438 #endif /* ADDCMD */
9439
9440 #ifdef CK_RESEND
9441     if (cx == XXPSEN) {                 /* PSEND */
9442         int seekto = 0;
9443
9444         cmarg = cmarg2 = "";
9445         x = cmifi("File to partially send", "", &s, &y, xxstring);
9446         if (x < 0) {
9447             if (x == -3) {
9448                 printf("?A file specification is required\n");
9449                 return(-9);
9450             } else return(x);
9451         }
9452         nfils = -1;                     /* Files come from internal list. */
9453 #ifndef NOMSEND
9454         addlist = 0;                    /* Don't use SEND-LIST. */
9455         filenext = NULL;
9456 #endif /* NOMSEND */
9457         ckstrncpy(line,s,LINBUFSIZ);    /* Save copy of string just parsed. */
9458         debug(F110,"PSEND line",line,0);
9459         if (y != 0) {
9460             printf("?Sorry, wildcards not permitted in this command\n");
9461             return(-9);
9462         }
9463         if (sizeof(int) < 4) {
9464             printf("?Sorry, this command needs 32-bit integers\n");
9465             return(-9);
9466         }
9467         x = cmnum("starting position (byte number)",
9468                   "",10,&seekto,xxstring);
9469         if (x < 0)
9470           return(x);
9471         zfnqfp(s,fspeclen,fspec);       /* Get full path */
9472         if ((x = cmtxt("Name to send it with","",&s,NULL)) < 0)
9473           return(x);
9474         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
9475
9476 #ifdef IKSD
9477         if (inserver && !ENABLED(en_get)) {
9478             printf("?Sorry, sending files is disabled\n");
9479             return(-9);
9480         }
9481 #endif /* IKSD */
9482 #ifdef PIPESEND
9483         if (sndfilter) {
9484             printf("?Sorry, no PSEND while SEND FILTER selected\n");
9485             return(-9);
9486         }
9487 #endif /* PIPESEND */
9488 #ifdef CK_XYZ
9489         if ((protocol == PROTO_X || protocol == PROTO_XC)) {
9490             printf("Sorry, PSEND works only with Kermit protocol\n");
9491             return(-9);
9492         }
9493 #endif /* CK_XYZ */
9494
9495         cmarg2 = brstrip(tmpbuf);       /* Strip braces */
9496         cmarg = line;                   /* File to send */
9497         debug(F110,"PSEND filename",cmarg,0);
9498         debug(F110,"PSEND as-name",cmarg2,0);
9499         sendstart = seekto;
9500         sstate = 's';                   /* Set start state to SEND */
9501 #ifndef NOMSEND
9502         addlist = 0;
9503         filenext = NULL;
9504 #endif /* NOMSEND */
9505         sendmode = SM_PSEND;
9506 #ifdef MAC
9507         what = W_SEND;
9508         scrcreate();
9509 #endif /* MAC */
9510         if (local) {                    /* If in local mode, */
9511             displa = 1;                 /* enable file transfer display */
9512         }
9513         return(0);
9514     }
9515 #endif /* CK_RESEND */
9516 #endif /* NOXFER */
9517
9518 #ifndef NOXFER
9519 #ifndef NOMSEND
9520     if (cx == XXMSE || cx == XXMMOVE) {
9521 #ifdef NEWFTP
9522         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9523           return(doftpput(cx,0));
9524 #endif /* NEWFTP */
9525 #ifdef CK_XYZ
9526         if (protocol == PROTO_X || protocol == PROTO_XC) {
9527             printf(
9528 "Sorry, you can only send one file at a time with XMODEM protocol\n"
9529                    );
9530             return(-9);
9531         }
9532 #endif /* CK_XYZ */
9533         return(doxsend(cx));
9534     }
9535
9536 #ifdef COMMENT                          /* (moved to doxsend) */
9537     if (cx == XXMSE || cx == XXMMOVE) { /* MSEND and MMOVE commands */
9538         nfils = 0;                      /* Like getting a list of */
9539         lp = line;                      /* files on the command line */
9540         addlist = 0;                    /* Do not use SEND-LIST */
9541         filenext = NULL;                /* Ditto ! */
9542
9543         while (1) {
9544             char *p;
9545             if ((x = cmifi("Names of files to send, separated by spaces","",
9546                            &s,&y,xxstring)) < 0) {
9547                 if (x == -3) {
9548                     if (nfils <= 0) {
9549                         printf("?A file specification is required\n");
9550                         return(-9);
9551                     } else break;
9552                 }
9553                 return(x);
9554             }
9555             msfiles[nfils++] = lp;      /* Got one, count it, point to it, */
9556             p = lp;                     /* remember pointer, */
9557             while (*lp++ = *s++)        /* and copy it into buffer */
9558               if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
9559                   printf("?MSEND list too long\n");
9560                   line[0] = NUL;
9561                   return(-9);
9562               }
9563             debug(F111,"msfiles",msfiles[nfils-1],nfils-1);
9564             if (nfils == 1) *fspec = NUL; /* Take care of \v(filespec) */
9565 #ifdef ZFNQFP
9566             zfnqfp(p,TMPBUFSIZ,tmpbuf);
9567             p = tmpbuf;
9568 #endif /* ZFNQFP */
9569             if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
9570                 strcat(fspec,p);        /* safe */
9571                 strcat(fspec," ");      /* safe */
9572             } else printf("WARNING - \\v(filespec) buffer overflow\n");
9573         }
9574         cmlist = msfiles;               /* Point cmlist to pointer array */
9575         cmarg2 = "";                    /* No internal expansion list (yet) */
9576         sndsrc = nfils;                 /* Filenames come from cmlist */
9577         sendmode = SM_MSEND;            /* Remember this kind of SENDing */
9578         sstate = 's';                   /* Set start state for SEND */
9579         if (cx == XXMMOVE)              /* If MMOVE'ing, */
9580           moving = 1;                   /*  set this flag. */
9581 #ifdef MAC
9582         what = W_SEND;
9583         scrcreate();
9584 #endif /* MAC */
9585         if (local) {                    /* If in local mode, */
9586             displa = 1;                 /* turn on file transfer display */
9587             ttflui();                   /* and flush tty input buffer. */
9588         }
9589         return(0);
9590     }
9591 #endif /* COMMENT */
9592 #endif /* NOMSEND */
9593 #endif /* NOXFER */
9594
9595 #ifndef NOSERVER
9596     if (cx == XXSER) {                  /* SERVER */
9597 #ifdef CK_XYZ
9598         if (protocol != PROTO_K) {
9599             printf("Sorry, SERVER only works with Kermit protocol\n");
9600             return(-9);
9601         }
9602 #endif /* CK_XYZ */
9603 #ifdef COMMENT
9604 /*
9605   Parse for time limit, but since we don't use it yet,
9606   the parsing is commented out.
9607 */
9608         x_ifnum = 1;                    /* Turn off internal complaints */
9609         y = cmnum("optional time limit, seconds, or time of day as hh:mm:ss",
9610                   "0", 10, &x, xxstring
9611                   );
9612         x_ifnum = 0;
9613         if (y < 0) {
9614             if (y == -2) {              /* Invalid number or expression */
9615                 zz = tod2sec(atmbuf);   /* Convert to secs since midnight */
9616                 if (zz < 0L) {
9617                     printf("?Number, expression, or time of day required\n");
9618                     return(-9);
9619                 } else {
9620                     char now[32];       /* Current time */
9621                     char *p;
9622                     long tnow;
9623                     p = now;
9624                     ztime(&p);
9625                     tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
9626                     if (zz < tnow)      /* User's time before now */
9627                       zz += 86400L;     /* So make it tomorrow */
9628                     zz -= tnow;         /* Seconds from now. */
9629                 }
9630             } else
9631               return(y);
9632         }
9633         if (zz > -1L) {
9634             x = zz;
9635             if (zz != (long) x) {
9636                 printf(
9637 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
9638                        );
9639                 return(-9);
9640             }
9641         }
9642         if (x < 0)
9643           x = 0;
9644 #endif /* COMMENT */
9645
9646         if ((x = cmcfm()) < 0) return(x);
9647         sstate = 'x';
9648 #ifdef MAC
9649         what = W_RECV;
9650         scrcreate();
9651 #endif /* MAC */
9652         if (local) displa = 1;
9653 #ifdef AMIGA
9654         reqoff();                       /* No DOS requestors while server */
9655 #endif /* AMIGA */
9656         return(0);
9657     }
9658 #endif /* NOSERVER */
9659
9660     if (cx == XXSAVE) {                 /* SAVE command */
9661         x = cmkey(savtab,nsav,"option","keymap",xxstring);
9662         if (x == -3) {
9663             printf("?You must specify an option to save\n");
9664             return(-9);
9665         }
9666         if (x < 0) return(x);
9667         /* have to set success separately for each item in doprm()... */
9668         /* actually not really, could have just had doprm return 0 or 1 */
9669         /* and set success here... */
9670         y = dosave(x);
9671         if (y == -3) {
9672             printf("?More fields required\n");
9673             return(-9);
9674         } else return(y);
9675     }
9676
9677     if (cx == XXSET) {                  /* SET command */
9678         x = cmkey(prmtab,nprm,"Parameter","",xxstring);
9679         if (x == -3) {
9680             printf("?You must specify a parameter to set\n");
9681             return(-9);
9682         }
9683         if (x < 0) return(x);
9684         /* have to set success separately for each item in doprm()... */
9685         /* actually not really, could have just had doprm return 0 or 1 */
9686         /* and set success here... */
9687         y = doprm(x,0);
9688         if (y == -3) {
9689             printf("?More fields required\n");
9690             return(-9);
9691         } else return(y);
9692     }
9693
9694 #ifndef NOPUSH
9695     if (cx == XXSHE                     /* SHELL (system) command */
9696         || cx == XXEXEC                 /* exec() */
9697         ) {
9698         int rx = 0;
9699         char * p = NULL;
9700         int i /* ,n */ ;
9701 #ifdef UNIXOROSK
9702         char * args[256];
9703 #endif /* UNIXOROSK */
9704
9705 #ifdef IKSD
9706         if (inserver && (nopush || !ENABLED(en_hos))) {
9707             printf("?Sorry, host command access is disabled\n");
9708             return(-9);
9709         }
9710 #endif /* IKSD */
9711
9712 #ifdef CKEXEC
9713         if (cx == XXEXEC) {             /* EXEC (overlay ourselves) */
9714             struct FDB sw, fl;
9715             cmfdbi(&sw,                 /* First FDB - command switches */
9716                    _CMKEY,              /* fcode */
9717                    "Command to overlay C-Kermit\n or switch", /* hlpmsg */
9718                    "",                  /* default */
9719                    "",                  /* addtl string data */
9720                    1,                   /* addtl numeric data 1: tbl size */
9721                    4,                   /* addtl numeric data 2: 4 = cmswi */
9722                    xxstring,            /* Processing function */
9723                    redirsw,             /* Keyword table */
9724                    &fl                  /* Pointer to next FDB */
9725                    );
9726             cmfdbi(&fl,                 /* 2nd FDB - command to exec */
9727                    _CMFLD,              /* fcode */
9728                    "Command to overlay C-Kermit", /* hlpmsg */
9729                    "",                  /* default */
9730                    "",                  /* addtl string data */
9731                    0,                   /* addtl numeric data 1 */
9732                    0,                   /* addtl numeric data 2 */
9733                    xxstring,
9734                    NULL,
9735                    NULL                 /* No more after this */
9736                    );
9737             while (1) {
9738                 x = cmfdb(&sw);         /* Parse something */
9739                 debug(F101,"exec cmfdb","",x);
9740                 if (x < 0)
9741                   return(x);
9742                 /* Generalize this if we add more switches */
9743                 if (cmresult.fcode == _CMKEY) {
9744                     rx = 1;
9745                     continue;
9746                 }
9747                 if (cmresult.fcode == _CMFLD)
9748                   break;
9749                 return(-2);
9750             }
9751             ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
9752             if (!tmpbuf[0]) {
9753                 printf("?Command required\n");
9754                 return(-9);
9755             }
9756             p = brstrip(tmpbuf);
9757             args[0] = NULL;             /* Set argv[0] to it */
9758             makestr(&args[0],p);
9759             for (i = 1; i < 255; i++) { /* Get arguments for command */
9760                 if ((x = cmfld("Argument","",&s,xxstring)) < 0) {
9761                     if (x == -3) {
9762                         if ((x = cmcfm()) < 0)
9763                           return(x);
9764                         break;
9765                     } else
9766                       return(x);
9767                 }
9768                 args[i] = NULL;
9769                 s = brstrip(s);
9770                 makestr(&args[i],s);
9771             }
9772             args[i] = NULL;
9773         } else {
9774 #endif /* CKEXEC */
9775             if ((x = cmtxt("System command to execute","",&s,xxstring)) < 0)
9776               return(x);
9777 #ifdef CKEXEC
9778         }
9779 #endif /* CKEXEC */
9780         if (nopush)
9781           return(success = 0);
9782 #ifdef CK_APC
9783         if (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
9784           return(success = 0);
9785 #endif /* CK_APC */
9786         conres();                       /* Make console normal  */
9787 #ifdef OS2
9788         if (!(s && *s)) {
9789             os2push();
9790             return(success = 1);
9791         } else
9792 #endif /* OS2 */
9793           if (cx == XXSHE) {
9794               x = zshcmd(s);
9795               debug(F101,"RUN zshcmd code","",x);
9796               concb((char)escape);
9797               return(success = x);
9798 #ifdef CKEXEC
9799           } else {
9800 #ifdef DEBUG
9801               if (deblog) {
9802                   debug(F111,"EXEC cmd",p,0);
9803                   for (i = 0; i < 256 && args[i]; i++)
9804                     debug(F111,"EXEC arg",args[i],i);
9805               }
9806 #endif /* DEBUG */
9807               if (p) {
9808                   z_exec(p,args,rx);    /* Overlay ourself */
9809                   debug(F100,"EXEC fails","",0);
9810                   concb((char)escape);  /* In case it returns */
9811               }
9812               return(success = 0);
9813 #endif /* CKEXEC */
9814           }
9815     }
9816
9817 #ifdef CK_REDIR
9818     if (cx == XXFUN) {                  /* REDIRECT */
9819 #ifdef CK_APC
9820         if ((apcactive == APC_LOCAL) ||
9821             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9822           return(success = 0);
9823 #endif /* CK_APC */
9824         ckmakmsg(tmpbuf,
9825                  TMPBUFSIZ,
9826                  "Local command to run,\n",
9827                  "with its standard input/output redirected to ",
9828                  local ? ttname : "the communications connection",
9829                  "\n"
9830                  );
9831         if ((x = cmtxt(tmpbuf,"",&s,xxstring)) < 0)
9832           return(x);
9833         if (nopush) {
9834             printf("?REDIRECT disabled\n");
9835             return(success=0);
9836         }
9837         if (!local) {
9838             printf("?SET LINE or SET HOST required first\n");
9839             return(-9);
9840         }
9841         if (!*s) {
9842             printf("?REDIRECT requires a command to redirect\n");
9843             return(-9);
9844         }
9845         return(success = ttruncmd(s));
9846     }
9847 #endif /* CK_REDIR */
9848 #endif /* NOPUSH */
9849
9850 #ifndef NOSHOW
9851     if (cx == XXSHO) {                  /* SHOW */
9852         x = cmkey(shotab,nsho,"","parameters",xxstring);
9853         if (x < 0) return(x);
9854         return(doshow(x));
9855     }
9856 #endif /* NOSHOW */
9857
9858 #ifndef MAC
9859     if (cx == XXSPA) {                  /* SPACE */
9860 #ifdef IKSD
9861         if (inserver && !ENABLED(en_spa)) {
9862             printf("?Sorry, SPACE command disabled\n");
9863             return(-9);
9864         }
9865 #endif /* IKSD */
9866 #ifdef datageneral
9867         /* AOS/VS can take an argument after its "space" command. */
9868         if ((x = cmtxt("Confirm, or local directory name","",&s,xxstring)) < 0)
9869           return(x);
9870         if (nopush) {
9871             printf("?Sorry, SPACE command disabled\n");
9872             return(-9);
9873         } else if (*s == NUL) {
9874             xsystem(SPACMD);
9875         } else {
9876             ckmakmsg(line,LINBUFSIZ,"space ",s,NULL,NULL);
9877             xsystem(line);
9878         }
9879 #else
9880 #ifdef OS2
9881         if ((x = cmtxt("Press Enter for current disk,\n\
9882  or specify a disk letter like A:","",&s,xxstring)) < 0)
9883           return(x);
9884         if (*s == NUL) {                /* Current disk */
9885             unsigned long space = zdskspace(0);
9886             if (space > 0 && space < 1024)
9887               printf(" Free space: unknown\n");
9888             else
9889               printf(" Free space: %ldK\n", space/1024L);
9890         } else {
9891             int drive = toupper(*s);
9892             unsigned long space = zdskspace(drive - 'A' + 1);
9893             if (space > 0 && space < 1024)
9894               printf(" Drive %c: unknown free\n");
9895             else
9896               printf(" Drive %c: %ldK free\n", drive,space / 1024L);
9897         }
9898 #else
9899 #ifdef UNIXOROSK
9900         x = cmdir("Confirm for current disk,\n\
9901  or specify a disk device or directory","",&s,xxstring);
9902         if (x == -3)
9903           s = "";
9904         else if (x < 0)
9905           return(x);
9906         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
9907         s = tmpbuf;
9908         if ((x = cmcfm()) < 0) return(x);
9909         if (nopush) {
9910             printf("?Sorry, SPACE command disabled\n");
9911             return(-9);
9912         }
9913         if (!*s) {                      /* Current disk */
9914             xsystem(SPACMD);
9915         } else {                        /* Specified disk */
9916             ckmakmsg(line,LINBUFSIZ,SPACM2," ",s,NULL);
9917             xsystem(line);
9918         }
9919 #else
9920         if ((x = cmcfm()) < 0) return(x);
9921         if (nopush) {
9922             printf("?Sorry, SPACE command disabled\n");
9923             return(-9);
9924         }
9925         xsystem(SPACMD);
9926 #endif /* UNIXOROSK */
9927 #endif /* OS2 */
9928 #endif /* datageneral */
9929         return(success = 1);            /* Pretend it worked */
9930     }
9931 #endif /* MAC */
9932
9933 #ifndef NOXFER
9934     if (cx == XXSTA) {                  /* STATISTICS */
9935         if ((x = cmkey(stattab,2,"Carriage return, or option",
9936                        "/brief",xxstring)) < 0)
9937           return(x);
9938         if ((y = cmcfm()) < 0) return(y);
9939         return(success = dostat(x));
9940     }
9941 #endif /* NOXFER */
9942
9943     if (cx == XXSTO || cx == XXEND) {   /* STOP, END, or POP */
9944         if ((y = cmnum("exit status code","0",10,&x,xxstring)) < 0)
9945           return(y);
9946         if ((y = cmtxt("Message to print","",&s,xxstring)) < 0)
9947           return(y);
9948         s = brstrip(s);
9949         if (*s) printf("%s\n",s);
9950         if (cx == XXSTO) {
9951             dostop();
9952         } else {
9953             doend(x);
9954         }
9955         return(success = (x == 0));
9956     }
9957     if (cx == XXSUS) {                  /* SUSPEND */
9958         if ((y = cmcfm()) < 0) return(y);
9959 #ifdef NOJC
9960         printf("Sorry, this version of Kermit cannot be suspended\n");
9961 #else
9962 #ifdef IKSD
9963         if (inserver) {
9964             printf("?Sorry, IKSD can not be suspended\n");
9965             return(-9);
9966         } else
9967 #endif /* IKSD */
9968           if (nopush) {
9969             printf("?Sorry, access to system is disabled\n");
9970             return(-9);
9971         }
9972         stptrap(0);
9973 #endif /* NOJC */
9974         return(0);
9975     }
9976
9977     if (cx == XXTAK) {                  /* TAKE */
9978         char * scriptenv = NULL;        
9979 #ifdef OS2
9980         char * GetAppData(int);
9981         extern char startupdir[],exedir[],inidir[];
9982         char * keymapenv = NULL;
9983         char * appdata0 = NULL, *appdata1 = NULL;
9984         int xx;
9985 #define TAKEPATHLEN 4096
9986 #else /* OS2 */
9987 #define TAKEPATHLEN 1024
9988 #endif /* OS2 */
9989         char takepath[TAKEPATHLEN];
9990
9991         if (tlevel >= MAXTAKE-1) {
9992             printf("?Take files nested too deeply\n");
9993             return(-9);
9994         }
9995 #ifdef OS2
9996 #ifdef NT
9997         scriptenv = getenv("K95SCRIPTS");
9998         keymapenv = getenv("K95KEYMAPS");
9999         makestr(&appdata0,(char *)GetAppData(0));
10000         makestr(&appdata1,(char *)GetAppData(1));
10001 #else /* NT */
10002         scriptenv = getenv("K2SCRIPTS");
10003         keymapenv = getenv("K2KEYMAPS");
10004 #endif /* NT */
10005 #endif /* OS2 */
10006
10007         if (!scriptenv)                 /* Let this work for Unix etc too */
10008           scriptenv = getenv("CK_SCRIPTS"); /* Use this if defined */
10009 #ifndef OS2
10010         if (!scriptenv)                 /* Otherwise use home directory */
10011           scriptenv = homepath();
10012 #endif /* OS2 */
10013         if (!scriptenv)
10014           scriptenv = "";
10015         ckstrncpy(takepath,scriptenv,TAKEPATHLEN);
10016         debug(F110,"TAKE initial takepath",takepath,0);
10017
10018 #ifdef OS2
10019         if (!keymapenv)
10020           keymapenv = getenv("CK_KEYMAPS");
10021         if (!keymapenv)
10022           keymapenv = "";
10023
10024         ckstrncat(takepath,
10025                   (scriptenv && scriptenv[strlen(scriptenv)-1]==';')?"":";",
10026                   TAKEPATHLEN
10027                   );
10028         ckstrncat(takepath,keymapenv?keymapenv:"",TAKEPATHLEN);
10029         ckstrncat(takepath,
10030                   (keymapenv && keymapenv[strlen(keymapenv)-1]==';')?"":";",
10031                   TAKEPATHLEN
10032                   );
10033         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10034         ckstrncat(takepath,";",TAKEPATHLEN);
10035         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10036         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10037         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10038         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10039
10040         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10041         ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
10042         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10043         ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
10044         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10045         ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
10046
10047         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10048         ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
10049         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10050         ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
10051         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10052         ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
10053
10054         ckstrncat(takepath,inidir,TAKEPATHLEN);
10055         ckstrncat(takepath,";",TAKEPATHLEN);
10056         ckstrncat(takepath,inidir,TAKEPATHLEN);
10057         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10058         ckstrncat(takepath,inidir,TAKEPATHLEN);
10059         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10060
10061         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10062         ckstrncat(takepath,";",TAKEPATHLEN);
10063         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10064         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10065         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10066         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10067
10068         ckstrncat(takepath,exedir,TAKEPATHLEN);
10069         ckstrncat(takepath,";",TAKEPATHLEN);
10070         ckstrncat(takepath,exedir,TAKEPATHLEN);
10071         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10072         ckstrncat(takepath,exedir,TAKEPATHLEN);
10073         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10074 #endif /* OS2 */
10075         debug(F110,"TAKE final takepath",takepath,0);
10076
10077         if ((y = cmifip("Commands from file",
10078                         "",&s,&x,0,takepath,xxstring)) < 0) {
10079             if (y == -3) {
10080                 printf("?A file name is required\n");
10081                 return(-9);
10082             } else
10083               return(y);
10084         }
10085         if (x != 0) {
10086             printf("?Wildcards not allowed in command file name\n");
10087             return(-9);
10088         }
10089         ckstrncpy(line,s,LINBUFSIZ);
10090         debug(F110,"TAKE file",s,0);
10091         if (isdir(s)) {
10092             printf("?Can't execute a directory - \"%s\"\n", s);
10093             return(-9);
10094         }
10095 #ifndef NOTAKEARGS
10096         {
10097             char * p;
10098             x = strlen(line);
10099             debug(F111,"TAKE args",line,x);
10100             p = line + x + 1;
10101             if ((y = cmtxt("Optional arguments","",&s,xxstring)) < 0)
10102               return(y);
10103             if (*s) {                   /* Args given? */
10104                 ckstrncpy(p,s,LINBUFSIZ-x-1);
10105 #ifdef ZFNQFP
10106                 zfnqfp(line,TMPBUFSIZ,tmpbuf);
10107                 s = tmpbuf;
10108 #else
10109                 s = line;
10110 #endif /* ZFNQFP */
10111                 debug(F110,"TAKE filename",s,0);
10112                 x = strlen(s);
10113                 debug(F101,"TAKE new len",s,x);
10114
10115 #ifdef COMMENT
10116 /*
10117   This was added in C-Kermit 7.0 to allow args to be passed from the TAKE
10118   command to the command file.  But it overwrites the current argument vector,
10119   which is at best surprising, and at worst unsafe.
10120 */
10121                 addmac("%0",s);         /* Define %0 = name of file */
10122                 varnam[0] = '%';
10123                 varnam[2] = '\0';
10124                 debug(F110,"take arg 0",s,0);
10125                 debug(F110,"take args",p,0);
10126                 for (y = 1; y < 10; y++) { /* Clear current args %1..%9 */
10127                     varnam[1] = (char) (y + '0');
10128                     delmac(varnam,0);
10129                 }
10130                 xwords(p,MAXARGLIST,NULL,0); /* Assign new args */
10131                 debug(F110,"take args",p,0);
10132 #else
10133 /*
10134   This method is used in 8.0.  If the TAKE command includes arguments, we
10135   insert an intermediate temporary macro between the current level; we pass
10136   the arguments to the macro and then the macro TAKEs the command file.
10137   If the user Ctrl-C's out of the TAKE file, some temporary macro definitions
10138   and other small malloc'd bits might be left behind.
10139 */
10140                 {
10141                     char * q = NULL;
10142                     char * r = NULL;
10143                     int k, m;
10144                     m = maclvl;
10145                     q = (char *)malloc(x+24);
10146                     if (q) {
10147                         r = (char *)malloc(x+24);
10148                         if (r) {
10149                             sprintf(q,"_file[%s](%d)",s,cmdlvl); /* safe */
10150                             sprintf(r,"take %s",s); /* safe */
10151                             k = addmac(q,r);
10152                             if (k > -1) {
10153                                 dodo(k,p,0);
10154                                 while (maclvl > m) {
10155                                     sstate = (CHAR) parser(1);
10156                                     if (sstate) proto();
10157                                 }
10158                             }
10159                             k = delmac(q,0);
10160                             free(q);
10161                             free(r);
10162                             return(success);
10163                         }
10164                     }
10165                 }
10166                 return(success = 0);
10167 #endif /* COMMENT */
10168             }
10169         }
10170 #else
10171         if ((y = cmcfm()) < 0) return(y);
10172 #endif /* NOTAKEARGS */
10173         return(success = dotake(line));
10174     }
10175
10176 #ifndef NOLOCAL
10177 #ifdef OS2
10178     if (cx == XXVIEW) {                 /* VIEW Only Terminal mode */
10179         viewonly = TRUE;
10180         success = doconect(0, 0);
10181         viewonly = FALSE;
10182         return success;
10183     }
10184 #endif /* OS2 */
10185
10186 #ifdef NETCONN
10187     if (cx == XXTEL || cx == XXIKSD) {  /* TELNET */
10188         int x,z;
10189 #ifdef OS2
10190     if (!tcp_avail) {
10191         printf("?Sorry, either TCP/IP is not available on this system or\n\
10192 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
10193         success = 0;
10194         return(-9);
10195     } else
10196 #endif /* OS2 */
10197       {
10198           x = nettype;                  /* Save net type in case of failure */
10199           z = ttnproto;                 /* Save protocol in case of failure */
10200           nettype = NET_TCPB;
10201           ttnproto = (cx == XXTEL) ? NP_TELNET : NP_KERMIT;
10202           if ((y = setlin(XYHOST,0,1)) <= 0) {
10203               nettype = x;              /* Failed, restore net type. */
10204               ttnproto = z;             /* and protocol */
10205               success = 0;
10206           }
10207           didsetlin++;
10208         }
10209         return(y);
10210     }
10211
10212 #ifndef PTYORPIPE
10213 #ifdef NETCMD
10214 #define PTYORPIPE
10215 #else
10216 #ifdef NETPTY
10217 #define PTYORPIPE
10218 #endif /* NETPTY */
10219 #endif /* NETCMD */
10220 #endif /* PTYORPIPE */
10221
10222 #ifdef PTYORPIPE
10223     if (cx == XXPIPE || cx == XXPTY) {  /* PIPE or PTY */
10224         int x;
10225         extern int netsave;
10226         x = nettype;                    /* Save net type in case of failure */
10227         nettype = (cx == XXPIPE) ? NET_CMD : NET_PTY;
10228         if ((y = setlin(XYHOST,0,1)) < 0) {
10229             nettype = x;                /* Failed, restore net type. */
10230             ttnproto = z;               /* and protocol */
10231             success = 0;
10232         }
10233         didsetlin++;
10234         netsave = x;
10235         return(y);
10236     }
10237 #endif /* PTYORPIPE */
10238
10239 #ifdef ANYSSH
10240     if (cx == XXSSH) {                  /* SSH (Secure Shell) */
10241         extern int netsave;
10242 #ifdef SSHBUILTIN
10243         int k, x, havehost = 0, trips = 0;
10244         int    tmpver = -1, tmpxfw = -1;
10245 #ifndef SSHTEST
10246         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
10247         extern int sl_ssh_ver, sl_ssh_ver_saved;
10248 #endif /* SSHTEST */
10249         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
10250         extern char * slmsg;
10251         extern char uidbuf[], sl_uidbuf[];
10252         extern char pwbuf[], * g_pswd;
10253         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
10254         struct FDB sw, kw, fl;
10255
10256         if (ssh_tmpstr)
10257           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
10258         makestr(&ssh_tmpstr,NULL);
10259         makestr(&ssh_tmpuid,NULL);
10260         makestr(&ssh_tmpcmd,NULL);
10261         makestr(&ssh_tmpport,NULL);
10262
10263         cmfdbi(&kw,                     /* 1st FDB - commands */
10264                _CMKEY,                  /* fcode */
10265                "host [ port ],\n or action",    /* hlpmsg */
10266                "",                      /* default */
10267                "",                      /* addtl string data */
10268                nsshcmd,                 /* addtl numeric data 1: tbl size */
10269                0,                       /* addtl numeric data 2: 0 = keyword */
10270                xxstring,                /* Processing function */
10271                sshkwtab,                /* Keyword table */
10272                &fl                      /* Pointer to next FDB */
10273                );
10274         cmfdbi(&fl,                     /* Host */
10275                _CMFLD,                  /* fcode */
10276                "",                      /* hlpmsg */
10277                "",                      /* default */
10278                "",                      /* addtl string data */
10279                0,                       /* addtl numeric data 1 */
10280                0,                       /* addtl numeric data 2 */
10281                xxstring,
10282                NULL,
10283                NULL
10284                );
10285
10286         x = cmfdb(&kw);
10287         if (x == -3) {
10288             printf("?ssh what?\n");
10289             return(-9);
10290         }
10291         if (x < 0)
10292           return(x);
10293         havehost = 0;
10294         if (cmresult.fcode == _CMFLD) {
10295             havehost = 1;
10296             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
10297             cmresult.nresult = XSSH_OPN;
10298         }
10299         switch (cmresult.nresult) {     /* SSH keyword */
10300           case XSSH_OPN:                /* SSH OPEN */
10301             if (!havehost) {
10302                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
10303                   return(x);
10304                 ckstrncpy(line,s,LINBUFSIZ);
10305             }
10306             /* Parse [ port ] [ switches ] */
10307             cmfdbi(&kw,                 /* Switches */
10308                    _CMKEY,
10309                    "Port number or service name,\nor switch",
10310                    "",
10311                    "",
10312                    nsshopnsw,
10313                    4,
10314                    xxstring,
10315                    sshopnsw,
10316                    &fl
10317                    );
10318             cmfdbi(&fl,                 /* Port number or service name */
10319                    _CMFLD,
10320                    "",
10321                    "",
10322                    "",
10323                    0,
10324                    0,
10325                    xxstring,
10326                    NULL,
10327                    NULL
10328                    );
10329             trips = 0;                  /* Explained below */
10330             while (1) {                 /* Parse port and switches */
10331                 x = cmfdb(&kw);         /* Get a field */
10332                 if (x == -3)            /* User typed CR so quit from loop */
10333                   break;
10334                 if (x < 0)              /* Other parse error, pass it back */
10335                   return(x);
10336                 switch (cmresult.fcode) { /* Field or Keyword? */
10337                   case _CMFLD:            /* Field */
10338                     makestr(&ssh_tmpport,cmresult.sresult);
10339                     break;
10340                   case _CMKEY:          /* Keyword */
10341                     switch (cmresult.nresult) { /* Which one? */
10342                       case SSHSW_USR:           /* /USER: */
10343                         if (!cmgbrk()) {
10344                             printf("?This switch requires an argument\n");
10345                             return(-9);
10346                         }
10347                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
10348                           return(y);
10349                         s = brstrip(s);
10350                         makestr(&ssh_tmpuid,s);
10351                         break;
10352                       case SSHSW_PWD:
10353                         if (!cmgbrk()) {
10354                             printf("?This switch requires an argument\n");
10355                             return(-9);
10356                         }
10357                         debok = 0;
10358                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
10359                             if (x == -3) {
10360                                 makestr(&ssh_tmpstr,"");
10361                             } else {
10362                                 return(x);
10363                             }
10364                         } else {
10365                             s = brstrip(s);
10366                             if ((x = (int)strlen(s)) > PWBUFL) {
10367                                 makestr(&slmsg,"Internal error");
10368                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
10369                                 return(-9);
10370                             }
10371                             makestr(&ssh_tmpstr,s);
10372                         }
10373                         break;
10374
10375                       case SSHSW_VER:
10376                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
10377                           return(x);
10378                         if (z < 1 || z > 2) {
10379                             printf("?Out of range: %d\n",z);
10380                             return(-9);
10381                         }
10382                         tmpver = z;
10383                         break;
10384                       case SSHSW_CMD:
10385                       case SSHSW_SUB:
10386                         if ((x = cmfld("Text","",&s,xxstring)) < 0)
10387                           return(x);
10388                         makestr(&ssh_tmpcmd,s);
10389                         ssh_cas = (cmresult.nresult == SSHSW_SUB);
10390                         break;
10391                       case SSHSW_X11:
10392                         if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
10393                           return(x);
10394                         tmpxfw = x;
10395                         break;
10396                       default:
10397                         return(-2);
10398                     }
10399                 }
10400                 if (trips++ == 0) {     /* After first time through */
10401                     cmfdbi(&kw,         /* only parse switches, not port. */
10402                            _CMKEY,
10403                            "Switch",
10404                            "",
10405                            "",
10406                            nsshopnsw,
10407                            4,
10408                            xxstring,
10409                            sshopnsw,
10410                            NULL
10411                            );
10412                 }
10413             }
10414             if ((x = cmcfm()) < 0)      /* Get confirmation */
10415               return(x);
10416             if (clskconnx(1) < 0) {     /* Close current Kermit connection */
10417               if ( ssh_tmpstr ) {
10418                   memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
10419                   makestr(&ssh_tmpstr,NULL);
10420               }
10421               return(success = 0);
10422             }
10423             makestr(&ssh_hst,line);     /* Stash everything */
10424             if (ssh_tmpuid) {
10425                 if (!sl_uid_saved) {
10426                     ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
10427                     sl_uid_saved = 1;
10428                 }
10429                 ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
10430                 makestr(&ssh_tmpuid,NULL);
10431             }
10432             if (ssh_tmpport) {
10433                 makestr(&ssh_prt,ssh_tmpport);
10434                 makestr(&ssh_tmpport,NULL);
10435             } else
10436                 makestr(&ssh_prt,NULL);
10437
10438             if (ssh_tmpcmd) {
10439                 makestr(&ssh_cmd,brstrip(ssh_tmpcmd));
10440                 makestr(&ssh_tmpcmd,NULL);
10441             } else
10442                 makestr(&ssh_cmd,NULL);
10443
10444             if (tmpver > -1) {
10445 #ifndef SSHTEST
10446                 if (!sl_ssh_ver_saved) {
10447                     sl_ssh_ver = ssh_ver;
10448                     sl_ssh_ver_saved = 1;
10449                 }
10450 #endif /* SSHTEST */
10451                 ssh_ver = tmpver;
10452             }
10453             if (tmpxfw > -1) {
10454 #ifndef SSHTEST
10455                 if (!sl_ssh_xfw_saved) {
10456                     sl_ssh_xfw = ssh_xfw;
10457                     sl_ssh_xfw_saved = 1;
10458                 }
10459 #endif /* SSHTEST */
10460                 ssh_xfw = tmpxfw;
10461             }
10462             if (ssh_tmpstr) {
10463                 if (ssh_tmpstr[0]) {
10464                     ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
10465                     pwflg = 1;
10466                     pwcrypt = 0;
10467                 } else
10468                   pwflg = 0;
10469                 makestr(&ssh_tmpstr,NULL);
10470             }
10471             nettype = NET_SSH;
10472             if (mdmsav < 0)
10473               mdmsav = mdmtyp;
10474             mdmtyp = -nettype;
10475             x = 1;
10476
10477 #ifndef NOSPL
10478             makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
10479             g_pflg = pwflg;                     /* and flag */
10480             g_pcpt = pwcrypt;
10481 #endif /* NOSPL */
10482
10483             /* Line parameter to ttopen() is ignored */
10484             k = ttopen(line,&x,mdmtyp, 0);
10485             if (k < 0) {
10486                 printf("?Unable to connect to %s\n",ssh_hst);
10487                 mdmtyp = mdmsav;
10488                 slrestor();
10489                 return(success = 0);
10490             }
10491             duplex = 0;             /* Remote echo */
10492             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
10493             debug(F110,"ssh ttname",ttname,0);
10494             makestr(&slmsg,NULL);       /* No SET LINE error message */
10495             cxtype = CXT_SSH;
10496 #ifndef NODIAL
10497             dialsta = DIA_UNK;
10498 #endif /* NODIAL */
10499             success = 1;                /* SET LINE succeeded */
10500             network = 1;                /* Network connection (not serial) */
10501             local = 1;                  /* Local mode (not remote) */
10502             if ((reliable != SET_OFF || !setreliable))
10503               reliable = SET_ON;        /* Transport is reliable end to end */
10504 #ifdef OS2
10505             DialerSend(OPT_KERMIT_CONNECT, 0);
10506 #endif /* OS2 */
10507             setflow();                  /* Set appropriate flow control */
10508
10509             haveline = 1;
10510 #ifdef CKLOGDIAL
10511 #ifdef NETCONN
10512             dolognet();
10513 #endif /* NETCONN */
10514 #endif /* CKLOGDIAL */
10515
10516 #ifndef NOSPL
10517             if (local) {
10518                 if (nmac) {             /* Any macros defined? */
10519                     int k;              /* Yes */
10520                     k = mlook(mactab,"on_open",nmac); /* Look this up */
10521                     if (k >= 0) {                     /* If found, */
10522                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
10523                           parser(1);                  /* and execute it */
10524                     }
10525                 }
10526             }
10527 #endif /* NOSPL */
10528 #ifdef LOCUS            
10529             if (autolocus)
10530                 setlocus(1,1);
10531 #endif /* LOCUS */
10532
10533         /* Command was confirmed so we can pre-pop command level. */
10534         /* This is so CONNECT module won't think we're executing a */
10535         /* script if CONNECT was the final command in the script. */
10536             if (cmdlvl > 0)
10537               prepop();
10538             success = doconect(0,cmdlvl == 0 ? 1 : 0);
10539             if (ttchk() < 0)
10540               dologend();
10541             return(success);
10542
10543           case XSSH_CLR:
10544             if ((y = cmkey(sshclr,nsshclr,"","", xxstring)) < 0) {
10545                 if (y == -3) {
10546                     printf("?clear what?\n");
10547                     return(-9);
10548                 }
10549                 return(y);
10550             }
10551             if ((x = cmcfm()) < 0)
10552               return(x);
10553             switch (y) {
10554               case SSHC_LPF:
10555                 ssh_pf_lcl_n = 0;
10556                 break;
10557               case SSHC_RPF:
10558                 ssh_pf_rmt_n = 0;
10559                 break;
10560               default:
10561                 return(-2);
10562             }
10563             return(success = 1);        /* or whatever */
10564
10565           case XSSH_AGT: {              /* SSH AGENT */
10566               int doeach = 0;
10567               if ((y = cmkey(sshagent,nsshagent,"","",xxstring)) < 0)
10568                 return(y);
10569               switch (y) {
10570                 case SSHA_ADD:          /* SSH AGENT ADD ... */
10571                   if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
10572 #ifndef SSHTEST
10573                       if (x == -3)      /* No name given */
10574                         doeach = 1;     /* so do them all */
10575                       else
10576 #endif /* SSHTEST */
10577                         return(x);
10578                   }
10579                   ckstrncpy(line,s,LINBUFSIZ);
10580                   if ((x = cmcfm()) < 0)
10581                     return(x);
10582 #ifdef SSHTEST
10583                   x = 0;
10584 #else
10585                   if (doeach) {
10586                       int i;
10587                       x = 0;
10588                       for (i = 0; i < ssh_idf_n; i++)
10589                         x += ssh_agent_add_file(ssh_idf[i]);
10590                   } else
10591                     x = ssh_agent_add_file(line);
10592 #endif /* SSHTEST */
10593                   return(success = (x == 0));
10594
10595                 case SSHA_DEL: {        /* SSH AGENT DELETE ... */
10596                     int doall = 0;
10597                     if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
10598 #ifndef SSHTEST
10599                         if (x == -3)    /* No name given */
10600                           doall = 1;    /* so do them all */
10601                         else
10602 #endif /* SSHTEST */
10603                           return(x);
10604                     }
10605                     ckstrncpy(line,s,LINBUFSIZ);
10606                     if ((x = cmcfm()) < 0)
10607                       return(x);
10608 #ifdef SSHTEST
10609                     x = 0;
10610 #else
10611                     if (doall)
10612                       x = ssh_agent_delete_all();
10613                     else
10614                       x = ssh_agent_delete_file(line);
10615 #endif /* SSHTEST */
10616                     return(success = (x == 0));
10617                 }
10618                 case SSHA_LST: {
10619                     int fingerprint = 0;
10620                     if ((y = cmswi(sshagtsw,nsshagtsw,"","",xxstring)) < 0) {
10621                         if (y != -3)
10622                           return(y);
10623                     } else if (cmgbrk() > SP) {
10624                         printf("?This switch does not take an argument\n");
10625                         return(-9);
10626                     } else if (y == SSHASW_FP) {
10627                         fingerprint = 1;
10628                     }
10629                     if ((x = cmcfm()) < 0)
10630                       return(x);
10631 #ifdef SSHTEST
10632                     return(success = 1);
10633 #else
10634                     return(success =
10635                            (ssh_agent_list_identities(fingerprint) == 0));
10636 #endif /* SSHTEST */
10637                 }
10638                 default:
10639                   return(-2);
10640               }
10641           }
10642           case XSSH_ADD: {              /* SSH ADD */
10643               /* ssh add { local, remote } port host port */
10644               int cx, i, j, k;
10645               char * h;
10646               if ((cx = cmkey(addfwd,naddfwd,"","", xxstring)) < 0)
10647                 return(cx);
10648               if ((x = cmnum((cx == SSHF_LCL) ?
10649                              "Local port number" : "Remote port number",
10650                              "",10,&j,xxstring)) < 0)
10651                 return(x);
10652               if ((x = cmfld("Host","",&s,xxstring)) < 0)
10653                 return(x);
10654               makestr(&h,s);
10655               if ((x = cmnum("Port","",10,&k,xxstring)) < 0)
10656                 return(x);
10657               if ((x = cmcfm()) < 0)
10658                 return(x);
10659
10660               switch(cx) {
10661                 case SSHF_LCL:
10662                    if (ssh_pf_lcl_n == 32) {
10663                        printf(
10664 "?Maximum number of local port forwardings already specified\n"
10665                              );
10666                        free(h);
10667                        return(success = 0);
10668                   }
10669                   ssh_pf_lcl[ssh_pf_lcl_n].p1 = j;
10670                   makestr(&(ssh_pf_lcl[ssh_pf_lcl_n].host),h);
10671                   makestr(&h,NULL);
10672                   ssh_pf_lcl[ssh_pf_lcl_n].p2 = k;
10673                   ssh_pf_lcl_n++;
10674                   break;
10675                 case SSHF_RMT:
10676                   if (ssh_pf_rmt_n == 32) {
10677                       printf(
10678 "?Maximum number of remote port forwardings already specified\n"
10679                             );
10680                       free(h);
10681                       return(success = 0);
10682                   }
10683                   ssh_pf_rmt[ssh_pf_rmt_n].p1 = j;
10684                   makestr(&(ssh_pf_rmt[ssh_pf_rmt_n].host),h);
10685                   makestr(&h,NULL);
10686                   ssh_pf_rmt[ssh_pf_rmt_n].p2 = k;
10687                   ssh_pf_rmt_n++;
10688               }
10689               return(success = 1);
10690           }
10691           /* Not supporting arbitrary forwarding yet */
10692           case XSSH_FLP:                /* SSH FORWARD-LOCAL-PORT */
10693           case XSSH_FRP: {              /* SSH FORWARD-REMOTE-PORT */
10694               int li_port = 0;
10695               int to_port = 0;
10696               char * fw_host = NULL;
10697               int n;
10698               if ((x = cmnum(cmresult.nresult == XSSH_FLP ?
10699                               "local-port":"remote-port",
10700                               "",10,&li_port,xxstring)) < 0)
10701                   return(x);
10702               if (li_port < 1 || li_port > 65535) {
10703                   printf("?Out range - min: 1, max: 65535\n");
10704                   return(-9);
10705               }
10706               if ((x = cmfld("host",ssh_hst?ssh_hst:"",&s,xxstring)) < 0)
10707                 return(x);
10708               n = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
10709               fw_host = tmpbuf;
10710               if ((x = cmnum("host-port",ckuitoa(li_port),10,
10711                               &to_port,xxstring)) < 0)
10712                   return(x);
10713               if (to_port < 1 || to_port > 65535) {
10714                   printf("?Out range - min: 1, max: 65535\n");
10715                   return(-9);
10716               }
10717               if ((x = cmcfm()) < 0)
10718                 return(x);
10719               switch (cmresult.nresult) {
10720                 case XSSH_FLP:  /* SSH FORWARD-LOCAL-PORT */
10721 #ifndef SSHTEST
10722                   ssh_fwd_local_port(li_port,fw_host,to_port);
10723 #endif /* SSHTEST */
10724                   return(success = 1);
10725                 case XSSH_FRP:  /* SSH FORWARD-REMOTE-PORT */
10726 #ifndef SSHTEST
10727                   ssh_fwd_remote_port(li_port,fw_host,to_port);
10728 #endif /* SSHTEST */
10729                   return(success = 1);
10730               }
10731               return(success = 1);
10732           }
10733         case XSSH_V2:           /* SSH V2 */
10734           if ((cx = cmkey(ssh2tab,nssh2tab,"","", xxstring)) < 0)
10735             return(cx);
10736           switch (cx) {
10737             case XSSH2_RKE:
10738               if ((x = cmcfm()) < 0)
10739                 return(x);
10740 #ifndef SSHTEST
10741               ssh_v2_rekey();
10742 #endif /* SSHTEST */
10743               return(success = 1);
10744             default:
10745               return(-2);
10746           }
10747         case XSSH_KEY:
10748           if ((cx = cmkey(sshkey,nsshkey,"","", xxstring)) < 0)
10749             return(cx);
10750           switch (cx) {
10751             case SSHK_PASS: {   /* Change passphrase */
10752               char * oldp = NULL, * newp = NULL;
10753               struct FDB df, sw;
10754               cmfdbi(&sw,
10755                      _CMKEY,            /* fcode */
10756                      "Filename, or switch", /* hlpmsg */
10757                      "",                /* default */
10758                      "",                /* addtl string data */
10759                      2,                 /* addtl numeric data 1: tbl size */
10760                      4,                 /* addtl numeric data 2: 4 = cmswi */
10761                      xxstring,          /* Processing function */
10762                      sshkpsw,           /* Keyword table */
10763                      &df                /* Pointer to next FDB */
10764                      );
10765               cmfdbi(&df,               /* 2nd FDB - file for display */
10766                      _CMIFI,            /* output file */
10767                      "",                /* hlpmsg */
10768                      "",                /* default */
10769                      "",                /* addtl string data */
10770                      0,                 /* addtl numeric data 1 */
10771                      0,                 /* addtl numeric data 2 */
10772                      xxstring,
10773                      NULL,
10774                      NULL
10775                      );
10776               line[0] = NUL;
10777
10778               while (1) {
10779                   x = cmfdb(&sw);
10780                   if (x == -3) break;
10781                   if (x < 0)
10782                     return(x);
10783                   if (cmresult.fcode != _CMKEY)
10784                     break;
10785                   if (!cmgbrk()) {
10786                       printf("?This switch requires an argument\n");
10787                       return(-9);
10788                   }
10789                   if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
10790                     return(y);
10791                   switch (cmresult.nresult) {
10792                     case 1:             /* Old */
10793                       makestr(&oldp,s);
10794                       break;
10795                     case 2:             /* New */
10796                       makestr(&newp,s);
10797                   }
10798               }
10799               if (cmresult.fcode == _CMIFI) { /* Filename */
10800                   ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
10801                   if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
10802                     ckstrncpy(line,tmpbuf,LINBUFSIZ);
10803               }
10804               if ((x = cmcfm()) < 0) return(x);
10805
10806 #ifndef SSHTEST
10807               x = sshkey_change_passphrase(line[0] ? line : NULL,
10808                                              oldp, newp);
10809 #endif /* SSHTEST */
10810               makestr(&oldp,NULL);
10811               makestr(&newp,NULL);
10812               success = (x == 0);
10813               return(success);
10814             }
10815             case SSHK_CREA: {   /* SSH KEY CREATE /switches... */
10816               int bits = 1024, keytype = SSHKT_2R;
10817               char * pass = NULL, * comment = NULL;
10818               struct FDB df, sw;
10819
10820               /*
10821                * char * sshkey_default_file(int keytype) 
10822                * will provide the default filename for a given keytype
10823                * is it possible to have the default value for the 2nd
10824                * FDB set and changed when a /TYPE switch is provided?
10825                * Would this allow for tab completion of the filename?
10826                */
10827               cmfdbi(&sw,
10828                      _CMKEY,            /* fcode */
10829                      "Filename, or switch", /* hlpmsg */
10830                      "",                /* default */
10831                      "",                /* addtl string data */
10832                      nsshkcrea,         /* addtl numeric data 1: tbl size */
10833                      4,                 /* addtl numeric data 2: 4 = cmswi */
10834                      xxstring,          /* Processing function */
10835                      sshkcrea,          /* Keyword table */
10836                      &df                /* Pointer to next FDB */
10837                      );
10838               cmfdbi(&df,               /* 2nd FDB - file for display */
10839                      _CMOFI,            /* output file */
10840                      "",                /* hlpmsg */
10841                      "",                /* default */
10842                      "",                /* addtl string data */
10843                      0,                 /* addtl numeric data 1 */
10844                      0,                 /* addtl numeric data 2 */
10845                      xxstring,
10846                      NULL,
10847                      NULL
10848                      );
10849               line[0] = NUL;
10850
10851               while (1) {
10852                   x = cmfdb(&sw);
10853                   if (x == -3) break;
10854                   if (x < 0)
10855                     return(x);
10856                   if (cmresult.fcode != _CMKEY)
10857                     break;
10858                   if (!cmgbrk()) {
10859                       printf("?This switch requires an argument\n");
10860                       return(-9);
10861                   }
10862                   switch (cmresult.nresult) {
10863                     case SSHKC_BI:      /* /BITS:n */
10864                       if ((y = cmnum("","1024",10,&z,xxstring)) < 0)
10865                         return(y);
10866                       if (z < 512 || z > 4096) {
10867                           printf("?Out range - min: 512, max: 4096\n");
10868                           return(-9);
10869                       }
10870                       bits = z;
10871                       break;
10872                     case SSHKC_PP:      /* /PASSPHRASE:blah */
10873                       if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
10874                         return(y);
10875                       makestr(&pass,s);
10876                       break;
10877                     case SSHKC_TY:      /* /TYPE:keyword */
10878                       if ((y = cmkey(sshkcty,nsshkcty,"",
10879                                      "v2-rsa",xxstring)) < 0)
10880                         return(y);
10881                       keytype = y;
10882                       break;
10883                     case SSHKC_1R:      /* /COMMENT */
10884                       if ((y = cmfld("Text","",&s,xxstring)) < 0)
10885                         return(y);
10886                       makestr(&comment,s);
10887                       break;
10888                   }
10889               }
10890               if (cmresult.fcode == _CMOFI) { /* Filename */
10891                   if (cmresult.sresult) {
10892                       ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
10893                       if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
10894                           ckstrncpy(line,tmpbuf,LINBUFSIZ);
10895                   }
10896               }
10897               if ((y = cmcfm()) < 0) /* Confirm */
10898                 return(y);
10899 #ifndef SSHTEST
10900               x = sshkey_create(line[0] ? line : NULL,
10901                                 bits, pass, keytype, comment);
10902               if (pass)
10903                 memset(pass,0,strlen(pass));
10904 #endif /* SSHTEST */
10905               makestr(&pass,NULL);
10906               makestr(&comment,NULL);
10907               return(success = (x == 0));
10908             }
10909             case SSHK_DISP: {   /* SSH KEY DISPLAY /switches... */
10910               char c;
10911               int infmt = 0, outfmt = 0;
10912               struct FDB df, sw;
10913               cmfdbi(&sw,
10914                      _CMKEY,            /* fcode */
10915                      "Filename, or switch", /* hlpmsg */
10916                      "",                /* default */
10917                      "",                /* addtl string data */
10918                      nsshdswi,          /* addtl numeric data 1: tbl size */
10919                      4,                 /* addtl numeric data 2: 4 = cmswi */
10920                      xxstring,          /* Processing function */
10921                      sshdswi,           /* Keyword table */
10922                      &df                /* Pointer to next FDB */
10923                      );
10924               cmfdbi(&df,               /* 2nd FDB - file for display */
10925                      _CMIFI,            /* fcode */
10926                      "",                /* hlpmsg */
10927                      "",                /* default */
10928                      "",                /* addtl string data */
10929                      0,                 /* addtl numeric data 1 */
10930                      0,                 /* addtl numeric data 2 */
10931                      xxstring,
10932                      NULL,
10933                      NULL
10934                      );
10935               line[0] = NUL;
10936
10937               while (1) {
10938                   x = cmfdb(&sw);
10939                   if (x == -3) break;
10940                   if (x < 0)
10941                     return(x);
10942                   if (cmresult.fcode != _CMKEY)
10943                     break;
10944                   if (!cmgbrk()) {
10945                       printf("?This switch requires an argument\n");
10946                       return(-9);
10947                   }
10948                   switch (cmresult.nresult) {
10949 #ifdef COMMENT
10950                     case SSHKD_IN:      /* /IN-FORMAT: */
10951                       if ((y = cmkey(sshdifmt,nsshdifmt,
10952                                      "","",xxstring)) < 0)
10953                         return(y);
10954                       infmt = y;
10955                       break;
10956 #endif /* COMMENT */
10957                     case SSHKD_OUT:     /* /FORMAT: */
10958                       if ((y = cmkey(sshdofmt,nsshdofmt,
10959                                      "","",xxstring)) < 0)
10960                         return(y);
10961                       outfmt = y;
10962                       break;
10963                   }
10964               }
10965               if (cmresult.fcode == _CMIFI) { /* Filename */
10966                   ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
10967                   if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
10968                     ckstrncpy(line,tmpbuf,LINBUFSIZ);
10969               }
10970 #ifdef COMMENT
10971               if (!line[0]) {
10972                   printf("?Key filename required\n");
10973                   return(-9);
10974               }
10975 #endif /* COMMENT */
10976               if ((y = cmcfm()) < 0) /* Confirm */
10977                 return(y);
10978 #ifndef SSHTEST
10979               switch (outfmt) {
10980                 case SKDF_OSSH:
10981                   /* 2nd param is optional passphrase */
10982                   x = sshkey_display_public(line[0] ? line : NULL, NULL);
10983                   break;
10984                 case SKDF_SSHC:
10985                   /* 2nd param is optional passphrase */
10986                   x = sshkey_display_public_as_ssh2(line[0] ? line : NULL,
10987                                                     NULL);
10988                   break;
10989                 case SKDF_IETF:
10990                   x = sshkey_display_fingerprint(line[0] ? line : NULL, 1);
10991                   break;
10992                 case SKDF_FING:
10993                   x = sshkey_display_fingerprint(line[0] ? line : NULL, 0);
10994                   break;
10995               }
10996 #endif /* SSHTEST */
10997               return(success = (x == 0));
10998             }
10999             case SSHK_V1:               /* SSH KEY V1 SET-COMMENT */
11000               if ((x = cmkey(sshkv1,1,"","set-comment", xxstring)) < 0)
11001                 return(x);
11002               if (x != 1) return(-2);
11003               if ((x = cmifi("Key file name","",&s,&y,xxstring)) < 0) {
11004                   if (x == -3) {
11005                       printf("?Name of key file required\n");
11006                       return(-9);
11007                   }
11008               }
11009               ckstrncpy(line,s,LINBUFSIZ);
11010               if ((x = cmtxt("Comment text","",&s,xxstring)) < 0)
11011                 return(x);
11012 #ifndef SSHTEST
11013               x = sshkey_v1_change_comment(line,  /* filename */
11014                                            s,     /* new comment */
11015                                            NULL   /* passphrase */
11016                                            );
11017 #endif /* SSHTEST */
11018               success = (x == 0);
11019               return(success);
11020           }
11021           default:
11022             return(-2);
11023         }
11024 #else  /* SSHBUILTIN */
11025 #ifdef SSHCMD
11026         x = nettype;
11027         if ((y = setlin(XXSSH,0,1)) < 0) {
11028             if (errno)
11029               printf("?%s\n",ck_errstr());
11030             else
11031 #ifdef COMMENT
11032             /* This isn't right either because it catches command editing */
11033               printf("?Sorry, pseudoterminal open failed\n");
11034             if (hints)
11035               printf("Hint: Try \"ssh -t %s\"\n",line);
11036 #else
11037               return(y);
11038 #endif /* COMMENT */
11039             nettype = x;                /* Failed, restore net type. */
11040             ttnproto = z;               /* and protocol */
11041             success = 0;
11042         }
11043         didsetlin++;
11044         netsave = x;
11045         return(y);
11046 #endif /* SSHCMD */
11047 #endif /* SSHBUILTIN */
11048     }
11049 #endif /* ANYSSH */
11050
11051 #ifdef SSHBUILTIN
11052     if (cx == XXSKRM) {                 /* SKERMIT (Secure Shell Kermit) */
11053         extern int netsave;
11054         int k, x, havehost = 0, trips = 0;
11055         int    tmpver = -1, tmpxfw = -1;
11056 #ifndef SSHTEST
11057         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
11058         extern int sl_ssh_ver, sl_ssh_ver_saved;
11059 #endif /* SSHTEST */
11060         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
11061         extern char * slmsg;
11062         extern char uidbuf[], sl_uidbuf[];
11063         extern char pwbuf[], * g_pswd;
11064         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
11065         struct FDB sw, kw, fl;
11066
11067         if (ssh_tmpstr)
11068           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11069         makestr(&ssh_tmpstr,NULL);
11070         makestr(&ssh_tmpuid,NULL);
11071         makestr(&ssh_tmpcmd,NULL);
11072         makestr(&ssh_tmpport,NULL);
11073
11074         cmfdbi(&kw,                     /* 1st FDB - commands */
11075                _CMKEY,                  /* fcode */
11076                "host [ port ],\n or action", /* hlpmsg */
11077                "",                      /* default */
11078                "",                      /* addtl string data */
11079                nsshkermit,              /* addtl numeric data 1: tbl size */
11080                0,                       /* addtl numeric data 2: 0 = keyword */
11081                xxstring,                /* Processing function */
11082                sshkermit,               /* Keyword table */
11083                &fl                      /* Pointer to next FDB */
11084                );
11085         cmfdbi(&fl,                     /* Host */
11086                _CMFLD,                  /* fcode */
11087                "",                      /* hlpmsg */
11088                "",                      /* default */
11089                "",                      /* addtl string data */
11090                0,                       /* addtl numeric data 1 */
11091                0,                       /* addtl numeric data 2 */
11092                xxstring,
11093                NULL,
11094                NULL
11095                );
11096
11097         x = cmfdb(&kw);
11098         if (x == -3) {
11099             printf("?skermit what?\n");
11100             return(-9);
11101         }
11102         if (x < 0)
11103           return(x);
11104         havehost = 0;
11105         if (cmresult.fcode == _CMFLD) {
11106             havehost = 1;
11107             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
11108             cmresult.nresult = SKRM_OPN;
11109         }
11110         switch (cmresult.nresult) {     /* SSH keyword */
11111           case SKRM_OPN:                /* SSH OPEN */
11112             if (!havehost) {
11113                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
11114                   return(x);
11115                 ckstrncpy(line,s,LINBUFSIZ);
11116             }
11117             /* Parse [ port ] [ switches ] */
11118             cmfdbi(&kw,                 /* Switches */
11119                    _CMKEY,
11120                    "Port number or service name,\nor switch",
11121                    "",
11122                    "",
11123                    nsshkrmopnsw,
11124                    4,
11125                    xxstring,
11126                    sshkrmopnsw,
11127                    &fl
11128                    );
11129             cmfdbi(&fl,                 /* Port number or service name */
11130                    _CMFLD,
11131                    "",
11132                    "",
11133                    "",
11134                    0,
11135                    0,
11136                    xxstring,
11137                    NULL,
11138                    NULL
11139                    );
11140             trips = 0;                  /* Explained below */
11141             while (1) {                 /* Parse port and switches */
11142                 x = cmfdb(&kw);         /* Get a field */
11143                 if (x == -3)            /* User typed CR so quit from loop */
11144                   break;
11145                 if (x < 0)              /* Other parse error, pass it back */
11146                   return(x);
11147                 switch (cmresult.fcode) { /* Field or Keyword? */
11148                   case _CMFLD:            /* Field */
11149                     makestr(&ssh_tmpport,cmresult.sresult);
11150                     break;
11151                   case _CMKEY:          /* Keyword */
11152                     switch (cmresult.nresult) { /* Which one? */
11153                       case SSHSW_USR:           /* /USER: */
11154                         if (!cmgbrk()) {
11155                             printf("?This switch requires an argument\n");
11156                             return(-9);
11157                         }
11158                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
11159                           return(y);
11160                         s = brstrip(s);
11161                         makestr(&ssh_tmpuid,s);
11162                         break;
11163                       case SSHSW_PWD:
11164                         if (!cmgbrk()) {
11165                             printf("?This switch requires an argument\n");
11166                             return(-9);
11167                         }
11168                         debok = 0;
11169                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
11170                             if (x == -3) {
11171                                 makestr(&ssh_tmpstr,"");
11172                             } else {
11173                                 return(x);
11174                             }
11175                         } else {
11176                             s = brstrip(s);
11177                             if ((x = (int)strlen(s)) > PWBUFL) {
11178                                 makestr(&slmsg,"Internal error");
11179                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
11180                                 return(-9);
11181                             }
11182                             makestr(&ssh_tmpstr,s);
11183                         }
11184                         break;
11185
11186                     case SSHSW_VER:
11187                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
11188                           return(x);
11189                         if (z < 1 || z > 2) {
11190                             printf("?Out of range: %d\n",z);
11191                             return(-9);
11192                         }
11193                         tmpver = z;
11194                         break;
11195                     default:
11196                         return(-2);
11197                     }
11198                   }
11199                 if (trips++ == 0) {     /* After first time through */
11200                     cmfdbi(&kw,         /* only parse switches, not port. */
11201                            _CMKEY,
11202                            "Switch",
11203                            "",
11204                            "",
11205                            nsshkrmopnsw,
11206                            4,
11207                            xxstring,
11208                            sshkrmopnsw,
11209                            NULL
11210                            );
11211                 }
11212             }
11213             if ((x = cmcfm()) < 0)      /* Get confirmation */
11214               return(x);
11215               if (clskconnx(1) < 0) {   /* Close current Kermit connection */
11216                   if ( ssh_tmpstr ) {
11217                       memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11218                       makestr(&ssh_tmpstr,NULL);
11219                   }
11220                   return(success = 0);
11221               }
11222               makestr(&ssh_hst,line);   /* Stash everything */
11223               if (ssh_tmpuid) {
11224                   if (!sl_uid_saved) {
11225                       ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
11226                       sl_uid_saved = 1;
11227                   }
11228                   ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
11229                   makestr(&ssh_tmpuid,NULL);
11230               }
11231               if (ssh_tmpport) {
11232                   makestr(&ssh_prt,ssh_tmpport);
11233                   makestr(&ssh_tmpport,NULL);
11234               } else
11235                   makestr(&ssh_prt,NULL);
11236
11237               /* Set the Subsystem to Kermit */
11238               ssh_cas = 1;
11239               makestr(&ssh_cmd,"kermit");
11240
11241               if (tmpver > -1) {
11242 #ifndef SSHTEST
11243                   if (!sl_ssh_ver_saved) {
11244                       sl_ssh_ver = ssh_ver;
11245                       sl_ssh_ver_saved = 1;
11246                   }
11247 #endif /* SSHTEST */
11248                   ssh_ver = tmpver;
11249               }
11250               /* Disable X11 Forwarding */
11251 #ifndef SSHTEST
11252               if (!sl_ssh_xfw_saved) {
11253                   sl_ssh_xfw = ssh_xfw;
11254                   sl_ssh_xfw_saved = 1;
11255               }
11256 #endif /* SSHTEST */
11257               ssh_xfw = 0;
11258
11259               if (ssh_tmpstr) {
11260                   if (ssh_tmpstr[0]) {
11261                       ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
11262                       pwflg = 1;
11263                       pwcrypt = 0;
11264                   } else
11265                       pwflg = 0;
11266                   makestr(&ssh_tmpstr,NULL);
11267               }
11268               nettype = NET_SSH;
11269               if (mdmsav < 0)
11270                   mdmsav = mdmtyp;
11271               mdmtyp = -nettype;
11272               x = 1;
11273
11274 #ifndef NOSPL
11275             makestr(&g_pswd,pwbuf);     /* Save global pwbuf */
11276             g_pflg = pwflg;             /* and flag */
11277             g_pcpt = pwcrypt;
11278 #endif /* NOSPL */
11279
11280             /* Line parameter to ttopen() is ignored */
11281             k = ttopen(line,&x,mdmtyp, 0);
11282             if (k < 0) {
11283                 printf("?Unable to connect to %s\n",ssh_hst);
11284                 mdmtyp = mdmsav;
11285                 slrestor();
11286                 return(success = 0);
11287             }
11288             duplex = 0;             /* Remote echo */
11289             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
11290             debug(F110,"ssh ttname",ttname,0);
11291             makestr(&slmsg,NULL);       /* No SET LINE error message */
11292             cxtype = CXT_SSH;
11293 #ifndef NODIAL
11294             dialsta = DIA_UNK;
11295 #endif /* NODIAL */
11296             success = 1;                /* SET LINE succeeded */
11297             network = 1;                /* Network connection (not serial) */
11298             local = 1;                  /* Local mode (not remote) */
11299             if ((reliable != SET_OFF || !setreliable))
11300               reliable = SET_ON;        /* Transport is reliable end to end */
11301 #ifdef OS2
11302             DialerSend(OPT_KERMIT_CONNECT, 0);
11303 #endif /* OS2 */
11304             setflow();                  /* Set appropriate flow control */
11305
11306             haveline = 1;
11307 #ifdef CKLOGDIAL
11308 #ifdef NETCONN
11309             dolognet();
11310 #endif /* NETCONN */
11311 #endif /* CKLOGDIAL */
11312
11313 #ifndef NOSPL
11314             if (local) {
11315                 if (nmac) {             /* Any macros defined? */
11316                     int k;              /* Yes */
11317                     k = mlook(mactab,"on_open",nmac); /* Look this up */
11318                     if (k >= 0) {                     /* If found, */
11319                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
11320                           parser(1);                  /* and execute it */
11321                     }
11322                 }
11323             }
11324 #endif /* NOSPL */
11325 #ifdef LOCUS            
11326             if (autolocus)
11327                 setlocus(1,1);
11328 #endif /* LOCUS */
11329
11330         /* Command was confirmed so we can pre-pop command level. */
11331         /* This is so CONNECT module won't think we're executing a */
11332         /* script if CONNECT was the final command in the script. */
11333             if (cmdlvl > 0)
11334               prepop();
11335             return(success = 1);
11336
11337           default:
11338             return(-2);
11339         }
11340     }
11341 #endif /* SSHBUILTIN */
11342
11343 #ifdef SFTP_BUILTIN
11344     if (cx == XXSFTP) {                 /* SFTP (Secure Shell File Transfer) */
11345         extern int netsave;
11346         int k, x, havehost = 0, trips = 0;
11347         int    tmpver = -1, tmpxfw = -1;
11348 #ifndef SSHTEST
11349         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
11350         extern int sl_ssh_ver, sl_ssh_ver_saved;
11351 #endif /* SSHTEST */
11352         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
11353         extern char * slmsg;
11354         extern char uidbuf[], sl_uidbuf[];
11355         extern char pwbuf[], * g_pswd;
11356         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
11357         struct FDB sw, kw, fl;
11358
11359         if (ssh_tmpstr)
11360           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11361         makestr(&ssh_tmpstr,NULL);
11362         makestr(&ssh_tmpuid,NULL);
11363         makestr(&ssh_tmpcmd,NULL);
11364         makestr(&ssh_tmpport,NULL);
11365
11366         cmfdbi(&kw,                     /* 1st FDB - commands */
11367                _CMKEY,                  /* fcode */
11368                "host [ port ],\n or action", /* hlpmsg */
11369                "",                      /* default */
11370                "",                      /* addtl string data */
11371                nsftpkwtab,              /* addtl numeric data 1: tbl size */
11372                0,                       /* addtl numeric data 2: 0 = keyword */
11373                xxstring,                /* Processing function */
11374                sftpkwtab,               /* Keyword table */
11375                &fl                      /* Pointer to next FDB */
11376                );
11377         cmfdbi(&fl,                     /* Host */
11378                _CMFLD,                  /* fcode */
11379                "",                      /* hlpmsg */
11380                "",                      /* default */
11381                "",                      /* addtl string data */
11382                0,                       /* addtl numeric data 1 */
11383                0,                       /* addtl numeric data 2 */
11384                xxstring,
11385                NULL,
11386                NULL
11387                );
11388
11389         x = cmfdb(&kw);
11390         if (x == -3) {
11391             printf("?sftp what?\n");
11392             return(-9);
11393         }
11394         if (x < 0)
11395           return(x);
11396         havehost = 0;
11397         if (cmresult.fcode == _CMFLD) {
11398             havehost = 1;
11399             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
11400             cmresult.nresult = SFTP_OPN;
11401         }
11402         switch (cmresult.nresult) {     /* SFTP keyword */
11403           case SFTP_OPN:                /* SFTP OPEN */
11404             if (!havehost) {
11405                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
11406                   return(x);
11407                 ckstrncpy(line,s,LINBUFSIZ);
11408             }
11409             /* Parse [ port ] [ switches ] */
11410             cmfdbi(&kw,                 /* Switches */
11411                    _CMKEY,
11412                    "Port number or service name,\nor switch",
11413                    "",
11414                    "",
11415                    nsshkrmopnsw,
11416                    4,
11417                    xxstring,
11418                    sshkrmopnsw,
11419                    &fl
11420                    );
11421             cmfdbi(&fl,                 /* Port number or service name */
11422                    _CMFLD,
11423                    "",
11424                    "",
11425                    "",
11426                    0,
11427                    0,
11428                    xxstring,
11429                    NULL,
11430                    NULL
11431                    );
11432             trips = 0;                  /* Explained below */
11433             while (1) {                 /* Parse port and switches */
11434                 x = cmfdb(&kw);         /* Get a field */
11435                 if (x == -3)            /* User typed CR so quit from loop */
11436                   break;
11437                 if (x < 0)              /* Other parse error, pass it back */
11438                   return(x);
11439                 switch (cmresult.fcode) { /* Field or Keyword? */
11440                   case _CMFLD:            /* Field */
11441                     makestr(&ssh_tmpport,cmresult.sresult);
11442                     break;
11443                   case _CMKEY:          /* Keyword */
11444                     switch (cmresult.nresult) { /* Which one? */
11445                       case SSHSW_USR:           /* /USER: */
11446                         if (!cmgbrk()) {
11447                             printf("?This switch requires an argument\n");
11448                             return(-9);
11449                         }
11450                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
11451                           return(y);
11452                         s = brstrip(s);
11453                         makestr(&ssh_tmpuid,s);
11454                         break;
11455                       case SSHSW_PWD:
11456                         if (!cmgbrk()) {
11457                             printf("?This switch requires an argument\n");
11458                             return(-9);
11459                         }
11460                         debok = 0;
11461                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
11462                             if (x == -3) {
11463                                 makestr(&ssh_tmpstr,"");
11464                             } else {
11465                                 return(x);
11466                             }
11467                         } else {
11468                             s = brstrip(s);
11469                             if ((x = (int)strlen(s)) > PWBUFL) {
11470                                 makestr(&slmsg,"Internal error");
11471                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
11472                                 return(-9);
11473                             }
11474                             makestr(&ssh_tmpstr,s);
11475                         }
11476                         break;
11477
11478                     case SSHSW_VER:
11479                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
11480                           return(x);
11481                         if (z < 1 || z > 2) {
11482                             printf("?Out of range: %d\n",z);
11483                             return(-9);
11484                         }
11485                         tmpver = z;
11486                         break;
11487                     default:
11488                         return(-2);
11489                     }
11490                 }
11491                 if (trips++ == 0) {     /* After first time through */
11492                     cmfdbi(&kw,         /* only parse switches, not port. */
11493                            _CMKEY,
11494                            "Switch",
11495                            "",
11496                            "",
11497                            nsshkrmopnsw,
11498                            4,
11499                            xxstring,
11500                            sshkrmopnsw,
11501                            NULL
11502                            );
11503                 }
11504             }
11505             if ((x = cmcfm()) < 0)      /* Get confirmation */
11506               return(x);
11507               if (clskconnx(1) < 0) {   /* Close current Kermit connection */
11508                   if ( ssh_tmpstr ) {
11509                       memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11510                       makestr(&ssh_tmpstr,NULL);
11511                   }
11512                   return(success = 0);
11513               }
11514               makestr(&ssh_hst,line);   /* Stash everything */
11515               if (ssh_tmpuid) {
11516                   if (!sl_uid_saved) {
11517                       ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
11518                       sl_uid_saved = 1;
11519                   }
11520                   ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
11521                   makestr(&ssh_tmpuid,NULL);
11522               }
11523               if (ssh_tmpport) {
11524                   makestr(&ssh_prt,ssh_tmpport);
11525                   makestr(&ssh_tmpport,NULL);
11526               } else
11527                   makestr(&ssh_prt,NULL);
11528
11529               /* Set the Subsystem to Kermit */
11530               ssh_cas = 1;
11531               makestr(&ssh_cmd,"sftp");
11532
11533               if (tmpver > -1) {
11534 #ifndef SSHTEST
11535                   if (!sl_ssh_ver_saved) {
11536                       sl_ssh_ver = ssh_ver;
11537                       sl_ssh_ver_saved = 1;
11538                   }
11539 #endif /* SSHTEST */
11540                   ssh_ver = tmpver;
11541               }
11542               /* Disable X11 Forwarding */
11543 #ifndef SSHTEST
11544               if (!sl_ssh_xfw_saved) {
11545                   sl_ssh_xfw = ssh_xfw;
11546                   sl_ssh_xfw_saved = 1;
11547               }
11548 #endif /* SSHTEST */
11549               ssh_xfw = 0;
11550
11551               if (ssh_tmpstr) {
11552                   if (ssh_tmpstr[0]) {
11553                       ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
11554                       pwflg = 1;
11555                       pwcrypt = 0;
11556                   } else
11557                       pwflg = 0;
11558                   makestr(&ssh_tmpstr,NULL);
11559               }
11560               nettype = NET_SSH;
11561               if (mdmsav < 0)
11562                   mdmsav = mdmtyp;
11563               mdmtyp = -nettype;
11564               x = 1;
11565
11566 #ifndef NOSPL
11567             makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
11568             g_pflg = pwflg;                     /* and flag */
11569             g_pcpt = pwcrypt;
11570 #endif /* NOSPL */
11571
11572             /* Line parameter to ttopen() is ignored */
11573             k = ttopen(line,&x,mdmtyp, 0);
11574             if (k < 0) {
11575                 printf("?Unable to connect to %s\n",ssh_hst);
11576                 mdmtyp = mdmsav;
11577                 slrestor();
11578                 return(success = 0);
11579             }
11580             duplex = 0;             /* Remote echo */
11581             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
11582             debug(F110,"ssh ttname",ttname,0);
11583             makestr(&slmsg,NULL);       /* No SET LINE error message */
11584             cxtype = CXT_SSH;
11585 #ifndef NODIAL
11586             dialsta = DIA_UNK;
11587 #endif /* NODIAL */
11588             success = 1;                /* SET LINE succeeded */
11589             network = 1;                /* Network connection (not serial) */
11590             local = 1;                  /* Local mode (not remote) */
11591             if ((reliable != SET_OFF || !setreliable))
11592               reliable = SET_ON;        /* Transport is reliable end to end */
11593 #ifdef OS2
11594             DialerSend(OPT_KERMIT_CONNECT, 0);
11595 #endif /* OS2 */
11596             setflow();                  /* Set appropriate flow control */
11597
11598             haveline = 1;
11599 #ifdef CKLOGDIAL
11600 #ifdef NETCONN
11601             dolognet();
11602 #endif /* NETCONN */
11603 #endif /* CKLOGDIAL */
11604
11605 #ifndef NOSPL
11606             if (local) {
11607                 if (nmac) {             /* Any macros defined? */
11608                     int k;              /* Yes */
11609                     k = mlook(mactab,"on_open",nmac); /* Look this up */
11610                     if (k >= 0) {                     /* If found, */
11611                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
11612                           parser(1);                  /* and execute it */
11613                     }
11614                 }
11615             }
11616 #endif /* NOSPL */
11617 #ifdef LOCUS            
11618             if (autolocus)
11619                 setlocus(1,1);
11620 #endif /* LOCUS */
11621
11622         /* Command was confirmed so we can pre-pop command level. */
11623         /* This is so CONNECT module won't think we're executing a */
11624         /* script if CONNECT was the final command in the script. */
11625             if (cmdlvl > 0)
11626               prepop();
11627
11628             success = sftp_do_init();
11629             return(success = 1);
11630
11631           case SFTP_CD:
11632           case SFTP_CHGRP:
11633           case SFTP_CHMOD:
11634           case SFTP_CHOWN:
11635           case SFTP_RM:
11636           case SFTP_DIR:
11637           case SFTP_GET:
11638           case SFTP_MKDIR:
11639           case SFTP_PUT:
11640           case SFTP_PWD:
11641           case SFTP_REN:
11642           case SFTP_RMDIR:
11643           case SFTP_LINK:
11644           case SFTP_VER:
11645             if ((y = cmtxt("command parameters","",&s,xxstring)) < 0) 
11646               return(y);
11647             if (ssh_tchk() < 0 || !ssh_cas || strcmp(ssh_cmd,"sftp")) {
11648                 printf("?Not connected to SFTP Service\n");
11649                 return(success = 0);
11650             }
11651             success = sftp_do_cmd(cmresult.nresult,s);
11652             return(success);
11653           default:
11654             return(-2);
11655         }
11656     }
11657 #endif /* SFTP_BUILTIN */
11658
11659     if (cx == XXRLOG) {                 /* RLOGIN */
11660 #ifdef RLOGCODE
11661         int x,z;
11662 #ifdef OS2
11663         if (!tcp_avail) {
11664             printf("?Sorry, either TCP/IP is not available on this system or\n\
11665 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
11666                    );
11667             success = 0;
11668             return(-9);
11669         } else {
11670 #endif /* OS2 */
11671             x = nettype;                /* Save net type in case of failure */
11672             z = ttnproto;               /* Save protocol in case of failure */
11673             nettype = NET_TCPB;
11674             ttnproto = NP_RLOGIN;
11675             if ((y = setlin(XYHOST,0,1)) <= 0) {
11676                 nettype = x;            /* Failed, restore net type. */
11677                 ttnproto = z;           /* and protocol */
11678                 success = 0;
11679             }
11680             didsetlin++;
11681 #ifdef OS2
11682         }
11683 #endif /* OS2 */
11684         return(y);
11685 #else
11686         printf("?Sorry, RLOGIN is not configured in this copy of C-Kermit.\n");
11687         return(-9);
11688 #endif /* RLOGCODE */
11689     }
11690 #endif /* NETCONN */
11691 #endif /* NOLOCAL */
11692
11693 #ifndef NOXMIT
11694     if (cx == XXTRA) {                  /* TRANSMIT */
11695         extern int xfrxla;
11696         int i, n, xpipe = 0, xbinary = 0, xxlate = 1, xxnowait = 0, getval;
11697         int xxecho = 0;
11698         int scan = 1;
11699         char c;
11700         struct FDB sf, sw, tx;          /* FDBs for parse functions */
11701 #ifndef NOCSETS
11702         extern int tcs_transp;          /* Term charset is transparent */
11703 #else
11704         int tcs_transp = 1;
11705 #endif /* NOCSETS */
11706
11707 #ifdef COMMENT
11708         xbinary = binary;               /* Default text/binary mode */
11709 #else
11710         xbinary = 0;                    /* Default is text */
11711 #endif /* COMMENT */
11712         xxecho = xmitx;
11713
11714         cmfdbi(&sw,                     /* First FDB - command switches */
11715                _CMKEY,                  /* fcode */
11716                "Filename, or switch",   /* hlpmsg */
11717                "",                      /* default */
11718                "",                      /* addtl string data */
11719                nxmitsw,                 /* addtl numeric data 1: tbl size */
11720                4,                       /* addtl numeric data 2: 4 = cmswi */
11721                xxstring,                /* Processing function */
11722                xmitsw,                  /* Keyword table */
11723                &sf                      /* Pointer to next FDB */
11724                );
11725         cmfdbi(&sf,                     /* 2nd FDB - file to send */
11726                _CMIFI,                  /* fcode */
11727                "File to transmit",      /* hlpmsg */
11728                "",                      /* default */
11729                "",                      /* addtl string data */
11730                0,                       /* addtl numeric data 1 */
11731                0,                       /* addtl numeric data 2 */
11732                xxstring,
11733                NULL,
11734 #ifdef PIPESEND
11735                &tx
11736 #else
11737                NULL
11738 #endif /* PIPESEND */
11739                );
11740 #ifdef PIPESEND
11741         cmfdbi(&tx,
11742                _CMTXT,                  /* fcode */
11743                "Command",               /* hlpmsg */
11744                "",                      /* default */
11745                "",                      /* addtl string data */
11746                0,                       /* addtl numeric data 1 */
11747                0,                       /* addtl numeric data 2 */
11748                xxstring,
11749                NULL,
11750                NULL
11751                );
11752 #endif /* PIPESEND */
11753
11754         while (1) {
11755             x = cmfdb(&sw);
11756             if (x < 0)
11757               return(x);
11758             if (cmresult.fcode != _CMKEY)
11759               break;
11760             c = cmgbrk();               /* Have switch, get break character */
11761             if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
11762                 printf("?This switch does not take an argument\n");
11763                 return(-9);
11764             }
11765             if (!getval && (cmgkwflgs() & CM_ARG)) {
11766                 printf("?This switch requires an argument\n");
11767                 return(-9);
11768             }
11769             n = cmresult.nresult;       /* Numeric result = switch ID */
11770             switch (n) {                /* Process the switch */
11771 #ifdef PIPESEND
11772               case XMI_CMD:             /* Transmit from a command */
11773                 if (nopush) {
11774                     printf("?Sorry, system command access is disabled\n");
11775                     return(-9);
11776                 }
11777                 sw.hlpmsg = "Command, or switch"; /* Change help message */
11778                 xpipe = 1;              /* (No way to undo this one) */
11779                 break;
11780 #endif /* PIPESEND */
11781
11782               case XMI_BIN:             /* Binary */
11783                 xbinary = 1;
11784                 xxlate = 0;             /* Don't translate charsets */
11785                 scan = 0;
11786                 break;
11787
11788               case XMI_TXT:             /* Text */
11789                 xbinary = 0;
11790                 xxlate = !tcs_transp;   /* Translate if TERM CHAR not TRANSP */
11791                 scan = 0;
11792                 break;
11793
11794               case XMI_TRA:             /* Transparent text */
11795                 xbinary = 0;
11796                 xxlate = 0;             /* But don't translate charsets */
11797                 scan = 0;
11798                 break;
11799
11800 #ifdef COMMENT
11801               case XMI_VRB:             /* /VERBOSE */
11802               case XMI_QUI:             /* /QUIET */
11803                 break;                  /* (not implemented yet) */
11804 #endif /* COMMENT */
11805
11806               case XMI_NOW:             /* /NOWAIT */
11807                 xxnowait = 1;
11808                 break;
11809
11810               case XMI_NOE:             /* /NOWAIT */
11811                 xxecho = 0;
11812                 break;
11813
11814               default:
11815                 return(-2);
11816             }
11817
11818         }
11819         if (cmresult.fcode != _CMIFI && cmresult.fcode != _CMTXT)
11820           return(-2);
11821         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Filename */
11822         if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
11823           ckstrncpy(line,tmpbuf,LINBUFSIZ);
11824         s = line;
11825         if ((y = cmcfm()) < 0)          /* Confirm */
11826           return(y);
11827 #ifdef CK_APC
11828         if ((apcactive == APC_LOCAL) ||
11829             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
11830           return(success = 0);
11831 #endif /* CK_APC */
11832         if (cmresult.nresult != 0) {
11833             printf("?Only a single file may be transmitted\n");
11834             return(-9);
11835         }
11836 #ifdef PIPESEND
11837         if (xpipe) {
11838             s = brstrip(s);
11839             if (!*s) {
11840                 printf("?Sorry, a command to send from is required\n");
11841                 return(-9);
11842             }
11843             pipesend = 1;
11844         }
11845 #endif /* PIPESEND */
11846
11847         if (scan && (filepeek
11848 #ifndef NOXFER
11849                      || patterns
11850 #endif /* NOXFER */
11851                      )) {               /* If user didn't specify type */
11852             int k, x;                         /* scan the file to see */
11853             x = -1;
11854             k = scanfile(s,&x,nscanfile);
11855             if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
11856         }
11857         if (!xfrxla) xxlate = 0;
11858         success = transmit(s,
11859                            (char) (xxnowait ? '\0' : (char)xmitp),
11860                            xxlate,
11861                            xbinary,
11862                            xxecho
11863                            );
11864         return(success);
11865     }
11866 #endif /* NOXMIT */
11867
11868 #ifndef NOFRILLS
11869     if (cx == XXTYP  || cx == XXCAT || cx == XXMORE ||
11870         cx == XXHEAD || cx == XXTAIL) {
11871         int paging = 0, havename = 0, head = 0, width = 0;
11872         int height = 0, count = 0;
11873         char pfxbuf[64], * prefix = NULL;
11874         char outfile[CKMAXPATH+1];
11875         struct FDB sf, sw;
11876         char * pat = NULL;
11877         int incs = 0, outcs = 0, cset = -1, number = 0;
11878 #ifdef UNICODE
11879         char * tocs = "";
11880         extern int fileorder;
11881 #ifdef OS2
11882 #ifdef NT
11883         char guibuf[128], * gui_title = NULL;
11884         int  gui = 0;
11885 #endif /* NT */
11886 #ifndef NOCSETS
11887         extern int tcsr, tcsl;
11888 #endif /* NOCSETS */
11889 #endif /* OS2 */
11890 #endif /* UNICODE */
11891
11892         outfile[0] = NUL;
11893
11894         if (cx == XXMORE)
11895           paging = 1;
11896         else if (cx == XXCAT)
11897           paging = 0;
11898         else
11899           paging = (typ_page < 0) ? xaskmore : typ_page;
11900         if (paging < 0)
11901           paging = saveask;
11902
11903         if (cx == XXHEAD) {
11904             head = 10;
11905             cx = XXTYP;
11906         } else if (cx == XXTAIL) {
11907             head = -10;
11908             cx = XXTYP;
11909         }
11910
11911 #ifdef IKSD
11912         if (inserver && !ENABLED(en_typ)) {
11913             printf("?Sorry, TYPE command disabled\n");
11914             return(-9);
11915         }
11916 #endif /* IKSD */
11917
11918         cmfdbi(&sw,                     /* 2nd FDB - optional /PAGE switch */
11919                _CMKEY,                  /* fcode */
11920                "Filename or switch",    /* hlpmsg */
11921                "",                      /* default */
11922                "",                      /* addtl string data */
11923                ntypetab,                /* addtl numeric data 1: tbl size */
11924                4,                       /* addtl numeric data 2: 4 = cmswi */
11925                xxstring,                /* Processing function */
11926                typetab,                 /* Keyword table */
11927                &sf                      /* Pointer to next FDB */
11928                );
11929         cmfdbi(&sf,                     /* 1st FDB - file to type */
11930                _CMIFI,                  /* fcode */
11931                "",                      /* hlpmsg */
11932                "",                      /* default */
11933                "",                      /* addtl string data */
11934                0,                       /* addtl numeric data 1 */
11935                0,                       /* addtl numeric data 2 */
11936                xxstring,
11937                NULL,
11938                NULL
11939                );
11940
11941         while (!havename) {
11942             x = cmfdb(&sw);             /* Parse something */
11943             debug(F101,"type cmfdb","",x);
11944             debug(F101,"type cmresult.fcode","",cmresult.fcode);
11945             debug(F101,"type cmresult.nresult","",cmresult.nresult);
11946             if (x < 0) {                        /* Error */
11947                 if (x == -3) {
11948                     x = -9;
11949                     printf("?Filename required\n");
11950                 }
11951                 return(x);
11952             } else if (cmresult.fcode == _CMKEY) {
11953                 char c; int getval;
11954                 c = cmgbrk();
11955                 getval = (c == ':' || c == '=');
11956                 if (getval && !(cmgkwflgs() & CM_ARG)) {
11957                     printf("?This switch does not take an argument\n");
11958                     return(-9);
11959                 }
11960 #ifdef COMMENT
11961                 if (!getval && (cmgkwflgs() & CM_ARG)) {
11962                     printf("?This switch requires an argument\n");
11963                     /* Not if it has a default! */
11964                     return(-9);
11965                 }
11966 #endif /* COMMENT */
11967                 switch (cmresult.nresult) {
11968 #ifdef CK_TTGWSIZ
11969                   case TYP_PAG:
11970                     paging = 1;
11971                     break;
11972
11973                   case TYP_NOP:
11974                     paging = 0;
11975                     break;
11976 #endif /* CK_TTGWSIZ */
11977
11978                   case TYP_COU:
11979                     paging = 0;
11980                     count = 1;
11981                     break;
11982
11983                   case TYP_HEA:
11984                   case TYP_TAI:
11985                     y = 10;
11986                     if (getval)
11987                       if ((x = cmnum("Number of lines",
11988                                      "10",10,&y,xxstring)) < 0)
11989                         return(x);
11990                     head = (cmresult.nresult == TYP_TAI) ? -y : y;
11991                     break;
11992
11993                   case TYP_WID:
11994                     y = typ_wid > -1 ? typ_wid : cmd_cols;
11995                     if (getval)
11996                       if ((x = cmnum("Column at which to truncate",
11997                                      ckitoa(y),10,&y,xxstring)) < 0)
11998                         return(x);
11999                     width = y;
12000                     break;
12001
12002 #ifdef KUI
12003                   case TYP_HIG:
12004                     if (getval)
12005                       if ((x = cmnum("Height of GUI dialog",
12006                                      ckitoa(y),10,&y,xxstring)) < 0)
12007                         return(x);
12008                     height = y;
12009                     break;
12010 #endif /* KUI */
12011
12012                   case TYP_PAT:
12013                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12014                         printf("?This switch requires an argument\n");
12015                         return(-9);
12016                     }
12017                     if ((x = cmfld("pattern","",&s,xxstring)) < 0)
12018                       return(x);
12019                     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12020                     pat = tmpbuf;
12021                     break;
12022
12023                   case TYP_PFX:
12024                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12025                         printf("?This switch requires an argument\n");
12026                         return(-9);
12027                     }
12028                     if ((x = cmfld("prefix for each line","",&s,xxstring)) < 0)
12029                       return(x);
12030                     if ((int)strlen(s) > 63) {
12031                         printf("?Too long - 63 max\n");
12032                         return(-9);
12033                     }
12034                     ckstrncpy(pfxbuf,s,64);
12035                     prefix = brstrip(pfxbuf);
12036                     number = 0;
12037                     break;
12038
12039 #ifdef KUI
12040                   case TYP_GUI:
12041                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12042                         printf("?This switch requires an argument\n");
12043                         return(-9);
12044                     }
12045                     if ((x = cmfld("Dialog box title","",&s,xxstring)) < 0) {
12046                         if (x != -3)
12047                           return(x);
12048                     } else {
12049                         if ((int)strlen(s) > 127) {
12050                             printf("?Too long - 127 max\n");
12051                             return(-9);
12052                         }
12053                         ckstrncpy(guibuf,s,128);
12054                         gui_title = brstrip(guibuf);
12055                     }
12056                     gui = 1;
12057                     break;
12058 #endif /* KUI */
12059
12060                   case TYP_NUM:         /* /NUMBER */
12061                     number = 1;
12062                     prefix = NULL;
12063                     break;
12064
12065 #ifdef UNICODE
12066                   case TYP_XPA:         /* /TRANSPARENT */
12067                     incs = 0;
12068                     cset = 0;
12069                     outcs = -1;
12070                     break;
12071
12072                   case TYP_XIN:         /* /CHARACTER-SET: */
12073                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12074                         printf("?This switch requires an argument\n");
12075                         return(-9);
12076                     }
12077                     if ((incs = cmkey(fcstab,nfilc,
12078                                       "character-set name","",xxstring)) < 0) {
12079                         if (incs == -3) /* Note: No default */
12080                           incs = -2;
12081                         return(incs);
12082                     }
12083                     cset = incs;
12084                     break;
12085
12086                   case TYP_XUT:         /* /TRANSLATE-TO: */
12087                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12088                         printf("?This switch requires an argument\n");
12089                         return(-9);
12090                     }
12091 #ifdef OS2
12092                     if (!inserver && !k95stdout) {
12093                         tocs = "ucs2";
12094                     } else {
12095 #ifdef CKOUNI
12096                         tocs = rlookup(txrtab,ntxrtab,tcsl);
12097 #else /* CKOUNI */
12098                         extern struct keytab ttcstab[];
12099                         extern int ntxrtab;
12100                         tocs = rlookup(ttcstab,ntermc,tocs);
12101                         if (!tocs)
12102                           tocs = getdcset();
12103 #endif /* CKOUNI */
12104                     }
12105 #else /* OS2 */
12106                     tocs = getdcset();
12107 #endif /* OS2 */
12108                     if ((outcs = cmkey(fcstab,nfilc,
12109                                        "character-set",tocs,xxstring)) < 0)
12110                       return(outcs);
12111                     break;
12112 #endif /* UNICODE */
12113                   case TYP_OUT:
12114                     if ((x = cmofi("File for result lines","",
12115                                    &s,xxstring)) < 0)
12116                       return(x);
12117                     ckstrncpy(outfile,s,CKMAXPATH);
12118                     break;
12119                 }
12120             } else if (cmresult.fcode == _CMIFI)
12121               havename = 1;
12122             else
12123               return(-2);
12124         }
12125         if (havename) {
12126             ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
12127             y = cmresult.nresult;
12128         } else {
12129             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
12130                 if (x == -3) {
12131                     printf("?Name of an existing file required\n");
12132                     return(-9);
12133                 } else return(x);
12134             }
12135             ckstrncpy(line,s,LINBUFSIZ);
12136         }
12137         if (y != 0) {
12138             printf("?A single file please\n");
12139             return(-9);
12140         }
12141 #ifdef KUI
12142         if ( outfile[0] && gui ) {
12143             printf("?/GUI and /OUTPUT are incompatible\n");
12144             return(-9);
12145         }
12146 #endif /* KUI */
12147
12148         if ((y = cmcfm()) < 0)          /* Confirm the command */
12149           return(y);
12150
12151 #ifdef UNICODE
12152         fileorder = -1;
12153         if (cset < 0 && filepeek) {     /* If no charset switches given */
12154             int k, x = -1;
12155             k = scanfile(line,&x,nscanfile); /* Call file analyzer */
12156             debug(F111,"type scanfile",line,k);
12157             debug(F101,"type scanfile flag","",x);
12158             switch(k) {
12159               case FT_UTF8:             /* which can detect UTF-8... */
12160                 cset = 0;
12161                 incs = FC_UTF8;
12162                 break;
12163               case FT_UCS2:             /* and UCS-2... */
12164                 cset = 0;
12165                 incs = FC_UCS2;
12166                 fileorder = x;          /* even if there is no BOM. */
12167                 debug(F101,"type fileorder","",fileorder);
12168                 break;
12169             }
12170         }
12171 #ifdef OS2
12172         if (cset < 0) {                 /* If input charset still not known */
12173 #ifdef CKOUNI
12174             tocs = rlookup(txrtab,ntxrtab,tcsl);
12175 #else /* CKOUNI */
12176             extern struct keytab ttcstab[];
12177             extern int ntxrtab;
12178             tocs = rlookup(ttcstab,ntermc,incs);
12179             if (!tocs)
12180               tocs = getdcset();
12181 #endif /* CKOUNI */
12182             incs = lookup(fcstab,tocs,nfilc,&x);
12183         }
12184 #endif /* OS2 */
12185
12186         if (outcs == 0 && incs != 0) {  /* Supply default target charset */
12187             int x = 0;                  /* if switch not given. */
12188             tocs = getdcset();
12189             outcs = lookup(fcstab,tocs,nfilc,&x);
12190         }
12191 #else  /* !UNICODE */
12192         if (cset < 0) incs = outcs = 0;
12193 #endif /* UNICODE */
12194
12195         if (outfile[0] && paging)       /* This combination makes no sense */
12196           paging = 0;                   /* so turn off paging */
12197
12198 #ifdef KUI
12199         /* No paging when dialog is used */
12200         if ( gui && paging )
12201           paging = 0;
12202
12203         if ( !gui && height ) {
12204             printf("?The /HEIGHT switch is not supported without /GUI\n");
12205             return(-9);
12206         }
12207 #endif /* KUI */
12208
12209         if (count) paging = -1;
12210         debug(F111,"type",line,paging);
12211 #ifdef KUI
12212         if ( gui ) {
12213             s = (char *)1;    /* ok, its an ugly hack */
12214             if (gui_text_popup_create(gui_title ?
12215                                       gui_title : line, height,width) < 0) {
12216                 printf("?/GUI not supported on this system\n");
12217                 gui = 0;
12218                 return(-9);
12219             }
12220             width = 0;
12221         } else
12222 #endif /* KUI */
12223           s = outfile;
12224         success =
12225           dotype(line,paging,0,head,pat,width,prefix,incs,outcs,s,number);
12226         return(success);
12227     }
12228 #endif /* NOFRILLS */
12229
12230 #ifndef NOCSETS
12231     if (cx == XXXLA) {                  /* TRANSLATE file's charset */
12232         _PROTOTYP (int doxlate, ( void ) );
12233         return(doxlate());
12234     }
12235 #endif /* NOCSETS */
12236
12237     if (cx == XXVER) {                  /* VERSION */
12238         int n = 0;
12239         extern char * ck_patch, * ck_s_test;
12240 #ifdef COMMENT
12241         extern int hmtopline;
12242 #endif /* COMMENT */
12243         if ((y = cmcfm()) < 0)
12244           return(y);
12245
12246         printf("\n%s, for%s\n Numeric: %ld",versio,ckxsys,vernum);
12247         printf("\n\n");
12248         printf("Authors:\n");
12249         printf(" Frank da Cruz, Columbia University\n");
12250         printf(" Jeffrey Eric Altman, Secure Endpoints, Inc. %s\n",
12251                "<jaltman@secure-endpoints.com>"
12252                );
12253         printf(" Contributions from many others.\n");
12254         n = 7;
12255         if (*ck_s_test) {
12256             printf("\nTHIS IS A TEST VERSION, NOT FOR PRODUCTION USE.\n");
12257             n += 2;
12258         }
12259         if (*ck_patch) {
12260             printf(" Patches: %s\n", ck_patch);
12261             n++;
12262         }
12263         printf(" Type COPYRIGHT for copyright and license.\n\n");
12264 #ifdef OS2
12265         shoreg();
12266 #else
12267 #ifdef COMMENT
12268         hmtopline = n+1;
12269         hmsga(copyright);
12270         hmtopline = 0;
12271 #endif /* COMMENT */
12272 #endif /* OS2 */
12273         return(success = 1);
12274     }
12275
12276     if (cx == XXCPR) {                  /* COPYRIGHT or LICENSE */
12277         if ((y = cmcfm()) < 0)
12278           return(y);
12279 #ifdef OS2
12280         if (inserver) {                 /* Free WIKSD */
12281             extern char * wiksdcpr[];
12282             hmsga(wiksdcpr);
12283         } else
12284 #endif /* OS2 */
12285           hmsga(copyright);
12286         return(success = 1);
12287     }
12288
12289 #ifndef MAC                             /* Only for multiuser systems */
12290 #ifndef OS2
12291 #ifndef NOFRILLS
12292     if (cx == XXWHO) {                  /* WHO */
12293         char *wc;
12294 #ifdef IKSD
12295         if (inserver && !ENABLED(en_who)) {
12296             printf("?Sorry, WHO command disabled\n");
12297             return(-9);
12298         }
12299 #endif /* IKSD */
12300 #ifdef datageneral
12301         if ((z = cmcfm()) < 0) return(z);
12302         if (nopush) {
12303             printf("?Sorry, who not allowed\n");
12304             return(success = 0);
12305         }
12306         xsystem(WHOCMD);
12307 #else
12308         if ((y = cmtxt("user name","",&s,xxstring)) < 0) return(y);
12309         if (nopush) {
12310             printf("?Sorry, WHO command disabled\n");
12311             return(success = 0);
12312         }
12313         if (!(wc = getenv("CK_WHO"))) wc = WHOCMD;
12314         if (wc)
12315           if ((int) strlen(wc) > 0) {
12316               ckmakmsg(line,LINBUFSIZ,wc," ",s,NULL);
12317               xsystem(line);
12318           }
12319 #endif /* datageneral */
12320         return(success = 1);
12321     }
12322 #endif /* NOFRILLS */
12323 #endif /* OS2 */
12324 #endif /* MAC */
12325
12326 #ifndef NOFRILLS
12327     if (cx == XXWRI || cx == XXWRL || cx == XXWRBL) { /* WRITE */
12328         int x,y;                        /* On stack in case of \fexec() */
12329         if ((x = cmkey(writab,nwri,"to file or log","",xxstring)) < 0) {
12330             if (x == -3) printf("?Write to what?\n");
12331             return(x);
12332         }
12333         if ((y = cmtxt("text","",&s,xxstring)) < 0) return(y);
12334         s = brstrip(s);
12335         switch (x) {
12336           case LOGD: y = ZDFILE; break;
12337           case LOGP: y = ZPFILE; break;
12338 #ifndef NOLOCAL
12339           case LOGS: y = ZSFILE; break;
12340 #endif /* NOLOCAL */
12341           case LOGT: y = ZTFILE; break;
12342 #ifndef NOSPL
12343           case LOGW: y = ZWFILE; break;
12344 #endif /* NOSPL */
12345           case LOGX:                    /* SCREEN (stdout) */
12346           case LOGE:                    /* ERROR  (stderr) */
12347             if (x == LOGE) {
12348                 debug(F110,
12349                       (cx == XXWRL) ? "WRITELN ERROR" : "WRITE ERROR", s,0);
12350                 fprintf(stderr,"%s%s",s,(cx == XXWRL) ? "\n" : "");
12351             } else {
12352                 debug(F110,
12353                       (cx == XXWRL) ? "WRITELN SCREEN" : "WRITE SCREEN", s,0);
12354                 printf("%s%s",s,(cx == XXWRL) ? "\n" : "");
12355             }
12356             return(success = 1);
12357           default: return(-2);
12358         }
12359         if (chkfn(y) > 0) {
12360             x = (cx == XXWRI) ? zsout(y,s) : zsoutl(y,s);
12361             if (x < 0) printf("?Write error\n");
12362         } else {
12363             x = -1;
12364             printf("?File or log not open\n");
12365         }
12366         return(success = (x == 0) ? 1 : 0);
12367     }
12368 #endif /* NOFRILLS */
12369
12370 #ifndef NOXFER
12371     if (cx == XXASC || cx == XXBIN) {
12372         if ((x = cmcfm()) < 0) return(x);
12373 #ifdef NEWFTP
12374         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
12375           return(success = doftptyp((cx == XXASC) ? 0 : 1));
12376 #endif /* NEWFTP */
12377         binary = (cx == XXASC) ? XYFT_T : XYFT_B;
12378         return(success = 1);
12379     }
12380 #endif /* NOXFER */
12381
12382     if (cx == XXCLS) {
12383         if ((x = cmcfm()) < 0) return(x);
12384         y = ck_cls();
12385         return(success = (y > -1) ? 1 : 0);
12386     }
12387
12388 #ifdef CK_MKDIR
12389     if (cx == XXMKDIR || cx == XXLMKD) {
12390         char *p;
12391 #ifdef LOCUS
12392         if (!locus && cx != XXLMKD) {
12393 #ifdef NOXFER
12394             return(-2);
12395 #else
12396             return(dormt(XZMKD));
12397 #endif /* NOXFER */
12398         }
12399 #endif /* LOCUS */
12400 #ifdef IKSD
12401         if (inserver && !ENABLED(en_mkd)) {
12402             printf("?Sorry, directory creation is disabled\n");
12403             return(-9);
12404         }
12405 #endif /* IKSD */
12406         if ((x = cmfld("Name for new directory","",&s,xxstring)) < 0) {
12407             if (x != -3) {
12408                 return(x);
12409             } else {
12410                 printf("?Directory name required\n");
12411                 return(-9);
12412             }
12413         }
12414         ckstrncpy(line,s,LINBUFSIZ);
12415         s = line;
12416         if ((x = cmcfm()) < 0) return(x);
12417         s = brstrip(s);
12418         bgchk();                        /* Set msgflg */
12419         x = ckmkdir(0,s,&p,msgflg,0);
12420 #ifdef COMMENT
12421         if (msgflg && x == 0)
12422           printf("?Directory already exists\n");
12423 #endif /* COMMENT */
12424         return(success = (x < 0) ? 0 : 1);
12425     }
12426     if (cx == XXRMDIR || cx == XXLRMD) { /* RMDIR */
12427         char *p;
12428 #ifdef LOCUS
12429         if (!locus && cx != XXLRMD) {
12430 #ifdef NOXFER
12431             return(-2);
12432 #else
12433             return(dormt(XZRMD));
12434 #endif /* NOXFER */
12435         }
12436 #endif /* LOCUS */
12437 #ifdef IKSD
12438         if (inserver && !ENABLED(en_rmd)) {
12439             printf("?Sorry, directory removal is disabled\n");
12440             return(-9);
12441         }
12442 #endif /* IKSD */
12443         if ((x = cmdir("Name of directory to be removed","",&s,xxstring)) < 0)
12444           return(x);
12445         ckstrncpy(line,s,LINBUFSIZ);
12446         s = line;
12447         if ((x = cmcfm()) < 0) return(x);
12448         s = brstrip(s);
12449         x = ckmkdir(1,s,&p,msgflg,0);
12450         return(success = (x < 0) ? 0 : 1);
12451     }
12452 #endif /* CK_MKDIR */
12453
12454 #ifdef TNCODE
12455     if (cx == XXTELOP)
12456       return(dotelopt());
12457 #endif /* TNCODE */
12458
12459 #ifndef NOPUSH
12460     if (cx == XXNPSH) {
12461         if ((z = cmcfm()) < 0) return(z);
12462         nopush = 1;
12463 #ifndef NOSERVER
12464         en_hos = 0;
12465 #endif /* NOSERVER */
12466 #ifdef PIPESEND
12467         usepipes = 0;
12468 #endif /* PIPESEND */
12469         return(success = 1);
12470     }
12471 #endif /* NOPUSH */
12472
12473 #ifdef OS2
12474     if (cx == XXNSCR) {
12475         if ((z = cmcfm()) < 0) return(z);
12476         tt_scroll = 0;
12477         return(success = 1);
12478     }
12479 #endif /* OS2 */
12480
12481 #ifndef NOSPL
12482     if (cx == XXLOCAL)                  /* LOCAL variable declarations */
12483       return(success = dolocal());
12484 #endif /* NOSPL */
12485
12486     if (cx == XXKERMI) {                /* The KERMIT command */
12487         char * list[65];
12488         extern char **xargv;
12489         extern int xargc;
12490         int i;
12491         if ((y = cmtxt("kermit command-line arguments, -h for help",
12492                        "",&s,xxstring)) < 0)
12493           return(y);
12494         ckstrncpy(line,"kermit ",LINBUFSIZ);
12495         ckstrncat(line,s,LINBUFSIZ-8);
12496         xwords(line,64,list,0);
12497         for (i = 1; i < 64; i++) {
12498             if (!list[i])
12499               break;
12500         }
12501         i--;
12502         xargc = i;
12503         xargv = list;
12504         xargv++;
12505         sstate = cmdlin();
12506         if (sstate) {
12507             extern int justone;
12508             debug(F000,"KERMIT sstate","",sstate);
12509             justone = 1;                /* Force return to command mode */
12510             proto();                    /* after protocol */
12511             return(success);
12512         } else {
12513             debug(F101,"KERMIT sstate","",sstate);
12514             return(success = 1);        /* Not exactly right, but... */
12515         }
12516     }
12517     if (cx == XXDATE) {                 /* DATE command */
12518         extern char cmdatebuf[], * cmdatemsg;
12519
12520 #ifndef COMMENT
12521         char * dp;
12522         if ((y = cmtxt("date and/or time, or carriage return for current",
12523                        "",&s,xxstring)) < 0)
12524           return(y);
12525         s = brstrip(s);
12526         dp = cmcvtdate(s,1);
12527         if (!dp) {
12528             printf("?%s\n",cmdatemsg ? cmdatemsg : "Date conversion error");
12529             success = 0;
12530         } else {
12531             printf("%s\n",dp);
12532             success = 1;
12533         }
12534 #else
12535         /* This works fine but messes up my "dates" torture-test script */
12536
12537         if ((x = cmdate("Date and/or time, or carriage return for current",
12538                         "",&s,0,xxstring)) < 0) {
12539             return(x);
12540         } else {
12541             printf("%s\n",cmdatebuf);
12542             success = 1;
12543         }
12544 #endif /* COMMENT */
12545         return(success);
12546     }
12547 #ifndef NOPUSH
12548 #ifndef NOFRILLS
12549     if (cx == XXEDIT)
12550       return(doedit());
12551 #endif /* NOFRILLS */
12552 #endif /* NOPUSH */
12553
12554 #ifdef BROWSER                          /* Defined only ifndef NOPUSH */
12555     if (cx == XXBROWS)
12556       return(dobrowse());
12557 #endif /* BROWSER */
12558
12559 #ifdef CK_TAPI
12560     if (cx == XXTAPI) {                 /* Microsoft TAPI */
12561         return (success = dotapi());
12562     }
12563 #endif /* CK_TAPI */
12564
12565 #ifndef NOXFER
12566     if (cx == XXWHERE) {
12567         extern char * rfspec, * sfspec, * srfspec, * rrfspec;
12568         if ((x = cmcfm()) < 0) return(x);
12569         printf("\nFile most recently...\n\n");
12570         printf("  Sent:       %s\n",   sfspec ? sfspec : "(none)");
12571         if (sfspec && srfspec) {
12572             printf("  Stored as:  %s\n",   srfspec);
12573             printf("\n");
12574         }
12575         printf("  Received:   %s\n",   rrfspec ? rrfspec : "(none)");
12576         if (rfspec && rrfspec)
12577         printf("  Stored as:  %s\n",   rfspec);
12578         printf(
12579 "\nIf the full path is not shown, then the file is probably in your current\n"
12580                );
12581         printf(
12582 "directory or your download directory (if any - SHOW FILE to find out).\n\n"
12583                );
12584         return(success = 1);
12585     }
12586 #endif /* NOXFER */
12587
12588 #ifdef CK_RECALL
12589     if (cx == XXREDO)
12590       return(doredo());
12591 #endif /* CK_RECALL */
12592
12593 #ifdef CKROOT
12594     if (cx == XXCHRT)                   /* Change Kermit's root directory */
12595       return(dochroot());
12596 #endif /* CKROOT */
12597
12598 #ifdef CK_KERBEROS
12599     if (cx == XXAUTH) {                 /* KERBEROS */
12600         x = cp_auth();                  /* Parse it */
12601 #ifdef IKSD
12602         if (inserver) {
12603             printf("?Command disabled in IKSD.\r\n");
12604             return(success = 0);
12605         }
12606 #endif /* IKSD */
12607         if (x < 0)                      /* Pass parse errors back */
12608           return(x);
12609         return(success = doauth(cx));
12610     }
12611 #endif /* CK_KERBEROS */
12612
12613 #ifndef NOLOCAL
12614     if (cx == XXTERM) {
12615         return(settrmtyp());
12616     }
12617 #endif /* NOLOCAL */
12618
12619     if (cx == XXSTATUS) {
12620         if ((x = cmcfm()) < 0) return(x);
12621         printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
12622         return(0);                      /* Don't change it */
12623     }
12624
12625     if (cx == XXFAIL) {
12626         if ((x = cmcfm()) < 0) return(x);
12627         return(success = 0);
12628     }
12629
12630     if (cx == XXSUCC) {
12631         if ((x = cmcfm()) < 0) return(x);
12632         return(success = 1);
12633     }
12634
12635     if (cx == XXNLCL) {
12636         extern int nolocal;
12637         if ((x = cmcfm()) < 0) return(x);
12638         nolocal = 1;
12639         return(success = 1);
12640     }
12641
12642 #ifndef NOXFER
12643     if (cx == XXRASG)                   /* Shortcuts for REMOTE commands */
12644       return(dormt(XZASG));
12645     if (cx == XXRCWD)
12646       return(dormt(XZCWD));
12647     if (cx == XXRCPY)
12648       return(dormt(XZCPY));
12649     if (cx == XXRDEL)
12650       return(dormt(XZDEL));
12651     if (cx == XXRDIR)
12652       return(dormt(XZDIR));
12653     if (cx == XXRXIT)
12654       return(dormt(XZXIT));
12655     if (cx == XXRHLP)
12656       return(dormt(XZHLP));
12657     if (cx == XXRHOS)
12658       return(dormt(XZHOS));
12659     if (cx == XXRKER)
12660       return(dormt(XZKER));
12661     if (cx == XXRPWD)
12662       return(dormt(XZPWD));
12663     if (cx == XXRQUE)
12664       return(dormt(XZQUE));
12665     if (cx == XXRREN)
12666       return(dormt(XZREN));
12667     if (cx == XXRMKD)
12668       return(dormt(XZMKD));
12669     if (cx == XXRRMD)
12670       return(dormt(XZRMD));
12671     if (cx == XXRSET)
12672       return(dormt(XZSET));
12673     if (cx == XXRSPA)
12674       return(dormt(XZSPA));
12675     if (cx == XXRTYP)
12676       return(dormt(XZTYP));
12677     if (cx == XXRWHO)
12678       return(dormt(XZWHO));
12679     if (cx == XXRCDUP)
12680       return(dormt(XZCDU));
12681     if (cx == XXRPRI)
12682       return(dormt(XZPRI));
12683 #endif /* NOXFER */
12684
12685     if (cx == XXRESET) {                /* RESET */
12686         if ((x = cmcfm()) < 0)
12687           return(x);
12688         doclean(0);                     /* Close all files */
12689         return(success = 1);
12690     }
12691
12692 #ifndef NOXFER
12693 #ifndef NOCSETS
12694     if (cx == XXASSOC)                  /* ASSOCIATE */
12695       return(doassoc());
12696 #endif /* NOCSETS */
12697 #endif /* NOXFER */
12698
12699 #ifndef NOSPL
12700     if (cx == XXSHIFT) {                /* SHIFT */
12701         if ((y = cmnum("Number of arguments to shift","1",10,&x,xxstring)) < 0)
12702           return(y);
12703         if ((z = cmcfm()) < 0)
12704           return(z);
12705         return(success = doshift(x));
12706     }
12707 #endif /* NOSPL */
12708
12709 #ifndef NOHELP
12710     if (cx == XXMAN)
12711       return(domanual());
12712 #endif /* NOHELP */
12713
12714 #ifndef NOSPL
12715     if (cx == XXSORT)                   /* SORT an array */
12716       return(dosort());
12717 #endif /* NOSPL */
12718
12719     if (cx == XXPURGE) {
12720 #ifdef IKSD
12721         if (inserver && (!ENABLED(en_del)
12722 #ifdef CK_LOGIN
12723                           || isguest
12724 #endif /* CK_LOGIN */
12725                          )) {
12726             printf("?Sorry, DELETE is disabled\n");
12727             return(-9);
12728         }
12729 #endif /* IKSD */
12730 #ifdef CK_APC
12731         if ((apcactive == APC_LOCAL) ||
12732             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
12733           return(success = 0);
12734 #endif /* CK_APC */
12735 #ifdef CKPURGE
12736         return(dopurge());
12737 #else
12738 #ifdef VMS
12739         if ((x = cmtxt("optional switches followed by filespec",
12740                        "",&s,xxstring)) < 0)
12741           return(x);
12742         if (nopush) {
12743             printf("?Sorry, DCL access is disabled\n");
12744             return(-9);
12745         }
12746         ckstrncpy(line,s,LINBUFSIZ);
12747         s = line;
12748         x = mlook(mactab,"purge",nmac);
12749         return(success = dodo(x,s,cmdstk[cmdlvl].ccflgs));
12750 #else
12751         return(-2);
12752 #endif /* VMS */
12753 #endif /* CKPURGE */
12754     }
12755
12756 #ifndef NOSPL
12757     if (cx == XXFAST) {
12758         if ((x = cmcfm()) < 0) return(x);
12759         x = mlook(mactab,"fast",nmac);
12760         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12761     }
12762     if (cx == XXCAU) {
12763         if ((x = cmcfm()) < 0) return(x);
12764         x = mlook(mactab,"cautious",nmac);
12765         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12766     }
12767     if (cx == XXROB) {
12768         if ((x = cmcfm()) < 0) return(x);
12769         x = mlook(mactab,"robust",nmac);
12770         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12771     }
12772 #endif /* NOSPL */
12773
12774     if (cx == XXSCRN) {                 /* SCREEN */
12775         int row, col;
12776         if ((x = cmkey(scntab, nscntab,"screen action","", xxstring)) < 0)
12777           return(x);
12778         switch (x) {                    /* MOVE-TO (cursor position) */
12779           case SCN_MOV:
12780             if ((y = cmnum("Row (1-based)","",10,&z,xxstring)) < 0)
12781               return(y);
12782             row = z;
12783             y = cmnum("Column (1-based)","1",10,&z,xxstring);
12784             if (y < 0)
12785               return(y);
12786             col = z;
12787             if ((y = cmcfm()) < 0)
12788               return(y);
12789             if (row < 0 || col < 0) {
12790                 printf("?Row and Column must be 1 or greater\n");
12791                 return(-9);
12792             }
12793             if (cmd_rows > 0 && row > cmd_rows)
12794               row = cmd_rows;
12795             if (cmd_cols > 0 && col > cmd_cols)
12796               col = cmd_cols;
12797             y = ck_curpos(row,col);
12798             return(success = (y > -1) ? 1 : 0);
12799
12800           case SCN_CLR:                 /* CLEAR */
12801             if ((y = cmcfm()) < 0)
12802               return(y);
12803             debug(F100,"screen calling ck_cls()","",0);
12804             y = ck_cls();
12805             return(success = (y > -1) ? 1 : 0);
12806
12807           case SCN_CLE:                 /* CLEOL */
12808             if ((y = cmcfm()) < 0)
12809               return(y);
12810             y = ck_cleol();
12811             return(success = (y > -1) ? 1 : 0);
12812         }
12813     }
12814
12815 #ifndef NOHTTP
12816 #ifdef TCPSOCKET
12817     if (cx == XXHTTP)
12818       return(dohttp());
12819 #endif /* TCPSOCKET */
12820 #endif /* NOHTTP */
12821
12822 #ifndef NOSPL
12823     if (cx == XXARRAY) {                /* ARRAY */
12824 #ifndef NOSHOW
12825         extern int showarray();
12826 #endif /* NOSHOW */
12827         if ((x = cmkey(arraytab, narraytab,"Array operation","",xxstring)) < 0)
12828           return(x);
12829         switch (x) {
12830           case ARR_DCL:
12831             return(dodcl(XXDCL));
12832           case ARR_SRT:
12833             return(dosort());
12834 #ifndef NOSHOW
12835           case ARR_SHO:
12836             return(showarray());
12837 #endif /* NOSHOW */
12838           case ARR_CPY:
12839             return(copyarray());
12840           case ARR_SET:
12841           case ARR_CLR:
12842             return(clrarray(x));
12843           case ARR_DST:
12844             return(unarray());
12845           case ARR_RSZ:
12846             return(rszarray());
12847           case ARR_EQU:
12848             return(linkarray());
12849
12850           default:
12851             printf("?Sorry, not implemented yet - \"%s\"\n",cmdbuf);
12852             return(-9);
12853         }
12854     }
12855     if (cx == XXTRACE)
12856       return(dotrace());
12857 #endif /* NOSPL */
12858
12859 #ifdef CK_PERMS
12860 #ifdef UNIX
12861     if (cx == XXCHMOD)
12862       return(douchmod());               /* Do Unix chmod */
12863 #endif /* UNIX */
12864 #endif /* CK_PERMS */
12865
12866     if (cx == XXPROMP)
12867       return(doprompt());
12868
12869     if (cx == XXGREP)
12870       return(dogrep());
12871
12872     if (cx == XXDEBUG) {                /* DEBUG */
12873 #ifndef DEBUG
12874         int dummy = 0;
12875         return(seton(&dummy));
12876 #else
12877         return(seton(&deblog));
12878 #endif /* DEBUG */
12879     }
12880
12881 #ifdef CKLEARN
12882     if (cx == XXLEARN) {                /* LEARN */
12883         struct FDB of, sw, cm;
12884         int closing = 0, off = 0, on = 0, confirmed = 0;
12885         char c;
12886
12887         cmfdbi(&sw,                     /* 2nd FDB - optional /PAGE switch */
12888                _CMKEY,                  /* fcode */
12889                "Script file name, or switch", /* hlpmsg */
12890                "",                      /* default */
12891                "",                      /* addtl string data */
12892                3,                       /* addtl numeric data 1: tbl size */
12893                4,                       /* addtl numeric data 2: 4 = cmswi */
12894                xxstring,                /* Processing function */
12895                learnswi,                /* Keyword table */
12896                &of                      /* Pointer to next FDB */
12897                );
12898         cmfdbi(&of,_CMOFI,"","","",0,0,xxstring,NULL,&cm);
12899         cmfdbi(&cm,_CMCFM,"","","",0,0,NULL,NULL,NULL);
12900         line[0] = NUL;
12901
12902         while (!confirmed) {
12903             x = cmfdb(&sw);             /* Parse something */
12904             if (x < 0)
12905               return(x);
12906             switch (cmresult.fcode) {   /* What was it? */
12907               case _CMOFI:              /* Output file name */
12908                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
12909                 break;
12910               case _CMKEY:              /* Switch */
12911                 c = cmgbrk();
12912                 if ((c == ':' || c == '=') && !(cmgkwflgs() & CM_ARG)) {
12913                     printf("?This switch does not take an argument\n");
12914                     return(-9);
12915                 }
12916                 switch (cmresult.nresult) {
12917                   case 2:               /* /CLOSE */
12918                     closing = 1;        /* Fall thru on purpose */
12919                   case 0:               /* /OFF */
12920                     off = 1;
12921                     on = 0;
12922                     break;
12923                   case 1:               /* /ON */
12924                     on = 1;
12925                     off = 0;
12926                     break;
12927                 }
12928                 break;
12929               case _CMCFM:              /* Confirmation */
12930                 confirmed++;
12931                 break;
12932             }
12933         }
12934         if (closing) {
12935             if (learnfp) {
12936                 fclose(learnfp);
12937                 learnfp = NULL;
12938             }
12939             makestr(&learnfile,NULL);
12940         }
12941         if (line[0]) {
12942             if (!on && !off)
12943               on = 1;
12944             if (learnfp) {
12945                 fclose(learnfp);
12946                 learnfp = NULL;
12947             }
12948             makestr(&learnfile,line);
12949             if (learnfile) {
12950                 char * modes = "w";
12951                 learnfp = fopen(learnfile,modes);
12952                 if (!learnfp) {
12953                     debug(F110,"LEARN file open error",learnfile,0);
12954                     perror(learnfile);
12955                     return(-9);
12956                 } else {
12957 #ifdef ZFNQFP
12958                     if (zfnqfp(learnfile,TMPBUFSIZ,tmpbuf))
12959                       makestr(&learnfile,tmpbuf);
12960 #endif /* ZFNQFP */
12961                     debug(F110,"LEARN file open ok",learnfile,0);
12962                     if (!quiet) {
12963                         printf("Recording to %s...\n\n",learnfile);
12964                         printf(
12965 " WARNING: If you type your password during script recording, it will appear\n\
12966  in the file.  Be sure to edit it or take other appropriate precautions.\n\n"
12967                                );
12968                     }
12969                     fputs(  "; Scriptfile: ",learnfp);
12970                     fputs(learnfile,learnfp);
12971                     fputs("\n; Directory:  ",learnfp);
12972                     fputs(zgtdir(),learnfp);
12973                     fputs("\n; Recorded:   ",learnfp);
12974                     fputs(ckdate(),learnfp);
12975                     fputs("\n",learnfp);
12976                 }
12977             }
12978         }
12979         if (on) {
12980             learning = 1;
12981         } else if (off) {
12982             learning = 0;
12983         }
12984         debug(F101,"LEARN learning","",learning);
12985         return(success = 1);
12986     }
12987 #endif /* CKLEARN */
12988
12989 #ifdef NEWFTP
12990     if (cx == XXUSER || cx == XXACCT) {
12991         if (!ftpisopen()) {
12992             printf("?FTP connection is not open\n");
12993             return(-9);
12994         }
12995         return(success = (cx == XXUSER) ? doftpusr() : doftpacct());
12996     }
12997     if (cx == XXSITE || cx == XXPASV) {
12998         if (!ftpisopen()) {
12999             printf("?FTP connection is not open\n");
13000             return(-9);
13001         }
13002         return(success = (cx == XXSITE) ? doftpsite() : dosetftppsv());
13003     }
13004 #endif /* NEWFTP */
13005
13006     if (cx == XXORIE) {                 /* ORIENTATION */
13007         extern char * myname;
13008         int i, y, n = 0;
13009         char * s, *p, vbuf[32];
13010         char * vars[16];       char * legend[16];
13011
13012         if ((y = cmcfm()) < 0)
13013           return(y);
13014
13015         printf("\nProgram name:\n  %s\n\n",myname);
13016         n += 4;
13017
13018 #ifdef NT
13019         vars[0] = "home";      legend[0] = "Your home directory";
13020         vars[1] = "directory"; legend[1] = "K95's current directory";
13021         vars[2] = "exedir";    legend[2] = "K95 Program directory";
13022         vars[3] = "inidir";    legend[3] = "K95 Initialization file directory";
13023         vars[4] = "startup";   legend[4] = "Current directory when started";
13024         
13025         vars[5] = "common";
13026         legend[5] = "K95 data for all users and K95SITE.INI file";
13027         
13028         vars[6] = "personal";  legend[6] = "Your personal data directory tree";
13029         vars[7] = "desktop";   legend[7] = "Your deskop directory tree";
13030         
13031         vars[8] = "appdata";
13032         legend[8] = "Your personal K95 data tree and K95CUSTOM.INI file";
13033         
13034         vars[9] = "download";  legend[9] = "Your K95 download directory";
13035         vars[10] = "tmpdir";   legend[10] = "Your TEMP directory";
13036         vars[11] = NULL;       legend[11] = NULL;
13037
13038         for (i = 0; i < 16 && vars[i]; i++) {
13039             printf("%s:\n",legend[i]);
13040             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13041             ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
13042             printf("  Variable:   %s\n",vbuf);
13043             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13044             y = TMPBUFSIZ;
13045             s = tmpbuf;
13046             zzstring(vbuf,&s,&y);
13047             line[0] = NUL;
13048             ckGetLongPathName(tmpbuf,line,LINBUFSIZ);
13049             printf("  Long name:  %s\n",line);
13050             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13051             line[0] = NUL;
13052             GetShortPathName(tmpbuf,line,LINBUFSIZ);
13053             printf("  Short name: %s\n",line);
13054             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13055             printf("\n");
13056             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13057         }
13058 #else  /* NT */
13059
13060         vars[0] = "home";      legend[0] = "Your home directory";
13061         vars[1] = "directory"; legend[1] = "Kermit's current directory";
13062         vars[2] = "exedir";    legend[2] = "Kermit's program directory";
13063         vars[3] = "inidir";    legend[3] = "Initialization file directory";
13064         vars[4] = "startup";   legend[4] = "Current directory when started";
13065         vars[5] = "download";  legend[5] = "Kermit download directory";
13066         vars[6] = NULL;        legend[6] = NULL;
13067
13068         for (i = 0; i < 16 && vars[i]; i++) {
13069             printf("%s:\n",legend[i]);
13070             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13071             ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
13072             printf("  Variable: %s\n",vbuf);
13073             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13074             y = TMPBUFSIZ;
13075             s = tmpbuf;
13076             zzstring(vbuf,&s,&y);
13077             printf("  Value:    %s\n",tmpbuf);
13078             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13079             printf("\n");
13080             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13081         }
13082 #endif /* NT */
13083         return(success = 1);
13084     }
13085
13086 #ifdef NT
13087     if (cx == XXDIALER) {
13088         StartDialer();
13089         return(success = 1);
13090     }
13091 #endif /* NT */
13092
13093     if (cx == XXCONT) {                 /* CONTINUE */
13094         if ((x = cmcfm()) < 0)
13095           return(x);
13096         if (!xcmdsrc) {                 /* At prompt: continue script */
13097             if (cmdlvl > 0)
13098               popclvl();                /* Pop command level */
13099             return(success = 1);        /* always succeeds */
13100 #ifndef NOSPL
13101         } else {                        /* In script: whatever... */
13102             x = mlook(mactab,"continue",nmac);
13103             /* Don't set success */
13104             return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
13105 #endif /* NOSPL */
13106         }
13107     }
13108     if (cx == XXNOTAV) {                /* Command in table not available */
13109         ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
13110         if ((x = cmtxt("Rest of command","",&s,NULL)) < 0)
13111           return(x);
13112         printf("Sorry, \"%s\" not configured in this version of Kermit.\n",
13113                tmpbuf
13114                );
13115         return(success = 0);
13116     }
13117     return(-2);                         /* None of the above */
13118
13119 } /* end of docmd() */
13120
13121 #endif /* NOICP */