Standards-Version: 3.9.6 (no changes)
[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, 2011,
17     Trustees of Columbia University in the City of New York.
18     All rights reserved.  See the C-Kermit COPYING.TXT file or the
19     copyright text in the ckcmai.c module for disclaimer and permissions.
20 */
21
22 /*  SET command (but much material has been split off into ckuus7.c). */
23
24 /*
25   Kermit-specific includes.
26   Definitions here supersede those from system include files.
27 */
28 #include "ckcdeb.h"                     /* Debugging & compiler things */
29 #include "ckcasc.h"                     /* ASCII character symbols */
30 #include "ckcker.h"                     /* Kermit application definitions */
31 #include "ckcxla.h"                     /* Character set translation */
32 #include "ckcnet.h"                     /* Network symbols */
33
34 char pwbuf[PWBUFL+1]  = { NUL, NUL };
35 int pwflg = 0;
36 int pwcrypt = 0;
37
38 #ifndef NOICP
39
40 #ifdef CK_AUTHENTICATION
41 #include "ckuath.h"
42 #endif /* CK_AUTHENTICATION */
43 #ifdef CK_SSL
44 #include "ck_ssl.h"
45 #endif /* CK_SSL */
46 #include "ckuusr.h"                     /* User interface symbols */
47 #ifdef OS2
48 #include "ckcuni.h"
49 #ifdef SSHBUILTIN
50 #include "ckossh.h"
51 #endif /* SSHBUILTIN */
52 #ifdef CK_NETBIOS
53 #include <os2.h>
54 #ifdef COMMENT                          /* Would you believe */
55 #undef COMMENT                          /* <os2.h> defines this ? */
56 #endif /* COMMENT */
57 #include "ckonbi.h"
58 extern UCHAR NetBiosAdapter;
59 #endif /* CK_NETBIOS */
60 #include "ckocon.h"
61 #include "ckokey.h"
62 #ifndef NOTERM
63 extern unsigned char colorcmd;  /* Command-screen colors */
64 extern struct keytab ttyclrtab[];
65 extern int nclrs;
66 extern int tt_cols[], tt_rows[], tt_szchng[], tt_status[];
67 #endif /* NOTERM */
68 _PROTOTYP(int setprty, (void));
69 extern char startupdir[], exedir[];
70 extern int tt_modechg;
71 #ifdef NT
72 #include <windows.h>
73 #include <tapi.h>
74 #include "ckntap.h"                     /* Microsoft TAPI */
75 #endif /* NT */
76 #endif /* OS2 */
77
78 #ifndef OS2
79 extern char * exedir;
80 #endif /* OS2 */
81
82 #ifdef CK_RECALL
83 extern int cm_retry;
84 #endif /* CK_RECALL */
85
86 #ifdef NEWFTP
87 extern int ftpisopen();
88 #endif /* NEWFTP */
89
90 extern int cmdint;
91 extern int srvidl;
92
93 #ifdef CKFLOAT
94 extern CKFLOAT floatval;                /* (see isfloat()) */
95 #endif /* CKFLOAT */
96
97 #ifndef NOPUSH
98 #ifndef NOFRILLS
99 #ifdef VMS
100 char editor[CKMAXPATH + 1] = "edit";
101 #else
102 char editor[CKMAXPATH + 1] = { NUL, NUL };
103 #endif /* VMS */
104 char editopts[128] = { NUL, NUL };
105 char editfile[CKMAXPATH + 1] = { NUL, NUL };
106 #ifdef BROWSER
107 char browser[CKMAXPATH + 1] = { NUL, NUL };
108 char browsopts[128] = { NUL, NUL };
109 char browsurl[4096] = { NUL, NUL };
110 #endif /* BROWSER */
111 #endif /*  NOFRILLS */
112 #endif /* NOPUSH */
113
114 #ifndef NOFRILLS
115 #ifndef NORENAME
116 _PROTOTYP(int setrename, (void));
117 #endif  /* NORENAME */
118 #endif  /* NOFRILLS */
119
120 /* Variables */
121
122 int cmd_quoting = 1;
123 int cmd_err = 1;
124 extern int hints, xcmdsrc;
125
126 #ifdef CK_KERBEROS
127 char * k4pwprompt = NULL;               /* Kerberos 4 password prompt */
128 char * k4prprompt = NULL;               /* Kerberos 4 principal prompt */
129 char * k5pwprompt = NULL;               /* Kerberos 5 password prompt */
130 char * k5prprompt = NULL;               /* Kerberos 5 principal prompt */
131 #endif /* CK_KERBEROS */
132 #ifdef CK_SRP
133 char * srppwprompt = NULL;
134 #endif /* CK_SRP */
135
136 extern char * ckprompt, * ikprompt;     /* Default prompt */
137 extern xx_strp xxstring;
138
139 extern char * cdmsgfile[], * cdmsgstr;
140
141 extern int
142   local, server, success, dest, sleepcan, inserver, flow, autoflow, binary,
143   parity, escape, what, turn, duplex, backgrd, hwparity, stopbits, turnch,
144   mdmtyp, network, quiet, nettype, carrier, debses, debtim, cdtimo, nlangs,
145   bgset, pflag, msgflg, cmdmsk, xsuspend, techo, pacing, xitwarn, xitsta,
146   outesc, cmd_cols, cmd_rows, ckxech, xaskmore, haveline, didsetlin, isguest,
147   mdmsav, clearrq, saveask, debmsg;
148
149 extern int reliable, setreliable, matchdot, matchfifo, dir_dots;
150
151 #ifndef NOSERVER
152   extern int en_pri;
153 #endif /* NOSERVER */
154
155 #ifdef IKSDCONF
156 extern int iksdcf;
157 #endif /* IKSDCONF */
158 #ifdef TCPSOCKET
159   extern int tn_exit;
160 #endif /* TCPSOCKET */
161 #ifdef TNCODE
162   char * tn_pr_uid = NULL;
163 #endif /* TNCODE */
164   extern int exitonclose;
165
166 #ifndef NOKVERBS
167 extern int nkverbs;
168 extern struct keytab kverbs[];
169 #endif /* NOKVERBS */
170
171 extern int ttnproto;                    /* Network protocol */
172
173 extern char *ccntab[];                  /* Names of control chars */
174
175 #ifdef CK_APC
176 extern int apcactive, apcstatus;
177 #endif /* CK_APC */
178
179 #ifndef NOSCRIPT
180 extern int secho;                       /* Whether SCRIPT cmd should echo */
181 #endif /* NOSCRIPT */
182
183 #ifdef DCMDBUF
184 extern char *atmbuf, *atxbuf;
185 #else
186 extern char atmbuf[], atxbuf[];
187 #endif /* DCMDBUF */
188 extern int cmflgs;
189
190 extern char psave[];
191 extern char uidbuf[];
192 extern int  sl_uid_saved;
193 int DeleteStartupFile = 0;
194
195 extern int cmdlvl;                      /* Overall command level */
196
197 #ifndef NOSPL
198 _PROTOTYP( static int parsdir, (int) );
199 char prmbuf[PWBUFL+1] = { NUL, NUL };
200 int fndiags = 1;                        /* Function diagnostics on/off */
201 int fnerror = 1;                        /* Function error treatment */
202
203 #ifdef DCMDBUF
204 extern int *count, *takerr, *merror, *inpcas;
205 #else
206 extern int count[], takerr[], merror[], inpcas[];
207 #endif /* DCMDBUF */
208 extern int mecho;                       /* Macro echo */
209 extern long ck_alarm;
210 extern char alrm_date[], alrm_time[];
211 #else
212 extern int takerr[];
213 #endif /* NOSPL */
214
215 extern int x_ifnum;
216 extern int bigsbsiz, bigrbsiz;          /* Packet buffers */
217
218 extern long speed;                      /* Terminal speed */
219
220 extern char ttname[];                   /* Communication device name */
221 extern char myhost[] ;
222 extern char inidir[];                   /* Ini File directory */
223
224 #ifndef NOSETKEY
225 extern KEY *keymap;                     /* Character map for SET KEY (1:1)  */
226 extern MACRO *macrotab;                 /* Macro map for SET KEY (1:string) */
227 #endif /* NOSETKEY */
228 #ifdef OS2
229 int wideresult;                         /* For wide OS/2 scan codes/cmnum() */
230 #endif /* OS2 */
231
232 #ifndef NOLOCAL
233 #ifdef OS2
234 extern int tt_scrsize[];                /* Scrollback buffer Sizes */
235 #endif /* OS2 */
236 #endif /* NOLOCAL */
237
238 /* Printer settings */
239
240 extern char * printername;              /* NULL if printer not redirected */
241 extern int printpipe;
242 extern int noprinter;
243 #ifdef PRINTSWI
244 int printtimo = 0;
245 char * printterm = NULL;
246 char * printsep = NULL;
247 int printertype = 0;
248 #ifdef BPRINT
249 int printbidi = 0;                      /* SET BPRINTER (bidirectional) */
250 long pportspeed = 0L;                   /* Bidirection printer port speed, */
251 int pportparity = 0;                    /*  parity, */
252 int pportflow = FLO_KEEP;               /*  and flow control */
253 #endif /* BPRINT */
254 #ifdef OS2
255 extern int txt2ps;                      /* Text2PS conversion? */
256 extern int ps_width, ps_length;         /* Text2PS dimensions */
257 #endif /* OS2 */
258 #endif /* PRINTSWI */
259
260 #ifdef OS2
261 extern int tcp_avail;                   /* Nonzero if TCP/IP is available */
262 #ifdef DECNET
263 extern int dnet_avail;                  /* Ditto for DECnet */
264 #endif /* DECNET */
265 #ifdef SUPERLAT
266 extern int slat_avail;
267 #endif /* SUPERLAT */
268 #endif /* OS2 */
269
270 static struct keytab logintab[] = {
271     { "password", LOGI_PSW, CM_INV },
272     { "prompt",   LOGI_PRM, CM_INV },
273     { "userid",   LOGI_UID, 0 }
274 };
275
276 #ifndef NOCSETS
277 /* system-independent character sets, defined in ckcxla.[ch] */
278 extern struct csinfo tcsinfo[];
279 extern struct langinfo langs[];
280
281 /* Other character-set related variables */
282 extern int tcharset, tslevel, language;
283 #endif /* NOCSETS */
284
285 /* File-transfer variable declarations */
286
287 #ifndef NOXFER
288 #ifdef CK_AUTODL
289 extern int cmdadl;
290 #endif /* CK_AUTODL */
291
292 #ifndef NOSERVER
293 extern int ngetpath;
294 extern char * getpath[];
295 #endif /* NOSERVER */
296
297 extern struct ck_p ptab[];
298
299 extern CHAR sstate;                     /* Protocol start state */
300 extern CHAR myctlq;                     /* Control-character prefix */
301 extern CHAR myrptq;                     /* Repeat-count prefix */
302
303 extern int protocol, size, spsiz, spmax, urpsiz, srvtim, srvcdmsg, slostart,
304   srvdis, xfermode, ckdelay, keep, maxtry, unkcs, bctr, bctf, ebqflg, swcapr,
305   wslotr, lscapr, lscapu, spsizr, rptena, rptmin, docrc, xfrcan, xfrchr,
306   xfrnum, xfrbel, xfrint, srvping, g_xfermode, xfrxla;
307
308 #ifdef PIPESEND
309 extern int usepipes;
310 #endif /* PIPESEND */
311
312 #ifdef CKXXCHAR                         /* DOUBLE / IGNORE char table */
313 extern int dblflag, ignflag, dblchar;
314 extern short dblt[];
315 #endif /* CKXXCHAR */
316
317 #ifdef CK_SPEED
318 extern short ctlp[];                    /* Control-prefix table */
319 extern int prefixing;
320 static struct keytab pfxtab[] = {
321     "all",         PX_ALL, 0,
322     "cautious",    PX_CAU, 0,
323     "minimal",     PX_WIL, 0,
324     "none",        PX_NON, 0
325 };
326 #endif /* CK_SPEED */
327 #endif /* NOXFER */
328
329 /* Declarations from cmd package */
330
331 #ifdef DCMDBUF
332 extern char *cmdbuf;                    /* Command buffer */
333 extern char *line;
334 extern char *tmpbuf;
335 #else
336 extern char cmdbuf[];                   /* Command buffer */
337 extern char line[];                     /* Character buffer for anything */
338 extern char tmpbuf[];
339 #endif /* DCMDBUF */
340
341 /* From main ckuser module... */
342
343 extern char *tp, *lp;                   /* Temporary buffer */
344
345 extern int tlevel;                      /* Take Command file level */
346
347 #ifndef NOLOCAL
348 extern int sessft;                      /* Session-log file type */
349 extern int slogts;                      /* Session-log timestamps on/off */
350 extern int slognul;                     /* Lines null-terminated */
351 #endif /* NOLOCAL */
352
353 char * tempdir = NULL;
354
355 #ifdef VMS
356 int vms_msgs = 1;                       /* SET MESSAGES */
357 extern int batch;
358 #endif /* VMS */
359
360 /* Keyword tables for SET commands */
361
362 #ifdef CK_SPEED
363 struct keytab ctltab[] = {
364     "prefixed",   1, 0,                 /* Note, the values are important. */
365     "unprefixed", 0, 0
366 };
367 #endif /* CK_SPEED */
368
369 static struct keytab oldnew[] = {
370     "new", 0, 0,
371     "old", 1, 0
372 };
373
374 #define MCH_FIFO 1
375 #define MCH_DOTF 2
376 struct keytab matchtab[] = {
377     { "dotfile", MCH_DOTF, 0 },
378     { "fifo",    MCH_FIFO, 0 }
379 };
380 int nmatchtab = (sizeof(matchtab) / sizeof(struct keytab));
381
382 #ifndef NOSPL
383 static struct keytab functab[] = {
384     "diagnostics", FUNC_DI, 0,
385     "error",       FUNC_ER, 0
386 };
387 static int nfunctab = (sizeof(functab) / sizeof(struct keytab));
388
389 struct keytab outptab[] = {             /* SET OUTPUT parameters */
390     "pacing", 0, 0,                     /* only one so far... */
391     "special-escapes", 1, 0
392 };
393 int noutptab = (sizeof(outptab) / sizeof(struct keytab)); /* How many */
394 #endif /* NOSPL */
395
396 struct keytab chktab[] = {              /* Block check types */
397     "1", 1, 0,                          /* 1 =  6-bit checksum */
398     "2", 2, 0,                          /* 2 = 12-bit checksum */
399     "3", 3, 0,                          /* 3 = 16-bit CRC */
400     "4", 4, 0,                          /* Same as B */
401     "5", 5, 0,                          /* Same as F */
402     "blank-free-2", 4, CM_INV,          /* B = 12-bit checksum, no blanks */
403     "force-3", 5, CM_INV                /* F = Force CRC on ALL packets */
404 };
405 static int nchkt = (sizeof(chktab) / sizeof(struct keytab));
406
407 struct keytab rpttab[] = {              /* SET REPEAT */
408     "counts",    0, 0,                  /* On or Off */
409 #ifdef COMMENT
410     "minimum",   1, 0,                  /* Threshhold */
411 #endif /* COMMENT */
412     "prefix",    2, 0                   /* Repeat-prefix character value */
413 };
414
415 #ifndef NOLOCAL
416 /* For SET [ MODEM ] CARRIER, and also for SET DIAL CONNECT */
417
418 struct keytab crrtab[] = {
419     "automatic", CAR_AUT, 0,            /* 2 */
420     "off",       CAR_OFF, 0,            /* 0 */
421     "on",        CAR_ON,  0             /* 1 */
422 };
423 int ncrr = 3;
424 #endif /* NOLOCAL */
425
426 struct keytab ooatab[] = {              /* On/Off/Auto table */
427     "automatic", SET_AUTO, 0,           /* 2 */
428     "off",       SET_OFF,  0,           /* 0 */
429     "on",        SET_ON,   0            /* 1 */
430 };
431
432 struct keytab ooetab[] = {              /* On/Off/Stderr table 2010/03/12 */
433     "off",       SET_OFF, 0,            /* for SET DEBUG MESSAGES */
434     "on",        SET_ON,  0,
435     "s",         2,       CM_ABR|CM_INV,
436     "st",        2,       CM_ABR|CM_INV,
437     "std",       2,       CM_ABR|CM_INV,
438     "stderr",    2,       0,
439     "stdout",    SET_ON,  CM_INV
440 };
441 static int nooetab = (sizeof(ooetab) / sizeof(struct keytab));
442
443 struct keytab ooktab[] = {              /* On/Off/Ask table */
444     "ask",       2,        0,           /* 2 */
445     "off",       SET_OFF,  0,           /* 0 */
446     "on",        SET_ON,   0            /* 1 */
447 };
448
449 struct keytab qvtab[] = {               /* Quiet/Verbose table */
450     "quiet", 1, 0,
451     "verbose", 0, 0
452 };
453 int nqvt = 2;
454
455 /* For SET DEBUG */
456
457 #define DEB_OFF  0
458 #define DEB_ON   1
459 #define DEB_SES  2
460 #define DEB_TIM  3
461 #define DEB_LEN  4
462 #define DEB_MSG  5
463
464 struct keytab dbgtab[] = {
465     "linelength", DEB_LEN, CM_INV,
466     "m",          DEB_MSG, CM_ABR|CM_INV,
467     "message",    DEB_MSG, 0,
468     "msg",        DEB_MSG, CM_INV,
469     "off",        DEB_OFF, 0,
470     "on",         DEB_ON,  0,
471     "session",    DEB_SES, 0,
472     "timestamps", DEB_TIM, 0
473 };
474 int ndbg = (sizeof(dbgtab) / sizeof(struct keytab));
475
476 #ifndef NOLOCAL
477 /* Transmission speeds */
478
479 #ifdef TTSPDLIST /* Speed table constructed at runtime . . . */
480
481 struct keytab * spdtab = NULL;
482 int nspd = 0;
483
484 #else
485 /*
486   Note, the values are encoded in cps rather than bps because 19200 and higher
487   are too big for some ints.  All but 75bps are multiples of ten.  Result of
488   lookup in this table must be multiplied by 10 to get actual speed in bps.
489   If this number is 70, it must be changed to 75.  If it is 888, this means
490   75/1200 split speed.
491
492   The values are generic, rather than specific to UNIX.  We can't use B75,
493   B1200, B9600, etc, because non-UNIX versions of C-Kermit will not
494   necessarily have these symbols defined.  The BPS_xxx symbols are
495   Kermit-specific, and are defined in ckcdeb.h or on the CC command line.
496
497   Like all other keytabs, this one must be in "alphabetical" order,
498   rather than numeric order.
499 */
500 struct keytab spdtab[] = {
501     "0",      0,  CM_INV,
502     "110",   11,  0,
503 #ifdef BPS_115K
504  "115200",11520,  0,
505 #endif /* BPS_115K */
506   "1200",   120,  0,
507 #ifdef BPS_134
508   "134.5",  134,  0,
509 #endif /* BPS_134 */
510 #ifdef BPS_14K
511   "14400", 1440,  0,
512 #endif /* BPS_14K */
513 #ifdef BPS_150
514   "150",     15,  0,
515 #endif /* BPS_150 */
516 #ifdef BPS_1800
517   "1800",     180,  0,
518 #endif /* BPS_150 */
519 #ifdef BPS_19K
520   "19200", 1920,  0,
521 #endif /* BPS_19K */
522 #ifdef BPS_200
523   "200",     20,  0,
524 #endif /* BPS_200 */
525 #ifdef BPS_230K
526   "230400", 23040, 0,
527 #endif /* BPS_230K */
528   "2400",   240,  0,
529 #ifdef BPS_28K
530   "28800", 2880,  0,
531 #endif /* BPS_28K */
532   "300",     30,  0,
533 #ifdef BPS_3600
534   "3600",   360,  0,
535 #endif /* BPS_3600 */
536 #ifdef BPS_38K
537   "38400", 3840,  0,
538 #endif /* BPS_38K */
539 #ifdef BPS_460K
540   "460800", 46080,  0,                  /* Need 32 bits for this... */
541 #endif /* BPS_460K */
542   "4800",   480,  0,
543 #ifdef BPS_50
544   "50",       5,  0,
545 #endif /* BPS_50 */
546 #ifdef BPS_57K
547   "57600", 5760,  0,
548 #endif /* BPS_57K */
549   "600",     60,  0,
550 #ifdef BPS_7200
551   "7200",   720,  0,
552 #endif /* BPS_7200 */
553 #ifdef BPS_75
554   "75",       7,  0,
555 #endif /* BPS_75 */
556 #ifdef BPS_7512
557   "75/1200",888,  0,                    /* Code "888" for split speed */
558 #endif /* BPS_7512 */
559 #ifdef BPS_76K
560   "76800", 7680,  0,
561 #endif /* BPS_76K */
562 #ifdef BPS_921K
563   "921600", 92160,0,                    /* Need 32 bits for this... */
564 #endif /* BPS_921K */
565   "9600",   960,  0
566 };
567 int nspd = (sizeof(spdtab) / sizeof(struct keytab)); /* How many speeds */
568 #endif /* TTSPDLIST */
569
570 #ifdef TN_COMPORT
571 struct keytab tnspdtab[] = {            /* RFC 2217 TELNET COMPORT Option */
572     "115200", 11520,  0,                /* (add any other defined speeds) */
573     "1200",     120,  0,
574     "14400",   1440,  0,
575     "19200",   1920,  0,
576     "230400", 23040,  0,
577     "2400",     240,  0,
578     "28800",   2880,  0,
579     "300",       30,  0,
580     "38400",   3840,  0,
581     "460800", 46080,  0,
582     "4800",     480,  0,
583     "57600",   5760,  0,
584     "600",       60,  0,
585     "9600",     960,  0
586 };
587 int ntnspd = (sizeof(tnspdtab) / sizeof(struct keytab)); /* How many speeds */
588 #endif /* TN_COMPORT */
589 #endif /* NOLOCAL */
590
591 #ifndef NOCSETS
592 extern struct keytab lngtab[];          /* Languages for SET LANGUAGE */
593 extern int nlng;
594 #endif /* NOCSETS */
595
596 #ifndef NOLOCAL
597 /* Duplex keyword table */
598
599 struct keytab dpxtab[] = {
600     "full",      0, 0,
601     "half",      1, 0
602 };
603 #endif /* NOLOCAL */
604
605 /* Flow Control */
606
607 struct keytab cxtypesw[] = {
608 #ifdef DECNET
609     "/decnet",         CXT_DECNET,  0,
610 #endif /* DECNET */
611     "/direct-serial",  CXT_DIRECT,  0,
612 #ifdef DECNET
613     "/lat",            CXT_LAT,     0,
614 #else
615 #ifdef SUPERLAT
616     "/lat",            CXT_LAT,     0,
617 #endif /* SUPERLAT */
618 #endif /* DECNET */
619     "/modem",          CXT_MODEM,   0,
620 #ifdef NPIPE
621     "/named-pipe",     CXT_NPIPE,   0,
622 #endif /* NPIPE */
623 #ifdef NETBIOS
624     "/netbios",        CXT_NETBIOS, 0,
625 #endif /* NETBIOS */
626     "/remote",         CXT_REMOTE,  0,
627 #ifdef TCPSOCKET
628     "/tcpip",          CXT_TCPIP,   0,
629 #endif /* TCPSOCKET */
630 #ifdef ANYX25
631     "/x.25",           CXT_X25,     0,
632 #endif /* ANYX25 */
633     "", 0, 0
634 };
635 int ncxtypesw = (sizeof(cxtypesw) / sizeof(struct keytab));
636
637 #ifdef TN_COMPORT
638 struct keytab tnflotab[] = {            /* SET FLOW-CONTROL keyword table */
639     "dtr/cd",    FLO_DTRC, 0,           /* for RFC 2217 Telnet COMPORT */
640     "dtr/cts",   FLO_DTRT, 0,
641     "keep",      FLO_KEEP, 0,
642     "none",      FLO_NONE, 0,
643     "rts/cts",   FLO_RTSC, 0,
644     "xon/xoff",  FLO_XONX, 0
645 };
646 int ntnflo = (sizeof(tnflotab) / sizeof(struct keytab));
647 #endif /* TN_COMPORT */
648
649 struct keytab flotab[] = {              /* SET FLOW-CONTROL keyword table */
650     "automatic", FLO_AUTO, CM_INV,      /* Not needed any more */
651 #ifdef CK_DTRCD
652     "dtr/cd",    FLO_DTRC, 0,
653 #endif /* CK_DTRCD */
654 #ifdef CK_DTRCTS
655     "dtr/cts",   FLO_DTRT, 0,
656 #endif /* CK_DTRCTS */
657     "keep",      FLO_KEEP, 0,
658     "none",      FLO_NONE, 0,
659 #ifdef CK_RTSCTS
660     "rts/cts",   FLO_RTSC, 0,
661 #endif /* CK_RTSCTS */
662 #ifndef Plan9
663     "xon/xoff",  FLO_XONX, 0,
664 #endif /* Plan9 */
665     "", 0, 0
666 };
667 int nflo = (sizeof(flotab) / sizeof(struct keytab)) - 1;
668
669 /*  Handshake characters  */
670
671 struct keytab hshtab[] = {
672     "bell", 007, 0,
673     "code", 998, 0,
674     "cr",   015, 0,
675     "esc",  033, 0,
676     "lf",   012, 0,
677     "none", 999, 0,                     /* (can't use negative numbers) */
678     "xoff", 023, 0,
679     "xon",  021, 0
680 };
681 int nhsh = (sizeof(hshtab) / sizeof(struct keytab));
682
683 #ifndef NOLOCAL
684 static struct keytab sfttab[] = {       /* File types for SET SESSION-LOG */
685     "ascii",     XYFT_T, CM_INV,
686     "binary",    XYFT_B, 0,
687     "debug",     XYFT_D, 0,
688     "null-padded-lines", 998, 0,
689     "text",      XYFT_T, 0,
690     "timestamped-text", 999, 0
691 };
692 static int nsfttab = (sizeof(sfttab) / sizeof(struct keytab));
693 #endif /* NOLOCAL */
694
695 #ifndef NODIAL
696
697 #ifdef NETCONN                          /* Networks directory depends */
698 int nnetdir = 0;                        /* on DIAL code -- fix later... */
699 char *netdir[MAXDDIR+2];
700 #endif /* NETCONN */
701
702 _PROTOTYP( static int setdial, (int) );
703 _PROTOTYP( static int setdcd, (void) );
704 _PROTOTYP( static int cklogin, (void) );
705
706 #ifndef MINIDIAL
707 #ifdef OLDTBCODE
708 extern int tbmodel;                     /* Telebit model ID */
709 #endif /* OLDTBCODE */
710 #endif /* MINIDIAL */
711
712 extern MDMINF *modemp[];                /* Pointers to modem info structs */
713 extern struct keytab mdmtab[];          /* Modem types (in module ckudia.c) */
714 extern int nmdm;                        /* Number of them */
715
716 _PROTOTYP(static int dialstr,(char **, char *));
717
718 extern int dialhng, dialtmo, dialksp, dialdpy, dialmhu, dialec, dialdc;
719 extern int dialrtr, dialint, dialudt, dialsrt, dialrstr, mdmwaitd;
720 extern int mdmspd, dialfc, dialmth, dialesc, dialfld, dialidt, dialpace;
721 extern int mdmspk, mdmvol, dialtest;
722
723 int dialcvt = 2;                        /* DIAL CONVERT-DIRECTORY */
724 int dialcnf = 0;                        /* DIAL CONFIRMATION */
725 int dialcon = 2;                        /* DIAL CONNECT */
726 int dialcq  = 0;                        /* DIAL CONNECT AUTO quiet/verbose */
727 extern long dialmax, dialcapas;
728 int usermdm = 0;
729 extern int ndialdir;
730 extern char *dialini,   *dialmstr, *dialmprmt, *dialdir[], *dialcmd,  *dialnpr,
731  *dialdcon, *dialdcoff, *dialecon, *dialecoff, *dialhcmd,  *dialx3,
732  *dialhwfc, *dialswfc,  *dialnofc, *dialtone,  *dialpulse, *dialname, *diallac;
733 extern char *diallcc,   *dialixp,  *dialixs,   *dialldp,   *diallds,  *dialtfp,
734  *dialpxi,  *dialpxo,   *dialsfx,  *dialaaon,  *dialaaoff;
735 extern char *diallcp,   *diallcs,  *dialini2,  *dialmac;
736 extern char *dialspoff, *dialspon, *dialvol1,  *dialvol2,  *dialvol3;
737
738 char *dialtocc[MAXTPCC] = { NULL, NULL };
739 int ndialtocc = 0;
740 char *dialpucc[MAXTPCC] = { NULL, NULL };
741 int ndialpucc = 0;
742
743 char *dialtfc[MAXTOLLFREE] = {
744     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
745 };
746 int ntollfree = 0;
747
748 char *dialpxx[MAXPBXEXCH] = {
749     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
750 };
751 int ndialpxx = 0;
752
753 char *diallcac[MAXLOCALAC] = {
754     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
755     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
756     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
757     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
758 };
759 int nlocalac = 0;
760
761 static struct keytab drstrtab[] = {
762     "international", 5, 0,
763     "local",         2, 0,
764     "long-distance", 4, 0,
765     "none",          6, 0
766 };
767
768 static struct keytab dcnvtab[] = {
769     "ask",  2, 0,
770     "off",  0, 0,
771     "on",   1, 0
772 };
773
774 struct keytab setmdm[] = {
775     "capabilities",     XYDCAP,  0,
776     "carrier-watch",    XYDMCD,  0,
777     "command",          XYDSTR,  0,
778     "compression",      XYDDC,   CM_INV,
779     "data-compression", XYDDC,   0,
780     "dial-command",     XYDDIA,  0,
781     "error-correction", XYDEC,   0,
782     "escape-character", XYDESC,  0,
783     "flow-control",     XYDFC,   0,
784     "hangup-method",    XYDMHU,  0,
785 #ifndef NOXFER
786     "kermit-spoof",     XYDKSP,  0,
787 #endif /* NOXFER */
788     "maximum-speed",    XYDMAX,  0,
789     "name",             XYDNAM,  0,
790     "speaker",          XYDSPK,  0,
791     "speed-matching",   XYDSPD,  0,
792     "type",             XYDTYP,  0,
793     "volume",           XYDVOL,  0
794 };
795 int nsetmdm = (sizeof(setmdm) / sizeof(struct keytab));
796
797 struct keytab voltab[] = {
798     "high",   3,  0,
799     "low",    1,  0,
800     "medium", 2,  0
801 };
802
803 struct keytab mdmcap[] = {
804     "at-commands",      CKD_AT,  0,
805     "compression",      CKD_DC,  0,
806     "dc",               CKD_DC,  CM_INV,
807     "ec",               CKD_EC,  CM_INV,
808     "error-correction", CKD_EC,  0,
809     "hardware-flow",    CKD_HW,  0,
810     "hwfc",             CKD_HW,  CM_INV,
811     "itu",              CKD_V25, CM_INV,
812     "kermit-spoof",     CKD_KS,  0,
813     "ks",               CKD_KS,  CM_INV,
814     "sb",               CKD_SB,  CM_INV,
815     "software-flow",    CKD_SW,  0,
816     "speed-buffering",  CKD_SB,  0,
817     "swfc",             CKD_SW,  CM_INV,
818     "tb",               CKD_TB,  CM_INV,
819     "telebit",          CKD_TB,  0,
820     "v25bis-commands",  CKD_V25, 0
821 };
822 int nmdmcap = (sizeof(mdmcap) / sizeof(struct keytab));
823
824 #ifdef COMMENT                          /* SET ANSWER not implemented yet */
825 static struct keytab answertab[] = {
826     { "caller-id",  XYA_CID,  0 };
827     { "rings",      XYA_RNG,  0 };
828     { "", 0, 0 }
829 };
830 static int nanswertab =  (sizeof(answertab) / sizeof(struct keytab)) - 1;
831 #endif /* COMMENT */
832
833 struct keytab dialtab[] = {             /* SET DIAL table */
834     "area-code",        XYDLAC, 0,      /* Also still includes items     */
835     "compression",      XYDDC,  CM_INV, /* that were moved to SET MODEM, */
836     "confirmation",     XYDCNF, 0,      /* but they are CM_INVisible...  */
837     "connect",          XYDCON, 0,
838     "convert-directory",XYDCVT, 0,
839     "country-code",     XYDLCC, 0,
840     "dial-command",     XYDDIA, CM_INV,
841     "directory",        XYDDIR, 0,
842     "display",          XYDDPY, 0,
843     "escape-character", XYDESC, CM_INV,
844     "error-correction", XYDEC,  CM_INV,
845     "flow-control",     XYDFC,  CM_INV,
846     "force-long-distance", XYDFLD, 0,
847     "hangup",           XYDHUP, 0,
848     "ignore-dialtone",  XYDIDT, 0,
849     "interval",         XYDINT, 0,
850     "in",               XYDINI, CM_INV|CM_ABR,
851     "init-string",      XYDINI, CM_INV,
852     "intl-prefix",      XYDIXP, 0,
853     "intl-suffix",      XYDIXS, 0,
854 #ifndef NOXFER
855     "kermit-spoof",     XYDKSP, CM_INV,
856 #endif /* NOXFER */
857     "lc-area-codes",    XYDLLAC, 0,
858     "lc-prefix",        XYDLCP, 0,
859     "lc-suffix",        XYDLCS, 0,
860     "ld-prefix",        XYDLDP, 0,
861     "ld-suffix",        XYDLDS, 0,
862     "local-area-code",  XYDLAC, CM_INV,
863     "local-prefix",     XYDLCP, CM_INV,
864     "local-suffix",     XYDLCS, CM_INV,
865     "m",                XYDMTH, CM_INV|CM_ABR,
866 #ifndef NOSPL
867     "macro",            XYDMAC, 0,      /* 195 */
868 #endif /* NOSPL */
869 #ifdef MDMHUP
870     "me",               XYDMTH, CM_INV|CM_ABR,
871 #endif /* MDMHUP */
872     "method",           XYDMTH, 0,
873     "mnp-enable",       XYDMNP, CM_INV, /* obsolete but still accepted */
874 #ifdef MDMHUP
875     "modem-hangup",     XYDMHU, CM_INV,
876 #endif /* MDMHUP */
877     "pacing",           XYDPAC,  0,
878     "pbx-exchange",     XYDPXX,  0,
879     "pbx-inside-prefix",XYDPXI,  0,
880     "pbx-outside-prefix",XYDPXO, 0,
881     "prefix",           XYDNPR,  0,
882     "pulse-countries",  XYDPUCC, 0,
883     "restrict",         XYDRSTR, 0,
884     "retries",          XYDRTM,  0,
885     "sort",             XYDSRT,  0,
886     "speed-matching",   XYDSPD,  CM_INV,
887     "string",           XYDSTR,  CM_INV,
888     "suffix",           XYDSFX,  0,
889     "test",             XYDTEST, 0,
890     "timeout",          XYDTMO,  0,
891     "tf-area-code",     XYDTFC,  CM_INV,
892     "tf-prefix",        XYDTFP,  CM_INV,
893     "toll-free-area-code",XYDTFC,0,
894     "toll-free-prefix", XYDTFP,  0,
895     "tone-countries",   XYDTOCC, 0
896 };
897 int ndial = (sizeof(dialtab) / sizeof(struct keytab));
898
899 #ifdef MDMHUP
900 struct keytab mdmhang[] = {
901     "dtr",           0, 0,
902     "modem-command", 1, 0,
903     "rs232-signal",  0, 0,
904     "v24-signal",    0, CM_INV
905 };
906 #endif /* MDMHUP */
907
908 static struct keytab mdmcmd[] = {
909     "autoanswer",       XYDS_AN, 0,     /* autoanswer */
910     "compression",      XYDS_DC, 0,     /* data compression */
911     "dial-mode-prompt", XYDS_MP, 0,     /* dial mode prompt */
912     "dial-mode-string", XYDS_MS, 0,     /* dial mode string */
913     "error-correction", XYDS_EC, 0,     /* error correction */
914     "hangup-command",   XYDS_HU, 0,     /* hangup command */
915     "hardware-flow",    XYDS_HW, 0,     /* hwfc */
916     "ignore-dialtone",  XYDS_ID, 0,     /* ignore dialtone */
917     "init-string",      XYDS_IN, 0,     /* init string */
918     "no-flow-control",  XYDS_NF, 0,     /* no flow control */
919     "predial-init",     XYDS_I2, 0,     /* last-minute setup commands */
920     "pulse",            XYDS_DP, 0,     /* pulse */
921     "software-flow",    XYDS_SW, 0,     /* swfc */
922     "speaker",          XYDS_SP, 0,     /* Speaker */
923     "tone",             XYDS_DT, 0,     /* tone */
924     "volume",           XYDS_VO, 0      /* Volume */
925 };
926 static int nmdmcmd = (sizeof(mdmcmd) / sizeof(struct keytab));
927
928 struct keytab dial_fc[] = {
929     "auto",     FLO_AUTO, 0,
930     "none",     FLO_NONE, 0,
931     "rts/cts",  FLO_RTSC, 0,
932     "xon/xoff", FLO_XONX, 0
933 };
934
935 struct keytab dial_m[] = {              /* DIAL METHOD */
936     "auto",    XYDM_A, 0,
937     "default", XYDM_D, 0,
938     "pulse",   XYDM_P, 0,
939     "tone",    XYDM_T, 0
940 };
941 int ndial_m = (sizeof(dial_m)/sizeof(struct keytab));
942 #endif /* NODIAL */
943
944 #ifdef CK_TAPI
945 struct keytab tapitab[] = {             /* Top-Level Microsoft TAPI */
946     "configure-line",     XYTAPI_CFG,  0,
947     "dialing-properties", XYTAPI_DIAL, 0
948 };
949 int ntapitab = (sizeof(tapitab)/sizeof(struct keytab));
950
951 struct keytab settapitab[] = {          /* SET Microsoft TAPI */
952     "inactivity-timeout", XYTAPI_INA,  0,
953     "line",               XYTAPI_LIN,  0,
954     "location",           XYTAPI_LOC,  0,
955     "manual-dialing",     XYTAPI_MAN,  0,
956     "modem-dialing",      XYTAPI_PASS, 0,
957     "modem-lights",       XYTAPI_LGHT, 0,
958     "phone-number-conversions",   XYTAPI_CON,  0,
959     "port",               XYTAPI_LIN,  CM_INV,
960     "post-dial-terminal", XYTAPI_PST,  0,
961     "pre-dial-terminal",  XYTAPI_PRE,  0,
962     "use-windows-configuration", XYTAPI_USE, 0,
963     "wait-for-credit-card-tone", XYTAPI_BNG, 0
964 };
965 int nsettapitab = (sizeof(settapitab)/sizeof(struct keytab));
966
967 struct keytab * tapiloctab = NULL;      /* Microsoft TAPI Locations */
968 int ntapiloc = 0;
969 extern struct keytab * tapilinetab;     /* Microsoft TAPI Line Devices */
970 extern int ntapiline;
971 extern int tttapi;                      /* TAPI in use */
972 extern int tapipass;                    /* TAPI Passthrough mode */
973 extern int tapiconv;                    /* TAPI Conversion mode */
974 extern int tapilights;
975 extern int tapipreterm;
976 extern int tapipostterm;
977 extern int tapimanual;
978 extern int tapiinactivity;
979 extern int tapibong;
980 extern int tapiusecfg;
981 #endif /* CK_TAPI */
982
983 #ifndef NOPUSH
984 extern int nopush;
985 extern int wildena;
986 #ifdef UNIX
987 struct keytab wildtab[] = {             /* SET WILDCARD-EXPANSION */
988 #ifdef UNIX
989     "kermit",  WILD_KER, 0,             /* By Kermit */
990 #endif  /* UNIX */
991     "off",     WILD_OFF, 0,             /* Disabled */
992     "on",      WILD_ON,  0,             /* Enabled */
993 #ifdef UNIX
994     "shell",   WILD_SHE, 0,             /* By Shell */
995 #endif  /* UNIX */
996     "", 0, 0
997 };
998 int nwild = (sizeof(wildtab) / sizeof(struct keytab)) - 1;
999
1000 struct keytab wdottab[] = {             /* cont'd */
1001     "/match-dot-files",    1, 0,
1002     "/no-match-dot-files", 0, 0
1003 };
1004 extern int wildxpand;
1005 #endif /* UNIX */
1006 #endif /* NOPUSH */
1007
1008 #ifdef NETCONN
1009 extern struct keytab netcmd[], netkey[];
1010 extern int nnets, nnetkey;
1011 #ifdef TCPSOCKET
1012 extern struct keytab tcpopt[];
1013 extern int ntcpopt;
1014 #endif /* TCPSOCKET */
1015 #ifdef NPIPE
1016 char pipename[PIPENAML+1] = { NUL, NUL };
1017 #endif /* NPIPE */
1018 #ifdef CK_NETBIOS
1019 extern unsigned char NetBiosName[];
1020 #endif /* CK_NETBIOS */
1021 #endif /* NETCONN */
1022
1023 #ifdef ANYX25
1024 struct keytab x25tab[] = {
1025     "call-user-data",    XYUDAT, 0,
1026     "closed-user-group", XYCLOS, 0,
1027     "reverse-charge",    XYREVC, 0
1028 };
1029 int nx25 = (sizeof(x25tab) / sizeof(struct keytab));
1030
1031 #ifndef IBMX25
1032 struct keytab padx3tab[] = {
1033     "break-action",         PAD_BREAK_ACTION,           0,
1034     "break-character",      PAD_BREAK_CHARACTER,        0,
1035     "character-delete",     PAD_CHAR_DELETE_CHAR,       0,
1036     "cr-padding",           PAD_PADDING_AFTER_CR,       0,
1037     "discard-output",       PAD_SUPPRESSION_OF_DATA,    0,
1038     "echo",                 PAD_ECHO,                   0,
1039     "editing",              PAD_EDITING,                0,
1040     "escape",               PAD_ESCAPE,                 0,
1041     "forward",              PAD_DATA_FORWARD_CHAR,      0,
1042     "lf-padding",           PAD_PADDING_AFTER_LF,       0,
1043     "lf-insert",            PAD_LF_AFTER_CR,            0,
1044     "line-delete",          PAD_BUFFER_DELETE_CHAR,     0,
1045     "line-display",         PAD_BUFFER_DISPLAY_CHAR,    0,
1046     "line-fold",            PAD_LINE_FOLDING,           0,
1047     "pad-flow-control",     PAD_FLOW_CONTROL_BY_PAD,    0,
1048     "service-signals",      PAD_SUPPRESSION_OF_SIGNALS, 0,
1049     "timeout",              PAD_DATA_FORWARD_TIMEOUT,   0,
1050 /* Speed is read-only */
1051     "transmission-rate",    PAD_LINE_SPEED,             0,
1052     "user-flow-control",    PAD_FLOW_CONTROL_BY_USER,   0
1053 };
1054 int npadx3 = (sizeof(padx3tab) / sizeof(struct keytab));
1055 #endif /* IBMX25 */
1056 #endif /* ANYX25 */
1057
1058 #ifdef TLOG
1059 static struct keytab vbtab[] = {
1060     "brief",   0, 0,
1061 #ifdef OS2ORUNIX
1062     "ftp",     2, 0,
1063 #else
1064 #ifdef VMS
1065     "ftp",     2, 0,
1066 #endif /* def VMS */
1067 #endif /* OS2ORUNIX */
1068     "verbose", 1, 0
1069 };
1070 int nvb = (sizeof(vbtab) / sizeof(struct keytab));
1071 #endif /* TLOG */
1072
1073 #ifdef CKSYSLOG
1074 static struct keytab syslogtab[] = {
1075     "all",         SYSLG_CX, 0,
1076     "commands",    SYSLG_CM, 0,
1077     "connection",  SYSLG_AC, 0,
1078     "debug",       SYSLG_DB, 0,
1079     "dial",        SYSLG_DI, 0,
1080     "file-access", SYSLG_FA, 0,
1081     "file-create", SYSLG_FC, 0,
1082     "login",       SYSLG_LI, 0,
1083     "none",        SYSLG_NO, 0,
1084     "protocol",    SYSLG_PR, 0
1085 };
1086 int nsyslog = (sizeof(syslogtab) / sizeof(struct keytab));
1087 #endif /* CKSYSLOG */
1088
1089 /* Parity keyword table */
1090
1091 struct keytab partbl[] = {
1092     "even",    'e', 0,
1093 #ifdef HWPARITY
1094     "hardware",'H', 0,
1095 #endif /* HWPARITY */
1096     "mark",    'm', 0,
1097     "none",     0 , 0,
1098     "odd",     'o', 0,
1099     "space",   's', 0
1100 };
1101 int npar = (sizeof(partbl) / sizeof(struct keytab));
1102
1103 #ifdef HWPARITY
1104 struct keytab hwpartbl[] = {
1105 /* Add mark and space if needed and possible */
1106     "even",    'e', 0,
1107 #ifdef OS2
1108     "mark",    'm', 0,
1109 #endif /* OS2 */
1110     "odd",     'o', 0,
1111 #ifdef OS2
1112     "space",   's', 0,
1113 #endif /* OS2 */
1114     "", 0, 0
1115 };
1116 int nhwpar = (sizeof(hwpartbl) / sizeof(struct keytab)) - 1;
1117 #endif /* HWPARITY */
1118
1119 /* On/Off table */
1120
1121 struct keytab onoff[] = {
1122     "off",       0, 0,
1123     "on",        1, 0
1124 };
1125
1126 #define XYCD_M    0                     /* CD MESSAGE */
1127 #define XYCD_P    1                     /* CD PATH */
1128 #define XYCD_H    2                     /* CD HOME */
1129
1130 struct keytab cdtab[] = {
1131     "home",      XYCD_H, 0,
1132     "message",   XYCD_M, 0,
1133     "path",      XYCD_P, 0
1134 };
1135 int ncdtab = (sizeof(cdtab) / sizeof(struct keytab));
1136
1137 struct keytab cdmsg[] = {
1138     "file",      2, 0,
1139     "off",       0, 0,
1140     "on",        1, 0
1141 };
1142 int ncdmsg = (sizeof(cdmsg) / sizeof(struct keytab));
1143
1144 static
1145 struct keytab xittab[] = {              /* SET EXIT */
1146     "hangup",        3, 0,              /* ...HANGUP */
1147     "on-disconnect", 2, 0,              /* ...ON-DISCONNECT */
1148     "status",        0, 0,              /* ...STATUS */
1149     "warning",       1, 0               /* ...WARNING */
1150 };
1151 int nexit = (sizeof(xittab) / sizeof(struct keytab));
1152
1153 struct keytab xitwtab[] = {             /* SET EXIT WARNING */
1154     "always", 2, 0,                     /* even when not connected */
1155     "off",    0, 0,                     /* no warning     */
1156     "on",     1, 0                      /* when connected */
1157 };
1158 int nexitw = (sizeof(xitwtab) / sizeof(struct keytab));
1159
1160 struct keytab rltab[] = {
1161     "local",     1, 0,                  /* ECHO values */
1162     "off",       0, CM_INV,
1163     "on",        1, CM_INV,
1164     "remote",    0, 0
1165 };
1166 int nrlt = (sizeof(rltab) / sizeof(struct keytab));
1167
1168 /* Incomplete File Disposition table */
1169
1170 struct keytab ifdtab[] = {
1171     "discard", SET_OFF, 0,
1172     "keep",    SET_ON,  0
1173 };
1174
1175 struct keytab ifdatab[] = {
1176     "auto",    SET_AUTO, 0,
1177     "discard", SET_OFF,  0,
1178     "keep",    SET_ON,   0
1179 };
1180
1181 char * ifdnam[] = { "discard", "keep", "auto" };
1182
1183 /* SET TAKE parameters table */
1184 static
1185 struct keytab taktab[] = {
1186     "echo",  0, 0,
1187     "error", 1, 0,
1188     "off",   2, CM_INV,                 /* For compatibility */
1189     "on",    3, CM_INV                  /* with MS-DOS Kermit... */
1190 };
1191
1192 #ifndef NOSPL
1193 #ifdef COMMENT
1194 /* not used */
1195 static
1196 struct keytab suftab[] = {              /* (what to do with) STARTUP-FILE */
1197     "delete", 1, 0,
1198     "keep",   0, 0
1199 };
1200 #endif /* COMMENT */
1201
1202 /* SET MACRO parameters table */
1203 static
1204 struct keytab smactab[] = {
1205     "echo",  0, 0,
1206     "error", 1, 0
1207 };
1208 #endif /* NOSPL */
1209
1210 #ifndef NOSCRIPT
1211 static
1212 struct keytab scrtab[] = {
1213     "echo",  0, 0
1214 };
1215 #endif /* NOSCRIPT */
1216
1217 /* SET COMMAND table */
1218
1219 /* SET COMMAND items... */
1220
1221 #define SCMD_BSZ 0      /* BYTESIZE */
1222 #define SCMD_RCL 1      /* RECALL */
1223 #define SCMD_RTR 2      /* RETRY */
1224 #define SCMD_QUO 3      /* QUOTING */
1225 #define SCMD_COL 4      /* COLOR */
1226 #define SCMD_HIG 5      /* HEIGHT */
1227 #define SCMD_WID 6      /* WIDTH */
1228 #define SCMD_CUR 7      /* CURSOR-POSITION */
1229 #define SCMD_SCR 8      /* SCROLLBACK */
1230 #define SCMD_MOR 9      /* MORE-PROMPTING */
1231 #define SCMD_INT 10     /* INTERRUPTION */
1232 #define SCMD_ADL 11     /* AUTODOWNLOAD */
1233 #define SCMD_STA 12     /* STATUSLINE */
1234 #define SCMD_DBQ 13     /* DOUBLEQUOTING */
1235 #define SCMD_CBR 14     /* CBREAK */
1236 #define SCMD_BFL 15     /* BUFFER-SIZE (not used) */
1237 #define SCMD_ERR 16     /* ERROR */
1238 #define SCMD_VAR 17     /* VARIABLE-EVALUATION */
1239
1240 static struct keytab scmdtab[] = {
1241 #ifdef CK_AUTODL
1242     "autodownload",       SCMD_ADL, 0,
1243 #endif /* CK_AUTODL */
1244 #ifdef COMMENT
1245 /*
1246   To implement this requires that we change CMDBL and ATMBL
1247   from compile-time symbols to runtime variables.  Not a big deal,
1248   but not trivial either.
1249  */
1250     "buffer-size",        SCMD_BFL, 0,
1251 #endif /* COMMENT */
1252     "bytesize",           SCMD_BSZ, 0,
1253     "cbreak",             SCMD_CBR, CM_INV,
1254 #ifdef OS2
1255     "color",              SCMD_COL, 0,
1256     "cursor-position",    SCMD_CUR, 0,
1257 #endif /* OS2 */
1258 #ifdef DOUBLEQUOTING
1259     "doublequoting",      SCMD_DBQ, 0,
1260 #endif /* DOUBLEQUOTING */
1261     "error-display",      SCMD_ERR, 0,
1262     "height",             SCMD_HIG, 0,
1263     "interruption",       SCMD_INT, 0,
1264     "more-prompting",     SCMD_MOR, 0,
1265     "quoting",            SCMD_QUO, 0,
1266 #ifdef CK_RECALL
1267     "recall-buffer-size", SCMD_RCL, 0,
1268 #endif /* CK_RECALL */
1269 #ifdef CK_RECALL
1270     "retry",              SCMD_RTR, 0,
1271 #endif /* CK_RECALL */
1272 #ifdef OS2
1273 #ifdef ONETERMUPD
1274     "scrollback",         SCMD_SCR, 0,
1275     "statusline",         SCMD_STA, 0,
1276 #endif /* ONETERMUPD */
1277 #endif /* OS2 */
1278     "variable-evaluation", SCMD_VAR,0,
1279     "width",              SCMD_WID, 0
1280 };
1281 static int nbytt = (sizeof(scmdtab) / sizeof(struct keytab));
1282
1283 #ifndef NOSERVER
1284 /* Server parameters table */
1285 static struct keytab srvtab[] = {
1286     "cd-message",   XYSERC, 0,
1287     "display",      XYSERD, 0,
1288     "get-path",     XYSERP, 0,
1289     "idle-timeout", XYSERI, 0,
1290     "keepalive",    XYSERK, 0,
1291     "login",        XYSERL, 0,
1292     "timeout",      XYSERT, 0
1293 };
1294 static int nsrvt = (sizeof(srvtab) / sizeof(struct keytab));
1295 #endif /* NOSERVER */
1296
1297 static struct keytab sleeptab[] = {     /* SET SLEEP table */
1298     "cancellation",  0,   0
1299 };
1300
1301 static struct keytab tstab[] = {        /* SET TRANSFER/XFER table */
1302     "bell",            XYX_BEL, 0,
1303 #ifdef XFRCAN
1304     "cancellation",    XYX_CAN, 0,
1305 #endif /* XFRCAN */
1306 #ifndef NOCSETS
1307     "character-set",   XYX_CSE, 0,
1308 #endif /* NOCSETS */
1309 #ifndef NOSPL
1310     "crc-calculation", XYX_CRC, 0,
1311 #endif /* NOSPL */
1312     "display",         XYX_DIS, 0,
1313     "interruption",    XYX_INT, 0,
1314     "locking-shift",   XYX_LSH, 0,
1315     "message",         XYX_MSG, 0,
1316     "mode",            XYX_MOD, 0,
1317     "msg",             XYX_MSG, CM_INV,
1318 #ifdef PIPESEND
1319     "pipes",           XYX_PIP, 0,
1320 #endif /* PIPESEND */
1321 #ifdef CK_XYZ
1322     "protocol",        XYX_PRO, 0,
1323 #endif /* CK_XYZ */
1324     "report",          XYX_RPT, 0,
1325     "slow-start",      XYX_SLO, 0,
1326 #ifndef NOCSETS
1327     "translation",     XYX_XLA, 0,
1328 #else
1329     "translation",     XYX_XLA, CM_INV,
1330 #endif /* NOCSETS */
1331     "xlation",         XYX_XLA, CM_INV,
1332     "", 0, 0
1333 };
1334 static int nts = (sizeof(tstab) / sizeof(struct keytab)) - 1;
1335
1336 static struct keytab rtstab[] = {       /* REMOTE SET TRANSFER/XFER table */
1337 #ifndef NOCSETS
1338     "character-set",   XYX_CSE, 0,
1339 #endif /* NOCSETS */
1340     "mode",            XYX_MOD, 0
1341 };
1342 static int nrts = (sizeof(rtstab) / sizeof(struct keytab));
1343
1344 struct keytab xfrmtab[] = {             /* TRANSFER MODE table */
1345     "automatic", XMODE_A, 0,
1346     "manual",    XMODE_M, 0
1347 };
1348
1349 #ifdef LOCUS
1350 extern int locus, autolocus;
1351
1352 static struct keytab locustab[] = {
1353 #ifdef KUI
1354     { "ask",     3, 0 },                /* Presently implemented in GUI only */
1355 #endif /* KUI */
1356     { "auto",    2, 0 },
1357     { "local",   1, 0 },
1358     { "remote",  0, 0 }
1359 };
1360 static int nlocustab = (sizeof(locustab) / sizeof(struct keytab));
1361
1362 #endif /* LOCUS */
1363
1364 #ifndef NOCSETS
1365 /* SET TRANSFER CHARACTER-SET table */
1366
1367 extern struct keytab tcstab[];
1368 extern int ntcs;
1369 #endif /* NOCSETS */
1370
1371 /* SET TRANSFER LOCKING-SHIFT table */
1372 struct keytab lstab[] = {
1373     "forced", 2,   0,
1374     "off",    0,   0,
1375     "on",     1,   0
1376 };
1377 int nls = (sizeof(lstab) / sizeof(struct keytab));
1378
1379 /* SET TELNET tables */
1380 #ifdef TNCODE
1381 extern int tn_nlm, tn_b_nlm, tn_b_meu, tn_b_ume, tn_b_xfer, tn_sb_bug;
1382 extern int tn_no_encrypt_xfer, tn_auth_krb5_des_bug;
1383 extern int tn_wait_flg, tn_duplex, tn_delay_sb, tn_sfu;
1384 extern int sl_tn_saved;
1385 extern int tn_infinite;
1386 extern int tn_rem_echo;
1387 extern int tn_deb;
1388 extern int tn_auth_how;
1389 extern int tn_auth_enc;
1390 #ifdef CK_FORWARD_X
1391 extern char * tn_fwdx_xauthority;
1392 #endif /* CK_FORWARD_X */
1393 #ifdef CK_AUTHENTICATION
1394 static struct keytab setauth[] = {
1395 #ifdef CK_KERBEROS
1396     "k4",        AUTH_KRB4, CM_INV,
1397     "k5",        AUTH_KRB5, CM_INV,
1398     "kerberos4", AUTH_KRB4, 0,
1399     "kerberos5", AUTH_KRB5, 0,
1400     "kerberos_iv",AUTH_KRB4, CM_INV,
1401     "kerberos_v", AUTH_KRB5, CM_INV,
1402     "krb4",      AUTH_KRB4, CM_INV,
1403     "krb5",      AUTH_KRB5, CM_INV,
1404 #endif /* CK_KERBEROS */
1405 #ifdef CK_SRP
1406     "srp",       AUTH_SRP,  0,
1407 #endif /* CK_SRP */
1408 #ifdef CK_SSL
1409     "ssl",      AUTH_SSL,   0,
1410     "tls",      AUTH_TLS,   0,
1411 #endif /* CK_SSL */
1412     "",         0,      0
1413 };
1414 static int nsetauth = sizeof(setauth)/sizeof(struct keytab) - 1;
1415 #ifdef CK_KERBEROS
1416 extern char * krb5_d_principal;         /* Default principal */
1417 extern char * krb5_d_instance;
1418 extern char * krb5_d_realm;             /* Default realm */
1419 extern char * krb5_d_cc;                /* Default credentials cache */
1420 extern char * krb5_d_srv;               /* Default service name */
1421 extern int    krb5_d_lifetime;          /* Default lifetime */
1422 extern int    krb5_d_forwardable;
1423 extern int    krb5_d_proxiable;
1424 extern int    krb5_d_renewable;
1425 extern int    krb5_autoget;
1426 extern int    krb5_autodel;
1427 extern int    krb5_d_getk4;
1428 extern int    krb5_checkaddrs;          /* Check TGT Addrs */
1429 extern int    krb5_d_no_addresses;
1430 extern char * krb5_d_addrs[];
1431 extern char * k5_keytab;                /* Keytab file */
1432
1433 extern struct krb4_init_data krb4_init;
1434 extern char * krb4_d_principal;         /* Default principal */
1435 extern char * krb4_d_realm;             /* Default realm */
1436 extern char * krb4_d_srv;               /* Default service name */
1437 extern int    krb4_d_lifetime;          /* Default lifetime */
1438 extern int    krb4_d_preauth;
1439 extern char * krb4_d_instance;
1440 extern int    krb4_autoget;
1441 extern int    krb4_autodel;
1442 extern int    krb4_checkaddrs;          /* Check TGT Addrs */
1443 extern char * k4_keytab;                /* Keytab file */
1444 #ifdef KRB4
1445 extern int    k4debug;
1446 #endif /* KRB4 */
1447 static struct keytab krbver[] = {
1448     "4",                 4, 0,
1449     "5",                 5, 0,
1450     "iv",                4, CM_INV,
1451     "v",                 5, CM_INV
1452 };
1453 static int nkrbver = sizeof(krbver)/sizeof(struct keytab);
1454
1455 static struct keytab kdestab[] = {
1456     "never",            KRB_DEL_NO, 0,
1457     "no",               KRB_DEL_NO, CM_INV,
1458     "on-close",         KRB_DEL_CL, 0,
1459     "on-exit",          KRB_DEL_EX, 0
1460 };
1461 static int nkdestab = sizeof(kdestab)/sizeof(struct keytab);
1462
1463 static struct keytab k4tab[] = {
1464     "autodel",           XYKRBDEL, CM_INV,
1465     "autodestroy",       XYKRBDEL, 0,
1466     "autoget",           XYKRBGET, 0,
1467     "check-address",     XYKRBADR, 0,
1468     "debug",             XYKRBDBG, CM_INV,
1469     "instance",          XYKRBINS, 0,
1470     "keytab",            XYKRBKTB, 0,
1471     "lifetime",          XYKRBLIF, 0,
1472     "preauth",           XYKRBPRE, 0,
1473     "principal",         XYKRBPR,  0,
1474     "prompt",            XYKRBPRM, 0,
1475     "realm",             XYKRBRL,  0,
1476     "service-name",      XYKRBSRV, 0
1477 };
1478 static int nk4tab = sizeof(k4tab)/sizeof(struct keytab);
1479
1480 static struct keytab k5tab[] = {
1481     "addresses",         XYKRBADD, 0,
1482     "autodelete",        XYKRBDEL, CM_INV,
1483     "autodestroy",       XYKRBDEL, 0,
1484     "autoget",           XYKRBGET, 0,
1485     "cc",                XYKRBCC,  CM_INV,
1486     "check-address",     XYKRBADR, 0,
1487     "credentials-cache", XYKRBCC,  0,
1488     "forwardable",       XYKRBFWD, 0,
1489     "get-k4-tgt",        XYKRBK5K4,0,
1490     "instance",          XYKRBINS, 0,
1491     "keytab",            XYKRBKTB, 0,
1492     "lifetime",          XYKRBLIF, 0,
1493     "no-addresses",      XYKRBNAD, 0,
1494     "principal",         XYKRBPR,  0,
1495     "prompt",            XYKRBPRM, 0,
1496     "proxiable",         XYKRBPRX, 0,
1497     "realm",             XYKRBRL,  0,
1498     "renewable",         XYKRBRNW, 0,
1499     "service-name",      XYKRBSRV, 0
1500 };
1501 static int nk5tab = sizeof(k5tab)/sizeof(struct keytab);
1502
1503 #define KRB_PW_PRM 1
1504 #define KRB_PR_PRM 2
1505
1506 static struct keytab krbprmtab[] = {
1507     "password",  KRB_PW_PRM, 0,
1508     "principal", KRB_PR_PRM, 0
1509 };
1510
1511 #endif /* CK_KERBEROS */
1512 #ifdef CK_SRP
1513 static struct keytab srptab[] = {
1514     "prompt",            XYSRPPRM, 0
1515 };
1516 static int nsrptab = sizeof(srptab)/sizeof(struct keytab);
1517 #define SRP_PW_PRM 1
1518
1519 static struct keytab srpprmtab[] = {
1520     "password",  SRP_PW_PRM, 0
1521 };
1522 #endif /* CK_SRP */
1523 #ifdef CK_SSL
1524 static struct keytab ssltab[] = {
1525     "certs-ok",          XYSSLCOK,  CM_INV,
1526     "cipher-list",       XYSSLCL,   0,
1527     "crl-dir",           XYSSLCRLD, 0,
1528     "crl-file",          XYSSLCRL,  0,
1529     "debug",             XYSSLDBG,  0,
1530     "dh-key-file",       XYSSLDKFL, CM_INV,
1531     "dh-param-file",     XYSSLDPFL, 0,
1532     "dsa-cert-chain-file", XYSSLDCCF, 0,
1533     "dsa-cert-file",     XYSSLDCFL, 0,
1534     "dsa-key-file",      XYSSLDKFL, 0,
1535     "dummy",             XYSSLDUM,  CM_INV,
1536     "only",              XYSSLON,   CM_INV,
1537     "random-file",       XYSSLRND,  0,
1538     "rsa-cert-chain-file", XYSSLRCCF, 0,
1539     "rsa-cert-file",     XYSSLRCFL, 0,
1540     "rsa-key-file",      XYSSLRKFL, 0,
1541     "verbose",           XYSSLVRB,  0,
1542     "verify",            XYSSLVRF,  0,
1543     "verify-dir",        XYSSLVRFD, 0,
1544     "verify-file",       XYSSLVRFF, 0
1545 };
1546 static int nssltab = sizeof(ssltab)/sizeof(struct keytab);
1547 static struct keytab sslvertab[] = {
1548     "fail-if-no-peer-cert", SSL_VERIFY_PEER |
1549                             SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0,
1550     "no",               SSL_VERIFY_NONE, 0,
1551     "none",             SSL_VERIFY_NONE, CM_INV,
1552     "off",              SSL_VERIFY_NONE, CM_INV,
1553     "on",               SSL_VERIFY_PEER, CM_INV,
1554     "peer-cert",        SSL_VERIFY_PEER, 0
1555 };
1556 static int nsslvertab = sizeof(sslvertab)/sizeof(struct keytab);
1557 #endif /* CK_SSL */
1558 #endif /* CK_AUTHENTICATION */
1559 #ifdef CK_ENCRYPTION
1560 int cx_type = CX_AUTO;
1561 extern int sl_cx_type;
1562 #endif /* CK_ENCRYPTION */
1563 extern char *tcp_address;
1564 #ifndef NOHTTP
1565 extern char * tcp_http_proxy;
1566 extern char * tcp_http_proxy_user;
1567 extern char * tcp_http_proxy_pwd;
1568 extern char * tcp_http_proxy_agent;
1569 #endif /* NOHTTP */
1570 #ifdef NT
1571 #ifdef CK_SOCKS
1572 extern char *tcp_socks_svr;
1573 extern char *tcp_socks_user;
1574 #ifdef CK_SOCKS_NS
1575 extern char *tcp_socks_ns;
1576 #endif /* CK_SOCKS_NS */
1577 #endif /* CK_SOCKS */
1578 #endif /* NT */
1579
1580 #define UPW_USER  1
1581 #define UPW_PASS  2
1582 #define UPW_AGENT 3
1583
1584 static struct keytab userpass[] = {
1585     { "/agent",   UPW_AGENT, CM_ARG },
1586     { "/password", UPW_PASS, CM_ARG },
1587     { "/user",     UPW_USER, CM_ARG },
1588 };
1589 static int nuserpass = sizeof(userpass)/sizeof(struct keytab);
1590
1591 static struct keytab tnnegtab[] = {     /* TELNET NEGOTIATION table */
1592     "accepted",  TN_NG_AC, 0,
1593     "refused",   TN_NG_RF, 0,
1594     "req",       TN_NG_RQ, CM_INV|CM_ABR,
1595     "requ",      TN_NG_RQ, CM_INV|CM_ABR,
1596     "reque",     TN_NG_RQ, CM_INV|CM_ABR,
1597     "reques",    TN_NG_RQ, CM_INV|CM_ABR,
1598     "request",   TN_NG_RQ, CM_INV|CM_ABR,
1599     "requeste",  TN_NG_RQ, CM_INV|CM_ABR,
1600     "requested", TN_NG_RQ, 0,
1601     "required",  TN_NG_MU, 0
1602 };
1603 static int ntnnegtab = sizeof(tnnegtab)/sizeof(struct keytab);
1604
1605 #ifdef CK_ENCRYPTION
1606 static struct keytab typkwd[] = {
1607     "/type", 0, CM_ARG
1608 };
1609
1610 static struct keytab tnenctab[] = {     /* TELNET ENCRYPTION table */
1611     "accepted",   TN_NG_AC,    CM_INV,
1612     "refused",    TN_NG_RF,    CM_INV,
1613     "req",        TN_NG_RQ,    CM_INV|CM_ABR,
1614     "requ",       TN_NG_RQ,    CM_INV|CM_ABR,
1615     "reque",      TN_NG_RQ,    CM_INV|CM_ABR,
1616     "reques",     TN_NG_RQ,    CM_INV|CM_ABR,
1617     "request",    TN_NG_RQ,    CM_INV|CM_ABR,
1618     "requeste",   TN_NG_RQ,    CM_INV|CM_ABR,
1619     "requested",  TN_NG_RQ,    CM_INV,
1620     "required",   TN_NG_MU,    CM_INV,
1621     "start",      TN_EN_START, CM_INV,
1622     "stop",       TN_EN_STOP,  CM_INV,
1623     "type",       TN_EN_TYP,   0
1624 };
1625 static int ntnenc = sizeof(tnenctab)/sizeof(struct keytab) ;
1626 #endif /* CK_ENCRYPTION */
1627
1628 #ifdef CK_FORWARD_X
1629 static struct keytab tnfwdxtab[] = {    /* TELNET FORWARD-X table */
1630     "no-encryption",    1,  CM_INV,
1631     "xauthority-file",  0,  0
1632 };
1633 static int ntnfwdx = sizeof(tnfwdxtab)/sizeof(struct keytab) ;
1634 #endif /* CK_FORWARD_X */
1635
1636 static struct keytab tnbugtab[] = {     /* TELNET BUG table */
1637     "auth-krb5-des",         4, 0,
1638     "binary-me-means-u-too", 0, 0,
1639     "binary-u-means-me-too", 1, 0,
1640     "infinite-loop-check",   2, 0,
1641     "sb-implies-will-do",    3, 0
1642 };
1643
1644 #ifdef CK_ENVIRONMENT
1645 static struct keytab tnenvtab[] = {     /* TELNET ENVIRONMENT table */
1646     "acct",     TN_ENV_ACCT,    0,
1647     "display",  TN_ENV_DISP,    0,
1648     "job",      TN_ENV_JOB,     0,
1649     "location", TN_ENV_LOC,     0,
1650     "off",      TN_ENV_OFF,     CM_INV,
1651     "on",       TN_ENV_ON,      CM_INV,
1652     "printer",  TN_ENV_PRNT,    0,
1653     "systemtype",TN_ENV_SYS,    0,
1654     "user",     TN_ENV_USR,     0,
1655     "uservar",  TN_ENV_UVAR,    0,
1656     "", 0, 0
1657 };
1658 static int ntnenv = sizeof(tnenvtab)/sizeof(struct keytab) - 1;
1659 #endif /* CK_ENVIRONMENT */
1660
1661 #ifdef CK_AUTHENTICATION
1662 static struct keytab tnauthtab[] = {    /* TELNET AUTHENTICATION table */
1663     "accepted",   TN_NG_AC,  CM_INV,
1664     "encrypt-flag", TN_AU_ENC, 0,
1665     "forwarding", TN_AU_FWD,   0,
1666     "how-flag",   TN_AU_HOW,   0,
1667     "refused",    TN_NG_RF,  CM_INV,
1668     "req",        TN_NG_RQ,  CM_INV|CM_ABR,
1669     "requ",       TN_NG_RQ,  CM_INV|CM_ABR,
1670     "reque",      TN_NG_RQ,  CM_INV|CM_ABR,
1671     "reques",     TN_NG_RQ,  CM_INV|CM_ABR,
1672     "request",    TN_NG_RQ,  CM_INV|CM_ABR,
1673     "requeste",   TN_NG_RQ,  CM_INV|CM_ABR,
1674     "requested",  TN_NG_RQ,  CM_INV,
1675     "required",   TN_NG_MU,  CM_INV,
1676     "type",       TN_AU_TYP, 0
1677 };
1678 static int ntnauth = sizeof(tnauthtab)/sizeof(struct keytab) ;
1679
1680 struct keytab autyptab[] = {    /* TELNET AUTHENTICATION TYPE table */
1681     "automatic",  AUTH_AUTO, 0,
1682 #ifdef CK_KERBEROS
1683     "k4",         AUTH_KRB4, CM_INV,
1684     "k5",         AUTH_KRB5, CM_INV,
1685     "kerberos4",  AUTH_KRB4, 0,
1686     "kerberos5",  AUTH_KRB5, 0,
1687     "kerberos_iv",AUTH_KRB4, CM_INV,
1688     "kerberos_v", AUTH_KRB5, CM_INV,
1689     "krb4",       AUTH_KRB4, CM_INV,
1690     "krb5",       AUTH_KRB5, CM_INV,
1691 #endif /* CK_KERBEROS */
1692     "none",       AUTH_NONE, 0,
1693 #ifdef NT
1694     "ntlm",       AUTH_NTLM, 0,
1695 #endif /* NT */
1696 #ifdef CK_SRP
1697     "srp",        AUTH_SRP,  0,
1698 #endif /* CK_SRP */
1699 #ifdef CK_SSL
1700     "ssl",        AUTH_SSL,  0,
1701 #endif /* CK_SSL */
1702     "", 0, 0
1703 };
1704 int nautyp = sizeof(autyptab)/sizeof(struct keytab) - 1;
1705
1706 struct keytab auhowtab[] = {    /* TELNET AUTHENTICATION HOW table */
1707     "any",     TN_AUTH_HOW_ANY,     0,
1708     "mutual",  TN_AUTH_HOW_MUTUAL,  0,
1709     "one-way", TN_AUTH_HOW_ONE_WAY, 0,
1710     "", 0, 0
1711 };
1712 int nauhow = sizeof(auhowtab)/sizeof(struct keytab) - 1;
1713
1714 struct keytab auenctab[] = {    /* TELNET AUTHENTICATION ENCRYPT table */
1715     "any",     TN_AUTH_ENC_ANY,     0,
1716     "none",    TN_AUTH_ENC_NONE,    0,
1717     "telopt",  TN_AUTH_ENC_TELOPT,  0,
1718 #ifdef CK_SSL
1719     "tls",     TN_AUTH_ENC_TLS,     0,
1720 #endif /* CK_SSL */
1721     "", 0, 0
1722 };
1723 int nauenc = sizeof(auenctab)/sizeof(struct keytab) - 1;
1724 #endif /* CK_AUTHENTICATION */
1725
1726 #define TN_NL_BIN 3
1727 #define TN_NL_NVT 4
1728 static struct keytab tn_nlmtab[] = {    /* TELNET NEWLINE-MODE table */
1729     "binary-mode", TN_NL_BIN, 0,        /* Binary mode */
1730     "nvt",    TN_NL_NVT, 0,             /* NVT mode */
1731     "off",    TNL_CRNUL, CM_INV,        /* CR-NUL (TELNET spec) */
1732     "on",     TNL_CRLF,  CM_INV,        /* CR-LF (TELNET spec) */
1733     "raw",    TNL_CR,    CM_INV         /* CR only (out of spec) */
1734 };
1735 static int ntn_nlm = (sizeof(tn_nlmtab) / sizeof(struct keytab));
1736
1737 static struct keytab tnlmtab[] = {      /* TELNET NEWLINE-MODE table */
1738     "cr",     TNL_CR,    CM_INV,        /* CR only (out of spec) */
1739     "cr-lf",  TNL_CRLF,  CM_INV,        /* CR-LF (TELNET spec) */
1740     "cr-nul", TNL_CRNUL, CM_INV,        /* CR-NUL (TELNET spec) */
1741     "lf",     TNL_LF,    CM_INV,        /* LF instead of CR-LF */
1742     "off",    TNL_CRNUL, 0,             /* CR-NUL (TELNET spec) */
1743     "on",     TNL_CRLF,  0,             /* CR-LF (TELNET spec) */
1744     "raw",    TNL_CR,    0              /* CR only (out of spec) */
1745 };
1746 static int ntnlm = (sizeof(tnlmtab) / sizeof(struct keytab));
1747
1748 struct keytab tntab[] = {
1749 #ifdef CK_AUTHENTICATION
1750     "authentication",       CK_TN_AU,  0,
1751 #endif /* CK_AUTHENTICATION */
1752     "b",                    CK_TN_BM,  CM_INV|CM_ABR,
1753     "bi",                   CK_TN_BM,  CM_INV|CM_ABR,
1754     "bin",                  CK_TN_BM,  CM_INV|CM_ABR,
1755     "bina",                 CK_TN_BM,  CM_INV|CM_ABR,
1756     "binar",                CK_TN_BM,  CM_INV|CM_ABR,
1757     "binary",               CK_TN_BM,  CM_INV|CM_ABR,
1758     "binary-",              CK_TN_BM,  CM_INV|CM_ABR,
1759     "binary-mode",          CK_TN_BM,  CM_INV,
1760     "binary-transfer-mode", CK_TN_XF,  0,
1761     "binary-xfer-mode",     CK_TN_XF,  CM_INV,
1762     "bug",                  CK_TN_BUG, 0,
1763     "debug",                CK_TN_DB,  0,
1764     "delay-sb",             CK_TN_DL,  0,
1765     "echo",                 CK_TN_EC,  0,
1766 #ifdef CK_ENCRYPTION
1767     "encryption",      CK_TN_ENC,  0,
1768 #endif /* CK_ENCRYPTION */
1769 #ifdef CK_ENVIRONMENT
1770     "environment",     CK_TN_ENV,  0,
1771 #endif /* CK_ENVIRONMENT */
1772 #ifdef CK_FORWARD_X
1773     "forward-x",       CK_TN_FX,   0,
1774 #endif /* CK_FORWARD_X */
1775 #ifdef IKS_OPTION
1776     "kermit",          CK_TN_IKS,  CM_INV,
1777 #endif /* IKS_OPTION */
1778 #ifdef CK_SNDLOC
1779     "location",        CK_TN_LOC,  0,
1780 #endif /* CK_SNDLOC */
1781 #ifdef CK_NAWS
1782     "naws",            CK_TN_NAWS, CM_INV,
1783 #endif /* CK_NAWS */
1784     "newline-mode",    CK_TN_NL,   0,
1785     "no-encrypt-during-xfer", CK_TN_NE, CM_INV,
1786     "prompt-for-userid",CK_TN_PUID,0,
1787     "remote-echo",     CK_TN_RE,   0,
1788 #ifdef CK_SSL
1789     "start-tls",       CK_TN_TLS,  CM_INV,
1790 #endif /* CK_SSL */
1791 #ifdef NT
1792     "sfu-compatibility", CK_TN_SFU, 0,
1793 #else
1794     "sfu-compatibility", CK_TN_SFU, CM_INV,
1795 #endif /* NT */
1796     "terminal-type",   CK_TN_TT,   0,
1797     "wait-for-negotiations", CK_TN_WAIT, 0,
1798 #ifdef CK_ENVIRONMENT
1799     "xdisplay-location",CK_TN_XD, CM_INV,
1800 #endif /* CK_ENVIRONMENT */
1801     "", 0, 0
1802 };
1803 int ntn = (sizeof(tntab) / sizeof(struct keytab)) - 1;
1804
1805 struct keytab tnopttab[] = {
1806 #ifdef CK_AUTHENTICATION
1807     "authentication",  CK_TN_AU,   0,
1808 #else
1809     "authentication",  CK_TN_AU,   CM_INV,
1810 #endif /* CK_AUTHENTICATION */
1811     "binary-mode",     CK_TN_BM,   0,
1812 #ifdef TN_COMPORT
1813     "c",               CK_TN_CPC,   CM_INV|CM_ABR,
1814     "co",              CK_TN_CPC,   CM_INV|CM_ABR,
1815     "com",             CK_TN_CPC,   CM_INV|CM_ABR,
1816     "com-port-control",CK_TN_CPC,   0,
1817     "comport-control", CK_TN_CPC,   CM_INV,
1818 #else /* TN_COMPORT */
1819     "com-port-control",CK_TN_CPC,  CM_INV,
1820     "comport-control", CK_TN_CPC,   CM_INV,
1821 #endif /* TN_COMPORT */
1822     "echo",            CK_TN_EC,   0,
1823 #ifdef CK_ENCRYPTION
1824     "encryption",      CK_TN_ENC,  0,
1825 #else
1826     "encryption",      CK_TN_ENC,  CM_INV,
1827 #endif /* CK_ENCRYPTION */
1828 #ifdef CK_FORWARD_X
1829     "forward-x",       CK_TN_FX,   0,
1830 #else /* CK_FORWARD_X */
1831     "forward-x",       CK_TN_FX,   CM_INV,
1832 #endif /* CK_FORWARD_X */
1833     "ibm-sak",         CK_TN_SAK,  CM_INV,
1834 #ifdef IKS_OPTION
1835     "kermit",          CK_TN_IKS,  0,
1836 #else
1837     "kermit",          CK_TN_IKS,  CM_INV,
1838 #endif /* IKS_OPTION */
1839     "lflow",           CK_TN_FLW,  CM_INV,
1840     "logout",          CK_TN_LOG,  0,
1841 #ifdef CK_NAWS
1842     "naws",            CK_TN_NAWS, 0,
1843 #else
1844     "naws",            CK_TN_NAWS, CM_INV,
1845 #endif /* CK_NAWS */
1846 #ifdef CK_ENVIRONMENT
1847     "new-environment", CK_TN_ENV,  0,
1848 #else
1849     "new-environment", CK_TN_ENV,  CM_INV,
1850 #endif /* CK_ENVIRONMENT */
1851     "pragma-heartbeat",CK_TN_PHR,  CM_INV,
1852     "pragma-logon",    CK_TN_PLG,  CM_INV,
1853     "pragma-sspi",     CK_TN_PSP,  CM_INV,
1854     "sak",             CK_TN_SAK,  CM_INV,
1855 #ifdef CK_SNDLOC
1856     "send-location",   CK_TN_LOC,  0,
1857 #else
1858     "send-location",   CK_TN_LOC,  CM_INV,
1859 #endif /* CK_SNDLOC */
1860     "sga",             CK_TN_SGA, CM_INV|CM_ABR,
1861 #ifdef CK_SSL
1862     "start-tls",       CK_TN_TLS,  0,
1863 #else
1864     "start-tls",       CK_TN_TLS,  CM_INV,
1865 #endif /* CK_SSL */
1866     "suppress-go-aheads", CK_TN_SGA, 0,
1867     "terminal-type",   CK_TN_TT,   0,
1868     "ttype",           CK_TN_TT,   CM_INV|CM_ABR,
1869 #ifdef CK_ENVIRONMENT
1870     "xdisplay-location", CK_TN_XD, 0,
1871 #else
1872     "xdisplay-location", CK_TN_XD, CM_INV,
1873 #endif /* CK_ENVIRONMENT */
1874     "", 0, 0
1875 };
1876 int ntnopt = (sizeof(tnopttab) / sizeof(struct keytab)) - 1;
1877
1878 struct keytab tnoptsw[] = {
1879     "/client",  CK_TN_CLIENT,   0,
1880     "/server",  CK_TN_SERVER,   0
1881 };
1882 int ntnoptsw = (sizeof(tnoptsw) / sizeof(struct keytab));
1883 #endif /* TNCODE */
1884
1885 struct keytab ftrtab[] = {              /* Feature table */
1886 #ifndef NOCSETS                         /* 0 = we have it, 1 = we don't */
1887 "character-sets",       0, 0,
1888 #else
1889 "character-sets",       1, 0,
1890 #endif /* NOCSETS */
1891 #ifndef NOCYRIL
1892 "cyrillic",             0, 0,
1893 #else
1894 "cyrillic",             1, 0,
1895 #endif /* NOCYRIL */
1896
1897 #ifndef NOLOGDIAL
1898 "cx-log",               0, 0,
1899 #else
1900 "cx-log",               1, 0,
1901 #endif /* NOLOGDIAL */
1902
1903 #ifndef NODEBUG
1904 "debug",                0, 0,
1905 #else
1906 "debug",                1, 0,
1907 #endif /* NODEBUG */
1908
1909 #ifndef NODIAL
1910 "dial",                 0, 0,
1911 #else
1912 "dial",                 1, 0,
1913 #endif /* NODIAL */
1914
1915 #ifdef DYNAMIC
1916 "dynamic-memory",       0, 0,
1917 #else
1918 "dynamic-memory",       1, 0,
1919 #endif /* DYNAMIC */
1920
1921 #ifndef NOXFER
1922 "file-transfer",        0, 0,
1923 #else
1924 "file-transfer",        1, 0,
1925 #endif /* NOXFER */
1926
1927 #ifdef XXFWD
1928 "forward",              0, 0,
1929 #else
1930 "forward",              1, 0,
1931 #endif /* XXFWD */
1932
1933 #ifdef NEWFTP
1934 "ftp",                  0, 0,
1935 #else
1936 "ftp",                  1, 0,
1937 #endif /* NEWFTP */
1938
1939 #ifdef CK_CURSES
1940 "fullscreen-display",   0, 0,
1941 #else
1942 "fullscreen-display",   1, 0,
1943 #endif /* CK_CURSES */
1944 #ifdef GREEK
1945 "greek",                0, 0,
1946 #else
1947 "greek",                1, 0,
1948 #endif /* GREEK */
1949 #ifdef HEBREW
1950 "hebrew",               0, 0,
1951 #else
1952 "hebrew",               1, 0,
1953 #endif /* HEBREW */
1954 #ifndef NOHELP
1955 "help",                 0, 0,
1956 #else
1957 "help",                 1, 0,
1958 #endif /* NOHELP */
1959
1960 #ifndef NOIKSD
1961 "iksd",                 0, 0,
1962 #else
1963 "iksd",                 1, 0,
1964 #endif /* NOIKSD */
1965
1966 #ifndef NOSPL
1967 "if-command",           0, 0,
1968 #else
1969 "if-command",           1, 0,
1970 #endif /* NOSPL */
1971 #ifndef NOJC
1972 #ifdef UNIX
1973 "job-control",          0, 0,
1974 #else
1975 "job-control",          1, 0,
1976 #endif /* UNIX */
1977 #else
1978 "job-control",          1, 0,
1979 #endif /* NOJC */
1980 #ifdef KANJI
1981 "kanji",                0, 0,
1982 #else
1983 "kanji",                1, 0,
1984 #endif /* KANJI */
1985
1986 #ifndef NOXFER
1987 "kermit",               0, 0,
1988 #else
1989 "kermit",               1, 0,
1990 #endif /* NOXFER */
1991
1992 #ifdef CK_KERBEROS
1993 "kerberos",             0, 0,
1994 #else
1995 "kerberos",             1, 0,
1996 #endif /* CK_KERBEROS */
1997
1998 #ifndef NOCSETS
1999 "latin1",               0, 0,
2000 #else
2001 "latin1",               1, 0,
2002 #endif /* NOCSETS */
2003 #ifdef LATIN2
2004 "latin2",               0, 0,
2005 #else
2006 "latin2",               1, 0,
2007 #endif /* LATIN2 */
2008
2009 #ifdef CKLEARN
2010 "learned-scripts",       0, 0,
2011 #else
2012 "learned-scripts",       1, 0,
2013 #endif /* CKLEARN */
2014
2015 #ifndef NOLOCAL
2016 "making-connections",   0, 0,
2017 #else
2018 "making-connections",   1, 0,
2019 #endif /* NOLOCAL */
2020
2021 #ifdef NETCONN
2022 "network",              0, 0,
2023 #else
2024 "network",              1, 0,
2025 #endif /* NETCONN */
2026
2027 #ifdef NT
2028 #ifdef CK_AUTHENTICATION
2029 "ntlm",                 1, 0,
2030 #else /* CK_AUTHENTICATION */
2031 "ntlm",                 0, 0,
2032 #endif /* CK_AUTHENTICATION */
2033 #else /* NT */
2034 "ntlm",                 0, 0,
2035 #endif /* NT */
2036
2037 #ifdef PIPESEND
2038 "pipes",                0, 0,
2039 #else
2040 #ifdef NETCMD
2041 "pipes",                0, 0,
2042 #endif /* NETCMD */
2043 #endif /* PIPESEND */
2044 #ifndef PIPESEND
2045 #ifndef NETCMD
2046 "pipes",                1, 0,
2047 #endif /* PIPESEND */
2048 #endif /* NETCMD */
2049
2050 #ifdef NETPTY
2051 "pty",                  0, 0,
2052 #else
2053 "pty",                  1, 0,
2054 #endif /* NETPTY */
2055
2056 #ifndef NOPUSH
2057 "push",                 0, 0,
2058 #else
2059 "push",                 1, 0,
2060 #endif /* PUSH */
2061
2062 #ifdef CK_REDIR
2063 "redirect",             0, 0,
2064 #else
2065 "redirect",             1, 0,
2066 #endif /* CK_REDIR */
2067
2068 #ifdef CK_RTSCTS
2069 "rts/cts",              0, 0,
2070 #else
2071 "rts/cts",              1, 0,
2072 #endif /* RTS/CTS */
2073
2074 #ifndef NOSCRIPT
2075 "script-command",       0, 0,
2076 #else
2077 "script-command",       1, 0,
2078 #endif /* NOSCRIPT */
2079 #ifndef NOSERVER
2080 "server-mode",          0, 0,
2081 #else
2082 "server-mode",          1, 0,
2083 #endif /* NOSERVER */
2084
2085 #ifndef NOSEXP
2086 "sexpression",          0, 0,
2087 #else
2088 "sexpression",          1, 0,
2089 #endif /* NOSEXP */
2090
2091 #ifdef SFTP_BUILTIN
2092 "sftp",                 1, 0,
2093 #else
2094 "sftp",                 0, 0,
2095 #endif /* SFTP_BUILTIN */
2096
2097 #ifndef NOSHOW
2098 "show-command",         0, 0,
2099 #else
2100 "show-command",         1, 0,
2101 #endif /* NOSHOW */
2102
2103 #ifdef CK_SRP
2104 "srp",                  0, 0,
2105 #else
2106 "srp",                  1, 0,
2107 #endif /* CK_SRP */
2108
2109 #ifdef SSHBUILTIN
2110 "ssh",                  0, 0,
2111 #else /* SSHBUILTIN */
2112 "ssh",                  1, 0,
2113 #endif /* SSHBUILTIN */
2114
2115 #ifdef CK_SSL
2116 "ssl/tls",              0, 0,
2117 #else
2118 "ssl/tls",              1, 0,
2119 #endif /* CK_SSL */
2120
2121 #ifndef NOXMIT
2122 "transmit",             0, 0,
2123 #else
2124 "transmit",             1, 0,
2125 #endif /* NOXMIT */
2126
2127 #ifdef UNICODE
2128 "unicode",              0, 0,
2129 #else
2130 "unicode",              1, 0,
2131 #endif /* UNICODE */
2132
2133 #ifdef CK_XYZ
2134 "xyzmodem",             0, 0,
2135 #else
2136 "xyzmodem",             1, 0,
2137 #endif /* CK_XYZ */
2138
2139 "", 0, 0
2140 };
2141 int nftr = (sizeof(ftrtab) / sizeof(struct keytab)) - 1;
2142
2143 struct keytab desttab[] = {             /* SET DESTINATION */
2144 #ifdef CALIBRATE
2145     "calibrate", DEST_N, CM_INV,
2146 #endif /* CALIBRATE */
2147     "disk",    DEST_D, 0,
2148 #ifdef CALIBRATE
2149     "nowhere", DEST_N, 0,
2150 #endif /* CALIBRATE */
2151     "printer", DEST_P, 0,
2152     "screen",  DEST_S, 0
2153 };
2154 int ndests =  (sizeof(desttab) / sizeof(struct keytab));
2155
2156 #ifndef NOSPL           /* Used only with script programming items... */
2157
2158 #ifndef NOSERVER                        /* This is just to avoid some */
2159 #define CK_PARSDIR                      /* "statement not reached" */
2160 #else                                   /* complaints... */
2161 #ifndef NODIAL
2162 #define CK_PARSDIR
2163 #endif /* NODIAL */
2164 #endif /* NOSERVER */
2165
2166 /*
2167   cx == 0 means dial directory
2168   cx == 1 means network directory
2169   cx == 2 means a directory path list
2170 */
2171 static int
2172 parsdir(cx) int cx; {
2173     int i, x, y, dd;                    /* Workers */
2174     int nxdir;
2175     char *s;
2176     char ** xdir;
2177     char *pp[MAXGETPATH];               /* Temporary name pointers */
2178 #ifdef ZFNQFP
2179     struct zfnfp * fnp;
2180 #ifdef OS2
2181     char * env;
2182     char dirpath[4096];
2183 #else /* OS2 */
2184     char dirpath[1024];                 /* For fully qualified filenames */
2185 #endif /* OS2 */
2186 #endif /* ZFNQFP */
2187
2188     int max = 0;                        /* Maximum number of things to parse */
2189     char c;
2190
2191 #ifndef NODIAL
2192     if (cx == 0) {                      /* Dialing */
2193         nxdir = ndialdir;
2194         xdir = dialdir;
2195         max = MAXDDIR;
2196     } else
2197 #ifdef NETCONN
2198     if (cx == 1) {                      /* Network */
2199         nxdir = nnetdir;
2200         xdir = netdir;
2201         max = MAXDDIR;
2202     } else
2203 #endif /* NETCONN */
2204 #endif /* NODIAL */
2205 #ifndef NOSERVER
2206     if (cx == 2) {                      /* GET path */
2207         nxdir = ngetpath;
2208         xdir = getpath;
2209         max = MAXGETPATH;
2210     } else                              /* Called with invalid function code */
2211 #endif /* NOSERVER */
2212       return(-2);
2213
2214     for (i = 0; i < MAXGETPATH; i++)    /* Init these. */
2215       pp[i] = NULL;
2216
2217 #ifdef CK_PARSDIR
2218     dd = 0;                             /* Temporary name counter */
2219     while (1) {
2220         if (cx != 2) {                  /* Dialing or Network Directory */
2221 #ifdef OS2
2222             int len;
2223             char * appdata0 = NULL, * appdata1 = NULL;
2224 #ifdef NT
2225             env = getenv("K95PHONES");
2226             makestr(&appdata0,(char *)GetAppData(0));
2227             makestr(&appdata1,(char *)GetAppData(1));
2228 #else /* NT */
2229             env = getenv("K2PHONES");
2230 #endif /* NT */
2231             if (!env)
2232               env = getenv("K95PHONES");
2233             if (!env)
2234               env = "";
2235
2236             dirpath[0] = '\0';
2237             len = strlen(env) + 2*strlen(startupdir) + 2*strlen(inidir)
2238                 + (appdata0?2*strlen(appdata0):0) 
2239                 + (appdata1?2*strlen(appdata1):0)
2240                 + 2*strlen(zhome()) + 2*strlen(exedir) + 8*strlen("PHONES/")
2241                 + 12;
2242             if (len < 4096)             /* SAFE */
2243               sprintf(dirpath,
2244                     "%s%s%s;%s%s;%s%s%s%s%s%s%s%s%s;%s%s;%s;%s%s",
2245                     /* Semicolon-separated path list */
2246                     env,
2247                     (env[0] && env[strlen(env)-1] == ';') ? "" : ";",
2248                     startupdir,
2249                     startupdir, "PHONES/",
2250                     appdata1 ? appdata1 : "", 
2251                     appdata1 ? "Kermit 95;" : "",
2252                     appdata1 ? appdata1 : "", 
2253                     appdata1 ? "Kermit 95/PHONES/;" : "",
2254                     appdata0 ? appdata0 : "", 
2255                     appdata0 ? "Kermit 95;" : "",
2256                     appdata0 ? appdata0 : "", 
2257                     appdata0 ? "Kermit 95/PHONES/;" : "",
2258                     inidir,
2259                     inidir, "PHONES/",
2260                     zhome(),
2261                     zhome(), "PHONES/",
2262                     exedir,
2263                     exedir, "PHONES/"
2264                     );
2265 #ifdef NT
2266             makestr(&appdata0,NULL);
2267             makestr(&appdata1,NULL);
2268 #endif /* NT */
2269 #else
2270 #ifdef UNIX
2271             y = 1024;
2272             s = dirpath;
2273             zzstring("\\v(home)",&s,&y);
2274 #endif /* UNIX */
2275 #endif /* OS2 */
2276             y = cmifip(
2277                   "Names of one or more directory files, separated by spaces",
2278                        "",&s,&x,0,
2279 #ifdef OS2ORUNIX
2280                        dirpath,
2281 #else
2282                        NULL,
2283 #endif /* OS2ORUNIX */
2284                        xxstring
2285                        );
2286         } else {                        /* List of directory names */
2287             x = 0;
2288             y = cmdir("Directory name","",&s,xxstring);
2289         }
2290         if (y < 0) {
2291             if (y == -3) {              /* EOL or user typed <CR> */
2292                 if ((y = cmcfm()) < 0) return(y);
2293                 for (i = 0; i < max; i++) { /* Clear these */
2294                     if (i < nxdir && xdir[i]) {
2295                         free(xdir[i]);
2296                     }
2297                     xdir[i] = (i < dd) ? pp[i] : NULL;
2298                 }
2299 #ifndef NODIAL
2300                 if (cx == 0)
2301                   ndialdir = dd;
2302 #ifdef NETCONN
2303                 if (cx == 1)
2304                   nnetdir = dd;
2305 #endif /* NETCONN */
2306 #endif /* NODIAL */
2307 #ifndef NOSERVER
2308                 if (cx == 2)
2309                   ngetpath = dd;
2310 #endif /* NOSERVER */
2311                 return(success = 1);
2312
2313             } else {                    /* Parse error */
2314                 for (i = 0; i < dd; i++) {  /* Free temp storage */
2315                     if (pp[i]) free(pp[i]); /* but don't change */
2316                     pp[i] = NULL;           /* anything else */
2317                 }
2318                 return(y);
2319             }
2320         }
2321         if (x) {
2322             printf("?Wildcards not allowed\n");
2323             return(-9);
2324         }
2325 #ifdef CK_TMPDIR
2326         if (cx == 2 && !isdir(s)) {
2327             printf("?Not a directory - %s\n", s);
2328             return(-9);
2329         }
2330 #endif /* CK_TMPDIR */
2331
2332 #ifdef ZFNQFP
2333         if (cx < 2) {
2334             if (!isabsolute(s)) {       /* If not relative get full path */
2335                 if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
2336                     if (fnp->fpath)
2337                       if ((int) strlen(fnp->fpath) > 0)
2338                         s = fnp->fpath;
2339                 }
2340             }
2341         }
2342 #endif /* ZFNQFP */
2343         c = NUL;
2344         x = strlen(s);
2345         if (x > 0)                      /* Get last char */
2346           c = s[x-1];
2347         debug(F000,"parsdir s",s,c);
2348         if ((pp[dd] = malloc(strlen(s)+2)) == NULL) {
2349             printf("?Internal error - malloc\n");
2350             for (i = 0; i < dd; i++) {  /* Free temp storage */
2351                 if (pp[i]) free(pp[i]);
2352                 pp[i] = NULL;
2353             }
2354             return(-9);
2355         } else {                        /* Have storage for name */
2356             strcpy(pp[dd],s);           /* Copy string into new storage */
2357             debug(F111,"parsdir pp[dd] 1",pp[dd],dd);
2358 #ifndef NOXFER
2359             if (cx == 2) {              /* If we are parsing directories */
2360                 char dirsep[2];
2361                 extern int myindex;     /* Append directory separator if */
2362                 extern struct sysdata sysidlist[]; /* it is missing...   */
2363                 debug(F101,"parsdir myindex","",myindex);
2364                 if (myindex > -1)
2365                   if (sysidlist[myindex].sid_unixlike)
2366                     if (c != sysidlist[myindex].sid_dirsep) {
2367                         dirsep[0] = sysidlist[myindex].sid_dirsep;
2368                         dirsep[1] = NUL;
2369                         strcat(pp[dd], (char *) dirsep); /* safe */
2370                     }
2371             }
2372 #endif /* NOXFER */
2373             debug(F111,"parsdir pp[dd] 2",pp[dd],dd);
2374             if (++dd > max) {
2375                 printf("?Too many directories - %d max\n", max);
2376                 for (i = 0; i < dd; i++) {  /* Free temp storage */
2377                     if (pp[i]) free(pp[i]);
2378                     pp[i] = NULL;
2379                 }
2380             }
2381         }
2382     }
2383 #endif /* CK_PARSDIR */
2384 }
2385 #endif /* NOSPL */
2386
2387 #ifndef NOSERVER
2388 static int
2389 cklogin() {
2390     int x;
2391     char * s;
2392     char username[LOGINLEN+1];
2393     char password[LOGINLEN+1];
2394     char account[LOGINLEN+1];
2395     extern char * x_user, * x_passwd, * x_acct;
2396     extern int x_login, x_logged;
2397
2398     username[0] = NUL;
2399     password[0] = NUL;
2400     account[0]  = NUL;
2401
2402     x = cmfld("username", "", &s, xxstring);
2403     if (x != -3) {
2404         if (x < 0)
2405           return(x);
2406         if ((int)strlen(s) > LOGINLEN) {
2407             printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2408             return(-9);
2409         }
2410         ckstrncpy(username,s,LOGINLEN+1);
2411         x = cmfld("password", "", &s, xxstring);
2412         if (x != -3) {
2413             if (x < 0)
2414               return(x);
2415             if ((int)strlen(s) > LOGINLEN) {
2416                 printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2417                 return(-9);
2418             }
2419             ckstrncpy(password,s,LOGINLEN+1);
2420             x = cmfld("account", "", &s, xxstring);
2421             if (x != -3) {
2422                 if (x < 0)
2423                   return(x);
2424                 if ((int)strlen(s) > LOGINLEN) {
2425                     printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
2426                     return(-9);
2427                 }
2428                 ckstrncpy(account,s,LOGINLEN+1);
2429                 if ((x = cmcfm()) < 0)
2430                   return(x);
2431             }
2432         }
2433     }
2434     makestr(&x_user,username);
2435     makestr(&x_passwd,password);
2436     makestr(&x_acct,account);
2437     x_login = (x_user) ? 1 : 0;
2438     x_logged = 0;
2439     return(1);
2440 }
2441 #endif /* NOSERVER */
2442
2443 #ifndef NOLOCAL
2444 static int
2445 setdcd() {
2446     int x, y, z = 0;
2447     if ((y = cmkey(crrtab,ncrr,"","automatic",xxstring)) < 0) return(y);
2448     if (y == CAR_ON) {
2449         x = cmnum("Carrier wait timeout, seconds","0",10,&z,xxstring);
2450         if (x < 0) return(x);
2451     }
2452     if ((x = cmcfm()) < 0) return(x);
2453     carrier = ttscarr(y);
2454     cdtimo = z;
2455     return(1);
2456 }
2457 #endif /* NOLOCAL */
2458
2459 extern struct keytab yesno[];
2460 extern int nyesno;
2461
2462 /* g e t y e s n o  */
2463
2464 static struct keytab q0yesno[] = {      /* Yes/No/Quit keyword table */
2465     "no",    0, 0,
2466     "ok",    1, 0,
2467     "yes",   1, 0
2468 };
2469 static int nq0yesno = (sizeof(q0yesno) / sizeof(struct keytab));
2470
2471 static struct keytab q1yesno[] = {      /* Yes/No/Quit keyword table */
2472     "no",    0, 0,
2473     "ok",    1, 0,
2474     "quit",  2, 0,
2475     "yes",   1, 0
2476 };
2477 static int nq1yesno = (sizeof(q1yesno) / sizeof(struct keytab));
2478
2479 static struct keytab q2yesno[] = {      /* Yes/No/Quit keyword table */
2480     "go",    3, 0,
2481     "no",    0, 0,
2482     "ok",    1, 0,
2483     "yes",   1, 0
2484 };
2485 static int nq2yesno = (sizeof(q2yesno) / sizeof(struct keytab));
2486
2487 static struct keytab q3yesno[] = {      /* Yes/No/Quit keyword table */
2488     "go",    3, 0,
2489     "no",    0, 0,
2490     "ok",    1, 0,
2491     "quit",  2, 0,
2492     "yes",   1, 0
2493 };
2494 static int nq3yesno = (sizeof(q3yesno) / sizeof(struct keytab));
2495
2496
2497 /* Ask question, get yes/no answer */
2498
2499 int
2500 getyesno(msg, flags) char * msg; int flags; {
2501 #ifdef CK_RECALL
2502     extern int on_recall;               /* around Password prompting */
2503 #endif /* CK_RECALL */
2504     int y, z;
2505
2506 #ifndef NOLOCAL
2507 #ifdef OS2
2508     extern int vmode, win95_popup, startflags;
2509     int vmode_sav = vmode;
2510 #endif /* OS2 */
2511 #endif /* NOLOCAL */
2512
2513 #ifdef CK_APC
2514     if ( apcactive != APC_INACTIVE && (apcstatus & APC_NOINP) ) {
2515         return(success = 0);
2516     }
2517 #endif /* CK_APC */
2518
2519 #ifndef NOLOCAL
2520 #ifdef OS2
2521 #ifdef COMMENT
2522     if (win95_popup && !(startflags & 96)
2523 #ifdef IKSD
2524         && !inserver
2525 #endif /* IKSD */
2526         )
2527       return(popup_readyesno(vmode,NULL,msg,flags));
2528 #endif /* COMMENT */
2529     if (vmode == VTERM) {
2530         vmode = VCMD;
2531         VscrnIsDirty(VTERM);
2532         VscrnIsDirty(VCMD);
2533     }
2534 #endif /* OS2 */
2535 #endif /* NOLOCAL */
2536 #ifdef VMS
2537 /*
2538   In VMS, whenever a TAKE file or macro is active, we restore the
2539   original console modes so Ctrl-C/Ctrl-Y can work.  But here we
2540   go interactive again, so we have to temporarily put them back.
2541 */
2542     if (!xcmdsrc)
2543       concb((char)escape);
2544 #endif /* VMS */
2545
2546 #ifdef CK_RECALL
2547     on_recall = 0;
2548 #endif /* CK_RECALL */
2549     cmsavp(psave,PROMPTL);              /* Save old prompt */
2550     cmsetp(msg);                        /* Make new prompt */
2551     z = 0;                              /* Initialize answer to No. */
2552     cmini(ckxech);                      /* Initialize parser. */
2553     do {
2554         prompt(NULL);                   /* Issue prompt. */
2555         switch (flags) {
2556           case 0:  y = cmkey(q0yesno,nq0yesno,"","",NULL); break;
2557           case 1:  y = cmkey(q1yesno,nq1yesno,"","",NULL); break;
2558           case 2:  y = cmkey(q2yesno,nq2yesno,"","",NULL); break;
2559           default: y = cmkey(q3yesno,nq3yesno,"","",NULL);
2560         }
2561         if (y < 0) {
2562             if (y == -4) {              /* EOF */
2563                 z = y;
2564                 break;
2565             } else if (y == -3)         /* No answer? */
2566               printf(" Please respond; type '?' to see valid answers.\n");
2567             cmini(ckxech);
2568         } else {
2569             z = y;                      /* Save answer */
2570             y = cmcfm();                /* Get confirmation */
2571         }
2572     } while (y < 0);                    /* Continue till done */
2573     cmsetp(psave);                      /* Restore real prompt */
2574 #ifdef VMS
2575     if (cmdlvl > 0)                     /* In VMS and not at top level, */
2576       conres();                         /*  restore console again. */
2577 #endif /* VMS */
2578 #ifndef NOLOCAL
2579 #ifdef OS2
2580     if (vmode != vmode_sav) {
2581         vmode = VTERM;
2582         VscrnIsDirty(VCMD);
2583         VscrnIsDirty(VTERM);
2584     }
2585 #endif /* OS2 */
2586 #endif /* NOLOCAL */
2587     return(z);
2588 }
2589
2590 #ifdef KUI
2591 extern HWND hwndConsole;
2592 _PROTOTYP(int gui_txt_dialog,(char *,char *,int,char *,int,char *,int));
2593 _PROTOTYP(int gui_mtxt_dialog,(char *,int,struct txtbox []));
2594 _PROTOTYP(int gui_position,(int, int));
2595 _PROTOTYP(int gui_resize_mode,(int));
2596 _PROTOTYP(int gui_win_run_mode,(int));
2597 _PROTOTYP(int gui_saveas_dialog,(char *,char *, int, char *, char *, int));
2598 extern int gui_dialog;
2599 #endif /* KUI */
2600
2601 /* u q _ o k  --  User Query, get Yes/No or OK Cancel  */
2602 /*
2603   Call with:  
2604     preface: Explanatory text to print, or NULL.
2605     prompt:  Prompt.
2606     mask:    Bitmask for legal responses: 1 = OK or Yes; 2 = No or Cancel.
2607     help:    Help text (array of strings or NULL) [not used by parser].
2608     dflt:    Default response (1 or 2) [not used by parser].
2609   Returns:
2610    -1:       Invalid argument(s).
2611     0:       User said No or Cancel.
2612     1        User said Yes or OK.    
2613   Notes:
2614     preface and prompt should not include final line terminator but may
2615     include embedded ones.  Help text is in case GUI dialog needs a Help
2616     button; final element of help-string array is "".  dflt is used by GUI
2617     to highlight the default response button.
2618 */
2619 int
2620 #ifdef CK_ANSIC
2621 uq_ok(char * preface, char * prompt, int mask,char ** help, int dflt)
2622 #else /* CK_ANSIC */
2623 uq_ok(preface,prompt,mask,help,dflt)
2624     char * preface, * prompt, ** help;
2625     int mask, dflt;
2626 #endif /* CK_ANSIC */
2627 /* uq_ok */ {
2628     int rc, len;
2629     char * text=NULL;
2630
2631     if (!prompt)
2632       return(-1);
2633
2634     if ((mask & 3) == 1) {              /* OK (GUI only) */
2635 #ifdef KUI
2636       if ( gui_dialog ) {
2637         /* This one is for popup help, alerts, etc */
2638         if (preface) {
2639             len = strlen(preface) + strlen(prompt) + 4;
2640             text = (char *)malloc(len);
2641             ckmakmsg(text,len,preface,"\n",prompt,NULL);
2642         }
2643         rc = MessageBox(hwndConsole,
2644                          text ? text : prompt,
2645                          prompt,
2646                          MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2647         ShowWindowAsync(hwndConsole,SW_SHOWNORMAL);
2648         SetForegroundWindow(hwndConsole);
2649         if (text)
2650           free(text);
2651         if (!rc)
2652           return(-1);
2653         else 
2654           return(1);
2655       } else
2656 #endif  /* KUI */
2657       {
2658         if (preface)                    /* Just display the text, if any */
2659           printf("%s\n",preface);
2660         if (prompt)
2661           printf("%s\n",prompt);
2662         return(1);
2663       }
2664     } else if ((mask & 3) == 3) {       /* Yes/No or OK/Cancel */
2665 #ifdef KUI
2666       if ( gui_dialog ) {
2667         if (preface) {
2668             len = strlen(preface) + strlen(prompt) + 4;
2669             text = (char *)malloc(len);
2670             ckmakmsg(text,len,preface,"\n",prompt,NULL);
2671         }
2672         rc = MessageBox(hwndConsole,
2673                          text ? text : prompt,
2674                          prompt,
2675                          MB_YESNO | MB_ICONINFORMATION | MB_TASKMODAL | 
2676                          (dflt == 2 ? MB_DEFBUTTON2 : MB_DEFBUTTON1));
2677         ShowWindowAsync(hwndConsole,SW_SHOWNORMAL);
2678         SetForegroundWindow(hwndConsole);
2679         if (text)
2680           free(text);
2681         if (!rc)
2682           return(-1);
2683         else if (rc == IDNO || rc == IDCANCEL)
2684           return(0);
2685         else
2686           return(1);
2687       } else
2688 #endif  /* KUI */
2689       {
2690         if (preface)
2691           printf("%s\n",preface);
2692         return(getyesno(prompt,0));
2693       }
2694     } else {
2695         printf("?Internal error: uq_ok()\n");
2696         return(-1);
2697     }
2698 }
2699
2700 /* u q _ t x t  --  User Query, get single text response  */
2701 /*
2702   Call with:  
2703     preface: Explanatory text to print, or NULL.
2704     prompt:  Prompt. 
2705     echo:    0 = don't echo; 1 = echo; 2 = echo with asterisks.
2706     help:    Help text (array of strings or NULL) [not used by parser].
2707     buf:     Pointer to result buffer.
2708     buflen:  Length of result buffer.
2709     dflt:    Default response text or NULL [not used by parser].
2710     timer:   Optional Timeout
2711   Returns:
2712     0:       User said No or Cancel.
2713     1        User said Yes or OK.    
2714   Notes:
2715     preface, prompt, and help as for uq_ok().
2716 */
2717 int
2718 #ifdef CK_ANSIC
2719 uq_txt(char * preface, char * prompt, int echo, char ** help, char * buf, 
2720        int buflen, char *dflt, int timer)
2721 #else /* CK_ANSIC */
2722 uq_txt(preface,prompt,echo,help,buf,buflen,dflt,timer)
2723     char * preface, * prompt, ** help, * buf, * dflt; 
2724     int buflen, echo, timer;
2725 #endif /* CK_ANSIC */
2726 {
2727 #ifndef NOLOCAL
2728 #ifdef OS2
2729     extern int vmode;
2730     extern int startflags;
2731     extern int win95_popup;
2732 #endif /* OS2 */
2733 #endif /* NOLOCAL */
2734     int rc; 
2735
2736     if (buflen < 1 || !buf)
2737       return(0);
2738 #ifdef KUI
2739     if ( gui_dialog ) {
2740         rc = gui_txt_dialog(preface,prompt,echo,buf,buflen,dflt,timer);
2741         if ( rc > -1 )
2742             return(rc);
2743     /* Otherwise, the dialog could not be created.  Fallback to text mode */
2744     } 
2745 #endif /* KUI */
2746 #ifndef NOLOCAL
2747 #ifdef OS2
2748     if (win95_popup && !(startflags & 96)
2749 #ifdef IKSD
2750          && !inserver
2751 #endif /* IKSD */
2752          ) {
2753         debok = 0;                          /* Don't log */
2754         if (echo == 1)
2755                 popup_readtext(vmode,preface,prompt,buf,buflen,0);
2756             else
2757                 popup_readpass(vmode,preface,prompt,buf,buflen,0);
2758         debok = 1;
2759         return(1);
2760     }
2761 #endif /* OS2 */
2762 #endif /* NOLOCAL */
2763
2764     if (preface)
2765       printf("%s\n",preface);
2766     if (echo == 1)
2767       readtext(prompt,buf,buflen);
2768     else
2769       readpass(prompt,buf,buflen);
2770     return(1);                          /* (no buttons in parser) */
2771 }
2772
2773 /* u q _ m t x t  --  User Query, get multiple text responses */
2774 /*
2775   Call with:  
2776     preface: Explanatory text to print, or NULL.
2777     help:    Help text (array of strings or NULL) [not used by parser].
2778     n:       Number of responses wanted.
2779     field:   Array of struct txtbox, one element per field, see ckuusr.h.
2780   Returns:
2781     0:       User said No or Cancel.
2782     1        User said Yes or OK.    
2783   Notes:
2784     preface and help as for uq_ok().
2785 */
2786 int
2787 #ifdef CK_ANSIC
2788 uq_mtxt(char * preface,char **help, int n, struct txtbox field[])
2789 #else /* CK_ANSIC */
2790 uq_mtxt(preface,help,n,field)
2791     char * preface; char ** help; int n; struct txtbox field[]; 
2792 #endif /* CK_ANSIC */
2793 {
2794 #ifndef NOLOCAL
2795 #ifdef OS2
2796     extern int vmode;
2797     extern int startflags;
2798     extern int win95_popup;
2799 #endif /* OS2 */
2800 #endif /* NOLOCAL */
2801     int i, rc;
2802
2803     if (n < 1 || !field)
2804       return(0);
2805 #ifdef KUI
2806     if ( gui_dialog ) {
2807         rc = gui_mtxt_dialog(preface, n, field);
2808         if ( rc > -1 )
2809             return(rc);
2810     /* Otherwise, the dialog could not be created.  Fallback to text mode */
2811     }
2812 #endif /* KUI */
2813 #ifndef NOLOCAL
2814 #ifdef OS2
2815     if (win95_popup && !(startflags & 96)
2816 #ifdef IKSD
2817          && !inserver
2818 #endif /* IKSD */
2819          ) {
2820         debok = 0;                          /* Don't log */
2821         for (i = 0; i < n; i++) {
2822             if (field[i].t_echo == 1)
2823                 popup_readtext(vmode,preface,field[i].t_lbl,field[i].t_buf,field[i].t_len,0);
2824             else
2825                 popup_readpass(vmode,preface,field[i].t_lbl,field[i].t_buf,field[i].t_len,0);
2826         }
2827         debok = 1;
2828         return(1);
2829     }
2830 #endif /* OS2 */
2831 #endif /* NOLOCAL */
2832
2833     if (preface)
2834       printf("%s\n",preface);
2835     for (i = 0; i < n; i++) {
2836         if (field[i].t_echo == 1)
2837           readtext(field[i].t_lbl,field[i].t_buf,field[i].t_len);
2838         else
2839           readpass(field[i].t_lbl,field[i].t_buf,field[i].t_len);
2840     }
2841     return(1);
2842 }
2843
2844 /* u q _ f i l e  --  User Query, get file or directory name  */
2845 /*
2846   Call with:  
2847     preface: Explanatory text to print, or NULL.
2848     prompt:  Prompt string.
2849     fc:      Function code:
2850                1 = input (existing) file
2851                2 = existing directory 
2852                3 = create new output file
2853                4 = output file allowing append access
2854     help:    Help text (array of strings or NULL) [not used by parser].
2855     dflt:    Default response.
2856     result:  Pointer to result buffer.
2857     rlength: Length of result buffer.
2858
2859   Returns:
2860    -1:       Invalid argument, result too long, or other error.
2861     0:       User Canceled.
2862     1:       OK, with file/pathname copied to result buffer.
2863     2:       Like 1, but for output file that is to be appended to.
2864
2865   Notes:
2866     1. preface and prompt should not include final line terminator but may
2867        include embedded ones.  Help text is in case GUI dialog needs a Help
2868        button; final element of help-string array is "".
2869
2870     2. The default might be a filename, a directory name, a relative
2871        pathname, or an absolute pathname.  This routine must convert it into
2872        into a fully qualified (absolute) pathname so the user knows exactly
2873        where the file is to be found or stored.  In addition, the Windows
2874        version of this routine must separate the directory part from the
2875        name part, so it can display the given directory in the file dialog,
2876        and put name in the filename box to be edited, replaced, or
2877        accepted.
2878
2879     3. When called with FC 4, the Windows version should include "New" and
2880        "Append" buttons in the dialog. so the user can say whether the file
2881        should overwrite any file of the same name, or be appended to it.
2882 */
2883
2884 int
2885 #ifdef CK_ANSIC
2886 uq_file(char * preface, char * fprompt, int fc, char ** help,
2887         char * dflt, char * result, int rlength)
2888 #else /* CK_ANSIC */
2889 uq_file(preface,fprompt,fc,help,dflt,result,rlength)
2890     char * preface, * fprompt, ** help, * dflt, * result;
2891     int fc, rlength;
2892 #endif /* CK_ANSIC */
2893 /* uq_file */ {
2894
2895     int rc = -1, x, y, z;
2896     char * s, * p, * fullpath;
2897     char filebuf[CKMAXPATH+1];
2898
2899 #ifdef CK_RECALL
2900     extern int on_recall;
2901 #endif /* CK_RECALL */
2902
2903 #ifdef KUI
2904     if ( gui_dialog ) {
2905         rc = gui_saveas_dialog(preface,fprompt,fc,dflt,result,rlength);
2906         return rc;
2907     }
2908 #endif /* KUI */
2909
2910 #ifdef CK_RECALL
2911     on_recall = 0;
2912 #endif /* CK_RECALL */
2913
2914     if (preface)                        /* If prefatory text given... */
2915       printf("%s\n",preface);           /* display it. */
2916
2917     cmsavp(psave,PROMPTL);              /* Save old prompt */
2918
2919     /* We get the full pathname of the proposed output file just so */
2920     /* we can show it to the user but we don't use it ourselves. */
2921
2922     p = NULL;                           /* Build new prompt */
2923     if (!dflt) dflt = "";
2924     if (*dflt)                          /* Have default filename */
2925       zfnqfp(dflt,CKMAXPATH+1,filebuf); /* Get full path */
2926     else
2927       ckmakmsg(filebuf,CKMAXPATH+1,zgtdir(),"newfile",NULL,NULL);
2928     fullpath = filebuf;
2929     x = strlen(fullpath);
2930
2931     /* If no prompt given, build one that shows the proposed full pathname. */
2932
2933     if (!fprompt) fprompt = "";
2934     if (!*fprompt) fprompt = x ? " Filename" : " Filename: ";
2935     y = strlen(fprompt);
2936     if (x > 0) {                        /* Have default pathname? */
2937         p = (char *)malloc(x + y + 7);  /* Get temp storage */
2938         if (p) {                        /* Build prompt */
2939             ckmakmsg(p,x+y+7,fprompt," [",fullpath,"]: ");
2940             fprompt = p;
2941         }
2942     }
2943     cmsetp(fprompt);                    /* Make new prompt */
2944     if (p) free(p);                     /* Free temp storage */
2945     cmini(ckxech);                      /* Initialize parser. */
2946     x = -1;
2947     do {
2948         prompt(NULL);                   /* Issue prompt. */
2949         switch (fc) {                   /* Parse depends on function code */
2950           case 1:                       /* Input file */
2951             x = cmifi("Name of existing file",dflt,&s,&y,xxstring);
2952             rc = 1;
2953             break;
2954           case 2:                       /* Directory */
2955             x = cmdir("Directory name",dflt,&s,xxstring);
2956             rc = 1;
2957             break;
2958           case 3:                       /* New output file */
2959             /* Fall thru... */
2960           case 4:                       /* Output file - Append allowed */
2961             x = cmofi("Output file specification",dflt,&s,xxstring);
2962             rc = (fc == 4) ? 1 : 2;
2963             break;
2964           default:                      /* Bad function code */
2965             goto x_uq_file;
2966         }
2967         if (x < 0) {                    /* Parse error */
2968             filebuf[0] = NUL;
2969             if (x == -4) {              /* EOF */
2970                 break;
2971             } else if (x == -3)         /* No answer? */
2972               printf(fc == 2 ?
2973                      " Please enter a directory name.\n" :
2974                      " Please enter a filename.\n"
2975                      );
2976             cmini(ckxech);
2977         } else {
2978             z = strlen(s);
2979             if (z > rlength || ckstrncpy(filebuf,brstrip(s),CKMAXPATH+1) < z) {
2980                 printf("?Name too long\n");
2981                 x = -9;
2982             } else
2983               x = cmcfm();              /* Get confirmation */
2984         }
2985         if (fc == 1 && x > -1 && y > 0) {
2986             printf("?Wildcards not allowed\n");
2987             x = -9;
2988         }
2989     } while (x < 0);                    /* Continue till done */
2990
2991   x_uq_file:
2992     if (x < 0)
2993       rc = -1;
2994
2995     cmsetp(psave);                      /* Restore real prompt */
2996
2997     if (rc > 0)
2998       ckstrncpy(result,filebuf,rlength);
2999     return(rc);
3000 }
3001
3002
3003 #ifdef CK_PERMS
3004 #ifdef UNIX
3005
3006 _PROTOTYP( int zsetperm, (char *, int));
3007
3008 /* CHMOD command for UNIX only */
3009
3010 #define CHM_DIR 0
3011 #define CHM_DOT 1
3012 #define CHM_FIL 2
3013 #define CHM_LIS 3
3014 #define CHM_NOL 4
3015 #define CHM_QUI 5
3016 #define CHM_REC 6
3017 #define CHM_VRB 7
3018 #define CHM_PAG 8
3019 #define CHM_NOP 9
3020 #define CHM_TYP 10
3021 #define CHM_SIM 11
3022
3023 static struct keytab uchmodsw[] = {
3024     "/directories", CHM_DIR, 0,
3025     "/dotfiles",    CHM_DOT, 0,
3026     "/files",       CHM_FIL, 0,
3027     "/list",        CHM_LIS, 0,
3028     "/nolist",      CHM_NOL, 0,
3029     "/nopage",      CHM_NOP, 0,
3030     "/page",        CHM_PAG, 0,
3031     "/quiet",       CHM_QUI, CM_INV,
3032     "/recursive",   CHM_REC, 0,
3033     "/simulate",    CHM_SIM, 0,
3034     "/type",        CHM_TYP, CM_ARG,
3035     "/verbose",     CHM_VRB, CM_INV,
3036 };
3037 static int nchmodsw = (sizeof(uchmodsw) / sizeof(struct keytab));
3038
3039 int
3040 douchmod() {
3041     extern int recursive, nscanfile, diractive;
3042 #ifdef CK_TTGWSIZ
3043     extern int tt_rows, tt_cols;
3044     int n = 0;
3045 #endif /* CK_TTGWSIZ */
3046     int i, files = 1, t1 = 1, t2 = 0, x, y, z, verbose = 0, rc = 1, paging;
3047     int xmode = -1, fs = 0, getval = 0, simulate = 0, wild = 0;
3048     char c, * s;
3049     struct FDB sw, nu;
3050
3051     if (xaskmore < 0) {
3052 #ifdef CK_TTGWSIZ
3053         xaskmore = 1;
3054 #else
3055         xaskmore = 0;
3056 #endif /* CK_TTGWSIZ */
3057     }
3058     paging = xaskmore;
3059
3060     cmfdbi(&sw,                         /* First FDB - command switches */
3061            _CMKEY,                      /* fcode */
3062            "Octal file permission code, or switch",
3063            "",                          /* default */
3064            "",                          /* addtl string data */
3065            nchmodsw,                    /* addtl numeric data 1: tbl size */
3066            4,                           /* addtl numeric data 2: 4 = cmswi */
3067            xxstring,                    /* Processing function */
3068            uchmodsw,                    /* Keyword table */
3069            &nu                          /* Pointer to next FDB */
3070            );
3071     cmfdbi(&nu,
3072            _CMNUM,                      /* Number */
3073            "",                          /* Help message */
3074            "",                          /* Default */
3075            "",                          /* N/A */
3076            8,                           /* Radix = 8 */
3077            0,                           /* N/A */
3078            xxstring,                    /* Processing function */
3079            NULL,                        /* N/A */
3080            NULL                         /* Next */
3081            );
3082
3083     while (1) {
3084         if ((x = cmfdb(&sw)) < 0) {
3085             if (x == -3) {
3086                 x = -9;
3087                 printf("?Filename required\n");
3088             }
3089             return(x);
3090         }
3091         if (cmresult.fcode != _CMKEY)
3092           break;
3093         c = cmgbrk();
3094         getval = (c == ':' || c == '=');
3095         if (getval && !(cmgkwflgs() & CM_ARG)) {
3096             printf("?This switch does not take an argument\n");
3097             return(-9);
3098         }
3099         if (!getval && (cmgkwflgs() & CM_ARG)) {
3100             printf("?This switch requires an argument\n");
3101             return(-9);
3102         }
3103         switch (cmresult.nresult) {
3104           case CHM_DIR:
3105             t1 = 1;
3106             t2 = 1;
3107             break;
3108           case CHM_DOT:
3109             matchdot = 1;
3110             break;
3111           case CHM_FIL:
3112             t1 = 0;
3113             t2 = 0;
3114             break;
3115           case CHM_LIS:
3116           case CHM_VRB:
3117             verbose = 1;
3118             break;
3119           case CHM_NOL:
3120           case CHM_QUI:
3121             verbose = 0;
3122             break;
3123           case CHM_REC:
3124             recursive = 1;
3125             break;
3126           case CHM_PAG:
3127             verbose = 1;
3128             paging = 1;
3129             break;
3130           case CHM_NOP:
3131             paging = 0;
3132             break;
3133           case CHM_SIM:
3134             simulate = 1;
3135             break;
3136           case CHM_TYP: {
3137               extern struct keytab txtbin[];
3138               if ((x = cmkey(txtbin,3,"","",xxstring)) < 0)
3139                 return(x);
3140               if (x == 2) {             /* ALL */
3141                   xmode = -1;
3142               } else {                  /* TEXT or BINARY only */
3143                   xmode = x;
3144                   fs = 1;
3145               }
3146               break;
3147           }
3148         }
3149     }
3150     z = cmresult.nresult;
3151     x = cmifi2("File specification","",&s,&wild,t1,NULL,xxstring,t2);
3152     if (x < 0) {
3153         if (x == -3) {
3154             printf("?A file specification is required\n");
3155             return(-9);
3156         } else
3157           return(x);
3158     }
3159     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
3160     s = tmpbuf;
3161     if ((x = cmcfm()) < 0)
3162       return(x);
3163 #ifdef ZXREWIND
3164     if (wild) files = zxrewind();
3165 #else
3166     if (wild) files = nzxpand(s,0);
3167 #endif /* ZXREWIND */
3168
3169     if (paging > -1)
3170       xaskmore = paging;
3171
3172 #ifdef CK_TTGWSIZ
3173     if (verbose && paging) {
3174 #ifdef OS2
3175         ttgcwsz();
3176 #else /* OS2 */
3177         if (ttgwsiz() > 0) {
3178             if (tt_rows > 0 && tt_cols > 0) {
3179                 cmd_rows = tt_rows;
3180                 cmd_cols = tt_cols;
3181             }
3182         }
3183 #endif /* OS2 */
3184     }
3185 #endif /* CK_TTGWSIZ */
3186
3187     for (i = 0; i < files; i++) {
3188         if (files == 1 && wild == 0) {  /* For "chmod 777 ." */
3189             ckstrncpy(line,s,LINBUFSIZ);
3190         } else {
3191             x = znext(line);
3192             if (x < 1) {
3193                 if (i == 0) {
3194                     printf("?No files match - \"%s\"\n",line);
3195                     return(-9);
3196                 }
3197                 return(1);
3198             }
3199         }
3200         if (fs) {
3201 #ifdef VMSORUNIX
3202             /* If /TYPE:TEXT or BINARY given, skip directories and links */
3203             /* since they are neither text nor binary. */
3204             extern int zgfs_dir, zgfs_link;
3205             zgetfs(line);
3206             if (zgfs_dir || zgfs_link)
3207               continue;
3208 #else
3209             if (zchki(line) < 0)
3210               continue;
3211 #endif /* VMSORUNIX */
3212             /* Regular file, scan it */
3213             switch (scanfile(line,&y,nscanfile)) {
3214               case FT_BIN:
3215                 if (xmode != 1)
3216                   continue;
3217                 break;
3218               case FT_TEXT:
3219               case FT_7BIT:
3220               case FT_8BIT:
3221 #ifdef UNICODE
3222               case FT_UTF8:
3223               case FT_UCS2:
3224 #endif /* UNICODE */
3225                 if (xmode != 0)
3226                   continue;
3227             }
3228         }
3229         if (simulate) {
3230 #ifdef UNIX
3231             extern int zchkod;          /* Unidentified Flying */
3232             int xx = zchkod;            /* API Extension... */
3233             zchkod = 1;
3234 #endif /* UNIX */
3235             if (zchko(line) < 0)
3236               printf("%s - Access denied\n",line);
3237             else
3238               printf("%s - OK\n",line);
3239 #ifdef UNIX
3240             zchkod = xx;
3241 #endif /* UNIX */
3242         } else {
3243             if (zsetperm(line,z) < 1) {
3244                 if (verbose || files < 2) {
3245                     printf("%s: %s\n",line,ck_errstr());
3246                 }
3247                 rc = 0;
3248             } else if (verbose) {
3249                 printf("%s  %s\n",ziperm(line),line);
3250             }
3251         }
3252 #ifdef CK_TTGWSIZ
3253         if (verbose && paging) {        /* Pause at end of screen */
3254             if (cmd_rows > 0 && cmd_cols > 0) {
3255                 if (++n > cmd_rows - 3) {
3256                     if (!askmore())
3257                       break;
3258                     else
3259                       n = 0;
3260                 }
3261             }
3262         }
3263 #endif /* CK_TTGWSIZ */
3264
3265     }
3266     return(success = rc);
3267 }
3268 #endif /* UNIX */
3269 #endif /* CK_PERMS */
3270
3271 #ifndef NOSPL                           /* S-Expressions */
3272 #ifndef NOSEXP
3273
3274 struct keytab sexptab[] = {
3275     "depth-limit", 1, 0,
3276     "echo-result", 0, 0,
3277     "truncate-all-results", 2
3278 };
3279
3280 static int sexpmaxdep = 1000;           /* Maximum depth */
3281
3282 #define xxfloat(s,x) \
3283 ((isdigit(*s)||(*s=='-')||(*s=='+')||(*s=='.')||(*s=='\040'))?isfloat(s,x):0)
3284
3285 #define SX_ADD  1                       /* Symbols for built-in operators */
3286 #define SX_SUB  2
3287 #define SX_MUL  3
3288 #define SX_DIV  4
3289 #define SX_POW  5
3290 #define SX_SET  6
3291 #define SX_MOD  7
3292 #define SX_EVA  8
3293 #define SX_EXP  9
3294 #define SX_AEQ 10
3295 #define SX_ALT 11
3296 #define SX_AGT 12
3297 #define SX_ALE 13
3298 #define SX_AGE 14
3299 #define SX_MIN 15
3300 #define SX_MAX 16
3301 #define SX_SQR 17
3302 #define SX_FLR 18
3303 #define SX_CEI 19
3304 #define SX_TRU 20
3305 #define SX_ABS 21
3306 #define SX_ROU 22
3307 #define SX_LET 23
3308 #define SX_LGN 24
3309 #define SX_LGX 25
3310 #define SX_FLO 26
3311 #define SX_IFC 27
3312 #define SX_NOT 28
3313 #define SX_NEQ 29
3314 #define SX_AND 30
3315 #define SX_LOR 31
3316 #define SX_SIN 32
3317 #define SX_COS 33
3318 #define SX_TAN 34
3319 #define SX_BWA 35
3320 #define SX_BWO 36
3321 #define SX_BWX 37
3322 #define SX_BWN 38
3323 #define SX_XOR 39
3324 #define SX_INC 40
3325 #define SX_DEC 41
3326 #define SX_QUO 42
3327 #define SX_STR 43
3328
3329 /* Operator flags */
3330
3331 #define SXF_PRE 256                     /* Predicate */
3332 #define SXF_ONE 512                     /* Requires one arg */
3333 #define SXF_TWO 1024                    /* Requires two args or more */
3334 #define SXF_FLO 2048                    /* Coerce to floating-point */
3335
3336 /* Built-in constants */
3337
3338 #define SXC_NIL 1                       /* NIL */
3339 #define SXC_PI  2                       /* PI */
3340 #define SXC_T   3                       /* T */
3341
3342 /*
3343   This is an xlookup() table and so need not be in "alhabetical" order.
3344   Therefore entries are arranged to minimize search for most common
3345   operators.
3346 */
3347 static struct keytab sexpops[] = {      /* Built-in operators */
3348     "setq",    SX_SET, 0,               /* Global assignment */
3349     "+",       SX_ADD, 0,               /* Simple arithmetic */
3350     "-",       SX_SUB, 0,
3351     "*",       SX_MUL, 0,
3352     "/",       SX_DIV, SXF_TWO,
3353     "^",       SX_POW, SXF_TWO,
3354
3355     "if",      SX_IFC, SXF_TWO,         /* IF */
3356     "let",     SX_LET, 0,               /* Local assignment */
3357     "not",     SX_NOT, SXF_ONE,         /* NOT */
3358     "mod",     SX_MOD, SXF_TWO,         /* Modulus */
3359
3360     "<",       SX_ALT, SXF_PRE,         /* Comparisons */
3361     ">",       SX_AGT, SXF_PRE,
3362     "<=",      SX_ALE, SXF_PRE,
3363     "=",       SX_AEQ, SXF_PRE,
3364     ">=",      SX_AGE, SXF_PRE,
3365     "!=",      SX_NEQ, SXF_PRE,
3366
3367     "++",      SX_INC, SXF_ONE|SXF_TWO, /* Increment */
3368     "--",      SX_DEC, SXF_ONE|SXF_TWO, /* Decrement */
3369
3370     "**",      SX_POW, SXF_TWO,         /* Common synonyms */
3371     "==",      SX_AEQ, SXF_PRE,
3372     "!",       SX_NOT, SXF_ONE,
3373     ".",       SX_EVA, 0,
3374
3375     "and",     SX_AND, 0,               /* Logical operators */
3376     "or",      SX_LOR, 0,
3377     "xor",     SX_XOR, SXF_TWO,
3378
3379     "max",     SX_MAX, SXF_ONE|SXF_TWO, /* Max and min */
3380     "min",     SX_MIN, SXF_ONE|SXF_TWO,
3381
3382     "%",       SX_MOD, SXF_TWO,         /* More synonyms */
3383     "||",      SX_LOR, 0,
3384     "&&",      SX_AND, 0,
3385
3386     "quote",   SX_QUO, SXF_ONE,
3387     "string",  SX_STR, SXF_ONE,
3388
3389     "eval",    SX_EVA, 0,               /* Assorted commands */
3390     "abs",     SX_ABS, SXF_ONE,
3391     "truncate",SX_TRU, SXF_ONE|SXF_FLO,
3392     "round",   SX_ROU, SXF_ONE|SXF_TWO|SXF_FLO,
3393     "ceiling", SX_CEI, SXF_ONE|SXF_FLO,
3394     "floor",   SX_FLR, SXF_ONE|SXF_FLO,
3395     "float",   SX_FLO, SXF_ONE|SXF_FLO,
3396
3397 #ifdef FNFLOAT
3398     "sqrt",    SX_SQR, SXF_ONE|SXF_FLO, /* Floating point functions */
3399     "exp",     SX_EXP, SXF_ONE|SXF_FLO,
3400     "sin",     SX_SIN, SXF_ONE|SXF_FLO,
3401     "cos",     SX_COS, SXF_ONE|SXF_FLO,
3402     "tan",     SX_TAN, SXF_ONE|SXF_FLO,
3403     "log",     SX_LGN, SXF_ONE|SXF_FLO,
3404     "log10",   SX_LGX, SXF_ONE|SXF_FLO,
3405 #endif /* FNFLOAT */
3406
3407     "#",       SX_BWX, SXF_TWO,         /* Bitwise operators */
3408     "&",       SX_BWA, 0,
3409     "|",       SX_BWO, 0,
3410     "~",       SX_BWN, SXF_ONE,
3411     "", 0, 0                            /* (end) */
3412 };
3413 static int nsexpops = (sizeof(sexpops) / sizeof(struct keytab)) - 1;
3414
3415 static struct keytab sexpconsts[] = {   /* Built-in constants */
3416     "nil", SXC_NIL, 0,                  /* NIL (false) */
3417     "pi",  SXC_PI,  0,                  /* Pi (3.1415926...) */
3418     "t",   SXC_T,   0,                  /* T (true) */
3419     "", 0, 0
3420 };
3421 static int nsexpconsts = (sizeof(sexpconsts) / sizeof(struct keytab)) - 1;
3422
3423 int sexprc = 0;                         /* S-Expression error flag */
3424 int sexppv = -1;                        /* Predicate value */
3425 static int sexptrunc = 0;               /* Flag to force all results to int */
3426
3427 #define SXMLEN 64                       /* Macro arg list initial length */
3428 #include <math.h>                       /* Floating-point functions */
3429
3430 _PROTOTYP( char * fpformat, (CKFLOAT, int, int) );
3431 _PROTOTYP( CKFLOAT ckround, (CKFLOAT, int, char *, int) );
3432
3433 extern char math_pi[];                  /* Value of Pi */
3434 extern int sexpecho;                    /* SET SEXPRESSION ECHO value */
3435 extern char * sexpval;                  /* Last top-level S-Expression value */
3436 extern char * lastsexp;                 /* Last S-Expression */
3437 int sexprmax = 0;                       /* Longest result (for stats) */
3438 int sexpdmax = 0;                       /* Max depth reached (for stats) */
3439 int sexpdep  = 0;                       /* dosexp() recursion depth */
3440 static int * sxrlen = NULL;             /* Result stack string sizes */
3441 static char ** sxresult = NULL;         /* Result stack */
3442
3443 /*  s h o s e x p  --  Show S-Expression info  */
3444
3445 VOID
3446 shosexp() {
3447     printf("\n");
3448     printf(" sexpression echo-result: %s\n",showooa(sexpecho));
3449     printf(" sexpression depth-limit: %d\n",sexpmaxdep);
3450     printf("\n");
3451     printf(" maximum depth reached:   %d\n",sexpdmax);
3452     printf(" longest result returned: %d\n",sexprmax);
3453     printf("\n");
3454     printf(" truncate all results:    %s\n",showoff(sexptrunc));
3455     printf("\n");
3456     printf(" last sexpression:        %s\n",lastsexp ? lastsexp : "(none)");
3457     printf(" last value:              %s\n",sexpval ? sexpval : "(none)");
3458     printf("\n");
3459 }
3460
3461
3462 static char *
3463 sexpdebug(s) char * s; {
3464     /* For debugging -- includes recursion depth in each debug entry */
3465     static char buf[64];
3466     ckmakmsg(buf,64,"dosexp[",ckitoa(sexpdep),"] ",s);
3467     return((char *)buf);
3468 }
3469
3470 /*  d o s e x p  --  S-Expression Reader  */
3471
3472 /*  Returns value as string (empty, numeric, or non-numeric) */
3473
3474 static char sxroundbuf[32];             /* For ROUND result */
3475
3476 char *
3477 dosexp(s) char *s; {                    /* s = S-Expression */
3478     extern struct mtab *mactab;         /* Macro table */
3479     extern int maclvl, nmac;
3480     extern char *mrval[];
3481     extern int makestrlen;              /* (see makestr()) */
3482     struct stringarray * q = NULL;      /* cksplit() return type */
3483     char * p[SEXPMAX+1], ** p2;         /* List items (must be on stack) */
3484     char * line = NULL;                 /* For building macro argument list */
3485     int nosplit = 0;
3486     int linelen = 0;
3487     int linepos = 0;
3488     int quote = 0;                      /* LISP quote flag */
3489     char * s2;                          /* Workers */
3490     int kw, kwflags, mx = 0, x = 0;
3491     int not = 0, truncate = 0, builtin = 0;
3492     int fpflag = 0, quit = 0, macro = 0;
3493     CK_OFF_T result = 0, i, j, k, n = 0;
3494     CKFLOAT fpj, fpresult = 0.0;        /* Floating-point results */
3495     int pflag = 0;                      /* Have predicate */
3496     int presult = 0;                    /* Predicate result */
3497     int mustfree = 0;                   /* If we malloc'd we must free */
3498
3499     sexppv = -1;                        /* Predicate value */
3500     s2 = "";                            /* Default return value */
3501
3502     debug(F111,sexpdebug("entry 1"),s,sexprc);
3503
3504     if (++sexpdep > sexpmaxdep) {       /* Keep track of depth */
3505         printf("?S-Expression depth limit exceeded: %d\n",sexpmaxdep);
3506         sexprc++;
3507         debug(F111,sexpdebug("max depth exceeded"),s,sexprc);
3508     }
3509     if (sexpdep > sexpdmax)             /* For stats */
3510       sexpdmax = sexpdep;
3511
3512     if (sexprc)                         /* Error, quit all levels */
3513       goto xdosexp;                     /* Always goto common exit point */
3514
3515     debug(F111,sexpdebug("entry 2"),s,sexprc);
3516
3517     if (!s) s = "";                     /* Null or empty arg */
3518
3519     while (*s == SP) s++;               /* Strip leading spaces */
3520     if (!*s)                            /* so empty result */
3521       goto xdosexp;
3522 /*
3523   Allocate result stack upon first use, or after it has been resized with
3524   SET SEXP DEPTH-LIMIT.
3525 */
3526     if (!sxresult) {
3527         sxresult = (char **)malloc(sexpmaxdep * sizeof(char *));
3528         if (!sxresult) {
3529             printf("?Memory allocation failure - \"%s\"\n", s);
3530             sexprc++;
3531             goto xdosexp;
3532         }
3533         sxrlen = (int *)malloc(sexpmaxdep * sizeof(int));
3534         if (!sxrlen) {
3535             printf("?Memory allocation failure - \"%s\"\n", s);
3536             sexprc++;
3537             goto xdosexp;
3538         }
3539         for (i = 0; i < sexpmaxdep; i++) {
3540             sxresult[i] = NULL;         /* Result pointers */
3541             sxrlen[i] = 0;              /* Buffer sizes */
3542         }
3543     }
3544     s2 = s;                             /* s2 is the result pointer */
3545     k = 0;                              /* Length accumulator */
3546     if (s[0] == '(') {                  /* Starts with open paren? */
3547         while (*s2++) k++;              /* Get length */
3548         if (s[k-1] == ')') {            /* Strip outer parens if any */
3549             s[k-1] = NUL;
3550             s++;
3551             k -= 2;
3552             while (*s == SP) {          /* Strip leading spaces from result */
3553                 s++;
3554                 k--;
3555             }
3556             while (k > 0 && s[k-1] == SP) { /* And trailing spaces. */
3557                 s[k-1] = NUL;
3558                 k--;
3559             }
3560         }
3561         if (!*s) {                      /* If nothing remains */
3562             s2 = "";                    /* return empty result. */
3563             goto xdosexp;
3564         }
3565     }
3566     /* Break result up into "words" (an SEXP counts as a word) */
3567
3568     for (i = 0; i < SEXPMAX+1; i++ ) {  /* Clear the operands */
3569         p[i] = NULL;
3570     }
3571     if (!*(s+1) || !*(s+2)) {           /* No need to call cksplit() */
3572         n = 1;                          /* if it's one or two chars. */
3573         p[1] = s;                       /* No need to malloc this either. */
3574         nosplit = 1;
3575         debug(F101,sexpdebug("nosplit"),"",n);
3576         if (s[0] == '(') {              /* () empty */
3577             s2 = "";
3578             goto xdosexp;
3579         }
3580     } else {
3581         nosplit = 0;
3582         q = cksplit(1,SEXPMAX,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",8,39,0);
3583         if (!q)
3584           goto xdosexp;
3585         n = q->a_size;                  /* Number of items */
3586         debug(F101,sexpdebug("split"),"",n);
3587         if (n < 0 || n > SEXPMAX) {     /* Check for too many */
3588             printf("?Too many operands: max = %d\n",SEXPMAX);
3589             sexprc++;
3590             goto xdosexp;
3591         }
3592         if (n == 0)                     /* None, result is NULL, done. */
3593           goto xdosexp;
3594         if (n == 1 && s[0] == '(') {    /* One but it's another SEXP */
3595             s2 = dosexp(s);
3596             goto xdosexp;
3597         }
3598         p2 = q->a_head;                 /* Point to result array. */
3599         for (i = 1; i <= n; i++) {      /* We must copy it because */
3600             p[i] = NULL;                /* recursive calls to dosexp() */
3601             if (p2[i])                  /* write over the same array */
3602               makestr(&(p[i]),p2[i]);
3603         }
3604         if (s[0] == '(') {              /* Operator is an S-Expression */
3605             s2 = dosexp(p[1]);          /* Replace it by its value */
3606             makestr(&(p[1]),s2);
3607         }
3608         mustfree++;                     /* Remember to free it */
3609     }
3610     debug(F110,sexpdebug("head"),p[1],0);
3611
3612     if (n == 1 && p[1]) {
3613         if (*(p[1]) == '\047') {       /* Apostrophe = LISP quote character */
3614             s2 = p[1];
3615             goto xdosexp;
3616         }
3617     }
3618 /*
3619   This section sidesteps xlookup() of the most common operators.
3620   It's not necessary but it speeds up SEXP-heavy loops by about 10%.
3621 */
3622     kwflags = 0;
3623     if (n > 0) {                        /* Look up the operator */
3624         s2 = p[1];                      /* Prelookup optimization... */
3625         if (!s2)
3626           s2 = "";
3627         if (!*s2)
3628           goto xdosexp;
3629         kw = 0;
3630         x = 0;
3631         if (isdigit(*s2)) {             /* Digit */
3632             x = -2;
3633
3634         } else if (isalpha(*s2) && !*(s2+1)) { /* Single letter */
3635             x = -1;
3636
3637         } else if (*s2 == 's' || *s2 == 'S') { /* SETQ */
3638             s2++;
3639             if (*s2 == 'e' || *s2 == 'E') {
3640                 s2++;
3641                 if (*s2 == 't' || *s2 == 'T') {
3642                     s2++;
3643                     if (*s2 == 'q' || *s2 == 'Q') {
3644                         if (!*(s2+1)) {
3645                             x = SX_SET;
3646                             kwflags = 0;
3647                             builtin = 1;
3648                         }
3649                     }
3650                 }
3651             }
3652         }
3653         if (!x) {
3654             if (!*(s2+1)) {             /* Common single-character ops */
3655                 if (*s2 == '+') {
3656                     x = SX_ADD;
3657                     kwflags = 0;
3658                     builtin = 1;
3659                 } else if (*s2 == '-') {
3660                     x = SX_SUB;
3661                     kwflags = 0;
3662                     builtin = 1;
3663                 } else if (*s2 == '*') {
3664                     x = SX_MUL;
3665                     kwflags = 0;
3666                     builtin = 1;
3667                 } else if (*s2 == '/') {
3668                     x = SX_DIV;
3669                     kwflags = SXF_TWO;
3670                     builtin = 1;
3671                 }
3672             }
3673             if (!x) {                   /* None of the above, look it up */
3674                 x = xlookup(sexpops,p[1],nsexpops,&kw);
3675                 if (x > 0) {
3676                     kwflags = sexpops[kw].flgs;
3677                     builtin = 1;
3678                 }
3679             }
3680         }
3681     }
3682     /* If none of the above, check built-in constants */
3683
3684     if (x == -1) {
3685         x = xlookup(sexpconsts,p[1],nsexpconsts,&kw);
3686         if (x > 0) {
3687             switch (x) {
3688               case SXC_NIL:
3689                 s2 = "";
3690                 goto xdosexp;
3691               case SXC_PI:
3692                 s2 = math_pi;
3693                 goto xdosexp;
3694               case SXC_T:
3695                 s2 = "1";
3696                 goto xdosexp;
3697             }
3698         }
3699     }
3700     if (n == 1) {                       /* Not an expression */
3701         if (builtin) {                  /* Built-in operand? */
3702             switch (x) {                /* Operators with default values */
3703               case SX_EVA:
3704                 s2 = "";
3705                 goto xdosexp;
3706               case SX_MUL:              /* (*) */
3707                 s2 = sexpval ? sexpval : "1";
3708                 goto xdosexp;
3709               case SX_AND:              /* (AND) */
3710               case SX_BWA:              /* Bitwise (&) */
3711                 result++;
3712               case SX_LOR:              /* (OR) */
3713               case SX_BWO:              /* Bitwise (|) */
3714               case SX_ADD:              /* (+) */
3715               case SX_SUB:              /* (-) */
3716                 s2 = result ? "1" : "0";
3717                 goto xdosexp;
3718             }
3719
3720         } else {                        /* Not a built-in operand */
3721             char * p1;
3722             p1 = p[1];
3723             while (*p1 == SP) p1++;
3724             if (!isalpha(*p1)) {
3725                 if (xxfloat(p1,0) > 0) { /* Is it a number? */
3726                     s2 = p1;
3727                     while (*s2 == '+') s2++;
3728                 } else if (*p1 == '(') { /* An S-Expression? */
3729
3730 #ifdef COMMENT
3731                     s2 = dosexp(s2);
3732 #else
3733                     s2 = dosexp(p1);
3734 #endif /* COMMENT */
3735                 }
3736                 goto xdosexp;
3737             } else if (x < 1) {         /* Is it a variable? */
3738                 j = mxlook(mactab,p[1],nmac); /* Look it up */
3739                 debug(F111,sexpdebug("n==1 mxlook"),p[1],j);
3740                 s2 = (j > -1) ? mactab[j].mval : "";
3741                 if (!s2) s2 = "";
3742                 if (xxfloat(s2,0) > 0)  /* Macro value is a number */
3743                   goto xdosexp;
3744                 if (j > -1) {           /* It's a macro */
3745                     mx = j;
3746                     x = j;              /* whose definition is not numeric */
3747                     if (*s2 == '(') {   /* Is it an S-Expression? */
3748                         /* We have to allocate memory on the stack */
3749                         /* to call ourselves recursively on it */
3750                         /* otherwise we'll wipe out the macro definition */
3751                         char * s3 = NULL;
3752                         /* int k = 0; */
3753                         s3 = s2;
3754                         while (*s3++) k++;
3755                         s3 = (char *)malloc(k + 4);
3756                         if (s3) {
3757                             strcpy(s3,s2);   /* SAFE */
3758                             s2 = dosexp(s3); /* Evaluate it */
3759                             free(s3);
3760                         } else {
3761                             printf("?Memory allocation failure - \"%s\"\n",s2);
3762                             sexprc++;
3763                         }
3764                         goto xdosexp;
3765                     }
3766                     if (*s2 == '\047') {
3767                         s2++;
3768 #ifdef COMMENT
3769                         /* Dumps core if petty optimization was taken */
3770                         makestr(&(p[1]),s2);
3771 #else
3772                         if (!nosplit && p[1]) free(p[1]);
3773                         p[1] = (char *)malloc((int)strlen(s2) + 1);
3774 #endif /* COMMENT */
3775                         s2 = p[1];
3776                         if (!s2) s2 = "";
3777                         if (*s2 == '(') {
3778                             if (s2[makestrlen-1] == ')') {
3779                                 s2[makestrlen-1] = NUL;
3780                                 s2++;
3781                             }
3782                         }
3783                         debug(F110,sexpdebug("'A"),s2,0);
3784                         goto xdosexp;
3785                     }
3786                     macro++;            /* Not an S-Expression */
3787                 } else {                /* Not found in macro table */
3788                     printf("?Not defined - \"%s\"\n", p[1]);
3789                     sexprc++;
3790                     goto xdosexp;
3791                 }
3792             }
3793         }
3794     } else if (x < 1 && !macro) {       /* n > 1 and not a built-in operator */
3795         x = mxlook(mactab,p[1],nmac);   /* See if it's a macro */
3796         debug(F111,sexpdebug("n!=1 mxlook"),p[1],x);
3797         if (x < 0) {
3798             printf("?Invalid operand - \"%s\"\n",p[1]);
3799             sexprc++;
3800             goto xdosexp;
3801         }
3802         mx = x;
3803         macro++;
3804     }
3805     if (builtin) {                      /* Built-in operator... */
3806         if (kwflags) {
3807             int flgs;
3808             if ((flgs = (kwflags & (SXF_ONE|SXF_TWO)))) {
3809                 switch (flgs) {
3810                   case (SXF_ONE|SXF_TWO):
3811                     if (n < 2) {
3812                         printf("?Too few operands - \"%s\"\n",s);
3813                         sexprc++;
3814                         goto xdosexp;
3815                     }
3816                     break;
3817                   case SXF_TWO:
3818                     if (n < 3) {
3819                         printf("?Too few operands - \"%s\"\n",s);
3820                         sexprc++;
3821                         goto xdosexp;
3822                     }
3823                     break;
3824                   case SXF_ONE:
3825                     if (n != 2) {
3826                         printf("?Too %s operands - \"%s\"\n",
3827                                (n > 2) ? "many" : "few", s);
3828                         sexprc++;
3829                         goto xdosexp;
3830                     }
3831                 }
3832             }
3833             if (kwflags & SXF_PRE) {    /* Predicate? */
3834                 if (n < 2) {
3835                     printf("?Too few operands - \"%s\"\n",s);
3836                     sexprc++;
3837                     goto xdosexp;
3838                 }
3839                 pflag = 1;
3840                 presult = 1;
3841             }
3842             if (kwflags & SXF_FLO)      /* Operator requires floating point */
3843               fpflag++;                 /* Force it */
3844
3845             if (x == SX_ROU) {          /* ROUND can have 1 or 2 arguments */
3846                 if (n < 2 || n > 3) {
3847                     printf("?Too %s operands - \"%s\"\n",
3848                            (n > 3) ? "many" : "few", s);
3849                     sexprc++;
3850                     goto xdosexp;
3851                 }
3852             }
3853             if (x == SX_ROU) {
3854                 /* But they are not "cumulative" like other SEXP args */
3855                 /* So this case is handled specially */
3856                 char buf1[32], buf2[32];
3857                 float r;
3858                 char * s0, * s1;
3859                 char * q0, * q1;
3860
3861                 s0 = p[2];
3862                 if (!s0) s0 = "";
3863                 if (!*s0) s0 = "0";
3864                 q0 = dosexp(s0);
3865                 ckstrncpy(buf1,q0,32);
3866                 q0 = buf1;
3867
3868                 s1 = p[3];
3869                 if (!s1) s1 = "";
3870                 if (!*s1) s1 = "0";
3871                 q1 = dosexp(s1);
3872                 if (!q1) q1 = "";
3873                 if (!*q1) q1 = "0";
3874                 ckstrncpy(buf2,q1,32);
3875                 q1 = buf2;
3876
3877                 r = ckround(atof(q0),(int)(atof(q1)),sxroundbuf,31);
3878                 s2 = sxroundbuf;
3879                 sexprc = 0;
3880                 goto xdosexp;
3881             }
3882         }
3883         if (x == SX_SET || x == SX_LET || /* Assignment is special */
3884             x == SX_INC || x == SX_DEC) {
3885             int rc;
3886             char c, * m, * s3;
3887             if (n == 1) {
3888                 s2 = "";
3889                 goto xdosexp;
3890             }
3891             s2 = NULL;
3892             for (i = 1; i < n; i += 2) { /* Loop thru operand pairs */
3893                 rc = 0;
3894                 s3 = p[i+1];
3895                 c = *s3;
3896                 debug(F110,sexpdebug("target p"),s3,0);
3897
3898                 /* Make sure target doesn't have multiple words */
3899                 while (*s3) { if (*s3 < '!') { rc = 1; break; }; s3++; }
3900                 s3 = p[i+1];
3901                 if (rc) {               /* If it does it must have been */
3902                     char * s4;          /* an SEXP so evaluate it */
3903                     s3 = dosexp(s3);
3904                     s4 = s3;
3905                     rc = 0;
3906                     while (*s4) { if (*s4 < '!') { rc = 1; break; }; s4++; }
3907                     if (rc == 0) makestr(&(p[i+1]),s3);
3908                 }
3909
3910                 /* And that it's not a number, etc. */
3911                 if (rc > 0 || isdigit(c) || c == '(') {
3912                     printf("?Invalid assignment - \"%s\"\n",s);
3913                     sexprc++;
3914                     goto xdosexp;
3915                 } else if (isalpha(c)) {
3916                     rc = xlookup(sexpconsts,s3,nsexpconsts,NULL);
3917                     if (rc > 0) {
3918                         printf("?Assignment to constant - \"%s\"\n",s);
3919                         sexprc++;
3920                         goto xdosexp;
3921                     }
3922                 }
3923
3924                 /* If ++ or --, get current value of variable */
3925                 if (x == SX_INC || x == SX_DEC) {
3926                     int ok = 1;
3927                     char buf[32];
3928                     if (c == CMDQ) {    /* A backslash variable */
3929                         int n = 32;
3930                         char * s = buf;
3931                         buf[0] = NUL;
3932                         if (zzstring(s3,&s,&n) < 0 || !buf[0])
3933                           ok = 0;
3934                         s2 = buf;
3935                     } else {            /* A macro */
3936                         if ((k = mxlook(mactab,s3,nmac)) < 0)
3937                           ok = 0;
3938                         else
3939                           s2 = mactab[k].mval;
3940                     }
3941                     if (!ok) {
3942                         printf("?Not defined - \"%s\"\n",p[i+1]);
3943                         sexprc++;
3944                         goto xdosexp;
3945                     }
3946                     if (!s2) s2 = "";
3947                     k = xxfloat(s2,0);
3948                     if (k < 1) {
3949                         printf("?Not numeric - \"%s\"\n",p[i+1]);
3950                         sexprc++;
3951                         goto xdosexp;
3952                     }
3953                     while (*s2 == '+') s2++;
3954                     result = ckatofs(s2);
3955                     fpresult = floatval;
3956                     if (k > 1 || fpresult != result)
3957                       fpflag++;
3958                 }
3959                 if (n < i+2) {          /* Variable with no value */
3960                     s2 = "";
3961                     if (x == SX_SET || x == SX_LET) {
3962                         delmac(p[i+1],1); /* Delete the variable */
3963                         break;
3964                     } else {
3965                         s2 = "1";
3966                     }
3967                 } else {                /* Variable with value */
3968                     k = xxfloat(p[i+2],0); /* Is it a number? */
3969                     if (k > 0) {
3970                         s2 = p[i+2];
3971                         while (*s2 == '+') s2++;
3972                     } else {
3973                         s2 = dosexp(p[i+2]); /* Have value, evaluate it */
3974                         if (sexprc) goto xdosexp;
3975                         if (!s2) s2 = "";
3976                         if (!*s2 && (x == SX_INC || x == SX_DEC))
3977                           continue;
3978                     }
3979                 }
3980                 if (x == SX_INC || x == SX_DEC) {
3981                     k = xxfloat(s2,0);
3982                     if (k < 1) {
3983                         printf("?Not numeric - \"%s\"\n",s2);
3984                         sexprc++;
3985                         goto xdosexp;
3986                     }
3987                     while (*s2 == '+') s2++;
3988                     j = ckatofs(s2);
3989                     if (k > 1) {
3990                         fpj = floatval;
3991                         fpflag++;
3992                     } else {
3993                         fpj = (CKFLOAT)j;
3994                     }
3995                     if (x == SX_INC) {
3996                         result += j;
3997                         fpresult += fpj;
3998                     } else if (x == SX_DEC) {
3999                         result -= j;
4000                         fpresult -= fpj;
4001                     }
4002 #ifdef FNFLOAT
4003                     if (result != fpresult) fpflag++;
4004 #endif  /* FNFLOAT */
4005                     s2 = (fpflag && !sexptrunc) ?
4006                         fpformat(fpresult,0,0) : ckfstoa(result);
4007                 }
4008                 if (x == SX_LET && cmdlvl > 0) /* LET makes var local */
4009                   addlocal(p[i+1]);
4010                 if ((rc = addmac(p[i+1],s2)) < 0) { /* Add the value */
4011                     switch (rc) {
4012                       case -3: m = "Array not declared"; break;
4013                       case -2: m = "Subscript out of range"; break;
4014                       case -4: m = "Out of memory"; break;
4015                       default: m = "Error creating variable";
4016                     }
4017                     printf("?%s - \"%s\"\n",m,s);
4018                     sexprc++;
4019                     goto xdosexp;
4020                 }
4021                 if (s2) result = ckatofs(s2);
4022             }
4023             goto xdosexp;
4024         } else if (x == SX_IFC) {               /* Conditional expression */
4025             int true = 0;
4026             if (n > 4) {
4027                 printf("?Too many operands: IF - \"%s\"\n",s);
4028                 sexprc++;
4029                 goto xdosexp;
4030             }
4031             s2 = dosexp(p[2]);
4032             if (sexprc) goto xdosexp;
4033             if (s2) {
4034                 j = ckatofs(s2);
4035                 if (xxfloat(s2,0) == 2) {
4036                     fpflag++;
4037                     fpresult = (CKFLOAT)result;
4038                     fpj = floatval;
4039                 } else {
4040                     fpj = atof(s2);
4041                 }
4042                 true = ((fpj != 0.0) ? 1 : 0);
4043             }
4044             if (!true && n < 4) {
4045                 s2 = NULL;
4046             } else {
4047                 s2 = dosexp(true ? p[3] : p[4]);
4048                 if (sexprc) goto xdosexp;
4049                 j = s2 ? ckatofs(s2) : 0;
4050                 if (xxfloat(s2,0) == 2) {
4051                     fpflag++;
4052                     fpresult = (CKFLOAT)result;
4053                     fpj = floatval;
4054                 } else {
4055                     fpj = s2 ? atof(s2) : 0.0;
4056                 }
4057                 fpresult = fpj;
4058                 result = j;
4059             }
4060             goto xdosexp;
4061         } else if (x == SX_QUO) {
4062 #ifndef COMMENT
4063             int xx;
4064             xx = strlen(p[2]);
4065             p[3] = (char *)malloc(xx+4);
4066             s2 = p[3];
4067             ckmakmsg(p[3],xx+4,"'(",p[2],")",NULL);
4068             n++;
4069 #else
4070             s2 = p[2];
4071 #endif /* COMMENT */
4072             goto xdosexp;
4073         } else if (x == SX_STR) {
4074             int xx;
4075             s2 = dosexp(p[2]);
4076             if (sexprc) goto xdosexp;
4077             xx = strlen(s2);
4078             p[3] = (char *)malloc(xx+4);
4079             ckmakmsg(p[3],xx+4,"'(",s2,")",NULL);
4080             s2 = p[3];
4081             n++;
4082             goto xdosexp;
4083         }
4084     }
4085     /* Arithmetic operator or macro - Loop thru operands */
4086
4087     quit = 0;                           /* Short-circuit flag. */
4088     if (macro && n > 1) {               /* If operator is a macro */
4089         if (!line) {                    /* allocate local buffer for */
4090             line = (char *)malloc(SXMLEN); /* the evaluated argument list. */
4091             if (!line) {
4092                 printf("?Memory allocation failure - \"%s\"\n",p[1]);
4093                 sexprc++;
4094                 goto xdosexp;
4095             }
4096             linelen = SXMLEN;
4097             /* debug(F101,"dosexp macro arg buffer","",linelen); */
4098         }
4099         linepos = 0;
4100         line[linepos] = NUL;
4101     }
4102     for (i = 1; ((i < n) && !sexprc && !quit); i++) { /* Loop thru operands */
4103         quote = 0;
4104         s2 = p[i+1];                    /* Get operand */
4105         if (!s2) s2 = "";
4106
4107 #ifdef COMMENT
4108         if (*s2 == '\047') {            /* Is it quoted? */
4109             debug(F110,sexpdebug("'B"),s2,0);
4110             s2++;                       /* Space past the quote */
4111             quote++;
4112             if (*s2 == '(') {           /* Quoted S-Expression? */
4113                 char c4, * s4 = s2+1;   /* Strip outer parens */
4114                 while ((c4 = *s4++)) {
4115                     if (c4 == ')' && !*s4) {
4116                         s2++;
4117                         *(s4-1) = NUL;
4118                         break;
4119                     }
4120                 }
4121             }
4122             debug(F110,sexpdebug("'C"),s2,0);
4123
4124         } else {                        /* Not quoted */
4125             s2 = dosexp(p[i+1]);        /* evaluate it */
4126             if (sexprc) goto xdosexp;
4127             if (!s2) s2 = "";
4128             if (!macro && x == SX_EVA)
4129               continue;
4130         }
4131 #else
4132         if (*s2 != '\047') {            /* Is it quoted? */
4133             s2 = dosexp(p[i+1]);        /* No, evaluate it */
4134             if (sexprc) goto xdosexp;
4135             if (!s2) s2 = "";
4136             if (!macro && x == SX_EVA)
4137               continue;
4138         }
4139         if (*s2 == '\047') {            /* Is result quoted? */
4140             debug(F110,sexpdebug("'B"),s2,0);
4141             s2++;                       /* Space past the quote */
4142             quote++;
4143             if (*s2 == '(') {           /* Quoted S-Expression? */
4144                 char c4, * s4 = s2+1;   /* Strip outer parens */
4145                 while ((c4 = *s4++)) {
4146                     if (c4 == ')' && !*s4) {
4147                         s2++;
4148                         *(s4-1) = NUL;
4149                         break;
4150                     }
4151                 }
4152             }
4153             debug(F110,sexpdebug("'C"),s2,0);
4154         }
4155 #endif /* COMMENT */
4156         if (macro) {
4157             debug(F111,sexpdebug("macro arg"),s2,i);
4158             if (!*s2) quote++;
4159             if (!quote) {
4160                 register char c4, * s4 = s2;
4161                 while ((c4 = *s4++)) if (c4 == SP) { quote++; break; }
4162             }
4163             if (quote) line[linepos++] = '{';
4164             while ((line[linepos++] = *s2++)) {
4165                 if (linepos > linelen - 3) {
4166                     char * tmp = NULL;
4167                     line[linepos] = NUL;
4168                     linelen += SXMLEN;
4169                     tmp = (char *) malloc(linelen);
4170                     if (!tmp) {
4171                         printf("?Memory re-allocation failure - \"%s...\"\n",
4172                                line);
4173                         sexprc++;
4174                         goto xdosexp;
4175                     }
4176                     strcpy(tmp,line);
4177                     free(line);
4178                     line = tmp;
4179                 }
4180             }
4181             linepos--;                  /* Back up over NUL */
4182             if (quote)
4183               line[linepos++] = '}';    /* End quote group */
4184             line[linepos++] = SP;       /* add a space */
4185             line[linepos] = NUL;        /* and a NUL */
4186             continue;
4187         }
4188         if (!quote) {                   /* Built-in operator... */
4189             s2 = dosexp(s2);
4190             if (sexprc) goto xdosexp;
4191             if (!s2) s2 = "";
4192         }
4193         if (x == SX_EVA)
4194           continue;
4195
4196         if (!*s2) {
4197             /* An empty value is not a legal number */
4198             /* but it is a legal truth value */
4199             if (x != SX_AND && x != SX_LOR && x != SX_NOT) {
4200                 printf("?Not Numeric - \"%s\"\n",p[i+1]);
4201                 sexprc++;
4202                 goto xdosexp;
4203             }
4204             j = 0;
4205             fpj = 0.0;
4206         } else {
4207             j = ckatofs(s2);
4208             /* Switch to floating-point upon encountering any f.p. arg */
4209             /* OR... if integer is too big */
4210             if (!fpflag) if (xxfloat(s2,0) == 2)
4211               fpflag++;
4212             fpj = atof(s2);
4213         }
4214         if (i == 1) {                   /* Initial result is first operand */
4215             result = (n == 2 && x == SX_SUB) ? 0-j : j;
4216             fpresult = (n == 2 && x == SX_SUB) ? -fpj : fpj;
4217             if ((x == SX_AND && result == 0) || /* Short circuit */
4218                 (x == SX_LOR && result != 0))
4219               quit++;
4220             if (!(kwflags & SXF_ONE))   /* Command w/single arg */
4221               continue;
4222         }
4223         if (x == SX_MOD || x == SX_DIV) {
4224             if (!result)
4225               fpflag++;
4226             if (!fpj) {
4227                 printf("?Divide by zero - \"%s\"\n",cmdbuf);
4228                 sexprc++;
4229                 goto xdosexp;
4230             }
4231         }
4232         switch (x) {                    /* Accumulate result */
4233
4234           case SX_EVA:                  /* EVAL */
4235             result = j;
4236             fpresult = fpj;
4237             break;
4238
4239           case SX_ADD:                  /* + */
4240             result += j;
4241             fpresult += fpj;
4242 #ifdef FNFLOAT
4243             if (result != fpresult)
4244               fpflag++;
4245 #endif  /* FNFLOAT */
4246             break;
4247
4248           case SX_SUB:                  /* - */
4249             result -= j;
4250             fpresult -= fpj;
4251 #ifdef FNFLOAT
4252             if (result != fpresult)
4253               fpflag++;
4254 #endif  /* FNFLOAT */
4255             break;
4256
4257           case SX_MUL:                  /* * */
4258             result *= j;
4259             fpresult *= fpj;
4260 #ifdef FNFLOAT
4261             if (result != fpresult)
4262               fpflag++;
4263 #endif  /* FNFLOAT */
4264             break;
4265
4266           case SX_AND:                  /* AND */
4267             result = result && j;
4268             if (!result) quit++;
4269             fpresult = fpresult && fpj;
4270             break;
4271
4272           case SX_LOR:                  /* OR */
4273             result = result || j;
4274             if (!result) quit++;
4275             fpresult = fpresult || fpj;
4276             break;
4277
4278           case SX_MOD:                  /* Modulus */
4279             result = result % j;
4280 #ifdef FNFLOAT
4281             fpresult = (CKFLOAT)fmod(fpresult,fpj);
4282             if (result != fpresult)
4283               fpflag++;
4284 #else
4285             fpresult = result;
4286 #endif /* FNFLOAT */
4287             break;
4288
4289           case SX_DIV:                  /* / */
4290             if (j) {
4291                 result /= j;
4292                 fpresult /= fpj;
4293 #ifdef FNFLOAT
4294                 if (result != fpresult)
4295                   fpflag++;
4296 #endif  /* FNFLOAT */
4297             } else {
4298                 fpresult /= fpj;
4299                 result = fpj;
4300 #ifdef FNFLOAT
4301                   fpflag++;
4302 #endif  /* FNFLOAT */
4303             }
4304             break;
4305
4306           case SX_AEQ:                  /* Test for equality */
4307             if (fpflag) {
4308                 if (fpresult != fpj)
4309                   presult = 0;
4310             } else {
4311                 if (result != j)
4312                   presult = 0;
4313             }
4314             break;
4315
4316           case SX_NEQ:                  /* Test for ineqality */
4317             if (fpflag) {
4318                 if (fpresult == fpj)
4319                   presult = 0;
4320             } else {
4321                 if (result == j)
4322                   presult = 0;
4323             }
4324             break;
4325
4326           case SX_ALE:                  /* Arithmetic less-equal */
4327             if (fpflag) {
4328                 if (fpj < fpresult)
4329                   presult = 0;
4330                 fpresult = fpj;
4331             } else {
4332                 if (j < result)
4333                   presult = 0;
4334                 result = j;
4335             }
4336             break;
4337
4338           case SX_ALT:                  /* Arithmetic less-than */
4339             if (fpflag) {
4340                 if (fpj <= fpresult)
4341                   presult = 0;
4342                 fpresult = fpj;
4343             } else {
4344                 if (j <= result)
4345                   presult = 0;
4346                 result = j;
4347             }
4348             break;
4349
4350           case SX_AGT:                  /* Arithmetic greater-than */
4351             if (fpflag) {
4352                 if (fpj >= fpresult)
4353                   presult = 0;
4354                 fpresult = fpj;
4355             } else {
4356                 if (j >= result)
4357                   presult = 0;
4358                 result = j;
4359             }
4360             break;
4361
4362           case SX_AGE:                  /* Arithmetic greater-equal */
4363             if (fpflag) {
4364                 if (fpj > fpresult)
4365                   presult = 0;
4366                 fpresult = fpj;
4367             } else {
4368                 if (j > result)
4369                   presult = 0;
4370                 result = j;
4371             }
4372             break;
4373
4374           case SX_POW:                  /* Raise to power */
4375 #ifdef FNFLOAT
4376             {
4377                 double dummy;
4378                 if (!fpj) {
4379                     fpresult = 1.0;
4380                 } else if ((!fpresult && fpj <= 0.0)) {
4381                     printf("?Divide by zero - \"%s\"\n",cmdbuf);
4382                     sexprc++;
4383                     goto xdosexp;
4384                 } else if (fpresult < 0.0 && modf(fpj,&dummy)) {
4385                     printf("?Domain error - \"%s\"\n",cmdbuf);
4386                     sexprc++;
4387                     goto xdosexp;
4388                 } else {
4389                     fpresult = (CKFLOAT)pow(fpresult,fpj);
4390                 }
4391             }
4392 #endif /* FNFLOAT */
4393             if (j == 0) {
4394                 result = 1;
4395             } else {
4396                 CK_OFF_T z, sign = 0;
4397                 if (j < 0) {
4398                     if (result == 0) {
4399                         printf("?Divide by zero - \"%s\"\n",cmdbuf);
4400                         sexprc++;
4401                         goto xdosexp;
4402                     }
4403                     j = 0 - j;
4404                     sign++;
4405                 }
4406                 z = result;
4407                 while (--j > 0)
4408                   result *= z;
4409                 if (sign)
4410                   result = 1 / result;
4411             }
4412 #ifdef FNFLOAT
4413             if (result != fpresult)
4414               fpflag++;
4415 #endif  /* FNFLOAT */
4416             break;
4417
4418 #ifdef FNFLOAT
4419           case SX_EXP:                  /* e to the given power */
4420             fpresult = (CKFLOAT) exp(fpj);
4421             break;
4422
4423           case SX_LGN:                  /* Natural log */
4424           case SX_LGX:                  /* Log base 10 */
4425           case SX_SQR:                  /* Square root */
4426             if (fpj < 0.0) {
4427                 printf("?Argument out of range - \"%s\"\n",cmdbuf);
4428                 sexprc++;
4429                 goto xdosexp;
4430             }
4431             if (x == SX_SQR)
4432               fpresult = (CKFLOAT) sqrt(fpj);
4433             else if (x == SX_LGN)
4434               fpresult = (CKFLOAT) log(fpj);
4435             else
4436               fpresult = (CKFLOAT) log10(fpj);
4437             break;
4438
4439           case SX_SIN:                  /* sine */
4440             fpresult = (CKFLOAT) sin(fpj);
4441             break;
4442
4443           case SX_COS:                  /* cosine */
4444             fpresult = (CKFLOAT) cos(fpj);
4445             break;
4446
4447           case SX_TAN:                  /* tangent */
4448             fpresult = (CKFLOAT) tan(fpj);
4449             break;
4450 #endif /* FNFLOAT */
4451
4452           case SX_CEI:                  /* Ceiling */
4453             if (j != fpj)
4454               if (fpj > 0.0)
4455                 fpj += 1.0;
4456             fpresult = fpj;
4457             fpflag = 1;
4458             truncate = 1;
4459             break;
4460
4461           case SX_FLR:                  /* Floor */
4462             if (j != fpj)
4463               if (fpj < 0.0)
4464                 fpj -= 1.0;
4465             fpresult = fpj;
4466             fpflag = 1;
4467             truncate = 1;
4468             break;
4469
4470           case SX_TRU:                  /* Truncate */
4471             fpresult = fpj;
4472             fpflag = 1;
4473             truncate = 1;
4474             break;
4475
4476           case SX_ABS:                  /* Absolute value */
4477             result = (j < 0) ? 0 - j : j;
4478 #ifdef FNFLOAT
4479             fpresult = (fpj < 0.0) ? 0.0 - fpj : fpj;
4480             if (result != fpresult)
4481               fpflag++;
4482 #endif  /* FNFLOAT */
4483             break;
4484
4485           case SX_MAX:                  /* Max */
4486             if (j != fpj)
4487               fpflag++;
4488             if (fpflag) {
4489                 if (fpj > fpresult)
4490                   fpresult = fpj;
4491             } else
4492               if (j > result)
4493                 result = j;
4494             break;
4495
4496           case SX_MIN:                  /* Min */
4497             if (j != fpj)
4498               fpflag++;
4499             if (fpflag) {
4500                 if (fpj < fpresult)
4501                   fpresult = fpj;
4502             } else
4503               if (j < result)
4504                 result = j;
4505             break;
4506
4507           case SX_FLO:                  /* Float */
4508             fpflag++;
4509             fpresult = result;
4510             fpj = j;
4511             break;
4512
4513           case SX_NOT:                  /* NOT (reverse truth value) */
4514             fpflag = 0;
4515             not++;
4516             break;
4517
4518           case SX_BWA:                  /* Bitwise AND */
4519             fpflag = 0;
4520             result &= j;
4521             break;
4522
4523           case SX_BWO:                  /* Bitwise OR */
4524             fpflag = 0;
4525             result |= j;
4526             break;
4527
4528           case SX_BWX:                  /* Bitwise XOR */
4529           case SX_XOR:                  /* Logical XOR */
4530             if (n > 3) {
4531                 printf("?Too many operands - \"%s\"\n",s);
4532                 sexprc++;
4533                 goto xdosexp;
4534             }
4535             fpflag = 0;
4536             if (x == SX_BWX) {
4537                 result ^= j;
4538             } else {
4539                 result = (result && !j) || (!result && j);
4540                 if (result) result = 1;
4541             }
4542             break;
4543
4544           case SX_BWN:                  /* Bitwise Not */
4545             fpflag = 0;
4546             result = ~result;
4547             break;
4548
4549           default:
4550             printf("BAD OP [%s]\n",p[1]);
4551             sexprc++;
4552         }
4553     }
4554     if (!pflag)                         /* Not a predicate */
4555       sexppv = -1;                      /* So unset this */
4556
4557   /* domacro: */
4558
4559     if (macro) {                        /* User-defined macro */
4560         extern int fsexpflag;           /* (see fneval():ckuus4.c) */
4561         int lookagain = 0;              /* Maybe the macro table changed */
4562         if (mactab[mx].kwd) {           /* Check and see */
4563             if (ckstrcmp(mactab[mx].kwd,p[1],-1,0))
4564               lookagain++;
4565         } else
4566           lookagain++;
4567         if (lookagain) {                /* The table changed */
4568             mx = mxlook(mactab,p[1],nmac); /* Get the macro's new index */
4569             debug(F111,sexpdebug("macro moved"),p[1],mx);
4570             if (mx < 0) {                  /* Yikes! */
4571                 printf("?Macro disappeared! - \"%s\"\n",p[1]);
4572                 sexprc++;
4573                 goto xdosexp;
4574             }
4575         }
4576         debug(F111,sexpdebug("macro mx"),mactab[mx].kwd,mx);
4577         if (fsexpflag) {                /* If embedded in a function call */
4578             if (cmpush() > -1) {        /* get a new copy of the parsing */
4579                 extern int ifc;         /* environment, */
4580                 int k, ifcsav = ifc;    /* save the IF state */
4581                 dodo(mx,line,0);        /* Set up the macro */
4582                 k = parser(1);          /* Call the parser to execute it */
4583                 cmpop();                /* Pop back to previous level */
4584                 ifc = ifcsav;           /* restore IF state */
4585                 if (k == 0)             /* If no error */
4586                   s2 = mrval[maclvl+1]; /* get return value, if any */
4587                 if (!s2) s2 = "";
4588                 debug(F110,sexpdebug("macro return"),s2,0);
4589             } else {
4590                 printf("?Resources exhausted - \"%s\"\n",s);
4591                 sexprc++;
4592             }
4593         } else {                        /* Not embedded in a function call */
4594             dodo(mx,line,0);            /* As above but without cmpush/pop() */
4595             k = parser(1);
4596             if (k == 0)
4597               s2 = mrval[maclvl+1];
4598             if (!s2) s2 = "";
4599         }
4600     } else if (pflag) {                 /* Predicate */
4601         if (not) presult = presult ? 0 : 1;
4602         sexppv = presult;               /* So set predicate value (0 or 1) */
4603         s2 = presult ? "1" : "0";
4604     } else if (fpflag && !sexptrunc) {  /* Result is floating-point */
4605         if (not) fpresult = fpresult ? 0.0 : 1.0;
4606         s2 = fpformat(fpresult,0,0);
4607     } else if (x != SX_EVA) {
4608         if (not) result = result ? 0 : 1;
4609         s2 = ckfstoa(result);
4610     }
4611
4612 /* Common exit point.  Always come here to exit. */
4613
4614   xdosexp:
4615
4616     if (!s2) s2 = "";
4617     if (!sexprc && s2) {                /* Have a result */
4618         char * sx;
4619         char * q2 = s2; int xx = 0;
4620         if (*s2) {
4621             while (*q2++) xx++;         /* Get length */
4622             if (xx > sexprmax)          /* (stats) */
4623               sexprmax = xx;
4624         } else
4625           xx = 0;
4626         if (xx > sxrlen[sexpdep] || !sxresult[sexpdep]) {
4627             int k;
4628             k = xx + xx / 4;
4629             if (k < 32) k = 32;
4630             if (sxresult[sexpdep])
4631               free(sxresult[sexpdep]);
4632             if ((sxresult[sexpdep] = (char *)malloc(k))) {
4633                 sxrlen[sexpdep] = k;
4634             } else {
4635                 printf("?Memory allocation failure - \"%s\"\n",s2);
4636                 sexprc++;
4637             }
4638         }
4639         sx = sxresult[sexpdep];         /* Point to result buffer */
4640         while ((*sx++ = *s2++)) ;       /* copy result. */
4641         if (fpflag && truncate) {       /* Floating point + truncate */
4642             sx = sxresult[sexpdep];     /* at decimal point */
4643             for (i = xx - 1; i >= 0; i--) {
4644                 if (sx[i] == '.') {
4645                     sx[i] = NUL;
4646                     if (i == 0) {       /* If nothing left */
4647                         sx[0] = '0';    /* put a zero. */
4648                         sx[1] = NUL;
4649                     }
4650                 }
4651             }
4652         }
4653     }
4654     if (line)                           /* If macro arg buffer allocated */
4655       free(line);                       /* free it. */
4656     if (mustfree) {                     /* And free local copy of split list */
4657         for (i = 1; i <= n; i++) {
4658             if (p[i]) free(p[i]);
4659         }
4660     }
4661     debug(F111,sexpdebug("exit"),sxresult[sexpdep],sexprc);
4662     return(sxresult[sexpdep--]);
4663 }
4664 #endif /* NOSEXP */
4665 #endif /* NOSPL */
4666
4667 int                                     /* CHECK command */
4668 dochk() {
4669     int x, y;
4670     if ((y = cmkey(ftrtab,nftr,"","",xxstring)) < 0)
4671       return(y);
4672     ckstrncpy(line,atmbuf,LINBUFSIZ);
4673     if ((y = cmcfm()) < 0)
4674       return(y);
4675 #ifndef NOPUSH
4676     if (!ckstrcmp(line,"push",(int)strlen(line),0)) {
4677         if (msgflg)                     /* If at top level... */
4678           printf(" push%s available\n", nopush ? " not" : "");
4679         else if (nopush && !backgrd)
4680           printf(" CHECK: push not available\n");
4681         return(success = 1 - nopush);
4682     }
4683 #endif /* NOPUSH */
4684 #ifdef PIPESEND
4685     if (!ckstrcmp(line,"pipes",(int)strlen(line),0)) {
4686         if (msgflg)                     /* If at top level... */
4687           printf(" pipes%s available\n",
4688                  (nopush || protocol != PROTO_K) ? " not" : "");
4689         else if ((nopush || protocol != PROTO_K) && !backgrd)
4690           printf(" CHECK: pipes not available\n");
4691         return(success = 1 - nopush);
4692     }
4693 #endif /* PIPESEND */
4694     y = lookup(ftrtab,line,nftr,&x);    /* Look it up */
4695     debug(F111,"dochk",ftrtab[x].kwd,y);
4696     if (msgflg)                         /* If at top level... */
4697       printf(" %s%s available\n", ftrtab[x].kwd, y ? " not" : "");
4698     else if (y && !backgrd)
4699       printf(" CHECK: %s not available\n", ftrtab[x].kwd);
4700     return(success = 1 - y);
4701 }
4702
4703 #ifndef NOLOCAL
4704 #ifdef CKLOGDIAL
4705
4706 /* Connection log and elapsed-time reporting */
4707
4708 extern char cxlogbuf[];                 /* Log record buffer */
4709 extern char diafil[];                   /* Log file name */
4710 extern int dialog, cx_active;           /* Flags */
4711 static long cx_prev = 0L;               /* Elapsed time of previous session */
4712
4713 #endif /* CKLOGDIAL */
4714 #endif /* NOLOCAL */
4715
4716 VOID
4717 dologend() {                            /* Write record to connection log */
4718 #ifdef LOCUS
4719     extern int locus, autolocus;
4720 #endif /* LOCUS */
4721
4722 #ifndef NOLOCAL
4723 #ifdef CKLOGDIAL
4724     long d1, d2, t1, t2;
4725     char buf[32], * p;
4726 #endif /* CKLOGDIAL */
4727 #endif /* NOLOCAL */
4728
4729 #ifdef LOCUS
4730     if (autolocus) {
4731         int x = locus;
4732 #ifdef NEWFTP
4733         debug(F101,"dologend ftpisconnected","",ftpisconnected());
4734         setlocus(ftpisconnected() ? 0 : 1, 1);
4735 #else
4736         setlocus(1,1);
4737 #endif /* NEWFTP */
4738     }
4739 #endif /* LOCUS */
4740
4741 #ifndef NOLOCAL
4742 #ifdef CKLOGDIAL
4743     debug(F101,"dologend dialog","",dialog);
4744     debug(F101,"dologend cxlogbuf[0]","",cxlogbuf[0]);
4745 #ifdef CKSYSLOG
4746     debug(F101,"dologend ckxlogging","",ckxlogging);
4747 #endif /* CKSYSLOG */
4748
4749     if (!cx_active || !cxlogbuf[0])     /* No active record */
4750       return;
4751
4752     cx_active = 0;                      /* Record is not active */
4753     debug(F111,"dologend cxlogbuf 1",cxlogbuf,cx_active);
4754
4755     d1 = mjd((char *)cxlogbuf);         /* Get start date of this session */
4756     ckstrncpy(buf,ckdate(),31);         /* Get current date */
4757     d2 = mjd(buf);                      /* Convert them to mjds */
4758     p = cxlogbuf;                       /* Get start time */
4759     p[11] = NUL;
4760     p[14] = NUL;                        /* Convert to seconds */
4761     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4762     p[11] = ':';
4763     p[14] = ':';
4764     p = buf;                            /* Get end time */
4765     p[11] = NUL;
4766     p[14] = NUL;
4767     t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4768     t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Compute elapsed time */
4769     debug(F101,"dologend t2","",t2);
4770     if (t2 > -1L) {
4771         cx_prev = t2;
4772         p = hhmmss(t2);
4773         debug(F110,"dologend hhmmss",p,0);
4774         ckstrncat(cxlogbuf,"E=",CXLOGBUFL); /* Append to log record */
4775         ckstrncat(cxlogbuf,p,CXLOGBUFL);
4776         debug(F110,"dologend cxlogbuf 2",cxlogbuf,0);
4777     } else
4778       cx_prev = 0L;
4779     debug(F101,"dologend cx_prev","",cx_prev);
4780     if (dialog) {                       /* If logging */
4781         int x;
4782         x = diaopn(diafil,1,1);         /* Open log in append mode */
4783         debug(F101,"dologend diaopn","",x);
4784         x = zsoutl(ZDIFIL,cxlogbuf);    /* Write the record */
4785         debug(F101,"dologend zsoutl","",x);
4786         x = zclose(ZDIFIL);             /* Close the log */
4787         debug(F101,"dologend zclose","",x);
4788     }
4789 #ifdef CKSYSLOG
4790     debug(F101,"dologend ckxlogging","",ckxlogging);
4791     if (ckxlogging) {
4792         int x;
4793         x = ckindex("T=DIAL",cxlogbuf,0,0,1);
4794         debug(F111,"dologend ckxsyslog",cxlogbuf,ckxsyslog);
4795         debug(F111,"dologend ckindex","T=DIAL",x);
4796         if (x > 0) {
4797             if (ckxsyslog >= SYSLG_DI) {
4798                 debug(F110,"dologend syslog",cxlogbuf+18,0);
4799                 cksyslog(SYSLG_DI,1,"CONNECTION",(char *)(cxlogbuf+18),"");
4800             } else if (ckxsyslog >= SYSLG_AC) {
4801                 debug(F110,"dologend syslog",cxlogbuf+18,0);
4802                 cksyslog(SYSLG_AC,1,"CONNECTION",(char *)(cxlogbuf+18),"");
4803             }
4804         }
4805     }
4806 #endif /* CKSYSLOG */
4807 #endif /* CKLOGDIAL */
4808 #endif /* NOLOCAL */
4809 }
4810
4811 #ifndef NOLOCAL
4812 #ifdef CKLOGDIAL
4813
4814 /*  D O L O G S H O W  --  Show session/connection info  */
4815
4816 /* Call with fc == 1 to show, fc == 0 to only calculate. */
4817 /* Returns session elapsed time in seconds. */
4818 /* If no session active, returns elapsed time of previous session, if any, */
4819 /* otherwise 0 */
4820
4821 long
4822 dologshow(fc) int fc; {                 /* SHOW (current) CONNECTION */
4823     long d1, d2, t1, t2 = 0, prev;
4824     char c, buf1[32], buf2[32], * info[32], * p, * s;
4825     char * xlogbuf, xbuf[CXLOGBUFL+1];
4826     int i, x = 0, z, ftp = 0, active = 0;
4827
4828 #ifdef NEWFTP
4829     extern char ftplogbuf[];
4830     extern long ftplogprev;
4831     extern int ftplogactive;
4832     if (fc & W_FTP) {
4833         fc &= 63;
4834         ftp = 1;
4835         xlogbuf = ftplogbuf;
4836         prev = ftplogprev;
4837         active = ftplogactive;
4838     } else {
4839 #endif /* NEWFTP */
4840         ftp = 0;
4841         xlogbuf = cxlogbuf;
4842         prev = cx_prev;
4843         active = cx_active;
4844 #ifdef NEWFTP
4845     }
4846 #endif /* NEWFTP */
4847
4848     debug(F101,"dologshow local","",local);
4849     debug(F101,"dologshow ftp","",ftp);
4850     debug(F111,"dologshow active",xlogbuf,active);
4851
4852     if (!xlogbuf[0]) {
4853         if (fc) {
4854             if (didsetlin || ftp)
4855               printf(" %s: No record.\n", ftp ? "FTP" : "Kermit");
4856             else
4857               printf(" %s: No connection.\n", ftp ? "FTP" : "Kermit");
4858         }
4859         return(prev);
4860     }
4861
4862 #ifdef NEWFTP
4863     if (ftp) {
4864         z = ftpisconnected() ? 1 : -1;
4865     } else {
4866 #endif /* NEWFTP */
4867         if (local) {                    /* See if we have an open connection */
4868             z = ttchk();
4869             debug(F101,"dologshow ttchk","",z);
4870             z = (z > -1) ? 1 : -2;
4871         } else {
4872             z = active ? 1 : -2;
4873         }
4874 #ifdef NEWFTP
4875     }
4876 #endif /* NEWFTP */
4877     if (z < 0L) {
4878         if (!fc)
4879           return(prev);
4880         else
4881           t2 = prev;
4882     }
4883     /* Note: NOT ckstrncpy! */
4884     strncpy(buf1,xlogbuf,17);           /* Copy of just the timestamp */
4885     buf1[17] = NUL;                     /* Terminate it */
4886     ckstrncpy(xbuf,xlogbuf+18,CXLOGBUFL); /* Copy that can be poked */
4887     debug(F111,"dologshow prev",xbuf,prev);
4888
4889     xwords(xbuf,31,info,1);             /* Break up into fields */
4890     d1 = mjd(buf1);                     /* Convert start time to MJD */
4891     ckstrncpy(buf2,ckdate(),31);        /* Current date */
4892     d2 = mjd(buf2);                     /* Convert to MJD */
4893     p = buf1;                           /* Point to start time */
4894     p[11] = NUL;
4895     p[14] = NUL;                        /* Convert to seconds */
4896     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4897     p[11] = ':';
4898     p[14] = ':';
4899     p = buf2;                           /* Ditto for current time */
4900     p[11] = NUL;
4901     p[14] = NUL;
4902     if (z > -1L) {
4903         t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4904         t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Elapsed time so far */
4905     }
4906     if (fc) {
4907         p = NULL;
4908         if (t2 > -1L)                   /* Convert seconds to hh:mm:ss */
4909           p = hhmmss(t2);
4910         if (z > -1)
4911           s = "Active";
4912         else if (z == -2)
4913           s = "Closed";
4914         else
4915           s = "Unknown";
4916         printf("\n");                   /* Show results */
4917         printf(" Status:       %s\n",s);
4918         printf(" Opened:       %s\n",buf1);
4919         printf(" User:         %s\n",info[1] ? info[1] : "");
4920         printf(" PID:          %s\n",info[2] ? info[2] : "");
4921         for (i = 3; info[i]; i++) {
4922             c = info[i][0];
4923             s = (info[i]) ? info[i]+2 : "";
4924             switch (c) {
4925               case 'T': printf(" Type:         %s\n", s); break;
4926               case 'N': printf(" To:           %s\n", s); break;
4927               case 'P': printf(" Port:         %s\n", s); break;
4928               case 'H': printf(" From:         %s\n", s); break;
4929               case 'D': printf(" Device:       %s\n", s); break;
4930               case 'O': printf(" Origin:       %s\n", s); break;
4931               case 'E': break;
4932               default:  printf(" %s\n",info[i] ? info[i] : "");
4933             }
4934         }
4935         if (z < 0L)
4936           printf(" Elapsed time: %s\n", hhmmss(t2));
4937         else
4938           printf(" Elapsed time: %s\n", p ? p : "(unknown)");
4939         x = 0;
4940 #ifdef NETCONN
4941 #ifdef SSHBUILTIN
4942         if ( IS_SSH() ) x++;
4943 #endif /* SSHBUILTIN */
4944 #ifdef CK_ENCRYPTION
4945         if (ck_tn_encrypting() && ck_tn_decrypting()) x++;
4946 #endif /* CK_ENCRYPTION */
4947 #ifdef CK_SSL
4948         if (tls_active_flag || ssl_active_flag) x++;
4949 #endif /* CK_SSL */
4950 #ifdef RLOGCODE
4951 #ifdef CK_KERBEROS
4952 #ifdef CK_ENCRYPTION
4953         if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) x++;
4954 #endif /* CK_ENCRYPTION */
4955 #endif /* CK_KERBEROS */
4956 #endif /* RLOGCODE */
4957 #endif /* NETCONN */
4958         if (z > 0)
4959           printf(" Encrypted:    %s\n", x ? "Yes" : "No");
4960         printf(" Log:          %s\n", dialog ? diafil : "(none)");
4961         printf("\n");
4962     }
4963     return(t2 > -1L ? t2 : 0L);
4964 }
4965
4966 VOID
4967 dologline() {
4968     char * p;
4969     int n, m = 0;
4970
4971     dologend();                         /* Previous session not closed out? */
4972     cx_active = 1;                      /* Record is active */
4973     cx_prev = 0L;
4974     p = ckdate();                       /* Get timestamp */
4975     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL-1); /* Start record off with it */
4976     if (!uidbuf[0]) {
4977         debug(F100,"dologline uidbuf empty","",0);
4978 #ifdef UNIX                             /* Who has whoami()... */
4979         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
4980 #else
4981 #ifdef STRATUS
4982         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
4983 #else
4984         ckstrncpy(uidbuf,"UNKNOWN",UIDBUFLEN);
4985 #endif /* STRATUS */
4986 #endif /* UNIX */
4987     }
4988     m = strlen(uidbuf) + strlen(myhost) + strlen(ttname) + 32;
4989     if (n+m < CXLOGBUFL-1) {            /* Add serial device info */
4990         p = cxlogbuf+n;
4991         sprintf(p," %s %s T=SERIAL H=%s D=%s ", /* SAFE */
4992                 uidbuf,
4993                 ckgetpid(),
4994                 myhost,
4995                 ttname
4996                 );
4997     } else
4998       ckstrncpy(cxlogbuf,"LOGLINE BUFFER OVERFLOW",CXLOGBUFL);
4999     debug(F110,"dologline",cxlogbuf,0);
5000 }
5001
5002 #ifdef NETCONN
5003 VOID
5004 dolognet() {
5005     char * p, * s = "NET", * uu = uidbuf;
5006     char * port = "";
5007     int n, m, tcp = 0;
5008     char * h = NULL;
5009
5010     dologend();                         /* Previous session not closed out? */
5011     cx_prev = 0L;
5012     cx_active = 1;                      /* Record is active */
5013     p = ckdate();
5014     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL);
5015 #ifdef TCPSOCKET
5016     if (nettype == NET_TCPB || nettype == NET_TCPA) {
5017         tcp++;
5018         s = "TCP";
5019     } else if (nettype == NET_SSH) {
5020         s = "SSH";
5021         tcp++;
5022     }
5023 #endif /* TCPSOCKET */
5024 #ifdef ANYX25
5025     if (nettype == NET_SX25 || nettype == NET_VX25 || nettype == NET_IX25)
5026       s = "X25";
5027 #endif /* ANYX25 */
5028 #ifdef DECNET
5029     if (nettype == NET_DEC)
5030       s = "DECNET";
5031 #endif /* DECNET */
5032 #ifdef SUPERLAT
5033     if (nettype == NET_SLAT)
5034       s = "SUPERLAT";
5035 #endif /* SUPERLAT */
5036 #ifdef CK_NETBIOS
5037     if (nettype == NET_BIOS)
5038       s = "NETBIOS";
5039 #endif /* CK_NETBIOS */
5040
5041     if (!uu[0]) {
5042         debug(F100,"dolognet uidbuf empty","",0);
5043 #ifdef OS2ORUNIX                        /* Who has whoami()... */
5044         uu = (char *)whoami();
5045 #else
5046 #ifdef STRATUS
5047         uu = (char *)whoami();
5048 #else
5049         uu = "UNKNOWN";
5050 #endif /* STRATUS */
5051 #endif /* UNIX */
5052     }
5053 #ifdef TCPSOCKET
5054     if (tcp) {
5055         int k;
5056         makestr(&h,myhost);
5057         if ((k = ckindex(":",h,0,0,0)) > 0) {
5058             h[k-1] = NUL;
5059             port = &h[k];
5060         } else {
5061             int svcnum = gettcpport();
5062             if (svcnum > 0)
5063               port = ckitoa(svcnum);
5064             else
5065               port = "unk";
5066         }
5067     }
5068 #endif  /* TCPSOCKET */
5069     m = strlen(uu) + strlen(myhost) + strlen(ttname) + strlen(s) + 32;
5070     if (n+m < CXLOGBUFL-1) {            /* SAFE */
5071         p = cxlogbuf+n;
5072         sprintf(p," %s %s T=%s N=%s H=%s P=%s ",
5073                 uu,
5074                 ckgetpid(),
5075                 s,
5076                 ttname,
5077                 myhost,
5078                 port
5079                 );
5080     } else
5081       ckstrncpy(cxlogbuf,"LOGNET BUFFER OVERFLOW",CXLOGBUFL);
5082     debug(F110,"dolognet cxlogbuf",cxlogbuf,0);
5083     if (h) makestr(&h,NULL);
5084 }
5085 #endif /* NETCONN */
5086 #endif /* CKLOGDIAL */
5087
5088 #ifndef NODIAL
5089 /*
5090   Parse a DIAL-related string, stripping enclosing braces, if any.
5091 */
5092 static int
5093 dialstr(p,msg) char **p; char *msg; {
5094     int x;
5095     char *s;
5096
5097     if ((x = cmtxt(msg, "", &s, xxstring)) < 0)
5098       return(x);
5099     s = brstrip(s);                     /* Strip braces around. */
5100     debug(F110,"dialstr",s,0);
5101     makestr(p,*s?s:NULL);
5102     return(success = 1);
5103 }
5104
5105 VOID
5106 initmdm(x) int x; {
5107     MDMINF * p;
5108     int m;
5109
5110     mdmtyp = x;                         /* Set global modem type */
5111     debug(F101,"initmdm mdmtyp","",mdmtyp);
5112     debug(F101,"initmdm usermdm","",usermdm);
5113     if (x < 1) return;
5114
5115     m = usermdm ? usermdm : mdmtyp;
5116
5117     p = modemp[m];                      /* Point to modem info struct, and */
5118     /* debug(F101,"initmdm p","",p); */
5119     if (p) {
5120         dialec = p->capas & CKD_EC;     /* set DIAL ERROR-CORRECTION, */
5121         dialdc = p->capas & CKD_DC;     /* DIAL DATA-COMPRESSION, and */
5122         mdmspd = p->capas & CKD_SB ? 0 : 1; /* DIAL SPEED-MATCHING from it. */
5123         dialfc = FLO_AUTO;                  /* Modem's local flow control.. */
5124         dialmax   = p->max_speed;
5125         dialcapas = p->capas;
5126         dialesc   = p->esc_char;
5127     } else if (mdmtyp > 0) {
5128         printf("WARNING: modem info for \"%s\" not filled in yet\n",
5129                gmdmtyp()
5130                );
5131     }
5132
5133 /* Reset or set the SET DIAL STRING items ... */
5134
5135 #ifdef DEBUG
5136     if (deblog) {
5137         debug(F110,"initmdm dialini",dialini,0);
5138         debug(F110,"initmdm dialmstr ",dialmstr,0);
5139         debug(F110,"initmdm dialmprmt",dialmprmt,0);
5140         debug(F110,"initmdm dialcmd",dialcmd,0);
5141         debug(F110,"initmdm dialdcon",dialdcon,0);
5142         debug(F110,"initmdm dialdcoff",dialdcoff,0);
5143         debug(F110,"initmdm dialecon",dialecon,0);
5144         debug(F110,"initmdm dialecoff",dialecoff,0);
5145         debug(F110,"initmdm dialhcmd",dialhcmd,0);
5146         debug(F110,"initmdm dialhwfc",dialhwfc,0);
5147         debug(F110,"initmdm dialswfc",dialswfc,0);
5148         debug(F110,"initmdm dialnofc",dialnofc,0);
5149         debug(F110,"initmdm dialtone",dialtone,0);
5150         debug(F110,"initmdm dialpulse",dialpulse,0);
5151         debug(F110,"initmdm dialname",dialname,0);
5152         debug(F110,"initmdm dialaaon",dialaaon,0);
5153         debug(F110,"initmdm dialaaoff",dialaaoff,0);
5154         debug(F110,"initmdm dialx3",dialx3,0);
5155         debug(F110,"initmdm dialspon",dialspon,0);
5156         debug(F110,"initmdm dialspoff",dialspoff,0);
5157         debug(F110,"initmdm dialvol1",dialvol1,0);
5158         debug(F110,"initmdm dialvol2",dialvol2,0);
5159         debug(F110,"initmdm dialvol3",dialvol3,0);
5160         debug(F110,"initmdm dialini2",dialini2,0);
5161     }
5162 #endif /* DEBUG */
5163
5164     if (usermdm && p) { /* USER-DEFINED: copy info from specified template */
5165
5166         makestr(&dialini  ,p->wake_str);
5167         makestr(&dialmstr ,p->dmode_str);
5168         makestr(&dialmprmt,p->dmode_prompt);
5169         makestr(&dialcmd  ,p->dial_str);
5170         makestr(&dialdcon ,p->dc_on_str);
5171         makestr(&dialdcoff,p->dc_off_str);
5172         makestr(&dialecon ,p->ec_on_str);
5173         makestr(&dialecoff,p->ec_off_str);
5174         makestr(&dialhcmd ,p->hup_str);
5175         makestr(&dialhwfc ,p->hwfc_str);
5176         makestr(&dialswfc ,p->swfc_str);
5177         makestr(&dialnofc ,p->nofc_str);
5178         makestr(&dialtone ,p->tone);
5179         makestr(&dialpulse,p->pulse);
5180         makestr(&dialname ,"This space available (use SET MODEM NAME)");
5181         makestr(&dialaaon ,p->aa_on_str);
5182         makestr(&dialaaoff,p->aa_off_str);
5183         makestr(&dialx3   ,p->ignoredt);
5184         makestr(&dialspon ,p->sp_on_str);
5185         makestr(&dialspoff,p->sp_off_str);
5186         makestr(&dialvol1 ,p->vol1_str);
5187         makestr(&dialvol2 ,p->vol2_str);
5188         makestr(&dialvol3 ,p->vol3_str);
5189         makestr(&dialini2 ,p->ini2);
5190
5191     } else {                    /* Not user-defined, so wipe out overrides */
5192
5193         if (dialini)   makestr(&dialini,NULL);   /* Init-string */
5194         if (dialmstr)  makestr(&dialmstr,NULL);  /* Dial-mode-str */
5195         if (dialmprmt) makestr(&dialmprmt,NULL); /* Dial-mode-pro */
5196         if (dialcmd)   makestr(&dialcmd,NULL);   /* Dial-command  */
5197         if (dialdcon)  makestr(&dialdcon,NULL);  /* DC ON command */
5198         if (dialdcoff) makestr(&dialdcoff,NULL); /* DC OFF command */
5199         if (dialecon)  makestr(&dialecon,NULL);  /* EC ON command */
5200         if (dialecoff) makestr(&dialecoff,NULL); /* EC OFF command */
5201         if (dialhcmd)  makestr(&dialhcmd,NULL);  /* Hangup command */
5202         if (dialhwfc)  makestr(&dialhwfc,NULL);  /* Flow control... */
5203         if (dialswfc)  makestr(&dialswfc,NULL);  /*  */
5204         if (dialnofc)  makestr(&dialnofc,NULL);  /*  */
5205         if (dialtone)  makestr(&dialtone,NULL);  /* Dialing method */
5206         if (dialpulse) makestr(&dialpulse,NULL); /*  */
5207         if (dialname)  makestr(&dialname,NULL);  /* Modem name */
5208         if (dialaaon)  makestr(&dialaaon,NULL);  /* Autoanswer On */
5209         if (dialaaoff) makestr(&dialaaoff,NULL); /* Autoanswer Off */
5210         if (dialx3)    makestr(&dialx3,NULL);    /* Ignore dialtone */
5211         if (dialspon)  makestr(&dialspon,NULL);  /* Speaker On */
5212         if (dialspoff) makestr(&dialspoff,NULL); /* Speaker Off */
5213         if (dialvol1)  makestr(&dialvol1,NULL);  /* Low volume */
5214         if (dialvol2)  makestr(&dialvol2,NULL);  /* Medium volume */
5215         if (dialvol3)  makestr(&dialvol3,NULL);  /* High volume */
5216         if (dialini2)  makestr(&dialini2,NULL);  /* Init string 2 */
5217     }
5218     if (autoflow)                       /* Maybe change flow control */
5219       setflow();
5220
5221 #ifndef MINIDIAL
5222 #ifdef OLDTBCODE
5223     tbmodel = 0;           /* If it's a Telebit, we don't know the model yet */
5224 #endif /* OLDTBCODE */
5225 #endif /* MINIDIAL */
5226 }
5227
5228 #ifdef COMMENT
5229 /* Not implemented yet */
5230 int
5231 setanswer() {
5232     int x, y;
5233     extern int ans_cid, ans_ring;
5234     if ((x = cmkey(answertab,nanswertab,"","",xxstring)) < 0)
5235       return(x);
5236     switch (x) {
5237       case XYA_CID:
5238         return(seton(&ans_cid));
5239       case XYA_RNG:
5240         y = cmnum("How many rings before answering","1",10,&x,xxstring);
5241         y = setnum(&ans_rings,x,y,254);
5242         return(y);
5243     }
5244 }
5245 #endif /* COMMENT */
5246
5247 int
5248 setmodem() {                            /* SET MODEM */
5249
5250     int x, y, z;
5251     long zz;
5252     struct FDB k1, k2;
5253     extern int mdmset;
5254
5255     cmfdbi(&k1,_CMKEY,
5256            "Modem parameter","","",nsetmdm, 0, xxstring, setmdm, &k2);
5257     cmfdbi(&k2,_CMKEY,"","","",nmdm,0,xxstring,mdmtab,NULL);
5258     x = cmfdb(&k1);
5259     if (x < 0) {                        /* Error */
5260         if (x == -2 || x == -9)
5261           printf("?No keywords match: \"%s\"\n",atmbuf);
5262         return(x);
5263     }
5264     y = cmresult.nresult;               /* Keyword value */
5265     if (cmresult.fdbaddr == &k2) {      /* Modem-type keyword table */
5266         if ((x = cmcfm()) < 0)
5267           return(x);
5268         usermdm = 0;
5269         initmdm(cmresult.nresult);      /* Set the modem type. */
5270         return(success = 1);            /* Done */
5271     }
5272     switch (cmresult.nresult) {         /* SET MODEM keyword table. */
5273 #ifdef MDMHUP
5274       case XYDMHU:                      /* DIAL MODEM-HANGUP */
5275         if ((y = cmkey(mdmhang,4,"how to hang up modem",
5276                        "modem-command", xxstring)) < 0)
5277           return(y);
5278         if ((x = cmcfm()) < 0)
5279           return(x);
5280         dialmhu = y;
5281 #ifdef COMMENT
5282 /* Nope, I fixed it (2001 11 08) */
5283 #ifdef CK_SCOV5
5284         if (dialmhu == 0 && !quiet) {
5285             printf(
5286 "\n WARNING: RS-232 signal sampling and manipulation do not work\n"
5287                     );
5288             printf(
5289 " in the standard SCO OSR5 serial i/o drivers.  SET MODEM HANGUP-METHOD\n"
5290                    );
5291             printf(
5292 " MODEM-COMMAND is recommended for OSR5.\n\n"
5293                     );
5294         }
5295 #endif /* CK_SCOV5 */
5296 #endif /* COMMENT */
5297         return(success = 1);
5298 #endif /* MDMHUP */
5299
5300       case XYDCAP:
5301         zz = 0L;
5302         y = 0;
5303         while (y != -3) {
5304             if ((y = cmkey(mdmcap,nmdmcap,
5305                            "capability of modem", "", xxstring)) < 0) {
5306                 if (y == -3)
5307                   break;
5308                 else
5309                   return(y);
5310             }
5311             zz |= y;
5312         }
5313         if ((x = cmcfm()) < 0)
5314           return(x);
5315         dialcapas = zz;
5316         debug(F101,"setmodem autoflow","",autoflow);
5317         debug(F101,"setmodem flow 1","",flow);
5318         if (autoflow)                   /* Maybe change flow control */
5319           setflow();
5320         debug(F101,"setmodem flow 2","",flow);
5321         mdmspd = zz & CKD_SB ? 0 : 1;   /* Set MODEM SPEED-MATCHING from it. */
5322         return(success = 1);
5323
5324       case XYDMAX:
5325 #ifdef TN_COMPORT
5326         if (network && istncomport())
5327           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
5328         else
5329 #endif /* TN_COMPORT */
5330           x = cmkey(spdtab,nspd,line,"",xxstring);
5331         if (x < 0) {
5332             if (x == -3) printf("?value required\n");
5333             return(x);
5334         }
5335         if ((y = cmcfm()) < 0) return(y);
5336         dialmax = (long) x * 10L;
5337         if (dialmax == 70) dialmax = 75;
5338         return(success = 1);
5339
5340       case XYDSTR:                      /* These moved from SET DIAL */
5341       case XYDDC:
5342       case XYDEC:
5343       case XYDESC:
5344       case XYDFC:
5345       case XYDKSP:
5346       case XYDSPD:
5347       case XYDDIA:
5348         return(setdial(x));
5349
5350       case XYDTYP:
5351         if ((y = cmkey(mdmtab,nmdm,"modem type","none", xxstring)) < 0)
5352           return(y);
5353         if (y == dialudt) {             /* User-defined modem type */
5354             if ((x = cmkey(mdmtab,nmdm,"based on existing modem type",
5355                            "unknown", xxstring)) < 0)
5356               return(x);
5357         }
5358         if ((z = cmcfm()) < 0)
5359           return(z);
5360         usermdm = 0;
5361         usermdm = (y == dialudt) ? x : 0;
5362         initmdm(y);
5363         mdmset = (mdmtyp > 0);
5364         return(success = 1);
5365
5366       case XYDNAM:
5367         return(dialstr(&dialname,"Descriptive name for modem"));
5368
5369       case XYDMCD:                      /* SET MODEM CARRIER-WATCH */
5370         return(setdcd());
5371
5372       case XYDSPK:                      /* SET MODEM SPEAKER */
5373         return(seton(&mdmspk));
5374
5375       case XYDVOL:                      /* SET MODEM VOLUME */
5376         if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0)
5377           return(x);
5378         if ((y = cmcfm()) < 0)
5379           return(y);
5380         mdmvol = x;
5381         return(success = 1);
5382
5383       default:
5384         printf("Unexpected SET MODEM parameter\n");
5385         return(-9);
5386     }
5387 }
5388
5389 static int                              /* Set DIAL command options */
5390 setdial(y) int y; {
5391     int x = 0, z = 0;
5392     char *s = NULL;
5393
5394     if (y < 0)
5395       if ((y = cmkey(dialtab,ndial,"","",xxstring)) < 0)
5396         return(y);
5397     switch (y) {
5398       case XYDHUP:                      /* DIAL HANGUP */
5399         return(seton(&dialhng));
5400       case XYDINI:                      /* DIAL INIT-STRING */
5401         return(dialstr(&dialini,"Modem initialization string"));
5402       case XYDNPR:                      /* DIAL PREFIX */
5403         return(dialstr(&dialnpr,"Telephone number prefix"));
5404       case XYDDIA:                      /* DIAL DIAL-COMMAND */
5405         x = cmtxt("Dialing command for modem,\n\
5406  include \"%s\" to stand for phone number,\n\
5407  for example, \"set dial dial-command ATDT%s\\13\"",
5408                   "",
5409                   &s,
5410                   xxstring);
5411         if (x < 0 && x != -3)           /* Handle parse errors */
5412           return(x);
5413         s = brstrip(s);                 /* Strip braces or quotes */
5414         y = x = strlen(s);              /* Get length of text */
5415         if (y > 0) {                    /* If there is any text (left), */
5416             for (x = 0; x < y; x++) {   /* make sure they included "%s" */
5417                 if (s[x] != '%') continue;
5418                 if (s[x+1] == 's') break;
5419             }
5420             if (x == y) {
5421                 printf(
5422 "?Dial-command must contain \"%cs\" for phone number.\n",'%');
5423                 return(-9);
5424             }
5425         }
5426         if (dialcmd) {                  /* Free any previous string. */
5427             free(dialcmd);
5428             dialcmd = (char *) 0;
5429         }
5430         if (y > 0) {
5431             dialcmd = malloc(y + 1);    /* Allocate space for it */
5432             if (dialcmd)
5433               strcpy(dialcmd,s);        /* and make a safe copy. */
5434         }
5435         return(success = 1);
5436 #ifndef NOXFER
5437       case XYDKSP:                      /* DIAL KERMIT-SPOOF */
5438         return(seton(&dialksp));
5439 #endif /* NOXFER */
5440       case XYDTMO:                      /* DIAL TIMEOUT */
5441         y = cmnum("Seconds to wait for call completion","0",10,&x,xxstring);
5442         if (y < 0) return(y);
5443         y = cmnum("Kermit/modem timeout differential","10",10,&z,xxstring);
5444         if (y < 0) return(y);
5445         if ((y = cmcfm()) < 0)
5446           return(y);
5447         dialtmo = x;
5448         mdmwaitd = z;
5449       case XYDESC:                      /* DIAL ESCAPE-CHARACTER */
5450         y = cmnum("ASCII value of character to escape back to modem",
5451                   "43",10,&x,xxstring);
5452         y = setnum(&dialesc,x,y,128);
5453         if (y > -1 && dialesc < 0)      /* No escape character */
5454           dialmhu = 0;                  /* So no hangup by modem command */
5455         return(y);
5456       case XYDDPY:                      /* DIAL DISPLAY */
5457         return(seton(&dialdpy));
5458       case XYDSPD:                      /* DIAL SPEED-MATCHING */
5459                                         /* used to be speed-changing */
5460         if ((y = seton(&mdmspd)) < 0) return(y);
5461 #ifdef COMMENT
5462         mdmspd = 1 - mdmspd;            /* so here we reverse the meaning */
5463 #endif /* COMMENT */
5464         return(success = 1);
5465       case XYDMNP:                      /* DIAL MNP-ENABLE */
5466       case XYDEC:                       /* DIAL ERROR-CORRECTION */
5467         x = seton(&dialec);
5468         if (x > 0)
5469           if (!dialec) dialdc = 0;      /* OFF also turns off compression */
5470         return(x);
5471
5472       case XYDDC:                       /* DIAL COMPRESSION */
5473         x = seton(&dialdc);
5474         if (x > 0)
5475           if (dialdc) dialec = 1;       /* ON also turns on error correction */
5476         return(x);
5477
5478 #ifdef MDMHUP
5479       case XYDMHU:                      /* DIAL MODEM-HANGUP */
5480         return(seton(&dialmhu));
5481 #endif /* MDMHUP */
5482
5483 #ifndef NOSPL
5484       case XYDDIR:                      /* DIAL DIRECTORY (zero or more) */
5485         return(parsdir(0));             /* 0 means DIAL */
5486 #endif /* NOSPL */
5487
5488       case XYDSTR:                      /* DIAL STRING */
5489         if ((y = cmkey(mdmcmd,nmdmcmd,"","",xxstring)) < 0) return(y);
5490         switch (y) {
5491           case XYDS_AN:                 /* Autoanswer ON/OFF */
5492           case XYDS_DC:                 /* Data compression ON/OFF */
5493           case XYDS_EC:                 /* Error correction ON/OFF */
5494             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
5495               return(x);
5496             sprintf(tmpbuf,"Modem's command to %sable %s", /* SAFE */
5497                     x ? "en" : "dis",
5498                     (y == XYDS_DC) ? "compression" :
5499                     ((y == XYDS_EC) ? "error-correction" :
5500                     "autoanswer")
5501                     );
5502             if (x) {
5503                 if (y == XYDS_DC)
5504                   return(dialstr(&dialdcon,tmpbuf));
5505                 else if (y == XYDS_EC)
5506                   return(dialstr(&dialecon,tmpbuf));
5507                 else
5508                   return(dialstr(&dialaaon,tmpbuf));
5509             } else {
5510                 if (y == XYDS_DC)
5511                   return(dialstr(&dialdcoff,tmpbuf));
5512                 else if (y == XYDS_EC)
5513                   return(dialstr(&dialecoff,tmpbuf));
5514                 else
5515                   return(dialstr(&dialaaoff,tmpbuf));
5516             }
5517           case XYDS_HU:                 /*    hangup command */
5518             return(dialstr(&dialhcmd,"Modem's hangup command"));
5519           case XYDS_HW:                 /*    hwfc */
5520             return(dialstr(&dialhwfc,
5521                            "Modem's command to enable hardware flow control"));
5522           case XYDS_IN:                 /*    init */
5523             return(dialstr(&dialini,"Modem's initialization string"));
5524           case XYDS_NF:                 /*    no flow control */
5525             return(dialstr(&dialnofc,
5526                            "Modem's command to disable local flow control"));
5527           case XYDS_PX:                 /*    prefix */
5528             return(dialstr(&dialnpr,"Telephone number prefix for dialing"));
5529           case XYDS_SW:                 /*    swfc */
5530             return(dialstr(&dialswfc,
5531                    "Modem's command to enable local software flow control"));
5532           case XYDS_DT:                 /*    tone dialing */
5533             return(dialstr(&dialtone,
5534                    "Command to configure modem for tone dialing"));
5535           case XYDS_DP:                 /*    pulse dialing */
5536             return(dialstr(&dialpulse,
5537                            "Command to configure modem for pulse dialing"));
5538           case XYDS_MS:                 /*    dial mode string */
5539             return(dialstr(&dialmstr,
5540                          "Command to enter dial mode"));
5541           case XYDS_MP:                 /*    dial mode prompt */
5542             return(dialstr(&dialmprmt,
5543                            "Modem response upon entering dial mode"));
5544           case XYDS_SP:                 /* SPEAKER OFF */
5545             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0) return(x);
5546             if (x)
5547               return(dialstr(&dialspon,"Command to turn modem speaker on"));
5548             else
5549               return(dialstr(&dialspoff,"Command to turn modem speaker off"));
5550
5551           case XYDS_VO:                 /* VOLUME LOW */
5552             if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0) return(x);
5553             switch (x) {
5554               case 0:
5555               case 1:
5556                 return(dialstr(&dialvol1,
5557                                "Command for low modem speaker volume"));
5558               case 2:
5559                 return(dialstr(&dialvol2,
5560                            "Command for medium modem speaker volume"));
5561
5562               case 3:
5563                 return(dialstr(&dialvol3,
5564                                "Command for high modem speaker volume"));
5565               default:
5566                 return(-2);
5567             }
5568
5569           case XYDS_ID:                 /* IGNORE-DIALTONE */
5570             return(dialstr(&dialx3,
5571                            "Command to tell modem to ignore dialtone"));
5572
5573           case XYDS_I2:                 /* PREDIAL-INIT */
5574             return(dialstr(&dialini2,
5575                            "Command to send to modem just prior to dialing"));
5576
5577           default:
5578             printf("?Unexpected SET DIAL STRING parameter\n");
5579         }
5580
5581       case XYDFC:                       /* DIAL FLOW-CONTROL */
5582         if ((y = cmkey(dial_fc,4,"","auto",xxstring)) < 0) return(y);
5583         if ((x = cmcfm()) < 0) return(x);
5584         dialfc = y;
5585         return(success = 1);
5586
5587       case XYDMTH: {                    /* DIAL METHOD */
5588         extern int dialmauto;
5589         if ((y = cmkey(dial_m,ndial_m,"","default",xxstring)) < 0)
5590           return(y);
5591         if ((x = cmcfm()) < 0)
5592           return(x);
5593         if (y == XYDM_A) {              /* AUTO */
5594             dialmauto = 1;              /* local country code, if known. */
5595             dialmth = XYDM_D;
5596         } else {
5597           dialmauto = 0;                /* use the method specified */
5598           dialmth = y;
5599         }
5600         return(success = 1);
5601       }
5602       case XYDRTM:
5603         y = cmnum("Number of times to try dialing a number",
5604                   "1",10,&x,xxstring);
5605         z = setnum(&dialrtr,x,y,-1);
5606         if (z > -1 && dialrtr < 0) {
5607             printf("?Sorry, negative dial retries not valid: %d\n",dialrtr);
5608             return(-9);
5609         }
5610         return(z);
5611
5612       case XYDINT:
5613         y = cmnum("Seconds to wait between redial attempts",
5614                   "30",10,&x,xxstring);
5615         z = setnum(&dialint,x,y,-1);
5616         if (z > -1 && dialint < 0) {
5617             printf("?Sorry, negative dial interval not valid: %d\n",dialint);
5618             return(-9);
5619         }
5620         return(z);
5621
5622       case XYDLAC:                      /* DIAL AREA-CODE */
5623         if ((x = dialstr(&diallac,"Area code you are calling from")) < 0)
5624           return(x);
5625         if (diallac) {
5626             if (!rdigits(diallac)) {
5627                 printf("?Sorry, area code must be numeric\n");
5628                 if (*diallac == '(')
5629                   printf("(please omit the parentheses)\n");
5630                 if (*diallac == '/')
5631                   printf("(no slashes, please)\n");
5632                 if (diallac) free(diallac);
5633                 diallac = NULL;
5634                 return(-9);
5635             }
5636         }
5637         return(x);
5638
5639       case XYDCNF:                      /* CONFIRMATION */
5640         return(success = seton(&dialcnf));
5641
5642       case XYDCVT:                      /* CONVERT-DIRECTORY */
5643         if ((y = cmkey(dcnvtab,3,"","ask",xxstring)) < 0)
5644           return(y);
5645         if ((x = cmcfm()) < 0)
5646           return(x);
5647         dialcvt = y;
5648         return(success = 1);
5649
5650       case XYDLCC:                      /* DIAL COUNTRY-CODE */
5651         x = dialstr(&diallcc,"Country code you are calling from");
5652         if (x < 1) return(x);
5653         if (diallcc) {
5654             if (!rdigits(diallcc)) {
5655                 printf("?Sorry, country code must be numeric\n");
5656                 if (*diallcc == '+')
5657                   printf("(please omit the plus sign)\n");
5658                 if (diallcc) free(diallcc);
5659                 diallcc = NULL;
5660                 return(-9);
5661             }
5662             if (!strcmp(diallcc,"1")) { /* Set defaults for USA and Canada */
5663                 if (!dialldp)           /* Long-distance prefix */
5664                   makestr(&dialldp,"1");
5665                 if (!dialixp)           /* International dialing prefix */
5666                   makestr(&dialixp,"011");
5667                 if (ntollfree == 0) {   /* Toll-free area codes */
5668                     if ((dialtfc[0] = malloc(4))) {
5669                         strcpy(dialtfc[0],"800"); /* 1970-something */
5670                         ntollfree++;
5671                         if ((dialtfc[1] = malloc(4))) {
5672                             strcpy(dialtfc[1],"888"); /* 1996 */
5673                             ntollfree++;
5674                             if ((dialtfc[2] = malloc(4))) {
5675                                 strcpy(dialtfc[2],"877"); /* 5 April 1998 */
5676                                 ntollfree++;
5677                                 if ((dialtfc[3] = malloc(4))) {
5678                                     strcpy(dialtfc[3],"866"); /* 2000? */
5679                                     ntollfree++;
5680                                 }
5681                             }
5682                         }
5683                     }
5684                 }
5685                 if (!dialtfp)           /* Toll-free dialing prefix */
5686                   makestr(&dialtfp,"1");
5687 #ifdef COMMENT
5688 /* The time for this is past */
5689             } else if (!strcmp(diallcc,"358") &&
5690                        ((int) strcmp(zzndate(),"19961011") > 0)
5691                        ) {              /* Finland */
5692                 if (!dialldp)           /* Long-distance prefix */
5693                   makestr(&dialldp,"9");
5694                 if (!dialixp)           /* International dialing prefix */
5695                   makestr(&dialixp,"990");
5696 #endif /* COMMENT */
5697             } else {                    /* Everywhere else ... */
5698                 if (!dialldp) {
5699                     if ((dialldp = malloc(4)))
5700                       strcpy(dialldp,"0");
5701                 }
5702                 if (!dialixp) {
5703                     if ((dialixp = malloc(4)))
5704                       strcpy(dialixp,"00");
5705                 }
5706             }
5707             if (!strcmp(diallcc,"33"))  /* France */
5708               dialfld = 1;              /* Long-distance dialing is forced */
5709         }
5710         return(success = 1);
5711
5712       case XYDIXP:                      /* DIAL INTL-PREFIX */
5713         return(dialstr(&dialixp,"International dialing prefix"));
5714
5715       case XYDIXS:                      /* DIAL INTL-SUFFIX */
5716         return(dialstr(&dialixs,"International dialing suffix"));
5717
5718       case XYDLDP:                      /* DIAL LD-PREFIX */
5719         return(dialstr(&dialldp,"Long-distance dialing prefix"));
5720
5721       case XYDLDS:                      /* DIAL LD-SUFFIX */
5722         return(dialstr(&diallds,"Long-distance dialing suffix"));
5723
5724       case XYDLCP:                      /* DIAL LC-PREFIX */
5725         return(dialstr(&diallcp,"Local dialing prefix"));
5726
5727       case XYDLCS:                      /* DIAL LC-SUFFIX */
5728         return(dialstr(&diallcs,"Local dialing suffix"));
5729
5730 #ifdef COMMENT
5731       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
5732         return(dialstr(&dialpxx,"Exchange of PBX you are calling from"));
5733 #endif /* COMMENT */
5734
5735       case XYDPXI: {                    /* DIAL PBX-INTERNAL-PREFIX */
5736 #ifdef COMMENT
5737           return(dialstr(&dialpxi,
5738                        "Internal-call prefix of PBX you are calling from"));
5739 #else
5740           int x;
5741           if ((x = cmtxt("Internal-call prefix of PBX you are calling from",
5742                          "",&s,NULL)) < 0) /* Don't evaluate */
5743             return(x);
5744 #ifndef NOSPL
5745           if (*s) {
5746               char c, * p = tmpbuf;
5747               if (*s == '\\') {
5748                   c = *(s+1);
5749                   if (isupper(c)) c = tolower(c);
5750                   if (c != 'f' &&
5751                       ckstrcmp(s,"\\v(d$px)",8,0) &&
5752                       ckstrcmp(s,"\\v(d$pxx)",9,0) &&
5753                       ckstrcmp(s,"\\v(d$p)",7,0)) {
5754                       x = TMPBUFSIZ;
5755                       zzstring(s,&p,&x);
5756                       s = tmpbuf;
5757                   }
5758               }
5759           }
5760 #endif /* NOSPL */
5761           makestr(&dialpxi,s);
5762           return(1);
5763       }
5764 #endif /* COMMENT */
5765
5766       case XYDPXO:                      /* DIAL PBX-OUTSIDE-PREFIX */
5767         return(dialstr(&dialpxo,
5768                        "Outside-line prefix of PBX you are calling from"));
5769
5770       case XYDSFX:                      /* DIAL INTL-SUFFIX */
5771         return(dialstr(&dialsfx," Telephone number suffix for dialing"));
5772
5773       case XYDSRT:                      /* DIAL SORT */
5774         return(success = seton(&dialsrt));
5775
5776       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
5777       case XYDTFC: {                    /* DIAL TOLL-FREE-AREA-CODE  */
5778           int n, i;                     /* (zero or more of them...) */
5779           char * p[MAXTOLLFREE];        /* Temporary pointers */
5780           char * m;
5781           for (n = 0; n < MAXTOLLFREE; n++) {
5782               if (n == 0) {
5783                   m = (y == XYDTFC) ?
5784                   "Toll-free area code(s) in the country you are calling from"
5785                     : "Exchange(s) of PBX you are calling from";
5786               } else {
5787                   m = (y == XYDTFC) ?
5788                     "Another toll-free area code"
5789                       : "Another PBX exchange";
5790               }
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 == XYDTFC) ? ntollfree : ndialpxx;
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 == XYDTFC)
5810                     makestr(&(dialtfc[i]),NULL);
5811                   else
5812                     makestr(&(dialpxx[i]),NULL);
5813               }
5814               if  (y == XYDTFC)
5815                 ntollfree = n;          /* New count */
5816               else
5817                 ndialpxx = n;
5818               for (i = 0; i < n; i++) { /* New list */
5819                   if  (y == XYDTFC)
5820                     makestr(&(dialtfc[i]),p[i]);
5821                   else
5822                     makestr(&(dialpxx[i]),p[i]);
5823               }
5824               x = 1;
5825           }
5826           for (i = 0; i < n; i++)
5827             if (p[i]) free(p[i]);
5828           return(x);
5829       }
5830
5831       case XYDTFP:                      /* TOLL-FREE-PREFIX */
5832         return(dialstr(&dialtfp,
5833                        " Long-distance prefix for toll-free dialing"));
5834
5835       case XYDCON:                      /* CONNECT */
5836         z = -1;
5837         if ((y = cmkey(crrtab,ncrr,"","auto",xxstring)) < 0) return(y);
5838         if (y != CAR_OFF)               /* AUTO or ON? */
5839           if ((z = cmkey(qvtab,nqvt,"","verbose",xxstring)) < 0) return(z);
5840         if ((x = cmcfm()) < 0) return(x);
5841         if (z > -1)
5842           dialcq = z;
5843         dialcon = y;
5844         return(success = 1);
5845
5846       case XYDRSTR:                     /* RESTRICT */
5847         if ((y = cmkey(drstrtab,4,"","none",xxstring)) < 0) return(y);
5848         if ((x = cmcfm()) < 0) return(x);
5849         dialrstr = y;
5850         return(success = 1);
5851
5852       case XYDLLAC: {                   /* Local area-code list  */
5853           int n, i;                     /* (zero or more of them...) */
5854           char * p[MAXLOCALAC]; /* Temporary pointers */
5855           for (n = 0; n < MAXLOCALAC; n++) {
5856               if ((x = cmfld(
5857                     "Area code to which calls from your area are local",
5858                        "",&s,xxstring)) < 0)
5859                 break;
5860               if (s) {
5861                   int k;
5862                   k = (int) strlen(s);
5863                   if (k > 0) {
5864                       if ((p[n] = malloc(k + 1)))
5865                         strcpy(p[n], s); /* safe */
5866                   } else break;
5867               } else break;
5868           }
5869           if (x == -3) {                /* Command was successful */
5870               if ((x = cmcfm()) < 0)
5871                 return(x);
5872               for (i = 0; i < nlocalac; i++) /* Remove old list, if any */
5873                 if (diallcac[i]) {
5874                     free(diallcac[i]);
5875                     diallcac[i] = NULL;
5876                 }
5877               nlocalac = n;             /* New count */
5878               for (i = 0; i < nlocalac; i++) /* New list */
5879                 diallcac[i] = p[i];
5880               return(success = 1);
5881           } else {                      /* Parse error, undo everything */
5882               for (i = 0; i < n; i++)
5883                 if (p[i]) free(p[i]);
5884               return(x);
5885           }
5886       }
5887
5888       case XYDFLD:
5889         return(success = seton(&dialfld));
5890
5891       case XYDIDT:                      /* DIAL IGNORE-DIALTONE */
5892         return(seton(&dialidt));
5893
5894       case XYDPAC:
5895         y = cmnum(
5896               "Milliseconds to pause between each character sent to dialer",
5897                   "",10,&x,xxstring);
5898         return(setnum(&dialpace,x,y,9999));
5899
5900 #ifndef NOSPL
5901       case XYDMAC:
5902         if ((x = cmfld("Name of macro to execute just prior to dialing",
5903                        "",&s,xxstring)) < 0) {
5904             if (x == -3)
5905               s = NULL;
5906             else
5907               return(x);
5908         }
5909         if (s) {
5910             if (!*s) {
5911                 s = NULL;
5912             } else {
5913                 ckstrncpy(line,s,LINBUFSIZ);
5914                 s = line;
5915             }
5916         }
5917         if ((x = cmcfm()) < 0)
5918           return(x);
5919         makestr(&dialmac,s);
5920         return(success = 1);
5921 #endif /* NOSPL */
5922
5923       case XYDPUCC:                     /* Pulse country codes */
5924       case XYDTOCC: {                   /* Tone country codes */
5925           int n, i;
5926           char * p[MAXTPCC];
5927           char * m;
5928           for (n = 0; n < MAXTPCC; n++) {
5929               if (n == 0) {
5930                   m = (y == XYDPUCC) ?
5931                   "Country code where Pulse dialing is required"
5932                     : "Country code where Tone dialing is available";
5933               } else
5934                 m = "Another country code";
5935               if ((x = cmfld(m,"",&s,xxstring)) < 0)
5936                 break;
5937               if (s) {
5938                   int k;
5939                   k = (int) strlen(s);
5940                   if (k > 0) {
5941                       if ((p[n] = malloc(k + 1)))
5942                         strcpy(p[n], s); /* safe */
5943                   } else break;
5944               } else break;
5945           }
5946           if (x == -3) {                /* Command was successful */
5947               int m;
5948               m = (y == XYDPUCC) ? ndialpucc : ndialtocc;
5949               if ((x = cmcfm()) < 0)
5950                 return(x);
5951               x = 1;
5952               for (i = 0; i < m; i++) { /* Remove old list, if any */
5953                   if (y == XYDPUCC)
5954                     makestr(&(dialpucc[i]),NULL);
5955                   else
5956                     makestr(&(dialtocc[i]),NULL);
5957               }
5958               if (y == XYDPUCC) {
5959                   ndialpucc = n;                /* New count */
5960               } else {
5961                   ndialtocc = n;
5962               }
5963               for (i = 0; i < n; i++) { /* New list */
5964                   if (y == XYDPUCC) {
5965                       makestr(&(dialpucc[i]),p[i]);
5966                   } else {
5967                       makestr(&(dialtocc[i]),p[i]);
5968                   }
5969               }
5970               x = 1;
5971           }
5972           for (i = 0; i < n; i++)
5973             if (p[i]) free(p[i]);
5974           return(x);
5975       }
5976       case XYDTEST:
5977         return(seton(&dialtest));
5978
5979       default:
5980         printf("?Unexpected SET DIAL parameter\n");
5981         return(-9);
5982     }
5983 }
5984
5985 #ifndef NOSHOW
5986 int                                     /* SHOW MODEM */
5987 shomodem() {
5988     MDMINF * p;
5989     int x, n, mdm;
5990     char c;
5991     long zz;
5992
5993 #ifdef IKSD
5994     if (inserver) {
5995         printf("Sorry, command disabled\r\n");
5996         return(success = 0);
5997     }
5998 #endif /* IKSD */
5999
6000     shmdmlin();
6001     printf("\n");
6002
6003     mdm = (mdmtyp > 0) ? mdmtyp : mdmsav;
6004     p = (mdm > 0) ? modemp[mdm] : NULL;
6005
6006     if (p) {
6007         printf(" %s\n\n", dialname ? dialname : p->name);
6008
6009         printf(" Modem capabilities:    ");
6010         zz = dialcapas ? dialcapas : p->capas;
6011         if (!zz) {
6012             printf(" (none)");
6013         } else {
6014             if (zz & CKD_AT) printf(" AT");
6015             if (zz & CKD_V25) printf(" ITU");
6016             if (zz & CKD_SB) printf(" SB");
6017             if (zz & CKD_EC) printf(" EC");
6018             if (zz & CKD_DC) printf(" DC");
6019             if (zz & CKD_HW) printf(" HWFC");
6020             if (zz & CKD_SW) printf(" SWFC");
6021             if (zz & CKD_KS) printf(" KS");
6022             if (zz & CKD_TB) printf(" TB");
6023         }
6024         printf("\n Modem carrier-watch:    ");
6025         if (carrier == CAR_OFF) printf("off\n");
6026         else if (carrier == CAR_ON) printf("on\n");
6027         else if (carrier == CAR_AUT) printf("auto\n");
6028         else printf("unknown\n");
6029
6030         printf(" Modem maximum-speed:    ");
6031         zz = (dialmax > 0L) ? dialmax : p->max_speed;
6032         if (zz > 0)
6033           printf("%ld bps\n", zz);
6034         else
6035           printf("(unknown)\n");
6036         printf(" Modem error-correction: %s\n", dialec ? "on" : "off");
6037         printf(" Modem compression:      %s\n", dialdc ? "on" : "off");
6038         printf(" Modem speed-matching:   %s",   mdmspd ? "on" : "off");
6039         printf(" (interface speed %s)\n", mdmspd ? "changes" : "is locked");
6040         printf(" Modem flow-control:     ");
6041         if (dialfc == FLO_NONE) printf("none\n");
6042         else if (dialfc == FLO_XONX) printf("xon/xoff\n");
6043         else if (dialfc == FLO_RTSC) printf("rts/cts\n");
6044         else if (dialfc == FLO_AUTO) printf("auto\n");
6045         printf(" Modem hangup-method:    %s\n",
6046                dialmhu ?
6047                "modem-command" :
6048                "rs232-signal"
6049                );
6050         printf(" Modem speaker:          %s\n", showoff(mdmspk));
6051         printf(" Modem volume:           %s\n",
6052                (mdmvol == 2) ? "medium" : ((mdmvol <= 1) ? "low" : "high"));
6053         printf(" Modem kermit-spoof:     %s\n", dialksp ? "on" : "off");
6054         c = (char) (x = (dialesc ? dialesc : p->esc_char));
6055         printf(" Modem escape-character: %d", x);
6056         if (isprint(c))
6057           printf(" (= \"%c\")",c);
6058         printf(
6059 "\n\nMODEM COMMANDs (* = set automatically by SET MODEM TYPE):\n\n");
6060         debug(F110,"show dialini",dialini,0);
6061         printf(" %c Init-string:          ", dialini ? ' ' : '*' );
6062         shods(dialini ? dialini : p->wake_str);
6063         printf(" %c Dial-mode-string:     ", dialmstr ? ' ' : '*' );
6064         shods(dialmstr ? dialmstr : p->dmode_str);
6065         n = local ? 19 : 20;
6066         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6067         printf(" %c Dial-mode-prompt:     ", dialmprmt ? ' ' : '*' );
6068         shods(dialmprmt ? dialmprmt : p->dmode_prompt);
6069         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6070         printf(" %c Dial-command:         ", dialcmd ? ' ' : '*' );
6071         shods(dialcmd ? dialcmd : p->dial_str);
6072         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6073         printf(" %c Compression on:       ", dialdcon ? ' ' : '*' );
6074         if (!dialdcon)
6075           debug(F110,"dialdcon","(null)",0);
6076         else
6077           debug(F110,"dialdcon",dialdcon,0);
6078         shods(dialdcon ? dialdcon : p->dc_on_str);
6079         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6080         printf(" %c Compression off:      ", dialdcoff ? ' ' : '*' );
6081         shods(dialdcoff ? dialdcoff : p->dc_off_str);
6082         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6083         printf(" %c Error-correction on:  ", dialecon ? ' ' : '*' );
6084         shods(dialecon ? dialecon : p->ec_on_str);
6085         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6086         printf(" %c Error-correction off: ", dialecoff ? ' ' : '*' );
6087         shods(dialecoff ? dialecoff : p->ec_off_str);
6088         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6089         printf(" %c Autoanswer on:        ", dialaaon ? ' ' : '*' );
6090         shods(dialaaon ? dialaaon : p->aa_on_str);
6091         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6092         printf(" %c Autoanswer off:       ", dialaaoff ? ' ' : '*' );
6093         shods(dialaaoff ? dialaaoff : p->aa_off_str);
6094         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6095
6096         printf(" %c Speaker on:           ", dialspon ? ' ' : '*' );
6097         shods(dialspon ? dialspon : p->sp_on_str);
6098         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6099         printf(" %c Speaker off:          ", dialspoff ? ' ' : '*' );
6100         shods(dialspoff ? dialspoff : p->sp_off_str);
6101         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6102         printf(" %c Volume low:           ", dialvol1 ? ' ' : '*' );
6103         shods(dialvol1 ? dialvol1 : p->vol1_str);
6104         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6105         printf(" %c Volume medium:        ", dialvol2 ? ' ' : '*' );
6106         shods(dialvol2 ? dialvol2 : p->vol2_str);
6107         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6108         printf(" %c Volume high:          ", dialvol3 ? ' ' : '*' );
6109         shods(dialvol3 ? dialvol3 : p->vol3_str);
6110         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6111
6112         printf(" %c Hangup-command:       ", dialhcmd ? ' ' : '*' );
6113         shods(dialhcmd ? dialhcmd : p->hup_str);
6114         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6115         printf(" %c Hardware-flow:        ", dialhwfc ? ' ' : '*' );
6116         shods(dialhwfc ? dialhwfc : p->hwfc_str);
6117         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6118         printf(" %c Software-flow:        ", dialswfc ? ' ' : '*' );
6119         shods(dialswfc ? dialswfc : p->swfc_str);
6120         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6121         printf(" %c No-flow-control:      ", dialnofc ? ' ' : '*' );
6122         shods(dialnofc ? dialnofc : p->nofc_str);
6123         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6124         printf(" %c Pulse:                ", dialpulse ? ' ' : '*');
6125         shods(dialpulse ? dialpulse : p->pulse);
6126         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6127         printf(" %c Tone:                 ", dialtone ? ' ' : '*');
6128         shods(dialtone ? dialtone : p->tone);
6129
6130         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6131         printf(" %c Ignore-dialtone:      ", dialx3 ? ' ' : '*');
6132         shods(dialx3 ? dialx3 : p->ignoredt);
6133
6134         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6135         printf(" %c Predial-init:         ", dialini2 ? ' ' : '*');
6136         shods(dialini2 ? dialini2 : p->ini2);
6137
6138         if (++n > cmd_rows - 4) if (!askmore()) return(0); else n = 0;
6139         printf("\n For more info: SHOW DIAL and SHOW COMMUNICATIONS\n");
6140
6141     } else if (mdm > 0) {
6142         printf("Modem info for \"%s\" not filled in yet\n", gmdmtyp());
6143     } else printf(
6144 " No modem selected, so DIAL and most SET MODEM commands have no effect.\n\
6145  Use SET MODEM TYPE to select a modem.\n");
6146     return(success = 1);
6147 }
6148 #endif /* NOSHOW */
6149 #endif /* NODIAL */
6150
6151 #ifdef CK_TAPI
6152 int                                             /* TAPI action commands */
6153 dotapi() {
6154     int x,y;
6155     char *s;
6156
6157     if (!TAPIAvail) {
6158         printf("\nTAPI is unavailable on this system.\n");
6159         return(-9);
6160     }
6161     if ((y = cmkey(tapitab,ntapitab,"MS TAPI command","",xxstring)) < 0)
6162       return(y);
6163     switch (y) {
6164       case XYTAPI_CFG: {                        /* TAPI CONFIGURE-LINE */
6165           extern struct keytab * tapilinetab;
6166           extern struct keytab * _tapilinetab;
6167           extern int ntapiline;
6168           extern int LineDeviceId;
6169           int lineID=LineDeviceId;
6170           if (TAPIAvail)
6171             cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
6172           if (tapilinetab && _tapilinetab && ntapiline > 0) {
6173               int i=0, j = 9999, k = -1;
6174
6175               if ( LineDeviceId == -1 ) {
6176                   /* Find out what the lowest numbered TAPI device is */
6177                   /* and use it as the default.                       */
6178                   for (i = 0; i < ntapiline; i++ ) {
6179                       if (tapilinetab[i].kwval < j) {
6180                           k = i;
6181                       }
6182                   }
6183               } else {
6184                   /* Find the LineDeviceId in the table and use that entry */
6185                   for (i = 0; i < ntapiline; i++ ) {
6186                       if (tapilinetab[i].kwval == LineDeviceId) {
6187                           k = i;
6188                           break;
6189                       }
6190                   }
6191               }
6192               if (k >= 0)
6193                 s = _tapilinetab[k].kwd;
6194               else
6195                 s = "";
6196
6197               if ((y = cmkey(_tapilinetab,ntapiline,
6198                               "TAPI device name",s,xxstring)) < 0)
6199                 return(y);
6200               lineID = y;
6201           }
6202           if ((x = cmcfm()) < 0) return(x);
6203 #ifdef IKSD
6204           if (inserver) {
6205               printf("Sorry, command disabled\r\n");
6206               return(success = 0);
6207           }
6208 #endif /* ISKD */
6209           cktapiConfigureLine(lineID);
6210           break;
6211       }
6212       case XYTAPI_DIAL:                 /* TAPI DIALING-PROPERTIES */
6213         if ((x = cmcfm()) < 0)
6214           return(x);
6215 #ifdef IKSD
6216         if (inserver) {
6217             printf("Sorry, command disabled\r\n");
6218             return(success = 0);
6219         }
6220 #endif /* ISKD */
6221         cktapiDialingProp();
6222         break;
6223     }
6224     return(success = 1);
6225 }
6226
6227 static int                              /* SET TAPI command options */
6228 settapi() {
6229     int x, y;
6230     char *s;
6231
6232     if (!TAPIAvail) {
6233         printf("\nTAPI is unavailable on this system.\n");
6234         return(-9);
6235     }
6236     if ((y = cmkey(settapitab,nsettapitab,"MS TAPI option","",xxstring)) < 0)
6237       return(y);
6238     switch (y) {
6239       case XYTAPI_USE:
6240         return (success = seton(&tapiusecfg));
6241       case XYTAPI_LGHT:
6242         return (success = seton(&tapilights));
6243       case XYTAPI_PRE:
6244         return (success = seton(&tapipreterm));
6245       case XYTAPI_PST:
6246         return (success = seton(&tapipostterm));
6247       case XYTAPI_INA:
6248         y = cmnum("seconds of inactivity before auto-disconnect",
6249                   "0",10,&x,xxstring);
6250         return(setnum(&tapiinactivity,x,y,65535));
6251       case XYTAPI_BNG:
6252         y = cmnum("seconds to wait for credit card tone",
6253                   "8",10,&x,xxstring);
6254         return(setnum(&tapibong,x,y,90));
6255       case XYTAPI_MAN:
6256         return (success = seton(&tapimanual));
6257       case XYTAPI_CON:                  /* TAPI CONVERSIONS */
6258         return (success = setonaut(&tapiconv));
6259       case XYTAPI_LIN:                  /* TAPI LINE */
6260         x = setlin(XYTAPI_LIN,1,0);
6261         if (x > -1) didsetlin++;
6262         return(x);
6263       case XYTAPI_PASS: {               /* TAPI PASSTHROUGH */
6264 #ifdef NODIAL
6265           printf("\n?Modem-dialing not supported\n");
6266           return(-9);
6267 #else /* NODIAL */
6268           /* Passthrough became Modem-dialing which is an antonym */
6269           success = seton(&tapipass);
6270           tapipass = !tapipass;
6271           return (success);
6272 #endif /* NODIAL */        
6273       }
6274       case XYTAPI_LOC: {                /* TAPI LOCATION */
6275           extern char tapiloc[];
6276           extern int tapilocid;
6277           int i = 0, j = 9999, k = -1;
6278
6279           cktapiBuildLocationTable(&tapiloctab, &ntapiloc);
6280           if (!tapiloctab || !ntapiloc) {
6281               printf("\nNo TAPI Locations are configured for this system\n");
6282               return(-9);
6283           }
6284           if (tapilocid == -1)
6285             tapilocid = cktapiGetCurrentLocationID();
6286
6287           /* Find the current tapiloc entry */
6288           /* and use it as the default. */
6289           for (k = 0; k < ntapiloc; k++) {
6290               if (tapiloctab[k].kwval == tapilocid)
6291                 break;
6292           }
6293           if (k >= 0 && k < ntapiloc)
6294             s = tapiloctab[k].kwd;
6295           else
6296             s = "";
6297
6298           if ((y = cmkey(tapiloctab,ntapiloc, "TAPI location",s,xxstring)) < 0)
6299             return(y);
6300
6301           if ((x = cmcfm()) < 0)
6302             return(x);
6303 #ifdef IKSD
6304           if (inserver) {
6305               printf("Sorry, command disabled\r\n");
6306               return(success = 0);
6307           }
6308 #endif /* IKSD */
6309           cktapiFetchLocationInfoByID( y );
6310 #ifndef NODIAL
6311           CopyTapiLocationInfoToKermitDialCmd();
6312 #endif /* NODIAL */
6313         }
6314         break;
6315     }
6316     return(success=1);
6317 }
6318 #endif /* CK_TAPI */
6319 #endif /* NOLOCAL */
6320
6321 #ifndef NOSPL
6322 /* Method for evaluating \%x and \&x[] variables */
6323
6324 static struct keytab varevaltab[] = {
6325     { "recursive", 1, 0 },
6326     { "simple",    0, 0 }
6327 };
6328 static int nvarevaltab = (sizeof(varevaltab) / sizeof(struct keytab));
6329
6330 int
6331 setvareval() {
6332     int x = 0, y = 0;
6333     extern int vareval;
6334 #ifdef DCMDBUF
6335     extern int * xvarev;
6336 #else
6337     extern int xvarev[];
6338 #endif /* DCMDBUF */
6339
6340     if ((x = cmkey(varevaltab,
6341                    nvarevaltab, 
6342                    "Method for evaluating \\%x and \\&x[] variables",
6343                    "",
6344                    xxstring)) < 0)
6345       return(x);
6346     if ((y = cmcfm()) < 0)
6347       return(y);
6348     xvarev[cmdlvl] = x;
6349     vareval = x;
6350     return(success = 1);
6351 }
6352
6353 #ifdef CK_ANSIC                         /* SET ALARM */
6354 int
6355 setalarm(long xx)
6356 #else
6357 int
6358 setalarm(xx) long xx;
6359 #endif /* CK_ANSIC */
6360 /* setalarm */ {
6361 #ifdef COMMENT
6362     int yyyy, mm, dd, x;
6363     char *s;
6364     long zz;
6365     char buf[6];
6366 #endif /* COMMENT */
6367     long sec, jd;
6368     char xbuf[20], * p;
6369
6370     debug(F101,"setalarm xx","",xx);
6371     ck_alarm = 0L;                      /* 0 = no alarm (in case of error) */
6372     if (xx < 0L) {
6373         printf("%ld - illegal value, must be 0 or positive\n", xx);
6374         return(-9);
6375     }
6376     if (xx == 0L) {                     /* CLEAR ALARM */
6377         alrm_date[0] = NUL;
6378         alrm_time[0] = NUL;
6379         return(1);
6380     }
6381 #ifdef COMMENT
6382     x = 8;                              /* Get current date */
6383     s = alrm_date;
6384     if (zzstring("\\v(ndate)",&s,&x) < 0) {
6385         printf("Internal date error, sorry.\n");
6386         alrm_date[0] = SP;
6387         return(-9);
6388     }
6389     x = 5;                              /* Get current time */
6390     s = alrm_time;
6391     if (zzstring("\\v(ntime)",&s,&x) < 0) {
6392         printf("Internal time error, sorry.\n");
6393         alrm_time[0] = SP;
6394         return(-9);
6395     }
6396     sprintf(buf,"%05ld",atol(alrm_time)); /* SAFE (20) */
6397     ckstrncpy(alrm_time,buf,8);
6398     debug(F110,"SET ALARM date (1)",alrm_date,0);
6399     debug(F110,"SET ALARM time (1)",alrm_time,0);
6400
6401     if ((zz = atol(alrm_time) + xx) < 0L) {
6402         printf("Internal time conversion error, sorry.\n");
6403         return(-9);
6404     }
6405     if (zz >= 86400L) {                 /* Alarm crosses midnight */
6406         char d[10];                     /* Local date buffer */
6407         int lastday;                    /* Last day of this month */
6408
6409         ckstrncpy(d,alrm_date,8);       /* We'll have to change the date */
6410
6411         x = (zz / 86400L);              /* How many days after today */
6412
6413         dd = atoi((char *)(d+6));       /* Parse yyyymmdd */
6414         d[6] = NUL;                     /* into yyyy, mm, dd ... */
6415         mm = atoi((char *)(d+4));
6416         d[4] = NUL;
6417         yyyy = atoi((char *)d);
6418
6419         /* How many days in this month */
6420
6421         lastday = mdays[mm];
6422         if (mm == 2 && yyyy % 4 == 0)   /* Works thru 2099 AD... */
6423           lastday++;
6424
6425         if (dd + x > lastday) {         /* Dumb loop */
6426             int y;
6427
6428             x -= (mdays[mm] - dd);      /* Deduct rest of this month's days */
6429
6430             /* There's a more elegant way to do this... */
6431
6432             while (1) {
6433                 mm++;                   /* Next month */
6434                 if (mm > 12) {          /* Wrap around */
6435                     mm = 1;             /* Jan, next year */
6436                     yyyy++;
6437                 }
6438                 y = mdays[mm];          /* Days in new month */
6439                 if (mm == 2 && yyyy % 4 == 0) /* Feb in leap year */
6440                   y++;                  /* Works until 2100 AD */
6441                 if (x - y < 1)
6442                   break;
6443                 x -= y;
6444             }
6445             dd = x;                     /* Day of alarm month */
6446         } else dd += x;
6447
6448         sprintf(alrm_date,"%04d%02d%02d",yyyy,mm,dd); /* SAFE (24) */
6449         zz = zz % 86400L;
6450     }
6451     sprintf(alrm_time,"%ld",zz);        /* SAFE (24) */
6452     debug(F110,"SET ALARM date (2)",alrm_date,0);
6453     debug(F110,"SET ALARM time (2)",alrm_time,0);
6454     ck_alarm = xx;
6455 #else
6456     /* Jul 1998 */
6457     ckstrncpy(xbuf,ckcvtdate("",1),20); /* Get current date and time */
6458     p = xbuf;
6459     ckstrncpy(alrm_date,xbuf,10);
6460     alrm_date[8] = NUL;
6461     sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
6462     debug(F110,"SET ALARM date (1)",alrm_date,0);
6463     debug(F101,"SET ALARM time (1)","",sec);
6464     if ((sec += xx) < 0L) {
6465         printf("Internal time conversion error, sorry.\n");
6466         return(-9);
6467     }
6468     if (sec >= 86400L) {                /* Alarm crosses midnight */
6469         long days;
6470         days = sec / 86400L;
6471         jd = mjd(p) + days;             /* Get modified Julian date */
6472         ckstrncpy(alrm_date,mjd2date(jd),10);
6473         sec %= 86400L;
6474     }
6475     sprintf(alrm_time,"%05ld",sec);     /* SAFE (24) */
6476     debug(F110,"SET ALARM date (2)",alrm_date,0);
6477     debug(F110,"SET ALARM time (2)",alrm_time,0);
6478     ck_alarm = 1;                       /* Alarm is set */
6479
6480 #endif /* COMMENT */
6481     return(success = 1);
6482 }
6483 #endif /* NOSPL */
6484
6485 #ifndef NOSETKEY
6486 int
6487 dosetkey() {                            /* SET KEY */
6488     int x, y;
6489     int flag = 0;
6490     int kc;                             /* Key code */
6491     char *s;                            /* Key binding */
6492 #ifndef NOKVERBS
6493     char *p;                            /* Worker */
6494 #endif /* NOKVERBS */
6495 #ifdef OS2
6496     extern int os2gks;
6497     extern int mskkeys;
6498     extern int initvik;
6499 #endif /* OS2 */
6500
6501     x_ifnum = 1;
6502     y = cmnum("numeric key code, or the word CLEAR,","",10,&kc,xxstring);
6503     x_ifnum = 0;
6504     if (y < 0) {
6505         debug(F111,"SET KEY",atmbuf,y);
6506         if (y == -2) {                  /* Not a valid number */
6507             if ((y = strlen(atmbuf)) < 0) /* Check for SET KEY CLEAR */
6508               return(-2);
6509             if (ckstrcmp(atmbuf,"clear",y,0))
6510               return(-2);
6511             if ((x = cmcfm()) < 0)
6512               return(x);
6513             for (y = 0; y < KMSIZE; y++) {
6514                 keymap[y] = (KEY) y;
6515                 macrotab[y] = NULL;
6516             }
6517 #ifdef OS2
6518             keymapinit();               /* Special OS/2 initializations */
6519             initvik = 1;                /* Update the VIK table */
6520 #endif /* OS2 */
6521             return(1);
6522         } else if (y == -3) {           /* SET KEY <Return> */
6523             printf(" Press key to be defined: "); /* Prompt for a keystroke */
6524 #ifdef UNIX
6525 #ifdef NOSETBUF
6526             fflush(stdout);
6527 #endif /* NOSETBUF */
6528 #endif /* UNIX */
6529             conbin((char)escape);       /* Put terminal in binary mode */
6530 #ifdef OS2
6531             os2gks = 0;                 /* Turn off Kverb preprocessing */
6532 #endif /* OS2 */
6533             kc = congks(0);             /* Get character or scan code */
6534 #ifdef OS2
6535             os2gks = 1;                 /* Turn on Kverb preprocessing */
6536 #endif /* OS2 */
6537             concb((char)escape);        /* Restore terminal to cbreak mode */
6538             if (kc < 0) {               /* Check for error */
6539                 printf("?Error reading key\n");
6540                 return(0);
6541             }
6542 #ifdef OS2
6543             shokeycode(kc,-1);          /* Show current definition */
6544 #else
6545             shokeycode(kc);             /* Show current definition */
6546 #endif /* OS2 */
6547             flag = 1;                   /* Remember it's a multiline command */
6548         } else                          /* Error */
6549           return(y);
6550     }
6551
6552     /* Normal SET KEY <scancode> <value> command... */
6553
6554 #ifdef OS2
6555     if (mskkeys)
6556       kc = msktock(kc);
6557 #endif /* OS2 */
6558
6559     if (kc < 0 || kc >= KMSIZE) {
6560         printf("?key code must be between 0 and %d\n", KMSIZE - 1);
6561         return(-9);
6562     }
6563     if (kc == escape) {
6564         printf("Sorry, %d is the CONNECT-mode escape character\n",kc);
6565         return(-9);
6566     }
6567 #ifdef OS2
6568     wideresult = -1;
6569 #endif /* OS2 */
6570     if (flag) {
6571         cmsavp(psave,PROMPTL);
6572         cmsetp(" Enter new definition: ");
6573         cmini(ckxech);
6574         cmflgs = 0;
6575         prompt(NULL);
6576     }
6577   def_again:
6578     if (flag)
6579       cmres();
6580     if ((y = cmtxt("key definition,\n\
6581 or Ctrl-C to cancel this command,\n\
6582 or Enter to restore default definition",
6583                    "",&s,NULL)) < 0) {
6584         if (flag)                       /* Handle parse errors */
6585           goto def_again;
6586         else
6587           return(y);
6588     }
6589     s = brstrip(s);
6590 #ifndef NOKVERBS
6591     p = s;                              /* Save this place */
6592 #endif /* NOKVERBS */
6593 /*
6594   If the definition included any \Kverbs, quote the backslash so the \Kverb
6595   will still be in the definition when the key is pressed.  We don't do this
6596   in zzstring(), because \Kverbs are valid only in this context and nowhere
6597   else.
6598
6599   We use this code active for all versions that support SET KEY, even if they
6600   don't support \Kverbs, because otherwise \K would behave differently for
6601   different versions.
6602 */
6603     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
6604         if ((x > 0) &&
6605             (s[x] == 'K' || s[x] == 'k')
6606             ) {                         /* Have K */
6607
6608             if ((x == 1 && s[x-1] == CMDQ) ||
6609                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
6610                 line[y++] = CMDQ;       /* Make it \\K */
6611             }
6612             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
6613                 line[y-1] = CMDQ;       /* Have \{K */
6614                 line[y++] = '{';        /* Make it \\{K */
6615             }
6616         }
6617         line[y] = s[x];
6618     }
6619     line[y++] = NUL;                    /* Terminate */
6620     s = line + y + 1;                   /* Point to after it */
6621     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
6622     if ((x < (LINBUFSIZ / 2)) ||
6623         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
6624         printf("?Key definition too long\n");
6625         if (flag) cmsetp(psave);
6626         return(-9);
6627     }
6628     s = line + y + 1;                   /* Point to result. */
6629
6630 #ifndef NOKVERBS
6631 /*
6632   Special case: see if the definition starts with a \Kverb.
6633   If it does, point to it with p, otherwise set p to NULL.
6634 */
6635     p = s;
6636     if (*p++ == CMDQ) {
6637         if (*p == '{') p++;
6638         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
6639     }
6640 #endif /* NOKVERBS */
6641
6642     if (macrotab[kc]) {                 /* Possibly free old macro from key. */
6643         free((char *)macrotab[kc]);
6644         macrotab[kc] = NULL;
6645     }
6646     switch (strlen(s)) {                /* Action depends on length */
6647       case 0:                           /* Reset to default binding */
6648         keymap[kc] = (KEY) kc;
6649         break;
6650       case 1:                           /* Single character */
6651         keymap[kc] = (CHAR) *s;
6652         break;
6653       default:                          /* Character string */
6654 #ifndef NOKVERBS
6655         if (p) {
6656             y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
6657             debug(F101,"set key kverb lookup",0,y); /* exact match required */
6658             if (y > -1) {
6659                 keymap[kc] = F_KVERB | y;
6660                 break;
6661             }
6662         }
6663 #endif /* NOKVERBS */
6664         keymap[kc] = (KEY) kc;
6665         macrotab[kc] = (MACRO) malloc(strlen(s)+1);
6666         if (macrotab[kc])
6667           strcpy((char *) macrotab[kc], s); /* safe */
6668         break;
6669     }
6670     if (flag) cmsetp(psave);
6671 #ifdef OS2
6672     initvik = 1;                        /* Update VIK table */
6673 #endif /* OS2 */
6674     return(1);
6675 }
6676 #endif /* NOSETKEY */
6677
6678 #ifdef STOPBITS
6679 struct keytab stoptbl[] = {
6680     { "1", 1, 0 },
6681     { "2", 2, 0 }
6682 };
6683 #endif /* STOPBITS */
6684
6685 static struct keytab sertbl[] = {
6686     { "7E1", 0, 0 },
6687     { "7E2", 1, 0 },
6688     { "7M1", 2, 0 },
6689     { "7M2", 3, 0 },
6690     { "7O1", 4, 0 },
6691     { "7O2", 5, 0 },
6692     { "7S1", 6, 0 },
6693     { "7S2", 7, 0 },
6694 #ifdef HWPARITY
6695     { "8E1", 9, 0 },
6696     { "8E2", 10, 0 },
6697 #endif /* HWPARITY */
6698     { "8N1", 8, 0 },
6699 #ifdef HWPARITY
6700     { "8N2", 11, 0 },
6701     { "8O1", 12, 0 },
6702     { "8O2", 13, 0 },
6703 #endif /* HWPARITY */
6704     { "", 0, 0 }
6705 };
6706 static int nsertbl = (sizeof(sertbl) / sizeof(struct keytab)) - 1;
6707
6708 static char * sernam[] = {              /* Keep this in sync with sertbl[] */
6709   "7E1", "7E2", "7M1", "7M2", "7O1", "7O2", "7S1", "7S2",
6710   "8N1", "8E1", "8E2", "8N2", "8O1", "8O2"
6711 };
6712
6713 static struct keytab optstab[] = {      /* SET OPTIONS table */
6714 #ifndef NOFRILLS
6715     { "delete",    XXDEL,   0},            /* DELETE */
6716 #endif /* NOFRILLS */
6717     { "directory", XXDIR,   0},         /* DIRECTORY */
6718 #ifdef CKPURGE
6719     { "purge",     XXPURGE, 0},         /* PURGE */
6720 #endif /* CKPURGE */
6721     { "type",      XXTYP,   0},         /* TYPE */
6722     { "", 0, 0}
6723 };
6724 static int noptstab =  (sizeof(optstab) / sizeof(struct keytab)) - 1;
6725
6726 #ifndef NOXFER
6727 /*
6728   PROTOCOL SELECTION.  Kermit is always available.  If CK_XYZ is defined at
6729   compile time, then the others become selections also.  In OS/2 and
6730   Windows, they are integrated and the various SET commands (e.g. "set file
6731   type") affect them as they would Kermit.  In other OS's (UNIX, VMS, etc),
6732   they are external protocols which are run via Kermit's REDIRECT mechanism.
6733   All we do is collect and verify the filenames and pass them along to the
6734   external protocol.
6735 */
6736 struct keytab protos[] = {
6737 #ifdef CK_XYZ
6738     "g",          PROTO_G,  CM_INV,
6739 #endif /* CK_XYZ */
6740     "kermit",     PROTO_K,  0,
6741 #ifdef CK_XYZ
6742     "other",      PROTO_O,  0,
6743     "x",          PROTO_X,  CM_INV|CM_ABR,
6744     "xmodem",     PROTO_X,  0,
6745     "xmodem-crc", PROTO_XC, 0,
6746     "y",          PROTO_Y,  CM_INV|CM_ABR,
6747     "ymodem",     PROTO_Y,  0,
6748     "ymodem-g",   PROTO_G,  0,
6749     "zmodem",     PROTO_Z,  0
6750 #endif /* CK_XYZ */
6751 };
6752 int nprotos =  (sizeof(protos) / sizeof(struct keytab));
6753
6754 #ifndef XYZ_INTERNAL
6755 #ifndef NOPUSH
6756 #define EXP_HANDLER 1
6757 #define EXP_STDERR  2
6758 #define EXP_TIMO    3
6759
6760 static struct keytab extprotab[] = {
6761     { "handler",          EXP_HANDLER, 0 },
6762     { "redirect-stderr",  EXP_STDERR, 0 },
6763     { "timeout",          EXP_TIMO, 0 }
6764 };
6765 static int nxtprotab =  (sizeof(extprotab) / sizeof(struct keytab));
6766 #endif  /* NOPUSH */
6767 #endif  /* XYZ_INTERNAL */
6768
6769 #define XPCMDLEN 71
6770
6771 _PROTOTYP(static int protofield, (char *, char *, char *));
6772 _PROTOTYP(static int setproto, (void));
6773
6774 static int
6775 protofield(current, help, px) char * current, * help, * px; {
6776
6777     char *s, tmpbuf[XPCMDLEN+1];
6778     int x;
6779
6780     if (current)                        /* Put braces around default */
6781       ckmakmsg(tmpbuf,TMPBUFSIZ,"{",current,"}",NULL);
6782     else
6783       tmpbuf[0] = NUL;
6784
6785     if ((x = cmfld(help, (char *)tmpbuf, &s, xxstring)) < 0)
6786       return(x);
6787     if ((int)strlen(s) > XPCMDLEN) {
6788         printf("?Sorry - maximum length is %d\n", XPCMDLEN);
6789         return(-9);
6790     } else if (*s) {
6791         strcpy(px,s);                   /* safe */
6792     } else {
6793         px = NULL;
6794     }
6795     return(x);
6796 }
6797
6798 static int
6799 setproto() {                            /* Select a file transfer protocol */
6800     /* char * s = NULL; */
6801     int x = 0, y;
6802     char s1[XPCMDLEN+1], s2[XPCMDLEN+1], s3[XPCMDLEN+1];
6803     char s4[XPCMDLEN+1], s5[XPCMDLEN+1], s6[XPCMDLEN+1], s7[XPCMDLEN+1];
6804     char * p1 = s1, * p2 = s2, *p3 = s3;
6805     char * p4 = s4, * p5 = s5, *p6 = s6, *p7 = s7;
6806
6807 #ifdef XYZ_INTERNAL
6808     extern int p_avail;
6809 #else
6810 #ifndef CK_REDIR
6811     x = 1;
6812 #endif /* CK_REDIR */
6813 #endif /* XYZ_INTERNAL */
6814     s1[0] = NUL;
6815     s2[0] = NUL;
6816     s3[0] = NUL;
6817     s4[0] = NUL;
6818     s5[0] = NUL;
6819     s6[0] = NUL;
6820
6821     if ((y = cmkey(protos,nprotos,"","kermit",xxstring)) < 0)
6822       return(y);
6823
6824     if (x && y != PROTO_K) {
6825         printf(
6826            "?Sorry, REDIRECT capability required for external protocols.\n");
6827         return(-9);
6828     }
6829     if ((x = protofield(ptab[y].h_b_init,
6830      "Optional command to send to host prior to uploading in binary mode",
6831                p1)) < 0) {
6832         if (x == -3) {
6833             protocol = y;               /* Set protocol but don't change */
6834             return(1);                  /* anything else */
6835         } else
6836           return(x);
6837     }
6838     if ((x = protofield(ptab[y].h_t_init,
6839      "Optional command to send to host prior to uploading in text mode",
6840                p2)) < 0) {
6841         if (x == -3)
6842           goto protoexit;
6843         else
6844           return(x);
6845     }
6846
6847     if (y == PROTO_K) {
6848         if ((x = protofield(ptab[y].h_x_init,
6849                     "Optional command to send to host to start Kermit server",
6850                             p3)) < 0) {
6851             if (x == -3)
6852               goto protoexit;
6853             else
6854               return(x);
6855         }
6856     }
6857
6858
6859 #ifndef XYZ_INTERNAL                    /* If XYZMODEM are external... */
6860
6861     if (y != PROTO_K) {
6862         if ((x = protofield(ptab[y].p_b_scmd,
6863                  "External command to SEND in BINARY mode with this protocol",
6864                             p4)) < 0) {
6865             if (x == -3)
6866               goto protoexit;
6867             else
6868               return(x);
6869         }
6870         if ((x = protofield(ptab[y].p_t_scmd,
6871                  "External command to SEND in TEXT mode with this protocol",
6872                             p5)) < 0) {
6873             if (x == -3)
6874               goto protoexit;
6875             else
6876               return(x);
6877         }
6878         if ((x = protofield(ptab[y].p_b_rcmd,
6879                "External command to RECEIVE in BINARY mode with this protocol",
6880                             p6)) < 0) {
6881             if (x == -3)
6882               goto protoexit;
6883             else
6884               return(x);
6885         }
6886         if ((x = protofield(ptab[y].p_t_rcmd,
6887                  "External command to RECEIVE in TEXT mode with this protocol",
6888                             p7)) < 0) {
6889             if (x == -3)
6890               goto protoexit;
6891             else
6892               return(x);
6893         }
6894     }
6895 #endif /* XYZ_INTERNAL */
6896
6897     if ((x = cmcfm()) < 0)              /* Confirm the command */
6898       return(x);
6899
6900 protoexit:                              /* Common exit from this routine */
6901
6902 #ifdef XYZ_INTERNAL
6903     if (!p_avail) {
6904         bleep(BP_WARN);
6905         printf("\n?X,Y, and Zmodem are unavailable\n");
6906         return(success = 0);
6907     }
6908 #endif /* XYZ_INTERNAL */
6909
6910     p1 = brstrip(p1);
6911     p2 = brstrip(p2);
6912     p3 = brstrip(p3);
6913     p4 = brstrip(p4);
6914     p5 = brstrip(p5);
6915     p6 = brstrip(p6);
6916     p7 = brstrip(p7);
6917     initproto(y,p1,p2,p3,p4,p5,p6,p7);
6918     return(success = 1);
6919 }
6920
6921 #ifndef NOPUSH
6922 #ifndef XYZ_INTERNAL
6923
6924 #define DEF_EXP_TIMO 12  /* Default timeout for external protocol (seconds) */
6925
6926 int exp_handler = 0;                    /* These are exported */
6927 int exp_timo = DEF_EXP_TIMO;
6928 int exp_stderr = SET_AUTO;
6929
6930 VOID
6931 shoextern() {                           /* Invoked by SHOW PROTOCOL */
6932     printf("\n External-protocol handler:         %s\n",
6933            exp_handler ? (exp_handler == 1 ? "pty" : "system") : "automatic");
6934 #ifdef COMMENT
6935     printf(" External-protocol redirect-stderr: %s\n", showooa(exp_stderr));
6936 #endif  /* COMMENT */
6937     printf(" External-protocol timeout:         %d (sec)\n", exp_timo);
6938 }
6939
6940 static struct keytab setexternhandler[] = {
6941     { "automatic", 0, 0 },
6942     { "pty",       1, 0 },
6943     { "system",    2, 0 }
6944 };
6945
6946 int
6947 setextern() {                           /* SET EXTERNAL-PROTOCOL */
6948     int x, y;
6949     if ((x = cmkey(extprotab,nxtprotab,"","",xxstring)) < 0)
6950       return(x);
6951     switch (x) {
6952       case EXP_HANDLER:
6953         if ((x = cmkey(setexternhandler,3,"","automatic",xxstring)) < 0)
6954           return(x);
6955         if ((y = cmcfm()) < 0)
6956           return(y);
6957         exp_handler = x;
6958         break;
6959         
6960 #ifdef COMMENT
6961       case EXP_STDERR:
6962         if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
6963           return(x);
6964         if ((y = cmcfm()) < 0)
6965           return(y);
6966         exp_stderr = x;
6967         break;
6968 #endif  /* COMMENT */
6969
6970       case EXP_TIMO:
6971         y = cmnum("Inactivity timeout, seconds,",ckitoa(DEF_EXP_TIMO),
6972                   10,&x,xxstring);
6973         return(setnum(&exp_timo,x,y,-1));
6974     }
6975     return(success = 1);
6976 }
6977 #endif  /* XYZ_INTERNAL */
6978 #endif  /* NOPUSH */
6979
6980 int
6981 setdest() {
6982     int x, y;
6983     if ((y = cmkey(desttab,ndests,"","disk",xxstring)) < 0) return(y);
6984     if ((x = cmcfm()) < 0) return(x);
6985     dest = y;
6986     return(1);
6987 }
6988 #endif /* NOXFER */
6989
6990 #ifdef DECNET
6991 struct keytab dnettab[] = {
6992 #ifndef OS2ONLY
6993     "cterm", NP_CTERM, 0,
6994 #endif /* OS2ONLY */
6995     "lat",   NP_LAT,   0
6996 };
6997 int ndnet =  (sizeof(dnettab) / sizeof(struct keytab));
6998 #endif /* DECNET */
6999
7000 /*  S E T P R I N T E R  --  SET PRINTER command  */
7001
7002 #ifdef PRINTSWI
7003 static struct keytab prntab[] = {       /* SET PRINTER switches */
7004     "/bidirectional",    PRN_BID, 0,
7005 #ifdef OS2
7006     "/character-set",    PRN_CS,  CM_ARG,
7007 #endif /* OS2 */
7008     "/command",          PRN_PIP, CM_ARG,
7009     "/dos-device",       PRN_DOS, CM_ARG,
7010     "/end-of-job-string",PRN_TRM, CM_ARG,
7011     "/file",             PRN_FIL, CM_ARG,
7012 #ifdef BPRINT
7013     "/flow-control",     PRN_FLO, CM_ARG,
7014 #endif /* BPRINT */
7015     "/job-header-file",  PRN_SEP, CM_ARG,
7016 #ifdef OS2
7017     "/length",           PRN_LEN, CM_ARG,
7018 #endif /* OS2 */
7019     "/none",             PRN_NON, 0,
7020 #ifdef OS2
7021     "/nopostscript",     PRN_RAW, 0,
7022     "/nops",             PRN_RAW, CM_INV,
7023 #endif /* OS2 */
7024     "/output-only",      PRN_OUT, 0,
7025 #ifdef BPRINT
7026     "/parity",           PRN_PAR, CM_ARG,
7027 #endif /* BPRINT */
7028     "/pipe",             PRN_PIP, CM_ARG|CM_INV,
7029 #ifdef OS2
7030     "/postscript",       PRN_PS,  0,
7031     "/ps",               PRN_PS,  CM_INV,
7032 #endif /* OS2 */
7033     "/separator",        PRN_SEP, CM_ARG|CM_INV,
7034 #ifdef BPRINT
7035     "/speed",            PRN_SPD, CM_ARG,
7036 #endif /* BPRINT */
7037     "/timeout",          PRN_TMO, CM_ARG,
7038     "/terminator",       PRN_TRM, CM_ARG|CM_INV,
7039 #ifdef OS2
7040 #ifdef NT
7041     "/w",                PRN_WIN, CM_ARG|CM_ABR|CM_INV,
7042     "/wi",               PRN_WIN, CM_ARG|CM_ABR|CM_INV,
7043 #endif /* NT */
7044     "/width",            PRN_WID, CM_ARG,
7045 #endif /* OS2 */
7046 #ifdef NT
7047     "/windows-queue",    PRN_WIN, CM_ARG,
7048 #endif /* NT */
7049     "",                 0,      0
7050 };
7051 int nprnswi =  (sizeof(prntab) / sizeof(struct keytab)) - 1;
7052 #endif /* PRINTSWI */
7053
7054 static int
7055 setprinter(xx) int xx; {
7056     int x, y;
7057     char * s;
7058     char * defname = NULL;
7059 #ifdef OS2
7060     extern int prncs;
7061 #endif /* OS2 */
7062
7063 #ifdef BPRINT
7064     char portbuf[64];
7065     long portspeed = 0L;
7066     int portparity = 0;
7067     int portflow = 0;
7068 #endif /* BPRINT */
7069
7070 #ifdef PRINTSWI
7071     int c, i, n, wild, confirmed = 0;   /* Workers */
7072     int getval = 0;                     /* Whether to get switch value */
7073     struct stringint pv[PRN_MAX+1];    /* Temporary array for switch values */
7074     struct FDB sw, of, cm;              /* FDBs for each parse function */
7075     int haveque = 0;
7076     int typeset = 0;
7077 #endif /* PRINTSWI */
7078
7079 #ifdef NT
7080     struct keytab * printtab = NULL, * _printtab = NULL;
7081     int nprint = 0, printdef=0;
7082 #endif /* NT */
7083
7084 #ifdef OS2
7085     defname = "PRN";                    /* default */
7086 #else
7087 #ifdef VMS
7088     defname = "LPT:";
7089 #else
7090 #ifdef UNIX
7091     defname = "|lpr";
7092 #endif /* UNIX */
7093 #endif /* VMS */
7094 #endif /* OS2 */
7095
7096 #ifdef PRINTSWI
7097 #ifdef NT
7098     haveque = Win32EnumPrt(&printtab,&_printtab,&nprint,&printdef);
7099     haveque = haveque && nprint;
7100 #endif /* NT */
7101
7102     for (i = 0; i <= PRN_MAX; i++) {    /* Initialize switch values */
7103         pv[i].sval = NULL;              /* to null pointers */
7104         pv[i].ival = -1;                /* and -1 int values */
7105         pv[i].wval = (CK_OFF_T)-1;      /* and -1 wide values */
7106     }
7107     if (xx == XYBDCP) {                 /* SET BPRINTER == /BIDIRECTIONAL */
7108         pv[PRN_BID].ival = 1;
7109         pv[PRN_OUT].ival = 0;
7110     }
7111
7112     /* Initialize defaults based upon current printer settings */
7113     if (printername) {
7114         defname = printername;
7115         switch (printertype) {
7116           case PRT_WIN: pv[PRN_WIN].ival = 1; break;
7117           case PRT_DOS: pv[PRN_DOS].ival = 1; break;
7118           case PRT_PIP: pv[PRN_PIP].ival = 1; break;
7119           case PRT_FIL: pv[PRN_FIL].ival = 1; break;
7120           case PRT_NON: pv[PRN_NON].ival = 1; break;
7121         }
7122     }
7123 #ifdef BPRINT
7124     /* only set the BIDI flag if we are bidi */
7125     if (printbidi)
7126         pv[PRN_BID].ival = 1;
7127
7128     /* serial port parameters may be set for non-bidi devices */
7129     pv[PRN_SPD].ival = pportspeed / 10L;
7130     pv[PRN_PAR].ival = pportparity;
7131     pv[PRN_FLO].ival = pportflow;
7132 #endif /* BPRINT */
7133     if (printtimo)
7134         pv[PRN_TMO].ival = printtimo;
7135     if (printterm) {
7136         pv[PRN_TRM].ival = 1;
7137         makestr(&pv[PRN_TRM].sval,printterm);
7138     }
7139     if (printsep) {
7140         pv[PRN_SEP].ival = 1;
7141         makestr(&pv[PRN_SEP].sval,printsep);
7142     }
7143     if (txt2ps) {
7144         pv[PRN_PS].ival = 1;
7145         pv[PRN_WID].ival = ps_width;
7146         pv[PRN_LEN].ival = ps_length;
7147     } else {
7148         pv[PRN_RAW].ival = 1;
7149     }
7150
7151     /* Set up chained parse functions... */
7152
7153     cmfdbi(&sw,                         /* First FDB - command switches */
7154            _CMKEY,                      /* fcode */
7155            "Switch",                    /* hlpmsg */
7156            "",                          /* default */
7157            "",                          /* addtl string data */
7158            nprnswi,                     /* addtl numeric data 1: tbl size */
7159            4,                           /* addtl numeric data 2: 4 = cmswi */
7160            xxstring,                    /* Processing function */
7161            prntab,                      /* Keyword table */
7162            &cm                          /* Pointer to next FDB */
7163            );
7164     cmfdbi(&cm,                         /* Second fdb for confirmation */
7165            _CMCFM,                      /* fcode */
7166            "",                          /* hlpmsg */
7167            "",                          /* default */
7168            "",                          /* addtl string data */
7169            0,                           /* addtl numeric data 1 */
7170            0,                           /* addtl numeric data 2 */
7171            NULL,
7172            NULL,
7173            &of
7174            );
7175     cmfdbi(&of,                         /* Third FDB for printer name */
7176            _CMOFI,                      /* fcode */
7177            "Printer or file name",      /* hlpmsg */
7178            defname,                     /* default */
7179            "",                          /* addtl string data */
7180            0,                           /* addtl numeric data 1: tbl size */
7181            0,                           /* addtl numeric data 2: 4 = cmswi */
7182            xxstring,                    /* Processing function */
7183            NULL,                        /* Nothing */
7184            NULL
7185            );
7186
7187     while (1) {                         /* Parse 0 or more switches */
7188         x = cmfdb(&sw);                 /* Parse switch or other thing */
7189         debug(F101,"setprinter cmfdb","",x);
7190         if (x < 0)                      /* Error */
7191           goto xsetprn;                 /* or reparse needed */
7192         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
7193           break;
7194         if (cmresult.fdbaddr != &sw)    /* Advanced usage :-) */
7195           break;
7196         c = cmgbrk();                   /* Get break character */
7197         getval = (c == ':' || c == '='); /* to see how they ended the switch */
7198         n = cmresult.nresult;           /* Numeric result = switch value */
7199         debug(F101,"setprinter switch","",n);
7200
7201         switch (n) {                    /* Process the switch */
7202           case PRN_PS:                  /* Text to Postscript */
7203             pv[PRN_PS].ival = 1;
7204             pv[PRN_BID].ival = 0;
7205             pv[PRN_OUT].ival = 1;
7206             pv[PRN_RAW].ival = 0;
7207             break;
7208
7209           case PRN_RAW:                 /* Non-Postscript */
7210             pv[PRN_PS].ival = 0;
7211             pv[PRN_RAW].ival = 1;
7212             break;
7213
7214           case PRN_BID:                 /* Bidirectional */
7215             pv[PRN_BID].ival = 1;
7216             pv[PRN_OUT].ival = 0;
7217             pv[PRN_PS].ival = 0;
7218             pv[PRN_RAW].ival = 1;
7219             break;
7220
7221           case PRN_OUT:                 /* Output-only */
7222             pv[PRN_OUT].ival = 1;
7223             pv[PRN_BID].ival = 0;
7224             pv[PRN_PS].ival = 0;
7225             pv[PRN_RAW].ival = 1;
7226             break;
7227
7228           case PRN_NON:                 /* NONE */
7229             typeset++;
7230             pv[n].ival = 1;
7231             pv[PRN_SPD].ival = 0;
7232             pv[PRN_PAR].ival = 0;
7233             pv[PRN_FLO].ival = FLO_KEEP;
7234             break;
7235
7236 #ifdef UNIX
7237           case PRN_WIN:
7238 #endif /* UNIX */
7239           case PRN_DOS:                 /* DOS printer name */
7240           case PRN_FIL:                 /* Or filename */
7241           case PRN_PIP:
7242             typeset++;
7243             if (pv[n].sval) free(pv[n].sval);
7244             pv[n].sval = NULL;
7245             pv[PRN_NON].ival = 0;       /* Zero any previous selections */
7246             pv[PRN_WIN].ival = 0;
7247             pv[PRN_DOS].ival = 0;
7248             pv[PRN_FIL].ival = 0;
7249             pv[PRN_PIP].ival = 0;
7250             pv[n].ival = 1;             /* Flag this one */
7251             if (!getval) break;         /* No value wanted */
7252
7253             if (n == PRN_FIL) {         /* File, check accessibility */
7254                 int wild = 0;
7255                 if ((x = cmiofi("Filename","kermit.prn",&s,&wild,xxstring))< 0)
7256                   if (x == -9) {
7257                       if (zchko(s) < 0) {
7258                           printf("Can't create \"%s\"\n",s);
7259                           return(x);
7260                       }
7261                   } else goto xsetprn;
7262                 if (iswild(s)) {
7263                     printf("?A single file please\n");
7264                     return(-9);
7265                 }
7266                 pv[PRN_SPD].ival = 0;
7267                 pv[PRN_PAR].ival = 0;
7268                 pv[PRN_FLO].ival = FLO_KEEP;
7269             } else if ((x = cmfld(n == PRN_DOS ? /* Value wanted - parse it */
7270                            "DOS printer device name" : /* Help message */
7271                            (n == PRN_PIP ?
7272                            "Program name" :
7273                            "Filename"),
7274                            n == PRN_DOS ?
7275                            "PRN" :      /* Default */
7276                            "",
7277                            &s,
7278                            xxstring
7279                            )) < 0)
7280               goto xsetprn;
7281             s = brstrip(s);             /* Strip enclosing braces */
7282             while (*s == SP)            /* Strip leading blanks */
7283               s++;
7284             if (n == PRN_PIP) {         /* If /PIPE: */
7285                 if (*s == '|') {        /* strip any extraneous pipe sign */
7286                     s++;
7287                     while (*s == SP)
7288                       s++;
7289                 }
7290                 pv[PRN_SPD].ival = 0;
7291                 pv[PRN_PAR].ival = 0;
7292                 pv[PRN_FLO].ival = FLO_KEEP;
7293             }
7294             if ((y = strlen(s)) > 0)    /* Anything left? */
7295               if (pv[n].sval = (char *) malloc(y+1)) /* Yes, keep it */
7296                 strcpy(pv[n].sval,s);   /* safe */
7297             break;
7298 #ifdef NT
7299           case PRN_WIN:                 /* Windows queue name */
7300             typeset++;
7301             if (pv[n].sval) free(pv[n].sval);
7302             pv[n].sval = NULL;
7303             pv[PRN_NON].ival = 0;
7304             pv[PRN_DOS].ival = 0;
7305             pv[PRN_FIL].ival = 0;
7306             pv[n].ival = 1;
7307             pv[PRN_SPD].ival = 0;
7308             pv[PRN_PAR].ival = 0;
7309             pv[PRN_FLO].ival = FLO_KEEP;
7310
7311             if (!getval || !haveque)
7312               break;
7313             if ((x = cmkey(_printtab,nprint,"Print queue name",
7314                            _printtab[printdef].kwd,xxstring)) < 0) {
7315                 if (x != -2)
7316                   goto xsetprn;
7317
7318                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7319                 s = atmbuf;
7320                 if ((y = strlen(s)) > 0)
7321                   if (pv[n].sval = (char *)malloc(y+1))
7322                     strcpy(pv[n].sval,s); /* safe */
7323             } else {
7324                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7325                 for (i = 0; i < nprint; i++) {
7326                     if (x == printtab[i].kwval) {
7327                         s = printtab[i].kwd;
7328                         break;
7329                     }
7330                 }
7331                 if ((y = strlen(s)) > 0)
7332                   if (pv[n].sval = (char *)malloc(y+1))
7333                     strcpy(pv[n].sval,s); /* safe */
7334             }
7335             break;
7336 #endif /* NT */
7337
7338           case PRN_SEP:                 /* /JOB-HEADER (separator) */
7339             if (pv[n].sval) free(pv[n].sval);
7340             pv[n].sval = NULL;
7341             pv[n].ival = 1;
7342             if (!getval) break;
7343             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0)
7344               goto xsetprn;
7345             if (y) {
7346                 printf("?Wildcards not allowed\n");
7347                 x = -9;
7348                 goto xsetprn;
7349             }
7350             if ((y = strlen(s)) > 0)
7351               if (pv[n].sval = (char *) malloc(y+1))
7352                 strcpy(pv[n].sval,s);   /* safe */
7353             break;
7354
7355           case PRN_TMO:                 /* /TIMEOUT:number */
7356             pv[n].ival = 0;
7357             if (!getval) break;
7358             if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
7359               goto xsetprn;
7360             if (y > 999) {
7361                 printf("?Sorry - 999 is the maximum\n");
7362                 x = -9;
7363                 goto xsetprn;
7364             } else
7365               pv[n].ival = y;
7366             break;
7367
7368           case PRN_TRM:                 /* /END-OF-JOB:string */
7369             if (pv[n].sval) free(pv[n].sval);
7370             pv[n].sval = NULL;
7371             pv[n].ival = 1;
7372             if (!getval) break;
7373             if ((x = cmfld("String (enclose in braces if it contains spaces)",
7374                            "",&s,xxstring)) < 0)
7375               goto xsetprn;
7376             s = brstrip(s);
7377             if ((y = strlen(s)) > 0)
7378               if (pv[n].sval = (char *) malloc(y+1))
7379                 strcpy(pv[n].sval,s);   /* safe */
7380             break;
7381
7382 #ifdef BPRINT
7383           case PRN_FLO:
7384             if (!getval) break;
7385             if ((x = cmkey(flotab,nflo,
7386                               "Serial printer-port flow control",
7387                               "rts/cts",xxstring)) < 0)
7388               goto xsetprn;
7389             pv[n].ival = x;
7390             break;
7391
7392 #ifndef NOLOCAL
7393           case PRN_SPD:
7394             if (!getval) break;
7395
7396             /* TN_COMPORT here too? */
7397
7398             if ((x = cmkey(spdtab,      /* Speed (no default) */
7399                            nspd,
7400                            "Serial printer-port interface speed",
7401                            "9600",
7402                            xxstring)
7403                  ) < 0)
7404               goto xsetprn;
7405             pv[n].ival = x;
7406             break;
7407 #endif /* NOLOCAL */
7408
7409           case PRN_PAR:
7410             pv[n].ival = 0;
7411             if (!getval) break;
7412             if ((x = cmkey(partbl,npar,"Serial printer-port parity",
7413                            "none",xxstring)) < 0)
7414               goto xsetprn;
7415             pv[n].ival = x;
7416             break;
7417 #endif /* BPRINT */
7418
7419 #ifdef OS2
7420           case PRN_LEN:
7421             if (!getval) break;
7422             if ((x = cmnum("PS page length", "66",10,&y,xxstring)) < 0)
7423               goto xsetprn;
7424             pv[n].ival = y;
7425             break;
7426
7427           case PRN_WID:
7428             if (!getval) break;
7429             if ((x = cmnum("PS page width", "80",10,&y,xxstring)) < 0)
7430               goto xsetprn;
7431             pv[n].ival = y;
7432             break;
7433
7434           case PRN_CS:
7435               pv[n].ival = 0;
7436               if (!getval) break;
7437               if ((y = cmkey(
7438 #ifdef CKOUNI
7439                        txrtab,ntxrtab,
7440 #else /* CKOUNI */
7441                        ttcstab,ntermc,
7442 #endif /* CKOUNI */
7443                        "auto-print/printscreen character-set",
7444                        "cp437",xxstring)) < 0)
7445                   goto xsetprn;
7446               pv[n].ival = y;
7447               break;
7448 #endif /* OS2 */
7449
7450           default:
7451             printf("?Unexpected switch value - %d\n",cmresult.nresult);
7452             x = -9;
7453             goto xsetprn;
7454         }
7455     }
7456     line[0] = NUL;                      /* Initialize printer name value */
7457     switch (cmresult.fcode) {           /* How did we get here? */
7458       case _CMOFI:                      /* They typed a filename */
7459         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
7460         wild = cmresult.nresult;        /* Wild flag */
7461         if (!typeset) {                 /* A printer name without a type */
7462             pv[PRN_NON].ival = 0;       /* is supposed to be treated as  */
7463             pv[PRN_WIN].ival = 0;       /* a DOS or Pipe printer.  We    */
7464             pv[PRN_FIL].ival = 0;       /* clear all the flags and let   */
7465             pv[PRN_PIP].ival = 0;       /* the code below dope out the   */
7466             pv[PRN_DOS].ival = 0;       /* type.                         */
7467         }
7468 #ifdef NT
7469         else if (pv[PRN_WIN].ival && lookup(_printtab,line,nprint,&y)) {
7470             /* invalid Window Queue name */
7471             printf("?invalid Windows Printer Queue name: \"%s\"\r\n",line);
7472             x = -9;
7473             goto xsetprn;
7474         }
7475 #endif /* NT */
7476         if ((x = cmcfm()) < 0)          /* Confirm the command */
7477           goto xsetprn;
7478         break;
7479       case _CMCFM:                      /* They entered the command */
7480         if (pv[PRN_DOS].ival > 0)
7481           ckstrncpy(line,pv[PRN_DOS].sval ? pv[PRN_DOS].sval : "",LINBUFSIZ);
7482         else if (pv[PRN_WIN].ival > 0)
7483           ckstrncpy(line,pv[PRN_WIN].sval ? pv[PRN_WIN].sval : "",LINBUFSIZ);
7484         else if (pv[PRN_FIL].ival > 0)
7485           ckstrncpy(line,pv[PRN_FIL].sval ? pv[PRN_FIL].sval : "",LINBUFSIZ);
7486         else if (pv[PRN_PIP].ival > 0)
7487           ckstrncpy(line,pv[PRN_PIP].sval ? pv[PRN_PIP].sval : "",LINBUFSIZ);
7488         break;
7489       default:                          /* By mistake */
7490         printf("?Unexpected function code: %d\n",cmresult.fcode);
7491         x = -9;
7492         goto xsetprn;
7493     }
7494
7495 #else  /* No PRINTSWI */
7496
7497     if ((x = cmofi("Printer or file name",defname,&s,xxstring)) < 0)
7498       return(x);
7499     if (x > 1) {
7500         printf("?Directory names not allowed\n");
7501         return(-9);
7502     }
7503     while (*s == SP || *s == HT) s++;   /* Trim leading whitespace */
7504     ckstrncpy(line,s,LINBUFSIZ);        /* Make a temporary safe copy */
7505     if ((x = cmcfm()) < 0) return(x);   /* Confirm the command */
7506 #endif /* PRINTSWI */
7507
7508 #ifdef IKSD
7509     if (inserver && (isguest
7510 #ifndef NOSERVER
7511                      || !ENABLED(en_pri)
7512 #endif /* NOSERVER */
7513                      )) {
7514         printf("Sorry, printing disabled\r\n");
7515         return(success = 0);
7516     }
7517 #endif /* ISKD */
7518
7519 #ifdef PRINTSWI
7520 #ifdef BPRINT
7521     if (printbidi) {                    /* If bidi printing active */
7522 #ifndef UNIX
7523         bprtstop();                     /* Stop it before proceeding */
7524 #endif /* UNIX */
7525         printbidi = 0;
7526     }
7527     if (pv[PRN_SPD].ival > 0) {
7528         portspeed = (long) pv[PRN_SPD].ival * 10L;
7529         if (portspeed == 70L) portspeed = 75L;
7530     }
7531     if (pv[PRN_PAR].ival > 0)
7532         portparity = pv[PRN_PAR].ival;
7533     if (pv[PRN_FLO].ival > 0)
7534         portflow = pv[PRN_FLO].ival;
7535 #endif /* BPRINT */
7536 #endif /* PRINTSWI */
7537
7538     s = line;                           /* Printer name, if given */
7539
7540 #ifdef OS2ORUNIX
7541 #ifdef PRINTSWI
7542     if (pv[PRN_PIP].ival > 0) {         /* /PIPE was given? */
7543         printpipe = 1;
7544         noprinter = 0;
7545         if (*s ==  '|') {               /* It might still have a pipe sign */
7546             s++;                        /* if name give later */
7547             while (*s == SP)            /* so remove it and spaces */
7548               s++;
7549         }
7550     } else
7551 #endif /* PRINTSWI */
7552       if (*s == '|') {                  /* Or pipe implied by name? */
7553           s++;                          /* Point past pipe sign */
7554           while (*s == SP)              /* Gobble whitespace */
7555             s++;
7556           if (*s) {
7557               printpipe = 1;
7558               noprinter = 0;
7559           }
7560       } else {
7561           printpipe = 0;
7562       }
7563
7564 #ifdef PRINTSWI
7565 #ifdef BPRINT
7566     if (printpipe && pv[PRN_BID].ival > 0) {
7567         printf("?Sorry, pipes not allowed for bidirectional printer\n");
7568         return(-9);
7569     }
7570 #endif /* BPRINT */
7571 #endif /* PRINTSWI */
7572 #endif /* OS2ORUNIX */
7573
7574 #ifdef OS2
7575     if ( pv[PRN_CS].ival > 0 ) 
7576         prncs = pv[PRN_CS].ival;
7577
7578     if ( pv[PRN_PS].ival > 0 ) {
7579         txt2ps = 1;
7580         ps_width = pv[PRN_WID].ival <= 0 ? 80 : pv[PRN_WID].ival;
7581         ps_length = pv[PRN_LEN].ival <= 0 ? 66 : pv[PRN_LEN].ival;
7582     }
7583 #endif /* OS2 */
7584
7585     y = strlen(s);                      /* Length of name of new print file */
7586     if (y > 0
7587 #ifdef OS2
7588         && ((y != 3) || (ckstrcmp(s,"PRN",3,0) != 0))
7589 #endif /* OS2 */
7590         ) {
7591         if (printername) {              /* Had a print file before? */
7592             free(printername);          /* Remove its name */
7593             printername = NULL;
7594         }
7595         printername = (char *) malloc(y + 1); /* Allocate space for it */
7596         if (!printername) {
7597             printf("?Memory allocation failure\n");
7598             return(-9);
7599         }
7600         strcpy(printername,s);          /* (safe) Copy new name to new space */
7601         debug(F110,"printername",printername,0);
7602     }
7603
7604 #ifdef PRINTSWI
7605     /* Set printer type from switches that were given explicitly */
7606
7607     if (pv[PRN_NON].ival > 0) {         /* No printer */
7608         printertype = PRT_NON;
7609         noprinter = 1;
7610         printpipe = 0;
7611     } else if (pv[PRN_FIL].ival > 0) {  /* File */
7612         printertype = PRT_FIL;
7613         noprinter = 0;
7614         printpipe = 0;
7615     } else if (pv[PRN_PIP].ival > 0) {  /* Pipe */
7616         printertype = PRT_PIP;
7617         noprinter = 0;
7618         printpipe = 1;
7619     } else if (pv[PRN_WIN].ival > 0) {  /* Windows print queue */
7620         printertype = PRT_WIN;
7621         noprinter = 0;
7622         printpipe = 0;
7623     } else if (pv[PRN_DOS].ival > 0) {  /* DOS device */
7624         printertype = PRT_DOS;
7625         noprinter = 0;
7626         printpipe = 0;
7627     } else if (line[0]) {               /* Name given without switches */
7628         noprinter = 0;
7629         printertype = printpipe ? PRT_PIP : PRT_DOS;
7630 #ifdef NT
7631         /* was the command SET PRINTER windows-queue ? */
7632         y = lookup(_printtab,line,nprint,&x);
7633         if (y >= 0) {
7634             printertype = PRT_WIN;
7635             if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7636             if (printername) {          /* Had a print file before? */
7637                 free(printername);      /* Remove its name */
7638                 printername = NULL;
7639             }
7640             pv[PRN_WIN].sval = NULL;
7641             pv[PRN_WIN].ival = 1;
7642             s = printtab[x].kwd;        /* Get full new name */
7643             if ((y = strlen(s)) > 0) {
7644                 makestr(&pv[PRN_WIN].sval,s);
7645                 makestr(&printername,s);
7646                 if (!printername) {
7647                     printf("?Memory allocation failure\n");
7648                     return(-9);
7649                 }
7650                 debug(F110,"printername",printername,0);
7651             }
7652         } else if ( y == -2 ) {
7653             /* Ambiguous Print Queue Name */
7654             printf("?Ambiguous printer name provided.\n");
7655             return(-9);
7656         }
7657 #endif /* NT */
7658     }
7659
7660 #ifdef BPRINT
7661     /* Port parameters may be set for non-bidi mode */
7662
7663     pportspeed = portspeed;             /* Set parameters */
7664     pportparity = portparity;
7665     pportflow = portflow;
7666
7667     if (pv[PRN_BID].ival > 0) {         /* Bidirectional */
7668 #ifdef UNIX
7669         printbidi = 1;                  /* (just to test parsing...) */
7670 #else
7671         printbidi = bprtstart();        /* Start bidirectional printer */
7672 #endif /* UNIX */
7673         return(success = printbidi);
7674     } else
7675       printbidi = 0;                    /* Not BPRINTER, unset flag */
7676 #endif /* BPRINT */
7677
7678     if (pv[PRN_TMO].ival > -1) {        /* Take care of timeout */
7679         printtimo = pv[PRN_TMO].ival;
7680     }
7681     if (pv[PRN_TRM].ival > 0) {         /* Termination string */
7682         if (printterm) {
7683             free(printterm);
7684             printterm = NULL;
7685         }
7686         if (pv[PRN_TRM].sval)
7687           makestr(&printterm,pv[PRN_TRM].sval);
7688     }
7689     if (pv[PRN_SEP].ival > 0) {         /* and separator file */
7690         if (printsep) {
7691             free(printsep);
7692             printsep = NULL;
7693         }
7694         if (pv[PRN_SEP].sval)
7695           makestr(&printsep,pv[PRN_SEP].sval);
7696     }
7697 #endif /* PRINTSWI */
7698
7699 #ifdef UNIXOROSK
7700     if (!printpipe
7701 #ifdef PRINTSWI
7702         && !noprinter
7703 #endif /* PRINTSWI */
7704         ) {                             /* File - check access */
7705         if (zchko(s) < 0) {
7706             printf("?Access denied - %s\n",s);
7707             x = -9;
7708             goto xsetprn;
7709         }
7710     }
7711 #endif /* UNIXOROSK */
7712
7713     x = 1;                              /* Return code */
7714
7715   xsetprn:                              /* Common exit */
7716 #ifdef PRINTSWI
7717     for (i = 0; i <= PRN_MAX; i++) {    /* Free malloc'd memory */
7718         if (pv[i].sval)
7719           free(pv[i].sval);
7720     }
7721 #endif /* PRINTSWI */
7722     success = (x > 0) ? 1 : 0;
7723     return(x);
7724 }
7725
7726 #ifdef ANYSSH
7727 /* The SET SSH command */
7728
7729 #define SSH_CMD  1                      /* SET SSH COMMAND */
7730
7731 #ifdef SSHBUILTIN                       /* Built-in SET SSH options */
7732 #define SSH_ADD  2                      /* Add */
7733 #define SSH_AFW  3                      /* Agent-forwarding */
7734 #define SSH_CHI  4                      /* Check Host IP */
7735 #define SSH_XFW  5                      /* X11-forwarding */
7736 #define SSH_DYF  6                      /* Dynamic forwarding */
7737 #define SSH_GWP  7                      /* Gatewa portgs */
7738 #define SSH_GSS  8                      /* GSSAPI */
7739 #define SSH_KBD  9                      /* KBD Interactive Devices */
7740 #define SSH_K4  10                      /* Kerberos 4 */
7741 #define SSH_K5  11                      /* Kerberos 5 */
7742 #define SSH_SHK 12                      /* Strict Host Key Check */
7743 #define SSH_V1  13                      /* SSH V1 */
7744 #define SSH_V2  14                      /* SSH V2 */
7745 #define SSH_PRP 15                      /* Privd port */
7746 #define SSH_CMP 16                      /* Compression */
7747 #define SSH_XAL 17                      /* X Auth Location */
7748 #define SSH_SHH 18                      /* Quiet */
7749 #define SSH_VER 19                      /* Version */
7750 #define SSH_VRB 20                      /* Verbosity level */
7751 #define SSH_IDF 21                      /* Identity File */
7752 #define SSH_CFG 22                      /* Use OpenSSH Config */
7753 #define SSH_HBT 23                      /* Heartbeat Interval */
7754 #endif /* SSHBUILTIN */
7755
7756 static struct keytab sshtab[] = {       /* SET SSH command table */
7757 #ifdef SSHBUILTIN
7758     { "agent-forwarding",        SSH_AFW,  0 },
7759     { "check-host-ip",           SSH_CHI,  0 },
7760     { "compression",             SSH_CMP,  0 },
7761     { "dynamic-forwarding",      SSH_DYF,  0 },
7762     { "gateway-ports",           SSH_GWP,  0 },
7763     { "gssapi",                  SSH_GSS,  0 },
7764     { "heartbeat-interval",      SSH_HBT,  0 },
7765     { "identity-file",           SSH_IDF,  0 },
7766 #ifdef COMMENT
7767     { "kbd-interactive-devices", SSH_KBD,  0 },
7768 #endif /* COMMENT */
7769     { "k4",                      SSH_K4, CM_INV },
7770     { "k5",                      SSH_K5, CM_INV },
7771     { "kerberos4",               SSH_K4,   0 },
7772     { "kerberos5",               SSH_K5,   0 },
7773     { "krb4",                    SSH_K4, CM_INV },
7774     { "krb5",                    SSH_K5, CM_INV },
7775     { "privileged-port",         SSH_PRP,  0 },
7776     { "quiet",                   SSH_SHH,  0 },
7777     { "strict-host-key-check",   SSH_SHK,  0 },
7778     { "use-openssh-config",      SSH_CFG,  0 },
7779     { "v1",                      SSH_V1,   0 },
7780     { "v2",                      SSH_V2,   0 },
7781     { "verbose",                 SSH_VRB,  0 },
7782     { "version",                 SSH_VER,  0 },
7783     { "x11-forwarding",          SSH_XFW,  0 },
7784     { "xauth-location",          SSH_XAL,  0 },
7785 #else
7786 #ifdef SSHCMD
7787     { "command",                 SSH_CMD,  0 },
7788 #endif /* SSHCMD */
7789 #endif /* SSHBUILTIN */
7790     { "", 0, 0 }
7791 };
7792 static int nsshtab = (sizeof(sshtab) / sizeof(struct keytab)) - 1;
7793
7794 #ifdef SSHBUILTIN
7795 static struct keytab sshver[] = {       /* SET SSH VERSION command table */
7796     { "1",          1,  0 },
7797     { "2",          2,  0 },
7798     { "automatic",  0,  0 }
7799 };
7800
7801 #define SSHA_CRS   1
7802 #define SSHA_DSA   2
7803 #define SSHA_GSS   3
7804 #define SSHA_HOS   4
7805 #define SSHA_KBD   5
7806 #define SSHA_K4    6
7807 #define SSHA_K5    7
7808 #define SSHA_PSW   8
7809 #define SSHA_PK    9
7810 #define SSHA_SKE  10
7811 #define SSHA_TIS  11
7812 #define SSHA_EXT  12
7813 #define SSHA_SRP  13
7814
7815 static struct keytab ssh2aut[] = {      /* SET SSH V2 AUTH command table */
7816     { "external-keyx",      SSHA_EXT, 0 },
7817     { "gssapi",             SSHA_GSS, 0 },
7818     { "hostbased",          SSHA_HOS, 0 },
7819     { "keyboard-interactive",  SSHA_KBD, 0 },
7820     { "password",           SSHA_PSW, 0 },
7821     { "publickey",          SSHA_PK,  0 },
7822     { "srp-gex-sha1",       SSHA_SRP, 0 },
7823     { "", 0, 0 }
7824 };
7825 static int nssh2aut = (sizeof(ssh2aut) / sizeof(struct keytab)) - 1;
7826
7827 #define SSHF_LCL   1
7828 #define SSHF_RMT   2
7829
7830 static struct keytab addfwd[] = {       /* SET SSH ADD command table */
7831     { "local-port-forward",  SSHF_LCL, 0 },
7832     { "remote-port-forward", SSHF_RMT, 0 },
7833     { "", 0, 0 }
7834 };
7835 static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
7836
7837 #define SSH1_CIF   1
7838 #define SSH1_GNH   2
7839 #define SSH1_UNH   3
7840 #define SSH1_K54   4
7841
7842 #define SSH2_CIF   1
7843 #define SSH2_GNH   2
7844 #define SSH2_UNH   3
7845 #define SSH2_ARK   4
7846 #define SSH2_HKA   5
7847 #define SSH2_MAC   6
7848 #define SSH2_AUT   7
7849
7850 static struct keytab sshv1tab[] = {     /* SET SSH V1 command table */
7851     { "cipher",                  SSH1_CIF, 0 },
7852     { "global-known-hosts-file", SSH1_GNH, 0 },
7853     { "k5-reuse-k4-messages",    SSH1_K54, CM_INV },
7854     { "user-known-hosts-file",   SSH1_UNH, 0 },
7855     { "", 0, 0 }
7856 };
7857 static int nsshv1tab = (sizeof(sshv1tab) / sizeof(struct keytab)) - 1;
7858
7859 static struct keytab sshv2tab[] = {     /* SET SSH V2 command table */
7860     { "authentication",          SSH2_AUT, 0 },
7861     { "auto-rekey",              SSH2_ARK, 0 },
7862     { "ciphers",                 SSH2_CIF, 0 },
7863     { "global-known-hosts-file", SSH2_GNH, 0 },
7864     { "hostkey-algorithms",      SSH2_HKA, 0 },
7865     { "macs",                    SSH2_MAC, 0 },
7866     { "user-known-hosts-file",   SSH2_UNH, 0 },
7867     { "", 0, 0 }
7868 };
7869 static int nsshv2tab = (sizeof(sshv2tab) / sizeof(struct keytab)) - 1;
7870
7871 #define SSHC_3DES 1                     /* 3DES */
7872 #define SSHC_3CBC 2                     /* 3DES-CBC */
7873 #define SSHC_A128 3                     /* AES128-CBC */
7874 #define SSHC_A192 4                     /* AES192-CBC */
7875 #define SSHC_A256 5                     /* AES256-CBC */
7876 #define SSHC_ARC4 6                     /* ARCFOUR */
7877 #define SSHC_FISH 7                     /* BLOWFISH */
7878 #define SSHC_BCBC 9                     /* BLOWFISH-CBC */
7879 #define SSHC_C128 8                     /* CAST128-CBC */
7880 #define SSHC_1DES 10                    /* DES */
7881
7882 static struct keytab ssh1ciphers[] = {
7883     { "3des",         SSHC_3DES, 0 },
7884     { "blowfish",     SSHC_FISH, 0 },
7885     { "des",          SSHC_1DES, 0 },
7886     { "", 0, 0 }
7887 };
7888 static int nssh1ciphers = (sizeof(ssh1ciphers) / sizeof(struct keytab)) - 1;
7889
7890 static struct keytab ssh2ciphers[] = {  /* SET SSH V2 CIPHERS command table */
7891     { "3des-cbc",        SSHC_3DES, 0 },
7892     { "aes128-cbc",      SSHC_A128, 0 },
7893     { "aes192-cbc",      SSHC_A192, 0 },
7894     { "aes256-cbc",      SSHC_A256, 0 },
7895     { "arcfour",         SSHC_ARC4, 0 },
7896     { "blowfish-cbc",    SSHC_FISH, 0 },
7897     { "cast128-cbc",     SSHC_C128, 0 },
7898     { "rijndael128-cbc", SSHC_A128, 0 },
7899     { "rijndael192-cbc", SSHC_A192, 0 },
7900     { "rijndael256-cbc", SSHC_A256, 0 },
7901     { "", 0, 0 }
7902 };
7903 static int nssh2ciphers = (sizeof(ssh2ciphers) / sizeof(struct keytab)) - 1;
7904
7905 #define SSHM_SHA        1               /* HMAC-SHA1 */
7906 #define SSHM_SHA_96     2               /* HMAC-SHA1-96 */
7907 #define SSHM_MD5        3               /* HMAC-MD5 */
7908 #define SSHM_MD5_96     4               /* HMAC-MD5-96 */
7909 #define SSHM_RIPE       5               /* HMAC-RIPEMD160 */
7910
7911 static struct keytab ssh2macs[] = {     /* SET SSH V2 MACS command table */
7912     { "hmac-md5",       SSHM_MD5,    0 },
7913     { "hmac-md5-96",    SSHM_MD5_96, 0 },
7914     { "hmac-ripemd160", SSHM_RIPE,   0 },
7915     { "hmac-sha1",      SSHM_SHA,    0 },
7916     { "hmac-sha1-96",   SSHM_SHA_96, 0 },
7917     { "", 0, 0 }
7918 };
7919 static int nssh2macs = (sizeof(ssh2macs) / sizeof(struct keytab)) - 1;
7920
7921 static struct keytab tgtpass[] = {
7922     { "tgt-passing", 1, 0, },
7923     { "", 0, 0 }
7924 };
7925 static int ntgtpass = (sizeof(tgtpass) / sizeof(struct keytab)) - 1;
7926
7927 static struct keytab gssapitab[] = {
7928     { "delegate-credentials", 1, 0, },
7929     { "key-exchange",         2, CM_INV, },
7930     { "", 0, 0 }
7931 };
7932 static int ngssapitab = (sizeof(gssapitab) / sizeof(struct keytab)) - 1;
7933
7934 #define HKA_RSA 1
7935 #define HKA_DSS 2
7936
7937 static struct keytab hkatab[] = {
7938     { "ssh-dss", HKA_DSS, 0, },
7939     { "ssh-rsa", HKA_RSA, 0, },
7940     { "", 0, 0 }
7941 };
7942 static int nhkatab = (sizeof(hkatab) / sizeof(struct keytab)) - 1;
7943
7944 int                                     /* SET SSH variables */
7945   ssh_afw = 0,                          /* agent forwarding */
7946   ssh_xfw = 0,                          /* x11 forwarding   */
7947   ssh_prp = SET_OFF,                    /* privileged ports */
7948   ssh_cmp = 1,                          /* compression */
7949   ssh_shh = 0,                          /* quiet       */
7950   ssh_ver = 0,                          /* protocol version (auto,1,2) */
7951   ssh_vrb = 2,                          /* Report errors */
7952   ssh_chkip = 0,                        /* SSH Check Host IP flag */
7953   ssh_gwp = 0,                          /* gateway ports */
7954   ssh_dyf = 0,                          /* dynamic forwarding */
7955   ssh_gsd = 0,                          /* gssapi delegate credentials */
7956   ssh_k4tgt = 0,                        /* k4 tgt passing */
7957   ssh_k5tgt = 0,                        /* k5 tgt passing */
7958   ssh_shk = 2,                          /* Strict host key (no, yes, ask) */
7959   ssh2_ark = 1,                         /* Auto re-key */
7960   ssh_cas = 0,                          /* command as subsys */
7961   ssh_cfg = 0,                          /* use OpenSSH config? */
7962   ssh_gkx = 1,                          /* gssapi key exchange */
7963   ssh_k5_is_k4 = 1,                     /* some SSH v1 use same codes */
7964   ssh_hbt = 0,                          /* heartbeat (seconds) */
7965   ssh_dummy = 0;                        /* bottom of list */
7966
7967 char                                    /* The following are to be malloc'd */
7968   * ssh1_cif = NULL,                    /* v1 cipher */
7969   * ssh2_cif = NULL,                    /* v2 cipher list */
7970   * ssh2_mac = NULL,                    /* v2 mac list */
7971   * ssh2_auth = NULL,                   /* v2 authentication list */
7972   * ssh_hst = NULL,                     /* hostname */
7973   * ssh_prt = NULL,                     /* port/service */
7974   * ssh_cmd = NULL,                     /* command to execute */
7975   * ssh_xal = NULL,                     /* xauth-location */
7976   * ssh1_gnh = NULL,                    /* v1 global known hosts file */
7977   * ssh1_unh = NULL,                    /* v1 user known hosts file */
7978   * ssh2_gnh = NULL,                    /* v2 global known hosts file */
7979   * ssh2_unh = NULL,                    /* v2 user known hosts file */
7980   * ssh2_hka = NULL,                    /* Host Key Algorithms */
7981   * xxx_dummy = NULL;
7982
7983 char * ssh_idf[32] = {                  /* Identity file list */
7984   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7985   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7986   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7987   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
7988 };
7989 char * ssh_tmp[32] = {                  /* Temp identity file list */
7990   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7991   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7992   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7993   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
7994 };
7995 int ssh_idf_n = 0;
7996
7997 extern int    ssh_pf_lcl_n,
7998               ssh_pf_rmt_n;
7999 extern struct ssh_pf ssh_pf_lcl[32];    /* Port forwarding structs */
8000 extern struct ssh_pf ssh_pf_rmt[32];    /* (declared in ckuusr.c) */
8001 #endif /* SSHBUILTIN */
8002
8003 #ifdef SFTP_BUILTIN
8004 static struct keytab sftptab[] = {
8005     { "end-of-line",            XY_SFTP_EOL, 0, },
8006     { "remote-character-set",   XY_SFTP_RCS, 0, },
8007     { "", 0, 0 }
8008 };
8009 static int nsftptab = (sizeof(sftptab) / sizeof(struct keytab)) - 1;
8010 #endif /* SFTP_BUILTIN */
8011
8012 VOID
8013 shossh() {
8014 #ifdef SSHBUILTIN
8015     int i, n = 0;                       /* ADD askmore()! */
8016
8017     printf("\nSSH is built in:\n\n");
8018
8019     printf(" ssh host:                        %s\n",showstring(ssh_hst));
8020     printf(" ssh port:                        %s\n",showstring(ssh_prt));
8021     printf(" ssh command:                     %s\n",showstring(ssh_cmd));
8022     printf(" ssh agent-forwarding:            %s\n",showoff(ssh_afw));
8023     printf(" ssh check-host-ip:               %s\n",showoff(ssh_chkip));
8024     printf(" ssh compression:                 %s\n",showoff(ssh_cmp));
8025     printf(" ssh dynamic-forwarding:          %s\n",showoff(ssh_dyf));
8026     if (ssh_pf_lcl[0].p1 && ssh_pf_lcl[0].host && ssh_pf_lcl[0].p2) {
8027       printf(" ssh forward-local-port:          %d %s %d\n",
8028              ssh_pf_lcl[0].p1, ssh_pf_lcl[0].host, ssh_pf_lcl[0].p2);
8029       for ( n=1;n<ssh_pf_lcl_n;n++ )
8030         printf("                       :          %d %s %d\n",
8031                ssh_pf_lcl[n].p1, ssh_pf_lcl[n].host, ssh_pf_lcl[n].p2);
8032     } else
8033       printf(" ssh forward-local-port:         (none)\n");
8034     if (ssh_pf_rmt[0].p1 && ssh_pf_rmt[0].host && ssh_pf_rmt[0].p2) {
8035       printf(" ssh forward-remote-port:         %d %s %d\n",
8036              ssh_pf_rmt[0].p1, ssh_pf_rmt[0].host, ssh_pf_rmt[0].p2);
8037       for ( n=1;n<ssh_pf_rmt_n;n++ )
8038         printf("                        :         %d %s %d\n",
8039                ssh_pf_rmt[n].p1, ssh_pf_rmt[n].host, ssh_pf_rmt[n].p2);
8040     } else
8041       printf(" ssh forward-remote-port:        (none)\n");
8042     printf(" ssh gateway-ports:               %s\n",showoff(ssh_gwp));
8043     printf(" ssh gssapi delegate-credentials: %s\n",showoff(ssh_gsd));
8044     printf(" ssh gssapi key-exchange        : %s\n",showoff(ssh_gkx));
8045     printf(" ssh identity-file:               %d\n",ssh_idf_n);
8046     for (i = 0; i < ssh_idf_n; i++)
8047       printf("  %2d. %s\n",i+1,showstring(ssh_idf[i]));
8048     printf(" ssh heartbeat interval:          %d\n", ssh_hbt);
8049     printf(" ssh k4 tgt-passing:              %s\n",showoff(ssh_k4tgt));
8050     printf(" ssh k5 tgt-passing:              %s\n",showoff(ssh_k5tgt));
8051
8052     printf(" ssh privileged-port:             %s\n",showooa(ssh_prp));
8053     printf(" ssh quiet:                       %s\n",showoff(ssh_shh));
8054     printf(" ssh strict-host-key-check:       %d\n",ssh_shk);
8055     printf(" ssh use-openssh-config:          %s\n",showoff(ssh_cfg));
8056     printf(" ssh verbose:                     %d\n",ssh_vrb);
8057     printf(" ssh version:                     %s\n",
8058            ssh_ver ? ckitoa(ssh_ver) : "automatic"
8059            );
8060     printf(" ssh x11-forwarding:              %s\n",showooa(ssh_xfw));
8061     printf(" ssh xauth-location:              %s\n",showstring(ssh_xal));
8062     printf("\n");
8063     printf(" ssh v1 cipher:                   %s\n",showstring(ssh1_cif));
8064     printf(" ssh v1 global-known-hosts-file:  %s\n",showstring(ssh1_gnh));
8065     printf(" ssh v1 user-known-hosts-file:    %s\n",showstring(ssh1_unh));
8066     printf("\n");
8067     printf(" ssh v2 authentication:           %s\n",showstring(ssh2_auth));
8068     printf(" ssh v2 auto-rekey:               %s\n",showoff(ssh2_ark));
8069     printf(" ssh v2 ciphers:                  %s\n",showstring(ssh2_cif));
8070     printf(" ssh v2 command-as-subsystem:     %s\n",showoff(ssh_cas));
8071     printf(" ssh v2 global-known-hosts-file:  %s\n",showstring(ssh2_gnh));
8072     printf(" ssh v2 hostkey-algorithms:       %s\n",showstring(ssh2_hka));
8073     printf(" ssh v2 mac:                      %s\n",showstring(ssh2_mac));
8074     printf(" ssh v2 user-known-hosts-file:    %s\n",showstring(ssh2_unh));
8075 #else
8076 #ifdef SSHCMD
8077     extern char * sshcmd, * defsshcmd;
8078     char * s;
8079     s = sshcmd ? sshcmd : defsshcmd;
8080     printf("\n SSH is external.\n\n");
8081     printf(" ssh command: %s\n",showstring(s));
8082 #endif /* SSHCMD */
8083 #endif /* SSHBUILTIN */
8084     printf("\n");
8085 }
8086
8087 static int
8088 dosetssh() {
8089 #ifdef SSHCMD
8090     extern char * sshcmd;
8091 #endif /* SSHCMD */
8092 #ifdef SSHBUILTIN
8093 #ifndef SSHTEST
8094     extern int sl_ssh_xfw_saved, sl_ssh_ver_saved;
8095 #endif /* SSHTEST */
8096 #endif /* SSHBUILTIN */
8097     int cx, x, y, z;
8098     char * s;
8099
8100     if ((cx = cmkey(sshtab,nsshtab,"","command", xxstring)) < 0)
8101       return(cx);
8102     switch (cx) {
8103 #ifdef SSHCMD
8104       case SSH_CMD:                     /* Command */
8105         if ((x = cmtxt("Command to start ssh","ssh -e none",
8106                        &s,xxstring)) < 0)
8107           return(x);
8108         makestr(&sshcmd,s);
8109         return(success = 1);
8110 #endif /* SSHCMD */
8111
8112 #ifdef SSHBUILTIN
8113       case SSH_AFW:                     /* Agent-forwarding */
8114         return(success = seton(&ssh_afw));
8115
8116       case SSH_CHI:                     /* Check Host IP */
8117         return(success = seton(&ssh_chkip));
8118         break;
8119
8120       case SSH_CMP:                     /* Compression */
8121         return(success = seton(&ssh_cmp));
8122
8123       case SSH_DYF:                     /* Dynamic Forwarding */
8124         return(success = seton(&ssh_dyf));
8125
8126       case SSH_GWP:                     /* Gateway ports */
8127         return(success = seton(&ssh_gwp));
8128
8129       case SSH_GSS:                     /* GSSAPI */
8130         if ((y = cmkey(gssapitab,ngssapitab,"","", xxstring)) < 0)
8131           return(y);
8132         switch (y) {
8133           case 1:                       /* Delegate credentials */
8134             return(success = seton(&ssh_gsd));
8135           case 2:                       /* key-exchange */
8136             return(success = seton(&ssh_gkx));
8137         }
8138         if ((x = cmcfm()) < 0)
8139           return(x);
8140         return(success = 0);
8141
8142 #ifdef COMMENT
8143       case SSH_KBD:                     /* Kbd Interactive Devices */
8144         if ((x = cmcfm()) < 0)
8145           return(x);
8146         /* TO BE FILLED IN */
8147         return(-2);
8148 #endif /* COMMENT */
8149
8150       case SSH_K4:                      /* Kerberos IV */
8151       case SSH_K5:                      /* Kerberos V */
8152         if ((y = cmkey(tgtpass,1,"","tgt-passing", xxstring)) < 0)
8153           return(y);
8154         switch (y) {
8155           case 1:
8156             return(success = (cx == SSH_K4) ?
8157                    seton(&ssh_k4tgt) : seton(&ssh_k5tgt));
8158         }
8159         if ((x = cmcfm()) < 0)
8160           return(x);
8161         return(success = 0);
8162
8163       case SSH_PRP:                     /* Privd port */
8164         return(success = seton(&ssh_prp));
8165
8166       case SSH_SHH:                     /* Quiet */
8167         return(success = seton(&ssh_shh));
8168
8169       case SSH_SHK:                     /* Strict Host Key Check */
8170         if ((y = cmkey(ooktab,3,"","", xxstring)) < 0)
8171           return(y);
8172         if ((x = cmcfm()) < 0)
8173           return(x);
8174         ssh_shk = y;
8175         return(success = 1);
8176
8177       case SSH_HBT:
8178         x = cmnum("Heartbeat interval, seconds","0",10,&z,xxstring);
8179         if (x < 0) return(x);
8180         if ((x = cmcfm()) < 0) return(x);
8181         ssh_hbt = z;
8182         return(success = 1);
8183
8184       case SSH_V1:                      /* SSH V1 */
8185         if ((y = cmkey(sshv1tab,nsshv1tab,"","", xxstring)) < 0)
8186           return(y);
8187         switch (y) {
8188           case SSH1_K54:
8189             return(success = seton(&ssh_k5_is_k4));
8190           case SSH1_CIF:                /* Not a list */
8191             if ((y = cmkey(ssh1ciphers,nssh1ciphers,"","", xxstring)) < 0)
8192               if (y != -3)
8193                 return(y);
8194             if ((x = cmcfm()) < 0) return(x);
8195             if (y == -3) {
8196                 makestr(&ssh1_cif,NULL);
8197             } else {
8198                 for (x = 0; x < nssh1ciphers; x++)
8199                   if (ssh1ciphers[x].kwval == y)
8200                     break;
8201                 makestr(&ssh1_cif,ssh1ciphers[x].kwd);
8202             }
8203             return(1);
8204           case SSH1_GNH:
8205           case SSH1_UNH:
8206             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
8207                 if (x != -3)
8208                   return(x);
8209             } else {
8210                 ckstrncpy(line,s,LINBUFSIZ);
8211                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8212                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
8213             }
8214             s = (x == -3) ? NULL : line;
8215             if ((x = cmcfm()) < 0)
8216               return(x);
8217             switch (y) {
8218               case SSH1_GNH: makestr(&ssh1_gnh,s); break;
8219               case SSH1_UNH: makestr(&ssh1_unh,s); break;
8220             }
8221             return(1);
8222         }
8223
8224       case SSH_V2:                      /* SSH V2 */
8225         if ((y = cmkey(sshv2tab,nsshv2tab,"","", xxstring)) < 0)
8226           return(y);
8227         switch (y) {
8228           case SSH2_ARK:
8229             return(success = seton(&ssh2_ark));
8230         case SSH2_AUT: {                        /* Authentication */
8231 #define TMPCNT 12
8232             int i, j, tmp[TMPCNT];
8233             for (i = 0; i < TMPCNT; i++)
8234               tmp[i] = 0;
8235             for (i = 0; i < TMPCNT; i++) {
8236                 if ((y = cmkey(ssh2aut,nssh2aut,
8237                                "Authentication method","",xxstring)) < 0) {
8238                     if (y == -3)
8239                       break;
8240                     return(y);
8241                 }
8242                 for (j = 0; j < i; j++) {
8243                     if (tmp[j] == y) {
8244                         printf("\r\n?Choice has already been used.\r\n");
8245                         return(-9);
8246                     }
8247                 }
8248                 tmp[i] = y;
8249             }
8250             if ((z = cmcfm()) < 0)
8251               return(z);
8252
8253             if (ssh2_auth) {
8254                 free(ssh2_auth);
8255                 ssh2_auth = NULL;
8256             }
8257             if (i > 0) {
8258                 int len = 0;
8259                 for (j = 0; j < i; j++) {
8260                     for (x = 0; x < nssh2aut; x++)
8261                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
8262                         break;
8263                     len += strlen(ssh2aut[x].kwd) + 1;
8264                 }
8265                 ssh2_auth = malloc(len);
8266                 ssh2_auth[0] = '\0';
8267                 for (j = 0; j < i; j++) {
8268                     for (x = 0; x < nssh2aut; x++)
8269                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
8270                         break;
8271                     ckstrncat(ssh2_auth,ssh2aut[x].kwd,len);
8272                     if (j < i - 1)
8273                       ckstrncat(ssh2_auth,",",len);
8274                 }
8275             }
8276             return(success = 1);
8277 #undef TMPCNT
8278           }
8279         case SSH2_CIF: {
8280 #define TMPCNT 12
8281             int i, j, tmp[TMPCNT];
8282             for (i = 0; i < TMPCNT; i++)
8283               tmp[i] = 0;
8284
8285             for (i = 0; i < TMPCNT; i++) {
8286                 if ((y = cmkey(ssh2ciphers,nssh2ciphers,
8287                                "","", xxstring)) < 0) {
8288                     if (y == -3)
8289                       break;
8290                     return(y);
8291                 }
8292                 for (j = 0; j < i; j++) {
8293                     if (tmp[j] == y) {
8294                         printf("\r\n?Choice has already been used.\r\n");
8295                         return(-9);
8296                     }
8297                 }
8298                 tmp[i] = y;
8299             }
8300             if ((z = cmcfm()) < 0)
8301               return(z);
8302
8303             if (ssh2_cif) {
8304                 free(ssh2_cif);
8305                 ssh2_cif = NULL;
8306             }
8307             if (i > 0) {
8308                 int len = 0;
8309                 for (j=0; j < i; j++) {
8310                     for (x = 0; x < nssh2ciphers; x++)
8311                       if (ssh2ciphers[x].kwval == tmp[j] &&
8312                           !ssh2ciphers[x].flgs)
8313                         break;
8314                     len += strlen(ssh2ciphers[x].kwd) + 1;
8315                 }
8316                 ssh2_cif = malloc(len);
8317                 ssh2_cif[0] = '\0';
8318                 for (j = 0; j < i; j++) {
8319                   for (x = 0; x < nssh2ciphers; x++)
8320                     if (ssh2ciphers[x].kwval == tmp[j] && !ssh2ciphers[x].flgs)
8321                       break;
8322                     ckstrncat(ssh2_cif,ssh2ciphers[x].kwd,len);
8323                     if (j < i - 1)
8324                       ckstrncat(ssh2_cif,",",len);
8325                 }
8326             }
8327             return(success = 1);
8328 #undef TMPCNT
8329         }
8330         case SSH2_MAC: {
8331 #define TMPCNT 12
8332             int i, j, tmp[TMPCNT];
8333             for (i = 0; i < TMPCNT; i++)
8334               tmp[i] = 0;
8335
8336             for (i = 0; i < TMPCNT; i++) {
8337                 if ((y = cmkey(ssh2macs,nssh2macs,"","", xxstring)) < 0) {
8338                     if (y == -3)
8339                       break;
8340                     return(y);
8341                 }
8342                 for (j = 0; j < i; j++) {
8343                     if (tmp[j] == y) {
8344                         printf("\r\n?Choice has already been used.\r\n");
8345                         return(-9);
8346                     }
8347                 }
8348                 tmp[i] = y;
8349             }
8350             if ((z = cmcfm()) < 0)
8351                 return(z);
8352
8353             if (ssh2_mac) {
8354                 free(ssh2_mac);
8355                 ssh2_mac = NULL;
8356             }
8357             if (i > 0) {
8358                 int len = 0;
8359                 for (j = 0; j < i; j++) {
8360                     for (x = 0; x < nssh2macs; x++)
8361                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
8362                         break;
8363                     len += strlen(ssh2macs[x].kwd) + 1;
8364                 }
8365                 ssh2_mac = malloc(len);
8366                 ssh2_mac[0] = '\0';
8367                 for (j=0; j < i; j++) {
8368                     for (x = 0; x < nssh2macs; x++)
8369                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
8370                         break;
8371                     ckstrncat(ssh2_mac,ssh2macs[x].kwd,len);
8372                     if (j < i - 1)
8373                       ckstrncat(ssh2_mac,",",len);
8374                 }
8375             }
8376             return(success = 1);
8377 #undef TMPCNT
8378           }
8379           case SSH2_HKA: {
8380 #define TMPCNT 12
8381             int i, j, tmp[TMPCNT];
8382             for (i = 0; i < TMPCNT; i++)
8383               tmp[i] = 0;
8384
8385             for (i = 0; i < TMPCNT; i++) {
8386                 if ((y = cmkey(hkatab,nhkatab,
8387                                "","", xxstring)) < 0) {
8388                     if (y == -3)
8389                       break;
8390                     return(y);
8391                 }
8392                 for (j = 0; j < i; j++) {
8393                     if (tmp[j] == y) {
8394                         printf("\r\n?Choice has already been used.\r\n");
8395                         return(-9);
8396                     }
8397                 }
8398                 tmp[i] = y;
8399             }
8400             if ((z = cmcfm()) < 0)
8401               return(z);
8402
8403             if (ssh2_hka) {
8404                 free(ssh2_hka);
8405                 ssh2_hka = NULL;
8406             }
8407             if (i > 0) {
8408                 int len = 0;
8409                 for (j=0; j < i; j++) {
8410                     for (x = 0; x < nhkatab; x++)
8411                       if (hkatab[x].kwval == tmp[j] &&
8412                           !hkatab[x].flgs)
8413                         break;
8414                     len += strlen(hkatab[x].kwd) + 1;
8415                 }
8416                 ssh2_hka = malloc(len);
8417                 ssh2_hka[0] = '\0';
8418                 for (j = 0; j < i; j++) {
8419                   for (x = 0; x < nhkatab; x++)
8420                     if (hkatab[x].kwval == tmp[j] && !hkatab[x].flgs)
8421                       break;
8422                     ckstrncat(ssh2_hka,hkatab[x].kwd,len);
8423                     if (j < i - 1)
8424                       ckstrncat(ssh2_hka,",",len);
8425                 }
8426             }
8427             return(success = 1);
8428 #undef TMPCNT
8429           }
8430           case SSH2_GNH:
8431           case SSH2_UNH:
8432             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
8433                 if (x != -3)
8434                   return(x);
8435             } else {
8436                 ckstrncpy(line,s,LINBUFSIZ);
8437                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8438                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
8439             }
8440             s = (x == -3) ? NULL : line;
8441             if ((x = cmcfm()) < 0)
8442               return(x);
8443             switch (y) {
8444               case SSH2_GNH: makestr(&ssh2_gnh,s); break;
8445               case SSH2_UNH: makestr(&ssh2_unh,s); break;
8446               default: return(success = 0);
8447             }
8448             return(success = 1);
8449         }
8450
8451       case SSH_VRB:                     /* Verbosity level */
8452         y = cmnum("SSH verbosity level, 0-7","2",10,&x,xxstring);
8453         return(setnum(&ssh_vrb,x,y,7));
8454
8455       case SSH_VER:                     /* Version */
8456         if ((y = cmkey(sshver,3,"","auto", xxstring)) < 0)
8457           return(y);
8458         if ((x = cmcfm()) < 0)
8459           return(x);
8460         ssh_ver = y;                    /* 0 == AUTO */
8461 #ifndef SSHTEST
8462         sl_ssh_ver_saved = 0;
8463 #endif /* SSHTEST */
8464         return(success = 1);
8465
8466       case SSH_IDF: {                   /* Identity file */
8467         int i, n;
8468         for (i = 0; i < 32; i++) {
8469             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
8470                 if (x == -3)
8471                   break;
8472                 return(x);
8473             }
8474             if (!zfnqfp(s,LINBUFSIZ,line))
8475               ckstrncpy(line,s,LINBUFSIZ);
8476             makestr(&ssh_tmp[i],line);
8477         }
8478         n = i;
8479         if ((x = cmcfm()) < 0) {
8480             for (i = 0; i < n; i++)
8481               makestr(&(ssh_tmp[i]),NULL);
8482             return(x);
8483         }
8484         for (i = 0; i < 32; i++) {
8485             makestr(&(ssh_idf[i]),NULL);
8486             if (i < n) {
8487                 ssh_idf[i] = ssh_tmp[i];
8488                 ssh_tmp[i] = NULL;
8489             } else {
8490                 makestr(&(ssh_tmp[i]),NULL);
8491             }
8492         }
8493         ssh_idf_n = n;
8494         return(success = 1);
8495       }
8496       case SSH_XFW:                     /* X11-forwarding */
8497         success = seton(&ssh_xfw);
8498 #ifndef SSHTEST
8499         if (success)
8500           sl_ssh_xfw_saved = 0;
8501 #endif /* SSHTEST */
8502         return(success);
8503
8504       case SSH_XAL:                     /* SSH Xauth Location */
8505         if ((x = cmifi("Path to executable", "",&s,&y,xxstring)) < 0) {
8506             if (x != -3)
8507               return(x);
8508         } else {
8509             ckstrncpy(line,s,LINBUFSIZ);
8510             if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8511               ckstrncpy(line,tmpbuf,LINBUFSIZ);
8512         }
8513         s = (x == -3) ? NULL : line;
8514         if ((x = cmcfm()) < 0) return(x);
8515         makestr(&ssh_xal,s);
8516         return(success = 1);
8517
8518       case SSH_CFG:                     /* Use OpenSSH Config */
8519         return(success = seton(&ssh_cfg));
8520 #endif /* SSHBUILTIN */
8521
8522       default:
8523         return(-2);
8524     }
8525 }
8526 #endif /* ANYSSH */
8527
8528 #ifdef SFTP_BUILTIN
8529 static int
8530 dosetsftp() {
8531     int cx, x, y, z;
8532     char * s;
8533
8534     if ((cx = cmkey(sftptab,nsftptab,"","", xxstring)) < 0)
8535       return(cx);
8536     switch (cx) {
8537     case XY_SFTP_EOL:
8538     case XY_SFTP_RCS:
8539     default:
8540         return(-2);
8541     }
8542 }
8543 #endif /* SFTP_BUILTIN */
8544
8545 #ifdef KUI
8546 #include "ikui.h"
8547 extern ULONG RGBTable[16];
8548
8549 #define GUI_RGB  1
8550 #define GUI_WIN  2
8551 #define GUI_FON  3
8552 #define GUI_DIA  4
8553 #define GUI_TLB  5
8554 #define GUI_MNB  6
8555 #define GUI_CLS  7
8556
8557 #define GUIW_POS 1
8558 #define GUIW_RES 2
8559 #define GUIW_RUN 3
8560 #define GUIWR_NON 0
8561 #define GUIWR_FON 1
8562 #define GUIWR_DIM 2
8563 #define GUIWN_RES 1
8564 #define GUIWN_MIN 2
8565 #define GUIWN_MAX 3
8566
8567 static struct keytab guitab[] = {
8568     { "close",       GUI_CLS,  0 },
8569     { "dialogs",     GUI_DIA,  0 },
8570     { "font",        GUI_FON,  0 },
8571     { "menubar",     GUI_MNB,  0 },
8572     { "rgbcolor",    GUI_RGB,  0 },
8573     { "toolbar",     GUI_TLB,  0 },
8574     { "window",      GUI_WIN,  0 },
8575     { "", 0, 0}
8576 };
8577 static int nguitab = (sizeof(guitab) / sizeof(struct keytab));
8578
8579 static struct keytab guiwtab[] = {
8580     { "position",    GUIW_POS, 0 },
8581     { "resize-mode", GUIW_RES, 0 },
8582     { "run-mode",    GUIW_RUN, 0 },
8583     { "", 0, 0}
8584 };
8585 static int nguiwtab = (sizeof(guiwtab) / sizeof(struct keytab));
8586
8587 static struct keytab guiwrtab[] = {
8588     { "change-dimensions",  GUIWR_DIM, 0 },
8589     { "none",               GUIWR_NON, 0 },
8590     { "scale-font",         GUIWR_FON, 0 },
8591     { "", 0, 0}
8592 };
8593 static int nguiwrtab = (sizeof(guiwrtab) / sizeof(struct keytab));
8594
8595 static struct keytab guiwntab[] = {
8596     { "maximize",  GUIWN_MAX, 0 },
8597     { "minimize",  GUIWN_MIN, 0 },
8598     { "restore",   GUIWN_RES, 0 },
8599     { "", 0, 0}
8600 };
8601 static int nguiwntab = (sizeof(guiwntab) / sizeof(struct keytab));
8602
8603 static struct keytab rgbtab[] = {
8604     { "black",         0, 0 },
8605     { "blue",          1, 0 },
8606     { "brown",         6, 0 },
8607     { "cyan",          3, 0 },
8608     { "darkgray",      8, 0 },
8609     { "dgray",         8, CM_INV },
8610     { "green",         2, 0 },
8611     { "lblue",         9, CM_INV },
8612     { "lcyan",        11, CM_INV },
8613     { "lgreen",       10, CM_INV },
8614     { "lgray",         7, CM_INV },
8615     { "lightblue",     9, 0 },
8616     { "lightcyan",    11, 0 },
8617     { "lightgreen",   10, 0 },
8618     { "lightgray",     7, 0 },
8619     { "lightmagenta", 13, 0 },
8620     { "lightred",     12, 0 },
8621     { "lmagenta",     13, CM_INV },
8622     { "lred",         12, CM_INV },
8623     { "magenta",       5, 0 },
8624     { "red",           4, 0 },
8625     { "white",        15, 0 },
8626     { "yellow",       14, 0 },
8627
8628 };
8629 int nrgb = (sizeof(rgbtab) / sizeof(struct keytab));
8630
8631 VOID
8632 shogui() {
8633     extern gui_dialog;
8634     extern HWND getHwndKUI();
8635     unsigned char cmdsav = colorcmd;
8636     int i, red, green, blue, lines=0;
8637     char * s;
8638
8639
8640     printf("GUI paramters:\n");
8641     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8642     printf("  Dialogs:     %s\n",showoff(gui_dialog));
8643     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8644     printf("  Position:    %d,%d\n",get_gui_window_pos_x(),
8645             get_gui_window_pos_y());
8646     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8647     printf("  Resolution:  %d x %d\n",GetSystemMetrics(SM_CXSCREEN),
8648             GetSystemMetrics(SM_CYSCREEN));
8649     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8650     printf("  Run-mode:    %s\n",IsIconic(getHwndKUI()) ? "minimized" :
8651             IsZoomed(getHwndKUI()) ? "maximized" : "restored");
8652     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8653     switch ( get_gui_resize_mode() ) {
8654       case GUIWR_NON:
8655         s = "none";
8656         break;
8657       case GUIWR_FON:
8658         s = "scales font";
8659         break;
8660       case GUIWR_DIM:
8661         s= "changes dimensions";
8662         break;
8663     }
8664     printf("  Resize-mode: %s\n",s);
8665     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8666     printf("\n");
8667     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8668
8669     printf("RGB Color Table:\n");
8670     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8671     printf("  Color              Red Green Blue\n");
8672     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8673     printf("  ------------------------------------------\n");
8674     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8675     for (i = 0; i < nrgb; i++) {
8676         if (!rgbtab[i].flgs) {
8677             blue = (RGBTable[rgbtab[i].kwval] & 0x00FF0000)>>16;
8678             green = (RGBTable[rgbtab[i].kwval] & 0x0000FF00)>>8;
8679             red = (RGBTable[rgbtab[i].kwval] & 0x000000FF);
8680             printf("  %-18s %3d  %3d  %3d  ",rgbtab[i].kwd,red,green,blue);
8681             colorcmd = rgbtab[i].kwval << 4;
8682             printf("********");
8683             colorcmd = cmdsav;
8684             printf("\n");
8685             if (++lines > cmd_rows - 3) {
8686                 if (!askmore())
8687                   return;
8688                 else
8689                   lines = 0;
8690             }
8691         }
8692     }
8693     printf("\n");
8694 }
8695
8696 int
8697 setrgb() {
8698     int cx, red = 0, blue = 0, green = 0, z, x;
8699
8700     if ((cx = cmkey(rgbtab,nrgb,"","",xxstring)) < 0)
8701       return(cx);
8702     if ((z = cmnum("Red value, 0-255","",10,&red,xxstring)) < 0)
8703       return(z);
8704     if ((z = cmnum("Green value, 0-255","",10,&green,xxstring)) < 0)
8705       return(z);
8706     if ((z = cmnum("Blue value, 0-255","",10,&blue,xxstring)) < 0)
8707       return(z);
8708     if ((x = cmcfm()) < 0) return(x);
8709     if (cx > 15 || red > 255 || blue > 255 || green > 255)
8710       return(-2);
8711     RGBTable[cx] = (unsigned)(((unsigned)blue << 16) |
8712         (unsigned)((unsigned)green << 8) |
8713         (unsigned)red);
8714     return(success = 1);
8715 }
8716
8717 /*
8718   Set GUI window position: XY coordinates of upper left corner,
8719   expressed as pixel numbers in the current screen resolution.
8720   (0,0) means put ourselves in the upper left corner.
8721   Can we check for out of bounds?
8722 */
8723
8724 int
8725 setguiwin() {
8726     int cx, x, y, z;
8727     if ((cx = cmkey(guiwtab,nguiwtab,"","",xxstring)) < 0)
8728       return(cx);
8729     switch (cx) {
8730       case GUIW_POS:
8731         if ((z = cmnum("X coordinate (pixel number)","",10,&x,xxstring)) < 0)
8732           return(z);
8733         if ((z = cmnum("Y coordinate (pixel number)","",10,&y,xxstring)) < 0)
8734           return(z);
8735         if ((z = cmcfm()) < 0)
8736           return(z);
8737         if (x < 0 || y < 0) {
8738             printf("?Coordinates must be 0 or greater\n");
8739             return(-9);
8740         }
8741         gui_position(x,y);
8742         return(success = 1);
8743       case GUIW_RES:
8744         if ((x = cmkey(guiwrtab,nguiwrtab,"","",xxstring)) < 0)
8745           return(x);
8746         if ((z = cmcfm()) < 0)
8747           return(z);
8748         gui_resize_mode(x);
8749         return(success = 1);
8750       case GUIW_RUN:
8751         if ((x = cmkey(guiwntab,nguiwntab,"","",xxstring)) < 0)
8752           return(x);
8753         if ((z = cmcfm()) < 0)
8754           return(z);
8755         gui_win_run_mode(x);
8756         return(success = 1);
8757       default:
8758         return(-2);
8759     }
8760 }
8761
8762 int
8763 setguifont() {                          /* Assumes that CKFLOAT is defined! */
8764
8765     extern struct keytab * term_font;
8766     extern struct keytab * _term_font;
8767     extern int tt_font, tt_font_size, ntermfont;
8768     int x, y, z;
8769     char *s;
8770
8771     if (ntermfont == 0)
8772       BuildFontTable(&term_font, &_term_font, &ntermfont);
8773     if (!(term_font && _term_font && ntermfont > 0)) {
8774         printf("?Internal error: Failure to enumerate fonts\n");
8775         return(-9);
8776     }
8777     if ((x = cmkey(_term_font,ntermfont,"","",xxstring)) < 0)
8778       return(x);
8779     if ((z = cmfld("Height of font in points","12",&s,xxstring)) < 0)
8780       return(z);
8781     if (isfloat(s,0) < 1) {             /* (sets floatval) */
8782         printf("?Integer or floating-point number required\n");
8783         return(-9);
8784     }
8785     if (floatval < 0.5) {
8786         printf("?Positive number required\n");
8787         return(-9);
8788     }
8789     if ((z = cmcfm()) < 0)
8790       return(z);
8791     tt_font = x;                        /* Font index */
8792     tt_font_size = (int)(floatval * 2); /* Font size in half points */
8793     KuiSetProperty(KUI_TERM_FONT, (long)tt_font, (long)tt_font_size);
8794     return(success = 1);
8795 }
8796
8797 VOID
8798 setguidialog(x) int x;
8799 {
8800     extern int gui_dialog;
8801     gui_dialog = x;
8802     KuiSetProperty(KUI_GUI_DIALOGS, (long)x, 0L);
8803 }
8804
8805 VOID
8806 setguimenubar(x) int x;
8807 {
8808     KuiSetProperty(KUI_GUI_MENUBAR, (long)x, 0L);
8809 }
8810
8811 VOID
8812 setguitoolbar(x) int x;
8813 {
8814     KuiSetProperty(KUI_GUI_TOOLBAR, (long)x, 0L);
8815 }
8816
8817 VOID
8818 setguiclose(x) int x;
8819 {
8820     KuiSetProperty(KUI_GUI_CLOSE, (long)x, 0L);
8821 }
8822
8823 int
8824 setgui() {
8825     int cx, x, rc;
8826     if ((cx = cmkey(guitab,nguitab,"","",xxstring)) < 0)
8827       return(cx);
8828     switch (cx) {
8829       case GUI_DIA:
8830         rc = seton(&x);
8831         if (rc >= 0)
8832           setguidialog(x);
8833         return(rc);
8834       case GUI_FON:
8835         return(setguifont());
8836       case GUI_RGB:
8837         return(setrgb());
8838       case GUI_WIN:
8839         return(setguiwin());
8840       case GUI_TLB:
8841         rc = seton(&x);
8842         if (rc >= 0)
8843           setguitoolbar(x);
8844         return(rc);
8845       case GUI_MNB:
8846         rc = seton(&x);
8847         if (rc >= 0)
8848           setguimenubar(x);
8849         return(rc);
8850       case GUI_CLS:
8851         rc = seton(&x);
8852         if (rc >= 0)
8853           setguiclose(x);
8854         return(rc);
8855       default:
8856         return(-2);
8857     }
8858 }
8859 #endif /* KUI */
8860
8861 VOID
8862 setexitwarn(x) int x; 
8863 {
8864     xitwarn = x;
8865 #ifdef KUI
8866     KuiSetProperty(KUI_EXIT_WARNING, (long)x, 0L);
8867 #endif /* KUI */
8868 }
8869
8870 #ifndef NOLOCAL
8871 VOID
8872 setdebses(x) int x; {
8873 #ifdef OS2
8874     if ((debses != 0) && (x == 0))      /* It was on and we turned it off? */
8875       os2debugoff();                    /* Fix OS/2 coloration */
8876 #endif /* OS2 */
8877     debses = x;
8878 #ifdef KUI
8879     KuiSetProperty(KUI_TERM_DEBUG,x,0);
8880 #endif /* KUI */
8881 }
8882 #endif /* NOLOCAL */
8883
8884 /*  D O P R M  --  Set a parameter.  */
8885 /*
8886  Returns:
8887   -2: illegal input
8888   -1: reparse needed
8889    0: success
8890 */
8891 int
8892 doprm(xx,rmsflg) int xx, rmsflg; {
8893     int i = 0, x = 0, y = 0, z = 0;
8894     long zz = 0L;
8895     char *s = NULL, *p = NULL;
8896 #ifdef OS2
8897     char portbuf[64];
8898     long portspeed = 0L;
8899     int portparity = 0;
8900     int portflow = 0;
8901 #endif /* OS2 */
8902
8903 #ifndef NOSETKEY
8904 #ifdef OS2
8905     if (xx == XYMSK)
8906       return(setmsk());
8907 #endif /* OS2 */
8908 #endif /* NOSETKEY */
8909
8910     if (xx == XYFLAG) {                 /* SET FLAG */
8911         extern int ooflag;
8912         return(success = seton(&ooflag));
8913     }
8914     if (xx == XYPRTR                    /* SET PRINTER (or BPRINTER) */
8915 #ifdef BPRINT
8916         || xx == XYBDCP
8917 #endif /* BPRINT */
8918         )
8919       return(setprinter(xx));
8920
8921     switch (xx) {
8922
8923 #ifdef ANYX25                           /* SET X25 ... */
8924 case XYX25:
8925         return(setx25());
8926
8927 #ifndef IBMX25
8928 case XYPAD:                             /* SET PAD ... */
8929         return(setpadp());
8930 #endif /* IBMX25 */
8931 #endif /* ANYX25 */
8932
8933 #ifndef NOXFER
8934       case XYEOL:       /* These have all been moved to set send/receive... */
8935       case XYLEN:       /* Let the user know what to do. */
8936       case XYMARK:
8937       case XYNPAD:
8938       case XYPADC:
8939       case XYTIMO:
8940         printf("...Use SET SEND or SET RECEIVE instead.\n");
8941         printf("Type HELP SET SEND or HELP SET RECEIVE for more info.\n");
8942         return(success = 0);
8943
8944       case XYATTR:                      /* File Attribute packets */
8945         return(setat(rmsflg));
8946
8947       case XYIFD:                       /* Incomplete file disposition */
8948         if ((y = cmkey(ifdatab,3,"","auto",xxstring)) < 0) return(y);
8949         if ((x = cmcfm()) < 0) return(x);
8950         if (rmsflg) {
8951             sstate = setgen('S',
8952                             "310",
8953                             y == 0 ? "0" : (y == 1 ? "1" : "2"),
8954                             ""
8955                             );
8956             return((int) sstate);
8957         } else {
8958             keep = y;
8959             return(success = 1);
8960         }
8961 #endif /* NOXFER */
8962
8963       case XYMATCH:                     /* [ REMOTE ] SET MATCH...  */
8964 #ifndef NOXFER
8965         if ((z = cmkey(matchtab,nmatchtab,"","",xxstring)) < 0)
8966           return(z);
8967         if (rmsflg) {
8968             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
8969             if ((x = cmcfm()) < 0) return(x);
8970             switch (z) {
8971               case MCH_DOTF:
8972                 return(sstate = setgen('S',"330", y == 0 ? "0" : "1", ""));
8973               case MCH_FIFO:
8974                 return(sstate = setgen('S',"331", y == 0 ? "0" : "1", ""));
8975               default:
8976                 return(-2);
8977               }
8978           }
8979 #endif /* NOXFER */
8980           switch (z) {
8981             case MCH_FIFO:
8982               return(success = seton(&matchfifo));
8983             case MCH_DOTF:
8984               x = seton(&matchdot); 
8985               if (x < 0) return(x);
8986               dir_dots = -1;
8987               return(success = x);
8988             default:
8989               return(-2);
8990           }
8991
8992 #ifndef NOSPL
8993       case XYINPU:                      /* SET INPUT */
8994         return(setinp());
8995 #endif /* NOSPL */
8996
8997 #ifdef NETCONN
8998       case XYNET: {                     /* SET NETWORK */
8999
9000           struct FDB k1, k2;
9001
9002           cmfdbi(&k1,_CMKEY,"","","",nnetkey, 0, xxstring, netkey, &k2);
9003           cmfdbi(&k2,_CMKEY,"","","",nnets,   0, xxstring, netcmd, NULL);
9004
9005 #ifdef OS2     /* Hide network-type keywords for networks not installed */
9006           for (z = 0; z < nnets; z++) {
9007               if (netcmd[z].kwval == NET_TCPB && tcp_avail == 0)
9008                 netcmd[z].flgs =  CM_INV;
9009 #ifdef SSHBUILTIN
9010               if (netcmd[z].kwval == NET_SSH &&
9011                    !ck_ssleay_is_installed())
9012                 netcmd[z].flgs =  CM_INV;
9013 #endif /* SSHBUILTIN */
9014 #ifdef DECNET
9015               else if (netcmd[z].kwval == NET_DEC  && dnet_avail == 0)
9016                 netcmd[z].flgs =  CM_INV;
9017 #endif /* DECNET */
9018 #ifdef CK_NETBIOS
9019               else if (netcmd[z].kwval == NET_BIOS && netbiosAvail == 0)
9020                 netcmd[z].flgs =  CM_INV;
9021 #endif /* CK_NETBIOS */
9022 #ifdef SUPERLAT
9023               else if (netcmd[z].kwval == NET_SLAT  && slat_avail == 0)
9024                 netcmd[z].flgs =  CM_INV;
9025 #endif /* SUPERLAT */
9026           }
9027           if (tcp_avail)                /* Default network type */
9028             ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
9029 #ifdef SSHBUILTIN
9030           else if ( ck_ssleay_is_installed() )
9031             ckstrncpy(tmpbuf,"ssh",TMPBUFSIZ);
9032 #endif /* SSHBUILTIN */
9033 #ifdef DECNET
9034           else if (dnet_avail)
9035             ckstrncpy(tmpbuf,"decnet",TMPBUFSIZ);
9036 #endif /* DECNET */
9037 #ifdef SUPERLAT
9038           else if (slat_avail)
9039             ckstrncpy(tmpbuf,"superlat",TMPBUFSIZ);
9040 #endif /* SUPERLAT */
9041 #ifdef CK_NETBIOS
9042           else if (netbiosAvail)
9043             ckstrncpy(tmpbuf,"netbios",TMPBUFSIZ);
9044 #endif /* CK_NETBIOS */
9045           else ckstrncpy(tmpbuf,"named-pipe",TMPBUFSIZ);
9046 #else  /* OS2 */
9047 #ifdef TCPSOCKET
9048           ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
9049 #else
9050 #ifdef ANYX25
9051           ckstrncpy(tmpbuf,"x.25",TMPBUFSIZ);
9052 #else
9053           ckstrncpy(tmpbuf,"",TMPBUFSIZ);
9054 #endif /* ANYX25 */
9055 #endif /* TCPSOCKET */
9056 #endif /* OS2 */
9057
9058           x = cmfdb(&k1);
9059           if (x < 0) {                  /* Error */
9060               if (x == -2 || x == -9)
9061                 printf("?No keywords match: \"%s\"\n",atmbuf);
9062               return(x);
9063           }
9064           z = cmresult.nresult;         /* Keyword value */
9065           if (cmresult.fdbaddr == &k1) { /* Which table? */
9066 #ifndef NOSPL
9067 #ifndef NODIAL
9068               if (z == XYNET_D)
9069                 return(parsdir(1));
9070 #endif /* NODIAL */
9071 #endif /* NOSPL */
9072               if ((z = cmkey(netcmd,nnets,"",tmpbuf,xxstring)) < 0)
9073                 return(z);
9074           }
9075
9076 #ifdef NETCMD
9077           if (z == NET_CMD && nopush) {
9078               printf("\n?Sorry, access to external commands is disabled\n");
9079               return(-9);
9080           }
9081 #endif /* NETCMD */
9082
9083 #ifndef NOPUSH
9084 #ifdef NETPTY
9085           if (z == NET_PTY && nopush) {
9086               printf("\n?Sorry, access to external commands is disabled\n");
9087               return(-9);
9088           }
9089 #endif /* NETPTY */
9090 #endif /* NOPUSH */
9091
9092 #ifdef OS2
9093           if (z == NET_TCPB && tcp_avail == 0) {
9094               printf(
9095 "\n?Sorry, either TCP/IP is not available on this system or\n\
9096 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
9097               return(-9);
9098 #ifdef SSHBUILTIN
9099           } else if (z == NET_SSH && !ck_ssleay_is_installed()) {
9100             printf("\n?Sorry, SSH is not available on this system.\n") ;
9101             return(-9);
9102 #endif /* SSHBUILTIN */
9103 #ifdef CK_NETBIOS
9104           } else if (z == NET_BIOS && netbiosAvail == 0) {
9105               printf("\n?Sorry, NETBIOS is not available on this system.\n") ;
9106               return(-9);
9107 #endif /* CK_NETBIOS */
9108 #ifdef DECNET
9109           } else if (z == NET_DEC && dnet_avail == 0) {
9110               printf("\n?Sorry, DECnet is not available on this system.\n") ;
9111               return(-9);
9112 #endif /* DECNET */
9113 #ifdef SUPERLAT
9114           } else if (z == NET_SLAT && slat_avail == 0) {
9115               printf("\n?Sorry, SuperLAT is not available on this system.\n") ;
9116               return(-9);
9117 #endif /* SUPERLAT */
9118           }
9119 #endif /* OS2 */
9120
9121 #ifdef NPIPEORBIOS
9122           if (z == NET_PIPE ||          /* Named pipe -- also get pipename */
9123               z == NET_BIOS) {          /* NETBIOS -- also get local name */
9124               char *defnam;
9125 #ifdef CK_NETBIOS
9126               char tmpnbnam[NETBIOS_NAME_LEN+1];
9127 #endif /* CK_NETBIOS */
9128               /* Construct default name  */
9129               if (z == NET_PIPE) {      /* Named pipe */
9130                   defnam = "kermit";    /* Default name is always "kermit" */
9131               } 
9132 #ifdef CK_NETBIOS
9133               else {                    /* NetBIOS */
9134                   if (NetBiosName[0] != SP) { /* If there is already a name, */
9135                       char *p = NULL;
9136                       int n;            /* use it as the default. */
9137                       ckstrncpy(tmpnbnam,NetBiosName,NETBIOS_NAME_LEN+1);
9138                       /* convert trailing spaces to NULs */
9139                       p = &tmpnbnam[NETBIOS_NAME_LEN-1];
9140                       while (*p == SP) {
9141                           *p = NUL;
9142                           p--;
9143                       }
9144                       defnam = tmpnbnam;
9145                   } else if (*myhost)   /* Otherwise use this PC's host name */
9146                     defnam = (char *) myhost;
9147                   else                  /* Otherwise use "kermit" */
9148                     defnam = "kermit";
9149               }
9150 #endif /* CK_NETBIOS */
9151               if ((y = cmtxt((z == NET_PIPE) ? "name of named-pipe" :
9152                              "local NETBIOS name",
9153                              defnam, &s, xxstring)) < 0)
9154                 return(y);
9155 #ifdef NPIPE
9156               pipename[0] = NUL;
9157 #endif /* NPIPE */
9158               if ((y = (int) strlen(s)) < 1) {
9159                   printf("?You must also specify a %s name\n",
9160                          (z == NET_PIPE) ? "pipe" : "local NETBIOS" );
9161                   return(-9);
9162               }
9163 #ifdef CK_NETBIOS
9164               if (z == NET_BIOS) {
9165                   if (!netbiosAvail) {
9166                       printf("?NETBIOS is not available on this system.\n") ;
9167                       return(-9);
9168                   }
9169                   if (y - NETBIOS_NAME_LEN > 0) {
9170                       printf("?NETBIOS name too long, %ld maximum\n",
9171                              NETBIOS_NAME_LEN);
9172                       return(-9);
9173                   } else if ( !strcmp(s,tmpnbnam) ) {
9174                       nettype = z;      /* Returning to old connection... */
9175                       return(success = 1); /* Done */
9176                   } else if (strcmp("                ",NetBiosName)) {
9177                       printf("?NETBIOS name already assigned to \"%s\"\n",
9178                              NetBiosName);
9179                       return(-9);
9180                   } else {
9181                       NCB ncb;
9182                       APIRET rc;
9183                       ckstrncpy(NetBiosName,s,16);
9184                       for (x = y; x < NETBIOS_NAME_LEN; x++)
9185                         NetBiosName[x] = SP;
9186                       NetBiosName[NETBIOS_NAME_LEN] = NUL;
9187                       printf("Checking \"%s\" as a unique NetBIOS name...\n",
9188                              NetBiosName);
9189                       rc = NCBAddName( NetbeuiAPI,
9190                                       &ncb, NetBiosAdapter, NetBiosName );
9191                       if (rc) {
9192                           printf(
9193                 "?Sorry, \"%s\" is already in use by another NetBIOS node.\n",
9194                                  NetBiosName);
9195                           for (x = 0; x < NETBIOS_NAME_LEN; x++)
9196                             NetBiosName[x] = SP;
9197                           return(-9);
9198                       }
9199                   }
9200               }
9201 #endif /* CK_NETBIOS */
9202 #ifdef NPIPE
9203               if (z == NET_PIPE)
9204                 ckstrncpy(pipename,s,PIPENAML);
9205 #endif /* NPIPE */
9206           } else
9207 #endif /* NPIPEORBIOS */
9208 #ifdef DECNET
9209             if (z == NET_DEC) {
9210                 /* Determine if we are using LAT or CTERM */
9211                 if ((y = cmkey(dnettab,
9212                                ndnet,"DECNET protocol","lat",xxstring)) < 0)
9213                   return(y);
9214                 if ((x = cmcfm()) < 0) return(x);
9215                 ttnproto = y;
9216             } else
9217 #endif /* DECNET */
9218 #ifdef NETDLL
9219               if (z == NET_DLL) {
9220                   /* Find out which DLL they are using */
9221                   char dllname[256]="";
9222                   char * p=NULL;
9223                   if ((x = cmifi("Dynamic load library",
9224                                  "",&p,&y,xxstring)) < 0) {
9225                       if (x == -3) {
9226                           printf("?Name of DLL required\n");
9227                           return(-9);
9228                       }
9229                       return(x);
9230                   }
9231                   ckstrncpy(dllname,p,256);
9232                   if ((x = cmcfm()) < 0) return(x);
9233
9234                   if (netdll_load(dllname) < 0) /* Try to load the dll */
9235                     return(success = 0);
9236                   else {
9237                       nettype = z;
9238                       return(success = 1);
9239                   }
9240               } else
9241 #endif /* NETDLL */
9242                 if ((x = cmcfm()) < 0) return(x);
9243           nettype = z;
9244           if (
9245 #ifdef DECNET
9246               (nettype != NET_DEC)  &&
9247 #endif /* DECNET */
9248 #ifdef NPIPE
9249               (nettype != NET_PIPE) &&
9250 #endif /* NPIPE */
9251 #ifdef CK_NETBIOS
9252               (nettype != NET_BIOS) &&
9253 #endif /* CK_NETBIOS */
9254 #ifdef NETFILE
9255               (nettype != NET_FILE) &&
9256 #endif /* NETFILE */
9257 #ifdef NETCMD
9258               (nettype != NET_CMD) &&
9259 #endif /* NETCMD */
9260 #ifdef NETPTY
9261               (nettype != NET_PTY) &&
9262 #endif /* NETPTY */
9263 #ifdef NETDLL
9264               (nettype != NET_DLL) &&
9265 #endif /* NETDLL */
9266 #ifdef SUPERLAT
9267               (nettype != NET_SLAT) &&
9268 #endif /* SUPERLAT */
9269               (nettype != NET_SX25) &&
9270               (nettype != NET_VX25) &&
9271 #ifdef IBMX25
9272               (nettype != NET_IX25) &&
9273 #endif /* IBMX25 */
9274 #ifdef SSHBUILTIN
9275               (nettype != NET_SSH) &&
9276 #endif /* SSHBUILTIN */
9277               (nettype != NET_TCPB)) {
9278               printf("?Network type not supported\n");
9279               return(success = 0);
9280           } else {
9281               return(success = 1);
9282           }
9283       }
9284
9285 #ifndef NOTCPOPTS
9286 #ifdef TCPSOCKET
9287       case XYTCP: {
9288         extern int ttyfd;
9289
9290         if ((z = cmkey(tcpopt,ntcpopt,"TCP option","nodelay",xxstring)) < 0)
9291           return(z);
9292
9293         switch (z) {
9294 #ifndef NOHTTP
9295           case XYTCP_HTTP_PROXY: {
9296               struct FDB sw, tx;
9297               int n, x;
9298               char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1], abuf[256];
9299               ubuf[0] = pbuf[0] = abuf[0] = 0;
9300
9301               cmfdbi(&sw,               /* First FDB - switches */
9302                      _CMKEY,            /* fcode */
9303                      "HTTP proxy server host[:port] or switch",
9304                      "",                /* default */
9305                      "",                /* addtl string data */
9306                      nuserpass,         /* addtl numeric data 1: tbl size */
9307                      4,                 /* addtl numeric data 2: 4 = cmswi */
9308                      xxstring,          /* Processing function */
9309                      userpass,          /* Keyword table */
9310                      &tx                /* Pointer to next FDB */
9311                      );
9312               cmfdbi(&tx,
9313                      _CMTXT,            /* fcode */
9314                      "HTTP proxy server host[:port]",
9315                      "",                /* default */
9316                      "",                /* addtl string data */
9317                      0,                 /* addtl numeric data 1 */
9318                      0,                 /* addtl numeric data 2 */
9319                      xxstring,
9320                      NULL,
9321                      NULL
9322                      );
9323               while (1) {
9324                   if ((x = cmfdb(&sw)) < 0) {
9325                       if (x == -3) {
9326                           x = -9;
9327                           printf("?Hostname required\n");
9328                       }
9329                       return(x);
9330                   }
9331                   if (cmresult.fcode != _CMKEY)
9332                     break;
9333                   n = cmresult.nresult;
9334                   switch (n) {
9335                     case UPW_USER:
9336                     case UPW_PASS:
9337                     case UPW_AGENT:
9338                       if ((x = cmfld((n == UPW_USER) ?
9339                                      "Username" :
9340                                      ((n == UPW_PASS) ? "Password" : "Agent"),
9341                                      "", &s, xxstring)) < 0) {
9342                           if (x != -3)
9343                             return(x);
9344                       }
9345                       ckstrncpy((n == UPW_USER) ? ubuf :
9346                         ((n == UPW_PASS) ? pbuf : abuf), s, 
9347                         (n == UPW_AGENT) ? 256 : (LOGINLEN+1));
9348                   }
9349               }
9350               if (cmresult.fcode != _CMTXT)
9351                 return(-2);
9352               s = cmresult.sresult;
9353               if (s) if (!*s) s = NULL;
9354
9355 #ifdef IKSDCONF
9356               if (iksdcf)
9357                 return(success = 0);
9358 #endif /* IKSDCONF */
9359               makestr(&tcp_http_proxy_user,ubuf[0]?ubuf:NULL);
9360               makestr(&tcp_http_proxy_pwd,pbuf[0]?pbuf:NULL);
9361               makestr(&tcp_http_proxy_agent,abuf[0]?abuf:NULL);
9362               makestr(&tcp_http_proxy,s);
9363               memset(pbuf,0,sizeof(pbuf));
9364               return(success = 1);
9365           }
9366 #endif /* NOHTTP */
9367 /*
9368   It would have been easy to combine XYTCP_SOCKS_SVR with the previous
9369   one except for the #ifdefs...
9370 */
9371 #ifdef NT
9372 #ifdef CK_SOCKS
9373           case XYTCP_SOCKS_SVR: {
9374               char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1];
9375               char * p = getenv("SOCKS_SERVER");
9376               struct FDB sw, tx;
9377               int n, x;
9378
9379               if (!p) p = "";
9380
9381               cmfdbi(&sw,               /* First FDB - switches */
9382                      _CMKEY,            /* fcode */
9383                      "SOCKS server host[:port] or switch",
9384                      "",                /* default */
9385                      "",                /* addtl string data */
9386                      nuserpass,         /* addtl numeric data 1: tbl size */
9387                      4,                 /* addtl numeric data 2: 4 = cmswi */
9388                      xxstring,          /* Processing function */
9389                      userpass,          /* Keyword table */
9390                      &tx                /* Pointer to next FDB */
9391                      );
9392               cmfdbi(&tx,
9393                      _CMTXT,            /* fcode */
9394                      "SOCKS server host[:port]",
9395                      p,                 /* default */
9396                      "",                /* addtl string data */
9397                      0,                 /* addtl numeric data 1 */
9398                      0,                 /* addtl numeric data 2 */
9399                      xxstring,
9400                      NULL,
9401                      NULL
9402                      );
9403               while (1) {
9404                   if ((x = cmfdb(&sw)) < 0) {
9405                       if (x == -3) {
9406                           x = -9;
9407                           printf("?Hostname required\n");
9408                       }
9409                       return(x);
9410                   }
9411                   if (cmresult.fcode != _CMKEY)
9412                     break;
9413                   n = cmresult.nresult;
9414                   switch (n) {
9415                     case UPW_USER:
9416                     case UPW_PASS:
9417                       if ((x = cmfld((n == UPW_USER) ? "Username" : "Password",
9418                                      "", &s, xxstring)) < 0) {
9419                           if (x != -3)
9420                             return(x);
9421                       }
9422                       ckstrncpy((n == UPW_USER) ? ubuf : pbuf, s, LOGINLEN+1);
9423                   }
9424               }
9425               if (cmresult.fcode != _CMTXT)
9426                 return(-2);
9427               s = cmresult.sresult;
9428               if (s) if (!*s) s = NULL;
9429
9430 #ifdef IKSDCONF
9431               if (iksdcf)
9432                 return(success = 0);
9433 #endif /* IKSDCONF */
9434               makestr(&tcp_socks_user,ubuf);
9435               memset(pbuf,0,sizeof(pbuf));
9436               makestr(&tcp_socks_svr,s);
9437               return(success = 1);
9438           }
9439
9440 #ifdef CK_SOCKS_NS
9441           case XYTCP_SOCKS_NS: {
9442             char * p = getenv("SOCKS_NS");
9443             if (!p) p = "";
9444             if ((y = cmtxt("hostname or IP of SOCKS Name Server",p,
9445                             &s,xxstring)) < 0)
9446                 return(y);
9447 #ifdef IKSDCONF
9448               if (iksdcf) return(success = 0);
9449 #endif /* IKSDCONF */
9450               if (tcp_socks_ns) {
9451                   free(tcp_socks_ns);   /* Free any previous storage */
9452                   tcp_socks_ns = NULL;
9453               }
9454               if (s == NULL || *s == NUL) { /* If none given */
9455                   tcp_socks_ns = NULL;  /* remove the override string */
9456                   return(success = 1);
9457               } else if ((tcp_socks_ns = malloc(strlen(s)+1))) {
9458                   strcpy(tcp_socks_ns,s);
9459                   return(success = 1);
9460               } else
9461                 return(success = 0);
9462           }
9463 #endif /* CK_SOCKS_NS */
9464 #endif /* CK_SOCKS */
9465 #endif /* NT */
9466           case XYTCP_ADDRESS:
9467             if ((y = cmtxt("preferred IP Address for TCP connections","",
9468                            &s,xxstring)) < 0)
9469               return(y);
9470 #ifdef IKSDCONF
9471             if (iksdcf) return(success = 0);
9472 #endif /* IKSDCONF */
9473             if (tcp_address) {
9474                 free(tcp_address);      /* Free any previous storage */
9475                 tcp_address = NULL;
9476             }
9477             if (s == NULL || *s == NUL) { /* If none given */
9478                 tcp_address = NULL;     /* remove the override string */
9479                 return(success = 1);
9480             } else if ((tcp_address = malloc(strlen(s)+1))) {
9481                 strcpy(tcp_address,s);
9482                 return(success = 1);
9483             } else
9484               return(success = 0);
9485 #ifdef SO_KEEPALIVE
9486           case XYTCP_KEEPALIVE:
9487             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9488             if ((y = cmcfm()) < 0) return(y);
9489 #ifdef IKSDCONF
9490             if (iksdcf) return(success = 0);
9491 #endif /* IKSDCONF */
9492 #ifdef SSHBUILTIN
9493             if (network && nettype == NET_SSH && ssh_sock != -1)
9494               success = keepalive(ssh_sock,z);
9495             else
9496 #endif /* SSHBUILTIN */
9497               success = keepalive(ttyfd,z);
9498             return(success);
9499 #endif /* SO_KEEPALIVE */
9500 #ifdef SO_DONTROUTE
9501           case XYTCP_DONTROUTE:
9502             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
9503             if ((y = cmcfm()) < 0) return(y);
9504 #ifdef IKSDCONF
9505             if (iksdcf) return(success = 0);
9506 #endif /* IKSDCONF */
9507 #ifdef SSHBUILTIN
9508             if (network && nettype == NET_SSH && ssh_sock != -1)
9509               success = dontroute(ssh_sock,z);
9510             else
9511 #endif /* SSHBUILTIN */
9512               success = dontroute(ttyfd,z);
9513             return(success);
9514 #endif /* SO_DONTROUTE */
9515 #ifdef TCP_NODELAY
9516           case XYTCP_NODELAY:
9517             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
9518             if ((y = cmcfm()) < 0) return(y);
9519 #ifdef IKSDCONF
9520             if (iksdcf) return(success = 0);
9521 #endif /* IKSDCONF */
9522 #ifdef SSHBUILTIN
9523             if (network && nettype == NET_SSH && ssh_sock != -1)
9524               success = no_delay(ssh_sock,z);
9525             else
9526 #endif /* SSHBUILTIN */
9527               success = no_delay(ttyfd,z);
9528             return(success);
9529           case XYTCP_NAGLE:             /* The inverse of NODELAY */
9530             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9531             if ((y = cmcfm()) < 0) return(y);
9532 #ifdef IKSDCONF
9533             if (iksdcf) return(success = 0);
9534 #endif /* IKSDCONF */
9535 #ifdef SSHBUILTIN
9536             if (network && nettype == NET_SSH && ssh_sock != -1)
9537               success = no_delay(ssh_sock,z);
9538             else
9539 #endif /* SSHBUILTIN */
9540               success = no_delay(ttyfd,!z);
9541             return(success);
9542 #endif /* TCP_NODELAY */
9543 #ifdef SO_LINGER
9544           case XYTCP_LINGER:
9545             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0)
9546               return(z);
9547             if (z) {                    /* if on, we need a timeout value */
9548                 if ((x = cmnum("Linger timeout in 10th of a millisecond",
9549                                "0",10,&y,xxstring)) < 0)
9550                   return(x);
9551             } else
9552               y = 0;
9553             if ((x = cmcfm()) < 0)
9554               return(x);
9555 #ifdef IKSDCONF
9556             if (iksdcf) return(success = 0);
9557 #endif /* IKSDCONF */
9558 #ifdef SSHBUILTIN
9559             if (network && nettype == NET_SSH && ssh_sock != -1)
9560               success = ck_linger(ssh_sock,z,y);
9561             else
9562 #endif /* SSHBUILTIN */
9563               success = ck_linger(ttyfd,z,y);
9564             return(success);
9565 #endif /* SO_LINGER */
9566 #ifdef SO_SNDBUF
9567           case XYTCP_SENDBUF:
9568             x = cmnum("Send buffer size, bytes","8192",10,&z,xxstring);
9569             if (x < 0) return(x);
9570             if ((x = cmcfm()) < 0) return(x);
9571 #ifdef IKSDCONF
9572             if (iksdcf) return(success = 0);
9573 #endif /* IKSDCONF */
9574 #ifdef SSHBUILTIN
9575             if (network && nettype == NET_SSH && ssh_sock != -1)
9576               success = sendbuf(ssh_sock,z);
9577             else
9578 #endif /* SSHBUILTIN */
9579               success = sendbuf(ttyfd,z);
9580             return(success);
9581 #endif /* SO_SNDBUF */
9582 #ifdef SO_RCVBUF
9583           case XYTCP_RECVBUF:
9584             x = cmnum("Receive buffer size, bytes","8192",10,&z,xxstring);
9585             if (x < 0) return(x);
9586             if ((x = cmcfm()) < 0) return(x);
9587 #ifdef IKSDCONF
9588             if (iksdcf) return(success = 0);
9589 #endif /* IKSDCONF */
9590
9591 /* Note: The following is not 16-bit safe */
9592
9593 #ifndef QNX16
9594             if (x > 52248) {
9595                 printf("?Warning: receive buffers larger than 52248 bytes\n");
9596                 printf(" may not be understood by all hosts.  Performance\n");
9597                 printf(" may suffer.\n");
9598                 return(-9);
9599             }
9600 #endif /* QNX16 */
9601 #ifdef SSHBUILTIN
9602             if (network && nettype == NET_SSH && ssh_sock != -1)
9603               success = recvbuf(ssh_sock,z);
9604             else
9605 #endif /* SSHBUILTIN */
9606               success = recvbuf(ttyfd,z);
9607             return(success);
9608 #endif /* SO_RCVBUF */
9609
9610 #ifdef VMS
9611 #ifdef DEC_TCPIP
9612           case XYTCP_UCX: {             /* UCX 2.0 port swabbing bug */
9613               extern int ucx_port_bug;
9614               return(success = seton(&ucx_port_bug));
9615           }
9616 #endif /* DEC_TCPIP */
9617 #endif /* VMS */
9618
9619           case XYTCP_RDNS: {
9620               extern int tcp_rdns;
9621               return(success = setonaut(&tcp_rdns));
9622           }
9623
9624 #ifdef CK_DNS_SRV
9625           case XYTCP_DNS_SRV: {
9626               extern int tcp_dns_srv;
9627               return(success = seton(&tcp_dns_srv));
9628           }
9629 #endif /* CK_DNS_SRV */
9630
9631           default:
9632             return(0);
9633         }
9634       }
9635 #endif /* TCPSOCKET */
9636 #endif /* NOTCPOPTS */
9637 #endif /* NETCONN */
9638     }
9639
9640     switch (xx) {
9641
9642 #ifndef NOLOCAL
9643 #ifdef NETCONN
9644       case XYHOST: {                    /* SET HOST */
9645           z = ttnproto;                 /* Save protocol in case of failure */
9646 #ifdef DECNET
9647           if (nettype != NET_DEC)
9648 #endif /* DECNET */
9649             ttnproto = NP_NONE;
9650           if ((y = setlin(XYHOST,1,0)) <= 0) { /* Sets success to 1 */
9651               debug(F101,"SET HOST fail mdmtyp","",mdmtyp);
9652               ttnproto = z;             /* Failed, restore protocol */
9653               success = 0;
9654           }
9655           didsetlin++;
9656           debug(F101,"SET HOST OK mdmtyp","",mdmtyp);
9657           debug(F101,"SET HOST reliable","",reliable);
9658           return(y);
9659       }
9660 #endif /* NETCONN */
9661
9662       case XYLINE:                      /* SET LINE (= SET PORT) */
9663         debug(F101,"setlin flow 1","",flow);
9664         x = setlin(xx,1,0);
9665         if (x > -1) didsetlin++;
9666         debug(F101,"SET LINE setlin","",x);
9667         debug(F101,"SET LINE flow","",flow);
9668         debug(F101,"SET LINE local","",local);
9669         debug(F101,"SET LINE reliable","",reliable);
9670         return(x);
9671 #endif /* NOLOCAL */
9672
9673 #ifndef NOSETKEY
9674       case XYKEY:                       /* SET KEY */
9675         return(dosetkey());
9676 #endif /* NOSETKEY */
9677
9678 #ifndef NOCSETS
9679       case XYLANG:                      /* Language */
9680         if ((y = cmkey(lngtab,nlng,"","none",xxstring)) < 0)
9681           return(y);
9682         if ((x = cmcfm()) < 0) return(x);
9683
9684         /* Look up language and get associated character sets */
9685         for (i = 0; (i < nlangs) && (langs[i].id != y); i++) ;
9686         if (i >= nlangs) {
9687             printf("?internal error, sorry\n");
9688             return(success = 0);
9689         } /*  */
9690         language = i;                   /* All good, set the language, */
9691         return(success = 1);
9692 #endif /* NOCSETS */
9693
9694 #ifndef MAC
9695       case XYBACK:                      /* BACKGROUND */
9696         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
9697         if ((y = cmcfm()) < 0) return(y);
9698 #ifdef COMMENT
9699         bgset = z;                      /* 0 = off (foreground) */
9700 #ifdef VMS                              /* 1 = on (background) */
9701         if (batch && bgset == 0)        /* To enable echoing of commands */
9702           ckxech = 1;                   /* in VMS batch logs */
9703 #endif /* VMS */
9704 #else  /* COMMENT */
9705         if (z) {                        /* 1 = Background */
9706             bgset = 1;
9707             backgrd = 1;
9708 #ifdef VMS
9709             batch = 1;
9710 #endif /* VMS */
9711         } else {                        /* 0 = Foreground */
9712             bgset = 0;
9713             backgrd = 0;
9714 #ifdef VMS
9715             batch = 0;
9716 #endif /* VMS */
9717         }
9718 #endif /* COMMENT */
9719         success = 1;
9720         bgchk();
9721         return(success);
9722 #endif /* MAC */
9723
9724       case XYQUIE: {                    /* QUIET */
9725 #ifdef DCMDBUF
9726           extern int * xquiet;
9727 #else
9728           extern int xquiet[];
9729 #endif /* DCMDBUF */
9730           x = seton(&quiet);
9731           if (x < 0) return(x);
9732           xquiet[cmdlvl] = quiet;
9733           return(success = x);
9734       }
9735
9736 #ifndef NOXFER
9737       case XYBUF: {                     /* BUFFERS */
9738 #ifdef DYNAMIC
9739           int sb, rb;
9740           if ((y = cmnum("Send buffer size","",10,&sb,xxstring)) < 0) {
9741               if (y == -3) printf("?Buffer size required\n");
9742               return(y);
9743           }
9744           if (sb < 0) {
9745               if (*atmbuf == '-')
9746                 printf("?Negative numbers can't be used here\n");
9747               else printf("?Integer overflow, use a smaller number please\n");
9748               return(-9);
9749           } else if (sb < 80) {
9750               printf("?Too small\n");
9751               return(-9);
9752           }
9753           if ((y=cmnum("Receive buffer size",ckitoa(sb),10,&rb,xxstring)) < 0)
9754             return(y);
9755           if (rb < 0) {
9756               if (*atmbuf == '-')
9757                 printf("?Negative numbers can't be used here\n");
9758               else printf("?Integer overflow, use a smaller number please\n");
9759               return(-9);
9760           } else if (rb < 80) {
9761               printf("?Too small\n");
9762               return(-9);
9763           }
9764           if ((y = cmcfm()) < 0) return(y);
9765           if ((y = inibufs(sb,rb)) < 0) return(y);
9766           y = adjpkl(urpsiz,wslotr,bigrbsiz); /* Maybe adjust packet sizes */
9767           if (y != urpsiz) urpsiz = y;
9768           y = adjpkl(spsiz,wslotr,bigsbsiz);
9769           if (y != spsiz) spsiz = spmax = spsizr = y;
9770           return(success = 1);
9771 #else
9772           printf("?Sorry, not available\n");
9773           return(success = 0);
9774 #endif /* DYNAMIC */
9775       }
9776
9777       case XYCHKT:                      /* BLOCK-CHECK */
9778         if ((x = cmkey(chktab,nchkt,"","3",xxstring)) < 0) return(x);
9779         if ((y = cmcfm()) < 0) return(y);
9780         if (x == 5) {
9781             bctf = 1;
9782 #ifdef COMMENT
9783             printf("?5 - Not implemented yet\n");
9784             return(success = 0);
9785 #endif  /* COMMENT */
9786         }
9787         bctr = x;                       /* Set local too even if REMOTE SET */
9788
9789         if (rmsflg) {
9790             if (x == 4) {
9791                 tmpbuf[0] = 'B';
9792                 tmpbuf[1] = '\0';
9793             } else
9794               ckstrncpy(tmpbuf,ckitoa(x),TMPBUFSIZ);
9795             sstate = setgen('S', "400", tmpbuf, "");
9796             return((int) sstate);
9797         } else {
9798             return(success = 1);
9799         }
9800 #endif /* NOXFER */
9801
9802 #ifndef NOLOCAL
9803 #ifndef MAC                             /* The Mac has no RS-232 */
9804 case XYCARR:                            /* CARRIER-WATCH */
9805         return(setdcd());
9806 #endif /* MAC */
9807 #endif /* NOLOCAL */
9808     }
9809
9810 #ifdef TNCODE
9811     switch (xx) {                       /* Avoid long switch statements... */
9812       case XYTELOP: {
9813           int c, n;                     /* Workers */
9814           int getval = 0;               /* Whether to get switch value */
9815           int tnserver = 0;             /* Client by default */
9816           int opt = -1;                 /* Telnet Option */
9817           struct FDB sw, op;            /* FDBs for each parse function */
9818 #ifdef CK_AUTHENTICATION
9819           extern int sl_topt_a_s_saved;
9820           extern int sl_topt_a_c_saved;
9821           extern int sl_topt_e_s_saved;
9822           extern int sl_topt_e_c_saved;
9823 #endif /* CK_AUTHENTICATION */
9824 #ifdef IKSD
9825           if (inserver)                 /* Server by default when IKSD */
9826             tnserver = 1;
9827 #endif /* IKSD */
9828
9829           /* Set up chained parse functions... */
9830
9831           cmfdbi(&op,                   /* First fdb - telopts*/
9832                  _CMKEY,                /* fcode */
9833                  "/client, /server or", /* hlpmsg */
9834                  "",                    /* default */
9835                  "",                    /* addtl string data */
9836                  ntnopt,                /* addtl numeric data 1 */
9837                  0,                     /* addtl numeric data 2 */
9838                  xxstring,
9839                  tnopttab,
9840                  &sw
9841                  );
9842           cmfdbi(&sw,                   /* Second FDB - command switches */
9843                  _CMKEY,                /* fcode */
9844                  "",                    /* hlpmsg */
9845                  "",                    /* default */
9846                  "",                    /* addtl string data */
9847                  ntnoptsw,              /* addtl numeric data 1: tbl size */
9848                  4,                     /* addtl numeric data 2: 4 = cmswi */
9849                  xxstring,              /* Processing function */
9850                  tnoptsw,               /* Keyword table */
9851                  NULL                   /* Pointer to next FDB */
9852                  );
9853
9854           while (opt < 0) {             /* Parse 0 or more switches */
9855               x = cmfdb(&op);           /* Parse switch or other thing */
9856               debug(F101,"XYTELOP cmfdb","",x);
9857               if (x < 0)                /* Error */
9858                 return(x);              /* or reparse needed */
9859               if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
9860                 break;
9861               c = cmgbrk();             /* Get break character */
9862               getval = (c == ':' || c == '='); /* see how switch ended */
9863               if (getval && !(cmresult.kflags & CM_ARG)) {
9864                   printf("?This switch does not take arguments\n");
9865                   return(-9);
9866               }
9867               z = cmresult.nresult;     /* Numeric result = switch value */
9868               debug(F101,"XYTELOP switch","",z);
9869
9870               switch (z) {              /* Process the switch */
9871                 case CK_TN_CLIENT:
9872                   tnserver = 0;
9873                   break;
9874                 case CK_TN_SERVER:
9875                   tnserver = 1;
9876                     break;
9877                 case CK_TN_EC:
9878                   opt = TELOPT_ECHO;
9879                   break;
9880                 case CK_TN_TT:
9881                   opt = TELOPT_TTYPE;
9882                   break;
9883                 case CK_TN_BM:
9884                   opt = TELOPT_BINARY;
9885                   break;
9886                 case CK_TN_ENV:
9887                   opt = TELOPT_NEWENVIRON;
9888                   break;
9889                 case CK_TN_LOC:
9890                   opt = TELOPT_SNDLOC;
9891                   break;
9892                 case CK_TN_AU:
9893                   opt = TELOPT_AUTHENTICATION;
9894                   break;
9895                 case CK_TN_FX:
9896                   opt = TELOPT_FORWARD_X;
9897                   break;
9898                 case CK_TN_ENC:
9899                   opt = TELOPT_ENCRYPTION;
9900                   break;
9901                 case CK_TN_IKS:
9902                   opt = TELOPT_KERMIT;
9903                   break;
9904                 case CK_TN_TLS:
9905                   opt = TELOPT_START_TLS;
9906                   break;
9907                 case CK_TN_XD:
9908                   opt = TELOPT_XDISPLOC;
9909                   break;
9910                 case CK_TN_NAWS:
9911                   opt = TELOPT_NAWS;
9912                   break;
9913                 case CK_TN_SGA:
9914                   opt = TELOPT_SGA;
9915                   break;
9916                 case CK_TN_PHR:
9917                   opt = TELOPT_PRAGMA_HEARTBEAT;
9918                   break;
9919                 case CK_TN_PSP:
9920                   opt = TELOPT_SSPI_LOGON;
9921                   break;
9922                 case CK_TN_PLG:
9923                   opt = TELOPT_PRAGMA_LOGON;
9924                   break;
9925                 case CK_TN_SAK:
9926                   opt = TELOPT_IBM_SAK;
9927                   break;
9928                 case CK_TN_CPC:
9929                   opt = TELOPT_COMPORT;
9930                   break;
9931                 case CK_TN_LOG:
9932                   opt = TELOPT_LOGOUT;
9933                   break;
9934                 case CK_TN_FLW:
9935                   opt = TELOPT_LFLOW;
9936                   break;
9937                 default:
9938                   printf("?Unexpected value - %d\n",z);
9939                   return(-9);
9940               }
9941 #ifdef COMMENT
9942               if (cmresult.fdbaddr == &op)
9943                 break;
9944 #endif /* COMMENT */
9945           }
9946           switch (opt) {
9947             case TELOPT_ECHO:           /* Options only the Server WILL */
9948             case TELOPT_FORWARD_X:
9949             case TELOPT_SEND_URL:
9950             case TELOPT_IBM_SAK:
9951             case TELOPT_LOGOUT:
9952               if ((x = cmkey(tnnegtab,
9953                              ntnnegtab,
9954                              "desired server state",
9955    TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
9956                              xxstring)
9957                    ) < 0)
9958                 return(x);
9959               if ((z = cmcfm()) < 0)
9960                   return(z);
9961               if (tnserver) {
9962                   TELOPT_DEF_S_ME_MODE(opt) = x;
9963                   TELOPT_ME_MODE(opt) = x;
9964               } else {
9965                   TELOPT_DEF_C_U_MODE(opt) = x;
9966                   TELOPT_U_MODE(opt) = x;
9967               }
9968               break;
9969
9970             case TELOPT_TTYPE:          /* Options only the Client WILL */
9971             case TELOPT_NEWENVIRON:
9972             case TELOPT_SNDLOC:
9973             case TELOPT_AUTHENTICATION:
9974             case TELOPT_START_TLS:
9975             case TELOPT_XDISPLOC:
9976             case TELOPT_NAWS:
9977             case TELOPT_LFLOW:
9978             case TELOPT_COMPORT:
9979               if ((x = cmkey(tnnegtab,
9980                              ntnnegtab,
9981                              "desired client state",
9982     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
9983                              xxstring)
9984                    ) < 0)
9985                 return(x);
9986               if ((z = cmcfm()) < 0)
9987                 return(z);
9988               if (tnserver) {
9989                   TELOPT_DEF_S_U_MODE(opt) = x;
9990                   TELOPT_U_MODE(opt) = x;
9991 #ifdef CK_AUTHENTICATION
9992                   if (opt == TELOPT_AUTHENTICATION)
9993                     sl_topt_a_s_saved = 0;
9994 #endif /* CK_AUTHENTICATION */
9995               } else {
9996                   TELOPT_DEF_C_ME_MODE(opt) = x;
9997                   TELOPT_ME_MODE(opt) = x;
9998 #ifdef CK_AUTHENTICATION
9999                   if (opt == TELOPT_AUTHENTICATION)
10000                     sl_topt_a_c_saved = 0;
10001 #endif /* CK_AUTHENTICATION */
10002               }
10003               break;
10004
10005             default:
10006               if ((x = cmkey(tnnegtab,
10007                              ntnnegtab,
10008                              tnserver ?
10009                              "desired server state" :
10010                              "desired client state",
10011     TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
10012                              xxstring
10013                              )
10014                    ) < 0)
10015                 return(x);
10016               if ((y = cmkey(tnnegtab,
10017                              ntnnegtab,
10018                              !tnserver ? "desired server state" :
10019                              "desired client state",
10020     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
10021                              xxstring
10022                              )
10023                    ) < 0)
10024                 return(y);
10025               if ((z = cmcfm()) < 0)
10026                 return(z);
10027               if (tnserver) {
10028                   TELOPT_DEF_S_ME_MODE(opt) = x;
10029                   TELOPT_ME_MODE(opt) = x;
10030                   TELOPT_DEF_S_U_MODE(opt) = y;
10031                   TELOPT_U_MODE(opt) = y;
10032 #ifdef CK_ENCRYPTION
10033                   if (opt == TELOPT_ENCRYPTION)
10034                     sl_topt_e_s_saved = 0;
10035 #endif /* CK_ENCRYPTION */
10036               } else {
10037                   TELOPT_DEF_C_ME_MODE(opt) = x;
10038                   TELOPT_ME_MODE(opt) = x;
10039                   TELOPT_DEF_C_U_MODE(opt) = y;
10040                   TELOPT_U_MODE(opt) = y;
10041 #ifdef CK_ENCRYPTION
10042                   if (opt == TELOPT_ENCRYPTION)
10043                     sl_topt_e_c_saved = 0;
10044 #endif /* CK_ENCRYPTION */
10045               }
10046           }
10047           return(success = 1);
10048       }
10049
10050       case XYTEL:                       /* TELNET */
10051         if ((z = cmkey(tntab,ntn,"parameter for TELNET negotiations", "",
10052                        xxstring)) < 0)
10053           return(z);
10054         switch (z) {
10055           case CK_TN_EC:                /* ECHO */
10056             if ((x = cmkey(rltab,nrlt,
10057                            "initial TELNET echoing state",
10058                            "local",xxstring)) < 0)
10059               return(x);
10060             if ((y = cmcfm()) < 0) return(y);
10061             tn_duplex = x;
10062             return(success = 1);
10063
10064           case CK_TN_RE:                /* REMOTE-ECHO */
10065             return(success = seton(&tn_rem_echo));
10066
10067           case CK_TN_DB:                /* DEBUG */
10068             return(success = seton(&tn_deb));
10069
10070           case CK_TN_TT:                /* TERMINAL TYPE */
10071             if ((y = cmtxt("terminal type for TELNET connections","",
10072                            &s,xxstring)) < 0)
10073               return(y);
10074             if (tn_term) {
10075                 free(tn_term);          /* Free any previous storage */
10076                 tn_term = NULL;
10077             }
10078             if (s == NULL || *s == NUL) { /* If none given */
10079                 tn_term = NULL;         /* remove the override string */
10080                 return(success = 1);
10081             } else if ((tn_term = malloc(strlen(s)+1))) {
10082                 strcpy(tn_term,s);
10083                 return(success = 1);
10084             } else return(success = 0);
10085
10086 #ifdef CK_FORWARD_X
10087           case CK_TN_FX:                /* FORWARD-X */
10088             if ((x=cmkey(tnfwdxtab,ntnfwdx,"","xauthority-file",xxstring)) < 0)
10089               return(x);
10090             switch (x) {
10091               case 0: {                 /* Xauthority-File */
10092                   x = cmifi("Full path of .Xauthority file","",&s,&y,xxstring);
10093                   if (x < 0 && x != -3)
10094                     return(x);
10095                   makestr(&tn_fwdx_xauthority,s);
10096                   return(success = 1);
10097               }
10098               case 1: {                 /* No-Encryption */
10099                   extern int fwdx_no_encrypt;
10100                   return(success = seton(&fwdx_no_encrypt));
10101               }
10102             }
10103             return(success = 0);
10104 #endif /* CK_FORWARD_X */
10105
10106           case CK_TN_NL:                /* TELNET NEWLINE-MODE */
10107             if ((x = cmkey(tn_nlmtab,ntn_nlm,"","nvt",xxstring)) < 0)
10108               return(x);
10109             if (x == TN_NL_BIN) {
10110               if ((x = cmkey(tnlmtab,ntnlm,"","raw",xxstring)) < 0)
10111                 return(x);
10112               if ((y = cmcfm()) < 0)
10113                 return(y);
10114               tn_b_nlm = x;
10115               return(success = 1);
10116           } else if (x == TN_NL_NVT) {
10117               if ((x = cmkey(tnlmtab,ntnlm,"","on",xxstring)) < 0)
10118                 return(x);
10119               if ((y = cmcfm()) < 0)
10120                 return(y);
10121               tn_nlm = x;
10122               return(success = 1);
10123           } else {
10124               if ((y = cmcfm()) < 0)
10125                 return(y);
10126               tn_nlm = x;
10127               return(success = 1);
10128           }
10129
10130         case CK_TN_XF:                  /* BINARY-TRANSFER-MODE */
10131             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10132             if ((y = cmcfm()) < 0) return(y);
10133             tn_b_xfer = z;
10134             return(success = 1);
10135
10136         case CK_TN_NE:                  /* NO-ENCRYPT-DURING-XFER */
10137             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10138             if ((y = cmcfm()) < 0) return(y);
10139 #ifdef CK_APC
10140             /* Don't let this be set remotely */
10141             if (apcactive == APC_LOCAL ||
10142                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
10143               return(success = 0);
10144 #endif /* CK_APC */
10145             tn_no_encrypt_xfer = z;
10146             return(success = 1);
10147
10148           case CK_TN_BM:                /* BINARY-MODE */
10149             if ((x = cmkey(tnnegtab,ntnnegtab,"","refused",xxstring)) < 0)
10150               return(x);
10151             if ((y = cmcfm()) < 0)
10152               return(y);
10153             TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = x;
10154             TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = x;
10155             TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = x;
10156             TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = x;
10157             return(success = 1);
10158
10159 #ifdef IKS_OPTION
10160           case CK_TN_IKS:               /* KERMIT */
10161             if ((x = cmkey(tnnegtab,ntnnegtab,"DO","accept",xxstring)) < 0)
10162               return(x);
10163             if ((y = cmkey(tnnegtab,ntnnegtab,"WILL","accept",xxstring)) < 0)
10164               return(y);
10165             if ((z = cmcfm()) < 0)
10166               return(z);
10167             TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = y;
10168             TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = x;
10169             TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = y;
10170             TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = x;
10171             return(success = 1);
10172 #endif /* IKS_OPTION */
10173
10174 #ifdef CK_SSL
10175           case CK_TN_TLS:               /* START_TLS */
10176             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10177               return(x);
10178             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10179               return(y);
10180             if ((z = cmcfm()) < 0)
10181               return(z);
10182             TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = x;
10183             TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = y;
10184             TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = x;
10185             TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = y;
10186             return(success = 1);
10187 #endif /* CK_SSL */
10188
10189 #ifdef CK_NAWS
10190           case CK_TN_NAWS:              /* NAWS */
10191             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10192               return(x);
10193             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10194               return(y);
10195             if ((z = cmcfm()) < 0)
10196               return(z);
10197             TELOPT_DEF_S_ME_MODE(TELOPT_NAWS) = x;
10198             TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = y;
10199             TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = x;
10200             TELOPT_DEF_C_U_MODE(TELOPT_NAWS) = y;
10201             return(success = 1);
10202 #endif /* CK_NAWS */
10203
10204 #ifdef CK_AUTHENTICATION
10205           case CK_TN_AU:                /* AUTHENTICATION */
10206             if ((x = cmkey(tnauthtab,ntnauth,"","",xxstring)) < 0)
10207               return(x);
10208             if (x == TN_AU_FWD) {
10209                 extern int forward_flag;
10210                 return(success = seton(&forward_flag));
10211             } else if (x == TN_AU_TYP) {
10212                 extern int auth_type_user[];
10213                 extern int sl_auth_type_user[];
10214                 extern int sl_auth_saved;
10215                 int i, j, atypes[AUTHTYPLSTSZ];
10216
10217                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
10218                     if ((y = cmkey(autyptab,nautyp,"",
10219                                    i == 0 ? "automatic" : "" ,
10220                                    xxstring)) < 0) {
10221                         if (y == -3)
10222                           break;
10223                         return(y);
10224                     }
10225                     if (i > 0 && (y == AUTHTYPE_AUTO || y == AUTHTYPE_NULL)) {
10226                         printf(
10227                         "\r\n?Choice may only be used in first position.\r\n");
10228                         return(-9);
10229                     }
10230                     for (j = 0; j < i; j++) {
10231                         if (atypes[j] == y) {
10232                             printf("\r\n?Choice has already been used.\r\n");
10233                             return(-9);
10234                         }
10235                     }
10236                     atypes[i] = y;
10237                     if (y == AUTHTYPE_NULL || y == AUTHTYPE_AUTO) {
10238                         i++;
10239                         break;
10240                     }
10241                 }
10242                 if (i < AUTHTYPLSTSZ)
10243                   atypes[i] = AUTHTYPE_NULL;
10244                 if ((z = cmcfm()) < 0)
10245                   return(z);
10246                 sl_auth_saved = 0;
10247                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
10248                     auth_type_user[i] = atypes[i];
10249                     sl_auth_type_user[i] = 0;
10250                 }
10251             } else if (x == TN_AU_HOW) {
10252                 if ((y = cmkey(auhowtab,nauhow,"","any",xxstring)) < 0)
10253                   return(y);
10254                 if ((z = cmcfm()) < 0)
10255                   return(z);
10256                 tn_auth_how = y;
10257             } else if (x == TN_AU_ENC) {
10258                 if ((y = cmkey(auenctab,nauenc,"","encrypt",xxstring)) < 0)
10259                   return(y);
10260                 if ((z = cmcfm()) < 0)
10261                   return(z);
10262                 tn_auth_enc = y;
10263             } else {
10264                 if ((y = cmcfm()) < 0)
10265                   return(y);
10266                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = x;
10267                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = x;
10268             }
10269             return(success = 1);
10270 #endif /* CK_AUTHENTICATION */
10271
10272 #ifdef CK_ENCRYPTION
10273           case CK_TN_ENC: {             /* ENCRYPTION */
10274               int c, tmp = -1;
10275               int getval = 0;
10276               static struct keytab * tnetbl = NULL;
10277               static int ntnetbl = 0;
10278
10279               if ((y = cmkey(tnenctab,ntnenc,"","",xxstring)) < 0)
10280                 return(y);
10281               switch (y) {
10282                 case TN_EN_TYP:
10283                   x = ck_get_crypt_table(&tnetbl,&ntnetbl);
10284                   debug(F101,"ck_get_crypt_table x","",x);
10285                   debug(F101,"ck_get_crypt_table n","",ntnetbl);
10286                   if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
10287                     x = 0;
10288                   if (!x) {
10289                       printf("?Oops, types not loaded\n");
10290                       return(-9);
10291                   }
10292                   if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
10293                                  "automatic",xxstring)) < 0)
10294                     return(x);
10295                   if ((z = cmcfm()) < 0)
10296                     return(z);
10297                   cx_type = x;
10298                   sl_cx_type = 0;
10299                   break;
10300                 case TN_EN_START:
10301                   if ((z = cmcfm()) < 0)
10302                     return(z);
10303 #ifdef CK_APC
10304                   /* Don't let this be set remotely */
10305                   if (apcactive == APC_LOCAL ||
10306                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10307                     return(success = 0);
10308 #endif /* CK_APC */
10309                   ck_tn_enc_start();
10310                   break;
10311                 case TN_EN_STOP:
10312                   if ((z = cmcfm()) < 0)
10313                     return(z);
10314 #ifdef CK_APC
10315                   /* Don't let this be set remotely */
10316                   if (apcactive == APC_LOCAL ||
10317                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10318                     return(success = 0);
10319 #endif /* CK_APC */
10320                   ck_tn_enc_stop();
10321                   break;
10322                 default:
10323                   if ((z = cmcfm()) < 0)
10324                     return(z);
10325                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = y;
10326                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = y;
10327                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = y;
10328                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = y;
10329               }
10330               return(success = 1);
10331           }
10332 #endif /* CK_ENCRYPTION */
10333
10334           case CK_TN_BUG:               /* BUG */
10335             if ((x = cmkey(tnbugtab,4,"",
10336                            "binary-me-means-u-too",xxstring)) < 0)
10337               return(x);
10338             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
10339             if ((y = cmcfm()) < 0) return(y);
10340             switch (x) {
10341               case 0:
10342                 tn_b_meu = z;
10343                 break;
10344               case 1:
10345                 tn_b_ume = z;
10346                 break;
10347               case 2:
10348                 tn_infinite = z;
10349                 break;
10350               case 3:
10351                 tn_sb_bug = z;
10352                 break;
10353               case 4:
10354                 tn_auth_krb5_des_bug = z;
10355                 break;
10356             }
10357             return(success = 1);
10358
10359 #ifdef CK_ENVIRONMENT
10360           case CK_TN_XD:                /* XDISPLOC */
10361             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10362               return(x);
10363             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10364               return(y);
10365             if ((z = cmcfm()) < 0)
10366               return(z);
10367             TELOPT_DEF_S_ME_MODE(TELOPT_XDISPLOC) = x;
10368             TELOPT_DEF_S_U_MODE(TELOPT_XDISPLOC) = y;
10369             TELOPT_DEF_C_ME_MODE(TELOPT_XDISPLOC) = x;
10370             TELOPT_DEF_C_U_MODE(TELOPT_XDISPLOC) = y;
10371             return(success = 1);
10372
10373           case CK_TN_ENV: {
10374               char * msg = "value of telnet environment variable";
10375               extern int tn_env_flg;
10376               extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
10377               tn_env_prnt[], tn_env_sys[];
10378               extern char * tn_loc;
10379               if ((x = cmkey(tnenvtab,ntnenv,"","",xxstring)) < 0)
10380                 return(x);
10381               if (x == TN_ENV_UVAR) {   /* User variables */
10382                   char * uvar=NULL;
10383                   char * uval=NULL;
10384                   char * env;
10385                   extern char * tn_env_uservar[8][2];
10386
10387                   /* Get the user variable name */
10388                   if ((x = cmfld("Name of Environment Variable","",&s,
10389                                  xxstring)) < 0)
10390                     return(x);
10391                   makestr(&uvar,s);
10392
10393                   env = getenv(uvar);
10394                   if (!env) env = "";
10395
10396                   if ((x = cmtxt("Value of Environment Variable",env,
10397                                  &s,xxstring)) < 0)
10398                     return(x);
10399                   if (*s)
10400                     makestr(&uval,s);
10401
10402                   /* Now that we have the variable and perhaps a value */
10403                   /* there are three possibilities: (1) new variable   */
10404                   /* and associated value; (2) variable already exists */
10405                   /* but we have a new value; (3) variable already     */
10406                   /* exists but no new value therefore the user wants  */
10407                   /* to clear variable.                                */
10408
10409                   /* Try to find an existing variable */
10410                   for (x = 0; x < 8; x++) {
10411                       if (!ckstrcmp(tn_env_uservar[x][0],uvar,-1,0)) {
10412                           if (uval) {
10413                               free(tn_env_uservar[x][1]);
10414                               tn_env_uservar[x][1] = uval;
10415                               free(uvar);
10416                               return(success = 1);
10417                           } else {
10418                               free(tn_env_uservar[x][0]);
10419                               tn_env_uservar[x][0] = NULL;
10420                               free(tn_env_uservar[x][1]);
10421                               tn_env_uservar[x][1] = NULL;
10422                               free(uvar);
10423                               return(success = 1);
10424                           }
10425                       }
10426                   }
10427
10428                   /* Couldn't find one; look for empty location to insert */
10429                   for (x = 0; x < 8; x++) {
10430                       if (!tn_env_uservar[x][0]) {
10431                           tn_env_uservar[x][0] = uvar;
10432                           tn_env_uservar[x][1] = uval;
10433                           return(success = 1);
10434                       }
10435                   }
10436                   printf("?Sorry, no space for variable.\n");
10437                   return(success = 0);
10438               }
10439               if (x == TN_ENV_OFF || x == TN_ENV_ON) {
10440                   if ((y = cmcfm()) < 0) return(y);
10441 #ifdef IKSD
10442                   if (inserver) {
10443                       printf("?Sorry, command disabled.\r\n");
10444                       return(success = 0);
10445                   }
10446 #endif /* IKSD */
10447                   tn_env_flg = x == TN_ENV_OFF ? 0 : 1;
10448                   return(success = 1);
10449               }
10450
10451               /* Not ON/OFF - Get the value */
10452               z = cmdgquo();
10453               cmdsquo(0);
10454               if ((y = cmtxt(msg, "", &s, xxstring)) < 0) {
10455                   cmdsquo(z);
10456                   return(y);
10457               }
10458               cmdsquo(z);
10459 #ifdef IKSD
10460               if (inserver)
10461                 return(success = 0);
10462 #endif /* IKSD */
10463               if ((int)strlen(s) > 63) {
10464                   printf("Sorry, too long\n");
10465                   return(-9);
10466               }
10467               switch (x) {
10468                 case TN_ENV_USR:
10469                   ckstrncpy(uidbuf,s,UIDBUFLEN);
10470                   sl_uid_saved = 0;
10471                   break;
10472                 case TN_ENV_ACCT:
10473                   ckstrncpy(tn_env_acct,s,64);
10474                   break;
10475                 case TN_ENV_DISP:
10476                   ckstrncpy(tn_env_disp,s,64);
10477                   break;
10478                 case TN_ENV_JOB:
10479                   ckstrncpy(tn_env_job,s,64);
10480                   break;
10481                 case TN_ENV_PRNT:
10482                   ckstrncpy(tn_env_prnt,s,64);
10483                   break;
10484                 case TN_ENV_SYS:
10485                   ckstrncpy(tn_env_sys,s,64);
10486                   break;
10487                 case TN_ENV_LOC:
10488                   if (!*s) s = NULL;
10489                   makestr(&tn_loc,s);
10490                   break;
10491                 case TN_ENV_UVAR:
10492                   printf("\n?Not yet implemented\n");
10493                   break;
10494               }
10495               return(success = 1);
10496           }
10497 #endif /* CK_ENVIRONMENT */
10498
10499 #ifdef CK_SNDLOC
10500           case CK_TN_LOC: {             /* LOCATION */
10501               extern char * tn_loc;
10502               if ((y = cmtxt("Location string","",&s,xxstring)) < 0)
10503                 return(y);
10504               if (!*s) s = NULL;
10505               makestr(&tn_loc,s);
10506               return(success = 1);
10507           }
10508 #endif /* CK_SNDLOC */
10509           case CK_TN_SFU:               /* Microsoft SFU compatibility */
10510             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10511             if ((y = cmcfm()) < 0) return(y);
10512             tn_sfu = z;
10513             return(success = 1);
10514             break;
10515
10516           case CK_TN_WAIT:              /* WAIT-FOR-NEGOTIATIONS */
10517             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10518             if ((y = cmcfm()) < 0) return(y);
10519 #ifdef IKSD
10520             if (inserver &&
10521 #ifdef IKSDCONF
10522                 iksdcf
10523 #else
10524                 1
10525 #endif /* IKSDCONF */
10526                 ) {
10527                 printf("?Sorry, command disabled.\r\n");
10528                 return(success = 0);
10529             }
10530 #endif /* IKSD */
10531             tn_wait_flg = z;
10532             sl_tn_saved = 0;
10533             return(success = 1);
10534
10535           case CK_TN_DL:                /* DELAY SUBNEGOTIATIONS */
10536             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10537             if ((y = cmcfm()) < 0) return(y);
10538 #ifdef IKSD
10539             if (inserver &&
10540 #ifdef IKSDCONF
10541                 iksdcf
10542 #else
10543                 1
10544 #endif /* IKSDCONF */
10545                 ) {
10546                 printf("?Sorry, command disabled.\r\n");
10547                 return(success = 0);
10548             }
10549 #endif /* IKSD */
10550             tn_delay_sb = z;
10551             return(success = 1);
10552
10553           case CK_TN_PUID: {            /* PROMPT-FOR-USERID */
10554               int i,len;
10555               if ((y = cmtxt("Prompt string","",&s,xxstring)) < 0)
10556                 return(y);
10557               s = brstrip(s);
10558               /* we must check to make sure there are no % fields */
10559               len = strlen(s);
10560               for (i = 0; i < len; i++) {
10561                   if (s[i] == '%') {
10562                       if (s[i+1] != '%') {
10563                           printf("%% fields are not used in this command.\n");
10564                           return(-9);
10565                       }
10566                       i++;
10567                   }
10568               }
10569               makestr(&tn_pr_uid,s);
10570               return(success = 1);
10571           }
10572           default:
10573             return(-2);
10574         }
10575     }
10576 #endif /* TNCODE */
10577
10578     switch (xx) {
10579 #ifndef NOSPL
10580       case XYCOUN:                      /* SET COUNT */
10581         x = cmnum("Positive number","0",10,&z,xxstring);
10582         if (x < 0) return(x);
10583         if ((x = cmcfm()) < 0) return(x);
10584         if (z < 0) {
10585             printf("?A positive number, please\n");
10586             return(0);
10587         }
10588         debug(F101,"XYCOUN: z","",z);
10589         return(success = setnum(&count[cmdlvl],z,0,10000));
10590 #endif /* NOSPL */
10591
10592 #ifndef NOSPL
10593       case XYCASE:
10594         return(success = seton(&inpcas[cmdlvl]));
10595 #endif /* NOSPL */
10596
10597       case XYCMD:                       /* COMMAND ... */
10598         if ((y = cmkey(scmdtab,nbytt,"","",xxstring)) < 0)
10599           return(y);
10600         switch (y) {
10601           case SCMD_CBR:
10602             if ((y = cmcfm()) < 0)
10603               return(y);
10604             concb((char)escape);
10605             return(success = 1);
10606
10607           case SCMD_BSZ:
10608             if ((y = cmnum("bytesize for command characters, 7 or 8","7",10,&x,
10609                            xxstring)) < 0)
10610               return(y);
10611             if (x != 7 && x != 8) {
10612                 printf("\n?The choices are 7 and 8\n");
10613                 return(success = 0);
10614             }
10615             if ((y = cmcfm()) < 0) return(y);
10616             if (x == 7) cmdmsk = 0177;
10617             else if (x == 8) cmdmsk = 0377;
10618             return(success = 1);
10619 #ifdef CK_RECALL
10620           case SCMD_RCL:
10621             if ((y = cmnum("maximum number of commands in recall buffer","10",
10622                            10,&x,xxstring)) < 0)
10623               return(y);
10624             if ((y = cmcfm()) < 0) return(y);
10625             return(success = cmrini(x));
10626 #endif /* CK_RECALL */
10627 #ifdef CK_RECALL
10628           case SCMD_RTR:
10629             return(success = seton(&cm_retry));
10630 #endif /* CK_RECALL */
10631           case SCMD_MOR:                /* More-prompting */
10632             success = seton(&xaskmore);
10633             if (success)
10634               saveask = xaskmore;
10635             return(success);
10636           case SCMD_QUO:
10637             if ((x = seton(&y)) < 0) return(x);
10638             cmdsquo(y);                 /* Do it the right way */
10639             cmd_quoting = y;            /* Also keep a global copy */
10640             /* Set string-processing function */
10641 #ifdef datageneral
10642             xxstring = y ? zzstring : (xx_strp) NULL;
10643 #else
10644 #ifdef CK_ANSIC
10645             xxstring = y ? zzstring : (xx_strp) NULL;
10646 #else
10647             xxstring = y ? zzstring : (xx_strp) NULL;
10648 #endif /* CK_ANSIC */
10649 #endif /* datageneral */
10650             return(success = 1);
10651
10652 #ifdef OS2
10653 #ifndef NOLOCAL
10654           case SCMD_COL: {              /* Command-screen colors */
10655               int fg, bg;
10656               fg = cmkey(ttyclrtab, nclrs,
10657                          "foreground color and then background color",
10658                          "white",
10659                          xxstring);
10660               if (fg < 0)
10661                 return(fg);
10662               if ((bg = cmkey(ttyclrtab,nclrs,
10663                               "background color","black",xxstring)) < 0)
10664                 return(bg);
10665               if ((y = cmcfm()) < 0)
10666                 return(y);
10667               colorcmd = fg | bg << 4;
10668               return(success = 1);
10669           }
10670           case SCMD_SCR:                /* Command Scrollback size */
10671             if ((y = cmnum("COMMAND scrollback buffer size, lines","512",10,&x,
10672                            xxstring)) < 0)
10673               return(y);
10674             /* The max number of lines is the RAM  */
10675             /* we can actually dedicate to a       */
10676             /* scrollback buffer given the maximum */
10677             /* process memory space of 512MB       */
10678             if (x < 256 || x > 2000000L) {
10679                 printf("\n?The size must be between 256 and 2,000,000.\n");
10680                 return(success = 0);
10681             }
10682             if ((y = cmcfm()) < 0) return(y);
10683             tt_scrsize[VCMD] = x;
10684             VscrnInit( VCMD );
10685             return(success = 1);
10686
10687           case SCMD_WID: {
10688               if ((y = cmnum("Number of columns in display window",
10689                          "80",10,&x,xxstring)) < 0)
10690                 return(y);
10691               if ((y = cmcfm()) < 0) return(y);
10692
10693               os2_setcmdwidth(x);
10694               return(success = 1);
10695           }
10696           case SCMD_HIG:
10697             if ((y = cmnum("Number of rows in display window",
10698                            "24",10,&x,xxstring)) < 0)
10699               return(y);
10700             if ((y = cmcfm()) < 0) return(y);
10701             os2_setcmdheight(x);
10702             return(success = 1);
10703
10704           case SCMD_STA: {
10705               extern int marginbot;
10706               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
10707               if ((x = cmcfm()) < 0) return(x);
10708               if (y != tt_status[VCMD]) {
10709                   /* Might need to fixup the margins */
10710                   tt_status[VCMD] = y;
10711                   if (y) {
10712                       tt_szchng[VCMD] = 2;
10713                       tt_rows[VCMD]--;
10714                       cmd_rows--;
10715                       VscrnInit(VCMD);  /* Height set here */
10716                       printf("\n");
10717                   } else {
10718                       tt_szchng[VCMD] = 1;
10719                       tt_rows[VCMD]++;
10720                       cmd_rows++;
10721                       VscrnInit(VCMD);  /* Height set here */
10722                   }
10723               }
10724               return(success = 1);
10725           }
10726
10727           case SCMD_CUR: {
10728               int row, col;
10729               position * ppos;
10730
10731               ppos = VscrnGetCurPos(VCMD);
10732 #ifdef NT
10733 #define itoa _itoa
10734 #endif /* NT */
10735               itoa(ppos->y+1, tmpbuf, 10);
10736               if ((y = cmnum("row (1-based)",tmpbuf,10,&row,xxstring)) < 0)
10737                 return(y);
10738
10739               itoa(ppos->x+1, tmpbuf, 10);
10740               if ((y = cmnum("col (1-based)",tmpbuf,10,&col,xxstring)) < 0)
10741                 return(y);
10742               if ((x = cmcfm()) < 0) return(x);
10743
10744               lgotoxy( VCMD, col, row ) ;
10745               VscrnIsDirty( VCMD );
10746               return(success=1);
10747           }
10748 #endif /* NOLOCAL */
10749 #else
10750           case SCMD_WID:
10751             y = cmnum("Command screen width, characters","80",10,&x,xxstring);
10752             return(setnum(&cmd_cols,x,y,1024));
10753
10754           case SCMD_HIG:
10755             y = cmnum("Command screen height, rows","24",10,&x,xxstring);
10756             return(setnum(&cmd_rows,x,y,1024));
10757 #endif /* OS2 */
10758
10759           case SCMD_INT:
10760             return(seton(&cmdint));
10761
10762 #ifdef CK_AUTODL
10763           case SCMD_ADL:
10764             return(seton(&cmdadl));
10765 #endif /* CK_AUTODL */
10766
10767 #ifdef DOUBLEQUOTING
10768           case SCMD_DBQ: {
10769               extern int dblquo;
10770               return(seton(&dblquo));
10771           }
10772 #endif /* DOUBLEQUOTING */
10773
10774           case SCMD_ERR:
10775             y = cmnum("Error message verbosity level, 0-3","1",10,&x,xxstring);
10776             return(setnum(&cmd_err,x,y,3));
10777
10778           case SCMD_VAR:
10779             return(setvareval());
10780
10781           default:
10782             return(-2);
10783         }
10784     }
10785
10786     switch (xx) {
10787
10788       case XYDFLT:                      /* SET DEFAULT = CD */
10789         return(success = docd(XXCWD));
10790
10791 case XYDEBU:                            /* SET DEBUG { on, off, session } */
10792         if ((y = cmkey(dbgtab,ndbg,"","",xxstring)) < 0)
10793           return(y);
10794         if (y == DEB_TIM)
10795 #ifdef COMMENT
10796           return(seton(&debtim) < 0 ? x : (success = 1));
10797 #else
10798           /* why this change? */
10799           return(success = seton(&debtim));
10800 #endif /* COMMENT */
10801
10802 #ifdef IKSD
10803         if (inserver && isguest) {
10804             printf("?Sorry, command disabled.\r\n");
10805             return(success = 0);
10806     }
10807 #endif /* IKSD */
10808
10809         switch (y) {
10810           case DEB_LEN:
10811             y = cmnum("Max length for debug log strings","",10,&x,xxstring);
10812             if ((z = setnum(&debxlen,x,y,-1)) < 0)
10813               return(z);
10814             if ((x = cmcfm()) < 0)
10815               return(x);
10816             return(success = 1);
10817
10818           case DEB_OFF:
10819             if ((x = cmcfm()) < 0)
10820               return(x);
10821 #ifndef NOLOCAL
10822             setdebses(0);
10823 #endif /* NOLOCAL */
10824 #ifdef DEBUG
10825             if (deblog) doclslog(LOGD);
10826 #endif /* DEBUG */
10827             return(success = 1);
10828
10829           case DEB_ON:
10830             if ((x = cmcfm()) < 0)
10831               return(x);
10832 #ifdef DEBUG
10833             deblog = debopn("debug.log", 0);
10834             return(success = deblog ? 1 : 0);
10835 #else
10836             printf("?Sorry, debug log feature not enabled\n");
10837             return(success = 0);
10838 #endif /* DEBUG */
10839           case DEB_SES:
10840             if ((x = cmcfm()) < 0)
10841               return(x);
10842 #ifndef NOLOCAL
10843             setdebses(1);
10844 #endif /* NOLOCAL */
10845             return(success = 1);
10846
10847           case DEB_MSG:                 /* Debug messages 2010/03/12 */
10848             if ((y = cmkey(ooetab,nooetab,"","on",xxstring)) < 0) return(y);
10849             if ((x = cmcfm()) < 0) return(x);
10850             debmsg = y;
10851             return(1);
10852         }
10853         break;
10854
10855 #ifndef NOXFER
10856       case XYDELA:                      /* SET DELAY */
10857         y = cmnum("Number of seconds before starting to send",
10858                   "5",10,&x,xxstring);
10859         if (x < 0) x = 0;
10860         return(success = setnum(&ckdelay,x,y,999));
10861 #endif /* NOXFER */
10862
10863       default:
10864         break;
10865     }
10866
10867     switch (xx) {
10868 #ifdef CK_TAPI
10869       case XYTAPI:
10870         return(settapi());
10871 #endif /* CK_TAPI */
10872 #ifndef NODIAL
10873       case XYDIAL:                      /* SET MODEM or SET DIAL */
10874         return(setdial(-1));
10875       case XYMODM:
10876         return(setmodem());
10877 #ifdef COMMENT
10878       /* not implemented yet */
10879       case XYANSWER:                    /* SET ANSWER */
10880         return(setanswer());
10881 #endif /* COMMENT */
10882 #endif /* NODIAL */
10883
10884 #ifndef NOLOCAL
10885       case XYDUPL:                      /* SET DUPLEX */
10886         if ((y = cmkey(dpxtab,2,"","full",xxstring)) < 0) return(y);
10887         if ((x = cmcfm()) < 0) return(x);
10888         duplex = y;
10889         return(success = 1);
10890
10891       case XYLCLE:                      /* LOCAL-ECHO (= DUPLEX) */
10892         return(success = seton(&duplex));
10893
10894       case XYESC:                       /* SET ESCAPE */
10895         return(success = setcc(ckitoa(DFESC),&escape));
10896 #endif /* NOLOCAL */
10897
10898       case XYEXIT:                      /* SET EXIT */
10899         if ((z = cmkey(xittab,nexit,"","",xxstring)) < 0)
10900           return(z);
10901         switch (z) {
10902           case 0:                       /* STATUS */
10903             y = cmnum("EXIT status code","",10,&x,xxstring);
10904             return(success = setnum(&xitsta,x,y,-1));
10905           case 1:                       /* WARNING */
10906             if ((z = cmkey(xitwtab,nexitw,"","",xxstring)) < 0)
10907               return(z);
10908             if ((y = cmcfm()) < 0) return(y);
10909             setexitwarn(z);
10910             return(success = 1);
10911           case 2:
10912             success = seton(&exitonclose);
10913 #ifdef TCPSOCKET
10914             if (success) tn_exit = exitonclose;
10915 #endif /* TCPSOCKET */
10916             return(success);
10917           case 3: {
10918               extern int exithangup;
10919               return((success = seton(&exithangup)));
10920           }
10921           default:
10922             return(-2);
10923         } /* End of SET EXIT switch() */
10924       default:
10925         break;
10926     }
10927
10928     switch (xx) {
10929
10930       case XYFILE:                      /* SET FILE */
10931         return(setfil(rmsflg));
10932
10933       case XYFLOW: {                    /* FLOW-CONTROL */
10934           extern int cxflow[];
10935           struct FDB k1, k2;
10936           int tncomport = 0;
10937           char * m;
10938
10939 #ifdef TN_COMPORT
10940           if (network && istncomport())
10941             tncomport = 1;
10942 #endif /* TN_COMPORT */
10943
10944           if (tncomport) {
10945               m = "Flow control type, one of the following:\n\
10946    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
10947  or connection type";
10948           } else {
10949           /* All this is because chained FDB's don't give chained help yet */
10950               m =
10951 #ifdef Plan9
10952 #ifdef CK_RTSCTS
10953            "Flow control type, one of the following:\n\
10954    keep   none    rts/cts\n\
10955  or connection type",
10956 #else
10957            "Flow control type, one of the following:\n\
10958    keep   none\n\
10959  or connection type";
10960 #endif /* CK_RTSCTS */
10961 #else
10962 #ifdef CK_RTSCTS
10963 #ifdef CK_DTRCD
10964 #ifdef CK_DTRCTS
10965            "Flow control type, one of the following:\n\
10966    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
10967  or connection type";
10968 #else /* CK_DTRCTS */
10969            "Flow control type, one of the following:\n\
10970    dtr/cd    keep    none    rts/cts   xon/xoff\n\
10971             or connection type";
10972 #endif /* CK_DTRCTS */
10973 #else /* CK_DTRCD */
10974 #ifdef CK_DTRCTS
10975            "Flow control type, one of the following:\n\
10976    dtr/cts   keep   none    rts/cts   xon/xoff\n\
10977  or connection type";
10978 #else /* CK_DTRCTS */
10979            "Flow control type, one of the following:\n\
10980    keep   none    rts/cts   xon/xoff\n\
10981  or connection type";
10982 #endif /* CK_DTRCTS */
10983 #endif /* CK_DTRCD */
10984 #else
10985            "Flow control type, one of the following:\n\
10986    keep   none    xon/xoff\n\
10987  or connection type";
10988 #endif /* CK_RTSCTS */
10989 #endif /* Plan9 */
10990           }
10991           cmfdbi(&k1,_CMKEY,m,"","",ncxtypesw, 4, xxstring, cxtypesw, &k2);
10992           cmfdbi(&k2,
10993                  _CMKEY,
10994                  "",
10995                  "",
10996                  "",
10997 #ifdef TN_COMPORT
10998                  (tncomport ? ntnflo : nflo),
10999 #else
11000                  nflo,
11001 #endif /* TN_COMPORT */
11002                  0,
11003                  xxstring,
11004 #ifdef TN_COMPORT
11005                  (tncomport ? tnflotab : flotab),
11006 #else
11007                  flotab,
11008 #endif /* TN_COMPORT */
11009                  NULL
11010                  );
11011           x = cmfdb(&k1);
11012           if (x < 0) {                  /* Error */
11013               if (x == -2 || x == -9)
11014                 printf("?No keywords or switches match: \"%s\"\n",atmbuf);
11015               return(x);
11016           }
11017           z = cmresult.nresult;         /* Keyword value */
11018           if (cmresult.fdbaddr == &k2) { /* Flow-control type keyword table */
11019               if ((x = cmcfm()) < 0)    /* Set it immediately */
11020                 return(x);
11021               flow = z;
11022               debug(F101,"set flow","",flow);
11023 #ifdef CK_SPEED
11024               if (flow == FLO_XONX)     /* Xon/Xoff forces prefixing */
11025                 ctlp[XON] = ctlp[XOFF] = ctlp[XON+128] = ctlp[XOFF+128] = 1;
11026 #endif /* CK_SPEED */
11027               autoflow = (flow == FLO_AUTO);
11028               return(success = 1);      /* Done */
11029           }
11030           debug(F101,"set flow /blah 1","",z); /* SET FLOW /for-what */
11031           if ((y = cmkey(flotab,nflo,"Flow control type","none",xxstring)) < 0)
11032             return(y);
11033           if ((x = cmcfm()) < 0)
11034             return(x);
11035           debug(F101,"set flow /blah 2","",y);
11036           if (y == FLO_AUTO) {
11037               printf(
11038   "?Sorry, \"automatic\" can not be assigned to a connection type.\n");
11039               return(-9);
11040           } else if (z >= 0 && z <= CXT_MAX)
11041             cxflow[z] = y;
11042           debug(F101,"set flow","",flow);
11043           debug(F101,"set flow autoflow","",autoflow);
11044           return(success = 1);
11045       }
11046
11047       case XYHAND:                      /* HANDSHAKE */
11048         if ((y = cmkey(hshtab,nhsh,"","none",xxstring)) < 0) return(y);
11049         if (y == 998) {
11050             if ((x = cmnum("ASCII value","",10,&y,xxstring)) < 0)
11051               return(x);
11052             if ((y < 1) || ((y > 31) && (y != 127))) {
11053                 printf("?Character must be in ASCII control range\n");
11054                 return(-9);
11055             }
11056         }
11057         if ((x = cmcfm()) < 0) return(x);
11058         turn = (y > 0127) ? 0 : 1;
11059         turnch = y;
11060         return(success = 1);
11061
11062 #ifndef NOSPL
11063       case XYMACR:                      /* SET MACRO */
11064         if ((y = cmkey(smactab,2,"","",xxstring)) < 0) return(y);
11065         switch (y) {
11066           case 0: return(success = seton(&mecho));
11067           case 1: return(success = seton(&merror[cmdlvl]));
11068           default: return(-2);
11069         }
11070 #endif /* NOSPL */
11071
11072       case XYMSGS:
11073 #ifdef VMS
11074         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
11075         if ((y = cmcfm()) < 0) return(y);
11076         vms_msgs = z;
11077         printf("Sorry, SET MESSAGES not implemented yet\n");
11078         return(success = 0);
11079 #endif /* VMS */
11080       default:
11081         break;
11082     }
11083
11084     switch (xx) {
11085
11086       case XYPARI:                      /* PARITY */
11087         if ((y = cmkey(partbl,npar,"","none",xxstring)) < 0)
11088           return(y);
11089
11090         /* If parity not none, then we also want 8th-bit prefixing */
11091
11092 #ifdef HWPARITY
11093         if (y == 'H') {                 /* Hardware */
11094             if ((x = cmkey(hwpartbl,nhwpar,"","even",xxstring)) < 0)
11095               return(x);
11096         }
11097 #endif /* HWPARITY */
11098
11099         if ((z = cmcfm()) < 0)
11100           return(z);
11101
11102 #ifdef HWPARITY
11103         if (y == 'H') {                 /* 8 data bits plus hardware parity */
11104             parity = 0;
11105 #ifndef NOXFER
11106             ebqflg = 0;
11107 #endif /* NOXFER */
11108             hwparity = x;
11109         } else {                        /* 7 data bits + software parity */
11110             hwparity = 0;
11111 #endif /* HWPARITY */
11112             parity = y;
11113 #ifndef NOXFER
11114             ebqflg = (parity) ? 1 : 0;
11115 #endif /* NOXFER */
11116 #ifdef HWPARITY
11117         }
11118 #endif /* HWPARITY */
11119
11120 #ifdef TN_COMPORT
11121         if (network && istncomport())
11122           tnsettings(parity, 0);
11123 #endif /* TN_COMPORT */
11124
11125         return(success = 1);
11126
11127 #ifndef NOFRILLS
11128       case XYPROM:                      /* SET PROMPT */
11129 /*
11130   Note: xxstring not invoked here.  Instead, it is invoked every time the
11131   prompt is issued.  This allows the prompt string to contain variables
11132   that can change, like \v(dir), \v(time), etc.
11133 */
11134         ckmakmsg(line,                  /* Default might have trailing space */
11135                  LINBUFSIZ,
11136                  "{",
11137                  inserver ? ikprompt : ckprompt,
11138                  "}",
11139                  NULL
11140                  );
11141         if ((x = cmtxt("Program's command prompt",line,&s,NULL)) < 0)
11142           return(x);
11143         s = brstrip(s);                 /* Remove enclosing braces, if any */
11144         cmsetp(s);                      /* Set the prompt */
11145         return(success = 1);
11146 #endif /* NOFRILLS */
11147
11148 #ifndef NOXFER
11149       case XYRETR:                      /* RETRY: per-packet retry limit */
11150         y = cmnum("Maximum retries per packet","10",10,&x,xxstring);
11151         if (x < 0) x = 0;
11152         if ((x = setnum(&maxtry,x,y,999)) < 0) return(x);
11153 #ifdef COMMENT
11154         if (maxtry <= wslotr) {
11155             printf("?Retry limit must be greater than window size\n");
11156             return(success = 0);
11157         }
11158 #endif /* COMMENT */
11159         if (rmsflg) {
11160             sstate = setgen('S', "403", ckitoa(maxtry), "");
11161             return((int) sstate);
11162         } else return(success = x);
11163 #endif /* NOXFER */
11164
11165 #ifndef NOSERVER
11166       case XYSERV:                      /* SET SERVER items */
11167         if ((y = cmkey(srvtab,nsrvt,"","",xxstring)) < 0) return(y);
11168         switch (y) {
11169           case XYSERI:
11170             if ((y = cmnum("Number of seconds, or 0 for no idle timeout",
11171                            "0",10,&x,xxstring)) < 0)
11172               return(y);
11173             if (x < 0)
11174               x = 0;
11175             if ((y = cmcfm()) < 0)
11176               return(y);
11177 #ifndef OS2
11178             srvtim = 0;
11179 #endif /* OS2 */
11180             srvidl = x;
11181             return(success = 1);
11182           case XYSERT:
11183             if ((y = cmnum("Interval for server NAKs, 0 = none",
11184                            ckitoa(DSRVTIM),
11185                            10,&x, xxstring)) < 0)
11186               return(y);
11187             if (x < 0) {
11188                 printf(
11189                    "\n?Specify a positive number, or 0 for no server NAKs\n");
11190                 return(0);
11191             }
11192             if ((y = cmcfm()) < 0) return(y);
11193             if (rmsflg) {
11194                 sstate = setgen('S', "404", ckitoa(x), "");
11195                 return((int) sstate);
11196             } else {
11197 #ifndef OS2
11198                 srvidl = 0;
11199 #endif /* OS2 */
11200                 srvtim = x;             /* Set the server timeout variable */
11201                 return(success = 1);
11202             }
11203           case XYSERD:                  /* SERVER DISPLAY */
11204             return(success = seton(&srvdis)); /* ON or OFF... */
11205
11206 #ifndef NOSPL
11207           case XYSERP:                  /* SERVER GET-PATH */
11208             return(parsdir(2));
11209 #endif /* NOSPL */
11210
11211           case XYSERL:                  /* SERVER LOGIN */
11212             return(cklogin());
11213
11214           case XYSERC:                  /* SERVER CD-MESSAGE */
11215             x = rmsflg ?
11216               cmkey(onoff,2,"","",xxstring) :
11217                 cmkey(cdmsg,3,"","",xxstring);
11218             if (x < 0)
11219               return(x);
11220             if (x == 2) {               /* CD-MESSAGE FILE */
11221                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
11222                   return(x);
11223                 if (!*s) {
11224                     s = NULL;
11225                     srvcdmsg = 0;
11226                 }
11227                 makestr(&cdmsgstr,s);
11228                 makelist(cdmsgstr,cdmsgfile,8);
11229                 return(success = 1);
11230             }
11231             if ((y = cmcfm()) < 0)      /* CD-MESSAGE ON/OFF */
11232               return(y);
11233             if (rmsflg) {
11234                 sstate = setgen('S', "420", x ? "1" : "0", "");
11235                 return((int) sstate);
11236             } else {
11237                 if (x > 0)
11238                   srvcdmsg |= 1;
11239                 else
11240                   srvcdmsg &= 2;
11241                 return(success = 1);
11242             }
11243           case XYSERK:                  /* SERVER KEEPALIVE */
11244             return(success = seton(&srvping)); /* ON or OFF... */
11245
11246           default:
11247             return(-2);
11248         }
11249 #endif /* NOSERVER */
11250     }
11251
11252     switch (xx) {
11253 #ifdef UNIX
11254 #ifndef NOJC
11255       case XYSUSP:                      /* SET SUSPEND */
11256         seton(&xsuspend);               /* on or off... */
11257         return(success = 1);
11258 #endif /* NOJC */
11259 #endif /* UNIX */
11260
11261       case XYTAKE:                      /* SET TAKE */
11262         if ((y = cmkey(taktab,4,"","",xxstring)) < 0) return(y);
11263         switch (y) {
11264           case 0: return(success = seton(&techo));
11265 #ifndef NOSPL
11266           case 1: return(success = seton(&takerr[cmdlvl]));
11267 #else
11268           case 1: return(success = seton(&takerr[tlevel]));
11269 #endif /* NOSPL */
11270           case 2: techo = 0; return(success = 1); /* For compatibility with */
11271           case 3: techo = 1; return(success = 1); /* MS-DOS Kermit */
11272           default: return(-2);
11273         }
11274
11275 #ifndef NOSCRIPT
11276       case XYSCRI:                      /* SET SCRIPT */
11277         if ((y = cmkey(scrtab,1,"","echo",xxstring)) < 0) return(y);
11278         switch (y) {
11279           case 0: return(success = seton(&secho));
11280           default: return(-2);
11281         }
11282 #endif /* NOSCRIPT */
11283
11284       default:
11285         break;
11286     }
11287
11288 #ifndef NOLOCAL
11289     switch (xx) {
11290       case XYTERM:                      /* SET TERMINAL */
11291         x = settrm();
11292         success = (x > 0) ? 1 : 0;
11293         return(x);
11294
11295 #ifdef NT
11296       case XYWIN95:                     /* SET WIN95 workarounds */
11297         x = setwin95();
11298         success = (x > 0 ? 1 : 0);
11299         return(x);
11300 #endif /* NT */
11301
11302 #ifdef OS2
11303       case XYDLR:                       /* SET DIALER workarounds */
11304         x = setdialer();
11305         success = (x > 0 ? 1 : 0);
11306         return(x);
11307
11308       case XYTITLE:                     /* SET TITLE of window */
11309         x = settitle();
11310         success = (x > 0 ? 1 : 0);
11311         return(x);
11312 #endif /* OS2 */
11313
11314 #ifdef OS2MOUSE
11315       case XYMOUSE:                     /* SET MOUSE */
11316         return(success = setmou());
11317 #endif /* OS2MOUSE */
11318
11319       case XYBELL:                      /* SET BELL */
11320         return(success = setbell());
11321
11322 #ifdef OS2
11323       case XYPRTY:
11324         return(success = setprty() );
11325 #endif /* OS2 */
11326
11327       default:
11328         break;
11329     }
11330 #endif /* NOLOCAL */
11331
11332     switch (xx) {
11333
11334 /* SET SEND/RECEIVE protocol parameters. */
11335
11336 #ifndef NOXFER
11337       case XYRECV:
11338       case XYSEND:
11339         return(setsr(xx,rmsflg));
11340 #endif /* NOXFER */
11341
11342 #ifndef NOLOCAL
11343       case XYSESS:                      /* SESSION-LOG */
11344         if ((x = cmkey(sfttab,nsfttab,"type of file",
11345 #ifdef OS2
11346                        "binary",
11347 #else /* OS2 */
11348                        "text",
11349 #endif /* OS2 */
11350                        xxstring
11351                        )
11352              ) < 0)
11353           return(x);
11354         if ((y = cmcfm()) < 0)
11355           return(y);
11356         if (x == 999) {                 /* TIMESTAMPED-TEXT */
11357             sessft = XYFT_T;            /* Implies text */
11358             slogts = 1;                 /* and timestamps */
11359         } else if (x == 998) {          /* NULL-PADDED-LINES */
11360             slognul = 1;                /* adds NUL after ^J */
11361         } else {                        /* A regular type */
11362             sessft = x;                 /* The type */
11363             slogts = 0;                 /* No timestampes */
11364         }
11365         return(success = 1);
11366
11367       case XYSPEE:                      /* SET SPEED */
11368         lp = line;
11369         if (local && !network) {
11370           ckmakmsg(lp,
11371                    LINBUFSIZ,
11372                    "Transmission rate for ",
11373                    ttname,
11374                    " (bits per second)",
11375                    NULL
11376                    );
11377         } else {
11378           ckstrncpy(lp,
11379                     "Serial-port speed (bits per second)",
11380                     LINBUFSIZ
11381                     );
11382         }
11383         zz = -1L;
11384
11385 #ifdef TN_COMPORT
11386         if (network && istncomport())
11387           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
11388         else
11389 #endif /* TN_COMPORT */
11390           x = cmkey(spdtab,nspd,line,"",xxstring);
11391         if (x < 0) {
11392             if (x == -3) printf("?value required\n");
11393 #ifdef USETCSETSPEED
11394             /* In this case, any number can be tried */
11395             /* There's a parse error message but the request still goes thru */
11396             if (rdigits(atmbuf))
11397               zz = atol(atmbuf);
11398             else
11399 #endif /* USETCSETSPEED */
11400               return(x);
11401         }
11402         if ((y = cmcfm()) < 0) return(y);
11403 #ifdef IKSD
11404         if (inserver) {
11405             printf("?Sorry, command disabled.\r\n");
11406             return(success = 0);
11407         }
11408 #endif /* IKSD */
11409         if (!local) {
11410             printf("?SET SPEED has no effect without prior SET LINE\n");
11411             return(success = 0);
11412         } else if (network
11413 #ifdef TN_COMPORT
11414                    && !istncomport()
11415 #endif /* TN_COMPORT */
11416                    ) {
11417             printf("\n?Speed cannot be set for network connections\n");
11418             return(success = 0);
11419         }
11420
11421 /*
11422   Note: This way of handling speeds is not 16-bit safe for speeds greater
11423   than 230400.  The argument to ttsspd() should have been a long.
11424 */
11425 #ifdef USETCSETSPEED
11426         if (zz > -1L)
11427           x = zz / 10L;
11428 #endif /* USETCSETSPEED */
11429         zz = (long) x * 10L;
11430         if (zz == 130L) zz = 134L;
11431         if (zz == 70L) zz = 75L;        /* (see spdtab[] definition) */
11432         if (ttsspd(x) < 0)  {           /* Call ttsspd with cps, not bps! */
11433             printf("?Unsupported line speed - %ld\n",zz);
11434             return(success = 0);
11435         } else {
11436 #ifdef CK_TAPI
11437             if (!tttapi || tapipass)
11438               speed = ttgspd();         /* Read it back */
11439             else
11440               speed = zz;
11441 #else /* CK_TAPI */
11442             speed = ttgspd();           /* Read it back */
11443 #endif /* CK_TAPI */
11444             if (speed != zz)  {         /* Call ttsspd with cps, not bps! */
11445                 printf("?SET SPEED fails, speed is %ld\n",speed);
11446                 return(success = 0);
11447             }
11448             if (pflag && !xcmdsrc) {
11449                 if (speed == 8880)
11450                   printf("%s, 75/1200 bps\n",ttname);
11451                 else if (speed == 134)
11452                   printf("%s, 134.5 bps\n",ttname);
11453                 else
11454                   printf("%s, %ld bps\n",ttname,speed);
11455             }
11456             return(success = 1);
11457         }
11458 #endif /* NOLOCAL */
11459
11460 #ifndef NOXFER
11461       case XYXFER:                      /* SET TRANSFER */
11462         if ((y = cmkey(rmsflg ? rtstab : tstab, /* (or REMOTE SET TRANSFER) */
11463                        rmsflg ? nrts : nts,
11464                        "","character-set",xxstring)) < 0) return(y);
11465         switch (y) {
11466 #ifdef XFRCAN
11467           case XYX_CAN:                 /* CANCELLATION */
11468             if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
11469             if (z == 0) {               /* OFF */
11470                 if ((y = cmcfm()) < 0) return(y);
11471                 xfrcan = 0;
11472             } else {
11473                 if ((y = cmnum("ASCII code for cancellation character",
11474                                "3",10,&x,
11475                                xxstring)) < 0)
11476                   return(y);
11477                 if (x > 31 && x != 127) {
11478                     printf("Cancel character must be 0-31 or 127\n");
11479                     return(-9);
11480                 }
11481                 if ((y = cmnum("How many required to cause cancellation",
11482                                "2",10,&z, xxstring)) < 0)
11483                   return(y);
11484                 if (z < 2) {
11485                     printf("Number must be 2 or greater\n");
11486                     return(-9);
11487                 }
11488                 if ((y = cmcfm()) < 0) return(y);
11489                 xfrcan = 1;             /* CANCELLATION ON */
11490                 xfrchr = x;             /* Using this character */
11491                 xfrnum = z;             /* Needing this many of them */
11492             }
11493             return(success = 1);
11494 #endif /* XFRCAN */
11495
11496 #ifndef NOCSETS
11497           case XYX_CSE:                 /* CHARACTER-SET */
11498             if ((y = cmkey(tcstab,ntcs,"","transparent",xxstring)) < 0)
11499               return(y);
11500             if ((x = cmcfm()) < 0) return(x);
11501             if (rmsflg) {
11502                 sstate = setgen('S', "405", tcsinfo[y].designator, "");
11503                 return((int) sstate);
11504             } else {
11505                 extern int s_cset, fcharset, axcset[], tcs_save;
11506                 tslevel = (y == TC_TRANSP) ? 0 : 1; /* transfer syntax level */
11507                 xfrxla = tslevel;
11508                 tcharset = y;           /* transfer character set */
11509                 /* SEND CHARACTER-SET AUTO */
11510                 if (tslevel > 0 && s_cset == XMODE_A)
11511                   if (y > -1 && y <= MAXTCSETS)
11512                     if (axcset[y] > -1 && axcset[y] > MAXFCSETS)
11513                       fcharset = axcset[y]; /* Auto-pick file charset */
11514                 setxlatype(tcharset,fcharset); /* Translation type */
11515                 tcs_save = -1;
11516                 return(success = 1);
11517             }
11518 #endif /* NOCSETS */
11519
11520           case XYX_LSH:                 /* LOCKING-SHIFT */
11521             if ((y = cmkey(lstab,nls,"","on",xxstring)) < 0)
11522               return(y);
11523             if ((x = cmcfm()) < 0) return(x);
11524             lscapr = (y == 1) ? 1 : 0;  /* ON: requested = 1 */
11525             lscapu = (y == 2) ? 2 : 0;  /* FORCED:  used = 1 */
11526             return(success = 1);
11527
11528 /* #ifdef CK_XYZ */
11529           case XYX_PRO:                 /* Protocol */
11530 #ifndef OS2
11531             if (inserver) {
11532                 printf("?Sorry, only Kermit protocol is available\n");
11533                 return(-9);
11534             }
11535 #endif /* OS2 */
11536             return(setproto());
11537 /* #endif */ /* CK_XYZ */
11538
11539           case XYX_MOD:                 /* Mode */
11540             if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
11541               return(y);
11542             if ((x = cmcfm()) < 0) return(x);
11543             if (rmsflg) {
11544                 sstate = setgen('S', "410", y == XMODE_A ? "0" : "1", "");
11545                 return((int)sstate);
11546             }
11547             g_xfermode = y;
11548             xfermode = y;
11549 #ifdef NEWFTP
11550             if (ftpisopen()) {          /* If an FTP connection is open */
11551                 extern int ftp_xfermode; /* change its transfer mode too */
11552                 ftp_xfermode = xfermode;
11553             }         
11554 #endif  /* NEWFTP */
11555             return(success = 1);
11556
11557 #ifndef NOLOCAL
11558           case XYX_DIS:                 /* Display */
11559             return(doxdis(1));          /* 1 == Kermit */
11560 #endif /* NOLOCAL */
11561
11562           case XYX_SLO:                 /* Slow-start */
11563             return(seton(&slostart));
11564
11565 #ifndef NOSPL
11566           case XYX_CRC:                 /* CRC */
11567             return(seton(&docrc));
11568 #endif /* NOSPL */
11569
11570           case XYX_BEL:                 /* Bell */
11571             return(seton(&xfrbel));
11572
11573 #ifdef PIPESEND
11574           case XYX_PIP:                 /* Pipes */
11575 #ifndef NOPUSH
11576             if (nopush) {
11577 #endif /* NOPUSH */
11578                 printf("Sorry, access to pipes is disabled\n");
11579                 return(-9);
11580 #ifndef NOPUSH
11581             } else
11582 #endif /* NOPUSH */
11583               return(seton(&usepipes));
11584 #endif /* PIPESEND */
11585
11586           case XYX_INT:                 /* Interruption */
11587             return(seton(&xfrint));
11588
11589           case XYX_XLA:
11590             return(seton(&xfrxla));     /* Translation */
11591
11592           case XYX_MSG: {
11593               extern char * xfrmsg;
11594               if ((x = cmtxt("Prompt string","",&s,xxstring)) < 0)
11595                 return(x);
11596               if (!*s) s = NULL;
11597               makestr(&xfrmsg,s);
11598               return(success = 1);
11599
11600           }
11601           case XYX_RPT: {
11602               extern int whereflg;
11603               return(seton(&whereflg));
11604           }
11605           default:
11606             return(-2);
11607         }
11608 #endif /* NOXFER */
11609     }
11610
11611     switch (xx) {
11612
11613 #ifndef NOXMIT
11614       case XYXMIT:                      /* SET TRANSMIT */
11615         return(setxmit());
11616 #endif /* NOXMIT */
11617
11618 #ifndef NOXFER
11619 #ifndef NOCSETS
11620       case XYUNCS:                      /* UNKNOWN-CHARACTER-SET */
11621         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
11622         if ((x = cmcfm()) < 0) return(x);
11623         unkcs = y;
11624         return(success = 1);
11625 #endif /* NOCSETS */
11626 #endif /* NOXFER */
11627
11628 #ifndef NOPUSH
11629 #ifdef UNIX
11630       case XYWILD:                      /* WILDCARD-EXPANSION */
11631         if ((y = cmkey(wildtab,nwild,
11632                        "Wildcard expansion option","on",xxstring)) < 0)
11633           return(y);
11634         if ((z = cmkey(wdottab,
11635                        2,
11636                        "whether to match filenames that start with \".\"",
11637                        "/no-match-dot-files",
11638                        xxstring)
11639              ) < 0)
11640           return(z);
11641         if ((x = cmcfm()) < 0) return(x);
11642         if (nopush) {
11643             if (y > 0) {
11644                 printf("Shell expansion is disabled\n");
11645                 return(success = 0);
11646             }
11647         }
11648         switch (y) {
11649           case WILD_ON:
11650             wildena = 1; 
11651             break;
11652           case WILD_OFF:
11653             wildena = 0; 
11654             break;
11655           case WILD_KER:
11656             wildxpand = 0;              /* These are the previous */
11657             break;                      /* hardwired values */
11658           case WILD_SHE:
11659             wildxpand = 1; 
11660             break;
11661         }
11662         matchdot = z;
11663         return(success = 1);
11664 #endif /* UNIX */
11665 #endif /* NOPUSH */
11666
11667 #ifndef NOXFER
11668       case XYWIND:                      /* WINDOW-SLOTS */
11669         if (protocol == PROTO_K) {
11670             y = cmnum("Window size for Kermit protocol, 1 to 32",
11671                       "1", 10, &x, xxstring);
11672             y = setnum(&z,x,y,MAXWS);   /* == 32 */
11673         }
11674 #ifdef CK_XYZ
11675         else if (protocol == PROTO_Z) {
11676             y = cmnum("Window size for ZMODEM protocol, 0 to 65535",
11677                       "0", 10, &x, xxstring);
11678             y = setnum(&z,x,y,65535);
11679         }
11680 #endif /* CK_XYZ */
11681         else {
11682             y = cmnum("Window size for current protocol",
11683                       "", 10, &x, xxstring);
11684             y = setnum(&z,x,y,65472);   /* Doesn't matter - we won't use it */
11685         }
11686         if (y < 0) return(y);
11687         if (protocol == PROTO_K) {
11688             if (z < 1)
11689               z = 1;
11690         }
11691 #ifdef CK_XYZ
11692         else if (protocol == PROTO_Z) {
11693             /* Zmodem windowing is closer to Kermit packet length */
11694             /* than Kermit window size.  If Window size is zero   */
11695             /* an end of frame and CRC is sent only at the end of */
11696             /* the file (default).  Otherwise, an End of Frame    */
11697             /* and CRC are sent after Window Size number of bytes */
11698             if (z < 0)                  /* Disable windowing  */
11699               z = 0;
11700         } else {
11701             printf("?SET WINDOW does not apply to %s protocol\n",
11702                    ptab[protocol].p_name
11703                    );
11704         }
11705 #endif /* CK_XYZ */
11706
11707 #ifdef COMMENT
11708         /* This is taken care of automatically now in protocol negotiation */
11709         if (maxtry < z) {
11710             printf("?Window slots must be less than retry limit\n");
11711             return(success = 0);
11712         }
11713 #endif /* COMMENT */
11714         if (protocol == PROTO_K && rmsflg) { /* Set remote window size */
11715             wslotr = z;                 /* Set local window size too */
11716             ptab[protocol].winsize = wslotr;
11717             sstate = setgen('S', "406", ckitoa(z), "");
11718             return((int) sstate);
11719         }
11720         wslotr = z;                     /* Set requested window size here */
11721         ptab[protocol].winsize = wslotr; /* and in protocol-specific table */
11722         if (protocol == PROTO_K) {      /* And for Kermit only... */
11723             swcapr = (wslotr > 1) ? 1 : 0; /* set window bit in capas word */
11724             if (wslotr > 1) {           /* Window size > 1? */
11725                 /* Maybe adjust packet size */
11726                 y = adjpkl(urpsiz,wslotr,bigrbsiz);
11727                 if (y != urpsiz) {      /* Did it change? */
11728                     urpsiz = y;
11729                     if (msgflg)
11730                       printf(
11731 " Adjusting receive packet-length to %d for %d window slots\n",
11732                              urpsiz,
11733                              wslotr
11734                              );
11735                 }
11736             }
11737         }
11738         return(success = 1);
11739 #endif /* NOXFER */
11740     }
11741
11742     switch (xx) {
11743
11744 #ifndef NOSPL
11745       case XYOUTP:                      /* OUTPUT command parameters */
11746         if ((y = cmkey(outptab,noutptab,"OUTPUT command parameter","pacing",
11747                        xxstring)) < 0)
11748           return(y);
11749         switch(y) {                     /* Which parameter */
11750           case OUT_PAC:                 /* PACING */
11751             y = cmnum("Milliseconds to pause between each OUTPUT character",
11752                       "100", 10,&x,xxstring);
11753             y = setnum(&z,x,y,16383);   /* Verify and get confirmation */
11754             if (y < 0) return(y);
11755             if (z < 0) z = 0;           /* (save some space) */
11756             pacing = z;
11757             return(success = 1);
11758           case OUT_ESC:                 /* Special-escapes */
11759             return(seton(&outesc));
11760           default:                      /* (shouldn't happen) */
11761             return(-2);
11762         }
11763 #endif /* NOSPL */
11764
11765 #ifdef CK_SPEED
11766       case XYQCTL: {
11767           short *p;
11768           int zz;
11769           if ((z = cmkey(ctltab,2, "control-character prefixing option",""
11770                          ,xxstring)) < 0)
11771             return(z);
11772           /* Make space for a temporary copy of the prefixing table */
11773
11774           p = (short *)malloc(256 * sizeof(short));
11775           if (!p) {
11776               printf("?Internal error - malloc failure\n");
11777               return(-9);
11778           }
11779           for (i = 0; i < 256; i++) p[i] = ctlp[i]; /* Copy current table */
11780
11781           switch (z) {
11782             case 0:                     /* UNPREFIXED control character */
11783             case 1:                     /* PREFIXED control character */
11784               while (1) {               /* Collect a list of numbers */
11785 #ifndef NOSPL
11786                   x_ifnum = 1;          /* Turn off complaints from eval() */
11787 #endif /* NOSPL */
11788                   if ((x = cmnum((z == 0) ?
11789 "\n Numeric ASCII value of control character that needs NO prefix,\n\
11790  or the word \"all\", or carriage return to complete the list" :
11791 "\n Numeric ASCII value of control character that MUST BE prefixed,\n\
11792  or the word \"all\", or carriage return to complete the list",
11793                                  "",10,&y,xxstring
11794                                  )) < 0) {
11795 #ifndef NOSPL
11796                       x_ifnum = 0;
11797 #endif /* NOSPL */
11798                       if (x == -3) {
11799                           if ((x = cmcfm()) < 0) return(x);
11800                           break;
11801                       }
11802                       if (x == -2) {
11803                           if (p) { free((char *)p); p = NULL; }
11804                           debug(F110,"SET CONTROL atmbuf",atmbuf,0);
11805                           if (!ckstrcmp(atmbuf,"all",3,0) || /* "ALL" */
11806                               !ckstrcmp(atmbuf,"al",2,0) ||
11807                               !ckstrcmp(atmbuf,"a",1,0)) {
11808                               if ((x = cmcfm()) < 0) /* Get confirmation */
11809                                 return(x);
11810                               prefixing = z ? PX_ALL : PX_NON;
11811                               setprefix(prefixing);
11812                               return(success = 1);
11813                           } else {      /* Not number, not ALL */
11814                               printf(
11815                                  "?Please specify a number or the word ALL\n");
11816                               return(-9);
11817                           }
11818                       } else {
11819                           if (p) free((char *)p);
11820                           return(x);
11821                       }
11822                   }
11823 #ifndef NOSPL
11824                   x_ifnum = 0;
11825 #endif /* NOSPL */
11826 #ifdef UNPREFIXZERO
11827                   zz = 0;
11828 #else
11829 #ifndef OS2
11830                   zz = 1 - z;
11831 #else
11832                   zz = 0;               /* Allow 0 (but only for Zmodem) */
11833 #endif /* OS2 */
11834 #endif /* UNPREFIXZERO */
11835
11836             /* printf("x = %d, y = %d, z = %d, zz = %d\n", x,y,z,zz); */
11837
11838                   if ((y >  31 && y < 127) || /* A specific numeric value */
11839                       (y > 159 && y < 255) || /* Check that it is a valid */
11840                       (y < zz) ||       /* control code. */
11841                       (y > 255)) {
11842                       printf("?Values allowed are: %d-31, 127-159, 255\n",zz);
11843                       if (p) free((char *)p);
11844                       return(-9);
11845                   }
11846                   x = y & 127;          /* Get 7-bit value */
11847                   if (z == 0) {         /* If they are saying it is safe... */
11848                       /* If flow control is Xon/Xoff */
11849                       if (((flow == FLO_XONX) &&
11850                            /* XON & XOFF chars not safe. */
11851                            (x == XON || x == XOFF))
11852                           ) {
11853                           if (msgflg)
11854                             printf(
11855                               "Sorry, not while Xon/Xoff is in effect.\n");
11856                           if (p) free((char *)p);
11857                           return(-9);
11858                       }
11859 #ifdef TNCODE
11860                       else if (network && IS_TELNET()
11861                                && (y == CR ||
11862                                    (unsigned) y == (unsigned) 255)) {
11863                           if (msgflg)
11864                             printf("Sorry, not on a TELNET connection.\n");
11865                           if (p) free((char *)p);
11866                           return(-9);
11867                       }
11868 #endif /* TNCODE */
11869                   }
11870                   p[y] = (char) z;      /* All OK, set flag */
11871               } /* End of while loop */
11872 /*
11873   Get here only if they have made no mistakes.  Copy temporary table back to
11874   permanent one, then free temporary table and return successfully.
11875 */
11876               for (i = 0; i < 256; i++) ctlp[i] = p[i];
11877               if (p) free((char *)p);
11878               if (z > 0) clearrq = 0;   /* 199 (see SET PREFIXING) */
11879               return(success = 1);
11880             default:
11881               return(-2);
11882           }
11883       }
11884 #endif /* CK_SPEED */
11885     }
11886
11887     switch (xx) {
11888
11889 #ifndef NOXFER
11890       case XYREPT:
11891         if ((y = cmkey(rpttab,2,
11892                        "repeat-count compression parameter","",xxstring)) < 0)
11893           return(y);
11894         switch(y) {
11895           case 0:
11896             return(success = seton(&rptena)); /* REPEAT COUNTS = ON, OFF */
11897           case 1:                       /* REPEAT MININUM number */
11898             printf("(not implemented yet, nothing happens)\n");
11899             return(-9);
11900           case 2:                       /* REPEAT PREFIX char */
11901             if ((x = cmnum("ASCII value","",10,&z,xxstring)) < 0)
11902               return(x);
11903             if ((x = cmcfm()) < 0) return(x);
11904             if ((z > 32 && z < 63) || (z > 95 && z < 127)) {
11905                 if (y == 1) rptmin = (CHAR) z; else myrptq = (CHAR) z;
11906                 return(success = 1);
11907             } else {
11908                 printf("?Illegal value for prefix character\n");
11909                 return(-9);
11910             }
11911         }
11912 #endif /* NOXFER */
11913
11914 #ifndef NOSPL
11915       case XYALRM: {
11916 #ifndef COMMENT
11917           int yy;
11918           long zz;
11919           zz = -1L;
11920           yy = x_ifnum;
11921           x_ifnum = 1;                  /* Turn off internal complaints */
11922           y = cmnum("Seconds from now, or time of day as hh:mm:ss",
11923                     "0" ,10, &x, xxstring);
11924           x_ifnum = yy;
11925           if (y < 0) {
11926               if (y == -2) {            /* Invalid number or expression */
11927                   zz = tod2sec(atmbuf); /* Convert to secs since midnight */
11928                   if (zz < 0L) {
11929                       printf("?Number, expression, or time of day required\n");
11930                       return(-9);
11931                   } else {
11932                       char now[32];     /* Current time */
11933                       char *p;
11934                       long tnow;
11935                       p = now;
11936                       ztime(&p);
11937                       tnow = atol(p+11) * 3600L +
11938                         atol(p+14) * 60L + atol(p+17);
11939                       if (zz < tnow)    /* User's time before now */
11940                         zz += 86400L;   /* So make it tomorrow */
11941                       zz -= tnow;       /* Seconds from now. */
11942                   }
11943               } else
11944                 return(y);
11945           }
11946           if (x < 0) {
11947               printf("?Alarm time is in the past.\n");
11948               return(-9);
11949           }
11950           if ((y = cmcfm()) < 0) return(y);
11951           if (zz > -1L) {               /* Time of day given? */
11952               x = zz;
11953               if (zz != (long) x) {
11954                   printf(
11955 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
11956                          );
11957                   return(-9);
11958               }
11959           }
11960           return(setalarm((long)x));
11961       }
11962 #else
11963 /*
11964   This is to allow long values where int and long are not the same, e.g.
11965   on 16-bit systems.  But something is wrong with it.
11966 */
11967         if ((y = cmtxt("seconds from now", "0", &s, xxstring)) < 0)
11968           return(y);
11969         if (rdigits(s)) {
11970             return(setalarm(atol(s)));
11971         } else {
11972             printf("%s - not a number\n",s);
11973             return(-9);
11974         }
11975 #endif /* COMMENT */
11976 #endif /* NOSPL */
11977
11978 #ifndef NOXFER
11979       case XYPROTO:
11980         return(setproto());
11981 #endif /* NOXFER */
11982
11983 /*
11984   C-Kermit unprefixes control characters automatically on network connections
11985   if CLEAR-CHANNEL is ON, which it is by default.  But not all network
11986   connections are transparent to all control characters.  For example, the
11987   DEC-20, even when you TELNET to it, is sensitive to Ctrl-O and Ctrl-T.
11988   If you tell C-Kermit to SET CONTROL PREFIX 15 and/or 20, it doesn't help
11989   because CLEAR-CHANNEL is still in effect.  If the user goes to the trouble
11990   to set up some prefixing, then Kermit should do what the user said.  In
11991   C-Kermit 7.1 Alpha.03 we change the code to set clearrq to 0 if the user
11992   gives a SET PREFIXING or SET CONTROL PREFIX command.
11993 */
11994
11995 #ifdef CK_SPEED
11996       case XYPREFIX: {
11997 #ifdef COMMENT
11998           extern int clearrq;
11999 #endif /* COMMENT */
12000           if ((z = cmkey(pfxtab, 4, "control-character prefixing option",
12001                          "", xxstring)) < 0)
12002             return(z);
12003           if ((x = cmcfm()) < 0) return(x);
12004           clearrq = 0;                  /* 199 */
12005           setprefix(z);
12006 #ifdef COMMENT
12007           if (hints && (z == PX_ALL || z == PX_CAU) && clearrq) {
12008         printf("Hint: Use SET CLEAR-CHANNEL OFF to disable negotiation of\n");
12009         printf("      SET PREFIXING NONE during file transfers on reliable\n");
12010         printf("      connections.\n");
12011           }
12012 #endif /* COMMENT */
12013           return(success = 1);
12014       }
12015 #endif /* CK_SPEED */
12016
12017 #ifndef NOSPL
12018       case XYLOGIN:
12019         if ((z = cmkey(logintab, 3, "value for login script","userid",
12020                        xxstring)) < 0)
12021           return(z);
12022         x = cmdgquo();
12023         if (z == LOGI_PSW)
12024           cmdsquo(0);
12025         if ((y = cmtxt("text","", &s, NULL)) < 0) {
12026             cmdsquo(x);
12027             return(y);
12028         }
12029         cmdsquo(x);
12030 #ifdef IKSD
12031         if (inserver)
12032           return(success = 0);
12033 #endif /* IKSD */
12034         s = brstrip(s);
12035         if ((int)strlen(s) > 63) {
12036             printf("Sorry, too long\n");
12037             return(-9);
12038         }
12039         switch(z) {
12040           case LOGI_UID:
12041             ckstrncpy(uidbuf,s,UIDBUFLEN);
12042             sl_uid_saved = 0;
12043             break;
12044           case LOGI_PSW:
12045             ckstrncpy(pwbuf,s,PWBUFL);
12046             if (pwbuf[0]) {
12047                 pwflg = 1;
12048 #ifdef OS2
12049                 pwcrypt = 1;
12050 #else /* OS2 */
12051                 pwcrypt = 0;
12052 #endif /* OS2 */
12053             }
12054             break;
12055           case LOGI_PRM:
12056             ckstrncpy(prmbuf,s,PWBUFL);
12057         }
12058         return(success = 1);
12059 #endif /* NOSPL */
12060     }
12061
12062     switch (xx) {
12063
12064       case XYSTARTUP:
12065         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
12066         if ((x = cmcfm()) < 0) return(x);
12067         DeleteStartupFile = (y != 0) ? 0 : 1;
12068         return(success = 1);
12069
12070       case XYTMPDIR:
12071         x = cmdir("Name of temporary directory","",&s,xxstring);
12072         if (x == -3)
12073           s = "";
12074         else if (x < 0)
12075           return(x);
12076         if ((x = cmcfm()) < 0) return(x);
12077         makestr(&tempdir,s);
12078         return(tempdir ? 1 : 0);
12079
12080 #ifndef NOXFER
12081       case XYDEST:                      /* DESTINATION */
12082         return(setdest());
12083 #endif /* NOXFER */
12084
12085 #ifndef NOPUSH
12086 #ifndef NOFRILLS
12087
12088 /* Editor, Browser, and FTP Client */
12089
12090       case XYEDIT:                      /* EDITOR */
12091 #ifdef IKSD
12092         if (inserver) {
12093             printf("?Sorry, command disabled.\r\n");
12094             return(success = 0);
12095         }
12096 #endif /* IKSD */
12097 #ifdef CK_APC
12098         /* Don't let this be set remotely */
12099         if (apcactive == APC_LOCAL ||
12100             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12101           return(success = 0);
12102 #endif /* CK_APC */
12103
12104 #ifdef OS2ORUNIX
12105         {
12106             char *p = getenv("PATH");
12107             char *e;
12108             e = editor[0] ? (char *) editor : getenv("EDITOR");
12109             if (!e) e = "";
12110             if (p)
12111               x = cmifip("Name of preferred editor",e,&s,&y,0,p,xxstring);
12112             else
12113               x = cmifi("Full path of preferred editor",e,&s,&y,xxstring);
12114             if (x < 0 && x != -3)
12115               return(x);
12116         }
12117 #else
12118 #ifdef VMS
12119         if ((y = cmtxt("DCL command for editing", "edit", &s, NULL)) < 0) {
12120             if (x != -3)
12121               return(x);
12122         }
12123 #else
12124         if ((x = cmifi("Full path of preferred editor","",&s,&y,xxstring))<0) {
12125             if (x != -3)
12126               return(x);
12127         }
12128 #endif /* VMS */
12129 #endif /* OS2ORUNIX */
12130 #ifdef VMS
12131         ckstrncpy(editor,s,CKMAXPATH);
12132         editopts[0] = NUL;
12133 #else
12134         if (y != 0) {
12135             printf("?A single file please\n");
12136             return(-2);
12137         }
12138         ckstrncpy(line,s,LINBUFSIZ);
12139         if ((x = cmtxt("editor command-line options","",&s,NULL)) < 0)
12140           return(x);
12141         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12142         if ((z = cmcfm()) < 0) return(z);
12143         if (line[0]) {
12144             zfnqfp(line,CKMAXPATH,editor);
12145             ckstrncpy(editopts,tmpbuf,128);
12146         } else {
12147             editor[0] = NUL;
12148             editopts[0] = NUL;
12149         }
12150 #endif /* VMS */
12151         return(success = 1);
12152
12153 #ifndef NOFTP
12154 #ifndef SYSFTP
12155 #ifdef TCPSOCKET
12156       case XYFTPX:
12157         return(dosetftp());             /* SET FTP */
12158 #endif /* TCPSOCKET */
12159 #endif /* SYSFTP */
12160 #endif /* NOFTP */
12161
12162 #ifdef BROWSER
12163 #ifndef NOFTP
12164 #ifdef SYSFTP
12165       case XYFTP:                       /* SET FTP-CLIENT */
12166 #endif /* SYSFTP */
12167 #endif /* NOFTP */
12168       case XYBROWSE:                    /* SET BROWSER */
12169         {
12170             char *p = getenv("PATH");
12171             char *app = (char *) browser, *opts = (char *) browsopts;
12172 #ifndef NOFTP
12173 #ifdef SYSFTP
12174             extern char ftpapp[], ftpopts[];
12175             if (xx == XYFTP) {
12176                 app = (char *)ftpapp;
12177                 opts = (char *)ftpopts;
12178             }
12179 #endif /* SYSFTP */
12180 #endif /* NOFTP */
12181 #ifdef IKSD
12182             if (inserver) {
12183                 printf("?Sorry, command disabled.\r\n");
12184                 return(success = 0);
12185             }
12186 #endif /* IKSD */
12187 #ifdef CK_APC
12188             /* Don't let this be set remotely */
12189             if (apcactive == APC_LOCAL ||
12190                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12191               return(success = 0);
12192 #endif /* CK_APC */
12193 #ifdef OS2ORUNIX
12194             if (p)
12195               x = cmifip(xx == XYBROWSE ?
12196                          "Name of preferred browser" :
12197                          "Name of preferred ftp client",
12198 #ifdef OS2
12199                          xx == XYFTP ? "ftp.exe" : ""
12200 #else
12201                          xx == XYFTP ? "ftp" : ""
12202 #endif /* OS2 */
12203                          ,&s,&y,0,p,xxstring
12204                          );
12205             else
12206               x = cmifi(xx == XYBROWSE ?
12207                         "Full path of preferred browser" :
12208                         "Full path of preferred ftp client",
12209                         "",&s,&y,xxstring
12210                         );
12211             if (x < 0 && x != -3)
12212               return(x);
12213 #else
12214 #ifdef VMS
12215             if ((x = cmtxt("DCL command to start your preferred Web browser",
12216                            "", &s, NULL)) < 0) {
12217                 if (x != -3)
12218                   return(x);
12219             }
12220 #else
12221             if ((x = cmifi("Full path of preferred browser","",&s,&y,xxstring)
12222                  ) < 0) {
12223                 if (x != -3)
12224                   return(x);
12225             }
12226 #endif /* VMS */
12227 #endif /* OS2ORUNIX */
12228 #ifdef VMS
12229             ckstrncpy(app,s,CKMAXPATH);
12230             *opts = NUL;
12231 #else
12232             if (y != 0) {
12233                 printf("?A single file please\n");
12234                 return(-2);
12235             }
12236             ckstrncpy(line,s,LINBUFSIZ);
12237             if ((x = cmtxt(xx == XYBROWSE ?
12238                            "browser command-line options" :
12239                            "ftp client command-line options",
12240                            "",&s,NULL)
12241                  ) < 0)
12242               return(x);
12243             ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12244             if ((z = cmcfm()) < 0) return(z);
12245             if (line[0]) {
12246                 zfnqfp(line,CKMAXPATH,app);
12247                 ckstrncpy(opts, tmpbuf, 128);
12248             } else {
12249                 *app = NUL;
12250                 *opts = NUL;
12251             }
12252 #endif /* VMS */
12253             return(success = 1);
12254         }
12255 #endif /* BROWSER */
12256 #endif /* NOFRILLS */
12257 #endif /* NOPUSH */
12258
12259 #ifdef CK_CTRLZ
12260       case XYEOF: {                     /* SET EOF */
12261           extern int eofmethod; extern struct keytab eoftab[];
12262           if ((x = cmkey(eoftab,3,"end-of-file detection method","",
12263                          xxstring)) < 0)
12264             return(x);
12265           if ((y = cmcfm()) < 0)
12266             return(y);
12267           eofmethod = x;
12268           return(success = 1);
12269       }
12270 #endif /* CK_CTRLZ */
12271
12272 #ifdef SESLIMIT
12273       case XYLIMIT: {  /* Session-Limit (length of session in seconds) */
12274           extern int seslimit;
12275 #ifdef OS2
12276           extern int downloaded;
12277 #endif /* OS2 */
12278           y = cmnum("Maximum length of session, seconds","0",10,&x,xxstring);
12279           if (inserver &&
12280 #ifdef IKSDCONF
12281               iksdcf
12282 #else
12283               1
12284 #endif /* IKSDCONF */
12285 #ifdef OS2
12286                || downloaded
12287 #endif /* OS2 */
12288               ) {
12289               if ((z = cmcfm()) < 0)
12290                 return(z);
12291               printf("?Sorry, command disabled.\r\n");
12292               return(success = 0);
12293           }
12294           return(setnum(&seslimit,x,y,86400));
12295       }
12296 #endif /* SESLIMIT */
12297
12298       case XYRELY: {                    /* SET RELIABLE */
12299           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12300             return(x);
12301           if ((y = cmcfm()) < 0) return(y);
12302           reliable = x;
12303           setreliable = (x != SET_AUTO);
12304           debug(F101,"SET RELIABLE reliable","",reliable);
12305           return(success = 1);
12306       }
12307
12308 #ifdef STREAMING
12309       case XYSTREAM: {                  /* SET STREAMING */
12310           extern int streamrq;
12311           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12312             return(x);
12313           if ((y = cmcfm()) < 0) return(y);
12314           streamrq = x;
12315           return(success = 1);
12316       }
12317 #endif /* STREAMING */
12318
12319 #ifdef CKSYSLOG
12320       case XYSYSL: {
12321           if ((x = cmkey(syslogtab,nsyslog,"","",xxstring)) < 0)
12322             return(x);
12323           if ((y = cmcfm()) < 0) return(y);
12324 #ifdef IKSD
12325           if (inserver &&
12326 #ifdef IKSDCONF
12327               iksdcf
12328 #else
12329               1
12330 #endif /* IKSDCONF */
12331               ) {
12332               printf("?Sorry, command disabled.\n");
12333               return(success = 0);
12334           }
12335 #endif /* IKSD */
12336 #ifdef CK_APC
12337           /* Don't let this be set remotely */
12338           if (apcactive == APC_LOCAL ||
12339               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12340             return(success = 0);
12341 #endif /* CK_APC */
12342           ckxsyslog = x;
12343           return(success = 1);
12344       }
12345 #endif /* CKSYSLOG */
12346
12347 #ifdef TLOG
12348       case XYTLOG: {                    /* SET TRANSACTION-LOG */
12349           extern int tlogsep;
12350           if ((x = cmkey(vbtab,nvb,"","verbose",xxstring)) < 0)
12351             return(x);
12352           if (x == 0) {
12353               if ((y = cmtxt("field separator",",",&s,NULL)) < 0) return(y);
12354               s = brstrip(s);
12355               if (*s) {
12356                   if (s[1]) {
12357                       printf("?A single character, please.\n");
12358                       return(-9);
12359                   } else if ((*s >= '0' && *s <= '9') ||
12360                              (*s >= 'A' && *s <= 'Z') ||
12361                              (*s >= 'a' && *s <= 'z')) {
12362                       printf("?A non-alphanumeric character, please.\n");
12363                       return(-9);
12364                   } else
12365                     tlogsep = *s;
12366               }
12367           } else {
12368               if ((y = cmcfm()) < 0) return(y);
12369           }
12370 #ifdef IKSD
12371           if (inserver && isguest) {
12372               printf("?Sorry, command disabled.\n");
12373               return(success = 0);
12374           }
12375 #endif /* IKSD */
12376 #ifdef CK_APC
12377           /* Don't let this be set remotely */
12378           if (apcactive == APC_LOCAL ||
12379               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12380             return(success = 0);
12381 #endif /* CK_APC */
12382           tlogfmt = x;
12383           return(success = 1);
12384       }
12385 #endif /* TLOG */
12386
12387       case XYCLEAR: {                   /* SET CLEARCHANNEL */
12388           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12389             return(x);
12390           if ((y = cmcfm()) < 0) return(y);
12391           clearrq = x;
12392           return(success = 1);
12393       }
12394
12395 #ifdef CK_AUTHENTICATION
12396       case XYAUTH: {                    /* SET AUTHENTICATION */
12397 #ifdef CK_KERBEROS
12398           int kv = 0;
12399           extern struct krb_op_data krb_op;
12400 #endif /* CK_KERBEROS */
12401           char * p = NULL;
12402           if ((x =
12403                cmkey(setauth,nsetauth,"authentication type","",xxstring)) < 0)
12404             return(x);
12405           switch (x) {
12406 #ifdef CK_KERBEROS
12407             case AUTH_KRB4: kv = 4; break; /* Don't assume values are same */
12408             case AUTH_KRB5: kv = 5; break;
12409 #endif /* CK_KERBEROS */
12410 #ifdef CK_SRP
12411             case AUTH_SRP: break;
12412 #endif /* CK_SRP */
12413 #ifdef CK_SSL
12414             case AUTH_SSL:
12415             case AUTH_TLS:
12416               break;
12417 #endif /* CK_SSL */
12418             default:
12419               printf("?Authorization type not supported yet - \"%s\"\n",
12420                      atmbuf);
12421               return(-9);
12422           }
12423 #ifdef IKSD
12424           if (inserver &&
12425 #ifdef IKSDCONF
12426               iksdcf
12427 #else
12428               1
12429 #endif /* IKSDCONF */
12430               ) {
12431               if ((y = cmcfm()) < 0) return(y);
12432               printf("?Sorry, command disabled.\n");
12433               return(success = 0);
12434           }
12435 #endif /* IKSD */
12436 #ifdef CK_APC
12437           /* Don't let this be set remotely */
12438           if (apcactive == APC_LOCAL ||
12439               apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)) {
12440               if ((y = cmcfm()) < 0) return(y);
12441               return(success = 0);
12442           }
12443 #endif /* CK_APC */
12444
12445           switch(x) {
12446 #ifdef CK_KERBEROS
12447             case AUTH_KRB4:
12448             case AUTH_KRB5: {
12449                 if ((x = cmkey(kv == 4 ? k4tab : k5tab,
12450                                kv == 4 ? nk4tab : nk5tab,
12451                                "Kerberos parameter","",xxstring)) < 0) {
12452                     return(x);
12453                 }
12454                 s = "";
12455                 switch (x) {
12456 #ifdef KRB4
12457                   case XYKRBDBG:
12458                     if (kv == 4) {
12459                         if ((y = seton(&k4debug)) < 0)
12460                           return(y);
12461 #ifdef NT
12462                         ck_krb4_debug(k4debug);
12463 #endif /* NT */
12464                     } else {
12465                         return(-9);
12466                     }
12467                     break;
12468 #endif /* KRB4 */
12469                   case XYKRBLIF:
12470                     if ((y = cmnum("TGT lifetime","600",10,&z,xxstring)) < 0)
12471                       return(y);
12472                     break;
12473                   case XYKRBPRE:
12474                     if (kv == 4) {
12475                         if ((y = seton(&krb4_d_preauth)) < 0)
12476                           return(y);
12477                     } else {
12478                         return(-9);
12479                     }
12480                     break;
12481                   case XYKRBINS:
12482                     if ((y = cmtxt("Instance name","",&s,xxstring)) < 0)
12483                       return(y);
12484                     break;
12485                   case XYKRBFWD:
12486                     if (kv == 5) {
12487                         if ((y = seton(&krb5_d_forwardable)) < 0)
12488                           return(y);
12489                     } else {
12490                         return(-9);
12491                     }
12492                     break;
12493                   case XYKRBPRX:
12494                     if (kv == 5) {
12495                         if ((y = seton(&krb5_d_proxiable)) < 0)
12496                           return(y);
12497                     } else {
12498                         return(-9);
12499                     }
12500                     break;
12501                   case XYKRBRNW:
12502                     if ((y = cmnum("TGT renewable lifetime",
12503                                    "0",10,&z,xxstring)) < 0)
12504                       return(y);
12505                     break;
12506                   case XYKRBADR:
12507                     if (kv == 5) {
12508                         if ((y = seton(&krb5_checkaddrs)) < 0)
12509                           return(y);
12510                     } else {
12511                         if ((y = seton(&krb4_checkaddrs)) < 0)
12512                           return(y);
12513                     }
12514                     break;
12515                   case XYKRBNAD:
12516                     if (kv == 5) {
12517                         if ((y = seton(&krb5_d_no_addresses)) < 0)
12518                           return(y);
12519                     }
12520                     break;
12521                   case XYKRBADD:
12522                     if (kv == 5) {
12523                         char * tmpaddrs[KRB5_NUM_OF_ADDRS];
12524                         for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
12525                           tmpaddrs[i] = NULL;
12526
12527                         if ((y =
12528                              cmfld("List of IP addresses","",&s,xxstring)) < 0)
12529                           return(y);
12530                         makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
12531                         if ((y = cmcfm()) < 0) {
12532                             for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
12533                                 if (tmpaddrs[i] != NULL)
12534                                   free(tmpaddrs[i]);
12535                             }
12536                             return(y);
12537                         }
12538                         for (i = 0;
12539                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
12540                              i++) {
12541                             if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
12542                                 printf("invalid ip address: %s\n",
12543                                        tmpaddrs[i]);
12544                                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
12545                                     if (tmpaddrs[i] != NULL)
12546                                       free(tmpaddrs[i]);
12547                                 }
12548                                 return(-9);
12549                             }
12550                         }
12551                         for (i = 0;
12552                              i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];
12553                              i++) {
12554                             if (krb5_d_addrs[i])
12555                               free(krb5_d_addrs[i]);
12556                             krb5_d_addrs[i] = NULL;
12557                         }
12558                         for (i = 0;
12559                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
12560                              i++) {
12561                             krb5_d_addrs[i] = tmpaddrs[i];
12562                             tmpaddrs[i] = NULL;
12563                         }
12564                         krb5_d_addrs[i] = NULL;
12565                         return(success = 1);
12566                     }
12567                     break;
12568
12569                   case XYKRBGET:
12570                     if (kv == 5) {
12571                         if ((y = seton(&krb5_autoget)) < 0)
12572                           return(y);
12573                     } else {
12574                         if ((y = seton(&krb4_autoget)) < 0)
12575                           return(y);
12576                     }
12577                     break;
12578                   case XYKRBDEL:
12579                     if ((z = cmkey(kdestab,nkdestab,
12580                                    "Auto Destroy Tickets",
12581                                    "never",xxstring)) < 0)
12582                       return(z);
12583                     break;
12584                   case XYKRBPR:
12585                     if ((y = cmtxt("User ID",uidbuf,&s,xxstring)) < 0)
12586                       return(y);
12587                     break;
12588                   case XYKRBRL:
12589                     if ((y = cmtxt("Name of realm","",&s,xxstring)) < 0)
12590                       return(y);
12591                     break;
12592                   case XYKRBKTB:
12593                     y = cmifi("Filename","",&s,&z,xxstring);
12594                     if (y != -3) {
12595                        if (y < 0)
12596                          return(y);
12597                        if (z) {
12598                          printf("?Wildcards not allowed\n");
12599                          return(-9);
12600                        }
12601                     }
12602                     break;
12603                   case XYKRBCC:
12604                     if ((y = cmofi("Filename","",&s,xxstring)) < 0)
12605                       return(y);
12606                     break;
12607                   case XYKRBSRV:
12608                     if ((y = cmtxt("Name of service to use in ticket",
12609                                    (kv == 4 ? "rcmd" : "host"),
12610                                    &s,
12611                                    xxstring
12612                                    )) < 0)
12613                       return(y);
12614                     break;
12615                   case XYKRBK5K4:
12616                     if (kv == 5) {
12617                         if ((y = seton(&krb5_d_getk4)) < 0)
12618                           return(y);
12619                     } else {
12620                         return(-9);
12621                     }
12622                     break;
12623                   case XYKRBPRM:        /* Prompt */
12624                     if ((z = cmkey(krbprmtab,2,"","",xxstring)) < 0)
12625                       return(z);
12626                     if ((y = cmtxt((z == KRB_PW_PRM) ?
12627   "Text of prompt;\nmay contain \"%s\" to be replaced by principal name" :
12628   "Text of prompt",
12629                                    "",
12630                                    &s,
12631                                    xxstring
12632                                    )
12633                          ) < 0)
12634                       return(y);
12635                     break;
12636                 }
12637                 ckstrncpy(line,s,LINBUFSIZ);
12638                 s = line;
12639                 if ((y = cmcfm()) < 0)
12640                   return(y);
12641 #ifdef IKSD
12642                 if (inserver &&
12643 #ifdef IKSDCONF
12644                     iksdcf
12645 #else /* IKSDCONF */
12646                     1
12647 #endif /* IKSDCONF */
12648                     )
12649                   return(success = 0);
12650 #endif /* IKSD */
12651
12652                 switch (x) {            /* Copy value to right place */
12653                   case XYKRBLIF:        /* Lifetime */
12654                     if (kv == 4)
12655                       krb4_d_lifetime = z;
12656                     else
12657                       krb5_d_lifetime = z;
12658                     break;
12659                   case XYKRBRNW:
12660                     if (kv == 5)
12661                       krb5_d_renewable = z;
12662                     break;
12663                   case XYKRBPR:         /* Principal */
12664                     s = brstrip(s);     /* Strip braces around. */
12665                     if (kv == 4)
12666                       makestr(&krb4_d_principal,s);
12667                     else
12668                       makestr(&krb5_d_principal,s);
12669                     break;
12670                   case XYKRBINS:        /* Instance */
12671                     if (kv == 4)
12672                       makestr(&krb4_d_instance,s);
12673                     else
12674                       makestr(&krb5_d_instance,s);
12675                     break;
12676                   case XYKRBRL:         /* Realm */
12677                     if (kv == 4)
12678                       makestr(&krb4_d_realm,s);
12679                     else
12680                       makestr(&krb5_d_realm,s);
12681                     break;
12682                   case XYKRBKTB:        /* Key Table */
12683                     if (kv == 4)
12684                       makestr(&k4_keytab,s);
12685                     else
12686                       makestr(&k5_keytab,s);
12687                     break;
12688                   case XYKRBCC:         /* Credentials cache */
12689                     makestr(&krb5_d_cc,s);
12690                     break;
12691                   case XYKRBSRV:        /* Service Name */
12692                     if (kv == 4)
12693                       makestr(&krb4_d_srv,s);
12694                     else
12695                       makestr(&krb5_d_srv,s);
12696                     break;
12697                   case XYKRBDEL:
12698                     if (kv == 5)
12699                       krb5_autodel = z;
12700                     else
12701                       krb4_autodel = z;
12702                     break;
12703                   case XYKRBPRM:        /* Prompt */
12704                     s = brstrip(s);
12705                     switch (z) {
12706                       case KRB_PW_PRM: { /* Password */
12707                           /* Check that there are no more than */
12708                           /* two % fields and % must followed by 's'. */
12709                           int i,n,len;
12710                           len = strlen(s);
12711                           for (i = 0, n = 0; i < len; i++) {
12712                               if (s[i] == '%') {
12713                                   if (s[i+1] != '%') {
12714                                       if (s[i+1] != 's') {
12715                                           printf(
12716                                            "Only %%s fields are permitted.\n"
12717                                                  );
12718                                           return(-9);
12719                                       }
12720                                       if (++n > 2) {
12721                                           printf(
12722                                       "Only two %%s fields are permitted.\n");
12723                                           return(-9);
12724                                       }
12725                                   }
12726                                   i++;
12727                               }
12728                           }
12729                           if (kv == 5)
12730                             makestr(&k5pwprompt,s);
12731                           else
12732                             makestr(&k4pwprompt,s);
12733                           break;
12734                       }
12735                       case KRB_PR_PRM: { /* Principal */
12736                           /* Check to make sure there are no % fields */
12737                           int i,len;
12738                           len = strlen(s);
12739                           for (i = 0; i < len; i++) {
12740                               if (s[i] == '%') {
12741                                   if (s[i+1] != '%') {
12742                                       printf(
12743                                   "%% fields are not used in this command.\n");
12744                                       return(-9);
12745                                   }
12746                                   i++;
12747                               }
12748                           }
12749                           if (kv == 5)
12750                             makestr(&k5prprompt,s);
12751                           else
12752                             makestr(&k4prprompt,s);
12753                           break;
12754                       }
12755                     }
12756                 }
12757                 break;
12758             }
12759 #endif /* CK_KERBEROS */
12760 #ifdef CK_SRP
12761             case AUTH_SRP: {
12762                 if ((x = cmkey(srptab, nsrptab,
12763                                "SRP parameter","",xxstring)) < 0) {
12764                     return(x);
12765                 }
12766                 s = "";
12767                 switch (x) {
12768                   case XYSRPPRM:        /* Prompt */
12769                     if ((z = cmkey(srpprmtab,1,"","",xxstring)) < 0)
12770                       return(z);
12771                     if ((y = cmtxt(
12772   "Text of prompt;\nmay contain one \"%s\" to be replaced by the username",
12773                                    "",
12774                                    &s,
12775                                    xxstring
12776                                    )
12777                          ) < 0)
12778                       return(y);
12779                     break;
12780                 }
12781                 ckstrncpy(line,s,LINBUFSIZ);
12782                 s = line;
12783                 if ((y = cmcfm()) < 0)
12784                   return(y);
12785                 switch (x) {            /* Copy value to right place */
12786                   case XYSRPPRM:        /* Prompt */
12787                     s = brstrip(s);
12788                     switch (z) {
12789                       case SRP_PW_PRM: { /* Password */
12790                           /* Check %s fields */
12791                           int i,n,len;
12792                           len = strlen(s);
12793                           for (i = 0, n = 0; i < len; i++) {
12794                               if (s[i] == '%') {
12795                                   if (s[i+1] != '%') {
12796                                       if (s[i+1] != 's') {
12797                                           printf(
12798                                           "Only %%s fields are permitted.\n");
12799                                           return(-9);
12800                                       }
12801                                       if (++n > 1) {
12802                                           printf(
12803                                        "Only one %%s field is permitted.\n");
12804                                           return(-9);
12805                                       }
12806                                   }
12807                                   i++;
12808                               }
12809                           }
12810                           makestr(&srppwprompt,s);
12811                           break;
12812                       }
12813                     }
12814                 }
12815                 break;
12816             }
12817 #endif /* CK_SRP */
12818 #ifdef CK_SSL
12819             case AUTH_SSL:
12820             case AUTH_TLS: {
12821                 if ((z = cmkey(ssltab, nssltab,
12822                            (x == AUTH_SSL ? "SSL parameter" : "TLS parameter"),
12823                            "",xxstring)) < 0)
12824                   return(z);
12825                 s = "";
12826                 switch (z) {
12827                   case XYSSLRCFL:       /* SSL/TLS RSA Certs file */
12828                   case XYSSLRCCF:       /* SSL/TLS RSA Certs Chain file */
12829                   case XYSSLRKFL:       /* SSL/TLS RSA Key File */
12830                   case XYSSLDCFL:       /* SSL/TLS DSA Certs file */
12831                   case XYSSLDCCF:       /* SSL/TLS DSA Certs Chain file */
12832                   case XYSSLDKFL:       /* SSL/TLS DH Key File */
12833                   case XYSSLDPFL:       /* SSL/TLS DH Param File */
12834                   case XYSSLCRL:        /* SSL/TLS CRL File */
12835                   case XYSSLVRFF:       /* SSL/TLS Verify File */
12836                   case XYSSLRND:        /* SSL/TLS Random File */
12837                     y = cmifi("Filename","",&s,&x,xxstring);
12838                     if (y != -3) {
12839                         if (y < 0)
12840                           return(y);
12841                         if (x) {
12842                             printf("?Wildcards not allowed\n");
12843                             return(-9);
12844                         }
12845                     }
12846                     ckstrncpy(line,s,LINBUFSIZ);
12847                     s = line;
12848                     s = brstrip(s);
12849                     if ((y = cmcfm()) < 0)
12850                       return(y);
12851                     switch (z) {
12852                       case XYSSLRCFL:   /* SSL/TLS RSA Certs file */
12853                         if (!s[0] && ssl_rsa_cert_file) {
12854                             free(ssl_rsa_cert_file);
12855                             ssl_rsa_cert_file = NULL;
12856                         } else if (s[0]) {
12857                             makestr(&ssl_rsa_cert_file,s);
12858                             if (!ssl_rsa_key_file)
12859                               makestr(&ssl_rsa_key_file,s);
12860                         }
12861                         break;
12862                       case XYSSLRCCF:   /* SSL/TLS RSA Certs Chain file */
12863                           if (!s[0] && ssl_rsa_cert_chain_file) {
12864                               free(ssl_rsa_cert_chain_file);
12865                               ssl_rsa_cert_chain_file = NULL;
12866                           } else if (s[0]) {
12867                               makestr(&ssl_rsa_cert_chain_file,s);
12868                           }
12869                           break;
12870                       case XYSSLRKFL:   /* SSL/TLS RSA Key File */
12871                         if (!s[0] && ssl_rsa_key_file) {
12872                             free(ssl_rsa_key_file);
12873                             ssl_rsa_key_file = NULL;
12874                         } else if (s[0]) {
12875                             makestr(&ssl_rsa_key_file,s);
12876                         }
12877                         break;
12878                       case XYSSLDCFL:   /* SSL/TLS DSA Certs file */
12879                         if (!s[0] && ssl_dsa_cert_file) {
12880                             free(ssl_dsa_cert_file);
12881                             ssl_dsa_cert_file = NULL;
12882                         } else if (s[0]) {
12883                             makestr(&ssl_dsa_cert_file,s);
12884                             if (!ssl_dh_key_file)
12885                               makestr(&ssl_dh_key_file,s);
12886                         }
12887                         break;
12888                       case XYSSLDCCF:   /* SSL/TLS DSA Certs Chain file */
12889                           if (!s[0] && ssl_dsa_cert_chain_file) {
12890                               free(ssl_dsa_cert_chain_file);
12891                               ssl_dsa_cert_chain_file = NULL;
12892                           } else if (s[0]) {
12893                               makestr(&ssl_dsa_cert_chain_file,s);
12894                           }
12895                           break;
12896                       case XYSSLDKFL:   /* SSL/TLS DH Key File */
12897                         if (!s[0] && ssl_dh_key_file) {
12898                             free(ssl_dh_key_file);
12899                             ssl_dh_key_file = NULL;
12900                         } else if (s[0]) {
12901                             makestr(&ssl_dh_key_file,s);
12902                         }
12903                         break;
12904                       case XYSSLDPFL:   /* SSL/TLS DH Param File */
12905                         if (!s[0] && ssl_dh_param_file) {
12906                             free(ssl_dh_param_file);
12907                             ssl_dh_param_file = NULL;
12908                         } else if (s[0]) {
12909                             makestr(&ssl_dh_param_file,s);
12910                         }
12911                         break;
12912                       case XYSSLCRL:    /* SSL/TLS CRL File */
12913                         if (!s[0] && ssl_crl_file) {
12914                             free(ssl_crl_file);
12915                             ssl_crl_file = NULL;
12916                         } else if (s[0]) {
12917                             makestr(&ssl_crl_file,s);
12918                         }
12919                         break;
12920                       case XYSSLVRFF:   /* SSL/TLS Verify File */
12921                         if (!s[0] && ssl_verify_file) {
12922                             free(ssl_verify_file);
12923                             ssl_verify_file = NULL;
12924                         } else if (s[0]) {
12925                             makestr(&ssl_verify_file,s);
12926                         }
12927                         break;
12928                       case XYSSLRND:    /* SSL/TLS Random File */
12929                         if (!s[0] && ssl_rnd_file) {
12930                             free(ssl_rnd_file);
12931                             ssl_rnd_file = NULL;
12932                         } else if (s[0]) {
12933                             makestr(&ssl_rnd_file,s);
12934                         }
12935                         break;
12936                     }
12937                     break;
12938
12939                   case XYSSLCRLD:
12940                   case XYSSLVRFD: {
12941                     char * d = NULL;
12942                     if (z == XYSSLVRFD)
12943                       d= getenv("SSL_CERT_DIR");
12944                     if (d == NULL)
12945                         d = "";
12946                     if ((y = cmdir("Directory",d,&s,xxstring)) < 0)
12947                       if (y != -3)
12948                         return(y);
12949                     ckstrncpy(line,s,LINBUFSIZ);
12950                     s = line;
12951                     s = brstrip(s);
12952                     if ((y = cmcfm()) < 0)
12953                       return(y);
12954                     switch(z) {
12955                       case XYSSLCRLD:
12956                         if (!s[0] && ssl_crl_dir) {
12957                             free(ssl_crl_dir);
12958                             ssl_crl_dir = NULL;
12959                         } else if (s[0]) {
12960                             makestr(&ssl_crl_dir,s);
12961                         }
12962                         break;
12963                       case XYSSLVRFD:
12964                         if (!s[0] && ssl_verify_dir) {
12965                             free(ssl_verify_dir);
12966                             ssl_verify_dir = NULL;
12967                         } else if (s[0]) {
12968                             makestr(&ssl_verify_dir,s);
12969                         }
12970                         break;
12971                     }
12972                     break;
12973                   }
12974                   case XYSSLCOK:        /* SSL/TLS Certs-Ok flag */
12975                     if ((y = seton(&ssl_certsok_flag)) < 0)
12976                       return(y);
12977                     break;
12978                   case XYSSLDBG:                /* SSL/TLS Debug flag */
12979                     if ((y = seton(&ssl_debug_flag)) < 0)
12980                       return(y);
12981                     break;
12982                   case XYSSLON:         /* SSL/TLS Only flag */
12983                     switch (x) {
12984                       case AUTH_SSL:
12985                         if ((y = seton(&ssl_only_flag)) < 0)
12986                           return(y);
12987                         break;
12988                       case AUTH_TLS:
12989                         if ((y = seton(&tls_only_flag)) < 0)
12990                           return(y);
12991                         break;
12992                     }
12993                     break;
12994                   case XYSSLVRB:        /* SSL/TLS Verbose flag */
12995                     if ((y = seton(&ssl_verbose_flag)) < 0)
12996                       return(y);
12997                     break;
12998                   case XYSSLVRF:        /* SSL/TLS Verify flag */
12999                     if ((x = cmkey(sslvertab, nsslvertab,
13000                                    "SSL/TLS verify mode",
13001                                    "peer-cert",xxstring)) < 0)
13002                       return(x);
13003                     if ((y = cmcfm()) < 0)
13004                       return(y);
13005                     ssl_verify_flag = x;
13006                     break;
13007                   case XYSSLDUM:
13008                     if ((y = seton(&ssl_dummy_flag)) < 0)
13009                       return(y);
13010                     break;
13011                   case XYSSLCL: {               /* SSL/TLS Cipher List */
13012 #ifdef COMMENT
13013                       /* This code is used to generate a colon delimited */
13014                       /* list of the ciphers currently in use to be used */
13015                       /* as the default for cmtxt().  However, a better  */
13016                       /* default is simply the magic keyword "ALL".      */
13017                       CHAR def[1024] = "";
13018                       if (ssl_con != NULL) {
13019                           CHAR * p = NULL, *q = def;
13020                           int i, len;
13021
13022                           for (i = 0; ; i++) {
13023                               p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
13024                               if (p == NULL)
13025                                 break;
13026                               len = strlen(p);
13027                               if (q+len+1 >= def+1024)
13028                                 break;
13029                               if (i != 0)
13030                                 *q++ = ':';
13031                               strcpy(q,p);
13032                               q += len;
13033                           }
13034                       }
13035 #endif /* COMMENT */
13036                       char * p = getenv("SSL_CIPHER");
13037                       if (!p)
13038                         p = "ALL";
13039                       if ((y = cmtxt(
13040                     "Colon-delimited list of ciphers or ALL (case-sensitive)",
13041                                      p,
13042                                      &s,
13043                                      xxstring
13044                                      )
13045                            ) < 0)
13046                         return(y);
13047                       makestr(&ssl_cipher_list,s);
13048                       if (ssl_con == NULL) {
13049                           SSL_library_init();
13050                           ssl_ctx = (SSL_CTX *)
13051                             SSL_CTX_new((SSL_METHOD *)TLSv1_method());
13052                           if (ssl_ctx != NULL)
13053                             ssl_con= (SSL *) SSL_new(ssl_ctx);
13054                       }
13055                       if (ssl_con) {
13056                           SSL_set_cipher_list(ssl_con,ssl_cipher_list);
13057                       }
13058                       break;
13059                   }
13060                 }
13061                 break;
13062             }
13063 #endif /* CK_SSL */
13064             default:
13065               break;
13066           }
13067           return(success = 1);
13068       }
13069 #endif /* CK_AUTHENTICATION */
13070
13071 #ifndef NOSPL
13072       case XYFUNC:
13073         if ((x = cmkey(functab,nfunctab,"","diagnostics",xxstring)) < 0)
13074           return(x);
13075         switch (x) {
13076           case FUNC_DI: return(seton(&fndiags));
13077           case FUNC_ER: return(seton(&fnerror));
13078           default:      return(-2);
13079         }
13080 #endif /* NOSPL */
13081
13082       case XYSLEEP:                     /* SET SLEEP / PAUSE */
13083         if ((x = cmkey(sleeptab,1,"","cancellation",xxstring)) < 0)
13084           return(x);
13085         return(seton(&sleepcan));
13086
13087       case XYCD:                        /* SET CD */
13088         if ((x = cmkey(cdtab,ncdtab,"","",xxstring)) < 0)
13089           return(x);
13090         switch (x) {
13091           case XYCD_H: {                /* SET CD HOME */
13092               extern char * myhome;
13093               if ((y = cmdir("Directory name",zhome(),&s,xxstring)) < 0)
13094                 return(y);
13095               makestr(&myhome,s);
13096               return(success = 1);
13097           }
13098           case XYCD_M:                  /* SET CD MESSAGE */
13099             if ((x = cmkey(cdmsg,ncdmsg,"","",xxstring)) < 0)
13100               return(x);
13101             if (x == 2) {               /* CD MESSAGE FILE */
13102                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
13103                   return(x);
13104                 if (!*s) {
13105                     s = NULL;
13106 #ifndef NOXFER
13107                     srvcdmsg = 0;
13108 #endif /* NOXFER */
13109                 }
13110                 makestr(&cdmsgstr,s);
13111                 makelist(cdmsgstr,cdmsgfile,8);
13112                 return(success = 1);
13113             }
13114
13115             if ((y = cmcfm()) < 0) return(y); /* CD-MESSAGE ON/OFF */
13116 #ifndef NOXFER
13117             if (x > 0)
13118               srvcdmsg |= 2;
13119             else
13120               srvcdmsg &= 1;
13121 #endif /* NOXFER */
13122             return(success = 1);
13123
13124           case XYCD_P: {                /* SET CD PATH */
13125               extern char * ckcdpath;
13126               if ((x = cmtxt("CD PATH string","",&s,xxstring)) < 0)
13127                 return(x);
13128               makestr(&ckcdpath,s);
13129               return(success = 1);
13130           }
13131         }
13132
13133 #ifndef NOLOCAL
13134 #ifdef STOPBITS
13135       case XYSTOP:                      /* STOP-BITS */
13136         if ((x = cmkey(stoptbl,2,"Stop bits for serial device","",
13137                        xxstring)) < 0)
13138           return(x);
13139         if ((y = cmcfm()) < 0)
13140           return(y);
13141         if (x > 0 && x < 3) {
13142             stopbits = x;
13143 #ifdef TN_COMPORT
13144             if (network && istncomport()) {
13145                 tnsettings(-1, x);
13146                 return(success = 1);
13147             }
13148 #endif /* TN_COMPORT */
13149 #ifdef HWPARITY
13150             return(success = 1);
13151 #else /* HWPARITY */
13152             return(-2);
13153 #endif /* HWPARITY */
13154         } else
13155           return(-2);
13156 #endif /* STOPBITS */
13157
13158       case XYDISC: {
13159           extern int clsondisc;
13160           return(seton(&clsondisc));
13161       }
13162
13163       case XYSERIAL: {
13164           /* char c; */
13165           extern int cmask;
13166           if ((x = cmkey(sertbl,nsertbl,
13167                          "Serial device character size, parity, and stop bits",
13168                          "8N1", xxstring)) < 0)
13169             return(x);
13170           ckstrncpy(line,atmbuf,LINBUFSIZ); /* Associated keyword string */
13171           s = line;
13172           if ((y = cmcfm()) < 0)
13173             return(y);
13174           ckstrncpy(line,sernam[x],LINBUFSIZ);
13175           s = line;
13176           if (s[0] != '8' && s[0] != '7') /* Char size */
13177             return(-2);
13178           else
13179             z = s[0] - '0';
13180           if (isupper(s[1]))            /* Parity */
13181             s[1] = tolower(s[1]);
13182           if (s[2] != '1' && s[2] != '2') /* Stop bits */
13183             return(-2);
13184           else
13185             stopbits = s[2] - '0';
13186           if (z == 8) {                 /* 8 bits + parity (or not) */
13187               parity = 0;               /* Set parity */
13188               hwparity = (s[1] == 'n') ? 0 : s[1];
13189               setcmask(8);              /* Also set TERM BYTESIZE to 8 */
13190           } else {                      /* 7 bits plus parity */
13191               parity = (s[1] == 'n') ? 0 : s[1];
13192               hwparity = 0;
13193               setcmask(7);              /* Also set TERM BYTESIZE to 7 */
13194           }
13195 #ifdef TN_COMPORT
13196           if (network && !istncomport())
13197             tnsettings(parity, stopbits);
13198 #endif /* TN_COMPORT */
13199
13200           return(success = 1);          /* from SET SERIAL */
13201       }
13202
13203       case XYOPTS: {                    /* SET OPTIONS */
13204           extern int setdiropts();
13205           extern int settypopts();
13206 #ifdef CKPURGE
13207           extern int setpurgopts();
13208 #endif /* CKPURGE */
13209           if ((x = cmkey(optstab,noptstab,"for command","", xxstring)) < 0)
13210             return(x);
13211           switch (x) {
13212 #ifndef NOFRILLS
13213             case XXDEL:
13214               return(setdelopts());
13215 #endif /* NOFRILLS */
13216             case XXDIR:
13217               return(setdiropts());
13218             case XXTYP:
13219               return(settypopts());
13220 #ifdef CKPURGE
13221             case XXPURGE:
13222               return(setpurgopts());
13223 #endif /* CKPURGE */
13224             default:
13225               return(-2);
13226           }
13227       }
13228 #endif /* NOLOCAL */
13229 #ifndef NOXFER
13230       case XYQ8FLG: {
13231           extern int q8flag;
13232           return(seton(&q8flag));
13233       }
13234       case XYTIMER: {
13235           extern int asktimer;
13236           y = cmnum("Time limit for ASK command, seconds","0",10,&x,xxstring);
13237 #ifdef QNX16
13238           return(setnum(&asktimer,x,y,32767));
13239 #else
13240           return(setnum(&asktimer,x,y,86400));
13241 #endif /* QNX16 */
13242       }
13243       case XYFACKB: {
13244           extern int fackbug;
13245           return(seton(&fackbug));
13246       }
13247 #endif /* NOXFER */
13248
13249       case XYHINTS:
13250         return(seton(&hints));
13251
13252 #ifndef NOSPL
13253       case XYEVAL: {
13254           extern int oldeval;
13255           if ((x = cmkey(oldnew,2,"","", xxstring)) < 0)
13256             return(x);
13257           if ((y = cmcfm()) < 0)
13258             return(y);
13259           oldeval = x;
13260           return(success = 1);
13261       }
13262 #endif /* NOSPL */
13263
13264 #ifndef NOXFER
13265       case XYFACKP: {
13266           extern int fackpath;
13267           return(seton(&fackpath));
13268       }
13269 #endif /* NOXFER */
13270
13271       case XYQNXPL: {
13272           extern int qnxportlock;
13273           return(seton(&qnxportlock));
13274       }
13275
13276 #ifndef NOCMDL
13277 #ifdef IKSD
13278       case XYIKS: {
13279           int setiks();
13280           return(setiks());
13281       }
13282 #endif /* IKSD */
13283 #endif /* NOCMDL */
13284
13285 #ifdef CKROOT
13286       case XYROOT:
13287         return(dochroot());
13288 #endif /* CKROOT */
13289
13290 #ifndef NOSPL
13291 #ifndef NOSEXP
13292       case XYSEXP: {
13293           if ((x = cmkey(sexptab,3,"","", xxstring)) < 0)
13294             return(x);
13295           switch (x) {
13296             case 0:
13297               if ((x = cmkey(ooatab,3,"","automatic", xxstring)) < 0)
13298                 return(x);
13299               if ((y = cmcfm()) < 0)
13300                 return(y);
13301               sexpecho = x;
13302               break;
13303             case 1: {
13304                 int i, xx;
13305                 xx = sexpmaxdep;
13306                 if ((y = cmnum("Maximum recursion depth",
13307                                "1000",10,&x,xxstring)) < 0)
13308                   return(y);
13309                 z = setnum(&sexpmaxdep,x,y,-1);
13310                 if (z < 0)
13311                   return(z);
13312                 if (sxresult) {         /* Free old stack if allocated */
13313                     for (i = 0; i < xx; i++)
13314                       if (sxresult[i]) free(sxresult[i]);
13315                     free((char *)sxresult);
13316                     if (sxrlen) free((char *)sxrlen);
13317                     sxresult = NULL;
13318                     sxrlen = NULL;
13319                 }
13320                 break;
13321             }
13322             case 2:
13323               return(seton(&sexptrunc));
13324           }
13325           return(success = 1);
13326       }
13327 #endif /* NOSEXPL */
13328 #endif /* NOSPL */
13329
13330 #ifdef NEWFTP
13331       case XYGPR: {
13332           extern struct keytab gprtab[];
13333           extern int ftpget;
13334           if ((x = cmkey(gprtab,3,"","kermit", xxstring)) < 0)
13335             return(x);
13336           if ((y = cmcfm()) < 0)
13337             return(y);
13338           ftpget = x;
13339           return(success = 1);
13340       }
13341 #endif /* NEWFTP */
13342
13343 #ifdef ANYSSH
13344       case XYSSH:
13345         return(dosetssh());
13346 #endif /* ANYSHH */
13347
13348 #ifdef SFTP_BUILTIN
13349       case XYSFTP:
13350         return(dosetsftp());
13351 #endif /* SFTP_BUILTIN */
13352
13353 #ifdef LOCUS
13354       case XYLOCUS:
13355           if ((x = cmkey(locustab,nlocustab,"",
13356 #ifdef KUI
13357                          "ask"
13358 #else
13359                          "auto"
13360 #endif /* KUI */
13361                          ,xxstring)) < 0)
13362             return(x);
13363           if ((y = cmcfm()) < 0)
13364             return(y);
13365           if (x == 2 || x == 3) {       /* AUTO or ASK */
13366               setautolocus(x - 1);      /* Two forms of automatic locusing */
13367               /* setlocus(1,0); */      /* we're not changing the locus here */
13368           } else {                      /* LOCAL or REMOTE */
13369               setautolocus(0);          /* No automatic Locus changing */
13370               setlocus(x,0);            /* Set Locus as requested */
13371           }
13372           return(success = 1);
13373 #endif /* LOCUS */
13374
13375 #ifdef KUI
13376       case XYGUI:
13377         return(setgui());
13378 #endif /* KUI */
13379
13380 #ifndef NOFRILLS
13381 #ifndef NORENAME
13382       case XY_REN:                      /* SET RENAME */
13383         return(setrename());
13384 #endif  /* NORENAME */
13385 #endif  /* NOFRILLS */
13386
13387 #ifndef NOPUSH
13388 #ifdef CK_REDIR
13389 #ifndef NOXFER
13390       case XYEXTRN:                     /* SET EXTERNAL-PROTOCOL */
13391         return(setextern());
13392 #endif  /* NOXFER */
13393 #endif  /* CK_REDIR */
13394 #endif  /* NOPUSH */
13395
13396 #ifndef NOSPL
13397       case XYVAREV:                     /* SET VARIABLE-EVALUATION */
13398         return(setvareval());
13399 #endif  /* NOSPL */
13400
13401       default:
13402          if ((x = cmcfm()) < 0) return(x);
13403          printf("Not implemented - %s\n",cmdbuf);
13404          return(success = 0);
13405     }
13406 }
13407
13408 /*
13409   H U P O K  --  Is Hangup OK?
13410
13411   Issues a warning and gets OK from user depending on whether a connection
13412   seems to be open and what the SET EXIT WARNING setting is.  Returns:
13413     0 if not OK to hang up or exit (i.e. user said No);
13414     nonzero if OK.
13415   Argument x is used to differentiate the EXIT command from SET LINE / HOST.
13416 */
13417 int
13418 hupok(x) int x; {                       /* Returns 1 if OK, 0 if not OK */
13419     int y, z = 1;
13420     extern int exithangup;
13421 #ifdef VMS
13422     extern int batch;
13423
13424     if (batch)                          /* No warnings in batch */
13425       return(1);
13426 #else
13427 #ifdef UNIX
13428     if (backgrd)                        /* No warnings in background */
13429       return(1);
13430 #endif /* UNIX */
13431 #endif /* VMS */
13432
13433 #ifndef K95G
13434     debug(F101,"hupok local","",local);
13435
13436     if (!local)                         /* No warnings in remote mode */
13437       return(1);
13438 #endif /* K95G */
13439
13440     if (x == 0 && exithangup == 0)      /* EXIT and EXIT HANGUP is OFF */
13441       return(1);
13442
13443     debug(F101,"hupok x","",x);
13444     debug(F101,"hupok xitwarn","",xitwarn);
13445     debug(F101,"hupok network","",network);
13446     debug(F101,"hupok haveline","",haveline);
13447
13448     if ((local && xitwarn) ||           /* Is a connection open? */
13449         (!x && xitwarn == 2)) {         /* Or Always give warning on EXIT */
13450         int needwarn = 0;
13451         char warning[256];
13452
13453         if (network) {
13454             if (ttchk() >= 0)
13455               needwarn = 1;
13456             /* A connection seems to be open but it can't possibly be */
13457             if (!haveline)
13458               needwarn = 0;
13459             if (needwarn) {
13460                 if (strcmp(ttname,"*"))
13461                     ckmakmsg(warning,256,
13462                               " A network connection to ",ttname,
13463                               " might still be active.\n",NULL);
13464                 else
13465                   ckstrncpy(warning,
13466                    " An incoming network connection might still be active.\n",
13467                              256);
13468             }
13469         } else {                        /* Serial connection */
13470             if (carrier == CAR_OFF)     /* SET CARRIER OFF */
13471               needwarn = 0;             /* so we don't care about carrier. */
13472             else if ((y = ttgmdm()) >= 0) /* else, get modem signals */
13473               needwarn = (y & BM_DCD);  /* Check for carrier */
13474             else                        /* If we can't get modem signals... */
13475               needwarn = (ttchk() >= 0);
13476             /* A connection seems to be open but it can't possibly be */
13477             if (!haveline || !exithangup)
13478               needwarn = 0;
13479             if (needwarn)
13480                 ckmakmsg(warning,256,
13481                      " A serial connection might still be active on ",
13482                      ttname,".\n",NULL);
13483         }
13484
13485 /* If a warning was issued, get user's permission to EXIT. */
13486
13487         if (needwarn || (!x && xitwarn == 2
13488 #ifndef K95G
13489                         && local
13490 #endif /* K95G */
13491                          )) {
13492             if ( !needwarn )
13493                 ckstrncpy(warning, "No active connections", 256);
13494
13495 #ifdef COMMENT
13496             printf("%s",warning);
13497             z = getyesno(x ? "OK to close? " : "OK to exit? ",0);
13498             debug(F101,"hupok getyesno","",z);
13499             if (z < -3) z = 0;
13500 #else
13501             z = uq_ok(warning,
13502                       x ? "OK to close? " : "OK to exit? ",
13503                       3,
13504                       NULL,
13505                       0
13506                       );
13507             debug(F101,"hupok uq_ok","",z);
13508             if (z < 0) z = 0;
13509 #endif /* COMMENT */
13510         }
13511     }
13512     return(z);
13513 }
13514
13515 #ifndef NOSHOW
13516 VOID
13517 shoctl() {                              /* SHOW CONTROL-PREFIXING */
13518 #ifdef CK_SPEED
13519     int i;
13520 #ifdef OS2
13521     int zero;
13522 #endif /* OS2 */
13523     printf(
13524 "\ncontrol quote = %d, applied to (0 = unprefixed, 1 = prefixed):\n\n",
13525            myctlq);
13526 #ifdef OS2
13527 #ifndef UNPREFIXZERO
13528     zero = ctlp[0];
13529     if (protocol == PROTO_K)            /* Zero can't be unprefixed */
13530       ctlp[0] = 1;                      /* for Kermit */
13531 #endif /* UNPREFIXZERO */
13532 #endif /* OS2 */
13533     for (i = 0; i < 16; i++) {
13534         printf("  %3d: %d   %3d: %d ",i,ctlp[i], i+16, ctlp[i+16]);
13535         if (i == 15)
13536           printf("  127: %d",ctlp[127]);
13537         else
13538           printf("        ");
13539         printf("  %3d: %d   %3d: %d ",i+128,ctlp[i+128], i+144, ctlp[i+144]);
13540         if (i == 15)  printf("  255: %d",ctlp[255]);
13541         printf("\n");
13542     }
13543     printf("\n");
13544 #ifndef UNPREFIXZERO
13545 #ifdef OS2
13546     ctlp[0] = zero;
13547 #endif /* OS2 */
13548 #endif /* UNPREFIXZERO */
13549
13550 #endif /* CK_SPEED */
13551 }
13552
13553 #ifndef NOXFER
13554 VOID
13555 shodbl() {                              /* SHOW DOUBLE/IGNORE */
13556 #ifdef CKXXCHAR
13557     int i, n = 0;
13558     printf("\nSET SEND DOUBLE characters:\n");
13559     for (i = 0; i < 255; i++) {
13560         if (dblt[i] & 2) {
13561             n++;
13562             printf(" %d", i);
13563         }
13564     }
13565     if (n == 0)
13566       printf(" (none)");
13567     n = 0;
13568     printf("\nSET RECEIVE IGNORE characters:\n");
13569     for (i = 0; i < 255; i++) {
13570         if (dblt[i] & 1) {
13571             n++;
13572             printf(" %d", i);
13573         }
13574     }
13575     if (n == 0)
13576       printf(" (none)");
13577     printf("\n\n");
13578 #endif /* CKXXCHAR */
13579 }
13580 #endif /* NOXFER */
13581 #endif /* NOSHOW */
13582
13583 #ifndef NOPUSH
13584 #ifdef CK_REXX
13585 /*
13586   Rexx command.  Note, this is not OS/2-specific, because Rexx also runs
13587   on other systems where C-Kermit also runs, like the Amiga.
13588 */
13589 #define REXBUFL 100                     /* Change this if neccessary */
13590 char rexxbuf[REXBUFL] = { '\0' };       /* Rexx's return value (string) */
13591
13592 int
13593 dorexx() {
13594     int x, y;
13595     char *rexxcmd;
13596
13597         if ((x = cmtxt("Rexx command","",&rexxcmd,xxstring)) < 0)
13598           return(x);
13599
13600 #ifdef IKSD
13601     if (inserver) {
13602         printf("?Sorry, command disabled.\r\n");
13603         return(success = 0);
13604     }
13605 #endif /* IKSD */
13606 #ifdef CK_APC
13607     /* Don't let this be set remotely */
13608     if (apcactive == APC_LOCAL ||
13609         apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
13610       return(success = 0);
13611 #endif /* CK_APC */
13612
13613         ckstrncpy(line,rexxcmd,LINBUFSIZ);
13614         rexxcmd = line;
13615 #ifdef OS2
13616         return(os2rexx(rexxcmd,rexxbuf,REXBUFL));
13617 #else /* !OS2 */
13618         printf("Sorry, nothing happens.\n");
13619         return(success = 0);
13620 #endif /* OS2 */
13621 }
13622 #endif /* CK_REXX */
13623 #endif /* NOPUSH */
13624 #else  /* NOICP */
13625 VOID
13626 dologend() {
13627     /* Dummy write record to connection log */
13628 }
13629 #endif /* NOICP */