fixed "interupted" spelling errors
[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             if ((y = cmtxt("Braced list of commands","",&s,xxstring)) < 0)
7987               return(y);
7988             k = ckstrncpy(line+k,s,LINBUFSIZ-k);
7989             debug(F111,"XXMACRO B",line,k);
7990         }
7991         x = strlen(line);
7992         if ((line[0] == '{' && line[x-1] != '}') || line[0] == '}')
7993           return(-2);
7994         if (line[0] != '{' && line[x-1] != '}') {
7995             /* Unknown command.  If ON_UNKNOWN_COMMAND macro is defined, */
7996             /* parse args and then execute it, but only if it is not */
7997             /* already active. */
7998             int k = -1;
7999             if (!unkmacro) {
8000                 k = mxlook(mactab,"on_unknown_command",nmac);
8001             }
8002             if (k > -1) {
8003                 ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
8004                 z = maclvl;             /* Save the current maclvl */
8005                 if ((y = cmtxt("text","",&s,xxstring)) < 0)
8006                   return(y);
8007                 ckstrncat(tmpbuf," ",TMPBUFSIZ);
8008                 ckstrncat(tmpbuf,s,TMPBUFSIZ);
8009                 unkmacro = 1;
8010                 debug(F110,"ON_UNKNOWN_COMMAND",s,0);
8011                 dodo(k,tmpbuf,cmdstk[cmdlvl].ccflgs); /* Run the macro */
8012                 while (maclvl > z) {
8013                     sstate = (CHAR) parser(1);
8014                     if (sstate) proto();
8015                 }
8016                 debug(F101,"UNKMAC loop exit maclvl","",maclvl);
8017                 unkmacro = 0;
8018                 return(success);
8019             }
8020             if (x > 0)
8021               printf("?Not a command or macro name: \"%s\"\n",line);
8022             else
8023               printf("?Not a command or macro name.\n");
8024             return(-9);
8025         }
8026         s = brstrip(line);
8027         sprintf(mnamebuf," ..tmp:%03d",cmdlvl); /* safe (16) */
8028         x = addmac(mnamebuf,s);
8029         return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs) < 1 ? (success = 0) : 1);
8030     }
8031
8032     if (cx == XXLBL) {                  /* LABEL */
8033         if ((x = cmfld("label","",&s,xxstring)) < 0) {
8034             if (x == -3) {
8035 #ifdef COMMENT
8036                 printf("?LABEL: Label name required: \"%s\"\n", cmdbuf);
8037                 return(-9);
8038 #else
8039                 s = "";
8040 #endif /* COMMENT */
8041             } else return(x);
8042
8043         }
8044         debug(F111,"LABEL",s,x);
8045         if ((x = cmcfm()) < 0) return(x);
8046         return(0);
8047     }
8048
8049     if (cx == XXEVAL || cx == XX_EVAL) /* _EVALUATE,  EVALUATE  */
8050       return(doeval(cx));
8051
8052 #ifndef NOSEXP
8053     if (cx == XXSEXP) {                 /* Lisp-like S-Expression */
8054         struct stringarray * q;
8055         char /* *p, *r, */ *tmp, *m;
8056         int i, k, n, quote = 0, contd = 0, size = 0, len = 0;
8057         extern int sexprc, sexppv;
8058
8059         tmp = tmpbuf;                   /* Buffer to collect SEXP */
8060         tmpbuf[0] = NUL;                /* Clear it */
8061         size = TMPBUFSIZ;               /* Capacity of buffer */
8062         sexprc = -1;                    /* Assume bad input */
8063         n = 0;                          /* Paren balance counter */
8064
8065         while (1) {                     /* Allow SEXP on multiple lines */
8066             m = contd ?
8067               "Continuation of S-Expression" :
8068                 "S-Expression (\"help sexp\" for details)";
8069             x = cmtxt(m,"",&s,xxstring);
8070             if (x < 0)
8071               return(x);
8072             if (!*s)                    /* Needed for (=) and (:) */
8073               s = atmbuf;
8074             k = ckmakmsg(tmp, size, contd ? " " : "(", s, NULL, NULL);
8075             if (k < 1) {
8076                 printf("?SEXP too long - %d max\n",TMPBUFSIZ);
8077                 return(-9);
8078             }
8079             debug(F111,contd ? "sexp contd" : "sexp",s,k);
8080
8081             for (i = len; i < len+k; i++) { /* Check balance  */
8082                 if (!quote && tmpbuf[i] == CMDQ) {
8083                     quote = 1;
8084                     continue;
8085                 }
8086                 if (quote) {
8087                     quote = 0;
8088                     continue;
8089                 }
8090                 if (tmpbuf[i] == '(')
8091                   n++;
8092                 else if (tmpbuf[i] == ')')
8093                   n--;
8094             }
8095             if (n == 0) {               /* Break when balanced */
8096                 break;
8097             }
8098             if (n < 0) {                /* Too many right parens */
8099                 printf("?Unbalanced S-Expression: \"%s\"\n",tmpbuf);
8100                 return(-9);
8101             }
8102             contd++;                    /* Need more right parens */
8103             cmini(ckxech);              /* so keep parsing */
8104             tmp += k;                   /* adjust buffer pointer */
8105             size -= k;                  /* and capacity */
8106             len += k;                   /* and length so far */
8107         }
8108         s = tmpbuf;
8109         makestr(&lastsexp,s);
8110         q = cksplit(1,SEXPMAX,s,NULL,NULL,8,0,0); /* Precheck for > 1 SEXP */
8111         debug(F101,"sexp split","",q->a_size);
8112
8113         if (q->a_size == 1) {           /* We should get exactly one back */
8114             char * result, * dosexp();
8115             sexprc = 0;                 /* Reset out-of-band return code */
8116             result = dosexp(s);         /* Get result */
8117             debug(F111,"sexp result",result,sexprc);
8118             if (sexprc == 0) {          /* Success */
8119                 /* Echo the result if desired */
8120                 if ((!xcmdsrc && sexpecho != SET_OFF) || sexpecho == SET_ON)
8121                   printf(" %s\n",result ? result : "");
8122                 makestr(&sexpval,result);
8123                 success = sexppv > -1 ? sexppv : 1;
8124                 return(success);
8125             }
8126         }
8127         if (sexprc < 0)
8128           printf("?Invalid S-Expression: \"%s\"\n",lastsexp);
8129         return(-9);
8130     }
8131 #endif /* NOSEXP */
8132
8133 #endif /* NOSPL */
8134
8135     if (cx == XXECH || cx == XXXECH || cx == XXVOID
8136 #ifndef NOSPL
8137         || cx == XXAPC
8138 #endif /* NOSPL */
8139         ) {                             /* ECHO or APC */
8140         if ((x = cmtxt((cx == XXECH || cx == XXXECH) ?
8141                        "Text to be echoed" :
8142                        ((cx == XXVOID) ? "Text" :
8143                         "Application Program Command text"),
8144                        "",
8145                        &s,
8146                        xxstring
8147                        )
8148              ) < 0)
8149           return(x);
8150         if (!s) s = "";
8151 #ifdef COMMENT
8152 /* This is to preserver the pre-8.0 behavior but it's too confusing */
8153         x = strlen(s);
8154         x = (x > 1) ? ((s[0] == '"' && s[x-1] == '"') ? 1 : 0) : 0;
8155 #endif /* COMMENT */
8156         s = brstrip(s);                 /* Strip braces and doublequotes */
8157         if (cx == XXECH) {              /* ECHO */
8158 #ifndef NOSPL
8159             if (!fndiags || fnsuccess) {
8160 #endif /* NOSPL */
8161 #ifdef COMMENT
8162                 /* The "if (x)" business preserves previous behavior */
8163                 /* by putting back the doublequotes if they were included. */
8164                 if (x)
8165                   printf("\"%s\"\n",s);
8166                 else
8167 #endif /* COMMENT */
8168                   printf("%s\n",s);
8169 #ifndef NOSPL
8170             }
8171 #endif /* NOSPL */
8172         } else if (cx == XXXECH) {      /* XECHO */
8173             if (x)
8174               printf("\"%s\"",s);
8175             else
8176               printf("%s",s);
8177 #ifdef UNIX
8178             fflush(stdout);
8179 #endif /* UNIX */
8180         } else if (cx == XXAPC) {       /* APC */
8181 #ifdef CK_APC
8182             if (apcactive == APC_LOCAL ||
8183                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
8184               return(success = 0);
8185 #endif /* CK_APC */
8186             if (!local) {
8187                 printf("%c_%s%c\\",ESC,s,ESC);
8188 #ifdef UNIX
8189                 fflush(stdout);
8190 #endif /* UNIX */
8191
8192             } else {                    /* Local mode - have connection */
8193 #ifndef NOSPL
8194                 if (ckmakxmsg(tmpbuf,   /* Form APC string in buffer */
8195                               TMPBUFSIZ,
8196                               ckctoa((char)ESC),
8197                               ckctoa('_'),
8198                               s,
8199                               ckctoa((char)ESC),
8200                               ckctoa('\\'),
8201                               NULL,NULL,NULL,NULL,NULL,NULL,NULL
8202                               ) > 0)
8203                   return(success = dooutput(tmpbuf, XXOUT));
8204                 printf("?Too long\n");
8205                 return(-9);
8206 #else
8207                 printf("%c_%s%c\\",ESC,s,ESC);
8208 #endif /* NOSPL */
8209             }
8210         }
8211         return(success = 1);
8212     }
8213
8214 #ifndef NOSPL
8215 /* Copy macro args from/to two levels up, used internally by _floop et al. */
8216     if (cx == XXGTA || cx == XXPTA) {   /* _GETARGS, _PUTARGS */
8217         int x;
8218         debug(F101,"docmd XXGTA","",XXGTA);
8219         debug(F101,"docmd cx","",cx);
8220         debug(F101,"docmd XXGTA maclvl","",maclvl);
8221         x = dogta(cx);
8222         debug(F101,"docmd dogta returns","",x);
8223         debug(F101,"docmd dogta maclvl","",maclvl);
8224         return(x);
8225     }
8226 #endif /* NOSPL */
8227
8228 #ifndef NOSPL
8229 #ifdef CKCHANNELIO
8230     if (cx == XXFILE)
8231       return(dofile(cx));
8232     else if (cx == XXF_RE || cx == XXF_WR || cx == XXF_OP ||
8233              cx == XXF_CL || cx == XXF_SE || cx == XXF_RW ||
8234              cx == XXF_FL || cx == XXF_LI || cx == XXF_ST || cx == XXF_CO)
8235       return(dofile(cx));
8236 #endif /* CKCHANNELIO */
8237
8238 /* ASK, ASKQ, READ */
8239     if (cx == XXASK  || cx == XXASKQ || cx == XXREA ||
8240         cx == XXRDBL || cx == XXGETC || cx == XXGETK) {
8241         return(doask(cx));
8242     }
8243 #endif /* NOSPL */
8244
8245 #ifndef NOFRILLS
8246     if (cx == XXBUG) {                  /* BUG */
8247         if ((x = cmcfm()) < 0) return(x);
8248         return(dobug());
8249     }
8250 #endif /* NOFRILLS */
8251
8252 #ifndef NOXFER
8253     if (cx == XXBYE) {                  /* BYE */
8254         extern int ftp_cmdlin;
8255         if ((x = cmcfm()) < 0) return(x);
8256
8257 #ifdef NEWFTP
8258         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen())) {
8259             extern int stayflg, ftp_fai;
8260             success = ftpbye();
8261             if (ftp_cmdlin && !stayflg && !local)
8262               doexit(ftp_fai ? BAD_EXIT : GOOD_EXIT,-1);
8263             else
8264               return(success);
8265         }
8266 #endif /* NEWFTP */
8267
8268         if (!local) {
8269             printf("?No connection - use EXIT to quit.\n");
8270             return(-9);
8271         }
8272
8273 #ifdef CK_XYZ
8274         if (protocol != PROTO_K) {
8275             printf("?Sorry, BYE only works with Kermit protocol\n");
8276             return(-9);
8277         }
8278 #endif /* CK_XYZ */
8279
8280 #ifdef IKS_OPTION
8281         if (
8282 #ifdef CK_XYZ
8283             protocol == PROTO_K &&
8284 #endif /* CK_XYZ */
8285             !iks_wait(KERMIT_REQ_START,1)) {
8286             printf(
8287              "?A Kermit Server is not available to process this command\n");
8288             return(-9);                 /* Correct the return code */
8289         }
8290 #endif /* IKS_OPTION */
8291
8292         bye_active = 1;
8293         sstate = setgen('L',"","","");
8294         if (local) ttflui();            /* If local, flush tty input buffer */
8295         return(0);
8296     }
8297 #endif /* NOXFER */
8298
8299     if (cx == XXBEEP) {                 /* BEEP */
8300         int x;
8301 #ifdef OS2
8302         int y;
8303         if ((y = cmkey(beeptab, nbeeptab, "which kind of beep", "information",
8304                        xxstring)) < 0 )
8305           return (y);
8306         if ((x = cmcfm()) < 0) return(x);
8307         bleep((short)y);                /* y is one of the BP_ values */
8308 #else  /* OS2 */
8309         if ((x = cmcfm()) < 0) return(x);
8310 #ifndef NOSPL
8311         bleep(BP_NOTE);
8312 #else
8313         putchar('\07');
8314 #endif /* NOSPL */
8315 #endif /* OS2 */
8316         return(0);
8317     }
8318
8319 #ifndef NOFRILLS
8320     if (cx == XXCLE)                    /* CLEAR */
8321       return(success = doclear());
8322 #endif /* NOFRILLS */
8323
8324     if (cx == XXCOM) {                  /* COMMENT */
8325         if ((x = cmtxt("Text of comment line","",&s,NULL)) < 0)
8326           return(x);
8327         /* Don't change SUCCESS flag for this one */
8328         return(0);
8329     }
8330
8331 #ifndef NOLOCAL
8332     if (cx == XXCON || cx == XXCQ)      /* CONNECT or CONNECT /QUIETLY */
8333       return(doxconn(cx));
8334 #endif /* NOLOCAL */
8335
8336 #ifndef NOFRILLS
8337 #ifdef ZCOPY
8338     if (cx == XXCPY) {                  /* COPY a file */
8339 #ifdef IKSD
8340         if (inserver && !ENABLED(en_cpy)) {
8341             printf("?Sorry, COPY is disabled\n");
8342             return(-9);
8343         }
8344 #endif /* IKSD */
8345 #ifdef CK_APC
8346         if (apcactive == APC_LOCAL ||
8347             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
8348             )
8349           return(success = 0);
8350 #endif /* CK_APC */
8351         return(docopy());
8352     }
8353 #endif /* ZCOPY */
8354 #ifdef NT
8355     if ( cx == XXLINK ) {
8356 #ifdef IKSD
8357         if (inserver && !ENABLED(en_cpy)) {
8358             printf("?Sorry, LINK (COPY) is disabled\n");
8359             return(-9);
8360         }
8361 #endif /* IKSD */
8362 #ifdef CK_APC
8363         if (apcactive == APC_LOCAL ||
8364             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
8365             )
8366           return(success = 0);
8367 #endif /* CK_APC */
8368         return(dolink());
8369     }
8370 #endif /* NT */
8371 #endif /* NOFRILLS */
8372
8373     /* CD and friends */
8374     if (cx == XXCWD  || cx == XXCDUP || cx == XXBACK ||
8375         cx == XXLCWD || cx == XXLCDU || cx == XXKCD) {
8376 #ifdef LOCUS
8377         if (!locus) {
8378             if (cx == XXCWD) {
8379 #ifdef NOXFER
8380                 return(-2);
8381 #else
8382                 return(dormt(XZCWD));
8383 #endif /* NOXFER */
8384             } else if (cx == XXCDUP) {
8385 #ifdef NOXFER
8386                 return(-2);
8387 #else
8388                 return(dormt(XZCDU));
8389 #endif /* NOXFER */
8390             }
8391         }
8392 #endif /* LOCUS */
8393 #ifdef IKSD
8394         if (inserver && !ENABLED(en_cwd)) {
8395             printf("?Sorry, changing directories is disabled\n");
8396             return(-9);
8397         }
8398 #endif /* IKSD */
8399         return(success = docd(cx));
8400     }
8401
8402     if (cx == XXCHK)                    /* CHECK */
8403       return(success = dochk());
8404
8405     if (cx == XXCLO) {                  /* CLOSE */
8406         x = cmkey(clstab,ncls,"\"CONNECTION\", or log or file to close",
8407                   "connection",xxstring);
8408         if (x == -3) {
8409             printf("?You must say which file or log\n");
8410             return(-9);
8411         }
8412         if (x < 0) return(x);
8413         if ((y = cmcfm()) < 0) return(y);
8414 #ifndef NOLOCAL
8415         if (x == 9999) {                /* CLOSE CONNECTION */
8416             x = clsconnx(0);
8417             switch (x) {
8418               case 0:
8419                 if (msgflg) printf("?Connection was not open\n");
8420               case -1:
8421                 return(0);
8422               case 1:
8423                 whyclosed = WC_CLOS;
8424                 return(1);
8425             }
8426             return(0);
8427         }
8428 #endif /* NOLOCAL */
8429         y = doclslog(x);
8430         success = (y == 1);
8431         return(success);
8432     }
8433
8434 #ifndef NOSPL
8435     if (cx == XXDCL || cx == XXUNDCL) { /* DECLARE an array */
8436         return(dodcl(cx));
8437     }
8438 #endif /* NOSPL */
8439
8440 #ifndef NODIAL
8441     if (cx == XXRED  || cx == XXDIAL || cx == XXPDIA ||
8442         cx == XXANSW || cx == XXLOOK) { /* DIAL, REDIAL etc */
8443 #ifdef VMS
8444         extern int batch;
8445 #else
8446 #ifdef UNIXOROSK
8447         extern int backgrd;
8448 #endif /* UNIXOROSK */
8449 #endif /* VMS */
8450         x = dodial(cx);
8451         debug(F101,"dodial returns","",x);
8452         if ((cx == XXDIAL || cx == XXRED || cx == XXANSW) &&
8453             (x > 0) &&                  /* If DIAL or REDIAL succeeded */
8454             (dialsta != DIA_PART) &&    /* and it wasn't partial */
8455             (dialcon > 0)) {
8456             if ((dialcon == 1 ||        /* And DIAL CONNECT is ON, */
8457                 ((dialcon == 2) &&      /* or DIAL CONNECT is AUTO */
8458                  !xcmdsrc               /* and we're at top level... */
8459 #ifdef VMS
8460                  && !batch              /* Not if running from batch */
8461 #else
8462 #ifdef UNIXOROSK
8463                  && !backgrd            /* Not if running in background */
8464 #endif /* UNIXOROSK */
8465 #endif /* VMS */
8466                  ))) /* Or AUTO */
8467               x = doconect(dialcq,      /* Then also CONNECT */
8468                            cmdlvl == 0 ? 1 : 0
8469                            );
8470             if (ttchk() < 0)
8471               dologend();
8472         }
8473         return(success = x);
8474     }
8475 #endif /* NODIAL */
8476
8477 #ifndef NOPUSH
8478 #ifdef CK_REXX
8479     if (cx == XXREXX) {                 /* REXX */
8480         extern int nopush;
8481         if ( nopush )
8482           return(success=0);
8483         return(dorexx());
8484     }
8485 #endif /* CK_REXX */
8486 #endif /* NOPUSH */
8487
8488 #ifndef NOFRILLS
8489     if (cx == XXDEL || cx == XXLDEL) {  /* DELETE */
8490 #ifdef LOCUS
8491         if (!locus && cx != XXLDEL) {
8492 #ifdef NOXFER
8493             return(-2);
8494 #else
8495             return(dormt(XZDEL));
8496 #endif /* NOXFER */
8497         }
8498 #endif /* LOCUS */
8499 #ifdef IKSD
8500         if (inserver && (!ENABLED(en_del)
8501 #ifdef CK_LOGIN
8502                          || isguest
8503 #endif /* CK_LOGIN */
8504                          )) {
8505             printf("?Sorry, DELETE is disabled\n");
8506             return(-9);
8507         }
8508 #endif /* IKSD */
8509 #ifdef CK_APC
8510         if ((apcactive == APC_LOCAL) ||
8511             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8512           return(success = 0);
8513 #endif /* CK_APC */
8514         return(dodel());
8515     }
8516 #endif /* NOFRILLS */
8517
8518     if (cx == XXDIR || cx == XXLS || cx == XXLDIR) { /* DIRECTORY or LS */
8519 #ifdef LOCUS
8520         if (!locus && cx != XXLDIR) {
8521 #ifdef NOXFER
8522             return(-2);
8523 #else
8524             return(dormt(XZDIR));
8525 #endif /* NOXFER */
8526         }
8527 #endif /* LOCUS */
8528 #ifdef IKSD
8529         if (inserver && !ENABLED(en_dir)) {
8530             printf("?Sorry, DIRECTORY is disabled\n");
8531             return(-9);
8532         }
8533 #endif /* IKSD */
8534         return(dodir(cx));
8535     }
8536
8537 #ifndef NOSPL
8538     if (cx == XXELS)                    /* ELSE */
8539       return(doelse());
8540 #endif /* NOSPL */
8541
8542 #ifndef NOSERVER
8543 #ifndef NOFRILLS
8544     if (cx == XXENA || cx == XXDIS) {   /* ENABLE, DISABLE */
8545         s = (cx == XXENA) ?
8546           "Server function to enable" :
8547             "Server function to disable";
8548
8549         if ((x = cmkey(enatab,nena,s,"",xxstring)) < 0) {
8550             if (x == -3) {
8551                 printf("?Name of server function required\n");
8552                 return(-9);
8553             } else return(x);
8554         }
8555         if ((y = cmkey(kmstab,3,"mode","both",xxstring)) < 0) {
8556             if (y == -3) {
8557                 printf("?Please specify remote, local, or both\n");
8558                 return(-9);
8559             } else return(y);
8560         }
8561         if (cx == XXDIS)                /* Disabling, not enabling */
8562           y = 3 - y;
8563         if ((z = cmcfm()) < 0) return(z);
8564 #ifdef CK_APC
8565         if ((apcactive == APC_LOCAL) ||
8566             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8567           return(success = 0);
8568 #endif /* CK_APC */
8569 #ifdef IKSD
8570         /* This may seem like it duplicates the work in doenable()  */
8571         /* but this code returns failure whereas doenable() returns */
8572         /* success.                                                 */
8573         if (inserver &&
8574 #ifdef IKSDCONF
8575             iksdcf &&
8576 #endif /* IKSDCONF */
8577             (x == EN_HOS || x == EN_PRI || x == EN_MAI || x == EN_WHO ||
8578               isguest))
8579             return(success = 0);
8580 #endif /* IKSD */
8581         return(doenable(y,x));
8582     }
8583 #endif /* NOFRILLS */
8584 #endif /* NOSERVER */
8585
8586 #ifndef NOSPL
8587     if (cx == XXRET) {                  /* RETURN */
8588         if ((x = cmtxt("Optional return value","",&s,NULL)) < 0)
8589           return(x);
8590         s = brstrip(s);                 /* Strip braces */
8591         if (cmdlvl == 0)                /* At top level, nothing happens... */
8592           return(success = 1);
8593         switch (cmdstk[cmdlvl].src) {   /* Action depends on command source */
8594           case CMD_TF:                  /* Command file */
8595             popclvl();                  /* Pop command level */
8596             return(success = 1);        /* always succeeds */
8597           case CMD_MD:                  /* Macro */
8598           case CMD_KB:                  /* Prompt */
8599             return(doreturn(s));        /* Trailing text is return value. */
8600           default:                      /* Shouldn't happen */
8601             return(-2);
8602         }
8603     }
8604 #endif /* NOSPL */
8605
8606 #ifndef NOSPL
8607     if (cx == XXOPE)                    /* OPEN */
8608       return(doopen());
8609 #endif /* NOSPL */
8610
8611 #ifndef NOSPL
8612     if (cx == XXOUT || cx == XXLNOUT) { /* OUTPUT or LINEOUT */
8613         if ((x = cmtxt("Text to be output","",&s,NULL)) < 0)
8614           return(x);
8615 #ifdef CK_APC
8616         if ((apcactive == APC_LOCAL) ||
8617             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
8618           return(success = 0);
8619 #endif /* CK_APC */
8620         debug(F110,"OUTPUT 1",s,0);
8621         s = brstrip(s);                 /* Strip enclosing braces, */
8622         debug(F110,"OUTPUT 2",s,0);
8623 /*
8624   I don't think I could ever fully explain this in a million years...
8625   We have read the user's string without calling the variable-expander
8626   function.  Now, before we call it, we have to double backslashes that
8627   appear before \N, \B, \L, and \ itself, so the expander function will
8628   reduce them back to single backslashes, so when we call dooutput()...
8629   But it's more complicated than that.
8630 */
8631         if (cmdgquo()) {                /* Only if COMMAND QUOTING ON ... */
8632             for (x = 0, y = 0; s[x]; x++, y++) {
8633                 if (s[x] == CMDQ) {
8634                     char c = s[x+1];
8635                     if (c == 'n' || c == 'N' ||
8636                         c == 'b' || c == 'B' ||
8637                         c == 'l' || c == 'L' ||
8638                         c == CMDQ)
8639                       line[y++] = CMDQ;
8640                 }
8641                 line[y] = s[x];
8642             }
8643             line[y++] = '\0';           /* Now expand variables, etc. */
8644             debug(F110,"OUTPUT 3",line,0);
8645             s = line+y+1;
8646             x = LINBUFSIZ - (int) strlen(line) - 1;
8647             debug(F101,"OUTPUT size","",x);
8648             if (zzstring(line,&s,&x) < 0)
8649               return(success = 0);
8650             s = line+y+1;
8651             debug(F110,"OUTPUT 4",s,0);
8652         }
8653         success = dooutput(s,cx);
8654         return(success);
8655     }
8656 #endif /* NOSPL */
8657
8658 #ifdef ANYX25
8659 #ifndef IBMX25
8660     if (cx == XXPAD) {                  /* PAD commands */
8661         x = cmkey(padtab,npadc,"PAD command","",xxstring);
8662         if (x == -3) {
8663             printf("?You must specify a PAD command to execute\n");
8664             return(-9);
8665         }
8666         if (x < 0) return(x);
8667
8668         switch (x) {
8669           case XYPADL:
8670             if (x25stat() < 0)
8671               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8672             else {
8673                 x25clear();
8674                 initpad();
8675             }
8676             break;
8677           case XYPADS:
8678             if (x25stat() < 0)
8679               printf("Not connected\r\n");
8680             else {
8681                 extern int linkid, lcn;
8682                 conol("Connected thru ");
8683                 conol(ttname);
8684                 printf(", Link id %d, Logical channel number %d\r\n",
8685                        linkid,lcn);
8686             }
8687             break;
8688           case XYPADR:
8689             if (x25stat() < 0)
8690               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8691             else
8692               x25reset(0,0);
8693             break;
8694           case XYPADI:
8695             if (x25stat() < 0)
8696               printf("Sorry, you must 'set network' & 'set host' first\r\n");
8697             else
8698               x25intr(0);
8699         }
8700         return(0);
8701     }
8702 #endif /* IBMX25 */
8703 #endif /* ANYX25 */
8704
8705 #ifndef NOSPL
8706     if (cx == XXPAU || cx == XXWAI || cx == XXMSL) /* PAUSE, WAIT, etc */
8707       return(dopaus(cx));
8708 #endif /* NOSPL */
8709
8710 #ifndef NOFRILLS
8711     if (cx == XXPRI) {
8712 #ifdef IKSD
8713 #ifdef CK_LOGIN
8714         if (inserver && (isguest || !ENABLED(en_pri))) {
8715             printf("?Sorry, printing is disabled\n");
8716             return(-9);
8717         }
8718 #endif /* CK_LOGIN */
8719 #endif /* IKSD */
8720         if ((x = cmifi("File to print","",&s,&y,xxstring)) < 0) {
8721             if (x == -3) {
8722                 printf("?A file specification is required\n");
8723                 return(-9);
8724             } else return(x);
8725         }
8726         if (y != 0) {
8727             printf("?Wildcards not allowed\n");
8728             return(-9);
8729         }
8730         ckstrncpy(line,s,LINBUFSIZ);
8731         s = "";
8732 #ifndef NT
8733         if ((x = cmtxt("Local print command options, or carriage return","",&s,
8734                        xxstring)) < 0)
8735           return(x);
8736 #endif /* NT */
8737         if ((x = cmcfm()) < 0)
8738           return(x);
8739         return(success = (zprint(s,line) == 0) ? 1 : 0);
8740     }
8741 #endif /* NOFRILLS */
8742
8743 #ifdef TCPSOCKET
8744 #ifndef NOPUSH
8745     if (cx == XXPNG)                    /* PING an IP host */
8746       return(doping());
8747 #endif /* NOPUSH */
8748
8749 #ifndef NOFTP
8750     if (cx == XXFTP)                    /* FTP */
8751 #ifdef SYSFTP
8752 #ifndef NOPUSH
8753       return(doftp());                  /* Just runs system's ftp program */
8754 #else
8755       return(-2);
8756 #endif /* NOPUSH */
8757 #else
8758     return(doxftp());
8759 #endif /* SYSFTP */
8760 #endif /* NOFTP */
8761 #endif /* TCPSOCKET */
8762
8763     if (cx == XXPWD || cx == XXLPWD) {  /* PWD */
8764 #ifdef OS2
8765         char *pwp;
8766 #endif /* OS2 */
8767         if ((x = cmcfm()) < 0)
8768           return(x);
8769 #ifdef LOCUS
8770         if (!locus && cx != XXLPWD) {
8771 #ifdef NOXFER
8772             return(-2);
8773 #else
8774             return(dormt(XZPWD));
8775 #endif /* NOXFER */
8776         }
8777 #endif /* LOCUS */
8778
8779 #ifndef MAC
8780 #ifndef OS2
8781 #ifdef UNIX
8782         printf("%s\n",zgtdir());
8783 #else
8784         xsystem(PWDCMD);
8785 #endif /* UNIX */
8786         return(success = 1);            /* Blind faith */
8787 #else  /* OS2 */
8788         if (pwp = zgtdir()) {
8789             if (*pwp) {
8790 #ifdef NT
8791                 line[0] = NUL;
8792                 ckGetLongPathName(pwp,line,LINBUFSIZ);
8793                 line[LINBUFSIZ-1] = NUL;
8794                 tmpbuf[0] = NUL;
8795                 GetShortPathName(pwp,tmpbuf,TMPBUFSIZ);
8796                 tmpbuf[TMPBUFSIZ-1] = NUL;
8797                 pwp = line;
8798                 if (!strcmp(line,tmpbuf)) {
8799 #endif /* NT */
8800                     printf("%s\n",pwp);
8801 #ifdef NT
8802                 } else {
8803                     printf("  Long name:  %s\n",line);
8804                     printf("  Short name: %s\n",tmpbuf);
8805                 }            
8806 #endif /* NT */
8807             }
8808             return(success = ((int)strlen(pwp) > 0));
8809         } else return(success = 0);
8810 #endif /* OS2 */
8811 #else  /* MAC */
8812         if (pwp = zgtdir()) {
8813             printf("%s\n",pwp);
8814             return(success = ((int)strlen(pwp) > 0));
8815         } else return(success = 0);
8816 #endif /* MAC */
8817     }
8818
8819     if (cx == XXQUI || cx == XXEXI) {   /* EXIT, QUIT */
8820         extern int quitting;
8821
8822         if ((y = cmnum("exit status code",ckitoa(xitsta),10,&x,xxstring)) < 0)
8823           return(y);
8824         if ((y = cmtxt("Optional EXIT message","",&s,xxstring)) < 0)
8825           return(y);
8826         s = brstrip(s);
8827         ckstrncpy(line,s,LINBUFSIZ);
8828
8829         if (!hupok(0))                  /* Check if connection still open */
8830           return(success = 0);
8831
8832         if (line[0])                    /* Print EXIT message if given */
8833           printf("%s\n",(char *)line);
8834
8835         quitting = 1;                   /* Flag that we are quitting. */
8836
8837 #ifdef VMS
8838         doexit(GOOD_EXIT,x);
8839 #else
8840 #ifdef OSK
8841 /* Returning any codes here makes the OS-9 shell print an error message. */
8842         doexit(GOOD_EXIT,-1);
8843 #else
8844 #ifdef datageneral
8845         doexit(GOOD_EXIT,x);
8846 #else
8847         doexit(x,-1);
8848 #endif /* datageneral */
8849 #endif /* OSK */
8850 #endif /* VMS */
8851     }
8852
8853 #ifndef NOXFER
8854 #ifndef NOFRILLS
8855     if (cx == XXERR) {                  /* ERROR */
8856 #ifdef CK_XYZ
8857         if (protocol != PROTO_K) {
8858             printf("Sorry, E-PACKET only works with Kermit protocol\n");
8859             return(-9);
8860         }
8861 #endif /* CK_XYZ */
8862         if ((x = cmcfm()) < 0) return(x);
8863         ttflui();
8864         epktflg = 1;
8865         sstate = 'a';
8866         return(0);
8867     }
8868 #endif /* NOFRILLS */
8869
8870     if (cx == XXFIN) {                  /* FINISH */
8871 #ifdef NEWFTP
8872         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
8873           return(ftpbye());
8874 #endif /* NEWFTP */
8875 #ifdef CK_XYZ
8876         if (protocol != PROTO_K) {
8877             printf("Sorry, FINISH only works with Kermit protocol\n");
8878             return(-9);
8879         }
8880 #endif /* CK_XYZ */
8881         if ((x = cmcfm()) < 0) return(x);
8882
8883 #ifdef IKS_OPTION
8884         if (
8885 #ifdef CK_XYZ
8886             protocol == PROTO_K &&
8887 #endif /* CK_XYZ */
8888             !iks_wait(KERMIT_REQ_START,1)) {
8889             printf(
8890               "?A Kermit Server is not available to process this command\n");
8891             return(-9);                 /* Correct the return code */
8892         }
8893 #endif /* IKS_OPTION */
8894
8895         sstate = setgen('F',"","","");
8896         if (local) ttflui();            /* If local, flush tty input buffer */
8897         return(0);
8898     }
8899 #endif /* NOXFER */
8900
8901 #ifndef NOSPL
8902     if (cx == XXFOR)                    /* FOR loop */
8903       return(dofor());
8904 #endif /* NOSPL */
8905
8906 #ifndef NOXFER
8907     /* GET MGET REGET RETRIEVE etc */
8908     if (cx == XXGET || cx == XXMGET || cx == XXREGET || cx == XXRETR) {
8909 #ifdef IKSD
8910         if (inserver && !ENABLED(en_sen)) {
8911             printf("?Sorry, reception of files is disabled\n");
8912             return(-9);
8913         }
8914 #endif /* IKSD */
8915         return(doxget(cx));
8916     }
8917 #endif /* NOXFER */
8918
8919 #ifndef NOSPL
8920 #ifndef NOFRILLS
8921     if (cx == XXGOK) {                  /* GETOK */
8922         return(success = doask(cx));
8923     }
8924 #endif /* NOFRILLS */
8925 #endif /* NOSPL */
8926
8927     if (cx == XXHLP) {                  /* HELP */
8928 #ifdef NOHELP
8929         return(dohlp(XXHLP));
8930 #else
8931         x = cmkey2(cmdtab,ncmd,"\nCommand or topic","help",toktab,xxstring,3);
8932         debug(F101,"HELP command x","",x);
8933         if (x == -5) {
8934             y = chktok(toktab);
8935             debug(F101,"HELP cmkey token","",y);
8936             /* ungword(); */
8937             switch (y) {
8938 #ifndef NOPUSH
8939               case '!': x = XXSHE; break;
8940 #endif /* NOPUSH */
8941               case '#': x = XXCOM; break;
8942               case ';': x = XXCOM; break;
8943 #ifndef NOSPL
8944               case '.': x = XXDEF; break;
8945               case ':': x = XXLBL; break;
8946 #ifndef NOSEXP
8947               case '(': x = XXSEXP; break;
8948 #endif /* NOSEXP */
8949 #endif /* NOSPL */
8950               case '&': x = XXECH; break;
8951               default:
8952                 printf("\n?Invalid - %s\n",cmdbuf);
8953                 x = -2;
8954             }
8955         }
8956         makestr(&hlptok,atmbuf);
8957         debug(F111,"HELP token",hlptok,x);
8958         return(dohlp(x));
8959 #endif /* NOHELP */
8960     }
8961
8962 #ifndef NOHELP
8963     if (cx == XXINT)                    /* INTRO */
8964       return(hmsga(introtxt));
8965     if (cx == XXNEW) {                  /* NEWS */
8966         int x;
8967         extern char * k_info_dir;
8968         x = hmsga(newstxt);
8969         return(x);
8970     }
8971
8972 #ifdef OS2ONLY
8973     if (cx == XXUPD) {                  /* View UPDATE file */
8974         extern char exedir[];
8975         char * pTopic;
8976         char updstr[2048];
8977         if ((x = cmtxt("topic name","",&pTopic,xxstring)) < 0)
8978             return x;
8979 #ifdef COMMENT
8980         sprintf(updstr,
8981                 "start view %s\\docs\\k2.inf+%s\\docs\\using_ck.inf+\
8982 %s\\docs\\dialing.inf+%s\\docs\\modems.inf %s",
8983                 exedir,exedir,exedir,exedir,pTopic
8984                 );
8985 #else
8986         if (ckmakxmsg(updstr,
8987                      2048,
8988                      "start view ",
8989                      exedir,
8990                      "\\docs\\k2.inf+",
8991                      exedir,
8992                      "\\docs\\using_ck.inf+",
8993                      exedir,
8994                      "\\docs\\dialing.inf+",
8995                      exedir,
8996                      "\\docs\\modems.inf ",
8997                      pTopic,
8998                      NULL,
8999                      NULL
9000                      ) > 0)
9001 #endif /* COMMENT */
9002           system(updstr);
9003         return(success = 1);
9004     }
9005 #endif /* OS2ONLY */
9006 #endif /* NOHELP */
9007
9008 #ifndef NOLOCAL
9009     if (cx == XXHAN) {                  /* HANGUP */
9010         if ((x = cmcfm()) < 0) return(x);
9011 #ifdef NEWFTP
9012         if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
9013           return(success = ftpbye());
9014 #endif /* NEWFTP */
9015 #ifndef NODIAL
9016         if ((x = mdmhup()) < 1) {
9017             debug(F101,"HANGUP mdmup","",x);
9018 #endif /* NODIAL */
9019             x = tthang();
9020             debug(F101,"HANGUP tthang","",x);
9021             x = (x > -1);
9022 #ifndef NODIAL
9023         }
9024         dialsta = DIA_UNK;
9025 #endif /* NODIAL */
9026         whyclosed = WC_CLOS;
9027         ttchk();                        /* In case of CLOSE-ON-DISCONNECT */
9028         dologend();
9029 #ifdef OS2
9030         if (x)
9031           DialerSend(OPT_KERMIT_HANGUP, 0);
9032 #endif /* OS2 */
9033         if (x) haveline = 0;
9034         return(success = x);
9035     }
9036 #endif /* NOLOCAL */
9037
9038 #ifndef NOSPL
9039     /* INPUT, REINPUT, and MINPUT */
9040
9041     if (cx == XXINP || cx == XXREI || cx == XXMINP) {
9042         long zz;
9043         extern int ispattern, isjoin;
9044
9045         struct FDB sw, nu, fl;
9046         int fc, havetime = 0;
9047         char * m;
9048
9049         if (cx == XXREI) {
9050             m = "Timeout in seconds (ignored)";
9051         } else {
9052             m = "Seconds to wait for input,\n or time of day hh:mm:ss, \
9053  or switch";
9054         }
9055         innomatch = 0;                  /* Initialize switch value(s) */
9056
9057         cmfdbi(&sw,                     /* First FDB - command switches */
9058                _CMKEY,                  /* fcode */
9059                m,                       /* helpmsg */
9060                ckitoa(indef),           /* default */
9061                "",                      /* addtl string data */
9062                ninputsw,                /* addtl numeric data 1: tbl size */
9063                4,                       /* addtl numeric data 2: 4 = cmswi */
9064                xxstring,                /* Processing function */
9065                inputsw,                 /* Keyword table */
9066                &nu                      /* Pointer to next FDB */
9067                );
9068         cmfdbi(&nu,
9069                _CMNUM,                  /* Number */
9070                m,                       /* Help message */
9071                ckitoa(indef),           /* default */
9072                "",                      /* N/A */
9073                10,                      /* Radix = 10 */
9074                0,                       /* N/A */
9075                xxstring,                /* Processing function */
9076                NULL,                    /* N/A */
9077                &fl                      /* Next */
9078                );
9079         cmfdbi(&fl,                     /* Time of day hh:mm:ss */
9080                _CMFLD,                  /* fcode */
9081                "",                      /* hlpmsg */
9082                "",
9083                "",                      /* addtl string data */
9084                0,                       /* addtl numeric data 1 */
9085                0,                       /* addtl numeric data 2 */
9086                xxstring,
9087                NULL,
9088                NULL
9089                );
9090         fc = (cx == XXREI) ? cmfdb(&nu) : cmfdb(&sw); /* Parse something */
9091
9092         while (!havetime) {
9093             if (fc < 0) {               /* Error */
9094                 if (fc == -3) {
9095                     printf("?Syntax error in INPUT-class command\n");
9096                     return(-9);
9097                 } else
9098                   return(fc);
9099             }
9100             switch (cmresult.fcode) {
9101               case _CMKEY:              /* Switch */
9102                 if (cmresult.nresult == INPSW_NOM) /* /NOMATCH */
9103                   innomatch = 1;
9104                 m = "Seconds to wait for input,\n or time of day hh:mm:ss";
9105                 cmfdbi(&nu,_CMNUM,m,"","",10,0,xxstring,NULL,&fl);
9106                 cmfdbi(&fl,_CMFLD,"","","",0,0,xxstring,NULL,NULL);
9107                 fc = cmfdb(&nu);        /* Parse something */
9108                 continue;
9109
9110               case _CMNUM:              /* Seconds to time out */
9111                 x = cmresult.nresult;
9112 #ifdef CKFLOAT
9113                 if (inscale != 1.0)     /* Scale */
9114                   x *= inscale;         
9115 #endif  /* CKFLOAT */
9116                 havetime++;
9117                 break;
9118
9119               case _CMFLD:
9120                 zz = tod2sec(atmbuf);   /* Convert to secs since midnight */
9121                 if (zz < 0L) {
9122                     printf("?Number, expression, or time of day required\n");
9123                     return(-9);
9124                 } else {
9125                     char now[32];       /* Current time */
9126                     char *p;
9127                     long tnow;
9128                     p = now;
9129                     ztime(&p);
9130                     tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
9131                     if (zz < tnow)      /* User's time before now */
9132                       zz += 86400L;     /* So make it tomorrow */
9133                     zz -= tnow;         /* Seconds from now. */
9134                     if (zz > -1L) {
9135                         x = zz;
9136                         if (zz != (long) x) {
9137                             printf(
9138 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
9139 );
9140                             return(-9);
9141                         }
9142                     }
9143                     havetime++;
9144                 }
9145                 break;
9146               default:          
9147                 printf("?Internal error\n");
9148                 return(-9);
9149             }
9150         }
9151         /* Now parse the search text */
9152
9153 #ifdef CK_MINPUT
9154         for (y = 0; y < MINPMAX; y++) { /* Initialize strings */
9155             mp[y] = 0;                  /* Assume it's not a pattern */
9156             if (ms[y]) {
9157                 free(ms[y]);            /* Free old strings, if any */
9158                 ms[y] = NULL;
9159             }
9160         }
9161         if (cx == XXMINP) {             /* MINPUT */
9162             int i, k = 0, n = 0;
9163             struct stringarray * q;
9164             keepallchars = 1;
9165             while (k < MINPMAX) {
9166                 if ((y = cmfld("String or pattern","",&s,xxstring)) < 0) {
9167                     if (y == -3) {
9168                         if ((y = cmcfm()) < 0)
9169                           return(y);
9170                         break;
9171                     } else {
9172                         return(y);
9173                     }
9174                 }
9175                 debug(F111,"MINPUT field",s,k);
9176                 if (isjoin) {
9177                     if ((q = cksplit(1,0,s," ",(char *)c1chars,3,0,0))) {
9178                         char ** ap = q->a_head;
9179                         n = q->a_size;
9180                         debug(F101,"minput cksplit size","",n);
9181                         for (i = 1; i <= n && k < MINPMAX; i++) {
9182                             if (!ap[i]) /* Add non-empty elements */
9183                               continue;
9184                             if (!*(ap[i]))
9185                               continue;
9186                             makestr(&(ms[k]),ap[i]);
9187                             debug(F111,"MINPUT JOIN",ms[k],k);
9188                             k++;
9189                         }
9190                     }
9191                 } else {
9192                     if (s) if (*s) {
9193                         makestr(&(ms[k]),brstrip(s));
9194                         if (ispattern) mp[k] = 1;
9195                         debug(F111,"MINPUT",ms[k],ispattern);
9196                         k++;
9197                     }
9198                 }
9199             }
9200             keepallchars = 0;
9201         } else {
9202 #endif /* CK_MINPUT */
9203
9204             /* INPUT or REINPUT */
9205
9206             if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
9207               return(y);
9208             mp[0] = ispattern ? 1 : 0;
9209             makestr(&(ms[0]),brstrip(s));
9210             ms[1] = NULL;
9211
9212 #ifdef CK_MINPUT
9213         }
9214 #endif /* CK_MINPUT */
9215
9216 #ifdef COMMENT
9217         printf("/NOMATCH=%d\n",innomatch);
9218         printf("Timeout=%d\n",x);
9219         return(1);
9220 #endif  /* COMMENT */
9221
9222         if (cx == XXINP || cx == XXMINP) { /* Not REINPUT... */
9223             i_active = 1;
9224             /* Go try to input the search string */
9225             success = doinput(x,ms,mp,innomatch);
9226             i_active = 0;
9227         } else {                        /* REINPUT */
9228             success = doreinp(x,ms[0],ispattern);
9229         }
9230         if (intime[cmdlvl] && !success) { /* TIMEOUT-ACTION = QUIT? */
9231             popclvl();                  /* If so, pop command level. */
9232             if (pflag && cmdlvl == 0) {
9233                 if (cx == XXINP)  printf("?INPUT timed out\n");
9234                 if (cx == XXMINP) printf("?MINPUT timed out\n");
9235                 if (cx == XXREI)  printf("?REINPUT failed\n");
9236             }
9237         }
9238         return(success);                /* Return do(re)input's return code */
9239     }
9240
9241 #endif /* NOSPL */
9242
9243     if (cx == XXLOG) {                  /* LOG */
9244         x = cmkey(logtab,nlog,"What to log","",xxstring);
9245         if (x == -3) {
9246             printf("?Type of log required\n");
9247             return(-9);
9248         }
9249         if (x < 0) return(x);
9250         x = dolog(x);
9251         if (x < 0)
9252           return(x);
9253         else
9254           return(success = x);
9255     }
9256
9257     if (cx == XXLOGIN) {                /* (REMOTE) LOGIN */
9258 #ifdef NEWFTP
9259         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9260           return(success = doftpusr());
9261 #endif /* NEWFTP */
9262 #ifdef IKSD
9263         if (inserver) {
9264             printf("?Already logged in\n");
9265             return(-9);
9266         } else
9267 #endif /* IKSD */
9268         {
9269 #ifdef NOXFER
9270             return(-2);
9271 #else
9272             return(dormt(XZLGI));
9273 #endif /* NOXFER */
9274         }
9275     }
9276     if (cx == XXLOGOUT) {               /* (REMOTE) LOGOUT */
9277 #ifdef NEWFTP
9278         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9279           return(success = doftpres());
9280 #endif /* NEWFTP */
9281
9282 #ifdef IKSD
9283         if (inserver) {
9284             if ((x = cmcfm()) < 0)
9285               return(x);
9286             doexit(GOOD_EXIT,xitsta);
9287         } else
9288 #endif /* IKSD */
9289         if (!local || (network && ttchk() < 0)) {
9290             printf("?No connection.\n");
9291             return(-9);
9292         } else {
9293 #ifdef NOXFER
9294             return(-2);
9295 #else
9296             return(dormt(XZLGO));
9297 #endif /* NOXFER */
9298         }
9299     }
9300
9301 #ifndef NOSCRIPT
9302     if (cx == XXLOGI) {                 /* UUCP-style script */
9303         if ((x = cmtxt("expect-send expect-send ...","",&s,xxstring)) < 0)
9304           return(x);
9305 #ifdef CK_APC
9306         if ((apcactive == APC_LOCAL) ||
9307             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9308           return(success = 0);
9309 #endif /* CK_APC */
9310 #ifdef VMS
9311         conres();                       /* For Ctrl-C to work... */
9312 #endif /* VMS */
9313         return(success = dologin(s));   /* Return 1=completed, 0=failed */
9314     }
9315 #endif /* NOSCRIPT */
9316
9317 #ifndef NOXFER
9318 #ifdef PIPESEND
9319     if (cx == XXCREC) {                 /* CRECEIVE */
9320         if (protocol != PROTO_K) {
9321             printf("?Sorry, CRECEIVE works only with Kermit protocol\n");
9322             return(-9);
9323         } else
9324           return(doxget(cx));
9325     }
9326     if (cx == XXCGET) {                 /* CGET */
9327         return(doxget(cx));
9328     }
9329 #endif /* PIPESEND */
9330
9331     if (cx == XXREC)                    /* RECEIVE */
9332       return(doxget(cx));
9333 #endif /* NOXFER */
9334
9335 #ifndef NOXFER
9336     if (cx == XXREM) {                  /* REMOTE */
9337 #ifdef NEWFTP
9338         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9339           return(doftprmt(0,0));
9340 #endif /* NEWFTP */
9341 #ifdef CK_XYZ
9342         if (protocol != PROTO_K) {
9343             printf("Sorry, REMOTE commands only work with Kermit protocol\n");
9344             return(-9);
9345         }
9346 #endif /* CK_XYZ */
9347         x = cmkey(remcmd,nrmt,"Remote Kermit server command","",xxstring);
9348         if (x == -3) {
9349             printf("?You must specify a command for the remote server\n");
9350             return(-9);
9351         }
9352         return(dormt(x));
9353     }
9354 #endif /* NOXFER */
9355
9356 #ifndef NORENAME
9357 #ifndef NOFRILLS
9358     if (cx == XXREN || cx == XXLREN) {  /* RENAME */
9359 #ifdef LOCUS
9360         if (!locus && cx != XXLREN) {
9361 #ifdef NOXFER
9362             return(-2);
9363 #else
9364             return(dormt(XZREN));
9365 #endif /* NOXFER */
9366         }
9367 #endif /* LOCUS */
9368 #ifdef IKSD
9369         if (inserver && (!ENABLED(en_ren)
9370 #ifdef CK_LOGIN
9371                          || isguest
9372 #endif /* CK_LOGIN */
9373                          )) {
9374             printf("?Sorry, renaming of files is disabled\n");
9375             return(-9);
9376         }
9377 #endif /* IKSD */
9378 #ifdef CK_APC
9379         if ((apcactive == APC_LOCAL) ||
9380             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9381           return(success = 0);
9382 #endif /* CK_APC */
9383         return(dorenam());
9384     }
9385 #endif /* NOFRILLS */
9386 #endif /* NORENAME */
9387
9388     if (cx == XXEIGHT) {                /* EIGHTBIT */
9389         extern int parity, cmask, cmdmsk;
9390         if ((x = cmcfm()) < 0)
9391           return(x);
9392         parity = 0;
9393         cmask = 0xff;
9394         cmdmsk = 0xff;
9395         return(success = 1);
9396     }
9397
9398 #ifndef NOXFER
9399 /* SEND, CSEND, MOVE, MAIL, and RESEND use the new common code */
9400
9401     if (cx == XXSEN                     /* SEND */
9402 #ifdef PIPESEND
9403         || cx == XXCSEN                 /* CSEND */
9404 #endif /* PIPESEND */
9405         || cx == XXMOVE                 /* MOVE */
9406         || cx == XXMAI                  /* MAIL */
9407 #ifdef CK_RESEND
9408         || cx == XXRSEN                 /* RESEND */
9409 #endif /* CK_RESEND */
9410         ) {
9411 #ifdef IKSD
9412         if (inserver && !ENABLED(en_get)) {
9413             printf("?Sorry, sending files is disabled\n");
9414             return(-9);
9415         }
9416 #endif /* IKSD */
9417         return(doxsend(cx));
9418     }
9419
9420 /* PSEND, ADD, and REMOVE use special parsing */
9421
9422 #ifdef ADDCMD
9423     /* ADD and REMOVE */
9424     if (cx == XXADD || cx == XXREMV) {
9425         char * m;
9426         m = (cx == XXADD) ? "Add to which list?" : "Remove from which list?";
9427         x = cmkey(addtab,naddtab,m,"",xxstring);
9428         if (x < 0)
9429           return(x);
9430 #ifndef NOMSEND
9431         if (x == ADD_SND)
9432           return(addsend(cx));
9433         else
9434 #endif /* NOMSEND */
9435           return(doadd(cx,x));
9436     }
9437 #endif /* ADDCMD */
9438
9439 #ifdef CK_RESEND
9440     if (cx == XXPSEN) {                 /* PSEND */
9441         int seekto = 0;
9442
9443         cmarg = cmarg2 = "";
9444         x = cmifi("File to partially send", "", &s, &y, xxstring);
9445         if (x < 0) {
9446             if (x == -3) {
9447                 printf("?A file specification is required\n");
9448                 return(-9);
9449             } else return(x);
9450         }
9451         nfils = -1;                     /* Files come from internal list. */
9452 #ifndef NOMSEND
9453         addlist = 0;                    /* Don't use SEND-LIST. */
9454         filenext = NULL;
9455 #endif /* NOMSEND */
9456         ckstrncpy(line,s,LINBUFSIZ);    /* Save copy of string just parsed. */
9457         debug(F110,"PSEND line",line,0);
9458         if (y != 0) {
9459             printf("?Sorry, wildcards not permitted in this command\n");
9460             return(-9);
9461         }
9462         if (sizeof(int) < 4) {
9463             printf("?Sorry, this command needs 32-bit integers\n");
9464             return(-9);
9465         }
9466         x = cmnum("starting position (byte number)",
9467                   "",10,&seekto,xxstring);
9468         if (x < 0)
9469           return(x);
9470         zfnqfp(s,fspeclen,fspec);       /* Get full path */
9471         if ((x = cmtxt("Name to send it with","",&s,NULL)) < 0)
9472           return(x);
9473         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
9474
9475 #ifdef IKSD
9476         if (inserver && !ENABLED(en_get)) {
9477             printf("?Sorry, sending files is disabled\n");
9478             return(-9);
9479         }
9480 #endif /* IKSD */
9481 #ifdef PIPESEND
9482         if (sndfilter) {
9483             printf("?Sorry, no PSEND while SEND FILTER selected\n");
9484             return(-9);
9485         }
9486 #endif /* PIPESEND */
9487 #ifdef CK_XYZ
9488         if ((protocol == PROTO_X || protocol == PROTO_XC)) {
9489             printf("Sorry, PSEND works only with Kermit protocol\n");
9490             return(-9);
9491         }
9492 #endif /* CK_XYZ */
9493
9494         cmarg2 = brstrip(tmpbuf);       /* Strip braces */
9495         cmarg = line;                   /* File to send */
9496         debug(F110,"PSEND filename",cmarg,0);
9497         debug(F110,"PSEND as-name",cmarg2,0);
9498         sendstart = seekto;
9499         sstate = 's';                   /* Set start state to SEND */
9500 #ifndef NOMSEND
9501         addlist = 0;
9502         filenext = NULL;
9503 #endif /* NOMSEND */
9504         sendmode = SM_PSEND;
9505 #ifdef MAC
9506         what = W_SEND;
9507         scrcreate();
9508 #endif /* MAC */
9509         if (local) {                    /* If in local mode, */
9510             displa = 1;                 /* enable file transfer display */
9511         }
9512         return(0);
9513     }
9514 #endif /* CK_RESEND */
9515 #endif /* NOXFER */
9516
9517 #ifndef NOXFER
9518 #ifndef NOMSEND
9519     if (cx == XXMSE || cx == XXMMOVE) {
9520 #ifdef NEWFTP
9521         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
9522           return(doftpput(cx,0));
9523 #endif /* NEWFTP */
9524 #ifdef CK_XYZ
9525         if (protocol == PROTO_X || protocol == PROTO_XC) {
9526             printf(
9527 "Sorry, you can only send one file at a time with XMODEM protocol\n"
9528                    );
9529             return(-9);
9530         }
9531 #endif /* CK_XYZ */
9532         return(doxsend(cx));
9533     }
9534
9535 #ifdef COMMENT                          /* (moved to doxsend) */
9536     if (cx == XXMSE || cx == XXMMOVE) { /* MSEND and MMOVE commands */
9537         nfils = 0;                      /* Like getting a list of */
9538         lp = line;                      /* files on the command line */
9539         addlist = 0;                    /* Do not use SEND-LIST */
9540         filenext = NULL;                /* Ditto ! */
9541
9542         while (1) {
9543             char *p;
9544             if ((x = cmifi("Names of files to send, separated by spaces","",
9545                            &s,&y,xxstring)) < 0) {
9546                 if (x == -3) {
9547                     if (nfils <= 0) {
9548                         printf("?A file specification is required\n");
9549                         return(-9);
9550                     } else break;
9551                 }
9552                 return(x);
9553             }
9554             msfiles[nfils++] = lp;      /* Got one, count it, point to it, */
9555             p = lp;                     /* remember pointer, */
9556             while (*lp++ = *s++)        /* and copy it into buffer */
9557               if (lp > (line + LINBUFSIZ)) { /* Avoid memory leak */
9558                   printf("?MSEND list too long\n");
9559                   line[0] = NUL;
9560                   return(-9);
9561               }
9562             debug(F111,"msfiles",msfiles[nfils-1],nfils-1);
9563             if (nfils == 1) *fspec = NUL; /* Take care of \v(filespec) */
9564 #ifdef ZFNQFP
9565             zfnqfp(p,TMPBUFSIZ,tmpbuf);
9566             p = tmpbuf;
9567 #endif /* ZFNQFP */
9568             if (((int)strlen(fspec) + (int)strlen(p) + 1) < fspeclen) {
9569                 strcat(fspec,p);        /* safe */
9570                 strcat(fspec," ");      /* safe */
9571             } else printf("WARNING - \\v(filespec) buffer overflow\n");
9572         }
9573         cmlist = msfiles;               /* Point cmlist to pointer array */
9574         cmarg2 = "";                    /* No internal expansion list (yet) */
9575         sndsrc = nfils;                 /* Filenames come from cmlist */
9576         sendmode = SM_MSEND;            /* Remember this kind of SENDing */
9577         sstate = 's';                   /* Set start state for SEND */
9578         if (cx == XXMMOVE)              /* If MMOVE'ing, */
9579           moving = 1;                   /*  set this flag. */
9580 #ifdef MAC
9581         what = W_SEND;
9582         scrcreate();
9583 #endif /* MAC */
9584         if (local) {                    /* If in local mode, */
9585             displa = 1;                 /* turn on file transfer display */
9586             ttflui();                   /* and flush tty input buffer. */
9587         }
9588         return(0);
9589     }
9590 #endif /* COMMENT */
9591 #endif /* NOMSEND */
9592 #endif /* NOXFER */
9593
9594 #ifndef NOSERVER
9595     if (cx == XXSER) {                  /* SERVER */
9596 #ifdef CK_XYZ
9597         if (protocol != PROTO_K) {
9598             printf("Sorry, SERVER only works with Kermit protocol\n");
9599             return(-9);
9600         }
9601 #endif /* CK_XYZ */
9602 #ifdef COMMENT
9603 /*
9604   Parse for time limit, but since we don't use it yet,
9605   the parsing is commented out.
9606 */
9607         x_ifnum = 1;                    /* Turn off internal complaints */
9608         y = cmnum("optional time limit, seconds, or time of day as hh:mm:ss",
9609                   "0", 10, &x, xxstring
9610                   );
9611         x_ifnum = 0;
9612         if (y < 0) {
9613             if (y == -2) {              /* Invalid number or expression */
9614                 zz = tod2sec(atmbuf);   /* Convert to secs since midnight */
9615                 if (zz < 0L) {
9616                     printf("?Number, expression, or time of day required\n");
9617                     return(-9);
9618                 } else {
9619                     char now[32];       /* Current time */
9620                     char *p;
9621                     long tnow;
9622                     p = now;
9623                     ztime(&p);
9624                     tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
9625                     if (zz < tnow)      /* User's time before now */
9626                       zz += 86400L;     /* So make it tomorrow */
9627                     zz -= tnow;         /* Seconds from now. */
9628                 }
9629             } else
9630               return(y);
9631         }
9632         if (zz > -1L) {
9633             x = zz;
9634             if (zz != (long) x) {
9635                 printf(
9636 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
9637                        );
9638                 return(-9);
9639             }
9640         }
9641         if (x < 0)
9642           x = 0;
9643 #endif /* COMMENT */
9644
9645         if ((x = cmcfm()) < 0) return(x);
9646         sstate = 'x';
9647 #ifdef MAC
9648         what = W_RECV;
9649         scrcreate();
9650 #endif /* MAC */
9651         if (local) displa = 1;
9652 #ifdef AMIGA
9653         reqoff();                       /* No DOS requestors while server */
9654 #endif /* AMIGA */
9655         return(0);
9656     }
9657 #endif /* NOSERVER */
9658
9659     if (cx == XXSAVE) {                 /* SAVE command */
9660         x = cmkey(savtab,nsav,"option","keymap",xxstring);
9661         if (x == -3) {
9662             printf("?You must specify an option to save\n");
9663             return(-9);
9664         }
9665         if (x < 0) return(x);
9666         /* have to set success separately for each item in doprm()... */
9667         /* actually not really, could have just had doprm return 0 or 1 */
9668         /* and set success here... */
9669         y = dosave(x);
9670         if (y == -3) {
9671             printf("?More fields required\n");
9672             return(-9);
9673         } else return(y);
9674     }
9675
9676     if (cx == XXSET) {                  /* SET command */
9677         x = cmkey(prmtab,nprm,"Parameter","",xxstring);
9678         if (x == -3) {
9679             printf("?You must specify a parameter to set\n");
9680             return(-9);
9681         }
9682         if (x < 0) return(x);
9683         /* have to set success separately for each item in doprm()... */
9684         /* actually not really, could have just had doprm return 0 or 1 */
9685         /* and set success here... */
9686         y = doprm(x,0);
9687         if (y == -3) {
9688             printf("?More fields required\n");
9689             return(-9);
9690         } else return(y);
9691     }
9692
9693 #ifndef NOPUSH
9694     if (cx == XXSHE                     /* SHELL (system) command */
9695         || cx == XXEXEC                 /* exec() */
9696         ) {
9697         int rx = 0;
9698         char * p = NULL;
9699         int i /* ,n */ ;
9700 #ifdef UNIXOROSK
9701         char * args[256];
9702 #endif /* UNIXOROSK */
9703
9704 #ifdef IKSD
9705         if (inserver && (nopush || !ENABLED(en_hos))) {
9706             printf("?Sorry, host command access is disabled\n");
9707             return(-9);
9708         }
9709 #endif /* IKSD */
9710
9711 #ifdef CKEXEC
9712         if (cx == XXEXEC) {             /* EXEC (overlay ourselves) */
9713             struct FDB sw, fl;
9714             cmfdbi(&sw,                 /* First FDB - command switches */
9715                    _CMKEY,              /* fcode */
9716                    "Command to overlay C-Kermit\n or switch", /* hlpmsg */
9717                    "",                  /* default */
9718                    "",                  /* addtl string data */
9719                    1,                   /* addtl numeric data 1: tbl size */
9720                    4,                   /* addtl numeric data 2: 4 = cmswi */
9721                    xxstring,            /* Processing function */
9722                    redirsw,             /* Keyword table */
9723                    &fl                  /* Pointer to next FDB */
9724                    );
9725             cmfdbi(&fl,                 /* 2nd FDB - command to exec */
9726                    _CMFLD,              /* fcode */
9727                    "Command to overlay C-Kermit", /* hlpmsg */
9728                    "",                  /* default */
9729                    "",                  /* addtl string data */
9730                    0,                   /* addtl numeric data 1 */
9731                    0,                   /* addtl numeric data 2 */
9732                    xxstring,
9733                    NULL,
9734                    NULL                 /* No more after this */
9735                    );
9736             while (1) {
9737                 x = cmfdb(&sw);         /* Parse something */
9738                 debug(F101,"exec cmfdb","",x);
9739                 if (x < 0)
9740                   return(x);
9741                 /* Generalize this if we add more switches */
9742                 if (cmresult.fcode == _CMKEY) {
9743                     rx = 1;
9744                     continue;
9745                 }
9746                 if (cmresult.fcode == _CMFLD)
9747                   break;
9748                 return(-2);
9749             }
9750             ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
9751             if (!tmpbuf[0]) {
9752                 printf("?Command required\n");
9753                 return(-9);
9754             }
9755             p = brstrip(tmpbuf);
9756             args[0] = NULL;             /* Set argv[0] to it */
9757             makestr(&args[0],p);
9758             for (i = 1; i < 255; i++) { /* Get arguments for command */
9759                 if ((x = cmfld("Argument","",&s,xxstring)) < 0) {
9760                     if (x == -3) {
9761                         if ((x = cmcfm()) < 0)
9762                           return(x);
9763                         break;
9764                     } else
9765                       return(x);
9766                 }
9767                 args[i] = NULL;
9768                 s = brstrip(s);
9769                 makestr(&args[i],s);
9770             }
9771             args[i] = NULL;
9772         } else {
9773 #endif /* CKEXEC */
9774             if ((x = cmtxt("System command to execute","",&s,xxstring)) < 0)
9775               return(x);
9776 #ifdef CKEXEC
9777         }
9778 #endif /* CKEXEC */
9779         if (nopush)
9780           return(success = 0);
9781 #ifdef CK_APC
9782         if (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
9783           return(success = 0);
9784 #endif /* CK_APC */
9785         conres();                       /* Make console normal  */
9786 #ifdef OS2
9787         if (!(s && *s)) {
9788             os2push();
9789             return(success = 1);
9790         } else
9791 #endif /* OS2 */
9792           if (cx == XXSHE) {
9793               x = zshcmd(s);
9794               debug(F101,"RUN zshcmd code","",x);
9795               concb((char)escape);
9796               return(success = x);
9797 #ifdef CKEXEC
9798           } else {
9799 #ifdef DEBUG
9800               if (deblog) {
9801                   debug(F111,"EXEC cmd",p,0);
9802                   for (i = 0; i < 256 && args[i]; i++)
9803                     debug(F111,"EXEC arg",args[i],i);
9804               }
9805 #endif /* DEBUG */
9806               if (p) {
9807                   z_exec(p,args,rx);    /* Overlay ourself */
9808                   debug(F100,"EXEC fails","",0);
9809                   concb((char)escape);  /* In case it returns */
9810               }
9811               return(success = 0);
9812 #endif /* CKEXEC */
9813           }
9814     }
9815
9816 #ifdef CK_REDIR
9817     if (cx == XXFUN) {                  /* REDIRECT */
9818 #ifdef CK_APC
9819         if ((apcactive == APC_LOCAL) ||
9820             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
9821           return(success = 0);
9822 #endif /* CK_APC */
9823         ckmakmsg(tmpbuf,
9824                  TMPBUFSIZ,
9825                  "Local command to run,\n",
9826                  "with its standard input/output redirected to ",
9827                  local ? ttname : "the communications connection",
9828                  "\n"
9829                  );
9830         if ((x = cmtxt(tmpbuf,"",&s,xxstring)) < 0)
9831           return(x);
9832         if (nopush) {
9833             printf("?REDIRECT disabled\n");
9834             return(success=0);
9835         }
9836         if (!local) {
9837             printf("?SET LINE or SET HOST required first\n");
9838             return(-9);
9839         }
9840         if (!*s) {
9841             printf("?REDIRECT requires a command to redirect\n");
9842             return(-9);
9843         }
9844         return(success = ttruncmd(s));
9845     }
9846 #endif /* CK_REDIR */
9847 #endif /* NOPUSH */
9848
9849 #ifndef NOSHOW
9850     if (cx == XXSHO) {                  /* SHOW */
9851         x = cmkey(shotab,nsho,"","parameters",xxstring);
9852         if (x < 0) return(x);
9853         return(doshow(x));
9854     }
9855 #endif /* NOSHOW */
9856
9857 #ifndef MAC
9858     if (cx == XXSPA) {                  /* SPACE */
9859 #ifdef IKSD
9860         if (inserver && !ENABLED(en_spa)) {
9861             printf("?Sorry, SPACE command disabled\n");
9862             return(-9);
9863         }
9864 #endif /* IKSD */
9865 #ifdef datageneral
9866         /* AOS/VS can take an argument after its "space" command. */
9867         if ((x = cmtxt("Confirm, or local directory name","",&s,xxstring)) < 0)
9868           return(x);
9869         if (nopush) {
9870             printf("?Sorry, SPACE command disabled\n");
9871             return(-9);
9872         } else if (*s == NUL) {
9873             xsystem(SPACMD);
9874         } else {
9875             ckmakmsg(line,LINBUFSIZ,"space ",s,NULL,NULL);
9876             xsystem(line);
9877         }
9878 #else
9879 #ifdef OS2
9880         if ((x = cmtxt("Press Enter for current disk,\n\
9881  or specify a disk letter like A:","",&s,xxstring)) < 0)
9882           return(x);
9883         if (*s == NUL) {                /* Current disk */
9884             unsigned long space = zdskspace(0);
9885             if (space > 0 && space < 1024)
9886               printf(" Free space: unknown\n");
9887             else
9888               printf(" Free space: %ldK\n", space/1024L);
9889         } else {
9890             int drive = toupper(*s);
9891             unsigned long space = zdskspace(drive - 'A' + 1);
9892             if (space > 0 && space < 1024)
9893               printf(" Drive %c: unknown free\n");
9894             else
9895               printf(" Drive %c: %ldK free\n", drive,space / 1024L);
9896         }
9897 #else
9898 #ifdef UNIXOROSK
9899         x = cmdir("Confirm for current disk,\n\
9900  or specify a disk device or directory","",&s,xxstring);
9901         if (x == -3)
9902           s = "";
9903         else if (x < 0)
9904           return(x);
9905         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
9906         s = tmpbuf;
9907         if ((x = cmcfm()) < 0) return(x);
9908         if (nopush) {
9909             printf("?Sorry, SPACE command disabled\n");
9910             return(-9);
9911         }
9912         if (!*s) {                      /* Current disk */
9913             xsystem(SPACMD);
9914         } else {                        /* Specified disk */
9915             ckmakmsg(line,LINBUFSIZ,SPACM2," ",s,NULL);
9916             xsystem(line);
9917         }
9918 #else
9919         if ((x = cmcfm()) < 0) return(x);
9920         if (nopush) {
9921             printf("?Sorry, SPACE command disabled\n");
9922             return(-9);
9923         }
9924         xsystem(SPACMD);
9925 #endif /* UNIXOROSK */
9926 #endif /* OS2 */
9927 #endif /* datageneral */
9928         return(success = 1);            /* Pretend it worked */
9929     }
9930 #endif /* MAC */
9931
9932 #ifndef NOXFER
9933     if (cx == XXSTA) {                  /* STATISTICS */
9934         if ((x = cmkey(stattab,2,"Carriage return, or option",
9935                        "/brief",xxstring)) < 0)
9936           return(x);
9937         if ((y = cmcfm()) < 0) return(y);
9938         return(success = dostat(x));
9939     }
9940 #endif /* NOXFER */
9941
9942     if (cx == XXSTO || cx == XXEND) {   /* STOP, END, or POP */
9943         if ((y = cmnum("exit status code","0",10,&x,xxstring)) < 0)
9944           return(y);
9945         if ((y = cmtxt("Message to print","",&s,xxstring)) < 0)
9946           return(y);
9947         s = brstrip(s);
9948         if (*s) printf("%s\n",s);
9949         if (cx == XXSTO) {
9950             dostop();
9951         } else {
9952             doend(x);
9953         }
9954         return(success = (x == 0));
9955     }
9956     if (cx == XXSUS) {                  /* SUSPEND */
9957         if ((y = cmcfm()) < 0) return(y);
9958 #ifdef NOJC
9959         printf("Sorry, this version of Kermit cannot be suspended\n");
9960 #else
9961 #ifdef IKSD
9962         if (inserver) {
9963             printf("?Sorry, IKSD can not be suspended\n");
9964             return(-9);
9965         } else
9966 #endif /* IKSD */
9967           if (nopush) {
9968             printf("?Sorry, access to system is disabled\n");
9969             return(-9);
9970         }
9971         stptrap(0);
9972 #endif /* NOJC */
9973         return(0);
9974     }
9975
9976     if (cx == XXTAK) {                  /* TAKE */
9977         char * scriptenv = NULL;        
9978 #ifdef OS2
9979         char * GetAppData(int);
9980         extern char startupdir[],exedir[],inidir[];
9981         char * keymapenv = NULL;
9982         char * appdata0 = NULL, *appdata1 = NULL;
9983         int xx;
9984 #define TAKEPATHLEN 4096
9985 #else /* OS2 */
9986 #define TAKEPATHLEN 1024
9987 #endif /* OS2 */
9988         char takepath[TAKEPATHLEN];
9989
9990         if (tlevel >= MAXTAKE-1) {
9991             printf("?Take files nested too deeply\n");
9992             return(-9);
9993         }
9994 #ifdef OS2
9995 #ifdef NT
9996         scriptenv = getenv("K95SCRIPTS");
9997         keymapenv = getenv("K95KEYMAPS");
9998         makestr(&appdata0,(char *)GetAppData(0));
9999         makestr(&appdata1,(char *)GetAppData(1));
10000 #else /* NT */
10001         scriptenv = getenv("K2SCRIPTS");
10002         keymapenv = getenv("K2KEYMAPS");
10003 #endif /* NT */
10004 #endif /* OS2 */
10005
10006         if (!scriptenv)                 /* Let this work for Unix etc too */
10007           scriptenv = getenv("CK_SCRIPTS"); /* Use this if defined */
10008 #ifndef OS2
10009         if (!scriptenv)                 /* Otherwise use home directory */
10010           scriptenv = homepath();
10011 #endif /* OS2 */
10012         if (!scriptenv)
10013           scriptenv = "";
10014         ckstrncpy(takepath,scriptenv,TAKEPATHLEN);
10015         debug(F110,"TAKE initial takepath",takepath,0);
10016
10017 #ifdef OS2
10018         if (!keymapenv)
10019           keymapenv = getenv("CK_KEYMAPS");
10020         if (!keymapenv)
10021           keymapenv = "";
10022
10023         ckstrncat(takepath,
10024                   (scriptenv && scriptenv[strlen(scriptenv)-1]==';')?"":";",
10025                   TAKEPATHLEN
10026                   );
10027         ckstrncat(takepath,keymapenv?keymapenv:"",TAKEPATHLEN);
10028         ckstrncat(takepath,
10029                   (keymapenv && keymapenv[strlen(keymapenv)-1]==';')?"":";",
10030                   TAKEPATHLEN
10031                   );
10032         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10033         ckstrncat(takepath,";",TAKEPATHLEN);
10034         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10035         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10036         ckstrncat(takepath,startupdir,TAKEPATHLEN);
10037         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10038
10039         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10040         ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
10041         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10042         ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
10043         ckstrncat(takepath,appdata1,TAKEPATHLEN);
10044         ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
10045
10046         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10047         ckstrncat(takepath,"Kermit 95/;",TAKEPATHLEN);
10048         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10049         ckstrncat(takepath,"Kermit 95/SCRIPTS/;",TAKEPATHLEN);
10050         ckstrncat(takepath,appdata0,TAKEPATHLEN);
10051         ckstrncat(takepath,"Kermit 95/KEYMAPS/;",TAKEPATHLEN);
10052
10053         ckstrncat(takepath,inidir,TAKEPATHLEN);
10054         ckstrncat(takepath,";",TAKEPATHLEN);
10055         ckstrncat(takepath,inidir,TAKEPATHLEN);
10056         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10057         ckstrncat(takepath,inidir,TAKEPATHLEN);
10058         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10059
10060         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10061         ckstrncat(takepath,";",TAKEPATHLEN);
10062         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10063         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10064         ckstrncat(takepath,zhome(),TAKEPATHLEN);
10065         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10066
10067         ckstrncat(takepath,exedir,TAKEPATHLEN);
10068         ckstrncat(takepath,";",TAKEPATHLEN);
10069         ckstrncat(takepath,exedir,TAKEPATHLEN);
10070         ckstrncat(takepath,"SCRIPTS/;",TAKEPATHLEN);
10071         ckstrncat(takepath,exedir,TAKEPATHLEN);
10072         ckstrncat(takepath,"KEYMAPS/;",TAKEPATHLEN);
10073 #endif /* OS2 */
10074         debug(F110,"TAKE final takepath",takepath,0);
10075
10076         if ((y = cmifip("Commands from file",
10077                         "",&s,&x,0,takepath,xxstring)) < 0) {
10078             if (y == -3) {
10079                 printf("?A file name is required\n");
10080                 return(-9);
10081             } else
10082               return(y);
10083         }
10084         if (x != 0) {
10085             printf("?Wildcards not allowed in command file name\n");
10086             return(-9);
10087         }
10088         ckstrncpy(line,s,LINBUFSIZ);
10089         debug(F110,"TAKE file",s,0);
10090         if (isdir(s)) {
10091             printf("?Can't execute a directory - \"%s\"\n", s);
10092             return(-9);
10093         }
10094 #ifndef NOTAKEARGS
10095         {
10096             char * p;
10097             x = strlen(line);
10098             debug(F111,"TAKE args",line,x);
10099             p = line + x + 1;
10100             if ((y = cmtxt("Optional arguments","",&s,xxstring)) < 0)
10101               return(y);
10102             if (*s) {                   /* Args given? */
10103                 ckstrncpy(p,s,LINBUFSIZ-x-1);
10104 #ifdef ZFNQFP
10105                 zfnqfp(line,TMPBUFSIZ,tmpbuf);
10106                 s = tmpbuf;
10107 #else
10108                 s = line;
10109 #endif /* ZFNQFP */
10110                 debug(F110,"TAKE filename",s,0);
10111                 x = strlen(s);
10112                 debug(F101,"TAKE new len",s,x);
10113
10114 #ifdef COMMENT
10115 /*
10116   This was added in C-Kermit 7.0 to allow args to be passed from the TAKE
10117   command to the command file.  But it overwrites the current argument vector,
10118   which is at best surprising, and at worst unsafe.
10119 */
10120                 addmac("%0",s);         /* Define %0 = name of file */
10121                 varnam[0] = '%';
10122                 varnam[2] = '\0';
10123                 debug(F110,"take arg 0",s,0);
10124                 debug(F110,"take args",p,0);
10125                 for (y = 1; y < 10; y++) { /* Clear current args %1..%9 */
10126                     varnam[1] = (char) (y + '0');
10127                     delmac(varnam,0);
10128                 }
10129                 xwords(p,MAXARGLIST,NULL,0); /* Assign new args */
10130                 debug(F110,"take args",p,0);
10131 #else
10132 /*
10133   This method is used in 8.0.  If the TAKE command includes arguments, we
10134   insert an intermediate temporary macro between the current level; we pass
10135   the arguments to the macro and then the macro TAKEs the command file.
10136   If the user Ctrl-C's out of the TAKE file, some temporary macro definitions
10137   and other small malloc'd bits might be left behind.
10138 */
10139                 {
10140                     char * q = NULL;
10141                     char * r = NULL;
10142                     int k, m;
10143                     m = maclvl;
10144                     q = (char *)malloc(x+24);
10145                     if (q) {
10146                         r = (char *)malloc(x+24);
10147                         if (r) {
10148                             sprintf(q,"_file[%s](%d)",s,cmdlvl); /* safe */
10149                             sprintf(r,"take %s",s); /* safe */
10150                             k = addmac(q,r);
10151                             if (k > -1) {
10152                                 dodo(k,p,0);
10153                                 while (maclvl > m) {
10154                                     sstate = (CHAR) parser(1);
10155                                     if (sstate) proto();
10156                                 }
10157                             }
10158                             k = delmac(q,0);
10159                             free(q);
10160                             free(r);
10161                             return(success);
10162                         }
10163                     }
10164                 }
10165                 return(success = 0);
10166 #endif /* COMMENT */
10167             }
10168         }
10169 #else
10170         if ((y = cmcfm()) < 0) return(y);
10171 #endif /* NOTAKEARGS */
10172         return(success = dotake(line));
10173     }
10174
10175 #ifndef NOLOCAL
10176 #ifdef OS2
10177     if (cx == XXVIEW) {                 /* VIEW Only Terminal mode */
10178         viewonly = TRUE;
10179         success = doconect(0, 0);
10180         viewonly = FALSE;
10181         return success;
10182     }
10183 #endif /* OS2 */
10184
10185 #ifdef NETCONN
10186     if (cx == XXTEL || cx == XXIKSD) {  /* TELNET */
10187         int x,z;
10188 #ifdef OS2
10189     if (!tcp_avail) {
10190         printf("?Sorry, either TCP/IP is not available on this system or\n\
10191 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
10192         success = 0;
10193         return(-9);
10194     } else
10195 #endif /* OS2 */
10196       {
10197           x = nettype;                  /* Save net type in case of failure */
10198           z = ttnproto;                 /* Save protocol in case of failure */
10199           nettype = NET_TCPB;
10200           ttnproto = (cx == XXTEL) ? NP_TELNET : NP_KERMIT;
10201           if ((y = setlin(XYHOST,0,1)) <= 0) {
10202               nettype = x;              /* Failed, restore net type. */
10203               ttnproto = z;             /* and protocol */
10204               success = 0;
10205           }
10206           didsetlin++;
10207         }
10208         return(y);
10209     }
10210
10211 #ifndef PTYORPIPE
10212 #ifdef NETCMD
10213 #define PTYORPIPE
10214 #else
10215 #ifdef NETPTY
10216 #define PTYORPIPE
10217 #endif /* NETPTY */
10218 #endif /* NETCMD */
10219 #endif /* PTYORPIPE */
10220
10221 #ifdef PTYORPIPE
10222     if (cx == XXPIPE || cx == XXPTY) {  /* PIPE or PTY */
10223         int x;
10224         extern int netsave;
10225         x = nettype;                    /* Save net type in case of failure */
10226         nettype = (cx == XXPIPE) ? NET_CMD : NET_PTY;
10227         if ((y = setlin(XYHOST,0,1)) < 0) {
10228             nettype = x;                /* Failed, restore net type. */
10229             ttnproto = z;               /* and protocol */
10230             success = 0;
10231         }
10232         didsetlin++;
10233         netsave = x;
10234         return(y);
10235     }
10236 #endif /* PTYORPIPE */
10237
10238 #ifdef ANYSSH
10239     if (cx == XXSSH) {                  /* SSH (Secure Shell) */
10240         extern int netsave;
10241 #ifdef SSHBUILTIN
10242         int k, x, havehost = 0, trips = 0;
10243         int    tmpver = -1, tmpxfw = -1;
10244 #ifndef SSHTEST
10245         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
10246         extern int sl_ssh_ver, sl_ssh_ver_saved;
10247 #endif /* SSHTEST */
10248         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
10249         extern char * slmsg;
10250         extern char uidbuf[], sl_uidbuf[];
10251         extern char pwbuf[], * g_pswd;
10252         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
10253         struct FDB sw, kw, fl;
10254
10255         if (ssh_tmpstr)
10256           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
10257         makestr(&ssh_tmpstr,NULL);
10258         makestr(&ssh_tmpuid,NULL);
10259         makestr(&ssh_tmpcmd,NULL);
10260         makestr(&ssh_tmpport,NULL);
10261
10262         cmfdbi(&kw,                     /* 1st FDB - commands */
10263                _CMKEY,                  /* fcode */
10264                "host [ port ],\n or action",    /* hlpmsg */
10265                "",                      /* default */
10266                "",                      /* addtl string data */
10267                nsshcmd,                 /* addtl numeric data 1: tbl size */
10268                0,                       /* addtl numeric data 2: 0 = keyword */
10269                xxstring,                /* Processing function */
10270                sshkwtab,                /* Keyword table */
10271                &fl                      /* Pointer to next FDB */
10272                );
10273         cmfdbi(&fl,                     /* Host */
10274                _CMFLD,                  /* fcode */
10275                "",                      /* hlpmsg */
10276                "",                      /* default */
10277                "",                      /* addtl string data */
10278                0,                       /* addtl numeric data 1 */
10279                0,                       /* addtl numeric data 2 */
10280                xxstring,
10281                NULL,
10282                NULL
10283                );
10284
10285         x = cmfdb(&kw);
10286         if (x == -3) {
10287             printf("?ssh what?\n");
10288             return(-9);
10289         }
10290         if (x < 0)
10291           return(x);
10292         havehost = 0;
10293         if (cmresult.fcode == _CMFLD) {
10294             havehost = 1;
10295             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
10296             cmresult.nresult = XSSH_OPN;
10297         }
10298         switch (cmresult.nresult) {     /* SSH keyword */
10299           case XSSH_OPN:                /* SSH OPEN */
10300             if (!havehost) {
10301                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
10302                   return(x);
10303                 ckstrncpy(line,s,LINBUFSIZ);
10304             }
10305             /* Parse [ port ] [ switches ] */
10306             cmfdbi(&kw,                 /* Switches */
10307                    _CMKEY,
10308                    "Port number or service name,\nor switch",
10309                    "",
10310                    "",
10311                    nsshopnsw,
10312                    4,
10313                    xxstring,
10314                    sshopnsw,
10315                    &fl
10316                    );
10317             cmfdbi(&fl,                 /* Port number or service name */
10318                    _CMFLD,
10319                    "",
10320                    "",
10321                    "",
10322                    0,
10323                    0,
10324                    xxstring,
10325                    NULL,
10326                    NULL
10327                    );
10328             trips = 0;                  /* Explained below */
10329             while (1) {                 /* Parse port and switches */
10330                 x = cmfdb(&kw);         /* Get a field */
10331                 if (x == -3)            /* User typed CR so quit from loop */
10332                   break;
10333                 if (x < 0)              /* Other parse error, pass it back */
10334                   return(x);
10335                 switch (cmresult.fcode) { /* Field or Keyword? */
10336                   case _CMFLD:            /* Field */
10337                     makestr(&ssh_tmpport,cmresult.sresult);
10338                     break;
10339                   case _CMKEY:          /* Keyword */
10340                     switch (cmresult.nresult) { /* Which one? */
10341                       case SSHSW_USR:           /* /USER: */
10342                         if (!cmgbrk()) {
10343                             printf("?This switch requires an argument\n");
10344                             return(-9);
10345                         }
10346                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
10347                           return(y);
10348                         s = brstrip(s);
10349                         makestr(&ssh_tmpuid,s);
10350                         break;
10351                       case SSHSW_PWD:
10352                         if (!cmgbrk()) {
10353                             printf("?This switch requires an argument\n");
10354                             return(-9);
10355                         }
10356                         debok = 0;
10357                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
10358                             if (x == -3) {
10359                                 makestr(&ssh_tmpstr,"");
10360                             } else {
10361                                 return(x);
10362                             }
10363                         } else {
10364                             s = brstrip(s);
10365                             if ((x = (int)strlen(s)) > PWBUFL) {
10366                                 makestr(&slmsg,"Internal error");
10367                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
10368                                 return(-9);
10369                             }
10370                             makestr(&ssh_tmpstr,s);
10371                         }
10372                         break;
10373
10374                       case SSHSW_VER:
10375                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
10376                           return(x);
10377                         if (z < 1 || z > 2) {
10378                             printf("?Out of range: %d\n",z);
10379                             return(-9);
10380                         }
10381                         tmpver = z;
10382                         break;
10383                       case SSHSW_CMD:
10384                       case SSHSW_SUB:
10385                         if ((x = cmfld("Text","",&s,xxstring)) < 0)
10386                           return(x);
10387                         makestr(&ssh_tmpcmd,s);
10388                         ssh_cas = (cmresult.nresult == SSHSW_SUB);
10389                         break;
10390                       case SSHSW_X11:
10391                         if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
10392                           return(x);
10393                         tmpxfw = x;
10394                         break;
10395                       default:
10396                         return(-2);
10397                     }
10398                 }
10399                 if (trips++ == 0) {     /* After first time through */
10400                     cmfdbi(&kw,         /* only parse switches, not port. */
10401                            _CMKEY,
10402                            "Switch",
10403                            "",
10404                            "",
10405                            nsshopnsw,
10406                            4,
10407                            xxstring,
10408                            sshopnsw,
10409                            NULL
10410                            );
10411                 }
10412             }
10413             if ((x = cmcfm()) < 0)      /* Get confirmation */
10414               return(x);
10415             if (clskconnx(1) < 0) {     /* Close current Kermit connection */
10416               if ( ssh_tmpstr ) {
10417                   memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
10418                   makestr(&ssh_tmpstr,NULL);
10419               }
10420               return(success = 0);
10421             }
10422             makestr(&ssh_hst,line);     /* Stash everything */
10423             if (ssh_tmpuid) {
10424                 if (!sl_uid_saved) {
10425                     ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
10426                     sl_uid_saved = 1;
10427                 }
10428                 ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
10429                 makestr(&ssh_tmpuid,NULL);
10430             }
10431             if (ssh_tmpport) {
10432                 makestr(&ssh_prt,ssh_tmpport);
10433                 makestr(&ssh_tmpport,NULL);
10434             } else
10435                 makestr(&ssh_prt,NULL);
10436
10437             if (ssh_tmpcmd) {
10438                 makestr(&ssh_cmd,brstrip(ssh_tmpcmd));
10439                 makestr(&ssh_tmpcmd,NULL);
10440             } else
10441                 makestr(&ssh_cmd,NULL);
10442
10443             if (tmpver > -1) {
10444 #ifndef SSHTEST
10445                 if (!sl_ssh_ver_saved) {
10446                     sl_ssh_ver = ssh_ver;
10447                     sl_ssh_ver_saved = 1;
10448                 }
10449 #endif /* SSHTEST */
10450                 ssh_ver = tmpver;
10451             }
10452             if (tmpxfw > -1) {
10453 #ifndef SSHTEST
10454                 if (!sl_ssh_xfw_saved) {
10455                     sl_ssh_xfw = ssh_xfw;
10456                     sl_ssh_xfw_saved = 1;
10457                 }
10458 #endif /* SSHTEST */
10459                 ssh_xfw = tmpxfw;
10460             }
10461             if (ssh_tmpstr) {
10462                 if (ssh_tmpstr[0]) {
10463                     ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
10464                     pwflg = 1;
10465                     pwcrypt = 0;
10466                 } else
10467                   pwflg = 0;
10468                 makestr(&ssh_tmpstr,NULL);
10469             }
10470             nettype = NET_SSH;
10471             if (mdmsav < 0)
10472               mdmsav = mdmtyp;
10473             mdmtyp = -nettype;
10474             x = 1;
10475
10476 #ifndef NOSPL
10477             makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
10478             g_pflg = pwflg;                     /* and flag */
10479             g_pcpt = pwcrypt;
10480 #endif /* NOSPL */
10481
10482             /* Line parameter to ttopen() is ignored */
10483             k = ttopen(line,&x,mdmtyp, 0);
10484             if (k < 0) {
10485                 printf("?Unable to connect to %s\n",ssh_hst);
10486                 mdmtyp = mdmsav;
10487                 slrestor();
10488                 return(success = 0);
10489             }
10490             duplex = 0;             /* Remote echo */
10491             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
10492             debug(F110,"ssh ttname",ttname,0);
10493             makestr(&slmsg,NULL);       /* No SET LINE error message */
10494             cxtype = CXT_SSH;
10495 #ifndef NODIAL
10496             dialsta = DIA_UNK;
10497 #endif /* NODIAL */
10498             success = 1;                /* SET LINE succeeded */
10499             network = 1;                /* Network connection (not serial) */
10500             local = 1;                  /* Local mode (not remote) */
10501             if ((reliable != SET_OFF || !setreliable))
10502               reliable = SET_ON;        /* Transport is reliable end to end */
10503 #ifdef OS2
10504             DialerSend(OPT_KERMIT_CONNECT, 0);
10505 #endif /* OS2 */
10506             setflow();                  /* Set appropriate flow control */
10507
10508             haveline = 1;
10509 #ifdef CKLOGDIAL
10510 #ifdef NETCONN
10511             dolognet();
10512 #endif /* NETCONN */
10513 #endif /* CKLOGDIAL */
10514
10515 #ifndef NOSPL
10516             if (local) {
10517                 if (nmac) {             /* Any macros defined? */
10518                     int k;              /* Yes */
10519                     k = mlook(mactab,"on_open",nmac); /* Look this up */
10520                     if (k >= 0) {                     /* If found, */
10521                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
10522                           parser(1);                  /* and execute it */
10523                     }
10524                 }
10525             }
10526 #endif /* NOSPL */
10527 #ifdef LOCUS            
10528             if (autolocus)
10529                 setlocus(1,1);
10530 #endif /* LOCUS */
10531
10532         /* Command was confirmed so we can pre-pop command level. */
10533         /* This is so CONNECT module won't think we're executing a */
10534         /* script if CONNECT was the final command in the script. */
10535             if (cmdlvl > 0)
10536               prepop();
10537             success = doconect(0,cmdlvl == 0 ? 1 : 0);
10538             if (ttchk() < 0)
10539               dologend();
10540             return(success);
10541
10542           case XSSH_CLR:
10543             if ((y = cmkey(sshclr,nsshclr,"","", xxstring)) < 0) {
10544                 if (y == -3) {
10545                     printf("?clear what?\n");
10546                     return(-9);
10547                 }
10548                 return(y);
10549             }
10550             if ((x = cmcfm()) < 0)
10551               return(x);
10552             switch (y) {
10553               case SSHC_LPF:
10554                 ssh_pf_lcl_n = 0;
10555                 break;
10556               case SSHC_RPF:
10557                 ssh_pf_rmt_n = 0;
10558                 break;
10559               default:
10560                 return(-2);
10561             }
10562             return(success = 1);        /* or whatever */
10563
10564           case XSSH_AGT: {              /* SSH AGENT */
10565               int doeach = 0;
10566               if ((y = cmkey(sshagent,nsshagent,"","",xxstring)) < 0)
10567                 return(y);
10568               switch (y) {
10569                 case SSHA_ADD:          /* SSH AGENT ADD ... */
10570                   if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
10571 #ifndef SSHTEST
10572                       if (x == -3)      /* No name given */
10573                         doeach = 1;     /* so do them all */
10574                       else
10575 #endif /* SSHTEST */
10576                         return(x);
10577                   }
10578                   ckstrncpy(line,s,LINBUFSIZ);
10579                   if ((x = cmcfm()) < 0)
10580                     return(x);
10581 #ifdef SSHTEST
10582                   x = 0;
10583 #else
10584                   if (doeach) {
10585                       int i;
10586                       x = 0;
10587                       for (i = 0; i < ssh_idf_n; i++)
10588                         x += ssh_agent_add_file(ssh_idf[i]);
10589                   } else
10590                     x = ssh_agent_add_file(line);
10591 #endif /* SSHTEST */
10592                   return(success = (x == 0));
10593
10594                 case SSHA_DEL: {        /* SSH AGENT DELETE ... */
10595                     int doall = 0;
10596                     if ((x = cmifi("Identity file","",&s,&y,xxstring)) < 0) {
10597 #ifndef SSHTEST
10598                         if (x == -3)    /* No name given */
10599                           doall = 1;    /* so do them all */
10600                         else
10601 #endif /* SSHTEST */
10602                           return(x);
10603                     }
10604                     ckstrncpy(line,s,LINBUFSIZ);
10605                     if ((x = cmcfm()) < 0)
10606                       return(x);
10607 #ifdef SSHTEST
10608                     x = 0;
10609 #else
10610                     if (doall)
10611                       x = ssh_agent_delete_all();
10612                     else
10613                       x = ssh_agent_delete_file(line);
10614 #endif /* SSHTEST */
10615                     return(success = (x == 0));
10616                 }
10617                 case SSHA_LST: {
10618                     int fingerprint = 0;
10619                     if ((y = cmswi(sshagtsw,nsshagtsw,"","",xxstring)) < 0) {
10620                         if (y != -3)
10621                           return(y);
10622                     } else if (cmgbrk() > SP) {
10623                         printf("?This switch does not take an argument\n");
10624                         return(-9);
10625                     } else if (y == SSHASW_FP) {
10626                         fingerprint = 1;
10627                     }
10628                     if ((x = cmcfm()) < 0)
10629                       return(x);
10630 #ifdef SSHTEST
10631                     return(success = 1);
10632 #else
10633                     return(success =
10634                            (ssh_agent_list_identities(fingerprint) == 0));
10635 #endif /* SSHTEST */
10636                 }
10637                 default:
10638                   return(-2);
10639               }
10640           }
10641           case XSSH_ADD: {              /* SSH ADD */
10642               /* ssh add { local, remote } port host port */
10643               int cx, i, j, k;
10644               char * h;
10645               if ((cx = cmkey(addfwd,naddfwd,"","", xxstring)) < 0)
10646                 return(cx);
10647               if ((x = cmnum((cx == SSHF_LCL) ?
10648                              "Local port number" : "Remote port number",
10649                              "",10,&j,xxstring)) < 0)
10650                 return(x);
10651               if ((x = cmfld("Host","",&s,xxstring)) < 0)
10652                 return(x);
10653               makestr(&h,s);
10654               if ((x = cmnum("Port","",10,&k,xxstring)) < 0)
10655                 return(x);
10656               if ((x = cmcfm()) < 0)
10657                 return(x);
10658
10659               switch(cx) {
10660                 case SSHF_LCL:
10661                    if (ssh_pf_lcl_n == 32) {
10662                        printf(
10663 "?Maximum number of local port forwardings already specified\n"
10664                              );
10665                        free(h);
10666                        return(success = 0);
10667                   }
10668                   ssh_pf_lcl[ssh_pf_lcl_n].p1 = j;
10669                   makestr(&(ssh_pf_lcl[ssh_pf_lcl_n].host),h);
10670                   makestr(&h,NULL);
10671                   ssh_pf_lcl[ssh_pf_lcl_n].p2 = k;
10672                   ssh_pf_lcl_n++;
10673                   break;
10674                 case SSHF_RMT:
10675                   if (ssh_pf_rmt_n == 32) {
10676                       printf(
10677 "?Maximum number of remote port forwardings already specified\n"
10678                             );
10679                       free(h);
10680                       return(success = 0);
10681                   }
10682                   ssh_pf_rmt[ssh_pf_rmt_n].p1 = j;
10683                   makestr(&(ssh_pf_rmt[ssh_pf_rmt_n].host),h);
10684                   makestr(&h,NULL);
10685                   ssh_pf_rmt[ssh_pf_rmt_n].p2 = k;
10686                   ssh_pf_rmt_n++;
10687               }
10688               return(success = 1);
10689           }
10690           /* Not supporting arbitrary forwarding yet */
10691           case XSSH_FLP:                /* SSH FORWARD-LOCAL-PORT */
10692           case XSSH_FRP: {              /* SSH FORWARD-REMOTE-PORT */
10693               int li_port = 0;
10694               int to_port = 0;
10695               char * fw_host = NULL;
10696               int n;
10697               if ((x = cmnum(cmresult.nresult == XSSH_FLP ?
10698                               "local-port":"remote-port",
10699                               "",10,&li_port,xxstring)) < 0)
10700                   return(x);
10701               if (li_port < 1 || li_port > 65535) {
10702                   printf("?Out range - min: 1, max: 65535\n");
10703                   return(-9);
10704               }
10705               if ((x = cmfld("host",ssh_hst?ssh_hst:"",&s,xxstring)) < 0)
10706                 return(x);
10707               n = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
10708               fw_host = tmpbuf;
10709               if ((x = cmnum("host-port",ckuitoa(li_port),10,
10710                               &to_port,xxstring)) < 0)
10711                   return(x);
10712               if (to_port < 1 || to_port > 65535) {
10713                   printf("?Out range - min: 1, max: 65535\n");
10714                   return(-9);
10715               }
10716               if ((x = cmcfm()) < 0)
10717                 return(x);
10718               switch (cmresult.nresult) {
10719                 case XSSH_FLP:  /* SSH FORWARD-LOCAL-PORT */
10720 #ifndef SSHTEST
10721                   ssh_fwd_local_port(li_port,fw_host,to_port);
10722 #endif /* SSHTEST */
10723                   return(success = 1);
10724                 case XSSH_FRP:  /* SSH FORWARD-REMOTE-PORT */
10725 #ifndef SSHTEST
10726                   ssh_fwd_remote_port(li_port,fw_host,to_port);
10727 #endif /* SSHTEST */
10728                   return(success = 1);
10729               }
10730               return(success = 1);
10731           }
10732         case XSSH_V2:           /* SSH V2 */
10733           if ((cx = cmkey(ssh2tab,nssh2tab,"","", xxstring)) < 0)
10734             return(cx);
10735           switch (cx) {
10736             case XSSH2_RKE:
10737               if ((x = cmcfm()) < 0)
10738                 return(x);
10739 #ifndef SSHTEST
10740               ssh_v2_rekey();
10741 #endif /* SSHTEST */
10742               return(success = 1);
10743             default:
10744               return(-2);
10745           }
10746         case XSSH_KEY:
10747           if ((cx = cmkey(sshkey,nsshkey,"","", xxstring)) < 0)
10748             return(cx);
10749           switch (cx) {
10750             case SSHK_PASS: {   /* Change passphrase */
10751               char * oldp = NULL, * newp = NULL;
10752               struct FDB df, sw;
10753               cmfdbi(&sw,
10754                      _CMKEY,            /* fcode */
10755                      "Filename, or switch", /* hlpmsg */
10756                      "",                /* default */
10757                      "",                /* addtl string data */
10758                      2,                 /* addtl numeric data 1: tbl size */
10759                      4,                 /* addtl numeric data 2: 4 = cmswi */
10760                      xxstring,          /* Processing function */
10761                      sshkpsw,           /* Keyword table */
10762                      &df                /* Pointer to next FDB */
10763                      );
10764               cmfdbi(&df,               /* 2nd FDB - file for display */
10765                      _CMIFI,            /* output file */
10766                      "",                /* hlpmsg */
10767                      "",                /* default */
10768                      "",                /* addtl string data */
10769                      0,                 /* addtl numeric data 1 */
10770                      0,                 /* addtl numeric data 2 */
10771                      xxstring,
10772                      NULL,
10773                      NULL
10774                      );
10775               line[0] = NUL;
10776
10777               while (1) {
10778                   x = cmfdb(&sw);
10779                   if (x == -3) break;
10780                   if (x < 0)
10781                     return(x);
10782                   if (cmresult.fcode != _CMKEY)
10783                     break;
10784                   if (!cmgbrk()) {
10785                       printf("?This switch requires an argument\n");
10786                       return(-9);
10787                   }
10788                   if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
10789                     return(y);
10790                   switch (cmresult.nresult) {
10791                     case 1:             /* Old */
10792                       makestr(&oldp,s);
10793                       break;
10794                     case 2:             /* New */
10795                       makestr(&newp,s);
10796                   }
10797               }
10798               if (cmresult.fcode == _CMIFI) { /* Filename */
10799                   ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
10800                   if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
10801                     ckstrncpy(line,tmpbuf,LINBUFSIZ);
10802               }
10803               if ((x = cmcfm()) < 0) return(x);
10804
10805 #ifndef SSHTEST
10806               x = sshkey_change_passphrase(line[0] ? line : NULL,
10807                                              oldp, newp);
10808 #endif /* SSHTEST */
10809               makestr(&oldp,NULL);
10810               makestr(&newp,NULL);
10811               success = (x == 0);
10812               return(success);
10813             }
10814             case SSHK_CREA: {   /* SSH KEY CREATE /switches... */
10815               int bits = 1024, keytype = SSHKT_2R;
10816               char * pass = NULL, * comment = NULL;
10817               struct FDB df, sw;
10818
10819               /*
10820                * char * sshkey_default_file(int keytype) 
10821                * will provide the default filename for a given keytype
10822                * is it possible to have the default value for the 2nd
10823                * FDB set and changed when a /TYPE switch is provided?
10824                * Would this allow for tab completion of the filename?
10825                */
10826               cmfdbi(&sw,
10827                      _CMKEY,            /* fcode */
10828                      "Filename, or switch", /* hlpmsg */
10829                      "",                /* default */
10830                      "",                /* addtl string data */
10831                      nsshkcrea,         /* addtl numeric data 1: tbl size */
10832                      4,                 /* addtl numeric data 2: 4 = cmswi */
10833                      xxstring,          /* Processing function */
10834                      sshkcrea,          /* Keyword table */
10835                      &df                /* Pointer to next FDB */
10836                      );
10837               cmfdbi(&df,               /* 2nd FDB - file for display */
10838                      _CMOFI,            /* output file */
10839                      "",                /* hlpmsg */
10840                      "",                /* default */
10841                      "",                /* addtl string data */
10842                      0,                 /* addtl numeric data 1 */
10843                      0,                 /* addtl numeric data 2 */
10844                      xxstring,
10845                      NULL,
10846                      NULL
10847                      );
10848               line[0] = NUL;
10849
10850               while (1) {
10851                   x = cmfdb(&sw);
10852                   if (x == -3) break;
10853                   if (x < 0)
10854                     return(x);
10855                   if (cmresult.fcode != _CMKEY)
10856                     break;
10857                   if (!cmgbrk()) {
10858                       printf("?This switch requires an argument\n");
10859                       return(-9);
10860                   }
10861                   switch (cmresult.nresult) {
10862                     case SSHKC_BI:      /* /BITS:n */
10863                       if ((y = cmnum("","1024",10,&z,xxstring)) < 0)
10864                         return(y);
10865                       if (z < 512 || z > 4096) {
10866                           printf("?Out range - min: 512, max: 4096\n");
10867                           return(-9);
10868                       }
10869                       bits = z;
10870                       break;
10871                     case SSHKC_PP:      /* /PASSPHRASE:blah */
10872                       if ((y = cmfld("Passphrase","",&s,xxstring)) < 0)
10873                         return(y);
10874                       makestr(&pass,s);
10875                       break;
10876                     case SSHKC_TY:      /* /TYPE:keyword */
10877                       if ((y = cmkey(sshkcty,nsshkcty,"",
10878                                      "v2-rsa",xxstring)) < 0)
10879                         return(y);
10880                       keytype = y;
10881                       break;
10882                     case SSHKC_1R:      /* /COMMENT */
10883                       if ((y = cmfld("Text","",&s,xxstring)) < 0)
10884                         return(y);
10885                       makestr(&comment,s);
10886                       break;
10887                   }
10888               }
10889               if (cmresult.fcode == _CMOFI) { /* Filename */
10890                   if (cmresult.sresult) {
10891                       ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
10892                       if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
10893                           ckstrncpy(line,tmpbuf,LINBUFSIZ);
10894                   }
10895               }
10896               if ((y = cmcfm()) < 0) /* Confirm */
10897                 return(y);
10898 #ifndef SSHTEST
10899               x = sshkey_create(line[0] ? line : NULL,
10900                                 bits, pass, keytype, comment);
10901               if (pass)
10902                 memset(pass,0,strlen(pass));
10903 #endif /* SSHTEST */
10904               makestr(&pass,NULL);
10905               makestr(&comment,NULL);
10906               return(success = (x == 0));
10907             }
10908             case SSHK_DISP: {   /* SSH KEY DISPLAY /switches... */
10909               char c;
10910               int infmt = 0, outfmt = 0;
10911               struct FDB df, sw;
10912               cmfdbi(&sw,
10913                      _CMKEY,            /* fcode */
10914                      "Filename, or switch", /* hlpmsg */
10915                      "",                /* default */
10916                      "",                /* addtl string data */
10917                      nsshdswi,          /* addtl numeric data 1: tbl size */
10918                      4,                 /* addtl numeric data 2: 4 = cmswi */
10919                      xxstring,          /* Processing function */
10920                      sshdswi,           /* Keyword table */
10921                      &df                /* Pointer to next FDB */
10922                      );
10923               cmfdbi(&df,               /* 2nd FDB - file for display */
10924                      _CMIFI,            /* fcode */
10925                      "",                /* hlpmsg */
10926                      "",                /* default */
10927                      "",                /* addtl string data */
10928                      0,                 /* addtl numeric data 1 */
10929                      0,                 /* addtl numeric data 2 */
10930                      xxstring,
10931                      NULL,
10932                      NULL
10933                      );
10934               line[0] = NUL;
10935
10936               while (1) {
10937                   x = cmfdb(&sw);
10938                   if (x == -3) break;
10939                   if (x < 0)
10940                     return(x);
10941                   if (cmresult.fcode != _CMKEY)
10942                     break;
10943                   if (!cmgbrk()) {
10944                       printf("?This switch requires an argument\n");
10945                       return(-9);
10946                   }
10947                   switch (cmresult.nresult) {
10948 #ifdef COMMENT
10949                     case SSHKD_IN:      /* /IN-FORMAT: */
10950                       if ((y = cmkey(sshdifmt,nsshdifmt,
10951                                      "","",xxstring)) < 0)
10952                         return(y);
10953                       infmt = y;
10954                       break;
10955 #endif /* COMMENT */
10956                     case SSHKD_OUT:     /* /FORMAT: */
10957                       if ((y = cmkey(sshdofmt,nsshdofmt,
10958                                      "","",xxstring)) < 0)
10959                         return(y);
10960                       outfmt = y;
10961                       break;
10962                   }
10963               }
10964               if (cmresult.fcode == _CMIFI) { /* Filename */
10965                   ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
10966                   if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
10967                     ckstrncpy(line,tmpbuf,LINBUFSIZ);
10968               }
10969 #ifdef COMMENT
10970               if (!line[0]) {
10971                   printf("?Key filename required\n");
10972                   return(-9);
10973               }
10974 #endif /* COMMENT */
10975               if ((y = cmcfm()) < 0) /* Confirm */
10976                 return(y);
10977 #ifndef SSHTEST
10978               switch (outfmt) {
10979                 case SKDF_OSSH:
10980                   /* 2nd param is optional passphrase */
10981                   x = sshkey_display_public(line[0] ? line : NULL, NULL);
10982                   break;
10983                 case SKDF_SSHC:
10984                   /* 2nd param is optional passphrase */
10985                   x = sshkey_display_public_as_ssh2(line[0] ? line : NULL,
10986                                                     NULL);
10987                   break;
10988                 case SKDF_IETF:
10989                   x = sshkey_display_fingerprint(line[0] ? line : NULL, 1);
10990                   break;
10991                 case SKDF_FING:
10992                   x = sshkey_display_fingerprint(line[0] ? line : NULL, 0);
10993                   break;
10994               }
10995 #endif /* SSHTEST */
10996               return(success = (x == 0));
10997             }
10998             case SSHK_V1:               /* SSH KEY V1 SET-COMMENT */
10999               if ((x = cmkey(sshkv1,1,"","set-comment", xxstring)) < 0)
11000                 return(x);
11001               if (x != 1) return(-2);
11002               if ((x = cmifi("Key file name","",&s,&y,xxstring)) < 0) {
11003                   if (x == -3) {
11004                       printf("?Name of key file required\n");
11005                       return(-9);
11006                   }
11007               }
11008               ckstrncpy(line,s,LINBUFSIZ);
11009               if ((x = cmtxt("Comment text","",&s,xxstring)) < 0)
11010                 return(x);
11011 #ifndef SSHTEST
11012               x = sshkey_v1_change_comment(line,  /* filename */
11013                                            s,     /* new comment */
11014                                            NULL   /* passphrase */
11015                                            );
11016 #endif /* SSHTEST */
11017               success = (x == 0);
11018               return(success);
11019           }
11020           default:
11021             return(-2);
11022         }
11023 #else  /* SSHBUILTIN */
11024 #ifdef SSHCMD
11025         x = nettype;
11026         if ((y = setlin(XXSSH,0,1)) < 0) {
11027             if (errno)
11028               printf("?%s\n",ck_errstr());
11029             else
11030 #ifdef COMMENT
11031             /* This isn't right either because it catches command editing */
11032               printf("?Sorry, pseudoterminal open failed\n");
11033             if (hints)
11034               printf("Hint: Try \"ssh -t %s\"\n",line);
11035 #else
11036               return(y);
11037 #endif /* COMMENT */
11038             nettype = x;                /* Failed, restore net type. */
11039             ttnproto = z;               /* and protocol */
11040             success = 0;
11041         }
11042         didsetlin++;
11043         netsave = x;
11044         return(y);
11045 #endif /* SSHCMD */
11046 #endif /* SSHBUILTIN */
11047     }
11048 #endif /* ANYSSH */
11049
11050 #ifdef SSHBUILTIN
11051     if (cx == XXSKRM) {                 /* SKERMIT (Secure Shell Kermit) */
11052         extern int netsave;
11053         int k, x, havehost = 0, trips = 0;
11054         int    tmpver = -1, tmpxfw = -1;
11055 #ifndef SSHTEST
11056         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
11057         extern int sl_ssh_ver, sl_ssh_ver_saved;
11058 #endif /* SSHTEST */
11059         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
11060         extern char * slmsg;
11061         extern char uidbuf[], sl_uidbuf[];
11062         extern char pwbuf[], * g_pswd;
11063         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
11064         struct FDB sw, kw, fl;
11065
11066         if (ssh_tmpstr)
11067           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11068         makestr(&ssh_tmpstr,NULL);
11069         makestr(&ssh_tmpuid,NULL);
11070         makestr(&ssh_tmpcmd,NULL);
11071         makestr(&ssh_tmpport,NULL);
11072
11073         cmfdbi(&kw,                     /* 1st FDB - commands */
11074                _CMKEY,                  /* fcode */
11075                "host [ port ],\n or action", /* hlpmsg */
11076                "",                      /* default */
11077                "",                      /* addtl string data */
11078                nsshkermit,              /* addtl numeric data 1: tbl size */
11079                0,                       /* addtl numeric data 2: 0 = keyword */
11080                xxstring,                /* Processing function */
11081                sshkermit,               /* Keyword table */
11082                &fl                      /* Pointer to next FDB */
11083                );
11084         cmfdbi(&fl,                     /* Host */
11085                _CMFLD,                  /* fcode */
11086                "",                      /* hlpmsg */
11087                "",                      /* default */
11088                "",                      /* addtl string data */
11089                0,                       /* addtl numeric data 1 */
11090                0,                       /* addtl numeric data 2 */
11091                xxstring,
11092                NULL,
11093                NULL
11094                );
11095
11096         x = cmfdb(&kw);
11097         if (x == -3) {
11098             printf("?skermit what?\n");
11099             return(-9);
11100         }
11101         if (x < 0)
11102           return(x);
11103         havehost = 0;
11104         if (cmresult.fcode == _CMFLD) {
11105             havehost = 1;
11106             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
11107             cmresult.nresult = SKRM_OPN;
11108         }
11109         switch (cmresult.nresult) {     /* SSH keyword */
11110           case SKRM_OPN:                /* SSH OPEN */
11111             if (!havehost) {
11112                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
11113                   return(x);
11114                 ckstrncpy(line,s,LINBUFSIZ);
11115             }
11116             /* Parse [ port ] [ switches ] */
11117             cmfdbi(&kw,                 /* Switches */
11118                    _CMKEY,
11119                    "Port number or service name,\nor switch",
11120                    "",
11121                    "",
11122                    nsshkrmopnsw,
11123                    4,
11124                    xxstring,
11125                    sshkrmopnsw,
11126                    &fl
11127                    );
11128             cmfdbi(&fl,                 /* Port number or service name */
11129                    _CMFLD,
11130                    "",
11131                    "",
11132                    "",
11133                    0,
11134                    0,
11135                    xxstring,
11136                    NULL,
11137                    NULL
11138                    );
11139             trips = 0;                  /* Explained below */
11140             while (1) {                 /* Parse port and switches */
11141                 x = cmfdb(&kw);         /* Get a field */
11142                 if (x == -3)            /* User typed CR so quit from loop */
11143                   break;
11144                 if (x < 0)              /* Other parse error, pass it back */
11145                   return(x);
11146                 switch (cmresult.fcode) { /* Field or Keyword? */
11147                   case _CMFLD:            /* Field */
11148                     makestr(&ssh_tmpport,cmresult.sresult);
11149                     break;
11150                   case _CMKEY:          /* Keyword */
11151                     switch (cmresult.nresult) { /* Which one? */
11152                       case SSHSW_USR:           /* /USER: */
11153                         if (!cmgbrk()) {
11154                             printf("?This switch requires an argument\n");
11155                             return(-9);
11156                         }
11157                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
11158                           return(y);
11159                         s = brstrip(s);
11160                         makestr(&ssh_tmpuid,s);
11161                         break;
11162                       case SSHSW_PWD:
11163                         if (!cmgbrk()) {
11164                             printf("?This switch requires an argument\n");
11165                             return(-9);
11166                         }
11167                         debok = 0;
11168                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
11169                             if (x == -3) {
11170                                 makestr(&ssh_tmpstr,"");
11171                             } else {
11172                                 return(x);
11173                             }
11174                         } else {
11175                             s = brstrip(s);
11176                             if ((x = (int)strlen(s)) > PWBUFL) {
11177                                 makestr(&slmsg,"Internal error");
11178                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
11179                                 return(-9);
11180                             }
11181                             makestr(&ssh_tmpstr,s);
11182                         }
11183                         break;
11184
11185                     case SSHSW_VER:
11186                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
11187                           return(x);
11188                         if (z < 1 || z > 2) {
11189                             printf("?Out of range: %d\n",z);
11190                             return(-9);
11191                         }
11192                         tmpver = z;
11193                         break;
11194                     default:
11195                         return(-2);
11196                     }
11197                   }
11198                 if (trips++ == 0) {     /* After first time through */
11199                     cmfdbi(&kw,         /* only parse switches, not port. */
11200                            _CMKEY,
11201                            "Switch",
11202                            "",
11203                            "",
11204                            nsshkrmopnsw,
11205                            4,
11206                            xxstring,
11207                            sshkrmopnsw,
11208                            NULL
11209                            );
11210                 }
11211             }
11212             if ((x = cmcfm()) < 0)      /* Get confirmation */
11213               return(x);
11214               if (clskconnx(1) < 0) {   /* Close current Kermit connection */
11215                   if ( ssh_tmpstr ) {
11216                       memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11217                       makestr(&ssh_tmpstr,NULL);
11218                   }
11219                   return(success = 0);
11220               }
11221               makestr(&ssh_hst,line);   /* Stash everything */
11222               if (ssh_tmpuid) {
11223                   if (!sl_uid_saved) {
11224                       ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
11225                       sl_uid_saved = 1;
11226                   }
11227                   ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
11228                   makestr(&ssh_tmpuid,NULL);
11229               }
11230               if (ssh_tmpport) {
11231                   makestr(&ssh_prt,ssh_tmpport);
11232                   makestr(&ssh_tmpport,NULL);
11233               } else
11234                   makestr(&ssh_prt,NULL);
11235
11236               /* Set the Subsystem to Kermit */
11237               ssh_cas = 1;
11238               makestr(&ssh_cmd,"kermit");
11239
11240               if (tmpver > -1) {
11241 #ifndef SSHTEST
11242                   if (!sl_ssh_ver_saved) {
11243                       sl_ssh_ver = ssh_ver;
11244                       sl_ssh_ver_saved = 1;
11245                   }
11246 #endif /* SSHTEST */
11247                   ssh_ver = tmpver;
11248               }
11249               /* Disable X11 Forwarding */
11250 #ifndef SSHTEST
11251               if (!sl_ssh_xfw_saved) {
11252                   sl_ssh_xfw = ssh_xfw;
11253                   sl_ssh_xfw_saved = 1;
11254               }
11255 #endif /* SSHTEST */
11256               ssh_xfw = 0;
11257
11258               if (ssh_tmpstr) {
11259                   if (ssh_tmpstr[0]) {
11260                       ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
11261                       pwflg = 1;
11262                       pwcrypt = 0;
11263                   } else
11264                       pwflg = 0;
11265                   makestr(&ssh_tmpstr,NULL);
11266               }
11267               nettype = NET_SSH;
11268               if (mdmsav < 0)
11269                   mdmsav = mdmtyp;
11270               mdmtyp = -nettype;
11271               x = 1;
11272
11273 #ifndef NOSPL
11274             makestr(&g_pswd,pwbuf);     /* Save global pwbuf */
11275             g_pflg = pwflg;             /* and flag */
11276             g_pcpt = pwcrypt;
11277 #endif /* NOSPL */
11278
11279             /* Line parameter to ttopen() is ignored */
11280             k = ttopen(line,&x,mdmtyp, 0);
11281             if (k < 0) {
11282                 printf("?Unable to connect to %s\n",ssh_hst);
11283                 mdmtyp = mdmsav;
11284                 slrestor();
11285                 return(success = 0);
11286             }
11287             duplex = 0;             /* Remote echo */
11288             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
11289             debug(F110,"ssh ttname",ttname,0);
11290             makestr(&slmsg,NULL);       /* No SET LINE error message */
11291             cxtype = CXT_SSH;
11292 #ifndef NODIAL
11293             dialsta = DIA_UNK;
11294 #endif /* NODIAL */
11295             success = 1;                /* SET LINE succeeded */
11296             network = 1;                /* Network connection (not serial) */
11297             local = 1;                  /* Local mode (not remote) */
11298             if ((reliable != SET_OFF || !setreliable))
11299               reliable = SET_ON;        /* Transport is reliable end to end */
11300 #ifdef OS2
11301             DialerSend(OPT_KERMIT_CONNECT, 0);
11302 #endif /* OS2 */
11303             setflow();                  /* Set appropriate flow control */
11304
11305             haveline = 1;
11306 #ifdef CKLOGDIAL
11307 #ifdef NETCONN
11308             dolognet();
11309 #endif /* NETCONN */
11310 #endif /* CKLOGDIAL */
11311
11312 #ifndef NOSPL
11313             if (local) {
11314                 if (nmac) {             /* Any macros defined? */
11315                     int k;              /* Yes */
11316                     k = mlook(mactab,"on_open",nmac); /* Look this up */
11317                     if (k >= 0) {                     /* If found, */
11318                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
11319                           parser(1);                  /* and execute it */
11320                     }
11321                 }
11322             }
11323 #endif /* NOSPL */
11324 #ifdef LOCUS            
11325             if (autolocus)
11326                 setlocus(1,1);
11327 #endif /* LOCUS */
11328
11329         /* Command was confirmed so we can pre-pop command level. */
11330         /* This is so CONNECT module won't think we're executing a */
11331         /* script if CONNECT was the final command in the script. */
11332             if (cmdlvl > 0)
11333               prepop();
11334             return(success = 1);
11335
11336           default:
11337             return(-2);
11338         }
11339     }
11340 #endif /* SSHBUILTIN */
11341
11342 #ifdef SFTP_BUILTIN
11343     if (cx == XXSFTP) {                 /* SFTP (Secure Shell File Transfer) */
11344         extern int netsave;
11345         int k, x, havehost = 0, trips = 0;
11346         int    tmpver = -1, tmpxfw = -1;
11347 #ifndef SSHTEST
11348         extern int sl_ssh_xfw, sl_ssh_xfw_saved;
11349         extern int sl_ssh_ver, sl_ssh_ver_saved;
11350 #endif /* SSHTEST */
11351         extern int mdmtyp, mdmsav, cxtype, sl_uid_saved;
11352         extern char * slmsg;
11353         extern char uidbuf[], sl_uidbuf[];
11354         extern char pwbuf[], * g_pswd;
11355         extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
11356         struct FDB sw, kw, fl;
11357
11358         if (ssh_tmpstr)
11359           memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11360         makestr(&ssh_tmpstr,NULL);
11361         makestr(&ssh_tmpuid,NULL);
11362         makestr(&ssh_tmpcmd,NULL);
11363         makestr(&ssh_tmpport,NULL);
11364
11365         cmfdbi(&kw,                     /* 1st FDB - commands */
11366                _CMKEY,                  /* fcode */
11367                "host [ port ],\n or action", /* hlpmsg */
11368                "",                      /* default */
11369                "",                      /* addtl string data */
11370                nsftpkwtab,              /* addtl numeric data 1: tbl size */
11371                0,                       /* addtl numeric data 2: 0 = keyword */
11372                xxstring,                /* Processing function */
11373                sftpkwtab,               /* Keyword table */
11374                &fl                      /* Pointer to next FDB */
11375                );
11376         cmfdbi(&fl,                     /* Host */
11377                _CMFLD,                  /* fcode */
11378                "",                      /* hlpmsg */
11379                "",                      /* default */
11380                "",                      /* addtl string data */
11381                0,                       /* addtl numeric data 1 */
11382                0,                       /* addtl numeric data 2 */
11383                xxstring,
11384                NULL,
11385                NULL
11386                );
11387
11388         x = cmfdb(&kw);
11389         if (x == -3) {
11390             printf("?sftp what?\n");
11391             return(-9);
11392         }
11393         if (x < 0)
11394           return(x);
11395         havehost = 0;
11396         if (cmresult.fcode == _CMFLD) {
11397             havehost = 1;
11398             ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Hostname */
11399             cmresult.nresult = SFTP_OPN;
11400         }
11401         switch (cmresult.nresult) {     /* SFTP keyword */
11402           case SFTP_OPN:                /* SFTP OPEN */
11403             if (!havehost) {
11404                 if ((x = cmfld("Host","",&s,xxstring)) < 0)
11405                   return(x);
11406                 ckstrncpy(line,s,LINBUFSIZ);
11407             }
11408             /* Parse [ port ] [ switches ] */
11409             cmfdbi(&kw,                 /* Switches */
11410                    _CMKEY,
11411                    "Port number or service name,\nor switch",
11412                    "",
11413                    "",
11414                    nsshkrmopnsw,
11415                    4,
11416                    xxstring,
11417                    sshkrmopnsw,
11418                    &fl
11419                    );
11420             cmfdbi(&fl,                 /* Port number or service name */
11421                    _CMFLD,
11422                    "",
11423                    "",
11424                    "",
11425                    0,
11426                    0,
11427                    xxstring,
11428                    NULL,
11429                    NULL
11430                    );
11431             trips = 0;                  /* Explained below */
11432             while (1) {                 /* Parse port and switches */
11433                 x = cmfdb(&kw);         /* Get a field */
11434                 if (x == -3)            /* User typed CR so quit from loop */
11435                   break;
11436                 if (x < 0)              /* Other parse error, pass it back */
11437                   return(x);
11438                 switch (cmresult.fcode) { /* Field or Keyword? */
11439                   case _CMFLD:            /* Field */
11440                     makestr(&ssh_tmpport,cmresult.sresult);
11441                     break;
11442                   case _CMKEY:          /* Keyword */
11443                     switch (cmresult.nresult) { /* Which one? */
11444                       case SSHSW_USR:           /* /USER: */
11445                         if (!cmgbrk()) {
11446                             printf("?This switch requires an argument\n");
11447                             return(-9);
11448                         }
11449                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
11450                           return(y);
11451                         s = brstrip(s);
11452                         makestr(&ssh_tmpuid,s);
11453                         break;
11454                       case SSHSW_PWD:
11455                         if (!cmgbrk()) {
11456                             printf("?This switch requires an argument\n");
11457                             return(-9);
11458                         }
11459                         debok = 0;
11460                         if ((x = cmfld("Password","",&s,xxstring)) < 0) {
11461                             if (x == -3) {
11462                                 makestr(&ssh_tmpstr,"");
11463                             } else {
11464                                 return(x);
11465                             }
11466                         } else {
11467                             s = brstrip(s);
11468                             if ((x = (int)strlen(s)) > PWBUFL) {
11469                                 makestr(&slmsg,"Internal error");
11470                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
11471                                 return(-9);
11472                             }
11473                             makestr(&ssh_tmpstr,s);
11474                         }
11475                         break;
11476
11477                     case SSHSW_VER:
11478                         if ((x = cmnum("Number","",10,&z,xxstring)) < 0)
11479                           return(x);
11480                         if (z < 1 || z > 2) {
11481                             printf("?Out of range: %d\n",z);
11482                             return(-9);
11483                         }
11484                         tmpver = z;
11485                         break;
11486                     default:
11487                         return(-2);
11488                     }
11489                 }
11490                 if (trips++ == 0) {     /* After first time through */
11491                     cmfdbi(&kw,         /* only parse switches, not port. */
11492                            _CMKEY,
11493                            "Switch",
11494                            "",
11495                            "",
11496                            nsshkrmopnsw,
11497                            4,
11498                            xxstring,
11499                            sshkrmopnsw,
11500                            NULL
11501                            );
11502                 }
11503             }
11504             if ((x = cmcfm()) < 0)      /* Get confirmation */
11505               return(x);
11506               if (clskconnx(1) < 0) {   /* Close current Kermit connection */
11507                   if ( ssh_tmpstr ) {
11508                       memset(ssh_tmpstr,0,strlen(ssh_tmpstr));
11509                       makestr(&ssh_tmpstr,NULL);
11510                   }
11511                   return(success = 0);
11512               }
11513               makestr(&ssh_hst,line);   /* Stash everything */
11514               if (ssh_tmpuid) {
11515                   if (!sl_uid_saved) {
11516                       ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
11517                       sl_uid_saved = 1;
11518                   }
11519                   ckstrncpy(uidbuf,ssh_tmpuid,UIDBUFLEN);
11520                   makestr(&ssh_tmpuid,NULL);
11521               }
11522               if (ssh_tmpport) {
11523                   makestr(&ssh_prt,ssh_tmpport);
11524                   makestr(&ssh_tmpport,NULL);
11525               } else
11526                   makestr(&ssh_prt,NULL);
11527
11528               /* Set the Subsystem to Kermit */
11529               ssh_cas = 1;
11530               makestr(&ssh_cmd,"sftp");
11531
11532               if (tmpver > -1) {
11533 #ifndef SSHTEST
11534                   if (!sl_ssh_ver_saved) {
11535                       sl_ssh_ver = ssh_ver;
11536                       sl_ssh_ver_saved = 1;
11537                   }
11538 #endif /* SSHTEST */
11539                   ssh_ver = tmpver;
11540               }
11541               /* Disable X11 Forwarding */
11542 #ifndef SSHTEST
11543               if (!sl_ssh_xfw_saved) {
11544                   sl_ssh_xfw = ssh_xfw;
11545                   sl_ssh_xfw_saved = 1;
11546               }
11547 #endif /* SSHTEST */
11548               ssh_xfw = 0;
11549
11550               if (ssh_tmpstr) {
11551                   if (ssh_tmpstr[0]) {
11552                       ckstrncpy(pwbuf,ssh_tmpstr,PWBUFL+1);
11553                       pwflg = 1;
11554                       pwcrypt = 0;
11555                   } else
11556                       pwflg = 0;
11557                   makestr(&ssh_tmpstr,NULL);
11558               }
11559               nettype = NET_SSH;
11560               if (mdmsav < 0)
11561                   mdmsav = mdmtyp;
11562               mdmtyp = -nettype;
11563               x = 1;
11564
11565 #ifndef NOSPL
11566             makestr(&g_pswd,pwbuf);             /* Save global pwbuf */
11567             g_pflg = pwflg;                     /* and flag */
11568             g_pcpt = pwcrypt;
11569 #endif /* NOSPL */
11570
11571             /* Line parameter to ttopen() is ignored */
11572             k = ttopen(line,&x,mdmtyp, 0);
11573             if (k < 0) {
11574                 printf("?Unable to connect to %s\n",ssh_hst);
11575                 mdmtyp = mdmsav;
11576                 slrestor();
11577                 return(success = 0);
11578             }
11579             duplex = 0;             /* Remote echo */
11580             ckstrncpy(ttname,line,TTNAMLEN); /* Record the command */
11581             debug(F110,"ssh ttname",ttname,0);
11582             makestr(&slmsg,NULL);       /* No SET LINE error message */
11583             cxtype = CXT_SSH;
11584 #ifndef NODIAL
11585             dialsta = DIA_UNK;
11586 #endif /* NODIAL */
11587             success = 1;                /* SET LINE succeeded */
11588             network = 1;                /* Network connection (not serial) */
11589             local = 1;                  /* Local mode (not remote) */
11590             if ((reliable != SET_OFF || !setreliable))
11591               reliable = SET_ON;        /* Transport is reliable end to end */
11592 #ifdef OS2
11593             DialerSend(OPT_KERMIT_CONNECT, 0);
11594 #endif /* OS2 */
11595             setflow();                  /* Set appropriate flow control */
11596
11597             haveline = 1;
11598 #ifdef CKLOGDIAL
11599 #ifdef NETCONN
11600             dolognet();
11601 #endif /* NETCONN */
11602 #endif /* CKLOGDIAL */
11603
11604 #ifndef NOSPL
11605             if (local) {
11606                 if (nmac) {             /* Any macros defined? */
11607                     int k;              /* Yes */
11608                     k = mlook(mactab,"on_open",nmac); /* Look this up */
11609                     if (k >= 0) {                     /* If found, */
11610                         if (dodo(k,ssh_hst,0) > -1)   /* set it up, */
11611                           parser(1);                  /* and execute it */
11612                     }
11613                 }
11614             }
11615 #endif /* NOSPL */
11616 #ifdef LOCUS            
11617             if (autolocus)
11618                 setlocus(1,1);
11619 #endif /* LOCUS */
11620
11621         /* Command was confirmed so we can pre-pop command level. */
11622         /* This is so CONNECT module won't think we're executing a */
11623         /* script if CONNECT was the final command in the script. */
11624             if (cmdlvl > 0)
11625               prepop();
11626
11627             success = sftp_do_init();
11628             return(success = 1);
11629
11630           case SFTP_CD:
11631           case SFTP_CHGRP:
11632           case SFTP_CHMOD:
11633           case SFTP_CHOWN:
11634           case SFTP_RM:
11635           case SFTP_DIR:
11636           case SFTP_GET:
11637           case SFTP_MKDIR:
11638           case SFTP_PUT:
11639           case SFTP_PWD:
11640           case SFTP_REN:
11641           case SFTP_RMDIR:
11642           case SFTP_LINK:
11643           case SFTP_VER:
11644             if ((y = cmtxt("command parameters","",&s,xxstring)) < 0) 
11645               return(y);
11646             if (ssh_tchk() < 0 || !ssh_cas || strcmp(ssh_cmd,"sftp")) {
11647                 printf("?Not connected to SFTP Service\n");
11648                 return(success = 0);
11649             }
11650             success = sftp_do_cmd(cmresult.nresult,s);
11651             return(success);
11652           default:
11653             return(-2);
11654         }
11655     }
11656 #endif /* SFTP_BUILTIN */
11657
11658     if (cx == XXRLOG) {                 /* RLOGIN */
11659 #ifdef RLOGCODE
11660         int x,z;
11661 #ifdef OS2
11662         if (!tcp_avail) {
11663             printf("?Sorry, either TCP/IP is not available on this system or\n\
11664 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n"
11665                    );
11666             success = 0;
11667             return(-9);
11668         } else {
11669 #endif /* OS2 */
11670             x = nettype;                /* Save net type in case of failure */
11671             z = ttnproto;               /* Save protocol in case of failure */
11672             nettype = NET_TCPB;
11673             ttnproto = NP_RLOGIN;
11674             if ((y = setlin(XYHOST,0,1)) <= 0) {
11675                 nettype = x;            /* Failed, restore net type. */
11676                 ttnproto = z;           /* and protocol */
11677                 success = 0;
11678             }
11679             didsetlin++;
11680 #ifdef OS2
11681         }
11682 #endif /* OS2 */
11683         return(y);
11684 #else
11685         printf("?Sorry, RLOGIN is not configured in this copy of C-Kermit.\n");
11686         return(-9);
11687 #endif /* RLOGCODE */
11688     }
11689 #endif /* NETCONN */
11690 #endif /* NOLOCAL */
11691
11692 #ifndef NOXMIT
11693     if (cx == XXTRA) {                  /* TRANSMIT */
11694         extern int xfrxla;
11695         int i, n, xpipe = 0, xbinary = 0, xxlate = 1, xxnowait = 0, getval;
11696         int xxecho = 0;
11697         int scan = 1;
11698         char c;
11699         struct FDB sf, sw, tx;          /* FDBs for parse functions */
11700 #ifndef NOCSETS
11701         extern int tcs_transp;          /* Term charset is transparent */
11702 #else
11703         int tcs_transp = 1;
11704 #endif /* NOCSETS */
11705
11706 #ifdef COMMENT
11707         xbinary = binary;               /* Default text/binary mode */
11708 #else
11709         xbinary = 0;                    /* Default is text */
11710 #endif /* COMMENT */
11711         xxecho = xmitx;
11712
11713         cmfdbi(&sw,                     /* First FDB - command switches */
11714                _CMKEY,                  /* fcode */
11715                "Filename, or switch",   /* hlpmsg */
11716                "",                      /* default */
11717                "",                      /* addtl string data */
11718                nxmitsw,                 /* addtl numeric data 1: tbl size */
11719                4,                       /* addtl numeric data 2: 4 = cmswi */
11720                xxstring,                /* Processing function */
11721                xmitsw,                  /* Keyword table */
11722                &sf                      /* Pointer to next FDB */
11723                );
11724         cmfdbi(&sf,                     /* 2nd FDB - file to send */
11725                _CMIFI,                  /* fcode */
11726                "File to transmit",      /* hlpmsg */
11727                "",                      /* default */
11728                "",                      /* addtl string data */
11729                0,                       /* addtl numeric data 1 */
11730                0,                       /* addtl numeric data 2 */
11731                xxstring,
11732                NULL,
11733 #ifdef PIPESEND
11734                &tx
11735 #else
11736                NULL
11737 #endif /* PIPESEND */
11738                );
11739 #ifdef PIPESEND
11740         cmfdbi(&tx,
11741                _CMTXT,                  /* fcode */
11742                "Command",               /* hlpmsg */
11743                "",                      /* default */
11744                "",                      /* addtl string data */
11745                0,                       /* addtl numeric data 1 */
11746                0,                       /* addtl numeric data 2 */
11747                xxstring,
11748                NULL,
11749                NULL
11750                );
11751 #endif /* PIPESEND */
11752
11753         while (1) {
11754             x = cmfdb(&sw);
11755             if (x < 0)
11756               return(x);
11757             if (cmresult.fcode != _CMKEY)
11758               break;
11759             c = cmgbrk();               /* Have switch, get break character */
11760             if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
11761                 printf("?This switch does not take an argument\n");
11762                 return(-9);
11763             }
11764             if (!getval && (cmgkwflgs() & CM_ARG)) {
11765                 printf("?This switch requires an argument\n");
11766                 return(-9);
11767             }
11768             n = cmresult.nresult;       /* Numeric result = switch ID */
11769             switch (n) {                /* Process the switch */
11770 #ifdef PIPESEND
11771               case XMI_CMD:             /* Transmit from a command */
11772                 if (nopush) {
11773                     printf("?Sorry, system command access is disabled\n");
11774                     return(-9);
11775                 }
11776                 sw.hlpmsg = "Command, or switch"; /* Change help message */
11777                 xpipe = 1;              /* (No way to undo this one) */
11778                 break;
11779 #endif /* PIPESEND */
11780
11781               case XMI_BIN:             /* Binary */
11782                 xbinary = 1;
11783                 xxlate = 0;             /* Don't translate charsets */
11784                 scan = 0;
11785                 break;
11786
11787               case XMI_TXT:             /* Text */
11788                 xbinary = 0;
11789                 xxlate = !tcs_transp;   /* Translate if TERM CHAR not TRANSP */
11790                 scan = 0;
11791                 break;
11792
11793               case XMI_TRA:             /* Transparent text */
11794                 xbinary = 0;
11795                 xxlate = 0;             /* But don't translate charsets */
11796                 scan = 0;
11797                 break;
11798
11799 #ifdef COMMENT
11800               case XMI_VRB:             /* /VERBOSE */
11801               case XMI_QUI:             /* /QUIET */
11802                 break;                  /* (not implemented yet) */
11803 #endif /* COMMENT */
11804
11805               case XMI_NOW:             /* /NOWAIT */
11806                 xxnowait = 1;
11807                 break;
11808
11809               case XMI_NOE:             /* /NOWAIT */
11810                 xxecho = 0;
11811                 break;
11812
11813               default:
11814                 return(-2);
11815             }
11816
11817         }
11818         if (cmresult.fcode != _CMIFI && cmresult.fcode != _CMTXT)
11819           return(-2);
11820         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Filename */
11821         if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
11822           ckstrncpy(line,tmpbuf,LINBUFSIZ);
11823         s = line;
11824         if ((y = cmcfm()) < 0)          /* Confirm */
11825           return(y);
11826 #ifdef CK_APC
11827         if ((apcactive == APC_LOCAL) ||
11828             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
11829           return(success = 0);
11830 #endif /* CK_APC */
11831         if (cmresult.nresult != 0) {
11832             printf("?Only a single file may be transmitted\n");
11833             return(-9);
11834         }
11835 #ifdef PIPESEND
11836         if (xpipe) {
11837             s = brstrip(s);
11838             if (!*s) {
11839                 printf("?Sorry, a command to send from is required\n");
11840                 return(-9);
11841             }
11842             pipesend = 1;
11843         }
11844 #endif /* PIPESEND */
11845
11846         if (scan && (filepeek
11847 #ifndef NOXFER
11848                      || patterns
11849 #endif /* NOXFER */
11850                      )) {               /* If user didn't specify type */
11851             int k, x;                         /* scan the file to see */
11852             x = -1;
11853             k = scanfile(s,&x,nscanfile);
11854             if (k > 0) xbinary = (k == FT_BIN) ? XYFT_B : XYFT_T;
11855         }
11856         if (!xfrxla) xxlate = 0;
11857         success = transmit(s,
11858                            (char) (xxnowait ? '\0' : (char)xmitp),
11859                            xxlate,
11860                            xbinary,
11861                            xxecho
11862                            );
11863         return(success);
11864     }
11865 #endif /* NOXMIT */
11866
11867 #ifndef NOFRILLS
11868     if (cx == XXTYP  || cx == XXCAT || cx == XXMORE ||
11869         cx == XXHEAD || cx == XXTAIL) {
11870         int paging = 0, havename = 0, head = 0, width = 0;
11871         int height = 0, count = 0;
11872         char pfxbuf[64], * prefix = NULL;
11873         char outfile[CKMAXPATH+1];
11874         struct FDB sf, sw;
11875         char * pat = NULL;
11876         int incs = 0, outcs = 0, cset = -1, number = 0;
11877 #ifdef UNICODE
11878         char * tocs = "";
11879         extern int fileorder;
11880 #ifdef OS2
11881 #ifdef NT
11882         char guibuf[128], * gui_title = NULL;
11883         int  gui = 0;
11884 #endif /* NT */
11885 #ifndef NOCSETS
11886         extern int tcsr, tcsl;
11887 #endif /* NOCSETS */
11888 #endif /* OS2 */
11889 #endif /* UNICODE */
11890
11891         outfile[0] = NUL;
11892
11893         if (cx == XXMORE)
11894           paging = 1;
11895         else if (cx == XXCAT)
11896           paging = 0;
11897         else
11898           paging = (typ_page < 0) ? xaskmore : typ_page;
11899         if (paging < 0)
11900           paging = saveask;
11901
11902         if (cx == XXHEAD) {
11903             head = 10;
11904             cx = XXTYP;
11905         } else if (cx == XXTAIL) {
11906             head = -10;
11907             cx = XXTYP;
11908         }
11909
11910 #ifdef IKSD
11911         if (inserver && !ENABLED(en_typ)) {
11912             printf("?Sorry, TYPE command disabled\n");
11913             return(-9);
11914         }
11915 #endif /* IKSD */
11916
11917         cmfdbi(&sw,                     /* 2nd FDB - optional /PAGE switch */
11918                _CMKEY,                  /* fcode */
11919                "Filename or switch",    /* hlpmsg */
11920                "",                      /* default */
11921                "",                      /* addtl string data */
11922                ntypetab,                /* addtl numeric data 1: tbl size */
11923                4,                       /* addtl numeric data 2: 4 = cmswi */
11924                xxstring,                /* Processing function */
11925                typetab,                 /* Keyword table */
11926                &sf                      /* Pointer to next FDB */
11927                );
11928         cmfdbi(&sf,                     /* 1st FDB - file to type */
11929                _CMIFI,                  /* fcode */
11930                "",                      /* hlpmsg */
11931                "",                      /* default */
11932                "",                      /* addtl string data */
11933                0,                       /* addtl numeric data 1 */
11934                0,                       /* addtl numeric data 2 */
11935                xxstring,
11936                NULL,
11937                NULL
11938                );
11939
11940         while (!havename) {
11941             x = cmfdb(&sw);             /* Parse something */
11942             debug(F101,"type cmfdb","",x);
11943             debug(F101,"type cmresult.fcode","",cmresult.fcode);
11944             debug(F101,"type cmresult.nresult","",cmresult.nresult);
11945             if (x < 0) {                        /* Error */
11946                 if (x == -3) {
11947                     x = -9;
11948                     printf("?Filename required\n");
11949                 }
11950                 return(x);
11951             } else if (cmresult.fcode == _CMKEY) {
11952                 char c; int getval;
11953                 c = cmgbrk();
11954                 getval = (c == ':' || c == '=');
11955                 if (getval && !(cmgkwflgs() & CM_ARG)) {
11956                     printf("?This switch does not take an argument\n");
11957                     return(-9);
11958                 }
11959 #ifdef COMMENT
11960                 if (!getval && (cmgkwflgs() & CM_ARG)) {
11961                     printf("?This switch requires an argument\n");
11962                     /* Not if it has a default! */
11963                     return(-9);
11964                 }
11965 #endif /* COMMENT */
11966                 switch (cmresult.nresult) {
11967 #ifdef CK_TTGWSIZ
11968                   case TYP_PAG:
11969                     paging = 1;
11970                     break;
11971
11972                   case TYP_NOP:
11973                     paging = 0;
11974                     break;
11975 #endif /* CK_TTGWSIZ */
11976
11977                   case TYP_COU:
11978                     paging = 0;
11979                     count = 1;
11980                     break;
11981
11982                   case TYP_HEA:
11983                   case TYP_TAI:
11984                     y = 10;
11985                     if (getval)
11986                       if ((x = cmnum("Number of lines",
11987                                      "10",10,&y,xxstring)) < 0)
11988                         return(x);
11989                     head = (cmresult.nresult == TYP_TAI) ? -y : y;
11990                     break;
11991
11992                   case TYP_WID:
11993                     y = typ_wid > -1 ? typ_wid : cmd_cols;
11994                     if (getval)
11995                       if ((x = cmnum("Column at which to truncate",
11996                                      ckitoa(y),10,&y,xxstring)) < 0)
11997                         return(x);
11998                     width = y;
11999                     break;
12000
12001 #ifdef KUI
12002                   case TYP_HIG:
12003                     if (getval)
12004                       if ((x = cmnum("Height of GUI dialog",
12005                                      ckitoa(y),10,&y,xxstring)) < 0)
12006                         return(x);
12007                     height = y;
12008                     break;
12009 #endif /* KUI */
12010
12011                   case TYP_PAT:
12012                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12013                         printf("?This switch requires an argument\n");
12014                         return(-9);
12015                     }
12016                     if ((x = cmfld("pattern","",&s,xxstring)) < 0)
12017                       return(x);
12018                     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12019                     pat = tmpbuf;
12020                     break;
12021
12022                   case TYP_PFX:
12023                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12024                         printf("?This switch requires an argument\n");
12025                         return(-9);
12026                     }
12027                     if ((x = cmfld("prefix for each line","",&s,xxstring)) < 0)
12028                       return(x);
12029                     if ((int)strlen(s) > 63) {
12030                         printf("?Too long - 63 max\n");
12031                         return(-9);
12032                     }
12033                     ckstrncpy(pfxbuf,s,64);
12034                     prefix = brstrip(pfxbuf);
12035                     number = 0;
12036                     break;
12037
12038 #ifdef KUI
12039                   case TYP_GUI:
12040                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12041                         printf("?This switch requires an argument\n");
12042                         return(-9);
12043                     }
12044                     if ((x = cmfld("Dialog box title","",&s,xxstring)) < 0) {
12045                         if (x != -3)
12046                           return(x);
12047                     } else {
12048                         if ((int)strlen(s) > 127) {
12049                             printf("?Too long - 127 max\n");
12050                             return(-9);
12051                         }
12052                         ckstrncpy(guibuf,s,128);
12053                         gui_title = brstrip(guibuf);
12054                     }
12055                     gui = 1;
12056                     break;
12057 #endif /* KUI */
12058
12059                   case TYP_NUM:         /* /NUMBER */
12060                     number = 1;
12061                     prefix = NULL;
12062                     break;
12063
12064 #ifdef UNICODE
12065                   case TYP_XPA:         /* /TRANSPARENT */
12066                     incs = 0;
12067                     cset = 0;
12068                     outcs = -1;
12069                     break;
12070
12071                   case TYP_XIN:         /* /CHARACTER-SET: */
12072                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12073                         printf("?This switch requires an argument\n");
12074                         return(-9);
12075                     }
12076                     if ((incs = cmkey(fcstab,nfilc,
12077                                       "character-set name","",xxstring)) < 0) {
12078                         if (incs == -3) /* Note: No default */
12079                           incs = -2;
12080                         return(incs);
12081                     }
12082                     cset = incs;
12083                     break;
12084
12085                   case TYP_XUT:         /* /TRANSLATE-TO: */
12086                     if (!getval && (cmgkwflgs() & CM_ARG)) {
12087                         printf("?This switch requires an argument\n");
12088                         return(-9);
12089                     }
12090 #ifdef OS2
12091                     if (!inserver && !k95stdout) {
12092                         tocs = "ucs2";
12093                     } else {
12094 #ifdef CKOUNI
12095                         tocs = rlookup(txrtab,ntxrtab,tcsl);
12096 #else /* CKOUNI */
12097                         extern struct keytab ttcstab[];
12098                         extern int ntxrtab;
12099                         tocs = rlookup(ttcstab,ntermc,tocs);
12100                         if (!tocs)
12101                           tocs = getdcset();
12102 #endif /* CKOUNI */
12103                     }
12104 #else /* OS2 */
12105                     tocs = getdcset();
12106 #endif /* OS2 */
12107                     if ((outcs = cmkey(fcstab,nfilc,
12108                                        "character-set",tocs,xxstring)) < 0)
12109                       return(outcs);
12110                     break;
12111 #endif /* UNICODE */
12112                   case TYP_OUT:
12113                     if ((x = cmofi("File for result lines","",
12114                                    &s,xxstring)) < 0)
12115                       return(x);
12116                     ckstrncpy(outfile,s,CKMAXPATH);
12117                     break;
12118                 }
12119             } else if (cmresult.fcode == _CMIFI)
12120               havename = 1;
12121             else
12122               return(-2);
12123         }
12124         if (havename) {
12125             ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
12126             y = cmresult.nresult;
12127         } else {
12128             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
12129                 if (x == -3) {
12130                     printf("?Name of an existing file required\n");
12131                     return(-9);
12132                 } else return(x);
12133             }
12134             ckstrncpy(line,s,LINBUFSIZ);
12135         }
12136         if (y != 0) {
12137             printf("?A single file please\n");
12138             return(-9);
12139         }
12140 #ifdef KUI
12141         if ( outfile[0] && gui ) {
12142             printf("?/GUI and /OUTPUT are incompatible\n");
12143             return(-9);
12144         }
12145 #endif /* KUI */
12146
12147         if ((y = cmcfm()) < 0)          /* Confirm the command */
12148           return(y);
12149
12150 #ifdef UNICODE
12151         fileorder = -1;
12152         if (cset < 0 && filepeek) {     /* If no charset switches given */
12153             int k, x = -1;
12154             k = scanfile(line,&x,nscanfile); /* Call file analyzer */
12155             debug(F111,"type scanfile",line,k);
12156             debug(F101,"type scanfile flag","",x);
12157             switch(k) {
12158               case FT_UTF8:             /* which can detect UTF-8... */
12159                 cset = 0;
12160                 incs = FC_UTF8;
12161                 break;
12162               case FT_UCS2:             /* and UCS-2... */
12163                 cset = 0;
12164                 incs = FC_UCS2;
12165                 fileorder = x;          /* even if there is no BOM. */
12166                 debug(F101,"type fileorder","",fileorder);
12167                 break;
12168             }
12169         }
12170 #ifdef OS2
12171         if (cset < 0) {                 /* If input charset still not known */
12172 #ifdef CKOUNI
12173             tocs = rlookup(txrtab,ntxrtab,tcsl);
12174 #else /* CKOUNI */
12175             extern struct keytab ttcstab[];
12176             extern int ntxrtab;
12177             tocs = rlookup(ttcstab,ntermc,incs);
12178             if (!tocs)
12179               tocs = getdcset();
12180 #endif /* CKOUNI */
12181             incs = lookup(fcstab,tocs,nfilc,&x);
12182         }
12183 #endif /* OS2 */
12184
12185         if (outcs == 0 && incs != 0) {  /* Supply default target charset */
12186             int x = 0;                  /* if switch not given. */
12187             tocs = getdcset();
12188             outcs = lookup(fcstab,tocs,nfilc,&x);
12189         }
12190 #else  /* !UNICODE */
12191         if (cset < 0) incs = outcs = 0;
12192 #endif /* UNICODE */
12193
12194         if (outfile[0] && paging)       /* This combination makes no sense */
12195           paging = 0;                   /* so turn off paging */
12196
12197 #ifdef KUI
12198         /* No paging when dialog is used */
12199         if ( gui && paging )
12200           paging = 0;
12201
12202         if ( !gui && height ) {
12203             printf("?The /HEIGHT switch is not supported without /GUI\n");
12204             return(-9);
12205         }
12206 #endif /* KUI */
12207
12208         if (count) paging = -1;
12209         debug(F111,"type",line,paging);
12210 #ifdef KUI
12211         if ( gui ) {
12212             s = (char *)1;    /* ok, its an ugly hack */
12213             if (gui_text_popup_create(gui_title ?
12214                                       gui_title : line, height,width) < 0) {
12215                 printf("?/GUI not supported on this system\n");
12216                 gui = 0;
12217                 return(-9);
12218             }
12219             width = 0;
12220         } else
12221 #endif /* KUI */
12222           s = outfile;
12223         success =
12224           dotype(line,paging,0,head,pat,width,prefix,incs,outcs,s,number);
12225         return(success);
12226     }
12227 #endif /* NOFRILLS */
12228
12229 #ifndef NOCSETS
12230     if (cx == XXXLA) {                  /* TRANSLATE file's charset */
12231         _PROTOTYP (int doxlate, ( void ) );
12232         return(doxlate());
12233     }
12234 #endif /* NOCSETS */
12235
12236     if (cx == XXVER) {                  /* VERSION */
12237         int n = 0;
12238         extern char * ck_patch, * ck_s_test;
12239 #ifdef COMMENT
12240         extern int hmtopline;
12241 #endif /* COMMENT */
12242         if ((y = cmcfm()) < 0)
12243           return(y);
12244
12245         printf("\n%s, for%s\n Numeric: %ld",versio,ckxsys,vernum);
12246         printf("\n\n");
12247         printf("Authors:\n");
12248         printf(" Frank da Cruz, Columbia University\n");
12249         printf(" Jeffrey Eric Altman, Secure Endpoints, Inc. %s\n",
12250                "<jaltman@secure-endpoints.com>"
12251                );
12252         printf(" Contributions from many others.\n");
12253         n = 7;
12254         if (*ck_s_test) {
12255             printf("\nTHIS IS A TEST VERSION, NOT FOR PRODUCTION USE.\n");
12256             n += 2;
12257         }
12258         if (*ck_patch) {
12259             printf(" Patches: %s\n", ck_patch);
12260             n++;
12261         }
12262         printf(" Type COPYRIGHT for copyright and license.\n\n");
12263 #ifdef OS2
12264         shoreg();
12265 #else
12266 #ifdef COMMENT
12267         hmtopline = n+1;
12268         hmsga(copyright);
12269         hmtopline = 0;
12270 #endif /* COMMENT */
12271 #endif /* OS2 */
12272         return(success = 1);
12273     }
12274
12275     if (cx == XXCPR) {                  /* COPYRIGHT or LICENSE */
12276         if ((y = cmcfm()) < 0)
12277           return(y);
12278 #ifdef OS2
12279         if (inserver) {                 /* Free WIKSD */
12280             extern char * wiksdcpr[];
12281             hmsga(wiksdcpr);
12282         } else
12283 #endif /* OS2 */
12284           hmsga(copyright);
12285         return(success = 1);
12286     }
12287
12288 #ifndef MAC                             /* Only for multiuser systems */
12289 #ifndef OS2
12290 #ifndef NOFRILLS
12291     if (cx == XXWHO) {                  /* WHO */
12292         char *wc;
12293 #ifdef IKSD
12294         if (inserver && !ENABLED(en_who)) {
12295             printf("?Sorry, WHO command disabled\n");
12296             return(-9);
12297         }
12298 #endif /* IKSD */
12299 #ifdef datageneral
12300         if ((z = cmcfm()) < 0) return(z);
12301         if (nopush) {
12302             printf("?Sorry, who not allowed\n");
12303             return(success = 0);
12304         }
12305         xsystem(WHOCMD);
12306 #else
12307         if ((y = cmtxt("user name","",&s,xxstring)) < 0) return(y);
12308         if (nopush) {
12309             printf("?Sorry, WHO command disabled\n");
12310             return(success = 0);
12311         }
12312         if (!(wc = getenv("CK_WHO"))) wc = WHOCMD;
12313         if (wc)
12314           if ((int) strlen(wc) > 0) {
12315               ckmakmsg(line,LINBUFSIZ,wc," ",s,NULL);
12316               xsystem(line);
12317           }
12318 #endif /* datageneral */
12319         return(success = 1);
12320     }
12321 #endif /* NOFRILLS */
12322 #endif /* OS2 */
12323 #endif /* MAC */
12324
12325 #ifndef NOFRILLS
12326     if (cx == XXWRI || cx == XXWRL || cx == XXWRBL) { /* WRITE */
12327         int x,y;                        /* On stack in case of \fexec() */
12328         if ((x = cmkey(writab,nwri,"to file or log","",xxstring)) < 0) {
12329             if (x == -3) printf("?Write to what?\n");
12330             return(x);
12331         }
12332         if ((y = cmtxt("text","",&s,xxstring)) < 0) return(y);
12333         s = brstrip(s);
12334         switch (x) {
12335           case LOGD: y = ZDFILE; break;
12336           case LOGP: y = ZPFILE; break;
12337 #ifndef NOLOCAL
12338           case LOGS: y = ZSFILE; break;
12339 #endif /* NOLOCAL */
12340           case LOGT: y = ZTFILE; break;
12341 #ifndef NOSPL
12342           case LOGW: y = ZWFILE; break;
12343 #endif /* NOSPL */
12344           case LOGX:                    /* SCREEN (stdout) */
12345           case LOGE:                    /* ERROR  (stderr) */
12346             if (x == LOGE) {
12347                 debug(F110,
12348                       (cx == XXWRL) ? "WRITELN ERROR" : "WRITE ERROR", s,0);
12349                 fprintf(stderr,"%s%s",s,(cx == XXWRL) ? "\n" : "");
12350             } else {
12351                 debug(F110,
12352                       (cx == XXWRL) ? "WRITELN SCREEN" : "WRITE SCREEN", s,0);
12353                 printf("%s%s",s,(cx == XXWRL) ? "\n" : "");
12354             }
12355             return(success = 1);
12356           default: return(-2);
12357         }
12358         if (chkfn(y) > 0) {
12359             x = (cx == XXWRI) ? zsout(y,s) : zsoutl(y,s);
12360             if (x < 0) printf("?Write error\n");
12361         } else {
12362             x = -1;
12363             printf("?File or log not open\n");
12364         }
12365         return(success = (x == 0) ? 1 : 0);
12366     }
12367 #endif /* NOFRILLS */
12368
12369 #ifndef NOXFER
12370     if (cx == XXASC || cx == XXBIN) {
12371         if ((x = cmcfm()) < 0) return(x);
12372 #ifdef NEWFTP
12373         if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
12374           return(success = doftptyp((cx == XXASC) ? 0 : 1));
12375 #endif /* NEWFTP */
12376         binary = (cx == XXASC) ? XYFT_T : XYFT_B;
12377         return(success = 1);
12378     }
12379 #endif /* NOXFER */
12380
12381     if (cx == XXCLS) {
12382         if ((x = cmcfm()) < 0) return(x);
12383         y = ck_cls();
12384         return(success = (y > -1) ? 1 : 0);
12385     }
12386
12387 #ifdef CK_MKDIR
12388     if (cx == XXMKDIR || cx == XXLMKD) {
12389         char *p;
12390 #ifdef LOCUS
12391         if (!locus && cx != XXLMKD) {
12392 #ifdef NOXFER
12393             return(-2);
12394 #else
12395             return(dormt(XZMKD));
12396 #endif /* NOXFER */
12397         }
12398 #endif /* LOCUS */
12399 #ifdef IKSD
12400         if (inserver && !ENABLED(en_mkd)) {
12401             printf("?Sorry, directory creation is disabled\n");
12402             return(-9);
12403         }
12404 #endif /* IKSD */
12405         if ((x = cmfld("Name for new directory","",&s,xxstring)) < 0) {
12406             if (x != -3) {
12407                 return(x);
12408             } else {
12409                 printf("?Directory name required\n");
12410                 return(-9);
12411             }
12412         }
12413         ckstrncpy(line,s,LINBUFSIZ);
12414         s = line;
12415         if ((x = cmcfm()) < 0) return(x);
12416         s = brstrip(s);
12417         bgchk();                        /* Set msgflg */
12418         x = ckmkdir(0,s,&p,msgflg,0);
12419 #ifdef COMMENT
12420         if (msgflg && x == 0)
12421           printf("?Directory already exists\n");
12422 #endif /* COMMENT */
12423         return(success = (x < 0) ? 0 : 1);
12424     }
12425     if (cx == XXRMDIR || cx == XXLRMD) { /* RMDIR */
12426         char *p;
12427 #ifdef LOCUS
12428         if (!locus && cx != XXLRMD) {
12429 #ifdef NOXFER
12430             return(-2);
12431 #else
12432             return(dormt(XZRMD));
12433 #endif /* NOXFER */
12434         }
12435 #endif /* LOCUS */
12436 #ifdef IKSD
12437         if (inserver && !ENABLED(en_rmd)) {
12438             printf("?Sorry, directory removal is disabled\n");
12439             return(-9);
12440         }
12441 #endif /* IKSD */
12442         if ((x = cmdir("Name of directory to be removed","",&s,xxstring)) < 0)
12443           return(x);
12444         ckstrncpy(line,s,LINBUFSIZ);
12445         s = line;
12446         if ((x = cmcfm()) < 0) return(x);
12447         s = brstrip(s);
12448         x = ckmkdir(1,s,&p,msgflg,0);
12449         return(success = (x < 0) ? 0 : 1);
12450     }
12451 #endif /* CK_MKDIR */
12452
12453 #ifdef TNCODE
12454     if (cx == XXTELOP)
12455       return(dotelopt());
12456 #endif /* TNCODE */
12457
12458 #ifndef NOPUSH
12459     if (cx == XXNPSH) {
12460         if ((z = cmcfm()) < 0) return(z);
12461         nopush = 1;
12462 #ifndef NOSERVER
12463         en_hos = 0;
12464 #endif /* NOSERVER */
12465 #ifdef PIPESEND
12466         usepipes = 0;
12467 #endif /* PIPESEND */
12468         return(success = 1);
12469     }
12470 #endif /* NOPUSH */
12471
12472 #ifdef OS2
12473     if (cx == XXNSCR) {
12474         if ((z = cmcfm()) < 0) return(z);
12475         tt_scroll = 0;
12476         return(success = 1);
12477     }
12478 #endif /* OS2 */
12479
12480 #ifndef NOSPL
12481     if (cx == XXLOCAL)                  /* LOCAL variable declarations */
12482       return(success = dolocal());
12483 #endif /* NOSPL */
12484
12485     if (cx == XXKERMI) {                /* The KERMIT command */
12486         char * list[65];
12487         extern char **xargv;
12488         extern int xargc;
12489         int i;
12490         if ((y = cmtxt("kermit command-line arguments, -h for help",
12491                        "",&s,xxstring)) < 0)
12492           return(y);
12493         ckstrncpy(line,"kermit ",LINBUFSIZ);
12494         ckstrncat(line,s,LINBUFSIZ-8);
12495         xwords(line,64,list,0);
12496         for (i = 1; i < 64; i++) {
12497             if (!list[i])
12498               break;
12499         }
12500         i--;
12501         xargc = i;
12502         xargv = list;
12503         xargv++;
12504         sstate = cmdlin();
12505         if (sstate) {
12506             extern int justone;
12507             debug(F000,"KERMIT sstate","",sstate);
12508             justone = 1;                /* Force return to command mode */
12509             proto();                    /* after protocol */
12510             return(success);
12511         } else {
12512             debug(F101,"KERMIT sstate","",sstate);
12513             return(success = 1);        /* Not exactly right, but... */
12514         }
12515     }
12516     if (cx == XXDATE) {                 /* DATE command */
12517         extern char cmdatebuf[], * cmdatemsg;
12518
12519 #ifndef COMMENT
12520         char * dp;
12521         if ((y = cmtxt("date and/or time, or carriage return for current",
12522                        "",&s,xxstring)) < 0)
12523           return(y);
12524         s = brstrip(s);
12525         dp = cmcvtdate(s,1);
12526         if (!dp) {
12527             printf("?%s\n",cmdatemsg ? cmdatemsg : "Date conversion error");
12528             success = 0;
12529         } else {
12530             printf("%s\n",dp);
12531             success = 1;
12532         }
12533 #else
12534         /* This works fine but messes up my "dates" torture-test script */
12535
12536         if ((x = cmdate("Date and/or time, or carriage return for current",
12537                         "",&s,0,xxstring)) < 0) {
12538             return(x);
12539         } else {
12540             printf("%s\n",cmdatebuf);
12541             success = 1;
12542         }
12543 #endif /* COMMENT */
12544         return(success);
12545     }
12546 #ifndef NOPUSH
12547 #ifndef NOFRILLS
12548     if (cx == XXEDIT)
12549       return(doedit());
12550 #endif /* NOFRILLS */
12551 #endif /* NOPUSH */
12552
12553 #ifdef BROWSER                          /* Defined only ifndef NOPUSH */
12554     if (cx == XXBROWS)
12555       return(dobrowse());
12556 #endif /* BROWSER */
12557
12558 #ifdef CK_TAPI
12559     if (cx == XXTAPI) {                 /* Microsoft TAPI */
12560         return (success = dotapi());
12561     }
12562 #endif /* CK_TAPI */
12563
12564 #ifndef NOXFER
12565     if (cx == XXWHERE) {
12566         extern char * rfspec, * sfspec, * srfspec, * rrfspec;
12567         if ((x = cmcfm()) < 0) return(x);
12568         printf("\nFile most recently...\n\n");
12569         printf("  Sent:       %s\n",   sfspec ? sfspec : "(none)");
12570         if (sfspec && srfspec) {
12571             printf("  Stored as:  %s\n",   srfspec);
12572             printf("\n");
12573         }
12574         printf("  Received:   %s\n",   rrfspec ? rrfspec : "(none)");
12575         if (rfspec && rrfspec)
12576         printf("  Stored as:  %s\n",   rfspec);
12577         printf(
12578 "\nIf the full path is not shown, then the file is probably in your current\n"
12579                );
12580         printf(
12581 "directory or your download directory (if any - SHOW FILE to find out).\n\n"
12582                );
12583         return(success = 1);
12584     }
12585 #endif /* NOXFER */
12586
12587 #ifdef CK_RECALL
12588     if (cx == XXREDO)
12589       return(doredo());
12590 #endif /* CK_RECALL */
12591
12592 #ifdef CKROOT
12593     if (cx == XXCHRT)                   /* Change Kermit's root directory */
12594       return(dochroot());
12595 #endif /* CKROOT */
12596
12597 #ifdef CK_KERBEROS
12598     if (cx == XXAUTH) {                 /* KERBEROS */
12599         x = cp_auth();                  /* Parse it */
12600 #ifdef IKSD
12601         if (inserver) {
12602             printf("?Command disabled in IKSD.\r\n");
12603             return(success = 0);
12604         }
12605 #endif /* IKSD */
12606         if (x < 0)                      /* Pass parse errors back */
12607           return(x);
12608         return(success = doauth(cx));
12609     }
12610 #endif /* CK_KERBEROS */
12611
12612 #ifndef NOLOCAL
12613     if (cx == XXTERM) {
12614         return(settrmtyp());
12615     }
12616 #endif /* NOLOCAL */
12617
12618     if (cx == XXSTATUS) {
12619         if ((x = cmcfm()) < 0) return(x);
12620         printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
12621         return(0);                      /* Don't change it */
12622     }
12623
12624     if (cx == XXFAIL) {
12625         if ((x = cmcfm()) < 0) return(x);
12626         return(success = 0);
12627     }
12628
12629     if (cx == XXSUCC) {
12630         if ((x = cmcfm()) < 0) return(x);
12631         return(success = 1);
12632     }
12633
12634     if (cx == XXNLCL) {
12635         extern int nolocal;
12636         if ((x = cmcfm()) < 0) return(x);
12637         nolocal = 1;
12638         return(success = 1);
12639     }
12640
12641 #ifndef NOXFER
12642     if (cx == XXRASG)                   /* Shortcuts for REMOTE commands */
12643       return(dormt(XZASG));
12644     if (cx == XXRCWD)
12645       return(dormt(XZCWD));
12646     if (cx == XXRCPY)
12647       return(dormt(XZCPY));
12648     if (cx == XXRDEL)
12649       return(dormt(XZDEL));
12650     if (cx == XXRDIR)
12651       return(dormt(XZDIR));
12652     if (cx == XXRXIT)
12653       return(dormt(XZXIT));
12654     if (cx == XXRHLP)
12655       return(dormt(XZHLP));
12656     if (cx == XXRHOS)
12657       return(dormt(XZHOS));
12658     if (cx == XXRKER)
12659       return(dormt(XZKER));
12660     if (cx == XXRPWD)
12661       return(dormt(XZPWD));
12662     if (cx == XXRQUE)
12663       return(dormt(XZQUE));
12664     if (cx == XXRREN)
12665       return(dormt(XZREN));
12666     if (cx == XXRMKD)
12667       return(dormt(XZMKD));
12668     if (cx == XXRRMD)
12669       return(dormt(XZRMD));
12670     if (cx == XXRSET)
12671       return(dormt(XZSET));
12672     if (cx == XXRSPA)
12673       return(dormt(XZSPA));
12674     if (cx == XXRTYP)
12675       return(dormt(XZTYP));
12676     if (cx == XXRWHO)
12677       return(dormt(XZWHO));
12678     if (cx == XXRCDUP)
12679       return(dormt(XZCDU));
12680     if (cx == XXRPRI)
12681       return(dormt(XZPRI));
12682 #endif /* NOXFER */
12683
12684     if (cx == XXRESET) {                /* RESET */
12685         if ((x = cmcfm()) < 0)
12686           return(x);
12687         doclean(0);                     /* Close all files */
12688         return(success = 1);
12689     }
12690
12691 #ifndef NOXFER
12692 #ifndef NOCSETS
12693     if (cx == XXASSOC)                  /* ASSOCIATE */
12694       return(doassoc());
12695 #endif /* NOCSETS */
12696 #endif /* NOXFER */
12697
12698 #ifndef NOSPL
12699     if (cx == XXSHIFT) {                /* SHIFT */
12700         if ((y = cmnum("Number of arguments to shift","1",10,&x,xxstring)) < 0)
12701           return(y);
12702         if ((z = cmcfm()) < 0)
12703           return(z);
12704         return(success = doshift(x));
12705     }
12706 #endif /* NOSPL */
12707
12708 #ifndef NOHELP
12709     if (cx == XXMAN)
12710       return(domanual());
12711 #endif /* NOHELP */
12712
12713 #ifndef NOSPL
12714     if (cx == XXSORT)                   /* SORT an array */
12715       return(dosort());
12716 #endif /* NOSPL */
12717
12718     if (cx == XXPURGE) {
12719 #ifdef IKSD
12720         if (inserver && (!ENABLED(en_del)
12721 #ifdef CK_LOGIN
12722                           || isguest
12723 #endif /* CK_LOGIN */
12724                          )) {
12725             printf("?Sorry, DELETE is disabled\n");
12726             return(-9);
12727         }
12728 #endif /* IKSD */
12729 #ifdef CK_APC
12730         if ((apcactive == APC_LOCAL) ||
12731             ((apcactive == APC_REMOTE) && (!(apcstatus & APC_UNCH))))
12732           return(success = 0);
12733 #endif /* CK_APC */
12734 #ifdef CKPURGE
12735         return(dopurge());
12736 #else
12737 #ifdef VMS
12738         if ((x = cmtxt("optional switches followed by filespec",
12739                        "",&s,xxstring)) < 0)
12740           return(x);
12741         if (nopush) {
12742             printf("?Sorry, DCL access is disabled\n");
12743             return(-9);
12744         }
12745         ckstrncpy(line,s,LINBUFSIZ);
12746         s = line;
12747         x = mlook(mactab,"purge",nmac);
12748         return(success = dodo(x,s,cmdstk[cmdlvl].ccflgs));
12749 #else
12750         return(-2);
12751 #endif /* VMS */
12752 #endif /* CKPURGE */
12753     }
12754
12755 #ifndef NOSPL
12756     if (cx == XXFAST) {
12757         if ((x = cmcfm()) < 0) return(x);
12758         x = mlook(mactab,"fast",nmac);
12759         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12760     }
12761     if (cx == XXCAU) {
12762         if ((x = cmcfm()) < 0) return(x);
12763         x = mlook(mactab,"cautious",nmac);
12764         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12765     }
12766     if (cx == XXROB) {
12767         if ((x = cmcfm()) < 0) return(x);
12768         x = mlook(mactab,"robust",nmac);
12769         return(success = dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
12770     }
12771 #endif /* NOSPL */
12772
12773     if (cx == XXSCRN) {                 /* SCREEN */
12774         int row, col;
12775         if ((x = cmkey(scntab, nscntab,"screen action","", xxstring)) < 0)
12776           return(x);
12777         switch (x) {                    /* MOVE-TO (cursor position) */
12778           case SCN_MOV:
12779             if ((y = cmnum("Row (1-based)","",10,&z,xxstring)) < 0)
12780               return(y);
12781             row = z;
12782             y = cmnum("Column (1-based)","1",10,&z,xxstring);
12783             if (y < 0)
12784               return(y);
12785             col = z;
12786             if ((y = cmcfm()) < 0)
12787               return(y);
12788             if (row < 0 || col < 0) {
12789                 printf("?Row and Column must be 1 or greater\n");
12790                 return(-9);
12791             }
12792             if (cmd_rows > 0 && row > cmd_rows)
12793               row = cmd_rows;
12794             if (cmd_cols > 0 && col > cmd_cols)
12795               col = cmd_cols;
12796             y = ck_curpos(row,col);
12797             return(success = (y > -1) ? 1 : 0);
12798
12799           case SCN_CLR:                 /* CLEAR */
12800             if ((y = cmcfm()) < 0)
12801               return(y);
12802             debug(F100,"screen calling ck_cls()","",0);
12803             y = ck_cls();
12804             return(success = (y > -1) ? 1 : 0);
12805
12806           case SCN_CLE:                 /* CLEOL */
12807             if ((y = cmcfm()) < 0)
12808               return(y);
12809             y = ck_cleol();
12810             return(success = (y > -1) ? 1 : 0);
12811         }
12812     }
12813
12814 #ifndef NOHTTP
12815 #ifdef TCPSOCKET
12816     if (cx == XXHTTP)
12817       return(dohttp());
12818 #endif /* TCPSOCKET */
12819 #endif /* NOHTTP */
12820
12821 #ifndef NOSPL
12822     if (cx == XXARRAY) {                /* ARRAY */
12823 #ifndef NOSHOW
12824         extern int showarray();
12825 #endif /* NOSHOW */
12826         if ((x = cmkey(arraytab, narraytab,"Array operation","",xxstring)) < 0)
12827           return(x);
12828         switch (x) {
12829           case ARR_DCL:
12830             return(dodcl(XXDCL));
12831           case ARR_SRT:
12832             return(dosort());
12833 #ifndef NOSHOW
12834           case ARR_SHO:
12835             return(showarray());
12836 #endif /* NOSHOW */
12837           case ARR_CPY:
12838             return(copyarray());
12839           case ARR_SET:
12840           case ARR_CLR:
12841             return(clrarray(x));
12842           case ARR_DST:
12843             return(unarray());
12844           case ARR_RSZ:
12845             return(rszarray());
12846           case ARR_EQU:
12847             return(linkarray());
12848
12849           default:
12850             printf("?Sorry, not implemented yet - \"%s\"\n",cmdbuf);
12851             return(-9);
12852         }
12853     }
12854     if (cx == XXTRACE)
12855       return(dotrace());
12856 #endif /* NOSPL */
12857
12858 #ifdef CK_PERMS
12859 #ifdef UNIX
12860     if (cx == XXCHMOD)
12861       return(douchmod());               /* Do Unix chmod */
12862 #endif /* UNIX */
12863 #endif /* CK_PERMS */
12864
12865     if (cx == XXPROMP)
12866       return(doprompt());
12867
12868     if (cx == XXGREP)
12869       return(dogrep());
12870
12871     if (cx == XXDEBUG) {                /* DEBUG */
12872 #ifndef DEBUG
12873         int dummy = 0;
12874         return(seton(&dummy));
12875 #else
12876         return(seton(&deblog));
12877 #endif /* DEBUG */
12878     }
12879
12880 #ifdef CKLEARN
12881     if (cx == XXLEARN) {                /* LEARN */
12882         struct FDB of, sw, cm;
12883         int closing = 0, off = 0, on = 0, confirmed = 0;
12884         char c;
12885
12886         cmfdbi(&sw,                     /* 2nd FDB - optional /PAGE switch */
12887                _CMKEY,                  /* fcode */
12888                "Script file name, or switch", /* hlpmsg */
12889                "",                      /* default */
12890                "",                      /* addtl string data */
12891                3,                       /* addtl numeric data 1: tbl size */
12892                4,                       /* addtl numeric data 2: 4 = cmswi */
12893                xxstring,                /* Processing function */
12894                learnswi,                /* Keyword table */
12895                &of                      /* Pointer to next FDB */
12896                );
12897         cmfdbi(&of,_CMOFI,"","","",0,0,xxstring,NULL,&cm);
12898         cmfdbi(&cm,_CMCFM,"","","",0,0,NULL,NULL,NULL);
12899         line[0] = NUL;
12900
12901         while (!confirmed) {
12902             x = cmfdb(&sw);             /* Parse something */
12903             if (x < 0)
12904               return(x);
12905             switch (cmresult.fcode) {   /* What was it? */
12906               case _CMOFI:              /* Output file name */
12907                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
12908                 break;
12909               case _CMKEY:              /* Switch */
12910                 c = cmgbrk();
12911                 if ((c == ':' || c == '=') && !(cmgkwflgs() & CM_ARG)) {
12912                     printf("?This switch does not take an argument\n");
12913                     return(-9);
12914                 }
12915                 switch (cmresult.nresult) {
12916                   case 2:               /* /CLOSE */
12917                     closing = 1;        /* Fall thru on purpose */
12918                   case 0:               /* /OFF */
12919                     off = 1;
12920                     on = 0;
12921                     break;
12922                   case 1:               /* /ON */
12923                     on = 1;
12924                     off = 0;
12925                     break;
12926                 }
12927                 break;
12928               case _CMCFM:              /* Confirmation */
12929                 confirmed++;
12930                 break;
12931             }
12932         }
12933         if (closing) {
12934             if (learnfp) {
12935                 fclose(learnfp);
12936                 learnfp = NULL;
12937             }
12938             makestr(&learnfile,NULL);
12939         }
12940         if (line[0]) {
12941             if (!on && !off)
12942               on = 1;
12943             if (learnfp) {
12944                 fclose(learnfp);
12945                 learnfp = NULL;
12946             }
12947             makestr(&learnfile,line);
12948             if (learnfile) {
12949                 char * modes = "w";
12950                 learnfp = fopen(learnfile,modes);
12951                 if (!learnfp) {
12952                     debug(F110,"LEARN file open error",learnfile,0);
12953                     perror(learnfile);
12954                     return(-9);
12955                 } else {
12956 #ifdef ZFNQFP
12957                     if (zfnqfp(learnfile,TMPBUFSIZ,tmpbuf))
12958                       makestr(&learnfile,tmpbuf);
12959 #endif /* ZFNQFP */
12960                     debug(F110,"LEARN file open ok",learnfile,0);
12961                     if (!quiet) {
12962                         printf("Recording to %s...\n\n",learnfile);
12963                         printf(
12964 " WARNING: If you type your password during script recording, it will appear\n\
12965  in the file.  Be sure to edit it or take other appropriate precautions.\n\n"
12966                                );
12967                     }
12968                     fputs(  "; Scriptfile: ",learnfp);
12969                     fputs(learnfile,learnfp);
12970                     fputs("\n; Directory:  ",learnfp);
12971                     fputs(zgtdir(),learnfp);
12972                     fputs("\n; Recorded:   ",learnfp);
12973                     fputs(ckdate(),learnfp);
12974                     fputs("\n",learnfp);
12975                 }
12976             }
12977         }
12978         if (on) {
12979             learning = 1;
12980         } else if (off) {
12981             learning = 0;
12982         }
12983         debug(F101,"LEARN learning","",learning);
12984         return(success = 1);
12985     }
12986 #endif /* CKLEARN */
12987
12988 #ifdef NEWFTP
12989     if (cx == XXUSER || cx == XXACCT) {
12990         if (!ftpisopen()) {
12991             printf("?FTP connection is not open\n");
12992             return(-9);
12993         }
12994         return(success = (cx == XXUSER) ? doftpusr() : doftpacct());
12995     }
12996     if (cx == XXSITE || cx == XXPASV) {
12997         if (!ftpisopen()) {
12998             printf("?FTP connection is not open\n");
12999             return(-9);
13000         }
13001         return(success = (cx == XXSITE) ? doftpsite() : dosetftppsv());
13002     }
13003 #endif /* NEWFTP */
13004
13005     if (cx == XXORIE) {                 /* ORIENTATION */
13006         extern char * myname;
13007         int i, y, n = 0;
13008         char * s, *p, vbuf[32];
13009         char * vars[16];       char * legend[16];
13010
13011         if ((y = cmcfm()) < 0)
13012           return(y);
13013
13014         printf("\nProgram name:\n  %s\n\n",myname);
13015         n += 4;
13016
13017 #ifdef NT
13018         vars[0] = "home";      legend[0] = "Your home directory";
13019         vars[1] = "directory"; legend[1] = "K95's current directory";
13020         vars[2] = "exedir";    legend[2] = "K95 Program directory";
13021         vars[3] = "inidir";    legend[3] = "K95 Initialization file directory";
13022         vars[4] = "startup";   legend[4] = "Current directory when started";
13023         
13024         vars[5] = "common";
13025         legend[5] = "K95 data for all users and K95SITE.INI file";
13026         
13027         vars[6] = "personal";  legend[6] = "Your personal data directory tree";
13028         vars[7] = "desktop";   legend[7] = "Your deskop directory tree";
13029         
13030         vars[8] = "appdata";
13031         legend[8] = "Your personal K95 data tree and K95CUSTOM.INI file";
13032         
13033         vars[9] = "download";  legend[9] = "Your K95 download directory";
13034         vars[10] = "tmpdir";   legend[10] = "Your TEMP directory";
13035         vars[11] = NULL;       legend[11] = NULL;
13036
13037         for (i = 0; i < 16 && vars[i]; i++) {
13038             printf("%s:\n",legend[i]);
13039             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13040             ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
13041             printf("  Variable:   %s\n",vbuf);
13042             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13043             y = TMPBUFSIZ;
13044             s = tmpbuf;
13045             zzstring(vbuf,&s,&y);
13046             line[0] = NUL;
13047             ckGetLongPathName(tmpbuf,line,LINBUFSIZ);
13048             printf("  Long name:  %s\n",line);
13049             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13050             line[0] = NUL;
13051             GetShortPathName(tmpbuf,line,LINBUFSIZ);
13052             printf("  Short name: %s\n",line);
13053             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13054             printf("\n");
13055             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13056         }
13057 #else  /* NT */
13058
13059         vars[0] = "home";      legend[0] = "Your home directory";
13060         vars[1] = "directory"; legend[1] = "Kermit's current directory";
13061         vars[2] = "exedir";    legend[2] = "Kermit's program directory";
13062         vars[3] = "inidir";    legend[3] = "Initialization file directory";
13063         vars[4] = "startup";   legend[4] = "Current directory when started";
13064         vars[5] = "download";  legend[5] = "Kermit download directory";
13065         vars[6] = NULL;        legend[6] = NULL;
13066
13067         for (i = 0; i < 16 && vars[i]; i++) {
13068             printf("%s:\n",legend[i]);
13069             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13070             ckmakmsg(vbuf,32,"\\v(",vars[i],")",NULL);
13071             printf("  Variable: %s\n",vbuf);
13072             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13073             y = TMPBUFSIZ;
13074             s = tmpbuf;
13075             zzstring(vbuf,&s,&y);
13076             printf("  Value:    %s\n",tmpbuf);
13077             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13078             printf("\n");
13079             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13080         }
13081 #endif /* NT */
13082         return(success = 1);
13083     }
13084
13085 #ifdef NT
13086     if (cx == XXDIALER) {
13087         StartDialer();
13088         return(success = 1);
13089     }
13090 #endif /* NT */
13091
13092     if (cx == XXCONT) {                 /* CONTINUE */
13093         if ((x = cmcfm()) < 0)
13094           return(x);
13095         if (!xcmdsrc) {                 /* At prompt: continue script */
13096             if (cmdlvl > 0)
13097               popclvl();                /* Pop command level */
13098             return(success = 1);        /* always succeeds */
13099 #ifndef NOSPL
13100         } else {                        /* In script: whatever... */
13101             x = mlook(mactab,"continue",nmac);
13102             /* Don't set success */
13103             return(dodo(x,NULL,cmdstk[cmdlvl].ccflgs));
13104 #endif /* NOSPL */
13105         }
13106     }
13107     if (cx == XXNOTAV) {                /* Command in table not available */
13108         ckstrncpy(tmpbuf,atmbuf,TMPBUFSIZ);
13109         if ((x = cmtxt("Rest of command","",&s,NULL)) < 0)
13110           return(x);
13111         printf("Sorry, \"%s\" not configured in this version of Kermit.\n",
13112                tmpbuf
13113                );
13114         return(success = 0);
13115     }
13116     return(-2);                         /* None of the above */
13117
13118 } /* end of docmd() */
13119
13120 #endif /* NOICP */