apply 010_makefile-destdir-support
[ckermit.git] / ckuus3.c
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, Columbia University, New York City
13     Jeffrey E Altman <jaltman@secure-endpoints.com>
14       Secure Endpoints Inc., New York City
15
16   Copyright (C) 1985, 2004,
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 extern int cmdint;
87 extern int srvidl;
88
89 #ifdef CKFLOAT
90 extern CKFLOAT floatval;                /* (see isfloat()) */
91 #endif /* CKFLOAT */
92
93 #ifndef NOPUSH
94 #ifndef NOFRILLS
95 #ifdef VMS
96 char editor[CKMAXPATH + 1] = "edit";
97 #else
98 char editor[CKMAXPATH + 1] = { NUL, NUL };
99 #endif /* VMS */
100 char editopts[128] = { NUL, NUL };
101 char editfile[CKMAXPATH + 1] = { NUL, NUL };
102 #ifdef BROWSER
103 char browser[CKMAXPATH + 1] = { NUL, NUL };
104 char browsopts[128] = { NUL, NUL };
105 char browsurl[4096] = { NUL, NUL };
106 #endif /* BROWSER */
107 #endif /*  NOFRILLS */
108 #endif /* NOPUSH */
109
110 /* Variables */
111
112 int cmd_quoting = 1;
113 extern int hints, xcmdsrc;
114
115 #ifdef CK_KERBEROS
116 char * k4pwprompt = NULL;               /* Kerberos 4 password prompt */
117 char * k4prprompt = NULL;               /* Kerberos 4 principal prompt */
118 char * k5pwprompt = NULL;               /* Kerberos 5 password prompt */
119 char * k5prprompt = NULL;               /* Kerberos 5 principal prompt */
120 #endif /* CK_KERBEROS */
121 #ifdef CK_SRP
122 char * srppwprompt = NULL;
123 #endif /* CK_SRP */
124
125 extern char * ckprompt, * ikprompt;     /* Default prompt */
126 extern xx_strp xxstring;
127
128 extern char * cdmsgfile[], * cdmsgstr;
129
130 extern int
131   local, server, success, dest, sleepcan, inserver, flow, autoflow, binary,
132   parity, escape, what, turn, duplex, backgrd, hwparity, stopbits, turnch,
133   mdmtyp, network, quiet, nettype, carrier, debses, debtim, cdtimo, nlangs,
134   bgset, pflag, msgflg, cmdmsk, xsuspend, techo, pacing, xitwarn, xitsta,
135   outesc, cmd_cols, cmd_rows, ckxech, xaskmore, haveline, didsetlin, isguest,
136   mdmsav, clearrq, saveask;
137
138 extern int reliable, setreliable, matchdot, matchfifo, dir_dots;
139
140 #ifndef NOSERVER
141   extern int en_pri;
142 #endif /* NOSERVER */
143
144 #ifdef IKSDCONF
145 extern int iksdcf;
146 #endif /* IKSDCONF */
147 #ifdef TCPSOCKET
148   extern int tn_exit;
149 #endif /* TCPSOCKET */
150 #ifdef TNCODE
151   char * tn_pr_uid = NULL;
152 #endif /* TNCODE */
153   extern int exitonclose;
154
155 #ifndef NOKVERBS
156 extern int nkverbs;
157 extern struct keytab kverbs[];
158 #endif /* NOKVERBS */
159
160 extern int ttnproto;                    /* Network protocol */
161
162 extern char *ccntab[];                  /* Names of control chars */
163
164 #ifdef CK_APC
165 extern int apcactive, apcstatus;
166 #endif /* CK_APC */
167
168 #ifndef NOSCRIPT
169 extern int secho;                       /* Whether SCRIPT cmd should echo */
170 #endif /* NOSCRIPT */
171
172 #ifdef DCMDBUF
173 extern char *atmbuf, *atxbuf;
174 #else
175 extern char atmbuf[], atxbuf[];
176 #endif /* DCMDBUF */
177 extern int cmflgs;
178
179 extern char psave[];
180 extern char uidbuf[];
181 extern int  sl_uid_saved;
182 int DeleteStartupFile = 0;
183
184 extern int cmdlvl;                      /* Overall command level */
185
186 #ifndef NOSPL
187 _PROTOTYP( static int parsdir, (int) );
188 char prmbuf[PWBUFL+1] = { NUL, NUL };
189 int fndiags = 1;                        /* Function diagnostics on/off */
190 int fnerror = 1;                        /* Function error treatment */
191
192 #ifdef DCMDBUF
193 extern int *count, *takerr, *merror, *inpcas;
194 #else
195 extern int count[], takerr[], merror[], inpcas[];
196 #endif /* DCMDBUF */
197 extern int mecho;                       /* Macro echo */
198 extern long ck_alarm;
199 extern char alrm_date[], alrm_time[];
200 #else
201 extern int takerr[];
202 #endif /* NOSPL */
203
204 extern int x_ifnum;
205 extern int bigsbsiz, bigrbsiz;          /* Packet buffers */
206
207 extern long speed;                      /* Terminal speed */
208
209 extern char ttname[];                   /* Communication device name */
210 extern char myhost[] ;
211 extern char inidir[];                   /* Ini File directory */
212
213 #ifndef NOSETKEY
214 extern KEY *keymap;                     /* Character map for SET KEY (1:1)  */
215 extern MACRO *macrotab;                 /* Macro map for SET KEY (1:string) */
216 #endif /* NOSETKEY */
217 #ifdef OS2
218 int wideresult;                         /* For wide OS/2 scan codes/cmnum() */
219 #endif /* OS2 */
220
221 #ifndef NOLOCAL
222 #ifdef OS2
223 extern int tt_scrsize[];                /* Scrollback buffer Sizes */
224 #endif /* OS2 */
225 #endif /* NOLOCAL */
226
227 /* Printer settings */
228
229 extern char * printername;              /* NULL if printer not redirected */
230 extern int printpipe;
231 extern int noprinter;
232 #ifdef PRINTSWI
233 int printtimo = 0;
234 char * printterm = NULL;
235 char * printsep = NULL;
236 int printertype = 0;
237 #ifdef BPRINT
238 int printbidi = 0;                      /* SET BPRINTER (bidirectional) */
239 long pportspeed = 0L;                   /* Bidirection printer port speed, */
240 int pportparity = 0;                    /*  parity, */
241 int pportflow = FLO_KEEP;               /*  and flow control */
242 #endif /* BPRINT */
243 #ifdef OS2
244 extern int txt2ps;                      /* Text2PS conversion? */
245 extern int ps_width, ps_length;         /* Text2PS dimensions */
246 #endif /* OS2 */
247 #endif /* PRINTSWI */
248
249 #ifdef OS2
250 extern int tcp_avail;                   /* Nonzero if TCP/IP is available */
251 #ifdef DECNET
252 extern int dnet_avail;                  /* Ditto for DECnet */
253 #endif /* DECNET */
254 #ifdef SUPERLAT
255 extern int slat_avail;
256 #endif /* SUPERLAT */
257 #endif /* OS2 */
258
259 static struct keytab logintab[] = {
260     { "password", LOGI_PSW, CM_INV },
261     { "prompt",   LOGI_PRM, CM_INV },
262     { "userid",   LOGI_UID, 0 }
263 };
264
265 #ifndef NOCSETS
266 /* system-independent character sets, defined in ckcxla.[ch] */
267 extern struct csinfo tcsinfo[];
268 extern struct langinfo langs[];
269
270 /* Other character-set related variables */
271 extern int tcharset, tslevel, language;
272 #endif /* NOCSETS */
273
274 /* File-transfer variable declarations */
275
276 #ifndef NOXFER
277 #ifdef CK_AUTODL
278 extern int cmdadl;
279 #endif /* CK_AUTODL */
280
281 #ifndef NOSERVER
282 extern int ngetpath;
283 extern char * getpath[];
284 #endif /* NOSERVER */
285
286 extern struct ck_p ptab[];
287
288 extern CHAR sstate;                     /* Protocol start state */
289 extern CHAR myctlq;                     /* Control-character prefix */
290 extern CHAR myrptq;                     /* Repeat-count prefix */
291
292 extern int protocol, size, spsiz, spmax, urpsiz, srvtim, srvcdmsg, slostart,
293   srvdis, xfermode, ckdelay, keep, maxtry, unkcs, bctr, ebqflg, swcapr,
294   wslotr, lscapr, lscapu, spsizr, rptena, rptmin, docrc, xfrcan, xfrchr,
295   xfrnum, xfrbel, xfrint, srvping, g_xfermode, xfrxla;
296
297 #ifdef PIPESEND
298 extern int usepipes;
299 #endif /* PIPESEND */
300
301 #ifdef CKXXCHAR                         /* DOUBLE / IGNORE char table */
302 extern int dblflag, ignflag, dblchar;
303 extern short dblt[];
304 #endif /* CKXXCHAR */
305
306 #ifdef CK_SPEED
307 extern short ctlp[];                    /* Control-prefix table */
308 extern int prefixing;
309 static struct keytab pfxtab[] = {
310     "all",         PX_ALL, 0,
311     "cautious",    PX_CAU, 0,
312     "minimal",     PX_WIL, 0,
313     "none",        PX_NON, 0
314 };
315 #endif /* CK_SPEED */
316 #endif /* NOXFER */
317
318 /* Declarations from cmd package */
319
320 #ifdef DCMDBUF
321 extern char *cmdbuf;                    /* Command buffer */
322 extern char *line;
323 extern char *tmpbuf;
324 #else
325 extern char cmdbuf[];                   /* Command buffer */
326 extern char line[];                     /* Character buffer for anything */
327 extern char tmpbuf[];
328 #endif /* DCMDBUF */
329
330 /* From main ckuser module... */
331
332 extern char *tp, *lp;                   /* Temporary buffer */
333
334 extern int tlevel;                      /* Take Command file level */
335
336 #ifndef NOLOCAL
337 extern int sessft;                      /* Session-log file type */
338 extern int slogts;                      /* Session-log timestamps on/off */
339 #endif /* NOLOCAL */
340
341 char * tempdir = NULL;
342
343 #ifdef VMS
344 int vms_msgs = 1;                       /* SET MESSAGES */
345 extern int batch;
346 #endif /* VMS */
347
348 /* Keyword tables for SET commands */
349
350 #ifdef CK_SPEED
351 struct keytab ctltab[] = {
352     "prefixed",   1, 0,                 /* Note, the values are important. */
353     "unprefixed", 0, 0
354 };
355 #endif /* CK_SPEED */
356
357 static struct keytab oldnew[] = {
358     "new", 0, 0,
359     "old", 1, 0
360 };
361
362 #define MCH_FIFO 1
363 #define MCH_DOTF 2
364 struct keytab matchtab[] = {
365     { "dotfile", MCH_DOTF, 0 },
366     { "fifo",    MCH_FIFO, 0 }
367 };
368 int nmatchtab = (sizeof(matchtab) / sizeof(struct keytab));
369
370 #ifndef NOSPL
371 static struct keytab functab[] = {
372     "diagnostics", FUNC_DI, 0,
373     "error",       FUNC_ER, 0
374 };
375 static int nfunctab = (sizeof(functab) / sizeof(struct keytab));
376
377 struct keytab outptab[] = {             /* SET OUTPUT parameters */
378     "pacing", 0, 0,                     /* only one so far... */
379     "special-escapes", 1, 0
380 };
381 int noutptab = (sizeof(outptab) / sizeof(struct keytab)); /* How many */
382 #endif /* NOSPL */
383
384 struct keytab chktab[] = {              /* Block check types */
385     "1", 1, 0,                          /* 1 =  6-bit checksum */
386     "2", 2, 0,                          /* 2 = 12-bit checksum */
387     "3", 3, 0,                          /* 3 = 16-bit CRC */
388     "4", 4, CM_INV,                     /* Same as B */
389     "blank-free-2", 4, 0                /* B = 12-bit checksum, no blanks */
390 };
391
392 struct keytab rpttab[] = {              /* SET REPEAT */
393     "counts",    0, 0,                  /* On or Off */
394 #ifdef COMMENT
395     "minimum",   1, 0,                  /* Threshhold */
396 #endif /* COMMENT */
397     "prefix",    2, 0                   /* Repeat-prefix character value */
398 };
399
400 #ifndef NOLOCAL
401 /* For SET [ MODEM ] CARRIER, and also for SET DIAL CONNECT */
402
403 struct keytab crrtab[] = {
404     "automatic", CAR_AUT, 0,            /* 2 */
405     "off",       CAR_OFF, 0,            /* 0 */
406     "on",        CAR_ON,  0             /* 1 */
407 };
408 int ncrr = 3;
409 #endif /* NOLOCAL */
410
411 struct keytab ooatab[] = {              /* On/Off/Auto table */
412     "automatic", SET_AUTO, 0,           /* 2 */
413     "off",       SET_OFF,  0,           /* 0 */
414     "on",        SET_ON,   0            /* 1 */
415 };
416
417 struct keytab ooktab[] = {              /* On/Off/Ask table */
418     "ask",       2,        0,           /* 2 */
419     "off",       SET_OFF,  0,           /* 0 */
420     "on",        SET_ON,   0            /* 1 */
421 };
422
423 struct keytab qvtab[] = {               /* Quiet/Verbose table */
424     "quiet", 1, 0,
425     "verbose", 0, 0
426 };
427 int nqvt = 2;
428
429 /* For SET DEBUG */
430
431 #define DEB_OFF  0
432 #define DEB_ON   1
433 #define DEB_SES  2
434 #define DEB_TIM  3
435 #define DEB_LEN  4
436
437 struct keytab dbgtab[] = {
438     "linelength", DEB_LEN, CM_INV,
439     "off",        DEB_OFF, 0,
440     "on",         DEB_ON,  0,
441     "session",    DEB_SES, 0,
442     "timestamps", DEB_TIM, 0
443 };
444 int ndbg = (sizeof(dbgtab) / sizeof(struct keytab));
445
446 #ifndef NOLOCAL
447 /* Transmission speeds */
448
449 #ifdef TTSPDLIST /* Speed table constructed at runtime . . . */
450
451 struct keytab * spdtab = NULL;
452 int nspd = 0;
453
454 #else
455 /*
456   Note, the values are encoded in cps rather than bps because 19200 and higher
457   are too big for some ints.  All but 75bps are multiples of ten.  Result of
458   lookup in this table must be multiplied by 10 to get actual speed in bps.
459   If this number is 70, it must be changed to 75.  If it is 888, this means
460   75/1200 split speed.
461
462   The values are generic, rather than specific to UNIX.  We can't use B75,
463   B1200, B9600, etc, because non-UNIX versions of C-Kermit will not
464   necessarily have these symbols defined.  The BPS_xxx symbols are
465   Kermit-specific, and are defined in ckcdeb.h or on the CC command line.
466
467   Like all other keytabs, this one must be in "alphabetical" order,
468   rather than numeric order.
469 */
470 struct keytab spdtab[] = {
471     "0",      0,  CM_INV,
472     "110",   11,  0,
473 #ifdef BPS_115K
474  "115200",11520,  0,
475 #endif /* BPS_115K */
476   "1200",   120,  0,
477 #ifdef BPS_134
478   "134.5",  134,  0,
479 #endif /* BPS_134 */
480 #ifdef BPS_14K
481   "14400", 1440,  0,
482 #endif /* BPS_14K */
483 #ifdef BPS_150
484   "150",     15,  0,
485 #endif /* BPS_150 */
486 #ifdef BPS_1800
487   "1800",     180,  0,
488 #endif /* BPS_150 */
489 #ifdef BPS_19K
490   "19200", 1920,  0,
491 #endif /* BPS_19K */
492 #ifdef BPS_200
493   "200",     20,  0,
494 #endif /* BPS_200 */
495 #ifdef BPS_230K
496   "230400", 23040, 0,
497 #endif /* BPS_230K */
498   "2400",   240,  0,
499 #ifdef BPS_28K
500   "28800", 2880,  0,
501 #endif /* BPS_28K */
502   "300",     30,  0,
503 #ifdef BPS_3600
504   "3600",   360,  0,
505 #endif /* BPS_3600 */
506 #ifdef BPS_38K
507   "38400", 3840,  0,
508 #endif /* BPS_38K */
509 #ifdef BPS_460K
510   "460800", 46080,  0,                  /* Need 32 bits for this... */
511 #endif /* BPS_460K */
512   "4800",   480,  0,
513 #ifdef BPS_50
514   "50",       5,  0,
515 #endif /* BPS_50 */
516 #ifdef BPS_57K
517   "57600", 5760,  0,
518 #endif /* BPS_57K */
519   "600",     60,  0,
520 #ifdef BPS_7200
521   "7200",   720,  0,
522 #endif /* BPS_7200 */
523 #ifdef BPS_75
524   "75",       7,  0,
525 #endif /* BPS_75 */
526 #ifdef BPS_7512
527   "75/1200",888,  0,                    /* Code "888" for split speed */
528 #endif /* BPS_7512 */
529 #ifdef BPS_76K
530   "76800", 7680,  0,
531 #endif /* BPS_76K */
532 #ifdef BPS_921K
533   "921600", 92160,0,                    /* Need 32 bits for this... */
534 #endif /* BPS_921K */
535   "9600",   960,  0
536 };
537 int nspd = (sizeof(spdtab) / sizeof(struct keytab)); /* How many speeds */
538 #endif /* TTSPDLIST */
539
540 #ifdef TN_COMPORT
541 struct keytab tnspdtab[] = {            /* RFC 2217 TELNET COMPORT Option */
542     "115200", 11520,  0,                /* (add any other defined speeds) */
543     "1200",     120,  0,
544     "14400",   1440,  0,
545     "19200",   1920,  0,
546     "230400", 23040,  0,
547     "2400",     240,  0,
548     "28800",   2880,  0,
549     "300",       30,  0,
550     "38400",   3840,  0,
551     "460800", 46080,  0,
552     "4800",     480,  0,
553     "57600",   5760,  0,
554     "600",       60,  0,
555     "9600",     960,  0
556 };
557 int ntnspd = (sizeof(tnspdtab) / sizeof(struct keytab)); /* How many speeds */
558 #endif /* TN_COMPORT */
559 #endif /* NOLOCAL */
560
561 #ifndef NOCSETS
562 extern struct keytab lngtab[];          /* Languages for SET LANGUAGE */
563 extern int nlng;
564 #endif /* NOCSETS */
565
566 #ifndef NOLOCAL
567 /* Duplex keyword table */
568
569 struct keytab dpxtab[] = {
570     "full",      0, 0,
571     "half",      1, 0
572 };
573 #endif /* NOLOCAL */
574
575 /* Flow Control */
576
577 struct keytab cxtypesw[] = {
578 #ifdef DECNET
579     "/decnet",         CXT_DECNET,  0,
580 #endif /* DECNET */
581     "/direct-serial",  CXT_DIRECT,  0,
582 #ifdef DECNET
583     "/lat",            CXT_LAT,     0,
584 #else
585 #ifdef SUPERLAT
586     "/lat",            CXT_LAT,     0,
587 #endif /* SUPERLAT */
588 #endif /* DECNET */
589     "/modem",          CXT_MODEM,   0,
590 #ifdef NPIPE
591     "/named-pipe",     CXT_NPIPE,   0,
592 #endif /* NPIPE */
593 #ifdef NETBIOS
594     "/netbios",        CXT_NETBIOS, 0,
595 #endif /* NETBIOS */
596     "/remote",         CXT_REMOTE,  0,
597 #ifdef TCPSOCKET
598     "/tcpip",          CXT_TCPIP,   0,
599 #endif /* TCPSOCKET */
600 #ifdef ANYX25
601     "/x.25",           CXT_X25,     0,
602 #endif /* ANYX25 */
603     "", 0, 0
604 };
605 int ncxtypesw = (sizeof(cxtypesw) / sizeof(struct keytab));
606
607 #ifdef TN_COMPORT
608 struct keytab tnflotab[] = {            /* SET FLOW-CONTROL keyword table */
609     "dtr/cd",    FLO_DTRC, 0,           /* for RFC 2217 Telnet COMPORT */
610     "dtr/cts",   FLO_DTRT, 0,
611     "keep",      FLO_KEEP, 0,
612     "none",      FLO_NONE, 0,
613     "rts/cts",   FLO_RTSC, 0,
614     "xon/xoff",  FLO_XONX, 0
615 };
616 int ntnflo = (sizeof(tnflotab) / sizeof(struct keytab));
617 #endif /* TN_COMPORT */
618
619 struct keytab flotab[] = {              /* SET FLOW-CONTROL keyword table */
620     "automatic", FLO_AUTO, CM_INV,      /* Not needed any more */
621 #ifdef CK_DTRCD
622     "dtr/cd",    FLO_DTRC, 0,
623 #endif /* CK_DTRCD */
624 #ifdef CK_DTRCTS
625     "dtr/cts",   FLO_DTRT, 0,
626 #endif /* CK_DTRCTS */
627     "keep",      FLO_KEEP, 0,
628     "none",      FLO_NONE, 0,
629 #ifdef CK_RTSCTS
630     "rts/cts",   FLO_RTSC, 0,
631 #endif /* CK_RTSCTS */
632 #ifndef Plan9
633     "xon/xoff",  FLO_XONX, 0,
634 #endif /* Plan9 */
635     "", 0, 0
636 };
637 int nflo = (sizeof(flotab) / sizeof(struct keytab)) - 1;
638
639 /*  Handshake characters  */
640
641 struct keytab hshtab[] = {
642     "bell", 007, 0,
643     "code", 998, 0,
644     "cr",   015, 0,
645     "esc",  033, 0,
646     "lf",   012, 0,
647     "none", 999, 0,                     /* (can't use negative numbers) */
648     "xoff", 023, 0,
649     "xon",  021, 0
650 };
651 int nhsh = (sizeof(hshtab) / sizeof(struct keytab));
652
653 #ifndef NOLOCAL
654 static struct keytab sfttab[] = {       /* File types for SET SESSION-LOG */
655     "ascii",     XYFT_T, CM_INV,
656     "binary",    XYFT_B, 0,
657     "debug",     XYFT_D, 0,
658     "text",      XYFT_T, 0,
659     "timestamped-text", 999, 0
660 };
661 static int nsfttab = (sizeof(sfttab) / sizeof(struct keytab));
662 #endif /* NOLOCAL */
663
664 #ifndef NODIAL
665
666 #ifdef NETCONN                          /* Networks directory depends */
667 int nnetdir = 0;                        /* on DIAL code -- fix later... */
668 char *netdir[MAXDDIR+2];
669 #endif /* NETCONN */
670
671 _PROTOTYP( static int setdial, (int) );
672 _PROTOTYP( static int setdcd, (void) );
673 _PROTOTYP( static int cklogin, (void) );
674
675 #ifndef MINIDIAL
676 #ifdef OLDTBCODE
677 extern int tbmodel;                     /* Telebit model ID */
678 #endif /* OLDTBCODE */
679 #endif /* MINIDIAL */
680
681 extern MDMINF *modemp[];                /* Pointers to modem info structs */
682 extern struct keytab mdmtab[];          /* Modem types (in module ckudia.c) */
683 extern int nmdm;                        /* Number of them */
684
685 _PROTOTYP(static int dialstr,(char **, char *));
686
687 extern int dialhng, dialtmo, dialksp, dialdpy, dialmhu, dialec, dialdc;
688 extern int dialrtr, dialint, dialudt, dialsrt, dialrstr, mdmwaitd;
689 extern int mdmspd, dialfc, dialmth, dialesc, dialfld, dialidt, dialpace;
690 extern int mdmspk, mdmvol, dialtest;
691
692 int dialcvt = 2;                        /* DIAL CONVERT-DIRECTORY */
693 int dialcnf = 0;                        /* DIAL CONFIRMATION */
694 int dialcon = 2;                        /* DIAL CONNECT */
695 int dialcq  = 0;                        /* DIAL CONNECT AUTO quiet/verbose */
696 extern long dialmax, dialcapas;
697 int usermdm = 0;
698 extern int ndialdir;
699 extern char *dialini,   *dialmstr, *dialmprmt, *dialdir[], *dialcmd,  *dialnpr,
700  *dialdcon, *dialdcoff, *dialecon, *dialecoff, *dialhcmd,  *dialx3,
701  *dialhwfc, *dialswfc,  *dialnofc, *dialtone,  *dialpulse, *dialname, *diallac;
702 extern char *diallcc,   *dialixp,  *dialixs,   *dialldp,   *diallds,  *dialtfp,
703  *dialpxi,  *dialpxo,   *dialsfx,  *dialaaon,  *dialaaoff;
704 extern char *diallcp,   *diallcs,  *dialini2,  *dialmac;
705 extern char *dialspoff, *dialspon, *dialvol1,  *dialvol2,  *dialvol3;
706
707 char *dialtocc[MAXTPCC] = { NULL, NULL };
708 int ndialtocc = 0;
709 char *dialpucc[MAXTPCC] = { NULL, NULL };
710 int ndialpucc = 0;
711
712 char *dialtfc[MAXTOLLFREE] = {
713     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
714 };
715 int ntollfree = 0;
716
717 char *dialpxx[MAXPBXEXCH] = {
718     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
719 };
720 int ndialpxx = 0;
721
722 char *diallcac[MAXLOCALAC] = {
723     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
724     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
725     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
726     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
727 };
728 int nlocalac = 0;
729
730 static struct keytab drstrtab[] = {
731     "international", 5, 0,
732     "local",         2, 0,
733     "long-distance", 4, 0,
734     "none",          6, 0
735 };
736
737 static struct keytab dcnvtab[] = {
738     "ask",  2, 0,
739     "off",  0, 0,
740     "on",   1, 0
741 };
742
743 struct keytab setmdm[] = {
744     "capabilities",     XYDCAP,  0,
745     "carrier-watch",    XYDMCD,  0,
746     "command",          XYDSTR,  0,
747     "compression",      XYDDC,   CM_INV,
748     "data-compression", XYDDC,   0,
749     "dial-command",     XYDDIA,  0,
750     "error-correction", XYDEC,   0,
751     "escape-character", XYDESC,  0,
752     "flow-control",     XYDFC,   0,
753     "hangup-method",    XYDMHU,  0,
754 #ifndef NOXFER
755     "kermit-spoof",     XYDKSP,  0,
756 #endif /* NOXFER */
757     "maximum-speed",    XYDMAX,  0,
758     "name",             XYDNAM,  0,
759     "speaker",          XYDSPK,  0,
760     "speed-matching",   XYDSPD,  0,
761     "type",             XYDTYP,  0,
762     "volume",           XYDVOL,  0
763 };
764 int nsetmdm = (sizeof(setmdm) / sizeof(struct keytab));
765
766 struct keytab voltab[] = {
767     "high",   3,  0,
768     "low",    1,  0,
769     "medium", 2,  0
770 };
771
772 struct keytab mdmcap[] = {
773     "at-commands",      CKD_AT,  0,
774     "compression",      CKD_DC,  0,
775     "dc",               CKD_DC,  CM_INV,
776     "ec",               CKD_EC,  CM_INV,
777     "error-correction", CKD_EC,  0,
778     "hardware-flow",    CKD_HW,  0,
779     "hwfc",             CKD_HW,  CM_INV,
780     "itu",              CKD_V25, CM_INV,
781     "kermit-spoof",     CKD_KS,  0,
782     "ks",               CKD_KS,  CM_INV,
783     "sb",               CKD_SB,  CM_INV,
784     "software-flow",    CKD_SW,  0,
785     "speed-buffering",  CKD_SB,  0,
786     "swfc",             CKD_SW,  CM_INV,
787     "tb",               CKD_TB,  CM_INV,
788     "telebit",          CKD_TB,  0,
789     "v25bis-commands",  CKD_V25, 0
790 };
791 int nmdmcap = (sizeof(mdmcap) / sizeof(struct keytab));
792
793 #ifdef COMMENT                          /* SET ANSWER not implemented yet */
794 static struct keytab answertab[] = {
795     { "caller-id",  XYA_CID,  0 };
796     { "rings",      XYA_RNG,  0 };
797     { "", 0, 0 }
798 };
799 static int nanswertab =  (sizeof(answertab) / sizeof(struct keytab)) - 1;
800 #endif /* COMMENT */
801
802 struct keytab dialtab[] = {             /* SET DIAL table */
803     "area-code",        XYDLAC, 0,      /* Also still includes items     */
804     "compression",      XYDDC,  CM_INV, /* that were moved to SET MODEM, */
805     "confirmation",     XYDCNF, 0,      /* but they are CM_INVisible...  */
806     "connect",          XYDCON, 0,
807     "convert-directory",XYDCVT, 0,
808     "country-code",     XYDLCC, 0,
809     "dial-command",     XYDDIA, CM_INV,
810     "directory",        XYDDIR, 0,
811     "display",          XYDDPY, 0,
812     "escape-character", XYDESC, CM_INV,
813     "error-correction", XYDEC,  CM_INV,
814     "flow-control",     XYDFC,  CM_INV,
815     "force-long-distance", XYDFLD, 0,
816     "hangup",           XYDHUP, 0,
817     "ignore-dialtone",  XYDIDT, 0,
818     "interval",         XYDINT, 0,
819     "in",               XYDINI, CM_INV|CM_ABR,
820     "init-string",      XYDINI, CM_INV,
821     "intl-prefix",      XYDIXP, 0,
822     "intl-suffix",      XYDIXS, 0,
823 #ifndef NOXFER
824     "kermit-spoof",     XYDKSP, CM_INV,
825 #endif /* NOXFER */
826     "lc-area-codes",    XYDLLAC, 0,
827     "lc-prefix",        XYDLCP, 0,
828     "lc-suffix",        XYDLCS, 0,
829     "ld-prefix",        XYDLDP, 0,
830     "ld-suffix",        XYDLDS, 0,
831     "local-area-code",  XYDLAC, CM_INV,
832     "local-prefix",     XYDLCP, CM_INV,
833     "local-suffix",     XYDLCS, CM_INV,
834     "m",                XYDMTH, CM_INV|CM_ABR,
835 #ifndef NOSPL
836     "macro",            XYDMAC, 0,      /* 195 */
837 #endif /* NOSPL */
838 #ifdef MDMHUP
839     "me",               XYDMTH, CM_INV|CM_ABR,
840 #endif /* MDMHUP */
841     "method",           XYDMTH, 0,
842     "mnp-enable",       XYDMNP, CM_INV, /* obsolete but still accepted */
843 #ifdef MDMHUP
844     "modem-hangup",     XYDMHU, CM_INV,
845 #endif /* MDMHUP */
846     "pacing",           XYDPAC,  0,
847     "pbx-exchange",     XYDPXX,  0,
848     "pbx-inside-prefix",XYDPXI,  0,
849     "pbx-outside-prefix",XYDPXO, 0,
850     "prefix",           XYDNPR,  0,
851     "pulse-countries",  XYDPUCC, 0,
852     "restrict",         XYDRSTR, 0,
853     "retries",          XYDRTM,  0,
854     "sort",             XYDSRT,  0,
855     "speed-matching",   XYDSPD,  CM_INV,
856     "string",           XYDSTR,  CM_INV,
857     "suffix",           XYDSFX,  0,
858     "test",             XYDTEST, 0,
859     "timeout",          XYDTMO,  0,
860     "tf-area-code",     XYDTFC,  CM_INV,
861     "tf-prefix",        XYDTFP,  CM_INV,
862     "toll-free-area-code",XYDTFC,0,
863     "toll-free-prefix", XYDTFP,  0,
864     "tone-countries",   XYDTOCC, 0
865 };
866 int ndial = (sizeof(dialtab) / sizeof(struct keytab));
867
868 #ifdef MDMHUP
869 struct keytab mdmhang[] = {
870     "dtr",           0, 0,
871     "modem-command", 1, 0,
872     "rs232-signal",  0, 0,
873     "v24-signal",    0, CM_INV
874 };
875 #endif /* MDMHUP */
876
877 static struct keytab mdmcmd[] = {
878     "autoanswer",       XYDS_AN, 0,     /* autoanswer */
879     "compression",      XYDS_DC, 0,     /* data compression */
880     "dial-mode-prompt", XYDS_MP, 0,     /* dial mode prompt */
881     "dial-mode-string", XYDS_MS, 0,     /* dial mode string */
882     "error-correction", XYDS_EC, 0,     /* error correction */
883     "hangup-command",   XYDS_HU, 0,     /* hangup command */
884     "hardware-flow",    XYDS_HW, 0,     /* hwfc */
885     "ignore-dialtone",  XYDS_ID, 0,     /* ignore dialtone */
886     "init-string",      XYDS_IN, 0,     /* init string */
887     "no-flow-control",  XYDS_NF, 0,     /* no flow control */
888     "predial-init",     XYDS_I2, 0,     /* last-minute setup commands */
889     "pulse",            XYDS_DP, 0,     /* pulse */
890     "software-flow",    XYDS_SW, 0,     /* swfc */
891     "speaker",          XYDS_SP, 0,     /* Speaker */
892     "tone",             XYDS_DT, 0,     /* tone */
893     "volume",           XYDS_VO, 0      /* Volume */
894 };
895 static int nmdmcmd = (sizeof(mdmcmd) / sizeof(struct keytab));
896
897 struct keytab dial_fc[] = {
898     "auto",     FLO_AUTO, 0,
899     "none",     FLO_NONE, 0,
900     "rts/cts",  FLO_RTSC, 0,
901     "xon/xoff", FLO_XONX, 0
902 };
903
904 struct keytab dial_m[] = {              /* DIAL METHOD */
905     "auto",    XYDM_A, 0,
906     "default", XYDM_D, 0,
907     "pulse",   XYDM_P, 0,
908     "tone",    XYDM_T, 0
909 };
910 int ndial_m = (sizeof(dial_m)/sizeof(struct keytab));
911 #endif /* NODIAL */
912
913 #ifdef CK_TAPI
914 struct keytab tapitab[] = {             /* Top-Level Microsoft TAPI */
915     "configure-line",     XYTAPI_CFG,  0,
916     "dialing-properties", XYTAPI_DIAL, 0
917 };
918 int ntapitab = (sizeof(tapitab)/sizeof(struct keytab));
919
920 struct keytab settapitab[] = {          /* SET Microsoft TAPI */
921     "inactivity-timeout", XYTAPI_INA,  0,
922     "line",               XYTAPI_LIN,  0,
923     "location",           XYTAPI_LOC,  0,
924     "manual-dialing",     XYTAPI_MAN,  0,
925     "modem-dialing",      XYTAPI_PASS, 0,
926     "modem-lights",       XYTAPI_LGHT, 0,
927     "phone-number-conversions",   XYTAPI_CON,  0,
928     "port",               XYTAPI_LIN,  CM_INV,
929     "post-dial-terminal", XYTAPI_PST,  0,
930     "pre-dial-terminal",  XYTAPI_PRE,  0,
931     "use-windows-configuration", XYTAPI_USE, 0,
932     "wait-for-credit-card-tone", XYTAPI_BNG, 0
933 };
934 int nsettapitab = (sizeof(settapitab)/sizeof(struct keytab));
935
936 struct keytab * tapiloctab = NULL;      /* Microsoft TAPI Locations */
937 int ntapiloc = 0;
938 extern struct keytab * tapilinetab;     /* Microsoft TAPI Line Devices */
939 extern int ntapiline;
940 extern int tttapi;                      /* TAPI in use */
941 extern int tapipass;                    /* TAPI Passthrough mode */
942 extern int tapiconv;                    /* TAPI Conversion mode */
943 extern int tapilights;
944 extern int tapipreterm;
945 extern int tapipostterm;
946 extern int tapimanual;
947 extern int tapiinactivity;
948 extern int tapibong;
949 extern int tapiusecfg;
950 #endif /* CK_TAPI */
951
952 #ifndef NOPUSH
953 extern int nopush;
954 #ifdef UNIX
955 struct keytab wildtab[] = {             /* SET WILDCARD-EXPANSION */
956     "kermit",  0, 0,
957     "shell",   1, 0
958 };
959 struct keytab wdottab[] = {             /* cont'd */
960     "/match-dot-files",    1, 0,
961     "/no-match-dot-files", 0, 0
962 };
963 extern int wildxpand;
964 #endif /* UNIX */
965 #endif /* NOPUSH */
966
967 #ifdef NETCONN
968 extern struct keytab netcmd[], netkey[];
969 extern int nnets, nnetkey;
970 #ifdef TCPSOCKET
971 extern struct keytab tcpopt[];
972 extern int ntcpopt;
973 #endif /* TCPSOCKET */
974 #ifdef NPIPE
975 char pipename[PIPENAML+1] = { NUL, NUL };
976 #endif /* NPIPE */
977 #ifdef CK_NETBIOS
978 extern unsigned char NetBiosName[];
979 #endif /* CK_NETBIOS */
980 #endif /* NETCONN */
981
982 #ifdef ANYX25
983 struct keytab x25tab[] = {
984     "call-user-data",    XYUDAT, 0,
985     "closed-user-group", XYCLOS, 0,
986     "reverse-charge",    XYREVC, 0
987 };
988 int nx25 = (sizeof(x25tab) / sizeof(struct keytab));
989
990 #ifndef IBMX25
991 struct keytab padx3tab[] = {
992     "break-action",         PAD_BREAK_ACTION,           0,
993     "break-character",      PAD_BREAK_CHARACTER,        0,
994     "character-delete",     PAD_CHAR_DELETE_CHAR,       0,
995     "cr-padding",           PAD_PADDING_AFTER_CR,       0,
996     "discard-output",       PAD_SUPPRESSION_OF_DATA,    0,
997     "echo",                 PAD_ECHO,                   0,
998     "editing",              PAD_EDITING,                0,
999     "escape",               PAD_ESCAPE,                 0,
1000     "forward",              PAD_DATA_FORWARD_CHAR,      0,
1001     "lf-padding",           PAD_PADDING_AFTER_LF,       0,
1002     "lf-insert",            PAD_LF_AFTER_CR,            0,
1003     "line-delete",          PAD_BUFFER_DELETE_CHAR,     0,
1004     "line-display",         PAD_BUFFER_DISPLAY_CHAR,    0,
1005     "line-fold",            PAD_LINE_FOLDING,           0,
1006     "pad-flow-control",     PAD_FLOW_CONTROL_BY_PAD,    0,
1007     "service-signals",      PAD_SUPPRESSION_OF_SIGNALS, 0,
1008     "timeout",              PAD_DATA_FORWARD_TIMEOUT,   0,
1009 /* Speed is read-only */
1010     "transmission-rate",    PAD_LINE_SPEED,             0,
1011     "user-flow-control",    PAD_FLOW_CONTROL_BY_USER,   0
1012 };
1013 int npadx3 = (sizeof(padx3tab) / sizeof(struct keytab));
1014 #endif /* IBMX25 */
1015 #endif /* ANYX25 */
1016
1017 #ifdef TLOG
1018 static struct keytab vbtab[] = {
1019     "brief",   0, 0,
1020 #ifdef OS2ORUNIX
1021     "ftp",     2, 0,
1022 #endif /* OS2ORUNIX */
1023     "verbose", 1, 0
1024 };
1025 int nvb = (sizeof(vbtab) / sizeof(struct keytab));
1026 #endif /* TLOG */
1027
1028 #ifdef CKSYSLOG
1029 static struct keytab syslogtab[] = {
1030     "all",         SYSLG_CX, 0,
1031     "commands",    SYSLG_CM, 0,
1032     "connection",  SYSLG_AC, 0,
1033     "debug",       SYSLG_DB, 0,
1034     "dial",        SYSLG_DI, 0,
1035     "file-access", SYSLG_FA, 0,
1036     "file-create", SYSLG_FC, 0,
1037     "login",       SYSLG_LI, 0,
1038     "none",        SYSLG_NO, 0,
1039     "protocol",    SYSLG_PR, 0
1040 };
1041 int nsyslog = (sizeof(syslogtab) / sizeof(struct keytab));
1042 #endif /* CKSYSLOG */
1043
1044 /* Parity keyword table */
1045
1046 struct keytab partbl[] = {
1047     "even",    'e', 0,
1048 #ifdef HWPARITY
1049     "hardware",'H', 0,
1050 #endif /* HWPARITY */
1051     "mark",    'm', 0,
1052     "none",     0 , 0,
1053     "odd",     'o', 0,
1054     "space",   's', 0
1055 };
1056 int npar = (sizeof(partbl) / sizeof(struct keytab));
1057
1058 #ifdef HWPARITY
1059 struct keytab hwpartbl[] = {
1060 /* Add mark and space if needed and possible */
1061     "even",    'e', 0,
1062 #ifdef OS2
1063     "mark",    'm', 0,
1064 #endif /* OS2 */
1065     "odd",     'o', 0,
1066 #ifdef OS2
1067     "space",   's', 0,
1068 #endif /* OS2 */
1069     "", 0, 0
1070 };
1071 int nhwpar = (sizeof(hwpartbl) / sizeof(struct keytab)) - 1;
1072 #endif /* HWPARITY */
1073
1074 /* On/Off table */
1075
1076 struct keytab onoff[] = {
1077     "off",       0, 0,
1078     "on",        1, 0
1079 };
1080
1081 #define XYCD_M    0                     /* CD MESSAGE */
1082 #define XYCD_P    1                     /* CD PATH */
1083 #define XYCD_H    2                     /* CD HOME */
1084
1085 struct keytab cdtab[] = {
1086     "home",      XYCD_H, 0,
1087     "message",   XYCD_M, 0,
1088     "path",      XYCD_P, 0
1089 };
1090 int ncdtab = (sizeof(cdtab) / sizeof(struct keytab));
1091
1092 struct keytab cdmsg[] = {
1093     "file",      2, 0,
1094     "off",       0, 0,
1095     "on",        1, 0
1096 };
1097 int ncdmsg = (sizeof(cdmsg) / sizeof(struct keytab));
1098
1099 static
1100 struct keytab xittab[] = {              /* SET EXIT */
1101     "hangup",        3, 0,              /* ...HANGUP */
1102     "on-disconnect", 2, 0,              /* ...ON-DISCONNECT */
1103     "status",        0, 0,              /* ...STATUS */
1104     "warning",       1, 0               /* ...WARNING */
1105 };
1106 int nexit = (sizeof(xittab) / sizeof(struct keytab));
1107
1108 struct keytab xitwtab[] = {             /* SET EXIT WARNING */
1109     "always", 2, 0,                     /* even when not connected */
1110     "off",    0, 0,                     /* no warning     */
1111     "on",     1, 0                      /* when connected */
1112 };
1113 int nexitw = (sizeof(xitwtab) / sizeof(struct keytab));
1114
1115 struct keytab rltab[] = {
1116     "local",     1, 0,                  /* ECHO values */
1117     "off",       0, CM_INV,
1118     "on",        1, CM_INV,
1119     "remote",    0, 0
1120 };
1121 int nrlt = (sizeof(rltab) / sizeof(struct keytab));
1122
1123 /* Incomplete File Disposition table */
1124
1125 struct keytab ifdtab[] = {
1126     "discard", SET_OFF, 0,
1127     "keep",    SET_ON,  0
1128 };
1129
1130 struct keytab ifdatab[] = {
1131     "auto",    SET_AUTO, 0,
1132     "discard", SET_OFF,  0,
1133     "keep",    SET_ON,   0
1134 };
1135
1136 char * ifdnam[] = { "discard", "keep", "auto" };
1137
1138 /* SET TAKE parameters table */
1139 static
1140 struct keytab taktab[] = {
1141     "echo",  0, 0,
1142     "error", 1, 0,
1143     "off",   2, CM_INV,                 /* For compatibility */
1144     "on",    3, CM_INV                  /* with MS-DOS Kermit... */
1145 };
1146
1147 #ifndef NOSPL
1148 #ifdef COMMENT
1149 /* not used */
1150 static
1151 struct keytab suftab[] = {              /* (what to do with) STARTUP-FILE */
1152     "delete", 1, 0,
1153     "keep",   0, 0
1154 };
1155 #endif /* COMMENT */
1156
1157 /* SET MACRO parameters table */
1158 static
1159 struct keytab smactab[] = {
1160     "echo",  0, 0,
1161     "error", 1, 0
1162 };
1163 #endif /* NOSPL */
1164
1165 #ifndef NOSCRIPT
1166 static
1167 struct keytab scrtab[] = {
1168     "echo",  0, 0
1169 };
1170 #endif /* NOSCRIPT */
1171
1172 /* SET COMMAND table */
1173
1174 /* SET COMMAND items... */
1175
1176 #define SCMD_BSZ 0      /* BYTESIZE */
1177 #define SCMD_RCL 1      /* RECALL */
1178 #define SCMD_RTR 2      /* RETRY */
1179 #define SCMD_QUO 3      /* QUOTING */
1180 #define SCMD_COL 4      /* COLOR */
1181 #define SCMD_HIG 5      /* HEIGHT */
1182 #define SCMD_WID 6      /* WIDTH */
1183 #define SCMD_CUR 7      /* CURSOR-POSITION */
1184 #define SCMD_SCR 8      /* SCROLLBACK */
1185 #define SCMD_MOR 9      /* MORE-PROMPTING */
1186 #define SCMD_INT 10     /* INTERRUPTION */
1187 #define SCMD_ADL 11     /* AUTODOWNLOAD */
1188 #define SCMD_STA 12     /* STATUSLINE */
1189 #define SCMD_DBQ 13     /* DOUBLEQUOTING */
1190 #define SCMD_CBR 14     /* CBREAK */
1191 #define SCMD_BFL 15     /* BUFFER-SIZE (not used) */
1192
1193 static struct keytab scmdtab[] = {
1194 #ifdef CK_AUTODL
1195     "autodownload",       SCMD_ADL, 0,
1196 #endif /* CK_AUTODL */
1197 #ifdef COMMENT
1198 /*
1199   To implement this requires that we change CMDBL and ATMBL
1200   from compile-time symbols to runtime variables.  Not a big deal,
1201   but not trivial either.
1202  */
1203     "buffer-size",        SCMD_BFL, 0,
1204 #endif /* COMMENT */
1205     "bytesize",           SCMD_BSZ, 0,
1206     "cbreak",             SCMD_CBR, CM_INV,
1207 #ifdef OS2
1208     "color",              SCMD_COL, 0,
1209     "cursor-position",    SCMD_CUR, 0,
1210 #endif /* OS2 */
1211 #ifdef DOUBLEQUOTING
1212     "doublequoting",      SCMD_DBQ, 0,
1213 #endif /* DOUBLEQUOTING */
1214     "height",             SCMD_HIG, 0,
1215     "interruption",       SCMD_INT, 0,
1216     "more-prompting",     SCMD_MOR, 0,
1217     "quoting",            SCMD_QUO, 0,
1218 #ifdef CK_RECALL
1219     "recall-buffer-size", SCMD_RCL, 0,
1220 #endif /* CK_RECALL */
1221 #ifdef CK_RECALL
1222     "retry",              SCMD_RTR, 0,
1223 #endif /* CK_RECALL */
1224 #ifdef OS2
1225 #ifdef ONETERMUPD
1226     "scrollback",         SCMD_SCR, 0,
1227     "statusline",         SCMD_STA, 0,
1228 #endif /* ONETERMUPD */
1229 #endif /* OS2 */
1230     "width",              SCMD_WID, 0
1231 };
1232 static int nbytt = (sizeof(scmdtab) / sizeof(struct keytab));
1233
1234 #ifndef NOSERVER
1235 /* Server parameters table */
1236 static struct keytab srvtab[] = {
1237     "cd-message",   XYSERC, 0,
1238     "display",      XYSERD, 0,
1239     "get-path",     XYSERP, 0,
1240     "idle-timeout", XYSERI, 0,
1241     "keepalive",    XYSERK, 0,
1242     "login",        XYSERL, 0,
1243     "timeout",      XYSERT, 0
1244 };
1245 static int nsrvt = (sizeof(srvtab) / sizeof(struct keytab));
1246 #endif /* NOSERVER */
1247
1248 static struct keytab sleeptab[] = {     /* SET SLEEP table */
1249     "cancellation",  0,   0
1250 };
1251
1252 static struct keytab tstab[] = {        /* SET TRANSFER/XFER table */
1253     "bell",            XYX_BEL, 0,
1254 #ifdef XFRCAN
1255     "cancellation",    XYX_CAN, 0,
1256 #endif /* XFRCAN */
1257 #ifndef NOCSETS
1258     "character-set",   XYX_CSE, 0,
1259 #endif /* NOCSETS */
1260 #ifndef NOSPL
1261     "crc-calculation", XYX_CRC, 0,
1262 #endif /* NOSPL */
1263     "display",         XYX_DIS, 0,
1264     "interruption",    XYX_INT, 0,
1265     "locking-shift",   XYX_LSH, 0,
1266     "message",         XYX_MSG, 0,
1267     "mode",            XYX_MOD, 0,
1268     "msg",             XYX_MSG, CM_INV,
1269 #ifdef PIPESEND
1270     "pipes",           XYX_PIP, 0,
1271 #endif /* PIPESEND */
1272 #ifdef CK_XYZ
1273     "protocol",        XYX_PRO, 0,
1274 #endif /* CK_XYZ */
1275     "report",          XYX_RPT, 0,
1276     "slow-start",      XYX_SLO, 0,
1277 #ifndef NOCSETS
1278     "translation",     XYX_XLA, 0,
1279 #else
1280     "translation",     XYX_XLA, CM_INV,
1281 #endif /* NOCSETS */
1282     "xlation",         XYX_XLA, CM_INV,
1283     "", 0, 0
1284 };
1285 static int nts = (sizeof(tstab) / sizeof(struct keytab)) - 1;
1286
1287 static struct keytab rtstab[] = {       /* REMOTE SET TRANSFER/XFER table */
1288 #ifndef NOCSETS
1289     "character-set",   XYX_CSE, 0,
1290 #endif /* NOCSETS */
1291     "mode",            XYX_MOD, 0
1292 };
1293 static int nrts = (sizeof(rtstab) / sizeof(struct keytab));
1294
1295 struct keytab xfrmtab[] = {             /* TRANSFER MODE table */
1296     "automatic", XMODE_A, 0,
1297     "manual",    XMODE_M, 0
1298 };
1299
1300 #ifdef LOCUS
1301 extern int locus, autolocus;
1302
1303 static struct keytab locustab[] = {
1304 #ifdef KUI
1305     { "ask",     3, 0 },                /* Presently implemented in GUI only */
1306 #endif /* KUI */
1307     { "auto",    2, 0 },
1308     { "local",   1, 0 },
1309     { "remote",  0, 0 }
1310 };
1311 static int nlocustab = (sizeof(locustab) / sizeof(struct keytab));
1312
1313 #endif /* LOCUS */
1314
1315 #ifndef NOCSETS
1316 /* SET TRANSFER CHARACTER-SET table */
1317
1318 extern struct keytab tcstab[];
1319 extern int ntcs;
1320 #endif /* NOCSETS */
1321
1322 /* SET TRANSFER LOCKING-SHIFT table */
1323 struct keytab lstab[] = {
1324     "forced", 2,   0,
1325     "off",    0,   0,
1326     "on",     1,   0
1327 };
1328 int nls = (sizeof(lstab) / sizeof(struct keytab));
1329
1330 /* SET TELNET tables */
1331 #ifdef TNCODE
1332 extern int tn_nlm, tn_b_nlm, tn_b_meu, tn_b_ume, tn_b_xfer, tn_sb_bug;
1333 extern int tn_no_encrypt_xfer, tn_auth_krb5_des_bug;
1334 extern int tn_wait_flg, tn_duplex, tn_delay_sb, tn_sfu;
1335 extern int sl_tn_saved;
1336 extern int tn_infinite;
1337 extern int tn_rem_echo;
1338 extern int tn_deb;
1339 extern int tn_auth_how;
1340 extern int tn_auth_enc;
1341 #ifdef CK_FORWARD_X
1342 extern char * tn_fwdx_xauthority;
1343 #endif /* CK_FORWARD_X */
1344 #ifdef CK_AUTHENTICATION
1345 static struct keytab setauth[] = {
1346 #ifdef CK_KERBEROS
1347     "k4",        AUTH_KRB4, CM_INV,
1348     "k5",        AUTH_KRB5, CM_INV,
1349     "kerberos4", AUTH_KRB4, 0,
1350     "kerberos5", AUTH_KRB5, 0,
1351     "kerberos_iv",AUTH_KRB4, CM_INV,
1352     "kerberos_v", AUTH_KRB5, CM_INV,
1353     "krb4",      AUTH_KRB4, CM_INV,
1354     "krb5",      AUTH_KRB5, CM_INV,
1355 #endif /* CK_KERBEROS */
1356 #ifdef CK_SRP
1357     "srp",       AUTH_SRP,  0,
1358 #endif /* CK_SRP */
1359 #ifdef CK_SSL
1360     "ssl",      AUTH_SSL,   0,
1361     "tls",      AUTH_TLS,   0,
1362 #endif /* CK_SSL */
1363     "",         0,      0
1364 };
1365 static int nsetauth = sizeof(setauth)/sizeof(struct keytab) - 1;
1366 #ifdef CK_KERBEROS
1367 extern char * krb5_d_principal;         /* Default principal */
1368 extern char * krb5_d_instance;
1369 extern char * krb5_d_realm;             /* Default realm */
1370 extern char * krb5_d_cc;                /* Default credentials cache */
1371 extern char * krb5_d_srv;               /* Default service name */
1372 extern int    krb5_d_lifetime;          /* Default lifetime */
1373 extern int    krb5_d_forwardable;
1374 extern int    krb5_d_proxiable;
1375 extern int    krb5_d_renewable;
1376 extern int    krb5_autoget;
1377 extern int    krb5_autodel;
1378 extern int    krb5_d_getk4;
1379 extern int    krb5_checkaddrs;          /* Check TGT Addrs */
1380 extern int    krb5_d_no_addresses;
1381 extern char * krb5_d_addrs[];
1382 extern char * k5_keytab;                /* Keytab file */
1383
1384 extern struct krb4_init_data krb4_init;
1385 extern char * krb4_d_principal;         /* Default principal */
1386 extern char * krb4_d_realm;             /* Default realm */
1387 extern char * krb4_d_srv;               /* Default service name */
1388 extern int    krb4_d_lifetime;          /* Default lifetime */
1389 extern int    krb4_d_preauth;
1390 extern char * krb4_d_instance;
1391 extern int    krb4_autoget;
1392 extern int    krb4_autodel;
1393 extern int    krb4_checkaddrs;          /* Check TGT Addrs */
1394 extern char * k4_keytab;                /* Keytab file */
1395 #ifdef KRB4
1396 extern int    k4debug;
1397 #endif /* KRB4 */
1398 static struct keytab krbver[] = {
1399     "4",                 4, 0,
1400     "5",                 5, 0,
1401     "iv",                4, CM_INV,
1402     "v",                 5, CM_INV
1403 };
1404 static int nkrbver = sizeof(krbver)/sizeof(struct keytab);
1405
1406 static struct keytab kdestab[] = {
1407     "never",            KRB_DEL_NO, 0,
1408     "no",               KRB_DEL_NO, CM_INV,
1409     "on-close",         KRB_DEL_CL, 0,
1410     "on-exit",          KRB_DEL_EX, 0
1411 };
1412 static int nkdestab = sizeof(kdestab)/sizeof(struct keytab);
1413
1414 static struct keytab k4tab[] = {
1415     "autodel",           XYKRBDEL, CM_INV,
1416     "autodestroy",       XYKRBDEL, 0,
1417     "autoget",           XYKRBGET, 0,
1418     "check-address",     XYKRBADR, 0,
1419     "debug",             XYKRBDBG, CM_INV,
1420     "instance",          XYKRBINS, 0,
1421     "keytab",            XYKRBKTB, 0,
1422     "lifetime",          XYKRBLIF, 0,
1423     "preauth",           XYKRBPRE, 0,
1424     "principal",         XYKRBPR,  0,
1425     "prompt",            XYKRBPRM, 0,
1426     "realm",             XYKRBRL,  0,
1427     "service-name",      XYKRBSRV, 0
1428 };
1429 static int nk4tab = sizeof(k4tab)/sizeof(struct keytab);
1430
1431 static struct keytab k5tab[] = {
1432     "addresses",         XYKRBADD, 0,
1433     "autodelete",        XYKRBDEL, CM_INV,
1434     "autodestroy",       XYKRBDEL, 0,
1435     "autoget",           XYKRBGET, 0,
1436     "cc",                XYKRBCC,  CM_INV,
1437     "check-address",     XYKRBADR, 0,
1438     "credentials-cache", XYKRBCC,  0,
1439     "forwardable",       XYKRBFWD, 0,
1440     "get-k4-tgt",        XYKRBK5K4,0,
1441     "instance",          XYKRBINS, 0,
1442     "keytab",            XYKRBKTB, 0,
1443     "lifetime",          XYKRBLIF, 0,
1444     "no-addresses",      XYKRBNAD, 0,
1445     "principal",         XYKRBPR,  0,
1446     "prompt",            XYKRBPRM, 0,
1447     "proxiable",         XYKRBPRX, 0,
1448     "realm",             XYKRBRL,  0,
1449     "renewable",         XYKRBRNW, 0,
1450     "service-name",      XYKRBSRV, 0
1451 };
1452 static int nk5tab = sizeof(k5tab)/sizeof(struct keytab);
1453
1454 #define KRB_PW_PRM 1
1455 #define KRB_PR_PRM 2
1456
1457 static struct keytab krbprmtab[] = {
1458     "password",  KRB_PW_PRM, 0,
1459     "principal", KRB_PR_PRM, 0
1460 };
1461
1462 #endif /* CK_KERBEROS */
1463 #ifdef CK_SRP
1464 static struct keytab srptab[] = {
1465     "prompt",            XYSRPPRM, 0
1466 };
1467 static int nsrptab = sizeof(srptab)/sizeof(struct keytab);
1468 #define SRP_PW_PRM 1
1469
1470 static struct keytab srpprmtab[] = {
1471     "password",  SRP_PW_PRM, 0
1472 };
1473 #endif /* CK_SRP */
1474 #ifdef CK_SSL
1475 static struct keytab ssltab[] = {
1476     "certs-ok",          XYSSLCOK,  CM_INV,
1477     "cipher-list",       XYSSLCL,   0,
1478     "crl-dir",           XYSSLCRLD, 0,
1479     "crl-file",          XYSSLCRL,  0,
1480     "debug",             XYSSLDBG,  0,
1481     "dh-key-file",       XYSSLDKFL, CM_INV,
1482     "dh-param-file",     XYSSLDPFL, 0,
1483     "dsa-cert-chain-file", XYSSLDCCF, 0,
1484     "dsa-cert-file",     XYSSLDCFL, 0,
1485     "dsa-key-file",      XYSSLDKFL, 0,
1486     "dummy",             XYSSLDUM,  CM_INV,
1487     "only",              XYSSLON,   CM_INV,
1488     "random-file",       XYSSLRND,  0,
1489     "rsa-cert-chain-file", XYSSLRCCF, 0,
1490     "rsa-cert-file",     XYSSLRCFL, 0,
1491     "rsa-key-file",      XYSSLRKFL, 0,
1492     "verbose",           XYSSLVRB,  0,
1493     "verify",            XYSSLVRF,  0,
1494     "verify-dir",        XYSSLVRFD, 0,
1495     "verify-file",       XYSSLVRFF, 0
1496 };
1497 static int nssltab = sizeof(ssltab)/sizeof(struct keytab);
1498 static struct keytab sslvertab[] = {
1499     "fail-if-no-peer-cert", SSL_VERIFY_PEER |
1500                             SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0,
1501     "no",               SSL_VERIFY_NONE, 0,
1502     "none",             SSL_VERIFY_NONE, CM_INV,
1503     "off",              SSL_VERIFY_NONE, CM_INV,
1504     "on",               SSL_VERIFY_PEER, CM_INV,
1505     "peer-cert",        SSL_VERIFY_PEER, 0
1506 };
1507 static int nsslvertab = sizeof(sslvertab)/sizeof(struct keytab);
1508 #endif /* CK_SSL */
1509 #endif /* CK_AUTHENTICATION */
1510 #ifdef CK_ENCRYPTION
1511 int cx_type = CX_AUTO;
1512 extern int sl_cx_type;
1513 #endif /* CK_ENCRYPTION */
1514 extern char *tcp_address;
1515 #ifndef NOHTTP
1516 extern char * tcp_http_proxy;
1517 extern char * tcp_http_proxy_user;
1518 extern char * tcp_http_proxy_pwd;
1519 extern char * tcp_http_proxy_agent;
1520 #endif /* NOHTTP */
1521 #ifdef NT
1522 #ifdef CK_SOCKS
1523 extern char *tcp_socks_svr;
1524 extern char *tcp_socks_user;
1525 #ifdef CK_SOCKS_NS
1526 extern char *tcp_socks_ns;
1527 #endif /* CK_SOCKS_NS */
1528 #endif /* CK_SOCKS */
1529 #endif /* NT */
1530
1531 #define UPW_USER  1
1532 #define UPW_PASS  2
1533 #define UPW_AGENT 3
1534
1535 static struct keytab userpass[] = {
1536     { "/agent",   UPW_AGENT, CM_ARG },
1537     { "/password", UPW_PASS, CM_ARG },
1538     { "/user",     UPW_USER, CM_ARG },
1539 };
1540 static int nuserpass = sizeof(userpass)/sizeof(struct keytab);
1541
1542 static struct keytab tnnegtab[] = {     /* TELNET NEGOTIATION table */
1543     "accepted",  TN_NG_AC, 0,
1544     "refused",   TN_NG_RF, 0,
1545     "req",       TN_NG_RQ, CM_INV|CM_ABR,
1546     "requ",      TN_NG_RQ, CM_INV|CM_ABR,
1547     "reque",     TN_NG_RQ, CM_INV|CM_ABR,
1548     "reques",    TN_NG_RQ, CM_INV|CM_ABR,
1549     "request",   TN_NG_RQ, CM_INV|CM_ABR,
1550     "requeste",  TN_NG_RQ, CM_INV|CM_ABR,
1551     "requested", TN_NG_RQ, 0,
1552     "required",  TN_NG_MU, 0
1553 };
1554 static int ntnnegtab = sizeof(tnnegtab)/sizeof(struct keytab);
1555
1556 #ifdef CK_ENCRYPTION
1557 static struct keytab typkwd[] = {
1558     "/type", 0, CM_ARG
1559 };
1560
1561 static struct keytab tnenctab[] = {     /* TELNET ENCRYPTION table */
1562     "accepted",   TN_NG_AC,    CM_INV,
1563     "refused",    TN_NG_RF,    CM_INV,
1564     "req",        TN_NG_RQ,    CM_INV|CM_ABR,
1565     "requ",       TN_NG_RQ,    CM_INV|CM_ABR,
1566     "reque",      TN_NG_RQ,    CM_INV|CM_ABR,
1567     "reques",     TN_NG_RQ,    CM_INV|CM_ABR,
1568     "request",    TN_NG_RQ,    CM_INV|CM_ABR,
1569     "requeste",   TN_NG_RQ,    CM_INV|CM_ABR,
1570     "requested",  TN_NG_RQ,    CM_INV,
1571     "required",   TN_NG_MU,    CM_INV,
1572     "start",      TN_EN_START, CM_INV,
1573     "stop",       TN_EN_STOP,  CM_INV,
1574     "type",       TN_EN_TYP,   0
1575 };
1576 static int ntnenc = sizeof(tnenctab)/sizeof(struct keytab) ;
1577 #endif /* CK_ENCRYPTION */
1578
1579 #ifdef CK_FORWARD_X
1580 static struct keytab tnfwdxtab[] = {    /* TELNET FORWARD-X table */
1581     "no-encryption",    1,  CM_INV,
1582     "xauthority-file",  0,  0
1583 };
1584 static int ntnfwdx = sizeof(tnfwdxtab)/sizeof(struct keytab) ;
1585 #endif /* CK_FORWARD_X */
1586
1587 static struct keytab tnbugtab[] = {     /* TELNET BUG table */
1588     "auth-krb5-des",         4, 0,
1589     "binary-me-means-u-too", 0, 0,
1590     "binary-u-means-me-too", 1, 0,
1591     "infinite-loop-check",   2, 0,
1592     "sb-implies-will-do",    3, 0
1593 };
1594
1595 #ifdef CK_ENVIRONMENT
1596 static struct keytab tnenvtab[] = {     /* TELNET ENVIRONMENT table */
1597     "acct",     TN_ENV_ACCT,    0,
1598     "display",  TN_ENV_DISP,    0,
1599     "job",      TN_ENV_JOB,     0,
1600     "location", TN_ENV_LOC,     0,
1601     "off",      TN_ENV_OFF,     CM_INV,
1602     "on",       TN_ENV_ON,      CM_INV,
1603     "printer",  TN_ENV_PRNT,    0,
1604     "systemtype",TN_ENV_SYS,    0,
1605     "user",     TN_ENV_USR,     0,
1606     "uservar",  TN_ENV_UVAR,    0,
1607     "", 0, 0
1608 };
1609 static int ntnenv = sizeof(tnenvtab)/sizeof(struct keytab) - 1;
1610 #endif /* CK_ENVIRONMENT */
1611
1612 #ifdef CK_AUTHENTICATION
1613 static struct keytab tnauthtab[] = {    /* TELNET AUTHENTICATION table */
1614     "accepted",   TN_NG_AC,  CM_INV,
1615     "encrypt-flag", TN_AU_ENC, 0,
1616     "forwarding", TN_AU_FWD,   0,
1617     "how-flag",   TN_AU_HOW,   0,
1618     "refused",    TN_NG_RF,  CM_INV,
1619     "req",        TN_NG_RQ,  CM_INV|CM_ABR,
1620     "requ",       TN_NG_RQ,  CM_INV|CM_ABR,
1621     "reque",      TN_NG_RQ,  CM_INV|CM_ABR,
1622     "reques",     TN_NG_RQ,  CM_INV|CM_ABR,
1623     "request",    TN_NG_RQ,  CM_INV|CM_ABR,
1624     "requeste",   TN_NG_RQ,  CM_INV|CM_ABR,
1625     "requested",  TN_NG_RQ,  CM_INV,
1626     "required",   TN_NG_MU,  CM_INV,
1627     "type",       TN_AU_TYP, 0
1628 };
1629 static int ntnauth = sizeof(tnauthtab)/sizeof(struct keytab) ;
1630
1631 struct keytab autyptab[] = {    /* TELNET AUTHENTICATION TYPE table */
1632     "automatic",  AUTH_AUTO, 0,
1633 #ifdef CK_KERBEROS
1634     "k4",         AUTH_KRB4, CM_INV,
1635     "k5",         AUTH_KRB5, CM_INV,
1636     "kerberos4",  AUTH_KRB4, 0,
1637     "kerberos5",  AUTH_KRB5, 0,
1638     "kerberos_iv",AUTH_KRB4, CM_INV,
1639     "kerberos_v", AUTH_KRB5, CM_INV,
1640     "krb4",       AUTH_KRB4, CM_INV,
1641     "krb5",       AUTH_KRB5, CM_INV,
1642 #endif /* CK_KERBEROS */
1643     "none",       AUTH_NONE, 0,
1644 #ifdef NT
1645     "ntlm",       AUTH_NTLM, 0,
1646 #endif /* NT */
1647 #ifdef CK_SRP
1648     "srp",        AUTH_SRP,  0,
1649 #endif /* CK_SRP */
1650 #ifdef CK_SSL
1651     "ssl",        AUTH_SSL,  0,
1652 #endif /* CK_SSL */
1653     "", 0, 0
1654 };
1655 int nautyp = sizeof(autyptab)/sizeof(struct keytab) - 1;
1656
1657 struct keytab auhowtab[] = {    /* TELNET AUTHENTICATION HOW table */
1658     "any",     TN_AUTH_HOW_ANY,     0,
1659     "mutual",  TN_AUTH_HOW_MUTUAL,  0,
1660     "one-way", TN_AUTH_HOW_ONE_WAY, 0,
1661     "", 0, 0
1662 };
1663 int nauhow = sizeof(auhowtab)/sizeof(struct keytab) - 1;
1664
1665 struct keytab auenctab[] = {    /* TELNET AUTHENTICATION ENCRYPT table */
1666     "any",     TN_AUTH_ENC_ANY,     0,
1667     "none",    TN_AUTH_ENC_NONE,    0,
1668     "telopt",  TN_AUTH_ENC_TELOPT,  0,
1669 #ifdef CK_SSL
1670     "tls",     TN_AUTH_ENC_TLS,     0,
1671 #endif /* CK_SSL */
1672     "", 0, 0
1673 };
1674 int nauenc = sizeof(auenctab)/sizeof(struct keytab) - 1;
1675 #endif /* CK_AUTHENTICATION */
1676
1677 #define TN_NL_BIN 3
1678 #define TN_NL_NVT 4
1679 static struct keytab tn_nlmtab[] = {    /* TELNET NEWLINE-MODE table */
1680     "binary-mode", TN_NL_BIN, 0,        /* Binary mode */
1681     "nvt",    TN_NL_NVT, 0,             /* NVT mode */
1682     "off",    TNL_CRNUL, CM_INV,        /* CR-NUL (TELNET spec) */
1683     "on",     TNL_CRLF,  CM_INV,        /* CR-LF (TELNET spec) */
1684     "raw",    TNL_CR,    CM_INV         /* CR only (out of spec) */
1685 };
1686 static int ntn_nlm = (sizeof(tn_nlmtab) / sizeof(struct keytab));
1687
1688 static struct keytab tnlmtab[] = {      /* TELNET NEWLINE-MODE table */
1689     "cr",     TNL_CR,    CM_INV,        /* CR only (out of spec) */
1690     "cr-lf",  TNL_CRLF,  CM_INV,        /* CR-LF (TELNET spec) */
1691     "cr-nul", TNL_CRNUL, CM_INV,        /* CR-NUL (TELNET spec) */
1692     "lf",     TNL_LF,    CM_INV,        /* LF instead of CR-LF */
1693     "off",    TNL_CRNUL, 0,             /* CR-NUL (TELNET spec) */
1694     "on",     TNL_CRLF,  0,             /* CR-LF (TELNET spec) */
1695     "raw",    TNL_CR,    0              /* CR only (out of spec) */
1696 };
1697 static int ntnlm = (sizeof(tnlmtab) / sizeof(struct keytab));
1698
1699 struct keytab tntab[] = {
1700 #ifdef CK_AUTHENTICATION
1701     "authentication",       CK_TN_AU,  0,
1702 #endif /* CK_AUTHENTICATION */
1703     "b",                    CK_TN_BM,  CM_INV|CM_ABR,
1704     "bi",                   CK_TN_BM,  CM_INV|CM_ABR,
1705     "bin",                  CK_TN_BM,  CM_INV|CM_ABR,
1706     "bina",                 CK_TN_BM,  CM_INV|CM_ABR,
1707     "binar",                CK_TN_BM,  CM_INV|CM_ABR,
1708     "binary",               CK_TN_BM,  CM_INV|CM_ABR,
1709     "binary-",              CK_TN_BM,  CM_INV|CM_ABR,
1710     "binary-mode",          CK_TN_BM,  CM_INV,
1711     "binary-transfer-mode", CK_TN_XF,  0,
1712     "binary-xfer-mode",     CK_TN_XF,  CM_INV,
1713     "bug",                  CK_TN_BUG, 0,
1714     "debug",                CK_TN_DB,  0,
1715     "delay-sb",             CK_TN_DL,  0,
1716     "echo",                 CK_TN_EC,  0,
1717 #ifdef CK_ENCRYPTION
1718     "encryption",      CK_TN_ENC,  0,
1719 #endif /* CK_ENCRYPTION */
1720 #ifdef CK_ENVIRONMENT
1721     "environment",     CK_TN_ENV,  0,
1722 #endif /* CK_ENVIRONMENT */
1723 #ifdef CK_FORWARD_X
1724     "forward-x",       CK_TN_FX,   0,
1725 #endif /* CK_FORWARD_X */
1726 #ifdef IKS_OPTION
1727     "kermit",          CK_TN_IKS,  CM_INV,
1728 #endif /* IKS_OPTION */
1729 #ifdef CK_SNDLOC
1730     "location",        CK_TN_LOC,  0,
1731 #endif /* CK_SNDLOC */
1732 #ifdef CK_NAWS
1733     "naws",            CK_TN_NAWS, CM_INV,
1734 #endif /* CK_NAWS */
1735     "newline-mode",    CK_TN_NL,   0,
1736     "no-encrypt-during-xfer", CK_TN_NE, CM_INV,
1737     "prompt-for-userid",CK_TN_PUID,0,
1738     "remote-echo",     CK_TN_RE,   0,
1739 #ifdef CK_SSL
1740     "start-tls",       CK_TN_TLS,  CM_INV,
1741 #endif /* CK_SSL */
1742 #ifdef NT
1743     "sfu-compatibility", CK_TN_SFU, 0,
1744 #else
1745     "sfu-compatibility", CK_TN_SFU, CM_INV,
1746 #endif /* NT */
1747     "terminal-type",   CK_TN_TT,   0,
1748     "wait-for-negotiations", CK_TN_WAIT, 0,
1749 #ifdef CK_ENVIRONMENT
1750     "xdisplay-location",CK_TN_XD, CM_INV,
1751 #endif /* CK_ENVIRONMENT */
1752     "", 0, 0
1753 };
1754 int ntn = (sizeof(tntab) / sizeof(struct keytab)) - 1;
1755
1756 struct keytab tnopttab[] = {
1757 #ifdef CK_AUTHENTICATION
1758     "authentication",  CK_TN_AU,   0,
1759 #else
1760     "authentication",  CK_TN_AU,   CM_INV,
1761 #endif /* CK_AUTHENTICATION */
1762     "binary-mode",     CK_TN_BM,   0,
1763 #ifdef TN_COMPORT
1764     "c",               CK_TN_CPC,   CM_INV|CM_ABR,
1765     "co",              CK_TN_CPC,   CM_INV|CM_ABR,
1766     "com",             CK_TN_CPC,   CM_INV|CM_ABR,
1767     "com-port-control",CK_TN_CPC,   0,
1768     "comport-control", CK_TN_CPC,   CM_INV,
1769 #else /* TN_COMPORT */
1770     "com-port-control",CK_TN_CPC,  CM_INV,
1771     "comport-control", CK_TN_CPC,   CM_INV,
1772 #endif /* TN_COMPORT */
1773     "echo",            CK_TN_EC,   0,
1774 #ifdef CK_ENCRYPTION
1775     "encryption",      CK_TN_ENC,  0,
1776 #else
1777     "encryption",      CK_TN_ENC,  CM_INV,
1778 #endif /* CK_ENCRYPTION */
1779 #ifdef CK_FORWARD_X
1780     "forward-x",       CK_TN_FX,   0,
1781 #else /* CK_FORWARD_X */
1782     "forward-x",       CK_TN_FX,   CM_INV,
1783 #endif /* CK_FORWARD_X */
1784     "ibm-sak",         CK_TN_SAK,  CM_INV,
1785 #ifdef IKS_OPTION
1786     "kermit",          CK_TN_IKS,  0,
1787 #else
1788     "kermit",          CK_TN_IKS,  CM_INV,
1789 #endif /* IKS_OPTION */
1790     "lflow",           CK_TN_FLW,  CM_INV,
1791     "logout",          CK_TN_LOG,  0,
1792 #ifdef CK_NAWS
1793     "naws",            CK_TN_NAWS, 0,
1794 #else
1795     "naws",            CK_TN_NAWS, CM_INV,
1796 #endif /* CK_NAWS */
1797 #ifdef CK_ENVIRONMENT
1798     "new-environment", CK_TN_ENV,  0,
1799 #else
1800     "new-environment", CK_TN_ENV,  CM_INV,
1801 #endif /* CK_ENVIRONMENT */
1802     "pragma-heartbeat",CK_TN_PHR,  CM_INV,
1803     "pragma-logon",    CK_TN_PLG,  CM_INV,
1804     "pragma-sspi",     CK_TN_PSP,  CM_INV,
1805     "sak",             CK_TN_SAK,  CM_INV,
1806 #ifdef CK_SNDLOC
1807     "send-location",   CK_TN_LOC,  0,
1808 #else
1809     "send-location",   CK_TN_LOC,  CM_INV,
1810 #endif /* CK_SNDLOC */
1811     "sga",             CK_TN_SGA, CM_INV|CM_ABR,
1812 #ifdef CK_SSL
1813     "start-tls",       CK_TN_TLS,  0,
1814 #else
1815     "start-tls",       CK_TN_TLS,  CM_INV,
1816 #endif /* CK_SSL */
1817     "suppress-go-aheads", CK_TN_SGA, 0,
1818     "terminal-type",   CK_TN_TT,   0,
1819     "ttype",           CK_TN_TT,   CM_INV|CM_ABR,
1820 #ifdef CK_ENVIRONMENT
1821     "xdisplay-location", CK_TN_XD, 0,
1822 #else
1823     "xdisplay-location", CK_TN_XD, CM_INV,
1824 #endif /* CK_ENVIRONMENT */
1825     "", 0, 0
1826 };
1827 int ntnopt = (sizeof(tnopttab) / sizeof(struct keytab)) - 1;
1828
1829 struct keytab tnoptsw[] = {
1830     "/client",  CK_TN_CLIENT,   0,
1831     "/server",  CK_TN_SERVER,   0
1832 };
1833 int ntnoptsw = (sizeof(tnoptsw) / sizeof(struct keytab));
1834 #endif /* TNCODE */
1835
1836 struct keytab ftrtab[] = {              /* Feature table */
1837 #ifndef NOCSETS                         /* 0 = we have it, 1 = we don't */
1838 "character-sets",       0, 0,
1839 #else
1840 "character-sets",       1, 0,
1841 #endif /* NOCSETS */
1842 #ifndef NOCYRIL
1843 "cyrillic",             0, 0,
1844 #else
1845 "cyrillic",             1, 0,
1846 #endif /* NOCYRIL */
1847
1848 #ifndef NOLOGDIAL
1849 "cx-log",               0, 0,
1850 #else
1851 "cx-log",               1, 0,
1852 #endif /* NOLOGDIAL */
1853
1854 #ifndef NODEBUG
1855 "debug",                0, 0,
1856 #else
1857 "debug",                1, 0,
1858 #endif /* NODEBUG */
1859
1860 #ifndef NODIAL
1861 "dial",                 0, 0,
1862 #else
1863 "dial",                 1, 0,
1864 #endif /* NODIAL */
1865
1866 #ifdef DYNAMIC
1867 "dynamic-memory",       0, 0,
1868 #else
1869 "dynamic-memory",       1, 0,
1870 #endif /* DYNAMIC */
1871
1872 #ifndef NOXFER
1873 "file-transfer",        0, 0,
1874 #else
1875 "file-transfer",        1, 0,
1876 #endif /* NOXFER */
1877
1878 #ifdef XXFWD
1879 "forward",              0, 0,
1880 #else
1881 "forward",              1, 0,
1882 #endif /* XXFWD */
1883
1884 #ifdef NEWFTP
1885 "ftp",                  0, 0,
1886 #else
1887 "ftp",                  1, 0,
1888 #endif /* NEWFTP */
1889
1890 #ifdef CK_CURSES
1891 "fullscreen-display",   0, 0,
1892 #else
1893 "fullscreen-display",   1, 0,
1894 #endif /* CK_CURSES */
1895 #ifdef GREEK
1896 "greek",                0, 0,
1897 #else
1898 "greek",                1, 0,
1899 #endif /* GREEK */
1900 #ifdef HEBREW
1901 "hebrew",               0, 0,
1902 #else
1903 "hebrew",               1, 0,
1904 #endif /* HEBREW */
1905 #ifndef NOHELP
1906 "help",                 0, 0,
1907 #else
1908 "help",                 1, 0,
1909 #endif /* NOHELP */
1910
1911 #ifndef NOIKSD
1912 "iksd",                 0, 0,
1913 #else
1914 "iksd",                 1, 0,
1915 #endif /* NOIKSD */
1916
1917 #ifndef NOSPL
1918 "if-command",           0, 0,
1919 #else
1920 "if-command",           1, 0,
1921 #endif /* NOSPL */
1922 #ifndef NOJC
1923 #ifdef UNIX
1924 "job-control",          0, 0,
1925 #else
1926 "job-control",          1, 0,
1927 #endif /* UNIX */
1928 #else
1929 "job-control",          1, 0,
1930 #endif /* NOJC */
1931 #ifdef KANJI
1932 "kanji",                0, 0,
1933 #else
1934 "kanji",                1, 0,
1935 #endif /* KANJI */
1936
1937 #ifndef NOXFER
1938 "kermit",               0, 0,
1939 #else
1940 "kermit",               1, 0,
1941 #endif /* NOXFER */
1942
1943 #ifdef CK_KERBEROS
1944 "kerberos",             0, 0,
1945 #else
1946 "kerberos",             1, 0,
1947 #endif /* CK_KERBEROS */
1948
1949 #ifndef NOCSETS
1950 "latin1",               0, 0,
1951 #else
1952 "latin1",               1, 0,
1953 #endif /* NOCSETS */
1954 #ifdef LATIN2
1955 "latin2",               0, 0,
1956 #else
1957 "latin2",               1, 0,
1958 #endif /* LATIN2 */
1959
1960 #ifdef CKLEARN
1961 "learned-scripts",       0, 0,
1962 #else
1963 "learned-scripts",       1, 0,
1964 #endif /* CKLEARN */
1965
1966 #ifndef NOLOCAL
1967 "making-connections",   0, 0,
1968 #else
1969 "making-connections",   1, 0,
1970 #endif /* NOLOCAL */
1971
1972 #ifdef NETCONN
1973 "network",              0, 0,
1974 #else
1975 "network",              1, 0,
1976 #endif /* NETCONN */
1977
1978 #ifdef NT
1979 #ifdef CK_AUTHENTICATION
1980 "ntlm",                 1, 0,
1981 #else /* CK_AUTHENTICATION */
1982 "ntlm",                 0, 0,
1983 #endif /* CK_AUTHENTICATION */
1984 #else /* NT */
1985 "ntlm",                 0, 0,
1986 #endif /* NT */
1987
1988 #ifdef PIPESEND
1989 "pipes",                0, 0,
1990 #else
1991 #ifdef NETCMD
1992 "pipes",                0, 0,
1993 #endif /* NETCMD */
1994 #endif /* PIPESEND */
1995 #ifndef PIPESEND
1996 #ifndef NETCMD
1997 "pipes",                1, 0,
1998 #endif /* PIPESEND */
1999 #endif /* NETCMD */
2000
2001 #ifdef NETPTY
2002 "pty",                  0, 0,
2003 #else
2004 "pty",                  1, 0,
2005 #endif /* NETPTY */
2006
2007 #ifndef NOPUSH
2008 "push",                 0, 0,
2009 #else
2010 "push",                 1, 0,
2011 #endif /* PUSH */
2012
2013 #ifdef CK_REDIR
2014 "redirect",             0, 0,
2015 #else
2016 "redirect",             1, 0,
2017 #endif /* CK_REDIR */
2018
2019 #ifdef CK_RTSCTS
2020 "rts/cts",              0, 0,
2021 #else
2022 "rts/cts",              1, 0,
2023 #endif /* RTS/CTS */
2024
2025 #ifndef NOSCRIPT
2026 "script-command",       0, 0,
2027 #else
2028 "script-command",       1, 0,
2029 #endif /* NOSCRIPT */
2030 #ifndef NOSERVER
2031 "server-mode",          0, 0,
2032 #else
2033 "server-mode",          1, 0,
2034 #endif /* NOSERVER */
2035
2036 #ifndef NOSEXP
2037 "sexpression",          0, 0,
2038 #else
2039 "sexpression",          1, 0,
2040 #endif /* NOSEXP */
2041
2042 #ifdef SFTP_BUILTIN
2043 "sftp",                 1, 0,
2044 #else
2045 "sftp",                 0, 0,
2046 #endif /* SFTP_BUILTIN */
2047
2048 #ifndef NOSHOW
2049 "show-command",         0, 0,
2050 #else
2051 "show-command",         1, 0,
2052 #endif /* NOSHOW */
2053
2054 #ifdef CK_SRP
2055 "srp",                  0, 0,
2056 #else
2057 "srp",                  1, 0,
2058 #endif /* CK_SRP */
2059
2060 #ifdef SSHBUILTIN
2061 "ssh",                  0, 0,
2062 #else /* SSHBUILTIN */
2063 "ssh",                  1, 0,
2064 #endif /* SSHBUILTIN */
2065
2066 #ifdef CK_SSL
2067 "ssl/tls",              0, 0,
2068 #else
2069 "ssl/tls",              1, 0,
2070 #endif /* CK_SSL */
2071
2072 #ifndef NOXMIT
2073 "transmit",             0, 0,
2074 #else
2075 "transmit",             1, 0,
2076 #endif /* NOXMIT */
2077
2078 #ifdef UNICODE
2079 "unicode",              0, 0,
2080 #else
2081 "unicode",              1, 0,
2082 #endif /* UNICODE */
2083
2084 #ifdef CK_XYZ
2085 "xyzmodem",             0, 0,
2086 #else
2087 "xyzmodem",             1, 0,
2088 #endif /* NOXMIT */
2089
2090 "", 0, 0
2091 };
2092 int nftr = (sizeof(ftrtab) / sizeof(struct keytab)) - 1;
2093
2094 struct keytab desttab[] = {             /* SET DESTINATION */
2095 #ifdef CALIBRATE
2096     "calibrate", DEST_N, CM_INV,
2097 #endif /* CALIBRATE */
2098     "disk",    DEST_D, 0,
2099 #ifdef CALIBRATE
2100     "nowhere", DEST_N, 0,
2101 #endif /* CALIBRATE */
2102     "printer", DEST_P, 0,
2103     "screen",  DEST_S, 0
2104 };
2105 int ndests =  (sizeof(desttab) / sizeof(struct keytab));
2106
2107 #ifndef NOSPL           /* Used only with script programming items... */
2108
2109 #ifndef NOSERVER                        /* This is just to avoid some */
2110 #define CK_PARSDIR                      /* "statement not reached" */
2111 #else                                   /* complaints... */
2112 #ifndef NODIAL
2113 #define CK_PARSDIR
2114 #endif /* NODIAL */
2115 #endif /* NOSERVER */
2116
2117 /*
2118   cx == 0 means dial directory
2119   cx == 1 means network directory
2120   cx == 2 means a directory path list
2121 */
2122 static int
2123 parsdir(cx) int cx; {
2124     int i, x, y, dd;                    /* Workers */
2125     int nxdir;
2126     char *s;
2127     char ** xdir;
2128     char *pp[MAXGETPATH];               /* Temporary name pointers */
2129 #ifdef ZFNQFP
2130     struct zfnfp * fnp;
2131 #ifdef OS2
2132     char * env;
2133     char dirpath[4096];
2134 #else /* OS2 */
2135     char dirpath[1024];                 /* For fully qualified filenames */
2136 #endif /* OS2 */
2137 #endif /* ZFNQFP */
2138
2139     int max = 0;                        /* Maximum number of things to parse */
2140     char c;
2141
2142 #ifndef NODIAL
2143     if (cx == 0) {                      /* Dialing */
2144         nxdir = ndialdir;
2145         xdir = dialdir;
2146         max = MAXDDIR;
2147     } else
2148 #ifdef NETCONN
2149     if (cx == 1) {                      /* Network */
2150         nxdir = nnetdir;
2151         xdir = netdir;
2152         max = MAXDDIR;
2153     } else
2154 #endif /* NETCONN */
2155 #endif /* NODIAL */
2156 #ifndef NOSERVER
2157     if (cx == 2) {                      /* GET path */
2158         nxdir = ngetpath;
2159         xdir = getpath;
2160         max = MAXGETPATH;
2161     } else                              /* Called with invalid function code */
2162 #endif /* NOSERVER */
2163       return(-2);
2164
2165     for (i = 0; i < MAXGETPATH; i++)    /* Init these. */
2166       pp[i] = NULL;
2167
2168 #ifdef CK_PARSDIR
2169     dd = 0;                             /* Temporary name counter */
2170     while (1) {
2171         if (cx != 2) {                  /* Dialing or Network Directory */
2172 #ifdef OS2
2173             int len;
2174             char * appdata0 = NULL, * appdata1 = NULL;
2175 #ifdef NT
2176             env = getenv("K95PHONES");
2177             makestr(&appdata0,(char *)GetAppData(0));
2178             makestr(&appdata1,(char *)GetAppData(1));
2179 #else /* NT */
2180             env = getenv("K2PHONES");
2181 #endif /* NT */
2182             if (!env)
2183               env = getenv("K95PHONES");
2184             if (!env)
2185               env = "";
2186
2187             dirpath[0] = '\0';
2188             len = strlen(env) + 2*strlen(startupdir) + 2*strlen(inidir)
2189                 + (appdata0?2*strlen(appdata0):0) 
2190                 + (appdata1?2*strlen(appdata1):0)
2191                 + 2*strlen(zhome()) + 2*strlen(exedir) + 8*strlen("PHONES/")
2192                 + 12;
2193             if (len < 4096)             /* SAFE */
2194               sprintf(dirpath,
2195                     "%s%s%s;%s%s;%s%s%s%s%s%s%s%s%s;%s%s;%s;%s%s",
2196                     /* Semicolon-separated path list */
2197                     env,
2198                     (env[0] && env[strlen(env)-1] == ';') ? "" : ";",
2199                     startupdir,
2200                     startupdir, "PHONES/",
2201                     appdata1 ? appdata1 : "", 
2202                     appdata1 ? "Kermit 95;" : "",
2203                     appdata1 ? appdata1 : "", 
2204                     appdata1 ? "Kermit 95/PHONES/;" : "",
2205                     appdata0 ? appdata0 : "", 
2206                     appdata0 ? "Kermit 95;" : "",
2207                     appdata0 ? appdata0 : "", 
2208                     appdata0 ? "Kermit 95/PHONES/;" : "",
2209                     inidir,
2210                     inidir, "PHONES/",
2211                     zhome(),
2212                     zhome(), "PHONES/",
2213                     exedir,
2214                     exedir, "PHONES/"
2215                     );
2216 #ifdef NT
2217             makestr(&appdata0,NULL);
2218             makestr(&appdata1,NULL);
2219 #endif /* NT */
2220 #else
2221 #ifdef UNIX
2222             y = 1024;
2223             s = dirpath;
2224             zzstring("\\v(home)",&s,&y);
2225 #endif /* UNIX */
2226 #endif /* OS2 */
2227             y = cmifip(
2228                   "Names of one or more directory files, separated by spaces",
2229                        "",&s,&x,0,
2230 #ifdef OS2ORUNIX
2231                        dirpath,
2232 #else
2233                        NULL,
2234 #endif /* OS2ORUNIX */
2235                        xxstring
2236                        );
2237         } else {                        /* List of directory names */
2238             x = 0;
2239             y = cmdir("Directory name","",&s,xxstring);
2240         }
2241         if (y < 0) {
2242             if (y == -3) {              /* EOL or user typed <CR> */
2243                 if ((y = cmcfm()) < 0) return(y);
2244                 for (i = 0; i < max; i++) { /* Clear these */
2245                     if (i < nxdir && xdir[i]) {
2246                         free(xdir[i]);
2247                     }
2248                     xdir[i] = (i < dd) ? pp[i] : NULL;
2249                 }
2250 #ifndef NODIAL
2251                 if (cx == 0)
2252                   ndialdir = dd;
2253 #ifdef NETCONN
2254                 if (cx == 1)
2255                   nnetdir = dd;
2256 #endif /* NETCONN */
2257 #endif /* NODIAL */
2258 #ifndef NOSERVER
2259                 if (cx == 2)
2260                   ngetpath = dd;
2261 #endif /* NOSERVER */
2262                 return(success = 1);
2263
2264             } else {                    /* Parse error */
2265                 for (i = 0; i < dd; i++) {  /* Free temp storage */
2266                     if (pp[i]) free(pp[i]); /* but don't change */
2267                     pp[i] = NULL;           /* anything else */
2268                 }
2269                 return(y);
2270             }
2271         }
2272         if (x) {
2273             printf("?Wildcards not allowed\n");
2274             return(-9);
2275         }
2276 #ifdef CK_TMPDIR
2277         if (cx == 2 && !isdir(s)) {
2278             printf("?Not a directory - %s\n", s);
2279             return(-9);
2280         }
2281 #endif /* CK_TMPDIR */
2282
2283 #ifdef ZFNQFP
2284         if (cx < 2) {
2285             if (!isabsolute(s)) {       /* If not relative get full path */
2286                 if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
2287                     if (fnp->fpath)
2288                       if ((int) strlen(fnp->fpath) > 0)
2289                         s = fnp->fpath;
2290                 }
2291             }
2292         }
2293 #endif /* ZFNQFP */
2294         c = NUL;
2295         x = strlen(s);
2296         if (x > 0)                      /* Get last char */
2297           c = s[x-1];
2298         debug(F000,"parsdir s",s,c);
2299         if ((pp[dd] = malloc(strlen(s)+2)) == NULL) {
2300             printf("?Internal error - malloc\n");
2301             for (i = 0; i < dd; i++) {  /* Free temp storage */
2302                 if (pp[i]) free(pp[i]);
2303                 pp[i] = NULL;
2304             }
2305             return(-9);
2306         } else {                        /* Have storage for name */
2307             strcpy(pp[dd],s);           /* Copy string into new storage */
2308             debug(F111,"parsdir pp[dd] 1",pp[dd],dd);
2309 #ifndef NOXFER
2310             if (cx == 2) {              /* If we are parsing directories */
2311                 char dirsep[2];
2312                 extern int myindex;     /* Append directory separator if */
2313                 extern struct sysdata sysidlist[]; /* it is missing...   */
2314                 debug(F101,"parsdir myindex","",myindex);
2315                 if (myindex > -1)
2316                   if (sysidlist[myindex].sid_unixlike)
2317                     if (c != sysidlist[myindex].sid_dirsep) {
2318                         dirsep[0] = sysidlist[myindex].sid_dirsep;
2319                         dirsep[1] = NUL;
2320                         strcat(pp[dd], (char *) dirsep); /* safe */
2321                     }
2322             }
2323 #endif /* NOXFER */
2324             debug(F111,"parsdir pp[dd] 2",pp[dd],dd);
2325             if (++dd > max) {
2326                 printf("?Too many directories - %d max\n", max);
2327                 for (i = 0; i < dd; i++) {  /* Free temp storage */
2328                     if (pp[i]) free(pp[i]);
2329                     pp[i] = NULL;
2330                 }
2331             }
2332         }
2333     }
2334 #endif /* CK_PARSDIR */
2335 }
2336 #endif /* NOSPL */
2337
2338 #ifndef NOSERVER
2339 static int
2340 cklogin() {
2341     int x;
2342     char * s;
2343     char username[LOGINLEN+1];
2344     char password[LOGINLEN+1];
2345     char account[LOGINLEN+1];
2346     extern char * x_user, * x_passwd, * x_acct;
2347     extern int x_login, x_logged;
2348
2349     username[0] = NUL;
2350     password[0] = NUL;
2351     account[0]  = NUL;
2352
2353     x = cmfld("username", "", &s, xxstring);
2354     if (x != -3) {
2355         if (x < 0)
2356           return(x);
2357         if ((int)strlen(s) > LOGINLEN) {
2358             printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2359             return(-9);
2360         }
2361         ckstrncpy(username,s,LOGINLEN+1);
2362         x = cmfld("password", "", &s, xxstring);
2363         if (x != -3) {
2364             if (x < 0)
2365               return(x);
2366             if ((int)strlen(s) > LOGINLEN) {
2367                 printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2368                 return(-9);
2369             }
2370             ckstrncpy(password,s,LOGINLEN+1);
2371             x = cmfld("account", "", &s, xxstring);
2372             if (x != -3) {
2373                 if (x < 0)
2374                   return(x);
2375                 if ((int)strlen(s) > LOGINLEN) {
2376                     printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2377                     return(-9);
2378                 }
2379                 ckstrncpy(account,s,LOGINLEN+1);
2380                 if ((x = cmcfm()) < 0)
2381                   return(x);
2382             }
2383         }
2384     }
2385     makestr(&x_user,username);
2386     makestr(&x_passwd,password);
2387     makestr(&x_acct,account);
2388     x_login = (x_user) ? 1 : 0;
2389     x_logged = 0;
2390     return(1);
2391 }
2392 #endif /* NOSERVER */
2393
2394 #ifndef NOLOCAL
2395 static int
2396 setdcd() {
2397     int x, y, z = 0;
2398     if ((y = cmkey(crrtab,ncrr,"","automatic",xxstring)) < 0) return(y);
2399     if (y == CAR_ON) {
2400         x = cmnum("Carrier wait timeout, seconds","0",10,&z,xxstring);
2401         if (x < 0) return(x);
2402     }
2403     if ((x = cmcfm()) < 0) return(x);
2404     carrier = ttscarr(y);
2405     cdtimo = z;
2406     return(1);
2407 }
2408 #endif /* NOLOCAL */
2409
2410 extern struct keytab yesno[];
2411 extern int nyesno;
2412
2413 /* g e t y e s n o  */
2414
2415 static struct keytab q0yesno[] = {      /* Yes/No/Quit keyword table */
2416     "no",    0, 0,
2417     "ok",    1, 0,
2418     "yes",   1, 0
2419 };
2420 static int nq0yesno = (sizeof(q0yesno) / sizeof(struct keytab));
2421
2422 static struct keytab q1yesno[] = {      /* Yes/No/Quit keyword table */
2423     "no",    0, 0,
2424     "ok",    1, 0,
2425     "quit",  2, 0,
2426     "yes",   1, 0
2427 };
2428 static int nq1yesno = (sizeof(q1yesno) / sizeof(struct keytab));
2429
2430 static struct keytab q2yesno[] = {      /* Yes/No/Quit keyword table */
2431     "go",    3, 0,
2432     "no",    0, 0,
2433     "ok",    1, 0,
2434     "yes",   1, 0
2435 };
2436 static int nq2yesno = (sizeof(q2yesno) / sizeof(struct keytab));
2437
2438 static struct keytab q3yesno[] = {      /* Yes/No/Quit keyword table */
2439     "go",    3, 0,
2440     "no",    0, 0,
2441     "ok",    1, 0,
2442     "quit",  2, 0,
2443     "yes",   1, 0
2444 };
2445 static int nq3yesno = (sizeof(q3yesno) / sizeof(struct keytab));
2446
2447
2448 /* Ask question, get yes/no answer */
2449
2450 int
2451 getyesno(msg, flags) char * msg; int flags; {
2452 #ifdef CK_RECALL
2453     extern int on_recall;               /* around Password prompting */
2454 #endif /* CK_RECALL */
2455     int y, z;
2456
2457 #ifndef NOLOCAL
2458 #ifdef OS2
2459     extern int vmode, win95_popup, startflags;
2460     int vmode_sav = vmode;
2461 #endif /* OS2 */
2462 #endif /* NOLOCAL */
2463
2464 #ifdef CK_APC
2465     if ( apcactive != APC_INACTIVE && (apcstatus & APC_NOINP) ) {
2466         return(success = 0);
2467     }
2468 #endif /* CK_APC */
2469
2470 #ifndef NOLOCAL
2471 #ifdef OS2
2472 #ifdef COMMENT
2473     if (win95_popup && !(startflags & 96)
2474 #ifdef IKSD
2475         && !inserver
2476 #endif /* IKSD */
2477         )
2478       return(popup_readyesno(vmode,NULL,msg,flags));
2479 #endif /* COMMENT */
2480     if (vmode == VTERM) {
2481         vmode = VCMD;
2482         VscrnIsDirty(VTERM);
2483         VscrnIsDirty(VCMD);
2484     }
2485 #endif /* OS2 */
2486 #endif /* NOLOCAL */
2487 #ifdef VMS
2488 /*
2489   In VMS, whenever a TAKE file or macro is active, we restore the
2490   original console modes so Ctrl-C/Ctrl-Y can work.  But here we
2491   go interactive again, so we have to temporarily put them back.
2492 */
2493     if (!xcmdsrc)
2494       concb((char)escape);
2495 #endif /* VMS */
2496
2497 #ifdef CK_RECALL
2498     on_recall = 0;
2499 #endif /* CK_RECALL */
2500     cmsavp(psave,PROMPTL);              /* Save old prompt */
2501     cmsetp(msg);                        /* Make new prompt */
2502     z = 0;                              /* Initialize answer to No. */
2503     cmini(ckxech);                      /* Initialize parser. */
2504     do {
2505         prompt(NULL);                   /* Issue prompt. */
2506         switch (flags) {
2507           case 0:  y = cmkey(q0yesno,nq0yesno,"","",NULL); break;
2508           case 1:  y = cmkey(q1yesno,nq1yesno,"","",NULL); break;
2509           case 2:  y = cmkey(q2yesno,nq2yesno,"","",NULL); break;
2510           default: y = cmkey(q3yesno,nq3yesno,"","",NULL);
2511         }
2512         if (y < 0) {
2513             if (y == -4) {              /* EOF */
2514                 z = y;
2515                 break;
2516             } else if (y == -3)         /* No answer? */
2517               printf(" Please respond; type '?' to see valid answers.\n");
2518             cmini(ckxech);
2519         } else {
2520             z = y;                      /* Save answer */
2521             y = cmcfm();                /* Get confirmation */
2522         }
2523     } while (y < 0);                    /* Continue till done */
2524     cmsetp(psave);                      /* Restore real prompt */
2525 #ifdef VMS
2526     if (cmdlvl > 0)                     /* In VMS and not at top level, */
2527       conres();                         /*  restore console again. */
2528 #endif /* VMS */
2529 #ifndef NOLOCAL
2530 #ifdef OS2
2531     if (vmode != vmode_sav) {
2532         vmode = VTERM;
2533         VscrnIsDirty(VCMD);
2534         VscrnIsDirty(VTERM);
2535     }
2536 #endif /* OS2 */
2537 #endif /* NOLOCAL */
2538     return(z);
2539 }
2540
2541 #ifdef KUI
2542 extern HWND hwndConsole;
2543 _PROTOTYP(int gui_txt_dialog,(char *,char *,int,char *,int,char *,int));
2544 _PROTOTYP(int gui_mtxt_dialog,(char *,int,struct txtbox []));
2545 _PROTOTYP(int gui_position,(int, int));
2546 _PROTOTYP(int gui_resize_mode,(int));
2547 _PROTOTYP(int gui_win_run_mode,(int));
2548 _PROTOTYP(int gui_saveas_dialog,(char *,char *, int, char *, char *, int));
2549 extern int gui_dialog;
2550 #endif /* KUI */
2551
2552 /* u q _ o k  --  User Query, get Yes/No or OK Cancel  */
2553 /*
2554   Call with:  
2555     preface: Explanatory text to print, or NULL.
2556     prompt:  Prompt.
2557     mask:    Bitmask for legal responses: 1 = OK or Yes; 2 = No or Cancel.
2558     help:    Help text (array of strings or NULL) [not used by parser].
2559     dflt:    Default response (1 or 2) [not used by parser].
2560   Returns:
2561    -1:       Invalid argument(s).
2562     0:       User said No or Cancel.
2563     1        User said Yes or OK.    
2564   Notes:
2565     preface and prompt should not include final line terminator but may
2566     include embedded ones.  Help text is in case GUI dialog needs a Help
2567     button; final element of help-string array is "".  dflt is used by GUI
2568     to highlight the default response button.
2569 */
2570 int
2571 #ifdef CK_ANSIC
2572 uq_ok(char * preface, char * prompt, int mask,char ** help, int dflt)
2573 #else /* CK_ANSIC */
2574 uq_ok(preface,prompt,mask,help,dflt)
2575     char * preface, * prompt, ** help;
2576     int mask, dflt;
2577 #endif /* CK_ANSIC */
2578 /* uq_ok */ {
2579     int rc, len;
2580     char * text=NULL;
2581
2582     if (!prompt)
2583       return(-1);
2584
2585     if ((mask & 3) == 1) {              /* OK (GUI only) */
2586 #ifdef KUI
2587       if ( gui_dialog ) {
2588         /* This one is for popup help, alerts, etc */
2589         if (preface) {
2590             len = strlen(preface) + strlen(prompt) + 4;
2591             text = (char *)malloc(len);
2592             ckmakmsg(text,len,preface,"\n",prompt,NULL);
2593         }
2594         rc = MessageBox(hwndConsole,
2595                          text ? text : prompt,
2596                          prompt,
2597                          MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2598         ShowWindowAsync(hwndConsole,SW_SHOWNORMAL);
2599         SetForegroundWindow(hwndConsole);
2600         if (text)
2601           free(text);
2602         if (!rc)
2603           return(-1);
2604         else 
2605           return(1);
2606       } else
2607 #endif  /* KUI */
2608       {
2609         if (preface)                    /* Just display the text, if any */
2610           printf("%s\n",preface);
2611         if (prompt)
2612           printf("%s\n",prompt);
2613         return(1);
2614       }
2615     } else if ((mask & 3) == 3) {       /* Yes/No or OK/Cancel */
2616 #ifdef KUI
2617       if ( gui_dialog ) {
2618         if (preface) {
2619             len = strlen(preface) + strlen(prompt) + 4;
2620             text = (char *)malloc(len);
2621             ckmakmsg(text,len,preface,"\n",prompt,NULL);
2622         }
2623         rc = MessageBox(hwndConsole,
2624                          text ? text : prompt,
2625                          prompt,
2626                          MB_YESNO | MB_ICONINFORMATION | MB_TASKMODAL | 
2627                          (dflt == 2 ? MB_DEFBUTTON2 : MB_DEFBUTTON1));
2628         ShowWindowAsync(hwndConsole,SW_SHOWNORMAL);
2629         SetForegroundWindow(hwndConsole);
2630         if (text)
2631           free(text);
2632         if (!rc)
2633           return(-1);
2634         else if (rc == IDNO || rc == IDCANCEL)
2635           return(0);
2636         else
2637           return(1);
2638       } else
2639 #endif  /* KUI */
2640       {
2641         if (preface)
2642           printf("%s\n",preface);
2643         return(getyesno(prompt,0));
2644       }
2645     } else {
2646         printf("?Internal error: uq_ok()\n");
2647         return(-1);
2648     }
2649 }
2650
2651 /* u q _ t x t  --  User Query, get single text response  */
2652 /*
2653   Call with:  
2654     preface: Explanatory text to print, or NULL.
2655     prompt:  Prompt. 
2656     echo:    0 = don't echo; 1 = echo; 2 = echo with asterisks.
2657     help:    Help text (array of strings or NULL) [not used by parser].
2658     buf:     Pointer to result buffer.
2659     buflen:  Length of result buffer.
2660     dflt:    Default response text or NULL [not used by parser].
2661     timer:   Optional Timeout
2662   Returns:
2663     0:       User said No or Cancel.
2664     1        User said Yes or OK.    
2665   Notes:
2666     preface, prompt, and help as for uq_ok().
2667 */
2668 int
2669 #ifdef CK_ANSIC
2670 uq_txt(char * preface, char * prompt, int echo, char ** help, char * buf, 
2671        int buflen, char *dflt, int timer)
2672 #else /* CK_ANSIC */
2673 uq_txt(preface,prompt,echo,help,buf,buflen,dflt,timer)
2674     char * preface, * prompt, ** help, * buf, * dflt; 
2675     int buflen, echo, timer;
2676 #endif /* CK_ANSIC */
2677 {
2678 #ifndef NOLOCAL
2679 #ifdef OS2
2680     extern int vmode;
2681     extern int startflags;
2682     extern int win95_popup;
2683 #endif /* OS2 */
2684 #endif /* NOLOCAL */
2685     int rc; 
2686
2687     if (buflen < 1 || !buf)
2688       return(0);
2689 #ifdef KUI
2690     if ( gui_dialog ) {
2691         rc = gui_txt_dialog(preface,prompt,echo,buf,buflen,dflt,timer);
2692         if ( rc > -1 )
2693             return(rc);
2694     /* Otherwise, the dialog could not be created.  Fallback to text mode */
2695     } 
2696 #endif /* KUI */
2697 #ifndef NOLOCAL
2698 #ifdef OS2
2699     if (win95_popup && !(startflags & 96)
2700 #ifdef IKSD
2701          && !inserver
2702 #endif /* IKSD */
2703          ) {
2704         debok = 0;                          /* Don't log */
2705         if (echo == 1)
2706                 popup_readtext(vmode,preface,prompt,buf,buflen,0);
2707             else
2708                 popup_readpass(vmode,preface,prompt,buf,buflen,0);
2709         debok = 1;
2710         return(1);
2711     }
2712 #endif /* OS2 */
2713 #endif /* NOLOCAL */
2714
2715     if (preface)
2716       printf("%s\n",preface);
2717     if (echo == 1)
2718       readtext(prompt,buf,buflen);
2719     else
2720       readpass(prompt,buf,buflen);
2721     return(1);                          /* (no buttons in parser) */
2722 }
2723
2724 /* u q _ m t x t  --  User Query, get multiple text responses */
2725 /*
2726   Call with:  
2727     preface: Explanatory text to print, or NULL.
2728     help:    Help text (array of strings or NULL) [not used by parser].
2729     n:       Number of responses wanted.
2730     field:   Array of struct txtbox, one element per field, see ckuusr.h.
2731   Returns:
2732     0:       User said No or Cancel.
2733     1        User said Yes or OK.    
2734   Notes:
2735     preface and help as for uq_ok().
2736 */
2737 int
2738 #ifdef CK_ANSIC
2739 uq_mtxt(char * preface,char **help, int n, struct txtbox field[])
2740 #else /* CK_ANSIC */
2741 uq_mtxt(preface,help,n,field)
2742     char * preface; char ** help; int n; struct txtbox field[]; 
2743 #endif /* CK_ANSIC */
2744 {
2745 #ifndef NOLOCAL
2746 #ifdef OS2
2747     extern int vmode;
2748     extern int startflags;
2749     extern int win95_popup;
2750 #endif /* OS2 */
2751 #endif /* NOLOCAL */
2752     int i, rc;
2753
2754     if (n < 1 || !field)
2755       return(0);
2756 #ifdef KUI
2757     if ( gui_dialog ) {
2758         rc = gui_mtxt_dialog(preface, n, field);
2759         if ( rc > -1 )
2760             return(rc);
2761     /* Otherwise, the dialog could not be created.  Fallback to text mode */
2762     }
2763 #endif /* KUI */
2764 #ifndef NOLOCAL
2765 #ifdef OS2
2766     if (win95_popup && !(startflags & 96)
2767 #ifdef IKSD
2768          && !inserver
2769 #endif /* IKSD */
2770          ) {
2771         debok = 0;                          /* Don't log */
2772         for (i = 0; i < n; i++) {
2773             if (field[i].t_echo == 1)
2774                 popup_readtext(vmode,preface,field[i].t_lbl,field[i].t_buf,field[i].t_len,0);
2775             else
2776                 popup_readpass(vmode,preface,field[i].t_lbl,field[i].t_buf,field[i].t_len,0);
2777         }
2778         debok = 1;
2779         return(1);
2780     }
2781 #endif /* OS2 */
2782 #endif /* NOLOCAL */
2783
2784     if (preface)
2785       printf("%s\n",preface);
2786     for (i = 0; i < n; i++) {
2787         if (field[i].t_echo == 1)
2788           readtext(field[i].t_lbl,field[i].t_buf,field[i].t_len);
2789         else
2790           readpass(field[i].t_lbl,field[i].t_buf,field[i].t_len);
2791     }
2792     return(1);
2793 }
2794
2795 /* u q _ f i l e  --  User Query, get file or directory name  */
2796 /*
2797   Call with:  
2798     preface: Explanatory text to print, or NULL.
2799     prompt:  Prompt string.
2800     fc:      Function code:
2801                1 = input (existing) file
2802                2 = existing directory 
2803                3 = create new output file
2804                4 = output file allowing append access
2805     help:    Help text (array of strings or NULL) [not used by parser].
2806     dflt:    Default response.
2807     result:  Pointer to result buffer.
2808     rlength: Length of result buffer.
2809
2810   Returns:
2811    -1:       Invalid argument, result too long, or other error.
2812     0:       User Canceled.
2813     1:       OK, with file/pathname copied to result buffer.
2814     2:       Like 1, but for output file that is to be appended to.
2815
2816   Notes:
2817     1. preface and prompt should not include final line terminator but may
2818        include embedded ones.  Help text is in case GUI dialog needs a Help
2819        button; final element of help-string array is "".
2820
2821     2. The default might be a filename, a directory name, a relative
2822        pathname, or an absolute pathname.  This routine must convert it into
2823        into a fully qualified (absolute) pathname so the user knows exactly
2824        where the file is to be found or stored.  In addition, the Windows
2825        version of this routine must separate the directory part from the
2826        name part, so it can display the given directory in the file dialog,
2827        and put name in the filename box to be edited, replaced, or
2828        accepted.
2829
2830     3. When called with FC 4, the Windows version should include "New" and
2831        "Append" buttons in the dialog. so the user can say whether the file
2832        should overwrite any file of the same name, or be appended to it.
2833 */
2834
2835 int
2836 #ifdef CK_ANSIC
2837 uq_file(char * preface, char * fprompt, int fc, char ** help,
2838         char * dflt, char * result, int rlength)
2839 #else /* CK_ANSIC */
2840 uq_file(preface,fprompt,fc,help,dflt,result,rlength)
2841     char * preface, * fprompt, ** help, * dflt, * result;
2842     int fc, rlength;
2843 #endif /* CK_ANSIC */
2844 /* uq_file */ {
2845
2846     int rc = -1, x, y, z;
2847     char * s, * p, * fullpath;
2848     char filebuf[CKMAXPATH+1];
2849
2850 #ifdef CK_RECALL
2851     extern int on_recall;
2852 #endif /* CK_RECALL */
2853
2854 #ifdef KUI
2855     if ( gui_dialog ) {
2856         rc = gui_saveas_dialog(preface,fprompt,fc,dflt,result,rlength);
2857         return rc;
2858     }
2859 #endif /* KUI */
2860
2861 #ifdef CK_RECALL
2862     on_recall = 0;
2863 #endif /* CK_RECALL */
2864
2865     if (preface)                        /* If prefatory text given... */
2866       printf("%s\n",preface);           /* display it. */
2867
2868     cmsavp(psave,PROMPTL);              /* Save old prompt */
2869
2870     /* We get the full pathname of the proposed output file just so */
2871     /* we can show it to the user but we don't use it ourselves. */
2872
2873     p = NULL;                           /* Build new prompt */
2874     if (!dflt) dflt = "";
2875     if (*dflt)                          /* Have default filename */
2876       zfnqfp(dflt,CKMAXPATH+1,filebuf); /* Get full path */
2877     else
2878       ckmakmsg(filebuf,CKMAXPATH+1,zgtdir(),"newfile",NULL,NULL);
2879     fullpath = filebuf;
2880     x = strlen(fullpath);
2881
2882     /* If no prompt given, build one that shows the proposed full pathname. */
2883
2884     if (!fprompt) fprompt = "";
2885     if (!*fprompt) fprompt = x ? " Filename" : " Filename: ";
2886     y = strlen(fprompt);
2887     if (x > 0) {                        /* Have default pathname? */
2888         p = (char *)malloc(x + y + 7);  /* Get temp storage */
2889         if (p) {                        /* Build prompt */
2890             ckmakmsg(p,x+y+7,fprompt," [",fullpath,"]: ");
2891             fprompt = p;
2892         }
2893     }
2894     cmsetp(fprompt);                    /* Make new prompt */
2895     if (p) free(p);                     /* Free temp storage */
2896     cmini(ckxech);                      /* Initialize parser. */
2897     x = -1;
2898     do {
2899         prompt(NULL);                   /* Issue prompt. */
2900         switch (fc) {                   /* Parse depends on function code */
2901           case 1:                       /* Input file */
2902             x = cmifi("Name of existing file",dflt,&s,&y,xxstring);
2903             rc = 1;
2904             break;
2905           case 2:                       /* Directory */
2906             x = cmdir("Directory name",dflt,&s,xxstring);
2907             rc = 1;
2908             break;
2909           case 3:                       /* New output file */
2910             /* Fall thru... */
2911           case 4:                       /* Output file - Append allowed */
2912             x = cmofi("Output file specification",dflt,&s,xxstring);
2913             rc = (fc == 4) ? 1 : 2;
2914             break;
2915           default:                      /* Bad function code */
2916             goto x_uq_file;
2917         }
2918         if (x < 0) {                    /* Parse error */
2919             filebuf[0] = NUL;
2920             if (x == -4) {              /* EOF */
2921                 break;
2922             } else if (x == -3)         /* No answer? */
2923               printf(fc == 2 ?
2924                      " Please enter a directory name.\n" :
2925                      " Please enter a filename.\n"
2926                      );
2927             cmini(ckxech);
2928         } else {
2929             z = strlen(s);
2930             if (z > rlength || ckstrncpy(filebuf,brstrip(s),CKMAXPATH+1) < z) {
2931                 printf("?Name too long\n");
2932                 x = -9;
2933             } else
2934               x = cmcfm();              /* Get confirmation */
2935         }
2936         if (fc == 1 && x > -1 && y > 0) {
2937             printf("?Wildcards not allowed\n");
2938             x = -9;
2939         }
2940     } while (x < 0);                    /* Continue till done */
2941
2942   x_uq_file:
2943     if (x < 0)
2944       rc = -1;
2945
2946     cmsetp(psave);                      /* Restore real prompt */
2947
2948     if (rc > 0)
2949       ckstrncpy(result,filebuf,rlength);
2950     return(rc);
2951 }
2952
2953
2954 #ifdef CK_PERMS
2955 #ifdef UNIX
2956
2957 _PROTOTYP( int zsetperm, (char *, int));
2958
2959 /* CHMOD command for UNIX only */
2960
2961 #define CHM_DIR 0
2962 #define CHM_DOT 1
2963 #define CHM_FIL 2
2964 #define CHM_LIS 3
2965 #define CHM_NOL 4
2966 #define CHM_QUI 5
2967 #define CHM_REC 6
2968 #define CHM_VRB 7
2969 #define CHM_PAG 8
2970 #define CHM_NOP 9
2971 #define CHM_TYP 10
2972 #define CHM_SIM 11
2973
2974 static struct keytab uchmodsw[] = {
2975     "/directories", CHM_DIR, 0,
2976     "/dotfiles",    CHM_DOT, 0,
2977     "/files",       CHM_FIL, 0,
2978     "/list",        CHM_LIS, 0,
2979     "/nolist",      CHM_NOL, 0,
2980     "/nopage",      CHM_NOP, 0,
2981     "/page",        CHM_PAG, 0,
2982     "/quiet",       CHM_QUI, CM_INV,
2983     "/recursive",   CHM_REC, 0,
2984     "/simulate",    CHM_SIM, 0,
2985     "/type",        CHM_TYP, CM_ARG,
2986     "/verbose",     CHM_VRB, CM_INV,
2987 };
2988 static int nchmodsw = (sizeof(uchmodsw) / sizeof(struct keytab));
2989
2990 int
2991 douchmod() {
2992     extern int recursive, nscanfile, diractive;
2993 #ifdef CK_TTGWSIZ
2994     extern int tt_rows, tt_cols;
2995     int n = 0;
2996 #endif /* CK_TTGWSIZ */
2997     int i, files = 1, t1 = 1, t2 = 0, x, y, z, verbose = 0, rc = 1, paging;
2998     int xmode = -1, fs = 0, getval = 0, simulate = 0, wild = 0;
2999     char c, * s;
3000     struct FDB sw, nu;
3001
3002     if (xaskmore < 0) {
3003 #ifdef CK_TTGWSIZ
3004         xaskmore = 1;
3005 #else
3006         xaskmore = 0;
3007 #endif /* CK_TTGWSIZ */
3008     }
3009     paging = xaskmore;
3010
3011     cmfdbi(&sw,                         /* First FDB - command switches */
3012            _CMKEY,                      /* fcode */
3013            "Octal file permission code, or switch",
3014            "",                          /* default */
3015            "",                          /* addtl string data */
3016            nchmodsw,                    /* addtl numeric data 1: tbl size */
3017            4,                           /* addtl numeric data 2: 4 = cmswi */
3018            xxstring,                    /* Processing function */
3019            uchmodsw,                    /* Keyword table */
3020            &nu                          /* Pointer to next FDB */
3021            );
3022     cmfdbi(&nu,
3023            _CMNUM,                      /* Number */
3024            "",                          /* Help message */
3025            "",                          /* Default */
3026            "",                          /* N/A */
3027            8,                           /* Radix = 8 */
3028            0,                           /* N/A */
3029            xxstring,                    /* Processing function */
3030            NULL,                        /* N/A */
3031            NULL                         /* Next */
3032            );
3033
3034     while (1) {
3035         if ((x = cmfdb(&sw)) < 0) {
3036             if (x == -3) {
3037                 x = -9;
3038                 printf("?Filename required\n");
3039             }
3040             return(x);
3041         }
3042         if (cmresult.fcode != _CMKEY)
3043           break;
3044         c = cmgbrk();
3045         getval = (c == ':' || c == '=');
3046         if (getval && !(cmgkwflgs() & CM_ARG)) {
3047             printf("?This switch does not take an argument\n");
3048             return(-9);
3049         }
3050         if (!getval && (cmgkwflgs() & CM_ARG)) {
3051             printf("?This switch requires an argument\n");
3052             return(-9);
3053         }
3054         switch (cmresult.nresult) {
3055           case CHM_DIR:
3056             t1 = 1;
3057             t2 = 1;
3058             break;
3059           case CHM_DOT:
3060             matchdot = 1;
3061             break;
3062           case CHM_FIL:
3063             t1 = 0;
3064             t2 = 0;
3065             break;
3066           case CHM_LIS:
3067           case CHM_VRB:
3068             verbose = 1;
3069             break;
3070           case CHM_NOL:
3071           case CHM_QUI:
3072             verbose = 0;
3073             break;
3074           case CHM_REC:
3075             recursive = 1;
3076             break;
3077           case CHM_PAG:
3078             verbose = 1;
3079             paging = 1;
3080             break;
3081           case CHM_NOP:
3082             paging = 0;
3083             break;
3084           case CHM_SIM:
3085             simulate = 1;
3086             break;
3087           case CHM_TYP: {
3088               extern struct keytab txtbin[];
3089               if ((x = cmkey(txtbin,3,"","",xxstring)) < 0)
3090                 return(x);
3091               if (x == 2) {             /* ALL */
3092                   xmode = -1;
3093               } else {                  /* TEXT or BINARY only */
3094                   xmode = x;
3095                   fs = 1;
3096               }
3097               break;
3098           }
3099         }
3100     }
3101     z = cmresult.nresult;
3102     x = cmifi2("File specification","",&s,&wild,t1,NULL,xxstring,t2);
3103     if (x < 0) {
3104         if (x == -3) {
3105             printf("?A file specification is required\n");
3106             return(-9);
3107         } else
3108           return(x);
3109     }
3110     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
3111     s = tmpbuf;
3112     if ((x = cmcfm()) < 0)
3113       return(x);
3114 #ifdef ZXREWIND
3115     if (wild) files = zxrewind();
3116 #else
3117     if (wild) files = nzxpand(s,0);
3118 #endif /* ZXREWIND */
3119
3120     if (paging > -1)
3121       xaskmore = paging;
3122
3123 #ifdef CK_TTGWSIZ
3124     if (verbose && paging) {
3125 #ifdef OS2
3126         ttgcwsz();
3127 #else /* OS2 */
3128         if (ttgwsiz() > 0) {
3129             if (tt_rows > 0 && tt_cols > 0) {
3130                 cmd_rows = tt_rows;
3131                 cmd_cols = tt_cols;
3132             }
3133         }
3134 #endif /* OS2 */
3135     }
3136 #endif /* CK_TTGWSIZ */
3137
3138     for (i = 0; i < files; i++) {
3139         if (files == 1 && wild == 0) {  /* For "chmod 777 ." */
3140             ckstrncpy(line,s,LINBUFSIZ);
3141         } else {
3142             x = znext(line);
3143             if (x < 1) {
3144                 if (i == 0) {
3145                     printf("?No files match - \"%s\"\n",line);
3146                     return(-9);
3147                 }
3148                 return(1);
3149             }
3150         }
3151         if (fs) {
3152 #ifdef VMSORUNIX
3153             /* If /TYPE:TEXT or BINARY given, skip directories and links */
3154             /* since they are neither text nor binary. */
3155             extern int zgfs_dir, zgfs_link;
3156             zgetfs(line);
3157             if (zgfs_dir || zgfs_link)
3158               continue;
3159 #else
3160             if (zchki(line) < 0)
3161               continue;
3162 #endif /* VMSORUNIX */
3163             /* Regular file, scan it */
3164             switch (scanfile(line,&y,nscanfile)) {
3165               case FT_BIN:
3166                 if (xmode != 1)
3167                   continue;
3168                 break;
3169               case FT_TEXT:
3170               case FT_7BIT:
3171               case FT_8BIT:
3172 #ifdef UNICODE
3173               case FT_UTF8:
3174               case FT_UCS2:
3175 #endif /* UNICODE */
3176                 if (xmode != 0)
3177                   continue;
3178             }
3179         }
3180         if (simulate) {
3181 #ifdef UNIX
3182             extern int zchkod;          /* Unidentified Flying */
3183             int xx = zchkod;            /* API Extension... */
3184             zchkod = 1;
3185 #endif /* UNIX */
3186             if (zchko(line) < 0)
3187               printf("%s - Access denied\n",line);
3188             else
3189               printf("%s - OK\n",line);
3190 #ifdef UNIX
3191             zchkod = xx;
3192 #endif /* UNIX */
3193         } else {
3194             if (zsetperm(line,z) < 1) {
3195                 if (verbose || files < 2) {
3196                     printf("%s: %s\n",line,ck_errstr());
3197                 }
3198                 rc = 0;
3199             } else if (verbose) {
3200                 printf("%s  %s\n",ziperm(line),line);
3201             }
3202         }
3203 #ifdef CK_TTGWSIZ
3204         if (verbose && paging) {        /* Pause at end of screen */
3205             if (cmd_rows > 0 && cmd_cols > 0) {
3206                 if (++n > cmd_rows - 3) {
3207                     if (!askmore())
3208                       break;
3209                     else
3210                       n = 0;
3211                 }
3212             }
3213         }
3214 #endif /* CK_TTGWSIZ */
3215
3216     }
3217     return(success = rc);
3218 }
3219 #endif /* UNIX */
3220 #endif /* CK_PERMS */
3221
3222 #ifndef NOSPL                           /* S-Expressions */
3223 #ifndef NOSEXP
3224
3225 struct keytab sexptab[] = {
3226     "depth-limit", 1, 0,
3227     "echo-result", 0, 0
3228 };
3229
3230 static int sexpmaxdep = 1000;           /* Maximum depth */
3231
3232 #define xxfloat(s,x) \
3233 ((isdigit(*s)||(*s=='-')||(*s=='+')||(*s=='.')||(*s=='\040'))?isfloat(s,x):0)
3234
3235 #define SX_ADD  1                       /* Symbols for built-in operators */
3236 #define SX_SUB  2
3237 #define SX_MUL  3
3238 #define SX_DIV  4
3239 #define SX_POW  5
3240 #define SX_SET  6
3241 #define SX_MOD  7
3242 #define SX_EVA  8
3243 #define SX_EXP  9
3244 #define SX_AEQ 10
3245 #define SX_ALT 11
3246 #define SX_AGT 12
3247 #define SX_ALE 13
3248 #define SX_AGE 14
3249 #define SX_MIN 15
3250 #define SX_MAX 16
3251 #define SX_SQR 17
3252 #define SX_FLR 18
3253 #define SX_CEI 19
3254 #define SX_TRU 20
3255 #define SX_ABS 21
3256 #define SX_ROU 22
3257 #define SX_LET 23
3258 #define SX_LGN 24
3259 #define SX_LGX 25
3260 #define SX_FLO 26
3261 #define SX_IFC 27
3262 #define SX_NOT 28
3263 #define SX_NEQ 29
3264 #define SX_AND 30
3265 #define SX_LOR 31
3266 #define SX_SIN 32
3267 #define SX_COS 33
3268 #define SX_TAN 34
3269 #define SX_BWA 35
3270 #define SX_BWO 36
3271 #define SX_BWX 37
3272 #define SX_BWN 38
3273 #define SX_XOR 39
3274 #define SX_INC 40
3275 #define SX_DEC 41
3276 #define SX_QUO 42
3277 #define SX_STR 43
3278
3279 /* Operator flags */
3280
3281 #define SXF_PRE 256                     /* Predicate */
3282 #define SXF_ONE 512                     /* Requires one arg */
3283 #define SXF_TWO 1024                    /* Requires two args or more */
3284 #define SXF_FLO 2048                    /* Coerce to floating-point */
3285
3286 /* Built-in constants */
3287
3288 #define SXC_NIL 1                       /* NIL */
3289 #define SXC_PI  2                       /* PI */
3290 #define SXC_T   3                       /* T */
3291
3292 /*
3293   This is an xlookup() table and so need not be in "alhabetical" order.
3294   Therefore entries are arranged to minimize search for most common
3295   operators.
3296 */
3297 static struct keytab sexpops[] = {      /* Built-in operators */
3298     "setq",    SX_SET, 0,               /* Global assignment */
3299     "+",       SX_ADD, 0,               /* Simple arithmetic */
3300     "-",       SX_SUB, 0,
3301     "*",       SX_MUL, 0,
3302     "/",       SX_DIV, SXF_TWO,
3303     "^",       SX_POW, SXF_TWO,
3304
3305     "if",      SX_IFC, SXF_TWO,         /* IF */
3306     "let",     SX_LET, 0,               /* Local assignment */
3307     "not",     SX_NOT, SXF_ONE,         /* NOT */
3308     "mod",     SX_MOD, SXF_TWO,         /* Modulus */
3309
3310     "<",       SX_ALT, SXF_PRE|SXF_TWO, /* Comparisons */
3311     ">",       SX_AGT, SXF_PRE|SXF_TWO,
3312     "<=",      SX_ALE, SXF_PRE|SXF_TWO,
3313     "=",       SX_AEQ, SXF_PRE|SXF_TWO,
3314     ">=",      SX_AGE, SXF_PRE|SXF_TWO,
3315     "!=",      SX_NEQ, SXF_PRE|SXF_TWO,
3316
3317     "++",      SX_INC, SXF_ONE|SXF_TWO, /* Increment */
3318     "--",      SX_DEC, SXF_ONE|SXF_TWO, /* Decrement */
3319
3320     "**",      SX_POW, SXF_TWO,         /* Common synonyms */
3321     "==",      SX_AEQ, SXF_PRE|SXF_TWO,
3322     "!",       SX_NOT, SXF_ONE,
3323     ".",       SX_EVA, 0,
3324
3325     "and",     SX_AND, 0,               /* Logical operators */
3326     "or",      SX_LOR, 0,
3327     "xor",     SX_XOR, SXF_TWO,
3328
3329     "max",     SX_MAX, SXF_ONE|SXF_TWO, /* Max and min */
3330     "min",     SX_MIN, SXF_ONE|SXF_TWO,
3331
3332     "%",       SX_MOD, SXF_TWO,         /* More synonyms */
3333     "||",      SX_LOR, 0,
3334     "&&",      SX_AND, 0,
3335
3336     "quote",   SX_QUO, SXF_ONE,
3337     "string",  SX_STR, SXF_ONE,
3338
3339     "eval",    SX_EVA, 0,               /* Assorted commands */
3340     "abs",     SX_ABS, SXF_ONE,
3341     "truncate",SX_TRU, SXF_ONE|SXF_FLO,
3342     "round",   SX_ROU, SXF_ONE|SXF_FLO,
3343     "ceiling", SX_CEI, SXF_ONE|SXF_FLO,
3344     "floor",   SX_FLR, SXF_ONE|SXF_FLO,
3345     "float",   SX_FLO, SXF_ONE|SXF_FLO,
3346
3347 #ifdef FNFLOAT
3348     "sqrt",    SX_SQR, SXF_ONE|SXF_FLO, /* Floating point functions */
3349     "exp",     SX_EXP, SXF_ONE|SXF_FLO,
3350     "sin",     SX_SIN, SXF_ONE|SXF_FLO,
3351     "cos",     SX_COS, SXF_ONE|SXF_FLO,
3352     "tan",     SX_TAN, SXF_ONE|SXF_FLO,
3353     "log",     SX_LGN, SXF_ONE|SXF_FLO,
3354     "log10",   SX_LGX, SXF_ONE|SXF_FLO,
3355 #endif /* FNFLOAT */
3356
3357     "#",       SX_BWX, SXF_TWO,         /* Bitwise operators */
3358     "&",       SX_BWA, 0,
3359     "|",       SX_BWO, 0,
3360     "~",       SX_BWN, SXF_ONE,
3361     "", 0, 0                            /* (end) */
3362 };
3363 static int nsexpops = (sizeof(sexpops) / sizeof(struct keytab)) - 1;
3364
3365 static struct keytab sexpconsts[] = {   /* Built-in constants */
3366     "nil", SXC_NIL, 0,                  /* NIL (false) */
3367     "pi",  SXC_PI,  0,                  /* Pi (3.1415926...) */
3368     "t",   SXC_T,   0,                  /* T (true) */
3369     "", 0, 0
3370 };
3371 static int nsexpconsts = (sizeof(sexpconsts) / sizeof(struct keytab)) - 1;
3372
3373 int sexprc = 0;                         /* S-Expression error flag */
3374 int sexppv = -1;                        /* Predicate value */
3375
3376 #define SXMLEN 64                       /* Macro arg list initial length */
3377 #include <math.h>                       /* Floating-point functions */
3378
3379 _PROTOTYP( char * fpformat, (CKFLOAT, int, int) );
3380
3381 extern char math_pi[];                  /* Value of Pi */
3382 extern int sexpecho;                    /* SET SEXPRESSION ECHO value */
3383 extern char * sexpval;                  /* Last top-level S-Expression value */
3384 extern char * lastsexp;                 /* Last S-Expression */
3385 int sexprmax = 0;                       /* Longest result (for stats) */
3386 int sexpdmax = 0;                       /* Max depth reached (for stats) */
3387 int sexpdep  = 0;                       /* dosexp() recursion depth */
3388 static int * sxrlen = NULL;             /* Result stack string sizes */
3389 static char ** sxresult = NULL;         /* Result stack */
3390
3391 /*  s h o s e x p  --  Show S-Expression info  */
3392
3393 VOID
3394 shosexp() {
3395     printf("\n");
3396     printf(" sexpression echo-result: %s\n",showooa(sexpecho));
3397     printf(" sexpression depth-limit: %d\n",sexpmaxdep);
3398     printf("\n");
3399     printf(" maximum depth reached:   %d\n",sexpdmax);
3400     printf(" longest result returned: %d\n",sexprmax);
3401     printf("\n");
3402     printf(" last sexpression:        %s\n",lastsexp ? lastsexp : "(none)");
3403     printf(" last value:              %s\n",sexpval ? sexpval : "(none)");
3404     printf("\n");
3405 }
3406
3407
3408 static char *
3409 sexpdebug(s) char * s; {
3410     /* For debugging -- includes recursion depth in each debug entry */
3411     static char buf[64];
3412     ckmakmsg(buf,64,"dosexp[",ckitoa(sexpdep),"] ",s);
3413     return((char *)buf);
3414 }
3415
3416 /*  d o s e x p  --  S-Expression Reader  */
3417
3418 /*  Returns value as string (empty, numeric, or non-numeric) */
3419
3420 char *
3421 dosexp(s) char *s; {                    /* s = S-Expression */
3422     extern struct mtab *mactab;         /* Macro table */
3423     extern int maclvl, nmac;
3424     extern char *mrval[];
3425     extern int makestrlen;              /* (see makestr()) */
3426     struct stringarray * q = NULL;      /* cksplit() return type */
3427     char * p[SEXPMAX+1], ** p2;         /* List items (must be on stack) */
3428     char * line = NULL;                 /* For building macro argument list */
3429     int nosplit = 0;
3430     int linelen = 0;
3431     int linepos = 0;
3432     int quote = 0;                      /* LISP quote flag */
3433     char * s2;                          /* Workers */
3434     int i, j, k, n = 0, x = 0, kw, kwflags, mx = 0;
3435     int result = 0, not = 0, truncate = 0, builtin = 0;
3436     int fpflag = 0, quit = 0, macro = 0;
3437     CKFLOAT fpj, fpresult = 0.0;        /* Floating-point results */
3438     int pflag = 0;                      /* Have predicate */
3439     int presult = 0;                    /* Predicate result */
3440     int mustfree = 0;                   /* If we malloc'd we must free */
3441
3442     sexppv = -1;                        /* Predicate value */
3443     s2 = "";                            /* Default return value */
3444
3445     if (++sexpdep > sexpmaxdep) {       /* Keep track of depth */
3446         printf("?S-Expression depth limit exceeded: %d\n",sexpmaxdep);
3447         sexprc++;
3448         debug(F111,sexpdebug("max depth exceeded"),s,sexprc);
3449     }
3450     if (sexpdep > sexpdmax)             /* For stats */
3451       sexpdmax = sexpdep;
3452
3453     if (sexprc)                         /* Error, quit all levels */
3454       goto xdosexp;                     /* Always goto common exit point */
3455
3456     debug(F111,sexpdebug("entry"),s,sexprc);
3457
3458     if (!s) s = "";                     /* Null or empty arg */
3459
3460     while (*s == SP) s++;               /* Strip leading spaces */
3461     if (!*s)                            /* so empty result */
3462       goto xdosexp;
3463
3464 /*
3465   Allocate result stack upon first use, or after it has been resized with
3466   SET SEXP DEPTH-LIMIT.
3467 */
3468     if (!sxresult) {
3469         sxresult = (char **)malloc(sexpmaxdep * sizeof(char *));
3470         if (!sxresult) {
3471             printf("?Memory allocation failure - \"%s\"\n", s);
3472             sexprc++;
3473             goto xdosexp;
3474         }
3475         sxrlen = (int *)malloc(sexpmaxdep * sizeof(int));
3476         if (!sxrlen) {
3477             printf("?Memory allocation failure - \"%s\"\n", s);
3478             sexprc++;
3479             goto xdosexp;
3480         }
3481         for (i = 0; i < sexpmaxdep; i++) {
3482             sxresult[i] = NULL;         /* Result pointers */
3483             sxrlen[i] = 0;              /* Buffer sizes */
3484         }
3485     }
3486     s2 = s;                             /* s2 is the result pointer */
3487     k = 0;                              /* Length accumulator */
3488     if (s[0] == '(') {                  /* Starts with open paren? */
3489         while (*s2++) k++;              /* Get length */
3490         if (s[k-1] == ')') {            /* Strip outer parens if any */
3491             s[k-1] = NUL;
3492             s++;
3493             k -= 2;
3494             while (*s == SP) {          /* Strip leading spaces from result */
3495                 s++;
3496                 k--;
3497             }
3498             while (k > 0 && s[k-1] == SP) { /* And trailing spaces. */
3499                 s[k-1] = NUL;
3500                 k--;
3501             }
3502         }
3503         if (!*s) {                      /* If nothing remains */
3504             s2 = "";                    /* return empty result. */
3505             goto xdosexp;
3506         }
3507     }
3508     /* Break result up into "words" (an SEXP counts as a word) */
3509
3510     p[0] = NULL;                        /* (We don't use element 0) */
3511     if (!*(s+1) || !*(s+2)) {           /* No need to call cksplit() */
3512         n = 1;                          /* if it's one or two chars. */
3513         p[1] = s;                       /* No need to malloc this either. */
3514         nosplit = 1;
3515         debug(F101,sexpdebug("nosplit"),"",n);
3516         if (s[0] == '(') {              /* () empty */
3517             s2 = "";
3518             goto xdosexp;
3519         }
3520     } else {
3521         nosplit = 0;
3522         q = cksplit(1,SEXPMAX,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",8,39,0);
3523         if (!q)
3524           goto xdosexp;
3525         n = q->a_size;                  /* Number of items */
3526         debug(F101,sexpdebug("split"),"",n);
3527         if (n < 0 || n > SEXPMAX) {     /* Check for too many */
3528             printf("?Too many operands: max = %d\n",SEXPMAX);
3529             sexprc++;
3530             goto xdosexp;
3531         }
3532         if (n == 0)                     /* None, result is NULL, done. */
3533           goto xdosexp;
3534         if (n == 1 && s[0] == '(') {    /* One but it's another SEXP */
3535             s2 = dosexp(s);
3536             goto xdosexp;
3537         }
3538         p2 = q->a_head;                 /* Point to result array. */
3539         for (i = 1; i <= n; i++) {      /* We must copy it because */
3540             p[i] = NULL;                /* recursive calls to dosexp() */
3541             if (p2[i])                  /* write over the same array */
3542               makestr(&(p[i]),p2[i]);
3543         }
3544         if (s[0] == '(') {              /* Operator is an S-Expression */
3545             s2 = dosexp(p[1]);          /* Replace it by its value */
3546             makestr(&(p[1]),s2);
3547         }
3548         mustfree++;                     /* Remember to free it */
3549     }
3550     debug(F110,sexpdebug("head"),p[1],0);
3551
3552     if (n == 1 && p[1]) {
3553         if (*(p[1]) == '\047') {
3554             s2 = p[1];
3555             goto xdosexp;
3556         }
3557     }
3558 /*
3559   This section sidesteps xlookup() of the most common operators.
3560   It's not necessary but it speeds up SEXP-heavy loops by about 10%.
3561 */
3562     kwflags = 0;
3563     if (n > 0) {                        /* Look up the operator */
3564         s2 = p[1];                      /* Prelookup optimization... */
3565         if (!s2)
3566           s2 = "";
3567         if (!*s2)
3568           goto xdosexp;
3569         kw = 0;
3570         x = 0;
3571         if (isdigit(*s2)) {             /* Digit */
3572             x = -2;
3573
3574         } else if (isalpha(*s2) && !*(s2+1)) { /* Single letter */
3575             x = -1;
3576
3577         } else if (*s2 == 's' || *s2 == 'S') { /* SETQ */
3578             s2++;
3579             if (*s2 == 'e' || *s2 == 'E') {
3580                 s2++;
3581                 if (*s2 == 't' || *s2 == 'T') {
3582                     s2++;
3583                     if (*s2 == 'q' || *s2 == 'Q') {
3584                         if (!*(s2+1)) {
3585                             x = SX_SET;
3586                             kwflags = 0;
3587                             builtin = 1;
3588                         }
3589                     }
3590                 }
3591             }
3592         }
3593         if (!x) {
3594             if (!*(s2+1)) {             /* Common single-character ops */
3595                 if (*s2 == '+') {
3596                     x = SX_ADD;
3597                     kwflags = 0;
3598                     builtin = 1;
3599                 } else if (*s2 == '-') {
3600                     x = SX_SUB;
3601                     kwflags = 0;
3602                     builtin = 1;
3603                 } else if (*s2 == '*') {
3604                     x = SX_MUL;
3605                     kwflags = 0;
3606                     builtin = 1;
3607                 } else if (*s2 == '/') {
3608                     x = SX_DIV;
3609                     kwflags = SXF_TWO;
3610                     builtin = 1;
3611                 }
3612             }
3613             if (!x) {                   /* None of the above, look it up */
3614                 x = xlookup(sexpops,p[1],nsexpops,&kw);
3615                 debug(F111,"XXX",p[1],x);
3616                 if (x > 0) {
3617                     kwflags = sexpops[kw].flgs;
3618                     builtin = 1;
3619                 }
3620             }
3621         }
3622     }
3623     /* If none of the above, check built-in constants */
3624
3625     if (x == -1) {
3626         x = xlookup(sexpconsts,p[1],nsexpconsts,&kw);
3627         if (x > 0) {
3628             switch (x) {
3629               case SXC_NIL:
3630                 s2 = "";
3631                 goto xdosexp;
3632               case SXC_PI:
3633                 s2 = math_pi;
3634                 goto xdosexp;
3635               case SXC_T:
3636                 s2 = "1";
3637                 goto xdosexp;
3638             }
3639         }
3640     }
3641     if (n == 1) {                       /* Not an expression */
3642         if (builtin) {                  /* Built-in operand? */
3643             switch (x) {                /* Operators with default values */
3644               case SX_EVA:
3645                 s2 = "";
3646                 goto xdosexp;
3647               case SX_MUL:              /* (*) */
3648                 s2 = sexpval ? sexpval : "1";
3649                 goto xdosexp;
3650               case SX_AND:              /* (AND) */
3651               case SX_BWA:              /* Bitwise (&) */
3652                 result++;
3653               case SX_LOR:              /* (OR) */
3654               case SX_BWO:              /* Bitwise (|) */
3655               case SX_ADD:              /* (+) */
3656               case SX_SUB:              /* (-) */
3657                 s2 = result ? "1" : "0";
3658                 goto xdosexp;
3659             }
3660
3661         } else {                        /* Not a built-in operand */
3662             char * p1;
3663             p1 = p[1];
3664             while (*p1 == SP) p1++;
3665             if (!isalpha(*p1)) {
3666                 if (xxfloat(p1,0) > 0) { /* Is it a number? */
3667                     s2 = p1;
3668                     while (*s2 == '+') s2++;
3669                 } else if (*p1 == '(') { /* An S-Expression? */
3670
3671 #ifdef COMMENT
3672                     s2 = dosexp(s2);
3673 #else
3674                     s2 = dosexp(p1);
3675 #endif /* COMMENT */
3676                 }
3677                 goto xdosexp;
3678             } else if (x < 1) {         /* Is it a variable? */
3679                 j = mxlook(mactab,p[1],nmac); /* Look it up */
3680                 debug(F111,sexpdebug("n==1 mxlook"),p[1],j);
3681                 s2 = (j > -1) ? mactab[j].mval : "";
3682                 if (!s2) s2 = "";
3683                 if (xxfloat(s2,0) > 0)  /* Macro value is a number */
3684                   goto xdosexp;
3685                 if (j > -1) {           /* It's a macro */
3686                     mx = j;
3687                     x = j;              /* whose definition is not numeric */
3688                     if (*s2 == '(') {   /* Is it an S-Expression? */
3689                         /* We have to allocate memory on the stack */
3690                         /* to call ourselves recursively on it */
3691                         /* otherwise we'll wipe out the macro definition */
3692                         char * s3 = NULL;
3693                         /* int k = 0; */
3694                         s3 = s2;
3695                         while (*s3++) k++;
3696                         s3 = (char *)malloc(k + 4);
3697                         if (s3) {
3698                             strcpy(s3,s2);   /* SAFE */
3699                             s2 = dosexp(s3); /* Evaluate it */
3700                             free(s3);
3701                         } else {
3702                             printf("?Memory allocation failure - \"%s\"\n",s2);
3703                             sexprc++;
3704                         }
3705                         goto xdosexp;
3706                     }
3707                     if (*s2 == '\047') {
3708                         s2++;
3709 #ifdef COMMENT
3710                         /* Dumps core if petty optimization was taken */
3711                         makestr(&(p[1]),s2);
3712 #else
3713                         if (!nosplit && p[1]) free(p[1]);
3714                         p[1] = (char *)malloc((int)strlen(s2) + 1);
3715 #endif /* COMMENT */
3716                         s2 = p[1];
3717                         if (!s2) s2 = "";
3718                         if (*s2 == '(') {
3719                             if (s2[makestrlen-1] == ')') {
3720                                 s2[makestrlen-1] = NUL;
3721                                 s2++;
3722                             }
3723                         }
3724                         debug(F110,sexpdebug("'A"),s2,0);
3725                         goto xdosexp;
3726                     }
3727                     macro++;            /* Not an S-Expression */
3728                 } else {                /* Not found in macro table */
3729                     printf("?Not defined - \"%s\"\n", p[1]);
3730                     sexprc++;
3731                     goto xdosexp;
3732                 }
3733             }
3734         }
3735     } else if (x < 1 && !macro) {       /* n > 1 and not a built-in operator */
3736         x = mxlook(mactab,p[1],nmac);   /* See if it's a macro */
3737         debug(F111,sexpdebug("n!=1 mxlook"),p[1],x);
3738         if (x < 0) {
3739             printf("?Invalid operand - \"%s\"\n",p[1]);
3740             sexprc++;
3741             goto xdosexp;
3742         }
3743         mx = x;
3744         macro++;
3745     }
3746     if (builtin) {                      /* Built-in operator... */
3747         if (kwflags) {
3748             int flgs;
3749             if ((flgs = (kwflags & (SXF_ONE|SXF_TWO)))) {
3750                 switch (flgs) {
3751                   case (SXF_ONE|SXF_TWO):
3752                     if (n < 2) {
3753                         printf("?Too few operands - \"%s\"\n",s);
3754                         sexprc++;
3755                         goto xdosexp;
3756                     }
3757                     break;
3758                   case SXF_TWO:
3759                     if (n < 3) {
3760                         printf("?Too few operands - \"%s\"\n",s);
3761                         sexprc++;
3762                         goto xdosexp;
3763                     }
3764                     break;
3765                   case SXF_ONE:
3766                     if (n != 2) {
3767                         printf("?Too %s operands - \"%s\"\n",
3768                                (n > 2) ? "many" : "few", s);
3769                         sexprc++;
3770                         goto xdosexp;
3771                     }
3772                 }
3773             }
3774             if (kwflags & SXF_PRE) {    /* Predicate? */
3775                 pflag = 1;
3776                 presult = 1;
3777             }
3778             if (kwflags & SXF_FLO)      /* Operator requires floating point */
3779               fpflag++;                 /* Force it */
3780         }
3781         if (x == SX_SET || x == SX_LET || /* Assignment is special */
3782             x == SX_INC || x == SX_DEC) {
3783             int rc;
3784             char c, * m, * s3;
3785             if (n == 1) {
3786                 s2 = "";
3787                 goto xdosexp;
3788             }
3789             s2 = NULL;
3790             for (i = 1; i < n; i += 2) { /* Loop thru operand pairs */
3791                 rc = 0;
3792                 s3 = p[i+1];
3793                 c = *s3;
3794                 debug(F110,sexpdebug("target p"),s3,0);
3795
3796                 /* Make sure target doesn't have multiple words */
3797                 while (*s3) { if (*s3 < '!') { rc = 1; break; }; s3++; }
3798                 s3 = p[i+1];
3799                 if (rc) {               /* If it does it must have been */
3800                     char * s4;          /* an SEXP so evaluate it */
3801                     s3 = dosexp(s3);
3802                     s4 = s3;
3803                     rc = 0;
3804                     while (*s4) { if (*s4 < '!') { rc = 1; break; }; s4++; }
3805                     if (rc == 0) makestr(&(p[i+1]),s3);
3806                 }
3807
3808                 /* And that it's not a number, etc. */
3809                 if (rc > 0 || isdigit(c) || c == '(') {
3810                     printf("?Invalid assignment - \"%s\"\n",s);
3811                     sexprc++;
3812                     goto xdosexp;
3813                 } else if (isalpha(c)) {
3814                     rc = xlookup(sexpconsts,s3,nsexpconsts,NULL);
3815                     if (rc > 0) {
3816                         printf("?Assignment to constant - \"%s\"\n",s);
3817                         sexprc++;
3818                         goto xdosexp;
3819                     }
3820                 }
3821
3822                 /* If ++ or --, get current value of variable */
3823                 if (x == SX_INC || x == SX_DEC) {
3824                     int ok = 1;
3825                     char buf[32];
3826                     if (c == CMDQ) {    /* A backslash variable */
3827                         int n = 32;
3828                         char * s = buf;
3829                         buf[0] = NUL;
3830                         if (zzstring(s3,&s,&n) < 0 || !buf[0])
3831                           ok = 0;
3832                         s2 = buf;
3833                     } else {            /* A macro */
3834                         if ((k = mxlook(mactab,s3,nmac)) < 0)
3835                           ok = 0;
3836                         else
3837                           s2 = mactab[k].mval;
3838                     }
3839                     if (!ok) {
3840                         printf("?Not defined - \"%s\"\n",p[i+1]);
3841                         sexprc++;
3842                         goto xdosexp;
3843                     }
3844                     if (!s2) s2 = "";
3845                     k = xxfloat(s2,0);
3846                     if (k < 1) {
3847                         printf("?Not numeric - \"%s\"\n",p[i+1]);
3848                         sexprc++;
3849                         goto xdosexp;
3850                     }
3851                     while (*s2 == '+') s2++;
3852                     result = atoi(s2);
3853                     fpresult = floatval;
3854                     if (k > 1 || fpresult != result)
3855                       fpflag++;
3856                 }
3857                 if (n < i+2) {          /* Variable with no value */
3858                     s2 = "";
3859                     if (x == SX_SET || x == SX_LET) {
3860                         delmac(p[i+1],1); /* Delete the variable */
3861                         break;
3862                     } else {
3863                         s2 = "1";
3864                     }
3865                 } else {                /* Variable with value */
3866                     k = xxfloat(p[i+2],0); /* Is it a number? */
3867                     if (k > 0) {
3868                         s2 = p[i+2];
3869                         while (*s2 == '+') s2++;
3870                     } else {
3871                         s2 = dosexp(p[i+2]); /* Have value, evaluate it */
3872                         if (sexprc) goto xdosexp;
3873                         if (!s2) s2 = "";
3874                         if (!*s2 && (x == SX_INC || x == SX_DEC))
3875                           continue;
3876                     }
3877                 }
3878                 if (x == SX_INC || x == SX_DEC) {
3879                     k = xxfloat(s2,0);
3880                     if (k < 1) {
3881                         printf("?Not numeric - \"%s\"\n",s2);
3882                         sexprc++;
3883                         goto xdosexp;
3884                     }
3885                     while (*s2 == '+') s2++;
3886                     j = atoi(s2);
3887                     if (k > 1) {
3888                         fpj = floatval;
3889                         fpflag++;
3890                     } else {
3891                         fpj = (CKFLOAT)j;
3892                     }
3893                     if (x == SX_INC) {
3894                         result += j;
3895                         fpresult += fpj;
3896                     } else if (x == SX_DEC) {
3897                         result -= j;
3898                         fpresult -= fpj;
3899                     }
3900                     if (result != fpresult) fpflag++;
3901                     s2 = fpflag ? fpformat(fpresult,0,0) : ckitoa(result);
3902                 }
3903                 if (x == SX_LET && cmdlvl > 0) /* LET makes var local */
3904                   addlocal(p[i+1]);
3905                 if ((rc = addmac(p[i+1],s2)) < 0) { /* Add the value */
3906                     switch (rc) {
3907                       case -3: m = "Array not declared"; break;
3908                       case -2: m = "Subscript out of range"; break;
3909                       case -4: m = "Out of memory"; break;
3910                       default: m = "Error creating variable";
3911                     }
3912                     printf("?%s - \"%s\"\n",m,s);
3913                     sexprc++;
3914                     goto xdosexp;
3915                 }
3916                 if (s2) result = atoi(s2);
3917             }
3918             goto xdosexp;
3919         } else if (x == SX_IFC) {               /* Conditional expression */
3920             int true = 0;
3921             if (n > 4) {
3922                 printf("?Too many operands: IF - \"%s\"\n",s);
3923                 sexprc++;
3924                 goto xdosexp;
3925             }
3926             s2 = dosexp(p[2]);
3927             if (sexprc) goto xdosexp;
3928             if (s2) {
3929                 j = atoi(s2);
3930                 if (xxfloat(s2,0) == 2) {
3931                     fpflag++;
3932                     fpresult = (CKFLOAT)result;
3933                     fpj = floatval;
3934                 } else {
3935                     fpj = atof(s2);
3936                 }
3937                 true = ((fpj != 0.0) ? 1 : 0);
3938             }
3939             if (!true && n < 4) {
3940                 s2 = NULL;
3941             } else {
3942                 s2 = dosexp(true ? p[3] : p[4]);
3943                 if (sexprc) goto xdosexp;
3944                 j = s2 ? atoi(s2) : 0;
3945                 if (xxfloat(s2,0) == 2) {
3946                     fpflag++;
3947                     fpresult = (CKFLOAT)result;
3948                     fpj = floatval;
3949                 } else {
3950                     fpj = s2 ? atof(s2) : 0.0;
3951                 }
3952                 fpresult = fpj;
3953                 result = j;
3954             }
3955             goto xdosexp;
3956         } else if (x == SX_QUO) {
3957 #ifndef COMMENT
3958             int xx;
3959             xx = strlen(p[2]);
3960             p[3] = (char *)malloc(xx+4);
3961             s2 = p[3];
3962             ckmakmsg(p[3],xx+4,"'(",p[2],")",NULL);
3963             n++;
3964 #else
3965             s2 = p[2];
3966 #endif /* COMMENT */
3967             goto xdosexp;
3968         } else if (x == SX_STR) {
3969             int xx;
3970             s2 = dosexp(p[2]);
3971             if (sexprc) goto xdosexp;
3972             xx = strlen(s2);
3973             p[3] = (char *)malloc(xx+4);
3974             ckmakmsg(p[3],xx+4,"'(",s2,")",NULL);
3975             s2 = p[3];
3976             n++;
3977             goto xdosexp;
3978         }
3979     }
3980     /* Arithmetic operator or macro - Loop thru operands */
3981
3982     quit = 0;                           /* Short-circuit flag. */
3983     if (macro && n > 1) {               /* If operator is a macro */
3984         if (!line) {                    /* allocate local buffer for */
3985             line = (char *)malloc(SXMLEN); /* the evaluated argument list. */
3986             if (!line) {
3987                 printf("?Memory allocation failure - \"%s\"\n",p[1]);
3988                 sexprc++;
3989                 goto xdosexp;
3990             }
3991             linelen = SXMLEN;
3992             /* debug(F101,"dosexp macro arg buffer","",linelen); */
3993         }
3994         linepos = 0;
3995         line[linepos] = NUL;
3996     }
3997     for (i = 1; ((i < n) && !sexprc && !quit); i++) { /* Loop thru operands */
3998         quote = 0;
3999         s2 = p[i+1];                    /* Get operand */
4000         if (!s2) s2 = "";
4001 #ifdef COMMENT
4002         if (*s2 == '\047') {            /* Is it quoted? */
4003             debug(F110,sexpdebug("'B"),s2,0);
4004             s2++;                       /* Space past the quote */
4005             quote++;
4006             if (*s2 == '(') {           /* Quoted S-Expression? */
4007                 char c4, * s4 = s2+1;   /* Strip outer parens */
4008                 while ((c4 = *s4++)) {
4009                     if (c4 == ')' && !*s4) {
4010                         s2++;
4011                         *(s4-1) = NUL;
4012                         break;
4013                     }
4014                 }
4015             }
4016             debug(F110,sexpdebug("'C"),s2,0);
4017
4018         } else {                        /* Not quoted */
4019             s2 = dosexp(p[i+1]);        /* evaluate it */
4020             if (sexprc) goto xdosexp;
4021             if (!s2) s2 = "";
4022             if (!macro && x == SX_EVA)
4023               continue;
4024         }
4025 #else
4026         if (*s2 != '\047') {            /* Is it quoted? */
4027             s2 = dosexp(p[i+1]);        /* No, evaluate it */
4028             if (sexprc) goto xdosexp;
4029             if (!s2) s2 = "";
4030             if (!macro && x == SX_EVA)
4031               continue;
4032         }
4033         if (*s2 == '\047') {            /* Is result quoted? */
4034             debug(F110,sexpdebug("'B"),s2,0);
4035             s2++;                       /* Space past the quote */
4036             quote++;
4037             if (*s2 == '(') {           /* Quoted S-Expression? */
4038                 char c4, * s4 = s2+1;   /* Strip outer parens */
4039                 while ((c4 = *s4++)) {
4040                     if (c4 == ')' && !*s4) {
4041                         s2++;
4042                         *(s4-1) = NUL;
4043                         break;
4044                     }
4045                 }
4046             }
4047             debug(F110,sexpdebug("'C"),s2,0);
4048         }
4049 #endif /* COMMENT */
4050         if (macro) {
4051             debug(F111,sexpdebug("macro arg"),s2,i);
4052             if (!*s2) quote++;
4053             if (!quote) {
4054                 register char c4, * s4 = s2;
4055                 while ((c4 = *s4++)) if (c4 == SP) { quote++; break; }
4056             }
4057             if (quote) line[linepos++] = '{';
4058             while ((line[linepos++] = *s2++)) {
4059                 if (linepos > linelen - 3) {
4060                     char * tmp = NULL;
4061                     line[linepos] = NUL;
4062                     linelen += SXMLEN;
4063                     tmp = (char *) malloc(linelen);
4064                     if (!tmp) {
4065                         printf("?Memory re-allocation failure - \"%s...\"\n",
4066                                line);
4067                         sexprc++;
4068                         goto xdosexp;
4069                     }
4070                     strcpy(tmp,line);
4071                     free(line);
4072                     line = tmp;
4073                 }
4074             }
4075             linepos--;                  /* Back up over NUL */
4076             if (quote)
4077               line[linepos++] = '}';    /* End quote group */
4078             line[linepos++] = SP;       /* add a space */
4079             line[linepos] = NUL;        /* and a NUL */
4080             continue;
4081         }
4082         if (!quote) {                   /* Built-in operator... */
4083             s2 = dosexp(s2);
4084             if (sexprc) goto xdosexp;
4085             if (!s2) s2 = "";
4086         }
4087         if (x == SX_EVA)
4088           continue;
4089
4090         if (!*s2) {
4091             /* An empty value is not a legal number */
4092             /* but it is a legal truth value */
4093             if (x != SX_AND && x != SX_LOR && x != SX_NOT) {
4094                 printf("?Not Numeric - \"%s\"\n",p[i+1]);
4095                 sexprc++;
4096                 goto xdosexp;
4097             }
4098             j = 0;
4099             fpj = 0.0;
4100         } else {
4101             j = atoi(s2);
4102             /* Switch to floating-point upon encountering any f.p. arg */
4103             /* OR... if integer is too big */
4104             if (!fpflag) if (xxfloat(s2,0) == 2)
4105               fpflag++;
4106             fpj = atof(s2);
4107         }
4108         if (i == 1) {                   /* Initial result is first operand */
4109             result = (n == 2 && x == SX_SUB) ? 0-j : j;
4110             fpresult = (n == 2 && x == SX_SUB) ? -fpj : fpj;
4111             if (!(kwflags & SXF_ONE))   /* Command with single arg */
4112               continue;
4113         }
4114         if (x == SX_MOD || x == SX_DIV) {
4115             if (!result)
4116               fpflag++;
4117             if (!fpj) {
4118                 printf("?Divide by zero - \"%s\"\n",cmdbuf);
4119                 sexprc++;
4120                 goto xdosexp;
4121             }
4122         }
4123         switch (x) {                    /* Accumulate result */
4124
4125           case SX_EVA:                  /* EVAL */
4126             result = j;
4127             fpresult = fpj;
4128             break;
4129
4130           case SX_ADD:                  /* + */
4131             result += j;
4132             fpresult += fpj;
4133             if (result != fpresult)
4134               fpflag++;
4135             break;
4136
4137           case SX_SUB:                  /* - */
4138             result -= j;
4139             fpresult -= fpj;
4140             if (result != fpresult)
4141               fpflag++;
4142             break;
4143
4144           case SX_MUL:                  /* * */
4145             result *= j;
4146             fpresult *= fpj;
4147             if (result != fpresult)
4148               fpflag++;
4149             break;
4150
4151           case SX_AND:                  /* AND */
4152             result = result && j;
4153             if (!result) quit++;
4154             fpresult = fpresult && fpj;
4155             break;
4156
4157           case SX_LOR:                  /* OR */
4158             result = result || j;
4159             if (!result) quit++;
4160             fpresult = fpresult || fpj;
4161             break;
4162
4163           case SX_MOD:                  /* Modulus */
4164             result = result % j;
4165 #ifdef FNFLOAT
4166             fpresult = (CKFLOAT)fmod(fpresult,fpj);
4167             if (result != fpresult)
4168               fpflag++;
4169 #else
4170             fpresult = result;
4171 #endif /* FNFLOAT */
4172             break;
4173
4174           case SX_DIV:                  /* / */
4175             result /= j;
4176             fpresult /= fpj;
4177             if (result != fpresult)
4178               fpflag++;
4179             break;
4180
4181           case SX_AEQ:                  /* Test for equality */
4182             if (fpflag) {
4183                 if (fpresult != fpj)
4184                   presult = 0;
4185             } else {
4186                 if (result != j)
4187                   presult = 0;
4188             }
4189             break;
4190
4191           case SX_NEQ:                  /* Test for ineqality */
4192             if (fpflag) {
4193                 if (fpresult == fpj)
4194                   presult = 0;
4195             } else {
4196                 if (result == j)
4197                   presult = 0;
4198             }
4199             break;
4200
4201           case SX_ALE:                  /* Arithmetic less-equal */
4202             if (fpflag) {
4203                 if (fpj < fpresult)
4204                   presult = 0;
4205                 fpresult = fpj;
4206             } else {
4207                 if (j < result)
4208                   presult = 0;
4209                 result = j;
4210             }
4211             break;
4212
4213           case SX_ALT:                  /* Arithmetic less-than */
4214             if (fpflag) {
4215                 if (fpj <= fpresult)
4216                   presult = 0;
4217                 fpresult = fpj;
4218             } else {
4219                 if (j <= result)
4220                   presult = 0;
4221                 result = j;
4222             }
4223             break;
4224
4225           case SX_AGT:                  /* Arithmetic greater-than */
4226             if (fpflag) {
4227                 if (fpj >= fpresult)
4228                   presult = 0;
4229                 fpresult = fpj;
4230             } else {
4231                 if (j >= result)
4232                   presult = 0;
4233                 result = j;
4234             }
4235             break;
4236
4237           case SX_AGE:                  /* Arithmetic greater-equal */
4238             if (fpflag) {
4239                 if (fpj > fpresult)
4240                   presult = 0;
4241                 fpresult = fpj;
4242             } else {
4243                 if (j > result)
4244                   presult = 0;
4245                 result = j;
4246             }
4247             break;
4248
4249           case SX_POW:                  /* Raise to power */
4250 #ifdef FNFLOAT
4251             {
4252                 double dummy;
4253                 if (!fpj) {
4254                     fpresult = 1.0;
4255                 } else if ((!fpresult && fpj <= 0.0)) {
4256                     printf("?Divide by zero - \"%s\"\n",cmdbuf);
4257                     sexprc++;
4258                     goto xdosexp;
4259                 } else if (fpresult < 0.0 && modf(fpj,&dummy)) {
4260                     printf("?Domain error - \"%s\"\n",cmdbuf);
4261                     sexprc++;
4262                     goto xdosexp;
4263                 } else {
4264                     fpresult = (CKFLOAT)pow(fpresult,fpj);
4265                 }
4266             }
4267 #endif /* FNFLOAT */
4268             if (j == 0) {
4269                 result = 1;
4270             } else {
4271                 int z, sign = 0;
4272                 if (j < 0) {
4273                     if (result == 0) {
4274                         printf("?Divide by zero - \"%s\"\n",cmdbuf);
4275                         sexprc++;
4276                         goto xdosexp;
4277                     }
4278                     j = 0 - j;
4279                     sign++;
4280                 }
4281                 z = result;
4282                 while (--j > 0)
4283                   result *= z;
4284                 if (sign)
4285                   result = 1 / result;
4286             }
4287             if (result != fpresult)
4288               fpflag++;
4289             break;
4290
4291 #ifdef FNFLOAT
4292           case SX_EXP:                  /* e to the given power */
4293             fpresult = (CKFLOAT) exp(fpj);
4294             break;
4295
4296           case SX_LGN:                  /* Natural log */
4297           case SX_LGX:                  /* Log base 10 */
4298           case SX_SQR:                  /* Square root */
4299             if (fpj < 0.0) {
4300                 printf("?Argument out of range - \"%s\"\n",cmdbuf);
4301                 sexprc++;
4302                 goto xdosexp;
4303             }
4304             if (x == SX_SQR)
4305               fpresult = (CKFLOAT) sqrt(fpj);
4306             else if (x == SX_LGN)
4307               fpresult = (CKFLOAT) log(fpj);
4308             else
4309               fpresult = (CKFLOAT) log10(fpj);
4310             break;
4311
4312           case SX_SIN:                  /* sine */
4313             fpresult = (CKFLOAT) sin(fpj);
4314             break;
4315
4316           case SX_COS:                  /* cosine */
4317             fpresult = (CKFLOAT) cos(fpj);
4318             break;
4319
4320           case SX_TAN:                  /* tangent */
4321             fpresult = (CKFLOAT) tan(fpj);
4322             break;
4323 #endif /* FNFLOAT */
4324
4325           case SX_CEI:                  /* Ceiling */
4326             if (j != fpj)
4327               if (fpj > 0.0)
4328                 fpj += 1.0;
4329             fpresult = fpj;
4330             fpflag = 1;
4331             truncate = 1;
4332             break;
4333
4334           case SX_FLR:                  /* Floor */
4335             if (j != fpj)
4336               if (fpj < 0.0)
4337                 fpj -= 1.0;
4338             fpresult = fpj;
4339             fpflag = 1;
4340             truncate = 1;
4341             break;
4342
4343           case SX_TRU:                  /* Truncate */
4344             fpresult = fpj;
4345             fpflag = 1;
4346             truncate = 1;
4347             break;
4348
4349           case SX_ROU:                  /* Round */
4350             if (fpj > 0.0)
4351               fpj += 0.5;
4352             else if (fpj < 0.0)
4353               fpj -= 0.5;
4354             fpresult = fpj;
4355             fpflag = 1;
4356             truncate = 1;
4357             break;
4358
4359           case SX_ABS:                  /* Absolute value */
4360             result = (j < 0) ? 0 - j : j;
4361             fpresult = (fpj < 0.0) ? 0.0 - fpj : fpj;
4362             if (result != fpresult)
4363               fpflag++;
4364             break;
4365
4366           case SX_MAX:                  /* Max */
4367             if (j != fpj)
4368               fpflag++;
4369             if (fpflag) {
4370                 if (fpj > fpresult)
4371                   fpresult = fpj;
4372             } else
4373               if (j > result)
4374                 result = j;
4375             break;
4376
4377           case SX_MIN:                  /* Min */
4378             if (j != fpj)
4379               fpflag++;
4380             if (fpflag) {
4381                 if (fpj < fpresult)
4382                   fpresult = fpj;
4383             } else
4384               if (j < result)
4385                 result = j;
4386             break;
4387
4388           case SX_FLO:                  /* Float */
4389             fpflag++;
4390             fpresult = result;
4391             fpj = j;
4392             break;
4393
4394           case SX_NOT:                  /* NOT (reverse truth value) */
4395             fpflag = 0;
4396             not++;
4397             break;
4398
4399           case SX_BWA:                  /* Bitwise AND */
4400             fpflag = 0;
4401             result &= j;
4402             break;
4403
4404           case SX_BWO:                  /* Bitwise OR */
4405             fpflag = 0;
4406             result |= j;
4407             break;
4408
4409           case SX_BWX:                  /* Bitwise XOR */
4410           case SX_XOR:                  /* Logical XOR */
4411             if (n > 3) {
4412                 printf("?Too many operands - \"%s\"\n",s);
4413                 sexprc++;
4414                 goto xdosexp;
4415             }
4416             fpflag = 0;
4417             if (x == SX_BWX) {
4418                 result ^= j;
4419             } else {
4420                 result = (result && !j) || (!result && j);
4421                 if (result) result = 1;
4422             }
4423             break;
4424
4425           case SX_BWN:                  /* Bitwise Not */
4426             fpflag = 0;
4427             result = ~result;
4428             break;
4429
4430           default:
4431             printf("BAD OP [%s]\n",p[1]);
4432             sexprc++;
4433         }
4434     }
4435     if (!pflag)                         /* Not a predicate */
4436       sexppv = -1;                      /* So unset this */
4437
4438   /* domacro: */
4439
4440     if (macro) {                        /* User-defined macro */
4441         extern int fsexpflag;           /* (see fneval():ckuus4.c) */
4442         int lookagain = 0;              /* Maybe the macro table changed */
4443         if (mactab[mx].kwd) {           /* Check and see */
4444             if (ckstrcmp(mactab[mx].kwd,p[1],-1,0))
4445               lookagain++;
4446         } else
4447           lookagain++;
4448         if (lookagain) {                /* The table changed */
4449             mx = mxlook(mactab,p[1],nmac); /* Get the macro's new index */
4450             debug(F111,sexpdebug("macro moved"),p[1],mx);
4451             if (mx < 0) {                  /* Yikes! */
4452                 printf("?Macro disappeared! - \"%s\"\n",p[1]);
4453                 sexprc++;
4454                 goto xdosexp;
4455             }
4456         }
4457         debug(F111,sexpdebug("macro mx"),mactab[mx].kwd,mx);
4458         if (fsexpflag) {                /* If embedded in a function call */
4459             if (cmpush() > -1) {        /* get a new copy of the parsing */
4460                 extern int ifc;         /* environment, */
4461                 int k, ifcsav = ifc;    /* save the IF state */
4462                 dodo(mx,line,0);        /* Set up the macro */
4463                 k = parser(1);          /* Call the parser to execute it */
4464                 cmpop();                /* Pop back to previous level */
4465                 ifc = ifcsav;           /* restore IF state */
4466                 if (k == 0)             /* If no error */
4467                   s2 = mrval[maclvl+1]; /* get return value, if any */
4468                 if (!s2) s2 = "";
4469                 debug(F110,sexpdebug("macro return"),s2,0);
4470             } else {
4471                 printf("?Resources exhausted - \"%s\"\n",s);
4472                 sexprc++;
4473             }
4474         } else {                        /* Not embedded in a function call */
4475             dodo(mx,line,0);            /* As above but without cmpush/pop() */
4476             k = parser(1);
4477             if (k == 0)
4478               s2 = mrval[maclvl+1];
4479             if (!s2) s2 = "";
4480         }
4481     } else if (pflag) {                 /* Predicate */
4482         if (not) presult = presult ? 0 : 1;
4483         sexppv = presult;               /* So set predicate value (0 or 1) */
4484         s2 = presult ? "1" : "0";
4485     } else if (fpflag) {                /* Result is floating-point */
4486         if (not) fpresult = fpresult ? 0.0 : 1.0;
4487         s2 = fpformat(fpresult,0,0);
4488     } else if (x != SX_EVA) {
4489         if (not) result = result ? 0 : 1;
4490         s2 = ckitoa(result);
4491     }
4492
4493 /* Common exit point.  Always come here to exit. */
4494
4495   xdosexp:
4496
4497     if (!s2) s2 = "";
4498     if (!sexprc && s2) {                /* Have a result */
4499         char * sx;
4500         char * q2 = s2; int xx = 0;
4501         if (*s2) {
4502             while (*q2++) xx++;         /* Get length */
4503             if (xx > sexprmax)          /* (stats) */
4504               sexprmax = xx;
4505         } else
4506           xx = 0;
4507         if (xx > sxrlen[sexpdep] || !sxresult[sexpdep]) {
4508             int k;
4509             k = xx + xx / 4;
4510             if (k < 32) k = 32;
4511             if (sxresult[sexpdep])
4512               free(sxresult[sexpdep]);
4513             if ((sxresult[sexpdep] = (char *)malloc(k))) {
4514                 sxrlen[sexpdep] = k;
4515             } else {
4516                 printf("?Memory allocation failure - \"%s\"\n",s2);
4517                 sexprc++;
4518             }
4519         }
4520         sx = sxresult[sexpdep];         /* Point to result buffer */
4521         while ((*sx++ = *s2++)) ;       /* copy result. */
4522         if (fpflag && truncate) {       /* Floating point + truncate */
4523             sx = sxresult[sexpdep];     /* at decimal point */
4524             for (i = xx - 1; i >= 0; i--) {
4525                 if (sx[i] == '.') {
4526                     sx[i] = NUL;
4527                     if (i == 0) {       /* If nothing left */
4528                         sx[0] = '0';    /* put a zero. */
4529                         sx[1] = NUL;
4530                     }
4531                 }
4532             }
4533         }
4534     }
4535     if (line)                           /* If macro arg buffer allocated */
4536       free(line);                       /* free it. */
4537     if (mustfree) {                     /* And free local copy of split list */
4538         for (i = 1; i <= n; i++) {
4539             if (p[i]) free(p[i]);
4540         }
4541     }
4542     debug(F111,sexpdebug("exit"),sxresult[sexpdep],sexprc);
4543     return(sxresult[sexpdep--]);
4544 }
4545 #endif /* NOSEXP */
4546 #endif /* NOSPL */
4547
4548 int                                     /* CHECK command */
4549 dochk() {
4550     int x, y;
4551     if ((y = cmkey(ftrtab,nftr,"","",xxstring)) < 0)
4552       return(y);
4553     ckstrncpy(line,atmbuf,LINBUFSIZ);
4554     if ((y = cmcfm()) < 0)
4555       return(y);
4556 #ifndef NOPUSH
4557     if (!ckstrcmp(line,"push",(int)strlen(line),0)) {
4558         if (msgflg)                     /* If at top level... */
4559           printf(" push%s available\n", nopush ? " not" : "");
4560         else if (nopush && !backgrd)
4561           printf(" CHECK: push not available\n");
4562         return(success = 1 - nopush);
4563     }
4564 #endif /* NOPUSH */
4565 #ifdef PIPESEND
4566     if (!ckstrcmp(line,"pipes",(int)strlen(line),0)) {
4567         if (msgflg)                     /* If at top level... */
4568           printf(" pipes%s available\n",
4569                  (nopush || protocol != PROTO_K) ? " not" : "");
4570         else if ((nopush || protocol != PROTO_K) && !backgrd)
4571           printf(" CHECK: pipes not available\n");
4572         return(success = 1 - nopush);
4573     }
4574 #endif /* PIPESEND */
4575     y = lookup(ftrtab,line,nftr,&x);    /* Look it up */
4576     debug(F111,"dochk",ftrtab[x].kwd,y);
4577     if (msgflg)                         /* If at top level... */
4578       printf(" %s%s available\n", ftrtab[x].kwd, y ? " not" : "");
4579     else if (y && !backgrd)
4580       printf(" CHECK: %s not available\n", ftrtab[x].kwd);
4581     return(success = 1 - y);
4582 }
4583
4584 #ifndef NOLOCAL
4585 #ifdef CKLOGDIAL
4586
4587 /* Connection log and elapsed-time reporting */
4588
4589 extern char cxlogbuf[];                 /* Log record buffer */
4590 extern char diafil[];                   /* Log file name */
4591 extern int dialog, cx_active;           /* Flags */
4592 static long cx_prev = 0L;               /* Elapsed time of previous session */
4593
4594 #endif /* CKLOGDIAL */
4595 #endif /* NOLOCAL */
4596
4597 VOID
4598 dologend() {                            /* Write record to connection log */
4599 #ifdef LOCUS
4600     extern int locus, autolocus;
4601 #endif /* LOCUS */
4602
4603 #ifndef NOLOCAL
4604 #ifdef CKLOGDIAL
4605     long d1, d2, t1, t2;
4606     char buf[32], * p;
4607 #endif /* CKLOGDIAL */
4608 #endif /* NOLOCAL */
4609
4610 #ifdef LOCUS
4611     if (autolocus) {
4612         int x = locus;
4613 #ifdef NEWFTP
4614         extern int ftpisconnected();
4615         debug(F101,"dologend ftpisconnected","",ftpisconnected());
4616         setlocus(ftpisconnected() ? 0 : 1, 1);
4617 #else
4618         setlocus(1,1);
4619 #endif /* NEWFTP */
4620     }
4621 #endif /* LOCUS */
4622
4623 #ifndef NOLOCAL
4624 #ifdef CKLOGDIAL
4625     debug(F101,"dologend dialog","",dialog);
4626     debug(F101,"dologend cxlogbuf[0]","",cxlogbuf[0]);
4627 #ifdef CKSYSLOG
4628     debug(F101,"dologend ckxlogging","",ckxlogging);
4629 #endif /* CKSYSLOG */
4630
4631     if (!cx_active || !cxlogbuf[0])     /* No active record */
4632       return;
4633
4634     cx_active = 0;                      /* Record is not active */
4635     debug(F111,"dologend cxlogbuf 1",cxlogbuf,cx_active);
4636
4637     d1 = mjd((char *)cxlogbuf);         /* Get start date of this session */
4638     ckstrncpy(buf,ckdate(),31);         /* Get current date */
4639     d2 = mjd(buf);                      /* Convert them to mjds */
4640     p = cxlogbuf;                       /* Get start time */
4641     p[11] = NUL;
4642     p[14] = NUL;                        /* Convert to seconds */
4643     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4644     p[11] = ':';
4645     p[14] = ':';
4646     p = buf;                            /* Get end time */
4647     p[11] = NUL;
4648     p[14] = NUL;
4649     t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4650     t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Compute elapsed time */
4651     debug(F101,"dologend t2","",t2);
4652     if (t2 > -1L) {
4653         cx_prev = t2;
4654         p = hhmmss(t2);
4655         debug(F110,"dologend hhmmss",p,0);
4656         strncat(cxlogbuf,"E=",CXLOGBUFL); /* Append to log record */
4657         strncat(cxlogbuf,p,CXLOGBUFL);
4658         debug(F110,"dologend cxlogbuf 2",cxlogbuf,0);
4659     } else
4660       cx_prev = 0L;
4661     debug(F101,"dologend cx_prev","",cx_prev);
4662     if (dialog) {                       /* If logging */
4663         int x;
4664         x = diaopn(diafil,1,1);         /* Open log in append mode */
4665         debug(F101,"dologend diaopn","",x);
4666         x = zsoutl(ZDIFIL,cxlogbuf);    /* Write the record */
4667         debug(F101,"dologend zsoutl","",x);
4668         x = zclose(ZDIFIL);             /* Close the log */
4669         debug(F101,"dologend zclose","",x);
4670     }
4671 #ifdef CKSYSLOG
4672     debug(F101,"dologend ckxlogging","",ckxlogging);
4673     if (ckxlogging) {
4674         int x;
4675         x = ckindex("T=DIAL",cxlogbuf,0,0,1);
4676         debug(F111,"dologend ckxsyslog",cxlogbuf,ckxsyslog);
4677         debug(F111,"dologend ckindex","T=DIAL",x);
4678         if (x > 0) {
4679             if (ckxsyslog >= SYSLG_DI) {
4680                 debug(F110,"dologend syslog",cxlogbuf+18,0);
4681                 cksyslog(SYSLG_DI,1,"CONNECTION",(char *)(cxlogbuf+18),"");
4682             } else if (ckxsyslog >= SYSLG_AC) {
4683                 debug(F110,"dologend syslog",cxlogbuf+18,0);
4684                 cksyslog(SYSLG_AC,1,"CONNECTION",(char *)(cxlogbuf+18),"");
4685             }
4686         }
4687     }
4688 #endif /* CKSYSLOG */
4689 #endif /* CKLOGDIAL */
4690 #endif /* NOLOCAL */
4691 }
4692
4693 #ifndef NOLOCAL
4694 #ifdef CKLOGDIAL
4695
4696 /*  D O L O G S H O W  --  Show session/connection info  */
4697
4698 /* Call with fc == 1 to show, fc == 0 to only calculate. */
4699 /* Returns session elapsed time in seconds. */
4700 /* If no session active, returns elapsed time of previous session, if any, */
4701 /* otherwise 0 */
4702
4703 long
4704 dologshow(fc) int fc; {                 /* SHOW (current) CONNECTION */
4705     long d1, d2, t1, t2 = 0, prev;
4706     char c, buf1[32], buf2[32], * info[32], * p, * s;
4707     char * xlogbuf, xbuf[CXLOGBUFL+1];
4708     int i, x = 0, z, ftp = 0, active = 0;
4709
4710 #ifdef NEWFTP
4711     extern char ftplogbuf[];
4712     extern long ftplogprev;
4713     extern int ftplogactive;
4714     if (fc & W_FTP) {
4715         fc &= 63;
4716         ftp = 1;
4717         xlogbuf = ftplogbuf;
4718         prev = ftplogprev;
4719         active = ftplogactive;
4720     } else {
4721 #endif /* NEWFTP */
4722         ftp = 0;
4723         xlogbuf = cxlogbuf;
4724         prev = cx_prev;
4725         active = cx_active;
4726 #ifdef NEWFTP
4727     }
4728 #endif /* NEWFTP */
4729
4730     debug(F101,"dologshow local","",local);
4731     debug(F101,"dologshow ftp","",ftp);
4732     debug(F111,"dologshow active",xlogbuf,active);
4733
4734     if (!xlogbuf[0]) {
4735         if (fc) {
4736             if (didsetlin || ftp)
4737               printf(" %s: No record.\n", ftp ? "FTP" : "Kermit");
4738             else
4739               printf(" %s: No connection.\n", ftp ? "FTP" : "Kermit");
4740         }
4741         return(prev);
4742     }
4743
4744 #ifdef NEWFTP
4745     if (ftp) {
4746         z = ftpisconnected() ? 1 : -1;
4747     } else {
4748 #endif /* NEWFTP */
4749         if (local) {                    /* See if we have an open connection */
4750             z = ttchk();
4751             debug(F101,"dologshow ttchk","",z);
4752             z = (z > -1) ? 1 : -2;
4753         } else {
4754             z = active ? 1 : -2;
4755         }
4756 #ifdef NEWFTP
4757     }
4758 #endif /* NEWFTP */
4759     if (z < 0L) {
4760         if (!fc)
4761           return(prev);
4762         else
4763           t2 = prev;
4764     }
4765     /* Note: NOT ckstrncpy! */
4766     strncpy(buf1,xlogbuf,17);           /* Copy of just the timestamp */
4767     buf1[17] = NUL;                     /* Terminate it */
4768     ckstrncpy(xbuf,xlogbuf+18,CXLOGBUFL); /* Copy that can be poked */
4769     debug(F111,"dologshow prev",xbuf,prev);
4770
4771     xwords(xbuf,31,info,1);             /* Break up into fields */
4772     d1 = mjd(buf1);                     /* Convert start time to MJD */
4773     ckstrncpy(buf2,ckdate(),31);        /* Current date */
4774     d2 = mjd(buf2);                     /* Convert to MJD */
4775     p = buf1;                           /* Point to start time */
4776     p[11] = NUL;
4777     p[14] = NUL;                        /* Convert to seconds */
4778     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4779     p[11] = ':';
4780     p[14] = ':';
4781     p = buf2;                           /* Ditto for current time */
4782     p[11] = NUL;
4783     p[14] = NUL;
4784     if (z > -1L) {
4785         t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4786         t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Elapsed time so far */
4787     }
4788     if (fc) {
4789         p = NULL;
4790         if (t2 > -1L)                   /* Convert seconds to hh:mm:ss */
4791           p = hhmmss(t2);
4792         if (z > -1)
4793           s = "Active";
4794         else if (z == -2)
4795           s = "Closed";
4796         else
4797           s = "Unknown";
4798         printf("\n");                   /* Show results */
4799         printf(" Status:       %s\n",s);
4800         printf(" Opened:       %s\n",buf1);
4801         printf(" User:         %s\n",info[1] ? info[1] : "");
4802         printf(" PID:          %s\n",info[2] ? info[2] : "");
4803         for (i = 3; info[i]; i++) {
4804             c = info[i][0];
4805             s = (info[i]) ? info[i]+2 : "";
4806             switch (c) {
4807               case 'T': printf(" Type:         %s\n", s); break;
4808               case 'N': printf(" To:           %s\n", s); break;
4809               case 'H': printf(" From:         %s\n", s); break;
4810               case 'D': printf(" Device:       %s\n", s); break;
4811               case 'O': printf(" Origin:       %s\n", s); break;
4812               case 'E': break;
4813               default:  printf(" %s\n",info[i] ? info[i] : "");
4814             }
4815         }
4816         if (z < 0L)
4817           printf(" Elapsed time: %s\n", hhmmss(t2));
4818         else
4819           printf(" Elapsed time: %s\n", p ? p : "(unknown)");
4820         x = 0;
4821 #ifdef NETCONN
4822 #ifdef SSHBUILTIN
4823         if ( IS_SSH() ) x++;
4824 #endif /* SSHBUILTIN */
4825 #ifdef CK_ENCRYPTION
4826         if (ck_tn_encrypting() && ck_tn_decrypting()) x++;
4827 #endif /* CK_ENCRYPTION */
4828 #ifdef CK_SSL
4829         if (tls_active_flag || ssl_active_flag) x++;
4830 #endif /* CK_SSL */
4831 #ifdef RLOGCODE
4832 #ifdef CK_KERBEROS
4833 #ifdef CK_ENCRYPTION
4834         if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) x++;
4835 #endif /* CK_ENCRYPTION */
4836 #endif /* CK_KERBEROS */
4837 #endif /* RLOGCODE */
4838 #endif /* NETCONN */
4839         if (z > 0)
4840           printf(" Encrypted:    %s\n", x ? "Yes" : "No");
4841         printf(" Log:          %s\n", dialog ? diafil : "(none)");
4842         printf("\n");
4843     }
4844     return(t2 > -1L ? t2 : 0L);
4845 }
4846
4847 VOID
4848 dologline() {
4849     char * p;
4850     int n, m = 0;
4851
4852     dologend();                         /* Previous session not closed out? */
4853     cx_active = 1;                      /* Record is active */
4854     cx_prev = 0L;
4855     p = ckdate();                       /* Get timestamp */
4856     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL-1); /* Start record off with it */
4857     if (!uidbuf[0]) {
4858         debug(F100,"dologline uidbuf empty","",0);
4859 #ifdef UNIX                             /* Who has whoami()... */
4860         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
4861 #else
4862 #ifdef STRATUS
4863         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
4864 #else
4865         ckstrncpy(uidbuf,"UNKNOWN",UIDBUFLEN);
4866 #endif /* STRATUS */
4867 #endif /* UNIX */
4868     }
4869     m = strlen(uidbuf) + strlen(myhost) + strlen(ttname) + 32;
4870     if (n+m < CXLOGBUFL-1) {            /* Add serial device info */
4871         p = cxlogbuf+n;
4872         sprintf(p," %s %s T=SERIAL H=%s D=%s ", /* SAFE */
4873                 uidbuf,
4874                 ckgetpid(),
4875                 myhost,
4876                 ttname
4877                 );
4878     } else
4879       ckstrncpy(cxlogbuf,"LOGLINE BUFFER OVERFLOW",CXLOGBUFL);
4880     debug(F110,"dologline",cxlogbuf,0);
4881 }
4882
4883 #ifdef NETCONN
4884 VOID
4885 dolognet() {
4886     char * p, * s = "NET", * uu = uidbuf;
4887     int n, m;
4888
4889     dologend();                         /* Previous session not closed out? */
4890     cx_prev = 0L;
4891     cx_active = 1;                      /* Record is active */
4892     p = ckdate();
4893     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL);
4894 #ifdef TCPSOCKET
4895     if (nettype == NET_TCPB || nettype == NET_TCPA)
4896       s = "TCP";
4897 #endif /* TCPSOCKET */
4898 #ifdef ANYX25
4899     if (nettype == NET_SX25 || nettype == NET_VX25 || nettype == NET_IX25)
4900       s = "X25";
4901 #endif /* ANYX25 */
4902 #ifdef DECNET
4903     if (nettype == NET_DEC)
4904       s = "DECNET";
4905 #endif /* DECNET */
4906 #ifdef SUPERLAT
4907     if (nettype == NET_SLAT)
4908       s = "SUPERLAT";
4909 #endif /* SUPERLAT */
4910 #ifdef CK_NETBIOS
4911     if (nettype == NET_BIOS)
4912       s = "NETBIOS";
4913 #endif /* CK_NETBIOS */
4914
4915     if (!uu[0]) {
4916         debug(F100,"dolognet uidbuf empty","",0);
4917 #ifdef OS2ORUNIX                        /* Who has whoami()... */
4918         uu = (char *)whoami();
4919 #else
4920 #ifdef STRATUS
4921         uu = (char *)whoami();
4922 #else
4923         uu = "UNKNOWN";
4924 #endif /* STRATUS */
4925 #endif /* UNIX */
4926     }
4927     m = strlen(uu) + strlen(myhost) + strlen(ttname) + strlen(s) + 32;
4928     if (n+m < CXLOGBUFL-1) {            /* SAFE */
4929         p = cxlogbuf+n;
4930         sprintf(p," %s %s T=%s N=%s H=%s ",
4931                 uu,
4932                 ckgetpid(),
4933                 s,
4934                 ttname,
4935                 myhost
4936                 );
4937     } else
4938       ckstrncpy(cxlogbuf,"LOGNET BUFFER OVERFLOW",CXLOGBUFL);
4939     debug(F110,"dolognet cxlogbuf",cxlogbuf,0);
4940 }
4941 #endif /* NETCONN */
4942 #endif /* CKLOGDIAL */
4943
4944 #ifndef NODIAL
4945 /*
4946   Parse a DIAL-related string, stripping enclosing braces, if any.
4947 */
4948 static int
4949 dialstr(p,msg) char **p; char *msg; {
4950     int x;
4951     char *s;
4952
4953     if ((x = cmtxt(msg, "", &s, xxstring)) < 0)
4954       return(x);
4955     s = brstrip(s);                     /* Strip braces around. */
4956     debug(F110,"dialstr",s,0);
4957     makestr(p,*s?s:NULL);
4958     return(success = 1);
4959 }
4960
4961 VOID
4962 initmdm(x) int x; {
4963     MDMINF * p;
4964     int m;
4965
4966     mdmtyp = x;                         /* Set global modem type */
4967     debug(F101,"initmdm mdmtyp","",mdmtyp);
4968     debug(F101,"initmdm usermdm","",usermdm);
4969     if (x < 1) return;
4970
4971     m = usermdm ? usermdm : mdmtyp;
4972
4973     p = modemp[m];                      /* Point to modem info struct, and */
4974     debug(F101,"initmdm p","",p);
4975     if (p) {
4976         dialec = p->capas & CKD_EC;     /* set DIAL ERROR-CORRECTION, */
4977         dialdc = p->capas & CKD_DC;     /* DIAL DATA-COMPRESSION, and */
4978         mdmspd = p->capas & CKD_SB ? 0 : 1; /* DIAL SPEED-MATCHING from it. */
4979         dialfc = FLO_AUTO;                  /* Modem's local flow control.. */
4980         dialmax   = p->max_speed;
4981         dialcapas = p->capas;
4982         dialesc   = p->esc_char;
4983     } else if (mdmtyp > 0) {
4984         printf("WARNING: modem info for \"%s\" not filled in yet\n",
4985                gmdmtyp()
4986                );
4987     }
4988
4989 /* Reset or set the SET DIAL STRING items ... */
4990
4991 #ifdef DEBUG
4992     if (deblog) {
4993         debug(F110,"initmdm dialini",dialini,0);
4994         debug(F110,"initmdm dialmstr ",dialmstr,0);
4995         debug(F110,"initmdm dialmprmt",dialmprmt,0);
4996         debug(F110,"initmdm dialcmd",dialcmd,0);
4997         debug(F110,"initmdm dialdcon",dialdcon,0);
4998         debug(F110,"initmdm dialdcoff",dialdcoff,0);
4999         debug(F110,"initmdm dialecon",dialecon,0);
5000         debug(F110,"initmdm dialecoff",dialecoff,0);
5001         debug(F110,"initmdm dialhcmd",dialhcmd,0);
5002         debug(F110,"initmdm dialhwfc",dialhwfc,0);
5003         debug(F110,"initmdm dialswfc",dialswfc,0);
5004         debug(F110,"initmdm dialnofc",dialnofc,0);
5005         debug(F110,"initmdm dialtone",dialtone,0);
5006         debug(F110,"initmdm dialpulse",dialpulse,0);
5007         debug(F110,"initmdm dialname",dialname,0);
5008         debug(F110,"initmdm dialaaon",dialaaon,0);
5009         debug(F110,"initmdm dialaaoff",dialaaoff,0);
5010         debug(F110,"initmdm dialx3",dialx3,0);
5011         debug(F110,"initmdm dialspon",dialspon,0);
5012         debug(F110,"initmdm dialspoff",dialspoff,0);
5013         debug(F110,"initmdm dialvol1",dialvol1,0);
5014         debug(F110,"initmdm dialvol2",dialvol2,0);
5015         debug(F110,"initmdm dialvol3",dialvol3,0);
5016         debug(F110,"initmdm dialini2",dialini2,0);
5017     }
5018 #endif /* DEBUG */
5019
5020     if (usermdm && p) { /* USER-DEFINED: copy info from specified template */
5021
5022         makestr(&dialini  ,p->wake_str);
5023         makestr(&dialmstr ,p->dmode_str);
5024         makestr(&dialmprmt,p->dmode_prompt);
5025         makestr(&dialcmd  ,p->dial_str);
5026         makestr(&dialdcon ,p->dc_on_str);
5027         makestr(&dialdcoff,p->dc_off_str);
5028         makestr(&dialecon ,p->ec_on_str);
5029         makestr(&dialecoff,p->ec_off_str);
5030         makestr(&dialhcmd ,p->hup_str);
5031         makestr(&dialhwfc ,p->hwfc_str);
5032         makestr(&dialswfc ,p->swfc_str);
5033         makestr(&dialnofc ,p->nofc_str);
5034         makestr(&dialtone ,p->tone);
5035         makestr(&dialpulse,p->pulse);
5036         makestr(&dialname ,"This space available (use SET MODEM NAME)");
5037         makestr(&dialaaon ,p->aa_on_str);
5038         makestr(&dialaaoff,p->aa_off_str);
5039         makestr(&dialx3   ,p->ignoredt);
5040         makestr(&dialspon ,p->sp_on_str);
5041         makestr(&dialspoff,p->sp_off_str);
5042         makestr(&dialvol1 ,p->vol1_str);
5043         makestr(&dialvol2 ,p->vol2_str);
5044         makestr(&dialvol3 ,p->vol3_str);
5045         makestr(&dialini2 ,p->ini2);
5046
5047     } else {                    /* Not user-defined, so wipe out overrides */
5048
5049         if (dialini)   makestr(&dialini,NULL);   /* Init-string */
5050         if (dialmstr)  makestr(&dialmstr,NULL);  /* Dial-mode-str */
5051         if (dialmprmt) makestr(&dialmprmt,NULL); /* Dial-mode-pro */
5052         if (dialcmd)   makestr(&dialcmd,NULL);   /* Dial-command  */
5053         if (dialdcon)  makestr(&dialdcon,NULL);  /* DC ON command */
5054         if (dialdcoff) makestr(&dialdcoff,NULL); /* DC OFF command */
5055         if (dialecon)  makestr(&dialecon,NULL);  /* EC ON command */
5056         if (dialecoff) makestr(&dialecoff,NULL); /* EC OFF command */
5057         if (dialhcmd)  makestr(&dialhcmd,NULL);  /* Hangup command */
5058         if (dialhwfc)  makestr(&dialhwfc,NULL);  /* Flow control... */
5059         if (dialswfc)  makestr(&dialswfc,NULL);  /*  */
5060         if (dialnofc)  makestr(&dialnofc,NULL);  /*  */
5061         if (dialtone)  makestr(&dialtone,NULL);  /* Dialing method */
5062         if (dialpulse) makestr(&dialpulse,NULL); /*  */
5063         if (dialname)  makestr(&dialname,NULL);  /* Modem name */
5064         if (dialaaon)  makestr(&dialaaon,NULL);  /* Autoanswer On */
5065         if (dialaaoff) makestr(&dialaaoff,NULL); /* Autoanswer Off */
5066         if (dialx3)    makestr(&dialx3,NULL);    /* Ignore dialtone */
5067         if (dialspon)  makestr(&dialspon,NULL);  /* Speaker On */
5068         if (dialspoff) makestr(&dialspoff,NULL); /* Speaker Off */
5069         if (dialvol1)  makestr(&dialvol1,NULL);  /* Low volume */
5070         if (dialvol2)  makestr(&dialvol2,NULL);  /* Medium volume */
5071         if (dialvol3)  makestr(&dialvol3,NULL);  /* High volume */
5072         if (dialini2)  makestr(&dialini2,NULL);  /* Init string 2 */
5073     }
5074     if (autoflow)                       /* Maybe change flow control */
5075       setflow();
5076
5077 #ifndef MINIDIAL
5078 #ifdef OLDTBCODE
5079     tbmodel = 0;           /* If it's a Telebit, we don't know the model yet */
5080 #endif /* OLDTBCODE */
5081 #endif /* MINIDIAL */
5082 }
5083
5084 #ifdef COMMENT
5085 /* Not implemented yet */
5086 int
5087 setanswer() {
5088     int x, y;
5089     extern int ans_cid, ans_ring;
5090     if ((x = cmkey(answertab,nanswertab,"","",xxstring)) < 0)
5091       return(x);
5092     switch (x) {
5093       case XYA_CID:
5094         return(seton(&ans_cid));
5095       case XYA_RNG:
5096         y = cmnum("How many rings before answering","1",10,&x,xxstring);
5097         y = setnum(&ans_rings,x,y,254);
5098         return(y);
5099     }
5100 }
5101 #endif /* COMMENT */
5102
5103 int
5104 setmodem() {                            /* SET MODEM */
5105
5106     int x, y, z;
5107     long zz;
5108     struct FDB k1, k2;
5109     extern int mdmset;
5110
5111     cmfdbi(&k1,_CMKEY,
5112            "Modem parameter","","",nsetmdm, 0, xxstring, setmdm, &k2);
5113     cmfdbi(&k2,_CMKEY,"","","",nmdm,0,xxstring,mdmtab,NULL);
5114     x = cmfdb(&k1);
5115     if (x < 0) {                        /* Error */
5116         if (x == -2 || x == -9)
5117           printf("?No keywords match: \"%s\"\n",atmbuf);
5118         return(x);
5119     }
5120     y = cmresult.nresult;               /* Keyword value */
5121     if (cmresult.fdbaddr == &k2) {      /* Modem-type keyword table */
5122         if ((x = cmcfm()) < 0)
5123           return(x);
5124         usermdm = 0;
5125         initmdm(cmresult.nresult);      /* Set the modem type. */
5126         return(success = 1);            /* Done */
5127     }
5128     switch (cmresult.nresult) {         /* SET MODEM keyword table. */
5129 #ifdef MDMHUP
5130       case XYDMHU:                      /* DIAL MODEM-HANGUP */
5131         if ((y = cmkey(mdmhang,4,"how to hang up modem",
5132                        "modem-command", xxstring)) < 0)
5133           return(y);
5134         if ((x = cmcfm()) < 0)
5135           return(x);
5136         dialmhu = y;
5137 #ifdef COMMENT
5138 /* Nope, I fixed it (2001 11 08) */
5139 #ifdef CK_SCOV5
5140         if (dialmhu == 0 && !quiet) {
5141             printf(
5142 "\n WARNING: RS-232 signal sampling and manipulation do not work\n"
5143                     );
5144             printf(
5145 " in the standard SCO OSR5 serial i/o drivers.  SET MODEM HANGUP-METHOD\n"
5146                    );
5147             printf(
5148 " MODEM-COMMAND is recommended for OSR5.\n\n"
5149                     );
5150         }
5151 #endif /* CK_SCOV5 */
5152 #endif /* COMMENT */
5153         return(success = 1);
5154 #endif /* MDMHUP */
5155
5156       case XYDCAP:
5157         zz = 0L;
5158         y = 0;
5159         while (y != -3) {
5160             if ((y = cmkey(mdmcap,nmdmcap,
5161                            "capability of modem", "", xxstring)) < 0) {
5162                 if (y == -3)
5163                   break;
5164                 else
5165                   return(y);
5166             }
5167             zz |= y;
5168         }
5169         if ((x = cmcfm()) < 0)
5170           return(x);
5171         dialcapas = zz;
5172         debug(F101,"setmodem autoflow","",autoflow);
5173         debug(F101,"setmodem flow 1","",flow);
5174         if (autoflow)                   /* Maybe change flow control */
5175           setflow();
5176         debug(F101,"setmodem flow 2","",flow);
5177         mdmspd = zz & CKD_SB ? 0 : 1;   /* Set MODEM SPEED-MATCHING from it. */
5178         return(success = 1);
5179
5180       case XYDMAX:
5181 #ifdef TN_COMPORT
5182         if (network && istncomport())
5183           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
5184         else
5185 #endif /* TN_COMPORT */
5186           x = cmkey(spdtab,nspd,line,"",xxstring);
5187         if (x < 0) {
5188             if (x == -3) printf("?value required\n");
5189             return(x);
5190         }
5191         if ((y = cmcfm()) < 0) return(y);
5192         dialmax = (long) x * 10L;
5193         if (dialmax == 70) dialmax = 75;
5194         return(success = 1);
5195
5196       case XYDSTR:                      /* These moved from SET DIAL */
5197       case XYDDC:
5198       case XYDEC:
5199       case XYDESC:
5200       case XYDFC:
5201       case XYDKSP:
5202       case XYDSPD:
5203       case XYDDIA:
5204         return(setdial(x));
5205
5206       case XYDTYP:
5207         if ((y = cmkey(mdmtab,nmdm,"modem type","none", xxstring)) < 0)
5208           return(y);
5209         if (y == dialudt) {             /* User-defined modem type */
5210             if ((x = cmkey(mdmtab,nmdm,"based on existing modem type",
5211                            "unknown", xxstring)) < 0)
5212               return(x);
5213         }
5214         if ((z = cmcfm()) < 0)
5215           return(z);
5216         usermdm = 0;
5217         usermdm = (y == dialudt) ? x : 0;
5218         initmdm(y);
5219         mdmset = (mdmtyp > 0);
5220         return(success = 1);
5221
5222       case XYDNAM:
5223         return(dialstr(&dialname,"Descriptive name for modem"));
5224
5225       case XYDMCD:                      /* SET MODEM CARRIER-WATCH */
5226         return(setdcd());
5227
5228       case XYDSPK:                      /* SET MODEM SPEAKER */
5229         return(seton(&mdmspk));
5230
5231       case XYDVOL:                      /* SET MODEM VOLUME */
5232         if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0)
5233           return(x);
5234         if ((y = cmcfm()) < 0)
5235           return(y);
5236         mdmvol = x;
5237         return(success = 1);
5238
5239       default:
5240         printf("Unexpected SET MODEM parameter\n");
5241         return(-9);
5242     }
5243 }
5244
5245 static int                              /* Set DIAL command options */
5246 setdial(y) int y; {
5247     int x = 0, z = 0;
5248     char *s = NULL;
5249
5250     if (y < 0)
5251       if ((y = cmkey(dialtab,ndial,"","",xxstring)) < 0)
5252         return(y);
5253     switch (y) {
5254       case XYDHUP:                      /* DIAL HANGUP */
5255         return(seton(&dialhng));
5256       case XYDINI:                      /* DIAL INIT-STRING */
5257         return(dialstr(&dialini,"Modem initialization string"));
5258       case XYDNPR:                      /* DIAL PREFIX */
5259         return(dialstr(&dialnpr,"Telephone number prefix"));
5260       case XYDDIA:                      /* DIAL DIAL-COMMAND */
5261         x = cmtxt("Dialing command for modem,\n\
5262  include \"%s\" to stand for phone number,\n\
5263  for example, \"set dial dial-command ATDT%s\\13\"",
5264                   "",
5265                   &s,
5266                   xxstring);
5267         if (x < 0 && x != -3)           /* Handle parse errors */
5268           return(x);
5269         s = brstrip(s);                 /* Strip braces or quotes */
5270         y = x = strlen(s);              /* Get length of text */
5271         if (y > 0) {                    /* If there is any text (left), */
5272             for (x = 0; x < y; x++) {   /* make sure they included "%s" */
5273                 if (s[x] != '%') continue;
5274                 if (s[x+1] == 's') break;
5275             }
5276             if (x == y) {
5277                 printf(
5278 "?Dial-command must contain \"%cs\" for phone number.\n",'%');
5279                 return(-9);
5280             }
5281         }
5282         if (dialcmd) {                  /* Free any previous string. */
5283             free(dialcmd);
5284             dialcmd = (char *) 0;
5285         }
5286         if (y > 0) {
5287             dialcmd = malloc(y + 1);    /* Allocate space for it */
5288             if (dialcmd)
5289               strcpy(dialcmd,s);        /* and make a safe copy. */
5290         }
5291         return(success = 1);
5292 #ifndef NOXFER
5293       case XYDKSP:                      /* DIAL KERMIT-SPOOF */
5294         return(seton(&dialksp));
5295 #endif /* NOXFER */
5296       case XYDTMO:                      /* DIAL TIMEOUT */
5297         y = cmnum("Seconds to wait for call completion","0",10,&x,xxstring);
5298         if (y < 0) return(y);
5299         y = cmnum("Kermit/modem timeout differential","10",10,&z,xxstring);
5300         if (y < 0) return(y);
5301         if ((y = cmcfm()) < 0)
5302           return(y);
5303         dialtmo = x;
5304         mdmwaitd = z;
5305       case XYDESC:                      /* DIAL ESCAPE-CHARACTER */
5306         y = cmnum("ASCII value of character to escape back to modem",
5307                   "43",10,&x,xxstring);
5308         y = setnum(&dialesc,x,y,128);
5309         if (y > -1 && dialesc < 0)      /* No escape character */
5310           dialmhu = 0;                  /* So no hangup by modem command */
5311         return(y);
5312       case XYDDPY:                      /* DIAL DISPLAY */
5313         return(seton(&dialdpy));
5314       case XYDSPD:                      /* DIAL SPEED-MATCHING */
5315                                         /* used to be speed-changing */
5316         if ((y = seton(&mdmspd)) < 0) return(y);
5317 #ifdef COMMENT
5318         mdmspd = 1 - mdmspd;            /* so here we reverse the meaning */
5319 #endif /* COMMENT */
5320         return(success = 1);
5321       case XYDMNP:                      /* DIAL MNP-ENABLE */
5322       case XYDEC:                       /* DIAL ERROR-CORRECTION */
5323         x = seton(&dialec);
5324         if (x > 0)
5325           if (!dialec) dialdc = 0;      /* OFF also turns off compression */
5326         return(x);
5327
5328       case XYDDC:                       /* DIAL COMPRESSION */
5329         x = seton(&dialdc);
5330         if (x > 0)
5331           if (dialdc) dialec = 1;       /* ON also turns on error correction */
5332         return(x);
5333
5334 #ifdef MDMHUP
5335       case XYDMHU:                      /* DIAL MODEM-HANGUP */
5336         return(seton(&dialmhu));
5337 #endif /* MDMHUP */
5338
5339 #ifndef NOSPL
5340       case XYDDIR:                      /* DIAL DIRECTORY (zero or more) */
5341         return(parsdir(0));             /* 0 means DIAL */
5342 #endif /* NOSPL */
5343
5344       case XYDSTR:                      /* DIAL STRING */
5345         if ((y = cmkey(mdmcmd,nmdmcmd,"","",xxstring)) < 0) return(y);
5346         switch (y) {
5347           case XYDS_AN:                 /* Autoanswer ON/OFF */
5348           case XYDS_DC:                 /* Data compression ON/OFF */
5349           case XYDS_EC:                 /* Error correction ON/OFF */
5350             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
5351               return(x);
5352             sprintf(tmpbuf,"Modem's command to %sable %s", /* SAFE */
5353                     x ? "en" : "dis",
5354                     (y == XYDS_DC) ? "compression" :
5355                     ((y == XYDS_EC) ? "error-correction" :
5356                     "autoanswer")
5357                     );
5358             if (x) {
5359                 if (y == XYDS_DC)
5360                   return(dialstr(&dialdcon,tmpbuf));
5361                 else if (y == XYDS_EC)
5362                   return(dialstr(&dialecon,tmpbuf));
5363                 else
5364                   return(dialstr(&dialaaon,tmpbuf));
5365             } else {
5366                 if (y == XYDS_DC)
5367                   return(dialstr(&dialdcoff,tmpbuf));
5368                 else if (y == XYDS_EC)
5369                   return(dialstr(&dialecoff,tmpbuf));
5370                 else
5371                   return(dialstr(&dialaaoff,tmpbuf));
5372             }
5373           case XYDS_HU:                 /*    hangup command */
5374             return(dialstr(&dialhcmd,"Modem's hangup command"));
5375           case XYDS_HW:                 /*    hwfc */
5376             return(dialstr(&dialhwfc,
5377                            "Modem's command to enable hardware flow control"));
5378           case XYDS_IN:                 /*    init */
5379             return(dialstr(&dialini,"Modem's initialization string"));
5380           case XYDS_NF:                 /*    no flow control */
5381             return(dialstr(&dialnofc,
5382                            "Modem's command to disable local flow control"));
5383           case XYDS_PX:                 /*    prefix */
5384             return(dialstr(&dialnpr,"Telephone number prefix for dialing"));
5385           case XYDS_SW:                 /*    swfc */
5386             return(dialstr(&dialswfc,
5387                    "Modem's command to enable local software flow control"));
5388           case XYDS_DT:                 /*    tone dialing */
5389             return(dialstr(&dialtone,
5390                    "Command to configure modem for tone dialing"));
5391           case XYDS_DP:                 /*    pulse dialing */
5392             return(dialstr(&dialpulse,
5393                            "Command to configure modem for pulse dialing"));
5394           case XYDS_MS:                 /*    dial mode string */
5395             return(dialstr(&dialmstr,
5396                          "Command to enter dial mode"));
5397           case XYDS_MP:                 /*    dial mode prompt */
5398             return(dialstr(&dialmprmt,
5399                            "Modem response upon entering dial mode"));
5400           case XYDS_SP:                 /* SPEAKER OFF */
5401             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0) return(x);
5402             if (x)
5403               return(dialstr(&dialspon,"Command to turn modem speaker on"));
5404             else
5405               return(dialstr(&dialspoff,"Command to turn modem speaker off"));
5406
5407           case XYDS_VO:                 /* VOLUME LOW */
5408             if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0) return(x);
5409             switch (x) {
5410               case 0:
5411               case 1:
5412                 return(dialstr(&dialvol1,
5413                                "Command for low modem speaker volume"));
5414               case 2:
5415                 return(dialstr(&dialvol2,
5416                            "Command for medium modem speaker volume"));
5417
5418               case 3:
5419                 return(dialstr(&dialvol3,
5420                                "Command for high modem speaker volume"));
5421               default:
5422                 return(-2);
5423             }
5424
5425           case XYDS_ID:                 /* IGNORE-DIALTONE */
5426             return(dialstr(&dialx3,
5427                            "Command to tell modem to ignore dialtone"));
5428
5429           case XYDS_I2:                 /* PREDIAL-INIT */
5430             return(dialstr(&dialini2,
5431                            "Command to send to modem just prior to dialing"));
5432
5433           default:
5434             printf("?Unexpected SET DIAL STRING parameter\n");
5435         }
5436
5437       case XYDFC:                       /* DIAL FLOW-CONTROL */
5438         if ((y = cmkey(dial_fc,4,"","auto",xxstring)) < 0) return(y);
5439         if ((x = cmcfm()) < 0) return(x);
5440         dialfc = y;
5441         return(success = 1);
5442
5443       case XYDMTH: {                    /* DIAL METHOD */
5444         extern int dialmauto;
5445         if ((y = cmkey(dial_m,ndial_m,"","default",xxstring)) < 0)
5446           return(y);
5447         if ((x = cmcfm()) < 0)
5448           return(x);
5449         if (y == XYDM_A) {              /* AUTO */
5450             dialmauto = 1;              /* local country code, if known. */
5451             dialmth = XYDM_D;
5452         } else {
5453           dialmauto = 0;                /* use the method specified */
5454           dialmth = y;
5455         }
5456         return(success = 1);
5457       }
5458       case XYDRTM:
5459         y = cmnum("Number of times to try dialing a number",
5460                   "1",10,&x,xxstring);
5461         z = setnum(&dialrtr,x,y,-1);
5462         if (z > -1 && dialrtr < 0) {
5463             printf("?Sorry, negative dial retries not valid: %d\n",dialrtr);
5464             return(-9);
5465         }
5466         return(z);
5467
5468       case XYDINT:
5469         y = cmnum("Seconds to wait between redial attempts",
5470                   "30",10,&x,xxstring);
5471         z = setnum(&dialint,x,y,-1);
5472         if (z > -1 && dialint < 0) {
5473             printf("?Sorry, negative dial interval not valid: %d\n",dialint);
5474             return(-9);
5475         }
5476         return(z);
5477
5478       case XYDLAC:                      /* DIAL AREA-CODE */
5479         if ((x = dialstr(&diallac,"Area code you are calling from")) < 0)
5480           return(x);
5481         if (diallac) {
5482             if (!rdigits(diallac)) {
5483                 printf("?Sorry, area code must be numeric\n");
5484                 if (*diallac == '(')
5485                   printf("(please omit the parentheses)\n");
5486                 if (*diallac == '/')
5487                   printf("(no slashes, please)\n");
5488                 if (diallac) free(diallac);
5489                 diallac = NULL;
5490                 return(-9);
5491             }
5492         }
5493         return(x);
5494
5495       case XYDCNF:                      /* CONFIRMATION */
5496         return(success = seton(&dialcnf));
5497
5498       case XYDCVT:                      /* CONVERT-DIRECTORY */
5499         if ((y = cmkey(dcnvtab,3,"","ask",xxstring)) < 0)
5500           return(y);
5501         if ((x = cmcfm()) < 0)
5502           return(x);
5503         dialcvt = y;
5504         return(success = 1);
5505
5506       case XYDLCC:                      /* DIAL COUNTRY-CODE */
5507         x = dialstr(&diallcc,"Country code you are calling from");
5508         if (x < 1) return(x);
5509         if (diallcc) {
5510             if (!rdigits(diallcc)) {
5511                 printf("?Sorry, country code must be numeric\n");
5512                 if (*diallcc == '+')
5513                   printf("(please omit the plus sign)\n");
5514                 if (diallcc) free(diallcc);
5515                 diallcc = NULL;
5516                 return(-9);
5517             }
5518             if (!strcmp(diallcc,"1")) { /* Set defaults for USA and Canada */
5519                 if (!dialldp)           /* Long-distance prefix */
5520                   makestr(&dialldp,"1");
5521                 if (!dialixp)           /* International dialing prefix */
5522                   makestr(&dialixp,"011");
5523                 if (ntollfree == 0) {   /* Toll-free area codes */
5524                     if ((dialtfc[0] = malloc(4))) {
5525                         strcpy(dialtfc[0],"800"); /* 1970-something */
5526                         ntollfree++;
5527                         if ((dialtfc[1] = malloc(4))) {
5528                             strcpy(dialtfc[1],"888"); /* 1996 */
5529                             ntollfree++;
5530                             if ((dialtfc[2] = malloc(4))) {
5531                                 strcpy(dialtfc[2],"877"); /* 5 April 1998 */
5532                                 ntollfree++;
5533                                 if ((dialtfc[3] = malloc(4))) {
5534                                     strcpy(dialtfc[3],"866"); /* 2000? */
5535                                     ntollfree++;
5536                                 }
5537                             }
5538                         }
5539                     }
5540                 }
5541                 if (!dialtfp)           /* Toll-free dialing prefix */
5542                   makestr(&dialtfp,"1");
5543 #ifdef COMMENT
5544 /* The time for this is past */
5545             } else if (!strcmp(diallcc,"358") &&
5546                        ((int) strcmp(zzndate(),"19961011") > 0)
5547                        ) {              /* Finland */
5548                 if (!dialldp)           /* Long-distance prefix */
5549                   makestr(&dialldp,"9");
5550                 if (!dialixp)           /* International dialing prefix */
5551                   makestr(&dialixp,"990");
5552 #endif /* COMMENT */
5553             } else {                    /* Everywhere else ... */
5554                 if (!dialldp) {
5555                     if ((dialldp = malloc(4)))
5556                       strcpy(dialldp,"0");
5557                 }
5558                 if (!dialixp) {
5559                     if ((dialixp = malloc(4)))
5560                       strcpy(dialixp,"00");
5561                 }
5562             }
5563             if (!strcmp(diallcc,"33"))  /* France */
5564               dialfld = 1;              /* Long-distance dialing is forced */
5565         }
5566         return(success = 1);
5567
5568       case XYDIXP:                      /* DIAL INTL-PREFIX */
5569         return(dialstr(&dialixp,"International dialing prefix"));
5570
5571       case XYDIXS:                      /* DIAL INTL-SUFFIX */
5572         return(dialstr(&dialixs,"International dialing suffix"));
5573
5574       case XYDLDP:                      /* DIAL LD-PREFIX */
5575         return(dialstr(&dialldp,"Long-distance dialing prefix"));
5576
5577       case XYDLDS:                      /* DIAL LD-SUFFIX */
5578         return(dialstr(&diallds,"Long-distance dialing suffix"));
5579
5580       case XYDLCP:                      /* DIAL LC-PREFIX */
5581         return(dialstr(&diallcp,"Local dialing prefix"));
5582
5583       case XYDLCS:                      /* DIAL LC-SUFFIX */
5584         return(dialstr(&diallcs,"Local dialing suffix"));
5585
5586 #ifdef COMMENT
5587       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
5588         return(dialstr(&dialpxx,"Exchange of PBX you are calling from"));
5589 #endif /* COMMENT */
5590
5591       case XYDPXI: {                    /* DIAL PBX-INTERNAL-PREFIX */
5592 #ifdef COMMENT
5593           return(dialstr(&dialpxi,
5594                        "Internal-call prefix of PBX you are calling from"));
5595 #else
5596           int x;
5597           if ((x = cmtxt("Internal-call prefix of PBX you are calling from",
5598                          "",&s,NULL)) < 0) /* Don't evaluate */
5599             return(x);
5600 #ifndef NOSPL
5601           if (*s) {
5602               char c, * p = tmpbuf;
5603               if (*s == '\\') {
5604                   c = *(s+1);
5605                   if (isupper(c)) c = tolower(c);
5606                   if (c != 'f' &&
5607                       ckstrcmp(s,"\\v(d$px)",8,0) &&
5608                       ckstrcmp(s,"\\v(d$pxx)",9,0) &&
5609                       ckstrcmp(s,"\\v(d$p)",7,0)) {
5610                       x = TMPBUFSIZ;
5611                       zzstring(s,&p,&x);
5612                       s = tmpbuf;
5613                   }
5614               }
5615           }
5616 #endif /* NOSPL */
5617           makestr(&dialpxi,s);
5618           return(1);
5619       }
5620 #endif /* COMMENT */
5621
5622       case XYDPXO:                      /* DIAL PBX-OUTSIDE-PREFIX */
5623         return(dialstr(&dialpxo,
5624                        "Outside-line prefix of PBX you are calling from"));
5625
5626       case XYDSFX:                      /* DIAL INTL-SUFFIX */
5627         return(dialstr(&dialsfx," Telephone number suffix for dialing"));
5628
5629       case XYDSRT:                      /* DIAL SORT */
5630         return(success = seton(&dialsrt));
5631
5632       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
5633       case XYDTFC: {                    /* DIAL TOLL-FREE-AREA-CODE  */
5634           int n, i;                     /* (zero or more of them...) */
5635           char * p[MAXTOLLFREE];        /* Temporary pointers */
5636           char * m;
5637           for (n = 0; n < MAXTOLLFREE; n++) {
5638               if (n == 0) {
5639                   m = (y == XYDTFC) ?
5640                   "Toll-free area code(s) in the country you are calling from"
5641                     : "Exchange(s) of PBX you are calling from";
5642               } else {
5643                   m = (y == XYDTFC) ?
5644                     "Another toll-free area code"
5645                       : "Another PBX exchange";
5646               }
5647               if ((x = cmfld(m,"",&s,xxstring)) < 0)
5648                 break;
5649               if (s) {
5650                   int k;
5651                   k = (int) strlen(s);
5652                   if (k > 0) {
5653                       if ((p[n] = malloc(k + 1)))
5654                         strcpy(p[n], s); /* safe */
5655                   } else break;
5656               } else break;
5657           }
5658           if (x == -3) {                /* Command was successful */
5659               int m;
5660               m = (y == XYDTFC) ? ntollfree : ndialpxx;
5661               if ((x = cmcfm()) < 0)
5662                 return(x);
5663               x = 1;
5664               for (i = 0; i < m; i++) { /* Remove old list, if any */
5665                   if  (y == XYDTFC)
5666                     makestr(&(dialtfc[i]),NULL);
5667                   else
5668                     makestr(&(dialpxx[i]),NULL);
5669               }
5670               if  (y == XYDTFC)
5671                 ntollfree = n;          /* New count */
5672               else
5673                 ndialpxx = n;
5674               for (i = 0; i < n; i++) { /* New list */
5675                   if  (y == XYDTFC)
5676                     makestr(&(dialtfc[i]),p[i]);
5677                   else
5678                     makestr(&(dialpxx[i]),p[i]);
5679               }
5680               x = 1;
5681           }
5682           for (i = 0; i < n; i++)
5683             if (p[i]) free(p[i]);
5684           return(x);
5685       }
5686
5687       case XYDTFP:                      /* TOLL-FREE-PREFIX */
5688         return(dialstr(&dialtfp,
5689                        " Long-distance prefix for toll-free dialing"));
5690
5691       case XYDCON:                      /* CONNECT */
5692         z = -1;
5693         if ((y = cmkey(crrtab,ncrr,"","auto",xxstring)) < 0) return(y);
5694         if (y != CAR_OFF)               /* AUTO or ON? */
5695           if ((z = cmkey(qvtab,nqvt,"","verbose",xxstring)) < 0) return(z);
5696         if ((x = cmcfm()) < 0) return(x);
5697         if (z > -1)
5698           dialcq = z;
5699         dialcon = y;
5700         return(success = 1);
5701
5702       case XYDRSTR:                     /* RESTRICT */
5703         if ((y = cmkey(drstrtab,4,"","none",xxstring)) < 0) return(y);
5704         if ((x = cmcfm()) < 0) return(x);
5705         dialrstr = y;
5706         return(success = 1);
5707
5708       case XYDLLAC: {                   /* Local area-code list  */
5709           int n, i;                     /* (zero or more of them...) */
5710           char * p[MAXLOCALAC]; /* Temporary pointers */
5711           for (n = 0; n < MAXLOCALAC; n++) {
5712               if ((x = cmfld(
5713                     "Area code to which calls from your area are local",
5714                        "",&s,xxstring)) < 0)
5715                 break;
5716               if (s) {
5717                   int k;
5718                   k = (int) strlen(s);
5719                   if (k > 0) {
5720                       if ((p[n] = malloc(k + 1)))
5721                         strcpy(p[n], s); /* safe */
5722                   } else break;
5723               } else break;
5724           }
5725           if (x == -3) {                /* Command was successful */
5726               if ((x = cmcfm()) < 0)
5727                 return(x);
5728               for (i = 0; i < nlocalac; i++) /* Remove old list, if any */
5729                 if (diallcac[i]) {
5730                     free(diallcac[i]);
5731                     diallcac[i] = NULL;
5732                 }
5733               nlocalac = n;             /* New count */
5734               for (i = 0; i < nlocalac; i++) /* New list */
5735                 diallcac[i] = p[i];
5736               return(success = 1);
5737           } else {                      /* Parse error, undo everything */
5738               for (i = 0; i < n; i++)
5739                 if (p[i]) free(p[i]);
5740               return(x);
5741           }
5742       }
5743
5744       case XYDFLD:
5745         return(success = seton(&dialfld));
5746
5747       case XYDIDT:                      /* DIAL IGNORE-DIALTONE */
5748         return(seton(&dialidt));
5749
5750       case XYDPAC:
5751         y = cmnum(
5752               "Milliseconds to pause between each character sent to dialer",
5753                   "",10,&x,xxstring);
5754         return(setnum(&dialpace,x,y,9999));
5755
5756 #ifndef NOSPL
5757       case XYDMAC:
5758         if ((x = cmfld("Name of macro to execute just prior to dialing",
5759                        "",&s,xxstring)) < 0) {
5760             if (x == -3)
5761               s = NULL;
5762             else
5763               return(x);
5764         }
5765         if (s) {
5766             if (!*s) {
5767                 s = NULL;
5768             } else {
5769                 ckstrncpy(line,s,LINBUFSIZ);
5770                 s = line;
5771             }
5772         }
5773         if ((x = cmcfm()) < 0)
5774           return(x);
5775         makestr(&dialmac,s);
5776         return(success = 1);
5777 #endif /* NOSPL */
5778
5779       case XYDPUCC:                     /* Pulse country codes */
5780       case XYDTOCC: {                   /* Tone country codes */
5781           int n, i;
5782           char * p[MAXTPCC];
5783           char * m;
5784           for (n = 0; n < MAXTPCC; n++) {
5785               if (n == 0) {
5786                   m = (y == XYDPUCC) ?
5787                   "Country code where Pulse dialing is required"
5788                     : "Country code where Tone dialing is available";
5789               } else
5790                 m = "Another country code";
5791               if ((x = cmfld(m,"",&s,xxstring)) < 0)
5792                 break;
5793               if (s) {
5794                   int k;
5795                   k = (int) strlen(s);
5796                   if (k > 0) {
5797                       if ((p[n] = malloc(k + 1)))
5798                         strcpy(p[n], s); /* safe */
5799                   } else break;
5800               } else break;
5801           }
5802           if (x == -3) {                /* Command was successful */
5803               int m;
5804               m = (y == XYDPUCC) ? ndialpucc : ndialtocc;
5805               if ((x = cmcfm()) < 0)
5806                 return(x);
5807               x = 1;
5808               for (i = 0; i < m; i++) { /* Remove old list, if any */
5809                   if (y == XYDPUCC)
5810                     makestr(&(dialpucc[i]),NULL);
5811                   else
5812                     makestr(&(dialtocc[i]),NULL);
5813               }
5814               if (y == XYDPUCC) {
5815                   ndialpucc = n;                /* New count */
5816               } else {
5817                   ndialtocc = n;
5818               }
5819               for (i = 0; i < n; i++) { /* New list */
5820                   if (y == XYDPUCC) {
5821                       makestr(&(dialpucc[i]),p[i]);
5822                   } else {
5823                       makestr(&(dialtocc[i]),p[i]);
5824                   }
5825               }
5826               x = 1;
5827           }
5828           for (i = 0; i < n; i++)
5829             if (p[i]) free(p[i]);
5830           return(x);
5831       }
5832       case XYDTEST:
5833         return(seton(&dialtest));
5834
5835       default:
5836         printf("?Unexpected SET DIAL parameter\n");
5837         return(-9);
5838     }
5839 }
5840
5841 #ifndef NOSHOW
5842 int                                     /* SHOW MODEM */
5843 shomodem() {
5844     MDMINF * p;
5845     int x, n, mdm;
5846     char c;
5847     long zz;
5848
5849 #ifdef IKSD
5850     if (inserver) {
5851         printf("Sorry, command disabled\r\n");
5852         return(success = 0);
5853     }
5854 #endif /* IKSD */
5855
5856     shmdmlin();
5857     printf("\n");
5858
5859     mdm = (mdmtyp > 0) ? mdmtyp : mdmsav;
5860     p = (mdm > 0) ? modemp[mdm] : NULL;
5861
5862     if (p) {
5863         printf(" %s\n\n", dialname ? dialname : p->name);
5864
5865         printf(" Modem capabilities:    ");
5866         zz = dialcapas ? dialcapas : p->capas;
5867         if (!zz) {
5868             printf(" (none)");
5869         } else {
5870             if (zz & CKD_AT) printf(" AT");
5871             if (zz & CKD_V25) printf(" ITU");
5872             if (zz & CKD_SB) printf(" SB");
5873             if (zz & CKD_EC) printf(" EC");
5874             if (zz & CKD_DC) printf(" DC");
5875             if (zz & CKD_HW) printf(" HWFC");
5876             if (zz & CKD_SW) printf(" SWFC");
5877             if (zz & CKD_KS) printf(" KS");
5878             if (zz & CKD_TB) printf(" TB");
5879         }
5880         printf("\n Modem carrier-watch:    ");
5881         if (carrier == CAR_OFF) printf("off\n");
5882         else if (carrier == CAR_ON) printf("on\n");
5883         else if (carrier == CAR_AUT) printf("auto\n");
5884         else printf("unknown\n");
5885
5886         printf(" Modem maximum-speed:    ");
5887         zz = (dialmax > 0L) ? dialmax : p->max_speed;
5888         if (zz > 0)
5889           printf("%ld bps\n", zz);
5890         else
5891           printf("(unknown)\n");
5892         printf(" Modem error-correction: %s\n", dialec ? "on" : "off");
5893         printf(" Modem compression:      %s\n", dialdc ? "on" : "off");
5894         printf(" Modem speed-matching:   %s",   mdmspd ? "on" : "off");
5895         printf(" (interface speed %s)\n", mdmspd ? "changes" : "is locked");
5896         printf(" Modem flow-control:     ");
5897         if (dialfc == FLO_NONE) printf("none\n");
5898         else if (dialfc == FLO_XONX) printf("xon/xoff\n");
5899         else if (dialfc == FLO_RTSC) printf("rts/cts\n");
5900         else if (dialfc == FLO_AUTO) printf("auto\n");
5901         printf(" Modem hangup-method:    %s\n",
5902                dialmhu ?
5903                "modem-command" :
5904                "rs232-signal"
5905                );
5906         printf(" Modem speaker:          %s\n", showoff(mdmspk));
5907         printf(" Modem volume:           %s\n",
5908                (mdmvol == 2) ? "medium" : ((mdmvol <= 1) ? "low" : "high"));
5909         printf(" Modem kermit-spoof:     %s\n", dialksp ? "on" : "off");
5910         c = (char) (x = (dialesc ? dialesc : p->esc_char));
5911         printf(" Modem escape-character: %d", x);
5912         if (isprint(c))
5913           printf(" (= \"%c\")",c);
5914         printf(
5915 "\n\nMODEM COMMANDs (* = set automatically by SET MODEM TYPE):\n\n");
5916         debug(F110,"show dialini",dialini,0);
5917         printf(" %c Init-string:          ", dialini ? ' ' : '*' );
5918         shods(dialini ? dialini : p->wake_str);
5919         printf(" %c Dial-mode-string:     ", dialmstr ? ' ' : '*' );
5920         shods(dialmstr ? dialmstr : p->dmode_str);
5921         n = local ? 19 : 20;
5922         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5923         printf(" %c Dial-mode-prompt:     ", dialmprmt ? ' ' : '*' );
5924         shods(dialmprmt ? dialmprmt : p->dmode_prompt);
5925         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5926         printf(" %c Dial-command:         ", dialcmd ? ' ' : '*' );
5927         shods(dialcmd ? dialcmd : p->dial_str);
5928         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5929         printf(" %c Compression on:       ", dialdcon ? ' ' : '*' );
5930         if (!dialdcon)
5931           debug(F110,"dialdcon","(null)",0);
5932         else
5933           debug(F110,"dialdcon",dialdcon,0);
5934         shods(dialdcon ? dialdcon : p->dc_on_str);
5935         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5936         printf(" %c Compression off:      ", dialdcoff ? ' ' : '*' );
5937         shods(dialdcoff ? dialdcoff : p->dc_off_str);
5938         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5939         printf(" %c Error-correction on:  ", dialecon ? ' ' : '*' );
5940         shods(dialecon ? dialecon : p->ec_on_str);
5941         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5942         printf(" %c Error-correction off: ", dialecoff ? ' ' : '*' );
5943         shods(dialecoff ? dialecoff : p->ec_off_str);
5944         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5945         printf(" %c Autoanswer on:        ", dialaaon ? ' ' : '*' );
5946         shods(dialaaon ? dialaaon : p->aa_on_str);
5947         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5948         printf(" %c Autoanswer off:       ", dialaaoff ? ' ' : '*' );
5949         shods(dialaaoff ? dialaaoff : p->aa_off_str);
5950         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5951
5952         printf(" %c Speaker on:           ", dialspon ? ' ' : '*' );
5953         shods(dialspon ? dialspon : p->sp_on_str);
5954         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5955         printf(" %c Speaker off:          ", dialspoff ? ' ' : '*' );
5956         shods(dialspoff ? dialspoff : p->sp_off_str);
5957         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5958         printf(" %c Volume low:           ", dialvol1 ? ' ' : '*' );
5959         shods(dialvol1 ? dialvol1 : p->vol1_str);
5960         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5961         printf(" %c Volume medium:        ", dialvol2 ? ' ' : '*' );
5962         shods(dialvol2 ? dialvol2 : p->vol2_str);
5963         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5964         printf(" %c Volume high:          ", dialvol3 ? ' ' : '*' );
5965         shods(dialvol3 ? dialvol3 : p->vol3_str);
5966         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5967
5968         printf(" %c Hangup-command:       ", dialhcmd ? ' ' : '*' );
5969         shods(dialhcmd ? dialhcmd : p->hup_str);
5970         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5971         printf(" %c Hardware-flow:        ", dialhwfc ? ' ' : '*' );
5972         shods(dialhwfc ? dialhwfc : p->hwfc_str);
5973         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5974         printf(" %c Software-flow:        ", dialswfc ? ' ' : '*' );
5975         shods(dialswfc ? dialswfc : p->swfc_str);
5976         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5977         printf(" %c No-flow-control:      ", dialnofc ? ' ' : '*' );
5978         shods(dialnofc ? dialnofc : p->nofc_str);
5979         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5980         printf(" %c Pulse:                ", dialpulse ? ' ' : '*');
5981         shods(dialpulse ? dialpulse : p->pulse);
5982         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5983         printf(" %c Tone:                 ", dialtone ? ' ' : '*');
5984         shods(dialtone ? dialtone : p->tone);
5985
5986         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5987         printf(" %c Ignore-dialtone:      ", dialx3 ? ' ' : '*');
5988         shods(dialx3 ? dialx3 : p->ignoredt);
5989
5990         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5991         printf(" %c Predial-init:         ", dialini2 ? ' ' : '*');
5992         shods(dialini2 ? dialini2 : p->ini2);
5993
5994         if (++n > cmd_rows - 4) if (!askmore()) return(0); else n = 0;
5995         printf("\n For more info: SHOW DIAL and SHOW COMMUNICATIONS\n");
5996
5997     } else if (mdm > 0) {
5998         printf("Modem info for \"%s\" not filled in yet\n", gmdmtyp());
5999     } else printf(
6000 " No modem selected, so DIAL and most SET MODEM commands have no effect.\n\
6001  Use SET MODEM TYPE to select a modem.\n");
6002     return(success = 1);
6003 }
6004 #endif /* NOSHOW */
6005 #endif /* NODIAL */
6006
6007 #ifdef CK_TAPI
6008 int                                             /* TAPI action commands */
6009 dotapi() {
6010     int x,y;
6011     char *s;
6012
6013     if (!TAPIAvail) {
6014         printf("\nTAPI is unavailable on this system.\n");
6015         return(-9);
6016     }
6017     if ((y = cmkey(tapitab,ntapitab,"MS TAPI command","",xxstring)) < 0)
6018       return(y);
6019     switch (y) {
6020       case XYTAPI_CFG: {                        /* TAPI CONFIGURE-LINE */
6021           extern struct keytab * tapilinetab;
6022           extern struct keytab * _tapilinetab;
6023           extern int ntapiline;
6024           extern int LineDeviceId;
6025           int lineID=LineDeviceId;
6026           if (TAPIAvail)
6027             cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
6028           if (tapilinetab && _tapilinetab && ntapiline > 0) {
6029               int i=0, j = 9999, k = -1;
6030
6031               if ( LineDeviceId == -1 ) {
6032                   /* Find out what the lowest numbered TAPI device is */
6033                   /* and use it as the default.                       */
6034                   for (i = 0; i < ntapiline; i++ ) {
6035                       if (tapilinetab[i].kwval < j) {
6036                           k = i;
6037                       }
6038                   }
6039               } else {
6040                   /* Find the LineDeviceId in the table and use that entry */
6041                   for (i = 0; i < ntapiline; i++ ) {
6042                       if (tapilinetab[i].kwval == LineDeviceId) {
6043                           k = i;
6044                           break;
6045                       }
6046                   }
6047               }
6048               if (k >= 0)
6049                 s = _tapilinetab[k].kwd;
6050               else
6051                 s = "";
6052
6053               if ((y = cmkey(_tapilinetab,ntapiline,
6054                               "TAPI device name",s,xxstring)) < 0)
6055                 return(y);
6056               lineID = y;
6057           }
6058           if ((x = cmcfm()) < 0) return(x);
6059 #ifdef IKSD
6060           if (inserver) {
6061               printf("Sorry, command disabled\r\n");
6062               return(success = 0);
6063           }
6064 #endif /* ISKD */
6065           cktapiConfigureLine(lineID);
6066           break;
6067       }
6068       case XYTAPI_DIAL:                 /* TAPI DIALING-PROPERTIES */
6069         if ((x = cmcfm()) < 0)
6070           return(x);
6071 #ifdef IKSD
6072         if (inserver) {
6073             printf("Sorry, command disabled\r\n");
6074             return(success = 0);
6075         }
6076 #endif /* ISKD */
6077         cktapiDialingProp();
6078         break;
6079     }
6080     return(success = 1);
6081 }
6082
6083 static int                              /* SET TAPI command options */
6084 settapi() {
6085     int x, y;
6086     char *s;
6087
6088     if (!TAPIAvail) {
6089         printf("\nTAPI is unavailable on this system.\n");
6090         return(-9);
6091     }
6092     if ((y = cmkey(settapitab,nsettapitab,"MS TAPI option","",xxstring)) < 0)
6093       return(y);
6094     switch (y) {
6095       case XYTAPI_USE:
6096         return (success = seton(&tapiusecfg));
6097       case XYTAPI_LGHT:
6098         return (success = seton(&tapilights));
6099       case XYTAPI_PRE:
6100         return (success = seton(&tapipreterm));
6101       case XYTAPI_PST:
6102         return (success = seton(&tapipostterm));
6103       case XYTAPI_INA:
6104         y = cmnum("seconds of inactivity before auto-disconnect",
6105                   "0",10,&x,xxstring);
6106         return(setnum(&tapiinactivity,x,y,65535));
6107       case XYTAPI_BNG:
6108         y = cmnum("seconds to wait for credit card tone",
6109                   "8",10,&x,xxstring);
6110         return(setnum(&tapibong,x,y,90));
6111       case XYTAPI_MAN:
6112         return (success = seton(&tapimanual));
6113       case XYTAPI_CON:                  /* TAPI CONVERSIONS */
6114         return (success = setonaut(&tapiconv));
6115       case XYTAPI_LIN:                  /* TAPI LINE */
6116         x = setlin(XYTAPI_LIN,1,0);
6117         if (x > -1) didsetlin++;
6118         return(x);
6119       case XYTAPI_PASS: {               /* TAPI PASSTHROUGH */
6120 #ifdef NODIAL
6121           printf("\n?Modem-dialing not supported\n");
6122           return(-9);
6123 #else /* NODIAL */
6124           /* Passthrough became Modem-dialing which is an antonym */
6125           success = seton(&tapipass);
6126           tapipass = !tapipass;
6127           return (success);
6128 #endif /* NODIAL */        
6129       }
6130       case XYTAPI_LOC: {                /* TAPI LOCATION */
6131           extern char tapiloc[];
6132           extern int tapilocid;
6133           int i = 0, j = 9999, k = -1;
6134
6135           cktapiBuildLocationTable(&tapiloctab, &ntapiloc);
6136           if (!tapiloctab || !ntapiloc) {
6137               printf("\nNo TAPI Locations are configured for this system\n");
6138               return(-9);
6139           }
6140           if (tapilocid == -1)
6141             tapilocid = cktapiGetCurrentLocationID();
6142
6143           /* Find the current tapiloc entry */
6144           /* and use it as the default. */
6145           for (k = 0; k < ntapiloc; k++) {
6146               if (tapiloctab[k].kwval == tapilocid)
6147                 break;
6148           }
6149           if (k >= 0 && k < ntapiloc)
6150             s = tapiloctab[k].kwd;
6151           else
6152             s = "";
6153
6154           if ((y = cmkey(tapiloctab,ntapiloc, "TAPI location",s,xxstring)) < 0)
6155             return(y);
6156
6157           if ((x = cmcfm()) < 0)
6158             return(x);
6159 #ifdef IKSD
6160           if (inserver) {
6161               printf("Sorry, command disabled\r\n");
6162               return(success = 0);
6163           }
6164 #endif /* IKSD */
6165           cktapiFetchLocationInfoByID( y );
6166 #ifndef NODIAL
6167           CopyTapiLocationInfoToKermitDialCmd();
6168 #endif /* NODIAL */
6169         }
6170         break;
6171     }
6172     return(success=1);
6173 }
6174 #endif /* CK_TAPI */
6175 #endif /* NOLOCAL */
6176
6177 #ifndef NOSPL
6178 #ifdef CK_ANSIC                         /* SET ALARM */
6179 int
6180 setalarm(long xx)
6181 #else
6182 int
6183 setalarm(xx) long xx;
6184 #endif /* CK_ANSIC */
6185 /* setalarm */ {
6186 #ifdef COMMENT
6187     int yyyy, mm, dd, x;
6188     char *s;
6189     long zz;
6190     char buf[6];
6191 #endif /* COMMENT */
6192     long sec, jd;
6193     char xbuf[20], * p;
6194
6195     debug(F101,"setalarm xx","",xx);
6196     ck_alarm = 0L;                      /* 0 = no alarm (in case of error) */
6197     if (xx < 0L) {
6198         printf("%ld - illegal value, must be 0 or positive\n", xx);
6199         return(-9);
6200     }
6201     if (xx == 0L) {                     /* CLEAR ALARM */
6202         alrm_date[0] = NUL;
6203         alrm_time[0] = NUL;
6204         return(1);
6205     }
6206 #ifdef COMMENT
6207     x = 8;                              /* Get current date */
6208     s = alrm_date;
6209     if (zzstring("\\v(ndate)",&s,&x) < 0) {
6210         printf("Internal date error, sorry.\n");
6211         alrm_date[0] = SP;
6212         return(-9);
6213     }
6214     x = 5;                              /* Get current time */
6215     s = alrm_time;
6216     if (zzstring("\\v(ntime)",&s,&x) < 0) {
6217         printf("Internal time error, sorry.\n");
6218         alrm_time[0] = SP;
6219         return(-9);
6220     }
6221     sprintf(buf,"%05ld",atol(alrm_time)); /* SAFE (20) */
6222     ckstrncpy(alrm_time,buf,8);
6223     debug(F110,"SET ALARM date (1)",alrm_date,0);
6224     debug(F110,"SET ALARM time (1)",alrm_time,0);
6225
6226     if ((zz = atol(alrm_time) + xx) < 0L) {
6227         printf("Internal time conversion error, sorry.\n");
6228         return(-9);
6229     }
6230     if (zz >= 86400L) {                 /* Alarm crosses midnight */
6231         char d[10];                     /* Local date buffer */
6232         int lastday;                    /* Last day of this month */
6233
6234         ckstrncpy(d,alrm_date,8);       /* We'll have to change the date */
6235
6236         x = (zz / 86400L);              /* How many days after today */
6237
6238         dd = atoi((char *)(d+6));       /* Parse yyyymmdd */
6239         d[6] = NUL;                     /* into yyyy, mm, dd ... */
6240         mm = atoi((char *)(d+4));
6241         d[4] = NUL;
6242         yyyy = atoi((char *)d);
6243
6244         /* How many days in this month */
6245
6246         lastday = mdays[mm];
6247         if (mm == 2 && yyyy % 4 == 0)   /* Works thru 2099 AD... */
6248           lastday++;
6249
6250         if (dd + x > lastday) {         /* Dumb loop */
6251             int y;
6252
6253             x -= (mdays[mm] - dd);      /* Deduct rest of this month's days */
6254
6255             /* There's a more elegant way to do this... */
6256
6257             while (1) {
6258                 mm++;                   /* Next month */
6259                 if (mm > 12) {          /* Wrap around */
6260                     mm = 1;             /* Jan, next year */
6261                     yyyy++;
6262                 }
6263                 y = mdays[mm];          /* Days in new month */
6264                 if (mm == 2 && yyyy % 4 == 0) /* Feb in leap year */
6265                   y++;                  /* Works until 2100 AD */
6266                 if (x - y < 1)
6267                   break;
6268                 x -= y;
6269             }
6270             dd = x;                     /* Day of alarm month */
6271         } else dd += x;
6272
6273         sprintf(alrm_date,"%04d%02d%02d",yyyy,mm,dd); /* SAFE (24) */
6274         zz = zz % 86400L;
6275     }
6276     sprintf(alrm_time,"%ld",zz);        /* SAFE (24) */
6277     debug(F110,"SET ALARM date (2)",alrm_date,0);
6278     debug(F110,"SET ALARM time (2)",alrm_time,0);
6279     ck_alarm = xx;
6280 #else
6281     /* Jul 1998 */
6282     ckstrncpy(xbuf,ckcvtdate("",1),20); /* Get current date and time */
6283     p = xbuf;
6284     ckstrncpy(alrm_date,xbuf,10);
6285     alrm_date[8] = NUL;
6286     sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
6287     debug(F110,"SET ALARM date (1)",alrm_date,0);
6288     debug(F101,"SET ALARM time (1)","",sec);
6289     if ((sec += xx) < 0L) {
6290         printf("Internal time conversion error, sorry.\n");
6291         return(-9);
6292     }
6293     if (sec >= 86400L) {                /* Alarm crosses midnight */
6294         long days;
6295         days = sec / 86400L;
6296         jd = mjd(p) + days;             /* Get modified Julian date */
6297         ckstrncpy(alrm_date,mjd2date(jd),10);
6298         sec %= 86400L;
6299     }
6300     sprintf(alrm_time,"%05ld",sec);     /* SAFE (24) */
6301     debug(F110,"SET ALARM date (2)",alrm_date,0);
6302     debug(F110,"SET ALARM time (2)",alrm_time,0);
6303     ck_alarm = 1;                       /* Alarm is set */
6304
6305 #endif /* COMMENT */
6306     return(success = 1);
6307 }
6308 #endif /* NOSPL */
6309
6310 #ifndef NOSETKEY
6311 int
6312 dosetkey() {                            /* SET KEY */
6313     int x, y;
6314     int flag = 0;
6315     int kc;                             /* Key code */
6316     char *s;                            /* Key binding */
6317 #ifndef NOKVERBS
6318     char *p;                            /* Worker */
6319 #endif /* NOKVERBS */
6320 #ifdef OS2
6321     extern int os2gks;
6322     extern int mskkeys;
6323     extern int initvik;
6324 #endif /* OS2 */
6325
6326     x_ifnum = 1;
6327     y = cmnum("numeric key code, or the word CLEAR,","",10,&kc,xxstring);
6328     x_ifnum = 0;
6329     if (y < 0) {
6330         debug(F111,"SET KEY",atmbuf,y);
6331         if (y == -2) {                  /* Not a valid number */
6332             if ((y = strlen(atmbuf)) < 0) /* Check for SET KEY CLEAR */
6333               return(-2);
6334             if (ckstrcmp(atmbuf,"clear",y,0))
6335               return(-2);
6336             if ((x = cmcfm()) < 0)
6337               return(x);
6338             for (y = 0; y < KMSIZE; y++) {
6339                 keymap[y] = (KEY) y;
6340                 macrotab[y] = NULL;
6341             }
6342 #ifdef OS2
6343             keymapinit();               /* Special OS/2 initializations */
6344             initvik = 1;                /* Update the VIK table */
6345 #endif /* OS2 */
6346             return(1);
6347         } else if (y == -3) {           /* SET KEY <Return> */
6348             printf(" Press key to be defined: "); /* Prompt for a keystroke */
6349 #ifdef UNIX
6350 #ifdef NOSETBUF
6351             fflush(stdout);
6352 #endif /* NOSETBUF */
6353 #endif /* UNIX */
6354             conbin((char)escape);       /* Put terminal in binary mode */
6355 #ifdef OS2
6356             os2gks = 0;                 /* Turn off Kverb preprocessing */
6357 #endif /* OS2 */
6358             kc = congks(0);             /* Get character or scan code */
6359 #ifdef OS2
6360             os2gks = 1;                 /* Turn on Kverb preprocessing */
6361 #endif /* OS2 */
6362             concb((char)escape);        /* Restore terminal to cbreak mode */
6363             if (kc < 0) {               /* Check for error */
6364                 printf("?Error reading key\n");
6365                 return(0);
6366             }
6367 #ifdef OS2
6368             shokeycode(kc,-1);          /* Show current definition */
6369 #else
6370             shokeycode(kc);             /* Show current definition */
6371 #endif /* OS2 */
6372             flag = 1;                   /* Remember it's a multiline command */
6373         } else                          /* Error */
6374           return(y);
6375     }
6376
6377     /* Normal SET KEY <scancode> <value> command... */
6378
6379 #ifdef OS2
6380     if (mskkeys)
6381       kc = msktock(kc);
6382 #endif /* OS2 */
6383
6384     if (kc < 0 || kc >= KMSIZE) {
6385         printf("?key code must be between 0 and %d\n", KMSIZE - 1);
6386         return(-9);
6387     }
6388     if (kc == escape) {
6389         printf("Sorry, %d is the CONNECT-mode escape character\n",kc);
6390         return(-9);
6391     }
6392 #ifdef OS2
6393     wideresult = -1;
6394 #endif /* OS2 */
6395     if (flag) {
6396         cmsavp(psave,PROMPTL);
6397         cmsetp(" Enter new definition: ");
6398         cmini(ckxech);
6399         cmflgs = 0;
6400         prompt(NULL);
6401     }
6402   def_again:
6403     if (flag)
6404       cmres();
6405     if ((y = cmtxt("key definition,\n\
6406 or Ctrl-C to cancel this command,\n\
6407 or Enter to restore default definition",
6408                    "",&s,NULL)) < 0) {
6409         if (flag)                       /* Handle parse errors */
6410           goto def_again;
6411         else
6412           return(y);
6413     }
6414     s = brstrip(s);
6415 #ifndef NOKVERBS
6416     p = s;                              /* Save this place */
6417 #endif /* NOKVERBS */
6418 /*
6419   If the definition included any \Kverbs, quote the backslash so the \Kverb
6420   will still be in the definition when the key is pressed.  We don't do this
6421   in zzstring(), because \Kverbs are valid only in this context and nowhere
6422   else.
6423
6424   We use this code active for all versions that support SET KEY, even if they
6425   don't support \Kverbs, because otherwise \K would behave differently for
6426   different versions.
6427 */
6428     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
6429         if ((x > 0) &&
6430             (s[x] == 'K' || s[x] == 'k')
6431             ) {                         /* Have K */
6432
6433             if ((x == 1 && s[x-1] == CMDQ) ||
6434                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
6435                 line[y++] = CMDQ;       /* Make it \\K */
6436             }
6437             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
6438                 line[y-1] = CMDQ;       /* Have \{K */
6439                 line[y++] = '{';        /* Make it \\{K */
6440             }
6441         }
6442         line[y] = s[x];
6443     }
6444     line[y++] = NUL;                    /* Terminate */
6445     s = line + y + 1;                   /* Point to after it */
6446     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
6447     if ((x < (LINBUFSIZ / 2)) ||
6448         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
6449         printf("?Key definition too long\n");
6450         if (flag) cmsetp(psave);
6451         return(-9);
6452     }
6453     s = line + y + 1;                   /* Point to result. */
6454
6455 #ifndef NOKVERBS
6456 /*
6457   Special case: see if the definition starts with a \Kverb.
6458   If it does, point to it with p, otherwise set p to NULL.
6459 */
6460     p = s;
6461     if (*p++ == CMDQ) {
6462         if (*p == '{') p++;
6463         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
6464     }
6465 #endif /* NOKVERBS */
6466
6467     if (macrotab[kc]) {                 /* Possibly free old macro from key. */
6468         free((char *)macrotab[kc]);
6469         macrotab[kc] = NULL;
6470     }
6471     switch (strlen(s)) {                /* Action depends on length */
6472       case 0:                           /* Reset to default binding */
6473         keymap[kc] = (KEY) kc;
6474         break;
6475       case 1:                           /* Single character */
6476         keymap[kc] = (CHAR) *s;
6477         break;
6478       default:                          /* Character string */
6479 #ifndef NOKVERBS
6480         if (p) {
6481             y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
6482             debug(F101,"set key kverb lookup",0,y); /* exact match required */
6483             if (y > -1) {
6484                 keymap[kc] = F_KVERB | y;
6485                 break;
6486             }
6487         }
6488 #endif /* NOKVERBS */
6489         keymap[kc] = (KEY) kc;
6490         macrotab[kc] = (MACRO) malloc(strlen(s)+1);
6491         if (macrotab[kc])
6492           strcpy((char *) macrotab[kc], s); /* safe */
6493         break;
6494     }
6495     if (flag) cmsetp(psave);
6496 #ifdef OS2
6497     initvik = 1;                        /* Update VIK table */
6498 #endif /* OS2 */
6499     return(1);
6500 }
6501 #endif /* NOSETKEY */
6502
6503 #ifdef STOPBITS
6504 struct keytab stoptbl[] = {
6505     { "1", 1, 0 },
6506     { "2", 2, 0 }
6507 };
6508 #endif /* STOPBITS */
6509
6510 static struct keytab sertbl[] = {
6511     { "7E1", 0, 0 },
6512     { "7E2", 1, 0 },
6513     { "7M1", 2, 0 },
6514     { "7M2", 3, 0 },
6515     { "7O1", 4, 0 },
6516     { "7O2", 5, 0 },
6517     { "7S1", 6, 0 },
6518     { "7S2", 7, 0 },
6519 #ifdef HWPARITY
6520     { "8E1", 9, 0 },
6521     { "8E2", 10, 0 },
6522 #endif /* HWPARITY */
6523     { "8N1", 8, 0 },
6524 #ifdef HWPARITY
6525     { "8N2", 11, 0 },
6526     { "8O1", 12, 0 },
6527     { "8O2", 13, 0 },
6528 #endif /* HWPARITY */
6529     { "", 0, 0 }
6530 };
6531 static int nsertbl = (sizeof(sertbl) / sizeof(struct keytab)) - 1;
6532
6533 static char * sernam[] = {              /* Keep this in sync with sertbl[] */
6534   "7E1", "7E2", "7M1", "7M2", "7O1", "7O2", "7S1", "7S2",
6535   "8N1", "8E1", "8E2", "8N2", "8O1", "8O2"
6536 };
6537
6538 static struct keytab optstab[] = {      /* SET OPTIONS table */
6539 #ifndef NOFRILLS
6540     { "delete",    XXDEL,   0},            /* DELETE */
6541 #endif /* NOFRILLS */
6542     { "directory", XXDIR,   0},         /* DIRECTORY */
6543 #ifdef CKPURGE
6544     { "purge",     XXPURGE, 0},         /* PURGE */
6545 #endif /* CKPURGE */
6546     { "type",      XXTYP,   0},         /* TYPE */
6547     { "", 0, 0}
6548 };
6549 static int noptstab =  (sizeof(optstab) / sizeof(struct keytab)) - 1;
6550
6551 #ifndef NOXFER
6552 /*
6553   PROTOCOL SELECTION.  Kermit is always available.  If CK_XYZ is defined at
6554   compile time, then the others become selections also.  In OS/2 and
6555   Windows, they are integrated and the various SET commands (e.g. "set file
6556   type") affect them as they would Kermit.  In other OS's (UNIX, VMS, etc),
6557   they are external protocols which are run via Kermit's REDIRECT mechanism.
6558   All we do is collect and verify the filenames and pass them along to the
6559   external protocol.
6560 */
6561 struct keytab protos[] = {
6562 #ifdef CK_XYZ
6563     "g",          PROTO_G,  CM_INV,
6564 #endif /* CK_XYZ */
6565     "kermit",     PROTO_K,  0,
6566 #ifdef CK_XYZ
6567     "other",      PROTO_O,  0,
6568     "x",          PROTO_X,  CM_INV|CM_ABR,
6569     "xmodem",     PROTO_X,  0,
6570     "xmodem-crc", PROTO_XC, 0,
6571     "y",          PROTO_Y,  CM_INV|CM_ABR,
6572     "ymodem",     PROTO_Y,  0,
6573     "ymodem-g",   PROTO_G,  0,
6574     "zmodem",     PROTO_Z,  0
6575 #endif /* CK_XYZ */
6576 };
6577 int nprotos =  (sizeof(protos) / sizeof(struct keytab));
6578
6579 #define XPCMDLEN 71
6580
6581 _PROTOTYP(static int protofield, (char *, char *, char *));
6582 _PROTOTYP(static int setproto, (void));
6583
6584 static int
6585 protofield(current, help, px) char * current, * help, * px; {
6586
6587     char *s, tmpbuf[XPCMDLEN+1];
6588     int x;
6589
6590     if (current)                        /* Put braces around default */
6591       ckmakmsg(tmpbuf,TMPBUFSIZ,"{",current,"}",NULL);
6592     else
6593       tmpbuf[0] = NUL;
6594
6595     if ((x = cmfld(help, (char *)tmpbuf, &s, xxstring)) < 0)
6596       return(x);
6597     if ((int)strlen(s) > XPCMDLEN) {
6598         printf("?Sorry - maximum length is %d\n", XPCMDLEN);
6599         return(-9);
6600     } else if (*s) {
6601         strcpy(px,s);                   /* safe */
6602     } else {
6603         px = NULL;
6604     }
6605     return(x);
6606 }
6607
6608 static int
6609 setproto() {                            /* Select a file transfer protocol */
6610     /* char * s = NULL; */
6611     int x = 0, y;
6612     char s1[XPCMDLEN+1], s2[XPCMDLEN+1], s3[XPCMDLEN+1];
6613     char s4[XPCMDLEN+1], s5[XPCMDLEN+1], s6[XPCMDLEN+1], s7[XPCMDLEN+1];
6614     char * p1 = s1, * p2 = s2, *p3 = s3;
6615     char * p4 = s4, * p5 = s5, *p6 = s6, *p7 = s7;
6616
6617 #ifdef XYZ_INTERNAL
6618     extern int p_avail;
6619 #else
6620 #ifndef CK_REDIR
6621     x = 1;
6622 #endif /* CK_REDIR */
6623 #endif /* XYZ_INTERNAL */
6624     s1[0] = NUL;
6625     s2[0] = NUL;
6626     s3[0] = NUL;
6627     s4[0] = NUL;
6628     s5[0] = NUL;
6629     s6[0] = NUL;
6630
6631     if ((y = cmkey(protos,nprotos,"","kermit",xxstring)) < 0)
6632       return(y);
6633
6634     if (x && y != PROTO_K) {
6635         printf(
6636            "?Sorry, REDIRECT capability required for external protocols.\n");
6637         return(-9);
6638     }
6639     if ((x = protofield(ptab[y].h_b_init,
6640      "Optional command to send to host prior to uploading in binary mode",
6641                p1)) < 0) {
6642         if (x == -3) {
6643             protocol = y;               /* Set protocol but don't change */
6644             return(1);                  /* anything else */
6645         } else
6646           return(x);
6647     }
6648     if ((x = protofield(ptab[y].h_t_init,
6649      "Optional command to send to host prior to uploading in text mode",
6650                p2)) < 0) {
6651         if (x == -3)
6652           goto protoexit;
6653         else
6654           return(x);
6655     }
6656
6657     if (y == PROTO_K) {
6658         if ((x = protofield(ptab[y].h_x_init,
6659                     "Optional command to send to host to start Kermit server",
6660                             p3)) < 0) {
6661             if (x == -3)
6662               goto protoexit;
6663             else
6664               return(x);
6665         }
6666     }
6667
6668
6669 #ifndef XYZ_INTERNAL                    /* If XYZMODEM are external... */
6670
6671     if (y != PROTO_K) {
6672         if ((x = protofield(ptab[y].p_b_scmd,
6673                  "External command to SEND in BINARY mode with this protocol",
6674                             p4)) < 0) {
6675             if (x == -3)
6676               goto protoexit;
6677             else
6678               return(x);
6679         }
6680         if ((x = protofield(ptab[y].p_t_scmd,
6681                  "External command to SEND in TEXT mode with this protocol",
6682                             p5)) < 0) {
6683             if (x == -3)
6684               goto protoexit;
6685             else
6686               return(x);
6687         }
6688         if ((x = protofield(ptab[y].p_b_rcmd,
6689                "External command to RECEIVE in BINARY mode with this protocol",
6690                             p6)) < 0) {
6691             if (x == -3)
6692               goto protoexit;
6693             else
6694               return(x);
6695         }
6696         if ((x = protofield(ptab[y].p_t_rcmd,
6697                  "External command to RECEIVE in TEXT mode with this protocol",
6698                             p7)) < 0) {
6699             if (x == -3)
6700               goto protoexit;
6701             else
6702               return(x);
6703         }
6704     }
6705 #endif /* XYZ_INTERNAL */
6706
6707     if ((x = cmcfm()) < 0)              /* Confirm the command */
6708       return(x);
6709
6710 protoexit:                              /* Common exit from this routine */
6711
6712 #ifdef XYZ_INTERNAL
6713     if (!p_avail) {
6714         bleep(BP_WARN);
6715         printf("\n?X,Y, and Zmodem are unavailable\n");
6716         return(success = 0);
6717     }
6718 #endif /* XYZ_INTERNAL */
6719
6720     p1 = brstrip(p1);
6721     p2 = brstrip(p2);
6722     p3 = brstrip(p3);
6723     p4 = brstrip(p4);
6724     p5 = brstrip(p5);
6725     p6 = brstrip(p6);
6726     p7 = brstrip(p7);
6727     initproto(y,p1,p2,p3,p4,p5,p6,p7);
6728     return(success = 1);
6729 }
6730
6731 int
6732 setdest() {
6733     int x, y;
6734     if ((y = cmkey(desttab,ndests,"","disk",xxstring)) < 0) return(y);
6735     if ((x = cmcfm()) < 0) return(x);
6736     dest = y;
6737     return(1);
6738 }
6739 #endif /* NOXFER */
6740
6741 #ifdef DECNET
6742 struct keytab dnettab[] = {
6743 #ifndef OS2ONLY
6744     "cterm", NP_CTERM, 0,
6745 #endif /* OS2ONLY */
6746     "lat",   NP_LAT,   0
6747 };
6748 int ndnet =  (sizeof(dnettab) / sizeof(struct keytab));
6749 #endif /* DECNET */
6750
6751 /*  S E T P R I N T E R  --  SET PRINTER command  */
6752
6753 #ifdef PRINTSWI
6754 static struct keytab prntab[] = {       /* SET PRINTER switches */
6755     "/bidirectional",    PRN_BID, 0,
6756 #ifdef OS2
6757     "/character-set",    PRN_CS,  CM_ARG,
6758 #endif /* OS2 */
6759     "/command",          PRN_PIP, CM_ARG,
6760     "/dos-device",       PRN_DOS, CM_ARG,
6761     "/end-of-job-string",PRN_TRM, CM_ARG,
6762     "/file",             PRN_FIL, CM_ARG,
6763 #ifdef BPRINT
6764     "/flow-control",     PRN_FLO, CM_ARG,
6765 #endif /* BPRINT */
6766     "/job-header-file",  PRN_SEP, CM_ARG,
6767 #ifdef OS2
6768     "/length",           PRN_LEN, CM_ARG,
6769 #endif /* OS2 */
6770     "/none",             PRN_NON, 0,
6771 #ifdef OS2
6772     "/nopostscript",     PRN_RAW, 0,
6773     "/nops",             PRN_RAW, CM_INV,
6774 #endif /* OS2 */
6775     "/output-only",      PRN_OUT, 0,
6776 #ifdef BPRINT
6777     "/parity",           PRN_PAR, CM_ARG,
6778 #endif /* BPRINT */
6779     "/pipe",             PRN_PIP, CM_ARG|CM_INV,
6780 #ifdef OS2
6781     "/postscript",       PRN_PS,  0,
6782     "/ps",               PRN_PS,  CM_INV,
6783 #endif /* OS2 */
6784     "/separator",        PRN_SEP, CM_ARG|CM_INV,
6785 #ifdef BPRINT
6786     "/speed",            PRN_SPD, CM_ARG,
6787 #endif /* BPRINT */
6788     "/timeout",          PRN_TMO, CM_ARG,
6789     "/terminator",       PRN_TRM, CM_ARG|CM_INV,
6790 #ifdef OS2
6791 #ifdef NT
6792     "/w",                PRN_WIN, CM_ARG|CM_ABR|CM_INV,
6793     "/wi",               PRN_WIN, CM_ARG|CM_ABR|CM_INV,
6794 #endif /* NT */
6795     "/width",            PRN_WID, CM_ARG,
6796 #endif /* OS2 */
6797 #ifdef NT
6798     "/windows-queue",    PRN_WIN, CM_ARG,
6799 #endif /* NT */
6800     "",                 0,      0
6801 };
6802 int nprnswi =  (sizeof(prntab) / sizeof(struct keytab)) - 1;
6803 #endif /* PRINTSWI */
6804
6805 static int
6806 setprinter(xx) int xx; {
6807     int x, y;
6808     char * s;
6809     char * defname = NULL;
6810 #ifdef OS2
6811     extern int prncs;
6812 #endif /* OS2 */
6813
6814 #ifdef BPRINT
6815     char portbuf[64];
6816     long portspeed = 0L;
6817     int portparity = 0;
6818     int portflow = 0;
6819 #endif /* BPRINT */
6820
6821 #ifdef PRINTSWI
6822     int c, i, n, wild, confirmed = 0;   /* Workers */
6823     int getval = 0;                     /* Whether to get switch value */
6824     struct stringint {                  /* Temporary array for switch values */
6825         char * sval;
6826         int ival;
6827     } pv[PRN_MAX+1];
6828     struct FDB sw, of, cm;              /* FDBs for each parse function */
6829     int haveque = 0;
6830     int typeset = 0;
6831 #endif /* PRINTSWI */
6832
6833 #ifdef NT
6834     struct keytab * printtab = NULL, * _printtab = NULL;
6835     int nprint = 0, printdef=0;
6836 #endif /* NT */
6837
6838 #ifdef OS2
6839     defname = "PRN";                    /* default */
6840 #else
6841 #ifdef VMS
6842     defname = "LPT:";
6843 #else
6844 #ifdef UNIX
6845     defname = "|lpr";
6846 #endif /* UNIX */
6847 #endif /* VMS */
6848 #endif /* OS2 */
6849
6850 #ifdef PRINTSWI
6851 #ifdef NT
6852     haveque = Win32EnumPrt(&printtab,&_printtab,&nprint,&printdef);
6853     haveque = haveque && nprint;
6854 #endif /* NT */
6855
6856     for (i = 0; i <= PRN_MAX; i++) {    /* Initialize switch values */
6857         pv[i].sval = NULL;              /* to null pointers */
6858         pv[i].ival = -1;                /* and -1 int values */
6859     }
6860     if (xx == XYBDCP) {                 /* SET BPRINTER == /BIDIRECTIONAL */
6861         pv[PRN_BID].ival = 1;
6862         pv[PRN_OUT].ival = 0;
6863     }
6864
6865     /* Initialize defaults based upon current printer settings */
6866     if (printername) {
6867         defname = printername;
6868         switch (printertype) {
6869           case PRT_WIN: pv[PRN_WIN].ival = 1; break;
6870           case PRT_DOS: pv[PRN_DOS].ival = 1; break;
6871           case PRT_PIP: pv[PRN_PIP].ival = 1; break;
6872           case PRT_FIL: pv[PRN_FIL].ival = 1; break;
6873           case PRT_NON: pv[PRN_NON].ival = 1; break;
6874         }
6875     }
6876 #ifdef BPRINT
6877     /* only set the BIDI flag if we are bidi */
6878     if (printbidi)
6879         pv[PRN_BID].ival = 1;
6880
6881     /* serial port parameters may be set for non-bidi devices */
6882     pv[PRN_SPD].ival = pportspeed / 10L;
6883     pv[PRN_PAR].ival = pportparity;
6884     pv[PRN_FLO].ival = pportflow;
6885 #endif /* BPRINT */
6886     if (printtimo)
6887         pv[PRN_TMO].ival = printtimo;
6888     if (printterm) {
6889         pv[PRN_TRM].ival = 1;
6890         makestr(&pv[PRN_TRM].sval,printterm);
6891     }
6892     if (printsep) {
6893         pv[PRN_SEP].ival = 1;
6894         makestr(&pv[PRN_SEP].sval,printsep);
6895     }
6896     if (txt2ps) {
6897         pv[PRN_PS].ival = 1;
6898         pv[PRN_WID].ival = ps_width;
6899         pv[PRN_LEN].ival = ps_length;
6900     } else {
6901         pv[PRN_RAW].ival = 1;
6902     }
6903
6904     /* Set up chained parse functions... */
6905
6906     cmfdbi(&sw,                         /* First FDB - command switches */
6907            _CMKEY,                      /* fcode */
6908            "Switch",                    /* hlpmsg */
6909            "",                          /* default */
6910            "",                          /* addtl string data */
6911            nprnswi,                     /* addtl numeric data 1: tbl size */
6912            4,                           /* addtl numeric data 2: 4 = cmswi */
6913            xxstring,                    /* Processing function */
6914            prntab,                      /* Keyword table */
6915            &cm                          /* Pointer to next FDB */
6916            );
6917     cmfdbi(&cm,                         /* Second fdb for confirmation */
6918            _CMCFM,                      /* fcode */
6919            "",                          /* hlpmsg */
6920            "",                          /* default */
6921            "",                          /* addtl string data */
6922            0,                           /* addtl numeric data 1 */
6923            0,                           /* addtl numeric data 2 */
6924            NULL,
6925            NULL,
6926            &of
6927            );
6928     cmfdbi(&of,                         /* Third FDB for printer name */
6929            _CMOFI,                      /* fcode */
6930            "Printer or file name",      /* hlpmsg */
6931            defname,                     /* default */
6932            "",                          /* addtl string data */
6933            0,                           /* addtl numeric data 1: tbl size */
6934            0,                           /* addtl numeric data 2: 4 = cmswi */
6935            xxstring,                    /* Processing function */
6936            NULL,                        /* Nothing */
6937            NULL
6938            );
6939
6940     while (1) {                         /* Parse 0 or more switches */
6941         x = cmfdb(&sw);                 /* Parse switch or other thing */
6942         debug(F101,"setprinter cmfdb","",x);
6943         if (x < 0)                      /* Error */
6944           goto xsetprn;                 /* or reparse needed */
6945         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
6946           break;
6947         if (cmresult.fdbaddr != &sw)    /* Advanced usage :-) */
6948           break;
6949         c = cmgbrk();                   /* Get break character */
6950         getval = (c == ':' || c == '='); /* to see how they ended the switch */
6951         n = cmresult.nresult;           /* Numeric result = switch value */
6952         debug(F101,"setprinter switch","",n);
6953
6954         switch (n) {                    /* Process the switch */
6955           case PRN_PS:                  /* Text to Postscript */
6956             pv[PRN_PS].ival = 1;
6957             pv[PRN_BID].ival = 0;
6958             pv[PRN_OUT].ival = 1;
6959             pv[PRN_RAW].ival = 0;
6960             break;
6961
6962           case PRN_RAW:                 /* Non-Postscript */
6963             pv[PRN_PS].ival = 0;
6964             pv[PRN_RAW].ival = 1;
6965             break;
6966
6967           case PRN_BID:                 /* Bidirectional */
6968             pv[PRN_BID].ival = 1;
6969             pv[PRN_OUT].ival = 0;
6970             pv[PRN_PS].ival = 0;
6971             pv[PRN_RAW].ival = 1;
6972             break;
6973
6974           case PRN_OUT:                 /* Output-only */
6975             pv[PRN_OUT].ival = 1;
6976             pv[PRN_BID].ival = 0;
6977             pv[PRN_PS].ival = 0;
6978             pv[PRN_RAW].ival = 1;
6979             break;
6980
6981           case PRN_NON:                 /* NONE */
6982             typeset++;
6983             pv[n].ival = 1;
6984             pv[PRN_SPD].ival = 0;
6985             pv[PRN_PAR].ival = 0;
6986             pv[PRN_FLO].ival = FLO_KEEP;
6987             break;
6988
6989 #ifdef UNIX
6990           case PRN_WIN:
6991 #endif /* UNIX */
6992           case PRN_DOS:                 /* DOS printer name */
6993           case PRN_FIL:                 /* Or filename */
6994           case PRN_PIP:
6995             typeset++;
6996             if (pv[n].sval) free(pv[n].sval);
6997             pv[n].sval = NULL;
6998             pv[PRN_NON].ival = 0;       /* Zero any previous selections */
6999             pv[PRN_WIN].ival = 0;
7000             pv[PRN_DOS].ival = 0;
7001             pv[PRN_FIL].ival = 0;
7002             pv[PRN_PIP].ival = 0;
7003             pv[n].ival = 1;             /* Flag this one */
7004             if (!getval) break;         /* No value wanted */
7005
7006             if (n == PRN_FIL) {         /* File, check accessibility */
7007                 int wild = 0;
7008                 if ((x = cmiofi("Filename","kermit.prn",&s,&wild,xxstring))< 0)
7009                   if (x == -9) {
7010                       if (zchko(s) < 0) {
7011                           printf("Can't create \"%s\"\n",s);
7012                           return(x);
7013                       }
7014                   } else goto xsetprn;
7015                 if (iswild(s)) {
7016                     printf("?A single file please\n");
7017                     return(-9);
7018                 }
7019                 pv[PRN_SPD].ival = 0;
7020                 pv[PRN_PAR].ival = 0;
7021                 pv[PRN_FLO].ival = FLO_KEEP;
7022             } else if ((x = cmfld(n == PRN_DOS ? /* Value wanted - parse it */
7023                            "DOS printer device name" : /* Help message */
7024                            (n == PRN_PIP ?
7025                            "Program name" :
7026                            "Filename"),
7027                            n == PRN_DOS ?
7028                            "PRN" :      /* Default */
7029                            "",
7030                            &s,
7031                            xxstring
7032                            )) < 0)
7033               goto xsetprn;
7034             s = brstrip(s);             /* Strip enclosing braces */
7035             while (*s == SP)            /* Strip leading blanks */
7036               s++;
7037             if (n == PRN_PIP) {         /* If /PIPE: */
7038                 if (*s == '|') {        /* strip any extraneous pipe sign */
7039                     s++;
7040                     while (*s == SP)
7041                       s++;
7042                 }
7043                 pv[PRN_SPD].ival = 0;
7044                 pv[PRN_PAR].ival = 0;
7045                 pv[PRN_FLO].ival = FLO_KEEP;
7046             }
7047             if ((y = strlen(s)) > 0)    /* Anything left? */
7048               if (pv[n].sval = (char *) malloc(y+1)) /* Yes, keep it */
7049                 strcpy(pv[n].sval,s);   /* safe */
7050             break;
7051 #ifdef NT
7052           case PRN_WIN:                 /* Windows queue name */
7053             typeset++;
7054             if (pv[n].sval) free(pv[n].sval);
7055             pv[n].sval = NULL;
7056             pv[PRN_NON].ival = 0;
7057             pv[PRN_DOS].ival = 0;
7058             pv[PRN_FIL].ival = 0;
7059             pv[n].ival = 1;
7060             pv[PRN_SPD].ival = 0;
7061             pv[PRN_PAR].ival = 0;
7062             pv[PRN_FLO].ival = FLO_KEEP;
7063
7064             if (!getval || !haveque)
7065               break;
7066             if ((x = cmkey(_printtab,nprint,"Print queue name",
7067                            _printtab[printdef].kwd,xxstring)) < 0) {
7068                 if (x != -2)
7069                   goto xsetprn;
7070
7071                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7072                 s = atmbuf;
7073                 if ((y = strlen(s)) > 0)
7074                   if (pv[n].sval = (char *)malloc(y+1))
7075                     strcpy(pv[n].sval,s); /* safe */
7076             } else {
7077                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7078                 for (i = 0; i < nprint; i++) {
7079                     if (x == printtab[i].kwval) {
7080                         s = printtab[i].kwd;
7081                         break;
7082                     }
7083                 }
7084                 if ((y = strlen(s)) > 0)
7085                   if (pv[n].sval = (char *)malloc(y+1))
7086                     strcpy(pv[n].sval,s); /* safe */
7087             }
7088             break;
7089 #endif /* NT */
7090
7091           case PRN_SEP:                 /* /JOB-HEADER (separator) */
7092             if (pv[n].sval) free(pv[n].sval);
7093             pv[n].sval = NULL;
7094             pv[n].ival = 1;
7095             if (!getval) break;
7096             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0)
7097               goto xsetprn;
7098             if (y) {
7099                 printf("?Wildcards not allowed\n");
7100                 x = -9;
7101                 goto xsetprn;
7102             }
7103             if ((y = strlen(s)) > 0)
7104               if (pv[n].sval = (char *) malloc(y+1))
7105                 strcpy(pv[n].sval,s);   /* safe */
7106             break;
7107
7108           case PRN_TMO:                 /* /TIMEOUT:number */
7109             pv[n].ival = 0;
7110             if (!getval) break;
7111             if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
7112               goto xsetprn;
7113             if (y > 999) {
7114                 printf("?Sorry - 999 is the maximum\n");
7115                 x = -9;
7116                 goto xsetprn;
7117             } else
7118               pv[n].ival = y;
7119             break;
7120
7121           case PRN_TRM:                 /* /END-OF-JOB:string */
7122             if (pv[n].sval) free(pv[n].sval);
7123             pv[n].sval = NULL;
7124             pv[n].ival = 1;
7125             if (!getval) break;
7126             if ((x = cmfld("String (enclose in braces if it contains spaces)",
7127                            "",&s,xxstring)) < 0)
7128               goto xsetprn;
7129             s = brstrip(s);
7130             if ((y = strlen(s)) > 0)
7131               if (pv[n].sval = (char *) malloc(y+1))
7132                 strcpy(pv[n].sval,s);   /* safe */
7133             break;
7134
7135 #ifdef BPRINT
7136           case PRN_FLO:
7137             if (!getval) break;
7138             if ((x = cmkey(flotab,nflo,
7139                               "Serial printer-port flow control",
7140                               "rts/cts",xxstring)) < 0)
7141               goto xsetprn;
7142             pv[n].ival = x;
7143             break;
7144
7145 #ifndef NOLOCAL
7146           case PRN_SPD:
7147             if (!getval) break;
7148
7149             /* TN_COMPORT here too? */
7150
7151             if ((x = cmkey(spdtab,      /* Speed (no default) */
7152                            nspd,
7153                            "Serial printer-port interface speed",
7154                            "9600",
7155                            xxstring)
7156                  ) < 0)
7157               goto xsetprn;
7158             pv[n].ival = x;
7159             break;
7160 #endif /* NOLOCAL */
7161
7162           case PRN_PAR:
7163             pv[n].ival = 0;
7164             if (!getval) break;
7165             if ((x = cmkey(partbl,npar,"Serial printer-port parity",
7166                            "none",xxstring)) < 0)
7167               goto xsetprn;
7168             pv[n].ival = x;
7169             break;
7170 #endif /* BPRINT */
7171
7172 #ifdef OS2
7173           case PRN_LEN:
7174             if (!getval) break;
7175             if ((x = cmnum("PS page length", "66",10,&y,xxstring)) < 0)
7176               goto xsetprn;
7177             pv[n].ival = y;
7178             break;
7179
7180           case PRN_WID:
7181             if (!getval) break;
7182             if ((x = cmnum("PS page width", "80",10,&y,xxstring)) < 0)
7183               goto xsetprn;
7184             pv[n].ival = y;
7185             break;
7186
7187           case PRN_CS:
7188               pv[n].ival = 0;
7189               if (!getval) break;
7190               if ((y = cmkey(
7191 #ifdef CKOUNI
7192                        txrtab,ntxrtab,
7193 #else /* CKOUNI */
7194                        ttcstab,ntermc,
7195 #endif /* CKOUNI */
7196                        "auto-print/printscreen character-set",
7197                        "cp437",xxstring)) < 0)
7198                   goto xsetprn;
7199               pv[n].ival = x;
7200               break;
7201 #endif /* OS2 */
7202
7203           default:
7204             printf("?Unexpected switch value - %d\n",cmresult.nresult);
7205             x = -9;
7206             goto xsetprn;
7207         }
7208     }
7209     line[0] = NUL;                      /* Initialize printer name value */
7210     switch (cmresult.fcode) {           /* How did we get here? */
7211       case _CMOFI:                      /* They typed a filename */
7212         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
7213         wild = cmresult.nresult;        /* Wild flag */
7214         if (!typeset) {                 /* A printer name without a type */
7215             pv[PRN_NON].ival = 0;       /* is supposed to be treated as  */
7216             pv[PRN_WIN].ival = 0;       /* a DOS or Pipe printer.  We    */
7217             pv[PRN_FIL].ival = 0;       /* clear all the flags and let   */
7218             pv[PRN_PIP].ival = 0;       /* the code below dope out the   */
7219             pv[PRN_DOS].ival = 0;       /* type.                         */
7220         }
7221 #ifdef NT
7222         else if (pv[PRN_WIN].ival && lookup(_printtab,line,nprint,&y)) {
7223             /* invalid Window Queue name */
7224             printf("?invalid Windows Printer Queue name: \"%s\"\r\n",line);
7225             x = -9;
7226             goto xsetprn;
7227         }
7228 #endif /* NT */
7229         if ((x = cmcfm()) < 0)          /* Confirm the command */
7230           goto xsetprn;
7231         break;
7232       case _CMCFM:                      /* They entered the command */
7233         if (pv[PRN_DOS].ival > 0)
7234           ckstrncpy(line,pv[PRN_DOS].sval ? pv[PRN_DOS].sval : "",LINBUFSIZ);
7235         else if (pv[PRN_WIN].ival > 0)
7236           ckstrncpy(line,pv[PRN_WIN].sval ? pv[PRN_WIN].sval : "",LINBUFSIZ);
7237         else if (pv[PRN_FIL].ival > 0)
7238           ckstrncpy(line,pv[PRN_FIL].sval ? pv[PRN_FIL].sval : "",LINBUFSIZ);
7239         else if (pv[PRN_PIP].ival > 0)
7240           ckstrncpy(line,pv[PRN_PIP].sval ? pv[PRN_PIP].sval : "",LINBUFSIZ);
7241         break;
7242       default:                          /* By mistake */
7243         printf("?Unexpected function code: %d\n",cmresult.fcode);
7244         x = -9;
7245         goto xsetprn;
7246     }
7247
7248 #else  /* No PRINTSWI */
7249
7250     if ((x = cmofi("Printer or file name",defname,&s,xxstring)) < 0)
7251       return(x);
7252     if (x > 1) {
7253         printf("?Directory names not allowed\n");
7254         return(-9);
7255     }
7256     while (*s == SP || *s == HT) s++;   /* Trim leading whitespace */
7257     ckstrncpy(line,s,LINBUFSIZ);        /* Make a temporary safe copy */
7258     if ((x = cmcfm()) < 0) return(x);   /* Confirm the command */
7259 #endif /* PRINTSWI */
7260
7261 #ifdef IKSD
7262     if (inserver && (isguest
7263 #ifndef NOSERVER
7264                      || !ENABLED(en_pri)
7265 #endif /* NOSERVER */
7266                      )) {
7267         printf("Sorry, printing disabled\r\n");
7268         return(success = 0);
7269     }
7270 #endif /* ISKD */
7271
7272 #ifdef PRINTSWI
7273 #ifdef BPRINT
7274     if (printbidi) {                    /* If bidi printing active */
7275 #ifndef UNIX
7276         bprtstop();                     /* Stop it before proceeding */
7277 #endif /* UNIX */
7278         printbidi = 0;
7279     }
7280     if (pv[PRN_SPD].ival > 0) {
7281         portspeed = (long) pv[PRN_SPD].ival * 10L;
7282         if (portspeed == 70L) portspeed = 75L;
7283     }
7284     if (pv[PRN_PAR].ival > 0)
7285         portparity = pv[PRN_PAR].ival;
7286     if (pv[PRN_FLO].ival > 0)
7287         portflow = pv[PRN_FLO].ival;
7288 #endif /* BPRINT */
7289 #endif /* PRINTSWI */
7290
7291     s = line;                           /* Printer name, if given */
7292
7293 #ifdef OS2ORUNIX
7294 #ifdef PRINTSWI
7295     if (pv[PRN_PIP].ival > 0) {         /* /PIPE was given? */
7296         printpipe = 1;
7297         noprinter = 0;
7298         if (*s ==  '|') {               /* It might still have a pipe sign */
7299             s++;                        /* if name give later */
7300             while (*s == SP)            /* so remove it and spaces */
7301               s++;
7302         }
7303     } else
7304 #endif /* PRINTSWI */
7305       if (*s == '|') {                  /* Or pipe implied by name? */
7306           s++;                          /* Point past pipe sign */
7307           while (*s == SP)              /* Gobble whitespace */
7308             s++;
7309           if (*s) {
7310               printpipe = 1;
7311               noprinter = 0;
7312           }
7313       } else {
7314           printpipe = 0;
7315       }
7316
7317 #ifdef PRINTSWI
7318 #ifdef BPRINT
7319     if (printpipe && pv[PRN_BID].ival > 0) {
7320         printf("?Sorry, pipes not allowed for bidirectional printer\n");
7321         return(-9);
7322     }
7323 #endif /* BPRINT */
7324 #endif /* PRINTSWI */
7325 #endif /* OS2ORUNIX */
7326
7327 #ifdef OS2
7328     if ( pv[PRN_CS].ival > 0 ) 
7329         prncs = pv[PRN_CS].ival;
7330
7331     if ( pv[PRN_PS].ival > 0 ) {
7332         txt2ps = 1;
7333         ps_width = pv[PRN_WID].ival <= 0 ? 80 : pv[PRN_WID].ival;
7334         ps_length = pv[PRN_LEN].ival <= 0 ? 66 : pv[PRN_LEN].ival;
7335     }
7336 #endif /* OS2 */
7337
7338     y = strlen(s);                      /* Length of name of new print file */
7339     if (y > 0
7340 #ifdef OS2
7341         && ((y != 3) || (ckstrcmp(s,"PRN",3,0) != 0))
7342 #endif /* OS2 */
7343         ) {
7344         if (printername) {              /* Had a print file before? */
7345             free(printername);          /* Remove its name */
7346             printername = NULL;
7347         }
7348         printername = (char *) malloc(y + 1); /* Allocate space for it */
7349         if (!printername) {
7350             printf("?Memory allocation failure\n");
7351             return(-9);
7352         }
7353         strcpy(printername,s);          /* (safe) Copy new name to new space */
7354         debug(F110,"printername",printername,0);
7355     }
7356
7357 #ifdef PRINTSWI
7358     /* Set printer type from switches that were given explicitly */
7359
7360     if (pv[PRN_NON].ival > 0) {         /* No printer */
7361         printertype = PRT_NON;
7362         noprinter = 1;
7363         printpipe = 0;
7364     } else if (pv[PRN_FIL].ival > 0) {  /* File */
7365         printertype = PRT_FIL;
7366         noprinter = 0;
7367         printpipe = 0;
7368     } else if (pv[PRN_PIP].ival > 0) {  /* Pipe */
7369         printertype = PRT_PIP;
7370         noprinter = 0;
7371         printpipe = 1;
7372     } else if (pv[PRN_WIN].ival > 0) {  /* Windows print queue */
7373         printertype = PRT_WIN;
7374         noprinter = 0;
7375         printpipe = 0;
7376     } else if (pv[PRN_DOS].ival > 0) {  /* DOS device */
7377         printertype = PRT_DOS;
7378         noprinter = 0;
7379         printpipe = 0;
7380     } else if (line[0]) {               /* Name given without switches */
7381         noprinter = 0;
7382         printertype = printpipe ? PRT_PIP : PRT_DOS;
7383 #ifdef NT
7384         /* was the command SET PRINTER windows-queue ? */
7385         y = lookup(_printtab,line,nprint,&x);
7386         if (y >= 0) {
7387             printertype = PRT_WIN;
7388             if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7389             if (printername) {          /* Had a print file before? */
7390                 free(printername);      /* Remove its name */
7391                 printername = NULL;
7392             }
7393             pv[PRN_WIN].sval = NULL;
7394             pv[PRN_WIN].ival = 1;
7395             s = printtab[x].kwd;        /* Get full new name */
7396             if ((y = strlen(s)) > 0) {
7397                 makestr(&pv[PRN_WIN].sval,s);
7398                 makestr(&printername,s);
7399                 if (!printername) {
7400                     printf("?Memory allocation failure\n");
7401                     return(-9);
7402                 }
7403                 debug(F110,"printername",printername,0);
7404             }
7405         } else if ( y == -2 ) {
7406             /* Ambiguous Print Queue Name */
7407             printf("?Ambiguous printer name provided.\n");
7408             return(-9);
7409         }
7410 #endif /* NT */
7411     }
7412
7413 #ifdef BPRINT
7414     /* Port parameters may be set for non-bidi mode */
7415
7416     pportspeed = portspeed;             /* Set parameters */
7417     pportparity = portparity;
7418     pportflow = portflow;
7419
7420     if (pv[PRN_BID].ival > 0) {         /* Bidirectional */
7421 #ifdef UNIX
7422         printbidi = 1;                  /* (just to test parsing...) */
7423 #else
7424         printbidi = bprtstart();        /* Start bidirectional printer */
7425 #endif /* UNIX */
7426         return(success = printbidi);
7427     } else
7428       printbidi = 0;                    /* Not BPRINTER, unset flag */
7429 #endif /* BPRINT */
7430
7431     if (pv[PRN_TMO].ival > -1) {        /* Take care of timeout */
7432         printtimo = pv[PRN_TMO].ival;
7433     }
7434     if (pv[PRN_TRM].ival > 0) {         /* Termination string */
7435         if (printterm) {
7436             free(printterm);
7437             printterm = NULL;
7438         }
7439         if (pv[PRN_TRM].sval)
7440           makestr(&printterm,pv[PRN_TRM].sval);
7441     }
7442     if (pv[PRN_SEP].ival > 0) {         /* and separator file */
7443         if (printsep) {
7444             free(printsep);
7445             printsep = NULL;
7446         }
7447         if (pv[PRN_SEP].sval)
7448           makestr(&printsep,pv[PRN_SEP].sval);
7449     }
7450 #endif /* PRINTSWI */
7451
7452 #ifdef UNIXOROSK
7453     if (!printpipe
7454 #ifdef PRINTSWI
7455         && !noprinter
7456 #endif /* PRINTSWI */
7457         ) {                             /* File - check access */
7458         if (zchko(s) < 0) {
7459             printf("?Access denied - %s\n",s);
7460             x = -9;
7461             goto xsetprn;
7462         }
7463     }
7464 #endif /* UNIXOROSK */
7465
7466     x = 1;                              /* Return code */
7467
7468   xsetprn:                              /* Common exit */
7469 #ifdef PRINTSWI
7470     for (i = 0; i <= PRN_MAX; i++) {    /* Free malloc'd memory */
7471         if (pv[i].sval)
7472           free(pv[i].sval);
7473     }
7474 #endif /* PRINTSWI */
7475     success = (x > 0) ? 1 : 0;
7476     return(x);
7477 }
7478
7479 #ifdef ANYSSH
7480 /* The SET SSH command */
7481
7482 #define SSH_CMD  1                      /* SET SSH COMMAND */
7483
7484 #ifdef SSHBUILTIN                       /* Built-in SET SSH options */
7485 #define SSH_ADD  2                      /* Add */
7486 #define SSH_AFW  3                      /* Agent-forwarding */
7487 #define SSH_CHI  4                      /* Check Host IP */
7488 #define SSH_XFW  5                      /* X11-forwarding */
7489 #define SSH_DYF  6                      /* Dynamic forwarding */
7490 #define SSH_GWP  7                      /* Gatewa portgs */
7491 #define SSH_GSS  8                      /* GSSAPI */
7492 #define SSH_KBD  9                      /* KBD Interactive Devices */
7493 #define SSH_K4  10                      /* Kerberos 4 */
7494 #define SSH_K5  11                      /* Kerberos 5 */
7495 #define SSH_SHK 12                      /* Strict Host Key Check */
7496 #define SSH_V1  13                      /* SSH V1 */
7497 #define SSH_V2  14                      /* SSH V2 */
7498 #define SSH_PRP 15                      /* Privd port */
7499 #define SSH_CMP 16                      /* Compression */
7500 #define SSH_XAL 17                      /* X Auth Location */
7501 #define SSH_SHH 18                      /* Quiet */
7502 #define SSH_VER 19                      /* Version */
7503 #define SSH_VRB 20                      /* Verbosity level */
7504 #define SSH_IDF 21                      /* Identity File */
7505 #define SSH_CFG 22                      /* Use OpenSSH Config */
7506 #define SSH_HBT 23                      /* Heartbeat Interval */
7507 #endif /* SSHBUILTIN */
7508
7509 static struct keytab sshtab[] = {       /* SET SSH command table */
7510 #ifdef SSHBUILTIN
7511     { "agent-forwarding",        SSH_AFW,  0 },
7512     { "check-host-ip",           SSH_CHI,  0 },
7513     { "compression",             SSH_CMP,  0 },
7514     { "dynamic-forwarding",      SSH_DYF,  0 },
7515     { "gateway-ports",           SSH_GWP,  0 },
7516     { "gssapi",                  SSH_GSS,  0 },
7517     { "heartbeat-interval",      SSH_HBT,  0 },
7518     { "identity-file",           SSH_IDF,  0 },
7519 #ifdef COMMENT
7520     { "kbd-interactive-devices", SSH_KBD,  0 },
7521 #endif /* COMMENT */
7522     { "k4",                      SSH_K4, CM_INV },
7523     { "k5",                      SSH_K5, CM_INV },
7524     { "kerberos4",               SSH_K4,   0 },
7525     { "kerberos5",               SSH_K5,   0 },
7526     { "krb4",                    SSH_K4, CM_INV },
7527     { "krb5",                    SSH_K5, CM_INV },
7528     { "privileged-port",         SSH_PRP,  0 },
7529     { "quiet",                   SSH_SHH,  0 },
7530     { "strict-host-key-check",   SSH_SHK,  0 },
7531     { "use-openssh-config",      SSH_CFG,  0 },
7532     { "v1",                      SSH_V1,   0 },
7533     { "v2",                      SSH_V2,   0 },
7534     { "verbose",                 SSH_VRB,  0 },
7535     { "version",                 SSH_VER,  0 },
7536     { "x11-forwarding",          SSH_XFW,  0 },
7537     { "xauth-location",          SSH_XAL,  0 },
7538 #else
7539 #ifdef SSHCMD
7540     { "command",                 SSH_CMD,  0 },
7541 #endif /* SSHCMD */
7542 #endif /* SSHBUILTIN */
7543     { "", 0, 0 }
7544 };
7545 static int nsshtab = (sizeof(sshtab) / sizeof(struct keytab)) - 1;
7546
7547 #ifdef SSHBUILTIN
7548 static struct keytab sshver[] = {       /* SET SSH VERSION command table */
7549     { "1",          1,  0 },
7550     { "2",          2,  0 },
7551     { "automatic",  0,  0 }
7552 };
7553
7554 #define SSHA_CRS   1
7555 #define SSHA_DSA   2
7556 #define SSHA_GSS   3
7557 #define SSHA_HOS   4
7558 #define SSHA_KBD   5
7559 #define SSHA_K4    6
7560 #define SSHA_K5    7
7561 #define SSHA_PSW   8
7562 #define SSHA_PK    9
7563 #define SSHA_SKE  10
7564 #define SSHA_TIS  11
7565 #define SSHA_EXT  12
7566 #define SSHA_SRP  13
7567
7568 static struct keytab ssh2aut[] = {      /* SET SSH V2 AUTH command table */
7569     { "external-keyx",      SSHA_EXT, 0 },
7570     { "gssapi",             SSHA_GSS, 0 },
7571     { "hostbased",          SSHA_HOS, 0 },
7572     { "keyboard-interactive",  SSHA_KBD, 0 },
7573     { "password",           SSHA_PSW, 0 },
7574     { "publickey",          SSHA_PK,  0 },
7575     { "srp-gex-sha1",       SSHA_SRP, 0 },
7576     { "", 0, 0 }
7577 };
7578 static int nssh2aut = (sizeof(ssh2aut) / sizeof(struct keytab)) - 1;
7579
7580 #define SSHF_LCL   1
7581 #define SSHF_RMT   2
7582
7583 static struct keytab addfwd[] = {       /* SET SSH ADD command table */
7584     { "local-port-forward",  SSHF_LCL, 0 },
7585     { "remote-port-forward", SSHF_RMT, 0 },
7586     { "", 0, 0 }
7587 };
7588 static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
7589
7590 #define SSH1_CIF   1
7591 #define SSH1_GNH   2
7592 #define SSH1_UNH   3
7593 #define SSH1_K54   4
7594
7595 #define SSH2_CIF   1
7596 #define SSH2_GNH   2
7597 #define SSH2_UNH   3
7598 #define SSH2_ARK   4
7599 #define SSH2_HKA   5
7600 #define SSH2_MAC   6
7601 #define SSH2_AUT   7
7602
7603 static struct keytab sshv1tab[] = {     /* SET SSH V1 command table */
7604     { "cipher",                  SSH1_CIF, 0 },
7605     { "global-known-hosts-file", SSH1_GNH, 0 },
7606     { "k5-reuse-k4-messages",    SSH1_K54, CM_INV },
7607     { "user-known-hosts-file",   SSH1_UNH, 0 },
7608     { "", 0, 0 }
7609 };
7610 static int nsshv1tab = (sizeof(sshv1tab) / sizeof(struct keytab)) - 1;
7611
7612 static struct keytab sshv2tab[] = {     /* SET SSH V2 command table */
7613     { "authentication",          SSH2_AUT, 0 },
7614     { "auto-rekey",              SSH2_ARK, 0 },
7615     { "ciphers",                 SSH2_CIF, 0 },
7616     { "global-known-hosts-file", SSH2_GNH, 0 },
7617     { "hostkey-algorithms",      SSH2_HKA, 0 },
7618     { "macs",                    SSH2_MAC, 0 },
7619     { "user-known-hosts-file",   SSH2_UNH, 0 },
7620     { "", 0, 0 }
7621 };
7622 static int nsshv2tab = (sizeof(sshv2tab) / sizeof(struct keytab)) - 1;
7623
7624 #define SSHC_3DES 1                     /* 3DES */
7625 #define SSHC_3CBC 2                     /* 3DES-CBC */
7626 #define SSHC_A128 3                     /* AES128-CBC */
7627 #define SSHC_A192 4                     /* AES192-CBC */
7628 #define SSHC_A256 5                     /* AES256-CBC */
7629 #define SSHC_ARC4 6                     /* ARCFOUR */
7630 #define SSHC_FISH 7                     /* BLOWFISH */
7631 #define SSHC_BCBC 9                     /* BLOWFISH-CBC */
7632 #define SSHC_C128 8                     /* CAST128-CBC */
7633 #define SSHC_1DES 10                    /* DES */
7634
7635 static struct keytab ssh1ciphers[] = {
7636     { "3des",         SSHC_3DES, 0 },
7637     { "blowfish",     SSHC_FISH, 0 },
7638     { "des",          SSHC_1DES, 0 },
7639     { "", 0, 0 }
7640 };
7641 static int nssh1ciphers = (sizeof(ssh1ciphers) / sizeof(struct keytab)) - 1;
7642
7643 static struct keytab ssh2ciphers[] = {  /* SET SSH V2 CIPHERS command table */
7644     { "3des-cbc",        SSHC_3DES, 0 },
7645     { "aes128-cbc",      SSHC_A128, 0 },
7646     { "aes192-cbc",      SSHC_A192, 0 },
7647     { "aes256-cbc",      SSHC_A256, 0 },
7648     { "arcfour",         SSHC_ARC4, 0 },
7649     { "blowfish-cbc",    SSHC_FISH, 0 },
7650     { "cast128-cbc",     SSHC_C128, 0 },
7651     { "rijndael128-cbc", SSHC_A128, 0 },
7652     { "rijndael192-cbc", SSHC_A192, 0 },
7653     { "rijndael256-cbc", SSHC_A256, 0 },
7654     { "", 0, 0 }
7655 };
7656 static int nssh2ciphers = (sizeof(ssh2ciphers) / sizeof(struct keytab)) - 1;
7657
7658 #define SSHM_SHA        1               /* HMAC-SHA1 */
7659 #define SSHM_SHA_96     2               /* HMAC-SHA1-96 */
7660 #define SSHM_MD5        3               /* HMAC-MD5 */
7661 #define SSHM_MD5_96     4               /* HMAC-MD5-96 */
7662 #define SSHM_RIPE       5               /* HMAC-RIPEMD160 */
7663
7664 static struct keytab ssh2macs[] = {     /* SET SSH V2 MACS command table */
7665     { "hmac-md5",       SSHM_MD5,    0 },
7666     { "hmac-md5-96",    SSHM_MD5_96, 0 },
7667     { "hmac-ripemd160", SSHM_RIPE,   0 },
7668     { "hmac-sha1",      SSHM_SHA,    0 },
7669     { "hmac-sha1-96",   SSHM_SHA_96, 0 },
7670     { "", 0, 0 }
7671 };
7672 static int nssh2macs = (sizeof(ssh2macs) / sizeof(struct keytab)) - 1;
7673
7674 static struct keytab tgtpass[] = {
7675     { "tgt-passing", 1, 0, },
7676     { "", 0, 0 }
7677 };
7678 static int ntgtpass = (sizeof(tgtpass) / sizeof(struct keytab)) - 1;
7679
7680 static struct keytab gssapitab[] = {
7681     { "delegate-credentials", 1, 0, },
7682     { "key-exchange",         2, CM_INV, },
7683     { "", 0, 0 }
7684 };
7685 static int ngssapitab = (sizeof(gssapitab) / sizeof(struct keytab)) - 1;
7686
7687 #define HKA_RSA 1
7688 #define HKA_DSS 2
7689
7690 static struct keytab hkatab[] = {
7691     { "ssh-dss", HKA_DSS, 0, },
7692     { "ssh-rsa", HKA_RSA, 0, },
7693     { "", 0, 0 }
7694 };
7695 static int nhkatab = (sizeof(hkatab) / sizeof(struct keytab)) - 1;
7696
7697 int                                     /* SET SSH variables */
7698   ssh_afw = 0,                          /* agent forwarding */
7699   ssh_xfw = 0,                          /* x11 forwarding   */
7700   ssh_prp = SET_OFF,                    /* privileged ports */
7701   ssh_cmp = 1,                          /* compression */
7702   ssh_shh = 0,                          /* quiet       */
7703   ssh_ver = 0,                          /* protocol version (auto,1,2) */
7704   ssh_vrb = 2,                          /* Report errors */
7705   ssh_chkip = 0,                        /* SSH Check Host IP flag */
7706   ssh_gwp = 0,                          /* gateway ports */
7707   ssh_dyf = 0,                          /* dynamic forwarding */
7708   ssh_gsd = 0,                          /* gssapi delegate credentials */
7709   ssh_k4tgt = 0,                        /* k4 tgt passing */
7710   ssh_k5tgt = 0,                        /* k5 tgt passing */
7711   ssh_shk = 2,                          /* Strict host key (no, yes, ask) */
7712   ssh2_ark = 1,                         /* Auto re-key */
7713   ssh_cas = 0,                          /* command as subsys */
7714   ssh_cfg = 0,                          /* use OpenSSH config? */
7715   ssh_gkx = 1,                          /* gssapi key exchange */
7716   ssh_k5_is_k4 = 1,                     /* some SSH v1 use same codes */
7717   ssh_hbt = 0,                          /* heartbeat (seconds) */
7718   ssh_dummy = 0;                        /* bottom of list */
7719
7720 char                                    /* The following are to be malloc'd */
7721   * ssh1_cif = NULL,                    /* v1 cipher */
7722   * ssh2_cif = NULL,                    /* v2 cipher list */
7723   * ssh2_mac = NULL,                    /* v2 mac list */
7724   * ssh2_auth = NULL,                   /* v2 authentication list */
7725   * ssh_hst = NULL,                     /* hostname */
7726   * ssh_prt = NULL,                     /* port/service */
7727   * ssh_cmd = NULL,                     /* command to execute */
7728   * ssh_xal = NULL,                     /* xauth-location */
7729   * ssh1_gnh = NULL,                    /* v1 global known hosts file */
7730   * ssh1_unh = NULL,                    /* v1 user known hosts file */
7731   * ssh2_gnh = NULL,                    /* v2 global known hosts file */
7732   * ssh2_unh = NULL,                    /* v2 user known hosts file */
7733   * ssh2_hka = NULL,                    /* Host Key Algorithms */
7734   * xxx_dummy = NULL;
7735
7736 char * ssh_idf[32] = {                  /* Identity file list */
7737   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7738   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7739   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7740   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
7741 };
7742 char * ssh_tmp[32] = {                  /* Temp identity file list */
7743   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7744   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7745   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7746   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
7747 };
7748 int ssh_idf_n = 0;
7749
7750 extern int    ssh_pf_lcl_n,
7751               ssh_pf_rmt_n;
7752 extern struct ssh_pf ssh_pf_lcl[32];    /* Port forwarding structs */
7753 extern struct ssh_pf ssh_pf_rmt[32];    /* (declared in ckuusr.c) */
7754 #endif /* SSHBUILTIN */
7755
7756 #ifdef SFTP_BUILTIN
7757 static struct keytab sftptab[] = {
7758     { "end-of-line",            XY_SFTP_EOL, 0, },
7759     { "remote-character-set",   XY_SFTP_RCS, 0, },
7760     { "", 0, 0 }
7761 };
7762 static int nsftptab = (sizeof(sftptab) / sizeof(struct keytab)) - 1;
7763 #endif /* SFTP_BUILTIN */
7764
7765 VOID
7766 shossh() {
7767 #ifdef SSHBUILTIN
7768     int i, n = 0;                       /* ADD askmore()! */
7769
7770     printf("\nSSH is built in:\n\n");
7771
7772     printf(" ssh host:                        %s\n",showstring(ssh_hst));
7773     printf(" ssh port:                        %s\n",showstring(ssh_prt));
7774     printf(" ssh command:                     %s\n",showstring(ssh_cmd));
7775     printf(" ssh agent-forwarding:            %s\n",showoff(ssh_afw));
7776     printf(" ssh check-host-ip:               %s\n",showoff(ssh_chkip));
7777     printf(" ssh compression:                 %s\n",showoff(ssh_cmp));
7778     printf(" ssh dynamic-forwarding:          %s\n",showoff(ssh_dyf));
7779     if (ssh_pf_lcl[0].p1 && ssh_pf_lcl[0].host && ssh_pf_lcl[0].p2) {
7780       printf(" ssh forward-local-port:          %d %s %d\n",
7781              ssh_pf_lcl[0].p1, ssh_pf_lcl[0].host, ssh_pf_lcl[0].p2);
7782       for ( n=1;n<ssh_pf_lcl_n;n++ )
7783         printf("                       :          %d %s %d\n",
7784                ssh_pf_lcl[n].p1, ssh_pf_lcl[n].host, ssh_pf_lcl[n].p2);
7785     } else
7786       printf(" ssh forward-local-port:         (none)\n");
7787     if (ssh_pf_rmt[0].p1 && ssh_pf_rmt[0].host && ssh_pf_rmt[0].p2) {
7788       printf(" ssh forward-remote-port:         %d %s %d\n",
7789              ssh_pf_rmt[0].p1, ssh_pf_rmt[0].host, ssh_pf_rmt[0].p2);
7790       for ( n=1;n<ssh_pf_rmt_n;n++ )
7791         printf("                        :         %d %s %d\n",
7792                ssh_pf_rmt[n].p1, ssh_pf_rmt[n].host, ssh_pf_rmt[n].p2);
7793     } else
7794       printf(" ssh forward-remote-port:        (none)\n");
7795     printf(" ssh gateway-ports:               %s\n",showoff(ssh_gwp));
7796     printf(" ssh gssapi delegate-credentials: %s\n",showoff(ssh_gsd));
7797     printf(" ssh gssapi key-exchange        : %s\n",showoff(ssh_gkx));
7798     printf(" ssh identity-file:               %d\n",ssh_idf_n);
7799     for (i = 0; i < ssh_idf_n; i++)
7800       printf("  %2d. %s\n",i+1,showstring(ssh_idf[i]));
7801     printf(" ssh heartbeat interval:          %d\n", ssh_hbt);
7802     printf(" ssh k4 tgt-passing:              %s\n",showoff(ssh_k4tgt));
7803     printf(" ssh k5 tgt-passing:              %s\n",showoff(ssh_k5tgt));
7804
7805     printf(" ssh privileged-port:             %s\n",showooa(ssh_prp));
7806     printf(" ssh quiet:                       %s\n",showoff(ssh_shh));
7807     printf(" ssh strict-host-key-check:       %d\n",ssh_shk);
7808     printf(" ssh use-openssh-config:          %s\n",showoff(ssh_cfg));
7809     printf(" ssh verbose:                     %d\n",ssh_vrb);
7810     printf(" ssh version:                     %s\n",
7811            ssh_ver ? ckitoa(ssh_ver) : "automatic"
7812            );
7813     printf(" ssh x11-forwarding:              %s\n",showooa(ssh_xfw));
7814     printf(" ssh xauth-location:              %s\n",showstring(ssh_xal));
7815     printf("\n");
7816     printf(" ssh v1 cipher:                   %s\n",showstring(ssh1_cif));
7817     printf(" ssh v1 global-known-hosts-file:  %s\n",showstring(ssh1_gnh));
7818     printf(" ssh v1 user-known-hosts-file:    %s\n",showstring(ssh1_unh));
7819     printf("\n");
7820     printf(" ssh v2 authentication:           %s\n",showstring(ssh2_auth));
7821     printf(" ssh v2 auto-rekey:               %s\n",showoff(ssh2_ark));
7822     printf(" ssh v2 ciphers:                  %s\n",showstring(ssh2_cif));
7823     printf(" ssh v2 command-as-subsystem:     %s\n",showoff(ssh_cas));
7824     printf(" ssh v2 global-known-hosts-file:  %s\n",showstring(ssh2_gnh));
7825     printf(" ssh v2 hostkey-algorithms:       %s\n",showstring(ssh2_hka));
7826     printf(" ssh v2 mac:                      %s\n",showstring(ssh2_mac));
7827     printf(" ssh v2 user-known-hosts-file:    %s\n",showstring(ssh2_unh));
7828 #else
7829 #ifdef SSHCMD
7830     extern char * sshcmd, * defsshcmd;
7831     char * s;
7832     s = sshcmd ? sshcmd : defsshcmd;
7833     printf("\n SSH is external.\n\n");
7834     printf(" ssh command: %s\n",showstring(s));
7835 #endif /* SSHCMD */
7836 #endif /* SSHBUILTIN */
7837     printf("\n");
7838 }
7839
7840 static int
7841 dosetssh() {
7842 #ifdef SSHCMD
7843     extern char * sshcmd;
7844 #endif /* SSHCMD */
7845 #ifdef SSHBUILTIN
7846 #ifndef SSHTEST
7847     extern int sl_ssh_xfw_saved, sl_ssh_ver_saved;
7848 #endif /* SSHTEST */
7849 #endif /* SSHBUILTIN */
7850     int cx, x, y, z;
7851     char * s;
7852
7853     if ((cx = cmkey(sshtab,nsshtab,"","command", xxstring)) < 0)
7854       return(cx);
7855     switch (cx) {
7856 #ifdef SSHCMD
7857       case SSH_CMD:                     /* Command */
7858         if ((x = cmtxt("Command to start ssh","ssh -e none",
7859                        &s,xxstring)) < 0)
7860           return(x);
7861         makestr(&sshcmd,s);
7862         return(success = 1);
7863 #endif /* SSHCMD */
7864
7865 #ifdef SSHBUILTIN
7866       case SSH_AFW:                     /* Agent-forwarding */
7867         return(success = seton(&ssh_afw));
7868
7869       case SSH_CHI:                     /* Check Host IP */
7870         return(success = seton(&ssh_chkip));
7871         break;
7872
7873       case SSH_CMP:                     /* Compression */
7874         return(success = seton(&ssh_cmp));
7875
7876       case SSH_DYF:                     /* Dynamic Forwarding */
7877         return(success = seton(&ssh_dyf));
7878
7879       case SSH_GWP:                     /* Gateway ports */
7880         return(success = seton(&ssh_gwp));
7881
7882       case SSH_GSS:                     /* GSSAPI */
7883         if ((y = cmkey(gssapitab,ngssapitab,"","", xxstring)) < 0)
7884           return(y);
7885         switch (y) {
7886           case 1:                       /* Delegate credentials */
7887             return(success = seton(&ssh_gsd));
7888           case 2:                       /* key-exchange */
7889             return(success = seton(&ssh_gkx));
7890         }
7891         if ((x = cmcfm()) < 0)
7892           return(x);
7893         return(success = 0);
7894
7895 #ifdef COMMENT
7896       case SSH_KBD:                     /* Kbd Interactive Devices */
7897         if ((x = cmcfm()) < 0)
7898           return(x);
7899         /* TO BE FILLED IN */
7900         return(-2);
7901 #endif /* COMMENT */
7902
7903       case SSH_K4:                      /* Kerberos IV */
7904       case SSH_K5:                      /* Kerberos V */
7905         if ((y = cmkey(tgtpass,1,"","tgt-passing", xxstring)) < 0)
7906           return(y);
7907         switch (y) {
7908           case 1:
7909             return(success = (cx == SSH_K4) ?
7910                    seton(&ssh_k4tgt) : seton(&ssh_k5tgt));
7911         }
7912         if ((x = cmcfm()) < 0)
7913           return(x);
7914         return(success = 0);
7915
7916       case SSH_PRP:                     /* Privd port */
7917         return(success = seton(&ssh_prp));
7918
7919       case SSH_SHH:                     /* Quiet */
7920         return(success = seton(&ssh_shh));
7921
7922       case SSH_SHK:                     /* Strict Host Key Check */
7923         if ((y = cmkey(ooktab,3,"","", xxstring)) < 0)
7924           return(y);
7925         if ((x = cmcfm()) < 0)
7926           return(x);
7927         ssh_shk = y;
7928         return(success = 1);
7929
7930       case SSH_HBT:
7931         x = cmnum("Heartbeat interval, seconds","0",10,&z,xxstring);
7932         if (x < 0) return(x);
7933         if ((x = cmcfm()) < 0) return(x);
7934         ssh_hbt = z;
7935         return(success = 1);
7936
7937       case SSH_V1:                      /* SSH V1 */
7938         if ((y = cmkey(sshv1tab,nsshv1tab,"","", xxstring)) < 0)
7939           return(y);
7940         switch (y) {
7941           case SSH1_K54:
7942             return(success = seton(&ssh_k5_is_k4));
7943           case SSH1_CIF:                /* Not a list */
7944             if ((y = cmkey(ssh1ciphers,nssh1ciphers,"","", xxstring)) < 0)
7945               if (y != -3)
7946                 return(y);
7947             if ((x = cmcfm()) < 0) return(x);
7948             if (y == -3) {
7949                 makestr(&ssh1_cif,NULL);
7950             } else {
7951                 for (x = 0; x < nssh1ciphers; x++)
7952                   if (ssh1ciphers[x].kwval == y)
7953                     break;
7954                 makestr(&ssh1_cif,ssh1ciphers[x].kwd);
7955             }
7956             return(1);
7957           case SSH1_GNH:
7958           case SSH1_UNH:
7959             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
7960                 if (x != -3)
7961                   return(x);
7962             } else {
7963                 ckstrncpy(line,s,LINBUFSIZ);
7964                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
7965                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
7966             }
7967             s = (x == -3) ? NULL : line;
7968             if ((x = cmcfm()) < 0)
7969               return(x);
7970             switch (y) {
7971               case SSH1_GNH: makestr(&ssh1_gnh,s); break;
7972               case SSH1_UNH: makestr(&ssh1_unh,s); break;
7973             }
7974             return(1);
7975         }
7976
7977       case SSH_V2:                      /* SSH V2 */
7978         if ((y = cmkey(sshv2tab,nsshv2tab,"","", xxstring)) < 0)
7979           return(y);
7980         switch (y) {
7981           case SSH2_ARK:
7982             return(success = seton(&ssh2_ark));
7983         case SSH2_AUT: {                        /* Authentication */
7984 #define TMPCNT 12
7985             int i, j, tmp[TMPCNT];
7986             for (i = 0; i < TMPCNT; i++)
7987               tmp[i] = 0;
7988             for (i = 0; i < TMPCNT; i++) {
7989                 if ((y = cmkey(ssh2aut,nssh2aut,
7990                                "Authentication method","",xxstring)) < 0) {
7991                     if (y == -3)
7992                       break;
7993                     return(y);
7994                 }
7995                 for (j = 0; j < i; j++) {
7996                     if (tmp[j] == y) {
7997                         printf("\r\n?Choice has already been used.\r\n");
7998                         return(-9);
7999                     }
8000                 }
8001                 tmp[i] = y;
8002             }
8003             if ((z = cmcfm()) < 0)
8004               return(z);
8005
8006             if (ssh2_auth) {
8007                 free(ssh2_auth);
8008                 ssh2_auth = NULL;
8009             }
8010             if (i > 0) {
8011                 int len = 0;
8012                 for (j = 0; j < i; j++) {
8013                     for (x = 0; x < nssh2aut; x++)
8014                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
8015                         break;
8016                     len += strlen(ssh2aut[x].kwd) + 1;
8017                 }
8018                 ssh2_auth = malloc(len);
8019                 ssh2_auth[0] = '\0';
8020                 for (j = 0; j < i; j++) {
8021                     for (x = 0; x < nssh2aut; x++)
8022                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
8023                         break;
8024                     ckstrncat(ssh2_auth,ssh2aut[x].kwd,len);
8025                     if (j < i - 1)
8026                       ckstrncat(ssh2_auth,",",len);
8027                 }
8028             }
8029             return(success = 1);
8030 #undef TMPCNT
8031           }
8032         case SSH2_CIF: {
8033 #define TMPCNT 12
8034             int i, j, tmp[TMPCNT];
8035             for (i = 0; i < TMPCNT; i++)
8036               tmp[i] = 0;
8037
8038             for (i = 0; i < TMPCNT; i++) {
8039                 if ((y = cmkey(ssh2ciphers,nssh2ciphers,
8040                                "","", xxstring)) < 0) {
8041                     if (y == -3)
8042                       break;
8043                     return(y);
8044                 }
8045                 for (j = 0; j < i; j++) {
8046                     if (tmp[j] == y) {
8047                         printf("\r\n?Choice has already been used.\r\n");
8048                         return(-9);
8049                     }
8050                 }
8051                 tmp[i] = y;
8052             }
8053             if ((z = cmcfm()) < 0)
8054               return(z);
8055
8056             if (ssh2_cif) {
8057                 free(ssh2_cif);
8058                 ssh2_cif = NULL;
8059             }
8060             if (i > 0) {
8061                 int len = 0;
8062                 for (j=0; j < i; j++) {
8063                     for (x = 0; x < nssh2ciphers; x++)
8064                       if (ssh2ciphers[x].kwval == tmp[j] &&
8065                           !ssh2ciphers[x].flgs)
8066                         break;
8067                     len += strlen(ssh2ciphers[x].kwd) + 1;
8068                 }
8069                 ssh2_cif = malloc(len);
8070                 ssh2_cif[0] = '\0';
8071                 for (j = 0; j < i; j++) {
8072                   for (x = 0; x < nssh2ciphers; x++)
8073                     if (ssh2ciphers[x].kwval == tmp[j] && !ssh2ciphers[x].flgs)
8074                       break;
8075                     ckstrncat(ssh2_cif,ssh2ciphers[x].kwd,len);
8076                     if (j < i - 1)
8077                       ckstrncat(ssh2_cif,",",len);
8078                 }
8079             }
8080             return(success = 1);
8081 #undef TMPCNT
8082         }
8083         case SSH2_MAC: {
8084 #define TMPCNT 12
8085             int i, j, tmp[TMPCNT];
8086             for (i = 0; i < TMPCNT; i++)
8087               tmp[i] = 0;
8088
8089             for (i = 0; i < TMPCNT; i++) {
8090                 if ((y = cmkey(ssh2macs,nssh2macs,"","", xxstring)) < 0) {
8091                     if (y == -3)
8092                       break;
8093                     return(y);
8094                 }
8095                 for (j = 0; j < i; j++) {
8096                     if (tmp[j] == y) {
8097                         printf("\r\n?Choice has already been used.\r\n");
8098                         return(-9);
8099                     }
8100                 }
8101                 tmp[i] = y;
8102             }
8103             if ((z = cmcfm()) < 0)
8104                 return(z);
8105
8106             if (ssh2_mac) {
8107                 free(ssh2_mac);
8108                 ssh2_mac = NULL;
8109             }
8110             if (i > 0) {
8111                 int len = 0;
8112                 for (j = 0; j < i; j++) {
8113                     for (x = 0; x < nssh2macs; x++)
8114                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
8115                         break;
8116                     len += strlen(ssh2macs[x].kwd) + 1;
8117                 }
8118                 ssh2_mac = malloc(len);
8119                 ssh2_mac[0] = '\0';
8120                 for (j=0; j < i; j++) {
8121                     for (x = 0; x < nssh2macs; x++)
8122                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
8123                         break;
8124                     ckstrncat(ssh2_mac,ssh2macs[x].kwd,len);
8125                     if (j < i - 1)
8126                       ckstrncat(ssh2_mac,",",len);
8127                 }
8128             }
8129             return(success = 1);
8130 #undef TMPCNT
8131           }
8132           case SSH2_HKA: {
8133 #define TMPCNT 12
8134             int i, j, tmp[TMPCNT];
8135             for (i = 0; i < TMPCNT; i++)
8136               tmp[i] = 0;
8137
8138             for (i = 0; i < TMPCNT; i++) {
8139                 if ((y = cmkey(hkatab,nhkatab,
8140                                "","", xxstring)) < 0) {
8141                     if (y == -3)
8142                       break;
8143                     return(y);
8144                 }
8145                 for (j = 0; j < i; j++) {
8146                     if (tmp[j] == y) {
8147                         printf("\r\n?Choice has already been used.\r\n");
8148                         return(-9);
8149                     }
8150                 }
8151                 tmp[i] = y;
8152             }
8153             if ((z = cmcfm()) < 0)
8154               return(z);
8155
8156             if (ssh2_hka) {
8157                 free(ssh2_hka);
8158                 ssh2_hka = NULL;
8159             }
8160             if (i > 0) {
8161                 int len = 0;
8162                 for (j=0; j < i; j++) {
8163                     for (x = 0; x < nhkatab; x++)
8164                       if (hkatab[x].kwval == tmp[j] &&
8165                           !hkatab[x].flgs)
8166                         break;
8167                     len += strlen(hkatab[x].kwd) + 1;
8168                 }
8169                 ssh2_hka = malloc(len);
8170                 ssh2_hka[0] = '\0';
8171                 for (j = 0; j < i; j++) {
8172                   for (x = 0; x < nhkatab; x++)
8173                     if (hkatab[x].kwval == tmp[j] && !hkatab[x].flgs)
8174                       break;
8175                     ckstrncat(ssh2_hka,hkatab[x].kwd,len);
8176                     if (j < i - 1)
8177                       ckstrncat(ssh2_hka,",",len);
8178                 }
8179             }
8180             return(success = 1);
8181 #undef TMPCNT
8182           }
8183           case SSH2_GNH:
8184           case SSH2_UNH:
8185             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
8186                 if (x != -3)
8187                   return(y);
8188             } else {
8189                 ckstrncpy(line,s,LINBUFSIZ);
8190                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8191                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
8192             }
8193             s = (x == -3) ? NULL : line;
8194             if ((x = cmcfm()) < 0)
8195               return(x);
8196             switch (y) {
8197               case SSH2_GNH: makestr(&ssh2_gnh,s); break;
8198               case SSH2_UNH: makestr(&ssh2_unh,s); break;
8199               default: return(success = 0);
8200             }
8201             return(success = 1);
8202         }
8203
8204       case SSH_VRB:                     /* Verbosity level */
8205         y = cmnum("SSH verbosity level, 0-7","2",10,&x,xxstring);
8206         return(setnum(&ssh_vrb,x,y,7));
8207
8208       case SSH_VER:                     /* Version */
8209         if ((y = cmkey(sshver,3,"","auto", xxstring)) < 0)
8210           return(y);
8211         if ((x = cmcfm()) < 0)
8212           return(x);
8213         ssh_ver = y;                    /* 0 == AUTO */
8214 #ifndef SSHTEST
8215         sl_ssh_ver_saved = 0;
8216 #endif /* SSHTEST */
8217         return(success = 1);
8218
8219       case SSH_IDF: {                   /* Identity file */
8220         int i, n;
8221         for (i = 0; i < 32; i++) {
8222             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
8223                 if (x == -3)
8224                   break;
8225                 return(x);
8226             }
8227             if (!zfnqfp(s,LINBUFSIZ,line))
8228               ckstrncpy(line,s,LINBUFSIZ);
8229             makestr(&ssh_tmp[i],line);
8230         }
8231         n = i;
8232         if ((x = cmcfm()) < 0) {
8233             for (i = 0; i < n; i++)
8234               makestr(&(ssh_tmp[i]),NULL);
8235             return(x);
8236         }
8237         for (i = 0; i < 32; i++) {
8238             makestr(&(ssh_idf[i]),NULL);
8239             if (i < n) {
8240                 ssh_idf[i] = ssh_tmp[i];
8241                 ssh_tmp[i] = NULL;
8242             } else {
8243                 makestr(&(ssh_tmp[i]),NULL);
8244             }
8245         }
8246         ssh_idf_n = n;
8247         return(success = 1);
8248       }
8249       case SSH_XFW:                     /* X11-forwarding */
8250         success = seton(&ssh_xfw);
8251 #ifndef SSHTEST
8252         if (success)
8253           sl_ssh_xfw_saved = 0;
8254 #endif /* SSHTEST */
8255         return(success);
8256
8257       case SSH_XAL:                     /* SSH Xauth Location */
8258         if ((x = cmifi("Path to executable", "",&s,&y,xxstring)) < 0) {
8259             if (x != -3)
8260               return(x);
8261         } else {
8262             ckstrncpy(line,s,LINBUFSIZ);
8263             if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8264               ckstrncpy(line,tmpbuf,LINBUFSIZ);
8265         }
8266         s = (x == -3) ? NULL : line;
8267         if ((x = cmcfm()) < 0) return(x);
8268         makestr(&ssh_xal,s);
8269         return(success = 1);
8270
8271       case SSH_CFG:                     /* Use OpenSSH Config */
8272         return(success = seton(&ssh_cfg));
8273 #endif /* SSHBUILTIN */
8274
8275       default:
8276         return(-2);
8277     }
8278 }
8279 #endif /* ANYSSH */
8280
8281 #ifdef SFTP_BUILTIN
8282 static int
8283 dosetsftp() {
8284     int cx, x, y, z;
8285     char * s;
8286
8287     if ((cx = cmkey(sftptab,nsftptab,"","", xxstring)) < 0)
8288       return(cx);
8289     switch (cx) {
8290     case XY_SFTP_EOL:
8291     case XY_SFTP_RCS:
8292     default:
8293         return(-2);
8294     }
8295 }
8296 #endif /* SFTP_BUILTIN */
8297
8298 #ifdef KUI
8299 #include "ikui.h"
8300 extern ULONG RGBTable[16];
8301
8302 #define GUI_RGB  1
8303 #define GUI_WIN  2
8304 #define GUI_FON  3
8305 #define GUI_DIA  4
8306 #define GUI_TLB  5
8307 #define GUI_MNB  6
8308
8309 #define GUIW_POS 1
8310 #define GUIW_RES 2
8311 #define GUIW_RUN 3
8312 #define GUIWR_NON 0
8313 #define GUIWR_FON 1
8314 #define GUIWR_DIM 2
8315 #define GUIWN_RES 1
8316 #define GUIWN_MIN 2
8317 #define GUIWN_MAX 3
8318
8319 static struct keytab guitab[] = {
8320     { "dialogs",     GUI_DIA,  0 },
8321     { "font",        GUI_FON,  0 },
8322     { "menubar",     GUI_MNB,  0 },
8323     { "rgbcolor",    GUI_RGB,  0 },
8324     { "toolbar",     GUI_TLB,  0 },
8325     { "window",      GUI_WIN,  0 },
8326     { "", 0, 0}
8327 };
8328 static int nguitab = (sizeof(guitab) / sizeof(struct keytab));
8329
8330 static struct keytab guiwtab[] = {
8331     { "position",    GUIW_POS, 0 },
8332     { "resize-mode", GUIW_RES, 0 },
8333     { "run-mode",    GUIW_RUN, 0 },
8334     { "", 0, 0}
8335 };
8336 static int nguiwtab = (sizeof(guiwtab) / sizeof(struct keytab));
8337
8338 static struct keytab guiwrtab[] = {
8339     { "change-dimensions",  GUIWR_DIM, 0 },
8340     { "none",               GUIWR_NON, 0 },
8341     { "scale-font",         GUIWR_FON, 0 },
8342     { "", 0, 0}
8343 };
8344 static int nguiwrtab = (sizeof(guiwrtab) / sizeof(struct keytab));
8345
8346 static struct keytab guiwntab[] = {
8347     { "maximize",  GUIWN_MAX, 0 },
8348     { "minimize",  GUIWN_MIN, 0 },
8349     { "restore",   GUIWN_RES, 0 },
8350     { "", 0, 0}
8351 };
8352 static int nguiwntab = (sizeof(guiwntab) / sizeof(struct keytab));
8353
8354 static struct keytab rgbtab[] = {
8355     { "black",         0, 0 },
8356     { "blue",          1, 0 },
8357     { "brown",         6, 0 },
8358     { "cyan",          3, 0 },
8359     { "darkgray",      8, 0 },
8360     { "dgray",         8, CM_INV },
8361     { "green",         2, 0 },
8362     { "lblue",         9, CM_INV },
8363     { "lcyan",        11, CM_INV },
8364     { "lgreen",       10, CM_INV },
8365     { "lgray",         7, CM_INV },
8366     { "lightblue",     9, 0 },
8367     { "lightcyan",    11, 0 },
8368     { "lightgreen",   10, 0 },
8369     { "lightgray",     7, 0 },
8370     { "lightmagenta", 13, 0 },
8371     { "lightred",     12, 0 },
8372     { "lmagenta",     13, CM_INV },
8373     { "lred",         12, CM_INV },
8374     { "magenta",       5, 0 },
8375     { "red",           4, 0 },
8376     { "white",        15, 0 },
8377     { "yellow",       14, 0 },
8378
8379 };
8380 int nrgb = (sizeof(rgbtab) / sizeof(struct keytab));
8381
8382 VOID
8383 shogui() {
8384     extern gui_dialog;
8385     extern HWND getHwndKUI();
8386     unsigned char cmdsav = colorcmd;
8387     int i, red, green, blue, lines=0;
8388     char * s;
8389
8390
8391     printf("GUI paramters:\n");
8392     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8393     printf("  Dialogs:     %s\n",showoff(gui_dialog));
8394     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8395     printf("  Position:    %d,%d\n",get_gui_window_pos_x(),
8396             get_gui_window_pos_y());
8397     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8398     printf("  Resolution:  %d x %d\n",GetSystemMetrics(SM_CXSCREEN),
8399             GetSystemMetrics(SM_CYSCREEN));
8400     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8401     printf("  Run-mode:    %s\n",IsIconic(getHwndKUI()) ? "minimized" :
8402             IsZoomed(getHwndKUI()) ? "maximized" : "restored");
8403     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8404     switch ( get_gui_resize_mode() ) {
8405       case GUIWR_NON:
8406         s = "none";
8407         break;
8408       case GUIWR_FON:
8409         s = "scales font";
8410         break;
8411       case GUIWR_DIM:
8412         s= "changes dimensions";
8413         break;
8414     }
8415     printf("  Resize-mode: %s\n",s);
8416     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8417     printf("\n");
8418     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8419
8420     printf("RGB Color Table:\n");
8421     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8422     printf("  Color              Red Green Blue\n");
8423     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8424     printf("  ------------------------------------------\n");
8425     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8426     for (i = 0; i < nrgb; i++) {
8427         if (!rgbtab[i].flgs) {
8428             blue = (RGBTable[rgbtab[i].kwval] & 0x00FF0000)>>16;
8429             green = (RGBTable[rgbtab[i].kwval] & 0x0000FF00)>>8;
8430             red = (RGBTable[rgbtab[i].kwval] & 0x000000FF);
8431             printf("  %-18s %3d  %3d  %3d  ",rgbtab[i].kwd,red,green,blue);
8432             colorcmd = rgbtab[i].kwval << 4;
8433             printf("********");
8434             colorcmd = cmdsav;
8435             printf("\n");
8436             if (++lines > cmd_rows - 3) {
8437                 if (!askmore())
8438                   return;
8439                 else
8440                   lines = 0;
8441             }
8442         }
8443     }
8444     printf("\n");
8445 }
8446
8447 int
8448 setrgb() {
8449     int cx, red = 0, blue = 0, green = 0, z, x;
8450
8451     if ((cx = cmkey(rgbtab,nrgb,"","",xxstring)) < 0)
8452       return(cx);
8453     if ((z = cmnum("Red value, 0-255","",10,&red,xxstring)) < 0)
8454       return(z);
8455     if ((z = cmnum("Green value, 0-255","",10,&green,xxstring)) < 0)
8456       return(z);
8457     if ((z = cmnum("Blue value, 0-255","",10,&blue,xxstring)) < 0)
8458       return(z);
8459     if ((x = cmcfm()) < 0) return(x);
8460     if (cx > 15 || red > 255 || blue > 255 || green > 255)
8461       return(-2);
8462     RGBTable[cx] = (unsigned)(((unsigned)blue << 16) |
8463         (unsigned)((unsigned)green << 8) |
8464         (unsigned)red);
8465     return(success = 1);
8466 }
8467
8468 /*
8469   Set GUI window position: XY coordinates of upper left corner,
8470   expressed as pixel numbers in the current screen resolution.
8471   (0,0) means put ourselves in the upper left corner.
8472   Can we check for out of bounds?
8473 */
8474
8475 int
8476 setguiwin() {
8477     int cx, x, y, z;
8478     if ((cx = cmkey(guiwtab,nguiwtab,"","",xxstring)) < 0)
8479       return(cx);
8480     switch (cx) {
8481       case GUIW_POS:
8482         if ((z = cmnum("X coordinate (pixel number)","",10,&x,xxstring)) < 0)
8483           return(z);
8484         if ((z = cmnum("Y coordinate (pixel number)","",10,&y,xxstring)) < 0)
8485           return(z);
8486         if ((z = cmcfm()) < 0)
8487           return(z);
8488         if (x < 0 || y < 0) {
8489             printf("?Coordinates must be 0 or greater\n");
8490             return(-9);
8491         }
8492         gui_position(x,y);
8493         return(success = 1);
8494       case GUIW_RES:
8495         if ((x = cmkey(guiwrtab,nguiwrtab,"","",xxstring)) < 0)
8496           return(x);
8497         if ((z = cmcfm()) < 0)
8498           return(z);
8499         gui_resize_mode(x);
8500         return(success = 1);
8501       case GUIW_RUN:
8502         if ((x = cmkey(guiwntab,nguiwntab,"","",xxstring)) < 0)
8503           return(x);
8504         if ((z = cmcfm()) < 0)
8505           return(z);
8506         gui_win_run_mode(x);
8507         return(success = 1);
8508       default:
8509         return(-2);
8510     }
8511 }
8512
8513 int
8514 setguifont() {                          /* Assumes that CKFLOAT is defined! */
8515
8516     extern struct keytab * term_font;
8517     extern struct keytab * _term_font;
8518     extern int tt_font, tt_font_size, ntermfont;
8519     int x, y, z;
8520     char *s;
8521
8522     if (ntermfont == 0)
8523       BuildFontTable(&term_font, &_term_font, &ntermfont);
8524     if (!(term_font && _term_font && ntermfont > 0)) {
8525         printf("?Internal error: Failure to enumerate fonts\n");
8526         return(-9);
8527     }
8528     if ((x = cmkey(_term_font,ntermfont,"","",xxstring)) < 0)
8529       return(x);
8530     if ((z = cmfld("Height of font in points","12",&s,xxstring)) < 0)
8531       return(z);
8532     if (isfloat(s,0) < 1) {             /* (sets floatval) */
8533         printf("?Integer or floating-point number required\n");
8534         return(-9);
8535     }
8536     if (floatval < 0.5) {
8537         printf("?Positive number required\n");
8538         return(-9);
8539     }
8540     if ((z = cmcfm()) < 0)
8541       return(z);
8542     tt_font = x;                        /* Font index */
8543     tt_font_size = (int)(floatval * 2); /* Font size in half points */
8544     KuiSetProperty(KUI_TERM_FONT, (long)tt_font, (long)tt_font_size);
8545     return(success = 1);
8546 }
8547
8548 VOID
8549 setguidialog(x) int x;
8550 {
8551     extern int gui_dialog;
8552     gui_dialog = x;
8553     KuiSetProperty(KUI_GUI_DIALOGS, (long)x, 0L);
8554 }
8555
8556 VOID
8557 setguimenubar(x) int x;
8558 {
8559     KuiSetProperty(KUI_GUI_MENUBAR, (long)x, 0L);
8560 }
8561
8562 VOID
8563 setguitoolbar(x) int x;
8564 {
8565     KuiSetProperty(KUI_GUI_TOOLBAR, (long)x, 0L);
8566 }
8567
8568 int
8569 setgui() {
8570     int cx, x, rc;
8571     if ((cx = cmkey(guitab,nguitab,"","",xxstring)) < 0)
8572       return(cx);
8573     switch (cx) {
8574       case GUI_DIA:
8575         rc = seton(&x);
8576         if (rc >= 0)
8577           setguidialog(x);
8578         return(rc);
8579       case GUI_FON:
8580         return(setguifont());
8581       case GUI_RGB:
8582         return(setrgb());
8583       case GUI_WIN:
8584         return(setguiwin());
8585       case GUI_TLB:
8586         rc = seton(&x);
8587         if (rc >= 0)
8588           setguitoolbar(x);
8589         return(rc);
8590       case GUI_MNB:
8591         rc = seton(&x);
8592         if (rc >= 0)
8593           setguimenubar(x);
8594         return(rc);
8595       default:
8596         return(-2);
8597     }
8598 }
8599 #endif /* KUI */
8600
8601 VOID
8602 setexitwarn(x) int x; 
8603 {
8604     xitwarn = x;
8605 #ifdef KUI
8606     KuiSetProperty(KUI_EXIT_WARNING, (long)x, 0L);
8607 #endif /* KUI */
8608 }
8609
8610 #ifndef NOLOCAL
8611 VOID
8612 setdebses(x) int x; {
8613 #ifdef OS2
8614     if ((debses != 0) && (x == 0))      /* It was on and we turned it off? */
8615       os2debugoff();                    /* Fix OS/2 coloration */
8616 #endif /* OS2 */
8617     debses = x;
8618 #ifdef KUI
8619     KuiSetProperty(KUI_TERM_DEBUG,x,0);
8620 #endif /* KUI */
8621 }
8622 #endif /* NOLOCAL */
8623
8624 /*  D O P R M  --  Set a parameter.  */
8625 /*
8626  Returns:
8627   -2: illegal input
8628   -1: reparse needed
8629    0: success
8630 */
8631 int
8632 doprm(xx,rmsflg) int xx, rmsflg; {
8633     int i = 0, x = 0, y = 0, z = 0;
8634     long zz = 0L;
8635     char *s = NULL, *p = NULL;
8636 #ifdef OS2
8637     char portbuf[64];
8638     long portspeed = 0L;
8639     int portparity = 0;
8640     int portflow = 0;
8641 #endif /* OS2 */
8642
8643 #ifndef NOSETKEY
8644 #ifdef OS2
8645     if (xx == XYMSK)
8646       return(setmsk());
8647 #endif /* OS2 */
8648 #endif /* NOSETKEY */
8649
8650     if (xx == XYFLAG) {                 /* SET FLAG */
8651         extern int ooflag;
8652         return(success = seton(&ooflag));
8653     }
8654     if (xx == XYPRTR                    /* SET PRINTER (or BPRINTER) */
8655 #ifdef BPRINT
8656         || xx == XYBDCP
8657 #endif /* BPRINT */
8658         )
8659       return(setprinter(xx));
8660
8661     switch (xx) {
8662
8663 #ifdef ANYX25                           /* SET X25 ... */
8664 case XYX25:
8665         return(setx25());
8666
8667 #ifndef IBMX25
8668 case XYPAD:                             /* SET PAD ... */
8669         return(setpadp());
8670 #endif /* IBMX25 */
8671 #endif /* ANYX25 */
8672
8673 #ifndef NOXFER
8674       case XYEOL:       /* These have all been moved to set send/receive... */
8675       case XYLEN:       /* Let the user know what to do. */
8676       case XYMARK:
8677       case XYNPAD:
8678       case XYPADC:
8679       case XYTIMO:
8680         printf("...Use SET SEND or SET RECEIVE instead.\n");
8681         printf("Type HELP SET SEND or HELP SET RECEIVE for more info.\n");
8682         return(success = 0);
8683
8684       case XYATTR:                      /* File Attribute packets */
8685         return(setat(rmsflg));
8686
8687       case XYIFD:                       /* Incomplete file disposition */
8688         if ((y = cmkey(ifdatab,3,"","auto",xxstring)) < 0) return(y);
8689         if ((x = cmcfm()) < 0) return(x);
8690         if (rmsflg) {
8691             sstate = setgen('S',
8692                             "310",
8693                             y == 0 ? "0" : (y == 1 ? "1" : "2"),
8694                             ""
8695                             );
8696             return((int) sstate);
8697         } else {
8698             keep = y;
8699             return(success = 1);
8700         }
8701 #endif /* NOXFER */
8702
8703       case XYMATCH:                     /* [ REMOTE ] SET MATCH...  */
8704 #ifndef NOXFER
8705         if ((z = cmkey(matchtab,nmatchtab,"","",xxstring)) < 0)
8706           return(z);
8707         if (rmsflg) {
8708             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
8709             if ((x = cmcfm()) < 0) return(x);
8710             switch (z) {
8711               case MCH_DOTF:
8712                 return(sstate = setgen('S',"330", y == 0 ? "0" : "1", ""));
8713               case MCH_FIFO:
8714                 return(sstate = setgen('S',"331", y == 0 ? "0" : "1", ""));
8715               default:
8716                 return(-2);
8717               }
8718           }
8719 #endif /* NOXFER */
8720           switch (z) {
8721             case MCH_FIFO:
8722               return(success = seton(&matchfifo));
8723             case MCH_DOTF:
8724               x = seton(&matchdot); 
8725               if (x < 0) return(x);
8726               dir_dots = -1;
8727               return(success = x);
8728             default:
8729               return(-2);
8730           }
8731
8732 #ifndef NOSPL
8733       case XYINPU:                      /* SET INPUT */
8734         return(setinp());
8735 #endif /* NOSPL */
8736
8737 #ifdef NETCONN
8738       case XYNET: {                     /* SET NETWORK */
8739
8740           struct FDB k1, k2;
8741
8742           cmfdbi(&k1,_CMKEY,"","","",nnetkey, 0, xxstring, netkey, &k2);
8743           cmfdbi(&k2,_CMKEY,"","","",nnets,   0, xxstring, netcmd, NULL);
8744
8745 #ifdef OS2     /* Hide network-type keywords for networks not installed */
8746           for (z = 0; z < nnets; z++) {
8747               if (netcmd[z].kwval == NET_TCPB && tcp_avail == 0)
8748                 netcmd[z].flgs =  CM_INV;
8749 #ifdef SSHBUILTIN
8750               if (netcmd[z].kwval == NET_SSH &&
8751                    !ck_ssleay_is_installed())
8752                 netcmd[z].flgs =  CM_INV;
8753 #endif /* SSHBUILTIN */
8754 #ifdef DECNET
8755               else if (netcmd[z].kwval == NET_DEC  && dnet_avail == 0)
8756                 netcmd[z].flgs =  CM_INV;
8757 #endif /* DECNET */
8758 #ifdef CK_NETBIOS
8759               else if (netcmd[z].kwval == NET_BIOS && netbiosAvail == 0)
8760                 netcmd[z].flgs =  CM_INV;
8761 #endif /* CK_NETBIOS */
8762 #ifdef SUPERLAT
8763               else if (netcmd[z].kwval == NET_SLAT  && slat_avail == 0)
8764                 netcmd[z].flgs =  CM_INV;
8765 #endif /* SUPERLAT */
8766           }
8767           if (tcp_avail)                /* Default network type */
8768             ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
8769 #ifdef SSHBUILTIN
8770           else if ( ck_ssleay_is_installed() )
8771             ckstrncpy(tmpbuf,"ssh",TMPBUFSIZ);
8772 #endif /* SSHBUILTIN */
8773 #ifdef DECNET
8774           else if (dnet_avail)
8775             ckstrncpy(tmpbuf,"decnet",TMPBUFSIZ);
8776 #endif /* DECNET */
8777 #ifdef SUPERLAT
8778           else if (slat_avail)
8779             ckstrncpy(tmpbuf,"superlat",TMPBUFSIZ);
8780 #endif /* SUPERLAT */
8781 #ifdef CK_NETBIOS
8782           else if (netbiosAvail)
8783             ckstrncpy(tmpbuf,"netbios",TMPBUFSIZ);
8784 #endif /* CK_NETBIOS */
8785           else ckstrncpy(tmpbuf,"named-pipe",TMPBUFSIZ);
8786 #else  /* OS2 */
8787 #ifdef TCPSOCKET
8788           ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
8789 #else
8790 #ifdef ANYX25
8791           ckstrncpy(tmpbuf,"x.25",TMPBUFSIZ);
8792 #else
8793           ckstrncpy(tmpbuf,"",TMPBUFSIZ);
8794 #endif /* ANYX25 */
8795 #endif /* TCPSOCKET */
8796 #endif /* OS2 */
8797
8798           x = cmfdb(&k1);
8799           if (x < 0) {                  /* Error */
8800               if (x == -2 || x == -9)
8801                 printf("?No keywords match: \"%s\"\n",atmbuf);
8802               return(x);
8803           }
8804           z = cmresult.nresult;         /* Keyword value */
8805           if (cmresult.fdbaddr == &k1) { /* Which table? */
8806 #ifndef NOSPL
8807 #ifndef NODIAL
8808               if (z == XYNET_D)
8809                 return(parsdir(1));
8810 #endif /* NODIAL */
8811 #endif /* NOSPL */
8812               if ((z = cmkey(netcmd,nnets,"",tmpbuf,xxstring)) < 0)
8813                 return(z);
8814           }
8815
8816 #ifdef NETCMD
8817           if (z == NET_CMD && nopush) {
8818               printf("\n?Sorry, access to external commands is disabled\n");
8819               return(-9);
8820           }
8821 #endif /* NETCMD */
8822
8823 #ifndef NOPUSH
8824 #ifdef NETPTY
8825           if (z == NET_PTY && nopush) {
8826               printf("\n?Sorry, access to external commands is disabled\n");
8827               return(-9);
8828           }
8829 #endif /* NETPTY */
8830 #endif /* NOPUSH */
8831
8832 #ifdef OS2
8833           if (z == NET_TCPB && tcp_avail == 0) {
8834               printf(
8835 "\n?Sorry, either TCP/IP is not available on this system or\n\
8836 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
8837               return(-9);
8838 #ifdef SSHBUILTIN
8839           } else if (z == NET_SSH && !ck_ssleay_is_installed()) {
8840             printf("\n?Sorry, SSH is not available on this system.\n") ;
8841             return(-9);
8842 #endif /* SSHBUILTIN */
8843 #ifdef CK_NETBIOS
8844           } else if (z == NET_BIOS && netbiosAvail == 0) {
8845               printf("\n?Sorry, NETBIOS is not available on this system.\n") ;
8846               return(-9);
8847 #endif /* CK_NETBIOS */
8848 #ifdef DECNET
8849           } else if (z == NET_DEC && dnet_avail == 0) {
8850               printf("\n?Sorry, DECnet is not available on this system.\n") ;
8851               return(-9);
8852 #endif /* DECNET */
8853 #ifdef SUPERLAT
8854           } else if (z == NET_SLAT && slat_avail == 0) {
8855               printf("\n?Sorry, SuperLAT is not available on this system.\n") ;
8856               return(-9);
8857 #endif /* SUPERLAT */
8858           }
8859 #endif /* OS2 */
8860
8861 #ifdef NPIPEORBIOS
8862           if (z == NET_PIPE ||          /* Named pipe -- also get pipename */
8863               z == NET_BIOS) {          /* NETBIOS -- also get local name */
8864               char *defnam;
8865 #ifdef CK_NETBIOS
8866               char tmpnbnam[NETBIOS_NAME_LEN+1];
8867 #endif /* CK_NETBIOS */
8868               /* Construct default name  */
8869               if (z == NET_PIPE) {      /* Named pipe */
8870                   defnam = "kermit";    /* Default name is always "kermit" */
8871               } else {                  /* NetBIOS */
8872                   if (NetBiosName[0] != SP) { /* If there is already a name, */
8873                       char *p = NULL;
8874                       int n;            /* use it as the default. */
8875                       ckstrncpy(tmpnbnam,NetBiosName,NETBIOS_NAME_LEN+1);
8876                       /* convert trailing spaces to NULs */
8877                       p = &tmpnbnam[NETBIOS_NAME_LEN-1];
8878                       while (*p == SP) {
8879                           *p = NUL;
8880                           p--;
8881                       }
8882                       defnam = tmpnbnam;
8883                   } else if (*myhost)   /* Otherwise use this PC's host name */
8884                     defnam = (char *) myhost;
8885                   else                  /* Otherwise use "kermit" */
8886                     defnam = "kermit";
8887               }
8888               if ((y = cmtxt((z == NET_PIPE) ? "pipe name" :
8889                              "local NETBIOS name",
8890                              defnam, &s, xxstring)) < 0)
8891                 return(y);
8892 #ifdef NPIPE
8893               pipename[0] = NUL;
8894 #endif /* NPIPE */
8895               if ((y = (int) strlen(s)) < 1) {
8896                   printf("?You must also specify a %s name\n",
8897                          (z == NET_PIPE) ? "pipe" : "local NETBIOS" );
8898                   return(-9);
8899               }
8900 #ifdef CK_NETBIOS
8901               if (z == NET_BIOS) {
8902                   if (!netbiosAvail) {
8903                       printf("?NETBIOS is not available on this system.\n") ;
8904                       return(-9);
8905                   }
8906                   if (y - NETBIOS_NAME_LEN > 0) {
8907                       printf("?NETBIOS name too long, %ld maximum\n",
8908                              NETBIOS_NAME_LEN);
8909                       return(-9);
8910                   } else if ( !strcmp(s,tmpnbnam) ) {
8911                       nettype = z;      /* Returning to old connection... */
8912                       return(success = 1); /* Done */
8913                   } else if (strcmp("                ",NetBiosName)) {
8914                       printf("?NETBIOS name already assigned to \"%s\"\n",
8915                              NetBiosName);
8916                       return(-9);
8917                   } else {
8918                       NCB ncb;
8919                       APIRET rc;
8920                       ckstrncpy(NetBiosName,s,16);
8921                       for (x = y; x < NETBIOS_NAME_LEN; x++)
8922                         NetBiosName[x] = SP;
8923                       NetBiosName[NETBIOS_NAME_LEN] = NUL;
8924                       printf("Checking \"%s\" as a unique NetBIOS name...\n",
8925                              NetBiosName);
8926                       rc = NCBAddName( NetbeuiAPI,
8927                                       &ncb, NetBiosAdapter, NetBiosName );
8928                       if (rc) {
8929                           printf(
8930                 "?Sorry, \"%s\" is already in use by another NetBIOS node.\n",
8931                                  NetBiosName);
8932                           for (x = 0; x < NETBIOS_NAME_LEN; x++)
8933                             NetBiosName[x] = SP;
8934                           return(-9);
8935                       }
8936                   }
8937               }
8938 #endif /* CK_NETBIOS */
8939 #ifdef NPIPE
8940               if (z == NET_PIPE)
8941                 ckstrncpy(pipename,s,PIPENAML);
8942 #endif /* NPIPE */
8943           } else
8944 #endif /* NPIPEORBIOS */
8945 #ifdef DECNET
8946             if (z == NET_DEC) {
8947                 /* Determine if we are using LAT or CTERM */
8948                 if ((y = cmkey(dnettab,
8949                                ndnet,"DECNET protocol","lat",xxstring)) < 0)
8950                   return(y);
8951                 if ((x = cmcfm()) < 0) return(x);
8952                 ttnproto = y;
8953             } else
8954 #endif /* DECNET */
8955 #ifdef NETDLL
8956               if (z == NET_DLL) {
8957                   /* Find out which DLL they are using */
8958                   char dllname[256]="";
8959                   char * p=NULL;
8960                   if ((x = cmifi("Dynamic load library",
8961                                  "",&p,&y,xxstring)) < 0) {
8962                       if (x == -3) {
8963                           printf("?Name of DLL required\n");
8964                           return(-9);
8965                       }
8966                       return(x);
8967                   }
8968                   ckstrncpy(dllname,p,256);
8969                   if ((x = cmcfm()) < 0) return(x);
8970
8971                   if (netdll_load(dllname) < 0) /* Try to load the dll */
8972                     return(success = 0);
8973                   else {
8974                       nettype = z;
8975                       return(success = 1);
8976                   }
8977               } else
8978 #endif /* NETDLL */
8979                 if ((x = cmcfm()) < 0) return(x);
8980           nettype = z;
8981           if (
8982 #ifdef DECNET
8983               (nettype != NET_DEC)  &&
8984 #endif /* DECNET */
8985 #ifdef NPIPE
8986               (nettype != NET_PIPE) &&
8987 #endif /* NPIPE */
8988 #ifdef CK_NETBIOS
8989               (nettype != NET_BIOS) &&
8990 #endif /* CK_NETBIOS */
8991 #ifdef NETFILE
8992               (nettype != NET_FILE) &&
8993 #endif /* NETFILE */
8994 #ifdef NETCMD
8995               (nettype != NET_CMD) &&
8996 #endif /* NETCMD */
8997 #ifdef NETPTY
8998               (nettype != NET_PTY) &&
8999 #endif /* NETPTY */
9000 #ifdef NETDLL
9001               (nettype != NET_DLL) &&
9002 #endif /* NETDLL */
9003 #ifdef SUPERLAT
9004               (nettype != NET_SLAT) &&
9005 #endif /* SUPERLAT */
9006               (nettype != NET_SX25) &&
9007               (nettype != NET_VX25) &&
9008 #ifdef IBMX25
9009               (nettype != NET_IX25) &&
9010 #endif /* IBMX25 */
9011 #ifdef SSHBUILTIN
9012               (nettype != NET_SSH) &&
9013 #endif /* SSHBUILTIN */
9014               (nettype != NET_TCPB)) {
9015               printf("?Network type not supported\n");
9016               return(success = 0);
9017           } else {
9018               return(success = 1);
9019           }
9020       }
9021
9022 #ifndef NOTCPOPTS
9023 #ifdef TCPSOCKET
9024       case XYTCP: {
9025         extern int ttyfd;
9026
9027         if ((z = cmkey(tcpopt,ntcpopt,"TCP option","nodelay",xxstring)) < 0)
9028           return(z);
9029
9030         switch (z) {
9031 #ifndef NOHTTP
9032           case XYTCP_HTTP_PROXY: {
9033               struct FDB sw, tx;
9034               int n, x;
9035               char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1], abuf[256];
9036               ubuf[0] = pbuf[0] = abuf[0] = 0;
9037
9038               cmfdbi(&sw,               /* First FDB - switches */
9039                      _CMKEY,            /* fcode */
9040                      "HTTP proxy server host[:port] or switch",
9041                      "",                /* default */
9042                      "",                /* addtl string data */
9043                      nuserpass,         /* addtl numeric data 1: tbl size */
9044                      4,                 /* addtl numeric data 2: 4 = cmswi */
9045                      xxstring,          /* Processing function */
9046                      userpass,          /* Keyword table */
9047                      &tx                /* Pointer to next FDB */
9048                      );
9049               cmfdbi(&tx,
9050                      _CMTXT,            /* fcode */
9051                      "HTTP proxy server host[:port]",
9052                      "",                /* default */
9053                      "",                /* addtl string data */
9054                      0,                 /* addtl numeric data 1 */
9055                      0,                 /* addtl numeric data 2 */
9056                      xxstring,
9057                      NULL,
9058                      NULL
9059                      );
9060               while (1) {
9061                   if ((x = cmfdb(&sw)) < 0) {
9062                       if (x == -3) {
9063                           x = -9;
9064                           printf("?Hostname required\n");
9065                       }
9066                       return(x);
9067                   }
9068                   if (cmresult.fcode != _CMKEY)
9069                     break;
9070                   n = cmresult.nresult;
9071                   switch (n) {
9072                     case UPW_USER:
9073                     case UPW_PASS:
9074                     case UPW_AGENT:
9075                       if ((x = cmfld((n == UPW_USER) ?
9076                                      "Username" :
9077                                      ((n == UPW_PASS) ? "Password" : "Agent"),
9078                                      "", &s, xxstring)) < 0) {
9079                           if (x != -3)
9080                             return(x);
9081                       }
9082                       ckstrncpy((n == UPW_USER) ? ubuf :
9083                         ((n == UPW_PASS) ? pbuf : abuf), s, 
9084                         (n == UPW_AGENT) ? 256 : (LOGINLEN+1));
9085                   }
9086               }
9087               if (cmresult.fcode != _CMTXT)
9088                 return(-2);
9089               s = cmresult.sresult;
9090               if (s) if (!*s) s = NULL;
9091
9092 #ifdef IKSDCONF
9093               if (iksdcf)
9094                 return(success = 0);
9095 #endif /* IKSDCONF */
9096               makestr(&tcp_http_proxy_user,ubuf[0]?ubuf:NULL);
9097               makestr(&tcp_http_proxy_pwd,pbuf[0]?pbuf:NULL);
9098               makestr(&tcp_http_proxy_agent,abuf[0]?abuf:NULL);
9099               makestr(&tcp_http_proxy,s);
9100               memset(pbuf,0,sizeof(pbuf));
9101               return(success = 1);
9102           }
9103 #endif /* NOHTTP */
9104 /*
9105   It would have been easy to combine XYTCP_SOCKS_SVR with the previous
9106   one except for the #ifdefs...
9107 */
9108 #ifdef NT
9109 #ifdef CK_SOCKS
9110           case XYTCP_SOCKS_SVR: {
9111               char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1];
9112               char * p = getenv("SOCKS_SERVER");
9113               struct FDB sw, tx;
9114               int n, x;
9115
9116               if (!p) p = "";
9117
9118               cmfdbi(&sw,               /* First FDB - switches */
9119                      _CMKEY,            /* fcode */
9120                      "SOCKS server host[:port] or switch",
9121                      "",                /* default */
9122                      "",                /* addtl string data */
9123                      nuserpass,         /* addtl numeric data 1: tbl size */
9124                      4,                 /* addtl numeric data 2: 4 = cmswi */
9125                      xxstring,          /* Processing function */
9126                      userpass,          /* Keyword table */
9127                      &tx                /* Pointer to next FDB */
9128                      );
9129               cmfdbi(&tx,
9130                      _CMTXT,            /* fcode */
9131                      "SOCKS server host[:port]",
9132                      p,                 /* default */
9133                      "",                /* addtl string data */
9134                      0,                 /* addtl numeric data 1 */
9135                      0,                 /* addtl numeric data 2 */
9136                      xxstring,
9137                      NULL,
9138                      NULL
9139                      );
9140               while (1) {
9141                   if ((x = cmfdb(&sw)) < 0) {
9142                       if (x == -3) {
9143                           x = -9;
9144                           printf("?Hostname required\n");
9145                       }
9146                       return(x);
9147                   }
9148                   if (cmresult.fcode != _CMKEY)
9149                     break;
9150                   n = cmresult.nresult;
9151                   switch (n) {
9152                     case UPW_USER:
9153                     case UPW_PASS:
9154                       if ((x = cmfld((n == UPW_USER) ? "Username" : "Password",
9155                                      "", &s, xxstring)) < 0) {
9156                           if (x != -3)
9157                             return(x);
9158                       }
9159                       ckstrncpy((n == UPW_USER) ? ubuf : pbuf, s, LOGINLEN+1);
9160                   }
9161               }
9162               if (cmresult.fcode != _CMTXT)
9163                 return(-2);
9164               s = cmresult.sresult;
9165               if (s) if (!*s) s = NULL;
9166
9167 #ifdef IKSDCONF
9168               if (iksdcf)
9169                 return(success = 0);
9170 #endif /* IKSDCONF */
9171               makestr(&tcp_socks_user,ubuf);
9172               memset(pbuf,0,sizeof(pbuf));
9173               makestr(&tcp_socks_svr,s);
9174               return(success = 1);
9175           }
9176
9177 #ifdef CK_SOCKS_NS
9178           case XYTCP_SOCKS_NS: {
9179             char * p = getenv("SOCKS_NS");
9180             if (!p) p = "";
9181             if ((y = cmtxt("hostname or IP of SOCKS Name Server",p,
9182                             &s,xxstring)) < 0)
9183                 return(y);
9184 #ifdef IKSDCONF
9185               if (iksdcf) return(success = 0);
9186 #endif /* IKSDCONF */
9187               if (tcp_socks_ns) {
9188                   free(tcp_socks_ns);   /* Free any previous storage */
9189                   tcp_socks_ns = NULL;
9190               }
9191               if (s == NULL || *s == NUL) { /* If none given */
9192                   tcp_socks_ns = NULL;  /* remove the override string */
9193                   return(success = 1);
9194               } else if ((tcp_socks_ns = malloc(strlen(s)+1))) {
9195                   strcpy(tcp_socks_ns,s);
9196                   return(success = 1);
9197               } else
9198                 return(success = 0);
9199           }
9200 #endif /* CK_SOCKS_NS */
9201 #endif /* CK_SOCKS */
9202 #endif /* NT */
9203           case XYTCP_ADDRESS:
9204             if ((y = cmtxt("preferred IP Address for TCP connections","",
9205                            &s,xxstring)) < 0)
9206               return(y);
9207 #ifdef IKSDCONF
9208             if (iksdcf) return(success = 0);
9209 #endif /* IKSDCONF */
9210             if (tcp_address) {
9211                 free(tcp_address);      /* Free any previous storage */
9212                 tcp_address = NULL;
9213             }
9214             if (s == NULL || *s == NUL) { /* If none given */
9215                 tcp_address = NULL;     /* remove the override string */
9216                 return(success = 1);
9217             } else if ((tcp_address = malloc(strlen(s)+1))) {
9218                 strcpy(tcp_address,s);
9219                 return(success = 1);
9220             } else
9221               return(success = 0);
9222 #ifdef SO_KEEPALIVE
9223           case XYTCP_KEEPALIVE:
9224             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9225             if ((y = cmcfm()) < 0) return(y);
9226 #ifdef IKSDCONF
9227             if (iksdcf) return(success = 0);
9228 #endif /* IKSDCONF */
9229 #ifdef SSHBUILTIN
9230             if (network && nettype == NET_SSH && ssh_sock != -1)
9231               success = keepalive(ssh_sock,z);
9232             else
9233 #endif /* SSHBUILTIN */
9234               success = keepalive(ttyfd,z);
9235             return(success);
9236 #endif /* SO_KEEPALIVE */
9237 #ifdef SO_DONTROUTE
9238           case XYTCP_DONTROUTE:
9239             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
9240             if ((y = cmcfm()) < 0) return(y);
9241 #ifdef IKSDCONF
9242             if (iksdcf) return(success = 0);
9243 #endif /* IKSDCONF */
9244 #ifdef SSHBUILTIN
9245             if (network && nettype == NET_SSH && ssh_sock != -1)
9246               success = dontroute(ssh_sock,z);
9247             else
9248 #endif /* SSHBUILTIN */
9249               success = dontroute(ttyfd,z);
9250             return(success);
9251 #endif /* SO_DONTROUTE */
9252 #ifdef TCP_NODELAY
9253           case XYTCP_NODELAY:
9254             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
9255             if ((y = cmcfm()) < 0) return(y);
9256 #ifdef IKSDCONF
9257             if (iksdcf) return(success = 0);
9258 #endif /* IKSDCONF */
9259 #ifdef SSHBUILTIN
9260             if (network && nettype == NET_SSH && ssh_sock != -1)
9261               success = no_delay(ssh_sock,z);
9262             else
9263 #endif /* SSHBUILTIN */
9264               success = no_delay(ttyfd,z);
9265             return(success);
9266           case XYTCP_NAGLE:             /* The inverse of NODELAY */
9267             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9268             if ((y = cmcfm()) < 0) return(y);
9269 #ifdef IKSDCONF
9270             if (iksdcf) return(success = 0);
9271 #endif /* IKSDCONF */
9272 #ifdef SSHBUILTIN
9273             if (network && nettype == NET_SSH && ssh_sock != -1)
9274               success = no_delay(ssh_sock,z);
9275             else
9276 #endif /* SSHBUILTIN */
9277               success = no_delay(ttyfd,!z);
9278             return(success);
9279 #endif /* TCP_NODELAY */
9280 #ifdef SO_LINGER
9281           case XYTCP_LINGER:
9282             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0)
9283               return(z);
9284             if (z) {                    /* if on, we need a timeout value */
9285                 if ((x = cmnum("Linger timeout in 10th of a millisecond",
9286                                "0",10,&y,xxstring)) < 0)
9287                   return(x);
9288             } else
9289               y = 0;
9290             if ((x = cmcfm()) < 0)
9291               return(x);
9292 #ifdef IKSDCONF
9293             if (iksdcf) return(success = 0);
9294 #endif /* IKSDCONF */
9295 #ifdef SSHBUILTIN
9296             if (network && nettype == NET_SSH && ssh_sock != -1)
9297               success = ck_linger(ssh_sock,z,y);
9298             else
9299 #endif /* SSHBUILTIN */
9300               success = ck_linger(ttyfd,z,y);
9301             return(success);
9302 #endif /* SO_LINGER */
9303 #ifdef SO_SNDBUF
9304           case XYTCP_SENDBUF:
9305             x = cmnum("Send buffer size, bytes","8192",10,&z,xxstring);
9306             if (x < 0) return(x);
9307             if ((x = cmcfm()) < 0) return(x);
9308 #ifdef IKSDCONF
9309             if (iksdcf) return(success = 0);
9310 #endif /* IKSDCONF */
9311 #ifdef SSHBUILTIN
9312             if (network && nettype == NET_SSH && ssh_sock != -1)
9313               success = sendbuf(ssh_sock,z);
9314             else
9315 #endif /* SSHBUILTIN */
9316               success = sendbuf(ttyfd,z);
9317             return(success);
9318 #endif /* SO_SNDBUF */
9319 #ifdef SO_RCVBUF
9320           case XYTCP_RECVBUF:
9321             x = cmnum("Receive buffer size, bytes","8192",10,&z,xxstring);
9322             if (x < 0) return(x);
9323             if ((x = cmcfm()) < 0) return(x);
9324 #ifdef IKSDCONF
9325             if (iksdcf) return(success = 0);
9326 #endif /* IKSDCONF */
9327
9328 /* Note: The following is not 16-bit safe */
9329
9330 #ifndef QNX16
9331             if (x > 52248) {
9332                 printf("?Warning: receive buffers larger than 52248 bytes\n");
9333                 printf(" may not be understood by all hosts.  Performance\n");
9334                 printf(" may suffer.\n");
9335                 return(-9);
9336             }
9337 #endif /* QNX16 */
9338 #ifdef SSHBUILTIN
9339             if (network && nettype == NET_SSH && ssh_sock != -1)
9340               success = recvbuf(ssh_sock,z);
9341             else
9342 #endif /* SSHBUILTIN */
9343               success = recvbuf(ttyfd,z);
9344             return(success);
9345 #endif /* SO_RCVBUF */
9346
9347 #ifdef VMS
9348 #ifdef DEC_TCPIP
9349           case XYTCP_UCX: {             /* UCX 2.0 port swabbing bug */
9350               extern int ucx_port_bug;
9351               return(success = seton(&ucx_port_bug));
9352           }
9353 #endif /* DEC_TCPIP */
9354 #endif /* VMS */
9355
9356           case XYTCP_RDNS: {
9357               extern int tcp_rdns;
9358               return(success = setonaut(&tcp_rdns));
9359           }
9360
9361 #ifdef CK_DNS_SRV
9362           case XYTCP_DNS_SRV: {
9363               extern int tcp_dns_srv;
9364               return(success = seton(&tcp_dns_srv));
9365           }
9366 #endif /* CK_DNS_SRV */
9367
9368           default:
9369             return(0);
9370         }
9371       }
9372 #endif /* TCPSOCKET */
9373 #endif /* NOTCPOPTS */
9374 #endif /* NETCONN */
9375     }
9376
9377     switch (xx) {
9378
9379 #ifndef NOLOCAL
9380 #ifdef NETCONN
9381       case XYHOST: {                    /* SET HOST */
9382           z = ttnproto;                 /* Save protocol in case of failure */
9383 #ifdef DECNET
9384           if (nettype != NET_DEC)
9385 #endif /* DECNET */
9386             ttnproto = NP_NONE;
9387           if ((y = setlin(XYHOST,1,0)) <= 0) { /* Sets success to 1 */
9388               debug(F101,"SET HOST fail mdmtyp","",mdmtyp);
9389               ttnproto = z;             /* Failed, restore protocol */
9390               success = 0;
9391           }
9392           didsetlin++;
9393           debug(F101,"SET HOST OK mdmtyp","",mdmtyp);
9394           debug(F101,"SET HOST reliable","",reliable);
9395           return(y);
9396       }
9397 #endif /* NETCONN */
9398
9399       case XYLINE:                      /* SET LINE (= SET PORT) */
9400         debug(F101,"setlin flow 1","",flow);
9401         x = setlin(xx,1,0);
9402         if (x > -1) didsetlin++;
9403         debug(F101,"SET LINE setlin","",x);
9404         debug(F101,"SET LINE flow","",flow);
9405         debug(F101,"SET LINE local","",local);
9406         debug(F101,"SET LINE reliable","",reliable);
9407         return(x);
9408 #endif /* NOLOCAL */
9409
9410 #ifndef NOSETKEY
9411       case XYKEY:                       /* SET KEY */
9412         return(dosetkey());
9413 #endif /* NOSETKEY */
9414
9415 #ifndef NOCSETS
9416       case XYLANG:                      /* Language */
9417         if ((y = cmkey(lngtab,nlng,"","none",xxstring)) < 0)
9418           return(y);
9419         if ((x = cmcfm()) < 0) return(x);
9420
9421         /* Look up language and get associated character sets */
9422         for (i = 0; (i < nlangs) && (langs[i].id != y); i++) ;
9423         if (i >= nlangs) {
9424             printf("?internal error, sorry\n");
9425             return(success = 0);
9426         } /*  */
9427         language = i;                   /* All good, set the language, */
9428         return(success = 1);
9429 #endif /* NOCSETS */
9430
9431 #ifndef MAC
9432       case XYBACK:                      /* BACKGROUND */
9433         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
9434         if ((y = cmcfm()) < 0) return(y);
9435 #ifdef COMMENT
9436         bgset = z;                      /* 0 = off (foreground) */
9437 #ifdef VMS                              /* 1 = on (background) */
9438         if (batch && bgset == 0)        /* To enable echoing of commands */
9439           ckxech = 1;                   /* in VMS batch logs */
9440 #endif /* VMS */
9441 #else  /* COMMENT */
9442         if (z) {                        /* 1 = Background */
9443             bgset = 1;
9444             backgrd = 1;
9445 #ifdef VMS
9446             batch = 1;
9447 #endif /* VMS */
9448         } else {                        /* 0 = Foreground */
9449             bgset = 0;
9450             backgrd = 0;
9451 #ifdef VMS
9452             batch = 0;
9453 #endif /* VMS */
9454         }
9455 #endif /* COMMENT */
9456         success = 1;
9457         bgchk();
9458         return(success);
9459 #endif /* MAC */
9460
9461       case XYQUIE: {                    /* QUIET */
9462 #ifdef DCMDBUF
9463           extern int * xquiet;
9464 #else
9465           extern int xquiet[];
9466 #endif /* DCMDBUF */
9467           x = seton(&quiet);
9468           if (x < 0) return(x);
9469           xquiet[cmdlvl] = quiet;
9470           return(success = x);
9471       }
9472
9473 #ifndef NOXFER
9474       case XYBUF: {                     /* BUFFERS */
9475 #ifdef DYNAMIC
9476           int sb, rb;
9477           if ((y = cmnum("Send buffer size","",10,&sb,xxstring)) < 0) {
9478               if (y == -3) printf("?Buffer size required\n");
9479               return(y);
9480           }
9481           if (sb < 0) {
9482               if (*atmbuf == '-')
9483                 printf("?Negative numbers can't be used here\n");
9484               else printf("?Integer overflow, use a smaller number please\n");
9485               return(-9);
9486           } else if (sb < 80) {
9487               printf("?Too small\n");
9488               return(-9);
9489           }
9490           if ((y=cmnum("Receive buffer size",ckitoa(sb),10,&rb,xxstring)) < 0)
9491             return(y);
9492           if (rb < 0) {
9493               if (*atmbuf == '-')
9494                 printf("?Negative numbers can't be used here\n");
9495               else printf("?Integer overflow, use a smaller number please\n");
9496               return(-9);
9497           } else if (rb < 80) {
9498               printf("?Too small\n");
9499               return(-9);
9500           }
9501           if ((y = cmcfm()) < 0) return(y);
9502           if ((y = inibufs(sb,rb)) < 0) return(y);
9503           y = adjpkl(urpsiz,wslotr,bigrbsiz); /* Maybe adjust packet sizes */
9504           if (y != urpsiz) urpsiz = y;
9505           y = adjpkl(spsiz,wslotr,bigsbsiz);
9506           if (y != spsiz) spsiz = spmax = spsizr = y;
9507           return(success = 1);
9508 #else
9509           printf("?Sorry, not available\n");
9510           return(success = 0);
9511 #endif /* DYNAMIC */
9512       }
9513
9514       case XYCHKT:                      /* BLOCK-CHECK */
9515         if ((x = cmkey(chktab,4,"","3",xxstring)) < 0) return(x);
9516         if ((y = cmcfm()) < 0) return(y);
9517         bctr = x;                       /* Set local too even if REMOTE SET */
9518         if (rmsflg) {
9519             if (x == 4) {
9520                 tmpbuf[0] = 'B';
9521                 tmpbuf[1] = '\0';
9522             } else
9523               ckstrncpy(tmpbuf,ckitoa(x),TMPBUFSIZ);
9524             sstate = setgen('S', "400", tmpbuf, "");
9525             return((int) sstate);
9526         } else {
9527             return(success = 1);
9528         }
9529 #endif /* NOXFER */
9530
9531 #ifndef NOLOCAL
9532 #ifndef MAC                             /* The Mac has no RS-232 */
9533 case XYCARR:                            /* CARRIER-WATCH */
9534         return(setdcd());
9535 #endif /* MAC */
9536 #endif /* NOLOCAL */
9537     }
9538
9539 #ifdef TNCODE
9540     switch (xx) {                       /* Avoid long switch statements... */
9541       case XYTELOP: {
9542           int c, n;                     /* Workers */
9543           int getval = 0;               /* Whether to get switch value */
9544           int tnserver = 0;             /* Client by default */
9545           int opt = -1;                 /* Telnet Option */
9546           struct FDB sw, op;            /* FDBs for each parse function */
9547 #ifdef CK_AUTHENTICATION
9548           extern int sl_topt_a_s_saved;
9549           extern int sl_topt_a_c_saved;
9550           extern int sl_topt_e_s_saved;
9551           extern int sl_topt_e_c_saved;
9552 #endif /* CK_AUTHENTICATION */
9553 #ifdef IKSD
9554           if (inserver)                 /* Server by default when IKSD */
9555             tnserver = 1;
9556 #endif /* IKSD */
9557
9558           /* Set up chained parse functions... */
9559
9560           cmfdbi(&op,                   /* First fdb - telopts*/
9561                  _CMKEY,                /* fcode */
9562                  "/client, /server or", /* hlpmsg */
9563                  "",                    /* default */
9564                  "",                    /* addtl string data */
9565                  ntnopt,                /* addtl numeric data 1 */
9566                  0,                     /* addtl numeric data 2 */
9567                  xxstring,
9568                  tnopttab,
9569                  &sw
9570                  );
9571           cmfdbi(&sw,                   /* Second FDB - command switches */
9572                  _CMKEY,                /* fcode */
9573                  "",                    /* hlpmsg */
9574                  "",                    /* default */
9575                  "",                    /* addtl string data */
9576                  ntnoptsw,              /* addtl numeric data 1: tbl size */
9577                  4,                     /* addtl numeric data 2: 4 = cmswi */
9578                  xxstring,              /* Processing function */
9579                  tnoptsw,               /* Keyword table */
9580                  NULL                   /* Pointer to next FDB */
9581                  );
9582
9583           while (opt < 0) {             /* Parse 0 or more switches */
9584               x = cmfdb(&op);           /* Parse switch or other thing */
9585               debug(F101,"XYTELOP cmfdb","",x);
9586               if (x < 0)                /* Error */
9587                 return(x);              /* or reparse needed */
9588               if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
9589                 break;
9590               c = cmgbrk();             /* Get break character */
9591               getval = (c == ':' || c == '='); /* see how switch ended */
9592               if (getval && !(cmresult.kflags & CM_ARG)) {
9593                   printf("?This switch does not take arguments\n");
9594                   return(-9);
9595               }
9596               z = cmresult.nresult;     /* Numeric result = switch value */
9597               debug(F101,"XYTELOP switch","",z);
9598
9599               switch (z) {              /* Process the switch */
9600                 case CK_TN_CLIENT:
9601                   tnserver = 0;
9602                   break;
9603                 case CK_TN_SERVER:
9604                   tnserver = 1;
9605                     break;
9606                 case CK_TN_EC:
9607                   opt = TELOPT_ECHO;
9608                   break;
9609                 case CK_TN_TT:
9610                   opt = TELOPT_TTYPE;
9611                   break;
9612                 case CK_TN_BM:
9613                   opt = TELOPT_BINARY;
9614                   break;
9615                 case CK_TN_ENV:
9616                   opt = TELOPT_NEWENVIRON;
9617                   break;
9618                 case CK_TN_LOC:
9619                   opt = TELOPT_SNDLOC;
9620                   break;
9621                 case CK_TN_AU:
9622                   opt = TELOPT_AUTHENTICATION;
9623                   break;
9624                 case CK_TN_FX:
9625                   opt = TELOPT_FORWARD_X;
9626                   break;
9627                 case CK_TN_ENC:
9628                   opt = TELOPT_ENCRYPTION;
9629                   break;
9630                 case CK_TN_IKS:
9631                   opt = TELOPT_KERMIT;
9632                   break;
9633                 case CK_TN_TLS:
9634                   opt = TELOPT_START_TLS;
9635                   break;
9636                 case CK_TN_XD:
9637                   opt = TELOPT_XDISPLOC;
9638                   break;
9639                 case CK_TN_NAWS:
9640                   opt = TELOPT_NAWS;
9641                   break;
9642                 case CK_TN_SGA:
9643                   opt = TELOPT_SGA;
9644                   break;
9645                 case CK_TN_PHR:
9646                   opt = TELOPT_PRAGMA_HEARTBEAT;
9647                   break;
9648                 case CK_TN_PSP:
9649                   opt = TELOPT_SSPI_LOGON;
9650                   break;
9651                 case CK_TN_PLG:
9652                   opt = TELOPT_PRAGMA_LOGON;
9653                   break;
9654                 case CK_TN_SAK:
9655                   opt = TELOPT_IBM_SAK;
9656                   break;
9657                 case CK_TN_CPC:
9658                   opt = TELOPT_COMPORT;
9659                   break;
9660                 case CK_TN_LOG:
9661                   opt = TELOPT_LOGOUT;
9662                   break;
9663                 case CK_TN_FLW:
9664                   opt = TELOPT_LFLOW;
9665                   break;
9666                 default:
9667                   printf("?Unexpected value - %d\n",z);
9668                   return(-9);
9669               }
9670 #ifdef COMMENT
9671               if (cmresult.fdbaddr == &op)
9672                 break;
9673 #endif /* COMMENT */
9674           }
9675           switch (opt) {
9676             case TELOPT_ECHO:           /* Options only the Server WILL */
9677             case TELOPT_FORWARD_X:
9678             case TELOPT_SEND_URL:
9679             case TELOPT_IBM_SAK:
9680             case TELOPT_LOGOUT:
9681               if ((x = cmkey(tnnegtab,
9682                              ntnnegtab,
9683                              "desired server state",
9684    TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
9685                              xxstring)
9686                    ) < 0)
9687                 return(x);
9688               if ((z = cmcfm()) < 0)
9689                   return(z);
9690               if (tnserver) {
9691                   TELOPT_DEF_S_ME_MODE(opt) = x;
9692                   TELOPT_ME_MODE(opt) = x;
9693               } else {
9694                   TELOPT_DEF_C_U_MODE(opt) = x;
9695                   TELOPT_U_MODE(opt) = x;
9696               }
9697               break;
9698
9699             case TELOPT_TTYPE:          /* Options only the Client WILL */
9700             case TELOPT_NEWENVIRON:
9701             case TELOPT_SNDLOC:
9702             case TELOPT_AUTHENTICATION:
9703             case TELOPT_START_TLS:
9704             case TELOPT_XDISPLOC:
9705             case TELOPT_NAWS:
9706             case TELOPT_LFLOW:
9707             case TELOPT_COMPORT:
9708               if ((x = cmkey(tnnegtab,
9709                              ntnnegtab,
9710                              "desired client state",
9711     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
9712                              xxstring)
9713                    ) < 0)
9714                 return(x);
9715               if ((z = cmcfm()) < 0)
9716                 return(z);
9717               if (tnserver) {
9718                   TELOPT_DEF_S_U_MODE(opt) = x;
9719                   TELOPT_U_MODE(opt) = x;
9720 #ifdef CK_AUTHENTICATION
9721                   if (opt == TELOPT_AUTHENTICATION)
9722                     sl_topt_a_s_saved = 0;
9723 #endif /* CK_AUTHENTICATION */
9724               } else {
9725                   TELOPT_DEF_C_ME_MODE(opt) = x;
9726                   TELOPT_ME_MODE(opt) = x;
9727 #ifdef CK_AUTHENTICATION
9728                   if (opt == TELOPT_AUTHENTICATION)
9729                     sl_topt_a_c_saved = 0;
9730 #endif /* CK_AUTHENTICATION */
9731               }
9732               break;
9733
9734             default:
9735               if ((x = cmkey(tnnegtab,
9736                              ntnnegtab,
9737                              tnserver ?
9738                              "desired server state" :
9739                              "desired client state",
9740     TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
9741                              xxstring
9742                              )
9743                    ) < 0)
9744                 return(x);
9745               if ((y = cmkey(tnnegtab,
9746                              ntnnegtab,
9747                              !tnserver ? "desired server state" :
9748                              "desired client state",
9749     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
9750                              xxstring
9751                              )
9752                    ) < 0)
9753                 return(y);
9754               if ((z = cmcfm()) < 0)
9755                 return(z);
9756               if (tnserver) {
9757                   TELOPT_DEF_S_ME_MODE(opt) = x;
9758                   TELOPT_ME_MODE(opt) = x;
9759                   TELOPT_DEF_S_U_MODE(opt) = y;
9760                   TELOPT_U_MODE(opt) = y;
9761 #ifdef CK_ENCRYPTION
9762                   if (opt == TELOPT_ENCRYPTION)
9763                     sl_topt_e_s_saved = 0;
9764 #endif /* CK_ENCRYPTION */
9765               } else {
9766                   TELOPT_DEF_C_ME_MODE(opt) = x;
9767                   TELOPT_ME_MODE(opt) = x;
9768                   TELOPT_DEF_C_U_MODE(opt) = y;
9769                   TELOPT_U_MODE(opt) = y;
9770 #ifdef CK_ENCRYPTION
9771                   if (opt == TELOPT_ENCRYPTION)
9772                     sl_topt_e_c_saved = 0;
9773 #endif /* CK_ENCRYPTION */
9774               }
9775           }
9776           return(success = 1);
9777       }
9778
9779       case XYTEL:                       /* TELNET */
9780         if ((z = cmkey(tntab,ntn,"parameter for TELNET negotiations", "",
9781                        xxstring)) < 0)
9782           return(z);
9783         switch (z) {
9784           case CK_TN_EC:                /* ECHO */
9785             if ((x = cmkey(rltab,nrlt,
9786                            "initial TELNET echoing state",
9787                            "local",xxstring)) < 0)
9788               return(x);
9789             if ((y = cmcfm()) < 0) return(y);
9790             tn_duplex = x;
9791             return(success = 1);
9792
9793           case CK_TN_RE:                /* REMOTE-ECHO */
9794             return(success = seton(&tn_rem_echo));
9795
9796           case CK_TN_DB:                /* DEBUG */
9797             return(success = seton(&tn_deb));
9798
9799           case CK_TN_TT:                /* TERMINAL TYPE */
9800             if ((y = cmtxt("terminal type for TELNET connections","",
9801                            &s,xxstring)) < 0)
9802               return(y);
9803             if (tn_term) {
9804                 free(tn_term);          /* Free any previous storage */
9805                 tn_term = NULL;
9806             }
9807             if (s == NULL || *s == NUL) { /* If none given */
9808                 tn_term = NULL;         /* remove the override string */
9809                 return(success = 1);
9810             } else if ((tn_term = malloc(strlen(s)+1))) {
9811                 strcpy(tn_term,s);
9812                 return(success = 1);
9813             } else return(success = 0);
9814
9815 #ifdef CK_FORWARD_X
9816           case CK_TN_FX:                /* FORWARD-X */
9817             if ((x=cmkey(tnfwdxtab,ntnfwdx,"","xauthority-file",xxstring)) < 0)
9818               return(x);
9819             switch (x) {
9820               case 0: {                 /* Xauthority-File */
9821                   x = cmifi("Full path of .Xauthority file","",&s,&y,xxstring);
9822                   if (x < 0 && x != -3)
9823                     return(x);
9824                   makestr(&tn_fwdx_xauthority,s);
9825                   return(success = 1);
9826               }
9827               case 1: {                 /* No-Encryption */
9828                   extern int fwdx_no_encrypt;
9829                   return(success = seton(&fwdx_no_encrypt));
9830               }
9831             }
9832             return(success = 0);
9833 #endif /* CK_FORWARD_X */
9834
9835           case CK_TN_NL:                /* TELNET NEWLINE-MODE */
9836             if ((x = cmkey(tn_nlmtab,ntn_nlm,"","nvt",xxstring)) < 0)
9837               return(x);
9838             if (x == TN_NL_BIN) {
9839               if ((x = cmkey(tnlmtab,ntnlm,"","raw",xxstring)) < 0)
9840                 return(x);
9841               if ((y = cmcfm()) < 0)
9842                 return(y);
9843               tn_b_nlm = x;
9844               return(success = 1);
9845           } else if (x == TN_NL_NVT) {
9846               if ((x = cmkey(tnlmtab,ntnlm,"","on",xxstring)) < 0)
9847                 return(x);
9848               if ((y = cmcfm()) < 0)
9849                 return(y);
9850               tn_nlm = x;
9851               return(success = 1);
9852           } else {
9853               if ((y = cmcfm()) < 0)
9854                 return(y);
9855               tn_nlm = x;
9856               return(success = 1);
9857           }
9858
9859         case CK_TN_XF:                  /* BINARY-TRANSFER-MODE */
9860             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9861             if ((y = cmcfm()) < 0) return(y);
9862             tn_b_xfer = z;
9863             return(success = 1);
9864
9865         case CK_TN_NE:                  /* NO-ENCRYPT-DURING-XFER */
9866             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9867             if ((y = cmcfm()) < 0) return(y);
9868 #ifdef CK_APC
9869             /* Don't let this be set remotely */
9870             if (apcactive == APC_LOCAL ||
9871                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
9872               return(success = 0);
9873 #endif /* CK_APC */
9874             tn_no_encrypt_xfer = z;
9875             return(success = 1);
9876
9877           case CK_TN_BM:                /* BINARY-MODE */
9878             if ((x = cmkey(tnnegtab,ntnnegtab,"","refused",xxstring)) < 0)
9879               return(x);
9880             if ((y = cmcfm()) < 0)
9881               return(y);
9882             TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = x;
9883             TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = x;
9884             TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = x;
9885             TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = x;
9886             return(success = 1);
9887
9888 #ifdef IKS_OPTION
9889           case CK_TN_IKS:               /* KERMIT */
9890             if ((x = cmkey(tnnegtab,ntnnegtab,"DO","accept",xxstring)) < 0)
9891               return(x);
9892             if ((y = cmkey(tnnegtab,ntnnegtab,"WILL","accept",xxstring)) < 0)
9893               return(y);
9894             if ((z = cmcfm()) < 0)
9895               return(z);
9896             TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = y;
9897             TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = x;
9898             TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = y;
9899             TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = x;
9900             return(success = 1);
9901 #endif /* IKS_OPTION */
9902
9903 #ifdef CK_SSL
9904           case CK_TN_TLS:               /* START_TLS */
9905             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
9906               return(x);
9907             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
9908               return(y);
9909             if ((z = cmcfm()) < 0)
9910               return(z);
9911             TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = x;
9912             TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = y;
9913             TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = x;
9914             TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = y;
9915             return(success = 1);
9916 #endif /* CK_SSL */
9917
9918 #ifdef CK_NAWS
9919           case CK_TN_NAWS:              /* NAWS */
9920             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
9921               return(x);
9922             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
9923               return(y);
9924             if ((z = cmcfm()) < 0)
9925               return(z);
9926             TELOPT_DEF_S_ME_MODE(TELOPT_NAWS) = x;
9927             TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = y;
9928             TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = x;
9929             TELOPT_DEF_C_U_MODE(TELOPT_NAWS) = y;
9930             return(success = 1);
9931 #endif /* CK_NAWS */
9932
9933 #ifdef CK_AUTHENTICATION
9934           case CK_TN_AU:                /* AUTHENTICATION */
9935             if ((x = cmkey(tnauthtab,ntnauth,"","",xxstring)) < 0)
9936               return(x);
9937             if (x == TN_AU_FWD) {
9938                 extern int forward_flag;
9939                 return(success = seton(&forward_flag));
9940             } else if (x == TN_AU_TYP) {
9941                 extern int auth_type_user[];
9942                 extern int sl_auth_type_user[];
9943                 extern int sl_auth_saved;
9944                 int i, j, atypes[AUTHTYPLSTSZ];
9945
9946                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
9947                     if ((y = cmkey(autyptab,nautyp,"",
9948                                    i == 0 ? "automatic" : "" ,
9949                                    xxstring)) < 0) {
9950                         if (y == -3)
9951                           break;
9952                         return(y);
9953                     }
9954                     if (i > 0 && (y == AUTHTYPE_AUTO || y == AUTHTYPE_NULL)) {
9955                         printf(
9956                         "\r\n?Choice may only be used in first position.\r\n");
9957                         return(-9);
9958                     }
9959                     for (j = 0; j < i; j++) {
9960                         if (atypes[j] == y) {
9961                             printf("\r\n?Choice has already been used.\r\n");
9962                             return(-9);
9963                         }
9964                     }
9965                     atypes[i] = y;
9966                     if (y == AUTHTYPE_NULL || y == AUTHTYPE_AUTO) {
9967                         i++;
9968                         break;
9969                     }
9970                 }
9971                 if (i < AUTHTYPLSTSZ)
9972                   atypes[i] = AUTHTYPE_NULL;
9973                 if ((z = cmcfm()) < 0)
9974                   return(z);
9975                 sl_auth_saved = 0;
9976                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
9977                     auth_type_user[i] = atypes[i];
9978                     sl_auth_type_user[i] = 0;
9979                 }
9980             } else if (x == TN_AU_HOW) {
9981                 if ((y = cmkey(auhowtab,nauhow,"","any",xxstring)) < 0)
9982                   return(y);
9983                 if ((z = cmcfm()) < 0)
9984                   return(z);
9985                 tn_auth_how = y;
9986             } else if (x == TN_AU_ENC) {
9987                 if ((y = cmkey(auenctab,nauenc,"","encrypt",xxstring)) < 0)
9988                   return(y);
9989                 if ((z = cmcfm()) < 0)
9990                   return(z);
9991                 tn_auth_enc = y;
9992             } else {
9993                 if ((y = cmcfm()) < 0)
9994                   return(y);
9995                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = x;
9996                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = x;
9997             }
9998             return(success = 1);
9999 #endif /* CK_AUTHENTICATION */
10000
10001 #ifdef CK_ENCRYPTION
10002           case CK_TN_ENC: {             /* ENCRYPTION */
10003               int c, tmp = -1;
10004               int getval = 0;
10005               static struct keytab * tnetbl = NULL;
10006               static int ntnetbl = 0;
10007
10008               if ((y = cmkey(tnenctab,ntnenc,"","",xxstring)) < 0)
10009                 return(y);
10010               switch (y) {
10011                 case TN_EN_TYP:
10012                   x = ck_get_crypt_table(&tnetbl,&ntnetbl);
10013                   debug(F101,"ck_get_crypt_table x","",x);
10014                   debug(F101,"ck_get_crypt_table n","",ntnetbl);
10015                   if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
10016                     x = 0;
10017                   if (!x) {
10018                       printf("?Oops, types not loaded\n");
10019                       return(-9);
10020                   }
10021                   if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
10022                                  "automatic",xxstring)) < 0)
10023                     return(x);
10024                   if ((z = cmcfm()) < 0)
10025                     return(z);
10026                   cx_type = x;
10027                   sl_cx_type = 0;
10028                   break;
10029                 case TN_EN_START:
10030                   if ((z = cmcfm()) < 0)
10031                     return(z);
10032 #ifdef CK_APC
10033                   /* Don't let this be set remotely */
10034                   if (apcactive == APC_LOCAL ||
10035                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10036                     return(success = 0);
10037 #endif /* CK_APC */
10038                   ck_tn_enc_start();
10039                   break;
10040                 case TN_EN_STOP:
10041                   if ((z = cmcfm()) < 0)
10042                     return(z);
10043 #ifdef CK_APC
10044                   /* Don't let this be set remotely */
10045                   if (apcactive == APC_LOCAL ||
10046                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10047                     return(success = 0);
10048 #endif /* CK_APC */
10049                   ck_tn_enc_stop();
10050                   break;
10051                 default:
10052                   if ((z = cmcfm()) < 0)
10053                     return(z);
10054                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = y;
10055                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = y;
10056                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = y;
10057                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = y;
10058               }
10059               return(success = 1);
10060           }
10061 #endif /* CK_ENCRYPTION */
10062
10063           case CK_TN_BUG:               /* BUG */
10064             if ((x = cmkey(tnbugtab,4,"",
10065                            "binary-me-means-u-too",xxstring)) < 0)
10066               return(x);
10067             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
10068             if ((y = cmcfm()) < 0) return(y);
10069             switch (x) {
10070               case 0:
10071                 tn_b_meu = z;
10072                 break;
10073               case 1:
10074                 tn_b_ume = z;
10075                 break;
10076               case 2:
10077                 tn_infinite = z;
10078                 break;
10079               case 3:
10080                 tn_sb_bug = z;
10081                 break;
10082               case 4:
10083                 tn_auth_krb5_des_bug = z;
10084                 break;
10085             }
10086             return(success = 1);
10087
10088 #ifdef CK_ENVIRONMENT
10089           case CK_TN_XD:                /* XDISPLOC */
10090             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10091               return(x);
10092             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10093               return(y);
10094             if ((z = cmcfm()) < 0)
10095               return(z);
10096             TELOPT_DEF_S_ME_MODE(TELOPT_XDISPLOC) = x;
10097             TELOPT_DEF_S_U_MODE(TELOPT_XDISPLOC) = y;
10098             TELOPT_DEF_C_ME_MODE(TELOPT_XDISPLOC) = x;
10099             TELOPT_DEF_C_U_MODE(TELOPT_XDISPLOC) = y;
10100             return(success = 1);
10101
10102           case CK_TN_ENV: {
10103               char * msg = "value of telnet environment variable";
10104               extern int tn_env_flg;
10105               extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
10106               tn_env_prnt[], tn_env_sys[];
10107               extern char * tn_loc;
10108               if ((x = cmkey(tnenvtab,ntnenv,"","",xxstring)) < 0)
10109                 return(x);
10110               if (x == TN_ENV_UVAR) {   /* User variables */
10111                   char * uvar=NULL;
10112                   char * uval=NULL;
10113                   char * env;
10114                   extern char * tn_env_uservar[8][2];
10115
10116                   /* Get the user variable name */
10117                   if ((x = cmfld("Name of Environment Variable","",&s,
10118                                  xxstring)) < 0)
10119                     return(x);
10120                   makestr(&uvar,s);
10121
10122                   env = getenv(uvar);
10123                   if (!env) env = "";
10124
10125                   if ((x = cmtxt("Value of Environment Variable",env,
10126                                  &s,xxstring)) < 0)
10127                     return(x);
10128                   if (*s)
10129                     makestr(&uval,s);
10130
10131                   /* Now that we have the variable and perhaps a value */
10132                   /* there are three possibilities: (1) new variable   */
10133                   /* and associated value; (2) variable already exists */
10134                   /* but we have a new value; (3) variable already     */
10135                   /* exists but no new value therefore the user wants  */
10136                   /* to clear variable.                                */
10137
10138                   /* Try to find an existing variable */
10139                   for (x = 0; x < 8; x++) {
10140                       if (!ckstrcmp(tn_env_uservar[x][0],uvar,-1,0)) {
10141                           if (uval) {
10142                               free(tn_env_uservar[x][1]);
10143                               tn_env_uservar[x][1] = uval;
10144                               free(uvar);
10145                               return(success = 1);
10146                           } else {
10147                               free(tn_env_uservar[x][0]);
10148                               tn_env_uservar[x][0] = NULL;
10149                               free(tn_env_uservar[x][1]);
10150                               tn_env_uservar[x][1] = NULL;
10151                               free(uvar);
10152                               return(success = 1);
10153                           }
10154                       }
10155                   }
10156
10157                   /* Couldn't find one; look for empty location to insert */
10158                   for (x = 0; x < 8; x++) {
10159                       if (!tn_env_uservar[x][0]) {
10160                           tn_env_uservar[x][0] = uvar;
10161                           tn_env_uservar[x][1] = uval;
10162                           return(success = 1);
10163                       }
10164                   }
10165                   printf("?Sorry, no space for variable.\n");
10166                   return(success = 0);
10167               }
10168               if (x == TN_ENV_OFF || x == TN_ENV_ON) {
10169                   if ((y = cmcfm()) < 0) return(y);
10170 #ifdef IKSD
10171                   if (inserver) {
10172                       printf("?Sorry, command disabled.\r\n");
10173                       return(success = 0);
10174                   }
10175 #endif /* IKSD */
10176                   tn_env_flg = x == TN_ENV_OFF ? 0 : 1;
10177                   return(success = 1);
10178               }
10179
10180               /* Not ON/OFF - Get the value */
10181               z = cmdgquo();
10182               cmdsquo(0);
10183               if ((y = cmtxt(msg, "", &s, xxstring)) < 0) {
10184                   cmdsquo(z);
10185                   return(y);
10186               }
10187               cmdsquo(z);
10188 #ifdef IKSD
10189               if (inserver)
10190                 return(success = 0);
10191 #endif /* IKSD */
10192               if ((int)strlen(s) > 63) {
10193                   printf("Sorry, too long\n");
10194                   return(-9);
10195               }
10196               switch (x) {
10197                 case TN_ENV_USR:
10198                   ckstrncpy(uidbuf,s,UIDBUFLEN);
10199                   sl_uid_saved = 0;
10200                   break;
10201                 case TN_ENV_ACCT:
10202                   ckstrncpy(tn_env_acct,s,64);
10203                   break;
10204                 case TN_ENV_DISP:
10205                   ckstrncpy(tn_env_disp,s,64);
10206                   break;
10207                 case TN_ENV_JOB:
10208                   ckstrncpy(tn_env_job,s,64);
10209                   break;
10210                 case TN_ENV_PRNT:
10211                   ckstrncpy(tn_env_prnt,s,64);
10212                   break;
10213                 case TN_ENV_SYS:
10214                   ckstrncpy(tn_env_sys,s,64);
10215                   break;
10216                 case TN_ENV_LOC:
10217                   if (!*s) s = NULL;
10218                   makestr(&tn_loc,s);
10219                   break;
10220                 case TN_ENV_UVAR:
10221                   printf("\n?Not yet implemented\n");
10222                   break;
10223               }
10224               return(success = 1);
10225           }
10226 #endif /* CK_ENVIRONMENT */
10227
10228 #ifdef CK_SNDLOC
10229           case CK_TN_LOC: {             /* LOCATION */
10230               extern char * tn_loc;
10231               if ((y = cmtxt("Location string","",&s,xxstring)) < 0)
10232                 return(y);
10233               if (!*s) s = NULL;
10234               makestr(&tn_loc,s);
10235               return(success = 1);
10236           }
10237 #endif /* CK_SNDLOC */
10238           case CK_TN_SFU:               /* Microsoft SFU compatibility */
10239             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10240             if ((y = cmcfm()) < 0) return(y);
10241             tn_sfu = z;
10242             return(success = 1);
10243             break;
10244
10245           case CK_TN_WAIT:              /* WAIT-FOR-NEGOTIATIONS */
10246             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10247             if ((y = cmcfm()) < 0) return(y);
10248 #ifdef IKSD
10249             if (inserver &&
10250 #ifdef IKSDCONF
10251                 iksdcf
10252 #else
10253                 1
10254 #endif /* IKSDCONF */
10255                 ) {
10256                 printf("?Sorry, command disabled.\r\n");
10257                 return(success = 0);
10258             }
10259 #endif /* IKSD */
10260             tn_wait_flg = z;
10261             sl_tn_saved = 0;
10262             return(success = 1);
10263
10264           case CK_TN_DL:                /* DELAY SUBNEGOTIATIONS */
10265             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10266             if ((y = cmcfm()) < 0) return(y);
10267 #ifdef IKSD
10268             if (inserver &&
10269 #ifdef IKSDCONF
10270                 iksdcf
10271 #else
10272                 1
10273 #endif /* IKSDCONF */
10274                 ) {
10275                 printf("?Sorry, command disabled.\r\n");
10276                 return(success = 0);
10277             }
10278 #endif /* IKSD */
10279             tn_delay_sb = z;
10280             return(success = 1);
10281
10282           case CK_TN_PUID: {            /* PROMPT-FOR-USERID */
10283               int i,len;
10284               if ((y = cmtxt("Prompt string","",&s,xxstring)) < 0)
10285                 return(y);
10286               if (s == "") s = NULL;
10287               if (s) {
10288                   s = brstrip(s);
10289                   if (s == "") s = NULL;
10290               }
10291               /* we must check to make sure there are no % fields */
10292               len = strlen(s);
10293               for (i = 0; i < len; i++) {
10294                   if (s[i] == '%') {
10295                       if (s[i+1] != '%') {
10296                           printf("%% fields are not used in this command.\n");
10297                           return(-9);
10298                       }
10299                       i++;
10300                   }
10301               }
10302               makestr(&tn_pr_uid,s);
10303               return(success = 1);
10304           }
10305           default:
10306             return(-2);
10307         }
10308     }
10309 #endif /* TNCODE */
10310
10311     switch (xx) {
10312 #ifndef NOSPL
10313       case XYCOUN:                      /* SET COUNT */
10314         x = cmnum("Positive number","0",10,&z,xxstring);
10315         if (x < 0) return(x);
10316         if ((x = cmcfm()) < 0) return(x);
10317         if (z < 0) {
10318             printf("?A positive number, please\n");
10319             return(0);
10320         }
10321         debug(F101,"XYCOUN: z","",z);
10322         return(success = setnum(&count[cmdlvl],z,0,10000));
10323 #endif /* NOSPL */
10324
10325 #ifndef NOSPL
10326       case XYCASE:
10327         return(success = seton(&inpcas[cmdlvl]));
10328 #endif /* NOSPL */
10329
10330       case XYCMD:                       /* COMMAND ... */
10331         if ((y = cmkey(scmdtab,nbytt,"","",xxstring)) < 0)
10332           return(y);
10333         switch (y) {
10334           case SCMD_CBR:
10335             if ((y = cmcfm()) < 0)
10336               return(y);
10337             concb((char)escape);
10338             return(success = 1);
10339
10340           case SCMD_BSZ:
10341             if ((y = cmnum("bytesize for command characters, 7 or 8","7",10,&x,
10342                            xxstring)) < 0)
10343               return(y);
10344             if (x != 7 && x != 8) {
10345                 printf("\n?The choices are 7 and 8\n");
10346                 return(success = 0);
10347             }
10348             if ((y = cmcfm()) < 0) return(y);
10349             if (x == 7) cmdmsk = 0177;
10350             else if (x == 8) cmdmsk = 0377;
10351             return(success = 1);
10352 #ifdef CK_RECALL
10353           case SCMD_RCL:
10354             if ((y = cmnum("maximum number of commands in recall buffer","10",
10355                            10,&x,xxstring)) < 0)
10356               return(y);
10357             if ((y = cmcfm()) < 0) return(y);
10358             return(success = cmrini(x));
10359 #endif /* CK_RECALL */
10360 #ifdef CK_RECALL
10361           case SCMD_RTR:
10362             return(success = seton(&cm_retry));
10363 #endif /* CK_RECALL */
10364           case SCMD_MOR:                /* More-prompting */
10365             success = seton(&xaskmore);
10366             if (success)
10367               saveask = xaskmore;
10368             return(success);
10369           case SCMD_QUO:
10370             if ((x = seton(&y)) < 0) return(x);
10371             cmdsquo(y);                 /* Do it the right way */
10372             cmd_quoting = y;            /* Also keep a global copy */
10373             /* Set string-processing function */
10374 #ifdef datageneral
10375             xxstring = y ? zzstring : (xx_strp) NULL;
10376 #else
10377 #ifdef CK_ANSIC
10378             xxstring = y ? zzstring : (xx_strp) NULL;
10379 #else
10380             xxstring = y ? zzstring : (xx_strp) NULL;
10381 #endif /* CK_ANSIC */
10382 #endif /* datageneral */
10383             return(success = 1);
10384
10385 #ifdef OS2
10386 #ifndef NOLOCAL
10387           case SCMD_COL: {              /* Command-screen colors */
10388               int fg, bg;
10389               fg = cmkey(ttyclrtab, nclrs,
10390                          "foreground color and then background color",
10391                          "white",
10392                          xxstring);
10393               if (fg < 0)
10394                 return(fg);
10395               if ((bg = cmkey(ttyclrtab,nclrs,
10396                               "background color","black",xxstring)) < 0)
10397                 return(bg);
10398               if ((y = cmcfm()) < 0)
10399                 return(y);
10400               colorcmd = fg | bg << 4;
10401               return(success = 1);
10402           }
10403           case SCMD_SCR:                /* Command Scrollback size */
10404             if ((y = cmnum("COMMAND scrollback buffer size, lines","512",10,&x,
10405                            xxstring)) < 0)
10406               return(y);
10407             /* The max number of lines is the RAM  */
10408             /* we can actually dedicate to a       */
10409             /* scrollback buffer given the maximum */
10410             /* process memory space of 512MB       */
10411             if (x < 256 || x > 2000000L) {
10412                 printf("\n?The size must be between 256 and 2,000,000.\n");
10413                 return(success = 0);
10414             }
10415             if ((y = cmcfm()) < 0) return(y);
10416             tt_scrsize[VCMD] = x;
10417             VscrnInit( VCMD );
10418             return(success = 1);
10419
10420           case SCMD_WID: {
10421               if ((y = cmnum("Number of columns in display window",
10422                          "80",10,&x,xxstring)) < 0)
10423                 return(y);
10424               if ((y = cmcfm()) < 0) return(y);
10425
10426               os2_setcmdwidth(x);
10427               return(success = 1);
10428           }
10429           case SCMD_HIG:
10430             if ((y = cmnum("Number of rows in display window",
10431                            "24",10,&x,xxstring)) < 0)
10432               return(y);
10433             if ((y = cmcfm()) < 0) return(y);
10434             os2_setcmdheight(x);
10435             return(success = 1);
10436
10437           case SCMD_STA: {
10438               extern int marginbot;
10439               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
10440               if ((x = cmcfm()) < 0) return(x);
10441               if (y != tt_status[VCMD]) {
10442                   /* Might need to fixup the margins */
10443                   tt_status[VCMD] = y;
10444                   if (y) {
10445                       tt_szchng[VCMD] = 2;
10446                       tt_rows[VCMD]--;
10447                       cmd_rows--;
10448                       VscrnInit(VCMD);  /* Height set here */
10449                       printf("\n");
10450                   } else {
10451                       tt_szchng[VCMD] = 1;
10452                       tt_rows[VCMD]++;
10453                       cmd_rows++;
10454                       VscrnInit(VCMD);  /* Height set here */
10455                   }
10456               }
10457               return(success = 1);
10458           }
10459
10460           case SCMD_CUR: {
10461               int row, col;
10462               position * ppos;
10463
10464               ppos = VscrnGetCurPos(VCMD);
10465 #ifdef NT
10466 #define itoa _itoa
10467 #endif /* NT */
10468               itoa(ppos->y+1, tmpbuf, 10);
10469               if ((y = cmnum("row (1-based)",tmpbuf,10,&row,xxstring)) < 0)
10470                 return(y);
10471
10472               itoa(ppos->x+1, tmpbuf, 10);
10473               if ((y = cmnum("col (1-based)",tmpbuf,10,&col,xxstring)) < 0)
10474                 return(y);
10475               if ((x = cmcfm()) < 0) return(x);
10476
10477               lgotoxy( VCMD, col, row ) ;
10478               VscrnIsDirty( VCMD );
10479               return(success=1);
10480           }
10481 #endif /* NOLOCAL */
10482 #else
10483           case SCMD_WID:
10484             y = cmnum("Command screen width, characters","80",10,&x,xxstring);
10485             return(setnum(&cmd_cols,x,y,1024));
10486
10487           case SCMD_HIG:
10488             y = cmnum("Command screen height, rows","24",10,&x,xxstring);
10489             return(setnum(&cmd_rows,x,y,1024));
10490 #endif /* OS2 */
10491
10492           case SCMD_INT:
10493             return(seton(&cmdint));
10494
10495 #ifdef CK_AUTODL
10496           case SCMD_ADL:
10497             return(seton(&cmdadl));
10498 #endif /* CK_AUTODL */
10499
10500 #ifdef DOUBLEQUOTING
10501           case SCMD_DBQ: {
10502               extern int dblquo;
10503               return(seton(&dblquo));
10504           }
10505 #endif /* DOUBLEQUOTING */
10506
10507           default:
10508             return(-2);
10509         }
10510     }
10511
10512     switch (xx) {
10513
10514       case XYDFLT:                      /* SET DEFAULT = CD */
10515         return(success = docd(XXCWD));
10516
10517 case XYDEBU:                            /* SET DEBUG { on, off, session } */
10518         if ((y = cmkey(dbgtab,ndbg,"","",xxstring)) < 0)
10519           return(y);
10520         if (y == DEB_TIM)
10521 #ifdef COMMENT
10522           return(seton(&debtim) < 0 ? x : (success = 1));
10523 #else
10524           /* why this change? */
10525           return(success = seton(&debtim));
10526 #endif /* COMMENT */
10527
10528 #ifdef IKSD
10529         if (inserver && isguest) {
10530             printf("?Sorry, command disabled.\r\n");
10531             return(success = 0);
10532     }
10533 #endif /* IKSD */
10534
10535         switch (y) {
10536           case DEB_LEN:
10537             y = cmnum("Max length for debug log strings","",10,&x,xxstring);
10538             if ((z = setnum(&debxlen,x,y,-1)) < 0)
10539               return(z);
10540             if ((x = cmcfm()) < 0)
10541               return(x);
10542             return(success = 1);
10543
10544           case DEB_OFF:
10545             if ((x = cmcfm()) < 0)
10546               return(x);
10547 #ifndef NOLOCAL
10548             setdebses(0);
10549 #endif /* NOLOCAL */
10550 #ifdef DEBUG
10551             if (deblog) doclslog(LOGD);
10552 #endif /* DEBUG */
10553             return(success = 1);
10554
10555           case DEB_ON:
10556             if ((x = cmcfm()) < 0)
10557               return(x);
10558 #ifdef DEBUG
10559             deblog = debopn("debug.log", 0);
10560             return(success = deblog ? 1 : 0);
10561 #else
10562             printf("?Sorry, debug log feature not enabled\n");
10563             return(success = 0);
10564 #endif /* DEBUG */
10565           case DEB_SES:
10566             if ((x = cmcfm()) < 0)
10567               return(x);
10568 #ifndef NOLOCAL
10569             setdebses(1);
10570 #endif /* NOLOCAL */
10571             return(success = 1);
10572         }
10573         break;
10574
10575 #ifndef NOXFER
10576       case XYDELA:                      /* SET DELAY */
10577         y = cmnum("Number of seconds before starting to send",
10578                   "5",10,&x,xxstring);
10579         if (x < 0) x = 0;
10580         return(success = setnum(&ckdelay,x,y,999));
10581 #endif /* NOXFER */
10582
10583       default:
10584         break;
10585     }
10586
10587     switch (xx) {
10588 #ifdef CK_TAPI
10589       case XYTAPI:
10590         return(settapi());
10591 #endif /* CK_TAPI */
10592 #ifndef NODIAL
10593       case XYDIAL:                      /* SET MODEM or SET DIAL */
10594         return(setdial(-1));
10595       case XYMODM:
10596         return(setmodem());
10597 #ifdef COMMENT
10598       /* not implemented yet */
10599       case XYANSWER:                    /* SET ANSWER */
10600         return(setanswer());
10601 #endif /* COMMENT */
10602 #endif /* NODIAL */
10603
10604 #ifndef NOLOCAL
10605       case XYDUPL:                      /* SET DUPLEX */
10606         if ((y = cmkey(dpxtab,2,"","full",xxstring)) < 0) return(y);
10607         if ((x = cmcfm()) < 0) return(x);
10608         duplex = y;
10609         return(success = 1);
10610
10611       case XYLCLE:                      /* LOCAL-ECHO (= DUPLEX) */
10612         return(success = seton(&duplex));
10613
10614       case XYESC:                       /* SET ESCAPE */
10615         return(success = setcc(ckitoa(DFESC),&escape));
10616 #endif /* NOLOCAL */
10617
10618       case XYEXIT:                      /* SET EXIT */
10619         if ((z = cmkey(xittab,nexit,"","",xxstring)) < 0)
10620           return(z);
10621         switch (z) {
10622           case 0:                       /* STATUS */
10623             y = cmnum("EXIT status code","",10,&x,xxstring);
10624             return(success = setnum(&xitsta,x,y,-1));
10625           case 1:                       /* WARNING */
10626             if ((z = cmkey(xitwtab,nexitw,"","",xxstring)) < 0)
10627               return(z);
10628             if ((y = cmcfm()) < 0) return(y);
10629             setexitwarn(z);
10630             return(success = 1);
10631           case 2:
10632             success = seton(&exitonclose);
10633 #ifdef TCPSOCKET
10634             if (success) tn_exit = exitonclose;
10635 #endif /* TCPSOCKET */
10636             return(success);
10637           case 3: {
10638               extern int exithangup;
10639               return((success = seton(&exithangup)));
10640           }
10641           default:
10642             return(-2);
10643         } /* End of SET EXIT switch() */
10644       default:
10645         break;
10646     }
10647
10648     switch (xx) {
10649
10650       case XYFILE:                      /* SET FILE */
10651         return(setfil(rmsflg));
10652
10653       case XYFLOW: {                    /* FLOW-CONTROL */
10654           extern int cxflow[];
10655           struct FDB k1, k2;
10656           int tncomport = 0;
10657           char * m;
10658
10659 #ifdef TN_COMPORT
10660           if (network && istncomport())
10661             tncomport = 1;
10662 #endif /* TN_COMPORT */
10663
10664           if (tncomport) {
10665               m = "Flow control type, one of the following:\n\
10666    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
10667  or connection type";
10668           } else {
10669           /* All this is because chained FDB's don't give chained help yet */
10670               m =
10671 #ifdef Plan9
10672 #ifdef CK_RTSCTS
10673            "Flow control type, one of the following:\n\
10674    keep   none    rts/cts\n\
10675  or connection type",
10676 #else
10677            "Flow control type, one of the following:\n\
10678    keep   none\n\
10679  or connection type";
10680 #endif /* CK_RTSCTS */
10681 #else
10682 #ifdef CK_RTSCTS
10683 #ifdef CK_DTRCD
10684 #ifdef CK_DTRCTS
10685            "Flow control type, one of the following:\n\
10686    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
10687  or connection type";
10688 #else /* CK_DTRCTS */
10689            "Flow control type, one of the following:\n\
10690    dtr/cd    keep    none    rts/cts   xon/xoff\n\
10691             or connection type";
10692 #endif /* CK_DTRCTS */
10693 #else /* CK_DTRCD */
10694 #ifdef CK_DTRCTS
10695            "Flow control type, one of the following:\n\
10696    dtr/cts   keep   none    rts/cts   xon/xoff\n\
10697  or connection type";
10698 #else /* CK_DTRCTS */
10699            "Flow control type, one of the following:\n\
10700    keep   none    rts/cts   xon/xoff\n\
10701  or connection type";
10702 #endif /* CK_DTRCTS */
10703 #endif /* CK_DTRCD */
10704 #else
10705            "Flow control type, one of the following:\n\
10706    keep   none    xon/xoff\n\
10707  or connection type";
10708 #endif /* CK_RTSCTS */
10709 #endif /* Plan9 */
10710           }
10711           cmfdbi(&k1,_CMKEY,m,"","",ncxtypesw, 4, xxstring, cxtypesw, &k2);
10712           cmfdbi(&k2,
10713                  _CMKEY,
10714                  "",
10715                  "",
10716                  "",
10717 #ifdef TN_COMPORT
10718                  (tncomport ? ntnflo : nflo),
10719 #else
10720                  nflo,
10721 #endif /* TN_COMPORT */
10722                  0,
10723                  xxstring,
10724 #ifdef TN_COMPORT
10725                  (tncomport ? tnflotab : flotab),
10726 #else
10727                  flotab,
10728 #endif /* TN_COMPORT */
10729                  NULL
10730                  );
10731           x = cmfdb(&k1);
10732           if (x < 0) {                  /* Error */
10733               if (x == -2 || x == -9)
10734                 printf("?No keywords or switches match: \"%s\"\n",atmbuf);
10735               return(x);
10736           }
10737           z = cmresult.nresult;         /* Keyword value */
10738           if (cmresult.fdbaddr == &k2) { /* Flow-control type keyword table */
10739               if ((x = cmcfm()) < 0)    /* Set it immediately */
10740                 return(x);
10741               flow = z;
10742               debug(F101,"set flow","",flow);
10743 #ifdef CK_SPEED
10744               if (flow == FLO_XONX)     /* Xon/Xoff forces prefixing */
10745                 ctlp[XON] = ctlp[XOFF] = ctlp[XON+128] = ctlp[XOFF+128] = 1;
10746 #endif /* CK_SPEED */
10747               autoflow = (flow == FLO_AUTO);
10748               return(success = 1);      /* Done */
10749           }
10750           debug(F101,"set flow /blah 1","",z); /* SET FLOW /for-what */
10751           if ((y = cmkey(flotab,nflo,"Flow control type","none",xxstring)) < 0)
10752             return(y);
10753           if ((x = cmcfm()) < 0)
10754             return(x);
10755           debug(F101,"set flow /blah 2","",y);
10756           if (y == FLO_AUTO) {
10757               printf(
10758   "?Sorry, \"automatic\" can not be assigned to a connection type.\n");
10759               return(-9);
10760           } else if (z >= 0 && z <= CXT_MAX)
10761             cxflow[z] = y;
10762           debug(F101,"set flow","",flow);
10763           debug(F101,"set flow autoflow","",autoflow);
10764           return(success = 1);
10765       }
10766
10767       case XYHAND:                      /* HANDSHAKE */
10768         if ((y = cmkey(hshtab,nhsh,"","none",xxstring)) < 0) return(y);
10769         if (y == 998) {
10770             if ((x = cmnum("ASCII value","",10,&y,xxstring)) < 0)
10771               return(x);
10772             if ((y < 1) || ((y > 31) && (y != 127))) {
10773                 printf("?Character must be in ASCII control range\n");
10774                 return(-9);
10775             }
10776         }
10777         if ((x = cmcfm()) < 0) return(x);
10778         turn = (y > 0127) ? 0 : 1;
10779         turnch = y;
10780         return(success = 1);
10781
10782 #ifndef NOSPL
10783       case XYMACR:                      /* SET MACRO */
10784         if ((y = cmkey(smactab,2,"","",xxstring)) < 0) return(y);
10785         switch (y) {
10786           case 0: return(success = seton(&mecho));
10787           case 1: return(success = seton(&merror[cmdlvl]));
10788           default: return(-2);
10789         }
10790 #endif /* NOSPL */
10791
10792       case XYMSGS:
10793 #ifdef VMS
10794         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
10795         if ((y = cmcfm()) < 0) return(y);
10796         vms_msgs = z;
10797         printf("Sorry, SET MESSAGES not implemented yet\n");
10798         return(success = 0);
10799 #endif /* VMS */
10800       default:
10801         break;
10802     }
10803
10804     switch (xx) {
10805
10806       case XYPARI:                      /* PARITY */
10807         if ((y = cmkey(partbl,npar,"","none",xxstring)) < 0)
10808           return(y);
10809
10810         /* If parity not none, then we also want 8th-bit prefixing */
10811
10812 #ifdef HWPARITY
10813         if (y == 'H') {                 /* Hardware */
10814             if ((x = cmkey(hwpartbl,nhwpar,"","even",xxstring)) < 0)
10815               return(x);
10816         }
10817 #endif /* HWPARITY */
10818
10819         if ((z = cmcfm()) < 0)
10820           return(z);
10821
10822 #ifdef HWPARITY
10823         if (y == 'H') {                 /* 8 data bits plus hardware parity */
10824             parity = 0;
10825 #ifndef NOXFER
10826             ebqflg = 0;
10827 #endif /* NOXFER */
10828             hwparity = x;
10829         } else {                        /* 7 data bits + software parity */
10830             hwparity = 0;
10831 #endif /* HWPARITY */
10832             parity = y;
10833 #ifndef NOXFER
10834             ebqflg = (parity) ? 1 : 0;
10835 #endif /* NOXFER */
10836 #ifdef HWPARITY
10837         }
10838 #endif /* HWPARITY */
10839
10840 #ifdef TN_COMPORT
10841         if (network && istncomport())
10842           tnsettings(parity, 0);
10843 #endif /* TN_COMPORT */
10844
10845         return(success = 1);
10846
10847 #ifndef NOFRILLS
10848       case XYPROM:                      /* SET PROMPT */
10849 /*
10850   Note: xxstring not invoked here.  Instead, it is invoked every time the
10851   prompt is issued.  This allows the prompt string to contain variables
10852   that can change, like \v(dir), \v(time), etc.
10853 */
10854         ckmakmsg(line,                  /* Default might have trailing space */
10855                  LINBUFSIZ,
10856                  "{",
10857                  inserver ? ikprompt : ckprompt,
10858                  "}",
10859                  NULL
10860                  );
10861         if ((x = cmtxt("Program's command prompt",line,&s,NULL)) < 0)
10862           return(x);
10863         s = brstrip(s);                 /* Remove enclosing braces, if any */
10864         cmsetp(s);                      /* Set the prompt */
10865         return(success = 1);
10866 #endif /* NOFRILLS */
10867
10868 #ifndef NOXFER
10869       case XYRETR:                      /* RETRY: per-packet retry limit */
10870         y = cmnum("Maximum retries per packet","10",10,&x,xxstring);
10871         if (x < 0) x = 0;
10872         if ((x = setnum(&maxtry,x,y,999)) < 0) return(x);
10873 #ifdef COMMENT
10874         if (maxtry <= wslotr) {
10875             printf("?Retry limit must be greater than window size\n");
10876             return(success = 0);
10877         }
10878 #endif /* COMMENT */
10879         if (rmsflg) {
10880             sstate = setgen('S', "403", ckitoa(maxtry), "");
10881             return((int) sstate);
10882         } else return(success = x);
10883 #endif /* NOXFER */
10884
10885 #ifndef NOSERVER
10886       case XYSERV:                      /* SET SERVER items */
10887         if ((y = cmkey(srvtab,nsrvt,"","",xxstring)) < 0) return(y);
10888         switch (y) {
10889           case XYSERI:
10890             if ((y = cmnum("Number of seconds, or 0 for no idle timeout",
10891                            "0",10,&x,xxstring)) < 0)
10892               return(y);
10893             if (x < 0)
10894               x = 0;
10895             if ((y = cmcfm()) < 0)
10896               return(y);
10897 #ifndef OS2
10898             srvtim = 0;
10899 #endif /* OS2 */
10900             srvidl = x;
10901             return(success = 1);
10902           case XYSERT:
10903             if ((y = cmnum("Interval for server NAKs, 0 = none",
10904                            ckitoa(DSRVTIM),
10905                            10,&x, xxstring)) < 0)
10906               return(y);
10907             if (x < 0) {
10908                 printf(
10909                    "\n?Specify a positive number, or 0 for no server NAKs\n");
10910                 return(0);
10911             }
10912             if ((y = cmcfm()) < 0) return(y);
10913             if (rmsflg) {
10914                 sstate = setgen('S', "404", ckitoa(x), "");
10915                 return((int) sstate);
10916             } else {
10917 #ifndef OS2
10918                 srvidl = 0;
10919 #endif /* OS2 */
10920                 srvtim = x;             /* Set the server timeout variable */
10921                 return(success = 1);
10922             }
10923           case XYSERD:                  /* SERVER DISPLAY */
10924             return(success = seton(&srvdis)); /* ON or OFF... */
10925
10926 #ifndef NOSPL
10927           case XYSERP:                  /* SERVER GET-PATH */
10928             return(parsdir(2));
10929 #endif /* NOSPL */
10930
10931           case XYSERL:                  /* SERVER LOGIN */
10932             return(cklogin());
10933
10934           case XYSERC:                  /* SERVER CD-MESSAGE */
10935             x = rmsflg ?
10936               cmkey(onoff,2,"","",xxstring) :
10937                 cmkey(cdmsg,3,"","",xxstring);
10938             if (x < 0)
10939               return(x);
10940             if (x == 2) {               /* CD-MESSAGE FILE */
10941                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
10942                   return(x);
10943                 if (!*s) {
10944                     s = NULL;
10945                     srvcdmsg = 0;
10946                 }
10947                 makestr(&cdmsgstr,s);
10948                 makelist(cdmsgstr,cdmsgfile,8);
10949                 return(success = 1);
10950             }
10951             if ((y = cmcfm()) < 0)      /* CD-MESSAGE ON/OFF */
10952               return(y);
10953             if (rmsflg) {
10954                 sstate = setgen('S', "420", x ? "1" : "0", "");
10955                 return((int) sstate);
10956             } else {
10957                 if (x > 0)
10958                   srvcdmsg |= 1;
10959                 else
10960                   srvcdmsg &= 2;
10961                 return(success = 1);
10962             }
10963           case XYSERK:                  /* SERVER KEEPALIVE */
10964             return(success = seton(&srvping)); /* ON or OFF... */
10965
10966           default:
10967             return(-2);
10968         }
10969 #endif /* NOSERVER */
10970     }
10971
10972     switch (xx) {
10973 #ifdef UNIX
10974 #ifndef NOJC
10975       case XYSUSP:                      /* SET SUSPEND */
10976         seton(&xsuspend);               /* on or off... */
10977         return(success = 1);
10978 #endif /* NOJC */
10979 #endif /* UNIX */
10980
10981       case XYTAKE:                      /* SET TAKE */
10982         if ((y = cmkey(taktab,4,"","",xxstring)) < 0) return(y);
10983         switch (y) {
10984           case 0: return(success = seton(&techo));
10985 #ifndef NOSPL
10986           case 1: return(success = seton(&takerr[cmdlvl]));
10987 #else
10988           case 1: return(success = seton(&takerr[tlevel]));
10989 #endif /* NOSPL */
10990           case 2: techo = 0; return(success = 1); /* For compatibility with */
10991           case 3: techo = 1; return(success = 1); /* MS-DOS Kermit */
10992           default: return(-2);
10993         }
10994
10995 #ifndef NOSCRIPT
10996       case XYSCRI:                      /* SET SCRIPT */
10997         if ((y = cmkey(scrtab,1,"","echo",xxstring)) < 0) return(y);
10998         switch (y) {
10999           case 0: return(success = seton(&secho));
11000           default: return(-2);
11001         }
11002 #endif /* NOSCRIPT */
11003
11004       default:
11005         break;
11006     }
11007
11008 #ifndef NOLOCAL
11009     switch (xx) {
11010       case XYTERM:                      /* SET TERMINAL */
11011         x = settrm();
11012         success = (x > 0) ? 1 : 0;
11013         return(x);
11014
11015 #ifdef NT
11016       case XYWIN95:                     /* SET WIN95 workarounds */
11017         x = setwin95();
11018         success = (x > 0 ? 1 : 0);
11019         return(x);
11020 #endif /* NT */
11021
11022 #ifdef OS2
11023       case XYDLR:                       /* SET DIALER workarounds */
11024         x = setdialer();
11025         success = (x > 0 ? 1 : 0);
11026         return(x);
11027
11028       case XYTITLE:                     /* SET TITLE of window */
11029         x = settitle();
11030         success = (x > 0 ? 1 : 0);
11031         return(x);
11032 #endif /* OS2 */
11033
11034 #ifdef OS2MOUSE
11035       case XYMOUSE:                     /* SET MOUSE */
11036         return(success = setmou());
11037 #endif /* OS2MOUSE */
11038
11039       case XYBELL:                      /* SET BELL */
11040         return(success = setbell());
11041
11042 #ifdef OS2
11043       case XYPRTY:
11044         return(success = setprty() );
11045 #endif /* OS2 */
11046
11047       default:
11048         break;
11049     }
11050 #endif /* NOLOCAL */
11051
11052     switch (xx) {
11053
11054 /* SET SEND/RECEIVE protocol parameters. */
11055
11056 #ifndef NOXFER
11057       case XYRECV:
11058       case XYSEND:
11059         return(setsr(xx,rmsflg));
11060 #endif /* NOXFER */
11061
11062 #ifndef NOLOCAL
11063       case XYSESS:                      /* SESSION-LOG */
11064         if ((x = cmkey(sfttab,nsfttab,"type of file",
11065 #ifdef OS2
11066                        "binary",
11067 #else /* OS2 */
11068                        "text",
11069 #endif /* OS2 */
11070                        xxstring
11071                        )
11072              ) < 0)
11073           return(x);
11074         if ((y = cmcfm()) < 0)
11075           return(y);
11076         if (x == 999) {                 /* TIMESTAMPED-TEXT */
11077             sessft = XYFT_T;            /* Implies text */
11078             slogts = 1;                 /* and timestamps */
11079         } else {                        /* A regular type */
11080             sessft = x;                 /* The type */
11081             slogts = 0;                 /* No timestampes */
11082         }
11083         return(success = 1);
11084
11085       case XYSPEE:                      /* SET SPEED */
11086         lp = line;
11087         if (local && !network) {
11088           ckmakmsg(lp,
11089                    LINBUFSIZ,
11090                    "Transmission rate for ",
11091                    ttname,
11092                    " (bits per second)",
11093                    NULL
11094                    );
11095         } else {
11096           ckstrncpy(lp,
11097                     "Serial-port speed (bits per second)",
11098                     LINBUFSIZ
11099                     );
11100         }
11101         zz = -1L;
11102
11103 #ifdef TN_COMPORT
11104         if (network && istncomport())
11105           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
11106         else
11107 #endif /* TN_COMPORT */
11108           x = cmkey(spdtab,nspd,line,"",xxstring);
11109         if (x < 0) {
11110             if (x == -3) printf("?value required\n");
11111 #ifdef USETCSETSPEED
11112             /* In this case, any number can be tried */
11113             /* There's a parse error message but the request still goes thru */
11114             if (rdigits(atmbuf))
11115               zz = atol(atmbuf);
11116             else
11117 #endif /* USETCSETSPEED */
11118               return(x);
11119         }
11120         if ((y = cmcfm()) < 0) return(y);
11121 #ifdef IKSD
11122         if (inserver) {
11123             printf("?Sorry, command disabled.\r\n");
11124             return(success = 0);
11125         }
11126 #endif /* IKSD */
11127         if (!local) {
11128             printf("?SET SPEED has no effect without prior SET LINE\n");
11129             return(success = 0);
11130         } else if (network
11131 #ifdef TN_COMPORT
11132                    && !istncomport()
11133 #endif /* TN_COMPORT */
11134                    ) {
11135             printf("\n?Speed cannot be set for network connections\n");
11136             return(success = 0);
11137         }
11138
11139 /*
11140   Note: This way of handling speeds is not 16-bit safe for speeds greater
11141   than 230400.  The argument to ttsspd() should have been a long.
11142 */
11143 #ifdef USETCSETSPEED
11144         if (zz > -1L)
11145           x = zz / 10L;
11146 #endif /* USETCSETSPEED */
11147         zz = (long) x * 10L;
11148         if (zz == 130L) zz = 134L;
11149         if (zz == 70L) zz = 75L;        /* (see spdtab[] definition) */
11150         if (ttsspd(x) < 0)  {           /* Call ttsspd with cps, not bps! */
11151             printf("?Unsupported line speed - %ld\n",zz);
11152             return(success = 0);
11153         } else {
11154 #ifdef CK_TAPI
11155             if (!tttapi || tapipass)
11156               speed = ttgspd();         /* Read it back */
11157             else
11158               speed = zz;
11159 #else /* CK_TAPI */
11160             speed = ttgspd();           /* Read it back */
11161 #endif /* CK_TAPI */
11162             if (speed != zz)  {         /* Call ttsspd with cps, not bps! */
11163                 printf("?SET SPEED fails, speed is %ld\n",speed);
11164                 return(success = 0);
11165             }
11166             if (pflag && !xcmdsrc) {
11167                 if (speed == 8880)
11168                   printf("%s, 75/1200 bps\n",ttname);
11169                 else if (speed == 134)
11170                   printf("%s, 134.5 bps\n",ttname);
11171                 else
11172                   printf("%s, %ld bps\n",ttname,speed);
11173             }
11174             return(success = 1);
11175         }
11176 #endif /* NOLOCAL */
11177
11178 #ifndef NOXFER
11179       case XYXFER:                      /* SET TRANSFER */
11180         if ((y = cmkey(rmsflg ? rtstab : tstab, /* (or REMOTE SET TRANSFER) */
11181                        rmsflg ? nrts : nts,
11182                        "","character-set",xxstring)) < 0) return(y);
11183         switch (y) {
11184 #ifdef XFRCAN
11185           case XYX_CAN:                 /* CANCELLATION */
11186             if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
11187             if (z == 0) {               /* OFF */
11188                 if ((y = cmcfm()) < 0) return(y);
11189                 xfrcan = 0;
11190             } else {
11191                 if ((y = cmnum("ASCII code for cancellation character",
11192                                "3",10,&x,
11193                                xxstring)) < 0)
11194                   return(y);
11195                 if (x > 31 && x != 127) {
11196                     printf("Cancel character must be 0-31 or 127\n");
11197                     return(-9);
11198                 }
11199                 if ((y = cmnum("How many required to cause cancellation",
11200                                "2",10,&z, xxstring)) < 0)
11201                   return(y);
11202                 if (z < 2) {
11203                     printf("Number must be 2 or greater\n");
11204                     return(-9);
11205                 }
11206                 if ((y = cmcfm()) < 0) return(y);
11207                 xfrcan = 1;             /* CANCELLATION ON */
11208                 xfrchr = x;             /* Using this character */
11209                 xfrnum = z;             /* Needing this many of them */
11210             }
11211             return(success = 1);
11212 #endif /* XFRCAN */
11213
11214 #ifndef NOCSETS
11215           case XYX_CSE:                 /* CHARACTER-SET */
11216             if ((y = cmkey(tcstab,ntcs,"","transparent",xxstring)) < 0)
11217               return(y);
11218             if ((x = cmcfm()) < 0) return(x);
11219             if (rmsflg) {
11220                 sstate = setgen('S', "405", tcsinfo[y].designator, "");
11221                 return((int) sstate);
11222             } else {
11223                 extern int s_cset, fcharset, axcset[], tcs_save;
11224                 tslevel = (y == TC_TRANSP) ? 0 : 1; /* transfer syntax level */
11225                 xfrxla = tslevel;
11226                 tcharset = y;           /* transfer character set */
11227                 /* SEND CHARACTER-SET AUTO */
11228                 if (tslevel > 0 && s_cset == XMODE_A)
11229                   if (y > -1 && y <= MAXTCSETS)
11230                     if (axcset[y] > -1 && axcset[y] > MAXFCSETS)
11231                       fcharset = axcset[y]; /* Auto-pick file charset */
11232                 setxlatype(tcharset,fcharset); /* Translation type */
11233                 tcs_save = -1;
11234                 return(success = 1);
11235             }
11236 #endif /* NOCSETS */
11237
11238           case XYX_LSH:                 /* LOCKING-SHIFT */
11239             if ((y = cmkey(lstab,nls,"","on",xxstring)) < 0)
11240               return(y);
11241             if ((x = cmcfm()) < 0) return(x);
11242             lscapr = (y == 1) ? 1 : 0;  /* ON: requested = 1 */
11243             lscapu = (y == 2) ? 2 : 0;  /* FORCED:  used = 1 */
11244             return(success = 1);
11245
11246 #ifdef CK_XYZ
11247           case XYX_PRO:                 /* Protocol */
11248 #ifndef OS2
11249             if (inserver) {
11250                 printf("?Sorry, only Kermit protocol is available\n");
11251                 return(-9);
11252             }
11253 #endif /* OS2 */
11254             return(setproto());
11255 #endif /* CK_XYZ */
11256
11257           case XYX_MOD:                 /* Mode */
11258             if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
11259               return(y);
11260             if ((x = cmcfm()) < 0) return(x);
11261             if (rmsflg) {
11262                 sstate = setgen('S', "410", y == XMODE_A ? "0" : "1", "");
11263                 return((int)sstate);
11264             }
11265             g_xfermode = y;
11266             xfermode = y;
11267             return(success = 1);
11268
11269 #ifndef NOLOCAL
11270           case XYX_DIS:                 /* Display */
11271             return(doxdis(1));          /* 1 == Kermit */
11272 #endif /* NOLOCAL */
11273
11274           case XYX_SLO:                 /* Slow-start */
11275             return(seton(&slostart));
11276
11277 #ifndef NOSPL
11278           case XYX_CRC:                 /* CRC */
11279             return(seton(&docrc));
11280 #endif /* NOSPL */
11281
11282           case XYX_BEL:                 /* Bell */
11283             return(seton(&xfrbel));
11284
11285 #ifdef PIPESEND
11286           case XYX_PIP:                 /* Pipes */
11287 #ifndef NOPUSH
11288             if (nopush) {
11289 #endif /* NOPUSH */
11290                 printf("Sorry, access to pipes is disabled\n");
11291                 return(-9);
11292 #ifndef NOPUSH
11293             } else
11294 #endif /* NOPUSH */
11295               return(seton(&usepipes));
11296 #endif /* PIPESEND */
11297
11298           case XYX_INT:                 /* Interruption */
11299             return(seton(&xfrint));
11300
11301           case XYX_XLA:
11302             return(seton(&xfrxla));     /* Translation */
11303
11304           case XYX_MSG: {
11305               extern char * xfrmsg;
11306               if ((x = cmtxt("Prompt string","",&s,xxstring)) < 0)
11307                 return(x);
11308               if (!*s) s = NULL;
11309               makestr(&xfrmsg,s);
11310               return(success = 1);
11311
11312           }
11313           case XYX_RPT: {
11314               extern int whereflg;
11315               return(seton(&whereflg));
11316           }
11317           default:
11318             return(-2);
11319         }
11320 #endif /* NOXFER */
11321     }
11322
11323     switch (xx) {
11324
11325 #ifndef NOXMIT
11326       case XYXMIT:                      /* SET TRANSMIT */
11327         return(setxmit());
11328 #endif /* NOXMIT */
11329
11330 #ifndef NOXFER
11331 #ifndef NOCSETS
11332       case XYUNCS:                      /* UNKNOWN-CHARACTER-SET */
11333         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
11334         if ((x = cmcfm()) < 0) return(x);
11335         unkcs = y;
11336         return(success = 1);
11337 #endif /* NOCSETS */
11338 #endif /* NOXFER */
11339
11340 #ifndef NOPUSH
11341 #ifdef UNIX
11342       case XYWILD:                      /* WILDCARD-EXPANSION */
11343         if ((y = cmkey(wildtab,2,
11344                        "Who expands wildcards","kermit",xxstring)) < 0)
11345           return(y);
11346         if ((z = cmkey(wdottab,
11347                        2,
11348                        "whether to match filenames that start with \".\"",
11349                        "/no-match-dot-files",
11350                        xxstring)
11351              ) < 0)
11352           return(z);
11353         if ((x = cmcfm()) < 0) return(x);
11354         if (nopush) {
11355             if (y > 0) {
11356                 printf("Shell expansion is disabled\n");
11357                 return(success = 0);
11358             }
11359         }
11360         wildxpand = y;
11361         matchdot = z;
11362         return(success = 1);
11363 #endif /* UNIX */
11364 #endif /* NOPUSH */
11365
11366 #ifndef NOXFER
11367       case XYWIND:                      /* WINDOW-SLOTS */
11368         if (protocol == PROTO_K) {
11369             y = cmnum("Window size for Kermit protocol, 1 to 32",
11370                       "1", 10, &x, xxstring);
11371             y = setnum(&z,x,y,MAXWS);   /* == 32 */
11372         }
11373 #ifdef CK_XYZ
11374         else if (protocol == PROTO_Z) {
11375             y = cmnum("Window size for ZMODEM protocol, 0 to 65535",
11376                       "0", 10, &x, xxstring);
11377             y = setnum(&z,x,y,65535);
11378         }
11379 #endif /* CK_XYZ */
11380         else {
11381             y = cmnum("Window size for current protocol",
11382                       "", 10, &x, xxstring);
11383             y = setnum(&z,x,y,65472);   /* Doesn't matter - we won't use it */
11384         }
11385         if (y < 0) return(y);
11386         if (protocol == PROTO_K) {
11387             if (z < 1)
11388               z = 1;
11389         }
11390 #ifdef CK_XYZ
11391         else if (protocol == PROTO_Z) {
11392             /* Zmodem windowing is closer to Kermit packet length */
11393             /* than Kermit window size.  If Window size is zero   */
11394             /* an end of frame and CRC is sent only at the end of */
11395             /* the file (default).  Otherwise, an End of Frame    */
11396             /* and CRC are sent after Window Size number of bytes */
11397             if (z < 0)                  /* Disable windowing  */
11398               z = 0;
11399         } else {
11400             printf("?SET WINDOW does not apply to %s protocol\n",
11401                    ptab[protocol].p_name
11402                    );
11403         }
11404 #endif /* CK_XYZ */
11405
11406 #ifdef COMMENT
11407         /* This is taken care of automatically now in protocol negotiation */
11408         if (maxtry < z) {
11409             printf("?Window slots must be less than retry limit\n");
11410             return(success = 0);
11411         }
11412 #endif /* COMMENT */
11413         if (protocol == PROTO_K && rmsflg) { /* Set remote window size */
11414             wslotr = z;                 /* Set local window size too */
11415             ptab[protocol].winsize = wslotr;
11416             sstate = setgen('S', "406", ckitoa(z), "");
11417             return((int) sstate);
11418         }
11419         wslotr = z;                     /* Set requested window size here */
11420         ptab[protocol].winsize = wslotr; /* and in protocol-specific table */
11421         if (protocol == PROTO_K) {      /* And for Kermit only... */
11422             swcapr = (wslotr > 1) ? 1 : 0; /* set window bit in capas word */
11423             if (wslotr > 1) {           /* Window size > 1? */
11424                 /* Maybe adjust packet size */
11425                 y = adjpkl(urpsiz,wslotr,bigrbsiz);
11426                 if (y != urpsiz) {      /* Did it change? */
11427                     urpsiz = y;
11428                     if (msgflg)
11429                       printf(
11430 " Adjusting receive packet-length to %d for %d window slots\n",
11431                              urpsiz,
11432                              wslotr
11433                              );
11434                 }
11435             }
11436         }
11437         return(success = 1);
11438 #endif /* NOXFER */
11439     }
11440
11441     switch (xx) {
11442
11443 #ifndef NOSPL
11444       case XYOUTP:                      /* OUTPUT command parameters */
11445         if ((y = cmkey(outptab,noutptab,"OUTPUT command parameter","pacing",
11446                        xxstring)) < 0)
11447           return(y);
11448         switch(y) {                     /* Which parameter */
11449           case OUT_PAC:                 /* PACING */
11450             y = cmnum("Milliseconds to pause between each OUTPUT character",
11451                       "100", 10,&x,xxstring);
11452             y = setnum(&z,x,y,16383);   /* Verify and get confirmation */
11453             if (y < 0) return(y);
11454             if (z < 0) z = 0;           /* (save some space) */
11455             pacing = z;
11456             return(success = 1);
11457           case OUT_ESC:                 /* Special-escapes */
11458             return(seton(&outesc));
11459           default:                      /* (shouldn't happen) */
11460             return(-2);
11461         }
11462 #endif /* NOSPL */
11463
11464 #ifdef CK_SPEED
11465       case XYQCTL: {
11466           short *p;
11467           int zz;
11468           if ((z = cmkey(ctltab,2, "control-character prefixing option",""
11469                          ,xxstring)) < 0)
11470             return(z);
11471           /* Make space for a temporary copy of the prefixing table */
11472
11473           p = (short *)malloc(256 * sizeof(short));
11474           if (!p) {
11475               printf("?Internal error - malloc failure\n");
11476               return(-9);
11477           }
11478           for (i = 0; i < 256; i++) p[i] = ctlp[i]; /* Copy current table */
11479
11480           switch (z) {
11481             case 0:                     /* UNPREFIXED control character */
11482             case 1:                     /* PREFIXED control character */
11483               while (1) {               /* Collect a list of numbers */
11484 #ifndef NOSPL
11485                   x_ifnum = 1;          /* Turn off complaints from eval() */
11486 #endif /* NOSPL */
11487                   if ((x = cmnum((z == 0) ?
11488 "\n Numeric ASCII value of control character that needs NO prefix,\n\
11489  or the word \"all\", or carriage return to complete the list" :
11490 "\n Numeric ASCII value of control character that MUST BE prefixed,\n\
11491  or the word \"all\", or carriage return to complete the list",
11492                                  "",10,&y,xxstring
11493                                  )) < 0) {
11494 #ifndef NOSPL
11495                       x_ifnum = 0;
11496 #endif /* NOSPL */
11497                       if (x == -3) {
11498                           if ((x = cmcfm()) < 0) return(x);
11499                           break;
11500                       }
11501                       if (x == -2) {
11502                           if (p) { free((char *)p); p = NULL; }
11503                           debug(F110,"SET CONTROL atmbuf",atmbuf,0);
11504                           if (!ckstrcmp(atmbuf,"all",3,0) || /* "ALL" */
11505                               !ckstrcmp(atmbuf,"al",2,0) ||
11506                               !ckstrcmp(atmbuf,"a",1,0)) {
11507                               if ((x = cmcfm()) < 0) /* Get confirmation */
11508                                 return(x);
11509                               prefixing = z ? PX_ALL : PX_NON;
11510                               setprefix(prefixing);
11511                               return(success = 1);
11512                           } else {      /* Not number, not ALL */
11513                               printf(
11514                                  "?Please specify a number or the word ALL\n");
11515                               return(-9);
11516                           }
11517                       } else {
11518                           if (p) free((char *)p);
11519                           return(x);
11520                       }
11521                   }
11522 #ifndef NOSPL
11523                   x_ifnum = 0;
11524 #endif /* NOSPL */
11525 #ifdef UNPREFIXZERO
11526                   zz = 0;
11527 #else
11528 #ifndef OS2
11529                   zz = 1 - z;
11530 #else
11531                   zz = 0;               /* Allow 0 (but only for Zmodem) */
11532 #endif /* OS2 */
11533 #endif /* UNPREFIXZERO */
11534
11535             /* printf("x = %d, y = %d, z = %d, zz = %d\n", x,y,z,zz); */
11536
11537                   if ((y >  31 && y < 127) || /* A specific numeric value */
11538                       (y > 159 && y < 255) || /* Check that it is a valid */
11539                       (y < zz) ||       /* control code. */
11540                       (y > 255)) {
11541                       printf("?Values allowed are: %d-31, 127-159, 255\n",zz);
11542                       if (p) free((char *)p);
11543                       return(-9);
11544                   }
11545                   x = y & 127;          /* Get 7-bit value */
11546                   if (z == 0) {         /* If they are saying it is safe... */
11547                       /* If flow control is Xon/Xoff */
11548                       if (((flow == FLO_XONX) &&
11549                            /* XON & XOFF chars not safe. */
11550                            (x == XON || x == XOFF))
11551                           ) {
11552                           if (msgflg)
11553                             printf(
11554                               "Sorry, not while Xon/Xoff is in effect.\n");
11555                           if (p) free((char *)p);
11556                           return(-9);
11557                       }
11558 #ifdef TNCODE
11559                       else if (network && IS_TELNET()
11560                                && (y == CR ||
11561                                    (unsigned) y == (unsigned) 255)) {
11562                           if (msgflg)
11563                             printf("Sorry, not on a TELNET connection.\n");
11564                           if (p) free((char *)p);
11565                           return(-9);
11566                       }
11567 #endif /* TNCODE */
11568                   }
11569                   p[y] = (char) z;      /* All OK, set flag */
11570               } /* End of while loop */
11571 /*
11572   Get here only if they have made no mistakes.  Copy temporary table back to
11573   permanent one, then free temporary table and return successfully.
11574 */
11575               for (i = 0; i < 256; i++) ctlp[i] = p[i];
11576               if (p) free((char *)p);
11577               if (z > 0) clearrq = 0;   /* 199 (see SET PREFIXING) */
11578               return(success = 1);
11579             default:
11580               return(-2);
11581           }
11582       }
11583 #endif /* CK_SPEED */
11584     }
11585
11586     switch (xx) {
11587
11588 #ifndef NOXFER
11589       case XYREPT:
11590         if ((y = cmkey(rpttab,2,
11591                        "repeat-count compression parameter","",xxstring)) < 0)
11592           return(y);
11593         switch(y) {
11594           case 0:
11595             return(success = seton(&rptena)); /* REPEAT COUNTS = ON, OFF */
11596           case 1:                       /* REPEAT MININUM number */
11597             printf("(not implemented yet, nothing happens)\n");
11598             return(-9);
11599           case 2:                       /* REPEAT PREFIX char */
11600             if ((x = cmnum("ASCII value","",10,&z,xxstring)) < 0)
11601               return(x);
11602             if ((x = cmcfm()) < 0) return(x);
11603             if ((z > 32 && z < 63) || (z > 95 && z < 127)) {
11604                 if (y == 1) rptmin = (CHAR) z; else myrptq = (CHAR) z;
11605                 return(success = 1);
11606             } else {
11607                 printf("?Illegal value for prefix character\n");
11608                 return(-9);
11609             }
11610         }
11611 #endif /* NOXFER */
11612
11613 #ifndef NOSPL
11614       case XYALRM: {
11615 #ifndef COMMENT
11616           int yy;
11617           long zz;
11618           zz = -1L;
11619           yy = x_ifnum;
11620           x_ifnum = 1;                  /* Turn off internal complaints */
11621           y = cmnum("Seconds from now, or time of day as hh:mm:ss",
11622                     "0" ,10, &x, xxstring);
11623           x_ifnum = yy;
11624           if (y < 0) {
11625               if (y == -2) {            /* Invalid number or expression */
11626                   zz = tod2sec(atmbuf); /* Convert to secs since midnight */
11627                   if (zz < 0L) {
11628                       printf("?Number, expression, or time of day required\n");
11629                       return(-9);
11630                   } else {
11631                       char now[32];     /* Current time */
11632                       char *p;
11633                       long tnow;
11634                       p = now;
11635                       ztime(&p);
11636                       tnow = atol(p+11) * 3600L +
11637                         atol(p+14) * 60L + atol(p+17);
11638                       if (zz < tnow)    /* User's time before now */
11639                         zz += 86400L;   /* So make it tomorrow */
11640                       zz -= tnow;       /* Seconds from now. */
11641                   }
11642               } else
11643                 return(y);
11644           }
11645           if (x < 0) {
11646               printf("?Alarm time is in the past.\n");
11647               return(-9);
11648           }
11649           if ((y = cmcfm()) < 0) return(y);
11650           if (zz > -1L) {               /* Time of day given? */
11651               x = zz;
11652               if (zz != (long) x) {
11653                   printf(
11654 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
11655                          );
11656                   return(-9);
11657               }
11658           }
11659           return(setalarm((long)x));
11660       }
11661 #else
11662 /*
11663   This is to allow long values where int and long are not the same, e.g.
11664   on 16-bit systems.  But something is wrong with it.
11665 */
11666         if ((y = cmtxt("seconds from now", "0", &s, xxstring)) < 0)
11667           return(y);
11668         if (rdigits(s)) {
11669             return(setalarm(atol(s)));
11670         } else {
11671             printf("%s - not a number\n",s);
11672             return(-9);
11673         }
11674 #endif /* COMMENT */
11675 #endif /* NOSPL */
11676
11677 #ifndef NOXFER
11678       case XYPROTO:
11679         return(setproto());
11680 #endif /* NOXFER */
11681
11682 /*
11683   C-Kermit unprefixes control characters automatically on network connections
11684   if CLEAR-CHANNEL is ON, which it is by default.  But not all network
11685   connections are transparent to all control characters.  For example, the
11686   DEC-20, even when you TELNET to it, is sensitive to Ctrl-O and Ctrl-T.
11687   If you tell C-Kermit to SET CONTROL PREFIX 15 and/or 20, it doesn't help
11688   because CLEAR-CHANNEL is still in effect.  If the user goes to the trouble
11689   to set up some prefixing, then Kermit should do what the user said.  In
11690   C-Kermit 7.1 Alpha.03 we change the code to set clearrq to 0 if the user
11691   gives a SET PREFIXING or SET CONTROL PREFIX command.
11692 */
11693
11694 #ifdef CK_SPEED
11695       case XYPREFIX: {
11696 #ifdef COMMENT
11697           extern int clearrq;
11698 #endif /* COMMENT */
11699           if ((z = cmkey(pfxtab, 4, "control-character prefixing option",
11700                          "", xxstring)) < 0)
11701             return(z);
11702           if ((x = cmcfm()) < 0) return(x);
11703           clearrq = 0;                  /* 199 */
11704           setprefix(z);
11705 #ifdef COMMENT
11706           if (hints && (z == PX_ALL || z == PX_CAU) && clearrq) {
11707         printf("Hint: Use SET CLEAR-CHANNEL OFF to disable negotiation of\n");
11708         printf("      SET PREFIXING NONE during file transfers on reliable\n");
11709         printf("      connections.\n");
11710           }
11711 #endif /* COMMENT */
11712           return(success = 1);
11713       }
11714 #endif /* CK_SPEED */
11715
11716 #ifndef NOSPL
11717       case XYLOGIN:
11718         if ((z = cmkey(logintab, 3, "value for login script","userid",
11719                        xxstring)) < 0)
11720           return(z);
11721         x = cmdgquo();
11722         if (z == LOGI_PSW)
11723           cmdsquo(0);
11724         if ((y = cmtxt("text","", &s, NULL)) < 0) {
11725             cmdsquo(x);
11726             return(y);
11727         }
11728         cmdsquo(x);
11729 #ifdef IKSD
11730         if (inserver)
11731           return(success = 0);
11732 #endif /* IKSD */
11733         s = brstrip(s);
11734         if ((int)strlen(s) > 63) {
11735             printf("Sorry, too long\n");
11736             return(-9);
11737         }
11738         switch(z) {
11739           case LOGI_UID:
11740             ckstrncpy(uidbuf,s,UIDBUFLEN);
11741             sl_uid_saved = 0;
11742             break;
11743           case LOGI_PSW:
11744             ckstrncpy(pwbuf,s,PWBUFL);
11745             if (pwbuf[0]) {
11746                 pwflg = 1;
11747 #ifdef OS2
11748                 pwcrypt = 1;
11749 #else /* OS2 */
11750                 pwcrypt = 0;
11751 #endif /* OS2 */
11752             }
11753             break;
11754           case LOGI_PRM:
11755             ckstrncpy(prmbuf,s,PWBUFL);
11756         }
11757         return(success = 1);
11758 #endif /* NOSPL */
11759     }
11760
11761     switch (xx) {
11762
11763       case XYSTARTUP:
11764         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
11765         if ((x = cmcfm()) < 0) return(x);
11766         DeleteStartupFile = (y != 0) ? 0 : 1;
11767         return(success = 1);
11768
11769       case XYTMPDIR:
11770         x = cmdir("Name of temporary directory","",&s,xxstring);
11771         if (x == -3)
11772           s = "";
11773         else if (x < 0)
11774           return(x);
11775         if ((x = cmcfm()) < 0) return(x);
11776         makestr(&tempdir,s);
11777         return(tempdir ? 1 : 0);
11778
11779 #ifndef NOXFER
11780       case XYDEST:                      /* DESTINATION */
11781         return(setdest());
11782 #endif /* NOXFER */
11783
11784 #ifndef NOPUSH
11785 #ifndef NOFRILLS
11786
11787 /* Editor, Browser, and FTP Client */
11788
11789       case XYEDIT:                      /* EDITOR */
11790 #ifdef IKSD
11791         if (inserver) {
11792             printf("?Sorry, command disabled.\r\n");
11793             return(success = 0);
11794         }
11795 #endif /* IKSD */
11796 #ifdef CK_APC
11797         /* Don't let this be set remotely */
11798         if (apcactive == APC_LOCAL ||
11799             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
11800           return(success = 0);
11801 #endif /* CK_APC */
11802
11803 #ifdef OS2ORUNIX
11804         {
11805             char *p = getenv("PATH");
11806             char *e;
11807             e = editor[0] ? (char *) editor : getenv("EDITOR");
11808             if (!e) e = "";
11809             if (p)
11810               x = cmifip("Name of preferred editor",e,&s,&y,0,p,xxstring);
11811             else
11812               x = cmifi("Full path of preferred editor",e,&s,&y,xxstring);
11813             if (x < 0 && x != -3)
11814               return(x);
11815         }
11816 #else
11817 #ifdef VMS
11818         if ((y = cmtxt("DCL command for editing", "edit", &s, NULL)) < 0) {
11819             if (x != -3)
11820               return(x);
11821         }
11822 #else
11823         if ((x = cmifi("Full path of preferred editor","",&s,&y,xxstring))<0) {
11824             if (x != -3)
11825               return(x);
11826         }
11827 #endif /* VMS */
11828 #endif /* OS2ORUNIX */
11829 #ifdef VMS
11830         ckstrncpy(editor,s,CKMAXPATH);
11831         editopts[0] = NUL;
11832 #else
11833         if (y != 0) {
11834             printf("?A single file please\n");
11835             return(-2);
11836         }
11837         ckstrncpy(line,s,LINBUFSIZ);
11838         if ((x = cmtxt("editor command-line options","",&s,NULL)) < 0)
11839           return(x);
11840         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
11841         if ((z = cmcfm()) < 0) return(z);
11842         if (line[0]) {
11843             zfnqfp(line,CKMAXPATH,editor);
11844             ckstrncpy(editopts,tmpbuf,128);
11845         } else {
11846             editor[0] = NUL;
11847             editopts[0] = NUL;
11848         }
11849 #endif /* VMS */
11850         return(success = 1);
11851
11852 #ifndef NOFTP
11853 #ifndef SYSFTP
11854 #ifdef TCPSOCKET
11855       case XYFTPX:
11856         return(dosetftp());             /* SET FTP */
11857 #endif /* TCPSOCKET */
11858 #endif /* SYSFTP */
11859 #endif /* NOFTP */
11860
11861 #ifdef BROWSER
11862 #ifndef NOFTP
11863 #ifdef SYSFTP
11864       case XYFTP:                       /* SET FTP-CLIENT */
11865 #endif /* SYSFTP */
11866 #endif /* NOFTP */
11867       case XYBROWSE:                    /* SET BROWSER */
11868         {
11869             char *p = getenv("PATH");
11870             char *app = (char *) browser, *opts = (char *) browsopts;
11871 #ifndef NOFTP
11872 #ifdef SYSFTP
11873             extern char ftpapp[], ftpopts[];
11874             if (xx == XYFTP) {
11875                 app = (char *)ftpapp;
11876                 opts = (char *)ftpopts;
11877             }
11878 #endif /* SYSFTP */
11879 #endif /* NOFTP */
11880 #ifdef IKSD
11881             if (inserver) {
11882                 printf("?Sorry, command disabled.\r\n");
11883                 return(success = 0);
11884             }
11885 #endif /* IKSD */
11886 #ifdef CK_APC
11887             /* Don't let this be set remotely */
11888             if (apcactive == APC_LOCAL ||
11889                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
11890               return(success = 0);
11891 #endif /* CK_APC */
11892 #ifdef OS2ORUNIX
11893             if (p)
11894               x = cmifip(xx == XYBROWSE ?
11895                          "Name of preferred browser" :
11896                          "Name of preferred ftp client",
11897 #ifdef OS2
11898                          xx == XYFTP ? "ftp.exe" : ""
11899 #else
11900                          xx == XYFTP ? "ftp" : ""
11901 #endif /* OS2 */
11902                          ,&s,&y,0,p,xxstring
11903                          );
11904             else
11905               x = cmifi(xx == XYBROWSE ?
11906                         "Full path of preferred browser" :
11907                         "Full path of preferred ftp client",
11908                         "",&s,&y,xxstring
11909                         );
11910             if (x < 0 && x != -3)
11911               return(x);
11912 #else
11913 #ifdef VMS
11914             if ((x = cmtxt("DCL command to start your preferred Web browser",
11915                            "", &s, NULL)) < 0) {
11916                 if (x != -3)
11917                   return(x);
11918             }
11919 #else
11920             if ((x = cmifi("Full path of preferred browser","",&s,&y,xxstring)
11921                  ) < 0) {
11922                 if (x != -3)
11923                   return(x);
11924             }
11925 #endif /* VMS */
11926 #endif /* OS2ORUNIX */
11927 #ifdef VMS
11928             ckstrncpy(app,s,CKMAXPATH);
11929             *opts = NUL;
11930 #else
11931             if (y != 0) {
11932                 printf("?A single file please\n");
11933                 return(-2);
11934             }
11935             ckstrncpy(line,s,LINBUFSIZ);
11936             if ((x = cmtxt(xx == XYBROWSE ?
11937                            "browser command-line options" :
11938                            "ftp client command-line options",
11939                            "",&s,NULL)
11940                  ) < 0)
11941               return(x);
11942             ckstrncpy(tmpbuf,s,TMPBUFSIZ);
11943             if ((z = cmcfm()) < 0) return(z);
11944             if (line[0]) {
11945                 zfnqfp(line,CKMAXPATH,app);
11946                 ckstrncpy(opts, tmpbuf, 128);
11947             } else {
11948                 *app = NUL;
11949                 *opts = NUL;
11950             }
11951 #endif /* VMS */
11952             return(success = 1);
11953         }
11954 #endif /* BROWSER */
11955 #endif /* NOFRILLS */
11956 #endif /* NOPUSH */
11957
11958 #ifdef CK_CTRLZ
11959       case XYEOF: {                     /* SET EOF */
11960           extern int eofmethod; extern struct keytab eoftab[];
11961           if ((x = cmkey(eoftab,3,"end-of-file detection method","",
11962                          xxstring)) < 0)
11963             return(x);
11964           if ((y = cmcfm()) < 0)
11965             return(y);
11966           eofmethod = x;
11967           return(success = 1);
11968       }
11969 #endif /* CK_CTRLZ */
11970
11971 #ifdef SESLIMIT
11972       case XYLIMIT: {  /* Session-Limit (length of session in seconds) */
11973           extern int seslimit;
11974 #ifdef OS2
11975           extern int downloaded;
11976 #endif /* OS2 */
11977           y = cmnum("Maximum length of session, seconds","0",10,&x,xxstring);
11978           if (inserver &&
11979 #ifdef IKSDCONF
11980               iksdcf
11981 #else
11982               1
11983 #endif /* IKSDCONF */
11984 #ifdef OS2
11985                || downloaded
11986 #endif /* OS2 */
11987               ) {
11988               if ((z = cmcfm()) < 0)
11989                 return(z);
11990               printf("?Sorry, command disabled.\r\n");
11991               return(success = 0);
11992           }
11993           return(setnum(&seslimit,x,y,86400));
11994       }
11995 #endif /* SESLIMIT */
11996
11997       case XYRELY: {                    /* SET RELIABLE */
11998           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
11999             return(x);
12000           if ((y = cmcfm()) < 0) return(y);
12001           reliable = x;
12002           setreliable = (x != SET_AUTO);
12003           debug(F101,"SET RELIABLE reliable","",reliable);
12004           return(success = 1);
12005       }
12006
12007 #ifdef STREAMING
12008       case XYSTREAM: {                  /* SET STREAMING */
12009           extern int streamrq;
12010           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12011             return(x);
12012           if ((y = cmcfm()) < 0) return(y);
12013           streamrq = x;
12014           return(success = 1);
12015       }
12016 #endif /* STREAMING */
12017
12018 #ifdef CKSYSLOG
12019       case XYSYSL: {
12020           if ((x = cmkey(syslogtab,nsyslog,"","",xxstring)) < 0)
12021             return(x);
12022           if ((y = cmcfm()) < 0) return(y);
12023 #ifdef IKSD
12024           if (inserver &&
12025 #ifdef IKSDCONF
12026               iksdcf
12027 #else
12028               1
12029 #endif /* IKSDCONF */
12030               ) {
12031               printf("?Sorry, command disabled.\n");
12032               return(success = 0);
12033           }
12034 #endif /* IKSD */
12035 #ifdef CK_APC
12036           /* Don't let this be set remotely */
12037           if (apcactive == APC_LOCAL ||
12038               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12039             return(success = 0);
12040 #endif /* CK_APC */
12041           ckxsyslog = x;
12042           return(success = 1);
12043       }
12044 #endif /* CKSYSLOG */
12045
12046 #ifdef TLOG
12047       case XYTLOG: {                    /* SET TRANSACTION-LOG */
12048           extern int tlogsep;
12049           if ((x = cmkey(vbtab,nvb,"","verbose",xxstring)) < 0)
12050             return(x);
12051           if (x == 0) {
12052               if ((y = cmtxt("field separator",",",&s,NULL)) < 0) return(y);
12053               s = brstrip(s);
12054               if (*s) {
12055                   if (s[1]) {
12056                       printf("?A single character, please.\n");
12057                       return(-9);
12058                   } else if ((*s >= '0' && *s <= '9') ||
12059                              (*s >= 'A' && *s <= 'Z') ||
12060                              (*s >= 'a' && *s <= 'z')) {
12061                       printf("?A non-alphanumeric character, please.\n");
12062                       return(-9);
12063                   } else
12064                     tlogsep = *s;
12065               }
12066           } else {
12067               if ((y = cmcfm()) < 0) return(y);
12068           }
12069 #ifdef IKSD
12070           if (inserver && isguest) {
12071               printf("?Sorry, command disabled.\n");
12072               return(success = 0);
12073           }
12074 #endif /* IKSD */
12075 #ifdef CK_APC
12076           /* Don't let this be set remotely */
12077           if (apcactive == APC_LOCAL ||
12078               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12079             return(success = 0);
12080 #endif /* CK_APC */
12081           tlogfmt = x;
12082           return(success = 1);
12083       }
12084 #endif /* TLOG */
12085
12086       case XYCLEAR: {                   /* SET CLEARCHANNEL */
12087           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12088             return(x);
12089           if ((y = cmcfm()) < 0) return(y);
12090           clearrq = x;
12091           return(success = 1);
12092       }
12093
12094 #ifdef CK_AUTHENTICATION
12095       case XYAUTH: {                    /* SET AUTHENTICATION */
12096 #ifdef CK_KERBEROS
12097           int kv = 0;
12098           extern struct krb_op_data krb_op;
12099 #endif /* CK_KERBEROS */
12100           char * p = NULL;
12101           if ((x =
12102                cmkey(setauth,nsetauth,"authentication type","",xxstring)) < 0)
12103             return(x);
12104           switch (x) {
12105 #ifdef CK_KERBEROS
12106             case AUTH_KRB4: kv = 4; break; /* Don't assume values are same */
12107             case AUTH_KRB5: kv = 5; break;
12108 #endif /* CK_KERBEROS */
12109 #ifdef CK_SRP
12110             case AUTH_SRP: break;
12111 #endif /* CK_SRP */
12112 #ifdef CK_SSL
12113             case AUTH_SSL:
12114             case AUTH_TLS:
12115               break;
12116 #endif /* CK_SSL */
12117             default:
12118               printf("?Authorization type not supported yet - \"%s\"\n",
12119                      atmbuf);
12120               return(-9);
12121           }
12122 #ifdef IKSD
12123           if (inserver &&
12124 #ifdef IKSDCONF
12125               iksdcf
12126 #else
12127               1
12128 #endif /* IKSDCONF */
12129               ) {
12130               if ((y = cmcfm()) < 0) return(y);
12131               printf("?Sorry, command disabled.\n");
12132               return(success = 0);
12133           }
12134 #endif /* IKSD */
12135 #ifdef CK_APC
12136           /* Don't let this be set remotely */
12137           if (apcactive == APC_LOCAL ||
12138               apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)) {
12139               if ((y = cmcfm()) < 0) return(y);
12140               return(success = 0);
12141           }
12142 #endif /* CK_APC */
12143
12144           switch(x) {
12145 #ifdef CK_KERBEROS
12146             case AUTH_KRB4:
12147             case AUTH_KRB5: {
12148                 if ((x = cmkey(kv == 4 ? k4tab : k5tab,
12149                                kv == 4 ? nk4tab : nk5tab,
12150                                "Kerberos parameter","",xxstring)) < 0) {
12151                     return(x);
12152                 }
12153                 s = "";
12154                 switch (x) {
12155 #ifdef KRB4
12156                   case XYKRBDBG:
12157                     if (kv == 4) {
12158                         if ((y = seton(&k4debug)) < 0)
12159                           return(y);
12160 #ifdef NT
12161                         ck_krb4_debug(k4debug);
12162 #endif /* NT */
12163                     } else {
12164                         return(-9);
12165                     }
12166                     break;
12167 #endif /* KRB4 */
12168                   case XYKRBLIF:
12169                     if ((y = cmnum("TGT lifetime","600",10,&z,xxstring)) < 0)
12170                       return(y);
12171                     break;
12172                   case XYKRBPRE:
12173                     if (kv == 4) {
12174                         if ((y = seton(&krb4_d_preauth)) < 0)
12175                           return(y);
12176                     } else {
12177                         return(-9);
12178                     }
12179                     break;
12180                   case XYKRBINS:
12181                     if ((y = cmtxt("Instance name","",&s,xxstring)) < 0)
12182                       return(y);
12183                     break;
12184                   case XYKRBFWD:
12185                     if (kv == 5) {
12186                         if ((y = seton(&krb5_d_forwardable)) < 0)
12187                           return(y);
12188                     } else {
12189                         return(-9);
12190                     }
12191                     break;
12192                   case XYKRBPRX:
12193                     if (kv == 5) {
12194                         if ((y = seton(&krb5_d_proxiable)) < 0)
12195                           return(y);
12196                     } else {
12197                         return(-9);
12198                     }
12199                     break;
12200                   case XYKRBRNW:
12201                     if ((y = cmnum("TGT renewable lifetime",
12202                                    "0",10,&z,xxstring)) < 0)
12203                       return(y);
12204                     break;
12205                   case XYKRBADR:
12206                     if (kv == 5) {
12207                         if ((y = seton(&krb5_checkaddrs)) < 0)
12208                           return(y);
12209                     } else {
12210                         if ((y = seton(&krb4_checkaddrs)) < 0)
12211                           return(y);
12212                     }
12213                     break;
12214                   case XYKRBNAD:
12215                     if (kv == 5) {
12216                         if ((y = seton(&krb5_d_no_addresses)) < 0)
12217                           return(y);
12218                     }
12219                     break;
12220                   case XYKRBADD:
12221                     if (kv == 5) {
12222                         char * tmpaddrs[KRB5_NUM_OF_ADDRS];
12223                         for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
12224                           tmpaddrs[i] = NULL;
12225
12226                         if ((y =
12227                              cmfld("List of IP addresses","",&s,xxstring)) < 0)
12228                           return(y);
12229                         makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
12230                         if ((y = cmcfm()) < 0) {
12231                             for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
12232                                 if (tmpaddrs[i] != NULL)
12233                                   free(tmpaddrs[i]);
12234                             }
12235                             return(y);
12236                         }
12237                         for (i = 0;
12238                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
12239                              i++) {
12240                             if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
12241                                 printf("invalid ip address: %s\n",
12242                                        tmpaddrs[i]);
12243                                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
12244                                     if (tmpaddrs[i] != NULL)
12245                                       free(tmpaddrs[i]);
12246                                 }
12247                                 return(-9);
12248                             }
12249                         }
12250                         for (i = 0;
12251                              i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];
12252                              i++) {
12253                             if (krb5_d_addrs[i])
12254                               free(krb5_d_addrs[i]);
12255                             krb5_d_addrs[i] = NULL;
12256                         }
12257                         for (i = 0;
12258                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
12259                              i++) {
12260                             krb5_d_addrs[i] = tmpaddrs[i];
12261                             tmpaddrs[i] = NULL;
12262                         }
12263                         krb5_d_addrs[i] = NULL;
12264                         return(success = 1);
12265                     }
12266                     break;
12267
12268                   case XYKRBGET:
12269                     if (kv == 5) {
12270                         if ((y = seton(&krb5_autoget)) < 0)
12271                           return(y);
12272                     } else {
12273                         if ((y = seton(&krb4_autoget)) < 0)
12274                           return(y);
12275                     }
12276                     break;
12277                   case XYKRBDEL:
12278                     if ((z = cmkey(kdestab,nkdestab,
12279                                    "Auto Destroy Tickets",
12280                                    "never",xxstring)) < 0)
12281                       return(z);
12282                     break;
12283                   case XYKRBPR:
12284                     if ((y = cmtxt("User ID",uidbuf,&s,xxstring)) < 0)
12285                       return(y);
12286                     break;
12287                   case XYKRBRL:
12288                     if ((y = cmtxt("Name of realm","",&s,xxstring)) < 0)
12289                       return(y);
12290                     break;
12291                   case XYKRBKTB:
12292                     y = cmifi("Filename","",&s,&z,xxstring);
12293                     if (y != -3) {
12294                        if (y < 0)
12295                          return(y);
12296                        if (z) {
12297                          printf("?Wildcards not allowed\n");
12298                          return(-9);
12299                        }
12300                     }
12301                     break;
12302                   case XYKRBCC:
12303                     if ((y = cmofi("Filename","",&s,xxstring)) < 0)
12304                       return(y);
12305                     break;
12306                   case XYKRBSRV:
12307                     if ((y = cmtxt("Name of service to use in ticket",
12308                                    (kv == 4 ? "rcmd" : "host"),
12309                                    &s,
12310                                    xxstring
12311                                    )) < 0)
12312                       return(y);
12313                     break;
12314                   case XYKRBK5K4:
12315                     if (kv == 5) {
12316                         if ((y = seton(&krb5_d_getk4)) < 0)
12317                           return(y);
12318                     } else {
12319                         return(-9);
12320                     }
12321                     break;
12322                   case XYKRBPRM:        /* Prompt */
12323                     if ((z = cmkey(krbprmtab,2,"","",xxstring)) < 0)
12324                       return(z);
12325                     if ((y = cmtxt((z == KRB_PW_PRM) ?
12326   "Text of prompt;\nmay contain \"%s\" to be replaced by principal name" :
12327   "Text of prompt",
12328                                    "",
12329                                    &s,
12330                                    xxstring
12331                                    )
12332                          ) < 0)
12333                       return(y);
12334                     break;
12335                 }
12336                 ckstrncpy(line,s,LINBUFSIZ);
12337                 s = line;
12338                 if ((y = cmcfm()) < 0)
12339                   return(y);
12340 #ifdef IKSD
12341                 if (inserver &&
12342 #ifdef IKSDCONF
12343                     iksdcf
12344 #else /* IKSDCONF */
12345                     1
12346 #endif /* IKSDCONF */
12347                     )
12348                   return(success = 0);
12349 #endif /* IKSD */
12350
12351                 switch (x) {            /* Copy value to right place */
12352                   case XYKRBLIF:        /* Lifetime */
12353                     if (kv == 4)
12354                       krb4_d_lifetime = z;
12355                     else
12356                       krb5_d_lifetime = z;
12357                     break;
12358                   case XYKRBRNW:
12359                     if (kv == 5)
12360                       krb5_d_renewable = z;
12361                     break;
12362                   case XYKRBPR:         /* Principal */
12363                     s = brstrip(s);     /* Strip braces around. */
12364                     if (kv == 4)
12365                       makestr(&krb4_d_principal,s);
12366                     else
12367                       makestr(&krb5_d_principal,s);
12368                     break;
12369                   case XYKRBINS:        /* Instance */
12370                     if (kv == 4)
12371                       makestr(&krb4_d_instance,s);
12372                     else
12373                       makestr(&krb5_d_instance,s);
12374                     break;
12375                   case XYKRBRL:         /* Realm */
12376                     if (kv == 4)
12377                       makestr(&krb4_d_realm,s);
12378                     else
12379                       makestr(&krb5_d_realm,s);
12380                     break;
12381                   case XYKRBKTB:        /* Key Table */
12382                     if (kv == 4)
12383                       makestr(&k4_keytab,s);
12384                     else
12385                       makestr(&k5_keytab,s);
12386                     break;
12387                   case XYKRBCC:         /* Credentials cache */
12388                     makestr(&krb5_d_cc,s);
12389                     break;
12390                   case XYKRBSRV:        /* Service Name */
12391                     if (kv == 4)
12392                       makestr(&krb4_d_srv,s);
12393                     else
12394                       makestr(&krb5_d_srv,s);
12395                     break;
12396                   case XYKRBDEL:
12397                     if (kv == 5)
12398                       krb5_autodel = z;
12399                     else
12400                       krb4_autodel = z;
12401                     break;
12402                   case XYKRBPRM:        /* Prompt */
12403                     if (s == "") s = NULL;
12404                     if (s) {
12405                         s = brstrip(s);
12406                         if (s == "") s = NULL;
12407                     }
12408                     switch (z) {
12409                       case KRB_PW_PRM: { /* Password */
12410                           /* Check that there are no more than */
12411                           /* two % fields and % must followed by 's'. */
12412                           int i,n,len;
12413                           len = strlen(s);
12414                           for (i = 0, n = 0; i < len; i++) {
12415                               if (s[i] == '%') {
12416                                   if (s[i+1] != '%') {
12417                                       if (s[i+1] != 's') {
12418                                           printf(
12419                                            "Only %%s fields are permitted.\n"
12420                                                  );
12421                                           return(-9);
12422                                       }
12423                                       if (++n > 2) {
12424                                           printf(
12425                                       "Only two %%s fields are permitted.\n");
12426                                           return(-9);
12427                                       }
12428                                   }
12429                                   i++;
12430                               }
12431                           }
12432                           if (kv == 5)
12433                             makestr(&k5pwprompt,s);
12434                           else
12435                             makestr(&k4pwprompt,s);
12436                           break;
12437                       }
12438                       case KRB_PR_PRM: { /* Principal */
12439                           /* Check to make sure there are no % fields */
12440                           int i,len;
12441                           len = strlen(s);
12442                           for (i = 0; i < len; i++) {
12443                               if (s[i] == '%') {
12444                                   if (s[i+1] != '%') {
12445                                       printf(
12446                                   "%% fields are not used in this command.\n");
12447                                       return(-9);
12448                                   }
12449                                   i++;
12450                               }
12451                           }
12452                           if (kv == 5)
12453                             makestr(&k5prprompt,s);
12454                           else
12455                             makestr(&k4prprompt,s);
12456                           break;
12457                       }
12458                     }
12459                 }
12460                 break;
12461             }
12462 #endif /* CK_KERBEROS */
12463 #ifdef CK_SRP
12464             case AUTH_SRP: {
12465                 if ((x = cmkey(srptab, nsrptab,
12466                                "SRP parameter","",xxstring)) < 0) {
12467                     return(x);
12468                 }
12469                 s = "";
12470                 switch (x) {
12471                   case XYSRPPRM:        /* Prompt */
12472                     if ((z = cmkey(srpprmtab,1,"","",xxstring)) < 0)
12473                       return(z);
12474                     if ((y = cmtxt(
12475   "Text of prompt;\nmay contain one \"%s\" to be replaced by the username",
12476                                    "",
12477                                    &s,
12478                                    xxstring
12479                                    )
12480                          ) < 0)
12481                       return(y);
12482                     break;
12483                 }
12484                 ckstrncpy(line,s,LINBUFSIZ);
12485                 s = line;
12486                 if ((y = cmcfm()) < 0)
12487                   return(y);
12488                 switch (x) {            /* Copy value to right place */
12489                   case XYSRPPRM:        /* Prompt */
12490                     if (s == "") s = NULL;
12491                     if (s) {
12492                         s = brstrip(s);
12493                         if (s == "") s = NULL;
12494                     }
12495                     switch (z) {
12496                       case SRP_PW_PRM: { /* Password */
12497                           /* Check %s fields */
12498                           int i,n,len;
12499                           len = strlen(s);
12500                           for (i = 0, n = 0; i < len; i++) {
12501                               if (s[i] == '%') {
12502                                   if (s[i+1] != '%') {
12503                                       if (s[i+1] != 's') {
12504                                           printf(
12505                                           "Only %%s fields are permitted.\n");
12506                                           return(-9);
12507                                       }
12508                                       if (++n > 1) {
12509                                           printf(
12510                                        "Only one %%s field is permitted.\n");
12511                                           return(-9);
12512                                       }
12513                                   }
12514                                   i++;
12515                               }
12516                           }
12517                           makestr(&srppwprompt,s);
12518                           break;
12519                       }
12520                     }
12521                 }
12522                 break;
12523             }
12524 #endif /* CK_SRP */
12525 #ifdef CK_SSL
12526             case AUTH_SSL:
12527             case AUTH_TLS: {
12528                 if ((z = cmkey(ssltab, nssltab,
12529                            (x == AUTH_SSL ? "SSL parameter" : "TLS parameter"),
12530                            "",xxstring)) < 0)
12531                   return(z);
12532                 s = "";
12533                 switch (z) {
12534                   case XYSSLRCFL:       /* SSL/TLS RSA Certs file */
12535                   case XYSSLRCCF:       /* SSL/TLS RSA Certs Chain file */
12536                   case XYSSLRKFL:       /* SSL/TLS RSA Key File */
12537                   case XYSSLDCFL:       /* SSL/TLS DSA Certs file */
12538                   case XYSSLDCCF:       /* SSL/TLS DSA Certs Chain file */
12539                   case XYSSLDKFL:       /* SSL/TLS DH Key File */
12540                   case XYSSLDPFL:       /* SSL/TLS DH Param File */
12541                   case XYSSLCRL:        /* SSL/TLS CRL File */
12542                   case XYSSLVRFF:       /* SSL/TLS Verify File */
12543                   case XYSSLRND:        /* SSL/TLS Random File */
12544                     y = cmifi("Filename","",&s,&x,xxstring);
12545                     if (y != -3) {
12546                         if (y < 0)
12547                           return(y);
12548                         if (x) {
12549                             printf("?Wildcards not allowed\n");
12550                             return(-9);
12551                         }
12552                     }
12553                     ckstrncpy(line,s,LINBUFSIZ);
12554                     s = line;
12555                     s = brstrip(s);
12556                     if ((y = cmcfm()) < 0)
12557                       return(y);
12558                     switch (z) {
12559                       case XYSSLRCFL:   /* SSL/TLS RSA Certs file */
12560                         if (!s[0] && ssl_rsa_cert_file) {
12561                             free(ssl_rsa_cert_file);
12562                             ssl_rsa_cert_file = NULL;
12563                         } else if (s[0]) {
12564                             makestr(&ssl_rsa_cert_file,s);
12565                             if (!ssl_rsa_key_file)
12566                               makestr(&ssl_rsa_key_file,s);
12567                         }
12568                         break;
12569                       case XYSSLRCCF:   /* SSL/TLS RSA Certs Chain file */
12570                           if (!s[0] && ssl_rsa_cert_chain_file) {
12571                               free(ssl_rsa_cert_chain_file);
12572                               ssl_rsa_cert_chain_file = NULL;
12573                           } else if (s[0]) {
12574                               makestr(&ssl_rsa_cert_chain_file,s);
12575                           }
12576                           break;
12577                       case XYSSLRKFL:   /* SSL/TLS RSA Key File */
12578                         if (!s[0] && ssl_rsa_key_file) {
12579                             free(ssl_rsa_key_file);
12580                             ssl_rsa_key_file = NULL;
12581                         } else if (s[0]) {
12582                             makestr(&ssl_rsa_key_file,s);
12583                         }
12584                         break;
12585                       case XYSSLDCFL:   /* SSL/TLS DSA Certs file */
12586                         if (!s[0] && ssl_dsa_cert_file) {
12587                             free(ssl_dsa_cert_file);
12588                             ssl_dsa_cert_file = NULL;
12589                         } else if (s[0]) {
12590                             makestr(&ssl_dsa_cert_file,s);
12591                             if (!ssl_dh_key_file)
12592                               makestr(&ssl_dh_key_file,s);
12593                         }
12594                         break;
12595                       case XYSSLDCCF:   /* SSL/TLS DSA Certs Chain file */
12596                           if (!s[0] && ssl_dsa_cert_chain_file) {
12597                               free(ssl_dsa_cert_chain_file);
12598                               ssl_dsa_cert_chain_file = NULL;
12599                           } else if (s[0]) {
12600                               makestr(&ssl_dsa_cert_chain_file,s);
12601                           }
12602                           break;
12603                       case XYSSLDKFL:   /* SSL/TLS DH Key File */
12604                         if (!s[0] && ssl_dh_key_file) {
12605                             free(ssl_dh_key_file);
12606                             ssl_dh_key_file = NULL;
12607                         } else if (s[0]) {
12608                             makestr(&ssl_dh_key_file,s);
12609                         }
12610                         break;
12611                       case XYSSLDPFL:   /* SSL/TLS DH Param File */
12612                         if (!s[0] && ssl_dh_param_file) {
12613                             free(ssl_dh_param_file);
12614                             ssl_dh_param_file = NULL;
12615                         } else if (s[0]) {
12616                             makestr(&ssl_dh_param_file,s);
12617                         }
12618                         break;
12619                       case XYSSLCRL:    /* SSL/TLS CRL File */
12620                         if (!s[0] && ssl_crl_file) {
12621                             free(ssl_crl_file);
12622                             ssl_crl_file = NULL;
12623                         } else if (s[0]) {
12624                             makestr(&ssl_crl_file,s);
12625                         }
12626                         break;
12627                       case XYSSLVRFF:   /* SSL/TLS Verify File */
12628                         if (!s[0] && ssl_verify_file) {
12629                             free(ssl_verify_file);
12630                             ssl_verify_file = NULL;
12631                         } else if (s[0]) {
12632                             makestr(&ssl_verify_file,s);
12633                         }
12634                         break;
12635                       case XYSSLRND:    /* SSL/TLS Random File */
12636                         if (!s[0] && ssl_rnd_file) {
12637                             free(ssl_rnd_file);
12638                             ssl_rnd_file = NULL;
12639                         } else if (s[0]) {
12640                             makestr(&ssl_rnd_file,s);
12641                         }
12642                         break;
12643                     }
12644                     break;
12645
12646                   case XYSSLCRLD:
12647                   case XYSSLVRFD: {
12648                     char * d = NULL;
12649                     if (z == XYSSLVRFD)
12650                       d= getenv("SSL_CERT_DIR");
12651                     if (d == NULL)
12652                         d = "";
12653                     if ((y = cmdir("Directory",d,&s,xxstring)) < 0)
12654                       if (y != -3)
12655                         return(y);
12656                     ckstrncpy(line,s,LINBUFSIZ);
12657                     s = line;
12658                     s = brstrip(s);
12659                     if ((y = cmcfm()) < 0)
12660                       return(y);
12661                     switch(z) {
12662                       case XYSSLCRLD:
12663                         if (!s[0] && ssl_crl_dir) {
12664                             free(ssl_crl_dir);
12665                             ssl_crl_dir = NULL;
12666                         } else if (s[0]) {
12667                             makestr(&ssl_crl_dir,s);
12668                         }
12669                         break;
12670                       case XYSSLVRFD:
12671                         if (!s[0] && ssl_verify_dir) {
12672                             free(ssl_verify_dir);
12673                             ssl_verify_dir = NULL;
12674                         } else if (s[0]) {
12675                             makestr(&ssl_verify_dir,s);
12676                         }
12677                         break;
12678                     }
12679                     break;
12680                   }
12681                   case XYSSLCOK:        /* SSL/TLS Certs-Ok flag */
12682                     if ((y = seton(&ssl_certsok_flag)) < 0)
12683                       return(y);
12684                     break;
12685                   case XYSSLDBG:                /* SSL/TLS Debug flag */
12686                     if ((y = seton(&ssl_debug_flag)) < 0)
12687                       return(y);
12688                     break;
12689                   case XYSSLON:         /* SSL/TLS Only flag */
12690                     switch (x) {
12691                       case AUTH_SSL:
12692                         if ((y = seton(&ssl_only_flag)) < 0)
12693                           return(y);
12694                         break;
12695                       case AUTH_TLS:
12696                         if ((y = seton(&tls_only_flag)) < 0)
12697                           return(y);
12698                         break;
12699                     }
12700                     break;
12701                   case XYSSLVRB:        /* SSL/TLS Verbose flag */
12702                     if ((y = seton(&ssl_verbose_flag)) < 0)
12703                       return(y);
12704                     break;
12705                   case XYSSLVRF:        /* SSL/TLS Verify flag */
12706                     if ((x = cmkey(sslvertab, nsslvertab,
12707                                    "SSL/TLS verify mode",
12708                                    "peer-cert",xxstring)) < 0)
12709                       return(x);
12710                     if ((y = cmcfm()) < 0)
12711                       return(y);
12712                     ssl_verify_flag = x;
12713                     break;
12714                   case XYSSLDUM:
12715                     if ((y = seton(&ssl_dummy_flag)) < 0)
12716                       return(y);
12717                     break;
12718                   case XYSSLCL: {               /* SSL/TLS Cipher List */
12719 #ifdef COMMENT
12720                       /* This code is used to generate a colon delimited */
12721                       /* list of the ciphers currently in use to be used */
12722                       /* as the default for cmtxt().  However, a better  */
12723                       /* default is simply the magic keyword "ALL".      */
12724                       CHAR def[1024] = "";
12725                       if (ssl_con != NULL) {
12726                           CHAR * p = NULL, *q = def;
12727                           int i, len;
12728
12729                           for (i = 0; ; i++) {
12730                               p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
12731                               if (p == NULL)
12732                                 break;
12733                               len = strlen(p);
12734                               if (q+len+1 >= def+1024)
12735                                 break;
12736                               if (i != 0)
12737                                 *q++ = ':';
12738                               strcpy(q,p);
12739                               q += len;
12740                           }
12741                       }
12742 #endif /* COMMENT */
12743                       char * p = getenv("SSL_CIPHER");
12744                       if (!p)
12745                         p = "ALL";
12746                       if ((y = cmtxt(
12747                     "Colon-delimited list of ciphers or ALL (case-sensitive)",
12748                                      p,
12749                                      &s,
12750                                      xxstring
12751                                      )
12752                            ) < 0)
12753                         return(y);
12754                       makestr(&ssl_cipher_list,s);
12755                       if (ssl_con == NULL) {
12756                           SSL_library_init();
12757                           ssl_ctx = (SSL_CTX *)
12758                             SSL_CTX_new((SSL_METHOD *)TLSv1_method());
12759                           if (ssl_ctx != NULL)
12760                             ssl_con= (SSL *) SSL_new(ssl_ctx);
12761                       }
12762                       if (ssl_con) {
12763                           SSL_set_cipher_list(ssl_con,ssl_cipher_list);
12764                       }
12765                       break;
12766                   }
12767                 }
12768                 break;
12769             }
12770 #endif /* CK_SSL */
12771             default:
12772               break;
12773           }
12774           return(success = 1);
12775       }
12776 #endif /* CK_AUTHENTICATION */
12777
12778 #ifndef NOSPL
12779       case XYFUNC:
12780         if ((x = cmkey(functab,nfunctab,"","diagnostics",xxstring)) < 0)
12781           return(x);
12782         switch (x) {
12783           case FUNC_DI: return(seton(&fndiags));
12784           case FUNC_ER: return(seton(&fnerror));
12785           default:      return(-2);
12786         }
12787 #endif /* NOSPL */
12788
12789       case XYSLEEP:                     /* SET SLEEP / PAUSE */
12790         if ((x = cmkey(sleeptab,1,"","cancellation",xxstring)) < 0)
12791           return(x);
12792         return(seton(&sleepcan));
12793
12794       case XYCD:                        /* SET CD */
12795         if ((x = cmkey(cdtab,ncdtab,"","",xxstring)) < 0)
12796           return(x);
12797         switch (x) {
12798           case XYCD_H: {                /* SET CD HOME */
12799               extern char * myhome;
12800               if ((y = cmdir("Directory name",zhome(),&s,xxstring)) < 0)
12801                 return(y);
12802               makestr(&myhome,s);
12803               return(success = 1);
12804           }
12805           case XYCD_M:                  /* SET CD MESSAGE */
12806             if ((x = cmkey(cdmsg,ncdmsg,"","",xxstring)) < 0)
12807               return(x);
12808             if (x == 2) {               /* CD MESSAGE FILE */
12809                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
12810                   return(x);
12811                 if (!*s) {
12812                     s = NULL;
12813 #ifndef NOXFER
12814                     srvcdmsg = 0;
12815 #endif /* NOXFER */
12816                 }
12817                 makestr(&cdmsgstr,s);
12818                 makelist(cdmsgstr,cdmsgfile,8);
12819                 return(success = 1);
12820             }
12821
12822             if ((y = cmcfm()) < 0) return(y); /* CD-MESSAGE ON/OFF */
12823 #ifndef NOXFER
12824             if (x > 0)
12825               srvcdmsg |= 2;
12826             else
12827               srvcdmsg &= 1;
12828 #endif /* NOXFER */
12829             return(success = 1);
12830
12831           case XYCD_P: {                /* SET CD PATH */
12832               extern char * ckcdpath;
12833               if ((x = cmtxt("CD PATH string","",&s,xxstring)) < 0)
12834                 return(x);
12835               makestr(&ckcdpath,s);
12836               return(success = 1);
12837           }
12838         }
12839
12840 #ifndef NOLOCAL
12841 #ifdef STOPBITS
12842       case XYSTOP:                      /* STOP-BITS */
12843         if ((x = cmkey(stoptbl,2,"Stop bits for serial device","",
12844                        xxstring)) < 0)
12845           return(x);
12846         if ((y = cmcfm()) < 0)
12847           return(y);
12848         if (x > 0 && x < 3) {
12849             stopbits = x;
12850 #ifdef TN_COMPORT
12851             if (network && istncomport()) {
12852                 tnsettings(-1, x);
12853                 return(success = 1);
12854             }
12855 #endif /* TN_COMPORT */
12856 #ifdef HWPARITY
12857             return(success = 1);
12858 #else /* HWPARITY */
12859             return(-2);
12860 #endif /* HWPARITY */
12861         } else
12862           return(-2);
12863 #endif /* STOPBITS */
12864
12865       case XYDISC: {
12866           extern int clsondisc;
12867           return(seton(&clsondisc));
12868       }
12869
12870       case XYSERIAL: {
12871           /* char c; */
12872           extern int cmask;
12873           if ((x = cmkey(sertbl,nsertbl,
12874                          "Serial device character size, parity, and stop bits",
12875                          "8N1", xxstring)) < 0)
12876             return(x);
12877           ckstrncpy(line,atmbuf,LINBUFSIZ); /* Associated keyword string */
12878           s = line;
12879           if ((y = cmcfm()) < 0)
12880             return(y);
12881           ckstrncpy(line,sernam[x],LINBUFSIZ);
12882           s = line;
12883           if (s[0] != '8' && s[0] != '7') /* Char size */
12884             return(-2);
12885           else
12886             z = s[0] - '0';
12887           if (isupper(s[1]))            /* Parity */
12888             s[1] = tolower(s[1]);
12889           if (s[2] != '1' && s[2] != '2') /* Stop bits */
12890             return(-2);
12891           else
12892             stopbits = s[2] - '0';
12893           if (z == 8) {                 /* 8 bits + parity (or not) */
12894               parity = 0;               /* Set parity */
12895               hwparity = (s[1] == 'n') ? 0 : s[1];
12896               setcmask(8);              /* Also set TERM BYTESIZE to 8 */
12897           } else {                      /* 7 bits plus parity */
12898               parity = (s[1] == 'n') ? 0 : s[1];
12899               hwparity = 0;
12900               setcmask(7);              /* Also set TERM BYTESIZE to 7 */
12901           }
12902 #ifdef TN_COMPORT
12903           if (network && !istncomport())
12904             tnsettings(parity, stopbits);
12905 #endif /* TN_COMPORT */
12906
12907           return(success = 1);          /* from SET SERIAL */
12908       }
12909
12910       case XYOPTS: {                    /* SET OPTIONS */
12911           extern int setdiropts();
12912           extern int settypopts();
12913 #ifdef CKPURGE
12914           extern int setpurgopts();
12915 #endif /* CKPURGE */
12916           if ((x = cmkey(optstab,noptstab,"for command","", xxstring)) < 0)
12917             return(x);
12918           switch (x) {
12919 #ifndef NOFRILLS
12920             case XXDEL:
12921               return(setdelopts());
12922 #endif /* NOFRILLS */
12923             case XXDIR:
12924               return(setdiropts());
12925             case XXTYP:
12926               return(settypopts());
12927 #ifdef CKPURGE
12928             case XXPURGE:
12929               return(setpurgopts());
12930 #endif /* CKPURGE */
12931             default:
12932               return(-2);
12933           }
12934       }
12935 #endif /* NOLOCAL */
12936 #ifndef NOXFER
12937       case XYQ8FLG: {
12938           extern int q8flag;
12939           return(seton(&q8flag));
12940       }
12941       case XYTIMER: {
12942           extern int asktimer;
12943           y = cmnum("Time limit for ASK command, seconds","0",10,&x,xxstring);
12944 #ifdef QNX16
12945           return(setnum(&asktimer,x,y,32767));
12946 #else
12947           return(setnum(&asktimer,x,y,86400));
12948 #endif /* QNX16 */
12949       }
12950       case XYFACKB: {
12951           extern int fackbug;
12952           return(seton(&fackbug));
12953       }
12954 #endif /* NOXFER */
12955
12956       case XYHINTS:
12957         return(seton(&hints));
12958
12959 #ifndef NOSPL
12960       case XYEVAL: {
12961           extern int oldeval;
12962           if ((x = cmkey(oldnew,2,"","", xxstring)) < 0)
12963             return(x);
12964           if ((y = cmcfm()) < 0)
12965             return(y);
12966           oldeval = x;
12967           return(success = 1);
12968       }
12969 #endif /* NOSPL */
12970
12971 #ifndef NOXFER
12972       case XYFACKP: {
12973           extern int fackpath;
12974           return(seton(&fackpath));
12975       }
12976 #endif /* NOXFER */
12977
12978       case XYQNXPL: {
12979           extern int qnxportlock;
12980           return(seton(&qnxportlock));
12981       }
12982
12983 #ifndef NOCMDL
12984 #ifdef IKSD
12985       case XYIKS: {
12986           int setiks();
12987           return(setiks());
12988       }
12989 #endif /* IKSD */
12990 #endif /* NOCMDL */
12991
12992 #ifdef CKROOT
12993       case XYROOT:
12994         return(dochroot());
12995 #endif /* CKROOT */
12996
12997 #ifndef NOSPL
12998 #ifndef NOSEXP
12999       case XYSEXP: {
13000           if ((x = cmkey(sexptab,2,"","", xxstring)) < 0)
13001             return(x);
13002           switch (x) {
13003             case 0:
13004               if ((x = cmkey(ooatab,3,"","automatic", xxstring)) < 0)
13005                 return(x);
13006               if ((y = cmcfm()) < 0)
13007                 return(y);
13008               sexpecho = x;
13009               break;
13010             case 1: {
13011                 int i, xx;
13012                 xx = sexpmaxdep;
13013                 if ((y = cmnum("Maximum recursion depth",
13014                                "1000",10,&x,xxstring)) < 0)
13015                   return(y);
13016                 z = setnum(&sexpmaxdep,x,y,-1);
13017                 if (z < 0)
13018                   return(z);
13019                 if (sxresult) {         /* Free old stack if allocated */
13020                     for (i = 0; i < xx; i++)
13021                       if (sxresult[i]) free(sxresult[i]);
13022                     free((char *)sxresult);
13023                     if (sxrlen) free((char *)sxrlen);
13024                     sxresult = NULL;
13025                     sxrlen = NULL;
13026                 }
13027                 break;
13028             }
13029           }
13030           return(success = 1);
13031       }
13032 #endif /* NOSEXPL */
13033 #endif /* NOSPL */
13034
13035 #ifdef NEWFTP
13036       case XYGPR: {
13037           extern struct keytab gprtab[];
13038           extern int ftpget;
13039           if ((x = cmkey(gprtab,3,"","kermit", xxstring)) < 0)
13040             return(x);
13041           if ((y = cmcfm()) < 0)
13042             return(y);
13043           ftpget = x;
13044           return(success = 1);
13045       }
13046 #endif /* NEWFTP */
13047
13048 #ifdef ANYSSH
13049       case XYSSH:
13050         return(dosetssh());
13051 #endif /* ANYSHH */
13052
13053 #ifdef SFTP_BUILTIN
13054       case XYSFTP:
13055         return(dosetsftp());
13056 #endif /* SFTP_BUILTIN */
13057
13058 #ifdef LOCUS
13059       case XYLOCUS:
13060           if ((x = cmkey(locustab,nlocustab,"",
13061 #ifdef KUI
13062                          "ask"
13063 #else
13064                          "auto"
13065 #endif /* KUI */
13066                          ,xxstring)) < 0)
13067             return(x);
13068           if ((y = cmcfm()) < 0)
13069             return(y);
13070           if (x == 2 || x == 3) {       /* AUTO or ASK */
13071               setautolocus(x - 1);      /* Two forms of automatic locusing */
13072               /* setlocus(1,0); */      /* we're not changing the locus here */
13073           } else {                      /* LOCAL or REMOTE */
13074               setautolocus(0);          /* No automatic Locus changing */
13075               setlocus(x,0);            /* Set Locus as requested */
13076           }
13077           return(success = 1);
13078 #endif /* LOCUS */
13079
13080 #ifdef KUI
13081       case XYGUI:
13082         return(setgui());
13083 #endif /* KUI */
13084
13085       default:
13086          if ((x = cmcfm()) < 0) return(x);
13087          printf("Not implemented - %s\n",cmdbuf);
13088          return(success = 0);
13089     }
13090 }
13091
13092 /*
13093   H U P O K  --  Is Hangup OK?
13094
13095   Issues a warning and gets OK from user depending on whether a connection
13096   seems to be open and what the SET EXIT WARNING setting is.  Returns:
13097     0 if not OK to hang up or exit (i.e. user said No);
13098     nonzero if OK.
13099   Argument x is used to differentiate the EXIT command from SET LINE / HOST.
13100 */
13101 int
13102 hupok(x) int x; {                       /* Returns 1 if OK, 0 if not OK */
13103     int y, z = 1;
13104     extern int exithangup;
13105 #ifdef VMS
13106     extern int batch;
13107
13108     if (batch)                          /* No warnings in batch */
13109       return(1);
13110 #else
13111 #ifdef UNIX
13112     if (backgrd)                        /* No warnings in background */
13113       return(1);
13114 #endif /* UNIX */
13115 #endif /* VMS */
13116
13117 #ifndef K95G
13118     debug(F101,"hupok local","",local);
13119
13120     if (!local)                         /* No warnings in remote mode */
13121       return(1);
13122 #endif /* K95G */
13123
13124     if (x == 0 && exithangup == 0)      /* EXIT and EXIT HANGUP is OFF */
13125       return(1);
13126
13127     debug(F101,"hupok x","",x);
13128     debug(F101,"hupok xitwarn","",xitwarn);
13129     debug(F101,"hupok network","",network);
13130     debug(F101,"hupok haveline","",haveline);
13131
13132     if ((local && xitwarn) ||           /* Is a connection open? */
13133         (!x && xitwarn == 2)) {         /* Or Always give warning on EXIT */
13134         int needwarn = 0;
13135         char warning[256];
13136
13137         if (network) {
13138             if (ttchk() >= 0)
13139               needwarn = 1;
13140             /* A connection seems to be open but it can't possibly be */
13141             if (!haveline)
13142               needwarn = 0;
13143             if (needwarn) {
13144                 if (strcmp(ttname,"*"))
13145                     ckmakmsg(warning,256,
13146                               " A network connection to ",ttname,
13147                               " might still be active.\n",NULL);
13148                 else
13149                   ckstrncpy(warning,
13150                    " An incoming network connection might still be active.\n",
13151                              256);
13152             }
13153         } else {                        /* Serial connection */
13154             if (carrier == CAR_OFF)     /* SET CARRIER OFF */
13155               needwarn = 0;             /* so we don't care about carrier. */
13156             else if ((y = ttgmdm()) >= 0) /* else, get modem signals */
13157               needwarn = (y & BM_DCD);  /* Check for carrier */
13158             else                        /* If we can't get modem signals... */
13159               needwarn = (ttchk() >= 0);
13160             /* A connection seems to be open but it can't possibly be */
13161             if (!haveline || !exithangup)
13162               needwarn = 0;
13163             if (needwarn)
13164                 ckmakmsg(warning,256,
13165                      " A serial connection might still be active on ",
13166                      ttname,".\n",NULL);
13167         }
13168
13169 /* If a warning was issued, get user's permission to EXIT. */
13170
13171         if (needwarn || (!x && xitwarn == 2
13172 #ifndef K95G
13173                         && local
13174 #endif /* K95G */
13175                          )) {
13176 #ifdef COMMENT
13177             printf("%s",warning);
13178             z = getyesno(x ? "OK to close? " : "OK to exit? ",0);
13179             debug(F101,"hupok getyesno","",z);
13180             if (z < -3) z = 0;
13181 #else
13182             z = uq_ok(warning,
13183                       x ? "OK to close? " : "OK to exit? ",
13184                       3,
13185                       NULL,
13186                       0
13187                       );
13188             debug(F101,"hupok uq_ok","",z);
13189             if (z < 0) z = 0;
13190 #endif /* COMMENT */
13191         }
13192     }
13193     return(z);
13194 }
13195
13196 #ifndef NOSHOW
13197 VOID
13198 shoctl() {                              /* SHOW CONTROL-PREFIXING */
13199 #ifdef CK_SPEED
13200     int i;
13201 #ifdef OS2
13202     int zero;
13203 #endif /* OS2 */
13204     printf(
13205 "\ncontrol quote = %d, applied to (0 = unprefixed, 1 = prefixed):\n\n",
13206            myctlq);
13207 #ifdef OS2
13208 #ifndef UNPREFIXZERO
13209     zero = ctlp[0];
13210     if (protocol == PROTO_K)            /* Zero can't be unprefixed */
13211       ctlp[0] = 1;                      /* for Kermit */
13212 #endif /* UNPREFIXZERO */
13213 #endif /* OS2 */
13214     for (i = 0; i < 16; i++) {
13215         printf("  %3d: %d   %3d: %d ",i,ctlp[i], i+16, ctlp[i+16]);
13216         if (i == 15)
13217           printf("  127: %d",ctlp[127]);
13218         else
13219           printf("        ");
13220         printf("  %3d: %d   %3d: %d ",i+128,ctlp[i+128], i+144, ctlp[i+144]);
13221         if (i == 15)  printf("  255: %d",ctlp[255]);
13222         printf("\n");
13223     }
13224     printf("\n");
13225 #ifndef UNPREFIXZERO
13226 #ifdef OS2
13227     ctlp[0] = zero;
13228 #endif /* OS2 */
13229 #endif /* UNPREFIXZERO */
13230
13231 #endif /* CK_SPEED */
13232 }
13233
13234 #ifndef NOXFER
13235 VOID
13236 shodbl() {                              /* SHOW DOUBLE/IGNORE */
13237 #ifdef CKXXCHAR
13238     int i, n = 0;
13239     printf("\nSET SEND DOUBLE characters:\n");
13240     for (i = 0; i < 255; i++) {
13241         if (dblt[i] & 2) {
13242             n++;
13243             printf(" %d", i);
13244         }
13245     }
13246     if (n == 0)
13247       printf(" (none)");
13248     n = 0;
13249     printf("\nSET RECEIVE IGNORE characters:\n");
13250     for (i = 0; i < 255; i++) {
13251         if (dblt[i] & 1) {
13252             n++;
13253             printf(" %d", i);
13254         }
13255     }
13256     if (n == 0)
13257       printf(" (none)");
13258     printf("\n\n");
13259 #endif /* CKXXCHAR */
13260 }
13261 #endif /* NOXFER */
13262 #endif /* NOSHOW */
13263
13264 #ifndef NOPUSH
13265 #ifdef CK_REXX
13266 /*
13267   Rexx command.  Note, this is not OS/2-specific, because Rexx also runs
13268   on other systems where C-Kermit also runs, like the Amiga.
13269 */
13270 #define REXBUFL 100                     /* Change this if neccessary */
13271 char rexxbuf[REXBUFL] = { '\0' };       /* Rexx's return value (string) */
13272
13273 int
13274 dorexx() {
13275     int x, y;
13276     char *rexxcmd;
13277
13278         if ((x = cmtxt("Rexx command","",&rexxcmd,xxstring)) < 0)
13279           return(x);
13280
13281 #ifdef IKSD
13282     if (inserver) {
13283         printf("?Sorry, command disabled.\r\n");
13284         return(success = 0);
13285     }
13286 #endif /* IKSD */
13287 #ifdef CK_APC
13288     /* Don't let this be set remotely */
13289     if (apcactive == APC_LOCAL ||
13290         apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
13291       return(success = 0);
13292 #endif /* CK_APC */
13293
13294         ckstrncpy(line,rexxcmd,LINBUFSIZ);
13295         rexxcmd = line;
13296 #ifdef OS2
13297         return(os2rexx(rexxcmd,rexxbuf,REXBUFL));
13298 #else /* !OS2 */
13299         printf("Sorry, nothing happens.\n");
13300         return(success = 0);
13301 #endif /* OS2 */
13302 }
13303 #endif /* CK_REXX */
13304 #endif /* NOPUSH */
13305 #else  /* NOICP */
13306 VOID
13307 dologend() {
13308     /* Dummy write record to connection log */
13309 }
13310 #endif /* NOICP */