apply 010_makefile-destdir-support
[ckermit.git] / ckuus7.c
1 #include "ckcsym.h"
2
3 /*  C K U U S 7 --  "User Interface" for C-Kermit, part 7  */
4
5 /*
6   Authors:
7     Frank da Cruz <fdc@columbia.edu>,
8       The Kermit Project, Columbia University, New York City
9     Jeffrey E Altman <jaltman@secure-endpoints.com>
10       Secure Endpoints Inc., New York City
11
12   Copyright (C) 1985, 2004,
13     Trustees of Columbia University in the City of New York.
14     All rights reserved.  See the C-Kermit COPYING.TXT file or the
15     copyright text in the ckcmai.c module for disclaimer and permissions.
16 */
17
18 /*
19   This file created from parts of ckuus3.c, which became too big for
20   Mark Williams Coherent compiler to handle.
21 */
22
23 /*
24   Definitions here supersede those from system include files.
25 */
26 #include "ckcdeb.h"                     /* Debugging & compiler things */
27 #include "ckcasc.h"                     /* ASCII character symbols */
28 #include "ckcker.h"                     /* Kermit application definitions */
29 #include "ckcxla.h"                     /* Character set translation */
30 #include "ckcnet.h"                     /* Network symbols */
31 #include "ckuusr.h"                     /* User interface symbols */
32 #include "ckucmd.h"
33 #include "ckclib.h"
34
35 #ifdef VMS
36 #ifndef TCPSOCKET
37 #include <errno.h>
38 #endif /* TCPSOCKET */
39 #endif /* VMS */
40
41 #ifdef OS2
42 #ifndef NT
43 #define INCL_NOPM
44 #define INCL_VIO                        /* Needed for ckocon.h */
45 #define INCL_DOSMODULEMGR
46 #include <os2.h>
47 #undef COMMENT
48 #else /* NT */
49 #define APIRET ULONG
50 #include <windows.h>
51 #include <tapi.h>
52 #include "cknwin.h"
53 #include "ckntap.h"
54 #endif /* NT */
55 #include "ckowin.h"
56 #include "ckocon.h"
57 #include "ckodir.h"
58 #ifdef OS2MOUSE
59 #include "ckokey.h"
60 #endif /* OS2MOUSE */
61 #ifdef KUI
62 #include "ikui.h"
63 #endif /* KUI */
64 #ifdef putchar
65 #undef putchar
66 #endif /* putchar */
67 #define putchar(x) conoc(x)
68 extern int mskkeys;
69 #endif /* OS2 */
70
71 #ifdef CK_AUTHENTICATION
72 #include "ckuath.h"
73 #endif /* CK_AUTHENTICATION */
74 #ifdef CK_SSL
75 #include "ck_ssl.h"
76 #endif /* CK_SSL */
77 #ifdef SSHBUILTIN
78 #include "ckossh.h"
79 #endif /* SSHBUILTIN */
80 #ifdef STRATUS                          /* Stratus Computer, Inc.  VOS */
81 #ifdef putchar
82 #undef putchar
83 #endif /* putchar */
84 #define putchar(x) conoc(x)
85 #ifdef getchar
86 #undef getchar
87 #endif /* getchar */
88 #define getchar(x) coninc(0)
89 #endif /* STRATUS */
90
91 char * slmsg = NULL;
92
93 static int x, y = 0, z;
94 static char *s;
95
96 extern CHAR feol;
97 extern int g_matchdot, hints, xcmdsrc, rcdactive;
98
99 extern char * k_info_dir;
100
101 #ifndef NOSPL
102 extern int nmac;
103 extern struct mtab *mactab;
104 #endif /* NOSPL */
105
106 #ifndef NOXFER
107 #ifdef CK_SPEED
108 extern short ctlp[];                    /* Control-char prefixing table */
109 #endif /* CK_SPEED */
110
111 #ifdef PIPESEND
112 extern char * sndfilter, * g_sfilter;
113 extern char * rcvfilter, * g_rfilter;
114 #endif /* PIPESEND */
115
116 extern char * snd_move;
117 extern char * snd_rename;
118 extern char * g_snd_move;
119 extern char * g_snd_rename;
120 extern char * rcv_move;
121 extern char * rcv_rename;
122 extern char * g_rcv_move;
123 extern char * g_rcv_rename;
124
125 #ifdef PATTERNS
126 extern char *binpatterns[], *txtpatterns[];
127 extern int patterns;
128 #endif /* PATTERNS */
129
130 extern char * remdest;
131 #ifdef CK_TMPDIR
132 char * dldir = NULL;
133 #endif /* CK_TMPDIR */
134
135 extern struct ck_p ptab[];
136
137 extern int protocol, remfile, rempipe, remappd, reliable, xreliable, fmask,
138   fncnv, frecl, maxrps, wslotr, bigsbsiz, bigrbsiz, urpsiz, rpsiz, spsiz,
139   bctr, npad, timef, timint, spsizr, spsizf, maxsps, spmax, nfils, displa,
140   atcapr, pkttim, rtimo, fncact, mypadn, fdispla, f_save, pktpaus, setreliable,
141   fnrpath, fnspath, atenci, atenco, atdati, atdato, atleni, atleno, atblki,
142   atblko, attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
143
144 extern int stathack;
145
146 extern int atfrmi, atfrmo;
147 #ifdef STRATUS
148 extern int atcrei, atcreo, atacti, atacto;
149 #endif /* STRATUS */
150 #ifdef CK_PERMS
151 extern int atlpri, atlpro, atgpri, atgpro;
152 #endif /* CK_PERMS */
153
154 extern CHAR
155   sstate, eol, seol, stchr, mystch, mypadc, padch, ctlq, myctlq;
156
157 #ifdef IKSD
158 extern int inserver;
159 #ifdef IKSDCONF
160 extern int iksdcf;
161 #endif /* IKSDCONF */
162 #endif /* IKSD */
163
164 extern char *cmarg, *cmarg2;
165
166 #ifndef NOFRILLS
167 extern char optbuf[];                   /* Buffer for MAIL or PRINT options */
168 extern int rprintf;                     /* REMOTE PRINT flag */
169 #endif /* NOFRILLS */
170 #endif /* NOXFER */
171
172 #ifdef CK_TRIGGER
173 extern char * tt_trigger[];
174 #endif /* CK_TRIGGER */
175
176 extern int tcs_transp;
177 #ifdef PCTERM
178 extern int tt_pcterm;
179 #endif /* PCTERM */
180 #ifdef NT
181 extern int tt_vtnt;
182 #endif /* NT */
183
184 #ifdef SSHBUILTIN
185 int sl_ssh_xfw = 0;
186 int sl_ssh_xfw_saved = 0;
187 int sl_ssh_ver = 0;
188 int sl_ssh_ver_saved = 0;
189 #endif /* SSHBUILTIN */
190
191 #ifdef CK_AUTHENTICATION
192 extern int auth_type_user[];
193 int sl_auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_NULL, AUTHTYPE_NULL};
194 int sl_auth_saved = 0;
195 int sl_topt_a_su = 0;
196 int sl_topt_a_s_saved = 0;
197 int sl_topt_a_cm = 0;
198 int sl_topt_a_c_saved = 0;
199 #endif /* CK_AUTHENTICATION */
200 #ifdef CK_ENCRYPTION
201 extern int cx_type;
202 int sl_cx_type = 0;
203 int sl_cx_saved = 0;
204 int sl_topt_e_su = 0;
205 int sl_topt_e_sm = 0;
206 int sl_topt_e_s_saved = 0;
207 int sl_topt_e_cu = 0;
208 int sl_topt_e_cm = 0;
209 int sl_topt_e_c_saved = 0;
210 #endif /* CK_ENCRYPTION */
211 extern char uidbuf[];
212 static int uidflag = 0;
213 char sl_uidbuf[UIDBUFLEN] = { NUL, NUL };
214 int  sl_uid_saved = 0;
215 #ifdef TNCODE
216 int  sl_tn_wait = 0;
217 int  sl_tn_saved = 0;
218 #endif /* TNCODE */
219
220 #ifdef TNCODE
221 extern int tn_wait_flg;
222 #endif /* TNCODE */
223
224 VOID
225 slrestor() {
226 #ifdef CK_AUTHENTICATION
227     int x;
228     if (sl_auth_saved) {
229         for (x = 0; x < AUTHTYPLSTSZ; x++)
230           auth_type_user[x] = sl_auth_type_user[x];
231         sl_auth_saved = 0;
232     }
233     if (sl_topt_a_s_saved) {
234         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = sl_topt_a_su;
235         sl_topt_a_s_saved = 0;
236     }
237     if (sl_topt_a_c_saved) {
238         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = sl_topt_a_cm;
239         sl_topt_a_c_saved = 0;
240     }
241 #endif /* CK_AUTHENTICATION */
242 #ifdef CK_ENCRYPTION
243     if (sl_cx_saved) {
244         cx_type = sl_cx_type;
245         sl_cx_saved = 0;
246     }
247     if (sl_topt_e_s_saved) {
248         TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION)  = sl_topt_e_su;
249         TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = sl_topt_e_sm;
250         sl_topt_e_s_saved = 0;
251     }
252     if (sl_topt_e_c_saved) {
253         TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION)  = sl_topt_e_cu;
254         TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = sl_topt_e_cm;
255         sl_topt_e_c_saved = 0;
256     }
257 #endif /* CK_ENCRYPTION */
258     if (sl_uid_saved) {
259         ckstrncpy(uidbuf,sl_uidbuf,UIDBUFLEN);
260         sl_uid_saved = 0;
261     }
262 #ifdef TNCODE
263     if (sl_tn_saved) {
264         tn_wait_flg = sl_tn_wait;
265         sl_tn_saved = 0;
266     }
267 #endif /* TNCODE */
268 #ifdef SSHBUILTIN
269     if (sl_ssh_xfw_saved) {
270         ssh_xfw = sl_ssh_xfw;
271         sl_ssh_xfw_saved = 0;
272     }
273     if (sl_ssh_ver_saved) {
274         ssh_ver = sl_ssh_ver;
275         sl_ssh_ver_saved = 0;
276     }
277 #endif /* SSHBUILTIN */
278 }
279
280 int oldplex = -1;                       /* Duplex holder around network */
281
282 #ifndef NOICP
283 #ifdef LOCUS
284 extern int locus, autolocus;
285 #endif /* LOCUS */
286 #ifndef NODIAL
287 extern int dialsta;
288 #endif /* NODIAL */
289
290 /* Note: gcc -Wall wants braces around each keyword table entry. */
291
292 static struct keytab psltab[] = {       /* SET LINE/PORT command options */
293     { "/connect", SL_CNX, 0 },
294 #ifdef OS2ORVMS
295     { "/noshare", SL_NSH, 0 },
296 #endif /* OS2ORVMS */
297     { "/server",  SL_SRV, 0 },
298 #ifdef OS2ORVMS
299     { "/share",   SL_SHR, 0 },
300 #endif /* OS2ORVMS */
301     { "", 0, 0 }
302 };
303 static int npsltab = sizeof(psltab)/sizeof(struct keytab) - 1;
304
305 #ifdef NETCONN
306 static struct keytab shtab[] = {        /* SET HOST command options */
307 #ifdef NETCMD
308     /* (COMMAND is also a network type) */
309     { "/command",      SL_CMD,    CM_INV },
310 #endif /* NETCMD */
311     { "/connect",      SL_CNX,    0 },
312     { "/network-type", SL_NET,    CM_ARG },
313     { "/nowait",       SL_NOWAIT, 0 },
314 #ifndef NOSPL
315 #ifdef CK_AUTHENTICATION
316     { "/password",     SL_PSW,    CM_ARG },
317 #endif /* CK_AUTHENTICATION */
318 #endif /* NOSPL */
319 #ifdef NETCMD
320     { "/pipe",         SL_CMD,    0 },
321 #endif /* NETCMD */
322 #ifdef NETPTY
323     { "/pty",          SL_PTY,    0 },
324 #endif /* NETPTY */
325     { "/server",       SL_SRV,    0 },
326     { "/timeout",      SL_TMO,    CM_ARG },
327     { "/userid",       SL_UID,    CM_ARG },
328     { "/wait",         SL_WAIT,   0 },
329     { "", 0, 0 }
330 };
331 static int nshtab = sizeof(shtab)/sizeof(struct keytab) - 1;
332
333 static struct keytab shteltab[] = {     /* TELNET command options */
334 #ifdef CK_AUTHENTICATION
335     { "/auth",         SL_AUTH,   CM_ARG },
336 #endif /* CK_AUTHENTICATION */
337 #ifdef CK_ENCRYPTION
338     { "/encrypt",      SL_ENC,    CM_ARG },
339 #endif /* CK_ENCRYPTION */
340     { "/nowait",       SL_NOWAIT, 0 },
341 #ifndef NOSPL
342 #ifdef CK_AUTHENTICATION
343     { "/password",     SL_PSW,    CM_ARG },
344 #endif /* CK_AUTHENTICATION */
345 #endif /* NOSPL */
346     { "/timeout",      SL_TMO,    CM_ARG },
347     { "/userid",       SL_UID,    CM_ARG },
348     { "/wait",         SL_WAIT,   0 },
349     { "", 0 ,0 }
350 };
351 static int nshteltab = sizeof(shteltab)/sizeof(struct keytab) - 1;
352
353 #ifdef RLOGCODE
354 static struct keytab shrlgtab[] = {     /* SET HOST RLOGIN command options */
355 #ifdef CK_KERBEROS
356 #ifdef CK_ENCRYPTION
357     { "/encrypt",      SL_ENC, 0 },
358 #endif /* CK_ENCRYPTION */
359     { "/k4",           SL_KRB4, CM_INV },
360     { "/k5",           SL_KRB5, CM_INV },
361     { "/kerberos4",    SL_KRB4, 0 },
362     { "/kerberos5",    SL_KRB5, 0 },
363     { "/kerberos_iv",  SL_KRB4, CM_INV },
364     { "/kerberos_v",   SL_KRB5, CM_INV },
365     { "/krb4",         SL_KRB4, CM_INV },
366     { "/krb5",         SL_KRB5, CM_INV },
367 #endif /* CK_KERBEROS */
368     { "", 0 ,0 }
369 };
370 static int nshrlgtab = sizeof(shrlgtab)/sizeof(struct keytab)-1;
371 #endif /* RLOGCODE */
372
373 extern struct keytab netcmd[];
374 extern int nnets;
375 #ifndef NODIAL
376 extern int dirline;
377 extern int nnetdir;                     /* Network services directory */
378 extern char *netdir[];
379 _PROTOTYP( VOID ndreset, (void) );
380 char *nh_p[MAXDNUMS + 1];               /* Network directory entry pointers */
381 char *nh_p2[MAXDNUMS + 1];              /* Network directory entry nettype */
382 char *nh_px[4][MAXDNUMS + 1];           /* Network-specific stuff... */
383 #endif /* NODIAL */
384 int nhcount = 0;
385 int ndinited = 0;
386 char * n_name = NULL;                   /* Network name pointer */
387 #endif /* NETCONN */
388
389 _PROTOTYP(int remtxt, (char **) );
390 _PROTOTYP(VOID rmsg, (void) );
391 _PROTOTYP(static int remcfm, (void) );
392
393 extern int nopush;
394
395 int mdmsav = -1;                        /* Save modem type around network */
396 extern int isguest;                     /* Global flag for anonymous login */
397
398 extern xx_strp xxstring;
399
400 extern int success, binary, b_save, ckwarn, msgflg, quiet, cmask, pflag, local,
401   nettype, escape, mdmtyp, duplex, dfloc, network, cdtimo, autoflow, tnlm,
402   sosi, tlevel, lf_opts, backgrd, flow, debses, parity, ttnproto, ckxech,
403   x_ifnum, cmflgs, haveline, cxtype, cxflow[], maclvl;
404
405 #ifdef DCMDBUF
406 extern struct cmdptr *cmdstk;           /* The command stack itself */
407 #else
408 extern struct cmdptr cmdstk[];          /* The command stack itself */
409 #endif /* DCMDBUF */
410 extern FILE * tfile[];
411 extern char * macp[];
412
413 extern char psave[];                    /* For saving & restoring prompt */
414 extern int sprmlen, rprmlen;
415
416 #ifdef OS2
417 static struct keytab strmkeytab[] = {
418     { "clear",   0, 0 },
419     { "default", 1, 0 }
420 };
421 static int nstrmkeytab = sizeof(strmkeytab)/sizeof(struct keytab);
422
423 static struct keytab strmswitab[] = {
424     { "/literal", 0, 0 }
425 };
426 static int nstrmswitab = sizeof(strmswitab)/sizeof(struct keytab);
427
428 static struct keytab normrev[] = {
429     { "dark-display", 0, 0 },
430     { "light-display", 1, 0 },
431     { "normal",   0, 0 },
432     { "reverse",  1, 0 }
433 };
434
435 static struct keytab prnmtab[] = {
436     { "auto", 1, 0 },
437     { "copy", 2, 0 },
438     { "off",  0, 0 },
439     { "on",   1, CM_INV },              /* Compatibility with XPRINT version */
440     { "user", 3, 0 },
441     { "transparent", 3, CM_INV }        /* not really transparent */
442 };
443 static int nprnmtab = sizeof(prnmtab)/sizeof(struct keytab);
444
445 extern int tt_diff_upd;
446
447 #ifdef NT
448 #define stricmp _stricmp
449 extern int tt_attr_bug;
450 #endif /* NT */
451 extern int tt_rows[], tt_cols[];
452 extern int tt_cols_usr;
453 extern int tt_szchng[VNUM];
454 int tt_modechg = TVC_ENA;
455 extern int tt_url_hilite, tt_url_hilite_attr;
456 extern struct _vtG G[4];
457 extern int priority;
458 extern bool send_c1;
459 int send_c1_usr = FALSE;
460 extern int sgrcolors;
461 extern int marginbell, marginbellcol;
462 extern int autoscroll, wy_autopage;
463 extern int tt_sac;
464 extern int dec_nrc, dec_lang, dec_kbd;
465 #else /* OS2 */
466 extern int tt_rows, tt_cols;
467 #endif /*  OS2 */
468
469 extern int tt_escape;
470 extern long speed;
471
472 extern char *dftty;
473
474 extern char *tp, *lp;                   /* Temporary buffer & pointers */
475 extern char ttname[];
476
477 #ifdef CK_TAPI
478 int tttapi = 0;                         /* is Line TAPI? */
479 struct keytab * tapilinetab = NULL;
480 struct keytab * _tapilinetab = NULL;
481 int ntapiline = 0;
482 #endif /* CK_TAPI */
483
484 #ifdef NETCONN                          /* Network items */
485
486 #ifdef ANYX25
487 extern int revcall, closgr, cudata, nx25;
488 extern char udata[];
489 extern struct keytab x25tab[];
490 #ifndef IBMX25
491 extern int npadx3;
492 extern CHAR padparms[];
493 extern struct keytab padx3tab[];
494 #endif /* IBMX25 */
495 #endif /* ANYX25 */
496
497 #ifdef OS2
498 extern bool ttshare;
499 #ifndef NT
500 extern bool ttslip,ttppp;
501 #endif /* NT */
502 #endif /* OS2 */
503 #ifdef NPIPE
504 extern char pipename[];
505 #endif /* NPIPE */
506
507 #ifdef TCPSOCKET
508 static struct keytab tcprawtab[] = {    /* SET HOST options */
509     { "/default",    NP_DEFAULT,    CM_INV },
510 #ifdef CK_AUTHENTICATION
511 #ifdef CK_KERBEROS
512 #ifdef RLOGCODE
513     { "/ek4login",    NP_EK4LOGIN,    0 },
514     { "/ek5login",    NP_EK5LOGIN,    0 },
515     { "/k4login",     NP_K4LOGIN,     0 },
516     { "/k5login",     NP_K5LOGIN,     0 },
517 #endif /* RLOGCODE */
518 #ifdef KRB5_U2U
519     { "/k5user2user", NP_K5U2U,       0 },
520 #endif /* KRB5_U2U */
521 #endif /* CK_KERBEROS */
522 #endif /* CK_AUTHENTICATION */
523     { "/no-telnet-init", NP_NONE,   0 },
524     { "/none",       NP_NONE,   CM_INV },
525     { "/raw-socket", NP_TCPRAW, 0 },
526 #ifdef RLOGCODE
527     { "/rlogin",     NP_RLOGIN, 0 },
528 #endif /* RLOGCODE */
529 #ifdef CK_SSL
530     { "/ssl",        NP_SSL,    0 },
531     { "/ssl-telnet", NP_SSL_TELNET, 0 },
532 #endif /* CK_SSL */
533     { "/telnet",     NP_TELNET, 0 },
534 #ifdef CK_SSL
535     { "/tls",        NP_TLS,    0 },
536     { "/tls-telnet", NP_TLS_TELNET, 0 },
537 #endif /* CK_SSL */
538     { "", 0, 0 }
539 };
540 static int ntcpraw = (sizeof(tcprawtab) / sizeof(struct keytab)) - 1;
541
542 #ifdef RLOGCODE
543 _PROTOTYP( int rlog_naws, (void) );
544 #endif /* RLOGCODE */
545 #endif /* TCPSOCKET */
546
547 #ifdef SUPERLAT
548 extern char slat_pwd[18];
549 #endif /* SUPERLAT */
550 #endif /* NETCONN */
551
552 #ifdef COMMENT
553 #ifndef NOSETKEY
554 extern KEY *keymap;
555 #ifndef OS2
556 #define mapkey(x) keymap[x]
557 #endif /* OS2 */
558 extern MACRO *macrotab;
559 #ifndef NOKVERBS
560 extern struct keytab kverbs[];
561 extern int nkverbs;
562 #endif /* NOKVERBS */
563 #endif /* NOSETKEY */
564 #else
565 #ifndef NOSETKEY
566 extern KEY *keymap;
567 extern MACRO *macrotab;
568 #ifndef NOKVERBS
569 extern struct keytab kverbs[];
570 extern int nkverbs;
571 #endif /* NOKVERBS */
572 #endif /* NOSETKEY */
573 #endif /* COMMENT */
574
575 #ifdef OS2                              /* AUTODOWNLOAD parameters */
576 extern int    adl_kmode, adl_zmode;     /* Match Packet to signal download */
577 extern char * adl_kstr;                 /* KERMIT Download String */
578 extern char * adl_zstr;                 /* ZMODEM Download String */
579 extern int adl_kc0, adl_zc0;            /* Process ADL C0s in emulation */
580 #endif /* OS2 */
581
582 /* Keyword tables ... */
583
584 extern struct keytab onoff[], rltab[];
585 extern int nrlt;
586
587 #ifndef NOCSETS
588 static struct keytab fdfltab[] = {
589     { "7bit-character-set", 7, 0 },
590     { "8bit-character-set", 8, 0 }
591 };
592 static int nfdflt = (sizeof(fdfltab) / sizeof(struct keytab));
593 #endif /* NOCSETS */
594
595 /* SET FILE parameters */
596
597 static struct keytab filtab[] = {
598 #ifndef NOXFER
599 #ifdef PATTERNS
600     { "binary-patterns",   XYFIBP,  0 },
601 #endif /* PATTERNS */
602     { "bytesize",         XYFILS,   0 },
603 #ifndef NOCSETS
604     { "character-set",    XYFILC,   0 },
605 #endif /* NOCSETS */
606     { "collision",        XYFILX,   0 },
607     { "default",          XYF_DFLT, 0 },
608     { "destination",      XYFILY,   0 },
609     { "display",          XYFILD,   CM_INV },
610 #ifdef CK_TMPDIR
611     { "download-directory", XYFILG, 0 },
612 #endif /* CK_TMPDIR */
613 #endif /* NOXFER */
614     { "end-of-line",      XYFILA,   0 },
615     { "eol",              XYFILA,   CM_INV },
616 #ifdef CK_CTRLZ
617     { "eof",              XYFILV,   0 },
618 #endif /* CK_CTRLZ */
619 #ifndef NOXFER
620     { "fastlookups",      9997,     CM_INV },
621     { "incomplete",       XYFILI,   0 },
622 #ifndef datageneral
623     { "inspection",       XYF_INSP, CM_INV },
624 #endif /* datageneral */
625 #ifdef CK_LABELED
626     { "label",            XYFILL, 0 },
627 #endif /* CK_LABELED */
628
629 #ifdef UNIX
630 #ifdef DYNAMIC
631     { "listsize",         XYF_LSIZ, 0 },
632 #endif /* DYNAMIC */
633 #endif /* UNIX */
634
635     { "names",            XYFILN, 0 },
636 #ifdef UNIX
637     { "output",           XYFILH, 0 },
638 #endif /* UNIX */
639 #ifdef PATTERNS
640     { "patterns",         XYFIPA, 0 },
641 #endif /* PATTERNS */
642 #ifdef COMMENT /* Not implemented (but see CHMOD) */
643     { "permissions",      XYF_PRM, CM_INV },
644     { "protection",       XYF_PRM, 0 },
645 #endif /* COMMENt */
646 #ifdef VMS
647     { "record-length",    XYFILR, 0 },
648 #endif /* VMS */
649 #ifndef datageneral
650     { "scan",             XYF_INSP, 0 },
651 #endif /* datageneral */
652
653 #ifdef UNIX
654 #ifdef DYNAMIC
655     { "stringspace",      XYF_SSPA, 0 },
656 #endif /* DYNAMIC */
657 #endif /* UNIX */
658
659 #ifdef PATTERNS
660     { "t",                XYFILT, CM_INV|CM_ABR },
661     { "text-patterns",    XYFITP, 0 },
662 #endif /* PATTERNS */
663 #endif /* NOXFER */
664     { "type",             XYFILT, 0 },
665 #ifdef UNICODE
666     { "ucs",              XYFILU, 0 },
667 #endif /* UNICODE */
668 #ifndef NOXFER
669     { "warning",          XYFILW, CM_INV }
670 #endif /* NOXFER */
671 };
672 static int nfilp = (sizeof(filtab) / sizeof(struct keytab));
673
674 struct keytab pathtab[] = {
675     { "absolute",  PATH_ABS,  0      },
676     { "none",      PATH_OFF,  CM_INV },
677     { "off",       PATH_OFF,  0      },
678     { "on",        PATH_ABS,  CM_INV },
679     { "relative",  PATH_REL,  0      }
680 };
681 int npathtab = (sizeof(pathtab) / sizeof(struct keytab));
682
683 struct keytab rpathtab[] = {
684     { "absolute",  PATH_ABS,  0      },
685     { "auto",      PATH_AUTO, 0      },
686     { "none",      PATH_OFF,  CM_INV },
687     { "off",       PATH_OFF,  0      },
688     { "on",        PATH_ABS,  CM_INV },
689     { "relative",  PATH_REL,  0      }
690 };
691 int nrpathtab = (sizeof(rpathtab) / sizeof(struct keytab));
692
693 #ifdef CK_CTRLZ
694 struct keytab eoftab[] = {              /* EOF detection method */
695     { "ctrl-z",          1, 0      },
696     { "length",          0, 0      },
697     { "noctrl-z",        0, CM_INV }
698 };
699 #endif /* CK_CTRLZ */
700
701 struct keytab fttab[] = {               /* File types for SET FILE TYPE */
702     { "ascii",     XYFT_T, CM_INV },
703 #ifdef VMS
704     { "b",         XYFT_B, CM_INV|CM_ABR },
705 #endif /* VMS */
706     { "binary",    XYFT_B, 0 },
707 #ifdef VMS
708     { "block",     XYFT_I, CM_INV },
709     { "image",     XYFT_I, 0 },
710 #endif /* VMS */
711 #ifdef CK_LABELED
712     { "labeled",   XYFT_L, 0 },
713 #endif /* CK_LABELED */
714 #ifdef MAC
715     { "macbinary", XYFT_M, 0 },
716 #endif /* MAC */
717     { "text",      XYFT_T, 0 }
718 };
719 int nfttyp = (sizeof(fttab) / sizeof(struct keytab));
720
721 static struct keytab rfttab[] = {       /* File types for REMOTE SET FILE */
722     { "ascii",     XYFT_T, CM_INV },
723     { "binary",    XYFT_B, 0 },
724 #ifdef VMS
725     { "labeled",   XYFT_L, 0 },
726 #else
727 #ifdef OS2
728     { "labeled",   XYFT_L, 0 },
729 #endif /* OS2 */
730 #endif /* VMS */
731     { "text",      XYFT_T, 0 }
732 };
733 static int nrfttyp = (sizeof(rfttab) / sizeof(struct keytab));
734
735 #ifdef OS2ORUNIX
736 #define ZOF_BLK  0
737 #define ZOF_NBLK 1
738 #define ZOF_BUF  2
739 #define ZOF_NBUF 3
740 static struct keytab zoftab[] = {
741     { "blocking",    ZOF_BLK,  0 },
742     { "buffered",    ZOF_BUF,  0 },
743     { "nonblocking", ZOF_NBLK, 0 },
744     { "unbuffered",  ZOF_NBUF, 0 }
745 };
746 static int nzoftab = (sizeof(zoftab) / sizeof(struct keytab));
747 #endif /* OS2ORUNIX */
748
749 extern int query;                       /* Global flag for QUERY active */
750
751 #ifndef NOSPL
752 #ifndef NOXFER
753 static struct keytab vartyp[] = {       /* Variable types for REMOTE QUERY */
754     { "global",   (int) 'G', CM_INV },
755     { "kermit",   (int) 'K', 0 },
756     { "system",   (int) 'S', 0 },
757     { "user",     (int) 'G', 0 }
758 };
759 static int nvartyp = (sizeof(vartyp) / sizeof(struct keytab));
760 #endif /* NOXFER */
761 #endif /* NOSPL */
762
763 #ifdef CK_TIMERS
764 static struct keytab timotab[] = {      /* Timer types */
765     { "dynamic", 1, 0 },
766     { "fixed",   0, 0 }
767 };
768 #endif /* CK_TIMERS */
769
770 #ifdef DCMDBUF
771 extern char *atxbuf, *atmbuf;           /* Atom buffer */
772 extern char *cmdbuf;                    /* Command buffer */
773 extern char *line, *tmpbuf;             /* Character buffers for anything */
774 extern int *intime;                     /* INPUT TIMEOUT */
775
776 #else  /* Not DCMDBUF ... */
777
778 extern char atxbuf[], atmbuf[];         /* Atom buffer */
779 extern char cmdbuf[];                   /* Command buffer */
780 extern char line[], tmpbuf[];           /* Character buffer for anything */
781 extern int intime[];
782
783 #endif /* DCMDBUF */
784
785 #ifndef NOCSETS
786 extern struct keytab fcstab[];          /* For SET FILE CHARACTER-SET */
787 extern struct csinfo fcsinfo[];         /* File character set info. */
788 extern struct keytab ttcstab[];
789 extern int nfilc, fcharset, tcharset, ntermc, tcsr, tcsl, dcset7, dcset8;
790 #ifdef CKOUNI
791 extern int tt_utf8;
792 #endif /* CKOUNI */
793 #ifdef OS2
794 _PROTOTYP( int os2setcp, (int) );
795 _PROTOTYP( int os2getcp, (void) );
796 _PROTOTYP( void os2debugoff, (void) );
797 #endif /* OS2 */
798 #endif /* NOCSETS */
799
800 extern int cmdlvl;                      /* Overall command level */
801
802 #ifndef NOSPL
803 #ifdef DCMDBUF
804 extern int *inpcas;                     /* INPUT CASE setting on cmd stack */
805 #else
806 extern int inpcas[];
807 #endif /* DCMDBUF */
808 #endif /* NOSPL */
809
810 #ifdef CK_CURSES
811 #ifndef VMS
812 _PROTOTYP(int tgetent,(char *, char *));
813 #else
814 #ifdef __DECC
815 _PROTOTYP(int tgetent,(char *, char *));
816 #endif /* __DECC */
817 #endif /* VMS */
818 #endif /* CK_CURSES */
819
820 #ifndef NOXMIT
821 #define XMITF 0                         /* SET TRANSMIT values */
822 #define XMITL 1                         /* (Local to this module) */
823 #define XMITP 2
824 #define XMITE 3
825 #define XMITX 4
826 #define XMITS 5
827 #define XMITW 6
828 #define XMITT 7
829
830 #define XMBUFL 50
831 extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw, xmitt;
832 char xmitbuf[XMBUFL+1] = { NUL };       /* TRANSMIT eof string */
833
834 struct keytab xmitab[] = {              /* SET TRANSMIT */
835     { "echo",          XMITX, 0 },
836     { "eof",           XMITE, 0 },
837     { "fill",          XMITF, 0 },
838     { "linefeed",      XMITL, 0 },
839     { "locking-shift", XMITS, 0 },
840     { "pause",         XMITW, 0 },
841     { "prompt",        XMITP, 0 },
842     { "timeout",       XMITT, 0 }
843 };
844 int nxmit = (sizeof(xmitab) / sizeof(struct keytab));
845 #endif /* NOXMIT */
846
847 /* For SET FILE COLLISION */
848 /* Some of the following may be possible for some C-Kermit implementations */
849 /* but not others.  Those that are not possible for your implementation */
850 /* should be ifdef'd out. */
851
852 struct keytab colxtab[] = { /* SET FILE COLLISION options */
853 #ifndef MAC
854     { "append",    XYFX_A, 0 },         /* append to old file */
855 #endif /* MAC */
856 #ifdef COMMENT
857     { "ask",       XYFX_Q, 0 },         /* ask what to do (not implemented) */
858 #endif
859     { "backup",    XYFX_B, 0 },         /* rename old file */
860 #ifndef MAC
861     /* This crashes Mac Kermit. */
862     { "discard",   XYFX_D, 0 },         /* don't accept new file */
863     { "no-supersede", XYFX_D, CM_INV }, /* ditto (MSK compatibility) */
864 #endif /* MAC */
865     { "overwrite", XYFX_X, 0 },         /* overwrite the old file */
866     { "rename",    XYFX_R, 0 },         /* rename the incoming file */
867 #ifndef MAC                             /* This crashes Mac Kermit. */
868     { "update",    XYFX_U, 0 },         /* replace if newer */
869 #endif /* MAC */
870     { "", 0, 0 }
871 };
872 int ncolx = (sizeof(colxtab) / sizeof(struct keytab)) - 1;
873
874 static struct keytab rfiltab[] = {      /* for REMOTE SET FILE */
875 #ifndef NOCSETS
876     { "character-set", XYFILC, 0 },
877 #endif /* NOCSETS */
878     { "collision",     XYFILX, 0 },
879     { "incomplete",    XYFILI, 0 },
880     { "names",         XYFILN, 0 },
881     { "record-length", XYFILR, 0 },
882     { "type",          XYFILT, 0 }
883 };
884 int nrfilp = (sizeof(rfiltab) / sizeof(struct keytab));
885
886 struct keytab eoltab[] = {              /* File eof delimiters */
887     { "cr",        XYFA_C, 0 },
888     { "crlf",      XYFA_2, 0 },
889     { "lf",        XYFA_L, 0 }
890 };
891 static int neoltab = (sizeof(eoltab) / sizeof(struct keytab));
892
893 struct keytab fntab[] = {               /* File naming */
894     { "converted", XYFN_C, 0      },
895     { "literal",   XYFN_L, 0      },
896     { "standard",  XYFN_C, CM_INV }
897 };
898 int nfntab = (sizeof(fntab) / sizeof(struct keytab));
899
900 #ifndef NOLOCAL
901 /* Terminal parameters table */
902 static struct keytab trmtab[] = {
903 #ifdef OS2
904     { "answerback",    XYTANS,    0 },
905 #endif /* OS2 */
906 #ifdef CK_APC
907     { "apc",           XYTAPC,    0 },
908 #endif /* CK_APC */
909 #ifdef OS2
910     { "arrow-keys",    XYTARR,    0 },
911 #endif /* OS2 */
912 #ifdef NT
913     { "at",            XYTATTR,   CM_INV|CM_ABR },
914     { "att",           XYTATTR,   CM_INV|CM_ABR },
915     { "attr",          XYTATTR,   CM_INV|CM_ABR },
916     { "attr-bug",      XYTATTBUG, CM_INV },
917 #endif /* NT */
918 #ifdef OS2
919     { "attribute",     XYTATTR,   0 },
920 #endif /* OS2 */
921 #ifdef CK_APC
922 #ifdef CK_AUTODL
923    { "autodownload",   XYTAUTODL, 0, },
924 #endif /* CK_AUTODL */
925 #endif /* CK_APC */
926 #ifdef OS2
927     { "autopage",      XYTAPAGE,  0 },
928     { "autoscroll",    XYTASCRL,  0 },
929     { "bell",          XYTBEL,    CM_INV },
930 #endif /* OS2 */
931     { "bytesize",      XYTBYT,    0 },
932 #ifndef NOCSETS
933     { "character-set", XYTCS,     0 },
934 #endif /* NOCSETS */
935 #ifdef OS2
936     { "code-page",     XYTCPG,    0 },
937     { "color",         XYTCOL,    0 },
938     { "controls",      XYTCTRL,   0 },
939 #endif /* OS2 */
940     { "cr-display",    XYTCRD,    0 },
941 #ifdef OS2
942     { "cursor",        XYTCUR,    0 },
943 #endif /* OS2 */
944     { "debug",         XYTDEB,    0 },
945 #ifdef OS2
946     { "dg-unix-mode",  XYTUNX,    0 },
947 #endif /* OS2 */
948     { "echo",          XYTEC,     0 },
949     { "escape-character", XYTESC, 0 },
950 #ifdef OS2
951 #ifdef PCFONTS
952     { "font",          XYTFON,    0 },
953 #else
954 #ifdef KUI
955     { "font",          XYTFON,    0 },
956 #endif /* KUI */
957 #endif /* PCFONTS */
958 #endif /* OS2 */
959     { "height",        XYTHIG,    0 },
960 #ifdef CKTIDLE
961     { "idle-action",   XYTIACT,   0 },
962     { "idle-limit",    XYTITMO,   CM_INV },
963     { "idle-send",     XYTIDLE,   CM_INV },
964     { "idle-timeout",  XYTITMO,   0 },
965 #endif /* CKTIDLE */
966 #ifdef OS2
967 #ifndef NOCSETS
968     { "kbd-follows-gl/gr", XYTKBDGL, 0 },
969 #endif /* NOCSETS */
970     { "key",           XYTKEY,    0 },
971     { "keyboard-mode", XYTKBMOD,  0 },
972     { "keypad-mode",   XYTKPD,    0 },
973 #endif /* OS2 */
974 #ifndef NOCSETS
975 #ifdef OS2
976 #ifndef KUI
977     { "line-spacing",  XYTLSP,    CM_INV },
978     { "local-character-set", XYTLCS,  0 },
979 #else
980     { "line-spacing",  XYTLSP,    0 },
981     { "local-character-set", XYTLCS,  CM_INV },
982 #endif /* KUI */
983 #else
984     { "local-character-set", XYTLCS,  CM_INV },
985 #endif /* OS2 */
986 #endif /* NOCSETS */
987     { "locking-shift", XYTSO,     0 },
988 #ifdef OS2
989     { "margin-bell",   XYTMBEL,   0 },
990 #endif /* OS2 */
991 #ifdef OS2MOUSE
992     { "mouse",         XYTMOU,    CM_INV },
993 #endif /* OS2MOUSE */
994     { "newline-mode",  XYTNL,     0 },
995 #ifdef OS2
996     { "output-pacing", XYTPAC,    0 },
997 #ifdef PCTERM
998     { "pcterm",        XYTPCTERM, 0 },
999 #endif /* PCTERM */
1000 #endif /* OS2 */
1001 #ifdef OS2ORUNIX
1002     { "print",         XYTPRN,    0 },
1003 #endif /* OS2ORUNIX */
1004 #ifndef NOCSETS
1005 #ifdef OS2
1006     { "remote-character-set", XYTRCS,  0 },
1007 #else
1008     { "remote-character-set", XYTRCS,  CM_INV },
1009 #endif /* OS2 */
1010 #endif /* NOCSETS */
1011 #ifdef OS2
1012     { "roll-mode",       XYTROL, 0 },
1013     { "s",               XYTUPD, CM_ABR|CM_INV },
1014     { "sc",              XYTUPD, CM_ABR|CM_INV },
1015     { "scr",             XYTUPD, CM_ABR|CM_INV },
1016     { "scree",           XYTUPD, CM_ABR|CM_INV },
1017     { "screen",          XYTUPD, CM_ABR|CM_INV },
1018     { "screen-",         XYTUPD, CM_ABR|CM_INV },
1019     { "screen-mode",     XYTSCNM,   0 },
1020     { "screen-optimize", XYTOPTI,   0 },
1021     { "screen-update",   XYTUPD,    0 },
1022     { "scrollback",      XYSCRS,    0 },
1023     { "send-data",         XYTSEND, 0 },
1024     { "send-end-of-block", XYTSEOB, 0 },
1025     { "sgr-colors",            XYTSGRC,  0 },
1026     { "sni-ch.code",           XYTSNICC, 0 },
1027     { "sni-firmware-versions", XYTSNIFV, 0 },
1028     { "sni-language",          XYTVTLNG, 0 },
1029     { "sni-pagemode",          XYTSNIPM, CM_INV },
1030     { "sni-scrollmode",              XYTSNISM, CM_INV },
1031     { "spacing-attribute-character", XYTSAC,   CM_INV },
1032     { "statusline",                  XYTSTAT,  0 },
1033     { "tra",                         XYTCTS,   CM_INV|CM_ABR },
1034     { "transmit-timeout",            XYTCTS,   0 },
1035 #endif /* OS2 */
1036
1037 #ifdef OS2ORUNIX
1038     { "transparent-print", XYTPRN,   CM_INV },
1039 #endif /* OS2ORUNIX */
1040
1041 #ifdef CK_TRIGGER
1042     { "trigger",           XYTRIGGER,0 },
1043 #endif /* CK_TRIGGER */
1044 #ifdef OS2
1045     { "type",              XYTTYP,   0 },
1046 #else
1047     { "type",              XYTTYP,   CM_INV },
1048 #endif /* OS2 */
1049
1050 #ifndef NOCSETS
1051 #ifdef UNICODE
1052 #ifdef CKOUNI
1053     { "unicode",           XYTUNI,   CM_INV },
1054 #endif /* CKOUNI */
1055 #endif /* UNICODE */
1056 #endif /* NOCSETS */
1057 #ifdef OS2
1058     { "unix-mode",         XYTUNX,   CM_INV },
1059     { "url-highlight",     XYTURLHI, 0 },
1060 #ifdef NT
1061     { "video-change",      XYTVCH,   0 },
1062 #endif /* NT */
1063     { "vt-language",       XYTVTLNG, 0 },
1064     { "vt-nrc-mode",       XYTVTNRC, 0 },
1065 #endif /* OS2 */
1066     { "width",             XYTWID,   0 },
1067 #ifdef OS2
1068     { "wrap",              XYTWRP,   0 },
1069 #endif /* OS2 */
1070     { "", 0, 0 }
1071 };
1072 int ntrm = (sizeof(trmtab) / sizeof(struct keytab)) - 1;
1073
1074 #ifdef OS2
1075 struct keytab termctrl[] = {    /* SET TERM CONTROLS */
1076     { "7",      7, 0 },
1077     { "8",      8, 0 }
1078 };
1079 int ntermctrl = (sizeof(termctrl) / sizeof(struct keytab));
1080
1081 struct keytab curontab[] = {    /* SET TERM CURSOR */
1082 #ifdef KUI
1083     { "noblink", 2, 0 },
1084 #else
1085     { "noblink", 2, CM_INV },
1086 #endif /* KUI */
1087     { "off",     0, 0 },
1088     { "on",      1, 0 }
1089 };
1090 int ncuron = (sizeof(curontab) / sizeof(struct keytab));
1091
1092 struct keytab rolltab[] = {   /* Set TERM Roll Options */
1093     { "insert",    TTR_INSERT, 0      },
1094     { "keystrokes",TTR_KEYS,   0      },
1095     { "off",       TTR_OVER,   CM_INV },
1096     { "on",        TTR_INSERT, CM_INV },
1097     { "overwrite", TTR_OVER,   0      }
1098 };
1099 int nroll = (sizeof(rolltab) / sizeof(struct keytab));
1100
1101 struct keytab rollkeytab[] = {          /* Set TERM ROLL KEYSTROKES */
1102     { "ignore",            TTRK_IGN, 0 },
1103     { "restore-and-send",  TTRK_RST, 0 },
1104     { "send",              TTRK_SND, 0 }
1105 };
1106 int nrollkey = (sizeof(rollkeytab) / sizeof(struct keytab));
1107
1108 #define TT_GR_ALL 4
1109 #define TT_GR_G0  0
1110 #define TT_GR_G1  1
1111 #define TT_GR_G2  2
1112 #define TT_GR_G3  3
1113 #define TT_GR_KBD 4
1114 struct keytab graphsettab[] = {  /* DEC VT Graphic Sets */
1115     { "all",      TT_GR_ALL, 0 },
1116     { "g0",       TT_GR_G0,  0 },
1117     { "g1",       TT_GR_G1,  0 },
1118     { "g2",       TT_GR_G2,  0 },
1119     { "g3",       TT_GR_G3,  0 },
1120     { "keyboard", TT_GR_KBD, 0 }
1121 };
1122 int ngraphset = (sizeof(graphsettab) / sizeof(struct keytab));
1123 #endif /* OS2 */
1124
1125 struct keytab adltab[] = {              /* Autodownload Options */
1126     { "ask",     TAD_ASK, 0 },
1127     { "error",   TAD_ERR, 0 },
1128 #ifdef OS2
1129     { "kermit",  TAD_K,   0 },
1130 #endif /* OS2 */
1131     { "off",     TAD_OFF, 0 },
1132     { "on",      TAD_ON,  0 },
1133 #ifdef OS2
1134     { "zmodem",  TAD_Z,   0 },
1135 #endif /* OS2 */
1136     { "", 0, 0 }
1137 };
1138 int nadltab = (sizeof(adltab) / sizeof(struct keytab)) - 1;
1139
1140 struct keytab adlerrtab[] = {           /* Autodownload Error Options */
1141     { "continue", 0, 0 },
1142     { "go",       0, CM_INV },
1143     { "stop",     1, 0 }
1144 };
1145 int nadlerrtab = (sizeof(adlerrtab) / sizeof(struct keytab));
1146
1147 #ifdef OS2
1148 struct keytab adlxtab[] = {             /* Autodownload Options */
1149     { "c0-conflicts",     TAD_X_C0,     0 },
1150     { "detection-method", TAD_X_DETECT, 0 },
1151     { "string",           TAD_X_STR,    0 }
1152 };
1153 int nadlxtab = (sizeof(adlxtab) / sizeof(struct keytab));
1154
1155 struct keytab adldtab[] = {             /* Auto-dl Detection Methods */
1156     { "packet",           ADL_PACK,     0 },
1157     { "string",           ADL_STR,      0 }
1158 };
1159 int nadldtab = (sizeof(adldtab) / sizeof(struct keytab));
1160
1161 struct keytab adlc0tab[] = {            /* Auto-dl Detection Methods */
1162     { "ignored-by-emulator",    0,      0 },
1163     { "processed-by-emulator",  1,      0 }
1164 };
1165 int nadlc0tab = (sizeof(adlc0tab) / sizeof(struct keytab));
1166
1167 #ifndef NOCSETS
1168 struct keytab vtlangtab[] = {
1169     { "belgian",        VTL_BELGIAN , 0 },
1170     { "british",        VTL_BRITISH , 0 },
1171     { "canadian",       VTL_CANADIAN, 0 },
1172     { "czech",          VTL_CZECH   , 0 },
1173     { "danish",         VTL_DANISH  , 0 },
1174     { "dutch",          VTL_DUTCH   , 0 },
1175     { "finnish",        VTL_FINNISH , 0 },
1176     { "french",         VTL_FRENCH  , 0 },
1177     { "french-canadian",VTL_FR_CAN  , 0 },
1178     { "german",         VTL_GERMAN  , 0 },
1179     { "greek",          VTL_GREEK   , 0 },
1180     { "hebrew",         VTL_HEBREW  , 0 },
1181     { "hungarian",      VTL_HUNGARIA, 0 },
1182     { "italian",        VTL_ITALIAN , 0 },
1183     { "latin-american", VTL_LATIN_AM, 0 },
1184     { "north-american", VTL_NORTH_AM, 0 },
1185     { "norwegian",      VTL_NORWEGIA, 0 },
1186     { "polish",         VTL_POLISH  , 0 },
1187     { "portugese",      VTL_PORTUGES, 0 },
1188     { "romanian",       VTL_ROMANIAN, 0 },
1189     { "russian",        VTL_RUSSIAN , 0 },
1190     { "scs",            VTL_SCS     , CM_INV },
1191     { "slovak",         VTL_SLOVAK  , 0 },
1192     { "spanish",        VTL_SPANISH , 0 },
1193     { "swedish",        VTL_SWEDISH , 0 },
1194     { "swiss-french",   VTL_SW_FR   , 0 },
1195     { "swiss-german",   VTL_SW_GR   , 0 },
1196     { "turkish-f",      VTL_TURK_F  , CM_INV },
1197     { "turkish-q",      VTL_TURK_Q  , CM_INV }
1198 };
1199 int nvtlangtab = (sizeof(vtlangtab) / sizeof(struct keytab));
1200 #endif /* NOCSETS */
1201 #endif /* OS2 */
1202
1203 struct keytab crdtab[] = {              /* Carriage-return display */
1204     { "crlf",        1, 0 },
1205     { "normal",      0, 0 }
1206 };
1207 extern int tt_crd;                      /* Carriage-return display variable */
1208
1209 #ifdef CK_APC
1210 extern int apcstatus, apcactive;
1211 static struct keytab apctab[] = {       /* Terminal APC parameters */
1212     {  "no-input", APC_ON|APC_NOINP,0 },
1213     { "off",       APC_OFF,  0 },
1214     { "on",        APC_ON,   0 },
1215     { "unchecked", APC_ON|APC_UNCH, 0 },
1216     { "unchecked-no-input", APC_ON|APC_NOINP|APC_UNCH, 0 }
1217 };
1218 int napctab = (sizeof(apctab) / sizeof(struct keytab));
1219 #endif /* CK_APC */
1220 #endif /* NOLOCAL */
1221
1222 extern int autodl, adl_err, adl_ask;
1223
1224 struct keytab beltab[] = {              /* Terminal bell mode */
1225 #ifdef OS2
1226     { "audible", XYB_AUD,  0 },
1227     { "none",    XYB_NONE, 0 },
1228 #else
1229     { "audible", XYB_AUD,  CM_INV },
1230     { "none",    XYB_NONE, CM_INV },
1231 #endif /* OS2 */
1232 #ifdef OS2
1233     { "off",     XYB_NONE, CM_INV },
1234     { "on",      XYB_AUD,  CM_INV },
1235 #else
1236     { "off",     XYB_NONE, 0 },
1237     { "on",      XYB_AUD,  0 },
1238 #endif /* OS2 */
1239 #ifdef OS2
1240     { "visible", XYB_VIS,  0 },
1241 #endif /* OS2 */
1242     { "", 0, 0 }
1243 };
1244 int nbeltab = sizeof(beltab)/sizeof(struct keytab) - 1;
1245
1246 int tt_unicode = 1;                     /* Use Unicode if possible */
1247 #ifdef CKTIDLE
1248 int tt_idlesnd_tmo = 0;                 /* Idle Send Timeout, disabled */
1249 char * tt_idlesnd_str = NULL;           /* Idle Send String, none */
1250 char * tt_idlestr = NULL;
1251 extern int tt_idleact, tt_idlelimit;
1252 #endif /* CKTIDLE */
1253
1254 #ifdef OS2
1255 #ifndef NOLOCAL
1256 /*
1257   OS/2 serial communication devices.
1258 */
1259 struct keytab os2devtab[] = {
1260     { "1",    1, CM_INV },                      /* Invisible synonyms, like */
1261     { "2",    2, CM_INV },                      /* "set port 1" */
1262     { "3",    3, CM_INV },
1263     { "4",    4, CM_INV },
1264     { "5",    5, CM_INV },
1265     { "6",    6, CM_INV },
1266     { "7",    7, CM_INV },
1267     { "8",    8, CM_INV },
1268     { "com1", 1, 0 },                   /* Real device names */
1269     { "com2", 2, 0 },
1270     { "com3", 3, 0 },
1271     { "com4", 4, 0 },
1272     { "com5", 5, 0 },
1273     { "com6", 6, 0 },
1274     { "com7", 7, 0 },
1275     { "com8", 8, 0 },
1276 #ifdef OS2ONLY
1277     { "slipcom1", 1, 0 },                       /* For use with SLIP driver */
1278     { "slipcom2", 2, 0 },                       /* shared access */
1279     { "slipcom3", 3, 0 },
1280     { "slipcom4", 4, 0 },
1281     { "slipcom5", 5, 0 },
1282     { "slipcom6", 6, 0 },
1283     { "slipcom7", 7, 0 },
1284     { "slipcom8", 8, 0 },
1285     { "pppcom1", 1, 0 },                        /* For use with PPP driver */
1286     { "pppcom2", 2, 0 },                        /* shared access */
1287     { "pppcom3", 3, 0 },
1288     { "pppcom4", 4, 0 },
1289     { "pppcom5", 5, 0 },
1290     { "pppcom6", 6, 0 },
1291     { "pppcom7", 7, 0 },
1292     { "pppcom8", 8, 0 }
1293 #endif /* OS2ONLY */
1294 };
1295 int nos2dev = (sizeof(os2devtab) / sizeof(struct keytab)) - 1;
1296
1297 #ifdef OS2ONLY
1298 struct keytab os2ppptab[] = {
1299     { "0",    0, CM_INV },
1300     { "1",    1, CM_INV },                      /* Invisible synonyms, like */
1301     { "2",    2, CM_INV },                      /* "set port 1" */
1302     { "3",    3, CM_INV },
1303     { "4",    4, CM_INV },
1304     { "5",    5, CM_INV },
1305     { "6",    6, CM_INV },
1306     { "7",    7, CM_INV },
1307     { "8",    8, CM_INV },
1308     { "9",    9, CM_INV },
1309     { "ppp0", 0, 0 },
1310     { "ppp1", 1, 0 },                   /* For use with PPP driver */
1311     { "ppp2", 2, 0 },                   /* shared access */
1312     { "ppp3", 3, 0 },
1313     { "ppp4", 4, 0 },
1314     { "ppp5", 5, 0 },
1315     { "ppp6", 6, 0 },
1316     { "ppp7", 7, 0 },
1317     { "ppp8", 8, 0 },
1318     { "ppp9", 9, 0 }
1319 };
1320 int nos2ppp = (sizeof(os2ppptab) / sizeof(struct keytab));
1321 #endif /* OS2ONLY */
1322
1323 /*
1324   Terminal parameters that can be set by SET commands.
1325   Used by the ck?con.c terminal emulator code.
1326   For now, only used for #ifdef OS2.  Should add these for Macintosh.
1327 */
1328 int tt_arrow = TTK_NORM;                /* Arrow key mode: normal (cursor) */
1329 int tt_keypad = TTK_NORM;               /* Keypad mode: normal (numeric) */
1330 int tt_shift_keypad = 0;                /* Keypad Shift mode: Off */
1331 int tt_wrap = 1;                        /* Terminal wrap, 1 = On */
1332 int tt_type = TT_VT320;                 /* Terminal type, initially VT320 */
1333 int tt_type_mode = TT_VT320;            /* Terminal type set by host command */
1334 int tt_cursor = 0;                      /* Terminal cursor, 0 = Underline */
1335 int tt_cursor_usr = 0;                  /* Users Terminal cursor type */
1336 int tt_cursorena_usr = 1;               /* Users Terminal cursor enabled */
1337 int tt_cursor_blink = 1;                /* Terminal Cursor Blink */
1338 int tt_answer = 0;                      /* Terminal answerback (disabled) */
1339 int tt_scrsize[VNUM] = {512,512,512,1}; /* Terminal scrollback buffer size */
1340 int tt_roll[VNUM] = {1,1,1,1};          /* Terminal roll (on) */
1341 int tt_rkeys[VNUM] = {1,1,1,1};         /* Terminal roll keys (send) */
1342 int tt_pacing = 0;                      /* Terminal output-pacing (none) */
1343 int tt_ctstmo = 15;                     /* Terminal transmit-timeout */
1344 int tt_codepage = -1;                   /* Terminal code-page */
1345 int tt_update = 100;                    /* Terminal screen-update interval */
1346 int tt_updmode = TTU_FAST;              /* Terminal screen-update mode FAST */
1347 extern int updmode;
1348 #ifndef KUI
1349 int tt_status[VNUM] = {1,1,0,0};        /* Terminal status line displayed */
1350 int tt_status_usr[VNUM] = {1,1,0,0};
1351 #else  /* KUI */
1352 extern CKFLOAT floatval;
1353 CKFLOAT tt_linespacing[VNUM] = {1.0,1.0,1.0,1.0};
1354 #ifdef K95G
1355 int tt_status[VNUM] = {1,1,0,0};        /* Terminal status line displayed */
1356 int tt_status_usr[VNUM] = {1,1,0,0};
1357 #else /* K95G */
1358 int tt_status[VNUM] = {0,0,0,0};        /* Terminal status line displayed */
1359 int tt_status_usr[VNUM] = {0,0,0,0};
1360 #endif /* K95G */
1361 #endif /* KUI */
1362 int tt_senddata = 0;                    /* Let host read terminal data */
1363 extern int wy_blockend;                 /* Terminal Send Data EOB type */
1364 int tt_hidattr = 1;                     /* Attributes are hidden */
1365
1366 extern unsigned char colornormal, colorselect,
1367 colorunderline, colorstatus, colorhelp, colorborder,
1368 colorgraphic, colordebug, colorreverse, coloritalic;
1369
1370 extern int trueblink, trueunderline, truereverse, trueitalic, truedim;
1371
1372 extern int bgi, fgi;
1373 extern int scrninitialized[];
1374
1375 struct keytab audibletab[] = {          /* Terminal Bell Audible mode */
1376     { "beep",          XYB_BEEP, 0 },   /* Values ORd with bell mode */
1377     { "system-sounds", XYB_SYS,  0 }
1378 };
1379 int naudibletab = sizeof(audibletab)/sizeof(struct keytab);
1380
1381 struct keytab akmtab[] = {              /* Arrow key mode */
1382     { "application", TTK_APPL, 0 },
1383     { "cursor",      TTK_NORM, 0 }
1384 };
1385 struct keytab kpmtab[] = {              /* Keypad mode */
1386     { "application", TTK_APPL, 0 },
1387     { "numeric",     TTK_NORM, 0 }
1388 };
1389
1390 struct keytab ttcolmodetab[] = {
1391     { "current-color", 0, 0 },
1392     { "default-color", 1, 0 }
1393 };
1394 int ncolmode = sizeof(ttcolmodetab)/sizeof(struct keytab);
1395
1396 #define TTCOLNOR  0
1397 #define TTCOLREV  1
1398 #define TTCOLUND  2
1399 #define TTCOLSTA  3
1400 #define TTCOLHLP  4
1401 #define TTCOLBOR  5
1402 #define TTCOLSEL  6
1403 #define TTCOLDEB  7
1404 #define TTCOLGRP  8
1405 #define TTCOLITA  9
1406 #define TTCOLRES  10
1407 #define TTCOLERA  11
1408
1409 struct keytab ttycoltab[] = {                   /* Terminal Screen coloring */
1410     { "border",             TTCOLBOR, 0 },      /* Screen border color */
1411     { "debug-terminal",     TTCOLDEB, 0 },      /* Debug color */
1412     { "erase",              TTCOLERA, 0 },      /* Erase mode */
1413     { "graphic",            TTCOLGRP, 0 },      /* Graphic Color */
1414     { "help-text",          TTCOLHLP, 0 },      /* Help screens */
1415     { "italic",             TTCOLITA, 0 },      /* Italic Color */
1416     { "normal",             TTCOLNOR, CM_INV }, /* Normal screen text */
1417     { "reset-on-esc[0m",    TTCOLRES, 0 },      /* Reset on ESC [ 0 m */
1418     { "reverse-video",      TTCOLREV, 0 },      /* Reverse video */
1419     { "status-line",        TTCOLSTA, 0 },      /* Status line */
1420     { "selection",          TTCOLSEL, 0 },      /* Selection color */
1421     { "terminal-screen",    TTCOLNOR, 0 },      /* Better name than "normal" */
1422     { "underlined-text",    TTCOLUND, 0 }       /* Underlined text */
1423 };
1424 int ncolors = (sizeof(ttycoltab) / sizeof(struct keytab));
1425
1426 #define TTATTNOR  0
1427 #define TTATTBLI  1
1428 #define TTATTREV  2
1429 #define TTATTUND  3
1430 #define TTATTPRO  4
1431 #define TTATTBLD  5
1432 #define TTATTDIM  6
1433 #define TTATTINV  7
1434 #define TTATTITA  8
1435 #define TTATTDONE 9
1436
1437 struct keytab ttyattrtab[] = {
1438     { "blink",     TTATTBLI, 0 },
1439     { "dim",       TTATTDIM, 0 },
1440     { "italic",    TTATTITA, 0 },
1441     { "protected", TTATTPRO, 0 },
1442     { "reverse",   TTATTREV, 0 },
1443     { "underline", TTATTUND, 0 }
1444 };
1445 int nattrib = (sizeof(ttyattrtab) / sizeof(struct keytab));
1446
1447 struct keytab ttyprotab[] = {
1448     { "blink",       TTATTBLI,  0 },
1449     { "bold",        TTATTBLD,  0 },
1450     { "dim",         TTATTDIM,  0 },
1451     { "done",        TTATTDONE, CM_INV },
1452     { "invisible",   TTATTINV,  0 },
1453     { "italic",      TTATTITA,  0 },
1454     { "normal",      TTATTNOR,  0 },
1455     { "reverse",     TTATTREV,  0 },
1456     { "underlined",  TTATTUND,  0 }
1457
1458 };
1459 int nprotect = (sizeof(ttyprotab) / sizeof(struct keytab));
1460
1461 struct keytab ttyseobtab[] = {
1462     { "crlf_etx",  1, 0 },
1463     { "us_cr",     0, 0 }
1464 };
1465
1466 struct keytab ttyclrtab[] = {           /* Colors */
1467     { "black",         0, 0      },
1468     { "blue",          1, 0      },
1469     { "brown",         6, 0      },
1470     { "cyan",          3, 0      },
1471     { "darkgray",      8, CM_INV },
1472     { "dgray",         8, 0      },
1473     { "green",         2, 0      },
1474     { "lblue",         9, CM_INV },
1475     { "lcyan",        11, CM_INV },
1476     { "lgray",         7, CM_INV },
1477     { "lgreen",       10, CM_INV },
1478     { "lightblue",     9, 0      },
1479     { "lightcyan",    11, 0      },
1480     { "lightgray",     7, 0      },
1481     { "lightgreen",   10, 0      },
1482     { "lightmagenta", 13, 0      },
1483     { "lightred",     12, 0      },
1484     { "lmagenta",     13, CM_INV },
1485     { "lred",         12, CM_INV },
1486     { "magenta",       5, 0      },
1487     { "red",           4, 0      },
1488     { "white",        15, 0      },
1489     { "yellow",       14, 0      }
1490 };
1491 int nclrs = (sizeof (ttyclrtab) / sizeof (struct keytab));
1492
1493 struct keytab ttycurtab[] = {
1494     { "full",        TTC_BLOCK, 0 },
1495     { "half",        TTC_HALF,  0 },
1496     { "underline",   TTC_ULINE, 0 }
1497 };
1498 int ncursors = 3;
1499
1500 struct keytab ttyptab[] = {
1501     { "aaa",      TT_AAA,     CM_INV },     /* AnnArbor */
1502     { "adm3a",    TT_ADM3A,   0 },          /* LSI ADM-3A */
1503     { "adm5",     TT_ADM5,    0 },          /* LSI ADM-5 */
1504     { "aixterm",  TT_AIXTERM, 0 },          /* IBM AIXterm */
1505     { "annarbor", TT_AAA,     0 },          /* AnnArbor */
1506     { "ansi-bbs", TT_ANSI,    0 },          /* ANSI.SYS (BBS) */
1507     { "at386",    TT_AT386,   0 },          /* Unixware ANSI */
1508     { "avatar/0+",TT_ANSI,    0 },          /* AVATAR/0+ */
1509     { "ba80",     TT_BA80,    0 },          /* Nixdorf BA80 */
1510     { "be",       TT_BEOS,    CM_INV|CM_ABR },
1511     { "beos-ansi",TT_BEOS,    CM_INV },     /* BeOS ANSI */
1512     { "beterm",   TT_BEOS,    0 },          /* BeOS Terminal (as of PR2 ) */
1513     { "d200",     TT_DG200,   CM_INV|CM_ABR }, /* Data General DASHER 200 */
1514     { "d210",     TT_DG210,   CM_INV|CM_ABR }, /* Data General DASHER 210 */
1515     { "d217",     TT_DG217,   CM_INV|CM_ABR }, /* Data General DASHER 217 */
1516     { "dg200",    TT_DG200,   0 },          /* Data General DASHER 200 */
1517     { "dg210",    TT_DG210,   0 },          /* Data General DASHER 210 */
1518     { "dg217",    TT_DG217,   0 },          /* Data General DASHER 217 */
1519     { "h1500",    TT_HZL1500, CM_INV },     /* Hazeltine 1500 */
1520     { "h19",      TT_H19,     CM_INV },     /* Heath-19 */
1521     { "heath19",  TT_H19,     0 },          /* Heath-19 */
1522     { "hft",      TT_HFT,     0 },          /* IBM High Function Terminal */
1523     { "hp2621a",  TT_HP2621,  0 },          /* HP 2621A */
1524     { "hpterm",   TT_HPTERM,  0 },          /* HP TERM */
1525     { "hz1500",   TT_HZL1500, 0 },          /* Hazeltine 1500 */
1526     { "ibm3151",  TT_IBM31,   0 },          /* IBM 3101-xx,3161 */
1527     { "linux",    TT_LINUX,   0 },          /* Linux */
1528     { "qansi",    TT_QANSI,   0 },          /* QNX ANSI */
1529     { "qnx",      TT_QNX,     0 },          /* QNX Console */
1530     { "scoansi",  TT_SCOANSI, 0 },          /* SCO ANSI */
1531     { "sni-97801",TT_97801,   0 },          /* SNI 97801 */
1532     { "sun",      TT_SUN,     0 },          /* SUN Console */
1533 /*
1534   The idea of NONE is to let the console driver handle the escape sequences,
1535   which, in theory at least, would give not only ANSI emulation, but also any
1536   other kind of emulation that might be provided by alternative console
1537   drivers, if any existed.
1538
1539   For this to work, ckocon.c would need to be modified to make higher-level
1540   calls, like VioWrtTTY(), DosWrite(), or (simply) write(), rather than
1541   VioWrt*Cell() and similar, and it would also have to give up its rollback
1542   feature, and its status line and help screens would also have to be
1543   forgotten or else done in an ANSI way.
1544
1545   As matters stand, we already have perfectly good ANSI emulation built in,
1546   and there are no alternative console drivers available, so there is no point
1547   in having a terminal type of NONE, so it is commented out.  However, should
1548   you uncomment it, it will work like a "glass tty" -- no escape sequence
1549   interpretation at all; somewhat similar to debug mode, except without the
1550   debugging (no highlighting of control chars or escape sequences); help
1551   screens, status line, and rollback will still work.
1552 */
1553 #ifdef OS2PM
1554 #ifdef COMMENT
1555     { "tek4014", TT_TEK40,  0 },
1556 #endif /* COMMENT */
1557 #endif /* OS2PM */
1558     { "tty",     TT_NONE,   0 },
1559     { "tvi910+", TT_TVI910, 0 },
1560     { "tvi925",  TT_TVI925, 0 },
1561     { "tvi950",  TT_TVI950, 0 },
1562     { "vc404",   TT_VC4404, 0 },
1563     { "vc4404",  TT_VC4404, CM_INV },
1564     { "vip7809", TT_VIP7809,0 },
1565     { "vt100",   TT_VT100,  0 },
1566     { "vt102",   TT_VT102,  0 },
1567     { "vt220",   TT_VT220,  0 },
1568     { "vt220pc", TT_VT220PC,0 },
1569     { "vt320",   TT_VT320,  0 },
1570     { "vt320pc", TT_VT320PC,0 },
1571     { "vt52",    TT_VT52,   0 },
1572 #ifdef NT
1573     { "vtnt",    TT_VTNT,   0 },
1574 #else /* NT */
1575     { "vtnt",    TT_VTNT,  CM_INV },
1576 #endif /* NT */
1577     { "wy160",   TT_WY160,  0 },
1578     { "wy30",    TT_WY30,   0 },
1579     { "wy370",   TT_WY370,  0 },
1580     { "wy50",    TT_WY50,   0 },
1581     { "wy60",    TT_WY60,   0 },
1582     { "wyse30",  TT_WY30,   CM_INV },
1583     { "wyse370", TT_WY370,  CM_INV },
1584     { "wyse50",  TT_WY50,   CM_INV },
1585     { "wyse60",  TT_WY60,   CM_INV }
1586 };
1587 int nttyp = (sizeof(ttyptab) / sizeof(struct keytab));
1588
1589 struct keytab ttkeytab[] = {
1590     { "aaa",       TT_AAA,        CM_INV },        /* AnnArbor */
1591     { "adm3a",     TT_ADM3A,      0 },             /* LSI ADM-3A */
1592     { "adm5",      TT_ADM5,       0 },             /* LSI ADM-5 */
1593     { "aixterm",   TT_AIXTERM,    0 },             /* IBM AIXterm */
1594     { "annarbor",  TT_AAA,        0 },             /* AnnArbor */
1595     { "ansi-bbs",  TT_ANSI,       0 },             /* ANSI.SYS (BBS) */
1596     { "at386",     TT_AT386,      0 },             /* Unixware ANSI */
1597     { "avatar/0+", TT_ANSI,       0 },             /* AVATAR/0+ */
1598     { "ba80",      TT_BA80,       0 },             /* Nixdorf BA80 */
1599     { "be",        TT_BEOS,       CM_INV|CM_ABR },
1600     { "beos-ansi", TT_BEOS,       CM_INV },        /* BeOS ANSI */
1601     { "beterm",    TT_BEOS,       0 },             /* BeOS Terminal (DR2) */
1602     { "d200",      TT_DG200,      CM_INV|CM_ABR }, /* DG DASHER 200 */
1603     { "d210",      TT_DG210,      CM_INV|CM_ABR }, /* DG DASHER 210 */
1604     { "d217",      TT_DG217,      CM_INV|CM_ABR }, /* DG DASHER 217 */
1605     { "dg200",     TT_DG200,      0 },             /* DG DASHER 200 */
1606     { "dg210",     TT_DG210,      0 },             /* DG DASHER 210 */
1607     { "dg217",     TT_DG217,      0 },             /* DG DASHER 217 */
1608     { "emacs",     TT_KBM_EMACS,  0 },             /* Emacs mode */
1609     { "h19",       TT_H19,        CM_INV },        /* Heath-19 */
1610     { "heath19",   TT_H19,        0 },             /* Heath-19 */
1611     { "hebrew",    TT_KBM_HEBREW, 0 },             /* Hebrew mode */
1612     { "hft",       TT_HFT,        0 },             /* IBM High Function Term */
1613     { "hp2621a",   TT_HP2621,     0 },             /* HP 2621A */
1614     { "hpterm",    TT_HPTERM,     0 },             /* HP TERM */
1615     { "hz1500",    TT_HZL1500,    0 },             /* Hazeltine 1500 */
1616     { "ibm3151",   TT_IBM31,      0 },             /* IBM 3101-xx,3161 */
1617     { "linux",     TT_LINUX,      0 },             /* Linux */
1618     { "qansi",     TT_QANSI,      0 },             /* QNX ANSI */
1619     { "qnx",       TT_QNX,        0 },             /* QNX */
1620     { "russian",   TT_KBM_RUSSIAN,0 },             /* Russian mode */
1621     { "scoansi",   TT_SCOANSI,    0 },             /* SCO ANSI */
1622     { "sni-97801", TT_97801,      0 },             /* SNI 97801 */
1623     { "sun",       TT_SUN,        0 },             /* SUN Console */
1624 #ifdef OS2PM
1625 #ifdef COMMENT
1626     { "tek4014",   TT_TEK40,      0 },
1627 #endif /* COMMENT */
1628 #endif /* OS2PM */
1629     { "tty",       TT_NONE,       0 },
1630     { "tvi910+",   TT_TVI910,     0 },
1631     { "tvi925",    TT_TVI925,     0 },
1632     { "tvi950",    TT_TVI950,     0 },
1633     { "vc404",     TT_VC4404,     0 },
1634     { "vc4404",    TT_VC4404,     CM_INV },
1635     { "vip7809",   TT_VIP7809,    0 },
1636     { "vt100",     TT_VT100,      0 },
1637     { "vt102",     TT_VT102,      0 },
1638     { "vt220",     TT_VT220,      0 },
1639     { "vt220pc",   TT_VT220PC,    0 },
1640     { "vt320",     TT_VT320,      0 },
1641     { "vt320pc",   TT_VT320PC,    0 },
1642     { "vt52",      TT_VT52,       0 },
1643     { "vtnt",      TT_VTNT,       CM_INV },
1644     { "wp",        TT_KBM_WP,     0 },             /* Word Perfect mode */
1645     { "wy160",     TT_WY160,      0 },
1646     { "wy30",      TT_WY30,       0 },
1647     { "wy370",     TT_WY370,      0 },
1648     { "wy50",      TT_WY50,       0 },
1649     { "wy60",      TT_WY60,       0 },
1650     { "wyse30",    TT_WY30,       CM_INV },
1651     { "wyse370",   TT_WY370,      CM_INV },
1652     { "wyse50",    TT_WY50,       CM_INV },
1653     { "wyse60",    TT_WY60,       CM_INV }
1654 };
1655 int nttkey = (sizeof(ttkeytab) / sizeof(struct keytab));
1656
1657 #ifndef NOSETKEY
1658 struct keytab kbmodtab[] = {
1659     { "emacs",   KBM_EM, 0      },
1660     { "english", KBM_EN, CM_INV },
1661     { "hebrew",  KBM_HE, 0      },
1662     { "normal",  KBM_EN, 0      },
1663     { "none",    KBM_EN, CM_INV },
1664     { "russian", KBM_RU, 0      },
1665     { "wp",      KBM_WP, 0      }
1666 };
1667 int nkbmodtab = (sizeof(kbmodtab) / sizeof(struct keytab));
1668 #endif /* NOSETKEY */
1669 #endif /* NOLOCAL */
1670
1671 int tt_inpacing = 0;                    /* input-pacing (none) */
1672
1673 struct keytab prtytab[] = { /* OS/2 Priority Levels */
1674     { "foreground-server", XYP_SRV, 0       },
1675     { "idle",              XYP_IDLE, CM_INV },
1676     { "regular",           XYP_REG, 0       },
1677     { "time-critical",     XYP_RTP, 0       }
1678 };
1679 int nprty = (sizeof(prtytab) / sizeof(struct keytab));
1680 #endif /* OS2 */
1681
1682 #ifdef NT
1683 struct keytab win95tab[] = { /* Win95 work-arounds */
1684     { "8.3-filenames",         XYW8_3,    0 },
1685     { "alt-gr",                XYWAGR,    0 },
1686     { "horizontal-scan-line-substitutions", XYWHSL, 0 },
1687     { "keyboard-translation",  XYWKEY,    0 },
1688     { "lucida-substitutions",  XYWLUC,    0 },
1689     { "overlapped-io",         XYWOIO,    0 },
1690     { "popups",                XYWPOPUP,  0 },
1691     { "select-bug",            XYWSELECT, 0 }
1692 };
1693 int nwin95 = (sizeof(win95tab) / sizeof(struct keytab));
1694 #endif /* NT */
1695
1696 #ifdef OS2MOUSE
1697 extern int wideresult;
1698 int tt_mouse = 1;                       /* Terminal mouse on/off */
1699
1700 struct keytab mousetab[] = {            /* Mouse items */
1701     { "activate", XYM_ON,     0 },
1702     { "button",   XYM_BUTTON, 0 },
1703     { "clear",    XYM_CLEAR,  0 },
1704     { "debug",    XYM_DEBUG,  0 }
1705 };
1706 int nmtab = (sizeof(mousetab)/sizeof(struct keytab));
1707
1708 struct keytab mousebuttontab[] = {      /* event button */
1709     { "1",             XYM_B1, 0 },
1710     { "2",             XYM_B2, 0 },
1711     { "3",             XYM_B3, 0 },
1712     { "one",           XYM_B1, CM_INV },
1713     { "three",         XYM_B3, CM_INV },
1714     { "two",           XYM_B2, CM_INV }
1715 };
1716 int nmbtab = (sizeof(mousebuttontab) / sizeof(struct keytab));
1717
1718 struct keytab mousemodtab[] = {         /* event button key modifier */
1719     { "alt",              XYM_ALT,   0 },
1720     { "alt-shift",        XYM_SHIFT|XYM_ALT, 0 },
1721     { "ctrl",             XYM_CTRL,  0 },
1722     { "ctrl-alt",         XYM_CTRL|XYM_ALT, 0 },
1723     { "ctrl-alt-shift",   XYM_CTRL|XYM_SHIFT|XYM_ALT, 0 },
1724     { "ctrl-shift",       XYM_CTRL|XYM_SHIFT, 0 },
1725     { "none",             0, 0 },
1726     { "shift",            XYM_SHIFT, 0 }
1727 };
1728 int nmmtab = (sizeof(mousemodtab) / sizeof(struct keytab));
1729
1730 struct keytab mclicktab[] = {           /* event button click modifier */
1731     { "click",        XYM_C1,   0 },
1732     { "drag",         XYM_DRAG, 0 },
1733     { "double-click", XYM_C2,   0 }
1734 };
1735 int nmctab = (sizeof(mclicktab) / sizeof(struct keytab));
1736
1737 #ifndef NOKVERBS
1738 extern int nkverbs;
1739 extern struct keytab kverbs[];
1740 #endif /* NOKVERBS */
1741 #endif /* OS2MOUSE */
1742
1743 /* #ifdef VMS */
1744 struct keytab fbtab[] = {               /* Binary record types for VMS */
1745     { "fixed",     XYFT_B, 0 },         /* Fixed is normal for binary */
1746     { "undefined", XYFT_U, 0 }          /* Undefined if they ask for it */
1747 };
1748 int nfbtyp = (sizeof(fbtab) / sizeof(struct keytab));
1749 /* #endif */
1750
1751 #ifdef VMS
1752 struct keytab lbltab[] = {              /* Labeled File info */
1753     { "acl",         LBL_ACL, 0 },
1754     { "backup-date", LBL_BCK, 0 },
1755     { "name",        LBL_NAM, 0 },
1756     { "owner",       LBL_OWN, 0 },
1757     { "path",        LBL_PTH, 0 }
1758 };
1759 int nlblp = (sizeof(lbltab) / sizeof(struct keytab));
1760 #else
1761 #ifdef OS2
1762 struct keytab lbltab[] = {              /* Labeled File info */
1763     { "archive",   LBL_ARC, 0 },
1764     { "extended",  LBL_EXT, 0 },
1765     { "hidden",    LBL_HID, 0 },
1766     { "read-only", LBL_RO,  0 },
1767     { "system",    LBL_SYS, 0 }
1768 };
1769 int nlblp = (sizeof(lbltab) / sizeof(struct keytab));
1770 #endif /* OS2 */
1771 #endif /* VMS */
1772
1773 #ifdef CK_CURSES
1774 #ifdef CK_PCT_BAR
1775 static struct keytab fdftab[] = {       /* SET FILE DISPLAY FULL options */
1776     { "thermometer",    1, 0, },
1777     { "no-thermometer", 0, 0  }
1778 };
1779 extern int thermometer;
1780 #endif /* CK_PCT_BAR */
1781 #endif /* CK_CURSES */
1782
1783 static struct keytab fdtab[] = {        /* SET FILE DISPLAY options */
1784 #ifdef MAC                              /* Macintosh */
1785     { "fullscreen", XYFD_R,      0 },   /* Full-screen but not curses */
1786     { "none",       XYFD_N,      0 },
1787     { "off",        XYFD_N, CM_INV },
1788     { "on",         XYFD_R, CM_INV },
1789     { "quiet",      XYFD_N, CM_INV },
1790 #else                                   /* Not Mac */
1791     { "brief", XYFD_B, 0 },             /* Brief */
1792     { "crt", XYFD_S, 0 },               /* CRT display */
1793 #ifdef CK_CURSES
1794 #ifdef COMMENT
1795     { "curses",     XYFD_C,  CM_INV },  /* Full-screen, curses */
1796 #endif /* COMMENT */
1797     { "fullscreen", XYFD_C,  0 },       /* Full-screen, whatever the method */
1798 #endif /* CK_CURSES */
1799 #ifdef KUI
1800     { "gui",    XYFD_G, 0 },            /* GUI */
1801 #endif /* KUI */        
1802     { "none",   XYFD_N, 0      },       /* No display */
1803     { "off",    XYFD_N, CM_INV },       /* Ditto */
1804     { "on",     XYFD_R, CM_INV },       /* On = Serial */
1805     { "quiet",  XYFD_N, CM_INV },       /* No display */
1806     { "serial", XYFD_R, 0      },       /* Serial */
1807 #endif /* MAC */
1808     { "", 0, 0 }
1809 };
1810 int nfdtab = (sizeof(fdtab) / sizeof(struct keytab)) - 1;
1811
1812 struct keytab rsrtab[] = {              /* For REMOTE SET RECEIVE */
1813     { "packet-length", XYLEN,  0 },
1814     { "timeout",       XYTIMO, 0 }
1815 };
1816 int nrsrtab = (sizeof(rsrtab) / sizeof(struct keytab));
1817
1818 /* Send/Receive Parameters */
1819
1820 struct keytab srtab[] = {
1821     { "backup", XYBUP, 0 },
1822 #ifndef NOCSETS
1823     { "character-set-selection", XYCSET, 0 },
1824 #endif /* NOCSETS */
1825     { "control-prefix", XYQCTL, 0 },
1826 #ifdef CKXXCHAR
1827     { "double-character", XYDBL, 0 },
1828 #endif /* CKXXCHAR */
1829     { "end-of-packet", XYEOL, 0 },
1830 #ifdef PIPESEND
1831     { "filter", XYFLTR, 0 },
1832 #endif /* PIPESEND */
1833 #ifdef CKXXCHAR
1834     { "ignore-character", XYIGN, 0 },
1835 #endif /* CKXXCHAR */
1836     { "i-packets", 993, 0 },
1837     { "move-to", XYMOVE, 0 },
1838     { "negotiation-string-max-length", XYINIL, CM_INV },
1839     { "packet-length", XYLEN, 0 },
1840     { "pad-character", XYPADC, 0 },
1841     { "padding", XYNPAD, 0 },
1842     { "pathnames", XYFPATH, 0 },
1843     { "pause", XYPAUS, 0 },
1844 #ifdef CK_PERMS
1845     { "permissions", 994, 0},           /* 206 */
1846 #endif /* CK_PERMS */
1847     { "quote", XYQCTL, CM_INV },        /* = CONTROL-PREFIX */
1848     { "rename-to", XYRENAME, 0 },
1849     { "start-of-packet", XYMARK, 0 },
1850     { "timeout", XYTIMO, 0 },
1851 #ifdef VMS
1852     { "version-numbers", 887, 0 },      /* VMS version numbers */
1853 #endif /* VMS */
1854     { "", 0, 0 }
1855 };
1856 int nsrtab = (sizeof(srtab) / sizeof(struct keytab)) - 1;
1857
1858 #ifdef UNICODE
1859 #define UCS_BOM 1
1860 #define UCS_BYT 2
1861 static struct keytab ucstab[] = {
1862     { "bom",        UCS_BOM, 0 },
1863     { "byte-order", UCS_BYT, 0 },
1864     { "", 0, 0 }
1865 };
1866 int nucstab = (sizeof(ucstab) / sizeof(struct keytab)) - 1;
1867
1868 static struct keytab botab[] = {
1869     { "big-endian",    0, 0 },
1870     { "little-endian", 1, 0 }
1871 };
1872 static int nbotab = 2;
1873 #endif /* UNICODE */
1874
1875 /* REMOTE SET */
1876
1877 struct keytab rmstab[] = {
1878     { "attributes",  XYATTR, 0      },
1879     { "block-check", XYCHKT, 0      },
1880     { "file",        XYFILE, 0      },
1881     { "incomplete",  XYIFD,  CM_INV },  /* = REMOTE SET FILE INCOMPLETE */
1882     { "match",       XYMATCH,0      },
1883     { "receive",     XYRECV, 0      },
1884     { "retry",       XYRETR, 0      },
1885     { "server",      XYSERV, 0      },
1886     { "transfer",    XYXFER, 0      },
1887     { "window",      XYWIND, 0      },
1888     { "xfer",        XYXFER, CM_INV }
1889 };
1890 int nrms = (sizeof(rmstab) / sizeof(struct keytab));
1891
1892 struct keytab attrtab[] = {
1893 #ifdef STRATUS
1894     { "account",       AT_ACCT, 0 },
1895 #endif /* STRATUS */
1896     { "all",           AT_XALL, 0 },
1897 #ifdef COMMENT
1898     { "blocksize",     AT_BLKS, 0 },    /* (not used) */
1899 #endif /* COMMENT */
1900 #ifndef NOCSETS
1901     { "character-set", AT_ENCO, 0 },
1902 #endif /* NOCSETS */
1903 #ifdef STRATUS
1904     { "creator",       AT_CREA, 0 },
1905 #endif /* STRATUS */
1906     { "date",          AT_DATE, 0 },
1907     { "disposition",   AT_DISP, 0 },
1908     { "encoding",      AT_ENCO, CM_INV },
1909     { "format",        AT_RECF, CM_INV },
1910     { "length",        AT_LENK, 0 },
1911     { "off",           AT_ALLN, 0 },
1912     { "on",            AT_ALLY, 0 },
1913 #ifdef COMMENT
1914     { "os-specific",   AT_SYSP, 0 },    /* (not used by UNIX or VMS) */
1915 #endif /* COMMENT */
1916 #ifdef CK_PERMS
1917     { "protection",    AT_LPRO, 0 },
1918     { "permissions",   AT_LPRO, CM_INV },
1919 #endif /* CK_PERMS */
1920     { "record-format", AT_RECF, 0 },
1921     { "system-id",     AT_SYSI, 0 },
1922     { "type",          AT_FTYP, 0 }
1923 };
1924 int natr = (sizeof(attrtab) / sizeof(struct keytab)); /* how many attributes */
1925
1926 #ifdef CKTIDLE
1927 struct keytab idlacts[] = {
1928     { "exit",       IDLE_EXIT, 0 },
1929     { "hangup",     IDLE_HANG, 0 },
1930     { "output",     IDLE_OUT,  0 },
1931     { "return",     IDLE_RET,  0 },
1932 #ifdef TNCODE
1933     { "telnet-nop", IDLE_TNOP, 0 },
1934     { "telnet-ayt", IDLE_TAYT, 0 },
1935 #endif /* TNCODE */
1936     { "", 0, 0 }
1937 };
1938 int nidlacts = (sizeof(idlacts) / sizeof(struct keytab)) - 1;
1939 #endif /* CKTIDLE */
1940
1941 #ifndef NOSPL
1942 extern int indef, inecho, insilence, inbufsize, inautodl, inintr;
1943 #ifdef CKFLOAT
1944 extern CKFLOAT inscale;
1945 #endif  /* CKFLOAT */
1946 extern char * inpbuf, * inpbp;
1947 #ifdef OS2
1948 extern int interm;
1949 #endif /* OS2 */
1950 struct keytab inptab[] = {              /* SET INPUT parameters */
1951 #ifdef CK_AUTODL
1952     { "autodownload",    IN_ADL, 0 },
1953 #endif /* CK_AUTODL */
1954     { "buffer-length",   IN_BUF, 0 },
1955     { "cancellation",    IN_CAN, 0 },
1956     { "case",            IN_CAS, 0 },
1957     { "default-timeout", IN_DEF, CM_INV }, /* There is no default timeout */
1958     { "echo",            IN_ECH, 0 },
1959 #ifdef OS2
1960     { "pacing",          IN_PAC, CM_INV },
1961 #endif /* OS2 */
1962     { "scale-factor",    IN_SCA, 0 },
1963     { "silence",         IN_SIL, 0 },
1964 #ifdef OS2
1965     { "terminal",        IN_TRM, 0 },
1966 #endif /* OS2 */
1967     { "timeout-action",  IN_TIM, 0 }
1968 };
1969 int ninp = (sizeof(inptab) / sizeof(struct keytab));
1970
1971 struct keytab intimt[] = {              /* SET INPUT TIMEOUT parameters */
1972     { "proceed", 0, 0 },                /* 0 = proceed */
1973     { "quit",    1, 0 }                 /* 1 = quit */
1974 };
1975
1976 struct keytab incast[] = {              /* SET INPUT CASE parameters */
1977     { "ignore",  0, 0 },                /* 0 = ignore */
1978     { "observe", 1, 0 }                 /* 1 = observe */
1979 };
1980 #endif /* NOSPL */
1981
1982 struct keytab nabltab[] = {             /* For any command that needs */
1983     { "disabled", 0, 0 },
1984     { "enabled",  1, 0 },
1985     { "off",      0, CM_INV },          /* these keywords... */
1986     { "on",       1, CM_INV }
1987 };
1988 int nnabltab = sizeof(nabltab) / sizeof(struct keytab);
1989
1990 #ifdef OS2
1991 struct keytab tvctab[] = {              /* SET TERM VIDEO-CHANGE */
1992     { "disabled",     TVC_DIS, 0 },
1993     { "enabled",      TVC_ENA, 0 },
1994 #ifdef NT
1995     { "win95-safe",   TVC_W95, 0 },
1996 #endif /* NT */
1997     { "", 0, 0 }
1998 };
1999 int ntvctab = (sizeof(tvctab) / sizeof(struct keytab)) - 1;
2000
2001 struct keytab msktab[] = { /* SET MS-DOS KERMIT compatibilities */
2002 #ifdef COMMENT
2003     { "color",    MSK_COLOR,  0 },
2004 #endif /* COMMENT */
2005     { "keycodes", MSK_KEYS,   0 }
2006 };
2007 int nmsk = (sizeof(msktab) / sizeof(struct keytab));
2008
2009 struct keytab scrnupd[] = {             /* SET TERMINAL SCREEN-UPDATE */
2010     { "fast",   TTU_FAST,   0 },
2011     { "smooth", TTU_SMOOTH, 0 }
2012 };
2013 int nscrnupd = (sizeof(scrnupd) / sizeof(struct keytab));
2014
2015 #ifdef PCFONTS
2016 /* This definition of the term_font[] table is only for     */
2017 /* the OS/2 Full Screen Session and is not used on Windows */
2018 struct keytab term_font[] = {           /* SET TERMINAL FONT */
2019 #ifdef COMMENT
2020     { "cp111", TTF_111, 0 },
2021     { "cp112", TTF_112, 0 },
2022     { "cp113", TTF_113, 0 },
2023 #endif /* COMMENT */
2024     { "cp437", TTF_437, 0 },
2025     { "cp850", TTF_850, 0 },
2026 #ifdef COMMENT
2027     { "cp851", TTF_851, 0 },
2028 #endif /* COMMENT */
2029     { "cp852", TTF_852, 0 },
2030 #ifdef COMMENT
2031     { "cp853", TTF_853, 0 },
2032     { "cp860", TTF_860, 0 },
2033     { "cp861", TTF_861, 0 },
2034 #endif /* COMMENT */
2035     { "cp862", TTF_862, 0 },
2036 #ifdef COMMENT
2037     { "cp863", TTF_863, 0 },
2038     { "cp864", TTF_864, 0 },
2039     { "cp865", TTF_865, 0 },
2040 #endif /* COMMENT */
2041     { "cp866", TTF_866, 0 },
2042 #ifdef COMMENT
2043     { "cp880", TTF_880, 0 },
2044     { "cp881", TTF_881, 0 },
2045     { "cp882", TTF_882, 0 },
2046     { "cp883", TTF_883, 0 },
2047     { "cp884", TTF_884, 0 },
2048     { "cp885", TTF_885, 0 },
2049 #endif /* COMMENT */
2050     { "default",TTF_ROM,0 }
2051 };
2052 int ntermfont = (sizeof(term_font) / sizeof(struct keytab));
2053 int tt_font = TTF_ROM;                  /* Terminal screen font */
2054 #else /* PCFONTS */
2055 #ifdef NT
2056 #ifdef KUI
2057 struct keytab * term_font = NULL;
2058 struct keytab * _term_font = NULL;
2059 char * tt_facename = NULL;
2060 int ntermfont = 0;
2061 int tt_font = 0;
2062 int tt_font_size = 0;
2063 #endif /* KUI */
2064 #endif /* NT */
2065 #endif /* PCFONTS */
2066
2067 struct keytab anbktab[] = {             /* For any command that needs */
2068     { "message", 2, 0 },                /* these keywords... */
2069     { "off",     0, 0 },
2070     { "on",      1, 0 },
2071     { "unsafe-messag0", 99, CM_INV },
2072     { "unsafe-message", 3,  CM_INV }
2073 };
2074 int nansbk = (sizeof(anbktab) / sizeof(struct keytab));
2075
2076 int win95_popup = 1;
2077 #ifdef NT
2078 #ifdef KUI
2079 int win95lucida = 0;
2080 int win95hsl = 1;
2081 #else /* KUI */
2082 int win95lucida = 1;
2083 int win95hsl = 1;
2084 #endif /* KUI */
2085 #else /* NT */
2086 int win95lucida = 0;
2087 int win95hsl = 1;
2088 #endif /* NT */
2089 #ifdef NT
2090 int win95altgr  = 0;
2091 extern int win95selectbug;
2092 extern int win95_8_3;
2093
2094 #ifdef COMMENT
2095 extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR);
2096 extern struct keytab tcstab[];
2097 extern int ntcs;
2098 #endif /* COMMENT */
2099 extern int maxow, maxow_usr; owwait;    /* Overlapped I/O variables */
2100 #endif /* NT */
2101 #endif /* OS2 */
2102
2103
2104 /* The following routines broken out of doprm() to give compilers a break. */
2105
2106 /*  S E T O N  --  Parse on/off (default on), set parameter to result  */
2107
2108 int
2109 seton(prm) int *prm; {
2110     int x, y;
2111     if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
2112     if ((x = cmcfm()) < 0) return(x);
2113     *prm = y;
2114     return(1);
2115 }
2116
2117 /*  S E T O N A U T O --  Parse on/off/auto (default auto) & set result */
2118
2119 struct keytab onoffaut[] = {
2120     { "auto", SET_AUTO, 0 },            /* 2 */
2121     { "off",  SET_OFF,  0 },            /* 0 */
2122     { "on",   SET_ON,   0 }             /* 1 */
2123 };
2124
2125 int
2126 setonaut(prm) int *prm; {
2127     int x, y;
2128     if ((y = cmkey(onoffaut,3,"","auto",xxstring)) < 0) return(y);
2129     if ((x = cmcfm()) < 0) return(x);
2130     *prm = y;
2131     return(1);
2132 }
2133
2134 /*  S E T N U M  --  Set parameter to result of cmnum() parse.  */
2135 /*
2136  Call with pointer to integer variable to be set,
2137    x = number from cnum parse, y = return code from cmnum,
2138    max = maximum value to accept, -1 if no maximum.
2139  Returns -9 on failure, after printing a message, or 1 on success.
2140 */
2141 int
2142 setnum(prm,x,y,max) int x, y, *prm, max; {
2143     debug(F101,"setnum","",y);
2144     if (y == -3) {
2145         printf("\n?Value required\n");
2146         return(-9);
2147     }
2148     if (y == -2) {
2149         printf("%s?Not a number: %s\n",cmflgs == 1 ? "" : "\n", atxbuf);
2150         return(-9);
2151     }
2152     if (y < 0) return(y);
2153     if (max > -1 && x > max) {
2154         printf("?Sorry, %d is the maximum\n",max);
2155         return(-9);
2156     }
2157     if ((y = cmcfm()) < 0) return(y);
2158     *prm = x;
2159     return(1);
2160 }
2161
2162 /*  S E T C C  --  Set parameter var to an ASCII control character value.  */
2163 /*
2164   Parses a number, or a literal control character, or a caret (^) followed
2165   by an ASCII character whose value is 63-95 or 97-122, then gets confirmation,
2166   then sets the parameter to the code value of the character given.  If there
2167   are any parse errors, they are returned, otherwise on success 1 is returned.
2168 */
2169 int
2170 setcc(dflt,var) char *dflt; int *var; {
2171     int x, y;
2172     unsigned int c;
2173     char *hlpmsg = "Control character,\n\
2174  numeric ASCII value,\n\
2175  or in ^X notation,\n\
2176  or preceded by a backslash and entered literally";
2177
2178     /* This is a hack to turn off complaints from expression evaluator. */
2179     x_ifnum = 1;
2180     y = cmnum(hlpmsg, dflt, 10, &x, xxstring); /* Parse a number */
2181     x_ifnum = 0;                               /* Allow complaints again */
2182     if (y < 0) {                        /* Parse failed */
2183         if (y != -2)                    /* Reparse needed or somesuch */
2184           return(y);                    /* Pass failure back up the chain */
2185     }
2186     /* Real control character or literal 8-bit character... */
2187
2188     for (c = strlen(atmbuf) - 1; c > 0; c--) /* Trim */
2189       if (atmbuf[c] == SP) atmbuf[c] = NUL;
2190
2191     if (y < 0) {                        /* It was not a number */
2192         if (((c = atmbuf[0])) && !atmbuf[1]) { /* Literal character? */
2193             c &= 0xff;
2194             if (((c > 31) && (c < 127)) || (c > 255)) {
2195                 printf("\n?%d: Out of range - must be 0-31 or 127-255\n",c);
2196                 return(-9);
2197             } else {
2198                 if ((y = cmcfm()) < 0)  /* Confirm */
2199                   return(y);
2200                 *var = c;               /* Set the variable */
2201                 return(1);
2202             }
2203         } else if (atmbuf[0] == '^' && !atmbuf[2]) { /* Or ^X notation? */
2204             c = atmbuf[1];
2205             if (islower((char) c))      /* Uppercase lowercase letters */
2206               c = toupper(c);
2207             if (c > 62 && c < 96) {     /* Check range */
2208                 if ((y = cmcfm()) < 0)
2209                   return(y);
2210                 *var = ctl(c);          /* OK */
2211                 return(1);
2212             } else {
2213                 printf("?Not a control character - %s\n", atmbuf);
2214                 return(-9);
2215             }
2216         } else {                        /* Something illegal was typed */
2217             printf("?Invalid - %s\n", atmbuf);
2218             return(-9);
2219         }
2220     }
2221     if (((x > 31) && (x < 127)) || (x > 255)) { /* They typed a number */
2222         printf("\n?%d: Out of range - must be 0-31 or 127-255\n",x);
2223         return(-9);
2224     }
2225     if ((y = cmcfm()) < 0)              /* In range, confirm */
2226       return(y);
2227     *var = x;                           /* Set variable */
2228     return(1);
2229 }
2230
2231 #ifndef NOSPL                           /* The SORT command... */
2232
2233 static struct keytab srtswtab[] = {     /* SORT command switches */
2234     { "/case",    SRT_CAS, CM_ARG },
2235     { "/key",     SRT_KEY, CM_ARG },
2236     { "/numeric", SRT_NUM, 0 },
2237     { "/range",   SRT_RNG, CM_ARG },
2238     { "/reverse", SRT_REV, 0 }
2239 };
2240 static int nsrtswtab = sizeof(srtswtab)/sizeof(struct keytab);
2241
2242 extern char **a_ptr[];                  /* Array pointers */
2243 extern int a_dim[];                     /* Array dimensions */
2244
2245 int
2246 dosort() {                              /* Do the SORT command */
2247     char c, *p = NULL, ** ap, ** xp = NULL;
2248     struct FDB sw, fl, cm;
2249     int hi, lo;
2250     int xn = 0, xr = -1, xk = -1, xc = -1, xs = 0;
2251     int getval = 0, range[2], confirmed = 0;
2252
2253     cmfdbi(&sw,                         /* First FDB - command switches */
2254            _CMKEY,                      /* fcode */
2255            "Array name or switch",
2256            "",                          /* default */
2257            "",                          /* addtl string data */
2258            nsrtswtab,                   /* addtl numeric data 1: tbl size */
2259            4,                           /* addtl numeric data 2: 4 = cmswi */
2260            NULL,                        /* Processing function */
2261            srtswtab,                    /* Keyword table */
2262            &fl                          /* Pointer to next FDB */
2263            );
2264     cmfdbi(&fl,                         /* Anything that doesn't match */
2265            _CMFLD,                      /* fcode */
2266            "Array name",                /* hlpmsg */
2267            "",                          /* default */
2268            "",                          /* addtl string data */
2269            0,                           /* addtl numeric data 1 */
2270            0,                           /* addtl numeric data 2 */
2271            NULL,
2272            NULL,
2273            &cm
2274            );
2275     cmfdbi(&cm,                         /* Or premature confirmation */
2276            _CMCFM,                      /* fcode */
2277            "",                          /* hlpmsg */
2278            "",                          /* default */
2279            "",                          /* addtl string data */
2280            0,                           /* addtl numeric data 1 */
2281            0,                           /* addtl numeric data 2 */
2282            NULL,
2283            NULL,
2284            NULL
2285            );
2286
2287     range[0] = -1;
2288     range[1] = -1;
2289
2290     while (1) {                         /* Parse 0 or more switches */
2291         x = cmfdb(&sw);
2292         if (x < 0)
2293           return(x);
2294         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
2295           break;
2296         c = cmgbrk();
2297         getval = (c == ':' || c == '=');
2298         if (getval && !(cmresult.kflags & CM_ARG)) {
2299             printf("?This switch does not take arguments\n");
2300             return(-9);
2301         }
2302         switch (cmresult.nresult) {
2303           case SRT_REV:
2304             xr = 1;
2305             break;
2306           case SRT_KEY:
2307             if (getval) {
2308                 if ((y = cmnum("Column for comparison (1-based)",
2309                                "1",10,&x,xxstring)) < 0)
2310                   return(y);
2311                 xk = x - 1;
2312             } else
2313               xk = 0;
2314             break;
2315           case SRT_CAS:
2316             if (getval) {
2317                 if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
2318                   return(y);
2319                 xc = y;
2320             } else
2321               xc = 1;
2322             break;
2323           case SRT_RNG:                 /* /RANGE */
2324             if (getval) {
2325                 char buf[32];
2326                 char buf2[16];
2327                 int i;
2328                 char * p, * q;
2329                 if ((y = cmfld("low:high element","1",&s,NULL)) < 0)
2330                   return(y);
2331                 s = brstrip(s);
2332                 ckstrncpy(buf,s,32);
2333                 p = buf;
2334                 for (i = 0; *p && i < 2; i++) { /* Get low and high */
2335                     q = p;              /* Start of this piece */
2336                     while (*p) {        /* Find end of this piece */
2337                         if (*p == ':') {
2338                             *p = NUL;
2339                             p++;
2340                             break;
2341                         }
2342                         p++;
2343                     }
2344                     y = 15;             /* Evaluate this piece */
2345                     s = buf2;
2346                     zzstring(q,&s,&y);
2347                     s = evalx(buf2);
2348                     if (s) if (*s) ckstrncpy(buf2,s,16);
2349                     if (!rdigits(buf2)) {
2350                         printf("?Not numeric: %s\n",buf2);
2351                         return(-9);
2352                     }
2353                     range[i] = atoi(buf2);
2354                 }
2355             }
2356             break;
2357           case SRT_NUM:                 /* /NUMERIC */
2358             xn = 1;
2359             break;
2360           default:
2361             return(-2);
2362         }
2363     }
2364     switch (cmresult.fcode) {
2365       case _CMCFM:
2366         confirmed = 1;
2367         break;
2368       case _CMFLD:
2369         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Safe copy of name */
2370         s = line;
2371         break;
2372       default:
2373         printf("?Unexpected function code: %d\n",cmresult.fcode);
2374         return(-9);
2375     }
2376     if (confirmed) {
2377         printf("?Array name required\n");
2378         return(-9);
2379     }
2380     ckmakmsg(tmpbuf,TMPBUFSIZ,
2381              "Second array to sort according to ",s,NULL,NULL);
2382     if ((x = cmfld(tmpbuf,"",&p,NULL)) < 0)
2383       if (x != -3)
2384         return(x);
2385     tmpbuf[0] = NUL;
2386     ckstrncpy(tmpbuf,p,TMPBUFSIZ);
2387     p = tmpbuf;
2388     if ((x = cmcfm()) < 0)              /* Get confirmation */
2389       return(x);
2390
2391     x = arraybounds(s,&lo,&hi);         /* Get array index & bounds */
2392     if (x < 0) {                        /* Check */
2393         printf("?Bad array name: %s\n",s);
2394         return(-9);
2395     }
2396     if (lo > -1) range[0] = lo;         /* Set range */
2397     if (hi > -1) range[1] = hi;
2398     ap = a_ptr[x];                      /* Get pointer to array element list */
2399     if (!ap) {                          /* Check */
2400         printf("?Array not declared: %s\n", s);
2401         return(-9);
2402     }
2403     if (range[0] < 0)                   /* Starting element */
2404       range[0] = 1;
2405     if (range[1] < 0)                   /* Final element */
2406       range[1] = a_dim[x];
2407     if (range[1] > a_dim[x]) {
2408         printf("?range %d:%d exceeds array dimension %d\n",
2409                range[0],range[1],a_dim[x]
2410                );
2411         return(-9);
2412     }
2413     ap += range[0];
2414     xs = range[1] - range[0] + 1;       /* Number of elements to sort */
2415     if (xs < 1) {                       /* Check */
2416         printf("?Bad range: %d:%d\n",range[0],range[1]);
2417         return(-9);
2418     }
2419     if (xk < 0) xk = 0;                 /* Key position */
2420     if (xr < 0) xr = 0;                 /* Reverse flag */
2421     if (xn)                             /* Numeric flag */
2422       xc = 2;
2423     else if (xc < 0)                    /* Not numeric */
2424       xc = inpcas[cmdlvl];              /* so alpha case option */
2425
2426     if (*p) {                           /* Parallel array given? */
2427         y = xarray(p);                  /* Yes, get its index. */
2428         if (y < 0) {
2429             printf("?Bad array name: %s\n", p);
2430             return(-9);
2431         }
2432         if (y != x) {                   /* If the 2 arrays are different  */
2433             xp = a_ptr[y];              /* Pointer to 2nd array element list */
2434             if (!xp) {
2435                 printf("?Array not declared: %s\n", p);
2436                 return(-9);
2437             }
2438             if (a_dim[y] < range[1]) {
2439                 printf("?Array %s smaller than %s\n", p, s);
2440                 return(-9);
2441             }
2442             xp += range[0];             /* Set base to same as 1st array */
2443         }
2444     }
2445     sh_sort(ap,xp,xs,xk,xr,xc);         /* Sort the array(s) */
2446     return(success = 1);                /* Always succeeds */
2447 }
2448 #endif /* NOSPL */
2449
2450 static struct keytab purgtab[] = {      /* PURGE command switches */
2451     { "/after",        PU_AFT,  CM_ARG },
2452     { "/ask",          PU_ASK,  0 },
2453     { "/before",       PU_BEF,  CM_ARG },
2454     { "/delete",       PU_DELE, CM_INV },
2455 #ifdef UNIXOROSK
2456     { "/dotfiles",     PU_DOT,  0 },
2457 #endif /* UNIXOROSK */
2458     { "/except",       PU_EXC,  CM_ARG },
2459     { "/heading",      PU_HDG,  0 },
2460     { "/keep",         PU_KEEP, CM_ARG },
2461     { "/larger-than",  PU_LAR,  CM_ARG },
2462     { "/list",         PU_LIST, 0 },
2463     { "/log",          PU_LIST, CM_INV },
2464     { "/noask",        PU_NASK, 0 },
2465     { "/nodelete",     PU_NODE, CM_INV },
2466 #ifdef UNIXOROSK
2467     { "/nodotfiles",   PU_NODOT,0 },
2468 #endif /* UNIXOROSK */
2469     { "/noheading",    PU_NOH,  0 },
2470     { "/nol",          PU_NOLI, CM_INV|CM_ABR },
2471     { "/nolist",       PU_NOLI, 0 },
2472     { "/nolog",        PU_NOLI, CM_INV },
2473 #ifdef CK_TTGWSIZ
2474     { "/nopage",       PU_NOPA, 0 },
2475 #endif /* CK_TTGWSIZ */
2476     { "/not-after",    PU_NAF,  CM_ARG },
2477     { "/not-before",   PU_NBF,  CM_ARG },
2478     { "/not-since",    PU_NAF,  CM_INV|CM_ARG },
2479 #ifdef CK_TTGWSIZ
2480     { "/page",         PU_PAGE, 0 },
2481 #endif /* CK_TTGWSIZ */
2482     { "/quiet",        PU_QUIE, CM_INV },
2483 #ifdef RECURSIVE
2484     { "/recursive",    PU_RECU, 0 },
2485 #endif /* RECURSIVE */
2486     { "/since",        PU_AFT,  CM_ARG|CM_INV },
2487     { "/simulate",     PU_NODE, 0 },
2488     { "/smaller-than", PU_SMA,  CM_ARG },
2489     { "/verbose",      PU_VERB, CM_INV }
2490 };
2491 static int npurgtab = sizeof(purgtab)/sizeof(struct keytab);
2492
2493
2494
2495
2496
2497 int
2498 bkupnum(s,i) char * s; int *i; {
2499     int k = 0, pos = 0;
2500     char * p = NULL, *q;
2501     *i = pos;
2502     if (!s) s = "";
2503     if (!*s)
2504       return(-1);
2505     if ((k = strlen(s)) < 5)
2506       return(-1);
2507
2508     if (s[k-1] != '~')
2509       return(-1);
2510     pos = k - 2;
2511     q = s + pos;
2512     while (q >= s && isdigit(*q)) {
2513         p = q--;
2514         pos--;
2515     }
2516     if (!p)
2517       return(-1);
2518     if (q < s+2)
2519       return(-1);
2520     if (*q != '~' || *(q-1) != '.')
2521       return(-1);
2522     pos--;
2523     *i = pos;
2524     debug(F111,"bkupnum",s+pos,pos);
2525     return(atoi(p));
2526 }
2527
2528 #ifdef CKPURGE
2529 /* Presently only for UNIX because we need direct access to the file array. */
2530 /* Not needed for VMS anyway, because we don't make backup files there. */
2531
2532 #define MAXKEEP 32                      /* Biggest /KEEP: value */
2533
2534 static int
2535   pu_keep = 0, pu_list = 0, pu_dot = 0, pu_ask = 0, pu_hdg = 0;
2536
2537 #ifdef CK_TTGWSIZ
2538 static int pu_page = -1;
2539 #else
2540 static int pu_page = 0;
2541 #endif /* CK_TTGWSIZ */
2542
2543 #ifndef NOSHOW
2544 VOID
2545 showpurgopts() {                        /* SHOW PURGE command options */
2546     int x = 0;
2547     extern int optlines;
2548     prtopt(&optlines,"PURGE");
2549     if (pu_ask > -1) {
2550         x++;
2551         prtopt(&optlines, pu_ask ? "/ASK" : "/NOASK");
2552     }
2553 #ifdef UNIXOROSK
2554     if (pu_dot > -1) {
2555         x++;
2556         prtopt(&optlines, pu_dot ? "/DOTFILES" : "/NODOTFILES");
2557     }
2558 #endif /* UNIXOROSK */
2559     if (pu_keep > -1) {
2560         x++;
2561         ckmakmsg(tmpbuf,TMPBUFSIZ,"/KEEP:",ckitoa(pu_keep),NULL,NULL);
2562         prtopt(&optlines,tmpbuf);
2563     }
2564     if (pu_list > -1) {
2565         x++;
2566         prtopt(&optlines, pu_list ? "/LIST" : "/NOLIST");
2567     }
2568     if (pu_hdg > -1) {
2569         x++;
2570         prtopt(&optlines, pu_hdg ? "/HEADING" : "/NOHEADING");
2571     }
2572 #ifdef CK_TTGWSIZ
2573     if (pu_page > -1) {
2574         x++;
2575         prtopt(&optlines, pu_page ? "/PAGE" : "/NOPAGE");
2576     }
2577 #endif /* CK_TTGWSIZ */
2578     if (!x) prtopt(&optlines,"(no options set)");
2579     prtopt(&optlines,"");
2580 }
2581 #endif /* NOSHOW */
2582
2583 int
2584 setpurgopts() {                         /* Set PURGE command options */
2585     int c, z, getval = 0;
2586     int
2587       x_keep  = -1, x_list = -1, x_page = -1,
2588       x_hdg   = -1, x_ask  = -1, x_dot  = -1;
2589
2590     while (1) {
2591         if ((y = cmswi(purgtab,npurgtab,"Switch","",xxstring)) < 0) {
2592             if (y == -3)
2593               break;
2594             else
2595               return(y);
2596         }
2597         c = cmgbrk();
2598         if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
2599             printf("?This switch does not take an argument\n");
2600             return(-9);
2601         }
2602         if (!getval && (cmgkwflgs() & CM_ARG)) {
2603             printf("?This switch requires an argument\n");
2604             return(-9);
2605         }
2606         switch (y) {
2607           case PU_KEEP:
2608             z = 1;
2609             if (c == ':' || c == '=')
2610               if ((y = cmnum("How many backup files to keep",
2611                              "1",10,&z,xxstring)) < 0)
2612                 return(y);
2613             if (z < 0 || z > MAXKEEP) {
2614                 printf("?Please specify a number between 0 and %d\n",
2615                        MAXKEEP
2616                        );
2617                 return(-9);
2618             }
2619             x_keep = z;
2620             break;
2621           case PU_LIST:
2622           case PU_VERB:
2623             x_list = 1;
2624             break;
2625           case PU_QUIE:
2626           case PU_NOLI:
2627             x_list = 0;
2628             break;
2629 #ifdef CK_TTGWSIZ
2630           case PU_PAGE:
2631             x_page = 1;
2632             break;
2633           case PU_NOPA:
2634             x_page = 0;
2635             break;
2636 #endif /* CK_TTGWSIZ */
2637           case PU_HDG:
2638             x_hdg = 1;
2639             break;
2640           case PU_NOH:
2641             x_hdg = 0;
2642             break;
2643           case PU_ASK:
2644             x_ask = 1;
2645             break;
2646           case PU_NASK:
2647             x_ask = 0;
2648             break;
2649 #ifdef UNIXOROSK
2650           case PU_DOT:
2651             x_dot = 1;
2652             break;
2653           case PU_NODOT:
2654             x_dot = 0;
2655             break;
2656 #endif /* UNIXOROSK */
2657           default:
2658             printf("?This option can not be set\n");
2659             return(-9);
2660         }
2661     }
2662     if ((x = cmcfm()) < 0)              /* Get confirmation */
2663       return(x);
2664     if (x_keep > -1)                    /* Set PURGE defaults. */
2665       pu_keep = x_keep;
2666     if (x_list > -1)
2667       pu_list = x_list;
2668 #ifdef CK_TTGWSIZ
2669     if (x_page > -1)
2670       pu_page = x_page;
2671 #endif /* CK_TTGWSIZ */
2672     if (x_hdg > -1)
2673       pu_hdg = x_hdg;
2674     if (x_ask > -1)
2675       pu_ask = x_ask;
2676     if (x_dot > -1)
2677       pu_dot = x_dot;
2678     return(success = 1);
2679 }
2680
2681 int
2682 dopurge() {                             /* Do the PURGE command */
2683     extern char ** mtchs;
2684     extern int xaskmore, cmd_rows, recursive;
2685     int simulate = 0, asking = 0;
2686     int listing = 0, paging = -1, lines = 0, deleting = 1, errors = 0;
2687     struct FDB sw, sf, cm;
2688     int g, i, j, k, m = 0, n, x, y, z, done = 0, count = 0, flags = 0;
2689     int tokeep = 0, getval = 0, havename = 0, confirmed = 0;
2690     int xx[MAXKEEP+1];                  /* Array of numbers to keep */
2691     int min = -1;
2692     int x_hdg = 0, fs = 0, rc = 0;
2693     long minsize = -1L, maxsize = -1L;
2694     char namebuf[CKMAXPATH+4];
2695     char basebuf[CKMAXPATH+4];
2696     char
2697       * pu_aft = NULL,
2698       * pu_bef = NULL,
2699       * pu_naf = NULL,
2700       * pu_nbf = NULL,
2701       * pu_exc = NULL;
2702     char * pxlist[8];                   /* Exception list */
2703
2704     if (pu_keep > -1)                   /* Set PURGE defaults. */
2705       tokeep = pu_keep;
2706     if (pu_list > -1)
2707       listing = pu_list;
2708 #ifdef CK_TTGWSIZ
2709     if (pu_page > -1)
2710       paging = pu_page;
2711 #endif /* CK_TTGWSIZ */
2712
2713     for (i = 0; i <= MAXKEEP; i++)      /* Clear this number buffer */
2714       xx[i] = 0;
2715     for (i = 0; i < 8; i++)             /* Initialize these... */
2716       pxlist[i] = NULL;
2717
2718     g_matchdot = matchdot;              /* Save these... */
2719
2720     cmfdbi(&sw,                         /* 1st FDB - PURGE switches */
2721            _CMKEY,                      /* fcode */
2722            "Filename or switch",        /* hlpmsg */
2723            "",                          /* default */
2724            "",                          /* addtl string data */
2725            npurgtab,                    /* addtl numeric data 1: tbl size */
2726            4,                           /* addtl numeric data 2: 4 = cmswi */
2727            xxstring,                    /* Processing function */
2728            purgtab,                     /* Keyword table */
2729            &sf                          /* Pointer to next FDB */
2730            );
2731     cmfdbi(&sf,                         /* 2nd FDB - filespec to purge */
2732            _CMIFI,                      /* fcode */
2733            "",
2734            "",                          /* default */
2735            "",                          /* addtl string data */
2736            0,                           /* addtl numeric data 1 */
2737            0,                           /* addtl numeric data 2 */
2738            xxstring,
2739            NULL,
2740            &cm
2741            );
2742     cmfdbi(&cm,                         /* Or premature confirmation */
2743            _CMCFM,                      /* fcode */
2744            "",                          /* hlpmsg */
2745            "",                          /* default */
2746            "",                          /* addtl string data */
2747            0,                           /* addtl numeric data 1 */
2748            0,                           /* addtl numeric data 2 */
2749            NULL,
2750            NULL,
2751            NULL
2752            );
2753
2754     while (!havename && !confirmed) {
2755         x = cmfdb(&sw);                 /* Parse something */
2756         if (x < 0) {                    /* Error */
2757             rc = x;
2758             goto xpurge;
2759         } else if (cmresult.fcode == _CMKEY) {
2760             char c;
2761             c = cmgbrk();
2762             if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
2763                 printf("?This switch does not take an argument\n");
2764                 rc = -9;
2765                 goto xpurge;
2766             }
2767             if (!getval && (cmgkwflgs() & CM_ARG)) {
2768                 printf("?This switch requires an argument\n");
2769                 rc = -9;
2770                 goto xpurge;
2771             }
2772             switch (k = cmresult.nresult) {
2773               case PU_KEEP:
2774                 z = 1;
2775                 if (c == ':' || c == '=') {
2776                     if ((y = cmnum("How many backup files to keep",
2777                                    "1",10,&z,xxstring)) < 0) {
2778                         rc = y;
2779                         goto xpurge;
2780                     }
2781                 }
2782                 if (z < 0 || z > MAXKEEP) {
2783                     printf("?Please specify a number between 0 and %d\n",
2784                            MAXKEEP
2785                            );
2786                     rc = -9;
2787                     goto xpurge;
2788                 }
2789                 tokeep = z;
2790                 break;
2791               case PU_LIST:
2792                 listing = 1;
2793                 break;
2794               case PU_NOLI:
2795                 listing = 0;
2796                 break;
2797 #ifdef CK_TTGWSIZ
2798               case PU_PAGE:
2799                 paging = 1;
2800                 break;
2801               case PU_NOPA:
2802                 paging = 0;
2803                 break;
2804 #endif /* CK_TTGWSIZ */
2805               case PU_DELE:
2806                 deleting = 1;
2807                 break;
2808               case PU_NODE:
2809                 deleting = 0;
2810                 simulate = 1;
2811                 listing = 1;
2812                 break;
2813               case PU_ASK:
2814                 asking = 1;
2815                 break;
2816               case PU_NASK:
2817                 asking = 0;
2818                 break;
2819               case PU_AFT:
2820               case PU_BEF:
2821               case PU_NAF:
2822               case PU_NBF:
2823                 if ((x = cmdate("File-time","",&s,0,xxstring)) < 0) {
2824                     if (x == -3) {
2825                         printf("?Date-time required\n");
2826                         rc = -9;
2827                     } else
2828                       rc = x;
2829                     goto xpurge;
2830                 }
2831                 fs++;
2832                 switch (k) {
2833                   case PU_AFT: makestr(&pu_aft,s); break;
2834                   case PU_BEF: makestr(&pu_bef,s); break;
2835                   case PU_NAF: makestr(&pu_naf,s); break;
2836                   case PU_NBF: makestr(&pu_nbf,s); break;
2837                 }
2838                 break;
2839               case PU_SMA:
2840               case PU_LAR:
2841                 if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0) {
2842                     rc = x;
2843                     goto xpurge;
2844                 }
2845                 fs++;
2846                 switch (cmresult.nresult) {
2847                   case PU_SMA: minsize = y; break;
2848                   case PU_LAR: maxsize = y; break;
2849                 }
2850                 break;
2851               case PU_DOT:
2852                 matchdot = 1;
2853                 break;
2854               case PU_NODOT:
2855                 matchdot = 0;
2856                 break;
2857               case PU_EXC:
2858                 if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
2859                     if (x == -3) {
2860                         printf("?Pattern required\n");
2861                         rc = -9;
2862                     } else
2863                       rc = x;
2864                     goto xpurge;
2865                 }
2866                 fs++;
2867                 makestr(&pu_exc,s);
2868                 break;
2869               case PU_HDG:
2870                 x_hdg = 1;
2871                 break;
2872 #ifdef RECURSIVE
2873               case PU_RECU:             /* /RECURSIVE */
2874                 recursive = 2;
2875                 break;
2876 #endif /* RECURSIVE */
2877               default:
2878                 printf("?Not implemented yet - \"%s\"\n",atmbuf);
2879                 rc = -9;
2880                 goto xpurge;
2881             }
2882         } else if (cmresult.fcode == _CMIFI) {
2883             havename = 1;
2884         } else if (cmresult.fcode == _CMCFM) {
2885             confirmed = 1;
2886         } else {
2887             rc = -2;
2888             goto xpurge;
2889         }
2890     }
2891     if (havename) {
2892 #ifdef CKREGEX
2893         ckmakmsg(line,LINBUFSIZ,cmresult.sresult,".~[1-9]*~",NULL,NULL);
2894 #else
2895         ckmakmsg(line,LINBUFSIZ,cmresult.sresult,".~*~",NULL,NULL);
2896 #endif /* CKREGEX */
2897     } else {
2898 #ifdef CKREGEX
2899         ckstrncpy(line,"*.~[1-9]*~",LINBUFSIZ);
2900 #else
2901         ckstrncpy(line,"*.~*~",LINBUFSIZ);
2902 #endif /* CKREGEX */
2903     }
2904     if (!confirmed) {
2905         if ((x = cmcfm()) < 0) {
2906             rc = x;
2907             goto xpurge;
2908         }
2909     }
2910     /* Parse finished - now action */
2911
2912 #ifdef CK_LOGIN
2913     if (isguest) {
2914         printf("?File deletion by guests not permitted.\n");
2915         rc = -9;
2916         goto xpurge;
2917     }
2918 #endif /* CK_LOGIN */
2919
2920 #ifdef CK_TTGWSIZ
2921     if (paging < 0)                     /* /[NO]PAGE not given */
2922       paging = xaskmore;                /* so use prevailing */
2923 #endif /* CK_TTGWSIZ */
2924
2925     lines = 0;
2926     if (x_hdg > 0) {
2927         printf("Purging %s, keeping %d...%s\n",
2928                s,
2929                tokeep,
2930                simulate ? " (SIMULATION)" : "");
2931         lines += 2;
2932     }
2933     flags = ZX_FILONLY;
2934     if (recursive) flags |= ZX_RECURSE;
2935     n = nzxpand(line,flags);            /* Get list of backup files */
2936     if (tokeep < 1) {                   /* Deleting all of them... */
2937         for (i = 0; i < n; i++) {
2938             if (fs) if (fileselect(mtchs[i],
2939                                    pu_aft,pu_bef,pu_naf,pu_nbf,
2940                                    minsize,maxsize,0,8,pxlist) < 1) {
2941                 if (listing > 0) {
2942                     printf(" %s (SKIPPED)\n",mtchs[i]);
2943 #ifdef CK_TTGWSIZ
2944                     if (paging)
2945                       if (++lines > cmd_rows - 3) {
2946                           if (!askmore()) goto xpurge; else lines = 0;
2947                       }
2948 #endif /* CK_TTGWSIZ */
2949                 }
2950                 continue;
2951             }
2952             if (asking) {
2953                 int x;
2954                 ckmakmsg(tmpbuf,TMPBUFSIZ," Delete ",mtchs[i],"?",NULL);
2955                 x = getyesno(tmpbuf,1);
2956                 switch (x) {
2957                   case 0: continue;
2958                   case 1: break;
2959                   case 2: goto xpurge;
2960                 }
2961             }
2962             x = deleting ? zdelet(mtchs[i]) : 0;
2963             if (x > -1) {
2964                 if (listing)
2965                   printf(" %s (%s)\n", mtchs[i],deleting ? "OK" : "SELECTED");
2966                 count++;
2967             } else {
2968                 errors++;
2969                 if (listing)
2970                   printf(" %s (FAILED)\n", mtchs[i]);
2971             }
2972 #ifdef CK_TTGWSIZ
2973             if (listing && paging)
2974               if (++lines > cmd_rows - 3) {
2975                   if (!askmore()) goto xpurge; else lines = 0;
2976               }
2977 #endif /* CK_TTGWSIZ */
2978         }
2979         goto xpurge;
2980     }
2981     if (n < tokeep) {                   /* Not deleting any */
2982         count = 0;
2983         if (listing)
2984           printf(" Matches = %d: Not enough to purge.\n");
2985         goto xpurge;
2986     }
2987
2988     /* General case - delete some but not others */
2989
2990     sh_sort(mtchs,NULL,n,0,0,filecase); /* Alphabetize the list (ESSENTIAL) */
2991
2992     g = 0;                              /* Start of current group */
2993     for (i = 0; i < n; i++) {           /* Go thru sorted file list */
2994         x = znext(namebuf);             /* Get next file */
2995         if (x < 1 || !namebuf[0] || i == n - 1) /* No more? */
2996           done = 1;                     /* NOTE: 'done' must be 0 or 1 only */
2997         if (fs) if (fileselect(namebuf,
2998                                pu_aft,pu_bef,pu_naf,pu_nbf,
2999                                minsize,maxsize,0,8,pxlist) < 1) {
3000             if (listing > 0) {
3001                 printf(" %s (SKIPPED)\n",namebuf);
3002                 if (++lines > cmd_rows - 3)
3003                   if (!askmore()) goto xpurge; else lines = 0;
3004             }
3005             continue;
3006         }
3007         if (x > 0)
3008           if ((m = bkupnum(namebuf,&z)) < 0) /* This file's backup number. */
3009             continue;
3010         for (j = 0; j < tokeep; j++) {  /* Insert in list. */
3011             if (m > xx[j]) {
3012                 for (k = tokeep - 1; k > j; k--)
3013                   xx[k] = xx[k-1];
3014                 xx[j] = m;
3015                 break;
3016             }
3017         }
3018         /* New group? */
3019         if (done || (i > 0 && ckstrcmp(namebuf,basebuf,z,1))) {
3020             if (i + done - g > tokeep) { /* Do we have enough to purge? */
3021                 min = xx[tokeep-1];     /* Yes, lowest backup number to keep */
3022                 debug(F111,"dopurge group",basebuf,min);
3023                 for (j = g; j < i + done; j++) { /* Go through this group */
3024                     x = bkupnum(mtchs[j],&z);    /* Get file backup number */
3025                     if (x > 0 && x < min) {      /* Below minimum? */
3026                         x = deleting ? zdelet(mtchs[j]) : 0;
3027                         if (x < 0) errors++;
3028                         if (listing)
3029                           printf(" %s (%s)\n",
3030                                  mtchs[j],
3031                                  ((x < 0) ? "ERROR" :
3032                                   (deleting ? "DELETED" : "SELECTED"))
3033                                  );
3034                         count++;
3035                     } else if (listing) /* Not below minimum - keep this one */
3036                       printf(" %s (KEPT)\n",mtchs[j]);
3037 #ifdef CK_TTGWSIZ
3038                     if (listing && paging)
3039                       if (++lines > cmd_rows - 3) {
3040                           if (!askmore()) goto xpurge; else lines = 0;
3041                       }
3042 #endif /* CK_TTGWSIZ */
3043                 }
3044             } else if (listing && paging) { /* Not enough to purge */
3045                 printf(" %s.~*~ (KEPT)\n",basebuf);
3046 #ifdef CK_TTGWSIZ
3047                 if (++lines > cmd_rows - 3) {
3048                     if (!askmore()) goto xpurge; else lines = 0;
3049                 }
3050 #endif /* CK_TTGWSIZ */
3051             }
3052             for (j = 0; j < tokeep; j++) /* Clear the backup number list */
3053               xx[j] = 0;
3054             g = i;                      /* Reset the group pointer */
3055         }
3056         if (done)                       /* No more files, done. */
3057           break;
3058         strncpy(basebuf,namebuf,z);     /* Set basename of this file */
3059         basebuf[z] = NUL;
3060     }
3061   xpurge:                               /* Common exit point */
3062     if (g_matchdot > -1) {
3063         matchdot = g_matchdot;          /* Restore these... */
3064         g_matchdot = -1;
3065     }
3066     if (rc < 0) return(rc);             /* Parse error */
3067     if (x_hdg)
3068       printf("Files purged: %d%s\n",
3069              count,
3070              deleting ? "" : " (not really)"
3071              );
3072     return(success = count > 0 ? 1 : (errors > 0) ? 0 : 1);
3073 }
3074 #endif /* CKPURGE */
3075
3076 #ifndef NOXFER
3077 #ifndef NOLOCAL
3078 int
3079 doxdis(which) int which; {              /* 1 = Kermit, 2 = FTP */
3080     extern int nolocal;
3081     int x, y = 0, z;
3082 #ifdef NEWFTP
3083     extern int ftp_dis;
3084 #endif /* NEWFTP */
3085
3086 #ifdef COMMENT
3087     char *s;
3088 #endif /* COMMENT */
3089
3090     if ((x = cmkey(fdtab,nfdtab,"file transfer display style","",
3091                    xxstring)) < 0)
3092       return(x);
3093 #ifdef CK_PCT_BAR
3094     if ((y = cmkey(fdftab,2,"","thermometer",xxstring)) < 0)
3095       return(y);
3096 #endif /* CK_PCT_BAR */
3097     if ((z = cmcfm()) < 0) return(z);
3098 #ifdef CK_CURSES
3099     if (x == XYFD_C) {                  /* FULLSCREEN */
3100 #ifdef COMMENT
3101 #ifndef MYCURSES
3102         extern char * trmbuf;           /* Real curses */
3103         int z;
3104 #endif /* MYCURSES */
3105 #endif /* COMMENT */
3106
3107         if (nolocal)                    /* Nothing to do in this case */
3108           return(success = 1);
3109
3110 #ifdef COMMENT
3111 #ifndef MYCURSES
3112 #ifndef VMS
3113         s = getenv("TERM");
3114         debug(F110,"doxdis TERM",s,0);
3115         if (!s) s = "";
3116         fxdinit(x);
3117         if (*s && trmbuf) {             /* Don't call tgetent */
3118             z = tgetent(trmbuf,s);      /* if trmbuf not allocated */
3119             debug(F111,"doxdis tgetent",s,z);
3120         } else {
3121             z = 0;
3122             debug(F110,"doxdis tgetent skipped",s,0);
3123         }
3124         if (z < 1) {
3125             printf("Sorry, terminal type unknown: \"%s\"\n",s);
3126             return(success = 0);
3127         }
3128 #endif /* VMS */
3129 #endif /* MYCURSES */
3130 #else
3131         fxdinit(x);
3132 #endif /* COMMENT */
3133
3134 #ifdef CK_PCT_BAR
3135         thermometer = y;
3136 #endif /* CK_PCT_BAR */
3137
3138         line[0] = '\0';                 /* (What's this for?) */
3139     }
3140 #endif /* CK_CURSES */
3141     if (which == 1)                     /* It's OK. */
3142       fdispla = x;
3143 #ifdef NEWFTP
3144     else
3145       ftp_dis = x;
3146 #endif /* NEWFTP */
3147     return(success = 1);
3148 }
3149 #endif /* NOLOCAL */
3150 #endif /* NOXFER */
3151
3152 int
3153 setfil(rmsflg) int rmsflg; {
3154 #ifdef COMMENT
3155     extern int en_del;
3156 #endif /* COMMENT */
3157 #ifndef NOXFER
3158     if (rmsflg) {
3159         if ((y = cmkey(rfiltab,nrfilp,"Remote file parameter","",
3160                        xxstring)) < 0) {
3161             if (y == -3) {
3162                 printf("?Remote file parameter required\n");
3163                 return(-9);
3164             } else return(y);
3165         }
3166     } else {
3167 #endif /* NOXFER */
3168         if ((y = cmkey(filtab,nfilp,"File parameter","",xxstring)) < 0)
3169           return(y);
3170 #ifndef NOXFER
3171     }
3172 #endif /* NOXFER */
3173     switch (y) {
3174 #ifdef COMMENT                          /* Not needed */
3175       case XYFILB:                      /* Blocksize */
3176         if ((y = cmnum("file block size",ckitoa(DBLKSIZ),10,&z,xxstring)) < 0)
3177           return(y);
3178         if ((x = cmcfm()) < 0) return(x);
3179         if (rmsflg) {
3180             sstate = setgen('S', "311", ckitoa(z), "");
3181             return((int) sstate);
3182         } else {
3183             fblksiz = z;
3184             return(success = 1);
3185         }
3186 #endif /* COMMENT */
3187
3188 #ifndef NOXFER
3189       case XYFILS:                      /* Byte size */
3190         if ((y = cmnum("file byte size (7 or 8)","8",10,&z,xxstring)) < 0)
3191           return(y);
3192         if (z != 7 && z != 8) {
3193             printf("\n?The choices are 7 and 8\n");
3194             return(0);
3195         }
3196         if ((y = cmcfm()) < 0) return(y);
3197         if (z == 7) fmask = 0177;
3198         else if (z == 8) fmask = 0377;
3199         return(success = 1);
3200
3201 #ifndef NOCSETS
3202       case XYFILC: {                    /* Character set */
3203           char * csetname = NULL;
3204           extern int
3205             r_cset, s_cset, afcset[];   /* SEND CHARACTER-SET AUTO or MANUAL */
3206
3207           struct FDB kw, fl;
3208           cmfdbi(&kw,                   /* First FDB - command switches */
3209                  _CMKEY,                /* fcode */
3210                  rmsflg ? "server character-set name" : "",  /* help */
3211                  "",                    /* default */
3212                  "",                    /* addtl string data */
3213                  nfilc,                 /* addtl numeric data 1: tbl size */
3214                  0,                     /* addtl numeric data 2: 0 = keyword */
3215                  xxstring,              /* Processing function */
3216                  fcstab,                /* Keyword table */
3217                  rmsflg ? &fl : NULL    /* Pointer to next FDB */
3218            );
3219           cmfdbi(&fl,                   /* Anything that doesn't match */
3220                  _CMFLD,                /* fcode */
3221                  "",                    /* hlpmsg */
3222                  "",                    /* default */
3223                  "",                    /* addtl string data */
3224                  0,                     /* addtl numeric data 1 */
3225                  0,                     /* addtl numeric data 2 */
3226                  xxstring,
3227                  NULL,
3228                  NULL
3229                  );
3230           if ((x = cmfdb(&kw)) < 0)
3231             return(x);
3232           if (cmresult.fcode == _CMKEY) {
3233               x = cmresult.nresult;
3234               csetname = fcsinfo[x].keyword;
3235           } else {
3236               ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
3237               csetname = line;
3238           }
3239           if ((z = cmcfm()) < 0) return(z);
3240           if (rmsflg) {
3241               sstate = setgen('S', "320", csetname, "");
3242               return((int) sstate);
3243           }
3244           fcharset = x;
3245           if (s_cset == XMODE_A)        /* If SEND CHARACTER-SET is AUTO */
3246             if (x > -1 && x <= MAXFCSETS)
3247               if (afcset[x] > -1 && afcset[x] <= MAXTCSETS)
3248                 tcharset = afcset[x]; /* Pick corresponding xfer charset */
3249           setxlatype(tcharset,fcharset); /* Translation type */
3250           /* If I say SET FILE CHARACTER-SET blah, I want to be blah! */
3251           r_cset = XMODE_M;             /* Don't switch incoming set! */
3252           x = fcsinfo[fcharset].size;   /* Also set default x-bit charset */
3253           if (x == 128)                 /* 7-bit... */
3254             dcset7 = fcharset;
3255           else if (x == 256)            /* 8-bit... */
3256             dcset8 = fcharset;
3257           return(success = 1);
3258       }
3259 #endif /* NOCSETS */
3260
3261 #ifndef NOLOCAL
3262       case XYFILD:                      /* Display */
3263         return(doxdis(1));              /* 1 == kermit */
3264 #endif /* NOLOCAL */
3265 #endif /* NOXFER */
3266
3267       case XYFILA:                      /* End-of-line */
3268 #ifdef NLCHAR
3269         s = "";
3270         if (NLCHAR == 015)
3271           s = "cr";
3272         else if (NLCHAR == 012)
3273           s = "lf";
3274         if ((x = cmkey(eoltab, neoltab,
3275                        "local text-file line terminator",s,xxstring)) < 0)
3276           return(x);
3277 #else
3278         if ((x = cmkey(eoltab, neoltab,
3279                        "local text-file line terminator","crlf",xxstring)) < 0)
3280           return(x);
3281 #endif /* NLCHAR */
3282         if ((z = cmcfm()) < 0) return(z);
3283         feol = (CHAR) x;
3284         return(success = 1);
3285
3286 #ifndef NOXFER
3287       case XYFILN:                      /* Names */
3288         if ((x = cmkey(fntab,nfntab,"how to handle filenames","converted",
3289                        xxstring)) < 0)
3290           return(x);
3291         if ((z = cmcfm()) < 0) return(z);
3292         if (rmsflg) {
3293             sstate = setgen('S', "301", ckitoa(1 - x), "");
3294             return((int) sstate);
3295         } else {
3296             ptab[protocol].fncn = x;    /* Set structure */
3297             fncnv = x;                  /* Set variable */
3298             f_save = x;                 /* And set "permanent" variable */
3299             return(success = 1);
3300         }
3301
3302       case XYFILR:                      /* Record length */
3303         if ((y = cmnum("file record length",
3304                        ckitoa(DLRECL),10,&z,xxstring)) < 0)
3305           return(y);
3306         if ((x = cmcfm()) < 0) return(x);
3307         if (rmsflg) {
3308             sstate = setgen('S', "312", ckitoa(z), "");
3309             return((int) sstate);
3310         } else {
3311             frecl = z;
3312             return(success = 1);
3313         }
3314
3315 #ifdef COMMENT
3316       case XYFILO:                      /* Organization */
3317         if ((x = cmkey(forgtab,nforg,"file organization","sequential",
3318                        xxstring)) < 0)
3319           return(x);
3320         if ((y = cmcfm()) < 0) return(y);
3321         if (rmsflg) {
3322             sstate = setgen('S', "314", ckitoa(x), "");
3323             return((int) sstate);
3324         } else {
3325             forg = x;
3326             return(success = 1);
3327         }
3328 #endif /* COMMENT */
3329
3330 #ifdef COMMENT                          /* Not needed */
3331       case XYFILF:                      /* Format */
3332         if ((x = cmkey(frectab,nfrec,"file record format","stream",
3333                        xxstring)) < 0)
3334           return(x);
3335         if ((y = cmcfm()) < 0) return(y);
3336         if (rmsflg) {
3337             sstate = setgen('S', "313", ckitoa(x), "");
3338             return((int) sstate);
3339         } else {
3340             frecfm = x;
3341             return(success = 1);
3342         }
3343 #endif /* COMMENT */
3344
3345 #ifdef COMMENT
3346       case XYFILP:                      /* Printer carriage control */
3347         if ((x = cmkey(fcctab,nfcc,"file carriage control","newline",
3348                        xxstring)) < 0)
3349           return(x);
3350         if ((y = cmcfm()) < 0) return(y);
3351         if (rmsflg) {
3352             sstate = setgen('S', "315", ckitoa(x), "");
3353             return((int) sstate);
3354         } else {
3355             fcctrl = x;
3356             return(success = 1);
3357         }
3358 #endif /* COMMENT */
3359 #endif /* NOXFER */
3360
3361       case XYFILT:                      /* Type */
3362         if ((x = cmkey(rmsflg ? rfttab  : fttab,
3363                        rmsflg ? nrfttyp : nfttyp,
3364                        "type of file transfer","text",xxstring)) < 0)
3365           return(x);
3366
3367 #ifdef VMS
3368         /* Allow VMS users to choose record format for binary files */
3369         if ((x == XYFT_B) && (rmsflg == 0)) {
3370             if ((x = cmkey(fbtab,nfbtyp,"VMS record format","fixed",
3371                            xxstring)) < 0)
3372               return(x);
3373         }
3374 #endif /* VMS */
3375         if ((y = cmcfm()) < 0) return(y);
3376         binary = x;
3377         b_save = x;
3378 #ifdef MAC
3379         (void) mac_setfildflg(binary);
3380 #endif /* MAC */
3381 #ifndef NOXFER
3382         if (rmsflg) {
3383             /* Allow for LABELED in VMS & OS/2 */
3384             sstate = setgen('S', "300", ckitoa(x), "");
3385             return((int) sstate);
3386         } else {
3387 #endif /* NOXFER */
3388             return(success = 1);
3389 #ifndef NOXFER
3390         }
3391 #endif /* NOXFER */
3392
3393 #ifndef NOXFER
3394       case XYFILX:                      /* Collision Action */
3395         if ((x = cmkey(colxtab,ncolx,"Filename collision action","backup",
3396                        xxstring)) < 0)
3397           return(x);
3398         if ((y = cmcfm()) < 0) return(y);
3399 #ifdef CK_LOGIN
3400         if (isguest) {
3401             /* Don't let guests change existing files */
3402             printf("?This command not valid for guests\n");
3403             return(-9);
3404         }
3405 #endif /* CK_LOGIN */
3406 #ifdef COMMENT
3407         /* Not appropriate - DISABLE DELETE only refers to server */
3408         if ((x == XYFX_X || x == XYFX_B || x == XYFX_U || x == XYFX_A) &&
3409             (!ENABLED(en_del))) {
3410             printf("?Sorry, file deletion is disabled.\n");
3411             return(-9);
3412         }
3413 #endif /* COMMENT */
3414         fncact = x;
3415         ptab[protocol].fnca = x;
3416         if (rmsflg) {
3417             sstate = setgen('S', "302", ckitoa(fncact), "");
3418             return((int) sstate);
3419         } else {
3420             if (fncact == XYFX_R) ckwarn = 1; /* FILE WARNING implications */
3421             if (fncact == XYFX_X) ckwarn = 0; /* ... */
3422             return(success = 1);
3423         }
3424
3425       case XYFILW:                      /* Warning/Write-Protect */
3426         if ((x = seton(&ckwarn)) < 0) return(x);
3427         if (ckwarn)
3428           fncact = XYFX_R;
3429         else
3430           fncact = XYFX_X;
3431         return(success = 1);
3432
3433 #ifdef CK_LABELED
3434       case XYFILL:                      /* LABELED FILE parameters */
3435         if ((x = cmkey(lbltab,nlblp,"Labeled file feature","",
3436                        xxstring)) < 0)
3437           return(x);
3438         if ((success = seton(&y)) < 0)
3439           return(success);
3440         if (y)                          /* Set or reset the selected bit */
3441           lf_opts |= x;                 /* in the options bitmask. */
3442         else
3443           lf_opts &= ~x;
3444         return(success);
3445 #endif /* CK_LABELED */
3446
3447       case XYFILI: {                    /* INCOMPLETE */
3448           extern struct keytab ifdatab[];
3449           extern int keep;
3450           if ((y = cmkey(ifdatab,3,"","auto",xxstring)) < 0) return(y);
3451           if ((x = cmcfm()) < 0) return(x);
3452           if (rmsflg) {
3453               sstate = setgen('S',
3454                               "310",
3455                               y == 0 ? "0" : (y == 1 ? "1" : "2"),
3456                               ""
3457                               );
3458               return((int) sstate);
3459           } else {
3460               keep = y;
3461               return(success = 1);
3462           }
3463       }
3464
3465 #ifdef CK_TMPDIR
3466       case XYFILG: {                    /* Download directory */
3467           int x;
3468           char *s;
3469 #ifdef ZFNQFP
3470           struct zfnfp * fnp;
3471 #endif /* ZFNQFP */
3472 #ifdef MAC
3473           char temp[34];
3474 #endif /* MAC */
3475
3476 #ifdef GEMDOS
3477           if ((x = cmdir("Name of local directory, or carriage return",
3478                          "",&s,
3479                          NULL)) < 0 ) {
3480               if (x != -3)
3481                 return(x);
3482           }
3483 #else
3484 #ifdef OS2
3485           if ((x = cmdir("Name of PC disk and/or directory,\n\
3486        or press the Enter key to use current directory",
3487                          "",&s,xxstring)) < 0 ) {
3488               if (x != -3)
3489                 return(x);
3490           }
3491 #else
3492 #ifdef MAC
3493           x = ckstrncpy(temp,zhome(),32);
3494           if (x > 0) if (temp[x-1] != ':') { temp[x] = ':'; temp[x+1] = NUL; }
3495           if ((x = cmtxt("Name of Macintosh volume and/or folder,\n\
3496  or press the Return key for the desktop on the boot disk",
3497                          temp,&s, xxstring)) < 0 )
3498             return(x);
3499 #else
3500           if ((x = cmdir("Name of local directory, or carriage return",
3501                          "", &s, xxstring)) < 0 ) {
3502               if (x != -3)
3503                 return(x);
3504           }
3505 #endif /* MAC */
3506 #endif /* OS2 */
3507 #endif /* GEMDOS */
3508           debug(F110,"download dir",s,0);
3509
3510 #ifndef MAC
3511           if (x == 2) {
3512               printf("?Wildcards not allowed in directory name\n");
3513               return(-9);
3514           }
3515 #endif /* MAC */
3516
3517 #ifdef ZFNQFP
3518           if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
3519               if (fnp->fpath)
3520                 if ((int) strlen(fnp->fpath) > 0)
3521                   s = fnp->fpath;
3522           }
3523           debug(F110,"download zfnqfp",s,0);
3524 #endif /* ZFNQFP */
3525
3526           ckstrncpy(line,s,LINBUFSIZ);  /* Make a safe copy */
3527 #ifndef MAC
3528           if ((x = cmcfm()) < 0)        /* Get confirmation */
3529             return(x);
3530 #endif /* MAC */
3531
3532 #ifdef CK_LOGIN
3533         if (isguest) {
3534             /* Don't let guests change existing files */
3535             printf("?This command not valid for guests\n");
3536             return(-9);
3537         }
3538 #endif /* CK_LOGIN */
3539           x = strlen(s);
3540
3541           if (x) {
3542 #ifdef datageneral                      /* AOS/VS */
3543               if (s[x-1] == ':')        /* homdir ends in colon, */
3544                 s[x-1] = NUL;           /* and "dir" doesn't like that... */
3545 #else
3546 #ifdef OS2ORUNIX                        /* Unix or K-95... */
3547               if ((x < (LINBUFSIZ - 2)) && /* Add trailing dirsep */
3548                   (s[x-1] != '/')) {    /* if none present.  */
3549                   s[x] = '/';           /* Note that Windows path has */
3550                   s[x+1] = NUL;         /* been canonicalized to forward */
3551               }                         /* slashes at this point. */
3552 #endif /* OS2ORUNIX */
3553 #endif /* datageneral */
3554               makestr(&dldir,s);
3555           } else
3556             makestr(&dldir,NULL);       /* dldir is NULL when not assigned */
3557
3558           return(success = 1);
3559       }
3560 #endif /* CK_TMPDIR */
3561       case XYFILY:
3562         return(setdest());
3563 #endif /* NOXFER */
3564
3565 #ifdef CK_CTRLZ
3566       case XYFILV: {                    /* EOF */
3567           extern int eofmethod;
3568           if ((x = cmkey(eoftab,3,"end-of-file detection method","",
3569                          xxstring)) < 0)
3570             return(x);
3571           if ((y = cmcfm()) < 0)
3572             return(y);
3573           eofmethod = x;
3574           return(success = 1);
3575       }
3576 #endif /* CK_CTRLZ */
3577
3578 #ifndef NOXFER
3579 #ifdef UNIX
3580       case XYFILH: {                    /* OUTPUT */
3581           extern int zofbuffer, zobufsize, zofblock;
3582 #ifdef DYNAMIC
3583           extern char * zoutbuffer;
3584 #endif /* DYNAMIC */
3585
3586           if ((x = cmkey(zoftab,nzoftab,"output file writing method","",
3587                          xxstring)) < 0)
3588             return(x);
3589           if (x == ZOF_BUF || x == ZOF_NBUF) {
3590               if ((y = cmnum("output buffer size","32768",10,&z,xxstring)) < 0)
3591                 return(y);
3592               if (z < 1) {
3593                   printf("?Bad size - %d\n", z);
3594                   return(-9);
3595               }
3596           }
3597           if ((y = cmcfm()) < 0) return(y);
3598           switch (x) {
3599             case ZOF_BUF:
3600             case ZOF_NBUF:
3601               zofbuffer = (x == ZOF_BUF);
3602               zobufsize = z;
3603               break;
3604             case ZOF_BLK:
3605             case ZOF_NBLK:
3606               zofblock = (x == ZOF_BLK);
3607               break;
3608           }
3609 #ifdef DYNAMIC
3610           if (zoutbuffer) free(zoutbuffer);
3611           if (!(zoutbuffer = (char *)malloc(z))) {
3612               printf("MEMORY ALLOCATION ERROR - FATAL\n");
3613               doexit(BAD_EXIT,-1);
3614           } else
3615             zobufsize = z;
3616 #else
3617           if (z <= OBUFSIZE) {
3618               zobufsize = z;
3619           } else {
3620               printf("?Sorry, %d is too big - %d is the maximum\n",z,OBUFSIZE);
3621               return(-9);
3622           }
3623 #endif /* DYNAMIC */
3624           return(success = 1);
3625       }
3626 #endif /* UNIX */
3627
3628 #ifdef PATTERNS
3629       case XYFIBP:                      /* BINARY-PATTERN */
3630       case XYFITP: {                    /* TEXT-PATTERN */
3631           char * tmp[FTPATTERNS];
3632           int i, n = 0;
3633           while (n < FTPATTERNS) {
3634               tmp[n] = NULL;
3635               if ((x = cmfld("Pattern","",&s,xxstring)) < 0)
3636                 break;
3637               ckstrncpy(line,s,LINBUFSIZ);
3638               s = brstrip(line);
3639               makestr(&(tmp[n++]),s);
3640           }
3641           if (x == -3) x = cmcfm();
3642           for (i = 0; i <= n; i++) {
3643               if (x > -1) {
3644                   if (y == XYFIBP)
3645                     makestr(&(binpatterns[i]),tmp[i]);
3646                   else
3647                     makestr(&(txtpatterns[i]),tmp[i]);
3648               }
3649               free(tmp[i]);
3650           }
3651           if (y == XYFIBP)              /* Null-terminate the list */
3652             makestr(&(binpatterns[i]),NULL);
3653           else
3654             makestr(&(txtpatterns[i]),NULL);
3655           return(x);
3656       }
3657
3658       case XYFIPA:                      /* PATTERNS */
3659         if ((x = setonaut(&patterns)) < 0)
3660           return(x);
3661         return(success = 1);
3662 #endif /* PATTERNS */
3663 #endif /* NOXFER */
3664
3665 #ifdef UNICODE
3666       case XYFILU: {                    /* UCS */
3667           extern int ucsorder, ucsbom, byteorder;
3668           if ((x = cmkey(ucstab,nucstab,"","",xxstring)) < 0)
3669             return(x);
3670           switch (x) {
3671             case UCS_BYT:
3672               if ((y = cmkey(botab,nbotab,
3673                              "Byte order",
3674                              byteorder ? "little-endian" : "big-endian",
3675                              xxstring
3676                              )
3677                    ) < 0)
3678                 return(y);
3679               if ((x = cmcfm()) < 0)
3680                 return(x);
3681               ucsorder = y;
3682               return(success = 1);
3683             case UCS_BOM:
3684               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
3685                 return(y);
3686               if ((x = cmcfm()) < 0)
3687                 return(x);
3688               ucsbom = y;
3689               return(success = 1);
3690             default:
3691               return(-2);
3692           }
3693       }
3694 #endif /* UNICODE */
3695
3696 #ifndef datageneral
3697       case XYF_INSP: {                  /* SCAN (INSPECTION) */
3698           extern int filepeek, nscanfile;
3699           if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
3700             return(x);
3701           if (y) {
3702               if ((y = cmnum("How much to scan",ckitoa(SCANFILEBUF),
3703                              10,&z,xxstring)) < 0)
3704                 return(y);
3705           }
3706           if ((y = cmcfm()) < 0)
3707             return(y);
3708 #ifdef VMS
3709           filepeek = 0;
3710           nscanfile = 0;
3711           return(success = 0);
3712 #else
3713           filepeek = x;
3714           nscanfile = z;
3715           return(success = 1);
3716 #endif /* VMS */
3717       }
3718 #endif /* datageneral */
3719
3720       case XYF_DFLT:
3721         y = 0;
3722 #ifndef NOCSETS
3723         if ((y = cmkey(fdfltab,nfdflt,"","",xxstring)) < 0)
3724           return(y);
3725         if (y == 7 || y == 8) {
3726             if (y == 7)
3727               s = fcsinfo[dcset7].keyword;
3728             else
3729               s = fcsinfo[dcset8].keyword;
3730             if ((x = cmkey(fcstab,nfilc,"character-set",s,xxstring)) < 0)
3731               return(x);
3732         }
3733         ckstrncpy(line,fcsinfo[x].keyword,LINBUFSIZ);
3734         s = line;
3735 #endif /* NOCSETS */
3736         if ((z = cmcfm()) < 0)
3737           return(z);
3738         switch (y) {
3739 #ifndef NOCSETS
3740           case 7:
3741             if (fcsinfo[x].size != 128) {
3742                 printf("%s - Not a 7-bit set\n",s);
3743                 return(-9);
3744             }
3745             dcset7 = x;
3746             break;
3747           case 8:
3748             if (fcsinfo[x].size != 256) {
3749                 printf("%s - Not an 8-bit set\n",s);
3750                 return(-9);
3751             }
3752             dcset8 = x;
3753             break;
3754 #endif /* NOCSETS */
3755           default:
3756             return(-2);
3757         }
3758         return(success = 1);
3759
3760 #ifndef NOXFER
3761       case 9997:                        /* FASTLOOKUPS */
3762         return(success = seton(&stathack));
3763 #endif /* NOXFER */
3764
3765 #ifdef UNIX
3766 #ifdef DYNAMIC
3767       case XYF_LSIZ: {                  /* LISTSIZE */
3768           int zz;
3769           y = cmnum("Maximum number of filenames","",10,&x,xxstring);
3770           if ((x = setnum(&zz,x,y,-1)) < 0)
3771             return(x);
3772           if (zsetfil(zz,3) < 0) {
3773               printf("?Memory allocation failure\n");
3774               return(-9);
3775           }
3776           return(success = 1);
3777       }
3778       case XYF_SSPA: {                  /* STRINGSPACE */
3779           int zz;
3780           y = cmnum("Number of characters for filename list",
3781                     "",10,&x,xxstring);
3782           if ((x = setnum(&zz,x,y,-1)) < 0)
3783             return(x);
3784           if (zsetfil(zz,1) < 0) {
3785               printf("?Memory allocation failure\n");
3786               return(-9);
3787           }
3788           return(success = 1);
3789       }
3790
3791 #endif /* DYNAMIC */
3792 #endif /* UNIX */
3793
3794       default:
3795         printf("?unexpected file parameter\n");
3796         return(-2);
3797     }
3798 }
3799
3800 #ifndef NOLOCAL
3801 #ifdef OS2
3802 /* MS-DOS KERMIT compatibility modes */
3803 int
3804 setmsk() {
3805     if ((y = cmkey(msktab,nmsk,"MS-DOS Kermit compatibility mode",
3806                     "keycodes",xxstring)) < 0) return(y);
3807
3808     switch ( y ) {
3809 #ifdef COMMENT
3810       case MSK_COLOR:
3811         return(seton(&mskcolors));
3812 #endif /* COMMENT */
3813       case MSK_KEYS:
3814         return(seton(&mskkeys));
3815       default:                          /* Shouldn't get here. */
3816         return(-2);
3817     }
3818 }
3819 #endif /* OS2 */
3820
3821 int
3822 settrmtyp() {
3823 #ifdef OS2
3824 #ifdef TNCODE
3825     extern int ttnum;                    /* Last Telnet Terminal Type sent */
3826     extern int ttnumend;                 /* Has end of list been found */
3827 #endif /* TNCODE */
3828     if ((x = cmkey(ttyptab,nttyp,"","vt320",xxstring)) < 0)
3829       return(x);
3830     if ((y = cmcfm()) < 0)
3831       return(y);
3832     settermtype(x,1);
3833 #ifdef TNCODE
3834     /* So we send the correct terminal name to the host if it asks for it */
3835     ttnum = -1;                         /* Last Telnet Terminal Type sent */
3836     ttnumend = 0;                       /* end of list not found */
3837 #endif /* TNCODE */
3838     return(success = 1);
3839 #else  /* Not OS2 */
3840     printf(
3841 "\n Sorry, this version of C-Kermit does not support the SET TERMINAL TYPE\n");
3842     printf(
3843 " command.  Type \"help set terminal\" for further information.\n");
3844 #endif /* OS2 */
3845     return(success = 0);
3846 }
3847
3848 #ifdef CKTIDLE
3849 static char iactbuf[132];
3850
3851 char *
3852 getiact() {
3853     switch (tt_idleact) {
3854       case IDLE_RET:  return("return");
3855       case IDLE_EXIT: return("exit");
3856       case IDLE_HANG: return("hangup");
3857 #ifdef TNCODE
3858       case IDLE_TNOP: return("Telnet NOP");
3859       case IDLE_TAYT: return("Telnet AYT");
3860 #endif /* TNCODE */
3861
3862       case IDLE_OUT: {
3863           int c, k, n;
3864           char * p, * q, * t;
3865           k = ckstrncpy(iactbuf,"output ",132);
3866           n = k;
3867           q = &iactbuf[k];
3868           p = tt_idlestr;
3869           if (!p) p = "";
3870           if (!*p) return("output (nothing)");
3871           while ((c = *p++) && n < 131) {
3872               c &= 0xff;
3873               if (c == '\\') {
3874                   if (n > 130) break;
3875                   *q++ = '\\';
3876                   *q++ = '\\';
3877                   *q = NUL;
3878                   n += 2;
3879               } else if ((c > 31 && c < 127) || c > 159) {
3880                   *q++ = c;
3881                   *q = NUL;
3882                   n++;
3883               } else {
3884                   if (n > (131 - 6))
3885                     break;
3886                   sprintf(q,"\\{%d}",c);
3887                   k = strlen(q);
3888                   q += k;
3889                   n += k;
3890                   *q = NUL;
3891               }
3892           }
3893           *q = NUL;
3894 #ifdef OS2
3895           k = tt_cols[VTERM];
3896 #else
3897           k = tt_cols;
3898 #endif /* OS2 */
3899           if (n > k - 52) {
3900               n = k - 52;
3901               iactbuf[n-2] = '.';
3902               iactbuf[n-1] = '.';
3903               iactbuf[n] = NUL;
3904           }
3905           return(iactbuf);
3906       }
3907       default: return("unknown");
3908     }
3909 }
3910 #endif /* CKTIDLE */
3911
3912 #ifndef NOCSETS
3913 VOID
3914 setlclcharset(x) int x; {
3915     int i;
3916     tcsl = y;                   /* Local character set */
3917 #ifdef OS2
3918     for (i = 0; i < 4; i++) {
3919         G[i].init = TRUE;
3920         x = G[i].designation;
3921         G[i].c1 = (x != tcsl) && cs_is_std(x);
3922         x = G[i].def_designation;
3923         G[i].def_c1 = (x != tcsl) && cs_is_std(x);
3924     }
3925 #endif /* OS2 */
3926 }
3927
3928 VOID
3929 setremcharset(x, z) int x, z; {
3930     int i;
3931
3932 #ifdef KUI
3933     KuiSetProperty( KUI_TERM_REMCHARSET, (long) x, (long) z ) ;
3934 #endif /* KUI */
3935 #ifdef UNICODE
3936     if (x == TX_TRANSP)
3937 #else /* UNICODE */
3938     if (x == FC_TRANSP)
3939 #endif /* UNICODE */
3940     {                           /* TRANSPARENT? */
3941 #ifndef OS2
3942         tcsr = tcsl;            /* Make both sets the same */
3943 #else /* OS2 */
3944 #ifdef CKOUNI
3945         tt_utf8 = 0;            /* Turn off UTF8 flag */
3946         tcsr = tcsl = dec_kbd = TX_TRANSP; /* No translation */
3947         tcs_transp = 1;
3948
3949         if (!cs_is_nrc(tcsl)) {
3950             G[0].def_designation = G[0].designation = TX_ASCII;
3951             G[0].init = TRUE;
3952             G[0].def_c1 = G[0].c1 = FALSE;
3953             G[0].size = cs94;
3954             G[0].national = FALSE;
3955         }
3956         for (i = cs_is_nrc(tcsl) ? 0 : 1; i < 4; i++) {
3957             G[i].def_designation = G[i].designation = tcsl;
3958             G[i].init = TRUE;
3959             G[i].def_c1 = G[i].c1 = FALSE;
3960             switch (cs_size(G[i].designation)) { /* 94, 96, or 128 */
3961             case 128:
3962             case 96:
3963                 G[i].size = G[i].def_size = cs96;
3964                 break;
3965             case 94:
3966                 G[i].size = G[i].def_size = cs94;
3967                 break;
3968             default:
3969                 G[i].size = G[i].def_size = csmb;
3970                 break;
3971             }
3972             G[i].national = cs_is_nrc(x);
3973         }
3974 #else /* CKOUNI */
3975         tcsr = tcsl;            /* Make both sets the same */
3976         for (i = 0; i < 4; i++) {
3977             G[i].def_designation = G[i].designation = FC_TRANSP;
3978             G[i].init = FALSE;
3979             G[i].size = G[i].def_size = cs96;
3980             G[i].c1 = G[i].def_c1 = FALSE;
3981             G[i].rtoi = NULL;
3982             G[i].itol = NULL;
3983             G[i].ltoi = NULL;
3984             G[i].itor = NULL;
3985             G[i].national = FALSE;
3986         }
3987 #endif /* CKOUNI */
3988 #endif /* OS2 */
3989         return;
3990     }
3991 #ifdef OS2
3992 #ifdef CKOUNI
3993     else if (x == TX_UTF8) {
3994         tcs_transp = 0;
3995         tt_utf8 = 1;            /* Turn it on if we are UTF8 */
3996         return;
3997     }
3998 #endif /* CKOUNI */
3999     else {
4000         tcs_transp = 0;
4001         tcsr = x;                       /* Remote character set */
4002 #ifdef CKOUNI
4003         tt_utf8 = 0;                    /* Turn off UTF8 flag */
4004 #endif /* CKOUNI */
4005
4006         if (z == TT_GR_ALL) {
4007             int i;
4008 #ifdef UNICODE
4009             dec_kbd = x;
4010 #endif /* UNICODE */
4011             for (i = 0; i < 4; i++) {
4012                 G[i].init = TRUE;
4013                 if ( i == 0 && !cs_is_nrc(x) ) {
4014                     G[0].designation = G[0].def_designation = FC_USASCII;
4015                     G[0].size = G[0].def_size = cs94;
4016                     G[0].national = 1;
4017                 } else {
4018                     G[i].def_designation = G[i].designation = x;
4019                     switch (cs_size(x)) {       /* 94, 96, or 128 */
4020                     case 128:
4021                     case 96:
4022                         G[i].size = G[i].def_size = cs96;
4023                         break;
4024                     case 94:
4025                         G[i].size = G[i].def_size = cs94;
4026                         break;
4027                     default:
4028                         G[i].size = G[i].def_size = csmb;
4029                         break;
4030                     }
4031                     G[i].national = cs_is_nrc(x);
4032                 }
4033                 G[i].c1 = G[i].def_c1 = x != tcsl && cs_is_std(x);
4034             }
4035 #ifdef UNICODE
4036         } else if (z == TT_GR_KBD) {    /* Keyboard only */
4037             dec_kbd = x;
4038 #endif /* UNICODE */
4039         } else {                        /* Specific Gn */
4040             G[z].def_designation = G[z].designation = x;
4041             G[z].init = TRUE;
4042             switch (cs_size(x)) {       /* 94, 96, or 128 */
4043             case 128:
4044             case 96:
4045                 G[z].size = G[z].def_size = cs96;
4046                 break;
4047             case 94:
4048                 G[z].size = G[z].def_size = cs94;
4049                 break;
4050             default:
4051                 G[z].size = G[z].def_size = csmb;
4052                 break;
4053             }
4054             G[z].c1 = G[z].def_c1 = x != tcsl && cs_is_std(x);
4055             G[z].national = cs_is_nrc(x);
4056         }
4057     }
4058 #else /* not OS2 */
4059     tcsr = x;                   /* Remote character set */
4060 #endif /* OS2 */
4061 }
4062 #endif /* NOCSETS */
4063
4064 VOID
4065 setcmask(x) int x; {
4066     if (x == 7) {
4067         cmask = 0177;
4068     } else if (x == 8) {
4069         cmask = 0377;
4070         parity = 0;
4071     }
4072 #ifdef KUI      
4073     KuiSetProperty(KUI_TERM_CMASK,x,0);
4074 #endif /* KUI */
4075 }
4076
4077 #ifdef CK_AUTODL
4078 VOID
4079 setautodl(x,y) int x,y; {
4080     autodl = x;
4081     adl_ask = y;
4082 #ifdef KUI      
4083     KuiSetProperty(KUI_TERM_AUTODOWNLOAD,x?(y?2:1):0,0);
4084 #endif /* KUI */
4085 }
4086 #endif /* CK_AUTODL */
4087
4088 #ifdef OS2
4089 VOID
4090 seturlhl(int x) {
4091     tt_url_hilite = x;
4092 #ifdef KUI      
4093     KuiSetProperty(KUI_TERM_URL_HIGHLIGHT,x,0);
4094 #endif /* KUI */
4095 }
4096
4097 VOID
4098 setaprint(int x) {
4099     extern int aprint;
4100     aprint = x;
4101 #ifdef KUI
4102     KuiSetProperty(KUI_TERM_PRINTERCOPY,x,0);
4103 #endif /* KUI */
4104 }
4105 #endif /* OS2 */
4106
4107 int
4108 settrm() {
4109     int i = 0;
4110 #ifdef OS2
4111     extern int colorreset, user_erasemode;
4112 #endif /* OS2 */
4113     if ((y = cmkey(trmtab,ntrm,"", "",xxstring)) < 0) return(y);
4114 #ifdef MAC
4115     printf("\n?Sorry, not implemented yet.  Please use the Settings menu.\n");
4116     return(-9);
4117 #else
4118 #ifdef IKSD
4119     if (inserver) {
4120         if ((y = cmcfm()) < 0) return(y);
4121         printf("?Sorry, command disabled.\r\n");
4122         return(success = 0);
4123     }
4124 #endif /* IKSD */
4125
4126     switch (y) {
4127       case XYTBYT:                      /* SET TERMINAL BYTESIZE */
4128         if ((y = cmnum("bytesize for terminal connection","8",10,&x,
4129                        xxstring)) < 0)
4130           return(y);
4131         if (x != 7 && x != 8) {
4132             printf("\n?The choices are 7 and 8\n");
4133             return(success = 0);
4134         }
4135         if ((y = cmcfm()) < 0) return(y);
4136         setcmask(x);
4137 #ifdef OS2
4138         if (IS97801(tt_type_mode))
4139           SNI_bitmode(x);
4140 #endif /* OS2 */
4141         return(success = 1);
4142
4143       case XYTSO:                       /* SET TERMINAL LOCKING-SHIFT */
4144         return(seton(&sosi));
4145
4146       case XYTNL:                       /* SET TERMINAL NEWLINE-MODE */
4147         return(seton(&tnlm));
4148
4149 #ifdef OS2
4150       case XYTCOL:
4151         if ((x = cmkey(ttycoltab,ncolors,"","terminal",xxstring)) < 0)
4152           return(x);
4153         else if (x == TTCOLRES) {
4154             if ((y = cmkey(ttcolmodetab,ncolmode,
4155                            "","default-color",xxstring)) < 0)
4156               return(y);
4157             if ((z = cmcfm()) < 0)
4158               return(z);
4159             colorreset = y;
4160             return(success = 1);
4161         } else if (x == TTCOLERA) {
4162             if ((y = cmkey(ttcolmodetab,ncolmode,"",
4163                            "current-color",xxstring)) < 0)
4164               return(y);
4165             if ((z = cmcfm()) < 0)
4166               return(z);
4167             user_erasemode = y;
4168             return(success=1);
4169         } else {                        /* No parse error */
4170             int fg = 0, bg = 0;
4171             fg = cmkey(ttyclrtab, nclrs,
4172                        (x == TTCOLBOR ?
4173                         "color for screen border" :
4174                         "foreground color and then background color"),
4175                        "lgray", xxstring);
4176             if (fg < 0)
4177               return(fg);
4178             if (x != TTCOLBOR) {
4179                 if ((bg = cmkey(ttyclrtab,nclrs,
4180                                 "background color","blue",xxstring)) < 0)
4181                   return(bg);
4182             }
4183             if ((y = cmcfm()) < 0)
4184               return(y);
4185             switch (x) {
4186               case TTCOLNOR:
4187                 colornormal = fg | bg << 4;
4188                 fgi = fg & 0x08;
4189                 bgi = bg & 0x08;
4190                 break;
4191               case TTCOLREV:
4192                 colorreverse = fg | bg << 4;
4193                 break;
4194               case TTCOLITA:
4195                 coloritalic = fg | bg << 4;
4196                 break;
4197               case TTCOLUND:
4198                 colorunderline = fg | bg << 4;
4199                 break;
4200               case TTCOLGRP:
4201                 colorgraphic = fg | bg << 4;
4202                 break;
4203               case TTCOLDEB:
4204                 colordebug = fg | bg << 4;
4205                 break;
4206               case TTCOLSTA:
4207                 colorstatus = fg | bg << 4;
4208                 break;
4209               case TTCOLHLP:
4210                 colorhelp = fg | bg << 4;
4211                 break;
4212               case TTCOLBOR:
4213                 colorborder = fg;
4214                 break;
4215               case TTCOLSEL:
4216                 colorselect = fg | bg << 4;
4217                 break;
4218               default:
4219                 printf("%s - invalid\n",cmdbuf);
4220                 return(-9);
4221                 break;
4222             }
4223             scrninitialized[VTERM] = 0;
4224             VscrnInit(VTERM);
4225         }
4226         return(success = 1);
4227
4228       case XYTCUR: {                    /* SET TERMINAL CURSOR */
4229           extern int cursorena[];
4230           extern int cursoron[] ;       /* Cursor state on/off       */
4231           if ((x = cmkey(ttycurtab,ncursors,"","underline",xxstring)) < 0)
4232             return(x);
4233           if ((z = cmkey(curontab,ncuron,"","on",xxstring)) < 0)
4234             return(z);
4235           if ((y = cmcfm()) < 0) return(y);
4236           tt_cursor = tt_cursor_usr = x;
4237           if ( z == 2 ) {
4238               cursorena[VTERM] = tt_cursorena_usr = 1;
4239               tt_cursor_blink = 0;
4240           } else {
4241               cursorena[VTERM] = tt_cursorena_usr = z;/* turn cursor on/off */
4242               tt_cursor_blink = 1;
4243           }
4244           cursoron[VTERM] = FALSE; /* Force newcursor to restore the cursor */
4245           return(success = 1);
4246       }
4247 #endif /* OS2 */
4248
4249       case XYTTYP:                      /* SET TERMINAL TYPE */
4250         return(settrmtyp());
4251
4252 #ifdef OS2
4253       case XYTARR:                      /* SET TERMINAL ARROW-KEYS */
4254         if ((x = cmkey(akmtab,2,"","",xxstring)) < 0) return(x);
4255         if ((y = cmcfm()) < 0) return(y);
4256         tt_arrow = x;                   /* TTK_NORM / TTK_APPL; see ckuusr.h */
4257         return(success = 1);
4258
4259       case XYTKPD:                      /* SET TERMINAL KEYPAD-MODE */
4260         if ((x = cmkey(kpmtab,2,"","",xxstring)) < 0) return(x);
4261         if ((y = cmcfm()) < 0) return(y);
4262         tt_keypad = x;                  /* TTK_NORM / TTK_APPL; see ckuusr.h */
4263         return(success = 1);
4264
4265       case XYTUNX: {                    /* SET TERM UNIX-MODE (DG) */
4266         extern int dgunix,dgunix_usr;
4267         x = seton(&dgunix);
4268         dgunix_usr = dgunix;
4269         return(x);
4270       }
4271       case XYTKBMOD: {                  /* SET TERM KEYBOARD MODE */
4272           extern int tt_kb_mode;
4273           if ((x = cmkey(kbmodtab,
4274                          nkbmodtab,
4275                          "normal",
4276                          "special keyboard mode for terminal emulation",
4277                          xxstring)
4278                ) < 0)
4279             return(x);
4280           if ((y = cmcfm()) < 0) return(y);
4281           tt_kb_mode = x;
4282           return(success = 1);
4283       }
4284
4285       case XYTWRP:                      /* SET TERMINAL WRAP */
4286         return(seton(&tt_wrap));
4287
4288       case XYSCRS:
4289         if ((y = cmnum("CONNECT scrollback buffer size, lines","2000",10,&x,
4290                        xxstring)) < 0)
4291           return(y);
4292         /* The max number of lines is the RAM  */
4293         /* we can actually dedicate to a       */
4294         /* scrollback buffer given the maximum */
4295         /* process memory space of 512MB       */
4296         if (x < 256 || x > 2000000L) {
4297             printf("\n?The size must be between 256 and 2,000,000.\n");
4298             return(success = 0);
4299         }
4300         if ((y = cmcfm()) < 0) return(y);
4301         tt_scrsize[VTERM] = x;
4302         VscrnInit(VTERM);
4303         return(success = 1);
4304 #endif /* OS2 */
4305
4306 #ifndef NOCSETS
4307       case XYTCS: {                     /* SET TERMINAL CHARACTER-SET */
4308         int eol;
4309           /* set terminal character-set <remote> <local> */
4310         if ((x = cmkey(
4311 #ifdef CKOUNI
4312                        txrtab,ntxrtab,
4313 #else  /* CKOUNI */
4314                        ttcstab,ntermc,
4315 #endif /* CKOUNI */
4316                        "remote terminal character-set","",xxstring)) < 0)
4317           return(x);
4318
4319 #ifdef UNICODE
4320         if (x == TX_TRANSP
4321 #ifdef CKOUNI
4322             || x == TX_UTF8
4323 #endif /* CKOUNI */
4324            ) {
4325               if ((y = cmcfm()) < 0)    /* Confirm the command */
4326                   return(y);
4327 #ifdef OS2
4328             if ( isunicode() && x == TX_TRANSP ) {
4329                 /* If we are in unicode display mode then transparent
4330                  * only affects the output direction.  We need to know
4331                  * the actual remote character set in order to perform
4332                  * the tcsr -> ucs2 translation for display.
4333                  */
4334                 x = y = tcsl;
4335             } else
4336 #endif /* OS2 */
4337                 y = x;
4338         }
4339 #else /* UNICODE */
4340         if (x == FC_TRANSP) {
4341             if ((y = cmcfm()) < 0)      /* Confirm the command */
4342                 return(y);
4343             y = x;
4344         }
4345 #endif /* UNICODE */
4346
4347         /* Not transparent or UTF8, so get local set to translate it into */
4348         s = "";
4349 #ifdef OS2
4350         y = os2getcp();                 /* Default is current code page */
4351         switch (y) {
4352           case 437: s = "cp437"; break;
4353           case 850: s = "cp850"; break;
4354           case 852: s = "cp852"; break;
4355           case 857: s = "cp857"; break;
4356           case 858: s = "cp858"; break;
4357           case 862: s = "cp862"; break;
4358           case 866: s = "cp866"; break;
4359           case 869: s = "cp869"; break;
4360           case 1250: s = "cp1250"; break;
4361           case 1251: s = "cp1251"; break;
4362           case 1252: s = "cp1252"; break;
4363           case 1253: s = "cp1253"; break;
4364           case 1254: s = "cp1254"; break;
4365           case 1255: s = "cp1255"; break;
4366           case 1256: s = "cp1256"; break;
4367           case 1257: s = "cp1257"; break;
4368           case 1258: s = "cp1258"; break;
4369         }
4370 #ifdef PCFONTS
4371 /*
4372    If the user has loaded a font with SET TERMINAL FONT then we want
4373    to change the default code page to the font that was loaded.
4374 */
4375         if (tt_font != TTF_ROM) {
4376             for (y = 0; y < ntermfont; y++ ) {
4377                 if (term_font[y].kwval == tt_font) {
4378                     s = term_font[y].kwd;
4379                     break;
4380                 }
4381             }
4382         }
4383 #endif /* PCFONTS */
4384 #else  /* Not K95... */
4385         s = fcsinfo[fcharset].keyword;
4386 #endif /* OS2 */
4387
4388         if ((y = cmkey(
4389 #ifdef CKOUNI
4390                        txrtab,ntxrtab,
4391 #else /* CKOUNI */
4392                        ttcstab,ntermc,
4393 #endif /* CKOUNI */
4394                        "local character-set",s,xxstring)) < 0)
4395           return(y);
4396
4397 #ifdef UNICODE
4398         if (y == TX_UTF8) {
4399             printf("?UTF8 may not be used as a local character set.\r\n");
4400             return(-9);
4401         }
4402 #endif /* UNICODE */
4403 #ifdef OS2
4404         if ((z = cmkey(graphsettab,ngraphset,
4405                        "DEC VT intermediate graphic set","all",xxstring)) < 0)
4406             return(z);
4407 #endif /* OS2 */
4408         if ((eol = cmcfm()) < 0)
4409             return(eol); /* Confirm the command */
4410
4411         /* End of command parsing - actions begin */
4412         setlclcharset(y);
4413         setremcharset(x,z);
4414         return(success = 1);
4415       }
4416 #endif /* NOCSETS */
4417
4418 #ifndef NOCSETS
4419       case XYTLCS:                      /* SET TERMINAL LOCAL-CHARACTER-SET */
4420         /* set terminal character-set <local> */
4421         s = getdcset();                 /* Get display character-set name */
4422         if ((y = cmkey(
4423 #ifdef CKOUNI
4424                        txrtab,ntxrtab,
4425 #else /* CKOUNI */
4426                        fcstab,nfilc,
4427 #endif /* CKOUNI */
4428                        "local character-set",s,xxstring)) < 0)
4429           return(y);
4430
4431 #ifdef UNICODE
4432           if (y == TX_UTF8) {
4433               printf("?UTF8 may not be used as a local character set.\r\n");
4434               return(-9);
4435           }
4436 #endif /* UNICODE */
4437           if ((z = cmcfm()) < 0) return(z); /* Confirm the command */
4438
4439           /* End of command parsing - action begins */
4440
4441         setlclcharset(y);
4442         return(success = 1);
4443 #endif /* NOCSETS */
4444
4445 #ifndef NOCSETS
4446 #ifdef UNICODE
4447       case XYTUNI:                      /* SET TERMINAL UNICODE */
4448         return(seton(&tt_unicode));
4449 #endif /* UNICODE */
4450
4451       case XYTRCS:                      /* SET TERMINAL REMOTE-CHARACTER-SET */
4452         /* set terminal character-set <remote> <Graphic-set> */
4453         if ((x = cmkey(
4454 #ifdef CKOUNI
4455                 txrtab, ntxrtab,
4456 #else /* CKOUNI */
4457                 ttcstab,ntermc,
4458 #endif /* CKOUNI */
4459                        "remote terminal character-set","",xxstring)) < 0)
4460           return(x);
4461
4462 #ifdef UNICODE
4463         if (x == TX_TRANSP
4464 #ifdef CKOUNI
4465             || x == TX_UTF8
4466 #endif /* CKOUNI */
4467            ) {
4468               if ((y = cmcfm()) < 0)    /* Confirm the command */
4469                   return(y);
4470 #ifdef OS2
4471             if ( isunicode() && x == TX_TRANSP ) {
4472                 /* If we are in unicode display mode then transparent
4473                  * only affects the output direction.  We need to know
4474                  * the actual remote character set in order to perform
4475                  * the tcsr -> ucs2 translation for display.
4476                  */
4477                 x = tcsl;
4478             }
4479 #endif /* OS2 */
4480         }
4481 #else /* UNICODE */
4482         if (x == FC_TRANSP) {
4483           if ((y = cmcfm()) < 0)        /* Confirm the command */
4484             return(y);
4485         }
4486 #endif /* UNICODE */
4487         else {
4488 #ifdef OS2
4489           if ((z = cmkey(graphsettab,ngraphset,
4490                       "DEC VT intermediate graphic set","all",xxstring)) < 0)
4491             return(z);
4492 #endif /* OS2 */
4493           if ((y = cmcfm()) < 0)        /* Confirm the command */
4494             return(y);
4495         }
4496         /* Command parsing ends here */
4497
4498         setremcharset(x,z);
4499         return(success = 1);
4500 #endif /* NOCSETS */
4501
4502       case XYTEC:                       /* SET TERMINAL ECHO */
4503         if ((x = cmkey(rltab,nrlt,"which side echos during CONNECT",
4504                        "remote", xxstring)) < 0) return(x);
4505         if ((y = cmcfm()) < 0) return(y);
4506 #ifdef NETCONN
4507         oldplex = x;
4508 #endif /* NETCONN */
4509         duplex = x;
4510         return(success = 1);
4511
4512       case XYTESC:                      /* SET TERM ESC */
4513         if ((x = cmkey(nabltab,nnabltab,"","enabled",xxstring)) < 0)
4514           return(x);
4515         if ((y = cmcfm()) < 0) return(y);
4516         tt_escape = x;
4517         return(1);
4518
4519       case XYTCRD:                      /* SET TERMINAL CR-DISPLAY */
4520         if ((x = cmkey(crdtab,2,"", "normal", xxstring)) < 0) return(x);
4521         if ((y = cmcfm()) < 0) return(y);
4522         tt_crd = x;
4523         return(success = 1);
4524
4525 #ifdef OS2
4526       case XYTANS: {                    /* SET TERMINAL ANSWERBACK */
4527 /*
4528   NOTE: We let them enable and disable the answerback sequence, but we
4529   do NOT let them change it, and we definitely do not let the host set it.
4530   This is a security feature.
4531
4532   As of 1.1.8 we allow the SET TERM ANSWERBACK MESSAGE <string> to be
4533   used just as MS-DOS Kermit does.  C0 and C1 controls as well as DEL
4534   are not allowed to be used as characters.  They are translated to
4535   underscore.  This may not be set by APC.
4536 */
4537           if ((x = cmkey(anbktab,nansbk,"", "off", xxstring)) < 0)
4538             return(x);
4539           if (x < 2) {
4540               if ((y = cmcfm()) < 0)
4541                 return(y);
4542               tt_answer = x;
4543               return(success = 1);
4544           } else if ( x == 2 || x == 3) {
4545               int len = 0;
4546               extern int safeanswerbk;
4547               extern char useranswerbk[];
4548               if ((y = cmtxt("Answerback extension","",&s,xxstring)) < 0)
4549                 return(y);
4550               if (apcactive == APC_LOCAL ||
4551                   (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
4552                 return(success = 0);
4553               len = strlen(s);
4554               if (x == 2) {
4555                   /* Safe Answerback's don't have C0/C1 chars */
4556                   for (z = 0; z < len; z++) {
4557                       if ((s[z] & 0x7F) <= SP || (s[z] & 0x7F) == DEL)
4558                         useranswerbk[z] = '_';
4559                       else
4560                         useranswerbk[z] = s[z];
4561                   }
4562                   useranswerbk[z] = '\0';
4563                   safeanswerbk = 1 ;    /* TRUE */
4564               } else {
4565                   ckstrncpy(useranswerbk,s,60); /* (see ckocon.c) */
4566                   safeanswerbk = 0;     /* FALSE */
4567               }
4568               updanswerbk();
4569               return(success = 1);
4570           } else
4571             return(success = 0);
4572       }
4573 #endif /* OS2 */
4574
4575 #ifdef CK_APC
4576       case XYTAPC:
4577         if ((y = cmkey(apctab,napctab,
4578                        "application program command execution","",
4579                        xxstring)) < 0)
4580           return(y);
4581         if ((x = cmcfm()) < 0)
4582           return(x);
4583         if (apcactive == APC_LOCAL ||
4584             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
4585           return(success = 0);
4586         apcstatus = y;
4587         return(success = 1);
4588
4589 #ifdef CK_AUTODL
4590       case XYTAUTODL:                   /* AUTODOWNLOAD */
4591         if ((y = cmkey(adltab,nadltab,"Auto-download options","",
4592                        xxstring)) < 0)
4593           return(y);
4594         switch (y) {
4595           case TAD_ON:
4596           case TAD_OFF:
4597             if ((x = cmcfm()) < 0)
4598               return(x);
4599             setautodl(y,0);
4600             break;
4601           case TAD_ASK:
4602             if ((x = cmcfm()) < 0)
4603               return(x);
4604             setautodl(TAD_ON,1);
4605             break;
4606           case TAD_ERR:
4607             if ((y = cmkey(adlerrtab,nadlerrtab,"","", xxstring)) < 0)
4608               return(y);
4609             if ((x = cmcfm()) < 0)
4610               return(x);
4611             adl_err = y;
4612             break;
4613 #ifdef OS2
4614           case TAD_K:
4615             if ((y = cmkey(adlxtab,nadlxtab,"","", xxstring)) < 0)
4616               return(y);
4617             switch (y) {
4618               case TAD_X_C0:
4619                 if ((y = cmkey(adlc0tab,nadlc0tab,"",
4620                                "processed-by-emulator",xxstring)) < 0)
4621                   return(y);
4622                 if ((x = cmcfm()) < 0)
4623                   return(x);
4624                 adl_kc0 = y;
4625                 break;
4626               case TAD_X_DETECT:
4627                 if ((y = cmkey(adldtab,nadldtab,"","packet",xxstring)) < 0)
4628                   return(y);
4629                 if ((x = cmcfm()) < 0)
4630                   return(x);
4631                 adl_kmode = y;
4632                 break;
4633               case TAD_X_STR:
4634                 if ((y = cmtxt("Kermit start string","KERMIT READY TO SEND...",
4635                                &s,xxstring)) < 0)
4636                   return(y);
4637                 free(adl_kstr);
4638                 adl_kstr = strdup(s);
4639                 break;
4640             }
4641             break;
4642
4643           case TAD_Z:
4644             if ((y = cmkey(adlxtab,nadlxtab,"","",xxstring)) < 0)
4645               return(y);
4646             switch (y) {
4647               case TAD_X_C0:
4648                 if ((y = cmkey(adlc0tab,nadlc0tab,"",
4649                                "processed-by-emulator",xxstring)) < 0)
4650                   return(y);
4651                 if ((x = cmcfm()) < 0)
4652                   return(x);
4653                 adl_zc0 = y;
4654                 break;
4655               case TAD_X_DETECT:
4656                 if ((y = cmkey(adldtab,nadldtab,"","packet",xxstring)) < 0)
4657                   return(y);
4658                 if ((x = cmcfm()) < 0)
4659                   return(x);
4660                 adl_zmode = y;
4661                 break;
4662               case TAD_X_STR:
4663                 if ((y = cmtxt("","rz\\{13}",&s,xxstring)) < 0)
4664                   return(y);
4665                 free(adl_zstr);
4666                 adl_zstr = strdup(s);
4667                 break;
4668             }
4669             break;
4670 #endif /* OS2 */
4671         }
4672         return(success = 1);
4673
4674 #endif /* CK_AUTODL */
4675 #endif /* CK_APC */
4676
4677 #ifdef OS2
4678       case XYTBEL:
4679         return(success = setbell());
4680
4681       case XYTMBEL:                     /* MARGIN-BELL */
4682         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
4683         if (y) {                        /* ON */
4684             if ((z = cmnum("Column at which to set margin bell",
4685                            "72",10,&x,xxstring)) < 0)
4686               return(z);
4687         }
4688         if ((z = cmcfm()) < 0) return(z);
4689         marginbell = y;
4690         marginbellcol = x;
4691         return(success = 1);
4692 #endif /* OS2 */
4693
4694 #ifdef CKTIDLE
4695       case XYTIDLE:                     /* IDLE-SEND */
4696       case XYTITMO:                     /* IDLE-TIMEOUT */
4697         if ((z = cmnum("seconds of idle time to wait, or 0 to disable",
4698                        "0",10,&x,xxstring)) < 0)
4699           return(z);
4700         if (y == XYTIDLE) {
4701             if ((y = cmtxt("string to send, may contain kverbs and variables",
4702                            "\\v(newline)",&s,xxstring)) < 0)
4703               return(y);
4704             tt_idlesnd_tmo = x;         /* (old) */
4705             tt_idlelimit = x;           /* (new) */
4706             makestr(&tt_idlestr,brstrip(s)); /* (new) */
4707             tt_idlesnd_str = tt_idlestr; /* (old) */
4708             tt_idleact = IDLE_OUT;      /* (new) */
4709         } else {
4710             if ((y = cmcfm()) < 0)
4711               return(y);
4712             tt_idlelimit = x;
4713         }
4714 #ifdef OS2
4715         puterror(VTERM);
4716 #endif /* OS2 */
4717         return(success = 1);
4718
4719       case XYTIACT: {                   /* SET TERM IDLE-ACTION */
4720           if ((y = cmkey(idlacts,nidlacts,"","",xxstring)) < 0)
4721             return(y);
4722           if (y == IDLE_OUT) {
4723               if ((x = cmtxt("string to send, may contain kverbs and variables"
4724                              , "\\v(newline)",&s,xxstring)) < 0)
4725                 return(x);
4726               makestr(&tt_idlestr,brstrip(s)); /* (new) */
4727               tt_idlesnd_str = tt_idlestr; /* (old) */
4728           } else {
4729               if ((x = cmcfm()) < 0)
4730                 return(x);
4731           }
4732           tt_idleact = y;
4733           return(success = 1);
4734       }
4735 #endif /* CKTIDLE */
4736
4737       case XYTDEB:                      /* TERMINAL DEBUG */
4738         y = seton(&x);                  /* Go parse ON or OFF */
4739         if (y > 0)                      /* Command succeeded? */
4740           setdebses(x);
4741         return(y);
4742
4743 #ifdef OS2
4744       case XYTASCRL:                    /* SET TERMINAL AUTOSCROLL */
4745           y = seton(&autoscroll);
4746           return(y);
4747
4748       case XYTAPAGE:                    /* SET TERMINAL AUTOPAGE */
4749           y = seton(&wy_autopage);
4750           return(y);
4751
4752       case XYTROL:                      /* SET TERMINAL ROLL */
4753         if ((y = cmkey(rolltab,nroll,"scrollback mode","insert",xxstring))<0)
4754           return(y);
4755         if (y == TTR_KEYS) {
4756             if ((x = cmkey(rollkeytab,nrollkey,"","send",xxstring))<0)
4757               return(x);
4758             if ((z = cmcfm()) < 0) return(z);
4759             tt_rkeys[VTERM] = x;
4760         } else {
4761             if ((x = cmcfm()) < 0) return(x);
4762             tt_roll[VTERM] = y;
4763         }
4764         return(success = 1);
4765
4766       case XYTCTS:                      /* SET TERMINAL TRANSMIT-TIMEOUT */
4767         y = cmnum("Maximum seconds to allow CTS off during CONNECT",
4768                   "5",10,&x,xxstring);
4769         return(setnum(&tt_ctstmo,x,y,10000));
4770
4771       case XYTCPG: {                    /* SET TERMINAL CODE-PAGE */
4772         int i;
4773         int cp = -1;
4774         y = cmnum("PC code page to use during terminal emulation",
4775                   ckitoa(os2getcp()),10,&x,xxstring);
4776         if ((x = setnum(&cp,x,y,11000)) < 0) return(x);
4777         if (os2setcp(cp) != 1) {
4778 #ifdef NT
4779             if (isWin95())
4780               printf(
4781                  "Sorry, Windows 95 does not support code page switching\n");
4782             else
4783 #endif /* NT */
4784               printf(
4785                  "Sorry, %d is not a valid code page for this system.\n",cp);
4786             return(-9);
4787         }
4788     /* Force the terminal character-sets conversions to be updated */
4789         for ( i = 0; i < 4; i++ )
4790           G[i].init = TRUE;
4791         return(1);
4792     }
4793
4794       case XYTPAC:                      /* SET TERMINAL OUTPUT-PACING */
4795         y = cmnum(
4796            "Pause between sending each character during CONNECT, milliseconds",
4797                   "-1",10,&x,xxstring);
4798         return(setnum(&tt_pacing,x,y,10000));
4799
4800 #ifdef OS2MOUSE
4801       case XYTMOU: {                    /* SET TERMINAL MOUSE */
4802           int old_mou = tt_mouse;
4803           if ((x = seton(&tt_mouse)) < 0)
4804             return(x);
4805           if (tt_mouse != old_mou)
4806             if (tt_mouse)
4807               os2_mouseon();
4808             else
4809               os2_mouseoff();
4810           return(1);
4811       }
4812 #endif /* OS2MOUSE */
4813 #endif /* OS2 */
4814
4815       case XYTWID: {
4816           if ((y = cmnum(
4817 #ifdef OS2
4818                          "number of columns in display window during CONNECT",
4819 #else
4820                          "number of columns on your screen",
4821 #endif /* OS2 */
4822                          "80",10,&x,xxstring)) < 0)
4823             return(y);
4824           if ((y = cmcfm()) < 0) return(y);
4825 #ifdef OS2
4826           return(success = os2_settermwidth(x));
4827 #else  /* Not OS/2 */
4828           tt_cols = x;
4829           return(success = 1);
4830 #endif /* OS2 */
4831       }
4832
4833       case XYTHIG:
4834         if ((y = cmnum(
4835 #ifdef OS2
4836  "number of rows in display window during CONNECT, not including status line",
4837  tt_status[VTERM]?"24":"25",
4838 #else
4839  "24","number of rows on your screen",
4840 #endif /* OS2 */
4841                        10,&x,xxstring)) < 0)
4842           return(y);
4843         if ((y = cmcfm()) < 0) return(y);
4844
4845 #ifdef OS2
4846         return (success = os2_settermheight(x));
4847 #else  /* Not OS/2 */
4848         tt_rows = x;
4849         return(success = 1);
4850 #endif /* OS2 */
4851
4852 #ifdef OS2
4853       case XYTPRN: {                    /* Print Mode */
4854           extern bool xprint, aprint, cprint, uprint;
4855           if ((y = cmkey(prnmtab,nprnmtab,"","off", xxstring)) < 0) return(y);
4856           if ((x = cmcfm()) < 0) return(x);
4857           switch (y) {
4858             case 0:
4859               if (cprint || uprint || aprint || xprint)
4860                 printeroff();
4861               cprint = xprint = uprint = 0;
4862               setaprint(0);
4863               break;
4864             case 1:
4865               if (!(cprint || uprint || aprint || xprint))
4866                 printeron();
4867               setaprint(1);
4868               cprint = xprint = uprint = 0;
4869               break;
4870             case 2:
4871               if (!(cprint || uprint || aprint || xprint))
4872                 printeron();
4873               cprint = 1;
4874               setaprint(0);
4875               xprint = uprint = 0;
4876               break;
4877             case 3:
4878               if (!(cprint || uprint || aprint || xprint))
4879                 printeron();
4880               uprint = 1;
4881               setaprint(0);
4882               xprint = cprint = 0;
4883               break;
4884           }
4885           return(1);
4886       }
4887 #else
4888 #ifdef XPRINT
4889       case XYTPRN: {
4890           extern int tt_print;
4891           if ((x = seton(&tt_print)) < 0)
4892             return(x);
4893           return(success = 1);
4894       }
4895 #endif /* XPRINT */
4896 #endif /* OS2 */
4897
4898 #ifdef OS2
4899       case XYTSCNM: {
4900           extern int decscnm, decscnm_usr;
4901           if ((y = cmkey(normrev,4,"",
4902                          decscnm_usr?"reverse":"normal",
4903                          xxstring)
4904                ) < 0)
4905             return(y);
4906           if ((x = cmcfm()) < 0) return(x);
4907           decscnm_usr = y;
4908           if (decscnm != decscnm_usr)
4909             flipscreen(VTERM);
4910           return(1);
4911     }
4912     case XYTOPTI:
4913         if ((y = cmkey(onoff,2,"",tt_diff_upd?"on":"off",
4914                         xxstring)) < 0) return(y);
4915         if ((x = cmcfm()) < 0) return(x);
4916         tt_diff_upd = y;
4917         return(1);
4918     case XYTUPD: {
4919         int mode, delay;
4920         if ((mode = cmkey(scrnupd,nscrnupd,"","fast",xxstring)) < 0) {
4921             return(mode);
4922         } else {
4923             y = cmnum(
4924             "Pause between FAST screen updates in CONNECT mode, milliseconds",
4925                       "100",10,&x,xxstring
4926                       );
4927             if (x < 0 || x > 1000 ) {
4928                 printf(
4929             "\n?The update rate must be between 0 and 1000 milliseconds.\n"
4930                        );
4931                 return(success = 0);
4932             }
4933             if ((y = cmcfm()) < 0) return(y);
4934
4935             updmode = tt_updmode = mode;
4936             return(setnum(&tt_update,x,y,10000));
4937         }
4938     }
4939     case XYTCTRL:
4940           if ((x = cmkey(termctrl,ntermctrl,"","7",xxstring)) < 0) {
4941               return(x);
4942           } else {
4943               if ((y = cmcfm()) < 0)
4944                   return(y);
4945               switch ( x ) {
4946               case 8:
4947                   send_c1 = send_c1_usr = TRUE;
4948                   break;
4949               case 7:
4950               default:
4951                   send_c1 = send_c1_usr = FALSE;
4952                   break;
4953               }
4954           }
4955           return(success = TRUE);
4956           break;
4957
4958 #ifdef PCFONTS
4959       case XYTFON:
4960         if ( !IsOS2FullScreen() ) {
4961             printf(
4962         "\n?SET TERMINAL FONT is only supported in Full Screen sessions.\n");
4963             return(success = FALSE);
4964         }
4965
4966         if ((x = cmkey(term_font,ntermfont,"","default",xxstring)) < 0) {
4967             return(x);
4968         } else {
4969             if ((y = cmcfm()) < 0) return(y);
4970             if ( !os2LoadPCFonts() ) {
4971                 tt_font = x;
4972                 return(success = TRUE);
4973             } else {
4974                 printf(
4975       "\n?PCFONTS.DLL is not available in CKERMIT executable directory.\n");
4976                 return(success = FALSE);
4977             }
4978         }
4979         break;
4980 #else /* PCFONTS */
4981 #ifdef NT
4982 #ifdef KUI
4983     case XYTFON:
4984         return(setguifont());           /* ckuus3.c */
4985 #endif /* KUI */
4986 #endif /* NT */
4987 #endif /* PCFONTS */
4988
4989       case XYTVCH: {
4990           extern int pheight, marginbot, cmd_rows, cmd_cols;
4991           if ((x = cmkey(tvctab,ntvctab,"",isWin95()?"win95-safe":"enabled",
4992                          xxstring)) < 0)
4993             return(x);
4994           if ((y = cmcfm()) < 0) return(y);
4995 #ifndef KUI
4996           if (x != tt_modechg) {
4997               switch (x) {
4998                 case TVC_DIS:
4999                   /* When disabled the heights of all of the virtual screens */
5000                   /* must be equal to the physical height of the console     */
5001                   /* window and may not be changed.                          */
5002                   /* The width of the window may not be altered.             */
5003                   tt_modechg = TVC_ENA;                 /* Temporary */
5004                   if (marginbot > pheight-(tt_status[VTERM]?1:0))
5005                     marginbot = pheight-(tt_status[VTERM]?1:0);
5006                   tt_szchng[VCMD] = 1 ;
5007                   tt_rows[VCMD] = pheight;
5008                   VscrnInit(VCMD);
5009                   SetCols(VCMD);
5010                   cmd_rows = y;
5011
5012                   tt_szchng[VTERM] = 2 ;
5013                   tt_rows[VTERM] = pheight - (tt_status[VTERM]?1:0);
5014                   VscrnInit(VTERM);
5015
5016                   break;
5017
5018                 case TVC_ENA:
5019                   /* When enabled the physical height of the console windows */
5020                   /* should be adjusted to the height of the virtual screen  */
5021                   /* The width may be set to anything.                       */
5022                   /* nothing to do                                           */
5023                   break;
5024
5025               case TVC_W95:
5026                   /* Win95-safe mode allows the physical height to change    */
5027                   /* but restricts it to a width of 80 and a height equal to */
5028                   /* 25, 43, or 50.  Must be adjusted now.                   */
5029                   /* The virtual heights must be equal to the above.         */
5030                   if (pheight != 25 && pheight != 43 && pheight != 50) {
5031                       if (pheight < 25)
5032                         y = 25;
5033                       else if (pheight < 43)
5034                         y = 43;
5035                       else
5036                         y = 50;
5037                   } else
5038                     y = pheight;
5039
5040                   tt_modechg = TVC_ENA; /* Temporary */
5041
5042                   tt_szchng[VCMD] = 1;
5043                   tt_rows[VCMD] = y;
5044                   tt_cols[VCMD] = 80;
5045                   VscrnInit(VCMD);
5046                   SetCols(VCMD);
5047                   cmd_rows = y;
5048                   cmd_cols = 80;
5049
5050                   marginbot = y-(tt_status[VTERM]?1:0);
5051                   tt_szchng[VTERM] = 2;
5052                   tt_rows[VTERM] = y - (tt_status[VTERM]?1:0);
5053                   tt_cols[VTERM] = 80;
5054                   VscrnInit(VTERM);
5055                   break;
5056               }
5057               tt_modechg = x;
5058           }
5059           return(success = 1);
5060 #else
5061           return(success = 0);
5062 #endif /* KUI */
5063       }
5064       case XYTSTAT: {
5065           extern int marginbot;
5066           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5067           if ((x = cmcfm()) < 0) return(x);
5068           if (y != tt_status[VTERM] || y != tt_status_usr[VTERM]) {
5069               /* Might need to fixup the margins */
5070               if ( marginbot == VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) )
5071                 if (y) {
5072                     marginbot--;
5073                 } else {
5074                     marginbot++;
5075                 }
5076               tt_status_usr[VTERM] = tt_status[VTERM] = y;
5077               if (y) {
5078                     tt_szchng[VTERM] = 2;
5079                     tt_rows[VTERM]--;
5080                     VscrnInit(VTERM);  /* Height set here */
5081 #ifdef TNCODE
5082                     if (TELOPT_ME(TELOPT_NAWS))
5083                       tn_snaws();
5084 #endif /* TNCODE */
5085 #ifdef RLOGCODE
5086                     if (TELOPT_ME(TELOPT_NAWS))
5087                       rlog_naws();
5088 #endif /* RLOGCODE */
5089 #ifdef SSHBUILTIN
5090                     if (TELOPT_ME(TELOPT_NAWS))
5091                       ssh_snaws();
5092 #endif /* SSHBUILTIN */
5093               } else {
5094                   tt_szchng[VTERM] = 1;
5095                   tt_rows[VTERM]++;
5096                   VscrnInit(VTERM);     /* Height set here */
5097 #ifdef TNCODE
5098                   if (TELOPT_ME(TELOPT_NAWS))
5099                     tn_snaws();
5100 #endif /* TNCODE */
5101 #ifdef RLOGCODE
5102                   if (TELOPT_ME(TELOPT_NAWS))
5103                     rlog_naws();
5104 #endif /* RLOGCODE */
5105 #ifdef SSHBUILTIN
5106                   if (TELOPT_ME(TELOPT_NAWS))
5107                     ssh_snaws();
5108 #endif /* SSHBUILTIN */
5109               }
5110           }
5111           return(1);
5112       }
5113 #endif /* OS2 */
5114
5115 #ifdef NT
5116       case XYTATTBUG:
5117         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5118         if ((x = cmcfm()) < 0) return(x);
5119         tt_attr_bug = y;
5120         return(1);
5121 #endif /* NT */
5122
5123 #ifdef OS2
5124       case XYTSGRC:
5125         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5126         if ((x = cmcfm()) < 0) return(x);
5127         sgrcolors = y;
5128         return(1);
5129
5130       case XYTSEND:
5131           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5132           if ((x = cmcfm()) < 0) return(x);
5133           tt_senddata = y;
5134           return(1);
5135
5136       case XYTSEOB:
5137           if ((y = cmkey(ttyseobtab,2,"","us_cr",xxstring)) < 0) return(y);
5138           if ((x = cmcfm()) < 0) return(x);
5139           wy_blockend = y;
5140           return(1);
5141
5142       case XYTURLHI: {
5143           int done = 0, attr = VT_CHAR_ATTR_NORMAL;
5144
5145           if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
5146             return(x);
5147           if (x) {
5148               z = 0;
5149               while (!done) {
5150                   if ((y = cmkey(ttyprotab,nprotect,"",
5151                                  z?"done":"reverse",xxstring)) < 0)
5152                     return(y);
5153                   switch (y) {
5154                     case TTATTDONE:
5155                       done = TRUE;
5156                       break;
5157                     case TTATTBLI:
5158                       attr |= VT_CHAR_ATTR_BLINK;
5159                       break;
5160                     case TTATTREV:
5161                       attr |= VT_CHAR_ATTR_REVERSE;
5162                       break;
5163                     case TTATTITA:
5164                       attr |= VT_CHAR_ATTR_ITALIC;
5165                       break;
5166                     case TTATTUND:
5167                       attr |= VT_CHAR_ATTR_UNDERLINE;
5168                       break;
5169                     case TTATTBLD:
5170                       attr |= VT_CHAR_ATTR_BOLD;
5171                       break;
5172                     case TTATTDIM:
5173                       attr |= VT_CHAR_ATTR_DIM;
5174                       break;
5175                     case TTATTINV:
5176                       attr |= VT_CHAR_ATTR_INVISIBLE;
5177                       break;
5178                     case TTATTNOR:
5179                       break;
5180                   }
5181                   z = 1;                /* One attribute has been chosen */
5182               }
5183           }
5184           if ((z = cmcfm()) < 0) return(z);
5185           seturlhl(x);
5186           if (x)
5187             tt_url_hilite_attr = attr;
5188           return(1);
5189       }
5190       case XYTATTR:
5191         if ((x = cmkey(ttyattrtab,nattrib,"","underline",xxstring)) < 0)
5192           return(x);
5193         switch (x) {
5194           case TTATTBLI:
5195             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5196             if ((x = cmcfm()) < 0) return(x);
5197             trueblink = y;
5198 #ifndef KUI
5199             if ( !trueblink && trueunderline ) {
5200                 trueunderline = 0;
5201                 printf("Warning: Underline being simulated by color.\n");
5202             }
5203
5204 #endif /* KUI */
5205             break;
5206
5207           case TTATTDIM:
5208             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5209             if ((x = cmcfm()) < 0) return(x);
5210             truedim = y;
5211             break;
5212
5213           case TTATTREV:
5214             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5215             if ((x = cmcfm()) < 0) return(x);
5216             truereverse = y;
5217             break;
5218
5219           case TTATTUND:
5220             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5221             if ((x = cmcfm()) < 0) return(x);
5222             trueunderline = y;
5223 #ifndef KUI
5224             if (!trueblink && trueunderline) {
5225                 trueblink = 1;
5226                 printf("Warning: True blink mode is active.\n");
5227             }
5228 #endif /* KUI */
5229             break;
5230
5231           case TTATTITA:
5232               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5233               if ((x = cmcfm()) < 0) return(x);
5234               trueitalic = y;
5235             break;
5236
5237           case TTATTPRO: {      /* Set default Protected Character attribute */
5238               extern vtattrib WPattrib;    /* current WP Mode Attrib */
5239               extern vtattrib defWPattrib; /* default WP Mode Attrib */
5240               vtattrib wpa = {0,0,0,0,0,1,0,0,0,0,0};   /* Protected */
5241               int done = 0;
5242
5243               x = 0;
5244               while (!done) {
5245                   if ((y = cmkey(ttyprotab,nprotect,"",
5246                                  x?"done":"dim",xxstring)) < 0)
5247                     return(y);
5248                   switch (y) {
5249                     case TTATTNOR:
5250                       break;
5251                     case TTATTBLI:      /* Blinking doesn't work */
5252                       wpa.blinking = TRUE;
5253                       break;
5254                     case TTATTREV:
5255                       wpa.reversed = TRUE;
5256                       break;
5257                     case TTATTITA:
5258                       wpa.italic = TRUE;
5259                       break;
5260                     case TTATTUND:
5261                       wpa.underlined = TRUE;
5262                       break;
5263                     case TTATTBLD:
5264                       wpa.bold = TRUE;
5265                       break;
5266                     case TTATTDIM:
5267                       wpa.dim = TRUE;
5268                       break;
5269                     case TTATTINV:
5270                       wpa.invisible = TRUE ;
5271                       break;
5272                     case TTATTDONE:
5273                       done = TRUE;
5274                       break;
5275                   }
5276                   x = 1;                /* One attribute has been chosen */
5277               }
5278               if ((x = cmcfm()) < 0) return(x);
5279               WPattrib = defWPattrib = wpa;
5280               break;
5281           }
5282         }
5283         return(1);
5284
5285       case XYTKEY: {                    /* SET TERMINAL KEY */
5286           int t, x, y;
5287           int clear = 0, deflt = 0;
5288           int confirmed = 0;
5289           int flag = 0;
5290           int kc = -1;                  /* Key code */
5291           int litstr = 0;               /* Literal String? */
5292           char *s = NULL;               /* Key binding */
5293 #ifndef NOKVERBS
5294           char *p = NULL;               /* Worker */
5295 #endif /* NOKVERBS */
5296           con_event defevt;
5297           extern int os2gks;
5298           extern int mskkeys;
5299           extern int initvik;
5300           struct FDB kw,sw,nu,cm;
5301
5302           defevt.type = error;
5303
5304           if ((t = cmkey(ttkeytab,nttkey,"","",xxstring)) < 0)
5305             return(t);
5306           cmfdbi(&nu,                   /* First FDB - command switches */
5307                  _CMNUM,                /* fcode */
5308                  "/literal, keycode, or action",
5309                  "",                    /* default */
5310                  "",                    /* addtl string data */
5311                  10,                    /* addtl numeric data 1: radix */
5312                  0,                     /* addtl numeric data 2: 0 */
5313                  xxstring,              /* Processing function */
5314                  NULL,                  /* Keyword table */
5315                  &sw                    /* Pointer to next FDB */
5316                  );                     /*  */
5317           cmfdbi(&sw,                   /* Second FDB - switches */
5318                  _CMKEY,                /* fcode */
5319                  "",
5320                  "",                    /* default */
5321                  "",                    /* addtl string data */
5322                  nstrmswitab,           /* addtl numeric data 1: tbl size */
5323                  4,                     /* addtl numeric data 2: 4 = cmswi */
5324                  xxstring,              /* Processing function */
5325                  strmswitab,            /* Keyword table */
5326                  &kw                    /* Pointer to next FDB */
5327                  );
5328           cmfdbi(&kw,                   /* Third FDB - command switches */
5329                  _CMKEY,                /* fcode */
5330                  "/literal, keycode, or action",
5331                  "",                    /* default */
5332                  "",                    /* addtl string data */
5333                  nstrmkeytab,           /* addtl numeric data 1: tbl size */
5334                  0,                     /* addtl numeric data 2 */
5335                  xxstring,              /* Processing function */
5336                  strmkeytab,            /* Keyword table */
5337                  &cm                    /* Pointer to next FDB */
5338                  );
5339           cmfdbi(&cm,                   /* Final FDB - Confirmation */
5340                  _CMCFM,                /* fcode */
5341                  "",
5342                  "",                    /* default */
5343                  "",                    /* addtl string data */
5344                  0,                     /* addtl numeric data 1: tbl size */
5345                  0,                     /* addtl numeric data 2: 4 = cmswi */
5346                  xxstring,              /* Processing function */
5347                  NULL,                  /* Keyword table */
5348                  NULL                   /* Pointer to next FDB */
5349                  );
5350           while (kc < 0) {
5351               x = cmfdb(&nu);           /* Parse something */
5352               if (x < 0)
5353                 return(x);
5354
5355               switch (cmresult.fcode) {
5356                 case _CMCFM:
5357                   printf(" Press key to be defined: ");
5358                   conbin((char)escape); /* Put terminal in binary mode */
5359                   os2gks = 0;           /* Turn off Kverb preprocessing */
5360                   kc = congks(0);       /* Get character or scan code */
5361                   os2gks = 1;           /* Turn on Kverb preprocessing */
5362                   concb((char)escape);  /* Restore terminal to cbreak mode */
5363                   if (kc < 0) {         /* Check for error */
5364                       printf("?Error reading key\n");
5365                       return(0);
5366                   }
5367                   shokeycode(kc,t);     /* Show current definition */
5368                   flag = 1;             /* Remember it's a multiline command */
5369                   break;
5370                 case _CMNUM:
5371                   kc = cmresult.nresult;
5372                   break;
5373                 case _CMKEY:
5374                   if (cmresult.fdbaddr == &sw) { /* Switch */
5375                       if (cmresult.nresult == 0)
5376                         litstr = 1;
5377                   } else if (cmresult.fdbaddr == &kw) { /* Keyword */
5378                       if (cmresult.nresult == 0)
5379                         clear = 1;
5380                       else
5381                         deflt = 1;
5382                       if ((x = cmcfm()) < 0)
5383                         return(x);
5384                       if (clear)
5385                         clearkeymap(t);
5386                       else if (deflt)
5387                         defaultkeymap(t);
5388                       initvik = 1;
5389                       return(1);
5390                   }
5391               }
5392           }
5393
5394     /* Normal SET TERMINAL KEY <terminal> <scancode> <value> command... */
5395
5396           if (mskkeys)
5397             kc = msktock(kc);
5398
5399           if (kc < 0 || kc >= KMSIZE) {
5400               printf("?key code must be between 0 and %d\n", KMSIZE - 1);
5401               return(-9);
5402           }
5403           if (kc == escape) {
5404               printf("Sorry, %d is the CONNECT-mode escape character\n",kc);
5405               return(-9);
5406           }
5407           wideresult = -1;
5408           if (flag) {
5409               cmsavp(psave,PROMPTL);
5410               cmsetp(" Enter new definition: ");
5411               cmini(ckxech);
5412           }
5413         def_again:
5414           if (flag) prompt(NULL);
5415           if ((y = cmtxt("key definition,\n\
5416  or Ctrl-C to cancel this command,\n\
5417  or Enter to restore default definition",
5418                          "",&s,NULL)) < 0) {
5419               if (flag)                 /* Handle parse errors */
5420                 goto def_again;
5421               else
5422                 return(y);
5423           }
5424           s = brstrip(s);
5425 #ifndef NOKVERBS
5426           p = s;                        /* Save this place */
5427 #endif /* NOKVERBS */
5428 /*
5429   If the definition included any \Kverbs, quote the backslash so the \Kverb
5430   will still be in the definition when the key is pressed.  We don't do this
5431   in zzstring(), because \Kverbs are valid only in this context and nowhere
5432   else.
5433
5434   We use this code active for all versions that support SET KEY, even if they
5435   don't support \Kverbs, because otherwise \K would behave differently for
5436   different versions.
5437 */
5438           for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
5439               if ((x > 0) &&
5440                   (s[x] == 'K' || s[x] == 'k')
5441                   ) {                   /* Have K */
5442
5443                   if ((x == 1 && s[x-1] == CMDQ) ||
5444                       (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
5445                       line[y++] = CMDQ; /* Make it \\K */
5446                   }
5447                   if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
5448                       line[y-1] = CMDQ; /* Have \{K */
5449                       line[y++] = '{';  /* Make it \\{K */
5450                   }
5451               }
5452               line[y] = s[x];
5453           }
5454           line[y++] = NUL;              /* Terminate */
5455           s = line + y + 1;             /* Point to after it */
5456           x = LINBUFSIZ - (int) strlen(line) - 1; /* Get remaining space */
5457           if ((x < (LINBUFSIZ / 2)) ||
5458               (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
5459               printf("?Key definition too long\n");
5460               if (flag) cmsetp(psave);
5461               return(-9);
5462           }
5463           s = line + y + 1;             /* Point to result. */
5464
5465 #ifndef NOKVERBS
5466 /*
5467   Special case: see if the definition starts with a \Kverb.
5468   If it does, point to it with p, otherwise set p to NULL.
5469 */
5470           p = s;
5471           if (*p++ == CMDQ) {
5472               if (*p == '{') p++;
5473               p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
5474           }
5475 #endif /* NOKVERBS */
5476
5477           switch (strlen(s)) {          /* Action depends on length */
5478             case 0:                     /* Clear individual key def */
5479               deletekeymap(t,kc);
5480               break;
5481             case 1:
5482               if (!litstr) {
5483                   defevt.type = key;    /* Single character */
5484                   defevt.key.scancode = *s;
5485                   break;
5486               }
5487             default:                    /* Character string */
5488 #ifndef NOKVERBS
5489               if (p) {
5490                   y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
5491                   /* Need exact match */
5492                   debug(F101,"set key kverb lookup",0,y);
5493                   if (y > -1) {
5494                       defevt.type = kverb;
5495                       defevt.kverb.id = y;
5496                       break;
5497                   }
5498               }
5499 #endif /* NOKVERBS */
5500               if (litstr) {
5501                   defevt.type = literal;
5502                   defevt.literal.string = (char *) malloc(strlen(s)+1);
5503                   if (defevt.literal.string)
5504                     strcpy(defevt.literal.string, s); /* safe */
5505               } else {
5506                   defevt.type = macro;
5507                   defevt.macro.string = (char *) malloc(strlen(s)+1);
5508                   if (defevt.macro.string)
5509                     strcpy(defevt.macro.string, s); /* safe */
5510               }
5511               break;
5512           }
5513           insertkeymap(t, kc, defevt);
5514           if (flag)
5515             cmsetp(psave);
5516           initvik = 1;                  /* Update VIK table */
5517           return(1);
5518       }
5519
5520 #ifdef PCTERM
5521       case XYTPCTERM:                   /* PCTERM Keyboard Mode */
5522         if ((x = seton(&tt_pcterm)) < 0) return(x);
5523         return(success = 1);
5524 #endif /* PCTERM */
5525 #endif /* OS2 */
5526
5527 #ifdef CK_TRIGGER
5528       case XYTRIGGER:
5529         if ((y = cmtxt("String to trigger automatic return to command mode",
5530                        "",&s,xxstring)) < 0)
5531           return(y);
5532         makelist(s,tt_trigger,TRIGGERS);
5533         return(1);
5534 #endif /* CK_TRIGGER */
5535
5536 #ifdef OS2
5537       case XYTSAC:
5538         if ((y = cmnum("ASCII value to use for spacing attributes",
5539                        "32",10,&x,xxstring)) < 0)
5540           return(y);
5541         if ((y = cmcfm()) < 0) return(y);
5542         tt_sac = x;
5543         return(success = 1);
5544
5545       case XYTKBDGL: {      /* SET TERM KBD-FOLLOWS-GL/GR */
5546           extern int tt_kb_glgr;        /* from ckoco3.c */
5547           if ((x = seton(&tt_kb_glgr)) < 0)
5548               return(x);
5549           return(success = 1);
5550       }
5551 #ifndef NOCSETS
5552       case XYTVTLNG:        /* SET TERM DEC-LANGUAGE */
5553         if ((y = cmkey(vtlangtab,nvtlangtab,"VT language",
5554                        IS97801(tt_type_mode)?"german":"north-american",
5555                        xxstring)) < 0)
5556           return(y);
5557         if ((x = cmcfm()) < 0) return(x);
5558
5559         /* A real VT terminal would use the language to set the   */
5560         /* default keyboard language for both 8-bit multinational */
5561         /* and 7-bit national modes.  For 8-bit mode it would     */
5562         /* set the terminal character-set to the ISO set if it    */
5563         /* is not already set.                                    */
5564         /* Latin-1 can be replaced by DEC Multinational           */
5565         switch (y) {
5566           case VTL_NORTH_AM:  /* North American */
5567             /* Multinational: Latin-1   */
5568             /* National:      US_ASCII  */
5569             dec_lang = y;
5570             dec_nrc = TX_ASCII;
5571             dec_kbd = TX_8859_1;
5572             break;
5573           case VTL_BRITISH :
5574             /* Multinational: Latin-1   */
5575             /* National:      UK_ASCII  */
5576             dec_lang = y;
5577             dec_nrc = TX_BRITISH;
5578             dec_kbd = TX_8859_1;
5579             break;
5580           case VTL_FRENCH  :
5581           case VTL_BELGIAN :
5582           case VTL_CANADIAN:
5583             /* Multinational: Latin-1   */
5584             /* National:      FR_ASCII  */
5585             dec_lang = y;
5586             dec_nrc = TX_FRENCH;
5587             dec_kbd = TX_8859_1;
5588             break;
5589           case VTL_FR_CAN  :
5590             /* Multinational: Latin-1   */
5591             /* National:      FC_ASCII  */
5592             dec_lang = y;
5593             dec_nrc = TX_CN_FRENCH;
5594             dec_kbd = TX_8859_1;
5595             break;
5596           case VTL_DANISH  :
5597           case VTL_NORWEGIA:
5598             /* Multinational: Latin-1   */
5599             /* National:      NO_ASCII  */
5600             dec_lang = y;
5601             dec_nrc = TX_NORWEGIAN;
5602             dec_kbd = TX_8859_1;
5603             break;
5604           case VTL_FINNISH :
5605             /* Multinational: Latin-1   */
5606             /* National:      FI_ASCII  */
5607             dec_lang = y;
5608             dec_nrc = TX_FINNISH;
5609             dec_kbd = TX_8859_1;
5610             break;
5611           case VTL_GERMAN  :
5612             /* Multinational: Latin-1   */
5613             /* National:      GR_ASCII  */
5614             dec_lang = y;
5615             dec_nrc = TX_GERMAN;
5616             dec_kbd = TX_8859_1;
5617             break;
5618           case VTL_DUTCH   :
5619             /* Multinational: Latin-1   */
5620             /* National:      DU_ASCII  */
5621             dec_lang = y;
5622             dec_nrc = TX_DUTCH;
5623             dec_kbd = TX_8859_1;
5624             break;
5625           case VTL_ITALIAN :
5626             /* Multinational: Latin-1   */
5627             /* National:      IT_ASCII  */
5628             dec_lang = y;
5629             dec_nrc = TX_ITALIAN;
5630             dec_kbd = TX_8859_1;
5631             break;
5632           case VTL_SW_FR   :
5633           case VTL_SW_GR   :
5634             /* Multinational: Latin-1   */
5635             /* National:      CH_ASCII  */
5636             dec_lang = y;
5637             dec_nrc = TX_SWISS;
5638             dec_kbd = TX_8859_1;
5639             break;
5640           case VTL_SWEDISH :
5641             /* Multinational: Latin-1   */
5642             /* National:      SW_ASCII  */
5643             dec_lang = y;
5644             dec_nrc = TX_SWEDISH;
5645             dec_kbd = TX_8859_1;
5646             break;
5647           case VTL_SPANISH :
5648             /* Multinational: Latin-1   */
5649             /* National:      SP_ASCII  */
5650             dec_lang = y;
5651             dec_nrc = TX_SPANISH;
5652             dec_kbd = TX_8859_1;
5653             break;
5654           case VTL_PORTUGES:
5655             /* Multinational: Latin-1   */
5656             /* National:      Portugese ASCII  */
5657             dec_lang = y;
5658             dec_nrc = TX_PORTUGUESE;
5659             dec_kbd = TX_8859_1;
5660             break;
5661           case VTL_HEBREW  :
5662             /* Multinational: Latin-Hebrew / DEC-Hebrew  */
5663             /* National:      DEC 7-bit Hebrew  */
5664             dec_lang = y;
5665             dec_nrc = TX_HE7;
5666             dec_kbd = TX_8859_8;
5667             break;
5668           case VTL_GREEK   :
5669             /* Multinational: Latin-Greek / DEC-Greek   */
5670             /* National:      DEC Greek NRC             */
5671             /* is ELOT927 equivalent to DEC Greek????   */
5672             dec_lang = y;
5673             dec_nrc = TX_ELOT927;
5674             dec_kbd = TX_8859_7;
5675             break;
5676 #ifdef COMMENT
5677           case VTL_TURK_Q  :
5678           case VTL_TURK_F  :
5679             /* Multinational: Latin-Turkish / DEC-Turkish   */
5680             /* National:      DEC 7-bit Turkish             */
5681             break;
5682 #endif /* COMMENT */
5683           case VTL_HUNGARIA:
5684             /* Multinational: Latin-2   */
5685             /* National:      no national mode  */
5686             dec_lang = y;
5687             dec_nrc = TX_HUNGARIAN;
5688             dec_kbd = TX_8859_2;
5689             break;
5690           case VTL_SLOVAK  :
5691           case VTL_CZECH   :
5692           case VTL_POLISH  :
5693           case VTL_ROMANIAN:
5694             /* Multinational: Latin-2   */
5695             /* National:      no national mode  */
5696             dec_lang = y;
5697             dec_nrc = TX_ASCII;
5698             dec_kbd = TX_8859_2;
5699             break;
5700           case VTL_RUSSIAN :
5701             /* Multinational: Latin-Cyrillic / KOI-8   */
5702             /* National:      DEC Russian NRC  */
5703             dec_lang = y;
5704             dec_nrc = TX_KOI7;
5705             dec_kbd = TX_8859_5;
5706             break;
5707           case VTL_LATIN_AM:
5708             /* Multinational: not listed in table   */
5709             /* National:      not listed in table  */
5710             dec_lang = y;
5711             dec_nrc = TX_ASCII;
5712             dec_kbd = TX_8859_1;
5713             break;
5714 #ifdef COMMENT
5715           case VTL_SCS     :
5716             /* Multinational: Latin-2   */
5717             /* National:      SCS NRC   */
5718             break;
5719 #endif /* COMMENT */
5720           default:
5721             return(success = 0);
5722         }
5723         if (IS97801(tt_type_mode)) {
5724             SNI_bitmode(cmask == 0377 ? 8 : 7);
5725         }
5726         return(success = 1);
5727 #endif /* NOCSETS */
5728
5729       case XYTVTNRC: {                  /* SET TERM DEC-NRC-MODE */
5730           extern int decnrcm_usr, decnrcm;        /* from ckoco3.c */
5731           if ((x = seton(&decnrcm_usr)) < 0)
5732             return(x);
5733           decnrcm = decnrcm_usr;
5734           return(success = 1);
5735       }
5736       case XYTSNIPM: {                  /* SET TERM SNI-PAGEMODE */
5737           extern int sni_pagemode, sni_pagemode_usr;
5738           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5739           if ((x = cmcfm()) < 0) return(x);
5740           sni_pagemode_usr = sni_pagemode = y;
5741           return(success = 1);
5742       }
5743       case XYTSNISM: {                  /* SET TERM SNI-SCROLLMODE */
5744           extern int sni_scroll_mode, sni_scroll_mode_usr;
5745           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5746           if ((x = cmcfm()) < 0) return(x);
5747           sni_scroll_mode_usr = sni_scroll_mode = y;
5748           return(success = 1);
5749       }
5750       case XYTSNICC: {  /* SET TERM SNI-CH.CODE */
5751           extern int sni_chcode_usr;
5752           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5753           if ((x = cmcfm()) < 0) return(x);
5754           sni_chcode_usr = y;
5755           SNI_chcode(y);
5756           return(success = 1);
5757       }
5758       case XYTSNIFV: {  /* SET TERM SNI-FIRMWARE-VERSIONS */
5759           extern CHAR sni_kbd_firmware[], sni_term_firmware[];
5760           CHAR kbd[7],term[7];
5761
5762           if ((x = cmfld("Keyboard Firmware Version",sni_kbd_firmware,
5763                          &s, xxstring)) < 0)
5764             return(x);
5765           if ((int)strlen(s) != 6) {
5766               printf("?Sorry - the firmware version must be 6 digits long\n");
5767               return(-9);
5768           }
5769           for (i = 0; i < 6; i++) {
5770               if (!isdigit(s[i])) {
5771    printf("?Sorry - the firmware version can only contain digits [0-9]\n");
5772                   return(-9);
5773               }
5774           }
5775           ckstrncpy(kbd,s,7);
5776
5777           if ((x = cmfld("Terminal Firmware Version",sni_term_firmware,
5778                          &s, xxstring)) < 0)
5779             return(x);
5780           if ((int)strlen(s) != 6) {
5781               printf("?Sorry - the firmware version must be 6 digits long\n");
5782               return(-9);
5783           }
5784           for (i = 0; i < 6; i++) {
5785               if (!isdigit(s[i])) {
5786    printf("?Sorry - the firmware version can only contain digits [0-9]\n");
5787                    return(-9);
5788               }
5789           }
5790           ckstrncpy(term,s,7);
5791           if ((x = cmcfm()) < 0) return(x);
5792
5793           ckstrncpy(sni_kbd_firmware,kbd,7);
5794           ckstrncpy(sni_term_firmware,term,7);
5795           return(success = 1);
5796     }
5797
5798     case XYTLSP: {              /* SET TERM LINE-SPACING */
5799         if ((x = cmfld("Line Spacing","1",&s, xxstring)) < 0)
5800           return(x);
5801         if (isfloat(s,0) < 1) {         /* (sets floatval) */
5802             printf("?Integer or floating-point number required\n");
5803             return(-9);
5804         }
5805         if (floatval < 1.0 || floatval > 3.0) {
5806             printf("?Value must within the range 1.0 and 3.0 (inclusive)\n");
5807             return(-9);
5808         }
5809         if ((x = cmcfm()) < 0) return(x);
5810 #ifdef KUI
5811         tt_linespacing[VCMD] = tt_linespacing[VTERM] = floatval;
5812         return(success = 1);
5813 #else /* KUI */
5814         printf("?Sorry, Line-spacing is only supported in K95G.EXE.\n");
5815         return(success = 0);
5816 #endif /* KUI */
5817     }
5818 #endif /* OS2 */
5819
5820       default:                          /* Shouldn't get here. */
5821         return(-2);
5822     }
5823 #endif /* MAC */
5824 #ifdef COMMENT
5825     /*
5826       This was supposed to shut up picky compilers but instead it makes
5827       most compilers complain about "statement not reached".
5828     */
5829     return(-2);
5830 #endif /* COMMENT */
5831 #ifdef OS2
5832 return(-2);
5833 #endif /* OS2 */
5834 }
5835
5836 #ifdef OS2
5837 int
5838 settitle(void) {
5839     extern char usertitle[];
5840     if ((y = cmtxt("title text","",&s,xxstring)) < 0)
5841       return(y);
5842 #ifdef IKSD
5843     if (inserver) {
5844         printf("?Sorry, command disabled.\r\n");
5845         return(success = 0);
5846     }
5847 #endif /* IKSD */
5848     s = brstrip(s);
5849     ckstrncpy(usertitle,s,64);
5850     os2settitle("",1);
5851     return(1);
5852 }
5853
5854 static struct keytab dialertab[] = {    /* K95 Dialer types */
5855     "backspace",        0, 0,
5856     "enter",            1, 0
5857 };
5858 static int ndialer = 2;
5859
5860 int
5861 setdialer(void) {
5862     int t, x, y;
5863     int clear = 0, deflt = 0;
5864     int kc;                             /* Key code */
5865     char *s = NULL;                     /* Key binding */
5866 #ifndef NOKVERBS
5867     char *p = NULL;                     /* Worker */
5868 #endif /* NOKVERBS */
5869     con_event defevt;
5870     extern int os2gks;
5871     extern int mskkeys;
5872     extern int initvik;
5873
5874     defevt.type = error;
5875
5876     if (( x = cmkey(dialertab, ndialer,
5877                     "Kermit-95 dialer work-arounds",
5878                     "", xxstring)) < 0 )
5879       return(x);
5880     switch (x) {
5881       case 0:                           /* Backspace */
5882         kc = 264;
5883         break;
5884       case 1:                           /* Enter */
5885         kc = 269;
5886         break;
5887       default:
5888         printf("Illegal value in setdialer()\n");
5889         return(-9);
5890     }
5891     if ((y = cmtxt("Key definition","",&s,xxstring)) < 0)
5892       return(y);
5893
5894 #ifdef IKSD
5895     if (inserver) {
5896         printf("?Sorry, command disabled.\r\n");
5897         return(success = 0);
5898     }
5899 #endif /* IKSD */
5900     s = brstrip(s);
5901 #ifndef NOKVERBS
5902     p = s;                              /* Save this place */
5903 #endif /* NOKVERBS */
5904 /*
5905   If the definition included any \Kverbs, quote the backslash so the \Kverb
5906   will still be in the definition when the key is pressed.  We don't do this
5907   in zzstring(), because \Kverbs are valid only in this context and nowhere
5908   else.
5909
5910   We use this code active for all versions that support SET KEY, even if they
5911   don't support \Kverbs, because otherwise \K would behave differently for
5912   different versions.
5913 */
5914     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
5915         if ((x > 0) &&
5916             (s[x] == 'K' || s[x] == 'k')
5917             ) {                         /* Have K */
5918
5919             if ((x == 1 && s[x-1] == CMDQ) ||
5920                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
5921                 line[y++] = CMDQ;       /* Make it \\K */
5922             }
5923             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
5924                 line[y-1] = CMDQ;       /* Have \{K */
5925                 line[y++] = '{';        /* Make it \\{K */
5926             }
5927         }
5928         line[y] = s[x];
5929     }
5930     line[y++] = NUL;                    /* Terminate */
5931     s = line + y + 1;                   /* Point to after it */
5932     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
5933     if ((x < (LINBUFSIZ / 2)) ||
5934         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
5935         printf("?Key definition too long\n");
5936         return(-9);
5937     }
5938     s = line + y + 1;                   /* Point to result. */
5939
5940 #ifndef NOKVERBS
5941 /*
5942   Special case: see if the definition starts with a \Kverb.
5943   If it does, point to it with p, otherwise set p to NULL.
5944 */
5945     p = s;
5946     if (*p++ == CMDQ) {
5947         if (*p == '{') p++;
5948         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
5949     }
5950 #endif /* NOKVERBS */
5951
5952     /* Clear the definition for SET KEY */
5953     if (macrotab[kc]) {                 /* Possibly free old macro from key. */
5954         free((char *)macrotab[kc]);
5955         macrotab[kc] = NULL;
5956     }
5957     keymap[kc] = (KEY) kc;
5958
5959     /* Now reprogram the default value for all terminal types */
5960     /* remember to treat Wyse and Televideo terminals special */
5961     /* because of their use of Kverbs for Backspace and Enter */
5962     for (t = 0; t <= TT_MAX; t++) {
5963         if ( ISDG200(t) && kc == 264) {
5964             extern char * udkfkeys[] ;
5965             if (kc == 264) {            /* \Kdgbs */
5966                 if (udkfkeys[83])
5967                   free(udkfkeys[83]);
5968                 udkfkeys[83] = strdup(s);
5969             }
5970         } else if (ISWYSE(t) || ISTVI(t)) {
5971             extern char * udkfkeys[] ;
5972             if (kc == 264) {            /* \Kwybs or \Ktvibs */
5973                 if (udkfkeys[32])
5974                   free(udkfkeys[32]);
5975                 udkfkeys[32] = strdup(s);
5976             }
5977             if (kc == 269) {            /* \Kwyenter and \Kwyreturn */
5978                 if (udkfkeys[39])       /* \Ktvienter and \Ktvireturn */
5979                   free(udkfkeys[39]);
5980                 udkfkeys[39] = strdup(s);
5981                 if (udkfkeys[49])
5982                   free(udkfkeys[49]);
5983                 udkfkeys[49] = strdup(s);
5984             }
5985         } else {
5986             switch (strlen(s)) {        /* Action depends on length */
5987               case 0:                   /* Clear individual key def */
5988                 deletekeymap(t,kc);
5989                 break;
5990               case 1:
5991                 defevt.type = key;      /* Single character */
5992                 defevt.key.scancode = *s;
5993                 break;
5994               default:                  /* Character string */
5995 #ifndef NOKVERBS
5996                 if (p) {
5997                     y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
5998                     /* Exact match req'd */
5999                     debug(F101,"set key kverb lookup",0,y);
6000                     if (y > -1) {
6001                         defevt.type = kverb;
6002                         defevt.kverb.id = y;
6003                         break;
6004                     }
6005                 }
6006 #endif /* NOKVERBS */
6007                 defevt.type = macro;
6008                 defevt.macro.string = (char *) malloc(strlen(s)+1);
6009                 if (defevt.macro.string)
6010                   strcpy(defevt.macro.string, s); /* safe */
6011                 break;
6012             }
6013             insertkeymap( t, kc, defevt ) ;
6014             initvik = 1;                /* Update VIK table */
6015         }
6016     }
6017     return(1);
6018 }
6019 #endif /* OS2 */
6020
6021 #ifdef NT
6022 int
6023 setwin95( void ) {
6024     int x, y, z;
6025
6026     if (( y = cmkey(win95tab, nwin95,
6027                     "Windows 95 specific work-arounds",
6028                     "keyboard-translation",
6029                     xxstring)) < 0 )
6030         return (y);
6031     switch (y) {
6032       case XYWPOPUP:
6033         if ((y = cmkey(onoff,2,"popups are used to prompt the user for data",
6034                        "on",xxstring)) < 0)
6035           return(y);
6036         if ((x = cmcfm()) < 0) return(x);
6037         win95_popup = y;
6038         return(1);
6039
6040       case XYW8_3:
6041         if ((y = cmkey(onoff,2,"8.3 FAT file names","off",xxstring)) < 0)
6042           return(y);
6043         if ((x = cmcfm()) < 0) return(x);
6044         win95_8_3 = y;
6045         return(1);
6046
6047       case XYWSELECT:
6048         if ((y = cmkey(onoff,2,"\"select()\" fails on write","off",
6049              xxstring)) < 0)
6050           return(y);
6051         if ((x = cmcfm()) < 0) return(x);
6052         win95selectbug = y;
6053         return(1);
6054
6055       case XYWAGR:
6056         if ((y = cmkey(onoff,2,"Right-Alt is Alt-Gr","off",xxstring)) < 0)
6057           return(y);
6058         if ((x = cmcfm()) < 0) return(x);
6059         win95altgr = y;
6060         return(1);
6061
6062       case XYWOIO:
6063         if ((y = cmkey(onoff,2,"Use Overlapped I/O","on",xxstring)) < 0)
6064           return(y);
6065         if (y) {
6066             if ((x = cmnum("Maximum number of outstanding I/O requests",
6067                            "10",10,&z,xxstring)) < 0)
6068               return(x);
6069             if (z < 1 || z > 7) {
6070                 printf(
6071 "?Maximum outstanding I/O requests must be between 1 and 7.\n");
6072                 return(-9);
6073             }
6074         } else
6075           z = 1;
6076         if ((x = cmcfm()) < 0) return(x);
6077         owwait = !y;
6078         maxow = maxow_usr = z;
6079         return(1);
6080
6081       case XYWKEY:
6082 #ifndef COMMENT
6083         printf("\n?\"Keyboard-Translation\" is no longer required.\n");
6084         return(-9);
6085 #else /* COMMENT */
6086         if (( z = cmkey(tcstab, ntcs,
6087                         "Keyboard Character Set",
6088                         "latin1-iso",
6089                         xxstring)) < 0)
6090           return (z);
6091         if ((x = cmcfm()) < 0)
6092           return(x);
6093
6094         win95kcsi = z;
6095         win95kl2 = (win95kcsi == TC_2LATIN);
6096
6097         if (win95kcsi == TC_TRANSP) {
6098             win95kcs = NULL;
6099         } else {
6100 #ifdef UNICODE
6101             win95kcs = xlr[win95kcsi][tx2fc(tcsl)];
6102 #else /* UNICODE */
6103             win95kcs = xlr[win95kcsi][tcsl];
6104 #endif /* UNICODE */
6105         }
6106         return(1);
6107 #endif /* COMMENT */
6108
6109       case XYWLUC:
6110         if ((y = cmkey(onoff,2,"Unicode-to-Lucida-Console substitutions",
6111                        "on",xxstring)) < 0)
6112           return(y);
6113         if ((x = cmcfm()) < 0) return(x);
6114         win95lucida = y;
6115         return(1);
6116
6117       case XYWHSL:
6118         if ((y = cmkey(onoff,2,"Horizontal Scan Line substitutions",
6119                        "on",xxstring)) < 0)
6120           return(y);
6121         if ((x = cmcfm()) < 0) return(x);
6122         win95hsl = y;
6123         return(1);
6124
6125       default:
6126         printf("Illegal value in setwin95()\n");
6127         return(-9);
6128     }
6129 }
6130 #endif /* NT */
6131
6132 #ifdef OS2
6133 int
6134 setprty (
6135 #ifdef CK_ANSIC
6136     void
6137 #endif /* CK_ANSIC */
6138 /* setprty */ ) {
6139     int x, y, z;
6140
6141     if (( y = cmkey(prtytab, nprty,
6142                     "priority level of terminal and communication threads",
6143                     "foreground-server",
6144                     xxstring)) < 0 )
6145       return (y);
6146
6147     if ((x = cmcfm()) < 0)
6148       return (x);
6149 #ifdef IKSD
6150     if (inserver &&
6151 #ifdef IKSDCONF
6152          iksdcf
6153 #else
6154          1
6155 #endif /* IKSDCONF */
6156     ) {
6157         if ((y = cmcfm()) < 0) return(y);
6158         printf("?Sorry, command disabled.\r\n");
6159         return(success = 0);
6160     }
6161 #endif /* IKSD */
6162     priority = y;
6163     return(TRUE);
6164 }
6165 #endif /* OS2 */
6166
6167 int
6168 setbell() {
6169     int y, x;
6170 #ifdef OS2
6171     int z;
6172 #endif /* OS2 */
6173
6174     if ((y = cmkey(beltab,nbeltab,
6175 #ifdef OS2
6176         "how console and terminal bells should\nbe generated", "audible",
6177 #else
6178         "Whether Kermit should ring the terminal bell (beep)", "on",
6179 #endif /* OS2 */
6180                    xxstring)) < 0)
6181           return(y);
6182
6183 #ifdef IKSD
6184     if (inserver) {
6185         if ((y = cmcfm()) < 0) return(y);
6186         printf("?Sorry, command disabled.\r\n");
6187         return(success = 0);
6188     }
6189 #endif /* IKSD */
6190
6191     switch (y) {                        /* SET BELL */
6192       case XYB_NONE:
6193 #ifdef OS2
6194       case XYB_VIS:
6195 #endif /* OS2 */
6196         if ((x = cmcfm()) < 0)
6197           return(x);
6198 #ifdef OS2
6199         tt_bell = y;
6200 #else
6201         tt_bell = 0;
6202 #endif /* OS2 */
6203         break;
6204
6205       case XYB_AUD:
6206 #ifdef OS2
6207         if ((x = cmkey(audibletab, naudibletab,
6208                "how audible console and terminal\nbells should be generated",
6209                        "beep",xxstring))<0)
6210           return(x);
6211         if ((z = cmcfm()) < 0)
6212           return(z);
6213         tt_bell = y | x;
6214 #else
6215         /* This lets C-Kermit accept but ignore trailing K95 keywords */
6216         if ((x = cmtxt("Confirm with carriage return","",&s,xxstring)) < 0)
6217           return(x);
6218         tt_bell = 1;
6219 #endif /* OS2 */
6220         break;
6221     }
6222     return(1);
6223 }
6224
6225 #ifdef OS2MOUSE
6226 int
6227 setmou(
6228 #ifdef CK_ANSIC
6229        void
6230 #endif /* CK_ANSIC */
6231  /* setmou */ ) {
6232     extern int initvik;
6233     int button = 0, event = 0;
6234     char * p;
6235
6236     if ((y = cmkey(mousetab,nmtab,"","",xxstring)) < 0)
6237       return(y);
6238
6239 #ifdef IKSD
6240     if (inserver) {
6241         if ((y = cmcfm()) < 0) return(y);
6242         printf("?Sorry, command disabled.\r\n");
6243         return(success = 0);
6244     }
6245 #endif /* IKSD */
6246
6247     if (y == XYM_ON) {                  /* MOUSE ACTIVATION */
6248         int old_mou = tt_mouse;
6249         if ((x = seton(&tt_mouse)) < 0)
6250             return(x);
6251         if (tt_mouse != old_mou)
6252           if (tt_mouse)
6253             os2_mouseon();
6254           else
6255             os2_mouseoff();
6256         return(1);
6257     }
6258
6259     if (y == XYM_DEBUG) {               /* MOUSE DEBUG */
6260         extern int MouseDebug;
6261         if ((x = seton(&MouseDebug)) < 0)
6262             return(x);
6263         return(1);
6264     }
6265
6266     if (y == XYM_CLEAR) {               /* Reset Mouse Defaults */
6267         if ((x = cmcfm()) < 0) return(x);
6268         mousemapinit(-1,-1);
6269         initvik = 1;                    /* Update VIK Table */
6270         return 1;
6271     }
6272     if (y != XYM_BUTTON) {              /* Shouldn't happen. */
6273         printf("Internal parsing error\n");
6274         return(-9);
6275     }
6276
6277     /* MOUSE EVENT ... */
6278
6279     if ((button = cmkey(mousebuttontab,nmbtab,
6280                         "Button number","1",
6281                         xxstring)) < 0)
6282       return(button);
6283
6284     if ((y =  cmkey(mousemodtab,nmmtab,
6285                     "Keyboard modifier","none",
6286                     xxstring)) < 0)
6287       return(y);
6288
6289     event |= y;                         /* OR in the bits */
6290
6291     if ((y =  cmkey(mclicktab,nmctab,"","click",xxstring)) < 0)
6292       return(y);
6293
6294     /* Two bits are assigned, if neither are set then it is button one */
6295
6296     event |= y;                 /* OR in the bit */
6297
6298     wideresult = -1;
6299
6300     if ((y = cmtxt("definition,\n\
6301 or Ctrl-C to cancel this command,\n\
6302 or Enter to restore default definition",
6303                    "",&s,NULL)) < 0) {
6304         return(y);
6305     }
6306     s = brstrip(s);
6307     p = s;                              /* Save this place */
6308 /*
6309   If the definition included any \Kverbs, quote the backslash so the \Kverb
6310   will still be in the definition when the key is pressed.  We don't do this
6311   in zzstring(), because \Kverbs are valid only in this context and nowhere
6312   else.  This code copied from SET KEY, q.v. for addt'l commentary.
6313 */
6314     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
6315         if ((x > 0) &&
6316             (s[x] == 'K' || s[x] == 'k')
6317             ) {                         /* Have K */
6318
6319             if ((x == 1 && s[x-1] == CMDQ) ||
6320                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
6321                 line[y++] = CMDQ;       /* Make it \\K */
6322             }
6323             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
6324                 line[y-1] = CMDQ;       /* Have \{K */
6325                 line[y++] = '{';        /* Make it \\{K */
6326             }
6327         }
6328         line[y] = s[x];
6329     }
6330     line[y++] = NUL;                    /* Terminate */
6331     s = line + y + 1;                   /* Point to after it */
6332     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
6333     if ((x < (LINBUFSIZ / 2)) ||
6334         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
6335         printf("?Key definition too long\n");
6336         return(-9);
6337     }
6338     s = line + y + 1;                   /* Point to result. */
6339
6340 #ifndef NOKVERBS
6341 /*
6342   Special case: see if the definition starts with a \Kverb.
6343   If it does, point to it with p, otherwise set p to NULL.
6344 */
6345     p = s;
6346     if (*p++ == CMDQ) {
6347         if (*p == '{') p++;
6348         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
6349     }
6350 #else
6351     p = NULL;
6352 #endif /* NOKVERBS */
6353
6354     /* free the old definition if necessary */
6355     if (mousemap[button][event].type == macro) {
6356         free( mousemap[button][event].macro.string);
6357         mousemap[button][event].macro.string = NULL;
6358     }
6359     switch (strlen(s)) {                /* Action depends on length */
6360       case 0:                           /* Reset to default binding */
6361         mousemapinit( button, event );
6362         break;
6363       case 1:                           /* Single character */
6364             mousemap[button][event].type = key;
6365         mousemap[button][event].key.scancode = *s;
6366         break;
6367       default:                          /* Character string */
6368 #ifndef NOKVERBS
6369         if (p) {
6370             y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
6371             debug(F101,"set mouse kverb lookup",0,y); /* need exact match */
6372             if (y > -1) {
6373             /* Assign the kverb to the event */
6374             mousemap[button][event].type = kverb;
6375             mousemap[button][event].kverb.id = F_KVERB | y;
6376             break;
6377             }
6378         }
6379 #endif /* NOKVERBS */
6380
6381        /* Otherwise, it's a macro, so assign the macro to the event */
6382        mousemap[button][event].type = macro;
6383        mousemap[button][event].macro.string = (MACRO) malloc(strlen(s)+1);
6384        if (mousemap[button][event].macro.string)
6385          strcpy((char *) mousemap[button][event].macro.string, s); /* safe */
6386         break;
6387     }
6388     initvik = 1;                        /* Update VIK Table */
6389     if ( (button == XYM_B3) && (mousebuttoncount() < 3) && !quiet )
6390     {
6391         printf("?Warning: this machine does not have a three button mouse.\n");
6392         return(0);
6393     }
6394     return(1);
6395 }
6396 #endif /* OS2MOUSE */
6397 #endif /* NOLOCAL */
6398
6399 #ifndef NOXFER
6400 int                                     /* SET SEND/RECEIVE */
6401 setsr(xx, rmsflg) int xx; int rmsflg; {
6402     if (xx == XYRECV)
6403       ckstrncpy(line,"Parameter for inbound packets",LINBUFSIZ);
6404     else
6405       ckstrncpy(line,"Parameter for outbound packets",LINBUFSIZ);
6406
6407     if (rmsflg) {
6408         if ((y = cmkey(rsrtab,nrsrtab,line,"",xxstring)) < 0) {
6409             if (y == -3) {
6410                 printf("?Remote receive parameter required\n");
6411                 return(-9);
6412             } else return(y);
6413         }
6414     } else {
6415         if ((y = cmkey(srtab,nsrtab,line,"",xxstring)) < 0) return(y);
6416     }
6417     switch (y) {
6418       case XYQCTL:                      /* CONTROL-PREFIX */
6419         if ((x = cmnum("ASCII value of control prefix","",10,&y,xxstring)) < 0)
6420           return(x);
6421         if ((x = cmcfm()) < 0) return(x);
6422         if ((y > 32 && y < 63) || (y > 95 && y < 127)) {
6423             if (xx == XYRECV)
6424               ctlq = (CHAR) y;          /* RECEIVE prefix, use with caution! */
6425             else
6426               myctlq = (CHAR) y;        /* SEND prefix, OK to change */
6427             return(success = 1);
6428         } else {
6429             printf("?Illegal value for prefix character\n");
6430             return(-9);
6431         }
6432
6433       case XYEOL:
6434         if ((y = setcc("13",&z)) < 0)
6435             return(y);
6436         if (z > 31) {
6437             printf("Sorry, the legal values are 0-31\n");
6438             return(-9);
6439         }
6440         if (xx == XYRECV)
6441           eol = (CHAR) z;
6442         else
6443           seol = (CHAR) z;
6444         return(success = y);
6445
6446       case XYLEN:
6447         y = cmnum("Maximum number of characters in a packet","90",10,&x,
6448                   xxstring);
6449         if (xx == XYRECV) {             /* Receive... */
6450             if ((y = setnum(&z,x,y,maxrps)) < 0)
6451               return(y);
6452             if (protocol != PROTO_K) {
6453                 printf("?Sorry, this command does not apply to %s protocol.\n",
6454                        ptab[protocol].p_name
6455                        );
6456                 printf("Use SET SEND PACKET-LENGTH for XYZMODEM\n");
6457                 return(-9);
6458             }
6459             if (z < 10) {
6460                 printf("Sorry, 10 is the minimum\n");
6461                 return(-9);
6462             }
6463             if (rmsflg) {
6464                 sstate = setgen('S', "401", ckitoa(z), "");
6465                 return((int) sstate);
6466             } else {
6467                 if (protocol == PROTO_K) {
6468                     if (z > MAXRP) z = MAXRP;
6469                     y = adjpkl(z,wslotr,bigrbsiz);
6470                     if (y != z) {
6471                         urpsiz = y;
6472                         if (!xcmdsrc)
6473                           if (msgflg) printf(
6474 " Adjusting receive packet-length to %d for %d window slots\n",
6475                                              y, wslotr);
6476                     }
6477                     urpsiz = y;
6478                     ptab[protocol].rpktlen = urpsiz;
6479                     rpsiz =  (y > 94) ? 94 : y;
6480                 } else {
6481 #ifdef CK_XYZ
6482                     if ((protocol == PROTO_X || protocol == PROTO_XC) &&
6483                          z != 128 && z != 1024) {
6484                         printf("Sorry, bad packet length for XMODEM.\n");
6485                         printf("Please use 128 or 1024.\n");
6486                         return(-9);
6487                     }
6488 #endif /* CK_XYZ */
6489                     urpsiz = rpsiz = z;
6490                 }
6491             }
6492         } else {                        /* Send... */
6493             if ((y = setnum(&z,x,y,maxsps)) < 0)
6494               return(y);
6495             if (z < 10) {
6496                 printf("Sorry, 10 is the minimum\n");
6497                 return(-9);
6498             }
6499             if (protocol == PROTO_K) {
6500                 if (z > MAXSP) z = MAXSP;
6501                 spsiz = z;              /* Set it */
6502                 y = adjpkl(spsiz,wslotr,bigsbsiz);
6503                 if (y != spsiz && !xcmdsrc)
6504                   if (msgflg)
6505                     printf("Adjusting packet size to %d for %d window slots\n",
6506                            y,wslotr);
6507             } else
6508               y = z;
6509 #ifdef CK_XYZ
6510             if ((protocol == PROTO_X || protocol == PROTO_XC) &&
6511                  z != 128 && z != 1024) {
6512                 printf("Sorry, bad packet length for XMODEM.\n");
6513                 printf("Please use 128 or 1024.\n");
6514                 return(-9);
6515             }
6516 #endif /* CK_XYZ */
6517             spsiz = spmax = spsizr = y; /* Set it and flag that it was set */
6518             spsizf = 1;                 /* to allow overriding Send-Init. */
6519             ptab[protocol].spktflg = spsizf;
6520             ptab[protocol].spktlen = spsiz;
6521         }
6522         if (pflag && protocol == PROTO_K && !xcmdsrc) {
6523             if (z > 94 && !reliable && msgflg) {
6524                 /* printf("Extended-length packets requested.\n"); */
6525                 if (bctr < 2 && z > 200) printf("\
6526 Remember to SET BLOCK 2 or 3 for long packets.\n");
6527             }
6528             if (speed <= 0L) speed = ttgspd();
6529 #ifdef COMMENT
6530 /*
6531   Kermit does this now itself.
6532 */
6533             if (speed <= 0L && z > 200 && msgflg) {
6534                 printf("\
6535 Make sure your timeout interval is long enough for %d-byte packets.\n",z);
6536             }
6537 #endif /* COMMENT */
6538         }
6539         return(success = y);
6540
6541       case XYMARK:
6542 #ifdef DOOMSDAY
6543 /*
6544   Printable start-of-packet works for UNIX and VMS only!
6545 */
6546         x_ifnum = 1;
6547         y = cmnum("Code for packet-start character","1",10,&x,xxstring);
6548         x_ifnum = 0;
6549         if ((y = setnum(&z,x,y,126)) < 0) return(y);
6550 #else
6551         if ((y = setcc("1",&z)) < 0)
6552             return(y);
6553 #endif /* DOOMSDAY */
6554         if (xx == XYRECV)
6555           stchr = (CHAR) z;
6556         else {
6557             mystch = (CHAR) z;
6558 #ifdef IKS_OPTION
6559             /* If IKS negotiation in use   */
6560             if (TELOPT_U(TELOPT_KERMIT) || TELOPT_ME(TELOPT_KERMIT))
6561               tn_siks(KERMIT_SOP);      /* Report change to other side */
6562 #endif /* IKS_OPTION */
6563         }
6564         return(success = y);
6565
6566       case XYNPAD:                      /* PADDING */
6567         y = cmnum("How many padding characters for inbound packets","0",10,&x,
6568                   xxstring);
6569         if ((y = setnum(&z,x,y,94)) < 0) return(y);
6570         if (xx == XYRECV)
6571           mypadn = (CHAR) z;
6572         else
6573           npad = (CHAR) z;
6574         return(success = y);
6575
6576       case XYPADC:                      /* PAD-CHARACTER */
6577         if ((y = setcc("0",&z)) < 0) return(y);
6578         if (xx == XYRECV) mypadc = z; else padch = z;
6579         return(success = y);
6580
6581       case XYTIMO:                      /* TIMEOUT */
6582         if (xx == XYRECV) {
6583             y = cmnum("Packet timeout interval",ckitoa(URTIME),10,&x,xxstring);
6584             if ((y = setnum(&z,x,y,94)) < 0) return(y);
6585
6586             if (rmsflg) {               /* REMOTE SET RECEIVE TIMEOUT */
6587                 sstate = setgen('S', "402", ckitoa(z), "");
6588                 return((int) sstate);
6589             } else {                    /* SET RECEIVE TIMEOUT */
6590                 pkttim = z;             /*   Value to put in my negotiation */
6591             }                           /*   packet for other Kermit to use */
6592
6593         } else {                        /* SET SEND TIMEOUT */
6594 #ifdef CK_TIMERS
6595             extern int rttflg, mintime, maxtime;
6596             int tmin = 0, tmax = 0;
6597 #endif /* CK_TIMERS */
6598             y = cmnum("Packet timeout interval",ckitoa(DMYTIM),10,&x,xxstring);
6599             if (y == -3) {              /* They cancelled a previous */
6600                 x = DMYTIM;             /* SET SEND command, so restore */
6601                 timef = 0;              /* and turn off the override flag */
6602                 y = cmcfm();
6603             }
6604 #ifdef CK_TIMERS
6605             if (y < 0) return(y);
6606             if (x < 0) {
6607                 printf("?Out of range - %d\n",x);
6608                 return(-9);
6609             }
6610             if ((z = cmkey(timotab,2,"","dynamic",xxstring)) < 0) return(z);
6611             if (z) {
6612                 if ((y = cmnum("Minimum timeout to allow",
6613                                "1",10,&tmin,xxstring)) < 0)
6614                   return(y);
6615                 if (tmin < 1) {
6616                     printf("?Out of range - %d\n",tmin);
6617                     return(-9);
6618                 }
6619                 if ((y = cmnum("Maximum timeout to allow",
6620                                "0",10,&tmax,xxstring)) < 0)
6621                   return(y);
6622                 /* 0 means let Kermit choose, < 0 means no maximum */
6623             }
6624             if ((y = cmcfm()) < 0)
6625               return(y);
6626             rttflg = z;                 /* Round-trip timer flag */
6627             z = x;
6628 #else
6629             if ((y = setnum(&z,x,y,94)) < 0)
6630               return(y);
6631 #endif /* CK_TIMERS */
6632             timef = 1;                  /* Turn on the override flag */
6633             timint = rtimo = z;         /* Override value for me to use */
6634 #ifdef CK_TIMERS
6635             if (rttflg) {               /* Lower and upper bounds */
6636                 mintime = tmin;
6637                 maxtime = tmax;
6638             }
6639 #endif /* CK_TIMERS */
6640         }
6641         return(success = 1);
6642
6643       case XYFPATH:                     /* PATHNAMES */
6644         if (xx == XYRECV) {
6645             y = cmkey(rpathtab,nrpathtab,"","auto",xxstring);
6646         } else {
6647             y = cmkey(pathtab,npathtab,"","off",xxstring);
6648         }
6649         if (y < 0) return(y);
6650
6651         if ((x = cmcfm()) < 0) return(x);
6652         if (xx == XYRECV) {             /* SET RECEIVE PATHNAMES */
6653             fnrpath = y;
6654             ptab[protocol].fnrp = fnrpath;
6655         } else {                        /* SET SEND PATHNAMES */
6656             fnspath = y;
6657             ptab[protocol].fnsp = fnspath;
6658         }
6659         return(success = 1);            /* Note: 0 = ON, 1 = OFF */
6660         /* In other words, ON = leave pathnames ON, OFF = take them off. */
6661
6662       case XYPAUS:                      /* SET SEND/RECEIVE PAUSE */
6663         y = cmnum("Milliseconds to pause between packets","0",10,&x,xxstring);
6664         if ((y = setnum(&z,x,y,15000)) < 0)
6665           return(y);
6666         pktpaus = z;
6667         return(success = 1);
6668
6669 #ifdef CKXXCHAR                         /* SET SEND/RECEIVE IGNORE/DOUBLE */
6670       case XYIGN:
6671       case XYDBL: {
6672           int i, zz;
6673           short *p;
6674           extern short dblt[];
6675           extern int dblflag, ignflag;
6676
6677           /* Make space for a temporary copy of the ignore/double table */
6678
6679           zz = y;
6680 #ifdef COMMENT
6681           if (zz == XYIGN && xx == XYSEND) {
6682               blah blah who cares
6683           }
6684           if (zz == XYDBL && xx == XYRECV) {
6685               blah blah
6686           }
6687 #endif /* COMMENT */
6688           p = (short *)malloc(256 * sizeof(short));
6689           if (!p) {
6690               printf("?Internal error - malloc failure\n");
6691               return(-9);
6692           }
6693           for (i = 0; i < 256; i++) p[i] = dblt[i]; /* Copy current table */
6694
6695           while (1) {                   /* Collect a list of numbers */
6696 #ifndef NOSPL
6697               x_ifnum = 1;              /* Turn off complaints from eval() */
6698 #endif /* NOSPL */
6699               if ((x = cmnum(zz == XYDBL ?
6700                              "Character to double" :
6701                              "Character to ignore",
6702                              "",10,&y,xxstring
6703                              )) < 0) {
6704 #ifndef NOSPL
6705                   x_ifnum = 0;
6706 #endif /* NOSPL */
6707                   if (x == -3)          /* Done */
6708                     break;
6709                   if (x == -2) {
6710                       if (p) { free(p); p = NULL; }
6711                       debug(F110,"SET S/R DOUBLE/IGNORE atmbuf",atmbuf,0);
6712                       if (!ckstrcmp(atmbuf,"none",4,0) ||
6713                           !ckstrcmp(atmbuf,"non",3,0) ||
6714                           !ckstrcmp(atmbuf,"no",2,0) ||
6715                           !ckstrcmp(atmbuf,"n",1,0)) {
6716                           if ((x = cmcfm()) < 0) /* Get confirmation */
6717                             return(x);
6718                           for (y = 0; y < 256; y++)
6719                             dblt[y] &= (zz == XYDBL) ? 1 : 2;
6720                           if (zz == XYDBL) dblflag = 0;
6721                           if (zz == XYIGN) ignflag = 0;
6722                           return(success = 1);
6723                       } else {
6724                           printf(
6725                             "?Please specify a number or the word NONE\n");
6726                           return(-9);
6727                       }
6728                   } else {
6729                       free(p);
6730                       p = NULL;
6731                       return(x);
6732                   }
6733               }
6734 #ifndef NOSPL
6735               x_ifnum = 0;
6736 #endif /* NOSPL */
6737               if (y < 0 || y > 255) {
6738                   printf("?Please enter a character code in range 0-255\n");
6739                   free(p);
6740                   p = NULL;
6741                   return(-9);
6742               }
6743               p[y] |= (zz == XYDBL) ? 2 : 1;
6744               if (zz == XYDBL) dblflag = 1;
6745               if (zz == XYIGN) ignflag = 1;
6746           } /* End of while loop */
6747
6748           if ((x = cmcfm()) < 0) return(x);
6749 /*
6750   Get here only if they have made no mistakes.  Copy temporary table back to
6751   permanent one, then free temporary table and return successfully.
6752 */
6753           if (p) {
6754               for (i = 0; i < 256; i++) dblt[i] = p[i];
6755               free(p);
6756               p = NULL;
6757           }
6758           return(success = 1);
6759       }
6760 #endif /* CKXXCHAR */
6761
6762 #ifdef PIPESEND
6763       case XYFLTR: {                    /* SET { SEND, RECEIVE } FILTER */
6764           if ((y = cmtxt((xx == XYSEND) ?
6765                 "Filter program for sending files -\n\
6766  use \\v(filename) to substitute filename" :
6767                 "Filter program for receiving files -\n\
6768  use \\v(filename) to substitute filename",
6769                          "",&s,NULL)) < 0)
6770             return(y);
6771           if (!*s) {                    /* Removing a filter... */
6772               if (xx == XYSEND && sndfilter) {
6773                   makestr(&g_sfilter,NULL);
6774                   makestr(&sndfilter,NULL);
6775               } else if (rcvfilter) {
6776                   makestr(&g_rfilter,NULL);
6777                   makestr(&rcvfilter,NULL);
6778               }
6779               return(success = 1);
6780           }                             /* Adding a filter... */
6781           s = brstrip(s);               /* Strip any braces */
6782           y = strlen(s);
6783           if (xx == XYSEND) {           /* For SEND filter... */
6784               for (x = 0; x < y; x++) { /* make sure they included "\v(...)" */
6785                   if (s[x] != '\\') continue;
6786                   if (s[x+1] == 'v') break;
6787               }
6788               if (x == y) {
6789                   printf(
6790               "?Filter must contain a replacement variable for filename.\n"
6791                          );
6792                   return(-9);
6793               }
6794           }
6795           if (xx == XYSEND) {
6796               makestr(&sndfilter,s);
6797               makestr(&g_sfilter,s);
6798           } else {
6799               makestr(&rcvfilter,s);
6800               makestr(&g_rfilter,s);
6801           }
6802           return(success = 1);
6803       }
6804 #endif /* PIPESEND */
6805
6806       case XYINIL:
6807         y = cmnum("Max length for protocol init string","-1",10,&x,xxstring);
6808         if ((y = setnum(&z,x,y,-1)) < 0)
6809           return(y);
6810         if (xx == XYSEND)
6811           sprmlen = z;
6812         else
6813           rprmlen = z;
6814         return(success = 1);
6815
6816       case 993: {
6817           extern int sendipkts;
6818           if (xx == XYSEND) {
6819               if ((x = seton(&sendipkts)) < 0)
6820                 return(x);
6821           }
6822           return(1);
6823       }
6824 #ifdef CK_PERMS
6825       case 994:
6826         switch(xx) {
6827           case XYSEND:
6828             if ((x = seton(&atlpro)) < 0) return(x);
6829             atgpro = atlpro;
6830             return(1);
6831           case XYRECV:
6832             if ((x = seton(&atlpri)) < 0) return(x);
6833             atgpri = atlpri;
6834             return(1);
6835           default:
6836             return(-2);
6837         }
6838 #endif /* CK_PERMS */
6839
6840 #ifndef NOCSETS
6841       case XYCSET: {                    /* CHARACTER-SET-SELECTION */
6842           extern struct keytab xfrmtab[];
6843           extern int r_cset, s_cset;
6844           if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
6845             return(y);
6846           if ((x = cmcfm()) < 0)
6847             return(x);
6848           if (xx == XYSEND)
6849             s_cset = y;
6850           else
6851             r_cset = y;
6852           return(success = 1);
6853       }
6854 #endif /* NOCSETS */
6855
6856       case XYBUP:
6857         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
6858           return(y);
6859         if ((x = cmcfm()) < 0) return(x);
6860         if (xx == XYSEND) {
6861             extern int skipbup;
6862             skipbup = (y == 0) ? 1 : 0;
6863             return(success = 1);
6864         } else {
6865             printf(
6866 "?Please use SET FILE COLLISION to choose the desired action\n");
6867             return(-9);
6868         }
6869
6870       case XYMOVE:
6871 #ifdef COMMENT
6872         y = cmdir("Directory to move file(s) to after successful transfer",
6873                   "",&s,xxstring);
6874 #else
6875         y = cmtxt("Directory to move file(s) to after successful transfer",
6876                   "",&s,xxstring);
6877 #endif /* COMMENT */
6878
6879         if (y < 0 && y != -3)
6880           return(y);
6881         ckstrncpy(line,s,LINBUFSIZ);
6882         s = brstrip(line);
6883
6884 #ifdef COMMENT
6885         /* Only needed for cmdir() */
6886         if ((x = cmcfm()) < 0)
6887           return(x);
6888 #endif /* COMMENT */
6889         
6890         /* Check directory existence if absolute */
6891         /* THIS MEANS IT CAN'T INCLUDE ANY DEFERRED VARIABLES! */
6892         if (s) if (*s) {
6893             if (isabsolute(s) && !isdir(s)) {
6894                 printf("?Directory does not exist - %s\n",s);
6895                 return(-9);
6896             }
6897         }
6898         if (xx == XYSEND) {
6899             if (*s) {
6900 #ifdef COMMENT
6901                 /* Allow it to be relative */
6902                 zfnqfp(s,LINBUFSIZ,line);
6903 #endif /* COMMENT */
6904                 makestr(&snd_move,line);
6905                 makestr(&g_snd_move,line);
6906             } else {
6907                 makestr(&snd_move,NULL);
6908                 makestr(&g_snd_move,NULL);
6909             }
6910         } else {
6911             if (*s) {
6912 #ifdef COMMENT
6913                 /* Allow it to be relative */
6914                 zfnqfp(s,LINBUFSIZ,line);
6915 #endif /* COMMENT */
6916                 makestr(&rcv_move,line);
6917                 makestr(&g_rcv_move,line);
6918             } else {
6919                 makestr(&rcv_move,NULL);
6920                 makestr(&g_rcv_move,NULL);
6921             }
6922         }
6923         return(success = 1);
6924
6925       case XYRENAME:
6926         y = cmtxt("Template to rename file(s) to after successful transfer",
6927                   "",&s,NULL);          /* NOTE: no xxstring */
6928         if (y < 0 && y != -3)           /* Evaluation is deferred */
6929           return(y);
6930         ckstrncpy(line,s,LINBUFSIZ);
6931         s = brstrip(line);
6932         if ((x = cmcfm()) < 0)
6933           return(x);
6934         if (xx == XYSEND) {
6935             if (*s) {
6936                 makestr(&snd_rename,s);
6937                 makestr(&g_snd_rename,s);
6938             } else {
6939                 makestr(&snd_rename,NULL);
6940                 makestr(&g_snd_rename,NULL);
6941             }
6942         } else {
6943             if (*s) {
6944                 makestr(&rcv_rename,s);
6945                 makestr(&g_rcv_rename,s);
6946             } else {
6947                 makestr(&rcv_rename,NULL);
6948                 makestr(&g_rcv_rename,NULL);
6949             }
6950         }
6951         return(success = 1);
6952
6953 #ifdef VMS
6954       case 887:                         /* VERSION-NUMBERS */
6955         if (xx == XYSEND) {
6956             extern int vmssversions;
6957             return(seton(&vmssversions));
6958         } else {
6959             extern int vmsrversions;
6960             return(seton(&vmsrversions));
6961         }
6962 #endif /* VMS */
6963
6964       default:
6965         return(-2);
6966     }                                   /* End of SET SEND/RECEIVE... */
6967 }
6968 #endif /* NOXFER */
6969
6970 #ifndef NOXMIT
6971 int
6972 setxmit() {
6973     if ((y = cmkey(xmitab,nxmit,"","",xxstring)) < 0) return(y);
6974     switch (y) {
6975       case XMITE:                       /* EOF */
6976         y = cmtxt("Characters to send at end of file,\n\
6977  Use backslash codes for control characters","",&s,xxstring);
6978         if (y < 0) return(y);
6979         if ((int)strlen(s) > XMBUFL) {
6980             printf("?Too many characters, %d maximum\n",XMBUFL);
6981             return(-2);
6982         }
6983         ckstrncpy(xmitbuf,s,XMBUFL);
6984         return(success = 1);
6985
6986       case XMITF:                       /* Fill */
6987         y = cmnum("Numeric code for blank-line fill character","0",10,&x,
6988                   xxstring);
6989         if ((y = setnum(&z,x,y,127)) < 0) return(y);
6990         xmitf = z;
6991         return(success = 1);
6992       case XMITL:                       /* Linefeed */
6993         return(seton(&xmitl));
6994       case XMITS:                       /* Locking-Shift */
6995         return(seton(&xmits));
6996       case XMITP:                       /* Prompt */
6997         y = cmnum("Numeric code for host's prompt character, 0 for none",
6998                   "10",10,&x,xxstring);
6999         if ((y = setnum(&z,x,y,127)) < 0) return(y);
7000         xmitp = z;
7001         return(success = 1);
7002       case XMITX:                       /* Echo */
7003         return(seton(&xmitx));
7004       case XMITW:                       /* Pause */
7005         y = cmnum("Number of milliseconds to pause between binary characters\n\
7006 or text lines during transmission","0",10,&x,xxstring);
7007         if ((y = setnum(&z,x,y,1000)) < 0) return(y);
7008         xmitw = z;
7009         return(success = 1);
7010       case XMITT:                       /* Timeout */
7011         y = cmnum("Seconds to wait for each character to echo",
7012                   "1",10,&x,xxstring);
7013         if ((y = setnum(&z,x,y,1000)) < 0) return(y);
7014         xmitt = z;
7015         return(success = 1);
7016       default:
7017         return(-2);
7018     }
7019 }
7020 #endif /* NOXMIT */
7021
7022 #ifndef NOXFER
7023 /*  D O R M T  --  Do a remote command  */
7024
7025 VOID
7026 rmsg() {
7027     if (pflag && !quiet && fdispla != XYFD_N)
7028       printf(
7029 #ifdef CK_NEED_SIG
7030        " Type your escape character, %s, followed by X or E to cancel.\n",
7031        dbchr(escape)
7032 #else
7033        " Press the X or E key to cancel.\n"
7034 #endif /* CK_NEED_SIG */
7035       );
7036 }
7037
7038 static int xzcmd = 0;                   /* Global copy of REMOTE cmd index */
7039
7040 /*  R E M C F M  --  Confirm a REMOTE command  */
7041 /*
7042   Like cmcfm(), but allows for a redirection indicator on the end,
7043   like "> filename" or "| command".  Returns what cmcfm() would have
7044   returned: -1 if reparse needed, etc etc blah blah.  On success,
7045   returns 1 with:
7046
7047     char * remdest containing the name of the file or command.
7048     int remfile set to 1 if there is to be any redirection.
7049     int remappd set to 1 if output file is to be appended to.
7050     int rempipe set to 1 if remdest is a command, 0 if it is a file.
7051 */
7052 static int
7053 remcfm() {
7054     int x;
7055     char *s;
7056     char c;
7057
7058     remfile = 0;
7059     rempipe = 0;
7060     remappd = 0;
7061
7062     if ((x = cmtxt(
7063              "> filename, | command,\n\
7064 or type carriage return to confirm the command",
7065                    "",&s,xxstring)) < 0)
7066       return(x);
7067     if (remdest) {
7068         free(remdest);
7069         remdest = NULL;
7070     }
7071     debug(F101,"remcfm local","",local);
7072     debug(F110,"remcfm s",s,0);
7073     debug(F101,"remcfm cmd","",xzcmd);
7074
7075     if (!*s) {                          /* No redirection indicator */
7076         if (!local &&
7077             (xzcmd == XZDIR || xzcmd == XZTYP ||
7078              xzcmd == XZXIT || xzcmd == XZSPA ||
7079              xzcmd == XZHLP || xzcmd == XZPWD ||
7080              xzcmd == XZLGI || xzcmd == XZLGO ||
7081              xzcmd == XZWHO || xzcmd == XZHOS)) {
7082             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
7083             return(-9);
7084         } else
7085           return(1);
7086     }
7087     c = *s;                             /* We have something */
7088     if (c != '>' && c != '|') {         /* Is it > or | ? */
7089         printf("?Not confirmed\n");     /* No */
7090         return(-9);
7091     }
7092     s++;                                /* See what follows */
7093     if (c == '>' && *s == '>') {        /* Allow for ">>" too */
7094         s++;
7095         remappd = 1;                    /* Append to output file */
7096     }
7097     while (*s == SP || *s == HT) s++;   /* Strip intervening whitespace */
7098     if (!*s) {
7099         printf("?%s missing\n", c == '>' ? "Filename" : "Command");
7100         return(-9);
7101     }
7102     if (c == '>' && zchko(s) < 0) {     /* Check accessibility */
7103         printf("?Access denied - %s\n", s);
7104         return(-9);
7105     }
7106     remfile = 1;                        /* Set global results */
7107     rempipe = (c == '|');
7108     if (rempipe
7109 #ifndef NOPUSH
7110         && nopush
7111 #endif /* NOPUSH */
7112         ) {
7113         printf("?Sorry, access to external commands is disabled.\n");
7114         return(-9);
7115     }
7116     makestr(&remdest,s);
7117 #ifndef NODEBUG
7118     if (deblog) {
7119         debug(F101,"remcfm remfile","",remfile);
7120         debug(F101,"remcfm remappd","",remappd);
7121         debug(F101,"remcfm rempipe","",rempipe);
7122         debug(F110,"remcfm remdest",remdest, 0);
7123     }
7124 #endif /* NODEBUG */
7125     return(1);
7126 }
7127
7128 /*  R E M T X T  --  Like remcfm()...  */
7129 /*
7130    ... but for REMOTE commands that end with cmtxt().
7131    Here we must decipher braces to discover whether the trailing
7132    redirection indicator is intended for local use, or to be sent out
7133    to the server, as in:
7134
7135      remote host blah blah > file                 This end
7136      remote host { blah blah } > file             This end
7137      remote host { blah blah > file }             That end
7138      remote host { blah blah > file } > file      Both ends
7139
7140    Pipes too:
7141
7142      remote host blah blah | cmd                  This end
7143      remote host { blah blah } | cmd              This end
7144      remote host { blah blah | cmd }              That end
7145      remote host { blah blah | cmd } | cmd        Both ends
7146
7147    Or both:
7148
7149      remote host blah blah | cmd > file           This end, etc etc...
7150
7151    Note: this really only makes sense for REMOTE HOST, but why be picky?
7152    Call after calling cmtxt(), with pointer to string that cmtxt() parsed,
7153    as in "remtxt(&s);".
7154
7155    Returns:
7156     1 on success with braces & redirection things removed & pointer updated,
7157    -9 on failure (bad indirection), after printing error message.
7158 */
7159 int
7160 remtxt(p) char ** p; {
7161     int i, x, bpos, ppos;
7162     char c, *s, *q;
7163
7164     remfile = 0;                        /* Initialize global results */
7165     rempipe = 0;
7166     remappd = 0;
7167     if (remdest) {
7168         free(remdest);
7169         remdest = NULL;
7170     }
7171     s = *p;
7172     if (!s)                             /* No redirection indicator */
7173       s = "";
7174     if (!*s) {                          /* Ditto */
7175         if (!local &&
7176             (xzcmd == XZDIR || xzcmd == XZTYP ||
7177              xzcmd == XZXIT || xzcmd == XZSPA ||
7178              xzcmd == XZHLP || xzcmd == XZPWD ||
7179              xzcmd == XZLGI || xzcmd == XZLGO ||
7180              xzcmd == XZWHO || xzcmd == XZHOS)) {
7181             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
7182             if (hints) {
7183                 printf("Hint: Try again with an output redirector.\n");
7184             }
7185             return(-9);
7186         } else
7187           return(1);
7188     }
7189     bpos = -1;                          /* Position of > (bracket) */
7190     ppos = -1;                          /* Position of | (pipe) */
7191     x = strlen(s);                      /* Length of cmtxt() string */
7192
7193     for (i = x-1; i >= 0; i--) {        /* Search right to left. */
7194         c = s[i];
7195         if (c == '}')                   /* Break on first right brace */
7196           break;                        /* Don't look at contents of braces */
7197         else if (c == '>')              /* Record position of > */
7198           bpos = i;
7199         else if (c == '|')              /* and of | */
7200           ppos = i;
7201     }
7202     if (bpos < 0 && ppos < 0) {         /* No redirectors. */
7203         if (!local &&
7204             (xzcmd == XZDIR || xzcmd == XZTYP ||
7205              xzcmd == XZXIT || xzcmd == XZSPA ||
7206              xzcmd == XZHLP || xzcmd == XZPWD ||
7207              xzcmd == XZLGI || xzcmd == XZLGO ||
7208              xzcmd == XZWHO || xzcmd == XZHOS)) {
7209             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
7210             if (hints) {
7211                 printf("Hint: Try again with an output redirector.\n");
7212             }
7213             return(-9);
7214         }
7215         s = brstrip(s);                 /* Remove outer braces if any. */
7216         *p = s;                         /* Point to result */
7217         return(1);                      /* and return. */
7218     }
7219     remfile = 1;                        /* It's | or > */
7220     i = -1;                             /* Get leftmost symbol */
7221     if (bpos > -1)                      /* Bracket */
7222       i = bpos;
7223     if (ppos > -1 && (ppos < bpos || bpos < 0)) { /* or pipe */
7224         i = ppos;
7225         rempipe = 1;
7226     }
7227     if (rempipe
7228 #ifndef NOPUSH
7229         && nopush
7230 #endif /* NOPUSH */
7231         ) {
7232         printf("?Sorry, access to external commands is disabled.\n");
7233         return(-9);
7234     }
7235     c = s[i];                           /* Copy of symbol */
7236
7237     if (c == '>' && s[i+1] == '>')      /* ">>" for append? */
7238       remappd = 1;                     /* It's not just a flag it's a number */
7239
7240     q = s + i + 1 + remappd;            /* Point past symbol in string */
7241     while (*q == SP || *q == HT) q++;   /* and any intervening whitespace */
7242     if (!*q) {
7243         printf("?%s missing\n", c == '>' ? "Filename" : "Command");
7244         return(-9);
7245     }
7246     if (c == '>' && zchko(q) < 0) {     /* (Doesn't work for | cmd > file) */
7247         printf("?Access denied - %s\n", q);
7248         return(-9);
7249     }
7250     makestr(&remdest,q);                /* Create the destination string */
7251     q = s + i - 1;                      /* Point before symbol */
7252     while (q > s && (*q == SP || *q == HT)) /* Strip trailing whitespace */
7253       q--;
7254     *(q+1) = NUL;                       /* Terminate the string. */
7255     s = brstrip(s);                     /* Remove any braces */
7256     *p = s;                             /* Set return value */
7257
7258 #ifndef NODEBUG
7259     if (deblog) {
7260         debug(F101,"remtxt remfile","",remfile);
7261         debug(F101,"remtxt remappd","",remappd);
7262         debug(F101,"remtxt rempipe","",rempipe);
7263         debug(F110,"remtxt remdest",remdest, 0);
7264         debug(F110,"remtxt command",s,0);
7265     }
7266 #endif /* NODEBUG */
7267
7268     return(1);
7269 }
7270
7271 int
7272 plogin(xx) int xx; {
7273     char *p1 = NULL, *p2 = NULL, *p3 = NULL;
7274     int psaved = 0, rc = 0;
7275 #ifdef CK_RECALL
7276     extern int on_recall;               /* around Password prompting */
7277 #endif /* CK_RECALL */
7278     debug(F101,"plogin local","",local);
7279
7280     if (!local || (network && ttchk() < 0)) {
7281         printf("?No connection\n");
7282         return(-9);
7283     }
7284     if ((x = cmfld("User ID","",&s,xxstring)) < 0) { /* Get User ID */
7285         if (x != -3) return(x);
7286     }
7287     y = strlen(s);
7288     if (y > 0) {
7289         if ((p1 = malloc(y + 1)) == NULL) {
7290             printf("?Internal error: malloc\n");
7291             rc = -9;
7292             goto XZXLGI;
7293         } else
7294           strcpy(p1,s);                 /* safe */
7295         if ((rc = cmfld("Password","",&s,xxstring)) < 0)
7296           if (rc != -3) goto XZXLGI;
7297         y = strlen(s);
7298         if (y > 0) {
7299             if ((p2 = malloc(y + 1)) == NULL) {
7300                 printf("?Internal error: malloc\n");
7301                 rc = -9;
7302                 goto XZXLGI;
7303             } else
7304               strcpy(p2,s);             /* safe */
7305             if ((rc = cmfld("Account","",&s,xxstring)) < 0)
7306               if (rc != -3) goto XZXLGI;
7307             y = strlen(s);
7308             if (y > 0) {
7309                 if ((p3 = malloc(y + 1)) == NULL) {
7310                     printf("?Internal error: malloc\n");
7311                     rc = -9;
7312                     goto XZXLGI;
7313                 } else
7314                   strcpy(p3,s);         /* safe */
7315             }
7316         }
7317     }
7318     if ((rc = remtxt(&s)) < 0)          /* Confirm & handle redirectors */
7319       goto XZXLGI;
7320
7321     if (!p1) {                          /* No Userid specified... */
7322         debok = 0;                      /* Don't log this */
7323         /* Prompt for username, password, and account */
7324 #ifdef CK_RECALL
7325         on_recall = 0;
7326 #endif /* CK_RECALL */
7327         cmsavp(psave,PROMPTL);          /* Save old prompt */
7328         psaved = 1;
7329         debug(F110,"REMOTE LOGIN saved",psave,0);
7330
7331         cmsetp("Username: ");           /* Make new prompt */
7332         concb((char)escape);            /* Put console in cbreak mode */
7333         cmini(1);
7334         prompt(xxstring);
7335         rc = -9;
7336         for (x = -1; x < 0; ) {         /* Prompt till they answer */
7337             cmres();                    /* Reset the parser */
7338             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
7339         }
7340         y = strlen(s);
7341         if (y < 1) {
7342             printf("?Canceled\n");
7343             goto XZXLGI;
7344         }
7345         if ((p1 = malloc(y + 1)) == NULL) {
7346             printf("?Internal error: malloc\n");
7347             goto XZXLGI;
7348         } else
7349           strcpy(p1,s);                 /* safe */
7350
7351         cmsetp("Password: ");           /* Make new prompt */
7352         concb((char)escape);            /* Put console in cbreak mode */
7353         cmini(0);                       /* No echo */
7354         prompt(xxstring);
7355         debok = 0;
7356         for (x = -1; x < 0 && x != -3; ) { /* Get answer */
7357             cmres();                    /* Reset the parser */
7358             x = cmtxt("","",&s,NULL);   /* Get literal line of text */
7359         }
7360         if ((p2 = malloc((int)strlen(s) + 1)) == NULL) {
7361             printf("?Internal error: malloc\n");
7362             goto XZXLGI;
7363         } else
7364           strcpy(p2,s);                 /* safe */
7365         printf("\r\n");
7366         if ((rc = cmcfm()) < 0)
7367           goto XZXLGI;
7368     }
7369     sstate = setgen('I',p1,p2,p3);      /* Get here with at least user ID */
7370     rc = 0;
7371
7372   XZXLGI:                               /* Common exit point */
7373     if (psaved)
7374       cmsetp(psave);                    /* Restore original prompt */
7375     if (p3) { free(p3); p3 = NULL; }    /* Free malloc'd storage */
7376     if (p2) { free(p2); p2 = NULL; }
7377     if (p1) { free(p1); p1 = NULL; }
7378     if (rc > -1) {
7379         if (local && rc > -1)           /* If local, flush tty input buffer */
7380           ttflui();
7381     }
7382     return(rc);
7383 }
7384
7385 #ifdef OS2
7386 #ifndef NOLOCAL
7387 int
7388 dormt(xx) int xx; {
7389     int rc = 0;
7390     extern int term_io;
7391     int term_io_sav = term_io;
7392 #ifdef NEWFTP
7393     extern int ftpget, ftpisopen();
7394     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
7395       return(doftprmt(xx,0));
7396 #endif /* NEWFTP */
7397     term_io = 0;
7398     rc = xxdormt(xx);
7399     term_io = term_io_sav;
7400     return rc;
7401 }
7402
7403
7404 int
7405 xxdormt(xx) int xx;
7406 #else /* NOLOCAL */
7407 int
7408 dormt(xx) int xx;
7409 #endif /* NOLOCAL */
7410 #else /* OS2 */
7411 int
7412 dormt(xx) int xx;
7413 #endif /* OS2 */
7414 {                                       /* REMOTE commands */
7415     int x, y, retcode;
7416     char *s, sbuf[50], *s2;
7417
7418 #ifdef NEWFTP
7419     extern int ftpget, ftpisopen();
7420     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
7421       return(doftprmt(xx,0));
7422 #endif /* NEWFTP */
7423
7424     remfile = 0;                        /* Clear these */
7425     rempipe = 0;
7426     remappd = 0;
7427
7428     if (xx < 0) return(xx);             /* REMOTE what? */
7429
7430     xzcmd = xx;                         /* Make global copy of arg */
7431
7432     if (xx == XZSET) {                  /* REMOTE SET */
7433         if ((y = cmkey(rmstab,nrms,"","",xxstring)) < 0) {
7434             if (y == -3) {
7435                 printf("?Parameter name required\n");
7436                 return(-9);
7437             } else return(y);
7438         }
7439         return(doprm(y,1));
7440     }
7441
7442     switch (xx) {                       /* Others... */
7443
7444       case XZCDU:
7445         if ((x = cmcfm()) < 0) return(x);
7446         printf("?Sorry, REMOTE CDUP not supported yet\n");
7447         return(-9);
7448
7449       case XZCWD:                       /* CWD (CD) */
7450         if ((x = cmtxt("Remote directory name","",&s,xxstring)) < 0)
7451           return(x);
7452         if ((x = remtxt(&s)) < 0)
7453           return(x);
7454         debug(F111,"XZCWD: ",s,x);
7455         *sbuf = NUL;
7456         s2 = sbuf;
7457 /*
7458   The following is commented out because since the disappearance of the
7459   DECSYSTEM-20 from the planet, no known computer requires a password for
7460   changing directory.
7461 */
7462 #ifdef DIRPWDPR
7463         if (*s != NUL) {                /* If directory name given, */
7464                                         /* get password on separate line. */
7465             if (tlevel > -1) {          /* From take file... */
7466
7467                 if (fgets(sbuf,50,tfile[tlevel]) == NULL)
7468                   fatal("take file ends prematurely in 'remote cwd'");
7469                 debug(F110," pswd from take file",s2,0);
7470                 for (x = (int)strlen(sbuf);
7471                      x > 0 && (sbuf[x-1] == NL || sbuf[x-1] == CR);
7472                      x--)
7473                   sbuf[x-1] = '\0';
7474
7475             } else {                    /* From terminal... */
7476
7477                 printf(" Password: ");  /* get a password */
7478 #ifdef IKSD
7479                 if (!local && inserver) {
7480                     x = coninc(0);
7481                 } else
7482 #endif /* IKSD */
7483 #ifdef OS2
7484                   x = is_a_tty(0) ? coninc(0) : /* with no echo ... */
7485                     getchar();
7486 #else /* OS2 */
7487                 x = getchar();
7488 #endif /* OS2 */
7489                 while ((x != NL) && (x != CR)) {
7490                     if ((x &= 0177) == '?') {
7491                         printf("? Password of remote directory\n Password: ");
7492                         s2 = sbuf;
7493                         *sbuf = NUL;
7494                     } else if (x == ESC) /* Mini command line editor... */
7495                       bleep(BP_WARN);
7496                     else if (x == BS || x == 0177)
7497                       s2--;
7498                     else if (x == 025) {        /* Ctrl-U */
7499                         s2 = sbuf;
7500                         *sbuf = NUL;
7501                     } else
7502                       *s2++ = x;
7503
7504                     /* Get the next character */
7505 #ifdef IKSD
7506                     if (!local && inserver) {
7507                         x = coninc(0);
7508                     } else
7509 #endif /* IKSD */
7510 #ifdef OS2
7511                     x = is_a_tty(0) ? coninc(0) : /* with no echo ... */
7512                       getchar();
7513 #else /* OS2 */
7514                     x = getchar();
7515 #endif /* OS2 */
7516                 }
7517                 *s2 = NUL;
7518                 putchar('\n');
7519             }
7520             s2 = sbuf;
7521         } else s2 = "";
7522 #endif /* DIRPWDPR */
7523
7524         debug(F110," password",s2,0);
7525         rcdactive = 1;
7526         sstate = setgen('C',s,s2,"");
7527         retcode = 0;
7528         break;
7529
7530       case XZDEL:                               /* Delete */
7531         if ((x = cmtxt("Name of remote file(s) to delete",
7532                        "",&s,xxstring)) < 0) {
7533             if (x == -3) {
7534                 printf("?Name of remote file(s) required\n");
7535                 return(-9);
7536             } else return(x);
7537         }
7538         if ((x = remtxt(&s)) < 0)
7539           return(x);
7540         if (local) ttflui();            /* If local, flush tty input buffer */
7541         retcode = sstate = rfilop(s,'E');
7542         break;
7543
7544       case XZDIR:                       /* Directory */
7545         if ((x = cmtxt("Remote directory or file specification","",&s,
7546                        xxstring)) < 0)
7547           return(x);
7548         if ((x = remtxt(&s)) < 0)
7549           return(x);
7550         if (local) ttflui();            /* If local, flush tty input buffer */
7551         rmsg();
7552         retcode = sstate = setgen('D',s,"","");
7553         break;
7554
7555       case XZHLP:                       /* Help */
7556         if ((x = remcfm()) < 0) return(x);
7557         sstate = setgen('H',"","","");
7558         retcode = 0;
7559         break;
7560
7561       case XZHOS:                       /* Host */
7562         if ((x = cmtxt("Command for remote system","",&s,xxstring)) < 0)
7563           return(x);
7564         if ((x = remtxt(&s)) < 0)
7565           return(x);
7566         if ((y = (int)strlen(s)) < 1)
7567           return(x);
7568         ckstrncpy(line,s,LINBUFSIZ);
7569         cmarg = line;
7570         rmsg();
7571         retcode = sstate = 'c';
7572         break;
7573
7574 #ifndef NOFRILLS
7575       case XZKER:
7576         if ((x = cmtxt("Command for remote Kermit","",&s,xxstring)) < 0)
7577           return(x);
7578         if ((x = remtxt(&s)) < 0)
7579           return(x);
7580         if ((int)strlen(s) < 1)  {
7581             if (x == -3) {
7582                 printf("?Remote Kermit command required\n");
7583                 return(-9);
7584             } else return(x);
7585         }
7586         ckstrncpy(line,s,LINBUFSIZ);
7587         cmarg = line;
7588         retcode = sstate = 'k';
7589         rmsg();
7590         break;
7591
7592       case XZLGI:                       /* Login */
7593         rcdactive = 1;                  /* Suppress "Logged in" msg if quiet */
7594         return(plogin(XXREM));
7595
7596       case XZLGO: {                     /* Logout */
7597           extern int bye_active;
7598           if ((x = remcfm()) < 0) return(x);
7599           sstate = setgen('I',"","","");
7600           retcode = 0;
7601           bye_active = 1;               /* Close connection when done */
7602           break;
7603       }
7604
7605       case XZPRI:                       /* Print */
7606         if (!atdiso || !atcapr) {       /* Disposition attribute off? */
7607             printf("?Disposition Attribute is Off\n");
7608             return(-2);
7609         }
7610         cmarg = "";
7611         cmarg2 = "";
7612         if ((x = cmifi("Local file(s) to print on remote printer","",&s,&y,
7613                        xxstring)) < 0) {
7614             if (x == -3) {
7615                 printf("?Name of local file(s) required\n");
7616                 return(-9);
7617             }
7618             return(x);
7619         }
7620         ckstrncpy(line,s,LINBUFSIZ);    /* Make a safe copy of filename */
7621         *optbuf = NUL;                  /* Wipe out any old options */
7622         if ((x = cmtxt("Options for remote print command","",&s,xxstring)) < 0)
7623           return(x);
7624         if ((x = remtxt(&s)) < 0)
7625           return(x);
7626         if ((int)strlen(optbuf) > 94) { /* Make sure this is legal */
7627             printf("?Option string too long\n");
7628             return(-9);
7629         }
7630         ckstrncpy(optbuf,s,OPTBUFLEN);  /* Make a safe copy of options */
7631         nfils = -1;                     /* Expand file list internally */
7632         cmarg = line;                   /* Point to file list. */
7633         rprintf = 1;                    /* REMOTE PRINT modifier for SEND */
7634         sstate = 's';                   /* Set start state to SEND */
7635         if (local) displa = 1;
7636         retcode = 0;
7637         break;
7638 #endif /* NOFRILLS */
7639
7640       case XZSPA:                       /* Space */
7641         if ((x = cmtxt("Confirm, or remote directory name",
7642                        "",&s,xxstring)) < 0)
7643           return(x);
7644         if ((x = remtxt(&s)) < 0)
7645           return(x);
7646         retcode = sstate = setgen('U',s,"","");
7647         break;
7648
7649 #ifndef NOFRILLS
7650       case XZTYP:                       /* Type */
7651         if ((x = cmtxt("Remote file specification","",&s,xxstring)) < 0)
7652           return(x);
7653         if ((int)strlen(s) < 1) {
7654             printf("?Remote filename required\n");
7655             return(-9);
7656         }
7657         if ((x = remtxt(&s)) < 0)
7658           return(x);
7659         rmsg();
7660         retcode = sstate = rfilop(s,'T');
7661         break;
7662 #endif /* NOFRILLS */
7663
7664 #ifndef NOFRILLS
7665       case XZWHO:
7666         if ((x = cmtxt("Remote user name, or carriage return",
7667                        "",&s,xxstring)) < 0)
7668           return(x);
7669         if ((x = remtxt(&s)) < 0)
7670           return(x);
7671         retcode = sstate = setgen('W',s,"","");
7672         break;
7673 #endif /* NOFRILLS */
7674
7675       case XZPWD:                       /* PWD */
7676         if ((x = remcfm()) < 0) return(x);
7677         sstate = setgen('A',"","","");
7678         retcode = 0;
7679         break;
7680
7681 #ifndef NOSPL
7682       case XZQUE: {                     /* Query */
7683           char buf[2];
7684           extern char querybuf[], * qbufp;
7685           extern int qbufn;
7686           if ((y = cmkey(vartyp,nvartyp,"","",xxstring)) < 0)
7687             return(y);
7688           if ((x = cmtxt(y == 'F' ? "Remote function invocation" :
7689                          ('K' ? "Remote variable name or function":
7690                          "Remote variable name"),
7691                          "",
7692                          &s,
7693                          (y == 'K') ? xxstring : NULL
7694                          )) < 0)        /* Don't evaluate */
7695             return(x);
7696           if ((x = remtxt(&s)) < 0)
7697             return(x);
7698           query = 1;                    /* QUERY is active */
7699           qbufp = querybuf;             /* Initialize query response buffer */
7700           qbufn = 0;
7701           querybuf[0] = NUL;
7702           buf[0] = (char) (y & 127);
7703           buf[1] = NUL;
7704           retcode = sstate = setgen('V',"Q",(char *)buf,s);
7705           break;
7706       }
7707
7708       case XZASG: {                     /* Assign */
7709           char buf[VNAML];
7710           if ((y = cmfld("Remote variable name","",&s,NULL)) < 0) /* No eval */
7711             return(y);
7712           if ((int)strlen(s) >= VNAML) {
7713               printf("?Too long\n");
7714               return(-9);
7715           }
7716           ckstrncpy(buf,s,VNAML);
7717           if ((x = cmtxt("Assignment for remote variable",
7718                    "",&s,xxstring)) < 0) /* Evaluate this one */
7719             return(x);
7720           if ((x = remtxt(&s)) < 0)
7721             return(x);
7722 #ifdef COMMENT
7723 /*
7724   Server commands can't be long packets.  In principle there's no reason
7725   why they shouldn't be, except that we don't know at this point if the
7726   server is capable of accepting long packets because we haven't started
7727   the protocol yet.  In practice, allowing a long packet here breaks a lot
7728   of assumptions, causes buffer overruns and crashes, etc.  To be fixed
7729   later.  (But since this is commented out, evidently I fixed it later...)
7730 */
7731           if ((int)strlen(s) > 85) {    /* Allow for encoding expansion */
7732               printf("?Sorry, value is too long - 85 characters max\n");
7733               return(-9);
7734           }
7735 #endif /* COMMENT */
7736           retcode = sstate = setgen('V',"S",(char *)buf,s);
7737           break;
7738       }
7739 #endif /* NOSPL */
7740
7741       case XZCPY: {                     /* COPY */
7742           char buf[TMPBUFSIZ];
7743           buf[TMPBUFSIZ-1] = '\0';
7744           if ((x = cmfld("Name of remote file to copy","",&s,xxstring)) < 0) {
7745               if (x == -3) {
7746                   printf("?Name of remote file required\n");
7747                   return(-9);
7748               }
7749               else
7750                 return(x);
7751           }
7752           ckstrncpy(buf,s,TMPBUFSIZ);
7753           if ((x = cmfld("Name of remote destination file or directory",
7754                          "",&s, xxstring)) < 0) {
7755               if (x == -3) {
7756                   printf("?Name of remote file or directory required\n");
7757                   return(-9);
7758               } else return(x);
7759           }
7760           ckstrncpy(tmpbuf,s,TMPBUFSIZ);
7761           if ((x = remcfm()) < 0)
7762             return(x);
7763           if (local) ttflui();          /* If local, flush tty input buffer */
7764           retcode = sstate = setgen('K',buf,tmpbuf,"");
7765           break;
7766       }
7767       case XZREN: {                     /* Rename */
7768           char buf[TMPBUFSIZ];
7769           buf[TMPBUFSIZ-1] = '\0';
7770           if ((x = cmfld("Name of remote file to rename",
7771                          "",&s,xxstring)) < 0) {
7772               if (x == -3) {
7773                   printf("?Name of remote file required\n");
7774                   return(-9);
7775               } else return(x);
7776           }
7777           ckstrncpy(buf,s,TMPBUFSIZ);
7778           if ((x = cmfld("New name of remote file","",&s, xxstring)) < 0) {
7779               if (x == -3) {
7780                   printf("?Name of remote file required\n");
7781                   return(-9);
7782               } else return(x);
7783           }
7784           ckstrncpy(tmpbuf,s,TMPBUFSIZ);
7785           if ((x = remcfm()) < 0)
7786             return(x);
7787           if (local) ttflui();          /* If local, flush device buffer */
7788           retcode = sstate = setgen('R',buf,tmpbuf,"");
7789           break;
7790       }
7791       case XZMKD:                       /* mkdir */
7792       case XZRMD:                       /* rmdir */
7793         if ((x = cmtxt((xx == XZMKD) ?
7794                        "Name of remote directory to create" :
7795                        "Name of remote directory to delete",
7796                        "",
7797                        &s,
7798                        xxstring
7799                        )) < 0) {
7800             if (x == -3) {
7801                 printf("?Name required\n");
7802                 return(-9);
7803             } else return(x);
7804         }
7805         if ((x = remtxt(&s)) < 0)
7806           return(x);
7807         if (local) ttflui();            /* If local, flush tty input buffer */
7808         retcode = sstate = rfilop(s, (char)(xx == XZMKD ? 'm' : 'd'));
7809         break;
7810
7811       case XZXIT:                       /* Exit */
7812         if ((x = remcfm()) < 0) return(x);
7813         sstate = setgen('X',"","","");
7814         retcode = 0;
7815         break;
7816
7817       default:
7818         if ((x = remcfm()) < 0) return(x);
7819         printf("?Not implemented - %s\n",cmdbuf);
7820         return(-2);
7821     }
7822     if (local && retcode > -1)          /* If local, flush tty input buffer */
7823       ttflui();
7824     return(retcode);
7825 }
7826
7827
7828 /*  R F I L O P  --  Remote File Operation  */
7829
7830 CHAR
7831 #ifdef CK_ANSIC
7832 rfilop(char * s, char t)
7833 #else
7834 rfilop(s,t) char *s, t;
7835 #endif /* CK_ANSIC */
7836 /* rfilop */ {
7837     if (*s == NUL) {
7838         printf("?File specification required\n");
7839         return((CHAR) 0);
7840     }
7841     debug(F111,"rfilop",s,t);
7842     return(setgen(t,s,"",""));
7843 }
7844 #endif /* NOXFER */
7845
7846 #ifdef ANYX25
7847 int
7848 setx25() {
7849     if ((y = cmkey(x25tab,nx25,"X.25 call options","",xxstring)) < 0)
7850       return(y);
7851     switch (y) {
7852       case XYUDAT:
7853         if ((z = cmkey(onoff,2,"X.25 call user data","",xxstring))
7854             < 0) return(z);
7855         if (z == 0) {
7856             if ((z = cmcfm()) < 0) return(z);
7857             cudata = 0;             /* disable call user data */
7858             return (success = 1);
7859         }
7860         if ((x = cmtxt("X.25 call user data string","",&s,xxstring)) < 0)
7861           return(x);
7862         if ((int)strlen(s) == 0) {
7863             return (-3);
7864         } else if ((int)strlen(s) > MAXCUDATA) {
7865             printf("?The length must be > 0 and <= %d\n",MAXCUDATA);
7866             return(-2);
7867         }
7868         if ((y = cmcfm()) < 0) return(y);
7869         ckstrncpy(udata,s,MAXCUDATA);
7870         cudata = 1;                     /* X.25 call user data specified */
7871         return (success = 1);
7872       case XYCLOS:
7873         if ((z = cmkey(onoff,2,"X.25 closed user group call","",xxstring))
7874             < 0) return(z);
7875         if (z == 0) {
7876             if ((z = cmcfm()) < 0) return(z);
7877             closgr = -1;                /* disable closed user group */
7878             return (success = 1);
7879         }
7880         if ((y = cmnum("0 <= cug index >= 99","",10,&x,xxstring)) < 0)
7881           return(y);
7882         if (x < 0 || x > 99) {
7883             printf("?The choices are 0 <= cug index >= 99\n");
7884             return(-2);
7885         }
7886         if ((y = cmcfm()) < 0) return(y);
7887         closgr = x;                     /* closed user group selected */
7888         return (success = 1);
7889
7890       case XYREVC:
7891         if((z = cmkey(onoff,2,"X.25 reverse charge call","",xxstring)) < 0)
7892           return(z);
7893         if ((x = cmcfm()) < 0) return(x);
7894         revcall = z;
7895         return (success = 1);
7896     }
7897 }
7898
7899 #ifndef IBMX25
7900 int
7901 setpadp() {
7902     if ((y = cmkey(padx3tab,npadx3,"PAD X.3 parameter name","",xxstring)) < 0)
7903       return(y);
7904     x = y;
7905     switch (x) {
7906       case PAD_BREAK_CHARACTER:
7907         if ((y = cmnum("PAD break character value","",10,&z,xxstring)) < 0)
7908           return(y);
7909         if ((y = cmcfm()) < 0) return(y);
7910         break;
7911       case PAD_ESCAPE:
7912         if ((y = cmnum("PAD escape","",10,&z,xxstring)) < 0) return(y);
7913         if (z != 0 && z != 1) {
7914             printf("?The choices are 0 or 1\n");
7915             return(-2);
7916         }
7917         if ((y = cmcfm()) < 0) return(y);
7918         break;
7919       case PAD_ECHO:
7920         if ((y = cmnum("PAD echo","",10,&z,xxstring)) < 0) return(y);
7921         if (z != 0 && z != 1) {
7922             printf("?The choices are 0 or 1\n");
7923             return(-2);
7924         }
7925         if ((y = cmcfm()) < 0) return(y);
7926         break;
7927       case PAD_DATA_FORWARD_CHAR:
7928         if ((y = cmnum("PAD data forward char","",10,&z,xxstring)) < 0)
7929           return(y);
7930         if (z != 0 && z != 2) {
7931             printf("?The choices are 0 or 2\n");
7932             return(-2);
7933         }
7934         if ((y = cmcfm()) < 0) return(y);
7935         break;
7936       case PAD_DATA_FORWARD_TIMEOUT:
7937         if ((y = cmnum("PAD data forward timeout","",10,&z,xxstring)) < 0)
7938             return(y);
7939         if (z < 0 || z > 255) {
7940             printf("?The choices are 0 or 1 <= timeout <= 255\n");
7941             return(-2);
7942         }
7943         if ((y = cmcfm()) < 0) return(y);
7944         break;
7945       case PAD_FLOW_CONTROL_BY_PAD:
7946         if ((y = cmnum("PAD pad flow control","",10,&z,xxstring)) < 0)
7947           return(y);
7948         if (z != 0 && z != 1) {
7949             printf("?The choices are 0 or 1\n");
7950             return(-2);
7951         }
7952         if ((y = cmcfm()) < 0) return(y);
7953         break;
7954       case PAD_SUPPRESSION_OF_SIGNALS:
7955         if ((y = cmnum("PAD service","",10,&z,xxstring)) < 0) return(y);
7956         if (z != 0 && z != 1) {
7957             printf("?The choices are 0 or 1\n");
7958             return(-2);
7959         }
7960         if ((y = cmcfm()) < 0) return(y);
7961         break;
7962
7963       case PAD_BREAK_ACTION:
7964         if ((y = cmnum("PAD break action","",10,&z,xxstring)) < 0) return(y);
7965         if (z != 0 && z != 1 && z != 2 && z != 5 && z != 8 && z != 21) {
7966             printf("?The choices are 0, 1, 2, 5, 8 or 21\n");
7967             return(-2);
7968         }
7969         if ((y = cmcfm()) < 0) return(y);
7970         break;
7971
7972       case PAD_SUPPRESSION_OF_DATA:
7973         if ((y = cmnum("PAD data delivery","",10,&z,xxstring)) < 0) return(y);
7974         if (z != 0 && z != 1) {
7975             printf("?The choices are 0 or 1\n");
7976             return(-2);
7977         }
7978         if ((y = cmcfm()) < 0) return(y);
7979         break;
7980
7981       case PAD_PADDING_AFTER_CR:
7982         if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
7983         if (z < 0 || z > 7) {
7984             printf("?The choices are 0 or 1 <= crpad <= 7\n");
7985             return(-2);
7986         }
7987         if ((y = cmcfm()) < 0) return(y);
7988         break;
7989
7990       case PAD_LINE_FOLDING:
7991         if ((y = cmnum("PAD linefold","",10,&z,xxstring)) < 0) return(y);
7992         if (z < 0 || z > 255) {
7993             printf("?The choices are 0 or 1 <= linefold <= 255\n");
7994             return(-2);
7995         }
7996         if ((y = cmcfm()) < 0) return(y);
7997         break;
7998
7999       case PAD_LINE_SPEED:
8000         if ((y = cmnum("PAD baudrate","",10,&z,xxstring)) < 0) return(y);
8001         if (z < 0 || z > 18) {
8002             printf("?The choices are 0 <= baudrate <= 18\n");
8003             return(-2);
8004         }
8005         if ((y = cmcfm()) < 0) return(y);
8006         break;
8007
8008       case PAD_FLOW_CONTROL_BY_USER:
8009         if ((y = cmnum("PAD terminal flow control","",10,&z,xxstring)) < 0)
8010             return(y);
8011         if (z != 0 && z != 1) {
8012             printf("?The choices are 0 or 1\n");
8013             return(-2);
8014         }
8015         if ((y = cmcfm()) < 0) return(y);
8016         break;
8017
8018       case PAD_LF_AFTER_CR:
8019         if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
8020         if (z < 0 || z == 3 || z > 7) {
8021             printf("?The choices are 0, 1, 2, 4, 5, 6 or 7\n");
8022             return(-2);
8023         }
8024         if ((y = cmcfm()) < 0) return(y);
8025         break;
8026
8027       case PAD_PADDING_AFTER_LF:
8028         if ((y = cmnum("PAD lfpad","",10,&z,xxstring)) < 0) return(y);
8029         if (z < 0 || z > 7) {
8030             printf("?The choices are 0 or 1 <= lfpad <= 7\n");
8031             return(-2);
8032         }
8033         if ((y = cmcfm()) < 0) return(y);
8034         break;
8035
8036       case PAD_EDITING:
8037         if ((y = cmnum("PAD edit control","",10,&z,xxstring)) < 0) return(y);
8038         if (z != 0 && z != 1) {
8039             printf("?The choices are 0 or 1\n");
8040             return(-2);
8041         }
8042         if ((y = cmcfm()) < 0) return(y);
8043         break;
8044
8045       case PAD_CHAR_DELETE_CHAR:
8046         if ((y = cmnum("PAD char delete char","",10,&z,xxstring)) < 0)
8047             return(y);
8048         if (z < 0 || z > 127) {
8049             printf("?The choices are 0 or 1 <= chardelete <= 127\n");
8050             return(-2);
8051         }
8052         if ((y = cmcfm()) < 0) return(y);
8053         break;
8054
8055       case PAD_BUFFER_DELETE_CHAR:
8056         if ((y = cmnum("PAD buffer delete char","",10,&z,xxstring)) < 0)
8057             return(y);
8058         if (z < 0 || z > 127) {
8059             printf("?The choices are 0 or 1 <= bufferdelete <= 127\n");
8060             return(-2);
8061         }
8062         if ((y = cmcfm()) < 0) return(y);
8063         break;
8064
8065       case PAD_BUFFER_DISPLAY_CHAR:
8066         if ((y = cmnum("PAD display line char","",10,&z,xxstring)) < 0)
8067             return(y);
8068         if (z < 0 || z > 127) {
8069             printf("?The choices are 0 or 1 <= displayline <= 127\n");
8070             return(-2);
8071         }
8072         if ((y = cmcfm()) < 0) return(y);
8073         break;
8074     }
8075     padparms[x] = z;
8076     return(success = 1);
8077 }
8078 #endif /* IBMX25 */
8079 #endif /* ANYX25 */
8080
8081 #ifndef NOXFER
8082 int
8083 setat(rmsflg) int rmsflg; {
8084     int xx;
8085     if ((y = cmkey(attrtab,natr,"File Attribute packets","",xxstring)) < 0)
8086       return(y);
8087     if (y == AT_XALL) {                 /* ATTRIBUTES ALL ON or ALL OFF */
8088         if ((z = seton(&xx)) < 0) return(z);
8089         if (rmsflg) {
8090             printf("Sorry, command not available\n");
8091             return(-9);
8092         } else {
8093             atenci = xx;                /* Encoding in */
8094             atenco = xx;                /* Encoding out */
8095             atdati = xx;                /* Date in */
8096             atdato = xx;                /* Date out */
8097             atdisi = xx;                /* Disposition in/out */
8098             atdiso = xx;
8099             atleni = xx;                /* Length in/out (both kinds) */
8100             atleno = xx;
8101             atblki = xx;                /* Blocksize in/out */
8102             atblko = xx;
8103             attypi = xx;                /* File type in/out */
8104             attypo = xx;
8105             atsidi = xx;                /* System ID in/out */
8106             atsido = xx;
8107             atsysi = xx;                /* System-dependent params in/out */
8108             atsyso = xx;
8109 #ifdef CK_PERMS                         /* Protection */
8110             atlpri = xx;                /* Local in */
8111             atlpro = xx;                /* Local out */
8112             atgpri = xx;                /* Generic in */
8113             atgpro = xx;                /* Generic out */
8114 #endif /* CK_PERMS */
8115 #ifdef STRATUS
8116             atfrmi = xx;                /* Format in/out */
8117             atfrmo = xx;
8118             atcrei = xx;                /* Creator id in/out */
8119             atcreo = xx;
8120             atacti = xx;                /* Account in/out */
8121             atacto = xx;
8122 #endif /* STRATUS */
8123         }
8124         return(z);
8125     } else if (y == AT_ALLY || y == AT_ALLN) { /* ATTRIBUTES ON or OFF */
8126         if ((x = cmcfm()) < 0) return(x);
8127         atcapr = (y == AT_ALLY) ? 1 : 0;
8128         if (rmsflg) {
8129             sstate = setgen('S', "132", atcapr ? "1" : "0", "");
8130             return((int) sstate);
8131         } else return(success = 1);
8132     }
8133     /* Otherwise, it's an individual attribute that wants turning off/on */
8134
8135     if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
8136     if ((x = cmcfm()) < 0) return(x);
8137
8138 /* There are better ways to do this... */
8139 /* The real problem is that we're not separating the in and out cases */
8140 /* and so we have to arbitrarily pick the "in" case, i.e tell the remote */
8141 /* server to ignore incoming attributes of the specified type, rather */
8142 /* than telling it not to send them.  The protocol does not (yet) define */
8143 /* codes for "in-and-out-at-the-same-time". */
8144
8145     switch (y) {
8146 #ifdef CK_PERMS
8147 /* We're lumping local and generic protection together for now... */
8148       case AT_LPRO:
8149       case AT_GPRO:
8150         if (rmsflg) {
8151             sstate = setgen('S', "143", z ? "1" : "0", "");
8152             return((int) sstate);
8153         }
8154         atlpri = atlpro = atgpri = atgpro = z; break;
8155 #endif /* CK_PERMS */
8156       case AT_DISP:
8157         if (rmsflg) {
8158             sstate = setgen('S', "142", z ? "1" : "0", "");
8159             return((int) sstate);
8160         }
8161         atdisi = atdiso = z; break;
8162       case AT_ENCO:
8163         if (rmsflg) {
8164             sstate = setgen('S', "141", z ? "1" : "0", "");
8165             return((int) sstate);
8166         }
8167         atenci = atenco = z; break;
8168       case AT_DATE:
8169         if (rmsflg) {
8170             sstate = setgen('S', "135", z ? "1" : "0", "");
8171             return((int) sstate);
8172         }
8173         atdati = atdato = z; break;
8174       case AT_LENB:
8175       case AT_LENK:
8176         if (rmsflg) {
8177             sstate = setgen('S', "133", z ? "1" : "0", "");
8178             return((int) sstate);
8179         }
8180         atleni = atleno = z; break;
8181       case AT_BLKS:
8182         if (rmsflg) {
8183             sstate = setgen('S', "139", z ? "1" : "0", "");
8184             return((int) sstate);
8185         }
8186         atblki = atblko = z; break;
8187       case AT_FTYP:
8188         if (rmsflg) {
8189             sstate = setgen('S', "134", z ? "1" : "0", "");
8190             return((int) sstate);
8191         }
8192         attypi = attypo = z; break;
8193 #ifdef STRATUS
8194       case AT_CREA:
8195         if (rmsflg) {
8196             sstate = setgen('S', "136", z ? "1" : "0", "");
8197             return((int) sstate);
8198         }
8199         atcrei = atcreo = z; break;
8200       case AT_ACCT:
8201         if (rmsflg) {
8202             sstate = setgen('S', "137", z ? "1" : "0", "");
8203             return((int) sstate);
8204         }
8205         atacti = atacto = z; break;
8206 #endif /* STRATUS */
8207       case AT_SYSI:
8208         if (rmsflg) {
8209             sstate = setgen('S', "145", z ? "1" : "0", "");
8210             return((int) sstate);
8211         }
8212         atsidi = atsido = z; break;
8213       case AT_RECF:
8214         if (rmsflg) {
8215             sstate = setgen('S', "146", z ? "1" : "0", "");
8216             return((int) sstate);
8217         }
8218         atfrmi = atfrmo = z; break;
8219       case AT_SYSP:
8220         if (rmsflg) {
8221             sstate = setgen('S', "147", z ? "1" : "0", "");
8222             return((int) sstate);
8223         }
8224         atsysi = atsyso = z; break;
8225       default:
8226         printf("?Not available\n");
8227         return(-2);
8228     }
8229     return(1);
8230 }
8231 #endif /* NOXFER */
8232
8233 #ifndef NOSPL
8234 int
8235 setinp() {
8236     if ((y = cmkey(inptab,ninp,"","",xxstring)) < 0) return(y);
8237     switch (y) {
8238 #ifdef OS2
8239       case IN_PAC:                      /* SET INPUT PACING */
8240         z = cmnum("milliseconds","0",10,&x,xxstring);
8241         return(setnum(&tt_inpacing,x,z,1000));
8242       case IN_TRM:                      /* SET INPUT TERMINAL */
8243         return(seton(&interm));
8244 #endif /* OS2 */
8245       case IN_DEF:                      /* SET INPUT DEFAULT-TIMEOUT */
8246         z = cmnum("Positive number","",10,&x,xxstring);
8247         return(setnum(&indef,x,z,94));
8248 #ifdef CKFLOAT
8249       case IN_SCA:                      /* SET INPUT SCALE-FACTOR */
8250         if ((x = cmfld("Number such as 2 or 0.5","1.0",&s, xxstring)) < 0)
8251           return(x);
8252         if (isfloat(s,0)) {             /* A floating-point number? */
8253             extern char * inpscale;
8254             inscale = floatval;         /* Yes, get its value */
8255             makestr(&inpscale,s);       /* Save it as \v(inscale) */
8256             return(success = 1);
8257         } else {
8258             return(-2);
8259         }
8260 #endif  /* CKFLOAT */
8261       case IN_TIM:                      /* SET INPUT TIMEOUT-ACTION */
8262         if ((z = cmkey(intimt,2,"","",xxstring)) < 0) return(z);
8263         if ((x = cmcfm()) < 0) return(x);
8264         intime[cmdlvl] = z;
8265         return(success = 1);
8266       case IN_CAS:                      /* SET INPUT CASE */
8267         if ((z = cmkey(incast,2,"","",xxstring)) < 0) return(z);
8268         if ((x = cmcfm()) < 0) return(x);
8269         inpcas[cmdlvl] = z;
8270         return(success = 1);
8271       case IN_ECH:                      /* SET INPUT ECHO */
8272         return(seton(&inecho));
8273       case IN_SIL:                      /* SET INPUT SILENCE */
8274         z = cmnum("Seconds of inactivity before INPUT fails","",10,&x,
8275                   xxstring);
8276         return(setnum(&insilence,x,z,-1));
8277
8278       case IN_BUF:                      /* SET INPUT BUFFER-SIZE */
8279         if ((z = cmnum("Number of bytes in INPUT buffer",
8280                        ckitoa(INPBUFSIZ),10,&x, xxstring)) < 0)
8281           return(z);
8282         if ((y = cmcfm()) < 0) return(y);
8283         inbufsize = 0;
8284         if (inpbuf) {
8285             free(inpbuf);
8286             inpbuf = NULL;
8287             inpbp = NULL;
8288         }
8289         if (!(s = (char *)malloc(x + 1)))
8290           return(0);
8291         inpbuf = s;
8292         inpbp = s;
8293         inbufsize = x;
8294         for (x = 0; x <= inbufsize; x++)
8295           inpbuf[x] = NUL;
8296         return(success = 1);
8297
8298 #ifdef CK_AUTODL
8299       case IN_ADL:                      /* AUTODOWNLOAD */
8300         return(seton(&inautodl));
8301 #endif /* CK_AUTODL */
8302
8303       case IN_CAN:                      /* SET INPUT INTERRUPTS */
8304         return(seton(&inintr));
8305     }
8306     return(0);
8307 }
8308 #endif /* NOSPL */
8309
8310 #ifdef NETCONN
8311 VOID
8312 ndreset() {
8313 #ifndef NODIAL                          /* This depends on DIAL... */
8314     int i=0, j=0;
8315     if (!ndinited)                      /* Don't free garbage... */
8316       return;
8317     for (i = 0; i < nhcount; i++) {     /* Clean out previous list */
8318         if (nh_p[i])
8319           free(nh_p[i]);
8320         nh_p[i] = NULL;
8321         if (nh_p2[i])
8322           free(nh_p2[i]);
8323         nh_p2[i] = NULL;
8324         for (j = 0; j < 4; j++) {
8325             if (nh_px[j][i])
8326               free(nh_px[j][i]);
8327             nh_px[j][i] = NULL;
8328         }
8329     }
8330 #endif /* NODIAL */
8331 }
8332
8333 VOID
8334 ndinit() {                              /* Net directory pointers */
8335 #ifndef NODIAL                          /* This depends on DIAL... */
8336     int i, j;
8337     if (ndinited++)                     /* Don't do this more than once. */
8338       return;
8339     for (i = 0; i < MAXDDIR; i++) {     /* Init all pointers to NULL */
8340         netdir[i] = NULL;
8341     }
8342     for (i = 0; i < MAXDNUMS; i++) {
8343         nh_p[i] = NULL;
8344         nh_p2[i] = NULL;
8345         for (j = 0; j < 4; j++)
8346           nh_px[j][i] = NULL;
8347     }
8348 #endif /* NODIAL */
8349 }
8350
8351 #ifndef NODIAL
8352 #ifdef NETCONN
8353 VOID                                    /* Get net defaults from environment */
8354 getnetenv() {
8355     char *p = NULL;
8356
8357     makestr(&p,getenv("K_NET_DIRECTORY")); /* Dialing directories */
8358     if (p) {
8359         int i;
8360         xwords(p,MAXDDIR,netdir,0);
8361         for (i = 0; i < MAXDDIR; i++) { /* Fill in any gaps... */
8362             if (!netdir[i+1])
8363               break;
8364             else
8365               netdir[i] = netdir[i+1];
8366             debug(F111,"netdir[i]",netdir[i],i);
8367         }
8368         nnetdir = i;
8369     }
8370 }
8371 #endif /* NETCONN */
8372 #endif /* NODIAL */
8373
8374 int
8375 #ifdef CK_ANSIC
8376 lunet(char *s)                          /* s = name to look up   */
8377 #else
8378 lunet(s) char *s;
8379 #endif /* CK_ANSIC */
8380 /* lunet */ {
8381 #ifndef NODIAL                          /* This depends on DIAL... */
8382     int n, n1, t, dd = 0;
8383     int ambiguous = 0;
8384     FILE * f;
8385     char *line = NULL;
8386     extern int dialdpy;
8387     int netdpy = dialdpy;
8388     char *info[8];
8389
8390     nhcount = 0;                        /* Set this before returning */
8391
8392     if (!s || nnetdir < 1)              /* Validate arguments */
8393       return(-1);
8394
8395     if (isdigit(*s) || *s == '*' || *s == '.')
8396       return(0);
8397
8398     if ((n1 = (int) strlen(s)) < 1)     /* Length of string to look up */
8399       return(-1);
8400
8401     if (!(line = malloc(1024)))         /* Allocate input buffer */
8402       return(-1);
8403
8404   lu_again:
8405     f = NULL;                           /* Network directory file descriptor */
8406     t = nhcount = 0;                    /* Match count */
8407     dd = 0;                             /* Directory counter */
8408
8409     dirline = 0;
8410     while (1) {                         /* We make one pass */
8411         if (!f) {                       /* Directory not open */
8412             if (dd >= nnetdir)          /* No directories left? */
8413               break;                    /* Done. */
8414             if ((f = fopen(netdir[dd],"r")) == NULL) { /* Open it */
8415                 perror(netdir[dd]);     /* Can't, print message saying why */
8416                 dd++;
8417                 continue;               /* But go on to next one. */
8418             }
8419             if (netdpy)
8420               printf("Opening %s...\n",netdir[dd]);
8421             dd++;
8422         }
8423         line[0] = NUL;
8424         if (getnct(line,1023,f,1) < 0) { /* Read a line */
8425             if (f) {                    /* f can be clobbered! */
8426                 fclose(f);              /* Close the file */
8427                 f = NULL;               /* Indicate next one needs opening */
8428             }
8429             continue;
8430         }
8431         if (!line[0])                   /* Empty line */
8432           continue;
8433
8434         xwords(line,7,info,0);          /* Parse it */
8435
8436         if (!info[1] || !info[2] || !info[3]) /* Required fields */
8437           continue;
8438         if (*info[1] == ';')            /* Full-line comment */
8439           continue;
8440         if ((n = (int) strlen(info[1])) < 1) /* Length of name-tag */
8441           continue;
8442         if (n < n1)                     /* Search name is longer */
8443           continue;                     /* Can't possibly match */
8444         if (ambiguous && n != n1)
8445           continue;
8446         if (ckstrcmp(s,info[1],n1,0))   /* Compare using length of */
8447           continue;                     /* search string s. */
8448
8449         /* Have a match */
8450
8451         makestr(&(nh_p[nhcount]), info[3]);    /* address */
8452         makestr(&(nh_p2[nhcount]),info[2]);    /* net type */
8453         makestr(&(nh_px[0][nhcount]),info[4]); /* net-specific stuff... */
8454         makestr(&(nh_px[1][nhcount]),info[5]);
8455         makestr(&(nh_px[2][nhcount]),info[6]);
8456         makestr(&(nh_px[3][nhcount]),info[7]);
8457
8458         nhcount++;                      /* Count this match */
8459         if (nhcount > MAXDNUMS) {       /* Watch out for too many */
8460             printf("Warning: %d matches found, %d max\n",
8461                    nhcount,
8462                    MAXDNUMS
8463                    );
8464             nhcount = MAXDNUMS;
8465             break;
8466         }
8467         if (nhcount == 1) {             /* First one - save entry name */
8468             if (n_name) {               /* Free the one from before if any */
8469                 free(n_name);
8470                 n_name = NULL;
8471             }
8472             if (!(n_name = (char *)malloc(n + 1))) { /* Allocate new storage */
8473                 printf("?memory allocation error - lunet:3\n");
8474                 if (line) {
8475                     free(line);
8476                     line = NULL;
8477                 }
8478                 nhcount = 0;
8479                 return(-1);
8480             }
8481             t = n;                      /* Remember its length */
8482             strcpy(n_name,info[1]);     /* safe */
8483         } else {                        /* Second or subsequent one */
8484             if ((int) strlen(info[1]) == t) /* Lengths compare */
8485               if (!ckstrcmp(n_name,info[1],t,0)) /* Caseless compare OK */
8486                 continue;
8487
8488             /* Name given by user matches entries with different names */
8489
8490             if (ambiguous)              /* Been here before */
8491               break;
8492
8493             ambiguous = 1;              /* Now an exact match is required */
8494             ndreset();                  /* Clear out previous list */
8495             goto lu_again;              /* Do it all over again. */
8496         }
8497     }
8498     if (line) {
8499         free(line);
8500         line = NULL;
8501     }
8502     if (nhcount == 0 && ambiguous)
8503       printf("?\"%s\" - ambiguous in network directory\n",s);
8504 #else
8505     nhcount = 0;
8506 #endif /* NODIAL */
8507     return(nhcount);
8508 }
8509 #endif /* NETCONN */
8510
8511 #ifndef NOLOCAL
8512 /*  C L S C O N N X  --  Close connection  */
8513
8514 int
8515 clsconnx(ask) int ask; {
8516     int x, rc = 0;
8517 #ifdef NEWFTP
8518     extern int ftpget, ftpisopen(), ftpbye();
8519     if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
8520       return(success = ftpbye());
8521 #endif /* NEWFTP */
8522     debug(F101,"clsconnx local","",local);
8523     if (local) {
8524         x = ask ? hupok(1) : 1;         /* Make sure it's OK to close */
8525         if (!x) {
8526             rc = -1;
8527             debug(F101,"clsconnx hupok says no","",rc);
8528             return(rc);
8529         }
8530         ttflui();                       /* Clear away buffered up junk */
8531 #ifndef NODIAL
8532 #ifdef OS2ONLY
8533 /* Don't hangup a line that is shared with the SLIP or PPP driver */
8534         if (!ttslip && !ttppp)
8535 #endif /* OS2ONLY */
8536           mdmhup();
8537 #endif /* NODIAL */
8538         if (network && msgflg)
8539           printf(" Closing connection\n");
8540         ttclos(0);                      /* Close old connection, if any */
8541         rc = 1;
8542         {
8543             extern int wasclosed, whyclosed;
8544             if (wasclosed) {
8545                 whyclosed = WC_CLOS;
8546 #ifndef NOSPL
8547                 if (nmac) {             /* Any macros defined? */
8548                     int k;              /* Yes */
8549                     /* printf("ON_CLOSE CLSCONNX\n"); */
8550                     wasclosed = 0;
8551                     k = mlook(mactab,"on_close",nmac);  /* Look this up */
8552                     if (k >= 0) {                       /* If found, */
8553                         if (dodo(k,ckitoa(whyclosed),0) > -1) /* set it up, */
8554                           parser(1);                    /* and execute it */
8555                     }
8556                 }
8557 #endif /* NOSPL */
8558                 whyclosed = WC_REMO;
8559                 wasclosed = 0;
8560             }
8561         }
8562     }
8563 #ifdef VMS                              /* Or maybe #ifndef UNIX? */
8564     else {                              /* Need to do this in VMS to */
8565         ttclos(0);                      /* free the tty channel number */
8566         rc = 1;                         /* obtained in ttopen() or else */
8567     }                                   /* subsequent ttopen's won't work */
8568 #endif /* VMS */
8569     dologend();
8570     haveline = 0;
8571     if (mdmtyp < 0) {                   /* Switching from net to async? */
8572         if (mdmsav > -1)                /* Restore modem type from last */
8573           mdmtyp = mdmsav;              /* SET MODEM command, if any. */
8574         else
8575           mdmtyp = 0;
8576         mdmsav = -1;
8577     }
8578     if (network)
8579       network = 0;
8580 #ifdef NETCONN
8581     if (oldplex > -1) {                 /* Restore previous duplex setting. */
8582         duplex = oldplex;
8583         oldplex = -1;
8584     }
8585 #endif /* NETCONN */
8586 #ifndef MAC
8587     ckstrncpy(ttname,dftty,TTNAMLEN);   /* Restore default communication */
8588 #endif /* MAC */
8589     local = dfloc;                      /* device and local/remote status */
8590     if (local) {
8591         cxtype = CXT_DIRECT;            /* Something reasonable */
8592         speed = ttgspd();               /* Get the current speed */
8593     } else {
8594         cxtype = CXT_REMOTE;
8595         speed = -1L;
8596     }
8597 #ifndef NOXFER
8598     if (xreliable > -1 && !setreliable) {
8599         reliable = xreliable;
8600         debug(F101,"clsconnx reliable A","",reliable);
8601     } else if (!setreliable) {
8602         reliable = SET_AUTO;
8603         debug(F101,"clsconnx reliable B","",reliable);
8604     }
8605 #endif /* NOXFER */
8606     setflow();                          /* Revert flow control */
8607     return(rc);
8608 }
8609
8610 int
8611 clskconnx(x) int x; {                   /* Close Kermit connection only */
8612     int t, rc;                          /* (not FTP) */
8613 #ifdef NEWFTP
8614     extern int ftpget;
8615     t = ftpget;
8616     ftpget = 0;
8617 #endif /* NEWFTP */
8618     rc = clsconnx(x);
8619 #ifdef NEWFTP
8620     ftpget = t;
8621 #endif /* NEWFTP */
8622     return(rc);
8623 }
8624
8625 /* May 2002: setlin() decomposition starts here ... */
8626
8627 #ifdef OS2
8628 #define SRVBUFSIZ PIPENAML
8629 #else /* OS2 */
8630 #define SRVBUFSIZ 63
8631 #endif /* OS2 */
8632 #define HOSTNAMLEN 15*65
8633
8634 int netsave = -1;
8635 static char * tmpstring = NULL;
8636 static char * tmpusrid = NULL;
8637
8638 #ifdef SSHCMD
8639 char * sshcmd = NULL;
8640 char * defsshcmd = "ssh -e none";
8641 #else
8642 #ifdef SSHBUILTIN
8643 char * sshrcmd = NULL;
8644 char * sshtmpcmd = NULL;
8645 #endif /* SSHBUILTIN */
8646 #endif /* SSHCMD */
8647
8648 /* c x _ f a i l  --  Common error exit routine for cx_net, cx_line */
8649
8650 int
8651 cx_fail(msg, text) int msg; char * text; {
8652     makestr(&slmsg,text);               /* For the record (or GUI) */
8653     if (msg)                            /* Not GUI, not quiet, etc */
8654       printf("?%s\n",text);             /* Print error message */
8655     slrestor();                         /* Restore LINE/HOST to known state */
8656     return(msg ? -9 : (success = 0));   /* Return appropriate code */
8657 }
8658
8659 #ifdef NETCONN
8660 /* c x _ n e t  --  Make a network connection */
8661
8662 /*
8663   Call with:
8664     net      = network type
8665     protocol = protocol type
8666     host     = string pointer to host name.
8667     svc      = string pointer to service or port on host.
8668     username = username for connection
8669     password = password for connection
8670     command  = command to execute
8671     param1   = Telnet: Authentication type
8672                SSH:    Version
8673     param2   = Telnet: Encryption type
8674                SSH:    Command as Subsystem
8675     param3   = Telnet: 1 to wait for negotiations, 0 otherwise
8676                SSH:    X11 Forwarding
8677     cx       = 1 to automatically enter Connect mode, 0 otherwise.
8678     sx       = 1 to automatically enter Server mode, 0 otherwise.
8679     flag     = if no host name given, 1 = close current connection, 0 = resume
8680     gui      = 1 if called from GUI dialog, 0 otherwise.
8681   Returns:
8682     1 on success
8683     0 on failure and no message printed, slmsg set to failure message.
8684    -9 on failure and message printed, ditto.
8685 */
8686 int
8687 #ifdef CK_ANSIC
8688 cx_net( int net, int protocol, char * xhost, char * svc, 
8689         char * username, char * password, char * command,
8690         int param1, int param2, int param3, int cx, int sx, int flag, int gui)
8691 #else /* CK_ANSIC */
8692 cx_net(net, protocol, xhost, svc,
8693        username, password, command,
8694        param1, param2, param3, cx, sx, flag, gui)
8695     char * xhost, * svc, * username, *password, *command; 
8696     int net, protocol, cx, sx, flag, param1, param2, param3, gui; 
8697 #endif /* CK_ANSIC */
8698 /* cx_net */ {
8699
8700     int i, n, x, msg;
8701     int _local = -1;
8702
8703     extern char pwbuf[], * g_pswd;
8704     extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
8705
8706     char srvbuf[SRVBUFSIZ+1];           /* Service */
8707     char hostbuf[HOSTNAMLEN];           /* Host buffer to manipulate */
8708     char hostname[HOSTNAMLEN];          /* Copy of host parameter */
8709     char * host = hostbuf;              /* Pointer to copy of host param */
8710
8711     if (!xhost) xhost = "";             /* Watch out for null pointers */
8712     if (!svc) svc = "";
8713     ckstrncpy(host,xhost,HOSTNAMLEN);   /* Avoid buffer confusion */
8714
8715     debug(F110,"cx_net host",host,0);
8716     debug(F111,"cx_net service",svc,SRVBUFSIZ);
8717     debug(F101,"cx_net network type","",net);
8718
8719     msg = (gui == 0) && msgflg;         /* Whether to print messages */
8720
8721 #ifndef NODIAL
8722     debug(F101,"cx_net nnetdir","",nnetdir);
8723     x = 0;                              /* Look up in network directory */
8724     if (*host == '=') {                 /* If number starts with = sign */
8725         host++;                         /* strip it */
8726         while (*host == SP) host++;     /* and any leading spaces */
8727         debug(F110,"cx_net host 2",host,0);
8728         nhcount = 0;
8729     } else if (*host) {                 /* We want to look it up. */
8730         if (nnetdir > 0)                /* If there is a directory... */
8731           x = lunet(host);              /* (sets nhcount) */
8732         else                            /* otherwise */
8733           nhcount = 0;                  /* we didn't find any there */
8734         if (x < 0)                      /* Internal error? */
8735           return(cx_fail(msg,"Network directory lookup error"));
8736         debug(F111,"cx_net lunet nhcount",host,nhcount);
8737     }
8738 #endif /* NODIAL */
8739
8740     /* New connection wanted.  Make a copy of the host name/address... */
8741
8742     if (clskconnx(1) < 0)               /* Close current Kermit connection */
8743       return(cx_fail(msg,"Error closing previous connection"));
8744
8745     if (*host) {                        /* They gave a hostname */
8746         _local = 1;                     /* Network connection always local */
8747         if (mdmsav < 0)
8748           mdmsav = mdmtyp;              /* Remember old modem type */
8749         mdmtyp = -net;                  /* Special code for network */
8750     } else {                            /* They just said "set host" */
8751         host = dftty;                   /* So go back to normal */
8752         _local = dfloc;                 /* default tty, location, */
8753         if (flag) {                     /* Close current connection */
8754             setflow();                  /* Maybe change flow control */
8755             haveline = 1;               /* (* is this right? *) */
8756             dologend();
8757 #ifndef NODIAL
8758             dialsta = DIA_UNK;
8759 #endif /* NODIAL */
8760 #ifdef LOCUS
8761             if (autolocus) {
8762                 setlocus(1,1);
8763             }
8764 #endif /* LOCUS */
8765             /* XXX - Is this right? */
8766             /* Should we be returning without doing anything ? */
8767             /* Yes it's right -- we closed the old connection just above. */
8768             return(success = 1);        
8769         }
8770     }
8771     success = 0;
8772     if (host != line)                   /* line[] is a global */
8773       ckstrncpy(line,host,LINBUFSIZ);
8774     ckstrncpy(hostname,host,HOSTNAMLEN);
8775     ckstrncpy(srvbuf,svc,SRVBUFSIZ+1);
8776
8777 #ifndef NODIAL
8778     if ((nhcount > 1) && msg) {
8779         int k;
8780         printf("%d entr%s found for \"%s\"%s\n",
8781                nhcount,
8782                (nhcount == 1) ? "y" : "ies",
8783                s,
8784                (nhcount > 0) ? ":" : "."
8785                );
8786         for (i = 0; i < nhcount; i++) {
8787                 printf("%3d. %-12s => %-9s %s",
8788                        i+1,n_name,nh_p2[i],nh_p[i]);
8789             for (k = 0; k < 4; k++) { /* Also list net-specific items */
8790                 if (nh_px[k][i])      /* free format... */
8791                   printf(" %s",nh_px[k][i]);
8792                 else
8793                   break;
8794             }
8795             printf("\n");
8796         }
8797     }
8798     if (nhcount == 0)
8799       n = 1;
8800     else
8801       n = nhcount;
8802 #else
8803     n = 1;
8804     nhcount = 0;
8805 #endif /* NODIAL */
8806
8807     for (i = 0; i < n; i++) {           /* Loop for each entry found */
8808         debug(F101,"cx_net loop i","",i);
8809 #ifndef NODIAL
8810         if (nhcount > 0) {              /* If we found at least one entry... */
8811             ckstrncpy(line,nh_p[i],LINBUFSIZ); /* Copy current entry */
8812             if (lookup(netcmd,nh_p2[i],nnets,&x) > -1) { /* Net type */
8813                 int xx;
8814                 xx = netcmd[x].kwval;
8815                 /* User specified SSH so don't let net directory override */
8816                 if (net != NET_SSH || xx != NET_TCPB) {
8817                     net = xx;
8818                     mdmtyp  = 0 - net;
8819                 }
8820             } else {
8821                 makestr(&slmsg,"Network type not supported");
8822                 if (msg)
8823                   printf("Error - network type \"%s\" not supported\n",
8824                          nh_p2[i]
8825                          );
8826                 continue;
8827             }
8828             switch (net) {              /* Net-specific directory things */
8829 #ifdef SSHBUILTIN
8830               case NET_SSH:             /* SSH */
8831                 /* Any SSH specific network directory stuff? */
8832                 break;                  /* NET_SSH */
8833 #endif /* SSHBUILTIN */
8834
8835               case NET_TCPB: {          /* TCP/IP TELNET,RLOGIN,... */
8836 #ifdef TCPSOCKET
8837                   char *q;
8838                   int flag = 0;
8839
8840                   /* Extract ":service", if any, from host string */
8841                   debug(F110,"cx_net service 1",line,0);
8842                   for (q = line; (*q != '\0') && (*q != ':'); q++)
8843                     ;
8844                   if (*q == ':') { *q++ = NUL; flag = 1; }
8845                   debug(F111,"cx_net service 2",line,flag);
8846
8847                   /* Get service, if any, from directory entry */
8848
8849                   if (!*srvbuf) {
8850                       if (nh_px[0][i]) {
8851                           ckstrncpy(srvbuf,nh_px[0][i],SRVBUFSIZ);
8852                           debug(F110,"cx_net service 3",srvbuf,0);
8853                       }
8854                       if (flag) {
8855                           ckstrncpy(srvbuf,q,SRVBUFSIZ);
8856                           debug(F110,"cx_net service 4",srvbuf,0);
8857                       }
8858                   }
8859                   ckstrncpy(hostname,line,HOSTNAMLEN);
8860
8861                   /* If we have a service, append to host name/address */
8862                   if (*srvbuf) {
8863                       ckstrncat(line, ":", LINBUFSIZ);
8864                       ckstrncat(line, srvbuf, LINBUFSIZ);
8865                       debug(F110,"cx_net service 5",line,0);
8866                   }
8867 #ifdef RLOGCODE
8868                   /* If no service given but command was RLOGIN */
8869                   else if (ttnproto == NP_RLOGIN) { /* add this... */
8870                       ckstrncat(line, ":login",LINBUFSIZ);
8871                       debug(F110,"cx_net service 6",line,0);
8872                   }
8873 #ifdef CK_AUTHENTICATION
8874 #ifdef CK_KERBEROS
8875                   else if (ttnproto == NP_K4LOGIN ||
8876                            ttnproto == NP_K5LOGIN) { /* add this... */
8877                       ckstrncat(line, ":klogin",LINBUFSIZ);
8878                       debug(F110,"cx_net service 7",line,0);
8879                   }
8880                   else if (ttnproto == NP_EK4LOGIN ||
8881                            ttnproto == NP_EK5LOGIN) { /* add this... */
8882                       ckstrncat(line, ":eklogin",LINBUFSIZ);
8883                       debug(F110,"cx_net service 8",line,0);
8884                   }
8885 #endif /* CK_KERBEROS */
8886 #endif /* CK_AUTHENTICATION */
8887 #endif /* RLOGCODE */
8888                   else {                /* Otherwise, add ":telnet". */
8889                       ckstrncat(line, ":telnet", LINBUFSIZ);
8890                       debug(F110,"cx_net service 9",line,0);
8891                   }
8892                   if (username) {       /* This is a parameter... */
8893                       ckstrncpy(uidbuf,username,UIDBUFLEN);
8894                       uidflag = 1;
8895                   }
8896                   /* Fifth field, if any, is user ID (for rlogin) */
8897
8898                   if (nh_px[1][i] && !uidflag)
8899                     ckstrncpy(uidbuf,username,UIDBUFLEN);
8900 #ifdef RLOGCODE
8901                   if (IS_RLOGIN() && !uidbuf[0])
8902                     return(cx_fail(msg,"Username required"));
8903 #endif /* RLOGCODE */
8904 #endif /* TCPSOCKET */
8905                   break;
8906               }
8907               case NET_PIPE:            /* Pipe */
8908 #ifdef NPIPE
8909                 if (!pipename[0]) { /* User didn't give a pipename */
8910                     if (nh_px[0][i]) { /* But directory entry has one */
8911                         if (strcmp(pipename,"\\pipe\\")) {
8912                             ckstrncpy(pipename,"\\pipe\\",LINBUFSIZ);
8913                             ckstrncat(srvbuf,nh_px[0][i],PIPENAML-6);
8914                         } else {
8915                             ckstrncpy(pipename,nh_px[0][i],PIPENAML);
8916                         }
8917                         debug(F110,"cx_net pipeneme",pipename,0);
8918                     }
8919                 }
8920 #endif /* NPIPE */
8921                 break;
8922
8923               case NET_SLAT:            /* LAT / CTERM */
8924 #ifdef SUPERLAT
8925                 if (!slat_pwd[0]) { /* User didn't give a password */
8926                     if (nh_px[0][i]) { /* But directory entry has one */
8927                         ckstrncpy(slat_pwd,nh_px[0][i],18);
8928                         debug(F110,"cx_net SuperLAT password",slat_pwd,0);
8929                     }
8930                 }
8931 #endif /* SUPERLAT */
8932                 break;
8933
8934               case NET_SX25:        /* X.25 keyword parameters */
8935               case NET_IX25:
8936               case NET_VX25: {
8937 #ifdef ANYX25
8938                   int k;            /* Cycle through the four fields */
8939                   for (k = 0; k < 4; k++) {
8940                       if (!nh_px[k][i]) /* Bail out if none left */
8941                         break;
8942                       if (!ckstrcmp(nh_px[k][i],"cug=",4,0)) {
8943                           closgr = atoi(nh_px[k][i]+4);
8944                           debug(F101,"X25 CUG","",closgr);
8945                       } else if (!ckstrcmp(nh_px[k][i],"cud=",4,0)) {
8946                           cudata = 1;
8947                           ckstrncpy(udata,nh_px[k][i]+4,MAXCUDATA);
8948                           debug(F110,"X25 CUD",cudata,0);
8949                       } else if (!ckstrcmp(nh_px[k][i],"rev=",4,0)) {
8950                           revcall = !ckstrcmp(nh_px[k][i]+4,"=on",3,0);
8951                           debug(F101,"X25 REV","",revcall);
8952 #ifndef IBMX25
8953                       } else if (!ckstrcmp(nh_px[k][i],"pad=",4,0)) {
8954                           int x3par, x3val;
8955                           char *s1, *s2;
8956                           s1 = s2 = nh_px[k][i]+4; /* PAD parameters */
8957                           while (*s2) {            /* Pick them apart */
8958                               if (*s2 == ':') {
8959                                   *s2 = NUL;
8960                                   x3par = atoi(s1);
8961                                   s1 = ++s2;
8962                                   continue;
8963                               } else if (*s2 == ',') {
8964                                   *s2 = NUL;
8965                                   x3val = atoi(s1);
8966                                   s1 = ++s2;
8967                                   debug(F111,"X25 PAD",x3par,x3val);
8968                                   if (x3par > -1 &&
8969                                       x3par <= MAXPADPARMS)
8970                                     padparms[x3par] = x3val;
8971                                   continue;
8972                               } else
8973                                 s2++;
8974                           }
8975 #endif /* IBMX25 */
8976                       }
8977                   }
8978 #endif /* ANYX25 */
8979                   break;
8980               }
8981               default:                  /* Nothing special for other nets */
8982                 break;
8983             }
8984         } else
8985 #endif /* NODIAL */
8986         {                               /* No directory entries found. */
8987             ckstrncpy(line,hostname,LINBUFSIZ); /* Put this back... */
8988             /* If the user gave a TCP service */
8989             if (net == NET_TCPB || net == NET_SSH)
8990               if (*srvbuf) {            /* Append it to host name/address */
8991                   ckstrncat(line, ":", LINBUFSIZ);
8992                   ckstrncat(line, srvbuf,LINBUFSIZ);
8993               }
8994         }
8995         /*
8996            Get here with host name/address and all net-specific
8997            parameters set, ready to open the connection.
8998         */
8999         mdmtyp = -net;                  /* This should have been done */
9000                                         /* already but just in case ... */
9001
9002         debug(F110,"cx_net net line[] before ttopen",line,0);
9003         debug(F101,"cx_net net mdmtyp before ttopen","",mdmtyp);
9004         debug(F101,"cx_net net ttnproto","",ttnproto);
9005
9006 #ifdef SSHBUILTIN
9007         if (net == NET_SSH) {
9008             makestr(&ssh_hst,hostname);        /* Stash everything */
9009             if (username) {
9010                 if (!sl_uid_saved) {
9011                     ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
9012                     sl_uid_saved = 1;
9013                 }
9014                 ckstrncpy(uidbuf,username,UIDBUFLEN);
9015             }
9016             if (srvbuf[0]) {
9017                 makestr(&ssh_prt,srvbuf);
9018             } else
9019                 makestr(&ssh_prt,NULL);
9020
9021             if (command) {
9022                 makestr(&ssh_cmd,brstrip(command));
9023                 ssh_cas = param2;
9024             } else
9025                 makestr(&ssh_cmd,NULL);
9026
9027             if (param1 > -1) {
9028 #ifndef SSHTEST
9029                 if (!sl_ssh_ver_saved) {
9030                     sl_ssh_ver = ssh_ver;
9031                     sl_ssh_ver_saved = 1;
9032                 }
9033 #endif /* SSHTEST */
9034                 ssh_ver = param1;
9035             }
9036             if (param3 > -1) {
9037 #ifndef SSHTEST
9038                 if (!sl_ssh_xfw_saved) {
9039                     sl_ssh_xfw = ssh_xfw;
9040                     sl_ssh_xfw_saved = 1;
9041                 }
9042 #endif /* SSHTEST */
9043                 ssh_xfw = param3;
9044             }
9045         } else                          /* NET_SSH */
9046 #endif /* SSHBUILTIN */
9047 #ifdef TCPSOCKET
9048           if (net == NET_TCPB) {
9049             switch (protocol) {
9050 #ifdef CK_SSL
9051               case NP_SSL:
9052                 ttnproto = protocol;
9053                 ssl_only_flag = 1;
9054                 tls_only_flag = 0;
9055                 break;
9056
9057               case NP_TLS:
9058                 ttnproto = protocol;
9059                 ssl_only_flag = 0;
9060                 tls_only_flag = 1;
9061                 break;
9062
9063               case NP_SSL_TELNET:
9064                 ttnproto = NP_TELNET;
9065                 ssl_only_flag = 1;
9066                 tls_only_flag = 0;
9067                 break;
9068
9069               case NP_TLS_TELNET:
9070                 ttnproto = NP_TELNET;
9071                 ssl_only_flag = 0;
9072                 tls_only_flag = 1;
9073                 break;
9074 #endif /* CK_SSL */
9075               case NP_NONE:
9076               case NP_TCPRAW:
9077               case NP_RLOGIN:
9078               case NP_K4LOGIN:
9079               case NP_K5LOGIN:
9080               case NP_EK4LOGIN:
9081               case NP_EK5LOGIN:
9082               case NP_TELNET:
9083               case NP_KERMIT:
9084               default:
9085                 ttnproto = protocol;
9086 #ifdef CK_SSL
9087                 ssl_only_flag = 0;
9088                 tls_only_flag = 0;
9089 #endif /* CK_SSL */
9090                 break;
9091             }
9092 #ifdef CK_AUTHENTICATION
9093             if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9094                 param1 > -1) {
9095             if (!sl_auth_saved) {
9096                 int x;
9097                 for (x = 0; x < AUTHTYPLSTSZ; x++)
9098                   sl_auth_type_user[x] = auth_type_user[x];
9099                 sl_auth_saved = 1;
9100             }
9101             if (!sl_topt_a_s_saved) {
9102                 sl_topt_a_su = TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION);
9103                 sl_topt_a_s_saved = 1;
9104             }
9105             if (!sl_topt_a_c_saved) {
9106                 sl_topt_a_cm = TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION);
9107                 sl_topt_a_c_saved = 1;
9108             }
9109             switch (param1) {
9110               case AUTHTYPE_AUTO:
9111                 auth_type_user[0] = AUTHTYPE_AUTO;
9112                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
9113                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
9114                 break;
9115               case AUTHTYPE_NULL:
9116                 auth_type_user[0] = AUTHTYPE_NULL;
9117                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
9118                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
9119                 break;
9120 #ifdef CK_SRP
9121               case AUTHTYPE_SRP:
9122                 auth_type_user[0] = AUTHTYPE_SRP;
9123                 auth_type_user[1] = AUTHTYPE_NULL;
9124                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9125                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9126                 break;
9127 #endif /* CK_SRP */
9128 #ifdef CK_SSL
9129               case AUTHTYPE_SSL:
9130                 auth_type_user[0] = AUTHTYPE_SSL;
9131                 auth_type_user[1] = AUTHTYPE_NULL;
9132                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9133                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9134                 break;
9135 #endif /* CK_SSL */
9136 #ifdef NT
9137               case AUTHTYPE_NTLM:
9138                 auth_type_user[0] = AUTHTYPE_NTLM;
9139                 auth_type_user[1] = AUTHTYPE_NULL;
9140                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9141                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9142                 break;
9143 #endif /* NT */
9144 #ifdef CK_KERBEROS
9145               case AUTHTYPE_KERBEROS_V4:
9146                 auth_type_user[0] = AUTHTYPE_KERBEROS_V4;
9147                 auth_type_user[1] = AUTHTYPE_NULL;
9148                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9149                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9150                 break;
9151
9152               case AUTHTYPE_KERBEROS_V5:
9153                 auth_type_user[0] = AUTHTYPE_KERBEROS_V5;
9154                 auth_type_user[1] = AUTHTYPE_NULL;
9155                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9156                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9157                 break;
9158 #endif /* CK_KERBEROS */
9159             }
9160         }
9161         /*
9162            If the user requires a particular type of Kerberos connection,
9163            make sure we have a valid TGT.
9164         */
9165         makestr(&slmsg,"Authentication failure");
9166         if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9167             (line[0] == '*' &&
9168              TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_MU ||
9169              line[0] != '*' &&
9170              TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_MU)
9171             ) {
9172 #ifdef CK_KERBEROS
9173             if ( auth_type_user[0] == AUTHTYPE_KERBEROS_V4 ) {
9174                 extern int krb4_autoget;
9175                 if (!ck_krb4_is_installed())
9176                   return(cx_fail(msg,
9177               "Required authentication method (Kerberos 4) is not installed"));
9178 #ifdef COMMENT
9179                 /* This code results in false failures when using */
9180                 /* kerberos to machines in realms other than the  */
9181                 /* default since we don't know the realm of the   */
9182                 /* other machine until perform the reverse DNS    */
9183                 /* lookup.                                        */
9184                 else if (line[0] != '*' && !ck_krb4_is_tgt_valid() &&
9185                            (!krb4_autoget ||
9186                             krb4_autoget && !ck_krb4_autoget_TGT(NULL))) {
9187                     return(cx_fail(msg,
9188                            "Kerberos 4: Ticket Getting Ticket not valid"));
9189                 }
9190 #endif /* COMMENT */
9191             } else if (auth_type_user[0] == AUTHTYPE_KERBEROS_V5) {
9192                 extern int krb5_autoget;
9193                 if (!ck_krb5_is_installed()) {
9194                     return(cx_fail(msg,
9195            "Required authentication method (Kerberos 5) is not installed"));
9196                 }
9197 #ifdef COMMENT
9198                 /* This code results in false failures when using */
9199                 /* kerberos to machines in realms other than the  */
9200                 /* default since we don't know the realm of the   */
9201                 /* other machine until perform the reverse DNS    */
9202                 /* lookup.                                        */
9203                 else if (line[0] != '*' && !ck_krb5_is_tgt_valid() &&
9204                            (!krb5_autoget ||
9205                             krb5_autoget && !ck_krb5_autoget_TGT(NULL))) {
9206                     return(cx_fail(msg,
9207                          "Kerberos 5: Ticket Getting Ticket not valid."));
9208                 }
9209 #endif /* COMMENT */
9210             }
9211 #endif /* CK_KERBEROS */
9212 #ifdef NT
9213             if (auth_type_user[0] == AUTHTYPE_NTLM) {
9214                 if (!ck_ntlm_is_installed()) {
9215                     return(cx_fail(msg,
9216                    "Required authentication method (NTLM) is not installed"));
9217                 } else if (line[0] != '*' && !ck_ntlm_is_valid(0)) {
9218                     return(cx_fail(msg,"NTLM: Credentials are unavailable."));
9219                 }
9220             }
9221 #endif /* NT */
9222 #ifdef CK_SSL
9223             if (auth_type_user[0] == AUTHTYPE_SSL) {
9224                 if (!ck_ssleay_is_installed()) {
9225                     return(cx_fail(msg,
9226                      "Required authentication method (SSL) is not installed"));
9227                 }
9228             }
9229 #endif /* CK_SSL */
9230 #ifdef CK_SRP
9231             if (auth_type_user[0] == AUTHTYPE_SRP) {
9232                 if (!ck_srp_is_installed()) {
9233                     return(cx_fail(msg,
9234                      "Required authentication method (SRP) is not installed"));
9235                 }
9236             }
9237 #endif /* CK_SRP */
9238         }
9239 #endif /* CK_AUTHENTICATION */
9240 #ifdef CK_ENCRYPTION
9241         if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9242              param2 > -1) {
9243             if (!sl_cx_saved) {
9244                 sl_cx_type = cx_type;
9245                 sl_cx_saved = 1;
9246             }
9247             if (!sl_topt_e_s_saved) {
9248                 sl_topt_e_su = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
9249                 sl_topt_e_sm = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
9250                 sl_topt_e_s_saved = 1;
9251             }
9252             if (!sl_topt_e_c_saved) {
9253                 sl_topt_e_cu = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
9254                 sl_topt_e_cm = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
9255                 sl_topt_e_c_saved = 1;
9256             }
9257             cx_type = param2;
9258             if (cx_type == CX_AUTO) {
9259                 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9260                 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9261                 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9262                 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9263             } else if (cx_type == CX_NONE) {
9264                 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9265                 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9266                 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9267                 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9268             } else {
9269                 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9270                 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9271                 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9272                 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9273             }
9274         }
9275         if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN ||
9276             (ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9277             ((line[0] == '*' &&
9278               TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) == TN_NG_MU &&
9279               TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_MU) ||
9280              (line[0] != '*' &&
9281               TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) == TN_NG_MU &&
9282               TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_MU))
9283             ) {
9284             if (!ck_crypt_is_installed()) {
9285                 return(cx_fail(msg,
9286                   "Required Encryption methods are not installed"));
9287             }
9288         }
9289 #endif /* CK_ENCRYPTION */
9290 #ifdef RLOGCODE
9291 #ifdef CK_KERBEROS
9292 #ifdef KRB4
9293         if (ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN) {
9294             extern int krb4_autoget;
9295             char tgt[256];
9296             char * realm;
9297
9298             /* We don't have the full hostname at yet so  */
9299             /* we do a DNS lookup before calling ttopen() */ 
9300
9301             realm = ck_krb4_realmofhost(ckgetfqhostname(hostname));
9302             ckmakmsg(tgt,256,"krbtgt.",realm,"@",realm);
9303             if (!ck_krb4_is_installed()) {
9304                 return(cx_fail(msg,
9305                  "Required authentication method (Kerberos 4) is not installed"
9306                                ));
9307             } else {
9308                 if ((ck_krb4_tkt_isvalid(tgt) <= 0) &&
9309                     (!krb4_autoget ||
9310                      krb4_autoget && !ck_krb4_autoget_TGT(realm))) {
9311                     return(cx_fail(msg,
9312                            "Kerberos 4: Ticket Getting Ticket not valid"));
9313                 }
9314             }
9315         }
9316 #endif /* KRB4 */
9317 #ifdef KRB5
9318         if (ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN ||
9319             ttnproto == NP_K5U2U)
9320         {
9321             extern int krb5_autoget;
9322             char tgt[256];
9323             char * realm;
9324
9325             /* Must get full hostname before calling ttopen() */
9326
9327             realm = ck_krb5_realmofhost(ckgetfqhostname(hostname));
9328             ckmakmsg(tgt,256,"krbtgt/",realm,"@",realm);
9329
9330             if (!ck_krb5_is_installed()) {
9331                 return(cx_fail(msg,
9332                  "Required authentication method (Kerberos 5) not installed"));
9333             } else if (!((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
9334                           ck_krb5_is_tgt_valid()) &&
9335                        (!krb5_autoget ||
9336                         krb5_autoget && !ck_krb5_autoget_TGT(realm))) {
9337                 return(cx_fail(msg,
9338                        "Kerberos 5: Ticket Getting Ticket not valid."));
9339             }
9340         }
9341 #endif /* KRB5 */
9342 #endif /* CK_KERBEROS */
9343 #endif /* RLOGCODE */
9344
9345 #ifndef NOSPL
9346 #ifdef RLOGCODE
9347         if (username) {
9348             if (!sl_uid_saved) {
9349                 ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
9350                 sl_uid_saved = 1;
9351             }
9352             ckstrncpy(uidbuf,username,UIDBUFLEN);
9353             uidflag = 1;
9354         }
9355 #endif /* RLOGCODE */
9356 #ifdef TNCODE
9357         if (!sl_tn_saved) {
9358             sl_tn_wait = tn_wait_flg;
9359             sl_tn_saved = 1;
9360         }
9361         tn_wait_flg = param3;
9362 #endif /* TNCODE */
9363 #endif /* NOSPL */
9364         } /* if (net == NET_TCPB) */
9365 #endif /* TCPSOCKET */
9366
9367 #ifndef NOSPL
9368 #ifdef CK_SECURITY
9369         if (password) {
9370             if (password[0]) {
9371                 ckstrncpy(pwbuf,password,PWBUFL+1);
9372                 pwflg = 1;
9373                 pwcrypt = 0;
9374             } else
9375                 pwflg = 0;
9376         }
9377 #endif /* CK_SECURITY */
9378 #endif /* NOSPL */
9379
9380         /* Try to open - network */
9381         ckstrncpy(ttname,line,TTNAMLEN);
9382         y = ttopen(line, &_local, mdmtyp, 0 );
9383
9384 #ifndef NOHTTP
9385         /*  If the connection failed and we are using an HTTP Proxy
9386          *  and the reason for the failure was an authentication
9387          *  error, then we need to give the user to ability to
9388          *  enter a username and password, just like a browser.
9389          *
9390          *  I tried to do all of this within the netopen() call
9391          *  but it is much too much work.
9392          */
9393         while (y < 0 && tcp_http_proxy != NULL ) {
9394
9395             if (tcp_http_proxy_errno == 401 ||
9396                 tcp_http_proxy_errno == 407 ) {
9397                 char uid[UIDBUFLEN];
9398                 char pwd[256];
9399                 struct txtbox tb[2];
9400                 int ok;
9401
9402                 tb[0].t_buf = uid;
9403                 tb[0].t_len = UIDBUFLEN;
9404                 tb[0].t_lbl = "Proxy Userid: ";
9405                 tb[0].t_dflt = NULL;
9406                 tb[0].t_echo = 1;
9407                 tb[1].t_buf = pwd;
9408                 tb[1].t_len = 256;
9409                 tb[1].t_lbl = "Proxy Passphrase: ";
9410                 tb[1].t_dflt = NULL;
9411                 tb[1].t_echo = 2;
9412
9413                 ok = uq_mtxt("Proxy Server Authentication Required\n",
9414                               NULL, 2, tb);
9415
9416                 if (ok && uid[0]) {
9417                     char * proxy_user, * proxy_pwd;
9418
9419                     proxy_user = tcp_http_proxy_user;
9420                     proxy_pwd  = tcp_http_proxy_pwd;
9421
9422                     tcp_http_proxy_user = uid;
9423                     tcp_http_proxy_pwd = pwd;
9424
9425                     ckstrncpy(ttname,line,TTNAMLEN);
9426                     y = ttopen(line, &_local, mdmtyp, 0);
9427                     memset(pwd,0,sizeof(pwd));
9428                     tcp_http_proxy_user = proxy_user;
9429                     tcp_http_proxy_pwd = proxy_pwd;
9430                 } else
9431                   break;
9432             } else
9433               break;
9434         }
9435 #endif /* NOHTTP */
9436         if (y < 0) {
9437             slrestor();
9438             makestr(&slmsg,"Network connection failure");
9439 #ifdef VMS
9440             if (msg && hints && !xcmdsrc && IS_RLOGIN()) {
9441                 makestr(&slmsg,"RLOGIN failure");
9442                 if  (socket_errno == EACCES) {
9443                     printf("*************************\n");
9444                     printf(
9445            "Hint: RLOGIN requires privileges to open an outbound port.\n");
9446                     printf(
9447                     "(Use SET HINTS OFF to suppress future hints.)\n");
9448                     printf("*************************\n");
9449                 }
9450             }
9451 #else  /* Not VMS... */
9452             if (errno) {
9453                 int x;
9454                 debug(F111,"set host line, errno","",errno);
9455                 makestr(&slmsg,ck_errstr());
9456                 if (msg) {
9457 #ifdef OS2
9458                     printf("Can't connect to %s\n",line);
9459 #else /* OS2 */
9460 #ifdef UNIX
9461                     if (hints && !xcmdsrc && IS_RLOGIN()) {
9462                         makestr(&slmsg,"RLOGIN failure");
9463                         printf("*************************\n");
9464                         printf(
9465          "Hint: RLOGIN requires privileges to open an outbound port.\n");
9466                         printf(
9467          "(Use SET HINTS OFF to suppress future hints.)\n");
9468                         printf("*************************\n");
9469                     }
9470 #endif /* UNIX */
9471 #endif /* OS2 */
9472                 } else printf("Can't connect to %s\n",line);
9473             } else
9474 #endif /* VMS */
9475               if (msg) printf("Can't open connection to %s\n",line);
9476             continue;
9477         } else {
9478             success = 1;
9479 #ifndef NODIAL
9480             dialsta = DIA_UNK;
9481 #endif /* NODIAL */
9482             switch (net) {
9483               case NET_TCPA:
9484               case NET_TCPB:
9485                 cxtype = CXT_TCPIP;
9486 #ifdef COMMENT
9487 /* This works but it messes up interactive anonymous login */
9488 #ifndef NOXFER
9489 #ifdef IKS_OPTION
9490                 /* If we have connected to an Internet Kermit service */
9491                 /* and a /USER: switch was given, then log in. */
9492
9493                 if (TELOPT_U(TELOPT_KERMIT) || TELOPT_ME(TELOPT_KERMIT)) {
9494                     debug(F111,"cx_net IKSD /USER:",uidbuf,haveuser);
9495                     if (haveuser /* && cx == 0 */ ) { /* /USER: given */
9496                         char * psw = pwbuf; /* Do we have a password? */
9497                         if (!*psw) {        /* No... */
9498                             if (!strcmp(uidbuf,"anonymous") ||
9499                                 !strcmp(uidbuf,"ftp")) {
9500                                 extern char myhost[];
9501                                 char * u = (char *)sl_uidbuf;
9502                                 char * h = (char *)myhost;
9503                                 if (!*u) u = "nobody";
9504                                 if (!*h) h = "nowhere";
9505                                 ckmakmsg(tmpbuf,TMPBUFSIZ,u,"@",h,NULL);
9506                                 psw = tmpbuf;
9507                                 debug(F110,"cx_net IKSD anon",psw,0);
9508                             } else {
9509                                 readpass(" Password: ",pwbuf,PWBUFL);
9510                             }
9511                         }
9512                         sstate = setgen('I',uidbuf,psw,"");
9513                     }
9514                 }
9515 #endif /* IKS_OPTION */
9516 #endif /* NOXFER */
9517 #endif /* COMMENT */
9518                 break;
9519               case NET_SSH:
9520                 cxtype = CXT_SSH;
9521                 duplex = 0;         /* Remote echo */
9522                 break;
9523               case NET_SLAT:
9524                 cxtype = CXT_LAT;
9525                 break;
9526               case NET_SX25:
9527               case NET_IX25:
9528               case NET_HX25:
9529               case NET_VX25:
9530                 cxtype = CXT_X25;
9531                 break;
9532               case NET_BIOS:
9533                 cxtype = CXT_NETBIOS;
9534                 break;
9535               case NET_FILE:
9536               case NET_PIPE:
9537               case NET_CMD:
9538               case NET_DLL:
9539               case NET_PTY:
9540                 cxtype = CXT_PIPE;
9541                 break;
9542               default:
9543                 cxtype = CXT_PIPE;
9544                 break;
9545             }
9546             break;
9547         }
9548     } /* for-loop */
9549     s = line;
9550
9551     debug(F101,"cx_net post ttopen success","",success);
9552     if (!success) {
9553         local = dfloc;                  /* Go back to normal */
9554 #ifndef MAC
9555         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty name */
9556 #endif /* MAC */
9557         speed = ttgspd();
9558         network = 0;                    /* No network connection active */
9559         haveline = 0;
9560         if (mdmtyp < 0) {               /* Switching from net to async? */
9561             if (mdmsav > -1)            /* Restore modem type from last */
9562               mdmtyp = mdmsav;          /* SET MODEM command, if any. */
9563             else
9564               mdmtyp = 0;
9565             mdmsav = -1;
9566         }
9567         return(0);                      /* Return failure */
9568     }
9569     if (_local > -1) local = _local;    /* Opened ok, set local/remote. */
9570     makestr(&slmsg,NULL);
9571     network = (mdmtyp < 0);             /* Remember connection type. */
9572     ckstrncpy(ttname,s,TTNAMLEN);       /* Copy name into real place. */
9573     debug(F110,"cx_net ok",ttname,0);
9574     debug(F101,"cx_net network","",network);
9575 #ifndef NOXFER
9576     if ((reliable != SET_OFF || !setreliable)) /* Assume not reliable. */
9577       reliable = SET_OFF;
9578 #endif /* NOXFER */
9579     if (!network || istncomport())      
9580       speed = ttgspd();                 /* Get the current speed. */
9581     debug(F101,"cx_net local","",local);
9582     if (network) {
9583         debug(F101,"cx_net net","",net);
9584 #ifndef NOXFER
9585         /* Force prefixing of 255 on TCP/IP connections... */
9586         if (net == NET_TCPB
9587 #ifdef SSHBUILTIN
9588              || net == NET_SSH
9589 #endif /* SSHBUILTIN */
9590              ) {
9591             debug(F101,"cx_net reliable A","",reliable);
9592 #ifdef CK_SPEED
9593             ctlp[(unsigned)255] = 1;
9594 #endif /* CK_SPEED */
9595             if ((reliable != SET_OFF || !setreliable)) {
9596 #ifdef TN_COMPORT
9597                 if (istncomport()) {    /* Telnet communication port */
9598                     reliable = SET_OFF; /* Transport is not reliable */
9599                     debug(F101,"cx_net reliable istncomport()","",1);
9600                 } else {
9601                     reliable = SET_ON;  /* Transport is reliable end to end */
9602                     debug(F101,"cx_net reliable istncomport()","",0);
9603                 }
9604 #else
9605                 reliable = SET_ON;      /* Transport is reliable end to end */
9606 #endif /* ifdef TN_COMPORT */
9607             }
9608             debug(F101,"cx_net reliable B","",reliable);
9609         } else if (net == NET_SX25 ||
9610                    net == NET_VX25 ||
9611                    net == NET_IX25 ||
9612                    net == NET_HX25) {
9613             duplex = 1;                 /* Local echo for X.25 */
9614             if (reliable != SET_OFF || !setreliable)
9615               reliable = SET_ON;        /* Transport is reliable end to end */
9616         }
9617 #endif /* NOXFER */
9618     }
9619 #ifndef NOXFER
9620     debug(F101,"cx_net reliable","",reliable);
9621 #endif /* NOXFER */
9622 #ifdef OS2
9623     if (mdmtyp <= 0)                    /* Network or Direct Connection */
9624       DialerSend(OPT_KERMIT_CONNECT, 0);
9625 #endif /* OS2 */
9626
9627   xcx_net:
9628
9629     setflow();                          /* Set appropriate flow control */
9630
9631     haveline = 1;
9632 #ifdef CKLOGDIAL
9633     dolognet();
9634 #endif /* CKLOGDIAL */
9635
9636 #ifndef NOSPL
9637     if (local) {
9638         if (nmac) {                     /* Any macros defined? */
9639             int k;                      /* Yes */
9640             k = mlook(mactab,"on_open",nmac);   /* Look this up */
9641             if (k >= 0) {                       /* If found, */
9642                 if (dodo(k,ttname,0) > -1)      /* set it up, */
9643                   parser(1);                    /* and execute it */
9644             }
9645         }
9646     }
9647 #endif /* NOSPL */
9648
9649     if (local && (cx || sx)) {          /* /CONNECT or /SERVER switch given */
9650         if (cx) {                       /* /CONNECT */
9651             if (!gui) {
9652                 /* Command was confirmed so we can pre-pop command level.  */
9653                 /* This is so CONNECT module won't think we're executing a */
9654                 /* script if CONNECT was the final command in the script.  */
9655                 if (cmdlvl > 0)
9656                   prepop();
9657             }
9658 #ifndef NODIAL
9659             dialsta = DIA_UNK;
9660 #endif /* NODIAL */
9661 #ifdef LOCUS
9662             if (autolocus) {
9663                 setlocus(1,1);
9664             }
9665 #endif /* LOCUS */
9666             success = doconect(0, cmdlvl == 0 ? 1 : 0);
9667             if (ttchk() < 0)
9668               dologend();
9669             debug(F101,"cx_net post doconect success","",success);
9670             return(success);
9671 #ifndef NOXFER
9672         } else if (sx) {                /* /SERVER */
9673             sstate = 'x';
9674 #ifdef MAC
9675             what = W_RECV;
9676             scrcreate();
9677 #endif /* MAC */
9678             if (local) displa = 1;
9679 #ifdef AMIGA
9680             reqoff();                   /* No DOS requestors while server */
9681 #endif /* AMIGA */
9682 #endif /* NOXFER */
9683         }
9684     }
9685 #ifndef NODIAL
9686     dialsta = DIA_UNK;
9687 #endif /* NODIAL */
9688 #ifdef LOCUS
9689     if (autolocus) {
9690         setlocus(1,1);
9691     }
9692 #endif /* LOCUS */
9693     return(success = 1);
9694 }
9695 #endif /* NETCONN */
9696
9697 /* c x _ s e r i a l  --  Make a serial connection */
9698
9699 /*
9700   Call with:
9701     device  = string pointer to device name.
9702     cx      = 1 to automatically enter Connect mode, 0 otherwise.
9703     sx      = 1 to automatically enter Server mode, 0 otherwise.
9704     shr     = 1 if device should be opened in shareable mode, 0 otherwise.
9705     flag    = if no dev name given: 1 = close current connection, 0 = resume.
9706     gui     = 1 if called from GUI dialog, 0 otherwise.
9707   Returns:
9708     1 on success
9709     0 on failure and no message printed, slmsg set to failure message.
9710    -9 on failure and message printed, ditto.
9711 */
9712
9713 /* these are bit flags */
9714 #define CX_TAPI 1
9715 #define CX_PPP  2
9716 #define CX_SLIP 4
9717
9718 int
9719 #ifdef CK_ANSIC
9720 cx_serial(char *device, 
9721           int cx, int sx, int shr, int flag, int gui, int special)
9722 #else /* CK_ANSIC */
9723 cx_serial(device, cx, sx, shr, flag, gui, special)
9724     char * device; int cx, sx, shr, flag, gui, special; 
9725 #endif /* CK_ANSIC */
9726 /* cx_serial */ {
9727     int i, n, x, y, msg;
9728     int _local = -1;
9729     char *s;
9730
9731     debug(F110,"cx_serial device",device,0);
9732     s = device;
9733     msg = (gui == 0) && msgflg;         /* Whether to print messages */
9734     success = 0;
9735
9736 #ifndef NODIAL
9737     dialsta = DIA_UNK;
9738 #endif /* NODIAL */
9739     debug(F101,"cx_serial mdmtyp","",mdmtyp);
9740     if (clskconnx(1) < 0)               /* Close the Kermit connection */
9741       return(success = 0);
9742     if (*s) {                           /* They gave a device name */
9743         _local = -1;                    /* Let ttopen decide about it */
9744     } else {                            /* They just said "set line" */
9745         s = dftty;                      /* so go back to normal tty */
9746         _local = dfloc;                 /* and mode. */
9747     }
9748 #ifdef VMS
9749     {
9750         extern int ok_to_share;
9751         ok_to_share = shr;
9752     }
9753 #endif /* VMS */
9754
9755 #ifdef OS2                              /* Must wait until after ttclos() */
9756 #ifdef NT                               /* to change these settings       */
9757 #ifdef CK_TAPI
9758     tttapi = special & CX_TAPI;
9759 #endif /* CK_TAPI */
9760 #else
9761     ttslip = special & CX_SLIP;
9762     ttppp  = special & CX_PPP;
9763 #endif /* NT */
9764     ttshare = shr;                      /* Shareable device ? */
9765     debug(F110,"OS2 SET PORT final s",s,"");
9766 #endif /* OS2 */
9767
9768     /* Open the new line */        
9769
9770     ckstrncpy(ttname,s,TTNAMLEN);
9771     if ((y = ttopen(s,&_local,mdmtyp,cdtimo)) > -1) {
9772         cxtype = (mdmtyp > 0) ? CXT_MODEM : CXT_DIRECT;
9773 #ifndef NODIAL
9774         dialsta = DIA_UNK;
9775 #ifdef CK_TAPI
9776         /* if the line is a tapi device, then we need to auto-execute */
9777         /* SET MODEM TYPE TAPI - which we do the equivalent of here.  */
9778         if (tttapi) {
9779             extern int usermdm;
9780             usermdm = 0;
9781             initmdm(38);                /* From ckudia.c n_TAPI == 38 */
9782         }
9783 #endif /* CK_TAPI */
9784 #endif /* NODIAL */
9785         success = 1;
9786     } else {                            /* Failed */
9787 #ifdef OS2ONLY
9788         if (!strcmp(s,dftty))   /* Do not generate an error with dftty */
9789           ;
9790         else if (y == -6 && ttslip) {
9791             makestr(&slmsg,"Can't access SLIP driver");
9792             if (msg) printf("?%s\n",slmsg);
9793         } else if (y == -6 && ttppp) {
9794             makestr(&slmsg,"Can't access PPP driver");
9795             if (msg) printf("?%s\n",slmsg);
9796         } else
9797 #endif /* OS2ONLY */
9798           if (y == -2) {
9799               makestr(&slmsg,"Timed out - no carrier");
9800               if (msg) {
9801                   printf("?%s\n",slmsg);
9802                   if (hints) {
9803                       printf("\n*************************\n");
9804                       printf(
9805                        "HINT (Use SET HINTS OFF to suppress future hints):\n");
9806                       printf(
9807                           "Try SET CARRIER OFF and SET LINE again, or else\n");
9808                       printf("SET MODEM, SET LINE, and then DIAL.\n");
9809                       printf("*************************\n\n");
9810                   }
9811               }
9812           } else if (y == -3) {
9813               makestr(&slmsg,"Access to lock denied");
9814               if (msg) {
9815 #ifdef UNIX
9816                   printf(
9817                    "Sorry, write access to UUCP lockfile directory denied.\n");
9818 #ifndef NOHINTS
9819                   if (hints) {
9820                       printf("\n*************************\n");
9821                       printf(
9822                        "HINT (Use SET HINTS OFF to suppress future hints):\n");
9823                       printf(
9824           "Please read the installation instructions file, %sckuins.txt,\n",
9825                              k_info_dir ? k_info_dir : ""
9826                              );
9827                       printf(
9828           "or the UNIX appendix of the manual, \"Using C-Kermit\"\n"
9829                              );
9830                       printf(
9831           "or visit http://www.columbia.edu/kermit/ckuins.html \n"
9832                              );
9833                       printf("*************************\n\n");
9834                   }
9835 #endif /* NOHINTS */
9836 #else
9837                   printf("Sorry, access to lock denied: %s\n",s);
9838 #endif /* UNIX */
9839               }
9840           } else if (y == -4) {
9841               makestr(&slmsg,"Access to device denied");
9842               if (msg) {
9843                   printf("Sorry, access to device denied: %s\n",s);
9844 #ifdef UNIX
9845 #ifndef NOHINTS
9846                   if (hints) {
9847                       printf("\n*************************\n");
9848                       printf(
9849                       "HINT (Use SET HINTS OFF to suppress future hints):\n");
9850                       printf(
9851             "Please read the installation instructions file, %sckuins.txt,\n",
9852                              k_info_dir ? k_info_dir : ""
9853                              );
9854                       printf(
9855             "or the UNIX appendix of the manual, \"Using C-Kermit\".\n"
9856                              );
9857                       printf("*************************\n\n");
9858                   }
9859 #endif /* NOHINTS */
9860 #endif /* UNIX */
9861               }
9862           } else if (y == -5) {
9863               makestr(&slmsg,"Device is in use or unavailable");
9864               if (msg)
9865 #ifdef VMS
9866                 printf(
9867                   "Sorry, device is in use or otherwise unavailable: %s\n",s);
9868 #else
9869               printf("Sorry, device is in use: %s\n",s);
9870 #endif /* VMS */
9871           } else {                      /* Other error. */
9872               makestr(&slmsg,"Device open failed");
9873               if (
9874 #ifdef VMS
9875                   1
9876 #else
9877                   errno
9878 #endif /* VMS */
9879                   ) {
9880                   int x;                /* Find a safe, long buffer */
9881                   makestr(&slmsg,ck_errstr());
9882 #ifndef VMS
9883                   debug(F111,"cx_serial serial errno",slmsg,errno);
9884 #endif /* VMS */
9885                   if (msg)
9886                     printf("Connection to %s failed: %s\n",s,slmsg);
9887               } else if (msg)
9888                 printf("Sorry, can't open connection: %s\n",s);
9889           }
9890     }
9891     network = 0;                        /* No network connection active */
9892     speed = ttgspd();
9893     if (!success) {
9894         local = dfloc;                  /* Go back to normal */
9895 #ifndef MAC
9896         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty name */
9897 #endif /* MAC */
9898         haveline = 0;
9899         if (mdmtyp < 0) {               /* Switching from net to async? */
9900             if (mdmsav > -1)            /* Restore modem type from last */
9901               mdmtyp = mdmsav;          /* SET MODEM command, if any. */
9902             else
9903               mdmtyp = 0;
9904             mdmsav = -1;
9905         }
9906         return(msg ? -9 : 0);           /* Return failure */
9907     }
9908     if (_local > -1)
9909       local = _local;                   /* Opened ok, set local/remote. */
9910     makestr(&slmsg,NULL);               /* Erase SET LINE message */
9911     ckstrncpy(ttname,s,TTNAMLEN);       /* Copy name into real place. */
9912     debug(F110,"cx_serial ok",ttname,0);
9913 #ifndef NOXFER
9914     if ((reliable != SET_OFF || !setreliable)) /* Assume not reliable. */
9915       reliable = SET_OFF;
9916 #endif /* NOXFER */
9917
9918   xcx_serial:
9919     setflow();                          /* Set appropriate flow control */
9920     haveline = 1;
9921 #ifdef CKLOGDIAL
9922       dologline();
9923 #endif /* CKLOGDIAL */
9924
9925 #ifndef NOSPL
9926     if (local) {
9927         if (nmac) {                     /* Any macros defined? */
9928             int k;                      /* Yes */
9929             k = mlook(mactab,"on_open",nmac);   /* Look this up */
9930             if (k >= 0) {                       /* If found, */
9931                 if (dodo(k,ttname,0) > -1)      /* set it up, */
9932                   parser(1);                    /* and execute it */
9933             }
9934         }
9935     }
9936 #endif /* NOSPL */
9937
9938     if (local && (cx || sx)) {          /* /CONNECT or /SERVER switch given */
9939         extern int carrier;
9940         if (carrier != CAR_OFF) {       /* Looking for carrier? */
9941             /* Open() turns on DTR -- wait up to a second for CD to come up */
9942             int i, x;
9943             for (i = 0; i < 10; i++) {  /* WAIT 1 CD... */
9944                 x = ttgmdm();
9945                 if (x < 0 || x & BM_DCD)
9946                   break;
9947                 msleep(100);
9948             }
9949         }
9950         if (cx) {                       /* /CONNECT */
9951             /* Command was confirmed so we can pre-pop command level. */
9952             /* This is so CONNECT module won't think we're executing a */
9953             /* script if CONNECT was the final command in the script. */
9954
9955             if (cmdlvl > 0)
9956               prepop();
9957 #ifndef NODIAL
9958             dialsta = DIA_UNK;
9959 #endif /* NODIAL */
9960 #ifdef LOCUS
9961             if (autolocus) {
9962                 setlocus(1,1);
9963             }
9964 #endif /* LOCUS */
9965             success = doconect(0, cmdlvl == 0 ? 1 : 0);
9966             if (ttchk() < 0)
9967               dologend();
9968             return(success);
9969 #ifndef NOXFER
9970         } else if (sx) {                /* /SERVER */
9971             sstate = 'x';
9972 #ifdef MAC
9973             what = W_RECV;
9974             scrcreate();
9975 #endif /* MAC */
9976             if (local) displa = 1;
9977 #ifdef AMIGA
9978             reqoff();                   /* No DOS requestors while server */
9979 #endif /* AMIGA */
9980 #endif /* NOXFER */
9981         }
9982     }
9983 #ifndef NODIAL
9984     dialsta = DIA_UNK;
9985 #endif /* NODIAL */
9986 #ifdef LOCUS
9987     if (autolocus) {
9988         setlocus(1,1);
9989     }
9990 #endif /* LOCUS */
9991     return(success = 1);
9992 }
9993
9994
9995 /* S E T L I N -- parse name of and then open communication device. */
9996 /*
9997   Call with:
9998     xx == XYLINE for a serial (tty) line, XYHOST for a network host,
9999     zz == 0 means if user doesn't give a device name, continue current
10000             active connection (if any);
10001     zz != 0 means if user doesn't give a device name, then close the
10002             current connection and restore the default communication device.
10003     fc == 0 to just make the connection, 1 to also CONNECT (e.g. "telnet").
10004 */
10005 int
10006 setlin(xx, zz, fc) 
10007     int xx, zz, fc; 
10008 {
10009     extern char pwbuf[], * g_pswd;
10010     extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
10011     int wait;
10012     /* int tn_wait_sv; */
10013     int mynet;
10014     int _local = -1;
10015     int c, i, haveswitch = 0;
10016     int haveuser = 0;
10017     int getval = 0;
10018     int wild = 0;                       /* Filespec has wildcards */
10019     int cx = 0;                         /* Connect after */
10020     int sx = 0;                         /* Become server after */
10021     int a_type = -1;                    /* Authentication type */
10022     int e_type = -1;                    /* Telnet /ENCRYPT type */
10023 #ifdef CK_ENCRYPTION
10024     int encrypt = 0;                    /* Encrypted? */
10025 #endif /* CK_ENCRYPTION */
10026     int shr = 0;                        /* Share serial device */
10027     int confirmed = 0;                  /* Command has been entered */
10028     struct FDB sw, tx, nx;
10029 #ifdef OS2
10030     struct FDB fl;
10031 #endif /* OS2 */
10032
10033     char * ss;
10034 #ifdef TCPSOCKET
10035     int rawflg = 0;
10036 #endif /* TCPSOCKET */
10037
10038     char srvbuf[SRVBUFSIZ+1];
10039
10040 #ifdef OS2
10041 #ifdef NT
10042     int xxtapi = 0;
10043 #else
10044     int xxslip = 0, xxppp = 0;
10045 #endif /* NT */
10046 #endif /* OS2 */
10047
10048     int dossh = 0;
10049
10050     debug(F101,"setlin fc","",fc);
10051     debug(F101,"setlin zz","",zz);
10052     debug(F101,"setlin xx","",xx);
10053
10054 #ifdef SSHCMD
10055     if (xx == XXSSH) {                  /* SSH becomes PTY SSH ... */
10056         dossh = 1;
10057         xx = XYHOST;
10058     }
10059 #endif /* SSHCMD */
10060
10061 #ifdef TNCODE
10062     /* tn_wait_sv = tn_wait_flg; */
10063     wait = tn_wait_flg;
10064 #else
10065     /* tn_wait_sv = 0; */
10066     wait = 0;
10067 #endif /* TNCODE */
10068
10069     mynet = nettype;
10070
10071     if (nolocal) {
10072         makestr(&slmsg,"Making connections is disabled");
10073         printf("?Sorry, making connections is disabled\n");
10074         return(-9);
10075     }
10076     if (netsave > -1)
10077       nettype = netsave;
10078
10079     if (fc != 0 || zz == 0)             /* Preset /CONNECT switch */
10080       cx = 1;
10081
10082     debug(F101,"setlin cx","",cx);
10083
10084     *srvbuf = NUL;
10085
10086     line[0] = NUL;
10087     s = line;
10088
10089 #ifdef NETCONN
10090 #ifdef CK_SECURITY
10091     if (tmpstring)
10092         makestr(&tmpstring,NULL);
10093 #endif /* CK_SECURITY */
10094     if (tmpusrid)
10095         makestr(&tmpusrid,NULL);
10096 #endif /* NETCONN */
10097
10098     autoflow = 1;                       /* Enable automatic flow setting */
10099
10100     if (xx == XYHOST) {                 /* SET HOST <hostname> */
10101 #ifndef NETCONN
10102         makestr(&slmsg,"Network connections not supported");
10103         printf("?%s\n",slmsg);
10104         return(-9);
10105 #else /* NETCONN */
10106 #ifndef NOPUSH
10107         if ((mynet == NET_CMD || mynet == NET_PTY || dossh) && nopush) {
10108             makestr(&slmsg,"Access to external commands is disabled");
10109             printf("?Sorry, access to external commands is disabled\n");
10110             return(-9);
10111         }
10112 #endif /* NOPUSH */
10113
10114 #ifdef SSHCMD
10115         if (dossh) {                    /* SSH connection via pty */
10116             int k;
10117             k = ckstrncpy(line, sshcmd ? sshcmd : defsshcmd, LINBUFSIZ);
10118             debug(F111,"setlin sshcmd 1",line,k);
10119             if ((x = cmtxt("Optional switches and hostname","",&s,xxstring))<0)
10120               return(x);
10121             if (!*s) {
10122                 printf("?SSH to where?\n");
10123                 return(-9);
10124             }
10125             if (k < LINBUFSIZ) {
10126                 line[k++] = SP;
10127                 line[k] = NUL;
10128                 debug(F111,"setlin sshcmd 2",line,k);
10129             } if (k < LINBUFSIZ) {
10130                 ckstrncpy(&line[k],s,LINBUFSIZ-k);
10131                 debug(F111,"setlin sshcmd 3",line,k);
10132             } else {
10133                 printf("?Too long\n");
10134                 return(-9);
10135             }
10136             x = cx_net( NET_PTY,                /* network type */
10137                         0,                      /* protocol (not used) */
10138                         line,                   /* host */
10139                         NULL,                   /* service (not used) */
10140                         NULL,                   /* username (not used) */
10141                         NULL,                   /* password (not used) */
10142                         NULL,                   /* command (not used) */
10143                         -1,-1,-1,               /* params 1-3 (not used) */
10144                         1,                      /* connect immediately */
10145                         sx,                     /* server? */
10146                         zz,                     /* close current? */
10147                         0);                     /* not gui */
10148             debug(F111,"setlin cx_net",line,x);
10149             return(x);
10150         }
10151 #endif /* SSHCMD */
10152
10153 /*
10154   Here we parse optional switches and then the hostname or whatever,
10155   which depends on the network type.  The tricky part is, the network type
10156   can be set by a switch.
10157 */
10158 #ifndef NOSPL
10159         makestr(&g_pswd,pwbuf);         /* Save global pwbuf */
10160         g_pflg = pwflg;                 /* and flag */
10161         g_pcpt = pwcrypt;
10162 #endif /* NOSPL */
10163
10164         confirmed = 0;
10165         haveswitch = 0;
10166 #ifdef NETFILE
10167         if (mynet != NET_FILE) {
10168 #endif /* NETFILE */
10169             ss = (mynet == NET_CMD || mynet == NET_PTY) ?
10170               "Command, or switch" :
10171                 (mynet == NET_TCPA || mynet == NET_TCPB
10172                   || mynet == NET_SSH) ?
10173                   "Hostname, ip-address, or switch" :
10174                     "Host or switch";
10175             if (fc) {
10176                 if (mynet == NET_TCPB &&
10177                     (ttnproto == NP_TELNET || ttnproto == NP_KERMIT)) {
10178                     if (nshteltab) {
10179                         haveswitch++;
10180                         cmfdbi(&sw,_CMKEY,ss,"","",nshteltab,4,xxstring,
10181                              shteltab,&nx);
10182                     }
10183                 }
10184 #ifdef RLOGCODE
10185                 else if (mynet == NET_TCPB && ttnproto == NP_RLOGIN) {
10186                     if (nshrlgtab) {
10187                         haveswitch++;
10188                         cmfdbi(&sw,_CMKEY,ss,"","",nshrlgtab,4,xxstring,
10189                                shrlgtab,&nx);
10190                     }
10191                 }
10192 #endif /* RLOGCODE */
10193             } else {
10194                 haveswitch++;
10195                 cmfdbi(&sw,_CMKEY,ss,"","",nshtab,4,xxstring,shtab,&nx);
10196             }
10197 #ifdef NETFILE
10198         }
10199 #endif /* NETFILE */
10200         if (mynet == NET_TCPB || mynet == NET_SLAT ||
10201             mynet == NET_SSH  || mynet == NET_DEC) {
10202             cmfdbi(&nx,_CMFLD,"Host","","",0,0,xxstring,NULL,NULL);
10203 #ifdef NETFILE
10204         } else if (mynet == NET_FILE) {
10205             cmfdbi(&nx,_CMIFI,"Filename","","",0,0,xxstring,NULL,NULL);
10206 #endif /* NETFILE */
10207 #ifdef PTYORPIPE
10208         } else if (mynet == NET_CMD || mynet == NET_PTY) {
10209             cmfdbi(&nx,_CMTXT,"Command","","",0,0,xxstring,NULL,NULL);
10210 #endif /* PTYORPIPE */
10211         } else {
10212             cmfdbi(&nx,_CMTXT,"Host","","",0,0,xxstring,NULL,NULL);
10213         }
10214         while (1) {
10215             x = cmfdb(haveswitch ? &sw : &nx);
10216             debug(F101,"setlin cmfdb","",x);
10217             if (x < 0)
10218               if (x != -3)
10219                 return(x);
10220             if (x == -3) {
10221                 if ((x = cmcfm()) < 0) {
10222                     return(x);
10223                 } else {
10224                     confirmed = 1;
10225                     break;
10226                 }
10227             }
10228             if (cmresult.fcode != _CMKEY) {    /* Not a switch */
10229                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Save the data */
10230                 s = line;                      /* that was parsed... */
10231                 if (cmresult.fcode == _CMIFI) {
10232                     wild = cmresult.nresult;
10233                 } else if (cmresult.fcode == _CMTXT) {
10234                     confirmed = 1;
10235                 }
10236                 break;                  /* and break out of this loop */
10237             }
10238             c = cmgbrk();               /* Have switch - get break character */
10239             getval = (c == ':' || c == '='); /* Must parse an agument? */
10240             if (getval && !(cmresult.kflags & CM_ARG)) {
10241                 printf("?This switch does not take arguments\n");
10242                 return(-9);
10243             }
10244             if (!getval && (cmgkwflgs() & CM_ARG)) {
10245                 printf("?This switch requires an argument\n");
10246                 return(-9);
10247             }
10248             switch (cmresult.nresult) { /* It's a switch.. */
10249               case SL_CNX:              /* /CONNECT */
10250                 cx = 1;
10251                 sx = 0;
10252                 break;
10253               case SL_SRV:              /* /SERVER */
10254                 cx = 0;
10255                 sx = 1;
10256                 break;
10257 #ifdef NETCMD
10258               case SL_CMD:              /* /COMMAND */
10259                 netsave = mynet;
10260                 mynet = NET_CMD;
10261                 break;
10262 #endif /* NETCMD */
10263 #ifdef NETPTY
10264               case SL_PTY:              /* /PTY */
10265                 netsave = mynet;
10266                 mynet = NET_PTY;
10267                 break;
10268 #endif /* NETPTY */
10269               case SL_NET:              /* /NETWORK-TYPE */
10270                 if ((x = cmkey(netcmd,nnets,"","",xxstring)) < 0)
10271                   return(x);
10272                 mynet = x;
10273                 break;
10274
10275 #ifdef CK_SECURITY
10276               case SL_PSW:              /* /PASSWORD: */
10277                 if (!getval)
10278                   break;
10279                 debok = 0;
10280                 if ((x = cmfld("Password","",&s,xxstring)) < 0) {
10281                     if (x == -3) {
10282                         makestr(&tmpstring,"");
10283                     } else {
10284                         return(x);
10285                     }
10286                 } else {
10287                     s = brstrip(s);
10288                     if ((x = (int)strlen(s)) > PWBUFL) {
10289                         makestr(&slmsg,"Internal error");
10290                         printf("?Sorry, too long - max = %d\n",PWBUFL);
10291                         return(-9);
10292                     }
10293                     makestr(&tmpstring,s);
10294                 }
10295                 break;
10296 #endif /* CK_SECURITY */
10297
10298               case SL_UID:              /* /USERID: */
10299                 if (!getval)
10300                   break;
10301                 if ((x = cmfld("Userid","",&s,xxstring)) < 0) {
10302                     if (x == -3) {
10303                         makestr(&tmpusrid,"");
10304                     } else {
10305                         return(x);
10306                     }
10307                 } else {
10308                     s = brstrip(s);
10309                     if ((x = (int)strlen(s)) > 63) {
10310                         makestr(&slmsg,"Internal error");
10311                         printf("?Sorry, too long - max = %d\n",63);
10312                         return(-9);
10313                     }
10314                     makestr(&tmpusrid,s);
10315                     haveuser = 1;
10316                 }
10317                 break;
10318
10319 #ifdef CK_AUTHENTICATION
10320 #ifdef CK_SRP
10321               case SL_SRP:
10322                 a_type = AUTHTYPE_SRP;
10323                 break;
10324 #endif /* CK_SRP */
10325 #ifdef CK_SSL
10326               case SL_SSL:
10327                 a_type = AUTHTYPE_SSL;
10328                 break;
10329 #endif /* CK_SSL */
10330 #ifdef NT
10331               case SL_NTLM:
10332                 a_type = AUTHTYPE_NTLM;
10333                 break;
10334 #endif /* NT */
10335 #ifdef CK_KERBEROS
10336               case SL_KRB4:
10337                 a_type = AUTHTYPE_KERBEROS_V4;
10338                 if (ttnproto == NP_RLOGIN)
10339                   ttnproto =
10340 #ifdef CK_ENCRYPTION
10341                     encrypt ? NP_EK4LOGIN :
10342 #endif /* CK_ENCRYPTION */
10343                       NP_K4LOGIN;
10344                 else if (ttnproto == NP_K5LOGIN)
10345                   ttnproto = NP_K4LOGIN;
10346 #ifdef CK_ENCRYPTION
10347                 else if (ttnproto == NP_EK5LOGIN)
10348                   ttnproto = NP_EK4LOGIN;
10349 #endif /* CK_ENCRYPTION */
10350                 break;
10351               case SL_KRB5:
10352                 a_type = AUTHTYPE_KERBEROS_V5;
10353                 if (ttnproto == NP_RLOGIN)
10354                   ttnproto =
10355 #ifdef CK_ENCRYPTION
10356                     encrypt ? NP_EK5LOGIN :
10357 #endif /* CK_ENCRYPTION */
10358                       NP_K5LOGIN;
10359                 else if (ttnproto == NP_K4LOGIN)
10360                   ttnproto = NP_K5LOGIN;
10361 #ifdef CK_ENCRYPTION
10362                 else if (ttnproto == NP_EK4LOGIN)
10363                   ttnproto = NP_EK5LOGIN;
10364 #endif /* CK_ENCRYPTION */
10365                 break;
10366 #endif /* CK_KERBEROS */
10367               case SL_AUTH: {
10368                   extern struct keytab autyptab[];
10369                   extern int nautyp;
10370                   if ((x = cmkey(autyptab,nautyp,"type of authentication",
10371                                  "automatic",xxstring)) < 0)
10372                     return(x);
10373                   a_type = x;
10374                   break;
10375               }
10376 #endif /* CK_AUTHENTICATION */
10377 #ifdef CK_ENCRYPTION
10378               case SL_ENC:
10379                 switch (ttnproto) {
10380                   case NP_K4LOGIN:
10381                     ttnproto = NP_EK4LOGIN;
10382                     encrypt = 1;
10383                     break;
10384                   case NP_K5LOGIN:
10385                     ttnproto = NP_EK5LOGIN;
10386                     encrypt = 1;
10387                     break;
10388                   case NP_KERMIT:
10389                   case NP_TELNET: {
10390                       static struct keytab * tnetbl = NULL;
10391                       static int ntnetbl = 0;
10392                       x = ck_get_crypt_table(&tnetbl,&ntnetbl);
10393                       debug(F101,"ck_get_crypt_table x","",x);
10394                       debug(F101,"ck_get_crypt_table n","",ntnetbl);
10395                       if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
10396                         x = 0;
10397                       if (!x) {
10398                           makestr(&slmsg,"Internal error");
10399                           printf("?Oops, types not loaded\n");
10400                           return(-9);
10401                       }
10402                       if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
10403                                      "automatic",xxstring)) < 0)
10404                         return(x);
10405                       e_type = x;
10406                       break;
10407                   }
10408                 }
10409                 break;
10410 #endif /* CK_ENCRYPTION */
10411               case SL_WAIT:
10412                 wait = 1;
10413                 break;
10414               case SL_NOWAIT:
10415                 wait = 0;
10416                 break;
10417             }
10418         }
10419
10420 #ifdef NETFILE
10421         if (mynet == NET_FILE) {        /* Parsed by cmifi() */
10422             if ((x = cmcfm()) < 0)      /* Needs confirmation */
10423               return(x);
10424             x = cx_net(mynet,           /* nettype */
10425                        0,               /* protocol (not used) */
10426                        line,            /* host */
10427                        "",              /* port */
10428                        NULL,            /* alternate username */
10429                        NULL,            /* password */
10430                        NULL,            /* command to execute */
10431                        0,               /* param1 */
10432                        0,               /* param2 */
10433                        0,               /* param3 */
10434                        cx,              /* enter CONNECT mode */
10435                        sx,              /* enter SERVER mode */
10436                        zz,              /* close connection if open */
10437                        0                /* gui */
10438                        );
10439         }
10440 #endif /* NETFILE */
10441
10442 #ifdef NETCMD
10443         if (mynet == NET_CMD || mynet == NET_PTY) {
10444             char *p = NULL;
10445             if (!confirmed) {
10446                 if ((x = cmtxt("Rest of command","",&s,xxstring)) < 0)
10447                   return(x);
10448                 if (*s) {
10449                     strncat(line," ",LINBUFSIZ);
10450                     strncat(line,s,LINBUFSIZ);
10451                 }
10452                 s = line;
10453             }
10454             /* s == line - so we must protect the line buffer */
10455             s = brstrip(s);
10456             makestr(&p,s);
10457             ckstrncpy(line,p,LINBUFSIZ);
10458             makestr(&p,NULL);
10459
10460             x = cx_net( mynet,                  /* nettype */
10461                         0,                      /* protocol (not used) */
10462                         line,                   /* host */
10463                         "",                     /* port */
10464                         NULL,                   /* alternate username */
10465                         NULL,                   /* password */
10466                         NULL,                   /* command to execute */
10467                         0,                      /* param1 */
10468                         0,                      /* param2 */
10469                         0,                      /* param3 */
10470                         cx,                     /* enter CONNECT mode */
10471                         sx,                     /* enter SERVER mode */
10472                         zz,                     /* close connection if open */
10473                         0                       /* gui */
10474                         );
10475         }
10476 #endif /* NETCMD */
10477
10478 #ifdef NPIPE                            /* Named pipe */
10479         if (mynet == NET_PIPE) {        /* Needs backslash twiddling */
10480             if (line[0]) {
10481                 if (strcmp(line,"*")) {    /* If remote, begin with */
10482                     char * p = NULL;
10483                     makestr(&p,line);      
10484                     ckstrncpy(line,"\\\\",LINBUFSIZ); /* server name */
10485                     ckstrncat(line,p,LINBUFSIZ);
10486                     makestr(&p,NULL);      
10487                 } else {
10488                     line[0]='\0';
10489                 }
10490                 ckstrncat(line,"\\pipe\\", LINBUFSIZ); /* Make pipe name */
10491                 ckstrncat(line,pipename, LINBUFSIZ); /* Add name of pipe */
10492
10493                 x = cx_net(mynet,       /* nettype */
10494                            0,           /* protocol (not used) */
10495                            line,        /* host */
10496                            "",          /* port */
10497                            NULL,        /* alternate username */
10498                            NULL,        /* password */
10499                            NULL,        /* command to execute */
10500                            0,           /* param1 */
10501                            0,           /* param2 */
10502                            0,           /* param3 */
10503                            cx,          /* enter CONNECT mode */
10504                            sx,          /* enter SERVER mode */
10505                            zz,          /* close connection if open */
10506                            0            /* gui */
10507                            );
10508             }
10509         }
10510 #endif /* NPIPE */
10511
10512 #ifdef SUPERLAT
10513         if (mynet == NET_SLAT) {        /* Needs password, etc. */
10514             slat_pwd[0] = NUL;          /* Erase any previous password */
10515             debok = 0;
10516             if (*line) {                /* If they gave a host name... */
10517                 if ((x = cmfld(
10518                      "password,\n or carriage return if no password required",
10519                                "",
10520                                &s,
10521                                xxstring
10522                                )) < 0 && x != -3)
10523                   return(x);
10524                 ckstrncpy(slat_pwd,s,18); /* Set the password, if any */
10525             }
10526             if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
10527
10528             x = cx_net(mynet,           /* nettype */
10529                        0,               /* protocol (not used) */
10530                        line,            /* host */
10531                        "",              /* port */
10532                        NULL,            /* alternate username */
10533                        NULL,            /* password */
10534                        NULL,            /* command to execute */
10535                        0,               /* param1 */
10536                        0,               /* param2 */
10537                        0,               /* param3 */
10538                        cx,              /* enter CONNECT mode */
10539                        sx,              /* enter SERVER mode */
10540                        zz,              /* close connection if open */
10541                        0                /* gui */
10542                        );
10543         }
10544 #endif /* SUPERLAT */
10545
10546 #ifdef DECNET
10547         if (mynet == NET_DEC) {  
10548             if (!line[0]) {                   /* If they gave a host name... */
10549                 printf("?hostname required\n");
10550                 return(-3);
10551             }
10552             if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
10553
10554             x = cx_net(mynet,           /* nettype */
10555                        0,               /* protocol (not used) */
10556                        line,            /* host */
10557                        "",              /* port */
10558                        NULL,            /* alternate username */
10559                        NULL,            /* password */
10560                        NULL,            /* command to execute */
10561                        0,               /* param1 */
10562                        0,               /* param2 */
10563                        0,               /* param3 */
10564                        cx,              /* enter CONNECT mode */
10565                        sx,              /* enter SERVER mode */
10566                        zz,              /* close connection if open */
10567                        0                /* gui */
10568                        );
10569         }
10570 #endif /* DECNET */
10571
10572 #ifdef SSHBUILTIN
10573         if (mynet == NET_SSH) {         /* SSH connection */
10574             int k, havehost = 0, trips = 0;
10575             int    tmpver = -1, tmpxfw = -1, tmpssh_cas;
10576 #ifndef SSHTEST
10577             extern int sl_ssh_xfw, sl_ssh_xfw_saved;
10578             extern int sl_ssh_ver, sl_ssh_ver_saved;
10579 #endif /* SSHTEST */
10580             extern struct keytab sshopnsw[];
10581             extern int nsshopnsw;
10582             extern char *ssh_tmpcmd, *ssh_tmpport;
10583             struct FDB sw, kw, fl;
10584
10585             debug(F110,"setlin SSH service 0",srvbuf,0);
10586             debug(F110,"setlin SSH host s 2",s,0);
10587             if (*s) {           /* If they gave a host name... */
10588                 debug(F110,"setlin SSH host s 1",s,0);
10589                 if (*s == '*') {
10590                     makestr(&slmsg,"Incoming connections not supported");
10591                     printf(
10592      "?Sorry, incoming connections not supported for SSH.\n"
10593                            );
10594                     return(-9);
10595                 }
10596                 ckstrncpy(line,s,LINBUFSIZ);
10597             } else {
10598                 printf("?hostname required\n");
10599                 return(-3);
10600             }
10601
10602             /* Parse [ port ] [ switches ] */
10603             cmfdbi(&kw,                 /* Switches */
10604                     _CMKEY,
10605                     "Port number or service name,\nor switch",
10606                     "",
10607                     "",
10608                     nsshopnsw,
10609                     4,
10610                     xxstring,
10611                     sshopnsw,
10612                     &fl
10613                     );
10614             cmfdbi(&fl,                 /* Port number or service name */
10615                     _CMFLD,
10616                     "",
10617                     "",
10618                     "",
10619                     0,
10620                     0,
10621                     xxstring,
10622                     NULL,
10623                     NULL
10624                     );
10625             trips = 0;                  /* Explained below */
10626             while (1) {                 /* Parse port and switches */
10627                 y = cmfdb(&kw);         /* Get a field */
10628                 if (y == -3)            /* User typed CR so quit from loop */
10629                     break;
10630                 if (y < 0)              /* Other parse error, pass it back */
10631                     return(y);
10632                 switch (cmresult.fcode) { /* Field or Keyword? */
10633                 case _CMFLD:              /* Field */
10634                     ckstrncpy(srvbuf,cmresult.sresult,SRVBUFSIZ);
10635                     break;
10636                 case _CMKEY:            /* Keyword */
10637                     switch (cmresult.nresult) { /* Which one? */
10638                     case SSHSW_PWD:
10639                         if (!cmgbrk()) {
10640                             printf("?This switch requires an argument\n");
10641                             return(-9);
10642                         }
10643                         debok = 0;
10644                         if ((y = cmfld("Password","",&s,xxstring)) < 0) {
10645                             if (y == -3) {
10646                                 makestr(&tmpstring,"");
10647                             } else {
10648                                 return(y);
10649                             }
10650                         } else {
10651                             s = brstrip(s);
10652                             if ((y = (int)strlen(s)) > PWBUFL) {
10653                                 makestr(&slmsg,"Internal error");
10654                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
10655                                 return(-9);
10656                             }
10657                             makestr(&tmpstring,s);
10658                         }
10659                         break;
10660                     case SSHSW_USR:             /* /USER: */
10661                         if (!cmgbrk()) {
10662                             printf("?This switch requires an argument\n");
10663                             return(-9);
10664                         }
10665                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
10666                             return(y);
10667                         s = brstrip(s);
10668                         makestr(&tmpusrid,s);
10669                         break;
10670                     case SSHSW_VER:
10671                         if ((y = cmnum("Number","",10,&z,xxstring)) < 0)
10672                             return(y);
10673                         if (z < 1 || z > 2) {
10674                             printf("?Out of range: %d\n",z);
10675                             return(-9);
10676                         }
10677                         tmpver = z;
10678                         break;
10679                     case SSHSW_CMD:
10680                     case SSHSW_SUB:
10681                         if ((y = cmfld("Text","",&s,xxstring)) < 0)
10682                           return(y);
10683                         makestr(&ssh_tmpcmd,s);
10684                         tmpssh_cas = (cmresult.nresult == SSHSW_SUB);
10685                         break;
10686                     case SSHSW_X11:
10687                         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
10688                             return(y);
10689                         tmpxfw = y;
10690                         break;
10691                     default:
10692                         return(-2);
10693                     }
10694                 }
10695                 if (trips++ == 0) {     /* After first time through */
10696                     cmfdbi(&kw,         /* only parse switches, not port. */
10697                             _CMKEY,
10698                             "Switch",
10699                             "",
10700                             "",
10701                             nsshopnsw,
10702                             4,
10703                             xxstring,
10704                             sshopnsw,
10705                             NULL
10706                             );
10707                 }
10708             }
10709             if ((y = cmcfm()) < 0)      /* Get confirmation */
10710                 return(y);
10711
10712             debug(F110,"setlin pre-cx_net line",line,0);
10713             debug(F110,"setlin pre-cx_net srvbuf",srvbuf,0);
10714             x = cx_net( mynet,                  /* nettype */
10715                         0,                      /* protocol (not used) */
10716                         line,                   /* host */
10717                         srvbuf,                 /* port */
10718                         tmpusrid,               /* alternate username */
10719                         tmpstring,              /* password */
10720                         ssh_tmpcmd,             /* command to execute */
10721                         tmpver,                 /* param1 - ssh version */
10722                         tmpssh_cas,             /* param2 - ssh cas  */
10723                         tmpxfw,                 /* param3 - ssh x11fwd */
10724                         cx,                     /* enter CONNECT mode */
10725                         sx,                     /* enter SERVER mode */
10726                         zz,                     /* close connection if open */
10727                         0                       /* gui */
10728                         );
10729             if (tmpusrid)
10730                 makestr(&tmpusrid,NULL);
10731             if (ssh_tmpcmd)
10732                 makestr(&ssh_tmpcmd,NULL);
10733         }
10734 #endif /* SSHBUILTIN */
10735
10736 #ifdef TCPSOCKET
10737         if (mynet == NET_TCPB) {        /* TCP/IP connection */
10738             debug(F110,"setlin service 0",srvbuf,0);
10739             debug(F110,"setlin host s 2",s,0);
10740             if (*s) {                   /* If they gave a host name... */
10741                 debug(F110,"setlin host s 1",s,0);
10742 #ifdef NOLISTEN
10743                 if (*s == '*') {
10744                     makestr(&slmsg,"Incoming connections not supported");
10745                     printf(
10746      "?Sorry, incoming connections not supported in this version of Kermit.\n"
10747                            );
10748                     return(-9);
10749                 }
10750 #endif /* NOLISTEN */
10751 #ifdef RLOGCODE
10752                 /* Allow a username if rlogin is requested */
10753                 if (mynet == NET_TCPB &&
10754                     (ttnproto == NP_RLOGIN || ttnproto == NP_K5LOGIN ||
10755                      ttnproto == NP_EK5LOGIN || ttnproto == NP_K4LOGIN ||
10756                      ttnproto == NP_EK4LOGIN
10757                     )) {
10758                     int y;
10759                     uidflag = 0;
10760                     /* Check for "host:service" */
10761                     for ( ; (*s != '\0') && (*s != ':'); s++) ;
10762                     if (*s) {   /* Service, save it */
10763                         *s = NUL;
10764                         ckstrncpy(srvbuf,++s,SRVBUFSIZ);
10765                     } else {            /* No :service, then use default. */
10766 #ifdef VMS
10767                         switch (ttnproto) {
10768                           case NP_RLOGIN:
10769                             ckstrncpy(srvbuf,"513",SRVBUFSIZ); /* "login" */
10770                             break;
10771                           case NP_K4LOGIN:
10772                           case NP_K5LOGIN:
10773                             ckstrncpy(srvbuf,"543",SRVBUFSIZ); /* "klogin" */
10774                             break;
10775                           case NP_EK4LOGIN:
10776                           case NP_EK5LOGIN:
10777                             ckstrncpy(srvbuf,"2105",SRVBUFSIZ); /* "eklogin" */
10778                             break;
10779                         }
10780 #else /* VMS */
10781                         switch (ttnproto) {
10782                           case NP_RLOGIN:
10783                             ckstrncpy(srvbuf,"login",SRVBUFSIZ);
10784                             break;
10785                           case NP_K4LOGIN:
10786                           case NP_K5LOGIN:
10787                             ckstrncpy(srvbuf,"klogin",SRVBUFSIZ);
10788                             break;
10789                           case NP_EK4LOGIN:
10790                           case NP_EK5LOGIN:
10791                             ckstrncpy(srvbuf,"eklogin",SRVBUFSIZ);
10792                             break;
10793                         }
10794 #endif /* VMS */
10795                     }
10796                     if (!confirmed) {
10797                         y = cmfld("Userid on remote system",
10798                                   uidbuf,&s,xxstring);
10799                         if (y < 0 && y != -3)
10800                           return(y);
10801                         if ((int)strlen(s) > 63) {
10802                             makestr(&slmsg,"Internal error");
10803                             printf("Sorry, too long\n");
10804                             return(-9);
10805                         }
10806                         makestr(&tmpusrid,s);
10807                     }
10808                 } else {        /* TELNET or SET HOST */
10809 #endif /* RLOGCODE */
10810                     /* Check for "host:service" */
10811                     for ( ; (*s != '\0') && (*s != ':'); s++) ;
10812                     if (*s) {   /* Service, save it */
10813                         *s = NUL;
10814                         ckstrncpy(srvbuf,++s,SRVBUFSIZ);
10815                     } else if (!confirmed) {
10816                         /* No :service, let them type one. */
10817                         if (*line != '*') { /* Not incoming */
10818                             if (mynet == NET_TCPB && ttnproto == NP_KERMIT) {
10819                                 if ((x = cmfld(
10820                                                "TCP service name or number",
10821                                                "kermit",&s,xxstring)
10822                                      ) < 0 && x != -3)
10823                                   return(x);
10824 #ifdef RLOGCODE
10825                             } else if (mynet == NET_TCPB &&
10826                                        ttnproto == NP_RLOGIN) {
10827                                 if ((x = cmfld(
10828   "TCP service name or number,\n or carriage return for rlogin (513)",
10829                                                "login",&s,xxstring)
10830                                      ) < 0 && x != -3)
10831                                   return(x);
10832 #ifdef CK_AUTHENTICATION
10833 #ifdef CK_KERBEROS
10834                             } else if (mynet == NET_TCPB &&
10835                                        (ttnproto == NP_K4LOGIN ||
10836                                        ttnproto == NP_K5LOGIN)) {
10837                                 if ((x = cmfld(
10838   "TCP service name or number,\n or carriage return for klogin (543)",
10839                                                "klogin",&s,xxstring)
10840                                      ) < 0 && x != -3)
10841                                   return(x);
10842                             } else if (mynet == NET_TCPB &&
10843                                        (ttnproto == NP_EK4LOGIN ||
10844                                         ttnproto == NP_EK5LOGIN)) {
10845                                 if ((x = cmfld(
10846   "TCP service name or number,\n or carriage return for eklogin (2105)",
10847                                                "eklogin",&s,xxstring)
10848                                      ) < 0 && x != -3)
10849                                   return(x);
10850 #endif /* CK_KERBEROS */
10851 #endif /* CK_AUTHENTICATION */
10852 #endif /* RLOGCODE */
10853                             } else {
10854                                 /* Do not set a default value in this call */
10855                                 /* If you do then it will prevent entries  */
10856                                 /* in the network directory from accessing */
10857                                 /* alternate ports.                        */
10858
10859                                 if ((x = cmfld(
10860                                                "TCP service name or number",
10861                                                "",&s,xxstring)
10862                                      ) < 0 && x != -3)
10863                                   return(x);
10864                             }
10865                         } else { /* Incoming connection */
10866                             if ((x = cmfld("TCP service name or number",
10867                                            "",&s,xxstring)
10868                                  ) < 0 && x != -3)
10869                               return(x);
10870                         }
10871                         if (*s)         /* If they gave a service, */
10872                           ckstrncpy(srvbuf,s,SRVBUFSIZ); /* copy it */
10873                         debug(F110,"setlin service 0.5",srvbuf,0);
10874                     }
10875 #ifdef RLOGCODE
10876                 }
10877 #endif /* RLOGCODE */
10878                 if (!confirmed) {
10879                     char * defproto;
10880                     switch (ttnproto) {
10881                       case NP_RLOGIN:
10882                         defproto = "/rlogin";
10883                         break;
10884                       case NP_K4LOGIN:
10885                         defproto = "/k4login";
10886                         break;
10887                       case NP_K5LOGIN:
10888                         defproto = "/k5login";
10889                         break;
10890                       case NP_EK4LOGIN:
10891                         defproto = "/ek4login";
10892                         break;
10893                       case NP_EK5LOGIN:
10894                         defproto = "/ek5login";
10895                         break;
10896                       case NP_KERMIT:
10897                       case NP_TELNET:
10898                         defproto = "/telnet";
10899                         break;
10900                       default:
10901                         defproto = "/default";
10902                     }
10903                     if ((x = cmkey(tcprawtab,ntcpraw,"Switch",defproto,
10904                                    xxstring)) < 0) {
10905                         if (x != -3)
10906                           return(x);
10907                         else if ((x = cmcfm()) < 0)
10908                           return(x);
10909                     } else {
10910                         rawflg = x;
10911                         if ((x = cmcfm()) < 0)
10912                           return(x);
10913                     }
10914                 }
10915             }
10916             debug(F110,"setlin pre-cx_net line",line,0);
10917             debug(F110,"setlin pre-cx_net srvbuf",srvbuf,0);
10918             x = cx_net( mynet,                  /* nettype */
10919                         rawflg                  /* protocol */,
10920                         line,                   /* host */
10921                         srvbuf,                 /* port */
10922                         tmpusrid,               /* alternate username */
10923                         tmpstring,              /* password */
10924                         NULL,                   /* command to execute */
10925                         a_type,                 /* param1 - telnet authtype */
10926                         e_type,                 /* param2 - telnet enctype  */
10927                         wait,                   /* param3 - telnet wait */
10928                         cx,                     /* enter CONNECT mode */
10929                         sx,                     /* enter SERVER mode */
10930                         zz,                     /* close connection if open */
10931                         0                       /* gui */
10932                         );
10933         }
10934 #endif /* TCPSOCKET */
10935
10936 #ifdef CK_SECURITY
10937         if (tmpstring)
10938             makestr(&tmpstring,NULL);
10939 #endif /* CK_SECURITY */
10940         if (tmpusrid)
10941             makestr(&tmpusrid,NULL);
10942         debug(F111,"setlin cx_net",line,x);
10943         return(x);
10944 #endif /* NETCONN */
10945     }
10946
10947 /* Serial tty device, possibly modem, connection... */
10948
10949 #ifdef OS2
10950 /*
10951   User can type:
10952     COM1..COM8 = Regular COM port
10953     1..8       = Synonym for COM1..COM8, is translated to COM1..COM8
10954     _n         = (n is a number) = open file handle
10955     string     = any text string = name of some other kind of device,
10956                  taken literally, as given.
10957 */
10958     s = "Communication device name";
10959
10960 #ifdef CK_TAPI
10961     if (TAPIAvail)
10962       cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
10963     if (!(tapilinetab && _tapilinetab && ntapiline > 0) &&
10964         xx == XYTAPI_LIN ) {
10965         makestr(&slmsg,"TAPI device not configured");
10966         printf("\nNo TAPI Line Devices are configured for this system\n");
10967         return(-9);
10968     }
10969     if (xx == XYTAPI_LIN) {             /* Default (first) TAPI line */
10970         s = "tapi";                     /* (whatever it is) */
10971     } else {                            /* Query the user */
10972 #endif /* CK_TAPI */
10973
10974 /* Now parse optional switches and then device name */
10975
10976         confirmed = 0;
10977         cmfdbi(&sw,_CMKEY,"Device name, or switch",
10978                "","",npsltab,4,xxstring,psltab,&fl);
10979         cmfdbi(&fl,_CMFLD,"",dftty,"",0,0,xxstring,NULL,NULL);
10980         while (1) {
10981             x = cmfdb(&sw);
10982             debug(F101,"setlin cmfdb","",x);
10983             if (x < 0)
10984               if (x != -3)
10985                 return(x);
10986             if (x == -3) {
10987                 if ((x = cmcfm()) < 0) {
10988                     return(x);
10989                 } else {
10990                     confirmed = 1;
10991                     break;
10992                 }
10993             }
10994             if (cmresult.fcode == _CMFLD) {
10995                 s = cmresult.sresult;
10996                 break;
10997             } else if (cmresult.fcode == _CMKEY) {
10998                 switch (cmresult.nresult) {
10999                   case SL_CNX:          /* /CONNECT */
11000                     cx = 1;
11001                     sx = 0;
11002                     break;
11003                   case SL_SRV:          /* /SERVER */
11004                     cx = 0;
11005                     sx = 1;
11006                     break;
11007                   case SL_SHR:          /* /SHARE */
11008                     shr = 1;
11009                     break;
11010                   case SL_NSH:          /* /NOSHARE */
11011                     shr = 0;
11012                     break;
11013                 }
11014             }
11015         }
11016 #ifdef CK_TAPI
11017     }
11018 #endif /* CK_TAPI */
11019
11020     debug(F110,"OS2 SET PORT s",s,0);
11021     y = lookup(os2devtab,s,nos2dev,&x); /* Look up in keyword table */
11022     debug(F101,"OS2 SET PORT x","",x);
11023     debug(F101,"OS2 SET PORT y","",y);
11024     if ((y > -1) && (x >= 0 && x < 8)) { /* User typed a digit 1..8 */
11025         s = os2devtab[x+8].kwd;         /* Substitite its real name */
11026 #ifdef NT
11027         xxtapi = 0;
11028 #else /* NT */
11029         xxslip = xxppp = 0;
11030 #endif /* NT */
11031         debug(F110,"OS2 SET PORT subst s",s,"");
11032 #ifndef NT
11033     } else if ((y >-1) && (x >= 16 && x < 24)) { /* SLIP access */
11034         s = os2devtab[x-8].kwd;         /* Substitite its real name */
11035         debug(F110,"OS2 SET PORT SLIP subst s",s,"");
11036         xxslip = 1;
11037         xxppp  = 0;
11038     } else if ((y >-1) && (x >= 24 && x < 32)) { /* PPP access */
11039         s = os2devtab[x-16].kwd;        /* Substitite its real name */
11040         debug(F110,"OS2 SET PORT PPP subst s",s,"");
11041         xxppp = 1;
11042         xxslip = 0;
11043         if ((y = cmkey(os2ppptab,
11044                        nos2ppp,
11045                        "PPP driver interface",
11046                        "ppp0",
11047                        xxstring)
11048              ) < 0)
11049           return(y);
11050         debug(F101,"OS2 SET PORT PPP INTERFACE y","",y);
11051         xxppp = (y % 10) + 1;
11052 #endif /* NT */
11053     } else if (*s == '_') {             /* User used "_" prefix */
11054         s++;                            /* Remove it */
11055         /* Rest must be numeric */
11056         debug(F110,"OS2 SET PORT HANDLE _subst s",s,0);
11057         if (!rdigits(s)) {
11058             makestr(&slmsg,"Invalid file handle");
11059             printf("?Invalid format for file handle\n");
11060             return(-9);
11061         }
11062 #ifdef NT
11063         xxtapi = 0;
11064 #else /* NT */
11065         xxslip = xxppp = 0;
11066 #endif /* NT */
11067     } else {                            /* A normal COMx port or a string */
11068         s = brstrip(s);                 /* Strip braces if any */
11069 #ifdef NT
11070 #ifdef CK_TAPI
11071         /* Windows TAPI support - Look up in keyword table */
11072         if (tapilinetab && _tapilinetab && ntapiline > 0) {
11073             if (!ckstrcmp(s,"tapi",4,0)) {
11074
11075                 /* Find out what the lowest numbered TAPI device is */
11076                 /* and use it as the default.                       */
11077                 int j = 9999, k = -1;
11078                 for (i = 0; i < ntapiline; i++) {
11079                     if (tapilinetab[i].kwval < j) {
11080                         j = tapilinetab[i].kwval;
11081                         k = i;
11082                     }
11083                 }
11084                 if (k >= 0)
11085                   s = _tapilinetab[k].kwd;
11086                 else
11087                   s = "";
11088
11089                 if ((y = cmkey(_tapilinetab,ntapiline,
11090                                "TAPI device name",s,xxstring)) < 0)
11091                   return(y);
11092
11093                 xxtapi = 1;
11094
11095                 /* Get the non Underscored string */
11096                 for (i = 0; i < ntapiline; i++ ) {
11097                     if (tapilinetab[i].kwval == y) {
11098                         s = tapilinetab[i].kwd;
11099                         break;
11100                     }
11101                 }
11102             } else
11103               xxtapi = 0;
11104         }
11105 #endif /* CK_TAPI */
11106 #else /* NT */
11107         /* not OS/2 SLIP or PPP */
11108         xxslip = xxppp = 0;
11109 #endif /* NT */
11110     }
11111     ckstrncpy(tmpbuf,s,TMPBUFSIZ);      /* Copy to a safe place */
11112     s = tmpbuf;
11113     if ((x = cmcfm()) < 0)
11114       return(x);
11115
11116 #else /* !OS2 */
11117
11118     cmfdbi(&sw,_CMKEY,"Device name, or switch",
11119            "","",npsltab,4,xxstring,psltab,&tx);
11120     cmfdbi(&tx,_CMTXT,"",dftty,"",0,0,xxstring,NULL,NULL);
11121     while (!confirmed) {
11122         x = cmfdb(&sw);
11123         debug(F101,"setlin cmfdb","",x);
11124         if (x < 0)
11125           if (x != -3)
11126             return(x);
11127         if (x == -3) {
11128             if ((x = cmcfm()) < 0) {
11129                 return(x);
11130             } else {
11131                 confirmed = 1;
11132                 break;
11133             }
11134         }
11135         switch (cmresult.fcode) {
11136           case _CMTXT:
11137             ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
11138             s = tmpbuf;
11139             debug(F110,"setlin CMTXT",tmpbuf,0);
11140             confirmed = 1;
11141             break;
11142           case _CMKEY:                  /* Switch */
11143             debug(F101,"setlin CMKEY",tmpbuf,cmresult.nresult);
11144             switch (cmresult.nresult) {
11145               case SL_CNX:              /* /CONNECT */
11146                 cx = 1;
11147                 sx = 0;
11148                 break;
11149               case SL_SRV:              /* /SERVER */
11150                 cx = 0;
11151                 sx = 1;
11152                 break;
11153 #ifdef VMS
11154               case SL_SHR:              /* /SHARE */
11155                 shr = 1;
11156                 break;
11157               case SL_NSH:              /* /NOSHARE */
11158                 shr = 0;
11159                 break;
11160 #endif /* VMS */
11161             }
11162             continue;
11163           default:
11164             debug(F101,"setlin bad cmfdb result","",cmresult.fcode);
11165             makestr(&slmsg,"Internal error");
11166             printf("?Internal parsing error\n");
11167             return(-9);
11168         }
11169     }
11170 #endif /* OS2 */
11171     if (!confirmed)
11172       if ((x = cmcfm()) < 0)
11173         return(x);
11174
11175     debug(F110,"setlin pre-cx_serial s",s,0);
11176     debug(F110,"setlin pre-cx_serial line",line,0);
11177     x = cx_serial(s,cx,sx,shr,zz,0,
11178 #ifdef OS2
11179 #ifdef NT
11180                    (xxtapi ? CX_TAPI : 0)
11181 #else
11182                    (xxslip ? CX_SLIP : 0) | (xxppp ? CX_PPP : 0)
11183 #endif /* NT */
11184 #else /* OS2 */
11185                    0
11186 #endif /* OS2 */
11187                    );
11188     debug(F111,"setlin cx_serial",line,x);
11189     return(x);
11190 }
11191 #endif /* NOLOCAL */
11192
11193 #ifdef CKCHANNELIO
11194 /*
11195   C-Library based file-i/o package for scripts.  This should be portable to
11196   all C-Kermit versions since it uses the same APIs we have always used for
11197   processing command files.  The entire channel i/o package is contained
11198   herein, apart from some keyword table entries in the main keyword table
11199   and the help text in the HELP command module.
11200
11201   On platforms like VMS and VOS, this package handles only UNIX-style
11202   stream files.  If desired, it can be replaced for those platforms by
11203   <#>ifdef'ing out this code and adding the equivalent replacement routines
11204   to the ck?fio.c module, e.g. for RMS-based file i/o in ckvfio.c.
11205 */
11206
11207 /* Define NOSTAT if the <#>include causes trouble. */
11208
11209 #ifndef NOSTAT
11210 #ifdef VMS
11211 #ifdef VAXC                             /* As it does in VAX C */
11212 #define NOSTAT
11213 #endif /* VAXC */
11214 #endif /* VMS */
11215 #endif /* NOSTAT */
11216
11217 #ifndef NOSTAT
11218 #include <sys/stat.h>
11219 #endif /* NOSTAT */
11220
11221 #ifdef NLCHAR
11222 static int z_lt = 1;                    /* Length of line terminator */
11223 #else
11224 static int z_lt = 2;
11225 #endif /* NLCHAR */
11226
11227 struct ckz_file {                       /* C-Kermit file struct */
11228     FILE * z_fp;                        /* Includes the C-Lib file struct */
11229     unsigned int z_flags;               /* Plus C-Kermit mode flags, */
11230     long z_nline;                       /* current line number if known, */
11231     char z_name[CKMAXPATH+2];           /* and the file's name. */
11232 };
11233 static struct ckz_file * z_file = NULL; /* Array of C-Kermit file structs */
11234 static int z_inited = 0;                /* Flag for array initialized */
11235 int z_maxchan = Z_MAXCHAN;              /* Max number of C-Kermit channels */
11236 int z_openmax = CKMAXOPEN;              /* Max number of open files overall */
11237 int z_nopen = 0;                        /* How many channels presently open */
11238 int z_error = 0;                        /* Most recent error */
11239 int z_filcount = -1;                    /* Most recent FILE COUNT result */
11240
11241 #define RD_LINE 0                       /* FILE READ options */
11242 #define RD_CHAR 1
11243 #define RD_SIZE 2
11244 #define RD_TRIM 8                       /* Like Snobol &TRIM = 1 */
11245 #define RD_UNTA 9                       /* Untabify */
11246
11247 #define WR_LINE RD_LINE                 /* FILE WRITE options */
11248 #define WR_CHAR RD_CHAR
11249 #define WR_SIZE RD_SIZE
11250 #define WR_STRI 3
11251 #define WR_LPAD 4
11252 #define WR_RPAD 5
11253
11254 #ifdef UNIX
11255 extern int ckmaxfiles;                  /* Filled in by sysinit(). */
11256 #endif /* UNIX */
11257
11258 /* See ckcker.h for error numbers */
11259 /* See ckcdeb.h for Z_MAXCHAN and CKMAXOPEN definitions */
11260 /* NOTE: For VMS we might be able to fill in ckmaxfiles */
11261 /* from FILLM and CHANNELCNT -- find out about these... */
11262
11263 static char * fopnargs[] = {            /* Mode combinations for fopen() */
11264 #ifdef COMMENT
11265     /* All combinations of rwa */
11266     "",  "r",  "w",  "rw",  "a",  "ra",  "wa",  "rwa", /* Text mode */
11267     "b", "rb", "wb", "rwb", "ab", "rab", "wab", "rwab" /* Binary mode */
11268 #else
11269     /* Combinations and syntax permitted by C libraries... */
11270     "",  "r",  "w",  "r+",  "a",  "",   "a",  "", /* Text mode */
11271 #ifdef OS2
11272     "",  "rb", "wb", "r+b", "ab", "",   "ab", "" /* Binary modes for K95 */
11273 #else
11274 #ifdef VMS
11275     "",  "rb", "wb", "r+b", "ab", "",   "ab", "" /* Binary modes for VMS */
11276 #else
11277     "",  "r",   "w", "r+",  "a",  "",   "a",  "" /* Binary modes for UNIX */
11278 #endif /* VMS */
11279 #endif /* OS2 */
11280 #endif /* COMMENT */
11281 };
11282 static int nfopnargs = sizeof(fopnargs) / sizeof(char *);
11283
11284 char *                                  /* Error messages */
11285 ckferror(n) int n; {
11286     switch (n) {
11287       case FX_NER: return("No error");
11288       case FX_SYS: return(ck_errstr());
11289       case FX_EOF: return("End of file");
11290       case FX_NOP: return("File not open");
11291       case FX_CHN: return("Channel out of range");
11292       case FX_RNG: return("Parameter out of range");
11293       case FX_NMF: return("Too many files open");
11294       case FX_FOP: return("Operation conflicts with OPEN mode");
11295       case FX_NYI: return("OPEN mode not supported");
11296       case FX_BOM: return("Illegal combination of OPEN modes");
11297       case FX_ACC: return("Access denied");
11298       case FX_FNF: return("File not found");
11299       case FX_OFL: return("Buffer overflow");
11300       case FX_LNU: return("Current line number unknown");
11301       case FX_ROO: return("Off limits");
11302       case FX_UNK: return("Operation fails - reason unknown");
11303       default: return("Error number out of range");
11304     }
11305 }
11306
11307 /*
11308   Z _ O P E N --  Open a file for the requested type of access.
11309
11310   Call with:
11311     name:  Name of file to be opened.
11312     flags: Any combination of FM_xxx values except FM_EOF (ckcker.h).
11313   Returns:
11314     >= 0 on success: The assigned channel number
11315     <  0 on failure: A negative FX_xxx error code (ckcker.h).
11316 */
11317 int
11318 z_open(name, flags) char * name; int flags; {
11319     int i, n;
11320     FILE * t;
11321     char * mode;
11322     debug(F111,"z_open",name,flags);
11323     if (!name) name = "";               /* Check name argument */
11324     if (!name[0])
11325       return(z_error = FX_BFN);
11326     if (flags & FM_CMD)                 /* Opening pipes not implemented yet */
11327       return(z_error = FX_NYI);         /* (and not portable either) */
11328     debug(F101,"z_open nfopnargs","",nfopnargs);
11329     if (flags < 0 || flags >= nfopnargs) /* Range check flags */
11330       return(z_error = FX_RNG);
11331     mode = fopnargs[flags];             /* Get fopen() arg */
11332     debug(F111,"z_open fopen args",mode,flags);
11333     if (!mode[0])                       /* Check for illegal combinations */
11334       return(z_error = FX_BOM);
11335     if (!z_inited) {                    /* If file structs not inited */
11336         debug(F101,"z_open z_maxchan 1","",z_maxchan);
11337 #ifdef UNIX
11338         debug(F101,"z_open ckmaxfiles","",ckmaxfiles);
11339         if (ckmaxfiles > 0) {           /* Set in ck?tio.c: sysinit() */
11340             int x;
11341             x = ckmaxfiles - ZNFILS - 5;
11342             if (x > z_maxchan)          /* sysconf() value greater than */
11343               z_maxchan = x;            /* value from header files. */
11344             debug(F101,"z_open z_maxchan 2","",z_maxchan);
11345         }
11346 #endif /* UNIX */
11347         if (z_maxchan < Z_MINCHAN)      /* Allocate at least this many. */
11348           z_maxchan = Z_MINCHAN;
11349         debug(F101,"z_open z_maxchan 3","",z_maxchan);
11350         /* Note: This could be a pretty big chunk of memory */
11351         /* if z_maxchan is a big number.  If this becomes a problem */
11352         /* we'll need to malloc and free each element at open/close time */
11353         if (!(z_file = (struct ckz_file *)
11354               malloc(sizeof(struct ckz_file) * (z_maxchan + 1))))
11355           return(z_error = FX_NMF);
11356         for (i = 0; i < z_maxchan; i++) {
11357             z_file[i].z_fp = NULL;
11358             z_file[i].z_flags = 0;
11359             z_file[i].z_nline = 0;
11360             *(z_file[i].z_name) = '\0';
11361         }
11362         z_inited = 1;                   /* Remember we did */
11363     }
11364     for (n = -1, i = 0; i < z_maxchan; i++) {
11365         if (!z_file[i].z_fp) {
11366             n = i;
11367             break;
11368         }
11369     }
11370     if (n < 0 || n >= z_maxchan)        /* Any free channels? */
11371       return(z_error = FX_NMF);         /* No, fail. */
11372     errno = 0;
11373
11374     z_file[n].z_flags = 0;              /* In case of failure... */
11375
11376     t = fopen(name, mode);              /* Try to open the file. */
11377     if (!t) {                           /* Failed... */
11378         debug(F111,"z_open error",name,errno);
11379 #ifdef EMFILE
11380         if (errno == EMFILE)
11381           return(z_error = FX_NMF);
11382 #endif /* EMFILE */
11383         return(z_error = (errno ?  FX_SYS : FX_UNK)); /* Return error code */
11384     }
11385 #ifdef NT
11386 #ifdef O_SEQUENTIAL
11387     if (t)                              /* Caching hint for NT */
11388       _setmode(_fileno(t),O_SEQUENTIAL);
11389 #endif /* O_SEQUENTIAL */
11390 #endif /* NT */
11391     z_nopen++;                          /* Open, count it. */
11392     z_file[n].z_fp = t;                 /* Stash the file pointer */
11393     z_file[n].z_flags = flags;          /* and the flags */
11394     z_error = 0;
11395     zfnqfp(name,CKMAXPATH,z_file[n].z_name); /* and the file's full name */
11396     return(n);                          /* Return the channel number */
11397 }
11398
11399 int
11400 z_close(channel) int channel; {         /* Close file on given channel */
11401     int x;
11402     FILE * t;
11403     if (!z_inited)                      /* Called before any files are open? */
11404       return(z_error = FX_NOP);
11405     if (channel >= z_maxchan)           /* Channel out of range? */
11406       return(z_error = FX_CHN);
11407     if (!(t = z_file[channel].z_fp))    /* Channel wasn't open? */
11408       return(z_error = FX_NOP);
11409     errno = 0;                          /* Set errno 0 to get a good reading */
11410     x = fclose(t);                      /* Try to close */
11411     if (x == EOF)                       /* On failure */
11412       return(z_error = FX_SYS);         /* indicate system error. */
11413     z_nopen--;                          /* Closed OK, decrement open count */
11414     z_file[channel].z_fp = NULL;        /* Set file pointer to NULL */
11415     z_file[channel].z_nline = 0;        /* Current line number is 0 */
11416     z_file[channel].z_flags = 0;        /* Set flags to 0 */
11417     *(z_file[channel].z_name) = '\0';   /* Clear name */
11418     return(z_error = 0);
11419 }
11420
11421 /*
11422   Z _ O U T  --  Output string to channel.
11423
11424   Call with:
11425     channel:     Channel number to write to.
11426     s:           String to write.
11427     length > -1: How many characters of s to write.
11428     length < 0:  Write entire NUL-terminated string.
11429     flags == 0:  Supply line termination.
11430     flags >  0:  Don't supply line termination.
11431     flags <  0:  Write 'length' NUL characters.
11432   Special case:
11433     If flags > -1 and s is empty or NULL and length == 1, write 1 NUL.
11434   Returns:
11435     Number of characters written to channel on success, or
11436     negative FX_xxx error code on failure.
11437 */
11438 int
11439 z_out(channel,s,length,flags) int channel, flags, length; char * s; {
11440     FILE * t;
11441     int x, n;
11442     char c = '\0';
11443
11444     if (!s) s = "";                     /* Guard against null pointer */
11445 #ifdef DEBUG
11446     if (deblog) {
11447         debug(F111,"z_out",s,channel);
11448         debug(F101,"z_out length","",length);
11449         debug(F101,"z_out flags","",flags);
11450     }
11451 #endif /* DEBUG */
11452     if (!z_inited)                      /* File i/o inited? */
11453       return(z_error = FX_NOP);
11454     if (channel >= z_maxchan)           /* Channel in range? */
11455       return(z_error = FX_CHN);
11456     if (!(t = z_file[channel].z_fp))    /* File open? */
11457       return(z_error = FX_NOP);
11458     if (!((z_file[channel].z_flags) & (FM_WRI|FM_APP))) /* In write mode? */
11459       return(z_error = FX_FOP);
11460     n = length;                         /* Length of string to write */
11461     if (n < 0) {                        /* Negative means get it ourselves */
11462         if (flags < 0)                  /* Except when told to write NULs in */
11463           return(z_error = FX_RNG);     /* which case args are inconsistent */
11464         n = strlen(s);                  /* Get length of string arg */
11465     }
11466     errno = 0;                          /* Reset errno */
11467     debug(F101,"z_out n","",n);
11468     if (flags < 0) {                    /* Writing NULs... */
11469         int i;
11470         for (i = 0; i < n; i++) {
11471             x = fwrite(&c,1,1,t);
11472             if (x < 1)
11473               return(z_error = (errno ? FX_SYS : FX_UNK));
11474         }
11475         z_file[channel].z_nline = -1;   /* Current line no longer known */
11476         z_error = 0;
11477         return(i);
11478     } else {                            /* Writing string arg */
11479         if (n == 1 && !s[0])            /* Writing one char but it's NUL */
11480           x = fwrite(&c,1,1,t);
11481         else                            /* Writing non-NUL char or string */
11482           x = fwrite(s,1,n,t);
11483         debug(F101,"z_out fwrite",ckitoa(x),errno);
11484         if (x < n)                      /* Failure to write requested amount */
11485           return(z_error = (errno ? FX_SYS : FX_UNK)); /* Return error */
11486         if (flags == 0) {               /* If supplying line termination */
11487             if (fwrite("\n",1,1,t))     /* do that  */
11488               x += z_lt;                /* count the terminator */
11489             if (z_file[channel].z_nline > -1) /* count this line */
11490               z_file[channel].z_nline++;
11491         } else {
11492             z_file[channel].z_nline = -1; /* Current line no longer known */
11493         }
11494     }
11495     z_error = 0;
11496     return(x);
11497 }
11498
11499 #define Z_INBUFLEN 64
11500
11501 /*
11502   Z _ I N  --  Multichannel i/o file input function.
11503
11504   Call with:
11505     channel number to read from.
11506     s = address of destination buffer.
11507     buflen = destination buffer length.
11508     length = Number of bytes to read, must be < buflen.
11509     flags: 0 = read a line; nonzero = read the given number of bytes.
11510   Returns:
11511     Number of bytes read into buffer or a negative error code.
11512     A terminating NUL is deposited after the last byte that was read.
11513 */
11514 int
11515 z_in(channel,s,buflen,length,flags)
11516  int channel, buflen, length, flags; char * s;
11517 /* z_in */ {
11518     int i, j, x;
11519     FILE * t;
11520     char * p;
11521
11522     if (!z_inited)                      /* Check everything... */
11523       return(z_error = FX_NOP);
11524     if (channel >= z_maxchan)
11525       return(z_error = FX_CHN);
11526     if (!(t = z_file[channel].z_fp))
11527       return(z_error = FX_NOP);
11528     if (!((z_file[channel].z_flags) & FM_REA))
11529       return(z_error = FX_FOP);
11530     if (!s)                             /* Check destination */
11531      return(z_error = FX_RNG);
11532     s[0] = NUL;
11533     if (length == 0)                    /* Read 0 bytes - easy. */
11534       return(z_error = 0);
11535     debug(F101,"z_in channel","",channel);
11536     debug(F101,"z_in buflen","",buflen);
11537     debug(F101,"z_in length","",length);
11538     debug(F101,"z_in flags","",flags);
11539     if (length < 0 || buflen < 0)       /* Check length args */
11540       return(z_error = FX_RNG);
11541     if (buflen <= length)
11542       return(z_error = FX_RNG);
11543     errno = 0;                          /* Reset errno */
11544     if (flags) {                        /* Read block or byte */
11545         i = fread(s,1,length,t);
11546 #ifdef DEBUG
11547         if (deblog) {
11548             debug(F111,"z_in block",s,i);
11549             debug(F101,"z_in block errno","",errno);
11550             debug(F101,"z_in block ferror","",ferror(t));
11551             debug(F101,"z_in block feof","",feof(t));
11552         }
11553 #endif /* DEBUG */
11554         z_file[channel].z_nline = -1;   /* Current line no longer known */
11555     } else {                            /* Read line */
11556 #ifndef COMMENT
11557         /* This method is used because it's simpler than the others */
11558         /* and also marginally faster. */
11559         debug(F101,"z_in getc loop","",ftell(t));
11560         for (i = 0; i < length; i++) {
11561             if ((x = getc(t)) == EOF) {
11562                 debug(F101,"z_in getc error","",ftell(t));
11563                 s[i] = '\0';
11564                 break;
11565             }
11566             s[i] = x;
11567             if (s[i] == '\n') {
11568                 s[i] = '\0';
11569                 break;
11570             }
11571         }
11572         debug(F111,"z_in line byte loop",ckitoa(errno),i);
11573         debug(F111,"z_in line got",s,z_file[channel].z_nline);
11574         if (z_file[channel].z_nline > -1)
11575           z_file[channel].z_nline++;
11576 #else
11577 #ifdef COMMENT2
11578         /* Straightforward but strlen() slows it down. */
11579         s[0] = '\0';
11580         i = 0;
11581         if (fgets(s,length,t)) {
11582             i = strlen(s);
11583             if (i > 0 && s[i-1] == '\n') i--;
11584         }
11585         debug(F111,"z_in line fgets",ckitoa(errno),i);
11586         if (z_file[channel].z_nline > -1)
11587           z_file[channel].z_nline++;
11588 #else
11589         /* This is a do-it-yourself fgets() with its own readahead and */
11590         /* putback.  It's a bit faster than real fgets() but not enough */
11591         /* to justify the added complexity or the risk of the ftell() and */
11592         /* fseek() calls failing. */
11593         int k, flag = 0;
11594         long pos;
11595         for (i = 0; !flag && i <= (length - Z_INBUFLEN); i += Z_INBUFLEN) {
11596             k = ((length - i) < Z_INBUFLEN) ? length - i : Z_INBUFLEN;
11597             if ((x = fread(s+i,1,k,t)) < 1)
11598               break;
11599             s[i+x] = '\0';
11600             for (j = 0; j < x; j++) {
11601                 if (s[i+j] == '\n') {
11602                     s[i+j] = '\0';
11603                     flag ++;
11604                     pos = ftell(t);
11605                     if (pos > -1) {
11606                         pos -= (x - j - 1);
11607                         x = fseek(t, pos, 0);
11608                         i += j;
11609                         break;
11610                     } else
11611                       return(z_error = FX_SYS);
11612                 }
11613             }
11614         }
11615         if (z_file[channel].z_nline > -1)
11616           z_file[channel].z_nline++;
11617         debug(F111,"z_in line chunk loop",ckitoa(errno),i);
11618 #endif /* COMMENT2 */
11619 #endif /* COMMENT */
11620     }
11621     debug(F111,"z_in i",ckitoa(errno),i);
11622     if (i < 0) i = 0;                   /* NUL-terminate result */
11623     s[i] = '\0';
11624     if (i > 0) {
11625         z_error = 0;
11626         return(i);
11627     }
11628     if (i == 0 && feof(t))              /* EOF on reading? */
11629       return(z_error = FX_EOF);         /* Return EOF code */
11630     return(errno ? (z_error = -1) : i); /* Return length or system error */
11631 }
11632
11633 int
11634 z_flush(channel) int channel; {         /* Flush output channel */
11635     FILE * t;
11636     int x;
11637     if (!z_inited)                      /* Regular checks */
11638       return(z_error = FX_NOP);
11639     if (channel >= z_maxchan)
11640       return(z_error = FX_CHN);
11641     if (!(t = z_file[channel].z_fp))
11642       return(z_error = FX_NOP);
11643     if (!((z_file[channel].z_flags) & (FM_WRI|FM_APP))) /* Write access? */
11644       return(z_error = FX_FOP);
11645     errno = 0;                          /* Reset errno */
11646     x = fflush(t);                      /* Try to flush */
11647     return(x ? (z_error = FX_SYS) : 0); /* Return system error or 0 if OK */
11648 }
11649
11650 int
11651 #ifdef CK_ANSIC
11652 z_seek(int channel, long pos)           /* Move file pointer to byte */
11653 #else
11654 z_seek(channel,pos) int channel; long pos; /* (seek to given position) */
11655 #endif /* CK_ANSIC */
11656 {
11657     int i, x = 0, rc;
11658     FILE * t;
11659     if (!z_inited)                      /* Check... */
11660       return(z_error = FX_NOP);
11661     if (channel >= z_maxchan)
11662       return(z_error = FX_CHN);
11663     if (!(t = z_file[channel].z_fp))
11664       return(z_error = FX_NOP);
11665     if (pos < 0L) {
11666         x = 2;
11667         pos = (pos == -2) ? -1L : 0L;
11668     }
11669     errno = 0;
11670     rc = fseek(t,pos,x);                /* Try to seek */
11671     debug(F111,"z_seek",ckitoa(errno),rc);
11672     if (rc < 0)                         /* OK? */
11673       return(z_error = FX_SYS); /* No. */
11674     z_file[channel].z_nline = ((pos || x) ? -1 : 0);
11675     return(z_error = 0);
11676 }
11677
11678 int
11679 #ifdef CK_ANSIC
11680 z_line(int channel, long pos)           /* Move file pointer to line */
11681 #else
11682 z_line(channel,pos) int channel; long pos; /* (seek to given position) */
11683 #endif /* CK_ANSIC */
11684 {
11685     int i, len, x = 0;
11686     long current = 0L, prev = -1L, old = -1L;
11687     FILE * t;
11688     char tmpbuf[256];
11689     if (!z_inited)                      /* Check... */
11690       return(z_error = FX_NOP);
11691     if (channel >= z_maxchan)
11692       return(z_error = FX_CHN);
11693     if (!(t = z_file[channel].z_fp))
11694       return(z_error = FX_NOP);
11695     debug(F101,"z_line pos","",pos);
11696     if (pos < 0L) {                     /* EOF wanted */
11697         long n;
11698         n = z_file[channel].z_nline;
11699         debug(F101,"z_line n","",n);
11700         if (n < 0 || pos < 0) {
11701             rewind(t);
11702             n = 0;
11703         }
11704         while (1) {                     /* This could take a while... */
11705             if ((x = getc(t)) == EOF)
11706               break;
11707             if (x == '\n') {
11708                 n++;
11709                 if (pos == -2) {
11710                     old = prev;
11711                     prev = ftell(t);
11712                 }
11713             }
11714         }
11715         debug(F101,"z_line old","",old);
11716         debug(F101,"z_line prev","",prev);
11717         if (pos == -2) {
11718             if ((x = z_seek(channel,old)) < 0)
11719               return(z_error = x);
11720             else
11721               n--;
11722         }
11723         z_file[channel].z_nline = n;
11724         return(z_error = 0);
11725     }
11726     if (pos == 0L) {                    /* Rewind wanted */
11727         z_file[channel].z_nline = 0L;
11728         rewind(t);
11729         debug(F100,"z_line rewind","",0);
11730         return(0L);
11731     }
11732     tmpbuf[255] = NUL;                  /* Make sure buf is NUL terminated */
11733     current = z_file[channel].z_nline;  /* Current line */
11734     /*
11735       If necessary the following could be optimized, e.g. for positioning
11736       to a previous line in a large file without starting over.
11737     */
11738     if (current < 0 || pos < current) { /* Not known or behind us... */
11739         debug(F101,"z_line rewinding","",pos);
11740         if ((x = z_seek(channel, 0L)) < 0) /* Rewind */
11741           return(z_error = x);
11742         if (pos == 0)                   /* If 0th line wanted we're done */
11743           return(z_error = 0);
11744         current = 0;
11745     }
11746     while (current < pos) {             /* Search for specified line */
11747         if (fgets(tmpbuf,255,t)) {
11748             len = strlen(tmpbuf);
11749             if (len > 0 && tmpbuf[len-1] == '\n') {
11750                 current++;
11751                 debug(F111,"z_line read",ckitoa(len),current);
11752             } else if (len == 0) {
11753                 return(z_error = FX_UNK);
11754             }
11755         } else {
11756             z_file[channel].z_nline = -1L;
11757             debug(F101,"z_line premature EOF","",current);
11758             return(z_error = FX_EOF);
11759         }
11760     }
11761     z_file[channel].z_nline = current;
11762     debug(F101,"z_line result","",current);
11763     z_error = 0;
11764     return(current);
11765 }
11766
11767 char *
11768 z_getname(channel) int channel; {       /* Return name of file on channel */
11769     FILE * t;
11770     if (!z_inited) {
11771         z_error = FX_NOP;
11772         return(NULL);
11773     }
11774     if (channel >= z_maxchan) {
11775         z_error = FX_CHN;
11776         return(NULL);
11777     }
11778     if (!(t = z_file[channel].z_fp)) {
11779         z_error = FX_NOP;
11780         return(NULL);
11781     }
11782     return((char *)(z_file[channel].z_name));
11783 }
11784
11785 int
11786 z_getmode(channel) int channel; {       /* Return OPEN modes of channel */
11787     FILE * t;                           /* 0 if file not open */
11788 #ifndef NOSTAT
11789 #ifdef NT
11790     struct _stat statbuf;
11791 #else /* NT */
11792     struct stat statbuf;
11793 #endif /* NT */
11794 #endif /* NOSTAT */
11795     int x;
11796     if (!z_inited)
11797       return(0);
11798     if (channel >= z_maxchan)
11799       return(z_error = FX_CHN);
11800     if (!(t = z_file[channel].z_fp))
11801       return(0);
11802     x = z_file[channel].z_flags;
11803     if (feof(t)) {                      /* This might not work for */
11804         x |= FM_EOF;                    /* output files */
11805 #ifndef NOSTAT
11806     /* But this does if we can use it. */
11807     } else if (stat(z_file[channel].z_name,&statbuf) > -1) {
11808         if (ftell(t) == statbuf.st_size)
11809           x |= FM_EOF;
11810 #endif /* NOSTAT */
11811     }
11812     return(x);
11813 }
11814
11815 long
11816 z_getpos(channel) int channel; {        /* Get file pointer position */
11817     FILE * t;                           /* on this channel */
11818     long x;
11819     if (!z_inited)
11820       return(z_error = FX_NOP);
11821     if (channel >= z_maxchan)
11822       return(z_error = FX_CHN);
11823     if (!(t = z_file[channel].z_fp))
11824       return(z_error = FX_NOP);
11825     x = ftell(t);
11826     return((x < 0L) ? (z_error = FX_SYS) : x);
11827 }
11828
11829 long
11830 z_getline(channel) int channel; {       /* Get current line number */
11831     FILE * t;                           /* in file on this channel */
11832     long rc;
11833     if (!z_inited)
11834       return(z_error = FX_NOP);
11835     if (channel >= z_maxchan)
11836       return(z_error = FX_CHN);
11837     if (!(t = z_file[channel].z_fp))
11838       return(z_error = FX_NOP);
11839     debug(F101,"z_getline","",z_file[channel].z_nline);
11840     rc = z_file[channel].z_nline;
11841     return((rc < 0) ? (z_error = FX_LNU) : rc);
11842 }
11843
11844 int
11845 z_getfnum(channel) int channel; {       /* Get file number / handle */
11846     FILE * t;                           /* for file on this channel */
11847     if (!z_inited)
11848       return(z_error = FX_NOP);
11849     if (channel >= z_maxchan)
11850       return(z_error = FX_CHN);
11851     if (!(t = z_file[channel].z_fp))
11852       return(z_error = FX_NOP);
11853     z_error = 0;
11854     return(fileno(t));
11855 }
11856
11857 /*
11858   Line-oriented counts and seeks are as dumb as they can be at the moment.
11859   Later we can speed them up by building little indexes.
11860 */
11861 long
11862 z_count(channel, what) int channel, what; { /* Count bytes or lines in file */
11863     FILE * t;
11864     int i, x;
11865     long pos, count = 0L;
11866     if (!z_inited)                      /* Check stuff... */
11867       return(z_error = FX_NOP);
11868     if (channel >= z_maxchan)
11869       return(z_error = FX_CHN);
11870     if (!(t = z_file[channel].z_fp))
11871       return(z_error = FX_NOP);
11872     pos = ftell(t);                     /* Save current file pointer */
11873     errno = 0;
11874     z_error = 0;
11875     if (what == RD_CHAR) {              /* Size in bytes requested */
11876         if (!fseek(t,0L,2)) {           /* Seek to end */
11877             count = ftell(t);           /* Get file pointer */
11878             fseek(t,pos,0);             /* Restore file file pointer */
11879             return(count);
11880         } else                          /* Fallback in case seek fails */
11881           return(zgetfs(z_file[channel].z_name));
11882     }
11883     rewind(t);                          /* Line count requested - rewind. */
11884     while (1) {                         /* Count lines. */
11885         if ((x = getc(t)) == EOF)       /* Stupid byte loop */
11886           break;                        /* but it works as well as anything */
11887         if (x == '\n')                  /* else... */
11888           count++;
11889     }
11890     x = fseek(t,pos,0);                 /* Restore file pointer */
11891     return(count);
11892 }
11893
11894 /* User interface for generalized channel-oriented file i/o */
11895
11896 struct keytab fctab[] = {               /* FILE subcommands */
11897     { "close",      FIL_CLS, 0 },
11898     { "count",      FIL_COU, 0 },
11899     { "flush",      FIL_FLU, 0 },
11900     { "list",       FIL_LIS, 0 },
11901     { "open",       FIL_OPN, 0 },
11902     { "read",       FIL_REA, 0 },
11903     { "rewind",     FIL_REW, 0 },
11904     { "seek",       FIL_SEE, 0 },
11905     { "status",     FIL_STA, 0 },
11906     { "write",      FIL_WRI, 0 }
11907 };
11908 int nfctab = (sizeof (fctab) / sizeof (struct keytab));
11909
11910 static struct keytab fcswtab[] = {      /* OPEN modes */
11911     { "/append",    FM_APP,  0 },
11912     { "/binary",    FM_BIN,  0 },
11913 #ifdef COMMENT
11914     { "/command",   FM_CMD,  0 },       /* Not implemented */
11915 #endif /* COMMENT */
11916     { "/read",      FM_REA,  0 },
11917     { "/write",     FM_WRI,  0 }
11918 };
11919 static int nfcswtab = (sizeof (fcswtab) / sizeof (struct keytab));
11920
11921 static struct keytab fclkwtab[] = {     /* CLOSE options */
11922     { "all",        1,       0 }
11923 };
11924
11925 static struct keytab fsekwtab[] = {     /* SEEK symbols */
11926     { "eof",        1,       0 },
11927     { "last",       2,       0 }
11928 };
11929 static int nfsekwtab = (sizeof (fsekwtab) / sizeof (struct keytab));
11930
11931 #define SEE_LINE  RD_LINE               /* SEEK options */
11932 #define SEE_CHAR  RD_CHAR
11933 #define SEE_REL   3
11934 #define SEE_ABS   4
11935
11936 static struct keytab fskswtab[] = {
11937     { "/absolute",  SEE_ABS,  0 },
11938     { "/byte",      SEE_CHAR, 0 },
11939     { "/character", SEE_CHAR, CM_INV },
11940     { "/line",      SEE_LINE, 0 },
11941     { "/relative",  SEE_REL,  0 }
11942 };
11943 static int nfskswtab = (sizeof (fskswtab) / sizeof (struct keytab));
11944
11945 #define COU_LINE  RD_LINE               /* COUNT options */
11946 #define COU_CHAR  RD_CHAR
11947 #define COU_LIS   3
11948 #define COU_NOL   4
11949
11950 static struct keytab fcoswtab[] = {
11951     { "/bytes",     COU_CHAR, 0      },
11952     { "/characters",COU_CHAR, CM_INV },
11953     { "/lines",     COU_LINE, 0      },
11954     { "/list",      COU_LIS,  0      },
11955     { "/nolist",    COU_NOL,  0      },
11956     { "/quiet",     COU_NOL,  CM_INV }
11957 };
11958 static int nfcoswtab = (sizeof (fcoswtab) / sizeof (struct keytab));
11959
11960 static struct keytab frdtab[] = {       /* READ types */
11961     { "/block",     RD_SIZE, CM_INV|CM_ARG },
11962     { "/byte",      RD_CHAR, CM_INV },
11963     { "/character", RD_CHAR, 0      },
11964     { "/line",      RD_LINE, 0      },
11965     { "/size",      RD_SIZE, CM_ARG },
11966     { "/trim",      RD_TRIM, 0      },
11967     { "/untabify",  RD_UNTA, 0      }
11968 };
11969 static int nfrdtab = (sizeof (frdtab) / sizeof (struct keytab));
11970
11971 static struct keytab fwrtab[] = {       /* WRITE types */
11972     { "/block",     WR_SIZE, CM_INV|CM_ARG },
11973     { "/byte",      WR_CHAR, CM_INV },
11974     { "/character", WR_CHAR, 0      },
11975     { "/line",      WR_LINE, 0      },
11976     { "/lpad",      WR_LPAD, CM_ARG },
11977     { "/rpad",      WR_RPAD, CM_ARG },
11978     { "/size",      WR_SIZE, CM_ARG },
11979     { "/string",    WR_STRI, 0      }
11980 };
11981 static int nfwrtab = (sizeof (fwrtab) / sizeof (struct keytab));
11982
11983 static char blanks[] = "\040\040\040\040"; /* Some blanks for formatting */
11984
11985 int
11986 dofile(op) int op; {                    /* Do the FILE command */
11987     char vnambuf[VNAML];                /* Buffer for variable names */
11988     char *vnp = NULL;                   /* Pointer to same */
11989     char zfilnam[CKMAXPATH+2];
11990     char * p;
11991     struct FDB fl, sw, nu;
11992     long z;
11993     int rsize, filmode = 0, relative = -1, eofflg = 0;
11994     int rc, x, y, cx, n, getval, dummy, confirmed, listing = -1;
11995     int charflag = 0, sizeflag = 0;
11996     int pad = 32, wr_lpad = 0, wr_rpad = 0, rd_trim = 0, rd_untab = 0;
11997
11998     if (op == XXFILE) {                 /* FILE command was given */
11999         /* Get subcommand */
12000         if ((cx = cmkey(fctab,nfctab,"Operation","",xxstring)) < 0) {
12001             if (cx == -3) {
12002                 printf("?File operation required\n");
12003                 x = -9;
12004             }
12005             return(cx);
12006         }
12007     } else {                            /* Shorthand command was given */
12008         switch (op) {
12009           case XXF_CL: cx = FIL_CLS; break; /* FCLOSE */
12010           case XXF_FL: cx = FIL_FLU; break; /* FFLUSH */
12011           case XXF_LI: cx = FIL_LIS; break; /* FLIST */
12012           case XXF_OP: cx = FIL_OPN; break; /* etc... */
12013           case XXF_RE: cx = FIL_REA; break;
12014           case XXF_RW: cx = FIL_REW; break;
12015           case XXF_SE: cx = FIL_SEE; break;
12016           case XXF_ST: cx = FIL_STA; break;
12017           case XXF_WR: cx = FIL_WRI; break;
12018           case XXF_CO: cx = FIL_COU; break;
12019           default: return(-2);
12020         }
12021     }
12022     switch (cx) {                       /* Do requested subcommand */
12023       case FIL_OPN:                     /* OPEN */
12024         cmfdbi(&sw,                     /* Switches */
12025                _CMKEY,                  /* fcode */
12026                "Variable or switch",    /* hlpmsg */
12027                "",                      /* default */
12028                "",                      /* addtl string data */
12029                nfcswtab,                /* addtl numeric data 1: tbl size */
12030                4,                       /* addtl numeric data 2: 4 = cmswi */
12031                xxstring,                /* Processing function */
12032                fcswtab,                 /* Keyword table */
12033                &fl                      /* Pointer to next FDB */
12034                );
12035         cmfdbi(&fl,                     /* Anything that doesn't match */
12036                _CMFLD,                  /* fcode */
12037                "Variable",              /* hlpmsg */
12038                "",
12039                "",
12040                0,
12041                0,
12042                NULL,
12043                NULL,
12044                NULL
12045                );
12046         while (1) {
12047             x = cmfdb(&sw);             /* Parse something */
12048             if (x < 0) {
12049                 if (x == -3) {
12050                     printf("?Variable name and file name required\n");
12051                     x = -9;
12052                 }
12053                 return(x);
12054             }
12055             if (cmresult.fcode == _CMFLD)
12056               break;
12057             else if (cmresult.fcode == _CMKEY) {
12058                 char c;
12059                 c = cmgbrk();
12060                 if ((getval =
12061                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12062                     printf("?This switch does not take an argument\n");
12063                     return(-9);
12064                 }
12065 #ifdef COMMENT
12066                 /* Uncomment if we add any switches ere that take args */
12067                 if (!getval && (cmgkwflgs() & CM_ARG)) {
12068                     printf("?This switch requires an argument\n");
12069                     return(-9);         /* (none do...) */
12070                 }
12071 #endif /* COMMENT */
12072                 filmode |= cmresult.nresult; /* OR in the file mode */
12073             } else
12074               return(-2);
12075         }
12076         /* Not a switch - get the string */
12077         ckstrncpy(vnambuf,cmresult.sresult,VNAML);
12078         if (!vnambuf[0] || chknum(vnambuf)) { /* (if there is one...) */
12079             printf("?Variable name required\n");
12080             return(-9);
12081         }
12082         vnp = vnambuf;                  /* Check variable-name syntax */
12083         if (vnambuf[0] == CMDQ &&
12084             (vnambuf[1] == '%' || vnambuf[1] == '&'))
12085           vnp++;
12086         y = 0;
12087         if (*vnp == '%' || *vnp == '&') {
12088             if ((y = parsevar(vnp,&x,&dummy)) < 0) {
12089                 printf("?Syntax error in variable name\n");
12090                 return(-9);
12091             }
12092         }
12093         if (!(filmode & FM_RWA))        /* If no access mode specified */
12094           filmode |= FM_REA;            /* default to /READ. */
12095
12096         y = 0;                          /* Now parse the filename */
12097         if ((filmode & FM_RWA) == FM_WRI)
12098           x = cmofi("Name of new file","",&s,xxstring);
12099         else if ((filmode & FM_RWA) == FM_REA)
12100           x = cmifi("Name of existing file","",&s,&y,xxstring);
12101         else {
12102             x = cmiofi("Filename","",&s,&y,xxstring);
12103             debug(F101,"fopen /append x","",x);
12104         }
12105         if (x == -9) {
12106             if (zchko(s) < 0) {
12107                 printf("Can't create \"%s\"\n",s);
12108                 return(x);
12109             }
12110         } else if (x < 0) {
12111             if (x == -3) {
12112                 printf("?Filename required\n");
12113                 x = -9;
12114             }
12115             return(x);
12116         }
12117         if (y) {                        /* No wildcards */
12118             printf("?Wildcards not allowed here\n");
12119             return(-9);
12120         }
12121         if (filmode & (FM_APP|FM_WRI)) { /* Check output access */
12122 #ifndef VMS
12123             if (zchko(s) < 0) {          /* and set error code if denied */
12124                 z_error = FX_ACC;
12125                 printf("?Write access denied - \"%s\"\n",s);
12126                 return(-9);
12127             }
12128 #endif /* VMS */
12129         }
12130         ckstrncpy(zfilnam,s,CKMAXPATH); /* Is OK - make safe copy */
12131         if ((x = cmcfm()) < 0)          /* Get confirmation of command */
12132           return(x);
12133         if ((n = z_open(zfilnam,filmode)) < 0) {
12134             printf("?OPEN failed - %s: %s\n",zfilnam,ckferror(n));
12135             return(-9);
12136         }
12137         addmac(vnambuf,ckitoa(n));      /* Assign channel number to variable */
12138         return(success = 1);
12139
12140       case FIL_REW:                     /* REWIND */
12141         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
12142             if (x == -3) {
12143                 printf("?Channel number required\n");
12144                 x = -9;
12145             }
12146             return(x);
12147         }
12148         if ((x = cmcfm()) < 0)
12149           return(x);
12150         if ((rc = z_seek(n,0L)) < 0) {
12151             printf("?REWIND failed - Channel %d: %s\n",n,ckferror(rc));
12152             return(-9);
12153         }
12154         return(success = 1);
12155
12156       case FIL_CLS:                     /* CLOSE */
12157           cmfdbi(&sw,                   /* Second FDB - switches */
12158                  _CMKEY,                /* fcode */
12159                  "Channel number; or keyword",
12160                  "",
12161                  "",                    /* addtl string data */
12162                  1,                     /* addtl numeric data 1: tbl size */
12163                  0,                     /* addtl numeric data 2: 4 = cmswi */
12164                  xxstring,              /* Processing function */
12165                  fclkwtab,              /* Keyword table */
12166                  &nu                    /* Pointer to next FDB */
12167                  );
12168           cmfdbi(&nu,                   /* First FDB - command switches */
12169                  _CMNUM,                /* fcode */
12170                  "",
12171                  "",                    /* default */
12172                  "",                    /* addtl string data */
12173                  10,                    /* addtl numeric data 1: radix */
12174                  0,                     /* addtl numeric data 2: 0 */
12175                  xxstring,              /* Processing function */
12176                  NULL,                  /* Keyword table */
12177                  NULL                   /* Pointer to next FDB */
12178                  );                     /*  */
12179         x = cmfdb(&sw);                 /* Parse something */
12180         if (x < 0) {
12181             if (x == -3) {
12182                 printf("?Channel number or ALL required\n");
12183                 x = -9;
12184             }
12185             return(x);
12186         }
12187         if (cmresult.fcode == _CMNUM)
12188           n = cmresult.nresult;
12189         else if (cmresult.fcode == _CMKEY)
12190           n = -1;
12191         if ((x = cmcfm()) < 0)
12192           return(x);
12193         rc = 1;
12194         if (n < 0) {
12195             int count = 0;
12196             int i;
12197             for (i = 0; i < z_maxchan; i++) {
12198                 x = z_close(i);
12199                 if (x == FX_SYS) {
12200                     printf("?CLOSE failed - Channel %d: %s\n",n,ckferror(x));
12201                     rc = 0;
12202                 } else if (x > -1)
12203                   count++;
12204             }
12205             debug(F101,"FILE CLOSE ALL","",count);
12206         } else if ((x = z_close(n)) < 0) {
12207             printf("?CLOSE failed - Channel %d: %s\n",n,ckferror(x));
12208             return(-9);
12209         }
12210         return(success = rc);
12211
12212       case FIL_REA:                     /* READ */
12213       case FIL_WRI:                     /* WRITE */
12214         rsize = 0;
12215         cmfdbi(&sw,                     /* Switches */
12216                _CMKEY,                  /* fcode */
12217                "Channel or switch",     /* hlpmsg */
12218                "",                      /* default */
12219                "",                      /* addtl string data */
12220                (cx == FIL_REA) ? nfrdtab : nfwrtab,
12221                4,                       /* addtl numeric data 2: 4 = cmswi */
12222                xxstring,                /* Processing function */
12223                (cx == FIL_REA) ? frdtab : fwrtab, /* Keyword table */
12224                &nu                      /* Pointer to next FDB */
12225                );
12226         cmfdbi(&nu,                     /* Channel number */
12227                _CMNUM,                  /* fcode */
12228                "Channel",
12229                "",                      /* default */
12230                "",                      /* addtl string data */
12231                10,                      /* addtl numeric data 1: radix */
12232                0,                       /* addtl numeric data 2: 0 */
12233                xxstring,                /* Processing function */
12234                NULL,                    /* Keyword table */
12235                NULL                     /* Pointer to next FDB */
12236                );
12237         do {
12238             x = cmfdb(&sw);             /* Parse something */
12239             if (x < 0) {
12240                 if (x == -3) {
12241                     printf("?Channel number required\n");
12242                     x = -9;
12243                 }
12244                 return(x);
12245             }
12246             if (cmresult.fcode == _CMNUM) /* Channel number */
12247               break;
12248             else if (cmresult.fcode == _CMKEY) { /* Switch */
12249                 char c;
12250                 c = cmgbrk();
12251                 if ((getval =
12252                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12253                     printf("?This switch does not take an argument\n");
12254                     return(-9);
12255                 }
12256                 if (!getval && (cmgkwflgs() & CM_ARG)) {
12257                     printf("?This switch requires an argument\n");
12258                     return(-9);
12259                 }
12260                 switch (cmresult.nresult) {
12261                   case WR_LINE:
12262                     charflag = 0;
12263                     sizeflag = 0;
12264                     rsize = 0;
12265                     break;
12266                   case WR_CHAR:
12267                     rsize = 1;
12268                     charflag = 1;
12269                     sizeflag = 1;
12270                     break;
12271                   case WR_SIZE:
12272                     if ((x = cmnum("Bytes","",10,&rsize, xxstring)) < 0) {
12273                         if (x == -3) {
12274                             printf("?Number required\n");
12275                             x = -9;
12276                         }
12277                         return(x);
12278                     }
12279                     charflag = 0;
12280                     sizeflag = 1;
12281                     break;
12282                   case WR_STRI:
12283                     rsize = 1;
12284                     charflag = 0;
12285                     sizeflag = 0;
12286                     break;
12287                   case WR_LPAD:
12288                   case WR_RPAD:
12289                     if ((x = cmnum("Numeric ASCII character value",
12290                                    "32",10,&pad, xxstring)) < 0)
12291                       return(x);
12292                     if (cmresult.nresult == WR_LPAD)
12293                       wr_lpad = 1;
12294                     else
12295                       wr_rpad = 1;
12296                     break;
12297                   case RD_TRIM:
12298                     rd_trim = 1;
12299                     break;
12300                   case RD_UNTA:
12301                     rd_untab = 1;
12302                     break;
12303                 }
12304                 debug(F101,"FILE READ rsize 2","",rsize);
12305             } else
12306               return(-2);
12307         } while
12308           (cmresult.fcode == _CMKEY);
12309
12310         n = cmresult.nresult;           /* Channel */
12311         debug(F101,"FILE READ/WRITE channel","",n);
12312
12313         if (cx == FIL_WRI) {            /* WRITE */
12314             int len = 0;
12315             if ((x = cmtxt("Text","",&s,xxstring)) < 0)
12316               return(x);
12317             ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy */
12318             s = line;
12319             s = brstrip(s);             /* Strip braces */
12320             if (charflag) {             /* Write one char */
12321                 len = 1;                /* So length = 1 */
12322                 rsize = 1;              /* Don't supply terminator */
12323             } else if (!sizeflag) {     /* Write a string */
12324                 len = -1;               /* So length is unspecified */
12325             } else {                    /* Write a block of given size */
12326                 int i, k, xx;
12327                 if (rsize > TMPBUFSIZ) {
12328                     z_error = FX_OFL;
12329                     printf("?Buffer overflow\n");
12330                     return(-9);
12331                 }
12332                 len = rsize;            /* rsize is really length */
12333                 rsize = 1;              /* Don't supply a terminator */
12334                 xx = strlen(s);         /* Size of given string */
12335                 if (xx >= len) {        /* Bigger or equal */
12336                     s[len] = NUL;
12337                 } else if (wr_lpad) {   /* Smaller, left-padding requested */
12338                     for (i = 0; i < len - xx; i++) /* Must make a copy */
12339                       tmpbuf[i] = pad;
12340                     ckstrncpy(tmpbuf+i,s,TMPBUFSIZ-i);
12341                     tmpbuf[len] = NUL;
12342                     s = tmpbuf;         /* Redirect write source */
12343                 } else if (wr_rpad) {   /* Smaller with right-padding */
12344                     for (i = xx; i < len; i++)
12345                       s[i] = pad;
12346                     s[len] = NUL;
12347                 }
12348             }
12349             if ((rc = z_out(n,s,len,rsize)) < 0) { /* Try to write */
12350                 printf("?Channel %d WRITE error: %s\n",n,ckferror(rc));
12351                 return(-9);
12352             }
12353         } else {                        /* FIL_REA READ */
12354             confirmed = 0;
12355             vnambuf[0] = NUL;
12356             x = cmfld("Variable name","",&s,NULL);
12357             debug(F111,"FILE READ cmfld",s,x);
12358             if (x < 0) {
12359                 if (x == -3 || !*s) {
12360                     if ((x = cmcfm()) < 0)
12361                       return(x);
12362                     else
12363                       confirmed++;
12364                 } else
12365                   return(x);
12366             }
12367             ckstrncpy(vnambuf,s,VNAML);
12368             debug(F111,"FILE READ vnambuf",vnambuf,confirmed);
12369             if (vnambuf[0]) {           /* Variable name given, check it */
12370                 if (!confirmed) {
12371                     x = cmcfm();
12372                     if (x < 0)
12373                       return(x);
12374                     else
12375                       confirmed++;
12376                 }
12377                 vnp = vnambuf;
12378                 if (vnambuf[0] == CMDQ &&
12379                     (vnambuf[1] == '%' || vnambuf[1] == '&'))
12380                   vnp++;
12381                 y = 0;
12382                 if (*vnp == '%' || *vnp == '&') {
12383                     if ((y = parsevar(vnp,&x,&dummy)) < 0) {
12384                         printf("?Syntax error in variable name\n");
12385                         return(-9);
12386                     }
12387                 }
12388             }
12389             debug(F111,"FILE READ variable",vnambuf,confirmed);
12390
12391             if (!confirmed)
12392               if ((x = cmcfm()) < 0)
12393                 return(x);
12394
12395             line[0] = NUL;              /* Clear destination buffer */
12396             if (rsize >= LINBUFSIZ)     /* Don't overrun it */
12397               rsize = LINBUFSIZ - 1;
12398
12399             if (rsize == 0) {           /* Read a line */
12400                 rc = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
12401             } else {
12402                 rc = z_in(n,line,LINBUFSIZ,rsize,1); /* Read a block */
12403             }
12404             if (rc < 0) {               /* Error... */
12405                 debug(F101,"FILE READ error","",rc);
12406                 debug(F101,"FILE READ errno","",errno);
12407                 if (rc == FX_EOF) {     /* EOF - fail but no error message */
12408                     return(success = 0);
12409                 } else {                /* Other error - fail and print msg */
12410                     printf("?READ error: %s\n",ckferror(rc));
12411                     return(-9);
12412                 }
12413             }
12414             if (rsize == 0) {           /* FREAD /LINE postprocessing */
12415                 if (rd_trim) {          /* Trim */
12416                     int i, k;
12417                     k = strlen(line);
12418                     if (k > 0) {
12419                         for (i = k-1; i > 0; i--) {
12420                             if (line[i] == SP || line[i] == '\t')
12421                               line[i] = NUL;
12422                             else
12423                               break;
12424                         }
12425                     }
12426                 }
12427                 if (rd_untab) {         /* Untabify */
12428                     if (untabify(line,tmpbuf,TMPBUFSIZ) > -1)
12429                       ckstrncpy(line,tmpbuf,LINBUFSIZ);
12430                 }
12431             }
12432             debug(F110,"FILE READ data",line,0);
12433             if (vnambuf[0])             /* Read OK - If variable name given */
12434               addmac(vnambuf,line);     /* Assign result to variable */
12435             else                        /* otherwise */
12436               printf("%s\n",line);      /* just print it */
12437         }
12438         return(success = 1);
12439
12440       case FIL_SEE:                     /* SEEK */
12441       case FIL_COU:                     /* COUNT */
12442         rsize = RD_CHAR;                /* Defaults to /BYTE */
12443         cmfdbi(&sw,                     /* Switches */
12444                _CMKEY,                  /* fcode */
12445                "Channel or switch",     /* hlpmsg */
12446                "",                      /* default */
12447                "",                      /* addtl string data */
12448                ((cx == FIL_SEE) ? nfskswtab : nfcoswtab),
12449                4,                       /* addtl numeric data 2: 4 = cmswi */
12450                xxstring,                /* Processing function */
12451                ((cx == FIL_SEE) ? fskswtab : fcoswtab),
12452                &nu                      /* Pointer to next FDB */
12453                );
12454         cmfdbi(&nu,                     /* Channel number */
12455                _CMNUM,                  /* fcode */
12456                "Channel",
12457                "",                      /* default */
12458                "",                      /* addtl string data */
12459                10,                      /* addtl numeric data 1: radix */
12460                0,                       /* addtl numeric data 2: 0 */
12461                xxstring,                /* Processing function */
12462                NULL,                    /* Keyword table */
12463                NULL                     /* Pointer to next FDB */
12464                );
12465         do {
12466             x = cmfdb(&sw);             /* Parse something */
12467             if (x < 0) {
12468                 if (x == -3) {
12469                     printf("?Channel number required\n");
12470                     x = -9;
12471                 }
12472                 return(x);
12473             }
12474             if (cmresult.fcode == _CMNUM) /* Channel number */
12475               break;
12476             else if (cmresult.fcode == _CMKEY) { /* Switch */
12477                 char c;
12478                 c = cmgbrk();
12479                 if ((getval =
12480                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12481                     printf("?This switch does not take an argument\n");
12482                     return(-9);
12483                 }
12484                 if (cx == FIL_SEE) {
12485                     switch (cmresult.nresult) {
12486                       case SEE_REL: relative = 1; break;
12487                       case SEE_ABS: relative = 0; break;
12488                       default: rsize = cmresult.nresult;
12489                     }
12490                 } else if (cx == FIL_COU) {
12491                     switch (cmresult.nresult) {
12492                       case COU_LIS: listing = 1; break;
12493                       case COU_NOL: listing = 0; break;
12494                       default: rsize = cmresult.nresult;
12495                     }
12496                 }
12497             }
12498         } while
12499           (cmresult.fcode == _CMKEY);
12500
12501         n = cmresult.nresult;           /* Channel */
12502         debug(F101,"FILE SEEK/COUNT channel","",n);
12503         if (cx == FIL_COU) {
12504             if ((x = cmcfm()) < 0)
12505               return(x);
12506             z_filcount = z_count(n,rsize);
12507             if (z_filcount < 0) {
12508                 rc = z_filcount;
12509                 printf("?COUNT error: %s\n",ckferror(rc));
12510                 return(-9);
12511             }
12512             if (listing < 0)
12513               listing = !xcmdsrc;
12514             if (listing)
12515               printf(" %ld %s%s\n",
12516                      z_filcount,
12517                      ((rsize == RD_CHAR) ? "byte" : "line"),
12518                      ((z_filcount == 1L) ? "" : "s")
12519                      );
12520             return(success = (z_filcount > -1) ? 1 : 0);
12521         }
12522         cmfdbi(&sw,                     /* SEEK symbolic targets (EOF) */
12523                _CMKEY,                  /* fcode */
12524                "Channel number;\n or keyword",
12525                "",
12526                "",                      /* addtl string data */
12527                nfsekwtab,               /* addtl numeric data 1: table size */
12528                0,                       /* addtl numeric data 2: 4 = cmswi */
12529                xxstring,                /* Processing function */
12530                fsekwtab,                /* Keyword table */
12531                &nu                      /* Pointer to next FDB */
12532                );
12533         cmfdbi(&nu,                     /* Channel number */
12534                _CMNUM,                  /* fcode */
12535                "",
12536                "",                      /* default */
12537                "",                      /* addtl string data */
12538                10,                      /* addtl numeric data 1: radix */
12539                0,                       /* addtl numeric data 2: 0 */
12540                xxstring,                /* Processing function */
12541                NULL,                    /* Keyword table */
12542                NULL                     /* Pointer to next FDB */
12543                );
12544         x = cmfdb(&sw);                 /* Parse something */
12545         if (x < 0) {
12546             if (x == -3) {
12547                 printf("?Channel number or EOF required\n");
12548                 x = -9;
12549             }
12550             return(x);
12551         }
12552         if (cmresult.fcode == _CMNUM) {
12553             y = cmresult.nresult;
12554             debug(F110,"FILE SEEK atmbuf",atmbuf,0);
12555             if (relative < 0) {
12556                 if (cx == FIL_SEE && (atmbuf[0] == '+' || atmbuf[0] == '-'))
12557                   relative = 1;
12558                 else
12559                   relative = 0;
12560             }
12561         } else if (cmresult.fcode == _CMKEY) {
12562             eofflg = cmresult.nresult;
12563             relative = 0;
12564             y = 0 - eofflg;
12565         }
12566         if ((x = cmcfm()) < 0)
12567           return(x);
12568         z = y;                          /* Convert to long */
12569         y = 1;                          /* Recycle this */
12570         z_flush(n);
12571         debug(F101,"FILE SEEK relative","",relative);
12572         debug(F101,"FILE SEEK rsize","",rsize);
12573
12574         if (rsize == RD_CHAR) {         /* Seek to byte position */
12575             if (relative > 0) {
12576                 long pos;
12577                 pos = z_getpos(n);
12578                 if (pos < 0L) {
12579                     rc = pos;
12580                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
12581                     return(-9);
12582                 }
12583                 z += pos;
12584             } else {
12585                 if (z < 0 && !eofflg) { /* Negative arg but not relative */
12586                     y = 0;              /* Remember this was bad */
12587                     z = 0;              /* but substitute 0 */
12588                 }
12589             }
12590             debug(F101,"FILE SEEK /CHAR z","",z);
12591             if (z < 0 && !eofflg) {
12592                 z_error = FX_RNG;
12593                 return(success = 0);
12594             }
12595             if ((rc = z_seek(n,z)) < 0) {
12596                 if (rc == FX_EOF) return(success = 0);
12597                 printf("?SEEK /BYTE failed - Channel %d: %s\n",n,ckferror(rc));
12598                 return(-9);
12599             }
12600         } else {                        /* Seek to line */
12601             if (relative > 0) {
12602                 long pos;
12603                 pos = z_getline(n);
12604                 debug(F101,"FILE SEEK /LINE pos","",pos);
12605                 if (pos < 0L) {
12606                     rc = pos;
12607                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
12608                     return(-9);
12609                 }
12610                 z += pos;
12611             }
12612             debug(F101,"FILE SEEK /LINE z","",z);
12613             debug(F101,"FILE SEEK /LINE eofflg","",eofflg);
12614             if (z < 0 && !eofflg) {
12615                 z_error = FX_RNG;
12616                 return(success = 0);
12617             }
12618             if ((rc = z_line(n,z)) < 0) {
12619                 if (rc == FX_EOF) return(success = 0);
12620                 printf("?SEEK /LINE failed - Channel %d: %s\n",n,ckferror(rc));
12621                 return(-9);
12622             }
12623         }
12624         return(success = y);
12625
12626       case FIL_LIS: {                   /* LIST open files */
12627 #ifdef CK_TTGWSIZ
12628           extern int cmd_rows, cmd_cols;
12629 #endif /* CK_TTGWSIZ */
12630           extern int xaskmore;
12631           int i, x, n = 0, paging = 0;
12632           char * s;
12633
12634           if ((x = cmcfm()) < 0)
12635             return(x);
12636
12637 #ifdef CK_TTGWSIZ
12638           if (cmd_rows > 0 && cmd_cols > 0)
12639 #endif /* CK_TTGWSIZ */
12640             paging = xaskmore;
12641
12642           printf("System open file limit: %4d\n", z_openmax);
12643           printf("Maximum for FILE OPEN:  %4d\n", z_maxchan);
12644           printf("Files currently open:   %4d\n\n", z_nopen);
12645           n = 4;
12646           for (i = 0; i < z_maxchan; i++) {
12647               s = z_getname(i);         /* Got one? */
12648               if (s) {                  /* Yes */
12649                   char m[8];
12650                   m[0] = NUL;
12651                   printf("%2d. %s",i,s); /* Print name */
12652                   n++;                   /* Count it */
12653                   x = z_getmode(i);      /* Get modes & print them */
12654                   if (x > -1) {
12655                       if (x & FM_REA) ckstrncat(m,"R",8);
12656                       if (x & FM_WRI) ckstrncat(m,"W",8);
12657                       if (x & FM_APP) ckstrncat(m,"A",8);
12658                       if (x & FM_BIN) ckstrncat(m,"B",8);
12659                       if (m[0])
12660                         printf(" (%s)",m);
12661                       if (x & FM_EOF)
12662                         printf(" [EOF]");
12663                       else
12664                         printf(" %ld",z_getpos(i)); /* And file position too */
12665                   }
12666                   printf("\n");
12667 #ifdef CK_TTGWSIZ
12668                   if (paging > 0) {     /* Pause at end of screen */
12669                       if (n > cmd_rows - 3) {
12670                           if (!askmore())
12671                             break;
12672                           else
12673                             n = 0;
12674                       }
12675                   }
12676 #endif /* CK_TTGWSIZ */
12677               }
12678           }
12679           return(success = 1);
12680       }
12681
12682       case FIL_FLU:                     /* FLUSH */
12683         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
12684             if (x == -3) {
12685                 printf("?Channel number required\n");
12686                 x = -9;
12687             }
12688             return(x);
12689         }
12690         if ((x = cmcfm()) < 0)
12691           return(x);
12692         if ((rc = z_flush(n)) < 0) {
12693             printf("?FLUSH failed - Channel %d: %s\n",n,ckferror(rc));
12694             return(-9);
12695         }
12696         return(success = 1);
12697
12698       case FIL_STA:                     /* STATUS */
12699         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
12700             if (x == -3) {
12701                 printf("?Channel number required\n");
12702                 x = -9;
12703             }
12704             return(x);
12705         }
12706         if ((x = cmcfm()) < 0)
12707           return(x);
12708         p = blanks + 3;                 /* Tricky formatting... */
12709         if (n < 1000) p--;
12710         if (n < 100) p--;
12711         if (n < 10) p--;
12712         if ((rc = z_getmode(n)) < 0) {
12713             printf("Channel %d:%s%s\n",n,p,ckferror(rc));
12714             return(success = 0);
12715         } else if (!rc) {
12716             printf("Channel %d:%sNot open\n",n,p);
12717             return(success = 0);
12718         } else {
12719             long xx;
12720             s = z_getname(n);
12721             if (!s) s = "(name unknown)";
12722             printf("Channel %d:%sOpen\n",n,p);
12723             printf(" File:        %s\n Modes:      ",s);
12724             if (rc & FM_REA) printf(" /READ");
12725             if (rc & FM_WRI) printf(" /WRITE");
12726             if (rc & FM_APP) printf(" /APPEND");
12727             if (rc & FM_BIN) printf(" /BINARY");
12728             if (rc & FM_CMD) printf(" /COMMAND");
12729             if (rc & FM_EOF) printf(" [EOF]");
12730             printf("\n Size:        %ld\n",z_count(n,RD_CHAR));
12731             printf(" At byte:     %ld\n",z_getpos(n));
12732             xx = z_getline(n);
12733             if (xx > -1)
12734               printf(" At line:     %ld\n",xx);
12735             return(success = 1);
12736         }
12737       default:
12738         return(-2);
12739     }
12740 }
12741 #endif /* CKCHANNELIO */
12742
12743 #ifndef NOSETKEY
12744 /* Save Key maps and in OS/2 Mouse maps */
12745 int
12746 savkeys(name,disp) char * name; int disp; {
12747     char *tp;
12748     static struct filinfo xx;
12749     int savfil, i, j, k;
12750     char buf[1024];
12751
12752     zclose(ZMFILE);
12753
12754     if (disp) {
12755         xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
12756         xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
12757         xx.lblopts = 0;
12758         savfil = zopeno(ZMFILE,name,NULL,&xx);
12759     } else savfil = zopeno(ZMFILE,name,NULL,NULL);
12760
12761     if (savfil) {
12762 #ifdef OS2
12763         ztime(&tp);
12764         zsout(ZMFILE, "; Kermit 95 SAVE KEYMAP file: ");
12765         zsoutl(ZMFILE,tp);
12766         if (mskkeys) {
12767             zsoutl(ZMFILE,
12768          "if eq \"\\v(program)\" \"C-Kermit\" set mskermit keycodes on");
12769         } else {
12770             zsoutl(ZMFILE,
12771          "if NOT eq \"\\v(program)\" \"C-Kermit\" stop 1 C-Kermit required.");
12772             zsoutl(ZMFILE,"set mskermit keycodes off");
12773         }
12774         zsoutl(ZMFILE,"");
12775 #else /* OS2 */
12776         ztime(&tp);
12777         zsout(ZMFILE, "; C-Kermit SAVE KEYMAP file: ");
12778         zsoutl(ZMFILE,tp);
12779 #endif /* OS2 */
12780
12781         zsoutl(ZMFILE,"; Clear previous keyboard mappings ");
12782         zsoutl(ZMFILE,"set key clear");
12783 #ifdef OS2
12784         for (k = 0; k < nttkey; k++) {
12785             if (!ttkeytab[k].flgs) {
12786                 ckmakmsg(buf,1024,
12787                          "set terminal key ",
12788                          ttkeytab[k].kwd,
12789                          " clear",
12790                          NULL
12791                          );
12792                 zsoutl(ZMFILE,buf);
12793             }
12794         }
12795 #endif /* OS2 */
12796         zsoutl(ZMFILE,"");
12797
12798         for (i = 0; i < KMSIZE; i++) {
12799             if (macrotab[i]) {
12800                 int len = strlen((char *)macrotab[i]);
12801 #ifdef OS2
12802                 ckmakmsg(buf,
12803                          1024,
12804                          "set key \\",
12805                          ckitoa(mskkeys ? cktomsk(i) : i),
12806                          " ",
12807                          NULL
12808                          );
12809 #else /* OS2 */
12810                 ckmakmsg(buf,
12811                          1024,
12812                          "set key \\",
12813                          ckitoa(i),
12814                          NULL,NULL
12815                          );
12816 #endif /* OS2 */
12817                 zsout(ZMFILE,buf);
12818
12819                 for (j = 0; j < len; j++) {
12820                     char ch = macrotab[i][j];
12821                     if (ch <= SP || ch >= DEL ||
12822                          ch == '-' || ch == ',' ||
12823                          ch == '{' || ch == '}' ||
12824                          ch == ';' || ch == '?' ||
12825                          ch == '.' || ch == '\'' ||
12826                          ch == '\\' || ch == '/' ||
12827                          ch == '#') {
12828                         ckmakmsg(buf,1024,"\\{",ckitoa((int)ch),"}",NULL);
12829                         zsout(ZMFILE,buf);
12830                     } else {
12831                         ckmakmsg(buf,1024,ckctoa((char)ch),NULL,NULL,NULL);
12832                         zsout(ZMFILE,buf);
12833                     }
12834                 }
12835 #ifdef OS2
12836                 ckmakmsg(buf,1024,"\t; ",keyname(i),NULL,NULL);
12837                 zsoutl(ZMFILE,buf);
12838 #else
12839                 zsoutl(ZMFILE,"");
12840 #endif /* OS2 */
12841             } else if ( keymap[i] != i ) {
12842 #ifndef NOKVERBS
12843                 if (IS_KVERB(keymap[i])) {
12844                     for (j = 0; j < nkverbs; j++)
12845                       if (kverbs[j].kwval == (keymap[i] & ~F_KVERB))
12846                         break;
12847                     if (j != nkverbs) {
12848 #ifdef OS2
12849 #ifdef COMMENT
12850                         sprintf(buf, "set key \\%d \\K%s\t; %s",
12851                                 mskkeys ? cktomsk(i) : i,
12852                                 kverbs[j].kwd, keyname(i)
12853                                 );
12854 #else
12855                         ckmakxmsg(buf,  /* 12 string args */
12856                                   1024,
12857                                   "set key \\",
12858                                   ckitoa(mskkeys ? cktomsk(i) : i),
12859                                   " \\K",
12860                                   kverbs[j].kwd,
12861                                   "\t; ",
12862                                   keyname(i),
12863                                   NULL, NULL, NULL, NULL, NULL, NULL);
12864 #endif /* COMMENT */
12865                         zsoutl(ZMFILE,buf);
12866 #else
12867 #ifdef COMMENT
12868                         sprintf(buf, "set key \\%d \\K%s", i, kverbs[j].kwd);
12869 #else
12870                         ckmakmsg(buf,1024,
12871                                  "set key \\",
12872                                  ckitoa(i),
12873                                  " \\K",
12874                                  kverbs[j].kwd
12875                                  );
12876 #endif /* COMMENT */
12877                         zsoutl(ZMFILE,buf);
12878 #endif
12879                     }
12880                 } else
12881 #endif /* NOKVERBS */
12882                   {
12883 #ifdef OS2
12884 #ifdef COMMENT
12885                       sprintf(buf, "set key \\%d \\{%d}\t; %s",
12886                               mskkeys ? cktomsk(i) : i,
12887                               keymap[i],
12888                               keyname(i)
12889                               );
12890 #else
12891                       ckmakxmsg(buf,    /* 8 string args */
12892                                 1024,
12893                                 "set key \\",
12894                                 ckitoa(mskkeys ? cktomsk(i) : i),
12895                                 " \\{",
12896                                 ckitoa(keymap[i]),
12897                                 "}\t; ",
12898                                 keyname(i),
12899                                 NULL,NULL,NULL,NULL,NULL,NULL);
12900 #endif /* COMMENT */
12901                       zsoutl(ZMFILE,buf);
12902 #else
12903 #ifdef COMMENT
12904                       sprintf(buf, "set key \\%d \\{%d}", i, keymap[i]);
12905 #else
12906                       ckmakxmsg(buf,1024,
12907                                "set key \\",
12908                                ckitoa(i),
12909                                " \\{",
12910                                ckitoa(keymap[i]),
12911                                "}",
12912                                NULL,NULL,NULL,NULL,NULL,NULL,NULL);
12913 #endif /* COMMENT */
12914                       zsoutl(ZMFILE,buf);
12915 #endif /* OS2 */
12916                   }
12917             }
12918         }
12919 #ifdef OS2
12920         /* OS/2 also has the SET TERMINAL KEY <termtype> defines */
12921         for (k = 0; k < nttkey; k++) {
12922             extern struct keynode * ttkeymap[];
12923             struct keynode * pnode = NULL;
12924
12925             if (ttkeytab[k].flgs)       /* Don't process CM_INV or CM_ABR */
12926               continue;
12927
12928             zsoutl(ZMFILE,"");
12929             ckmakmsg(buf,1024,"; SET TERMINAL KEY ",ttkeytab[k].kwd,NULL,NULL);
12930             zsoutl(ZMFILE,buf);
12931
12932             for (pnode = ttkeymap[ttkeytab[k].kwval];
12933                  pnode;
12934                  pnode = pnode->next
12935                  ) {
12936                 switch (pnode->def.type) {
12937                   case key:
12938 #ifdef COMMENT
12939                     sprintf(buf, "set terminal key %s \\%d \\{%d}\t; %s",
12940                             ttkeytab[k].kwd,
12941                             mskkeys ? cktomsk(pnode->key) : pnode->key,
12942                             pnode->def.key.scancode,
12943                             keyname(pnode->key)
12944                             );
12945 #else
12946                     ckmakxmsg(buf,
12947                               1024,
12948                               "set terminal key ",
12949                               ttkeytab[k].kwd,
12950                               " \\",
12951                               ckitoa(mskkeys ?
12952                                      cktomsk(pnode->key) :
12953                                      pnode->key),
12954                               " \\{",
12955                               ckitoa(pnode->def.key.scancode),
12956                               "}\t; ",
12957                               keyname(pnode->key),
12958                               NULL,NULL,NULL,NULL
12959                               );
12960 #endif /* COMMENT */
12961                     zsoutl(ZMFILE,buf);
12962                     break;
12963                   case kverb:
12964                     for (j = 0; j < nkverbs; j++)
12965                       if (kverbs[j].kwval == (pnode->def.kverb.id & ~F_KVERB))
12966                         break;
12967                     if (j != nkverbs) {
12968 #ifdef COMMENT
12969                         sprintf(buf, "set terminal key %s \\%d \\K%s\t; %s",
12970                                 ttkeytab[k].kwd,
12971                                 mskkeys ? cktomsk(pnode->key) : pnode->key,
12972                                 kverbs[j].kwd, keyname(pnode->key)
12973                                 );
12974 #else
12975                         ckmakxmsg(buf,
12976                                   1024,
12977                                   "set terminal key ",
12978                                   ttkeytab[k].kwd,
12979                                   " \\",
12980                                   ckitoa(mskkeys ?
12981                                          cktomsk(pnode->key) :
12982                                          pnode->key),
12983                                   " \\K",
12984                                   kverbs[j].kwd,
12985                                   "\t; ",
12986                                   keyname(pnode->key),
12987                                   NULL,NULL,NULL,NULL
12988                                   );
12989 #endif /* COMMENT */
12990                         zsoutl(ZMFILE,buf);
12991                     }
12992                     break;
12993                   case macro: {
12994                       int len = strlen((char *)pnode->def.macro.string);
12995 #ifdef COMMENT
12996                       sprintf(buf,"set terminal key %s \\%d ",
12997                               ttkeytab[k].kwd,
12998                               mskkeys ? cktomsk(pnode->key) : pnode->key);
12999 #else
13000                       ckmakxmsg(buf,
13001                                1024,
13002                                "set terminal key ",
13003                                ttkeytab[k].kwd,
13004                                " \\",
13005                                ckitoa(mskkeys ?
13006                                       cktomsk(pnode->key) :
13007                                       pnode->key),
13008                                " ",
13009                                NULL,NULL,NULL,NULL,NULL,NULL,NULL
13010                               );
13011 #endif /* COMMENT */
13012                       zsout(ZMFILE,buf);
13013
13014                       for (j = 0; j < len; j++) {
13015                           char ch = pnode->def.macro.string[j];
13016                           if (ch <= SP || ch >= DEL ||
13017                                ch == '-' || ch == ',' ||
13018                                ch == '{' || ch == '}' ||
13019                                ch == ';' || ch == '?' ||
13020                                ch == '.' || ch == '\'' ||
13021                                ch == '\\' || ch == '/' ||
13022                                ch == '#') {
13023                               ckmakmsg(buf,1024,
13024                                        "\\{",ckitoa((int)ch),"}",NULL);
13025                               zsout(ZMFILE,buf);
13026                           } else {
13027                               ckmakmsg(buf,1024,
13028                                        ckctoa((char)ch),NULL,NULL,NULL);
13029                               zsout(ZMFILE,buf);
13030                           }
13031                       }
13032                       ckmakmsg(buf,1024,"\t; ",keyname(pnode->key),NULL,NULL);
13033                       zsoutl(ZMFILE,buf);
13034                       break;
13035                   }
13036                   case literal: {
13037                       int len = strlen((char *)pnode->def.literal.string);
13038 #ifdef COMMENT
13039                       sprintf(buf,"set terminal key %s /literal \\%d ",
13040                               ttkeytab[k].kwd,
13041                               mskkeys ? cktomsk(pnode->key) : pnode->key);
13042 #else
13043                       ckmakxmsg(buf,
13044                                1024,
13045                                "set terminal key ",
13046                                ttkeytab[k].kwd,
13047                                " /literal \\",
13048                                ckitoa(mskkeys ?
13049                                       cktomsk(pnode->key) :
13050                                       pnode->key),
13051                                " ",
13052                                NULL,NULL,NULL,NULL,NULL,NULL,NULL);
13053 #endif /* COMMENT */
13054                       zsout(ZMFILE,buf);
13055
13056                       for (j = 0; j < len; j++) {
13057                           char ch = pnode->def.literal.string[j];
13058                           if (ch <= SP || ch >= DEL ||
13059                                ch == '-' || ch == ',' ||
13060                                ch == '{' || ch == '}' ||
13061                                ch == ';' || ch == '?' ||
13062                                ch == '.' || ch == '\'' ||
13063                                ch == '\\' || ch == '/' ||
13064                                ch == '#') {
13065                               ckmakmsg(buf,1024,
13066                                        "\\{",ckitoa((int)ch),"}",NULL);
13067                               zsout(ZMFILE,buf);
13068                           } else {
13069                               ckmakmsg(buf,1024,
13070                                        ckctoa((char)ch),NULL,NULL,NULL);
13071                               zsout(ZMFILE,buf);
13072                           }
13073                       }
13074                       ckmakmsg(buf,1024,"\t; ",keyname(pnode->key),NULL,NULL);
13075                       zsoutl(ZMFILE,buf);
13076                       break;
13077                   }
13078                   case esc:
13079 #ifdef COMMENT
13080                     sprintf(buf,
13081                        "set terminal key %s /literal \\%d \\{%d}\\{%d}\t; %s",
13082                             ttkeytab[k].kwd,
13083                             mskkeys ? cktomsk(pnode->key) : pnode->key,
13084                             ISDG200(ttkeytab[k].kwval) ? 30 : 27,
13085                             pnode->def.esc.key & ~F_ESC,
13086                             keyname(pnode->key)
13087                             );
13088 #else
13089                     ckmakxmsg(buf,
13090                               1024,
13091                               "set terminal key ",
13092                               ttkeytab[k].kwd,
13093                               " /literal \\",
13094                               ckitoa(mskkeys ?
13095                                      cktomsk(pnode->key) :
13096                                      pnode->key),
13097                               " \\{",
13098                               ckitoa(ISDG200(ttkeytab[k].kwval) ? 30 : 27),
13099                               "}\\{",
13100                               ckitoa(pnode->def.esc.key & ~F_ESC),
13101                               "}\t; ",
13102                               keyname(pnode->key),
13103                               NULL,NULL
13104                               );
13105 #endif /* COMMENT */
13106                     zsoutl(ZMFILE,buf);
13107                     break;
13108                   case csi:
13109 #ifdef COMMENT
13110                     sprintf(buf,
13111                        "set terminal key %s /literal \\%d \\{27}[\\{%d}\t; %s",
13112                             ttkeytab[k].kwd,
13113                             mskkeys ? cktomsk(pnode->key) : pnode->key,
13114                             pnode->def.csi.key & ~F_CSI,
13115                             keyname(pnode->key)
13116                             );
13117 #else
13118                     ckmakxmsg(buf,
13119                               1024,
13120                               "set terminal key ",
13121                               ttkeytab[k].kwd,
13122                               " /literal \\",
13123                               ckitoa(mskkeys ?
13124                                      cktomsk(pnode->key) :
13125                                      pnode->key),
13126                               " \\{27}[\\{",
13127                               ckitoa(pnode->def.csi.key & ~F_CSI),
13128                               "}\t; ",
13129                               keyname(pnode->key),
13130                               NULL,NULL,NULL,NULL
13131                               );
13132 #endif /* COMMENT */
13133                     zsoutl(ZMFILE,buf);
13134                     break;
13135                   default:
13136                     continue;
13137                 }
13138             }
13139         }
13140 #endif /* OS2 */
13141
13142         zsoutl(ZMFILE,"");
13143         zsoutl(ZMFILE,"; End");
13144         zclose(ZMFILE);
13145         return(success = 1);
13146     } else {
13147         return(success = 0);
13148     }
13149 }
13150 #endif /* NOSETKEY */
13151
13152 #define SV_SCRL 0
13153 #define SV_HIST 1
13154
13155 #ifdef OS2
13156 #ifndef NOLOCAL
13157 static struct keytab trmtrmopt[] = {
13158     { "scrollback", SV_SCRL, 0 }
13159 };
13160 #endif /* NOLOCAL */
13161 #endif /* OS2 */
13162
13163 static struct keytab cmdtrmopt[] = {
13164 #ifdef CK_RECALL
13165     { "history",    SV_HIST, 0 },
13166 #endif /* CK_RECALL */
13167 #ifdef OS2
13168 #ifndef NOLOCAL
13169     { "scrollback", SV_SCRL, 0 },
13170 #endif /* NOLOCAL */
13171 #endif /* OS2 */
13172     { "", 0, 0 }
13173 };
13174 static int ncmdtrmopt = (sizeof (cmdtrmopt) / sizeof (struct keytab)) - 1;
13175
13176 #ifdef OS2
13177 #ifndef NOLOCAL
13178 _PROTOTYP(int savscrbk, (int, char *, int));
13179 #endif /* NOLOCAL */
13180 #endif /* OS2 */
13181
13182 #ifdef CK_RECALL
13183 _PROTOTYP(int savhistory, (char *, int));
13184 #endif /* CK_RECALL */
13185
13186 int
13187 dosave(xx) int xx; {
13188     int x, y = 0, disp;
13189     char * s = NULL;
13190     extern struct keytab disptb[];
13191 #ifdef ZFNQFP
13192     struct zfnfp * fnp;
13193 #endif /* ZFNQFP */
13194
13195 #ifndef NOSETKEY
13196     if (xx == XSKEY) {                  /* SAVE KEYMAP.. */
13197         z = cmofi("Name of Kermit command file","keymap.ksc",&s,xxstring);
13198     } else {
13199 #endif /* NOSETKEY */
13200         switch (xx) {
13201           case XSCMD:                   /* SAVE COMMAND.. */
13202             if ((y = cmkey(cmdtrmopt, ncmdtrmopt, "What to save",
13203 #ifdef OS2
13204                            "scrollback",
13205 #else
13206                            "history",
13207 #endif /* OS2 */
13208                            xxstring)) < 0)
13209               return(y);
13210             break;
13211 #ifdef OS2
13212 #ifndef NOLOCAL
13213           case XSTERM:                  /* SAVE TERMINAL.. */
13214             if ((y = cmkey(trmtrmopt,1,
13215                            "What to save","scrollback",xxstring)) < 0)
13216               return(y);
13217             break;
13218 #endif /* NOLOCAL */
13219 #endif /* OS2 */
13220         }
13221         z = cmofi("Filename",
13222                   ((y == SV_SCRL) ? "scrollbk.txt" : "history.txt"),
13223                   &s,
13224                   xxstring
13225                   );
13226 #ifndef NOSETKEY
13227     }
13228 #endif /* NOSETKEY */
13229     if (z < 0)                          /* Check output-file parse results */
13230       return(z);
13231     if (z == 2) {
13232         printf("?Sorry, %s is a directory name\n",s);
13233         return(-9);
13234     }
13235 #ifdef ZFNQFP
13236     if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {/* Convert to full pathname */
13237         if (fnp->fpath)
13238           if ((int) strlen(fnp->fpath) > 0)
13239             s = fnp->fpath;
13240     }
13241 #endif /* ZFNQFP */
13242
13243     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of pathname */
13244     s = line;
13245 #ifdef MAC
13246     z = 0;
13247 #else
13248     /* Get NEW/APPEND disposition */
13249     if ((z = cmkey(disptb,2,"Disposition","new",xxstring)) < 0)
13250       return(z);
13251 #endif /* MAC */
13252     disp = z;
13253     if ((x = cmcfm()) < 0)              /* Get confirmation */
13254       return(x);
13255
13256     switch (xx) {                       /* Do action.. */
13257 #ifndef NOSETKEY
13258       case XSKEY:                       /* SAVE KEYMAP */
13259         return (savkeys(s,disp));
13260 #endif /* NOSETKEY */
13261
13262       case XSCMD:                       /* SAVE COMMAND.. */
13263 #ifdef OS2
13264 #ifndef NOLOCAL
13265         if (y == SV_SCRL)               /* .. SCROLLBACK */
13266           return(success = savscrbk(VCMD,s,disp));
13267 #endif /* NOLOCAL */
13268 #endif /* OS2 */
13269 #ifndef NORECALL
13270         if (y == SV_HIST)               /* .. HISTORY */
13271           return(success = savhistory(s,disp));
13272         break;
13273 #endif /* NORECALL */
13274
13275 #ifdef OS2
13276 #ifndef NOLOCAL
13277       case XSTERM:                      /* SAVE TERMINAL SCROLLBACK */
13278         return(success = savscrbk(VTERM,s,disp));
13279 #endif /* NOLOCAL */
13280 #endif /* OS2 */
13281     }
13282     success = 0;
13283     return(-2);
13284 }
13285
13286 /*
13287   R E A D T E X T
13288
13289   Read text with a custom prompt into given buffer using command parser but
13290   with no echoing or entry into recall buffer.
13291 */
13292 int
13293 readtext(prmpt, buffer, bufsiz) char * prmpt; char * buffer; int bufsiz; {
13294 #ifdef CK_RECALL
13295     extern int on_recall;               /* Around Password prompting */
13296 #endif /* CK_RECALL */
13297     int rc;
13298 #ifndef NOLOCAL
13299 #ifdef OS2
13300     extern int vmode;
13301     extern int startflags;
13302     int vmode_sav = vmode;
13303
13304     if (!prmpt) prmpt = "";
13305
13306     if (win95_popup && !(startflags & 96)
13307 #ifdef IKSD
13308          && !inserver
13309 #endif /* IKSD */
13310          )
13311       return(popup_readtext(vmode,NULL,prmpt,buffer,bufsiz,0));
13312
13313     if (vmode == VTERM) {
13314         vmode = VCMD;
13315         VscrnIsDirty(VTERM);
13316         VscrnIsDirty(VCMD);
13317     }
13318 #endif /* OS2 */
13319 #endif /* NOLOCAL */
13320
13321 #ifdef CK_RECALL
13322     on_recall = 0;
13323 #endif /* CK_RECALL */
13324     cmsavp(psave,PROMPTL);              /* Save old prompt */
13325     cmsetp(prmpt);                      /* Make new prompt */
13326     concb((char)escape);                /* Put console in cbreak mode */
13327     cmini(1);                           /* and echo mode */
13328     if (pflag) prompt(xxstring);        /* Issue prompt if at top level */
13329     cmres();                            /* Reset the parser */
13330     for (rc = -1; rc < 0; ) {           /* Prompt till they answer */
13331         rc = cmtxt("","",&s,NULL);      /* Get a literal line of text */
13332         cmres();                        /* Reset the parser again */
13333     }
13334     ckstrncpy(buffer,s,bufsiz);
13335     cmsetp(psave);                      /* Restore original prompt */
13336
13337 #ifndef NOLOCAL
13338 #ifdef OS2
13339     if (vmode != vmode_sav) {
13340         vmode = VTERM;
13341         VscrnIsDirty(VCMD);
13342         VscrnIsDirty(VTERM);
13343     }
13344 #endif /* OS2 */
13345 #endif /* NOLOCAL */
13346     return(0);
13347 }
13348 #endif /* NOICP */
13349
13350 /* A general function to allow a Password or other information  */
13351 /* to be read from the command prompt without it going into     */
13352 /* the recall buffer or being echo'd.                           */
13353
13354 int
13355 readpass(prmpt, buffer, bufsiz) char * prmpt; char * buffer; int bufsiz; {
13356     int x;
13357 #ifdef NOICP
13358     if (!prmpt) prmpt = "";
13359     printf("%s", prmpt);
13360 #ifdef COMMENT
13361     /* Some linkers won't allow this because it's unsafe */
13362     gets(buffer);
13363 #else  /* COMMENT */
13364     {
13365         int c, i; char * p;
13366         p = buffer;
13367         for (i = 0; i < bufsiz-1; i++) {
13368             if ((c = getchar()) == EOF)
13369               break;
13370             if (c < SP)
13371               break;
13372             buffer[i] = c;
13373         }
13374         buffer[i] = NUL;
13375     }
13376 #endif /* COMMENT */
13377     return(1);
13378 #else  /* NOICP */
13379 #ifdef CK_RECALL
13380     extern int on_recall;               /* around Password prompting */
13381 #endif /* CK_RECALL */
13382     int rc;
13383 #ifndef NOLOCAL
13384 #ifdef OS2
13385     extern int vmode;
13386     extern int startflags;
13387     int vmode_sav = vmode;
13388 #endif /* OS2 */
13389 #endif /* NOLOCAL */
13390 #ifdef CKSYSLOG
13391     int savlog;
13392 #endif /* CKSYSLOG */
13393     if (!prmpt) prmpt = "";
13394 #ifndef NOLOCAL
13395     debok = 0;                          /* Don't log */
13396 #ifdef OS2
13397     if (win95_popup && !(startflags & 96)
13398 #ifdef IKSD
13399          && !inserver
13400 #endif /* IKSD */
13401          ) {
13402         x = popup_readpass(vmode,NULL,prmpt,buffer,bufsiz,0);
13403         debok = 1;
13404         return(x);
13405     }
13406 #endif /* OS2 */
13407 #endif /* NOLOCAL */
13408
13409 #ifdef CKSYSLOG
13410     savlog = ckxsyslog;                 /* Save and turn off syslogging */
13411     ckxsyslog = 0;
13412 #endif /* CKSYSLOG */
13413 #ifndef NOLOCAL
13414 #ifdef OS2
13415     if (vmode == VTERM) {
13416         vmode = VCMD;
13417         VscrnIsDirty(VTERM);
13418         VscrnIsDirty(VCMD);
13419     }
13420 #endif /* OS2 */
13421 #endif /* NOLOCAL */
13422 #ifdef CK_RECALL
13423     on_recall = 0;
13424 #endif /* CK_RECALL */
13425     cmsavp(psave,PROMPTL);              /* Save old prompt */
13426     cmsetp(prmpt);                      /* Make new prompt */
13427     concb((char)escape);                /* Put console in cbreak mode */
13428     cmini(0);                           /* and no-echo mode */
13429     if (pflag) prompt(xxstring);        /* Issue prompt if at top level */
13430     cmres();                            /* Reset the parser */
13431     for (rc = -1; rc < 0; ) {           /* Prompt till they answer */
13432         rc = cmtxt("","",&s,NULL);      /* Get a literal line of text */
13433         cmres();                        /* Reset the parser again */
13434     }
13435     ckstrncpy(buffer,s,bufsiz);
13436     printf("\r\n");                     /* Echo a CRLF */
13437     cmsetp(psave);                      /* Restore original prompt */
13438     cmini(1);                           /* Restore echo mode */
13439 #ifndef NOLOCAL
13440 #ifdef OS2
13441     if (vmode != vmode_sav) {
13442         vmode = VTERM;
13443         VscrnIsDirty(VCMD);
13444         VscrnIsDirty(VTERM);
13445     }
13446 #endif /* OS2 */
13447 #endif /* NOLOCAL */
13448 #ifdef CKSYSLOG
13449     ckxsyslog = savlog;                 /* Restore syslogging */
13450 #endif /* CKSYSLOG */
13451     debok = 1;
13452     return(0);
13453 #endif /* NOICP */
13454 }
13455
13456 #ifndef NOICP
13457 struct keytab authtab[] = {             /* Available authentication types */
13458 #ifdef CK_KERBEROS
13459     { "k4",        AUTH_KRB4, CM_INV },
13460     { "k5",        AUTH_KRB5, CM_INV },
13461     { "kerberos4", AUTH_KRB4, 0      },
13462     { "kerberos5", AUTH_KRB5, 0      },
13463     { "krb4",      AUTH_KRB4, CM_INV },
13464     { "krb5",      AUTH_KRB5, CM_INV },
13465 #endif /* CK_KERBEROS */
13466 #ifdef NT
13467     { "ntlm",      AUTH_NTLM, 0 },
13468 #endif /* NT */
13469 #ifdef CK_SRP
13470     { "srp",       AUTH_SRP,  0 },
13471 #endif /* CK_SRP */
13472 #ifdef CK_SSL
13473     { "ssl",       AUTH_SSL,  0 },
13474 #endif /* CK_SSL */
13475     { "",          0,         0 }
13476 };
13477 int authtabn = sizeof(authtab)/sizeof(struct keytab)-1;
13478
13479 #ifdef CK_KERBEROS
13480 struct keytab kerbtab[] = {             /* Kerberos authentication types */
13481     { "k4",        AUTH_KRB4, CM_INV },
13482     { "k5",        AUTH_KRB5, CM_INV },
13483     { "kerberos4", AUTH_KRB4, 0      },
13484     { "kerberos5", AUTH_KRB5, 0      },
13485     { "krb4",      AUTH_KRB4, CM_INV },
13486     { "krb5",      AUTH_KRB5, CM_INV }
13487 };
13488 int kerbtabn = sizeof(kerbtab)/sizeof(struct keytab);
13489
13490 static struct keytab krb_s_tbl[] = {    /* AUTHENTICATE command switches: */
13491     { "/cache",   KRB_S_CA, CM_ARG }
13492 };
13493 static int krb_s_n = sizeof(krb_s_tbl)/sizeof(struct keytab);
13494
13495 static struct keytab krb_v_tbl[] = {    /* KERBEROS version values: */
13496     { "4",    4, 0 },
13497     { "5",    5, 0 },                   /* (add others as needed...) */
13498     { "auto", 0, 0 }                    /* Note: 0 = auto */
13499 };
13500 static int krb_v_n = sizeof(krb_v_tbl)/sizeof(struct keytab);
13501
13502 static struct keytab krb_a_tbl[] = {    /* KERBEROS actions: */
13503     { "destroy",           KRB_A_DE, 0 },
13504     { "initialize",        KRB_A_IN, 0 },
13505     { "list-credentials",  KRB_A_LC, 0 }
13506 };
13507 static int krb_a_n = sizeof(krb_a_tbl)/sizeof(struct keytab);
13508
13509 static struct keytab krb4_i_tbl[] = {   /* KERBEROS 4 INITIALIZE switches: */
13510     { "/brief",            KRB_I_BR, 0 },      /* /BRIEF       */
13511     { "/instance",         KRB_I_IN, CM_ARG }, /* /INSTANCE:   */
13512     { "/lifetime",         KRB_I_LF, CM_ARG }, /* /LIFETIME:   */
13513     { "/not-preauth",      KRB_I_NPA, 0 },     /* /NOT-PREAUTH */
13514     { "/password",         KRB_I_PW, CM_ARG }, /* /PASSWORD:   */
13515 #ifdef OS2
13516     { "/popup",            KRB_I_POP, 0 },     /* /POPUP       */
13517 #endif /* OS2 */
13518     { "/preauth",          KRB_I_PA, 0 },      /* /PREAUTH     */
13519     { "/realm",            KRB_I_RL, CM_ARG }, /* /REALM:      */
13520     { "/verbose",          KRB_I_VB, 0 },      /* /VERBOSE     */
13521     { "", 0, 0 }
13522 };
13523 static int krb4_i_n = sizeof(krb4_i_tbl)/sizeof(struct keytab) - 1;
13524
13525 static struct keytab krb5_i_tbl[] = {   /* KERBEROS 5 INITIALIZE switches: */
13526     { "/addresses",        KRB_I_ADR, CM_ARG },
13527     { "/forwardable",      KRB_I_FW,  0 },         /* /FORWARDABLE */
13528     { "/instance",         KRB_I_IN, CM_ARG }, /* /INSTANCE:   */
13529     { "/k4",               KRB_I_K4,  CM_INV }, /* /KERBEROS4   */
13530     { "/kerberos4",        KRB_I_K4,  0 },      /* /KERBEROS4   */
13531     { "/krb4",             KRB_I_K4,  CM_INV }, /* /KERBEROS4   */
13532     { "/lifetime",         KRB_I_LF,  CM_ARG }, /* /LIFETIME:   */
13533     { "/no-addresses",     KRB_I_NAD, 0 },      /* /NO-ADDRESSES */
13534     { "/no-k4",            KRB_I_NK4, CM_INV },/* /NO-KERBEROS4 */
13535     { "/no-kerberos4",     KRB_I_NK4, 0 },     /* /NO-KERBEROS4 */
13536     { "/no-krb4",          KRB_I_NK4, CM_INV },/* /NO-KERBEROS4 */
13537     { "/not-forwardable",  KRB_I_NFW, 0 },         /* /NOT-FORWARDABLE */
13538     { "/not-proxiable",    KRB_I_NPR, 0 },     /* /NOT-PROXIABLE   */
13539     { "/password",         KRB_I_PW,  CM_ARG }, /* /PASSWORD:   */
13540 #ifdef OS2
13541     { "/popup",            KRB_I_POP, 0 },     /* /POPUP       */
13542 #endif /* OS2 */
13543     { "/postdate",         KRB_I_PD, CM_ARG }, /* /POSTDATE:   */
13544     { "/pr",               KRB_I_PR, CM_INV|CM_ABR }, /* to allow for */
13545     { "/pro",              KRB_I_PR, CM_INV|CM_ABR }, /* different spellings */
13546     { "/prox",             KRB_I_PR, CM_INV|CM_ABR },
13547     { "/proxiable",        KRB_I_PR, 0 },      /* /PROXIABLE   */
13548     { "/proxyable",        KRB_I_PR, CM_INV }, /* /PROXYABLE   */
13549     { "/realm",            KRB_I_RL, CM_ARG }, /* /REALM:      */
13550     { "/renew",            KRB_I_RN, 0 },          /* /RENEW       */
13551     { "/renewable",        KRB_I_RB, CM_ARG }, /* /RENEWABLE:  */
13552     { "/service",          KRB_I_SR, CM_ARG }, /* /SERVICE:    */
13553     { "/validate",         KRB_I_VA, 0 },          /* /VALIDATE    */
13554     { "", 0, 0 }
13555 };
13556 static int krb5_i_n = sizeof(krb5_i_tbl)/sizeof(struct keytab) - 1;
13557
13558 static struct keytab klctab[] = {       /* List Credentials switches*/
13559     { "/addresses",  XYKLCAD, 0 },
13560     { "/encryption", XYKLCEN, 0 },
13561     { "/flags",      XYKLCFL, 0 }
13562 };
13563 static int nklctab = sizeof(klctab)/sizeof(struct keytab);
13564
13565 extern int krb_action;
13566 extern struct krb_op_data krb_op;
13567
13568 extern struct krb5_list_cred_data krb5_lc;
13569 extern struct krb5_init_data krb5_init;
13570 extern char * krb5_d_principal;         /* Default principal */
13571 extern char * krb5_d_instance;
13572 extern char * krb5_d_realm;             /* Default realm */
13573 extern char * krb5_d_cc;                /* Default credentials cache */
13574 extern char * krb5_d_srv;               /* Default service name */
13575 extern int    krb5_d_lifetime;          /* Default lifetime */
13576 extern int    krb5_d_forwardable;
13577 extern int    krb5_d_proxiable;
13578 extern int    krb5_d_renewable;
13579 extern int    krb5_autoget;
13580 extern int    krb5_autodel;
13581 extern int    krb5_d_getk4;
13582 extern int    krb5_d_no_addresses;
13583 extern int    krb5_checkaddrs;
13584 extern char * krb5_d_addrs[];
13585 extern char * k5_keytab;                /* Keytab file */
13586
13587 extern struct krb4_init_data krb4_init;
13588 extern char * krb4_d_principal;         /* Default principal */
13589 extern char * krb4_d_realm;             /* Default realm */
13590 extern char * krb4_d_srv;               /* Default service name */
13591 extern int    krb4_d_lifetime;          /* Default lifetime */
13592 extern int    krb4_d_preauth;
13593 extern char * krb4_d_instance;
13594 extern int    krb4_autoget;
13595 extern int    krb4_autodel;
13596 extern int    krb4_checkaddrs;
13597 extern char * k4_keytab;                /* Keytab file */
13598 #endif /* CK_KERBEROS */
13599
13600 #ifndef NOSHOW
13601 int
13602 sho_iks() {
13603 #ifdef IKSDCONF
13604 #ifdef CK_LOGIN
13605     extern int ckxsyslog, ckxwtmp, ckxanon;
13606 #ifdef UNIX
13607     extern int ckxpriv;
13608 #endif /* UNIX */
13609 #ifdef CK_PERMS
13610     extern int ckxperms;
13611 #endif /* CK_PERMS */
13612     extern char * anonfile, * userfile, * anonroot;
13613 #ifdef OS2
13614     extern char * anonacct;
13615 #endif /* OS2 */
13616 #ifdef NT
13617     extern char * iks_domain;
13618 #endif /* NT */
13619 #endif /* CK_LOGIN */
13620 #ifdef CKWTMP
13621     extern char * wtmpfile;
13622 #endif /* CKWTMP */
13623 #ifdef IKSDB
13624     extern char * dbfile;
13625     extern int dbenabled;
13626 #endif /* IKSDB */
13627 #ifdef CK_LOGIN
13628     extern int logintimo;
13629 #endif /* CK_LOGIN */
13630     extern int srvcdmsg, success, iksdcf, noinit, arg_x;
13631     extern char * cdmsgfile[], * cdmsgstr, *kermrc;
13632     char * bannerfile = NULL;
13633     char * helpfile = NULL;
13634     extern int xferlog;
13635     extern char * xferfile;
13636     int i;
13637
13638     if (isguest) {
13639         printf("?Command disabled\r\n");
13640         return(success = 0);
13641     }
13642
13643     printf("IKS Settings\r\n");
13644 #ifdef CK_LOGIN
13645 #ifdef OS2
13646     printf("  Anonymous Account:   %s\r\n",anonacct?anonacct:"<none>");
13647 #endif /* OS2 */
13648     printf("  Anonymous Initfile:  %s\r\n",anonfile?anonfile:"<none>");
13649     printf("  Anonymous Login:     %d\r\n",ckxanon);
13650     printf("  Anonymous Root:      %s\r\n",anonroot?anonroot:"<none>");
13651 #endif /* CK_LOGIN */
13652     printf("  Bannerfile:          %s\r\n",bannerfile?bannerfile:"<none>");
13653     printf("  CDfile:              %s\r\n",cdmsgfile[0]?cdmsgfile[0]:"<none>");
13654     for ( i=1;i<16 && cdmsgfile[i];i++ )
13655         printf("  CDfile:              %s\r\n",cdmsgfile[i]);
13656     printf("  CDMessage:           %d\r\n",srvcdmsg);
13657 #ifdef IKSDB
13658     printf("  DBfile:              %s\r\n",dbfile?dbfile:"<none>");
13659     printf("  DBenabled:           %d\r\n",dbenabled);
13660 #endif /* IKSDB */
13661 #ifdef CK_LOGIN
13662 #ifdef NT
13663     printf("  Default-domain:      %s\r\n",iks_domain?iks_domain:".");
13664 #endif /* NT */
13665 #endif /* CK_LOGIN */
13666     printf("  Helpfile:            %s\r\n",helpfile?helpfile:"<none>");
13667     printf("  Initfile:            %s\r\n",kermrc?kermrc:"<none>");
13668     printf("  No-Initfile:         %d\r\n",noinit);
13669 #ifdef CK_LOGIN
13670 #ifdef CK_PERM
13671     printf("  Permission code:     %0d\r\n",ckxperms);
13672 #endif /* CK_PERM */
13673 #ifdef UNIX
13674     printf("  Privileged Login:    %d\r\n",ckxpriv);
13675 #endif /* UNIX */
13676 #endif /* CK_LOGIN */
13677     printf("  Server-only:         %d\r\n",arg_x);
13678     printf("  Syslog:              %d\r\n",ckxsyslog);
13679     printf("  Timeout (seconds):   %d\r\n",logintimo);
13680     printf("  Userfile:            %s\r\n",userfile?userfile:"<none>");
13681 #ifdef CK_LOGIN
13682 #ifdef CKWTMP
13683     printf("  Wtmplog:             %d\r\n",ckxwtmp);
13684     printf("  Wtmpfile:            %s\r\n",wtmpfile?wtmpfile:"<none>");
13685 #endif /* CKWTMP */
13686 #endif /* CK_LOGIN */
13687     printf("  Xferfile:            %s\r\n",xferfile?xferfile:"<none>");
13688     printf("  Xferlog:             %d\r\n",xferlog);
13689 #else /* IKSDCONF */
13690     printf("?Nothing to show.\r\n");
13691 #endif /* IKSDCONF */
13692     return(success = 1);
13693 }
13694
13695 #ifdef CK_AUTHENTICATION
13696 int
13697 sho_auth(cx) int cx; {
13698     extern int auth_type_user[], cmd_rows;
13699     int i;
13700     char * p;
13701     int kv = 0, all = 0, n = 0;
13702
13703 #ifdef IKSD
13704     if (inserver && isguest) {
13705         printf("?Sorry, command disabled.\r\n");
13706         return(success = 0);
13707     }
13708 #endif /* IKSD */
13709     if (cx) {
13710         kv = cx;
13711     } else if (auth_type_user[0] != AUTHTYPE_AUTO) {
13712         kv = auth_type_user[0];
13713     } else {
13714         all = 1;
13715         kv = AUTHTYPE_KERBEROS_V4;
13716     }
13717     while (kv) {
13718         switch (kv) {
13719           case AUTHTYPE_KERBEROS_V4:
13720             kv = all ? AUTHTYPE_KERBEROS_V5 : 0;
13721             if (ck_krb4_is_installed()) {
13722                 printf(" Authentication:      Kerberos 4\n");
13723                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13724             } else {
13725                 printf(" Authentication:      Kerberos 4 (not installed)\n");
13726                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13727                 continue;
13728             }
13729 #ifdef CK_KERBEROS
13730             printf(" Keytab file:         %s\n",
13731                       k4_keytab ? k4_keytab : "(none)");
13732             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13733             if (krb_action < 0) {
13734                 p = "(none)";
13735             } else {
13736                 for (p = "", i = 0; i < krb_a_n; i++) {
13737                     if (krb_action == krb_a_tbl[i].kwval) {
13738                         p = krb_a_tbl[i].kwd;
13739                         break;
13740                     }
13741                 }
13742             }
13743             printf(" Action:              %s\n", p);
13744             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13745             printf(" Default lifetime     %d\n",krb4_d_lifetime);
13746             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13747             printf(" Lifetime:            %d (minutes)\n",krb4_init.lifetime);
13748             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13749             printf(" Default preauth:     %d\n",krb4_d_preauth);
13750             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13751             printf(" Preauth:             %d\n",krb4_init.preauth);
13752             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13753             printf(" Default principal:   \"%s\"\n",
13754                     krb4_d_principal ? krb4_d_principal : "");
13755             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13756             printf(" Principal:           \"%s\"\n",
13757                     krb4_init.principal ? krb4_init.principal : "");
13758             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13759             printf(" Default realm:       \"%s\"\n",
13760                     krb4_d_realm ? krb4_d_realm : "");
13761             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13762             printf(" Realm:               \"%s\"\n",
13763                     krb4_init.realm ? krb4_init.realm : "");
13764             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13765             printf(" Default instance:    \"%s\"\n",
13766                     krb4_d_instance ? krb4_d_instance : "");
13767             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13768             printf(" Instance:            \"%s\"\n",
13769                     krb4_init.instance ? krb4_init.instance : "");
13770             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13771             printf(" Auto-Get TGTs:       %d\n",krb4_autoget);
13772             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13773             printf(" Auto-Destroy TGTs:   %s\n",
13774                     krb4_autodel==KRB_DEL_NO?"never":
13775                     krb4_autodel==KRB_DEL_CL?"on-close":"on-exit");
13776             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13777             printf(" Check IP Addresses:  %d\n",krb4_checkaddrs);
13778             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13779 #ifdef COMMENT
13780             printf(" Password:    \"%s\"\n",
13781                     krb4_init.password  ? krb4_init.password  : "");
13782             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13783 #endif /* COMMENT */
13784 #endif /* CK_KERBEROS */
13785             printf("\n");
13786             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13787             break;
13788         case AUTHTYPE_KERBEROS_V5:
13789             kv = all ? AUTHTYPE_SSL : 0;
13790             if (ck_krb5_is_installed()) {
13791                 if (ck_gssapi_is_installed())
13792                     printf(" Authentication:      Kerberos 5 plus GSSAPI\n");
13793                 else
13794                     printf(" Authentication:      Kerberos 5\n");
13795                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13796             } else {
13797                 printf(" Authentication:      Kerberos 5 (not installed)\n");
13798                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13799                 continue;
13800             }
13801
13802 #ifdef CK_KERBEROS
13803             printf(" Cache file:          %s\n",
13804                     krb_op.cache ? krb_op.cache : "(none)");
13805             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13806             printf(" Default cache:       %s\n",
13807                     krb5_d_cc ? krb5_d_cc : "(none)");
13808             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13809             printf(" Keytab file:         %s\n",
13810                       k5_keytab ? k5_keytab : "(none)");
13811             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13812             if (krb_action < 0) {
13813                 p = "(none)";
13814             } else  {
13815                 for (p = "", i = 0; i < krb_a_n; i++) {
13816                     if (krb_action == krb_a_tbl[i].kwval) {
13817                         p = krb_a_tbl[i].kwd;
13818                         break;
13819                     }
13820                 }
13821             }
13822             printf(" Action:              %s\n", p);
13823             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13824
13825             printf(" Default forwardable  %d\n",krb5_d_forwardable);
13826             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13827             printf(" Forwardable:         %d\n",krb5_init.forwardable);
13828             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13829             printf(" Default lifetime     %d\n",krb5_d_lifetime);
13830             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13831             printf(" Lifetime:            %d (minutes)\n",krb5_init.lifetime);
13832             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13833             printf(" Postdate:            \"%s\"\n",
13834                     krb5_init.postdate ? krb5_init.postdate: "");
13835             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13836             printf(" Default proxiable:   %d\n",krb5_d_proxiable);
13837             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13838             printf(" Proxiable:           %d\n",krb5_init.proxiable);
13839             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13840             printf(" Renew:               %d\n",krb5_init.renew);
13841             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13842             printf(" Default renewable:   %d (minutes)\n",krb5_d_renewable);
13843             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13844             printf(" Renewable:           %d (minutes)\n",krb5_init.renewable);
13845             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13846             printf(" Service:             \"%s\"\n",
13847                     krb5_init.service ? krb5_init.service : "");
13848             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13849             printf(" Validate:            %d\n",krb5_init.validate);
13850             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13851             printf(" Default principal:   \"%s\"\n",
13852                     krb5_d_principal ? krb5_d_principal : "");
13853             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13854             printf(" Principal:           \"%s\"\n",
13855                     krb5_init.principal ? krb5_init.principal : "");
13856             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13857             printf(" Default instance:    \"%s\"\n",
13858                     krb5_d_instance ? krb5_d_instance : "");
13859             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13860             printf(" Default realm:       \"%s\"\n",
13861                     krb5_d_realm ? krb5_d_realm : "");
13862             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13863             printf(" Realm:               \"%s\"\n",
13864                     krb5_init.realm ? krb5_init.realm : "");
13865             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13866             printf(" Auto-Get TGTs:       %d\n",krb5_autoget);
13867             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13868             printf(" Auto-Destroy TGTs:   %s\n",
13869                     krb5_autodel==KRB_DEL_NO?"never":
13870                     krb5_autodel==KRB_DEL_CL?"on-close":"on-exit");
13871             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13872             printf(" Default get K4 TGTs: %d\n",krb5_d_getk4);
13873             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13874             printf(" Get K4 TGTs: %d\n",krb5_init.getk4);
13875             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13876             printf(" Check IP Addresses:  %d\n",krb5_checkaddrs);
13877             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13878             printf(" No IP Addresses:  %d\n",krb5_d_no_addresses);
13879             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13880             printf(" IP-Addresses:        ");
13881             if (krb5_init.addrs && krb5_init.addrs[0]) {
13882                 for (i = 0; krb5_init.addrs[i]; i++) {
13883                     if (i)
13884                       printf(",");
13885                     printf("%s",krb5_init.addrs[i]);
13886                 }
13887             } else if (krb5_d_addrs[0]) {
13888                 for (i = 0;i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];i++) {
13889                     if (i)
13890                       printf(",");
13891                     printf("%s",krb5_d_addrs[i]);
13892                 }
13893             } else {
13894                 printf("(use default)");
13895             }
13896             printf("\n");
13897             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13898 #ifdef COMMENT
13899             printf(" Password:            \"%s\"\n",
13900                     krb5_init.password  ? krb5_init.password  : "");
13901             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13902 #endif /* COMMENT */
13903 #endif /* CK_KERBEROS */
13904             printf("\n");
13905             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13906             break;
13907           case AUTHTYPE_SSL:
13908             kv = all ? AUTHTYPE_SRP : 0;
13909             if (ck_ssleay_is_installed()) {
13910                 printf(" Authentication:      SSL/TLS (%s)\n",
13911                         SSLeay_version(SSLEAY_VERSION));
13912                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13913             } else {
13914                 printf(" Authentication:      SSL/TLS (not installed)\n");
13915                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13916                 continue;
13917             }
13918
13919 #ifdef CK_SSL
13920             printf(" RSA Certs file: %s\n",ssl_rsa_cert_file?
13921                   ssl_rsa_cert_file:"(none)");
13922             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13923             printf(" RSA Certs Chain file: %s\n",ssl_rsa_cert_chain_file?
13924                   ssl_rsa_cert_chain_file:"(none)");
13925             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13926             printf(" RSA Key file: %s\n",ssl_rsa_key_file?
13927                   ssl_rsa_key_file:"(none)");
13928             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13929             printf(" DSA Certs file: %s\n",ssl_dsa_cert_file?
13930                   ssl_dsa_cert_file:"(none)");
13931             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13932             printf(" DSA Certs Chain file: %s\n",ssl_dsa_cert_chain_file?
13933                   ssl_dsa_cert_chain_file:"(none)");
13934             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13935             printf(" DH Key file: %s\n",ssl_dh_key_file?
13936                   ssl_dh_key_file:"(none)");
13937             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13938             printf(" DH Param file: %s\n",ssl_dh_param_file?
13939                   ssl_dh_param_file:"(none)");
13940             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13941             printf(" CRL file: %s\n",ssl_crl_file?
13942                   ssl_crl_file:"(none)");
13943             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13944             printf(" CRL dir: %s\n",ssl_crl_dir?
13945                     ssl_crl_dir:"(none)");
13946             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13947             printf(" Random file: %s\n",ssl_rnd_file?
13948                   ssl_rnd_file:"(none)");
13949             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13950             printf(" Verify file: %s\n",ssl_verify_file?
13951                   ssl_verify_file:"(none)");
13952             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13953             printf(" Verify dir: %s\n",ssl_verify_dir?
13954                   ssl_verify_dir:"(none)");
13955             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13956             printf(" Cipher list: %s\n",ssl_cipher_list ? ssl_cipher_list : 
13957                     DEFAULT_CIPHER_LIST);
13958             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13959             if (ssl_con == NULL) {
13960                 SSL_library_init();
13961                 ssl_ctx = (SSL_CTX *)
13962                   SSL_CTX_new((SSL_METHOD *)TLSv1_method());
13963                 if (ssl_ctx != NULL)
13964                   ssl_con= (SSL *) SSL_new(ssl_ctx);
13965             }
13966             if (ssl_con != NULL) {
13967                 CHAR * p = NULL;
13968                 int i;
13969
13970                 for (i = 0; ; i++) {
13971                     p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
13972                     if (p == NULL)
13973                       break;
13974                     printf("    %s\n",p);
13975                     if (++n > cmd_rows - 3)
13976                         if (!askmore()) return(0); else n = 0;
13977                 }
13978             }
13979             printf(" Certs OK? %s\n",ssl_certsok_flag? "yes" : "no");
13980             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13981             printf(" Debug mode: %s\n", ssl_debug_flag ? "on" : "off");
13982             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13983             printf(" Verbose mode: %s\n", ssl_verbose_flag ? "on" : "off");
13984             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13985             printf(" Verify mode: %s\n",
13986                     ssl_verify_flag == SSL_VERIFY_NONE ? "none" :
13987                     ssl_verify_flag == SSL_VERIFY_PEER ? "peer-cert" :
13988                     "fail-if-no-peer-cert");
13989             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13990             printf(" SSL only? %s\n", ssl_only_flag ? "yes" : "no");
13991             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13992             printf(" TLS only? %s\n", tls_only_flag ? "yes" : "no");
13993             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
13994 #endif /* CK_SSL */
13995             break;
13996           case AUTHTYPE_NTLM:
13997             kv = 0;
13998             if (ck_ntlm_is_installed()) {
13999                 printf(" Authentication:      NTLM\n");
14000                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14001                 printf(" No options\n");
14002                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14003             } else {
14004                 printf(" Authentication:      NTLM (not installed)\n");
14005                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14006                 continue;
14007             }
14008             printf("\n");
14009             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14010             break;
14011           case AUTHTYPE_SRP:
14012             kv = all ? AUTHTYPE_NTLM : 0;
14013             if (ck_srp_is_installed()) {
14014                 if (ck_krypto_is_installed())
14015                     printf(" Authentication:      SRP plus Krypto API\n");
14016                 else
14017                     printf(" Authentication:      SRP\n");
14018                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14019                 printf(" No options\n");
14020                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14021             } else {
14022                 printf(" Authentication:      SRP (not installed)\n");
14023                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14024                 continue;
14025             }
14026             printf("\n");
14027             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14028             break;
14029         }
14030     }
14031     return(success = 1);
14032 }
14033 #endif /* CK_AUTHENTICATION */
14034 #endif /* NOSHOW */
14035
14036 #ifdef CK_KERBEROS
14037
14038 /*  C P _ A U T H  --  AUTHENTICATE command parsing  */
14039
14040 int
14041 cp_auth() {                             /* Command_Parse AUTHENTICATE */
14042     int c, i, n;                        /* Workers */
14043     int rc = 0;                         /* Return code */
14044     int getval;                         /* Parsing helpers */
14045     int tmpauth = 0;                    /* Temporary authentication type */
14046     int kv = 0;                         /* Temporary Kerberos version */
14047     int tmp_action = -1;                /* Temporary Kerberos action */
14048     int tmp_klc = 0;                    /* Temporary list-credentials */
14049     char tmphlp[256];                   /* For building help message */
14050     char * p;
14051     char * tmppswd  = NULL;             /* Password */
14052     char * tmpprinz = NULL;             /* Principal */
14053     char * tmprealm = NULL;             /* Realm */
14054     char * tmpcache = NULL;             /* Cache file */
14055     char * tmpinst  = NULL;             /* K4 Instance */
14056     char * tmpaddrs[KRB5_NUM_OF_ADDRS];
14057 #ifdef CK_RECALL
14058     extern int on_recall;               /* around Password prompting */
14059 #endif /* CK_RECALL */
14060     struct stringint {                  /* Temporary array for switch values */
14061         char * sval;                    /* String value */
14062         int ival;                       /* Integer value */
14063     } pv[KRB_I_MAX+1];                  /* This many */
14064     struct FDB kw, sw, fl;              /* FDBs for each parse function */
14065
14066     krb_action = -1;                    /* Initialize Kerberos action. */
14067     tmp_action = -1;                    /* And our local copy. */
14068     for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
14069       tmpaddrs[i] = NULL;
14070
14071     if ((y = cmkey(kerbtab,kerbtabn,"authentication type","",xxstring)) < 0)
14072       {
14073           if (y == -3)
14074             printf("?Authentication type not specified - nothing happens\n");
14075           return(y);
14076       }
14077     tmpauth = y;
14078     debug(F101,"kerberos authentication","",tmpauth);
14079     switch (tmpauth) {
14080       case AUTH_KRB4: kv = 4; break;    /* Don't assume values are the same */
14081       case AUTH_KRB5: kv = 5; break;
14082       default:
14083         printf("?Authentication type not supported: \"%s\"\n",atmbuf);
14084         return(-9);
14085     }
14086
14087     /* From here down is Kerberos */
14088     ini_kerb();                         /* Reset Init data to defaults */
14089
14090     if (kv == 4) {                      /* Set K4 defaults */
14091         if (krb4_d_realm)
14092           makestr(&tmprealm,krb4_d_realm);
14093         if (krb4_d_principal)
14094           makestr(&tmpprinz,krb4_d_principal);
14095         if (krb4_d_instance)
14096           makestr(&tmpinst,krb4_d_instance);
14097     } else if (kv == 5) {               /* Set K5 defaults */
14098         if (krb5_d_cc)
14099           makestr(&tmpcache,krb5_d_cc);
14100         if (krb5_d_realm)
14101           makestr(&tmprealm,krb5_d_realm);
14102         if (krb5_d_principal)
14103           makestr(&tmpprinz,krb5_d_principal);
14104         if (krb5_d_instance)
14105           makestr(&tmpinst,krb5_d_instance);
14106     }
14107
14108     for (i = 0; i <= KRB_I_MAX; i++) {  /* Initialize switch values */
14109         pv[i].sval = NULL;              /* to null pointers */
14110         pv[i].ival = 0;                 /* and 0 int values */
14111     }
14112
14113     if (kv == 4) {                      /* Kerberos 4 */
14114         pv[KRB_I_LF].ival = krb4_d_lifetime;
14115         pv[KRB_I_PA].ival = krb4_d_preauth;
14116
14117         if ((n = cmkey(krb_a_tbl,krb_a_n,"Kerberos 4 action","",xxstring)) < 0)
14118           {
14119               if (n == -3)
14120                 printf("?Action not specified - nothing happens.\n");
14121               return(n);
14122           }
14123     } else if (kv == 5) {               /* Kerberos 5 */
14124         pv[KRB_I_FW].ival = krb5_d_forwardable;
14125         pv[KRB_I_PR].ival = krb5_d_proxiable;
14126         pv[KRB_I_LF].ival = krb5_d_lifetime;
14127         pv[KRB_I_RB].ival = krb5_d_renewable;
14128         pv[KRB_I_K4].ival = krb5_d_getk4;
14129         pv[KRB_I_NAD].ival = krb5_d_no_addresses;
14130
14131         /* Make help message that shows switches and action keywords */
14132         ckstrncpy(tmphlp,"Kerberos 5 action, one of the following:\n ",256);
14133         for (i = 0; i < krb_a_n; i++) {
14134             ckstrncat(tmphlp,krb_a_tbl[i].kwd,sizeof(tmphlp));
14135             if (i == krb_a_n - 1)
14136               ckstrncat(tmphlp,"\nor switch",sizeof(tmphlp));
14137             else
14138               ckstrncat(tmphlp,"   ",sizeof(tmphlp));
14139         }
14140         /* Set up first set of chained FDB's */
14141
14142         cmfdbi(&sw,                     /* First FDB - command switches */
14143                _CMKEY,                  /* fcode */
14144                tmphlp,                  /* hlpmsg */
14145                "",                      /* default (none) */
14146                "",                      /* addtl string data */
14147                krb_s_n,                 /* Switch table size */
14148                4,                       /* addtl numeric data 2: 4 = cmswi */
14149                xxstring,                /* Processing function */
14150                krb_s_tbl,               /* Switch table */
14151                &kw                      /* Pointer to next FDB */
14152                );
14153         cmfdbi(&kw,                     /* Second FDB - action keywords */
14154                _CMKEY,                  /* fcode */
14155                "Kerberos action",       /* hlpmsg */
14156                "",                      /* default (none) */
14157                "",                      /* addtl string data */
14158                krb_a_n,                 /* Switch table size */
14159                0,                       /* addtl num data (0 = NOT switch) */
14160                xxstring,                /* Processing function */
14161                krb_a_tbl,               /* Keyword table */
14162                NULL                     /* Pointer to next FDB (none) */
14163                );
14164
14165         /* Parse */
14166
14167         while (1) {                     /* Parse 0 or more switches */
14168             rc = cmfdb(&sw);            /* Parse something */
14169             debug(F101,"kerberos cmfdb 1 rc","",rc);
14170             if (rc < 0) {                       /* Error */
14171                 if (rc == -3)
14172                   printf("?Action not specified - nothing happens.\n");
14173                 return(rc);             /* or reparse needed */
14174             }
14175             if (cmresult.fdbaddr != &sw) /* Break out if not a switch */
14176               break;
14177             c = cmgbrk();               /* Have switch - get break character */
14178             getval = (c == ':' || c == '='); /* Must parse an agument? */
14179             if (getval && !(cmresult.kflags & CM_ARG)) {
14180                 printf("?This switch does not take arguments\n");
14181                 return(-9);             /* OK because nothing malloc'd yet */
14182             }
14183             if (!getval && (cmgkwflgs() & CM_ARG)) {
14184                 printf("?This switch requires an argument\n");
14185                 return(-9);
14186             }
14187             n = cmresult.nresult;       /* Numeric result = switch value */
14188             debug(F101,"kerberos command switch","",n);
14189
14190             switch (n) {                /* Handle the switch */
14191               case KRB_S_CA:            /* /CACHE:<filename> */
14192                 p = krb5_d_cc ? krb5_d_cc : "";
14193                 if ((y = cmofi("Name of cache file",p,&s,xxstring)) < 0) {
14194                     if (y == -3)
14195                       s = NULL;
14196                     else
14197                       return(y);
14198                 }
14199                 makestr(&tmpcache,s);
14200                 break;
14201               default:
14202                 printf("?Unexpected switch value - internal error\n");
14203                 return(-9);             /* (if) nothing malloc'd yet. */
14204             }
14205         }
14206         if (cmresult.fdbaddr != &kw) {  /* Checking... */
14207             printf("?Unexpected result - internal error\n");
14208             return(-9);                 /* Nothing malloc'd yet. */
14209         }
14210         n = cmresult.nresult;           /* Get keyword value */
14211     } else {
14212         printf("?Unexpected Kerberos version - Internal error\n");
14213         return(-9);
14214     }
14215     debug(F101,"kerberos action","",n);
14216     switch (n) {
14217       case KRB_A_IN:                    /* INITIALIZE */
14218       case KRB_A_DE:                    /* DESTROY */
14219       case KRB_A_LC:                    /* LIST-CREDENTIALS */
14220         tmp_action = n;                 /* OK, set */
14221         break;
14222       default:                          /* Not OK, punt. */
14223         printf("?Unexpected action - internal error\n");
14224         return(-9);
14225     }
14226     if (tmp_action == KRB_A_IN) {       /* Action is INITIALIZE */
14227         int x;
14228         cmfdbi(&sw,                     /* INITIALIZE switches */
14229                _CMKEY,                  /* fcode */
14230                "Principal,\n or optional INITIALIZE switch(es)", /* hlpmsg */
14231                "",                      /* default (none) */
14232                "",                      /* addtl string data */
14233                kv == 4 ?  krb4_i_n : krb5_i_n, /* Switch table size */
14234                4,                       /* addtl numeric data 2: 4 = cmswi */
14235                xxstring,                /* Processing function */
14236                kv == 4 ?  krb4_i_tbl : krb5_i_tbl,      /* Switch table */
14237                &fl                      /* Pointer to next FDB */
14238                );
14239         cmfdbi(&fl,                     /* 3rd FDB - command to send from */
14240                _CMFLD,                  /* fcode */
14241                "Principal",             /* hlpmsg */
14242                kv == 4 ? krb4_d_principal : krb5_d_principal, /* principal */
14243                "",                      /* addtl string data */
14244                0,                       /* addtl numeric data 1 */
14245                0,                       /* addtl numeric data 2 */
14246                xxstring,
14247                NULL,
14248                NULL
14249                );
14250         while (1) {                     /* Parse INIT switches or principal */
14251             rc = cmfdb(&sw);
14252             debug(F101,"kerberos cmfdb 2 rc","",rc);
14253             if (rc < 0) {
14254                 if (rc == -3)
14255                   printf("?Principal name required\n");
14256                 goto kerbx;
14257             }
14258             debug(F101,"kerberos cmfdb 2 fcode","",cmresult.fcode);
14259             if (cmresult.fcode != _CMKEY) /* Not a switch, quit switch loop */
14260               break;
14261             c = cmgbrk();               /* Switch - get break character */
14262             debug(F101,"kerberos cmfdb 2 cmgbrk","",c);
14263             getval = (c == ':' || c == '=');
14264             if (getval && !(cmresult.kflags & CM_ARG)) {
14265                 printf("?This switch does not take arguments\n");
14266                 return(-9);             /* OK because nothing malloc'd yet */
14267             }
14268             if (!getval && (cmgkwflgs() & CM_ARG)) {
14269                 printf("?This switch requires an argument\n");
14270                 return(-9);
14271             }
14272             n = cmresult.nresult;       /* Numeric result = switch value */
14273             switch (n) {
14274               /* These don't take args... */
14275               case KRB_I_PA:            /* /PREAUTH */
14276               case KRB_I_FW:            /* /FORWARDABLE */
14277               case KRB_I_PR:            /* /PROXIABLE */
14278               case KRB_I_RN:            /* /RENEW */
14279               case KRB_I_VA:            /* /VALIDATE */
14280               case KRB_I_NPA:           /* /NOT-PREAUTH */
14281               case KRB_I_NFW:           /* /NOT-FORWARDABLE */
14282               case KRB_I_NPR:           /* /NOT-PROXIABLE */
14283               case KRB_I_VB:            /* /VERBOSE */
14284               case KRB_I_BR:            /* /BRIEF */
14285               case KRB_I_K4:            /* /KERBEROS4 */
14286               case KRB_I_NK4:           /* /NO-KERBEROS4 */
14287               case KRB_I_POP:           /* /POPUP */
14288               case KRB_I_NAD:           /* /NO-ADDRESSES */
14289                 if (getval) {
14290                     printf("?This switch does not take a value\n");
14291                     rc = -9;
14292                     goto kerbx;
14293                 }
14294                 switch (n) {
14295                   case KRB_I_NPA:
14296                     pv[KRB_I_PA].ival = 0;
14297                     break;
14298                   case KRB_I_NFW:
14299                     pv[KRB_I_FW].ival = 0;
14300                     break;
14301                   case KRB_I_NPR:
14302                     pv[KRB_I_PR].ival = 0;
14303                     break;
14304                   case KRB_I_VB:
14305                     pv[KRB_I_BR].ival = 0;
14306                     break;
14307                   case KRB_I_NK4:
14308                     pv[KRB_I_K4].ival = 0;
14309                     break;
14310                   default:
14311                     pv[n].ival = 1;
14312                 }
14313                 break;
14314
14315                 /* These do take arguments */
14316
14317               case KRB_I_RB:            /* /RENEWABLE:<minutes> */
14318                 pv[n].ival = 0;
14319                 if (!getval) break;
14320                 if ((rc = cmnum("Minutes",ckitoa(krb5_init.renewable),
14321                                 10,&y, xxstring)) < 0)
14322                   goto kerbx;
14323                 pv[n].ival = y;
14324                 break;
14325
14326               case KRB_I_LF:            /* /LIFETIME:<minutes> */
14327                 pv[n].ival = 0;
14328                 /* Default is previous value */
14329                 sprintf(tmpbuf,"%d",    /* SAFE */
14330                         kv == 4 ?
14331                         krb4_init.lifetime :
14332                         krb5_init.lifetime
14333                         );
14334                 if (!getval) break;
14335                 if ((rc = cmnum("Minutes",tmpbuf,10,&y, xxstring)) < 0)
14336                   goto kerbx;
14337                 pv[n].ival = y;
14338                 break;
14339
14340               case KRB_I_PD:            /* /POSTDATE:<timestamp> */
14341                 if (pv[n].sval) {
14342                     free(pv[n].sval);
14343                     pv[n].sval = NULL;
14344                 }
14345                 if (!getval) break;
14346                 if ((rc = cmdate("date-time","",&s,0,xxstring)) < 0)
14347                   goto kerbx;
14348                 makestr(&(pv[n].sval),s);
14349                 break;
14350
14351               case KRB_I_SR:            /* /SERVICE:<name> */
14352                 if (pv[n].sval) {
14353                     free(pv[n].sval);
14354                     pv[n].sval = NULL;
14355                 }
14356                 if (!getval) break;
14357                 if ((rc = cmfld("Service-name","",&s,xxstring)) < 0)
14358                   goto kerbx;
14359                 makestr(&(pv[n].sval),s);
14360                 break;
14361
14362               case KRB_I_RL:            /* /REALM:<name> */
14363                 if (pv[n].sval) {
14364                     free(pv[n].sval);
14365                     pv[n].sval = NULL;
14366                 }
14367                 if (!getval) break;
14368                 if (kv == 4)
14369                   p = krb4_d_realm ? krb4_d_realm : "";
14370                 else
14371                   p = krb5_d_realm ? krb5_d_realm : "";
14372                 if ((rc = cmfld("Realm",p,&s,xxstring)) < 0)
14373                   goto kerbx;
14374                 makestr(&(pv[n].sval),s);
14375                 break;
14376
14377               case KRB_I_IN:            /* /INSTANCE:<name> */
14378                 if (pv[n].sval) {
14379                     free(pv[n].sval);
14380                     pv[n].sval = NULL;
14381                 }
14382                 if (!getval) break;
14383                 if (kv == 4)
14384                     p = krb4_d_instance ? krb4_d_instance : "";
14385                 else
14386                     p = krb5_d_instance ? krb5_d_instance : "";
14387                 if ((rc = cmfld("Instance",p,&s,xxstring)) < 0)
14388                   goto kerbx;
14389                 makestr(&(pv[n].sval),s);
14390                 break;
14391
14392               case KRB_I_PW:            /* /PASSWORD:<password> */
14393                 debok = 0;
14394                 if (pv[n].sval) {
14395                     free(pv[n].sval);
14396                     pv[n].sval = NULL;
14397                 }
14398                 if (!getval) break;
14399                 if ((rc = cmfld("Password","",&s,xxstring)) < 0)
14400                   if (rc != -3)
14401                     goto kerbx;
14402                 makestr(&(pv[n].sval),s);
14403                 break;
14404
14405               case KRB_I_ADR:           /* /ADDRESSES:{<address-list>} */
14406                 if (pv[n].sval) {
14407                     free(pv[n].sval);
14408                     pv[n].sval = NULL;
14409                 }
14410                 if (!getval) break;
14411                 if ((rc = cmfld("List of IP addresses","",&s,xxstring)) < 0)
14412                   goto kerbx;
14413                 makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
14414                 for (i = 0; i < KRB5_NUM_OF_ADDRS && tmpaddrs[i]; i++) {
14415                     if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
14416                         printf("invalid ip address: %s\n",tmpaddrs[i]);
14417                         rc = -9;
14418                         goto kerbx;
14419                     }
14420                 }
14421                 pv[KRB_I_NAD].ival = 0;
14422                 break;
14423
14424               default:
14425                 printf("?Unexpected switch value - internal error\n");
14426                 rc = -9;
14427                 goto kerbx;
14428             }
14429         }
14430         if (cmresult.fcode != _CMFLD) {
14431             printf("?Unexected result - internal error\n");
14432             rc = -9;
14433             goto kerbx;
14434         }
14435         /* cmresult.sresult may be of the form PRINCIPAL@REALM */
14436         i = ckindex("@",cmresult.sresult,0,0,0);
14437         if (i != 0) {
14438             makestr(&tmprealm,&cmresult.sresult[i]);
14439             cmresult.sresult[i-1] = '\0';
14440         }
14441         makestr(&tmpprinz,cmresult.sresult); /* Principal (user) */
14442
14443         if ((rc = cmcfm()) < 0) {       /* Now get confirmation */
14444             if (rc == -3) {
14445                 printf("?Principal name required\n");
14446             }
14447             goto kerbx;
14448         }
14449         if (!tmpprinz || !tmpprinz[0]) {
14450             printf("?Principal name required\n");
14451             goto kerbx;
14452         }
14453         if (!pv[KRB_I_RN].ival && !pv[KRB_I_VA].ival) {
14454             /* Don't use a password if Validating or Renewing */
14455             if (pv[KRB_I_PW].sval) {    /* If they gave a /PASSWORD switch */
14456                 makestr(&tmppswd,pv[KRB_I_PW].sval); /* use this value */
14457             }
14458 #ifdef COMMENT
14459             /* Password prompting has been moved to ck_krb[45]_initTGT() */
14460             else {                      /* Otherwise must prompt for it */
14461                 char prmpt[80];
14462                 if (pv[KRB_I_RL].sval)
14463                   sprintf(prmpt,"%s@%s's Password: ",
14464                           tmpprinz,pv[KRB_I_RL].sval);
14465                 else if (tmprealm)
14466                   sprintf(prmpt,"%s@%s's Password: ",
14467                           tmpprinz,tmprealm);
14468                 else
14469                   sprintf(prmpt,"%s's Password: ",tmpprinz);
14470 #ifdef OS2
14471                 if (pv[KRB_I_POP].ival) {
14472                     char passwd[80]="";
14473                     readpass(prmpt,passwd,80);
14474                     makestr(&tmppswd,passwd);
14475                     memset(passwd,0,80);
14476                 } else
14477 #endif /* OS2 */
14478                 {
14479 #ifdef CK_RECALL
14480                     on_recall = 0;
14481 #endif /* CK_RECALL */
14482                     cmsavp(psave,PROMPTL); /* Save old prompt */
14483                     cmsetp(prmpt);      /* Make new prompt */
14484                     concb((char)escape); /* Put console in cbreak mode */
14485                     cmini(0);           /* and no-echo mode */
14486                     /* Issue prompt if at top level */
14487                     if (pflag) prompt(xxstring);
14488                     cmres();            /* Reset the parser */
14489                     for (rc = -1; rc < 0; ) { /* Prompt till they answer */
14490                         /* Get a literal line of text */
14491                         rc = cmtxt("","",&s,NULL);
14492                         cmres();        /* Reset the parser again */
14493                     }
14494                     makestr(&tmppswd,s);
14495                     printf("\n");       /* Echo a CRLF */
14496                     cmsetp(psave);      /* Restore original prompt */
14497                 }
14498             }
14499             x = 0;                      /* Check for password */
14500             if (tmppswd)
14501               if (*tmppswd)
14502                 x = 1;
14503             if (!x) {
14504                 printf("?Password required\n");
14505                 goto kerbx;
14506             }
14507 #endif /* COMMENT */
14508         }
14509     } else if (kv == 5 && tmp_action == KRB_A_LC) { /* LIST-CREDENTIALS */
14510         tmp_klc = 0;
14511         while (1) {
14512             if ((x = cmkey(klctab,nklctab,"Switch","",xxstring)) < 0) {
14513                 if (x == -3) {
14514                     if ((rc = cmcfm()) < 0)
14515                       goto kerbx;
14516                     else
14517                       break;
14518                 } else {
14519                     rc = x;
14520                     goto kerbx;
14521                 }
14522             }
14523             tmp_klc |= x;
14524         }
14525     } else if ((rc = cmcfm()) < 0)      /* DESTROY, just confirm */
14526         goto kerbx;
14527
14528 /* Done - Move confirmed data to final locations */
14529
14530     krb_action = tmp_action;            /* Action requested */
14531     krb_op.version = kv;                /* Kerberos version */
14532     krb_op.cache = tmpcache;            /* Cache file */
14533     tmpcache = NULL;                    /* So we don't free it */
14534
14535     switch (krb_action) {
14536       case KRB_A_IN:                    /* INITIALIZE */
14537         if (kv == 5) {
14538             krb5_init.forwardable = pv[KRB_I_FW].ival;
14539             krb5_init.proxiable   = pv[KRB_I_PR].ival;
14540             krb5_init.lifetime    = pv[KRB_I_LF].ival;
14541             krb5_init.renew       = pv[KRB_I_RN].ival;
14542             krb5_init.renewable   = pv[KRB_I_RB].ival;
14543             krb5_init.validate    = pv[KRB_I_VA].ival;
14544
14545             /* Here we just reassign the pointers and then set them to NULL */
14546             /* so they won't be freed below. */
14547
14548             krb5_init.postdate = pv[KRB_I_PD].sval; pv[KRB_I_PD].sval = NULL;
14549             krb5_init.service  = pv[KRB_I_SR].sval; pv[KRB_I_SR].sval = NULL;
14550             if (pv[KRB_I_RL].sval) {
14551                 krb5_init.realm  = pv[KRB_I_RL].sval; pv[KRB_I_RL].sval = NULL;
14552             } else if (tmprealm) {
14553                 krb5_init.realm = tmprealm; tmprealm = NULL;
14554             }
14555             if (pv[KRB_I_IN].sval) {
14556                 krb5_init.instance = pv[KRB_I_IN].sval;
14557                 pv[KRB_I_IN].sval = NULL;
14558             } else if ( tmpinst ) {
14559                 krb5_init.instance = tmpinst;
14560                 tmpinst = NULL;
14561             }
14562             if (tmpprinz) {
14563                 krb5_init.principal = tmpprinz;
14564                 tmpprinz = NULL;
14565             }
14566             krb5_init.password = tmppswd;
14567             tmppswd = NULL;
14568
14569             krb5_init.getk4 = pv[KRB_I_K4].ival;
14570             if (krb5_init.getk4) {
14571                 krb4_init.lifetime = pv[KRB_I_LF].ival;
14572                 if (krb5_init.realm)
14573                     makestr(&krb4_init.realm,krb5_init.realm);
14574                 krb4_init.preauth  = krb4_d_preauth;
14575                 krb4_init.verbose  = pv[KRB_I_BR].ival ? 0 : 1;
14576                 if (krb5_init.principal)
14577                     makestr(&krb4_init.principal,krb5_init.principal);
14578                 if (krb5_init.principal)
14579                     makestr(&krb4_init.password,krb5_init.password);
14580             }
14581             krb5_init.no_addresses = pv[KRB_I_NAD].ival;
14582             if (tmpaddrs[0]) {
14583                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
14584                     if (krb5_init.addrs[i]) {
14585                         free(krb5_init.addrs[i]);
14586                         krb5_init.addrs[i] = NULL;
14587                     }
14588                     krb5_init.addrs[i] = tmpaddrs[i];
14589                     tmpaddrs[i] = NULL;
14590                 }
14591             }
14592         } else if (kv == 4) {           /* Same deal for Kerberos 4 */
14593             krb4_init.lifetime = pv[KRB_I_LF].ival;
14594             if (pv[KRB_I_RL].sval) {
14595                 krb4_init.realm  = pv[KRB_I_RL].sval;
14596                 pv[KRB_I_RL].sval = NULL;
14597             } else if ( tmprealm ) {
14598                 krb4_init.realm  = tmprealm;
14599                 tmprealm = NULL;
14600             }
14601             if (pv[KRB_I_IN].sval) {
14602                 krb4_init.instance = pv[KRB_I_IN].sval;
14603                 pv[KRB_I_IN].sval = NULL;
14604             } else if ( tmpinst ) {
14605                 krb4_init.instance = tmpinst;
14606                 tmpinst = NULL;
14607             }
14608             krb4_init.preauth  = pv[KRB_I_PA].ival;
14609             krb4_init.verbose  = pv[KRB_I_BR].ival ? 0 : 1;
14610
14611             if (tmpprinz) {
14612                 krb4_init.principal = tmpprinz;
14613                 tmpprinz = NULL;
14614             }
14615             krb4_init.password = tmppswd;
14616             tmppswd = NULL;
14617         }
14618         break;
14619       case KRB_A_LC:                    /* List Credentials */
14620         krb5_lc.encryption = tmp_klc & XYKLCEN;
14621         krb5_lc.flags = tmp_klc & XYKLCFL;
14622         krb5_lc.addr  = tmp_klc & XYKLCAD;
14623         break;
14624     }
14625
14626 /* Common exit - Free temporary storage */
14627
14628   kerbx:
14629     for (i = 0; i <= KRB_I_MAX; i++) {  /* Free malloc'd switch data */
14630         if (pv[i].sval)
14631           free(pv[i].sval);
14632     }
14633     for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
14634         if (tmpaddrs[i])
14635           free(tmpaddrs[i]);
14636     }
14637     if (tmpprinz) free(tmpprinz);       /* And these too. */
14638     if (tmppswd)  free(tmppswd);
14639     if (tmpcache) free(tmpcache);
14640     if (tmprealm) free(tmprealm);
14641     if (tmpinst)  free(tmpinst);
14642
14643     return(rc);                         /* Return the return code */
14644 }
14645 #endif /* CK_KERBEROS */
14646
14647 #ifdef CK_LOGIN
14648 int
14649 #ifdef CK_ANSIC
14650 ckxlogin(CHAR * userid, CHAR * passwd, CHAR * acct, int promptok)
14651 #else /* CK_ANSIC */
14652 ckxlogin(userid, passwd, acct, promptok)
14653   CHAR * userid; CHAR * passwd; CHAR * acct; int promptok;
14654 #endif /* CK_ANSIC */
14655 /* ckxlogin */ {
14656 #ifdef CK_RECALL
14657     extern int on_recall;               /* around Password prompting */
14658 #endif /* CK_RECALL */
14659 #ifdef CK_PAM
14660     extern int guest;
14661 #endif /* CK_PAM */
14662     int rprompt = 0;                    /* Restore prompt */
14663 #ifdef CKSYSLOG
14664     int savlog;
14665 #endif /* CKSYSLOG */
14666
14667     extern int what, srvcdmsg;
14668
14669     int x = 0, ok = 0, rc = 0;
14670     CHAR * _u = NULL, * _p = NULL, * _a = NULL;
14671
14672     debug(F111,"ckxlogin userid",userid,promptok);
14673     debug(F110,"ckxlogin passwd",passwd,0);
14674
14675     isguest = 0;                        /* Global "anonymous" flag */
14676
14677     if (!userid) userid = (CHAR *)"";
14678     if (!passwd) passwd = (CHAR *)"";
14679
14680     debug(F111,"ckxlogin userid",userid,what);
14681
14682 #ifdef CK_RECALL
14683     on_recall = 0;
14684 #endif /* CK_RECALL */
14685
14686 #ifdef CKSYSLOG
14687     savlog = ckxsyslog;                 /* Save and turn off syslogging */
14688 #endif /* CKSYSLOG */
14689
14690     if ((!*userid || !*passwd) &&       /* Need to prompt for missing info */
14691         promptok) {
14692         cmsavp(psave,PROMPTL);          /* Save old prompt */
14693         debug(F110,"ckxlogin saved",psave,0);
14694         rprompt = 1;
14695     }
14696     if (!*userid) {
14697         if (!promptok)
14698           return(0);
14699         cmsetp("Username: ");           /* Make new prompt */
14700         concb((char)escape);            /* Put console in cbreak mode */
14701         cmini(1);
14702
14703 /* Flush typeahead */
14704
14705 #ifdef IKS_OPTION
14706         debug(F101,
14707               "ckxlogin TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
14708               "",
14709               TELOPT_SB(TELOPT_KERMIT).kermit.me_start
14710               );
14711 #endif /* IKS_OPTION */
14712
14713         while (ttchk() > 0) {
14714             x = ttinc(0);
14715             debug(F101,"ckxlogin flush user x","",x);
14716             if (x < 0)
14717               doexit(GOOD_EXIT,0);      /* Connection lost */
14718 #ifdef TNCODE
14719             if (sstelnet) {
14720                 if (x == IAC) {
14721                     x = tn_doop((CHAR)(x & 0xff),ckxech,ttinc);
14722                     debug(F101,"ckxlogin user tn_doop","",x);
14723 #ifdef IKS_OPTION
14724                     debug(F101,
14725                       "ckxlogin user TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
14726                       "",
14727                       TELOPT_SB(TELOPT_KERMIT).kermit.me_start
14728                       );
14729 #endif /* IKS_OPTION */
14730
14731                     if (x < 0)
14732                       goto XCKXLOG;
14733                     switch (x) {
14734                       case 1: ckxech = 1; break; /* Turn on echoing */
14735                       case 2: ckxech = 0; break; /* Turn off echoing */
14736 #ifdef IKS_OPTION
14737                       case 4:                    /* IKS event */
14738                         if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
14739                           break;                 /* else fall thru... */
14740 #endif /* IKS_OPTION */
14741                       case 6:                    /* Logout */
14742                         goto XCKXLOG;
14743                     }
14744                 }
14745             }
14746 #endif /* TNCODE */
14747         }
14748         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
14749         cmres();                        /* Reset the parser */
14750         for (x = -1; x < 0;) {          /* Prompt till they answer */
14751             /* Get a literal line of text */
14752             x=cmtxt("Your username, or \"ftp\", or \"anonymous\"","",&s,NULL);
14753             if (x == -4 || x == -10) {
14754                 printf("\r\n%sLogin cancelled\n",
14755                        x == -10 ? "Timed out: " : "");
14756 #ifdef CKSYSLOG
14757                 ckxsyslog = savlog;
14758 #endif /* CKSYSLOG */
14759                 doexit(GOOD_EXIT,0);
14760             }
14761             if (sstate)                 /* Did a packet come instead? */
14762               goto XCKXLOG;
14763             cmres();                    /* Reset the parser again */
14764         }
14765         if ((_u = (CHAR *)malloc((int)strlen(s) + 1)) == NULL) {
14766             printf("?Internal error: malloc\n");
14767             goto XCKXLOG;
14768         } else {
14769             strcpy((char *)_u,s);       /* safe */
14770             userid = _u;
14771         }
14772     }
14773     ok = zvuser((char *)userid);        /* Verify username */
14774     debug(F111,"ckxlogin zvuser",userid,ok);
14775
14776     if (!*passwd && promptok
14777 #ifdef CK_PAM
14778         && guest
14779 #endif /* CK_PAM */
14780         ) {
14781         char prmpt[80];
14782
14783 #ifdef CKSYSLOG
14784         savlog = ckxsyslog;             /* Save and turn off syslogging */
14785         ckxsyslog = 0;
14786 #endif /* CKSYSLOG */
14787
14788 /* Flush typeahead again */
14789
14790         while (ttchk() > 0) {
14791             x = ttinc(0);
14792             debug(F101,"ckxlogin flush user x","",x);
14793 #ifdef TNCODE
14794             if (sstelnet) {
14795                 if (x == IAC) {
14796                     x = tn_doop((CHAR)(x & 0xff),ckxech,ttinc);
14797                     debug(F101,"ckxlogin pass tn_doop","",x);
14798 #ifdef IKS_OPTION
14799                     debug(F101,
14800                       "ckxlogin pass TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
14801                       "",
14802                       TELOPT_SB(TELOPT_KERMIT).kermit.me_start
14803                       );
14804 #endif /* IKS_OPTION */
14805                     if (x < 0)
14806                       goto XCKXLOG;
14807                     switch (x) {
14808                       case 1: ckxech = 1; break; /* Turn on echoing */
14809                       case 2: ckxech = 0; break; /* Turn off echoing */
14810                       case 4:                    /* IKS event */
14811                         if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
14812                           break;                 /* else fall thru... */
14813                       case 6:                    /* Logout */
14814                         goto XCKXLOG;
14815                     }
14816                 }
14817             }
14818 #endif /* TNCODE */
14819         }
14820         if (!strcmp((char *)userid,"anonymous") ||
14821             !strcmp((char *)userid,"ftp")) {
14822             if (!ok)
14823               goto XCKXLOG;
14824             ckstrncpy(prmpt,"Enter e-mail address as Password: ",80);
14825         } else if (*userid && strlen((char *)userid) < 60) {
14826 #ifdef NT
14827             extern CHAR * pReferenceDomainName;
14828             if (pReferenceDomainName)
14829               ckmakxmsg(prmpt,
14830                        80,
14831                        "Enter ",
14832                        pReferenceDomainName,
14833                        "\\\\",
14834                        userid,
14835                        "'s Password: ",
14836                        NULL,NULL,NULL,NULL,NULL,NULL,NULL
14837                        );
14838             else
14839 #endif /* NT */
14840               ckmakmsg(prmpt,80,"Enter ",(char *)userid,"'s Password: ",NULL);
14841         } else
14842           ckstrncpy(prmpt,"Enter Password: ",80);
14843         cmsetp(prmpt);                  /* Make new prompt */
14844         concb((char)escape);            /* Put console in cbreak mode */
14845         if (strcmp((char *)userid,"anonymous") &&
14846             strcmp((char *)userid,"ftp")) { /* and if not anonymous */
14847             debok = 0;
14848             cmini(0);                   /* and no-echo mode */
14849         } else {
14850             cmini(1);
14851         }
14852         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
14853         cmres();                        /* Reset the parser */
14854         for (x = -1; x < 0;) {          /* Prompt till they answer */
14855             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
14856             if (x == -4 || x == -10) {
14857                 printf("\r\n%sLogin cancelled\n",
14858                        x == -10 ? "Timed out: " : "");
14859 #ifdef CKSYSLOG
14860                 ckxsyslog = savlog;
14861 #endif /* CKSYSLOG */
14862                 doexit(GOOD_EXIT,0);
14863             }
14864             if (sstate)                 /* In case of a Kermit packet */
14865               goto XCKXLOG;
14866             cmres();                    /* Reset the parser again */
14867         }
14868         printf("\r\n");                 /* Echo a CRLF */
14869         if ((_p = (CHAR *)malloc((int)strlen(s) + 1)) == NULL) {
14870             printf("?Internal error: malloc\n");
14871             goto XCKXLOG;
14872         } else {
14873             strcpy((char *)_p,s);       /* safe */
14874             passwd = _p;
14875         }
14876     }
14877 #ifdef CK_PAM
14878     else {
14879         cmres();                        /* Reset the parser */
14880
14881         /* We restore the prompt now because the PAM engine will call  */
14882         /* readpass() which will overwrite psave. */
14883         if (rprompt) {
14884             cmsetp(psave);              /* Restore original prompt */
14885             debug(F110,"ckxlogin restored",psave,0);
14886             rprompt = 0;
14887         }
14888     }
14889 #endif /* CK_PAM */
14890
14891 #ifdef CKSYSLOG
14892     ckxsyslog = savlog;
14893 #endif /* CKSYSLOG */
14894
14895     if (ok) {
14896         ok = zvpass((char *)passwd);    /* Check password */
14897         debug(F101,"ckxlogin zvpass","",ok);
14898     }
14899
14900     if (ok > 0 && isguest) {
14901 #ifndef NOPUSH
14902         nopush = 1;
14903 #endif /* NOPUSH */
14904         srvcdmsg = 1;
14905     }
14906     rc = ok;                            /* Set the return code */
14907     if ((char *)uidbuf != (char *)userid)
14908       ckstrncpy(uidbuf,(char *)userid,UIDBUFLEN); /* Remember username */
14909
14910   XCKXLOG:                              /* Common exit */
14911 #ifdef CKSYSLOG
14912     ckxsyslog = savlog;                 /* In case of GOTO above */
14913 #endif /* CKSYSLOG */
14914     if (rprompt) {
14915         cmsetp(psave);                  /* Restore original prompt */
14916         debug(F110,"ckxlogin restored",psave,0);
14917     }
14918     if (_u || _p || _a) {
14919         if (_u) free(_u);
14920         if (_p) free(_p);
14921         if (_a) free(_a);
14922     }
14923     return(rc);
14924 }
14925
14926 int
14927 ckxlogout() {
14928     doexit(GOOD_EXIT,0);                /* doexit calls zvlogout */
14929     return(0);                          /* not reached */
14930 }
14931 #endif /* CK_LOGIN */
14932
14933 #endif /* NOICP */