Imported Upstream version 302
[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, 2011,
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 extern int mskrename;
70 #endif /* OS2 */
71
72 #ifdef CK_AUTHENTICATION
73 #include "ckuath.h"
74 #endif /* CK_AUTHENTICATION */
75 #ifdef CK_SSL
76 #include "ck_ssl.h"
77 #endif /* CK_SSL */
78 #ifdef SSHBUILTIN
79 #include "ckossh.h"
80 #endif /* SSHBUILTIN */
81 #ifdef STRATUS                          /* Stratus Computer, Inc.  VOS */
82 #ifdef putchar
83 #undef putchar
84 #endif /* putchar */
85 #define putchar(x) conoc(x)
86 #ifdef getchar
87 #undef getchar
88 #endif /* getchar */
89 #define getchar(x) coninc(0)
90 #endif /* STRATUS */
91
92 char * slmsg = NULL;
93
94 static int x, y = 0, z;
95 static char *s;
96
97 extern CHAR feol;
98 extern int g_matchdot, hints, xcmdsrc, rcdactive;
99
100 extern char * k_info_dir;
101
102 #ifdef CK_LOGIN
103 #ifdef CK_PAM
104 int gotemptypasswd = 0;   /* distinguish empty passwd from none given */
105 #endif /* CK_PAM */
106 #endif /* CK_LOGIN */
107
108 #ifndef NOSPL
109 extern int nmac;
110 extern struct mtab *mactab;
111 #endif /* NOSPL */
112
113 #ifndef NOXFER
114 #ifdef CK_SPEED
115 extern short ctlp[];                    /* Control-char prefixing table */
116 #endif /* CK_SPEED */
117
118 #ifdef PIPESEND
119 extern char * sndfilter, * g_sfilter;
120 extern char * rcvfilter, * g_rfilter;
121 #endif /* PIPESEND */
122
123 extern char * snd_move;
124 extern char * snd_rename;
125 extern char * g_snd_move;
126 extern char * g_snd_rename;
127 extern char * rcv_move;
128 extern char * rcv_rename;
129 extern char * g_rcv_move;
130 extern char * g_rcv_rename;
131
132 #ifdef PATTERNS
133 extern char *binpatterns[], *txtpatterns[];
134 extern int patterns;
135 #endif /* PATTERNS */
136
137 extern char * remdest;
138 #ifdef CK_TMPDIR
139 char * dldir = NULL;
140 #endif /* CK_TMPDIR */
141
142 extern struct ck_p ptab[];
143
144 extern int protocol, remfile, rempipe, remappd, reliable, xreliable, fmask,
145   fncnv, frecl, maxrps, wslotr, bigsbsiz, bigrbsiz, urpsiz, rpsiz, spsiz,
146   bctr, npad, timef, timint, spsizr, spsizf, maxsps, spmax, nfils, displa,
147   atcapr, pkttim, rtimo, fncact, mypadn, fdispla, f_save, pktpaus, setreliable,
148   fnrpath, fnspath, atenci, atenco, atdati, atdato, atleni, atleno, atblki,
149   atblko, attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
150
151 extern int stathack;
152
153 extern int atfrmi, atfrmo;
154 #ifdef STRATUS
155 extern int atcrei, atcreo, atacti, atacto;
156 #endif /* STRATUS */
157 #ifdef CK_PERMS
158 extern int atlpri, atlpro, atgpri, atgpro;
159 #endif /* CK_PERMS */
160
161 extern CHAR
162   sstate, eol, seol, stchr, mystch, mypadc, padch, ctlq, myctlq;
163
164 #ifdef IKSD
165 extern int inserver;
166 #ifdef IKSDCONF
167 extern int iksdcf;
168 #endif /* IKSDCONF */
169 #endif /* IKSD */
170
171 extern char *cmarg, *cmarg2;
172
173 #ifndef NOFRILLS
174 extern char optbuf[];                   /* Buffer for MAIL or PRINT options */
175 extern int rprintf;                     /* REMOTE PRINT flag */
176 #endif /* NOFRILLS */
177 #endif /* NOXFER */
178
179 #ifdef CK_TRIGGER
180 extern char * tt_trigger[];
181 #endif /* CK_TRIGGER */
182
183 extern int tcs_transp;
184 #ifdef PCTERM
185 extern int tt_pcterm;
186 #endif /* PCTERM */
187 #ifdef NT
188 extern int tt_vtnt;
189 #endif /* NT */
190
191 #ifdef SSHBUILTIN
192 int sl_ssh_xfw = 0;
193 int sl_ssh_xfw_saved = 0;
194 int sl_ssh_ver = 0;
195 int sl_ssh_ver_saved = 0;
196 #endif /* SSHBUILTIN */
197
198 #ifdef CK_AUTHENTICATION
199 extern int auth_type_user[];
200 int sl_auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_NULL, AUTHTYPE_NULL};
201 int sl_auth_saved = 0;
202 int sl_topt_a_su = 0;
203 int sl_topt_a_s_saved = 0;
204 int sl_topt_a_cm = 0;
205 int sl_topt_a_c_saved = 0;
206 #endif /* CK_AUTHENTICATION */
207 #ifdef CK_ENCRYPTION
208 extern int cx_type;
209 int sl_cx_type = 0;
210 int sl_cx_saved = 0;
211 int sl_topt_e_su = 0;
212 int sl_topt_e_sm = 0;
213 int sl_topt_e_s_saved = 0;
214 int sl_topt_e_cu = 0;
215 int sl_topt_e_cm = 0;
216 int sl_topt_e_c_saved = 0;
217 #endif /* CK_ENCRYPTION */
218 extern char uidbuf[];
219 static int uidflag = 0;
220 char sl_uidbuf[UIDBUFLEN] = { NUL, NUL };
221 int  sl_uid_saved = 0;
222 #ifdef TNCODE
223 int  sl_tn_wait = 0;
224 int  sl_tn_saved = 0;
225 #endif /* TNCODE */
226
227 #ifdef TNCODE
228 extern int tn_wait_flg;
229 #endif /* TNCODE */
230
231 VOID
232 slrestor() {
233 #ifdef CK_AUTHENTICATION
234     int x;
235     if (sl_auth_saved) {
236         for (x = 0; x < AUTHTYPLSTSZ; x++)
237           auth_type_user[x] = sl_auth_type_user[x];
238         sl_auth_saved = 0;
239     }
240     if (sl_topt_a_s_saved) {
241         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = sl_topt_a_su;
242         sl_topt_a_s_saved = 0;
243     }
244     if (sl_topt_a_c_saved) {
245         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = sl_topt_a_cm;
246         sl_topt_a_c_saved = 0;
247     }
248 #endif /* CK_AUTHENTICATION */
249 #ifdef CK_ENCRYPTION
250     if (sl_cx_saved) {
251         cx_type = sl_cx_type;
252         sl_cx_saved = 0;
253     }
254     if (sl_topt_e_s_saved) {
255         TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION)  = sl_topt_e_su;
256         TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = sl_topt_e_sm;
257         sl_topt_e_s_saved = 0;
258     }
259     if (sl_topt_e_c_saved) {
260         TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION)  = sl_topt_e_cu;
261         TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = sl_topt_e_cm;
262         sl_topt_e_c_saved = 0;
263     }
264 #endif /* CK_ENCRYPTION */
265     if (sl_uid_saved) {
266         ckstrncpy(uidbuf,sl_uidbuf,UIDBUFLEN);
267         sl_uid_saved = 0;
268     }
269 #ifdef TNCODE
270     if (sl_tn_saved) {
271         tn_wait_flg = sl_tn_wait;
272         sl_tn_saved = 0;
273     }
274 #endif /* TNCODE */
275 #ifdef SSHBUILTIN
276     if (sl_ssh_xfw_saved) {
277         ssh_xfw = sl_ssh_xfw;
278         sl_ssh_xfw_saved = 0;
279     }
280     if (sl_ssh_ver_saved) {
281         ssh_ver = sl_ssh_ver;
282         sl_ssh_ver_saved = 0;
283     }
284 #endif /* SSHBUILTIN */
285 }
286
287 int oldplex = -1;                       /* Duplex holder around network */
288
289 #ifndef NOICP
290 #ifdef LOCUS
291 extern int locus, autolocus;
292 #endif /* LOCUS */
293 #ifndef NODIAL
294 extern int dialsta;
295 #endif /* NODIAL */
296
297 /* Note: gcc -Wall wants braces around each keyword table entry. */
298
299 static struct keytab psltab[] = {       /* SET LINE/PORT command options */
300     { "/connect", SL_CNX, 0 },
301 #ifdef OS2ORVMS
302     { "/noshare", SL_NSH, 0 },
303 #endif /* OS2ORVMS */
304     { "/server",  SL_SRV, 0 },
305 #ifdef OS2ORVMS
306     { "/share",   SL_SHR, 0 },
307 #endif /* OS2ORVMS */
308     { "", 0, 0 }
309 };
310 static int npsltab = sizeof(psltab)/sizeof(struct keytab) - 1;
311
312 #ifdef NETCONN
313 static struct keytab shtab[] = {        /* SET HOST command options */
314 #ifdef NETCMD
315     /* (COMMAND is also a network type) */
316     { "/command",      SL_CMD,    CM_INV },
317 #endif /* NETCMD */
318     { "/connect",      SL_CNX,    0 },
319     { "/network-type", SL_NET,    CM_ARG },
320     { "/nowait",       SL_NOWAIT, 0 },
321 #ifndef NOSPL
322 #ifdef CK_AUTHENTICATION
323     { "/password",     SL_PSW,    CM_ARG },
324 #endif /* CK_AUTHENTICATION */
325 #endif /* NOSPL */
326 #ifdef NETCMD
327     { "/pipe",         SL_CMD,    0 },
328 #endif /* NETCMD */
329 #ifdef NETPTY
330     { "/pty",          SL_PTY,    0 },
331 #endif /* NETPTY */
332     { "/server",       SL_SRV,    0 },
333     { "/timeout",      SL_TMO,    CM_ARG },
334     { "/userid",       SL_UID,    CM_ARG },
335     { "/wait",         SL_WAIT,   0 },
336     { "", 0, 0 }
337 };
338 static int nshtab = sizeof(shtab)/sizeof(struct keytab) - 1;
339
340 static struct keytab shteltab[] = {     /* TELNET command options */
341 #ifdef CK_AUTHENTICATION
342     { "/auth",         SL_AUTH,   CM_ARG },
343 #endif /* CK_AUTHENTICATION */
344 #ifdef CK_ENCRYPTION
345     { "/encrypt",      SL_ENC,    CM_ARG },
346 #endif /* CK_ENCRYPTION */
347     { "/nowait",       SL_NOWAIT, 0 },
348 #ifndef NOSPL
349 #ifdef CK_AUTHENTICATION
350     { "/password",     SL_PSW,    CM_ARG },
351 #endif /* CK_AUTHENTICATION */
352 #endif /* NOSPL */
353     { "/timeout",      SL_TMO,    CM_ARG },
354     { "/userid",       SL_UID,    CM_ARG },
355     { "/wait",         SL_WAIT,   0 },
356     { "", 0 ,0 }
357 };
358 static int nshteltab = sizeof(shteltab)/sizeof(struct keytab) - 1;
359
360 #ifdef RLOGCODE
361 static struct keytab shrlgtab[] = {     /* SET HOST RLOGIN command options */
362 #ifdef CK_KERBEROS
363 #ifdef CK_ENCRYPTION
364     { "/encrypt",      SL_ENC, 0 },
365 #endif /* CK_ENCRYPTION */
366     { "/k4",           SL_KRB4, CM_INV },
367     { "/k5",           SL_KRB5, CM_INV },
368     { "/kerberos4",    SL_KRB4, 0 },
369     { "/kerberos5",    SL_KRB5, 0 },
370     { "/kerberos_iv",  SL_KRB4, CM_INV },
371     { "/kerberos_v",   SL_KRB5, CM_INV },
372     { "/krb4",         SL_KRB4, CM_INV },
373     { "/krb5",         SL_KRB5, CM_INV },
374 #endif /* CK_KERBEROS */
375     { "", 0 ,0 }
376 };
377 static int nshrlgtab = sizeof(shrlgtab)/sizeof(struct keytab)-1;
378 #endif /* RLOGCODE */
379
380 extern struct keytab netcmd[];
381 extern int nnets;
382 #ifndef NODIAL
383 extern int dirline;
384 extern int nnetdir;                     /* Network services directory */
385 extern char *netdir[];
386 _PROTOTYP( VOID ndreset, (void) );
387 char *nh_p[MAXDNUMS + 1];               /* Network directory entry pointers */
388 char *nh_p2[MAXDNUMS + 1];              /* Network directory entry nettype */
389 char *nh_px[4][MAXDNUMS + 1];           /* Network-specific stuff... */
390 #endif /* NODIAL */
391 int nhcount = 0;
392 int ndinited = 0;
393 char * n_name = NULL;                   /* Network name pointer */
394 #endif /* NETCONN */
395
396 _PROTOTYP(int remtxt, (char **) );
397 _PROTOTYP(VOID rmsg, (void) );
398 _PROTOTYP(static int remcfm, (void) );
399
400 extern int nopush;
401
402 int mdmsav = -1;                        /* Save modem type around network */
403 extern int isguest;                     /* Global flag for anonymous login */
404
405 extern xx_strp xxstring;
406
407 extern int success, binary, b_save, ckwarn, msgflg, quiet, cmask, pflag, local,
408   nettype, escape, mdmtyp, duplex, dfloc, network, cdtimo, autoflow, tnlm,
409   sosi, tlevel, lf_opts, backgrd, flow, debses, parity, ttnproto, ckxech,
410   x_ifnum, cmflgs, haveline, cxtype, cxflow[], maclvl;
411
412 #ifdef DCMDBUF
413 extern struct cmdptr *cmdstk;           /* The command stack itself */
414 #else
415 extern struct cmdptr cmdstk[];          /* The command stack itself */
416 #endif /* DCMDBUF */
417 extern FILE * tfile[];
418 extern char * macp[];
419
420 extern char psave[];                    /* For saving & restoring prompt */
421 extern int sprmlen, rprmlen;
422
423 #ifdef OS2
424 static struct keytab strmkeytab[] = {
425     { "clear",   0, 0 },
426     { "default", 1, 0 }
427 };
428 static int nstrmkeytab = sizeof(strmkeytab)/sizeof(struct keytab);
429
430 static struct keytab strmswitab[] = {
431     { "/literal", 0, 0 }
432 };
433 static int nstrmswitab = sizeof(strmswitab)/sizeof(struct keytab);
434
435 static struct keytab normrev[] = {
436     { "dark-display", 0, 0 },
437     { "light-display", 1, 0 },
438     { "normal",   0, 0 },
439     { "reverse",  1, 0 }
440 };
441
442 static struct keytab prnmtab[] = {
443     { "auto", 1, 0 },
444     { "copy", 2, 0 },
445     { "off",  0, 0 },
446     { "on",   1, CM_INV },              /* Compatibility with XPRINT version */
447     { "user", 3, 0 },
448     { "transparent", 3, CM_INV }        /* not really transparent */
449 };
450 static int nprnmtab = sizeof(prnmtab)/sizeof(struct keytab);
451
452 extern int tt_diff_upd;
453
454 #ifdef NT
455 #define stricmp _stricmp
456 extern int tt_attr_bug;
457 #endif /* NT */
458 extern int tt_rows[], tt_cols[];
459 extern int tt_cols_usr;
460 extern int tt_szchng[VNUM];
461 int tt_modechg = TVC_ENA;
462 extern int tt_url_hilite, tt_url_hilite_attr;
463 extern struct _vtG G[4];
464 extern int priority;
465 extern bool send_c1;
466 int send_c1_usr = FALSE;
467 extern int sgrcolors;
468 extern int marginbell, marginbellcol;
469 extern int autoscroll, wy_autopage;
470 extern int tt_sac;
471 extern int dec_nrc, dec_lang, dec_kbd;
472 #else /* OS2 */
473 extern int tt_rows, tt_cols;
474 #endif /*  OS2 */
475
476 extern int tt_escape;
477 extern long speed;
478
479 extern char *dftty;
480
481 extern char *tp, *lp;                   /* Temporary buffer & pointers */
482 extern char ttname[];
483
484 #ifdef CK_TAPI
485 int tttapi = 0;                         /* is Line TAPI? */
486 struct keytab * tapilinetab = NULL;
487 struct keytab * _tapilinetab = NULL;
488 int ntapiline = 0;
489 #endif /* CK_TAPI */
490
491 #ifdef NETCONN                          /* Network items */
492
493 #ifdef ANYX25
494 extern int revcall, closgr, cudata, nx25;
495 extern char udata[];
496 extern struct keytab x25tab[];
497 #ifndef IBMX25
498 extern int npadx3;
499 extern CHAR padparms[];
500 extern struct keytab padx3tab[];
501 #endif /* IBMX25 */
502 #endif /* ANYX25 */
503
504 #ifdef OS2
505 extern bool ttshare;
506 #ifndef NT
507 extern bool ttslip,ttppp;
508 #endif /* NT */
509 #endif /* OS2 */
510 #ifdef NPIPE
511 extern char pipename[];
512 #endif /* NPIPE */
513
514 #ifdef TCPSOCKET
515 static struct keytab tcprawtab[] = {    /* SET HOST options */
516     { "/default",    NP_DEFAULT,    CM_INV },
517 #ifdef CK_AUTHENTICATION
518 #ifdef CK_KERBEROS
519 #ifdef RLOGCODE
520     { "/ek4login",    NP_EK4LOGIN,    0 },
521     { "/ek5login",    NP_EK5LOGIN,    0 },
522     { "/k4login",     NP_K4LOGIN,     0 },
523     { "/k5login",     NP_K5LOGIN,     0 },
524 #endif /* RLOGCODE */
525 #ifdef KRB5_U2U
526     { "/k5user2user", NP_K5U2U,       0 },
527 #endif /* KRB5_U2U */
528 #endif /* CK_KERBEROS */
529 #endif /* CK_AUTHENTICATION */
530     { "/no-telnet-init", NP_NONE,   0 },
531     { "/none",       NP_NONE,   CM_INV },
532     { "/raw-socket", NP_TCPRAW, 0 },
533 #ifdef RLOGCODE
534     { "/rlogin",     NP_RLOGIN, 0 },
535 #endif /* RLOGCODE */
536 #ifdef CK_SSL
537     { "/ssl",        NP_SSL,    0 },
538     { "/ssl-raw",    NP_SSL_RAW, 0 },
539     { "/ssl-telnet", NP_SSL_TELNET, 0 },
540 #endif /* CK_SSL */
541     { "/telnet",     NP_TELNET, 0 },
542 #ifdef CK_SSL
543     { "/tls",        NP_TLS,    0 },
544     { "/tls-raw",    NP_TLS_RAW, 0 },
545     { "/tls-telnet", NP_TLS_TELNET, 0 },
546 #endif /* CK_SSL */
547     { "", 0, 0 }
548 };
549 static int ntcpraw = (sizeof(tcprawtab) / sizeof(struct keytab)) - 1;
550
551 #ifdef RLOGCODE
552 _PROTOTYP( int rlog_naws, (void) );
553 #endif /* RLOGCODE */
554 #endif /* TCPSOCKET */
555
556 #ifdef SUPERLAT
557 extern char slat_pwd[18];
558 #endif /* SUPERLAT */
559 #endif /* NETCONN */
560
561 #ifdef COMMENT
562 #ifndef NOSETKEY
563 extern KEY *keymap;
564 #ifndef OS2
565 #define mapkey(x) keymap[x]
566 #endif /* OS2 */
567 extern MACRO *macrotab;
568 #ifndef NOKVERBS
569 extern struct keytab kverbs[];
570 extern int nkverbs;
571 #endif /* NOKVERBS */
572 #endif /* NOSETKEY */
573 #else
574 #ifndef NOSETKEY
575 extern KEY *keymap;
576 extern MACRO *macrotab;
577 #ifndef NOKVERBS
578 extern struct keytab kverbs[];
579 extern int nkverbs;
580 #endif /* NOKVERBS */
581 #endif /* NOSETKEY */
582 #endif /* COMMENT */
583
584 #ifdef OS2                              /* AUTODOWNLOAD parameters */
585 extern int    adl_kmode, adl_zmode;     /* Match Packet to signal download */
586 extern char * adl_kstr;                 /* KERMIT Download String */
587 extern char * adl_zstr;                 /* ZMODEM Download String */
588 extern int adl_kc0, adl_zc0;            /* Process ADL C0s in emulation */
589 #endif /* OS2 */
590
591 /* Keyword tables ... */
592
593 extern struct keytab onoff[], rltab[];
594 extern int nrlt;
595
596 #ifndef NOCSETS
597 static struct keytab fdfltab[] = {
598     { "7bit-character-set", 7, 0 },
599     { "8bit-character-set", 8, 0 }
600 };
601 static int nfdflt = (sizeof(fdfltab) / sizeof(struct keytab));
602 #endif /* NOCSETS */
603
604 /* SET FILE parameters */
605
606 static struct keytab filtab[] = {
607 #ifndef NOXFER
608 #ifdef PATTERNS
609     { "binary-patterns",   XYFIBP,  0 },
610 #endif /* PATTERNS */
611     { "bytesize",         XYFILS,   0 },
612 #ifndef NOCSETS
613     { "character-set",    XYFILC,   0 },
614 #endif /* NOCSETS */
615     { "collision",        XYFILX,   0 },
616     { "default",          XYF_DFLT, 0 },
617     { "destination",      XYFILY,   0 },
618     { "display",          XYFILD,   CM_INV },
619 #ifdef CK_TMPDIR
620     { "download-directory", XYFILG, 0 },
621 #endif /* CK_TMPDIR */
622 #endif /* NOXFER */
623     { "end-of-line",      XYFILA,   0 },
624     { "eol",              XYFILA,   CM_INV },
625 #ifdef CK_CTRLZ
626     { "eof",              XYFILV,   0 },
627 #endif /* CK_CTRLZ */
628 #ifndef NOXFER
629     { "fastlookups",      9997,     CM_INV },
630     { "incomplete",       XYFILI,   0 },
631 #ifndef datageneral
632     { "inspection",       XYF_INSP, CM_INV },
633 #endif /* datageneral */
634 #ifdef CK_LABELED
635     { "label",            XYFILL, 0 },
636 #endif /* CK_LABELED */
637
638 #ifdef UNIX
639 #ifdef DYNAMIC
640     { "listsize",         XYF_LSIZ, 0 },
641 #endif /* DYNAMIC */
642 #endif /* UNIX */
643
644     { "names",            XYFILN, 0 },
645 #ifdef UNIX
646     { "output",           XYFILH, 0 },
647 #endif /* UNIX */
648 #ifdef PATTERNS
649     { "patterns",         XYFIPA, 0 },
650 #endif /* PATTERNS */
651 #ifdef COMMENT /* Not implemented (but see CHMOD) */
652     { "permissions",      XYF_PRM, CM_INV },
653     { "protection",       XYF_PRM, 0 },
654 #endif /* COMMENt */
655 #ifdef VMS
656     { "record-length",    XYFILR, 0 },
657 #endif /* VMS */
658 #ifndef datageneral
659     { "scan",             XYF_INSP, 0 },
660 #endif /* datageneral */
661
662 #ifdef UNIX
663 #ifdef DYNAMIC
664     { "stringspace",      XYF_SSPA, 0 },
665 #endif /* DYNAMIC */
666 #endif /* UNIX */
667
668 #ifdef PATTERNS
669     { "t",                XYFILT, CM_INV|CM_ABR },
670     { "text-patterns",    XYFITP, 0 },
671 #endif /* PATTERNS */
672 #endif /* NOXFER */
673     { "type",             XYFILT, 0 },
674 #ifdef UNICODE
675     { "ucs",              XYFILU, 0 },
676 #endif /* UNICODE */
677 #ifndef NOXFER
678     { "warning",          XYFILW, CM_INV }
679 #endif /* NOXFER */
680 };
681 static int nfilp = (sizeof(filtab) / sizeof(struct keytab));
682
683 struct keytab pathtab[] = {
684     { "absolute",  PATH_ABS,  0      },
685     { "none",      PATH_OFF,  CM_INV },
686     { "off",       PATH_OFF,  0      },
687     { "on",        PATH_ABS,  CM_INV },
688     { "relative",  PATH_REL,  0      }
689 };
690 int npathtab = (sizeof(pathtab) / sizeof(struct keytab));
691
692 struct keytab rpathtab[] = {
693     { "absolute",  PATH_ABS,  0      },
694     { "auto",      PATH_AUTO, 0      },
695     { "none",      PATH_OFF,  CM_INV },
696     { "off",       PATH_OFF,  0      },
697     { "on",        PATH_ABS,  CM_INV },
698     { "relative",  PATH_REL,  0      }
699 };
700 int nrpathtab = (sizeof(rpathtab) / sizeof(struct keytab));
701
702 #ifdef CK_CTRLZ
703 struct keytab eoftab[] = {              /* EOF detection method */
704     { "ctrl-z",          1, 0      },
705     { "length",          0, 0      },
706     { "noctrl-z",        0, CM_INV }
707 };
708 #endif /* CK_CTRLZ */
709
710 struct keytab fttab[] = {               /* File types for SET FILE TYPE */
711     { "ascii",     XYFT_T, CM_INV },
712 #ifdef VMS
713     { "b",         XYFT_B, CM_INV|CM_ABR },
714 #endif /* VMS */
715     { "binary",    XYFT_B, 0 },
716 #ifdef VMS
717     { "block",     XYFT_I, CM_INV },
718     { "image",     XYFT_I, 0 },
719 #endif /* VMS */
720 #ifdef CK_LABELED
721     { "labeled",   XYFT_L, 0 },
722 #endif /* CK_LABELED */
723 #ifdef MAC
724     { "macbinary", XYFT_M, 0 },
725 #endif /* MAC */
726     { "text",      XYFT_T, 0 }
727 };
728 int nfttyp = (sizeof(fttab) / sizeof(struct keytab));
729
730 static struct keytab rfttab[] = {       /* File types for REMOTE SET FILE */
731     { "ascii",     XYFT_T, CM_INV },
732     { "binary",    XYFT_B, 0 },
733 #ifdef VMS
734     { "labeled",   XYFT_L, 0 },
735 #else
736 #ifdef OS2
737     { "labeled",   XYFT_L, 0 },
738 #endif /* OS2 */
739 #endif /* VMS */
740     { "text",      XYFT_T, 0 }
741 };
742 static int nrfttyp = (sizeof(rfttab) / sizeof(struct keytab));
743
744 #ifdef OS2ORUNIX
745 #define ZOF_BLK  0
746 #define ZOF_NBLK 1
747 #define ZOF_BUF  2
748 #define ZOF_NBUF 3
749 static struct keytab zoftab[] = {
750     { "blocking",    ZOF_BLK,  0 },
751     { "buffered",    ZOF_BUF,  0 },
752     { "nonblocking", ZOF_NBLK, 0 },
753     { "unbuffered",  ZOF_NBUF, 0 }
754 };
755 static int nzoftab = (sizeof(zoftab) / sizeof(struct keytab));
756 #endif /* OS2ORUNIX */
757
758 extern int query;                       /* Global flag for QUERY active */
759
760 #ifndef NOSPL
761 #ifndef NOXFER
762 static struct keytab vartyp[] = {       /* Variable types for REMOTE QUERY */
763     { "global",   (int) 'G', CM_INV },
764     { "kermit",   (int) 'K', 0 },
765     { "system",   (int) 'S', 0 },
766     { "user",     (int) 'G', 0 }
767 };
768 static int nvartyp = (sizeof(vartyp) / sizeof(struct keytab));
769 #endif /* NOXFER */
770 #endif /* NOSPL */
771
772 #ifdef CK_TIMERS
773 static struct keytab timotab[] = {      /* Timer types */
774     { "dynamic", 1, 0 },
775     { "fixed",   0, 0 }
776 };
777 #endif /* CK_TIMERS */
778
779 #ifdef DCMDBUF
780 extern char *atxbuf, *atmbuf;           /* Atom buffer */
781 extern char *cmdbuf;                    /* Command buffer */
782 extern char *line, *tmpbuf;             /* Character buffers for anything */
783 extern int *intime;                     /* INPUT TIMEOUT */
784
785 #else  /* Not DCMDBUF ... */
786
787 extern char atxbuf[], atmbuf[];         /* Atom buffer */
788 extern char cmdbuf[];                   /* Command buffer */
789 extern char line[], tmpbuf[];           /* Character buffer for anything */
790 extern int intime[];
791
792 #endif /* DCMDBUF */
793
794 #ifndef NOCSETS
795 extern struct keytab fcstab[];          /* For SET FILE CHARACTER-SET */
796 extern struct csinfo fcsinfo[];         /* File character set info. */
797 extern struct keytab ttcstab[];
798 extern int nfilc, fcharset, tcharset, ntermc, tcsr, tcsl, dcset7, dcset8;
799 #ifdef CKOUNI
800 extern int tt_utf8;
801 #endif /* CKOUNI */
802 #ifdef OS2
803 _PROTOTYP( int os2setcp, (int) );
804 _PROTOTYP( int os2getcp, (void) );
805 _PROTOTYP( void os2debugoff, (void) );
806 #endif /* OS2 */
807 #endif /* NOCSETS */
808
809 extern int cmdlvl;                      /* Overall command level */
810
811 #ifndef NOSPL
812 #ifdef DCMDBUF
813 extern int *inpcas;                     /* INPUT CASE setting on cmd stack */
814 #else
815 extern int inpcas[];
816 #endif /* DCMDBUF */
817 #endif /* NOSPL */
818
819 #ifdef CK_CURSES
820 #ifndef VMS
821 _PROTOTYP(int tgetent,(char *, char *));
822 #else
823 #ifdef __DECC
824 _PROTOTYP(int tgetent,(char *, char *));
825 #endif /* __DECC */
826 #endif /* VMS */
827 #endif /* CK_CURSES */
828
829 #ifndef NOXMIT
830 #define XMITF 0                         /* SET TRANSMIT values */
831 #define XMITL 1                         /* (Local to this module) */
832 #define XMITP 2
833 #define XMITE 3
834 #define XMITX 4
835 #define XMITS 5
836 #define XMITW 6
837 #define XMITT 7
838
839 #define XMBUFL 50
840 extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw, xmitt;
841 char xmitbuf[XMBUFL+1] = { NUL };       /* TRANSMIT eof string */
842
843 struct keytab xmitab[] = {              /* SET TRANSMIT */
844     { "echo",          XMITX, 0 },
845     { "eof",           XMITE, 0 },
846     { "fill",          XMITF, 0 },
847     { "linefeed",      XMITL, 0 },
848     { "locking-shift", XMITS, 0 },
849     { "pause",         XMITW, 0 },
850     { "prompt",        XMITP, 0 },
851     { "timeout",       XMITT, 0 }
852 };
853 int nxmit = (sizeof(xmitab) / sizeof(struct keytab));
854 #endif /* NOXMIT */
855
856 /* For SET FILE COLLISION */
857 /* Some of the following may be possible for some C-Kermit implementations */
858 /* but not others.  Those that are not possible for your implementation */
859 /* should be ifdef'd out. */
860
861 struct keytab colxtab[] = { /* SET FILE COLLISION options */
862 #ifndef MAC
863     { "append",    XYFX_A, 0 },         /* append to old file */
864 #endif /* MAC */
865 #ifdef COMMENT
866     { "ask",       XYFX_Q, 0 },         /* ask what to do (not implemented) */
867 #endif
868     { "backup",    XYFX_B, 0 },         /* rename old file */
869 #ifndef MAC
870     /* This crashes Mac Kermit. */
871     { "discard",   XYFX_D, CM_INV },    /* don't accept new file */
872     { "no-supersede", XYFX_D, CM_INV }, /* ditto (MSK compatibility) */
873 #endif /* MAC */
874     { "overwrite", XYFX_X, 0 },         /* overwrite the old file */
875     { "reject",    XYFX_D, 0 },         /* (better word than discard) */
876     { "rename",    XYFX_R, 0 },         /* rename the incoming file */
877 #ifndef MAC                             /* This crashes Mac Kermit. */
878     { "update",    XYFX_U, 0 },         /* replace if newer */
879 #endif /* MAC */
880     { "", 0, 0 }
881 };
882 int ncolx = (sizeof(colxtab) / sizeof(struct keytab)) - 1;
883
884 static struct keytab rfiltab[] = {      /* for REMOTE SET FILE */
885 #ifndef NOCSETS
886     { "character-set", XYFILC, 0 },
887 #endif /* NOCSETS */
888     { "collision",     XYFILX, 0 },
889     { "incomplete",    XYFILI, 0 },
890     { "names",         XYFILN, 0 },
891     { "record-length", XYFILR, 0 },
892     { "type",          XYFILT, 0 }
893 };
894 int nrfilp = (sizeof(rfiltab) / sizeof(struct keytab));
895
896 struct keytab eoltab[] = {              /* File eof delimiters */
897     { "cr",        XYFA_C, 0 },
898     { "crlf",      XYFA_2, 0 },
899     { "lf",        XYFA_L, 0 }
900 };
901 static int neoltab = (sizeof(eoltab) / sizeof(struct keytab));
902
903 struct keytab fntab[] = {               /* File naming */
904     { "converted", XYFN_C, 0      },
905     { "literal",   XYFN_L, 0      },
906     { "standard",  XYFN_C, CM_INV }
907 };
908 int nfntab = (sizeof(fntab) / sizeof(struct keytab));
909
910 #ifndef NOLOCAL
911 /* Terminal parameters table */
912 static struct keytab trmtab[] = {
913 #ifdef OS2
914     { "answerback",    XYTANS,    0 },
915 #endif /* OS2 */
916 #ifdef CK_APC
917     { "apc",           XYTAPC,    0 },
918 #endif /* CK_APC */
919 #ifdef OS2
920     { "arrow-keys",    XYTARR,    0 },
921 #endif /* OS2 */
922 #ifdef NT
923     { "at",            XYTATTR,   CM_INV|CM_ABR },
924     { "att",           XYTATTR,   CM_INV|CM_ABR },
925     { "attr",          XYTATTR,   CM_INV|CM_ABR },
926     { "attr-bug",      XYTATTBUG, CM_INV },
927 #endif /* NT */
928 #ifdef OS2
929     { "attribute",     XYTATTR,   0 },
930 #endif /* OS2 */
931 #ifdef CK_APC
932 #ifdef CK_AUTODL
933    { "autodownload",   XYTAUTODL, 0, },
934 #endif /* CK_AUTODL */
935 #endif /* CK_APC */
936 #ifdef OS2
937     { "autopage",      XYTAPAGE,  0 },
938     { "autoscroll",    XYTASCRL,  0 },
939     { "bell",          XYTBEL,    CM_INV },
940 #endif /* OS2 */
941     { "bytesize",      XYTBYT,    0 },
942 #ifndef NOCSETS
943     { "character-set", XYTCS,     0 },
944 #endif /* NOCSETS */
945 #ifdef OS2
946     { "code-page",     XYTCPG,    0 },
947     { "color",         XYTCOL,    0 },
948     { "controls",      XYTCTRL,   0 },
949 #endif /* OS2 */
950     { "cr-display",    XYTCRD,    0 },
951 #ifdef OS2
952     { "cursor",        XYTCUR,    0 },
953 #endif /* OS2 */
954     { "debug",         XYTDEB,    0 },
955 #ifdef OS2
956     { "dg-unix-mode",  XYTUNX,    0 },
957 #endif /* OS2 */
958     { "echo",          XYTEC,     0 },
959     { "escape-character", XYTESC, 0 },
960 #ifdef OS2
961 #ifdef PCFONTS
962     { "font",          XYTFON,    0 },
963 #else
964 #ifdef KUI
965     { "font",          XYTFON,    0 },
966 #endif /* KUI */
967 #endif /* PCFONTS */
968 #endif /* OS2 */
969     { "height",        XYTHIG,    0 },
970 #ifdef CKTIDLE
971     { "idle-action",   XYTIACT,   0 },
972     { "idle-limit",    XYTITMO,   CM_INV },
973     { "idle-send",     XYTIDLE,   CM_INV },
974     { "idle-timeout",  XYTITMO,   0 },
975 #endif /* CKTIDLE */
976 #ifdef OS2
977 #ifndef NOCSETS
978     { "kbd-follows-gl/gr", XYTKBDGL, 0 },
979 #endif /* NOCSETS */
980     { "key",           XYTKEY,    0 },
981     { "keyboard-mode", XYTKBMOD,  0 },
982     { "keypad-mode",   XYTKPD,    0 },
983 #endif /* OS2 */
984     { "lf-display",    XYTLFD,    0 },
985 #ifndef NOCSETS
986 #ifdef OS2
987 #ifndef KUI
988     { "line-spacing",  XYTLSP,    CM_INV },
989     { "local-character-set", XYTLCS,  0 },
990 #else
991     { "line-spacing",  XYTLSP,    0 },
992     { "local-character-set", XYTLCS,  CM_INV },
993 #endif /* KUI */
994 #else
995     { "local-character-set", XYTLCS,  CM_INV },
996 #endif /* OS2 */
997 #endif /* NOCSETS */
998     { "locking-shift", XYTSO,     0 },
999 #ifdef OS2
1000     { "margin-bell",   XYTMBEL,   0 },
1001 #endif /* OS2 */
1002 #ifdef OS2MOUSE
1003     { "mouse",         XYTMOU,    CM_INV },
1004 #endif /* OS2MOUSE */
1005     { "newline-mode",  XYTNL,     0 },
1006 #ifdef OS2
1007     { "output-pacing", XYTPAC,    0 },
1008 #ifdef PCTERM
1009     { "pcterm",        XYTPCTERM, 0 },
1010 #endif /* PCTERM */
1011 #endif /* OS2 */
1012 #ifdef OS2ORUNIX
1013     { "print",         XYTPRN,    0 },
1014 #endif /* OS2ORUNIX */
1015 #ifndef NOCSETS
1016 #ifdef OS2
1017     { "remote-character-set", XYTRCS,  0 },
1018 #else
1019     { "remote-character-set", XYTRCS,  CM_INV },
1020 #endif /* OS2 */
1021 #endif /* NOCSETS */
1022 #ifdef OS2
1023     { "roll-mode",       XYTROL, 0 },
1024     { "s",               XYTUPD, CM_ABR|CM_INV },
1025     { "sc",              XYTUPD, CM_ABR|CM_INV },
1026     { "scr",             XYTUPD, CM_ABR|CM_INV },
1027     { "scree",           XYTUPD, CM_ABR|CM_INV },
1028     { "screen",          XYTUPD, CM_ABR|CM_INV },
1029     { "screen-",         XYTUPD, CM_ABR|CM_INV },
1030     { "screen-mode",     XYTSCNM,   0 },
1031     { "screen-optimize", XYTOPTI,   0 },
1032     { "screen-update",   XYTUPD,    0 },
1033     { "scrollback",      XYSCRS,    0 },
1034     { "send-data",         XYTSEND, 0 },
1035     { "send-end-of-block", XYTSEOB, 0 },
1036     { "sgr-colors",            XYTSGRC,  0 },
1037     { "sni-ch.code",           XYTSNICC, 0 },
1038     { "sni-firmware-versions", XYTSNIFV, 0 },
1039     { "sni-language",          XYTVTLNG, 0 },
1040     { "sni-pagemode",          XYTSNIPM, CM_INV },
1041     { "sni-scrollmode",              XYTSNISM, CM_INV },
1042     { "spacing-attribute-character", XYTSAC,   CM_INV },
1043     { "statusline",                  XYTSTAT,  0 },
1044     { "tra",                         XYTCTS,   CM_INV|CM_ABR },
1045     { "transmit-timeout",            XYTCTS,   0 },
1046 #endif /* OS2 */
1047
1048 #ifdef OS2ORUNIX
1049     { "transparent-print", XYTPRN,   CM_INV },
1050 #endif /* OS2ORUNIX */
1051
1052 #ifdef CK_TRIGGER
1053     { "trigger",           XYTRIGGER,0 },
1054 #endif /* CK_TRIGGER */
1055 #ifdef OS2
1056     { "type",              XYTTYP,   0 },
1057 #else
1058     { "type",              XYTTYP,   CM_INV },
1059 #endif /* OS2 */
1060
1061 #ifndef NOCSETS
1062 #ifdef UNICODE
1063 #ifdef CKOUNI
1064     { "unicode",           XYTUNI,   CM_INV },
1065 #endif /* CKOUNI */
1066 #endif /* UNICODE */
1067 #endif /* NOCSETS */
1068 #ifdef OS2
1069     { "unix-mode",         XYTUNX,   CM_INV },
1070     { "url-highlight",     XYTURLHI, 0 },
1071 #ifdef NT
1072     { "video-change",      XYTVCH,   0 },
1073 #endif /* NT */
1074     { "vt-language",       XYTVTLNG, 0 },
1075     { "vt-nrc-mode",       XYTVTNRC, 0 },
1076 #endif /* OS2 */
1077     { "width",             XYTWID,   0 },
1078 #ifdef OS2
1079     { "wrap",              XYTWRP,   0 },
1080 #endif /* OS2 */
1081     { "", 0, 0 }
1082 };
1083 int ntrm = (sizeof(trmtab) / sizeof(struct keytab)) - 1;
1084
1085 #ifdef OS2
1086 struct keytab termctrl[] = {    /* SET TERM CONTROLS */
1087     { "7",      7, 0 },
1088     { "8",      8, 0 }
1089 };
1090 int ntermctrl = (sizeof(termctrl) / sizeof(struct keytab));
1091
1092 struct keytab curontab[] = {    /* SET TERM CURSOR */
1093 #ifdef KUI
1094     { "noblink", 2, 0 },
1095 #else
1096     { "noblink", 2, CM_INV },
1097 #endif /* KUI */
1098     { "off",     0, 0 },
1099     { "on",      1, 0 }
1100 };
1101 int ncuron = (sizeof(curontab) / sizeof(struct keytab));
1102
1103 struct keytab rolltab[] = {   /* Set TERM Roll Options */
1104     { "insert",    TTR_INSERT, 0      },
1105     { "keystrokes",TTR_KEYS,   0      },
1106     { "off",       TTR_OVER,   CM_INV },
1107     { "on",        TTR_INSERT, CM_INV },
1108     { "overwrite", TTR_OVER,   0      }
1109 };
1110 int nroll = (sizeof(rolltab) / sizeof(struct keytab));
1111
1112 struct keytab rollkeytab[] = {          /* Set TERM ROLL KEYSTROKES */
1113     { "ignore",            TTRK_IGN, 0 },
1114     { "restore-and-send",  TTRK_RST, 0 },
1115     { "send",              TTRK_SND, 0 }
1116 };
1117 int nrollkey = (sizeof(rollkeytab) / sizeof(struct keytab));
1118
1119 #define TT_GR_ALL 4
1120 #define TT_GR_G0  0
1121 #define TT_GR_G1  1
1122 #define TT_GR_G2  2
1123 #define TT_GR_G3  3
1124 #define TT_GR_KBD 4
1125 struct keytab graphsettab[] = {  /* DEC VT Graphic Sets */
1126     { "all",      TT_GR_ALL, 0 },
1127     { "g0",       TT_GR_G0,  0 },
1128     { "g1",       TT_GR_G1,  0 },
1129     { "g2",       TT_GR_G2,  0 },
1130     { "g3",       TT_GR_G3,  0 },
1131     { "keyboard", TT_GR_KBD, 0 }
1132 };
1133 int ngraphset = (sizeof(graphsettab) / sizeof(struct keytab));
1134 #endif /* OS2 */
1135
1136 struct keytab adltab[] = {              /* Autodownload Options */
1137     { "ask",     TAD_ASK, 0 },
1138     { "error",   TAD_ERR, 0 },
1139 #ifdef OS2
1140     { "kermit",  TAD_K,   0 },
1141 #endif /* OS2 */
1142     { "off",     TAD_OFF, 0 },
1143     { "on",      TAD_ON,  0 },
1144 #ifdef OS2
1145     { "zmodem",  TAD_Z,   0 },
1146 #endif /* OS2 */
1147     { "", 0, 0 }
1148 };
1149 int nadltab = (sizeof(adltab) / sizeof(struct keytab)) - 1;
1150
1151 struct keytab adlerrtab[] = {           /* Autodownload Error Options */
1152     { "continue", 0, 0 },
1153     { "go",       0, CM_INV },
1154     { "stop",     1, 0 }
1155 };
1156 int nadlerrtab = (sizeof(adlerrtab) / sizeof(struct keytab));
1157
1158 #ifdef OS2
1159 struct keytab adlxtab[] = {             /* Autodownload Options */
1160     { "c0-conflicts",     TAD_X_C0,     0 },
1161     { "detection-method", TAD_X_DETECT, 0 },
1162     { "string",           TAD_X_STR,    0 }
1163 };
1164 int nadlxtab = (sizeof(adlxtab) / sizeof(struct keytab));
1165
1166 struct keytab adldtab[] = {             /* Auto-dl Detection Methods */
1167     { "packet",           ADL_PACK,     0 },
1168     { "string",           ADL_STR,      0 }
1169 };
1170 int nadldtab = (sizeof(adldtab) / sizeof(struct keytab));
1171
1172 struct keytab adlc0tab[] = {            /* Auto-dl Detection Methods */
1173     { "ignored-by-emulator",    0,      0 },
1174     { "processed-by-emulator",  1,      0 }
1175 };
1176 int nadlc0tab = (sizeof(adlc0tab) / sizeof(struct keytab));
1177
1178 #ifndef NOCSETS
1179 struct keytab vtlangtab[] = {
1180     { "belgian",        VTL_BELGIAN , 0 },
1181     { "british",        VTL_BRITISH , 0 },
1182     { "canadian",       VTL_CANADIAN, 0 },
1183     { "czech",          VTL_CZECH   , 0 },
1184     { "danish",         VTL_DANISH  , 0 },
1185     { "dutch",          VTL_DUTCH   , 0 },
1186     { "finnish",        VTL_FINNISH , 0 },
1187     { "french",         VTL_FRENCH  , 0 },
1188     { "french-canadian",VTL_FR_CAN  , 0 },
1189     { "german",         VTL_GERMAN  , 0 },
1190     { "greek",          VTL_GREEK   , 0 },
1191     { "hebrew",         VTL_HEBREW  , 0 },
1192     { "hungarian",      VTL_HUNGARIA, 0 },
1193     { "italian",        VTL_ITALIAN , 0 },
1194     { "latin-american", VTL_LATIN_AM, 0 },
1195     { "north-american", VTL_NORTH_AM, 0 },
1196     { "norwegian",      VTL_NORWEGIA, 0 },
1197     { "polish",         VTL_POLISH  , 0 },
1198     { "portugese",      VTL_PORTUGES, 0 },
1199     { "romanian",       VTL_ROMANIAN, 0 },
1200     { "russian",        VTL_RUSSIAN , 0 },
1201     { "scs",            VTL_SCS     , CM_INV },
1202     { "slovak",         VTL_SLOVAK  , 0 },
1203     { "spanish",        VTL_SPANISH , 0 },
1204     { "swedish",        VTL_SWEDISH , 0 },
1205     { "swiss-french",   VTL_SW_FR   , 0 },
1206     { "swiss-german",   VTL_SW_GR   , 0 },
1207     { "turkish-f",      VTL_TURK_F  , CM_INV },
1208     { "turkish-q",      VTL_TURK_Q  , CM_INV }
1209 };
1210 int nvtlangtab = (sizeof(vtlangtab) / sizeof(struct keytab));
1211 #endif /* NOCSETS */
1212 #endif /* OS2 */
1213
1214 struct keytab crdtab[] = {              /* Carriage-return display */
1215     { "crlf",        1, 0 },
1216     { "normal",      0, 0 }
1217 };
1218 extern int tt_crd;                      /* Carriage-return display variable */
1219 extern int tt_lfd;                      /* Linefeed display variable */
1220
1221 #ifdef CK_APC
1222 extern int apcstatus, apcactive;
1223 static struct keytab apctab[] = {       /* Terminal APC parameters */
1224     {  "no-input", APC_ON|APC_NOINP,0 },
1225     { "off",       APC_OFF,  0 },
1226     { "on",        APC_ON,   0 },
1227     { "unchecked", APC_ON|APC_UNCH, 0 },
1228     { "unchecked-no-input", APC_ON|APC_NOINP|APC_UNCH, 0 }
1229 };
1230 int napctab = (sizeof(apctab) / sizeof(struct keytab));
1231 #endif /* CK_APC */
1232 #endif /* NOLOCAL */
1233
1234 extern int autodl, adl_err, adl_ask;
1235
1236 struct keytab beltab[] = {              /* Terminal bell mode */
1237 #ifdef OS2
1238     { "audible", XYB_AUD,  0 },
1239     { "none",    XYB_NONE, 0 },
1240 #else
1241     { "audible", XYB_AUD,  CM_INV },
1242     { "none",    XYB_NONE, CM_INV },
1243 #endif /* OS2 */
1244 #ifdef OS2
1245     { "off",     XYB_NONE, CM_INV },
1246     { "on",      XYB_AUD,  CM_INV },
1247 #else
1248     { "off",     XYB_NONE, 0 },
1249     { "on",      XYB_AUD,  0 },
1250 #endif /* OS2 */
1251 #ifdef OS2
1252     { "visible", XYB_VIS,  0 },
1253 #endif /* OS2 */
1254     { "", 0, 0 }
1255 };
1256 int nbeltab = sizeof(beltab)/sizeof(struct keytab) - 1;
1257
1258 int tt_unicode = 1;                     /* Use Unicode if possible */
1259 #ifdef CKTIDLE
1260 int tt_idlesnd_tmo = 0;                 /* Idle Send Timeout, disabled */
1261 char * tt_idlesnd_str = NULL;           /* Idle Send String, none */
1262 char * tt_idlestr = NULL;
1263 extern int tt_idleact, tt_idlelimit;
1264 #endif /* CKTIDLE */
1265
1266 #ifdef OS2
1267 #ifndef NOLOCAL
1268 /*
1269   OS/2 serial communication devices.
1270 */
1271 struct keytab os2devtab[] = {
1272     { "1",    1, CM_INV },                      /* Invisible synonyms, like */
1273     { "2",    2, CM_INV },                      /* "set port 1" */
1274     { "3",    3, CM_INV },
1275     { "4",    4, CM_INV },
1276     { "5",    5, CM_INV },
1277     { "6",    6, CM_INV },
1278     { "7",    7, CM_INV },
1279     { "8",    8, CM_INV },
1280     { "com1", 1, 0 },                   /* Real device names */
1281     { "com2", 2, 0 },
1282     { "com3", 3, 0 },
1283     { "com4", 4, 0 },
1284     { "com5", 5, 0 },
1285     { "com6", 6, 0 },
1286     { "com7", 7, 0 },
1287     { "com8", 8, 0 },
1288 #ifdef OS2ONLY
1289     { "slipcom1", 1, 0 },                       /* For use with SLIP driver */
1290     { "slipcom2", 2, 0 },                       /* shared access */
1291     { "slipcom3", 3, 0 },
1292     { "slipcom4", 4, 0 },
1293     { "slipcom5", 5, 0 },
1294     { "slipcom6", 6, 0 },
1295     { "slipcom7", 7, 0 },
1296     { "slipcom8", 8, 0 },
1297     { "pppcom1", 1, 0 },                        /* For use with PPP driver */
1298     { "pppcom2", 2, 0 },                        /* shared access */
1299     { "pppcom3", 3, 0 },
1300     { "pppcom4", 4, 0 },
1301     { "pppcom5", 5, 0 },
1302     { "pppcom6", 6, 0 },
1303     { "pppcom7", 7, 0 },
1304     { "pppcom8", 8, 0 }
1305 #endif /* OS2ONLY */
1306 };
1307 int nos2dev = (sizeof(os2devtab) / sizeof(struct keytab)) - 1;
1308
1309 #ifdef OS2ONLY
1310 struct keytab os2ppptab[] = {
1311     { "0",    0, CM_INV },
1312     { "1",    1, CM_INV },                      /* Invisible synonyms, like */
1313     { "2",    2, CM_INV },                      /* "set port 1" */
1314     { "3",    3, CM_INV },
1315     { "4",    4, CM_INV },
1316     { "5",    5, CM_INV },
1317     { "6",    6, CM_INV },
1318     { "7",    7, CM_INV },
1319     { "8",    8, CM_INV },
1320     { "9",    9, CM_INV },
1321     { "ppp0", 0, 0 },
1322     { "ppp1", 1, 0 },                   /* For use with PPP driver */
1323     { "ppp2", 2, 0 },                   /* shared access */
1324     { "ppp3", 3, 0 },
1325     { "ppp4", 4, 0 },
1326     { "ppp5", 5, 0 },
1327     { "ppp6", 6, 0 },
1328     { "ppp7", 7, 0 },
1329     { "ppp8", 8, 0 },
1330     { "ppp9", 9, 0 }
1331 };
1332 int nos2ppp = (sizeof(os2ppptab) / sizeof(struct keytab));
1333 #endif /* OS2ONLY */
1334
1335 /*
1336   Terminal parameters that can be set by SET commands.
1337   Used by the ck?con.c terminal emulator code.
1338   For now, only used for #ifdef OS2.  Should add these for Macintosh.
1339 */
1340 int tt_arrow = TTK_NORM;                /* Arrow key mode: normal (cursor) */
1341 int tt_keypad = TTK_NORM;               /* Keypad mode: normal (numeric) */
1342 int tt_shift_keypad = 0;                /* Keypad Shift mode: Off */
1343 int tt_wrap = 1;                        /* Terminal wrap, 1 = On */
1344 int tt_type = TT_VT220;                 /* Terminal type, initially VT220 */
1345 int tt_type_mode = TT_VT220;            /* Terminal type set by host command */
1346 int tt_cursor = 0;                      /* Terminal cursor, 0 = Underline */
1347 int tt_cursor_usr = 0;                  /* Users Terminal cursor type */
1348 int tt_cursorena_usr = 1;               /* Users Terminal cursor enabled */
1349 int tt_cursor_blink = 1;                /* Terminal Cursor Blink */
1350 int tt_answer = 0;                      /* Terminal answerback (disabled) */
1351 int tt_scrsize[VNUM] = {512,512,512,1}; /* Terminal scrollback buffer size */
1352 int tt_roll[VNUM] = {1,1,1,1};          /* Terminal roll (on) */
1353 int tt_rkeys[VNUM] = {1,1,1,1};         /* Terminal roll keys (send) */
1354 int tt_pacing = 0;                      /* Terminal output-pacing (none) */
1355 int tt_ctstmo = 15;                     /* Terminal transmit-timeout */
1356 int tt_codepage = -1;                   /* Terminal code-page */
1357 int tt_update = 100;                    /* Terminal screen-update interval */
1358 int tt_updmode = TTU_FAST;              /* Terminal screen-update mode FAST */
1359 extern int updmode;
1360 #ifndef KUI
1361 int tt_status[VNUM] = {1,1,0,0};        /* Terminal status line displayed */
1362 int tt_status_usr[VNUM] = {1,1,0,0};
1363 #else  /* KUI */
1364 extern CKFLOAT floatval;
1365 CKFLOAT tt_linespacing[VNUM] = {1.0,1.0,1.0,1.0};
1366 #ifdef K95G
1367 int tt_status[VNUM] = {1,1,0,0};        /* Terminal status line displayed */
1368 int tt_status_usr[VNUM] = {1,1,0,0};
1369 #else /* K95G */
1370 int tt_status[VNUM] = {0,0,0,0};        /* Terminal status line displayed */
1371 int tt_status_usr[VNUM] = {0,0,0,0};
1372 #endif /* K95G */
1373 #endif /* KUI */
1374 int tt_senddata = 0;                    /* Let host read terminal data */
1375 extern int wy_blockend;                 /* Terminal Send Data EOB type */
1376 int tt_hidattr = 1;                     /* Attributes are hidden */
1377
1378 extern unsigned char colornormal, colorselect,
1379 colorunderline, colorstatus, colorhelp, colorborder,
1380 colorgraphic, colordebug, colorreverse, coloritalic;
1381
1382 extern int trueblink, trueunderline, truereverse, trueitalic, truedim;
1383
1384 extern int bgi, fgi;
1385 extern int scrninitialized[];
1386
1387 struct keytab audibletab[] = {          /* Terminal Bell Audible mode */
1388     { "beep",          XYB_BEEP, 0 },   /* Values ORd with bell mode */
1389     { "system-sounds", XYB_SYS,  0 }
1390 };
1391 int naudibletab = sizeof(audibletab)/sizeof(struct keytab);
1392
1393 struct keytab akmtab[] = {              /* Arrow key mode */
1394     { "application", TTK_APPL, 0 },
1395     { "cursor",      TTK_NORM, 0 }
1396 };
1397 struct keytab kpmtab[] = {              /* Keypad mode */
1398     { "application", TTK_APPL, 0 },
1399     { "numeric",     TTK_NORM, 0 }
1400 };
1401
1402 struct keytab ttcolmodetab[] = {
1403     { "current-color", 0, 0 },
1404     { "default-color", 1, 0 }
1405 };
1406 int ncolmode = sizeof(ttcolmodetab)/sizeof(struct keytab);
1407
1408 #define TTCOLNOR  0
1409 #define TTCOLREV  1
1410 #define TTCOLUND  2
1411 #define TTCOLSTA  3
1412 #define TTCOLHLP  4
1413 #define TTCOLBOR  5
1414 #define TTCOLSEL  6
1415 #define TTCOLDEB  7
1416 #define TTCOLGRP  8
1417 #define TTCOLITA  9
1418 #define TTCOLRES  10
1419 #define TTCOLERA  11
1420
1421 struct keytab ttycoltab[] = {                   /* Terminal Screen coloring */
1422     { "border",             TTCOLBOR, 0 },      /* Screen border color */
1423     { "debug-terminal",     TTCOLDEB, 0 },      /* Debug color */
1424     { "erase",              TTCOLERA, 0 },      /* Erase mode */
1425     { "graphic",            TTCOLGRP, 0 },      /* Graphic Color */
1426     { "help-text",          TTCOLHLP, 0 },      /* Help screens */
1427     { "italic",             TTCOLITA, 0 },      /* Italic Color */
1428     { "normal",             TTCOLNOR, CM_INV }, /* Normal screen text */
1429     { "reset-on-esc[0m",    TTCOLRES, 0 },      /* Reset on ESC [ 0 m */
1430     { "reverse-video",      TTCOLREV, 0 },      /* Reverse video */
1431     { "status-line",        TTCOLSTA, 0 },      /* Status line */
1432     { "selection",          TTCOLSEL, 0 },      /* Selection color */
1433     { "terminal-screen",    TTCOLNOR, 0 },      /* Better name than "normal" */
1434     { "underlined-text",    TTCOLUND, 0 }       /* Underlined text */
1435 };
1436 int ncolors = (sizeof(ttycoltab) / sizeof(struct keytab));
1437
1438 #define TTATTNOR  0
1439 #define TTATTBLI  1
1440 #define TTATTREV  2
1441 #define TTATTUND  3
1442 #define TTATTPRO  4
1443 #define TTATTBLD  5
1444 #define TTATTDIM  6
1445 #define TTATTINV  7
1446 #define TTATTITA  8
1447 #define TTATTDONE 9
1448
1449 struct keytab ttyattrtab[] = {
1450     { "blink",     TTATTBLI, 0 },
1451     { "dim",       TTATTDIM, 0 },
1452     { "italic",    TTATTITA, 0 },
1453     { "protected", TTATTPRO, 0 },
1454     { "reverse",   TTATTREV, 0 },
1455     { "underline", TTATTUND, 0 }
1456 };
1457 int nattrib = (sizeof(ttyattrtab) / sizeof(struct keytab));
1458
1459 struct keytab ttyprotab[] = {
1460     { "blink",       TTATTBLI,  0 },
1461     { "bold",        TTATTBLD,  0 },
1462     { "dim",         TTATTDIM,  0 },
1463     { "done",        TTATTDONE, CM_INV },
1464     { "invisible",   TTATTINV,  0 },
1465     { "italic",      TTATTITA,  0 },
1466     { "normal",      TTATTNOR,  0 },
1467     { "reverse",     TTATTREV,  0 },
1468     { "underlined",  TTATTUND,  0 }
1469
1470 };
1471 int nprotect = (sizeof(ttyprotab) / sizeof(struct keytab));
1472
1473 struct keytab ttyseobtab[] = {
1474     { "crlf_etx",  1, 0 },
1475     { "us_cr",     0, 0 }
1476 };
1477
1478 struct keytab ttyclrtab[] = {           /* Colors */
1479     { "black",         0, 0      },
1480     { "blue",          1, 0      },
1481     { "brown",         6, 0      },
1482     { "cyan",          3, 0      },
1483     { "darkgray",      8, CM_INV },
1484     { "dgray",         8, 0      },
1485     { "green",         2, 0      },
1486     { "lblue",         9, CM_INV },
1487     { "lcyan",        11, CM_INV },
1488     { "lgray",         7, CM_INV },
1489     { "lgreen",       10, CM_INV },
1490     { "lightblue",     9, 0      },
1491     { "lightcyan",    11, 0      },
1492     { "lightgray",     7, 0      },
1493     { "lightgreen",   10, 0      },
1494     { "lightmagenta", 13, 0      },
1495     { "lightred",     12, 0      },
1496     { "lmagenta",     13, CM_INV },
1497     { "lred",         12, CM_INV },
1498     { "magenta",       5, 0      },
1499     { "red",           4, 0      },
1500     { "white",        15, 0      },
1501     { "yellow",       14, 0      }
1502 };
1503 int nclrs = (sizeof (ttyclrtab) / sizeof (struct keytab));
1504
1505 struct keytab ttycurtab[] = {
1506     { "full",        TTC_BLOCK, 0 },
1507     { "half",        TTC_HALF,  0 },
1508     { "underline",   TTC_ULINE, 0 }
1509 };
1510 int ncursors = 3;
1511
1512 struct keytab ttyptab[] = {
1513     { "aaa",      TT_AAA,     CM_INV },     /* AnnArbor */
1514     { "adm3a",    TT_ADM3A,   0 },          /* LSI ADM-3A */
1515     { "adm5",     TT_ADM5,    0 },          /* LSI ADM-5 */
1516     { "aixterm",  TT_AIXTERM, 0 },          /* IBM AIXterm */
1517     { "annarbor", TT_AAA,     0 },          /* AnnArbor */
1518     { "ansi-bbs", TT_ANSI,    0 },          /* ANSI.SYS (BBS) */
1519     { "at386",    TT_AT386,   0 },          /* Unixware ANSI */
1520     { "avatar/0+",TT_ANSI,    0 },          /* AVATAR/0+ */
1521     { "ba80",     TT_BA80,    0 },          /* Nixdorf BA80 */
1522     { "be",       TT_BEOS,    CM_INV|CM_ABR },
1523     { "beos-ansi",TT_BEOS,    CM_INV },     /* BeOS ANSI */
1524     { "beterm",   TT_BEOS,    0 },          /* BeOS Terminal (as of PR2 ) */
1525     { "d200",     TT_DG200,   CM_INV|CM_ABR }, /* Data General DASHER 200 */
1526     { "d210",     TT_DG210,   CM_INV|CM_ABR }, /* Data General DASHER 210 */
1527     { "d217",     TT_DG217,   CM_INV|CM_ABR }, /* Data General DASHER 217 */
1528     { "dg200",    TT_DG200,   0 },          /* Data General DASHER 200 */
1529     { "dg210",    TT_DG210,   0 },          /* Data General DASHER 210 */
1530     { "dg217",    TT_DG217,   0 },          /* Data General DASHER 217 */
1531     { "h1500",    TT_HZL1500, CM_INV },     /* Hazeltine 1500 */
1532     { "h19",      TT_H19,     CM_INV },     /* Heath-19 */
1533     { "heath19",  TT_H19,     0 },          /* Heath-19 */
1534     { "hft",      TT_HFT,     0 },          /* IBM High Function Terminal */
1535     { "hp2621a",  TT_HP2621,  0 },          /* HP 2621A */
1536     { "hpterm",   TT_HPTERM,  0 },          /* HP TERM */
1537     { "hz1500",   TT_HZL1500, 0 },          /* Hazeltine 1500 */
1538     { "ibm3151",  TT_IBM31,   0 },          /* IBM 3101-xx,3161 */
1539     { "linux",    TT_LINUX,   0 },          /* Linux */
1540     { "qansi",    TT_QANSI,   0 },          /* QNX ANSI */
1541     { "qnx",      TT_QNX,     0 },          /* QNX Console */
1542     { "scoansi",  TT_SCOANSI, 0 },          /* SCO ANSI */
1543     { "sni-97801",TT_97801,   0 },          /* SNI 97801 */
1544     { "sun",      TT_SUN,     0 },          /* SUN Console */
1545 /*
1546   The idea of NONE is to let the console driver handle the escape sequences,
1547   which, in theory at least, would give not only ANSI emulation, but also any
1548   other kind of emulation that might be provided by alternative console
1549   drivers, if any existed.
1550
1551   For this to work, ckocon.c would need to be modified to make higher-level
1552   calls, like VioWrtTTY(), DosWrite(), or (simply) write(), rather than
1553   VioWrt*Cell() and similar, and it would also have to give up its rollback
1554   feature, and its status line and help screens would also have to be
1555   forgotten or else done in an ANSI way.
1556
1557   As matters stand, we already have perfectly good ANSI emulation built in,
1558   and there are no alternative console drivers available, so there is no point
1559   in having a terminal type of NONE, so it is commented out.  However, should
1560   you uncomment it, it will work like a "glass tty" -- no escape sequence
1561   interpretation at all; somewhat similar to debug mode, except without the
1562   debugging (no highlighting of control chars or escape sequences); help
1563   screens, status line, and rollback will still work.
1564 */
1565 #ifdef OS2PM
1566 #ifdef COMMENT
1567     { "tek4014", TT_TEK40,  0 },
1568 #endif /* COMMENT */
1569 #endif /* OS2PM */
1570     { "tty",     TT_NONE,   0 },
1571     { "tvi910+", TT_TVI910, 0 },
1572     { "tvi925",  TT_TVI925, 0 },
1573     { "tvi950",  TT_TVI950, 0 },
1574     { "vc404",   TT_VC4404, 0 },
1575     { "vc4404",  TT_VC4404, CM_INV },
1576     { "vip7809", TT_VIP7809,0 },
1577     { "vt100",   TT_VT100,  0 },
1578     { "vt102",   TT_VT102,  0 },
1579     { "vt220",   TT_VT220,  0 },
1580     { "vt220pc", TT_VT220PC,0 },
1581     { "vt320",   TT_VT320,  0 },
1582     { "vt320pc", TT_VT320PC,0 },
1583     { "vt52",    TT_VT52,   0 },
1584 #ifdef NT
1585     { "vtnt",    TT_VTNT,   0 },
1586 #else /* NT */
1587     { "vtnt",    TT_VTNT,  CM_INV },
1588 #endif /* NT */
1589     { "wy160",   TT_WY160,  0 },
1590     { "wy30",    TT_WY30,   0 },
1591     { "wy370",   TT_WY370,  0 },
1592     { "wy50",    TT_WY50,   0 },
1593     { "wy60",    TT_WY60,   0 },
1594     { "wyse30",  TT_WY30,   CM_INV },
1595     { "wyse370", TT_WY370,  CM_INV },
1596     { "wyse50",  TT_WY50,   CM_INV },
1597     { "wyse60",  TT_WY60,   CM_INV }
1598 };
1599 int nttyp = (sizeof(ttyptab) / sizeof(struct keytab));
1600
1601 struct keytab ttkeytab[] = {
1602     { "aaa",       TT_AAA,        CM_INV },        /* AnnArbor */
1603     { "adm3a",     TT_ADM3A,      0 },             /* LSI ADM-3A */
1604     { "adm5",      TT_ADM5,       0 },             /* LSI ADM-5 */
1605     { "aixterm",   TT_AIXTERM,    0 },             /* IBM AIXterm */
1606     { "annarbor",  TT_AAA,        0 },             /* AnnArbor */
1607     { "ansi-bbs",  TT_ANSI,       0 },             /* ANSI.SYS (BBS) */
1608     { "at386",     TT_AT386,      0 },             /* Unixware ANSI */
1609     { "avatar/0+", TT_ANSI,       0 },             /* AVATAR/0+ */
1610     { "ba80",      TT_BA80,       0 },             /* Nixdorf BA80 */
1611     { "be",        TT_BEOS,       CM_INV|CM_ABR },
1612     { "beos-ansi", TT_BEOS,       CM_INV },        /* BeOS ANSI */
1613     { "beterm",    TT_BEOS,       0 },             /* BeOS Terminal (DR2) */
1614     { "d200",      TT_DG200,      CM_INV|CM_ABR }, /* DG DASHER 200 */
1615     { "d210",      TT_DG210,      CM_INV|CM_ABR }, /* DG DASHER 210 */
1616     { "d217",      TT_DG217,      CM_INV|CM_ABR }, /* DG DASHER 217 */
1617     { "dg200",     TT_DG200,      0 },             /* DG DASHER 200 */
1618     { "dg210",     TT_DG210,      0 },             /* DG DASHER 210 */
1619     { "dg217",     TT_DG217,      0 },             /* DG DASHER 217 */
1620     { "emacs",     TT_KBM_EMACS,  0 },             /* Emacs mode */
1621     { "h19",       TT_H19,        CM_INV },        /* Heath-19 */
1622     { "heath19",   TT_H19,        0 },             /* Heath-19 */
1623     { "hebrew",    TT_KBM_HEBREW, 0 },             /* Hebrew mode */
1624     { "hft",       TT_HFT,        0 },             /* IBM High Function Term */
1625     { "hp2621a",   TT_HP2621,     0 },             /* HP 2621A */
1626     { "hpterm",    TT_HPTERM,     0 },             /* HP TERM */
1627     { "hz1500",    TT_HZL1500,    0 },             /* Hazeltine 1500 */
1628     { "ibm3151",   TT_IBM31,      0 },             /* IBM 3101-xx,3161 */
1629     { "linux",     TT_LINUX,      0 },             /* Linux */
1630     { "qansi",     TT_QANSI,      0 },             /* QNX ANSI */
1631     { "qnx",       TT_QNX,        0 },             /* QNX */
1632     { "russian",   TT_KBM_RUSSIAN,0 },             /* Russian mode */
1633     { "scoansi",   TT_SCOANSI,    0 },             /* SCO ANSI */
1634     { "sni-97801", TT_97801,      0 },             /* SNI 97801 */
1635     { "sun",       TT_SUN,        0 },             /* SUN Console */
1636 #ifdef OS2PM
1637 #ifdef COMMENT
1638     { "tek4014",   TT_TEK40,      0 },
1639 #endif /* COMMENT */
1640 #endif /* OS2PM */
1641     { "tty",       TT_NONE,       0 },
1642     { "tvi910+",   TT_TVI910,     0 },
1643     { "tvi925",    TT_TVI925,     0 },
1644     { "tvi950",    TT_TVI950,     0 },
1645     { "vc404",     TT_VC4404,     0 },
1646     { "vc4404",    TT_VC4404,     CM_INV },
1647     { "vip7809",   TT_VIP7809,    0 },
1648     { "vt100",     TT_VT100,      0 },
1649     { "vt102",     TT_VT102,      0 },
1650     { "vt220",     TT_VT220,      0 },
1651     { "vt220pc",   TT_VT220PC,    0 },
1652     { "vt320",     TT_VT320,      0 },
1653     { "vt320pc",   TT_VT320PC,    0 },
1654     { "vt52",      TT_VT52,       0 },
1655     { "vtnt",      TT_VTNT,       CM_INV },
1656     { "wp",        TT_KBM_WP,     0 },             /* Word Perfect mode */
1657     { "wy160",     TT_WY160,      0 },
1658     { "wy30",      TT_WY30,       0 },
1659     { "wy370",     TT_WY370,      0 },
1660     { "wy50",      TT_WY50,       0 },
1661     { "wy60",      TT_WY60,       0 },
1662     { "wyse30",    TT_WY30,       CM_INV },
1663     { "wyse370",   TT_WY370,      CM_INV },
1664     { "wyse50",    TT_WY50,       CM_INV },
1665     { "wyse60",    TT_WY60,       CM_INV }
1666 };
1667 int nttkey = (sizeof(ttkeytab) / sizeof(struct keytab));
1668
1669 #ifndef NOSETKEY
1670 struct keytab kbmodtab[] = {
1671     { "emacs",   KBM_EM, 0      },
1672     { "english", KBM_EN, CM_INV },
1673     { "hebrew",  KBM_HE, 0      },
1674     { "normal",  KBM_EN, 0      },
1675     { "none",    KBM_EN, CM_INV },
1676     { "russian", KBM_RU, 0      },
1677     { "wp",      KBM_WP, 0      }
1678 };
1679 int nkbmodtab = (sizeof(kbmodtab) / sizeof(struct keytab));
1680 #endif /* NOSETKEY */
1681 #endif /* NOLOCAL */
1682
1683 int tt_inpacing = 0;                    /* input-pacing (none) */
1684
1685 struct keytab prtytab[] = { /* OS/2 Priority Levels */
1686     { "foreground-server", XYP_SRV, 0       },
1687     { "idle",              XYP_IDLE, CM_INV },
1688     { "regular",           XYP_REG, 0       },
1689     { "time-critical",     XYP_RTP, 0       }
1690 };
1691 int nprty = (sizeof(prtytab) / sizeof(struct keytab));
1692 #endif /* OS2 */
1693
1694 #ifdef NT
1695 struct keytab win95tab[] = { /* Win95 work-arounds */
1696     { "8.3-filenames",         XYW8_3,    0 },
1697     { "alt-gr",                XYWAGR,    0 },
1698     { "horizontal-scan-line-substitutions", XYWHSL, 0 },
1699     { "keyboard-translation",  XYWKEY,    0 },
1700     { "lucida-substitutions",  XYWLUC,    0 },
1701     { "overlapped-io",         XYWOIO,    0 },
1702     { "popups",                XYWPOPUP,  0 },
1703     { "select-bug",            XYWSELECT, 0 }
1704 };
1705 int nwin95 = (sizeof(win95tab) / sizeof(struct keytab));
1706 #endif /* NT */
1707
1708 #ifdef OS2MOUSE
1709 extern int wideresult;
1710 int tt_mouse = 1;                       /* Terminal mouse on/off */
1711
1712 struct keytab mousetab[] = {            /* Mouse items */
1713     { "activate", XYM_ON,     0 },
1714     { "button",   XYM_BUTTON, 0 },
1715     { "clear",    XYM_CLEAR,  0 },
1716     { "debug",    XYM_DEBUG,  0 }
1717 };
1718 int nmtab = (sizeof(mousetab)/sizeof(struct keytab));
1719
1720 struct keytab mousebuttontab[] = {      /* event button */
1721     { "1",             XYM_B1, 0 },
1722     { "2",             XYM_B2, 0 },
1723     { "3",             XYM_B3, 0 },
1724     { "one",           XYM_B1, CM_INV },
1725     { "three",         XYM_B3, CM_INV },
1726     { "two",           XYM_B2, CM_INV }
1727 };
1728 int nmbtab = (sizeof(mousebuttontab) / sizeof(struct keytab));
1729
1730 struct keytab mousemodtab[] = {         /* event button key modifier */
1731     { "alt",              XYM_ALT,   0 },
1732     { "alt-shift",        XYM_SHIFT|XYM_ALT, 0 },
1733     { "ctrl",             XYM_CTRL,  0 },
1734     { "ctrl-alt",         XYM_CTRL|XYM_ALT, 0 },
1735     { "ctrl-alt-shift",   XYM_CTRL|XYM_SHIFT|XYM_ALT, 0 },
1736     { "ctrl-shift",       XYM_CTRL|XYM_SHIFT, 0 },
1737     { "none",             0, 0 },
1738     { "shift",            XYM_SHIFT, 0 }
1739 };
1740 int nmmtab = (sizeof(mousemodtab) / sizeof(struct keytab));
1741
1742 struct keytab mclicktab[] = {           /* event button click modifier */
1743     { "click",        XYM_C1,   0 },
1744     { "drag",         XYM_DRAG, 0 },
1745     { "double-click", XYM_C2,   0 }
1746 };
1747 int nmctab = (sizeof(mclicktab) / sizeof(struct keytab));
1748
1749 #ifndef NOKVERBS
1750 extern int nkverbs;
1751 extern struct keytab kverbs[];
1752 #endif /* NOKVERBS */
1753 #endif /* OS2MOUSE */
1754
1755 /* #ifdef VMS */
1756 struct keytab fbtab[] = {               /* Binary record types for VMS */
1757     { "fixed",     XYFT_B, 0 },         /* Fixed is normal for binary */
1758     { "undefined", XYFT_U, 0 }          /* Undefined if they ask for it */
1759 };
1760 int nfbtyp = (sizeof(fbtab) / sizeof(struct keytab));
1761 /* #endif */
1762
1763 #ifdef VMS
1764 struct keytab lbltab[] = {              /* Labeled File info */
1765     { "acl",         LBL_ACL, 0 },
1766     { "backup-date", LBL_BCK, 0 },
1767     { "name",        LBL_NAM, 0 },
1768     { "owner",       LBL_OWN, 0 },
1769     { "path",        LBL_PTH, 0 }
1770 };
1771 int nlblp = (sizeof(lbltab) / sizeof(struct keytab));
1772 #else
1773 #ifdef OS2
1774 struct keytab lbltab[] = {              /* Labeled File info */
1775     { "archive",   LBL_ARC, 0 },
1776     { "extended",  LBL_EXT, 0 },
1777     { "hidden",    LBL_HID, 0 },
1778     { "read-only", LBL_RO,  0 },
1779     { "system",    LBL_SYS, 0 }
1780 };
1781 int nlblp = (sizeof(lbltab) / sizeof(struct keytab));
1782 #endif /* OS2 */
1783 #endif /* VMS */
1784
1785 #ifdef CK_CURSES
1786 #ifdef CK_PCT_BAR
1787 static struct keytab fdftab[] = {       /* SET FILE DISPLAY FULL options */
1788     { "thermometer",    1, 0, },
1789     { "no-thermometer", 0, 0  }
1790 };
1791 extern int thermometer;
1792 #endif /* CK_PCT_BAR */
1793 #endif /* CK_CURSES */
1794
1795 static struct keytab fdtab[] = {        /* SET FILE DISPLAY options */
1796 #ifdef MAC                              /* Macintosh */
1797     { "fullscreen", XYFD_R,      0 },   /* Full-screen but not curses */
1798     { "none",       XYFD_N,      0 },
1799     { "off",        XYFD_N, CM_INV },
1800     { "on",         XYFD_R, CM_INV },
1801     { "quiet",      XYFD_N, CM_INV },
1802 #else                                   /* Not Mac */
1803     { "brief", XYFD_B, 0 },             /* Brief */
1804     { "crt", XYFD_S, 0 },               /* CRT display */
1805 #ifdef CK_CURSES
1806 #ifdef COMMENT
1807     { "curses",     XYFD_C,  CM_INV },  /* Full-screen, curses */
1808 #endif /* COMMENT */
1809     { "fullscreen", XYFD_C,  0 },       /* Full-screen, whatever the method */
1810 #endif /* CK_CURSES */
1811 #ifdef KUI
1812     { "gui",    XYFD_G, 0 },            /* GUI */
1813 #endif /* KUI */        
1814     { "none",   XYFD_N, 0      },       /* No display */
1815     { "off",    XYFD_N, CM_INV },       /* Ditto */
1816     { "on",     XYFD_R, CM_INV },       /* On = Serial */
1817     { "quiet",  XYFD_N, CM_INV },       /* No display */
1818     { "serial", XYFD_R, 0      },       /* Serial */
1819 #endif /* MAC */
1820     { "", 0, 0 }
1821 };
1822 int nfdtab = (sizeof(fdtab) / sizeof(struct keytab)) - 1;
1823
1824 struct keytab rsrtab[] = {              /* For REMOTE SET RECEIVE */
1825     { "packet-length", XYLEN,  0 },
1826     { "timeout",       XYTIMO, 0 }
1827 };
1828 int nrsrtab = (sizeof(rsrtab) / sizeof(struct keytab));
1829
1830 /* Send/Receive Parameters */
1831
1832 struct keytab srtab[] = {
1833     { "backup", XYBUP, 0 },
1834 #ifndef NOCSETS
1835     { "character-set-selection", XYCSET, 0 },
1836 #endif /* NOCSETS */
1837     { "control-prefix", XYQCTL, 0 },
1838 #ifdef CKXXCHAR
1839     { "double-character", XYDBL, 0 },
1840 #endif /* CKXXCHAR */
1841     { "end-of-packet", XYEOL, 0 },
1842 #ifdef PIPESEND
1843     { "filter", XYFLTR, 0 },
1844 #endif /* PIPESEND */
1845 #ifdef CKXXCHAR
1846     { "ignore-character", XYIGN, 0 },
1847 #endif /* CKXXCHAR */
1848     { "i-packets", 993, 0 },
1849     { "move-to", XYMOVE, 0 },
1850     { "negotiation-string-max-length", XYINIL, CM_INV },
1851     { "packet-length", XYLEN, 0 },
1852     { "pad-character", XYPADC, 0 },
1853     { "padding", XYNPAD, 0 },
1854     { "pathnames", XYFPATH, 0 },
1855     { "pause", XYPAUS, 0 },
1856 #ifdef CK_PERMS
1857     { "permissions", 994, 0},           /* 206 */
1858 #endif /* CK_PERMS */
1859     { "quote", XYQCTL, CM_INV },        /* = CONTROL-PREFIX */
1860     { "rename-to", XYRENAME, 0 },
1861     { "start-of-packet", XYMARK, 0 },
1862     { "timeout", XYTIMO, 0 },
1863 #ifdef VMS
1864     { "version-numbers", 887, 0 },      /* VMS version numbers */
1865 #endif /* VMS */
1866     { "", 0, 0 }
1867 };
1868 int nsrtab = (sizeof(srtab) / sizeof(struct keytab)) - 1;
1869
1870 #ifdef UNICODE
1871 #define UCS_BOM 1
1872 #define UCS_BYT 2
1873 static struct keytab ucstab[] = {
1874     { "bom",        UCS_BOM, 0 },
1875     { "byte-order", UCS_BYT, 0 },
1876     { "", 0, 0 }
1877 };
1878 int nucstab = (sizeof(ucstab) / sizeof(struct keytab)) - 1;
1879
1880 static struct keytab botab[] = {
1881     { "big-endian",    0, 0 },
1882     { "little-endian", 1, 0 }
1883 };
1884 static int nbotab = 2;
1885 #endif /* UNICODE */
1886
1887 /* REMOTE SET */
1888
1889 struct keytab rmstab[] = {
1890     { "attributes",  XYATTR, 0      },
1891     { "block-check", XYCHKT, 0      },
1892     { "file",        XYFILE, 0      },
1893     { "incomplete",  XYIFD,  CM_INV },  /* = REMOTE SET FILE INCOMPLETE */
1894     { "match",       XYMATCH,0      },
1895     { "receive",     XYRECV, 0      },
1896     { "retry",       XYRETR, 0      },
1897     { "server",      XYSERV, 0      },
1898     { "transfer",    XYXFER, 0      },
1899     { "window",      XYWIND, 0      },
1900     { "xfer",        XYXFER, CM_INV }
1901 };
1902 int nrms = (sizeof(rmstab) / sizeof(struct keytab));
1903
1904 struct keytab attrtab[] = {
1905 #ifdef STRATUS
1906     { "account",       AT_ACCT, 0 },
1907 #endif /* STRATUS */
1908     { "all",           AT_XALL, 0 },
1909 #ifdef COMMENT
1910     { "blocksize",     AT_BLKS, 0 },    /* (not used) */
1911 #endif /* COMMENT */
1912 #ifndef NOCSETS
1913     { "character-set", AT_ENCO, 0 },
1914 #endif /* NOCSETS */
1915 #ifdef STRATUS
1916     { "creator",       AT_CREA, 0 },
1917 #endif /* STRATUS */
1918     { "date",          AT_DATE, 0 },
1919     { "disposition",   AT_DISP, 0 },
1920     { "encoding",      AT_ENCO, CM_INV },
1921     { "format",        AT_RECF, CM_INV },
1922     { "length",        AT_LENK, 0 },
1923     { "off",           AT_ALLN, 0 },
1924     { "on",            AT_ALLY, 0 },
1925 #ifdef COMMENT
1926     { "os-specific",   AT_SYSP, 0 },    /* (not used by UNIX or VMS) */
1927 #endif /* COMMENT */
1928 #ifdef CK_PERMS
1929     { "protection",    AT_LPRO, 0 },
1930     { "permissions",   AT_LPRO, CM_INV },
1931 #endif /* CK_PERMS */
1932     { "record-format", AT_RECF, 0 },
1933     { "system-id",     AT_SYSI, 0 },
1934     { "type",          AT_FTYP, 0 }
1935 };
1936 int natr = (sizeof(attrtab) / sizeof(struct keytab)); /* how many attributes */
1937
1938 #ifdef CKTIDLE
1939 struct keytab idlacts[] = {
1940     { "exit",       IDLE_EXIT, 0 },
1941     { "hangup",     IDLE_HANG, 0 },
1942     { "output",     IDLE_OUT,  0 },
1943     { "return",     IDLE_RET,  0 },
1944 #ifdef TNCODE
1945     { "telnet-nop", IDLE_TNOP, 0 },
1946     { "telnet-ayt", IDLE_TAYT, 0 },
1947 #endif /* TNCODE */
1948     { "", 0, 0 }
1949 };
1950 int nidlacts = (sizeof(idlacts) / sizeof(struct keytab)) - 1;
1951 #endif /* CKTIDLE */
1952
1953 #ifndef NOSPL
1954 extern int indef, inecho, insilence, inbufsize, inautodl, inintr;
1955 #ifdef CKFLOAT
1956 extern CKFLOAT inscale;
1957 #endif  /* CKFLOAT */
1958 extern char * inpbuf, * inpbp;
1959 #ifdef OS2
1960 extern int interm;
1961 #endif /* OS2 */
1962 struct keytab inptab[] = {              /* SET INPUT parameters */
1963 #ifdef CK_AUTODL
1964     { "autodownload",    IN_ADL, 0 },
1965 #endif /* CK_AUTODL */
1966     { "buffer-length",   IN_BUF, 0 },
1967     { "cancellation",    IN_CAN, 0 },
1968     { "case",            IN_CAS, 0 },
1969     { "default-timeout", IN_DEF, CM_INV }, /* There is no default timeout */
1970     { "echo",            IN_ECH, 0 },
1971 #ifdef OS2
1972     { "pacing",          IN_PAC, CM_INV },
1973 #endif /* OS2 */
1974     { "scale-factor",    IN_SCA, 0 },
1975     { "silence",         IN_SIL, 0 },
1976 #ifdef OS2
1977     { "terminal",        IN_TRM, 0 },
1978 #endif /* OS2 */
1979     { "timeout-action",  IN_TIM, 0 }
1980 };
1981 int ninp = (sizeof(inptab) / sizeof(struct keytab));
1982
1983 struct keytab intimt[] = {              /* SET INPUT TIMEOUT parameters */
1984     { "proceed", 0, 0 },                /* 0 = proceed */
1985     { "quit",    1, 0 }                 /* 1 = quit */
1986 };
1987
1988 struct keytab incast[] = {              /* SET INPUT CASE parameters */
1989     { "ignore",  0, 0 },                /* 0 = ignore */
1990     { "observe", 1, 0 }                 /* 1 = observe */
1991 };
1992 #endif /* NOSPL */
1993
1994 struct keytab nabltab[] = {             /* For any command that needs */
1995     { "disabled", 0, 0 },
1996     { "enabled",  1, 0 },
1997     { "off",      0, CM_INV },          /* these keywords... */
1998     { "on",       1, CM_INV }
1999 };
2000 int nnabltab = sizeof(nabltab) / sizeof(struct keytab);
2001
2002 #ifdef OS2
2003 struct keytab tvctab[] = {              /* SET TERM VIDEO-CHANGE */
2004     { "disabled",     TVC_DIS, 0 },
2005     { "enabled",      TVC_ENA, 0 },
2006 #ifdef NT
2007     { "win95-safe",   TVC_W95, 0 },
2008 #endif /* NT */
2009     { "", 0, 0 }
2010 };
2011 int ntvctab = (sizeof(tvctab) / sizeof(struct keytab)) - 1;
2012
2013 struct keytab msktab[] = { /* SET MS-DOS KERMIT compatibilities */
2014 #ifdef COMMENT
2015     { "color",    MSK_COLOR,  0 },
2016 #endif /* COMMENT */
2017     { "file-renaming", MSK_REN, 0 },
2018     { "keycodes", MSK_KEYS,   0 }
2019 };
2020 int nmsk = (sizeof(msktab) / sizeof(struct keytab));
2021
2022 struct keytab scrnupd[] = {             /* SET TERMINAL SCREEN-UPDATE */
2023     { "fast",   TTU_FAST,   0 },
2024     { "smooth", TTU_SMOOTH, 0 }
2025 };
2026 int nscrnupd = (sizeof(scrnupd) / sizeof(struct keytab));
2027
2028 #ifdef PCFONTS
2029 /* This definition of the term_font[] table is only for     */
2030 /* the OS/2 Full Screen Session and is not used on Windows */
2031 struct keytab term_font[] = {           /* SET TERMINAL FONT */
2032 #ifdef COMMENT
2033     { "cp111", TTF_111, 0 },
2034     { "cp112", TTF_112, 0 },
2035     { "cp113", TTF_113, 0 },
2036 #endif /* COMMENT */
2037     { "cp437", TTF_437, 0 },
2038     { "cp850", TTF_850, 0 },
2039 #ifdef COMMENT
2040     { "cp851", TTF_851, 0 },
2041 #endif /* COMMENT */
2042     { "cp852", TTF_852, 0 },
2043 #ifdef COMMENT
2044     { "cp853", TTF_853, 0 },
2045     { "cp860", TTF_860, 0 },
2046     { "cp861", TTF_861, 0 },
2047 #endif /* COMMENT */
2048     { "cp862", TTF_862, 0 },
2049 #ifdef COMMENT
2050     { "cp863", TTF_863, 0 },
2051     { "cp864", TTF_864, 0 },
2052     { "cp865", TTF_865, 0 },
2053 #endif /* COMMENT */
2054     { "cp866", TTF_866, 0 },
2055 #ifdef COMMENT
2056     { "cp880", TTF_880, 0 },
2057     { "cp881", TTF_881, 0 },
2058     { "cp882", TTF_882, 0 },
2059     { "cp883", TTF_883, 0 },
2060     { "cp884", TTF_884, 0 },
2061     { "cp885", TTF_885, 0 },
2062 #endif /* COMMENT */
2063     { "default",TTF_ROM,0 }
2064 };
2065 int ntermfont = (sizeof(term_font) / sizeof(struct keytab));
2066 int tt_font = TTF_ROM;                  /* Terminal screen font */
2067 #else /* PCFONTS */
2068 #ifdef NT
2069 #ifdef KUI
2070 struct keytab * term_font = NULL;
2071 struct keytab * _term_font = NULL;
2072 char * tt_facename = NULL;
2073 int ntermfont = 0;
2074 int tt_font = 0;
2075 int tt_font_size = 0;
2076 #endif /* KUI */
2077 #endif /* NT */
2078 #endif /* PCFONTS */
2079
2080 struct keytab anbktab[] = {             /* For any command that needs */
2081     { "message", 2, 0 },                /* these keywords... */
2082     { "off",     0, 0 },
2083     { "on",      1, 0 },
2084     { "unsafe-messag0", 99, CM_INV },
2085     { "unsafe-message", 3,  CM_INV }
2086 };
2087 int nansbk = (sizeof(anbktab) / sizeof(struct keytab));
2088
2089 int win95_popup = 1;
2090 #ifdef NT
2091 #ifdef KUI
2092 int win95lucida = 0;
2093 int win95hsl = 1;
2094 #else /* KUI */
2095 int win95lucida = 1;
2096 int win95hsl = 1;
2097 #endif /* KUI */
2098 #else /* NT */
2099 int win95lucida = 0;
2100 int win95hsl = 1;
2101 #endif /* NT */
2102 #ifdef NT
2103 int win95altgr  = 0;
2104 extern int win95selectbug;
2105 extern int win95_8_3;
2106
2107 #ifdef COMMENT
2108 extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR);
2109 extern struct keytab tcstab[];
2110 extern int ntcs;
2111 #endif /* COMMENT */
2112 extern int maxow, maxow_usr; owwait;    /* Overlapped I/O variables */
2113 #endif /* NT */
2114 #endif /* OS2 */
2115
2116
2117 /* The following routines broken out of doprm() to give compilers a break. */
2118
2119 /*  S E T O N  --  Parse on/off (default on), set parameter to result  */
2120
2121 int
2122 seton(prm) int *prm; {
2123     int x, y;
2124     if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
2125     if ((x = cmcfm()) < 0) return(x);
2126     *prm = y;
2127     return(1);
2128 }
2129
2130 /*  S E T O N A U T O --  Parse on/off/auto (default auto) & set result */
2131
2132 struct keytab onoffaut[] = {
2133     { "auto", SET_AUTO, 0 },            /* 2 */
2134     { "off",  SET_OFF,  0 },            /* 0 */
2135     { "on",   SET_ON,   0 }             /* 1 */
2136 };
2137
2138 int
2139 setonaut(prm) int *prm; {
2140     int x, y;
2141     if ((y = cmkey(onoffaut,3,"","auto",xxstring)) < 0) return(y);
2142     if ((x = cmcfm()) < 0) return(x);
2143     *prm = y;
2144     return(1);
2145 }
2146
2147 /*  S E T N U M  --  Set parameter to result of cmnum() parse.  */
2148 /*
2149  Call with pointer to integer variable to be set,
2150    x = number from cnum parse, y = return code from cmnum,
2151    max = maximum value to accept, -1 if no maximum.
2152  Returns -9 on failure, after printing a message, or 1 on success.
2153 */
2154 int
2155 setnum(prm,x,y,max) int x, y, *prm, max; {
2156     debug(F101,"setnum","",y);
2157     if (y == -3) {
2158         printf("\n?Value required\n");
2159         return(-9);
2160     }
2161     if (y == -2) {
2162         printf("%s?Not a number: %s\n",cmflgs == 1 ? "" : "\n", atxbuf);
2163         return(-9);
2164     }
2165     if (y < 0) return(y);
2166     if (max > -1 && x > max) {
2167         printf("?Sorry, %d is the maximum\n",max);
2168         return(-9);
2169     }
2170     if ((y = cmcfm()) < 0) return(y);
2171     *prm = x;
2172     return(1);
2173 }
2174
2175 /*  S E T C C  --  Set parameter var to an ASCII control character value.  */
2176 /*
2177   Parses a number, or a literal control character, or a caret (^) followed
2178   by an ASCII character whose value is 63-95 or 97-122, then gets confirmation,
2179   then sets the parameter to the code value of the character given.  If there
2180   are any parse errors, they are returned, otherwise on success 1 is returned.
2181 */
2182 int
2183 setcc(dflt,var) char *dflt; int *var; {
2184     int x, y;
2185     unsigned int c;
2186     char *hlpmsg = "Control character,\n\
2187  numeric ASCII value,\n\
2188  or in ^X notation,\n\
2189  or preceded by a backslash and entered literally";
2190
2191     /* This is a hack to turn off complaints from expression evaluator. */
2192     x_ifnum = 1;
2193     y = cmnum(hlpmsg, dflt, 10, &x, xxstring); /* Parse a number */
2194     x_ifnum = 0;                               /* Allow complaints again */
2195     if (y < 0) {                        /* Parse failed */
2196         if (y != -2)                    /* Reparse needed or somesuch */
2197           return(y);                    /* Pass failure back up the chain */
2198     }
2199     /* Real control character or literal 8-bit character... */
2200
2201     for (c = strlen(atmbuf) - 1; c > 0; c--) /* Trim */
2202       if (atmbuf[c] == SP) atmbuf[c] = NUL;
2203
2204     if (y < 0) {                        /* It was not a number */
2205         if (((c = atmbuf[0])) && !atmbuf[1]) { /* Literal character? */
2206             c &= 0xff;
2207             if (((c > 31) && (c < 127)) || (c > 255)) {
2208                 printf("\n?%d: Out of range - must be 0-31 or 127-255\n",c);
2209                 return(-9);
2210             } else {
2211                 if ((y = cmcfm()) < 0)  /* Confirm */
2212                   return(y);
2213                 *var = c;               /* Set the variable */
2214                 return(1);
2215             }
2216         } else if (atmbuf[0] == '^' && !atmbuf[2]) { /* Or ^X notation? */
2217             c = atmbuf[1];
2218             if (islower((char) c))      /* Uppercase lowercase letters */
2219               c = toupper(c);
2220             if (c > 62 && c < 96) {     /* Check range */
2221                 if ((y = cmcfm()) < 0)
2222                   return(y);
2223                 *var = ctl(c);          /* OK */
2224                 return(1);
2225             } else {
2226                 printf("?Not a control character - %s\n", atmbuf);
2227                 return(-9);
2228             }
2229         } else {                        /* Something illegal was typed */
2230             printf("?Invalid - %s\n", atmbuf);
2231             return(-9);
2232         }
2233     }
2234     if (((x > 31) && (x < 127)) || (x > 255)) { /* They typed a number */
2235         printf("\n?%d: Out of range - must be 0-31 or 127-255\n",x);
2236         return(-9);
2237     }
2238     if ((y = cmcfm()) < 0)              /* In range, confirm */
2239       return(y);
2240     *var = x;                           /* Set variable */
2241     return(1);
2242 }
2243
2244 #ifndef NOSPL                           /* The SORT command... */
2245
2246 static struct keytab srtswtab[] = {     /* SORT command switches */
2247     { "/case",    SRT_CAS, CM_ARG },
2248     { "/key",     SRT_KEY, CM_ARG },
2249     { "/numeric", SRT_NUM, 0 },
2250     { "/range",   SRT_RNG, CM_ARG },
2251     { "/reverse", SRT_REV, 0 }
2252 };
2253 static int nsrtswtab = sizeof(srtswtab)/sizeof(struct keytab);
2254
2255 extern char **a_ptr[];                  /* Array pointers */
2256 extern int a_dim[];                     /* Array dimensions */
2257
2258 int
2259 dosort() {                              /* Do the SORT command */
2260     char c, *p = NULL, ** ap, ** xp = NULL;
2261     struct FDB sw, fl, cm;
2262     int hi, lo;
2263     int xn = 0, xr = -1, xk = -1, xc = -1, xs = 0;
2264     int getval = 0, range[2], confirmed = 0;
2265
2266     cmfdbi(&sw,                         /* First FDB - command switches */
2267            _CMKEY,                      /* fcode */
2268            "Array name or switch",
2269            "",                          /* default */
2270            "",                          /* addtl string data */
2271            nsrtswtab,                   /* addtl numeric data 1: tbl size */
2272            4,                           /* addtl numeric data 2: 4 = cmswi */
2273            NULL,                        /* Processing function */
2274            srtswtab,                    /* Keyword table */
2275            &fl                          /* Pointer to next FDB */
2276            );
2277     cmfdbi(&fl,                         /* Anything that doesn't match */
2278            _CMFLD,                      /* fcode */
2279            "Array name",                /* hlpmsg */
2280            "",                          /* default */
2281            "",                          /* addtl string data */
2282            0,                           /* addtl numeric data 1 */
2283            0,                           /* addtl numeric data 2 */
2284            NULL,
2285            NULL,
2286            &cm
2287            );
2288     cmfdbi(&cm,                         /* Or premature confirmation */
2289            _CMCFM,                      /* fcode */
2290            "",                          /* hlpmsg */
2291            "",                          /* default */
2292            "",                          /* addtl string data */
2293            0,                           /* addtl numeric data 1 */
2294            0,                           /* addtl numeric data 2 */
2295            NULL,
2296            NULL,
2297            NULL
2298            );
2299
2300     range[0] = -1;
2301     range[1] = -1;
2302
2303     while (1) {                         /* Parse 0 or more switches */
2304         x = cmfdb(&sw);
2305         if (x < 0)
2306           return(x);
2307         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
2308           break;
2309         c = cmgbrk();
2310         getval = (c == ':' || c == '=');
2311         if (getval && !(cmresult.kflags & CM_ARG)) {
2312             printf("?This switch does not take arguments\n");
2313             return(-9);
2314         }
2315         switch (cmresult.nresult) {
2316           case SRT_REV:
2317             xr = 1;
2318             break;
2319           case SRT_KEY:
2320             if (getval) {
2321                 if ((y = cmnum("Column for comparison (1-based)",
2322                                "1",10,&x,xxstring)) < 0)
2323                   return(y);
2324                 xk = x - 1;
2325             } else
2326               xk = 0;
2327             break;
2328           case SRT_CAS:
2329             if (getval) {
2330                 if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
2331                   return(y);
2332                 xc = y;
2333             } else
2334               xc = 1;
2335             break;
2336           case SRT_RNG:                 /* /RANGE */
2337             if (getval) {
2338                 char buf[32];
2339                 char buf2[16];
2340                 int i;
2341                 char * p, * q;
2342                 if ((y = cmfld("low:high element","1",&s,NULL)) < 0)
2343                   return(y);
2344                 s = brstrip(s);
2345                 ckstrncpy(buf,s,32);
2346                 p = buf;
2347                 for (i = 0; *p && i < 2; i++) { /* Get low and high */
2348                     q = p;              /* Start of this piece */
2349                     while (*p) {        /* Find end of this piece */
2350                         if (*p == ':') {
2351                             *p = NUL;
2352                             p++;
2353                             break;
2354                         }
2355                         p++;
2356                     }
2357                     y = 15;             /* Evaluate this piece */
2358                     s = buf2;
2359                     zzstring(q,&s,&y);
2360                     s = evalx(buf2);
2361                     if (s) if (*s) ckstrncpy(buf2,s,16);
2362                     if (!rdigits(buf2)) {
2363                         printf("?Not numeric: %s\n",buf2);
2364                         return(-9);
2365                     }
2366                     range[i] = atoi(buf2);
2367                 }
2368             }
2369             break;
2370           case SRT_NUM:                 /* /NUMERIC */
2371             xn = 1;
2372             break;
2373           default:
2374             return(-2);
2375         }
2376     }
2377     switch (cmresult.fcode) {
2378       case _CMCFM:
2379         confirmed = 1;
2380         break;
2381       case _CMFLD:
2382         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Safe copy of name */
2383         s = line;
2384         break;
2385       default:
2386         printf("?Unexpected function code: %d\n",cmresult.fcode);
2387         return(-9);
2388     }
2389     if (confirmed) {
2390         printf("?Array name required\n");
2391         return(-9);
2392     }
2393     ckmakmsg(tmpbuf,TMPBUFSIZ,
2394              "Second array to sort according to ",s,NULL,NULL);
2395     if ((x = cmfld(tmpbuf,"",&p,NULL)) < 0)
2396       if (x != -3)
2397         return(x);
2398     tmpbuf[0] = NUL;
2399     ckstrncpy(tmpbuf,p,TMPBUFSIZ);
2400     p = tmpbuf;
2401     if ((x = cmcfm()) < 0)              /* Get confirmation */
2402       return(x);
2403
2404     x = arraybounds(s,&lo,&hi);         /* Get array index & bounds */
2405     if (x < 0) {                        /* Check */
2406         printf("?Bad array name: %s\n",s);
2407         return(-9);
2408     }
2409     if (lo > -1) range[0] = lo;         /* Set range */
2410     if (hi > -1) range[1] = hi;
2411     ap = a_ptr[x];                      /* Get pointer to array element list */
2412     if (!ap) {                          /* Check */
2413         printf("?Array not declared: %s\n", s);
2414         return(-9);
2415     }
2416     if (range[0] < 0)                   /* Starting element */
2417       range[0] = 1;
2418     if (range[1] < 0)                   /* Final element */
2419       range[1] = a_dim[x];
2420     if (range[1] > a_dim[x]) {
2421         printf("?range %d:%d exceeds array dimension %d\n",
2422                range[0],range[1],a_dim[x]
2423                );
2424         return(-9);
2425     }
2426     ap += range[0];
2427     xs = range[1] - range[0] + 1;       /* Number of elements to sort */
2428     if (xs < 1) {                       /* Check */
2429         printf("?Bad range: %d:%d\n",range[0],range[1]);
2430         return(-9);
2431     }
2432     if (xk < 0) xk = 0;                 /* Key position */
2433     if (xr < 0) xr = 0;                 /* Reverse flag */
2434     if (xn)                             /* Numeric flag */
2435       xc = 2;
2436     else if (xc < 0)                    /* Not numeric */
2437       xc = inpcas[cmdlvl];              /* so alpha case option */
2438
2439     if (*p) {                           /* Parallel array given? */
2440         y = xarray(p);                  /* Yes, get its index. */
2441         if (y < 0) {
2442             printf("?Bad array name: %s\n", p);
2443             return(-9);
2444         }
2445         if (y != x) {                   /* If the 2 arrays are different  */
2446             xp = a_ptr[y];              /* Pointer to 2nd array element list */
2447             if (!xp) {
2448                 printf("?Array not declared: %s\n", p);
2449                 return(-9);
2450             }
2451             if (a_dim[y] < range[1]) {
2452                 printf("?Array %s smaller than %s\n", p, s);
2453                 return(-9);
2454             }
2455             xp += range[0];             /* Set base to same as 1st array */
2456         }
2457     }
2458     sh_sort(ap,xp,xs,xk,xr,xc);         /* Sort the array(s) */
2459     return(success = 1);                /* Always succeeds */
2460 }
2461 #endif /* NOSPL */
2462
2463 static struct keytab purgtab[] = {      /* PURGE command switches */
2464     { "/after",        PU_AFT,  CM_ARG },
2465     { "/ask",          PU_ASK,  0 },
2466     { "/before",       PU_BEF,  CM_ARG },
2467     { "/delete",       PU_DELE, CM_INV },
2468 #ifdef UNIXOROSK
2469     { "/dotfiles",     PU_DOT,  0 },
2470 #endif /* UNIXOROSK */
2471     { "/except",       PU_EXC,  CM_ARG },
2472     { "/heading",      PU_HDG,  0 },
2473     { "/keep",         PU_KEEP, CM_ARG },
2474     { "/larger-than",  PU_LAR,  CM_ARG },
2475     { "/list",         PU_LIST, 0 },
2476     { "/log",          PU_LIST, CM_INV },
2477     { "/noask",        PU_NASK, 0 },
2478     { "/nodelete",     PU_NODE, CM_INV },
2479 #ifdef UNIXOROSK
2480     { "/nodotfiles",   PU_NODOT,0 },
2481 #endif /* UNIXOROSK */
2482     { "/noheading",    PU_NOH,  0 },
2483     { "/nol",          PU_NOLI, CM_INV|CM_ABR },
2484     { "/nolist",       PU_NOLI, 0 },
2485     { "/nolog",        PU_NOLI, CM_INV },
2486 #ifdef CK_TTGWSIZ
2487     { "/nopage",       PU_NOPA, 0 },
2488 #endif /* CK_TTGWSIZ */
2489     { "/not-after",    PU_NAF,  CM_ARG },
2490     { "/not-before",   PU_NBF,  CM_ARG },
2491     { "/not-since",    PU_NAF,  CM_INV|CM_ARG },
2492 #ifdef CK_TTGWSIZ
2493     { "/page",         PU_PAGE, 0 },
2494 #endif /* CK_TTGWSIZ */
2495     { "/quiet",        PU_QUIE, CM_INV },
2496 #ifdef RECURSIVE
2497     { "/recursive",    PU_RECU, 0 },
2498 #endif /* RECURSIVE */
2499     { "/since",        PU_AFT,  CM_ARG|CM_INV },
2500     { "/simulate",     PU_NODE, 0 },
2501     { "/smaller-than", PU_SMA,  CM_ARG },
2502     { "/verbose",      PU_VERB, CM_INV }
2503 };
2504 static int npurgtab = sizeof(purgtab)/sizeof(struct keytab);
2505
2506
2507
2508
2509
2510 int
2511 bkupnum(s,i) char * s; int *i; {
2512     int k = 0, pos = 0;
2513     char * p = NULL, *q;
2514     *i = pos;
2515     if (!s) s = "";
2516     if (!*s)
2517       return(-1);
2518     if ((k = strlen(s)) < 5)
2519       return(-1);
2520
2521     if (s[k-1] != '~')
2522       return(-1);
2523     pos = k - 2;
2524     q = s + pos;
2525     while (q >= s && isdigit(*q)) {
2526         p = q--;
2527         pos--;
2528     }
2529     if (!p)
2530       return(-1);
2531     if (q < s+2)
2532       return(-1);
2533     if (*q != '~' || *(q-1) != '.')
2534       return(-1);
2535     pos--;
2536     *i = pos;
2537     debug(F111,"bkupnum",s+pos,pos);
2538     return(atoi(p));
2539 }
2540
2541 #ifdef CKPURGE
2542 /* Presently only for UNIX because we need direct access to the file array. */
2543 /* Not needed for VMS anyway, because we don't make backup files there. */
2544
2545 #define MAXKEEP 32                      /* Biggest /KEEP: value */
2546
2547 static int
2548   pu_keep = 0, pu_list = 0, pu_dot = 0, pu_ask = 0, pu_hdg = 0;
2549
2550 #ifdef CK_TTGWSIZ
2551 static int pu_page = -1;
2552 #else
2553 static int pu_page = 0;
2554 #endif /* CK_TTGWSIZ */
2555
2556 #ifndef NOSHOW
2557 VOID
2558 showpurgopts() {                        /* SHOW PURGE command options */
2559     int x = 0;
2560     extern int optlines;
2561     prtopt(&optlines,"PURGE");
2562     if (pu_ask > -1) {
2563         x++;
2564         prtopt(&optlines, pu_ask ? "/ASK" : "/NOASK");
2565     }
2566 #ifdef UNIXOROSK
2567     if (pu_dot > -1) {
2568         x++;
2569         prtopt(&optlines, pu_dot ? "/DOTFILES" : "/NODOTFILES");
2570     }
2571 #endif /* UNIXOROSK */
2572     if (pu_keep > -1) {
2573         x++;
2574         ckmakmsg(tmpbuf,TMPBUFSIZ,"/KEEP:",ckitoa(pu_keep),NULL,NULL);
2575         prtopt(&optlines,tmpbuf);
2576     }
2577     if (pu_list > -1) {
2578         x++;
2579         prtopt(&optlines, pu_list ? "/LIST" : "/NOLIST");
2580     }
2581     if (pu_hdg > -1) {
2582         x++;
2583         prtopt(&optlines, pu_hdg ? "/HEADING" : "/NOHEADING");
2584     }
2585 #ifdef CK_TTGWSIZ
2586     if (pu_page > -1) {
2587         x++;
2588         prtopt(&optlines, pu_page ? "/PAGE" : "/NOPAGE");
2589     }
2590 #endif /* CK_TTGWSIZ */
2591     if (!x) prtopt(&optlines,"(no options set)");
2592     prtopt(&optlines,"");
2593 }
2594 #endif /* NOSHOW */
2595
2596 int
2597 setpurgopts() {                         /* Set PURGE command options */
2598     int c, z, getval = 0;
2599     int
2600       x_keep  = -1, x_list = -1, x_page = -1,
2601       x_hdg   = -1, x_ask  = -1, x_dot  = -1;
2602
2603     while (1) {
2604         if ((y = cmswi(purgtab,npurgtab,"Switch","",xxstring)) < 0) {
2605             if (y == -3)
2606               break;
2607             else
2608               return(y);
2609         }
2610         c = cmgbrk();
2611         if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
2612             printf("?This switch does not take an argument\n");
2613             return(-9);
2614         }
2615         if (!getval && (cmgkwflgs() & CM_ARG)) {
2616             printf("?This switch requires an argument\n");
2617             return(-9);
2618         }
2619         switch (y) {
2620           case PU_KEEP:
2621             z = 1;
2622             if (c == ':' || c == '=')
2623               if ((y = cmnum("How many backup files to keep",
2624                              "1",10,&z,xxstring)) < 0)
2625                 return(y);
2626             if (z < 0 || z > MAXKEEP) {
2627                 printf("?Please specify a number between 0 and %d\n",
2628                        MAXKEEP
2629                        );
2630                 return(-9);
2631             }
2632             x_keep = z;
2633             break;
2634           case PU_LIST:
2635           case PU_VERB:
2636             x_list = 1;
2637             break;
2638           case PU_QUIE:
2639           case PU_NOLI:
2640             x_list = 0;
2641             break;
2642 #ifdef CK_TTGWSIZ
2643           case PU_PAGE:
2644             x_page = 1;
2645             break;
2646           case PU_NOPA:
2647             x_page = 0;
2648             break;
2649 #endif /* CK_TTGWSIZ */
2650           case PU_HDG:
2651             x_hdg = 1;
2652             break;
2653           case PU_NOH:
2654             x_hdg = 0;
2655             break;
2656           case PU_ASK:
2657             x_ask = 1;
2658             break;
2659           case PU_NASK:
2660             x_ask = 0;
2661             break;
2662 #ifdef UNIXOROSK
2663           case PU_DOT:
2664             x_dot = 1;
2665             break;
2666           case PU_NODOT:
2667             x_dot = 0;
2668             break;
2669 #endif /* UNIXOROSK */
2670           default:
2671             printf("?This option can not be set\n");
2672             return(-9);
2673         }
2674     }
2675     if ((x = cmcfm()) < 0)              /* Get confirmation */
2676       return(x);
2677     if (x_keep > -1)                    /* Set PURGE defaults. */
2678       pu_keep = x_keep;
2679     if (x_list > -1)
2680       pu_list = x_list;
2681 #ifdef CK_TTGWSIZ
2682     if (x_page > -1)
2683       pu_page = x_page;
2684 #endif /* CK_TTGWSIZ */
2685     if (x_hdg > -1)
2686       pu_hdg = x_hdg;
2687     if (x_ask > -1)
2688       pu_ask = x_ask;
2689     if (x_dot > -1)
2690       pu_dot = x_dot;
2691     return(success = 1);
2692 }
2693
2694 int
2695 dopurge() {                             /* Do the PURGE command */
2696     extern char ** mtchs;
2697     extern int xaskmore, cmd_rows, recursive;
2698     int simulate = 0, asking = 0;
2699     int listing = 0, paging = -1, lines = 0, deleting = 1, errors = 0;
2700     struct FDB sw, sf, cm;
2701     int g, i, j, k, m = 0, n, x, y, z, done = 0, count = 0, flags = 0;
2702     int tokeep = 0, getval = 0, havename = 0, confirmed = 0;
2703     int xx[MAXKEEP+1];                  /* Array of numbers to keep */
2704     int min = -1;
2705     int x_hdg = 0, fs = 0, rc = 0;
2706     CK_OFF_T minsize = -1L, maxsize = -1L;
2707     char namebuf[CKMAXPATH+4];
2708     char basebuf[CKMAXPATH+4];
2709     char
2710       * pu_aft = NULL,
2711       * pu_bef = NULL,
2712       * pu_naf = NULL,
2713       * pu_nbf = NULL,
2714       * pu_exc = NULL;
2715     char * pxlist[8];                   /* Exception list */
2716
2717     if (pu_keep > -1)                   /* Set PURGE defaults. */
2718       tokeep = pu_keep;
2719     if (pu_list > -1)
2720       listing = pu_list;
2721 #ifdef CK_TTGWSIZ
2722     if (pu_page > -1)
2723       paging = pu_page;
2724 #endif /* CK_TTGWSIZ */
2725
2726     for (i = 0; i <= MAXKEEP; i++)      /* Clear this number buffer */
2727       xx[i] = 0;
2728     for (i = 0; i < 8; i++)             /* Initialize these... */
2729       pxlist[i] = NULL;
2730
2731     g_matchdot = matchdot;              /* Save these... */
2732
2733     cmfdbi(&sw,                         /* 1st FDB - PURGE switches */
2734            _CMKEY,                      /* fcode */
2735            "Filename or switch",        /* hlpmsg */
2736            "",                          /* default */
2737            "",                          /* addtl string data */
2738            npurgtab,                    /* addtl numeric data 1: tbl size */
2739            4,                           /* addtl numeric data 2: 4 = cmswi */
2740            xxstring,                    /* Processing function */
2741            purgtab,                     /* Keyword table */
2742            &sf                          /* Pointer to next FDB */
2743            );
2744     cmfdbi(&sf,                         /* 2nd FDB - filespec to purge */
2745            _CMIFI,                      /* fcode */
2746            "",
2747            "",                          /* default */
2748            "",                          /* addtl string data */
2749            0,                           /* addtl numeric data 1 */
2750            0,                           /* addtl numeric data 2 */
2751            xxstring,
2752            NULL,
2753            &cm
2754            );
2755     cmfdbi(&cm,                         /* Or premature confirmation */
2756            _CMCFM,                      /* fcode */
2757            "",                          /* hlpmsg */
2758            "",                          /* default */
2759            "",                          /* addtl string data */
2760            0,                           /* addtl numeric data 1 */
2761            0,                           /* addtl numeric data 2 */
2762            NULL,
2763            NULL,
2764            NULL
2765            );
2766
2767     while (!havename && !confirmed) {
2768         x = cmfdb(&sw);                 /* Parse something */
2769         if (x < 0) {                    /* Error */
2770             rc = x;
2771             goto xpurge;
2772         } else if (cmresult.fcode == _CMKEY) {
2773             char c;
2774             c = cmgbrk();
2775             if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
2776                 printf("?This switch does not take an argument\n");
2777                 rc = -9;
2778                 goto xpurge;
2779             }
2780             if (!getval && (cmgkwflgs() & CM_ARG)) {
2781                 printf("?This switch requires an argument\n");
2782                 rc = -9;
2783                 goto xpurge;
2784             }
2785             switch (k = cmresult.nresult) {
2786               case PU_KEEP:
2787                 z = 1;
2788                 if (c == ':' || c == '=') {
2789                     if ((y = cmnum("How many backup files to keep",
2790                                    "1",10,&z,xxstring)) < 0) {
2791                         rc = y;
2792                         goto xpurge;
2793                     }
2794                 }
2795                 if (z < 0 || z > MAXKEEP) {
2796                     printf("?Please specify a number between 0 and %d\n",
2797                            MAXKEEP
2798                            );
2799                     rc = -9;
2800                     goto xpurge;
2801                 }
2802                 tokeep = z;
2803                 break;
2804               case PU_LIST:
2805                 listing = 1;
2806                 break;
2807               case PU_NOLI:
2808                 listing = 0;
2809                 break;
2810 #ifdef CK_TTGWSIZ
2811               case PU_PAGE:
2812                 paging = 1;
2813                 break;
2814               case PU_NOPA:
2815                 paging = 0;
2816                 break;
2817 #endif /* CK_TTGWSIZ */
2818               case PU_DELE:
2819                 deleting = 1;
2820                 break;
2821               case PU_NODE:
2822                 deleting = 0;
2823                 simulate = 1;
2824                 listing = 1;
2825                 break;
2826               case PU_ASK:
2827                 asking = 1;
2828                 break;
2829               case PU_NASK:
2830                 asking = 0;
2831                 break;
2832               case PU_AFT:
2833               case PU_BEF:
2834               case PU_NAF:
2835               case PU_NBF:
2836                 if ((x = cmdate("File-time","",&s,0,xxstring)) < 0) {
2837                     if (x == -3) {
2838                         printf("?Date-time required\n");
2839                         rc = -9;
2840                     } else
2841                       rc = x;
2842                     goto xpurge;
2843                 }
2844                 fs++;
2845                 switch (k) {
2846                   case PU_AFT: makestr(&pu_aft,s); break;
2847                   case PU_BEF: makestr(&pu_bef,s); break;
2848                   case PU_NAF: makestr(&pu_naf,s); break;
2849                   case PU_NBF: makestr(&pu_nbf,s); break;
2850                 }
2851                 break;
2852               case PU_SMA:
2853               case PU_LAR:
2854                 if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0) {
2855                     rc = x;
2856                     goto xpurge;
2857                 }
2858                 fs++;
2859                 switch (cmresult.nresult) {
2860                   case PU_SMA: minsize = y; break;
2861                   case PU_LAR: maxsize = y; break;
2862                 }
2863                 break;
2864               case PU_DOT:
2865                 matchdot = 1;
2866                 break;
2867               case PU_NODOT:
2868                 matchdot = 0;
2869                 break;
2870               case PU_EXC:
2871                 if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
2872                     if (x == -3) {
2873                         printf("?Pattern required\n");
2874                         rc = -9;
2875                     } else
2876                       rc = x;
2877                     goto xpurge;
2878                 }
2879                 fs++;
2880                 makestr(&pu_exc,s);
2881                 break;
2882               case PU_HDG:
2883                 x_hdg = 1;
2884                 break;
2885 #ifdef RECURSIVE
2886               case PU_RECU:             /* /RECURSIVE */
2887                 recursive = 2;
2888                 break;
2889 #endif /* RECURSIVE */
2890               default:
2891                 printf("?Not implemented yet - \"%s\"\n",atmbuf);
2892                 rc = -9;
2893                 goto xpurge;
2894             }
2895         } else if (cmresult.fcode == _CMIFI) {
2896             havename = 1;
2897         } else if (cmresult.fcode == _CMCFM) {
2898             confirmed = 1;
2899         } else {
2900             rc = -2;
2901             goto xpurge;
2902         }
2903     }
2904     if (havename) {
2905 #ifdef CKREGEX
2906         ckmakmsg(line,LINBUFSIZ,cmresult.sresult,".~[1-9]*~",NULL,NULL);
2907 #else
2908         ckmakmsg(line,LINBUFSIZ,cmresult.sresult,".~*~",NULL,NULL);
2909 #endif /* CKREGEX */
2910     } else {
2911 #ifdef CKREGEX
2912         ckstrncpy(line,"*.~[1-9]*~",LINBUFSIZ);
2913 #else
2914         ckstrncpy(line,"*.~*~",LINBUFSIZ);
2915 #endif /* CKREGEX */
2916     }
2917     if (!confirmed) {
2918         if ((x = cmcfm()) < 0) {
2919             rc = x;
2920             goto xpurge;
2921         }
2922     }
2923     /* Parse finished - now action */
2924
2925 #ifdef CK_LOGIN
2926     if (isguest) {
2927         printf("?File deletion by guests not permitted.\n");
2928         rc = -9;
2929         goto xpurge;
2930     }
2931 #endif /* CK_LOGIN */
2932
2933 #ifdef CK_TTGWSIZ
2934     if (paging < 0)                     /* /[NO]PAGE not given */
2935       paging = xaskmore;                /* so use prevailing */
2936 #endif /* CK_TTGWSIZ */
2937
2938     lines = 0;
2939     if (x_hdg > 0) {
2940         printf("Purging %s, keeping %d...%s\n",
2941                s,
2942                tokeep,
2943                simulate ? " (SIMULATION)" : "");
2944         lines += 2;
2945     }
2946     flags = ZX_FILONLY;
2947     if (recursive) flags |= ZX_RECURSE;
2948     n = nzxpand(line,flags);            /* Get list of backup files */
2949     if (tokeep < 1) {                   /* Deleting all of them... */
2950         for (i = 0; i < n; i++) {
2951             if (fs) if (fileselect(mtchs[i],
2952                                    pu_aft,pu_bef,pu_naf,pu_nbf,
2953                                    minsize,maxsize,0,8,pxlist) < 1) {
2954                 if (listing > 0) {
2955                     printf(" %s (SKIPPED)\n",mtchs[i]);
2956 #ifdef CK_TTGWSIZ
2957                     if (paging)
2958                       if (++lines > cmd_rows - 3) {
2959                           if (!askmore()) goto xpurge; else lines = 0;
2960                       }
2961 #endif /* CK_TTGWSIZ */
2962                 }
2963                 continue;
2964             }
2965             if (asking) {
2966                 int x;
2967                 ckmakmsg(tmpbuf,TMPBUFSIZ," Delete ",mtchs[i],"?",NULL);
2968                 x = getyesno(tmpbuf,1);
2969                 switch (x) {
2970                   case 0: continue;
2971                   case 1: break;
2972                   case 2: goto xpurge;
2973                 }
2974             }
2975             x = deleting ? zdelet(mtchs[i]) : 0;
2976             if (x > -1) {
2977                 if (listing)
2978                   printf(" %s (%s)\n", mtchs[i],deleting ? "OK" : "SELECTED");
2979                 count++;
2980             } else {
2981                 errors++;
2982                 if (listing)
2983                   printf(" %s (FAILED)\n", mtchs[i]);
2984             }
2985 #ifdef CK_TTGWSIZ
2986             if (listing && paging)
2987               if (++lines > cmd_rows - 3) {
2988                   if (!askmore()) goto xpurge; else lines = 0;
2989               }
2990 #endif /* CK_TTGWSIZ */
2991         }
2992         goto xpurge;
2993     }
2994     if (n < tokeep) {                   /* Not deleting any */
2995         count = 0;
2996         if (listing)
2997           printf(" Matches = %d: Not enough to purge.\n",n);
2998         goto xpurge;
2999     }
3000
3001     /* General case - delete some but not others */
3002
3003     sh_sort(mtchs,NULL,n,0,0,filecase); /* Alphabetize the list (ESSENTIAL) */
3004
3005     g = 0;                              /* Start of current group */
3006     for (i = 0; i < n; i++) {           /* Go thru sorted file list */
3007         x = znext(namebuf);             /* Get next file */
3008         if (x < 1 || !namebuf[0] || i == n - 1) /* No more? */
3009           done = 1;                     /* NOTE: 'done' must be 0 or 1 only */
3010         if (fs) if (fileselect(namebuf,
3011                                pu_aft,pu_bef,pu_naf,pu_nbf,
3012                                minsize,maxsize,0,8,pxlist) < 1) {
3013             if (listing > 0) {
3014                 printf(" %s (SKIPPED)\n",namebuf);
3015                 if (++lines > cmd_rows - 3)
3016                   if (!askmore()) goto xpurge; else lines = 0;
3017             }
3018             continue;
3019         }
3020         if (x > 0)
3021           if ((m = bkupnum(namebuf,&z)) < 0) /* This file's backup number. */
3022             continue;
3023         for (j = 0; j < tokeep; j++) {  /* Insert in list. */
3024             if (m > xx[j]) {
3025                 for (k = tokeep - 1; k > j; k--)
3026                   xx[k] = xx[k-1];
3027                 xx[j] = m;
3028                 break;
3029             }
3030         }
3031         /* New group? */
3032         if (done || (i > 0 && ckstrcmp(namebuf,basebuf,z,1))) {
3033             if (i + done - g > tokeep) { /* Do we have enough to purge? */
3034                 min = xx[tokeep-1];     /* Yes, lowest backup number to keep */
3035                 debug(F111,"dopurge group",basebuf,min);
3036                 for (j = g; j < i + done; j++) { /* Go through this group */
3037                     x = bkupnum(mtchs[j],&z);    /* Get file backup number */
3038                     if (x > 0 && x < min) {      /* Below minimum? */
3039                         x = deleting ? zdelet(mtchs[j]) : 0;
3040                         if (x < 0) errors++;
3041                         if (listing)
3042                           printf(" %s (%s)\n",
3043                                  mtchs[j],
3044                                  ((x < 0) ? "ERROR" :
3045                                   (deleting ? "DELETED" : "SELECTED"))
3046                                  );
3047                         count++;
3048                     } else if (listing) /* Not below minimum - keep this one */
3049                       printf(" %s (KEPT)\n",mtchs[j]);
3050 #ifdef CK_TTGWSIZ
3051                     if (listing && paging)
3052                       if (++lines > cmd_rows - 3) {
3053                           if (!askmore()) goto xpurge; else lines = 0;
3054                       }
3055 #endif /* CK_TTGWSIZ */
3056                 }
3057             } else if (listing && paging) { /* Not enough to purge */
3058                 printf(" %s.~*~ (KEPT)\n",basebuf);
3059 #ifdef CK_TTGWSIZ
3060                 if (++lines > cmd_rows - 3) {
3061                     if (!askmore()) goto xpurge; else lines = 0;
3062                 }
3063 #endif /* CK_TTGWSIZ */
3064             }
3065             for (j = 0; j < tokeep; j++) /* Clear the backup number list */
3066               xx[j] = 0;
3067             g = i;                      /* Reset the group pointer */
3068         }
3069         if (done)                       /* No more files, done. */
3070           break;
3071         strncpy(basebuf,namebuf,z);     /* Set basename of this file */
3072         basebuf[z] = NUL;
3073     }
3074   xpurge:                               /* Common exit point */
3075     if (g_matchdot > -1) {
3076         matchdot = g_matchdot;          /* Restore these... */
3077         g_matchdot = -1;
3078     }
3079     if (rc < 0) return(rc);             /* Parse error */
3080     if (x_hdg)
3081       printf("Files purged: %d%s\n",
3082              count,
3083              deleting ? "" : " (not really)"
3084              );
3085     return(success = count > 0 ? 1 : (errors > 0) ? 0 : 1);
3086 }
3087 #endif /* CKPURGE */
3088
3089 #ifndef NOXFER
3090 #ifndef NOLOCAL
3091 int
3092 doxdis(which) int which; {              /* 1 = Kermit, 2 = FTP */
3093     extern int nolocal;
3094     int x, y = 0, z;
3095 #ifdef NEWFTP
3096     extern int ftp_dis;
3097 #endif /* NEWFTP */
3098
3099 #ifdef COMMENT
3100     char *s;
3101 #endif /* COMMENT */
3102
3103     if ((x = cmkey(fdtab,nfdtab,"file transfer display style","",
3104                    xxstring)) < 0)
3105       return(x);
3106 #ifdef CK_PCT_BAR
3107     if ((y = cmkey(fdftab,2,"","thermometer",xxstring)) < 0)
3108       return(y);
3109 #endif /* CK_PCT_BAR */
3110     if ((z = cmcfm()) < 0) return(z);
3111 #ifdef CK_CURSES
3112     if (x == XYFD_C) {                  /* FULLSCREEN */
3113 #ifdef COMMENT
3114 #ifndef MYCURSES
3115         extern char * trmbuf;           /* Real curses */
3116         int z;
3117 #endif /* MYCURSES */
3118 #endif /* COMMENT */
3119
3120         if (nolocal)                    /* Nothing to do in this case */
3121           return(success = 1);
3122
3123 #ifdef COMMENT
3124 #ifndef MYCURSES
3125 #ifndef VMS
3126         s = getenv("TERM");
3127         debug(F110,"doxdis TERM",s,0);
3128         if (!s) s = "";
3129         fxdinit(x);
3130         if (*s && trmbuf) {             /* Don't call tgetent */
3131             z = tgetent(trmbuf,s);      /* if trmbuf not allocated */
3132             debug(F111,"doxdis tgetent",s,z);
3133         } else {
3134             z = 0;
3135             debug(F110,"doxdis tgetent skipped",s,0);
3136         }
3137         if (z < 1) {
3138             printf("Sorry, terminal type unknown: \"%s\"\n",s);
3139             return(success = 0);
3140         }
3141 #endif /* VMS */
3142 #endif /* MYCURSES */
3143 #else
3144         fxdinit(x);
3145 #endif /* COMMENT */
3146
3147 #ifdef CK_PCT_BAR
3148         thermometer = y;
3149 #endif /* CK_PCT_BAR */
3150
3151         line[0] = '\0';                 /* (What's this for?) */
3152     }
3153 #endif /* CK_CURSES */
3154     if (which == 1)                     /* It's OK. */
3155       fdispla = x;
3156 #ifdef NEWFTP
3157     else if (which == 2)
3158       ftp_dis = x;
3159 #endif /* NEWFTP */
3160     return(success = 1);
3161 }
3162 #endif /* NOLOCAL */
3163 #endif /* NOXFER */
3164
3165 int
3166 setfil(rmsflg) int rmsflg; {
3167 #ifdef COMMENT
3168     extern int en_del;
3169 #endif /* COMMENT */
3170 #ifndef NOXFER
3171     if (rmsflg) {
3172         if ((y = cmkey(rfiltab,nrfilp,"Remote file parameter","",
3173                        xxstring)) < 0) {
3174             if (y == -3) {
3175                 printf("?Remote file parameter required\n");
3176                 return(-9);
3177             } else return(y);
3178         }
3179     } else {
3180 #endif /* NOXFER */
3181         if ((y = cmkey(filtab,nfilp,"File parameter","",xxstring)) < 0)
3182           return(y);
3183 #ifndef NOXFER
3184     }
3185 #endif /* NOXFER */
3186     switch (y) {
3187 #ifdef COMMENT                          /* Not needed */
3188       case XYFILB:                      /* Blocksize */
3189         if ((y = cmnum("file block size",ckitoa(DBLKSIZ),10,&z,xxstring)) < 0)
3190           return(y);
3191         if ((x = cmcfm()) < 0) return(x);
3192         if (rmsflg) {
3193             sstate = setgen('S', "311", ckitoa(z), "");
3194             return((int) sstate);
3195         } else {
3196             fblksiz = z;
3197             return(success = 1);
3198         }
3199 #endif /* COMMENT */
3200
3201 #ifndef NOXFER
3202       case XYFILS:                      /* Byte size */
3203         if ((y = cmnum("file byte size (7 or 8)","8",10,&z,xxstring)) < 0)
3204           return(y);
3205         if (z != 7 && z != 8) {
3206             printf("\n?The choices are 7 and 8\n");
3207             return(0);
3208         }
3209         if ((y = cmcfm()) < 0) return(y);
3210         if (z == 7) fmask = 0177;
3211         else if (z == 8) fmask = 0377;
3212         return(success = 1);
3213
3214 #ifndef NOCSETS
3215       case XYFILC: {                    /* Character set */
3216           char * csetname = NULL;
3217           extern int
3218             r_cset, s_cset, afcset[];   /* SEND CHARACTER-SET AUTO or MANUAL */
3219
3220           struct FDB kw, fl;
3221           cmfdbi(&kw,                   /* First FDB - command switches */
3222                  _CMKEY,                /* fcode */
3223                  rmsflg ? "server character-set name" : "",  /* help */
3224                  "",                    /* default */
3225                  "",                    /* addtl string data */
3226                  nfilc,                 /* addtl numeric data 1: tbl size */
3227                  0,                     /* addtl numeric data 2: 0 = keyword */
3228                  xxstring,              /* Processing function */
3229                  fcstab,                /* Keyword table */
3230                  rmsflg ? &fl : NULL    /* Pointer to next FDB */
3231            );
3232           cmfdbi(&fl,                   /* Anything that doesn't match */
3233                  _CMFLD,                /* fcode */
3234                  "",                    /* hlpmsg */
3235                  "",                    /* default */
3236                  "",                    /* addtl string data */
3237                  0,                     /* addtl numeric data 1 */
3238                  0,                     /* addtl numeric data 2 */
3239                  xxstring,
3240                  NULL,
3241                  NULL
3242                  );
3243           if ((x = cmfdb(&kw)) < 0)
3244             return(x);
3245           if (cmresult.fcode == _CMKEY) {
3246               x = cmresult.nresult;
3247               csetname = fcsinfo[x].keyword;
3248           } else {
3249               ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
3250               csetname = line;
3251           }
3252           if ((z = cmcfm()) < 0) return(z);
3253           if (rmsflg) {
3254               sstate = setgen('S', "320", csetname, "");
3255               return((int) sstate);
3256           }
3257           fcharset = x;
3258           if (s_cset == XMODE_A)        /* If SEND CHARACTER-SET is AUTO */
3259             if (x > -1 && x <= MAXFCSETS)
3260               if (afcset[x] > -1 && afcset[x] <= MAXTCSETS)
3261                 tcharset = afcset[x]; /* Pick corresponding xfer charset */
3262           setxlatype(tcharset,fcharset); /* Translation type */
3263           /* If I say SET FILE CHARACTER-SET blah, I want to be blah! */
3264           r_cset = XMODE_M;             /* Don't switch incoming set! */
3265           x = fcsinfo[fcharset].size;   /* Also set default x-bit charset */
3266           if (x == 128)                 /* 7-bit... */
3267             dcset7 = fcharset;
3268           else if (x == 256)            /* 8-bit... */
3269             dcset8 = fcharset;
3270           return(success = 1);
3271       }
3272 #endif /* NOCSETS */
3273
3274 #ifndef NOLOCAL
3275       case XYFILD:                      /* Display */
3276         return(doxdis(1));              /* 1 == kermit */
3277 #endif /* NOLOCAL */
3278 #endif /* NOXFER */
3279
3280       case XYFILA:                      /* End-of-line */
3281 #ifdef NLCHAR
3282         s = "";
3283         if (NLCHAR == 015)
3284           s = "cr";
3285         else if (NLCHAR == 012)
3286           s = "lf";
3287         if ((x = cmkey(eoltab, neoltab,
3288                        "local text-file line terminator",s,xxstring)) < 0)
3289           return(x);
3290 #else
3291         if ((x = cmkey(eoltab, neoltab,
3292                        "local text-file line terminator","crlf",xxstring)) < 0)
3293           return(x);
3294 #endif /* NLCHAR */
3295         if ((z = cmcfm()) < 0) return(z);
3296         feol = (CHAR) x;
3297         return(success = 1);
3298
3299 #ifndef NOXFER
3300       case XYFILN:                      /* Names */
3301         if ((x = cmkey(fntab,nfntab,"how to handle filenames","converted",
3302                        xxstring)) < 0)
3303           return(x);
3304         if ((z = cmcfm()) < 0) return(z);
3305         if (rmsflg) {
3306             sstate = setgen('S', "301", ckitoa(1 - x), "");
3307             return((int) sstate);
3308         } else {
3309             ptab[protocol].fncn = x;    /* Set structure */
3310             fncnv = x;                  /* Set variable */
3311             f_save = x;                 /* And set "permanent" variable */
3312             return(success = 1);
3313         }
3314
3315       case XYFILR:                      /* Record length */
3316         if ((y = cmnum("file record length",
3317                        ckitoa(DLRECL),10,&z,xxstring)) < 0)
3318           return(y);
3319         if ((x = cmcfm()) < 0) return(x);
3320         if (rmsflg) {
3321             sstate = setgen('S', "312", ckitoa(z), "");
3322             return((int) sstate);
3323         } else {
3324             frecl = z;
3325             return(success = 1);
3326         }
3327
3328 #ifdef COMMENT
3329       case XYFILO:                      /* Organization */
3330         if ((x = cmkey(forgtab,nforg,"file organization","sequential",
3331                        xxstring)) < 0)
3332           return(x);
3333         if ((y = cmcfm()) < 0) return(y);
3334         if (rmsflg) {
3335             sstate = setgen('S', "314", ckitoa(x), "");
3336             return((int) sstate);
3337         } else {
3338             forg = x;
3339             return(success = 1);
3340         }
3341 #endif /* COMMENT */
3342
3343 #ifdef COMMENT                          /* Not needed */
3344       case XYFILF:                      /* Format */
3345         if ((x = cmkey(frectab,nfrec,"file record format","stream",
3346                        xxstring)) < 0)
3347           return(x);
3348         if ((y = cmcfm()) < 0) return(y);
3349         if (rmsflg) {
3350             sstate = setgen('S', "313", ckitoa(x), "");
3351             return((int) sstate);
3352         } else {
3353             frecfm = x;
3354             return(success = 1);
3355         }
3356 #endif /* COMMENT */
3357
3358 #ifdef COMMENT
3359       case XYFILP:                      /* Printer carriage control */
3360         if ((x = cmkey(fcctab,nfcc,"file carriage control","newline",
3361                        xxstring)) < 0)
3362           return(x);
3363         if ((y = cmcfm()) < 0) return(y);
3364         if (rmsflg) {
3365             sstate = setgen('S', "315", ckitoa(x), "");
3366             return((int) sstate);
3367         } else {
3368             fcctrl = x;
3369             return(success = 1);
3370         }
3371 #endif /* COMMENT */
3372 #endif /* NOXFER */
3373
3374       case XYFILT:                      /* Type */
3375         if ((x = cmkey(rmsflg ? rfttab  : fttab,
3376                        rmsflg ? nrfttyp : nfttyp,
3377                        "type of file transfer","text",xxstring)) < 0)
3378           return(x);
3379
3380 #ifdef VMS
3381         /* Allow VMS users to choose record format for binary files */
3382         if ((x == XYFT_B) && (rmsflg == 0)) {
3383             if ((x = cmkey(fbtab,nfbtyp,"VMS record format","fixed",
3384                            xxstring)) < 0)
3385               return(x);
3386         }
3387 #endif /* VMS */
3388         if ((y = cmcfm()) < 0) return(y);
3389         binary = x;
3390         b_save = x;
3391 #ifdef MAC
3392         (void) mac_setfildflg(binary);
3393 #endif /* MAC */
3394 #ifndef NOXFER
3395         if (rmsflg) {
3396             /* Allow for LABELED in VMS & OS/2 */
3397             sstate = setgen('S', "300", ckitoa(x), "");
3398             return((int) sstate);
3399         } else {
3400 #endif /* NOXFER */
3401             return(success = 1);
3402 #ifndef NOXFER
3403         }
3404 #endif /* NOXFER */
3405
3406 #ifndef NOXFER
3407       case XYFILX:                      /* Collision Action */
3408         if ((x = cmkey(colxtab,ncolx,"Filename collision action","backup",
3409                        xxstring)) < 0)
3410           return(x);
3411         if ((y = cmcfm()) < 0) return(y);
3412 #ifdef CK_LOGIN
3413         if (isguest) {
3414             /* Don't let guests change existing files */
3415             printf("?This command not valid for guests\n");
3416             return(-9);
3417         }
3418 #endif /* CK_LOGIN */
3419 #ifdef COMMENT
3420         /* Not appropriate - DISABLE DELETE only refers to server */
3421         if ((x == XYFX_X || x == XYFX_B || x == XYFX_U || x == XYFX_A) &&
3422             (!ENABLED(en_del))) {
3423             printf("?Sorry, file deletion is disabled.\n");
3424             return(-9);
3425         }
3426 #endif /* COMMENT */
3427         fncact = x;
3428         ptab[protocol].fnca = x;
3429         if (rmsflg) {
3430             sstate = setgen('S', "302", ckitoa(fncact), "");
3431             return((int) sstate);
3432         } else {
3433             if (fncact == XYFX_R) ckwarn = 1; /* FILE WARNING implications */
3434             if (fncact == XYFX_X) ckwarn = 0; /* ... */
3435             return(success = 1);
3436         }
3437
3438       case XYFILW:                      /* Warning/Write-Protect */
3439         if ((x = seton(&ckwarn)) < 0) return(x);
3440         if (ckwarn)
3441           fncact = XYFX_R;
3442         else
3443           fncact = XYFX_X;
3444         return(success = 1);
3445
3446 #ifdef CK_LABELED
3447       case XYFILL:                      /* LABELED FILE parameters */
3448         if ((x = cmkey(lbltab,nlblp,"Labeled file feature","",
3449                        xxstring)) < 0)
3450           return(x);
3451         if ((success = seton(&y)) < 0)
3452           return(success);
3453         if (y)                          /* Set or reset the selected bit */
3454           lf_opts |= x;                 /* in the options bitmask. */
3455         else
3456           lf_opts &= ~x;
3457         return(success);
3458 #endif /* CK_LABELED */
3459
3460       case XYFILI: {                    /* INCOMPLETE */
3461           extern struct keytab ifdatab[];
3462           extern int keep;
3463           if ((y = cmkey(ifdatab,3,"","auto",xxstring)) < 0) return(y);
3464           if ((x = cmcfm()) < 0) return(x);
3465           if (rmsflg) {
3466               sstate = setgen('S',
3467                               "310",
3468                               y == 0 ? "0" : (y == 1 ? "1" : "2"),
3469                               ""
3470                               );
3471               return((int) sstate);
3472           } else {
3473               keep = y;
3474               return(success = 1);
3475           }
3476       }
3477
3478 #ifdef CK_TMPDIR
3479       case XYFILG: {                    /* Download directory */
3480           int x;
3481           char *s;
3482 #ifdef ZFNQFP
3483           struct zfnfp * fnp;
3484 #endif /* ZFNQFP */
3485 #ifdef MAC
3486           char temp[34];
3487 #endif /* MAC */
3488
3489 #ifdef GEMDOS
3490           if ((x = cmdir("Name of local directory, or carriage return",
3491                          "",&s,
3492                          NULL)) < 0 ) {
3493               if (x != -3)
3494                 return(x);
3495           }
3496 #else
3497 #ifdef OS2
3498           if ((x = cmdir("Name of PC disk and/or directory,\n\
3499        or press the Enter key to use current directory",
3500                          "",&s,xxstring)) < 0 ) {
3501               if (x != -3)
3502                 return(x);
3503           }
3504 #else
3505 #ifdef MAC
3506           x = ckstrncpy(temp,zhome(),32);
3507           if (x > 0) if (temp[x-1] != ':') { temp[x] = ':'; temp[x+1] = NUL; }
3508           if ((x = cmtxt("Name of Macintosh volume and/or folder,\n\
3509  or press the Return key for the desktop on the boot disk",
3510                          temp,&s, xxstring)) < 0 )
3511             return(x);
3512 #else
3513           if ((x = cmdir("Name of local directory, or carriage return",
3514                          "", &s, xxstring)) < 0 ) {
3515               if (x != -3)
3516                 return(x);
3517           }
3518 #endif /* MAC */
3519 #endif /* OS2 */
3520 #endif /* GEMDOS */
3521           debug(F110,"download dir",s,0);
3522
3523 #ifndef MAC
3524           if (x == 2) {
3525               printf("?Wildcards not allowed in directory name\n");
3526               return(-9);
3527           }
3528 #endif /* MAC */
3529
3530 #ifdef ZFNQFP
3531           if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
3532               if (fnp->fpath)
3533                 if ((int) strlen(fnp->fpath) > 0)
3534                   s = fnp->fpath;
3535           }
3536           debug(F110,"download zfnqfp",s,0);
3537 #endif /* ZFNQFP */
3538
3539           ckstrncpy(line,s,LINBUFSIZ);  /* Make a safe copy */
3540 #ifndef MAC
3541           if ((x = cmcfm()) < 0)        /* Get confirmation */
3542             return(x);
3543 #endif /* MAC */
3544
3545 #ifdef CK_LOGIN
3546         if (isguest) {
3547             /* Don't let guests change existing files */
3548             printf("?This command not valid for guests\n");
3549             return(-9);
3550         }
3551 #endif /* CK_LOGIN */
3552           x = strlen(s);
3553
3554           if (x) {
3555 #ifdef datageneral                      /* AOS/VS */
3556               if (s[x-1] == ':')        /* homdir ends in colon, */
3557                 s[x-1] = NUL;           /* and "dir" doesn't like that... */
3558 #else
3559 #ifdef OS2ORUNIX                        /* Unix or K-95... */
3560               if ((x < (LINBUFSIZ - 2)) && /* Add trailing dirsep */
3561                   (s[x-1] != '/')) {    /* if none present.  */
3562                   s[x] = '/';           /* Note that Windows path has */
3563                   s[x+1] = NUL;         /* been canonicalized to forward */
3564               }                         /* slashes at this point. */
3565 #endif /* OS2ORUNIX */
3566 #endif /* datageneral */
3567               makestr(&dldir,s);
3568           } else
3569             makestr(&dldir,NULL);       /* dldir is NULL when not assigned */
3570
3571           return(success = 1);
3572       }
3573 #endif /* CK_TMPDIR */
3574       case XYFILY:
3575         return(setdest());
3576 #endif /* NOXFER */
3577
3578 #ifdef CK_CTRLZ
3579       case XYFILV: {                    /* EOF */
3580           extern int eofmethod;
3581           if ((x = cmkey(eoftab,3,"end-of-file detection method","",
3582                          xxstring)) < 0)
3583             return(x);
3584           if ((y = cmcfm()) < 0)
3585             return(y);
3586           eofmethod = x;
3587           return(success = 1);
3588       }
3589 #endif /* CK_CTRLZ */
3590
3591 #ifndef NOXFER
3592 #ifdef UNIX
3593       case XYFILH: {                    /* OUTPUT */
3594           extern int zofbuffer, zobufsize, zofblock;
3595 #ifdef DYNAMIC
3596           extern char * zoutbuffer;
3597 #endif /* DYNAMIC */
3598
3599           if ((x = cmkey(zoftab,nzoftab,"output file writing method","",
3600                          xxstring)) < 0)
3601             return(x);
3602           if (x == ZOF_BUF || x == ZOF_NBUF) {
3603               if ((y = cmnum("output buffer size","32768",10,&z,xxstring)) < 0)
3604                 return(y);
3605               if (z < 1) {
3606                   printf("?Bad size - %d\n", z);
3607                   return(-9);
3608               }
3609           }
3610           if ((y = cmcfm()) < 0) return(y);
3611           switch (x) {
3612             case ZOF_BUF:
3613             case ZOF_NBUF:
3614               zofbuffer = (x == ZOF_BUF);
3615               zobufsize = z;
3616               break;
3617             case ZOF_BLK:
3618             case ZOF_NBLK:
3619               zofblock = (x == ZOF_BLK);
3620               break;
3621           }
3622 #ifdef DYNAMIC
3623           if (zoutbuffer) free(zoutbuffer);
3624           if (!(zoutbuffer = (char *)malloc(z))) {
3625               printf("MEMORY ALLOCATION ERROR - FATAL\n");
3626               doexit(BAD_EXIT,-1);
3627           } else
3628             zobufsize = z;
3629 #else
3630           if (z <= OBUFSIZE) {
3631               zobufsize = z;
3632           } else {
3633               printf("?Sorry, %d is too big - %d is the maximum\n",z,OBUFSIZE);
3634               return(-9);
3635           }
3636 #endif /* DYNAMIC */
3637           return(success = 1);
3638       }
3639 #endif /* UNIX */
3640
3641 #ifdef PATTERNS
3642       case XYFIBP:                      /* BINARY-PATTERN */
3643       case XYFITP: {                    /* TEXT-PATTERN */
3644           char * tmp[FTPATTERNS];
3645           int i, n = 0;
3646           while (n < FTPATTERNS) {
3647               tmp[n] = NULL;
3648               if ((x = cmfld("Pattern","",&s,xxstring)) < 0)
3649                 break;
3650               ckstrncpy(line,s,LINBUFSIZ);
3651               s = brstrip(line);
3652               makestr(&(tmp[n++]),s);
3653           }
3654           if (x == -3) x = cmcfm();
3655           for (i = 0; i <= n; i++) {
3656               if (x > -1) {
3657                   if (y == XYFIBP)
3658                     makestr(&(binpatterns[i]),tmp[i]);
3659                   else
3660                     makestr(&(txtpatterns[i]),tmp[i]);
3661               }
3662               free(tmp[i]);
3663           }
3664           if (y == XYFIBP)              /* Null-terminate the list */
3665             makestr(&(binpatterns[i]),NULL);
3666           else
3667             makestr(&(txtpatterns[i]),NULL);
3668           return(x);
3669       }
3670
3671       case XYFIPA:                      /* PATTERNS */
3672         if ((x = setonaut(&patterns)) < 0)
3673           return(x);
3674         return(success = 1);
3675 #endif /* PATTERNS */
3676 #endif /* NOXFER */
3677
3678 #ifdef UNICODE
3679       case XYFILU: {                    /* UCS */
3680           extern int ucsorder, ucsbom, byteorder;
3681           if ((x = cmkey(ucstab,nucstab,"","",xxstring)) < 0)
3682             return(x);
3683           switch (x) {
3684             case UCS_BYT:
3685               if ((y = cmkey(botab,nbotab,
3686                              "Byte order",
3687                              byteorder ? "little-endian" : "big-endian",
3688                              xxstring
3689                              )
3690                    ) < 0)
3691                 return(y);
3692               if ((x = cmcfm()) < 0)
3693                 return(x);
3694               ucsorder = y;
3695               return(success = 1);
3696             case UCS_BOM:
3697               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
3698                 return(y);
3699               if ((x = cmcfm()) < 0)
3700                 return(x);
3701               ucsbom = y;
3702               return(success = 1);
3703             default:
3704               return(-2);
3705           }
3706       }
3707 #endif /* UNICODE */
3708
3709 #ifndef datageneral
3710       case XYF_INSP: {                  /* SCAN (INSPECTION) */
3711           extern int filepeek, nscanfile;
3712           if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
3713             return(x);
3714           if (y) {
3715               if ((y = cmnum("How much to scan",ckitoa(SCANFILEBUF),
3716                              10,&z,xxstring)) < 0)
3717                 return(y);
3718           }
3719           if ((y = cmcfm()) < 0)
3720             return(y);
3721 #ifdef VMS
3722           filepeek = 0;
3723           nscanfile = 0;
3724           return(success = 0);
3725 #else
3726           filepeek = x;
3727           nscanfile = z;
3728           return(success = 1);
3729 #endif /* VMS */
3730       }
3731 #endif /* datageneral */
3732
3733       case XYF_DFLT:
3734         y = 0;
3735 #ifndef NOCSETS
3736         if ((y = cmkey(fdfltab,nfdflt,"","",xxstring)) < 0)
3737           return(y);
3738         if (y == 7 || y == 8) {
3739             if (y == 7)
3740               s = fcsinfo[dcset7].keyword;
3741             else
3742               s = fcsinfo[dcset8].keyword;
3743             if ((x = cmkey(fcstab,nfilc,"character-set",s,xxstring)) < 0)
3744               return(x);
3745         }
3746         ckstrncpy(line,fcsinfo[x].keyword,LINBUFSIZ);
3747         s = line;
3748 #endif /* NOCSETS */
3749         if ((z = cmcfm()) < 0)
3750           return(z);
3751         switch (y) {
3752 #ifndef NOCSETS
3753           case 7:
3754             if (fcsinfo[x].size != 128) {
3755                 printf("%s - Not a 7-bit set\n",s);
3756                 return(-9);
3757             }
3758             dcset7 = x;
3759             break;
3760           case 8:
3761             if (fcsinfo[x].size != 256) {
3762                 printf("%s - Not an 8-bit set\n",s);
3763                 return(-9);
3764             }
3765             dcset8 = x;
3766             break;
3767 #endif /* NOCSETS */
3768           default:
3769             return(-2);
3770         }
3771         return(success = 1);
3772
3773 #ifndef NOXFER
3774       case 9997:                        /* FASTLOOKUPS */
3775         return(success = seton(&stathack));
3776 #endif /* NOXFER */
3777
3778 #ifdef UNIX
3779 #ifdef DYNAMIC
3780       case XYF_LSIZ: {                  /* LISTSIZE */
3781           int zz;
3782           y = cmnum("Maximum number of filenames","",10,&x,xxstring);
3783           if ((x = setnum(&zz,x,y,-1)) < 0)
3784             return(x);
3785           if (zsetfil(zz,3) < 0) {
3786               printf("?Memory allocation failure\n");
3787               return(-9);
3788           }
3789           return(success = 1);
3790       }
3791       case XYF_SSPA: {                  /* STRINGSPACE */
3792           int zz;
3793           y = cmnum("Number of characters for filename list",
3794                     "",10,&x,xxstring);
3795           if ((x = setnum(&zz,x,y,-1)) < 0)
3796             return(x);
3797           if (zsetfil(zz,1) < 0) {
3798               printf("?Memory allocation failure\n");
3799               return(-9);
3800           }
3801           return(success = 1);
3802       }
3803
3804 #endif /* DYNAMIC */
3805 #endif /* UNIX */
3806
3807       default:
3808         printf("?unexpected file parameter\n");
3809         return(-2);
3810     }
3811 }
3812
3813 #ifdef UNIX
3814 #ifndef NOPUTENV
3815 #ifdef BIGBUFOK
3816 #define NPUTENVS 4096
3817 #else
3818 #define NPUTENVS 128
3819 #endif  /* BIGBUFOK */
3820 /* environment variables must be static, not automatic */
3821
3822 static char * putenvs[NPUTENVS];        /* Array of environment var strings */
3823 static int nputenvs = -1;               /* Pointer into array */
3824 /*
3825   If anyone ever notices the limitation on the number of PUTENVs, the list
3826   can be made dynamic, we can recycle entries with the same name, etc.
3827 */
3828 int
3829 doputenv(s1, s2) char * s1; char * s2; {
3830     char * s, * t = tmpbuf;             /* Create or alter environment var */
3831
3832     if (nputenvs == -1) {               /* Table not used yet */
3833         int i;                          /* Initialize the pointers */
3834         for (i = 0; i < NPUTENVS; i++)
3835           putenvs[i] = NULL;
3836         nputenvs = 0;
3837     }
3838     if (!s1) return(1);                 /* Nothing to do */
3839     if (!*s1) return(1);                /* ditto */
3840
3841     if (ckindex("=",s1,0,0,0)) {        /* Does the name contain an '='? */
3842         printf(                         /* putenv() does not allow this. */
3843          /* This also catches the 'putenv name=value' case */
3844          "?PUTENV - Equal sign in variable name - 'help putenv' for info.\n");
3845         return(-9);
3846     }
3847     nputenvs++;                         /* Point to next free string */
3848
3849     debug(F111,"doputenv s1",s1,nputenvs);
3850     debug(F111,"doputenv s2",s2,nputenvs);
3851
3852     if (nputenvs > NPUTENVS - 1) {      /* Notice the end */
3853         printf("?PUTENV - static buffer space exhausted\n");
3854         return(-9);
3855     }
3856     /* Quotes are not needed but we allow them for familiarity */
3857     /* but then we strip them, so syntax is same as for Unix shell */
3858
3859     if (s2) {
3860         s2 = brstrip(s2);
3861     } else {
3862         s2 = (char *)"";
3863     }
3864     ckmakmsg(t,TMPBUFSIZ,s1,"=",s2,NULL);
3865     debug(F111,"doputenv",t,nputenvs);
3866     (VOID) makestr(&(putenvs[nputenvs]),t); /* Make a safe permananent copy */
3867     if (!putenvs[nputenvs]) {
3868         printf("?PUTENV - memory allocation failure\n");
3869         return(-9);
3870     }
3871     if (putenv(putenvs[nputenvs])) {
3872         printf("?PUTENV - %s\n",ck_errstr());
3873         return(-9);
3874     } else return(success = 1);
3875 }
3876 #endif  /* NOPUTENV */
3877 #endif  /* UNIX */
3878
3879 int
3880 settrmtyp() {
3881 #ifdef OS2
3882 #ifdef TNCODE
3883     extern int ttnum;                    /* Last Telnet Terminal Type sent */
3884     extern int ttnumend;                 /* Has end of list been found */
3885 #endif /* TNCODE */
3886     if ((x = cmkey(ttyptab,nttyp,"","vt220",xxstring)) < 0)
3887       return(x);
3888     if ((y = cmcfm()) < 0)
3889       return(y);
3890     settermtype(x,1);
3891 #ifdef TNCODE
3892     /* So we send the correct terminal name to the host if it asks for it */
3893     ttnum = -1;                         /* Last Telnet Terminal Type sent */
3894     ttnumend = 0;                       /* end of list not found */
3895 #endif /* TNCODE */
3896     return(success = 1);
3897 #else  /* Not OS2 */
3898 #ifdef UNIX
3899     extern int fxd_inited;
3900     x = cmtxt("Terminal type name, case sensitive","",&s,NULL);
3901 #ifdef NOPUTENV
3902     success = 1;
3903 #else
3904     success = doputenv("TERM",s);       /* Set the TERM variable */
3905 #ifdef CK_CURSES
3906     fxd_inited = 0;            /* Force reinitialization of curses database */
3907     (void)doxdis(0);                 /* Re-initialize file transfer display */
3908     concb((char)escape);                /* Fix command terminal */
3909 #endif  /* CK_CURSES */
3910 #endif  /* NOPUTENV */
3911     return(success);
3912 #else
3913     printf(
3914 "\n Sorry, this version of C-Kermit does not support the SET TERMINAL TYPE\n");
3915     printf(
3916 " command.  Type \"help set terminal\" for further information.\n");
3917     return(success = 0);
3918 #endif  /* UNIX */
3919 #endif /* OS2 */
3920 }
3921
3922 #ifndef NOLOCAL
3923 #ifdef OS2
3924 /* MS-DOS KERMIT compatibility modes */
3925 int
3926 setmsk() {
3927     if ((y = cmkey(msktab,nmsk,"MS-DOS Kermit compatibility mode",
3928                     "keycodes",xxstring)) < 0) return(y);
3929
3930     switch ( y ) {
3931 #ifdef COMMENT
3932       case MSK_COLOR:
3933         return(seton(&mskcolors));
3934 #endif /* COMMENT */
3935       case MSK_KEYS:
3936         return(seton(&mskkeys));
3937       case MSK_REN:
3938         return(seton(&mskrename));
3939       default:                          /* Shouldn't get here. */
3940         return(-2);
3941     }
3942 }
3943 #endif /* OS2 */
3944
3945 #ifdef CKTIDLE
3946 static char iactbuf[132];
3947
3948 char *
3949 getiact() {
3950     switch (tt_idleact) {
3951       case IDLE_RET:  return("return");
3952       case IDLE_EXIT: return("exit");
3953       case IDLE_HANG: return("hangup");
3954 #ifdef TNCODE
3955       case IDLE_TNOP: return("Telnet NOP");
3956       case IDLE_TAYT: return("Telnet AYT");
3957 #endif /* TNCODE */
3958
3959       case IDLE_OUT: {
3960           int c, k, n;
3961           char * p, * q, * t;
3962           k = ckstrncpy(iactbuf,"output ",132);
3963           n = k;
3964           q = &iactbuf[k];
3965           p = tt_idlestr;
3966           if (!p) p = "";
3967           if (!*p) return("output NUL");
3968           while ((c = *p++) && n < 131) {
3969               c &= 0xff;
3970               if (c == '\\') {
3971                   if (n > 130) break;
3972                   *q++ = '\\';
3973                   *q++ = '\\';
3974                   *q = NUL;
3975                   n += 2;
3976               } else if ((c > 32 && c < 127) || c > 159) {
3977                   *q++ = c;
3978                   *q = NUL;
3979                   n++;
3980               } else {
3981                   if (n > (131 - 6))
3982                     break;
3983                   sprintf(q,"\\{%d}",c);
3984                   k = strlen(q);
3985                   q += k;
3986                   n += k;
3987                   *q = NUL;
3988               }
3989           }
3990           *q = NUL;
3991 #ifdef OS2
3992           k = tt_cols[VTERM];
3993 #else
3994           k = tt_cols;
3995 #endif /* OS2 */
3996           if (n > k - 52) {
3997               n = k - 52;
3998               iactbuf[n-2] = '.';
3999               iactbuf[n-1] = '.';
4000               iactbuf[n] = NUL;
4001           }
4002           return(iactbuf);
4003       }
4004       default: return("unknown");
4005     }
4006 }
4007 #endif /* CKTIDLE */
4008
4009 #ifndef NOCSETS
4010 VOID
4011 setlclcharset(x) int x; {
4012     int i;
4013     tcsl = y;                   /* Local character set */
4014 #ifdef OS2
4015     for (i = 0; i < 4; i++) {
4016         G[i].init = TRUE;
4017         x = G[i].designation;
4018         G[i].c1 = (x != tcsl) && cs_is_std(x);
4019         x = G[i].def_designation;
4020         G[i].def_c1 = (x != tcsl) && cs_is_std(x);
4021     }
4022 #endif /* OS2 */
4023 }
4024
4025 VOID
4026 setremcharset(x, z) int x, z; {
4027     int i;
4028
4029 #ifdef KUI
4030     KuiSetProperty( KUI_TERM_REMCHARSET, (long) x, (long) z ) ;
4031 #endif /* KUI */
4032 #ifdef UNICODE
4033     if (x == TX_TRANSP)
4034 #else /* UNICODE */
4035     if (x == FC_TRANSP)
4036 #endif /* UNICODE */
4037     {                           /* TRANSPARENT? */
4038 #ifndef OS2
4039         tcsr = tcsl;            /* Make both sets the same */
4040 #else /* OS2 */
4041 #ifdef CKOUNI
4042         tt_utf8 = 0;            /* Turn off UTF8 flag */
4043         tcsr = tcsl = dec_kbd = TX_TRANSP; /* No translation */
4044         tcs_transp = 1;
4045
4046         if (!cs_is_nrc(tcsl)) {
4047             G[0].def_designation = G[0].designation = TX_ASCII;
4048             G[0].init = TRUE;
4049             G[0].def_c1 = G[0].c1 = FALSE;
4050             G[0].size = cs94;
4051             G[0].national = FALSE;
4052         }
4053         for (i = cs_is_nrc(tcsl) ? 0 : 1; i < 4; i++) {
4054             G[i].def_designation = G[i].designation = tcsl;
4055             G[i].init = TRUE;
4056             G[i].def_c1 = G[i].c1 = FALSE;
4057             switch (cs_size(G[i].designation)) { /* 94, 96, or 128 */
4058             case 128:
4059             case 96:
4060                 G[i].size = G[i].def_size = cs96;
4061                 break;
4062             case 94:
4063                 G[i].size = G[i].def_size = cs94;
4064                 break;
4065             default:
4066                 G[i].size = G[i].def_size = csmb;
4067                 break;
4068             }
4069             G[i].national = cs_is_nrc(x);
4070         }
4071 #else /* CKOUNI */
4072         tcsr = tcsl;            /* Make both sets the same */
4073         for (i = 0; i < 4; i++) {
4074             G[i].def_designation = G[i].designation = FC_TRANSP;
4075             G[i].init = FALSE;
4076             G[i].size = G[i].def_size = cs96;
4077             G[i].c1 = G[i].def_c1 = FALSE;
4078             G[i].rtoi = NULL;
4079             G[i].itol = NULL;
4080             G[i].ltoi = NULL;
4081             G[i].itor = NULL;
4082             G[i].national = FALSE;
4083         }
4084 #endif /* CKOUNI */
4085 #endif /* OS2 */
4086         return;
4087     }
4088 #ifdef OS2
4089 #ifdef CKOUNI
4090     else if (x == TX_UTF8) {
4091         tcs_transp = 0;
4092         tt_utf8 = 1;            /* Turn it on if we are UTF8 */
4093         return;
4094     }
4095 #endif /* CKOUNI */
4096     else {
4097         tcs_transp = 0;
4098         tcsr = x;                       /* Remote character set */
4099 #ifdef CKOUNI
4100         tt_utf8 = 0;                    /* Turn off UTF8 flag */
4101 #endif /* CKOUNI */
4102
4103         if (z == TT_GR_ALL) {
4104             int i;
4105 #ifdef UNICODE
4106             dec_kbd = x;
4107 #endif /* UNICODE */
4108             for (i = 0; i < 4; i++) {
4109                 G[i].init = TRUE;
4110                 if ( i == 0 && !cs_is_nrc(x) ) {
4111                     G[0].designation = G[0].def_designation = FC_USASCII;
4112                     G[0].size = G[0].def_size = cs94;
4113                     G[0].national = 1;
4114                 } else {
4115                     G[i].def_designation = G[i].designation = x;
4116                     switch (cs_size(x)) {       /* 94, 96, or 128 */
4117                     case 128:
4118                     case 96:
4119                         G[i].size = G[i].def_size = cs96;
4120                         break;
4121                     case 94:
4122                         G[i].size = G[i].def_size = cs94;
4123                         break;
4124                     default:
4125                         G[i].size = G[i].def_size = csmb;
4126                         break;
4127                     }
4128                     G[i].national = cs_is_nrc(x);
4129                 }
4130                 G[i].c1 = G[i].def_c1 = x != tcsl && cs_is_std(x);
4131             }
4132 #ifdef UNICODE
4133         } else if (z == TT_GR_KBD) {    /* Keyboard only */
4134             dec_kbd = x;
4135 #endif /* UNICODE */
4136         } else {                        /* Specific Gn */
4137             G[z].def_designation = G[z].designation = x;
4138             G[z].init = TRUE;
4139             switch (cs_size(x)) {       /* 94, 96, or 128 */
4140             case 128:
4141             case 96:
4142                 G[z].size = G[z].def_size = cs96;
4143                 break;
4144             case 94:
4145                 G[z].size = G[z].def_size = cs94;
4146                 break;
4147             default:
4148                 G[z].size = G[z].def_size = csmb;
4149                 break;
4150             }
4151             G[z].c1 = G[z].def_c1 = x != tcsl && cs_is_std(x);
4152             G[z].national = cs_is_nrc(x);
4153         }
4154     }
4155 #else /* not OS2 */
4156     tcsr = x;                   /* Remote character set */
4157 #endif /* OS2 */
4158 }
4159 #endif /* NOCSETS */
4160
4161 VOID
4162 setcmask(x) int x; {
4163     if (x == 7) {
4164         cmask = 0177;
4165     } else if (x == 8) {
4166         cmask = 0377;
4167         parity = 0;
4168     }
4169 #ifdef KUI      
4170     KuiSetProperty(KUI_TERM_CMASK,x,0);
4171 #endif /* KUI */
4172 }
4173
4174 #ifdef CK_AUTODL
4175 VOID
4176 setautodl(x,y) int x,y; {
4177     autodl = x;
4178     adl_ask = y;
4179 #ifdef KUI      
4180     KuiSetProperty(KUI_TERM_AUTODOWNLOAD,x?(y?2:1):0,0);
4181 #endif /* KUI */
4182 }
4183 #endif /* CK_AUTODL */
4184
4185 #ifdef OS2
4186 VOID
4187 seturlhl(int x) {
4188     tt_url_hilite = x;
4189 #ifdef KUI      
4190     KuiSetProperty(KUI_TERM_URL_HIGHLIGHT,x,0);
4191 #endif /* KUI */
4192 }
4193
4194 VOID
4195 setaprint(int x) {
4196     extern int aprint;
4197     aprint = x;
4198 #ifdef KUI
4199     KuiSetProperty(KUI_TERM_PRINTERCOPY,x,0);
4200 #endif /* KUI */
4201 }
4202 #endif /* OS2 */
4203
4204 int
4205 settrm() {
4206     int i = 0;
4207 #ifdef OS2
4208     extern int colorreset, user_erasemode;
4209 #endif /* OS2 */
4210     if ((y = cmkey(trmtab,ntrm,"", "",xxstring)) < 0) return(y);
4211 #ifdef MAC
4212     printf("\n?Sorry, not implemented yet.  Please use the Settings menu.\n");
4213     return(-9);
4214 #else
4215 #ifdef IKSD
4216     if (inserver) {
4217         if ((y = cmcfm()) < 0) return(y);
4218         printf("?Sorry, command disabled.\r\n");
4219         return(success = 0);
4220     }
4221 #endif /* IKSD */
4222
4223     switch (y) {
4224       case XYTBYT:                      /* SET TERMINAL BYTESIZE */
4225         if ((y = cmnum("bytesize for terminal connection","8",10,&x,
4226                        xxstring)) < 0)
4227           return(y);
4228         if (x != 7 && x != 8) {
4229             printf("\n?The choices are 7 and 8\n");
4230             return(success = 0);
4231         }
4232         if ((y = cmcfm()) < 0) return(y);
4233         setcmask(x);
4234 #ifdef OS2
4235         if (IS97801(tt_type_mode))
4236           SNI_bitmode(x);
4237 #endif /* OS2 */
4238         return(success = 1);
4239
4240       case XYTSO:                       /* SET TERMINAL LOCKING-SHIFT */
4241         return(seton(&sosi));
4242
4243       case XYTNL:                       /* SET TERMINAL NEWLINE-MODE */
4244         return(seton(&tnlm));
4245
4246 #ifdef OS2
4247       case XYTCOL:
4248         if ((x = cmkey(ttycoltab,ncolors,"","terminal",xxstring)) < 0)
4249           return(x);
4250         else if (x == TTCOLRES) {
4251             if ((y = cmkey(ttcolmodetab,ncolmode,
4252                            "","default-color",xxstring)) < 0)
4253               return(y);
4254             if ((z = cmcfm()) < 0)
4255               return(z);
4256             colorreset = y;
4257             return(success = 1);
4258         } else if (x == TTCOLERA) {
4259             if ((y = cmkey(ttcolmodetab,ncolmode,"",
4260                            "current-color",xxstring)) < 0)
4261               return(y);
4262             if ((z = cmcfm()) < 0)
4263               return(z);
4264             user_erasemode = y;
4265             return(success=1);
4266         } else {                        /* No parse error */
4267             int fg = 0, bg = 0;
4268             fg = cmkey(ttyclrtab, nclrs,
4269                        (x == TTCOLBOR ?
4270                         "color for screen border" :
4271                         "foreground color and then background color"),
4272                        "lgray", xxstring);
4273             if (fg < 0)
4274               return(fg);
4275             if (x != TTCOLBOR) {
4276                 if ((bg = cmkey(ttyclrtab,nclrs,
4277                                 "background color","blue",xxstring)) < 0)
4278                   return(bg);
4279             }
4280             if ((y = cmcfm()) < 0)
4281               return(y);
4282             switch (x) {
4283               case TTCOLNOR:
4284                 colornormal = fg | bg << 4;
4285                 fgi = fg & 0x08;
4286                 bgi = bg & 0x08;
4287                 break;
4288               case TTCOLREV:
4289                 colorreverse = fg | bg << 4;
4290                 break;
4291               case TTCOLITA:
4292                 coloritalic = fg | bg << 4;
4293                 break;
4294               case TTCOLUND:
4295                 colorunderline = fg | bg << 4;
4296                 break;
4297               case TTCOLGRP:
4298                 colorgraphic = fg | bg << 4;
4299                 break;
4300               case TTCOLDEB:
4301                 colordebug = fg | bg << 4;
4302                 break;
4303               case TTCOLSTA:
4304                 colorstatus = fg | bg << 4;
4305                 break;
4306               case TTCOLHLP:
4307                 colorhelp = fg | bg << 4;
4308                 break;
4309               case TTCOLBOR:
4310                 colorborder = fg;
4311                 break;
4312               case TTCOLSEL:
4313                 colorselect = fg | bg << 4;
4314                 break;
4315               default:
4316                 printf("%s - invalid\n",cmdbuf);
4317                 return(-9);
4318                 break;
4319             }
4320             scrninitialized[VTERM] = 0;
4321             VscrnInit(VTERM);
4322         }
4323         return(success = 1);
4324
4325       case XYTCUR: {                    /* SET TERMINAL CURSOR */
4326           extern int cursorena[];
4327           extern int cursoron[] ;       /* Cursor state on/off       */
4328           if ((x = cmkey(ttycurtab,ncursors,"","underline",xxstring)) < 0)
4329             return(x);
4330           if ((z = cmkey(curontab,ncuron,"","on",xxstring)) < 0)
4331             return(z);
4332           if ((y = cmcfm()) < 0) return(y);
4333           tt_cursor = tt_cursor_usr = x;
4334           if ( z == 2 ) {
4335               cursorena[VTERM] = tt_cursorena_usr = 1;
4336               tt_cursor_blink = 0;
4337           } else {
4338               cursorena[VTERM] = tt_cursorena_usr = z;/* turn cursor on/off */
4339               tt_cursor_blink = 1;
4340           }
4341           cursoron[VTERM] = FALSE; /* Force newcursor to restore the cursor */
4342           return(success = 1);
4343       }
4344 #endif /* OS2 */
4345
4346       case XYTTYP:                      /* SET TERMINAL TYPE */
4347         return(settrmtyp());
4348
4349 #ifdef OS2
4350       case XYTARR:                      /* SET TERMINAL ARROW-KEYS */
4351         if ((x = cmkey(akmtab,2,"","",xxstring)) < 0) return(x);
4352         if ((y = cmcfm()) < 0) return(y);
4353         tt_arrow = x;                   /* TTK_NORM / TTK_APPL; see ckuusr.h */
4354         return(success = 1);
4355
4356       case XYTKPD:                      /* SET TERMINAL KEYPAD-MODE */
4357         if ((x = cmkey(kpmtab,2,"","",xxstring)) < 0) return(x);
4358         if ((y = cmcfm()) < 0) return(y);
4359         tt_keypad = x;                  /* TTK_NORM / TTK_APPL; see ckuusr.h */
4360         return(success = 1);
4361
4362       case XYTUNX: {                    /* SET TERM UNIX-MODE (DG) */
4363         extern int dgunix,dgunix_usr;
4364         x = seton(&dgunix);
4365         dgunix_usr = dgunix;
4366         return(x);
4367       }
4368       case XYTKBMOD: {                  /* SET TERM KEYBOARD MODE */
4369           extern int tt_kb_mode;
4370           if ((x = cmkey(kbmodtab,
4371                          nkbmodtab,
4372                          "normal",
4373                          "special keyboard mode for terminal emulation",
4374                          xxstring)
4375                ) < 0)
4376             return(x);
4377           if ((y = cmcfm()) < 0) return(y);
4378           tt_kb_mode = x;
4379           return(success = 1);
4380       }
4381
4382       case XYTWRP:                      /* SET TERMINAL WRAP */
4383         return(seton(&tt_wrap));
4384
4385       case XYSCRS:
4386         if ((y = cmnum("CONNECT scrollback buffer size, lines","2000",10,&x,
4387                        xxstring)) < 0)
4388           return(y);
4389         /* The max number of lines is the RAM  */
4390         /* we can actually dedicate to a       */
4391         /* scrollback buffer given the maximum */
4392         /* process memory space of 512MB       */
4393         if (x < 256 || x > 2000000L) {
4394             printf("\n?The size must be between 256 and 2,000,000.\n");
4395             return(success = 0);
4396         }
4397         if ((y = cmcfm()) < 0) return(y);
4398         tt_scrsize[VTERM] = x;
4399         VscrnInit(VTERM);
4400         return(success = 1);
4401 #endif /* OS2 */
4402
4403 #ifndef NOCSETS
4404       case XYTCS: {                     /* SET TERMINAL CHARACTER-SET */
4405         int eol;
4406           /* set terminal character-set <remote> <local> */
4407         if ((x = cmkey(
4408 #ifdef CKOUNI
4409                        txrtab,ntxrtab,
4410 #else  /* CKOUNI */
4411                        ttcstab,ntermc,
4412 #endif /* CKOUNI */
4413                        "remote terminal character-set","",xxstring)) < 0)
4414           return(x);
4415
4416 #ifdef UNICODE
4417         if (x == TX_TRANSP
4418 #ifdef CKOUNI
4419             || x == TX_UTF8
4420 #endif /* CKOUNI */
4421            ) {
4422               if ((y = cmcfm()) < 0)    /* Confirm the command */
4423                   return(y);
4424 #ifdef OS2
4425             if ( isunicode() && x == TX_TRANSP ) {
4426                 /* If we are in unicode display mode then transparent
4427                  * only affects the output direction.  We need to know
4428                  * the actual remote character set in order to perform
4429                  * the tcsr -> ucs2 translation for display.
4430                  */
4431                 x = y = tcsl;
4432             } else
4433 #endif /* OS2 */
4434                 y = x;
4435         }
4436 #else /* UNICODE */
4437         if (x == FC_TRANSP) {
4438             if ((y = cmcfm()) < 0)      /* Confirm the command */
4439                 return(y);
4440             y = x;
4441         }
4442 #endif /* UNICODE */
4443
4444         /* Not transparent or UTF8, so get local set to translate it into */
4445         s = "";
4446 #ifdef OS2
4447         y = os2getcp();                 /* Default is current code page */
4448         switch (y) {
4449           case 437: s = "cp437"; break;
4450           case 850: s = "cp850"; break;
4451           case 852: s = "cp852"; break;
4452           case 857: s = "cp857"; break;
4453           case 858: s = "cp858"; break;
4454           case 862: s = "cp862"; break;
4455           case 866: s = "cp866"; break;
4456           case 869: s = "cp869"; break;
4457           case 1250: s = "cp1250"; break;
4458           case 1251: s = "cp1251"; break;
4459           case 1252: s = "cp1252"; break;
4460           case 1253: s = "cp1253"; break;
4461           case 1254: s = "cp1254"; break;
4462           case 1255: s = "cp1255"; break;
4463           case 1256: s = "cp1256"; break;
4464           case 1257: s = "cp1257"; break;
4465           case 1258: s = "cp1258"; break;
4466         }
4467 #ifdef PCFONTS
4468 /*
4469    If the user has loaded a font with SET TERMINAL FONT then we want
4470    to change the default code page to the font that was loaded.
4471 */
4472         if (tt_font != TTF_ROM) {
4473             for (y = 0; y < ntermfont; y++ ) {
4474                 if (term_font[y].kwval == tt_font) {
4475                     s = term_font[y].kwd;
4476                     break;
4477                 }
4478             }
4479         }
4480 #endif /* PCFONTS */
4481 #else  /* Not K95... */
4482         s = fcsinfo[fcharset].keyword;
4483 #endif /* OS2 */
4484
4485         if ((y = cmkey(
4486 #ifdef CKOUNI
4487                        txrtab,ntxrtab,
4488 #else /* CKOUNI */
4489                        ttcstab,ntermc,
4490 #endif /* CKOUNI */
4491                        "local character-set",s,xxstring)) < 0)
4492           return(y);
4493
4494 #ifdef UNICODE
4495         if (y == TX_UTF8) {
4496             printf("?UTF8 may not be used as a local character set.\r\n");
4497             return(-9);
4498         }
4499 #endif /* UNICODE */
4500 #ifdef OS2
4501         if ((z = cmkey(graphsettab,ngraphset,
4502                        "DEC VT intermediate graphic set","all",xxstring)) < 0)
4503             return(z);
4504 #endif /* OS2 */
4505         if ((eol = cmcfm()) < 0)
4506             return(eol); /* Confirm the command */
4507
4508         /* End of command parsing - actions begin */
4509         setlclcharset(y);
4510         setremcharset(x,z);
4511         return(success = 1);
4512       }
4513 #endif /* NOCSETS */
4514
4515 #ifndef NOCSETS
4516       case XYTLCS:                      /* SET TERMINAL LOCAL-CHARACTER-SET */
4517         /* set terminal character-set <local> */
4518         s = getdcset();                 /* Get display character-set name */
4519         if ((y = cmkey(
4520 #ifdef CKOUNI
4521                        txrtab,ntxrtab,
4522 #else /* CKOUNI */
4523                        fcstab,nfilc,
4524 #endif /* CKOUNI */
4525                        "local character-set",s,xxstring)) < 0)
4526           return(y);
4527
4528 #ifdef UNICODE
4529           if (y == TX_UTF8) {
4530               printf("?UTF8 may not be used as a local character set.\r\n");
4531               return(-9);
4532           }
4533 #endif /* UNICODE */
4534           if ((z = cmcfm()) < 0) return(z); /* Confirm the command */
4535
4536           /* End of command parsing - action begins */
4537
4538         setlclcharset(y);
4539         return(success = 1);
4540 #endif /* NOCSETS */
4541
4542 #ifndef NOCSETS
4543 #ifdef UNICODE
4544       case XYTUNI:                      /* SET TERMINAL UNICODE */
4545         return(seton(&tt_unicode));
4546 #endif /* UNICODE */
4547
4548       case XYTRCS:                      /* SET TERMINAL REMOTE-CHARACTER-SET */
4549         /* set terminal character-set <remote> <Graphic-set> */
4550         if ((x = cmkey(
4551 #ifdef CKOUNI
4552                 txrtab, ntxrtab,
4553 #else /* CKOUNI */
4554                 ttcstab,ntermc,
4555 #endif /* CKOUNI */
4556                        "remote terminal character-set","",xxstring)) < 0)
4557           return(x);
4558
4559 #ifdef UNICODE
4560         if (x == TX_TRANSP
4561 #ifdef CKOUNI
4562             || x == TX_UTF8
4563 #endif /* CKOUNI */
4564            ) {
4565               if ((y = cmcfm()) < 0)    /* Confirm the command */
4566                   return(y);
4567 #ifdef OS2
4568             if ( isunicode() && x == TX_TRANSP ) {
4569                 /* If we are in unicode display mode then transparent
4570                  * only affects the output direction.  We need to know
4571                  * the actual remote character set in order to perform
4572                  * the tcsr -> ucs2 translation for display.
4573                  */
4574                 x = tcsl;
4575             }
4576 #endif /* OS2 */
4577         }
4578 #else /* UNICODE */
4579         if (x == FC_TRANSP) {
4580           if ((y = cmcfm()) < 0)        /* Confirm the command */
4581             return(y);
4582         }
4583 #endif /* UNICODE */
4584         else {
4585 #ifdef OS2
4586           if ((z = cmkey(graphsettab,ngraphset,
4587                       "DEC VT intermediate graphic set","all",xxstring)) < 0)
4588             return(z);
4589 #endif /* OS2 */
4590           if ((y = cmcfm()) < 0)        /* Confirm the command */
4591             return(y);
4592         }
4593         /* Command parsing ends here */
4594
4595         setremcharset(x,z);
4596         return(success = 1);
4597 #endif /* NOCSETS */
4598
4599       case XYTEC:                       /* SET TERMINAL ECHO */
4600         if ((x = cmkey(rltab,nrlt,"which side echos during CONNECT",
4601                        "remote", xxstring)) < 0) return(x);
4602         if ((y = cmcfm()) < 0) return(y);
4603 #ifdef NETCONN
4604         oldplex = x;
4605 #endif /* NETCONN */
4606         duplex = x;
4607         return(success = 1);
4608
4609       case XYTESC:                      /* SET TERM ESC */
4610         if ((x = cmkey(nabltab,nnabltab,"","enabled",xxstring)) < 0)
4611           return(x);
4612         if ((y = cmcfm()) < 0) return(y);
4613         tt_escape = x;
4614         return(1);
4615
4616       case XYTCRD:                      /* SET TERMINAL CR-DISPLAY */
4617         if ((x = cmkey(crdtab,2,"", "normal", xxstring)) < 0) return(x);
4618         if ((y = cmcfm()) < 0) return(y);
4619         tt_crd = x;
4620         return(success = 1);
4621
4622       case XYTLFD:                      /* SET TERMINAL LF-DISPLAY */
4623         if ((x = cmkey(crdtab,2,"", "normal", xxstring)) < 0) return(x);
4624         if ((y = cmcfm()) < 0) return(y);
4625         tt_lfd = x;
4626         return(success = 1);
4627
4628 #ifdef OS2
4629       case XYTANS: {                    /* SET TERMINAL ANSWERBACK */
4630 /*
4631   NOTE: We let them enable and disable the answerback sequence, but we
4632   do NOT let them change it, and we definitely do not let the host set it.
4633   This is a security feature.
4634
4635   As of 1.1.8 we allow the SET TERM ANSWERBACK MESSAGE <string> to be
4636   used just as MS-DOS Kermit does.  C0 and C1 controls as well as DEL
4637   are not allowed to be used as characters.  They are translated to
4638   underscore.  This may not be set by APC.
4639 */
4640           if ((x = cmkey(anbktab,nansbk,"", "off", xxstring)) < 0)
4641             return(x);
4642           if (x < 2) {
4643               if ((y = cmcfm()) < 0)
4644                 return(y);
4645               tt_answer = x;
4646               return(success = 1);
4647           } else if ( x == 2 || x == 3) {
4648               int len = 0;
4649               extern int safeanswerbk;
4650               extern char useranswerbk[];
4651               if ((y = cmtxt("Answerback extension","",&s,xxstring)) < 0)
4652                 return(y);
4653               if (apcactive == APC_LOCAL ||
4654                   (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
4655                 return(success = 0);
4656               len = strlen(s);
4657               if (x == 2) {
4658                   /* Safe Answerback's don't have C0/C1 chars */
4659                   for (z = 0; z < len; z++) {
4660                       if ((s[z] & 0x7F) <= SP || (s[z] & 0x7F) == DEL)
4661                         useranswerbk[z] = '_';
4662                       else
4663                         useranswerbk[z] = s[z];
4664                   }
4665                   useranswerbk[z] = '\0';
4666                   safeanswerbk = 1 ;    /* TRUE */
4667               } else {
4668                   ckstrncpy(useranswerbk,s,60); /* (see ckocon.c) */
4669                   safeanswerbk = 0;     /* FALSE */
4670               }
4671               updanswerbk();
4672               return(success = 1);
4673           } else
4674             return(success = 0);
4675       }
4676 #endif /* OS2 */
4677
4678 #ifdef CK_APC
4679       case XYTAPC:
4680         if ((y = cmkey(apctab,napctab,
4681                        "application program command execution","",
4682                        xxstring)) < 0)
4683           return(y);
4684         if ((x = cmcfm()) < 0)
4685           return(x);
4686         if (apcactive == APC_LOCAL ||
4687             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
4688           return(success = 0);
4689         apcstatus = y;
4690         return(success = 1);
4691
4692 #ifdef CK_AUTODL
4693       case XYTAUTODL:                   /* AUTODOWNLOAD */
4694         if ((y = cmkey(adltab,nadltab,"Auto-download options","",
4695                        xxstring)) < 0)
4696           return(y);
4697         switch (y) {
4698           case TAD_ON:
4699           case TAD_OFF:
4700             if ((x = cmcfm()) < 0)
4701               return(x);
4702             setautodl(y,0);
4703             break;
4704           case TAD_ASK:
4705             if ((x = cmcfm()) < 0)
4706               return(x);
4707             setautodl(TAD_ON,1);
4708             break;
4709           case TAD_ERR:
4710             if ((y = cmkey(adlerrtab,nadlerrtab,"","", xxstring)) < 0)
4711               return(y);
4712             if ((x = cmcfm()) < 0)
4713               return(x);
4714             adl_err = y;
4715             break;
4716 #ifdef OS2
4717           case TAD_K:
4718             if ((y = cmkey(adlxtab,nadlxtab,"","", xxstring)) < 0)
4719               return(y);
4720             switch (y) {
4721               case TAD_X_C0:
4722                 if ((y = cmkey(adlc0tab,nadlc0tab,"",
4723                                "processed-by-emulator",xxstring)) < 0)
4724                   return(y);
4725                 if ((x = cmcfm()) < 0)
4726                   return(x);
4727                 adl_kc0 = y;
4728                 break;
4729               case TAD_X_DETECT:
4730                 if ((y = cmkey(adldtab,nadldtab,"","packet",xxstring)) < 0)
4731                   return(y);
4732                 if ((x = cmcfm()) < 0)
4733                   return(x);
4734                 adl_kmode = y;
4735                 break;
4736               case TAD_X_STR:
4737                 if ((y = cmtxt("Kermit start string","KERMIT READY TO SEND...",
4738                                &s,xxstring)) < 0)
4739                   return(y);
4740                 free(adl_kstr);
4741                 adl_kstr = strdup(s);
4742                 break;
4743             }
4744             break;
4745
4746           case TAD_Z:
4747             if ((y = cmkey(adlxtab,nadlxtab,"","",xxstring)) < 0)
4748               return(y);
4749             switch (y) {
4750               case TAD_X_C0:
4751                 if ((y = cmkey(adlc0tab,nadlc0tab,"",
4752                                "processed-by-emulator",xxstring)) < 0)
4753                   return(y);
4754                 if ((x = cmcfm()) < 0)
4755                   return(x);
4756                 adl_zc0 = y;
4757                 break;
4758               case TAD_X_DETECT:
4759                 if ((y = cmkey(adldtab,nadldtab,"","packet",xxstring)) < 0)
4760                   return(y);
4761                 if ((x = cmcfm()) < 0)
4762                   return(x);
4763                 adl_zmode = y;
4764                 break;
4765               case TAD_X_STR:
4766                 if ((y = cmtxt("","rz\\{13}",&s,xxstring)) < 0)
4767                   return(y);
4768                 free(adl_zstr);
4769                 adl_zstr = strdup(s);
4770                 break;
4771             }
4772             break;
4773 #endif /* OS2 */
4774         }
4775         return(success = 1);
4776
4777 #endif /* CK_AUTODL */
4778 #endif /* CK_APC */
4779
4780 #ifdef OS2
4781       case XYTBEL:
4782         return(success = setbell());
4783
4784       case XYTMBEL:                     /* MARGIN-BELL */
4785         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
4786         if (y) {                        /* ON */
4787             if ((z = cmnum("Column at which to set margin bell",
4788                            "72",10,&x,xxstring)) < 0)
4789               return(z);
4790         }
4791         if ((z = cmcfm()) < 0) return(z);
4792         marginbell = y;
4793         marginbellcol = x;
4794         return(success = 1);
4795 #endif /* OS2 */
4796
4797 #ifdef CKTIDLE
4798       case XYTIDLE:                     /* IDLE-SEND */
4799       case XYTITMO:                     /* IDLE-TIMEOUT */
4800         if ((z = cmnum("seconds of idle time to wait, or 0 to disable",
4801                        "0",10,&x,xxstring)) < 0)
4802           return(z);
4803         if (y == XYTIDLE) {
4804             if ((y = cmtxt("string to send, may contain kverbs and variables",
4805                            "\\v(newline)",&s,xxstring)) < 0)
4806               return(y);
4807             tt_idlesnd_tmo = x;         /* (old) */
4808             tt_idlelimit = x;           /* (new) */
4809             makestr(&tt_idlestr,brstrip(s)); /* (new) */
4810             tt_idlesnd_str = tt_idlestr; /* (old) */
4811             tt_idleact = IDLE_OUT;      /* (new) */
4812         } else {
4813             if ((y = cmcfm()) < 0)
4814               return(y);
4815             tt_idlelimit = x;
4816         }
4817 #ifdef OS2
4818         puterror(VTERM);
4819 #endif /* OS2 */
4820         return(success = 1);
4821
4822       case XYTIACT: {                   /* SET TERM IDLE-ACTION */
4823           if ((y = cmkey(idlacts,nidlacts,"","",xxstring)) < 0)
4824             return(y);
4825           if (y == IDLE_OUT) {
4826               if ((x = cmtxt("string to send, may contain kverbs and variables"
4827                              , "",&s,xxstring)) < 0)
4828                 return(x);
4829               makestr(&tt_idlestr,brstrip(s)); /* (new) */
4830               tt_idlesnd_str = tt_idlestr; /* (old) */
4831           } else {
4832               if ((x = cmcfm()) < 0)
4833                 return(x);
4834           }
4835           tt_idleact = y;
4836           return(success = 1);
4837       }
4838 #endif /* CKTIDLE */
4839
4840       case XYTDEB:                      /* TERMINAL DEBUG */
4841         y = seton(&x);                  /* Go parse ON or OFF */
4842         if (y > 0)                      /* Command succeeded? */
4843           setdebses(x);
4844         return(y);
4845
4846 #ifdef OS2
4847       case XYTASCRL:                    /* SET TERMINAL AUTOSCROLL */
4848           y = seton(&autoscroll);
4849           return(y);
4850
4851       case XYTAPAGE:                    /* SET TERMINAL AUTOPAGE */
4852           y = seton(&wy_autopage);
4853           return(y);
4854
4855       case XYTROL:                      /* SET TERMINAL ROLL */
4856         if ((y = cmkey(rolltab,nroll,"scrollback mode","insert",xxstring))<0)
4857           return(y);
4858         if (y == TTR_KEYS) {
4859             if ((x = cmkey(rollkeytab,nrollkey,"","send",xxstring))<0)
4860               return(x);
4861             if ((z = cmcfm()) < 0) return(z);
4862             tt_rkeys[VTERM] = x;
4863         } else {
4864             if ((x = cmcfm()) < 0) return(x);
4865             tt_roll[VTERM] = y;
4866         }
4867         return(success = 1);
4868
4869       case XYTCTS:                      /* SET TERMINAL TRANSMIT-TIMEOUT */
4870         y = cmnum("Maximum seconds to allow CTS off during CONNECT",
4871                   "5",10,&x,xxstring);
4872         return(setnum(&tt_ctstmo,x,y,10000));
4873
4874       case XYTCPG: {                    /* SET TERMINAL CODE-PAGE */
4875         int i;
4876         int cp = -1;
4877         y = cmnum("PC code page to use during terminal emulation",
4878                   ckitoa(os2getcp()),10,&x,xxstring);
4879         if ((x = setnum(&cp,x,y,11000)) < 0) return(x);
4880         if (os2setcp(cp) != 1) {
4881 #ifdef NT
4882             if (isWin95())
4883               printf(
4884                  "Sorry, Windows 95 does not support code page switching\n");
4885             else
4886 #endif /* NT */
4887               printf(
4888                  "Sorry, %d is not a valid code page for this system.\n",cp);
4889             return(-9);
4890         }
4891     /* Force the terminal character-sets conversions to be updated */
4892         for ( i = 0; i < 4; i++ )
4893           G[i].init = TRUE;
4894         return(1);
4895     }
4896
4897       case XYTPAC:                      /* SET TERMINAL OUTPUT-PACING */
4898         y = cmnum(
4899            "Pause between sending each character during CONNECT, milliseconds",
4900                   "-1",10,&x,xxstring);
4901         return(setnum(&tt_pacing,x,y,10000));
4902
4903 #ifdef OS2MOUSE
4904       case XYTMOU: {                    /* SET TERMINAL MOUSE */
4905           int old_mou = tt_mouse;
4906           if ((x = seton(&tt_mouse)) < 0)
4907             return(x);
4908           if (tt_mouse != old_mou)
4909             if (tt_mouse)
4910               os2_mouseon();
4911             else
4912               os2_mouseoff();
4913           return(1);
4914       }
4915 #endif /* OS2MOUSE */
4916 #endif /* OS2 */
4917
4918       case XYTWID: {
4919           if ((y = cmnum(
4920 #ifdef OS2
4921                          "number of columns in display window during CONNECT",
4922 #else
4923                          "number of columns on your screen",
4924 #endif /* OS2 */
4925                          "80",10,&x,xxstring)) < 0)
4926             return(y);
4927           if ((y = cmcfm()) < 0) return(y);
4928 #ifdef OS2
4929           return(success = os2_settermwidth(x));
4930 #else  /* Not OS/2 */
4931           tt_cols = x;
4932           return(success = 1);
4933 #endif /* OS2 */
4934       }
4935
4936       case XYTHIG:
4937         if ((y = cmnum(
4938 #ifdef OS2
4939  "number of rows in display window during CONNECT, not including status line",
4940  tt_status[VTERM]?"24":"25",
4941 #else
4942  "24","number of rows on your screen",
4943 #endif /* OS2 */
4944                        10,&x,xxstring)) < 0)
4945           return(y);
4946         if ((y = cmcfm()) < 0) return(y);
4947
4948 #ifdef OS2
4949         return (success = os2_settermheight(x));
4950 #else  /* Not OS/2 */
4951         tt_rows = x;
4952         return(success = 1);
4953 #endif /* OS2 */
4954
4955 #ifdef OS2
4956       case XYTPRN: {                    /* Print Mode */
4957           extern bool xprint, aprint, cprint, uprint;
4958           if ((y = cmkey(prnmtab,nprnmtab,"","off", xxstring)) < 0) return(y);
4959           if ((x = cmcfm()) < 0) return(x);
4960           switch (y) {
4961             case 0:
4962               if (cprint || uprint || aprint || xprint)
4963                 printeroff();
4964               cprint = xprint = uprint = 0;
4965               setaprint(0);
4966               break;
4967             case 1:
4968               if (!(cprint || uprint || aprint || xprint))
4969                 printeron();
4970               setaprint(1);
4971               cprint = xprint = uprint = 0;
4972               break;
4973             case 2:
4974               if (!(cprint || uprint || aprint || xprint))
4975                 printeron();
4976               cprint = 1;
4977               setaprint(0);
4978               xprint = uprint = 0;
4979               break;
4980             case 3:
4981               if (!(cprint || uprint || aprint || xprint))
4982                 printeron();
4983               uprint = 1;
4984               setaprint(0);
4985               xprint = cprint = 0;
4986               break;
4987           }
4988           return(1);
4989       }
4990 #else
4991 #ifdef XPRINT
4992       case XYTPRN: {
4993           extern int tt_print;
4994           if ((x = seton(&tt_print)) < 0)
4995             return(x);
4996           return(success = 1);
4997       }
4998 #endif /* XPRINT */
4999 #endif /* OS2 */
5000
5001 #ifdef OS2
5002       case XYTSCNM: {
5003           extern int decscnm, decscnm_usr;
5004           if ((y = cmkey(normrev,4,"",
5005                          decscnm_usr?"reverse":"normal",
5006                          xxstring)
5007                ) < 0)
5008             return(y);
5009           if ((x = cmcfm()) < 0) return(x);
5010           decscnm_usr = y;
5011           if (decscnm != decscnm_usr)
5012             flipscreen(VTERM);
5013           return(1);
5014     }
5015     case XYTOPTI:
5016         if ((y = cmkey(onoff,2,"",tt_diff_upd?"on":"off",
5017                         xxstring)) < 0) return(y);
5018         if ((x = cmcfm()) < 0) return(x);
5019         tt_diff_upd = y;
5020         return(1);
5021     case XYTUPD: {
5022         int mode, delay;
5023         if ((mode = cmkey(scrnupd,nscrnupd,"","fast",xxstring)) < 0) {
5024             return(mode);
5025         } else {
5026             y = cmnum(
5027             "Pause between FAST screen updates in CONNECT mode, milliseconds",
5028                       "100",10,&x,xxstring
5029                       );
5030             if (x < 0 || x > 1000 ) {
5031                 printf(
5032             "\n?The update rate must be between 0 and 1000 milliseconds.\n"
5033                        );
5034                 return(success = 0);
5035             }
5036             if ((y = cmcfm()) < 0) return(y);
5037
5038             updmode = tt_updmode = mode;
5039             return(setnum(&tt_update,x,y,10000));
5040         }
5041     }
5042     case XYTCTRL:
5043           if ((x = cmkey(termctrl,ntermctrl,"","7",xxstring)) < 0) {
5044               return(x);
5045           } else {
5046               if ((y = cmcfm()) < 0)
5047                   return(y);
5048               switch ( x ) {
5049               case 8:
5050                   send_c1 = send_c1_usr = TRUE;
5051                   break;
5052               case 7:
5053               default:
5054                   send_c1 = send_c1_usr = FALSE;
5055                   break;
5056               }
5057           }
5058           return(success = TRUE);
5059           break;
5060
5061 #ifdef PCFONTS
5062       case XYTFON:
5063         if ( !IsOS2FullScreen() ) {
5064             printf(
5065         "\n?SET TERMINAL FONT is only supported in Full Screen sessions.\n");
5066             return(success = FALSE);
5067         }
5068
5069         if ((x = cmkey(term_font,ntermfont,"","default",xxstring)) < 0) {
5070             return(x);
5071         } else {
5072             if ((y = cmcfm()) < 0) return(y);
5073             if ( !os2LoadPCFonts() ) {
5074                 tt_font = x;
5075                 return(success = TRUE);
5076             } else {
5077                 printf(
5078       "\n?PCFONTS.DLL is not available in CKERMIT executable directory.\n");
5079                 return(success = FALSE);
5080             }
5081         }
5082         break;
5083 #else /* PCFONTS */
5084 #ifdef NT
5085 #ifdef KUI
5086     case XYTFON:
5087         return(setguifont());           /* ckuus3.c */
5088 #endif /* KUI */
5089 #endif /* NT */
5090 #endif /* PCFONTS */
5091
5092       case XYTVCH: {
5093           extern int pheight, marginbot, cmd_rows, cmd_cols;
5094           if ((x = cmkey(tvctab,ntvctab,"",isWin95()?"win95-safe":"enabled",
5095                          xxstring)) < 0)
5096             return(x);
5097           if ((y = cmcfm()) < 0) return(y);
5098 #ifndef KUI
5099           if (x != tt_modechg) {
5100               switch (x) {
5101                 case TVC_DIS:
5102                   /* When disabled the heights of all of the virtual screens */
5103                   /* must be equal to the physical height of the console     */
5104                   /* window and may not be changed.                          */
5105                   /* The width of the window may not be altered.             */
5106                   tt_modechg = TVC_ENA;                 /* Temporary */
5107                   if (marginbot > pheight-(tt_status[VTERM]?1:0))
5108                     marginbot = pheight-(tt_status[VTERM]?1:0);
5109                   tt_szchng[VCMD] = 1 ;
5110                   tt_rows[VCMD] = pheight;
5111                   VscrnInit(VCMD);
5112                   SetCols(VCMD);
5113                   cmd_rows = y;
5114
5115                   tt_szchng[VTERM] = 2 ;
5116                   tt_rows[VTERM] = pheight - (tt_status[VTERM]?1:0);
5117                   VscrnInit(VTERM);
5118
5119                   break;
5120
5121                 case TVC_ENA:
5122                   /* When enabled the physical height of the console windows */
5123                   /* should be adjusted to the height of the virtual screen  */
5124                   /* The width may be set to anything.                       */
5125                   /* nothing to do                                           */
5126                   break;
5127
5128               case TVC_W95:
5129                   /* Win95-safe mode allows the physical height to change    */
5130                   /* but restricts it to a width of 80 and a height equal to */
5131                   /* 25, 43, or 50.  Must be adjusted now.                   */
5132                   /* The virtual heights must be equal to the above.         */
5133                   if (pheight != 25 && pheight != 43 && pheight != 50) {
5134                       if (pheight < 25)
5135                         y = 25;
5136                       else if (pheight < 43)
5137                         y = 43;
5138                       else
5139                         y = 50;
5140                   } else
5141                     y = pheight;
5142
5143                   tt_modechg = TVC_ENA; /* Temporary */
5144
5145                   tt_szchng[VCMD] = 1;
5146                   tt_rows[VCMD] = y;
5147                   tt_cols[VCMD] = 80;
5148                   VscrnInit(VCMD);
5149                   SetCols(VCMD);
5150                   cmd_rows = y;
5151                   cmd_cols = 80;
5152
5153                   marginbot = y-(tt_status[VTERM]?1:0);
5154                   tt_szchng[VTERM] = 2;
5155                   tt_rows[VTERM] = y - (tt_status[VTERM]?1:0);
5156                   tt_cols[VTERM] = 80;
5157                   VscrnInit(VTERM);
5158                   break;
5159               }
5160               tt_modechg = x;
5161           }
5162           return(success = 1);
5163 #else
5164           return(success = 0);
5165 #endif /* KUI */
5166       }
5167       case XYTSTAT: {
5168           extern int marginbot;
5169           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5170           if ((x = cmcfm()) < 0) return(x);
5171           if (y != tt_status[VTERM] || y != tt_status_usr[VTERM]) {
5172               /* Might need to fixup the margins */
5173               if ( marginbot == VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) )
5174                 if (y) {
5175                     marginbot--;
5176                 } else {
5177                     marginbot++;
5178                 }
5179               tt_status_usr[VTERM] = tt_status[VTERM] = y;
5180               if (y) {
5181                     tt_szchng[VTERM] = 2;
5182                     tt_rows[VTERM]--;
5183                     VscrnInit(VTERM);  /* Height set here */
5184 #ifdef TNCODE
5185                     if (TELOPT_ME(TELOPT_NAWS))
5186                       tn_snaws();
5187 #endif /* TNCODE */
5188 #ifdef RLOGCODE
5189                     if (TELOPT_ME(TELOPT_NAWS))
5190                       rlog_naws();
5191 #endif /* RLOGCODE */
5192 #ifdef SSHBUILTIN
5193                     if (TELOPT_ME(TELOPT_NAWS))
5194                       ssh_snaws();
5195 #endif /* SSHBUILTIN */
5196               } else {
5197                   tt_szchng[VTERM] = 1;
5198                   tt_rows[VTERM]++;
5199                   VscrnInit(VTERM);     /* Height set here */
5200 #ifdef TNCODE
5201                   if (TELOPT_ME(TELOPT_NAWS))
5202                     tn_snaws();
5203 #endif /* TNCODE */
5204 #ifdef RLOGCODE
5205                   if (TELOPT_ME(TELOPT_NAWS))
5206                     rlog_naws();
5207 #endif /* RLOGCODE */
5208 #ifdef SSHBUILTIN
5209                   if (TELOPT_ME(TELOPT_NAWS))
5210                     ssh_snaws();
5211 #endif /* SSHBUILTIN */
5212               }
5213           }
5214           return(1);
5215       }
5216 #endif /* OS2 */
5217
5218 #ifdef NT
5219       case XYTATTBUG:
5220         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5221         if ((x = cmcfm()) < 0) return(x);
5222         tt_attr_bug = y;
5223         return(1);
5224 #endif /* NT */
5225
5226 #ifdef OS2
5227       case XYTSGRC:
5228         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5229         if ((x = cmcfm()) < 0) return(x);
5230         sgrcolors = y;
5231         return(1);
5232
5233       case XYTSEND:
5234           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5235           if ((x = cmcfm()) < 0) return(x);
5236           tt_senddata = y;
5237           return(1);
5238
5239       case XYTSEOB:
5240           if ((y = cmkey(ttyseobtab,2,"","us_cr",xxstring)) < 0) return(y);
5241           if ((x = cmcfm()) < 0) return(x);
5242           wy_blockend = y;
5243           return(1);
5244
5245       case XYTURLHI: {
5246           int done = 0, attr = VT_CHAR_ATTR_NORMAL;
5247
5248           if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
5249             return(x);
5250           if (x) {
5251               z = 0;
5252               while (!done) {
5253                   if ((y = cmkey(ttyprotab,nprotect,"",
5254                                  z?"done":"reverse",xxstring)) < 0)
5255                     return(y);
5256                   switch (y) {
5257                     case TTATTDONE:
5258                       done = TRUE;
5259                       break;
5260                     case TTATTBLI:
5261                       attr |= VT_CHAR_ATTR_BLINK;
5262                       break;
5263                     case TTATTREV:
5264                       attr |= VT_CHAR_ATTR_REVERSE;
5265                       break;
5266                     case TTATTITA:
5267                       attr |= VT_CHAR_ATTR_ITALIC;
5268                       break;
5269                     case TTATTUND:
5270                       attr |= VT_CHAR_ATTR_UNDERLINE;
5271                       break;
5272                     case TTATTBLD:
5273                       attr |= VT_CHAR_ATTR_BOLD;
5274                       break;
5275                     case TTATTDIM:
5276                       attr |= VT_CHAR_ATTR_DIM;
5277                       break;
5278                     case TTATTINV:
5279                       attr |= VT_CHAR_ATTR_INVISIBLE;
5280                       break;
5281                     case TTATTNOR:
5282                       break;
5283                   }
5284                   z = 1;                /* One attribute has been chosen */
5285               }
5286           }
5287           if ((z = cmcfm()) < 0) return(z);
5288           seturlhl(x);
5289           if (x)
5290             tt_url_hilite_attr = attr;
5291           return(1);
5292       }
5293       case XYTATTR:
5294         if ((x = cmkey(ttyattrtab,nattrib,"","underline",xxstring)) < 0)
5295           return(x);
5296         switch (x) {
5297           case TTATTBLI:
5298             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5299             if ((x = cmcfm()) < 0) return(x);
5300             trueblink = y;
5301 #ifndef KUI
5302             if ( !trueblink && trueunderline ) {
5303                 trueunderline = 0;
5304                 printf("Warning: Underline being simulated by color.\n");
5305             }
5306
5307 #endif /* KUI */
5308             break;
5309
5310           case TTATTDIM:
5311             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5312             if ((x = cmcfm()) < 0) return(x);
5313             truedim = y;
5314             break;
5315
5316           case TTATTREV:
5317             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5318             if ((x = cmcfm()) < 0) return(x);
5319             truereverse = y;
5320             break;
5321
5322           case TTATTUND:
5323             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5324             if ((x = cmcfm()) < 0) return(x);
5325             trueunderline = y;
5326 #ifndef KUI
5327             if (!trueblink && trueunderline) {
5328                 trueblink = 1;
5329                 printf("Warning: True blink mode is active.\n");
5330             }
5331 #endif /* KUI */
5332             break;
5333
5334           case TTATTITA:
5335               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5336               if ((x = cmcfm()) < 0) return(x);
5337               trueitalic = y;
5338             break;
5339
5340           case TTATTPRO: {      /* Set default Protected Character attribute */
5341               extern vtattrib WPattrib;    /* current WP Mode Attrib */
5342               extern vtattrib defWPattrib; /* default WP Mode Attrib */
5343               vtattrib wpa = {0,0,0,0,0,1,0,0,0,0,0};   /* Protected */
5344               int done = 0;
5345
5346               x = 0;
5347               while (!done) {
5348                   if ((y = cmkey(ttyprotab,nprotect,"",
5349                                  x?"done":"dim",xxstring)) < 0)
5350                     return(y);
5351                   switch (y) {
5352                     case TTATTNOR:
5353                       break;
5354                     case TTATTBLI:      /* Blinking doesn't work */
5355                       wpa.blinking = TRUE;
5356                       break;
5357                     case TTATTREV:
5358                       wpa.reversed = TRUE;
5359                       break;
5360                     case TTATTITA:
5361                       wpa.italic = TRUE;
5362                       break;
5363                     case TTATTUND:
5364                       wpa.underlined = TRUE;
5365                       break;
5366                     case TTATTBLD:
5367                       wpa.bold = TRUE;
5368                       break;
5369                     case TTATTDIM:
5370                       wpa.dim = TRUE;
5371                       break;
5372                     case TTATTINV:
5373                       wpa.invisible = TRUE ;
5374                       break;
5375                     case TTATTDONE:
5376                       done = TRUE;
5377                       break;
5378                   }
5379                   x = 1;                /* One attribute has been chosen */
5380               }
5381               if ((x = cmcfm()) < 0) return(x);
5382               WPattrib = defWPattrib = wpa;
5383               break;
5384           }
5385         }
5386         return(1);
5387
5388       case XYTKEY: {                    /* SET TERMINAL KEY */
5389           int t, x, y;
5390           int clear = 0, deflt = 0;
5391           int confirmed = 0;
5392           int flag = 0;
5393           int kc = -1;                  /* Key code */
5394           int litstr = 0;               /* Literal String? */
5395           char *s = NULL;               /* Key binding */
5396 #ifndef NOKVERBS
5397           char *p = NULL;               /* Worker */
5398 #endif /* NOKVERBS */
5399           con_event defevt;
5400           extern int os2gks;
5401           extern int mskkeys;
5402           extern int initvik;
5403           struct FDB kw,sw,nu,cm;
5404
5405           defevt.type = error;
5406
5407           if ((t = cmkey(ttkeytab,nttkey,"","",xxstring)) < 0)
5408             return(t);
5409           cmfdbi(&nu,                   /* First FDB - command switches */
5410                  _CMNUM,                /* fcode */
5411                  "/literal, keycode, or action",
5412                  "",                    /* default */
5413                  "",                    /* addtl string data */
5414                  10,                    /* addtl numeric data 1: radix */
5415                  0,                     /* addtl numeric data 2: 0 */
5416                  xxstring,              /* Processing function */
5417                  NULL,                  /* Keyword table */
5418                  &sw                    /* Pointer to next FDB */
5419                  );                     /*  */
5420           cmfdbi(&sw,                   /* Second FDB - switches */
5421                  _CMKEY,                /* fcode */
5422                  "",
5423                  "",                    /* default */
5424                  "",                    /* addtl string data */
5425                  nstrmswitab,           /* addtl numeric data 1: tbl size */
5426                  4,                     /* addtl numeric data 2: 4 = cmswi */
5427                  xxstring,              /* Processing function */
5428                  strmswitab,            /* Keyword table */
5429                  &kw                    /* Pointer to next FDB */
5430                  );
5431           cmfdbi(&kw,                   /* Third FDB - command switches */
5432                  _CMKEY,                /* fcode */
5433                  "/literal, keycode, or action",
5434                  "",                    /* default */
5435                  "",                    /* addtl string data */
5436                  nstrmkeytab,           /* addtl numeric data 1: tbl size */
5437                  0,                     /* addtl numeric data 2 */
5438                  xxstring,              /* Processing function */
5439                  strmkeytab,            /* Keyword table */
5440                  &cm                    /* Pointer to next FDB */
5441                  );
5442           cmfdbi(&cm,                   /* Final FDB - Confirmation */
5443                  _CMCFM,                /* fcode */
5444                  "",
5445                  "",                    /* default */
5446                  "",                    /* addtl string data */
5447                  0,                     /* addtl numeric data 1: tbl size */
5448                  0,                     /* addtl numeric data 2: 4 = cmswi */
5449                  xxstring,              /* Processing function */
5450                  NULL,                  /* Keyword table */
5451                  NULL                   /* Pointer to next FDB */
5452                  );
5453           while (kc < 0) {
5454               x = cmfdb(&nu);           /* Parse something */
5455               if (x < 0)
5456                 return(x);
5457
5458               switch (cmresult.fcode) {
5459                 case _CMCFM:
5460                   printf(" Press key to be defined: ");
5461                   conbin((char)escape); /* Put terminal in binary mode */
5462                   os2gks = 0;           /* Turn off Kverb preprocessing */
5463                   kc = congks(0);       /* Get character or scan code */
5464                   os2gks = 1;           /* Turn on Kverb preprocessing */
5465                   concb((char)escape);  /* Restore terminal to cbreak mode */
5466                   if (kc < 0) {         /* Check for error */
5467                       printf("?Error reading key\n");
5468                       return(0);
5469                   }
5470                   shokeycode(kc,t);     /* Show current definition */
5471                   flag = 1;             /* Remember it's a multiline command */
5472                   break;
5473                 case _CMNUM:
5474                   kc = cmresult.nresult;
5475                   break;
5476                 case _CMKEY:
5477                   if (cmresult.fdbaddr == &sw) { /* Switch */
5478                       if (cmresult.nresult == 0)
5479                         litstr = 1;
5480                   } else if (cmresult.fdbaddr == &kw) { /* Keyword */
5481                       if (cmresult.nresult == 0)
5482                         clear = 1;
5483                       else
5484                         deflt = 1;
5485                       if ((x = cmcfm()) < 0)
5486                         return(x);
5487                       if (clear)
5488                         clearkeymap(t);
5489                       else if (deflt)
5490                         defaultkeymap(t);
5491                       initvik = 1;
5492                       return(1);
5493                   }
5494               }
5495           }
5496
5497     /* Normal SET TERMINAL KEY <terminal> <scancode> <value> command... */
5498
5499           if (mskkeys)
5500             kc = msktock(kc);
5501
5502           if (kc < 0 || kc >= KMSIZE) {
5503               printf("?key code must be between 0 and %d\n", KMSIZE - 1);
5504               return(-9);
5505           }
5506           if (kc == escape) {
5507               printf("Sorry, %d is the CONNECT-mode escape character\n",kc);
5508               return(-9);
5509           }
5510           wideresult = -1;
5511           if (flag) {
5512               cmsavp(psave,PROMPTL);
5513               cmsetp(" Enter new definition: ");
5514               cmini(ckxech);
5515           }
5516         def_again:
5517           if (flag) prompt(NULL);
5518           if ((y = cmtxt("key definition,\n\
5519  or Ctrl-C to cancel this command,\n\
5520  or Enter to restore default definition",
5521                          "",&s,NULL)) < 0) {
5522               if (flag)                 /* Handle parse errors */
5523                 goto def_again;
5524               else
5525                 return(y);
5526           }
5527           s = brstrip(s);
5528 #ifndef NOKVERBS
5529           p = s;                        /* Save this place */
5530 #endif /* NOKVERBS */
5531 /*
5532   If the definition included any \Kverbs, quote the backslash so the \Kverb
5533   will still be in the definition when the key is pressed.  We don't do this
5534   in zzstring(), because \Kverbs are valid only in this context and nowhere
5535   else.
5536
5537   We use this code active for all versions that support SET KEY, even if they
5538   don't support \Kverbs, because otherwise \K would behave differently for
5539   different versions.
5540 */
5541           for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
5542               if ((x > 0) &&
5543                   (s[x] == 'K' || s[x] == 'k')
5544                   ) {                   /* Have K */
5545
5546                   if ((x == 1 && s[x-1] == CMDQ) ||
5547                       (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
5548                       line[y++] = CMDQ; /* Make it \\K */
5549                   }
5550                   if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
5551                       line[y-1] = CMDQ; /* Have \{K */
5552                       line[y++] = '{';  /* Make it \\{K */
5553                   }
5554               }
5555               line[y] = s[x];
5556           }
5557           line[y++] = NUL;              /* Terminate */
5558           s = line + y + 1;             /* Point to after it */
5559           x = LINBUFSIZ - (int) strlen(line) - 1; /* Get remaining space */
5560           if ((x < (LINBUFSIZ / 2)) ||
5561               (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
5562               printf("?Key definition too long\n");
5563               if (flag) cmsetp(psave);
5564               return(-9);
5565           }
5566           s = line + y + 1;             /* Point to result. */
5567
5568 #ifndef NOKVERBS
5569 /*
5570   Special case: see if the definition starts with a \Kverb.
5571   If it does, point to it with p, otherwise set p to NULL.
5572 */
5573           p = s;
5574           if (*p++ == CMDQ) {
5575               if (*p == '{') p++;
5576               p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
5577           }
5578 #endif /* NOKVERBS */
5579
5580           switch (strlen(s)) {          /* Action depends on length */
5581             case 0:                     /* Clear individual key def */
5582               deletekeymap(t,kc);
5583               break;
5584             case 1:
5585               if (!litstr) {
5586                   defevt.type = key;    /* Single character */
5587                   defevt.key.scancode = *s;
5588                   break;
5589               }
5590             default:                    /* Character string */
5591 #ifndef NOKVERBS
5592               if (p) {
5593                   y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
5594                   /* Need exact match */
5595                   debug(F101,"set key kverb lookup",0,y);
5596                   if (y > -1) {
5597                       defevt.type = kverb;
5598                       defevt.kverb.id = y;
5599                       break;
5600                   }
5601               }
5602 #endif /* NOKVERBS */
5603               if (litstr) {
5604                   defevt.type = literal;
5605                   defevt.literal.string = (char *) malloc(strlen(s)+1);
5606                   if (defevt.literal.string)
5607                     strcpy(defevt.literal.string, s); /* safe */
5608               } else {
5609                   defevt.type = macro;
5610                   defevt.macro.string = (char *) malloc(strlen(s)+1);
5611                   if (defevt.macro.string)
5612                     strcpy(defevt.macro.string, s); /* safe */
5613               }
5614               break;
5615           }
5616           insertkeymap(t, kc, defevt);
5617           if (flag)
5618             cmsetp(psave);
5619           initvik = 1;                  /* Update VIK table */
5620           return(1);
5621       }
5622
5623 #ifdef PCTERM
5624       case XYTPCTERM:                   /* PCTERM Keyboard Mode */
5625         if ((x = seton(&tt_pcterm)) < 0) return(x);
5626         return(success = 1);
5627 #endif /* PCTERM */
5628 #endif /* OS2 */
5629
5630 #ifdef CK_TRIGGER
5631       case XYTRIGGER:
5632         if ((y = cmtxt("String to trigger automatic return to command mode",
5633                        "",&s,xxstring)) < 0)
5634           return(y);
5635         makelist(s,tt_trigger,TRIGGERS);
5636         return(1);
5637 #endif /* CK_TRIGGER */
5638
5639 #ifdef OS2
5640       case XYTSAC:
5641         if ((y = cmnum("ASCII value to use for spacing attributes",
5642                        "32",10,&x,xxstring)) < 0)
5643           return(y);
5644         if ((y = cmcfm()) < 0) return(y);
5645         tt_sac = x;
5646         return(success = 1);
5647
5648       case XYTKBDGL: {      /* SET TERM KBD-FOLLOWS-GL/GR */
5649           extern int tt_kb_glgr;        /* from ckoco3.c */
5650           if ((x = seton(&tt_kb_glgr)) < 0)
5651               return(x);
5652           return(success = 1);
5653       }
5654 #ifndef NOCSETS
5655       case XYTVTLNG:        /* SET TERM DEC-LANGUAGE */
5656         if ((y = cmkey(vtlangtab,nvtlangtab,"VT language",
5657                        IS97801(tt_type_mode)?"german":"north-american",
5658                        xxstring)) < 0)
5659           return(y);
5660         if ((x = cmcfm()) < 0) return(x);
5661
5662         /* A real VT terminal would use the language to set the   */
5663         /* default keyboard language for both 8-bit multinational */
5664         /* and 7-bit national modes.  For 8-bit mode it would     */
5665         /* set the terminal character-set to the ISO set if it    */
5666         /* is not already set.                                    */
5667         /* Latin-1 can be replaced by DEC Multinational           */
5668         switch (y) {
5669           case VTL_NORTH_AM:  /* North American */
5670             /* Multinational: Latin-1   */
5671             /* National:      US_ASCII  */
5672             dec_lang = y;
5673             dec_nrc = TX_ASCII;
5674             dec_kbd = TX_8859_1;
5675             break;
5676           case VTL_BRITISH :
5677             /* Multinational: Latin-1   */
5678             /* National:      UK_ASCII  */
5679             dec_lang = y;
5680             dec_nrc = TX_BRITISH;
5681             dec_kbd = TX_8859_1;
5682             break;
5683           case VTL_FRENCH  :
5684           case VTL_BELGIAN :
5685           case VTL_CANADIAN:
5686             /* Multinational: Latin-1   */
5687             /* National:      FR_ASCII  */
5688             dec_lang = y;
5689             dec_nrc = TX_FRENCH;
5690             dec_kbd = TX_8859_1;
5691             break;
5692           case VTL_FR_CAN  :
5693             /* Multinational: Latin-1   */
5694             /* National:      FC_ASCII  */
5695             dec_lang = y;
5696             dec_nrc = TX_CN_FRENCH;
5697             dec_kbd = TX_8859_1;
5698             break;
5699           case VTL_DANISH  :
5700           case VTL_NORWEGIA:
5701             /* Multinational: Latin-1   */
5702             /* National:      NO_ASCII  */
5703             dec_lang = y;
5704             dec_nrc = TX_NORWEGIAN;
5705             dec_kbd = TX_8859_1;
5706             break;
5707           case VTL_FINNISH :
5708             /* Multinational: Latin-1   */
5709             /* National:      FI_ASCII  */
5710             dec_lang = y;
5711             dec_nrc = TX_FINNISH;
5712             dec_kbd = TX_8859_1;
5713             break;
5714           case VTL_GERMAN  :
5715             /* Multinational: Latin-1   */
5716             /* National:      GR_ASCII  */
5717             dec_lang = y;
5718             dec_nrc = TX_GERMAN;
5719             dec_kbd = TX_8859_1;
5720             break;
5721           case VTL_DUTCH   :
5722             /* Multinational: Latin-1   */
5723             /* National:      DU_ASCII  */
5724             dec_lang = y;
5725             dec_nrc = TX_DUTCH;
5726             dec_kbd = TX_8859_1;
5727             break;
5728           case VTL_ITALIAN :
5729             /* Multinational: Latin-1   */
5730             /* National:      IT_ASCII  */
5731             dec_lang = y;
5732             dec_nrc = TX_ITALIAN;
5733             dec_kbd = TX_8859_1;
5734             break;
5735           case VTL_SW_FR   :
5736           case VTL_SW_GR   :
5737             /* Multinational: Latin-1   */
5738             /* National:      CH_ASCII  */
5739             dec_lang = y;
5740             dec_nrc = TX_SWISS;
5741             dec_kbd = TX_8859_1;
5742             break;
5743           case VTL_SWEDISH :
5744             /* Multinational: Latin-1   */
5745             /* National:      SW_ASCII  */
5746             dec_lang = y;
5747             dec_nrc = TX_SWEDISH;
5748             dec_kbd = TX_8859_1;
5749             break;
5750           case VTL_SPANISH :
5751             /* Multinational: Latin-1   */
5752             /* National:      SP_ASCII  */
5753             dec_lang = y;
5754             dec_nrc = TX_SPANISH;
5755             dec_kbd = TX_8859_1;
5756             break;
5757           case VTL_PORTUGES:
5758             /* Multinational: Latin-1   */
5759             /* National:      Portugese ASCII  */
5760             dec_lang = y;
5761             dec_nrc = TX_PORTUGUESE;
5762             dec_kbd = TX_8859_1;
5763             break;
5764           case VTL_HEBREW  :
5765             /* Multinational: Latin-Hebrew / DEC-Hebrew  */
5766             /* National:      DEC 7-bit Hebrew  */
5767             dec_lang = y;
5768             dec_nrc = TX_HE7;
5769             dec_kbd = TX_8859_8;
5770             break;
5771           case VTL_GREEK   :
5772             /* Multinational: Latin-Greek / DEC-Greek   */
5773             /* National:      DEC Greek NRC             */
5774             /* is ELOT927 equivalent to DEC Greek????   */
5775             dec_lang = y;
5776             dec_nrc = TX_ELOT927;
5777             dec_kbd = TX_8859_7;
5778             break;
5779 #ifdef COMMENT
5780           case VTL_TURK_Q  :
5781           case VTL_TURK_F  :
5782             /* Multinational: Latin-Turkish / DEC-Turkish   */
5783             /* National:      DEC 7-bit Turkish             */
5784             break;
5785 #endif /* COMMENT */
5786           case VTL_HUNGARIA:
5787             /* Multinational: Latin-2   */
5788             /* National:      no national mode  */
5789             dec_lang = y;
5790             dec_nrc = TX_HUNGARIAN;
5791             dec_kbd = TX_8859_2;
5792             break;
5793           case VTL_SLOVAK  :
5794           case VTL_CZECH   :
5795           case VTL_POLISH  :
5796           case VTL_ROMANIAN:
5797             /* Multinational: Latin-2   */
5798             /* National:      no national mode  */
5799             dec_lang = y;
5800             dec_nrc = TX_ASCII;
5801             dec_kbd = TX_8859_2;
5802             break;
5803           case VTL_RUSSIAN :
5804             /* Multinational: Latin-Cyrillic / KOI-8   */
5805             /* National:      DEC Russian NRC  */
5806             dec_lang = y;
5807             dec_nrc = TX_KOI7;
5808             dec_kbd = TX_8859_5;
5809             break;
5810           case VTL_LATIN_AM:
5811             /* Multinational: not listed in table   */
5812             /* National:      not listed in table  */
5813             dec_lang = y;
5814             dec_nrc = TX_ASCII;
5815             dec_kbd = TX_8859_1;
5816             break;
5817 #ifdef COMMENT
5818           case VTL_SCS     :
5819             /* Multinational: Latin-2   */
5820             /* National:      SCS NRC   */
5821             break;
5822 #endif /* COMMENT */
5823           default:
5824             return(success = 0);
5825         }
5826         if (IS97801(tt_type_mode)) {
5827             SNI_bitmode(cmask == 0377 ? 8 : 7);
5828         }
5829         return(success = 1);
5830 #endif /* NOCSETS */
5831
5832       case XYTVTNRC: {                  /* SET TERM DEC-NRC-MODE */
5833           extern int decnrcm_usr, decnrcm;        /* from ckoco3.c */
5834           if ((x = seton(&decnrcm_usr)) < 0)
5835             return(x);
5836           decnrcm = decnrcm_usr;
5837           return(success = 1);
5838       }
5839       case XYTSNIPM: {                  /* SET TERM SNI-PAGEMODE */
5840           extern int sni_pagemode, sni_pagemode_usr;
5841           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5842           if ((x = cmcfm()) < 0) return(x);
5843           sni_pagemode_usr = sni_pagemode = y;
5844           return(success = 1);
5845       }
5846       case XYTSNISM: {                  /* SET TERM SNI-SCROLLMODE */
5847           extern int sni_scroll_mode, sni_scroll_mode_usr;
5848           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5849           if ((x = cmcfm()) < 0) return(x);
5850           sni_scroll_mode_usr = sni_scroll_mode = y;
5851           return(success = 1);
5852       }
5853       case XYTSNICC: {  /* SET TERM SNI-CH.CODE */
5854           extern int sni_chcode_usr;
5855           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
5856           if ((x = cmcfm()) < 0) return(x);
5857           sni_chcode_usr = y;
5858           SNI_chcode(y);
5859           return(success = 1);
5860       }
5861       case XYTSNIFV: {  /* SET TERM SNI-FIRMWARE-VERSIONS */
5862           extern CHAR sni_kbd_firmware[], sni_term_firmware[];
5863           CHAR kbd[7],term[7];
5864
5865           if ((x = cmfld("Keyboard Firmware Version",sni_kbd_firmware,
5866                          &s, xxstring)) < 0)
5867             return(x);
5868           if ((int)strlen(s) != 6) {
5869               printf("?Sorry - the firmware version must be 6 digits long\n");
5870               return(-9);
5871           }
5872           for (i = 0; i < 6; i++) {
5873               if (!isdigit(s[i])) {
5874    printf("?Sorry - the firmware version can only contain digits [0-9]\n");
5875                   return(-9);
5876               }
5877           }
5878           ckstrncpy(kbd,s,7);
5879
5880           if ((x = cmfld("Terminal Firmware Version",sni_term_firmware,
5881                          &s, xxstring)) < 0)
5882             return(x);
5883           if ((int)strlen(s) != 6) {
5884               printf("?Sorry - the firmware version must be 6 digits long\n");
5885               return(-9);
5886           }
5887           for (i = 0; i < 6; i++) {
5888               if (!isdigit(s[i])) {
5889    printf("?Sorry - the firmware version can only contain digits [0-9]\n");
5890                    return(-9);
5891               }
5892           }
5893           ckstrncpy(term,s,7);
5894           if ((x = cmcfm()) < 0) return(x);
5895
5896           ckstrncpy(sni_kbd_firmware,kbd,7);
5897           ckstrncpy(sni_term_firmware,term,7);
5898           return(success = 1);
5899     }
5900
5901     case XYTLSP: {              /* SET TERM LINE-SPACING */
5902         if ((x = cmfld("Line Spacing","1",&s, xxstring)) < 0)
5903           return(x);
5904         if (isfloat(s,0) < 1) {         /* (sets floatval) */
5905             printf("?Integer or floating-point number required\n");
5906             return(-9);
5907         }
5908         if (floatval < 1.0 || floatval > 3.0) {
5909             printf("?Value must within the range 1.0 and 3.0 (inclusive)\n");
5910             return(-9);
5911         }
5912         if ((x = cmcfm()) < 0) return(x);
5913 #ifdef KUI
5914         tt_linespacing[VCMD] = tt_linespacing[VTERM] = floatval;
5915         return(success = 1);
5916 #else /* KUI */
5917         printf("?Sorry, Line-spacing is only supported in K95G.EXE.\n");
5918         return(success = 0);
5919 #endif /* KUI */
5920     }
5921 #endif /* OS2 */
5922
5923       default:                          /* Shouldn't get here. */
5924         return(-2);
5925     }
5926 #endif /* MAC */
5927 #ifdef COMMENT
5928     /*
5929       This was supposed to shut up picky compilers but instead it makes
5930       most compilers complain about "statement not reached".
5931     */
5932     return(-2);
5933 #endif /* COMMENT */
5934 #ifdef OS2
5935     return(-2);
5936 #endif /* OS2 */
5937 }
5938
5939 #ifdef OS2
5940 int
5941 settitle(void) {
5942     extern char usertitle[];
5943     if ((y = cmtxt("title text","",&s,xxstring)) < 0)
5944       return(y);
5945 #ifdef IKSD
5946     if (inserver) {
5947         printf("?Sorry, command disabled.\r\n");
5948         return(success = 0);
5949     }
5950 #endif /* IKSD */
5951     s = brstrip(s);
5952     ckstrncpy(usertitle,s,64);
5953     os2settitle("",1);
5954     return(1);
5955 }
5956
5957 static struct keytab dialertab[] = {    /* K95 Dialer types */
5958     "backspace",        0, 0,
5959     "enter",            1, 0
5960 };
5961 static int ndialer = 2;
5962
5963 int
5964 setdialer(void) {
5965     int t, x, y;
5966     int clear = 0, deflt = 0;
5967     int kc;                             /* Key code */
5968     char *s = NULL;                     /* Key binding */
5969 #ifndef NOKVERBS
5970     char *p = NULL;                     /* Worker */
5971 #endif /* NOKVERBS */
5972     con_event defevt;
5973     extern int os2gks;
5974     extern int mskkeys;
5975     extern int initvik;
5976
5977     defevt.type = error;
5978
5979     if (( x = cmkey(dialertab, ndialer,
5980                     "Kermit-95 dialer work-arounds",
5981                     "", xxstring)) < 0 )
5982       return(x);
5983     switch (x) {
5984       case 0:                           /* Backspace */
5985         kc = 264;
5986         break;
5987       case 1:                           /* Enter */
5988         kc = 269;
5989         break;
5990       default:
5991         printf("Illegal value in setdialer()\n");
5992         return(-9);
5993     }
5994     if ((y = cmtxt("Key definition","",&s,xxstring)) < 0)
5995       return(y);
5996
5997 #ifdef IKSD
5998     if (inserver) {
5999         printf("?Sorry, command disabled.\r\n");
6000         return(success = 0);
6001     }
6002 #endif /* IKSD */
6003     s = brstrip(s);
6004 #ifndef NOKVERBS
6005     p = s;                              /* Save this place */
6006 #endif /* NOKVERBS */
6007 /*
6008   If the definition included any \Kverbs, quote the backslash so the \Kverb
6009   will still be in the definition when the key is pressed.  We don't do this
6010   in zzstring(), because \Kverbs are valid only in this context and nowhere
6011   else.
6012
6013   We use this code active for all versions that support SET KEY, even if they
6014   don't support \Kverbs, because otherwise \K would behave differently for
6015   different versions.
6016 */
6017     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
6018         if ((x > 0) &&
6019             (s[x] == 'K' || s[x] == 'k')
6020             ) {                         /* Have K */
6021
6022             if ((x == 1 && s[x-1] == CMDQ) ||
6023                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
6024                 line[y++] = CMDQ;       /* Make it \\K */
6025             }
6026             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
6027                 line[y-1] = CMDQ;       /* Have \{K */
6028                 line[y++] = '{';        /* Make it \\{K */
6029             }
6030         }
6031         line[y] = s[x];
6032     }
6033     line[y++] = NUL;                    /* Terminate */
6034     s = line + y + 1;                   /* Point to after it */
6035     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
6036     if ((x < (LINBUFSIZ / 2)) ||
6037         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
6038         printf("?Key definition too long\n");
6039         return(-9);
6040     }
6041     s = line + y + 1;                   /* Point to result. */
6042
6043 #ifndef NOKVERBS
6044 /*
6045   Special case: see if the definition starts with a \Kverb.
6046   If it does, point to it with p, otherwise set p to NULL.
6047 */
6048     p = s;
6049     if (*p++ == CMDQ) {
6050         if (*p == '{') p++;
6051         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
6052     }
6053 #endif /* NOKVERBS */
6054
6055     /* Clear the definition for SET KEY */
6056     if (macrotab[kc]) {                 /* Possibly free old macro from key. */
6057         free((char *)macrotab[kc]);
6058         macrotab[kc] = NULL;
6059     }
6060     keymap[kc] = (KEY) kc;
6061
6062     /* Now reprogram the default value for all terminal types */
6063     /* remember to treat Wyse and Televideo terminals special */
6064     /* because of their use of Kverbs for Backspace and Enter */
6065     for (t = 0; t <= TT_MAX; t++) {
6066         if ( ISDG200(t) && kc == 264) {
6067             extern char * udkfkeys[] ;
6068             if (kc == 264) {            /* \Kdgbs */
6069                 if (udkfkeys[83])
6070                   free(udkfkeys[83]);
6071                 udkfkeys[83] = strdup(s);
6072             }
6073         } else if (ISWYSE(t) || ISTVI(t)) {
6074             extern char * udkfkeys[] ;
6075             if (kc == 264) {            /* \Kwybs or \Ktvibs */
6076                 if (udkfkeys[32])
6077                   free(udkfkeys[32]);
6078                 udkfkeys[32] = strdup(s);
6079             }
6080             if (kc == 269) {            /* \Kwyenter and \Kwyreturn */
6081                 if (udkfkeys[39])       /* \Ktvienter and \Ktvireturn */
6082                   free(udkfkeys[39]);
6083                 udkfkeys[39] = strdup(s);
6084                 if (udkfkeys[49])
6085                   free(udkfkeys[49]);
6086                 udkfkeys[49] = strdup(s);
6087             }
6088         } else {
6089             switch (strlen(s)) {        /* Action depends on length */
6090               case 0:                   /* Clear individual key def */
6091                 deletekeymap(t,kc);
6092                 break;
6093               case 1:
6094                 defevt.type = key;      /* Single character */
6095                 defevt.key.scancode = *s;
6096                 break;
6097               default:                  /* Character string */
6098 #ifndef NOKVERBS
6099                 if (p) {
6100                     y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
6101                     /* Exact match req'd */
6102                     debug(F101,"set key kverb lookup",0,y);
6103                     if (y > -1) {
6104                         defevt.type = kverb;
6105                         defevt.kverb.id = y;
6106                         break;
6107                     }
6108                 }
6109 #endif /* NOKVERBS */
6110                 defevt.type = macro;
6111                 defevt.macro.string = (char *) malloc(strlen(s)+1);
6112                 if (defevt.macro.string)
6113                   strcpy(defevt.macro.string, s); /* safe */
6114                 break;
6115             }
6116             insertkeymap( t, kc, defevt ) ;
6117             initvik = 1;                /* Update VIK table */
6118         }
6119     }
6120     return(1);
6121 }
6122 #endif /* OS2 */
6123
6124 #ifdef NT
6125 int
6126 setwin95( void ) {
6127     int x, y, z;
6128
6129     if (( y = cmkey(win95tab, nwin95,
6130                     "Windows 95 specific work-arounds",
6131                     "keyboard-translation",
6132                     xxstring)) < 0 )
6133         return (y);
6134     switch (y) {
6135       case XYWPOPUP:
6136         if ((y = cmkey(onoff,2,"popups are used to prompt the user for data",
6137                        "on",xxstring)) < 0)
6138           return(y);
6139         if ((x = cmcfm()) < 0) return(x);
6140         win95_popup = y;
6141         return(1);
6142
6143       case XYW8_3:
6144         if ((y = cmkey(onoff,2,"8.3 FAT file names","off",xxstring)) < 0)
6145           return(y);
6146         if ((x = cmcfm()) < 0) return(x);
6147         win95_8_3 = y;
6148         return(1);
6149
6150       case XYWSELECT:
6151         if ((y = cmkey(onoff,2,"\"select()\" fails on write","off",
6152              xxstring)) < 0)
6153           return(y);
6154         if ((x = cmcfm()) < 0) return(x);
6155         win95selectbug = y;
6156         return(1);
6157
6158       case XYWAGR:
6159         if ((y = cmkey(onoff,2,"Right-Alt is Alt-Gr","off",xxstring)) < 0)
6160           return(y);
6161         if ((x = cmcfm()) < 0) return(x);
6162         win95altgr = y;
6163         return(1);
6164
6165       case XYWOIO:
6166         if ((y = cmkey(onoff,2,"Use Overlapped I/O","on",xxstring)) < 0)
6167           return(y);
6168         if (y) {
6169             if ((x = cmnum("Maximum number of outstanding I/O requests",
6170                            "10",10,&z,xxstring)) < 0)
6171               return(x);
6172             if (z < 1 || z > 7) {
6173                 printf(
6174 "?Maximum outstanding I/O requests must be between 1 and 7.\n");
6175                 return(-9);
6176             }
6177         } else
6178           z = 1;
6179         if ((x = cmcfm()) < 0) return(x);
6180         owwait = !y;
6181         maxow = maxow_usr = z;
6182         return(1);
6183
6184       case XYWKEY:
6185 #ifndef COMMENT
6186         printf("\n?\"Keyboard-Translation\" is no longer required.\n");
6187         return(-9);
6188 #else /* COMMENT */
6189         if (( z = cmkey(tcstab, ntcs,
6190                         "Keyboard Character Set",
6191                         "latin1-iso",
6192                         xxstring)) < 0)
6193           return (z);
6194         if ((x = cmcfm()) < 0)
6195           return(x);
6196
6197         win95kcsi = z;
6198         win95kl2 = (win95kcsi == TC_2LATIN);
6199
6200         if (win95kcsi == TC_TRANSP) {
6201             win95kcs = NULL;
6202         } else {
6203 #ifdef UNICODE
6204             win95kcs = xlr[win95kcsi][tx2fc(tcsl)];
6205 #else /* UNICODE */
6206             win95kcs = xlr[win95kcsi][tcsl];
6207 #endif /* UNICODE */
6208         }
6209         return(1);
6210 #endif /* COMMENT */
6211
6212       case XYWLUC:
6213         if ((y = cmkey(onoff,2,"Unicode-to-Lucida-Console substitutions",
6214                        "on",xxstring)) < 0)
6215           return(y);
6216         if ((x = cmcfm()) < 0) return(x);
6217         win95lucida = y;
6218         return(1);
6219
6220       case XYWHSL:
6221         if ((y = cmkey(onoff,2,"Horizontal Scan Line substitutions",
6222                        "on",xxstring)) < 0)
6223           return(y);
6224         if ((x = cmcfm()) < 0) return(x);
6225         win95hsl = y;
6226         return(1);
6227
6228       default:
6229         printf("Illegal value in setwin95()\n");
6230         return(-9);
6231     }
6232 }
6233 #endif /* NT */
6234
6235 #ifdef OS2
6236 int
6237 setprty (
6238 #ifdef CK_ANSIC
6239     void
6240 #endif /* CK_ANSIC */
6241 /* setprty */ ) {
6242     int x, y, z;
6243
6244     if (( y = cmkey(prtytab, nprty,
6245                     "priority level of terminal and communication threads",
6246                     "foreground-server",
6247                     xxstring)) < 0 )
6248       return (y);
6249
6250     if ((x = cmcfm()) < 0)
6251       return (x);
6252 #ifdef IKSD
6253     if (inserver &&
6254 #ifdef IKSDCONF
6255          iksdcf
6256 #else
6257          1
6258 #endif /* IKSDCONF */
6259     ) {
6260         if ((y = cmcfm()) < 0) return(y);
6261         printf("?Sorry, command disabled.\r\n");
6262         return(success = 0);
6263     }
6264 #endif /* IKSD */
6265     priority = y;
6266     return(TRUE);
6267 }
6268 #endif /* OS2 */
6269
6270 int
6271 setbell() {
6272     int y, x;
6273 #ifdef OS2
6274     int z;
6275 #endif /* OS2 */
6276
6277     if ((y = cmkey(beltab,nbeltab,
6278 #ifdef OS2
6279         "how console and terminal bells should\nbe generated", "audible",
6280 #else
6281         "Whether Kermit should ring the terminal bell (beep)", "on",
6282 #endif /* OS2 */
6283                    xxstring)) < 0)
6284           return(y);
6285
6286 #ifdef IKSD
6287     if (inserver) {
6288         if ((y = cmcfm()) < 0) return(y);
6289         printf("?Sorry, command disabled.\r\n");
6290         return(success = 0);
6291     }
6292 #endif /* IKSD */
6293
6294     switch (y) {                        /* SET BELL */
6295       case XYB_NONE:
6296 #ifdef OS2
6297       case XYB_VIS:
6298 #endif /* OS2 */
6299         if ((x = cmcfm()) < 0)
6300           return(x);
6301 #ifdef OS2
6302         tt_bell = y;
6303 #else
6304         tt_bell = 0;
6305 #endif /* OS2 */
6306         break;
6307
6308       case XYB_AUD:
6309 #ifdef OS2
6310         if ((x = cmkey(audibletab, naudibletab,
6311                "how audible console and terminal\nbells should be generated",
6312                        "beep",xxstring))<0)
6313           return(x);
6314         if ((z = cmcfm()) < 0)
6315           return(z);
6316         tt_bell = y | x;
6317 #else
6318         /* This lets C-Kermit accept but ignore trailing K95 keywords */
6319         if ((x = cmtxt("Confirm with carriage return","",&s,xxstring)) < 0)
6320           return(x);
6321         tt_bell = 1;
6322 #endif /* OS2 */
6323         break;
6324     }
6325     return(1);
6326 }
6327
6328 #ifdef OS2MOUSE
6329 int
6330 setmou(
6331 #ifdef CK_ANSIC
6332        void
6333 #endif /* CK_ANSIC */
6334  /* setmou */ ) {
6335     extern int initvik;
6336     int button = 0, event = 0;
6337     char * p;
6338
6339     if ((y = cmkey(mousetab,nmtab,"","",xxstring)) < 0)
6340       return(y);
6341
6342 #ifdef IKSD
6343     if (inserver) {
6344         if ((y = cmcfm()) < 0) return(y);
6345         printf("?Sorry, command disabled.\r\n");
6346         return(success = 0);
6347     }
6348 #endif /* IKSD */
6349
6350     if (y == XYM_ON) {                  /* MOUSE ACTIVATION */
6351         int old_mou = tt_mouse;
6352         if ((x = seton(&tt_mouse)) < 0)
6353             return(x);
6354         if (tt_mouse != old_mou)
6355           if (tt_mouse)
6356             os2_mouseon();
6357           else
6358             os2_mouseoff();
6359         return(1);
6360     }
6361
6362     if (y == XYM_DEBUG) {               /* MOUSE DEBUG */
6363         extern int MouseDebug;
6364         if ((x = seton(&MouseDebug)) < 0)
6365             return(x);
6366         return(1);
6367     }
6368
6369     if (y == XYM_CLEAR) {               /* Reset Mouse Defaults */
6370         if ((x = cmcfm()) < 0) return(x);
6371         mousemapinit(-1,-1);
6372         initvik = 1;                    /* Update VIK Table */
6373         return 1;
6374     }
6375     if (y != XYM_BUTTON) {              /* Shouldn't happen. */
6376         printf("Internal parsing error\n");
6377         return(-9);
6378     }
6379
6380     /* MOUSE EVENT ... */
6381
6382     if ((button = cmkey(mousebuttontab,nmbtab,
6383                         "Button number","1",
6384                         xxstring)) < 0)
6385       return(button);
6386
6387     if ((y =  cmkey(mousemodtab,nmmtab,
6388                     "Keyboard modifier","none",
6389                     xxstring)) < 0)
6390       return(y);
6391
6392     event |= y;                         /* OR in the bits */
6393
6394     if ((y =  cmkey(mclicktab,nmctab,"","click",xxstring)) < 0)
6395       return(y);
6396
6397     /* Two bits are assigned, if neither are set then it is button one */
6398
6399     event |= y;                 /* OR in the bit */
6400
6401     wideresult = -1;
6402
6403     if ((y = cmtxt("definition,\n\
6404 or Ctrl-C to cancel this command,\n\
6405 or Enter to restore default definition",
6406                    "",&s,NULL)) < 0) {
6407         return(y);
6408     }
6409     s = brstrip(s);
6410     p = s;                              /* Save this place */
6411 /*
6412   If the definition included any \Kverbs, quote the backslash so the \Kverb
6413   will still be in the definition when the key is pressed.  We don't do this
6414   in zzstring(), because \Kverbs are valid only in this context and nowhere
6415   else.  This code copied from SET KEY, q.v. for addt'l commentary.
6416 */
6417     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
6418         if ((x > 0) &&
6419             (s[x] == 'K' || s[x] == 'k')
6420             ) {                         /* Have K */
6421
6422             if ((x == 1 && s[x-1] == CMDQ) ||
6423                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
6424                 line[y++] = CMDQ;       /* Make it \\K */
6425             }
6426             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
6427                 line[y-1] = CMDQ;       /* Have \{K */
6428                 line[y++] = '{';        /* Make it \\{K */
6429             }
6430         }
6431         line[y] = s[x];
6432     }
6433     line[y++] = NUL;                    /* Terminate */
6434     s = line + y + 1;                   /* Point to after it */
6435     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
6436     if ((x < (LINBUFSIZ / 2)) ||
6437         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
6438         printf("?Key definition too long\n");
6439         return(-9);
6440     }
6441     s = line + y + 1;                   /* Point to result. */
6442
6443 #ifndef NOKVERBS
6444 /*
6445   Special case: see if the definition starts with a \Kverb.
6446   If it does, point to it with p, otherwise set p to NULL.
6447 */
6448     p = s;
6449     if (*p++ == CMDQ) {
6450         if (*p == '{') p++;
6451         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
6452     }
6453 #else
6454     p = NULL;
6455 #endif /* NOKVERBS */
6456
6457     /* free the old definition if necessary */
6458     if (mousemap[button][event].type == macro) {
6459         free( mousemap[button][event].macro.string);
6460         mousemap[button][event].macro.string = NULL;
6461     }
6462     switch (strlen(s)) {                /* Action depends on length */
6463       case 0:                           /* Reset to default binding */
6464         mousemapinit( button, event );
6465         break;
6466       case 1:                           /* Single character */
6467             mousemap[button][event].type = key;
6468         mousemap[button][event].key.scancode = *s;
6469         break;
6470       default:                          /* Character string */
6471 #ifndef NOKVERBS
6472         if (p) {
6473             y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
6474             debug(F101,"set mouse kverb lookup",0,y); /* need exact match */
6475             if (y > -1) {
6476             /* Assign the kverb to the event */
6477             mousemap[button][event].type = kverb;
6478             mousemap[button][event].kverb.id = F_KVERB | y;
6479             break;
6480             }
6481         }
6482 #endif /* NOKVERBS */
6483
6484        /* Otherwise, it's a macro, so assign the macro to the event */
6485        mousemap[button][event].type = macro;
6486        mousemap[button][event].macro.string = (MACRO) malloc(strlen(s)+1);
6487        if (mousemap[button][event].macro.string)
6488          strcpy((char *) mousemap[button][event].macro.string, s); /* safe */
6489         break;
6490     }
6491     initvik = 1;                        /* Update VIK Table */
6492     if ( (button == XYM_B3) && (mousebuttoncount() < 3) && !quiet )
6493     {
6494         printf("?Warning: this machine does not have a three button mouse.\n");
6495         return(0);
6496     }
6497     return(1);
6498 }
6499 #endif /* OS2MOUSE */
6500 #endif /* NOLOCAL */
6501
6502 #ifndef NOXFER
6503 int                                     /* SET SEND/RECEIVE */
6504 setsr(xx, rmsflg) int xx; int rmsflg; {
6505     if (xx == XYRECV)
6506       ckstrncpy(line,"Parameter for inbound packets",LINBUFSIZ);
6507     else
6508       ckstrncpy(line,"Parameter for outbound packets",LINBUFSIZ);
6509
6510     if (rmsflg) {
6511         if ((y = cmkey(rsrtab,nrsrtab,line,"",xxstring)) < 0) {
6512             if (y == -3) {
6513                 printf("?Remote receive parameter required\n");
6514                 return(-9);
6515             } else return(y);
6516         }
6517     } else {
6518         if ((y = cmkey(srtab,nsrtab,line,"",xxstring)) < 0) return(y);
6519     }
6520     switch (y) {
6521       case XYQCTL:                      /* CONTROL-PREFIX */
6522         if ((x = cmnum("ASCII value of control prefix","",10,&y,xxstring)) < 0)
6523           return(x);
6524         if ((x = cmcfm()) < 0) return(x);
6525         if ((y > 32 && y < 63) || (y > 95 && y < 127)) {
6526             if (xx == XYRECV)
6527               ctlq = (CHAR) y;          /* RECEIVE prefix, use with caution! */
6528             else
6529               myctlq = (CHAR) y;        /* SEND prefix, OK to change */
6530             return(success = 1);
6531         } else {
6532             printf("?Illegal value for prefix character\n");
6533             return(-9);
6534         }
6535
6536       case XYEOL:
6537         if ((y = setcc("13",&z)) < 0)
6538             return(y);
6539         if (z > 31) {
6540             printf("Sorry, the legal values are 0-31\n");
6541             return(-9);
6542         }
6543         if (xx == XYRECV)
6544           eol = (CHAR) z;
6545         else
6546           seol = (CHAR) z;
6547         return(success = y);
6548
6549       case XYLEN:
6550         y = cmnum("Maximum number of characters in a packet","90",10,&x,
6551                   xxstring);
6552         if (xx == XYRECV) {             /* Receive... */
6553             if ((y = setnum(&z,x,y,maxrps)) < 0)
6554               return(y);
6555             if (protocol != PROTO_K) {
6556                 printf("?Sorry, this command does not apply to %s protocol.\n",
6557                        ptab[protocol].p_name
6558                        );
6559                 printf("Use SET SEND PACKET-LENGTH for XYZMODEM\n");
6560                 return(-9);
6561             }
6562             if (z < 10) {
6563                 printf("Sorry, 10 is the minimum\n");
6564                 return(-9);
6565             }
6566             if (rmsflg) {
6567                 sstate = setgen('S', "401", ckitoa(z), "");
6568                 return((int) sstate);
6569             } else {
6570                 if (protocol == PROTO_K) {
6571                     if (z > MAXRP) z = MAXRP;
6572                     y = adjpkl(z,wslotr,bigrbsiz);
6573                     if (y != z) {
6574                         urpsiz = y;
6575                         if (!xcmdsrc)
6576                           if (msgflg) printf(
6577 " Adjusting receive packet-length to %d for %d window slots\n",
6578                                              y, wslotr);
6579                     }
6580                     urpsiz = y;
6581                     ptab[protocol].rpktlen = urpsiz;
6582                     rpsiz =  (y > 94) ? 94 : y;
6583                 } else {
6584 #ifdef CK_XYZ
6585                     if ((protocol == PROTO_X || protocol == PROTO_XC) &&
6586                          z != 128 && z != 1024) {
6587                         printf("Sorry, bad packet length for XMODEM.\n");
6588                         printf("Please use 128 or 1024.\n");
6589                         return(-9);
6590                     }
6591 #endif /* CK_XYZ */
6592                     urpsiz = rpsiz = z;
6593                 }
6594             }
6595         } else {                        /* Send... */
6596             if ((y = setnum(&z,x,y,maxsps)) < 0)
6597               return(y);
6598             if (z < 10) {
6599                 printf("Sorry, 10 is the minimum\n");
6600                 return(-9);
6601             }
6602             if (protocol == PROTO_K) {
6603                 if (z > MAXSP) z = MAXSP;
6604                 spsiz = z;              /* Set it */
6605                 y = adjpkl(spsiz,wslotr,bigsbsiz);
6606                 if (y != spsiz && !xcmdsrc)
6607                   if (msgflg)
6608                     printf("Adjusting packet size to %d for %d window slots\n",
6609                            y,wslotr);
6610             } else
6611               y = z;
6612 #ifdef CK_XYZ
6613             if ((protocol == PROTO_X || protocol == PROTO_XC) &&
6614                  z != 128 && z != 1024) {
6615                 printf("Sorry, bad packet length for XMODEM.\n");
6616                 printf("Please use 128 or 1024.\n");
6617                 return(-9);
6618             }
6619 #endif /* CK_XYZ */
6620             spsiz = spmax = spsizr = y; /* Set it and flag that it was set */
6621             spsizf = 1;                 /* to allow overriding Send-Init. */
6622             ptab[protocol].spktflg = spsizf;
6623             ptab[protocol].spktlen = spsiz;
6624         }
6625         if (pflag && protocol == PROTO_K && !xcmdsrc) {
6626             if (z > 94 && !reliable && msgflg) {
6627                 /* printf("Extended-length packets requested.\n"); */
6628                 if (bctr < 2 && z > 200) printf("\
6629 Remember to SET BLOCK 2 or 3 for long packets.\n");
6630             }
6631             if (speed <= 0L) speed = ttgspd();
6632 #ifdef COMMENT
6633 /*
6634   Kermit does this now itself.
6635 */
6636             if (speed <= 0L && z > 200 && msgflg) {
6637                 printf("\
6638 Make sure your timeout interval is long enough for %d-byte packets.\n",z);
6639             }
6640 #endif /* COMMENT */
6641         }
6642         return(success = y);
6643
6644       case XYMARK:
6645 #ifdef DOOMSDAY
6646 /*
6647   Printable start-of-packet works for UNIX and VMS only!
6648 */
6649         x_ifnum = 1;
6650         y = cmnum("Code for packet-start character","1",10,&x,xxstring);
6651         x_ifnum = 0;
6652         if ((y = setnum(&z,x,y,126)) < 0) return(y);
6653 #else
6654         if ((y = setcc("1",&z)) < 0)
6655             return(y);
6656 #endif /* DOOMSDAY */
6657         if (xx == XYRECV)
6658           stchr = (CHAR) z;
6659         else {
6660             mystch = (CHAR) z;
6661 #ifdef IKS_OPTION
6662             /* If IKS negotiation in use   */
6663             if (TELOPT_U(TELOPT_KERMIT) || TELOPT_ME(TELOPT_KERMIT))
6664               tn_siks(KERMIT_SOP);      /* Report change to other side */
6665 #endif /* IKS_OPTION */
6666         }
6667         return(success = y);
6668
6669       case XYNPAD:                      /* PADDING */
6670         y = cmnum("How many padding characters for inbound packets","0",10,&x,
6671                   xxstring);
6672         if ((y = setnum(&z,x,y,94)) < 0) return(y);
6673         if (xx == XYRECV)
6674           mypadn = (CHAR) z;
6675         else
6676           npad = (CHAR) z;
6677         return(success = y);
6678
6679       case XYPADC:                      /* PAD-CHARACTER */
6680         if ((y = setcc("0",&z)) < 0) return(y);
6681         if (xx == XYRECV) mypadc = z; else padch = z;
6682         return(success = y);
6683
6684       case XYTIMO:                      /* TIMEOUT */
6685         if (xx == XYRECV) {
6686             y = cmnum("Packet timeout interval",ckitoa(URTIME),10,&x,xxstring);
6687             if ((y = setnum(&z,x,y,94)) < 0) return(y);
6688
6689             if (rmsflg) {               /* REMOTE SET RECEIVE TIMEOUT */
6690                 sstate = setgen('S', "402", ckitoa(z), "");
6691                 return((int) sstate);
6692             } else {                    /* SET RECEIVE TIMEOUT */
6693                 pkttim = z;             /*   Value to put in my negotiation */
6694             }                           /*   packet for other Kermit to use */
6695
6696         } else {                        /* SET SEND TIMEOUT */
6697 #ifdef CK_TIMERS
6698             extern int rttflg, mintime, maxtime;
6699             int tmin = 0, tmax = 0;
6700 #endif /* CK_TIMERS */
6701             y = cmnum("Packet timeout interval",ckitoa(DMYTIM),10,&x,xxstring);
6702             if (y == -3) {              /* They cancelled a previous */
6703                 x = DMYTIM;             /* SET SEND command, so restore */
6704                 timef = 0;              /* and turn off the override flag */
6705                 y = cmcfm();
6706             }
6707 #ifdef CK_TIMERS
6708             if (y < 0) return(y);
6709             if (x < 0) {
6710                 printf("?Out of range - %d\n",x);
6711                 return(-9);
6712             }
6713             if ((z = cmkey(timotab,2,"","dynamic",xxstring)) < 0) return(z);
6714             if (z) {
6715                 if ((y = cmnum("Minimum timeout to allow",
6716                                "1",10,&tmin,xxstring)) < 0)
6717                   return(y);
6718                 if (tmin < 1) {
6719                     printf("?Out of range - %d\n",tmin);
6720                     return(-9);
6721                 }
6722                 if ((y = cmnum("Maximum timeout to allow",
6723                                "0",10,&tmax,xxstring)) < 0)
6724                   return(y);
6725                 /* 0 means let Kermit choose, < 0 means no maximum */
6726             }
6727             if ((y = cmcfm()) < 0)
6728               return(y);
6729             rttflg = z;                 /* Round-trip timer flag */
6730             z = x;
6731 #else
6732             if ((y = setnum(&z,x,y,94)) < 0)
6733               return(y);
6734 #endif /* CK_TIMERS */
6735             timef = 1;                  /* Turn on the override flag */
6736             timint = rtimo = z;         /* Override value for me to use */
6737 #ifdef CK_TIMERS
6738             if (rttflg) {               /* Lower and upper bounds */
6739                 mintime = tmin;
6740                 maxtime = tmax;
6741             }
6742 #endif /* CK_TIMERS */
6743         }
6744         return(success = 1);
6745
6746       case XYFPATH:                     /* PATHNAMES */
6747         if (xx == XYRECV) {
6748             y = cmkey(rpathtab,nrpathtab,"","auto",xxstring);
6749         } else {
6750             y = cmkey(pathtab,npathtab,"","off",xxstring);
6751         }
6752         if (y < 0) return(y);
6753
6754         if ((x = cmcfm()) < 0) return(x);
6755         if (xx == XYRECV) {             /* SET RECEIVE PATHNAMES */
6756             fnrpath = y;
6757             ptab[protocol].fnrp = fnrpath;
6758         } else {                        /* SET SEND PATHNAMES */
6759             fnspath = y;
6760             ptab[protocol].fnsp = fnspath;
6761         }
6762         return(success = 1);            /* Note: 0 = ON, 1 = OFF */
6763         /* In other words, ON = leave pathnames ON, OFF = take them off. */
6764
6765       case XYPAUS:                      /* SET SEND/RECEIVE PAUSE */
6766         y = cmnum("Milliseconds to pause between packets","0",10,&x,xxstring);
6767         if ((y = setnum(&z,x,y,15000)) < 0)
6768           return(y);
6769         pktpaus = z;
6770         return(success = 1);
6771
6772 #ifdef CKXXCHAR                         /* SET SEND/RECEIVE IGNORE/DOUBLE */
6773       case XYIGN:
6774       case XYDBL: {
6775           int i, zz;
6776           short *p;
6777           extern short dblt[];
6778           extern int dblflag, ignflag;
6779
6780           /* Make space for a temporary copy of the ignore/double table */
6781
6782           zz = y;
6783 #ifdef COMMENT
6784           if (zz == XYIGN && xx == XYSEND) {
6785               blah blah who cares
6786           }
6787           if (zz == XYDBL && xx == XYRECV) {
6788               blah blah
6789           }
6790 #endif /* COMMENT */
6791           p = (short *)malloc(256 * sizeof(short));
6792           if (!p) {
6793               printf("?Internal error - malloc failure\n");
6794               return(-9);
6795           }
6796           for (i = 0; i < 256; i++) p[i] = dblt[i]; /* Copy current table */
6797
6798           while (1) {                   /* Collect a list of numbers */
6799 #ifndef NOSPL
6800               x_ifnum = 1;              /* Turn off complaints from eval() */
6801 #endif /* NOSPL */
6802               if ((x = cmnum(zz == XYDBL ?
6803                              "Character to double" :
6804                              "Character to ignore",
6805                              "",10,&y,xxstring
6806                              )) < 0) {
6807 #ifndef NOSPL
6808                   x_ifnum = 0;
6809 #endif /* NOSPL */
6810                   if (x == -3)          /* Done */
6811                     break;
6812                   if (x == -2) {
6813                       if (p) { free(p); p = NULL; }
6814                       debug(F110,"SET S/R DOUBLE/IGNORE atmbuf",atmbuf,0);
6815                       if (!ckstrcmp(atmbuf,"none",4,0) ||
6816                           !ckstrcmp(atmbuf,"non",3,0) ||
6817                           !ckstrcmp(atmbuf,"no",2,0) ||
6818                           !ckstrcmp(atmbuf,"n",1,0)) {
6819                           if ((x = cmcfm()) < 0) /* Get confirmation */
6820                             return(x);
6821                           for (y = 0; y < 256; y++)
6822                             dblt[y] &= (zz == XYDBL) ? 1 : 2;
6823                           if (zz == XYDBL) dblflag = 0;
6824                           if (zz == XYIGN) ignflag = 0;
6825                           return(success = 1);
6826                       } else {
6827                           printf(
6828                             "?Please specify a number or the word NONE\n");
6829                           return(-9);
6830                       }
6831                   } else {
6832                       free(p);
6833                       p = NULL;
6834                       return(x);
6835                   }
6836               }
6837 #ifndef NOSPL
6838               x_ifnum = 0;
6839 #endif /* NOSPL */
6840               if (y < 0 || y > 255) {
6841                   printf("?Please enter a character code in range 0-255\n");
6842                   free(p);
6843                   p = NULL;
6844                   return(-9);
6845               }
6846               p[y] |= (zz == XYDBL) ? 2 : 1;
6847               if (zz == XYDBL) dblflag = 1;
6848               if (zz == XYIGN) ignflag = 1;
6849           } /* End of while loop */
6850
6851           if ((x = cmcfm()) < 0) return(x);
6852 /*
6853   Get here only if they have made no mistakes.  Copy temporary table back to
6854   permanent one, then free temporary table and return successfully.
6855 */
6856           if (p) {
6857               for (i = 0; i < 256; i++) dblt[i] = p[i];
6858               free(p);
6859               p = NULL;
6860           }
6861           return(success = 1);
6862       }
6863 #endif /* CKXXCHAR */
6864
6865 #ifdef PIPESEND
6866       case XYFLTR: {                    /* SET { SEND, RECEIVE } FILTER */
6867           if ((y = cmtxt((xx == XYSEND) ?
6868                 "Filter program for sending files -\n\
6869  use \\v(filename) to substitute filename" :
6870                 "Filter program for receiving files -\n\
6871  use \\v(filename) to substitute filename",
6872                          "",&s,NULL)) < 0)
6873             return(y);
6874           if (!*s) {                    /* Removing a filter... */
6875               if (xx == XYSEND && sndfilter) {
6876                   makestr(&g_sfilter,NULL);
6877                   makestr(&sndfilter,NULL);
6878               } else if (rcvfilter) {
6879                   makestr(&g_rfilter,NULL);
6880                   makestr(&rcvfilter,NULL);
6881               }
6882               return(success = 1);
6883           }                             /* Adding a filter... */
6884           s = brstrip(s);               /* Strip any braces */
6885           y = strlen(s);
6886           if (xx == XYSEND) {           /* For SEND filter... */
6887               for (x = 0; x < y; x++) { /* make sure they included "\v(...)" */
6888                   if (s[x] != '\\') continue;
6889                   if (s[x+1] == 'v') break;
6890               }
6891               if (x == y) {
6892                   printf(
6893               "?Filter must contain a replacement variable for filename.\n"
6894                          );
6895                   return(-9);
6896               }
6897           }
6898           if (xx == XYSEND) {
6899               makestr(&sndfilter,s);
6900               makestr(&g_sfilter,s);
6901           } else {
6902               makestr(&rcvfilter,s);
6903               makestr(&g_rfilter,s);
6904           }
6905           return(success = 1);
6906       }
6907 #endif /* PIPESEND */
6908
6909       case XYINIL:
6910         y = cmnum("Max length for protocol init string","-1",10,&x,xxstring);
6911         if ((y = setnum(&z,x,y,-1)) < 0)
6912           return(y);
6913         if (xx == XYSEND)
6914           sprmlen = z;
6915         else
6916           rprmlen = z;
6917         return(success = 1);
6918
6919       case 993: {
6920           extern int sendipkts;
6921           if (xx == XYSEND) {
6922               if ((x = seton(&sendipkts)) < 0)
6923                 return(x);
6924           }
6925           return(1);
6926       }
6927 #ifdef CK_PERMS
6928       case 994:
6929         switch(xx) {
6930           case XYSEND:
6931             if ((x = seton(&atlpro)) < 0) return(x);
6932             atgpro = atlpro;
6933             return(1);
6934           case XYRECV:
6935             if ((x = seton(&atlpri)) < 0) return(x);
6936             atgpri = atlpri;
6937             return(1);
6938           default:
6939             return(-2);
6940         }
6941 #endif /* CK_PERMS */
6942
6943 #ifndef NOCSETS
6944       case XYCSET: {                    /* CHARACTER-SET-SELECTION */
6945           extern struct keytab xfrmtab[];
6946           extern int r_cset, s_cset;
6947           if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
6948             return(y);
6949           if ((x = cmcfm()) < 0)
6950             return(x);
6951           if (xx == XYSEND)
6952             s_cset = y;
6953           else
6954             r_cset = y;
6955           return(success = 1);
6956       }
6957 #endif /* NOCSETS */
6958
6959       case XYBUP:
6960         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
6961           return(y);
6962         if ((x = cmcfm()) < 0) return(x);
6963         if (xx == XYSEND) {
6964             extern int skipbup;
6965             skipbup = (y == 0) ? 1 : 0;
6966             return(success = 1);
6967         } else {
6968             printf(
6969 "?Please use SET FILE COLLISION to choose the desired action\n");
6970             return(-9);
6971         }
6972
6973       case XYMOVE:
6974 #ifdef COMMENT
6975         y = cmdir("Directory to move file(s) to after successful transfer",
6976                   "",&s,xxstring);
6977 #else
6978         y = cmtxt("Directory to move file(s) to after successful transfer",
6979                   "",&s,xxstring);
6980 #endif /* COMMENT */
6981
6982         if (y < 0 && y != -3)
6983           return(y);
6984         ckstrncpy(line,s,LINBUFSIZ);
6985         s = brstrip(line);
6986
6987 #ifdef COMMENT
6988         /* Only needed for cmdir() */
6989         if ((x = cmcfm()) < 0)
6990           return(x);
6991 #endif /* COMMENT */
6992         
6993         /* Check directory existence if absolute */
6994         /* THIS MEANS IT CAN'T INCLUDE ANY DEFERRED VARIABLES! */
6995         if (s) if (*s) {
6996             if (isabsolute(s) && !isdir(s)) {
6997                 printf("?Directory does not exist - %s\n",s);
6998                 return(-9);
6999             }
7000         }
7001         if (xx == XYSEND) {
7002             if (*s) {
7003 #ifdef COMMENT
7004                 /* Allow it to be relative */
7005                 zfnqfp(s,LINBUFSIZ,line);
7006 #endif /* COMMENT */
7007                 makestr(&snd_move,line);
7008                 makestr(&g_snd_move,line);
7009             } else {
7010                 makestr(&snd_move,NULL);
7011                 makestr(&g_snd_move,NULL);
7012             }
7013         } else {
7014             if (*s) {
7015 #ifdef COMMENT
7016                 /* Allow it to be relative */
7017                 zfnqfp(s,LINBUFSIZ,line);
7018 #endif /* COMMENT */
7019                 makestr(&rcv_move,line);
7020                 makestr(&g_rcv_move,line);
7021             } else {
7022                 makestr(&rcv_move,NULL);
7023                 makestr(&g_rcv_move,NULL);
7024             }
7025         }
7026         return(success = 1);
7027
7028       case XYRENAME:
7029         y = cmtxt("Template to rename file(s) to after successful transfer",
7030                   "",&s,NULL);          /* NOTE: no xxstring */
7031         if (y < 0 && y != -3)           /* Evaluation is deferred */
7032           return(y);
7033         ckstrncpy(line,s,LINBUFSIZ);
7034         s = brstrip(line);
7035         if ((x = cmcfm()) < 0)
7036           return(x);
7037         if (xx == XYSEND) {
7038             if (*s) {
7039                 makestr(&snd_rename,s);
7040                 makestr(&g_snd_rename,s);
7041             } else {
7042                 makestr(&snd_rename,NULL);
7043                 makestr(&g_snd_rename,NULL);
7044             }
7045         } else {
7046             if (*s) {
7047                 makestr(&rcv_rename,s);
7048                 makestr(&g_rcv_rename,s);
7049             } else {
7050                 makestr(&rcv_rename,NULL);
7051                 makestr(&g_rcv_rename,NULL);
7052             }
7053         }
7054         return(success = 1);
7055
7056 #ifdef VMS
7057       case 887:                         /* VERSION-NUMBERS */
7058         if (xx == XYSEND) {
7059             extern int vmssversions;
7060             return(seton(&vmssversions));
7061         } else {
7062             extern int vmsrversions;
7063             return(seton(&vmsrversions));
7064         }
7065 #endif /* VMS */
7066
7067       default:
7068         return(-2);
7069     }                                   /* End of SET SEND/RECEIVE... */
7070 }
7071 #endif /* NOXFER */
7072
7073 #ifndef NOXMIT
7074 int
7075 setxmit() {
7076     if ((y = cmkey(xmitab,nxmit,"","",xxstring)) < 0) return(y);
7077     switch (y) {
7078       case XMITE:                       /* EOF */
7079         y = cmtxt("Characters to send at end of file,\n\
7080  Use backslash codes for control characters","",&s,xxstring);
7081         if (y < 0) return(y);
7082         if ((int)strlen(s) > XMBUFL) {
7083             printf("?Too many characters, %d maximum\n",XMBUFL);
7084             return(-2);
7085         }
7086         ckstrncpy(xmitbuf,s,XMBUFL);
7087         return(success = 1);
7088
7089       case XMITF:                       /* Fill */
7090         y = cmnum("Numeric code for blank-line fill character","0",10,&x,
7091                   xxstring);
7092         if ((y = setnum(&z,x,y,127)) < 0) return(y);
7093         xmitf = z;
7094         return(success = 1);
7095       case XMITL:                       /* Linefeed */
7096         return(seton(&xmitl));
7097       case XMITS:                       /* Locking-Shift */
7098         return(seton(&xmits));
7099       case XMITP:                       /* Prompt */
7100         y = cmnum("Numeric code for host's prompt character, 0 for none",
7101                   "10",10,&x,xxstring);
7102         if ((y = setnum(&z,x,y,127)) < 0) return(y);
7103         xmitp = z;
7104         return(success = 1);
7105       case XMITX:                       /* Echo */
7106         return(seton(&xmitx));
7107       case XMITW:                       /* Pause */
7108         y = cmnum("Number of milliseconds to pause between binary characters\n\
7109 or text lines during transmission","0",10,&x,xxstring);
7110         if ((y = setnum(&z,x,y,1000)) < 0) return(y);
7111         xmitw = z;
7112         return(success = 1);
7113       case XMITT:                       /* Timeout */
7114         y = cmnum("Seconds to wait for each character to echo",
7115                   "1",10,&x,xxstring);
7116         if ((y = setnum(&z,x,y,1000)) < 0) return(y);
7117         xmitt = z;
7118         return(success = 1);
7119       default:
7120         return(-2);
7121     }
7122 }
7123 #endif /* NOXMIT */
7124
7125 #ifndef NOXFER
7126 /*  D O R M T  --  Do a remote command  */
7127
7128 VOID
7129 rmsg() {
7130     if (pflag && !quiet && fdispla != XYFD_N)
7131       printf(
7132 #ifdef CK_NEED_SIG
7133        " Type your escape character, %s, followed by X or E to cancel.\n",
7134        dbchr(escape)
7135 #else
7136        " Press the X or E key to cancel.\n"
7137 #endif /* CK_NEED_SIG */
7138       );
7139 }
7140
7141 static int xzcmd = 0;                   /* Global copy of REMOTE cmd index */
7142
7143 /*  R E M C F M  --  Confirm a REMOTE command  */
7144 /*
7145   Like cmcfm(), but allows for a redirection indicator on the end,
7146   like "> filename" or "| command".  Returns what cmcfm() would have
7147   returned: -1 if reparse needed, etc etc blah blah.  On success,
7148   returns 1 with:
7149
7150     char * remdest containing the name of the file or command.
7151     int remfile set to 1 if there is to be any redirection.
7152     int remappd set to 1 if output file is to be appended to.
7153     int rempipe set to 1 if remdest is a command, 0 if it is a file.
7154 */
7155 static int
7156 remcfm() {
7157     int x;
7158     char *s;
7159     char c;
7160
7161     remfile = 0;
7162     rempipe = 0;
7163     remappd = 0;
7164
7165     if ((x = cmtxt(
7166              "> filename, | command,\n\
7167 or type carriage return to confirm the command",
7168                    "",&s,xxstring)) < 0)
7169       return(x);
7170     if (remdest) {
7171         free(remdest);
7172         remdest = NULL;
7173     }
7174     debug(F101,"remcfm local","",local);
7175     debug(F110,"remcfm s",s,0);
7176     debug(F101,"remcfm cmd","",xzcmd);
7177 /* 
7178   This check was added in C-Kermit 6.0 or 7.0 but it turns out to be
7179   unhelpful in the situation where the remote is running a script that sends
7180   REMOTE commands to the local workstation.  What happens is, the local
7181   server executes the command and sends the result back as screen text, which
7182   is indicated by using an X packet instead of an F packet as the file
7183   header.  There are two parts to this: executing the command under control
7184   of the remote Kermit, which is desirable (and in fact some big applications
7185   depend on it, and therefore never installed any new C-Kermit versions after
7186   5A), and displaying the result.  Commenting out the check allows the
7187   command to be executed, but the result is still sent back to the remote in
7188   a file transfer, where it vanishes into the ether.  Actually it's on the
7189   communication connection, mixed in with the packets.  Pretty amazing that
7190   the file transfer still works, right?
7191 */
7192 #ifdef COMMENT
7193     if (!*s) {                          /* No redirection indicator */
7194         if (!local &&
7195             (xzcmd == XZDIR || xzcmd == XZTYP ||
7196              xzcmd == XZXIT || xzcmd == XZSPA ||
7197              xzcmd == XZHLP || xzcmd == XZPWD ||
7198              xzcmd == XZLGI || xzcmd == XZLGO ||
7199              xzcmd == XZWHO || xzcmd == XZHOS)) {
7200             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
7201             return(-9);
7202         } else
7203           return(1);
7204     }
7205 #endif  /* COMMENT */
7206     c = *s;                             /* We have something */
7207     if (c != '>' && c != '|') {         /* Is it > or | ? */
7208         printf("?Not confirmed\n");     /* No */
7209         return(-9);
7210     }
7211     s++;                                /* See what follows */
7212     if (c == '>' && *s == '>') {        /* Allow for ">>" too */
7213         s++;
7214         remappd = 1;                    /* Append to output file */
7215     }
7216     while (*s == SP || *s == HT) s++;   /* Strip intervening whitespace */
7217     if (!*s) {
7218         printf("?%s missing\n", c == '>' ? "Filename" : "Command");
7219         return(-9);
7220     }
7221     if (c == '>' && zchko(s) < 0) {     /* Check accessibility */
7222         printf("?Access denied - %s\n", s);
7223         return(-9);
7224     }
7225     remfile = 1;                        /* Set global results */
7226     rempipe = (c == '|');
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     makestr(&remdest,s);
7236 #ifndef NODEBUG
7237     if (deblog) {
7238         debug(F101,"remcfm remfile","",remfile);
7239         debug(F101,"remcfm remappd","",remappd);
7240         debug(F101,"remcfm rempipe","",rempipe);
7241         debug(F110,"remcfm remdest",remdest, 0);
7242     }
7243 #endif /* NODEBUG */
7244     return(1);
7245 }
7246
7247 /*  R E M T X T  --  Like remcfm()...  */
7248 /*
7249    ... but for REMOTE commands that end with cmtxt().
7250    Here we must decipher braces to discover whether the trailing
7251    redirection indicator is intended for local use, or to be sent out
7252    to the server, as in:
7253
7254      remote host blah blah > file                 This end
7255      remote host { blah blah } > file             This end
7256      remote host { blah blah > file }             That end
7257      remote host { blah blah > file } > file      Both ends
7258
7259    Pipes too:
7260
7261      remote host blah blah | cmd                  This end
7262      remote host { blah blah } | cmd              This end
7263      remote host { blah blah | cmd }              That end
7264      remote host { blah blah | cmd } | cmd        Both ends
7265
7266    Or both:
7267
7268      remote host blah blah | cmd > file           This end, etc etc...
7269
7270    Note: this really only makes sense for REMOTE HOST, but why be picky?
7271    Call after calling cmtxt(), with pointer to string that cmtxt() parsed,
7272    as in "remtxt(&s);".
7273
7274    Returns:
7275     1 on success with braces & redirection things removed & pointer updated,
7276    -9 on failure (bad indirection), after printing error message.
7277 */
7278 int
7279 remtxt(p) char ** p; {
7280     int i, x, bpos, ppos;
7281     char c, *s, *q;
7282
7283     remfile = 0;                        /* Initialize global results */
7284     rempipe = 0;
7285     remappd = 0;
7286     if (remdest) {
7287         free(remdest);
7288         remdest = NULL;
7289     }
7290     s = *p;
7291     if (!s)                             /* No redirection indicator */
7292       s = "";
7293 #ifdef COMMENT
7294     if (!*s) {                          /* Ditto */
7295         if (!local &&
7296             (xzcmd == XZDIR || xzcmd == XZTYP ||
7297              xzcmd == XZXIT || xzcmd == XZSPA ||
7298              xzcmd == XZHLP || xzcmd == XZPWD ||
7299              xzcmd == XZLGI || xzcmd == XZLGO ||
7300              xzcmd == XZWHO || xzcmd == XZHOS)) {
7301             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
7302             if (hints) {
7303                 printf("Hint: Try again with an output redirector.\n");
7304             }
7305             return(-9);
7306         } else
7307           return(1);
7308     }
7309 #endif  /* COMMENT */
7310     bpos = -1;                          /* Position of > (bracket) */
7311     ppos = -1;                          /* Position of | (pipe) */
7312     x = strlen(s);                      /* Length of cmtxt() string */
7313
7314     for (i = x-1; i >= 0; i--) {        /* Search right to left. */
7315         c = s[i];
7316         if (c == '}')                   /* Break on first right brace */
7317           break;                        /* Don't look at contents of braces */
7318         else if (c == '>')              /* Record position of > */
7319           bpos = i;
7320         else if (c == '|')              /* and of | */
7321           ppos = i;
7322     }
7323     if (bpos < 0 && ppos < 0) {         /* No redirectors. */
7324 #ifdef COMMENT
7325         if (!local &&
7326             (xzcmd == XZDIR || xzcmd == XZTYP ||
7327              xzcmd == XZXIT || xzcmd == XZSPA ||
7328              xzcmd == XZHLP || xzcmd == XZPWD ||
7329              xzcmd == XZLGI || xzcmd == XZLGO ||
7330              xzcmd == XZWHO || xzcmd == XZHOS)) {
7331             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
7332             if (hints) {
7333                 printf("Hint: Try again with an output redirector.\n");
7334             }
7335             return(-9);
7336         }
7337 #endif  /* COMMENT */
7338         s = brstrip(s);                 /* Remove outer braces if any. */
7339         *p = s;                         /* Point to result */
7340         return(1);                      /* and return. */
7341     }
7342     remfile = 1;                        /* It's | or > */
7343     i = -1;                             /* Get leftmost symbol */
7344     if (bpos > -1)                      /* Bracket */
7345       i = bpos;
7346     if (ppos > -1 && (ppos < bpos || bpos < 0)) { /* or pipe */
7347         i = ppos;
7348         rempipe = 1;
7349     }
7350     if (rempipe
7351 #ifndef NOPUSH
7352         && nopush
7353 #endif /* NOPUSH */
7354         ) {
7355         printf("?Sorry, access to external commands is disabled.\n");
7356         return(-9);
7357     }
7358     c = s[i];                           /* Copy of symbol */
7359
7360     if (c == '>' && s[i+1] == '>')      /* ">>" for append? */
7361       remappd = 1;                     /* It's not just a flag it's a number */
7362
7363     q = s + i + 1 + remappd;            /* Point past symbol in string */
7364     while (*q == SP || *q == HT) q++;   /* and any intervening whitespace */
7365     if (!*q) {
7366         printf("?%s missing\n", c == '>' ? "Filename" : "Command");
7367         return(-9);
7368     }
7369     if (c == '>' && zchko(q) < 0) {     /* (Doesn't work for | cmd > file) */
7370         printf("?Access denied - %s\n", q);
7371         return(-9);
7372     }
7373     makestr(&remdest,q);                /* Create the destination string */
7374     q = s + i - 1;                      /* Point before symbol */
7375     while (q > s && (*q == SP || *q == HT)) /* Strip trailing whitespace */
7376       q--;
7377     *(q+1) = NUL;                       /* Terminate the string. */
7378     s = brstrip(s);                     /* Remove any braces */
7379     *p = s;                             /* Set return value */
7380
7381 #ifndef NODEBUG
7382     if (deblog) {
7383         debug(F101,"remtxt remfile","",remfile);
7384         debug(F101,"remtxt remappd","",remappd);
7385         debug(F101,"remtxt rempipe","",rempipe);
7386         debug(F110,"remtxt remdest",remdest, 0);
7387         debug(F110,"remtxt command",s,0);
7388     }
7389 #endif /* NODEBUG */
7390
7391     return(1);
7392 }
7393
7394 int
7395 plogin(xx) int xx; {
7396     char *p1 = NULL, *p2 = NULL, *p3 = NULL;
7397     int psaved = 0, rc = 0;
7398 #ifdef CK_RECALL
7399     extern int on_recall;               /* around Password prompting */
7400 #endif /* CK_RECALL */
7401     debug(F101,"plogin local","",local);
7402
7403     if (!local || (network && ttchk() < 0)) {
7404         printf("?No connection\n");
7405         return(-9);
7406     }
7407     if ((x = cmfld("User ID","",&s,xxstring)) < 0) { /* Get User ID */
7408         if (x != -3) return(x);
7409     }
7410     y = strlen(s);
7411     if (y > 0) {
7412         if ((p1 = malloc(y + 1)) == NULL) {
7413             printf("?Internal error: malloc\n");
7414             rc = -9;
7415             goto XZXLGI;
7416         } else
7417           strcpy(p1,s);                 /* safe */
7418         if ((rc = cmfld("Password","",&s,xxstring)) < 0)
7419           if (rc != -3) goto XZXLGI;
7420         y = strlen(s);
7421         if (y > 0) {
7422             if ((p2 = malloc(y + 1)) == NULL) {
7423                 printf("?Internal error: malloc\n");
7424                 rc = -9;
7425                 goto XZXLGI;
7426             } else
7427               strcpy(p2,s);             /* safe */
7428             if ((rc = cmfld("Account","",&s,xxstring)) < 0)
7429               if (rc != -3) goto XZXLGI;
7430             y = strlen(s);
7431             if (y > 0) {
7432                 if ((p3 = malloc(y + 1)) == NULL) {
7433                     printf("?Internal error: malloc\n");
7434                     rc = -9;
7435                     goto XZXLGI;
7436                 } else
7437                   strcpy(p3,s);         /* safe */
7438             }
7439         }
7440     }
7441     if ((rc = remtxt(&s)) < 0)          /* Confirm & handle redirectors */
7442       goto XZXLGI;
7443
7444     if (!p1) {                          /* No Userid specified... */
7445         debok = 0;                      /* Don't log this */
7446         /* Prompt for username, password, and account */
7447 #ifdef CK_RECALL
7448         on_recall = 0;
7449 #endif /* CK_RECALL */
7450         cmsavp(psave,PROMPTL);          /* Save old prompt */
7451         psaved = 1;
7452         debug(F110,"REMOTE LOGIN saved",psave,0);
7453
7454         cmsetp("Username: ");           /* Make new prompt */
7455         concb((char)escape);            /* Put console in cbreak mode */
7456         cmini(1);
7457         prompt(xxstring);
7458         rc = -9;
7459         for (x = -1; x < 0; ) {         /* Prompt till they answer */
7460             cmres();                    /* Reset the parser */
7461             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
7462         }
7463         y = strlen(s);
7464         if (y < 1) {
7465             printf("?Canceled\n");
7466             goto XZXLGI;
7467         }
7468         if ((p1 = malloc(y + 1)) == NULL) {
7469             printf("?Internal error: malloc\n");
7470             goto XZXLGI;
7471         } else
7472           strcpy(p1,s);                 /* safe */
7473
7474         cmsetp("Password: ");           /* Make new prompt */
7475         concb((char)escape);            /* Put console in cbreak mode */
7476         cmini(0);                       /* No echo */
7477         prompt(xxstring);
7478         debok = 0;
7479         for (x = -1; x < 0 && x != -3; ) { /* Get answer */
7480             cmres();                    /* Reset the parser */
7481             x = cmtxt("","",&s,NULL);   /* Get literal line of text */
7482         }
7483         if ((p2 = malloc((int)strlen(s) + 1)) == NULL) {
7484             printf("?Internal error: malloc\n");
7485             goto XZXLGI;
7486         } else
7487           strcpy(p2,s);                 /* safe */
7488         printf("\r\n");
7489         if ((rc = cmcfm()) < 0)
7490           goto XZXLGI;
7491     }
7492     sstate = setgen('I',p1,p2,p3);      /* Get here with at least user ID */
7493     rc = 0;
7494
7495   XZXLGI:                               /* Common exit point */
7496     if (psaved)
7497       cmsetp(psave);                    /* Restore original prompt */
7498     if (p3) { free(p3); p3 = NULL; }    /* Free malloc'd storage */
7499     if (p2) { free(p2); p2 = NULL; }
7500     if (p1) { free(p1); p1 = NULL; }
7501     if (rc > -1) {
7502         if (local && rc > -1)           /* If local, flush tty input buffer */
7503           ttflui();
7504     }
7505     return(rc);
7506 }
7507
7508 #ifdef OS2
7509 #ifndef NOLOCAL
7510 int
7511 dormt(xx) int xx; {
7512     int rc = 0;
7513     extern int term_io;
7514     int term_io_sav = term_io;
7515 #ifdef NEWFTP
7516     extern int ftpget, ftpisopen();
7517     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
7518       return(doftprmt(xx,0));
7519 #endif /* NEWFTP */
7520     term_io = 0;
7521     rc = xxdormt(xx);
7522     term_io = term_io_sav;
7523     return rc;
7524 }
7525
7526
7527 int
7528 xxdormt(xx) int xx;
7529 #else /* NOLOCAL */
7530 int
7531 dormt(xx) int xx;
7532 #endif /* NOLOCAL */
7533 #else /* OS2 */
7534 int
7535 dormt(xx) int xx;
7536 #endif /* OS2 */
7537 {                                       /* REMOTE commands */
7538     int x, y, retcode;
7539     char *s, sbuf[50], *s2;
7540
7541 #ifdef NEWFTP
7542     extern int ftpget, ftpisopen();
7543     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
7544       return(doftprmt(xx,0));
7545 #endif /* NEWFTP */
7546
7547     remfile = 0;                        /* Clear these */
7548     rempipe = 0;
7549     remappd = 0;
7550
7551     if (xx < 0) return(xx);             /* REMOTE what? */
7552
7553     xzcmd = xx;                         /* Make global copy of arg */
7554
7555     if (xx == XZSET) {                  /* REMOTE SET */
7556         if ((y = cmkey(rmstab,nrms,"","",xxstring)) < 0) {
7557             if (y == -3) {
7558                 printf("?Parameter name required\n");
7559                 return(-9);
7560             } else return(y);
7561         }
7562         return(doprm(y,1));
7563     }
7564
7565     switch (xx) {                       /* Others... */
7566
7567       case XZCDU:
7568         if ((x = cmcfm()) < 0) return(x);
7569         printf("?Sorry, REMOTE CDUP not supported yet\n");
7570         return(-9);
7571
7572       case XZCWD:                       /* CWD (CD) */
7573         if ((x = cmtxt("Remote directory name","",&s,xxstring)) < 0)
7574           return(x);
7575         if ((x = remtxt(&s)) < 0)
7576           return(x);
7577         debug(F111,"XZCWD: ",s,x);
7578         *sbuf = NUL;
7579         s2 = sbuf;
7580 /*
7581   The following is commented out because since the disappearance of the
7582   DECSYSTEM-20 from the planet, no known computer requires a password for
7583   changing directory.
7584 */
7585 #ifdef DIRPWDPR
7586         if (*s != NUL) {                /* If directory name given, */
7587                                         /* get password on separate line. */
7588             if (tlevel > -1) {          /* From take file... */
7589
7590                 if (fgets(sbuf,50,tfile[tlevel]) == NULL)
7591                   fatal("take file ends prematurely in 'remote cwd'");
7592                 debug(F110," pswd from take file",s2,0);
7593                 for (x = (int)strlen(sbuf);
7594                      x > 0 && (sbuf[x-1] == NL || sbuf[x-1] == CR);
7595                      x--)
7596                   sbuf[x-1] = '\0';
7597
7598             } else {                    /* From terminal... */
7599
7600                 printf(" Password: ");  /* get a password */
7601 #ifdef IKSD
7602                 if (!local && inserver) {
7603                     x = coninc(0);
7604                 } else
7605 #endif /* IKSD */
7606 #ifdef OS2
7607                   x = is_a_tty(0) ? coninc(0) : /* with no echo ... */
7608                     getchar();
7609 #else /* OS2 */
7610                 x = getchar();
7611 #endif /* OS2 */
7612                 while ((x != NL) && (x != CR)) {
7613                     if ((x &= 0177) == '?') {
7614                         printf("? Password of remote directory\n Password: ");
7615                         s2 = sbuf;
7616                         *sbuf = NUL;
7617                     } else if (x == ESC) /* Mini command line editor... */
7618                       bleep(BP_WARN);
7619                     else if (x == BS || x == 0177)
7620                       s2--;
7621                     else if (x == 025) {        /* Ctrl-U */
7622                         s2 = sbuf;
7623                         *sbuf = NUL;
7624                     } else
7625                       *s2++ = x;
7626
7627                     /* Get the next character */
7628 #ifdef IKSD
7629                     if (!local && inserver) {
7630                         x = coninc(0);
7631                     } else
7632 #endif /* IKSD */
7633 #ifdef OS2
7634                     x = is_a_tty(0) ? coninc(0) : /* with no echo ... */
7635                       getchar();
7636 #else /* OS2 */
7637                     x = getchar();
7638 #endif /* OS2 */
7639                 }
7640                 *s2 = NUL;
7641                 putchar('\n');
7642             }
7643             s2 = sbuf;
7644         } else s2 = "";
7645 #endif /* DIRPWDPR */
7646
7647         debug(F110," password",s2,0);
7648         rcdactive = 1;
7649         sstate = setgen('C',s,s2,"");
7650         retcode = 0;
7651         break;
7652
7653       case XZDEL:                               /* Delete */
7654         if ((x = cmtxt("Name of remote file(s) to delete",
7655                        "",&s,xxstring)) < 0) {
7656             if (x == -3) {
7657                 printf("?Name of remote file(s) required\n");
7658                 return(-9);
7659             } else return(x);
7660         }
7661         if ((x = remtxt(&s)) < 0)
7662           return(x);
7663         if (local) ttflui();            /* If local, flush tty input buffer */
7664         retcode = sstate = rfilop(s,'E');
7665         break;
7666
7667       case XZDIR:                       /* Directory */
7668         if ((x = cmtxt("Remote directory or file specification","",&s,
7669                        xxstring)) < 0)
7670           return(x);
7671         if ((x = remtxt(&s)) < 0)
7672           return(x);
7673         if (local) ttflui();            /* If local, flush tty input buffer */
7674         rmsg();
7675         retcode = sstate = setgen('D',s,"","");
7676         break;
7677
7678       case XZHLP:                       /* Help */
7679         if ((x = remcfm()) < 0) return(x);
7680         sstate = setgen('H',"","","");
7681         retcode = 0;
7682         break;
7683
7684       case XZHOS:                       /* Host */
7685         if ((x = cmtxt("Command for remote system","",&s,xxstring)) < 0)
7686           return(x);
7687         if ((x = remtxt(&s)) < 0)
7688           return(x);
7689         if ((y = (int)strlen(s)) < 1)
7690           return(x);
7691         ckstrncpy(line,s,LINBUFSIZ);
7692         cmarg = line;
7693         rmsg();
7694         retcode = sstate = 'c';
7695         break;
7696
7697 #ifndef NOFRILLS
7698       case XZKER:
7699         if ((x = cmtxt("Command for remote Kermit","",&s,xxstring)) < 0)
7700           return(x);
7701         if ((x = remtxt(&s)) < 0)
7702           return(x);
7703         if ((int)strlen(s) < 1)  {
7704             if (x == -3) {
7705                 printf("?Remote Kermit command required\n");
7706                 return(-9);
7707             } else return(x);
7708         }
7709         ckstrncpy(line,s,LINBUFSIZ);
7710         cmarg = line;
7711         retcode = sstate = 'k';
7712         rmsg();
7713         break;
7714
7715       case XZLGI:                       /* Login */
7716         rcdactive = 1;                  /* Suppress "Logged in" msg if quiet */
7717         return(plogin(XXREM));
7718
7719       case XZLGO: {                     /* Logout */
7720           extern int bye_active;
7721           if ((x = remcfm()) < 0) return(x);
7722           sstate = setgen('I',"","","");
7723           retcode = 0;
7724           bye_active = 1;               /* Close connection when done */
7725           break;
7726       }
7727
7728       case XZPRI:                       /* Print */
7729         if (!atdiso || !atcapr) {       /* Disposition attribute off? */
7730             printf("?Disposition Attribute is Off\n");
7731             return(-2);
7732         }
7733         cmarg = "";
7734         cmarg2 = "";
7735         if ((x = cmifi("Local file(s) to print on remote printer","",&s,&y,
7736                        xxstring)) < 0) {
7737             if (x == -3) {
7738                 printf("?Name of local file(s) required\n");
7739                 return(-9);
7740             }
7741             return(x);
7742         }
7743         ckstrncpy(line,s,LINBUFSIZ);    /* Make a safe copy of filename */
7744         *optbuf = NUL;                  /* Wipe out any old options */
7745         if ((x = cmtxt("Options for remote print command","",&s,xxstring)) < 0)
7746           return(x);
7747         if ((x = remtxt(&s)) < 0)
7748           return(x);
7749         if ((int)strlen(optbuf) > 94) { /* Make sure this is legal */
7750             printf("?Option string too long\n");
7751             return(-9);
7752         }
7753         ckstrncpy(optbuf,s,OPTBUFLEN);  /* Make a safe copy of options */
7754         nfils = -1;                     /* Expand file list internally */
7755         cmarg = line;                   /* Point to file list. */
7756         rprintf = 1;                    /* REMOTE PRINT modifier for SEND */
7757         sstate = 's';                   /* Set start state to SEND */
7758         if (local) displa = 1;
7759         retcode = 0;
7760         break;
7761 #endif /* NOFRILLS */
7762
7763       case XZSPA:                       /* Space */
7764         if ((x = cmtxt("Confirm, or remote directory name",
7765                        "",&s,xxstring)) < 0)
7766           return(x);
7767         if ((x = remtxt(&s)) < 0)
7768           return(x);
7769         retcode = sstate = setgen('U',s,"","");
7770         break;
7771
7772       case XZMSG:                       /* Message */
7773         if ((x = cmtxt("Short text message for server","",&s,xxstring)) < 0)
7774           return(x);
7775         if ((x = remtxt(&s)) < 0)
7776           return(x);
7777         retcode = sstate = setgen('M',s,"","");
7778         break;
7779
7780 #ifndef NOFRILLS
7781       case XZTYP:                       /* Type */
7782         if ((x = cmtxt("Remote file specification","",&s,xxstring)) < 0)
7783           return(x);
7784         if ((int)strlen(s) < 1) {
7785             printf("?Remote filename required\n");
7786             return(-9);
7787         }
7788         if ((x = remtxt(&s)) < 0)
7789           return(x);
7790         rmsg();
7791         retcode = sstate = rfilop(s,'T');
7792         break;
7793 #endif /* NOFRILLS */
7794
7795 #ifndef NOFRILLS
7796       case XZWHO:
7797         if ((x = cmtxt("Remote user name, or carriage return",
7798                        "",&s,xxstring)) < 0)
7799           return(x);
7800         if ((x = remtxt(&s)) < 0)
7801           return(x);
7802         retcode = sstate = setgen('W',s,"","");
7803         break;
7804 #endif /* NOFRILLS */
7805
7806       case XZPWD:                       /* PWD */
7807         if ((x = remcfm()) < 0) return(x);
7808         sstate = setgen('A',"","","");
7809         retcode = 0;
7810         break;
7811
7812 #ifndef NOSPL
7813       case XZQUE: {                     /* Query */
7814           char buf[2];
7815           extern char querybuf[], * qbufp;
7816           extern int qbufn;
7817           if ((y = cmkey(vartyp,nvartyp,"","",xxstring)) < 0)
7818             return(y);
7819           if ((x = cmtxt(y == 'F' ? "Remote function invocation" :
7820                          ('K' ? "Remote variable name or function":
7821                          "Remote variable name"),
7822                          "",
7823                          &s,
7824                          (y == 'K') ? xxstring : NULL
7825                          )) < 0)        /* Don't evaluate */
7826             return(x);
7827           if ((x = remtxt(&s)) < 0)
7828             return(x);
7829           query = 1;                    /* QUERY is active */
7830           qbufp = querybuf;             /* Initialize query response buffer */
7831           qbufn = 0;
7832           querybuf[0] = NUL;
7833           buf[0] = (char) (y & 127);
7834           buf[1] = NUL;
7835           retcode = sstate = setgen('V',"Q",(char *)buf,s);
7836           break;
7837       }
7838
7839       case XZASG: {                     /* Assign */
7840           char buf[VNAML];
7841           if ((y = cmfld("Remote variable name","",&s,NULL)) < 0) /* No eval */
7842             return(y);
7843           if ((int)strlen(s) >= VNAML) {
7844               printf("?Too long\n");
7845               return(-9);
7846           }
7847           ckstrncpy(buf,s,VNAML);
7848           if ((x = cmtxt("Assignment for remote variable",
7849                    "",&s,xxstring)) < 0) /* Evaluate this one */
7850             return(x);
7851           if ((x = remtxt(&s)) < 0)
7852             return(x);
7853 #ifdef COMMENT
7854 /*
7855   Server commands can't be long packets.  In principle there's no reason
7856   why they shouldn't be, except that we don't know at this point if the
7857   server is capable of accepting long packets because we haven't started
7858   the protocol yet.  In practice, allowing a long packet here breaks a lot
7859   of assumptions, causes buffer overruns and crashes, etc.  To be fixed
7860   later.  (But since this is commented out, evidently I fixed it later...)
7861 */
7862           if ((int)strlen(s) > 85) {    /* Allow for encoding expansion */
7863               printf("?Sorry, value is too long - 85 characters max\n");
7864               return(-9);
7865           }
7866 #endif /* COMMENT */
7867           retcode = sstate = setgen('V',"S",(char *)buf,s);
7868           break;
7869       }
7870 #endif /* NOSPL */
7871
7872       case XZCPY: {                     /* COPY */
7873           char buf[TMPBUFSIZ];
7874           buf[TMPBUFSIZ-1] = '\0';
7875           if ((x = cmfld("Name of remote file to copy","",&s,xxstring)) < 0) {
7876               if (x == -3) {
7877                   printf("?Name of remote file required\n");
7878                   return(-9);
7879               }
7880               else
7881                 return(x);
7882           }
7883           ckstrncpy(buf,s,TMPBUFSIZ);
7884           if ((x = cmfld("Name of remote destination file or directory",
7885                          "",&s, xxstring)) < 0) {
7886               if (x == -3) {
7887                   printf("?Name of remote file or directory required\n");
7888                   return(-9);
7889               } else return(x);
7890           }
7891           ckstrncpy(tmpbuf,s,TMPBUFSIZ);
7892           if ((x = remcfm()) < 0)
7893             return(x);
7894           if (local) ttflui();          /* If local, flush tty input buffer */
7895           retcode = sstate = setgen('K',buf,tmpbuf,"");
7896           break;
7897       }
7898       case XZREN: {                     /* Rename */
7899           char buf[TMPBUFSIZ];
7900           buf[TMPBUFSIZ-1] = '\0';
7901           if ((x = cmfld("Name of remote file to rename",
7902                          "",&s,xxstring)) < 0) {
7903               if (x == -3) {
7904                   printf("?Name of remote file required\n");
7905                   return(-9);
7906               } else return(x);
7907           }
7908           ckstrncpy(buf,s,TMPBUFSIZ);
7909           if ((x = cmfld("New name of remote file","",&s, xxstring)) < 0) {
7910               if (x == -3) {
7911                   printf("?Name of remote file required\n");
7912                   return(-9);
7913               } else return(x);
7914           }
7915           ckstrncpy(tmpbuf,s,TMPBUFSIZ);
7916           if ((x = remcfm()) < 0)
7917             return(x);
7918           if (local) ttflui();          /* If local, flush device buffer */
7919           retcode = sstate = setgen('R',buf,tmpbuf,"");
7920           break;
7921       }
7922       case XZMKD:                       /* mkdir */
7923       case XZRMD:                       /* rmdir */
7924         if ((x = cmtxt((xx == XZMKD) ?
7925                        "Name of remote directory to create" :
7926                        "Name of remote directory to delete",
7927                        "",
7928                        &s,
7929                        xxstring
7930                        )) < 0) {
7931             if (x == -3) {
7932                 printf("?Name required\n");
7933                 return(-9);
7934             } else return(x);
7935         }
7936         if ((x = remtxt(&s)) < 0)
7937           return(x);
7938         if (local) ttflui();            /* If local, flush tty input buffer */
7939         retcode = sstate = rfilop(s, (char)(xx == XZMKD ? 'm' : 'd'));
7940         break;
7941
7942       case XZXIT:                       /* Exit */
7943         if ((x = remcfm()) < 0) return(x);
7944         sstate = setgen('X',"","","");
7945         retcode = 0;
7946         break;
7947
7948       default:
7949         if ((x = remcfm()) < 0) return(x);
7950         printf("?Not implemented - %s\n",cmdbuf);
7951         return(-2);
7952     }
7953     if (local && retcode > -1)          /* If local, flush tty input buffer */
7954       ttflui();
7955     return(retcode);
7956 }
7957
7958
7959 /*  R F I L O P  --  Remote File Operation  */
7960
7961 CHAR
7962 #ifdef CK_ANSIC
7963 rfilop(char * s, char t)
7964 #else
7965 rfilop(s,t) char *s, t;
7966 #endif /* CK_ANSIC */
7967 /* rfilop */ {
7968     if (*s == NUL) {
7969         printf("?File specification required\n");
7970         return((CHAR) 0);
7971     }
7972     debug(F111,"rfilop",s,t);
7973     return(setgen(t,s,"",""));
7974 }
7975 #endif /* NOXFER */
7976
7977 #ifdef ANYX25
7978 int
7979 setx25() {
7980     if ((y = cmkey(x25tab,nx25,"X.25 call options","",xxstring)) < 0)
7981       return(y);
7982     switch (y) {
7983       case XYUDAT:
7984         if ((z = cmkey(onoff,2,"X.25 call user data","",xxstring))
7985             < 0) return(z);
7986         if (z == 0) {
7987             if ((z = cmcfm()) < 0) return(z);
7988             cudata = 0;             /* disable call user data */
7989             return (success = 1);
7990         }
7991         if ((x = cmtxt("X.25 call user data string","",&s,xxstring)) < 0)
7992           return(x);
7993         if ((int)strlen(s) == 0) {
7994             return (-3);
7995         } else if ((int)strlen(s) > MAXCUDATA) {
7996             printf("?The length must be > 0 and <= %d\n",MAXCUDATA);
7997             return(-2);
7998         }
7999         if ((y = cmcfm()) < 0) return(y);
8000         ckstrncpy(udata,s,MAXCUDATA);
8001         cudata = 1;                     /* X.25 call user data specified */
8002         return (success = 1);
8003       case XYCLOS:
8004         if ((z = cmkey(onoff,2,"X.25 closed user group call","",xxstring))
8005             < 0) return(z);
8006         if (z == 0) {
8007             if ((z = cmcfm()) < 0) return(z);
8008             closgr = -1;                /* disable closed user group */
8009             return (success = 1);
8010         }
8011         if ((y = cmnum("0 <= cug index >= 99","",10,&x,xxstring)) < 0)
8012           return(y);
8013         if (x < 0 || x > 99) {
8014             printf("?The choices are 0 <= cug index >= 99\n");
8015             return(-2);
8016         }
8017         if ((y = cmcfm()) < 0) return(y);
8018         closgr = x;                     /* closed user group selected */
8019         return (success = 1);
8020
8021       case XYREVC:
8022         if((z = cmkey(onoff,2,"X.25 reverse charge call","",xxstring)) < 0)
8023           return(z);
8024         if ((x = cmcfm()) < 0) return(x);
8025         revcall = z;
8026         return (success = 1);
8027     }
8028 }
8029
8030 #ifndef IBMX25
8031 int
8032 setpadp() {
8033     if ((y = cmkey(padx3tab,npadx3,"PAD X.3 parameter name","",xxstring)) < 0)
8034       return(y);
8035     x = y;
8036     switch (x) {
8037       case PAD_BREAK_CHARACTER:
8038         if ((y = cmnum("PAD break character value","",10,&z,xxstring)) < 0)
8039           return(y);
8040         if ((y = cmcfm()) < 0) return(y);
8041         break;
8042       case PAD_ESCAPE:
8043         if ((y = cmnum("PAD escape","",10,&z,xxstring)) < 0) return(y);
8044         if (z != 0 && z != 1) {
8045             printf("?The choices are 0 or 1\n");
8046             return(-2);
8047         }
8048         if ((y = cmcfm()) < 0) return(y);
8049         break;
8050       case PAD_ECHO:
8051         if ((y = cmnum("PAD echo","",10,&z,xxstring)) < 0) return(y);
8052         if (z != 0 && z != 1) {
8053             printf("?The choices are 0 or 1\n");
8054             return(-2);
8055         }
8056         if ((y = cmcfm()) < 0) return(y);
8057         break;
8058       case PAD_DATA_FORWARD_CHAR:
8059         if ((y = cmnum("PAD data forward char","",10,&z,xxstring)) < 0)
8060           return(y);
8061         if (z != 0 && z != 2) {
8062             printf("?The choices are 0 or 2\n");
8063             return(-2);
8064         }
8065         if ((y = cmcfm()) < 0) return(y);
8066         break;
8067       case PAD_DATA_FORWARD_TIMEOUT:
8068         if ((y = cmnum("PAD data forward timeout","",10,&z,xxstring)) < 0)
8069             return(y);
8070         if (z < 0 || z > 255) {
8071             printf("?The choices are 0 or 1 <= timeout <= 255\n");
8072             return(-2);
8073         }
8074         if ((y = cmcfm()) < 0) return(y);
8075         break;
8076       case PAD_FLOW_CONTROL_BY_PAD:
8077         if ((y = cmnum("PAD pad flow control","",10,&z,xxstring)) < 0)
8078           return(y);
8079         if (z != 0 && z != 1) {
8080             printf("?The choices are 0 or 1\n");
8081             return(-2);
8082         }
8083         if ((y = cmcfm()) < 0) return(y);
8084         break;
8085       case PAD_SUPPRESSION_OF_SIGNALS:
8086         if ((y = cmnum("PAD service","",10,&z,xxstring)) < 0) return(y);
8087         if (z != 0 && z != 1) {
8088             printf("?The choices are 0 or 1\n");
8089             return(-2);
8090         }
8091         if ((y = cmcfm()) < 0) return(y);
8092         break;
8093
8094       case PAD_BREAK_ACTION:
8095         if ((y = cmnum("PAD break action","",10,&z,xxstring)) < 0) return(y);
8096         if (z != 0 && z != 1 && z != 2 && z != 5 && z != 8 && z != 21) {
8097             printf("?The choices are 0, 1, 2, 5, 8 or 21\n");
8098             return(-2);
8099         }
8100         if ((y = cmcfm()) < 0) return(y);
8101         break;
8102
8103       case PAD_SUPPRESSION_OF_DATA:
8104         if ((y = cmnum("PAD data delivery","",10,&z,xxstring)) < 0) return(y);
8105         if (z != 0 && z != 1) {
8106             printf("?The choices are 0 or 1\n");
8107             return(-2);
8108         }
8109         if ((y = cmcfm()) < 0) return(y);
8110         break;
8111
8112       case PAD_PADDING_AFTER_CR:
8113         if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
8114         if (z < 0 || z > 7) {
8115             printf("?The choices are 0 or 1 <= crpad <= 7\n");
8116             return(-2);
8117         }
8118         if ((y = cmcfm()) < 0) return(y);
8119         break;
8120
8121       case PAD_LINE_FOLDING:
8122         if ((y = cmnum("PAD linefold","",10,&z,xxstring)) < 0) return(y);
8123         if (z < 0 || z > 255) {
8124             printf("?The choices are 0 or 1 <= linefold <= 255\n");
8125             return(-2);
8126         }
8127         if ((y = cmcfm()) < 0) return(y);
8128         break;
8129
8130       case PAD_LINE_SPEED:
8131         if ((y = cmnum("PAD baudrate","",10,&z,xxstring)) < 0) return(y);
8132         if (z < 0 || z > 18) {
8133             printf("?The choices are 0 <= baudrate <= 18\n");
8134             return(-2);
8135         }
8136         if ((y = cmcfm()) < 0) return(y);
8137         break;
8138
8139       case PAD_FLOW_CONTROL_BY_USER:
8140         if ((y = cmnum("PAD terminal flow control","",10,&z,xxstring)) < 0)
8141             return(y);
8142         if (z != 0 && z != 1) {
8143             printf("?The choices are 0 or 1\n");
8144             return(-2);
8145         }
8146         if ((y = cmcfm()) < 0) return(y);
8147         break;
8148
8149       case PAD_LF_AFTER_CR:
8150         if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
8151         if (z < 0 || z == 3 || z > 7) {
8152             printf("?The choices are 0, 1, 2, 4, 5, 6 or 7\n");
8153             return(-2);
8154         }
8155         if ((y = cmcfm()) < 0) return(y);
8156         break;
8157
8158       case PAD_PADDING_AFTER_LF:
8159         if ((y = cmnum("PAD lfpad","",10,&z,xxstring)) < 0) return(y);
8160         if (z < 0 || z > 7) {
8161             printf("?The choices are 0 or 1 <= lfpad <= 7\n");
8162             return(-2);
8163         }
8164         if ((y = cmcfm()) < 0) return(y);
8165         break;
8166
8167       case PAD_EDITING:
8168         if ((y = cmnum("PAD edit control","",10,&z,xxstring)) < 0) return(y);
8169         if (z != 0 && z != 1) {
8170             printf("?The choices are 0 or 1\n");
8171             return(-2);
8172         }
8173         if ((y = cmcfm()) < 0) return(y);
8174         break;
8175
8176       case PAD_CHAR_DELETE_CHAR:
8177         if ((y = cmnum("PAD char delete char","",10,&z,xxstring)) < 0)
8178             return(y);
8179         if (z < 0 || z > 127) {
8180             printf("?The choices are 0 or 1 <= chardelete <= 127\n");
8181             return(-2);
8182         }
8183         if ((y = cmcfm()) < 0) return(y);
8184         break;
8185
8186       case PAD_BUFFER_DELETE_CHAR:
8187         if ((y = cmnum("PAD buffer delete char","",10,&z,xxstring)) < 0)
8188             return(y);
8189         if (z < 0 || z > 127) {
8190             printf("?The choices are 0 or 1 <= bufferdelete <= 127\n");
8191             return(-2);
8192         }
8193         if ((y = cmcfm()) < 0) return(y);
8194         break;
8195
8196       case PAD_BUFFER_DISPLAY_CHAR:
8197         if ((y = cmnum("PAD display line char","",10,&z,xxstring)) < 0)
8198             return(y);
8199         if (z < 0 || z > 127) {
8200             printf("?The choices are 0 or 1 <= displayline <= 127\n");
8201             return(-2);
8202         }
8203         if ((y = cmcfm()) < 0) return(y);
8204         break;
8205     }
8206     padparms[x] = z;
8207     return(success = 1);
8208 }
8209 #endif /* IBMX25 */
8210 #endif /* ANYX25 */
8211
8212 #ifndef NOXFER
8213 int
8214 setat(rmsflg) int rmsflg; {
8215     int xx;
8216     if ((y = cmkey(attrtab,natr,"File Attribute packets","",xxstring)) < 0)
8217       return(y);
8218     if (y == AT_XALL) {                 /* ATTRIBUTES ALL ON or ALL OFF */
8219         if ((z = seton(&xx)) < 0) return(z);
8220         if (rmsflg) {
8221             printf("Sorry, command not available\n");
8222             return(-9);
8223         } else {
8224             atenci = xx;                /* Encoding in */
8225             atenco = xx;                /* Encoding out */
8226             atdati = xx;                /* Date in */
8227             atdato = xx;                /* Date out */
8228             atdisi = xx;                /* Disposition in/out */
8229             atdiso = xx;
8230             atleni = xx;                /* Length in/out (both kinds) */
8231             atleno = xx;
8232             atblki = xx;                /* Blocksize in/out */
8233             atblko = xx;
8234             attypi = xx;                /* File type in/out */
8235             attypo = xx;
8236             atsidi = xx;                /* System ID in/out */
8237             atsido = xx;
8238             atsysi = xx;                /* System-dependent params in/out */
8239             atsyso = xx;
8240 #ifdef CK_PERMS                         /* Protection */
8241             atlpri = xx;                /* Local in */
8242             atlpro = xx;                /* Local out */
8243             atgpri = xx;                /* Generic in */
8244             atgpro = xx;                /* Generic out */
8245 #endif /* CK_PERMS */
8246 #ifdef STRATUS
8247             atfrmi = xx;                /* Format in/out */
8248             atfrmo = xx;
8249             atcrei = xx;                /* Creator id in/out */
8250             atcreo = xx;
8251             atacti = xx;                /* Account in/out */
8252             atacto = xx;
8253 #endif /* STRATUS */
8254         }
8255         return(z);
8256     } else if (y == AT_ALLY || y == AT_ALLN) { /* ATTRIBUTES ON or OFF */
8257         if ((x = cmcfm()) < 0) return(x);
8258         atcapr = (y == AT_ALLY) ? 1 : 0;
8259         if (rmsflg) {
8260             sstate = setgen('S', "132", atcapr ? "1" : "0", "");
8261             return((int) sstate);
8262         } else return(success = 1);
8263     }
8264     /* Otherwise, it's an individual attribute that wants turning off/on */
8265
8266     if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
8267     if ((x = cmcfm()) < 0) return(x);
8268
8269 /* There are better ways to do this... */
8270 /* The real problem is that we're not separating the in and out cases */
8271 /* and so we have to arbitrarily pick the "in" case, i.e tell the remote */
8272 /* server to ignore incoming attributes of the specified type, rather */
8273 /* than telling it not to send them.  The protocol does not (yet) define */
8274 /* codes for "in-and-out-at-the-same-time". */
8275
8276     switch (y) {
8277 #ifdef CK_PERMS
8278 /* We're lumping local and generic protection together for now... */
8279       case AT_LPRO:
8280       case AT_GPRO:
8281         if (rmsflg) {
8282             sstate = setgen('S', "143", z ? "1" : "0", "");
8283             return((int) sstate);
8284         }
8285         atlpri = atlpro = atgpri = atgpro = z; break;
8286 #endif /* CK_PERMS */
8287       case AT_DISP:
8288         if (rmsflg) {
8289             sstate = setgen('S', "142", z ? "1" : "0", "");
8290             return((int) sstate);
8291         }
8292         atdisi = atdiso = z; break;
8293       case AT_ENCO:
8294         if (rmsflg) {
8295             sstate = setgen('S', "141", z ? "1" : "0", "");
8296             return((int) sstate);
8297         }
8298         atenci = atenco = z; break;
8299       case AT_DATE:
8300         if (rmsflg) {
8301             sstate = setgen('S', "135", z ? "1" : "0", "");
8302             return((int) sstate);
8303         }
8304         atdati = atdato = z; break;
8305       case AT_LENB:
8306       case AT_LENK:
8307         if (rmsflg) {
8308             sstate = setgen('S', "133", z ? "1" : "0", "");
8309             return((int) sstate);
8310         }
8311         atleni = atleno = z; break;
8312       case AT_BLKS:
8313         if (rmsflg) {
8314             sstate = setgen('S', "139", z ? "1" : "0", "");
8315             return((int) sstate);
8316         }
8317         atblki = atblko = z; break;
8318       case AT_FTYP:
8319         if (rmsflg) {
8320             sstate = setgen('S', "134", z ? "1" : "0", "");
8321             return((int) sstate);
8322         }
8323         attypi = attypo = z; break;
8324 #ifdef STRATUS
8325       case AT_CREA:
8326         if (rmsflg) {
8327             sstate = setgen('S', "136", z ? "1" : "0", "");
8328             return((int) sstate);
8329         }
8330         atcrei = atcreo = z; break;
8331       case AT_ACCT:
8332         if (rmsflg) {
8333             sstate = setgen('S', "137", z ? "1" : "0", "");
8334             return((int) sstate);
8335         }
8336         atacti = atacto = z; break;
8337 #endif /* STRATUS */
8338       case AT_SYSI:
8339         if (rmsflg) {
8340             sstate = setgen('S', "145", z ? "1" : "0", "");
8341             return((int) sstate);
8342         }
8343         atsidi = atsido = z; break;
8344       case AT_RECF:
8345         if (rmsflg) {
8346             sstate = setgen('S', "146", z ? "1" : "0", "");
8347             return((int) sstate);
8348         }
8349         atfrmi = atfrmo = z; break;
8350       case AT_SYSP:
8351         if (rmsflg) {
8352             sstate = setgen('S', "147", z ? "1" : "0", "");
8353             return((int) sstate);
8354         }
8355         atsysi = atsyso = z; break;
8356       default:
8357         printf("?Not available\n");
8358         return(-2);
8359     }
8360     return(1);
8361 }
8362 #endif /* NOXFER */
8363
8364 #ifndef NOSPL
8365 int
8366 setinp() {
8367     if ((y = cmkey(inptab,ninp,"","",xxstring)) < 0) return(y);
8368     switch (y) {
8369 #ifdef OS2
8370       case IN_PAC:                      /* SET INPUT PACING */
8371         z = cmnum("milliseconds","0",10,&x,xxstring);
8372         return(setnum(&tt_inpacing,x,z,1000));
8373       case IN_TRM:                      /* SET INPUT TERMINAL */
8374         return(seton(&interm));
8375 #endif /* OS2 */
8376       case IN_DEF:                      /* SET INPUT DEFAULT-TIMEOUT */
8377         z = cmnum("Positive number","",10,&x,xxstring);
8378         return(setnum(&indef,x,z,94));
8379 #ifdef CKFLOAT
8380       case IN_SCA:                      /* SET INPUT SCALE-FACTOR */
8381         if ((x = cmfld("Number such as 2 or 0.5","1.0",&s, xxstring)) < 0)
8382           return(x);
8383         if (isfloat(s,0)) {             /* A floating-point number? */
8384             extern char * inpscale;
8385             inscale = floatval;         /* Yes, get its value */
8386             makestr(&inpscale,s);       /* Save it as \v(inscale) */
8387             return(success = 1);
8388         } else {
8389             return(-2);
8390         }
8391 #endif  /* CKFLOAT */
8392       case IN_TIM:                      /* SET INPUT TIMEOUT-ACTION */
8393         if ((z = cmkey(intimt,2,"","",xxstring)) < 0) return(z);
8394         if ((x = cmcfm()) < 0) return(x);
8395         intime[cmdlvl] = z;
8396         return(success = 1);
8397       case IN_CAS:                      /* SET INPUT CASE */
8398         if ((z = cmkey(incast,2,"","",xxstring)) < 0) return(z);
8399         if ((x = cmcfm()) < 0) return(x);
8400         inpcas[cmdlvl] = z;
8401         return(success = 1);
8402       case IN_ECH:                      /* SET INPUT ECHO */
8403         return(seton(&inecho));
8404       case IN_SIL:                      /* SET INPUT SILENCE */
8405         z = cmnum("Seconds of inactivity before INPUT fails","",10,&x,
8406                   xxstring);
8407         return(setnum(&insilence,x,z,-1));
8408
8409       case IN_BUF:                      /* SET INPUT BUFFER-SIZE */
8410         if ((z = cmnum("Number of bytes in INPUT buffer",
8411                        ckitoa(INPBUFSIZ),10,&x, xxstring)) < 0)
8412           return(z);
8413         if ((y = cmcfm()) < 0) return(y);
8414         inbufsize = 0;
8415         if (inpbuf) {
8416             free(inpbuf);
8417             inpbuf = NULL;
8418             inpbp = NULL;
8419         }
8420         if (!(s = (char *)malloc(x + 1)))
8421           return(0);
8422         inpbuf = s;
8423         inpbp = s;
8424         inbufsize = x;
8425         for (x = 0; x <= inbufsize; x++)
8426           inpbuf[x] = NUL;
8427         return(success = 1);
8428
8429 #ifdef CK_AUTODL
8430       case IN_ADL:                      /* AUTODOWNLOAD */
8431         return(seton(&inautodl));
8432 #endif /* CK_AUTODL */
8433
8434       case IN_CAN:                      /* SET INPUT INTERRUPTS */
8435         return(seton(&inintr));
8436     }
8437     return(0);
8438 }
8439 #endif /* NOSPL */
8440
8441 #ifdef NETCONN
8442 VOID
8443 ndreset() {
8444 #ifndef NODIAL                          /* This depends on DIAL... */
8445     int i=0, j=0;
8446     if (!ndinited)                      /* Don't free garbage... */
8447       return;
8448     for (i = 0; i < nhcount; i++) {     /* Clean out previous list */
8449         if (nh_p[i])
8450           free(nh_p[i]);
8451         nh_p[i] = NULL;
8452         if (nh_p2[i])
8453           free(nh_p2[i]);
8454         nh_p2[i] = NULL;
8455         for (j = 0; j < 4; j++) {
8456             if (nh_px[j][i])
8457               free(nh_px[j][i]);
8458             nh_px[j][i] = NULL;
8459         }
8460     }
8461 #endif /* NODIAL */
8462 }
8463
8464 VOID
8465 ndinit() {                              /* Net directory pointers */
8466 #ifndef NODIAL                          /* This depends on DIAL... */
8467     int i, j;
8468     if (ndinited++)                     /* Don't do this more than once. */
8469       return;
8470     for (i = 0; i < MAXDDIR; i++) {     /* Init all pointers to NULL */
8471         netdir[i] = NULL;
8472     }
8473     for (i = 0; i < MAXDNUMS; i++) {
8474         nh_p[i] = NULL;
8475         nh_p2[i] = NULL;
8476         for (j = 0; j < 4; j++)
8477           nh_px[j][i] = NULL;
8478     }
8479 #endif /* NODIAL */
8480 }
8481
8482 #ifndef NODIAL
8483 #ifdef NETCONN
8484 VOID                                    /* Get net defaults from environment */
8485 getnetenv() {
8486     char *p = NULL;
8487
8488     makestr(&p,getenv("K_NET_DIRECTORY")); /* Dialing directories */
8489     if (p) {
8490         int i;
8491         xwords(p,MAXDDIR,netdir,0);
8492         for (i = 0; i < MAXDDIR; i++) { /* Fill in any gaps... */
8493             if (!netdir[i+1])
8494               break;
8495             else
8496               netdir[i] = netdir[i+1];
8497             debug(F111,"netdir[i]",netdir[i],i);
8498         }
8499         nnetdir = i;
8500     }
8501 }
8502 #endif /* NETCONN */
8503 #endif /* NODIAL */
8504
8505 int
8506 #ifdef CK_ANSIC
8507 lunet(char *s)                          /* s = name to look up   */
8508 #else
8509 lunet(s) char *s;
8510 #endif /* CK_ANSIC */
8511 /* lunet */ {
8512 #ifndef NODIAL                          /* This depends on DIAL... */
8513     int n, n1, t, dd = 0;
8514     int ambiguous = 0;
8515     FILE * f;
8516     char *line = NULL;
8517     extern int dialdpy;
8518     int netdpy = dialdpy;
8519     char *info[8];
8520
8521     nhcount = 0;                        /* Set this before returning */
8522
8523     if (!s || nnetdir < 1)              /* Validate arguments */
8524       return(-1);
8525
8526     if (isdigit(*s) || *s == '*' || *s == '.')
8527       return(0);
8528
8529     if ((n1 = (int) strlen(s)) < 1)     /* Length of string to look up */
8530       return(-1);
8531
8532     if (!(line = malloc(1024)))         /* Allocate input buffer */
8533       return(-1);
8534
8535   lu_again:
8536     f = NULL;                           /* Network directory file descriptor */
8537     t = nhcount = 0;                    /* Match count */
8538     dd = 0;                             /* Directory counter */
8539
8540     dirline = 0;
8541     while (1) {                         /* We make one pass */
8542         if (!f) {                       /* Directory not open */
8543             if (dd >= nnetdir)          /* No directories left? */
8544               break;                    /* Done. */
8545             if ((f = fopen(netdir[dd],"r")) == NULL) { /* Open it */
8546                 perror(netdir[dd]);     /* Can't, print message saying why */
8547                 dd++;
8548                 continue;               /* But go on to next one. */
8549             }
8550             if (netdpy)
8551               printf("Opening %s...\n",netdir[dd]);
8552             dd++;
8553         }
8554         line[0] = NUL;
8555         if (getnct(line,1023,f,1) < 0) { /* Read a line */
8556             if (f) {                    /* f can be clobbered! */
8557                 fclose(f);              /* Close the file */
8558                 f = NULL;               /* Indicate next one needs opening */
8559             }
8560             continue;
8561         }
8562         if (!line[0])                   /* Empty line */
8563           continue;
8564
8565         xwords(line,7,info,0);          /* Parse it */
8566
8567         if (!info[1] || !info[2] || !info[3]) /* Required fields */
8568           continue;
8569         if (*info[1] == ';')            /* Full-line comment */
8570           continue;
8571         if ((n = (int) strlen(info[1])) < 1) /* Length of name-tag */
8572           continue;
8573         if (n < n1)                     /* Search name is longer */
8574           continue;                     /* Can't possibly match */
8575         if (ambiguous && n != n1)
8576           continue;
8577         if (ckstrcmp(s,info[1],n1,0))   /* Compare using length of */
8578           continue;                     /* search string s. */
8579
8580         /* Have a match */
8581
8582         makestr(&(nh_p[nhcount]), info[3]);    /* address */
8583         makestr(&(nh_p2[nhcount]),info[2]);    /* net type */
8584         makestr(&(nh_px[0][nhcount]),info[4]); /* net-specific stuff... */
8585         makestr(&(nh_px[1][nhcount]),info[5]);
8586         makestr(&(nh_px[2][nhcount]),info[6]);
8587         makestr(&(nh_px[3][nhcount]),info[7]);
8588
8589         nhcount++;                      /* Count this match */
8590         if (nhcount > MAXDNUMS) {       /* Watch out for too many */
8591             printf("Warning: %d matches found, %d max\n",
8592                    nhcount,
8593                    MAXDNUMS
8594                    );
8595             nhcount = MAXDNUMS;
8596             break;
8597         }
8598         if (nhcount == 1) {             /* First one - save entry name */
8599             if (n_name) {               /* Free the one from before if any */
8600                 free(n_name);
8601                 n_name = NULL;
8602             }
8603             if (!(n_name = (char *)malloc(n + 1))) { /* Allocate new storage */
8604                 printf("?memory allocation error - lunet:3\n");
8605                 if (line) {
8606                     free(line);
8607                     line = NULL;
8608                 }
8609                 nhcount = 0;
8610                 return(-1);
8611             }
8612             t = n;                      /* Remember its length */
8613             strcpy(n_name,info[1]);     /* safe */
8614         } else {                        /* Second or subsequent one */
8615             if ((int) strlen(info[1]) == t) /* Lengths compare */
8616               if (!ckstrcmp(n_name,info[1],t,0)) /* Caseless compare OK */
8617                 continue;
8618
8619             /* Name given by user matches entries with different names */
8620
8621             if (ambiguous)              /* Been here before */
8622               break;
8623
8624             ambiguous = 1;              /* Now an exact match is required */
8625             ndreset();                  /* Clear out previous list */
8626             goto lu_again;              /* Do it all over again. */
8627         }
8628     }
8629     if (line) {
8630         free(line);
8631         line = NULL;
8632     }
8633     if (nhcount == 0 && ambiguous)
8634       printf("?\"%s\" - ambiguous in network directory\n",s);
8635 #else
8636     nhcount = 0;
8637 #endif /* NODIAL */
8638     return(nhcount);
8639 }
8640 #endif /* NETCONN */
8641
8642 #ifndef NOLOCAL
8643 /*  C L S C O N N X  --  Close connection  */
8644
8645 int
8646 clsconnx(ask) int ask; {
8647     int x, rc = 0;
8648 #ifdef NEWFTP
8649     extern int ftpget, ftpisopen();
8650     if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
8651       return(success = ftpbye());
8652 #endif /* NEWFTP */
8653     debug(F101,"clsconnx local","",local);
8654     if (local) {
8655         x = ask ? hupok(1) : 1;         /* Make sure it's OK to close */
8656         if (!x) {
8657             rc = -1;
8658             debug(F101,"clsconnx hupok says no","",rc);
8659             return(rc);
8660         }
8661         ttflui();                       /* Clear away buffered up junk */
8662 #ifndef NODIAL
8663 #ifdef OS2ONLY
8664 /* Don't hangup a line that is shared with the SLIP or PPP driver */
8665         if (!ttslip && !ttppp)
8666 #endif /* OS2ONLY */
8667           mdmhup();
8668 #endif /* NODIAL */
8669         if (network && msgflg)
8670           printf(" Closing connection\n");
8671         ttclos(0);                      /* Close old connection, if any */
8672         rc = 1;
8673         {
8674             extern int wasclosed, whyclosed;
8675             if (wasclosed) {
8676                 whyclosed = WC_CLOS;
8677 #ifndef NOSPL
8678                 if (nmac) {             /* Any macros defined? */
8679                     int k;              /* Yes */
8680                     /* printf("ON_CLOSE CLSCONNX\n"); */
8681                     wasclosed = 0;
8682                     k = mlook(mactab,"on_close",nmac);  /* Look this up */
8683                     if (k >= 0) {                       /* If found, */
8684                         if (dodo(k,ckitoa(whyclosed),0) > -1) /* set it up, */
8685                           parser(1);                    /* and execute it */
8686                     }
8687                 }
8688 #endif /* NOSPL */
8689                 whyclosed = WC_REMO;
8690                 wasclosed = 0;
8691             }
8692         }
8693     }
8694 #ifdef VMS                              /* Or maybe #ifndef UNIX? */
8695     else {                              /* Need to do this in VMS to */
8696         ttclos(0);                      /* free the tty channel number */
8697         rc = 1;                         /* obtained in ttopen() or else */
8698     }                                   /* subsequent ttopen's won't work */
8699 #endif /* VMS */
8700     dologend();
8701     haveline = 0;
8702     if (mdmtyp < 0) {                   /* Switching from net to async? */
8703         if (mdmsav > -1)                /* Restore modem type from last */
8704           mdmtyp = mdmsav;              /* SET MODEM command, if any. */
8705         else
8706           mdmtyp = 0;
8707         mdmsav = -1;
8708     }
8709     if (network)
8710       network = 0;
8711 #ifdef NETCONN
8712     if (oldplex > -1) {                 /* Restore previous duplex setting. */
8713         duplex = oldplex;
8714         oldplex = -1;
8715     }
8716 #endif /* NETCONN */
8717 #ifndef MAC
8718     ckstrncpy(ttname,dftty,TTNAMLEN);   /* Restore default communication */
8719 #endif /* MAC */
8720     local = dfloc;                      /* device and local/remote status */
8721     if (local) {
8722         cxtype = CXT_DIRECT;            /* Something reasonable */
8723         speed = ttgspd();               /* Get the current speed */
8724     } else {
8725         cxtype = CXT_REMOTE;
8726         speed = -1L;
8727     }
8728 #ifndef NOXFER
8729     if (xreliable > -1 && !setreliable) {
8730         reliable = xreliable;
8731         debug(F101,"clsconnx reliable A","",reliable);
8732     } else if (!setreliable) {
8733         reliable = SET_AUTO;
8734         debug(F101,"clsconnx reliable B","",reliable);
8735     }
8736 #endif /* NOXFER */
8737     setflow();                          /* Revert flow control */
8738     return(rc);
8739 }
8740
8741 int
8742 clskconnx(x) int x; {                   /* Close Kermit connection only */
8743     int t, rc;                          /* (not FTP) */
8744 #ifdef NEWFTP
8745     extern int ftpget;
8746     t = ftpget;
8747     ftpget = 0;
8748 #endif /* NEWFTP */
8749     rc = clsconnx(x);
8750 #ifdef NEWFTP
8751     ftpget = t;
8752 #endif /* NEWFTP */
8753     return(rc);
8754 }
8755
8756 /* May 2002: setlin() decomposition starts here ... */
8757
8758 #ifdef OS2
8759 #define SRVBUFSIZ PIPENAML
8760 #else /* OS2 */
8761 #define SRVBUFSIZ 63
8762 #endif /* OS2 */
8763 #define HOSTNAMLEN 15*65
8764
8765 int netsave = -1;
8766 static char * tmpstring = NULL;
8767 static char * tmpusrid = NULL;
8768
8769 #ifdef SSHCMD
8770 char * sshcmd = NULL;
8771 char * defsshcmd = "ssh -e none";
8772 #else
8773 #ifdef SSHBUILTIN
8774 char * sshrcmd = NULL;
8775 char * sshtmpcmd = NULL;
8776 #endif /* SSHBUILTIN */
8777 #endif /* SSHCMD */
8778
8779 /* c x _ f a i l  --  Common error exit routine for cx_net, cx_line */
8780
8781 int
8782 cx_fail(msg, text) int msg; char * text; {
8783     makestr(&slmsg,text);               /* For the record (or GUI) */
8784     if (msg)                            /* Not GUI, not quiet, etc */
8785       printf("?%s\n",text);             /* Print error message */
8786     slrestor();                         /* Restore LINE/HOST to known state */
8787     return(msg ? -9 : (success = 0));   /* Return appropriate code */
8788 }
8789
8790 #ifdef NETCONN
8791 /* c x _ n e t  --  Make a network connection */
8792
8793 /*
8794   Call with:
8795     net      = network type
8796     protocol = protocol type
8797     host     = string pointer to host name.
8798     svc      = string pointer to service or port on host.
8799     username = username for connection
8800     password = password for connection
8801     command  = command to execute
8802     param1   = Telnet: Authentication type
8803                SSH:    Version
8804     param2   = Telnet: Encryption type
8805                SSH:    Command as Subsystem
8806     param3   = Telnet: 1 to wait for negotiations, 0 otherwise
8807                SSH:    X11 Forwarding
8808     cx       = 1 to automatically enter Connect mode, 0 otherwise.
8809     sx       = 1 to automatically enter Server mode, 0 otherwise.
8810     flag     = if no host name given, 1 = close current connection, 0 = resume
8811     gui      = 1 if called from GUI dialog, 0 otherwise.
8812   Returns:
8813     1 on success
8814     0 on failure and no message printed, slmsg set to failure message.
8815    -9 on failure and message printed, ditto.
8816 */
8817 int
8818 #ifdef CK_ANSIC
8819 cx_net( int net, int protocol, char * xhost, char * svc, 
8820         char * username, char * password, char * command,
8821         int param1, int param2, int param3, int cx, int sx, int flag, int gui)
8822 #else /* CK_ANSIC */
8823 cx_net(net, protocol, xhost, svc,
8824        username, password, command,
8825        param1, param2, param3, cx, sx, flag, gui)
8826     char * xhost, * svc, * username, *password, *command; 
8827     int net, protocol, cx, sx, flag, param1, param2, param3, gui; 
8828 #endif /* CK_ANSIC */
8829 /* cx_net */ {
8830
8831     int i, n, x, msg;
8832     int _local = -1;
8833
8834     extern char pwbuf[], * g_pswd;
8835     extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
8836
8837     char srvbuf[SRVBUFSIZ+1];           /* Service */
8838     char hostbuf[HOSTNAMLEN];           /* Host buffer to manipulate */
8839     char hostname[HOSTNAMLEN];          /* Copy of host parameter */
8840     char * host = hostbuf;              /* Pointer to copy of host param */
8841
8842     if (!xhost) xhost = "";             /* Watch out for null pointers */
8843     if (!svc) svc = "";
8844     ckstrncpy(host,xhost,HOSTNAMLEN);   /* Avoid buffer confusion */
8845
8846     debug(F110,"cx_net host",host,0);
8847     debug(F111,"cx_net service",svc,SRVBUFSIZ);
8848     debug(F101,"cx_net network type","",net);
8849
8850     msg = (gui == 0) && msgflg;         /* Whether to print messages */
8851
8852 #ifndef NODIAL
8853     debug(F101,"cx_net nnetdir","",nnetdir);
8854     x = 0;                              /* Look up in network directory */
8855     if (*host == '=') {                 /* If number starts with = sign */
8856         host++;                         /* strip it */
8857         while (*host == SP) host++;     /* and any leading spaces */
8858         debug(F110,"cx_net host 2",host,0);
8859         nhcount = 0;
8860     } else if (*host) {                 /* We want to look it up. */
8861         if (nnetdir > 0)                /* If there is a directory... */
8862           x = lunet(host);              /* (sets nhcount) */
8863         else                            /* otherwise */
8864           nhcount = 0;                  /* we didn't find any there */
8865         if (x < 0)                      /* Internal error? */
8866           return(cx_fail(msg,"Network directory lookup error"));
8867         debug(F111,"cx_net lunet nhcount",host,nhcount);
8868     }
8869 #endif /* NODIAL */
8870
8871     /* New connection wanted.  Make a copy of the host name/address... */
8872
8873     if (clskconnx(1) < 0)               /* Close current Kermit connection */
8874       return(cx_fail(msg,"Error closing previous connection"));
8875
8876     if (*host) {                        /* They gave a hostname */
8877         _local = 1;                     /* Network connection always local */
8878         if (mdmsav < 0)
8879           mdmsav = mdmtyp;              /* Remember old modem type */
8880         mdmtyp = -net;                  /* Special code for network */
8881     } else {                            /* They just said "set host" */
8882         host = dftty;                   /* So go back to normal */
8883         _local = dfloc;                 /* default tty, location, */
8884         if (flag) {                     /* Close current connection */
8885             setflow();                  /* Maybe change flow control */
8886             haveline = 1;               /* (* is this right? *) */
8887             dologend();
8888 #ifndef NODIAL
8889             dialsta = DIA_UNK;
8890 #endif /* NODIAL */
8891 #ifdef LOCUS
8892             if (autolocus) {
8893                 setlocus(1,1);
8894             }
8895 #endif /* LOCUS */
8896             /* XXX - Is this right? */
8897             /* Should we be returning without doing anything ? */
8898             /* Yes it's right -- we closed the old connection just above. */
8899             return(success = 1);        
8900         }
8901     }
8902     success = 0;
8903     if (host != line)                   /* line[] is a global */
8904       ckstrncpy(line,host,LINBUFSIZ);
8905     ckstrncpy(hostname,host,HOSTNAMLEN);
8906     ckstrncpy(srvbuf,svc,SRVBUFSIZ+1);
8907
8908 #ifndef NODIAL
8909     if ((nhcount > 1) && msg) {
8910         int k;
8911         printf("%d entr%s found for \"%s\"%s\n",
8912                nhcount,
8913                (nhcount == 1) ? "y" : "ies",
8914                s,
8915                (nhcount > 0) ? ":" : "."
8916                );
8917         for (i = 0; i < nhcount; i++) {
8918                 printf("%3d. %-12s => %-9s %s",
8919                        i+1,n_name,nh_p2[i],nh_p[i]);
8920             for (k = 0; k < 4; k++) { /* Also list net-specific items */
8921                 if (nh_px[k][i])      /* free format... */
8922                   printf(" %s",nh_px[k][i]);
8923                 else
8924                   break;
8925             }
8926             printf("\n");
8927         }
8928     }
8929     if (nhcount == 0)
8930       n = 1;
8931     else
8932       n = nhcount;
8933 #else
8934     n = 1;
8935     nhcount = 0;
8936 #endif /* NODIAL */
8937
8938     for (i = 0; i < n; i++) {           /* Loop for each entry found */
8939         debug(F101,"cx_net loop i","",i);
8940 #ifndef NODIAL
8941         if (nhcount > 0) {              /* If we found at least one entry... */
8942             ckstrncpy(line,nh_p[i],LINBUFSIZ); /* Copy current entry */
8943             if (lookup(netcmd,nh_p2[i],nnets,&x) > -1) { /* Net type */
8944                 int xx;
8945                 xx = netcmd[x].kwval;
8946                 /* User specified SSH so don't let net directory override */
8947                 if (net != NET_SSH || xx != NET_TCPB) {
8948                     net = xx;
8949                     mdmtyp  = 0 - net;
8950                 }
8951             } else {
8952                 makestr(&slmsg,"Network type not supported");
8953                 if (msg)
8954                   printf("Error - network type \"%s\" not supported\n",
8955                          nh_p2[i]
8956                          );
8957                 continue;
8958             }
8959             switch (net) {              /* Net-specific directory things */
8960 #ifdef SSHBUILTIN
8961               case NET_SSH:             /* SSH */
8962                 /* Any SSH specific network directory stuff? */
8963                 break;                  /* NET_SSH */
8964 #endif /* SSHBUILTIN */
8965
8966               case NET_TCPB: {          /* TCP/IP TELNET,RLOGIN,... */
8967 #ifdef TCPSOCKET
8968                   char *q;
8969                   int flag = 0;
8970
8971                   /* Extract ":service", if any, from host string */
8972                   debug(F110,"cx_net service 1",line,0);
8973                   for (q = line; (*q != '\0') && (*q != ':'); q++)
8974                     ;
8975                   if (*q == ':') { *q++ = NUL; flag = 1; }
8976                   debug(F111,"cx_net service 2",line,flag);
8977
8978                   /* Get service, if any, from directory entry */
8979
8980                   if (!*srvbuf) {
8981                       if (nh_px[0][i]) {
8982                           ckstrncpy(srvbuf,nh_px[0][i],SRVBUFSIZ);
8983                           debug(F110,"cx_net service 3",srvbuf,0);
8984                       }
8985                       if (flag) {
8986                           ckstrncpy(srvbuf,q,SRVBUFSIZ);
8987                           debug(F110,"cx_net service 4",srvbuf,0);
8988                       }
8989                   }
8990                   ckstrncpy(hostname,line,HOSTNAMLEN);
8991
8992                   /* If we have a service, append to host name/address */
8993                   if (*srvbuf) {
8994                       ckstrncat(line, ":", LINBUFSIZ);
8995                       ckstrncat(line, srvbuf, LINBUFSIZ);
8996                       debug(F110,"cx_net service 5",line,0);
8997                   }
8998 #ifdef RLOGCODE
8999                   /* If no service given but command was RLOGIN */
9000                   else if (ttnproto == NP_RLOGIN) { /* add this... */
9001                       ckstrncat(line, ":login",LINBUFSIZ);
9002                       debug(F110,"cx_net service 6",line,0);
9003                   }
9004 #ifdef CK_AUTHENTICATION
9005 #ifdef CK_KERBEROS
9006                   else if (ttnproto == NP_K4LOGIN ||
9007                            ttnproto == NP_K5LOGIN) { /* add this... */
9008                       ckstrncat(line, ":klogin",LINBUFSIZ);
9009                       debug(F110,"cx_net service 7",line,0);
9010                   }
9011                   else if (ttnproto == NP_EK4LOGIN ||
9012                            ttnproto == NP_EK5LOGIN) { /* add this... */
9013                       ckstrncat(line, ":eklogin",LINBUFSIZ);
9014                       debug(F110,"cx_net service 8",line,0);
9015                   }
9016 #endif /* CK_KERBEROS */
9017 #endif /* CK_AUTHENTICATION */
9018 #endif /* RLOGCODE */
9019                   else {                /* Otherwise, add ":telnet". */
9020                       ckstrncat(line, ":telnet", LINBUFSIZ);
9021                       debug(F110,"cx_net service 9",line,0);
9022                   }
9023                   if (username) {       /* This is a parameter... */
9024                       ckstrncpy(uidbuf,username,UIDBUFLEN);
9025                       uidflag = 1;
9026                   }
9027                   /* Fifth field, if any, is user ID (for rlogin) */
9028
9029                   if (nh_px[1][i] && !uidflag)
9030                     ckstrncpy(uidbuf,username,UIDBUFLEN);
9031 #ifdef RLOGCODE
9032                   if (IS_RLOGIN() && !uidbuf[0])
9033                     return(cx_fail(msg,"Username required"));
9034 #endif /* RLOGCODE */
9035 #endif /* TCPSOCKET */
9036                   break;
9037               }
9038               case NET_PIPE:            /* Pipe */
9039 #ifdef NPIPE
9040                 if (!pipename[0]) { /* User didn't give a pipename */
9041                     if (nh_px[0][i]) { /* But directory entry has one */
9042                         if (strcmp(pipename,"\\pipe\\")) {
9043                             ckstrncpy(pipename,"\\pipe\\",LINBUFSIZ);
9044                             ckstrncat(srvbuf,nh_px[0][i],PIPENAML-6);
9045                         } else {
9046                             ckstrncpy(pipename,nh_px[0][i],PIPENAML);
9047                         }
9048                         debug(F110,"cx_net pipeneme",pipename,0);
9049                     }
9050                 }
9051 #endif /* NPIPE */
9052                 break;
9053
9054               case NET_SLAT:            /* LAT / CTERM */
9055 #ifdef SUPERLAT
9056                 if (!slat_pwd[0]) { /* User didn't give a password */
9057                     if (nh_px[0][i]) { /* But directory entry has one */
9058                         ckstrncpy(slat_pwd,nh_px[0][i],18);
9059                         debug(F110,"cx_net SuperLAT password",slat_pwd,0);
9060                     }
9061                 }
9062 #endif /* SUPERLAT */
9063                 break;
9064
9065               case NET_SX25:        /* X.25 keyword parameters */
9066               case NET_IX25:
9067               case NET_VX25: {
9068 #ifdef ANYX25
9069                   int k;            /* Cycle through the four fields */
9070                   for (k = 0; k < 4; k++) {
9071                       if (!nh_px[k][i]) /* Bail out if none left */
9072                         break;
9073                       if (!ckstrcmp(nh_px[k][i],"cug=",4,0)) {
9074                           closgr = atoi(nh_px[k][i]+4);
9075                           debug(F101,"X25 CUG","",closgr);
9076                       } else if (!ckstrcmp(nh_px[k][i],"cud=",4,0)) {
9077                           cudata = 1;
9078                           ckstrncpy(udata,nh_px[k][i]+4,MAXCUDATA);
9079                           debug(F110,"X25 CUD",cudata,0);
9080                       } else if (!ckstrcmp(nh_px[k][i],"rev=",4,0)) {
9081                           revcall = !ckstrcmp(nh_px[k][i]+4,"=on",3,0);
9082                           debug(F101,"X25 REV","",revcall);
9083 #ifndef IBMX25
9084                       } else if (!ckstrcmp(nh_px[k][i],"pad=",4,0)) {
9085                           int x3par, x3val;
9086                           char *s1, *s2;
9087                           s1 = s2 = nh_px[k][i]+4; /* PAD parameters */
9088                           while (*s2) {            /* Pick them apart */
9089                               if (*s2 == ':') {
9090                                   *s2 = NUL;
9091                                   x3par = atoi(s1);
9092                                   s1 = ++s2;
9093                                   continue;
9094                               } else if (*s2 == ',') {
9095                                   *s2 = NUL;
9096                                   x3val = atoi(s1);
9097                                   s1 = ++s2;
9098                                   debug(F111,"X25 PAD",x3par,x3val);
9099                                   if (x3par > -1 &&
9100                                       x3par <= MAXPADPARMS)
9101                                     padparms[x3par] = x3val;
9102                                   continue;
9103                               } else
9104                                 s2++;
9105                           }
9106 #endif /* IBMX25 */
9107                       }
9108                   }
9109 #endif /* ANYX25 */
9110                   break;
9111               }
9112               default:                  /* Nothing special for other nets */
9113                 break;
9114             }
9115         } else
9116 #endif /* NODIAL */
9117         {                               /* No directory entries found. */
9118             ckstrncpy(line,hostname,LINBUFSIZ); /* Put this back... */
9119             /* If the user gave a TCP service */
9120             if (net == NET_TCPB || net == NET_SSH)
9121               if (*srvbuf) {            /* Append it to host name/address */
9122                   ckstrncat(line, ":", LINBUFSIZ);
9123                   ckstrncat(line, srvbuf,LINBUFSIZ);
9124               }
9125         }
9126         /*
9127            Get here with host name/address and all net-specific
9128            parameters set, ready to open the connection.
9129         */
9130         mdmtyp = -net;                  /* This should have been done */
9131                                         /* already but just in case ... */
9132
9133         debug(F110,"cx_net net line[] before ttopen",line,0);
9134         debug(F101,"cx_net net mdmtyp before ttopen","",mdmtyp);
9135         debug(F101,"cx_net net ttnproto","",ttnproto);
9136
9137 #ifdef SSHBUILTIN
9138         if (net == NET_SSH) {
9139             makestr(&ssh_hst,hostname);        /* Stash everything */
9140             if (username) {
9141                 if (!sl_uid_saved) {
9142                     ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
9143                     sl_uid_saved = 1;
9144                 }
9145                 ckstrncpy(uidbuf,username,UIDBUFLEN);
9146             }
9147             if (srvbuf[0]) {
9148                 makestr(&ssh_prt,srvbuf);
9149             } else
9150                 makestr(&ssh_prt,NULL);
9151
9152             if (command) {
9153                 makestr(&ssh_cmd,brstrip(command));
9154                 ssh_cas = param2;
9155             } else
9156                 makestr(&ssh_cmd,NULL);
9157
9158             if (param1 > -1) {
9159 #ifndef SSHTEST
9160                 if (!sl_ssh_ver_saved) {
9161                     sl_ssh_ver = ssh_ver;
9162                     sl_ssh_ver_saved = 1;
9163                 }
9164 #endif /* SSHTEST */
9165                 ssh_ver = param1;
9166             }
9167             if (param3 > -1) {
9168 #ifndef SSHTEST
9169                 if (!sl_ssh_xfw_saved) {
9170                     sl_ssh_xfw = ssh_xfw;
9171                     sl_ssh_xfw_saved = 1;
9172                 }
9173 #endif /* SSHTEST */
9174                 ssh_xfw = param3;
9175             }
9176         } else                          /* NET_SSH */
9177 #endif /* SSHBUILTIN */
9178 #ifdef TCPSOCKET
9179           if (net == NET_TCPB) {
9180             switch (protocol) {
9181 #ifdef CK_SSL
9182 #ifdef COMMENT
9183 /*
9184   Jeff's version from 30 Dec 2006 - doesn't work - SSL/TLS_RAW still
9185   start Telnet negotions if a 0xff byte comes in.
9186 */
9187               case NP_SSL_RAW:
9188                 ttnproto = NP_SSL_RAW;
9189                 debug(F101,"NP_SSL_RAW ttnproto","",ttnproto);
9190                 ssl_only_flag = 1;
9191                 tls_only_flag = 0;
9192                 break;
9193
9194               case NP_TLS_RAW:
9195                   ttnproto = NP_TLS_RAW;
9196                   debug(F101,"NP_TLS_RAW ttnproto","",ttnproto);
9197                   ssl_only_flag = 0;
9198                   tls_only_flag = 1;
9199                   break;
9200
9201               case NP_SSL:
9202                 ttnproto = NP_SSL;
9203                 debug(F101,"NP_SSL ttnproto","",ttnproto);
9204                 ssl_only_flag = 1;
9205                 tls_only_flag = 0;
9206                 break;
9207
9208               case NP_TLS:
9209                 ttnproto = NP_TLS;
9210                 debug(F101,"NP_TLS ttnproto","",ttnproto);
9211                 ssl_only_flag = 0;
9212                 tls_only_flag = 1;
9213                 break;
9214
9215               case NP_SSL_TELNET:
9216                 ttnproto = NP_TELNET;
9217                 debug(F101,"NP_SSL_TELNET ttnproto","",ttnproto);
9218                 ssl_only_flag = 1;
9219                 tls_only_flag = 0;
9220                 break;
9221
9222               case NP_TLS_TELNET:
9223                 ttnproto = NP_TELNET;
9224                 debug(F101,"NP_TLS_TELNET ttnproto","",ttnproto);
9225                 ssl_only_flag = 0;
9226                 tls_only_flag = 1;
9227                 break;
9228 #else
9229 /* fdc version of 4 Dec 2006 works OK */
9230               case NP_SSL_RAW:
9231               case NP_SSL:
9232                 ssl_raw_flag = (protocol == NP_SSL_RAW) ? 1 : 0;
9233                 ttnproto = protocol;
9234                 debug(F101,protocol==NP_SSL ?
9235                       "NP_SSL ttnproto" :
9236                       "NP_SSL_RAW ttnproto",
9237                       "",ttnproto);
9238                 ssl_only_flag = 1;
9239                 tls_only_flag = 0;
9240                 break;
9241
9242               case NP_TLS:
9243               case NP_TLS_RAW:
9244                 tls_raw_flag = (protocol == NP_SSL_RAW) ? 1 : 0;
9245                 ttnproto = protocol;
9246                 debug(F101,protocol==NP_TLS ?
9247                       "NP_TLS ttnproto" :
9248                       "NP_TLS_RAW ttnproto",
9249                       "",ttnproto);
9250                 ssl_only_flag = 0;
9251                 tls_only_flag = 1;
9252                 break;
9253
9254               case NP_SSL_TELNET:
9255                 ssl_raw_flag = 0;
9256                 ttnproto = NP_TELNET;
9257                 debug(F101,"NP_SSL_TELNET ttnproto","",ttnproto);
9258                 ssl_only_flag = 1;
9259                 tls_only_flag = 0;
9260                 break;
9261
9262               case NP_TLS_TELNET:
9263                 tls_raw_flag = 0;
9264                 ttnproto = NP_TELNET;
9265                 debug(F101,"NP_TLS_TELNET ttnproto","",ttnproto);
9266                 ssl_only_flag = 0;
9267                 tls_only_flag = 1;
9268                 break;
9269 #endif  /* COMMENT */
9270 #endif /* CK_SSL */
9271
9272               case NP_NONE:
9273               case NP_TCPRAW:
9274               case NP_RLOGIN:
9275               case NP_K4LOGIN:
9276               case NP_K5LOGIN:
9277               case NP_EK4LOGIN:
9278               case NP_EK5LOGIN:
9279               case NP_TELNET:
9280               case NP_KERMIT:
9281               default:
9282                 ttnproto = protocol;
9283 #ifdef CK_SSL
9284 #ifdef COMMENT
9285                 /* Jeff version from 30 Dec 2006 */
9286                 ssl_only_flag = 0;
9287                 tls_only_flag = 0;
9288 #else
9289                 /* fdc version from 4 Dec 2006 */
9290                 ssl_raw_flag = 0;
9291                 tls_raw_flag = 0;
9292                 ssl_only_flag = 0;
9293                 tls_only_flag = 0;
9294 #endif  /* COMMENT */
9295 #endif /* CK_SSL */
9296                 break;
9297             }
9298 #ifdef CK_AUTHENTICATION
9299             if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9300                 param1 > -1) {
9301             if (!sl_auth_saved) {
9302                 int x;
9303                 for (x = 0; x < AUTHTYPLSTSZ; x++)
9304                   sl_auth_type_user[x] = auth_type_user[x];
9305                 sl_auth_saved = 1;
9306             }
9307             if (!sl_topt_a_s_saved) {
9308                 sl_topt_a_su = TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION);
9309                 sl_topt_a_s_saved = 1;
9310             }
9311             if (!sl_topt_a_c_saved) {
9312                 sl_topt_a_cm = TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION);
9313                 sl_topt_a_c_saved = 1;
9314             }
9315             switch (param1) {
9316               case AUTHTYPE_AUTO:
9317                 auth_type_user[0] = AUTHTYPE_AUTO;
9318                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
9319                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
9320                 break;
9321               case AUTHTYPE_NULL:
9322                 auth_type_user[0] = AUTHTYPE_NULL;
9323                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
9324                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
9325                 break;
9326 #ifdef CK_SRP
9327               case AUTHTYPE_SRP:
9328                 auth_type_user[0] = AUTHTYPE_SRP;
9329                 auth_type_user[1] = AUTHTYPE_NULL;
9330                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9331                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9332                 break;
9333 #endif /* CK_SRP */
9334 #ifdef CK_SSL
9335               case AUTHTYPE_SSL:
9336                 auth_type_user[0] = AUTHTYPE_SSL;
9337                 auth_type_user[1] = AUTHTYPE_NULL;
9338                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9339                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9340                 break;
9341 #endif /* CK_SSL */
9342 #ifdef NT
9343               case AUTHTYPE_NTLM:
9344                 auth_type_user[0] = AUTHTYPE_NTLM;
9345                 auth_type_user[1] = AUTHTYPE_NULL;
9346                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9347                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9348                 break;
9349 #endif /* NT */
9350 #ifdef CK_KERBEROS
9351               case AUTHTYPE_KERBEROS_V4:
9352                 auth_type_user[0] = AUTHTYPE_KERBEROS_V4;
9353                 auth_type_user[1] = AUTHTYPE_NULL;
9354                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9355                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9356                 break;
9357
9358               case AUTHTYPE_KERBEROS_V5:
9359                 auth_type_user[0] = AUTHTYPE_KERBEROS_V5;
9360                 auth_type_user[1] = AUTHTYPE_NULL;
9361                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9362                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9363                 break;
9364 #endif /* CK_KERBEROS */
9365             }
9366         }
9367         /*
9368            If the user requires a particular type of Kerberos connection,
9369            make sure we have a valid TGT.
9370         */
9371         makestr(&slmsg,"Authentication failure");
9372         if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9373             (line[0] == '*' &&
9374              TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_MU ||
9375              line[0] != '*' &&
9376              TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_MU)
9377             ) {
9378 #ifdef CK_KERBEROS
9379             if ( auth_type_user[0] == AUTHTYPE_KERBEROS_V4 ) {
9380                 extern int krb4_autoget;
9381                 if (!ck_krb4_is_installed())
9382                   return(cx_fail(msg,
9383               "Required authentication method (Kerberos 4) is not installed"));
9384 #ifdef COMMENT
9385                 /* This code results in false failures when using */
9386                 /* kerberos to machines in realms other than the  */
9387                 /* default since we don't know the realm of the   */
9388                 /* other machine until perform the reverse DNS    */
9389                 /* lookup.                                        */
9390                 else if (line[0] != '*' && !ck_krb4_is_tgt_valid() &&
9391                            (!krb4_autoget ||
9392                             krb4_autoget && !ck_krb4_autoget_TGT(NULL))) {
9393                     return(cx_fail(msg,
9394                            "Kerberos 4: Ticket Getting Ticket not valid"));
9395                 }
9396 #endif /* COMMENT */
9397             } else if (auth_type_user[0] == AUTHTYPE_KERBEROS_V5) {
9398                 extern int krb5_autoget;
9399                 if (!ck_krb5_is_installed()) {
9400                     return(cx_fail(msg,
9401            "Required authentication method (Kerberos 5) is not installed"));
9402                 }
9403 #ifdef COMMENT
9404                 /* This code results in false failures when using */
9405                 /* kerberos to machines in realms other than the  */
9406                 /* default since we don't know the realm of the   */
9407                 /* other machine until perform the reverse DNS    */
9408                 /* lookup.                                        */
9409                 else if (line[0] != '*' && !ck_krb5_is_tgt_valid() &&
9410                            (!krb5_autoget ||
9411                             krb5_autoget && !ck_krb5_autoget_TGT(NULL))) {
9412                     return(cx_fail(msg,
9413                          "Kerberos 5: Ticket Getting Ticket not valid."));
9414                 }
9415 #endif /* COMMENT */
9416             }
9417 #endif /* CK_KERBEROS */
9418 #ifdef NT
9419             if (auth_type_user[0] == AUTHTYPE_NTLM) {
9420                 if (!ck_ntlm_is_installed()) {
9421                     return(cx_fail(msg,
9422                    "Required authentication method (NTLM) is not installed"));
9423                 } else if (line[0] != '*' && !ck_ntlm_is_valid(0)) {
9424                     return(cx_fail(msg,"NTLM: Credentials are unavailable."));
9425                 }
9426             }
9427 #endif /* NT */
9428 #ifdef CK_SSL
9429             if (auth_type_user[0] == AUTHTYPE_SSL) {
9430                 if (!ck_ssleay_is_installed()) {
9431                     return(cx_fail(msg,
9432                      "Required authentication method (SSL) is not installed"));
9433                 }
9434             }
9435 #endif /* CK_SSL */
9436 #ifdef CK_SRP
9437             if (auth_type_user[0] == AUTHTYPE_SRP) {
9438                 if (!ck_srp_is_installed()) {
9439                     return(cx_fail(msg,
9440                      "Required authentication method (SRP) is not installed"));
9441                 }
9442             }
9443 #endif /* CK_SRP */
9444         }
9445 #endif /* CK_AUTHENTICATION */
9446 #ifdef CK_ENCRYPTION
9447         if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9448              param2 > -1) {
9449             if (!sl_cx_saved) {
9450                 sl_cx_type = cx_type;
9451                 sl_cx_saved = 1;
9452             }
9453             if (!sl_topt_e_s_saved) {
9454                 sl_topt_e_su = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
9455                 sl_topt_e_sm = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
9456                 sl_topt_e_s_saved = 1;
9457             }
9458             if (!sl_topt_e_c_saved) {
9459                 sl_topt_e_cu = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
9460                 sl_topt_e_cm = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
9461                 sl_topt_e_c_saved = 1;
9462             }
9463             cx_type = param2;
9464             if (cx_type == CX_AUTO) {
9465                 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9466                 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9467                 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9468                 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9469             } else if (cx_type == CX_NONE) {
9470                 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9471                 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9472                 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9473                 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9474             } else {
9475                 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9476                 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9477                 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9478                 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9479             }
9480         }
9481         if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN ||
9482             (ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9483             ((line[0] == '*' &&
9484               TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) == TN_NG_MU &&
9485               TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_MU) ||
9486              (line[0] != '*' &&
9487               TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) == TN_NG_MU &&
9488               TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_MU))
9489             ) {
9490             if (!ck_crypt_is_installed()) {
9491                 return(cx_fail(msg,
9492                   "Required Encryption methods are not installed"));
9493             }
9494         }
9495 #endif /* CK_ENCRYPTION */
9496 #ifdef RLOGCODE
9497 #ifdef CK_KERBEROS
9498 #ifdef KRB4
9499         if (ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN) {
9500             extern int krb4_autoget;
9501             char tgt[256];
9502             char * realm;
9503
9504             /* We don't have the full hostname at yet so  */
9505             /* we do a DNS lookup before calling ttopen() */ 
9506
9507             realm = ck_krb4_realmofhost(ckgetfqhostname(hostname));
9508             ckmakmsg(tgt,256,"krbtgt.",realm,"@",realm);
9509             if (!ck_krb4_is_installed()) {
9510                 return(cx_fail(msg,
9511                  "Required authentication method (Kerberos 4) is not installed"
9512                                ));
9513             } else {
9514                 if ((ck_krb4_tkt_isvalid(tgt) <= 0) &&
9515                     (!krb4_autoget ||
9516                      krb4_autoget && !ck_krb4_autoget_TGT(realm))) {
9517                     return(cx_fail(msg,
9518                            "Kerberos 4: Ticket Getting Ticket not valid"));
9519                 }
9520             }
9521         }
9522 #endif /* KRB4 */
9523 #ifdef KRB5
9524         if (ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN ||
9525             ttnproto == NP_K5U2U)
9526         {
9527             extern int krb5_autoget;
9528             char tgt[256];
9529             char * realm;
9530
9531             /* Must get full hostname before calling ttopen() */
9532
9533             realm = ck_krb5_realmofhost(ckgetfqhostname(hostname));
9534             ckmakmsg(tgt,256,"krbtgt/",realm,"@",realm);
9535
9536             if (!ck_krb5_is_installed()) {
9537                 return(cx_fail(msg,
9538                  "Required authentication method (Kerberos 5) not installed"));
9539             } else if (!((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
9540                           ck_krb5_is_tgt_valid()) &&
9541                        (!krb5_autoget ||
9542                         krb5_autoget && !ck_krb5_autoget_TGT(realm))) {
9543                 return(cx_fail(msg,
9544                        "Kerberos 5: Ticket Getting Ticket not valid."));
9545             }
9546         }
9547 #endif /* KRB5 */
9548 #endif /* CK_KERBEROS */
9549 #endif /* RLOGCODE */
9550
9551 #ifndef NOSPL
9552 #ifdef RLOGCODE
9553         if (username) {
9554             if (!sl_uid_saved) {
9555                 ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
9556                 sl_uid_saved = 1;
9557             }
9558             ckstrncpy(uidbuf,username,UIDBUFLEN);
9559             uidflag = 1;
9560         }
9561 #endif /* RLOGCODE */
9562 #ifdef TNCODE
9563         if (!sl_tn_saved) {
9564             sl_tn_wait = tn_wait_flg;
9565             sl_tn_saved = 1;
9566         }
9567         tn_wait_flg = param3;
9568 #endif /* TNCODE */
9569 #endif /* NOSPL */
9570         } /* if (net == NET_TCPB) */
9571 #endif /* TCPSOCKET */
9572
9573 #ifndef NOSPL
9574 #ifdef CK_SECURITY
9575         if (password) {
9576             if (password[0]) {
9577                 ckstrncpy(pwbuf,password,PWBUFL+1);
9578                 pwflg = 1;
9579                 pwcrypt = 0;
9580             } else
9581                 pwflg = 0;
9582         }
9583 #endif /* CK_SECURITY */
9584 #endif /* NOSPL */
9585
9586         /* Try to open - network */
9587         ckstrncpy(ttname,line,TTNAMLEN);
9588         y = ttopen(line, &_local, mdmtyp, 0 );
9589
9590 #ifndef NOHTTP
9591         /*  If the connection failed and we are using an HTTP Proxy
9592          *  and the reason for the failure was an authentication
9593          *  error, then we need to give the user to ability to
9594          *  enter a username and password, just like a browser.
9595          *
9596          *  I tried to do all of this within the netopen() call
9597          *  but it is much too much work.
9598          */
9599         while (y < 0 && tcp_http_proxy != NULL ) {
9600
9601             if (tcp_http_proxy_errno == 401 ||
9602                 tcp_http_proxy_errno == 407 ) {
9603                 char uid[UIDBUFLEN];
9604                 char pwd[256];
9605                 struct txtbox tb[2];
9606                 int ok;
9607
9608                 tb[0].t_buf = uid;
9609                 tb[0].t_len = UIDBUFLEN;
9610                 tb[0].t_lbl = "Proxy Userid: ";
9611                 tb[0].t_dflt = NULL;
9612                 tb[0].t_echo = 1;
9613                 tb[1].t_buf = pwd;
9614                 tb[1].t_len = 256;
9615                 tb[1].t_lbl = "Proxy Passphrase: ";
9616                 tb[1].t_dflt = NULL;
9617                 tb[1].t_echo = 2;
9618
9619                 ok = uq_mtxt("Proxy Server Authentication Required\n",
9620                               NULL, 2, tb);
9621
9622                 if (ok && uid[0]) {
9623                     char * proxy_user, * proxy_pwd;
9624
9625                     proxy_user = tcp_http_proxy_user;
9626                     proxy_pwd  = tcp_http_proxy_pwd;
9627
9628                     tcp_http_proxy_user = uid;
9629                     tcp_http_proxy_pwd = pwd;
9630
9631                     ckstrncpy(ttname,line,TTNAMLEN);
9632                     y = ttopen(line, &_local, mdmtyp, 0);
9633                     memset(pwd,0,sizeof(pwd));
9634                     tcp_http_proxy_user = proxy_user;
9635                     tcp_http_proxy_pwd = proxy_pwd;
9636                 } else
9637                   break;
9638             } else
9639               break;
9640         }
9641 #endif /* NOHTTP */
9642         if (y < 0) {
9643             slrestor();
9644             makestr(&slmsg,"Network connection failure");
9645 #ifdef VMS
9646             if (msg && hints && !xcmdsrc && IS_RLOGIN()) {
9647                 makestr(&slmsg,"RLOGIN failure");
9648                 if  (socket_errno == EACCES) {
9649                     printf("*************************\n");
9650                     printf(
9651            "Hint: RLOGIN requires privileges to open an outbound port.\n");
9652                     printf(
9653                     "(Use SET HINTS OFF to suppress future hints.)\n");
9654                     printf("*************************\n");
9655                 }
9656             }
9657 #else  /* Not VMS... */
9658             if (errno) {
9659                 int x;
9660                 debug(F111,"set host line, errno","",errno);
9661                 makestr(&slmsg,ck_errstr());
9662                 if (msg) {
9663 #ifdef OS2
9664                     printf("Can't connect to %s\n",line);
9665 #else /* OS2 */
9666 #ifdef UNIX
9667                     if (hints && !xcmdsrc && IS_RLOGIN()) {
9668                         makestr(&slmsg,"RLOGIN failure");
9669                         printf("*************************\n");
9670                         printf(
9671          "Hint: RLOGIN requires privileges to open an outbound port.\n");
9672                         printf(
9673          "(Use SET HINTS OFF to suppress future hints.)\n");
9674                         printf("*************************\n");
9675                     }
9676 #endif /* UNIX */
9677 #endif /* OS2 */
9678                 } else printf("Can't connect to %s\n",line);
9679             } else
9680 #endif /* VMS */
9681               if (msg) printf("Can't open connection to %s\n",line);
9682             continue;
9683         } else {
9684             success = 1;
9685 #ifndef NODIAL
9686             dialsta = DIA_UNK;
9687 #endif /* NODIAL */
9688             switch (net) {
9689               case NET_TCPA:
9690               case NET_TCPB:
9691                 cxtype = CXT_TCPIP;
9692 #ifdef COMMENT
9693 /* This works but it messes up interactive anonymous login */
9694 #ifndef NOXFER
9695 #ifdef IKS_OPTION
9696                 /* If we have connected to an Internet Kermit service */
9697                 /* and a /USER: switch was given, then log in. */
9698
9699                 if (TELOPT_U(TELOPT_KERMIT) || TELOPT_ME(TELOPT_KERMIT)) {
9700                     debug(F111,"cx_net IKSD /USER:",uidbuf,haveuser);
9701                     if (haveuser /* && cx == 0 */ ) { /* /USER: given */
9702                         char * psw = pwbuf; /* Do we have a password? */
9703                         if (!*psw) {        /* No... */
9704                             if (!strcmp(uidbuf,"anonymous") ||
9705                                 !strcmp(uidbuf,"ftp")) {
9706                                 extern char myhost[];
9707                                 char * u = (char *)sl_uidbuf;
9708                                 char * h = (char *)myhost;
9709                                 if (!*u) u = "nobody";
9710                                 if (!*h) h = "nowhere";
9711                                 ckmakmsg(tmpbuf,TMPBUFSIZ,u,"@",h,NULL);
9712                                 psw = tmpbuf;
9713                                 debug(F110,"cx_net IKSD anon",psw,0);
9714                             } else {
9715                                 readpass(" Password: ",pwbuf,PWBUFL);
9716                             }
9717                         }
9718                         sstate = setgen('I',uidbuf,psw,"");
9719                     }
9720                 }
9721 #endif /* IKS_OPTION */
9722 #endif /* NOXFER */
9723 #endif /* COMMENT */
9724                 break;
9725               case NET_SSH:
9726                 cxtype = CXT_SSH;
9727                 duplex = 0;         /* Remote echo */
9728                 break;
9729               case NET_SLAT:
9730                 cxtype = CXT_LAT;
9731                 break;
9732               case NET_SX25:
9733               case NET_IX25:
9734               case NET_HX25:
9735               case NET_VX25:
9736                 cxtype = CXT_X25;
9737                 break;
9738               case NET_BIOS:
9739                 cxtype = CXT_NETBIOS;
9740                 break;
9741               case NET_FILE:
9742               case NET_PIPE:
9743               case NET_CMD:
9744               case NET_DLL:
9745               case NET_PTY:
9746                 cxtype = CXT_PIPE;
9747                 break;
9748               default:
9749                 cxtype = CXT_PIPE;
9750                 break;
9751             }
9752             break;
9753         }
9754     } /* for-loop */
9755     s = line;
9756
9757     debug(F101,"cx_net post ttopen success","",success);
9758     if (!success) {
9759         local = dfloc;                  /* Go back to normal */
9760 #ifndef MAC
9761         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty name */
9762 #endif /* MAC */
9763         speed = ttgspd();
9764         network = 0;                    /* No network connection active */
9765         haveline = 0;
9766         if (mdmtyp < 0) {               /* Switching from net to async? */
9767             if (mdmsav > -1)            /* Restore modem type from last */
9768               mdmtyp = mdmsav;          /* SET MODEM command, if any. */
9769             else
9770               mdmtyp = 0;
9771             mdmsav = -1;
9772         }
9773         return(0);                      /* Return failure */
9774     }
9775     if (_local > -1) local = _local;    /* Opened ok, set local/remote. */
9776     makestr(&slmsg,NULL);
9777     network = (mdmtyp < 0);             /* Remember connection type. */
9778     ckstrncpy(ttname,s,TTNAMLEN);       /* Copy name into real place. */
9779     debug(F110,"cx_net ok",ttname,0);
9780     debug(F101,"cx_net network","",network);
9781 #ifndef NOXFER
9782     if ((reliable != SET_OFF || !setreliable)) /* Assume not reliable. */
9783       reliable = SET_OFF;
9784 #endif /* NOXFER */
9785     if (!network || istncomport())      
9786       speed = ttgspd();                 /* Get the current speed. */
9787     debug(F101,"cx_net local","",local);
9788     if (network) {
9789         debug(F101,"cx_net net","",net);
9790 #ifndef NOXFER
9791         /* Force prefixing of 255 on TCP/IP connections... */
9792         if (net == NET_TCPB
9793 #ifdef SSHBUILTIN
9794              || net == NET_SSH
9795 #endif /* SSHBUILTIN */
9796              ) {
9797             debug(F101,"cx_net reliable A","",reliable);
9798 #ifdef CK_SPEED
9799             ctlp[(unsigned)255] = 1;
9800 #endif /* CK_SPEED */
9801             if ((reliable != SET_OFF || !setreliable)) {
9802 #ifdef TN_COMPORT
9803                 if (istncomport()) {    /* Telnet communication port */
9804                     reliable = SET_OFF; /* Transport is not reliable */
9805                     debug(F101,"cx_net reliable istncomport()","",1);
9806                 } else {
9807                     reliable = SET_ON;  /* Transport is reliable end to end */
9808                     debug(F101,"cx_net reliable istncomport()","",0);
9809                 }
9810 #else
9811                 reliable = SET_ON;      /* Transport is reliable end to end */
9812 #endif /* ifdef TN_COMPORT */
9813             }
9814             debug(F101,"cx_net reliable B","",reliable);
9815         } else if (net == NET_SX25 ||
9816                    net == NET_VX25 ||
9817                    net == NET_IX25 ||
9818                    net == NET_HX25) {
9819             duplex = 1;                 /* Local echo for X.25 */
9820             if (reliable != SET_OFF || !setreliable)
9821               reliable = SET_ON;        /* Transport is reliable end to end */
9822         }
9823 #endif /* NOXFER */
9824     }
9825 #ifndef NOXFER
9826     debug(F101,"cx_net reliable","",reliable);
9827 #endif /* NOXFER */
9828 #ifdef OS2
9829     if (mdmtyp <= 0)                    /* Network or Direct Connection */
9830       DialerSend(OPT_KERMIT_CONNECT, 0);
9831 #endif /* OS2 */
9832
9833   xcx_net:
9834
9835     setflow();                          /* Set appropriate flow control */
9836
9837     haveline = 1;
9838 #ifdef CKLOGDIAL
9839     dolognet();
9840 #endif /* CKLOGDIAL */
9841
9842 #ifndef NOSPL
9843     if (local) {
9844         if (nmac) {                     /* Any macros defined? */
9845             int k;                      /* Yes */
9846             k = mlook(mactab,"on_open",nmac);   /* Look this up */
9847             if (k >= 0) {                       /* If found, */
9848                 if (dodo(k,ttname,0) > -1)      /* set it up, */
9849                   parser(1);                    /* and execute it */
9850             }
9851         }
9852     }
9853 #endif /* NOSPL */
9854
9855     if (local && (cx || sx)) {          /* /CONNECT or /SERVER switch given */
9856         if (cx) {                       /* /CONNECT */
9857             if (!gui) {
9858                 /* Command was confirmed so we can pre-pop command level.  */
9859                 /* This is so CONNECT module won't think we're executing a */
9860                 /* script if CONNECT was the final command in the script.  */
9861                 if (cmdlvl > 0)
9862                   prepop();
9863             }
9864 #ifndef NODIAL
9865             dialsta = DIA_UNK;
9866 #endif /* NODIAL */
9867 #ifdef LOCUS
9868             if (autolocus) {
9869                 setlocus(1,1);
9870             }
9871 #endif /* LOCUS */
9872             success = doconect(0, cmdlvl == 0 ? 1 : 0);
9873             if (ttchk() < 0)
9874               dologend();
9875             debug(F101,"cx_net post doconect success","",success);
9876             return(success);
9877 #ifndef NOXFER
9878         } else if (sx) {                /* /SERVER */
9879             sstate = 'x';
9880 #ifdef MAC
9881             what = W_RECV;
9882             scrcreate();
9883 #endif /* MAC */
9884             if (local) displa = 1;
9885 #ifdef AMIGA
9886             reqoff();                   /* No DOS requestors while server */
9887 #endif /* AMIGA */
9888 #endif /* NOXFER */
9889         }
9890     }
9891 #ifndef NODIAL
9892     dialsta = DIA_UNK;
9893 #endif /* NODIAL */
9894 #ifdef LOCUS
9895     if (autolocus) {
9896         setlocus(1,1);
9897     }
9898 #endif /* LOCUS */
9899     return(success = 1);
9900 }
9901 #endif /* NETCONN */
9902
9903 /* c x _ s e r i a l  --  Make a serial connection */
9904
9905 /*
9906   Call with:
9907     device  = string pointer to device name.
9908     cx      = 1 to automatically enter Connect mode, 0 otherwise.
9909     sx      = 1 to automatically enter Server mode, 0 otherwise.
9910     shr     = 1 if device should be opened in shareable mode, 0 otherwise.
9911     flag    = if no dev name given: 1 = close current connection, 0 = resume.
9912     gui     = 1 if called from GUI dialog, 0 otherwise.
9913   Returns:
9914     1 on success
9915     0 on failure and no message printed, slmsg set to failure message.
9916    -9 on failure and message printed, ditto.
9917 */
9918
9919 /* these are bit flags */
9920 #define CX_TAPI 1
9921 #define CX_PPP  2
9922 #define CX_SLIP 4
9923
9924 int
9925 #ifdef CK_ANSIC
9926 cx_serial(char *device, 
9927           int cx, int sx, int shr, int flag, int gui, int special)
9928 #else /* CK_ANSIC */
9929 cx_serial(device, cx, sx, shr, flag, gui, special)
9930     char * device; int cx, sx, shr, flag, gui, special; 
9931 #endif /* CK_ANSIC */
9932 /* cx_serial */ {
9933     int i, n, x, y, msg;
9934     int _local = -1;
9935     char *s;
9936
9937     debug(F110,"cx_serial device",device,0);
9938     s = device;
9939     msg = (gui == 0) && msgflg;         /* Whether to print messages */
9940     success = 0;
9941
9942 #ifndef NODIAL
9943     dialsta = DIA_UNK;
9944 #endif /* NODIAL */
9945     debug(F101,"cx_serial mdmtyp","",mdmtyp);
9946     if (clskconnx(1) < 0)               /* Close the Kermit connection */
9947       return(success = 0);
9948     if (*s) {                           /* They gave a device name */
9949         _local = -1;                    /* Let ttopen decide about it */
9950     } else {                            /* They just said "set line" */
9951         s = dftty;                      /* so go back to normal tty */
9952         _local = dfloc;                 /* and mode. */
9953     }
9954 #ifdef VMS
9955     {
9956         extern int ok_to_share;
9957         ok_to_share = shr;
9958     }
9959 #endif /* VMS */
9960
9961 #ifdef OS2                              /* Must wait until after ttclos() */
9962 #ifdef NT                               /* to change these settings       */
9963 #ifdef CK_TAPI
9964     tttapi = special & CX_TAPI;
9965 #endif /* CK_TAPI */
9966 #else
9967     ttslip = special & CX_SLIP;
9968     ttppp  = special & CX_PPP;
9969 #endif /* NT */
9970     ttshare = shr;                      /* Shareable device ? */
9971     debug(F110,"OS2 SET PORT final s",s,"");
9972 #endif /* OS2 */
9973
9974     /* Open the new line */        
9975
9976     ckstrncpy(ttname,s,TTNAMLEN);
9977     if ((y = ttopen(s,&_local,mdmtyp,cdtimo)) > -1) {
9978         cxtype = (mdmtyp > 0) ? CXT_MODEM : CXT_DIRECT;
9979 #ifndef NODIAL
9980         dialsta = DIA_UNK;
9981 #ifdef CK_TAPI
9982         /* if the line is a tapi device, then we need to auto-execute */
9983         /* SET MODEM TYPE TAPI - which we do the equivalent of here.  */
9984         if (tttapi) {
9985             extern int usermdm;
9986             usermdm = 0;
9987             initmdm(38);                /* From ckudia.c n_TAPI == 38 */
9988         }
9989 #endif /* CK_TAPI */
9990 #endif /* NODIAL */
9991         success = 1;
9992     } else {                            /* Failed */
9993 #ifdef OS2ONLY
9994         if (!strcmp(s,dftty))   /* Do not generate an error with dftty */
9995           ;
9996         else if (y == -6 && ttslip) {
9997             makestr(&slmsg,"Can't access SLIP driver");
9998             if (msg) printf("?%s\n",slmsg);
9999         } else if (y == -6 && ttppp) {
10000             makestr(&slmsg,"Can't access PPP driver");
10001             if (msg) printf("?%s\n",slmsg);
10002         } else
10003 #endif /* OS2ONLY */
10004           if (y == -2) {
10005               makestr(&slmsg,"Timed out - no carrier");
10006               if (msg) {
10007                   printf("?%s\n",slmsg);
10008                   if (hints) {
10009                       printf("\n*************************\n");
10010                       printf(
10011                        "HINT (Use SET HINTS OFF to suppress future hints):\n");
10012                       printf(
10013                           "Try SET CARRIER OFF and SET LINE again, or else\n");
10014                       printf("SET MODEM, SET LINE, and then DIAL.\n");
10015                       printf("*************************\n\n");
10016                   }
10017               }
10018           } else if (y == -3) {
10019               makestr(&slmsg,"Access to lock denied");
10020               if (msg) {
10021 #ifdef UNIX
10022                   printf(
10023                    "Sorry, write access to UUCP lockfile directory denied.\n");
10024 #ifndef NOHINTS
10025                   if (hints) {
10026                       printf("\n*************************\n");
10027                       printf(
10028                        "HINT (Use SET HINTS OFF to suppress future hints):\n");
10029                       printf(
10030           "Please read the installation instructions file, %sckuins.txt,\n",
10031                              k_info_dir ? k_info_dir : ""
10032                              );
10033                       printf(
10034           "or the UNIX appendix of the manual, \"Using C-Kermit\"\n"
10035                              );
10036                       printf(
10037           "or visit http://www.columbia.edu/kermit/ckuins.html \n"
10038                              );
10039                       printf("*************************\n\n");
10040                   }
10041 #endif /* NOHINTS */
10042 #else
10043                   printf("Sorry, access to lock denied: %s\n",s);
10044 #endif /* UNIX */
10045               }
10046           } else if (y == -4) {
10047               makestr(&slmsg,"Access to device denied");
10048               if (msg) {
10049                   printf("Sorry, access to device denied: %s\n",s);
10050 #ifdef UNIX
10051 #ifndef NOHINTS
10052                   if (hints) {
10053                       printf("\n*************************\n");
10054                       printf(
10055                       "HINT (Use SET HINTS OFF to suppress future hints):\n");
10056                       printf(
10057             "Please read the installation instructions file, %sckuins.txt,\n",
10058                              k_info_dir ? k_info_dir : ""
10059                              );
10060                       printf(
10061             "or the UNIX appendix of the manual, \"Using C-Kermit\".\n"
10062                              );
10063                       printf("*************************\n\n");
10064                   }
10065 #endif /* NOHINTS */
10066 #endif /* UNIX */
10067               }
10068           } else if (y == -5) {
10069               makestr(&slmsg,"Device is in use or unavailable");
10070               if (msg)
10071 #ifdef VMS
10072                 printf(
10073                   "Sorry, device is in use or otherwise unavailable: %s\n",s);
10074 #else
10075               printf("Sorry, device is in use: %s\n",s);
10076 #endif /* VMS */
10077           } else {                      /* Other error. */
10078               makestr(&slmsg,"Device open failed");
10079               if (
10080 #ifdef VMS
10081                   1
10082 #else
10083                   errno
10084 #endif /* VMS */
10085                   ) {
10086                   int x;                /* Find a safe, long buffer */
10087                   makestr(&slmsg,ck_errstr());
10088 #ifndef VMS
10089                   debug(F111,"cx_serial serial errno",slmsg,errno);
10090 #endif /* VMS */
10091                   if (msg)
10092                     printf("Connection to %s failed: %s\n",s,slmsg);
10093               } else if (msg)
10094                 printf("Sorry, can't open connection: %s\n",s);
10095           }
10096     }
10097     network = 0;                        /* No network connection active */
10098     speed = ttgspd();
10099     if (!success) {
10100         local = dfloc;                  /* Go back to normal */
10101 #ifndef MAC
10102         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty name */
10103 #endif /* MAC */
10104         haveline = 0;
10105         if (mdmtyp < 0) {               /* Switching from net to async? */
10106             if (mdmsav > -1)            /* Restore modem type from last */
10107               mdmtyp = mdmsav;          /* SET MODEM command, if any. */
10108             else
10109               mdmtyp = 0;
10110             mdmsav = -1;
10111         }
10112         return(msg ? -9 : 0);           /* Return failure */
10113     }
10114     if (_local > -1)
10115       local = _local;                   /* Opened ok, set local/remote. */
10116     makestr(&slmsg,NULL);               /* Erase SET LINE message */
10117     ckstrncpy(ttname,s,TTNAMLEN);       /* Copy name into real place. */
10118     debug(F110,"cx_serial ok",ttname,0);
10119 #ifndef NOXFER
10120     if ((reliable != SET_OFF || !setreliable)) /* Assume not reliable. */
10121       reliable = SET_OFF;
10122 #endif /* NOXFER */
10123
10124   xcx_serial:
10125     setflow();                          /* Set appropriate flow control */
10126     haveline = 1;
10127 #ifdef CKLOGDIAL
10128       dologline();
10129 #endif /* CKLOGDIAL */
10130
10131 #ifndef NOSPL
10132     if (local) {
10133         if (nmac) {                     /* Any macros defined? */
10134             int k;                      /* Yes */
10135             k = mlook(mactab,"on_open",nmac);   /* Look this up */
10136             if (k >= 0) {                       /* If found, */
10137                 if (dodo(k,ttname,0) > -1)      /* set it up, */
10138                   parser(1);                    /* and execute it */
10139             }
10140         }
10141     }
10142 #endif /* NOSPL */
10143
10144     if (local && (cx || sx)) {          /* /CONNECT or /SERVER switch given */
10145         extern int carrier;
10146         if (carrier != CAR_OFF) {       /* Looking for carrier? */
10147             /* Open() turns on DTR -- wait up to a second for CD to come up */
10148             int i, x;
10149             for (i = 0; i < 10; i++) {  /* WAIT 1 CD... */
10150                 x = ttgmdm();
10151                 if (x < 0 || x & BM_DCD)
10152                   break;
10153                 msleep(100);
10154             }
10155         }
10156         if (cx) {                       /* /CONNECT */
10157             /* Command was confirmed so we can pre-pop command level. */
10158             /* This is so CONNECT module won't think we're executing a */
10159             /* script if CONNECT was the final command in the script. */
10160
10161             if (cmdlvl > 0)
10162               prepop();
10163 #ifndef NODIAL
10164             dialsta = DIA_UNK;
10165 #endif /* NODIAL */
10166 #ifdef LOCUS
10167             if (autolocus) {
10168                 setlocus(1,1);
10169             }
10170 #endif /* LOCUS */
10171             success = doconect(0, cmdlvl == 0 ? 1 : 0);
10172             if (ttchk() < 0)
10173               dologend();
10174             return(success);
10175 #ifndef NOXFER
10176         } else if (sx) {                /* /SERVER */
10177             sstate = 'x';
10178 #ifdef MAC
10179             what = W_RECV;
10180             scrcreate();
10181 #endif /* MAC */
10182             if (local) displa = 1;
10183 #ifdef AMIGA
10184             reqoff();                   /* No DOS requestors while server */
10185 #endif /* AMIGA */
10186 #endif /* NOXFER */
10187         }
10188     }
10189 #ifndef NODIAL
10190     dialsta = DIA_UNK;
10191 #endif /* NODIAL */
10192 #ifdef LOCUS
10193     if (autolocus) {
10194         setlocus(1,1);
10195     }
10196 #endif /* LOCUS */
10197     return(success = 1);
10198 }
10199
10200
10201 /* S E T L I N -- parse name of and then open communication device. */
10202 /*
10203   Call with:
10204     xx == XYLINE for a serial (tty) line, XYHOST for a network host,
10205     zz == 0 means if user doesn't give a device name, continue current
10206             active connection (if any);
10207     zz != 0 means if user doesn't give a device name, then close the
10208             current connection and restore the default communication device.
10209     fc == 0 to just make the connection, 1 to also CONNECT (e.g. "telnet").
10210 */
10211 int
10212 setlin(xx, zz, fc) 
10213     int xx, zz, fc; 
10214 {
10215     extern char pwbuf[], * g_pswd;
10216     extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
10217     int wait;
10218     /* int tn_wait_sv; */
10219     int mynet;
10220     int _local = -1;
10221     int c, i, haveswitch = 0;
10222     int haveuser = 0;
10223     int getval = 0;
10224     int wild = 0;                       /* Filespec has wildcards */
10225     int cx = 0;                         /* Connect after */
10226     int sx = 0;                         /* Become server after */
10227     int a_type = -1;                    /* Authentication type */
10228     int e_type = -1;                    /* Telnet /ENCRYPT type */
10229 #ifdef CK_ENCRYPTION
10230     int encrypt = 0;                    /* Encrypted? */
10231 #endif /* CK_ENCRYPTION */
10232     int shr = 0;                        /* Share serial device */
10233     int confirmed = 0;                  /* Command has been entered */
10234     struct FDB sw, tx, nx;
10235 #ifdef OS2
10236     struct FDB fl;
10237 #endif /* OS2 */
10238
10239     char * ss;
10240 #ifdef TCPSOCKET
10241     int rawflg = 0;
10242 #endif /* TCPSOCKET */
10243
10244     char srvbuf[SRVBUFSIZ+1];
10245
10246 #ifdef OS2
10247 #ifdef NT
10248     int xxtapi = 0;
10249 #else
10250     int xxslip = 0, xxppp = 0;
10251 #endif /* NT */
10252 #endif /* OS2 */
10253
10254     int dossh = 0;
10255
10256     debug(F101,"setlin fc","",fc);
10257     debug(F101,"setlin zz","",zz);
10258     debug(F101,"setlin xx","",xx);
10259
10260 #ifdef SSHCMD
10261     if (xx == XXSSH) {                  /* SSH becomes PTY SSH ... */
10262         dossh = 1;
10263         xx = XYHOST;
10264     } else if (!ckstrcmp("ssh ",line,4,0)) { /* 2010/03/01 */
10265         dossh = 1;
10266         xx = XYHOST;
10267     }
10268     debug(F101,"setlin dossh","",dossh);
10269 #endif /* SSHCMD */
10270
10271 #ifdef TNCODE
10272     /* tn_wait_sv = tn_wait_flg; */
10273     wait = tn_wait_flg;
10274 #else
10275     /* tn_wait_sv = 0; */
10276     wait = 0;
10277 #endif /* TNCODE */
10278
10279     mynet = nettype;
10280
10281     if (nolocal) {
10282         makestr(&slmsg,"Making connections is disabled");
10283         printf("?Sorry, making connections is disabled\n");
10284         return(-9);
10285     }
10286     if (netsave > -1)
10287       nettype = netsave;
10288
10289     if (fc != 0 || zz == 0)             /* Preset /CONNECT switch */
10290       cx = 1;
10291
10292     debug(F101,"setlin cx","",cx);
10293
10294     *srvbuf = NUL;
10295
10296     line[0] = NUL;
10297     s = line;
10298
10299 #ifdef NETCONN
10300 #ifdef CK_SECURITY
10301     if (tmpstring)
10302         makestr(&tmpstring,NULL);
10303 #endif /* CK_SECURITY */
10304     if (tmpusrid)
10305         makestr(&tmpusrid,NULL);
10306 #endif /* NETCONN */
10307
10308     autoflow = 1;                       /* Enable automatic flow setting */
10309
10310     if (xx == XYHOST) {                 /* SET HOST <hostname> */
10311 #ifndef NETCONN
10312         makestr(&slmsg,"Network connections not supported");
10313         printf("?%s\n",slmsg);
10314         return(-9);
10315 #else /* NETCONN */
10316 #ifndef NOPUSH
10317         if ((mynet == NET_CMD || mynet == NET_PTY || dossh) && nopush) {
10318             makestr(&slmsg,"Access to external commands is disabled");
10319             printf("?Sorry, access to external commands is disabled\n");
10320             return(-9);
10321         }
10322 #endif /* NOPUSH */
10323
10324 #ifdef SSHCMD
10325         if (dossh) {                    /* SSH connection via pty */
10326             int k;
10327             extern int ttyfd;           /* 2010/03/01 */
10328             k = ckstrncpy(line, sshcmd ? sshcmd : defsshcmd, LINBUFSIZ);
10329             debug(F111,"setlin sshcmd 1",line,k);
10330             if ((x = cmtxt("Optional switches and hostname","",&s,xxstring))<0)
10331               return(x);
10332
10333             /* 2010-03-30 */
10334             if (!*s && ttyfd < 0 && !ckstrcmp("ssh ",ttname,4,0)) { 
10335                 x = ckstrncpy(line,ttname,LINBUFSIZ);
10336             } else {
10337                 if (!*s) {
10338                     printf("?SSH to where?\n");
10339                     return(-9);
10340                 }
10341                 if (k < LINBUFSIZ) {
10342                     line[k++] = SP;
10343                     line[k] = NUL;
10344                     debug(F111,"setlin sshcmd 2",line,k);
10345                 } if (k < LINBUFSIZ) {
10346                     ckstrncpy(&line[k],s,LINBUFSIZ-k);
10347                     debug(F111,"setlin sshcmd 3",line,k);
10348                 } else {
10349                     printf("?Too long\n");
10350                     return(-9);
10351                 }
10352             }
10353             x = cx_net( NET_PTY,                /* network type */
10354                         0,                      /* protocol (not used) */
10355                         line,                   /* host */
10356                         NULL,                   /* service (not used) */
10357                         NULL,                   /* username (not used) */
10358                         NULL,                   /* password (not used) */
10359                         NULL,                   /* command (not used) */
10360                         -1,-1,-1,               /* params 1-3 (not used) */
10361                         1,                      /* connect immediately */
10362                         sx,                     /* server? */
10363                         zz,                     /* close current? */
10364                         0);                     /* not gui */
10365             debug(F111,"setlin cx_net",line,x);
10366             return(x);
10367         }
10368 #endif /* SSHCMD */
10369
10370 /*
10371   Here we parse optional switches and then the hostname or whatever,
10372   which depends on the network type.  The tricky part is, the network type
10373   can be set by a switch.
10374 */
10375 #ifndef NOSPL
10376         makestr(&g_pswd,pwbuf);         /* Save global pwbuf */
10377         g_pflg = pwflg;                 /* and flag */
10378         g_pcpt = pwcrypt;
10379 #endif /* NOSPL */
10380
10381         confirmed = 0;
10382         haveswitch = 0;
10383 #ifdef NETFILE
10384         if (mynet != NET_FILE) {
10385 #endif /* NETFILE */
10386             ss = (mynet == NET_CMD || mynet == NET_PTY) ?
10387               "Command, or switch" :
10388                 (mynet == NET_TCPA || mynet == NET_TCPB
10389                   || mynet == NET_SSH) ?
10390                   "Hostname, ip-address, or switch" :
10391                     "Host or switch";
10392             if (fc) {
10393                 if (mynet == NET_TCPB &&
10394                     (ttnproto == NP_TELNET || ttnproto == NP_KERMIT)) {
10395                     if (nshteltab) {
10396                         haveswitch++;
10397                         cmfdbi(&sw,_CMKEY,ss,"","",nshteltab,4,xxstring,
10398                              shteltab,&nx);
10399                     }
10400                 }
10401 #ifdef RLOGCODE
10402                 else if (mynet == NET_TCPB && ttnproto == NP_RLOGIN) {
10403                     if (nshrlgtab) {
10404                         haveswitch++;
10405                         cmfdbi(&sw,_CMKEY,ss,"","",nshrlgtab,4,xxstring,
10406                                shrlgtab,&nx);
10407                     }
10408                 }
10409 #endif /* RLOGCODE */
10410             } else {
10411                 haveswitch++;
10412                 cmfdbi(&sw,_CMKEY,ss,"","",nshtab,4,xxstring,shtab,&nx);
10413             }
10414 #ifdef NETFILE
10415         }
10416 #endif /* NETFILE */
10417         if (mynet == NET_TCPB || mynet == NET_SLAT ||
10418             mynet == NET_SSH  || mynet == NET_DEC) {
10419             cmfdbi(&nx,_CMFLD,"Host","","",0,0,xxstring,NULL,NULL);
10420 #ifdef NETFILE
10421         } else if (mynet == NET_FILE) {
10422             cmfdbi(&nx,_CMIFI,"Filename","","",0,0,xxstring,NULL,NULL);
10423 #endif /* NETFILE */
10424 #ifdef PTYORPIPE
10425         } else if (mynet == NET_CMD || mynet == NET_PTY) {
10426             cmfdbi(&nx,_CMTXT,"Command","","",0,0,xxstring,NULL,NULL);
10427 #endif /* PTYORPIPE */
10428         } else {
10429             cmfdbi(&nx,_CMTXT,"Host","","",0,0,xxstring,NULL,NULL);
10430         }
10431         while (1) {
10432             x = cmfdb(haveswitch ? &sw : &nx);
10433             debug(F101,"setlin cmfdb","",x);
10434             if (x < 0)
10435               if (x != -3)
10436                 return(x);
10437             if (x == -3) {
10438                 if ((x = cmcfm()) < 0) {
10439                     return(x);
10440                 } else {
10441                     confirmed = 1;
10442                     break;
10443                 }
10444             }
10445             if (cmresult.fcode != _CMKEY) {    /* Not a switch */
10446                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Save the data */
10447                 s = line;                      /* that was parsed... */
10448                 if (cmresult.fcode == _CMIFI) {
10449                     wild = cmresult.nresult;
10450                 } else if (cmresult.fcode == _CMTXT) {
10451                     confirmed = 1;
10452                 }
10453                 break;                  /* and break out of this loop */
10454             }
10455             c = cmgbrk();               /* Have switch - get break character */
10456             getval = (c == ':' || c == '='); /* Must parse an agument? */
10457             if (getval && !(cmresult.kflags & CM_ARG)) {
10458                 printf("?This switch does not take arguments\n");
10459                 return(-9);
10460             }
10461             if (!getval && (cmgkwflgs() & CM_ARG)) {
10462                 printf("?This switch requires an argument\n");
10463                 return(-9);
10464             }
10465             switch (cmresult.nresult) { /* It's a switch.. */
10466               case SL_CNX:              /* /CONNECT */
10467                 cx = 1;
10468                 sx = 0;
10469                 break;
10470               case SL_SRV:              /* /SERVER */
10471                 cx = 0;
10472                 sx = 1;
10473                 break;
10474 #ifdef NETCMD
10475               case SL_CMD:              /* /COMMAND */
10476                 netsave = mynet;
10477                 mynet = NET_CMD;
10478                 break;
10479 #endif /* NETCMD */
10480 #ifdef NETPTY
10481               case SL_PTY:              /* /PTY */
10482                 netsave = mynet;
10483                 mynet = NET_PTY;
10484                 break;
10485 #endif /* NETPTY */
10486               case SL_NET:              /* /NETWORK-TYPE */
10487                 if ((x = cmkey(netcmd,nnets,"","",xxstring)) < 0)
10488                   return(x);
10489                 mynet = x;
10490                 break;
10491
10492 #ifdef CK_SECURITY
10493               case SL_PSW:              /* /PASSWORD: */
10494                 if (!getval)
10495                   break;
10496                 debok = 0;
10497                 if ((x = cmfld("Password","",&s,xxstring)) < 0) {
10498                     if (x == -3) {
10499                         makestr(&tmpstring,"");
10500                     } else {
10501                         return(x);
10502                     }
10503                 } else {
10504                     s = brstrip(s);
10505                     if ((x = (int)strlen(s)) > PWBUFL) {
10506                         makestr(&slmsg,"Internal error");
10507                         printf("?Sorry, too long - max = %d\n",PWBUFL);
10508                         return(-9);
10509                     }
10510                     makestr(&tmpstring,s);
10511                 }
10512                 break;
10513 #endif /* CK_SECURITY */
10514
10515               case SL_UID:              /* /USERID: */
10516                 if (!getval)
10517                   break;
10518                 if ((x = cmfld("Userid","",&s,xxstring)) < 0) {
10519                     if (x == -3) {
10520                         makestr(&tmpusrid,"");
10521                     } else {
10522                         return(x);
10523                     }
10524                 } else {
10525                     s = brstrip(s);
10526                     if ((x = (int)strlen(s)) > 63) {
10527                         makestr(&slmsg,"Internal error");
10528                         printf("?Sorry, too long - max = %d\n",63);
10529                         return(-9);
10530                     }
10531                     makestr(&tmpusrid,s);
10532                     haveuser = 1;
10533                 }
10534                 break;
10535
10536 #ifdef CK_AUTHENTICATION
10537 #ifdef CK_SRP
10538               case SL_SRP:
10539                 a_type = AUTHTYPE_SRP;
10540                 break;
10541 #endif /* CK_SRP */
10542 #ifdef CK_SSL
10543               case SL_SSL:
10544                 a_type = AUTHTYPE_SSL;
10545                 break;
10546 #endif /* CK_SSL */
10547 #ifdef NT
10548               case SL_NTLM:
10549                 a_type = AUTHTYPE_NTLM;
10550                 break;
10551 #endif /* NT */
10552 #ifdef CK_KERBEROS
10553               case SL_KRB4:
10554                 a_type = AUTHTYPE_KERBEROS_V4;
10555                 if (ttnproto == NP_RLOGIN)
10556                   ttnproto =
10557 #ifdef CK_ENCRYPTION
10558                     encrypt ? NP_EK4LOGIN :
10559 #endif /* CK_ENCRYPTION */
10560                       NP_K4LOGIN;
10561                 else if (ttnproto == NP_K5LOGIN)
10562                   ttnproto = NP_K4LOGIN;
10563 #ifdef CK_ENCRYPTION
10564                 else if (ttnproto == NP_EK5LOGIN)
10565                   ttnproto = NP_EK4LOGIN;
10566 #endif /* CK_ENCRYPTION */
10567                 break;
10568               case SL_KRB5:
10569                 a_type = AUTHTYPE_KERBEROS_V5;
10570                 if (ttnproto == NP_RLOGIN)
10571                   ttnproto =
10572 #ifdef CK_ENCRYPTION
10573                     encrypt ? NP_EK5LOGIN :
10574 #endif /* CK_ENCRYPTION */
10575                       NP_K5LOGIN;
10576                 else if (ttnproto == NP_K4LOGIN)
10577                   ttnproto = NP_K5LOGIN;
10578 #ifdef CK_ENCRYPTION
10579                 else if (ttnproto == NP_EK4LOGIN)
10580                   ttnproto = NP_EK5LOGIN;
10581 #endif /* CK_ENCRYPTION */
10582                 break;
10583 #endif /* CK_KERBEROS */
10584               case SL_AUTH: {
10585                   extern struct keytab autyptab[];
10586                   extern int nautyp;
10587                   if ((x = cmkey(autyptab,nautyp,"type of authentication",
10588                                  "automatic",xxstring)) < 0)
10589                     return(x);
10590                   a_type = x;
10591                   break;
10592               }
10593 #endif /* CK_AUTHENTICATION */
10594 #ifdef CK_ENCRYPTION
10595               case SL_ENC:
10596                 switch (ttnproto) {
10597                   case NP_K4LOGIN:
10598                     ttnproto = NP_EK4LOGIN;
10599                     encrypt = 1;
10600                     break;
10601                   case NP_K5LOGIN:
10602                     ttnproto = NP_EK5LOGIN;
10603                     encrypt = 1;
10604                     break;
10605                   case NP_KERMIT:
10606                   case NP_TELNET: {
10607                       static struct keytab * tnetbl = NULL;
10608                       static int ntnetbl = 0;
10609                       x = ck_get_crypt_table(&tnetbl,&ntnetbl);
10610                       debug(F101,"ck_get_crypt_table x","",x);
10611                       debug(F101,"ck_get_crypt_table n","",ntnetbl);
10612                       if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
10613                         x = 0;
10614                       if (!x) {
10615                           makestr(&slmsg,"Internal error");
10616                           printf("?Oops, types not loaded\n");
10617                           return(-9);
10618                       }
10619                       if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
10620                                      "automatic",xxstring)) < 0)
10621                         return(x);
10622                       e_type = x;
10623                       break;
10624                   }
10625                 }
10626                 break;
10627 #endif /* CK_ENCRYPTION */
10628               case SL_WAIT:
10629                 wait = 1;
10630                 break;
10631               case SL_NOWAIT:
10632                 wait = 0;
10633                 break;
10634             }
10635         }
10636
10637 #ifdef NETFILE
10638         if (mynet == NET_FILE) {        /* Parsed by cmifi() */
10639             if ((x = cmcfm()) < 0)      /* Needs confirmation */
10640               return(x);
10641             x = cx_net(mynet,           /* nettype */
10642                        0,               /* protocol (not used) */
10643                        line,            /* host */
10644                        "",              /* port */
10645                        NULL,            /* alternate username */
10646                        NULL,            /* password */
10647                        NULL,            /* command to execute */
10648                        0,               /* param1 */
10649                        0,               /* param2 */
10650                        0,               /* param3 */
10651                        cx,              /* enter CONNECT mode */
10652                        sx,              /* enter SERVER mode */
10653                        zz,              /* close connection if open */
10654                        0                /* gui */
10655                        );
10656         }
10657 #endif /* NETFILE */
10658
10659 #ifdef NETCMD
10660         if (mynet == NET_CMD || mynet == NET_PTY) {
10661             char *p = NULL;
10662             if (!confirmed) {
10663                 if ((x = cmtxt("Rest of command","",&s,xxstring)) < 0)
10664                   return(x);
10665                 if (*s) {
10666                     ckstrncat(line," ",LINBUFSIZ);
10667                     ckstrncat(line,s,LINBUFSIZ);
10668                 }
10669                 s = line;
10670             }
10671             /* s == line - so we must protect the line buffer */
10672             s = brstrip(s);
10673             makestr(&p,s);
10674             ckstrncpy(line,p,LINBUFSIZ);
10675             makestr(&p,NULL);
10676
10677             x = cx_net( mynet,                  /* nettype */
10678                         0,                      /* protocol (not used) */
10679                         line,                   /* host */
10680                         "",                     /* port */
10681                         NULL,                   /* alternate username */
10682                         NULL,                   /* password */
10683                         NULL,                   /* command to execute */
10684                         0,                      /* param1 */
10685                         0,                      /* param2 */
10686                         0,                      /* param3 */
10687                         cx,                     /* enter CONNECT mode */
10688                         sx,                     /* enter SERVER mode */
10689                         zz,                     /* close connection if open */
10690                         0                       /* gui */
10691                         );
10692         }
10693 #endif /* NETCMD */
10694
10695 #ifdef NPIPE                            /* Named pipe */
10696         if (mynet == NET_PIPE) {        /* Needs backslash twiddling */
10697             if (line[0]) {
10698                 if (strcmp(line,"*")) {    /* If remote, begin with */
10699                     char * p = NULL;
10700                     makestr(&p,line);      
10701                     ckstrncpy(line,"\\\\",LINBUFSIZ); /* server name */
10702                     ckstrncat(line,p,LINBUFSIZ);
10703                     makestr(&p,NULL);      
10704                 } else {
10705                     line[0]='\0';
10706                 }
10707                 ckstrncat(line,"\\pipe\\", LINBUFSIZ); /* Make pipe name */
10708                 ckstrncat(line,pipename, LINBUFSIZ); /* Add name of pipe */
10709
10710                 x = cx_net(mynet,       /* nettype */
10711                            0,           /* protocol (not used) */
10712                            line,        /* host */
10713                            "",          /* port */
10714                            NULL,        /* alternate username */
10715                            NULL,        /* password */
10716                            NULL,        /* command to execute */
10717                            0,           /* param1 */
10718                            0,           /* param2 */
10719                            0,           /* param3 */
10720                            cx,          /* enter CONNECT mode */
10721                            sx,          /* enter SERVER mode */
10722                            zz,          /* close connection if open */
10723                            0            /* gui */
10724                            );
10725             }
10726         }
10727 #endif /* NPIPE */
10728
10729 #ifdef SUPERLAT
10730         if (mynet == NET_SLAT) {        /* Needs password, etc. */
10731             slat_pwd[0] = NUL;          /* Erase any previous password */
10732             debok = 0;
10733             if (*line) {                /* If they gave a host name... */
10734                 if ((x = cmfld(
10735                      "password,\n or carriage return if no password required",
10736                                "",
10737                                &s,
10738                                xxstring
10739                                )) < 0 && x != -3)
10740                   return(x);
10741                 ckstrncpy(slat_pwd,s,18); /* Set the password, if any */
10742             }
10743             if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
10744
10745             x = cx_net(mynet,           /* nettype */
10746                        0,               /* protocol (not used) */
10747                        line,            /* host */
10748                        "",              /* port */
10749                        NULL,            /* alternate username */
10750                        NULL,            /* password */
10751                        NULL,            /* command to execute */
10752                        0,               /* param1 */
10753                        0,               /* param2 */
10754                        0,               /* param3 */
10755                        cx,              /* enter CONNECT mode */
10756                        sx,              /* enter SERVER mode */
10757                        zz,              /* close connection if open */
10758                        0                /* gui */
10759                        );
10760         }
10761 #endif /* SUPERLAT */
10762
10763 #ifdef DECNET
10764         if (mynet == NET_DEC) {  
10765             if (!line[0]) {                   /* If they gave a host name... */
10766                 printf("?hostname required\n");
10767                 return(-3);
10768             }
10769             if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
10770
10771             x = cx_net(mynet,           /* nettype */
10772                        0,               /* protocol (not used) */
10773                        line,            /* host */
10774                        "",              /* port */
10775                        NULL,            /* alternate username */
10776                        NULL,            /* password */
10777                        NULL,            /* command to execute */
10778                        0,               /* param1 */
10779                        0,               /* param2 */
10780                        0,               /* param3 */
10781                        cx,              /* enter CONNECT mode */
10782                        sx,              /* enter SERVER mode */
10783                        zz,              /* close connection if open */
10784                        0                /* gui */
10785                        );
10786         }
10787 #endif /* DECNET */
10788
10789 #ifdef SSHBUILTIN
10790         if (mynet == NET_SSH) {         /* SSH connection */
10791             int k, havehost = 0, trips = 0;
10792             int    tmpver = -1, tmpxfw = -1, tmpssh_cas;
10793 #ifndef SSHTEST
10794             extern int sl_ssh_xfw, sl_ssh_xfw_saved;
10795             extern int sl_ssh_ver, sl_ssh_ver_saved;
10796 #endif /* SSHTEST */
10797             extern struct keytab sshopnsw[];
10798             extern int nsshopnsw;
10799             extern char *ssh_tmpcmd, *ssh_tmpport;
10800             struct FDB sw, kw, fl;
10801
10802             debug(F110,"setlin SSH service 0",srvbuf,0);
10803             debug(F110,"setlin SSH host s 2",s,0);
10804             if (*s) {           /* If they gave a host name... */
10805                 debug(F110,"setlin SSH host s 1",s,0);
10806                 if (*s == '*') {
10807                     makestr(&slmsg,"Incoming connections not supported");
10808                     printf(
10809      "?Sorry, incoming connections not supported for SSH.\n"
10810                            );
10811                     return(-9);
10812                 }
10813                 ckstrncpy(line,s,LINBUFSIZ);
10814             } else {
10815                 printf("?hostname required\n");
10816                 return(-3);
10817             }
10818
10819             /* Parse [ port ] [ switches ] */
10820             cmfdbi(&kw,                 /* Switches */
10821                     _CMKEY,
10822                     "Port number or service name,\nor switch",
10823                     "",
10824                     "",
10825                     nsshopnsw,
10826                     4,
10827                     xxstring,
10828                     sshopnsw,
10829                     &fl
10830                     );
10831             cmfdbi(&fl,                 /* Port number or service name */
10832                     _CMFLD,
10833                     "",
10834                     "",
10835                     "",
10836                     0,
10837                     0,
10838                     xxstring,
10839                     NULL,
10840                     NULL
10841                     );
10842             trips = 0;                  /* Explained below */
10843             while (1) {                 /* Parse port and switches */
10844                 y = cmfdb(&kw);         /* Get a field */
10845                 if (y == -3)            /* User typed CR so quit from loop */
10846                     break;
10847                 if (y < 0)              /* Other parse error, pass it back */
10848                     return(y);
10849                 switch (cmresult.fcode) { /* Field or Keyword? */
10850                 case _CMFLD:              /* Field */
10851                     ckstrncpy(srvbuf,cmresult.sresult,SRVBUFSIZ);
10852                     break;
10853                 case _CMKEY:            /* Keyword */
10854                     switch (cmresult.nresult) { /* Which one? */
10855                     case SSHSW_PWD:
10856                         if (!cmgbrk()) {
10857                             printf("?This switch requires an argument\n");
10858                             return(-9);
10859                         }
10860                         debok = 0;
10861                         if ((y = cmfld("Password","",&s,xxstring)) < 0) {
10862                             if (y == -3) {
10863                                 makestr(&tmpstring,"");
10864                             } else {
10865                                 return(y);
10866                             }
10867                         } else {
10868                             s = brstrip(s);
10869                             if ((y = (int)strlen(s)) > PWBUFL) {
10870                                 makestr(&slmsg,"Internal error");
10871                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
10872                                 return(-9);
10873                             }
10874                             makestr(&tmpstring,s);
10875                         }
10876                         break;
10877                     case SSHSW_USR:             /* /USER: */
10878                         if (!cmgbrk()) {
10879                             printf("?This switch requires an argument\n");
10880                             return(-9);
10881                         }
10882                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
10883                             return(y);
10884                         s = brstrip(s);
10885                         makestr(&tmpusrid,s);
10886                         break;
10887                     case SSHSW_VER:
10888                         if ((y = cmnum("Number","",10,&z,xxstring)) < 0)
10889                             return(y);
10890                         if (z < 1 || z > 2) {
10891                             printf("?Out of range: %d\n",z);
10892                             return(-9);
10893                         }
10894                         tmpver = z;
10895                         break;
10896                     case SSHSW_CMD:
10897                     case SSHSW_SUB:
10898                         if ((y = cmfld("Text","",&s,xxstring)) < 0)
10899                           return(y);
10900                         makestr(&ssh_tmpcmd,s);
10901                         tmpssh_cas = (cmresult.nresult == SSHSW_SUB);
10902                         break;
10903                     case SSHSW_X11:
10904                         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
10905                             return(y);
10906                         tmpxfw = y;
10907                         break;
10908                     default:
10909                         return(-2);
10910                     }
10911                 }
10912                 if (trips++ == 0) {     /* After first time through */
10913                     cmfdbi(&kw,         /* only parse switches, not port. */
10914                             _CMKEY,
10915                             "Switch",
10916                             "",
10917                             "",
10918                             nsshopnsw,
10919                             4,
10920                             xxstring,
10921                             sshopnsw,
10922                             NULL
10923                             );
10924                 }
10925             }
10926             if ((y = cmcfm()) < 0)      /* Get confirmation */
10927                 return(y);
10928
10929             debug(F110,"setlin pre-cx_net line",line,0);
10930             debug(F110,"setlin pre-cx_net srvbuf",srvbuf,0);
10931             x = cx_net( mynet,                  /* nettype */
10932                         0,                      /* protocol (not used) */
10933                         line,                   /* host */
10934                         srvbuf,                 /* port */
10935                         tmpusrid,               /* alternate username */
10936                         tmpstring,              /* password */
10937                         ssh_tmpcmd,             /* command to execute */
10938                         tmpver,                 /* param1 - ssh version */
10939                         tmpssh_cas,             /* param2 - ssh cas  */
10940                         tmpxfw,                 /* param3 - ssh x11fwd */
10941                         cx,                     /* enter CONNECT mode */
10942                         sx,                     /* enter SERVER mode */
10943                         zz,                     /* close connection if open */
10944                         0                       /* gui */
10945                         );
10946             if (tmpusrid)
10947                 makestr(&tmpusrid,NULL);
10948             if (ssh_tmpcmd)
10949                 makestr(&ssh_tmpcmd,NULL);
10950         }
10951 #endif /* SSHBUILTIN */
10952
10953 #ifdef TCPSOCKET
10954         if (mynet == NET_TCPB) {        /* TCP/IP connection */
10955             debug(F110,"setlin service 0",srvbuf,0);
10956             debug(F110,"setlin host s 2",s,0);
10957             if (*s) {                   /* If they gave a host name... */
10958                 debug(F110,"setlin host s 1",s,0);
10959 #ifdef NOLISTEN
10960                 if (*s == '*') {
10961                     makestr(&slmsg,"Incoming connections not supported");
10962                     printf(
10963      "?Sorry, incoming connections not supported in this version of Kermit.\n"
10964                            );
10965                     return(-9);
10966                 }
10967 #endif /* NOLISTEN */
10968 #ifdef RLOGCODE
10969                 /* Allow a username if rlogin is requested */
10970                 if (mynet == NET_TCPB &&
10971                     (ttnproto == NP_RLOGIN || ttnproto == NP_K5LOGIN ||
10972                      ttnproto == NP_EK5LOGIN || ttnproto == NP_K4LOGIN ||
10973                      ttnproto == NP_EK4LOGIN
10974                     )) {
10975                     int y;
10976                     uidflag = 0;
10977                     /* Check for "host:service" */
10978                     for ( ; (*s != '\0') && (*s != ':'); s++) ;
10979                     if (*s) {   /* Service, save it */
10980                         *s = NUL;
10981                         ckstrncpy(srvbuf,++s,SRVBUFSIZ);
10982                     } else {            /* No :service, then use default. */
10983 #ifdef VMS
10984                         switch (ttnproto) {
10985                           case NP_RLOGIN:
10986                             ckstrncpy(srvbuf,"513",SRVBUFSIZ); /* "login" */
10987                             break;
10988                           case NP_K4LOGIN:
10989                           case NP_K5LOGIN:
10990                             ckstrncpy(srvbuf,"543",SRVBUFSIZ); /* "klogin" */
10991                             break;
10992                           case NP_EK4LOGIN:
10993                           case NP_EK5LOGIN:
10994                             ckstrncpy(srvbuf,"2105",SRVBUFSIZ); /* "eklogin" */
10995                             break;
10996                         }
10997 #else /* VMS */
10998                         switch (ttnproto) {
10999                           case NP_RLOGIN:
11000                             ckstrncpy(srvbuf,"login",SRVBUFSIZ);
11001                             break;
11002                           case NP_K4LOGIN:
11003                           case NP_K5LOGIN:
11004                             ckstrncpy(srvbuf,"klogin",SRVBUFSIZ);
11005                             break;
11006                           case NP_EK4LOGIN:
11007                           case NP_EK5LOGIN:
11008                             ckstrncpy(srvbuf,"eklogin",SRVBUFSIZ);
11009                             break;
11010                         }
11011 #endif /* VMS */
11012                     }
11013                     if (!confirmed) {
11014                         y = cmfld("Userid on remote system",
11015                                   uidbuf,&s,xxstring);
11016                         if (y < 0 && y != -3)
11017                           return(y);
11018                         if ((int)strlen(s) > 63) {
11019                             makestr(&slmsg,"Internal error");
11020                             printf("Sorry, too long\n");
11021                             return(-9);
11022                         }
11023                         makestr(&tmpusrid,s);
11024                     }
11025                 } else {        /* TELNET or SET HOST */
11026 #endif /* RLOGCODE */
11027                     /* Check for "host:service" */
11028                     for ( ; (*s != '\0') && (*s != ':'); s++) ;
11029                     if (*s) {   /* Service, save it */
11030                         *s = NUL;
11031                         ckstrncpy(srvbuf,++s,SRVBUFSIZ);
11032                     } else if (!confirmed) {
11033                         /* No :service, let them type one. */
11034                         if (*line != '*') { /* Not incoming */
11035                             if (mynet == NET_TCPB && ttnproto == NP_KERMIT) {
11036                                 if ((x = cmfld(
11037                                                "TCP service name or number",
11038                                                "kermit",&s,xxstring)
11039                                      ) < 0 && x != -3)
11040                                   return(x);
11041 #ifdef RLOGCODE
11042                             } else if (mynet == NET_TCPB &&
11043                                        ttnproto == NP_RLOGIN) {
11044                                 if ((x = cmfld(
11045   "TCP service name or number,\n or carriage return for rlogin (513)",
11046                                                "login",&s,xxstring)
11047                                      ) < 0 && x != -3)
11048                                   return(x);
11049 #ifdef CK_AUTHENTICATION
11050 #ifdef CK_KERBEROS
11051                             } else if (mynet == NET_TCPB &&
11052                                        (ttnproto == NP_K4LOGIN ||
11053                                        ttnproto == NP_K5LOGIN)) {
11054                                 if ((x = cmfld(
11055   "TCP service name or number,\n or carriage return for klogin (543)",
11056                                                "klogin",&s,xxstring)
11057                                      ) < 0 && x != -3)
11058                                   return(x);
11059                             } else if (mynet == NET_TCPB &&
11060                                        (ttnproto == NP_EK4LOGIN ||
11061                                         ttnproto == NP_EK5LOGIN)) {
11062                                 if ((x = cmfld(
11063   "TCP service name or number,\n or carriage return for eklogin (2105)",
11064                                                "eklogin",&s,xxstring)
11065                                      ) < 0 && x != -3)
11066                                   return(x);
11067 #endif /* CK_KERBEROS */
11068 #endif /* CK_AUTHENTICATION */
11069 #endif /* RLOGCODE */
11070                             } else {
11071                                 /* Do not set a default value in this call */
11072                                 /* If you do then it will prevent entries  */
11073                                 /* in the network directory from accessing */
11074                                 /* alternate ports.                        */
11075
11076                                 if ((x = cmfld(
11077                                                "TCP service name or number",
11078                                                "",&s,xxstring)
11079                                      ) < 0 && x != -3)
11080                                   return(x);
11081                             }
11082                         } else { /* Incoming connection */
11083                             if ((x = cmfld("TCP service name or number",
11084                                            "",&s,xxstring)
11085                                  ) < 0 && x != -3)
11086                               return(x);
11087                         }
11088                         if (*s)         /* If they gave a service, */
11089                           ckstrncpy(srvbuf,s,SRVBUFSIZ); /* copy it */
11090                         debug(F110,"setlin service 0.5",srvbuf,0);
11091                     }
11092 #ifdef RLOGCODE
11093                 }
11094 #endif /* RLOGCODE */
11095                 if (!confirmed) {
11096                     char * defproto;
11097                     switch (ttnproto) {
11098                       case NP_RLOGIN:
11099                         defproto = "/rlogin";
11100                         break;
11101                       case NP_K4LOGIN:
11102                         defproto = "/k4login";
11103                         break;
11104                       case NP_K5LOGIN:
11105                         defproto = "/k5login";
11106                         break;
11107                       case NP_EK4LOGIN:
11108                         defproto = "/ek4login";
11109                         break;
11110                       case NP_EK5LOGIN:
11111                         defproto = "/ek5login";
11112                         break;
11113                       case NP_KERMIT:
11114                       case NP_TELNET:
11115                         defproto = "/telnet";
11116                         break;
11117                       default:
11118                         defproto = "/default";
11119                     }
11120                     if ((x = cmkey(tcprawtab,ntcpraw,"Switch",defproto,
11121                                    xxstring)) < 0) {
11122                         if (x != -3)
11123                           return(x);
11124                         else if ((x = cmcfm()) < 0)
11125                           return(x);
11126                     } else {
11127                         rawflg = x;
11128                         if ((x = cmcfm()) < 0)
11129                           return(x);
11130                     }
11131                 }
11132             }
11133             debug(F110,"setlin pre-cx_net line",line,0);
11134             debug(F110,"setlin pre-cx_net srvbuf",srvbuf,0);
11135             x = cx_net( mynet,                  /* nettype */
11136                         rawflg                  /* protocol */,
11137                         line,                   /* host */
11138                         srvbuf,                 /* port */
11139                         tmpusrid,               /* alternate username */
11140                         tmpstring,              /* password */
11141                         NULL,                   /* command to execute */
11142                         a_type,                 /* param1 - telnet authtype */
11143                         e_type,                 /* param2 - telnet enctype  */
11144                         wait,                   /* param3 - telnet wait */
11145                         cx,                     /* enter CONNECT mode */
11146                         sx,                     /* enter SERVER mode */
11147                         zz,                     /* close connection if open */
11148                         0                       /* gui */
11149                         );
11150         }
11151 #endif /* TCPSOCKET */
11152
11153 #ifdef CK_SECURITY
11154         if (tmpstring)
11155             makestr(&tmpstring,NULL);
11156 #endif /* CK_SECURITY */
11157         if (tmpusrid)
11158             makestr(&tmpusrid,NULL);
11159         debug(F111,"setlin cx_net",line,x);
11160         return(x);
11161 #endif /* NETCONN */
11162     }
11163
11164 /* Serial tty device, possibly modem, connection... */
11165
11166 #ifdef OS2
11167 /*
11168   User can type:
11169     COM1..COM8 = Regular COM port
11170     1..8       = Synonym for COM1..COM8, is translated to COM1..COM8
11171     _n         = (n is a number) = open file handle
11172     string     = any text string = name of some other kind of device,
11173                  taken literally, as given.
11174 */
11175     s = "Communication device name";
11176
11177 #ifdef CK_TAPI
11178     if (TAPIAvail)
11179       cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
11180     if (!(tapilinetab && _tapilinetab && ntapiline > 0) &&
11181         xx == XYTAPI_LIN ) {
11182         makestr(&slmsg,"TAPI device not configured");
11183         printf("\nNo TAPI Line Devices are configured for this system\n");
11184         return(-9);
11185     }
11186     if (xx == XYTAPI_LIN) {             /* Default (first) TAPI line */
11187         s = "tapi";                     /* (whatever it is) */
11188     } else {                            /* Query the user */
11189 #endif /* CK_TAPI */
11190
11191 /* Now parse optional switches and then device name */
11192
11193         confirmed = 0;
11194         cmfdbi(&sw,_CMKEY,"Device name, or switch",
11195                "","",npsltab,4,xxstring,psltab,&fl);
11196         cmfdbi(&fl,_CMFLD,"",dftty,"",0,0,xxstring,NULL,NULL);
11197         while (1) {
11198             x = cmfdb(&sw);
11199             debug(F101,"setlin cmfdb","",x);
11200             if (x < 0)
11201               if (x != -3)
11202                 return(x);
11203             if (x == -3) {
11204                 if ((x = cmcfm()) < 0) {
11205                     return(x);
11206                 } else {
11207                     confirmed = 1;
11208                     break;
11209                 }
11210             }
11211             if (cmresult.fcode == _CMFLD) {
11212                 s = cmresult.sresult;
11213                 break;
11214             } else if (cmresult.fcode == _CMKEY) {
11215                 switch (cmresult.nresult) {
11216                   case SL_CNX:          /* /CONNECT */
11217                     cx = 1;
11218                     sx = 0;
11219                     break;
11220                   case SL_SRV:          /* /SERVER */
11221                     cx = 0;
11222                     sx = 1;
11223                     break;
11224                   case SL_SHR:          /* /SHARE */
11225                     shr = 1;
11226                     break;
11227                   case SL_NSH:          /* /NOSHARE */
11228                     shr = 0;
11229                     break;
11230                 }
11231             }
11232         }
11233 #ifdef CK_TAPI
11234     }
11235 #endif /* CK_TAPI */
11236
11237     debug(F110,"OS2 SET PORT s",s,0);
11238     y = lookup(os2devtab,s,nos2dev,&x); /* Look up in keyword table */
11239     debug(F101,"OS2 SET PORT x","",x);
11240     debug(F101,"OS2 SET PORT y","",y);
11241     if ((y > -1) && (x >= 0 && x < 8)) { /* User typed a digit 1..8 */
11242         s = os2devtab[x+8].kwd;         /* Substitite its real name */
11243 #ifdef NT
11244         xxtapi = 0;
11245 #else /* NT */
11246         xxslip = xxppp = 0;
11247 #endif /* NT */
11248         debug(F110,"OS2 SET PORT subst s",s,"");
11249 #ifndef NT
11250     } else if ((y >-1) && (x >= 16 && x < 24)) { /* SLIP access */
11251         s = os2devtab[x-8].kwd;         /* Substitite its real name */
11252         debug(F110,"OS2 SET PORT SLIP subst s",s,"");
11253         xxslip = 1;
11254         xxppp  = 0;
11255     } else if ((y >-1) && (x >= 24 && x < 32)) { /* PPP access */
11256         s = os2devtab[x-16].kwd;        /* Substitite its real name */
11257         debug(F110,"OS2 SET PORT PPP subst s",s,"");
11258         xxppp = 1;
11259         xxslip = 0;
11260         if ((y = cmkey(os2ppptab,
11261                        nos2ppp,
11262                        "PPP driver interface",
11263                        "ppp0",
11264                        xxstring)
11265              ) < 0)
11266           return(y);
11267         debug(F101,"OS2 SET PORT PPP INTERFACE y","",y);
11268         xxppp = (y % 10) + 1;
11269 #endif /* NT */
11270     } else if (*s == '_') {             /* User used "_" prefix */
11271         s++;                            /* Remove it */
11272         /* Rest must be numeric */
11273         debug(F110,"OS2 SET PORT HANDLE _subst s",s,0);
11274         if (!rdigits(s)) {
11275             makestr(&slmsg,"Invalid file handle");
11276             printf("?Invalid format for file handle\n");
11277             return(-9);
11278         }
11279 #ifdef NT
11280         xxtapi = 0;
11281 #else /* NT */
11282         xxslip = xxppp = 0;
11283 #endif /* NT */
11284     } else {                            /* A normal COMx port or a string */
11285         s = brstrip(s);                 /* Strip braces if any */
11286 #ifdef NT
11287 #ifdef CK_TAPI
11288         /* Windows TAPI support - Look up in keyword table */
11289         if (tapilinetab && _tapilinetab && ntapiline > 0) {
11290             if (!ckstrcmp(s,"tapi",4,0)) {
11291
11292                 /* Find out what the lowest numbered TAPI device is */
11293                 /* and use it as the default.                       */
11294                 int j = 9999, k = -1;
11295                 for (i = 0; i < ntapiline; i++) {
11296                     if (tapilinetab[i].kwval < j) {
11297                         j = tapilinetab[i].kwval;
11298                         k = i;
11299                     }
11300                 }
11301                 if (k >= 0)
11302                   s = _tapilinetab[k].kwd;
11303                 else
11304                   s = "";
11305
11306                 if ((y = cmkey(_tapilinetab,ntapiline,
11307                                "TAPI device name",s,xxstring)) < 0)
11308                   return(y);
11309
11310                 xxtapi = 1;
11311
11312                 /* Get the non Underscored string */
11313                 for (i = 0; i < ntapiline; i++ ) {
11314                     if (tapilinetab[i].kwval == y) {
11315                         s = tapilinetab[i].kwd;
11316                         break;
11317                     }
11318                 }
11319             } else
11320               xxtapi = 0;
11321         }
11322 #endif /* CK_TAPI */
11323 #else /* NT */
11324         /* not OS/2 SLIP or PPP */
11325         xxslip = xxppp = 0;
11326 #endif /* NT */
11327     }
11328     ckstrncpy(tmpbuf,s,TMPBUFSIZ);      /* Copy to a safe place */
11329     s = tmpbuf;
11330     if ((x = cmcfm()) < 0)
11331       return(x);
11332
11333 #else /* !OS2 */
11334
11335     cmfdbi(&sw,_CMKEY,"Device name, or switch",
11336            "","",npsltab,4,xxstring,psltab,&tx);
11337     cmfdbi(&tx,_CMTXT,"",dftty,"",0,0,xxstring,NULL,NULL);
11338     while (!confirmed) {
11339         x = cmfdb(&sw);
11340         debug(F101,"setlin cmfdb","",x);
11341         if (x < 0)
11342           if (x != -3)
11343             return(x);
11344         if (x == -3) {
11345             if ((x = cmcfm()) < 0) {
11346                 return(x);
11347             } else {
11348                 confirmed = 1;
11349                 break;
11350             }
11351         }
11352         switch (cmresult.fcode) {
11353           case _CMTXT:
11354             ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
11355             s = tmpbuf;
11356             debug(F110,"setlin CMTXT",tmpbuf,0);
11357             confirmed = 1;
11358             break;
11359           case _CMKEY:                  /* Switch */
11360             debug(F101,"setlin CMKEY",tmpbuf,cmresult.nresult);
11361             switch (cmresult.nresult) {
11362               case SL_CNX:              /* /CONNECT */
11363                 cx = 1;
11364                 sx = 0;
11365                 break;
11366               case SL_SRV:              /* /SERVER */
11367                 cx = 0;
11368                 sx = 1;
11369                 break;
11370 #ifdef VMS
11371               case SL_SHR:              /* /SHARE */
11372                 shr = 1;
11373                 break;
11374               case SL_NSH:              /* /NOSHARE */
11375                 shr = 0;
11376                 break;
11377 #endif /* VMS */
11378             }
11379             continue;
11380           default:
11381             debug(F101,"setlin bad cmfdb result","",cmresult.fcode);
11382             makestr(&slmsg,"Internal error");
11383             printf("?Internal parsing error\n");
11384             return(-9);
11385         }
11386     }
11387 #endif /* OS2 */
11388     if (!confirmed)
11389       if ((x = cmcfm()) < 0)
11390         return(x);
11391
11392     debug(F110,"setlin pre-cx_serial s",s,0);
11393     debug(F110,"setlin pre-cx_serial line",line,0);
11394     x = cx_serial(s,cx,sx,shr,zz,0,
11395 #ifdef OS2
11396 #ifdef NT
11397                    (xxtapi ? CX_TAPI : 0)
11398 #else
11399                    (xxslip ? CX_SLIP : 0) | (xxppp ? CX_PPP : 0)
11400 #endif /* NT */
11401 #else /* OS2 */
11402                    0
11403 #endif /* OS2 */
11404                    );
11405     debug(F111,"setlin cx_serial",line,x);
11406     return(x);
11407 }
11408 #endif /* NOLOCAL */
11409
11410 #ifdef CKCHANNELIO
11411 /*
11412   C-Library based file-i/o package for scripts.  This should be portable to
11413   all C-Kermit versions since it uses the same APIs we have always used for
11414   processing command files.  The entire channel i/o package is contained
11415   herein, apart from some keyword table entries in the main keyword table
11416   and the help text in the HELP command module.
11417
11418   On platforms like VMS and VOS, this package handles only UNIX-style
11419   stream files.  If desired, it can be replaced for those platforms by
11420   <#>ifdef'ing out this code and adding the equivalent replacement routines
11421   to the ck?fio.c module, e.g. for RMS-based file i/o in ckvfio.c.
11422 */
11423 #ifndef NOSTAT
11424 #ifdef VMS
11425 /* 2010-03-09 SMS.  VAX C needs help to find "sys".  It's easier not to try. */
11426 #include <stat.h>
11427 #else /* def VMS */
11428 #include <sys/stat.h>
11429 #endif /* def VMS [else] */
11430 #endif /* NOSTAT */
11431
11432 #ifdef NLCHAR
11433 static int z_lt = 1;                    /* Length of line terminator */
11434 #else
11435 static int z_lt = 2;
11436 #endif /* NLCHAR */
11437
11438 struct ckz_file {                       /* C-Kermit file struct */
11439     FILE * z_fp;                        /* Includes the C-Lib file struct */
11440     unsigned int z_flags;               /* Plus C-Kermit mode flags, */
11441     CK_OFF_T z_nline;                   /* current line number if known, */
11442     char z_name[CKMAXPATH+2];           /* and the file's name. */
11443 };
11444 static struct ckz_file ** z_file = NULL; /* Array of C-Kermit file structs */
11445 static int z_inited = 0;                /* Flag for array initialized */
11446 int z_maxchan = Z_MAXCHAN;              /* Max number of C-Kermit channels */
11447 int z_openmax = CKMAXOPEN;              /* Max number of open files overall */
11448 int z_nopen = 0;                        /* How many channels presently open */
11449 int z_error = 0;                        /* Most recent error */
11450 int z_filcount = -1;                    /* Most recent FILE COUNT result */
11451
11452 #define RD_LINE 0                       /* FILE READ options */
11453 #define RD_CHAR 1
11454 #define RD_SIZE 2
11455 #define RD_TRIM 8                       /* Like Snobol &TRIM = 1 */
11456 #define RD_UNTA 9                       /* Untabify */
11457
11458 #define WR_LINE RD_LINE                 /* FILE WRITE options */
11459 #define WR_CHAR RD_CHAR
11460 #define WR_SIZE RD_SIZE
11461 #define WR_STRI 3
11462 #define WR_LPAD 4
11463 #define WR_RPAD 5
11464
11465 #ifdef UNIX
11466 extern int ckmaxfiles;                  /* Filled in by sysinit(). */
11467 #endif /* UNIX */
11468
11469 /* See ckcker.h for error numbers */
11470 /* See ckcdeb.h for Z_MAXCHAN and CKMAXOPEN definitions */
11471 /* NOTE: For VMS we might be able to fill in ckmaxfiles */
11472 /* from FILLM and CHANNELCNT -- find out about these... */
11473
11474 static char * fopnargs[] = {            /* Mode combinations for fopen() */
11475 #ifdef COMMENT
11476     /* All combinations of rwa */
11477     "",  "r",  "w",  "rw",  "a",  "ra",  "wa",  "rwa", /* Text mode */
11478     "b", "rb", "wb", "rwb", "ab", "rab", "wab", "rwab" /* Binary mode */
11479 #else
11480     /* Combinations and syntax permitted by C libraries... */
11481     "",  "r",  "w",  "r+",  "a",  "",   "a",  "", /* Text mode */
11482 #ifdef OS2
11483     "",  "rb", "wb", "r+b", "ab", "",   "ab", "" /* Binary modes for K95 */
11484 #else
11485 #ifdef VMS
11486     "",  "rb", "wb", "r+b", "ab", "",   "ab", "" /* Binary modes for VMS */
11487 #else
11488     "",  "r",   "w", "r+",  "a",  "",   "a",  "" /* Binary modes for UNIX */
11489 #endif /* VMS */
11490 #endif /* OS2 */
11491 #endif /* COMMENT */
11492 };
11493 static int nfopnargs = sizeof(fopnargs) / sizeof(char *);
11494
11495 char *                                  /* Error messages */
11496 ckferror(n) int n; {
11497     switch (n) {
11498       case FX_NER: return("No error");
11499       case FX_SYS: return(ck_errstr());
11500       case FX_EOF: return("End of file");
11501       case FX_NOP: return("File not open");
11502       case FX_CHN: return("Channel out of range");
11503       case FX_RNG: return("Parameter out of range");
11504       case FX_NMF: return("Too many files open");
11505       case FX_FOP: return("Operation conflicts with OPEN mode");
11506       case FX_NYI: return("OPEN mode not supported");
11507       case FX_BOM: return("Illegal combination of OPEN modes");
11508       case FX_ACC: return("Access denied");
11509       case FX_FNF: return("File not found");
11510       case FX_OFL: return("Buffer overflow");
11511       case FX_LNU: return("Current line number unknown");
11512       case FX_ROO: return("Off limits");
11513       case FX_UNK: return("Operation fails - reason unknown");
11514       default: return("Error number out of range");
11515     }
11516 }
11517
11518 /*
11519   Z _ O P E N --  Open a file for the requested type of access.
11520
11521   Call with:
11522     name:  Name of file to be opened.
11523     flags: Any combination of FM_xxx values except FM_EOF (ckcker.h).
11524   Returns:
11525     >= 0 on success: The assigned channel number
11526     <  0 on failure: A negative FX_xxx error code (ckcker.h).
11527 */
11528 int
11529 z_open(name, flags) char * name; int flags; {
11530     int i, n;
11531     FILE * t;
11532     char * mode;
11533     debug(F111,"z_open",name,flags);
11534     if (!name) name = "";               /* Check name argument */
11535     if (!name[0])
11536       return(z_error = FX_BFN);
11537     if (flags & FM_CMD)                 /* Opening pipes not implemented yet */
11538       return(z_error = FX_NYI);         /* (and not portable either) */
11539     debug(F101,"z_open nfopnargs","",nfopnargs);
11540     if (flags < 0 || flags >= nfopnargs) /* Range check flags */
11541       return(z_error = FX_RNG);
11542     mode = fopnargs[flags];             /* Get fopen() arg */
11543     debug(F111,"z_open fopen args",mode,flags);
11544     if (!mode[0])                       /* Check for illegal combinations */
11545       return(z_error = FX_BOM);
11546     if (!z_inited) {                    /* If file structs not inited */
11547         debug(F101,"z_open z_maxchan 1","",z_maxchan);
11548 #ifdef UNIX
11549         debug(F101,"z_open ckmaxfiles","",ckmaxfiles);
11550         if (ckmaxfiles > 0) {           /* Set in ck?tio.c: sysinit() */
11551             int x;
11552             x = ckmaxfiles - ZNFILS - 5;
11553             if (x > z_maxchan)          /* sysconf() value greater than */
11554               z_maxchan = x;            /* value from header files. */
11555             debug(F101,"z_open z_maxchan 2","",z_maxchan);
11556         }
11557 #endif /* UNIX */
11558         if (z_maxchan < Z_MINCHAN)      /* Allocate at least this many. */
11559           z_maxchan = Z_MINCHAN;
11560         debug(F101,"z_open z_maxchan 3","",z_maxchan);
11561         /* Note: This could be a pretty big chunk of memory */
11562         /* if z_maxchan is a big number.  If this becomes a problem */
11563         /* we'll need to malloc and free each element at open/close time */
11564 #ifdef COMMENT
11565         /* May 2006 - it's time - in current Linux this about 3MB */
11566         if (!(z_file = (struct ckz_file *)
11567               malloc(sizeof(struct ckz_file) * (z_maxchan + 1))))
11568           return(z_error = FX_NMF);
11569         for (i = 0; i < z_maxchan; i++) {
11570             z_file[i].z_fp = NULL;
11571             z_file[i].z_flags = 0;
11572             z_file[i].z_nline = 0;
11573             *(z_file[i].z_name) = '\0';
11574         }
11575 #else
11576         /* New economical way, allocate storage for each channel as needed */
11577         if (!z_file) {
11578             z_file = (struct ckz_file **)malloc((z_maxchan + 1) *
11579                                                 sizeof(struct ckz_file *));
11580             if (!z_file)
11581               return(z_error = FX_NMF);
11582             for (i = 0; i < z_maxchan; i++)
11583               z_file[i] = NULL;
11584         }
11585 #endif  /* COMMENT */
11586         z_inited = 1;                   /* Remember we initialized */
11587     }
11588     for (n = -1, i = 0; i < z_maxchan; i++) { /* Find a free channel */
11589 #ifdef COMMENT
11590         if (!z_file[i].z_fp) {
11591             n = i;
11592             break;
11593         }
11594 #else
11595         if (!z_file[i]) {
11596             z_file[i] = (struct ckz_file *) malloc(sizeof(struct ckz_file));
11597             if (!z_file[i])
11598               return(z_error = FX_NMF);
11599             n = i;
11600             break;
11601         }
11602 #endif  /* COMMENT */
11603
11604     }
11605     if (n < 0 || n >= z_maxchan)        /* Any free channels? */
11606       return(z_error = FX_NMF);         /* No, fail. */
11607     errno = 0;
11608
11609     z_file[n]->z_flags = 0;             /* In case of failure... */
11610     z_file[n]->z_fp = NULL;             /* Set file pointer to NULL */
11611
11612     t = fopen(name, mode);              /* Try to open the file. */
11613     if (!t) {                           /* Failed... */
11614         debug(F111,"z_open error",name,errno);
11615 #ifdef EMFILE
11616         if (errno == EMFILE)
11617           return(z_error = FX_NMF);
11618 #endif /* EMFILE */
11619         free(z_file[n]);
11620         z_file[n] = NULL;
11621         return(z_error = (errno ?  FX_SYS : FX_UNK)); /* Return error code */
11622     }
11623 #ifdef NT
11624 #ifdef O_SEQUENTIAL
11625     if (t)                              /* Caching hint for NT */
11626       _setmode(_fileno(t),O_SEQUENTIAL);
11627 #endif /* O_SEQUENTIAL */
11628 #endif /* NT */
11629     z_nopen++;                          /* Open, count it. */
11630     z_file[n]->z_fp = t;                /* Stash the file pointer */
11631     z_file[n]->z_flags = flags;         /* and the flags */
11632     z_file[n]->z_nline = 0;             /* Current line number is 0 */
11633     z_error = 0;
11634     zfnqfp(name,CKMAXPATH,z_file[n]->z_name); /* and the file's full name */
11635     return(n);                          /* Return the channel number */
11636 }
11637
11638 int
11639 z_close(channel) int channel; {         /* Close file on given channel */
11640     int x;
11641     FILE * t;
11642     if (!z_inited)                      /* Called before any files are open? */
11643       return(z_error = FX_NOP);
11644     if (channel >= z_maxchan)           /* Channel out of range? */
11645       return(z_error = FX_CHN);
11646     if (!z_file[channel])
11647       return(z_error = FX_NOP);
11648     if (!(t = z_file[channel]->z_fp))    /* Channel wasn't open? */
11649       return(z_error = FX_NOP);
11650     errno = 0;                          /* Set errno 0 to get a good reading */
11651     x = fclose(t);                      /* Try to close */
11652     if (x == EOF)                       /* On failure */
11653       return(z_error = FX_SYS);         /* indicate system error. */
11654     z_nopen--;                          /* Closed OK, decrement open count */
11655     z_file[channel]->z_fp = NULL;       /* Set file pointer to NULL */
11656     z_file[channel]->z_nline = 0;       /* Current line number is 0 */
11657     z_file[channel]->z_flags = 0;       /* Set flags to 0 */
11658     *(z_file[channel]->z_name) = '\0';  /* Clear name */
11659     free(z_file[channel]);
11660     z_file[channel] = NULL;
11661     return(z_error = 0);
11662 }
11663
11664 /*
11665   Z _ O U T  --  Output string to channel.
11666
11667   Call with:
11668     channel:     Channel number to write to.
11669     s:           String to write.
11670     length > -1: How many characters of s to write.
11671     length < 0:  Write entire NUL-terminated string.
11672     flags == 0:  Supply line termination.
11673     flags >  0:  Don't supply line termination.
11674     flags <  0:  Write 'length' NUL characters.
11675   Special case:
11676     If flags > -1 and s is empty or NULL and length == 1, write 1 NUL.
11677   Returns:
11678     Number of characters written to channel on success, or
11679     negative FX_xxx error code on failure.
11680 */
11681 int
11682 z_out(channel,s,length,flags) int channel, flags, length; char * s; {
11683     FILE * t;
11684     int x, n;
11685     char c = '\0';
11686
11687     if (!s) s = "";                     /* Guard against null pointer */
11688 #ifdef DEBUG
11689     if (deblog) {
11690         debug(F111,"z_out",s,channel);
11691         debug(F101,"z_out length","",length);
11692         debug(F101,"z_out flags","",flags);
11693     }
11694 #endif /* DEBUG */
11695     if (!z_inited)                      /* File i/o inited? */
11696       return(z_error = FX_NOP);
11697     if (channel >= z_maxchan)           /* Channel in range? */
11698       return(z_error = FX_CHN);
11699     if (!z_file[channel])
11700       return(z_error = FX_NOP);
11701     if (!(t = z_file[channel]->z_fp))    /* File open? */
11702       return(z_error = FX_NOP);
11703     if (!((z_file[channel]->z_flags) & (FM_WRI|FM_APP))) /* In write mode? */
11704       return(z_error = FX_FOP);
11705     n = length;                         /* Length of string to write */
11706     if (n < 0) {                        /* Negative means get it ourselves */
11707         if (flags < 0)                  /* Except when told to write NULs in */
11708           return(z_error = FX_RNG);     /* which case args are inconsistent */
11709         n = strlen(s);                  /* Get length of string arg */
11710     }
11711     errno = 0;                          /* Reset errno */
11712     debug(F101,"z_out n","",n);
11713     if (flags < 0) {                    /* Writing NULs... */
11714         int i;
11715         for (i = 0; i < n; i++) {
11716             x = fwrite(&c,1,1,t);
11717             if (x < 1)
11718               return(z_error = (errno ? FX_SYS : FX_UNK));
11719         }
11720         z_file[channel]->z_nline = -1;   /* Current line no longer known */
11721         z_error = 0;
11722         return(i);
11723     } else {                            /* Writing string arg */
11724         if (n == 1 && !s[0])            /* Writing one char but it's NUL */
11725           x = fwrite(&c,1,1,t);
11726         else                            /* Writing non-NUL char or string */
11727           x = fwrite(s,1,n,t);
11728         debug(F101,"z_out fwrite",ckitoa(x),errno);
11729         if (x < n)                      /* Failure to write requested amount */
11730           return(z_error = (errno ? FX_SYS : FX_UNK)); /* Return error */
11731         if (flags == 0) {               /* If supplying line termination */
11732             if (fwrite("\n",1,1,t))     /* do that  */
11733               x += z_lt;                /* count the terminator */
11734             if (z_file[channel]->z_nline > -1) /* count this line */
11735               z_file[channel]->z_nline++;
11736         } else {
11737             z_file[channel]->z_nline = -1; /* Current line no longer known */
11738         }
11739     }
11740     z_error = 0;
11741     return(x);
11742 }
11743
11744 #define Z_INBUFLEN 64
11745
11746 /*
11747   Z _ I N  --  Multichannel i/o file input function.
11748
11749   Call with:
11750     channel number to read from.
11751     s = address of destination buffer.
11752     buflen = destination buffer length.
11753     length = Number of bytes to read, must be < buflen.
11754     flags: 0 = read a line; nonzero = read the given number of bytes.
11755   Returns:
11756     Number of bytes read into buffer or a negative error code.
11757     A terminating NUL is deposited after the last byte that was read.
11758 */
11759 int
11760 z_in(channel,s,buflen,length,flags)
11761  int channel, buflen, length, flags; char * s;
11762 /* z_in */ {
11763     int i, j, x;
11764     FILE * t;
11765     char * p;
11766
11767     if (!z_inited)                      /* Check everything... */
11768       return(z_error = FX_NOP);
11769     if (channel >= z_maxchan)
11770       return(z_error = FX_CHN);
11771     if (!z_file[channel])
11772       return(z_error = FX_NOP);
11773     if (!(t = z_file[channel]->z_fp))
11774       return(z_error = FX_NOP);
11775     if (!((z_file[channel]->z_flags) & FM_REA))
11776       return(z_error = FX_FOP);
11777     if (!s)                             /* Check destination */
11778      return(z_error = FX_RNG);
11779     s[0] = NUL;
11780     if (length == 0)                    /* Read 0 bytes - easy. */
11781       return(z_error = 0);
11782     debug(F101,"z_in channel","",channel);
11783     debug(F101,"z_in buflen","",buflen);
11784     debug(F101,"z_in length","",length);
11785     debug(F101,"z_in flags","",flags);
11786     if (length < 0 || buflen < 0)       /* Check length args */
11787       return(z_error = FX_RNG);
11788     if (buflen <= length)
11789       return(z_error = FX_RNG);
11790     errno = 0;                          /* Reset errno */
11791     if (flags) {                        /* Read block or byte */
11792         int n;                          /* 20050912 */
11793         n = length;                     /* 20050912 */
11794         i = 0;                          /* 20050912 */
11795         while (n > 0) {                 /* 20050912 */
11796             i = fread(s,1,n,t);         /* 20050912 */
11797 #ifdef DEBUG
11798             if (deblog) {
11799                 debug(F111,"z_in block",s,i);
11800                 debug(F101,"z_in block errno","",errno);
11801                 debug(F101,"z_in block ferror","",ferror(t));
11802                 debug(F101,"z_in block feof","",feof(t));
11803             }
11804 #endif /* DEBUG */
11805             if (i == 0) break;          /* 20050912 */
11806             s += i;                     /* 20050912 */
11807             n -= i;                     /* 20050912 */
11808         }
11809         /* Current line no longer known */
11810         z_file[channel]->z_nline = (CK_OFF_T)-1;
11811     } else {                            /* Read line */
11812 #ifndef COMMENT
11813         /* This method is used because it's simpler than the others */
11814         /* and also marginally faster. */
11815         debug(F101,"z_in getc loop","",CKFTELL(t));
11816         for (i = 0; i < length; i++) {
11817             if ((x = getc(t)) == EOF) {
11818                 debug(F101,"z_in getc error","",CKFTELL(t));
11819                 s[i] = '\0';
11820                 break;
11821             }
11822             s[i] = x;
11823             if (s[i] == '\n') {
11824                 s[i] = '\0';
11825                 break;
11826             }
11827         }
11828         debug(F111,"z_in line byte loop",ckitoa(errno),i);
11829         debug(F111,"z_in line got",s,z_file[channel]->z_nline);
11830         if (z_file[channel]->z_nline > -1)
11831           z_file[channel]->z_nline++;
11832 #else
11833 #ifdef COMMENT2
11834         /* Straightforward but strlen() slows it down. */
11835         s[0] = '\0';
11836         i = 0;
11837         if (fgets(s,length,t)) {
11838             i = strlen(s);
11839             if (i > 0 && s[i-1] == '\n') i--;
11840         }
11841         debug(F111,"z_in line fgets",ckitoa(errno),i);
11842         if (z_file[channel]->z_nline > -1)
11843           z_file[channel]->z_nline++;
11844 #else
11845         /* This is a do-it-yourself fgets() with its own readahead and */
11846         /* putback.  It's a bit faster than real fgets() but not enough */
11847         /* to justify the added complexity or the risk of the ftell() and */
11848         /* fseek() calls failing. */
11849         int k, flag = 0;
11850         CK_OFF_T pos;
11851         for (i = 0; !flag && i <= (length - Z_INBUFLEN); i += Z_INBUFLEN) {
11852             k = ((length - i) < Z_INBUFLEN) ? length - i : Z_INBUFLEN;
11853             if ((x = fread(s+i,1,k,t)) < 1)
11854               break;
11855             s[i+x] = '\0';
11856             for (j = 0; j < x; j++) {
11857                 if (s[i+j] == '\n') {
11858                     s[i+j] = '\0';
11859                     flag ++;
11860                     pos = CKFTELL(t);
11861                     if (pos > -1) {
11862                         pos -= (x - j - 1);
11863                         x = CKFSEEK(t, pos, 0);
11864                         i += j;
11865                         break;
11866                     } else
11867                       return(z_error = FX_SYS);
11868                 }
11869             }
11870         }
11871         if (z_file[channel]->z_nline > -1)
11872           z_file[channel]->z_nline++;
11873         debug(F111,"z_in line chunk loop",ckitoa(errno),i);
11874 #endif /* COMMENT2 */
11875 #endif /* COMMENT */
11876     }
11877     debug(F111,"z_in i",ckitoa(errno),i);
11878     if (i < 0) i = 0;                   /* NUL-terminate result */
11879     s[i] = '\0';
11880     if (i > 0) {
11881         z_error = 0;
11882         return(i);
11883     }
11884     if (i == 0 && feof(t))              /* EOF on reading? */
11885       return(z_error = FX_EOF);         /* Return EOF code */
11886     return(errno ? (z_error = -1) : i); /* Return length or system error */
11887 }
11888
11889 int
11890 z_flush(channel) int channel; {         /* Flush output channel */
11891     FILE * t;
11892     int x;
11893     if (!z_inited)                      /* Regular checks */
11894       return(z_error = FX_NOP);
11895     if (channel >= z_maxchan)
11896       return(z_error = FX_CHN);
11897     if (!z_file[channel])
11898       return(z_error = FX_NOP);
11899     if (!(t = z_file[channel]->z_fp))
11900       return(z_error = FX_NOP);
11901     if (!((z_file[channel]->z_flags) & (FM_WRI|FM_APP))) /* Write access? */
11902       return(z_error = FX_FOP);
11903     errno = 0;                          /* Reset errno */
11904     x = fflush(t);                      /* Try to flush */
11905     return(x ? (z_error = FX_SYS) : 0); /* Return system error or 0 if OK */
11906 }
11907
11908 int
11909 #ifdef CK_ANSIC
11910 z_seek(int channel, CK_OFF_T pos)       /* Move file pointer to byte */
11911 #else
11912 z_seek(channel,pos) int channel; CK_OFF_T pos; /* (seek to given position) */
11913 #endif /* CK_ANSIC */
11914 {
11915     int i, x = 0, rc;
11916     FILE * t;
11917     if (!z_inited)                      /* Check... */
11918       return(z_error = FX_NOP);
11919     if (channel >= z_maxchan)
11920       return(z_error = FX_CHN);
11921     if (!z_file[channel])
11922       return(z_error = FX_NOP);
11923     if (!(t = z_file[channel]->z_fp))
11924       return(z_error = FX_NOP);
11925     if (pos < 0L) {
11926         x = 2;
11927         pos = (pos == -2) ? -1L : 0L;
11928     }
11929     errno = 0;
11930     rc = CKFSEEK(t,pos,x);              /* Try to seek */
11931     debug(F111,"z_seek",ckitoa(errno),rc);
11932     if (rc < 0)                         /* OK? */
11933       return(z_error = FX_SYS); /* No. */
11934     z_file[channel]->z_nline = ((pos || x) ? -1 : 0);
11935     return(z_error = 0);
11936 }
11937
11938 int
11939 #ifdef CK_ANSIC
11940 z_line(int channel, CK_OFF_T pos)           /* Move file pointer to line */
11941 #else
11942 z_line(channel,pos) int channel; CK_OFF_T pos; /* (seek to given position) */
11943 #endif /* CK_ANSIC */
11944 {
11945     int i, len, x = 0;
11946     CK_OFF_T current = (CK_OFF_T)0, prev = (CK_OFF_T)-1, old = (CK_OFF_T)-1;
11947     FILE * t;
11948     char tmpbuf[256];
11949     if (!z_inited)                      /* Check... */
11950       return(z_error = FX_NOP);
11951     if (channel >= z_maxchan)
11952       return(z_error = FX_CHN);
11953     if (!z_file[channel])
11954       return(z_error = FX_NOP);
11955     if (!(t = z_file[channel]->z_fp))
11956       return(z_error = FX_NOP);
11957     debug(F101,"z_line pos","",pos);
11958     if (pos < 0L) {                     /* EOF wanted */
11959         CK_OFF_T n;
11960         n = z_file[channel]->z_nline;
11961         debug(F101,"z_line n","",n);
11962         if (n < 0 || pos < 0) {
11963             rewind(t);
11964             n = 0;
11965         }
11966         while (1) {                     /* This could take a while... */
11967             if ((x = getc(t)) == EOF)
11968               break;
11969             if (x == '\n') {
11970                 n++;
11971                 if (pos == -2) {
11972                     old = prev;
11973                     prev = CKFTELL(t);
11974                 }
11975             }
11976         }
11977         debug(F101,"z_line old","",old);
11978         debug(F101,"z_line prev","",prev);
11979         if (pos == -2) {
11980             if ((x = z_seek(channel,old)) < 0)
11981               return(z_error = x);
11982             else
11983               n--;
11984         }
11985         z_file[channel]->z_nline = n;
11986         return(z_error = 0);
11987     }
11988     if (pos == 0L) {                    /* Rewind wanted */
11989         z_file[channel]->z_nline = 0L;
11990         rewind(t);
11991         debug(F100,"z_line rewind","",0);
11992         return(0L);
11993     }
11994     tmpbuf[255] = NUL;                  /* Make sure buf is NUL terminated */
11995     current = z_file[channel]->z_nline;  /* Current line */
11996     /*
11997       If necessary the following could be optimized, e.g. for positioning
11998       to a previous line in a large file without starting over.
11999     */
12000     if (current < 0 || pos < current) { /* Not known or behind us... */
12001         debug(F101,"z_line rewinding","",pos);
12002         if ((x = z_seek(channel, 0L)) < 0) /* Rewind */
12003           return(z_error = x);
12004         if (pos == 0)                   /* If 0th line wanted we're done */
12005           return(z_error = 0);
12006         current = 0;
12007     }
12008     while (current < pos) {             /* Search for specified line */
12009         if (fgets(tmpbuf,255,t)) {
12010             len = strlen(tmpbuf);
12011             if (len > 0 && tmpbuf[len-1] == '\n') {
12012                 current++;
12013                 debug(F111,"z_line read",ckitoa(len),current);
12014             } else if (len == 0) {
12015                 return(z_error = FX_UNK);
12016             }
12017         } else {
12018             z_file[channel]->z_nline = -1L;
12019             debug(F101,"z_line premature EOF","",current);
12020             return(z_error = FX_EOF);
12021         }
12022     }
12023     z_file[channel]->z_nline = current;
12024     debug(F101,"z_line result","",current);
12025     z_error = 0;
12026     return(current);
12027 }
12028
12029 char *
12030 z_getname(channel) int channel; {       /* Return name of file on channel */
12031     FILE * t;
12032     if (!z_inited) {
12033         z_error = FX_NOP;
12034         return(NULL);
12035     }
12036     if (channel >= z_maxchan) {
12037         z_error = FX_CHN;
12038         return(NULL);
12039     }
12040     if (!z_file[channel]) {
12041         z_error = FX_NOP;
12042         return(NULL);
12043     }
12044     if (!(t = z_file[channel]->z_fp)) {
12045         z_error = FX_NOP;
12046         return(NULL);
12047     }
12048     return((char *)(z_file[channel]->z_name));
12049 }
12050
12051 int
12052 z_getmode(channel) int channel; {       /* Return OPEN modes of channel */
12053     FILE * t;                           /* 0 if file not open */
12054 #ifndef NOSTAT
12055 #ifdef NT
12056     struct _stat statbuf;
12057 #else /* NT */
12058     struct stat statbuf;
12059 #endif /* NT */
12060 #endif /* NOSTAT */
12061     int x;
12062     if (!z_inited)
12063       return(0);
12064     if (channel >= z_maxchan)
12065       return(z_error = FX_CHN);
12066     if (!z_file[channel])
12067       return(0);
12068     if (!(t = z_file[channel]->z_fp))
12069       return(0);
12070     x = z_file[channel]->z_flags;
12071     if (feof(t)) {                      /* This might not work for */
12072         x |= FM_EOF;                    /* output files */
12073 #ifndef NOSTAT
12074     /* But this does if we can use it. */
12075     } else if (stat(z_file[channel]->z_name,&statbuf) > -1) {
12076         if (CKFTELL(t) == statbuf.st_size)
12077           x |= FM_EOF;
12078 #endif /* NOSTAT */
12079     }
12080     return(x);
12081 }
12082
12083 CK_OFF_T
12084 z_getpos(channel) int channel; {        /* Get file pointer position */
12085     FILE * t;                           /* on this channel */
12086     CK_OFF_T x;
12087     if (!z_inited)
12088       return(z_error = FX_NOP);
12089     if (channel >= z_maxchan)
12090       return(z_error = FX_CHN);
12091     if (!z_file[channel])
12092       return(z_error = FX_NOP);
12093     if (!(t = z_file[channel]->z_fp))
12094       return(z_error = FX_NOP);
12095     x = CKFTELL(t);
12096     return((x < 0L) ? (z_error = FX_SYS) : x);
12097 }
12098
12099 CK_OFF_T
12100 z_getline(channel) int channel; {       /* Get current line number */
12101     FILE * t;                           /* in file on this channel */
12102     CK_OFF_T rc;
12103     if (!z_inited)
12104       return(z_error = FX_NOP);
12105     if (channel >= z_maxchan)
12106       return(z_error = FX_CHN);
12107     if (!z_file[channel])
12108       return(z_error = FX_NOP);
12109     if (!(t = z_file[channel]->z_fp))
12110       return(z_error = FX_NOP);
12111     debug(F101,"z_getline","",z_file[channel]->z_nline);
12112     rc = z_file[channel]->z_nline;
12113     return((rc < 0) ? (z_error = FX_LNU) : rc);
12114 }
12115
12116 int
12117 z_getfnum(channel) int channel; {       /* Get file number / handle */
12118     FILE * t;                           /* for file on this channel */
12119     if (!z_inited)
12120       return(z_error = FX_NOP);
12121     if (channel >= z_maxchan)
12122       return(z_error = FX_CHN);
12123     if (!z_file[channel])
12124       return(z_error = FX_NOP);
12125     if (!(t = z_file[channel]->z_fp))
12126       return(z_error = FX_NOP);
12127     z_error = 0;
12128     return(fileno(t));
12129 }
12130
12131 /*
12132   Line-oriented counts and seeks are as dumb as they can be at the moment.
12133   Later we can speed them up by building little indexes.
12134 */
12135 CK_OFF_T
12136 z_count(channel, what) int channel, what; { /* Count bytes or lines in file */
12137     FILE * t;
12138     int i, x;
12139     CK_OFF_T pos, count = (CK_OFF_T)0;
12140     if (!z_inited)                      /* Check stuff... */
12141       return(z_error = FX_NOP);
12142     if (channel >= z_maxchan)
12143       return(z_error = FX_CHN);
12144     if (!z_file[channel])
12145       return(z_error = FX_NOP);
12146     if (!(t = z_file[channel]->z_fp))
12147       return(z_error = FX_NOP);
12148     pos = CKFTELL(t);                   /* Save current file pointer */
12149     errno = 0;
12150     z_error = 0;
12151     if (what == RD_CHAR) {              /* Size in bytes requested */
12152 #ifdef COMMENT
12153         if (!CKFSEEK(t,0L,2)) {         /* Seek to end */
12154             count = CKFTELL(t);         /* Get file pointer */
12155             CKFSEEK(t,pos,0);           /* Restore file file pointer */
12156             return(count);
12157         } else                          /* Fallback in case seek fails */
12158 #endif  /* COMMENT */
12159           return(zgetfs(z_file[channel]->z_name));
12160     }
12161     rewind(t);                          /* Line count requested - rewind. */
12162     while (1) {                         /* Count lines. */
12163         if ((x = getc(t)) == EOF)       /* Stupid byte loop */
12164           break;                        /* but it works as well as anything */
12165         if (x == '\n')                  /* else... */
12166           count++;
12167     }
12168     x = CKFSEEK(t,pos,0);               /* Restore file pointer */
12169     return(count);
12170 }
12171
12172 /* User interface for generalized channel-oriented file i/o */
12173
12174 struct keytab fctab[] = {               /* FILE subcommands */
12175     { "close",      FIL_CLS, 0 },
12176     { "count",      FIL_COU, 0 },
12177     { "flush",      FIL_FLU, 0 },
12178     { "list",       FIL_LIS, 0 },
12179     { "open",       FIL_OPN, 0 },
12180     { "read",       FIL_REA, 0 },
12181     { "rewind",     FIL_REW, 0 },
12182     { "seek",       FIL_SEE, 0 },
12183     { "status",     FIL_STA, 0 },
12184     { "write",      FIL_WRI, 0 }
12185 };
12186 int nfctab = (sizeof (fctab) / sizeof (struct keytab));
12187
12188 static struct keytab fcswtab[] = {      /* OPEN modes */
12189     { "/append",    FM_APP,  0 },
12190     { "/binary",    FM_BIN,  0 },
12191 #ifdef COMMENT
12192     { "/command",   FM_CMD,  0 },       /* Not implemented */
12193 #endif /* COMMENT */
12194     { "/read",      FM_REA,  0 },
12195     { "/write",     FM_WRI,  0 }
12196 };
12197 static int nfcswtab = (sizeof (fcswtab) / sizeof (struct keytab));
12198
12199 static struct keytab fclkwtab[] = {     /* CLOSE options */
12200     { "all",        1,       0 }
12201 };
12202
12203 static struct keytab fsekwtab[] = {     /* SEEK symbols */
12204     { "eof",        1,       0 },
12205     { "last",       2,       0 }
12206 };
12207 static int nfsekwtab = (sizeof (fsekwtab) / sizeof (struct keytab));
12208
12209 #define SEE_LINE  RD_LINE               /* SEEK options */
12210 #define SEE_CHAR  RD_CHAR
12211 #define SEE_REL   3
12212 #define SEE_ABS   4
12213 #define SEE_FIND  5
12214
12215 static struct keytab fskswtab[] = {
12216     { "/absolute",  SEE_ABS,  0 },
12217     { "/byte",      SEE_CHAR, 0 },
12218     { "/character", SEE_CHAR, CM_INV },
12219     { "/find",      SEE_FIND, CM_ARG },
12220     { "/line",      SEE_LINE, 0 },
12221     { "/relative",  SEE_REL,  0 }
12222 };
12223 static int nfskswtab = (sizeof (fskswtab) / sizeof (struct keytab));
12224
12225 #define COU_LINE  RD_LINE               /* COUNT options */
12226 #define COU_CHAR  RD_CHAR
12227 #define COU_LIS   3
12228 #define COU_NOL   4
12229
12230 static struct keytab fcoswtab[] = {
12231     { "/bytes",     COU_CHAR, 0      },
12232     { "/characters",COU_CHAR, CM_INV },
12233     { "/lines",     COU_LINE, 0      },
12234     { "/list",      COU_LIS,  0      },
12235     { "/nolist",    COU_NOL,  0      },
12236     { "/quiet",     COU_NOL,  CM_INV }
12237 };
12238 static int nfcoswtab = (sizeof (fcoswtab) / sizeof (struct keytab));
12239
12240 static struct keytab frdtab[] = {       /* READ types */
12241     { "/block",     RD_SIZE, CM_INV|CM_ARG },
12242     { "/byte",      RD_CHAR, CM_INV },
12243     { "/character", RD_CHAR, 0      },
12244     { "/line",      RD_LINE, 0      },
12245     { "/size",      RD_SIZE, CM_ARG },
12246     { "/trim",      RD_TRIM, 0      },
12247     { "/untabify",  RD_UNTA, 0      }
12248 };
12249 static int nfrdtab = (sizeof (frdtab) / sizeof (struct keytab));
12250
12251 static struct keytab fwrtab[] = {       /* WRITE types */
12252     { "/block",     WR_SIZE, CM_INV|CM_ARG },
12253     { "/byte",      WR_CHAR, CM_INV },
12254     { "/character", WR_CHAR, 0      },
12255     { "/line",      WR_LINE, 0      },
12256     { "/lpad",      WR_LPAD, CM_ARG },
12257     { "/rpad",      WR_RPAD, CM_ARG },
12258     { "/size",      WR_SIZE, CM_ARG },
12259     { "/string",    WR_STRI, 0      }
12260 };
12261 static int nfwrtab = (sizeof (fwrtab) / sizeof (struct keytab));
12262
12263 static char blanks[] = "\040\040\040\040"; /* Some blanks for formatting */
12264 static char * seek_target = NULL;
12265
12266 int
12267 dofile(op) int op; {                    /* Do the FILE command */
12268     char vnambuf[VNAML];                /* Buffer for variable names */
12269     char *vnp = NULL;                   /* Pointer to same */
12270     char zfilnam[CKMAXPATH+2];
12271     char * p, * m;
12272     struct FDB fl, sw, nu;
12273     CK_OFF_T z;
12274     int rsize, filmode = 0, relative = -1, eofflg = 0;
12275     int rc, x, y, cx, n, getval, dummy, confirmed, listing = -1;
12276     int charflag = 0, sizeflag = 0;
12277     int pad = 32, wr_lpad = 0, wr_rpad = 0, rd_trim = 0, rd_untab = 0;
12278
12279     makestr(&seek_target,NULL);
12280
12281     if (op == XXFILE) {                 /* FILE command was given */
12282         /* Get subcommand */
12283         if ((cx = cmkey(fctab,nfctab,"Operation","",xxstring)) < 0) {
12284             if (cx == -3) {
12285                 printf("?File operation required\n");
12286                 x = -9;
12287             }
12288             return(cx);
12289         }
12290     } else {                            /* Shorthand command was given */
12291         switch (op) {
12292           case XXF_CL: cx = FIL_CLS; break; /* FCLOSE */
12293           case XXF_FL: cx = FIL_FLU; break; /* FFLUSH */
12294           case XXF_LI: cx = FIL_LIS; break; /* FLIST */
12295           case XXF_OP: cx = FIL_OPN; break; /* etc... */
12296           case XXF_RE: cx = FIL_REA; break;
12297           case XXF_RW: cx = FIL_REW; break;
12298           case XXF_SE: cx = FIL_SEE; break;
12299           case XXF_ST: cx = FIL_STA; break;
12300           case XXF_WR: cx = FIL_WRI; break;
12301           case XXF_CO: cx = FIL_COU; break;
12302           default: return(-2);
12303         }
12304     }
12305     switch (cx) {                       /* Do requested subcommand */
12306       case FIL_OPN:                     /* OPEN */
12307         cmfdbi(&sw,                     /* Switches */
12308                _CMKEY,                  /* fcode */
12309                "Variable or switch",    /* hlpmsg */
12310                "",                      /* default */
12311                "",                      /* addtl string data */
12312                nfcswtab,                /* addtl numeric data 1: tbl size */
12313                4,                       /* addtl numeric data 2: 4 = cmswi */
12314                xxstring,                /* Processing function */
12315                fcswtab,                 /* Keyword table */
12316                &fl                      /* Pointer to next FDB */
12317                );
12318         cmfdbi(&fl,                     /* Anything that doesn't match */
12319                _CMFLD,                  /* fcode */
12320                "Variable",              /* hlpmsg */
12321                "",
12322                "",
12323                0,
12324                0,
12325                NULL,
12326                NULL,
12327                NULL
12328                );
12329         while (1) {
12330             x = cmfdb(&sw);             /* Parse something */
12331             if (x < 0) {
12332                 if (x == -3) {
12333                     printf("?Variable name and file name required\n");
12334                     x = -9;
12335                 }
12336                 return(x);
12337             }
12338             if (cmresult.fcode == _CMFLD)
12339               break;
12340             else if (cmresult.fcode == _CMKEY) {
12341                 char c;
12342                 c = cmgbrk();
12343                 if ((getval =
12344                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12345                     printf("?This switch does not take an argument\n");
12346                     return(-9);
12347                 }
12348 #ifdef COMMENT
12349                 /* Uncomment if we add any switches here that take args */
12350                 if (!getval && (cmgkwflgs() & CM_ARG)) {
12351                     printf("?This switch requires an argument\n");
12352                     return(-9);         /* (none do...) */
12353                 }
12354 #endif /* COMMENT */
12355                 filmode |= cmresult.nresult; /* OR in the file mode */
12356             } else
12357               return(-2);
12358         }
12359         /* Not a switch - get the string */
12360         ckstrncpy(vnambuf,cmresult.sresult,VNAML);
12361         if (!vnambuf[0] || chknum(vnambuf)) { /* (if there is one...) */
12362             printf("?Variable name required\n");
12363             return(-9);
12364         }
12365         vnp = vnambuf;                  /* Check variable-name syntax */
12366         if (vnambuf[0] == CMDQ &&
12367             (vnambuf[1] == '%' || vnambuf[1] == '&'))
12368           vnp++;
12369         y = 0;
12370         if (*vnp == '%' || *vnp == '&') {
12371             if ((y = parsevar(vnp,&x,&dummy)) < 0) {
12372                 printf("?Syntax error in variable name\n");
12373                 return(-9);
12374             }
12375         }
12376         /* Assign a negative channel number in case we fail */
12377         addmac(vnambuf,"-1");
12378
12379         if (!(filmode & FM_RWA))        /* If no access mode specified */
12380           filmode |= FM_REA;            /* default to /READ. */
12381
12382         y = 0;                          /* Now parse the filename */
12383         if ((filmode & FM_RWA) == FM_WRI) {
12384             x = cmofi("Name of new file","",&s,xxstring);
12385         } else if ((filmode & FM_RWA) == FM_REA) {
12386             x = cmifi("Name of existing file","",&s,&y,xxstring);
12387         } else {
12388             x = cmiofi("Filename","",&s,&y,xxstring);
12389             debug(F111,"fopen /append x",s,x);
12390         }
12391         if (x < 0) {
12392             if (x == -3) {
12393                 printf("?Filename required\n");
12394                 x = -9;
12395             }
12396             return(x);
12397         }
12398         if (y) {                        /* No wildcards */
12399             printf("?Wildcards not allowed here\n");
12400             return(-9);
12401         }
12402         if (filmode & (FM_APP|FM_WRI)) { /* Check output access */
12403 #ifndef VMS
12404             if (zchko(s) < 0) {          /* and set error code if denied */
12405                 z_error = FX_ACC;
12406                 printf("?Write access denied - \"%s\"\n",s);
12407                 return(-9);
12408             }
12409 #endif /* VMS */
12410         }
12411         ckstrncpy(zfilnam,s,CKMAXPATH); /* Is OK - make safe copy */
12412         if ((x = cmcfm()) < 0)          /* Get confirmation of command */
12413           return(x);
12414         if ((n = z_open(zfilnam,filmode)) < 0) {
12415             printf("?OPEN failed - %s: %s\n",zfilnam,ckferror(n));
12416             return(-9);
12417         }
12418         addmac(vnambuf,ckitoa(n));      /* Assign channel number to variable */
12419         return(success = 1);
12420
12421       case FIL_REW:                     /* REWIND */
12422         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
12423             if (x == -3) {
12424                 printf("?Channel number required\n");
12425                 x = -9;
12426             }
12427             return(x);
12428         }
12429         if ((x = cmcfm()) < 0)
12430           return(x);
12431         if (n == -9) return(success = 0);
12432         if (n == -8) return(success = 1);
12433
12434         if ((rc = z_seek(n,0L)) < 0) {
12435             printf("?REWIND failed - Channel %d: %s\n",n,ckferror(rc));
12436             return(-9);
12437         }
12438         return(success = 1);
12439
12440       case FIL_CLS:                     /* CLOSE */
12441 #ifdef COMMENT                          /* fdc 20100804 - bad idea */
12442          {
12443             int i, j, k;                /* Supply default if only one open */
12444             s = "";
12445             for (k = 0, j = 0, i = 0; i < z_maxchan; i++) {
12446                 if (z_file)
12447                   if (z_file[i])
12448                     if (z_file[i]->z_fp) { k++; j = i; }
12449             }
12450             if (k == 1) s = ckitoa(j);
12451          }
12452 #endif  /* COMMENT */
12453           cmfdbi(&nu,                   /* Second FDB - channel number */
12454                  _CMNUM,                /* fcode */
12455                  "Channel number or ALL", /* Help message */
12456                  s,                     /* default */
12457                  "",                    /* addtl string data */
12458                  10,                    /* addtl numeric data 1: radix */
12459                  0,                     /* addtl numeric data 2: 0 */
12460                  xxstring,              /* Processing function */
12461                  NULL,                  /* Keyword table */
12462                  &sw                    /* Pointer to next FDB */
12463                  );                     /* Pointer to next FDB */
12464          cmfdbi(&sw,                    /* First FDB - command switches */
12465                  _CMKEY,                /* fcode */
12466                  "",                    /* help message */
12467                  "",                    /* Default */
12468                  "",                    /* No addtl string data */
12469                  1,                     /* addtl numeric data 1: tbl size */
12470                  0,                     /* addtl numeric data 2: 4 = cmswi */
12471                  xxstring,              /* Processing function */
12472                  fclkwtab,              /* Keyword table */
12473                  NULL                   /* Last in chain */
12474                  );
12475         x = cmfdb(&nu);                 /* Parse something */
12476         if (x < 0) {
12477             if (x == -3) {
12478                 printf("?Channel number or ALL required\n");
12479                 x = -9;
12480             }
12481             return(x);
12482         }
12483         if (cmresult.fcode == _CMNUM)
12484           n = cmresult.nresult;
12485         else if (cmresult.fcode == _CMKEY)
12486           n = -1;
12487         if ((x = cmcfm()) < 0)
12488           return(x);
12489         if (n == -9) return(success = 0);
12490         if (n == -8) return(success = 1);
12491
12492         rc = 1;
12493         if (n < 0) {
12494             int count = 0;
12495             int i;
12496             for (i = 0; i < z_maxchan; i++) {
12497                 x = z_close(i);
12498                 if (x == FX_SYS) {
12499                     printf("?CLOSE failed - Channel %d: %s\n",n,ckferror(x));
12500                     rc = 0;
12501                 } else if (x > -1)
12502                   count++;
12503             }
12504             debug(F101,"FILE CLOSE ALL","",count);
12505         } else if ((x = z_close(n)) < 0) {
12506             printf("?CLOSE failed - Channel %d: %s\n",n,ckferror(x));
12507             return(-9);
12508         }
12509         return(success = rc);
12510
12511       case FIL_REA:                     /* READ */
12512       case FIL_WRI:                     /* WRITE */
12513         rsize = 0;
12514         cmfdbi(&sw,                     /* Switches */
12515                _CMKEY,                  /* fcode */
12516                "Channel or switch",     /* hlpmsg */
12517                "",                      /* default */
12518                "",                      /* addtl string data */
12519                (cx == FIL_REA) ? nfrdtab : nfwrtab,
12520                4,                       /* addtl numeric data 2: 4 = cmswi */
12521                xxstring,                /* Processing function */
12522                (cx == FIL_REA) ? frdtab : fwrtab, /* Keyword table */
12523                &nu                      /* Pointer to next FDB */
12524                );
12525         cmfdbi(&nu,                     /* Channel number */
12526                _CMNUM,                  /* fcode */
12527                "Channel",
12528                "",                      /* default */
12529                "",                      /* addtl string data */
12530                10,                      /* addtl numeric data 1: radix */
12531                0,                       /* addtl numeric data 2: 0 */
12532                xxstring,                /* Processing function */
12533                NULL,                    /* Keyword table */
12534                NULL                     /* Pointer to next FDB */
12535                );
12536         do {
12537             x = cmfdb(&sw);             /* Parse something */
12538             if (x < 0) {
12539                 if (x == -3) {
12540                     printf("?Channel number required\n");
12541                     x = -9;
12542                 }
12543                 return(x);
12544             }
12545             if (cmresult.fcode == _CMNUM) /* Channel number */
12546               break;
12547             else if (cmresult.fcode == _CMKEY) { /* Switch */
12548                 char c;
12549                 c = cmgbrk();
12550                 if ((getval =
12551                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12552                     printf("?This switch does not take an argument\n");
12553                     return(-9);
12554                 }
12555                 if (!getval && (cmgkwflgs() & CM_ARG)) {
12556                     printf("?This switch requires an argument\n");
12557                     return(-9);
12558                 }
12559                 switch (cmresult.nresult) {
12560                   case WR_LINE:
12561                     charflag = 0;
12562                     sizeflag = 0;
12563                     rsize = 0;
12564                     break;
12565                   case WR_CHAR:
12566                     rsize = 1;
12567                     charflag = 1;
12568                     sizeflag = 1;
12569                     break;
12570                   case WR_SIZE:
12571                     if ((x = cmnum("Bytes","",10,&rsize, xxstring)) < 0) {
12572                         if (x == -3) {
12573                             printf("?Number required\n");
12574                             x = -9;
12575                         }
12576                         return(x);
12577                     }
12578                     if (rsize > LINBUFSIZ) {
12579                         printf("?Maximum FREAD/FWRITE size is %d\n",LINBUFSIZ);
12580                         rsize = 0;
12581                         return(-9);
12582                     }
12583                     charflag = 0;
12584                     sizeflag = 1;
12585                     break;
12586                   case WR_STRI:
12587                     rsize = 1;
12588                     charflag = 0;
12589                     sizeflag = 0;
12590                     break;
12591                   case WR_LPAD:
12592                   case WR_RPAD:
12593                     if ((x = cmnum("Numeric ASCII character value",
12594                                    "32",10,&pad, xxstring)) < 0)
12595                       return(x);
12596                     if (cmresult.nresult == WR_LPAD)
12597                       wr_lpad = 1;
12598                     else
12599                       wr_rpad = 1;
12600                     break;
12601                   case RD_TRIM:
12602                     rd_trim = 1;
12603                     break;
12604                   case RD_UNTA:
12605                     rd_untab = 1;
12606                     break;
12607                 }
12608                 debug(F101,"FILE READ rsize 2","",rsize);
12609             } else
12610               return(-2);
12611         } while
12612           (cmresult.fcode == _CMKEY);
12613
12614         n = cmresult.nresult;           /* Channel */
12615         debug(F101,"FILE READ/WRITE channel","",n);
12616
12617         if (cx == FIL_WRI) {            /* WRITE */
12618             int len = 0;
12619             if ((x = cmtxt("Text","",&s,xxstring)) < 0)
12620               return(x);
12621             if (n == -9) return(success = 0);
12622             if (n == -8) return(success = 1);
12623
12624             ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy */
12625             s = line;
12626             s = brstrip(s);             /* Strip braces */
12627             if (charflag) {             /* Write one char */
12628                 len = 1;                /* So length = 1 */
12629                 rsize = 1;              /* Don't supply terminator */
12630             } else if (!sizeflag) {     /* Write a string */
12631                 len = -1;               /* So length is unspecified */
12632             } else {                    /* Write a block of given size */
12633                 int i, k, xx;
12634                 if (rsize > TMPBUFSIZ) {
12635                     z_error = FX_OFL;
12636                     printf("?Buffer overflow\n");
12637                     return(-9);
12638                 }
12639                 len = rsize;            /* rsize is really length */
12640                 rsize = 1;              /* Don't supply a terminator */
12641                 xx = strlen(s);         /* Size of given string */
12642                 if (xx >= len) {        /* Bigger or equal */
12643                     s[len] = NUL;
12644                 } else if (wr_lpad) {   /* Smaller, left-padding requested */
12645                     for (i = 0; i < len - xx; i++) /* Must make a copy */
12646                       tmpbuf[i] = pad;
12647                     ckstrncpy(tmpbuf+i,s,TMPBUFSIZ-i);
12648                     tmpbuf[len] = NUL;
12649                     s = tmpbuf;         /* Redirect write source */
12650                 } else if (wr_rpad) {   /* Smaller with right-padding */
12651                     for (i = xx; i < len; i++)
12652                       s[i] = pad;
12653                     s[len] = NUL;
12654                 }
12655             }
12656             if ((rc = z_out(n,s,len,rsize)) < 0) { /* Try to write */
12657                 printf("?Channel %d WRITE error: %s\n",n,ckferror(rc));
12658                 return(-9);
12659             }
12660         } else {                        /* FIL_REA READ */
12661             confirmed = 0;
12662             vnambuf[0] = NUL;
12663             x = cmfld("Variable name","",&s,NULL);
12664             debug(F111,"FILE READ cmfld",s,x);
12665             if (x < 0) {
12666                 if (x == -3 || !*s) {
12667                     if ((x = cmcfm()) < 0)
12668                       return(x);
12669                     else
12670                       confirmed++;
12671                 } else
12672                   return(x);
12673             }
12674             ckstrncpy(vnambuf,s,VNAML);
12675             debug(F111,"FILE READ vnambuf",vnambuf,confirmed);
12676             if (vnambuf[0]) {           /* Variable name given, check it */
12677                 if (!confirmed) {
12678                     x = cmcfm();
12679                     if (x < 0)
12680                       return(x);
12681                     else
12682                       confirmed++;
12683                 }
12684                 vnp = vnambuf;
12685                 if (vnambuf[0] == CMDQ &&
12686                     (vnambuf[1] == '%' || vnambuf[1] == '&'))
12687                   vnp++;
12688                 y = 0;
12689                 if (*vnp == '%' || *vnp == '&') {
12690                     if ((y = parsevar(vnp,&x,&dummy)) < 0) {
12691                         printf("?Syntax error in variable name\n");
12692                         return(-9);
12693                     }
12694                 }
12695             }
12696             debug(F111,"FILE READ variable",vnambuf,confirmed);
12697
12698             if (!confirmed)
12699               if ((x = cmcfm()) < 0)
12700                 return(x);
12701
12702             if (n == -9) return(success = 0);
12703             if (n == -8) return(success = 1);
12704
12705             line[0] = NUL;              /* Clear destination buffer */
12706 #ifdef COMMENT
12707             if (rsize >= LINBUFSIZ)     /* Don't overrun it */
12708               rsize = LINBUFSIZ - 1;
12709 #endif  /* COMMENT */
12710
12711             if (rsize == 0) {           /* Read a line */
12712                 rc = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
12713             } else {
12714                 rc = z_in(n,line,LINBUFSIZ,rsize,1); /* Read a block */
12715             }
12716             if (rc < 0) {               /* Error... */
12717                 debug(F101,"FILE READ error","",rc);
12718                 debug(F101,"FILE READ errno","",errno);
12719                 if (rc == FX_EOF) {     /* EOF - fail but no error message */
12720                     return(success = 0);
12721                 } else {                /* Other error - fail and print msg */
12722                     printf("?READ error: %s\n",ckferror(rc));
12723                     return(-9);
12724                 }
12725             }
12726             if (rsize == 0) {           /* FREAD /LINE postprocessing */
12727                 if (rd_trim) {          /* Trim */
12728                     int i, k;
12729                     k = strlen(line);
12730                     if (k > 0) {
12731                         for (i = k-1; i > 0; i--) {
12732                             if (line[i] == SP || line[i] == '\t')
12733                               line[i] = NUL;
12734                             else
12735                               break;
12736                         }
12737                     }
12738                 }
12739                 if (rd_untab) {         /* Untabify */
12740                     if (untabify(line,tmpbuf,TMPBUFSIZ) > -1)
12741                       ckstrncpy(line,tmpbuf,LINBUFSIZ);
12742                 }
12743             }
12744             debug(F110,"FILE READ data",line,0);
12745             if (vnambuf[0])             /* Read OK - If variable name given */
12746               addmac(vnambuf,line);     /* Assign result to variable */
12747             else                        /* otherwise */
12748               printf("%s\n",line);      /* just print it */
12749         }
12750         return(success = 1);
12751
12752       case FIL_SEE:                     /* SEEK */
12753       case FIL_COU:                     /* COUNT */
12754         rsize = RD_CHAR;                /* Defaults to /BYTE */
12755         cmfdbi(&sw,                     /* Switches */
12756                _CMKEY,                  /* fcode */
12757                "Channel or switch",     /* hlpmsg */
12758                "",                      /* default */
12759                "",                      /* addtl string data */
12760                ((cx == FIL_SEE) ? nfskswtab : nfcoswtab),
12761                4,                       /* addtl numeric data 2: 4 = cmswi */
12762                xxstring,                /* Processing function */
12763                ((cx == FIL_SEE) ? fskswtab : fcoswtab),
12764                &nu                      /* Pointer to next FDB */
12765                );
12766         cmfdbi(&nu,                     /* Channel number */
12767                _CMNUM,                  /* fcode */
12768                "Channel",
12769                "",                      /* default */
12770                "",                      /* addtl string data */
12771                10,                      /* addtl numeric data 1: radix */
12772                0,                       /* addtl numeric data 2: 0 */
12773                xxstring,                /* Processing function */
12774                NULL,                    /* Keyword table */
12775                NULL                     /* Pointer to next FDB */
12776                );
12777         do {
12778             x = cmfdb(&sw);             /* Parse something */
12779             if (x < 0) {
12780                 if (x == -3) {
12781                     printf("?Channel number required\n");
12782                     x = -9;
12783                 }
12784                 return(x);
12785             }
12786             if (cmresult.fcode == _CMNUM) /* Channel number */
12787               break;
12788             else if (cmresult.fcode == _CMKEY) { /* Switch */
12789                 char c;
12790                 c = cmgbrk();
12791                 if ((getval =
12792                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12793                     printf("?This switch does not take an argument\n");
12794                     return(-9);
12795                 }
12796                 if (cx == FIL_SEE) {
12797                     switch (cmresult.nresult) {
12798                       case SEE_REL: relative = 1; break;
12799                       case SEE_ABS: relative = 0; break;
12800                       case SEE_FIND: {
12801                           if (getval) {
12802                               y = cmfld("string or pattern","",&s,xxstring);
12803                               if (y < 0)
12804                                 return(y);
12805                               makestr(&seek_target,brstrip(s));
12806                               break;
12807                           }
12808                       }
12809                       default: rsize = cmresult.nresult;
12810                     }
12811                 } else if (cx == FIL_COU) {
12812                     switch (cmresult.nresult) {
12813                       case COU_LIS: listing = 1; break;
12814                       case COU_NOL: listing = 0; break;
12815                       default: rsize = cmresult.nresult;
12816                     }
12817                 }
12818             }
12819         } while
12820           (cmresult.fcode == _CMKEY);
12821
12822         n = cmresult.nresult;           /* Channel */
12823         debug(F101,"FILE SEEK/COUNT channel","",n);
12824         if (cx == FIL_COU) {
12825             if ((x = cmcfm()) < 0)
12826               return(x);
12827             if (n == -9) return(success = 0);
12828             if (n == -8) return(success = 1);
12829
12830             z_filcount = z_count(n,rsize);
12831             if (z_filcount < 0) {
12832                 rc = z_filcount;
12833                 printf("?COUNT error: %s\n",ckferror(rc));
12834                 return(-9);
12835             }
12836             if (listing < 0)
12837               listing = !xcmdsrc;
12838             if (listing)
12839               printf(" %ld %s%s\n",
12840                      z_filcount,
12841                      ((rsize == RD_CHAR) ? "byte" : "line"),
12842                      ((z_filcount == 1L) ? "" : "s")
12843                      );
12844             return(success = (z_filcount > -1) ? 1 : 0);
12845         }
12846         m = (rsize == RD_CHAR) ?
12847             "Number of bytes;\n or keyword" :
12848             "Number of lines;\n or keyword";
12849         cmfdbi(&sw,                     /* SEEK symbolic targets (EOF) */
12850                _CMKEY,                  /* fcode */
12851                m,
12852                "",
12853                "",                      /* addtl string data */
12854                nfsekwtab,               /* addtl numeric data 1: table size */
12855                0,                       /* addtl numeric data 2: 4 = cmswi */
12856                xxstring,                /* Processing function */
12857                fsekwtab,                /* Keyword table */
12858                &nu                      /* Pointer to next FDB */
12859                );
12860         cmfdbi(&nu,                     /* Byte or line number */
12861                _CMNUW,                  /* fcode */
12862                "",
12863                "",                      /* default */
12864                "",                      /* addtl string data */
12865                10,                      /* addtl numeric data 1: radix */
12866                0,                       /* addtl numeric data 2: 0 */
12867                xxstring,                /* Processing function */
12868                NULL,                    /* Keyword table */
12869                NULL                     /* Pointer to next FDB */
12870                );
12871         x = cmfdb(&sw);                 /* Parse something */
12872         if (x < 0) {
12873             if (x == -3) {
12874                 printf("?Channel number or EOF required\n");
12875                 x = -9;
12876             }
12877             return(x);
12878         }
12879         if (cmresult.fcode == _CMNUW) {
12880             z = cmresult.wresult;
12881             debug(F110,"FILE SEEK atmbuf",atmbuf,0);
12882             if (relative < 0) {
12883                 if (cx == FIL_SEE && (atmbuf[0] == '+' || atmbuf[0] == '-'))
12884                   relative = 1;
12885                 else
12886                   relative = 0;
12887             }
12888         } else if (cmresult.fcode == _CMKEY) {
12889             eofflg = cmresult.nresult;
12890             relative = 0;
12891             y = 0 - eofflg;
12892         }
12893         if ((x = cmcfm()) < 0)
12894           return(x);
12895         if (n == -9) return(success = 0);
12896         if (n == -8) return(success = 1);
12897         y = 1;                          /* Recycle this */
12898         z_flush(n);
12899         debug(F101,"FILE SEEK relative","",relative);
12900         debug(F101,"FILE SEEK rsize","",rsize);
12901
12902         if (rsize == RD_CHAR) {         /* Seek to byte position */
12903             if (relative > 0) {
12904                 CK_OFF_T pos;
12905                 pos = z_getpos(n);
12906                 if (pos < (CK_OFF_T)0) {
12907                     rc = pos;
12908                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
12909                     return(-9);
12910                 }
12911                 z += pos;
12912             } else {
12913                 if (z < 0 && !eofflg) { /* Negative arg but not relative */
12914                     y = 0;              /* Remember this was bad */
12915                     z = 0;              /* but substitute 0 */
12916                 }
12917             }
12918             debug(F101,"FILE SEEK /CHAR z","",z);
12919             if (z < 0 && !eofflg) {
12920                 z_error = FX_RNG;
12921                 return(success = 0);
12922             }
12923             if ((rc = z_seek(n,z)) < 0) {
12924                 if (rc == FX_EOF) return(success = 0);
12925                 printf("?SEEK /BYTE failed - Channel %d: %s\n",n,ckferror(rc));
12926                 return(-9);
12927             }
12928         } else {                        /* Seek to line */
12929             if (relative > 0) {
12930                 CK_OFF_T pos;
12931                 pos = z_getline(n);
12932                 debug(F101,"FILE SEEK /LINE pos","",pos);
12933                 if (pos < 0) {
12934                     rc = pos;
12935                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
12936                     return(-9);
12937                 }
12938                 z += pos;
12939             }
12940             debug(F101,"FILE SEEK /LINE z","",z);
12941             debug(F101,"FILE SEEK /LINE eofflg","",eofflg);
12942             if (z < 0 && !eofflg) {
12943                 z_error = FX_RNG;
12944                 return(success = 0);
12945             }
12946             if ((rc = z_line(n,z)) < 0) {
12947                 if (rc == FX_EOF) return(success = 0);
12948                 printf("?SEEK /LINE failed - Channel %d: %s\n",n,ckferror(rc));
12949                 return(-9);
12950             }
12951         }
12952         /*
12953           Now, having sought to the desired starting spot, if a /FIND:
12954           target was specified, look for it now.
12955         */
12956         if (seek_target) {
12957             int flag = 0, ispat = 0, matchresult = 0;
12958             while (!flag) {
12959                 y = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
12960                 if (y < 0) {
12961                     y = 0;
12962                     break;
12963                 }
12964                 if (ispattern(seek_target)) {
12965                     matchresult = ckmatch(seek_target,line,inpcas[cmdlvl],1+4);
12966                 } else {
12967                     /* This is faster */
12968                     matchresult = ckindex(seek_target,line,0,0,inpcas[cmdlvl]);
12969                 }
12970                 if (matchresult) {
12971                     flag = 1;
12972                     break;
12973                 }
12974             }
12975             if (flag) {
12976                 debug(F111,"FSEEK HAVE MATCH",seek_target,z_getline(n));
12977                 /* Back up to beginning of line where target found */
12978                 if ((y = z_line(n,z_getline(n)-1)) < 0) {
12979                     if (rc == FX_EOF) return(success = 0);
12980                     printf("?SEEK /LINE failed - Channel %d: %s\n",
12981                            n,ckferror(rc));
12982                     return(-9);
12983                 }
12984                 debug(F101,"FSEEK LINE","",y);
12985             }
12986         }
12987         return(success = (y < 0) ? 0 : 1);
12988
12989       case FIL_LIS: {                   /* LIST open files */
12990 #ifdef CK_TTGWSIZ
12991           extern int cmd_rows, cmd_cols;
12992 #endif /* CK_TTGWSIZ */
12993           extern int xaskmore;
12994           int i, x, n = 0, paging = 0;
12995           char * s;
12996
12997           if ((x = cmcfm()) < 0)
12998             return(x);
12999
13000 #ifdef CK_TTGWSIZ
13001           if (cmd_rows > 0 && cmd_cols > 0)
13002 #endif /* CK_TTGWSIZ */
13003             paging = xaskmore;
13004
13005           printf("System open file limit:%5d\n", z_openmax);
13006           printf("Maximum for FILE OPEN: %5d\n", z_maxchan);
13007           printf("Files currently open:  %5d\n\n", z_nopen);
13008           n = 4;
13009           for (i = 0; i < z_maxchan; i++) {
13010               s = z_getname(i);         /* Got one? */
13011               if (s) {                  /* Yes */
13012                   char m[8];
13013                   m[0] = NUL;
13014                   printf("%2d. %s",i,s); /* Print name */
13015                   n++;                   /* Count it */
13016                   x = z_getmode(i);      /* Get modes & print them */
13017                   if (x > 0) {
13018                       if (x & FM_REA) ckstrncat(m,"R",8);
13019                       if (x & FM_WRI) ckstrncat(m,"W",8);
13020                       if (x & FM_APP) ckstrncat(m,"A",8);
13021                       if (x & FM_BIN) ckstrncat(m,"B",8);
13022                       if (m[0])
13023                         printf(" (%s)",m);
13024                       if (x & FM_EOF)
13025                         printf(" [EOF]");
13026                       else              /* And file position too */
13027                         printf(" %s",ckfstoa(z_getpos(i)));
13028                   }
13029                   printf("\n");
13030 #ifdef CK_TTGWSIZ
13031                   if (paging > 0) {     /* Pause at end of screen */
13032                       if (n > cmd_rows - 3) {
13033                           if (!askmore())
13034                             break;
13035                           else
13036                             n = 0;
13037                       }
13038                   }
13039 #endif /* CK_TTGWSIZ */
13040               }
13041           }
13042           return(success = 1);
13043       }
13044
13045       case FIL_FLU:                     /* FLUSH */
13046         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
13047             if (x == -3) {
13048                 printf("?Channel number required\n");
13049                 x = -9;
13050             }
13051             return(x);
13052         }
13053         if ((x = cmcfm()) < 0)
13054           return(x);
13055         if (n == -9) return(success = 0);
13056         if (n == -8) return(success = 1);
13057         if ((rc = z_flush(n)) < 0) {
13058             printf("?FLUSH failed - Channel %d: %s\n",n,ckferror(rc));
13059             return(-9);
13060         }
13061         return(success = 1);
13062
13063       case FIL_STA:                     /* STATUS */
13064         {
13065             int i, j, k;                /* Supply default if only one open */
13066             s = "";
13067             for (k = 0, j = 0, i = 0; i < z_maxchan; i++) {
13068                 if (z_file)
13069                   if (z_file[i])
13070                     if (z_file[i]->z_fp) { k++; j = i; }
13071             }
13072             if (k == 1) s = ckitoa(j);
13073         }
13074         if ((x = cmnum("Channel number",s,10,&n, xxstring)) < 0) {
13075             if (x == -3) {
13076                 if (z_nopen > 1) {
13077                     printf("?%d files open - please supply channel number\n",
13078                            z_nopen);
13079                     return(-9);
13080                 }
13081             } else
13082               return(x);
13083         }
13084         if ((y = cmcfm()) < 0)
13085           return(y);
13086         if ((!z_file || z_nopen == 0) && x == -3) {
13087             printf("No files open\n");
13088             return(success = 1);
13089         }
13090         p = blanks + 3;                 /* Tricky formatting... */
13091         if (n < 1000) p--;
13092         if (n < 100) p--;
13093         if (n < 10) p--;
13094         if ((rc = z_getmode(n)) < 0) {
13095             printf("Channel %d:%s%s\n",n,p,ckferror(rc));
13096             return(success = 0);
13097         } else if (!rc) {
13098             printf("Channel %d:%sNot open\n",n,p);
13099             return(success = 0);
13100         } else {
13101             CK_OFF_T xx;
13102             s = z_getname(n);
13103             if (!s) s = "(name unknown)";
13104             printf("Channel %d:%sOpen\n",n,p);
13105             printf(" File:        %s\n Modes:      ",s);
13106             if (rc & FM_REA) printf(" /READ");
13107             if (rc & FM_WRI) printf(" /WRITE");
13108             if (rc & FM_APP) printf(" /APPEND");
13109             if (rc & FM_BIN) printf(" /BINARY");
13110             if (rc & FM_CMD) printf(" /COMMAND");
13111             if (rc & FM_EOF) printf(" [EOF]");
13112             printf("\n Size:        %s\n",ckfstoa(z_count(n,RD_CHAR)));
13113             printf(" At byte:     %s\n",ckfstoa(z_getpos(n)));
13114             xx = z_getline(n);
13115             if (xx > (CK_OFF_T)-1)
13116               printf(" At line:     %s\n",ckfstoa(xx));
13117             return(success = 1);
13118         }
13119       default:
13120         return(-2);
13121     }
13122 }
13123 #endif /* CKCHANNELIO */
13124
13125 #ifndef NOSETKEY
13126 /* Save Key maps and in OS/2 Mouse maps */
13127 int
13128 savkeys(name,disp) char * name; int disp; {
13129     char *tp;
13130     static struct filinfo xx;
13131     int savfil, i, j, k;
13132     char buf[1024];
13133
13134     zclose(ZMFILE);
13135
13136     if (disp) {
13137         xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
13138         xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
13139         xx.lblopts = 0;
13140         savfil = zopeno(ZMFILE,name,NULL,&xx);
13141     } else savfil = zopeno(ZMFILE,name,NULL,NULL);
13142
13143     if (savfil) {
13144 #ifdef OS2
13145         ztime(&tp);
13146         zsout(ZMFILE, "; Kermit 95 SAVE KEYMAP file: ");
13147         zsoutl(ZMFILE,tp);
13148         if (mskkeys) {
13149             zsoutl(ZMFILE,
13150          "if eq \"\\v(program)\" \"C-Kermit\" set mskermit keycodes on");
13151         } else {
13152             zsoutl(ZMFILE,
13153          "if NOT eq \"\\v(program)\" \"C-Kermit\" stop 1 C-Kermit required.");
13154             zsoutl(ZMFILE,"set mskermit keycodes off");
13155         }
13156         zsoutl(ZMFILE,"");
13157 #else /* OS2 */
13158         ztime(&tp);
13159         zsout(ZMFILE, "; C-Kermit SAVE KEYMAP file: ");
13160         zsoutl(ZMFILE,tp);
13161 #endif /* OS2 */
13162
13163         zsoutl(ZMFILE,"; Clear previous keyboard mappings ");
13164         zsoutl(ZMFILE,"set key clear");
13165 #ifdef OS2
13166         for (k = 0; k < nttkey; k++) {
13167             if (!ttkeytab[k].flgs) {
13168                 ckmakmsg(buf,1024,
13169                          "set terminal key ",
13170                          ttkeytab[k].kwd,
13171                          " clear",
13172                          NULL
13173                          );
13174                 zsoutl(ZMFILE,buf);
13175             }
13176         }
13177 #endif /* OS2 */
13178         zsoutl(ZMFILE,"");
13179
13180         for (i = 0; i < KMSIZE; i++) {
13181             if (macrotab[i]) {
13182                 int len = strlen((char *)macrotab[i]);
13183 #ifdef OS2
13184                 ckmakmsg(buf,
13185                          1024,
13186                          "set key \\",
13187                          ckitoa(mskkeys ? cktomsk(i) : i),
13188                          " ",
13189                          NULL
13190                          );
13191 #else /* OS2 */
13192                 ckmakmsg(buf,
13193                          1024,
13194                          "set key \\",
13195                          ckitoa(i),
13196                          NULL,NULL
13197                          );
13198 #endif /* OS2 */
13199                 zsout(ZMFILE,buf);
13200
13201                 for (j = 0; j < len; j++) {
13202                     char ch = macrotab[i][j];
13203                     if (ch <= SP || ch >= DEL ||
13204                          ch == '-' || ch == ',' ||
13205                          ch == '{' || ch == '}' ||
13206                          ch == ';' || ch == '?' ||
13207                          ch == '.' || ch == '\'' ||
13208                          ch == '\\' || ch == '/' ||
13209                          ch == '#') {
13210                         ckmakmsg(buf,1024,"\\{",ckitoa((int)ch),"}",NULL);
13211                         zsout(ZMFILE,buf);
13212                     } else {
13213                         ckmakmsg(buf,1024,ckctoa((char)ch),NULL,NULL,NULL);
13214                         zsout(ZMFILE,buf);
13215                     }
13216                 }
13217 #ifdef OS2
13218                 ckmakmsg(buf,1024,"\t; ",keyname(i),NULL,NULL);
13219                 zsoutl(ZMFILE,buf);
13220 #else
13221                 zsoutl(ZMFILE,"");
13222 #endif /* OS2 */
13223             } else if ( keymap[i] != i ) {
13224 #ifndef NOKVERBS
13225                 if (IS_KVERB(keymap[i])) {
13226                     for (j = 0; j < nkverbs; j++)
13227                       if (kverbs[j].kwval == (keymap[i] & ~F_KVERB))
13228                         break;
13229                     if (j != nkverbs) {
13230 #ifdef OS2
13231 #ifdef COMMENT
13232                         sprintf(buf, "set key \\%d \\K%s\t; %s",
13233                                 mskkeys ? cktomsk(i) : i,
13234                                 kverbs[j].kwd, keyname(i)
13235                                 );
13236 #else
13237                         ckmakxmsg(buf,  /* 12 string args */
13238                                   1024,
13239                                   "set key \\",
13240                                   ckitoa(mskkeys ? cktomsk(i) : i),
13241                                   " \\K",
13242                                   kverbs[j].kwd,
13243                                   "\t; ",
13244                                   keyname(i),
13245                                   NULL, NULL, NULL, NULL, NULL, NULL);
13246 #endif /* COMMENT */
13247                         zsoutl(ZMFILE,buf);
13248 #else
13249 #ifdef COMMENT
13250                         sprintf(buf, "set key \\%d \\K%s", i, kverbs[j].kwd);
13251 #else
13252                         ckmakmsg(buf,1024,
13253                                  "set key \\",
13254                                  ckitoa(i),
13255                                  " \\K",
13256                                  kverbs[j].kwd
13257                                  );
13258 #endif /* COMMENT */
13259                         zsoutl(ZMFILE,buf);
13260 #endif
13261                     }
13262                 } else
13263 #endif /* NOKVERBS */
13264                   {
13265 #ifdef OS2
13266 #ifdef COMMENT
13267                       sprintf(buf, "set key \\%d \\{%d}\t; %s",
13268                               mskkeys ? cktomsk(i) : i,
13269                               keymap[i],
13270                               keyname(i)
13271                               );
13272 #else
13273                       ckmakxmsg(buf,    /* 8 string args */
13274                                 1024,
13275                                 "set key \\",
13276                                 ckitoa(mskkeys ? cktomsk(i) : i),
13277                                 " \\{",
13278                                 ckitoa(keymap[i]),
13279                                 "}\t; ",
13280                                 keyname(i),
13281                                 NULL,NULL,NULL,NULL,NULL,NULL);
13282 #endif /* COMMENT */
13283                       zsoutl(ZMFILE,buf);
13284 #else
13285 #ifdef COMMENT
13286                       sprintf(buf, "set key \\%d \\{%d}", i, keymap[i]);
13287 #else
13288                       ckmakxmsg(buf,1024,
13289                                "set key \\",
13290                                ckitoa(i),
13291                                " \\{",
13292                                ckitoa(keymap[i]),
13293                                "}",
13294                                NULL,NULL,NULL,NULL,NULL,NULL,NULL);
13295 #endif /* COMMENT */
13296                       zsoutl(ZMFILE,buf);
13297 #endif /* OS2 */
13298                   }
13299             }
13300         }
13301 #ifdef OS2
13302         /* OS/2 also has the SET TERMINAL KEY <termtype> defines */
13303         for (k = 0; k < nttkey; k++) {
13304             extern struct keynode * ttkeymap[];
13305             struct keynode * pnode = NULL;
13306
13307             if (ttkeytab[k].flgs)       /* Don't process CM_INV or CM_ABR */
13308               continue;
13309
13310             zsoutl(ZMFILE,"");
13311             ckmakmsg(buf,1024,"; SET TERMINAL KEY ",ttkeytab[k].kwd,NULL,NULL);
13312             zsoutl(ZMFILE,buf);
13313
13314             for (pnode = ttkeymap[ttkeytab[k].kwval];
13315                  pnode;
13316                  pnode = pnode->next
13317                  ) {
13318                 switch (pnode->def.type) {
13319                   case key:
13320 #ifdef COMMENT
13321                     sprintf(buf, "set terminal key %s \\%d \\{%d}\t; %s",
13322                             ttkeytab[k].kwd,
13323                             mskkeys ? cktomsk(pnode->key) : pnode->key,
13324                             pnode->def.key.scancode,
13325                             keyname(pnode->key)
13326                             );
13327 #else
13328                     ckmakxmsg(buf,
13329                               1024,
13330                               "set terminal key ",
13331                               ttkeytab[k].kwd,
13332                               " \\",
13333                               ckitoa(mskkeys ?
13334                                      cktomsk(pnode->key) :
13335                                      pnode->key),
13336                               " \\{",
13337                               ckitoa(pnode->def.key.scancode),
13338                               "}\t; ",
13339                               keyname(pnode->key),
13340                               NULL,NULL,NULL,NULL
13341                               );
13342 #endif /* COMMENT */
13343                     zsoutl(ZMFILE,buf);
13344                     break;
13345                   case kverb:
13346                     for (j = 0; j < nkverbs; j++)
13347                       if (kverbs[j].kwval == (pnode->def.kverb.id & ~F_KVERB))
13348                         break;
13349                     if (j != nkverbs) {
13350 #ifdef COMMENT
13351                         sprintf(buf, "set terminal key %s \\%d \\K%s\t; %s",
13352                                 ttkeytab[k].kwd,
13353                                 mskkeys ? cktomsk(pnode->key) : pnode->key,
13354                                 kverbs[j].kwd, keyname(pnode->key)
13355                                 );
13356 #else
13357                         ckmakxmsg(buf,
13358                                   1024,
13359                                   "set terminal key ",
13360                                   ttkeytab[k].kwd,
13361                                   " \\",
13362                                   ckitoa(mskkeys ?
13363                                          cktomsk(pnode->key) :
13364                                          pnode->key),
13365                                   " \\K",
13366                                   kverbs[j].kwd,
13367                                   "\t; ",
13368                                   keyname(pnode->key),
13369                                   NULL,NULL,NULL,NULL
13370                                   );
13371 #endif /* COMMENT */
13372                         zsoutl(ZMFILE,buf);
13373                     }
13374                     break;
13375                   case macro: {
13376                       int len = strlen((char *)pnode->def.macro.string);
13377 #ifdef COMMENT
13378                       sprintf(buf,"set terminal key %s \\%d ",
13379                               ttkeytab[k].kwd,
13380                               mskkeys ? cktomsk(pnode->key) : pnode->key);
13381 #else
13382                       ckmakxmsg(buf,
13383                                1024,
13384                                "set terminal key ",
13385                                ttkeytab[k].kwd,
13386                                " \\",
13387                                ckitoa(mskkeys ?
13388                                       cktomsk(pnode->key) :
13389                                       pnode->key),
13390                                " ",
13391                                NULL,NULL,NULL,NULL,NULL,NULL,NULL
13392                               );
13393 #endif /* COMMENT */
13394                       zsout(ZMFILE,buf);
13395
13396                       for (j = 0; j < len; j++) {
13397                           char ch = pnode->def.macro.string[j];
13398                           if (ch <= SP || ch >= DEL ||
13399                                ch == '-' || ch == ',' ||
13400                                ch == '{' || ch == '}' ||
13401                                ch == ';' || ch == '?' ||
13402                                ch == '.' || ch == '\'' ||
13403                                ch == '\\' || ch == '/' ||
13404                                ch == '#') {
13405                               ckmakmsg(buf,1024,
13406                                        "\\{",ckitoa((int)ch),"}",NULL);
13407                               zsout(ZMFILE,buf);
13408                           } else {
13409                               ckmakmsg(buf,1024,
13410                                        ckctoa((char)ch),NULL,NULL,NULL);
13411                               zsout(ZMFILE,buf);
13412                           }
13413                       }
13414                       ckmakmsg(buf,1024,"\t; ",keyname(pnode->key),NULL,NULL);
13415                       zsoutl(ZMFILE,buf);
13416                       break;
13417                   }
13418                   case literal: {
13419                       int len = strlen((char *)pnode->def.literal.string);
13420 #ifdef COMMENT
13421                       sprintf(buf,"set terminal key %s /literal \\%d ",
13422                               ttkeytab[k].kwd,
13423                               mskkeys ? cktomsk(pnode->key) : pnode->key);
13424 #else
13425                       ckmakxmsg(buf,
13426                                1024,
13427                                "set terminal key ",
13428                                ttkeytab[k].kwd,
13429                                " /literal \\",
13430                                ckitoa(mskkeys ?
13431                                       cktomsk(pnode->key) :
13432                                       pnode->key),
13433                                " ",
13434                                NULL,NULL,NULL,NULL,NULL,NULL,NULL);
13435 #endif /* COMMENT */
13436                       zsout(ZMFILE,buf);
13437
13438                       for (j = 0; j < len; j++) {
13439                           char ch = pnode->def.literal.string[j];
13440                           if (ch <= SP || ch >= DEL ||
13441                                ch == '-' || ch == ',' ||
13442                                ch == '{' || ch == '}' ||
13443                                ch == ';' || ch == '?' ||
13444                                ch == '.' || ch == '\'' ||
13445                                ch == '\\' || ch == '/' ||
13446                                ch == '#') {
13447                               ckmakmsg(buf,1024,
13448                                        "\\{",ckitoa((int)ch),"}",NULL);
13449                               zsout(ZMFILE,buf);
13450                           } else {
13451                               ckmakmsg(buf,1024,
13452                                        ckctoa((char)ch),NULL,NULL,NULL);
13453                               zsout(ZMFILE,buf);
13454                           }
13455                       }
13456                       ckmakmsg(buf,1024,"\t; ",keyname(pnode->key),NULL,NULL);
13457                       zsoutl(ZMFILE,buf);
13458                       break;
13459                   }
13460                   case esc:
13461 #ifdef COMMENT
13462                     sprintf(buf,
13463                        "set terminal key %s /literal \\%d \\{%d}\\{%d}\t; %s",
13464                             ttkeytab[k].kwd,
13465                             mskkeys ? cktomsk(pnode->key) : pnode->key,
13466                             ISDG200(ttkeytab[k].kwval) ? 30 : 27,
13467                             pnode->def.esc.key & ~F_ESC,
13468                             keyname(pnode->key)
13469                             );
13470 #else
13471                     ckmakxmsg(buf,
13472                               1024,
13473                               "set terminal key ",
13474                               ttkeytab[k].kwd,
13475                               " /literal \\",
13476                               ckitoa(mskkeys ?
13477                                      cktomsk(pnode->key) :
13478                                      pnode->key),
13479                               " \\{",
13480                               ckitoa(ISDG200(ttkeytab[k].kwval) ? 30 : 27),
13481                               "}\\{",
13482                               ckitoa(pnode->def.esc.key & ~F_ESC),
13483                               "}\t; ",
13484                               keyname(pnode->key),
13485                               NULL,NULL
13486                               );
13487 #endif /* COMMENT */
13488                     zsoutl(ZMFILE,buf);
13489                     break;
13490                   case csi:
13491 #ifdef COMMENT
13492                     sprintf(buf,
13493                        "set terminal key %s /literal \\%d \\{27}[\\{%d}\t; %s",
13494                             ttkeytab[k].kwd,
13495                             mskkeys ? cktomsk(pnode->key) : pnode->key,
13496                             pnode->def.csi.key & ~F_CSI,
13497                             keyname(pnode->key)
13498                             );
13499 #else
13500                     ckmakxmsg(buf,
13501                               1024,
13502                               "set terminal key ",
13503                               ttkeytab[k].kwd,
13504                               " /literal \\",
13505                               ckitoa(mskkeys ?
13506                                      cktomsk(pnode->key) :
13507                                      pnode->key),
13508                               " \\{27}[\\{",
13509                               ckitoa(pnode->def.csi.key & ~F_CSI),
13510                               "}\t; ",
13511                               keyname(pnode->key),
13512                               NULL,NULL,NULL,NULL
13513                               );
13514 #endif /* COMMENT */
13515                     zsoutl(ZMFILE,buf);
13516                     break;
13517                   default:
13518                     continue;
13519                 }
13520             }
13521         }
13522 #endif /* OS2 */
13523
13524         zsoutl(ZMFILE,"");
13525         zsoutl(ZMFILE,"; End");
13526         zclose(ZMFILE);
13527         return(success = 1);
13528     } else {
13529         return(success = 0);
13530     }
13531 }
13532 #endif /* NOSETKEY */
13533
13534 #define SV_SCRL 0
13535 #define SV_HIST 1
13536
13537 #ifdef OS2
13538 #ifndef NOLOCAL
13539 static struct keytab trmtrmopt[] = {
13540     { "scrollback", SV_SCRL, 0 }
13541 };
13542 #endif /* NOLOCAL */
13543 #endif /* OS2 */
13544
13545 static struct keytab cmdtrmopt[] = {
13546 #ifdef CK_RECALL
13547     { "history",    SV_HIST, 0 },
13548 #endif /* CK_RECALL */
13549 #ifdef OS2
13550 #ifndef NOLOCAL
13551     { "scrollback", SV_SCRL, 0 },
13552 #endif /* NOLOCAL */
13553 #endif /* OS2 */
13554     { "", 0, 0 }
13555 };
13556 static int ncmdtrmopt = (sizeof (cmdtrmopt) / sizeof (struct keytab)) - 1;
13557
13558 #ifdef OS2
13559 #ifndef NOLOCAL
13560 _PROTOTYP(int savscrbk, (int, char *, int));
13561 #endif /* NOLOCAL */
13562 #endif /* OS2 */
13563
13564 #ifdef CK_RECALL
13565 _PROTOTYP(int savhistory, (char *, int));
13566 #endif /* CK_RECALL */
13567
13568 int
13569 dosave(xx) int xx; {
13570     int x, y = 0, disp;
13571     char * s = NULL;
13572     extern struct keytab disptb[];
13573 #ifdef ZFNQFP
13574     struct zfnfp * fnp;
13575 #endif /* ZFNQFP */
13576
13577 #ifndef NOSETKEY
13578     if (xx == XSKEY) {                  /* SAVE KEYMAP.. */
13579         z = cmofi("Name of Kermit command file","keymap.ksc",&s,xxstring);
13580     } else {
13581 #endif /* NOSETKEY */
13582         switch (xx) {
13583           case XSCMD:                   /* SAVE COMMAND.. */
13584             if ((y = cmkey(cmdtrmopt, ncmdtrmopt, "What to save",
13585 #ifdef OS2
13586                            "scrollback",
13587 #else
13588                            "history",
13589 #endif /* OS2 */
13590                            xxstring)) < 0)
13591               return(y);
13592             break;
13593 #ifdef OS2
13594 #ifndef NOLOCAL
13595           case XSTERM:                  /* SAVE TERMINAL.. */
13596             if ((y = cmkey(trmtrmopt,1,
13597                            "What to save","scrollback",xxstring)) < 0)
13598               return(y);
13599             break;
13600 #endif /* NOLOCAL */
13601 #endif /* OS2 */
13602         }
13603         z = cmofi("Filename",
13604                   ((y == SV_SCRL) ? "scrollbk.txt" : "history.txt"),
13605                   &s,
13606                   xxstring
13607                   );
13608 #ifndef NOSETKEY
13609     }
13610 #endif /* NOSETKEY */
13611     if (z < 0)                          /* Check output-file parse results */
13612       return(z);
13613     if (z == 2) {
13614         printf("?Sorry, %s is a directory name\n",s);
13615         return(-9);
13616     }
13617 #ifdef ZFNQFP
13618     if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {/* Convert to full pathname */
13619         if (fnp->fpath)
13620           if ((int) strlen(fnp->fpath) > 0)
13621             s = fnp->fpath;
13622     }
13623 #endif /* ZFNQFP */
13624
13625     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of pathname */
13626     s = line;
13627 #ifdef MAC
13628     z = 0;
13629 #else
13630     /* Get NEW/APPEND disposition */
13631     if ((z = cmkey(disptb,2,"Disposition","new",xxstring)) < 0)
13632       return(z);
13633 #endif /* MAC */
13634     disp = z;
13635     if ((x = cmcfm()) < 0)              /* Get confirmation */
13636       return(x);
13637
13638     switch (xx) {                       /* Do action.. */
13639 #ifndef NOSETKEY
13640       case XSKEY:                       /* SAVE KEYMAP */
13641         return (savkeys(s,disp));
13642 #endif /* NOSETKEY */
13643
13644       case XSCMD:                       /* SAVE COMMAND.. */
13645 #ifdef OS2
13646 #ifndef NOLOCAL
13647         if (y == SV_SCRL)               /* .. SCROLLBACK */
13648           return(success = savscrbk(VCMD,s,disp));
13649 #endif /* NOLOCAL */
13650 #endif /* OS2 */
13651 #ifndef NORECALL
13652         if (y == SV_HIST)               /* .. HISTORY */
13653           return(success = savhistory(s,disp));
13654 #endif /* NORECALL */
13655         break;
13656
13657 #ifdef OS2
13658 #ifndef NOLOCAL
13659       case XSTERM:                      /* SAVE TERMINAL SCROLLBACK */
13660         return(success = savscrbk(VTERM,s,disp));
13661 #endif /* NOLOCAL */
13662 #endif /* OS2 */
13663     }
13664     success = 0;
13665     return(-2);
13666 }
13667
13668 /*
13669   R E A D T E X T
13670
13671   Read text with a custom prompt into given buffer using command parser but
13672   with no echoing or entry into recall buffer.
13673 */
13674 int
13675 readtext(prmpt, buffer, bufsiz) char * prmpt; char * buffer; int bufsiz; {
13676 #ifdef CK_RECALL
13677     extern int on_recall;               /* Around Password prompting */
13678 #endif /* CK_RECALL */
13679     int rc;
13680 #ifndef NOLOCAL
13681 #ifdef OS2
13682     extern int vmode;
13683     extern int startflags;
13684     int vmode_sav = vmode;
13685
13686     if (!prmpt) prmpt = "";
13687
13688     if (win95_popup && !(startflags & 96)
13689 #ifdef IKSD
13690          && !inserver
13691 #endif /* IKSD */
13692          )
13693       return(popup_readtext(vmode,NULL,prmpt,buffer,bufsiz,0));
13694
13695     if (vmode == VTERM) {
13696         vmode = VCMD;
13697         VscrnIsDirty(VTERM);
13698         VscrnIsDirty(VCMD);
13699     }
13700 #endif /* OS2 */
13701 #endif /* NOLOCAL */
13702
13703 #ifdef CK_RECALL
13704     on_recall = 0;
13705 #endif /* CK_RECALL */
13706     cmsavp(psave,PROMPTL);              /* Save old prompt */
13707     cmsetp(prmpt);                      /* Make new prompt */
13708     concb((char)escape);                /* Put console in cbreak mode */
13709     cmini(1);                           /* and echo mode */
13710     if (pflag) prompt(xxstring);        /* Issue prompt if at top level */
13711     cmres();                            /* Reset the parser */
13712     for (rc = -1; rc < 0; ) {           /* Prompt till they answer */
13713         rc = cmtxt("","",&s,NULL);      /* Get a literal line of text */
13714         cmres();                        /* Reset the parser again */
13715     }
13716     ckstrncpy(buffer,s,bufsiz);
13717     cmsetp(psave);                      /* Restore original prompt */
13718
13719 #ifndef NOLOCAL
13720 #ifdef OS2
13721     if (vmode != vmode_sav) {
13722         vmode = VTERM;
13723         VscrnIsDirty(VCMD);
13724         VscrnIsDirty(VTERM);
13725     }
13726 #endif /* OS2 */
13727 #endif /* NOLOCAL */
13728     return(0);
13729 }
13730 #endif /* NOICP */
13731
13732 /* A general function to allow a Password or other information  */
13733 /* to be read from the command prompt without it going into     */
13734 /* the recall buffer or being echo'd.                           */
13735
13736 int
13737 readpass(prmpt, buffer, bufsiz) char * prmpt; char * buffer; int bufsiz; {
13738     int x;
13739 #ifdef NOICP
13740     if (!prmpt) prmpt = "";
13741     printf("%s", prmpt);
13742 #ifdef COMMENT
13743     /* Some linkers won't allow this because it's unsafe */
13744     gets(buffer);
13745 #else  /* COMMENT */
13746     {
13747         int c, i; char * p;
13748         p = buffer;
13749         for (i = 0; i < bufsiz-1; i++) {
13750             if ((c = getchar()) == EOF)
13751               break;
13752             if (c < SP)
13753               break;
13754             buffer[i] = c;
13755         }
13756         buffer[i] = NUL;
13757     }
13758 #endif /* COMMENT */
13759     return(1);
13760 #else  /* NOICP */
13761 #ifdef CK_RECALL
13762     extern int on_recall;               /* around Password prompting */
13763 #endif /* CK_RECALL */
13764     int rc;
13765 #ifndef NOLOCAL
13766 #ifdef OS2
13767     extern int vmode;
13768     extern int startflags;
13769     int vmode_sav = vmode;
13770 #endif /* OS2 */
13771 #endif /* NOLOCAL */
13772 #ifdef CKSYSLOG
13773     int savlog;
13774 #endif /* CKSYSLOG */
13775     if (!prmpt) prmpt = "";
13776 #ifndef NOLOCAL
13777     debok = 0;                          /* Don't log */
13778 #ifdef OS2
13779     if (win95_popup && !(startflags & 96)
13780 #ifdef IKSD
13781          && !inserver
13782 #endif /* IKSD */
13783          ) {
13784         x = popup_readpass(vmode,NULL,prmpt,buffer,bufsiz,0);
13785         debok = 1;
13786         return(x);
13787     }
13788 #endif /* OS2 */
13789 #endif /* NOLOCAL */
13790
13791 #ifdef CKSYSLOG
13792     savlog = ckxsyslog;                 /* Save and turn off syslogging */
13793     ckxsyslog = 0;
13794 #endif /* CKSYSLOG */
13795 #ifndef NOLOCAL
13796 #ifdef OS2
13797     if (vmode == VTERM) {
13798         vmode = VCMD;
13799         VscrnIsDirty(VTERM);
13800         VscrnIsDirty(VCMD);
13801     }
13802 #endif /* OS2 */
13803 #endif /* NOLOCAL */
13804 #ifdef CK_RECALL
13805     on_recall = 0;
13806 #endif /* CK_RECALL */
13807     cmsavp(psave,PROMPTL);              /* Save old prompt */
13808     cmsetp(prmpt);                      /* Make new prompt */
13809     concb((char)escape);                /* Put console in cbreak mode */
13810     cmini(0);                           /* and no-echo mode */
13811     if (pflag) prompt(xxstring);        /* Issue prompt if at top level */
13812     cmres();                            /* Reset the parser */
13813     for (rc = -1; rc < 0; ) {           /* Prompt till they answer */
13814         rc = cmtxt("","",&s,NULL);      /* Get a literal line of text */
13815         cmres();                        /* Reset the parser again */
13816     }
13817     ckstrncpy(buffer,s,bufsiz);
13818     printf("\r\n");                     /* Echo a CRLF */
13819     cmsetp(psave);                      /* Restore original prompt */
13820     cmini(1);                           /* Restore echo mode */
13821 #ifndef NOLOCAL
13822 #ifdef OS2
13823     if (vmode != vmode_sav) {
13824         vmode = VTERM;
13825         VscrnIsDirty(VCMD);
13826         VscrnIsDirty(VTERM);
13827     }
13828 #endif /* OS2 */
13829 #endif /* NOLOCAL */
13830 #ifdef CKSYSLOG
13831     ckxsyslog = savlog;                 /* Restore syslogging */
13832 #endif /* CKSYSLOG */
13833     debok = 1;
13834     return(0);
13835 #endif /* NOICP */
13836 }
13837
13838 #ifndef NOICP
13839 struct keytab authtab[] = {             /* Available authentication types */
13840 #ifdef CK_KERBEROS
13841     { "k4",        AUTH_KRB4, CM_INV },
13842     { "k5",        AUTH_KRB5, CM_INV },
13843     { "kerberos4", AUTH_KRB4, 0      },
13844     { "kerberos5", AUTH_KRB5, 0      },
13845     { "krb4",      AUTH_KRB4, CM_INV },
13846     { "krb5",      AUTH_KRB5, CM_INV },
13847 #endif /* CK_KERBEROS */
13848 #ifdef NT
13849     { "ntlm",      AUTH_NTLM, 0 },
13850 #endif /* NT */
13851 #ifdef CK_SRP
13852     { "srp",       AUTH_SRP,  0 },
13853 #endif /* CK_SRP */
13854 #ifdef CK_SSL
13855     { "ssl",       AUTH_SSL,  0 },
13856 #endif /* CK_SSL */
13857     { "",          0,         0 }
13858 };
13859 int authtabn = sizeof(authtab)/sizeof(struct keytab)-1;
13860
13861 #ifdef CK_KERBEROS
13862 struct keytab kerbtab[] = {             /* Kerberos authentication types */
13863     { "k4",        AUTH_KRB4, CM_INV },
13864     { "k5",        AUTH_KRB5, CM_INV },
13865     { "kerberos4", AUTH_KRB4, 0      },
13866     { "kerberos5", AUTH_KRB5, 0      },
13867     { "krb4",      AUTH_KRB4, CM_INV },
13868     { "krb5",      AUTH_KRB5, CM_INV }
13869 };
13870 int kerbtabn = sizeof(kerbtab)/sizeof(struct keytab);
13871
13872 static struct keytab krb_s_tbl[] = {    /* AUTHENTICATE command switches: */
13873     { "/cache",   KRB_S_CA, CM_ARG }
13874 };
13875 static int krb_s_n = sizeof(krb_s_tbl)/sizeof(struct keytab);
13876
13877 static struct keytab krb_v_tbl[] = {    /* KERBEROS version values: */
13878     { "4",    4, 0 },
13879     { "5",    5, 0 },                   /* (add others as needed...) */
13880     { "auto", 0, 0 }                    /* Note: 0 = auto */
13881 };
13882 static int krb_v_n = sizeof(krb_v_tbl)/sizeof(struct keytab);
13883
13884 static struct keytab krb_a_tbl[] = {    /* KERBEROS actions: */
13885     { "destroy",           KRB_A_DE, 0 },
13886     { "initialize",        KRB_A_IN, 0 },
13887     { "list-credentials",  KRB_A_LC, 0 }
13888 };
13889 static int krb_a_n = sizeof(krb_a_tbl)/sizeof(struct keytab);
13890
13891 static struct keytab krb4_i_tbl[] = {   /* KERBEROS 4 INITIALIZE switches: */
13892     { "/brief",            KRB_I_BR, 0 },      /* /BRIEF       */
13893     { "/instance",         KRB_I_IN, CM_ARG }, /* /INSTANCE:   */
13894     { "/lifetime",         KRB_I_LF, CM_ARG }, /* /LIFETIME:   */
13895     { "/not-preauth",      KRB_I_NPA, 0 },     /* /NOT-PREAUTH */
13896     { "/password",         KRB_I_PW, CM_ARG }, /* /PASSWORD:   */
13897 #ifdef OS2
13898     { "/popup",            KRB_I_POP, 0 },     /* /POPUP       */
13899 #endif /* OS2 */
13900     { "/preauth",          KRB_I_PA, 0 },      /* /PREAUTH     */
13901     { "/realm",            KRB_I_RL, CM_ARG }, /* /REALM:      */
13902     { "/verbose",          KRB_I_VB, 0 },      /* /VERBOSE     */
13903     { "", 0, 0 }
13904 };
13905 static int krb4_i_n = sizeof(krb4_i_tbl)/sizeof(struct keytab) - 1;
13906
13907 static struct keytab krb5_i_tbl[] = {   /* KERBEROS 5 INITIALIZE switches: */
13908     { "/addresses",        KRB_I_ADR, CM_ARG },
13909     { "/forwardable",      KRB_I_FW,  0 },         /* /FORWARDABLE */
13910     { "/instance",         KRB_I_IN, CM_ARG }, /* /INSTANCE:   */
13911     { "/k4",               KRB_I_K4,  CM_INV }, /* /KERBEROS4   */
13912     { "/kerberos4",        KRB_I_K4,  0 },      /* /KERBEROS4   */
13913     { "/krb4",             KRB_I_K4,  CM_INV }, /* /KERBEROS4   */
13914     { "/lifetime",         KRB_I_LF,  CM_ARG }, /* /LIFETIME:   */
13915     { "/no-addresses",     KRB_I_NAD, 0 },      /* /NO-ADDRESSES */
13916     { "/no-k4",            KRB_I_NK4, CM_INV },/* /NO-KERBEROS4 */
13917     { "/no-kerberos4",     KRB_I_NK4, 0 },     /* /NO-KERBEROS4 */
13918     { "/no-krb4",          KRB_I_NK4, CM_INV },/* /NO-KERBEROS4 */
13919     { "/not-forwardable",  KRB_I_NFW, 0 },         /* /NOT-FORWARDABLE */
13920     { "/not-proxiable",    KRB_I_NPR, 0 },     /* /NOT-PROXIABLE   */
13921     { "/password",         KRB_I_PW,  CM_ARG }, /* /PASSWORD:   */
13922 #ifdef OS2
13923     { "/popup",            KRB_I_POP, 0 },     /* /POPUP       */
13924 #endif /* OS2 */
13925     { "/postdate",         KRB_I_PD, CM_ARG }, /* /POSTDATE:   */
13926     { "/pr",               KRB_I_PR, CM_INV|CM_ABR }, /* to allow for */
13927     { "/pro",              KRB_I_PR, CM_INV|CM_ABR }, /* different spellings */
13928     { "/prox",             KRB_I_PR, CM_INV|CM_ABR },
13929     { "/proxiable",        KRB_I_PR, 0 },      /* /PROXIABLE   */
13930     { "/proxyable",        KRB_I_PR, CM_INV }, /* /PROXYABLE   */
13931     { "/realm",            KRB_I_RL, CM_ARG }, /* /REALM:      */
13932     { "/renew",            KRB_I_RN, 0 },          /* /RENEW       */
13933     { "/renewable",        KRB_I_RB, CM_ARG }, /* /RENEWABLE:  */
13934     { "/service",          KRB_I_SR, CM_ARG }, /* /SERVICE:    */
13935     { "/validate",         KRB_I_VA, 0 },          /* /VALIDATE    */
13936     { "", 0, 0 }
13937 };
13938 static int krb5_i_n = sizeof(krb5_i_tbl)/sizeof(struct keytab) - 1;
13939
13940 static struct keytab klctab[] = {       /* List Credentials switches*/
13941     { "/addresses",  XYKLCAD, 0 },
13942     { "/encryption", XYKLCEN, 0 },
13943     { "/flags",      XYKLCFL, 0 }
13944 };
13945 static int nklctab = sizeof(klctab)/sizeof(struct keytab);
13946
13947 extern int krb_action;
13948 extern struct krb_op_data krb_op;
13949
13950 extern struct krb5_list_cred_data krb5_lc;
13951 extern struct krb5_init_data krb5_init;
13952 extern char * krb5_d_principal;         /* Default principal */
13953 extern char * krb5_d_instance;
13954 extern char * krb5_d_realm;             /* Default realm */
13955 extern char * krb5_d_cc;                /* Default credentials cache */
13956 extern char * krb5_d_srv;               /* Default service name */
13957 extern int    krb5_d_lifetime;          /* Default lifetime */
13958 extern int    krb5_d_forwardable;
13959 extern int    krb5_d_proxiable;
13960 extern int    krb5_d_renewable;
13961 extern int    krb5_autoget;
13962 extern int    krb5_autodel;
13963 extern int    krb5_d_getk4;
13964 extern int    krb5_d_no_addresses;
13965 extern int    krb5_checkaddrs;
13966 extern char * krb5_d_addrs[];
13967 extern char * k5_keytab;                /* Keytab file */
13968
13969 extern struct krb4_init_data krb4_init;
13970 extern char * krb4_d_principal;         /* Default principal */
13971 extern char * krb4_d_realm;             /* Default realm */
13972 extern char * krb4_d_srv;               /* Default service name */
13973 extern int    krb4_d_lifetime;          /* Default lifetime */
13974 extern int    krb4_d_preauth;
13975 extern char * krb4_d_instance;
13976 extern int    krb4_autoget;
13977 extern int    krb4_autodel;
13978 extern int    krb4_checkaddrs;
13979 extern char * k4_keytab;                /* Keytab file */
13980 #endif /* CK_KERBEROS */
13981
13982 #ifndef NOSHOW
13983 int
13984 sho_iks() {
13985 #ifdef IKSDCONF
13986 #ifdef CK_LOGIN
13987     extern int ckxsyslog, ckxwtmp, ckxanon;
13988 #ifdef UNIX
13989     extern int ckxpriv;
13990 #endif /* UNIX */
13991 #ifdef CK_PERMS
13992     extern int ckxperms;
13993 #endif /* CK_PERMS */
13994     extern char * anonfile, * userfile, * anonroot;
13995 #ifdef OS2
13996     extern char * anonacct;
13997 #endif /* OS2 */
13998 #ifdef NT
13999     extern char * iks_domain;
14000 #endif /* NT */
14001 #endif /* CK_LOGIN */
14002 #ifdef CKWTMP
14003     extern char * wtmpfile;
14004 #endif /* CKWTMP */
14005 #ifdef IKSDB
14006     extern char * dbfile;
14007     extern int dbenabled;
14008 #endif /* IKSDB */
14009 #ifdef CK_LOGIN
14010     extern int logintimo;
14011 #endif /* CK_LOGIN */
14012     extern int srvcdmsg, success, iksdcf, noinit, arg_x;
14013     extern char * cdmsgfile[], * cdmsgstr, *kermrc;
14014     char * bannerfile = NULL;
14015     char * helpfile = NULL;
14016     extern int xferlog;
14017     extern char * xferfile;
14018     int i;
14019
14020     if (isguest) {
14021         printf("?Command disabled\r\n");
14022         return(success = 0);
14023     }
14024
14025     printf("IKS Settings\r\n");
14026 #ifdef CK_LOGIN
14027 #ifdef OS2
14028     printf("  Anonymous Account:   %s\r\n",anonacct?anonacct:"<none>");
14029 #endif /* OS2 */
14030     printf("  Anonymous Initfile:  %s\r\n",anonfile?anonfile:"<none>");
14031     printf("  Anonymous Login:     %d\r\n",ckxanon);
14032     printf("  Anonymous Root:      %s\r\n",anonroot?anonroot:"<none>");
14033 #endif /* CK_LOGIN */
14034     printf("  Bannerfile:          %s\r\n",bannerfile?bannerfile:"<none>");
14035     printf("  CDfile:              %s\r\n",cdmsgfile[0]?cdmsgfile[0]:"<none>");
14036     for ( i=1;i<16 && cdmsgfile[i];i++ )
14037         printf("  CDfile:              %s\r\n",cdmsgfile[i]);
14038     printf("  CDMessage:           %d\r\n",srvcdmsg);
14039 #ifdef IKSDB
14040     printf("  DBfile:              %s\r\n",dbfile?dbfile:"<none>");
14041     printf("  DBenabled:           %d\r\n",dbenabled);
14042 #endif /* IKSDB */
14043 #ifdef CK_LOGIN
14044 #ifdef NT
14045     printf("  Default-domain:      %s\r\n",iks_domain?iks_domain:".");
14046 #endif /* NT */
14047 #endif /* CK_LOGIN */
14048     printf("  Helpfile:            %s\r\n",helpfile?helpfile:"<none>");
14049     printf("  Initfile:            %s\r\n",kermrc?kermrc:"<none>");
14050     printf("  No-Initfile:         %d\r\n",noinit);
14051 #ifdef CK_LOGIN
14052 #ifdef CK_PERM
14053     printf("  Permission code:     %0d\r\n",ckxperms);
14054 #endif /* CK_PERM */
14055 #ifdef UNIX
14056     printf("  Privileged Login:    %d\r\n",ckxpriv);
14057 #endif /* UNIX */
14058 #endif /* CK_LOGIN */
14059     printf("  Server-only:         %d\r\n",arg_x);
14060     printf("  Syslog:              %d\r\n",ckxsyslog);
14061     printf("  Timeout (seconds):   %d\r\n",logintimo);
14062     printf("  Userfile:            %s\r\n",userfile?userfile:"<none>");
14063 #ifdef CK_LOGIN
14064 #ifdef CKWTMP
14065     printf("  Wtmplog:             %d\r\n",ckxwtmp);
14066     printf("  Wtmpfile:            %s\r\n",wtmpfile?wtmpfile:"<none>");
14067 #endif /* CKWTMP */
14068 #endif /* CK_LOGIN */
14069     printf("  Xferfile:            %s\r\n",xferfile?xferfile:"<none>");
14070     printf("  Xferlog:             %d\r\n",xferlog);
14071 #else /* IKSDCONF */
14072     printf("?Nothing to show.\r\n");
14073 #endif /* IKSDCONF */
14074     return(success = 1);
14075 }
14076
14077 #ifdef CK_AUTHENTICATION
14078 int
14079 sho_auth(cx) int cx; {
14080     extern int auth_type_user[], cmd_rows;
14081     int i;
14082     char * p;
14083     int kv = 0, all = 0, n = 0;
14084
14085 #ifdef IKSD
14086     if (inserver && isguest) {
14087         printf("?Sorry, command disabled.\r\n");
14088         return(success = 0);
14089     }
14090 #endif /* IKSD */
14091     if (cx) {
14092         kv = cx;
14093     } else if (auth_type_user[0] != AUTHTYPE_AUTO) {
14094         kv = auth_type_user[0];
14095     } else {
14096         all = 1;
14097         kv = AUTHTYPE_KERBEROS_V4;
14098     }
14099     while (kv) {
14100         switch (kv) {
14101           case AUTHTYPE_KERBEROS_V4:
14102             kv = all ? AUTHTYPE_KERBEROS_V5 : 0;
14103             if (ck_krb4_is_installed()) {
14104                 printf(" Authentication:      Kerberos 4\n");
14105                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14106             } else {
14107                 printf(" Authentication:      Kerberos 4 (not installed)\n");
14108                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14109                 continue;
14110             }
14111 #ifdef CK_KERBEROS
14112             printf(" Keytab file:         %s\n",
14113                       k4_keytab ? k4_keytab : "(none)");
14114             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14115             if (krb_action < 0) {
14116                 p = "(none)";
14117             } else {
14118                 for (p = "", i = 0; i < krb_a_n; i++) {
14119                     if (krb_action == krb_a_tbl[i].kwval) {
14120                         p = krb_a_tbl[i].kwd;
14121                         break;
14122                     }
14123                 }
14124             }
14125             printf(" Action:              %s\n", p);
14126             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14127             printf(" Default lifetime     %d\n",krb4_d_lifetime);
14128             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14129             printf(" Lifetime:            %d (minutes)\n",krb4_init.lifetime);
14130             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14131             printf(" Default preauth:     %d\n",krb4_d_preauth);
14132             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14133             printf(" Preauth:             %d\n",krb4_init.preauth);
14134             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14135             printf(" Default principal:   \"%s\"\n",
14136                     krb4_d_principal ? krb4_d_principal : "");
14137             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14138             printf(" Principal:           \"%s\"\n",
14139                     krb4_init.principal ? krb4_init.principal : "");
14140             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14141             printf(" Default realm:       \"%s\"\n",
14142                     krb4_d_realm ? krb4_d_realm : "");
14143             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14144             printf(" Realm:               \"%s\"\n",
14145                     krb4_init.realm ? krb4_init.realm : "");
14146             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14147             printf(" Default instance:    \"%s\"\n",
14148                     krb4_d_instance ? krb4_d_instance : "");
14149             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14150             printf(" Instance:            \"%s\"\n",
14151                     krb4_init.instance ? krb4_init.instance : "");
14152             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14153             printf(" Auto-Get TGTs:       %d\n",krb4_autoget);
14154             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14155             printf(" Auto-Destroy TGTs:   %s\n",
14156                     krb4_autodel==KRB_DEL_NO?"never":
14157                     krb4_autodel==KRB_DEL_CL?"on-close":"on-exit");
14158             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14159             printf(" Check IP Addresses:  %d\n",krb4_checkaddrs);
14160             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14161 #ifdef COMMENT
14162             printf(" Password:    \"%s\"\n",
14163                     krb4_init.password  ? krb4_init.password  : "");
14164             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14165 #endif /* COMMENT */
14166 #endif /* CK_KERBEROS */
14167             printf("\n");
14168             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14169             break;
14170         case AUTHTYPE_KERBEROS_V5:
14171             kv = all ? AUTHTYPE_SSL : 0;
14172             if (ck_krb5_is_installed()) {
14173                 if (ck_gssapi_is_installed())
14174                     printf(" Authentication:      Kerberos 5 plus GSSAPI\n");
14175                 else
14176                     printf(" Authentication:      Kerberos 5\n");
14177                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14178             } else {
14179                 printf(" Authentication:      Kerberos 5 (not installed)\n");
14180                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14181                 continue;
14182             }
14183
14184 #ifdef CK_KERBEROS
14185             printf(" Cache file:          %s\n",
14186                     krb_op.cache ? krb_op.cache : "(none)");
14187             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14188             printf(" Default cache:       %s\n",
14189                     krb5_d_cc ? krb5_d_cc : "(none)");
14190             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14191             printf(" Keytab file:         %s\n",
14192                       k5_keytab ? k5_keytab : "(none)");
14193             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14194             if (krb_action < 0) {
14195                 p = "(none)";
14196             } else  {
14197                 for (p = "", i = 0; i < krb_a_n; i++) {
14198                     if (krb_action == krb_a_tbl[i].kwval) {
14199                         p = krb_a_tbl[i].kwd;
14200                         break;
14201                     }
14202                 }
14203             }
14204             printf(" Action:              %s\n", p);
14205             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14206
14207             printf(" Default forwardable  %d\n",krb5_d_forwardable);
14208             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14209             printf(" Forwardable:         %d\n",krb5_init.forwardable);
14210             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14211             printf(" Default lifetime     %d\n",krb5_d_lifetime);
14212             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14213             printf(" Lifetime:            %d (minutes)\n",krb5_init.lifetime);
14214             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14215             printf(" Postdate:            \"%s\"\n",
14216                     krb5_init.postdate ? krb5_init.postdate: "");
14217             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14218             printf(" Default proxiable:   %d\n",krb5_d_proxiable);
14219             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14220             printf(" Proxiable:           %d\n",krb5_init.proxiable);
14221             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14222             printf(" Renew:               %d\n",krb5_init.renew);
14223             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14224             printf(" Default renewable:   %d (minutes)\n",krb5_d_renewable);
14225             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14226             printf(" Renewable:           %d (minutes)\n",krb5_init.renewable);
14227             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14228             printf(" Service:             \"%s\"\n",
14229                     krb5_init.service ? krb5_init.service : "");
14230             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14231             printf(" Validate:            %d\n",krb5_init.validate);
14232             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14233             printf(" Default principal:   \"%s\"\n",
14234                     krb5_d_principal ? krb5_d_principal : "");
14235             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14236             printf(" Principal:           \"%s\"\n",
14237                     krb5_init.principal ? krb5_init.principal : "");
14238             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14239             printf(" Default instance:    \"%s\"\n",
14240                     krb5_d_instance ? krb5_d_instance : "");
14241             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14242             printf(" Default realm:       \"%s\"\n",
14243                     krb5_d_realm ? krb5_d_realm : "");
14244             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14245             printf(" Realm:               \"%s\"\n",
14246                     krb5_init.realm ? krb5_init.realm : "");
14247             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14248             printf(" Auto-Get TGTs:       %d\n",krb5_autoget);
14249             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14250             printf(" Auto-Destroy TGTs:   %s\n",
14251                     krb5_autodel==KRB_DEL_NO?"never":
14252                     krb5_autodel==KRB_DEL_CL?"on-close":"on-exit");
14253             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14254             printf(" Default get K4 TGTs: %d\n",krb5_d_getk4);
14255             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14256             printf(" Get K4 TGTs: %d\n",krb5_init.getk4);
14257             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14258             printf(" Check IP Addresses:  %d\n",krb5_checkaddrs);
14259             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14260             printf(" No IP Addresses:  %d\n",krb5_d_no_addresses);
14261             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14262             printf(" IP-Addresses:        ");
14263             if (krb5_init.addrs && krb5_init.addrs[0]) {
14264                 for (i = 0; krb5_init.addrs[i]; i++) {
14265                     if (i)
14266                       printf(",");
14267                     printf("%s",krb5_init.addrs[i]);
14268                 }
14269             } else if (krb5_d_addrs[0]) {
14270                 for (i = 0;i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];i++) {
14271                     if (i)
14272                       printf(",");
14273                     printf("%s",krb5_d_addrs[i]);
14274                 }
14275             } else {
14276                 printf("(use default)");
14277             }
14278             printf("\n");
14279             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14280 #ifdef COMMENT
14281             printf(" Password:            \"%s\"\n",
14282                     krb5_init.password  ? krb5_init.password  : "");
14283             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14284 #endif /* COMMENT */
14285 #endif /* CK_KERBEROS */
14286             printf("\n");
14287             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14288             break;
14289 #ifdef CK_SSL
14290           case AUTHTYPE_SSL:
14291             kv = all ? AUTHTYPE_SRP : 0;
14292             if (ck_ssleay_is_installed()) {
14293                 printf(" Authentication:      SSL/TLS (%s)\n",
14294                         SSLeay_version(SSLEAY_VERSION));
14295                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14296             } else {
14297                 printf(" Authentication:      SSL/TLS (not installed)\n");
14298                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14299                 continue;
14300             }
14301             printf(" RSA Certs file: %s\n",ssl_rsa_cert_file?
14302                   ssl_rsa_cert_file:"(none)");
14303             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14304             printf(" RSA Certs Chain file: %s\n",ssl_rsa_cert_chain_file?
14305                   ssl_rsa_cert_chain_file:"(none)");
14306             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14307             printf(" RSA Key file: %s\n",ssl_rsa_key_file?
14308                   ssl_rsa_key_file:"(none)");
14309             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14310             printf(" DSA Certs file: %s\n",ssl_dsa_cert_file?
14311                   ssl_dsa_cert_file:"(none)");
14312             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14313             printf(" DSA Certs Chain file: %s\n",ssl_dsa_cert_chain_file?
14314                   ssl_dsa_cert_chain_file:"(none)");
14315             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14316             printf(" DH Key file: %s\n",ssl_dh_key_file?
14317                   ssl_dh_key_file:"(none)");
14318             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14319             printf(" DH Param file: %s\n",ssl_dh_param_file?
14320                   ssl_dh_param_file:"(none)");
14321             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14322             printf(" CRL file: %s\n",ssl_crl_file?
14323                   ssl_crl_file:"(none)");
14324             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14325             printf(" CRL dir: %s\n",ssl_crl_dir?
14326                     ssl_crl_dir:"(none)");
14327             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14328             printf(" Random file: %s\n",ssl_rnd_file?
14329                   ssl_rnd_file:"(none)");
14330             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14331             printf(" Verify file: %s\n",ssl_verify_file?
14332                   ssl_verify_file:"(none)");
14333             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14334             printf(" Verify dir: %s\n",ssl_verify_dir?
14335                   ssl_verify_dir:"(none)");
14336             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14337             printf(" Cipher list: %s\n",ssl_cipher_list ? ssl_cipher_list : 
14338                     DEFAULT_CIPHER_LIST);
14339             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14340             if (ssl_con == NULL) {
14341                 SSL_library_init();
14342                 ssl_ctx = (SSL_CTX *)
14343                   SSL_CTX_new((SSL_METHOD *)TLSv1_method());
14344                 if (ssl_ctx != NULL)
14345                   ssl_con= (SSL *) SSL_new(ssl_ctx);
14346             }
14347             if (ssl_con != NULL) {
14348                 CHAR * p = NULL;
14349                 int i;
14350
14351                 for (i = 0; ; i++) {
14352                     p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
14353                     if (p == NULL)
14354                       break;
14355                     printf("    %s\n",p);
14356                     if (++n > cmd_rows - 3)
14357                         if (!askmore()) return(0); else n = 0;
14358                 }
14359             }
14360             printf(" Certs OK? %s\n",ssl_certsok_flag? "yes" : "no");
14361             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14362             printf(" Debug mode: %s\n", ssl_debug_flag ? "on" : "off");
14363             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14364             printf(" Verbose mode: %s\n", ssl_verbose_flag ? "on" : "off");
14365             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14366             printf(" Verify mode: %s\n",
14367                     ssl_verify_flag == SSL_VERIFY_NONE ? "none" :
14368                     ssl_verify_flag == SSL_VERIFY_PEER ? "peer-cert" :
14369                     "fail-if-no-peer-cert");
14370             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14371             printf(" SSL only? %s\n", ssl_only_flag ? "yes" : "no");
14372             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14373             printf(" TLS only? %s\n", tls_only_flag ? "yes" : "no");
14374             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14375 #endif /* CK_SSL */
14376             break;
14377           case AUTHTYPE_NTLM:
14378             kv = 0;
14379             if (ck_ntlm_is_installed()) {
14380                 printf(" Authentication:      NTLM\n");
14381                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14382                 printf(" No options\n");
14383                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14384             } else {
14385                 printf(" Authentication:      NTLM (not installed)\n");
14386                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14387                 continue;
14388             }
14389             printf("\n");
14390             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14391             break;
14392           case AUTHTYPE_SRP:
14393             kv = all ? AUTHTYPE_NTLM : 0;
14394             if (ck_srp_is_installed()) {
14395                 if (ck_krypto_is_installed())
14396                     printf(" Authentication:      SRP plus Krypto API\n");
14397                 else
14398                     printf(" Authentication:      SRP\n");
14399                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14400                 printf(" No options\n");
14401                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14402             } else {
14403                 printf(" Authentication:      SRP (not installed)\n");
14404                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14405                 continue;
14406             }
14407             printf("\n");
14408             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14409             break;
14410         }
14411     }
14412     return(success = 1);
14413 }
14414 #endif /* CK_AUTHENTICATION */
14415 #endif /* NOSHOW */
14416
14417 #ifdef CK_KERBEROS
14418
14419 /*  C P _ A U T H  --  AUTHENTICATE command parsing  */
14420
14421 int
14422 cp_auth() {                             /* Command_Parse AUTHENTICATE */
14423     int c, i, n;                        /* Workers */
14424     int rc = 0;                         /* Return code */
14425     int getval;                         /* Parsing helpers */
14426     int tmpauth = 0;                    /* Temporary authentication type */
14427     int kv = 0;                         /* Temporary Kerberos version */
14428     int tmp_action = -1;                /* Temporary Kerberos action */
14429     int tmp_klc = 0;                    /* Temporary list-credentials */
14430     char tmphlp[256];                   /* For building help message */
14431     char * p;
14432     char * tmppswd  = NULL;             /* Password */
14433     char * tmpprinz = NULL;             /* Principal */
14434     char * tmprealm = NULL;             /* Realm */
14435     char * tmpcache = NULL;             /* Cache file */
14436     char * tmpinst  = NULL;             /* K4 Instance */
14437     char * tmpaddrs[KRB5_NUM_OF_ADDRS];
14438 #ifdef CK_RECALL
14439     extern int on_recall;               /* around Password prompting */
14440 #endif /* CK_RECALL */
14441     struct stringint pv[KRB_I_MAX+1];   /* Temporary array for switch values */
14442     struct FDB kw, sw, fl;              /* FDBs for each parse function */
14443
14444     krb_action = -1;                    /* Initialize Kerberos action. */
14445     tmp_action = -1;                    /* And our local copy. */
14446     for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
14447       tmpaddrs[i] = NULL;
14448
14449     if ((y = cmkey(kerbtab,kerbtabn,"authentication type","",xxstring)) < 0)
14450       {
14451           if (y == -3)
14452             printf("?Authentication type not specified - nothing happens\n");
14453           return(y);
14454       }
14455     tmpauth = y;
14456     debug(F101,"kerberos authentication","",tmpauth);
14457     switch (tmpauth) {
14458       case AUTH_KRB4: kv = 4; break;    /* Don't assume values are the same */
14459       case AUTH_KRB5: kv = 5; break;
14460       default:
14461         printf("?Authentication type not supported: \"%s\"\n",atmbuf);
14462         return(-9);
14463     }
14464
14465     /* From here down is Kerberos */
14466     ini_kerb();                         /* Reset Init data to defaults */
14467
14468     if (kv == 4) {                      /* Set K4 defaults */
14469         if (krb4_d_realm)
14470           makestr(&tmprealm,krb4_d_realm);
14471         if (krb4_d_principal)
14472           makestr(&tmpprinz,krb4_d_principal);
14473         if (krb4_d_instance)
14474           makestr(&tmpinst,krb4_d_instance);
14475     } else if (kv == 5) {               /* Set K5 defaults */
14476         if (krb5_d_cc)
14477           makestr(&tmpcache,krb5_d_cc);
14478         if (krb5_d_realm)
14479           makestr(&tmprealm,krb5_d_realm);
14480         if (krb5_d_principal)
14481           makestr(&tmpprinz,krb5_d_principal);
14482         if (krb5_d_instance)
14483           makestr(&tmpinst,krb5_d_instance);
14484     }
14485     for (i = 0; i <= KRB_I_MAX; i++) {  /* Initialize switch values */
14486         pv[i].sval = NULL;              /* to null pointers */
14487         pv[i].ival = 0;                 /* and 0 int values */
14488         pv[i].wval = (CK_OFF_T)-1;      /* and -1 wide values */
14489     }
14490     if (kv == 4) {                      /* Kerberos 4 */
14491         pv[KRB_I_LF].ival = krb4_d_lifetime;
14492         pv[KRB_I_PA].ival = krb4_d_preauth;
14493
14494         if ((n = cmkey(krb_a_tbl,krb_a_n,"Kerberos 4 action","",xxstring)) < 0)
14495           {
14496               if (n == -3)
14497                 printf("?Action not specified - nothing happens.\n");
14498               return(n);
14499           }
14500     } else if (kv == 5) {               /* Kerberos 5 */
14501         pv[KRB_I_FW].ival = krb5_d_forwardable;
14502         pv[KRB_I_PR].ival = krb5_d_proxiable;
14503         pv[KRB_I_LF].ival = krb5_d_lifetime;
14504         pv[KRB_I_RB].ival = krb5_d_renewable;
14505         pv[KRB_I_K4].ival = krb5_d_getk4;
14506         pv[KRB_I_NAD].ival = krb5_d_no_addresses;
14507
14508         /* Make help message that shows switches and action keywords */
14509         ckstrncpy(tmphlp,"Kerberos 5 action, one of the following:\n ",256);
14510         for (i = 0; i < krb_a_n; i++) {
14511             ckstrncat(tmphlp,krb_a_tbl[i].kwd,sizeof(tmphlp));
14512             if (i == krb_a_n - 1)
14513               ckstrncat(tmphlp,"\nor switch",sizeof(tmphlp));
14514             else
14515               ckstrncat(tmphlp,"   ",sizeof(tmphlp));
14516         }
14517         /* Set up first set of chained FDB's */
14518
14519         cmfdbi(&sw,                     /* First FDB - command switches */
14520                _CMKEY,                  /* fcode */
14521                tmphlp,                  /* hlpmsg */
14522                "",                      /* default (none) */
14523                "",                      /* addtl string data */
14524                krb_s_n,                 /* Switch table size */
14525                4,                       /* addtl numeric data 2: 4 = cmswi */
14526                xxstring,                /* Processing function */
14527                krb_s_tbl,               /* Switch table */
14528                &kw                      /* Pointer to next FDB */
14529                );
14530         cmfdbi(&kw,                     /* Second FDB - action keywords */
14531                _CMKEY,                  /* fcode */
14532                "Kerberos action",       /* hlpmsg */
14533                "",                      /* default (none) */
14534                "",                      /* addtl string data */
14535                krb_a_n,                 /* Switch table size */
14536                0,                       /* addtl num data (0 = NOT switch) */
14537                xxstring,                /* Processing function */
14538                krb_a_tbl,               /* Keyword table */
14539                NULL                     /* Pointer to next FDB (none) */
14540                );
14541
14542         /* Parse */
14543
14544         while (1) {                     /* Parse 0 or more switches */
14545             rc = cmfdb(&sw);            /* Parse something */
14546             debug(F101,"kerberos cmfdb 1 rc","",rc);
14547             if (rc < 0) {                       /* Error */
14548                 if (rc == -3)
14549                   printf("?Action not specified - nothing happens.\n");
14550                 return(rc);             /* or reparse needed */
14551             }
14552             if (cmresult.fdbaddr != &sw) /* Break out if not a switch */
14553               break;
14554             c = cmgbrk();               /* Have switch - get break character */
14555             getval = (c == ':' || c == '='); /* Must parse an agument? */
14556             if (getval && !(cmresult.kflags & CM_ARG)) {
14557                 printf("?This switch does not take arguments\n");
14558                 return(-9);             /* OK because nothing malloc'd yet */
14559             }
14560             if (!getval && (cmgkwflgs() & CM_ARG)) {
14561                 printf("?This switch requires an argument\n");
14562                 return(-9);
14563             }
14564             n = cmresult.nresult;       /* Numeric result = switch value */
14565             debug(F101,"kerberos command switch","",n);
14566
14567             switch (n) {                /* Handle the switch */
14568               case KRB_S_CA:            /* /CACHE:<filename> */
14569                 p = krb5_d_cc ? krb5_d_cc : "";
14570                 if ((y = cmofi("Name of cache file",p,&s,xxstring)) < 0) {
14571                     if (y == -3)
14572                       s = NULL;
14573                     else
14574                       return(y);
14575                 }
14576                 makestr(&tmpcache,s);
14577                 break;
14578               default:
14579                 printf("?Unexpected switch value - internal error\n");
14580                 return(-9);             /* (if) nothing malloc'd yet. */
14581             }
14582         }
14583         if (cmresult.fdbaddr != &kw) {  /* Checking... */
14584             printf("?Unexpected result - internal error\n");
14585             return(-9);                 /* Nothing malloc'd yet. */
14586         }
14587         n = cmresult.nresult;           /* Get keyword value */
14588     } else {
14589         printf("?Unexpected Kerberos version - Internal error\n");
14590         return(-9);
14591     }
14592     debug(F101,"kerberos action","",n);
14593     switch (n) {
14594       case KRB_A_IN:                    /* INITIALIZE */
14595       case KRB_A_DE:                    /* DESTROY */
14596       case KRB_A_LC:                    /* LIST-CREDENTIALS */
14597         tmp_action = n;                 /* OK, set */
14598         break;
14599       default:                          /* Not OK, punt. */
14600         printf("?Unexpected action - internal error\n");
14601         return(-9);
14602     }
14603     if (tmp_action == KRB_A_IN) {       /* Action is INITIALIZE */
14604         int x;
14605         cmfdbi(&sw,                     /* INITIALIZE switches */
14606                _CMKEY,                  /* fcode */
14607                "Principal,\n or optional INITIALIZE switch(es)", /* hlpmsg */
14608                "",                      /* default (none) */
14609                "",                      /* addtl string data */
14610                kv == 4 ?  krb4_i_n : krb5_i_n, /* Switch table size */
14611                4,                       /* addtl numeric data 2: 4 = cmswi */
14612                xxstring,                /* Processing function */
14613                kv == 4 ?  krb4_i_tbl : krb5_i_tbl,      /* Switch table */
14614                &fl                      /* Pointer to next FDB */
14615                );
14616         cmfdbi(&fl,                     /* 3rd FDB - command to send from */
14617                _CMFLD,                  /* fcode */
14618                "Principal",             /* hlpmsg */
14619                kv == 4 ? krb4_d_principal : krb5_d_principal, /* principal */
14620                "",                      /* addtl string data */
14621                0,                       /* addtl numeric data 1 */
14622                0,                       /* addtl numeric data 2 */
14623                xxstring,
14624                NULL,
14625                NULL
14626                );
14627         while (1) {                     /* Parse INIT switches or principal */
14628             rc = cmfdb(&sw);
14629             debug(F101,"kerberos cmfdb 2 rc","",rc);
14630             if (rc < 0) {
14631                 if (rc == -3)
14632                   printf("?Principal name required\n");
14633                 goto kerbx;
14634             }
14635             debug(F101,"kerberos cmfdb 2 fcode","",cmresult.fcode);
14636             if (cmresult.fcode != _CMKEY) /* Not a switch, quit switch loop */
14637               break;
14638             c = cmgbrk();               /* Switch - get break character */
14639             debug(F101,"kerberos cmfdb 2 cmgbrk","",c);
14640             getval = (c == ':' || c == '=');
14641             if (getval && !(cmresult.kflags & CM_ARG)) {
14642                 printf("?This switch does not take arguments\n");
14643                 return(-9);             /* OK because nothing malloc'd yet */
14644             }
14645             if (!getval && (cmgkwflgs() & CM_ARG)) {
14646                 printf("?This switch requires an argument\n");
14647                 return(-9);
14648             }
14649             n = cmresult.nresult;       /* Numeric result = switch value */
14650             switch (n) {
14651               /* These don't take args... */
14652               case KRB_I_PA:            /* /PREAUTH */
14653               case KRB_I_FW:            /* /FORWARDABLE */
14654               case KRB_I_PR:            /* /PROXIABLE */
14655               case KRB_I_RN:            /* /RENEW */
14656               case KRB_I_VA:            /* /VALIDATE */
14657               case KRB_I_NPA:           /* /NOT-PREAUTH */
14658               case KRB_I_NFW:           /* /NOT-FORWARDABLE */
14659               case KRB_I_NPR:           /* /NOT-PROXIABLE */
14660               case KRB_I_VB:            /* /VERBOSE */
14661               case KRB_I_BR:            /* /BRIEF */
14662               case KRB_I_K4:            /* /KERBEROS4 */
14663               case KRB_I_NK4:           /* /NO-KERBEROS4 */
14664               case KRB_I_POP:           /* /POPUP */
14665               case KRB_I_NAD:           /* /NO-ADDRESSES */
14666                 if (getval) {
14667                     printf("?This switch does not take a value\n");
14668                     rc = -9;
14669                     goto kerbx;
14670                 }
14671                 switch (n) {
14672                   case KRB_I_NPA:
14673                     pv[KRB_I_PA].ival = 0;
14674                     break;
14675                   case KRB_I_NFW:
14676                     pv[KRB_I_FW].ival = 0;
14677                     break;
14678                   case KRB_I_NPR:
14679                     pv[KRB_I_PR].ival = 0;
14680                     break;
14681                   case KRB_I_VB:
14682                     pv[KRB_I_BR].ival = 0;
14683                     break;
14684                   case KRB_I_NK4:
14685                     pv[KRB_I_K4].ival = 0;
14686                     break;
14687                   default:
14688                     pv[n].ival = 1;
14689                 }
14690                 break;
14691
14692                 /* These do take arguments */
14693
14694               case KRB_I_RB:            /* /RENEWABLE:<minutes> */
14695                 pv[n].ival = 0;
14696                 if (!getval) break;
14697                 if ((rc = cmnum("Minutes",ckitoa(krb5_init.renewable),
14698                                 10,&y, xxstring)) < 0)
14699                   goto kerbx;
14700                 pv[n].ival = y;
14701                 break;
14702
14703               case KRB_I_LF:            /* /LIFETIME:<minutes> */
14704                 pv[n].ival = 0;
14705                 /* Default is previous value */
14706                 sprintf(tmpbuf,"%d",    /* SAFE */
14707                         kv == 4 ?
14708                         krb4_init.lifetime :
14709                         krb5_init.lifetime
14710                         );
14711                 if (!getval) break;
14712                 if ((rc = cmnum("Minutes",tmpbuf,10,&y, xxstring)) < 0)
14713                   goto kerbx;
14714                 pv[n].ival = y;
14715                 break;
14716
14717               case KRB_I_PD:            /* /POSTDATE:<timestamp> */
14718                 if (pv[n].sval) {
14719                     free(pv[n].sval);
14720                     pv[n].sval = NULL;
14721                 }
14722                 if (!getval) break;
14723                 if ((rc = cmdate("date-time","",&s,0,xxstring)) < 0)
14724                   goto kerbx;
14725                 makestr(&(pv[n].sval),s);
14726                 break;
14727
14728               case KRB_I_SR:            /* /SERVICE:<name> */
14729                 if (pv[n].sval) {
14730                     free(pv[n].sval);
14731                     pv[n].sval = NULL;
14732                 }
14733                 if (!getval) break;
14734                 if ((rc = cmfld("Service-name","",&s,xxstring)) < 0)
14735                   goto kerbx;
14736                 makestr(&(pv[n].sval),s);
14737                 break;
14738
14739               case KRB_I_RL:            /* /REALM:<name> */
14740                 if (pv[n].sval) {
14741                     free(pv[n].sval);
14742                     pv[n].sval = NULL;
14743                 }
14744                 if (!getval) break;
14745                 if (kv == 4)
14746                   p = krb4_d_realm ? krb4_d_realm : "";
14747                 else
14748                   p = krb5_d_realm ? krb5_d_realm : "";
14749                 if ((rc = cmfld("Realm",p,&s,xxstring)) < 0)
14750                   goto kerbx;
14751                 makestr(&(pv[n].sval),s);
14752                 break;
14753
14754               case KRB_I_IN:            /* /INSTANCE:<name> */
14755                 if (pv[n].sval) {
14756                     free(pv[n].sval);
14757                     pv[n].sval = NULL;
14758                 }
14759                 if (!getval) break;
14760                 if (kv == 4)
14761                     p = krb4_d_instance ? krb4_d_instance : "";
14762                 else
14763                     p = krb5_d_instance ? krb5_d_instance : "";
14764                 if ((rc = cmfld("Instance",p,&s,xxstring)) < 0)
14765                   goto kerbx;
14766                 makestr(&(pv[n].sval),s);
14767                 break;
14768
14769               case KRB_I_PW:            /* /PASSWORD:<password> */
14770                 debok = 0;
14771                 if (pv[n].sval) {
14772                     free(pv[n].sval);
14773                     pv[n].sval = NULL;
14774                 }
14775                 if (!getval) break;
14776                 if ((rc = cmfld("Password","",&s,xxstring)) < 0)
14777                   if (rc != -3)
14778                     goto kerbx;
14779                 makestr(&(pv[n].sval),s);
14780                 break;
14781
14782               case KRB_I_ADR:           /* /ADDRESSES:{<address-list>} */
14783                 if (pv[n].sval) {
14784                     free(pv[n].sval);
14785                     pv[n].sval = NULL;
14786                 }
14787                 if (!getval) break;
14788                 if ((rc = cmfld("List of IP addresses","",&s,xxstring)) < 0)
14789                   goto kerbx;
14790                 makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
14791                 for (i = 0; i < KRB5_NUM_OF_ADDRS && tmpaddrs[i]; i++) {
14792                     if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
14793                         printf("invalid ip address: %s\n",tmpaddrs[i]);
14794                         rc = -9;
14795                         goto kerbx;
14796                     }
14797                 }
14798                 pv[KRB_I_NAD].ival = 0;
14799                 break;
14800
14801               default:
14802                 printf("?Unexpected switch value - internal error\n");
14803                 rc = -9;
14804                 goto kerbx;
14805             }
14806         }
14807         if (cmresult.fcode != _CMFLD) {
14808             printf("?Unexected result - internal error\n");
14809             rc = -9;
14810             goto kerbx;
14811         }
14812         /* cmresult.sresult may be of the form PRINCIPAL@REALM */
14813         i = ckindex("@",cmresult.sresult,0,0,0);
14814         if (i != 0) {
14815             makestr(&tmprealm,&cmresult.sresult[i]);
14816             cmresult.sresult[i-1] = '\0';
14817         }
14818         makestr(&tmpprinz,cmresult.sresult); /* Principal (user) */
14819
14820         if ((rc = cmcfm()) < 0) {       /* Now get confirmation */
14821             if (rc == -3) {
14822                 printf("?Principal name required\n");
14823             }
14824             goto kerbx;
14825         }
14826         if (!tmpprinz || !tmpprinz[0]) {
14827             printf("?Principal name required\n");
14828             goto kerbx;
14829         }
14830         if (!pv[KRB_I_RN].ival && !pv[KRB_I_VA].ival) {
14831             /* Don't use a password if Validating or Renewing */
14832             if (pv[KRB_I_PW].sval) {    /* If they gave a /PASSWORD switch */
14833                 makestr(&tmppswd,pv[KRB_I_PW].sval); /* use this value */
14834             }
14835 #ifdef COMMENT
14836             /* Password prompting has been moved to ck_krb[45]_initTGT() */
14837             else {                      /* Otherwise must prompt for it */
14838                 char prmpt[80];
14839                 if (pv[KRB_I_RL].sval)
14840                   sprintf(prmpt,"%s@%s's Password: ",
14841                           tmpprinz,pv[KRB_I_RL].sval);
14842                 else if (tmprealm)
14843                   sprintf(prmpt,"%s@%s's Password: ",
14844                           tmpprinz,tmprealm);
14845                 else
14846                   sprintf(prmpt,"%s's Password: ",tmpprinz);
14847 #ifdef OS2
14848                 if (pv[KRB_I_POP].ival) {
14849                     char passwd[80]="";
14850                     readpass(prmpt,passwd,80);
14851                     makestr(&tmppswd,passwd);
14852                     memset(passwd,0,80);
14853                 } else
14854 #endif /* OS2 */
14855                 {
14856 #ifdef CK_RECALL
14857                     on_recall = 0;
14858 #endif /* CK_RECALL */
14859                     cmsavp(psave,PROMPTL); /* Save old prompt */
14860                     cmsetp(prmpt);      /* Make new prompt */
14861                     concb((char)escape); /* Put console in cbreak mode */
14862                     cmini(0);           /* and no-echo mode */
14863                     /* Issue prompt if at top level */
14864                     if (pflag) prompt(xxstring);
14865                     cmres();            /* Reset the parser */
14866                     for (rc = -1; rc < 0; ) { /* Prompt till they answer */
14867                         /* Get a literal line of text */
14868                         rc = cmtxt("","",&s,NULL);
14869                         cmres();        /* Reset the parser again */
14870                     }
14871                     makestr(&tmppswd,s);
14872                     printf("\n");       /* Echo a CRLF */
14873                     cmsetp(psave);      /* Restore original prompt */
14874                 }
14875             }
14876             x = 0;                      /* Check for password */
14877             if (tmppswd)
14878               if (*tmppswd)
14879                 x = 1;
14880             if (!x) {
14881                 printf("?Password required\n");
14882                 goto kerbx;
14883             }
14884 #endif /* COMMENT */
14885         }
14886     } else if (kv == 5 && tmp_action == KRB_A_LC) { /* LIST-CREDENTIALS */
14887         tmp_klc = 0;
14888         while (1) {
14889             if ((x = cmkey(klctab,nklctab,"Switch","",xxstring)) < 0) {
14890                 if (x == -3) {
14891                     if ((rc = cmcfm()) < 0)
14892                       goto kerbx;
14893                     else
14894                       break;
14895                 } else {
14896                     rc = x;
14897                     goto kerbx;
14898                 }
14899             }
14900             tmp_klc |= x;
14901         }
14902     } else if ((rc = cmcfm()) < 0)      /* DESTROY, just confirm */
14903         goto kerbx;
14904
14905 /* Done - Move confirmed data to final locations */
14906
14907     krb_action = tmp_action;            /* Action requested */
14908     krb_op.version = kv;                /* Kerberos version */
14909     krb_op.cache = tmpcache;            /* Cache file */
14910     tmpcache = NULL;                    /* So we don't free it */
14911
14912     switch (krb_action) {
14913       case KRB_A_IN:                    /* INITIALIZE */
14914         if (kv == 5) {
14915             krb5_init.forwardable = pv[KRB_I_FW].ival;
14916             krb5_init.proxiable   = pv[KRB_I_PR].ival;
14917             krb5_init.lifetime    = pv[KRB_I_LF].ival;
14918             krb5_init.renew       = pv[KRB_I_RN].ival;
14919             krb5_init.renewable   = pv[KRB_I_RB].ival;
14920             krb5_init.validate    = pv[KRB_I_VA].ival;
14921
14922             /* Here we just reassign the pointers and then set them to NULL */
14923             /* so they won't be freed below. */
14924
14925             krb5_init.postdate = pv[KRB_I_PD].sval; pv[KRB_I_PD].sval = NULL;
14926             krb5_init.service  = pv[KRB_I_SR].sval; pv[KRB_I_SR].sval = NULL;
14927             if (pv[KRB_I_RL].sval) {
14928                 krb5_init.realm  = pv[KRB_I_RL].sval; pv[KRB_I_RL].sval = NULL;
14929             } else if (tmprealm) {
14930                 krb5_init.realm = tmprealm; tmprealm = NULL;
14931             }
14932             if (pv[KRB_I_IN].sval) {
14933                 krb5_init.instance = pv[KRB_I_IN].sval;
14934                 pv[KRB_I_IN].sval = NULL;
14935             } else if ( tmpinst ) {
14936                 krb5_init.instance = tmpinst;
14937                 tmpinst = NULL;
14938             }
14939             if (tmpprinz) {
14940                 krb5_init.principal = tmpprinz;
14941                 tmpprinz = NULL;
14942             }
14943             krb5_init.password = tmppswd;
14944             tmppswd = NULL;
14945
14946             krb5_init.getk4 = pv[KRB_I_K4].ival;
14947             if (krb5_init.getk4) {
14948                 krb4_init.lifetime = pv[KRB_I_LF].ival;
14949                 if (krb5_init.realm)
14950                     makestr(&krb4_init.realm,krb5_init.realm);
14951                 krb4_init.preauth  = krb4_d_preauth;
14952                 krb4_init.verbose  = pv[KRB_I_BR].ival ? 0 : 1;
14953                 if (krb5_init.principal)
14954                     makestr(&krb4_init.principal,krb5_init.principal);
14955                 if (krb5_init.principal)
14956                     makestr(&krb4_init.password,krb5_init.password);
14957             }
14958             krb5_init.no_addresses = pv[KRB_I_NAD].ival;
14959             if (tmpaddrs[0]) {
14960                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
14961                     if (krb5_init.addrs[i]) {
14962                         free(krb5_init.addrs[i]);
14963                         krb5_init.addrs[i] = NULL;
14964                     }
14965                     krb5_init.addrs[i] = tmpaddrs[i];
14966                     tmpaddrs[i] = NULL;
14967                 }
14968             }
14969         } else if (kv == 4) {           /* Same deal for Kerberos 4 */
14970             krb4_init.lifetime = pv[KRB_I_LF].ival;
14971             if (pv[KRB_I_RL].sval) {
14972                 krb4_init.realm  = pv[KRB_I_RL].sval;
14973                 pv[KRB_I_RL].sval = NULL;
14974             } else if ( tmprealm ) {
14975                 krb4_init.realm  = tmprealm;
14976                 tmprealm = NULL;
14977             }
14978             if (pv[KRB_I_IN].sval) {
14979                 krb4_init.instance = pv[KRB_I_IN].sval;
14980                 pv[KRB_I_IN].sval = NULL;
14981             } else if ( tmpinst ) {
14982                 krb4_init.instance = tmpinst;
14983                 tmpinst = NULL;
14984             }
14985             krb4_init.preauth  = pv[KRB_I_PA].ival;
14986             krb4_init.verbose  = pv[KRB_I_BR].ival ? 0 : 1;
14987
14988             if (tmpprinz) {
14989                 krb4_init.principal = tmpprinz;
14990                 tmpprinz = NULL;
14991             }
14992             krb4_init.password = tmppswd;
14993             tmppswd = NULL;
14994         }
14995         break;
14996       case KRB_A_LC:                    /* List Credentials */
14997         krb5_lc.encryption = tmp_klc & XYKLCEN;
14998         krb5_lc.flags = tmp_klc & XYKLCFL;
14999         krb5_lc.addr  = tmp_klc & XYKLCAD;
15000         break;
15001     }
15002
15003 /* Common exit - Free temporary storage */
15004
15005   kerbx:
15006     for (i = 0; i <= KRB_I_MAX; i++) {  /* Free malloc'd switch data */
15007         if (pv[i].sval)
15008           free(pv[i].sval);
15009     }
15010     for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
15011         if (tmpaddrs[i])
15012           free(tmpaddrs[i]);
15013     }
15014     if (tmpprinz) free(tmpprinz);       /* And these too. */
15015     if (tmppswd)  free(tmppswd);
15016     if (tmpcache) free(tmpcache);
15017     if (tmprealm) free(tmprealm);
15018     if (tmpinst)  free(tmpinst);
15019
15020     return(rc);                         /* Return the return code */
15021 }
15022 #endif /* CK_KERBEROS */
15023
15024 #ifdef CK_LOGIN
15025 int
15026 #ifdef CK_ANSIC
15027 ckxlogin(CHAR * userid, CHAR * passwd, CHAR * acct, int promptok)
15028 #else /* CK_ANSIC */
15029 ckxlogin(userid, passwd, acct, promptok)
15030   CHAR * userid; CHAR * passwd; CHAR * acct; int promptok;
15031 #endif /* CK_ANSIC */
15032 /* ckxlogin */ {
15033 #ifdef CK_RECALL
15034     extern int on_recall;               /* around Password prompting */
15035 #endif /* CK_RECALL */
15036 #ifdef COMMENT
15037     extern int guest;
15038 #endif /* COMMENT */
15039     int rprompt = 0;                    /* Restore prompt */
15040 #ifdef CKSYSLOG
15041     int savlog;
15042 #endif /* CKSYSLOG */
15043
15044     extern int what, srvcdmsg;
15045
15046     int x = 0, ok = 0, rc = 0;
15047     CHAR * _u = NULL, * _p = NULL, * _a = NULL;
15048
15049     debug(F111,"ckxlogin userid",userid,promptok);
15050     debug(F110,"ckxlogin passwd",passwd,0);
15051
15052     isguest = 0;                        /* Global "anonymous" flag */
15053
15054     if (!userid) userid = (CHAR *)"";
15055     if (!passwd) passwd = (CHAR *)"";
15056
15057     debug(F111,"ckxlogin userid",userid,what);
15058
15059 #ifdef CK_RECALL
15060     on_recall = 0;
15061 #endif /* CK_RECALL */
15062
15063 #ifdef CKSYSLOG
15064     savlog = ckxsyslog;                 /* Save and turn off syslogging */
15065 #endif /* CKSYSLOG */
15066
15067     if ((!*userid || !*passwd) &&       /* Need to prompt for missing info */
15068         promptok) {
15069         cmsavp(psave,PROMPTL);          /* Save old prompt */
15070         debug(F110,"ckxlogin saved",psave,0);
15071         rprompt = 1;
15072     }
15073     if (!*userid) {
15074         if (!promptok)
15075           return(0);
15076         cmsetp("Username: ");           /* Make new prompt */
15077         concb((char)escape);            /* Put console in cbreak mode */
15078         cmini(1);
15079
15080 /* Flush typeahead */
15081
15082 #ifdef IKS_OPTION
15083         debug(F101,
15084               "ckxlogin TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
15085               "",
15086               TELOPT_SB(TELOPT_KERMIT).kermit.me_start
15087               );
15088 #endif /* IKS_OPTION */
15089
15090         while (ttchk() > 0) {
15091             x = ttinc(0);
15092             debug(F101,"ckxlogin flush user x","",x);
15093             if (x < 0)
15094               doexit(GOOD_EXIT,0);      /* Connection lost */
15095 #ifdef TNCODE
15096             if (sstelnet) {
15097                 if (x == IAC) {
15098                     x = tn_doop((CHAR)(x & 0xff),ckxech,ttinc);
15099                     debug(F101,"ckxlogin user tn_doop","",x);
15100 #ifdef IKS_OPTION
15101                     debug(F101,
15102                       "ckxlogin user TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
15103                       "",
15104                       TELOPT_SB(TELOPT_KERMIT).kermit.me_start
15105                       );
15106 #endif /* IKS_OPTION */
15107
15108                     if (x < 0)
15109                       goto XCKXLOG;
15110                     switch (x) {
15111                       case 1: ckxech = 1; break; /* Turn on echoing */
15112                       case 2: ckxech = 0; break; /* Turn off echoing */
15113 #ifdef IKS_OPTION
15114                       case 4:                    /* IKS event */
15115                         if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
15116                           break;                 /* else fall thru... */
15117 #endif /* IKS_OPTION */
15118                       case 6:                    /* Logout */
15119                         goto XCKXLOG;
15120                     }
15121                 }
15122             }
15123 #endif /* TNCODE */
15124         }
15125         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
15126         cmres();                        /* Reset the parser */
15127         for (x = -1; x < 0;) {          /* Prompt till they answer */
15128             /* Get a literal line of text */
15129             x=cmtxt("Your username, or \"ftp\", or \"anonymous\"","",&s,NULL);
15130             if (x == -4 || x == -10) {
15131                 printf("\r\n%sLogin cancelled\n",
15132                        x == -10 ? "Timed out: " : "");
15133 #ifdef CKSYSLOG
15134                 ckxsyslog = savlog;
15135 #endif /* CKSYSLOG */
15136                 doexit(GOOD_EXIT,0);
15137             }
15138             if (sstate)                 /* Did a packet come instead? */
15139               goto XCKXLOG;
15140             cmres();                    /* Reset the parser again */
15141         }
15142         if ((_u = (CHAR *)malloc((int)strlen(s) + 1)) == NULL) {
15143             printf("?Internal error: malloc\n");
15144             goto XCKXLOG;
15145         } else {
15146             strcpy((char *)_u,s);       /* safe */
15147             userid = _u;
15148         }
15149     }
15150     ok = zvuser((char *)userid);        /* Verify username */
15151     debug(F111,"ckxlogin zvuser",userid,ok);
15152
15153     if (!*passwd && promptok
15154 #ifdef COMMENT
15155         && guest
15156 #endif /* COMMENT */
15157         ) {
15158         char prmpt[80];
15159
15160 #ifdef CKSYSLOG
15161         savlog = ckxsyslog;             /* Save and turn off syslogging */
15162         ckxsyslog = 0;
15163 #endif /* CKSYSLOG */
15164
15165 /* Flush typeahead again */
15166
15167         while (ttchk() > 0) {
15168             x = ttinc(0);
15169             debug(F101,"ckxlogin flush user x","",x);
15170 #ifdef TNCODE
15171             if (sstelnet) {
15172                 if (x == IAC) {
15173                     x = tn_doop((CHAR)(x & 0xff),ckxech,ttinc);
15174                     debug(F101,"ckxlogin pass tn_doop","",x);
15175 #ifdef IKS_OPTION
15176                     debug(F101,
15177                       "ckxlogin pass TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
15178                       "",
15179                       TELOPT_SB(TELOPT_KERMIT).kermit.me_start
15180                       );
15181 #endif /* IKS_OPTION */
15182                     if (x < 0)
15183                       goto XCKXLOG;
15184                     switch (x) {
15185                       case 1: ckxech = 1; break; /* Turn on echoing */
15186                       case 2: ckxech = 0; break; /* Turn off echoing */
15187                       case 4:                    /* IKS event */
15188                         if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
15189                           break;                 /* else fall thru... */
15190                       case 6:                    /* Logout */
15191                         goto XCKXLOG;
15192                     }
15193                 }
15194             }
15195 #endif /* TNCODE */
15196         }
15197         if (!strcmp((char *)userid,"anonymous") ||
15198             !strcmp((char *)userid,"ftp")) {
15199             if (!ok)
15200               goto XCKXLOG;
15201             ckstrncpy(prmpt,"Enter e-mail address as Password: ",80);
15202         } else if (*userid && strlen((char *)userid) < 60) {
15203 #ifdef NT
15204             extern CHAR * pReferenceDomainName;
15205             if (pReferenceDomainName)
15206               ckmakxmsg(prmpt,
15207                        80,
15208                        "Enter ",
15209                        pReferenceDomainName,
15210                        "\\\\",
15211                        userid,
15212                        "'s Password: ",
15213                        NULL,NULL,NULL,NULL,NULL,NULL,NULL
15214                        );
15215             else
15216 #endif /* NT */
15217               ckmakmsg(prmpt,80,"Enter ",(char *)userid,"'s Password: ",NULL);
15218         } else
15219           ckstrncpy(prmpt,"Enter Password: ",80);
15220         cmsetp(prmpt);                  /* Make new prompt */
15221         concb((char)escape);            /* Put console in cbreak mode */
15222         if (strcmp((char *)userid,"anonymous") &&
15223             strcmp((char *)userid,"ftp")) { /* and if not anonymous */
15224             debok = 0;
15225             cmini(0);                   /* and no-echo mode */
15226         } else {
15227             cmini(1);
15228         }
15229         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
15230         cmres();                        /* Reset the parser */
15231         for (x = -1; x < 0;) {          /* Prompt till they answer */
15232 #ifdef CK_PAM
15233             gotemptypasswd=0;
15234 #endif /* CK_PAM */
15235             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
15236             if (x == -4 || x == -10) {
15237                 printf("\r\n%sLogin cancelled\n",
15238                        x == -10 ? "Timed out: " : "");
15239 #ifdef CKSYSLOG
15240                 ckxsyslog = savlog;
15241 #endif /* CKSYSLOG */
15242                 doexit(GOOD_EXIT,0);
15243             }
15244 #ifdef CK_PAM
15245             if (!*s)
15246               gotemptypasswd = 1;
15247 #endif /* CK_PAM */
15248             if (sstate)                 /* In case of a Kermit packet */
15249               goto XCKXLOG;
15250             cmres();                    /* Reset the parser again */
15251         }
15252         printf("\r\n");                 /* Echo a CRLF */
15253         if ((_p = (CHAR *)malloc((int)strlen(s) + 1)) == NULL) {
15254             printf("?Internal error: malloc\n");
15255             goto XCKXLOG;
15256         } else {
15257             strcpy((char *)_p,s);       /* safe */
15258             passwd = _p;
15259         }
15260     }
15261 #ifdef CK_PAM
15262     else {
15263         cmres();                        /* Reset the parser */
15264
15265         /* We restore the prompt now because the PAM engine will call  */
15266         /* readpass() which will overwrite psave. */
15267         if (rprompt) {
15268             cmsetp(psave);              /* Restore original prompt */
15269             debug(F110,"ckxlogin restored",psave,0);
15270             rprompt = 0;
15271         }
15272     }
15273 #endif /* CK_PAM */
15274
15275 #ifdef CKSYSLOG
15276     ckxsyslog = savlog;
15277 #endif /* CKSYSLOG */
15278
15279     if (ok) {
15280         ok = zvpass((char *)passwd);    /* Check password */
15281         debug(F101,"ckxlogin zvpass","",ok);
15282 #ifdef CK_PAM
15283     } else {
15284         /* Fake pam password failure for nonexistent users */
15285         sleep(1);
15286         printf("Authentication failure\n");
15287 #endif  /* CK_PAM */
15288     }
15289
15290     if (ok > 0 && isguest) {
15291 #ifndef NOPUSH
15292         nopush = 1;
15293 #endif /* NOPUSH */
15294         srvcdmsg = 1;
15295     }
15296     rc = ok;                            /* Set the return code */
15297     if ((char *)uidbuf != (char *)userid)
15298       ckstrncpy(uidbuf,(char *)userid,UIDBUFLEN); /* Remember username */
15299
15300   XCKXLOG:                              /* Common exit */
15301 #ifdef CKSYSLOG
15302     ckxsyslog = savlog;                 /* In case of GOTO above */
15303 #endif /* CKSYSLOG */
15304     if (rprompt) {
15305         cmsetp(psave);                  /* Restore original prompt */
15306         debug(F110,"ckxlogin restored",psave,0);
15307     }
15308     if (_u || _p || _a) {
15309         if (_u) free(_u);
15310         if (_p) free(_p);
15311         if (_a) free(_a);
15312     }
15313     return(rc);
15314 }
15315
15316 int
15317 ckxlogout() {
15318     doexit(GOOD_EXIT,0);                /* doexit calls zvlogout */
15319     return(0);                          /* not reached */
15320 }
15321 #endif /* CK_LOGIN */
15322
15323 #endif /* NOICP */