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, New York City
9     Jeffrey E Altman <jaltman@secure-endpoints.com>
10       Secure Endpoints Inc., New York City
11 
12   Copyright (C) 1985, 2020,
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
slrestor()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
seton(prm)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
setonaut(prm)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
setnum(prm,x,y,max)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
setcc(dflt,var)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("?Not valid here - '%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
dosort()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
bkupnum(s,i)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
showpurgopts()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
setpurgopts()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
dopurge()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
doxdis(which)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
setfil(rmsflg)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
doputenv(s1,s2)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
settrmtyp()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
setmsk()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 *
getiact()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
setlclcharset(x)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
setremcharset(x,z)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
setcmask(x)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
setautodl(x,y)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
seturlhl(int x)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
setaprint(int x)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
settrm()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
settitle(void)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
setdialer(void)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
setwin95(void)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
setprty(void)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
setbell()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
setmou(void)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 */
setsr(xx,rmsflg)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
setxmit()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
rmsg()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
remcfm()7156 remcfm() {
7157     int x = 0;
7158     char *s;
7159     char *helptxt = "> filename, | command,\n\
7160 or type carriage return to confirm the command";
7161     char c;
7162 
7163     remfile = 0;
7164     rempipe = 0;
7165     remappd = 0;
7166 
7167     if ((x = cmtxt(helptxt,"",&s,xxstring)) < 0) {
7168         return(x);
7169     }
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 
7207     if (!s) s = "";                     /* 2014-11-03 */
7208     if (!*s) return(1);                 /* 2014-11-03 */
7209 
7210     c = *s;                             /* We have something */
7211     if (c != '>' && c != '|') {         /* Is it > or | ? */
7212         printf("?Not confirmed\n");     /* No */
7213         return(-9);
7214     }
7215     s++;                                /* See what follows */
7216     if (c == '>' && *s == '>') {        /* Allow for ">>" too */
7217         s++;
7218         remappd = 1;                    /* Append to output file */
7219     }
7220     while (*s == SP || *s == HT) s++;   /* Strip intervening whitespace */
7221     if (!*s) {
7222         printf("?%s missing\n", c == '>' ? "Filename" : "Command");
7223         return(-9);
7224     }
7225     if (c == '>' && zchko(s) < 0) {     /* Check accessibility */
7226         printf("?Access denied - %s\n", s);
7227         return(-9);
7228     }
7229     remfile = 1;                        /* Set global results */
7230     rempipe = (c == '|');
7231     if (rempipe
7232 #ifndef NOPUSH
7233         && nopush
7234 #endif /* NOPUSH */
7235         ) {
7236         printf("?Sorry, access to external commands is disabled.\n");
7237         return(-9);
7238     }
7239     makestr(&remdest,s);
7240 #ifndef NODEBUG
7241     if (deblog) {
7242         debug(F101,"remcfm remfile","",remfile);
7243         debug(F101,"remcfm remappd","",remappd);
7244         debug(F101,"remcfm rempipe","",rempipe);
7245         debug(F110,"remcfm remdest",remdest, 0);
7246     }
7247 #endif /* NODEBUG */
7248     return(1);
7249 }
7250 
7251 /*  R E M T X T  --  Like remcfm()...  */
7252 /*
7253    ... but for REMOTE commands that end with cmtxt().
7254    Here we must decipher braces to discover whether the trailing
7255    redirection indicator is intended for local use, or to be sent out
7256    to the server, as in:
7257 
7258      remote host blah blah > file                 This end
7259      remote host { blah blah } > file             This end
7260      remote host { blah blah > file }             That end
7261      remote host { blah blah > file } > file      Both ends
7262 
7263    Pipes too:
7264 
7265      remote host blah blah | cmd                  This end
7266      remote host { blah blah } | cmd              This end
7267      remote host { blah blah | cmd }              That end
7268      remote host { blah blah | cmd } | cmd        Both ends
7269 
7270    Or both:
7271 
7272      remote host blah blah | cmd > file           This end, etc etc...
7273 
7274    Note: this really only makes sense for REMOTE HOST, but why be picky?
7275    Call after calling cmtxt(), with pointer to string that cmtxt() parsed,
7276    as in "remtxt(&s);".
7277 
7278    Returns:
7279     1 on success with braces & redirection things removed & pointer updated,
7280    -9 on failure (bad indirection), after printing error message.
7281 */
7282 int
remtxt(p)7283 remtxt(p) char ** p; {
7284     int i, x, bpos, ppos;
7285     char c, *s, *q;
7286 
7287     remfile = 0;                        /* Initialize global results */
7288     rempipe = 0;
7289     remappd = 0;
7290     if (remdest) {
7291         free(remdest);
7292         remdest = NULL;
7293     }
7294     s = *p;
7295     if (!s)                             /* No redirection indicator */
7296       s = "";
7297 #ifdef COMMENT
7298     if (!*s) {                          /* Ditto */
7299         if (!local &&
7300             (xzcmd == XZDIR || xzcmd == XZTYP ||
7301              xzcmd == XZXIT || xzcmd == XZSPA ||
7302              xzcmd == XZHLP || xzcmd == XZPWD ||
7303              xzcmd == XZLGI || xzcmd == XZLGO ||
7304              xzcmd == XZWHO || xzcmd == XZHOS)) {
7305             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
7306             if (hints) {
7307                 printf("Hint: Try again with an output redirector.\n");
7308             }
7309             return(-9);
7310         } else
7311           return(1);
7312     }
7313 #endif	/* COMMENT */
7314     bpos = -1;                          /* Position of > (bracket) */
7315     ppos = -1;                          /* Position of | (pipe) */
7316     x = strlen(s);                      /* Length of cmtxt() string */
7317 
7318     for (i = x-1; i >= 0; i--) {        /* Search right to left. */
7319         c = s[i];
7320         if (c == '}')                   /* Break on first right brace */
7321           break;                        /* Don't look at contents of braces */
7322         else if (c == '>')              /* Record position of > */
7323           bpos = i;
7324         else if (c == '|')              /* and of | */
7325           ppos = i;
7326     }
7327     if (bpos < 0 && ppos < 0) {         /* No redirectors. */
7328 #ifdef COMMENT
7329         if (!local &&
7330             (xzcmd == XZDIR || xzcmd == XZTYP ||
7331              xzcmd == XZXIT || xzcmd == XZSPA ||
7332              xzcmd == XZHLP || xzcmd == XZPWD ||
7333              xzcmd == XZLGI || xzcmd == XZLGO ||
7334              xzcmd == XZWHO || xzcmd == XZHOS)) {
7335             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
7336             if (hints) {
7337                 printf("Hint: Try again with an output redirector.\n");
7338             }
7339             return(-9);
7340         }
7341 #endif	/* COMMENT */
7342         s = brstrip(s);                 /* Remove outer braces if any. */
7343         *p = s;                         /* Point to result */
7344         return(1);                      /* and return. */
7345     }
7346     remfile = 1;                        /* It's | or > */
7347     i = -1;                             /* Get leftmost symbol */
7348     if (bpos > -1)                      /* Bracket */
7349       i = bpos;
7350     if (ppos > -1 && (ppos < bpos || bpos < 0)) { /* or pipe */
7351         i = ppos;
7352         rempipe = 1;
7353     }
7354     if (rempipe
7355 #ifndef NOPUSH
7356         && nopush
7357 #endif /* NOPUSH */
7358         ) {
7359         printf("?Sorry, access to external commands is disabled.\n");
7360         return(-9);
7361     }
7362     c = s[i];                           /* Copy of symbol */
7363 
7364     if (c == '>' && s[i+1] == '>')      /* ">>" for append? */
7365       remappd = 1;                     /* It's not just a flag it's a number */
7366 
7367     q = s + i + 1 + remappd;            /* Point past symbol in string */
7368     while (*q == SP || *q == HT) q++;   /* and any intervening whitespace */
7369     if (!*q) {
7370         printf("?%s missing\n", c == '>' ? "Filename" : "Command");
7371         return(-9);
7372     }
7373     if (c == '>' && zchko(q) < 0) {     /* (Doesn't work for | cmd > file) */
7374         printf("?Access denied - %s\n", q);
7375         return(-9);
7376     }
7377     makestr(&remdest,q);                /* Create the destination string */
7378     q = s + i - 1;                      /* Point before symbol */
7379     while (q > s && (*q == SP || *q == HT)) /* Strip trailing whitespace */
7380       q--;
7381     *(q+1) = NUL;                       /* Terminate the string. */
7382     s = brstrip(s);                     /* Remove any braces */
7383     *p = s;                             /* Set return value */
7384 
7385 #ifndef NODEBUG
7386     if (deblog) {
7387         debug(F101,"remtxt remfile","",remfile);
7388         debug(F101,"remtxt remappd","",remappd);
7389         debug(F101,"remtxt rempipe","",rempipe);
7390         debug(F110,"remtxt remdest",remdest, 0);
7391         debug(F110,"remtxt command",s,0);
7392     }
7393 #endif /* NODEBUG */
7394 
7395     return(1);
7396 }
7397 
7398 int
plogin(xx)7399 plogin(xx) int xx; {
7400     char *p1 = NULL, *p2 = NULL, *p3 = NULL;
7401     int psaved = 0, rc = 0;
7402 #ifdef CK_RECALL
7403     extern int on_recall;               /* around Password prompting */
7404 #endif /* CK_RECALL */
7405     debug(F101,"plogin local","",local);
7406 
7407     if (!local || (network && ttchk() < 0)) {
7408         printf("?No connection\n");
7409         return(-9);
7410     }
7411     if ((x = cmfld("User ID","",&s,xxstring)) < 0) { /* Get User ID */
7412         if (x != -3) return(x);
7413     }
7414     y = strlen(s);
7415     if (y > 0) {
7416         if ((p1 = malloc(y + 1)) == NULL) {
7417             printf("?Internal error: malloc\n");
7418             rc = -9;
7419             goto XZXLGI;
7420         } else
7421           strcpy(p1,s);                 /* safe */
7422         if ((rc = cmfld("Password","",&s,xxstring)) < 0)
7423           if (rc != -3) goto XZXLGI;
7424         y = strlen(s);
7425         if (y > 0) {
7426             if ((p2 = malloc(y + 1)) == NULL) {
7427                 printf("?Internal error: malloc\n");
7428                 rc = -9;
7429                 goto XZXLGI;
7430             } else
7431               strcpy(p2,s);             /* safe */
7432             if ((rc = cmfld("Account","",&s,xxstring)) < 0)
7433               if (rc != -3) goto XZXLGI;
7434             y = strlen(s);
7435             if (y > 0) {
7436                 if ((p3 = malloc(y + 1)) == NULL) {
7437                     printf("?Internal error: malloc\n");
7438                     rc = -9;
7439                     goto XZXLGI;
7440                 } else
7441                   strcpy(p3,s);         /* safe */
7442             }
7443         }
7444     }
7445     if ((rc = remtxt(&s)) < 0)          /* Confirm & handle redirectors */
7446       goto XZXLGI;
7447 
7448     if (!p1) {                          /* No Userid specified... */
7449         debok = 0;                      /* Don't log this */
7450         /* Prompt for username, password, and account */
7451 #ifdef CK_RECALL
7452         on_recall = 0;
7453 #endif /* CK_RECALL */
7454         cmsavp(psave,PROMPTL);          /* Save old prompt */
7455         psaved = 1;
7456         debug(F110,"REMOTE LOGIN saved",psave,0);
7457 
7458         cmsetp("Username: ");           /* Make new prompt */
7459         concb((char)escape);            /* Put console in cbreak mode */
7460         cmini(1);
7461         prompt(xxstring);
7462         rc = -9;
7463         for (x = -1; x < 0; ) {         /* Prompt till they answer */
7464             cmres();                    /* Reset the parser */
7465             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
7466         }
7467         y = strlen(s);
7468         if (y < 1) {
7469             printf("?Canceled\n");
7470             goto XZXLGI;
7471         }
7472         if ((p1 = malloc(y + 1)) == NULL) {
7473             printf("?Internal error: malloc\n");
7474             goto XZXLGI;
7475         } else
7476           strcpy(p1,s);                 /* safe */
7477 
7478         cmsetp("Password: ");           /* Make new prompt */
7479         concb((char)escape);            /* Put console in cbreak mode */
7480         cmini(0);                       /* No echo */
7481         prompt(xxstring);
7482         debok = 0;
7483         for (x = -1; x < 0 && x != -3; ) { /* Get answer */
7484             cmres();                    /* Reset the parser */
7485             x = cmtxt("","",&s,NULL);   /* Get literal line of text */
7486         }
7487         if ((p2 = malloc((int)strlen(s) + 1)) == NULL) {
7488             printf("?Internal error: malloc\n");
7489             goto XZXLGI;
7490         } else
7491           strcpy(p2,s);                 /* safe */
7492         printf("\r\n");
7493         if ((rc = cmcfm()) < 0)
7494           goto XZXLGI;
7495     }
7496     sstate = setgen('I',p1,p2,p3);      /* Get here with at least user ID */
7497     rc = 0;
7498 
7499   XZXLGI:                               /* Common exit point */
7500     if (psaved)
7501       cmsetp(psave);                    /* Restore original prompt */
7502     if (p3) { free(p3); p3 = NULL; }    /* Free malloc'd storage */
7503     if (p2) { free(p2); p2 = NULL; }
7504     if (p1) { free(p1); p1 = NULL; }
7505     if (rc > -1) {
7506         if (local && rc > -1)           /* If local, flush tty input buffer */
7507           ttflui();
7508     }
7509     return(rc);
7510 }
7511 
7512 #ifdef OS2
7513 #ifndef NOLOCAL
7514 int
dormt(xx)7515 dormt(xx) int xx; {
7516     int rc = 0;
7517     extern int term_io;
7518     int term_io_sav = term_io;
7519 #ifdef NEWFTP
7520     extern int ftpget, ftpisopen();
7521     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
7522       return(doftprmt(xx,0));
7523 #endif /* NEWFTP */
7524     term_io = 0;
7525     rc = xxdormt(xx);
7526     term_io = term_io_sav;
7527     return rc;
7528 }
7529 
7530 
7531 int
xxdormt(xx)7532 xxdormt(xx) int xx;
7533 #else /* NOLOCAL */
7534 int
7535 dormt(xx) int xx;
7536 #endif /* NOLOCAL */
7537 #else /* OS2 */
7538 int
7539 dormt(xx) int xx;
7540 #endif /* OS2 */
7541 {                                       /* REMOTE commands */
7542     int x, y, retcode;
7543     char *s, sbuf[50], *s2;
7544 
7545 #ifdef NEWFTP
7546     extern int ftpget, ftpisopen();
7547     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
7548       return(doftprmt(xx,0));
7549 #endif /* NEWFTP */
7550 
7551     remfile = 0;                        /* Clear these */
7552     rempipe = 0;
7553     remappd = 0;
7554 
7555     debug(F101,"XXX xxdormt xx","",xx);
7556 
7557     if (xx < 0) return(xx);             /* REMOTE what? */
7558 
7559     xzcmd = xx;                         /* Make global copy of arg */
7560 
7561     if (xx == XZSET) {                  /* REMOTE SET */
7562         if ((y = cmkey(rmstab,nrms,"","",xxstring)) < 0) {
7563             if (y == -3) {
7564                 printf("?Parameter name required\n");
7565                 return(-9);
7566             } else return(y);
7567         }
7568         return(doprm(y,1));
7569     }
7570 
7571     switch (xx) {                       /* Others... */
7572 
7573       case XZCDU:
7574         if ((x = cmcfm()) < 0) return(x);
7575         printf("?Sorry, REMOTE CDUP not supported yet\n");
7576         return(-9);
7577 
7578       case XZCWD:                       /* CWD (CD) */
7579         if ((x = cmtxt("Remote directory name","",&s,xxstring)) < 0)
7580           return(x);
7581         if ((x = remtxt(&s)) < 0)
7582           return(x);
7583         debug(F111,"XZCWD: ",s,x);
7584         *sbuf = NUL;
7585         s2 = sbuf;
7586 /*
7587   The following is commented out because since the disappearance of the
7588   DECSYSTEM-20 from the planet, no known computer requires a password for
7589   changing directory.
7590 */
7591 #ifdef DIRPWDPR
7592         if (*s != NUL) {                /* If directory name given, */
7593                                         /* get password on separate line. */
7594             if (tlevel > -1) {          /* From take file... */
7595 
7596                 if (fgets(sbuf,50,tfile[tlevel]) == NULL)
7597                   fatal("take file ends prematurely in 'remote cwd'");
7598                 debug(F110," pswd from take file",s2,0);
7599                 for (x = (int)strlen(sbuf);
7600                      x > 0 && (sbuf[x-1] == NL || sbuf[x-1] == CR);
7601                      x--)
7602                   sbuf[x-1] = '\0';
7603 
7604             } else {                    /* From terminal... */
7605 
7606                 printf(" Password: ");  /* get a password */
7607 #ifdef IKSD
7608                 if (!local && inserver) {
7609                     x = coninc(0);
7610                 } else
7611 #endif /* IKSD */
7612 #ifdef OS2
7613                   x = is_a_tty(0) ? coninc(0) : /* with no echo ... */
7614                     getchar();
7615 #else /* OS2 */
7616                 x = getchar();
7617 #endif /* OS2 */
7618                 while ((x != NL) && (x != CR)) {
7619                     if ((x &= 0177) == '?') {
7620                         printf("? Password of remote directory\n Password: ");
7621                         s2 = sbuf;
7622                         *sbuf = NUL;
7623                     } else if (x == ESC) /* Mini command line editor... */
7624                       bleep(BP_WARN);
7625                     else if (x == BS || x == 0177)
7626                       s2--;
7627                     else if (x == 025) {        /* Ctrl-U */
7628                         s2 = sbuf;
7629                         *sbuf = NUL;
7630                     } else
7631                       *s2++ = x;
7632 
7633                     /* Get the next character */
7634 #ifdef IKSD
7635                     if (!local && inserver) {
7636                         x = coninc(0);
7637                     } else
7638 #endif /* IKSD */
7639 #ifdef OS2
7640                     x = is_a_tty(0) ? coninc(0) : /* with no echo ... */
7641                       getchar();
7642 #else /* OS2 */
7643                     x = getchar();
7644 #endif /* OS2 */
7645                 }
7646                 *s2 = NUL;
7647                 putchar('\n');
7648             }
7649             s2 = sbuf;
7650         } else s2 = "";
7651 #endif /* DIRPWDPR */
7652 
7653         debug(F110," password",s2,0);
7654 	rcdactive = 1;
7655         sstate = setgen('C',s,s2,"");
7656         retcode = 0;
7657         break;
7658 
7659       case XZDEL:                               /* Delete */
7660         if ((x = cmtxt("Name of remote file(s) to delete",
7661                        "",&s,xxstring)) < 0) {
7662             if (x == -3) {
7663                 printf("?Name of remote file(s) required\n");
7664                 return(-9);
7665             } else return(x);
7666         }
7667         if ((x = remtxt(&s)) < 0)
7668           return(x);
7669         if (local) ttflui();            /* If local, flush tty input buffer */
7670         retcode = sstate = rfilop(s,'E');
7671         break;
7672 
7673       case XZDIR:                       /* Directory */
7674         if ((x = cmtxt("Remote directory or file specification","",&s,
7675                        xxstring)) < 0)
7676           return(x);
7677         if ((x = remtxt(&s)) < 0)
7678           return(x);
7679         if (local) ttflui();            /* If local, flush tty input buffer */
7680         rmsg();
7681         retcode = sstate = setgen('D',s,"","");
7682         break;
7683 
7684       case XZHLP:                       /* Help */
7685         if ((x = remcfm()) < 0) return(x);
7686         sstate = setgen('H',"","","");
7687         retcode = 0;
7688         break;
7689 
7690       case XZHOS:                       /* Host */
7691         if ((x = cmtxt("Command for remote system","",&s,xxstring)) < 0)
7692           return(x);
7693         if ((x = remtxt(&s)) < 0)
7694           return(x);
7695         if ((y = (int)strlen(s)) < 1)
7696           return(x);
7697         ckstrncpy(line,s,LINBUFSIZ);
7698         cmarg = line;
7699         rmsg();
7700         retcode = sstate = 'c';
7701         break;
7702 
7703 #ifndef NOFRILLS
7704       case XZKER:
7705         if ((x = cmtxt("Command for remote Kermit","",&s,xxstring)) < 0)
7706           return(x);
7707         if ((x = remtxt(&s)) < 0)
7708           return(x);
7709         if ((int)strlen(s) < 1)  {
7710             if (x == -3) {
7711                 printf("?Remote Kermit command required\n");
7712                 return(-9);
7713             } else return(x);
7714         }
7715         ckstrncpy(line,s,LINBUFSIZ);
7716         cmarg = line;
7717         retcode = sstate = 'k';
7718         rmsg();
7719         break;
7720 
7721       case XZLGI:                       /* Login */
7722 	rcdactive = 1;			/* Suppress "Logged in" msg if quiet */
7723         return(plogin(XXREM));
7724 
7725       case XZLGO: {                     /* Logout */
7726           extern int bye_active;
7727           if ((x = remcfm()) < 0) return(x);
7728           sstate = setgen('I',"","","");
7729           retcode = 0;
7730           bye_active = 1;               /* Close connection when done */
7731           break;
7732       }
7733 
7734       case XZPRI:                       /* Print */
7735         if (!atdiso || !atcapr) {       /* Disposition attribute off? */
7736             printf("?Disposition Attribute is Off\n");
7737             return(-2);
7738         }
7739         cmarg = "";
7740         cmarg2 = "";
7741         if ((x = cmifi("Local file(s) to print on remote printer","",&s,&y,
7742                        xxstring)) < 0) {
7743             if (x == -3) {
7744                 printf("?Name of local file(s) required\n");
7745                 return(-9);
7746             }
7747             return(x);
7748         }
7749         ckstrncpy(line,s,LINBUFSIZ);    /* Make a safe copy of filename */
7750         *optbuf = NUL;                  /* Wipe out any old options */
7751         if ((x = cmtxt("Options for remote print command","",&s,xxstring)) < 0)
7752           return(x);
7753         if ((x = remtxt(&s)) < 0)
7754           return(x);
7755         if ((int)strlen(optbuf) > 94) { /* Make sure this is legal */
7756             printf("?Option string too long\n");
7757             return(-9);
7758         }
7759         ckstrncpy(optbuf,s,OPTBUFLEN);  /* Make a safe copy of options */
7760         nfils = -1;                     /* Expand file list internally */
7761         cmarg = line;                   /* Point to file list. */
7762         rprintf = 1;                    /* REMOTE PRINT modifier for SEND */
7763         sstate = 's';                   /* Set start state to SEND */
7764         if (local) displa = 1;
7765         retcode = 0;
7766         break;
7767 #endif /* NOFRILLS */
7768 
7769       case XZSPA:                       /* Space */
7770         if ((x = cmtxt("Confirm, or remote directory name",
7771                        "",&s,xxstring)) < 0)
7772           return(x);
7773         if ((x = remtxt(&s)) < 0)
7774           return(x);
7775         retcode = sstate = setgen('U',s,"","");
7776         break;
7777 
7778       case XZMSG:                       /* Message */
7779         if ((x = cmtxt("Short text message for server","",&s,xxstring)) < 0)
7780           return(x);
7781         if ((x = remtxt(&s)) < 0)
7782           return(x);
7783         retcode = sstate = setgen('M',s,"","");
7784         break;
7785 
7786 #ifndef NOFRILLS
7787       case XZTYP:                       /* Type */
7788         if ((x = cmtxt("Remote file specification","",&s,xxstring)) < 0)
7789           return(x);
7790         if ((int)strlen(s) < 1) {
7791             printf("?Remote filename required\n");
7792             return(-9);
7793         }
7794         if ((x = remtxt(&s)) < 0)
7795           return(x);
7796         rmsg();
7797         retcode = sstate = rfilop(s,'T');
7798         break;
7799 #endif /* NOFRILLS */
7800 
7801 #ifndef NOFRILLS
7802       case XZWHO:
7803         if ((x = cmtxt("Remote user name, or carriage return",
7804                        "",&s,xxstring)) < 0)
7805           return(x);
7806         if ((x = remtxt(&s)) < 0)
7807           return(x);
7808         retcode = sstate = setgen('W',s,"","");
7809         break;
7810 #endif /* NOFRILLS */
7811 
7812       case XZPWD:                       /* PWD */
7813         if ((x = remcfm()) < 0) return(x);
7814         sstate = setgen('A',"","","");
7815         retcode = 0;
7816         break;
7817 
7818 #ifndef NOSPL
7819       case XZQUE: {                     /* Query */
7820           char buf[2];
7821           extern char querybuf[], * qbufp;
7822           extern int qbufn;
7823           if ((y = cmkey(vartyp,nvartyp,"","",xxstring)) < 0)
7824             return(y);
7825           if ((x = cmtxt(y == 'F' ? "Remote function invocation" :
7826                          ('K' ? "Remote variable name or function":
7827                          "Remote variable name"),
7828                          "",
7829                          &s,
7830                          (y == 'K') ? xxstring : NULL
7831                          )) < 0)        /* Don't evaluate */
7832             return(x);
7833           if ((x = remtxt(&s)) < 0)
7834             return(x);
7835           query = 1;                    /* QUERY is active */
7836           qbufp = querybuf;             /* Initialize query response buffer */
7837           qbufn = 0;
7838           querybuf[0] = NUL;
7839           buf[0] = (char) (y & 127);
7840           buf[1] = NUL;
7841           retcode = sstate = setgen('V',"Q",(char *)buf,s);
7842           break;
7843       }
7844 
7845       case XZASG: {                     /* Assign */
7846           char buf[VNAML];
7847           if ((y = cmfld("Remote variable name","",&s,NULL)) < 0) /* No eval */
7848             return(y);
7849           if ((int)strlen(s) >= VNAML) {
7850               printf("?Too long\n");
7851               return(-9);
7852           }
7853           ckstrncpy(buf,s,VNAML);
7854           if ((x = cmtxt("Assignment for remote variable",
7855                    "",&s,xxstring)) < 0) /* Evaluate this one */
7856             return(x);
7857           if ((x = remtxt(&s)) < 0)
7858             return(x);
7859 #ifdef COMMENT
7860 /*
7861   Server commands can't be long packets.  In principle there's no reason
7862   why they shouldn't be, except that we don't know at this point if the
7863   server is capable of accepting long packets because we haven't started
7864   the protocol yet.  In practice, allowing a long packet here breaks a lot
7865   of assumptions, causes buffer overruns and crashes, etc.  To be fixed
7866   later.  (But since this is commented out, evidently I fixed it later...)
7867 */
7868           if ((int)strlen(s) > 85) {    /* Allow for encoding expansion */
7869               printf("?Sorry, value is too long - 85 characters max\n");
7870               return(-9);
7871           }
7872 #endif /* COMMENT */
7873           retcode = sstate = setgen('V',"S",(char *)buf,s);
7874           break;
7875       }
7876 #endif /* NOSPL */
7877 
7878       case XZCPY: {                     /* COPY */
7879           char buf[TMPBUFSIZ];
7880           buf[TMPBUFSIZ-1] = '\0';
7881           if ((x = cmfld("Name of remote file to copy","",&s,xxstring)) < 0) {
7882               if (x == -3) {
7883                   printf("?Name of remote file required\n");
7884                   return(-9);
7885               }
7886               else
7887                 return(x);
7888           }
7889           ckstrncpy(buf,s,TMPBUFSIZ);
7890           if ((x = cmfld("Name of remote destination file or directory",
7891                          "",&s, xxstring)) < 0) {
7892               if (x == -3) {
7893                   printf("?Name of remote file or directory required\n");
7894                   return(-9);
7895               } else return(x);
7896           }
7897           ckstrncpy(tmpbuf,s,TMPBUFSIZ);
7898           if ((x = remcfm()) < 0)
7899             return(x);
7900           if (local) ttflui();          /* If local, flush tty input buffer */
7901           retcode = sstate = setgen('K',buf,tmpbuf,"");
7902           break;
7903       }
7904       case XZREN: {                     /* Rename */
7905           char buf[TMPBUFSIZ];
7906           buf[TMPBUFSIZ-1] = '\0';
7907           if ((x = cmfld("Name of remote file to rename",
7908                          "",&s,xxstring)) < 0) {
7909               if (x == -3) {
7910                   printf("?Name of remote file required\n");
7911                   return(-9);
7912               } else return(x);
7913           }
7914           ckstrncpy(buf,s,TMPBUFSIZ);
7915           if ((x = cmfld("New name of remote file","",&s, xxstring)) < 0) {
7916               if (x == -3) {
7917                   printf("?Name of remote file required\n");
7918                   return(-9);
7919               } else return(x);
7920           }
7921           ckstrncpy(tmpbuf,s,TMPBUFSIZ);
7922           if ((x = remcfm()) < 0)
7923             return(x);
7924           if (local) ttflui();          /* If local, flush device buffer */
7925           retcode = sstate = setgen('R',buf,tmpbuf,"");
7926           break;
7927       }
7928       case XZMKD:                       /* mkdir */
7929       case XZRMD:                       /* rmdir */
7930         if ((x = cmtxt((xx == XZMKD) ?
7931                        "Name of remote directory to create" :
7932                        "Name of remote directory to delete",
7933                        "",
7934                        &s,
7935                        xxstring
7936                        )) < 0) {
7937             if (x == -3) {
7938                 printf("?Name required\n");
7939                 return(-9);
7940             } else return(x);
7941         }
7942         if ((x = remtxt(&s)) < 0)
7943           return(x);
7944         if (local) ttflui();            /* If local, flush tty input buffer */
7945         retcode = sstate = rfilop(s, (char)(xx == XZMKD ? 'm' : 'd'));
7946         break;
7947 
7948       case XZXIT:                       /* Exit */
7949         if ((x = remcfm()) < 0) return(x);
7950         sstate = setgen('X',"","","");
7951         retcode = 0;
7952         break;
7953 
7954       default:
7955         if ((x = remcfm()) < 0) return(x);
7956         printf("?Not implemented - %s\n",cmdbuf);
7957         return(-2);
7958     }
7959     if (local && retcode > -1)          /* If local, flush tty input buffer */
7960       ttflui();
7961     return(retcode);
7962 }
7963 
7964 
7965 /*  R F I L O P  --  Remote File Operation  */
7966 
7967 CHAR
7968 #ifdef CK_ANSIC
rfilop(char * s,char t)7969 rfilop(char * s, char t)
7970 #else
7971 rfilop(s,t) char *s, t;
7972 #endif /* CK_ANSIC */
7973 /* rfilop */ {
7974     if (*s == NUL) {
7975         printf("?File specification required\n");
7976         return((CHAR) 0);
7977     }
7978     debug(F111,"rfilop",s,t);
7979     return(setgen(t,s,"",""));
7980 }
7981 #endif /* NOXFER */
7982 
7983 #ifdef ANYX25
7984 int
setx25()7985 setx25() {
7986     if ((y = cmkey(x25tab,nx25,"X.25 call options","",xxstring)) < 0)
7987       return(y);
7988     switch (y) {
7989       case XYUDAT:
7990         if ((z = cmkey(onoff,2,"X.25 call user data","",xxstring))
7991             < 0) return(z);
7992         if (z == 0) {
7993             if ((z = cmcfm()) < 0) return(z);
7994             cudata = 0;             /* disable call user data */
7995             return (success = 1);
7996         }
7997         if ((x = cmtxt("X.25 call user data string","",&s,xxstring)) < 0)
7998           return(x);
7999         if ((int)strlen(s) == 0) {
8000             return (-3);
8001         } else if ((int)strlen(s) > MAXCUDATA) {
8002             printf("?The length must be > 0 and <= %d\n",MAXCUDATA);
8003             return(-2);
8004         }
8005         if ((y = cmcfm()) < 0) return(y);
8006         ckstrncpy(udata,s,MAXCUDATA);
8007         cudata = 1;                     /* X.25 call user data specified */
8008         return (success = 1);
8009       case XYCLOS:
8010         if ((z = cmkey(onoff,2,"X.25 closed user group call","",xxstring))
8011             < 0) return(z);
8012         if (z == 0) {
8013             if ((z = cmcfm()) < 0) return(z);
8014             closgr = -1;                /* disable closed user group */
8015             return (success = 1);
8016         }
8017         if ((y = cmnum("0 <= cug index >= 99","",10,&x,xxstring)) < 0)
8018           return(y);
8019         if (x < 0 || x > 99) {
8020             printf("?The choices are 0 <= cug index >= 99\n");
8021             return(-2);
8022         }
8023         if ((y = cmcfm()) < 0) return(y);
8024         closgr = x;                     /* closed user group selected */
8025         return (success = 1);
8026 
8027       case XYREVC:
8028         if((z = cmkey(onoff,2,"X.25 reverse charge call","",xxstring)) < 0)
8029           return(z);
8030         if ((x = cmcfm()) < 0) return(x);
8031         revcall = z;
8032         return (success = 1);
8033     }
8034 }
8035 
8036 #ifndef IBMX25
8037 int
setpadp()8038 setpadp() {
8039     if ((y = cmkey(padx3tab,npadx3,"PAD X.3 parameter name","",xxstring)) < 0)
8040       return(y);
8041     x = y;
8042     switch (x) {
8043       case PAD_BREAK_CHARACTER:
8044         if ((y = cmnum("PAD break character value","",10,&z,xxstring)) < 0)
8045           return(y);
8046         if ((y = cmcfm()) < 0) return(y);
8047         break;
8048       case PAD_ESCAPE:
8049         if ((y = cmnum("PAD escape","",10,&z,xxstring)) < 0) return(y);
8050         if (z != 0 && z != 1) {
8051             printf("?The choices are 0 or 1\n");
8052             return(-2);
8053         }
8054         if ((y = cmcfm()) < 0) return(y);
8055         break;
8056       case PAD_ECHO:
8057         if ((y = cmnum("PAD echo","",10,&z,xxstring)) < 0) return(y);
8058         if (z != 0 && z != 1) {
8059             printf("?The choices are 0 or 1\n");
8060             return(-2);
8061         }
8062         if ((y = cmcfm()) < 0) return(y);
8063         break;
8064       case PAD_DATA_FORWARD_CHAR:
8065         if ((y = cmnum("PAD data forward char","",10,&z,xxstring)) < 0)
8066           return(y);
8067         if (z != 0 && z != 2) {
8068             printf("?The choices are 0 or 2\n");
8069             return(-2);
8070         }
8071         if ((y = cmcfm()) < 0) return(y);
8072         break;
8073       case PAD_DATA_FORWARD_TIMEOUT:
8074         if ((y = cmnum("PAD data forward timeout","",10,&z,xxstring)) < 0)
8075             return(y);
8076         if (z < 0 || z > 255) {
8077             printf("?The choices are 0 or 1 <= timeout <= 255\n");
8078             return(-2);
8079         }
8080         if ((y = cmcfm()) < 0) return(y);
8081         break;
8082       case PAD_FLOW_CONTROL_BY_PAD:
8083         if ((y = cmnum("PAD pad flow control","",10,&z,xxstring)) < 0)
8084           return(y);
8085         if (z != 0 && z != 1) {
8086             printf("?The choices are 0 or 1\n");
8087             return(-2);
8088         }
8089         if ((y = cmcfm()) < 0) return(y);
8090         break;
8091       case PAD_SUPPRESSION_OF_SIGNALS:
8092         if ((y = cmnum("PAD service","",10,&z,xxstring)) < 0) return(y);
8093         if (z != 0 && z != 1) {
8094             printf("?The choices are 0 or 1\n");
8095             return(-2);
8096         }
8097         if ((y = cmcfm()) < 0) return(y);
8098         break;
8099 
8100       case PAD_BREAK_ACTION:
8101         if ((y = cmnum("PAD break action","",10,&z,xxstring)) < 0) return(y);
8102         if (z != 0 && z != 1 && z != 2 && z != 5 && z != 8 && z != 21) {
8103             printf("?The choices are 0, 1, 2, 5, 8 or 21\n");
8104             return(-2);
8105         }
8106         if ((y = cmcfm()) < 0) return(y);
8107         break;
8108 
8109       case PAD_SUPPRESSION_OF_DATA:
8110         if ((y = cmnum("PAD data delivery","",10,&z,xxstring)) < 0) return(y);
8111         if (z != 0 && z != 1) {
8112             printf("?The choices are 0 or 1\n");
8113             return(-2);
8114         }
8115         if ((y = cmcfm()) < 0) return(y);
8116         break;
8117 
8118       case PAD_PADDING_AFTER_CR:
8119         if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
8120         if (z < 0 || z > 7) {
8121             printf("?The choices are 0 or 1 <= crpad <= 7\n");
8122             return(-2);
8123         }
8124         if ((y = cmcfm()) < 0) return(y);
8125         break;
8126 
8127       case PAD_LINE_FOLDING:
8128         if ((y = cmnum("PAD linefold","",10,&z,xxstring)) < 0) return(y);
8129         if (z < 0 || z > 255) {
8130             printf("?The choices are 0 or 1 <= linefold <= 255\n");
8131             return(-2);
8132         }
8133         if ((y = cmcfm()) < 0) return(y);
8134         break;
8135 
8136       case PAD_LINE_SPEED:
8137         if ((y = cmnum("PAD baudrate","",10,&z,xxstring)) < 0) return(y);
8138         if (z < 0 || z > 18) {
8139             printf("?The choices are 0 <= baudrate <= 18\n");
8140             return(-2);
8141         }
8142         if ((y = cmcfm()) < 0) return(y);
8143         break;
8144 
8145       case PAD_FLOW_CONTROL_BY_USER:
8146         if ((y = cmnum("PAD terminal flow control","",10,&z,xxstring)) < 0)
8147             return(y);
8148         if (z != 0 && z != 1) {
8149             printf("?The choices are 0 or 1\n");
8150             return(-2);
8151         }
8152         if ((y = cmcfm()) < 0) return(y);
8153         break;
8154 
8155       case PAD_LF_AFTER_CR:
8156         if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
8157         if (z < 0 || z == 3 || z > 7) {
8158             printf("?The choices are 0, 1, 2, 4, 5, 6 or 7\n");
8159             return(-2);
8160         }
8161         if ((y = cmcfm()) < 0) return(y);
8162         break;
8163 
8164       case PAD_PADDING_AFTER_LF:
8165         if ((y = cmnum("PAD lfpad","",10,&z,xxstring)) < 0) return(y);
8166         if (z < 0 || z > 7) {
8167             printf("?The choices are 0 or 1 <= lfpad <= 7\n");
8168             return(-2);
8169         }
8170         if ((y = cmcfm()) < 0) return(y);
8171         break;
8172 
8173       case PAD_EDITING:
8174         if ((y = cmnum("PAD edit control","",10,&z,xxstring)) < 0) return(y);
8175         if (z != 0 && z != 1) {
8176             printf("?The choices are 0 or 1\n");
8177             return(-2);
8178         }
8179         if ((y = cmcfm()) < 0) return(y);
8180         break;
8181 
8182       case PAD_CHAR_DELETE_CHAR:
8183         if ((y = cmnum("PAD char delete char","",10,&z,xxstring)) < 0)
8184             return(y);
8185         if (z < 0 || z > 127) {
8186             printf("?The choices are 0 or 1 <= chardelete <= 127\n");
8187             return(-2);
8188         }
8189         if ((y = cmcfm()) < 0) return(y);
8190         break;
8191 
8192       case PAD_BUFFER_DELETE_CHAR:
8193         if ((y = cmnum("PAD buffer delete char","",10,&z,xxstring)) < 0)
8194             return(y);
8195         if (z < 0 || z > 127) {
8196             printf("?The choices are 0 or 1 <= bufferdelete <= 127\n");
8197             return(-2);
8198         }
8199         if ((y = cmcfm()) < 0) return(y);
8200         break;
8201 
8202       case PAD_BUFFER_DISPLAY_CHAR:
8203         if ((y = cmnum("PAD display line char","",10,&z,xxstring)) < 0)
8204             return(y);
8205         if (z < 0 || z > 127) {
8206             printf("?The choices are 0 or 1 <= displayline <= 127\n");
8207             return(-2);
8208         }
8209         if ((y = cmcfm()) < 0) return(y);
8210         break;
8211     }
8212     padparms[x] = z;
8213     return(success = 1);
8214 }
8215 #endif /* IBMX25 */
8216 #endif /* ANYX25 */
8217 
8218 #ifndef NOXFER
8219 int
setat(rmsflg)8220 setat(rmsflg) int rmsflg; {
8221     int xx;
8222     if ((y = cmkey(attrtab,natr,"File Attribute packets","",xxstring)) < 0)
8223       return(y);
8224     if (y == AT_XALL) {                 /* ATTRIBUTES ALL ON or ALL OFF */
8225         if ((z = seton(&xx)) < 0) return(z);
8226         if (rmsflg) {
8227             printf("Sorry, command not available\n");
8228             return(-9);
8229         } else {
8230             atenci = xx;                /* Encoding in */
8231             atenco = xx;                /* Encoding out */
8232             atdati = xx;                /* Date in */
8233             atdato = xx;                /* Date out */
8234             atdisi = xx;                /* Disposition in/out */
8235             atdiso = xx;
8236             atleni = xx;                /* Length in/out (both kinds) */
8237             atleno = xx;
8238             atblki = xx;                /* Blocksize in/out */
8239             atblko = xx;
8240             attypi = xx;                /* File type in/out */
8241             attypo = xx;
8242             atsidi = xx;                /* System ID in/out */
8243             atsido = xx;
8244             atsysi = xx;                /* System-dependent params in/out */
8245             atsyso = xx;
8246 #ifdef CK_PERMS                         /* Protection */
8247             atlpri = xx;                /* Local in */
8248             atlpro = xx;                /* Local out */
8249             atgpri = xx;                /* Generic in */
8250             atgpro = xx;                /* Generic out */
8251 #endif /* CK_PERMS */
8252 #ifdef STRATUS
8253             atfrmi = xx;                /* Format in/out */
8254             atfrmo = xx;
8255             atcrei = xx;                /* Creator id in/out */
8256             atcreo = xx;
8257             atacti = xx;                /* Account in/out */
8258             atacto = xx;
8259 #endif /* STRATUS */
8260         }
8261         return(z);
8262     } else if (y == AT_ALLY || y == AT_ALLN) { /* ATTRIBUTES ON or OFF */
8263         if ((x = cmcfm()) < 0) return(x);
8264         atcapr = (y == AT_ALLY) ? 1 : 0;
8265         if (rmsflg) {
8266             sstate = setgen('S', "132", atcapr ? "1" : "0", "");
8267             return((int) sstate);
8268         } else return(success = 1);
8269     }
8270     /* Otherwise, it's an individual attribute that wants turning off/on */
8271 
8272     if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
8273     if ((x = cmcfm()) < 0) return(x);
8274 
8275 /* There are better ways to do this... */
8276 /* The real problem is that we're not separating the in and out cases */
8277 /* and so we have to arbitrarily pick the "in" case, i.e tell the remote */
8278 /* server to ignore incoming attributes of the specified type, rather */
8279 /* than telling it not to send them.  The protocol does not (yet) define */
8280 /* codes for "in-and-out-at-the-same-time". */
8281 
8282     switch (y) {
8283 #ifdef CK_PERMS
8284 /* We're lumping local and generic protection together for now... */
8285       case AT_LPRO:
8286       case AT_GPRO:
8287         if (rmsflg) {
8288             sstate = setgen('S', "143", z ? "1" : "0", "");
8289             return((int) sstate);
8290         }
8291         atlpri = atlpro = atgpri = atgpro = z; break;
8292 #endif /* CK_PERMS */
8293       case AT_DISP:
8294         if (rmsflg) {
8295             sstate = setgen('S', "142", z ? "1" : "0", "");
8296             return((int) sstate);
8297         }
8298         atdisi = atdiso = z; break;
8299       case AT_ENCO:
8300         if (rmsflg) {
8301             sstate = setgen('S', "141", z ? "1" : "0", "");
8302             return((int) sstate);
8303         }
8304         atenci = atenco = z; break;
8305       case AT_DATE:
8306         if (rmsflg) {
8307             sstate = setgen('S', "135", z ? "1" : "0", "");
8308             return((int) sstate);
8309         }
8310         atdati = atdato = z; break;
8311       case AT_LENB:
8312       case AT_LENK:
8313         if (rmsflg) {
8314             sstate = setgen('S', "133", z ? "1" : "0", "");
8315             return((int) sstate);
8316         }
8317         atleni = atleno = z; break;
8318       case AT_BLKS:
8319         if (rmsflg) {
8320             sstate = setgen('S', "139", z ? "1" : "0", "");
8321             return((int) sstate);
8322         }
8323         atblki = atblko = z; break;
8324       case AT_FTYP:
8325         if (rmsflg) {
8326             sstate = setgen('S', "134", z ? "1" : "0", "");
8327             return((int) sstate);
8328         }
8329         attypi = attypo = z; break;
8330 #ifdef STRATUS
8331       case AT_CREA:
8332         if (rmsflg) {
8333             sstate = setgen('S', "136", z ? "1" : "0", "");
8334             return((int) sstate);
8335         }
8336         atcrei = atcreo = z; break;
8337       case AT_ACCT:
8338         if (rmsflg) {
8339             sstate = setgen('S', "137", z ? "1" : "0", "");
8340             return((int) sstate);
8341         }
8342         atacti = atacto = z; break;
8343 #endif /* STRATUS */
8344       case AT_SYSI:
8345         if (rmsflg) {
8346             sstate = setgen('S', "145", z ? "1" : "0", "");
8347             return((int) sstate);
8348         }
8349         atsidi = atsido = z; break;
8350       case AT_RECF:
8351         if (rmsflg) {
8352             sstate = setgen('S', "146", z ? "1" : "0", "");
8353             return((int) sstate);
8354         }
8355         atfrmi = atfrmo = z; break;
8356       case AT_SYSP:
8357         if (rmsflg) {
8358             sstate = setgen('S', "147", z ? "1" : "0", "");
8359             return((int) sstate);
8360         }
8361         atsysi = atsyso = z; break;
8362       default:
8363         printf("?Not available\n");
8364         return(-2);
8365     }
8366     return(1);
8367 }
8368 #endif /* NOXFER */
8369 
8370 #ifndef NOSPL
8371 int
setinp()8372 setinp() {
8373     if ((y = cmkey(inptab,ninp,"","",xxstring)) < 0) return(y);
8374     switch (y) {
8375 #ifdef OS2
8376       case IN_PAC:                      /* SET INPUT PACING */
8377         z = cmnum("milliseconds","0",10,&x,xxstring);
8378         return(setnum(&tt_inpacing,x,z,1000));
8379       case IN_TRM:                      /* SET INPUT TERMINAL */
8380         return(seton(&interm));
8381 #endif /* OS2 */
8382       case IN_DEF:                      /* SET INPUT DEFAULT-TIMEOUT */
8383         z = cmnum("Positive number","",10,&x,xxstring);
8384         return(setnum(&indef,x,z,94));
8385 #ifdef CKFLOAT
8386       case IN_SCA:                      /* SET INPUT SCALE-FACTOR */
8387 	if ((x = cmfld("Number such as 2 or 0.5","1.0",&s, xxstring)) < 0)
8388 	  return(x);
8389         if (isfloat(s,0)) {		/* A floating-point number? */
8390             extern char * inpscale;
8391 	    inscale = floatval;		/* Yes, get its value */
8392 	    makestr(&inpscale,s);	/* Save it as \v(inscale) */
8393 	    return(success = 1);
8394 	} else {
8395 	    return(-2);
8396 	}
8397 #endif	/* CKFLOAT */
8398       case IN_TIM:                      /* SET INPUT TIMEOUT-ACTION */
8399         if ((z = cmkey(intimt,2,"","",xxstring)) < 0) return(z);
8400         if ((x = cmcfm()) < 0) return(x);
8401         intime[cmdlvl] = z;
8402         return(success = 1);
8403       case IN_CAS:                      /* SET INPUT CASE */
8404         if ((z = cmkey(incast,2,"","",xxstring)) < 0) return(z);
8405         if ((x = cmcfm()) < 0) return(x);
8406         inpcas[cmdlvl] = z;
8407         return(success = 1);
8408       case IN_ECH:                      /* SET INPUT ECHO */
8409         return(seton(&inecho));
8410       case IN_SIL:                      /* SET INPUT SILENCE */
8411         z = cmnum("Seconds of inactivity before INPUT fails","",10,&x,
8412                   xxstring);
8413         return(setnum(&insilence,x,z,-1));
8414 
8415       case IN_BUF:                      /* SET INPUT BUFFER-SIZE */
8416         if ((z = cmnum("Number of bytes in INPUT buffer",
8417                        ckitoa(INPBUFSIZ),10,&x, xxstring)) < 0)
8418           return(z);
8419         if ((y = cmcfm()) < 0) return(y);
8420         inbufsize = 0;
8421         if (inpbuf) {
8422             free(inpbuf);
8423             inpbuf = NULL;
8424             inpbp = NULL;
8425         }
8426         if (!(s = (char *)malloc(x + 1)))
8427           return(0);
8428         inpbuf = s;
8429         inpbp = s;
8430         inbufsize = x;
8431         for (x = 0; x <= inbufsize; x++)
8432           inpbuf[x] = NUL;
8433         return(success = 1);
8434 
8435 #ifdef CK_AUTODL
8436       case IN_ADL:                      /* AUTODOWNLOAD */
8437         return(seton(&inautodl));
8438 #endif /* CK_AUTODL */
8439 
8440       case IN_CAN:                      /* SET INPUT INTERRUPTS */
8441         return(seton(&inintr));
8442     }
8443     return(0);
8444 }
8445 #endif /* NOSPL */
8446 
8447 #ifdef NETCONN
8448 VOID
ndreset()8449 ndreset() {
8450 #ifndef NODIAL                          /* This depends on DIAL... */
8451     int i=0, j=0;
8452     if (!ndinited)                      /* Don't free garbage... */
8453       return;
8454     for (i = 0; i < nhcount; i++) {     /* Clean out previous list */
8455         if (nh_p[i])
8456           free(nh_p[i]);
8457         nh_p[i] = NULL;
8458         if (nh_p2[i])
8459           free(nh_p2[i]);
8460         nh_p2[i] = NULL;
8461         for (j = 0; j < 4; j++) {
8462             if (nh_px[j][i])
8463               free(nh_px[j][i]);
8464             nh_px[j][i] = NULL;
8465         }
8466     }
8467 #endif /* NODIAL */
8468 }
8469 
8470 VOID
ndinit()8471 ndinit() {                              /* Net directory pointers */
8472 #ifndef NODIAL                          /* This depends on DIAL... */
8473     int i, j;
8474     if (ndinited++)                     /* Don't do this more than once. */
8475       return;
8476     for (i = 0; i < MAXDDIR; i++) {     /* Init all pointers to NULL */
8477         netdir[i] = NULL;
8478     }
8479     for (i = 0; i < MAXDNUMS; i++) {
8480         nh_p[i] = NULL;
8481         nh_p2[i] = NULL;
8482         for (j = 0; j < 4; j++)
8483           nh_px[j][i] = NULL;
8484     }
8485 #endif /* NODIAL */
8486 }
8487 
8488 #ifndef NODIAL
8489 #ifdef NETCONN
8490 VOID                                    /* Get net defaults from environment */
getnetenv()8491 getnetenv() {
8492     char *p = NULL;
8493 
8494     makestr(&p,getenv("K_NET_DIRECTORY")); /* Dialing directories */
8495     if (p) {
8496         int i;
8497         xwords(p,MAXDDIR,netdir,0);
8498         for (i = 0; i < MAXDDIR; i++) { /* Fill in any gaps... */
8499             if (!netdir[i+1])
8500               break;
8501             else
8502               netdir[i] = netdir[i+1];
8503             debug(F111,"netdir[i]",netdir[i],i);
8504         }
8505         nnetdir = i;
8506     }
8507 }
8508 #endif /* NETCONN */
8509 #endif /* NODIAL */
8510 
8511 int
8512 #ifdef CK_ANSIC
lunet(char * s)8513 lunet(char *s)                          /* s = name to look up   */
8514 #else
8515 lunet(s) char *s;
8516 #endif /* CK_ANSIC */
8517 /* lunet */ {
8518 #ifndef NODIAL                          /* This depends on DIAL... */
8519     int n, n1, t, dd = 0;
8520     int ambiguous = 0;
8521     FILE * f;
8522     char *line = NULL;
8523     extern int dialdpy;
8524     int netdpy = dialdpy;
8525     char *info[8];
8526 
8527     nhcount = 0;                        /* Set this before returning */
8528 
8529     if (!s || nnetdir < 1)              /* Validate arguments */
8530       return(-1);
8531 
8532     if (isdigit(*s) || *s == '*' || *s == '.')
8533       return(0);
8534 
8535     if ((n1 = (int) strlen(s)) < 1)     /* Length of string to look up */
8536       return(-1);
8537 
8538     if (!(line = malloc(1024)))         /* Allocate input buffer */
8539       return(-1);
8540 
8541   lu_again:
8542     f = NULL;                           /* Network directory file descriptor */
8543     t = nhcount = 0;                    /* Match count */
8544     dd = 0;                             /* Directory counter */
8545 
8546     dirline = 0;
8547     while (1) {                         /* We make one pass */
8548         if (!f) {                       /* Directory not open */
8549             if (dd >= nnetdir)          /* No directories left? */
8550               break;                    /* Done. */
8551             if ((f = fopen(netdir[dd],"r")) == NULL) { /* Open it */
8552                 perror(netdir[dd]);     /* Can't, print message saying why */
8553                 dd++;
8554                 continue;               /* But go on to next one. */
8555             }
8556             if (netdpy)
8557               printf("Opening %s...\n",netdir[dd]);
8558             dd++;
8559         }
8560         line[0] = NUL;
8561         if (getnct(line,1023,f,1) < 0) { /* Read a line */
8562             if (f) {                    /* f can be clobbered! */
8563                 fclose(f);              /* Close the file */
8564                 f = NULL;               /* Indicate next one needs opening */
8565             }
8566             continue;
8567         }
8568         if (!line[0])                   /* Empty line */
8569           continue;
8570 
8571         xwords(line,7,info,0);          /* Parse it */
8572 
8573         if (!info[1] || !info[2] || !info[3]) /* Required fields */
8574           continue;
8575         if (*info[1] == ';')            /* Full-line comment */
8576           continue;
8577         if ((n = (int) strlen(info[1])) < 1) /* Length of name-tag */
8578           continue;
8579         if (n < n1)                     /* Search name is longer */
8580           continue;                     /* Can't possibly match */
8581         if (ambiguous && n != n1)
8582           continue;
8583         if (ckstrcmp(s,info[1],n1,0))   /* Compare using length of */
8584           continue;                     /* search string s. */
8585 
8586         /* Have a match */
8587 
8588         makestr(&(nh_p[nhcount]), info[3]);    /* address */
8589         makestr(&(nh_p2[nhcount]),info[2]);    /* net type */
8590         makestr(&(nh_px[0][nhcount]),info[4]); /* net-specific stuff... */
8591         makestr(&(nh_px[1][nhcount]),info[5]);
8592         makestr(&(nh_px[2][nhcount]),info[6]);
8593         makestr(&(nh_px[3][nhcount]),info[7]);
8594 
8595         nhcount++;                      /* Count this match */
8596         if (nhcount > MAXDNUMS) {       /* Watch out for too many */
8597             printf("Warning: %d matches found, %d max\n",
8598                    nhcount,
8599                    MAXDNUMS
8600                    );
8601             nhcount = MAXDNUMS;
8602             break;
8603         }
8604         if (nhcount == 1) {             /* First one - save entry name */
8605             if (n_name) {               /* Free the one from before if any */
8606                 free(n_name);
8607                 n_name = NULL;
8608             }
8609             if (!(n_name = (char *)malloc(n + 1))) { /* Allocate new storage */
8610                 printf("?memory allocation error - lunet:3\n");
8611                 if (line) {
8612                     free(line);
8613                     line = NULL;
8614                 }
8615                 nhcount = 0;
8616                 return(-1);
8617             }
8618             t = n;                      /* Remember its length */
8619             strcpy(n_name,info[1]);     /* safe */
8620         } else {                        /* Second or subsequent one */
8621             if ((int) strlen(info[1]) == t) /* Lengths compare */
8622               if (!ckstrcmp(n_name,info[1],t,0)) /* Caseless compare OK */
8623                 continue;
8624 
8625             /* Name given by user matches entries with different names */
8626 
8627             if (ambiguous)              /* Been here before */
8628               break;
8629 
8630             ambiguous = 1;              /* Now an exact match is required */
8631             ndreset();                  /* Clear out previous list */
8632             goto lu_again;              /* Do it all over again. */
8633         }
8634     }
8635     if (line) {
8636         free(line);
8637         line = NULL;
8638     }
8639     if (nhcount == 0 && ambiguous)
8640       printf("?\"%s\" - ambiguous in network directory\n",s);
8641 #else
8642     nhcount = 0;
8643 #endif /* NODIAL */
8644     return(nhcount);
8645 }
8646 #endif /* NETCONN */
8647 
8648 #ifndef NOLOCAL
8649 /*  C L S C O N N X  --  Close connection  */
8650 
8651 int
clsconnx(ask)8652 clsconnx(ask) int ask; {
8653     int x, rc = 0;
8654 #ifdef NEWFTP
8655     extern int ftpget, ftpisopen();
8656     if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
8657       return(success = ftpbye());
8658 #endif /* NEWFTP */
8659     debug(F101,"clsconnx local","",local);
8660     if (local) {
8661         x = ask ? hupok(1) : 1;         /* Make sure it's OK to close */
8662         if (!x) {
8663             rc = -1;
8664             debug(F101,"clsconnx hupok says no","",rc);
8665             return(rc);
8666         }
8667         ttflui();                       /* Clear away buffered up junk */
8668 #ifndef NODIAL
8669 #ifdef OS2ONLY
8670 /* Don't hangup a line that is shared with the SLIP or PPP driver */
8671         if (!ttslip && !ttppp)
8672 #endif /* OS2ONLY */
8673           mdmhup();
8674 #endif /* NODIAL */
8675         if (network && msgflg)
8676           printf(" Closing connection\n");
8677         ttclos(0);                      /* Close old connection, if any */
8678         rc = 1;
8679         {
8680             extern int wasclosed, whyclosed;
8681             if (wasclosed) {
8682                 whyclosed = WC_CLOS;
8683 #ifndef NOSPL
8684                 if (nmac) {             /* Any macros defined? */
8685                     int k;              /* Yes */
8686                     /* printf("ON_CLOSE CLSCONNX\n"); */
8687                     wasclosed = 0;
8688                     k = mlook(mactab,"on_close",nmac);  /* Look this up */
8689                     if (k >= 0) {                       /* If found, */
8690                         if (dodo(k,ckitoa(whyclosed),0) > -1) /* set it up, */
8691                           parser(1);                    /* and execute it */
8692                     }
8693                 }
8694 #endif /* NOSPL */
8695                 whyclosed = WC_REMO;
8696                 wasclosed = 0;
8697             }
8698         }
8699     }
8700 #ifdef VMS                              /* Or maybe #ifndef UNIX? */
8701     else {                              /* Need to do this in VMS to */
8702         ttclos(0);                      /* free the tty channel number */
8703         rc = 1;                         /* obtained in ttopen() or else */
8704     }                                   /* subsequent ttopen's won't work */
8705 #endif /* VMS */
8706     dologend();
8707     haveline = 0;
8708     if (mdmtyp < 0) {                   /* Switching from net to async? */
8709         if (mdmsav > -1)                /* Restore modem type from last */
8710           mdmtyp = mdmsav;              /* SET MODEM command, if any. */
8711         else
8712           mdmtyp = 0;
8713         mdmsav = -1;
8714     }
8715     if (network)
8716       network = 0;
8717 #ifdef NETCONN
8718     if (oldplex > -1) {                 /* Restore previous duplex setting. */
8719         duplex = oldplex;
8720         oldplex = -1;
8721     }
8722 #endif /* NETCONN */
8723 #ifndef MAC
8724     ckstrncpy(ttname,dftty,TTNAMLEN);   /* Restore default communication */
8725 #endif /* MAC */
8726     local = dfloc;                      /* device and local/remote status */
8727     if (local) {
8728         cxtype = CXT_DIRECT;            /* Something reasonable */
8729         speed = ttgspd();               /* Get the current speed */
8730     } else {
8731         cxtype = CXT_REMOTE;
8732         speed = -1L;
8733     }
8734 #ifndef NOXFER
8735     if (xreliable > -1 && !setreliable) {
8736         reliable = xreliable;
8737         debug(F101,"clsconnx reliable A","",reliable);
8738     } else if (!setreliable) {
8739         reliable = SET_AUTO;
8740         debug(F101,"clsconnx reliable B","",reliable);
8741     }
8742 #endif /* NOXFER */
8743     setflow();                          /* Revert flow control */
8744     return(rc);
8745 }
8746 
8747 int
clskconnx(x)8748 clskconnx(x) int x; {                   /* Close Kermit connection only */
8749     int t, rc;                          /* (not FTP) */
8750 #ifdef NEWFTP
8751     extern int ftpget;
8752     t = ftpget;
8753     ftpget = 0;
8754 #endif /* NEWFTP */
8755     rc = clsconnx(x);
8756 #ifdef NEWFTP
8757     ftpget = t;
8758 #endif /* NEWFTP */
8759     return(rc);
8760 }
8761 
8762 /* May 2002: setlin() decomposition starts here ... */
8763 
8764 #ifdef OS2
8765 #define SRVBUFSIZ PIPENAML
8766 #else /* OS2 */
8767 #define SRVBUFSIZ 63
8768 #endif /* OS2 */
8769 #define HOSTNAMLEN 15*65
8770 
8771 int netsave = -1;
8772 static char * tmpstring = NULL;
8773 static char * tmpusrid = NULL;
8774 
8775 #ifdef SSHCMD
8776 char * sshcmd = NULL;
8777 char * defsshcmd = "ssh -e none";
8778 #else
8779 #ifdef SSHBUILTIN
8780 char * sshrcmd = NULL;
8781 char * sshtmpcmd = NULL;
8782 #endif /* SSHBUILTIN */
8783 #endif /* SSHCMD */
8784 
8785 /* c x _ f a i l  --  Common error exit routine for cx_net, cx_line */
8786 
8787 int
cx_fail(msg,text)8788 cx_fail(msg, text) int msg; char * text; {
8789     makestr(&slmsg,text);		/* For the record (or GUI) */
8790     if (msg)				/* Not GUI, not quiet, etc */
8791       printf("?%s\n",text);		/* Print error message */
8792     slrestor();				/* Restore LINE/HOST to known state */
8793     return(msg ? -9 : (success = 0));	/* Return appropriate code */
8794 }
8795 
8796 #ifdef NETCONN
8797 /* c x _ n e t  --  Make a network connection */
8798 
8799 /*
8800   Call with:
8801     net      = network type
8802     protocol = protocol type
8803     host     = string pointer to host name.
8804     svc      = string pointer to service or port on host.
8805     username = username for connection
8806     password = password for connection
8807     command  = command to execute
8808     param1   = Telnet: Authentication type
8809                SSH:    Version
8810     param2   = Telnet: Encryption type
8811                SSH:    Command as Subsystem
8812     param3   = Telnet: 1 to wait for negotiations, 0 otherwise
8813                SSH:    X11 Forwarding
8814     cx       = 1 to automatically enter Connect mode, 0 otherwise.
8815     sx       = 1 to automatically enter Server mode, 0 otherwise.
8816     flag     = if no host name given, 1 = close current connection, 0 = resume
8817     gui      = 1 if called from GUI dialog, 0 otherwise.
8818   Returns:
8819     1 on success
8820     0 on failure and no message printed, slmsg set to failure message.
8821    -9 on failure and message printed, ditto.
8822 */
8823 int
8824 #ifdef CK_ANSIC
cx_net(int net,int protocol,char * xhost,char * svc,char * username,char * password,char * command,int param1,int param2,int param3,int cx,int sx,int flag,int gui)8825 cx_net( int net, int protocol, char * xhost, char * svc,
8826         char * username, char * password, char * command,
8827         int param1, int param2, int param3, int cx, int sx, int flag, int gui)
8828 #else /* CK_ANSIC */
8829 cx_net(net, protocol, xhost, svc,
8830        username, password, command,
8831        param1, param2, param3, cx, sx, flag, gui)
8832     char * xhost, * svc, * username, *password, *command;
8833     int net, protocol, cx, sx, flag, param1, param2, param3, gui;
8834 #endif /* CK_ANSIC */
8835 /* cx_net */ {
8836 
8837     int i, n, x, msg;
8838     int _local = -1;
8839 
8840     extern char pwbuf[], * g_pswd;
8841     extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
8842 
8843     char srvbuf[SRVBUFSIZ+1];		/* Service */
8844     char hostbuf[HOSTNAMLEN];		/* Host buffer to manipulate */
8845     char hostname[HOSTNAMLEN];		/* Copy of host parameter */
8846     char * host = hostbuf;		/* Pointer to copy of host param */
8847 
8848     if (!xhost) xhost = "";		/* Watch out for null pointers */
8849     if (!svc) svc = "";
8850     ckstrncpy(host,xhost,HOSTNAMLEN);	/* Avoid buffer confusion */
8851 
8852     debug(F110,"cx_net host",host,0);
8853     debug(F111,"cx_net service",svc,SRVBUFSIZ);
8854     debug(F101,"cx_net network type","",net);
8855 
8856     msg = (gui == 0) && msgflg;		/* Whether to print messages */
8857 
8858 #ifndef NODIAL
8859     debug(F101,"cx_net nnetdir","",nnetdir);
8860     x = 0;				/* Look up in network directory */
8861     if (*host == '=') {			/* If number starts with = sign */
8862 	host++;				/* strip it */
8863 	while (*host == SP) host++;	/* and any leading spaces */
8864 	debug(F110,"cx_net host 2",host,0);
8865 	nhcount = 0;
8866     } else if (*host) {			/* We want to look it up. */
8867 	if (nnetdir > 0)		/* If there is a directory... */
8868 	  x = lunet(host);		/* (sets nhcount) */
8869 	else				/* otherwise */
8870 	  nhcount = 0;			/* we didn't find any there */
8871 	if (x < 0)			/* Internal error? */
8872 	  return(cx_fail(msg,"Network directory lookup error"));
8873 	debug(F111,"cx_net lunet nhcount",host,nhcount);
8874     }
8875 #endif /* NODIAL */
8876 
8877     /* New connection wanted.  Make a copy of the host name/address... */
8878 
8879     if (clskconnx(1) < 0)		/* Close current Kermit connection */
8880       return(cx_fail(msg,"Error closing previous connection"));
8881 
8882     if (*host) {			/* They gave a hostname */
8883 	_local = 1;			/* Network connection always local */
8884 	if (mdmsav < 0)
8885 	  mdmsav = mdmtyp;		/* Remember old modem type */
8886 	mdmtyp = -net;			/* Special code for network */
8887     } else {				/* They just said "set host" */
8888 	host = dftty;			/* So go back to normal */
8889 	_local = dfloc;			/* default tty, location, */
8890 	if (flag) {			/* Close current connection */
8891 	    setflow();			/* Maybe change flow control */
8892 	    haveline = 1;		/* (* is this right? *) */
8893 	    dologend();
8894 #ifndef NODIAL
8895 	    dialsta = DIA_UNK;
8896 #endif /* NODIAL */
8897 #ifdef LOCUS
8898 	    if (autolocus) {
8899 		setlocus(1,1);
8900 	    }
8901 #endif /* LOCUS */
8902             /* XXX - Is this right? */
8903 	    /* Should we be returning without doing anything ? */
8904 	    /* Yes it's right -- we closed the old connection just above. */
8905 	    return(success = 1);
8906 	}
8907     }
8908     success = 0;
8909     if (host != line)                   /* line[] is a global */
8910       ckstrncpy(line,host,LINBUFSIZ);
8911     ckstrncpy(hostname,host,HOSTNAMLEN);
8912     ckstrncpy(srvbuf,svc,SRVBUFSIZ+1);
8913 
8914 #ifndef NODIAL
8915     if ((nhcount > 1) && msg) {
8916 	int k;
8917 	printf("%d entr%s found for \"%s\"%s\n",
8918 	       nhcount,
8919 	       (nhcount == 1) ? "y" : "ies",
8920 	       s,
8921 	       (nhcount > 0) ? ":" : "."
8922 	       );
8923 	for (i = 0; i < nhcount; i++) {
8924 		printf("%3d. %-12s => %-9s %s",
8925 		       i+1,n_name,nh_p2[i],nh_p[i]);
8926 	    for (k = 0; k < 4; k++) { /* Also list net-specific items */
8927 		if (nh_px[k][i])      /* free format... */
8928 		  printf(" %s",nh_px[k][i]);
8929 		else
8930 		  break;
8931 	    }
8932 	    printf("\n");
8933 	}
8934     }
8935     if (nhcount == 0)
8936       n = 1;
8937     else
8938       n = nhcount;
8939 #else
8940     n = 1;
8941     nhcount = 0;
8942 #endif /* NODIAL */
8943 
8944     for (i = 0; i < n; i++) {		/* Loop for each entry found */
8945 	debug(F101,"cx_net loop i","",i);
8946 #ifndef NODIAL
8947 	if (nhcount > 0) {		/* If we found at least one entry... */
8948 	    ckstrncpy(line,nh_p[i],LINBUFSIZ); /* Copy current entry */
8949 	    if (lookup(netcmd,nh_p2[i],nnets,&x) > -1) { /* Net type */
8950 		int xx;
8951 		xx = netcmd[x].kwval;
8952 		/* User specified SSH so don't let net directory override */
8953 		if (net != NET_SSH || xx != NET_TCPB) {
8954 		    net = xx;
8955 		    mdmtyp  = 0 - net;
8956 		}
8957 	    } else {
8958 		makestr(&slmsg,"Network type not supported");
8959 		if (msg)
8960 		  printf("Error - network type \"%s\" not supported\n",
8961 			 nh_p2[i]
8962 		         );
8963 		continue;
8964 	    }
8965 	    switch (net) {		/* Net-specific directory things */
8966 #ifdef SSHBUILTIN
8967 	      case NET_SSH:		/* SSH */
8968                 /* Any SSH specific network directory stuff? */
8969                 break;                  /* NET_SSH */
8970 #endif /* SSHBUILTIN */
8971 
8972 	      case NET_TCPB: {		/* TCP/IP TELNET,RLOGIN,... */
8973 #ifdef TCPSOCKET
8974 		  char *q;
8975 		  int flag = 0;
8976 
8977 		  /* Extract ":service", if any, from host string */
8978 		  debug(F110,"cx_net service 1",line,0);
8979 		  for (q = line; (*q != '\0') && (*q != ':'); q++)
8980 		    ;
8981 		  if (*q == ':') { *q++ = NUL; flag = 1; }
8982 		  debug(F111,"cx_net service 2",line,flag);
8983 
8984 		  /* Get service, if any, from directory entry */
8985 
8986 		  if (!*srvbuf) {
8987 		      if (nh_px[0][i]) {
8988 			  ckstrncpy(srvbuf,nh_px[0][i],SRVBUFSIZ);
8989 			  debug(F110,"cx_net service 3",srvbuf,0);
8990 		      }
8991 		      if (flag) {
8992 			  ckstrncpy(srvbuf,q,SRVBUFSIZ);
8993 			  debug(F110,"cx_net service 4",srvbuf,0);
8994 		      }
8995 		  }
8996 		  ckstrncpy(hostname,line,HOSTNAMLEN);
8997 
8998 		  /* If we have a service, append to host name/address */
8999 		  if (*srvbuf) {
9000 		      ckstrncat(line, ":", LINBUFSIZ);
9001 		      ckstrncat(line, srvbuf, LINBUFSIZ);
9002 		      debug(F110,"cx_net service 5",line,0);
9003 		  }
9004 #ifdef RLOGCODE
9005 		  /* If no service given but command was RLOGIN */
9006 		  else if (ttnproto == NP_RLOGIN) { /* add this... */
9007 		      ckstrncat(line, ":login",LINBUFSIZ);
9008 		      debug(F110,"cx_net service 6",line,0);
9009 		  }
9010 #ifdef CK_AUTHENTICATION
9011 #ifdef CK_KERBEROS
9012 		  else if (ttnproto == NP_K4LOGIN ||
9013 			   ttnproto == NP_K5LOGIN) { /* add this... */
9014 		      ckstrncat(line, ":klogin",LINBUFSIZ);
9015 		      debug(F110,"cx_net service 7",line,0);
9016 		  }
9017 		  else if (ttnproto == NP_EK4LOGIN ||
9018 			   ttnproto == NP_EK5LOGIN) { /* add this... */
9019 		      ckstrncat(line, ":eklogin",LINBUFSIZ);
9020 		      debug(F110,"cx_net service 8",line,0);
9021 		  }
9022 #endif /* CK_KERBEROS */
9023 #endif /* CK_AUTHENTICATION */
9024 #endif /* RLOGCODE */
9025 		  else {		/* Otherwise, add ":telnet". */
9026 		      ckstrncat(line, ":telnet", LINBUFSIZ);
9027 		      debug(F110,"cx_net service 9",line,0);
9028 		  }
9029 		  if (username) {	/* This is a parameter... */
9030 		      ckstrncpy(uidbuf,username,UIDBUFLEN);
9031 		      uidflag = 1;
9032 		  }
9033 		  /* Fifth field, if any, is user ID (for rlogin) */
9034 
9035 		  if (nh_px[1][i] && !uidflag)
9036 		    ckstrncpy(uidbuf,username,UIDBUFLEN);
9037 #ifdef RLOGCODE
9038 		  if (IS_RLOGIN() && !uidbuf[0])
9039 		    return(cx_fail(msg,"Username required"));
9040 #endif /* RLOGCODE */
9041 #endif /* TCPSOCKET */
9042 		  break;
9043 	      }
9044 	      case NET_PIPE:		/* Pipe */
9045 #ifdef NPIPE
9046 		if (!pipename[0]) { /* User didn't give a pipename */
9047 		    if (nh_px[0][i]) { /* But directory entry has one */
9048 			if (strcmp(pipename,"\\pipe\\")) {
9049 			    ckstrncpy(pipename,"\\pipe\\",LINBUFSIZ);
9050 			    ckstrncat(srvbuf,nh_px[0][i],PIPENAML-6);
9051 			} else {
9052 			    ckstrncpy(pipename,nh_px[0][i],PIPENAML);
9053 			}
9054 			debug(F110,"cx_net pipeneme",pipename,0);
9055 		    }
9056 		}
9057 #endif /* NPIPE */
9058 		break;
9059 
9060 	      case NET_SLAT:            /* LAT / CTERM */
9061 #ifdef SUPERLAT
9062 		if (!slat_pwd[0]) { /* User didn't give a password */
9063 		    if (nh_px[0][i]) { /* But directory entry has one */
9064 			ckstrncpy(slat_pwd,nh_px[0][i],18);
9065 			debug(F110,"cx_net SuperLAT password",slat_pwd,0);
9066 		    }
9067 		}
9068 #endif /* SUPERLAT */
9069 		break;
9070 
9071 	      case NET_SX25:        /* X.25 keyword parameters */
9072 	      case NET_IX25:
9073 	      case NET_VX25: {
9074 #ifdef ANYX25
9075 		  int k;            /* Cycle through the four fields */
9076 		  for (k = 0; k < 4; k++) {
9077 		      if (!nh_px[k][i]) /* Bail out if none left */
9078 			break;
9079 		      if (!ckstrcmp(nh_px[k][i],"cug=",4,0)) {
9080 			  closgr = atoi(nh_px[k][i]+4);
9081 			  debug(F101,"X25 CUG","",closgr);
9082 		      } else if (!ckstrcmp(nh_px[k][i],"cud=",4,0)) {
9083 			  cudata = 1;
9084 			  ckstrncpy(udata,nh_px[k][i]+4,MAXCUDATA);
9085 			  debug(F110,"X25 CUD",cudata,0);
9086 		      } else if (!ckstrcmp(nh_px[k][i],"rev=",4,0)) {
9087 			  revcall = !ckstrcmp(nh_px[k][i]+4,"=on",3,0);
9088 			  debug(F101,"X25 REV","",revcall);
9089 #ifndef IBMX25
9090 		      } else if (!ckstrcmp(nh_px[k][i],"pad=",4,0)) {
9091 			  int x3par, x3val;
9092 			  char *s1, *s2;
9093 			  s1 = s2 = nh_px[k][i]+4; /* PAD parameters */
9094 			  while (*s2) {            /* Pick them apart */
9095 			      if (*s2 == ':') {
9096 				  *s2 = NUL;
9097 				  x3par = atoi(s1);
9098 				  s1 = ++s2;
9099 				  continue;
9100 			      } else if (*s2 == ',') {
9101 				  *s2 = NUL;
9102 				  x3val = atoi(s1);
9103 				  s1 = ++s2;
9104 				  debug(F111,"X25 PAD",x3par,x3val);
9105 				  if (x3par > -1 &&
9106 				      x3par <= MAXPADPARMS)
9107 				    padparms[x3par] = x3val;
9108 				  continue;
9109 			      } else
9110 				s2++;
9111 			  }
9112 #endif /* IBMX25 */
9113 		      }
9114 		  }
9115 #endif /* ANYX25 */
9116 		  break;
9117 	      }
9118 	      default:			/* Nothing special for other nets */
9119 		break;
9120 	    }
9121 	} else
9122 #endif /* NODIAL */
9123 	{				/* No directory entries found. */
9124 	    ckstrncpy(line,hostname,LINBUFSIZ); /* Put this back... */
9125 	    /* If the user gave a TCP service */
9126 	    if (net == NET_TCPB || net == NET_SSH)
9127 	      if (*srvbuf) {		/* Append it to host name/address */
9128 		  ckstrncat(line, ":", LINBUFSIZ);
9129 		  ckstrncat(line, srvbuf,LINBUFSIZ);
9130 	      }
9131 	}
9132 	/*
9133 	   Get here with host name/address and all net-specific
9134 	   parameters set, ready to open the connection.
9135 	*/
9136 	mdmtyp = -net;			/* This should have been done */
9137 					/* already but just in case ... */
9138 
9139 	debug(F110,"cx_net net line[] before ttopen",line,0);
9140 	debug(F101,"cx_net net mdmtyp before ttopen","",mdmtyp);
9141 	debug(F101,"cx_net net ttnproto","",ttnproto);
9142 
9143 #ifdef SSHBUILTIN
9144         if (net == NET_SSH) {
9145             makestr(&ssh_hst,hostname);        /* Stash everything */
9146             if (username) {
9147                 if (!sl_uid_saved) {
9148                     ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
9149                     sl_uid_saved = 1;
9150                 }
9151                 ckstrncpy(uidbuf,username,UIDBUFLEN);
9152             }
9153             if (srvbuf[0]) {
9154                 makestr(&ssh_prt,srvbuf);
9155             } else
9156                 makestr(&ssh_prt,NULL);
9157 
9158             if (command) {
9159                 makestr(&ssh_cmd,brstrip(command));
9160                 ssh_cas = param2;
9161             } else
9162                 makestr(&ssh_cmd,NULL);
9163 
9164             if (param1 > -1) {
9165 #ifndef SSHTEST
9166                 if (!sl_ssh_ver_saved) {
9167                     sl_ssh_ver = ssh_ver;
9168                     sl_ssh_ver_saved = 1;
9169                 }
9170 #endif /* SSHTEST */
9171                 ssh_ver = param1;
9172             }
9173             if (param3 > -1) {
9174 #ifndef SSHTEST
9175                 if (!sl_ssh_xfw_saved) {
9176                     sl_ssh_xfw = ssh_xfw;
9177                     sl_ssh_xfw_saved = 1;
9178                 }
9179 #endif /* SSHTEST */
9180                 ssh_xfw = param3;
9181             }
9182         } else                          /* NET_SSH */
9183 #endif /* SSHBUILTIN */
9184 #ifdef TCPSOCKET
9185 	  if (net == NET_TCPB) {
9186             switch (protocol) {
9187 #ifdef CK_SSL
9188 #ifdef COMMENT
9189 /*
9190   Jeff's version from 30 Dec 2006 - doesn't work - SSL/TLS_RAW still
9191   start Telnet negotions if a 0xff byte comes in.
9192 */
9193 	      case NP_SSL_RAW:
9194                 ttnproto = NP_SSL_RAW;
9195 		debug(F101,"NP_SSL_RAW ttnproto","",ttnproto);
9196                 ssl_only_flag = 1;
9197                 tls_only_flag = 0;
9198                 break;
9199 
9200 	      case NP_TLS_RAW:
9201 		  ttnproto = NP_TLS_RAW;
9202 		  debug(F101,"NP_TLS_RAW ttnproto","",ttnproto);
9203 		  ssl_only_flag = 0;
9204 		  tls_only_flag = 1;
9205 		  break;
9206 
9207 	      case NP_SSL:
9208                 ttnproto = NP_SSL;
9209 		debug(F101,"NP_SSL ttnproto","",ttnproto);
9210                 ssl_only_flag = 1;
9211                 tls_only_flag = 0;
9212                 break;
9213 
9214 	      case NP_TLS:
9215                 ttnproto = NP_TLS;
9216 		debug(F101,"NP_TLS ttnproto","",ttnproto);
9217                 ssl_only_flag = 0;
9218                 tls_only_flag = 1;
9219                 break;
9220 
9221 	      case NP_SSL_TELNET:
9222                 ttnproto = NP_TELNET;
9223 		debug(F101,"NP_SSL_TELNET ttnproto","",ttnproto);
9224                 ssl_only_flag = 1;
9225                 tls_only_flag = 0;
9226                 break;
9227 
9228 	      case NP_TLS_TELNET:
9229                 ttnproto = NP_TELNET;
9230 		debug(F101,"NP_TLS_TELNET ttnproto","",ttnproto);
9231                 ssl_only_flag = 0;
9232                 tls_only_flag = 1;
9233                 break;
9234 #else
9235 /* fdc version of 4 Dec 2006 works OK */
9236 	      case NP_SSL_RAW:
9237 	      case NP_SSL:
9238 		ssl_raw_flag = (protocol == NP_SSL_RAW) ? 1 : 0;
9239                 ttnproto = protocol;
9240 		debug(F101,protocol==NP_SSL ?
9241 		      "NP_SSL ttnproto" :
9242 		      "NP_SSL_RAW ttnproto",
9243 		      "",ttnproto);
9244                 ssl_only_flag = 1;
9245                 tls_only_flag = 0;
9246                 break;
9247 
9248 	      case NP_TLS:
9249 	      case NP_TLS_RAW:
9250 		tls_raw_flag = (protocol == NP_SSL_RAW) ? 1 : 0;
9251                 ttnproto = protocol;
9252 		debug(F101,protocol==NP_TLS ?
9253 		      "NP_TLS ttnproto" :
9254 		      "NP_TLS_RAW ttnproto",
9255 		      "",ttnproto);
9256                 ssl_only_flag = 0;
9257                 tls_only_flag = 1;
9258                 break;
9259 
9260 	      case NP_SSL_TELNET:
9261 		ssl_raw_flag = 0;
9262                 ttnproto = NP_TELNET;
9263 		debug(F101,"NP_SSL_TELNET ttnproto","",ttnproto);
9264                 ssl_only_flag = 1;
9265                 tls_only_flag = 0;
9266                 break;
9267 
9268 	      case NP_TLS_TELNET:
9269 		tls_raw_flag = 0;
9270                 ttnproto = NP_TELNET;
9271 		debug(F101,"NP_TLS_TELNET ttnproto","",ttnproto);
9272                 ssl_only_flag = 0;
9273                 tls_only_flag = 1;
9274                 break;
9275 #endif	/* COMMENT */
9276 #endif /* CK_SSL */
9277 
9278 	      case NP_NONE:
9279 	      case NP_TCPRAW:
9280 	      case NP_RLOGIN:
9281 	      case NP_K4LOGIN:
9282 	      case NP_K5LOGIN:
9283 	      case NP_EK4LOGIN:
9284 	      case NP_EK5LOGIN:
9285 	      case NP_TELNET:
9286 	      case NP_KERMIT:
9287 	      default:
9288                 ttnproto = protocol;
9289 #ifdef CK_SSL
9290 #ifdef COMMENT
9291 		/* Jeff version from 30 Dec 2006 */
9292                 ssl_only_flag = 0;
9293                 tls_only_flag = 0;
9294 #else
9295 		/* fdc version from 4 Dec 2006 */
9296 		ssl_raw_flag = 0;
9297 		tls_raw_flag = 0;
9298                 ssl_only_flag = 0;
9299                 tls_only_flag = 0;
9300 #endif	/* COMMENT */
9301 #endif /* CK_SSL */
9302                 break;
9303             }
9304 #ifdef CK_AUTHENTICATION
9305             if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9306 		param1 > -1) {
9307 	    if (!sl_auth_saved) {
9308 		int x;
9309 		for (x = 0; x < AUTHTYPLSTSZ; x++)
9310 		  sl_auth_type_user[x] = auth_type_user[x];
9311 		sl_auth_saved = 1;
9312 	    }
9313 	    if (!sl_topt_a_s_saved) {
9314 		sl_topt_a_su = TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION);
9315 		sl_topt_a_s_saved = 1;
9316 	    }
9317 	    if (!sl_topt_a_c_saved) {
9318 		sl_topt_a_cm = TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION);
9319 		sl_topt_a_c_saved = 1;
9320 	    }
9321 	    switch (param1) {
9322 	      case AUTHTYPE_AUTO:
9323 		auth_type_user[0] = AUTHTYPE_AUTO;
9324 		TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
9325 		TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
9326 		break;
9327 	      case AUTHTYPE_NULL:
9328 		auth_type_user[0] = AUTHTYPE_NULL;
9329 		TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
9330 		TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
9331 		break;
9332 #ifdef CK_SRP
9333 	      case AUTHTYPE_SRP:
9334 		auth_type_user[0] = AUTHTYPE_SRP;
9335 		auth_type_user[1] = AUTHTYPE_NULL;
9336 		TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9337 		TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9338 		break;
9339 #endif /* CK_SRP */
9340 #ifdef CK_SSL
9341 	      case AUTHTYPE_SSL:
9342 		auth_type_user[0] = AUTHTYPE_SSL;
9343 		auth_type_user[1] = AUTHTYPE_NULL;
9344 		TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9345 		TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9346 		break;
9347 #endif /* CK_SSL */
9348 #ifdef NT
9349 	      case AUTHTYPE_NTLM:
9350 		auth_type_user[0] = AUTHTYPE_NTLM;
9351 		auth_type_user[1] = AUTHTYPE_NULL;
9352 		TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9353 		TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9354 		break;
9355 #endif /* NT */
9356 #ifdef CK_KERBEROS
9357 	      case AUTHTYPE_KERBEROS_V4:
9358 		auth_type_user[0] = AUTHTYPE_KERBEROS_V4;
9359 		auth_type_user[1] = AUTHTYPE_NULL;
9360 		TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9361 		TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9362 		break;
9363 
9364 	      case AUTHTYPE_KERBEROS_V5:
9365 		auth_type_user[0] = AUTHTYPE_KERBEROS_V5;
9366 		auth_type_user[1] = AUTHTYPE_NULL;
9367 		TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9368 		TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
9369 		break;
9370 #endif /* CK_KERBEROS */
9371 	    }
9372 	}
9373 	/*
9374 	   If the user requires a particular type of Kerberos connection,
9375 	   make sure we have a valid TGT.
9376 	*/
9377 	makestr(&slmsg,"Authentication failure");
9378 	if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9379 	    (line[0] == '*' &&
9380 	     TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_MU ||
9381 	     line[0] != '*' &&
9382 	     TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_MU)
9383 	    ) {
9384 #ifdef CK_KERBEROS
9385 	    if ( auth_type_user[0] == AUTHTYPE_KERBEROS_V4 ) {
9386 		extern int krb4_autoget;
9387 		if (!ck_krb4_is_installed())
9388 		  return(cx_fail(msg,
9389 	      "Required authentication method (Kerberos 4) is not installed"));
9390 #ifdef COMMENT
9391 		/* This code results in false failures when using */
9392 		/* kerberos to machines in realms other than the  */
9393 		/* default since we don't know the realm of the   */
9394 		/* other machine until perform the reverse DNS    */
9395 		/* lookup.                                        */
9396 		else if (line[0] != '*' && !ck_krb4_is_tgt_valid() &&
9397 			   (!krb4_autoget ||
9398 			    krb4_autoget && !ck_krb4_autoget_TGT(NULL))) {
9399 		    return(cx_fail(msg,
9400 			   "Kerberos 4: Ticket Getting Ticket not valid"));
9401 		}
9402 #endif /* COMMENT */
9403 	    } else if (auth_type_user[0] == AUTHTYPE_KERBEROS_V5) {
9404 		extern int krb5_autoget;
9405 		if (!ck_krb5_is_installed()) {
9406 		    return(cx_fail(msg,
9407 	   "Required authentication method (Kerberos 5) is not installed"));
9408 		}
9409 #ifdef COMMENT
9410 		/* This code results in false failures when using */
9411 		/* kerberos to machines in realms other than the  */
9412 		/* default since we don't know the realm of the   */
9413 		/* other machine until perform the reverse DNS    */
9414 		/* lookup.                                        */
9415 		else if (line[0] != '*' && !ck_krb5_is_tgt_valid() &&
9416 			   (!krb5_autoget ||
9417 			    krb5_autoget && !ck_krb5_autoget_TGT(NULL))) {
9418 		    return(cx_fail(msg,
9419 			 "Kerberos 5: Ticket Getting Ticket not valid."));
9420 		}
9421 #endif /* COMMENT */
9422 	    }
9423 #endif /* CK_KERBEROS */
9424 #ifdef NT
9425 	    if (auth_type_user[0] == AUTHTYPE_NTLM) {
9426 		if (!ck_ntlm_is_installed()) {
9427 		    return(cx_fail(msg,
9428 		   "Required authentication method (NTLM) is not installed"));
9429 		} else if (line[0] != '*' && !ck_ntlm_is_valid(0)) {
9430 		    return(cx_fail(msg,"NTLM: Credentials are unavailable."));
9431 		}
9432 	    }
9433 #endif /* NT */
9434 #ifdef CK_SSL
9435 	    if (auth_type_user[0] == AUTHTYPE_SSL) {
9436 		if (!ck_ssleay_is_installed()) {
9437 		    return(cx_fail(msg,
9438 		     "Required authentication method (SSL) is not installed"));
9439 		}
9440 	    }
9441 #endif /* CK_SSL */
9442 #ifdef CK_SRP
9443 	    if (auth_type_user[0] == AUTHTYPE_SRP) {
9444 		if (!ck_srp_is_installed()) {
9445 		    return(cx_fail(msg,
9446 		     "Required authentication method (SRP) is not installed"));
9447 		}
9448 	    }
9449 #endif /* CK_SRP */
9450 	}
9451 #endif /* CK_AUTHENTICATION */
9452 #ifdef CK_ENCRYPTION
9453 	if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9454 	     param2 > -1) {
9455 	    if (!sl_cx_saved) {
9456 		sl_cx_type = cx_type;
9457 		sl_cx_saved = 1;
9458 	    }
9459 	    if (!sl_topt_e_s_saved) {
9460 		sl_topt_e_su = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
9461 		sl_topt_e_sm = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
9462 		sl_topt_e_s_saved = 1;
9463 	    }
9464 	    if (!sl_topt_e_c_saved) {
9465 		sl_topt_e_cu = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
9466 		sl_topt_e_cm = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
9467 		sl_topt_e_c_saved = 1;
9468 	    }
9469 	    cx_type = param2;
9470 	    if (cx_type == CX_AUTO) {
9471 		TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9472 		TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9473 		TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9474 		TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
9475 	    } else if (cx_type == CX_NONE) {
9476 		TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9477 		TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9478 		TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9479 		TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
9480 	    } else {
9481 		TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9482 		TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9483 		TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9484 		TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
9485 	    }
9486 	}
9487 	if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN ||
9488 	    (ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
9489 	    ((line[0] == '*' &&
9490 	      TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) == TN_NG_MU &&
9491 	      TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_MU) ||
9492 	     (line[0] != '*' &&
9493 	      TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) == TN_NG_MU &&
9494 	      TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_MU))
9495 	    ) {
9496 	    if (!ck_crypt_is_installed()) {
9497 		return(cx_fail(msg,
9498 		  "Required Encryption methods are not installed"));
9499 	    }
9500 	}
9501 #endif /* CK_ENCRYPTION */
9502 #ifdef RLOGCODE
9503 #ifdef CK_KERBEROS
9504 #ifdef KRB4
9505 	if (ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN) {
9506 	    extern int krb4_autoget;
9507 	    char tgt[256];
9508 	    char * realm;
9509 
9510 	    /* We don't have the full hostname at yet so  */
9511 	    /* we do a DNS lookup before calling ttopen() */
9512 
9513 	    realm = ck_krb4_realmofhost(ckgetfqhostname(hostname));
9514 	    ckmakmsg(tgt,256,"krbtgt.",realm,"@",realm);
9515 	    if (!ck_krb4_is_installed()) {
9516 		return(cx_fail(msg,
9517 		 "Required authentication method (Kerberos 4) is not installed"
9518 			       ));
9519 	    } else {
9520 		if ((ck_krb4_tkt_isvalid(tgt) <= 0) &&
9521 		    (!krb4_autoget ||
9522 		     krb4_autoget && !ck_krb4_autoget_TGT(realm))) {
9523 		    return(cx_fail(msg,
9524 			   "Kerberos 4: Ticket Getting Ticket not valid"));
9525 		}
9526 	    }
9527 	}
9528 #endif /* KRB4 */
9529 #ifdef KRB5
9530 	if (ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN ||
9531 	    ttnproto == NP_K5U2U)
9532 	{
9533 	    extern int krb5_autoget;
9534 	    char tgt[256];
9535 	    char * realm;
9536 
9537 	    /* Must get full hostname before calling ttopen() */
9538 
9539 	    realm = ck_krb5_realmofhost(ckgetfqhostname(hostname));
9540 	    ckmakmsg(tgt,256,"krbtgt/",realm,"@",realm);
9541 
9542 	    if (!ck_krb5_is_installed()) {
9543 		return(cx_fail(msg,
9544                  "Required authentication method (Kerberos 5) not installed"));
9545 	    } else if (!((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
9546 			  ck_krb5_is_tgt_valid()) &&
9547 		       (!krb5_autoget ||
9548 			krb5_autoget && !ck_krb5_autoget_TGT(realm))) {
9549 		return(cx_fail(msg,
9550 		       "Kerberos 5: Ticket Getting Ticket not valid."));
9551 	    }
9552 	}
9553 #endif /* KRB5 */
9554 #endif /* CK_KERBEROS */
9555 #endif /* RLOGCODE */
9556 
9557 #ifndef NOSPL
9558 #ifdef RLOGCODE
9559 	if (username) {
9560 	    if (!sl_uid_saved) {
9561 		ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
9562 		sl_uid_saved = 1;
9563 	    }
9564 	    ckstrncpy(uidbuf,username,UIDBUFLEN);
9565 	    uidflag = 1;
9566 	}
9567 #endif /* RLOGCODE */
9568 #ifdef TNCODE
9569 	if (!sl_tn_saved) {
9570 	    sl_tn_wait = tn_wait_flg;
9571 	    sl_tn_saved = 1;
9572 	}
9573 	tn_wait_flg = param3;
9574 #endif /* TNCODE */
9575 #endif /* NOSPL */
9576 	} /* if (net == NET_TCPB) */
9577 #endif /* TCPSOCKET */
9578 
9579 #ifndef NOSPL
9580 #ifdef CK_SECURITY
9581 	if (password) {
9582 	    if (password[0]) {
9583 		ckstrncpy(pwbuf,password,PWBUFL+1);
9584 		pwflg = 1;
9585 		pwcrypt = 0;
9586 	    } else
9587 		pwflg = 0;
9588 	}
9589 #endif /* CK_SECURITY */
9590 #endif /* NOSPL */
9591 
9592 	/* Try to open - network */
9593 	ckstrncpy(ttname,line,TTNAMLEN);
9594 	y = ttopen(line, &_local, mdmtyp, 0 );
9595 
9596 #ifndef NOHTTP
9597 	/*  If the connection failed and we are using an HTTP Proxy
9598 	 *  and the reason for the failure was an authentication
9599 	 *  error, then we need to give the user to ability to
9600 	 *  enter a username and password, just like a browser.
9601 	 *
9602 	 *  I tried to do all of this within the netopen() call
9603 	 *  but it is much too much work.
9604 	 */
9605 	while (y < 0 && tcp_http_proxy != NULL ) {
9606 
9607 	    if (tcp_http_proxy_errno == 401 ||
9608 		tcp_http_proxy_errno == 407 ) {
9609 		char uid[UIDBUFLEN];
9610 		char pwd[256];
9611                 struct txtbox tb[2];
9612                 int ok;
9613 
9614                 tb[0].t_buf = uid;
9615                 tb[0].t_len = UIDBUFLEN;
9616                 tb[0].t_lbl = "Proxy Userid: ";
9617                 tb[0].t_dflt = NULL;
9618                 tb[0].t_echo = 1;
9619                 tb[1].t_buf = pwd;
9620                 tb[1].t_len = 256;
9621                 tb[1].t_lbl = "Proxy Passphrase: ";
9622                 tb[1].t_dflt = NULL;
9623                 tb[1].t_echo = 2;
9624 
9625                 ok = uq_mtxt("Proxy Server Authentication Required\n",
9626                               NULL, 2, tb);
9627 
9628 		if (ok && uid[0]) {
9629 		    char * proxy_user, * proxy_pwd;
9630 
9631 		    proxy_user = tcp_http_proxy_user;
9632 		    proxy_pwd  = tcp_http_proxy_pwd;
9633 
9634 		    tcp_http_proxy_user = uid;
9635 		    tcp_http_proxy_pwd = pwd;
9636 
9637 		    ckstrncpy(ttname,line,TTNAMLEN);
9638 		    y = ttopen(line, &_local, mdmtyp, 0);
9639 		    memset(pwd,0,sizeof(pwd));
9640 		    tcp_http_proxy_user = proxy_user;
9641 		    tcp_http_proxy_pwd = proxy_pwd;
9642 		} else
9643 		  break;
9644 	    } else
9645 	      break;
9646 	}
9647 #endif /* NOHTTP */
9648 	if (y < 0) {
9649 	    slrestor();
9650 	    makestr(&slmsg,"Network connection failure");
9651 #ifdef VMS
9652 	    if (msg && hints && !xcmdsrc && IS_RLOGIN()) {
9653 		makestr(&slmsg,"RLOGIN failure");
9654 		if  (socket_errno == EACCES) {
9655 		    printf("*************************\n");
9656 		    printf(
9657 	   "Hint: RLOGIN requires privileges to open an outbound port.\n");
9658 		    printf(
9659 		    "(Use SET HINTS OFF to suppress future hints.)\n");
9660 		    printf("*************************\n");
9661 		}
9662 	    }
9663 #else  /* Not VMS... */
9664 	    if (errno) {
9665 		int x;
9666 		debug(F111,"set host line, errno","",errno);
9667 		makestr(&slmsg,ck_errstr());
9668 		if (msg) {
9669 #ifdef OS2
9670 		    printf("Can't connect to %s\n",line);
9671 #else /* OS2 */
9672 #ifdef UNIX
9673 		    if (hints && !xcmdsrc && IS_RLOGIN()) {
9674 			makestr(&slmsg,"RLOGIN failure");
9675 			printf("*************************\n");
9676 			printf(
9677 	 "Hint: RLOGIN requires privileges to open an outbound port.\n");
9678 			printf(
9679 	 "(Use SET HINTS OFF to suppress future hints.)\n");
9680 			printf("*************************\n");
9681 		    }
9682 #endif /* UNIX */
9683 #endif /* OS2 */
9684 		} else printf("Can't connect to %s\n",line);
9685 	    } else
9686 #endif /* VMS */
9687 	      if (msg) printf("Can't open connection to %s\n",line);
9688 	    continue;
9689 	} else {
9690 	    success = 1;
9691 #ifndef NODIAL
9692 	    dialsta = DIA_UNK;
9693 #endif /* NODIAL */
9694 	    switch (net) {
9695 	      case NET_TCPA:
9696 	      case NET_TCPB:
9697 		cxtype = CXT_TCPIP;
9698 #ifdef COMMENT
9699 /* This works but it messes up interactive anonymous login */
9700 #ifndef NOXFER
9701 #ifdef IKS_OPTION
9702 		/* If we have connected to an Internet Kermit service */
9703 		/* and a /USER: switch was given, then log in. */
9704 
9705 		if (TELOPT_U(TELOPT_KERMIT) || TELOPT_ME(TELOPT_KERMIT)) {
9706 		    debug(F111,"cx_net IKSD /USER:",uidbuf,haveuser);
9707 		    if (haveuser /* && cx == 0 */ ) { /* /USER: given */
9708 			char * psw = pwbuf; /* Do we have a password? */
9709 			if (!*psw) {        /* No... */
9710 			    if (!strcmp(uidbuf,"anonymous") ||
9711 				!strcmp(uidbuf,"ftp")) {
9712 				extern char myhost[];
9713 				char * u = (char *)sl_uidbuf;
9714 				char * h = (char *)myhost;
9715 				if (!*u) u = "nobody";
9716 				if (!*h) h = "nowhere";
9717 				ckmakmsg(tmpbuf,TMPBUFSIZ,u,"@",h,NULL);
9718 				psw = tmpbuf;
9719 				debug(F110,"cx_net IKSD anon",psw,0);
9720 			    } else {
9721 				readpass(" Password: ",pwbuf,PWBUFL);
9722 			    }
9723 			}
9724 			sstate = setgen('I',uidbuf,psw,"");
9725 		    }
9726 		}
9727 #endif /* IKS_OPTION */
9728 #endif /* NOXFER */
9729 #endif /* COMMENT */
9730 		break;
9731 	      case NET_SSH:
9732 		cxtype = CXT_SSH;
9733 		duplex = 0;         /* Remote echo */
9734 		break;
9735 	      case NET_SLAT:
9736 		cxtype = CXT_LAT;
9737 		break;
9738 	      case NET_SX25:
9739 	      case NET_IX25:
9740 	      case NET_HX25:
9741 	      case NET_VX25:
9742 		cxtype = CXT_X25;
9743 		break;
9744 	      case NET_BIOS:
9745 		cxtype = CXT_NETBIOS;
9746 		break;
9747 	      case NET_FILE:
9748 	      case NET_PIPE:
9749 	      case NET_CMD:
9750 	      case NET_DLL:
9751 	      case NET_PTY:
9752 		cxtype = CXT_PIPE;
9753 		break;
9754 	      default:
9755 		cxtype = CXT_PIPE;
9756 		break;
9757 	    }
9758 	    break;
9759 	}
9760     } /* for-loop */
9761     s = line;
9762 
9763     debug(F101,"cx_net post ttopen success","",success);
9764     if (!success) {
9765         local = dfloc;                  /* Go back to normal */
9766 #ifndef MAC
9767         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty name */
9768 #endif /* MAC */
9769         speed = ttgspd();
9770         network = 0;                    /* No network connection active */
9771         haveline = 0;
9772         if (mdmtyp < 0) {               /* Switching from net to async? */
9773             if (mdmsav > -1)            /* Restore modem type from last */
9774               mdmtyp = mdmsav;          /* SET MODEM command, if any. */
9775             else
9776               mdmtyp = 0;
9777             mdmsav = -1;
9778         }
9779         return(0);                      /* Return failure */
9780     }
9781     if (_local > -1) local = _local;    /* Opened ok, set local/remote. */
9782     makestr(&slmsg,NULL);
9783     network = (mdmtyp < 0);             /* Remember connection type. */
9784     ckstrncpy(ttname,s,TTNAMLEN);       /* Copy name into real place. */
9785     debug(F110,"cx_net ok",ttname,0);
9786     debug(F101,"cx_net network","",network);
9787 #ifndef NOXFER
9788     if ((reliable != SET_OFF || !setreliable)) /* Assume not reliable. */
9789       reliable = SET_OFF;
9790 #endif /* NOXFER */
9791     if (!network || istncomport())
9792       speed = ttgspd();                 /* Get the current speed. */
9793     debug(F101,"cx_net local","",local);
9794     if (network) {
9795         debug(F101,"cx_net net","",net);
9796 #ifndef NOXFER
9797         /* Force prefixing of 255 on TCP/IP connections... */
9798         if (net == NET_TCPB
9799 #ifdef SSHBUILTIN
9800              || net == NET_SSH
9801 #endif /* SSHBUILTIN */
9802              ) {
9803             debug(F101,"cx_net reliable A","",reliable);
9804 #ifdef CK_SPEED
9805             ctlp[(unsigned)255] = 1;
9806 #endif /* CK_SPEED */
9807             if ((reliable != SET_OFF || !setreliable)) {
9808 #ifdef TN_COMPORT
9809                 if (istncomport()) {    /* Telnet communication port */
9810                     reliable = SET_OFF; /* Transport is not reliable */
9811                     debug(F101,"cx_net reliable istncomport()","",1);
9812                 } else {
9813                     reliable = SET_ON;  /* Transport is reliable end to end */
9814                     debug(F101,"cx_net reliable istncomport()","",0);
9815                 }
9816 #else
9817                 reliable = SET_ON;      /* Transport is reliable end to end */
9818 #endif /* ifdef TN_COMPORT */
9819             }
9820             debug(F101,"cx_net reliable B","",reliable);
9821         } else if (net == NET_SX25 ||
9822                    net == NET_VX25 ||
9823                    net == NET_IX25 ||
9824                    net == NET_HX25) {
9825             duplex = 1;                 /* Local echo for X.25 */
9826             if (reliable != SET_OFF || !setreliable)
9827               reliable = SET_ON;        /* Transport is reliable end to end */
9828         }
9829 #endif /* NOXFER */
9830     }
9831 #ifndef NOXFER
9832     debug(F101,"cx_net reliable","",reliable);
9833 #endif /* NOXFER */
9834 #ifdef OS2
9835     if (mdmtyp <= 0)                    /* Network or Direct Connection */
9836       DialerSend(OPT_KERMIT_CONNECT, 0);
9837 #endif /* OS2 */
9838 
9839   xcx_net:
9840 
9841     setflow();                          /* Set appropriate flow control */
9842 
9843     haveline = 1;
9844 #ifdef CKLOGDIAL
9845     dolognet();
9846 #endif /* CKLOGDIAL */
9847 
9848 #ifndef NOSPL
9849     if (local) {
9850         if (nmac) {                     /* Any macros defined? */
9851             int k;                      /* Yes */
9852             k = mlook(mactab,"on_open",nmac);   /* Look this up */
9853             if (k >= 0) {                       /* If found, */
9854                 if (dodo(k,ttname,0) > -1)      /* set it up, */
9855                   parser(1);                    /* and execute it */
9856             }
9857         }
9858     }
9859 #endif /* NOSPL */
9860 
9861     if (local && (cx || sx)) {          /* /CONNECT or /SERVER switch given */
9862         if (cx) {                       /* /CONNECT */
9863 	    if (!gui) {
9864 		/* Command was confirmed so we can pre-pop command level.  */
9865 		/* This is so CONNECT module won't think we're executing a */
9866 		/* script if CONNECT was the final command in the script.  */
9867 		if (cmdlvl > 0)
9868 		  prepop();
9869 	    }
9870 #ifndef NODIAL
9871             dialsta = DIA_UNK;
9872 #endif /* NODIAL */
9873 #ifdef LOCUS
9874             if (autolocus) {
9875 		setlocus(1,1);
9876             }
9877 #endif /* LOCUS */
9878             success = doconect(0, cmdlvl == 0 ? 1 : 0);
9879             if (ttchk() < 0)
9880               dologend();
9881 	    debug(F101,"cx_net post doconect success","",success);
9882             return(success);
9883 #ifndef NOXFER
9884         } else if (sx) {                /* /SERVER */
9885             sstate = 'x';
9886 #ifdef MAC
9887             what = W_RECV;
9888             scrcreate();
9889 #endif /* MAC */
9890             if (local) displa = 1;
9891 #ifdef AMIGA
9892             reqoff();                   /* No DOS requestors while server */
9893 #endif /* AMIGA */
9894 #endif /* NOXFER */
9895         }
9896     }
9897 #ifndef NODIAL
9898     dialsta = DIA_UNK;
9899 #endif /* NODIAL */
9900 #ifdef LOCUS
9901     if (autolocus) {
9902         setlocus(1,1);
9903     }
9904 #endif /* LOCUS */
9905     return(success = 1);
9906 }
9907 #endif /* NETCONN */
9908 
9909 /* c x _ s e r i a l  --  Make a serial connection */
9910 
9911 /*
9912   Call with:
9913     device  = string pointer to device name.
9914     cx      = 1 to automatically enter Connect mode, 0 otherwise.
9915     sx      = 1 to automatically enter Server mode, 0 otherwise.
9916     shr     = 1 if device should be opened in shareable mode, 0 otherwise.
9917     flag    = if no dev name given: 1 = close current connection, 0 = resume.
9918     gui     = 1 if called from GUI dialog, 0 otherwise.
9919   Returns:
9920     1 on success
9921     0 on failure and no message printed, slmsg set to failure message.
9922    -9 on failure and message printed, ditto.
9923 */
9924 
9925 /* these are bit flags */
9926 #define CX_TAPI 1
9927 #define CX_PPP  2
9928 #define CX_SLIP 4
9929 
9930 int
9931 #ifdef CK_ANSIC
cx_serial(char * device,int cx,int sx,int shr,int flag,int gui,int special)9932 cx_serial(char *device,
9933           int cx, int sx, int shr, int flag, int gui, int special)
9934 #else /* CK_ANSIC */
9935 cx_serial(device, cx, sx, shr, flag, gui, special)
9936     char * device; int cx, sx, shr, flag, gui, special;
9937 #endif /* CK_ANSIC */
9938 /* cx_serial */ {
9939     int i, n, x, y, msg;
9940     int _local = -1;
9941     char *s;
9942 
9943     debug(F110,"cx_serial device",device,0);
9944     s = device;
9945     msg = (gui == 0) && msgflg;		/* Whether to print messages */
9946     success = 0;
9947 
9948 #ifndef NODIAL
9949     dialsta = DIA_UNK;
9950 #endif /* NODIAL */
9951     debug(F101,"cx_serial mdmtyp","",mdmtyp);
9952     if (clskconnx(1) < 0)		/* Close the Kermit connection */
9953       return(success = 0);
9954     if (*s) {				/* They gave a device name */
9955 	_local = -1;			/* Let ttopen decide about it */
9956     } else {				/* They just said "set line" */
9957 	s = dftty;			/* so go back to normal tty */
9958 	_local = dfloc;			/* and mode. */
9959     }
9960 #ifdef VMS
9961     {
9962 	extern int ok_to_share;
9963 	ok_to_share = shr;
9964     }
9965 #endif /* VMS */
9966 
9967 #ifdef OS2                              /* Must wait until after ttclos() */
9968 #ifdef NT                               /* to change these settings       */
9969 #ifdef CK_TAPI
9970     tttapi = special & CX_TAPI;
9971 #endif /* CK_TAPI */
9972 #else
9973     ttslip = special & CX_SLIP;
9974     ttppp  = special & CX_PPP;
9975 #endif /* NT */
9976     ttshare = shr;			/* Shareable device ? */
9977     debug(F110,"OS2 SET PORT final s",s,"");
9978 #endif /* OS2 */
9979 
9980     /* Open the new line */
9981 
9982     ckstrncpy(ttname,s,TTNAMLEN);
9983     if ((y = ttopen(s,&_local,mdmtyp,cdtimo)) > -1) {
9984 	cxtype = (mdmtyp > 0) ? CXT_MODEM : CXT_DIRECT;
9985 #ifndef NODIAL
9986 	dialsta = DIA_UNK;
9987 #ifdef CK_TAPI
9988 	/* if the line is a tapi device, then we need to auto-execute */
9989 	/* SET MODEM TYPE TAPI - which we do the equivalent of here.  */
9990 	if (tttapi) {
9991 	    extern int usermdm;
9992 	    usermdm = 0;
9993 	    initmdm(38);		/* From ckudia.c n_TAPI == 38 */
9994 	}
9995 #endif /* CK_TAPI */
9996 #endif /* NODIAL */
9997 	success = 1;
9998     } else {				/* Failed */
9999 #ifdef OS2ONLY
10000 	if (!strcmp(s,dftty))   /* Do not generate an error with dftty */
10001 	  ;
10002 	else if (y == -6 && ttslip) {
10003 	    makestr(&slmsg,"Can't access SLIP driver");
10004 	    if (msg) printf("?%s\n",slmsg);
10005 	} else if (y == -6 && ttppp) {
10006 	    makestr(&slmsg,"Can't access PPP driver");
10007 	    if (msg) printf("?%s\n",slmsg);
10008 	} else
10009 #endif /* OS2ONLY */
10010 	  if (y == -2) {
10011 	      makestr(&slmsg,"Timed out - no carrier");
10012 	      if (msg) {
10013 		  printf("?%s\n",slmsg);
10014 		  if (hints) {
10015 		      printf("\n*************************\n");
10016 		      printf(
10017 		       "HINT (Use SET HINTS OFF to suppress future hints):\n");
10018 		      printf(
10019 			  "Try SET CARRIER OFF and SET LINE again, or else\n");
10020 		      printf("SET MODEM, SET LINE, and then DIAL.\n");
10021 		      printf("*************************\n\n");
10022 		  }
10023 	      }
10024 	  } else if (y == -3) {
10025 	      makestr(&slmsg,"Access to lock denied");
10026 	      if (msg) {
10027 #ifdef UNIX
10028 		  printf(
10029 		   "Sorry, write access to UUCP lockfile directory denied.\n");
10030 #ifndef NOHINTS
10031 		  if (hints) {
10032 		      printf("\n*************************\n");
10033 		      printf(
10034 		       "HINT (Use SET HINTS OFF to suppress future hints):\n");
10035 		      printf(
10036 	  "Please read the installation instructions file, %sckuins.txt,\n",
10037 	                     k_info_dir ? k_info_dir : ""
10038                              );
10039 		      printf(
10040 	  "or the UNIX appendix of the manual, \"Using C-Kermit\"\n"
10041                              );
10042 		      printf(
10043           "or visit http://www.kermitproject.org/ckuins.html \n"
10044                              );
10045 		      printf("*************************\n\n");
10046 		  }
10047 #endif /* NOHINTS */
10048 #else
10049 		  printf("Sorry, access to lock denied: %s\n",s);
10050 #endif /* UNIX */
10051 	      }
10052 	  } else if (y == -4) {
10053 	      makestr(&slmsg,"Access to device denied");
10054 	      if (msg) {
10055 		  printf("Sorry, access to device denied: %s\n",s);
10056 #ifdef UNIX
10057 #ifndef NOHINTS
10058 		  if (hints) {
10059 		      printf("\n*************************\n");
10060 		      printf(
10061 		      "HINT (Use SET HINTS OFF to suppress future hints):\n");
10062 		      printf(
10063 	    "Please read the installation instructions file, %sckuins.txt,\n",
10064                              k_info_dir ? k_info_dir : ""
10065                              );
10066 		      printf(
10067 	    "or the UNIX appendix of the manual, \"Using C-Kermit\".\n"
10068                              );
10069 		      printf("*************************\n\n");
10070 		  }
10071 #endif /* NOHINTS */
10072 #endif /* UNIX */
10073 	      }
10074 	  } else if (y == -5) {
10075 	      makestr(&slmsg,"Device is in use or unavailable");
10076 	      if (msg)
10077 #ifdef VMS
10078 		printf(
10079 		  "Sorry, device is in use or otherwise unavailable: %s\n",s);
10080 #else
10081 	      printf("Sorry, device is in use: %s\n",s);
10082 #endif /* VMS */
10083 	  } else {			/* Other error. */
10084 	      makestr(&slmsg,"Device open failed");
10085 	      if (
10086 #ifdef VMS
10087 		  1
10088 #else
10089 		  errno
10090 #endif /* VMS */
10091 		  ) {
10092 		  int x;		/* Find a safe, long buffer */
10093 		  makestr(&slmsg,ck_errstr());
10094 #ifndef VMS
10095 		  debug(F111,"cx_serial serial errno",slmsg,errno);
10096 #endif /* VMS */
10097 		  if (msg)
10098 		    printf("Connection to %s failed: %s\n",s,slmsg);
10099 	      } else if (msg)
10100 		printf("Sorry, can't open connection: %s\n",s);
10101 	  }
10102     }
10103     network = 0;			/* No network connection active */
10104     speed = ttgspd();
10105     if (!success) {
10106         local = dfloc;                  /* Go back to normal */
10107 #ifndef MAC
10108         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty name */
10109 #endif /* MAC */
10110         haveline = 0;
10111         if (mdmtyp < 0) {               /* Switching from net to async? */
10112             if (mdmsav > -1)            /* Restore modem type from last */
10113               mdmtyp = mdmsav;          /* SET MODEM command, if any. */
10114             else
10115               mdmtyp = 0;
10116             mdmsav = -1;
10117         }
10118         return(msg ? -9 : 0);		/* Return failure */
10119     }
10120     if (_local > -1)
10121       local = _local;			/* Opened ok, set local/remote. */
10122     makestr(&slmsg,NULL);		/* Erase SET LINE message */
10123     ckstrncpy(ttname,s,TTNAMLEN);       /* Copy name into real place. */
10124     debug(F110,"cx_serial ok",ttname,0);
10125 #ifndef NOXFER
10126     if ((reliable != SET_OFF || !setreliable)) /* Assume not reliable. */
10127       reliable = SET_OFF;
10128 #endif /* NOXFER */
10129 
10130   xcx_serial:
10131     setflow();                          /* Set appropriate flow control */
10132     haveline = 1;
10133 #ifdef CKLOGDIAL
10134       dologline();
10135 #endif /* CKLOGDIAL */
10136 
10137 #ifndef NOSPL
10138     if (local) {
10139         if (nmac) {                     /* Any macros defined? */
10140             int k;                      /* Yes */
10141             k = mlook(mactab,"on_open",nmac);   /* Look this up */
10142             if (k >= 0) {                       /* If found, */
10143                 if (dodo(k,ttname,0) > -1)      /* set it up, */
10144                   parser(1);                    /* and execute it */
10145             }
10146         }
10147     }
10148 #endif /* NOSPL */
10149 
10150     if (local && (cx || sx)) {          /* /CONNECT or /SERVER switch given */
10151         extern int carrier;
10152         if (carrier != CAR_OFF) {	/* Looking for carrier? */
10153             /* Open() turns on DTR -- wait up to a second for CD to come up */
10154             int i, x;
10155             for (i = 0; i < 10; i++) {  /* WAIT 1 CD... */
10156                 x = ttgmdm();
10157                 if (x < 0 || x & BM_DCD)
10158                   break;
10159                 msleep(100);
10160             }
10161         }
10162         if (cx) {                       /* /CONNECT */
10163             /* Command was confirmed so we can pre-pop command level. */
10164             /* This is so CONNECT module won't think we're executing a */
10165             /* script if CONNECT was the final command in the script. */
10166 
10167             if (cmdlvl > 0)
10168               prepop();
10169 #ifndef NODIAL
10170             dialsta = DIA_UNK;
10171 #endif /* NODIAL */
10172 #ifdef LOCUS
10173             if (autolocus) {
10174                 setlocus(1,1);
10175             }
10176 #endif /* LOCUS */
10177             success = doconect(0, cmdlvl == 0 ? 1 : 0);
10178             if (ttchk() < 0)
10179               dologend();
10180             return(success);
10181 #ifndef NOXFER
10182         } else if (sx) {                /* /SERVER */
10183             sstate = 'x';
10184 #ifdef MAC
10185             what = W_RECV;
10186             scrcreate();
10187 #endif /* MAC */
10188             if (local) displa = 1;
10189 #ifdef AMIGA
10190             reqoff();                   /* No DOS requestors while server */
10191 #endif /* AMIGA */
10192 #endif /* NOXFER */
10193         }
10194     }
10195 #ifndef NODIAL
10196     dialsta = DIA_UNK;
10197 #endif /* NODIAL */
10198 #ifdef LOCUS
10199     if (autolocus) {
10200         setlocus(1,1);
10201     }
10202 #endif /* LOCUS */
10203     return(success = 1);
10204 }
10205 
10206 
10207 /* S E T L I N -- parse name of and then open communication device. */
10208 /*
10209   Call with:
10210     xx == XYLINE for a serial (tty) line, XYHOST for a network host,
10211     zz == 0 means if user doesn't give a device name, continue current
10212             active connection (if any);
10213     zz != 0 means if user doesn't give a device name, then close the
10214             current connection and restore the default communication device.
10215     fc == 0 to just make the connection, 1 to also CONNECT (e.g. "telnet").
10216 */
10217 int
setlin(xx,zz,fc)10218 setlin(xx, zz, fc)
10219     int xx, zz, fc;
10220 {
10221     extern char pwbuf[], * g_pswd;
10222     extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
10223     int wait;
10224     /* int tn_wait_sv; */
10225     int mynet;
10226     int _local = -1;
10227     int c, i, haveswitch = 0;
10228     int haveuser = 0;
10229     int getval = 0;
10230     int wild = 0;                       /* Filespec has wildcards */
10231     int cx = 0;                         /* Connect after */
10232     int sx = 0;                         /* Become server after */
10233     int a_type = -1;                    /* Authentication type */
10234     int e_type = -1;                    /* Telnet /ENCRYPT type */
10235 #ifdef CK_ENCRYPTION
10236     int encrypt = 0;                    /* Encrypted? */
10237 #endif /* CK_ENCRYPTION */
10238     int shr = 0;                        /* Share serial device */
10239     int confirmed = 0;                  /* Command has been entered */
10240     struct FDB sw, tx, nx;
10241 #ifdef OS2
10242     struct FDB fl;
10243 #endif /* OS2 */
10244 
10245     char * ss;
10246 #ifdef TCPSOCKET
10247     int rawflg = 0;
10248 #endif /* TCPSOCKET */
10249 
10250     char srvbuf[SRVBUFSIZ+1];
10251 
10252 #ifdef OS2
10253 #ifdef NT
10254     int xxtapi = 0;
10255 #else
10256     int xxslip = 0, xxppp = 0;
10257 #endif /* NT */
10258 #endif /* OS2 */
10259 
10260     int dossh = 0;
10261 
10262     debug(F101,"setlin fc","",fc);
10263     debug(F101,"setlin zz","",zz);
10264     debug(F101,"setlin xx","",xx);
10265 
10266 #ifdef SSHCMD
10267     if (xx == XXSSH) {                  /* SSH becomes PTY SSH ... */
10268         dossh = 1;
10269         xx = XYHOST;
10270     } else if (!ckstrcmp("ssh ",line,4,0)) { /* 2010/03/01 */
10271         dossh = 1;
10272         xx = XYHOST;
10273     }
10274     debug(F101,"setlin dossh","",dossh);
10275 #endif /* SSHCMD */
10276 
10277 #ifdef TNCODE
10278     /* tn_wait_sv = tn_wait_flg; */
10279     wait = tn_wait_flg;
10280 #else
10281     /* tn_wait_sv = 0; */
10282     wait = 0;
10283 #endif /* TNCODE */
10284 
10285     mynet = nettype;
10286 
10287     if (nolocal) {
10288         makestr(&slmsg,"Making connections is disabled");
10289         printf("?Sorry, making connections is disabled\n");
10290         return(-9);
10291     }
10292     if (netsave > -1)
10293       nettype = netsave;
10294 
10295     if (fc != 0 || zz == 0)             /* Preset /CONNECT switch */
10296       cx = 1;
10297 
10298     debug(F101,"setlin cx","",cx);
10299 
10300     *srvbuf = NUL;
10301 
10302     line[0] = NUL;
10303     s = line;
10304 
10305 #ifdef NETCONN
10306 #ifdef CK_SECURITY
10307     if (tmpstring)
10308         makestr(&tmpstring,NULL);
10309 #endif /* CK_SECURITY */
10310     if (tmpusrid)
10311         makestr(&tmpusrid,NULL);
10312 #endif /* NETCONN */
10313 
10314     autoflow = 1;                       /* Enable automatic flow setting */
10315 
10316     if (xx == XYHOST) {                 /* SET HOST <hostname> */
10317 #ifndef NETCONN
10318         makestr(&slmsg,"Network connections not supported");
10319         printf("?%s\n",slmsg);
10320         return(-9);
10321 #else /* NETCONN */
10322 #ifndef NOPUSH
10323         if ((mynet == NET_CMD || mynet == NET_PTY || dossh) && nopush) {
10324             makestr(&slmsg,"Access to external commands is disabled");
10325             printf("?Sorry, access to external commands is disabled\n");
10326             return(-9);
10327         }
10328 #endif /* NOPUSH */
10329 
10330 #ifdef SSHCMD
10331         if (dossh) {                    /* SSH connection via pty */
10332             int k;
10333 	    extern int ttyfd;		/* 2010/03/01 */
10334             k = ckstrncpy(line, sshcmd ? sshcmd : defsshcmd, LINBUFSIZ);
10335             debug(F111,"setlin sshcmd 1",line,k);
10336             if ((x = cmtxt("Optional switches and hostname","",&s,xxstring))<0)
10337               return(x);
10338 
10339             /* 2010-03-30 */
10340 	    if (!*s && ttyfd < 0 && !ckstrcmp("ssh ",ttname,4,0)) {
10341 		x = ckstrncpy(line,ttname,LINBUFSIZ);
10342 	    } else {
10343 		if (!*s) {
10344 		    printf("?SSH to where?\n");
10345 		    return(-9);
10346 		}
10347 		if (k < LINBUFSIZ) {
10348 		    line[k++] = SP;
10349 		    line[k] = NUL;
10350 		    debug(F111,"setlin sshcmd 2",line,k);
10351 		} if (k < LINBUFSIZ) {
10352 		    ckstrncpy(&line[k],s,LINBUFSIZ-k);
10353 		    debug(F111,"setlin sshcmd 3",line,k);
10354 		} else {
10355 		    printf("?Too long\n");
10356 		    return(-9);
10357 		}
10358 	    }
10359 	    x = cx_net( NET_PTY,                /* network type */
10360                         0,                      /* protocol (not used) */
10361                         line,                   /* host */
10362                         NULL,                   /* service (not used) */
10363                         NULL,                   /* username (not used) */
10364                         NULL,                   /* password (not used) */
10365                         NULL,                   /* command (not used) */
10366                         -1,-1,-1,               /* params 1-3 (not used) */
10367                         1,                      /* connect immediately */
10368                         sx,                     /* server? */
10369                         zz,                     /* close current? */
10370                         0);                     /* not gui */
10371 	    debug(F111,"setlin cx_net",line,x);
10372 	    return(x);
10373         }
10374 #endif /* SSHCMD */
10375 
10376 /*
10377   Here we parse optional switches and then the hostname or whatever,
10378   which depends on the network type.  The tricky part is, the network type
10379   can be set by a switch.
10380 */
10381 #ifndef NOSPL
10382         makestr(&g_pswd,pwbuf);         /* Save global pwbuf */
10383         g_pflg = pwflg;                 /* and flag */
10384         g_pcpt = pwcrypt;
10385 #endif /* NOSPL */
10386 
10387         confirmed = 0;
10388         haveswitch = 0;
10389 #ifdef NETFILE
10390         if (mynet != NET_FILE) {
10391 #endif /* NETFILE */
10392             ss = (mynet == NET_CMD || mynet == NET_PTY) ?
10393               "Command, or switch" :
10394                 (mynet == NET_TCPA || mynet == NET_TCPB
10395                   || mynet == NET_SSH) ?
10396                   "Hostname, ip-address, or switch" :
10397                     "Host or switch";
10398             if (fc) {
10399                 if (mynet == NET_TCPB &&
10400                     (ttnproto == NP_TELNET || ttnproto == NP_KERMIT)) {
10401                     if (nshteltab) {
10402                         haveswitch++;
10403                         cmfdbi(&sw,_CMKEY,ss,"","",nshteltab,4,xxstring,
10404                              shteltab,&nx);
10405                     }
10406                 }
10407 #ifdef RLOGCODE
10408                 else if (mynet == NET_TCPB && ttnproto == NP_RLOGIN) {
10409                     if (nshrlgtab) {
10410                         haveswitch++;
10411                         cmfdbi(&sw,_CMKEY,ss,"","",nshrlgtab,4,xxstring,
10412                                shrlgtab,&nx);
10413                     }
10414                 }
10415 #endif /* RLOGCODE */
10416             } else {
10417                 haveswitch++;
10418                 cmfdbi(&sw,_CMKEY,ss,"","",nshtab,4,xxstring,shtab,&nx);
10419             }
10420 #ifdef NETFILE
10421         }
10422 #endif /* NETFILE */
10423         if (mynet == NET_TCPB || mynet == NET_SLAT ||
10424 	    mynet == NET_SSH  || mynet == NET_DEC) {
10425             cmfdbi(&nx,_CMFLD,"Host","","",0,0,xxstring,NULL,NULL);
10426 #ifdef NETFILE
10427         } else if (mynet == NET_FILE) {
10428             cmfdbi(&nx,_CMIFI,"Filename","","",0,0,xxstring,NULL,NULL);
10429 #endif /* NETFILE */
10430 #ifdef PTYORPIPE
10431         } else if (mynet == NET_CMD || mynet == NET_PTY) {
10432             cmfdbi(&nx,_CMTXT,"Command","","",0,0,xxstring,NULL,NULL);
10433 #endif /* PTYORPIPE */
10434         } else {
10435             cmfdbi(&nx,_CMTXT,"Host","","",0,0,xxstring,NULL,NULL);
10436         }
10437         while (1) {
10438             x = cmfdb(haveswitch ? &sw : &nx);
10439             debug(F101,"setlin cmfdb","",x);
10440             if (x < 0)
10441               if (x != -3)
10442                 return(x);
10443             if (x == -3) {
10444                 if ((x = cmcfm()) < 0) {
10445                     return(x);
10446                 } else {
10447                     confirmed = 1;
10448                     break;
10449                 }
10450             }
10451             if (cmresult.fcode != _CMKEY) {    /* Not a switch */
10452                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Save the data */
10453                 s = line;                      /* that was parsed... */
10454                 if (cmresult.fcode == _CMIFI) {
10455                     wild = cmresult.nresult;
10456                 } else if (cmresult.fcode == _CMTXT) {
10457                     confirmed = 1;
10458                 }
10459                 break;                  /* and break out of this loop */
10460             }
10461             c = cmgbrk();               /* Have switch - get break character */
10462             getval = (c == ':' || c == '='); /* Must parse an agument? */
10463             if (getval && !(cmresult.kflags & CM_ARG)) {
10464                 printf("?This switch does not take arguments\n");
10465                 return(-9);
10466             }
10467             if (!getval && (cmgkwflgs() & CM_ARG)) {
10468                 printf("?This switch requires an argument\n");
10469                 return(-9);
10470             }
10471             switch (cmresult.nresult) { /* It's a switch.. */
10472               case SL_CNX:              /* /CONNECT */
10473                 cx = 1;
10474                 sx = 0;
10475                 break;
10476               case SL_SRV:              /* /SERVER */
10477                 cx = 0;
10478                 sx = 1;
10479                 break;
10480 #ifdef NETCMD
10481               case SL_CMD:              /* /COMMAND */
10482                 netsave = mynet;
10483                 mynet = NET_CMD;
10484                 break;
10485 #endif /* NETCMD */
10486 #ifdef NETPTY
10487               case SL_PTY:              /* /PTY */
10488                 netsave = mynet;
10489                 mynet = NET_PTY;
10490                 break;
10491 #endif /* NETPTY */
10492               case SL_NET:              /* /NETWORK-TYPE */
10493                 if ((x = cmkey(netcmd,nnets,"","",xxstring)) < 0)
10494                   return(x);
10495                 mynet = x;
10496                 break;
10497 
10498 #ifdef CK_SECURITY
10499               case SL_PSW:              /* /PASSWORD: */
10500                 if (!getval)
10501                   break;
10502                 debok = 0;
10503                 if ((x = cmfld("Password","",&s,xxstring)) < 0) {
10504                     if (x == -3) {
10505                         makestr(&tmpstring,"");
10506                     } else {
10507                         return(x);
10508                     }
10509                 } else {
10510                     s = brstrip(s);
10511                     if ((x = (int)strlen(s)) > PWBUFL) {
10512                         makestr(&slmsg,"Internal error");
10513                         printf("?Sorry, too long - max = %d\n",PWBUFL);
10514                         return(-9);
10515                     }
10516                     makestr(&tmpstring,s);
10517                 }
10518                 break;
10519 #endif /* CK_SECURITY */
10520 
10521               case SL_UID:              /* /USERID: */
10522                 if (!getval)
10523                   break;
10524                 if ((x = cmfld("Userid","",&s,xxstring)) < 0) {
10525                     if (x == -3) {
10526                         makestr(&tmpusrid,"");
10527                     } else {
10528                         return(x);
10529                     }
10530                 } else {
10531                     s = brstrip(s);
10532                     if ((x = (int)strlen(s)) > 63) {
10533                         makestr(&slmsg,"Internal error");
10534                         printf("?Sorry, too long - max = %d\n",63);
10535                         return(-9);
10536                     }
10537                     makestr(&tmpusrid,s);
10538                     haveuser = 1;
10539                 }
10540                 break;
10541 
10542 #ifdef CK_AUTHENTICATION
10543 #ifdef CK_SRP
10544               case SL_SRP:
10545                 a_type = AUTHTYPE_SRP;
10546                 break;
10547 #endif /* CK_SRP */
10548 #ifdef CK_SSL
10549               case SL_SSL:
10550                 a_type = AUTHTYPE_SSL;
10551                 break;
10552 #endif /* CK_SSL */
10553 #ifdef NT
10554               case SL_NTLM:
10555                 a_type = AUTHTYPE_NTLM;
10556                 break;
10557 #endif /* NT */
10558 #ifdef CK_KERBEROS
10559               case SL_KRB4:
10560                 a_type = AUTHTYPE_KERBEROS_V4;
10561                 if (ttnproto == NP_RLOGIN)
10562                   ttnproto =
10563 #ifdef CK_ENCRYPTION
10564                     encrypt ? NP_EK4LOGIN :
10565 #endif /* CK_ENCRYPTION */
10566                       NP_K4LOGIN;
10567                 else if (ttnproto == NP_K5LOGIN)
10568                   ttnproto = NP_K4LOGIN;
10569 #ifdef CK_ENCRYPTION
10570                 else if (ttnproto == NP_EK5LOGIN)
10571                   ttnproto = NP_EK4LOGIN;
10572 #endif /* CK_ENCRYPTION */
10573                 break;
10574               case SL_KRB5:
10575                 a_type = AUTHTYPE_KERBEROS_V5;
10576                 if (ttnproto == NP_RLOGIN)
10577                   ttnproto =
10578 #ifdef CK_ENCRYPTION
10579                     encrypt ? NP_EK5LOGIN :
10580 #endif /* CK_ENCRYPTION */
10581                       NP_K5LOGIN;
10582                 else if (ttnproto == NP_K4LOGIN)
10583                   ttnproto = NP_K5LOGIN;
10584 #ifdef CK_ENCRYPTION
10585                 else if (ttnproto == NP_EK4LOGIN)
10586                   ttnproto = NP_EK5LOGIN;
10587 #endif /* CK_ENCRYPTION */
10588                 break;
10589 #endif /* CK_KERBEROS */
10590               case SL_AUTH: {
10591                   extern struct keytab autyptab[];
10592                   extern int nautyp;
10593                   if ((x = cmkey(autyptab,nautyp,"type of authentication",
10594                                  "automatic",xxstring)) < 0)
10595                     return(x);
10596                   a_type = x;
10597                   break;
10598               }
10599 #endif /* CK_AUTHENTICATION */
10600 #ifdef CK_ENCRYPTION
10601               case SL_ENC:
10602                 switch (ttnproto) {
10603                   case NP_K4LOGIN:
10604                     ttnproto = NP_EK4LOGIN;
10605                     encrypt = 1;
10606                     break;
10607                   case NP_K5LOGIN:
10608                     ttnproto = NP_EK5LOGIN;
10609                     encrypt = 1;
10610                     break;
10611                   case NP_KERMIT:
10612                   case NP_TELNET: {
10613                       static struct keytab * tnetbl = NULL;
10614                       static int ntnetbl = 0;
10615                       x = ck_get_crypt_table(&tnetbl,&ntnetbl);
10616                       debug(F101,"ck_get_crypt_table x","",x);
10617                       debug(F101,"ck_get_crypt_table n","",ntnetbl);
10618                       if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
10619                         x = 0;
10620                       if (!x) {
10621                           makestr(&slmsg,"Internal error");
10622                           printf("?Oops, types not loaded\n");
10623                           return(-9);
10624                       }
10625                       if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
10626                                      "automatic",xxstring)) < 0)
10627                         return(x);
10628                       e_type = x;
10629                       break;
10630                   }
10631                 }
10632                 break;
10633 #endif /* CK_ENCRYPTION */
10634               case SL_WAIT:
10635                 wait = 1;
10636                 break;
10637               case SL_NOWAIT:
10638                 wait = 0;
10639                 break;
10640             }
10641         }
10642 
10643 #ifdef NETFILE
10644         if (mynet == NET_FILE) {        /* Parsed by cmifi() */
10645 	    if ((x = cmcfm()) < 0)	/* Needs confirmation */
10646 	      return(x);
10647 	    x = cx_net(mynet,		/* nettype */
10648 		       0,		/* protocol (not used) */
10649 		       line,		/* host */
10650 		       "",		/* port */
10651 		       NULL,		/* alternate username */
10652 		       NULL,		/* password */
10653 		       NULL,		/* command to execute */
10654 		       0,		/* param1 */
10655 		       0,		/* param2 */
10656 		       0,		/* param3 */
10657 		       cx,		/* enter CONNECT mode */
10658 		       sx,		/* enter SERVER mode */
10659 		       zz,		/* close connection if open */
10660 		       0		/* gui */
10661 		       );
10662         }
10663 #endif /* NETFILE */
10664 
10665 #ifdef NETCMD
10666         if (mynet == NET_CMD || mynet == NET_PTY) {
10667             char *p = NULL;
10668             if (!confirmed) {
10669                 if ((x = cmtxt("Rest of command","",&s,xxstring)) < 0)
10670                   return(x);
10671                 if (*s) {
10672                     ckstrncat(line," ",LINBUFSIZ);
10673                     ckstrncat(line,s,LINBUFSIZ);
10674                 }
10675                 s = line;
10676             }
10677             /* s == line - so we must protect the line buffer */
10678             s = brstrip(s);
10679             makestr(&p,s);
10680             ckstrncpy(line,p,LINBUFSIZ);
10681             makestr(&p,NULL);
10682 
10683             x = cx_net( mynet,                  /* nettype */
10684                         0,                      /* protocol (not used) */
10685                         line,                   /* host */
10686                         "",                     /* port */
10687                         NULL,                   /* alternate username */
10688                         NULL,                   /* password */
10689                         NULL,                   /* command to execute */
10690                         0,                      /* param1 */
10691                         0,                      /* param2 */
10692                         0,                      /* param3 */
10693                         cx,                     /* enter CONNECT mode */
10694                         sx,                     /* enter SERVER mode */
10695                         zz,                     /* close connection if open */
10696                         0                       /* gui */
10697                         );
10698         }
10699 #endif /* NETCMD */
10700 
10701 #ifdef NPIPE                            /* Named pipe */
10702         if (mynet == NET_PIPE) {        /* Needs backslash twiddling */
10703             if (line[0]) {
10704                 if (strcmp(line,"*")) {    /* If remote, begin with */
10705                     char * p = NULL;
10706                     makestr(&p,line);
10707                     ckstrncpy(line,"\\\\",LINBUFSIZ); /* server name */
10708                     ckstrncat(line,p,LINBUFSIZ);
10709                     makestr(&p,NULL);
10710                 } else {
10711                     line[0]='\0';
10712                 }
10713                 ckstrncat(line,"\\pipe\\", LINBUFSIZ); /* Make pipe name */
10714                 ckstrncat(line,pipename, LINBUFSIZ); /* Add name of pipe */
10715 
10716                 x = cx_net(mynet,	/* nettype */
10717 			   0,		/* protocol (not used) */
10718 			   line,	/* host */
10719 			   "",		/* port */
10720 			   NULL,	/* alternate username */
10721 			   NULL,	/* password */
10722 			   NULL,	/* command to execute */
10723 			   0,		/* param1 */
10724 			   0,		/* param2 */
10725 			   0,		/* param3 */
10726 			   cx,		/* enter CONNECT mode */
10727 			   sx,		/* enter SERVER mode */
10728 			   zz,		/* close connection if open */
10729 			   0		/* gui */
10730 			   );
10731             }
10732         }
10733 #endif /* NPIPE */
10734 
10735 #ifdef SUPERLAT
10736         if (mynet == NET_SLAT) {        /* Needs password, etc. */
10737             slat_pwd[0] = NUL;          /* Erase any previous password */
10738             debok = 0;
10739             if (*line) {		/* If they gave a host name... */
10740                 if ((x = cmfld(
10741                      "password,\n or carriage return if no password required",
10742                                "",
10743                                &s,
10744                                xxstring
10745                                )) < 0 && x != -3)
10746                   return(x);
10747                 ckstrncpy(slat_pwd,s,18); /* Set the password, if any */
10748             }
10749             if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
10750 
10751             x = cx_net(mynet,		/* nettype */
10752                        0,		/* protocol (not used) */
10753                        line,		/* host */
10754                        "",		/* port */
10755                        NULL,		/* alternate username */
10756                        NULL,		/* password */
10757                        NULL,		/* command to execute */
10758                        0,		/* param1 */
10759                        0,		/* param2 */
10760                        0,		/* param3 */
10761                        cx,		/* enter CONNECT mode */
10762                        sx,		/* enter SERVER mode */
10763                        zz,		/* close connection if open */
10764                        0		/* gui */
10765                        );
10766         }
10767 #endif /* SUPERLAT */
10768 
10769 #ifdef DECNET
10770         if (mynet == NET_DEC) {
10771             if (!line[0]) {                   /* If they gave a host name... */
10772                 printf("?hostname required\n");
10773                 return(-3);
10774             }
10775             if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
10776 
10777             x = cx_net(mynet,		/* nettype */
10778                        0,		/* protocol (not used) */
10779                        line,		/* host */
10780                        "",		/* port */
10781                        NULL,		/* alternate username */
10782                        NULL,		/* password */
10783                        NULL,		/* command to execute */
10784                        0,		/* param1 */
10785                        0,		/* param2 */
10786                        0,		/* param3 */
10787                        cx,		/* enter CONNECT mode */
10788                        sx,		/* enter SERVER mode */
10789                        zz,		/* close connection if open */
10790                        0		/* gui */
10791                        );
10792         }
10793 #endif /* DECNET */
10794 
10795 #ifdef SSHBUILTIN
10796         if (mynet == NET_SSH) {		/* SSH connection */
10797             int k, havehost = 0, trips = 0;
10798             int    tmpver = -1, tmpxfw = -1, tmpssh_cas;
10799 #ifndef SSHTEST
10800             extern int sl_ssh_xfw, sl_ssh_xfw_saved;
10801             extern int sl_ssh_ver, sl_ssh_ver_saved;
10802 #endif /* SSHTEST */
10803             extern struct keytab sshopnsw[];
10804             extern int nsshopnsw;
10805             extern char *ssh_tmpcmd, *ssh_tmpport;
10806             struct FDB sw, kw, fl;
10807 
10808             debug(F110,"setlin SSH service 0",srvbuf,0);
10809             debug(F110,"setlin SSH host s 2",s,0);
10810             if (*s) {           /* If they gave a host name... */
10811                 debug(F110,"setlin SSH host s 1",s,0);
10812                 if (*s == '*') {
10813                     makestr(&slmsg,"Incoming connections not supported");
10814                     printf(
10815      "?Sorry, incoming connections not supported for SSH.\n"
10816                            );
10817                     return(-9);
10818                 }
10819                 ckstrncpy(line,s,LINBUFSIZ);
10820             } else {
10821                 printf("?hostname required\n");
10822                 return(-3);
10823             }
10824 
10825             /* Parse [ port ] [ switches ] */
10826             cmfdbi(&kw,                 /* Switches */
10827                     _CMKEY,
10828                     "Port number or service name,\nor switch",
10829                     "",
10830                     "",
10831                     nsshopnsw,
10832                     4,
10833                     xxstring,
10834                     sshopnsw,
10835                     &fl
10836                     );
10837             cmfdbi(&fl,                 /* Port number or service name */
10838                     _CMFLD,
10839                     "",
10840                     "",
10841                     "",
10842                     0,
10843                     0,
10844                     xxstring,
10845                     NULL,
10846                     NULL
10847                     );
10848             trips = 0;                  /* Explained below */
10849             while (1) {                 /* Parse port and switches */
10850                 y = cmfdb(&kw);         /* Get a field */
10851                 if (y == -3)            /* User typed CR so quit from loop */
10852                     break;
10853                 if (y < 0)              /* Other parse error, pass it back */
10854                     return(y);
10855                 switch (cmresult.fcode) { /* Field or Keyword? */
10856                 case _CMFLD:              /* Field */
10857                     ckstrncpy(srvbuf,cmresult.sresult,SRVBUFSIZ);
10858                     break;
10859                 case _CMKEY:            /* Keyword */
10860                     switch (cmresult.nresult) { /* Which one? */
10861                     case SSHSW_PWD:
10862                         if (!cmgbrk()) {
10863                             printf("?This switch requires an argument\n");
10864                             return(-9);
10865                         }
10866                         debok = 0;
10867                         if ((y = cmfld("Password","",&s,xxstring)) < 0) {
10868                             if (y == -3) {
10869                                 makestr(&tmpstring,"");
10870                             } else {
10871                                 return(y);
10872                             }
10873                         } else {
10874                             s = brstrip(s);
10875                             if ((y = (int)strlen(s)) > PWBUFL) {
10876                                 makestr(&slmsg,"Internal error");
10877                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
10878                                 return(-9);
10879                             }
10880                             makestr(&tmpstring,s);
10881                         }
10882                         break;
10883                     case SSHSW_USR:             /* /USER: */
10884                         if (!cmgbrk()) {
10885                             printf("?This switch requires an argument\n");
10886                             return(-9);
10887                         }
10888                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
10889                             return(y);
10890                         s = brstrip(s);
10891                         makestr(&tmpusrid,s);
10892                         break;
10893                     case SSHSW_VER:
10894                         if ((y = cmnum("Number","",10,&z,xxstring)) < 0)
10895                             return(y);
10896                         if (z < 1 || z > 2) {
10897                             printf("?Out of range: %d\n",z);
10898                             return(-9);
10899                         }
10900                         tmpver = z;
10901                         break;
10902                     case SSHSW_CMD:
10903                     case SSHSW_SUB:
10904                         if ((y = cmfld("Text","",&s,xxstring)) < 0)
10905                           return(y);
10906                         makestr(&ssh_tmpcmd,s);
10907                         tmpssh_cas = (cmresult.nresult == SSHSW_SUB);
10908                         break;
10909                     case SSHSW_X11:
10910                         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
10911                             return(y);
10912                         tmpxfw = y;
10913                         break;
10914                     default:
10915                         return(-2);
10916                     }
10917                 }
10918                 if (trips++ == 0) {     /* After first time through */
10919                     cmfdbi(&kw,         /* only parse switches, not port. */
10920                             _CMKEY,
10921                             "Switch",
10922                             "",
10923                             "",
10924                             nsshopnsw,
10925                             4,
10926                             xxstring,
10927                             sshopnsw,
10928                             NULL
10929                             );
10930                 }
10931             }
10932             if ((y = cmcfm()) < 0)      /* Get confirmation */
10933                 return(y);
10934 
10935             debug(F110,"setlin pre-cx_net line",line,0);
10936             debug(F110,"setlin pre-cx_net srvbuf",srvbuf,0);
10937             x = cx_net( mynet,                  /* nettype */
10938                         0,                      /* protocol (not used) */
10939                         line,                   /* host */
10940                         srvbuf,                 /* port */
10941                         tmpusrid,               /* alternate username */
10942                         tmpstring,              /* password */
10943                         ssh_tmpcmd,             /* command to execute */
10944                         tmpver,                 /* param1 - ssh version */
10945                         tmpssh_cas,             /* param2 - ssh cas  */
10946                         tmpxfw,                 /* param3 - ssh x11fwd */
10947                         cx,                     /* enter CONNECT mode */
10948                         sx,                     /* enter SERVER mode */
10949                         zz,                     /* close connection if open */
10950                         0                       /* gui */
10951                         );
10952             if (tmpusrid)
10953                 makestr(&tmpusrid,NULL);
10954             if (ssh_tmpcmd)
10955                 makestr(&ssh_tmpcmd,NULL);
10956         }
10957 #endif /* SSHBUILTIN */
10958 
10959 #ifdef TCPSOCKET
10960         if (mynet == NET_TCPB) {        /* TCP/IP connection */
10961             debug(F110,"setlin service 0",srvbuf,0);
10962             debug(F110,"setlin host s 2",s,0);
10963             if (*s) {			/* If they gave a host name... */
10964                 debug(F110,"setlin host s 1",s,0);
10965 #ifdef NOLISTEN
10966                 if (*s == '*') {
10967                     makestr(&slmsg,"Incoming connections not supported");
10968                     printf(
10969      "?Sorry, incoming connections not supported in this version of Kermit.\n"
10970                            );
10971                     return(-9);
10972                 }
10973 #endif /* NOLISTEN */
10974 #ifdef RLOGCODE
10975                 /* Allow a username if rlogin is requested */
10976                 if (mynet == NET_TCPB &&
10977                     (ttnproto == NP_RLOGIN || ttnproto == NP_K5LOGIN ||
10978                      ttnproto == NP_EK5LOGIN || ttnproto == NP_K4LOGIN ||
10979                      ttnproto == NP_EK4LOGIN
10980                     )) {
10981                     int y;
10982                     uidflag = 0;
10983                     /* Check for "host:service" */
10984                     for ( ; (*s != '\0') && (*s != ':'); s++) ;
10985                     if (*s) {   /* Service, save it */
10986                         *s = NUL;
10987                         ckstrncpy(srvbuf,++s,SRVBUFSIZ);
10988                     } else {            /* No :service, then use default. */
10989 #ifdef VMS
10990                         switch (ttnproto) {
10991                           case NP_RLOGIN:
10992                             ckstrncpy(srvbuf,"513",SRVBUFSIZ); /* "login" */
10993                             break;
10994                           case NP_K4LOGIN:
10995                           case NP_K5LOGIN:
10996                             ckstrncpy(srvbuf,"543",SRVBUFSIZ); /* "klogin" */
10997                             break;
10998                           case NP_EK4LOGIN:
10999                           case NP_EK5LOGIN:
11000                             ckstrncpy(srvbuf,"2105",SRVBUFSIZ); /* "eklogin" */
11001                             break;
11002                         }
11003 #else /* VMS */
11004                         switch (ttnproto) {
11005                           case NP_RLOGIN:
11006                             ckstrncpy(srvbuf,"login",SRVBUFSIZ);
11007                             break;
11008                           case NP_K4LOGIN:
11009                           case NP_K5LOGIN:
11010                             ckstrncpy(srvbuf,"klogin",SRVBUFSIZ);
11011                             break;
11012                           case NP_EK4LOGIN:
11013                           case NP_EK5LOGIN:
11014                             ckstrncpy(srvbuf,"eklogin",SRVBUFSIZ);
11015                             break;
11016                         }
11017 #endif /* VMS */
11018                     }
11019                     if (!confirmed) {
11020                         y = cmfld("Userid on remote system",
11021                                   uidbuf,&s,xxstring);
11022                         if (y < 0 && y != -3)
11023                           return(y);
11024                         if ((int)strlen(s) > 63) {
11025                             makestr(&slmsg,"Internal error");
11026                             printf("Sorry, too long\n");
11027                             return(-9);
11028                         }
11029                         makestr(&tmpusrid,s);
11030                     }
11031                 } else {        /* TELNET or SET HOST */
11032 #endif /* RLOGCODE */
11033                     /* Check for "host:service" */
11034                     for ( ; (*s != '\0') && (*s != ':'); s++) ;
11035                     if (*s) {   /* Service, save it */
11036                         *s = NUL;
11037                         ckstrncpy(srvbuf,++s,SRVBUFSIZ);
11038                     } else if (!confirmed) {
11039                         /* No :service, let them type one. */
11040                         if (*line != '*') { /* Not incoming */
11041                             if (mynet == NET_TCPB && ttnproto == NP_KERMIT) {
11042                                 if ((x = cmfld(
11043                                                "TCP service name or number",
11044                                                "kermit",&s,xxstring)
11045                                      ) < 0 && x != -3)
11046                                   return(x);
11047 #ifdef RLOGCODE
11048                             } else if (mynet == NET_TCPB &&
11049                                        ttnproto == NP_RLOGIN) {
11050                                 if ((x = cmfld(
11051   "TCP service name or number,\n or carriage return for rlogin (513)",
11052                                                "login",&s,xxstring)
11053                                      ) < 0 && x != -3)
11054                                   return(x);
11055 #ifdef CK_AUTHENTICATION
11056 #ifdef CK_KERBEROS
11057                             } else if (mynet == NET_TCPB &&
11058                                        (ttnproto == NP_K4LOGIN ||
11059                                        ttnproto == NP_K5LOGIN)) {
11060                                 if ((x = cmfld(
11061   "TCP service name or number,\n or carriage return for klogin (543)",
11062                                                "klogin",&s,xxstring)
11063                                      ) < 0 && x != -3)
11064                                   return(x);
11065                             } else if (mynet == NET_TCPB &&
11066                                        (ttnproto == NP_EK4LOGIN ||
11067                                         ttnproto == NP_EK5LOGIN)) {
11068                                 if ((x = cmfld(
11069   "TCP service name or number,\n or carriage return for eklogin (2105)",
11070                                                "eklogin",&s,xxstring)
11071                                      ) < 0 && x != -3)
11072                                   return(x);
11073 #endif /* CK_KERBEROS */
11074 #endif /* CK_AUTHENTICATION */
11075 #endif /* RLOGCODE */
11076                             } else {
11077                                 /* Do not set a default value in this call */
11078                                 /* If you do then it will prevent entries  */
11079                                 /* in the network directory from accessing */
11080                                 /* alternate ports.                        */
11081 
11082                                 if ((x = cmfld(
11083                                                "TCP service name or number",
11084                                                "",&s,xxstring)
11085                                      ) < 0 && x != -3)
11086                                   return(x);
11087                             }
11088                         } else { /* Incoming connection */
11089                             if ((x = cmfld("TCP service name or number",
11090                                            "",&s,xxstring)
11091                                  ) < 0 && x != -3)
11092                               return(x);
11093                         }
11094                         if (*s)         /* If they gave a service, */
11095                           ckstrncpy(srvbuf,s,SRVBUFSIZ); /* copy it */
11096                         debug(F110,"setlin service 0.5",srvbuf,0);
11097                     }
11098 #ifdef RLOGCODE
11099                 }
11100 #endif /* RLOGCODE */
11101                 if (!confirmed) {
11102                     char * defproto;
11103                     switch (ttnproto) {
11104                       case NP_RLOGIN:
11105                         defproto = "/rlogin";
11106                         break;
11107                       case NP_K4LOGIN:
11108                         defproto = "/k4login";
11109                         break;
11110                       case NP_K5LOGIN:
11111                         defproto = "/k5login";
11112                         break;
11113                       case NP_EK4LOGIN:
11114                         defproto = "/ek4login";
11115                         break;
11116                       case NP_EK5LOGIN:
11117                         defproto = "/ek5login";
11118                         break;
11119                       case NP_KERMIT:
11120                       case NP_TELNET:
11121                         defproto = "/telnet";
11122                         break;
11123                       default:
11124                         defproto = "/default";
11125                     }
11126                     if ((x = cmkey(tcprawtab,ntcpraw,"Switch",defproto,
11127                                    xxstring)) < 0) {
11128                         if (x != -3)
11129                           return(x);
11130                         else if ((x = cmcfm()) < 0)
11131                           return(x);
11132                     } else {
11133                         rawflg = x;
11134                         if ((x = cmcfm()) < 0)
11135                           return(x);
11136                     }
11137                 }
11138             }
11139             debug(F110,"setlin pre-cx_net line",line,0);
11140             debug(F110,"setlin pre-cx_net srvbuf",srvbuf,0);
11141             x = cx_net( mynet,                  /* nettype */
11142                         rawflg                  /* protocol */,
11143                         line,                   /* host */
11144                         srvbuf,                 /* port */
11145                         tmpusrid,               /* alternate username */
11146                         tmpstring,              /* password */
11147                         NULL,                   /* command to execute */
11148                         a_type,                 /* param1 - telnet authtype */
11149                         e_type,                 /* param2 - telnet enctype  */
11150                         wait,                   /* param3 - telnet wait */
11151                         cx,                     /* enter CONNECT mode */
11152                         sx,                     /* enter SERVER mode */
11153                         zz,                     /* close connection if open */
11154                         0                       /* gui */
11155                         );
11156         }
11157 #endif /* TCPSOCKET */
11158 
11159 #ifdef CK_SECURITY
11160         if (tmpstring)
11161             makestr(&tmpstring,NULL);
11162 #endif /* CK_SECURITY */
11163         if (tmpusrid)
11164             makestr(&tmpusrid,NULL);
11165 	debug(F111,"setlin cx_net",line,x);
11166 	return(x);
11167 #endif /* NETCONN */
11168     }
11169 
11170 /* Serial tty device, possibly modem, connection... */
11171 
11172 #ifdef OS2
11173 /*
11174   User can type:
11175     COM1..COM8 = Regular COM port
11176     1..8       = Synonym for COM1..COM8, is translated to COM1..COM8
11177     _n         = (n is a number) = open file handle
11178     string     = any text string = name of some other kind of device,
11179                  taken literally, as given.
11180 */
11181     s = "Communication device name";
11182 
11183 #ifdef CK_TAPI
11184     if (TAPIAvail)
11185       cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
11186     if (!(tapilinetab && _tapilinetab && ntapiline > 0) &&
11187 	xx == XYTAPI_LIN ) {
11188 	makestr(&slmsg,"TAPI device not configured");
11189 	printf("\nNo TAPI Line Devices are configured for this system\n");
11190 	return(-9);
11191     }
11192     if (xx == XYTAPI_LIN) {		/* Default (first) TAPI line */
11193 	s = "tapi";			/* (whatever it is) */
11194     } else {				/* Query the user */
11195 #endif /* CK_TAPI */
11196 
11197 /* Now parse optional switches and then device name */
11198 
11199 	confirmed = 0;
11200 	cmfdbi(&sw,_CMKEY,"Device name, or switch",
11201 	       "","",npsltab,4,xxstring,psltab,&fl);
11202 	cmfdbi(&fl,_CMFLD,"",dftty,"",0,0,xxstring,NULL,NULL);
11203 	while (1) {
11204 	    x = cmfdb(&sw);
11205 	    debug(F101,"setlin cmfdb","",x);
11206 	    if (x < 0)
11207 	      if (x != -3)
11208 		return(x);
11209 	    if (x == -3) {
11210 		if ((x = cmcfm()) < 0) {
11211 		    return(x);
11212 		} else {
11213 		    confirmed = 1;
11214 		    break;
11215 		}
11216 	    }
11217 	    if (cmresult.fcode == _CMFLD) {
11218 		s = cmresult.sresult;
11219 		break;
11220 	    } else if (cmresult.fcode == _CMKEY) {
11221 		switch (cmresult.nresult) {
11222 		  case SL_CNX:		/* /CONNECT */
11223 		    cx = 1;
11224 		    sx = 0;
11225 		    break;
11226 		  case SL_SRV:		/* /SERVER */
11227 		    cx = 0;
11228 		    sx = 1;
11229 		    break;
11230 		  case SL_SHR:		/* /SHARE */
11231 		    shr = 1;
11232 		    break;
11233 		  case SL_NSH:		/* /NOSHARE */
11234 		    shr = 0;
11235 		    break;
11236 		}
11237 	    }
11238 	}
11239 #ifdef CK_TAPI
11240     }
11241 #endif /* CK_TAPI */
11242 
11243     debug(F110,"OS2 SET PORT s",s,0);
11244     y = lookup(os2devtab,s,nos2dev,&x); /* Look up in keyword table */
11245     debug(F101,"OS2 SET PORT x","",x);
11246     debug(F101,"OS2 SET PORT y","",y);
11247     if ((y > -1) && (x >= 0 && x < 8)) { /* User typed a digit 1..8 */
11248 	s = os2devtab[x+8].kwd;		/* Substitite its real name */
11249 #ifdef NT
11250 	xxtapi = 0;
11251 #else /* NT */
11252 	xxslip = xxppp = 0;
11253 #endif /* NT */
11254 	debug(F110,"OS2 SET PORT subst s",s,"");
11255 #ifndef NT
11256     } else if ((y >-1) && (x >= 16 && x < 24)) { /* SLIP access */
11257 	s = os2devtab[x-8].kwd;		/* Substitite its real name */
11258 	debug(F110,"OS2 SET PORT SLIP subst s",s,"");
11259 	xxslip = 1;
11260 	xxppp  = 0;
11261     } else if ((y >-1) && (x >= 24 && x < 32)) { /* PPP access */
11262 	s = os2devtab[x-16].kwd;	/* Substitite its real name */
11263 	debug(F110,"OS2 SET PORT PPP subst s",s,"");
11264 	xxppp = 1;
11265 	xxslip = 0;
11266 	if ((y = cmkey(os2ppptab,
11267 		       nos2ppp,
11268 		       "PPP driver interface",
11269 		       "ppp0",
11270 		       xxstring)
11271 	     ) < 0)
11272 	  return(y);
11273 	debug(F101,"OS2 SET PORT PPP INTERFACE y","",y);
11274 	xxppp = (y % 10) + 1;
11275 #endif /* NT */
11276     } else if (*s == '_') {		/* User used "_" prefix */
11277 	s++;				/* Remove it */
11278 	/* Rest must be numeric */
11279 	debug(F110,"OS2 SET PORT HANDLE _subst s",s,0);
11280 	if (!rdigits(s)) {
11281 	    makestr(&slmsg,"Invalid file handle");
11282 	    printf("?Invalid format for file handle\n");
11283 	    return(-9);
11284 	}
11285 #ifdef NT
11286 	xxtapi = 0;
11287 #else /* NT */
11288 	xxslip = xxppp = 0;
11289 #endif /* NT */
11290     } else {				/* A normal COMx port or a string */
11291 	s = brstrip(s);			/* Strip braces if any */
11292 #ifdef NT
11293 #ifdef CK_TAPI
11294 	/* Windows TAPI support - Look up in keyword table */
11295 	if (tapilinetab && _tapilinetab && ntapiline > 0) {
11296 	    if (!ckstrcmp(s,"tapi",4,0)) {
11297 
11298 		/* Find out what the lowest numbered TAPI device is */
11299 		/* and use it as the default.                       */
11300 		int j = 9999, k = -1;
11301 		for (i = 0; i < ntapiline; i++) {
11302 		    if (tapilinetab[i].kwval < j) {
11303 			j = tapilinetab[i].kwval;
11304 			k = i;
11305 		    }
11306 		}
11307 		if (k >= 0)
11308 		  s = _tapilinetab[k].kwd;
11309 		else
11310 		  s = "";
11311 
11312 		if ((y = cmkey(_tapilinetab,ntapiline,
11313 			       "TAPI device name",s,xxstring)) < 0)
11314 		  return(y);
11315 
11316 		xxtapi = 1;
11317 
11318 		/* Get the non Underscored string */
11319 		for (i = 0; i < ntapiline; i++ ) {
11320 		    if (tapilinetab[i].kwval == y) {
11321 			s = tapilinetab[i].kwd;
11322 			break;
11323 		    }
11324 		}
11325 	    } else
11326 	      xxtapi = 0;
11327 	}
11328 #endif /* CK_TAPI */
11329 #else /* NT */
11330 	/* not OS/2 SLIP or PPP */
11331 	xxslip = xxppp = 0;
11332 #endif /* NT */
11333     }
11334     ckstrncpy(tmpbuf,s,TMPBUFSIZ);	/* Copy to a safe place */
11335     s = tmpbuf;
11336     if ((x = cmcfm()) < 0)
11337       return(x);
11338 
11339 #else /* !OS2 */
11340 
11341     cmfdbi(&sw,_CMKEY,"Device name, or switch",
11342 	   "","",npsltab,4,xxstring,psltab,&tx);
11343     cmfdbi(&tx,_CMTXT,"",dftty,"",0,0,xxstring,NULL,NULL);
11344     while (!confirmed) {
11345 	x = cmfdb(&sw);
11346 	debug(F101,"setlin cmfdb","",x);
11347 	if (x < 0)
11348 	  if (x != -3)
11349 	    return(x);
11350 	if (x == -3) {
11351 	    if ((x = cmcfm()) < 0) {
11352 		return(x);
11353 	    } else {
11354 		confirmed = 1;
11355 		break;
11356 	    }
11357 	}
11358 	switch (cmresult.fcode) {
11359 	  case _CMTXT:
11360 	    ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
11361 	    s = tmpbuf;
11362 	    debug(F110,"setlin CMTXT",tmpbuf,0);
11363 	    confirmed = 1;
11364 	    break;
11365 	  case _CMKEY:			/* Switch */
11366 	    debug(F101,"setlin CMKEY",tmpbuf,cmresult.nresult);
11367 	    switch (cmresult.nresult) {
11368 	      case SL_CNX:		/* /CONNECT */
11369 		cx = 1;
11370 		sx = 0;
11371 		break;
11372 	      case SL_SRV:		/* /SERVER */
11373 		cx = 0;
11374 		sx = 1;
11375 		break;
11376 #ifdef VMS
11377 	      case SL_SHR:		/* /SHARE */
11378 		shr = 1;
11379 		break;
11380 	      case SL_NSH:		/* /NOSHARE */
11381 		shr = 0;
11382 		break;
11383 #endif /* VMS */
11384 	    }
11385 	    continue;
11386 	  default:
11387 	    debug(F101,"setlin bad cmfdb result","",cmresult.fcode);
11388 	    makestr(&slmsg,"Internal error");
11389 	    printf("?Internal parsing error\n");
11390 	    return(-9);
11391 	}
11392     }
11393 #endif /* OS2 */
11394     if (!confirmed)
11395       if ((x = cmcfm()) < 0)
11396 	return(x);
11397 
11398     debug(F110,"setlin pre-cx_serial s",s,0);
11399     debug(F110,"setlin pre-cx_serial line",line,0);
11400     x = cx_serial(s,cx,sx,shr,zz,0,
11401 #ifdef OS2
11402 #ifdef NT
11403                    (xxtapi ? CX_TAPI : 0)
11404 #else
11405                    (xxslip ? CX_SLIP : 0) | (xxppp ? CX_PPP : 0)
11406 #endif /* NT */
11407 #else /* OS2 */
11408                    0
11409 #endif /* OS2 */
11410                    );
11411     debug(F111,"setlin cx_serial",line,x);
11412     return(x);
11413 }
11414 #endif /* NOLOCAL */
11415 
11416 #ifdef CKCHANNELIO
11417 /*
11418   C-Library based file-i/o package for scripts.  This should be portable to
11419   all C-Kermit versions since it uses the same APIs we have always used for
11420   processing command files.  The entire channel i/o package is contained
11421   herein, apart from some keyword table entries in the main keyword table
11422   and the help text in the HELP command module.
11423 
11424   On platforms like VMS and VOS, this package handles only UNIX-style
11425   stream files.  If desired, it can be replaced for those platforms by
11426   <#>ifdef'ing out this code and adding the equivalent replacement routines
11427   to the ck?fio.c module, e.g. for RMS-based file i/o in ckvfio.c.
11428 */
11429 #ifndef NOSTAT
11430 #ifdef VMS
11431 /* 2010-03-09 SMS.  VAX C needs help to find "sys".  It's easier not to try. */
11432 #include <stat.h>
11433 #else /* def VMS */
11434 #include <sys/stat.h>
11435 #endif /* def VMS [else] */
11436 #endif /* NOSTAT */
11437 
11438 #ifdef NLCHAR
11439 static int z_lt = 1;                    /* Length of line terminator */
11440 #else
11441 static int z_lt = 2;
11442 #endif /* NLCHAR */
11443 
11444 struct ckz_file {                       /* C-Kermit file struct */
11445     FILE * z_fp;                        /* Includes the C-Lib file struct */
11446     unsigned int z_flags;               /* Plus C-Kermit mode flags, */
11447     CK_OFF_T z_nline;			/* current line number if known, */
11448     char z_name[CKMAXPATH+2];           /* and the file's name. */
11449 };
11450 static struct ckz_file ** z_file = NULL; /* Array of C-Kermit file structs */
11451 static int z_inited = 0;                /* Flag for array initialized */
11452 int z_maxchan = Z_MAXCHAN;              /* Max number of C-Kermit channels */
11453 int z_openmax = CKMAXOPEN;              /* Max number of open files overall */
11454 int z_nopen = 0;                        /* How many channels presently open */
11455 int z_error = 0;                        /* Most recent error */
11456 int z_filcount = -1;                    /* Most recent FILE COUNT result */
11457 
11458 #define RD_LINE 0                       /* FILE READ options */
11459 #define RD_CHAR 1
11460 #define RD_SIZE 2
11461 #define RD_TRIM 8			/* Like Snobol &TRIM = 1 */
11462 #define RD_UNTA 9			/* Untabify */
11463 
11464 #define WR_LINE RD_LINE                 /* FILE WRITE options */
11465 #define WR_CHAR RD_CHAR
11466 #define WR_SIZE RD_SIZE
11467 #define WR_STRI 3
11468 #define WR_LPAD 4
11469 #define WR_RPAD 5
11470 
11471 #ifdef UNIX
11472 extern int ckmaxfiles;                  /* Filled in by sysinit(). */
11473 #endif /* UNIX */
11474 
11475 /* See ckcker.h for error numbers */
11476 /* See ckcdeb.h for Z_MAXCHAN and CKMAXOPEN definitions */
11477 /* NOTE: For VMS we might be able to fill in ckmaxfiles */
11478 /* from FILLM and CHANNELCNT -- find out about these... */
11479 
11480 static char * fopnargs[] = {            /* Mode combinations for fopen() */
11481 #ifdef COMMENT
11482     /* All combinations of rwa */
11483     "",  "r",  "w",  "rw",  "a",  "ra",  "wa",  "rwa", /* Text mode */
11484     "b", "rb", "wb", "rwb", "ab", "rab", "wab", "rwab" /* Binary mode */
11485 #else
11486     /* Combinations and syntax permitted by C libraries... */
11487     "",  "r",  "w",  "r+",  "a",  "",   "a",  "", /* Text mode */
11488 #ifdef OS2
11489     "",  "rb", "wb", "r+b", "ab", "",   "ab", "" /* Binary modes for K95 */
11490 #else
11491 #ifdef VMS
11492     "",  "rb", "wb", "r+b", "ab", "",   "ab", "" /* Binary modes for VMS */
11493 #else
11494     "",  "r",   "w", "r+",  "a",  "",   "a",  "" /* Binary modes for UNIX */
11495 #endif /* VMS */
11496 #endif /* OS2 */
11497 #endif /* COMMENT */
11498 };
11499 static int nfopnargs = sizeof(fopnargs) / sizeof(char *);
11500 
11501 char *                                  /* Error messages */
ckferror(n)11502 ckferror(n) int n; {
11503     switch (n) {
11504       case FX_NER: return("No error");
11505       case FX_SYS: return(ck_errstr());
11506       case FX_EOF: return("End of file");
11507       case FX_NOP: return("File not open");
11508       case FX_CHN: return("Channel out of range");
11509       case FX_RNG: return("Parameter out of range");
11510       case FX_NMF: return("Too many files open");
11511       case FX_FOP: return("Operation conflicts with OPEN mode");
11512       case FX_NYI: return("OPEN mode not supported");
11513       case FX_BOM: return("Illegal combination of OPEN modes");
11514       case FX_ACC: return("Access denied");
11515       case FX_FNF: return("File not found");
11516       case FX_OFL: return("Buffer overflow");
11517       case FX_LNU: return("Current line number unknown");
11518       case FX_ROO: return("Off limits");
11519       case FX_UNK: return("Operation fails - reason unknown");
11520       default: return("Error number out of range");
11521     }
11522 }
11523 
11524 /*
11525   Z _ O P E N --  Open a file for the requested type of access.
11526 
11527   Call with:
11528     name:  Name of file to be opened.
11529     flags: Any combination of FM_xxx values except FM_EOF (ckcker.h).
11530   Returns:
11531     >= 0 on success: The assigned channel number
11532     <  0 on failure: A negative FX_xxx error code (ckcker.h).
11533 */
11534 int
z_open(name,flags)11535 z_open(name, flags) char * name; int flags; {
11536     int i, n;
11537     FILE * t;
11538     char * mode;
11539     debug(F111,"z_open",name,flags);
11540     if (!name) name = "";               /* Check name argument */
11541     if (!name[0])
11542       return(z_error = FX_BFN);
11543     if (flags & FM_CMD)                 /* Opening pipes not implemented yet */
11544       return(z_error = FX_NYI);         /* (and not portable either) */
11545     debug(F101,"z_open nfopnargs","",nfopnargs);
11546 
11547     if (flags & FM_STDIN) {             /* Read from standard input */
11548         mode = "r";
11549     } else if (flags & (FM_STDOUT|FM_STDERR)) {
11550         mode = "w";
11551     } else {                            /* If regular file, not stdin.. */
11552         if (flags < 0 || flags >= nfopnargs) /* Range check flags */
11553           return(z_error = FX_RNG);
11554         mode = fopnargs[flags];         /* Get fopen() arg */
11555         debug(F111,"z_open fopen args",mode,flags);
11556         if (!mode[0])                   /* Check for illegal combinations */
11557           return(z_error = FX_BOM);
11558     }
11559     if (!z_inited) {                /* If file structs not inited */
11560         debug(F101,"z_open z_maxchan 1","",z_maxchan);
11561 #ifdef UNIX
11562         debug(F101,"z_open ckmaxfiles","",ckmaxfiles);
11563         if (ckmaxfiles > 0) {           /* Set in ck?tio.c: sysinit() */
11564             int x;
11565             x = ckmaxfiles - ZNFILS - 5;
11566             if (x > z_maxchan)          /* sysconf() value greater than */
11567               z_maxchan = x;            /* value from header files. */
11568             debug(F101,"z_open z_maxchan 2","",z_maxchan);
11569         }
11570 #endif /* UNIX */
11571         if (z_maxchan < Z_MINCHAN)      /* Allocate at least this many. */
11572           z_maxchan = Z_MINCHAN;
11573         debug(F101,"z_open z_maxchan 3","",z_maxchan);
11574         /* Note: This could be a pretty big chunk of memory */
11575         /* if z_maxchan is a big number.  If this becomes a problem */
11576         /* we'll need to malloc and free each element at open/close time */
11577 #ifdef COMMENT
11578 	/* May 2006 - it's time - in current Linux this about 3MB */
11579         if (!(z_file = (struct ckz_file *)
11580               malloc(sizeof(struct ckz_file) * (z_maxchan + 1))))
11581           return(z_error = FX_NMF);
11582         for (i = 0; i < z_maxchan; i++) {
11583             z_file[i].z_fp = NULL;
11584             z_file[i].z_flags = 0;
11585             z_file[i].z_nline = 0;
11586             *(z_file[i].z_name) = '\0';
11587         }
11588 #else
11589 	/* New economical way, allocate storage for each channel as needed */
11590 	if (!z_file) {
11591             debug(F100,"z_file[] is NULL","",0);
11592             debug(F101,"sizeof(struct ckz_file *)","",
11593                   sizeof(struct ckz_file *));
11594 	    z_file = (struct ckz_file **)malloc((z_maxchan + 1) *
11595 						sizeof(struct ckz_file *));
11596             debug(F101,"z_open z_maxchan 4","",z_maxchan);
11597 	    if (!z_file)
11598 	      return(z_error = FX_NMF);
11599 	    for (i = 0; i < z_maxchan; i++)
11600 	      z_file[i] = NULL;
11601             debug(F101,"z_open z_maxchan 5","",z_maxchan);
11602 	}
11603 #endif	/* COMMENT */
11604         debug(F101,"z_open z_maxchan 6","",z_maxchan);
11605         z_inited = 1;                   /* Remember we initialized */
11606     }
11607     for (n = -1, i = 0; i < z_maxchan; i++) { /* Find a free channel */
11608 #ifdef COMMENT
11609         if (!z_file[i].z_fp) {
11610             n = i;
11611             break;
11612         }
11613 #else
11614         debug(F101,"z_open find-free-channel loop","",i);
11615         if (!z_file[i]) {
11616 	    z_file[i] = (struct ckz_file *) malloc(sizeof(struct ckz_file));
11617 	    if (!z_file[i])
11618 	      return(z_error = FX_NMF);
11619             n = i;
11620             break;
11621         }
11622 #endif	/* COMMENT */
11623 
11624     }
11625     debug(F101,"z_open found free channel","",n);
11626     if (n < 0 || n >= z_maxchan)        /* Any free channels? */
11627       return(z_error = FX_NMF);         /* No, fail. */
11628     debug(F100,"z_open check n ok","",0);
11629     errno = 0;
11630     debug(F100,"z_open errno ok","",0);
11631     z_file[n]->z_flags = 0;		/* In case of failure... */
11632     debug(F100,"z_open z_file[n] flags ok","",0);
11633     z_file[n]->z_fp = NULL;		/* Set file pointer to NULL */
11634     debug(F100,"z_open z_file[n] fps ok","",0);
11635 
11636 #ifdef UNIX
11637     if (flags & FM_STDIN) {             /* Standard input */
11638         t = (FILE *)stdin;              /* We just use the ready-made stream */
11639         z_nopen++;                      /* Count it. */
11640         z_file[n]->z_fp = t;		/* Stash the file pointer */
11641         z_file[n]->z_flags = flags;     /* and the flags */
11642         z_file[n]->z_nline = 0;		/* Current line number is 0 */
11643         ckstrncpy(z_file[n]->z_name,name,CKMAXPATH); /* "filename" */
11644         z_error = 0;                    /* No error so far */
11645         return(n);                      /* Return the channel number */
11646     }
11647     if (flags & FM_STDOUT) {            /* Standard output */
11648         t = (FILE *)stdout;             /* Same deal */
11649         z_nopen++;
11650         z_file[n]->z_fp = t;
11651         z_file[n]->z_flags = flags;
11652         z_file[n]->z_nline = 0;
11653         ckstrncpy(z_file[n]->z_name,name,CKMAXPATH);
11654         z_error = 0;
11655         return(n);
11656     }
11657     if (flags & FM_STDERR) {            /* Standard error */
11658         t = (FILE *)stderr;
11659         z_nopen++;
11660         z_file[n]->z_fp = t;
11661         z_file[n]->z_flags = flags;
11662         z_file[n]->z_nline = 0;
11663         ckstrncpy(z_file[n]->z_name,name,CKMAXPATH);
11664         z_error = 0;
11665         return(n);
11666     }
11667 #endif /* UNIX */
11668     t = fopen(name, mode);              /* Try to open the file. */
11669     if (!t) {                           /* Failed... */
11670         debug(F111,"z_open error",name,errno);
11671 #ifdef EMFILE
11672         if (errno == EMFILE)
11673           return(z_error = FX_NMF);
11674 #endif /* EMFILE */
11675 	free(z_file[n]);
11676 	z_file[n] = NULL;
11677         return(z_error = (errno ?  FX_SYS : FX_UNK)); /* Return error code */
11678     }
11679 #ifdef NT
11680 #ifdef O_SEQUENTIAL
11681     if (t)                              /* Caching hint for NT */
11682       _setmode(_fileno(t),O_SEQUENTIAL);
11683 #endif /* O_SEQUENTIAL */
11684 #endif /* NT */
11685 
11686     z_nopen++;                          /* Open, count it. */
11687     z_file[n]->z_fp = t;		/* Stash the file pointer */
11688     z_file[n]->z_flags = flags;		/* and the flags */
11689     z_file[n]->z_nline = 0;		/* Current line number is 0 */
11690     z_error = 0;
11691     zfnqfp(name,CKMAXPATH,z_file[n]->z_name); /* and the file's full name */
11692     return(n);                          /* Return the channel number */
11693 }
11694 
11695 int
z_close(channel)11696 z_close(channel) int channel; {         /* Close file on given channel */
11697     int x;
11698     FILE * t;
11699     if (!z_inited)                      /* Called before any files are open? */
11700       return(z_error = FX_NOP);
11701     if (channel >= z_maxchan)           /* Channel out of range? */
11702       return(z_error = FX_CHN);
11703     if (!z_file[channel])
11704       return(z_error = FX_NOP);
11705     if (!(t = z_file[channel]->z_fp))    /* Channel wasn't open? */
11706       return(z_error = FX_NOP);
11707     errno = 0;                          /* Set errno 0 to get a good reading */
11708     if (!(z_file[channel]->z_flags & FM_STDM)) /* If not stdin/out/err... */
11709       x = fclose(t);                    /* Try to close */
11710     if (x == EOF)                       /* On failure */
11711       return(z_error = FX_SYS);         /* indicate system error. */
11712     z_nopen--;                          /* Closed OK, decrement open count */
11713     z_file[channel]->z_fp = NULL;	/* Set file pointer to NULL */
11714     z_file[channel]->z_nline = 0;	/* Current line number is 0 */
11715     z_file[channel]->z_flags = 0;	/* Set flags to 0 */
11716     *(z_file[channel]->z_name) = '\0';	/* Clear name */
11717     free(z_file[channel]);
11718     z_file[channel] = NULL;
11719     return(z_error = 0);
11720 }
11721 
11722 /*
11723   Z _ O U T  --  Output string to channel.
11724 
11725   Call with:
11726     channel:     Channel number to write to.
11727     s:           String to write.
11728     length > -1: How many characters of s to write.
11729     length < 0:  Write entire NUL-terminated string.
11730     flags == 0:  Supply line termination.
11731     flags >  0:  Don't supply line termination.
11732     flags <  0:  Write 'length' NUL characters.
11733   Special case:
11734     If flags > -1 and s is empty or NULL and length == 1, write 1 NUL.
11735   Returns:
11736     Number of characters written to channel on success, or
11737     negative FX_xxx error code on failure.
11738 */
11739 int
z_out(channel,s,length,flags)11740 z_out(channel,s,length,flags) int channel, flags, length; char * s; {
11741     FILE * t;
11742     int x, n;
11743     char c = '\0';
11744 
11745     if (!s) s = "";                     /* Guard against null pointer */
11746 #ifdef DEBUG
11747     if (deblog) {
11748         debug(F111,"z_out",s,channel);
11749         debug(F101,"z_out length","",length);
11750         debug(F101,"z_out flags","",flags);
11751     }
11752 #endif /* DEBUG */
11753     if (!z_inited)                      /* File i/o inited? */
11754       return(z_error = FX_NOP);
11755     if (channel >= z_maxchan)           /* Channel in range? */
11756       return(z_error = FX_CHN);
11757     if (!z_file[channel])
11758       return(z_error = FX_NOP);
11759     if (!(t = z_file[channel]->z_fp))    /* File open? */
11760       return(z_error = FX_NOP);
11761     if (!((z_file[channel]->z_flags) & (FM_WRI|FM_APP))) /* In write mode? */
11762       return(z_error = FX_FOP);
11763     n = length;                         /* Length of string to write */
11764     if (n < 0) {                        /* Negative means get it ourselves */
11765         if (flags < 0)                  /* Except when told to write NULs in */
11766           return(z_error = FX_RNG);     /* which case args are inconsistent */
11767         n = strlen(s);                  /* Get length of string arg */
11768     }
11769     errno = 0;                          /* Reset errno */
11770     debug(F101,"z_out n","",n);
11771     if (flags < 0) {                    /* Writing NULs... */
11772         int i;
11773         for (i = 0; i < n; i++) {
11774             x = fwrite(&c,1,1,t);
11775             if (x < 1)
11776               return(z_error = (errno ? FX_SYS : FX_UNK));
11777         }
11778         z_file[channel]->z_nline = -1;   /* Current line no longer known */
11779         z_error = 0;
11780         return(i);
11781     } else {                            /* Writing string arg */
11782         if (n == 1 && !s[0])            /* Writing one char but it's NUL */
11783           x = fwrite(&c,1,1,t);
11784         else                            /* Writing non-NUL char or string */
11785           x = fwrite(s,1,n,t);
11786         debug(F101,"z_out fwrite",ckitoa(x),errno);
11787         if (x < n)                      /* Failure to write requested amount */
11788           return(z_error = (errno ? FX_SYS : FX_UNK)); /* Return error */
11789         if (flags == 0) {               /* If supplying line termination */
11790             if (fwrite("\n",1,1,t))     /* do that  */
11791               x += z_lt;                /* count the terminator */
11792             if (z_file[channel]->z_nline > -1) /* count this line */
11793               z_file[channel]->z_nline++;
11794         } else {
11795             z_file[channel]->z_nline = -1; /* Current line no longer known */
11796         }
11797     }
11798     z_error = 0;
11799     return(x);
11800 }
11801 
11802 #define Z_INBUFLEN 64
11803 
11804 /*
11805   Z _ I N  --  Multichannel i/o file input function.
11806 
11807   Call with:
11808     channel number to read from.
11809     s = address of destination buffer.
11810     buflen = destination buffer length.
11811     length = Number of bytes to read, must be < buflen.
11812     flags: 0 = read a line; nonzero = read the given number of bytes.
11813   Returns:
11814     Number of bytes read into buffer or a negative error code.
11815     A terminating NUL is deposited after the last byte that was read.
11816 */
11817 int
z_in(channel,s,buflen,length,flags)11818 z_in(channel,s,buflen,length,flags)
11819  int channel, buflen, length, flags; char * s;
11820 /* z_in */ {
11821     int i, j, x;
11822     FILE * t;
11823     char * p;
11824 
11825     if (!z_inited)                      /* Check everything... */
11826       return(z_error = FX_NOP);
11827     if (channel >= z_maxchan)
11828       return(z_error = FX_CHN);
11829     if (!z_file[channel])
11830       return(z_error = FX_NOP);
11831     if (!(t = z_file[channel]->z_fp))
11832       return(z_error = FX_NOP);
11833     if (!((z_file[channel]->z_flags) & FM_REA))
11834       return(z_error = FX_FOP);
11835     if (!s)                             /* Check destination */
11836      return(z_error = FX_RNG);
11837     s[0] = NUL;
11838     if (length == 0)                    /* Read 0 bytes - easy. */
11839       return(z_error = 0);
11840     debug(F101,"z_in channel","",channel);
11841     debug(F101,"z_in buflen","",buflen);
11842     debug(F101,"z_in length","",length);
11843     debug(F101,"z_in flags","",flags);
11844     if (length < 0 || buflen < 0)       /* Check length args */
11845       return(z_error = FX_RNG);
11846     if (buflen <= length)
11847       return(z_error = FX_RNG);
11848     errno = 0;                          /* Reset errno */
11849     if (flags) {                        /* Read block or byte */
11850 	int n;				/* 20050912 */
11851 	n = length;			/* 20050912 */
11852 	i = 0;				/* 20050912 */
11853 	while (n > 0) {			/* 20050912 */
11854 	    i = fread(s,1,n,t);		/* 20050912 */
11855 #ifdef DEBUG
11856 	    if (deblog) {
11857 		debug(F111,"z_in block",s,i);
11858 		debug(F101,"z_in block errno","",errno);
11859 		debug(F101,"z_in block ferror","",ferror(t));
11860 		debug(F101,"z_in block feof","",feof(t));
11861 	    }
11862 #endif /* DEBUG */
11863 	    if (i == 0) break;		/* 20050912 */
11864 	    s += i;			/* 20050912 */
11865 	    n -= i;			/* 20050912 */
11866 	}
11867 	/* Current line no longer known */
11868         z_file[channel]->z_nline = (CK_OFF_T)-1;
11869     } else {                            /* Read line */
11870 #ifndef COMMENT
11871         /* This method is used because it's simpler than the others */
11872         /* and also marginally faster. */
11873         debug(F101,"z_in getc loop","",CKFTELL(t));
11874         for (i = 0; i < length; i++) {
11875             if ((x = getc(t)) == EOF) {
11876                 debug(F101,"z_in getc error","",CKFTELL(t));
11877                 s[i] = '\0';
11878                 break;
11879             }
11880             s[i] = x;
11881             if (s[i] == '\n') {
11882                 s[i] = '\0';
11883                 break;
11884             }
11885         }
11886         debug(F111,"z_in line byte loop",ckitoa(errno),i);
11887         debug(F111,"z_in line got",s,z_file[channel]->z_nline);
11888         if (z_file[channel]->z_nline > -1)
11889           z_file[channel]->z_nline++;
11890 #else
11891 #ifdef COMMENT2
11892         /* Straightforward but strlen() slows it down. */
11893         s[0] = '\0';
11894         i = 0;
11895         if (fgets(s,length,t)) {
11896             i = strlen(s);
11897             if (i > 0 && s[i-1] == '\n') i--;
11898         }
11899         debug(F111,"z_in line fgets",ckitoa(errno),i);
11900         if (z_file[channel]->z_nline > -1)
11901           z_file[channel]->z_nline++;
11902 #else
11903         /* This is a do-it-yourself fgets() with its own readahead and */
11904         /* putback.  It's a bit faster than real fgets() but not enough */
11905         /* to justify the added complexity or the risk of the ftell() and */
11906         /* fseek() calls failing. */
11907         int k, flag = 0;
11908         CK_OFF_T pos;
11909         for (i = 0; !flag && i <= (length - Z_INBUFLEN); i += Z_INBUFLEN) {
11910             k = ((length - i) < Z_INBUFLEN) ? length - i : Z_INBUFLEN;
11911             if ((x = fread(s+i,1,k,t)) < 1)
11912               break;
11913             s[i+x] = '\0';
11914             for (j = 0; j < x; j++) {
11915                 if (s[i+j] == '\n') {
11916                     s[i+j] = '\0';
11917                     flag ++;
11918                     pos = CKFTELL(t);
11919                     if (pos > -1) {
11920                         pos -= (x - j - 1);
11921                         x = CKFSEEK(t, pos, 0);
11922                         i += j;
11923                         break;
11924                     } else
11925                       return(z_error = FX_SYS);
11926                 }
11927             }
11928         }
11929         if (z_file[channel]->z_nline > -1)
11930           z_file[channel]->z_nline++;
11931         debug(F111,"z_in line chunk loop",ckitoa(errno),i);
11932 #endif /* COMMENT2 */
11933 #endif /* COMMENT */
11934     }
11935     debug(F111,"z_in i",ckitoa(errno),i);
11936     if (i < 0) i = 0;                   /* NUL-terminate result */
11937     s[i] = '\0';
11938     if (i > 0) {
11939         z_error = 0;
11940         return(i);
11941     }
11942     if (i == 0 && feof(t))              /* EOF on reading? */
11943       return(z_error = FX_EOF);         /* Return EOF code */
11944     return(errno ? (z_error = -1) : i); /* Return length or system error */
11945 }
11946 
11947 int
z_flush(channel)11948 z_flush(channel) int channel; {         /* Flush output channel */
11949     FILE * t;
11950     int x;
11951     if (!z_inited)                      /* Regular checks */
11952       return(z_error = FX_NOP);
11953     if (channel >= z_maxchan)
11954       return(z_error = FX_CHN);
11955     if (!z_file[channel])
11956       return(z_error = FX_NOP);
11957     if (!(t = z_file[channel]->z_fp))
11958       return(z_error = FX_NOP);
11959     if (!((z_file[channel]->z_flags) & (FM_WRI|FM_APP))) /* Write access? */
11960       return(z_error = FX_FOP);
11961     errno = 0;                          /* Reset errno */
11962     x = fflush(t);                      /* Try to flush */
11963     return(x ? (z_error = FX_SYS) : 0); /* Return system error or 0 if OK */
11964 }
11965 
11966 int
11967 #ifdef CK_ANSIC
z_seek(int channel,CK_OFF_T pos)11968 z_seek(int channel, CK_OFF_T pos)	/* Move file pointer to byte */
11969 #else
11970 z_seek(channel,pos) int channel; CK_OFF_T pos; /* (seek to given position) */
11971 #endif /* CK_ANSIC */
11972 {
11973     int i, x = 0, rc;
11974     FILE * t;
11975     if (!z_inited)                      /* Check... */
11976       return(z_error = FX_NOP);
11977     if (channel >= z_maxchan)
11978       return(z_error = FX_CHN);
11979     if (!z_file[channel])
11980       return(z_error = FX_NOP);
11981     if (!(t = z_file[channel]->z_fp))
11982       return(z_error = FX_NOP);
11983     if (pos < 0L) {
11984         x = 2;
11985         pos = (pos == -2) ? -1L : 0L;
11986     }
11987     errno = 0;
11988     rc = CKFSEEK(t,pos,x);		/* Try to seek */
11989     debug(F111,"z_seek",ckitoa(errno),rc);
11990     if (rc < 0)                         /* OK? */
11991       return(z_error = FX_SYS); /* No. */
11992     z_file[channel]->z_nline = ((pos || x) ? -1 : 0);
11993     return(z_error = 0);
11994 }
11995 
11996 int
11997 #ifdef CK_ANSIC
z_line(int channel,CK_OFF_T pos)11998 z_line(int channel, CK_OFF_T pos)           /* Move file pointer to line */
11999 #else
12000 z_line(channel,pos) int channel; CK_OFF_T pos; /* (seek to given position) */
12001 #endif /* CK_ANSIC */
12002 {
12003     int i, len, x = 0;
12004     CK_OFF_T current = (CK_OFF_T)0, prev = (CK_OFF_T)-1, old = (CK_OFF_T)-1;
12005     FILE * t;
12006     char tmpbuf[256];
12007     if (!z_inited)                      /* Check... */
12008       return(z_error = FX_NOP);
12009     if (channel >= z_maxchan)
12010       return(z_error = FX_CHN);
12011     if (!z_file[channel])
12012       return(z_error = FX_NOP);
12013     if (!(t = z_file[channel]->z_fp))
12014       return(z_error = FX_NOP);
12015     debug(F101,"z_line pos","",pos);
12016     if (pos < 0L) {                     /* EOF wanted */
12017         CK_OFF_T n;
12018         n = z_file[channel]->z_nline;
12019         debug(F101,"z_line n","",n);
12020         if (n < 0 || pos < 0) {
12021             rewind(t);
12022             n = 0;
12023         }
12024         while (1) {                     /* This could take a while... */
12025             if ((x = getc(t)) == EOF)
12026               break;
12027             if (x == '\n') {
12028                 n++;
12029                 if (pos == -2) {
12030                     old = prev;
12031                     prev = CKFTELL(t);
12032                 }
12033             }
12034         }
12035         debug(F101,"z_line old","",old);
12036         debug(F101,"z_line prev","",prev);
12037         if (pos == -2) {
12038             if ((x = z_seek(channel,old)) < 0)
12039               return(z_error = x);
12040             else
12041               n--;
12042         }
12043         z_file[channel]->z_nline = n;
12044         return(z_error = 0);
12045     }
12046     if (pos == 0L) {                    /* Rewind wanted */
12047         z_file[channel]->z_nline = 0L;
12048         rewind(t);
12049         debug(F100,"z_line rewind","",0);
12050         return(0L);
12051     }
12052     tmpbuf[255] = NUL;                  /* Make sure buf is NUL terminated */
12053     current = z_file[channel]->z_nline;  /* Current line */
12054     /*
12055       If necessary the following could be optimized, e.g. for positioning
12056       to a previous line in a large file without starting over.
12057     */
12058     if (current < 0 || pos < current) { /* Not known or behind us... */
12059         debug(F101,"z_line rewinding","",pos);
12060         if ((x = z_seek(channel, 0L)) < 0) /* Rewind */
12061           return(z_error = x);
12062         if (pos == 0)                   /* If 0th line wanted we're done */
12063           return(z_error = 0);
12064         current = 0;
12065     }
12066     while (current < pos) {             /* Search for specified line */
12067         if (fgets(tmpbuf,255,t)) {
12068             len = strlen(tmpbuf);
12069             if (len > 0 && tmpbuf[len-1] == '\n') {
12070                 current++;
12071                 debug(F111,"z_line read",ckitoa(len),current);
12072             } else if (len == 0) {
12073                 return(z_error = FX_UNK);
12074             }
12075         } else {
12076             z_file[channel]->z_nline = -1L;
12077             debug(F101,"z_line premature EOF","",current);
12078             return(z_error = FX_EOF);
12079         }
12080     }
12081     z_file[channel]->z_nline = current;
12082     debug(F101,"z_line result","",current);
12083     z_error = 0;
12084     return(current);
12085 }
12086 
12087 char *
z_getname(channel)12088 z_getname(channel) int channel; {       /* Return name of file on channel */
12089     FILE * t;
12090     if (!z_inited) {
12091         z_error = FX_NOP;
12092         return(NULL);
12093     }
12094     if (channel >= z_maxchan) {
12095         z_error = FX_CHN;
12096         return(NULL);
12097     }
12098     if (!z_file[channel]) {
12099         z_error = FX_NOP;
12100         return(NULL);
12101     }
12102     if (!(t = z_file[channel]->z_fp)) {
12103         z_error = FX_NOP;
12104         return(NULL);
12105     }
12106     return((char *)(z_file[channel]->z_name));
12107 }
12108 
12109 int
z_getmode(channel)12110 z_getmode(channel) int channel; {       /* Return OPEN modes of channel */
12111     FILE * t;                           /* 0 if file not open */
12112 #ifndef NOSTAT
12113 #ifdef NT
12114     struct _stat statbuf;
12115 #else /* NT */
12116     struct stat statbuf;
12117 #endif /* NT */
12118 #endif /* NOSTAT */
12119     int x;
12120     if (!z_inited)
12121       return(0);
12122     if (channel >= z_maxchan)
12123       return(z_error = FX_CHN);
12124     if (!z_file[channel])
12125       return(0);
12126     if (!(t = z_file[channel]->z_fp))
12127       return(0);
12128     x = z_file[channel]->z_flags;
12129     if (feof(t)) {                      /* This might not work for */
12130         x |= FM_EOF;                    /* output files */
12131 #ifndef NOSTAT
12132     /* But this does if we can use it. */
12133     } else if (stat(z_file[channel]->z_name,&statbuf) > -1) {
12134         if (CKFTELL(t) == statbuf.st_size)
12135           x |= FM_EOF;
12136 #endif /* NOSTAT */
12137     }
12138     return(x);
12139 }
12140 
12141 CK_OFF_T
z_getpos(channel)12142 z_getpos(channel) int channel; {        /* Get file pointer position */
12143     FILE * t;                           /* on this channel */
12144     CK_OFF_T x;
12145     if (!z_inited)
12146       return(z_error = FX_NOP);
12147     if (channel >= z_maxchan)
12148       return(z_error = FX_CHN);
12149     if (!z_file[channel])
12150       return(z_error = FX_NOP);
12151     if (!(t = z_file[channel]->z_fp))
12152       return(z_error = FX_NOP);
12153     x = CKFTELL(t);
12154     return((x < 0L) ? (z_error = FX_SYS) : x);
12155 }
12156 
12157 CK_OFF_T
z_getline(channel)12158 z_getline(channel) int channel; {       /* Get current line number */
12159     FILE * t;                           /* in file on this channel */
12160     CK_OFF_T rc;
12161     if (!z_inited)
12162       return(z_error = FX_NOP);
12163     if (channel >= z_maxchan)
12164       return(z_error = FX_CHN);
12165     if (!z_file[channel])
12166       return(z_error = FX_NOP);
12167     if (!(t = z_file[channel]->z_fp))
12168       return(z_error = FX_NOP);
12169     debug(F101,"z_getline","",z_file[channel]->z_nline);
12170     rc = z_file[channel]->z_nline;
12171     return((rc < 0) ? (z_error = FX_LNU) : rc);
12172 }
12173 
12174 int
z_getfnum(channel)12175 z_getfnum(channel) int channel; {       /* Get file number / handle */
12176     FILE * t;                           /* for file on this channel */
12177     if (!z_inited)
12178       return(z_error = FX_NOP);
12179     if (channel >= z_maxchan)
12180       return(z_error = FX_CHN);
12181     if (!z_file[channel])
12182       return(z_error = FX_NOP);
12183     if (!(t = z_file[channel]->z_fp))
12184       return(z_error = FX_NOP);
12185     z_error = 0;
12186     return(fileno(t));
12187 }
12188 
12189 /*
12190   Line-oriented counts and seeks are as dumb as they can be at the moment.
12191   Later we can speed them up by building little indexes.
12192 */
12193 CK_OFF_T
z_count(channel,what)12194 z_count(channel, what) int channel, what; { /* Count bytes or lines in file */
12195     FILE * t;
12196     int i, x;
12197     CK_OFF_T pos, count = (CK_OFF_T)0;
12198     if (!z_inited)                      /* Check stuff... */
12199       return(z_error = FX_NOP);
12200     if (channel >= z_maxchan)
12201       return(z_error = FX_CHN);
12202     if (!z_file[channel])
12203       return(z_error = FX_NOP);
12204     if (!(t = z_file[channel]->z_fp))
12205       return(z_error = FX_NOP);
12206     pos = CKFTELL(t);			/* Save current file pointer */
12207     errno = 0;
12208     z_error = 0;
12209     if (what == RD_CHAR) {              /* Size in bytes requested */
12210 #ifdef COMMENT
12211         if (!CKFSEEK(t,0L,2)) {		/* Seek to end */
12212             count = CKFTELL(t);		/* Get file pointer */
12213             CKFSEEK(t,pos,0);		/* Restore file file pointer */
12214             return(count);
12215         } else                          /* Fallback in case seek fails */
12216 #endif	/* COMMENT */
12217           return(zgetfs(z_file[channel]->z_name));
12218     }
12219     rewind(t);                          /* Line count requested - rewind. */
12220     while (1) {                         /* Count lines. */
12221         if ((x = getc(t)) == EOF)       /* Stupid byte loop */
12222           break;                        /* but it works as well as anything */
12223         if (x == '\n')                  /* else... */
12224           count++;
12225     }
12226     x = CKFSEEK(t,pos,0);		/* Restore file pointer */
12227     return(count);
12228 }
12229 
12230 /* User interface for generalized channel-oriented file i/o */
12231 
12232 struct keytab fctab[] = {               /* FILE subcommands */
12233     { "close",      FIL_CLS, 0 },
12234     { "count",      FIL_COU, 0 },
12235     { "flush",      FIL_FLU, 0 },
12236     { "list",       FIL_LIS, 0 },
12237     { "open",       FIL_OPN, 0 },
12238     { "read",       FIL_REA, 0 },
12239     { "rewind",     FIL_REW, 0 },
12240     { "seek",       FIL_SEE, 0 },
12241     { "status",     FIL_STA, 0 },
12242     { "write",      FIL_WRI, 0 }
12243 };
12244 int nfctab = (sizeof (fctab) / sizeof (struct keytab));
12245 
12246 static struct keytab fcswtab[] = {      /* OPEN modes */
12247     { "/append",    FM_APP,  0 },
12248     { "/binary",    FM_BIN,  0 },
12249 #ifdef COMMENT
12250     { "/command",   FM_CMD,  0 },       /* Not implemented */
12251 #endif /* COMMENT */
12252     { "/read",      FM_REA,  0 },
12253 #ifdef UNIX                             /* Could be expanded to VMS etc.. */
12254     { "/stderr",    FM_STDERR,0 },
12255     { "/stdin",     FM_STDIN,0 },
12256     { "/stdout",    FM_STDOUT,0 },
12257 #endif  /* UNIX */
12258     { "/write",     FM_WRI,  0 }
12259 };
12260 static int nfcswtab = (sizeof (fcswtab) / sizeof (struct keytab));
12261 
12262 static struct keytab fclkwtab[] = {     /* CLOSE options */
12263     { "all",        1,       0 }
12264 };
12265 
12266 static struct keytab fsekwtab[] = {     /* SEEK symbols */
12267     { "eof",        1,       0 },
12268     { "last",       2,       0 }
12269 };
12270 static int nfsekwtab = (sizeof (fsekwtab) / sizeof (struct keytab));
12271 
12272 #define SEE_LINE  RD_LINE               /* SEEK options */
12273 #define SEE_CHAR  RD_CHAR
12274 #define SEE_REL   3
12275 #define SEE_ABS   4
12276 #define SEE_FIND  5
12277 
12278 static struct keytab fskswtab[] = {
12279     { "/absolute",  SEE_ABS,  0 },
12280     { "/byte",      SEE_CHAR, 0 },
12281     { "/character", SEE_CHAR, CM_INV },
12282     { "/find",      SEE_FIND, CM_ARG },
12283     { "/line",      SEE_LINE, 0 },
12284     { "/relative",  SEE_REL,  0 }
12285 };
12286 static int nfskswtab = (sizeof (fskswtab) / sizeof (struct keytab));
12287 
12288 #define COU_LINE  RD_LINE               /* COUNT options */
12289 #define COU_CHAR  RD_CHAR
12290 #define COU_LIS   3
12291 #define COU_NOL   4
12292 
12293 static struct keytab fcoswtab[] = {
12294     { "/bytes",     COU_CHAR, 0      },
12295     { "/characters",COU_CHAR, CM_INV },
12296     { "/lines",     COU_LINE, 0      },
12297     { "/list",      COU_LIS,  0      },
12298     { "/nolist",    COU_NOL,  0      },
12299     { "/quiet",     COU_NOL,  CM_INV }
12300 };
12301 static int nfcoswtab = (sizeof (fcoswtab) / sizeof (struct keytab));
12302 
12303 static struct keytab frdtab[] = {       /* READ types */
12304     { "/block",     RD_SIZE, CM_INV|CM_ARG },
12305     { "/byte",      RD_CHAR, CM_INV },
12306     { "/character", RD_CHAR, 0      },
12307     { "/line",      RD_LINE, 0      },
12308     { "/size",      RD_SIZE, CM_ARG },
12309     { "/trim",      RD_TRIM, 0      },
12310     { "/untabify",  RD_UNTA, 0      }
12311 };
12312 static int nfrdtab = (sizeof (frdtab) / sizeof (struct keytab));
12313 
12314 static struct keytab fwrtab[] = {       /* WRITE types */
12315     { "/block",     WR_SIZE, CM_INV|CM_ARG },
12316     { "/byte",      WR_CHAR, CM_INV },
12317     { "/character", WR_CHAR, 0      },
12318     { "/line",      WR_LINE, 0      },
12319     { "/lpad",      WR_LPAD, CM_ARG },
12320     { "/rpad",      WR_RPAD, CM_ARG },
12321     { "/size",      WR_SIZE, CM_ARG },
12322     { "/string",    WR_STRI, 0      }
12323 };
12324 static int nfwrtab = (sizeof (fwrtab) / sizeof (struct keytab));
12325 
12326 static char blanks[] = "\040\040\040\040"; /* Some blanks for formatting */
12327 static char * seek_target = NULL;
12328 
12329 int
dofile(op)12330 dofile(op) int op; {                    /* Do the FILE command */
12331     char vnambuf[VNAML];                /* Buffer for variable names */
12332     char *vnp = NULL;                   /* Pointer to same */
12333     char zfilnam[CKMAXPATH+2];
12334     char * p, * m;
12335     struct FDB fl, sw, nu;
12336     CK_OFF_T z;
12337     int rsize, filmode = 0, relative = -1, eofflg = 0;
12338     int rc, x, y, cx, n, getval, dummy, confirmed, listing = -1;
12339     int charflag = 0, sizeflag = 0;
12340     int pad = 32, wr_lpad = 0, wr_rpad = 0, rd_trim = 0, rd_untab = 0;
12341 
12342     makestr(&seek_target,NULL);
12343 
12344     if (op == XXFILE) {                 /* FILE command was given */
12345         /* Get subcommand */
12346         if ((cx = cmkey(fctab,nfctab,"Operation","",xxstring)) < 0) {
12347             if (cx == -3) {
12348                 printf("?File operation required\n");
12349                 x = -9;
12350             }
12351             return(cx);
12352         }
12353     } else {                            /* Shorthand command was given */
12354         switch (op) {
12355           case XXF_CL: cx = FIL_CLS; break; /* FCLOSE */
12356           case XXF_FL: cx = FIL_FLU; break; /* FFLUSH */
12357           case XXF_LI: cx = FIL_LIS; break; /* FLIST */
12358           case XXF_OP: cx = FIL_OPN; break; /* etc... */
12359           case XXF_RE: cx = FIL_REA; break;
12360           case XXF_RW: cx = FIL_REW; break;
12361           case XXF_SE: cx = FIL_SEE; break;
12362           case XXF_ST: cx = FIL_STA; break;
12363           case XXF_WR: cx = FIL_WRI; break;
12364           case XXF_CO: cx = FIL_COU; break;
12365           default: return(-2);
12366         }
12367     }
12368     switch (cx) {                       /* Do requested subcommand */
12369       case FIL_OPN:                     /* OPEN */
12370         cmfdbi(&sw,                     /* Switches */
12371                _CMKEY,                  /* fcode */
12372                "Variable or switch",    /* hlpmsg */
12373                "",                      /* default */
12374                "",                      /* addtl string data */
12375                nfcswtab,                /* addtl numeric data 1: tbl size */
12376                4,                       /* addtl numeric data 2: 4 = cmswi */
12377                xxstring,                /* Processing function */
12378                fcswtab,                 /* Keyword table */
12379                &fl                      /* Pointer to next FDB */
12380                );
12381         cmfdbi(&fl,                     /* Anything that doesn't match */
12382                _CMFLD,                  /* fcode */
12383                "Variable",              /* hlpmsg */
12384                "",
12385                "",
12386                0,
12387                0,
12388                NULL,
12389                NULL,
12390                NULL
12391                );
12392         while (1) {
12393             x = cmfdb(&sw);             /* Parse something */
12394             if (x < 0) {
12395                 if (x == -3) {
12396                     printf("?Variable name and file name required\n");
12397                     x = -9;
12398                 }
12399                 return(x);
12400             }
12401             if (cmresult.fcode == _CMFLD)
12402               break;
12403             else if (cmresult.fcode == _CMKEY) {
12404                 char c;
12405                 c = cmgbrk();
12406                 if ((getval =
12407                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12408                     printf("?This switch does not take an argument\n");
12409                     return(-9);
12410                 }
12411 #ifdef COMMENT
12412                 /* Uncomment if we add any FOPEN switches that take args */
12413                 if (!getval && (cmgkwflgs() & CM_ARG)) {
12414                     printf("?This switch requires an argument\n");
12415                     return(-9);         /* (none do...) */
12416                 }
12417 #endif /* COMMENT */
12418                 debug(F101,"filmode A","",filmode);
12419                 filmode |= cmresult.nresult; /* OR in the file mode */
12420                 debug(F101,"filmode B","",filmode);
12421                 debug(F101,"filmode & (FM_REA|FM_STDIN)","",
12422                       filmode & (FM_REA|FM_STDIN));
12423                 debug(F101,"filmode & (FM_WRI|FM_STDOUT|FM_STDERR)","",
12424                       filmode & (FM_WRI|FM_STDOUT|FM_STDERR));
12425                 if ((filmode & (FM_REA|FM_STDIN)) &&
12426                     (filmode & (FM_WRI|FM_STDOUT|FM_STDERR))) {
12427                     printf("?Conflicting file modes\n");
12428                     return(-9);
12429                 }
12430             } else
12431               return(-2);
12432         }
12433         /* Not a switch - get the string */
12434         ckstrncpy(vnambuf,cmresult.sresult,VNAML);
12435         if (!vnambuf[0] || chknum(vnambuf)) { /* (if there is one...) */
12436             printf("?Variable name required\n");
12437             return(-9);
12438         }
12439         vnp = vnambuf;                  /* Check variable-name syntax */
12440         if (vnambuf[0] == CMDQ &&
12441             (vnambuf[1] == '%' || vnambuf[1] == '&'))
12442           vnp++;
12443         y = 0;
12444         if (*vnp == '%' || *vnp == '&') {
12445             if ((y = parsevar(vnp,&x,&dummy)) < 0) {
12446                 printf("?Syntax error in variable name\n");
12447                 return(-9);
12448             }
12449         }
12450 	/* Assign a negative channel number in case we fail */
12451 	addmac(vnambuf,"-1");
12452 
12453         if (!(filmode & FM_RWA))        /* If no access mode specified */
12454           filmode |= FM_REA;            /* default to /READ. */
12455 
12456 #ifdef UNIX
12457         if (filmode & FM_STDIN) {       /* If STDIN specified */
12458             filmode |= FM_REA;          /* it implies /READ */
12459             /* We don't need to parse anything further */
12460             s = "(stdin)";
12461             goto xdofile;               /* Skip around the following */
12462         }
12463         if (filmode & FM_STDOUT) {      /* If STDIN specified */
12464             filmode |= FM_WRI;          /* it implies /WRITE */
12465             /* We don't need to parse anything further */
12466             s = "(stdout)";
12467             goto xdofile;               /* Skip around the following */
12468         }
12469         if (filmode & FM_STDIN) {       /* If STDIN specified */
12470             filmode |= FM_WRI;          /* it implies /WRITE */
12471             /* We don't need to parse anything further */
12472             s = "(stderr)";
12473             goto xdofile;               /* Skip around the following */
12474         }
12475 #endif /* UNIX */
12476         y = 0;                          /* Now parse the filename */
12477         if ((filmode & FM_RWA) == FM_WRI) {
12478 	    x = cmofi("Name of new file","",&s,xxstring);
12479 	} else if ((filmode & FM_RWA) == FM_REA) {
12480 	    x = cmifi("Name of existing file","",&s,&y,xxstring);
12481 	} else {
12482             x = cmiofi("Filename","",&s,&y,xxstring);
12483             debug(F111,"fopen /append x",s,x);
12484 	}
12485         if (x < 0) {
12486             if (x == -3) {
12487                 printf("?Filename required\n");
12488                 x = -9;
12489             }
12490             return(x);
12491         }
12492         if (y) {                        /* No wildcards */
12493             printf("?Wildcards not allowed here\n");
12494             return(-9);
12495         }
12496         if (filmode & (FM_APP|FM_WRI)) { /* Check output access */
12497 #ifndef VMS
12498             if (zchko(s) < 0) {          /* and set error code if denied */
12499                 z_error = FX_ACC;
12500                 printf("?Write access denied - \"%s\"\n",s);
12501                 return(-9);
12502             }
12503 #endif /* VMS */
12504         }
12505 
12506       xdofile:
12507         ckstrncpy(zfilnam,s,CKMAXPATH); /* Is OK - make safe copy */
12508         if ((x = cmcfm()) < 0)          /* Get confirmation of command */
12509           return(x);
12510         if ((n = z_open(zfilnam,filmode)) < 0) {
12511             printf("?OPEN failed - %s: %s\n",zfilnam,ckferror(n));
12512             return(-9);
12513         }
12514         addmac(vnambuf,ckitoa(n));      /* Assign channel number to variable */
12515         return(success = 1);
12516 
12517       case FIL_REW:                     /* REWIND */
12518         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
12519             if (x == -3) {
12520                 printf("?Channel number required\n");
12521                 x = -9;
12522             }
12523             return(x);
12524         }
12525         if ((x = cmcfm()) < 0)
12526           return(x);
12527 	if (n == -9) return(success = 0);
12528 	if (n == -8) return(success = 1);
12529 
12530         if ((rc = z_seek(n,0L)) < 0) {
12531             printf("?REWIND failed - Channel %d: %s\n",n,ckferror(rc));
12532             return(-9);
12533         }
12534         return(success = 1);
12535 
12536       case FIL_CLS:                     /* CLOSE */
12537 #ifdef COMMENT				/* fdc 20100804 - bad idea */
12538          {
12539 	    int i, j, k;		/* Supply default if only one open */
12540 	    s = "";
12541 	    for (k = 0, j = 0, i = 0; i < z_maxchan; i++) {
12542 		if (z_file)
12543 		  if (z_file[i])
12544 		    if (z_file[i]->z_fp) { k++; j = i; }
12545 	    }
12546 	    if (k == 1) s = ckitoa(j);
12547 	 }
12548 #endif	/* COMMENT */
12549           cmfdbi(&nu,                   /* Second FDB - channel number */
12550                  _CMNUM,                /* fcode */
12551                  "Channel number or ALL", /* Help message */
12552                  s,			/* default */
12553                  "",                    /* addtl string data */
12554                  10,                    /* addtl numeric data 1: radix */
12555                  0,                     /* addtl numeric data 2: 0 */
12556                  xxstring,              /* Processing function */
12557                  NULL,                  /* Keyword table */
12558                  &sw			/* Pointer to next FDB */
12559                  );                     /* Pointer to next FDB */
12560 	 cmfdbi(&sw,			/* First FDB - command switches */
12561                  _CMKEY,                /* fcode */
12562                  "",			/* help message */
12563 		 "",			/* Default */
12564 		 "",			/* No addtl string data */
12565                  1,                     /* addtl numeric data 1: tbl size */
12566                  0,                     /* addtl numeric data 2: 4 = cmswi */
12567                  xxstring,              /* Processing function */
12568                  fclkwtab,              /* Keyword table */
12569 		 NULL			/* Last in chain */
12570                  );
12571         x = cmfdb(&nu);                 /* Parse something */
12572         if (x < 0) {
12573             if (x == -3) {
12574                 printf("?Channel number or ALL required\n");
12575                 x = -9;
12576             }
12577             return(x);
12578         }
12579         if (cmresult.fcode == _CMNUM)
12580           n = cmresult.nresult;
12581         else if (cmresult.fcode == _CMKEY)
12582           n = -1;
12583         if ((x = cmcfm()) < 0)
12584           return(x);
12585 	if (n == -9) return(success = 0);
12586 	if (n == -8) return(success = 1);
12587 
12588         rc = 1;
12589         if (n < 0) {
12590             int count = 0;
12591             int i;
12592             for (i = 0; i < z_maxchan; i++) {
12593                 x = z_close(i);
12594                 if (x == FX_SYS) {
12595                     printf("?CLOSE failed - Channel %d: %s\n",n,ckferror(x));
12596                     rc = 0;
12597                 } else if (x > -1)
12598                   count++;
12599             }
12600             debug(F101,"FILE CLOSE ALL","",count);
12601         } else if ((x = z_close(n)) < 0) {
12602             printf("?CLOSE failed - Channel %d: %s\n",n,ckferror(x));
12603             return(-9);
12604         }
12605         return(success = rc);
12606 
12607       case FIL_REA:                     /* READ */
12608       case FIL_WRI:                     /* WRITE */
12609         rsize = 0;
12610         cmfdbi(&sw,                     /* Switches */
12611                _CMKEY,                  /* fcode */
12612                "Channel or switch",     /* hlpmsg */
12613                "",                      /* default */
12614                "",                      /* addtl string data */
12615                (cx == FIL_REA) ? nfrdtab : nfwrtab,
12616                4,                       /* addtl numeric data 2: 4 = cmswi */
12617                xxstring,                /* Processing function */
12618                (cx == FIL_REA) ? frdtab : fwrtab, /* Keyword table */
12619                &nu                      /* Pointer to next FDB */
12620                );
12621         cmfdbi(&nu,                     /* Channel number */
12622                _CMNUM,                  /* fcode */
12623                "Channel",
12624                "",                      /* default */
12625                "",                      /* addtl string data */
12626                10,                      /* addtl numeric data 1: radix */
12627                0,                       /* addtl numeric data 2: 0 */
12628                xxstring,                /* Processing function */
12629                NULL,                    /* Keyword table */
12630                NULL                     /* Pointer to next FDB */
12631                );
12632         do {
12633             x = cmfdb(&sw);             /* Parse something */
12634             if (x < 0) {
12635                 if (x == -3) {
12636                     printf("?Channel number required\n");
12637                     x = -9;
12638                 }
12639                 return(x);
12640             }
12641             if (cmresult.fcode == _CMNUM) /* Channel number */
12642               break;
12643             else if (cmresult.fcode == _CMKEY) { /* Switch */
12644                 char c;
12645                 c = cmgbrk();
12646                 if ((getval =
12647                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12648                     printf("?This switch does not take an argument\n");
12649                     return(-9);
12650                 }
12651                 if (!getval && (cmgkwflgs() & CM_ARG)) {
12652                     printf("?This switch requires an argument\n");
12653                     return(-9);
12654                 }
12655                 switch (cmresult.nresult) {
12656                   case WR_LINE:
12657                     charflag = 0;
12658                     sizeflag = 0;
12659                     rsize = 0;
12660                     break;
12661                   case WR_CHAR:
12662                     rsize = 1;
12663                     charflag = 1;
12664                     sizeflag = 1;
12665                     break;
12666                   case WR_SIZE:
12667                     if ((x = cmnum("Bytes","",10,&rsize, xxstring)) < 0) {
12668                         if (x == -3) {
12669                             printf("?Number required\n");
12670                             x = -9;
12671                         }
12672                         return(x);
12673                     }
12674 		    if (rsize > LINBUFSIZ) {
12675 			printf("?Maximum FREAD/FWRITE size is %d\n",LINBUFSIZ);
12676 			rsize = 0;
12677 			return(-9);
12678 		    }
12679                     charflag = 0;
12680                     sizeflag = 1;
12681                     break;
12682                   case WR_STRI:
12683                     rsize = 1;
12684                     charflag = 0;
12685                     sizeflag = 0;
12686                     break;
12687                   case WR_LPAD:
12688                   case WR_RPAD:
12689                     if ((x = cmnum("Numeric ASCII character value",
12690                                    "32",10,&pad, xxstring)) < 0)
12691                       return(x);
12692                     if (cmresult.nresult == WR_LPAD)
12693                       wr_lpad = 1;
12694                     else
12695                       wr_rpad = 1;
12696                     break;
12697 		  case RD_TRIM:
12698 		    rd_trim = 1;
12699 		    break;
12700 		  case RD_UNTA:
12701 		    rd_untab = 1;
12702 		    break;
12703                 }
12704                 debug(F101,"FILE READ rsize 2","",rsize);
12705             } else
12706               return(-2);
12707         } while
12708           (cmresult.fcode == _CMKEY);
12709 
12710         n = cmresult.nresult;           /* Channel */
12711         debug(F101,"FILE READ/WRITE channel","",n);
12712 
12713         if (cx == FIL_WRI) {            /* WRITE */
12714             int len = 0;
12715             if ((x = cmtxt("Text","",&s,xxstring)) < 0)
12716               return(x);
12717 	    if (n == -9) return(success = 0);
12718 	    if (n == -8) return(success = 1);
12719 
12720             ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy */
12721             s = line;
12722             s = brstrip(s);             /* Strip braces */
12723             if (charflag) {             /* Write one char */
12724                 len = 1;                /* So length = 1 */
12725                 rsize = 1;              /* Don't supply terminator */
12726             } else if (!sizeflag) {     /* Write a string */
12727                 len = -1;               /* So length is unspecified */
12728             } else {                    /* Write a block of given size */
12729                 int i, k, xx;
12730                 if (rsize > TMPBUFSIZ) {
12731                     z_error = FX_OFL;
12732                     printf("?Buffer overflow\n");
12733                     return(-9);
12734                 }
12735                 len = rsize;            /* rsize is really length */
12736                 rsize = 1;              /* Don't supply a terminator */
12737                 xx = strlen(s);         /* Size of given string */
12738                 if (xx >= len) {        /* Bigger or equal */
12739                     s[len] = NUL;
12740                 } else if (wr_lpad) {   /* Smaller, left-padding requested */
12741                     for (i = 0; i < len - xx; i++) /* Must make a copy */
12742                       tmpbuf[i] = pad;
12743                     ckstrncpy(tmpbuf+i,s,TMPBUFSIZ-i);
12744                     tmpbuf[len] = NUL;
12745                     s = tmpbuf;         /* Redirect write source */
12746                 } else if (wr_rpad) {   /* Smaller with right-padding */
12747                     for (i = xx; i < len; i++)
12748                       s[i] = pad;
12749                     s[len] = NUL;
12750                 }
12751             }
12752             if ((rc = z_out(n,s,len,rsize)) < 0) { /* Try to write */
12753                 printf("?Channel %d WRITE error: %s\n",n,ckferror(rc));
12754                 return(-9);
12755             }
12756         } else {                        /* FIL_REA READ */
12757             confirmed = 0;
12758             vnambuf[0] = NUL;
12759             x = cmfld("Variable name","",&s,NULL);
12760             debug(F111,"FILE READ cmfld",s,x);
12761             if (x < 0) {
12762                 if (x == -3 || !*s) {
12763                     if ((x = cmcfm()) < 0)
12764                       return(x);
12765                     else
12766                       confirmed++;
12767                 } else
12768                   return(x);
12769             }
12770             ckstrncpy(vnambuf,s,VNAML);
12771             debug(F111,"FILE READ vnambuf",vnambuf,confirmed);
12772             if (vnambuf[0]) {           /* Variable name given, check it */
12773                 if (!confirmed) {
12774                     x = cmcfm();
12775                     if (x < 0)
12776                       return(x);
12777                     else
12778                       confirmed++;
12779                 }
12780                 vnp = vnambuf;
12781                 if (vnambuf[0] == CMDQ &&
12782                     (vnambuf[1] == '%' || vnambuf[1] == '&'))
12783                   vnp++;
12784                 y = 0;
12785                 if (*vnp == '%' || *vnp == '&') {
12786                     if ((y = parsevar(vnp,&x,&dummy)) < 0) {
12787                         printf("?Syntax error in variable name\n");
12788                         return(-9);
12789                     }
12790                 }
12791             }
12792             debug(F111,"FILE READ variable",vnambuf,confirmed);
12793 
12794             if (!confirmed)
12795               if ((x = cmcfm()) < 0)
12796                 return(x);
12797 
12798 	    if (n == -9) return(success = 0);
12799 	    if (n == -8) return(success = 1);
12800 
12801             line[0] = NUL;              /* Clear destination buffer */
12802 #ifdef COMMENT
12803             if (rsize >= LINBUFSIZ)     /* Don't overrun it */
12804               rsize = LINBUFSIZ - 1;
12805 #endif	/* COMMENT */
12806 
12807             if (rsize == 0) {		/* Read a line */
12808 		rc = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
12809             } else {
12810 		rc = z_in(n,line,LINBUFSIZ,rsize,1); /* Read a block */
12811 	    }
12812             if (rc < 0) {               /* Error... */
12813                 debug(F101,"FILE READ error","",rc);
12814                 debug(F101,"FILE READ errno","",errno);
12815                 if (rc == FX_EOF) {     /* EOF - fail but no error message */
12816                     return(success = 0);
12817                 } else {                /* Other error - fail and print msg */
12818                     printf("?READ error: %s\n",ckferror(rc));
12819                     return(-9);
12820                 }
12821             }
12822 	    if (rsize == 0) {		/* FREAD /LINE postprocessing */
12823 		if (rd_trim) {		/* Trim */
12824 		    int i, k;
12825 		    k = strlen(line);
12826 		    if (k > 0) {
12827 			for (i = k-1; i > 0; i--) {
12828 			    if (line[i] == SP || line[i] == '\t')
12829 			      line[i] = NUL;
12830 			    else
12831 			      break;
12832 			}
12833 		    }
12834 		}
12835 		if (rd_untab) {		/* Untabify */
12836 		    if (untabify(line,tmpbuf,TMPBUFSIZ) > -1)
12837 		      ckstrncpy(line,tmpbuf,LINBUFSIZ);
12838 		}
12839 	    }
12840             debug(F110,"FILE READ data",line,0);
12841             if (vnambuf[0])             /* Read OK - If variable name given */
12842               addmac(vnambuf,line);     /* Assign result to variable */
12843             else                        /* otherwise */
12844               printf("%s\n",line);      /* just print it */
12845         }
12846         return(success = 1);
12847 
12848       case FIL_SEE:                     /* SEEK */
12849       case FIL_COU:                     /* COUNT */
12850         rsize = RD_CHAR;                /* Defaults to /BYTE */
12851         cmfdbi(&sw,                     /* Switches */
12852                _CMKEY,                  /* fcode */
12853                "Channel or switch",     /* hlpmsg */
12854                "",                      /* default */
12855                "",                      /* addtl string data */
12856                ((cx == FIL_SEE) ? nfskswtab : nfcoswtab),
12857                4,                       /* addtl numeric data 2: 4 = cmswi */
12858                xxstring,                /* Processing function */
12859                ((cx == FIL_SEE) ? fskswtab : fcoswtab),
12860                &nu                      /* Pointer to next FDB */
12861                );
12862         cmfdbi(&nu,                     /* Channel number */
12863                _CMNUM,                  /* fcode */
12864                "Channel",
12865                "",                      /* default */
12866                "",                      /* addtl string data */
12867                10,                      /* addtl numeric data 1: radix */
12868                0,                       /* addtl numeric data 2: 0 */
12869                xxstring,                /* Processing function */
12870                NULL,                    /* Keyword table */
12871                NULL                     /* Pointer to next FDB */
12872                );
12873         do {
12874             x = cmfdb(&sw);             /* Parse something */
12875             if (x < 0) {
12876                 if (x == -3) {
12877                     printf("?Channel number required\n");
12878                     x = -9;
12879                 }
12880                 return(x);
12881             }
12882             if (cmresult.fcode == _CMNUM) /* Channel number */
12883               break;
12884             else if (cmresult.fcode == _CMKEY) { /* Switch */
12885                 char c;
12886                 c = cmgbrk();
12887                 if ((getval =
12888                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
12889                     printf("?This switch does not take an argument\n");
12890                     return(-9);
12891                 }
12892                 if (cx == FIL_SEE) {
12893                     switch (cmresult.nresult) {
12894                       case SEE_REL: relative = 1; break;
12895                       case SEE_ABS: relative = 0; break;
12896 		      case SEE_FIND: {
12897 			  if (getval) {
12898 			      y = cmfld("string or pattern","",&s,xxstring);
12899 			      if (y < 0)
12900 				return(y);
12901 			      makestr(&seek_target,brstrip(s));
12902 			      break;
12903 			  }
12904 		      }
12905                       default: rsize = cmresult.nresult;
12906                     }
12907                 } else if (cx == FIL_COU) {
12908                     switch (cmresult.nresult) {
12909                       case COU_LIS: listing = 1; break;
12910                       case COU_NOL: listing = 0; break;
12911                       default: rsize = cmresult.nresult;
12912                     }
12913                 }
12914             }
12915         } while
12916           (cmresult.fcode == _CMKEY);
12917 
12918         n = cmresult.nresult;           /* Channel */
12919         debug(F101,"FILE SEEK/COUNT channel","",n);
12920         if (cx == FIL_COU) {
12921             if ((x = cmcfm()) < 0)
12922               return(x);
12923 	    if (n == -9) return(success = 0);
12924 	    if (n == -8) return(success = 1);
12925 
12926             z_filcount = z_count(n,rsize);
12927             if (z_filcount < 0) {
12928                 rc = z_filcount;
12929                 printf("?COUNT error: %s\n",ckferror(rc));
12930                 return(-9);
12931             }
12932             if (listing < 0)
12933               listing = !xcmdsrc;
12934             if (listing)
12935               printf(" %ld %s%s\n",
12936                      z_filcount,
12937                      ((rsize == RD_CHAR) ? "byte" : "line"),
12938                      ((z_filcount == 1L) ? "" : "s")
12939                      );
12940             return(success = (z_filcount > -1) ? 1 : 0);
12941         }
12942 	m = (rsize == RD_CHAR) ?
12943 	    "Number of bytes;\n or keyword" :
12944 	    "Number of lines;\n or keyword";
12945         cmfdbi(&sw,                     /* SEEK symbolic targets (EOF) */
12946                _CMKEY,                  /* fcode */
12947                m,
12948                "",
12949                "",                      /* addtl string data */
12950                nfsekwtab,               /* addtl numeric data 1: table size */
12951                0,                       /* addtl numeric data 2: 4 = cmswi */
12952                xxstring,                /* Processing function */
12953                fsekwtab,                /* Keyword table */
12954                &nu                      /* Pointer to next FDB */
12955                );
12956         cmfdbi(&nu,                     /* Byte or line number */
12957                _CMNUW,                  /* fcode */
12958                "",
12959                "",                      /* default */
12960                "",                      /* addtl string data */
12961                10,                      /* addtl numeric data 1: radix */
12962                0,                       /* addtl numeric data 2: 0 */
12963                xxstring,                /* Processing function */
12964                NULL,                    /* Keyword table */
12965                NULL                     /* Pointer to next FDB */
12966                );
12967         x = cmfdb(&sw);                 /* Parse something */
12968         if (x < 0) {
12969             if (x == -3) {
12970                 printf("?Channel number or EOF required\n");
12971                 x = -9;
12972             }
12973             return(x);
12974         }
12975         if (cmresult.fcode == _CMNUW) {
12976             z = cmresult.wresult;
12977             debug(F110,"FILE SEEK atmbuf",atmbuf,0);
12978             if (relative < 0) {
12979                 if (cx == FIL_SEE && (atmbuf[0] == '+' || atmbuf[0] == '-'))
12980                   relative = 1;
12981                 else
12982                   relative = 0;
12983             }
12984         } else if (cmresult.fcode == _CMKEY) {
12985             eofflg = cmresult.nresult;
12986             relative = 0;
12987             y = 0 - eofflg;
12988         }
12989         if ((x = cmcfm()) < 0)
12990           return(x);
12991 	if (n == -9) return(success = 0);
12992 	if (n == -8) return(success = 1);
12993         y = 1;                          /* Recycle this */
12994         z_flush(n);
12995         debug(F101,"FILE SEEK relative","",relative);
12996         debug(F101,"FILE SEEK rsize","",rsize);
12997 
12998         if (rsize == RD_CHAR) {         /* Seek to byte position */
12999             if (relative > 0) {
13000                 CK_OFF_T pos;
13001                 pos = z_getpos(n);
13002                 if (pos < (CK_OFF_T)0) {
13003                     rc = pos;
13004                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
13005                     return(-9);
13006                 }
13007                 z += pos;
13008             } else {
13009                 if (z < 0 && !eofflg) { /* Negative arg but not relative */
13010                     y = 0;              /* Remember this was bad */
13011                     z = 0;              /* but substitute 0 */
13012                 }
13013             }
13014             debug(F101,"FILE SEEK /CHAR z","",z);
13015             if (z < 0 && !eofflg) {
13016                 z_error = FX_RNG;
13017                 return(success = 0);
13018             }
13019             if ((rc = z_seek(n,z)) < 0) {
13020                 if (rc == FX_EOF) return(success = 0);
13021                 printf("?SEEK /BYTE failed - Channel %d: %s\n",n,ckferror(rc));
13022                 return(-9);
13023             }
13024         } else {                        /* Seek to line */
13025             if (relative > 0) {
13026                 CK_OFF_T pos;
13027                 pos = z_getline(n);
13028                 debug(F101,"FILE SEEK /LINE pos","",pos);
13029                 if (pos < 0) {
13030                     rc = pos;
13031                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
13032                     return(-9);
13033                 }
13034                 z += pos;
13035             }
13036             debug(F101,"FILE SEEK /LINE z","",z);
13037             debug(F101,"FILE SEEK /LINE eofflg","",eofflg);
13038             if (z < 0 && !eofflg) {
13039                 z_error = FX_RNG;
13040                 return(success = 0);
13041             }
13042             if ((rc = z_line(n,z)) < 0) {
13043                 if (rc == FX_EOF) return(success = 0);
13044                 printf("?SEEK /LINE failed - Channel %d: %s\n",n,ckferror(rc));
13045                 return(-9);
13046             }
13047         }
13048 	/*
13049 	  Now, having sought to the desired starting spot, if a /FIND:
13050 	  target was specified, look for it now.
13051 	*/
13052 	if (seek_target) {
13053 	    int flag = 0, ispat = 0, matchresult = 0;
13054 	    while (!flag) {
13055 		y = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
13056 		if (y < 0) {
13057 		    y = 0;
13058 		    break;
13059 		}
13060 		if (ispattern(seek_target)) {
13061 		    matchresult = ckmatch(seek_target,line,inpcas[cmdlvl],1+4);
13062 		} else {
13063 		    /* This is faster */
13064 		    matchresult = ckindex(seek_target,line,0,0,inpcas[cmdlvl]);
13065 		}
13066 		if (matchresult) {
13067 		    flag = 1;
13068 		    break;
13069 		}
13070 	    }
13071 	    if (flag) {
13072 		debug(F111,"FSEEK HAVE MATCH",seek_target,z_getline(n));
13073 		/* Back up to beginning of line where target found */
13074 		if ((y = z_line(n,z_getline(n)-1)) < 0) {
13075 		    if (rc == FX_EOF) return(success = 0);
13076 		    printf("?SEEK /LINE failed - Channel %d: %s\n",
13077 			   n,ckferror(rc));
13078 		    return(-9);
13079 		}
13080 		debug(F101,"FSEEK LINE","",y);
13081 	    }
13082 	}
13083         return(success = (y < 0) ? 0 : 1);
13084 
13085       case FIL_LIS: {                   /* LIST open files */
13086 #ifdef CK_TTGWSIZ
13087           extern int cmd_rows, cmd_cols;
13088 #endif /* CK_TTGWSIZ */
13089           extern int xaskmore;
13090           int i, x, n = 0, paging = 0;
13091           char * s;
13092 
13093           if ((x = cmcfm()) < 0)
13094             return(x);
13095 
13096 #ifdef CK_TTGWSIZ
13097           if (cmd_rows > 0 && cmd_cols > 0)
13098 #endif /* CK_TTGWSIZ */
13099             paging = xaskmore;
13100 
13101           printf("System open file limit:%5d\n", z_openmax);
13102           printf("Maximum for FILE OPEN: %5d\n", z_maxchan);
13103           printf("Files currently open:  %5d\n\n", z_nopen);
13104           n = 4;
13105           for (i = 0; i < z_maxchan; i++) {
13106               s = z_getname(i);         /* Got one? */
13107               if (s) {                  /* Yes */
13108                   char m[8];
13109                   m[0] = NUL;
13110                   printf("%2d. %s",i,s); /* Print name */
13111                   n++;                   /* Count it */
13112                   x = z_getmode(i);      /* Get modes & print them */
13113                   if (x > 0) {
13114                       if (x & FM_REA) ckstrncat(m,"R",8);
13115                       if (x & FM_WRI) ckstrncat(m,"W",8);
13116                       if (x & FM_APP) ckstrncat(m,"A",8);
13117                       if (x & FM_BIN) ckstrncat(m,"B",8);
13118                       if (m[0])
13119                         printf(" (%s)",m);
13120                       if (x & FM_EOF)
13121                         printf(" [EOF]");
13122                       else		/* And file position too */
13123                         printf(" %s",ckfstoa(z_getpos(i)));
13124                   }
13125                   printf("\n");
13126 #ifdef CK_TTGWSIZ
13127                   if (paging > 0) {     /* Pause at end of screen */
13128                       if (n > cmd_rows - 3) {
13129                           if (!askmore())
13130                             break;
13131                           else
13132                             n = 0;
13133                       }
13134                   }
13135 #endif /* CK_TTGWSIZ */
13136               }
13137           }
13138           return(success = 1);
13139       }
13140 
13141       case FIL_FLU:                     /* FLUSH */
13142         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
13143             if (x == -3) {
13144                 printf("?Channel number required\n");
13145                 x = -9;
13146             }
13147             return(x);
13148         }
13149         if ((x = cmcfm()) < 0)
13150           return(x);
13151 	if (n == -9) return(success = 0);
13152 	if (n == -8) return(success = 1);
13153         if ((rc = z_flush(n)) < 0) {
13154             printf("?FLUSH failed - Channel %d: %s\n",n,ckferror(rc));
13155             return(-9);
13156         }
13157         return(success = 1);
13158 
13159       case FIL_STA:                     /* STATUS */
13160 	{
13161 	    int i, j, k;		/* Supply default if only one open */
13162 	    s = "";
13163 	    for (k = 0, j = 0, i = 0; i < z_maxchan; i++) {
13164 		if (z_file)
13165 		  if (z_file[i])
13166 		    if (z_file[i]->z_fp) { k++; j = i; }
13167 	    }
13168 	    if (k == 1) s = ckitoa(j);
13169 	}
13170         if ((x = cmnum("Channel number",s,10,&n, xxstring)) < 0) {
13171             if (x == -3) {
13172 		if (z_nopen > 1) {
13173 		    printf("?%d files open - please supply channel number\n",
13174 			   z_nopen);
13175 		    return(-9);
13176 		}
13177             } else
13178 	      return(x);
13179         }
13180         if ((y = cmcfm()) < 0)
13181           return(y);
13182 	if ((!z_file || z_nopen == 0) && x == -3) {
13183 	    printf("No files open\n");
13184 	    return(success = 1);
13185 	}
13186         p = blanks + 3;                 /* Tricky formatting... */
13187         if (n < 1000) p--;
13188         if (n < 100) p--;
13189         if (n < 10) p--;
13190         if ((rc = z_getmode(n)) < 0) {
13191             printf("Channel %d:%s%s\n",n,p,ckferror(rc));
13192             return(success = 0);
13193         } else if (!rc) {
13194             printf("Channel %d:%sNot open\n",n,p);
13195             return(success = 0);
13196         } else {
13197             CK_OFF_T xx;
13198             s = z_getname(n);
13199             if (!s) s = "(name unknown)";
13200             printf("Channel %d:%sOpen\n",n,p);
13201             printf(" File:        %s\n Modes:      ",s);
13202             if (rc & FM_REA) printf(" /READ");
13203             if (rc & FM_WRI) printf(" /WRITE");
13204             if (rc & FM_APP) printf(" /APPEND");
13205             if (rc & FM_BIN) printf(" /BINARY");
13206             if (rc & FM_CMD) printf(" /COMMAND");
13207             if (rc & FM_EOF) printf(" [EOF]");
13208             printf("\n Size:        %s\n",ckfstoa(z_count(n,RD_CHAR)));
13209             printf(" At byte:     %s\n",ckfstoa(z_getpos(n)));
13210             xx = z_getline(n);
13211             if (xx > (CK_OFF_T)-1)
13212               printf(" At line:     %s\n",ckfstoa(xx));
13213             return(success = 1);
13214         }
13215       default:
13216         return(-2);
13217     }
13218 }
13219 #endif /* CKCHANNELIO */
13220 
13221 #ifndef NOSETKEY
13222 /* Save Key maps and in OS/2 Mouse maps */
13223 int
savkeys(name,disp)13224 savkeys(name,disp) char * name; int disp; {
13225     char *tp;
13226     static struct filinfo xx;
13227     int savfil, i, j, k;
13228     char buf[1024];
13229 
13230     zclose(ZMFILE);
13231 
13232     if (disp) {
13233         xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
13234         xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
13235         xx.lblopts = 0;
13236         savfil = zopeno(ZMFILE,name,NULL,&xx);
13237     } else savfil = zopeno(ZMFILE,name,NULL,NULL);
13238 
13239     if (savfil) {
13240 #ifdef OS2
13241         ztime(&tp);
13242         zsout(ZMFILE, "; Kermit 95 SAVE KEYMAP file: ");
13243         zsoutl(ZMFILE,tp);
13244         if (mskkeys) {
13245             zsoutl(ZMFILE,
13246          "if eq \"\\v(program)\" \"C-Kermit\" set mskermit keycodes on");
13247         } else {
13248             zsoutl(ZMFILE,
13249          "if NOT eq \"\\v(program)\" \"C-Kermit\" stop 1 C-Kermit required.");
13250             zsoutl(ZMFILE,"set mskermit keycodes off");
13251         }
13252         zsoutl(ZMFILE,"");
13253 #else /* OS2 */
13254         ztime(&tp);
13255         zsout(ZMFILE, "; C-Kermit SAVE KEYMAP file: ");
13256         zsoutl(ZMFILE,tp);
13257 #endif /* OS2 */
13258 
13259         zsoutl(ZMFILE,"; Clear previous keyboard mappings ");
13260         zsoutl(ZMFILE,"set key clear");
13261 #ifdef OS2
13262         for (k = 0; k < nttkey; k++) {
13263             if (!ttkeytab[k].flgs) {
13264                 ckmakmsg(buf,1024,
13265                          "set terminal key ",
13266                          ttkeytab[k].kwd,
13267                          " clear",
13268                          NULL
13269                          );
13270                 zsoutl(ZMFILE,buf);
13271             }
13272         }
13273 #endif /* OS2 */
13274         zsoutl(ZMFILE,"");
13275 
13276         for (i = 0; i < KMSIZE; i++) {
13277             if (macrotab[i]) {
13278                 int len = strlen((char *)macrotab[i]);
13279 #ifdef OS2
13280                 ckmakmsg(buf,
13281                          1024,
13282                          "set key \\",
13283                          ckitoa(mskkeys ? cktomsk(i) : i),
13284                          " ",
13285                          NULL
13286                          );
13287 #else /* OS2 */
13288                 ckmakmsg(buf,
13289                          1024,
13290                          "set key \\",
13291                          ckitoa(i),
13292                          NULL,NULL
13293                          );
13294 #endif /* OS2 */
13295                 zsout(ZMFILE,buf);
13296 
13297                 for (j = 0; j < len; j++) {
13298                     char ch = macrotab[i][j];
13299                     if (ch <= SP || ch >= DEL ||
13300                          ch == '-' || ch == ',' ||
13301                          ch == '{' || ch == '}' ||
13302                          ch == ';' || ch == '?' ||
13303                          ch == '.' || ch == '\'' ||
13304                          ch == '\\' || ch == '/' ||
13305                          ch == '#') {
13306                         ckmakmsg(buf,1024,"\\{",ckitoa((int)ch),"}",NULL);
13307                         zsout(ZMFILE,buf);
13308                     } else {
13309                         ckmakmsg(buf,1024,ckctoa((char)ch),NULL,NULL,NULL);
13310                         zsout(ZMFILE,buf);
13311                     }
13312                 }
13313 #ifdef OS2
13314                 ckmakmsg(buf,1024,"\t; ",keyname(i),NULL,NULL);
13315                 zsoutl(ZMFILE,buf);
13316 #else
13317                 zsoutl(ZMFILE,"");
13318 #endif /* OS2 */
13319             } else if ( keymap[i] != i ) {
13320 #ifndef NOKVERBS
13321                 if (IS_KVERB(keymap[i])) {
13322                     for (j = 0; j < nkverbs; j++)
13323                       if (kverbs[j].kwval == (keymap[i] & ~F_KVERB))
13324                         break;
13325                     if (j != nkverbs) {
13326 #ifdef OS2
13327 #ifdef COMMENT
13328                         sprintf(buf, "set key \\%d \\K%s\t; %s",
13329                                 mskkeys ? cktomsk(i) : i,
13330                                 kverbs[j].kwd, keyname(i)
13331                                 );
13332 #else
13333                         ckmakxmsg(buf,  /* 12 string args */
13334                                   1024,
13335                                   "set key \\",
13336                                   ckitoa(mskkeys ? cktomsk(i) : i),
13337                                   " \\K",
13338                                   kverbs[j].kwd,
13339                                   "\t; ",
13340                                   keyname(i),
13341                                   NULL, NULL, NULL, NULL, NULL, NULL);
13342 #endif /* COMMENT */
13343                         zsoutl(ZMFILE,buf);
13344 #else
13345 #ifdef COMMENT
13346                         sprintf(buf, "set key \\%d \\K%s", i, kverbs[j].kwd);
13347 #else
13348                         ckmakmsg(buf,1024,
13349                                  "set key \\",
13350                                  ckitoa(i),
13351                                  " \\K",
13352                                  kverbs[j].kwd
13353                                  );
13354 #endif /* COMMENT */
13355                         zsoutl(ZMFILE,buf);
13356 #endif
13357                     }
13358                 } else
13359 #endif /* NOKVERBS */
13360                   {
13361 #ifdef OS2
13362 #ifdef COMMENT
13363                       sprintf(buf, "set key \\%d \\{%d}\t; %s",
13364                               mskkeys ? cktomsk(i) : i,
13365                               keymap[i],
13366                               keyname(i)
13367                               );
13368 #else
13369                       ckmakxmsg(buf,    /* 8 string args */
13370                                 1024,
13371                                 "set key \\",
13372                                 ckitoa(mskkeys ? cktomsk(i) : i),
13373                                 " \\{",
13374                                 ckitoa(keymap[i]),
13375                                 "}\t; ",
13376                                 keyname(i),
13377                                 NULL,NULL,NULL,NULL,NULL,NULL);
13378 #endif /* COMMENT */
13379                       zsoutl(ZMFILE,buf);
13380 #else
13381 #ifdef COMMENT
13382                       sprintf(buf, "set key \\%d \\{%d}", i, keymap[i]);
13383 #else
13384                       ckmakxmsg(buf,1024,
13385                                "set key \\",
13386                                ckitoa(i),
13387                                " \\{",
13388                                ckitoa(keymap[i]),
13389                                "}",
13390                                NULL,NULL,NULL,NULL,NULL,NULL,NULL);
13391 #endif /* COMMENT */
13392                       zsoutl(ZMFILE,buf);
13393 #endif /* OS2 */
13394                   }
13395             }
13396         }
13397 #ifdef OS2
13398         /* OS/2 also has the SET TERMINAL KEY <termtype> defines */
13399         for (k = 0; k < nttkey; k++) {
13400             extern struct keynode * ttkeymap[];
13401             struct keynode * pnode = NULL;
13402 
13403             if (ttkeytab[k].flgs)       /* Don't process CM_INV or CM_ABR */
13404               continue;
13405 
13406             zsoutl(ZMFILE,"");
13407             ckmakmsg(buf,1024,"; SET TERMINAL KEY ",ttkeytab[k].kwd,NULL,NULL);
13408             zsoutl(ZMFILE,buf);
13409 
13410             for (pnode = ttkeymap[ttkeytab[k].kwval];
13411                  pnode;
13412                  pnode = pnode->next
13413                  ) {
13414                 switch (pnode->def.type) {
13415                   case key:
13416 #ifdef COMMENT
13417                     sprintf(buf, "set terminal key %s \\%d \\{%d}\t; %s",
13418                             ttkeytab[k].kwd,
13419                             mskkeys ? cktomsk(pnode->key) : pnode->key,
13420                             pnode->def.key.scancode,
13421                             keyname(pnode->key)
13422                             );
13423 #else
13424                     ckmakxmsg(buf,
13425                               1024,
13426                               "set terminal key ",
13427                               ttkeytab[k].kwd,
13428                               " \\",
13429                               ckitoa(mskkeys ?
13430                                      cktomsk(pnode->key) :
13431                                      pnode->key),
13432                               " \\{",
13433                               ckitoa(pnode->def.key.scancode),
13434                               "}\t; ",
13435                               keyname(pnode->key),
13436                               NULL,NULL,NULL,NULL
13437                               );
13438 #endif /* COMMENT */
13439                     zsoutl(ZMFILE,buf);
13440                     break;
13441                   case kverb:
13442                     for (j = 0; j < nkverbs; j++)
13443                       if (kverbs[j].kwval == (pnode->def.kverb.id & ~F_KVERB))
13444                         break;
13445                     if (j != nkverbs) {
13446 #ifdef COMMENT
13447                         sprintf(buf, "set terminal key %s \\%d \\K%s\t; %s",
13448                                 ttkeytab[k].kwd,
13449                                 mskkeys ? cktomsk(pnode->key) : pnode->key,
13450                                 kverbs[j].kwd, keyname(pnode->key)
13451                                 );
13452 #else
13453                         ckmakxmsg(buf,
13454                                   1024,
13455                                   "set terminal key ",
13456                                   ttkeytab[k].kwd,
13457                                   " \\",
13458                                   ckitoa(mskkeys ?
13459                                          cktomsk(pnode->key) :
13460                                          pnode->key),
13461                                   " \\K",
13462                                   kverbs[j].kwd,
13463                                   "\t; ",
13464                                   keyname(pnode->key),
13465                                   NULL,NULL,NULL,NULL
13466                                   );
13467 #endif /* COMMENT */
13468                         zsoutl(ZMFILE,buf);
13469                     }
13470                     break;
13471                   case macro: {
13472                       int len = strlen((char *)pnode->def.macro.string);
13473 #ifdef COMMENT
13474                       sprintf(buf,"set terminal key %s \\%d ",
13475                               ttkeytab[k].kwd,
13476                               mskkeys ? cktomsk(pnode->key) : pnode->key);
13477 #else
13478                       ckmakxmsg(buf,
13479                                1024,
13480                                "set terminal key ",
13481                                ttkeytab[k].kwd,
13482                                " \\",
13483                                ckitoa(mskkeys ?
13484                                       cktomsk(pnode->key) :
13485                                       pnode->key),
13486                                " ",
13487                                NULL,NULL,NULL,NULL,NULL,NULL,NULL
13488                               );
13489 #endif /* COMMENT */
13490                       zsout(ZMFILE,buf);
13491 
13492                       for (j = 0; j < len; j++) {
13493                           char ch = pnode->def.macro.string[j];
13494                           if (ch <= SP || ch >= DEL ||
13495                                ch == '-' || ch == ',' ||
13496                                ch == '{' || ch == '}' ||
13497                                ch == ';' || ch == '?' ||
13498                                ch == '.' || ch == '\'' ||
13499                                ch == '\\' || ch == '/' ||
13500                                ch == '#') {
13501                               ckmakmsg(buf,1024,
13502                                        "\\{",ckitoa((int)ch),"}",NULL);
13503                               zsout(ZMFILE,buf);
13504                           } else {
13505                               ckmakmsg(buf,1024,
13506                                        ckctoa((char)ch),NULL,NULL,NULL);
13507                               zsout(ZMFILE,buf);
13508                           }
13509                       }
13510                       ckmakmsg(buf,1024,"\t; ",keyname(pnode->key),NULL,NULL);
13511                       zsoutl(ZMFILE,buf);
13512                       break;
13513                   }
13514                   case literal: {
13515                       int len = strlen((char *)pnode->def.literal.string);
13516 #ifdef COMMENT
13517                       sprintf(buf,"set terminal key %s /literal \\%d ",
13518                               ttkeytab[k].kwd,
13519                               mskkeys ? cktomsk(pnode->key) : pnode->key);
13520 #else
13521                       ckmakxmsg(buf,
13522                                1024,
13523                                "set terminal key ",
13524                                ttkeytab[k].kwd,
13525                                " /literal \\",
13526                                ckitoa(mskkeys ?
13527                                       cktomsk(pnode->key) :
13528                                       pnode->key),
13529                                " ",
13530                                NULL,NULL,NULL,NULL,NULL,NULL,NULL);
13531 #endif /* COMMENT */
13532                       zsout(ZMFILE,buf);
13533 
13534                       for (j = 0; j < len; j++) {
13535                           char ch = pnode->def.literal.string[j];
13536                           if (ch <= SP || ch >= DEL ||
13537                                ch == '-' || ch == ',' ||
13538                                ch == '{' || ch == '}' ||
13539                                ch == ';' || ch == '?' ||
13540                                ch == '.' || ch == '\'' ||
13541                                ch == '\\' || ch == '/' ||
13542                                ch == '#') {
13543                               ckmakmsg(buf,1024,
13544                                        "\\{",ckitoa((int)ch),"}",NULL);
13545                               zsout(ZMFILE,buf);
13546                           } else {
13547                               ckmakmsg(buf,1024,
13548                                        ckctoa((char)ch),NULL,NULL,NULL);
13549                               zsout(ZMFILE,buf);
13550                           }
13551                       }
13552                       ckmakmsg(buf,1024,"\t; ",keyname(pnode->key),NULL,NULL);
13553                       zsoutl(ZMFILE,buf);
13554                       break;
13555                   }
13556                   case esc:
13557 #ifdef COMMENT
13558                     sprintf(buf,
13559                        "set terminal key %s /literal \\%d \\{%d}\\{%d}\t; %s",
13560                             ttkeytab[k].kwd,
13561                             mskkeys ? cktomsk(pnode->key) : pnode->key,
13562                             ISDG200(ttkeytab[k].kwval) ? 30 : 27,
13563                             pnode->def.esc.key & ~F_ESC,
13564                             keyname(pnode->key)
13565                             );
13566 #else
13567                     ckmakxmsg(buf,
13568                               1024,
13569                               "set terminal key ",
13570                               ttkeytab[k].kwd,
13571                               " /literal \\",
13572                               ckitoa(mskkeys ?
13573                                      cktomsk(pnode->key) :
13574                                      pnode->key),
13575                               " \\{",
13576                               ckitoa(ISDG200(ttkeytab[k].kwval) ? 30 : 27),
13577                               "}\\{",
13578                               ckitoa(pnode->def.esc.key & ~F_ESC),
13579                               "}\t; ",
13580                               keyname(pnode->key),
13581                               NULL,NULL
13582                               );
13583 #endif /* COMMENT */
13584                     zsoutl(ZMFILE,buf);
13585                     break;
13586                   case csi:
13587 #ifdef COMMENT
13588                     sprintf(buf,
13589                        "set terminal key %s /literal \\%d \\{27}[\\{%d}\t; %s",
13590                             ttkeytab[k].kwd,
13591                             mskkeys ? cktomsk(pnode->key) : pnode->key,
13592                             pnode->def.csi.key & ~F_CSI,
13593                             keyname(pnode->key)
13594                             );
13595 #else
13596                     ckmakxmsg(buf,
13597                               1024,
13598                               "set terminal key ",
13599                               ttkeytab[k].kwd,
13600                               " /literal \\",
13601                               ckitoa(mskkeys ?
13602                                      cktomsk(pnode->key) :
13603                                      pnode->key),
13604                               " \\{27}[\\{",
13605                               ckitoa(pnode->def.csi.key & ~F_CSI),
13606                               "}\t; ",
13607                               keyname(pnode->key),
13608                               NULL,NULL,NULL,NULL
13609                               );
13610 #endif /* COMMENT */
13611                     zsoutl(ZMFILE,buf);
13612                     break;
13613                   default:
13614                     continue;
13615                 }
13616             }
13617         }
13618 #endif /* OS2 */
13619 
13620         zsoutl(ZMFILE,"");
13621         zsoutl(ZMFILE,"; End");
13622         zclose(ZMFILE);
13623         return(success = 1);
13624     } else {
13625         return(success = 0);
13626     }
13627 }
13628 #endif /* NOSETKEY */
13629 
13630 #define SV_SCRL 0
13631 #define SV_HIST 1
13632 
13633 #ifdef OS2
13634 #ifndef NOLOCAL
13635 static struct keytab trmtrmopt[] = {
13636     { "scrollback", SV_SCRL, 0 }
13637 };
13638 #endif /* NOLOCAL */
13639 #endif /* OS2 */
13640 
13641 static struct keytab cmdtrmopt[] = {
13642 #ifdef CK_RECALL
13643     { "history",    SV_HIST, 0 },
13644 #endif /* CK_RECALL */
13645 #ifdef OS2
13646 #ifndef NOLOCAL
13647     { "scrollback", SV_SCRL, 0 },
13648 #endif /* NOLOCAL */
13649 #endif /* OS2 */
13650     { "", 0, 0 }
13651 };
13652 static int ncmdtrmopt = (sizeof (cmdtrmopt) / sizeof (struct keytab)) - 1;
13653 
13654 #ifdef OS2
13655 #ifndef NOLOCAL
13656 _PROTOTYP(int savscrbk, (int, char *, int));
13657 #endif /* NOLOCAL */
13658 #endif /* OS2 */
13659 
13660 #ifdef CK_RECALL
13661 _PROTOTYP(int savhistory, (char *, int));
13662 #endif /* CK_RECALL */
13663 
13664 int
dosave(xx)13665 dosave(xx) int xx; {
13666     int x, y = 0, disp;
13667     char * s = NULL;
13668     extern struct keytab disptb[];
13669 #ifdef ZFNQFP
13670     struct zfnfp * fnp;
13671 #endif /* ZFNQFP */
13672 
13673 #ifndef NOSETKEY
13674     if (xx == XSKEY) {                  /* SAVE KEYMAP.. */
13675         z = cmofi("Name of Kermit command file","keymap.ksc",&s,xxstring);
13676     } else {
13677 #endif /* NOSETKEY */
13678         switch (xx) {
13679           case XSCMD:                   /* SAVE COMMAND.. */
13680             if ((y = cmkey(cmdtrmopt, ncmdtrmopt, "What to save",
13681 #ifdef OS2
13682                            "scrollback",
13683 #else
13684                            "history",
13685 #endif /* OS2 */
13686                            xxstring)) < 0)
13687               return(y);
13688             break;
13689 #ifdef OS2
13690 #ifndef NOLOCAL
13691           case XSTERM:                  /* SAVE TERMINAL.. */
13692             if ((y = cmkey(trmtrmopt,1,
13693                            "What to save","scrollback",xxstring)) < 0)
13694               return(y);
13695             break;
13696 #endif /* NOLOCAL */
13697 #endif /* OS2 */
13698         }
13699         z = cmofi("Filename",
13700                   ((y == SV_SCRL) ? "scrollbk.txt" : "history.txt"),
13701                   &s,
13702                   xxstring
13703                   );
13704 #ifndef NOSETKEY
13705     }
13706 #endif /* NOSETKEY */
13707     if (z < 0)                          /* Check output-file parse results */
13708       return(z);
13709     if (z == 2) {
13710         printf("?Sorry, %s is a directory name\n",s);
13711         return(-9);
13712     }
13713 #ifdef ZFNQFP
13714     if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {/* Convert to full pathname */
13715         if (fnp->fpath)
13716           if ((int) strlen(fnp->fpath) > 0)
13717             s = fnp->fpath;
13718     }
13719 #endif /* ZFNQFP */
13720 
13721     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of pathname */
13722     s = line;
13723 #ifdef MAC
13724     z = 0;
13725 #else
13726     /* Get NEW/APPEND disposition */
13727     if ((z = cmkey(disptb,2,"Disposition","new",xxstring)) < 0)
13728       return(z);
13729 #endif /* MAC */
13730     disp = z;
13731     if ((x = cmcfm()) < 0)              /* Get confirmation */
13732       return(x);
13733 
13734     switch (xx) {                       /* Do action.. */
13735 #ifndef NOSETKEY
13736       case XSKEY:                       /* SAVE KEYMAP */
13737         return (savkeys(s,disp));
13738 #endif /* NOSETKEY */
13739 
13740       case XSCMD:                       /* SAVE COMMAND.. */
13741 #ifdef OS2
13742 #ifndef NOLOCAL
13743         if (y == SV_SCRL)               /* .. SCROLLBACK */
13744           return(success = savscrbk(VCMD,s,disp));
13745 #endif /* NOLOCAL */
13746 #endif /* OS2 */
13747 #ifndef NORECALL
13748         if (y == SV_HIST)               /* .. HISTORY */
13749           return(success = savhistory(s,disp));
13750 #endif /* NORECALL */
13751         break;
13752 
13753 #ifdef OS2
13754 #ifndef NOLOCAL
13755       case XSTERM:                      /* SAVE TERMINAL SCROLLBACK */
13756         return(success = savscrbk(VTERM,s,disp));
13757 #endif /* NOLOCAL */
13758 #endif /* OS2 */
13759     }
13760     success = 0;
13761     return(-2);
13762 }
13763 
13764 /*
13765   R E A D T E X T
13766 
13767   Read text with a custom prompt into given buffer using command parser but
13768   with no echoing or entry into recall buffer.
13769 */
13770 int
readtext(prmpt,buffer,bufsiz)13771 readtext(prmpt, buffer, bufsiz) char * prmpt; char * buffer; int bufsiz; {
13772 #ifdef CK_RECALL
13773     extern int on_recall;               /* Around Password prompting */
13774 #endif /* CK_RECALL */
13775     int rc;
13776 #ifndef NOLOCAL
13777 #ifdef OS2
13778     extern BYTE vmode;
13779     extern int startflags;
13780     int vmode_sav = vmode;
13781 
13782     if (!prmpt) prmpt = "";
13783 
13784     if (win95_popup && !(startflags & 96)
13785 #ifdef IKSD
13786          && !inserver
13787 #endif /* IKSD */
13788          )
13789       return(popup_readtext(vmode,NULL,prmpt,buffer,bufsiz,0));
13790 
13791     if (vmode == VTERM) {
13792         vmode = VCMD;
13793         VscrnIsDirty(VTERM);
13794         VscrnIsDirty(VCMD);
13795     }
13796 #endif /* OS2 */
13797 #endif /* NOLOCAL */
13798 
13799 #ifdef CK_RECALL
13800     on_recall = 0;
13801 #endif /* CK_RECALL */
13802     cmsavp(psave,PROMPTL);              /* Save old prompt */
13803     cmsetp(prmpt);                      /* Make new prompt */
13804     concb((char)escape);                /* Put console in cbreak mode */
13805     cmini(1);                           /* and echo mode */
13806     if (pflag) prompt(xxstring);        /* Issue prompt if at top level */
13807     cmres();                            /* Reset the parser */
13808     for (rc = -1; rc < 0; ) {           /* Prompt till they answer */
13809         rc = cmtxt("","",&s,NULL);      /* Get a literal line of text */
13810         cmres();                        /* Reset the parser again */
13811     }
13812     ckstrncpy(buffer,s,bufsiz);
13813     cmsetp(psave);                      /* Restore original prompt */
13814 
13815 #ifndef NOLOCAL
13816 #ifdef OS2
13817     if (vmode != vmode_sav) {
13818         vmode = VTERM;
13819         VscrnIsDirty(VCMD);
13820         VscrnIsDirty(VTERM);
13821     }
13822 #endif /* OS2 */
13823 #endif /* NOLOCAL */
13824     return(0);
13825 }
13826 #endif /* NOICP */
13827 
13828 /* A general function to allow a Password or other information  */
13829 /* to be read from the command prompt without it going into     */
13830 /* the recall buffer or being echo'd.                           */
13831 
13832 int
readpass(prmpt,buffer,bufsiz)13833 readpass(prmpt, buffer, bufsiz) char * prmpt; char * buffer; int bufsiz; {
13834     int x;
13835 #ifdef NOICP
13836     if (!prmpt) prmpt = "";
13837     printf("%s", prmpt);
13838 #ifdef COMMENT
13839     /* Some linkers won't allow this because it's unsafe */
13840     gets(buffer);
13841 #else  /* COMMENT */
13842     {
13843         int c, i; char * p;
13844         p = buffer;
13845         for (i = 0; i < bufsiz-1; i++) {
13846             if ((c = getchar()) == EOF)
13847               break;
13848             if (c < SP)
13849               break;
13850             buffer[i] = c;
13851         }
13852         buffer[i] = NUL;
13853     }
13854 #endif /* COMMENT */
13855     return(1);
13856 #else  /* NOICP */
13857 #ifdef CK_RECALL
13858     extern int on_recall;               /* around Password prompting */
13859 #endif /* CK_RECALL */
13860     int rc;
13861 #ifndef NOLOCAL
13862 #ifdef OS2
13863     extern BYTE vmode;
13864     extern int startflags;
13865     int vmode_sav = vmode;
13866 #endif /* OS2 */
13867 #endif /* NOLOCAL */
13868 #ifdef CKSYSLOG
13869     int savlog;
13870 #endif /* CKSYSLOG */
13871     if (!prmpt) prmpt = "";
13872 #ifndef NOLOCAL
13873     debok = 0;                          /* Don't log */
13874 #ifdef OS2
13875     if (win95_popup && !(startflags & 96)
13876 #ifdef IKSD
13877          && !inserver
13878 #endif /* IKSD */
13879          ) {
13880         x = popup_readpass(vmode,NULL,prmpt,buffer,bufsiz,0);
13881         debok = 1;
13882         return(x);
13883     }
13884 #endif /* OS2 */
13885 #endif /* NOLOCAL */
13886 
13887 #ifdef CKSYSLOG
13888     savlog = ckxsyslog;                 /* Save and turn off syslogging */
13889     ckxsyslog = 0;
13890 #endif /* CKSYSLOG */
13891 #ifndef NOLOCAL
13892 #ifdef OS2
13893     if (vmode == VTERM) {
13894         vmode = VCMD;
13895         VscrnIsDirty(VTERM);
13896         VscrnIsDirty(VCMD);
13897     }
13898 #endif /* OS2 */
13899 #endif /* NOLOCAL */
13900 #ifdef CK_RECALL
13901     on_recall = 0;
13902 #endif /* CK_RECALL */
13903     cmsavp(psave,PROMPTL);              /* Save old prompt */
13904     cmsetp(prmpt);                      /* Make new prompt */
13905     concb((char)escape);                /* Put console in cbreak mode */
13906     cmini(0);                           /* and no-echo mode */
13907     if (pflag) prompt(xxstring);        /* Issue prompt if at top level */
13908     cmres();                            /* Reset the parser */
13909     for (rc = -1; rc < 0; ) {           /* Prompt till they answer */
13910         rc = cmtxt("","",&s,NULL);      /* Get a literal line of text */
13911         cmres();                        /* Reset the parser again */
13912     }
13913     ckstrncpy(buffer,s,bufsiz);
13914     printf("\r\n");                     /* Echo a CRLF */
13915     cmsetp(psave);                      /* Restore original prompt */
13916     cmini(1);                           /* Restore echo mode */
13917 #ifndef NOLOCAL
13918 #ifdef OS2
13919     if (vmode != vmode_sav) {
13920         vmode = VTERM;
13921         VscrnIsDirty(VCMD);
13922         VscrnIsDirty(VTERM);
13923     }
13924 #endif /* OS2 */
13925 #endif /* NOLOCAL */
13926 #ifdef CKSYSLOG
13927     ckxsyslog = savlog;                 /* Restore syslogging */
13928 #endif /* CKSYSLOG */
13929     debok = 1;
13930     return(0);
13931 #endif /* NOICP */
13932 }
13933 
13934 #ifndef NOICP
13935 struct keytab authtab[] = {             /* Available authentication types */
13936 #ifdef CK_KERBEROS
13937     { "k4",        AUTH_KRB4, CM_INV },
13938     { "k5",        AUTH_KRB5, CM_INV },
13939     { "kerberos4", AUTH_KRB4, 0      },
13940     { "kerberos5", AUTH_KRB5, 0      },
13941     { "krb4",      AUTH_KRB4, CM_INV },
13942     { "krb5",      AUTH_KRB5, CM_INV },
13943 #endif /* CK_KERBEROS */
13944 #ifdef NT
13945     { "ntlm",      AUTH_NTLM, 0 },
13946 #endif /* NT */
13947 #ifdef CK_SRP
13948     { "srp",       AUTH_SRP,  0 },
13949 #endif /* CK_SRP */
13950 #ifdef CK_SSL
13951     { "ssl",       AUTH_SSL,  0 },
13952 #endif /* CK_SSL */
13953     { "",          0,         0 }
13954 };
13955 int authtabn = sizeof(authtab)/sizeof(struct keytab)-1;
13956 
13957 #ifdef CK_KERBEROS
13958 struct keytab kerbtab[] = {             /* Kerberos authentication types */
13959     { "k4",        AUTH_KRB4, CM_INV },
13960     { "k5",        AUTH_KRB5, CM_INV },
13961     { "kerberos4", AUTH_KRB4, 0      },
13962     { "kerberos5", AUTH_KRB5, 0      },
13963     { "krb4",      AUTH_KRB4, CM_INV },
13964     { "krb5",      AUTH_KRB5, CM_INV }
13965 };
13966 int kerbtabn = sizeof(kerbtab)/sizeof(struct keytab);
13967 
13968 static struct keytab krb_s_tbl[] = {    /* AUTHENTICATE command switches: */
13969     { "/cache",   KRB_S_CA, CM_ARG }
13970 };
13971 static int krb_s_n = sizeof(krb_s_tbl)/sizeof(struct keytab);
13972 
13973 static struct keytab krb_v_tbl[] = {    /* KERBEROS version values: */
13974     { "4",    4, 0 },
13975     { "5",    5, 0 },                   /* (add others as needed...) */
13976     { "auto", 0, 0 }                    /* Note: 0 = auto */
13977 };
13978 static int krb_v_n = sizeof(krb_v_tbl)/sizeof(struct keytab);
13979 
13980 static struct keytab krb_a_tbl[] = {    /* KERBEROS actions: */
13981     { "destroy",           KRB_A_DE, 0 },
13982     { "initialize",        KRB_A_IN, 0 },
13983     { "list-credentials",  KRB_A_LC, 0 }
13984 };
13985 static int krb_a_n = sizeof(krb_a_tbl)/sizeof(struct keytab);
13986 
13987 static struct keytab krb4_i_tbl[] = {   /* KERBEROS 4 INITIALIZE switches: */
13988     { "/brief",            KRB_I_BR, 0 },      /* /BRIEF       */
13989     { "/instance",         KRB_I_IN, CM_ARG }, /* /INSTANCE:   */
13990     { "/lifetime",         KRB_I_LF, CM_ARG }, /* /LIFETIME:   */
13991     { "/not-preauth",      KRB_I_NPA, 0 },     /* /NOT-PREAUTH */
13992     { "/password",         KRB_I_PW, CM_ARG }, /* /PASSWORD:   */
13993 #ifdef OS2
13994     { "/popup",            KRB_I_POP, 0 },     /* /POPUP       */
13995 #endif /* OS2 */
13996     { "/preauth",          KRB_I_PA, 0 },      /* /PREAUTH     */
13997     { "/realm",            KRB_I_RL, CM_ARG }, /* /REALM:      */
13998     { "/verbose",          KRB_I_VB, 0 },      /* /VERBOSE     */
13999     { "", 0, 0 }
14000 };
14001 static int krb4_i_n = sizeof(krb4_i_tbl)/sizeof(struct keytab) - 1;
14002 
14003 static struct keytab krb5_i_tbl[] = {   /* KERBEROS 5 INITIALIZE switches: */
14004     { "/addresses",        KRB_I_ADR, CM_ARG },
14005     { "/forwardable",      KRB_I_FW,  0 },         /* /FORWARDABLE */
14006     { "/instance",         KRB_I_IN, CM_ARG }, /* /INSTANCE:   */
14007     { "/k4",               KRB_I_K4,  CM_INV }, /* /KERBEROS4   */
14008     { "/kerberos4",        KRB_I_K4,  0 },      /* /KERBEROS4   */
14009     { "/krb4",             KRB_I_K4,  CM_INV }, /* /KERBEROS4   */
14010     { "/lifetime",         KRB_I_LF,  CM_ARG }, /* /LIFETIME:   */
14011     { "/no-addresses",     KRB_I_NAD, 0 },      /* /NO-ADDRESSES */
14012     { "/no-k4",            KRB_I_NK4, CM_INV },/* /NO-KERBEROS4 */
14013     { "/no-kerberos4",     KRB_I_NK4, 0 },     /* /NO-KERBEROS4 */
14014     { "/no-krb4",          KRB_I_NK4, CM_INV },/* /NO-KERBEROS4 */
14015     { "/not-forwardable",  KRB_I_NFW, 0 },         /* /NOT-FORWARDABLE */
14016     { "/not-proxiable",    KRB_I_NPR, 0 },     /* /NOT-PROXIABLE   */
14017     { "/password",         KRB_I_PW,  CM_ARG }, /* /PASSWORD:   */
14018 #ifdef OS2
14019     { "/popup",            KRB_I_POP, 0 },     /* /POPUP       */
14020 #endif /* OS2 */
14021     { "/postdate",         KRB_I_PD, CM_ARG }, /* /POSTDATE:   */
14022     { "/pr",               KRB_I_PR, CM_INV|CM_ABR }, /* to allow for */
14023     { "/pro",              KRB_I_PR, CM_INV|CM_ABR }, /* different spellings */
14024     { "/prox",             KRB_I_PR, CM_INV|CM_ABR },
14025     { "/proxiable",        KRB_I_PR, 0 },      /* /PROXIABLE   */
14026     { "/proxyable",        KRB_I_PR, CM_INV }, /* /PROXYABLE   */
14027     { "/realm",            KRB_I_RL, CM_ARG }, /* /REALM:      */
14028     { "/renew",            KRB_I_RN, 0 },          /* /RENEW       */
14029     { "/renewable",        KRB_I_RB, CM_ARG }, /* /RENEWABLE:  */
14030     { "/service",          KRB_I_SR, CM_ARG }, /* /SERVICE:    */
14031     { "/validate",         KRB_I_VA, 0 },          /* /VALIDATE    */
14032     { "", 0, 0 }
14033 };
14034 static int krb5_i_n = sizeof(krb5_i_tbl)/sizeof(struct keytab) - 1;
14035 
14036 static struct keytab klctab[] = {       /* List Credentials switches*/
14037     { "/addresses",  XYKLCAD, 0 },
14038     { "/encryption", XYKLCEN, 0 },
14039     { "/flags",      XYKLCFL, 0 }
14040 };
14041 static int nklctab = sizeof(klctab)/sizeof(struct keytab);
14042 
14043 extern int krb_action;
14044 extern struct krb_op_data krb_op;
14045 
14046 extern struct krb5_list_cred_data krb5_lc;
14047 extern struct krb5_init_data krb5_init;
14048 extern char * krb5_d_principal;         /* Default principal */
14049 extern char * krb5_d_instance;
14050 extern char * krb5_d_realm;             /* Default realm */
14051 extern char * krb5_d_cc;                /* Default credentials cache */
14052 extern char * krb5_d_srv;               /* Default service name */
14053 extern int    krb5_d_lifetime;          /* Default lifetime */
14054 extern int    krb5_d_forwardable;
14055 extern int    krb5_d_proxiable;
14056 extern int    krb5_d_renewable;
14057 extern int    krb5_autoget;
14058 extern int    krb5_autodel;
14059 extern int    krb5_d_getk4;
14060 extern int    krb5_d_no_addresses;
14061 extern int    krb5_checkaddrs;
14062 extern char * krb5_d_addrs[];
14063 extern char * k5_keytab;                /* Keytab file */
14064 
14065 extern struct krb4_init_data krb4_init;
14066 extern char * krb4_d_principal;         /* Default principal */
14067 extern char * krb4_d_realm;             /* Default realm */
14068 extern char * krb4_d_srv;               /* Default service name */
14069 extern int    krb4_d_lifetime;          /* Default lifetime */
14070 extern int    krb4_d_preauth;
14071 extern char * krb4_d_instance;
14072 extern int    krb4_autoget;
14073 extern int    krb4_autodel;
14074 extern int    krb4_checkaddrs;
14075 extern char * k4_keytab;                /* Keytab file */
14076 #endif /* CK_KERBEROS */
14077 
14078 #ifndef NOSHOW
14079 int
sho_iks()14080 sho_iks() {
14081 #ifdef IKSDCONF
14082 #ifdef CK_LOGIN
14083     extern int ckxsyslog, ckxwtmp, ckxanon;
14084 #ifdef UNIX
14085     extern int ckxpriv;
14086 #endif /* UNIX */
14087 #ifdef CK_PERMS
14088     extern int ckxperms;
14089 #endif /* CK_PERMS */
14090     extern char * anonfile, * userfile, * anonroot;
14091 #ifdef OS2
14092     extern char * anonacct;
14093 #endif /* OS2 */
14094 #ifdef NT
14095     extern char * iks_domain;
14096 #endif /* NT */
14097 #endif /* CK_LOGIN */
14098 #ifdef CKWTMP
14099     extern char * wtmpfile;
14100 #endif /* CKWTMP */
14101 #ifdef IKSDB
14102     extern char * dbfile;
14103     extern int dbenabled;
14104 #endif /* IKSDB */
14105 #ifdef CK_LOGIN
14106     extern int logintimo;
14107 #endif /* CK_LOGIN */
14108     extern int srvcdmsg, success, iksdcf, noinit, arg_x;
14109     extern char * cdmsgfile[], * cdmsgstr, *kermrc;
14110     char * bannerfile = NULL;
14111     char * helpfile = NULL;
14112     extern int xferlog;
14113     extern char * xferfile;
14114     int i;
14115 
14116     if (isguest) {
14117         printf("?Command disabled\r\n");
14118         return(success = 0);
14119     }
14120 
14121     printf("IKS Settings\r\n");
14122 #ifdef CK_LOGIN
14123 #ifdef OS2
14124     printf("  Anonymous Account:   %s\r\n",anonacct?anonacct:"<none>");
14125 #endif /* OS2 */
14126     printf("  Anonymous Initfile:  %s\r\n",anonfile?anonfile:"<none>");
14127     printf("  Anonymous Login:     %d\r\n",ckxanon);
14128     printf("  Anonymous Root:      %s\r\n",anonroot?anonroot:"<none>");
14129 #endif /* CK_LOGIN */
14130     printf("  Bannerfile:          %s\r\n",bannerfile?bannerfile:"<none>");
14131     printf("  CDfile:              %s\r\n",cdmsgfile[0]?cdmsgfile[0]:"<none>");
14132     for ( i=1;i<16 && cdmsgfile[i];i++ )
14133         printf("  CDfile:              %s\r\n",cdmsgfile[i]);
14134     printf("  CDMessage:           %d\r\n",srvcdmsg);
14135 #ifdef IKSDB
14136     printf("  DBfile:              %s\r\n",dbfile?dbfile:"<none>");
14137     printf("  DBenabled:           %d\r\n",dbenabled);
14138 #endif /* IKSDB */
14139 #ifdef CK_LOGIN
14140 #ifdef NT
14141     printf("  Default-domain:      %s\r\n",iks_domain?iks_domain:".");
14142 #endif /* NT */
14143 #endif /* CK_LOGIN */
14144     printf("  Helpfile:            %s\r\n",helpfile?helpfile:"<none>");
14145     printf("  Initfile:            %s\r\n",kermrc?kermrc:"<none>");
14146     printf("  No-Initfile:         %d\r\n",noinit);
14147 #ifdef CK_LOGIN
14148 #ifdef CK_PERM
14149     printf("  Permission code:     %0d\r\n",ckxperms);
14150 #endif /* CK_PERM */
14151 #ifdef UNIX
14152     printf("  Privileged Login:    %d\r\n",ckxpriv);
14153 #endif /* UNIX */
14154 #endif /* CK_LOGIN */
14155     printf("  Server-only:         %d\r\n",arg_x);
14156     printf("  Syslog:              %d\r\n",ckxsyslog);
14157     printf("  Timeout (seconds):   %d\r\n",logintimo);
14158     printf("  Userfile:            %s\r\n",userfile?userfile:"<none>");
14159 #ifdef CK_LOGIN
14160 #ifdef CKWTMP
14161     printf("  Wtmplog:             %d\r\n",ckxwtmp);
14162     printf("  Wtmpfile:            %s\r\n",wtmpfile?wtmpfile:"<none>");
14163 #endif /* CKWTMP */
14164 #endif /* CK_LOGIN */
14165     printf("  Xferfile:            %s\r\n",xferfile?xferfile:"<none>");
14166     printf("  Xferlog:             %d\r\n",xferlog);
14167 #else /* IKSDCONF */
14168     printf("?Nothing to show.\r\n");
14169 #endif /* IKSDCONF */
14170     return(success = 1);
14171 }
14172 
14173 #ifdef CK_AUTHENTICATION
14174 int
sho_auth(cx)14175 sho_auth(cx) int cx; {
14176     extern int auth_type_user[], cmd_rows;
14177     int i;
14178     char * p;
14179     int kv = 0, all = 0, n = 0;
14180 
14181 #ifdef IKSD
14182     if (inserver && isguest) {
14183         printf("?Sorry, command disabled.\r\n");
14184         return(success = 0);
14185     }
14186 #endif /* IKSD */
14187     if (cx) {
14188         kv = cx;
14189     } else if (auth_type_user[0] != AUTHTYPE_AUTO) {
14190         kv = auth_type_user[0];
14191     } else {
14192         all = 1;
14193         kv = AUTHTYPE_KERBEROS_V4;
14194     }
14195     while (kv) {
14196         switch (kv) {
14197           case AUTHTYPE_KERBEROS_V4:
14198             kv = all ? AUTHTYPE_KERBEROS_V5 : 0;
14199             if (ck_krb4_is_installed()) {
14200                 printf(" Authentication:      Kerberos 4\n");
14201                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14202             } else {
14203                 printf(" Authentication:      Kerberos 4 (not installed)\n");
14204                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14205                 continue;
14206             }
14207 #ifdef CK_KERBEROS
14208             printf(" Keytab file:         %s\n",
14209                       k4_keytab ? k4_keytab : "(none)");
14210             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14211             if (krb_action < 0) {
14212                 p = "(none)";
14213             } else {
14214                 for (p = "", i = 0; i < krb_a_n; i++) {
14215                     if (krb_action == krb_a_tbl[i].kwval) {
14216                         p = krb_a_tbl[i].kwd;
14217                         break;
14218                     }
14219                 }
14220             }
14221             printf(" Action:              %s\n", p);
14222             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14223             printf(" Default lifetime     %d\n",krb4_d_lifetime);
14224             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14225             printf(" Lifetime:            %d (minutes)\n",krb4_init.lifetime);
14226             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14227             printf(" Default preauth:     %d\n",krb4_d_preauth);
14228             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14229             printf(" Preauth:             %d\n",krb4_init.preauth);
14230             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14231             printf(" Default principal:   \"%s\"\n",
14232                     krb4_d_principal ? krb4_d_principal : "");
14233             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14234             printf(" Principal:           \"%s\"\n",
14235                     krb4_init.principal ? krb4_init.principal : "");
14236             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14237             printf(" Default realm:       \"%s\"\n",
14238                     krb4_d_realm ? krb4_d_realm : "");
14239             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14240             printf(" Realm:               \"%s\"\n",
14241                     krb4_init.realm ? krb4_init.realm : "");
14242             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14243             printf(" Default instance:    \"%s\"\n",
14244                     krb4_d_instance ? krb4_d_instance : "");
14245             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14246             printf(" Instance:            \"%s\"\n",
14247                     krb4_init.instance ? krb4_init.instance : "");
14248             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14249             printf(" Auto-Get TGTs:       %d\n",krb4_autoget);
14250             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14251             printf(" Auto-Destroy TGTs:   %s\n",
14252                     krb4_autodel==KRB_DEL_NO?"never":
14253                     krb4_autodel==KRB_DEL_CL?"on-close":"on-exit");
14254             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14255             printf(" Check IP Addresses:  %d\n",krb4_checkaddrs);
14256             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14257 #ifdef COMMENT
14258             printf(" Password:    \"%s\"\n",
14259                     krb4_init.password  ? krb4_init.password  : "");
14260             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14261 #endif /* COMMENT */
14262 #endif /* CK_KERBEROS */
14263             printf("\n");
14264             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14265             break;
14266         case AUTHTYPE_KERBEROS_V5:
14267             kv = all ? AUTHTYPE_SSL : 0;
14268             if (ck_krb5_is_installed()) {
14269                 if (ck_gssapi_is_installed())
14270                     printf(" Authentication:      Kerberos 5 plus GSSAPI\n");
14271                 else
14272                     printf(" Authentication:      Kerberos 5\n");
14273                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14274             } else {
14275                 printf(" Authentication:      Kerberos 5 (not installed)\n");
14276                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14277                 continue;
14278             }
14279 
14280 #ifdef CK_KERBEROS
14281             printf(" Cache file:          %s\n",
14282                     krb_op.cache ? krb_op.cache : "(none)");
14283             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14284             printf(" Default cache:       %s\n",
14285                     krb5_d_cc ? krb5_d_cc : "(none)");
14286             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14287             printf(" Keytab file:         %s\n",
14288                       k5_keytab ? k5_keytab : "(none)");
14289             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14290             if (krb_action < 0) {
14291                 p = "(none)";
14292             } else  {
14293                 for (p = "", i = 0; i < krb_a_n; i++) {
14294                     if (krb_action == krb_a_tbl[i].kwval) {
14295                         p = krb_a_tbl[i].kwd;
14296                         break;
14297                     }
14298                 }
14299             }
14300             printf(" Action:              %s\n", p);
14301             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14302 
14303             printf(" Default forwardable  %d\n",krb5_d_forwardable);
14304             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14305             printf(" Forwardable:         %d\n",krb5_init.forwardable);
14306             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14307             printf(" Default lifetime     %d\n",krb5_d_lifetime);
14308             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14309             printf(" Lifetime:            %d (minutes)\n",krb5_init.lifetime);
14310             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14311             printf(" Postdate:            \"%s\"\n",
14312                     krb5_init.postdate ? krb5_init.postdate: "");
14313             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14314             printf(" Default proxiable:   %d\n",krb5_d_proxiable);
14315             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14316             printf(" Proxiable:           %d\n",krb5_init.proxiable);
14317             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14318             printf(" Renew:               %d\n",krb5_init.renew);
14319             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14320             printf(" Default renewable:   %d (minutes)\n",krb5_d_renewable);
14321             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14322             printf(" Renewable:           %d (minutes)\n",krb5_init.renewable);
14323             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14324             printf(" Service:             \"%s\"\n",
14325                     krb5_init.service ? krb5_init.service : "");
14326             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14327             printf(" Validate:            %d\n",krb5_init.validate);
14328             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14329             printf(" Default principal:   \"%s\"\n",
14330                     krb5_d_principal ? krb5_d_principal : "");
14331             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14332             printf(" Principal:           \"%s\"\n",
14333                     krb5_init.principal ? krb5_init.principal : "");
14334             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14335             printf(" Default instance:    \"%s\"\n",
14336                     krb5_d_instance ? krb5_d_instance : "");
14337             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14338             printf(" Default realm:       \"%s\"\n",
14339                     krb5_d_realm ? krb5_d_realm : "");
14340             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14341             printf(" Realm:               \"%s\"\n",
14342                     krb5_init.realm ? krb5_init.realm : "");
14343             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14344             printf(" Auto-Get TGTs:       %d\n",krb5_autoget);
14345             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14346             printf(" Auto-Destroy TGTs:   %s\n",
14347                     krb5_autodel==KRB_DEL_NO?"never":
14348                     krb5_autodel==KRB_DEL_CL?"on-close":"on-exit");
14349             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14350             printf(" Default get K4 TGTs: %d\n",krb5_d_getk4);
14351             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14352             printf(" Get K4 TGTs: %d\n",krb5_init.getk4);
14353             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14354             printf(" Check IP Addresses:  %d\n",krb5_checkaddrs);
14355             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14356             printf(" No IP Addresses:  %d\n",krb5_d_no_addresses);
14357             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14358             printf(" IP-Addresses:        ");
14359             if (krb5_init.addrs && krb5_init.addrs[0]) {
14360                 for (i = 0; krb5_init.addrs[i]; i++) {
14361                     if (i)
14362                       printf(",");
14363                     printf("%s",krb5_init.addrs[i]);
14364                 }
14365             } else if (krb5_d_addrs[0]) {
14366                 for (i = 0;i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];i++) {
14367                     if (i)
14368                       printf(",");
14369                     printf("%s",krb5_d_addrs[i]);
14370                 }
14371             } else {
14372                 printf("(use default)");
14373             }
14374             printf("\n");
14375             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14376 #ifdef COMMENT
14377             printf(" Password:            \"%s\"\n",
14378                     krb5_init.password  ? krb5_init.password  : "");
14379             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14380 #endif /* COMMENT */
14381 #endif /* CK_KERBEROS */
14382             printf("\n");
14383             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14384             break;
14385 #ifdef CK_SSL
14386           case AUTHTYPE_SSL:
14387             kv = all ? AUTHTYPE_SRP : 0;
14388             if (ck_ssleay_is_installed()) {
14389                 printf(" Authentication:      SSL/TLS (%s)\n",
14390                         SSLeay_version(SSLEAY_VERSION));
14391                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14392             } else {
14393                 printf(" Authentication:      SSL/TLS (not installed)\n");
14394                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14395                 continue;
14396             }
14397             printf(" RSA Certs file: %s\n",ssl_rsa_cert_file?
14398                   ssl_rsa_cert_file:"(none)");
14399             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14400             printf(" RSA Certs Chain file: %s\n",ssl_rsa_cert_chain_file?
14401                   ssl_rsa_cert_chain_file:"(none)");
14402             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14403             printf(" RSA Key file: %s\n",ssl_rsa_key_file?
14404                   ssl_rsa_key_file:"(none)");
14405             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14406             printf(" DSA Certs file: %s\n",ssl_dsa_cert_file?
14407                   ssl_dsa_cert_file:"(none)");
14408             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14409             printf(" DSA Certs Chain file: %s\n",ssl_dsa_cert_chain_file?
14410                   ssl_dsa_cert_chain_file:"(none)");
14411             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14412             printf(" DH Key file: %s\n",ssl_dh_key_file?
14413                   ssl_dh_key_file:"(none)");
14414             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14415             printf(" DH Param file: %s\n",ssl_dh_param_file?
14416                   ssl_dh_param_file:"(none)");
14417             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14418             printf(" CRL file: %s\n",ssl_crl_file?
14419                   ssl_crl_file:"(none)");
14420             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14421             printf(" CRL dir: %s\n",ssl_crl_dir?
14422                     ssl_crl_dir:"(none)");
14423             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14424             printf(" Random file: %s\n",ssl_rnd_file?
14425                   ssl_rnd_file:"(none)");
14426             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14427             printf(" Verify file: %s\n",ssl_verify_file?
14428                   ssl_verify_file:"(none)");
14429             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14430             printf(" Verify dir: %s\n",ssl_verify_dir?
14431                   ssl_verify_dir:"(none)");
14432             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14433             printf(" Cipher list: %s\n",ssl_cipher_list ? ssl_cipher_list :
14434 		    DEFAULT_CIPHER_LIST);
14435             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14436             if (ssl_con == NULL) {
14437                 SSL_library_init();
14438                 ssl_ctx = (SSL_CTX *)
14439 /* old...         SSL_CTX_new((SSL_METHOD *)TLSv1_method());  new below: */
14440                   SSL_CTX_new((SSL_METHOD *)SSLv23_method());
14441                 if (ssl_ctx != NULL)
14442                   ssl_con= (SSL *) SSL_new(ssl_ctx);
14443             }
14444             if (ssl_con != NULL) {
14445                 CHAR * p = NULL;
14446                 int i;
14447 
14448                 for (i = 0; ; i++) {
14449                     p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
14450                     if (p == NULL)
14451                       break;
14452                     printf("    %s\n",p);
14453                     if (++n > cmd_rows - 3)
14454                         if (!askmore()) return(0); else n = 0;
14455                 }
14456             }
14457             printf(" Certs OK? %s\n",ssl_certsok_flag? "yes" : "no");
14458             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14459             printf(" Debug mode: %s\n", ssl_debug_flag ? "on" : "off");
14460             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14461             printf(" Verbose mode: %s\n", ssl_verbose_flag ? "on" : "off");
14462             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14463             printf(" Verify mode: %s\n",
14464                     ssl_verify_flag == SSL_VERIFY_NONE ? "none" :
14465                     ssl_verify_flag == SSL_VERIFY_PEER ? "peer-cert" :
14466                     "fail-if-no-peer-cert");
14467             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14468             printf(" SSL only? %s\n", ssl_only_flag ? "yes" : "no");
14469             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14470             printf(" TLS only? %s\n", tls_only_flag ? "yes" : "no");
14471             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14472 #endif /* CK_SSL */
14473             break;
14474           case AUTHTYPE_NTLM:
14475             kv = 0;
14476             if (ck_ntlm_is_installed()) {
14477                 printf(" Authentication:      NTLM\n");
14478                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14479                 printf(" No options\n");
14480                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14481             } else {
14482                 printf(" Authentication:      NTLM (not installed)\n");
14483                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14484                 continue;
14485             }
14486             printf("\n");
14487             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14488             break;
14489           case AUTHTYPE_SRP:
14490             kv = all ? AUTHTYPE_NTLM : 0;
14491             if (ck_srp_is_installed()) {
14492                 if (ck_krypto_is_installed())
14493                     printf(" Authentication:      SRP plus Krypto API\n");
14494                 else
14495                     printf(" Authentication:      SRP\n");
14496                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14497                 printf(" No options\n");
14498                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14499             } else {
14500                 printf(" Authentication:      SRP (not installed)\n");
14501                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14502                 continue;
14503             }
14504             printf("\n");
14505             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
14506             break;
14507         }
14508     }
14509     return(success = 1);
14510 }
14511 #endif /* CK_AUTHENTICATION */
14512 #endif /* NOSHOW */
14513 
14514 #ifdef CK_KERBEROS
14515 
14516 /*  C P _ A U T H  --  AUTHENTICATE command parsing  */
14517 
14518 int
cp_auth()14519 cp_auth() {                             /* Command_Parse AUTHENTICATE */
14520     int c, i, n;                        /* Workers */
14521     int rc = 0;                         /* Return code */
14522     int getval;                         /* Parsing helpers */
14523     int tmpauth = 0;                    /* Temporary authentication type */
14524     int kv = 0;                         /* Temporary Kerberos version */
14525     int tmp_action = -1;                /* Temporary Kerberos action */
14526     int tmp_klc = 0;                    /* Temporary list-credentials */
14527     char tmphlp[256];                   /* For building help message */
14528     char * p;
14529     char * tmppswd  = NULL;             /* Password */
14530     char * tmpprinz = NULL;             /* Principal */
14531     char * tmprealm = NULL;             /* Realm */
14532     char * tmpcache = NULL;             /* Cache file */
14533     char * tmpinst  = NULL;             /* K4 Instance */
14534     char * tmpaddrs[KRB5_NUM_OF_ADDRS];
14535 #ifdef CK_RECALL
14536     extern int on_recall;               /* around Password prompting */
14537 #endif /* CK_RECALL */
14538     struct stringint pv[KRB_I_MAX+1];   /* Temporary array for switch values */
14539     struct FDB kw, sw, fl;              /* FDBs for each parse function */
14540 
14541     krb_action = -1;                    /* Initialize Kerberos action. */
14542     tmp_action = -1;                    /* And our local copy. */
14543     for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
14544       tmpaddrs[i] = NULL;
14545 
14546     if ((y = cmkey(kerbtab,kerbtabn,"authentication type","",xxstring)) < 0)
14547       {
14548           if (y == -3)
14549             printf("?Authentication type not specified - nothing happens\n");
14550           return(y);
14551       }
14552     tmpauth = y;
14553     debug(F101,"kerberos authentication","",tmpauth);
14554     switch (tmpauth) {
14555       case AUTH_KRB4: kv = 4; break;    /* Don't assume values are the same */
14556       case AUTH_KRB5: kv = 5; break;
14557       default:
14558         printf("?Authentication type not supported: \"%s\"\n",atmbuf);
14559         return(-9);
14560     }
14561 
14562     /* From here down is Kerberos */
14563     ini_kerb();                         /* Reset Init data to defaults */
14564 
14565     if (kv == 4) {                      /* Set K4 defaults */
14566         if (krb4_d_realm)
14567           makestr(&tmprealm,krb4_d_realm);
14568         if (krb4_d_principal)
14569           makestr(&tmpprinz,krb4_d_principal);
14570         if (krb4_d_instance)
14571           makestr(&tmpinst,krb4_d_instance);
14572     } else if (kv == 5) {               /* Set K5 defaults */
14573         if (krb5_d_cc)
14574           makestr(&tmpcache,krb5_d_cc);
14575         if (krb5_d_realm)
14576           makestr(&tmprealm,krb5_d_realm);
14577         if (krb5_d_principal)
14578           makestr(&tmpprinz,krb5_d_principal);
14579         if (krb5_d_instance)
14580           makestr(&tmpinst,krb5_d_instance);
14581     }
14582     for (i = 0; i <= KRB_I_MAX; i++) {  /* Initialize switch values */
14583         pv[i].sval = NULL;              /* to null pointers */
14584         pv[i].ival = 0;                 /* and 0 int values */
14585         pv[i].wval = (CK_OFF_T)-1;	/* and -1 wide values */
14586     }
14587     if (kv == 4) {                      /* Kerberos 4 */
14588         pv[KRB_I_LF].ival = krb4_d_lifetime;
14589         pv[KRB_I_PA].ival = krb4_d_preauth;
14590 
14591         if ((n = cmkey(krb_a_tbl,krb_a_n,"Kerberos 4 action","",xxstring)) < 0)
14592           {
14593               if (n == -3)
14594                 printf("?Action not specified - nothing happens.\n");
14595               return(n);
14596           }
14597     } else if (kv == 5) {               /* Kerberos 5 */
14598         pv[KRB_I_FW].ival = krb5_d_forwardable;
14599         pv[KRB_I_PR].ival = krb5_d_proxiable;
14600         pv[KRB_I_LF].ival = krb5_d_lifetime;
14601         pv[KRB_I_RB].ival = krb5_d_renewable;
14602         pv[KRB_I_K4].ival = krb5_d_getk4;
14603         pv[KRB_I_NAD].ival = krb5_d_no_addresses;
14604 
14605         /* Make help message that shows switches and action keywords */
14606         ckstrncpy(tmphlp,"Kerberos 5 action, one of the following:\n ",256);
14607         for (i = 0; i < krb_a_n; i++) {
14608             ckstrncat(tmphlp,krb_a_tbl[i].kwd,sizeof(tmphlp));
14609             if (i == krb_a_n - 1)
14610               ckstrncat(tmphlp,"\nor switch",sizeof(tmphlp));
14611             else
14612               ckstrncat(tmphlp,"   ",sizeof(tmphlp));
14613         }
14614         /* Set up first set of chained FDB's */
14615 
14616         cmfdbi(&sw,                     /* First FDB - command switches */
14617                _CMKEY,                  /* fcode */
14618                tmphlp,                  /* hlpmsg */
14619                "",                      /* default (none) */
14620                "",                      /* addtl string data */
14621                krb_s_n,                 /* Switch table size */
14622                4,                       /* addtl numeric data 2: 4 = cmswi */
14623                xxstring,                /* Processing function */
14624                krb_s_tbl,               /* Switch table */
14625                &kw                      /* Pointer to next FDB */
14626                );
14627         cmfdbi(&kw,                     /* Second FDB - action keywords */
14628                _CMKEY,                  /* fcode */
14629                "Kerberos action",       /* hlpmsg */
14630                "",                      /* default (none) */
14631                "",                      /* addtl string data */
14632                krb_a_n,                 /* Switch table size */
14633                0,                       /* addtl num data (0 = NOT switch) */
14634                xxstring,                /* Processing function */
14635                krb_a_tbl,               /* Keyword table */
14636                NULL                     /* Pointer to next FDB (none) */
14637                );
14638 
14639         /* Parse */
14640 
14641         while (1) {                     /* Parse 0 or more switches */
14642             rc = cmfdb(&sw);            /* Parse something */
14643             debug(F101,"kerberos cmfdb 1 rc","",rc);
14644             if (rc < 0) {                       /* Error */
14645                 if (rc == -3)
14646                   printf("?Action not specified - nothing happens.\n");
14647                 return(rc);             /* or reparse needed */
14648             }
14649             if (cmresult.fdbaddr != &sw) /* Break out if not a switch */
14650               break;
14651             c = cmgbrk();               /* Have switch - get break character */
14652             getval = (c == ':' || c == '='); /* Must parse an agument? */
14653             if (getval && !(cmresult.kflags & CM_ARG)) {
14654                 printf("?This switch does not take arguments\n");
14655                 return(-9);             /* OK because nothing malloc'd yet */
14656             }
14657             if (!getval && (cmgkwflgs() & CM_ARG)) {
14658                 printf("?This switch requires an argument\n");
14659                 return(-9);
14660             }
14661             n = cmresult.nresult;       /* Numeric result = switch value */
14662             debug(F101,"kerberos command switch","",n);
14663 
14664             switch (n) {                /* Handle the switch */
14665               case KRB_S_CA:            /* /CACHE:<filename> */
14666                 p = krb5_d_cc ? krb5_d_cc : "";
14667                 if ((y = cmofi("Name of cache file",p,&s,xxstring)) < 0) {
14668                     if (y == -3)
14669                       s = NULL;
14670                     else
14671                       return(y);
14672                 }
14673                 makestr(&tmpcache,s);
14674                 break;
14675               default:
14676                 printf("?Unexpected switch value - internal error\n");
14677                 return(-9);             /* (if) nothing malloc'd yet. */
14678             }
14679         }
14680         if (cmresult.fdbaddr != &kw) {  /* Checking... */
14681             printf("?Unexpected result - internal error\n");
14682             return(-9);                 /* Nothing malloc'd yet. */
14683         }
14684         n = cmresult.nresult;           /* Get keyword value */
14685     } else {
14686         printf("?Unexpected Kerberos version - Internal error\n");
14687         return(-9);
14688     }
14689     debug(F101,"kerberos action","",n);
14690     switch (n) {
14691       case KRB_A_IN:                    /* INITIALIZE */
14692       case KRB_A_DE:                    /* DESTROY */
14693       case KRB_A_LC:                    /* LIST-CREDENTIALS */
14694         tmp_action = n;                 /* OK, set */
14695         break;
14696       default:                          /* Not OK, punt. */
14697         printf("?Unexpected action - internal error\n");
14698         return(-9);
14699     }
14700     if (tmp_action == KRB_A_IN) {       /* Action is INITIALIZE */
14701         int x;
14702         cmfdbi(&sw,                     /* INITIALIZE switches */
14703                _CMKEY,                  /* fcode */
14704                "Principal,\n or optional INITIALIZE switch(es)", /* hlpmsg */
14705                "",                      /* default (none) */
14706                "",                      /* addtl string data */
14707                kv == 4 ?  krb4_i_n : krb5_i_n, /* Switch table size */
14708                4,                       /* addtl numeric data 2: 4 = cmswi */
14709                xxstring,                /* Processing function */
14710                kv == 4 ?  krb4_i_tbl : krb5_i_tbl,      /* Switch table */
14711                &fl                      /* Pointer to next FDB */
14712                );
14713         cmfdbi(&fl,                     /* 3rd FDB - command to send from */
14714                _CMFLD,                  /* fcode */
14715                "Principal",             /* hlpmsg */
14716                kv == 4 ? krb4_d_principal : krb5_d_principal, /* principal */
14717                "",                      /* addtl string data */
14718                0,                       /* addtl numeric data 1 */
14719                0,                       /* addtl numeric data 2 */
14720                xxstring,
14721                NULL,
14722                NULL
14723                );
14724         while (1) {                     /* Parse INIT switches or principal */
14725             rc = cmfdb(&sw);
14726             debug(F101,"kerberos cmfdb 2 rc","",rc);
14727             if (rc < 0) {
14728                 if (rc == -3)
14729                   printf("?Principal name required\n");
14730                 goto kerbx;
14731             }
14732             debug(F101,"kerberos cmfdb 2 fcode","",cmresult.fcode);
14733             if (cmresult.fcode != _CMKEY) /* Not a switch, quit switch loop */
14734               break;
14735             c = cmgbrk();               /* Switch - get break character */
14736             debug(F101,"kerberos cmfdb 2 cmgbrk","",c);
14737             getval = (c == ':' || c == '=');
14738             if (getval && !(cmresult.kflags & CM_ARG)) {
14739                 printf("?This switch does not take arguments\n");
14740                 return(-9);             /* OK because nothing malloc'd yet */
14741             }
14742             if (!getval && (cmgkwflgs() & CM_ARG)) {
14743                 printf("?This switch requires an argument\n");
14744                 return(-9);
14745             }
14746             n = cmresult.nresult;       /* Numeric result = switch value */
14747             switch (n) {
14748               /* These don't take args... */
14749               case KRB_I_PA:            /* /PREAUTH */
14750               case KRB_I_FW:            /* /FORWARDABLE */
14751               case KRB_I_PR:            /* /PROXIABLE */
14752               case KRB_I_RN:            /* /RENEW */
14753               case KRB_I_VA:            /* /VALIDATE */
14754               case KRB_I_NPA:           /* /NOT-PREAUTH */
14755               case KRB_I_NFW:           /* /NOT-FORWARDABLE */
14756               case KRB_I_NPR:           /* /NOT-PROXIABLE */
14757               case KRB_I_VB:            /* /VERBOSE */
14758               case KRB_I_BR:            /* /BRIEF */
14759               case KRB_I_K4:            /* /KERBEROS4 */
14760               case KRB_I_NK4:           /* /NO-KERBEROS4 */
14761               case KRB_I_POP:           /* /POPUP */
14762               case KRB_I_NAD:           /* /NO-ADDRESSES */
14763                 if (getval) {
14764                     printf("?This switch does not take a value\n");
14765                     rc = -9;
14766                     goto kerbx;
14767                 }
14768                 switch (n) {
14769                   case KRB_I_NPA:
14770                     pv[KRB_I_PA].ival = 0;
14771                     break;
14772                   case KRB_I_NFW:
14773                     pv[KRB_I_FW].ival = 0;
14774                     break;
14775                   case KRB_I_NPR:
14776                     pv[KRB_I_PR].ival = 0;
14777                     break;
14778                   case KRB_I_VB:
14779                     pv[KRB_I_BR].ival = 0;
14780                     break;
14781                   case KRB_I_NK4:
14782                     pv[KRB_I_K4].ival = 0;
14783                     break;
14784                   default:
14785                     pv[n].ival = 1;
14786                 }
14787                 break;
14788 
14789                 /* These do take arguments */
14790 
14791               case KRB_I_RB:            /* /RENEWABLE:<minutes> */
14792                 pv[n].ival = 0;
14793                 if (!getval) break;
14794                 if ((rc = cmnum("Minutes",ckitoa(krb5_init.renewable),
14795                                 10,&y, xxstring)) < 0)
14796                   goto kerbx;
14797                 pv[n].ival = y;
14798                 break;
14799 
14800               case KRB_I_LF:            /* /LIFETIME:<minutes> */
14801                 pv[n].ival = 0;
14802                 /* Default is previous value */
14803                 sprintf(tmpbuf,"%d",    /* SAFE */
14804                         kv == 4 ?
14805                         krb4_init.lifetime :
14806                         krb5_init.lifetime
14807                         );
14808                 if (!getval) break;
14809                 if ((rc = cmnum("Minutes",tmpbuf,10,&y, xxstring)) < 0)
14810                   goto kerbx;
14811                 pv[n].ival = y;
14812                 break;
14813 
14814               case KRB_I_PD:            /* /POSTDATE:<timestamp> */
14815                 if (pv[n].sval) {
14816                     free(pv[n].sval);
14817                     pv[n].sval = NULL;
14818                 }
14819                 if (!getval) break;
14820                 if ((rc = cmdate("date-time","",&s,0,xxstring)) < 0)
14821                   goto kerbx;
14822                 makestr(&(pv[n].sval),s);
14823                 break;
14824 
14825               case KRB_I_SR:            /* /SERVICE:<name> */
14826                 if (pv[n].sval) {
14827                     free(pv[n].sval);
14828                     pv[n].sval = NULL;
14829                 }
14830                 if (!getval) break;
14831                 if ((rc = cmfld("Service-name","",&s,xxstring)) < 0)
14832                   goto kerbx;
14833                 makestr(&(pv[n].sval),s);
14834                 break;
14835 
14836               case KRB_I_RL:            /* /REALM:<name> */
14837                 if (pv[n].sval) {
14838                     free(pv[n].sval);
14839                     pv[n].sval = NULL;
14840                 }
14841                 if (!getval) break;
14842                 if (kv == 4)
14843                   p = krb4_d_realm ? krb4_d_realm : "";
14844                 else
14845                   p = krb5_d_realm ? krb5_d_realm : "";
14846                 if ((rc = cmfld("Realm",p,&s,xxstring)) < 0)
14847                   goto kerbx;
14848                 makestr(&(pv[n].sval),s);
14849                 break;
14850 
14851               case KRB_I_IN:            /* /INSTANCE:<name> */
14852                 if (pv[n].sval) {
14853                     free(pv[n].sval);
14854                     pv[n].sval = NULL;
14855                 }
14856                 if (!getval) break;
14857                 if (kv == 4)
14858                     p = krb4_d_instance ? krb4_d_instance : "";
14859                 else
14860                     p = krb5_d_instance ? krb5_d_instance : "";
14861                 if ((rc = cmfld("Instance",p,&s,xxstring)) < 0)
14862                   goto kerbx;
14863                 makestr(&(pv[n].sval),s);
14864                 break;
14865 
14866               case KRB_I_PW:            /* /PASSWORD:<password> */
14867                 debok = 0;
14868                 if (pv[n].sval) {
14869                     free(pv[n].sval);
14870                     pv[n].sval = NULL;
14871                 }
14872                 if (!getval) break;
14873                 if ((rc = cmfld("Password","",&s,xxstring)) < 0)
14874                   if (rc != -3)
14875                     goto kerbx;
14876                 makestr(&(pv[n].sval),s);
14877                 break;
14878 
14879               case KRB_I_ADR:           /* /ADDRESSES:{<address-list>} */
14880                 if (pv[n].sval) {
14881                     free(pv[n].sval);
14882                     pv[n].sval = NULL;
14883                 }
14884                 if (!getval) break;
14885                 if ((rc = cmfld("List of IP addresses","",&s,xxstring)) < 0)
14886                   goto kerbx;
14887                 makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
14888                 for (i = 0; i < KRB5_NUM_OF_ADDRS && tmpaddrs[i]; i++) {
14889                     if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
14890                         printf("invalid ip address: %s\n",tmpaddrs[i]);
14891                         rc = -9;
14892                         goto kerbx;
14893                     }
14894                 }
14895                 pv[KRB_I_NAD].ival = 0;
14896                 break;
14897 
14898               default:
14899                 printf("?Unexpected switch value - internal error\n");
14900                 rc = -9;
14901                 goto kerbx;
14902             }
14903         }
14904         if (cmresult.fcode != _CMFLD) {
14905             printf("?Unexected result - internal error\n");
14906             rc = -9;
14907             goto kerbx;
14908         }
14909         /* cmresult.sresult may be of the form PRINCIPAL@REALM */
14910         i = ckindex("@",cmresult.sresult,0,0,0);
14911         if (i != 0) {
14912             makestr(&tmprealm,&cmresult.sresult[i]);
14913             cmresult.sresult[i-1] = '\0';
14914         }
14915         makestr(&tmpprinz,cmresult.sresult); /* Principal (user) */
14916 
14917         if ((rc = cmcfm()) < 0) {       /* Now get confirmation */
14918             if (rc == -3) {
14919                 printf("?Principal name required\n");
14920             }
14921             goto kerbx;
14922         }
14923         if (!tmpprinz || !tmpprinz[0]) {
14924             printf("?Principal name required\n");
14925             goto kerbx;
14926         }
14927         if (!pv[KRB_I_RN].ival && !pv[KRB_I_VA].ival) {
14928             /* Don't use a password if Validating or Renewing */
14929             if (pv[KRB_I_PW].sval) {    /* If they gave a /PASSWORD switch */
14930                 makestr(&tmppswd,pv[KRB_I_PW].sval); /* use this value */
14931             }
14932 #ifdef COMMENT
14933             /* Password prompting has been moved to ck_krb[45]_initTGT() */
14934             else {                      /* Otherwise must prompt for it */
14935                 char prmpt[80];
14936                 if (pv[KRB_I_RL].sval)
14937                   sprintf(prmpt,"%s@%s's Password: ",
14938                           tmpprinz,pv[KRB_I_RL].sval);
14939                 else if (tmprealm)
14940                   sprintf(prmpt,"%s@%s's Password: ",
14941                           tmpprinz,tmprealm);
14942                 else
14943                   sprintf(prmpt,"%s's Password: ",tmpprinz);
14944 #ifdef OS2
14945                 if (pv[KRB_I_POP].ival) {
14946                     char passwd[80]="";
14947                     readpass(prmpt,passwd,80);
14948                     makestr(&tmppswd,passwd);
14949                     memset(passwd,0,80);
14950                 } else
14951 #endif /* OS2 */
14952                 {
14953 #ifdef CK_RECALL
14954                     on_recall = 0;
14955 #endif /* CK_RECALL */
14956                     cmsavp(psave,PROMPTL); /* Save old prompt */
14957                     cmsetp(prmpt);      /* Make new prompt */
14958                     concb((char)escape); /* Put console in cbreak mode */
14959                     cmini(0);           /* and no-echo mode */
14960                     /* Issue prompt if at top level */
14961                     if (pflag) prompt(xxstring);
14962                     cmres();            /* Reset the parser */
14963                     for (rc = -1; rc < 0; ) { /* Prompt till they answer */
14964                         /* Get a literal line of text */
14965                         rc = cmtxt("","",&s,NULL);
14966                         cmres();        /* Reset the parser again */
14967                     }
14968                     makestr(&tmppswd,s);
14969                     printf("\n");       /* Echo a CRLF */
14970                     cmsetp(psave);      /* Restore original prompt */
14971                 }
14972             }
14973             x = 0;                      /* Check for password */
14974             if (tmppswd)
14975               if (*tmppswd)
14976                 x = 1;
14977             if (!x) {
14978                 printf("?Password required\n");
14979                 goto kerbx;
14980             }
14981 #endif /* COMMENT */
14982         }
14983     } else if (kv == 5 && tmp_action == KRB_A_LC) { /* LIST-CREDENTIALS */
14984         tmp_klc = 0;
14985         while (1) {
14986             if ((x = cmkey(klctab,nklctab,"Switch","",xxstring)) < 0) {
14987                 if (x == -3) {
14988                     if ((rc = cmcfm()) < 0)
14989                       goto kerbx;
14990                     else
14991                       break;
14992                 } else {
14993                     rc = x;
14994                     goto kerbx;
14995                 }
14996             }
14997             tmp_klc |= x;
14998         }
14999     } else if ((rc = cmcfm()) < 0)      /* DESTROY, just confirm */
15000         goto kerbx;
15001 
15002 /* Done - Move confirmed data to final locations */
15003 
15004     krb_action = tmp_action;            /* Action requested */
15005     krb_op.version = kv;                /* Kerberos version */
15006     krb_op.cache = tmpcache;            /* Cache file */
15007     tmpcache = NULL;                    /* So we don't free it */
15008 
15009     switch (krb_action) {
15010       case KRB_A_IN:                    /* INITIALIZE */
15011         if (kv == 5) {
15012             krb5_init.forwardable = pv[KRB_I_FW].ival;
15013             krb5_init.proxiable   = pv[KRB_I_PR].ival;
15014             krb5_init.lifetime    = pv[KRB_I_LF].ival;
15015             krb5_init.renew       = pv[KRB_I_RN].ival;
15016             krb5_init.renewable   = pv[KRB_I_RB].ival;
15017             krb5_init.validate    = pv[KRB_I_VA].ival;
15018 
15019             /* Here we just reassign the pointers and then set them to NULL */
15020             /* so they won't be freed below. */
15021 
15022             krb5_init.postdate = pv[KRB_I_PD].sval; pv[KRB_I_PD].sval = NULL;
15023             krb5_init.service  = pv[KRB_I_SR].sval; pv[KRB_I_SR].sval = NULL;
15024             if (pv[KRB_I_RL].sval) {
15025                 krb5_init.realm  = pv[KRB_I_RL].sval; pv[KRB_I_RL].sval = NULL;
15026             } else if (tmprealm) {
15027                 krb5_init.realm = tmprealm; tmprealm = NULL;
15028             }
15029             if (pv[KRB_I_IN].sval) {
15030                 krb5_init.instance = pv[KRB_I_IN].sval;
15031                 pv[KRB_I_IN].sval = NULL;
15032             } else if ( tmpinst ) {
15033                 krb5_init.instance = tmpinst;
15034                 tmpinst = NULL;
15035             }
15036             if (tmpprinz) {
15037                 krb5_init.principal = tmpprinz;
15038                 tmpprinz = NULL;
15039             }
15040             krb5_init.password = tmppswd;
15041             tmppswd = NULL;
15042 
15043             krb5_init.getk4 = pv[KRB_I_K4].ival;
15044             if (krb5_init.getk4) {
15045                 krb4_init.lifetime = pv[KRB_I_LF].ival;
15046                 if (krb5_init.realm)
15047                     makestr(&krb4_init.realm,krb5_init.realm);
15048                 krb4_init.preauth  = krb4_d_preauth;
15049                 krb4_init.verbose  = pv[KRB_I_BR].ival ? 0 : 1;
15050                 if (krb5_init.principal)
15051                     makestr(&krb4_init.principal,krb5_init.principal);
15052                 if (krb5_init.principal)
15053                     makestr(&krb4_init.password,krb5_init.password);
15054             }
15055             krb5_init.no_addresses = pv[KRB_I_NAD].ival;
15056             if (tmpaddrs[0]) {
15057                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
15058                     if (krb5_init.addrs[i]) {
15059                         free(krb5_init.addrs[i]);
15060                         krb5_init.addrs[i] = NULL;
15061                     }
15062                     krb5_init.addrs[i] = tmpaddrs[i];
15063                     tmpaddrs[i] = NULL;
15064                 }
15065             }
15066         } else if (kv == 4) {           /* Same deal for Kerberos 4 */
15067             krb4_init.lifetime = pv[KRB_I_LF].ival;
15068             if (pv[KRB_I_RL].sval) {
15069                 krb4_init.realm  = pv[KRB_I_RL].sval;
15070                 pv[KRB_I_RL].sval = NULL;
15071             } else if ( tmprealm ) {
15072                 krb4_init.realm  = tmprealm;
15073                 tmprealm = NULL;
15074             }
15075             if (pv[KRB_I_IN].sval) {
15076                 krb4_init.instance = pv[KRB_I_IN].sval;
15077                 pv[KRB_I_IN].sval = NULL;
15078             } else if ( tmpinst ) {
15079                 krb4_init.instance = tmpinst;
15080                 tmpinst = NULL;
15081             }
15082             krb4_init.preauth  = pv[KRB_I_PA].ival;
15083             krb4_init.verbose  = pv[KRB_I_BR].ival ? 0 : 1;
15084 
15085             if (tmpprinz) {
15086                 krb4_init.principal = tmpprinz;
15087                 tmpprinz = NULL;
15088             }
15089             krb4_init.password = tmppswd;
15090             tmppswd = NULL;
15091         }
15092         break;
15093       case KRB_A_LC:                    /* List Credentials */
15094         krb5_lc.encryption = tmp_klc & XYKLCEN;
15095         krb5_lc.flags = tmp_klc & XYKLCFL;
15096         krb5_lc.addr  = tmp_klc & XYKLCAD;
15097         break;
15098     }
15099 
15100 /* Common exit - Free temporary storage */
15101 
15102   kerbx:
15103     for (i = 0; i <= KRB_I_MAX; i++) {  /* Free malloc'd switch data */
15104         if (pv[i].sval)
15105           free(pv[i].sval);
15106     }
15107     for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
15108         if (tmpaddrs[i])
15109           free(tmpaddrs[i]);
15110     }
15111     if (tmpprinz) free(tmpprinz);       /* And these too. */
15112     if (tmppswd)  free(tmppswd);
15113     if (tmpcache) free(tmpcache);
15114     if (tmprealm) free(tmprealm);
15115     if (tmpinst)  free(tmpinst);
15116 
15117     return(rc);                         /* Return the return code */
15118 }
15119 #endif /* CK_KERBEROS */
15120 
15121 #ifdef CK_LOGIN
15122 int
15123 #ifdef CK_ANSIC
ckxlogin(CHAR * userid,CHAR * passwd,CHAR * acct,int promptok)15124 ckxlogin(CHAR * userid, CHAR * passwd, CHAR * acct, int promptok)
15125 #else /* CK_ANSIC */
15126 ckxlogin(userid, passwd, acct, promptok)
15127   CHAR * userid; CHAR * passwd; CHAR * acct; int promptok;
15128 #endif /* CK_ANSIC */
15129 /* ckxlogin */ {
15130 #ifdef CK_RECALL
15131     extern int on_recall;               /* around Password prompting */
15132 #endif /* CK_RECALL */
15133 #ifdef COMMENT
15134     extern int guest;
15135 #endif /* COMMENT */
15136     int rprompt = 0;                    /* Restore prompt */
15137 #ifdef CKSYSLOG
15138     int savlog;
15139 #endif /* CKSYSLOG */
15140 
15141     extern int what, srvcdmsg;
15142 
15143     int x = 0, ok = 0, rc = 0;
15144     CHAR * _u = NULL, * _p = NULL, * _a = NULL;
15145 
15146     debug(F111,"ckxlogin userid",userid,promptok);
15147     debug(F110,"ckxlogin passwd",passwd,0);
15148 
15149     isguest = 0;                        /* Global "anonymous" flag */
15150 
15151     if (!userid) userid = (CHAR *)"";
15152     if (!passwd) passwd = (CHAR *)"";
15153 
15154     debug(F111,"ckxlogin userid",userid,what);
15155 
15156 #ifdef CK_RECALL
15157     on_recall = 0;
15158 #endif /* CK_RECALL */
15159 
15160 #ifdef CKSYSLOG
15161     savlog = ckxsyslog;                 /* Save and turn off syslogging */
15162 #endif /* CKSYSLOG */
15163 
15164     if ((!*userid || !*passwd) &&       /* Need to prompt for missing info */
15165         promptok) {
15166         cmsavp(psave,PROMPTL);          /* Save old prompt */
15167         debug(F110,"ckxlogin saved",psave,0);
15168         rprompt = 1;
15169     }
15170     if (!*userid) {
15171         if (!promptok)
15172           return(0);
15173         cmsetp("Username: ");           /* Make new prompt */
15174         concb((char)escape);            /* Put console in cbreak mode */
15175         cmini(1);
15176 
15177 /* Flush typeahead */
15178 
15179 #ifdef IKS_OPTION
15180         debug(F101,
15181               "ckxlogin TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
15182               "",
15183               TELOPT_SB(TELOPT_KERMIT).kermit.me_start
15184               );
15185 #endif /* IKS_OPTION */
15186 
15187         while (ttchk() > 0) {
15188             x = ttinc(0);
15189             debug(F101,"ckxlogin flush user x","",x);
15190             if (x < 0)
15191               doexit(GOOD_EXIT,0);      /* Connection lost */
15192 #ifdef TNCODE
15193             if (sstelnet) {
15194                 if (x == IAC) {
15195                     x = tn_doop((CHAR)(x & 0xff),ckxech,ttinc);
15196                     debug(F101,"ckxlogin user tn_doop","",x);
15197 #ifdef IKS_OPTION
15198                     debug(F101,
15199                       "ckxlogin user TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
15200                       "",
15201                       TELOPT_SB(TELOPT_KERMIT).kermit.me_start
15202                       );
15203 #endif /* IKS_OPTION */
15204 
15205                     if (x < 0)
15206                       goto XCKXLOG;
15207                     switch (x) {
15208                       case 1: ckxech = 1; break; /* Turn on echoing */
15209                       case 2: ckxech = 0; break; /* Turn off echoing */
15210 #ifdef IKS_OPTION
15211                       case 4:                    /* IKS event */
15212                         if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
15213                           break;                 /* else fall thru... */
15214 #endif /* IKS_OPTION */
15215                       case 6:                    /* Logout */
15216                         goto XCKXLOG;
15217                     }
15218                 }
15219             }
15220 #endif /* TNCODE */
15221         }
15222         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
15223         cmres();                        /* Reset the parser */
15224         for (x = -1; x < 0;) {          /* Prompt till they answer */
15225             /* Get a literal line of text */
15226             x=cmtxt("Your username, or \"ftp\", or \"anonymous\"","",&s,NULL);
15227             if (x == -4 || x == -10) {
15228                 printf("\r\n%sLogin cancelled\n",
15229 		       x == -10 ? "Timed out: " : "");
15230 #ifdef CKSYSLOG
15231                 ckxsyslog = savlog;
15232 #endif /* CKSYSLOG */
15233                 doexit(GOOD_EXIT,0);
15234             }
15235             if (sstate)                 /* Did a packet come instead? */
15236               goto XCKXLOG;
15237             cmres();                    /* Reset the parser again */
15238         }
15239         if ((_u = (CHAR *)malloc((int)strlen(s) + 1)) == NULL) {
15240             printf("?Internal error: malloc\n");
15241             goto XCKXLOG;
15242         } else {
15243             strcpy((char *)_u,s);       /* safe */
15244             userid = _u;
15245         }
15246     }
15247     ok = zvuser((char *)userid);        /* Verify username */
15248     debug(F111,"ckxlogin zvuser",userid,ok);
15249 
15250     if (!*passwd && promptok
15251 #ifdef COMMENT
15252         && guest
15253 #endif /* COMMENT */
15254         ) {
15255         char prmpt[80];
15256 
15257 #ifdef CKSYSLOG
15258         savlog = ckxsyslog;             /* Save and turn off syslogging */
15259         ckxsyslog = 0;
15260 #endif /* CKSYSLOG */
15261 
15262 /* Flush typeahead again */
15263 
15264         while (ttchk() > 0) {
15265             x = ttinc(0);
15266             debug(F101,"ckxlogin flush user x","",x);
15267 #ifdef TNCODE
15268             if (sstelnet) {
15269                 if (x == IAC) {
15270                     x = tn_doop((CHAR)(x & 0xff),ckxech,ttinc);
15271                     debug(F101,"ckxlogin pass tn_doop","",x);
15272 #ifdef IKS_OPTION
15273                     debug(F101,
15274                       "ckxlogin pass TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
15275                       "",
15276                       TELOPT_SB(TELOPT_KERMIT).kermit.me_start
15277                       );
15278 #endif /* IKS_OPTION */
15279                     if (x < 0)
15280                       goto XCKXLOG;
15281                     switch (x) {
15282                       case 1: ckxech = 1; break; /* Turn on echoing */
15283                       case 2: ckxech = 0; break; /* Turn off echoing */
15284                       case 4:                    /* IKS event */
15285                         if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
15286                           break;                 /* else fall thru... */
15287                       case 6:                    /* Logout */
15288                         goto XCKXLOG;
15289                     }
15290                 }
15291             }
15292 #endif /* TNCODE */
15293         }
15294         if (!strcmp((char *)userid,"anonymous") ||
15295             !strcmp((char *)userid,"ftp")) {
15296             if (!ok)
15297               goto XCKXLOG;
15298             ckstrncpy(prmpt,"Enter e-mail address as Password: ",80);
15299         } else if (*userid && strlen((char *)userid) < 60) {
15300 #ifdef NT
15301             extern CHAR * pReferenceDomainName;
15302             if (pReferenceDomainName)
15303               ckmakxmsg(prmpt,
15304                        80,
15305                        "Enter ",
15306                        pReferenceDomainName,
15307                        "\\\\",
15308                        userid,
15309                        "'s Password: ",
15310                        NULL,NULL,NULL,NULL,NULL,NULL,NULL
15311                        );
15312             else
15313 #endif /* NT */
15314               ckmakmsg(prmpt,80,"Enter ",(char *)userid,"'s Password: ",NULL);
15315         } else
15316           ckstrncpy(prmpt,"Enter Password: ",80);
15317         cmsetp(prmpt);                  /* Make new prompt */
15318         concb((char)escape);            /* Put console in cbreak mode */
15319         if (strcmp((char *)userid,"anonymous") &&
15320             strcmp((char *)userid,"ftp")) { /* and if not anonymous */
15321             debok = 0;
15322             cmini(0);                   /* and no-echo mode */
15323         } else {
15324             cmini(1);
15325         }
15326         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
15327         cmres();                        /* Reset the parser */
15328         for (x = -1; x < 0;) {          /* Prompt till they answer */
15329 #ifdef CK_PAM
15330 	    gotemptypasswd=0;
15331 #endif /* CK_PAM */
15332             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
15333             if (x == -4 || x == -10) {
15334                 printf("\r\n%sLogin cancelled\n",
15335 		       x == -10 ? "Timed out: " : "");
15336 #ifdef CKSYSLOG
15337                 ckxsyslog = savlog;
15338 #endif /* CKSYSLOG */
15339                 doexit(GOOD_EXIT,0);
15340             }
15341 #ifdef CK_PAM
15342 	    if (!*s)
15343 	      gotemptypasswd = 1;
15344 #endif /* CK_PAM */
15345             if (sstate)                 /* In case of a Kermit packet */
15346               goto XCKXLOG;
15347             cmres();                    /* Reset the parser again */
15348         }
15349         printf("\r\n");                 /* Echo a CRLF */
15350         if ((_p = (CHAR *)malloc((int)strlen(s) + 1)) == NULL) {
15351             printf("?Internal error: malloc\n");
15352             goto XCKXLOG;
15353         } else {
15354             strcpy((char *)_p,s);       /* safe */
15355             passwd = _p;
15356         }
15357     }
15358 #ifdef CK_PAM
15359     else {
15360         cmres();                        /* Reset the parser */
15361 
15362         /* We restore the prompt now because the PAM engine will call  */
15363         /* readpass() which will overwrite psave. */
15364         if (rprompt) {
15365             cmsetp(psave);              /* Restore original prompt */
15366             debug(F110,"ckxlogin restored",psave,0);
15367             rprompt = 0;
15368         }
15369     }
15370 #endif /* CK_PAM */
15371 
15372 #ifdef CKSYSLOG
15373     ckxsyslog = savlog;
15374 #endif /* CKSYSLOG */
15375 
15376     if (ok) {
15377         ok = zvpass((char *)passwd);    /* Check password */
15378         debug(F101,"ckxlogin zvpass","",ok);
15379 #ifdef CK_PAM
15380     } else {
15381 	/* Fake pam password failure for nonexistent users */
15382 	sleep(1);
15383 	printf("Authentication failure\n");
15384 #endif	/* CK_PAM */
15385     }
15386 
15387     if (ok > 0 && isguest) {
15388 #ifndef NOPUSH
15389         nopush = 1;
15390 #endif /* NOPUSH */
15391         srvcdmsg = 1;
15392     }
15393     rc = ok;                            /* Set the return code */
15394     if ((char *)uidbuf != (char *)userid)
15395       ckstrncpy(uidbuf,(char *)userid,UIDBUFLEN); /* Remember username */
15396 
15397   XCKXLOG:                              /* Common exit */
15398 #ifdef CKSYSLOG
15399     ckxsyslog = savlog;                 /* In case of GOTO above */
15400 #endif /* CKSYSLOG */
15401     if (rprompt) {
15402         cmsetp(psave);                  /* Restore original prompt */
15403         debug(F110,"ckxlogin restored",psave,0);
15404     }
15405     if (_u || _p || _a) {
15406         if (_u) free(_u);
15407         if (_p) free(_p);
15408         if (_a) free(_a);
15409     }
15410     return(rc);
15411 }
15412 
15413 int
ckxlogout()15414 ckxlogout() {
15415     doexit(GOOD_EXIT,0);                /* doexit calls zvlogout */
15416     return(0);                          /* not reached */
15417 }
15418 #endif /* CK_LOGIN */
15419 
15420 #endif /* NOICP */
15421