1 #ifdef SSHTEST
2 #define SSHBUILTIN
3 #endif /* SSHTEST */
4 
5 #include "ckcsym.h"                     /* Symbol definitions */
6 
7 /*  C K U U S 3 --  "User Interface" for C-Kermit, part 3  */
8 
9 /*
10   Authors:
11     Frank da Cruz <fdc@columbia.edu>,
12       The Kermit Project, New York City
13     Jeffrey E Altman <jaltman@secure-endpoints.com>
14       Secure Endpoints Inc., New York City
15 
16   Copyright (C) 1985, 2020,
17     Trustees of Columbia University in the City of New York.
18     All rights reserved.  See the C-Kermit COPYING.TXT file or the
19     copyright text in the ckcmai.c module for disclaimer and permissions.
20 */
21 
22 /*  SET command (but much material has been split off into ckuus7.c). */
23 
24 /*
25   Kermit-specific includes.
26   Definitions here supersede those from system include files.
27 */
28 #include "ckcdeb.h"                     /* Debugging & compiler things */
29 #include "ckcasc.h"                     /* ASCII character symbols */
30 #include "ckcker.h"                     /* Kermit application definitions */
31 #include "ckcxla.h"                     /* Character set translation */
32 #include "ckcnet.h"                     /* Network symbols */
33 
34 char pwbuf[PWBUFL+1]  = { NUL, NUL };
35 int pwflg = 0;
36 int pwcrypt = 0;
37 
38 #ifndef NOICP
39 
40 #ifdef CK_AUTHENTICATION
41 #include "ckuath.h"
42 #endif /* CK_AUTHENTICATION */
43 #ifdef CK_SSL
44 #include "ck_ssl.h"
45 #endif /* CK_SSL */
46 #include "ckuusr.h"                     /* User interface symbols */
47 #ifdef OS2
48 #include "ckcuni.h"
49 #ifdef SSHBUILTIN
50 #include "ckossh.h"
51 #endif /* SSHBUILTIN */
52 #ifdef CK_NETBIOS
53 #include <os2.h>
54 #ifdef COMMENT                          /* Would you believe */
55 #undef COMMENT                          /* <os2.h> defines this ? */
56 #endif /* COMMENT */
57 #include "ckonbi.h"
58 extern UCHAR NetBiosAdapter;
59 #endif /* CK_NETBIOS */
60 #include "ckocon.h"
61 #include "ckokey.h"
62 #ifndef NOTERM
63 extern unsigned char colorcmd;  /* Command-screen colors */
64 extern struct keytab ttyclrtab[];
65 extern int nclrs;
66 extern int tt_cols[], tt_rows[], tt_szchng[], tt_status[];
67 #endif /* NOTERM */
68 _PROTOTYP(int setprty, (void));
69 extern char startupdir[], exedir[];
70 extern int tt_modechg;
71 #ifdef NT
72 #include <windows.h>
73 #include <tapi.h>
74 #include "ckntap.h"                     /* Microsoft TAPI */
75 #endif /* NT */
76 #endif /* OS2 */
77 
78 #ifndef OS2
79 extern char * exedir;
80 #endif /* OS2 */
81 
82 #ifdef CK_RECALL
83 extern int cm_retry;
84 #endif /* CK_RECALL */
85 
86 #ifdef NEWFTP
87 extern int ftpisopen();
88 #endif /* NEWFTP */
89 
90 extern int cmdint;
91 extern int srvidl;
92 
93 #ifdef CKFLOAT
94 extern CKFLOAT floatval;		/* (see isfloat()) */
95 #endif /* CKFLOAT */
96 
97 #ifndef NOPUSH
98 #ifndef NOFRILLS
99 #ifdef VMS
100 char editor[CKMAXPATH + 1] = "edit";
101 #else
102 char editor[CKMAXPATH + 1] = { NUL, NUL };
103 #endif /* VMS */
104 char editopts[128] = { NUL, NUL };
105 char editfile[CKMAXPATH + 1] = { NUL, NUL };
106 #ifdef BROWSER
107 char browser[CKMAXPATH + 1] = { NUL, NUL };
108 char browsopts[128] = { NUL, NUL };
109 char browsurl[4096] = { NUL, NUL };
110 #endif /* BROWSER */
111 #endif /*  NOFRILLS */
112 #endif /* NOPUSH */
113 
114 #ifndef NOFRILLS
115 #ifndef NORENAME
116 _PROTOTYP(int setrename, (void));
117 #endif	/* NORENAME */
118 #endif	/* NOFRILLS */
119 
120 /* Variables */
121 
122 int exitmsg = 1;
123 int cmd_quoting = 1;
124 int cmd_err = 1;
125 extern int hints, xcmdsrc;
126 
127 #ifdef CK_KERBEROS
128 char * k4pwprompt = NULL;               /* Kerberos 4 password prompt */
129 char * k4prprompt = NULL;               /* Kerberos 4 principal prompt */
130 char * k5pwprompt = NULL;               /* Kerberos 5 password prompt */
131 char * k5prprompt = NULL;               /* Kerberos 5 principal prompt */
132 #endif /* CK_KERBEROS */
133 #ifdef CK_SRP
134 char * srppwprompt = NULL;
135 #endif /* CK_SRP */
136 
137 extern char * ckprompt, * ikprompt;     /* Default prompt */
138 extern xx_strp xxstring;
139 
140 extern char * cdmsgfile[], * cdmsgstr;
141 
142 extern int
143   local, server, success, dest, sleepcan, inserver, flow, autoflow, binary,
144   parity, escape, what, turn, duplex, backgrd, hwparity, stopbits, turnch,
145   mdmtyp, network, quiet, nettype, carrier, debses, debtim, cdtimo, nlangs,
146   bgset, pflag, msgflg, cmdmsk, xsuspend, techo, pacing, xitwarn, xitsta,
147   outesc, cmd_cols, cmd_rows, ckxech, xaskmore, haveline, didsetlin, isguest,
148   mdmsav, clearrq, saveask, debmsg;
149 
150 extern int reliable, setreliable, matchdot, matchfifo, dir_dots;
151 
152 #ifndef NOSERVER
153   extern int en_pri;
154 #endif /* NOSERVER */
155 
156 #ifdef IKSDCONF
157 extern int iksdcf;
158 #endif /* IKSDCONF */
159 #ifdef TCPSOCKET
160   extern int tn_exit;
161 #endif /* TCPSOCKET */
162 #ifdef TNCODE
163   char * tn_pr_uid = NULL;
164 #endif /* TNCODE */
165   extern int exitonclose;
166 
167 #ifndef NOKVERBS
168 extern int nkverbs;
169 extern struct keytab kverbs[];
170 #endif /* NOKVERBS */
171 
172 extern int ttnproto;                    /* Network protocol */
173 
174 extern char *ccntab[];                  /* Names of control chars */
175 
176 #ifdef CK_APC
177 extern int apcactive, apcstatus;
178 #endif /* CK_APC */
179 
180 #ifndef NOSCRIPT
181 extern int secho;                       /* Whether SCRIPT cmd should echo */
182 #endif /* NOSCRIPT */
183 
184 #ifdef DCMDBUF
185 extern char *atmbuf, *atxbuf;
186 #else
187 extern char atmbuf[], atxbuf[];
188 #endif /* DCMDBUF */
189 extern int cmflgs;
190 
191 extern char psave[];
192 extern char uidbuf[];
193 extern int  sl_uid_saved;
194 int DeleteStartupFile = 0;
195 
196 extern int cmdlvl;                      /* Overall command level */
197 
198 #ifndef NOSPL
199 _PROTOTYP( static int parsdir, (int) );
200 char prmbuf[PWBUFL+1] = { NUL, NUL };
201 int fndiags = 1;                        /* Function diagnostics on/off */
202 int fnerror = 1;                        /* Function error treatment */
203 
204 #ifdef DCMDBUF
205 extern int *count, *takerr, *merror, *inpcas;
206 #else
207 extern int count[], takerr[], merror[], inpcas[];
208 #endif /* DCMDBUF */
209 extern int mecho;                       /* Macro echo */
210 extern long ck_alarm;
211 extern char alrm_date[], alrm_time[];
212 #else
213 extern int takerr[];
214 #endif /* NOSPL */
215 
216 extern int x_ifnum;
217 extern int bigsbsiz, bigrbsiz;          /* Packet buffers */
218 
219 extern long speed;                      /* Terminal speed */
220 
221 extern char ttname[];                   /* Communication device name */
222 extern char myhost[] ;
223 extern char inidir[];                   /* Ini File directory */
224 
225 #ifndef NOSETKEY
226 extern KEY *keymap;                     /* Character map for SET KEY (1:1)  */
227 extern MACRO *macrotab;                 /* Macro map for SET KEY (1:string) */
228 #endif /* NOSETKEY */
229 #ifdef OS2
230 int wideresult;                         /* For wide OS/2 scan codes/cmnum() */
231 #endif /* OS2 */
232 
233 #ifndef NOLOCAL
234 #ifdef OS2
235 extern int tt_scrsize[];                /* Scrollback buffer Sizes */
236 #endif /* OS2 */
237 #endif /* NOLOCAL */
238 
239 /* Printer settings */
240 
241 extern char * printername;              /* NULL if printer not redirected */
242 extern int printpipe;
243 extern int noprinter;
244 #ifdef PRINTSWI
245 int printtimo = 0;
246 char * printterm = NULL;
247 char * printsep = NULL;
248 int printertype = 0;
249 #ifdef BPRINT
250 int printbidi = 0;                      /* SET BPRINTER (bidirectional) */
251 long pportspeed = 0L;                   /* Bidirection printer port speed, */
252 int pportparity = 0;                    /*  parity, */
253 int pportflow = FLO_KEEP;               /*  and flow control */
254 #endif /* BPRINT */
255 #ifdef OS2
256 extern int txt2ps;                      /* Text2PS conversion? */
257 extern int ps_width, ps_length;         /* Text2PS dimensions */
258 #endif /* OS2 */
259 #endif /* PRINTSWI */
260 
261 #ifdef OS2
262 extern int tcp_avail;                   /* Nonzero if TCP/IP is available */
263 #ifdef DECNET
264 extern int dnet_avail;                  /* Ditto for DECnet */
265 #endif /* DECNET */
266 #ifdef SUPERLAT
267 extern int slat_avail;
268 #endif /* SUPERLAT */
269 #endif /* OS2 */
270 
271 static struct keytab logintab[] = {
272     { "password", LOGI_PSW, CM_INV },
273     { "prompt",   LOGI_PRM, CM_INV },
274     { "userid",   LOGI_UID, 0 }
275 };
276 
277 #ifndef NOCSETS
278 /* system-independent character sets, defined in ckcxla.[ch] */
279 extern struct csinfo tcsinfo[];
280 extern struct langinfo langs[];
281 
282 /* Other character-set related variables */
283 extern int tcharset, tslevel, language;
284 #endif /* NOCSETS */
285 
286 /* File-transfer variable declarations */
287 
288 #ifndef NOXFER
289 #ifdef CK_AUTODL
290 extern int cmdadl;
291 #endif /* CK_AUTODL */
292 
293 #ifndef NOSERVER
294 extern int ngetpath;
295 extern char * getpath[];
296 #endif /* NOSERVER */
297 
298 extern struct ck_p ptab[];
299 
300 extern CHAR sstate;                     /* Protocol start state */
301 extern CHAR myctlq;                     /* Control-character prefix */
302 extern CHAR myrptq;                     /* Repeat-count prefix */
303 
304 extern int protocol, size, spsiz, spmax, urpsiz, srvtim, srvcdmsg, slostart,
305   srvdis, xfermode, ckdelay, keep, maxtry, unkcs, bctr, bctf, ebqflg, swcapr,
306   wslotr, lscapr, lscapu, spsizr, rptena, rptmin, docrc, xfrcan, xfrchr,
307   xfrnum, xfrbel, xfrint, srvping, g_xfermode, xfrxla;
308 
309 #ifdef PIPESEND
310 extern int usepipes;
311 #endif /* PIPESEND */
312 
313 #ifdef CKXXCHAR                         /* DOUBLE / IGNORE char table */
314 extern int dblflag, ignflag, dblchar;
315 extern short dblt[];
316 #endif /* CKXXCHAR */
317 
318 #ifdef CK_SPEED
319 extern short ctlp[];                    /* Control-prefix table */
320 extern int prefixing;
321 static struct keytab pfxtab[] = {
322     "all",         PX_ALL, 0,
323     "cautious",    PX_CAU, 0,
324     "minimal",     PX_WIL, 0,
325     "none",        PX_NON, 0
326 };
327 #endif /* CK_SPEED */
328 #endif /* NOXFER */
329 
330 /* Declarations from cmd package */
331 
332 #ifdef DCMDBUF
333 extern char *cmdbuf;                    /* Command buffer */
334 extern char *line;
335 extern char *tmpbuf;
336 #else
337 extern char cmdbuf[];                   /* Command buffer */
338 extern char line[];                     /* Character buffer for anything */
339 extern char tmpbuf[];
340 #endif /* DCMDBUF */
341 
342 /* From main ckuser module... */
343 
344 extern char *tp, *lp;                   /* Temporary buffer */
345 
346 extern int tlevel;                      /* Take Command file level */
347 
348 #ifndef NOLOCAL
349 extern int sessft;                      /* Session-log file type */
350 extern int slogts;                      /* Session-log timestamps on/off */
351 extern int slognul;			/* Lines null-terminated */
352 #endif /* NOLOCAL */
353 
354 char * tempdir = NULL;                  /* Temporary directory */
355 
356 #ifdef VMS
357 int vms_msgs = 1;                       /* SET MESSAGES */
358 extern int batch;
359 #endif /* VMS */
360 
361 /* Keyword tables for SET commands */
362 
363 #ifdef CK_SPEED
364 struct keytab ctltab[] = {
365     "prefixed",   1, 0,                 /* Note, the values are important. */
366     "unprefixed", 0, 0
367 };
368 #endif /* CK_SPEED */
369 
370 static struct keytab oldnew[] = {
371     "new", 0, 0,
372     "old", 1, 0
373 };
374 
375 #define MCH_FIFO 1
376 #define MCH_DOTF 2
377 struct keytab matchtab[] = {
378     { "dotfile", MCH_DOTF, 0 },
379     { "fifo",    MCH_FIFO, 0 }
380 };
381 int nmatchtab = (sizeof(matchtab) / sizeof(struct keytab));
382 
383 #ifndef NOSPL
384 static struct keytab functab[] = {
385     "diagnostics", FUNC_DI, 0,
386     "error",       FUNC_ER, 0
387 };
388 static int nfunctab = (sizeof(functab) / sizeof(struct keytab));
389 
390 struct keytab outptab[] = {             /* SET OUTPUT parameters */
391     "pacing", 0, 0,                     /* only one so far... */
392     "special-escapes", 1, 0
393 };
394 int noutptab = (sizeof(outptab) / sizeof(struct keytab)); /* How many */
395 #endif /* NOSPL */
396 
397 struct keytab chktab[] = {              /* Block check types */
398     "1", 1, 0,                          /* 1 =  6-bit checksum */
399     "2", 2, 0,                          /* 2 = 12-bit checksum */
400     "3", 3, 0,                          /* 3 = 16-bit CRC */
401     "4", 4, 0,				/* Same as B */
402     "5", 5, 0,				/* Same as F */
403     "blank-free-2", 4, CM_INV,		/* B = 12-bit checksum, no blanks */
404     "force-3", 5, CM_INV		/* F = Force CRC on ALL packets */
405 };
406 static int nchkt = (sizeof(chktab) / sizeof(struct keytab));
407 
408 struct keytab rpttab[] = {              /* SET REPEAT */
409     "counts",    0, 0,                  /* On or Off */
410 #ifdef COMMENT
411     "minimum",   1, 0,                  /* Threshhold */
412 #endif /* COMMENT */
413     "prefix",    2, 0                   /* Repeat-prefix character value */
414 };
415 
416 #ifndef NOLOCAL
417 /* For SET [ MODEM ] CARRIER, and also for SET DIAL CONNECT */
418 
419 struct keytab crrtab[] = {
420     "automatic", CAR_AUT, 0,            /* 2 */
421     "off",       CAR_OFF, 0,            /* 0 */
422     "on",        CAR_ON,  0             /* 1 */
423 };
424 int ncrr = 3;
425 #endif /* NOLOCAL */
426 
427 struct keytab ooatab[] = {              /* On/Off/Auto table */
428     "automatic", SET_AUTO, 0,           /* 2 */
429     "off",       SET_OFF,  0,           /* 0 */
430     "on",        SET_ON,   0            /* 1 */
431 };
432 
433 struct keytab ooetab[] = {              /* On/Off/Stderr table 2010/03/12 */
434     "off",       SET_OFF, 0,		/* for SET DEBUG MESSAGES */
435     "on",        SET_ON,  0,		/* 2013-03-13 and SET EXIT MESSAGE */
436     "s",         2,       CM_ABR|CM_INV,
437     "st",        2,       CM_ABR|CM_INV,
438     "std",       2,       CM_ABR|CM_INV,
439     "stderr",    2,       0,
440     "stdout",    SET_ON,  CM_INV
441 };
442 static int nooetab = (sizeof(ooetab) / sizeof(struct keytab));
443 
444 struct keytab ooktab[] = {              /* On/Off/Ask table */
445     "ask",       2,        0,           /* 2 */
446     "off",       SET_OFF,  0,           /* 0 */
447     "on",        SET_ON,   0            /* 1 */
448 };
449 
450 struct keytab qvtab[] = {               /* Quiet/Verbose table */
451     "quiet", 1, 0,
452     "verbose", 0, 0
453 };
454 int nqvt = 2;
455 
456 /* For SET DEBUG */
457 
458 #define DEB_OFF  0
459 #define DEB_ON   1
460 #define DEB_SES  2
461 #define DEB_TIM  3
462 #define DEB_LEN  4
463 #define DEB_MSG  5
464 
465 struct keytab dbgtab[] = {
466     "linelength", DEB_LEN, CM_INV,
467     "m",          DEB_MSG, CM_ABR|CM_INV,
468     "message",    DEB_MSG, 0,
469     "msg",        DEB_MSG, CM_INV,
470     "off",        DEB_OFF, 0,
471     "on",         DEB_ON,  0,
472     "session",    DEB_SES, 0,
473     "timestamps", DEB_TIM, 0
474 };
475 int ndbg = (sizeof(dbgtab) / sizeof(struct keytab));
476 
477 #ifndef NOLOCAL
478 /* Transmission speeds */
479 
480 #ifdef TTSPDLIST /* Speed table constructed at runtime . . . */
481 
482 struct keytab * spdtab = NULL;
483 int nspd = 0;
484 
485 #else
486 /*
487   Note, the values are encoded in cps rather than bps because 19200 and higher
488   are too big for some ints.  All but 75bps are multiples of ten.  Result of
489   lookup in this table must be multiplied by 10 to get actual speed in bps.
490   If this number is 70, it must be changed to 75.  If it is 888, this means
491   75/1200 split speed.
492 
493   The values are generic, rather than specific to UNIX.  We can't use B75,
494   B1200, B9600, etc, because non-UNIX versions of C-Kermit will not
495   necessarily have these symbols defined.  The BPS_xxx symbols are
496   Kermit-specific, and are defined in ckcdeb.h or on the CC command line.
497 
498   Like all other keytabs, this one must be in "alphabetical" order,
499   rather than numeric order.
500 */
501 struct keytab spdtab[] = {
502     "0",      0,  CM_INV,
503     "110",   11,  0,
504 #ifdef BPS_115K
505  "115200",11520,  0,
506 #endif /* BPS_115K */
507   "1200",   120,  0,
508 #ifdef BPS_134
509   "134.5",  134,  0,
510 #endif /* BPS_134 */
511 #ifdef BPS_14K
512   "14400", 1440,  0,
513 #endif /* BPS_14K */
514 #ifdef BPS_150
515   "150",     15,  0,
516 #endif /* BPS_150 */
517 #ifdef BPS_1800
518   "1800",     180,  0,
519 #endif /* BPS_150 */
520 #ifdef BPS_19K
521   "19200", 1920,  0,
522 #endif /* BPS_19K */
523 #ifdef BPS_200
524   "200",     20,  0,
525 #endif /* BPS_200 */
526 #ifdef BPS_230K
527   "230400", 23040, 0,
528 #endif /* BPS_230K */
529   "2400",   240,  0,
530 #ifdef BPS_28K
531   "28800", 2880,  0,
532 #endif /* BPS_28K */
533   "300",     30,  0,
534 #ifdef BPS_3600
535   "3600",   360,  0,
536 #endif /* BPS_3600 */
537 #ifdef BPS_38K
538   "38400", 3840,  0,
539 #endif /* BPS_38K */
540 #ifdef BPS_460K
541   "460800", 46080,  0,                  /* Need 32 bits for this... */
542 #endif /* BPS_460K */
543   "4800",   480,  0,
544 #ifdef BPS_50
545   "50",       5,  0,
546 #endif /* BPS_50 */
547 #ifdef BPS_57K
548   "57600", 5760,  0,
549 #endif /* BPS_57K */
550   "600",     60,  0,
551 #ifdef BPS_7200
552   "7200",   720,  0,
553 #endif /* BPS_7200 */
554 #ifdef BPS_75
555   "75",       7,  0,
556 #endif /* BPS_75 */
557 #ifdef BPS_7512
558   "75/1200",888,  0,                    /* Code "888" for split speed */
559 #endif /* BPS_7512 */
560 #ifdef BPS_76K
561   "76800", 7680,  0,
562 #endif /* BPS_76K */
563 #ifdef BPS_921K
564   "921600", 92160,0,                    /* Need 32 bits for this... */
565 #endif /* BPS_921K */
566   "9600",   960,  0
567 };
568 int nspd = (sizeof(spdtab) / sizeof(struct keytab)); /* How many speeds */
569 #endif /* TTSPDLIST */
570 
571 #ifdef TN_COMPORT
572 struct keytab tnspdtab[] = {            /* RFC 2217 TELNET COMPORT Option */
573     "115200", 11520,  0,                /* (add any other defined speeds) */
574     "1200",     120,  0,
575     "14400",   1440,  0,
576     "19200",   1920,  0,
577     "230400", 23040,  0,
578     "2400",     240,  0,
579     "28800",   2880,  0,
580     "300",       30,  0,
581     "38400",   3840,  0,
582     "460800", 46080,  0,
583     "4800",     480,  0,
584     "57600",   5760,  0,
585     "600",       60,  0,
586     "9600",     960,  0
587 };
588 int ntnspd = (sizeof(tnspdtab) / sizeof(struct keytab)); /* How many speeds */
589 #endif /* TN_COMPORT */
590 #endif /* NOLOCAL */
591 
592 #ifndef NOCSETS
593 extern struct keytab lngtab[];          /* Languages for SET LANGUAGE */
594 extern int nlng;
595 #endif /* NOCSETS */
596 
597 #ifndef NOLOCAL
598 /* Duplex keyword table */
599 
600 struct keytab dpxtab[] = {
601     "full",      0, 0,
602     "half",      1, 0
603 };
604 #endif /* NOLOCAL */
605 
606 /* Flow Control */
607 
608 struct keytab cxtypesw[] = {
609 #ifdef DECNET
610     "/decnet",         CXT_DECNET,  0,
611 #endif /* DECNET */
612     "/direct-serial",  CXT_DIRECT,  0,
613 #ifdef DECNET
614     "/lat",            CXT_LAT,     0,
615 #else
616 #ifdef SUPERLAT
617     "/lat",            CXT_LAT,     0,
618 #endif /* SUPERLAT */
619 #endif /* DECNET */
620     "/modem",          CXT_MODEM,   0,
621 #ifdef NPIPE
622     "/named-pipe",     CXT_NPIPE,   0,
623 #endif /* NPIPE */
624 #ifdef NETBIOS
625     "/netbios",        CXT_NETBIOS, 0,
626 #endif /* NETBIOS */
627     "/remote",         CXT_REMOTE,  0,
628 #ifdef TCPSOCKET
629     "/tcpip",          CXT_TCPIP,   0,
630 #endif /* TCPSOCKET */
631 #ifdef ANYX25
632     "/x.25",           CXT_X25,     0,
633 #endif /* ANYX25 */
634     "", 0, 0
635 };
636 int ncxtypesw = (sizeof(cxtypesw) / sizeof(struct keytab));
637 
638 #ifdef TN_COMPORT
639 struct keytab tnflotab[] = {            /* SET FLOW-CONTROL keyword table */
640     "dtr/cd",    FLO_DTRC, 0,           /* for RFC 2217 Telnet COMPORT */
641     "dtr/cts",   FLO_DTRT, 0,
642     "keep",      FLO_KEEP, 0,
643     "none",      FLO_NONE, 0,
644     "rts/cts",   FLO_RTSC, 0,
645     "xon/xoff",  FLO_XONX, 0
646 };
647 int ntnflo = (sizeof(tnflotab) / sizeof(struct keytab));
648 #endif /* TN_COMPORT */
649 
650 struct keytab flotab[] = {              /* SET FLOW-CONTROL keyword table */
651     "automatic", FLO_AUTO, CM_INV,      /* Not needed any more */
652 #ifdef CK_DTRCD
653     "dtr/cd",    FLO_DTRC, 0,
654 #endif /* CK_DTRCD */
655 #ifdef CK_DTRCTS
656     "dtr/cts",   FLO_DTRT, 0,
657 #endif /* CK_DTRCTS */
658     "keep",      FLO_KEEP, 0,
659     "none",      FLO_NONE, 0,
660 #ifdef CK_RTSCTS
661     "rts/cts",   FLO_RTSC, 0,
662 #endif /* CK_RTSCTS */
663 #ifndef Plan9
664     "xon/xoff",  FLO_XONX, 0,
665 #endif /* Plan9 */
666     "", 0, 0
667 };
668 int nflo = (sizeof(flotab) / sizeof(struct keytab)) - 1;
669 
670 /*  Handshake characters  */
671 
672 struct keytab hshtab[] = {
673     "bell", 007, 0,
674     "code", 998, 0,
675     "cr",   015, 0,
676     "esc",  033, 0,
677     "lf",   012, 0,
678     "none", 999, 0,                     /* (can't use negative numbers) */
679     "xoff", 023, 0,
680     "xon",  021, 0
681 };
682 int nhsh = (sizeof(hshtab) / sizeof(struct keytab));
683 
684 #ifndef NOLOCAL
685 static struct keytab sfttab[] = {       /* File types for SET SESSION-LOG */
686     "ascii",     XYFT_T, CM_INV,
687     "binary",    XYFT_B, 0,
688     "debug",     XYFT_D, 0,
689     "null-padded-lines", 998, 0,
690     "text",      XYFT_T, 0,
691     "timestamped-text", 999, 0
692 };
693 static int nsfttab = (sizeof(sfttab) / sizeof(struct keytab));
694 #endif /* NOLOCAL */
695 
696 #ifndef NODIAL
697 
698 #ifdef NETCONN                          /* Networks directory depends */
699 int nnetdir = 0;                        /* on DIAL code -- fix later... */
700 char *netdir[MAXDDIR+2];
701 #endif /* NETCONN */
702 
703 _PROTOTYP( static int setdial, (int) );
704 _PROTOTYP( static int setdcd, (void) );
705 _PROTOTYP( static int cklogin, (void) );
706 
707 #ifndef MINIDIAL
708 #ifdef OLDTBCODE
709 extern int tbmodel;                     /* Telebit model ID */
710 #endif /* OLDTBCODE */
711 #endif /* MINIDIAL */
712 
713 extern MDMINF *modemp[];                /* Pointers to modem info structs */
714 extern struct keytab mdmtab[];          /* Modem types (in module ckudia.c) */
715 extern int nmdm;                        /* Number of them */
716 
717 _PROTOTYP(static int dialstr,(char **, char *));
718 
719 extern int dialhng, dialtmo, dialksp, dialdpy, dialmhu, dialec, dialdc;
720 extern int dialrtr, dialint, dialudt, dialsrt, dialrstr, mdmwaitd;
721 extern int mdmspd, dialfc, dialmth, dialesc, dialfld, dialidt, dialpace;
722 extern int mdmspk, mdmvol, dialtest;
723 
724 int dialcvt = 2;                        /* DIAL CONVERT-DIRECTORY */
725 int dialcnf = 0;                        /* DIAL CONFIRMATION */
726 int dialcon = 2;                        /* DIAL CONNECT */
727 int dialcq  = 0;                        /* DIAL CONNECT AUTO quiet/verbose */
728 extern long dialmax, dialcapas;
729 int usermdm = 0;
730 extern int ndialdir;
731 extern char *dialini,   *dialmstr, *dialmprmt, *dialdir[], *dialcmd,  *dialnpr,
732  *dialdcon, *dialdcoff, *dialecon, *dialecoff, *dialhcmd,  *dialx3,
733  *dialhwfc, *dialswfc,  *dialnofc, *dialtone,  *dialpulse, *dialname, *diallac;
734 extern char *diallcc,   *dialixp,  *dialixs,   *dialldp,   *diallds,  *dialtfp,
735  *dialpxi,  *dialpxo,   *dialsfx,  *dialaaon,  *dialaaoff;
736 extern char *diallcp,   *diallcs,  *dialini2,  *dialmac;
737 extern char *dialspoff, *dialspon, *dialvol1,  *dialvol2,  *dialvol3;
738 
739 char *dialtocc[MAXTPCC] = { NULL, NULL };
740 int ndialtocc = 0;
741 char *dialpucc[MAXTPCC] = { NULL, NULL };
742 int ndialpucc = 0;
743 
744 char *dialtfc[MAXTOLLFREE] = {
745     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
746 };
747 int ntollfree = 0;
748 
749 char *dialpxx[MAXPBXEXCH] = {
750     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
751 };
752 int ndialpxx = 0;
753 
754 char *diallcac[MAXLOCALAC] = {
755     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
756     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
757     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
758     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
759 };
760 int nlocalac = 0;
761 
762 static struct keytab drstrtab[] = {
763     "international", 5, 0,
764     "local",         2, 0,
765     "long-distance", 4, 0,
766     "none",          6, 0
767 };
768 
769 static struct keytab dcnvtab[] = {
770     "ask",  2, 0,
771     "off",  0, 0,
772     "on",   1, 0
773 };
774 
775 struct keytab setmdm[] = {
776     "capabilities",     XYDCAP,  0,
777     "carrier-watch",    XYDMCD,  0,
778     "command",          XYDSTR,  0,
779     "compression",      XYDDC,   CM_INV,
780     "data-compression", XYDDC,   0,
781     "dial-command",     XYDDIA,  0,
782     "error-correction", XYDEC,   0,
783     "escape-character", XYDESC,  0,
784     "flow-control",     XYDFC,   0,
785     "hangup-method",    XYDMHU,  0,
786 #ifndef NOXFER
787     "kermit-spoof",     XYDKSP,  0,
788 #endif /* NOXFER */
789     "maximum-speed",    XYDMAX,  0,
790     "name",             XYDNAM,  0,
791     "speaker",          XYDSPK,  0,
792     "speed-matching",   XYDSPD,  0,
793     "type",             XYDTYP,  0,
794     "volume",           XYDVOL,  0
795 };
796 int nsetmdm = (sizeof(setmdm) / sizeof(struct keytab));
797 
798 struct keytab voltab[] = {
799     "high",   3,  0,
800     "low",    1,  0,
801     "medium", 2,  0
802 };
803 
804 struct keytab mdmcap[] = {
805     "at-commands",      CKD_AT,  0,
806     "compression",      CKD_DC,  0,
807     "dc",               CKD_DC,  CM_INV,
808     "ec",               CKD_EC,  CM_INV,
809     "error-correction", CKD_EC,  0,
810     "hardware-flow",    CKD_HW,  0,
811     "hwfc",             CKD_HW,  CM_INV,
812     "itu",              CKD_V25, CM_INV,
813     "kermit-spoof",     CKD_KS,  0,
814     "ks",               CKD_KS,  CM_INV,
815     "sb",               CKD_SB,  CM_INV,
816     "software-flow",    CKD_SW,  0,
817     "speed-buffering",  CKD_SB,  0,
818     "swfc",             CKD_SW,  CM_INV,
819     "tb",               CKD_TB,  CM_INV,
820     "telebit",          CKD_TB,  0,
821     "v25bis-commands",  CKD_V25, 0
822 };
823 int nmdmcap = (sizeof(mdmcap) / sizeof(struct keytab));
824 
825 #ifdef COMMENT                          /* SET ANSWER not implemented yet */
826 static struct keytab answertab[] = {
827     { "caller-id",  XYA_CID,  0 };
828     { "rings",      XYA_RNG,  0 };
829     { "", 0, 0 }
830 };
831 static int nanswertab =  (sizeof(answertab) / sizeof(struct keytab)) - 1;
832 #endif /* COMMENT */
833 
834 struct keytab dialtab[] = {             /* SET DIAL table */
835     "area-code",        XYDLAC, 0,      /* Also still includes items     */
836     "compression",      XYDDC,  CM_INV, /* that were moved to SET MODEM, */
837     "confirmation",     XYDCNF, 0,      /* but they are CM_INVisible...  */
838     "connect",          XYDCON, 0,
839     "convert-directory",XYDCVT, 0,
840     "country-code",     XYDLCC, 0,
841     "dial-command",     XYDDIA, CM_INV,
842     "directory",        XYDDIR, 0,
843     "display",          XYDDPY, 0,
844     "escape-character", XYDESC, CM_INV,
845     "error-correction", XYDEC,  CM_INV,
846     "flow-control",     XYDFC,  CM_INV,
847     "force-long-distance", XYDFLD, 0,
848     "hangup",           XYDHUP, 0,
849     "ignore-dialtone",  XYDIDT, 0,
850     "interval",         XYDINT, 0,
851     "in",               XYDINI, CM_INV|CM_ABR,
852     "init-string",      XYDINI, CM_INV,
853     "intl-prefix",      XYDIXP, 0,
854     "intl-suffix",      XYDIXS, 0,
855 #ifndef NOXFER
856     "kermit-spoof",     XYDKSP, CM_INV,
857 #endif /* NOXFER */
858     "lc-area-codes",    XYDLLAC, 0,
859     "lc-prefix",        XYDLCP, 0,
860     "lc-suffix",        XYDLCS, 0,
861     "ld-prefix",        XYDLDP, 0,
862     "ld-suffix",        XYDLDS, 0,
863     "local-area-code",  XYDLAC, CM_INV,
864     "local-prefix",     XYDLCP, CM_INV,
865     "local-suffix",     XYDLCS, CM_INV,
866     "m",                XYDMTH, CM_INV|CM_ABR,
867 #ifndef NOSPL
868     "macro",            XYDMAC, 0,      /* 195 */
869 #endif /* NOSPL */
870 #ifdef MDMHUP
871     "me",               XYDMTH, CM_INV|CM_ABR,
872 #endif /* MDMHUP */
873     "method",           XYDMTH, 0,
874     "mnp-enable",       XYDMNP, CM_INV, /* obsolete but still accepted */
875 #ifdef MDMHUP
876     "modem-hangup",     XYDMHU, CM_INV,
877 #endif /* MDMHUP */
878     "pacing",           XYDPAC,  0,
879     "pbx-exchange",     XYDPXX,  0,
880     "pbx-inside-prefix",XYDPXI,  0,
881     "pbx-outside-prefix",XYDPXO, 0,
882     "prefix",           XYDNPR,  0,
883     "pulse-countries",  XYDPUCC, 0,
884     "restrict",         XYDRSTR, 0,
885     "retries",          XYDRTM,  0,
886     "sort",             XYDSRT,  0,
887     "speed-matching",   XYDSPD,  CM_INV,
888     "string",           XYDSTR,  CM_INV,
889     "suffix",           XYDSFX,  0,
890     "test",             XYDTEST, 0,
891     "timeout",          XYDTMO,  0,
892     "tf-area-code",     XYDTFC,  CM_INV,
893     "tf-prefix",        XYDTFP,  CM_INV,
894     "toll-free-area-code",XYDTFC,0,
895     "toll-free-prefix", XYDTFP,  0,
896     "tone-countries",   XYDTOCC, 0
897 };
898 int ndial = (sizeof(dialtab) / sizeof(struct keytab));
899 
900 #ifdef MDMHUP
901 struct keytab mdmhang[] = {
902     "dtr",           0, 0,
903     "modem-command", 1, 0,
904     "rs232-signal",  0, 0,
905     "v24-signal",    0, CM_INV
906 };
907 #endif /* MDMHUP */
908 
909 static struct keytab mdmcmd[] = {
910     "autoanswer",       XYDS_AN, 0,     /* autoanswer */
911     "compression",      XYDS_DC, 0,     /* data compression */
912     "dial-mode-prompt", XYDS_MP, 0,     /* dial mode prompt */
913     "dial-mode-string", XYDS_MS, 0,     /* dial mode string */
914     "error-correction", XYDS_EC, 0,     /* error correction */
915     "hangup-command",   XYDS_HU, 0,     /* hangup command */
916     "hardware-flow",    XYDS_HW, 0,     /* hwfc */
917     "ignore-dialtone",  XYDS_ID, 0,     /* ignore dialtone */
918     "init-string",      XYDS_IN, 0,     /* init string */
919     "no-flow-control",  XYDS_NF, 0,     /* no flow control */
920     "predial-init",     XYDS_I2, 0,     /* last-minute setup commands */
921     "pulse",            XYDS_DP, 0,     /* pulse */
922     "software-flow",    XYDS_SW, 0,     /* swfc */
923     "speaker",          XYDS_SP, 0,     /* Speaker */
924     "tone",             XYDS_DT, 0,     /* tone */
925     "volume",           XYDS_VO, 0      /* Volume */
926 };
927 static int nmdmcmd = (sizeof(mdmcmd) / sizeof(struct keytab));
928 
929 struct keytab dial_fc[] = {
930     "auto",     FLO_AUTO, 0,
931     "none",     FLO_NONE, 0,
932     "rts/cts",  FLO_RTSC, 0,
933     "xon/xoff", FLO_XONX, 0
934 };
935 
936 struct keytab dial_m[] = {              /* DIAL METHOD */
937     "auto",    XYDM_A, 0,
938     "default", XYDM_D, 0,
939     "pulse",   XYDM_P, 0,
940     "tone",    XYDM_T, 0
941 };
942 int ndial_m = (sizeof(dial_m)/sizeof(struct keytab));
943 #endif /* NODIAL */
944 
945 #ifdef CK_TAPI
946 struct keytab tapitab[] = {             /* Top-Level Microsoft TAPI */
947     "configure-line",     XYTAPI_CFG,  0,
948     "dialing-properties", XYTAPI_DIAL, 0
949 };
950 int ntapitab = (sizeof(tapitab)/sizeof(struct keytab));
951 
952 struct keytab settapitab[] = {          /* SET Microsoft TAPI */
953     "inactivity-timeout", XYTAPI_INA,  0,
954     "line",               XYTAPI_LIN,  0,
955     "location",           XYTAPI_LOC,  0,
956     "manual-dialing",     XYTAPI_MAN,  0,
957     "modem-dialing",      XYTAPI_PASS, 0,
958     "modem-lights",       XYTAPI_LGHT, 0,
959     "phone-number-conversions",   XYTAPI_CON,  0,
960     "port",               XYTAPI_LIN,  CM_INV,
961     "post-dial-terminal", XYTAPI_PST,  0,
962     "pre-dial-terminal",  XYTAPI_PRE,  0,
963     "use-windows-configuration", XYTAPI_USE, 0,
964     "wait-for-credit-card-tone", XYTAPI_BNG, 0
965 };
966 int nsettapitab = (sizeof(settapitab)/sizeof(struct keytab));
967 
968 struct keytab * tapiloctab = NULL;      /* Microsoft TAPI Locations */
969 int ntapiloc = 0;
970 extern struct keytab * tapilinetab;     /* Microsoft TAPI Line Devices */
971 extern int ntapiline;
972 extern int tttapi;                      /* TAPI in use */
973 extern int tapipass;                    /* TAPI Passthrough mode */
974 extern int tapiconv;                    /* TAPI Conversion mode */
975 extern int tapilights;
976 extern int tapipreterm;
977 extern int tapipostterm;
978 extern int tapimanual;
979 extern int tapiinactivity;
980 extern int tapibong;
981 extern int tapiusecfg;
982 #endif /* CK_TAPI */
983 
984 #ifndef NOPUSH
985 extern int nopush;
986 extern int wildena;
987 #ifdef UNIX
988 struct keytab wildtab[] = {             /* SET WILDCARD-EXPANSION */
989 #ifdef UNIX
990     "kermit",  WILD_KER, 0,		/* By Kermit */
991 #endif	/* UNIX */
992     "off",     WILD_OFF, 0,		/* Disabled */
993     "on",      WILD_ON,  0,		/* Enabled */
994 #ifdef UNIX
995     "shell",   WILD_SHE, 0,		/* By Shell */
996 #endif	/* UNIX */
997     "", 0, 0
998 };
999 int nwild = (sizeof(wildtab) / sizeof(struct keytab)) - 1;
1000 
1001 struct keytab wdottab[] = {             /* cont'd */
1002     "/match-dot-files",    1, 0,
1003     "/no-match-dot-files", 0, 0
1004 };
1005 extern int wildxpand;
1006 #endif /* UNIX */
1007 #endif /* NOPUSH */
1008 
1009 #ifdef NETCONN
1010 extern struct keytab netcmd[], netkey[];
1011 extern int nnets, nnetkey;
1012 #ifdef TCPSOCKET
1013 extern struct keytab tcpopt[];
1014 extern int ntcpopt;
1015 #endif /* TCPSOCKET */
1016 #ifdef NPIPE
1017 char pipename[PIPENAML+1] = { NUL, NUL };
1018 #endif /* NPIPE */
1019 #ifdef CK_NETBIOS
1020 extern unsigned char NetBiosName[];
1021 #endif /* CK_NETBIOS */
1022 #endif /* NETCONN */
1023 
1024 #ifdef ANYX25
1025 struct keytab x25tab[] = {
1026     "call-user-data",    XYUDAT, 0,
1027     "closed-user-group", XYCLOS, 0,
1028     "reverse-charge",    XYREVC, 0
1029 };
1030 int nx25 = (sizeof(x25tab) / sizeof(struct keytab));
1031 
1032 #ifndef IBMX25
1033 struct keytab padx3tab[] = {
1034     "break-action",         PAD_BREAK_ACTION,           0,
1035     "break-character",      PAD_BREAK_CHARACTER,        0,
1036     "character-delete",     PAD_CHAR_DELETE_CHAR,       0,
1037     "cr-padding",           PAD_PADDING_AFTER_CR,       0,
1038     "discard-output",       PAD_SUPPRESSION_OF_DATA,    0,
1039     "echo",                 PAD_ECHO,                   0,
1040     "editing",              PAD_EDITING,                0,
1041     "escape",               PAD_ESCAPE,                 0,
1042     "forward",              PAD_DATA_FORWARD_CHAR,      0,
1043     "lf-padding",           PAD_PADDING_AFTER_LF,       0,
1044     "lf-insert",            PAD_LF_AFTER_CR,            0,
1045     "line-delete",          PAD_BUFFER_DELETE_CHAR,     0,
1046     "line-display",         PAD_BUFFER_DISPLAY_CHAR,    0,
1047     "line-fold",            PAD_LINE_FOLDING,           0,
1048     "pad-flow-control",     PAD_FLOW_CONTROL_BY_PAD,    0,
1049     "service-signals",      PAD_SUPPRESSION_OF_SIGNALS, 0,
1050     "timeout",              PAD_DATA_FORWARD_TIMEOUT,   0,
1051 /* Speed is read-only */
1052     "transmission-rate",    PAD_LINE_SPEED,             0,
1053     "user-flow-control",    PAD_FLOW_CONTROL_BY_USER,   0
1054 };
1055 int npadx3 = (sizeof(padx3tab) / sizeof(struct keytab));
1056 #endif /* IBMX25 */
1057 #endif /* ANYX25 */
1058 
1059 #ifdef TLOG
1060 static struct keytab vbtab[] = {
1061     "brief",   0, 0,
1062 #ifdef OS2ORUNIX
1063     "ftp",     2, 0,
1064 #else
1065 #ifdef VMS
1066     "ftp",     2, 0,
1067 #endif /* def VMS */
1068 #endif /* OS2ORUNIX */
1069     "verbose", 1, 0
1070 };
1071 int nvb = (sizeof(vbtab) / sizeof(struct keytab));
1072 #endif /* TLOG */
1073 
1074 #ifdef CKSYSLOG
1075 static struct keytab syslogtab[] = {
1076     "all",         SYSLG_CX, 0,
1077     "commands",    SYSLG_CM, 0,
1078     "connection",  SYSLG_AC, 0,
1079     "debug",       SYSLG_DB, 0,
1080     "dial",        SYSLG_DI, 0,
1081     "file-access", SYSLG_FA, 0,
1082     "file-create", SYSLG_FC, 0,
1083     "login",       SYSLG_LI, 0,
1084     "none",        SYSLG_NO, 0,
1085     "protocol",    SYSLG_PR, 0
1086 };
1087 int nsyslog = (sizeof(syslogtab) / sizeof(struct keytab));
1088 #endif /* CKSYSLOG */
1089 
1090 /* Parity keyword table */
1091 
1092 struct keytab partbl[] = {
1093     "even",    'e', 0,
1094 #ifdef HWPARITY
1095     "hardware",'H', 0,
1096 #endif /* HWPARITY */
1097     "mark",    'm', 0,
1098     "none",     0 , 0,
1099     "odd",     'o', 0,
1100     "space",   's', 0
1101 };
1102 int npar = (sizeof(partbl) / sizeof(struct keytab));
1103 
1104 #ifdef HWPARITY
1105 struct keytab hwpartbl[] = {
1106 /* Add mark and space if needed and possible */
1107     "even",    'e', 0,
1108 #ifdef OS2
1109     "mark",    'm', 0,
1110 #endif /* OS2 */
1111     "odd",     'o', 0,
1112 #ifdef OS2
1113     "space",   's', 0,
1114 #endif /* OS2 */
1115     "", 0, 0
1116 };
1117 int nhwpar = (sizeof(hwpartbl) / sizeof(struct keytab)) - 1;
1118 #endif /* HWPARITY */
1119 
1120 /* On/Off table */
1121 
1122 struct keytab onoff[] = {
1123     "off",       0, 0,
1124     "on",        1, 0
1125 };
1126 
1127 #define XYCD_M    0			/* CD MESSAGE */
1128 #define XYCD_P    1			/* CD PATH */
1129 #define XYCD_H    2			/* CD HOME */
1130 
1131 struct keytab cdtab[] = {
1132     "home",      XYCD_H, 0,
1133     "message",   XYCD_M, 0,
1134     "path",      XYCD_P, 0
1135 };
1136 int ncdtab = (sizeof(cdtab) / sizeof(struct keytab));
1137 
1138 struct keytab cdmsg[] = {
1139     "file",      2, 0,
1140     "off",       0, 0,
1141     "on",        1, 0
1142 };
1143 int ncdmsg = (sizeof(cdmsg) / sizeof(struct keytab));
1144 
1145 static
1146 struct keytab xittab[] = {              /* SET EXIT */
1147     "hangup",        3, 0,              /* ...HANGUP */
1148     "message",       4, 0,		/* ...MESSAGE */
1149     "on-disconnect", 2, 0,              /* ...ON-DISCONNECT */
1150     "status",        0, 0,              /* ...STATUS */
1151     "warning",       1, 0               /* ...WARNING */
1152 };
1153 int nexit = (sizeof(xittab) / sizeof(struct keytab));
1154 
1155 struct keytab xitwtab[] = {             /* SET EXIT WARNING */
1156     "always", 2, 0,                     /* even when not connected */
1157     "off",    0, 0,                     /* no warning     */
1158     "on",     1, 0                      /* when connected */
1159 };
1160 int nexitw = (sizeof(xitwtab) / sizeof(struct keytab));
1161 
1162 struct keytab rltab[] = {
1163     "local",     1, 0,                  /* ECHO values */
1164     "off",       0, CM_INV,
1165     "on",        1, CM_INV,
1166     "remote",    0, 0
1167 };
1168 int nrlt = (sizeof(rltab) / sizeof(struct keytab));
1169 
1170 /* Incomplete File Disposition table */
1171 
1172 struct keytab ifdtab[] = {
1173     "discard", SET_OFF, 0,
1174     "keep",    SET_ON,  0
1175 };
1176 
1177 struct keytab ifdatab[] = {
1178     "auto",    SET_AUTO, 0,
1179     "discard", SET_OFF,  0,
1180     "keep",    SET_ON,   0
1181 };
1182 
1183 char * ifdnam[] = { "discard", "keep", "auto" };
1184 
1185 /* SET TAKE parameters table */
1186 static
1187 struct keytab taktab[] = {
1188     "echo",  0, 0,
1189     "error", 1, 0,
1190     "off",   2, CM_INV,                 /* For compatibility */
1191     "on",    3, CM_INV                  /* with MS-DOS Kermit... */
1192 };
1193 
1194 #ifndef NOSPL
1195 #ifdef COMMENT
1196 /* not used */
1197 static
1198 struct keytab suftab[] = {              /* (what to do with) STARTUP-FILE */
1199     "delete", 1, 0,
1200     "keep",   0, 0
1201 };
1202 #endif /* COMMENT */
1203 
1204 /* SET MACRO parameters table */
1205 static
1206 struct keytab smactab[] = {
1207     "echo",  0, 0,
1208     "error", 1, 0
1209 };
1210 #endif /* NOSPL */
1211 
1212 #ifndef NOSCRIPT
1213 static
1214 struct keytab scrtab[] = {
1215     "echo",  0, 0
1216 };
1217 #endif /* NOSCRIPT */
1218 
1219 /* SET COMMAND table */
1220 
1221 /* SET COMMAND items... */
1222 
1223 #define SCMD_BSZ 0	/* BYTESIZE */
1224 #define SCMD_RCL 1	/* RECALL */
1225 #define SCMD_RTR 2	/* RETRY */
1226 #define SCMD_QUO 3	/* QUOTING */
1227 #define SCMD_COL 4	/* COLOR */
1228 #define SCMD_HIG 5	/* HEIGHT */
1229 #define SCMD_WID 6	/* WIDTH */
1230 #define SCMD_CUR 7	/* CURSOR-POSITION */
1231 #define SCMD_SCR 8	/* SCROLLBACK */
1232 #define SCMD_MOR 9	/* MORE-PROMPTING */
1233 #define SCMD_INT 10     /* INTERRUPTION */
1234 #define SCMD_ADL 11     /* AUTODOWNLOAD */
1235 #define SCMD_STA 12     /* STATUSLINE */
1236 #define SCMD_DBQ 13	/* DOUBLEQUOTING */
1237 #define SCMD_CBR 14	/* CBREAK */
1238 #define SCMD_BFL 15	/* BUFFER-SIZE (not used) */
1239 #define SCMD_ERR 16	/* ERROR */
1240 #define SCMD_VAR 17	/* VARIABLE-EVALUATION */
1241 
1242 static struct keytab scmdtab[] = {
1243 #ifdef CK_AUTODL
1244     "autodownload",       SCMD_ADL, 0,
1245 #endif /* CK_AUTODL */
1246 #ifdef COMMENT
1247 /*
1248   To implement this requires that we change CMDBL and ATMBL
1249   from compile-time symbols to runtime variables.  Not a big deal,
1250   but not trivial either.
1251  */
1252     "buffer-size",        SCMD_BFL, 0,
1253 #endif /* COMMENT */
1254     "bytesize",           SCMD_BSZ, 0,
1255     "cbreak",             SCMD_CBR, CM_INV,
1256 #ifdef OS2
1257     "color",              SCMD_COL, 0,
1258     "cursor-position",    SCMD_CUR, 0,
1259 #endif /* OS2 */
1260 #ifdef DOUBLEQUOTING
1261     "doublequoting",      SCMD_DBQ, 0,
1262 #endif /* DOUBLEQUOTING */
1263     "error-display",      SCMD_ERR, 0,
1264     "height",             SCMD_HIG, 0,
1265     "interruption",       SCMD_INT, 0,
1266     "more-prompting",     SCMD_MOR, 0,
1267     "quoting",            SCMD_QUO, 0,
1268 #ifdef CK_RECALL
1269     "recall-buffer-size", SCMD_RCL, 0,
1270 #endif /* CK_RECALL */
1271 #ifdef CK_RECALL
1272     "retry",              SCMD_RTR, 0,
1273 #endif /* CK_RECALL */
1274 #ifdef OS2
1275 #ifdef ONETERMUPD
1276     "scrollback",         SCMD_SCR, 0,
1277     "statusline",         SCMD_STA, 0,
1278 #endif /* ONETERMUPD */
1279 #endif /* OS2 */
1280     "variable-evaluation", SCMD_VAR,0,
1281     "width",              SCMD_WID, 0
1282 };
1283 static int nbytt = (sizeof(scmdtab) / sizeof(struct keytab));
1284 
1285 #ifndef NOSERVER
1286 /* Server parameters table */
1287 static struct keytab srvtab[] = {
1288     "cd-message",   XYSERC, 0,
1289     "display",      XYSERD, 0,
1290     "get-path",     XYSERP, 0,
1291     "idle-timeout", XYSERI, 0,
1292     "keepalive",    XYSERK, 0,
1293     "login",        XYSERL, 0,
1294     "timeout",      XYSERT, 0
1295 };
1296 static int nsrvt = (sizeof(srvtab) / sizeof(struct keytab));
1297 #endif /* NOSERVER */
1298 
1299 static struct keytab sleeptab[] = {     /* SET SLEEP table */
1300     "cancellation",  0,   0
1301 };
1302 
1303 static struct keytab tstab[] = {        /* SET TRANSFER/XFER table */
1304     "bell",            XYX_BEL, 0,
1305 #ifdef XFRCAN
1306     "cancellation",    XYX_CAN, 0,
1307 #endif /* XFRCAN */
1308 #ifndef NOCSETS
1309     "character-set",   XYX_CSE, 0,
1310 #endif /* NOCSETS */
1311 #ifndef NOSPL
1312     "crc-calculation", XYX_CRC, 0,
1313 #endif /* NOSPL */
1314     "display",         XYX_DIS, 0,
1315     "interruption",    XYX_INT, 0,
1316     "locking-shift",   XYX_LSH, 0,
1317     "message",         XYX_MSG, 0,
1318     "mode",            XYX_MOD, 0,
1319     "msg",             XYX_MSG, CM_INV,
1320 #ifdef PIPESEND
1321     "pipes",           XYX_PIP, 0,
1322 #endif /* PIPESEND */
1323 #ifdef CK_XYZ
1324     "protocol",        XYX_PRO, 0,
1325 #endif /* CK_XYZ */
1326     "report",          XYX_RPT, 0,
1327     "slow-start",      XYX_SLO, 0,
1328 #ifndef NOCSETS
1329     "translation",     XYX_XLA, 0,
1330 #else
1331     "translation",     XYX_XLA, CM_INV,
1332 #endif /* NOCSETS */
1333     "xlation",         XYX_XLA, CM_INV,
1334     "", 0, 0
1335 };
1336 static int nts = (sizeof(tstab) / sizeof(struct keytab)) - 1;
1337 
1338 static struct keytab rtstab[] = {       /* REMOTE SET TRANSFER/XFER table */
1339 #ifndef NOCSETS
1340     "character-set",   XYX_CSE, 0,
1341 #endif /* NOCSETS */
1342     "mode",            XYX_MOD, 0
1343 };
1344 static int nrts = (sizeof(rtstab) / sizeof(struct keytab));
1345 
1346 struct keytab xfrmtab[] = {             /* TRANSFER MODE table */
1347     "automatic", XMODE_A, 0,
1348     "manual",    XMODE_M, 0
1349 };
1350 
1351 #ifdef LOCUS
1352 extern int locus, autolocus;
1353 
1354 static struct keytab locustab[] = {
1355 #ifdef KUI
1356     { "ask",     3, 0 },		/* Presently implemented in GUI only */
1357 #endif /* KUI */
1358     { "auto",    2, 0 },
1359     { "local",   1, 0 },
1360     { "remote",  0, 0 }
1361 };
1362 static int nlocustab = (sizeof(locustab) / sizeof(struct keytab));
1363 
1364 #endif /* LOCUS */
1365 
1366 #ifndef NOCSETS
1367 /* SET TRANSFER CHARACTER-SET table */
1368 
1369 extern struct keytab tcstab[];
1370 extern int ntcs;
1371 #endif /* NOCSETS */
1372 
1373 /* SET TRANSFER LOCKING-SHIFT table */
1374 struct keytab lstab[] = {
1375     "forced", 2,   0,
1376     "off",    0,   0,
1377     "on",     1,   0
1378 };
1379 int nls = (sizeof(lstab) / sizeof(struct keytab));
1380 
1381 /* SET TELNET tables */
1382 #ifdef TNCODE
1383 extern int tn_nlm, tn_b_nlm, tn_b_meu, tn_b_ume, tn_b_xfer, tn_sb_bug;
1384 extern int tn_no_encrypt_xfer, tn_auth_krb5_des_bug;
1385 extern int tn_wait_flg, tn_duplex, tn_delay_sb, tn_sfu;
1386 extern int sl_tn_saved;
1387 extern int tn_infinite;
1388 extern int tn_rem_echo;
1389 extern int tn_deb;
1390 extern int tn_auth_how;
1391 extern int tn_auth_enc;
1392 #ifdef CK_FORWARD_X
1393 extern char * tn_fwdx_xauthority;
1394 #endif /* CK_FORWARD_X */
1395 #ifdef CK_AUTHENTICATION
1396 static struct keytab setauth[] = {
1397 #ifdef CK_KERBEROS
1398     "k4",        AUTH_KRB4, CM_INV,
1399     "k5",        AUTH_KRB5, CM_INV,
1400     "kerberos4", AUTH_KRB4, 0,
1401     "kerberos5", AUTH_KRB5, 0,
1402     "kerberos_iv",AUTH_KRB4, CM_INV,
1403     "kerberos_v", AUTH_KRB5, CM_INV,
1404     "krb4",      AUTH_KRB4, CM_INV,
1405     "krb5",      AUTH_KRB5, CM_INV,
1406 #endif /* CK_KERBEROS */
1407 #ifdef CK_SRP
1408     "srp",       AUTH_SRP,  0,
1409 #endif /* CK_SRP */
1410 #ifdef CK_SSL
1411     "ssl",      AUTH_SSL,   0,
1412     "tls",      AUTH_TLS,   0,
1413 #endif /* CK_SSL */
1414     "",         0,      0
1415 };
1416 static int nsetauth = sizeof(setauth)/sizeof(struct keytab) - 1;
1417 #ifdef CK_KERBEROS
1418 extern char * krb5_d_principal;         /* Default principal */
1419 extern char * krb5_d_instance;
1420 extern char * krb5_d_realm;             /* Default realm */
1421 extern char * krb5_d_cc;                /* Default credentials cache */
1422 extern char * krb5_d_srv;               /* Default service name */
1423 extern int    krb5_d_lifetime;          /* Default lifetime */
1424 extern int    krb5_d_forwardable;
1425 extern int    krb5_d_proxiable;
1426 extern int    krb5_d_renewable;
1427 extern int    krb5_autoget;
1428 extern int    krb5_autodel;
1429 extern int    krb5_d_getk4;
1430 extern int    krb5_checkaddrs;          /* Check TGT Addrs */
1431 extern int    krb5_d_no_addresses;
1432 extern char * krb5_d_addrs[];
1433 extern char * k5_keytab;                /* Keytab file */
1434 
1435 extern struct krb4_init_data krb4_init;
1436 extern char * krb4_d_principal;         /* Default principal */
1437 extern char * krb4_d_realm;             /* Default realm */
1438 extern char * krb4_d_srv;               /* Default service name */
1439 extern int    krb4_d_lifetime;          /* Default lifetime */
1440 extern int    krb4_d_preauth;
1441 extern char * krb4_d_instance;
1442 extern int    krb4_autoget;
1443 extern int    krb4_autodel;
1444 extern int    krb4_checkaddrs;          /* Check TGT Addrs */
1445 extern char * k4_keytab;                /* Keytab file */
1446 #ifdef KRB4
1447 extern int    k4debug;
1448 #endif /* KRB4 */
1449 static struct keytab krbver[] = {
1450     "4",                 4, 0,
1451     "5",                 5, 0,
1452     "iv",                4, CM_INV,
1453     "v",                 5, CM_INV
1454 };
1455 static int nkrbver = sizeof(krbver)/sizeof(struct keytab);
1456 
1457 static struct keytab kdestab[] = {
1458     "never",            KRB_DEL_NO, 0,
1459     "no",               KRB_DEL_NO, CM_INV,
1460     "on-close",         KRB_DEL_CL, 0,
1461     "on-exit",          KRB_DEL_EX, 0
1462 };
1463 static int nkdestab = sizeof(kdestab)/sizeof(struct keytab);
1464 
1465 static struct keytab k4tab[] = {
1466     "autodel",           XYKRBDEL, CM_INV,
1467     "autodestroy",       XYKRBDEL, 0,
1468     "autoget",           XYKRBGET, 0,
1469     "check-address",     XYKRBADR, 0,
1470     "debug",             XYKRBDBG, CM_INV,
1471     "instance",          XYKRBINS, 0,
1472     "keytab",            XYKRBKTB, 0,
1473     "lifetime",          XYKRBLIF, 0,
1474     "preauth",           XYKRBPRE, 0,
1475     "principal",         XYKRBPR,  0,
1476     "prompt",            XYKRBPRM, 0,
1477     "realm",             XYKRBRL,  0,
1478     "service-name",      XYKRBSRV, 0
1479 };
1480 static int nk4tab = sizeof(k4tab)/sizeof(struct keytab);
1481 
1482 static struct keytab k5tab[] = {
1483     "addresses",         XYKRBADD, 0,
1484     "autodelete",        XYKRBDEL, CM_INV,
1485     "autodestroy",       XYKRBDEL, 0,
1486     "autoget",           XYKRBGET, 0,
1487     "cc",                XYKRBCC,  CM_INV,
1488     "check-address",     XYKRBADR, 0,
1489     "credentials-cache", XYKRBCC,  0,
1490     "forwardable",       XYKRBFWD, 0,
1491     "get-k4-tgt",        XYKRBK5K4,0,
1492     "instance",          XYKRBINS, 0,
1493     "keytab",            XYKRBKTB, 0,
1494     "lifetime",          XYKRBLIF, 0,
1495     "no-addresses",      XYKRBNAD, 0,
1496     "principal",         XYKRBPR,  0,
1497     "prompt",            XYKRBPRM, 0,
1498     "proxiable",         XYKRBPRX, 0,
1499     "realm",             XYKRBRL,  0,
1500     "renewable",         XYKRBRNW, 0,
1501     "service-name",      XYKRBSRV, 0
1502 };
1503 static int nk5tab = sizeof(k5tab)/sizeof(struct keytab);
1504 
1505 #define KRB_PW_PRM 1
1506 #define KRB_PR_PRM 2
1507 
1508 static struct keytab krbprmtab[] = {
1509     "password",  KRB_PW_PRM, 0,
1510     "principal", KRB_PR_PRM, 0
1511 };
1512 
1513 #endif /* CK_KERBEROS */
1514 #ifdef CK_SRP
1515 static struct keytab srptab[] = {
1516     "prompt",            XYSRPPRM, 0
1517 };
1518 static int nsrptab = sizeof(srptab)/sizeof(struct keytab);
1519 #define SRP_PW_PRM 1
1520 
1521 static struct keytab srpprmtab[] = {
1522     "password",  SRP_PW_PRM, 0
1523 };
1524 #endif /* CK_SRP */
1525 #ifdef CK_SSL
1526 static struct keytab ssltab[] = {
1527     "certs-ok",          XYSSLCOK,  CM_INV,
1528     "cipher-list",       XYSSLCL,   0,
1529     "crl-dir",           XYSSLCRLD, 0,
1530     "crl-file",          XYSSLCRL,  0,
1531     "debug",             XYSSLDBG,  0,
1532     "dh-key-file",       XYSSLDKFL, CM_INV,
1533     "dh-param-file",     XYSSLDPFL, 0,
1534     "dsa-cert-chain-file", XYSSLDCCF, 0,
1535     "dsa-cert-file",     XYSSLDCFL, 0,
1536     "dsa-key-file",      XYSSLDKFL, 0,
1537     "dummy",             XYSSLDUM,  CM_INV,
1538     "only",              XYSSLON,   CM_INV,
1539     "random-file",       XYSSLRND,  0,
1540     "rsa-cert-chain-file", XYSSLRCCF, 0,
1541     "rsa-cert-file",     XYSSLRCFL, 0,
1542     "rsa-key-file",      XYSSLRKFL, 0,
1543     "verbose",           XYSSLVRB,  0,
1544     "verify",            XYSSLVRF,  0,
1545     "verify-dir",        XYSSLVRFD, 0,
1546     "verify-file",       XYSSLVRFF, 0
1547 };
1548 static int nssltab = sizeof(ssltab)/sizeof(struct keytab);
1549 static struct keytab sslvertab[] = {
1550     "fail-if-no-peer-cert", SSL_VERIFY_PEER |
1551                             SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0,
1552     "no",               SSL_VERIFY_NONE, 0,
1553     "none",             SSL_VERIFY_NONE, CM_INV,
1554     "off",              SSL_VERIFY_NONE, CM_INV,
1555     "on",               SSL_VERIFY_PEER, CM_INV,
1556     "peer-cert",        SSL_VERIFY_PEER, 0
1557 };
1558 static int nsslvertab = sizeof(sslvertab)/sizeof(struct keytab);
1559 #endif /* CK_SSL */
1560 #endif /* CK_AUTHENTICATION */
1561 #ifdef CK_ENCRYPTION
1562 int cx_type = CX_AUTO;
1563 extern int sl_cx_type;
1564 #endif /* CK_ENCRYPTION */
1565 extern char *tcp_address;
1566 #ifndef NOHTTP
1567 extern char * tcp_http_proxy;
1568 extern char * tcp_http_proxy_user;
1569 extern char * tcp_http_proxy_pwd;
1570 extern char * tcp_http_proxy_agent;
1571 #endif /* NOHTTP */
1572 #ifdef NT
1573 #ifdef CK_SOCKS
1574 extern char *tcp_socks_svr;
1575 extern char *tcp_socks_user;
1576 #ifdef CK_SOCKS_NS
1577 extern char *tcp_socks_ns;
1578 #endif /* CK_SOCKS_NS */
1579 #endif /* CK_SOCKS */
1580 #endif /* NT */
1581 
1582 #define UPW_USER  1
1583 #define UPW_PASS  2
1584 #define UPW_AGENT 3
1585 
1586 static struct keytab userpass[] = {
1587     { "/agent",   UPW_AGENT, CM_ARG },
1588     { "/password", UPW_PASS, CM_ARG },
1589     { "/user",     UPW_USER, CM_ARG },
1590 };
1591 static int nuserpass = sizeof(userpass)/sizeof(struct keytab);
1592 
1593 static struct keytab tnnegtab[] = {     /* TELNET NEGOTIATION table */
1594     "accepted",  TN_NG_AC, 0,
1595     "refused",   TN_NG_RF, 0,
1596     "req",       TN_NG_RQ, CM_INV|CM_ABR,
1597     "requ",      TN_NG_RQ, CM_INV|CM_ABR,
1598     "reque",     TN_NG_RQ, CM_INV|CM_ABR,
1599     "reques",    TN_NG_RQ, CM_INV|CM_ABR,
1600     "request",   TN_NG_RQ, CM_INV|CM_ABR,
1601     "requeste",  TN_NG_RQ, CM_INV|CM_ABR,
1602     "requested", TN_NG_RQ, 0,
1603     "required",  TN_NG_MU, 0
1604 };
1605 static int ntnnegtab = sizeof(tnnegtab)/sizeof(struct keytab);
1606 
1607 #ifdef CK_ENCRYPTION
1608 static struct keytab typkwd[] = {
1609     "/type", 0, CM_ARG
1610 };
1611 
1612 static struct keytab tnenctab[] = {     /* TELNET ENCRYPTION table */
1613     "accepted",   TN_NG_AC,    CM_INV,
1614     "refused",    TN_NG_RF,    CM_INV,
1615     "req",        TN_NG_RQ,    CM_INV|CM_ABR,
1616     "requ",       TN_NG_RQ,    CM_INV|CM_ABR,
1617     "reque",      TN_NG_RQ,    CM_INV|CM_ABR,
1618     "reques",     TN_NG_RQ,    CM_INV|CM_ABR,
1619     "request",    TN_NG_RQ,    CM_INV|CM_ABR,
1620     "requeste",   TN_NG_RQ,    CM_INV|CM_ABR,
1621     "requested",  TN_NG_RQ,    CM_INV,
1622     "required",   TN_NG_MU,    CM_INV,
1623     "start",      TN_EN_START, CM_INV,
1624     "stop",       TN_EN_STOP,  CM_INV,
1625     "type",       TN_EN_TYP,   0
1626 };
1627 static int ntnenc = sizeof(tnenctab)/sizeof(struct keytab) ;
1628 #endif /* CK_ENCRYPTION */
1629 
1630 #ifdef CK_FORWARD_X
1631 static struct keytab tnfwdxtab[] = {    /* TELNET FORWARD-X table */
1632     "no-encryption",    1,  CM_INV,
1633     "xauthority-file",  0,  0
1634 };
1635 static int ntnfwdx = sizeof(tnfwdxtab)/sizeof(struct keytab) ;
1636 #endif /* CK_FORWARD_X */
1637 
1638 static struct keytab tnbugtab[] = {     /* TELNET BUG table */
1639     "auth-krb5-des",         4, 0,
1640     "binary-me-means-u-too", 0, 0,
1641     "binary-u-means-me-too", 1, 0,
1642     "infinite-loop-check",   2, 0,
1643     "sb-implies-will-do",    3, 0
1644 };
1645 
1646 #ifdef CK_ENVIRONMENT
1647 static struct keytab tnenvtab[] = {     /* TELNET ENVIRONMENT table */
1648     "acct",     TN_ENV_ACCT,    0,
1649     "display",  TN_ENV_DISP,    0,
1650     "job",      TN_ENV_JOB,     0,
1651     "location", TN_ENV_LOC,     0,
1652     "off",      TN_ENV_OFF,     CM_INV,
1653     "on",       TN_ENV_ON,      CM_INV,
1654     "printer",  TN_ENV_PRNT,    0,
1655     "systemtype",TN_ENV_SYS,    0,
1656     "user",     TN_ENV_USR,     0,
1657     "uservar",  TN_ENV_UVAR,    0,
1658     "", 0, 0
1659 };
1660 static int ntnenv = sizeof(tnenvtab)/sizeof(struct keytab) - 1;
1661 #endif /* CK_ENVIRONMENT */
1662 
1663 #ifdef CK_AUTHENTICATION
1664 static struct keytab tnauthtab[] = {    /* TELNET AUTHENTICATION table */
1665     "accepted",   TN_NG_AC,  CM_INV,
1666     "encrypt-flag", TN_AU_ENC, 0,
1667     "forwarding", TN_AU_FWD,   0,
1668     "how-flag",   TN_AU_HOW,   0,
1669     "refused",    TN_NG_RF,  CM_INV,
1670     "req",        TN_NG_RQ,  CM_INV|CM_ABR,
1671     "requ",       TN_NG_RQ,  CM_INV|CM_ABR,
1672     "reque",      TN_NG_RQ,  CM_INV|CM_ABR,
1673     "reques",     TN_NG_RQ,  CM_INV|CM_ABR,
1674     "request",    TN_NG_RQ,  CM_INV|CM_ABR,
1675     "requeste",   TN_NG_RQ,  CM_INV|CM_ABR,
1676     "requested",  TN_NG_RQ,  CM_INV,
1677     "required",   TN_NG_MU,  CM_INV,
1678     "type",       TN_AU_TYP, 0
1679 };
1680 static int ntnauth = sizeof(tnauthtab)/sizeof(struct keytab) ;
1681 
1682 struct keytab autyptab[] = {    /* TELNET AUTHENTICATION TYPE table */
1683     "automatic",  AUTH_AUTO, 0,
1684 #ifdef CK_KERBEROS
1685     "k4",         AUTH_KRB4, CM_INV,
1686     "k5",         AUTH_KRB5, CM_INV,
1687     "kerberos4",  AUTH_KRB4, 0,
1688     "kerberos5",  AUTH_KRB5, 0,
1689     "kerberos_iv",AUTH_KRB4, CM_INV,
1690     "kerberos_v", AUTH_KRB5, CM_INV,
1691     "krb4",       AUTH_KRB4, CM_INV,
1692     "krb5",       AUTH_KRB5, CM_INV,
1693 #endif /* CK_KERBEROS */
1694     "none",       AUTH_NONE, 0,
1695 #ifdef NT
1696     "ntlm",       AUTH_NTLM, 0,
1697 #endif /* NT */
1698 #ifdef CK_SRP
1699     "srp",        AUTH_SRP,  0,
1700 #endif /* CK_SRP */
1701 #ifdef CK_SSL
1702     "ssl",        AUTH_SSL,  0,
1703 #endif /* CK_SSL */
1704     "", 0, 0
1705 };
1706 int nautyp = sizeof(autyptab)/sizeof(struct keytab) - 1;
1707 
1708 struct keytab auhowtab[] = {    /* TELNET AUTHENTICATION HOW table */
1709     "any",     TN_AUTH_HOW_ANY,     0,
1710     "mutual",  TN_AUTH_HOW_MUTUAL,  0,
1711     "one-way", TN_AUTH_HOW_ONE_WAY, 0,
1712     "", 0, 0
1713 };
1714 int nauhow = sizeof(auhowtab)/sizeof(struct keytab) - 1;
1715 
1716 struct keytab auenctab[] = {    /* TELNET AUTHENTICATION ENCRYPT table */
1717     "any",     TN_AUTH_ENC_ANY,     0,
1718     "none",    TN_AUTH_ENC_NONE,    0,
1719     "telopt",  TN_AUTH_ENC_TELOPT,  0,
1720 #ifdef CK_SSL
1721     "tls",     TN_AUTH_ENC_TLS,     0,
1722 #endif /* CK_SSL */
1723     "", 0, 0
1724 };
1725 int nauenc = sizeof(auenctab)/sizeof(struct keytab) - 1;
1726 #endif /* CK_AUTHENTICATION */
1727 
1728 #define TN_NL_BIN 3
1729 #define TN_NL_NVT 4
1730 static struct keytab tn_nlmtab[] = {    /* TELNET NEWLINE-MODE table */
1731     "binary-mode", TN_NL_BIN, 0,        /* Binary mode */
1732     "nvt",    TN_NL_NVT, 0,             /* NVT mode */
1733     "off",    TNL_CRNUL, CM_INV,        /* CR-NUL (TELNET spec) */
1734     "on",     TNL_CRLF,  CM_INV,        /* CR-LF (TELNET spec) */
1735     "raw",    TNL_CR,    CM_INV         /* CR only (out of spec) */
1736 };
1737 static int ntn_nlm = (sizeof(tn_nlmtab) / sizeof(struct keytab));
1738 
1739 static struct keytab tnlmtab[] = {      /* TELNET NEWLINE-MODE table */
1740     "cr",     TNL_CR,    CM_INV,        /* CR only (out of spec) */
1741     "cr-lf",  TNL_CRLF,  CM_INV,        /* CR-LF (TELNET spec) */
1742     "cr-nul", TNL_CRNUL, CM_INV,        /* CR-NUL (TELNET spec) */
1743     "lf",     TNL_LF,    CM_INV,        /* LF instead of CR-LF */
1744     "off",    TNL_CRNUL, 0,             /* CR-NUL (TELNET spec) */
1745     "on",     TNL_CRLF,  0,             /* CR-LF (TELNET spec) */
1746     "raw",    TNL_CR,    0              /* CR only (out of spec) */
1747 };
1748 static int ntnlm = (sizeof(tnlmtab) / sizeof(struct keytab));
1749 
1750 struct keytab tntab[] = {
1751 #ifdef CK_AUTHENTICATION
1752     "authentication",       CK_TN_AU,  0,
1753 #endif /* CK_AUTHENTICATION */
1754     "b",                    CK_TN_BM,  CM_INV|CM_ABR,
1755     "bi",                   CK_TN_BM,  CM_INV|CM_ABR,
1756     "bin",                  CK_TN_BM,  CM_INV|CM_ABR,
1757     "bina",                 CK_TN_BM,  CM_INV|CM_ABR,
1758     "binar",                CK_TN_BM,  CM_INV|CM_ABR,
1759     "binary",               CK_TN_BM,  CM_INV|CM_ABR,
1760     "binary-",              CK_TN_BM,  CM_INV|CM_ABR,
1761     "binary-mode",          CK_TN_BM,  CM_INV,
1762     "binary-transfer-mode", CK_TN_XF,  0,
1763     "binary-xfer-mode",     CK_TN_XF,  CM_INV,
1764     "bug",                  CK_TN_BUG, 0,
1765     "debug",                CK_TN_DB,  0,
1766     "delay-sb",             CK_TN_DL,  0,
1767     "echo",                 CK_TN_EC,  0,
1768 #ifdef CK_ENCRYPTION
1769     "encryption",      CK_TN_ENC,  0,
1770 #endif /* CK_ENCRYPTION */
1771 #ifdef CK_ENVIRONMENT
1772     "environment",     CK_TN_ENV,  0,
1773 #endif /* CK_ENVIRONMENT */
1774 #ifdef CK_FORWARD_X
1775     "forward-x",       CK_TN_FX,   0,
1776 #endif /* CK_FORWARD_X */
1777 #ifdef IKS_OPTION
1778     "kermit",          CK_TN_IKS,  CM_INV,
1779 #endif /* IKS_OPTION */
1780 #ifdef CK_SNDLOC
1781     "location",        CK_TN_LOC,  0,
1782 #endif /* CK_SNDLOC */
1783 #ifdef CK_NAWS
1784     "naws",            CK_TN_NAWS, CM_INV,
1785 #endif /* CK_NAWS */
1786     "newline-mode",    CK_TN_NL,   0,
1787     "no-encrypt-during-xfer", CK_TN_NE, CM_INV,
1788     "prompt-for-userid",CK_TN_PUID,0,
1789     "remote-echo",     CK_TN_RE,   0,
1790 #ifdef CK_SSL
1791     "start-tls",       CK_TN_TLS,  CM_INV,
1792 #endif /* CK_SSL */
1793 #ifdef NT
1794     "sfu-compatibility", CK_TN_SFU, 0,
1795 #else
1796     "sfu-compatibility", CK_TN_SFU, CM_INV,
1797 #endif /* NT */
1798     "terminal-type",   CK_TN_TT,   0,
1799     "wait-for-negotiations", CK_TN_WAIT, 0,
1800 #ifdef CK_ENVIRONMENT
1801     "xdisplay-location",CK_TN_XD, CM_INV,
1802 #endif /* CK_ENVIRONMENT */
1803     "", 0, 0
1804 };
1805 int ntn = (sizeof(tntab) / sizeof(struct keytab)) - 1;
1806 
1807 struct keytab tnopttab[] = {
1808 #ifdef CK_AUTHENTICATION
1809     "authentication",  CK_TN_AU,   0,
1810 #else
1811     "authentication",  CK_TN_AU,   CM_INV,
1812 #endif /* CK_AUTHENTICATION */
1813     "binary-mode",     CK_TN_BM,   0,
1814 #ifdef TN_COMPORT
1815     "c",               CK_TN_CPC,   CM_INV|CM_ABR,
1816     "co",              CK_TN_CPC,   CM_INV|CM_ABR,
1817     "com",             CK_TN_CPC,   CM_INV|CM_ABR,
1818     "com-port-control",CK_TN_CPC,   0,
1819     "comport-control", CK_TN_CPC,   CM_INV,
1820 #else /* TN_COMPORT */
1821     "com-port-control",CK_TN_CPC,  CM_INV,
1822     "comport-control", CK_TN_CPC,   CM_INV,
1823 #endif /* TN_COMPORT */
1824     "echo",            CK_TN_EC,   0,
1825 #ifdef CK_ENCRYPTION
1826     "encryption",      CK_TN_ENC,  0,
1827 #else
1828     "encryption",      CK_TN_ENC,  CM_INV,
1829 #endif /* CK_ENCRYPTION */
1830 #ifdef CK_FORWARD_X
1831     "forward-x",       CK_TN_FX,   0,
1832 #else /* CK_FORWARD_X */
1833     "forward-x",       CK_TN_FX,   CM_INV,
1834 #endif /* CK_FORWARD_X */
1835     "ibm-sak",         CK_TN_SAK,  CM_INV,
1836 #ifdef IKS_OPTION
1837     "kermit",          CK_TN_IKS,  0,
1838 #else
1839     "kermit",          CK_TN_IKS,  CM_INV,
1840 #endif /* IKS_OPTION */
1841     "lflow",           CK_TN_FLW,  CM_INV,
1842     "logout",          CK_TN_LOG,  0,
1843 #ifdef CK_NAWS
1844     "naws",            CK_TN_NAWS, 0,
1845 #else
1846     "naws",            CK_TN_NAWS, CM_INV,
1847 #endif /* CK_NAWS */
1848 #ifdef CK_ENVIRONMENT
1849     "new-environment", CK_TN_ENV,  0,
1850 #else
1851     "new-environment", CK_TN_ENV,  CM_INV,
1852 #endif /* CK_ENVIRONMENT */
1853     "pragma-heartbeat",CK_TN_PHR,  CM_INV,
1854     "pragma-logon",    CK_TN_PLG,  CM_INV,
1855     "pragma-sspi",     CK_TN_PSP,  CM_INV,
1856     "sak",             CK_TN_SAK,  CM_INV,
1857 #ifdef CK_SNDLOC
1858     "send-location",   CK_TN_LOC,  0,
1859 #else
1860     "send-location",   CK_TN_LOC,  CM_INV,
1861 #endif /* CK_SNDLOC */
1862     "sga",             CK_TN_SGA, CM_INV|CM_ABR,
1863 #ifdef CK_SSL
1864     "start-tls",       CK_TN_TLS,  0,
1865 #else
1866     "start-tls",       CK_TN_TLS,  CM_INV,
1867 #endif /* CK_SSL */
1868     "suppress-go-aheads", CK_TN_SGA, 0,
1869     "terminal-type",   CK_TN_TT,   0,
1870     "ttype",           CK_TN_TT,   CM_INV|CM_ABR,
1871 #ifdef CK_ENVIRONMENT
1872     "xdisplay-location", CK_TN_XD, 0,
1873 #else
1874     "xdisplay-location", CK_TN_XD, CM_INV,
1875 #endif /* CK_ENVIRONMENT */
1876     "", 0, 0
1877 };
1878 int ntnopt = (sizeof(tnopttab) / sizeof(struct keytab)) - 1;
1879 
1880 struct keytab tnoptsw[] = {
1881     "/client",  CK_TN_CLIENT,   0,
1882     "/server",  CK_TN_SERVER,   0
1883 };
1884 int ntnoptsw = (sizeof(tnoptsw) / sizeof(struct keytab));
1885 #endif /* TNCODE */
1886 
1887 struct keytab ftrtab[] = {              /* Feature table */
1888 #ifndef NOCSETS                         /* 0 = we have it, 1 = we don't */
1889 "character-sets",       0, 0,
1890 #else
1891 "character-sets",       1, 0,
1892 #endif /* NOCSETS */
1893 #ifndef NOCYRIL
1894 "cyrillic",             0, 0,
1895 #else
1896 "cyrillic",             1, 0,
1897 #endif /* NOCYRIL */
1898 
1899 #ifndef NOLOGDIAL
1900 "cx-log",               0, 0,
1901 #else
1902 "cx-log",               1, 0,
1903 #endif /* NOLOGDIAL */
1904 
1905 #ifndef NODEBUG
1906 "debug",                0, 0,
1907 #else
1908 "debug",                1, 0,
1909 #endif /* NODEBUG */
1910 
1911 #ifndef NODIAL
1912 "dial",                 0, 0,
1913 #else
1914 "dial",                 1, 0,
1915 #endif /* NODIAL */
1916 
1917 #ifdef DYNAMIC
1918 "dynamic-memory",       0, 0,
1919 #else
1920 "dynamic-memory",       1, 0,
1921 #endif /* DYNAMIC */
1922 
1923 #ifndef NOXFER
1924 "file-transfer",        0, 0,
1925 #else
1926 "file-transfer",        1, 0,
1927 #endif /* NOXFER */
1928 
1929 #ifdef XXFWD
1930 "forward",              0, 0,
1931 #else
1932 "forward",              1, 0,
1933 #endif /* XXFWD */
1934 
1935 #ifdef NEWFTP
1936 "ftp",                  0, 0,
1937 #else
1938 "ftp",                  1, 0,
1939 #endif /* NEWFTP */
1940 
1941 #ifdef CK_CURSES
1942 "fullscreen-display",   0, 0,
1943 #else
1944 "fullscreen-display",   1, 0,
1945 #endif /* CK_CURSES */
1946 #ifdef GREEK
1947 "greek",                0, 0,
1948 #else
1949 "greek",                1, 0,
1950 #endif /* GREEK */
1951 #ifdef HEBREW
1952 "hebrew",               0, 0,
1953 #else
1954 "hebrew",               1, 0,
1955 #endif /* HEBREW */
1956 #ifndef NOHELP
1957 "help",                 0, 0,
1958 #else
1959 "help",                 1, 0,
1960 #endif /* NOHELP */
1961 
1962 #ifndef NOIKSD
1963 "iksd",                 0, 0,
1964 #else
1965 "iksd",                 1, 0,
1966 #endif /* NOIKSD */
1967 
1968 #ifndef NOSPL
1969 "if-command",           0, 0,
1970 #else
1971 "if-command",           1, 0,
1972 #endif /* NOSPL */
1973 #ifndef NOJC
1974 #ifdef UNIX
1975 "job-control",          0, 0,
1976 #else
1977 "job-control",          1, 0,
1978 #endif /* UNIX */
1979 #else
1980 "job-control",          1, 0,
1981 #endif /* NOJC */
1982 #ifdef KANJI
1983 "kanji",                0, 0,
1984 #else
1985 "kanji",                1, 0,
1986 #endif /* KANJI */
1987 
1988 #ifndef NOXFER
1989 "kermit",               0, 0,
1990 #else
1991 "kermit",               1, 0,
1992 #endif /* NOXFER */
1993 
1994 #ifdef CK_KERBEROS
1995 "kerberos",             0, 0,
1996 #else
1997 "kerberos",             1, 0,
1998 #endif /* CK_KERBEROS */
1999 
2000 #ifndef NOCSETS
2001 "latin1",               0, 0,
2002 #else
2003 "latin1",               1, 0,
2004 #endif /* NOCSETS */
2005 #ifdef LATIN2
2006 "latin2",               0, 0,
2007 #else
2008 "latin2",               1, 0,
2009 #endif /* LATIN2 */
2010 
2011 #ifdef CKLEARN
2012 "learned-scripts",      0, 0,
2013 #else
2014 "learned-scripts",      1, 0,
2015 #endif /* CKLEARN */
2016 
2017 #ifdef HAVE_LOCALE
2018 "locale",               0, 0,
2019 #else
2020 "locale",               1, 0,
2021 #endif /* HAVE_LOCALE */
2022 
2023 #ifndef NOLOCAL
2024 "making-connections",   0, 0,
2025 #else
2026 "making-connections",   1, 0,
2027 #endif /* NOLOCAL */
2028 
2029 #ifdef NETCONN
2030 "network",              0, 0,
2031 #else
2032 "network",              1, 0,
2033 #endif /* NETCONN */
2034 
2035 #ifdef NT
2036 #ifdef CK_AUTHENTICATION
2037 "ntlm",                 1, 0,
2038 #else /* CK_AUTHENTICATION */
2039 "ntlm",                 0, 0,
2040 #endif /* CK_AUTHENTICATION */
2041 #else /* NT */
2042 "ntlm",                 0, 0,
2043 #endif /* NT */
2044 
2045 #ifdef PIPESEND
2046 "pipes",                0, 0,
2047 #else
2048 #ifdef NETCMD
2049 "pipes",                0, 0,
2050 #endif /* NETCMD */
2051 #endif /* PIPESEND */
2052 #ifndef PIPESEND
2053 #ifndef NETCMD
2054 "pipes",                1, 0,
2055 #endif /* PIPESEND */
2056 #endif /* NETCMD */
2057 
2058 #ifdef NETPTY
2059 "pty",                  0, 0,
2060 #else
2061 "pty",                  1, 0,
2062 #endif /* NETPTY */
2063 
2064 #ifndef NOPUSH
2065 "push",                 0, 0,
2066 #else
2067 "push",                 1, 0,
2068 #endif /* PUSH */
2069 
2070 #ifdef CK_REDIR
2071 "redirect",             0, 0,
2072 #else
2073 "redirect",             1, 0,
2074 #endif /* CK_REDIR */
2075 
2076 #ifdef CK_RTSCTS
2077 "rts/cts",              0, 0,
2078 #else
2079 "rts/cts",              1, 0,
2080 #endif /* RTS/CTS */
2081 
2082 #ifndef NOSCRIPT
2083 "script-command",       0, 0,
2084 #else
2085 "script-command",       1, 0,
2086 #endif /* NOSCRIPT */
2087 #ifndef NOSERVER
2088 "server-mode",          0, 0,
2089 #else
2090 "server-mode",          1, 0,
2091 #endif /* NOSERVER */
2092 
2093 #ifndef NOSEXP
2094 "sexpression",          0, 0,
2095 #else
2096 "sexpression",          1, 0,
2097 #endif /* NOSEXP */
2098 
2099 #ifdef SFTP_BUILTIN
2100 "sftp",                 1, 0,
2101 #else
2102 "sftp",                 0, 0,
2103 #endif /* SFTP_BUILTIN */
2104 
2105 #ifndef NOSHOW
2106 "show-command",         0, 0,
2107 #else
2108 "show-command",         1, 0,
2109 #endif /* NOSHOW */
2110 
2111 #ifdef CK_SRP
2112 "srp",                  0, 0,
2113 #else
2114 "srp",                  1, 0,
2115 #endif /* CK_SRP */
2116 
2117 #ifdef SSHBUILTIN
2118 "ssh",                  0, 0,
2119 #else /* SSHBUILTIN */
2120 "ssh",                  1, 0,
2121 #endif /* SSHBUILTIN */
2122 
2123 #ifdef CK_SSL
2124 "ssl/tls",              0, 0,
2125 #else
2126 "ssl/tls",              1, 0,
2127 #endif /* CK_SSL */
2128 
2129 #ifndef NOXMIT
2130 "transmit",             0, 0,
2131 #else
2132 "transmit",             1, 0,
2133 #endif /* NOXMIT */
2134 
2135 #ifdef UNICODE
2136 "unicode",              0, 0,
2137 #else
2138 "unicode",              1, 0,
2139 #endif /* UNICODE */
2140 
2141 #ifdef CK_XYZ
2142 "xyzmodem",             0, 0,
2143 #else
2144 "xyzmodem",             1, 0,
2145 #endif /* CK_XYZ */
2146 
2147 "", 0, 0
2148 };
2149 int nftr = (sizeof(ftrtab) / sizeof(struct keytab)) - 1;
2150 
2151 struct keytab desttab[] = {             /* SET DESTINATION */
2152 #ifdef CALIBRATE
2153     "calibrate", DEST_N, CM_INV,
2154 #endif /* CALIBRATE */
2155     "disk",    DEST_D, 0,
2156 #ifdef CALIBRATE
2157     "nowhere", DEST_N, 0,
2158 #endif /* CALIBRATE */
2159     "printer", DEST_P, 0,
2160     "screen",  DEST_S, 0
2161 };
2162 int ndests =  (sizeof(desttab) / sizeof(struct keytab));
2163 
2164 #ifndef NOSPL           /* Used only with script programming items... */
2165 
2166 #ifndef NOSERVER                        /* This is just to avoid some */
2167 #define CK_PARSDIR                      /* "statement not reached" */
2168 #else                                   /* complaints... */
2169 #ifndef NODIAL
2170 #define CK_PARSDIR
2171 #endif /* NODIAL */
2172 #endif /* NOSERVER */
2173 
2174 /*
2175   cx == 0 means dial directory
2176   cx == 1 means network directory
2177   cx == 2 means a directory path list
2178 */
2179 static int
parsdir(cx)2180 parsdir(cx) int cx; {
2181     int i, x, y, dd;                    /* Workers */
2182     int nxdir;
2183     char *s;
2184     char ** xdir;
2185     char *pp[MAXGETPATH];               /* Temporary name pointers */
2186 #ifdef ZFNQFP
2187     struct zfnfp * fnp;
2188 #ifdef OS2
2189     char * env;
2190     char dirpath[4096];
2191 #else /* OS2 */
2192     char dirpath[1024];                 /* For fully qualified filenames */
2193 #endif /* OS2 */
2194 #endif /* ZFNQFP */
2195 
2196     int max = 0;                        /* Maximum number of things to parse */
2197     char c;
2198 
2199 #ifndef NODIAL
2200     if (cx == 0) {                      /* Dialing */
2201         nxdir = ndialdir;
2202         xdir = dialdir;
2203         max = MAXDDIR;
2204     } else
2205 #ifdef NETCONN
2206     if (cx == 1) {                      /* Network */
2207         nxdir = nnetdir;
2208         xdir = netdir;
2209         max = MAXDDIR;
2210     } else
2211 #endif /* NETCONN */
2212 #endif /* NODIAL */
2213 #ifndef NOSERVER
2214     if (cx == 2) {                      /* GET path */
2215         nxdir = ngetpath;
2216         xdir = getpath;
2217         max = MAXGETPATH;
2218     } else                              /* Called with invalid function code */
2219 #endif /* NOSERVER */
2220       return(-2);
2221 
2222     for (i = 0; i < MAXGETPATH; i++)    /* Init these. */
2223       pp[i] = NULL;
2224 
2225 #ifdef CK_PARSDIR
2226     dd = 0;                             /* Temporary name counter */
2227     while (1) {
2228         if (cx != 2) {                  /* Dialing or Network Directory */
2229 #ifdef OS2
2230             int len;
2231             char * appdata0 = NULL, * appdata1 = NULL;
2232 #ifdef NT
2233             env = getenv("K95PHONES");
2234             makestr(&appdata0,(char *)GetAppData(0));
2235             makestr(&appdata1,(char *)GetAppData(1));
2236 #else /* NT */
2237             env = getenv("K2PHONES");
2238 #endif /* NT */
2239             if (!env)
2240               env = getenv("K95PHONES");
2241             if (!env)
2242               env = "";
2243 
2244             dirpath[0] = '\0';
2245             len = strlen(env) + 2*strlen(startupdir) + 2*strlen(inidir)
2246                 + (appdata0?2*strlen(appdata0):0)
2247                 + (appdata1?2*strlen(appdata1):0)
2248                 + 2*strlen(zhome()) + 2*strlen(exedir) + 8*strlen("PHONES/")
2249                 + 12;
2250             if (len < 4096)             /* SAFE */
2251               sprintf(dirpath,
2252                     "%s%s%s;%s%s;%s%s%s%s%s%s%s%s%s;%s%s;%s;%s%s",
2253                     /* Semicolon-separated path list */
2254                     env,
2255                     (env[0] && env[strlen(env)-1] == ';') ? "" : ";",
2256                     startupdir,
2257                     startupdir, "PHONES/",
2258                     appdata1 ? appdata1 : "",
2259                     appdata1 ? "Kermit 95;" : "",
2260                     appdata1 ? appdata1 : "",
2261                     appdata1 ? "Kermit 95/PHONES/;" : "",
2262                     appdata0 ? appdata0 : "",
2263                     appdata0 ? "Kermit 95;" : "",
2264                     appdata0 ? appdata0 : "",
2265                     appdata0 ? "Kermit 95/PHONES/;" : "",
2266                     inidir,
2267                     inidir, "PHONES/",
2268                     zhome(),
2269                     zhome(), "PHONES/",
2270                     exedir,
2271                     exedir, "PHONES/"
2272                     );
2273 #ifdef NT
2274             makestr(&appdata0,NULL);
2275             makestr(&appdata1,NULL);
2276 #endif /* NT */
2277 #else
2278 #ifdef UNIX
2279             y = 1024;
2280             s = dirpath;
2281             zzstring("\\v(home)",&s,&y);
2282 #endif /* UNIX */
2283 #endif /* OS2 */
2284             y = cmifip(
2285                   "Names of one or more directory files, separated by spaces",
2286                        "",&s,&x,0,
2287 #ifdef OS2ORUNIX
2288                        dirpath,
2289 #else
2290                        NULL,
2291 #endif /* OS2ORUNIX */
2292                        xxstring
2293                        );
2294         } else {                        /* List of directory names */
2295             x = 0;
2296             y = cmdir("Directory name","",&s,xxstring);
2297         }
2298         if (y < 0) {
2299             if (y == -3) {              /* EOL or user typed <CR> */
2300                 if ((y = cmcfm()) < 0) return(y);
2301                 for (i = 0; i < max; i++) { /* Clear these */
2302                     if (i < nxdir && xdir[i]) {
2303                         free(xdir[i]);
2304                     }
2305                     xdir[i] = (i < dd) ? pp[i] : NULL;
2306                 }
2307 #ifndef NODIAL
2308                 if (cx == 0)
2309                   ndialdir = dd;
2310 #ifdef NETCONN
2311                 if (cx == 1)
2312                   nnetdir = dd;
2313 #endif /* NETCONN */
2314 #endif /* NODIAL */
2315 #ifndef NOSERVER
2316                 if (cx == 2)
2317                   ngetpath = dd;
2318 #endif /* NOSERVER */
2319                 return(success = 1);
2320 
2321             } else {                    /* Parse error */
2322                 for (i = 0; i < dd; i++) {  /* Free temp storage */
2323                     if (pp[i]) free(pp[i]); /* but don't change */
2324                     pp[i] = NULL;           /* anything else */
2325                 }
2326                 return(y);
2327             }
2328         }
2329         if (x) {
2330             printf("?Wildcards not allowed\n");
2331             return(-9);
2332         }
2333 #ifdef CK_TMPDIR
2334         if (cx == 2 && !isdir(s)) {
2335             printf("?Not a directory - %s\n", s);
2336             return(-9);
2337         }
2338 #endif /* CK_TMPDIR */
2339 
2340 #ifdef ZFNQFP
2341         if (cx < 2) {
2342             if (!isabsolute(s)) {       /* If not relative get full path */
2343                 if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
2344                     if (fnp->fpath)
2345                       if ((int) strlen(fnp->fpath) > 0)
2346                         s = fnp->fpath;
2347                 }
2348             }
2349         }
2350 #endif /* ZFNQFP */
2351         c = NUL;
2352         x = strlen(s);
2353         if (x > 0)                      /* Get last char */
2354           c = s[x-1];
2355         debug(F000,"parsdir s",s,c);
2356         if ((pp[dd] = malloc(strlen(s)+2)) == NULL) {
2357             printf("?Internal error - malloc\n");
2358             for (i = 0; i < dd; i++) {  /* Free temp storage */
2359                 if (pp[i]) free(pp[i]);
2360                 pp[i] = NULL;
2361             }
2362             return(-9);
2363         } else {                        /* Have storage for name */
2364             strcpy(pp[dd],s);           /* Copy string into new storage */
2365             debug(F111,"parsdir pp[dd] 1",pp[dd],dd);
2366 #ifndef NOXFER
2367             if (cx == 2) {              /* If we are parsing directories */
2368                 char dirsep[2];
2369                 extern int myindex;     /* Append directory separator if */
2370                 extern struct sysdata sysidlist[]; /* it is missing...   */
2371                 debug(F101,"parsdir myindex","",myindex);
2372                 if (myindex > -1)
2373                   if (sysidlist[myindex].sid_unixlike)
2374                     if (c != sysidlist[myindex].sid_dirsep) {
2375                         dirsep[0] = sysidlist[myindex].sid_dirsep;
2376                         dirsep[1] = NUL;
2377                         strcat(pp[dd], (char *) dirsep); /* safe */
2378                     }
2379             }
2380 #endif /* NOXFER */
2381             debug(F111,"parsdir pp[dd] 2",pp[dd],dd);
2382             if (++dd > max) {
2383                 printf("?Too many directories - %d max\n", max);
2384                 for (i = 0; i < dd; i++) {  /* Free temp storage */
2385                     if (pp[i]) free(pp[i]);
2386                     pp[i] = NULL;
2387                 }
2388             }
2389         }
2390     }
2391 #endif /* CK_PARSDIR */
2392 }
2393 #endif /* NOSPL */
2394 
2395 #ifndef NOSERVER
2396 static int
cklogin()2397 cklogin() {
2398     int x;
2399     char * s;
2400     char username[LOGINLEN+1];
2401     char password[LOGINLEN+1];
2402     char account[LOGINLEN+1];
2403     extern char * x_user, * x_passwd, * x_acct;
2404     extern int x_login, x_logged;
2405 
2406     username[0] = NUL;
2407     password[0] = NUL;
2408     account[0]  = NUL;
2409 
2410     x = cmfld("username", "", &s, xxstring);
2411     if (x != -3) {
2412         if (x < 0)
2413           return(x);
2414         if ((int)strlen(s) > LOGINLEN) {
2415             printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2416             return(-9);
2417         }
2418         ckstrncpy(username,s,LOGINLEN+1);
2419         x = cmfld("password", "", &s, xxstring);
2420         if (x != -3) {
2421             if (x < 0)
2422               return(x);
2423             if ((int)strlen(s) > LOGINLEN) {
2424                 printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2425                 return(-9);
2426             }
2427             ckstrncpy(password,s,LOGINLEN+1);
2428             x = cmfld("account", "", &s, xxstring);
2429             if (x != -3) {
2430                 if (x < 0)
2431                   return(x);
2432                 if ((int)strlen(s) > LOGINLEN) {
2433                     printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2434                     return(-9);
2435                 }
2436                 ckstrncpy(account,s,LOGINLEN+1);
2437                 if ((x = cmcfm()) < 0)
2438                   return(x);
2439             }
2440         }
2441     }
2442     makestr(&x_user,username);
2443     makestr(&x_passwd,password);
2444     makestr(&x_acct,account);
2445     x_login = (x_user) ? 1 : 0;
2446     x_logged = 0;
2447     return(1);
2448 }
2449 #endif /* NOSERVER */
2450 
2451 #ifndef NOLOCAL
2452 static int
setdcd()2453 setdcd() {
2454     int x, y, z = 0;
2455     if ((y = cmkey(crrtab,ncrr,"","automatic",xxstring)) < 0) return(y);
2456     if (y == CAR_ON) {
2457         x = cmnum("Carrier wait timeout, seconds","0",10,&z,xxstring);
2458         if (x < 0) return(x);
2459     }
2460     if ((x = cmcfm()) < 0) return(x);
2461     carrier = ttscarr(y);
2462     cdtimo = z;
2463     return(1);
2464 }
2465 #endif /* NOLOCAL */
2466 
2467 extern struct keytab yesno[];
2468 extern int nyesno;
2469 
2470 /* g e t y e s n o  */
2471 
2472 static struct keytab q0yesno[] = {      /* Yes/No/Quit keyword table */
2473     "no",    0, 0,
2474     "ok",    1, 0,
2475     "yes",   1, 0
2476 };
2477 static int nq0yesno = (sizeof(q0yesno) / sizeof(struct keytab));
2478 
2479 static struct keytab q1yesno[] = {      /* Yes/No/Quit keyword table */
2480     "no",    0, 0,
2481     "ok",    1, 0,
2482     "quit",  2, 0,
2483     "yes",   1, 0
2484 };
2485 static int nq1yesno = (sizeof(q1yesno) / sizeof(struct keytab));
2486 
2487 static struct keytab q2yesno[] = {      /* Yes/No/Quit keyword table */
2488     "go",    3, 0,
2489     "no",    0, 0,
2490     "ok",    1, 0,
2491     "yes",   1, 0
2492 };
2493 static int nq2yesno = (sizeof(q2yesno) / sizeof(struct keytab));
2494 
2495 static struct keytab q3yesno[] = {      /* Yes/No/Quit keyword table */
2496     "go",    3, 0,
2497     "no",    0, 0,
2498     "ok",    1, 0,
2499     "quit",  2, 0,
2500     "yes",   1, 0
2501 };
2502 static int nq3yesno = (sizeof(q3yesno) / sizeof(struct keytab));
2503 
2504 
2505 /* Ask question, get yes/no answer */
2506 
2507 int
getyesno(msg,flags)2508 getyesno(msg, flags) char * msg; int flags; {
2509 #ifdef CK_RECALL
2510     extern int on_recall;               /* around Password prompting */
2511 #endif /* CK_RECALL */
2512     int y, z;
2513 
2514 #ifndef NOLOCAL
2515 #ifdef OS2
2516     extern BYTE vmode;
2517     extern int win95_popup, startflags;
2518     int vmode_sav = vmode;
2519 #endif /* OS2 */
2520 #endif /* NOLOCAL */
2521 
2522 #ifdef CK_APC
2523     if ( apcactive != APC_INACTIVE && (apcstatus & APC_NOINP) ) {
2524         return(success = 0);
2525     }
2526 #endif /* CK_APC */
2527 
2528 #ifndef NOLOCAL
2529 #ifdef OS2
2530 #ifdef COMMENT
2531     if (win95_popup && !(startflags & 96)
2532 #ifdef IKSD
2533         && !inserver
2534 #endif /* IKSD */
2535         )
2536       return(popup_readyesno(vmode,NULL,msg,flags));
2537 #endif /* COMMENT */
2538     if (vmode == VTERM) {
2539         vmode = VCMD;
2540         VscrnIsDirty(VTERM);
2541         VscrnIsDirty(VCMD);
2542     }
2543 #endif /* OS2 */
2544 #endif /* NOLOCAL */
2545 #ifdef VMS
2546 /*
2547   In VMS, whenever a TAKE file or macro is active, we restore the
2548   original console modes so Ctrl-C/Ctrl-Y can work.  But here we
2549   go interactive again, so we have to temporarily put them back.
2550 */
2551     if (!xcmdsrc)
2552       concb((char)escape);
2553 #endif /* VMS */
2554 
2555 #ifdef CK_RECALL
2556     on_recall = 0;
2557 #endif /* CK_RECALL */
2558     cmsavp(psave,PROMPTL);              /* Save old prompt */
2559     cmsetp(msg);                        /* Make new prompt */
2560     z = 0;                              /* Initialize answer to No. */
2561     cmini(ckxech);                      /* Initialize parser. */
2562     do {
2563         prompt(NULL);                   /* Issue prompt. */
2564         switch (flags) {
2565           case 0:  y = cmkey(q0yesno,nq0yesno,"","",NULL); break;
2566           case 1:  y = cmkey(q1yesno,nq1yesno,"","",NULL); break;
2567           case 2:  y = cmkey(q2yesno,nq2yesno,"","",NULL); break;
2568           default: y = cmkey(q3yesno,nq3yesno,"","",NULL);
2569         }
2570         if (y < 0) {
2571             if (y == -4) {              /* EOF */
2572                 z = y;
2573                 break;
2574             } else if (y == -3)         /* No answer? */
2575               printf(" Please respond; type '?' to see valid answers.\n");
2576             cmini(ckxech);
2577         } else {
2578             z = y;                      /* Save answer */
2579             y = cmcfm();                /* Get confirmation */
2580         }
2581     } while (y < 0);                    /* Continue till done */
2582     cmsetp(psave);                      /* Restore real prompt */
2583 #ifdef VMS
2584     if (cmdlvl > 0)                     /* In VMS and not at top level, */
2585       conres();                         /*  restore console again. */
2586 #endif /* VMS */
2587 #ifndef NOLOCAL
2588 #ifdef OS2
2589     if (vmode != vmode_sav) {
2590         vmode = VTERM;
2591         VscrnIsDirty(VCMD);
2592         VscrnIsDirty(VTERM);
2593     }
2594 #endif /* OS2 */
2595 #endif /* NOLOCAL */
2596     return(z);
2597 }
2598 
2599 #ifdef KUI
2600 extern HWND hwndConsole;
2601 _PROTOTYP(int gui_txt_dialog,(char *,char *,int,char *,int,char *,int));
2602 _PROTOTYP(int gui_mtxt_dialog,(char *,int,struct txtbox []));
2603 _PROTOTYP(int gui_position,(int, int));
2604 _PROTOTYP(int gui_resize_mode,(int));
2605 _PROTOTYP(int gui_win_run_mode,(int));
2606 _PROTOTYP(int gui_saveas_dialog,(char *,char *, int, char *, char *, int));
2607 extern int gui_dialog;
2608 #endif /* KUI */
2609 
2610 /* u q _ o k  --  User Query, get Yes/No or OK Cancel  */
2611 /*
2612   Call with:
2613     preface: Explanatory text to print, or NULL.
2614     prompt:  Prompt.
2615     mask:    Bitmask for legal responses: 1 = OK or Yes; 2 = No or Cancel.
2616     help:    Help text (array of strings or NULL) [not used by parser].
2617     dflt:    Default response (1 or 2) [not used by parser].
2618   Returns:
2619    -1:       Invalid argument(s).
2620     0:       User said No or Cancel.
2621     1        User said Yes or OK.
2622   Notes:
2623     preface and prompt should not include final line terminator but may
2624     include embedded ones.  Help text is in case GUI dialog needs a Help
2625     button; final element of help-string array is "".  dflt is used by GUI
2626     to highlight the default response button.
2627 */
2628 int
2629 #ifdef CK_ANSIC
uq_ok(char * preface,char * prompt,int mask,char ** help,int dflt)2630 uq_ok(char * preface, char * prompt, int mask,char ** help, int dflt)
2631 #else /* CK_ANSIC */
2632 uq_ok(preface,prompt,mask,help,dflt)
2633     char * preface, * prompt, ** help;
2634     int mask, dflt;
2635 #endif /* CK_ANSIC */
2636 /* uq_ok */ {
2637     int rc, len;
2638     char * text=NULL;
2639 
2640     if (!prompt)
2641       return(-1);
2642 
2643     if ((mask & 3) == 1) {		/* OK (GUI only) */
2644 #ifdef KUI
2645       if ( gui_dialog ) {
2646 	/* This one is for popup help, alerts, etc */
2647         if (preface) {
2648             len = strlen(preface) + strlen(prompt) + 4;
2649             text = (char *)malloc(len);
2650             ckmakmsg(text,len,preface,"\n",prompt,NULL);
2651         }
2652         rc = MessageBox(hwndConsole,
2653                          text ? text : prompt,
2654                          prompt,
2655                          MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2656         ShowWindowAsync(hwndConsole,SW_SHOWNORMAL);
2657         SetForegroundWindow(hwndConsole);
2658         if (text)
2659 	  free(text);
2660         if (!rc)
2661 	  return(-1);
2662         else
2663 	  return(1);
2664       } else
2665 #endif  /* KUI */
2666       {
2667 	if (preface)			/* Just display the text, if any */
2668 	  printf("%s\n",preface);
2669 	if (prompt)
2670 	  printf("%s\n",prompt);
2671         return(1);
2672       }
2673     } else if ((mask & 3) == 3) {	/* Yes/No or OK/Cancel */
2674 #ifdef KUI
2675       if ( gui_dialog ) {
2676         if (preface) {
2677             len = strlen(preface) + strlen(prompt) + 4;
2678             text = (char *)malloc(len);
2679             ckmakmsg(text,len,preface,"\n",prompt,NULL);
2680         }
2681         rc = MessageBox(hwndConsole,
2682                          text ? text : prompt,
2683                          prompt,
2684                          MB_YESNO | MB_ICONINFORMATION | MB_TASKMODAL |
2685                          (dflt == 2 ? MB_DEFBUTTON2 : MB_DEFBUTTON1));
2686         ShowWindowAsync(hwndConsole,SW_SHOWNORMAL);
2687         SetForegroundWindow(hwndConsole);
2688         if (text)
2689 	  free(text);
2690         if (!rc)
2691 	  return(-1);
2692         else if (rc == IDNO || rc == IDCANCEL)
2693 	  return(0);
2694         else
2695 	  return(1);
2696       } else
2697 #endif  /* KUI */
2698       {
2699 	if (preface)
2700 	  printf("%s\n",preface);
2701 	return(getyesno(prompt,0));
2702       }
2703     } else {
2704 	printf("?Internal error: uq_ok()\n");
2705 	return(-1);
2706     }
2707 }
2708 
2709 /* u q _ t x t  --  User Query, get single text response  */
2710 /*
2711   Call with:
2712     preface: Explanatory text to print, or NULL.
2713     prompt:  Prompt.
2714     echo:    0 = don't echo; 1 = echo; 2 = echo with asterisks.
2715     help:    Help text (array of strings or NULL) [not used by parser].
2716     buf:     Pointer to result buffer.
2717     buflen:  Length of result buffer.
2718     dflt:    Default response text or NULL [not used by parser].
2719     timer:   Optional Timeout
2720   Returns:
2721     0:       User said No or Cancel.
2722     1        User said Yes or OK.
2723   Notes:
2724     preface, prompt, and help as for uq_ok().
2725 */
2726 int
2727 #ifdef CK_ANSIC
uq_txt(char * preface,char * prompt,int echo,char ** help,char * buf,int buflen,char * dflt,int timer)2728 uq_txt(char * preface, char * prompt, int echo, char ** help, char * buf,
2729        int buflen, char *dflt, int timer)
2730 #else /* CK_ANSIC */
2731 uq_txt(preface,prompt,echo,help,buf,buflen,dflt,timer)
2732     char * preface, * prompt, ** help, * buf, * dflt;
2733     int buflen, echo, timer;
2734 #endif /* CK_ANSIC */
2735 {
2736 #ifndef NOLOCAL
2737 #ifdef OS2
2738     extern BYTE vmode;
2739     extern int startflags;
2740     extern int win95_popup;
2741 #endif /* OS2 */
2742 #endif /* NOLOCAL */
2743     int rc;
2744 
2745     if (buflen < 1 || !buf)
2746       return(0);
2747 #ifdef KUI
2748     if ( gui_dialog ) {
2749         rc = gui_txt_dialog(preface,prompt,echo,buf,buflen,dflt,timer);
2750         if ( rc > -1 )
2751             return(rc);
2752     /* Otherwise, the dialog could not be created.  Fallback to text mode */
2753     }
2754 #endif /* KUI */
2755 #ifndef NOLOCAL
2756 #ifdef OS2
2757     if (win95_popup && !(startflags & 96)
2758 #ifdef IKSD
2759          && !inserver
2760 #endif /* IKSD */
2761          ) {
2762         debok = 0;                          /* Don't log */
2763         if (echo == 1)
2764                 popup_readtext(vmode,preface,prompt,buf,buflen,0);
2765             else
2766                 popup_readpass(vmode,preface,prompt,buf,buflen,0);
2767         debok = 1;
2768         return(1);
2769     }
2770 #endif /* OS2 */
2771 #endif /* NOLOCAL */
2772 
2773     if (preface)
2774       printf("%s\n",preface);
2775     if (echo == 1)
2776       readtext(prompt,buf,buflen);
2777     else
2778       readpass(prompt,buf,buflen);
2779     return(1);				/* (no buttons in parser) */
2780 }
2781 
2782 /* u q _ m t x t  --  User Query, get multiple text responses */
2783 /*
2784   Call with:
2785     preface: Explanatory text to print, or NULL.
2786     help:    Help text (array of strings or NULL) [not used by parser].
2787     n:       Number of responses wanted.
2788     field:   Array of struct txtbox, one element per field, see ckuusr.h.
2789   Returns:
2790     0:       User said No or Cancel.
2791     1        User said Yes or OK.
2792   Notes:
2793     preface and help as for uq_ok().
2794 */
2795 int
2796 #ifdef CK_ANSIC
uq_mtxt(char * preface,char ** help,int n,struct txtbox field[])2797 uq_mtxt(char * preface,char **help, int n, struct txtbox field[])
2798 #else /* CK_ANSIC */
2799 uq_mtxt(preface,help,n,field)
2800     char * preface; char ** help; int n; struct txtbox field[];
2801 #endif /* CK_ANSIC */
2802 {
2803 #ifndef NOLOCAL
2804 #ifdef OS2
2805     extern BYTE vmode;
2806     extern int startflags;
2807     extern int win95_popup;
2808 #endif /* OS2 */
2809 #endif /* NOLOCAL */
2810     int i, rc;
2811 
2812     if (n < 1 || !field)
2813       return(0);
2814 #ifdef KUI
2815     if ( gui_dialog ) {
2816         rc = gui_mtxt_dialog(preface, n, field);
2817         if ( rc > -1 )
2818             return(rc);
2819     /* Otherwise, the dialog could not be created.  Fallback to text mode */
2820     }
2821 #endif /* KUI */
2822 #ifndef NOLOCAL
2823 #ifdef OS2
2824     if (win95_popup && !(startflags & 96)
2825 #ifdef IKSD
2826          && !inserver
2827 #endif /* IKSD */
2828          ) {
2829         debok = 0;                          /* Don't log */
2830         for (i = 0; i < n; i++) {
2831             if (field[i].t_echo == 1)
2832                 popup_readtext(vmode,preface,field[i].t_lbl,field[i].t_buf,field[i].t_len,0);
2833             else
2834                 popup_readpass(vmode,preface,field[i].t_lbl,field[i].t_buf,field[i].t_len,0);
2835         }
2836         debok = 1;
2837         return(1);
2838     }
2839 #endif /* OS2 */
2840 #endif /* NOLOCAL */
2841 
2842     if (preface)
2843       printf("%s\n",preface);
2844     for (i = 0; i < n; i++) {
2845 	if (field[i].t_echo == 1)
2846 	  readtext(field[i].t_lbl,field[i].t_buf,field[i].t_len);
2847 	else
2848 	  readpass(field[i].t_lbl,field[i].t_buf,field[i].t_len);
2849     }
2850     return(1);
2851 }
2852 
2853 /* u q _ f i l e  --  User Query, get file or directory name  */
2854 /*
2855   Call with:
2856     preface: Explanatory text to print, or NULL.
2857     prompt:  Prompt string.
2858     fc:      Function code:
2859 	       1 = input (existing) file
2860 	       2 = existing directory
2861 	       3 = create new output file
2862 	       4 = output file allowing append access
2863     help:    Help text (array of strings or NULL) [not used by parser].
2864     dflt:    Default response.
2865     result:  Pointer to result buffer.
2866     rlength: Length of result buffer.
2867 
2868   Returns:
2869    -1:       Invalid argument, result too long, or other error.
2870     0:       User Canceled.
2871     1:       OK, with file/pathname copied to result buffer.
2872     2:       Like 1, but for output file that is to be appended to.
2873 
2874   Notes:
2875     1. preface and prompt should not include final line terminator but may
2876        include embedded ones.  Help text is in case GUI dialog needs a Help
2877        button; final element of help-string array is "".
2878 
2879     2. The default might be a filename, a directory name, a relative
2880        pathname, or an absolute pathname.  This routine must convert it into
2881        into a fully qualified (absolute) pathname so the user knows exactly
2882        where the file is to be found or stored.  In addition, the Windows
2883        version of this routine must separate the directory part from the
2884        name part, so it can display the given directory in the file dialog,
2885        and put name in the filename box to be edited, replaced, or
2886        accepted.
2887 
2888     3. When called with FC 4, the Windows version should include "New" and
2889        "Append" buttons in the dialog. so the user can say whether the file
2890        should overwrite any file of the same name, or be appended to it.
2891 */
2892 
2893 int
2894 #ifdef CK_ANSIC
uq_file(char * preface,char * fprompt,int fc,char ** help,char * dflt,char * result,int rlength)2895 uq_file(char * preface, char * fprompt, int fc, char ** help,
2896 	char * dflt, char * result, int rlength)
2897 #else /* CK_ANSIC */
2898 uq_file(preface,fprompt,fc,help,dflt,result,rlength)
2899     char * preface, * fprompt, ** help, * dflt, * result;
2900     int fc, rlength;
2901 #endif /* CK_ANSIC */
2902 /* uq_file */ {
2903 
2904     int rc = -1, x, y, z;
2905     char * s, * p, * fullpath;
2906     char filebuf[CKMAXPATH+1];
2907 
2908 #ifdef CK_RECALL
2909     extern int on_recall;
2910 #endif /* CK_RECALL */
2911 
2912 #ifdef KUI
2913     if ( gui_dialog ) {
2914         rc = gui_saveas_dialog(preface,fprompt,fc,dflt,result,rlength);
2915         return rc;
2916     }
2917 #endif /* KUI */
2918 
2919 #ifdef CK_RECALL
2920     on_recall = 0;
2921 #endif /* CK_RECALL */
2922 
2923     if (preface)			/* If prefatory text given... */
2924       printf("%s\n",preface);		/* display it. */
2925 
2926     cmsavp(psave,PROMPTL);              /* Save old prompt */
2927 
2928     /* We get the full pathname of the proposed output file just so */
2929     /* we can show it to the user but we don't use it ourselves. */
2930 
2931     p = NULL;				/* Build new prompt */
2932     if (!dflt) dflt = "";
2933     if (*dflt)				/* Have default filename */
2934       zfnqfp(dflt,CKMAXPATH+1,filebuf);	/* Get full path */
2935     else
2936       ckmakmsg(filebuf,CKMAXPATH+1,zgtdir(),"newfile",NULL,NULL);
2937     fullpath = filebuf;
2938     x = strlen(fullpath);
2939 
2940     /* If no prompt given, build one that shows the proposed full pathname. */
2941 
2942     if (!fprompt) fprompt = "";
2943     if (!*fprompt) fprompt = x ? " Filename" : " Filename: ";
2944     y = strlen(fprompt);
2945     if (x > 0) {			/* Have default pathname? */
2946 	p = (char *)malloc(x + y + 7);	/* Get temp storage */
2947 	if (p) {			/* Build prompt */
2948 	    ckmakmsg(p,x+y+7,fprompt," [",fullpath,"]: ");
2949 	    fprompt = p;
2950 	}
2951     }
2952     cmsetp(fprompt);			/* Make new prompt */
2953     if (p) free(p);			/* Free temp storage */
2954     cmini(ckxech);                      /* Initialize parser. */
2955     x = -1;
2956     do {
2957         prompt(NULL);                   /* Issue prompt. */
2958         switch (fc) {			/* Parse depends on function code */
2959           case 1:			/* Input file */
2960 	    x = cmifi("Name of existing file",dflt,&s,&y,xxstring);
2961 	    rc = 1;
2962 	    break;
2963 	  case 2:			/* Directory */
2964 	    x = cmdir("Directory name",dflt,&s,xxstring);
2965 	    rc = 1;
2966 	    break;
2967           case 3:			/* New output file */
2968 	    /* Fall thru... */
2969 	  case 4:			/* Output file - Append allowed */
2970 	    x = cmofi("Output file specification",dflt,&s,xxstring);
2971 	    rc = (fc == 4) ? 1 : 2;
2972 	    break;
2973           default:			/* Bad function code */
2974 	    goto x_uq_file;
2975         }
2976         if (x < 0) {			/* Parse error */
2977 	    filebuf[0] = NUL;
2978             if (x == -4) {              /* EOF */
2979                 break;
2980             } else if (x == -3)         /* No answer? */
2981               printf(fc == 2 ?
2982 		     " Please enter a directory name.\n" :
2983 		     " Please enter a filename.\n"
2984 		     );
2985             cmini(ckxech);
2986         } else {
2987 	    z = strlen(s);
2988 	    if (z > rlength || ckstrncpy(filebuf,brstrip(s),CKMAXPATH+1) < z) {
2989 		printf("?Name too long\n");
2990 		x = -9;
2991 	    } else
2992 	      x = cmcfm();		/* Get confirmation */
2993         }
2994 	if (fc == 1 && x > -1 && y > 0) {
2995 	    printf("?Wildcards not allowed\n");
2996 	    x = -9;
2997 	}
2998     } while (x < 0);                    /* Continue till done */
2999 
3000   x_uq_file:
3001     if (x < 0)
3002       rc = -1;
3003 
3004     cmsetp(psave);                      /* Restore real prompt */
3005 
3006     if (rc > 0)
3007       ckstrncpy(result,filebuf,rlength);
3008     return(rc);
3009 }
3010 
3011 
3012 #ifdef CK_PERMS
3013 #ifdef UNIX
3014 
3015 _PROTOTYP( int zsetperm, (char *, int));
3016 
3017 /* CHMOD command for UNIX only */
3018 
3019 #define CHM_DIR 0
3020 #define CHM_DOT 1
3021 #define CHM_FIL 2
3022 #define CHM_LIS 3
3023 #define CHM_NOL 4
3024 #define CHM_QUI 5
3025 #define CHM_REC 6
3026 #define CHM_VRB 7
3027 #define CHM_PAG 8
3028 #define CHM_NOP 9
3029 #define CHM_TYP 10
3030 #define CHM_SIM 11
3031 
3032 static struct keytab uchmodsw[] = {
3033     "/directories", CHM_DIR, 0,
3034     "/dotfiles",    CHM_DOT, 0,
3035     "/files",       CHM_FIL, 0,
3036     "/list",        CHM_LIS, 0,
3037     "/nolist",      CHM_NOL, 0,
3038     "/nopage",      CHM_NOP, 0,
3039     "/page",        CHM_PAG, 0,
3040     "/quiet",       CHM_QUI, CM_INV,
3041     "/recursive",   CHM_REC, 0,
3042     "/simulate",    CHM_SIM, 0,
3043     "/type",        CHM_TYP, CM_ARG,
3044     "/verbose",     CHM_VRB, CM_INV,
3045 };
3046 static int nchmodsw = (sizeof(uchmodsw) / sizeof(struct keytab));
3047 
3048 int
douchmod()3049 douchmod() {
3050     extern int recursive, nscanfile, diractive;
3051 #ifdef CK_TTGWSIZ
3052     extern int tt_rows, tt_cols;
3053     int n = 0;
3054 #endif /* CK_TTGWSIZ */
3055     int i, files = 1, t1 = 1, t2 = 0, x, y, z, verbose = 0, rc = 1, paging;
3056     int xmode = -1, fs = 0, getval = 0, simulate = 0, wild = 0;
3057     char c, * s;
3058     struct FDB sw, nu;
3059 
3060     if (xaskmore < 0) {
3061 #ifdef CK_TTGWSIZ
3062         xaskmore = 1;
3063 #else
3064         xaskmore = 0;
3065 #endif /* CK_TTGWSIZ */
3066     }
3067     paging = xaskmore;
3068 
3069     cmfdbi(&sw,                         /* First FDB - command switches */
3070            _CMKEY,                      /* fcode */
3071            "Octal file permission code, or switch",
3072            "",                          /* default */
3073            "",                          /* addtl string data */
3074            nchmodsw,                    /* addtl numeric data 1: tbl size */
3075            4,                           /* addtl numeric data 2: 4 = cmswi */
3076            xxstring,                    /* Processing function */
3077            uchmodsw,                    /* Keyword table */
3078            &nu                          /* Pointer to next FDB */
3079            );
3080     cmfdbi(&nu,
3081            _CMNUM,                      /* Number */
3082            "",                          /* Help message */
3083            "",                          /* Default */
3084            "",                          /* N/A */
3085            8,                           /* Radix = 8 */
3086            0,                           /* N/A */
3087            xxstring,                    /* Processing function */
3088            NULL,                        /* N/A */
3089            NULL                         /* Next */
3090            );
3091 
3092     while (1) {
3093         if ((x = cmfdb(&sw)) < 0) {
3094             if (x == -3) {
3095                 x = -9;
3096                 printf("?Filename required\n");
3097             }
3098             return(x);
3099         }
3100         if (cmresult.fcode != _CMKEY)
3101           break;
3102         c = cmgbrk();
3103         getval = (c == ':' || c == '=');
3104         if (getval && !(cmgkwflgs() & CM_ARG)) {
3105             printf("?This switch does not take an argument\n");
3106             return(-9);
3107         }
3108         if (!getval && (cmgkwflgs() & CM_ARG)) {
3109             printf("?This switch requires an argument\n");
3110             return(-9);
3111         }
3112         switch (cmresult.nresult) {
3113           case CHM_DIR:
3114             t1 = 1;
3115             t2 = 1;
3116             break;
3117           case CHM_DOT:
3118             matchdot = 1;
3119             break;
3120           case CHM_FIL:
3121             t1 = 0;
3122             t2 = 0;
3123             break;
3124           case CHM_LIS:
3125           case CHM_VRB:
3126             verbose = 1;
3127             break;
3128           case CHM_NOL:
3129           case CHM_QUI:
3130             verbose = 0;
3131             break;
3132           case CHM_REC:
3133             recursive = 1;
3134             break;
3135           case CHM_PAG:
3136             verbose = 1;
3137             paging = 1;
3138             break;
3139           case CHM_NOP:
3140             paging = 0;
3141             break;
3142           case CHM_SIM:
3143             simulate = 1;
3144             break;
3145           case CHM_TYP: {
3146               extern struct keytab txtbin[];
3147               if ((x = cmkey(txtbin,3,"","",xxstring)) < 0)
3148                 return(x);
3149               if (x == 2) {             /* ALL */
3150                   xmode = -1;
3151               } else {                  /* TEXT or BINARY only */
3152                   xmode = x;
3153                   fs = 1;
3154               }
3155               break;
3156           }
3157         }
3158     }
3159     z = cmresult.nresult;
3160     x = cmifi2("File specification","",&s,&wild,t1,NULL,xxstring,t2);
3161     if (x < 0) {
3162         if (x == -3) {
3163             printf("?A file specification is required\n");
3164             return(-9);
3165         } else
3166           return(x);
3167     }
3168     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
3169     s = tmpbuf;
3170     if ((x = cmcfm()) < 0)
3171       return(x);
3172 #ifdef ZXREWIND
3173     if (wild) files = zxrewind();
3174 #else
3175     if (wild) files = nzxpand(s,0);
3176 #endif /* ZXREWIND */
3177 
3178     if (paging > -1)
3179       xaskmore = paging;
3180 
3181 #ifdef CK_TTGWSIZ
3182     if (verbose && paging) {
3183 #ifdef OS2
3184         ttgcwsz();
3185 #else /* OS2 */
3186         if (ttgwsiz() > 0) {
3187             if (tt_rows > 0 && tt_cols > 0) {
3188                 cmd_rows = tt_rows;
3189                 cmd_cols = tt_cols;
3190             }
3191         }
3192 #endif /* OS2 */
3193     }
3194 #endif /* CK_TTGWSIZ */
3195 
3196     for (i = 0; i < files; i++) {
3197         if (files == 1 && wild == 0) {  /* For "chmod 777 ." */
3198             ckstrncpy(line,s,LINBUFSIZ);
3199         } else {
3200             x = znext(line);
3201             if (x < 1) {
3202                 if (i == 0) {
3203                     printf("?No files match - \"%s\"\n",line);
3204                     return(-9);
3205                 }
3206                 return(1);
3207             }
3208         }
3209         if (fs) {
3210 #ifdef VMSORUNIX
3211             /* If /TYPE:TEXT or BINARY given, skip directories and links */
3212             /* since they are neither text nor binary. */
3213             extern int zgfs_dir, zgfs_link;
3214             zgetfs(line);
3215             if (zgfs_dir || zgfs_link)
3216               continue;
3217 #else
3218             if (zchki(line) < 0)
3219               continue;
3220 #endif /* VMSORUNIX */
3221             /* Regular file, scan it */
3222             switch (scanfile(line,&y,nscanfile)) {
3223               case FT_BIN:
3224                 if (xmode != 1)
3225                   continue;
3226                 break;
3227               case FT_TEXT:
3228               case FT_7BIT:
3229               case FT_8BIT:
3230 #ifdef UNICODE
3231               case FT_UTF8:
3232               case FT_UCS2:
3233 #endif /* UNICODE */
3234                 if (xmode != 0)
3235                   continue;
3236             }
3237         }
3238         if (simulate) {
3239 #ifdef UNIX
3240             extern int zchkod;          /* Unidentified Flying */
3241             int xx = zchkod;            /* API Extension... */
3242             zchkod = 1;
3243 #endif /* UNIX */
3244             if (zchko(line) < 0)
3245               printf("%s - Access denied\n",line);
3246             else
3247               printf("%s - OK\n",line);
3248 #ifdef UNIX
3249             zchkod = xx;
3250 #endif /* UNIX */
3251         } else {
3252             if (zsetperm(line,z) < 1) {
3253                 if (verbose || files < 2) {
3254                     printf("%s: %s\n",line,ck_errstr());
3255                 }
3256                 rc = 0;
3257             } else if (verbose) {
3258                 printf("%s  %s\n",ziperm(line),line);
3259             }
3260         }
3261 #ifdef CK_TTGWSIZ
3262         if (verbose && paging) {        /* Pause at end of screen */
3263             if (cmd_rows > 0 && cmd_cols > 0) {
3264                 if (++n > cmd_rows - 3) {
3265                     if (!askmore())
3266                       break;
3267                     else
3268                       n = 0;
3269                 }
3270             }
3271         }
3272 #endif /* CK_TTGWSIZ */
3273 
3274     }
3275     return(success = rc);
3276 }
3277 #endif /* UNIX */
3278 #endif /* CK_PERMS */
3279 
3280 #ifndef NOSPL                           /* S-Expressions */
3281 #ifndef NOSEXP
3282 
3283 struct keytab sexptab[] = {
3284     "depth-limit", 1, 0,
3285     "echo-result", 0, 0,
3286     "truncate-all-results", 2
3287 };
3288 
3289 static int sexpmaxdep = 1000;           /* Maximum depth */
3290 
3291 #define xxfloat(s,x) \
3292 ((isdigit(*s)||(*s=='-')||(*s=='+')||(*s=='.')||(*s=='\040'))?isfloat(s,x):0)
3293 
3294 #define SX_ADD  1                       /* Symbols for built-in operators */
3295 #define SX_SUB  2
3296 #define SX_MUL  3
3297 #define SX_DIV  4
3298 #define SX_POW  5
3299 #define SX_SET  6
3300 #define SX_MOD  7
3301 #define SX_EVA  8
3302 #define SX_EXP  9
3303 #define SX_AEQ 10
3304 #define SX_ALT 11
3305 #define SX_AGT 12
3306 #define SX_ALE 13
3307 #define SX_AGE 14
3308 #define SX_MIN 15
3309 #define SX_MAX 16
3310 #define SX_SQR 17
3311 #define SX_FLR 18
3312 #define SX_CEI 19
3313 #define SX_TRU 20
3314 #define SX_ABS 21
3315 #define SX_ROU 22
3316 #define SX_LET 23
3317 #define SX_LGN 24
3318 #define SX_LGX 25
3319 #define SX_FLO 26
3320 #define SX_IFC 27
3321 #define SX_NOT 28
3322 #define SX_NEQ 29
3323 #define SX_AND 30
3324 #define SX_LOR 31
3325 #define SX_SIN 32
3326 #define SX_COS 33
3327 #define SX_TAN 34
3328 #define SX_BWA 35
3329 #define SX_BWO 36
3330 #define SX_BWX 37
3331 #define SX_BWN 38
3332 #define SX_XOR 39
3333 #define SX_INC 40
3334 #define SX_DEC 41
3335 #define SX_QUO 42
3336 #define SX_STR 43
3337 #define SX_ECH 44
3338 #define SX_UNQ 45
3339 
3340 /* Operator flags */
3341 
3342 #define SXF_PRE 256                     /* Predicate */
3343 #define SXF_ONE 512                     /* Requires one arg */
3344 #define SXF_TWO 1024                    /* Requires two args or more */
3345 #define SXF_FLO 2048                    /* Coerce to floating-point */
3346 
3347 /* Built-in constants */
3348 
3349 #define SXC_NIL 1                       /* NIL */
3350 #define SXC_PI  2                       /* PI */
3351 #define SXC_T   3                       /* T */
3352 
3353 /*
3354   This is an xlookup() table and so need not be in "alhabetical" order.
3355   Therefore entries are arranged to minimize search for most common
3356   operators.
3357 */
3358 static struct keytab sexpops[] = {      /* Built-in operators */
3359     "setq",    SX_SET, 0,               /* Global assignment */
3360     "+",       SX_ADD, 0,               /* Simple arithmetic */
3361     "-",       SX_SUB, 0,
3362     "*",       SX_MUL, 0,
3363     "/",       SX_DIV, SXF_TWO,
3364     "^",       SX_POW, SXF_TWO,
3365 
3366     "if",      SX_IFC, SXF_TWO,         /* IF */
3367     "let",     SX_LET, 0,               /* Local assignment */
3368     "not",     SX_NOT, SXF_ONE,         /* NOT */
3369     "mod",     SX_MOD, SXF_TWO,         /* Modulus */
3370 
3371     "<",       SX_ALT, SXF_PRE,		/* Comparisons */
3372     ">",       SX_AGT, SXF_PRE,
3373     "<=",      SX_ALE, SXF_PRE,
3374     "=",       SX_AEQ, SXF_PRE,
3375     ">=",      SX_AGE, SXF_PRE,
3376     "!=",      SX_NEQ, SXF_PRE,
3377 
3378     "++",      SX_INC, SXF_ONE|SXF_TWO, /* Increment */
3379     "--",      SX_DEC, SXF_ONE|SXF_TWO, /* Decrement */
3380 
3381     "**",      SX_POW, SXF_TWO,         /* Common synonyms */
3382     "==",      SX_AEQ, SXF_PRE,
3383     "!",       SX_NOT, SXF_ONE,
3384     ".",       SX_EVA, 0,
3385 
3386     "and",     SX_AND, 0,               /* Logical operators */
3387     "or",      SX_LOR, 0,
3388     "xor",     SX_XOR, SXF_TWO,
3389 
3390     "max",     SX_MAX, SXF_ONE|SXF_TWO, /* Max and min */
3391     "min",     SX_MIN, SXF_ONE|SXF_TWO,
3392 
3393     "%",       SX_MOD, SXF_TWO,         /* More synonyms */
3394     "||",      SX_LOR, 0,
3395     "&&",      SX_AND, 0,
3396 
3397     "quote",   SX_QUO, SXF_ONE,         /* String operators */
3398     "string",  SX_STR, SXF_ONE,
3399     "unquote", SX_UNQ, SXF_ONE,
3400 
3401     "eval",    SX_EVA, 0,               /* Assorted commands */
3402     "abs",     SX_ABS, SXF_ONE,
3403     "truncate",SX_TRU, SXF_ONE|SXF_FLO,
3404     "round",   SX_ROU, SXF_ONE|SXF_TWO|SXF_FLO,
3405     "ceiling", SX_CEI, SXF_ONE|SXF_FLO,
3406     "floor",   SX_FLR, SXF_ONE|SXF_FLO,
3407     "float",   SX_FLO, SXF_ONE|SXF_FLO,
3408     "echo",    SX_ECH, 0,
3409 
3410 #ifdef FNFLOAT
3411     "sqrt",    SX_SQR, SXF_ONE|SXF_FLO, /* Floating point functions */
3412     "exp",     SX_EXP, SXF_ONE|SXF_FLO,
3413     "sin",     SX_SIN, SXF_ONE|SXF_FLO,
3414     "cos",     SX_COS, SXF_ONE|SXF_FLO,
3415     "tan",     SX_TAN, SXF_ONE|SXF_FLO,
3416     "log",     SX_LGN, SXF_ONE|SXF_FLO,
3417     "log10",   SX_LGX, SXF_ONE|SXF_FLO,
3418 #endif /* FNFLOAT */
3419 
3420     "#",       SX_BWX, SXF_TWO,         /* Bitwise operators */
3421     "&",       SX_BWA, 0,
3422     "|",       SX_BWO, 0,
3423     "~",       SX_BWN, SXF_ONE,
3424     "", 0, 0                            /* (end) */
3425 };
3426 static int nsexpops = (sizeof(sexpops) / sizeof(struct keytab)) - 1;
3427 
3428 static struct keytab sexpconsts[] = {   /* Built-in constants */
3429     "nil", SXC_NIL, 0,                  /* NIL (false) */
3430     "pi",  SXC_PI,  0,                  /* Pi (3.1415926...) */
3431     "t",   SXC_T,   0,                  /* T (true) */
3432     "", 0, 0
3433 };
3434 static int nsexpconsts = (sizeof(sexpconsts) / sizeof(struct keytab)) - 1;
3435 
3436 int sexprc = 0;                         /* S-Expression error flag */
3437 int sexppv = -1;                        /* Predicate value */
3438 static int sexptrunc = 0;		/* Flag to force all results to int */
3439 
3440 #define SXMLEN 64                       /* Macro arg list initial length */
3441 #include <math.h>                       /* Floating-point functions */
3442 
3443 _PROTOTYP( char * fpformat, (CKFLOAT, int, int) );
3444 _PROTOTYP( CKFLOAT ckround, (CKFLOAT, int, char *, int) );
3445 
3446 extern char math_pi[];                  /* Value of Pi */
3447 extern int sexpecho;                    /* SET SEXPRESSION ECHO value */
3448 extern char * sexpval;                  /* Last top-level S-Expression value */
3449 extern char * lastsexp;                 /* Last S-Expression */
3450 int sexprmax = 0;                       /* Longest result (for stats) */
3451 int sexpdmax = 0;                       /* Max depth reached (for stats) */
3452 int sexpdep  = 0;                       /* dosexp() recursion depth */
3453 static int * sxrlen = NULL;             /* Result stack string sizes */
3454 static char ** sxresult = NULL;         /* Result stack */
3455 
3456 /*  s h o s e x p  --  Show S-Expression info  */
3457 
3458 VOID
shosexp()3459 shosexp() {
3460     printf("\n");
3461     printf(" sexpression echo-result: %s\n",showooa(sexpecho));
3462     printf(" sexpression depth-limit: %d\n",sexpmaxdep);
3463     printf("\n");
3464     printf(" maximum depth reached:   %d\n",sexpdmax);
3465     printf(" longest result returned: %d\n",sexprmax);
3466     printf("\n");
3467     printf(" truncate all results:    %s\n",showoff(sexptrunc));
3468     printf("\n");
3469     printf(" last sexpression:        %s\n",lastsexp ? lastsexp : "(none)");
3470     printf(" last value:              %s\n",sexpval ? sexpval : "(none)");
3471     printf("\n");
3472 }
3473 
3474 
3475 static char *
sexpdebug(s)3476 sexpdebug(s) char * s; {
3477     /* For debugging -- includes recursion depth in each debug entry */
3478     static char buf[64];
3479     ckmakmsg(buf,64,"dosexp[",ckitoa(sexpdep),"] ",s);
3480     return((char *)buf);
3481 }
3482 
3483 /*  d o s e x p  --  S-Expression Reader  */
3484 
3485 /*  Returns value as string (empty, numeric, or non-numeric) */
3486 
3487 static char sxroundbuf[32];		/* For ROUND result */
3488 
3489 char *
dosexp(s)3490 dosexp(s) char *s; {                    /* s = S-Expression */
3491     extern struct mtab *mactab;         /* Macro table */
3492     extern int maclvl, nmac;
3493     extern char *mrval[];
3494     extern int makestrlen;              /* (see makestr()) */
3495     struct stringarray * q = NULL;      /* cksplit() return type */
3496     char * p[SEXPMAX+1], ** p2;         /* List items (must be on stack) */
3497     char * line = NULL;                 /* For building macro argument list */
3498     int nosplit = 0;
3499     int linelen = 0;
3500     int linepos = 0;
3501     int quote = 0;                      /* LISP quote flag */
3502     char * s2;                          /* Workers */
3503     int kw, kwflags, mx = 0, x = 0;
3504     int not = 0, truncate = 0, builtin = 0;
3505     int fpflag = 0, quit = 0, macro = 0;
3506     CK_OFF_T result = 0, i, j, k, n = 0;
3507     CKFLOAT fpj, fpresult = 0.0;        /* Floating-point results */
3508     int pflag = 0;                      /* Have predicate */
3509     int presult = 0;                    /* Predicate result */
3510     int mustfree = 0;                   /* If we malloc'd we must free */
3511 
3512     sexppv = -1;                        /* Predicate value */
3513     s2 = "";                            /* Default return value */
3514 
3515     debug(F111,sexpdebug("entry 1"),s,sexprc);
3516 
3517     if (++sexpdep > sexpmaxdep) {       /* Keep track of depth */
3518         printf("?S-Expression depth limit exceeded: %d\n",sexpmaxdep);
3519         sexprc++;
3520         debug(F111,sexpdebug("max depth exceeded"),s,sexprc);
3521     }
3522     if (sexpdep > sexpdmax)             /* For stats */
3523       sexpdmax = sexpdep;
3524 
3525     if (sexprc)                         /* Error, quit all levels */
3526       goto xdosexp;                     /* Always goto common exit point */
3527 
3528     debug(F111,sexpdebug("entry 2"),s,sexprc);
3529 
3530     if (!s) s = "";                     /* Null or empty arg */
3531 
3532     while (*s == SP) s++;               /* Strip leading spaces */
3533     if (!*s)                            /* so empty result */
3534       goto xdosexp;
3535 /*
3536   Allocate result stack upon first use, or after it has been resized with
3537   SET SEXP DEPTH-LIMIT.
3538 */
3539     if (!sxresult) {
3540         sxresult = (char **)malloc(sexpmaxdep * sizeof(char *));
3541         if (!sxresult) {
3542             printf("?Memory allocation failure - \"%s\"\n", s);
3543             sexprc++;
3544             goto xdosexp;
3545         }
3546         sxrlen = (int *)malloc(sexpmaxdep * sizeof(int));
3547         if (!sxrlen) {
3548             printf("?Memory allocation failure - \"%s\"\n", s);
3549             sexprc++;
3550             goto xdosexp;
3551         }
3552         for (i = 0; i < sexpmaxdep; i++) {
3553             sxresult[i] = NULL;         /* Result pointers */
3554             sxrlen[i] = 0;              /* Buffer sizes */
3555         }
3556     }
3557     s2 = s;                             /* s2 is the result pointer */
3558     k = 0;                              /* Length accumulator */
3559     if (s[0] == '(') {                  /* Starts with open paren? */
3560         while (*s2++) k++;              /* Get length */
3561         if (s[k-1] == ')') {            /* Strip outer parens if any */
3562             s[k-1] = NUL;
3563             s++;
3564             k -= 2;
3565             while (*s == SP) {          /* Strip leading spaces from result */
3566                 s++;
3567                 k--;
3568             }
3569             while (k > 0 && s[k-1] == SP) { /* And trailing spaces. */
3570                 s[k-1] = NUL;
3571                 k--;
3572             }
3573         }
3574         if (!*s) {                      /* If nothing remains */
3575             s2 = "";                    /* return empty result. */
3576             goto xdosexp;
3577         }
3578     }
3579     /* Break result up into "words" (an SEXP counts as a word) */
3580 
3581     for (i = 0; i < SEXPMAX+1; i++ ) {	/* Clear the operands */
3582 	p[i] = NULL;
3583     }
3584     if (!*(s+1) || !*(s+2)) {           /* No need to call cksplit() */
3585         n = 1;                          /* if it's one or two chars. */
3586         p[1] = s;                       /* No need to malloc this either. */
3587 	nosplit = 1;
3588         debug(F101,sexpdebug("nosplit"),"",n);
3589         if (s[0] == '(') {              /* () empty */
3590             s2 = "";
3591             goto xdosexp;
3592         }
3593     } else {
3594 	nosplit = 0;
3595        q = cksplit(1,SEXPMAX,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",8,39,0,0);
3596         if (!q)
3597           goto xdosexp;
3598         n = q->a_size;                  /* Number of items */
3599 //        printf("XXX cksplit=%d\n",n);
3600         debug(F101,sexpdebug("split"),"",n);
3601         if (n < 0 || n > SEXPMAX) {     /* Check for too many */
3602             printf("?Too many operands: max = %d\n",SEXPMAX);
3603             sexprc++;
3604             goto xdosexp;
3605         }
3606         if (n == 0)                     /* None, result is NULL, done. */
3607           goto xdosexp;
3608         if (n == 1 && s[0] == '(') {    /* One but it's another SEXP */
3609 //            printf("XXX s.00=[%s]\n",s);
3610             s2 = dosexp(s);
3611 //            printf("XXX s2.00=[%s]\n",s2);
3612             goto xdosexp;
3613         }
3614         if (n == 1 && s[0] == '\047') { /* One but it's a string constant */
3615             int x = (int) strlen(s);
3616             s2 = s;
3617             if (s2[1] == '(' && s2[x-1] == ')') { /* '(string) */
3618                 s2[x-1] = NUL;
3619                 s2 += 2;
3620 //                printf("XXX s2.2=[%s]\n",s2);
3621             }
3622             goto xdosexp;
3623         }
3624         /* More than one */
3625 
3626         p2 = q->a_head;                 /* Point to result array. */
3627         for (i = 1; i <= n; i++) {      /* We must copy it because */
3628             p[i] = NULL;                /* recursive calls to dosexp() */
3629             if (p2[i])                  /* write over the same array */
3630               makestr(&(p[i]),p2[i]);
3631         }
3632         if (s[0] == '(') {              /* Operator is an S-Expression */
3633 //            printf("XXX p[1]=[%s] s=[%s]\n",p[1],s);
3634             s2 = dosexp(p[1]);          /* Replace it by its value */
3635 //            printf("XXX s2.1=[%s]\n",s2);
3636             if (s2[0] == '\047') {      /* LISP string literal */
3637                 int x = (int) strlen(s2);
3638                 if (s2[1] == '(' && s2[x-1] == ')') { /* '(string) */
3639                     s2[x-1] = NUL;
3640                     s2 += 2;
3641                     printf("XXX s2.2=[%s]\n",s2);
3642                 }
3643             }
3644             makestr(&(p[1]),s2);
3645         }
3646         mustfree++;                     /* Remember to free it */
3647     }
3648     debug(F110,sexpdebug("head"),p[1],0);
3649 
3650     if (n == 1 && p[1]) {
3651         if (*(p[1]) == '\047') {       /* Apostrophe = LISP quote character */
3652             s2 = p[1];
3653             goto xdosexp;
3654         }
3655     }
3656 /*
3657   This section sidesteps xlookup() of the most common operators.
3658   It's not necessary but it speeds up SEXP-heavy loops by about 10%.
3659 */
3660     kwflags = 0;
3661     if (n > 0) {                        /* Look up the operator */
3662         s2 = p[1];                      /* Prelookup optimization... */
3663         if (!s2)
3664           s2 = "";
3665         if (!*s2)
3666           goto xdosexp;
3667         kw = 0;
3668         x = 0;
3669         if (isdigit(*s2)) {             /* Digit */
3670             x = -2;
3671 
3672         } else if (isalpha(*s2) && !*(s2+1)) { /* Single letter */
3673             x = -1;
3674 
3675         } else if (*s2 == 's' || *s2 == 'S') { /* SETQ */
3676             s2++;
3677             if (*s2 == 'e' || *s2 == 'E') {
3678                 s2++;
3679                 if (*s2 == 't' || *s2 == 'T') {
3680                     s2++;
3681                     if (*s2 == 'q' || *s2 == 'Q') {
3682                         if (!*(s2+1)) {
3683                             x = SX_SET;
3684                             kwflags = 0;
3685                             builtin = 1;
3686                         }
3687                     }
3688                 }
3689             }
3690         }
3691         if (!x) {
3692             if (!*(s2+1)) {             /* Common single-character ops */
3693                 if (*s2 == '+') {
3694                     x = SX_ADD;
3695                     kwflags = 0;
3696                     builtin = 1;
3697                 } else if (*s2 == '-') {
3698                     x = SX_SUB;
3699                     kwflags = 0;
3700                     builtin = 1;
3701                 } else if (*s2 == '*') {
3702                     x = SX_MUL;
3703                     kwflags = 0;
3704                     builtin = 1;
3705                 } else if (*s2 == '/') {
3706                     x = SX_DIV;
3707                     kwflags = SXF_TWO;
3708                     builtin = 1;
3709                 }
3710             }
3711             if (!x) {                   /* None of the above, look it up */
3712                 x = xlookup(sexpops,p[1],nsexpops,&kw);
3713                 if (x > 0) {
3714                     kwflags = sexpops[kw].flgs;
3715                     builtin = 1;
3716                 }
3717             }
3718         }
3719     }
3720     /* If none of the above, check built-in constants */
3721 
3722     if (x == -1) {
3723         x = xlookup(sexpconsts,p[1],nsexpconsts,&kw);
3724         if (x > 0) {
3725             switch (x) {
3726               case SXC_NIL:
3727                 s2 = "";
3728                 goto xdosexp;
3729               case SXC_PI:
3730                 s2 = math_pi;
3731                 goto xdosexp;
3732               case SXC_T:
3733                 s2 = "1";
3734                 goto xdosexp;
3735             }
3736         }
3737     }
3738     if (n == 1) {                       /* Not an expression */
3739         if (builtin) {                  /* Built-in operand? */
3740             switch (x) {		/* Operators with default values */
3741               case SX_EVA:
3742                 s2 = "";
3743                 goto xdosexp;
3744               case SX_MUL:              /* (*) */
3745                 s2 = sexpval ? sexpval : "1";
3746                 goto xdosexp;
3747               case SX_AND:              /* (AND) */
3748               case SX_BWA:              /* Bitwise (&) */
3749                 result++;
3750               case SX_LOR:              /* (OR) */
3751               case SX_BWO:              /* Bitwise (|) */
3752               case SX_ADD:              /* (+) */
3753               case SX_SUB:              /* (-) */
3754                 s2 = result ? "1" : "0";
3755                 goto xdosexp;
3756             }
3757 
3758         } else {                        /* Not a built-in operand */
3759             char * p1;
3760             p1 = p[1];
3761             while (*p1 == SP) p1++;
3762             if (!isalpha(*p1)) {
3763                 if (xxfloat(p1,0) > 0) { /* Is it a number? */
3764                     s2 = p1;
3765                     while (*s2 == '+') s2++;
3766                 } else if (*p1 == '(') { /* An S-Expression? */
3767 
3768 #ifdef COMMENT
3769                     s2 = dosexp(s2);
3770 #else
3771                     s2 = dosexp(p1);
3772 #endif /* COMMENT */
3773                 }
3774                 goto xdosexp;
3775             } else if (x < 1) {         /* Is it a variable? */
3776                 j = mxlook(mactab,p[1],nmac); /* Look it up */
3777                 debug(F111,sexpdebug("n==1 mxlook"),p[1],j);
3778                 s2 = (j > -1) ? mactab[j].mval : "";
3779                 if (!s2) s2 = "";
3780                 if (xxfloat(s2,0) > 0)  /* Macro value is a number */
3781                   goto xdosexp;
3782                 if (j > -1) {           /* It's a macro */
3783                     mx = j;
3784                     x = j;              /* whose definition is not numeric */
3785                     if (*s2 == '(') {   /* Is it an S-Expression? */
3786                         /* We have to allocate memory on the stack */
3787                         /* to call ourselves recursively on it */
3788                         /* otherwise we'll wipe out the macro definition */
3789                         char * s3 = NULL;
3790                         /* int k = 0; */
3791                         s3 = s2;
3792                         while (*s3++) k++;
3793                         s3 = (char *)malloc(k + 4);
3794                         if (s3) {
3795                             strcpy(s3,s2);   /* SAFE */
3796                             s2 = dosexp(s3); /* Evaluate it */
3797                             free(s3);
3798                         } else {
3799                             printf("?Memory allocation failure - \"%s\"\n",s2);
3800                             sexprc++;
3801                         }
3802                         goto xdosexp;
3803                     }
3804                     if (*s2 == '\047') {
3805                         s2++;
3806 #ifdef COMMENT
3807 			/* Dumps core if petty optimization was taken */
3808                         makestr(&(p[1]),s2);
3809 #else
3810 			if (!nosplit && p[1]) free(p[1]);
3811 			p[1] = (char *)malloc((int)strlen(s2) + 1);
3812 #endif /* COMMENT */
3813                         s2 = p[1];
3814 			if (!s2) s2 = "";
3815                         if (*s2 == '(') {
3816                             if (s2[makestrlen-1] == ')') {
3817                                 s2[makestrlen-1] = NUL;
3818                                 s2++;
3819                             }
3820                         }
3821                         debug(F110,sexpdebug("'A"),s2,0);
3822                         goto xdosexp;
3823                     }
3824                     macro++;            /* Not an S-Expression */
3825                 } else {
3826                     printf("?Not defined - \"%s\"\n", p[1]);
3827                     sexprc++;
3828                     goto xdosexp;
3829                 }
3830             }
3831         }
3832     } else if (x < 1 && !macro) {       /* n > 1 and not a built-in operator */
3833         x = mxlook(mactab,p[1],nmac);   /* See if it's a macro */
3834         debug(F111,sexpdebug("n!=1 mxlook"),p[1],x);
3835         if (x < 0) {
3836             printf("?Invalid operand - \"%s\"\n",p[1]);
3837             sexprc++;
3838             s2 = NULL;			/* Bad operator, no result */
3839             goto xdosexp;
3840         }
3841         mx = x;
3842         macro++;
3843     }
3844     if (builtin) {                      /* Built-in operator... */
3845         if (kwflags) {
3846             int flgs;
3847             if ((flgs = (kwflags & (SXF_ONE|SXF_TWO)))) {
3848                 switch (flgs) {
3849                   case (SXF_ONE|SXF_TWO):
3850                     if (n < 2) {
3851                         printf("?Too few operands - \"%s\"\n",s);
3852                         sexprc++;
3853                         goto xdosexp;
3854                     }
3855                     break;
3856                   case SXF_TWO:
3857                     if (n < 3) {
3858                         printf("?Too few operands - \"%s\"\n",s);
3859                         sexprc++;
3860                         goto xdosexp;
3861                     }
3862                     break;
3863                   case SXF_ONE:
3864 		    if (n != 2) {
3865                         printf("?Too %s operands - \"%s\"\n",
3866                                (n > 2) ? "many" : "few", s);
3867                         sexprc++;
3868                         goto xdosexp;
3869                     }
3870                 }
3871             }
3872             if (kwflags & SXF_PRE) {    /* Predicate? */
3873 		if (n < 2) {
3874 		    printf("?Too few operands - \"%s\"\n",s);
3875 		    sexprc++;
3876 		    goto xdosexp;
3877 		}
3878                 pflag = 1;
3879                 presult = 1;
3880             }
3881             if (kwflags & SXF_FLO)      /* Operator requires floating point */
3882               fpflag++;                 /* Force it */
3883 
3884 	    if (x == SX_ROU) {		/* ROUND can have 1 or 2 arguments */
3885 		if (n < 2 || n > 3) {
3886 		    printf("?Too %s operands - \"%s\"\n",
3887 			   (n > 3) ? "many" : "few", s);
3888 		    sexprc++;
3889 		    goto xdosexp;
3890 		}
3891 	    }
3892 	    if (x == SX_ROU) {
3893 		/* But they are not "cumulative" like other SEXP args */
3894 		/* So this case is handled specially */
3895 		char buf1[32], buf2[32];
3896 		float r;
3897 		char * s0, * s1;
3898 		char * q0, * q1;
3899 
3900 		s0 = p[2];
3901 		if (!s0) s0 = "";
3902 		if (!*s0) s0 = "0";
3903 		q0 = dosexp(s0);
3904 		ckstrncpy(buf1,q0,32);
3905 		q0 = buf1;
3906 
3907 		s1 = p[3];
3908 		if (!s1) s1 = "";
3909 		if (!*s1) s1 = "0";
3910 		q1 = dosexp(s1);
3911 		if (!q1) q1 = "";
3912 		if (!*q1) q1 = "0";
3913 		ckstrncpy(buf2,q1,32);
3914 		q1 = buf2;
3915 		r = ckround(atof(q0),(int)(atof(q1)),sxroundbuf,31);
3916 		s2 = sxroundbuf;
3917 		sexprc = 0;
3918 		goto xdosexp;
3919 	    }
3920         }
3921         if (x == SX_SET || x == SX_LET || /* Assignment is special */
3922             x == SX_INC || x == SX_DEC) {
3923             int rc;
3924             char c, * m, * s3;
3925             if (n == 1) {
3926                 s2 = "";
3927                 goto xdosexp;
3928             }
3929             s2 = NULL;
3930             for (i = 1; i < n; i += 2) { /* Loop thru operand pairs */
3931                 rc = 0;
3932                 s3 = p[i+1];
3933                 c = *s3;
3934                 debug(F110,sexpdebug("target p"),s3,0);
3935 
3936                 /* Make sure target doesn't have multiple words */
3937                 while (*s3) { if (*s3 < '!') { rc = 1; break; }; s3++; }
3938                 s3 = p[i+1];
3939                 if (rc) {               /* If it does it must have been */
3940                     char * s4;          /* an SEXP so evaluate it */
3941                     s3 = dosexp(s3);
3942                     s4 = s3;
3943                     rc = 0;
3944                     while (*s4) { if (*s4 < '!') { rc = 1; break; }; s4++; }
3945                     if (rc == 0) makestr(&(p[i+1]),s3);
3946                 }
3947 
3948                 /* And that it's not a number, etc. */
3949                 if (rc > 0 || isdigit(c) || c == '(') {
3950                     printf("?Invalid assignment - \"%s\"\n",s);
3951                     sexprc++;
3952                     goto xdosexp;
3953                 } else if (isalpha(c)) {
3954                     rc = xlookup(sexpconsts,s3,nsexpconsts,NULL);
3955                     if (rc > 0) {
3956                         printf("?Assignment to constant - \"%s\"\n",s);
3957                         sexprc++;
3958                         goto xdosexp;
3959                     }
3960                 }
3961 
3962                 /* If ++ or --, get current value of variable */
3963                 if (x == SX_INC || x == SX_DEC) {
3964                     int ok = 1;
3965                     char buf[32];
3966                     if (c == CMDQ) {    /* A backslash variable */
3967                         int n = 32;
3968                         char * s = buf;
3969                         buf[0] = NUL;
3970                         if (zzstring(s3,&s,&n) < 0 || !buf[0])
3971                           ok = 0;
3972                         s2 = buf;
3973                     } else {            /* A macro */
3974                         if ((k = mxlook(mactab,s3,nmac)) < 0)
3975                           ok = 0;
3976                         else
3977                           s2 = mactab[k].mval;
3978                     }
3979                     if (!ok) {
3980                         printf("?Not defined - \"%s\"\n",p[i+1]);
3981                         sexprc++;
3982                         goto xdosexp;
3983                     }
3984                     if (!s2) s2 = "";
3985                     k = xxfloat(s2,0);
3986                     if (k < 1) {
3987                         printf("?Not numeric - \"%s\"\n",p[i+1]);
3988                         sexprc++;
3989                         goto xdosexp;
3990                     }
3991                     while (*s2 == '+') s2++;
3992                     result = ckatofs(s2);
3993                     fpresult = floatval;
3994                     if (k > 1 || fpresult != result)
3995                       fpflag++;
3996                 }
3997                 if (n < i+2) {          /* Variable with no value */
3998                     s2 = "";
3999                     if (x == SX_SET || x == SX_LET) {
4000                         delmac(p[i+1],1); /* Delete the variable */
4001                         break;
4002                     } else {
4003                         s2 = "1";
4004                     }
4005                 } else {                /* Variable with value */
4006                     k = xxfloat(p[i+2],0); /* Is it a number? */
4007                     if (k > 0) {
4008                         s2 = p[i+2];
4009                         while (*s2 == '+') s2++;
4010                     } else {
4011                         s2 = dosexp(p[i+2]); /* Have value, evaluate it */
4012                         if (sexprc) goto xdosexp;
4013                         if (!s2) s2 = "";
4014                         if (!*s2 && (x == SX_INC || x == SX_DEC))
4015                           continue;
4016                     }
4017                 }
4018                 if (x == SX_INC || x == SX_DEC) {
4019                     k = xxfloat(s2,0);
4020                     if (k < 1) {
4021                         printf("?Not numeric - \"%s\"\n",s2);
4022                         sexprc++;
4023                         goto xdosexp;
4024                     }
4025                     while (*s2 == '+') s2++;
4026                     j = ckatofs(s2);
4027                     if (k > 1) {
4028                         fpj = floatval;
4029                         fpflag++;
4030                     } else {
4031                         fpj = (CKFLOAT)j;
4032                     }
4033                     if (x == SX_INC) {
4034                         result += j;
4035                         fpresult += fpj;
4036                     } else if (x == SX_DEC) {
4037                         result -= j;
4038                         fpresult -= fpj;
4039                     }
4040 #ifdef FNFLOAT
4041                     if (result != fpresult) fpflag++;
4042 #endif	/* FNFLOAT */
4043                     s2 = (fpflag && !sexptrunc) ?
4044 			fpformat(fpresult,0,0) : ckfstoa(result);
4045                 }
4046                 if (x == SX_LET && cmdlvl > 0) /* LET makes var local */
4047                   addlocal(p[i+1]);
4048                 if ((rc = addmac(p[i+1],s2)) < 0) { /* Add the value */
4049                     switch (rc) {
4050                       case -3: m = "Array not declared"; break;
4051                       case -2: m = "Subscript out of range"; break;
4052                       case -4: m = "Out of memory"; break;
4053                       default: m = "Error creating variable";
4054                     }
4055                     printf("?%s - \"%s\"\n",m,s);
4056                     sexprc++;
4057                     goto xdosexp;
4058                 }
4059                 if (s2) result = ckatofs(s2);
4060             }
4061             goto xdosexp;
4062         } else if (x == SX_IFC) {               /* Conditional expression */
4063             int true = 0;
4064             if (n > 4) {
4065                 printf("?Too many operands: IF - \"%s\"\n",s);
4066                 sexprc++;
4067                 goto xdosexp;
4068             }
4069             s2 = dosexp(p[2]);
4070             if (sexprc) goto xdosexp;
4071             if (s2) {
4072                 j = ckatofs(s2);
4073                 if (xxfloat(s2,0) == 2) {
4074                     fpflag++;
4075                     fpresult = (CKFLOAT)result;
4076                     fpj = floatval;
4077                 } else {
4078                     fpj = atof(s2);
4079                 }
4080                 true = ((fpj != 0.0) ? 1 : 0);
4081             }
4082             if (!true && n < 4) {
4083                 s2 = NULL;
4084             } else {
4085                 s2 = dosexp(true ? p[3] : p[4]);
4086                 if (sexprc) goto xdosexp;
4087                 j = s2 ? ckatofs(s2) : 0;
4088                 if (xxfloat(s2,0) == 2) {
4089                     fpflag++;
4090                     fpresult = (CKFLOAT)result;
4091                     fpj = floatval;
4092                 } else {
4093                     fpj = s2 ? atof(s2) : 0.0;
4094                 }
4095                 fpresult = fpj;
4096                 result = j;
4097             }
4098             goto xdosexp;
4099         } else if (x == SX_QUO) {
4100             int k, xx;
4101             xx = strlen(p[2]);
4102             p[3] = (char *)malloc(xx+4);
4103             s2 = p[3];
4104             ckmakmsg(p[3],xx+4,"'(",p[2],")",NULL);
4105             n++;
4106             goto xdosexp;
4107         } else if (x == SX_UNQ) {       /* UNQUOTE */
4108             int k, xx = 0;
4109             s2 = p[2];
4110             if (!s2) s2 = "";
4111             xx = strlen(s2);
4112 //            printf("XXX ENTRY: %s, len=%d\n",s2,xx);
4113             if (xx = 0)                 /* Null or empty arg */
4114               goto xdosexp;
4115 
4116             /* Case 0 - number */
4117             if (isfloat(s2,0))
4118               goto xdosexp;
4119 
4120             /* Case 2 - S-expression that evaluates to a quoted string */
4121             if (s2[0] == '(' && s2[xx-1] == ')') {
4122 //                printf("XXX SEXP: %s\n",p[2]);
4123                 s2 = dosexp(s2);
4124 //                printf("XXX SEXP EVALUATED: %s\n",p[2]);
4125             } else if (s2[0] != '\047') {
4126             /* Case 3 - Variable */
4127 //                printf("XXX MACRO NAME: %s\n",p[2]);
4128                 if ((k = mxlook(mactab,p[2],nmac)) >= 0) {
4129                     s2 = mactab[k].mval;
4130 //                    printf("XXX MACRO VALUE: %s\n",s2);
4131                 } else {
4132 //                    printf("XXX UNDEFINED MACRO: %s\n",p[2]);
4133                     s2 = "";
4134                 }
4135             }
4136             /* If result is a quoted string, unquote it */
4137 //            printf("XXX BEFORE UNQUOTING: %s\n",s2);
4138             xx = strlen(s2);
4139             if (s2[0] == '\047' && s2[1] == '(' && s2[xx-1] == ')') {
4140 //                printf("XXX HAVE QUOTED STRING: %s\n",s2);
4141                 s2[xx-1] = NUL;
4142                 s2 += 2;
4143             }
4144 //            printf("XXX RESULT: %s\n",s2);
4145             goto xdosexp;
4146 
4147         } else if (x == SX_STR) {
4148             int xx;
4149             s2 = dosexp(p[2]);
4150             if (sexprc) goto xdosexp;
4151             xx = strlen(s2);
4152             p[3] = (char *)malloc(xx+4);
4153             ckmakmsg(p[3],xx+4,"'(",s2,")",NULL);
4154             s2 = p[3];
4155             n++;
4156             goto xdosexp;
4157         }
4158     }
4159     /* Arithmetic operator or macro - Loop thru operands */
4160 
4161     quit = 0;                           /* Short-circuit flag. */
4162     if (macro && n > 1) {               /* If operator is a macro */
4163         if (!line) {                    /* allocate local buffer for */
4164             line = (char *)malloc(SXMLEN); /* the evaluated argument list. */
4165             if (!line) {
4166                 printf("?Memory allocation failure - \"%s\"\n",p[1]);
4167                 sexprc++;
4168                 goto xdosexp;
4169             }
4170             linelen = SXMLEN;
4171             /* debug(F101,"dosexp macro arg buffer","",linelen); */
4172         }
4173         linepos = 0;
4174         line[linepos] = NUL;
4175     }
4176     for (i = 1; ((i < n) && !sexprc && !quit); i++) { /* Loop thru operands */
4177         quote = 0;
4178         s2 = p[i+1];                    /* Get operand */
4179         if (!s2) s2 = "";
4180 
4181 #ifdef COMMENT
4182         if (*s2 == '\047') {            /* Is it quoted? */
4183             debug(F110,sexpdebug("'B"),s2,0);
4184             s2++;                       /* Space past the quote */
4185             quote++;
4186             if (*s2 == '(') {           /* Quoted S-Expression? */
4187                 char c4, * s4 = s2+1;   /* Strip outer parens */
4188                 while ((c4 = *s4++)) {
4189                     if (c4 == ')' && !*s4) {
4190                         s2++;
4191                         *(s4-1) = NUL;
4192                         break;
4193                     }
4194                 }
4195             }
4196             debug(F110,sexpdebug("'C"),s2,0);
4197 
4198         } else {                        /* Not quoted */
4199             s2 = dosexp(p[i+1]);        /* evaluate it */
4200             if (sexprc) goto xdosexp;
4201             if (!s2) s2 = "";
4202             if (!macro && x == SX_EVA)
4203               continue;
4204         }
4205 #else
4206         if (*s2 != '\047') {            /* Not quoted */
4207 //            printf("XXX UNQUOTED ARG %s\n",s2);
4208             if (x == SX_ECH && (k = mxlook(mactab,s2,nmac)) > -1) {
4209                 s2 = mactab[k].mval;
4210 //                printf("XXX MACRO DEF %s\n",s2);
4211             } else {
4212               s2 = dosexp(s2);      /* No, evaluate it */
4213 //              printf("XXX SEXP VALUE %s\n",s2);
4214             }
4215             if (sexprc && x != SX_ECH)
4216                 goto xdosexp;
4217             if (!s2) s2 = "";
4218             if (!macro && x == SX_EVA)
4219               continue;
4220             if (x == SX_ECH) {          /* ECHO */
4221                 printf("%s ",s2);
4222                 if (i == n-1) printf("\n");
4223                 continue;
4224             }
4225         }
4226         if (*s2 == '\047') {            /* Is result quoted? */
4227             debug(F110,sexpdebug("'B"),s2,0);
4228             s2++;                       /* Space past the quote */
4229             quote++;
4230             if (*s2 == '(') {           /* Quoted S-Expression? */
4231                 char c4, * s4 = s2+1;   /* Strip outer parens */
4232                 while ((c4 = *s4++)) {
4233                     if (c4 == ')' && !*s4) {
4234                         s2++;
4235                         *(s4-1) = NUL;
4236                         break;
4237                     }
4238                 }
4239             }
4240             debug(F110,sexpdebug("'C"),s2,0);
4241             if (x == SX_ECH) {          /* ECHO */
4242                 printf("%s ",s2);
4243                 if (i == n-1) printf("\n");
4244                 continue;
4245             }
4246         }
4247 #endif /* COMMENT */
4248         if (macro) {
4249             debug(F111,sexpdebug("macro arg"),s2,i);
4250             if (!*s2) quote++;
4251             if (!quote) {
4252                 register char c4, * s4 = s2;
4253                 while ((c4 = *s4++)) if (c4 == SP) { quote++; break; }
4254             }
4255             if (quote) line[linepos++] = '{';
4256             while ((line[linepos++] = *s2++)) {
4257                 if (linepos > linelen - 3) {
4258                     char * tmp = NULL;
4259                     line[linepos] = NUL;
4260                     linelen += SXMLEN;
4261                     tmp = (char *) malloc(linelen);
4262                     if (!tmp) {
4263                         printf("?Memory re-allocation failure - \"%s...\"\n",
4264                                line);
4265                         sexprc++;
4266                         goto xdosexp;
4267                     }
4268                     strcpy(tmp,line);
4269                     free(line);
4270                     line = tmp;
4271                 }
4272             }
4273             linepos--;                  /* Back up over NUL */
4274             if (quote)
4275               line[linepos++] = '}';    /* End quote group */
4276             line[linepos++] = SP;       /* add a space */
4277             line[linepos] = NUL;        /* and a NUL */
4278             continue;
4279         }
4280         if (!quote) {                   /* Built-in operator... */
4281             s2 = dosexp(s2);
4282             if (sexprc) goto xdosexp;
4283             if (!s2) s2 = "";
4284         }
4285         if (x == SX_EVA)
4286           continue;
4287 
4288         if (!*s2) {
4289             /* An empty value is not a legal number */
4290             /* but it is a legal truth value */
4291             if (x != SX_AND && x != SX_LOR && x != SX_NOT) {
4292                 printf("?Not Numeric - \"%s\"\n",p[i+1]);
4293                 sexprc++;
4294                 goto xdosexp;
4295             }
4296             j = 0;
4297             fpj = 0.0;
4298         } else {
4299             j = ckatofs(s2);
4300             /* Switch to floating-point upon encountering any f.p. arg */
4301             /* OR... if integer is too big */
4302             if (!fpflag) if (xxfloat(s2,0) == 2)
4303               fpflag++;
4304             fpj = atof(s2);
4305         }
4306         if (i == 1) {                   /* Initial result is first operand */
4307             result = (n == 2 && x == SX_SUB) ? 0-j : j;
4308             fpresult = (n == 2 && x == SX_SUB) ? -fpj : fpj;
4309 	    if ((x == SX_AND && result == 0) ||	/* Short circuit */
4310 		(x == SX_LOR && result != 0))
4311 	      quit++;
4312             if (!(kwflags & SXF_ONE))	/* Command w/single arg */
4313               continue;
4314         }
4315         if (x == SX_MOD || x == SX_DIV) {
4316             if (!result)
4317               fpflag++;
4318             if (!fpj) {
4319                 printf("?Divide by zero - \"%s\"\n",cmdbuf);
4320                 sexprc++;
4321                 goto xdosexp;
4322             }
4323         }
4324         switch (x) {			/* Accumulate result */
4325 
4326           case SX_EVA:                  /* EVAL */
4327             result = j;
4328             fpresult = fpj;
4329             break;
4330 
4331           case SX_ADD:                  /* + */
4332             result += j;
4333             fpresult += fpj;
4334 #ifdef FNFLOAT
4335             if (result != fpresult)
4336               fpflag++;
4337 #endif	/* FNFLOAT */
4338             break;
4339 
4340           case SX_SUB:                  /* - */
4341             result -= j;
4342             fpresult -= fpj;
4343 #ifdef FNFLOAT
4344             if (result != fpresult)
4345               fpflag++;
4346 #endif	/* FNFLOAT */
4347             break;
4348 
4349           case SX_MUL:                  /* * */
4350             result *= j;
4351             fpresult *= fpj;
4352 #ifdef FNFLOAT
4353             if (result != fpresult)
4354               fpflag++;
4355 #endif	/* FNFLOAT */
4356             break;
4357 
4358           case SX_AND:                  /* AND */
4359             result = result && j;
4360             if (!result) quit++;
4361             fpresult = fpresult && fpj;
4362             break;
4363 
4364           case SX_LOR:                  /* OR */
4365             result = result || j;
4366             if (!result) quit++;
4367             fpresult = fpresult || fpj;
4368             break;
4369 
4370           case SX_MOD:                  /* Modulus */
4371             result = result % j;
4372 #ifdef FNFLOAT
4373             fpresult = (CKFLOAT)fmod(fpresult,fpj);
4374             if (result != fpresult)
4375               fpflag++;
4376 #else
4377             fpresult = result;
4378 #endif /* FNFLOAT */
4379             break;
4380 
4381           case SX_DIV:                  /* / */
4382 	    if (j) {
4383 		result /= j;
4384 		fpresult /= fpj;
4385 #ifdef FNFLOAT
4386 		if (result != fpresult)
4387 		  fpflag++;
4388 #endif	/* FNFLOAT */
4389 	    } else {
4390 		fpresult /= fpj;
4391 		result = fpj;
4392 #ifdef FNFLOAT
4393 		  fpflag++;
4394 #endif	/* FNFLOAT */
4395 	    }
4396             break;
4397 
4398           case SX_AEQ:                  /* Test for equality */
4399             if (fpflag) {
4400                 if (fpresult != fpj)
4401                   presult = 0;
4402             } else {
4403                 if (result != j)
4404                   presult = 0;
4405             }
4406             break;
4407 
4408           case SX_NEQ:                  /* Test for ineqality */
4409             if (fpflag) {
4410                 if (fpresult == fpj)
4411                   presult = 0;
4412             } else {
4413                 if (result == j)
4414                   presult = 0;
4415             }
4416             break;
4417 
4418           case SX_ALE:                  /* Arithmetic less-equal */
4419             if (fpflag) {
4420                 if (fpj < fpresult)
4421                   presult = 0;
4422                 fpresult = fpj;
4423             } else {
4424                 if (j < result)
4425                   presult = 0;
4426                 result = j;
4427             }
4428             break;
4429 
4430           case SX_ALT:                  /* Arithmetic less-than */
4431             if (fpflag) {
4432                 if (fpj <= fpresult)
4433                   presult = 0;
4434                 fpresult = fpj;
4435             } else {
4436                 if (j <= result)
4437                   presult = 0;
4438                 result = j;
4439             }
4440             break;
4441 
4442           case SX_AGT:                  /* Arithmetic greater-than */
4443             if (fpflag) {
4444                 if (fpj >= fpresult)
4445                   presult = 0;
4446                 fpresult = fpj;
4447             } else {
4448                 if (j >= result)
4449                   presult = 0;
4450                 result = j;
4451             }
4452             break;
4453 
4454           case SX_AGE:                  /* Arithmetic greater-equal */
4455             if (fpflag) {
4456                 if (fpj > fpresult)
4457                   presult = 0;
4458                 fpresult = fpj;
4459             } else {
4460                 if (j > result)
4461                   presult = 0;
4462                 result = j;
4463             }
4464             break;
4465 
4466           case SX_POW:                  /* Raise to power */
4467 #ifdef FNFLOAT
4468             {
4469                 double dummy;
4470                 if (!fpj) {
4471                     fpresult = 1.0;
4472                 } else if ((!fpresult && fpj <= 0.0)) {
4473                     printf("?Divide by zero - \"%s\"\n",cmdbuf);
4474                     sexprc++;
4475                     goto xdosexp;
4476                 } else if (fpresult < 0.0 && modf(fpj,&dummy)) {
4477                     printf("?Domain error - \"%s\"\n",cmdbuf);
4478                     sexprc++;
4479                     goto xdosexp;
4480                 } else {
4481                     fpresult = (CKFLOAT)pow(fpresult,fpj);
4482                 }
4483             }
4484 #endif /* FNFLOAT */
4485             if (j == 0) {
4486                 result = 1;
4487             } else {
4488                 CK_OFF_T z, sign = 0;
4489                 if (j < 0) {
4490                     if (result == 0) {
4491                         printf("?Divide by zero - \"%s\"\n",cmdbuf);
4492                         sexprc++;
4493                         goto xdosexp;
4494                     }
4495                     j = 0 - j;
4496                     sign++;
4497                 }
4498                 z = result;
4499                 while (--j > 0)
4500                   result *= z;
4501                 if (sign)
4502                   result = 1 / result;
4503             }
4504 #ifdef FNFLOAT
4505             if (result != fpresult)
4506               fpflag++;
4507 #endif	/* FNFLOAT */
4508             break;
4509 
4510 #ifdef FNFLOAT
4511           case SX_EXP:                  /* e to the given power */
4512             fpresult = (CKFLOAT) exp(fpj);
4513             break;
4514 
4515           case SX_LGN:                  /* Natural log */
4516           case SX_LGX:                  /* Log base 10 */
4517           case SX_SQR:                  /* Square root */
4518             if (fpj < 0.0) {
4519                 printf("?Argument out of range - \"%s\"\n",cmdbuf);
4520                 sexprc++;
4521                 goto xdosexp;
4522             }
4523             if (x == SX_SQR)
4524               fpresult = (CKFLOAT) sqrt(fpj);
4525             else if (x == SX_LGN)
4526               fpresult = (CKFLOAT) log(fpj);
4527             else
4528               fpresult = (CKFLOAT) log10(fpj);
4529             break;
4530 
4531           case SX_SIN:                  /* sine */
4532             fpresult = (CKFLOAT) sin(fpj);
4533             break;
4534 
4535           case SX_COS:                  /* cosine */
4536             fpresult = (CKFLOAT) cos(fpj);
4537             break;
4538 
4539           case SX_TAN:                  /* tangent */
4540             fpresult = (CKFLOAT) tan(fpj);
4541             break;
4542 #endif /* FNFLOAT */
4543 
4544           case SX_CEI:                  /* Ceiling */
4545             if (j != fpj)
4546               if (fpj > 0.0)
4547                 fpj += 1.0;
4548             fpresult = fpj;
4549             fpflag = 1;
4550             truncate = 1;
4551             break;
4552 
4553           case SX_FLR:                  /* Floor */
4554             if (j != fpj)
4555               if (fpj < 0.0)
4556                 fpj -= 1.0;
4557             fpresult = fpj;
4558             fpflag = 1;
4559             truncate = 1;
4560             break;
4561 
4562           case SX_TRU:                  /* Truncate */
4563             fpresult = fpj;
4564             fpflag = 1;
4565             truncate = 1;
4566             break;
4567 
4568           case SX_ABS:                  /* Absolute value */
4569             result = (j < 0) ? 0 - j : j;
4570 #ifdef FNFLOAT
4571             fpresult = (fpj < 0.0) ? 0.0 - fpj : fpj;
4572             if (result != fpresult)
4573               fpflag++;
4574 #endif	/* FNFLOAT */
4575             break;
4576 
4577           case SX_MAX:                  /* Max */
4578             if (j != fpj)
4579               fpflag++;
4580             if (fpflag) {
4581                 if (fpj > fpresult)
4582                   fpresult = fpj;
4583             } else
4584               if (j > result)
4585                 result = j;
4586             break;
4587 
4588           case SX_MIN:                  /* Min */
4589             if (j != fpj)
4590               fpflag++;
4591             if (fpflag) {
4592                 if (fpj < fpresult)
4593                   fpresult = fpj;
4594             } else
4595               if (j < result)
4596                 result = j;
4597             break;
4598 
4599           case SX_FLO:                  /* Float */
4600             fpflag++;
4601             fpresult = result;
4602             fpj = j;
4603             break;
4604 
4605           case SX_NOT:                  /* NOT (reverse truth value) */
4606             fpflag = 0;
4607             not++;
4608             break;
4609 
4610           case SX_BWA:                  /* Bitwise AND */
4611             fpflag = 0;
4612             result &= j;
4613             break;
4614 
4615           case SX_BWO:                  /* Bitwise OR */
4616             fpflag = 0;
4617             result |= j;
4618             break;
4619 
4620           case SX_BWX:                  /* Bitwise XOR */
4621           case SX_XOR:                  /* Logical XOR */
4622             if (n > 3) {
4623                 printf("?Too many operands - \"%s\"\n",s);
4624                 sexprc++;
4625                 goto xdosexp;
4626             }
4627             fpflag = 0;
4628             if (x == SX_BWX) {
4629                 result ^= j;
4630             } else {
4631                 result = (result && !j) || (!result && j);
4632                 if (result) result = 1;
4633             }
4634             break;
4635 
4636           case SX_BWN:                  /* Bitwise Not */
4637             fpflag = 0;
4638             result = ~result;
4639             break;
4640 
4641           default:
4642             printf("BAD OP [%s]\n",p[1]);
4643             sexprc++;
4644         }
4645     }
4646     if (!pflag)                         /* Not a predicate */
4647       sexppv = -1;                      /* So unset this */
4648 
4649   /* domacro: */
4650 
4651     if (macro) {                        /* User-defined macro */
4652         extern int fsexpflag;           /* (see fneval():ckuus4.c) */
4653         int lookagain = 0;              /* Maybe the macro table changed */
4654         if (mactab[mx].kwd) {           /* Check and see */
4655             if (ckstrcmp(mactab[mx].kwd,p[1],-1,0))
4656               lookagain++;
4657         } else
4658           lookagain++;
4659         if (lookagain) {                /* The table changed */
4660             mx = mxlook(mactab,p[1],nmac); /* Get the macro's new index */
4661             debug(F111,sexpdebug("macro moved"),p[1],mx);
4662             if (mx < 0) {                  /* Yikes! */
4663                 printf("?Macro disappeared! - \"%s\"\n",p[1]);
4664                 sexprc++;
4665                 goto xdosexp;
4666             }
4667         }
4668         debug(F111,sexpdebug("macro mx"),mactab[mx].kwd,mx);
4669         if (fsexpflag) {                /* If embedded in a function call */
4670             if (cmpush() > -1) {        /* get a new copy of the parsing */
4671                 extern int ifc;         /* environment, */
4672                 int k, ifcsav = ifc;    /* save the IF state */
4673                 dodo(mx,line,0);        /* Set up the macro */
4674                 k = parser(1);          /* Call the parser to execute it */
4675                 cmpop();                /* Pop back to previous level */
4676                 ifc = ifcsav;           /* restore IF state */
4677                 if (k == 0)             /* If no error */
4678                   s2 = mrval[maclvl+1]; /* get return value, if any */
4679                 if (!s2) s2 = "";
4680                 debug(F110,sexpdebug("macro return"),s2,0);
4681             } else {
4682                 printf("?Resources exhausted - \"%s\"\n",s);
4683                 sexprc++;
4684             }
4685         } else {                        /* Not embedded in a function call */
4686             dodo(mx,line,0);            /* As above but without cmpush/pop() */
4687             k = parser(1);
4688             if (k == 0)
4689               s2 = mrval[maclvl+1];
4690             if (!s2) s2 = "";
4691         }
4692     } else if (pflag) {                 /* Predicate */
4693         if (not) presult = presult ? 0 : 1;
4694         sexppv = presult;               /* So set predicate value (0 or 1) */
4695         s2 = presult ? "1" : "0";
4696     } else if (fpflag && !sexptrunc) {	/* Result is floating-point */
4697         if (not) fpresult = fpresult ? 0.0 : 1.0;
4698         s2 = fpformat(fpresult,0,0);
4699     } else if (x != SX_EVA) {
4700         if (not) result = result ? 0 : 1;
4701         s2 = ckfstoa(result);
4702     }
4703 
4704 /* Common exit point.  Always come here to exit. */
4705 
4706   xdosexp:
4707 
4708     if (!s2) s2 = "";
4709     debug(F111,"xdosexp s2",s2,sexprc);
4710 //    printf("XXX xdosexp s2=[%s]\n",s2);
4711     if (x == SX_ECH) s2 = "";
4712     debug(F111,"xdosexp s2 ECHO",s2,sexprc);
4713 
4714     if (!sexprc /* && *s2 */) {	    /* Have a result */
4715         char * sx;                  /* Note -- do this even if result empty */
4716         char * q2 = s2; int xx = 0;
4717         if (*s2) {
4718             while (*q2++) xx++;         /* Get length */
4719             if (xx > sexprmax)          /* (stats) */
4720               sexprmax = xx;
4721         } else
4722           xx = 0;
4723         if (xx > sxrlen[sexpdep] || !sxresult[sexpdep]) {
4724             int k;
4725             k = xx + xx / 4;
4726             if (k < 32) k = 32;
4727             if (sxresult[sexpdep])
4728               free(sxresult[sexpdep]);
4729             if ((sxresult[sexpdep] = (char *)malloc(k))) {
4730                 sxrlen[sexpdep] = k;
4731             } else {
4732                 printf("?Memory allocation failure - \"%s\"\n",s2);
4733                 sexprc++;
4734             }
4735         }
4736         sx = sxresult[sexpdep];         /* Point to result buffer */
4737         while ((*sx++ = *s2++)) ;       /* copy result. */
4738         if (fpflag && truncate) {       /* Floating point + truncate */
4739             sx = sxresult[sexpdep];     /* at decimal point */
4740             for (i = xx - 1; i >= 0; i--) {
4741                 if (sx[i] == '.') {
4742                     sx[i] = NUL;
4743                     if (i == 0) {       /* If nothing left */
4744                         sx[0] = '0';    /* put a zero. */
4745                         sx[1] = NUL;
4746                     }
4747                 }
4748             }
4749         }
4750     }
4751   xxdosexp:
4752     if (line)                           /* If macro arg buffer allocated */
4753       free(line);                       /* free it. */
4754     if (mustfree) {                     /* And free local copy of split list */
4755         for (i = 1; i <= n; i++) {
4756             if (p[i]) free(p[i]);
4757         }
4758     }
4759     debug(F111,sexpdebug("exit"),sxresult[sexpdep],sexprc);
4760     s = sxresult[sexpdep--];
4761     if (!s) s = "";
4762     return(s);
4763 }
4764 #endif /* NOSEXP */
4765 #endif /* NOSPL */
4766 
4767 int                                     /* CHECK command */
dochk()4768 dochk() {
4769     int x, y;
4770     if ((y = cmkey(ftrtab,nftr,"","",xxstring)) < 0)
4771       return(y);
4772     ckstrncpy(line,atmbuf,LINBUFSIZ);
4773     if ((y = cmcfm()) < 0)
4774       return(y);
4775 #ifdef HAVE_LOCALE
4776     if (!ckstrcmp(line,"locale",(int)strlen(line),0)) {
4777 	extern int nolocale;
4778 	int ok = 0;
4779         ok = (nolocale ? 0 : 1);
4780 	if (msgflg)
4781           printf(" locale%s available\n", ok ? "" : " not");
4782         else if (nolocale && !backgrd)
4783           printf(" CHECK: locale not available\n");
4784         return(success = ok);
4785     }
4786 #endif /* HAVE_LOCALE */
4787 #ifndef NOPUSH
4788     if (!ckstrcmp(line,"push",(int)strlen(line),0)) {
4789         if (msgflg)                     /* If at top level... */
4790           printf(" push%s available\n", nopush ? " not" : "");
4791         else if (nopush && !backgrd)
4792           printf(" CHECK: push not available\n");
4793         return(success = 1 - nopush);
4794     }
4795 #endif /* NOPUSH */
4796 #ifdef PIPESEND
4797     if (!ckstrcmp(line,"pipes",(int)strlen(line),0)) {
4798         if (msgflg)                     /* If at top level... */
4799           printf(" pipes%s available\n",
4800                  (nopush || protocol != PROTO_K) ? " not" : "");
4801         else if ((nopush || protocol != PROTO_K) && !backgrd)
4802           printf(" CHECK: pipes not available\n");
4803         return(success = 1 - nopush);
4804     }
4805 #endif /* PIPESEND */
4806     y = lookup(ftrtab,line,nftr,&x);    /* Look it up */
4807     debug(F111,"dochk",ftrtab[x].kwd,y);
4808     if (msgflg)                         /* If at top level... */
4809       printf(" %s%s available\n", ftrtab[x].kwd, y ? " not" : "");
4810     else if (y && !backgrd)
4811       printf(" CHECK: %s not available\n", ftrtab[x].kwd);
4812     return(success = 1 - y);
4813 }
4814 
4815 #ifndef NOLOCAL
4816 #ifdef CKLOGDIAL
4817 
4818 /* Connection log and elapsed-time reporting */
4819 
4820 extern char cxlogbuf[];                 /* Log record buffer */
4821 extern char diafil[];                   /* Log file name */
4822 extern int dialog, cx_active;           /* Flags */
4823 static long cx_prev = 0L;               /* Elapsed time of previous session */
4824 
4825 #endif /* CKLOGDIAL */
4826 #endif /* NOLOCAL */
4827 
4828 VOID
dologend()4829 dologend() {                            /* Write record to connection log */
4830 #ifdef LOCUS
4831     extern int locus, autolocus;
4832 #endif /* LOCUS */
4833 
4834 #ifndef NOLOCAL
4835 #ifdef CKLOGDIAL
4836     long d1, d2, t1, t2;
4837     char buf[32], * p;
4838 #endif /* CKLOGDIAL */
4839 #endif /* NOLOCAL */
4840 
4841 #ifdef LOCUS
4842     if (autolocus) {
4843         int x = locus;
4844 #ifdef NEWFTP
4845 	debug(F101,"dologend ftpisconnected","",ftpisconnected());
4846         setlocus(ftpisconnected() ? 0 : 1, 1);
4847 #else
4848         setlocus(1,1);
4849 #endif /* NEWFTP */
4850     }
4851 #endif /* LOCUS */
4852 
4853 #ifndef NOLOCAL
4854 #ifdef CKLOGDIAL
4855     debug(F101,"dologend dialog","",dialog);
4856     debug(F101,"dologend cxlogbuf[0]","",cxlogbuf[0]);
4857 #ifdef CKSYSLOG
4858     debug(F101,"dologend ckxlogging","",ckxlogging);
4859 #endif /* CKSYSLOG */
4860 
4861     if (!cx_active || !cxlogbuf[0])     /* No active record */
4862       return;
4863 
4864     cx_active = 0;                      /* Record is not active */
4865     debug(F111,"dologend cxlogbuf 1",cxlogbuf,cx_active);
4866 
4867     d1 = mjd((char *)cxlogbuf);         /* Get start date of this session */
4868     ckstrncpy(buf,ckdate(),31);         /* Get current date */
4869     d2 = mjd(buf);                      /* Convert them to mjds */
4870     p = cxlogbuf;                       /* Get start time */
4871     p[11] = NUL;
4872     p[14] = NUL;                        /* Convert to seconds */
4873     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4874     p[11] = ':';
4875     p[14] = ':';
4876     p = buf;                            /* Get end time */
4877     p[11] = NUL;
4878     p[14] = NUL;
4879     t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4880     t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Compute elapsed time */
4881     debug(F101,"dologend t2","",t2);
4882     if (t2 > -1L) {
4883         cx_prev = t2;
4884         p = hhmmss(t2);
4885         debug(F110,"dologend hhmmss",p,0);
4886         ckstrncat(cxlogbuf,"E=",CXLOGBUFL); /* Append to log record */
4887         ckstrncat(cxlogbuf,p,CXLOGBUFL);
4888         debug(F110,"dologend cxlogbuf 2",cxlogbuf,0);
4889     } else
4890       cx_prev = 0L;
4891     debug(F101,"dologend cx_prev","",cx_prev);
4892     if (dialog) {                       /* If logging */
4893         int x;
4894         x = diaopn(diafil,1,1);         /* Open log in append mode */
4895         debug(F101,"dologend diaopn","",x);
4896         x = zsoutl(ZDIFIL,cxlogbuf);    /* Write the record */
4897         debug(F101,"dologend zsoutl","",x);
4898         x = zclose(ZDIFIL);             /* Close the log */
4899         debug(F101,"dologend zclose","",x);
4900     }
4901 #ifdef CKSYSLOG
4902     debug(F101,"dologend ckxlogging","",ckxlogging);
4903     if (ckxlogging) {
4904         int x;
4905         x = ckindex("T=DIAL",cxlogbuf,0,0,1);
4906         debug(F111,"dologend ckxsyslog",cxlogbuf,ckxsyslog);
4907         debug(F111,"dologend ckindex","T=DIAL",x);
4908         if (x > 0) {
4909             if (ckxsyslog >= SYSLG_DI) {
4910                 debug(F110,"dologend syslog",cxlogbuf+18,0);
4911                 cksyslog(SYSLG_DI,1,"CONNECTION",(char *)(cxlogbuf+18),"");
4912             } else if (ckxsyslog >= SYSLG_AC) {
4913                 debug(F110,"dologend syslog",cxlogbuf+18,0);
4914                 cksyslog(SYSLG_AC,1,"CONNECTION",(char *)(cxlogbuf+18),"");
4915             }
4916         }
4917     }
4918 #endif /* CKSYSLOG */
4919 #endif /* CKLOGDIAL */
4920 #endif /* NOLOCAL */
4921 }
4922 
4923 #ifndef NOLOCAL
4924 #ifdef CKLOGDIAL
4925 
4926 /*  D O L O G S H O W  --  Show session/connection info  */
4927 
4928 /* Call with fc == 1 to show, fc == 0 to only calculate. */
4929 /* Returns session elapsed time in seconds. */
4930 /* If no session active, returns elapsed time of previous session, if any, */
4931 /* otherwise 0 */
4932 
4933 long
dologshow(fc)4934 dologshow(fc) int fc; {                 /* SHOW (current) CONNECTION */
4935     long d1, d2, t1, t2 = 0, prev;
4936     char c, buf1[32], buf2[32], * info[32], * p, * s;
4937     char * xlogbuf, xbuf[CXLOGBUFL+1];
4938     int i, x = 0, z, ftp = 0, active = 0;
4939 
4940 #ifdef NEWFTP
4941     extern char ftplogbuf[];
4942     extern long ftplogprev;
4943     extern int ftplogactive;
4944     if (fc & W_FTP) {
4945         fc &= 63;
4946         ftp = 1;
4947         xlogbuf = ftplogbuf;
4948         prev = ftplogprev;
4949         active = ftplogactive;
4950     } else {
4951 #endif /* NEWFTP */
4952         ftp = 0;
4953         xlogbuf = cxlogbuf;
4954         prev = cx_prev;
4955         active = cx_active;
4956 #ifdef NEWFTP
4957     }
4958 #endif /* NEWFTP */
4959 
4960     debug(F101,"dologshow local","",local);
4961     debug(F101,"dologshow ftp","",ftp);
4962     debug(F111,"dologshow active",xlogbuf,active);
4963 
4964     if (!xlogbuf[0]) {
4965         if (fc) {
4966             if (didsetlin || ftp)
4967               printf(" %s: No record.\n", ftp ? "FTP" : "Kermit");
4968             else
4969               printf(" %s: No connection.\n", ftp ? "FTP" : "Kermit");
4970         }
4971         return(prev);
4972     }
4973 
4974 #ifdef NEWFTP
4975     if (ftp) {
4976         z = ftpisconnected() ? 1 : -1;
4977     } else {
4978 #endif /* NEWFTP */
4979         if (local) {                    /* See if we have an open connection */
4980             z = ttchk();
4981             debug(F101,"dologshow ttchk","",z);
4982             z = (z > -1) ? 1 : -2;
4983         } else {
4984             z = active ? 1 : -2;
4985         }
4986 #ifdef NEWFTP
4987     }
4988 #endif /* NEWFTP */
4989     if (z < 0L) {
4990         if (!fc)
4991           return(prev);
4992         else
4993           t2 = prev;
4994     }
4995     /* Note: NOT ckstrncpy! */
4996     strncpy(buf1,xlogbuf,17);           /* Copy of just the timestamp */
4997     buf1[17] = NUL;                     /* Terminate it */
4998     ckstrncpy(xbuf,xlogbuf+18,CXLOGBUFL); /* Copy that can be poked */
4999     debug(F111,"dologshow prev",xbuf,prev);
5000 
5001     xwords(xbuf,31,info,1);             /* Break up into fields */
5002     d1 = mjd(buf1);                     /* Convert start time to MJD */
5003     ckstrncpy(buf2,ckdate(),31);        /* Current date */
5004     d2 = mjd(buf2);                     /* Convert to MJD */
5005     p = buf1;                           /* Point to start time */
5006     p[11] = NUL;
5007     p[14] = NUL;                        /* Convert to seconds */
5008     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
5009     p[11] = ':';
5010     p[14] = ':';
5011     p = buf2;                           /* Ditto for current time */
5012     p[11] = NUL;
5013     p[14] = NUL;
5014     if (z > -1L) {
5015         t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
5016         t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Elapsed time so far */
5017     }
5018     if (fc) {
5019         p = NULL;
5020         if (t2 > -1L)                   /* Convert seconds to hh:mm:ss */
5021           p = hhmmss(t2);
5022         if (z > -1)
5023           s = "Active";
5024         else if (z == -2)
5025           s = "Closed";
5026         else
5027           s = "Unknown";
5028         printf("\n");                   /* Show results */
5029         printf(" Status:       %s\n",s);
5030         printf(" Opened:       %s\n",buf1);
5031         printf(" User:         %s\n",info[1] ? info[1] : "");
5032         printf(" PID:          %s\n",info[2] ? info[2] : "");
5033         for (i = 3; info[i]; i++) {
5034             c = info[i][0];
5035             s = (info[i]) ? info[i]+2 : "";
5036             switch (c) {
5037               case 'T': printf(" Type:         %s\n", s); break;
5038               case 'N': printf(" To:           %s\n", s); break;
5039               case 'P': printf(" Port:         %s\n", s); break;
5040               case 'H': printf(" From:         %s\n", s); break;
5041               case 'D': printf(" Device:       %s\n", s); break;
5042               case 'O': printf(" Origin:       %s\n", s); break;
5043               case 'E': break;
5044               default:  printf(" %s\n",info[i] ? info[i] : "");
5045             }
5046         }
5047         if (z < 0L)
5048           printf(" Elapsed time: %s\n", hhmmss(t2));
5049         else
5050           printf(" Elapsed time: %s\n", p ? p : "(unknown)");
5051         x = 0;
5052 #ifdef NETCONN
5053 #ifdef SSHBUILTIN
5054         if ( IS_SSH() ) x++;
5055 #endif /* SSHBUILTIN */
5056 #ifdef CK_ENCRYPTION
5057         if (ck_tn_encrypting() && ck_tn_decrypting()) x++;
5058 #endif /* CK_ENCRYPTION */
5059 #ifdef CK_SSL
5060         if (tls_active_flag || ssl_active_flag) x++;
5061 #endif /* CK_SSL */
5062 #ifdef RLOGCODE
5063 #ifdef CK_KERBEROS
5064 #ifdef CK_ENCRYPTION
5065         if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) x++;
5066 #endif /* CK_ENCRYPTION */
5067 #endif /* CK_KERBEROS */
5068 #endif /* RLOGCODE */
5069 #endif /* NETCONN */
5070         if (z > 0)
5071           printf(" Encrypted:    %s\n", x ? "Yes" : "No");
5072         printf(" Log:          %s\n", dialog ? diafil : "(none)");
5073         printf("\n");
5074     }
5075     return(t2 > -1L ? t2 : 0L);
5076 }
5077 
5078 VOID
dologline()5079 dologline() {
5080     char * p;
5081     int n, m = 0;
5082 
5083     dologend();                         /* Previous session not closed out? */
5084     cx_active = 1;                      /* Record is active */
5085     cx_prev = 0L;
5086     p = ckdate();                       /* Get timestamp */
5087     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL-1); /* Start record off with it */
5088     if (!uidbuf[0]) {
5089         debug(F100,"dologline uidbuf empty","",0);
5090 #ifdef UNIX                             /* Who has whoami()... */
5091         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
5092 #else
5093 #ifdef STRATUS
5094         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
5095 #else
5096         ckstrncpy(uidbuf,"UNKNOWN",UIDBUFLEN);
5097 #endif /* STRATUS */
5098 #endif /* UNIX */
5099     }
5100     m = strlen(uidbuf) + strlen(myhost) + strlen(ttname) + 32;
5101     if (n+m < CXLOGBUFL-1) {            /* Add serial device info */
5102         p = cxlogbuf+n;
5103         sprintf(p," %s %s T=SERIAL H=%s D=%s ", /* SAFE */
5104                 uidbuf,
5105                 ckgetpid(),
5106                 myhost,
5107                 ttname
5108                 );
5109     } else
5110       ckstrncpy(cxlogbuf,"LOGLINE BUFFER OVERFLOW",CXLOGBUFL);
5111     debug(F110,"dologline",cxlogbuf,0);
5112 }
5113 
5114 #ifdef NETCONN
5115 VOID
dolognet()5116 dolognet() {
5117     char * p, * s = "NET", * uu = uidbuf;
5118     char * port = "";
5119     int n, m, tcp = 0;
5120     char * h = NULL;
5121 
5122     dologend();                         /* Previous session not closed out? */
5123     cx_prev = 0L;
5124     cx_active = 1;                      /* Record is active */
5125     p = ckdate();
5126     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL);
5127 #ifdef TCPSOCKET
5128     if (nettype == NET_TCPB || nettype == NET_TCPA) {
5129 	tcp++;
5130 	s = "TCP";
5131     } else if (nettype == NET_SSH) {
5132 	s = "SSH";
5133 	tcp++;
5134     }
5135 #endif /* TCPSOCKET */
5136 #ifdef ANYX25
5137     if (nettype == NET_SX25 || nettype == NET_VX25 || nettype == NET_IX25)
5138       s = "X25";
5139 #endif /* ANYX25 */
5140 #ifdef DECNET
5141     if (nettype == NET_DEC)
5142       s = "DECNET";
5143 #endif /* DECNET */
5144 #ifdef SUPERLAT
5145     if (nettype == NET_SLAT)
5146       s = "SUPERLAT";
5147 #endif /* SUPERLAT */
5148 #ifdef CK_NETBIOS
5149     if (nettype == NET_BIOS)
5150       s = "NETBIOS";
5151 #endif /* CK_NETBIOS */
5152 
5153     if (!uu[0]) {
5154         debug(F100,"dolognet uidbuf empty","",0);
5155 #ifdef OS2ORUNIX                        /* Who has whoami()... */
5156         uu = (char *)whoami();
5157 #else
5158 #ifdef STRATUS
5159         uu = (char *)whoami();
5160 #else
5161         uu = "UNKNOWN";
5162 #endif /* STRATUS */
5163 #endif /* UNIX */
5164     }
5165 #ifdef TCPSOCKET
5166     if (tcp) {
5167 	int k;
5168 	makestr(&h,myhost);
5169 	if ((k = ckindex(":",h,0,0,0)) > 0) {
5170 	    h[k-1] = NUL;
5171 	    port = &h[k];
5172 	} else {
5173 	    int svcnum = gettcpport();
5174 	    if (svcnum > 0)
5175 	      port = ckitoa(svcnum);
5176 	    else
5177 	      port = "unk";
5178 	}
5179     }
5180 #endif	/* TCPSOCKET */
5181     m = strlen(uu) + strlen(myhost) + strlen(ttname) + strlen(s) + 32;
5182     if (n+m < CXLOGBUFL-1) {            /* SAFE */
5183         p = cxlogbuf+n;
5184         sprintf(p," %s %s T=%s N=%s H=%s P=%s ",
5185                 uu,
5186                 ckgetpid(),
5187                 s,
5188                 ttname,
5189                 myhost,
5190 		port
5191                 );
5192     } else
5193       ckstrncpy(cxlogbuf,"LOGNET BUFFER OVERFLOW",CXLOGBUFL);
5194     debug(F110,"dolognet cxlogbuf",cxlogbuf,0);
5195     if (h) makestr(&h,NULL);
5196 }
5197 #endif /* NETCONN */
5198 #endif /* CKLOGDIAL */
5199 
5200 #ifndef NODIAL
5201 /*
5202   Parse a DIAL-related string, stripping enclosing braces, if any.
5203 */
5204 static int
dialstr(p,msg)5205 dialstr(p,msg) char **p; char *msg; {
5206     int x;
5207     char *s;
5208 
5209     if ((x = cmtxt(msg, "", &s, xxstring)) < 0)
5210       return(x);
5211     s = brstrip(s);                     /* Strip braces around. */
5212     debug(F110,"dialstr",s,0);
5213     makestr(p,*s?s:NULL);
5214     return(success = 1);
5215 }
5216 
5217 VOID
initmdm(x)5218 initmdm(x) int x; {
5219     MDMINF * p;
5220     int m;
5221 
5222     mdmtyp = x;                         /* Set global modem type */
5223     debug(F101,"initmdm mdmtyp","",mdmtyp);
5224     debug(F101,"initmdm usermdm","",usermdm);
5225     if (x < 1) return;
5226 
5227     m = usermdm ? usermdm : mdmtyp;
5228 
5229     p = modemp[m];                      /* Point to modem info struct, and */
5230     /* debug(F101,"initmdm p","",p); */
5231     if (p) {
5232         dialec = p->capas & CKD_EC;     /* set DIAL ERROR-CORRECTION, */
5233         dialdc = p->capas & CKD_DC;     /* DIAL DATA-COMPRESSION, and */
5234         mdmspd = p->capas & CKD_SB ? 0 : 1; /* DIAL SPEED-MATCHING from it. */
5235         dialfc = FLO_AUTO;                  /* Modem's local flow control.. */
5236         dialmax   = p->max_speed;
5237         dialcapas = p->capas;
5238         dialesc   = p->esc_char;
5239     } else if (mdmtyp > 0) {
5240         printf("WARNING: modem info for \"%s\" not filled in yet\n",
5241                gmdmtyp()
5242                );
5243     }
5244 
5245 /* Reset or set the SET DIAL STRING items ... */
5246 
5247 #ifdef DEBUG
5248     if (deblog) {
5249         debug(F110,"initmdm dialini",dialini,0);
5250         debug(F110,"initmdm dialmstr ",dialmstr,0);
5251         debug(F110,"initmdm dialmprmt",dialmprmt,0);
5252         debug(F110,"initmdm dialcmd",dialcmd,0);
5253         debug(F110,"initmdm dialdcon",dialdcon,0);
5254         debug(F110,"initmdm dialdcoff",dialdcoff,0);
5255         debug(F110,"initmdm dialecon",dialecon,0);
5256         debug(F110,"initmdm dialecoff",dialecoff,0);
5257         debug(F110,"initmdm dialhcmd",dialhcmd,0);
5258         debug(F110,"initmdm dialhwfc",dialhwfc,0);
5259         debug(F110,"initmdm dialswfc",dialswfc,0);
5260         debug(F110,"initmdm dialnofc",dialnofc,0);
5261         debug(F110,"initmdm dialtone",dialtone,0);
5262         debug(F110,"initmdm dialpulse",dialpulse,0);
5263         debug(F110,"initmdm dialname",dialname,0);
5264         debug(F110,"initmdm dialaaon",dialaaon,0);
5265         debug(F110,"initmdm dialaaoff",dialaaoff,0);
5266         debug(F110,"initmdm dialx3",dialx3,0);
5267         debug(F110,"initmdm dialspon",dialspon,0);
5268         debug(F110,"initmdm dialspoff",dialspoff,0);
5269         debug(F110,"initmdm dialvol1",dialvol1,0);
5270         debug(F110,"initmdm dialvol2",dialvol2,0);
5271         debug(F110,"initmdm dialvol3",dialvol3,0);
5272         debug(F110,"initmdm dialini2",dialini2,0);
5273     }
5274 #endif /* DEBUG */
5275 
5276     if (usermdm && p) { /* USER-DEFINED: copy info from specified template */
5277 
5278         makestr(&dialini  ,p->wake_str);
5279         makestr(&dialmstr ,p->dmode_str);
5280         makestr(&dialmprmt,p->dmode_prompt);
5281         makestr(&dialcmd  ,p->dial_str);
5282         makestr(&dialdcon ,p->dc_on_str);
5283         makestr(&dialdcoff,p->dc_off_str);
5284         makestr(&dialecon ,p->ec_on_str);
5285         makestr(&dialecoff,p->ec_off_str);
5286         makestr(&dialhcmd ,p->hup_str);
5287         makestr(&dialhwfc ,p->hwfc_str);
5288         makestr(&dialswfc ,p->swfc_str);
5289         makestr(&dialnofc ,p->nofc_str);
5290         makestr(&dialtone ,p->tone);
5291         makestr(&dialpulse,p->pulse);
5292         makestr(&dialname ,"This space available (use SET MODEM NAME)");
5293         makestr(&dialaaon ,p->aa_on_str);
5294         makestr(&dialaaoff,p->aa_off_str);
5295         makestr(&dialx3   ,p->ignoredt);
5296         makestr(&dialspon ,p->sp_on_str);
5297         makestr(&dialspoff,p->sp_off_str);
5298         makestr(&dialvol1 ,p->vol1_str);
5299         makestr(&dialvol2 ,p->vol2_str);
5300         makestr(&dialvol3 ,p->vol3_str);
5301         makestr(&dialini2 ,p->ini2);
5302 
5303     } else {                    /* Not user-defined, so wipe out overrides */
5304 
5305         if (dialini)   makestr(&dialini,NULL);   /* Init-string */
5306         if (dialmstr)  makestr(&dialmstr,NULL);  /* Dial-mode-str */
5307         if (dialmprmt) makestr(&dialmprmt,NULL); /* Dial-mode-pro */
5308         if (dialcmd)   makestr(&dialcmd,NULL);   /* Dial-command  */
5309         if (dialdcon)  makestr(&dialdcon,NULL);  /* DC ON command */
5310         if (dialdcoff) makestr(&dialdcoff,NULL); /* DC OFF command */
5311         if (dialecon)  makestr(&dialecon,NULL);  /* EC ON command */
5312         if (dialecoff) makestr(&dialecoff,NULL); /* EC OFF command */
5313         if (dialhcmd)  makestr(&dialhcmd,NULL);  /* Hangup command */
5314         if (dialhwfc)  makestr(&dialhwfc,NULL);  /* Flow control... */
5315         if (dialswfc)  makestr(&dialswfc,NULL);  /*  */
5316         if (dialnofc)  makestr(&dialnofc,NULL);  /*  */
5317         if (dialtone)  makestr(&dialtone,NULL);  /* Dialing method */
5318         if (dialpulse) makestr(&dialpulse,NULL); /*  */
5319         if (dialname)  makestr(&dialname,NULL);  /* Modem name */
5320         if (dialaaon)  makestr(&dialaaon,NULL);  /* Autoanswer On */
5321         if (dialaaoff) makestr(&dialaaoff,NULL); /* Autoanswer Off */
5322         if (dialx3)    makestr(&dialx3,NULL);    /* Ignore dialtone */
5323         if (dialspon)  makestr(&dialspon,NULL);  /* Speaker On */
5324         if (dialspoff) makestr(&dialspoff,NULL); /* Speaker Off */
5325         if (dialvol1)  makestr(&dialvol1,NULL);  /* Low volume */
5326         if (dialvol2)  makestr(&dialvol2,NULL);  /* Medium volume */
5327         if (dialvol3)  makestr(&dialvol3,NULL);  /* High volume */
5328         if (dialini2)  makestr(&dialini2,NULL);  /* Init string 2 */
5329     }
5330     if (autoflow)                       /* Maybe change flow control */
5331       setflow();
5332 
5333 #ifndef MINIDIAL
5334 #ifdef OLDTBCODE
5335     tbmodel = 0;           /* If it's a Telebit, we don't know the model yet */
5336 #endif /* OLDTBCODE */
5337 #endif /* MINIDIAL */
5338 }
5339 
5340 #ifdef COMMENT
5341 /* Not implemented yet */
5342 int
setanswer()5343 setanswer() {
5344     int x, y;
5345     extern int ans_cid, ans_ring;
5346     if ((x = cmkey(answertab,nanswertab,"","",xxstring)) < 0)
5347       return(x);
5348     switch (x) {
5349       case XYA_CID:
5350         return(seton(&ans_cid));
5351       case XYA_RNG:
5352         y = cmnum("How many rings before answering","1",10,&x,xxstring);
5353         y = setnum(&ans_rings,x,y,254);
5354         return(y);
5355     }
5356 }
5357 #endif /* COMMENT */
5358 
5359 int
setmodem()5360 setmodem() {                            /* SET MODEM */
5361 
5362     int x, y, z;
5363     long zz;
5364     struct FDB k1, k2;
5365     extern int mdmset;
5366 
5367     cmfdbi(&k1,_CMKEY,
5368            "Modem parameter","","",nsetmdm, 0, xxstring, setmdm, &k2);
5369     cmfdbi(&k2,_CMKEY,"","","",nmdm,0,xxstring,mdmtab,NULL);
5370     x = cmfdb(&k1);
5371     if (x < 0) {                        /* Error */
5372         if (x == -2 || x == -9)
5373           printf("?No keywords match: \"%s\"\n",atmbuf);
5374         return(x);
5375     }
5376     y = cmresult.nresult;               /* Keyword value */
5377     if (cmresult.fdbaddr == &k2) {      /* Modem-type keyword table */
5378         if ((x = cmcfm()) < 0)
5379           return(x);
5380         usermdm = 0;
5381         initmdm(cmresult.nresult);      /* Set the modem type. */
5382         return(success = 1);            /* Done */
5383     }
5384     switch (cmresult.nresult) {         /* SET MODEM keyword table. */
5385 #ifdef MDMHUP
5386       case XYDMHU:                      /* DIAL MODEM-HANGUP */
5387         if ((y = cmkey(mdmhang,4,"how to hang up modem",
5388                        "modem-command", xxstring)) < 0)
5389           return(y);
5390         if ((x = cmcfm()) < 0)
5391           return(x);
5392         dialmhu = y;
5393 #ifdef COMMENT
5394 /* Nope, I fixed it (2001 11 08) */
5395 #ifdef CK_SCOV5
5396         if (dialmhu == 0 && !quiet) {
5397             printf(
5398 "\n WARNING: RS-232 signal sampling and manipulation do not work\n"
5399                     );
5400             printf(
5401 " in the standard SCO OSR5 serial i/o drivers.  SET MODEM HANGUP-METHOD\n"
5402                    );
5403             printf(
5404 " MODEM-COMMAND is recommended for OSR5.\n\n"
5405                     );
5406         }
5407 #endif /* CK_SCOV5 */
5408 #endif /* COMMENT */
5409         return(success = 1);
5410 #endif /* MDMHUP */
5411 
5412       case XYDCAP:
5413         zz = 0L;
5414         y = 0;
5415         while (y != -3) {
5416             if ((y = cmkey(mdmcap,nmdmcap,
5417                            "capability of modem", "", xxstring)) < 0) {
5418                 if (y == -3)
5419                   break;
5420                 else
5421                   return(y);
5422             }
5423             zz |= y;
5424         }
5425         if ((x = cmcfm()) < 0)
5426           return(x);
5427         dialcapas = zz;
5428         debug(F101,"setmodem autoflow","",autoflow);
5429         debug(F101,"setmodem flow 1","",flow);
5430         if (autoflow)                   /* Maybe change flow control */
5431           setflow();
5432         debug(F101,"setmodem flow 2","",flow);
5433         mdmspd = zz & CKD_SB ? 0 : 1;   /* Set MODEM SPEED-MATCHING from it. */
5434         return(success = 1);
5435 
5436       case XYDMAX:
5437 #ifdef TN_COMPORT
5438         if (network && istncomport())
5439           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
5440         else
5441 #endif /* TN_COMPORT */
5442           x = cmkey(spdtab,nspd,line,"",xxstring);
5443         if (x < 0) {
5444             if (x == -3) printf("?value required\n");
5445             return(x);
5446         }
5447         if ((y = cmcfm()) < 0) return(y);
5448         dialmax = (long) x * 10L;
5449         if (dialmax == 70) dialmax = 75;
5450         return(success = 1);
5451 
5452       case XYDSTR:                      /* These moved from SET DIAL */
5453       case XYDDC:
5454       case XYDEC:
5455       case XYDESC:
5456       case XYDFC:
5457       case XYDKSP:
5458       case XYDSPD:
5459       case XYDDIA:
5460         return(setdial(x));
5461 
5462       case XYDTYP:
5463         if ((y = cmkey(mdmtab,nmdm,"modem type","none", xxstring)) < 0)
5464           return(y);
5465         if (y == dialudt) {             /* User-defined modem type */
5466             if ((x = cmkey(mdmtab,nmdm,"based on existing modem type",
5467                            "unknown", xxstring)) < 0)
5468               return(x);
5469         }
5470         if ((z = cmcfm()) < 0)
5471           return(z);
5472         usermdm = 0;
5473         usermdm = (y == dialudt) ? x : 0;
5474         initmdm(y);
5475         mdmset = (mdmtyp > 0);
5476         return(success = 1);
5477 
5478       case XYDNAM:
5479         return(dialstr(&dialname,"Descriptive name for modem"));
5480 
5481       case XYDMCD:                      /* SET MODEM CARRIER-WATCH */
5482         return(setdcd());
5483 
5484       case XYDSPK:                      /* SET MODEM SPEAKER */
5485         return(seton(&mdmspk));
5486 
5487       case XYDVOL:                      /* SET MODEM VOLUME */
5488         if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0)
5489           return(x);
5490         if ((y = cmcfm()) < 0)
5491           return(y);
5492         mdmvol = x;
5493         return(success = 1);
5494 
5495       default:
5496         printf("Unexpected SET MODEM parameter\n");
5497         return(-9);
5498     }
5499 }
5500 
5501 static int                              /* Set DIAL command options */
setdial(y)5502 setdial(y) int y; {
5503     int x = 0, z = 0;
5504     char *s = NULL;
5505 
5506     if (y < 0)
5507       if ((y = cmkey(dialtab,ndial,"","",xxstring)) < 0)
5508         return(y);
5509     switch (y) {
5510       case XYDHUP:                      /* DIAL HANGUP */
5511         return(seton(&dialhng));
5512       case XYDINI:                      /* DIAL INIT-STRING */
5513         return(dialstr(&dialini,"Modem initialization string"));
5514       case XYDNPR:                      /* DIAL PREFIX */
5515         return(dialstr(&dialnpr,"Telephone number prefix"));
5516       case XYDDIA:                      /* DIAL DIAL-COMMAND */
5517         x = cmtxt("Dialing command for modem,\n\
5518  include \"%s\" to stand for phone number,\n\
5519  for example, \"set dial dial-command ATDT%s\\13\"",
5520                   "",
5521                   &s,
5522                   xxstring);
5523         if (x < 0 && x != -3)           /* Handle parse errors */
5524           return(x);
5525         s = brstrip(s);                 /* Strip braces or quotes */
5526         y = x = strlen(s);              /* Get length of text */
5527         if (y > 0) {                    /* If there is any text (left), */
5528             for (x = 0; x < y; x++) {   /* make sure they included "%s" */
5529                 if (s[x] != '%') continue;
5530                 if (s[x+1] == 's') break;
5531             }
5532             if (x == y) {
5533                 printf(
5534 "?Dial-command must contain \"%cs\" for phone number.\n",'%');
5535                 return(-9);
5536             }
5537         }
5538         if (dialcmd) {                  /* Free any previous string. */
5539             free(dialcmd);
5540             dialcmd = (char *) 0;
5541         }
5542         if (y > 0) {
5543             dialcmd = malloc(y + 1);    /* Allocate space for it */
5544             if (dialcmd)
5545               strcpy(dialcmd,s);        /* and make a safe copy. */
5546         }
5547         return(success = 1);
5548 #ifndef NOXFER
5549       case XYDKSP:                      /* DIAL KERMIT-SPOOF */
5550         return(seton(&dialksp));
5551 #endif /* NOXFER */
5552       case XYDTMO:                      /* DIAL TIMEOUT */
5553         y = cmnum("Seconds to wait for call completion","0",10,&x,xxstring);
5554         if (y < 0) return(y);
5555         y = cmnum("Kermit/modem timeout differential","10",10,&z,xxstring);
5556         if (y < 0) return(y);
5557         if ((y = cmcfm()) < 0)
5558           return(y);
5559         dialtmo = x;
5560         mdmwaitd = z;
5561       case XYDESC:                      /* DIAL ESCAPE-CHARACTER */
5562         y = cmnum("ASCII value of character to escape back to modem",
5563                   "43",10,&x,xxstring);
5564         y = setnum(&dialesc,x,y,128);
5565         if (y > -1 && dialesc < 0)      /* No escape character */
5566           dialmhu = 0;                  /* So no hangup by modem command */
5567         return(y);
5568       case XYDDPY:                      /* DIAL DISPLAY */
5569         return(seton(&dialdpy));
5570       case XYDSPD:                      /* DIAL SPEED-MATCHING */
5571                                         /* used to be speed-changing */
5572         if ((y = seton(&mdmspd)) < 0) return(y);
5573 #ifdef COMMENT
5574         mdmspd = 1 - mdmspd;            /* so here we reverse the meaning */
5575 #endif /* COMMENT */
5576         return(success = 1);
5577       case XYDMNP:                      /* DIAL MNP-ENABLE */
5578       case XYDEC:                       /* DIAL ERROR-CORRECTION */
5579         x = seton(&dialec);
5580         if (x > 0)
5581           if (!dialec) dialdc = 0;      /* OFF also turns off compression */
5582         return(x);
5583 
5584       case XYDDC:                       /* DIAL COMPRESSION */
5585         x = seton(&dialdc);
5586         if (x > 0)
5587           if (dialdc) dialec = 1;       /* ON also turns on error correction */
5588         return(x);
5589 
5590 #ifdef MDMHUP
5591       case XYDMHU:                      /* DIAL MODEM-HANGUP */
5592         return(seton(&dialmhu));
5593 #endif /* MDMHUP */
5594 
5595 #ifndef NOSPL
5596       case XYDDIR:                      /* DIAL DIRECTORY (zero or more) */
5597         return(parsdir(0));             /* 0 means DIAL */
5598 #endif /* NOSPL */
5599 
5600       case XYDSTR:                      /* DIAL STRING */
5601         if ((y = cmkey(mdmcmd,nmdmcmd,"","",xxstring)) < 0) return(y);
5602         switch (y) {
5603           case XYDS_AN:                 /* Autoanswer ON/OFF */
5604           case XYDS_DC:                 /* Data compression ON/OFF */
5605           case XYDS_EC:                 /* Error correction ON/OFF */
5606             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
5607               return(x);
5608             sprintf(tmpbuf,"Modem's command to %sable %s", /* SAFE */
5609                     x ? "en" : "dis",
5610                     (y == XYDS_DC) ? "compression" :
5611                     ((y == XYDS_EC) ? "error-correction" :
5612                     "autoanswer")
5613                     );
5614             if (x) {
5615                 if (y == XYDS_DC)
5616                   return(dialstr(&dialdcon,tmpbuf));
5617                 else if (y == XYDS_EC)
5618                   return(dialstr(&dialecon,tmpbuf));
5619                 else
5620                   return(dialstr(&dialaaon,tmpbuf));
5621             } else {
5622                 if (y == XYDS_DC)
5623                   return(dialstr(&dialdcoff,tmpbuf));
5624                 else if (y == XYDS_EC)
5625                   return(dialstr(&dialecoff,tmpbuf));
5626                 else
5627                   return(dialstr(&dialaaoff,tmpbuf));
5628             }
5629           case XYDS_HU:                 /*    hangup command */
5630             return(dialstr(&dialhcmd,"Modem's hangup command"));
5631           case XYDS_HW:                 /*    hwfc */
5632             return(dialstr(&dialhwfc,
5633                            "Modem's command to enable hardware flow control"));
5634           case XYDS_IN:                 /*    init */
5635             return(dialstr(&dialini,"Modem's initialization string"));
5636           case XYDS_NF:                 /*    no flow control */
5637             return(dialstr(&dialnofc,
5638                            "Modem's command to disable local flow control"));
5639           case XYDS_PX:                 /*    prefix */
5640             return(dialstr(&dialnpr,"Telephone number prefix for dialing"));
5641           case XYDS_SW:                 /*    swfc */
5642             return(dialstr(&dialswfc,
5643                    "Modem's command to enable local software flow control"));
5644           case XYDS_DT:                 /*    tone dialing */
5645             return(dialstr(&dialtone,
5646                    "Command to configure modem for tone dialing"));
5647           case XYDS_DP:                 /*    pulse dialing */
5648             return(dialstr(&dialpulse,
5649                            "Command to configure modem for pulse dialing"));
5650           case XYDS_MS:                 /*    dial mode string */
5651             return(dialstr(&dialmstr,
5652                          "Command to enter dial mode"));
5653           case XYDS_MP:                 /*    dial mode prompt */
5654             return(dialstr(&dialmprmt,
5655                            "Modem response upon entering dial mode"));
5656           case XYDS_SP:                 /* SPEAKER OFF */
5657             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0) return(x);
5658             if (x)
5659               return(dialstr(&dialspon,"Command to turn modem speaker on"));
5660             else
5661               return(dialstr(&dialspoff,"Command to turn modem speaker off"));
5662 
5663           case XYDS_VO:                 /* VOLUME LOW */
5664             if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0) return(x);
5665             switch (x) {
5666               case 0:
5667               case 1:
5668                 return(dialstr(&dialvol1,
5669                                "Command for low modem speaker volume"));
5670               case 2:
5671                 return(dialstr(&dialvol2,
5672                            "Command for medium modem speaker volume"));
5673 
5674               case 3:
5675                 return(dialstr(&dialvol3,
5676                                "Command for high modem speaker volume"));
5677               default:
5678                 return(-2);
5679             }
5680 
5681           case XYDS_ID:                 /* IGNORE-DIALTONE */
5682             return(dialstr(&dialx3,
5683                            "Command to tell modem to ignore dialtone"));
5684 
5685           case XYDS_I2:                 /* PREDIAL-INIT */
5686             return(dialstr(&dialini2,
5687                            "Command to send to modem just prior to dialing"));
5688 
5689           default:
5690             printf("?Unexpected SET DIAL STRING parameter\n");
5691         }
5692 
5693       case XYDFC:                       /* DIAL FLOW-CONTROL */
5694         if ((y = cmkey(dial_fc,4,"","auto",xxstring)) < 0) return(y);
5695         if ((x = cmcfm()) < 0) return(x);
5696         dialfc = y;
5697         return(success = 1);
5698 
5699       case XYDMTH: {                    /* DIAL METHOD */
5700         extern int dialmauto;
5701         if ((y = cmkey(dial_m,ndial_m,"","default",xxstring)) < 0)
5702           return(y);
5703         if ((x = cmcfm()) < 0)
5704           return(x);
5705         if (y == XYDM_A) {              /* AUTO */
5706             dialmauto = 1;              /* local country code, if known. */
5707             dialmth = XYDM_D;
5708         } else {
5709           dialmauto = 0;                /* use the method specified */
5710           dialmth = y;
5711         }
5712         return(success = 1);
5713       }
5714       case XYDRTM:
5715         y = cmnum("Number of times to try dialing a number",
5716                   "1",10,&x,xxstring);
5717 	z = setnum(&dialrtr,x,y,-1);
5718 	if (z > -1 && dialrtr < 0) {
5719 	    printf("?Sorry, negative dial retries not valid: %d\n",dialrtr);
5720 	    return(-9);
5721 	}
5722         return(z);
5723 
5724       case XYDINT:
5725         y = cmnum("Seconds to wait between redial attempts",
5726                   "30",10,&x,xxstring);
5727         z = setnum(&dialint,x,y,-1);
5728 	if (z > -1 && dialint < 0) {
5729 	    printf("?Sorry, negative dial interval not valid: %d\n",dialint);
5730 	    return(-9);
5731 	}
5732         return(z);
5733 
5734       case XYDLAC:                      /* DIAL AREA-CODE */
5735         if ((x = dialstr(&diallac,"Area code you are calling from")) < 0)
5736           return(x);
5737         if (diallac) {
5738             if (!rdigits(diallac)) {
5739                 printf("?Sorry, area code must be numeric\n");
5740                 if (*diallac == '(')
5741                   printf("(please omit the parentheses)\n");
5742                 if (*diallac == '/')
5743                   printf("(no slashes, please)\n");
5744                 if (diallac) free(diallac);
5745                 diallac = NULL;
5746                 return(-9);
5747             }
5748         }
5749         return(x);
5750 
5751       case XYDCNF:                      /* CONFIRMATION */
5752         return(success = seton(&dialcnf));
5753 
5754       case XYDCVT:                      /* CONVERT-DIRECTORY */
5755         if ((y = cmkey(dcnvtab,3,"","ask",xxstring)) < 0)
5756           return(y);
5757         if ((x = cmcfm()) < 0)
5758           return(x);
5759         dialcvt = y;
5760         return(success = 1);
5761 
5762       case XYDLCC:                      /* DIAL COUNTRY-CODE */
5763         x = dialstr(&diallcc,"Country code you are calling from");
5764         if (x < 1) return(x);
5765         if (diallcc) {
5766             if (!rdigits(diallcc)) {
5767                 printf("?Sorry, country code must be numeric\n");
5768                 if (*diallcc == '+')
5769                   printf("(please omit the plus sign)\n");
5770                 if (diallcc) free(diallcc);
5771                 diallcc = NULL;
5772                 return(-9);
5773             }
5774             if (!strcmp(diallcc,"1")) { /* Set defaults for USA and Canada */
5775                 if (!dialldp)           /* Long-distance prefix */
5776                   makestr(&dialldp,"1");
5777                 if (!dialixp)           /* International dialing prefix */
5778                   makestr(&dialixp,"011");
5779                 if (ntollfree == 0) {   /* Toll-free area codes */
5780                     if ((dialtfc[0] = malloc(4))) {
5781                         strcpy(dialtfc[0],"800"); /* 1970-something */
5782                         ntollfree++;
5783                         if ((dialtfc[1] = malloc(4))) {
5784                             strcpy(dialtfc[1],"888"); /* 1996 */
5785                             ntollfree++;
5786                             if ((dialtfc[2] = malloc(4))) {
5787                                 strcpy(dialtfc[2],"877"); /* 5 April 1998 */
5788                                 ntollfree++;
5789                                 if ((dialtfc[3] = malloc(4))) {
5790                                     strcpy(dialtfc[3],"866"); /* 2000? */
5791                                     ntollfree++;
5792                                 }
5793                             }
5794                         }
5795                     }
5796                 }
5797                 if (!dialtfp)           /* Toll-free dialing prefix */
5798                   makestr(&dialtfp,"1");
5799 #ifdef COMMENT
5800 /* The time for this is past */
5801             } else if (!strcmp(diallcc,"358") &&
5802                        ((int) strcmp(zzndate(),"19961011") > 0)
5803                        ) {              /* Finland */
5804                 if (!dialldp)           /* Long-distance prefix */
5805                   makestr(&dialldp,"9");
5806                 if (!dialixp)           /* International dialing prefix */
5807                   makestr(&dialixp,"990");
5808 #endif /* COMMENT */
5809             } else {                    /* Everywhere else ... */
5810                 if (!dialldp) {
5811                     if ((dialldp = malloc(4)))
5812                       strcpy(dialldp,"0");
5813                 }
5814                 if (!dialixp) {
5815                     if ((dialixp = malloc(4)))
5816                       strcpy(dialixp,"00");
5817                 }
5818             }
5819             if (!strcmp(diallcc,"33"))  /* France */
5820               dialfld = 1;              /* Long-distance dialing is forced */
5821         }
5822         return(success = 1);
5823 
5824       case XYDIXP:                      /* DIAL INTL-PREFIX */
5825         return(dialstr(&dialixp,"International dialing prefix"));
5826 
5827       case XYDIXS:                      /* DIAL INTL-SUFFIX */
5828         return(dialstr(&dialixs,"International dialing suffix"));
5829 
5830       case XYDLDP:                      /* DIAL LD-PREFIX */
5831         return(dialstr(&dialldp,"Long-distance dialing prefix"));
5832 
5833       case XYDLDS:                      /* DIAL LD-SUFFIX */
5834         return(dialstr(&diallds,"Long-distance dialing suffix"));
5835 
5836       case XYDLCP:                      /* DIAL LC-PREFIX */
5837         return(dialstr(&diallcp,"Local dialing prefix"));
5838 
5839       case XYDLCS:                      /* DIAL LC-SUFFIX */
5840         return(dialstr(&diallcs,"Local dialing suffix"));
5841 
5842 #ifdef COMMENT
5843       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
5844         return(dialstr(&dialpxx,"Exchange of PBX you are calling from"));
5845 #endif /* COMMENT */
5846 
5847       case XYDPXI: {                    /* DIAL PBX-INTERNAL-PREFIX */
5848 #ifdef COMMENT
5849           return(dialstr(&dialpxi,
5850                        "Internal-call prefix of PBX you are calling from"));
5851 #else
5852           int x;
5853           if ((x = cmtxt("Internal-call prefix of PBX you are calling from",
5854                          "",&s,NULL)) < 0) /* Don't evaluate */
5855             return(x);
5856 #ifndef NOSPL
5857           if (*s) {
5858               char c, * p = tmpbuf;
5859               if (*s == '\\') {
5860                   c = *(s+1);
5861                   if (isupper(c)) c = tolower(c);
5862                   if (c != 'f' &&
5863                       ckstrcmp(s,"\\v(d$px)",8,0) &&
5864                       ckstrcmp(s,"\\v(d$pxx)",9,0) &&
5865                       ckstrcmp(s,"\\v(d$p)",7,0)) {
5866                       x = TMPBUFSIZ;
5867                       zzstring(s,&p,&x);
5868                       s = tmpbuf;
5869                   }
5870               }
5871           }
5872 #endif /* NOSPL */
5873           makestr(&dialpxi,s);
5874           return(1);
5875       }
5876 #endif /* COMMENT */
5877 
5878       case XYDPXO:                      /* DIAL PBX-OUTSIDE-PREFIX */
5879         return(dialstr(&dialpxo,
5880                        "Outside-line prefix of PBX you are calling from"));
5881 
5882       case XYDSFX:                      /* DIAL INTL-SUFFIX */
5883         return(dialstr(&dialsfx," Telephone number suffix for dialing"));
5884 
5885       case XYDSRT:                      /* DIAL SORT */
5886         return(success = seton(&dialsrt));
5887 
5888       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
5889       case XYDTFC: {                    /* DIAL TOLL-FREE-AREA-CODE  */
5890           int n, i;                     /* (zero or more of them...) */
5891           char * p[MAXTOLLFREE];        /* Temporary pointers */
5892           char * m;
5893           for (n = 0; n < MAXTOLLFREE; n++) {
5894               if (n == 0) {
5895                   m = (y == XYDTFC) ?
5896                   "Toll-free area code(s) in the country you are calling from"
5897                     : "Exchange(s) of PBX you are calling from";
5898               } else {
5899                   m = (y == XYDTFC) ?
5900                     "Another toll-free area code"
5901                       : "Another PBX exchange";
5902               }
5903               if ((x = cmfld(m,"",&s,xxstring)) < 0)
5904                 break;
5905               if (s) {
5906                   int k;
5907                   k = (int) strlen(s);
5908                   if (k > 0) {
5909                       if ((p[n] = malloc(k + 1)))
5910                         strcpy(p[n], s); /* safe */
5911                   } else break;
5912               } else break;
5913           }
5914           if (x == -3) {                /* Command was successful */
5915               int m;
5916               m = (y == XYDTFC) ? ntollfree : ndialpxx;
5917               if ((x = cmcfm()) < 0)
5918                 return(x);
5919               x = 1;
5920               for (i = 0; i < m; i++) { /* Remove old list, if any */
5921                   if  (y == XYDTFC)
5922                     makestr(&(dialtfc[i]),NULL);
5923                   else
5924                     makestr(&(dialpxx[i]),NULL);
5925               }
5926               if  (y == XYDTFC)
5927                 ntollfree = n;          /* New count */
5928               else
5929                 ndialpxx = n;
5930               for (i = 0; i < n; i++) { /* New list */
5931                   if  (y == XYDTFC)
5932                     makestr(&(dialtfc[i]),p[i]);
5933                   else
5934                     makestr(&(dialpxx[i]),p[i]);
5935               }
5936               x = 1;
5937           }
5938           for (i = 0; i < n; i++)
5939             if (p[i]) free(p[i]);
5940           return(x);
5941       }
5942 
5943       case XYDTFP:                      /* TOLL-FREE-PREFIX */
5944         return(dialstr(&dialtfp,
5945                        " Long-distance prefix for toll-free dialing"));
5946 
5947       case XYDCON:                      /* CONNECT */
5948         z = -1;
5949         if ((y = cmkey(crrtab,ncrr,"","auto",xxstring)) < 0) return(y);
5950         if (y != CAR_OFF)               /* AUTO or ON? */
5951           if ((z = cmkey(qvtab,nqvt,"","verbose",xxstring)) < 0) return(z);
5952         if ((x = cmcfm()) < 0) return(x);
5953         if (z > -1)
5954           dialcq = z;
5955         dialcon = y;
5956         return(success = 1);
5957 
5958       case XYDRSTR:                     /* RESTRICT */
5959         if ((y = cmkey(drstrtab,4,"","none",xxstring)) < 0) return(y);
5960         if ((x = cmcfm()) < 0) return(x);
5961         dialrstr = y;
5962         return(success = 1);
5963 
5964       case XYDLLAC: {                   /* Local area-code list  */
5965           int n, i;                     /* (zero or more of them...) */
5966           char * p[MAXLOCALAC]; /* Temporary pointers */
5967           for (n = 0; n < MAXLOCALAC; n++) {
5968               if ((x = cmfld(
5969                     "Area code to which calls from your area are local",
5970                        "",&s,xxstring)) < 0)
5971                 break;
5972               if (s) {
5973                   int k;
5974                   k = (int) strlen(s);
5975                   if (k > 0) {
5976                       if ((p[n] = malloc(k + 1)))
5977                         strcpy(p[n], s); /* safe */
5978                   } else break;
5979               } else break;
5980           }
5981           if (x == -3) {                /* Command was successful */
5982               if ((x = cmcfm()) < 0)
5983                 return(x);
5984               for (i = 0; i < nlocalac; i++) /* Remove old list, if any */
5985                 if (diallcac[i]) {
5986                     free(diallcac[i]);
5987                     diallcac[i] = NULL;
5988                 }
5989               nlocalac = n;             /* New count */
5990               for (i = 0; i < nlocalac; i++) /* New list */
5991                 diallcac[i] = p[i];
5992               return(success = 1);
5993           } else {                      /* Parse error, undo everything */
5994               for (i = 0; i < n; i++)
5995                 if (p[i]) free(p[i]);
5996               return(x);
5997           }
5998       }
5999 
6000       case XYDFLD:
6001         return(success = seton(&dialfld));
6002 
6003       case XYDIDT:                      /* DIAL IGNORE-DIALTONE */
6004         return(seton(&dialidt));
6005 
6006       case XYDPAC:
6007         y = cmnum(
6008               "Milliseconds to pause between each character sent to dialer",
6009                   "",10,&x,xxstring);
6010         return(setnum(&dialpace,x,y,9999));
6011 
6012 #ifndef NOSPL
6013       case XYDMAC:
6014         if ((x = cmfld("Name of macro to execute just prior to dialing",
6015                        "",&s,xxstring)) < 0) {
6016             if (x == -3)
6017               s = NULL;
6018             else
6019               return(x);
6020         }
6021         if (s) {
6022             if (!*s) {
6023                 s = NULL;
6024             } else {
6025                 ckstrncpy(line,s,LINBUFSIZ);
6026                 s = line;
6027             }
6028         }
6029         if ((x = cmcfm()) < 0)
6030           return(x);
6031         makestr(&dialmac,s);
6032         return(success = 1);
6033 #endif /* NOSPL */
6034 
6035       case XYDPUCC:                     /* Pulse country codes */
6036       case XYDTOCC: {                   /* Tone country codes */
6037           int n, i;
6038           char * p[MAXTPCC];
6039           char * m;
6040           for (n = 0; n < MAXTPCC; n++) {
6041               if (n == 0) {
6042                   m = (y == XYDPUCC) ?
6043                   "Country code where Pulse dialing is required"
6044                     : "Country code where Tone dialing is available";
6045               } else
6046                 m = "Another country code";
6047               if ((x = cmfld(m,"",&s,xxstring)) < 0)
6048                 break;
6049               if (s) {
6050                   int k;
6051                   k = (int) strlen(s);
6052                   if (k > 0) {
6053                       if ((p[n] = malloc(k + 1)))
6054                         strcpy(p[n], s); /* safe */
6055                   } else break;
6056               } else break;
6057           }
6058           if (x == -3) {                /* Command was successful */
6059               int m;
6060               m = (y == XYDPUCC) ? ndialpucc : ndialtocc;
6061               if ((x = cmcfm()) < 0)
6062                 return(x);
6063               x = 1;
6064               for (i = 0; i < m; i++) { /* Remove old list, if any */
6065                   if (y == XYDPUCC)
6066                     makestr(&(dialpucc[i]),NULL);
6067                   else
6068                     makestr(&(dialtocc[i]),NULL);
6069               }
6070               if (y == XYDPUCC) {
6071                   ndialpucc = n;                /* New count */
6072               } else {
6073                   ndialtocc = n;
6074               }
6075               for (i = 0; i < n; i++) { /* New list */
6076                   if (y == XYDPUCC) {
6077                       makestr(&(dialpucc[i]),p[i]);
6078                   } else {
6079                       makestr(&(dialtocc[i]),p[i]);
6080                   }
6081               }
6082               x = 1;
6083           }
6084           for (i = 0; i < n; i++)
6085             if (p[i]) free(p[i]);
6086           return(x);
6087       }
6088       case XYDTEST:
6089         return(seton(&dialtest));
6090 
6091       default:
6092         printf("?Unexpected SET DIAL parameter\n");
6093         return(-9);
6094     }
6095 }
6096 
6097 #ifndef NOSHOW
6098 int                                     /* SHOW MODEM */
6099 shomodem() {
6100     MDMINF * p;
6101     int x, n, mdm;
6102     char c;
6103     long zz;
6104 
6105 #ifdef IKSD
6106     if (inserver) {
6107         printf("Sorry, command disabled\r\n");
6108         return(success = 0);
6109     }
6110 #endif /* IKSD */
6111 
6112     shmdmlin();
6113     printf("\n");
6114 
6115     mdm = (mdmtyp > 0) ? mdmtyp : mdmsav;
6116     p = (mdm > 0) ? modemp[mdm] : NULL;
6117 
6118     if (p) {
6119         printf(" %s\n\n", dialname ? dialname : p->name);
6120 
6121         printf(" Modem capabilities:    ");
6122         zz = dialcapas ? dialcapas : p->capas;
6123         if (!zz) {
6124             printf(" (none)");
6125         } else {
6126             if (zz & CKD_AT) printf(" AT");
6127             if (zz & CKD_V25) printf(" ITU");
6128             if (zz & CKD_SB) printf(" SB");
6129             if (zz & CKD_EC) printf(" EC");
6130             if (zz & CKD_DC) printf(" DC");
6131             if (zz & CKD_HW) printf(" HWFC");
6132             if (zz & CKD_SW) printf(" SWFC");
6133             if (zz & CKD_KS) printf(" KS");
6134             if (zz & CKD_TB) printf(" TB");
6135         }
6136         printf("\n Modem carrier-watch:    ");
6137         if (carrier == CAR_OFF) printf("off\n");
6138         else if (carrier == CAR_ON) printf("on\n");
6139         else if (carrier == CAR_AUT) printf("auto\n");
6140         else printf("unknown\n");
6141 
6142         printf(" Modem maximum-speed:    ");
6143         zz = (dialmax > 0L) ? dialmax : p->max_speed;
6144         if (zz > 0)
6145           printf("%ld bps\n", zz);
6146         else
6147           printf("(unknown)\n");
6148         printf(" Modem error-correction: %s\n", dialec ? "on" : "off");
6149         printf(" Modem compression:      %s\n", dialdc ? "on" : "off");
6150         printf(" Modem speed-matching:   %s",   mdmspd ? "on" : "off");
6151         printf(" (interface speed %s)\n", mdmspd ? "changes" : "is locked");
6152         printf(" Modem flow-control:     ");
6153         if (dialfc == FLO_NONE) printf("none\n");
6154         else if (dialfc == FLO_XONX) printf("xon/xoff\n");
6155         else if (dialfc == FLO_RTSC) printf("rts/cts\n");
6156         else if (dialfc == FLO_AUTO) printf("auto\n");
6157         printf(" Modem hangup-method:    %s\n",
6158                dialmhu ?
6159                "modem-command" :
6160                "rs232-signal"
6161                );
6162         printf(" Modem speaker:          %s\n", showoff(mdmspk));
6163         printf(" Modem volume:           %s\n",
6164                (mdmvol == 2) ? "medium" : ((mdmvol <= 1) ? "low" : "high"));
6165         printf(" Modem kermit-spoof:     %s\n", dialksp ? "on" : "off");
6166         c = (char) (x = (dialesc ? dialesc : p->esc_char));
6167         printf(" Modem escape-character: %d", x);
6168         if (isprint(c))
6169           printf(" (= \"%c\")",c);
6170         printf(
6171 "\n\nMODEM COMMANDs (* = set automatically by SET MODEM TYPE):\n\n");
6172         debug(F110,"show dialini",dialini,0);
6173         printf(" %c Init-string:          ", dialini ? ' ' : '*' );
6174         shods(dialini ? dialini : p->wake_str);
6175         printf(" %c Dial-mode-string:     ", dialmstr ? ' ' : '*' );
6176         shods(dialmstr ? dialmstr : p->dmode_str);
6177         n = local ? 19 : 20;
6178         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6179         printf(" %c Dial-mode-prompt:     ", dialmprmt ? ' ' : '*' );
6180         shods(dialmprmt ? dialmprmt : p->dmode_prompt);
6181         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6182         printf(" %c Dial-command:         ", dialcmd ? ' ' : '*' );
6183         shods(dialcmd ? dialcmd : p->dial_str);
6184         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6185         printf(" %c Compression on:       ", dialdcon ? ' ' : '*' );
6186         if (!dialdcon)
6187           debug(F110,"dialdcon","(null)",0);
6188         else
6189           debug(F110,"dialdcon",dialdcon,0);
6190         shods(dialdcon ? dialdcon : p->dc_on_str);
6191         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6192         printf(" %c Compression off:      ", dialdcoff ? ' ' : '*' );
6193         shods(dialdcoff ? dialdcoff : p->dc_off_str);
6194         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6195         printf(" %c Error-correction on:  ", dialecon ? ' ' : '*' );
6196         shods(dialecon ? dialecon : p->ec_on_str);
6197         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6198         printf(" %c Error-correction off: ", dialecoff ? ' ' : '*' );
6199         shods(dialecoff ? dialecoff : p->ec_off_str);
6200         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6201         printf(" %c Autoanswer on:        ", dialaaon ? ' ' : '*' );
6202         shods(dialaaon ? dialaaon : p->aa_on_str);
6203         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6204         printf(" %c Autoanswer off:       ", dialaaoff ? ' ' : '*' );
6205         shods(dialaaoff ? dialaaoff : p->aa_off_str);
6206         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6207 
6208         printf(" %c Speaker on:           ", dialspon ? ' ' : '*' );
6209         shods(dialspon ? dialspon : p->sp_on_str);
6210         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6211         printf(" %c Speaker off:          ", dialspoff ? ' ' : '*' );
6212         shods(dialspoff ? dialspoff : p->sp_off_str);
6213         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6214         printf(" %c Volume low:           ", dialvol1 ? ' ' : '*' );
6215         shods(dialvol1 ? dialvol1 : p->vol1_str);
6216         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6217         printf(" %c Volume medium:        ", dialvol2 ? ' ' : '*' );
6218         shods(dialvol2 ? dialvol2 : p->vol2_str);
6219         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6220         printf(" %c Volume high:          ", dialvol3 ? ' ' : '*' );
6221         shods(dialvol3 ? dialvol3 : p->vol3_str);
6222         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6223 
6224         printf(" %c Hangup-command:       ", dialhcmd ? ' ' : '*' );
6225         shods(dialhcmd ? dialhcmd : p->hup_str);
6226         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6227         printf(" %c Hardware-flow:        ", dialhwfc ? ' ' : '*' );
6228         shods(dialhwfc ? dialhwfc : p->hwfc_str);
6229         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6230         printf(" %c Software-flow:        ", dialswfc ? ' ' : '*' );
6231         shods(dialswfc ? dialswfc : p->swfc_str);
6232         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6233         printf(" %c No-flow-control:      ", dialnofc ? ' ' : '*' );
6234         shods(dialnofc ? dialnofc : p->nofc_str);
6235         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6236         printf(" %c Pulse:                ", dialpulse ? ' ' : '*');
6237         shods(dialpulse ? dialpulse : p->pulse);
6238         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6239         printf(" %c Tone:                 ", dialtone ? ' ' : '*');
6240         shods(dialtone ? dialtone : p->tone);
6241 
6242         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6243         printf(" %c Ignore-dialtone:      ", dialx3 ? ' ' : '*');
6244         shods(dialx3 ? dialx3 : p->ignoredt);
6245 
6246         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6247         printf(" %c Predial-init:         ", dialini2 ? ' ' : '*');
6248         shods(dialini2 ? dialini2 : p->ini2);
6249 
6250         if (++n > cmd_rows - 4) if (!askmore()) return(0); else n = 0;
6251         printf("\n For more info: SHOW DIAL and SHOW COMMUNICATIONS\n");
6252 
6253     } else if (mdm > 0) {
6254         printf("Modem info for \"%s\" not filled in yet\n", gmdmtyp());
6255     } else printf(
6256 " No modem selected, so DIAL and most SET MODEM commands have no effect.\n\
6257  Use SET MODEM TYPE to select a modem.\n");
6258     return(success = 1);
6259 }
6260 #endif /* NOSHOW */
6261 #endif /* NODIAL */
6262 
6263 #ifdef CK_TAPI
6264 int                                             /* TAPI action commands */
6265 dotapi() {
6266     int x,y;
6267     char *s;
6268 
6269     if (!TAPIAvail) {
6270         printf("\nTAPI is unavailable on this system.\n");
6271         return(-9);
6272     }
6273     if ((y = cmkey(tapitab,ntapitab,"MS TAPI command","",xxstring)) < 0)
6274       return(y);
6275     switch (y) {
6276       case XYTAPI_CFG: {                        /* TAPI CONFIGURE-LINE */
6277           extern struct keytab * tapilinetab;
6278           extern struct keytab * _tapilinetab;
6279           extern int ntapiline;
6280           extern int LineDeviceId;
6281           int lineID=LineDeviceId;
6282           if (TAPIAvail)
6283             cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
6284           if (tapilinetab && _tapilinetab && ntapiline > 0) {
6285               int i=0, j = 9999, k = -1;
6286 
6287               if ( LineDeviceId == -1 ) {
6288                   /* Find out what the lowest numbered TAPI device is */
6289                   /* and use it as the default.                       */
6290                   for (i = 0; i < ntapiline; i++ ) {
6291                       if (tapilinetab[i].kwval < j) {
6292                           k = i;
6293                       }
6294                   }
6295               } else {
6296                   /* Find the LineDeviceId in the table and use that entry */
6297                   for (i = 0; i < ntapiline; i++ ) {
6298                       if (tapilinetab[i].kwval == LineDeviceId) {
6299                           k = i;
6300                           break;
6301                       }
6302                   }
6303               }
6304               if (k >= 0)
6305                 s = _tapilinetab[k].kwd;
6306               else
6307                 s = "";
6308 
6309               if ((y = cmkey(_tapilinetab,ntapiline,
6310                               "TAPI device name",s,xxstring)) < 0)
6311                 return(y);
6312               lineID = y;
6313           }
6314           if ((x = cmcfm()) < 0) return(x);
6315 #ifdef IKSD
6316           if (inserver) {
6317               printf("Sorry, command disabled\r\n");
6318               return(success = 0);
6319           }
6320 #endif /* ISKD */
6321           cktapiConfigureLine(lineID);
6322           break;
6323       }
6324       case XYTAPI_DIAL:                 /* TAPI DIALING-PROPERTIES */
6325         if ((x = cmcfm()) < 0)
6326           return(x);
6327 #ifdef IKSD
6328         if (inserver) {
6329             printf("Sorry, command disabled\r\n");
6330             return(success = 0);
6331         }
6332 #endif /* ISKD */
6333         cktapiDialingProp();
6334         break;
6335     }
6336     return(success = 1);
6337 }
6338 
6339 static int                              /* SET TAPI command options */
6340 settapi() {
6341     int x, y;
6342     char *s;
6343 
6344     if (!TAPIAvail) {
6345         printf("\nTAPI is unavailable on this system.\n");
6346         return(-9);
6347     }
6348     if ((y = cmkey(settapitab,nsettapitab,"MS TAPI option","",xxstring)) < 0)
6349       return(y);
6350     switch (y) {
6351       case XYTAPI_USE:
6352         return (success = seton(&tapiusecfg));
6353       case XYTAPI_LGHT:
6354         return (success = seton(&tapilights));
6355       case XYTAPI_PRE:
6356         return (success = seton(&tapipreterm));
6357       case XYTAPI_PST:
6358         return (success = seton(&tapipostterm));
6359       case XYTAPI_INA:
6360         y = cmnum("seconds of inactivity before auto-disconnect",
6361                   "0",10,&x,xxstring);
6362         return(setnum(&tapiinactivity,x,y,65535));
6363       case XYTAPI_BNG:
6364         y = cmnum("seconds to wait for credit card tone",
6365                   "8",10,&x,xxstring);
6366         return(setnum(&tapibong,x,y,90));
6367       case XYTAPI_MAN:
6368         return (success = seton(&tapimanual));
6369       case XYTAPI_CON:                  /* TAPI CONVERSIONS */
6370         return (success = setonaut(&tapiconv));
6371       case XYTAPI_LIN:                  /* TAPI LINE */
6372         x = setlin(XYTAPI_LIN,1,0);
6373         if (x > -1) didsetlin++;
6374         return(x);
6375       case XYTAPI_PASS: {               /* TAPI PASSTHROUGH */
6376 #ifdef NODIAL
6377           printf("\n?Modem-dialing not supported\n");
6378           return(-9);
6379 #else /* NODIAL */
6380           /* Passthrough became Modem-dialing which is an antonym */
6381           success = seton(&tapipass);
6382           tapipass = !tapipass;
6383           return (success);
6384 #endif /* NODIAL */
6385       }
6386       case XYTAPI_LOC: {                /* TAPI LOCATION */
6387           extern char tapiloc[];
6388           extern int tapilocid;
6389           int i = 0, j = 9999, k = -1;
6390 
6391           cktapiBuildLocationTable(&tapiloctab, &ntapiloc);
6392           if (!tapiloctab || !ntapiloc) {
6393               printf("\nNo TAPI Locations are configured for this system\n");
6394               return(-9);
6395           }
6396           if (tapilocid == -1)
6397             tapilocid = cktapiGetCurrentLocationID();
6398 
6399           /* Find the current tapiloc entry */
6400           /* and use it as the default. */
6401           for (k = 0; k < ntapiloc; k++) {
6402               if (tapiloctab[k].kwval == tapilocid)
6403                 break;
6404           }
6405           if (k >= 0 && k < ntapiloc)
6406             s = tapiloctab[k].kwd;
6407           else
6408             s = "";
6409 
6410           if ((y = cmkey(tapiloctab,ntapiloc, "TAPI location",s,xxstring)) < 0)
6411             return(y);
6412 
6413           if ((x = cmcfm()) < 0)
6414             return(x);
6415 #ifdef IKSD
6416           if (inserver) {
6417               printf("Sorry, command disabled\r\n");
6418               return(success = 0);
6419           }
6420 #endif /* IKSD */
6421           cktapiFetchLocationInfoByID( y );
6422 #ifndef NODIAL
6423           CopyTapiLocationInfoToKermitDialCmd();
6424 #endif /* NODIAL */
6425         }
6426         break;
6427     }
6428     return(success=1);
6429 }
6430 #endif /* CK_TAPI */
6431 #endif /* NOLOCAL */
6432 
6433 #ifndef NOSPL
6434 /* Method for evaluating \%x and \&x[] variables */
6435 
6436 static struct keytab varevaltab[] = {
6437     { "recursive", 1, 0 },
6438     { "simple",    0, 0 }
6439 };
6440 static int nvarevaltab = (sizeof(varevaltab) / sizeof(struct keytab));
6441 
6442 int
6443 setvareval() {
6444     int x = 0, y = 0;
6445     extern int vareval;
6446 #ifdef DCMDBUF
6447     extern int * xvarev;
6448 #else
6449     extern int xvarev[];
6450 #endif /* DCMDBUF */
6451 
6452     if ((x = cmkey(varevaltab,
6453 		   nvarevaltab,
6454 		   "Method for evaluating \\%x and \\&x[] variables",
6455 		   "",
6456 		   xxstring)) < 0)
6457       return(x);
6458     if ((y = cmcfm()) < 0)
6459       return(y);
6460     xvarev[cmdlvl] = x;
6461     vareval = x;
6462     return(success = 1);
6463 }
6464 
6465 #ifdef CK_ANSIC                         /* SET ALARM */
6466 int
6467 setalarm(long xx)
6468 #else
6469 int
6470 setalarm(xx) long xx;
6471 #endif /* CK_ANSIC */
6472 /* setalarm */ {
6473 #ifdef COMMENT
6474     int yyyy, mm, dd, x;
6475     char *s;
6476     long zz;
6477     char buf[6];
6478 #endif /* COMMENT */
6479     long sec, jd;
6480     char xbuf[20], * p;
6481 
6482     debug(F101,"setalarm xx","",xx);
6483     ck_alarm = 0L;                      /* 0 = no alarm (in case of error) */
6484     if (xx < 0L) {
6485         printf("%ld - illegal value, must be 0 or positive\n", xx);
6486         return(-9);
6487     }
6488     if (xx == 0L) {                     /* CLEAR ALARM */
6489         alrm_date[0] = NUL;
6490         alrm_time[0] = NUL;
6491         return(1);
6492     }
6493 #ifdef COMMENT
6494     x = 8;                              /* Get current date */
6495     s = alrm_date;
6496     if (zzstring("\\v(ndate)",&s,&x) < 0) {
6497         printf("Internal date error, sorry.\n");
6498         alrm_date[0] = SP;
6499         return(-9);
6500     }
6501     x = 5;                              /* Get current time */
6502     s = alrm_time;
6503     if (zzstring("\\v(ntime)",&s,&x) < 0) {
6504         printf("Internal time error, sorry.\n");
6505         alrm_time[0] = SP;
6506         return(-9);
6507     }
6508     sprintf(buf,"%05ld",atol(alrm_time)); /* SAFE (20) */
6509     ckstrncpy(alrm_time,buf,8);
6510     debug(F110,"SET ALARM date (1)",alrm_date,0);
6511     debug(F110,"SET ALARM time (1)",alrm_time,0);
6512 
6513     if ((zz = atol(alrm_time) + xx) < 0L) {
6514         printf("Internal time conversion error, sorry.\n");
6515         return(-9);
6516     }
6517     if (zz >= 86400L) {                 /* Alarm crosses midnight */
6518         char d[10];                     /* Local date buffer */
6519         int lastday;                    /* Last day of this month */
6520 
6521         ckstrncpy(d,alrm_date,8);       /* We'll have to change the date */
6522 
6523         x = (zz / 86400L);              /* How many days after today */
6524 
6525         dd = atoi((char *)(d+6));       /* Parse yyyymmdd */
6526         d[6] = NUL;                     /* into yyyy, mm, dd ... */
6527         mm = atoi((char *)(d+4));
6528         d[4] = NUL;
6529         yyyy = atoi((char *)d);
6530 
6531         /* How many days in this month */
6532 
6533         lastday = mdays[mm];
6534         if (mm == 2 && yyyy % 4 == 0)   /* Works thru 2099 AD... */
6535           lastday++;
6536 
6537         if (dd + x > lastday) {         /* Dumb loop */
6538             int y;
6539 
6540             x -= (mdays[mm] - dd);      /* Deduct rest of this month's days */
6541 
6542             /* There's a more elegant way to do this... */
6543 
6544             while (1) {
6545                 mm++;                   /* Next month */
6546                 if (mm > 12) {          /* Wrap around */
6547                     mm = 1;             /* Jan, next year */
6548                     yyyy++;
6549                 }
6550                 y = mdays[mm];          /* Days in new month */
6551                 if (mm == 2 && yyyy % 4 == 0) /* Feb in leap year */
6552                   y++;                  /* Works until 2100 AD */
6553                 if (x - y < 1)
6554                   break;
6555                 x -= y;
6556             }
6557             dd = x;                     /* Day of alarm month */
6558         } else dd += x;
6559 
6560         sprintf(alrm_date,"%04d%02d%02d",yyyy,mm,dd); /* SAFE (24) */
6561         zz = zz % 86400L;
6562     }
6563     sprintf(alrm_time,"%ld",zz);        /* SAFE (24) */
6564     debug(F110,"SET ALARM date (2)",alrm_date,0);
6565     debug(F110,"SET ALARM time (2)",alrm_time,0);
6566     ck_alarm = xx;
6567 #else
6568     /* Jul 1998 */
6569     ckstrncpy(xbuf,ckcvtdate("",1),20); /* Get current date and time */
6570     p = xbuf;
6571     ckstrncpy(alrm_date,xbuf,10);
6572     alrm_date[8] = NUL;
6573     sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
6574     debug(F110,"SET ALARM date (1)",alrm_date,0);
6575     debug(F101,"SET ALARM time (1)","",sec);
6576     if ((sec += xx) < 0L) {
6577         printf("Internal time conversion error, sorry.\n");
6578         return(-9);
6579     }
6580     if (sec >= 86400L) {                /* Alarm crosses midnight */
6581         long days;
6582         days = sec / 86400L;
6583         jd = mjd(p) + days;             /* Get modified Julian date */
6584         ckstrncpy(alrm_date,mjd2date(jd),10);
6585         sec %= 86400L;
6586     }
6587     sprintf(alrm_time,"%05ld",sec);     /* SAFE (24) */
6588     debug(F110,"SET ALARM date (2)",alrm_date,0);
6589     debug(F110,"SET ALARM time (2)",alrm_time,0);
6590     ck_alarm = 1;                       /* Alarm is set */
6591 
6592 #endif /* COMMENT */
6593     return(success = 1);
6594 }
6595 #endif /* NOSPL */
6596 
6597 #ifndef NOSETKEY
6598 int
6599 dosetkey() {                            /* SET KEY */
6600     int x, y;
6601     int flag = 0;
6602     int kc;                             /* Key code */
6603     char *s;                            /* Key binding */
6604 #ifndef NOKVERBS
6605     char *p;                            /* Worker */
6606 #endif /* NOKVERBS */
6607 #ifdef OS2
6608     extern int os2gks;
6609     extern int mskkeys;
6610     extern int initvik;
6611 #endif /* OS2 */
6612 
6613     x_ifnum = 1;
6614     y = cmnum("numeric key code, or the word CLEAR,","",10,&kc,xxstring);
6615     x_ifnum = 0;
6616     if (y < 0) {
6617         debug(F111,"SET KEY",atmbuf,y);
6618         if (y == -2) {                  /* Not a valid number */
6619             if ((y = strlen(atmbuf)) < 0) /* Check for SET KEY CLEAR */
6620               return(-2);
6621             if (ckstrcmp(atmbuf,"clear",y,0))
6622               return(-2);
6623             if ((x = cmcfm()) < 0)
6624               return(x);
6625             for (y = 0; y < KMSIZE; y++) {
6626                 keymap[y] = (KEY) y;
6627                 macrotab[y] = NULL;
6628             }
6629 #ifdef OS2
6630             keymapinit();               /* Special OS/2 initializations */
6631             initvik = 1;                /* Update the VIK table */
6632 #endif /* OS2 */
6633             return(1);
6634         } else if (y == -3) {           /* SET KEY <Return> */
6635             printf(" Press key to be defined: "); /* Prompt for a keystroke */
6636 #ifdef UNIX
6637 #ifdef NOSETBUF
6638             fflush(stdout);
6639 #endif /* NOSETBUF */
6640 #endif /* UNIX */
6641             conbin((char)escape);       /* Put terminal in binary mode */
6642 #ifdef OS2
6643             os2gks = 0;                 /* Turn off Kverb preprocessing */
6644 #endif /* OS2 */
6645             kc = congks(0);             /* Get character or scan code */
6646 #ifdef OS2
6647             os2gks = 1;                 /* Turn on Kverb preprocessing */
6648 #endif /* OS2 */
6649             concb((char)escape);        /* Restore terminal to cbreak mode */
6650             if (kc < 0) {               /* Check for error */
6651                 printf("?Error reading key\n");
6652                 return(0);
6653             }
6654 #ifdef OS2
6655             shokeycode(kc,-1);          /* Show current definition */
6656 #else
6657             shokeycode(kc);             /* Show current definition */
6658 #endif /* OS2 */
6659             flag = 1;                   /* Remember it's a multiline command */
6660         } else                          /* Error */
6661           return(y);
6662     }
6663 
6664     /* Normal SET KEY <scancode> <value> command... */
6665 
6666 #ifdef OS2
6667     if (mskkeys)
6668       kc = msktock(kc);
6669 #endif /* OS2 */
6670 
6671     if (kc < 0 || kc >= KMSIZE) {
6672         printf("?key code must be between 0 and %d\n", KMSIZE - 1);
6673         return(-9);
6674     }
6675     if (kc == escape) {
6676         printf("Sorry, %d is the CONNECT-mode escape character\n",kc);
6677         return(-9);
6678     }
6679 #ifdef OS2
6680     wideresult = -1;
6681 #endif /* OS2 */
6682     if (flag) {
6683         cmsavp(psave,PROMPTL);
6684         cmsetp(" Enter new definition: ");
6685         cmini(ckxech);
6686         cmflgs = 0;
6687         prompt(NULL);
6688     }
6689   def_again:
6690     if (flag)
6691       cmres();
6692     if ((y = cmtxt("key definition,\n\
6693 or Ctrl-C to cancel this command,\n\
6694 or Enter to restore default definition",
6695                    "",&s,NULL)) < 0) {
6696         if (flag)                       /* Handle parse errors */
6697           goto def_again;
6698         else
6699           return(y);
6700     }
6701     s = brstrip(s);
6702 #ifndef NOKVERBS
6703     p = s;                              /* Save this place */
6704 #endif /* NOKVERBS */
6705 /*
6706   If the definition included any \Kverbs, quote the backslash so the \Kverb
6707   will still be in the definition when the key is pressed.  We don't do this
6708   in zzstring(), because \Kverbs are valid only in this context and nowhere
6709   else.
6710 
6711   We use this code active for all versions that support SET KEY, even if they
6712   don't support \Kverbs, because otherwise \K would behave differently for
6713   different versions.
6714 */
6715     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
6716         if ((x > 0) &&
6717             (s[x] == 'K' || s[x] == 'k')
6718             ) {                         /* Have K */
6719 
6720             if ((x == 1 && s[x-1] == CMDQ) ||
6721                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
6722                 line[y++] = CMDQ;       /* Make it \\K */
6723             }
6724             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
6725                 line[y-1] = CMDQ;       /* Have \{K */
6726                 line[y++] = '{';        /* Make it \\{K */
6727             }
6728         }
6729         line[y] = s[x];
6730     }
6731     line[y++] = NUL;                    /* Terminate */
6732     s = line + y + 1;                   /* Point to after it */
6733     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
6734     if ((x < (LINBUFSIZ / 2)) ||
6735         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
6736         printf("?Key definition too long\n");
6737         if (flag) cmsetp(psave);
6738         return(-9);
6739     }
6740     s = line + y + 1;                   /* Point to result. */
6741 
6742 #ifndef NOKVERBS
6743 /*
6744   Special case: see if the definition starts with a \Kverb.
6745   If it does, point to it with p, otherwise set p to NULL.
6746 */
6747     p = s;
6748     if (*p++ == CMDQ) {
6749         if (*p == '{') p++;
6750         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
6751     }
6752 #endif /* NOKVERBS */
6753 
6754     if (macrotab[kc]) {                 /* Possibly free old macro from key. */
6755         free((char *)macrotab[kc]);
6756         macrotab[kc] = NULL;
6757     }
6758     switch (strlen(s)) {                /* Action depends on length */
6759       case 0:                           /* Reset to default binding */
6760         keymap[kc] = (KEY) kc;
6761         break;
6762       case 1:                           /* Single character */
6763         keymap[kc] = (CHAR) *s;
6764         break;
6765       default:                          /* Character string */
6766 #ifndef NOKVERBS
6767         if (p) {
6768             y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
6769             debug(F101,"set key kverb lookup",0,y); /* exact match required */
6770             if (y > -1) {
6771                 keymap[kc] = F_KVERB | y;
6772                 break;
6773             }
6774         }
6775 #endif /* NOKVERBS */
6776         keymap[kc] = (KEY) kc;
6777         macrotab[kc] = (MACRO) malloc(strlen(s)+1);
6778         if (macrotab[kc])
6779           strcpy((char *) macrotab[kc], s); /* safe */
6780         break;
6781     }
6782     if (flag) cmsetp(psave);
6783 #ifdef OS2
6784     initvik = 1;                        /* Update VIK table */
6785 #endif /* OS2 */
6786     return(1);
6787 }
6788 #endif /* NOSETKEY */
6789 
6790 #ifdef STOPBITS
6791 struct keytab stoptbl[] = {
6792     { "1", 1, 0 },
6793     { "2", 2, 0 }
6794 };
6795 #endif /* STOPBITS */
6796 
6797 static struct keytab sertbl[] = {
6798     { "7E1", 0, 0 },
6799     { "7E2", 1, 0 },
6800     { "7M1", 2, 0 },
6801     { "7M2", 3, 0 },
6802     { "7O1", 4, 0 },
6803     { "7O2", 5, 0 },
6804     { "7S1", 6, 0 },
6805     { "7S2", 7, 0 },
6806 #ifdef HWPARITY
6807     { "8E1", 9, 0 },
6808     { "8E2", 10, 0 },
6809 #endif /* HWPARITY */
6810     { "8N1", 8, 0 },
6811 #ifdef HWPARITY
6812     { "8N2", 11, 0 },
6813     { "8O1", 12, 0 },
6814     { "8O2", 13, 0 },
6815 #endif /* HWPARITY */
6816     { "", 0, 0 }
6817 };
6818 static int nsertbl = (sizeof(sertbl) / sizeof(struct keytab)) - 1;
6819 
6820 static char * sernam[] = {              /* Keep this in sync with sertbl[] */
6821   "7E1", "7E2", "7M1", "7M2", "7O1", "7O2", "7S1", "7S2",
6822   "8N1", "8E1", "8E2", "8N2", "8O1", "8O2"
6823 };
6824 
6825 static struct keytab optstab[] = {      /* SET OPTIONS table */
6826 #ifndef NOFRILLS
6827     { "delete",    XXDEL,   0},            /* DELETE */
6828 #endif /* NOFRILLS */
6829     { "directory", XXDIR,   0},         /* DIRECTORY */
6830 #ifdef CKPURGE
6831     { "purge",     XXPURGE, 0},         /* PURGE */
6832 #endif /* CKPURGE */
6833     { "type",      XXTYP,   0},         /* TYPE */
6834     { "", 0, 0}
6835 };
6836 static int noptstab =  (sizeof(optstab) / sizeof(struct keytab)) - 1;
6837 
6838 #ifndef NOXFER
6839 /*
6840   PROTOCOL SELECTION.  Kermit is always available.  If CK_XYZ is defined at
6841   compile time, then the others become selections also.  In OS/2 and
6842   Windows, they are integrated and the various SET commands (e.g. "set file
6843   type") affect them as they would Kermit.  In other OS's (UNIX, VMS, etc),
6844   they are external protocols which are run via Kermit's REDIRECT mechanism.
6845   All we do is collect and verify the filenames and pass them along to the
6846   external protocol.
6847 */
6848 struct keytab protos[] = {
6849 #ifdef CK_XYZ
6850     "g",          PROTO_G,  CM_INV,
6851 #endif /* CK_XYZ */
6852     "kermit",     PROTO_K,  0,
6853 #ifdef CK_XYZ
6854     "other",      PROTO_O,  0,
6855     "x",          PROTO_X,  CM_INV|CM_ABR,
6856     "xmodem",     PROTO_X,  0,
6857     "xmodem-crc", PROTO_XC, 0,
6858     "y",          PROTO_Y,  CM_INV|CM_ABR,
6859     "ymodem",     PROTO_Y,  0,
6860     "ymodem-g",   PROTO_G,  0,
6861     "zmodem",     PROTO_Z,  0
6862 #endif /* CK_XYZ */
6863 };
6864 int nprotos =  (sizeof(protos) / sizeof(struct keytab));
6865 
6866 #ifndef XYZ_INTERNAL
6867 #ifndef NOPUSH
6868 #define EXP_HANDLER 1
6869 #define EXP_STDERR  2
6870 #define EXP_TIMO    3
6871 
6872 static struct keytab extprotab[] = {
6873     { "handler",          EXP_HANDLER, 0 },
6874     { "redirect-stderr",  EXP_STDERR, 0 },
6875     { "timeout",          EXP_TIMO, 0 }
6876 };
6877 static int nxtprotab =  (sizeof(extprotab) / sizeof(struct keytab));
6878 #endif	/* NOPUSH */
6879 #endif	/* XYZ_INTERNAL */
6880 
6881 #define XPCMDLEN 71
6882 
6883 _PROTOTYP(static int protofield, (char *, char *, char *));
6884 _PROTOTYP(static int setproto, (void));
6885 
6886 static int
6887 protofield(current, help, px) char * current, * help, * px; {
6888 
6889     char *s, tmpbuf[XPCMDLEN+1];
6890     int x;
6891 
6892     if (current)                        /* Put braces around default */
6893       ckmakmsg(tmpbuf,TMPBUFSIZ,"{",current,"}",NULL);
6894     else
6895       tmpbuf[0] = NUL;
6896 
6897     if ((x = cmfld(help, (char *)tmpbuf, &s, xxstring)) < 0)
6898       return(x);
6899     if ((int)strlen(s) > XPCMDLEN) {
6900         printf("?Sorry - maximum length is %d\n", XPCMDLEN);
6901         return(-9);
6902     } else if (*s) {
6903         strcpy(px,s);                   /* safe */
6904     } else {
6905         px = NULL;
6906     }
6907     return(x);
6908 }
6909 
6910 static int
6911 setproto() {                            /* Select a file transfer protocol */
6912     /* char * s = NULL; */
6913     int x = 0, y;
6914     char s1[XPCMDLEN+1], s2[XPCMDLEN+1], s3[XPCMDLEN+1];
6915     char s4[XPCMDLEN+1], s5[XPCMDLEN+1], s6[XPCMDLEN+1], s7[XPCMDLEN+1];
6916     char * p1 = s1, * p2 = s2, *p3 = s3;
6917     char * p4 = s4, * p5 = s5, *p6 = s6, *p7 = s7;
6918 
6919 #ifdef XYZ_INTERNAL
6920     extern int p_avail;
6921 #else
6922 #ifndef CK_REDIR
6923     x = 1;
6924 #endif /* CK_REDIR */
6925 #endif /* XYZ_INTERNAL */
6926     s1[0] = NUL;
6927     s2[0] = NUL;
6928     s3[0] = NUL;
6929     s4[0] = NUL;
6930     s5[0] = NUL;
6931     s6[0] = NUL;
6932 
6933     if ((y = cmkey(protos,nprotos,"","kermit",xxstring)) < 0)
6934       return(y);
6935 
6936     if (x && y != PROTO_K) {
6937         printf(
6938            "?Sorry, REDIRECT capability required for external protocols.\n");
6939         return(-9);
6940     }
6941     if ((x = protofield(ptab[y].h_b_init,
6942      "Optional command to send to host prior to uploading in binary mode",
6943                p1)) < 0) {
6944         if (x == -3) {
6945             protocol = y;               /* Set protocol but don't change */
6946             return(1);                  /* anything else */
6947         } else
6948           return(x);
6949     }
6950     if ((x = protofield(ptab[y].h_t_init,
6951      "Optional command to send to host prior to uploading in text mode",
6952                p2)) < 0) {
6953         if (x == -3)
6954           goto protoexit;
6955         else
6956           return(x);
6957     }
6958 
6959     if (y == PROTO_K) {
6960         if ((x = protofield(ptab[y].h_x_init,
6961                     "Optional command to send to host to start Kermit server",
6962                             p3)) < 0) {
6963             if (x == -3)
6964               goto protoexit;
6965             else
6966               return(x);
6967         }
6968     }
6969 
6970 
6971 #ifndef XYZ_INTERNAL                    /* If XYZMODEM are external... */
6972 
6973     if (y != PROTO_K) {
6974         if ((x = protofield(ptab[y].p_b_scmd,
6975                  "External command to SEND in BINARY mode with this protocol",
6976                             p4)) < 0) {
6977             if (x == -3)
6978               goto protoexit;
6979             else
6980               return(x);
6981         }
6982         if ((x = protofield(ptab[y].p_t_scmd,
6983                  "External command to SEND in TEXT mode with this protocol",
6984                             p5)) < 0) {
6985             if (x == -3)
6986               goto protoexit;
6987             else
6988               return(x);
6989         }
6990         if ((x = protofield(ptab[y].p_b_rcmd,
6991                "External command to RECEIVE in BINARY mode with this protocol",
6992                             p6)) < 0) {
6993             if (x == -3)
6994               goto protoexit;
6995             else
6996               return(x);
6997         }
6998         if ((x = protofield(ptab[y].p_t_rcmd,
6999                  "External command to RECEIVE in TEXT mode with this protocol",
7000                             p7)) < 0) {
7001             if (x == -3)
7002               goto protoexit;
7003             else
7004               return(x);
7005         }
7006     }
7007 #endif /* XYZ_INTERNAL */
7008 
7009     if ((x = cmcfm()) < 0)              /* Confirm the command */
7010       return(x);
7011 
7012 protoexit:                              /* Common exit from this routine */
7013 
7014 #ifdef XYZ_INTERNAL
7015     if (!p_avail) {
7016         bleep(BP_WARN);
7017         printf("\n?X,Y, and Zmodem are unavailable\n");
7018         return(success = 0);
7019     }
7020 #endif /* XYZ_INTERNAL */
7021 
7022     p1 = brstrip(p1);
7023     p2 = brstrip(p2);
7024     p3 = brstrip(p3);
7025     p4 = brstrip(p4);
7026     p5 = brstrip(p5);
7027     p6 = brstrip(p6);
7028     p7 = brstrip(p7);
7029     initproto(y,p1,p2,p3,p4,p5,p6,p7);
7030     return(success = 1);
7031 }
7032 
7033 #ifndef NOPUSH
7034 #ifndef XYZ_INTERNAL
7035 
7036 #define DEF_EXP_TIMO 12	 /* Default timeout for external protocol (seconds) */
7037 
7038 int exp_handler = 0;			/* These are exported */
7039 int exp_timo = DEF_EXP_TIMO;
7040 int exp_stderr = SET_AUTO;
7041 
7042 VOID
7043 shoextern() {				/* Invoked by SHOW PROTOCOL */
7044     printf("\n External-protocol handler:         %s\n",
7045 	   exp_handler ? (exp_handler == 1 ? "pty" : "system") : "automatic");
7046 #ifdef COMMENT
7047     printf(" External-protocol redirect-stderr: %s\n", showooa(exp_stderr));
7048 #endif	/* COMMENT */
7049     printf(" External-protocol timeout:         %d (sec)\n", exp_timo);
7050 }
7051 
7052 static struct keytab setexternhandler[] = {
7053     { "automatic", 0, 0 },
7054     { "pty",       1, 0 },
7055     { "system",    2, 0 }
7056 };
7057 
7058 int
7059 setextern() {				/* SET EXTERNAL-PROTOCOL */
7060     int x, y;
7061     if ((x = cmkey(extprotab,nxtprotab,"","",xxstring)) < 0)
7062       return(x);
7063     switch (x) {
7064       case EXP_HANDLER:
7065 	if ((x = cmkey(setexternhandler,3,"","automatic",xxstring)) < 0)
7066 	  return(x);
7067 	if ((y = cmcfm()) < 0)
7068 	  return(y);
7069 	exp_handler = x;
7070 	break;
7071 
7072 #ifdef COMMENT
7073       case EXP_STDERR:
7074 	if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
7075 	  return(x);
7076 	if ((y = cmcfm()) < 0)
7077 	  return(y);
7078 	exp_stderr = x;
7079 	break;
7080 #endif	/* COMMENT */
7081 
7082       case EXP_TIMO:
7083 	y = cmnum("Inactivity timeout, seconds,",ckitoa(DEF_EXP_TIMO),
7084 		  10,&x,xxstring);
7085         return(setnum(&exp_timo,x,y,-1));
7086     }
7087     return(success = 1);
7088 }
7089 #endif	/* XYZ_INTERNAL */
7090 #endif	/* NOPUSH */
7091 
7092 int
7093 setdest() {
7094     int x, y;
7095     if ((y = cmkey(desttab,ndests,"","disk",xxstring)) < 0) return(y);
7096     if ((x = cmcfm()) < 0) return(x);
7097     dest = y;
7098     return(1);
7099 }
7100 #endif /* NOXFER */
7101 
7102 #ifdef DECNET
7103 struct keytab dnettab[] = {
7104 #ifndef OS2ONLY
7105     "cterm", NP_CTERM, 0,
7106 #endif /* OS2ONLY */
7107     "lat",   NP_LAT,   0
7108 };
7109 int ndnet =  (sizeof(dnettab) / sizeof(struct keytab));
7110 #endif /* DECNET */
7111 
7112 /*  S E T P R I N T E R  --  SET PRINTER command  */
7113 
7114 #ifdef PRINTSWI
7115 static struct keytab prntab[] = {       /* SET PRINTER switches */
7116     "/bidirectional",    PRN_BID, 0,
7117 #ifdef OS2
7118     "/character-set",    PRN_CS,  CM_ARG,
7119 #endif /* OS2 */
7120     "/command",          PRN_PIP, CM_ARG,
7121     "/dos-device",       PRN_DOS, CM_ARG,
7122     "/end-of-job-string",PRN_TRM, CM_ARG,
7123     "/file",             PRN_FIL, CM_ARG,
7124 #ifdef BPRINT
7125     "/flow-control",     PRN_FLO, CM_ARG,
7126 #endif /* BPRINT */
7127     "/job-header-file",  PRN_SEP, CM_ARG,
7128 #ifdef OS2
7129     "/length",           PRN_LEN, CM_ARG,
7130 #endif /* OS2 */
7131     "/none",             PRN_NON, 0,
7132 #ifdef OS2
7133     "/nopostscript",     PRN_RAW, 0,
7134     "/nops",             PRN_RAW, CM_INV,
7135 #endif /* OS2 */
7136     "/output-only",      PRN_OUT, 0,
7137 #ifdef BPRINT
7138     "/parity",           PRN_PAR, CM_ARG,
7139 #endif /* BPRINT */
7140     "/pipe",             PRN_PIP, CM_ARG|CM_INV,
7141 #ifdef OS2
7142     "/postscript",       PRN_PS,  0,
7143     "/ps",               PRN_PS,  CM_INV,
7144 #endif /* OS2 */
7145     "/separator",        PRN_SEP, CM_ARG|CM_INV,
7146 #ifdef BPRINT
7147     "/speed",            PRN_SPD, CM_ARG,
7148 #endif /* BPRINT */
7149     "/timeout",          PRN_TMO, CM_ARG,
7150     "/terminator",       PRN_TRM, CM_ARG|CM_INV,
7151 #ifdef OS2
7152 #ifdef NT
7153     "/w",                PRN_WIN, CM_ARG|CM_ABR|CM_INV,
7154     "/wi",               PRN_WIN, CM_ARG|CM_ABR|CM_INV,
7155 #endif /* NT */
7156     "/width",            PRN_WID, CM_ARG,
7157 #endif /* OS2 */
7158 #ifdef NT
7159     "/windows-queue",    PRN_WIN, CM_ARG,
7160 #endif /* NT */
7161     "",                 0,      0
7162 };
7163 int nprnswi =  (sizeof(prntab) / sizeof(struct keytab)) - 1;
7164 #endif /* PRINTSWI */
7165 
7166 static int
7167 setprinter(xx) int xx; {
7168     int x, y;
7169     char * s;
7170     char * defname = NULL;
7171 #ifdef OS2
7172     extern int prncs;
7173 #endif /* OS2 */
7174 
7175 #ifdef BPRINT
7176     char portbuf[64];
7177     long portspeed = 0L;
7178     int portparity = 0;
7179     int portflow = 0;
7180 #endif /* BPRINT */
7181 
7182 #ifdef PRINTSWI
7183     int c, i, n, wild, confirmed = 0;   /* Workers */
7184     int getval = 0;                     /* Whether to get switch value */
7185     struct stringint pv[PRN_MAX+1];    /* Temporary array for switch values */
7186     struct FDB sw, of, cm;              /* FDBs for each parse function */
7187     int haveque = 0;
7188     int typeset = 0;
7189 #endif /* PRINTSWI */
7190 
7191 #ifdef NT
7192     struct keytab * printtab = NULL, * _printtab = NULL;
7193     int nprint = 0, printdef=0;
7194 #endif /* NT */
7195 
7196 #ifdef OS2
7197     defname = "PRN";                    /* default */
7198 #else
7199 #ifdef VMS
7200     defname = "LPT:";
7201 #else
7202 #ifdef UNIX
7203     defname = "|lpr";
7204 #endif /* UNIX */
7205 #endif /* VMS */
7206 #endif /* OS2 */
7207 
7208 #ifdef PRINTSWI
7209 #ifdef NT
7210     haveque = Win32EnumPrt(&printtab,&_printtab,&nprint,&printdef);
7211     haveque = haveque && nprint;
7212 #endif /* NT */
7213 
7214     for (i = 0; i <= PRN_MAX; i++) {    /* Initialize switch values */
7215         pv[i].sval = NULL;              /* to null pointers */
7216         pv[i].ival = -1;                /* and -1 int values */
7217         pv[i].wval = (CK_OFF_T)-1;	/* and -1 wide values */
7218     }
7219     if (xx == XYBDCP) {                 /* SET BPRINTER == /BIDIRECTIONAL */
7220         pv[PRN_BID].ival = 1;
7221         pv[PRN_OUT].ival = 0;
7222     }
7223 
7224     /* Initialize defaults based upon current printer settings */
7225     if (printername) {
7226         defname = printername;
7227         switch (printertype) {
7228           case PRT_WIN: pv[PRN_WIN].ival = 1; break;
7229           case PRT_DOS: pv[PRN_DOS].ival = 1; break;
7230           case PRT_PIP: pv[PRN_PIP].ival = 1; break;
7231           case PRT_FIL: pv[PRN_FIL].ival = 1; break;
7232           case PRT_NON: pv[PRN_NON].ival = 1; break;
7233         }
7234     }
7235 #ifdef BPRINT
7236     /* only set the BIDI flag if we are bidi */
7237     if (printbidi)
7238         pv[PRN_BID].ival = 1;
7239 
7240     /* serial port parameters may be set for non-bidi devices */
7241     pv[PRN_SPD].ival = pportspeed / 10L;
7242     pv[PRN_PAR].ival = pportparity;
7243     pv[PRN_FLO].ival = pportflow;
7244 #endif /* BPRINT */
7245     if (printtimo)
7246         pv[PRN_TMO].ival = printtimo;
7247     if (printterm) {
7248         pv[PRN_TRM].ival = 1;
7249         makestr(&pv[PRN_TRM].sval,printterm);
7250     }
7251     if (printsep) {
7252         pv[PRN_SEP].ival = 1;
7253         makestr(&pv[PRN_SEP].sval,printsep);
7254     }
7255     if (txt2ps) {
7256         pv[PRN_PS].ival = 1;
7257         pv[PRN_WID].ival = ps_width;
7258         pv[PRN_LEN].ival = ps_length;
7259     } else {
7260         pv[PRN_RAW].ival = 1;
7261     }
7262 
7263     /* Set up chained parse functions... */
7264 
7265     cmfdbi(&sw,                         /* First FDB - command switches */
7266            _CMKEY,                      /* fcode */
7267            "Switch",                    /* hlpmsg */
7268            "",                          /* default */
7269            "",                          /* addtl string data */
7270            nprnswi,                     /* addtl numeric data 1: tbl size */
7271            4,                           /* addtl numeric data 2: 4 = cmswi */
7272            xxstring,                    /* Processing function */
7273            prntab,                      /* Keyword table */
7274            &cm                          /* Pointer to next FDB */
7275            );
7276     cmfdbi(&cm,                         /* Second fdb for confirmation */
7277            _CMCFM,                      /* fcode */
7278            "",                          /* hlpmsg */
7279            "",                          /* default */
7280            "",                          /* addtl string data */
7281            0,                           /* addtl numeric data 1 */
7282            0,                           /* addtl numeric data 2 */
7283            NULL,
7284            NULL,
7285            &of
7286            );
7287     cmfdbi(&of,                         /* Third FDB for printer name */
7288            _CMOFI,                      /* fcode */
7289            "Printer or file name",      /* hlpmsg */
7290            defname,                     /* default */
7291            "",                          /* addtl string data */
7292            0,                           /* addtl numeric data 1: tbl size */
7293            0,                           /* addtl numeric data 2: 4 = cmswi */
7294            xxstring,                    /* Processing function */
7295            NULL,                        /* Nothing */
7296            NULL
7297            );
7298 
7299     while (1) {                         /* Parse 0 or more switches */
7300         x = cmfdb(&sw);                 /* Parse switch or other thing */
7301         debug(F101,"setprinter cmfdb","",x);
7302         if (x < 0)                      /* Error */
7303           goto xsetprn;                 /* or reparse needed */
7304         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
7305           break;
7306         if (cmresult.fdbaddr != &sw)    /* Advanced usage :-) */
7307           break;
7308         c = cmgbrk();                   /* Get break character */
7309         getval = (c == ':' || c == '='); /* to see how they ended the switch */
7310         n = cmresult.nresult;           /* Numeric result = switch value */
7311         debug(F101,"setprinter switch","",n);
7312 
7313         switch (n) {                    /* Process the switch */
7314           case PRN_PS:                  /* Text to Postscript */
7315             pv[PRN_PS].ival = 1;
7316             pv[PRN_BID].ival = 0;
7317             pv[PRN_OUT].ival = 1;
7318             pv[PRN_RAW].ival = 0;
7319             break;
7320 
7321           case PRN_RAW:                 /* Non-Postscript */
7322             pv[PRN_PS].ival = 0;
7323             pv[PRN_RAW].ival = 1;
7324             break;
7325 
7326           case PRN_BID:                 /* Bidirectional */
7327             pv[PRN_BID].ival = 1;
7328             pv[PRN_OUT].ival = 0;
7329             pv[PRN_PS].ival = 0;
7330             pv[PRN_RAW].ival = 1;
7331             break;
7332 
7333           case PRN_OUT:                 /* Output-only */
7334             pv[PRN_OUT].ival = 1;
7335             pv[PRN_BID].ival = 0;
7336             pv[PRN_PS].ival = 0;
7337             pv[PRN_RAW].ival = 1;
7338             break;
7339 
7340           case PRN_NON:                 /* NONE */
7341             typeset++;
7342             pv[n].ival = 1;
7343             pv[PRN_SPD].ival = 0;
7344             pv[PRN_PAR].ival = 0;
7345             pv[PRN_FLO].ival = FLO_KEEP;
7346             break;
7347 
7348 #ifdef UNIX
7349           case PRN_WIN:
7350 #endif /* UNIX */
7351           case PRN_DOS:                 /* DOS printer name */
7352           case PRN_FIL:                 /* Or filename */
7353           case PRN_PIP:
7354             typeset++;
7355             if (pv[n].sval) free(pv[n].sval);
7356             pv[n].sval = NULL;
7357             pv[PRN_NON].ival = 0;       /* Zero any previous selections */
7358             pv[PRN_WIN].ival = 0;
7359             pv[PRN_DOS].ival = 0;
7360             pv[PRN_FIL].ival = 0;
7361             pv[PRN_PIP].ival = 0;
7362             pv[n].ival = 1;             /* Flag this one */
7363             if (!getval) break;         /* No value wanted */
7364 
7365             if (n == PRN_FIL) {         /* File, check accessibility */
7366                 int wild = 0;
7367                 if ((x = cmiofi("Filename","kermit.prn",&s,&wild,xxstring))< 0)
7368                   if (x == -9) {
7369                       if (zchko(s) < 0) {
7370                           printf("Can't create \"%s\"\n",s);
7371                           return(x);
7372                       }
7373                   } else goto xsetprn;
7374                 if (iswild(s)) {
7375                     printf("?A single file please\n");
7376                     return(-9);
7377                 }
7378                 pv[PRN_SPD].ival = 0;
7379                 pv[PRN_PAR].ival = 0;
7380                 pv[PRN_FLO].ival = FLO_KEEP;
7381             } else if ((x = cmfld(n == PRN_DOS ? /* Value wanted - parse it */
7382                            "DOS printer device name" : /* Help message */
7383                            (n == PRN_PIP ?
7384                            "Program name" :
7385                            "Filename"),
7386                            n == PRN_DOS ?
7387                            "PRN" :      /* Default */
7388                            "",
7389                            &s,
7390                            xxstring
7391                            )) < 0)
7392               goto xsetprn;
7393             s = brstrip(s);             /* Strip enclosing braces */
7394             while (*s == SP)            /* Strip leading blanks */
7395               s++;
7396             if (n == PRN_PIP) {         /* If /PIPE: */
7397                 if (*s == '|') {        /* strip any extraneous pipe sign */
7398                     s++;
7399                     while (*s == SP)
7400                       s++;
7401                 }
7402                 pv[PRN_SPD].ival = 0;
7403                 pv[PRN_PAR].ival = 0;
7404                 pv[PRN_FLO].ival = FLO_KEEP;
7405             }
7406             if ((y = strlen(s)) > 0)    /* Anything left? */
7407               if (pv[n].sval = (char *) malloc(y+1)) /* Yes, keep it */
7408                 strcpy(pv[n].sval,s);   /* safe */
7409             break;
7410 #ifdef NT
7411           case PRN_WIN:                 /* Windows queue name */
7412             typeset++;
7413             if (pv[n].sval) free(pv[n].sval);
7414             pv[n].sval = NULL;
7415             pv[PRN_NON].ival = 0;
7416             pv[PRN_DOS].ival = 0;
7417             pv[PRN_FIL].ival = 0;
7418             pv[n].ival = 1;
7419             pv[PRN_SPD].ival = 0;
7420             pv[PRN_PAR].ival = 0;
7421             pv[PRN_FLO].ival = FLO_KEEP;
7422 
7423             if (!getval || !haveque)
7424               break;
7425             if ((x = cmkey(_printtab,nprint,"Print queue name",
7426                            _printtab[printdef].kwd,xxstring)) < 0) {
7427                 if (x != -2)
7428                   goto xsetprn;
7429 
7430                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7431                 s = atmbuf;
7432                 if ((y = strlen(s)) > 0)
7433                   if (pv[n].sval = (char *)malloc(y+1))
7434                     strcpy(pv[n].sval,s); /* safe */
7435             } else {
7436                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7437                 for (i = 0; i < nprint; i++) {
7438                     if (x == printtab[i].kwval) {
7439                         s = printtab[i].kwd;
7440                         break;
7441                     }
7442                 }
7443                 if ((y = strlen(s)) > 0)
7444                   if (pv[n].sval = (char *)malloc(y+1))
7445                     strcpy(pv[n].sval,s); /* safe */
7446             }
7447             break;
7448 #endif /* NT */
7449 
7450           case PRN_SEP:                 /* /JOB-HEADER (separator) */
7451             if (pv[n].sval) free(pv[n].sval);
7452             pv[n].sval = NULL;
7453             pv[n].ival = 1;
7454             if (!getval) break;
7455             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0)
7456               goto xsetprn;
7457             if (y) {
7458                 printf("?Wildcards not allowed\n");
7459                 x = -9;
7460                 goto xsetprn;
7461             }
7462             if ((y = strlen(s)) > 0)
7463               if (pv[n].sval = (char *) malloc(y+1))
7464                 strcpy(pv[n].sval,s);   /* safe */
7465             break;
7466 
7467           case PRN_TMO:                 /* /TIMEOUT:number */
7468             pv[n].ival = 0;
7469             if (!getval) break;
7470             if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
7471               goto xsetprn;
7472             if (y > 999) {
7473                 printf("?Sorry - 999 is the maximum\n");
7474                 x = -9;
7475                 goto xsetprn;
7476             } else
7477               pv[n].ival = y;
7478             break;
7479 
7480           case PRN_TRM:                 /* /END-OF-JOB:string */
7481             if (pv[n].sval) free(pv[n].sval);
7482             pv[n].sval = NULL;
7483             pv[n].ival = 1;
7484             if (!getval) break;
7485             if ((x = cmfld("String (enclose in braces if it contains spaces)",
7486                            "",&s,xxstring)) < 0)
7487               goto xsetprn;
7488             s = brstrip(s);
7489             if ((y = strlen(s)) > 0)
7490               if (pv[n].sval = (char *) malloc(y+1))
7491                 strcpy(pv[n].sval,s);   /* safe */
7492             break;
7493 
7494 #ifdef BPRINT
7495           case PRN_FLO:
7496             if (!getval) break;
7497             if ((x = cmkey(flotab,nflo,
7498                               "Serial printer-port flow control",
7499                               "rts/cts",xxstring)) < 0)
7500               goto xsetprn;
7501             pv[n].ival = x;
7502             break;
7503 
7504 #ifndef NOLOCAL
7505           case PRN_SPD:
7506             if (!getval) break;
7507 
7508             /* TN_COMPORT here too? */
7509 
7510             if ((x = cmkey(spdtab,      /* Speed (no default) */
7511                            nspd,
7512                            "Serial printer-port interface speed",
7513                            "9600",
7514                            xxstring)
7515                  ) < 0)
7516               goto xsetprn;
7517             pv[n].ival = x;
7518             break;
7519 #endif /* NOLOCAL */
7520 
7521           case PRN_PAR:
7522             pv[n].ival = 0;
7523             if (!getval) break;
7524             if ((x = cmkey(partbl,npar,"Serial printer-port parity",
7525                            "none",xxstring)) < 0)
7526               goto xsetprn;
7527             pv[n].ival = x;
7528             break;
7529 #endif /* BPRINT */
7530 
7531 #ifdef OS2
7532           case PRN_LEN:
7533             if (!getval) break;
7534             if ((x = cmnum("PS page length", "66",10,&y,xxstring)) < 0)
7535               goto xsetprn;
7536             pv[n].ival = y;
7537             break;
7538 
7539           case PRN_WID:
7540             if (!getval) break;
7541             if ((x = cmnum("PS page width", "80",10,&y,xxstring)) < 0)
7542               goto xsetprn;
7543             pv[n].ival = y;
7544             break;
7545 
7546           case PRN_CS:
7547               pv[n].ival = 0;
7548               if (!getval) break;
7549               if ((y = cmkey(
7550 #ifdef CKOUNI
7551                        txrtab,ntxrtab,
7552 #else /* CKOUNI */
7553                        ttcstab,ntermc,
7554 #endif /* CKOUNI */
7555                        "auto-print/printscreen character-set",
7556                        "cp437",xxstring)) < 0)
7557                   goto xsetprn;
7558               pv[n].ival = y;
7559               break;
7560 #endif /* OS2 */
7561 
7562           default:
7563             printf("?Unexpected switch value - %d\n",cmresult.nresult);
7564             x = -9;
7565             goto xsetprn;
7566         }
7567     }
7568     line[0] = NUL;                      /* Initialize printer name value */
7569     switch (cmresult.fcode) {           /* How did we get here? */
7570       case _CMOFI:                      /* They typed a filename */
7571         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
7572         wild = cmresult.nresult;        /* Wild flag */
7573         if (!typeset) {                 /* A printer name without a type */
7574             pv[PRN_NON].ival = 0;       /* is supposed to be treated as  */
7575             pv[PRN_WIN].ival = 0;       /* a DOS or Pipe printer.  We    */
7576             pv[PRN_FIL].ival = 0;       /* clear all the flags and let   */
7577             pv[PRN_PIP].ival = 0;       /* the code below dope out the   */
7578             pv[PRN_DOS].ival = 0;       /* type.                         */
7579         }
7580 #ifdef NT
7581         else if (pv[PRN_WIN].ival && lookup(_printtab,line,nprint,&y)) {
7582             /* invalid Window Queue name */
7583             printf("?invalid Windows Printer Queue name: \"%s\"\r\n",line);
7584             x = -9;
7585             goto xsetprn;
7586         }
7587 #endif /* NT */
7588         if ((x = cmcfm()) < 0)          /* Confirm the command */
7589           goto xsetprn;
7590         break;
7591       case _CMCFM:                      /* They entered the command */
7592         if (pv[PRN_DOS].ival > 0)
7593           ckstrncpy(line,pv[PRN_DOS].sval ? pv[PRN_DOS].sval : "",LINBUFSIZ);
7594         else if (pv[PRN_WIN].ival > 0)
7595           ckstrncpy(line,pv[PRN_WIN].sval ? pv[PRN_WIN].sval : "",LINBUFSIZ);
7596         else if (pv[PRN_FIL].ival > 0)
7597           ckstrncpy(line,pv[PRN_FIL].sval ? pv[PRN_FIL].sval : "",LINBUFSIZ);
7598         else if (pv[PRN_PIP].ival > 0)
7599           ckstrncpy(line,pv[PRN_PIP].sval ? pv[PRN_PIP].sval : "",LINBUFSIZ);
7600         break;
7601       default:                          /* By mistake */
7602         printf("?Unexpected function code: %d\n",cmresult.fcode);
7603         x = -9;
7604         goto xsetprn;
7605     }
7606 
7607 #else  /* No PRINTSWI */
7608 
7609     if ((x = cmofi("Printer or file name",defname,&s,xxstring)) < 0)
7610       return(x);
7611     if (x > 1) {
7612         printf("?Directory names not allowed\n");
7613         return(-9);
7614     }
7615     while (*s == SP || *s == HT) s++;   /* Trim leading whitespace */
7616     ckstrncpy(line,s,LINBUFSIZ);        /* Make a temporary safe copy */
7617     if ((x = cmcfm()) < 0) return(x);   /* Confirm the command */
7618 #endif /* PRINTSWI */
7619 
7620 #ifdef IKSD
7621     if (inserver && (isguest
7622 #ifndef NOSERVER
7623                      || !ENABLED(en_pri)
7624 #endif /* NOSERVER */
7625                      )) {
7626         printf("Sorry, printing disabled\r\n");
7627         return(success = 0);
7628     }
7629 #endif /* ISKD */
7630 
7631 #ifdef PRINTSWI
7632 #ifdef BPRINT
7633     if (printbidi) {                    /* If bidi printing active */
7634 #ifndef UNIX
7635         bprtstop();                     /* Stop it before proceeding */
7636 #endif /* UNIX */
7637         printbidi = 0;
7638     }
7639     if (pv[PRN_SPD].ival > 0) {
7640         portspeed = (long) pv[PRN_SPD].ival * 10L;
7641         if (portspeed == 70L) portspeed = 75L;
7642     }
7643     if (pv[PRN_PAR].ival > 0)
7644         portparity = pv[PRN_PAR].ival;
7645     if (pv[PRN_FLO].ival > 0)
7646         portflow = pv[PRN_FLO].ival;
7647 #endif /* BPRINT */
7648 #endif /* PRINTSWI */
7649 
7650     s = line;                           /* Printer name, if given */
7651 
7652 #ifdef OS2ORUNIX
7653 #ifdef PRINTSWI
7654     if (pv[PRN_PIP].ival > 0) {         /* /PIPE was given? */
7655         printpipe = 1;
7656         noprinter = 0;
7657         if (*s ==  '|') {               /* It might still have a pipe sign */
7658             s++;                        /* if name give later */
7659             while (*s == SP)            /* so remove it and spaces */
7660               s++;
7661         }
7662     } else
7663 #endif /* PRINTSWI */
7664       if (*s == '|') {                  /* Or pipe implied by name? */
7665           s++;                          /* Point past pipe sign */
7666           while (*s == SP)              /* Gobble whitespace */
7667             s++;
7668           if (*s) {
7669               printpipe = 1;
7670               noprinter = 0;
7671           }
7672       } else {
7673           printpipe = 0;
7674       }
7675 
7676 #ifdef PRINTSWI
7677 #ifdef BPRINT
7678     if (printpipe && pv[PRN_BID].ival > 0) {
7679         printf("?Sorry, pipes not allowed for bidirectional printer\n");
7680         return(-9);
7681     }
7682 #endif /* BPRINT */
7683 #endif /* PRINTSWI */
7684 #endif /* OS2ORUNIX */
7685 
7686 #ifdef OS2
7687     if ( pv[PRN_CS].ival > 0 )
7688         prncs = pv[PRN_CS].ival;
7689 
7690     if ( pv[PRN_PS].ival > 0 ) {
7691         txt2ps = 1;
7692         ps_width = pv[PRN_WID].ival <= 0 ? 80 : pv[PRN_WID].ival;
7693         ps_length = pv[PRN_LEN].ival <= 0 ? 66 : pv[PRN_LEN].ival;
7694     }
7695 #endif /* OS2 */
7696 
7697     y = strlen(s);                      /* Length of name of new print file */
7698     if (y > 0
7699 #ifdef OS2
7700         && ((y != 3) || (ckstrcmp(s,"PRN",3,0) != 0))
7701 #endif /* OS2 */
7702         ) {
7703         if (printername) {              /* Had a print file before? */
7704             free(printername);          /* Remove its name */
7705             printername = NULL;
7706         }
7707         printername = (char *) malloc(y + 1); /* Allocate space for it */
7708         if (!printername) {
7709             printf("?Memory allocation failure\n");
7710             return(-9);
7711         }
7712         strcpy(printername,s);          /* (safe) Copy new name to new space */
7713         debug(F110,"printername",printername,0);
7714     }
7715 
7716 #ifdef PRINTSWI
7717     /* Set printer type from switches that were given explicitly */
7718 
7719     if (pv[PRN_NON].ival > 0) {         /* No printer */
7720         printertype = PRT_NON;
7721         noprinter = 1;
7722         printpipe = 0;
7723     } else if (pv[PRN_FIL].ival > 0) {  /* File */
7724         printertype = PRT_FIL;
7725         noprinter = 0;
7726         printpipe = 0;
7727     } else if (pv[PRN_PIP].ival > 0) {  /* Pipe */
7728         printertype = PRT_PIP;
7729         noprinter = 0;
7730         printpipe = 1;
7731     } else if (pv[PRN_WIN].ival > 0) {  /* Windows print queue */
7732         printertype = PRT_WIN;
7733         noprinter = 0;
7734         printpipe = 0;
7735     } else if (pv[PRN_DOS].ival > 0) {  /* DOS device */
7736         printertype = PRT_DOS;
7737         noprinter = 0;
7738         printpipe = 0;
7739     } else if (line[0]) {               /* Name given without switches */
7740         noprinter = 0;
7741         printertype = printpipe ? PRT_PIP : PRT_DOS;
7742 #ifdef NT
7743         /* was the command SET PRINTER windows-queue ? */
7744         y = lookup(_printtab,line,nprint,&x);
7745         if (y >= 0) {
7746             printertype = PRT_WIN;
7747             if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7748             if (printername) {          /* Had a print file before? */
7749                 free(printername);      /* Remove its name */
7750                 printername = NULL;
7751             }
7752             pv[PRN_WIN].sval = NULL;
7753             pv[PRN_WIN].ival = 1;
7754             s = printtab[x].kwd;        /* Get full new name */
7755             if ((y = strlen(s)) > 0) {
7756                 makestr(&pv[PRN_WIN].sval,s);
7757                 makestr(&printername,s);
7758                 if (!printername) {
7759                     printf("?Memory allocation failure\n");
7760                     return(-9);
7761                 }
7762                 debug(F110,"printername",printername,0);
7763             }
7764         } else if ( y == -2 ) {
7765             /* Ambiguous Print Queue Name */
7766             printf("?Ambiguous printer name provided.\n");
7767             return(-9);
7768         }
7769 #endif /* NT */
7770     }
7771 
7772 #ifdef BPRINT
7773     /* Port parameters may be set for non-bidi mode */
7774 
7775     pportspeed = portspeed;             /* Set parameters */
7776     pportparity = portparity;
7777     pportflow = portflow;
7778 
7779     if (pv[PRN_BID].ival > 0) {         /* Bidirectional */
7780 #ifdef UNIX
7781         printbidi = 1;                  /* (just to test parsing...) */
7782 #else
7783         printbidi = bprtstart();        /* Start bidirectional printer */
7784 #endif /* UNIX */
7785         return(success = printbidi);
7786     } else
7787       printbidi = 0;                    /* Not BPRINTER, unset flag */
7788 #endif /* BPRINT */
7789 
7790     if (pv[PRN_TMO].ival > -1) {        /* Take care of timeout */
7791         printtimo = pv[PRN_TMO].ival;
7792     }
7793     if (pv[PRN_TRM].ival > 0) {         /* Termination string */
7794         if (printterm) {
7795             free(printterm);
7796             printterm = NULL;
7797         }
7798         if (pv[PRN_TRM].sval)
7799           makestr(&printterm,pv[PRN_TRM].sval);
7800     }
7801     if (pv[PRN_SEP].ival > 0) {         /* and separator file */
7802         if (printsep) {
7803             free(printsep);
7804             printsep = NULL;
7805         }
7806         if (pv[PRN_SEP].sval)
7807           makestr(&printsep,pv[PRN_SEP].sval);
7808     }
7809 #endif /* PRINTSWI */
7810 
7811 #ifdef UNIXOROSK
7812     if (!printpipe
7813 #ifdef PRINTSWI
7814         && !noprinter
7815 #endif /* PRINTSWI */
7816         ) {                             /* File - check access */
7817         if (zchko(s) < 0) {
7818             printf("?Access denied - %s\n",s);
7819             x = -9;
7820             goto xsetprn;
7821         }
7822     }
7823 #endif /* UNIXOROSK */
7824 
7825     x = 1;                              /* Return code */
7826 
7827   xsetprn:                              /* Common exit */
7828 #ifdef PRINTSWI
7829     for (i = 0; i <= PRN_MAX; i++) {    /* Free malloc'd memory */
7830         if (pv[i].sval)
7831           free(pv[i].sval);
7832     }
7833 #endif /* PRINTSWI */
7834     success = (x > 0) ? 1 : 0;
7835     return(x);
7836 }
7837 
7838 #ifdef ANYSSH
7839 /* The SET SSH command */
7840 
7841 #define SSH_CMD  1                      /* SET SSH COMMAND */
7842 
7843 #ifdef SSHBUILTIN                       /* Built-in SET SSH options */
7844 #define SSH_ADD  2                      /* Add */
7845 #define SSH_AFW  3                      /* Agent-forwarding */
7846 #define SSH_CHI  4                      /* Check Host IP */
7847 #define SSH_XFW  5                      /* X11-forwarding */
7848 #define SSH_DYF  6                      /* Dynamic forwarding */
7849 #define SSH_GWP  7                      /* Gatewa portgs */
7850 #define SSH_GSS  8                      /* GSSAPI */
7851 #define SSH_KBD  9                      /* KBD Interactive Devices */
7852 #define SSH_K4  10                      /* Kerberos 4 */
7853 #define SSH_K5  11                      /* Kerberos 5 */
7854 #define SSH_SHK 12                      /* Strict Host Key Check */
7855 #define SSH_V1  13                      /* SSH V1 */
7856 #define SSH_V2  14                      /* SSH V2 */
7857 #define SSH_PRP 15                      /* Privd port */
7858 #define SSH_CMP 16                      /* Compression */
7859 #define SSH_XAL 17                      /* X Auth Location */
7860 #define SSH_SHH 18                      /* Quiet */
7861 #define SSH_VER 19                      /* Version */
7862 #define SSH_VRB 20                      /* Verbosity level */
7863 #define SSH_IDF 21                      /* Identity File */
7864 #define SSH_CFG 22                      /* Use OpenSSH Config */
7865 #define SSH_HBT 23                      /* Heartbeat Interval */
7866 #endif /* SSHBUILTIN */
7867 
7868 static struct keytab sshtab[] = {       /* SET SSH command table */
7869 #ifdef SSHBUILTIN
7870     { "agent-forwarding",        SSH_AFW,  0 },
7871     { "check-host-ip",           SSH_CHI,  0 },
7872     { "compression",             SSH_CMP,  0 },
7873     { "dynamic-forwarding",      SSH_DYF,  0 },
7874     { "gateway-ports",           SSH_GWP,  0 },
7875     { "gssapi",                  SSH_GSS,  0 },
7876     { "heartbeat-interval",      SSH_HBT,  0 },
7877     { "identity-file",           SSH_IDF,  0 },
7878 #ifdef COMMENT
7879     { "kbd-interactive-devices", SSH_KBD,  0 },
7880 #endif /* COMMENT */
7881     { "k4",                      SSH_K4, CM_INV },
7882     { "k5",                      SSH_K5, CM_INV },
7883     { "kerberos4",               SSH_K4,   0 },
7884     { "kerberos5",               SSH_K5,   0 },
7885     { "krb4",                    SSH_K4, CM_INV },
7886     { "krb5",                    SSH_K5, CM_INV },
7887     { "privileged-port",         SSH_PRP,  0 },
7888     { "quiet",                   SSH_SHH,  0 },
7889     { "strict-host-key-check",   SSH_SHK,  0 },
7890     { "use-openssh-config",      SSH_CFG,  0 },
7891     { "v1",                      SSH_V1,   0 },
7892     { "v2",                      SSH_V2,   0 },
7893     { "verbose",                 SSH_VRB,  0 },
7894     { "version",                 SSH_VER,  0 },
7895     { "x11-forwarding",          SSH_XFW,  0 },
7896     { "xauth-location",          SSH_XAL,  0 },
7897 #else
7898 #ifdef SSHCMD
7899     { "command",                 SSH_CMD,  0 },
7900 #endif /* SSHCMD */
7901 #endif /* SSHBUILTIN */
7902     { "", 0, 0 }
7903 };
7904 static int nsshtab = (sizeof(sshtab) / sizeof(struct keytab)) - 1;
7905 
7906 #ifdef SSHBUILTIN
7907 static struct keytab sshver[] = {       /* SET SSH VERSION command table */
7908     { "1",          1,  0 },
7909     { "2",          2,  0 },
7910     { "automatic",  0,  0 }
7911 };
7912 
7913 #define SSHA_CRS   1
7914 #define SSHA_DSA   2
7915 #define SSHA_GSS   3
7916 #define SSHA_HOS   4
7917 #define SSHA_KBD   5
7918 #define SSHA_K4    6
7919 #define SSHA_K5    7
7920 #define SSHA_PSW   8
7921 #define SSHA_PK    9
7922 #define SSHA_SKE  10
7923 #define SSHA_TIS  11
7924 #define SSHA_EXT  12
7925 #define SSHA_SRP  13
7926 
7927 static struct keytab ssh2aut[] = {      /* SET SSH V2 AUTH command table */
7928     { "external-keyx",      SSHA_EXT, 0 },
7929     { "gssapi",             SSHA_GSS, 0 },
7930     { "hostbased",          SSHA_HOS, 0 },
7931     { "keyboard-interactive",  SSHA_KBD, 0 },
7932     { "password",           SSHA_PSW, 0 },
7933     { "publickey",          SSHA_PK,  0 },
7934     { "srp-gex-sha1",       SSHA_SRP, 0 },
7935     { "", 0, 0 }
7936 };
7937 static int nssh2aut = (sizeof(ssh2aut) / sizeof(struct keytab)) - 1;
7938 
7939 #define SSHF_LCL   1
7940 #define SSHF_RMT   2
7941 
7942 static struct keytab addfwd[] = {       /* SET SSH ADD command table */
7943     { "local-port-forward",  SSHF_LCL, 0 },
7944     { "remote-port-forward", SSHF_RMT, 0 },
7945     { "", 0, 0 }
7946 };
7947 static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
7948 
7949 #define SSH1_CIF   1
7950 #define SSH1_GNH   2
7951 #define SSH1_UNH   3
7952 #define SSH1_K54   4
7953 
7954 #define SSH2_CIF   1
7955 #define SSH2_GNH   2
7956 #define SSH2_UNH   3
7957 #define SSH2_ARK   4
7958 #define SSH2_HKA   5
7959 #define SSH2_MAC   6
7960 #define SSH2_AUT   7
7961 
7962 static struct keytab sshv1tab[] = {     /* SET SSH V1 command table */
7963     { "cipher",                  SSH1_CIF, 0 },
7964     { "global-known-hosts-file", SSH1_GNH, 0 },
7965     { "k5-reuse-k4-messages",    SSH1_K54, CM_INV },
7966     { "user-known-hosts-file",   SSH1_UNH, 0 },
7967     { "", 0, 0 }
7968 };
7969 static int nsshv1tab = (sizeof(sshv1tab) / sizeof(struct keytab)) - 1;
7970 
7971 static struct keytab sshv2tab[] = {     /* SET SSH V2 command table */
7972     { "authentication",          SSH2_AUT, 0 },
7973     { "auto-rekey",              SSH2_ARK, 0 },
7974     { "ciphers",                 SSH2_CIF, 0 },
7975     { "global-known-hosts-file", SSH2_GNH, 0 },
7976     { "hostkey-algorithms",      SSH2_HKA, 0 },
7977     { "macs",                    SSH2_MAC, 0 },
7978     { "user-known-hosts-file",   SSH2_UNH, 0 },
7979     { "", 0, 0 }
7980 };
7981 static int nsshv2tab = (sizeof(sshv2tab) / sizeof(struct keytab)) - 1;
7982 
7983 #define SSHC_3DES 1                     /* 3DES */
7984 #define SSHC_3CBC 2                     /* 3DES-CBC */
7985 #define SSHC_A128 3                     /* AES128-CBC */
7986 #define SSHC_A192 4                     /* AES192-CBC */
7987 #define SSHC_A256 5                     /* AES256-CBC */
7988 #define SSHC_ARC4 6                     /* ARCFOUR */
7989 #define SSHC_FISH 7                     /* BLOWFISH */
7990 #define SSHC_BCBC 9                     /* BLOWFISH-CBC */
7991 #define SSHC_C128 8                     /* CAST128-CBC */
7992 #define SSHC_1DES 10                    /* DES */
7993 
7994 static struct keytab ssh1ciphers[] = {
7995     { "3des",         SSHC_3DES, 0 },
7996     { "blowfish",     SSHC_FISH, 0 },
7997     { "des",          SSHC_1DES, 0 },
7998     { "", 0, 0 }
7999 };
8000 static int nssh1ciphers = (sizeof(ssh1ciphers) / sizeof(struct keytab)) - 1;
8001 
8002 static struct keytab ssh2ciphers[] = {  /* SET SSH V2 CIPHERS command table */
8003     { "3des-cbc",        SSHC_3DES, 0 },
8004     { "aes128-cbc",      SSHC_A128, 0 },
8005     { "aes192-cbc",      SSHC_A192, 0 },
8006     { "aes256-cbc",      SSHC_A256, 0 },
8007     { "arcfour",         SSHC_ARC4, 0 },
8008     { "blowfish-cbc",    SSHC_FISH, 0 },
8009     { "cast128-cbc",     SSHC_C128, 0 },
8010     { "rijndael128-cbc", SSHC_A128, 0 },
8011     { "rijndael192-cbc", SSHC_A192, 0 },
8012     { "rijndael256-cbc", SSHC_A256, 0 },
8013     { "", 0, 0 }
8014 };
8015 static int nssh2ciphers = (sizeof(ssh2ciphers) / sizeof(struct keytab)) - 1;
8016 
8017 #define SSHM_SHA        1               /* HMAC-SHA1 */
8018 #define SSHM_SHA_96     2               /* HMAC-SHA1-96 */
8019 #define SSHM_MD5        3               /* HMAC-MD5 */
8020 #define SSHM_MD5_96     4               /* HMAC-MD5-96 */
8021 #define SSHM_RIPE       5               /* HMAC-RIPEMD160 */
8022 
8023 static struct keytab ssh2macs[] = {     /* SET SSH V2 MACS command table */
8024     { "hmac-md5",       SSHM_MD5,    0 },
8025     { "hmac-md5-96",    SSHM_MD5_96, 0 },
8026     { "hmac-ripemd160", SSHM_RIPE,   0 },
8027     { "hmac-sha1",      SSHM_SHA,    0 },
8028     { "hmac-sha1-96",   SSHM_SHA_96, 0 },
8029     { "", 0, 0 }
8030 };
8031 static int nssh2macs = (sizeof(ssh2macs) / sizeof(struct keytab)) - 1;
8032 
8033 static struct keytab tgtpass[] = {
8034     { "tgt-passing", 1, 0, },
8035     { "", 0, 0 }
8036 };
8037 static int ntgtpass = (sizeof(tgtpass) / sizeof(struct keytab)) - 1;
8038 
8039 static struct keytab gssapitab[] = {
8040     { "delegate-credentials", 1, 0, },
8041     { "key-exchange",         2, CM_INV, },
8042     { "", 0, 0 }
8043 };
8044 static int ngssapitab = (sizeof(gssapitab) / sizeof(struct keytab)) - 1;
8045 
8046 #define HKA_RSA 1
8047 #define HKA_DSS 2
8048 
8049 static struct keytab hkatab[] = {
8050     { "ssh-dss", HKA_DSS, 0, },
8051     { "ssh-rsa", HKA_RSA, 0, },
8052     { "", 0, 0 }
8053 };
8054 static int nhkatab = (sizeof(hkatab) / sizeof(struct keytab)) - 1;
8055 
8056 int                                     /* SET SSH variables */
8057   ssh_afw = 0,                          /* agent forwarding */
8058   ssh_xfw = 0,                          /* x11 forwarding   */
8059   ssh_prp = SET_OFF,                    /* privileged ports */
8060   ssh_cmp = 1,                          /* compression */
8061   ssh_shh = 0,                          /* quiet       */
8062   ssh_ver = 0,                          /* protocol version (auto,1,2) */
8063   ssh_vrb = 2,                          /* Report errors */
8064   ssh_chkip = 0,                        /* SSH Check Host IP flag */
8065   ssh_gwp = 0,                          /* gateway ports */
8066   ssh_dyf = 0,                          /* dynamic forwarding */
8067   ssh_gsd = 0,                          /* gssapi delegate credentials */
8068   ssh_k4tgt = 0,                        /* k4 tgt passing */
8069   ssh_k5tgt = 0,                        /* k5 tgt passing */
8070   ssh_shk = 2,                          /* Strict host key (no, yes, ask) */
8071   ssh2_ark = 1,                         /* Auto re-key */
8072   ssh_cas = 0,                          /* command as subsys */
8073   ssh_cfg = 0,                          /* use OpenSSH config? */
8074   ssh_gkx = 1,                          /* gssapi key exchange */
8075   ssh_k5_is_k4 = 1,                     /* some SSH v1 use same codes */
8076   ssh_hbt = 0,                          /* heartbeat (seconds) */
8077   ssh_dummy = 0;                        /* bottom of list */
8078 
8079 char                                    /* The following are to be malloc'd */
8080   * ssh1_cif = NULL,                    /* v1 cipher */
8081   * ssh2_cif = NULL,                    /* v2 cipher list */
8082   * ssh2_mac = NULL,                    /* v2 mac list */
8083   * ssh2_auth = NULL,                   /* v2 authentication list */
8084   * ssh_hst = NULL,                     /* hostname */
8085   * ssh_prt = NULL,                     /* port/service */
8086   * ssh_cmd = NULL,                     /* command to execute */
8087   * ssh_xal = NULL,                     /* xauth-location */
8088   * ssh1_gnh = NULL,                    /* v1 global known hosts file */
8089   * ssh1_unh = NULL,                    /* v1 user known hosts file */
8090   * ssh2_gnh = NULL,                    /* v2 global known hosts file */
8091   * ssh2_unh = NULL,                    /* v2 user known hosts file */
8092   * ssh2_hka = NULL,                    /* Host Key Algorithms */
8093   * xxx_dummy = NULL;
8094 
8095 char * ssh_idf[32] = {                  /* Identity file list */
8096   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
8097   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
8098   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
8099   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
8100 };
8101 char * ssh_tmp[32] = {                  /* Temp identity file list */
8102   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
8103   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
8104   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
8105   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
8106 };
8107 int ssh_idf_n = 0;
8108 
8109 extern int    ssh_pf_lcl_n,
8110               ssh_pf_rmt_n;
8111 extern struct ssh_pf ssh_pf_lcl[32];    /* Port forwarding structs */
8112 extern struct ssh_pf ssh_pf_rmt[32];    /* (declared in ckuusr.c) */
8113 #endif /* SSHBUILTIN */
8114 
8115 #ifdef SFTP_BUILTIN
8116 static struct keytab sftptab[] = {
8117     { "end-of-line",            XY_SFTP_EOL, 0, },
8118     { "remote-character-set",   XY_SFTP_RCS, 0, },
8119     { "", 0, 0 }
8120 };
8121 static int nsftptab = (sizeof(sftptab) / sizeof(struct keytab)) - 1;
8122 #endif /* SFTP_BUILTIN */
8123 
8124 VOID
8125 shossh() {
8126 #ifdef SSHBUILTIN
8127     int i, n = 0;                       /* ADD askmore()! */
8128 
8129     printf("\nSSH is built in:\n\n");
8130 
8131     printf(" ssh host:                        %s\n",showstring(ssh_hst));
8132     printf(" ssh port:                        %s\n",showstring(ssh_prt));
8133     printf(" ssh command:                     %s\n",showstring(ssh_cmd));
8134     printf(" ssh agent-forwarding:            %s\n",showoff(ssh_afw));
8135     printf(" ssh check-host-ip:               %s\n",showoff(ssh_chkip));
8136     printf(" ssh compression:                 %s\n",showoff(ssh_cmp));
8137     printf(" ssh dynamic-forwarding:          %s\n",showoff(ssh_dyf));
8138     if (ssh_pf_lcl[0].p1 && ssh_pf_lcl[0].host && ssh_pf_lcl[0].p2) {
8139       printf(" ssh forward-local-port:          %d %s %d\n",
8140              ssh_pf_lcl[0].p1, ssh_pf_lcl[0].host, ssh_pf_lcl[0].p2);
8141       for ( n=1;n<ssh_pf_lcl_n;n++ )
8142         printf("                       :          %d %s %d\n",
8143                ssh_pf_lcl[n].p1, ssh_pf_lcl[n].host, ssh_pf_lcl[n].p2);
8144     } else
8145       printf(" ssh forward-local-port:         (none)\n");
8146     if (ssh_pf_rmt[0].p1 && ssh_pf_rmt[0].host && ssh_pf_rmt[0].p2) {
8147       printf(" ssh forward-remote-port:         %d %s %d\n",
8148              ssh_pf_rmt[0].p1, ssh_pf_rmt[0].host, ssh_pf_rmt[0].p2);
8149       for ( n=1;n<ssh_pf_rmt_n;n++ )
8150         printf("                        :         %d %s %d\n",
8151                ssh_pf_rmt[n].p1, ssh_pf_rmt[n].host, ssh_pf_rmt[n].p2);
8152     } else
8153       printf(" ssh forward-remote-port:        (none)\n");
8154     printf(" ssh gateway-ports:               %s\n",showoff(ssh_gwp));
8155     printf(" ssh gssapi delegate-credentials: %s\n",showoff(ssh_gsd));
8156     printf(" ssh gssapi key-exchange        : %s\n",showoff(ssh_gkx));
8157     printf(" ssh identity-file:               %d\n",ssh_idf_n);
8158     for (i = 0; i < ssh_idf_n; i++)
8159       printf("  %2d. %s\n",i+1,showstring(ssh_idf[i]));
8160     printf(" ssh heartbeat interval:          %d\n", ssh_hbt);
8161     printf(" ssh k4 tgt-passing:              %s\n",showoff(ssh_k4tgt));
8162     printf(" ssh k5 tgt-passing:              %s\n",showoff(ssh_k5tgt));
8163 
8164     printf(" ssh privileged-port:             %s\n",showooa(ssh_prp));
8165     printf(" ssh quiet:                       %s\n",showoff(ssh_shh));
8166     printf(" ssh strict-host-key-check:       %d\n",ssh_shk);
8167     printf(" ssh use-openssh-config:          %s\n",showoff(ssh_cfg));
8168     printf(" ssh verbose:                     %d\n",ssh_vrb);
8169     printf(" ssh version:                     %s\n",
8170            ssh_ver ? ckitoa(ssh_ver) : "automatic"
8171            );
8172     printf(" ssh x11-forwarding:              %s\n",showooa(ssh_xfw));
8173     printf(" ssh xauth-location:              %s\n",showstring(ssh_xal));
8174     printf("\n");
8175     printf(" ssh v1 cipher:                   %s\n",showstring(ssh1_cif));
8176     printf(" ssh v1 global-known-hosts-file:  %s\n",showstring(ssh1_gnh));
8177     printf(" ssh v1 user-known-hosts-file:    %s\n",showstring(ssh1_unh));
8178     printf("\n");
8179     printf(" ssh v2 authentication:           %s\n",showstring(ssh2_auth));
8180     printf(" ssh v2 auto-rekey:               %s\n",showoff(ssh2_ark));
8181     printf(" ssh v2 ciphers:                  %s\n",showstring(ssh2_cif));
8182     printf(" ssh v2 command-as-subsystem:     %s\n",showoff(ssh_cas));
8183     printf(" ssh v2 global-known-hosts-file:  %s\n",showstring(ssh2_gnh));
8184     printf(" ssh v2 hostkey-algorithms:       %s\n",showstring(ssh2_hka));
8185     printf(" ssh v2 mac:                      %s\n",showstring(ssh2_mac));
8186     printf(" ssh v2 user-known-hosts-file:    %s\n",showstring(ssh2_unh));
8187 #else
8188 #ifdef SSHCMD
8189     extern char * sshcmd, * defsshcmd;
8190     char * s;
8191     s = sshcmd ? sshcmd : defsshcmd;
8192     printf("\n SSH is external.\n\n");
8193     printf(" ssh command: %s\n",showstring(s));
8194 #endif /* SSHCMD */
8195 #endif /* SSHBUILTIN */
8196     printf("\n");
8197 }
8198 
8199 static int
8200 dosetssh() {
8201 #ifdef SSHCMD
8202     extern char * sshcmd;
8203 #endif /* SSHCMD */
8204 #ifdef SSHBUILTIN
8205 #ifndef SSHTEST
8206     extern int sl_ssh_xfw_saved, sl_ssh_ver_saved;
8207 #endif /* SSHTEST */
8208 #endif /* SSHBUILTIN */
8209     int cx, x, y, z;
8210     char * s;
8211 
8212     if ((cx = cmkey(sshtab,nsshtab,"","command", xxstring)) < 0)
8213       return(cx);
8214     switch (cx) {
8215 #ifdef SSHCMD
8216       case SSH_CMD:                     /* Command */
8217         if ((x = cmtxt("Command to start ssh","ssh -e none",
8218                        &s,xxstring)) < 0)
8219           return(x);
8220         makestr(&sshcmd,s);
8221         return(success = 1);
8222 #endif /* SSHCMD */
8223 
8224 #ifdef SSHBUILTIN
8225       case SSH_AFW:                     /* Agent-forwarding */
8226         return(success = seton(&ssh_afw));
8227 
8228       case SSH_CHI:                     /* Check Host IP */
8229         return(success = seton(&ssh_chkip));
8230         break;
8231 
8232       case SSH_CMP:                     /* Compression */
8233         return(success = seton(&ssh_cmp));
8234 
8235       case SSH_DYF:                     /* Dynamic Forwarding */
8236         return(success = seton(&ssh_dyf));
8237 
8238       case SSH_GWP:                     /* Gateway ports */
8239         return(success = seton(&ssh_gwp));
8240 
8241       case SSH_GSS:                     /* GSSAPI */
8242         if ((y = cmkey(gssapitab,ngssapitab,"","", xxstring)) < 0)
8243           return(y);
8244         switch (y) {
8245           case 1:                       /* Delegate credentials */
8246             return(success = seton(&ssh_gsd));
8247           case 2:                       /* key-exchange */
8248             return(success = seton(&ssh_gkx));
8249         }
8250         if ((x = cmcfm()) < 0)
8251           return(x);
8252         return(success = 0);
8253 
8254 #ifdef COMMENT
8255       case SSH_KBD:                     /* Kbd Interactive Devices */
8256         if ((x = cmcfm()) < 0)
8257           return(x);
8258         /* TO BE FILLED IN */
8259         return(-2);
8260 #endif /* COMMENT */
8261 
8262       case SSH_K4:                      /* Kerberos IV */
8263       case SSH_K5:                      /* Kerberos V */
8264         if ((y = cmkey(tgtpass,1,"","tgt-passing", xxstring)) < 0)
8265           return(y);
8266         switch (y) {
8267           case 1:
8268             return(success = (cx == SSH_K4) ?
8269                    seton(&ssh_k4tgt) : seton(&ssh_k5tgt));
8270         }
8271         if ((x = cmcfm()) < 0)
8272           return(x);
8273         return(success = 0);
8274 
8275       case SSH_PRP:                     /* Privd port */
8276         return(success = seton(&ssh_prp));
8277 
8278       case SSH_SHH:                     /* Quiet */
8279         return(success = seton(&ssh_shh));
8280 
8281       case SSH_SHK:                     /* Strict Host Key Check */
8282         if ((y = cmkey(ooktab,3,"","", xxstring)) < 0)
8283           return(y);
8284         if ((x = cmcfm()) < 0)
8285           return(x);
8286         ssh_shk = y;
8287         return(success = 1);
8288 
8289       case SSH_HBT:
8290 	x = cmnum("Heartbeat interval, seconds","0",10,&z,xxstring);
8291 	if (x < 0) return(x);
8292 	if ((x = cmcfm()) < 0) return(x);
8293 	ssh_hbt = z;
8294 	return(success = 1);
8295 
8296       case SSH_V1:                      /* SSH V1 */
8297         if ((y = cmkey(sshv1tab,nsshv1tab,"","", xxstring)) < 0)
8298           return(y);
8299         switch (y) {
8300           case SSH1_K54:
8301             return(success = seton(&ssh_k5_is_k4));
8302           case SSH1_CIF:                /* Not a list */
8303             if ((y = cmkey(ssh1ciphers,nssh1ciphers,"","", xxstring)) < 0)
8304               if (y != -3)
8305                 return(y);
8306             if ((x = cmcfm()) < 0) return(x);
8307             if (y == -3) {
8308                 makestr(&ssh1_cif,NULL);
8309             } else {
8310                 for (x = 0; x < nssh1ciphers; x++)
8311                   if (ssh1ciphers[x].kwval == y)
8312                     break;
8313                 makestr(&ssh1_cif,ssh1ciphers[x].kwd);
8314             }
8315             return(1);
8316           case SSH1_GNH:
8317           case SSH1_UNH:
8318             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
8319                 if (x != -3)
8320                   return(x);
8321             } else {
8322                 ckstrncpy(line,s,LINBUFSIZ);
8323                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8324                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
8325             }
8326             s = (x == -3) ? NULL : line;
8327             if ((x = cmcfm()) < 0)
8328               return(x);
8329             switch (y) {
8330               case SSH1_GNH: makestr(&ssh1_gnh,s); break;
8331               case SSH1_UNH: makestr(&ssh1_unh,s); break;
8332             }
8333             return(1);
8334         }
8335 
8336       case SSH_V2:                      /* SSH V2 */
8337         if ((y = cmkey(sshv2tab,nsshv2tab,"","", xxstring)) < 0)
8338           return(y);
8339         switch (y) {
8340           case SSH2_ARK:
8341             return(success = seton(&ssh2_ark));
8342         case SSH2_AUT: {                        /* Authentication */
8343 #define TMPCNT 12
8344             int i, j, tmp[TMPCNT];
8345             for (i = 0; i < TMPCNT; i++)
8346               tmp[i] = 0;
8347             for (i = 0; i < TMPCNT; i++) {
8348                 if ((y = cmkey(ssh2aut,nssh2aut,
8349                                "Authentication method","",xxstring)) < 0) {
8350                     if (y == -3)
8351                       break;
8352                     return(y);
8353                 }
8354                 for (j = 0; j < i; j++) {
8355                     if (tmp[j] == y) {
8356                         printf("\r\n?Choice has already been used.\r\n");
8357                         return(-9);
8358                     }
8359                 }
8360                 tmp[i] = y;
8361             }
8362             if ((z = cmcfm()) < 0)
8363               return(z);
8364 
8365             if (ssh2_auth) {
8366                 free(ssh2_auth);
8367                 ssh2_auth = NULL;
8368             }
8369             if (i > 0) {
8370                 int len = 0;
8371                 for (j = 0; j < i; j++) {
8372                     for (x = 0; x < nssh2aut; x++)
8373                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
8374                         break;
8375                     len += strlen(ssh2aut[x].kwd) + 1;
8376                 }
8377                 ssh2_auth = malloc(len);
8378                 ssh2_auth[0] = '\0';
8379                 for (j = 0; j < i; j++) {
8380                     for (x = 0; x < nssh2aut; x++)
8381                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
8382                         break;
8383                     ckstrncat(ssh2_auth,ssh2aut[x].kwd,len);
8384                     if (j < i - 1)
8385                       ckstrncat(ssh2_auth,",",len);
8386                 }
8387             }
8388             return(success = 1);
8389 #undef TMPCNT
8390           }
8391         case SSH2_CIF: {
8392 #define TMPCNT 12
8393             int i, j, tmp[TMPCNT];
8394             for (i = 0; i < TMPCNT; i++)
8395               tmp[i] = 0;
8396 
8397             for (i = 0; i < TMPCNT; i++) {
8398                 if ((y = cmkey(ssh2ciphers,nssh2ciphers,
8399                                "","", xxstring)) < 0) {
8400                     if (y == -3)
8401                       break;
8402                     return(y);
8403                 }
8404                 for (j = 0; j < i; j++) {
8405                     if (tmp[j] == y) {
8406                         printf("\r\n?Choice has already been used.\r\n");
8407                         return(-9);
8408                     }
8409                 }
8410                 tmp[i] = y;
8411             }
8412             if ((z = cmcfm()) < 0)
8413               return(z);
8414 
8415             if (ssh2_cif) {
8416                 free(ssh2_cif);
8417                 ssh2_cif = NULL;
8418             }
8419             if (i > 0) {
8420                 int len = 0;
8421                 for (j=0; j < i; j++) {
8422                     for (x = 0; x < nssh2ciphers; x++)
8423                       if (ssh2ciphers[x].kwval == tmp[j] &&
8424                           !ssh2ciphers[x].flgs)
8425                         break;
8426                     len += strlen(ssh2ciphers[x].kwd) + 1;
8427                 }
8428                 ssh2_cif = malloc(len);
8429                 ssh2_cif[0] = '\0';
8430                 for (j = 0; j < i; j++) {
8431                   for (x = 0; x < nssh2ciphers; x++)
8432                     if (ssh2ciphers[x].kwval == tmp[j] && !ssh2ciphers[x].flgs)
8433                       break;
8434                     ckstrncat(ssh2_cif,ssh2ciphers[x].kwd,len);
8435                     if (j < i - 1)
8436                       ckstrncat(ssh2_cif,",",len);
8437                 }
8438             }
8439             return(success = 1);
8440 #undef TMPCNT
8441         }
8442         case SSH2_MAC: {
8443 #define TMPCNT 12
8444             int i, j, tmp[TMPCNT];
8445             for (i = 0; i < TMPCNT; i++)
8446               tmp[i] = 0;
8447 
8448             for (i = 0; i < TMPCNT; i++) {
8449                 if ((y = cmkey(ssh2macs,nssh2macs,"","", xxstring)) < 0) {
8450                     if (y == -3)
8451                       break;
8452                     return(y);
8453                 }
8454                 for (j = 0; j < i; j++) {
8455                     if (tmp[j] == y) {
8456                         printf("\r\n?Choice has already been used.\r\n");
8457                         return(-9);
8458                     }
8459                 }
8460                 tmp[i] = y;
8461             }
8462             if ((z = cmcfm()) < 0)
8463                 return(z);
8464 
8465             if (ssh2_mac) {
8466                 free(ssh2_mac);
8467                 ssh2_mac = NULL;
8468             }
8469             if (i > 0) {
8470                 int len = 0;
8471                 for (j = 0; j < i; j++) {
8472                     for (x = 0; x < nssh2macs; x++)
8473                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
8474                         break;
8475                     len += strlen(ssh2macs[x].kwd) + 1;
8476                 }
8477                 ssh2_mac = malloc(len);
8478                 ssh2_mac[0] = '\0';
8479                 for (j=0; j < i; j++) {
8480                     for (x = 0; x < nssh2macs; x++)
8481                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
8482                         break;
8483                     ckstrncat(ssh2_mac,ssh2macs[x].kwd,len);
8484                     if (j < i - 1)
8485                       ckstrncat(ssh2_mac,",",len);
8486                 }
8487             }
8488             return(success = 1);
8489 #undef TMPCNT
8490           }
8491           case SSH2_HKA: {
8492 #define TMPCNT 12
8493             int i, j, tmp[TMPCNT];
8494             for (i = 0; i < TMPCNT; i++)
8495               tmp[i] = 0;
8496 
8497             for (i = 0; i < TMPCNT; i++) {
8498                 if ((y = cmkey(hkatab,nhkatab,
8499                                "","", xxstring)) < 0) {
8500                     if (y == -3)
8501                       break;
8502                     return(y);
8503                 }
8504                 for (j = 0; j < i; j++) {
8505                     if (tmp[j] == y) {
8506                         printf("\r\n?Choice has already been used.\r\n");
8507                         return(-9);
8508                     }
8509                 }
8510                 tmp[i] = y;
8511             }
8512             if ((z = cmcfm()) < 0)
8513               return(z);
8514 
8515             if (ssh2_hka) {
8516                 free(ssh2_hka);
8517                 ssh2_hka = NULL;
8518             }
8519             if (i > 0) {
8520                 int len = 0;
8521                 for (j=0; j < i; j++) {
8522                     for (x = 0; x < nhkatab; x++)
8523                       if (hkatab[x].kwval == tmp[j] &&
8524                           !hkatab[x].flgs)
8525                         break;
8526                     len += strlen(hkatab[x].kwd) + 1;
8527                 }
8528                 ssh2_hka = malloc(len);
8529                 ssh2_hka[0] = '\0';
8530                 for (j = 0; j < i; j++) {
8531                   for (x = 0; x < nhkatab; x++)
8532                     if (hkatab[x].kwval == tmp[j] && !hkatab[x].flgs)
8533                       break;
8534                     ckstrncat(ssh2_hka,hkatab[x].kwd,len);
8535                     if (j < i - 1)
8536                       ckstrncat(ssh2_hka,",",len);
8537                 }
8538             }
8539             return(success = 1);
8540 #undef TMPCNT
8541           }
8542           case SSH2_GNH:
8543           case SSH2_UNH:
8544             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
8545                 if (x != -3)
8546                   return(x);
8547             } else {
8548                 ckstrncpy(line,s,LINBUFSIZ);
8549                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8550                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
8551             }
8552             s = (x == -3) ? NULL : line;
8553             if ((x = cmcfm()) < 0)
8554               return(x);
8555             switch (y) {
8556               case SSH2_GNH: makestr(&ssh2_gnh,s); break;
8557               case SSH2_UNH: makestr(&ssh2_unh,s); break;
8558               default: return(success = 0);
8559             }
8560             return(success = 1);
8561         }
8562 
8563       case SSH_VRB:                     /* Verbosity level */
8564         y = cmnum("SSH verbosity level, 0-7","2",10,&x,xxstring);
8565         return(setnum(&ssh_vrb,x,y,7));
8566 
8567       case SSH_VER:                     /* Version */
8568         if ((y = cmkey(sshver,3,"","auto", xxstring)) < 0)
8569           return(y);
8570         if ((x = cmcfm()) < 0)
8571           return(x);
8572         ssh_ver = y;                    /* 0 == AUTO */
8573 #ifndef SSHTEST
8574         sl_ssh_ver_saved = 0;
8575 #endif /* SSHTEST */
8576         return(success = 1);
8577 
8578       case SSH_IDF: {                   /* Identity file */
8579         int i, n;
8580         for (i = 0; i < 32; i++) {
8581             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
8582                 if (x == -3)
8583                   break;
8584                 return(x);
8585             }
8586             if (!zfnqfp(s,LINBUFSIZ,line))
8587               ckstrncpy(line,s,LINBUFSIZ);
8588             makestr(&ssh_tmp[i],line);
8589         }
8590         n = i;
8591         if ((x = cmcfm()) < 0) {
8592             for (i = 0; i < n; i++)
8593               makestr(&(ssh_tmp[i]),NULL);
8594             return(x);
8595         }
8596         for (i = 0; i < 32; i++) {
8597             makestr(&(ssh_idf[i]),NULL);
8598             if (i < n) {
8599                 ssh_idf[i] = ssh_tmp[i];
8600                 ssh_tmp[i] = NULL;
8601             } else {
8602                 makestr(&(ssh_tmp[i]),NULL);
8603             }
8604         }
8605         ssh_idf_n = n;
8606         return(success = 1);
8607       }
8608       case SSH_XFW:                     /* X11-forwarding */
8609         success = seton(&ssh_xfw);
8610 #ifndef SSHTEST
8611         if (success)
8612           sl_ssh_xfw_saved = 0;
8613 #endif /* SSHTEST */
8614         return(success);
8615 
8616       case SSH_XAL:                     /* SSH Xauth Location */
8617         if ((x = cmifi("Path to executable", "",&s,&y,xxstring)) < 0) {
8618             if (x != -3)
8619               return(x);
8620         } else {
8621             ckstrncpy(line,s,LINBUFSIZ);
8622             if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8623               ckstrncpy(line,tmpbuf,LINBUFSIZ);
8624         }
8625         s = (x == -3) ? NULL : line;
8626         if ((x = cmcfm()) < 0) return(x);
8627         makestr(&ssh_xal,s);
8628         return(success = 1);
8629 
8630       case SSH_CFG:                     /* Use OpenSSH Config */
8631         return(success = seton(&ssh_cfg));
8632 #endif /* SSHBUILTIN */
8633 
8634       default:
8635         return(-2);
8636     }
8637 }
8638 #endif /* ANYSSH */
8639 
8640 #ifdef SFTP_BUILTIN
8641 static int
8642 dosetsftp() {
8643     int cx, x, y, z;
8644     char * s;
8645 
8646     if ((cx = cmkey(sftptab,nsftptab,"","", xxstring)) < 0)
8647       return(cx);
8648     switch (cx) {
8649     case XY_SFTP_EOL:
8650     case XY_SFTP_RCS:
8651     default:
8652         return(-2);
8653     }
8654 }
8655 #endif /* SFTP_BUILTIN */
8656 
8657 #ifdef KUI
8658 #include "ikui.h"
8659 extern ULONG RGBTable[16];
8660 
8661 #define GUI_RGB  1
8662 #define GUI_WIN  2
8663 #define GUI_FON  3
8664 #define GUI_DIA  4
8665 #define GUI_TLB  5
8666 #define GUI_MNB  6
8667 #define GUI_CLS  7
8668 
8669 #define GUIW_POS 1
8670 #define GUIW_RES 2
8671 #define GUIW_RUN 3
8672 #define GUIWR_NON 0
8673 #define GUIWR_FON 1
8674 #define GUIWR_DIM 2
8675 #define GUIWN_RES 1
8676 #define GUIWN_MIN 2
8677 #define GUIWN_MAX 3
8678 
8679 static struct keytab guitab[] = {
8680     { "close",       GUI_CLS,  0 },
8681     { "dialogs",     GUI_DIA,  0 },
8682     { "font",        GUI_FON,  0 },
8683     { "menubar",     GUI_MNB,  0 },
8684     { "rgbcolor",    GUI_RGB,  0 },
8685     { "toolbar",     GUI_TLB,  0 },
8686     { "window",      GUI_WIN,  0 },
8687     { "", 0, 0}
8688 };
8689 static int nguitab = (sizeof(guitab) / sizeof(struct keytab));
8690 
8691 static struct keytab guiwtab[] = {
8692     { "position",    GUIW_POS, 0 },
8693     { "resize-mode", GUIW_RES, 0 },
8694     { "run-mode",    GUIW_RUN, 0 },
8695     { "", 0, 0}
8696 };
8697 static int nguiwtab = (sizeof(guiwtab) / sizeof(struct keytab));
8698 
8699 static struct keytab guiwrtab[] = {
8700     { "change-dimensions",  GUIWR_DIM, 0 },
8701     { "none",               GUIWR_NON, 0 },
8702     { "scale-font",         GUIWR_FON, 0 },
8703     { "", 0, 0}
8704 };
8705 static int nguiwrtab = (sizeof(guiwrtab) / sizeof(struct keytab));
8706 
8707 static struct keytab guiwntab[] = {
8708     { "maximize",  GUIWN_MAX, 0 },
8709     { "minimize",  GUIWN_MIN, 0 },
8710     { "restore",   GUIWN_RES, 0 },
8711     { "", 0, 0}
8712 };
8713 static int nguiwntab = (sizeof(guiwntab) / sizeof(struct keytab));
8714 
8715 static struct keytab rgbtab[] = {
8716     { "black",         0, 0 },
8717     { "blue",          1, 0 },
8718     { "brown",         6, 0 },
8719     { "cyan",          3, 0 },
8720     { "darkgray",      8, 0 },
8721     { "dgray",         8, CM_INV },
8722     { "green",         2, 0 },
8723     { "lblue",         9, CM_INV },
8724     { "lcyan",        11, CM_INV },
8725     { "lgreen",       10, CM_INV },
8726     { "lgray",         7, CM_INV },
8727     { "lightblue",     9, 0 },
8728     { "lightcyan",    11, 0 },
8729     { "lightgreen",   10, 0 },
8730     { "lightgray",     7, 0 },
8731     { "lightmagenta", 13, 0 },
8732     { "lightred",     12, 0 },
8733     { "lmagenta",     13, CM_INV },
8734     { "lred",         12, CM_INV },
8735     { "magenta",       5, 0 },
8736     { "red",           4, 0 },
8737     { "white",        15, 0 },
8738     { "yellow",       14, 0 },
8739 
8740 };
8741 int nrgb = (sizeof(rgbtab) / sizeof(struct keytab));
8742 
8743 VOID
8744 shogui() {
8745     extern gui_dialog;
8746     extern HWND getHwndKUI();
8747     unsigned char cmdsav = colorcmd;
8748     int i, red, green, blue, lines=0;
8749     char * s;
8750 
8751 
8752     printf("GUI paramters:\n");
8753     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8754     printf("  Dialogs:     %s\n",showoff(gui_dialog));
8755     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8756     printf("  Position:    %d,%d\n",get_gui_window_pos_x(),
8757             get_gui_window_pos_y());
8758     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8759     printf("  Resolution:  %d x %d\n",GetSystemMetrics(SM_CXSCREEN),
8760             GetSystemMetrics(SM_CYSCREEN));
8761     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8762     printf("  Run-mode:    %s\n",IsIconic(getHwndKUI()) ? "minimized" :
8763             IsZoomed(getHwndKUI()) ? "maximized" : "restored");
8764     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8765     switch ( get_gui_resize_mode() ) {
8766       case GUIWR_NON:
8767         s = "none";
8768         break;
8769       case GUIWR_FON:
8770         s = "scales font";
8771         break;
8772       case GUIWR_DIM:
8773         s= "changes dimensions";
8774         break;
8775     }
8776     printf("  Resize-mode: %s\n",s);
8777     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8778     printf("\n");
8779     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8780 
8781     printf("RGB Color Table:\n");
8782     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8783     printf("  Color              Red Green Blue\n");
8784     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8785     printf("  ------------------------------------------\n");
8786     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8787     for (i = 0; i < nrgb; i++) {
8788         if (!rgbtab[i].flgs) {
8789             blue = (RGBTable[rgbtab[i].kwval] & 0x00FF0000)>>16;
8790             green = (RGBTable[rgbtab[i].kwval] & 0x0000FF00)>>8;
8791             red = (RGBTable[rgbtab[i].kwval] & 0x000000FF);
8792             printf("  %-18s %3d  %3d  %3d  ",rgbtab[i].kwd,red,green,blue);
8793             colorcmd = rgbtab[i].kwval << 4;
8794             printf("********");
8795             colorcmd = cmdsav;
8796             printf("\n");
8797             if (++lines > cmd_rows - 3) {
8798 		if (!askmore())
8799 		  return;
8800 		else
8801 		  lines = 0;
8802 	    }
8803         }
8804     }
8805     printf("\n");
8806 }
8807 
8808 int
8809 setrgb() {
8810     int cx, red = 0, blue = 0, green = 0, z, x;
8811 
8812     if ((cx = cmkey(rgbtab,nrgb,"","",xxstring)) < 0)
8813       return(cx);
8814     if ((z = cmnum("Red value, 0-255","",10,&red,xxstring)) < 0)
8815       return(z);
8816     if ((z = cmnum("Green value, 0-255","",10,&green,xxstring)) < 0)
8817       return(z);
8818     if ((z = cmnum("Blue value, 0-255","",10,&blue,xxstring)) < 0)
8819       return(z);
8820     if ((x = cmcfm()) < 0) return(x);
8821     if (cx > 15 || red > 255 || blue > 255 || green > 255)
8822       return(-2);
8823     RGBTable[cx] = (unsigned)(((unsigned)blue << 16) |
8824         (unsigned)((unsigned)green << 8) |
8825         (unsigned)red);
8826     return(success = 1);
8827 }
8828 
8829 /*
8830   Set GUI window position: XY coordinates of upper left corner,
8831   expressed as pixel numbers in the current screen resolution.
8832   (0,0) means put ourselves in the upper left corner.
8833   Can we check for out of bounds?
8834 */
8835 
8836 int
8837 setguiwin() {
8838     int cx, x, y, z;
8839     if ((cx = cmkey(guiwtab,nguiwtab,"","",xxstring)) < 0)
8840       return(cx);
8841     switch (cx) {
8842       case GUIW_POS:
8843         if ((z = cmnum("X coordinate (pixel number)","",10,&x,xxstring)) < 0)
8844           return(z);
8845         if ((z = cmnum("Y coordinate (pixel number)","",10,&y,xxstring)) < 0)
8846           return(z);
8847         if ((z = cmcfm()) < 0)
8848           return(z);
8849         if (x < 0 || y < 0) {
8850             printf("?Coordinates must be 0 or greater\n");
8851             return(-9);
8852         }
8853         gui_position(x,y);
8854         return(success = 1);
8855       case GUIW_RES:
8856         if ((x = cmkey(guiwrtab,nguiwrtab,"","",xxstring)) < 0)
8857           return(x);
8858         if ((z = cmcfm()) < 0)
8859           return(z);
8860         gui_resize_mode(x);
8861         return(success = 1);
8862       case GUIW_RUN:
8863 	if ((x = cmkey(guiwntab,nguiwntab,"","",xxstring)) < 0)
8864 	  return(x);
8865 	if ((z = cmcfm()) < 0)
8866 	  return(z);
8867 	gui_win_run_mode(x);
8868 	return(success = 1);
8869       default:
8870         return(-2);
8871     }
8872 }
8873 
8874 int
8875 setguifont() {				/* Assumes that CKFLOAT is defined! */
8876 
8877     extern struct keytab * term_font;
8878     extern struct keytab * _term_font;
8879     extern int tt_font, tt_font_size, ntermfont;
8880     int x, y, z;
8881     char *s;
8882 
8883     if (ntermfont == 0)
8884       BuildFontTable(&term_font, &_term_font, &ntermfont);
8885     if (!(term_font && _term_font && ntermfont > 0)) {
8886         printf("?Internal error: Failure to enumerate fonts\n");
8887         return(-9);
8888     }
8889     if ((x = cmkey(_term_font,ntermfont,"","",xxstring)) < 0)
8890       return(x);
8891     if ((z = cmfld("Height of font in points","12",&s,xxstring)) < 0)
8892       return(z);
8893     if (isfloat(s,0) < 1) {		/* (sets floatval) */
8894 	printf("?Integer or floating-point number required\n");
8895 	return(-9);
8896     }
8897     if (floatval < 0.5) {
8898 	printf("?Positive number required\n");
8899 	return(-9);
8900     }
8901     if ((z = cmcfm()) < 0)
8902       return(z);
8903     tt_font = x;			/* Font index */
8904     tt_font_size = (int)(floatval * 2);	/* Font size in half points */
8905     KuiSetProperty(KUI_TERM_FONT, (long)tt_font, (long)tt_font_size);
8906     return(success = 1);
8907 }
8908 
8909 VOID
8910 setguidialog(x) int x;
8911 {
8912     extern int gui_dialog;
8913     gui_dialog = x;
8914     KuiSetProperty(KUI_GUI_DIALOGS, (long)x, 0L);
8915 }
8916 
8917 VOID
8918 setguimenubar(x) int x;
8919 {
8920     KuiSetProperty(KUI_GUI_MENUBAR, (long)x, 0L);
8921 }
8922 
8923 VOID
8924 setguitoolbar(x) int x;
8925 {
8926     KuiSetProperty(KUI_GUI_TOOLBAR, (long)x, 0L);
8927 }
8928 
8929 VOID
8930 setguiclose(x) int x;
8931 {
8932     KuiSetProperty(KUI_GUI_CLOSE, (long)x, 0L);
8933 }
8934 
8935 int
8936 setgui() {
8937     int cx, x, rc;
8938     if ((cx = cmkey(guitab,nguitab,"","",xxstring)) < 0)
8939       return(cx);
8940     switch (cx) {
8941       case GUI_DIA:
8942         rc = seton(&x);
8943         if (rc >= 0)
8944           setguidialog(x);
8945         return(rc);
8946       case GUI_FON:
8947         return(setguifont());
8948       case GUI_RGB:
8949         return(setrgb());
8950       case GUI_WIN:
8951         return(setguiwin());
8952       case GUI_TLB:
8953         rc = seton(&x);
8954         if (rc >= 0)
8955           setguitoolbar(x);
8956         return(rc);
8957       case GUI_MNB:
8958         rc = seton(&x);
8959         if (rc >= 0)
8960           setguimenubar(x);
8961         return(rc);
8962       case GUI_CLS:
8963         rc = seton(&x);
8964         if (rc >= 0)
8965           setguiclose(x);
8966         return(rc);
8967       default:
8968         return(-2);
8969     }
8970 }
8971 #endif /* KUI */
8972 
8973 VOID
8974 setexitwarn(x) int x;
8975 {
8976     xitwarn = x;
8977 #ifdef KUI
8978     KuiSetProperty(KUI_EXIT_WARNING, (long)x, 0L);
8979 #endif /* KUI */
8980 }
8981 
8982 #ifndef NOLOCAL
8983 VOID
8984 setdebses(x) int x; {
8985 #ifdef OS2
8986     if ((debses != 0) && (x == 0))	/* It was on and we turned it off? */
8987       os2debugoff();			/* Fix OS/2 coloration */
8988 #endif /* OS2 */
8989     debses = x;
8990 #ifdef KUI
8991     KuiSetProperty(KUI_TERM_DEBUG,x,0);
8992 #endif /* KUI */
8993 }
8994 #endif /* NOLOCAL */
8995 
8996 /*  D O P R M  --  Set a parameter.  */
8997 /*
8998  Returns:
8999   -2: illegal input
9000   -1: reparse needed
9001    0: success
9002 */
9003 int
9004 doprm(xx,rmsflg) int xx, rmsflg; {
9005     int i = 0, x = 0, y = 0, z = 0;
9006     long zz = 0L;
9007     char *s = NULL, *p = NULL;
9008 #ifdef OS2
9009     char portbuf[64];
9010     long portspeed = 0L;
9011     int portparity = 0;
9012     int portflow = 0;
9013 #endif /* OS2 */
9014 
9015 #ifndef NOSETKEY
9016 #ifdef OS2
9017     if (xx == XYMSK)
9018       return(setmsk());
9019 #endif /* OS2 */
9020 #endif /* NOSETKEY */
9021 
9022     if (xx == XYFLAG) {                 /* SET FLAG */
9023         extern int ooflag;
9024         return(success = seton(&ooflag));
9025     }
9026     if (xx == XYPRTR                    /* SET PRINTER (or BPRINTER) */
9027 #ifdef BPRINT
9028         || xx == XYBDCP
9029 #endif /* BPRINT */
9030         )
9031       return(setprinter(xx));
9032 
9033     switch (xx) {
9034 
9035 #ifdef ANYX25                           /* SET X25 ... */
9036 case XYX25:
9037         return(setx25());
9038 
9039 #ifndef IBMX25
9040 case XYPAD:                             /* SET PAD ... */
9041         return(setpadp());
9042 #endif /* IBMX25 */
9043 #endif /* ANYX25 */
9044 
9045 #ifndef NOXFER
9046       case XYEOL:       /* These have all been moved to set send/receive... */
9047       case XYLEN:       /* Let the user know what to do. */
9048       case XYMARK:
9049       case XYNPAD:
9050       case XYPADC:
9051       case XYTIMO:
9052         printf("...Use SET SEND or SET RECEIVE instead.\n");
9053         printf("Type HELP SET SEND or HELP SET RECEIVE for more info.\n");
9054         return(success = 0);
9055 
9056       case XYATTR:                      /* File Attribute packets */
9057         return(setat(rmsflg));
9058 
9059       case XYIFD:                       /* Incomplete file disposition */
9060         if ((y = cmkey(ifdatab,3,"","auto",xxstring)) < 0) return(y);
9061         if ((x = cmcfm()) < 0) return(x);
9062         if (rmsflg) {
9063             sstate = setgen('S',
9064                             "310",
9065                             y == 0 ? "0" : (y == 1 ? "1" : "2"),
9066                             ""
9067                             );
9068             return((int) sstate);
9069         } else {
9070             keep = y;
9071             return(success = 1);
9072         }
9073 #endif /* NOXFER */
9074 
9075       case XYMATCH:			/* [ REMOTE ] SET MATCH...  */
9076 #ifndef NOXFER
9077 	if ((z = cmkey(matchtab,nmatchtab,"","",xxstring)) < 0)
9078 	  return(z);
9079 	if (rmsflg) {
9080             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
9081 	    if ((x = cmcfm()) < 0) return(x);
9082 	    switch (z) {
9083 	      case MCH_DOTF:
9084 		return(sstate = setgen('S',"330", y == 0 ? "0" : "1", ""));
9085 	      case MCH_FIFO:
9086 		return(sstate = setgen('S',"331", y == 0 ? "0" : "1", ""));
9087 	      default:
9088 		return(-2);
9089 	      }
9090 	  }
9091 #endif /* NOXFER */
9092 	  switch (z) {
9093 	    case MCH_FIFO:
9094 	      return(success = seton(&matchfifo));
9095 	    case MCH_DOTF:
9096 	      x = seton(&matchdot);
9097 	      if (x < 0) return(x);
9098 	      dir_dots = -1;
9099 	      return(success = x);
9100 	    default:
9101 	      return(-2);
9102 	  }
9103 
9104 #ifndef NOSPL
9105       case XYINPU:                      /* SET INPUT */
9106         return(setinp());
9107 #endif /* NOSPL */
9108 
9109 #ifdef NETCONN
9110       case XYNET: {                     /* SET NETWORK */
9111 
9112           struct FDB k1, k2;
9113 
9114           cmfdbi(&k1,_CMKEY,"","","",nnetkey, 0, xxstring, netkey, &k2);
9115           cmfdbi(&k2,_CMKEY,"","","",nnets,   0, xxstring, netcmd, NULL);
9116 
9117 #ifdef OS2     /* Hide network-type keywords for networks not installed */
9118           for (z = 0; z < nnets; z++) {
9119               if (netcmd[z].kwval == NET_TCPB && tcp_avail == 0)
9120                 netcmd[z].flgs =  CM_INV;
9121 #ifdef SSHBUILTIN
9122               if (netcmd[z].kwval == NET_SSH &&
9123                    !ck_ssleay_is_installed())
9124                 netcmd[z].flgs =  CM_INV;
9125 #endif /* SSHBUILTIN */
9126 #ifdef DECNET
9127               else if (netcmd[z].kwval == NET_DEC  && dnet_avail == 0)
9128                 netcmd[z].flgs =  CM_INV;
9129 #endif /* DECNET */
9130 #ifdef CK_NETBIOS
9131               else if (netcmd[z].kwval == NET_BIOS && netbiosAvail == 0)
9132                 netcmd[z].flgs =  CM_INV;
9133 #endif /* CK_NETBIOS */
9134 #ifdef SUPERLAT
9135               else if (netcmd[z].kwval == NET_SLAT  && slat_avail == 0)
9136                 netcmd[z].flgs =  CM_INV;
9137 #endif /* SUPERLAT */
9138           }
9139           if (tcp_avail)                /* Default network type */
9140             ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
9141 #ifdef SSHBUILTIN
9142           else if ( ck_ssleay_is_installed() )
9143             ckstrncpy(tmpbuf,"ssh",TMPBUFSIZ);
9144 #endif /* SSHBUILTIN */
9145 #ifdef DECNET
9146           else if (dnet_avail)
9147             ckstrncpy(tmpbuf,"decnet",TMPBUFSIZ);
9148 #endif /* DECNET */
9149 #ifdef SUPERLAT
9150           else if (slat_avail)
9151             ckstrncpy(tmpbuf,"superlat",TMPBUFSIZ);
9152 #endif /* SUPERLAT */
9153 #ifdef CK_NETBIOS
9154           else if (netbiosAvail)
9155             ckstrncpy(tmpbuf,"netbios",TMPBUFSIZ);
9156 #endif /* CK_NETBIOS */
9157           else ckstrncpy(tmpbuf,"named-pipe",TMPBUFSIZ);
9158 #else  /* OS2 */
9159 #ifdef TCPSOCKET
9160           ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
9161 #else
9162 #ifdef ANYX25
9163           ckstrncpy(tmpbuf,"x.25",TMPBUFSIZ);
9164 #else
9165           ckstrncpy(tmpbuf,"",TMPBUFSIZ);
9166 #endif /* ANYX25 */
9167 #endif /* TCPSOCKET */
9168 #endif /* OS2 */
9169 
9170           x = cmfdb(&k1);
9171           if (x < 0) {                  /* Error */
9172               if (x == -2 || x == -9)
9173                 printf("?No keywords match: \"%s\"\n",atmbuf);
9174               return(x);
9175           }
9176           z = cmresult.nresult;         /* Keyword value */
9177           if (cmresult.fdbaddr == &k1) { /* Which table? */
9178 #ifndef NOSPL
9179 #ifndef NODIAL
9180               if (z == XYNET_D)
9181                 return(parsdir(1));
9182 #endif /* NODIAL */
9183 #endif /* NOSPL */
9184               if ((z = cmkey(netcmd,nnets,"",tmpbuf,xxstring)) < 0)
9185                 return(z);
9186           }
9187 
9188 #ifdef NETCMD
9189           if (z == NET_CMD && nopush) {
9190               printf("\n?Sorry, access to external commands is disabled\n");
9191               return(-9);
9192           }
9193 #endif /* NETCMD */
9194 
9195 #ifndef NOPUSH
9196 #ifdef NETPTY
9197           if (z == NET_PTY && nopush) {
9198               printf("\n?Sorry, access to external commands is disabled\n");
9199               return(-9);
9200           }
9201 #endif /* NETPTY */
9202 #endif /* NOPUSH */
9203 
9204 #ifdef OS2
9205           if (z == NET_TCPB && tcp_avail == 0) {
9206               printf(
9207 "\n?Sorry, either TCP/IP is not available on this system or\n\
9208 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
9209               return(-9);
9210 #ifdef SSHBUILTIN
9211           } else if (z == NET_SSH && !ck_ssleay_is_installed()) {
9212             printf("\n?Sorry, SSH is not available on this system.\n") ;
9213             return(-9);
9214 #endif /* SSHBUILTIN */
9215 #ifdef CK_NETBIOS
9216           } else if (z == NET_BIOS && netbiosAvail == 0) {
9217               printf("\n?Sorry, NETBIOS is not available on this system.\n") ;
9218               return(-9);
9219 #endif /* CK_NETBIOS */
9220 #ifdef DECNET
9221           } else if (z == NET_DEC && dnet_avail == 0) {
9222               printf("\n?Sorry, DECnet is not available on this system.\n") ;
9223               return(-9);
9224 #endif /* DECNET */
9225 #ifdef SUPERLAT
9226           } else if (z == NET_SLAT && slat_avail == 0) {
9227               printf("\n?Sorry, SuperLAT is not available on this system.\n") ;
9228               return(-9);
9229 #endif /* SUPERLAT */
9230           }
9231 #endif /* OS2 */
9232 
9233 #ifdef NPIPEORBIOS
9234           if (z == NET_PIPE ||          /* Named pipe -- also get pipename */
9235               z == NET_BIOS) {          /* NETBIOS -- also get local name */
9236               char *defnam;
9237 #ifdef CK_NETBIOS
9238               char tmpnbnam[NETBIOS_NAME_LEN+1];
9239 #endif /* CK_NETBIOS */
9240               /* Construct default name  */
9241               if (z == NET_PIPE) {      /* Named pipe */
9242                   defnam = "kermit";    /* Default name is always "kermit" */
9243               }
9244 #ifdef CK_NETBIOS
9245 	      else {			/* NetBIOS */
9246                   if (NetBiosName[0] != SP) { /* If there is already a name, */
9247                       char *p = NULL;
9248                       int n;            /* use it as the default. */
9249                       ckstrncpy(tmpnbnam,NetBiosName,NETBIOS_NAME_LEN+1);
9250                       /* convert trailing spaces to NULs */
9251                       p = &tmpnbnam[NETBIOS_NAME_LEN-1];
9252                       while (*p == SP) {
9253                           *p = NUL;
9254                           p--;
9255                       }
9256                       defnam = tmpnbnam;
9257                   } else if (*myhost)   /* Otherwise use this PC's host name */
9258                     defnam = (char *) myhost;
9259                   else                  /* Otherwise use "kermit" */
9260                     defnam = "kermit";
9261               }
9262 #endif /* CK_NETBIOS */
9263               if ((y = cmtxt((z == NET_PIPE) ? "name of named-pipe" :
9264                              "local NETBIOS name",
9265                              defnam, &s, xxstring)) < 0)
9266                 return(y);
9267 #ifdef NPIPE
9268               pipename[0] = NUL;
9269 #endif /* NPIPE */
9270               if ((y = (int) strlen(s)) < 1) {
9271                   printf("?You must also specify a %s name\n",
9272                          (z == NET_PIPE) ? "pipe" : "local NETBIOS" );
9273                   return(-9);
9274               }
9275 #ifdef CK_NETBIOS
9276               if (z == NET_BIOS) {
9277                   if (!netbiosAvail) {
9278                       printf("?NETBIOS is not available on this system.\n") ;
9279                       return(-9);
9280                   }
9281                   if (y - NETBIOS_NAME_LEN > 0) {
9282                       printf("?NETBIOS name too long, %ld maximum\n",
9283                              NETBIOS_NAME_LEN);
9284                       return(-9);
9285                   } else if ( !strcmp(s,tmpnbnam) ) {
9286                       nettype = z;      /* Returning to old connection... */
9287                       return(success = 1); /* Done */
9288                   } else if (strcmp("                ",NetBiosName)) {
9289                       printf("?NETBIOS name already assigned to \"%s\"\n",
9290                              NetBiosName);
9291                       return(-9);
9292                   } else {
9293                       NCB ncb;
9294                       APIRET rc;
9295                       ckstrncpy(NetBiosName,s,16);
9296                       for (x = y; x < NETBIOS_NAME_LEN; x++)
9297                         NetBiosName[x] = SP;
9298                       NetBiosName[NETBIOS_NAME_LEN] = NUL;
9299                       printf("Checking \"%s\" as a unique NetBIOS name...\n",
9300                              NetBiosName);
9301                       rc = NCBAddName( NetbeuiAPI,
9302                                       &ncb, NetBiosAdapter, NetBiosName );
9303                       if (rc) {
9304                           printf(
9305                 "?Sorry, \"%s\" is already in use by another NetBIOS node.\n",
9306                                  NetBiosName);
9307                           for (x = 0; x < NETBIOS_NAME_LEN; x++)
9308                             NetBiosName[x] = SP;
9309                           return(-9);
9310                       }
9311                   }
9312               }
9313 #endif /* CK_NETBIOS */
9314 #ifdef NPIPE
9315               if (z == NET_PIPE)
9316                 ckstrncpy(pipename,s,PIPENAML);
9317 #endif /* NPIPE */
9318           } else
9319 #endif /* NPIPEORBIOS */
9320 #ifdef DECNET
9321             if (z == NET_DEC) {
9322                 /* Determine if we are using LAT or CTERM */
9323                 if ((y = cmkey(dnettab,
9324                                ndnet,"DECNET protocol","lat",xxstring)) < 0)
9325                   return(y);
9326                 if ((x = cmcfm()) < 0) return(x);
9327                 ttnproto = y;
9328             } else
9329 #endif /* DECNET */
9330 #ifdef NETDLL
9331               if (z == NET_DLL) {
9332                   /* Find out which DLL they are using */
9333                   char dllname[256]="";
9334                   char * p=NULL;
9335                   if ((x = cmifi("Dynamic load library",
9336                                  "",&p,&y,xxstring)) < 0) {
9337                       if (x == -3) {
9338                           printf("?Name of DLL required\n");
9339                           return(-9);
9340                       }
9341                       return(x);
9342                   }
9343                   ckstrncpy(dllname,p,256);
9344                   if ((x = cmcfm()) < 0) return(x);
9345 
9346                   if (netdll_load(dllname) < 0) /* Try to load the dll */
9347                     return(success = 0);
9348                   else {
9349                       nettype = z;
9350                       return(success = 1);
9351                   }
9352               } else
9353 #endif /* NETDLL */
9354                 if ((x = cmcfm()) < 0) return(x);
9355           nettype = z;
9356           if (
9357 #ifdef DECNET
9358               (nettype != NET_DEC)  &&
9359 #endif /* DECNET */
9360 #ifdef NPIPE
9361               (nettype != NET_PIPE) &&
9362 #endif /* NPIPE */
9363 #ifdef CK_NETBIOS
9364               (nettype != NET_BIOS) &&
9365 #endif /* CK_NETBIOS */
9366 #ifdef NETFILE
9367               (nettype != NET_FILE) &&
9368 #endif /* NETFILE */
9369 #ifdef NETCMD
9370               (nettype != NET_CMD) &&
9371 #endif /* NETCMD */
9372 #ifdef NETPTY
9373               (nettype != NET_PTY) &&
9374 #endif /* NETPTY */
9375 #ifdef NETDLL
9376               (nettype != NET_DLL) &&
9377 #endif /* NETDLL */
9378 #ifdef SUPERLAT
9379               (nettype != NET_SLAT) &&
9380 #endif /* SUPERLAT */
9381               (nettype != NET_SX25) &&
9382               (nettype != NET_VX25) &&
9383 #ifdef IBMX25
9384               (nettype != NET_IX25) &&
9385 #endif /* IBMX25 */
9386 #ifdef SSHBUILTIN
9387               (nettype != NET_SSH) &&
9388 #endif /* SSHBUILTIN */
9389               (nettype != NET_TCPB)) {
9390               printf("?Network type not supported\n");
9391               return(success = 0);
9392           } else {
9393               return(success = 1);
9394           }
9395       }
9396 
9397 #ifndef NOTCPOPTS
9398 #ifdef TCPSOCKET
9399       case XYTCP: {
9400         extern int ttyfd;
9401 
9402         if ((z = cmkey(tcpopt,ntcpopt,"TCP option","nodelay",xxstring)) < 0)
9403           return(z);
9404 
9405         switch (z) {
9406 #ifndef NOHTTP
9407           case XYTCP_HTTP_PROXY: {
9408 	      struct FDB sw, tx;
9409 	      int n, x;
9410 	      char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1], abuf[256];
9411 	      ubuf[0] = pbuf[0] = abuf[0] = 0;
9412 
9413 	      cmfdbi(&sw,		/* First FDB - switches */
9414 		     _CMKEY,		/* fcode */
9415 		     "HTTP proxy server host[:port] or switch",
9416 		     "",		/* default */
9417 		     "",		/* addtl string data */
9418 		     nuserpass,		/* addtl numeric data 1: tbl size */
9419 		     4,			/* addtl numeric data 2: 4 = cmswi */
9420 		     xxstring,		/* Processing function */
9421 		     userpass,		/* Keyword table */
9422 		     &tx		/* Pointer to next FDB */
9423 		     );
9424 	      cmfdbi(&tx,
9425 		     _CMTXT,		/* fcode */
9426 		     "HTTP proxy server host[:port]",
9427 		     "",		/* default */
9428 		     "",		/* addtl string data */
9429 		     0,			/* addtl numeric data 1 */
9430 		     0,			/* addtl numeric data 2 */
9431 		     xxstring,
9432 		     NULL,
9433 		     NULL
9434 		     );
9435 	      while (1) {
9436 		  if ((x = cmfdb(&sw)) < 0) {
9437 		      if (x == -3) {
9438 			  x = -9;
9439 			  printf("?Hostname required\n");
9440 		      }
9441 		      return(x);
9442 		  }
9443 		  if (cmresult.fcode != _CMKEY)
9444 		    break;
9445 		  n = cmresult.nresult;
9446 		  switch (n) {
9447 		    case UPW_USER:
9448 		    case UPW_PASS:
9449 		    case UPW_AGENT:
9450 		      if ((x = cmfld((n == UPW_USER) ?
9451 				     "Username" :
9452 				     ((n == UPW_PASS) ? "Password" : "Agent"),
9453 				     "", &s, xxstring)) < 0) {
9454 			  if (x != -3)
9455 			    return(x);
9456 		      }
9457 		      ckstrncpy((n == UPW_USER) ? ubuf :
9458                         ((n == UPW_PASS) ? pbuf : abuf), s,
9459                         (n == UPW_AGENT) ? 256 : (LOGINLEN+1));
9460 		  }
9461 	      }
9462 	      if (cmresult.fcode != _CMTXT)
9463 		return(-2);
9464 	      s = cmresult.sresult;
9465 	      if (s) if (!*s) s = NULL;
9466 
9467 #ifdef IKSDCONF
9468 	      if (iksdcf)
9469 		return(success = 0);
9470 #endif /* IKSDCONF */
9471 	      makestr(&tcp_http_proxy_user,ubuf[0]?ubuf:NULL);
9472 	      makestr(&tcp_http_proxy_pwd,pbuf[0]?pbuf:NULL);
9473 	      makestr(&tcp_http_proxy_agent,abuf[0]?abuf:NULL);
9474 	      makestr(&tcp_http_proxy,s);
9475 	      memset(pbuf,0,sizeof(pbuf));
9476 	      return(success = 1);
9477 	  }
9478 #endif /* NOHTTP */
9479 /*
9480   It would have been easy to combine XYTCP_SOCKS_SVR with the previous
9481   one except for the #ifdefs...
9482 */
9483 #ifdef NT
9484 #ifdef CK_SOCKS
9485           case XYTCP_SOCKS_SVR: {
9486 	      char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1];
9487 	      char * p = getenv("SOCKS_SERVER");
9488 	      struct FDB sw, tx;
9489 	      int n, x;
9490 
9491 	      if (!p) p = "";
9492 
9493 	      cmfdbi(&sw,		/* First FDB - switches */
9494 		     _CMKEY,		/* fcode */
9495 		     "SOCKS server host[:port] or switch",
9496 		     "",		/* default */
9497 		     "",		/* addtl string data */
9498 		     nuserpass,		/* addtl numeric data 1: tbl size */
9499 		     4,			/* addtl numeric data 2: 4 = cmswi */
9500 		     xxstring,		/* Processing function */
9501 		     userpass,		/* Keyword table */
9502 		     &tx		/* Pointer to next FDB */
9503 		     );
9504 	      cmfdbi(&tx,
9505 		     _CMTXT,		/* fcode */
9506 		     "SOCKS server host[:port]",
9507 		     p,			/* default */
9508 		     "",		/* addtl string data */
9509 		     0,			/* addtl numeric data 1 */
9510 		     0,			/* addtl numeric data 2 */
9511 		     xxstring,
9512 		     NULL,
9513 		     NULL
9514 		     );
9515 	      while (1) {
9516 		  if ((x = cmfdb(&sw)) < 0) {
9517 		      if (x == -3) {
9518 			  x = -9;
9519 			  printf("?Hostname required\n");
9520 		      }
9521 		      return(x);
9522 		  }
9523 		  if (cmresult.fcode != _CMKEY)
9524 		    break;
9525 		  n = cmresult.nresult;
9526 		  switch (n) {
9527 		    case UPW_USER:
9528 		    case UPW_PASS:
9529 		      if ((x = cmfld((n == UPW_USER) ? "Username" : "Password",
9530 				     "", &s, xxstring)) < 0) {
9531 			  if (x != -3)
9532 			    return(x);
9533 		      }
9534 		      ckstrncpy((n == UPW_USER) ? ubuf : pbuf, s, LOGINLEN+1);
9535 		  }
9536 	      }
9537 	      if (cmresult.fcode != _CMTXT)
9538 		return(-2);
9539 	      s = cmresult.sresult;
9540 	      if (s) if (!*s) s = NULL;
9541 
9542 #ifdef IKSDCONF
9543 	      if (iksdcf)
9544 		return(success = 0);
9545 #endif /* IKSDCONF */
9546 	      makestr(&tcp_socks_user,ubuf);
9547               memset(pbuf,0,sizeof(pbuf));
9548 	      makestr(&tcp_socks_svr,s);
9549 	      return(success = 1);
9550 	  }
9551 
9552 #ifdef CK_SOCKS_NS
9553           case XYTCP_SOCKS_NS: {
9554             char * p = getenv("SOCKS_NS");
9555             if (!p) p = "";
9556             if ((y = cmtxt("hostname or IP of SOCKS Name Server",p,
9557                             &s,xxstring)) < 0)
9558                 return(y);
9559 #ifdef IKSDCONF
9560               if (iksdcf) return(success = 0);
9561 #endif /* IKSDCONF */
9562               if (tcp_socks_ns) {
9563                   free(tcp_socks_ns);   /* Free any previous storage */
9564                   tcp_socks_ns = NULL;
9565               }
9566               if (s == NULL || *s == NUL) { /* If none given */
9567                   tcp_socks_ns = NULL;  /* remove the override string */
9568                   return(success = 1);
9569               } else if ((tcp_socks_ns = malloc(strlen(s)+1))) {
9570                   strcpy(tcp_socks_ns,s);
9571                   return(success = 1);
9572               } else
9573                 return(success = 0);
9574           }
9575 #endif /* CK_SOCKS_NS */
9576 #endif /* CK_SOCKS */
9577 #endif /* NT */
9578           case XYTCP_ADDRESS:
9579             if ((y = cmtxt("preferred IP Address for TCP connections","",
9580                            &s,xxstring)) < 0)
9581               return(y);
9582 #ifdef IKSDCONF
9583             if (iksdcf) return(success = 0);
9584 #endif /* IKSDCONF */
9585             if (tcp_address) {
9586                 free(tcp_address);      /* Free any previous storage */
9587                 tcp_address = NULL;
9588             }
9589             if (s == NULL || *s == NUL) { /* If none given */
9590                 tcp_address = NULL;     /* remove the override string */
9591                 return(success = 1);
9592             } else if ((tcp_address = malloc(strlen(s)+1))) {
9593                 strcpy(tcp_address,s);
9594                 return(success = 1);
9595             } else
9596               return(success = 0);
9597 #ifdef SO_KEEPALIVE
9598           case XYTCP_KEEPALIVE:
9599             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9600             if ((y = cmcfm()) < 0) return(y);
9601 #ifdef IKSDCONF
9602             if (iksdcf) return(success = 0);
9603 #endif /* IKSDCONF */
9604 #ifdef SSHBUILTIN
9605             if (network && nettype == NET_SSH && ssh_sock != -1)
9606               success = keepalive(ssh_sock,z);
9607             else
9608 #endif /* SSHBUILTIN */
9609 	      success = keepalive(ttyfd,z);
9610             return(success);
9611 #endif /* SO_KEEPALIVE */
9612 #ifdef SO_DONTROUTE
9613           case XYTCP_DONTROUTE:
9614             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
9615             if ((y = cmcfm()) < 0) return(y);
9616 #ifdef IKSDCONF
9617             if (iksdcf) return(success = 0);
9618 #endif /* IKSDCONF */
9619 #ifdef SSHBUILTIN
9620             if (network && nettype == NET_SSH && ssh_sock != -1)
9621               success = dontroute(ssh_sock,z);
9622             else
9623 #endif /* SSHBUILTIN */
9624 	      success = dontroute(ttyfd,z);
9625             return(success);
9626 #endif /* SO_DONTROUTE */
9627 #ifdef TCP_NODELAY
9628           case XYTCP_NODELAY:
9629             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
9630             if ((y = cmcfm()) < 0) return(y);
9631 #ifdef IKSDCONF
9632             if (iksdcf) return(success = 0);
9633 #endif /* IKSDCONF */
9634 #ifdef SSHBUILTIN
9635             if (network && nettype == NET_SSH && ssh_sock != -1)
9636               success = no_delay(ssh_sock,z);
9637             else
9638 #endif /* SSHBUILTIN */
9639 	      success = no_delay(ttyfd,z);
9640             return(success);
9641           case XYTCP_NAGLE:             /* The inverse of NODELAY */
9642             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9643             if ((y = cmcfm()) < 0) return(y);
9644 #ifdef IKSDCONF
9645             if (iksdcf) return(success = 0);
9646 #endif /* IKSDCONF */
9647 #ifdef SSHBUILTIN
9648             if (network && nettype == NET_SSH && ssh_sock != -1)
9649               success = no_delay(ssh_sock,z);
9650             else
9651 #endif /* SSHBUILTIN */
9652 	      success = no_delay(ttyfd,!z);
9653             return(success);
9654 #endif /* TCP_NODELAY */
9655 #ifdef SO_LINGER
9656           case XYTCP_LINGER:
9657             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0)
9658               return(z);
9659             if (z) {                    /* if on, we need a timeout value */
9660                 if ((x = cmnum("Linger timeout in 10th of a millisecond",
9661                                "0",10,&y,xxstring)) < 0)
9662                   return(x);
9663             } else
9664               y = 0;
9665             if ((x = cmcfm()) < 0)
9666               return(x);
9667 #ifdef IKSDCONF
9668             if (iksdcf) return(success = 0);
9669 #endif /* IKSDCONF */
9670 #ifdef SSHBUILTIN
9671             if (network && nettype == NET_SSH && ssh_sock != -1)
9672               success = ck_linger(ssh_sock,z,y);
9673             else
9674 #endif /* SSHBUILTIN */
9675 	      success = ck_linger(ttyfd,z,y);
9676             return(success);
9677 #endif /* SO_LINGER */
9678 #ifdef SO_SNDBUF
9679           case XYTCP_SENDBUF:
9680             x = cmnum("Send buffer size, bytes","8192",10,&z,xxstring);
9681             if (x < 0) return(x);
9682             if ((x = cmcfm()) < 0) return(x);
9683 #ifdef IKSDCONF
9684             if (iksdcf) return(success = 0);
9685 #endif /* IKSDCONF */
9686 #ifdef SSHBUILTIN
9687             if (network && nettype == NET_SSH && ssh_sock != -1)
9688               success = sendbuf(ssh_sock,z);
9689             else
9690 #endif /* SSHBUILTIN */
9691 	      success = sendbuf(ttyfd,z);
9692             return(success);
9693 #endif /* SO_SNDBUF */
9694 #ifdef SO_RCVBUF
9695           case XYTCP_RECVBUF:
9696             x = cmnum("Receive buffer size, bytes","8192",10,&z,xxstring);
9697             if (x < 0) return(x);
9698             if ((x = cmcfm()) < 0) return(x);
9699 #ifdef IKSDCONF
9700             if (iksdcf) return(success = 0);
9701 #endif /* IKSDCONF */
9702 
9703 /* Note: The following is not 16-bit safe */
9704 
9705 #ifndef QNX16
9706             if (x > 52248) {
9707                 printf("?Warning: receive buffers larger than 52248 bytes\n");
9708                 printf(" may not be understood by all hosts.  Performance\n");
9709                 printf(" may suffer.\n");
9710                 return(-9);
9711             }
9712 #endif /* QNX16 */
9713 #ifdef SSHBUILTIN
9714             if (network && nettype == NET_SSH && ssh_sock != -1)
9715               success = recvbuf(ssh_sock,z);
9716             else
9717 #endif /* SSHBUILTIN */
9718 	      success = recvbuf(ttyfd,z);
9719             return(success);
9720 #endif /* SO_RCVBUF */
9721 
9722 #ifdef VMS
9723 #ifdef DEC_TCPIP
9724           case XYTCP_UCX: {             /* UCX 2.0 port swabbing bug */
9725               extern int ucx_port_bug;
9726               return(success = seton(&ucx_port_bug));
9727           }
9728 #endif /* DEC_TCPIP */
9729 #endif /* VMS */
9730 
9731           case XYTCP_RDNS: {
9732               extern int tcp_rdns;
9733               return(success = setonaut(&tcp_rdns));
9734           }
9735 
9736 #ifdef CK_DNS_SRV
9737           case XYTCP_DNS_SRV: {
9738               extern int tcp_dns_srv;
9739               return(success = seton(&tcp_dns_srv));
9740           }
9741 #endif /* CK_DNS_SRV */
9742 
9743           default:
9744             return(0);
9745         }
9746       }
9747 #endif /* TCPSOCKET */
9748 #endif /* NOTCPOPTS */
9749 #endif /* NETCONN */
9750     }
9751 
9752     switch (xx) {
9753 
9754 #ifndef NOLOCAL
9755 #ifdef NETCONN
9756       case XYHOST: {                    /* SET HOST */
9757           z = ttnproto;                 /* Save protocol in case of failure */
9758 #ifdef DECNET
9759           if (nettype != NET_DEC)
9760 #endif /* DECNET */
9761             ttnproto = NP_NONE;
9762           if ((y = setlin(XYHOST,1,0)) <= 0) { /* Sets success to 1 */
9763               debug(F101,"SET HOST fail mdmtyp","",mdmtyp);
9764               ttnproto = z;             /* Failed, restore protocol */
9765               success = 0;
9766           }
9767           didsetlin++;
9768           debug(F101,"SET HOST OK mdmtyp","",mdmtyp);
9769           debug(F101,"SET HOST reliable","",reliable);
9770           return(y);
9771       }
9772 #endif /* NETCONN */
9773 
9774       case XYLINE:                      /* SET LINE (= SET PORT) */
9775         debug(F101,"setlin flow 1","",flow);
9776         x = setlin(xx,1,0);
9777         if (x > -1) didsetlin++;
9778         debug(F101,"SET LINE setlin","",x);
9779         debug(F101,"SET LINE flow","",flow);
9780         debug(F101,"SET LINE local","",local);
9781         debug(F101,"SET LINE reliable","",reliable);
9782         return(x);
9783 #endif /* NOLOCAL */
9784 
9785 #ifndef NOSETKEY
9786       case XYKEY:                       /* SET KEY */
9787         return(dosetkey());
9788 #endif /* NOSETKEY */
9789 
9790 #ifndef NOCSETS
9791       case XYLANG:                      /* Language */
9792         if ((y = cmkey(lngtab,nlng,"","none",xxstring)) < 0)
9793           return(y);
9794         if ((x = cmcfm()) < 0) return(x);
9795 
9796         /* Look up language and get associated character sets */
9797         for (i = 0; (i < nlangs) && (langs[i].id != y); i++) ;
9798         if (i >= nlangs) {
9799             printf("?internal error, sorry\n");
9800             return(success = 0);
9801         } /*  */
9802         language = i;                   /* All good, set the language, */
9803         return(success = 1);
9804 #endif /* NOCSETS */
9805 
9806 #ifndef MAC
9807       case XYBACK:                      /* BACKGROUND */
9808         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
9809         if ((y = cmcfm()) < 0) return(y);
9810 #ifdef COMMENT
9811         bgset = z;                      /* 0 = off (foreground) */
9812 #ifdef VMS                              /* 1 = on (background) */
9813         if (batch && bgset == 0)        /* To enable echoing of commands */
9814           ckxech = 1;                   /* in VMS batch logs */
9815 #endif /* VMS */
9816 #else  /* COMMENT */
9817         if (z) {                        /* 1 = Background */
9818             bgset = 1;
9819             backgrd = 1;
9820 #ifdef VMS
9821             batch = 1;
9822 #endif /* VMS */
9823         } else {                        /* 0 = Foreground */
9824             bgset = 0;
9825             backgrd = 0;
9826 #ifdef VMS
9827             batch = 0;
9828 #endif /* VMS */
9829         }
9830 #endif /* COMMENT */
9831         success = 1;
9832         bgchk();
9833         return(success);
9834 #endif /* MAC */
9835 
9836       case XYQUIE: {                    /* QUIET */
9837 #ifdef DCMDBUF
9838           extern int * xquiet;
9839 #else
9840           extern int xquiet[];
9841 #endif /* DCMDBUF */
9842           x = seton(&quiet);
9843           if (x < 0) return(x);
9844           xquiet[cmdlvl] = quiet;
9845           return(success = x);
9846       }
9847 
9848 #ifndef NOXFER
9849       case XYBUF: {                     /* BUFFERS */
9850 #ifdef DYNAMIC
9851           int sb, rb;
9852           if ((y = cmnum("Send buffer size","",10,&sb,xxstring)) < 0) {
9853               if (y == -3) printf("?Buffer size required\n");
9854               return(y);
9855           }
9856           if (sb < 0) {
9857               if (*atmbuf == '-')
9858                 printf("?Negative numbers can't be used here\n");
9859               else printf("?Integer overflow, use a smaller number please\n");
9860               return(-9);
9861           } else if (sb < 80) {
9862               printf("?Too small\n");
9863               return(-9);
9864           }
9865           if ((y=cmnum("Receive buffer size",ckitoa(sb),10,&rb,xxstring)) < 0)
9866             return(y);
9867           if (rb < 0) {
9868               if (*atmbuf == '-')
9869                 printf("?Negative numbers can't be used here\n");
9870               else printf("?Integer overflow, use a smaller number please\n");
9871               return(-9);
9872           } else if (rb < 80) {
9873               printf("?Too small\n");
9874               return(-9);
9875           }
9876           if ((y = cmcfm()) < 0) return(y);
9877           if ((y = inibufs(sb,rb)) < 0) return(y);
9878           y = adjpkl(urpsiz,wslotr,bigrbsiz); /* Maybe adjust packet sizes */
9879           if (y != urpsiz) urpsiz = y;
9880           y = adjpkl(spsiz,wslotr,bigsbsiz);
9881           if (y != spsiz) spsiz = spmax = spsizr = y;
9882           return(success = 1);
9883 #else
9884           printf("?Sorry, not available\n");
9885           return(success = 0);
9886 #endif /* DYNAMIC */
9887       }
9888 
9889       case XYCHKT:                      /* BLOCK-CHECK */
9890         if ((x = cmkey(chktab,nchkt,"","3",xxstring)) < 0) return(x);
9891         if ((y = cmcfm()) < 0) return(y);
9892 	if (x == 5) {
9893 	    bctf = 1;
9894 #ifdef COMMENT
9895 	    printf("?5 - Not implemented yet\n");
9896 	    return(success = 0);
9897 #endif	/* COMMENT */
9898 	}
9899         bctr = x;                       /* Set local too even if REMOTE SET */
9900 
9901         if (rmsflg) {
9902             if (x == 4) {
9903                 tmpbuf[0] = 'B';
9904                 tmpbuf[1] = '\0';
9905             } else
9906               ckstrncpy(tmpbuf,ckitoa(x),TMPBUFSIZ);
9907             sstate = setgen('S', "400", tmpbuf, "");
9908             return((int) sstate);
9909         } else {
9910             return(success = 1);
9911         }
9912 #endif /* NOXFER */
9913 
9914 #ifndef NOLOCAL
9915 #ifndef MAC                             /* The Mac has no RS-232 */
9916 case XYCARR:                            /* CARRIER-WATCH */
9917         return(setdcd());
9918 #endif /* MAC */
9919 #endif /* NOLOCAL */
9920     }
9921 
9922 #ifdef TNCODE
9923     switch (xx) {                       /* Avoid long switch statements... */
9924       case XYTELOP: {
9925           int c, n;                     /* Workers */
9926           int getval = 0;               /* Whether to get switch value */
9927           int tnserver = 0;             /* Client by default */
9928           int opt = -1;                 /* Telnet Option */
9929           struct FDB sw, op;            /* FDBs for each parse function */
9930 #ifdef CK_AUTHENTICATION
9931           extern int sl_topt_a_s_saved;
9932           extern int sl_topt_a_c_saved;
9933           extern int sl_topt_e_s_saved;
9934           extern int sl_topt_e_c_saved;
9935 #endif /* CK_AUTHENTICATION */
9936 #ifdef IKSD
9937           if (inserver)                 /* Server by default when IKSD */
9938             tnserver = 1;
9939 #endif /* IKSD */
9940 
9941           /* Set up chained parse functions... */
9942 
9943           cmfdbi(&op,                   /* First fdb - telopts*/
9944                  _CMKEY,                /* fcode */
9945                  "/client, /server or", /* hlpmsg */
9946                  "",                    /* default */
9947                  "",                    /* addtl string data */
9948                  ntnopt,                /* addtl numeric data 1 */
9949                  0,                     /* addtl numeric data 2 */
9950                  xxstring,
9951                  tnopttab,
9952                  &sw
9953                  );
9954           cmfdbi(&sw,                   /* Second FDB - command switches */
9955                  _CMKEY,                /* fcode */
9956                  "",                    /* hlpmsg */
9957                  "",                    /* default */
9958                  "",                    /* addtl string data */
9959                  ntnoptsw,              /* addtl numeric data 1: tbl size */
9960                  4,                     /* addtl numeric data 2: 4 = cmswi */
9961                  xxstring,              /* Processing function */
9962                  tnoptsw,               /* Keyword table */
9963                  NULL                   /* Pointer to next FDB */
9964                  );
9965 
9966           while (opt < 0) {             /* Parse 0 or more switches */
9967               x = cmfdb(&op);           /* Parse switch or other thing */
9968               debug(F101,"XYTELOP cmfdb","",x);
9969               if (x < 0)                /* Error */
9970                 return(x);              /* or reparse needed */
9971               if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
9972                 break;
9973               c = cmgbrk();             /* Get break character */
9974               getval = (c == ':' || c == '='); /* see how switch ended */
9975               if (getval && !(cmresult.kflags & CM_ARG)) {
9976                   printf("?This switch does not take arguments\n");
9977                   return(-9);
9978               }
9979               z = cmresult.nresult;     /* Numeric result = switch value */
9980               debug(F101,"XYTELOP switch","",z);
9981 
9982               switch (z) {              /* Process the switch */
9983                 case CK_TN_CLIENT:
9984                   tnserver = 0;
9985                   break;
9986                 case CK_TN_SERVER:
9987                   tnserver = 1;
9988                     break;
9989                 case CK_TN_EC:
9990                   opt = TELOPT_ECHO;
9991                   break;
9992                 case CK_TN_TT:
9993                   opt = TELOPT_TTYPE;
9994                   break;
9995                 case CK_TN_BM:
9996                   opt = TELOPT_BINARY;
9997                   break;
9998                 case CK_TN_ENV:
9999                   opt = TELOPT_NEWENVIRON;
10000                   break;
10001                 case CK_TN_LOC:
10002                   opt = TELOPT_SNDLOC;
10003                   break;
10004                 case CK_TN_AU:
10005                   opt = TELOPT_AUTHENTICATION;
10006                   break;
10007                 case CK_TN_FX:
10008                   opt = TELOPT_FORWARD_X;
10009                   break;
10010                 case CK_TN_ENC:
10011                   opt = TELOPT_ENCRYPTION;
10012                   break;
10013                 case CK_TN_IKS:
10014                   opt = TELOPT_KERMIT;
10015                   break;
10016                 case CK_TN_TLS:
10017                   opt = TELOPT_START_TLS;
10018                   break;
10019                 case CK_TN_XD:
10020                   opt = TELOPT_XDISPLOC;
10021                   break;
10022                 case CK_TN_NAWS:
10023                   opt = TELOPT_NAWS;
10024                   break;
10025                 case CK_TN_SGA:
10026                   opt = TELOPT_SGA;
10027                   break;
10028                 case CK_TN_PHR:
10029                   opt = TELOPT_PRAGMA_HEARTBEAT;
10030                   break;
10031                 case CK_TN_PSP:
10032                   opt = TELOPT_SSPI_LOGON;
10033                   break;
10034                 case CK_TN_PLG:
10035                   opt = TELOPT_PRAGMA_LOGON;
10036                   break;
10037                 case CK_TN_SAK:
10038                   opt = TELOPT_IBM_SAK;
10039                   break;
10040                 case CK_TN_CPC:
10041                   opt = TELOPT_COMPORT;
10042                   break;
10043                 case CK_TN_LOG:
10044                   opt = TELOPT_LOGOUT;
10045                   break;
10046                 case CK_TN_FLW:
10047                   opt = TELOPT_LFLOW;
10048                   break;
10049                 default:
10050                   printf("?Unexpected value - %d\n",z);
10051                   return(-9);
10052               }
10053 #ifdef COMMENT
10054               if (cmresult.fdbaddr == &op)
10055                 break;
10056 #endif /* COMMENT */
10057           }
10058           switch (opt) {
10059             case TELOPT_ECHO:           /* Options only the Server WILL */
10060             case TELOPT_FORWARD_X:
10061             case TELOPT_SEND_URL:
10062             case TELOPT_IBM_SAK:
10063             case TELOPT_LOGOUT:
10064               if ((x = cmkey(tnnegtab,
10065                              ntnnegtab,
10066                              "desired server state",
10067    TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
10068                              xxstring)
10069                    ) < 0)
10070                 return(x);
10071               if ((z = cmcfm()) < 0)
10072                   return(z);
10073               if (tnserver) {
10074                   TELOPT_DEF_S_ME_MODE(opt) = x;
10075                   TELOPT_ME_MODE(opt) = x;
10076               } else {
10077                   TELOPT_DEF_C_U_MODE(opt) = x;
10078                   TELOPT_U_MODE(opt) = x;
10079               }
10080               break;
10081 
10082             case TELOPT_TTYPE:          /* Options only the Client WILL */
10083             case TELOPT_NEWENVIRON:
10084             case TELOPT_SNDLOC:
10085             case TELOPT_AUTHENTICATION:
10086             case TELOPT_START_TLS:
10087             case TELOPT_XDISPLOC:
10088             case TELOPT_NAWS:
10089             case TELOPT_LFLOW:
10090             case TELOPT_COMPORT:
10091               if ((x = cmkey(tnnegtab,
10092                              ntnnegtab,
10093                              "desired client state",
10094     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
10095                              xxstring)
10096                    ) < 0)
10097                 return(x);
10098               if ((z = cmcfm()) < 0)
10099                 return(z);
10100               if (tnserver) {
10101                   TELOPT_DEF_S_U_MODE(opt) = x;
10102                   TELOPT_U_MODE(opt) = x;
10103 #ifdef CK_AUTHENTICATION
10104                   if (opt == TELOPT_AUTHENTICATION)
10105                     sl_topt_a_s_saved = 0;
10106 #endif /* CK_AUTHENTICATION */
10107               } else {
10108                   TELOPT_DEF_C_ME_MODE(opt) = x;
10109                   TELOPT_ME_MODE(opt) = x;
10110 #ifdef CK_AUTHENTICATION
10111                   if (opt == TELOPT_AUTHENTICATION)
10112                     sl_topt_a_c_saved = 0;
10113 #endif /* CK_AUTHENTICATION */
10114               }
10115               break;
10116 
10117             default:
10118               if ((x = cmkey(tnnegtab,
10119                              ntnnegtab,
10120                              tnserver ?
10121                              "desired server state" :
10122                              "desired client state",
10123     TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
10124                              xxstring
10125                              )
10126                    ) < 0)
10127                 return(x);
10128               if ((y = cmkey(tnnegtab,
10129                              ntnnegtab,
10130                              !tnserver ? "desired server state" :
10131                              "desired client state",
10132     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
10133                              xxstring
10134                              )
10135                    ) < 0)
10136                 return(y);
10137               if ((z = cmcfm()) < 0)
10138                 return(z);
10139               if (tnserver) {
10140                   TELOPT_DEF_S_ME_MODE(opt) = x;
10141                   TELOPT_ME_MODE(opt) = x;
10142                   TELOPT_DEF_S_U_MODE(opt) = y;
10143                   TELOPT_U_MODE(opt) = y;
10144 #ifdef CK_ENCRYPTION
10145                   if (opt == TELOPT_ENCRYPTION)
10146                     sl_topt_e_s_saved = 0;
10147 #endif /* CK_ENCRYPTION */
10148               } else {
10149                   TELOPT_DEF_C_ME_MODE(opt) = x;
10150                   TELOPT_ME_MODE(opt) = x;
10151                   TELOPT_DEF_C_U_MODE(opt) = y;
10152                   TELOPT_U_MODE(opt) = y;
10153 #ifdef CK_ENCRYPTION
10154                   if (opt == TELOPT_ENCRYPTION)
10155                     sl_topt_e_c_saved = 0;
10156 #endif /* CK_ENCRYPTION */
10157               }
10158           }
10159           return(success = 1);
10160       }
10161 
10162       case XYTEL:                       /* TELNET */
10163         if ((z = cmkey(tntab,ntn,"parameter for TELNET negotiations", "",
10164                        xxstring)) < 0)
10165           return(z);
10166         switch (z) {
10167           case CK_TN_EC:                /* ECHO */
10168             if ((x = cmkey(rltab,nrlt,
10169                            "initial TELNET echoing state",
10170                            "local",xxstring)) < 0)
10171               return(x);
10172             if ((y = cmcfm()) < 0) return(y);
10173             tn_duplex = x;
10174             return(success = 1);
10175 
10176           case CK_TN_RE:                /* REMOTE-ECHO */
10177             return(success = seton(&tn_rem_echo));
10178 
10179           case CK_TN_DB:                /* DEBUG */
10180             return(success = seton(&tn_deb));
10181 
10182           case CK_TN_TT:                /* TERMINAL TYPE */
10183             if ((y = cmtxt("terminal type for TELNET connections","",
10184                            &s,xxstring)) < 0)
10185               return(y);
10186             if (tn_term) {
10187                 free(tn_term);          /* Free any previous storage */
10188                 tn_term = NULL;
10189             }
10190             if (s == NULL || *s == NUL) { /* If none given */
10191                 tn_term = NULL;         /* remove the override string */
10192                 return(success = 1);
10193             } else if ((tn_term = malloc(strlen(s)+1))) {
10194                 strcpy(tn_term,s);
10195                 return(success = 1);
10196             } else return(success = 0);
10197 
10198 #ifdef CK_FORWARD_X
10199           case CK_TN_FX:                /* FORWARD-X */
10200             if ((x=cmkey(tnfwdxtab,ntnfwdx,"","xauthority-file",xxstring)) < 0)
10201               return(x);
10202             switch (x) {
10203               case 0: {                 /* Xauthority-File */
10204                   x = cmifi("Full path of .Xauthority file","",&s,&y,xxstring);
10205                   if (x < 0 && x != -3)
10206                     return(x);
10207                   makestr(&tn_fwdx_xauthority,s);
10208                   return(success = 1);
10209               }
10210               case 1: {                 /* No-Encryption */
10211                   extern int fwdx_no_encrypt;
10212                   return(success = seton(&fwdx_no_encrypt));
10213               }
10214             }
10215             return(success = 0);
10216 #endif /* CK_FORWARD_X */
10217 
10218           case CK_TN_NL:                /* TELNET NEWLINE-MODE */
10219             if ((x = cmkey(tn_nlmtab,ntn_nlm,"","nvt",xxstring)) < 0)
10220               return(x);
10221             if (x == TN_NL_BIN) {
10222               if ((x = cmkey(tnlmtab,ntnlm,"","raw",xxstring)) < 0)
10223                 return(x);
10224               if ((y = cmcfm()) < 0)
10225                 return(y);
10226               tn_b_nlm = x;
10227               return(success = 1);
10228           } else if (x == TN_NL_NVT) {
10229               if ((x = cmkey(tnlmtab,ntnlm,"","on",xxstring)) < 0)
10230                 return(x);
10231               if ((y = cmcfm()) < 0)
10232                 return(y);
10233               tn_nlm = x;
10234               return(success = 1);
10235           } else {
10236               if ((y = cmcfm()) < 0)
10237                 return(y);
10238               tn_nlm = x;
10239               return(success = 1);
10240           }
10241 
10242         case CK_TN_XF:                  /* BINARY-TRANSFER-MODE */
10243             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10244             if ((y = cmcfm()) < 0) return(y);
10245             tn_b_xfer = z;
10246             return(success = 1);
10247 
10248         case CK_TN_NE:                  /* NO-ENCRYPT-DURING-XFER */
10249             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10250             if ((y = cmcfm()) < 0) return(y);
10251 #ifdef CK_APC
10252             /* Don't let this be set remotely */
10253             if (apcactive == APC_LOCAL ||
10254                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
10255               return(success = 0);
10256 #endif /* CK_APC */
10257             tn_no_encrypt_xfer = z;
10258             return(success = 1);
10259 
10260           case CK_TN_BM:                /* BINARY-MODE */
10261             if ((x = cmkey(tnnegtab,ntnnegtab,"","refused",xxstring)) < 0)
10262               return(x);
10263             if ((y = cmcfm()) < 0)
10264               return(y);
10265             TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = x;
10266             TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = x;
10267             TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = x;
10268             TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = x;
10269             return(success = 1);
10270 
10271 #ifdef IKS_OPTION
10272           case CK_TN_IKS:               /* KERMIT */
10273             if ((x = cmkey(tnnegtab,ntnnegtab,"DO","accept",xxstring)) < 0)
10274               return(x);
10275             if ((y = cmkey(tnnegtab,ntnnegtab,"WILL","accept",xxstring)) < 0)
10276               return(y);
10277             if ((z = cmcfm()) < 0)
10278               return(z);
10279             TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = y;
10280             TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = x;
10281             TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = y;
10282             TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = x;
10283             return(success = 1);
10284 #endif /* IKS_OPTION */
10285 
10286 #ifdef CK_SSL
10287           case CK_TN_TLS:               /* START_TLS */
10288             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10289               return(x);
10290             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10291               return(y);
10292             if ((z = cmcfm()) < 0)
10293               return(z);
10294             TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = x;
10295             TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = y;
10296             TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = x;
10297             TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = y;
10298             return(success = 1);
10299 #endif /* CK_SSL */
10300 
10301 #ifdef CK_NAWS
10302           case CK_TN_NAWS:              /* NAWS */
10303             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10304               return(x);
10305             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10306               return(y);
10307             if ((z = cmcfm()) < 0)
10308               return(z);
10309             TELOPT_DEF_S_ME_MODE(TELOPT_NAWS) = x;
10310             TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = y;
10311             TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = x;
10312             TELOPT_DEF_C_U_MODE(TELOPT_NAWS) = y;
10313             return(success = 1);
10314 #endif /* CK_NAWS */
10315 
10316 #ifdef CK_AUTHENTICATION
10317           case CK_TN_AU:                /* AUTHENTICATION */
10318             if ((x = cmkey(tnauthtab,ntnauth,"","",xxstring)) < 0)
10319               return(x);
10320             if (x == TN_AU_FWD) {
10321                 extern int forward_flag;
10322                 return(success = seton(&forward_flag));
10323             } else if (x == TN_AU_TYP) {
10324                 extern int auth_type_user[];
10325                 extern int sl_auth_type_user[];
10326                 extern int sl_auth_saved;
10327                 int i, j, atypes[AUTHTYPLSTSZ];
10328 
10329                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
10330                     if ((y = cmkey(autyptab,nautyp,"",
10331                                    i == 0 ? "automatic" : "" ,
10332                                    xxstring)) < 0) {
10333                         if (y == -3)
10334                           break;
10335                         return(y);
10336                     }
10337                     if (i > 0 && (y == AUTHTYPE_AUTO || y == AUTHTYPE_NULL)) {
10338                         printf(
10339                         "\r\n?Choice may only be used in first position.\r\n");
10340                         return(-9);
10341                     }
10342                     for (j = 0; j < i; j++) {
10343                         if (atypes[j] == y) {
10344                             printf("\r\n?Choice has already been used.\r\n");
10345                             return(-9);
10346                         }
10347                     }
10348                     atypes[i] = y;
10349                     if (y == AUTHTYPE_NULL || y == AUTHTYPE_AUTO) {
10350                         i++;
10351                         break;
10352                     }
10353                 }
10354                 if (i < AUTHTYPLSTSZ)
10355                   atypes[i] = AUTHTYPE_NULL;
10356                 if ((z = cmcfm()) < 0)
10357                   return(z);
10358                 sl_auth_saved = 0;
10359                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
10360                     auth_type_user[i] = atypes[i];
10361                     sl_auth_type_user[i] = 0;
10362                 }
10363             } else if (x == TN_AU_HOW) {
10364                 if ((y = cmkey(auhowtab,nauhow,"","any",xxstring)) < 0)
10365                   return(y);
10366                 if ((z = cmcfm()) < 0)
10367                   return(z);
10368                 tn_auth_how = y;
10369             } else if (x == TN_AU_ENC) {
10370                 if ((y = cmkey(auenctab,nauenc,"","encrypt",xxstring)) < 0)
10371                   return(y);
10372                 if ((z = cmcfm()) < 0)
10373                   return(z);
10374                 tn_auth_enc = y;
10375             } else {
10376                 if ((y = cmcfm()) < 0)
10377                   return(y);
10378                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = x;
10379                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = x;
10380             }
10381             return(success = 1);
10382 #endif /* CK_AUTHENTICATION */
10383 
10384 #ifdef CK_ENCRYPTION
10385           case CK_TN_ENC: {             /* ENCRYPTION */
10386               int c, tmp = -1;
10387               int getval = 0;
10388               static struct keytab * tnetbl = NULL;
10389               static int ntnetbl = 0;
10390 
10391               if ((y = cmkey(tnenctab,ntnenc,"","",xxstring)) < 0)
10392                 return(y);
10393               switch (y) {
10394                 case TN_EN_TYP:
10395                   x = ck_get_crypt_table(&tnetbl,&ntnetbl);
10396                   debug(F101,"ck_get_crypt_table x","",x);
10397                   debug(F101,"ck_get_crypt_table n","",ntnetbl);
10398                   if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
10399                     x = 0;
10400                   if (!x) {
10401                       printf("?Oops, types not loaded\n");
10402                       return(-9);
10403                   }
10404                   if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
10405                                  "automatic",xxstring)) < 0)
10406                     return(x);
10407                   if ((z = cmcfm()) < 0)
10408                     return(z);
10409                   cx_type = x;
10410                   sl_cx_type = 0;
10411                   break;
10412                 case TN_EN_START:
10413                   if ((z = cmcfm()) < 0)
10414                     return(z);
10415 #ifdef CK_APC
10416                   /* Don't let this be set remotely */
10417                   if (apcactive == APC_LOCAL ||
10418                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10419                     return(success = 0);
10420 #endif /* CK_APC */
10421                   ck_tn_enc_start();
10422                   break;
10423                 case TN_EN_STOP:
10424                   if ((z = cmcfm()) < 0)
10425                     return(z);
10426 #ifdef CK_APC
10427                   /* Don't let this be set remotely */
10428                   if (apcactive == APC_LOCAL ||
10429                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10430                     return(success = 0);
10431 #endif /* CK_APC */
10432                   ck_tn_enc_stop();
10433                   break;
10434                 default:
10435                   if ((z = cmcfm()) < 0)
10436                     return(z);
10437                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = y;
10438                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = y;
10439                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = y;
10440                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = y;
10441               }
10442               return(success = 1);
10443           }
10444 #endif /* CK_ENCRYPTION */
10445 
10446           case CK_TN_BUG:               /* BUG */
10447             if ((x = cmkey(tnbugtab,4,"",
10448                            "binary-me-means-u-too",xxstring)) < 0)
10449               return(x);
10450             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
10451             if ((y = cmcfm()) < 0) return(y);
10452             switch (x) {
10453               case 0:
10454                 tn_b_meu = z;
10455                 break;
10456               case 1:
10457                 tn_b_ume = z;
10458                 break;
10459               case 2:
10460                 tn_infinite = z;
10461                 break;
10462               case 3:
10463                 tn_sb_bug = z;
10464                 break;
10465               case 4:
10466                 tn_auth_krb5_des_bug = z;
10467                 break;
10468             }
10469             return(success = 1);
10470 
10471 #ifdef CK_ENVIRONMENT
10472           case CK_TN_XD:                /* XDISPLOC */
10473             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10474               return(x);
10475             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10476               return(y);
10477             if ((z = cmcfm()) < 0)
10478               return(z);
10479             TELOPT_DEF_S_ME_MODE(TELOPT_XDISPLOC) = x;
10480             TELOPT_DEF_S_U_MODE(TELOPT_XDISPLOC) = y;
10481             TELOPT_DEF_C_ME_MODE(TELOPT_XDISPLOC) = x;
10482             TELOPT_DEF_C_U_MODE(TELOPT_XDISPLOC) = y;
10483             return(success = 1);
10484 
10485           case CK_TN_ENV: {
10486               char * msg = "value of telnet environment variable";
10487               extern int tn_env_flg;
10488               extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
10489               tn_env_prnt[], tn_env_sys[];
10490               extern char * tn_loc;
10491               if ((x = cmkey(tnenvtab,ntnenv,"","",xxstring)) < 0)
10492                 return(x);
10493               if (x == TN_ENV_UVAR) {   /* User variables */
10494                   char * uvar=NULL;
10495                   char * uval=NULL;
10496                   char * env;
10497                   extern char * tn_env_uservar[8][2];
10498 
10499                   /* Get the user variable name */
10500                   if ((x = cmfld("Name of Environment Variable","",&s,
10501                                  xxstring)) < 0)
10502                     return(x);
10503                   makestr(&uvar,s);
10504 
10505                   env = getenv(uvar);
10506                   if (!env) env = "";
10507 
10508                   if ((x = cmtxt("Value of Environment Variable",env,
10509                                  &s,xxstring)) < 0)
10510                     return(x);
10511                   if (*s)
10512                     makestr(&uval,s);
10513 
10514                   /* Now that we have the variable and perhaps a value */
10515                   /* there are three possibilities: (1) new variable   */
10516                   /* and associated value; (2) variable already exists */
10517                   /* but we have a new value; (3) variable already     */
10518                   /* exists but no new value therefore the user wants  */
10519                   /* to clear variable.                                */
10520 
10521                   /* Try to find an existing variable */
10522                   for (x = 0; x < 8; x++) {
10523                       if (!ckstrcmp(tn_env_uservar[x][0],uvar,-1,0)) {
10524                           if (uval) {
10525                               free(tn_env_uservar[x][1]);
10526                               tn_env_uservar[x][1] = uval;
10527                               free(uvar);
10528                               return(success = 1);
10529                           } else {
10530                               free(tn_env_uservar[x][0]);
10531                               tn_env_uservar[x][0] = NULL;
10532                               free(tn_env_uservar[x][1]);
10533                               tn_env_uservar[x][1] = NULL;
10534                               free(uvar);
10535                               return(success = 1);
10536                           }
10537                       }
10538                   }
10539 
10540                   /* Couldn't find one; look for empty location to insert */
10541                   for (x = 0; x < 8; x++) {
10542                       if (!tn_env_uservar[x][0]) {
10543                           tn_env_uservar[x][0] = uvar;
10544                           tn_env_uservar[x][1] = uval;
10545                           return(success = 1);
10546                       }
10547                   }
10548                   printf("?Sorry, no space for variable.\n");
10549                   return(success = 0);
10550               }
10551               if (x == TN_ENV_OFF || x == TN_ENV_ON) {
10552                   if ((y = cmcfm()) < 0) return(y);
10553 #ifdef IKSD
10554                   if (inserver) {
10555                       printf("?Sorry, command disabled.\r\n");
10556                       return(success = 0);
10557                   }
10558 #endif /* IKSD */
10559                   tn_env_flg = x == TN_ENV_OFF ? 0 : 1;
10560                   return(success = 1);
10561               }
10562 
10563               /* Not ON/OFF - Get the value */
10564               z = cmdgquo();
10565               cmdsquo(0);
10566               if ((y = cmtxt(msg, "", &s, xxstring)) < 0) {
10567                   cmdsquo(z);
10568                   return(y);
10569               }
10570               cmdsquo(z);
10571 #ifdef IKSD
10572               if (inserver)
10573                 return(success = 0);
10574 #endif /* IKSD */
10575               if ((int)strlen(s) > 63) {
10576                   printf("Sorry, too long\n");
10577                   return(-9);
10578               }
10579               switch (x) {
10580                 case TN_ENV_USR:
10581                   ckstrncpy(uidbuf,s,UIDBUFLEN);
10582                   sl_uid_saved = 0;
10583                   break;
10584                 case TN_ENV_ACCT:
10585                   ckstrncpy(tn_env_acct,s,64);
10586                   break;
10587                 case TN_ENV_DISP:
10588                   ckstrncpy(tn_env_disp,s,64);
10589                   break;
10590                 case TN_ENV_JOB:
10591                   ckstrncpy(tn_env_job,s,64);
10592                   break;
10593                 case TN_ENV_PRNT:
10594                   ckstrncpy(tn_env_prnt,s,64);
10595                   break;
10596                 case TN_ENV_SYS:
10597                   ckstrncpy(tn_env_sys,s,64);
10598                   break;
10599                 case TN_ENV_LOC:
10600                   if (!*s) s = NULL;
10601                   makestr(&tn_loc,s);
10602                   break;
10603                 case TN_ENV_UVAR:
10604                   printf("\n?Not yet implemented\n");
10605                   break;
10606               }
10607               return(success = 1);
10608           }
10609 #endif /* CK_ENVIRONMENT */
10610 
10611 #ifdef CK_SNDLOC
10612           case CK_TN_LOC: {             /* LOCATION */
10613               extern char * tn_loc;
10614               if ((y = cmtxt("Location string","",&s,xxstring)) < 0)
10615                 return(y);
10616               if (!*s) s = NULL;
10617               makestr(&tn_loc,s);
10618               return(success = 1);
10619           }
10620 #endif /* CK_SNDLOC */
10621           case CK_TN_SFU:               /* Microsoft SFU compatibility */
10622             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10623             if ((y = cmcfm()) < 0) return(y);
10624             tn_sfu = z;
10625             return(success = 1);
10626             break;
10627 
10628           case CK_TN_WAIT:              /* WAIT-FOR-NEGOTIATIONS */
10629             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10630             if ((y = cmcfm()) < 0) return(y);
10631 #ifdef IKSD
10632             if (inserver &&
10633 #ifdef IKSDCONF
10634                 iksdcf
10635 #else
10636                 1
10637 #endif /* IKSDCONF */
10638                 ) {
10639                 printf("?Sorry, command disabled.\r\n");
10640                 return(success = 0);
10641             }
10642 #endif /* IKSD */
10643             tn_wait_flg = z;
10644             sl_tn_saved = 0;
10645             return(success = 1);
10646 
10647           case CK_TN_DL:                /* DELAY SUBNEGOTIATIONS */
10648             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10649             if ((y = cmcfm()) < 0) return(y);
10650 #ifdef IKSD
10651             if (inserver &&
10652 #ifdef IKSDCONF
10653                 iksdcf
10654 #else
10655                 1
10656 #endif /* IKSDCONF */
10657                 ) {
10658                 printf("?Sorry, command disabled.\r\n");
10659                 return(success = 0);
10660             }
10661 #endif /* IKSD */
10662             tn_delay_sb = z;
10663             return(success = 1);
10664 
10665           case CK_TN_PUID: {            /* PROMPT-FOR-USERID */
10666               int i,len;
10667               if ((y = cmtxt("Prompt string","",&s,xxstring)) < 0)
10668                 return(y);
10669 	      s = brstrip(s);
10670               /* we must check to make sure there are no % fields */
10671               len = strlen(s);
10672               for (i = 0; i < len; i++) {
10673                   if (s[i] == '%') {
10674                       if (s[i+1] != '%') {
10675                           printf("%% fields are not used in this command.\n");
10676                           return(-9);
10677                       }
10678                       i++;
10679                   }
10680               }
10681               makestr(&tn_pr_uid,s);
10682               return(success = 1);
10683           }
10684           default:
10685             return(-2);
10686         }
10687     }
10688 #endif /* TNCODE */
10689 
10690     switch (xx) {
10691 #ifndef NOSPL
10692       case XYCOUN:                      /* SET COUNT */
10693         x = cmnum("Positive number","0",10,&z,xxstring);
10694         if (x < 0) return(x);
10695         if ((x = cmcfm()) < 0) return(x);
10696         if (z < 0) {
10697             printf("?A positive number, please\n");
10698             return(0);
10699         }
10700         debug(F101,"XYCOUN: z","",z);
10701         return(success = setnum(&count[cmdlvl],z,0,10000));
10702 #endif /* NOSPL */
10703 
10704 #ifndef NOSPL
10705       case XYCASE:
10706         return(success = seton(&inpcas[cmdlvl]));
10707 #endif /* NOSPL */
10708 
10709       case XYCMD:                       /* COMMAND ... */
10710         if ((y = cmkey(scmdtab,nbytt,"","",xxstring)) < 0)
10711           return(y);
10712         switch (y) {
10713           case SCMD_CBR:
10714             if ((y = cmcfm()) < 0)
10715               return(y);
10716             concb((char)escape);
10717             return(success = 1);
10718 
10719           case SCMD_BSZ:
10720             if ((y = cmnum("bytesize for command characters, 7 or 8","7",10,&x,
10721                            xxstring)) < 0)
10722               return(y);
10723             if (x != 7 && x != 8) {
10724                 printf("\n?The choices are 7 and 8\n");
10725                 return(success = 0);
10726             }
10727             if ((y = cmcfm()) < 0) return(y);
10728             if (x == 7) cmdmsk = 0177;
10729             else if (x == 8) cmdmsk = 0377;
10730             return(success = 1);
10731 #ifdef CK_RECALL
10732           case SCMD_RCL:
10733             if ((y = cmnum("maximum number of commands in recall buffer","10",
10734                            10,&x,xxstring)) < 0)
10735               return(y);
10736             if ((y = cmcfm()) < 0) return(y);
10737             return(success = cmrini(x));
10738 #endif /* CK_RECALL */
10739 #ifdef CK_RECALL
10740           case SCMD_RTR:
10741             return(success = seton(&cm_retry));
10742 #endif /* CK_RECALL */
10743           case SCMD_MOR:                /* More-prompting */
10744             success = seton(&xaskmore);
10745             if (success)
10746               saveask = xaskmore;
10747             return(success);
10748           case SCMD_QUO:
10749             if ((x = seton(&y)) < 0) return(x);
10750             cmdsquo(y);                 /* Do it the right way */
10751             cmd_quoting = y;            /* Also keep a global copy */
10752             /* Set string-processing function */
10753 #ifdef datageneral
10754             xxstring = y ? zzstring : (xx_strp) NULL;
10755 #else
10756 #ifdef CK_ANSIC
10757             xxstring = y ? zzstring : (xx_strp) NULL;
10758 #else
10759             xxstring = y ? zzstring : (xx_strp) NULL;
10760 #endif /* CK_ANSIC */
10761 #endif /* datageneral */
10762             return(success = 1);
10763 
10764 #ifdef OS2
10765 #ifndef NOLOCAL
10766           case SCMD_COL: {              /* Command-screen colors */
10767               int fg, bg;
10768               fg = cmkey(ttyclrtab, nclrs,
10769                          "foreground color and then background color",
10770                          "white",
10771                          xxstring);
10772               if (fg < 0)
10773                 return(fg);
10774               if ((bg = cmkey(ttyclrtab,nclrs,
10775                               "background color","black",xxstring)) < 0)
10776                 return(bg);
10777               if ((y = cmcfm()) < 0)
10778                 return(y);
10779               colorcmd = fg | bg << 4;
10780               return(success = 1);
10781           }
10782           case SCMD_SCR:                /* Command Scrollback size */
10783             if ((y = cmnum("COMMAND scrollback buffer size, lines","512",10,&x,
10784                            xxstring)) < 0)
10785               return(y);
10786             /* The max number of lines is the RAM  */
10787             /* we can actually dedicate to a       */
10788             /* scrollback buffer given the maximum */
10789             /* process memory space of 512MB       */
10790             if (x < 256 || x > 2000000L) {
10791                 printf("\n?The size must be between 256 and 2,000,000.\n");
10792                 return(success = 0);
10793             }
10794             if ((y = cmcfm()) < 0) return(y);
10795             tt_scrsize[VCMD] = x;
10796             VscrnInit( VCMD );
10797             return(success = 1);
10798 
10799           case SCMD_WID: {
10800               if ((y = cmnum("Number of columns in display window",
10801                          "80",10,&x,xxstring)) < 0)
10802                 return(y);
10803               if ((y = cmcfm()) < 0) return(y);
10804 
10805               os2_setcmdwidth(x);
10806               return(success = 1);
10807           }
10808           case SCMD_HIG:
10809             if ((y = cmnum("Number of rows in display window",
10810                            "24",10,&x,xxstring)) < 0)
10811               return(y);
10812             if ((y = cmcfm()) < 0) return(y);
10813             os2_setcmdheight(x);
10814             return(success = 1);
10815 
10816           case SCMD_STA: {
10817               extern int marginbot;
10818               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
10819               if ((x = cmcfm()) < 0) return(x);
10820               if (y != tt_status[VCMD]) {
10821                   /* Might need to fixup the margins */
10822                   tt_status[VCMD] = y;
10823                   if (y) {
10824                       tt_szchng[VCMD] = 2;
10825                       tt_rows[VCMD]--;
10826                       cmd_rows--;
10827                       VscrnInit(VCMD);  /* Height set here */
10828                       printf("\n");
10829                   } else {
10830                       tt_szchng[VCMD] = 1;
10831                       tt_rows[VCMD]++;
10832                       cmd_rows++;
10833                       VscrnInit(VCMD);  /* Height set here */
10834                   }
10835               }
10836               return(success = 1);
10837           }
10838 
10839           case SCMD_CUR: {
10840               int row, col;
10841               position * ppos;
10842 
10843               ppos = VscrnGetCurPos(VCMD);
10844 #ifdef NT
10845 #define itoa _itoa
10846 #endif /* NT */
10847               itoa(ppos->y+1, tmpbuf, 10);
10848               if ((y = cmnum("row (1-based)",tmpbuf,10,&row,xxstring)) < 0)
10849                 return(y);
10850 
10851               itoa(ppos->x+1, tmpbuf, 10);
10852               if ((y = cmnum("col (1-based)",tmpbuf,10,&col,xxstring)) < 0)
10853                 return(y);
10854               if ((x = cmcfm()) < 0) return(x);
10855 
10856               lgotoxy( VCMD, col, row ) ;
10857               VscrnIsDirty( VCMD );
10858               return(success=1);
10859           }
10860 #endif /* NOLOCAL */
10861 #else
10862           case SCMD_WID:
10863             y = cmnum("Command screen width, characters","80",10,&x,xxstring);
10864             return(setnum(&cmd_cols,x,y,1024));
10865 
10866           case SCMD_HIG:
10867             y = cmnum("Command screen height, rows","24",10,&x,xxstring);
10868             return(setnum(&cmd_rows,x,y,1024));
10869 #endif /* OS2 */
10870 
10871           case SCMD_INT:
10872             return(seton(&cmdint));
10873 
10874 #ifdef CK_AUTODL
10875           case SCMD_ADL:
10876             return(seton(&cmdadl));
10877 #endif /* CK_AUTODL */
10878 
10879 #ifdef DOUBLEQUOTING
10880           case SCMD_DBQ: {
10881               extern int dblquo;
10882               return(seton(&dblquo));
10883           }
10884 #endif /* DOUBLEQUOTING */
10885 
10886 	  case SCMD_ERR:
10887             y = cmnum("Error message verbosity level, 0-3","1",10,&x,xxstring);
10888             return(setnum(&cmd_err,x,y,3));
10889 
10890 	  case SCMD_VAR:
10891 	    return(setvareval());
10892 
10893           default:
10894             return(-2);
10895         }
10896     }
10897 
10898     switch (xx) {
10899 
10900       case XYDFLT:                      /* SET DEFAULT = CD */
10901         return(success = docd(XXCWD));
10902 
10903 case XYDEBU:                            /* SET DEBUG { on, off, session } */
10904         if ((y = cmkey(dbgtab,ndbg,"","",xxstring)) < 0)
10905           return(y);
10906         if (y == DEB_TIM)
10907 #ifdef COMMENT
10908           return(seton(&debtim) < 0 ? x : (success = 1));
10909 #else
10910           /* why this change? */
10911           return(success = seton(&debtim));
10912 #endif /* COMMENT */
10913 
10914 #ifdef IKSD
10915         if (inserver && isguest) {
10916             printf("?Sorry, command disabled.\r\n");
10917             return(success = 0);
10918     }
10919 #endif /* IKSD */
10920 
10921         switch (y) {
10922           case DEB_LEN:
10923             y = cmnum("Max length for debug log strings","",10,&x,xxstring);
10924             if ((z = setnum(&debxlen,x,y,-1)) < 0)
10925               return(z);
10926             if ((x = cmcfm()) < 0)
10927               return(x);
10928             return(success = 1);
10929 
10930           case DEB_OFF:
10931             if ((x = cmcfm()) < 0)
10932               return(x);
10933 #ifndef NOLOCAL
10934             setdebses(0);
10935 #endif /* NOLOCAL */
10936 #ifdef DEBUG
10937             if (deblog) doclslog(LOGD);
10938 #endif /* DEBUG */
10939             return(success = 1);
10940 
10941           case DEB_ON:
10942             if ((x = cmcfm()) < 0)
10943               return(x);
10944 #ifdef DEBUG
10945             deblog = debopn("debug.log", 0);
10946             return(success = deblog ? 1 : 0);
10947 #else
10948             printf("?Sorry, debug log feature not enabled\n");
10949             return(success = 0);
10950 #endif /* DEBUG */
10951           case DEB_SES:
10952             if ((x = cmcfm()) < 0)
10953               return(x);
10954 #ifndef NOLOCAL
10955             setdebses(1);
10956 #endif /* NOLOCAL */
10957             return(success = 1);
10958 
10959 	  case DEB_MSG:			/* Debug messages 2010/03/12 */
10960 	    if ((y = cmkey(ooetab,nooetab,"","on",xxstring)) < 0) return(y);
10961 	    if ((x = cmcfm()) < 0) return(x);
10962 	    debmsg = y;
10963 	    return(1);
10964         }
10965         break;
10966 
10967 #ifndef NOXFER
10968       case XYDELA:                      /* SET DELAY */
10969         y = cmnum("Number of seconds before starting to send",
10970                   "5",10,&x,xxstring);
10971         if (x < 0) x = 0;
10972         return(success = setnum(&ckdelay,x,y,999));
10973 #endif /* NOXFER */
10974 
10975       default:
10976         break;
10977     }
10978 
10979     switch (xx) {
10980 #ifdef CK_TAPI
10981       case XYTAPI:
10982         return(settapi());
10983 #endif /* CK_TAPI */
10984 #ifndef NODIAL
10985       case XYDIAL:                      /* SET MODEM or SET DIAL */
10986         return(setdial(-1));
10987       case XYMODM:
10988         return(setmodem());
10989 #ifdef COMMENT
10990       /* not implemented yet */
10991       case XYANSWER:                    /* SET ANSWER */
10992         return(setanswer());
10993 #endif /* COMMENT */
10994 #endif /* NODIAL */
10995 
10996 #ifndef NOLOCAL
10997       case XYDUPL:                      /* SET DUPLEX */
10998         if ((y = cmkey(dpxtab,2,"","full",xxstring)) < 0) return(y);
10999         if ((x = cmcfm()) < 0) return(x);
11000         duplex = y;
11001         return(success = 1);
11002 
11003       case XYLCLE:                      /* LOCAL-ECHO (= DUPLEX) */
11004         return(success = seton(&duplex));
11005 
11006       case XYESC:                       /* SET ESCAPE */
11007         return(success = setcc(ckitoa(DFESC),&escape));
11008 #endif /* NOLOCAL */
11009 
11010       case XYEXIT:                      /* SET EXIT */
11011         if ((z = cmkey(xittab,nexit,"","",xxstring)) < 0)
11012           return(z);
11013         switch (z) {
11014           case 0:                       /* STATUS */
11015             y = cmnum("EXIT status code","",10,&x,xxstring);
11016             return(success = setnum(&xitsta,x,y,-1));
11017           case 1:                       /* WARNING */
11018             if ((z = cmkey(xitwtab,nexitw,"","",xxstring)) < 0)
11019               return(z);
11020             if ((y = cmcfm()) < 0) return(y);
11021             setexitwarn(z);
11022             return(success = 1);
11023           case 2:
11024             success = seton(&exitonclose);
11025 #ifdef TCPSOCKET
11026             if (success) tn_exit = exitonclose;
11027 #endif /* TCPSOCKET */
11028             return(success);
11029           case 3: {
11030               extern int exithangup;
11031               return((success = seton(&exithangup)));
11032           }
11033           case 4: {			/* MESSAGE 2013-03-13 */
11034             if ((z = cmkey(ooetab,nooetab,"","on",xxstring)) < 0)
11035               return(z);
11036             if ((y = cmcfm()) < 0) return(y);
11037 	    exitmsg = z;
11038             return(success = 1);
11039           }
11040           default:
11041             return(-2);
11042         } /* End of SET EXIT switch() */
11043       default:
11044         break;
11045     }
11046     switch (xx) {
11047 
11048       case XYFILE:                      /* SET FILE */
11049         return(setfil(rmsflg));
11050 
11051       case XYFLOW: {                    /* FLOW-CONTROL */
11052           extern int cxflow[];
11053           struct FDB k1, k2;
11054           int tncomport = 0;
11055           char * m;
11056 
11057 #ifdef TN_COMPORT
11058           if (network && istncomport())
11059             tncomport = 1;
11060 #endif /* TN_COMPORT */
11061 
11062           if (tncomport) {
11063               m = "Flow control type, one of the following:\n\
11064    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
11065  or connection type";
11066           } else {
11067           /* All this is because chained FDB's don't give chained help yet */
11068               m =
11069 #ifdef Plan9
11070 #ifdef CK_RTSCTS
11071            "Flow control type, one of the following:\n\
11072    keep   none    rts/cts\n\
11073  or connection type",
11074 #else
11075            "Flow control type, one of the following:\n\
11076    keep   none\n\
11077  or connection type";
11078 #endif /* CK_RTSCTS */
11079 #else
11080 #ifdef CK_RTSCTS
11081 #ifdef CK_DTRCD
11082 #ifdef CK_DTRCTS
11083            "Flow control type, one of the following:\n\
11084    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
11085  or connection type";
11086 #else /* CK_DTRCTS */
11087            "Flow control type, one of the following:\n\
11088    dtr/cd    keep    none    rts/cts   xon/xoff\n\
11089             or connection type";
11090 #endif /* CK_DTRCTS */
11091 #else /* CK_DTRCD */
11092 #ifdef CK_DTRCTS
11093            "Flow control type, one of the following:\n\
11094    dtr/cts   keep   none    rts/cts   xon/xoff\n\
11095  or connection type";
11096 #else /* CK_DTRCTS */
11097            "Flow control type, one of the following:\n\
11098    keep   none    rts/cts   xon/xoff\n\
11099  or connection type";
11100 #endif /* CK_DTRCTS */
11101 #endif /* CK_DTRCD */
11102 #else
11103            "Flow control type, one of the following:\n\
11104    keep   none    xon/xoff\n\
11105  or connection type";
11106 #endif /* CK_RTSCTS */
11107 #endif /* Plan9 */
11108           }
11109           cmfdbi(&k1,_CMKEY,m,"","",ncxtypesw, 4, xxstring, cxtypesw, &k2);
11110           cmfdbi(&k2,
11111                  _CMKEY,
11112                  "",
11113                  "",
11114                  "",
11115 #ifdef TN_COMPORT
11116                  (tncomport ? ntnflo : nflo),
11117 #else
11118                  nflo,
11119 #endif /* TN_COMPORT */
11120                  0,
11121                  xxstring,
11122 #ifdef TN_COMPORT
11123                  (tncomport ? tnflotab : flotab),
11124 #else
11125                  flotab,
11126 #endif /* TN_COMPORT */
11127                  NULL
11128                  );
11129           x = cmfdb(&k1);
11130           if (x < 0) {                  /* Error */
11131               if (x == -2 || x == -9)
11132                 printf("?No keywords or switches match: \"%s\"\n",atmbuf);
11133               return(x);
11134           }
11135           z = cmresult.nresult;         /* Keyword value */
11136           if (cmresult.fdbaddr == &k2) { /* Flow-control type keyword table */
11137               if ((x = cmcfm()) < 0)    /* Set it immediately */
11138                 return(x);
11139               flow = z;
11140               debug(F101,"set flow","",flow);
11141 #ifdef CK_SPEED
11142               if (flow == FLO_XONX)     /* Xon/Xoff forces prefixing */
11143                 ctlp[XON] = ctlp[XOFF] = ctlp[XON+128] = ctlp[XOFF+128] = 1;
11144 #endif /* CK_SPEED */
11145               autoflow = (flow == FLO_AUTO);
11146               return(success = 1);      /* Done */
11147           }
11148           debug(F101,"set flow /blah 1","",z); /* SET FLOW /for-what */
11149           if ((y = cmkey(flotab,nflo,"Flow control type","none",xxstring)) < 0)
11150             return(y);
11151           if ((x = cmcfm()) < 0)
11152             return(x);
11153           debug(F101,"set flow /blah 2","",y);
11154           if (y == FLO_AUTO) {
11155               printf(
11156   "?Sorry, \"automatic\" can not be assigned to a connection type.\n");
11157               return(-9);
11158           } else if (z >= 0 && z <= CXT_MAX)
11159             cxflow[z] = y;
11160           debug(F101,"set flow","",flow);
11161           debug(F101,"set flow autoflow","",autoflow);
11162           return(success = 1);
11163       }
11164 
11165       case XYHAND:                      /* HANDSHAKE */
11166         if ((y = cmkey(hshtab,nhsh,"","none",xxstring)) < 0) return(y);
11167         if (y == 998) {
11168             if ((x = cmnum("ASCII value","",10,&y,xxstring)) < 0)
11169               return(x);
11170             if ((y < 1) || ((y > 31) && (y != 127))) {
11171                 printf("?Character must be in ASCII control range\n");
11172                 return(-9);
11173             }
11174         }
11175         if ((x = cmcfm()) < 0) return(x);
11176         turn = (y > 0127) ? 0 : 1;
11177         turnch = y;
11178         return(success = 1);
11179 
11180 #ifndef NOSPL
11181       case XYMACR:                      /* SET MACRO */
11182         if ((y = cmkey(smactab,2,"","",xxstring)) < 0) return(y);
11183         switch (y) {
11184           case 0: return(success = seton(&mecho));
11185           case 1: return(success = seton(&merror[cmdlvl]));
11186           default: return(-2);
11187         }
11188 #endif /* NOSPL */
11189 
11190       case XYMSGS:
11191 #ifdef VMS
11192         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
11193         if ((y = cmcfm()) < 0) return(y);
11194         vms_msgs = z;
11195         printf("Sorry, SET MESSAGES not implemented yet\n");
11196         return(success = 0);
11197 #endif /* VMS */
11198       default:
11199         break;
11200     }
11201 
11202     switch (xx) {
11203 
11204       case XYPARI:                      /* PARITY */
11205         if ((y = cmkey(partbl,npar,"","none",xxstring)) < 0)
11206           return(y);
11207 
11208         /* If parity not none, then we also want 8th-bit prefixing */
11209 
11210 #ifdef HWPARITY
11211         if (y == 'H') {                 /* Hardware */
11212             if ((x = cmkey(hwpartbl,nhwpar,"","even",xxstring)) < 0)
11213               return(x);
11214         }
11215 #endif /* HWPARITY */
11216 
11217         if ((z = cmcfm()) < 0)
11218           return(z);
11219 
11220 #ifdef HWPARITY
11221         if (y == 'H') {                 /* 8 data bits plus hardware parity */
11222             parity = 0;
11223 #ifndef NOXFER
11224             ebqflg = 0;
11225 #endif /* NOXFER */
11226             hwparity = x;
11227         } else {                        /* 7 data bits + software parity */
11228             hwparity = 0;
11229 #endif /* HWPARITY */
11230             parity = y;
11231 #ifndef NOXFER
11232             ebqflg = (parity) ? 1 : 0;
11233 #endif /* NOXFER */
11234 #ifdef HWPARITY
11235         }
11236 #endif /* HWPARITY */
11237 
11238 #ifdef TN_COMPORT
11239         if (network && istncomport())
11240           tnsettings(parity, 0);
11241 #endif /* TN_COMPORT */
11242 
11243         return(success = 1);
11244 
11245 #ifndef NOFRILLS
11246       case XYPROM:                      /* SET PROMPT */
11247 /*
11248   Note: xxstring not invoked here.  Instead, it is invoked every time the
11249   prompt is issued.  This allows the prompt string to contain variables
11250   that can change, like \v(dir), \v(time), etc.
11251 */
11252         ckmakmsg(line,                  /* Default might have trailing space */
11253                  LINBUFSIZ,
11254                  "{",
11255                  inserver ? ikprompt : ckprompt,
11256                  "}",
11257                  NULL
11258                  );
11259         if ((x = cmtxt("Program's command prompt",line,&s,NULL)) < 0)
11260           return(x);
11261         s = brstrip(s);                 /* Remove enclosing braces, if any */
11262         cmsetp(s);                      /* Set the prompt */
11263         return(success = 1);
11264 #endif /* NOFRILLS */
11265 
11266 #ifndef NOXFER
11267       case XYRETR:                      /* RETRY: per-packet retry limit */
11268         y = cmnum("Maximum retries per packet","10",10,&x,xxstring);
11269         if (x < 0) x = 0;
11270         if ((x = setnum(&maxtry,x,y,999)) < 0) return(x);
11271 #ifdef COMMENT
11272         if (maxtry <= wslotr) {
11273             printf("?Retry limit must be greater than window size\n");
11274             return(success = 0);
11275         }
11276 #endif /* COMMENT */
11277         if (rmsflg) {
11278             sstate = setgen('S', "403", ckitoa(maxtry), "");
11279             return((int) sstate);
11280         } else return(success = x);
11281 #endif /* NOXFER */
11282 
11283 #ifndef NOSERVER
11284       case XYSERV:                      /* SET SERVER items */
11285         if ((y = cmkey(srvtab,nsrvt,"","",xxstring)) < 0) return(y);
11286         switch (y) {
11287           case XYSERI:
11288             if ((y = cmnum("Number of seconds, or 0 for no idle timeout",
11289                            "0",10,&x,xxstring)) < 0)
11290               return(y);
11291             if (x < 0)
11292               x = 0;
11293             if ((y = cmcfm()) < 0)
11294               return(y);
11295 #ifndef OS2
11296             srvtim = 0;
11297 #endif /* OS2 */
11298             srvidl = x;
11299             return(success = 1);
11300           case XYSERT:
11301             if ((y = cmnum("Interval for server NAKs, 0 = none",
11302                            ckitoa(DSRVTIM),
11303                            10,&x, xxstring)) < 0)
11304               return(y);
11305             if (x < 0) {
11306                 printf(
11307                    "\n?Specify a positive number, or 0 for no server NAKs\n");
11308                 return(0);
11309             }
11310             if ((y = cmcfm()) < 0) return(y);
11311             if (rmsflg) {
11312                 sstate = setgen('S', "404", ckitoa(x), "");
11313                 return((int) sstate);
11314             } else {
11315 #ifndef OS2
11316                 srvidl = 0;
11317 #endif /* OS2 */
11318                 srvtim = x;             /* Set the server timeout variable */
11319                 return(success = 1);
11320             }
11321           case XYSERD:                  /* SERVER DISPLAY */
11322             return(success = seton(&srvdis)); /* ON or OFF... */
11323 
11324 #ifndef NOSPL
11325           case XYSERP:                  /* SERVER GET-PATH */
11326             return(parsdir(2));
11327 #endif /* NOSPL */
11328 
11329           case XYSERL:                  /* SERVER LOGIN */
11330             return(cklogin());
11331 
11332           case XYSERC:                  /* SERVER CD-MESSAGE */
11333             x = rmsflg ?
11334               cmkey(onoff,2,"","",xxstring) :
11335                 cmkey(cdmsg,3,"","",xxstring);
11336             if (x < 0)
11337               return(x);
11338             if (x == 2) {               /* CD-MESSAGE FILE */
11339                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
11340                   return(x);
11341                 if (!*s) {
11342                     s = NULL;
11343                     srvcdmsg = 0;
11344                 }
11345                 makestr(&cdmsgstr,s);
11346                 makelist(cdmsgstr,cdmsgfile,8);
11347                 return(success = 1);
11348             }
11349             if ((y = cmcfm()) < 0)      /* CD-MESSAGE ON/OFF */
11350               return(y);
11351             if (rmsflg) {
11352                 sstate = setgen('S', "420", x ? "1" : "0", "");
11353                 return((int) sstate);
11354             } else {
11355                 if (x > 0)
11356                   srvcdmsg |= 1;
11357                 else
11358                   srvcdmsg &= 2;
11359                 return(success = 1);
11360             }
11361           case XYSERK:                  /* SERVER KEEPALIVE */
11362             return(success = seton(&srvping)); /* ON or OFF... */
11363 
11364           default:
11365             return(-2);
11366         }
11367 #endif /* NOSERVER */
11368     }
11369 
11370     switch (xx) {
11371 #ifdef UNIX
11372 #ifndef NOJC
11373       case XYSUSP:                      /* SET SUSPEND */
11374         seton(&xsuspend);		/* on or off... */
11375         return(success = 1);
11376 #endif /* NOJC */
11377 #endif /* UNIX */
11378 
11379       case XYTAKE:                      /* SET TAKE */
11380         if ((y = cmkey(taktab,4,"","",xxstring)) < 0) return(y);
11381         switch (y) {
11382           case 0: return(success = seton(&techo));
11383 #ifndef NOSPL
11384           case 1: return(success = seton(&takerr[cmdlvl]));
11385 #else
11386           case 1: return(success = seton(&takerr[tlevel]));
11387 #endif /* NOSPL */
11388           case 2: techo = 0; return(success = 1); /* For compatibility with */
11389           case 3: techo = 1; return(success = 1); /* MS-DOS Kermit */
11390           default: return(-2);
11391         }
11392 
11393 #ifndef NOSCRIPT
11394       case XYSCRI:                      /* SET SCRIPT */
11395         if ((y = cmkey(scrtab,1,"","echo",xxstring)) < 0) return(y);
11396         switch (y) {
11397           case 0: return(success = seton(&secho));
11398           default: return(-2);
11399         }
11400 #endif /* NOSCRIPT */
11401 
11402       default:
11403         break;
11404     }
11405 
11406 #ifndef NOLOCAL
11407     switch (xx) {
11408       case XYTERM:                      /* SET TERMINAL */
11409         x = settrm();
11410         success = (x > 0) ? 1 : 0;
11411         return(x);
11412 
11413 #ifdef NT
11414       case XYWIN95:                     /* SET WIN95 workarounds */
11415         x = setwin95();
11416         success = (x > 0 ? 1 : 0);
11417         return(x);
11418 #endif /* NT */
11419 
11420 #ifdef OS2
11421       case XYDLR:                       /* SET DIALER workarounds */
11422         x = setdialer();
11423         success = (x > 0 ? 1 : 0);
11424         return(x);
11425 
11426       case XYTITLE:                     /* SET TITLE of window */
11427         x = settitle();
11428         success = (x > 0 ? 1 : 0);
11429         return(x);
11430 #endif /* OS2 */
11431 
11432 #ifdef OS2MOUSE
11433       case XYMOUSE:                     /* SET MOUSE */
11434         return(success = setmou());
11435 #endif /* OS2MOUSE */
11436 
11437       case XYBELL:                      /* SET BELL */
11438         return(success = setbell());
11439 
11440 #ifdef OS2
11441       case XYPRTY:
11442         return(success = setprty() );
11443 #endif /* OS2 */
11444 
11445       default:
11446         break;
11447     }
11448 #endif /* NOLOCAL */
11449 
11450     switch (xx) {
11451 
11452 /* SET SEND/RECEIVE protocol parameters. */
11453 
11454 #ifndef NOXFER
11455       case XYRECV:
11456       case XYSEND:
11457         return(setsr(xx,rmsflg));
11458 #endif /* NOXFER */
11459 
11460 #ifndef NOLOCAL
11461       case XYSESS:                      /* SESSION-LOG */
11462         if ((x = cmkey(sfttab,nsfttab,"type of file",
11463 #ifdef OS2
11464                        "binary",
11465 #else /* OS2 */
11466                        "text",
11467 #endif /* OS2 */
11468                        xxstring
11469                        )
11470              ) < 0)
11471           return(x);
11472         if ((y = cmcfm()) < 0)
11473           return(y);
11474         if (x == 999) {                 /* TIMESTAMPED-TEXT */
11475             sessft = XYFT_T;            /* Implies text */
11476             slogts = 1;                 /* and timestamps */
11477 	} else if (x == 998) {		/* NULL-PADDED-LINES */
11478             slognul = 1;		/* adds NUL after ^J */
11479         } else {                        /* A regular type */
11480             sessft = x;                 /* The type */
11481             slogts = 0;                 /* No timestampes */
11482         }
11483         return(success = 1);
11484 
11485       case XYSPEE:                      /* SET SPEED */
11486         lp = line;
11487         if (local && !network) {
11488           ckmakmsg(lp,
11489                    LINBUFSIZ,
11490                    "Transmission rate for ",
11491                    ttname,
11492                    " (bits per second)",
11493                    NULL
11494                    );
11495         } else {
11496           ckstrncpy(lp,
11497                     "Serial-port speed (bits per second)",
11498                     LINBUFSIZ
11499                     );
11500         }
11501         zz = -1L;
11502 
11503 #ifdef TN_COMPORT
11504         if (network && istncomport())
11505           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
11506         else
11507 #endif /* TN_COMPORT */
11508           x = cmkey(spdtab,nspd,line,"",xxstring);
11509         if (x < 0) {
11510             if (x == -3) printf("?value required\n");
11511 #ifdef USETCSETSPEED
11512             /* In this case, any number can be tried */
11513             /* There's a parse error message but the request still goes thru */
11514             if (rdigits(atmbuf))
11515               zz = atol(atmbuf);
11516             else
11517 #endif /* USETCSETSPEED */
11518               return(x);
11519         }
11520         if ((y = cmcfm()) < 0) return(y);
11521 #ifdef IKSD
11522         if (inserver) {
11523             printf("?Sorry, command disabled.\r\n");
11524             return(success = 0);
11525         }
11526 #endif /* IKSD */
11527         if (!local) {
11528             printf("?SET SPEED has no effect without prior SET LINE\n");
11529             return(success = 0);
11530         } else if (network
11531 #ifdef TN_COMPORT
11532                    && !istncomport()
11533 #endif /* TN_COMPORT */
11534                    ) {
11535             printf("\n?Speed cannot be set for network connections\n");
11536             return(success = 0);
11537         }
11538 
11539 /*
11540   Note: This way of handling speeds is not 16-bit safe for speeds greater
11541   than 230400.  The argument to ttsspd() should have been a long.
11542 */
11543 #ifdef USETCSETSPEED
11544         if (zz > -1L)
11545           x = zz / 10L;
11546 #endif /* USETCSETSPEED */
11547         zz = (long) x * 10L;
11548         if (zz == 130L) zz = 134L;
11549         if (zz == 70L) zz = 75L;        /* (see spdtab[] definition) */
11550         if (ttsspd(x) < 0)  {           /* Call ttsspd with cps, not bps! */
11551             printf("?Unsupported line speed - %ld\n",zz);
11552             return(success = 0);
11553         } else {
11554 #ifdef CK_TAPI
11555             if (!tttapi || tapipass)
11556               speed = ttgspd();         /* Read it back */
11557             else
11558               speed = zz;
11559 #else /* CK_TAPI */
11560             speed = ttgspd();           /* Read it back */
11561 #endif /* CK_TAPI */
11562             if (speed != zz)  {         /* Call ttsspd with cps, not bps! */
11563                 printf("?SET SPEED fails, speed is %ld\n",speed);
11564                 return(success = 0);
11565             }
11566             if (pflag && !xcmdsrc) {
11567                 if (speed == 8880)
11568                   printf("%s, 75/1200 bps\n",ttname);
11569                 else if (speed == 134)
11570                   printf("%s, 134.5 bps\n",ttname);
11571                 else
11572                   printf("%s, %ld bps\n",ttname,speed);
11573             }
11574             return(success = 1);
11575         }
11576 #endif /* NOLOCAL */
11577 
11578 #ifndef NOXFER
11579       case XYXFER:                      /* SET TRANSFER */
11580         if ((y = cmkey(rmsflg ? rtstab : tstab, /* (or REMOTE SET TRANSFER) */
11581                        rmsflg ? nrts : nts,
11582                        "","character-set",xxstring)) < 0) return(y);
11583         switch (y) {
11584 #ifdef XFRCAN
11585           case XYX_CAN:                 /* CANCELLATION */
11586             if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
11587             if (z == 0) {               /* OFF */
11588                 if ((y = cmcfm()) < 0) return(y);
11589                 xfrcan = 0;
11590             } else {
11591                 if ((y = cmnum("ASCII code for cancellation character",
11592                                "3",10,&x,
11593                                xxstring)) < 0)
11594                   return(y);
11595                 if (x > 31 && x != 127) {
11596                     printf("Cancel character must be 0-31 or 127\n");
11597                     return(-9);
11598                 }
11599                 if ((y = cmnum("How many required to cause cancellation",
11600                                "2",10,&z, xxstring)) < 0)
11601                   return(y);
11602                 if (z < 2) {
11603                     printf("Number must be 2 or greater\n");
11604                     return(-9);
11605                 }
11606                 if ((y = cmcfm()) < 0) return(y);
11607                 xfrcan = 1;             /* CANCELLATION ON */
11608                 xfrchr = x;             /* Using this character */
11609                 xfrnum = z;             /* Needing this many of them */
11610             }
11611             return(success = 1);
11612 #endif /* XFRCAN */
11613 
11614 #ifndef NOCSETS
11615           case XYX_CSE:                 /* CHARACTER-SET */
11616             if ((y = cmkey(tcstab,ntcs,"","transparent",xxstring)) < 0)
11617               return(y);
11618             if ((x = cmcfm()) < 0) return(x);
11619             if (rmsflg) {
11620                 sstate = setgen('S', "405", tcsinfo[y].designator, "");
11621                 return((int) sstate);
11622             } else {
11623                 extern int s_cset, fcharset, axcset[], tcs_save;
11624                 tslevel = (y == TC_TRANSP) ? 0 : 1; /* transfer syntax level */
11625 		xfrxla = tslevel;
11626                 tcharset = y;           /* transfer character set */
11627                 /* SEND CHARACTER-SET AUTO */
11628                 if (tslevel > 0 && s_cset == XMODE_A)
11629                   if (y > -1 && y <= MAXTCSETS)
11630                     if (axcset[y] > -1 && axcset[y] > MAXFCSETS)
11631                       fcharset = axcset[y]; /* Auto-pick file charset */
11632                 setxlatype(tcharset,fcharset); /* Translation type */
11633 		tcs_save = -1;
11634                 return(success = 1);
11635             }
11636 #endif /* NOCSETS */
11637 
11638           case XYX_LSH:                 /* LOCKING-SHIFT */
11639             if ((y = cmkey(lstab,nls,"","on",xxstring)) < 0)
11640               return(y);
11641             if ((x = cmcfm()) < 0) return(x);
11642             lscapr = (y == 1) ? 1 : 0;  /* ON: requested = 1 */
11643             lscapu = (y == 2) ? 2 : 0;  /* FORCED:  used = 1 */
11644             return(success = 1);
11645 
11646 /* #ifdef CK_XYZ */
11647           case XYX_PRO:                 /* Protocol */
11648 #ifndef OS2
11649             if (inserver) {
11650                 printf("?Sorry, only Kermit protocol is available\n");
11651                 return(-9);
11652             }
11653 #endif /* OS2 */
11654             return(setproto());
11655 /* #endif */ /* CK_XYZ */
11656 
11657           case XYX_MOD:                 /* Mode */
11658             if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
11659               return(y);
11660             if ((x = cmcfm()) < 0) return(x);
11661             if (rmsflg) {
11662                 sstate = setgen('S', "410", y == XMODE_A ? "0" : "1", "");
11663                 return((int)sstate);
11664             }
11665             g_xfermode = y;
11666             xfermode = y;
11667 #ifdef NEWFTP
11668 	    if (ftpisopen()) {		/* If an FTP connection is open */
11669 		extern int ftp_xfermode; /* change its transfer mode too */
11670 		ftp_xfermode = xfermode;
11671 	    }
11672 #endif	/* NEWFTP */
11673             return(success = 1);
11674 
11675 #ifndef NOLOCAL
11676           case XYX_DIS:                 /* Display */
11677             return(doxdis(1));		/* 1 == Kermit */
11678 #endif /* NOLOCAL */
11679 
11680           case XYX_SLO:                 /* Slow-start */
11681             return(seton(&slostart));
11682 
11683 #ifndef NOSPL
11684           case XYX_CRC:                 /* CRC */
11685             return(seton(&docrc));
11686 #endif /* NOSPL */
11687 
11688           case XYX_BEL:                 /* Bell */
11689             return(seton(&xfrbel));
11690 
11691 #ifdef PIPESEND
11692           case XYX_PIP:                 /* Pipes */
11693 #ifndef NOPUSH
11694             if (nopush) {
11695 #endif /* NOPUSH */
11696                 printf("Sorry, access to pipes is disabled\n");
11697                 return(-9);
11698 #ifndef NOPUSH
11699             } else
11700 #endif /* NOPUSH */
11701               return(seton(&usepipes));
11702 #endif /* PIPESEND */
11703 
11704           case XYX_INT:                 /* Interruption */
11705             return(seton(&xfrint));
11706 
11707           case XYX_XLA:
11708             return(seton(&xfrxla));     /* Translation */
11709 
11710           case XYX_MSG: {
11711               extern char * xfrmsg;
11712               if ((x = cmtxt("Prompt string","",&s,xxstring)) < 0)
11713                 return(x);
11714               if (!*s) s = NULL;
11715               makestr(&xfrmsg,s);
11716               return(success = 1);
11717 
11718 	  }
11719 	  case XYX_RPT: {
11720 	      extern int whereflg;
11721 	      return(seton(&whereflg));
11722           }
11723           default:
11724             return(-2);
11725         }
11726 #endif /* NOXFER */
11727     }
11728 
11729     switch (xx) {
11730 
11731 #ifndef NOXMIT
11732       case XYXMIT:                      /* SET TRANSMIT */
11733         return(setxmit());
11734 #endif /* NOXMIT */
11735 
11736 #ifndef NOXFER
11737 #ifndef NOCSETS
11738       case XYUNCS:                      /* UNKNOWN-CHARACTER-SET */
11739         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
11740         if ((x = cmcfm()) < 0) return(x);
11741         unkcs = y;
11742         return(success = 1);
11743 #endif /* NOCSETS */
11744 #endif /* NOXFER */
11745 
11746 #ifndef NOPUSH
11747 #ifdef UNIX
11748       case XYWILD:                      /* WILDCARD-EXPANSION */
11749         if ((y = cmkey(wildtab,nwild,
11750                        "Wildcard expansion option","on",xxstring)) < 0)
11751           return(y);
11752         if ((z = cmkey(wdottab,
11753                        2,
11754                        "whether to match filenames that start with \".\"",
11755                        "/no-match-dot-files",
11756                        xxstring)
11757              ) < 0)
11758           return(z);
11759         if ((x = cmcfm()) < 0) return(x);
11760         if (nopush) {
11761             if (y > 0) {
11762                 printf("Shell expansion is disabled\n");
11763                 return(success = 0);
11764             }
11765         }
11766 	switch (y) {
11767 	  case WILD_ON:
11768 	    wildena = 1;
11769 	    break;
11770 	  case WILD_OFF:
11771 	    wildena = 0;
11772 	    break;
11773 	  case WILD_KER:
11774 	    wildxpand = 0; 		/* These are the previous */
11775 	    break;			/* hardwired values */
11776 	  case WILD_SHE:
11777 	    wildxpand = 1;
11778 	    break;
11779 	}
11780         matchdot = z;
11781         return(success = 1);
11782 #endif /* UNIX */
11783 #endif /* NOPUSH */
11784 
11785 #ifndef NOXFER
11786       case XYWIND:                      /* WINDOW-SLOTS */
11787         if (protocol == PROTO_K) {
11788             y = cmnum("Window size for Kermit protocol, 1 to 32",
11789                       "1", 10, &x, xxstring);
11790             y = setnum(&z,x,y,MAXWS);   /* == 32 */
11791         }
11792 #ifdef CK_XYZ
11793         else if (protocol == PROTO_Z) {
11794             y = cmnum("Window size for ZMODEM protocol, 0 to 65535",
11795                       "0", 10, &x, xxstring);
11796             y = setnum(&z,x,y,65535);
11797         }
11798 #endif /* CK_XYZ */
11799         else {
11800             y = cmnum("Window size for current protocol",
11801                       "", 10, &x, xxstring);
11802             y = setnum(&z,x,y,65472);   /* Doesn't matter - we won't use it */
11803         }
11804         if (y < 0) return(y);
11805         if (protocol == PROTO_K) {
11806             if (z < 1)
11807               z = 1;
11808         }
11809 #ifdef CK_XYZ
11810         else if (protocol == PROTO_Z) {
11811             /* Zmodem windowing is closer to Kermit packet length */
11812             /* than Kermit window size.  If Window size is zero   */
11813             /* an end of frame and CRC is sent only at the end of */
11814             /* the file (default).  Otherwise, an End of Frame    */
11815             /* and CRC are sent after Window Size number of bytes */
11816             if (z < 0)                  /* Disable windowing  */
11817               z = 0;
11818         } else {
11819             printf("?SET WINDOW does not apply to %s protocol\n",
11820                    ptab[protocol].p_name
11821                    );
11822         }
11823 #endif /* CK_XYZ */
11824 
11825 #ifdef COMMENT
11826         /* This is taken care of automatically now in protocol negotiation */
11827         if (maxtry < z) {
11828             printf("?Window slots must be less than retry limit\n");
11829             return(success = 0);
11830         }
11831 #endif /* COMMENT */
11832         if (protocol == PROTO_K && rmsflg) { /* Set remote window size */
11833             wslotr = z;                 /* Set local window size too */
11834             ptab[protocol].winsize = wslotr;
11835             sstate = setgen('S', "406", ckitoa(z), "");
11836             return((int) sstate);
11837         }
11838         wslotr = z;                     /* Set requested window size here */
11839         ptab[protocol].winsize = wslotr; /* and in protocol-specific table */
11840         if (protocol == PROTO_K) {      /* And for Kermit only... */
11841             swcapr = (wslotr > 1) ? 1 : 0; /* set window bit in capas word */
11842             if (wslotr > 1) {           /* Window size > 1? */
11843                 /* Maybe adjust packet size */
11844                 y = adjpkl(urpsiz,wslotr,bigrbsiz);
11845                 if (y != urpsiz) {      /* Did it change? */
11846                     urpsiz = y;
11847                     if (msgflg)
11848                       printf(
11849 " Adjusting receive packet-length to %d for %d window slots\n",
11850                              urpsiz,
11851                              wslotr
11852                              );
11853                 }
11854             }
11855         }
11856         return(success = 1);
11857 #endif /* NOXFER */
11858     }
11859 
11860     switch (xx) {
11861 
11862 #ifndef NOSPL
11863       case XYOUTP:                      /* OUTPUT command parameters */
11864         if ((y = cmkey(outptab,noutptab,"OUTPUT command parameter","pacing",
11865                        xxstring)) < 0)
11866           return(y);
11867         switch(y) {                     /* Which parameter */
11868           case OUT_PAC:                 /* PACING */
11869             y = cmnum("Milliseconds to pause between each OUTPUT character",
11870                       "100", 10,&x,xxstring);
11871             y = setnum(&z,x,y,16383);   /* Verify and get confirmation */
11872             if (y < 0) return(y);
11873             if (z < 0) z = 0;           /* (save some space) */
11874             pacing = z;
11875             return(success = 1);
11876           case OUT_ESC:                 /* Special-escapes */
11877             return(seton(&outesc));
11878           default:                      /* (shouldn't happen) */
11879             return(-2);
11880         }
11881 #endif /* NOSPL */
11882 
11883 #ifdef CK_SPEED
11884       case XYQCTL: {
11885           short *p;
11886           int zz;
11887           if ((z = cmkey(ctltab,2, "control-character prefixing option",""
11888                          ,xxstring)) < 0)
11889             return(z);
11890           /* Make space for a temporary copy of the prefixing table */
11891 
11892           p = (short *)malloc(256 * sizeof(short));
11893           if (!p) {
11894               printf("?Internal error - malloc failure\n");
11895               return(-9);
11896           }
11897           for (i = 0; i < 256; i++) p[i] = ctlp[i]; /* Copy current table */
11898 
11899           switch (z) {
11900             case 0:                     /* UNPREFIXED control character */
11901             case 1:                     /* PREFIXED control character */
11902               while (1) {               /* Collect a list of numbers */
11903 #ifndef NOSPL
11904                   x_ifnum = 1;          /* Turn off complaints from eval() */
11905 #endif /* NOSPL */
11906                   if ((x = cmnum((z == 0) ?
11907 "\n Numeric ASCII value of control character that needs NO prefix,\n\
11908  or the word \"all\", or carriage return to complete the list" :
11909 "\n Numeric ASCII value of control character that MUST BE prefixed,\n\
11910  or the word \"all\", or carriage return to complete the list",
11911                                  "",10,&y,xxstring
11912                                  )) < 0) {
11913 #ifndef NOSPL
11914                       x_ifnum = 0;
11915 #endif /* NOSPL */
11916                       if (x == -3) {
11917                           if ((x = cmcfm()) < 0) return(x);
11918                           break;
11919                       }
11920                       if (x == -2) {
11921                           if (p) { free((char *)p); p = NULL; }
11922                           debug(F110,"SET CONTROL atmbuf",atmbuf,0);
11923                           if (!ckstrcmp(atmbuf,"all",3,0) || /* "ALL" */
11924                               !ckstrcmp(atmbuf,"al",2,0) ||
11925                               !ckstrcmp(atmbuf,"a",1,0)) {
11926                               if ((x = cmcfm()) < 0) /* Get confirmation */
11927                                 return(x);
11928 			      prefixing = z ? PX_ALL : PX_NON;
11929 			      setprefix(prefixing);
11930 			      return(success = 1);
11931                           } else {	/* Not number, not ALL */
11932                               printf(
11933                                  "?Please specify a number or the word ALL\n");
11934                               return(-9);
11935                           }
11936                       } else {
11937                           if (p) free((char *)p);
11938                           return(x);
11939                       }
11940                   }
11941 #ifndef NOSPL
11942                   x_ifnum = 0;
11943 #endif /* NOSPL */
11944 #ifdef UNPREFIXZERO
11945                   zz = 0;
11946 #else
11947 #ifndef OS2
11948                   zz = 1 - z;
11949 #else
11950                   zz = 0;               /* Allow 0 (but only for Zmodem) */
11951 #endif /* OS2 */
11952 #endif /* UNPREFIXZERO */
11953 
11954             /* printf("x = %d, y = %d, z = %d, zz = %d\n", x,y,z,zz); */
11955 
11956                   if ((y >  31 && y < 127) || /* A specific numeric value */
11957                       (y > 159 && y < 255) || /* Check that it is a valid */
11958                       (y < zz) ||       /* control code. */
11959                       (y > 255)) {
11960                       printf("?Values allowed are: %d-31, 127-159, 255\n",zz);
11961                       if (p) free((char *)p);
11962                       return(-9);
11963                   }
11964                   x = y & 127;          /* Get 7-bit value */
11965                   if (z == 0) {         /* If they are saying it is safe... */
11966                       /* If flow control is Xon/Xoff */
11967                       if (((flow == FLO_XONX) &&
11968                            /* XON & XOFF chars not safe. */
11969                            (x == XON || x == XOFF))
11970                           ) {
11971                           if (msgflg)
11972                             printf(
11973                               "Sorry, not while Xon/Xoff is in effect.\n");
11974                           if (p) free((char *)p);
11975                           return(-9);
11976                       }
11977 #ifdef TNCODE
11978                       else if (network && IS_TELNET()
11979                                && (y == CR ||
11980                                    (unsigned) y == (unsigned) 255)) {
11981                           if (msgflg)
11982                             printf("Sorry, not on a TELNET connection.\n");
11983                           if (p) free((char *)p);
11984                           return(-9);
11985                       }
11986 #endif /* TNCODE */
11987                   }
11988                   p[y] = (char) z;      /* All OK, set flag */
11989               } /* End of while loop */
11990 /*
11991   Get here only if they have made no mistakes.  Copy temporary table back to
11992   permanent one, then free temporary table and return successfully.
11993 */
11994               for (i = 0; i < 256; i++) ctlp[i] = p[i];
11995               if (p) free((char *)p);
11996               if (z > 0) clearrq = 0;   /* 199 (see SET PREFIXING) */
11997               return(success = 1);
11998             default:
11999               return(-2);
12000           }
12001       }
12002 #endif /* CK_SPEED */
12003     }
12004 
12005     switch (xx) {
12006 
12007 #ifndef NOXFER
12008       case XYREPT:
12009         if ((y = cmkey(rpttab,2,
12010                        "repeat-count compression parameter","",xxstring)) < 0)
12011           return(y);
12012         switch(y) {
12013           case 0:
12014             return(success = seton(&rptena)); /* REPEAT COUNTS = ON, OFF */
12015           case 1:                       /* REPEAT MININUM number */
12016             printf("(not implemented yet, nothing happens)\n");
12017             return(-9);
12018           case 2:                       /* REPEAT PREFIX char */
12019             if ((x = cmnum("ASCII value","",10,&z,xxstring)) < 0)
12020               return(x);
12021             if ((x = cmcfm()) < 0) return(x);
12022             if ((z > 32 && z < 63) || (z > 95 && z < 127)) {
12023                 if (y == 1) rptmin = (CHAR) z; else myrptq = (CHAR) z;
12024                 return(success = 1);
12025             } else {
12026                 printf("?Illegal value for prefix character\n");
12027                 return(-9);
12028             }
12029         }
12030 #endif /* NOXFER */
12031 
12032 #ifndef NOSPL
12033       case XYALRM: {
12034 #ifndef COMMENT
12035           int yy;
12036           long zz;
12037           zz = -1L;
12038           yy = x_ifnum;
12039           x_ifnum = 1;                  /* Turn off internal complaints */
12040           y = cmnum("Seconds from now, or time of day as hh:mm:ss",
12041                     "0" ,10, &x, xxstring);
12042           x_ifnum = yy;
12043           if (y < 0) {
12044               if (y == -2) {            /* Invalid number or expression */
12045                   zz = tod2sec(atmbuf); /* Convert to secs since midnight */
12046                   if (zz < 0L) {
12047                       printf("?Number, expression, or time of day required\n");
12048                       return(-9);
12049                   } else {
12050                       char now[32];     /* Current time */
12051                       char *p;
12052                       long tnow;
12053                       p = now;
12054                       ztime(&p);
12055                       tnow = atol(p+11) * 3600L +
12056                         atol(p+14) * 60L + atol(p+17);
12057                       if (zz < tnow)    /* User's time before now */
12058                         zz += 86400L;   /* So make it tomorrow */
12059                       zz -= tnow;       /* Seconds from now. */
12060                   }
12061               } else
12062                 return(y);
12063           }
12064           if (x < 0) {
12065               printf("?Alarm time is in the past.\n");
12066               return(-9);
12067           }
12068           if ((y = cmcfm()) < 0) return(y);
12069           if (zz > -1L) {               /* Time of day given? */
12070               x = zz;
12071               if (zz != (long) x) {
12072                   printf(
12073 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
12074                          );
12075                   return(-9);
12076               }
12077           }
12078           return(setalarm((long)x));
12079       }
12080 #else
12081 /*
12082   This is to allow long values where int and long are not the same, e.g.
12083   on 16-bit systems.  But something is wrong with it.
12084 */
12085         if ((y = cmtxt("seconds from now", "0", &s, xxstring)) < 0)
12086           return(y);
12087         if (rdigits(s)) {
12088             return(setalarm(atol(s)));
12089         } else {
12090             printf("%s - not a number\n",s);
12091             return(-9);
12092         }
12093 #endif /* COMMENT */
12094 #endif /* NOSPL */
12095 
12096 #ifndef NOXFER
12097       case XYPROTO:
12098         return(setproto());
12099 #endif /* NOXFER */
12100 
12101 /*
12102   C-Kermit unprefixes control characters automatically on network connections
12103   if CLEAR-CHANNEL is ON, which it is by default.  But not all network
12104   connections are transparent to all control characters.  For example, the
12105   DEC-20, even when you TELNET to it, is sensitive to Ctrl-O and Ctrl-T.
12106   If you tell C-Kermit to SET CONTROL PREFIX 15 and/or 20, it doesn't help
12107   because CLEAR-CHANNEL is still in effect.  If the user goes to the trouble
12108   to set up some prefixing, then Kermit should do what the user said.  In
12109   C-Kermit 7.1 Alpha.03 we change the code to set clearrq to 0 if the user
12110   gives a SET PREFIXING or SET CONTROL PREFIX command.
12111 */
12112 
12113 #ifdef CK_SPEED
12114       case XYPREFIX: {
12115 #ifdef COMMENT
12116           extern int clearrq;
12117 #endif /* COMMENT */
12118           if ((z = cmkey(pfxtab, 4, "control-character prefixing option",
12119                          "", xxstring)) < 0)
12120             return(z);
12121           if ((x = cmcfm()) < 0) return(x);
12122           clearrq = 0;                  /* 199 */
12123           setprefix(z);
12124 #ifdef COMMENT
12125           if (hints && (z == PX_ALL || z == PX_CAU) && clearrq) {
12126         printf("Hint: Use SET CLEAR-CHANNEL OFF to disable negotiation of\n");
12127         printf("      SET PREFIXING NONE during file transfers on reliable\n");
12128         printf("      connections.\n");
12129           }
12130 #endif /* COMMENT */
12131           return(success = 1);
12132       }
12133 #endif /* CK_SPEED */
12134 
12135 #ifndef NOSPL
12136       case XYLOGIN:
12137         if ((z = cmkey(logintab, 3, "value for login script","userid",
12138                        xxstring)) < 0)
12139           return(z);
12140         x = cmdgquo();
12141         if (z == LOGI_PSW)
12142           cmdsquo(0);
12143         if ((y = cmtxt("text","",&s, (z == LOGI_PSW) ? NULL : xxstring)) < 0) {
12144             cmdsquo(x);
12145             return(y);
12146         }
12147         cmdsquo(x);
12148 #ifdef IKSD
12149         if (inserver)
12150           return(success = 0);
12151 #endif /* IKSD */
12152         s = brstrip(s);
12153         if ((int)strlen(s) > 63) {
12154             printf("Sorry, too long\n");
12155             return(-9);
12156         }
12157         switch(z) {
12158           case LOGI_UID:
12159             ckstrncpy(uidbuf,s,UIDBUFLEN);
12160             sl_uid_saved = 0;
12161             break;
12162           case LOGI_PSW:
12163             ckstrncpy(pwbuf,s,PWBUFL);
12164             if (pwbuf[0]) {
12165                 pwflg = 1;
12166 #ifdef OS2
12167                 pwcrypt = 1;
12168 #else /* OS2 */
12169                 pwcrypt = 0;
12170 #endif /* OS2 */
12171             }
12172             break;
12173           case LOGI_PRM:
12174             ckstrncpy(prmbuf,s,PWBUFL);
12175         }
12176         return(success = 1);
12177 #endif /* NOSPL */
12178     }
12179 
12180     switch (xx) {
12181 
12182       case XYSTARTUP:
12183         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
12184         if ((x = cmcfm()) < 0) return(x);
12185         DeleteStartupFile = (y != 0) ? 0 : 1;
12186         return(success = 1);
12187 
12188       case XYTMPDIR:
12189         x = cmdir("Name of temporary directory","",&s,xxstring);
12190         if (x == -3)
12191           s = "";
12192         else if (x < 0)
12193           return(x);
12194         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12195         if ((x = cmcfm()) < 0) return(x);
12196 #ifdef UNIX
12197         if (tmpbuf[0]) {
12198             extern int zchkod;
12199             char tmpname[MAXPATHLEN+1];
12200             char * p = tmpname;
12201             int x;
12202             zchkod = 1;                 /* Hack for asking zchko() if */
12203             x = zchko(tmpbuf);          /* a directory is writeable */
12204             zchkod = 0;
12205             if (x < 0) printf("WARNING: %s does not appear to be writable\n");
12206             zfnqfp(tmpbuf,MAXPATHLEN,p); /* Get and store full pathname */
12207             makestr(&tempdir,tmpname);
12208         }
12209 #else  /* No API for getting full pathname in other OS's */
12210         makestr(&tempdir,tmpbuf);
12211 #endif /* UNIX */
12212         return(tempdir ? 1 : 0);
12213 
12214 #ifndef NOXFER
12215       case XYDEST:                      /* DESTINATION */
12216         return(setdest());
12217 #endif /* NOXFER */
12218 
12219 #ifndef NOPUSH
12220 #ifndef NOFRILLS
12221 
12222 /* Editor, Browser, and FTP Client */
12223 
12224       case XYEDIT:                      /* EDITOR */
12225 #ifdef IKSD
12226         if (inserver) {
12227             printf("?Sorry, command disabled.\r\n");
12228             return(success = 0);
12229         }
12230 #endif /* IKSD */
12231 #ifdef CK_APC
12232         /* Don't let this be set remotely */
12233         if (apcactive == APC_LOCAL ||
12234             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12235           return(success = 0);
12236 #endif /* CK_APC */
12237 
12238 #ifdef OS2ORUNIX
12239         {
12240             char *p = getenv("PATH");
12241             char *e;
12242             e = editor[0] ? (char *) editor : getenv("EDITOR");
12243             if (!e) e = "";
12244             if (p)
12245               x = cmifip("Name of preferred editor",e,&s,&y,0,p,xxstring);
12246             else
12247               x = cmifi("Full path of preferred editor",e,&s,&y,xxstring);
12248             if (x < 0 && x != -3)
12249               return(x);
12250         }
12251 #else
12252 #ifdef VMS
12253         if ((y = cmtxt("DCL command for editing", "edit", &s, NULL)) < 0) {
12254             if (x != -3)
12255               return(x);
12256         }
12257 #else
12258         if ((x = cmifi("Full path of preferred editor","",&s,&y,xxstring))<0) {
12259             if (x != -3)
12260               return(x);
12261         }
12262 #endif /* VMS */
12263 #endif /* OS2ORUNIX */
12264 #ifdef VMS
12265         ckstrncpy(editor,s,CKMAXPATH);
12266         editopts[0] = NUL;
12267 #else
12268         if (y != 0) {
12269             printf("?A single file please\n");
12270             return(-2);
12271         }
12272         ckstrncpy(line,s,LINBUFSIZ);
12273         if ((x = cmtxt("editor command-line options","",&s,NULL)) < 0)
12274           return(x);
12275         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12276         if ((z = cmcfm()) < 0) return(z);
12277         if (line[0]) {
12278             zfnqfp(line,CKMAXPATH,editor);
12279             ckstrncpy(editopts,tmpbuf,128);
12280         } else {
12281             editor[0] = NUL;
12282             editopts[0] = NUL;
12283         }
12284 #endif /* VMS */
12285         return(success = 1);
12286 
12287 #ifndef NOFTP
12288 #ifndef SYSFTP
12289 #ifdef TCPSOCKET
12290       case XYFTPX:
12291         return(dosetftp());             /* SET FTP */
12292 #endif /* TCPSOCKET */
12293 #endif /* SYSFTP */
12294 #endif /* NOFTP */
12295 
12296 #ifdef BROWSER
12297 #ifndef NOFTP
12298 #ifdef SYSFTP
12299       case XYFTP:                       /* SET FTP-CLIENT */
12300 #endif /* SYSFTP */
12301 #endif /* NOFTP */
12302       case XYBROWSE:                    /* SET BROWSER */
12303         {
12304             char *p = getenv("PATH");
12305             char *app = (char *) browser, *opts = (char *) browsopts;
12306 #ifndef NOFTP
12307 #ifdef SYSFTP
12308             extern char ftpapp[], ftpopts[];
12309             if (xx == XYFTP) {
12310                 app = (char *)ftpapp;
12311                 opts = (char *)ftpopts;
12312             }
12313 #endif /* SYSFTP */
12314 #endif /* NOFTP */
12315 #ifdef IKSD
12316             if (inserver) {
12317                 printf("?Sorry, command disabled.\r\n");
12318                 return(success = 0);
12319             }
12320 #endif /* IKSD */
12321 #ifdef CK_APC
12322             /* Don't let this be set remotely */
12323             if (apcactive == APC_LOCAL ||
12324                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12325               return(success = 0);
12326 #endif /* CK_APC */
12327 #ifdef OS2ORUNIX
12328             if (p)
12329               x = cmifip(xx == XYBROWSE ?
12330                          "Name of preferred browser" :
12331                          "Name of preferred ftp client",
12332 #ifdef OS2
12333                          xx == XYFTP ? "ftp.exe" : ""
12334 #else
12335                          xx == XYFTP ? "ftp" : ""
12336 #endif /* OS2 */
12337                          ,&s,&y,0,p,xxstring
12338                          );
12339             else
12340               x = cmifi(xx == XYBROWSE ?
12341                         "Full path of preferred browser" :
12342                         "Full path of preferred ftp client",
12343                         "",&s,&y,xxstring
12344                         );
12345             if (x < 0 && x != -3)
12346               return(x);
12347 #else
12348 #ifdef VMS
12349             if ((x = cmtxt("DCL command to start your preferred Web browser",
12350                            "", &s, NULL)) < 0) {
12351                 if (x != -3)
12352                   return(x);
12353             }
12354 #else
12355             if ((x = cmifi("Full path of preferred browser","",&s,&y,xxstring)
12356                  ) < 0) {
12357                 if (x != -3)
12358                   return(x);
12359             }
12360 #endif /* VMS */
12361 #endif /* OS2ORUNIX */
12362 #ifdef VMS
12363             ckstrncpy(app,s,CKMAXPATH);
12364             *opts = NUL;
12365 #else
12366             if (y != 0) {
12367                 printf("?A single file please\n");
12368                 return(-2);
12369             }
12370             ckstrncpy(line,s,LINBUFSIZ);
12371             if ((x = cmtxt(xx == XYBROWSE ?
12372                            "browser command-line options" :
12373                            "ftp client command-line options",
12374                            "",&s,NULL)
12375                  ) < 0)
12376               return(x);
12377             ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12378             if ((z = cmcfm()) < 0) return(z);
12379             if (line[0]) {
12380                 zfnqfp(line,CKMAXPATH,app);
12381                 ckstrncpy(opts, tmpbuf, 128);
12382             } else {
12383                 *app = NUL;
12384                 *opts = NUL;
12385             }
12386 #endif /* VMS */
12387             return(success = 1);
12388         }
12389 #endif /* BROWSER */
12390 #endif /* NOFRILLS */
12391 #endif /* NOPUSH */
12392 
12393 #ifdef CK_CTRLZ
12394       case XYEOF: {                     /* SET EOF */
12395           extern int eofmethod; extern struct keytab eoftab[];
12396           if ((x = cmkey(eoftab,3,"end-of-file detection method","",
12397                          xxstring)) < 0)
12398             return(x);
12399           if ((y = cmcfm()) < 0)
12400             return(y);
12401           eofmethod = x;
12402           return(success = 1);
12403       }
12404 #endif /* CK_CTRLZ */
12405 
12406       case XYRELY: {                    /* SET RELIABLE */
12407           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12408             return(x);
12409           if ((y = cmcfm()) < 0) return(y);
12410           reliable = x;
12411           setreliable = (x != SET_AUTO);
12412           debug(F101,"SET RELIABLE reliable","",reliable);
12413           return(success = 1);
12414       }
12415 
12416 #ifdef STREAMING
12417       case XYSTREAM: {                  /* SET STREAMING */
12418           extern int streamrq;
12419           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12420             return(x);
12421           if ((y = cmcfm()) < 0) return(y);
12422           streamrq = x;
12423           return(success = 1);
12424       }
12425 #endif /* STREAMING */
12426 
12427 #ifdef CKSYSLOG
12428       case XYSYSL: {
12429           if ((x = cmkey(syslogtab,nsyslog,"","",xxstring)) < 0)
12430             return(x);
12431           if ((y = cmcfm()) < 0) return(y);
12432 #ifdef IKSD
12433           if (inserver &&
12434 #ifdef IKSDCONF
12435               iksdcf
12436 #else
12437               1
12438 #endif /* IKSDCONF */
12439               ) {
12440               printf("?Sorry, command disabled.\n");
12441               return(success = 0);
12442           }
12443 #endif /* IKSD */
12444 #ifdef CK_APC
12445           /* Don't let this be set remotely */
12446           if (apcactive == APC_LOCAL ||
12447               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12448             return(success = 0);
12449 #endif /* CK_APC */
12450           ckxsyslog = x;
12451           return(success = 1);
12452       }
12453 #endif /* CKSYSLOG */
12454 
12455 #ifdef TLOG
12456       case XYTLOG: {                    /* SET TRANSACTION-LOG */
12457           extern int tlogsep;
12458           if ((x = cmkey(vbtab,nvb,"","verbose",xxstring)) < 0)
12459             return(x);
12460           if (x == 0) {
12461               if ((y = cmtxt("field separator",",",&s,NULL)) < 0) return(y);
12462               s = brstrip(s);
12463               if (*s) {
12464                   if (s[1]) {
12465                       printf("?A single character, please.\n");
12466                       return(-9);
12467                   } else if ((*s >= '0' && *s <= '9') ||
12468                              (*s >= 'A' && *s <= 'Z') ||
12469                              (*s >= 'a' && *s <= 'z')) {
12470                       printf("?A non-alphanumeric character, please.\n");
12471                       return(-9);
12472                   } else
12473                     tlogsep = *s;
12474               }
12475           } else {
12476               if ((y = cmcfm()) < 0) return(y);
12477           }
12478 #ifdef IKSD
12479           if (inserver && isguest) {
12480               printf("?Sorry, command disabled.\n");
12481               return(success = 0);
12482           }
12483 #endif /* IKSD */
12484 #ifdef CK_APC
12485           /* Don't let this be set remotely */
12486           if (apcactive == APC_LOCAL ||
12487               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12488             return(success = 0);
12489 #endif /* CK_APC */
12490           tlogfmt = x;
12491           return(success = 1);
12492       }
12493 #endif /* TLOG */
12494 
12495       case XYCLEAR: {                   /* SET CLEARCHANNEL */
12496           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12497             return(x);
12498           if ((y = cmcfm()) < 0) return(y);
12499           clearrq = x;
12500           return(success = 1);
12501       }
12502 
12503 #ifdef CK_AUTHENTICATION
12504       case XYAUTH: {                    /* SET AUTHENTICATION */
12505 #ifdef CK_KERBEROS
12506           int kv = 0;
12507           extern struct krb_op_data krb_op;
12508 #endif /* CK_KERBEROS */
12509           char * p = NULL;
12510           if ((x =
12511                cmkey(setauth,nsetauth,"authentication type","",xxstring)) < 0)
12512             return(x);
12513           switch (x) {
12514 #ifdef CK_KERBEROS
12515             case AUTH_KRB4: kv = 4; break; /* Don't assume values are same */
12516             case AUTH_KRB5: kv = 5; break;
12517 #endif /* CK_KERBEROS */
12518 #ifdef CK_SRP
12519             case AUTH_SRP: break;
12520 #endif /* CK_SRP */
12521 #ifdef CK_SSL
12522             case AUTH_SSL:
12523             case AUTH_TLS:
12524               break;
12525 #endif /* CK_SSL */
12526             default:
12527               printf("?Authorization type not supported yet - \"%s\"\n",
12528                      atmbuf);
12529               return(-9);
12530           }
12531 #ifdef IKSD
12532           if (inserver &&
12533 #ifdef IKSDCONF
12534               iksdcf
12535 #else
12536               1
12537 #endif /* IKSDCONF */
12538               ) {
12539               if ((y = cmcfm()) < 0) return(y);
12540               printf("?Sorry, command disabled.\n");
12541               return(success = 0);
12542           }
12543 #endif /* IKSD */
12544 #ifdef CK_APC
12545           /* Don't let this be set remotely */
12546           if (apcactive == APC_LOCAL ||
12547               apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)) {
12548               if ((y = cmcfm()) < 0) return(y);
12549               return(success = 0);
12550           }
12551 #endif /* CK_APC */
12552 
12553           switch(x) {
12554 #ifdef CK_KERBEROS
12555             case AUTH_KRB4:
12556             case AUTH_KRB5: {
12557                 if ((x = cmkey(kv == 4 ? k4tab : k5tab,
12558                                kv == 4 ? nk4tab : nk5tab,
12559                                "Kerberos parameter","",xxstring)) < 0) {
12560                     return(x);
12561                 }
12562                 s = "";
12563                 switch (x) {
12564 #ifdef KRB4
12565                   case XYKRBDBG:
12566                     if (kv == 4) {
12567                         if ((y = seton(&k4debug)) < 0)
12568                           return(y);
12569 #ifdef NT
12570                         ck_krb4_debug(k4debug);
12571 #endif /* NT */
12572                     } else {
12573                         return(-9);
12574                     }
12575                     break;
12576 #endif /* KRB4 */
12577                   case XYKRBLIF:
12578                     if ((y = cmnum("TGT lifetime","600",10,&z,xxstring)) < 0)
12579                       return(y);
12580                     break;
12581                   case XYKRBPRE:
12582                     if (kv == 4) {
12583                         if ((y = seton(&krb4_d_preauth)) < 0)
12584                           return(y);
12585                     } else {
12586                         return(-9);
12587                     }
12588                     break;
12589                   case XYKRBINS:
12590                     if ((y = cmtxt("Instance name","",&s,xxstring)) < 0)
12591                       return(y);
12592                     break;
12593                   case XYKRBFWD:
12594                     if (kv == 5) {
12595                         if ((y = seton(&krb5_d_forwardable)) < 0)
12596                           return(y);
12597                     } else {
12598                         return(-9);
12599                     }
12600                     break;
12601                   case XYKRBPRX:
12602                     if (kv == 5) {
12603                         if ((y = seton(&krb5_d_proxiable)) < 0)
12604                           return(y);
12605                     } else {
12606                         return(-9);
12607                     }
12608                     break;
12609                   case XYKRBRNW:
12610                     if ((y = cmnum("TGT renewable lifetime",
12611                                    "0",10,&z,xxstring)) < 0)
12612                       return(y);
12613                     break;
12614                   case XYKRBADR:
12615                     if (kv == 5) {
12616                         if ((y = seton(&krb5_checkaddrs)) < 0)
12617                           return(y);
12618                     } else {
12619                         if ((y = seton(&krb4_checkaddrs)) < 0)
12620                           return(y);
12621                     }
12622                     break;
12623                   case XYKRBNAD:
12624                     if (kv == 5) {
12625                         if ((y = seton(&krb5_d_no_addresses)) < 0)
12626                           return(y);
12627                     }
12628                     break;
12629                   case XYKRBADD:
12630                     if (kv == 5) {
12631                         char * tmpaddrs[KRB5_NUM_OF_ADDRS];
12632                         for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
12633                           tmpaddrs[i] = NULL;
12634 
12635                         if ((y =
12636                              cmfld("List of IP addresses","",&s,xxstring)) < 0)
12637                           return(y);
12638                         makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
12639                         if ((y = cmcfm()) < 0) {
12640                             for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
12641                                 if (tmpaddrs[i] != NULL)
12642                                   free(tmpaddrs[i]);
12643                             }
12644                             return(y);
12645                         }
12646                         for (i = 0;
12647                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
12648                              i++) {
12649                             if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
12650                                 printf("invalid ip address: %s\n",
12651                                        tmpaddrs[i]);
12652                                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
12653                                     if (tmpaddrs[i] != NULL)
12654                                       free(tmpaddrs[i]);
12655                                 }
12656                                 return(-9);
12657                             }
12658                         }
12659                         for (i = 0;
12660                              i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];
12661                              i++) {
12662                             if (krb5_d_addrs[i])
12663                               free(krb5_d_addrs[i]);
12664                             krb5_d_addrs[i] = NULL;
12665                         }
12666                         for (i = 0;
12667                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
12668                              i++) {
12669                             krb5_d_addrs[i] = tmpaddrs[i];
12670                             tmpaddrs[i] = NULL;
12671                         }
12672                         krb5_d_addrs[i] = NULL;
12673                         return(success = 1);
12674                     }
12675                     break;
12676 
12677                   case XYKRBGET:
12678                     if (kv == 5) {
12679                         if ((y = seton(&krb5_autoget)) < 0)
12680                           return(y);
12681                     } else {
12682                         if ((y = seton(&krb4_autoget)) < 0)
12683                           return(y);
12684                     }
12685                     break;
12686                   case XYKRBDEL:
12687                     if ((z = cmkey(kdestab,nkdestab,
12688                                    "Auto Destroy Tickets",
12689                                    "never",xxstring)) < 0)
12690                       return(z);
12691                     break;
12692                   case XYKRBPR:
12693                     if ((y = cmtxt("User ID",uidbuf,&s,xxstring)) < 0)
12694                       return(y);
12695                     break;
12696                   case XYKRBRL:
12697                     if ((y = cmtxt("Name of realm","",&s,xxstring)) < 0)
12698                       return(y);
12699                     break;
12700                   case XYKRBKTB:
12701                     y = cmifi("Filename","",&s,&z,xxstring);
12702                     if (y != -3) {
12703                        if (y < 0)
12704                          return(y);
12705                        if (z) {
12706                          printf("?Wildcards not allowed\n");
12707                          return(-9);
12708                        }
12709                     }
12710                     break;
12711                   case XYKRBCC:
12712                     if ((y = cmofi("Filename","",&s,xxstring)) < 0)
12713                       return(y);
12714                     break;
12715                   case XYKRBSRV:
12716                     if ((y = cmtxt("Name of service to use in ticket",
12717                                    (kv == 4 ? "rcmd" : "host"),
12718                                    &s,
12719                                    xxstring
12720                                    )) < 0)
12721                       return(y);
12722                     break;
12723                   case XYKRBK5K4:
12724                     if (kv == 5) {
12725                         if ((y = seton(&krb5_d_getk4)) < 0)
12726                           return(y);
12727                     } else {
12728                         return(-9);
12729                     }
12730                     break;
12731                   case XYKRBPRM:        /* Prompt */
12732                     if ((z = cmkey(krbprmtab,2,"","",xxstring)) < 0)
12733                       return(z);
12734                     if ((y = cmtxt((z == KRB_PW_PRM) ?
12735   "Text of prompt;\nmay contain \"%s\" to be replaced by principal name" :
12736   "Text of prompt",
12737                                    "",
12738                                    &s,
12739                                    xxstring
12740                                    )
12741                          ) < 0)
12742                       return(y);
12743                     break;
12744                 }
12745                 ckstrncpy(line,s,LINBUFSIZ);
12746                 s = line;
12747                 if ((y = cmcfm()) < 0)
12748                   return(y);
12749 #ifdef IKSD
12750                 if (inserver &&
12751 #ifdef IKSDCONF
12752                     iksdcf
12753 #else /* IKSDCONF */
12754                     1
12755 #endif /* IKSDCONF */
12756                     )
12757                   return(success = 0);
12758 #endif /* IKSD */
12759 
12760                 switch (x) {            /* Copy value to right place */
12761                   case XYKRBLIF:        /* Lifetime */
12762                     if (kv == 4)
12763                       krb4_d_lifetime = z;
12764                     else
12765                       krb5_d_lifetime = z;
12766                     break;
12767                   case XYKRBRNW:
12768                     if (kv == 5)
12769                       krb5_d_renewable = z;
12770                     break;
12771                   case XYKRBPR:         /* Principal */
12772                     s = brstrip(s);	/* Strip braces around. */
12773                     if (kv == 4)
12774                       makestr(&krb4_d_principal,s);
12775                     else
12776                       makestr(&krb5_d_principal,s);
12777                     break;
12778                   case XYKRBINS:        /* Instance */
12779                     if (kv == 4)
12780                       makestr(&krb4_d_instance,s);
12781                     else
12782                       makestr(&krb5_d_instance,s);
12783                     break;
12784                   case XYKRBRL:         /* Realm */
12785                     if (kv == 4)
12786                       makestr(&krb4_d_realm,s);
12787                     else
12788                       makestr(&krb5_d_realm,s);
12789                     break;
12790                   case XYKRBKTB:        /* Key Table */
12791                     if (kv == 4)
12792                       makestr(&k4_keytab,s);
12793                     else
12794                       makestr(&k5_keytab,s);
12795                     break;
12796                   case XYKRBCC:         /* Credentials cache */
12797                     makestr(&krb5_d_cc,s);
12798                     break;
12799                   case XYKRBSRV:        /* Service Name */
12800                     if (kv == 4)
12801                       makestr(&krb4_d_srv,s);
12802                     else
12803                       makestr(&krb5_d_srv,s);
12804                     break;
12805                   case XYKRBDEL:
12806                     if (kv == 5)
12807                       krb5_autodel = z;
12808                     else
12809                       krb4_autodel = z;
12810                     break;
12811                   case XYKRBPRM:        /* Prompt */
12812 		    s = brstrip(s);
12813                     switch (z) {
12814                       case KRB_PW_PRM: { /* Password */
12815                           /* Check that there are no more than */
12816                           /* two % fields and % must followed by 's'. */
12817                           int i,n,len;
12818                           len = strlen(s);
12819                           for (i = 0, n = 0; i < len; i++) {
12820                               if (s[i] == '%') {
12821                                   if (s[i+1] != '%') {
12822                                       if (s[i+1] != 's') {
12823                                           printf(
12824                                            "Only %%s fields are permitted.\n"
12825                                                  );
12826                                           return(-9);
12827                                       }
12828                                       if (++n > 2) {
12829                                           printf(
12830                                       "Only two %%s fields are permitted.\n");
12831                                           return(-9);
12832                                       }
12833                                   }
12834                                   i++;
12835                               }
12836                           }
12837                           if (kv == 5)
12838                             makestr(&k5pwprompt,s);
12839                           else
12840                             makestr(&k4pwprompt,s);
12841                           break;
12842                       }
12843                       case KRB_PR_PRM: { /* Principal */
12844                           /* Check to make sure there are no % fields */
12845                           int i,len;
12846                           len = strlen(s);
12847                           for (i = 0; i < len; i++) {
12848                               if (s[i] == '%') {
12849                                   if (s[i+1] != '%') {
12850                                       printf(
12851                                   "%% fields are not used in this command.\n");
12852                                       return(-9);
12853                                   }
12854                                   i++;
12855                               }
12856                           }
12857                           if (kv == 5)
12858                             makestr(&k5prprompt,s);
12859                           else
12860                             makestr(&k4prprompt,s);
12861                           break;
12862                       }
12863                     }
12864                 }
12865                 break;
12866             }
12867 #endif /* CK_KERBEROS */
12868 #ifdef CK_SRP
12869             case AUTH_SRP: {
12870                 if ((x = cmkey(srptab, nsrptab,
12871                                "SRP parameter","",xxstring)) < 0) {
12872                     return(x);
12873                 }
12874                 s = "";
12875                 switch (x) {
12876                   case XYSRPPRM:        /* Prompt */
12877                     if ((z = cmkey(srpprmtab,1,"","",xxstring)) < 0)
12878                       return(z);
12879                     if ((y = cmtxt(
12880   "Text of prompt;\nmay contain one \"%s\" to be replaced by the username",
12881                                    "",
12882                                    &s,
12883                                    xxstring
12884                                    )
12885                          ) < 0)
12886                       return(y);
12887                     break;
12888                 }
12889                 ckstrncpy(line,s,LINBUFSIZ);
12890                 s = line;
12891                 if ((y = cmcfm()) < 0)
12892                   return(y);
12893                 switch (x) {            /* Copy value to right place */
12894                   case XYSRPPRM:        /* Prompt */
12895 		    s = brstrip(s);
12896                     switch (z) {
12897                       case SRP_PW_PRM: { /* Password */
12898                           /* Check %s fields */
12899                           int i,n,len;
12900                           len = strlen(s);
12901                           for (i = 0, n = 0; i < len; i++) {
12902                               if (s[i] == '%') {
12903                                   if (s[i+1] != '%') {
12904                                       if (s[i+1] != 's') {
12905                                           printf(
12906                                           "Only %%s fields are permitted.\n");
12907                                           return(-9);
12908                                       }
12909                                       if (++n > 1) {
12910                                           printf(
12911                                        "Only one %%s field is permitted.\n");
12912                                           return(-9);
12913                                       }
12914                                   }
12915                                   i++;
12916                               }
12917                           }
12918                           makestr(&srppwprompt,s);
12919                           break;
12920                       }
12921                     }
12922                 }
12923                 break;
12924             }
12925 #endif /* CK_SRP */
12926 #ifdef CK_SSL
12927             case AUTH_SSL:
12928             case AUTH_TLS: {
12929                 if ((z = cmkey(ssltab, nssltab,
12930                            (x == AUTH_SSL ? "SSL parameter" : "TLS parameter"),
12931                            "",xxstring)) < 0)
12932                   return(z);
12933                 s = "";
12934                 switch (z) {
12935                   case XYSSLRCFL:       /* SSL/TLS RSA Certs file */
12936                   case XYSSLRCCF:       /* SSL/TLS RSA Certs Chain file */
12937                   case XYSSLRKFL:       /* SSL/TLS RSA Key File */
12938                   case XYSSLDCFL:       /* SSL/TLS DSA Certs file */
12939                   case XYSSLDCCF:       /* SSL/TLS DSA Certs Chain file */
12940                   case XYSSLDKFL:       /* SSL/TLS DH Key File */
12941                   case XYSSLDPFL:       /* SSL/TLS DH Param File */
12942                   case XYSSLCRL:        /* SSL/TLS CRL File */
12943                   case XYSSLVRFF:       /* SSL/TLS Verify File */
12944                   case XYSSLRND:        /* SSL/TLS Random File */
12945                     y = cmifi("Filename","",&s,&x,xxstring);
12946                     if (y != -3) {
12947                         if (y < 0)
12948                           return(y);
12949                         if (x) {
12950                             printf("?Wildcards not allowed\n");
12951                             return(-9);
12952                         }
12953                     }
12954                     ckstrncpy(line,s,LINBUFSIZ);
12955                     s = line;
12956                     s = brstrip(s);
12957                     if ((y = cmcfm()) < 0)
12958                       return(y);
12959                     switch (z) {
12960                       case XYSSLRCFL:   /* SSL/TLS RSA Certs file */
12961                         if (!s[0] && ssl_rsa_cert_file) {
12962                             free(ssl_rsa_cert_file);
12963                             ssl_rsa_cert_file = NULL;
12964                         } else if (s[0]) {
12965                             makestr(&ssl_rsa_cert_file,s);
12966                             if (!ssl_rsa_key_file)
12967                               makestr(&ssl_rsa_key_file,s);
12968                         }
12969                         break;
12970                       case XYSSLRCCF:   /* SSL/TLS RSA Certs Chain file */
12971                           if (!s[0] && ssl_rsa_cert_chain_file) {
12972                               free(ssl_rsa_cert_chain_file);
12973                               ssl_rsa_cert_chain_file = NULL;
12974                           } else if (s[0]) {
12975                               makestr(&ssl_rsa_cert_chain_file,s);
12976                           }
12977                           break;
12978                       case XYSSLRKFL:   /* SSL/TLS RSA Key File */
12979                         if (!s[0] && ssl_rsa_key_file) {
12980                             free(ssl_rsa_key_file);
12981                             ssl_rsa_key_file = NULL;
12982                         } else if (s[0]) {
12983                             makestr(&ssl_rsa_key_file,s);
12984                         }
12985                         break;
12986                       case XYSSLDCFL:   /* SSL/TLS DSA Certs file */
12987                         if (!s[0] && ssl_dsa_cert_file) {
12988                             free(ssl_dsa_cert_file);
12989                             ssl_dsa_cert_file = NULL;
12990                         } else if (s[0]) {
12991                             makestr(&ssl_dsa_cert_file,s);
12992                             if (!ssl_dh_key_file)
12993                               makestr(&ssl_dh_key_file,s);
12994                         }
12995                         break;
12996                       case XYSSLDCCF:   /* SSL/TLS DSA Certs Chain file */
12997                           if (!s[0] && ssl_dsa_cert_chain_file) {
12998                               free(ssl_dsa_cert_chain_file);
12999                               ssl_dsa_cert_chain_file = NULL;
13000                           } else if (s[0]) {
13001                               makestr(&ssl_dsa_cert_chain_file,s);
13002                           }
13003                           break;
13004                       case XYSSLDKFL:   /* SSL/TLS DH Key File */
13005                         if (!s[0] && ssl_dh_key_file) {
13006                             free(ssl_dh_key_file);
13007                             ssl_dh_key_file = NULL;
13008                         } else if (s[0]) {
13009                             makestr(&ssl_dh_key_file,s);
13010                         }
13011                         break;
13012                       case XYSSLDPFL:   /* SSL/TLS DH Param File */
13013                         if (!s[0] && ssl_dh_param_file) {
13014                             free(ssl_dh_param_file);
13015                             ssl_dh_param_file = NULL;
13016                         } else if (s[0]) {
13017                             makestr(&ssl_dh_param_file,s);
13018                         }
13019                         break;
13020                       case XYSSLCRL:    /* SSL/TLS CRL File */
13021                         if (!s[0] && ssl_crl_file) {
13022                             free(ssl_crl_file);
13023                             ssl_crl_file = NULL;
13024                         } else if (s[0]) {
13025                             makestr(&ssl_crl_file,s);
13026                         }
13027                         break;
13028                       case XYSSLVRFF:   /* SSL/TLS Verify File */
13029                         if (!s[0] && ssl_verify_file) {
13030                             free(ssl_verify_file);
13031                             ssl_verify_file = NULL;
13032                         } else if (s[0]) {
13033                             makestr(&ssl_verify_file,s);
13034                         }
13035                         break;
13036                       case XYSSLRND:    /* SSL/TLS Random File */
13037                         if (!s[0] && ssl_rnd_file) {
13038                             free(ssl_rnd_file);
13039                             ssl_rnd_file = NULL;
13040                         } else if (s[0]) {
13041                             makestr(&ssl_rnd_file,s);
13042                         }
13043                         break;
13044                     }
13045                     break;
13046 
13047                   case XYSSLCRLD:
13048                   case XYSSLVRFD: {
13049                     char * d = NULL;
13050                     if (z == XYSSLVRFD)
13051                       d= getenv("SSL_CERT_DIR");
13052                     if (d == NULL)
13053                         d = "";
13054                     if ((y = cmdir("Directory",d,&s,xxstring)) < 0)
13055 		      if (y != -3)
13056 			return(y);
13057                     ckstrncpy(line,s,LINBUFSIZ);
13058                     s = line;
13059                     s = brstrip(s);
13060                     if ((y = cmcfm()) < 0)
13061                       return(y);
13062                     switch(z) {
13063                       case XYSSLCRLD:
13064                         if (!s[0] && ssl_crl_dir) {
13065                             free(ssl_crl_dir);
13066                             ssl_crl_dir = NULL;
13067                         } else if (s[0]) {
13068                             makestr(&ssl_crl_dir,s);
13069                         }
13070                         break;
13071                       case XYSSLVRFD:
13072                         if (!s[0] && ssl_verify_dir) {
13073                             free(ssl_verify_dir);
13074                             ssl_verify_dir = NULL;
13075                         } else if (s[0]) {
13076                             makestr(&ssl_verify_dir,s);
13077                         }
13078                         break;
13079                     }
13080                     break;
13081                   }
13082                   case XYSSLCOK:        /* SSL/TLS Certs-Ok flag */
13083                     if ((y = seton(&ssl_certsok_flag)) < 0)
13084                       return(y);
13085                     break;
13086                   case XYSSLDBG:                /* SSL/TLS Debug flag */
13087                     if ((y = seton(&ssl_debug_flag)) < 0)
13088                       return(y);
13089                     break;
13090                   case XYSSLON:         /* SSL/TLS Only flag */
13091                     switch (x) {
13092                       case AUTH_SSL:
13093                         if ((y = seton(&ssl_only_flag)) < 0)
13094                           return(y);
13095                         break;
13096                       case AUTH_TLS:
13097                         if ((y = seton(&tls_only_flag)) < 0)
13098                           return(y);
13099                         break;
13100                     }
13101                     break;
13102                   case XYSSLVRB:        /* SSL/TLS Verbose flag */
13103                     if ((y = seton(&ssl_verbose_flag)) < 0)
13104                       return(y);
13105                     break;
13106                   case XYSSLVRF:        /* SSL/TLS Verify flag */
13107                     if ((x = cmkey(sslvertab, nsslvertab,
13108                                    "SSL/TLS verify mode",
13109                                    "peer-cert",xxstring)) < 0)
13110                       return(x);
13111                     if ((y = cmcfm()) < 0)
13112                       return(y);
13113                     ssl_verify_flag = x;
13114                     break;
13115                   case XYSSLDUM:
13116                     if ((y = seton(&ssl_dummy_flag)) < 0)
13117                       return(y);
13118                     break;
13119                   case XYSSLCL: {               /* SSL/TLS Cipher List */
13120 #ifdef COMMENT
13121                       /* This code is used to generate a colon delimited */
13122                       /* list of the ciphers currently in use to be used */
13123                       /* as the default for cmtxt().  However, a better  */
13124                       /* default is simply the magic keyword "ALL".      */
13125                       CHAR def[1024] = "";
13126                       if (ssl_con != NULL) {
13127                           CHAR * p = NULL, *q = def;
13128                           int i, len;
13129 
13130                           for (i = 0; ; i++) {
13131                               p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
13132                               if (p == NULL)
13133                                 break;
13134                               len = strlen(p);
13135                               if (q+len+1 >= def+1024)
13136                                 break;
13137                               if (i != 0)
13138                                 *q++ = ':';
13139                               strcpy(q,p);
13140                               q += len;
13141                           }
13142                       }
13143 #endif /* COMMENT */
13144                       char * p = getenv("SSL_CIPHER");
13145                       if (!p)
13146                         p = "ALL";
13147                       if ((y = cmtxt(
13148                     "Colon-delimited list of ciphers or ALL (case-sensitive)",
13149                                      p,
13150                                      &s,
13151                                      xxstring
13152                                      )
13153                            ) < 0)
13154                         return(y);
13155                       makestr(&ssl_cipher_list,s);
13156                       if (ssl_con == NULL) {
13157                           SSL_library_init();
13158                           ssl_ctx = (SSL_CTX *)
13159 /* Changed in 9.0.305 Alpha.03 from NetBSD 'rhialto' */
13160 /* from: SSL_CTX_new((SSL_METHOD *)TLSv1_method()); to:...*/
13161                             SSL_CTX_new((SSL_METHOD *)SSLv23_method());
13162                           if (ssl_ctx != NULL)
13163                             ssl_con= (SSL *) SSL_new(ssl_ctx);
13164                       }
13165                       if (ssl_con) {
13166                           SSL_set_cipher_list(ssl_con,ssl_cipher_list);
13167                       }
13168                       break;
13169                   }
13170                 }
13171                 break;
13172             }
13173 #endif /* CK_SSL */
13174             default:
13175               break;
13176           }
13177           return(success = 1);
13178       }
13179 #endif /* CK_AUTHENTICATION */
13180 
13181 #ifndef NOSPL
13182       case XYFUNC:
13183         if ((x = cmkey(functab,nfunctab,"","diagnostics",xxstring)) < 0)
13184           return(x);
13185         switch (x) {
13186           case FUNC_DI: return(seton(&fndiags));
13187           case FUNC_ER: return(seton(&fnerror));
13188           default:      return(-2);
13189         }
13190 #endif /* NOSPL */
13191 
13192       case XYSLEEP:                     /* SET SLEEP / PAUSE */
13193         if ((x = cmkey(sleeptab,1,"","cancellation",xxstring)) < 0)
13194           return(x);
13195         return(seton(&sleepcan));
13196 
13197       case XYCD:                        /* SET CD */
13198         if ((x = cmkey(cdtab,ncdtab,"","",xxstring)) < 0)
13199           return(x);
13200         switch (x) {
13201 	  case XYCD_H: {		/* SET CD HOME */
13202 	      extern char * myhome;
13203 	      if ((y = cmdir("Directory name",zhome(),&s,xxstring)) < 0)
13204 		return(y);
13205 	      makestr(&myhome,s);
13206 	      return(success = 1);
13207 	  }
13208           case XYCD_M:                  /* SET CD MESSAGE */
13209             if ((x = cmkey(cdmsg,ncdmsg,"","",xxstring)) < 0)
13210               return(x);
13211             if (x == 2) {               /* CD MESSAGE FILE */
13212                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
13213                   return(x);
13214                 if (!*s) {
13215                     s = NULL;
13216 #ifndef NOXFER
13217                     srvcdmsg = 0;
13218 #endif /* NOXFER */
13219                 }
13220                 makestr(&cdmsgstr,s);
13221                 makelist(cdmsgstr,cdmsgfile,8);
13222                 return(success = 1);
13223             }
13224 
13225             if ((y = cmcfm()) < 0) return(y); /* CD-MESSAGE ON/OFF */
13226 #ifndef NOXFER
13227             if (x > 0)
13228               srvcdmsg |= 2;
13229             else
13230               srvcdmsg &= 1;
13231 #endif /* NOXFER */
13232             return(success = 1);
13233 
13234           case XYCD_P: {                /* SET CD PATH */
13235               extern char * ckcdpath;
13236               if ((x = cmtxt("CD PATH string","",&s,xxstring)) < 0)
13237                 return(x);
13238               makestr(&ckcdpath,s);
13239               return(success = 1);
13240           }
13241         }
13242 
13243 #ifndef NOLOCAL
13244 #ifdef STOPBITS
13245       case XYSTOP:                      /* STOP-BITS */
13246         if ((x = cmkey(stoptbl,2,"Stop bits for serial device","",
13247                        xxstring)) < 0)
13248           return(x);
13249         if ((y = cmcfm()) < 0)
13250           return(y);
13251         if (x > 0 && x < 3) {
13252             stopbits = x;
13253 #ifdef TN_COMPORT
13254             if (network && istncomport()) {
13255                 tnsettings(-1, x);
13256                 return(success = 1);
13257             }
13258 #endif /* TN_COMPORT */
13259 #ifdef HWPARITY
13260             return(success = 1);
13261 #else /* HWPARITY */
13262             return(-2);
13263 #endif /* HWPARITY */
13264         } else
13265           return(-2);
13266 #endif /* STOPBITS */
13267 
13268       case XYDISC: {
13269           extern int clsondisc;
13270           return(seton(&clsondisc));
13271       }
13272 
13273       case XYSERIAL: {
13274           /* char c; */
13275           extern int cmask;
13276           if ((x = cmkey(sertbl,nsertbl,
13277                          "Serial device character size, parity, and stop bits",
13278                          "8N1", xxstring)) < 0)
13279             return(x);
13280           ckstrncpy(line,atmbuf,LINBUFSIZ); /* Associated keyword string */
13281           s = line;
13282           if ((y = cmcfm()) < 0)
13283             return(y);
13284           ckstrncpy(line,sernam[x],LINBUFSIZ);
13285           s = line;
13286           if (s[0] != '8' && s[0] != '7') /* Char size */
13287             return(-2);
13288           else
13289             z = s[0] - '0';
13290           if (isupper(s[1]))            /* Parity */
13291             s[1] = tolower(s[1]);
13292           if (s[2] != '1' && s[2] != '2') /* Stop bits */
13293             return(-2);
13294           else
13295             stopbits = s[2] - '0';
13296           if (z == 8) {                 /* 8 bits + parity (or not) */
13297               parity = 0;               /* Set parity */
13298               hwparity = (s[1] == 'n') ? 0 : s[1];
13299               setcmask(8);              /* Also set TERM BYTESIZE to 8 */
13300           } else {                      /* 7 bits plus parity */
13301               parity = (s[1] == 'n') ? 0 : s[1];
13302               hwparity = 0;
13303               setcmask(7);              /* Also set TERM BYTESIZE to 7 */
13304           }
13305 #ifdef TN_COMPORT
13306           if (network && !istncomport())
13307             tnsettings(parity, stopbits);
13308 #endif /* TN_COMPORT */
13309 
13310           return(success = 1);          /* from SET SERIAL */
13311       }
13312 
13313       case XYOPTS: {                    /* SET OPTIONS */
13314           extern int setdiropts();
13315           extern int settypopts();
13316 #ifdef CKPURGE
13317           extern int setpurgopts();
13318 #endif /* CKPURGE */
13319           if ((x = cmkey(optstab,noptstab,"for command","", xxstring)) < 0)
13320             return(x);
13321           switch (x) {
13322 #ifndef NOFRILLS
13323             case XXDEL:
13324               return(setdelopts());
13325 #endif /* NOFRILLS */
13326             case XXDIR:
13327               return(setdiropts());
13328             case XXTYP:
13329               return(settypopts());
13330 #ifdef CKPURGE
13331             case XXPURGE:
13332               return(setpurgopts());
13333 #endif /* CKPURGE */
13334             default:
13335               return(-2);
13336           }
13337       }
13338 #endif /* NOLOCAL */
13339 #ifndef NOXFER
13340       case XYQ8FLG: {
13341           extern int q8flag;
13342           return(seton(&q8flag));
13343       }
13344       case XYTIMER: {
13345           extern int asktimer;
13346           y = cmnum("Time limit for ASK command, seconds","0",10,&x,xxstring);
13347 #ifdef QNX16
13348           return(setnum(&asktimer,x,y,32767));
13349 #else
13350           return(setnum(&asktimer,x,y,86400));
13351 #endif /* QNX16 */
13352       }
13353       case XYFACKB: {
13354           extern int fackbug;
13355           return(seton(&fackbug));
13356       }
13357 #endif /* NOXFER */
13358 
13359       case XYHINTS:
13360         return(seton(&hints));
13361 
13362 #ifndef NOSPL
13363       case XYEVAL: {
13364           extern int oldeval;
13365           if ((x = cmkey(oldnew,2,"","", xxstring)) < 0)
13366             return(x);
13367           if ((y = cmcfm()) < 0)
13368             return(y);
13369           oldeval = x;
13370           return(success = 1);
13371       }
13372 #endif /* NOSPL */
13373 
13374 #ifndef NOXFER
13375       case XYFACKP: {
13376           extern int fackpath;
13377           return(seton(&fackpath));
13378       }
13379 #endif /* NOXFER */
13380 
13381       case XYQNXPL: {
13382           extern int qnxportlock;
13383           return(seton(&qnxportlock));
13384       }
13385 
13386 #ifndef NOCMDL
13387 #ifdef IKSD
13388       case XYIKS: {
13389           int setiks();
13390           return(setiks());
13391       }
13392 #endif /* IKSD */
13393 #endif /* NOCMDL */
13394 
13395 #ifdef CKROOT
13396       case XYROOT:
13397         return(dochroot());
13398 #endif /* CKROOT */
13399 
13400 #ifndef NOSPL
13401 #ifndef NOSEXP
13402       case XYSEXP: {
13403           if ((x = cmkey(sexptab,3,"","", xxstring)) < 0)
13404             return(x);
13405           switch (x) {
13406             case 0:
13407               if ((x = cmkey(ooatab,3,"","automatic", xxstring)) < 0)
13408                 return(x);
13409               if ((y = cmcfm()) < 0)
13410                 return(y);
13411               sexpecho = x;
13412               break;
13413             case 1: {
13414                 int i, xx;
13415                 xx = sexpmaxdep;
13416                 if ((y = cmnum("Maximum recursion depth",
13417                                "1000",10,&x,xxstring)) < 0)
13418                   return(y);
13419                 z = setnum(&sexpmaxdep,x,y,-1);
13420                 if (z < 0)
13421                   return(z);
13422                 if (sxresult) {         /* Free old stack if allocated */
13423                     for (i = 0; i < xx; i++)
13424                       if (sxresult[i]) free(sxresult[i]);
13425                     free((char *)sxresult);
13426                     if (sxrlen) free((char *)sxrlen);
13427                     sxresult = NULL;
13428                     sxrlen = NULL;
13429                 }
13430                 break;
13431             }
13432 	    case 2:
13433 	      return(seton(&sexptrunc));
13434           }
13435           return(success = 1);
13436       }
13437 #endif /* NOSEXPL */
13438 #endif /* NOSPL */
13439 
13440 #ifdef NEWFTP
13441       case XYGPR: {
13442           extern struct keytab gprtab[];
13443           extern int ftpget;
13444           if ((x = cmkey(gprtab,3,"","kermit", xxstring)) < 0)
13445             return(x);
13446           if ((y = cmcfm()) < 0)
13447             return(y);
13448           ftpget = x;
13449           return(success = 1);
13450       }
13451 #endif /* NEWFTP */
13452 
13453 #ifdef ANYSSH
13454       case XYSSH:
13455         return(dosetssh());
13456 #endif /* ANYSHH */
13457 
13458 #ifdef SFTP_BUILTIN
13459       case XYSFTP:
13460         return(dosetsftp());
13461 #endif /* SFTP_BUILTIN */
13462 
13463 #ifdef LOCUS
13464       case XYLOCUS:
13465           if ((x = cmkey(locustab,nlocustab,"",
13466 #ifdef KUI
13467 			 "ask"
13468 #else
13469 			 "auto"
13470 #endif /* KUI */
13471 			 ,xxstring)) < 0)
13472             return(x);
13473           if ((y = cmcfm()) < 0)
13474             return(y);
13475           if (x == 2 || x == 3) {	/* AUTO or ASK */
13476               setautolocus(x - 1);	/* Two forms of automatic locusing */
13477 	      /* setlocus(1,0); */      /* we're not changing the locus here */
13478           } else {			/* LOCAL or REMOTE */
13479               setautolocus(0);		/* No automatic Locus changing */
13480               setlocus(x,0);		/* Set Locus as requested */
13481           }
13482           return(success = 1);
13483 #endif /* LOCUS */
13484 
13485 #ifdef KUI
13486       case XYGUI:
13487         return(setgui());
13488 #endif /* KUI */
13489 
13490 #ifndef NOFRILLS
13491 #ifndef NORENAME
13492       case XY_REN:			/* SET RENAME */
13493 	return(setrename());
13494 #endif	/* NORENAME */
13495 #endif	/* NOFRILLS */
13496 
13497 #ifndef NOPUSH
13498 #ifdef CK_REDIR
13499 #ifndef NOXFER
13500       case XYEXTRN:			/* SET EXTERNAL-PROTOCOL */
13501 	return(setextern());
13502 #endif	/* NOXFER */
13503 #endif	/* CK_REDIR */
13504 #endif	/* NOPUSH */
13505 
13506 #ifndef NOSPL
13507       case XYVAREV:			/* SET VARIABLE-EVALUATION */
13508 	return(setvareval());
13509 #endif /* NOSPL */
13510 
13511 #ifdef HAVE_LOCALE
13512       case XYLOCALE:
13513 	if ((x = cmtxt("Locale string","C",&s,xxstring)) < 0)
13514 	  return(x);
13515 	setlocale(LC_ALL, "");
13516 	setlocale(LC_ALL, s);
13517 	if (!setlocale(LC_ALL,NULL)) {
13518 	    printf("Warning: setlocale(%s) error: %s\n", s, ck_errstr());
13519 	}
13520 
13521 #ifdef COMMENT
13522 	if (!setlocale(LC_COLLATE, s))  {perror("COLLATE");return(success=0);}
13523 	if (!setlocale(LC_CTYPE, s))    {perror("CTYPE");return(success=0);}
13524 	if (!setlocale(LC_MESSAGES, s)) {perror("MESSAGES");return(success=0);}
13525 	if (!setlocale(LC_MONETARY, s)) {perror("MONETARY");return(success=0);}
13526 	if (!setlocale(LC_NUMERIC, s))  {perror("NUMERIC");return(success=0);}
13527 	if (!setlocale(LC_TIME, s))     {perror("TIME");return(success=0);}
13528 #endif /* COMMENT */
13529 	return(success=1);
13530 #endif /* HAVE_LOCALE */
13531 
13532       default:
13533          if ((x = cmcfm()) < 0) return(x);
13534          printf("Not implemented - %s\n",cmdbuf);
13535          return(success = 0);
13536     }
13537 }
13538 
13539 /*
13540   H U P O K  --  Is Hangup OK?
13541 
13542   Issues a warning and gets OK from user depending on whether a connection
13543   seems to be open and what the SET EXIT WARNING setting is.  Returns:
13544     0 if not OK to hang up or exit (i.e. user said No);
13545     nonzero if OK.
13546   Argument x is used to differentiate the EXIT command from SET LINE / HOST.
13547 */
13548 int
13549 hupok(x) int x; {                       /* Returns 1 if OK, 0 if not OK */
13550     int y, z = 1;
13551     extern int exithangup;
13552 #ifdef VMS
13553     extern int batch;
13554 
13555     if (batch)                          /* No warnings in batch */
13556       return(1);
13557 #else
13558 #ifdef UNIX
13559     if (backgrd)                        /* No warnings in background */
13560       return(1);
13561 #endif /* UNIX */
13562 #endif /* VMS */
13563 
13564 #ifndef K95G
13565     debug(F101,"hupok local","",local);
13566 
13567     if (!local)                         /* No warnings in remote mode */
13568       return(1);
13569 #endif /* K95G */
13570 
13571     if (x == 0 && exithangup == 0)      /* EXIT and EXIT HANGUP is OFF */
13572       return(1);
13573 
13574     debug(F101,"hupok x","",x);
13575     debug(F101,"hupok xitwarn","",xitwarn);
13576     debug(F101,"hupok network","",network);
13577     debug(F101,"hupok haveline","",haveline);
13578 
13579     if ((local && xitwarn) ||           /* Is a connection open? */
13580         (!x && xitwarn == 2)) {         /* Or Always give warning on EXIT */
13581         int needwarn = 0;
13582         char warning[256];
13583 
13584         if (network) {
13585             if (ttchk() >= 0)
13586               needwarn = 1;
13587             /* A connection seems to be open but it can't possibly be */
13588             if (!haveline)
13589               needwarn = 0;
13590             if (needwarn) {
13591                 if (strcmp(ttname,"*"))
13592                     ckmakmsg(warning,256,
13593                               " A network connection to ",ttname,
13594                               " might still be active.\n",NULL);
13595                 else
13596                   ckstrncpy(warning,
13597                    " An incoming network connection might still be active.\n",
13598                              256);
13599             }
13600         } else {                        /* Serial connection */
13601             if (carrier == CAR_OFF)     /* SET CARRIER OFF */
13602               needwarn = 0;             /* so we don't care about carrier. */
13603             else if ((y = ttgmdm()) >= 0) /* else, get modem signals */
13604               needwarn = (y & BM_DCD);  /* Check for carrier */
13605             else                        /* If we can't get modem signals... */
13606               needwarn = (ttchk() >= 0);
13607             /* A connection seems to be open but it can't possibly be */
13608             if (!haveline || !exithangup)
13609               needwarn = 0;
13610             if (needwarn)
13611                 ckmakmsg(warning,256,
13612                      " A serial connection might still be active on ",
13613                      ttname,".\n",NULL);
13614         }
13615 
13616 /* If a warning was issued, get user's permission to EXIT. */
13617 
13618         if (needwarn || (!x && xitwarn == 2
13619 #ifndef K95G
13620 			&& local
13621 #endif /* K95G */
13622 			 )) {
13623             if ( !needwarn )
13624                 ckstrncpy(warning, "No active connections", 256);
13625 
13626 #ifdef COMMENT
13627 	    printf("%s",warning);
13628             z = getyesno(x ? "OK to close? " : "OK to exit? ",0);
13629             debug(F101,"hupok getyesno","",z);
13630             if (z < -3) z = 0;
13631 #else
13632 	    z = uq_ok(warning,
13633 		      x ? "OK to close? " : "OK to exit? ",
13634 		      3,
13635 		      NULL,
13636 		      0
13637 		      );
13638             debug(F101,"hupok uq_ok","",z);
13639 	    if (z < 0) z = 0;
13640 #endif /* COMMENT */
13641         }
13642     }
13643     return(z);
13644 }
13645 
13646 #ifndef NOSHOW
13647 VOID
13648 shoctl() {                              /* SHOW CONTROL-PREFIXING */
13649 #ifdef CK_SPEED
13650     int i;
13651 #ifdef OS2
13652     int zero;
13653 #endif /* OS2 */
13654     printf(
13655 "\ncontrol quote = %d, applied to (0 = unprefixed, 1 = prefixed):\n\n",
13656            myctlq);
13657 #ifdef OS2
13658 #ifndef UNPREFIXZERO
13659     zero = ctlp[0];
13660     if (protocol == PROTO_K)            /* Zero can't be unprefixed */
13661       ctlp[0] = 1;                      /* for Kermit */
13662 #endif /* UNPREFIXZERO */
13663 #endif /* OS2 */
13664     for (i = 0; i < 16; i++) {
13665         printf("  %3d: %d   %3d: %d ",i,ctlp[i], i+16, ctlp[i+16]);
13666         if (i == 15)
13667           printf("  127: %d",ctlp[127]);
13668         else
13669           printf("        ");
13670         printf("  %3d: %d   %3d: %d ",i+128,ctlp[i+128], i+144, ctlp[i+144]);
13671         if (i == 15)  printf("  255: %d",ctlp[255]);
13672         printf("\n");
13673     }
13674     printf("\n");
13675 #ifndef UNPREFIXZERO
13676 #ifdef OS2
13677     ctlp[0] = zero;
13678 #endif /* OS2 */
13679 #endif /* UNPREFIXZERO */
13680 
13681 #endif /* CK_SPEED */
13682 }
13683 
13684 #ifndef NOXFER
13685 VOID
13686 shodbl() {                              /* SHOW DOUBLE/IGNORE */
13687 #ifdef CKXXCHAR
13688     int i, n = 0;
13689     printf("\nSET SEND DOUBLE characters:\n");
13690     for (i = 0; i < 255; i++) {
13691         if (dblt[i] & 2) {
13692             n++;
13693             printf(" %d", i);
13694         }
13695     }
13696     if (n == 0)
13697       printf(" (none)");
13698     n = 0;
13699     printf("\nSET RECEIVE IGNORE characters:\n");
13700     for (i = 0; i < 255; i++) {
13701         if (dblt[i] & 1) {
13702             n++;
13703             printf(" %d", i);
13704         }
13705     }
13706     if (n == 0)
13707       printf(" (none)");
13708     printf("\n\n");
13709 #endif /* CKXXCHAR */
13710 }
13711 #endif /* NOXFER */
13712 #endif /* NOSHOW */
13713 
13714 #ifndef NOPUSH
13715 #ifdef CK_REXX
13716 /*
13717   Rexx command.  Note, this is not OS/2-specific, because Rexx also runs
13718   on other systems where C-Kermit also runs, like the Amiga.
13719 */
13720 #define REXBUFL 100                     /* Change this if neccessary */
13721 char rexxbuf[REXBUFL] = { '\0' };       /* Rexx's return value (string) */
13722 
13723 int
13724 dorexx() {
13725     int x, y;
13726     char *rexxcmd;
13727 
13728         if ((x = cmtxt("Rexx command","",&rexxcmd,xxstring)) < 0)
13729           return(x);
13730 
13731 #ifdef IKSD
13732     if (inserver) {
13733         printf("?Sorry, command disabled.\r\n");
13734         return(success = 0);
13735     }
13736 #endif /* IKSD */
13737 #ifdef CK_APC
13738     /* Don't let this be set remotely */
13739     if (apcactive == APC_LOCAL ||
13740         apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
13741       return(success = 0);
13742 #endif /* CK_APC */
13743 
13744         ckstrncpy(line,rexxcmd,LINBUFSIZ);
13745         rexxcmd = line;
13746 #ifdef OS2
13747         return(os2rexx(rexxcmd,rexxbuf,REXBUFL));
13748 #else /* !OS2 */
13749         printf("Sorry, nothing happens.\n");
13750         return(success = 0);
13751 #endif /* OS2 */
13752 }
13753 #endif /* CK_REXX */
13754 #endif /* NOPUSH */
13755 #else  /* NOICP */
13756 VOID
13757 dologend() {
13758     /* Dummy write record to connection log */
13759 }
13760 #endif /* NOICP */
13761