debian/watch: remove boilerplate
[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, 2009,
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_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
3432 extern char math_pi[];                  /* Value of Pi */
3433 extern int sexpecho;                    /* SET SEXPRESSION ECHO value */
3434 extern char * sexpval;                  /* Last top-level S-Expression value */
3435 extern char * lastsexp;                 /* Last S-Expression */
3436 int sexprmax = 0;                       /* Longest result (for stats) */
3437 int sexpdmax = 0;                       /* Max depth reached (for stats) */
3438 int sexpdep  = 0;                       /* dosexp() recursion depth */
3439 static int * sxrlen = NULL;             /* Result stack string sizes */
3440 static char ** sxresult = NULL;         /* Result stack */
3441
3442 /*  s h o s e x p  --  Show S-Expression info  */
3443
3444 VOID
3445 shosexp() {
3446     printf("\n");
3447     printf(" sexpression echo-result: %s\n",showooa(sexpecho));
3448     printf(" sexpression depth-limit: %d\n",sexpmaxdep);
3449     printf("\n");
3450     printf(" maximum depth reached:   %d\n",sexpdmax);
3451     printf(" longest result returned: %d\n",sexprmax);
3452     printf("\n");
3453     printf(" truncate all results:    %s\n",showoff(sexptrunc));
3454     printf("\n");
3455     printf(" last sexpression:        %s\n",lastsexp ? lastsexp : "(none)");
3456     printf(" last value:              %s\n",sexpval ? sexpval : "(none)");
3457     printf("\n");
3458 }
3459
3460
3461 static char *
3462 sexpdebug(s) char * s; {
3463     /* For debugging -- includes recursion depth in each debug entry */
3464     static char buf[64];
3465     ckmakmsg(buf,64,"dosexp[",ckitoa(sexpdep),"] ",s);
3466     return((char *)buf);
3467 }
3468
3469 /*  d o s e x p  --  S-Expression Reader  */
3470
3471 /*  Returns value as string (empty, numeric, or non-numeric) */
3472
3473 char *
3474 dosexp(s) char *s; {                    /* s = S-Expression */
3475     extern struct mtab *mactab;         /* Macro table */
3476     extern int maclvl, nmac;
3477     extern char *mrval[];
3478     extern int makestrlen;              /* (see makestr()) */
3479     struct stringarray * q = NULL;      /* cksplit() return type */
3480     char * p[SEXPMAX+1], ** p2;         /* List items (must be on stack) */
3481     char * line = NULL;                 /* For building macro argument list */
3482     int nosplit = 0;
3483     int linelen = 0;
3484     int linepos = 0;
3485     int quote = 0;                      /* LISP quote flag */
3486     char * s2;                          /* Workers */
3487     int kw, kwflags, mx = 0, x = 0;
3488     int not = 0, truncate = 0, builtin = 0;
3489     int fpflag = 0, quit = 0, macro = 0;
3490     CK_OFF_T result = 0, i, j, k, n = 0;
3491     CKFLOAT fpj, fpresult = 0.0;        /* Floating-point results */
3492     int pflag = 0;                      /* Have predicate */
3493     int presult = 0;                    /* Predicate result */
3494     int mustfree = 0;                   /* If we malloc'd we must free */
3495
3496     sexppv = -1;                        /* Predicate value */
3497     s2 = "";                            /* Default return value */
3498
3499     debug(F111,sexpdebug("entry 1"),s,sexprc);
3500
3501     if (++sexpdep > sexpmaxdep) {       /* Keep track of depth */
3502         printf("?S-Expression depth limit exceeded: %d\n",sexpmaxdep);
3503         sexprc++;
3504         debug(F111,sexpdebug("max depth exceeded"),s,sexprc);
3505     }
3506     if (sexpdep > sexpdmax)             /* For stats */
3507       sexpdmax = sexpdep;
3508
3509     if (sexprc)                         /* Error, quit all levels */
3510       goto xdosexp;                     /* Always goto common exit point */
3511
3512     debug(F111,sexpdebug("entry 2"),s,sexprc);
3513
3514     if (!s) s = "";                     /* Null or empty arg */
3515
3516     while (*s == SP) s++;               /* Strip leading spaces */
3517     if (!*s)                            /* so empty result */
3518       goto xdosexp;
3519 /*
3520   Allocate result stack upon first use, or after it has been resized with
3521   SET SEXP DEPTH-LIMIT.
3522 */
3523     if (!sxresult) {
3524         sxresult = (char **)malloc(sexpmaxdep * sizeof(char *));
3525         if (!sxresult) {
3526             printf("?Memory allocation failure - \"%s\"\n", s);
3527             sexprc++;
3528             goto xdosexp;
3529         }
3530         sxrlen = (int *)malloc(sexpmaxdep * sizeof(int));
3531         if (!sxrlen) {
3532             printf("?Memory allocation failure - \"%s\"\n", s);
3533             sexprc++;
3534             goto xdosexp;
3535         }
3536         for (i = 0; i < sexpmaxdep; i++) {
3537             sxresult[i] = NULL;         /* Result pointers */
3538             sxrlen[i] = 0;              /* Buffer sizes */
3539         }
3540     }
3541     s2 = s;                             /* s2 is the result pointer */
3542     k = 0;                              /* Length accumulator */
3543     if (s[0] == '(') {                  /* Starts with open paren? */
3544         while (*s2++) k++;              /* Get length */
3545         if (s[k-1] == ')') {            /* Strip outer parens if any */
3546             s[k-1] = NUL;
3547             s++;
3548             k -= 2;
3549             while (*s == SP) {          /* Strip leading spaces from result */
3550                 s++;
3551                 k--;
3552             }
3553             while (k > 0 && s[k-1] == SP) { /* And trailing spaces. */
3554                 s[k-1] = NUL;
3555                 k--;
3556             }
3557         }
3558         if (!*s) {                      /* If nothing remains */
3559             s2 = "";                    /* return empty result. */
3560             goto xdosexp;
3561         }
3562     }
3563     /* Break result up into "words" (an SEXP counts as a word) */
3564
3565     p[0] = NULL;                        /* (We don't use element 0) */
3566     if (!*(s+1) || !*(s+2)) {           /* No need to call cksplit() */
3567         n = 1;                          /* if it's one or two chars. */
3568         p[1] = s;                       /* No need to malloc this either. */
3569         nosplit = 1;
3570         debug(F101,sexpdebug("nosplit"),"",n);
3571         if (s[0] == '(') {              /* () empty */
3572             s2 = "";
3573             goto xdosexp;
3574         }
3575     } else {
3576         nosplit = 0;
3577         q = cksplit(1,SEXPMAX,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",8,39,0);
3578         if (!q)
3579           goto xdosexp;
3580         n = q->a_size;                  /* Number of items */
3581         debug(F101,sexpdebug("split"),"",n);
3582         if (n < 0 || n > SEXPMAX) {     /* Check for too many */
3583             printf("?Too many operands: max = %d\n",SEXPMAX);
3584             sexprc++;
3585             goto xdosexp;
3586         }
3587         if (n == 0)                     /* None, result is NULL, done. */
3588           goto xdosexp;
3589         if (n == 1 && s[0] == '(') {    /* One but it's another SEXP */
3590             s2 = dosexp(s);
3591             goto xdosexp;
3592         }
3593         p2 = q->a_head;                 /* Point to result array. */
3594         for (i = 1; i <= n; i++) {      /* We must copy it because */
3595             p[i] = NULL;                /* recursive calls to dosexp() */
3596             if (p2[i])                  /* write over the same array */
3597               makestr(&(p[i]),p2[i]);
3598         }
3599         if (s[0] == '(') {              /* Operator is an S-Expression */
3600             s2 = dosexp(p[1]);          /* Replace it by its value */
3601             makestr(&(p[1]),s2);
3602         }
3603         mustfree++;                     /* Remember to free it */
3604     }
3605     debug(F110,sexpdebug("head"),p[1],0);
3606
3607     if (n == 1 && p[1]) {
3608         if (*(p[1]) == '\047') {
3609             s2 = p[1];
3610             goto xdosexp;
3611         }
3612     }
3613 /*
3614   This section sidesteps xlookup() of the most common operators.
3615   It's not necessary but it speeds up SEXP-heavy loops by about 10%.
3616 */
3617     kwflags = 0;
3618     if (n > 0) {                        /* Look up the operator */
3619         s2 = p[1];                      /* Prelookup optimization... */
3620         if (!s2)
3621           s2 = "";
3622         if (!*s2)
3623           goto xdosexp;
3624         kw = 0;
3625         x = 0;
3626         if (isdigit(*s2)) {             /* Digit */
3627             x = -2;
3628
3629         } else if (isalpha(*s2) && !*(s2+1)) { /* Single letter */
3630             x = -1;
3631
3632         } else if (*s2 == 's' || *s2 == 'S') { /* SETQ */
3633             s2++;
3634             if (*s2 == 'e' || *s2 == 'E') {
3635                 s2++;
3636                 if (*s2 == 't' || *s2 == 'T') {
3637                     s2++;
3638                     if (*s2 == 'q' || *s2 == 'Q') {
3639                         if (!*(s2+1)) {
3640                             x = SX_SET;
3641                             kwflags = 0;
3642                             builtin = 1;
3643                         }
3644                     }
3645                 }
3646             }
3647         }
3648         if (!x) {
3649             if (!*(s2+1)) {             /* Common single-character ops */
3650                 if (*s2 == '+') {
3651                     x = SX_ADD;
3652                     kwflags = 0;
3653                     builtin = 1;
3654                 } else if (*s2 == '-') {
3655                     x = SX_SUB;
3656                     kwflags = 0;
3657                     builtin = 1;
3658                 } else if (*s2 == '*') {
3659                     x = SX_MUL;
3660                     kwflags = 0;
3661                     builtin = 1;
3662                 } else if (*s2 == '/') {
3663                     x = SX_DIV;
3664                     kwflags = SXF_TWO;
3665                     builtin = 1;
3666                 }
3667             }
3668             if (!x) {                   /* None of the above, look it up */
3669                 x = xlookup(sexpops,p[1],nsexpops,&kw);
3670                 if (x > 0) {
3671                     kwflags = sexpops[kw].flgs;
3672                     builtin = 1;
3673                 }
3674             }
3675         }
3676     }
3677     /* If none of the above, check built-in constants */
3678
3679     if (x == -1) {
3680         x = xlookup(sexpconsts,p[1],nsexpconsts,&kw);
3681         if (x > 0) {
3682             switch (x) {
3683               case SXC_NIL:
3684                 s2 = "";
3685                 goto xdosexp;
3686               case SXC_PI:
3687                 s2 = math_pi;
3688                 goto xdosexp;
3689               case SXC_T:
3690                 s2 = "1";
3691                 goto xdosexp;
3692             }
3693         }
3694     }
3695     if (n == 1) {                       /* Not an expression */
3696         if (builtin) {                  /* Built-in operand? */
3697             switch (x) {                /* Operators with default values */
3698               case SX_EVA:
3699                 s2 = "";
3700                 goto xdosexp;
3701               case SX_MUL:              /* (*) */
3702                 s2 = sexpval ? sexpval : "1";
3703                 goto xdosexp;
3704               case SX_AND:              /* (AND) */
3705               case SX_BWA:              /* Bitwise (&) */
3706                 result++;
3707               case SX_LOR:              /* (OR) */
3708               case SX_BWO:              /* Bitwise (|) */
3709               case SX_ADD:              /* (+) */
3710               case SX_SUB:              /* (-) */
3711                 s2 = result ? "1" : "0";
3712                 goto xdosexp;
3713             }
3714
3715         } else {                        /* Not a built-in operand */
3716             char * p1;
3717             p1 = p[1];
3718             while (*p1 == SP) p1++;
3719             if (!isalpha(*p1)) {
3720                 if (xxfloat(p1,0) > 0) { /* Is it a number? */
3721                     s2 = p1;
3722                     while (*s2 == '+') s2++;
3723                 } else if (*p1 == '(') { /* An S-Expression? */
3724
3725 #ifdef COMMENT
3726                     s2 = dosexp(s2);
3727 #else
3728                     s2 = dosexp(p1);
3729 #endif /* COMMENT */
3730                 }
3731                 goto xdosexp;
3732             } else if (x < 1) {         /* Is it a variable? */
3733                 j = mxlook(mactab,p[1],nmac); /* Look it up */
3734                 debug(F111,sexpdebug("n==1 mxlook"),p[1],j);
3735                 s2 = (j > -1) ? mactab[j].mval : "";
3736                 if (!s2) s2 = "";
3737                 if (xxfloat(s2,0) > 0)  /* Macro value is a number */
3738                   goto xdosexp;
3739                 if (j > -1) {           /* It's a macro */
3740                     mx = j;
3741                     x = j;              /* whose definition is not numeric */
3742                     if (*s2 == '(') {   /* Is it an S-Expression? */
3743                         /* We have to allocate memory on the stack */
3744                         /* to call ourselves recursively on it */
3745                         /* otherwise we'll wipe out the macro definition */
3746                         char * s3 = NULL;
3747                         /* int k = 0; */
3748                         s3 = s2;
3749                         while (*s3++) k++;
3750                         s3 = (char *)malloc(k + 4);
3751                         if (s3) {
3752                             strcpy(s3,s2);   /* SAFE */
3753                             s2 = dosexp(s3); /* Evaluate it */
3754                             free(s3);
3755                         } else {
3756                             printf("?Memory allocation failure - \"%s\"\n",s2);
3757                             sexprc++;
3758                         }
3759                         goto xdosexp;
3760                     }
3761                     if (*s2 == '\047') {
3762                         s2++;
3763 #ifdef COMMENT
3764                         /* Dumps core if petty optimization was taken */
3765                         makestr(&(p[1]),s2);
3766 #else
3767                         if (!nosplit && p[1]) free(p[1]);
3768                         p[1] = (char *)malloc((int)strlen(s2) + 1);
3769 #endif /* COMMENT */
3770                         s2 = p[1];
3771                         if (!s2) s2 = "";
3772                         if (*s2 == '(') {
3773                             if (s2[makestrlen-1] == ')') {
3774                                 s2[makestrlen-1] = NUL;
3775                                 s2++;
3776                             }
3777                         }
3778                         debug(F110,sexpdebug("'A"),s2,0);
3779                         goto xdosexp;
3780                     }
3781                     macro++;            /* Not an S-Expression */
3782                 } else {                /* Not found in macro table */
3783                     printf("?Not defined - \"%s\"\n", p[1]);
3784                     sexprc++;
3785                     goto xdosexp;
3786                 }
3787             }
3788         }
3789     } else if (x < 1 && !macro) {       /* n > 1 and not a built-in operator */
3790         x = mxlook(mactab,p[1],nmac);   /* See if it's a macro */
3791         debug(F111,sexpdebug("n!=1 mxlook"),p[1],x);
3792         if (x < 0) {
3793             printf("?Invalid operand - \"%s\"\n",p[1]);
3794             sexprc++;
3795             goto xdosexp;
3796         }
3797         mx = x;
3798         macro++;
3799     }
3800     if (builtin) {                      /* Built-in operator... */
3801         if (kwflags) {
3802             int flgs;
3803             if ((flgs = (kwflags & (SXF_ONE|SXF_TWO)))) {
3804                 switch (flgs) {
3805                   case (SXF_ONE|SXF_TWO):
3806                     if (n < 2) {
3807                         printf("?Too few operands - \"%s\"\n",s);
3808                         sexprc++;
3809                         goto xdosexp;
3810                     }
3811                     break;
3812                   case SXF_TWO:
3813                     if (n < 3) {
3814                         printf("?Too few operands - \"%s\"\n",s);
3815                         sexprc++;
3816                         goto xdosexp;
3817                     }
3818                     break;
3819                   case SXF_ONE:
3820                     if (n != 2) {
3821                         printf("?Too %s operands - \"%s\"\n",
3822                                (n > 2) ? "many" : "few", s);
3823                         sexprc++;
3824                         goto xdosexp;
3825                     }
3826                 }
3827             }
3828             if (kwflags & SXF_PRE) {    /* Predicate? */
3829                 if (n < 2) {
3830                     printf("?Too few operands - \"%s\"\n",s);
3831                     sexprc++;
3832                     goto xdosexp;
3833                 }
3834                 pflag = 1;
3835                 presult = 1;
3836             }
3837             if (kwflags & SXF_FLO)      /* Operator requires floating point */
3838               fpflag++;                 /* Force it */
3839         }
3840         if (x == SX_SET || x == SX_LET || /* Assignment is special */
3841             x == SX_INC || x == SX_DEC) {
3842             int rc;
3843             char c, * m, * s3;
3844             if (n == 1) {
3845                 s2 = "";
3846                 goto xdosexp;
3847             }
3848             s2 = NULL;
3849             for (i = 1; i < n; i += 2) { /* Loop thru operand pairs */
3850                 rc = 0;
3851                 s3 = p[i+1];
3852                 c = *s3;
3853                 debug(F110,sexpdebug("target p"),s3,0);
3854
3855                 /* Make sure target doesn't have multiple words */
3856                 while (*s3) { if (*s3 < '!') { rc = 1; break; }; s3++; }
3857                 s3 = p[i+1];
3858                 if (rc) {               /* If it does it must have been */
3859                     char * s4;          /* an SEXP so evaluate it */
3860                     s3 = dosexp(s3);
3861                     s4 = s3;
3862                     rc = 0;
3863                     while (*s4) { if (*s4 < '!') { rc = 1; break; }; s4++; }
3864                     if (rc == 0) makestr(&(p[i+1]),s3);
3865                 }
3866
3867                 /* And that it's not a number, etc. */
3868                 if (rc > 0 || isdigit(c) || c == '(') {
3869                     printf("?Invalid assignment - \"%s\"\n",s);
3870                     sexprc++;
3871                     goto xdosexp;
3872                 } else if (isalpha(c)) {
3873                     rc = xlookup(sexpconsts,s3,nsexpconsts,NULL);
3874                     if (rc > 0) {
3875                         printf("?Assignment to constant - \"%s\"\n",s);
3876                         sexprc++;
3877                         goto xdosexp;
3878                     }
3879                 }
3880
3881                 /* If ++ or --, get current value of variable */
3882                 if (x == SX_INC || x == SX_DEC) {
3883                     int ok = 1;
3884                     char buf[32];
3885                     if (c == CMDQ) {    /* A backslash variable */
3886                         int n = 32;
3887                         char * s = buf;
3888                         buf[0] = NUL;
3889                         if (zzstring(s3,&s,&n) < 0 || !buf[0])
3890                           ok = 0;
3891                         s2 = buf;
3892                     } else {            /* A macro */
3893                         if ((k = mxlook(mactab,s3,nmac)) < 0)
3894                           ok = 0;
3895                         else
3896                           s2 = mactab[k].mval;
3897                     }
3898                     if (!ok) {
3899                         printf("?Not defined - \"%s\"\n",p[i+1]);
3900                         sexprc++;
3901                         goto xdosexp;
3902                     }
3903                     if (!s2) s2 = "";
3904                     k = xxfloat(s2,0);
3905                     if (k < 1) {
3906                         printf("?Not numeric - \"%s\"\n",p[i+1]);
3907                         sexprc++;
3908                         goto xdosexp;
3909                     }
3910                     while (*s2 == '+') s2++;
3911                     result = ckatofs(s2);
3912                     fpresult = floatval;
3913                     if (k > 1 || fpresult != result)
3914                       fpflag++;
3915                 }
3916                 if (n < i+2) {          /* Variable with no value */
3917                     s2 = "";
3918                     if (x == SX_SET || x == SX_LET) {
3919                         delmac(p[i+1],1); /* Delete the variable */
3920                         break;
3921                     } else {
3922                         s2 = "1";
3923                     }
3924                 } else {                /* Variable with value */
3925                     k = xxfloat(p[i+2],0); /* Is it a number? */
3926                     if (k > 0) {
3927                         s2 = p[i+2];
3928                         while (*s2 == '+') s2++;
3929                     } else {
3930                         s2 = dosexp(p[i+2]); /* Have value, evaluate it */
3931                         if (sexprc) goto xdosexp;
3932                         if (!s2) s2 = "";
3933                         if (!*s2 && (x == SX_INC || x == SX_DEC))
3934                           continue;
3935                     }
3936                 }
3937                 if (x == SX_INC || x == SX_DEC) {
3938                     k = xxfloat(s2,0);
3939                     if (k < 1) {
3940                         printf("?Not numeric - \"%s\"\n",s2);
3941                         sexprc++;
3942                         goto xdosexp;
3943                     }
3944                     while (*s2 == '+') s2++;
3945                     j = ckatofs(s2);
3946                     if (k > 1) {
3947                         fpj = floatval;
3948                         fpflag++;
3949                     } else {
3950                         fpj = (CKFLOAT)j;
3951                     }
3952                     if (x == SX_INC) {
3953                         result += j;
3954                         fpresult += fpj;
3955                     } else if (x == SX_DEC) {
3956                         result -= j;
3957                         fpresult -= fpj;
3958                     }
3959 #ifdef FNFLOAT
3960                     if (result != fpresult) fpflag++;
3961 #endif  /* FNFLOAT */
3962                     s2 = (fpflag && !sexptrunc) ?
3963                         fpformat(fpresult,0,0) : ckfstoa(result);
3964                 }
3965                 if (x == SX_LET && cmdlvl > 0) /* LET makes var local */
3966                   addlocal(p[i+1]);
3967                 if ((rc = addmac(p[i+1],s2)) < 0) { /* Add the value */
3968                     switch (rc) {
3969                       case -3: m = "Array not declared"; break;
3970                       case -2: m = "Subscript out of range"; break;
3971                       case -4: m = "Out of memory"; break;
3972                       default: m = "Error creating variable";
3973                     }
3974                     printf("?%s - \"%s\"\n",m,s);
3975                     sexprc++;
3976                     goto xdosexp;
3977                 }
3978                 if (s2) result = ckatofs(s2);
3979             }
3980             goto xdosexp;
3981         } else if (x == SX_IFC) {               /* Conditional expression */
3982             int true = 0;
3983             if (n > 4) {
3984                 printf("?Too many operands: IF - \"%s\"\n",s);
3985                 sexprc++;
3986                 goto xdosexp;
3987             }
3988             s2 = dosexp(p[2]);
3989             if (sexprc) goto xdosexp;
3990             if (s2) {
3991                 j = ckatofs(s2);
3992                 if (xxfloat(s2,0) == 2) {
3993                     fpflag++;
3994                     fpresult = (CKFLOAT)result;
3995                     fpj = floatval;
3996                 } else {
3997                     fpj = atof(s2);
3998                 }
3999                 true = ((fpj != 0.0) ? 1 : 0);
4000             }
4001             if (!true && n < 4) {
4002                 s2 = NULL;
4003             } else {
4004                 s2 = dosexp(true ? p[3] : p[4]);
4005                 if (sexprc) goto xdosexp;
4006                 j = s2 ? ckatofs(s2) : 0;
4007                 if (xxfloat(s2,0) == 2) {
4008                     fpflag++;
4009                     fpresult = (CKFLOAT)result;
4010                     fpj = floatval;
4011                 } else {
4012                     fpj = s2 ? atof(s2) : 0.0;
4013                 }
4014                 fpresult = fpj;
4015                 result = j;
4016             }
4017             goto xdosexp;
4018         } else if (x == SX_QUO) {
4019 #ifndef COMMENT
4020             int xx;
4021             xx = strlen(p[2]);
4022             p[3] = (char *)malloc(xx+4);
4023             s2 = p[3];
4024             ckmakmsg(p[3],xx+4,"'(",p[2],")",NULL);
4025             n++;
4026 #else
4027             s2 = p[2];
4028 #endif /* COMMENT */
4029             goto xdosexp;
4030         } else if (x == SX_STR) {
4031             int xx;
4032             s2 = dosexp(p[2]);
4033             if (sexprc) goto xdosexp;
4034             xx = strlen(s2);
4035             p[3] = (char *)malloc(xx+4);
4036             ckmakmsg(p[3],xx+4,"'(",s2,")",NULL);
4037             s2 = p[3];
4038             n++;
4039             goto xdosexp;
4040         }
4041     }
4042     /* Arithmetic operator or macro - Loop thru operands */
4043
4044     quit = 0;                           /* Short-circuit flag. */
4045     if (macro && n > 1) {               /* If operator is a macro */
4046         if (!line) {                    /* allocate local buffer for */
4047             line = (char *)malloc(SXMLEN); /* the evaluated argument list. */
4048             if (!line) {
4049                 printf("?Memory allocation failure - \"%s\"\n",p[1]);
4050                 sexprc++;
4051                 goto xdosexp;
4052             }
4053             linelen = SXMLEN;
4054             /* debug(F101,"dosexp macro arg buffer","",linelen); */
4055         }
4056         linepos = 0;
4057         line[linepos] = NUL;
4058     }
4059     for (i = 1; ((i < n) && !sexprc && !quit); i++) { /* Loop thru operands */
4060         quote = 0;
4061         s2 = p[i+1];                    /* Get operand */
4062         if (!s2) s2 = "";
4063 #ifdef COMMENT
4064         if (*s2 == '\047') {            /* Is it quoted? */
4065             debug(F110,sexpdebug("'B"),s2,0);
4066             s2++;                       /* Space past the quote */
4067             quote++;
4068             if (*s2 == '(') {           /* Quoted S-Expression? */
4069                 char c4, * s4 = s2+1;   /* Strip outer parens */
4070                 while ((c4 = *s4++)) {
4071                     if (c4 == ')' && !*s4) {
4072                         s2++;
4073                         *(s4-1) = NUL;
4074                         break;
4075                     }
4076                 }
4077             }
4078             debug(F110,sexpdebug("'C"),s2,0);
4079
4080         } else {                        /* Not quoted */
4081             s2 = dosexp(p[i+1]);        /* evaluate it */
4082             if (sexprc) goto xdosexp;
4083             if (!s2) s2 = "";
4084             if (!macro && x == SX_EVA)
4085               continue;
4086         }
4087 #else
4088         if (*s2 != '\047') {            /* Is it quoted? */
4089             s2 = dosexp(p[i+1]);        /* No, evaluate it */
4090             if (sexprc) goto xdosexp;
4091             if (!s2) s2 = "";
4092             if (!macro && x == SX_EVA)
4093               continue;
4094         }
4095         if (*s2 == '\047') {            /* Is result quoted? */
4096             debug(F110,sexpdebug("'B"),s2,0);
4097             s2++;                       /* Space past the quote */
4098             quote++;
4099             if (*s2 == '(') {           /* Quoted S-Expression? */
4100                 char c4, * s4 = s2+1;   /* Strip outer parens */
4101                 while ((c4 = *s4++)) {
4102                     if (c4 == ')' && !*s4) {
4103                         s2++;
4104                         *(s4-1) = NUL;
4105                         break;
4106                     }
4107                 }
4108             }
4109             debug(F110,sexpdebug("'C"),s2,0);
4110         }
4111 #endif /* COMMENT */
4112         if (macro) {
4113             debug(F111,sexpdebug("macro arg"),s2,i);
4114             if (!*s2) quote++;
4115             if (!quote) {
4116                 register char c4, * s4 = s2;
4117                 while ((c4 = *s4++)) if (c4 == SP) { quote++; break; }
4118             }
4119             if (quote) line[linepos++] = '{';
4120             while ((line[linepos++] = *s2++)) {
4121                 if (linepos > linelen - 3) {
4122                     char * tmp = NULL;
4123                     line[linepos] = NUL;
4124                     linelen += SXMLEN;
4125                     tmp = (char *) malloc(linelen);
4126                     if (!tmp) {
4127                         printf("?Memory re-allocation failure - \"%s...\"\n",
4128                                line);
4129                         sexprc++;
4130                         goto xdosexp;
4131                     }
4132                     strcpy(tmp,line);
4133                     free(line);
4134                     line = tmp;
4135                 }
4136             }
4137             linepos--;                  /* Back up over NUL */
4138             if (quote)
4139               line[linepos++] = '}';    /* End quote group */
4140             line[linepos++] = SP;       /* add a space */
4141             line[linepos] = NUL;        /* and a NUL */
4142             continue;
4143         }
4144         if (!quote) {                   /* Built-in operator... */
4145             s2 = dosexp(s2);
4146             if (sexprc) goto xdosexp;
4147             if (!s2) s2 = "";
4148         }
4149         if (x == SX_EVA)
4150           continue;
4151
4152         if (!*s2) {
4153             /* An empty value is not a legal number */
4154             /* but it is a legal truth value */
4155             if (x != SX_AND && x != SX_LOR && x != SX_NOT) {
4156                 printf("?Not Numeric - \"%s\"\n",p[i+1]);
4157                 sexprc++;
4158                 goto xdosexp;
4159             }
4160             j = 0;
4161             fpj = 0.0;
4162         } else {
4163             j = ckatofs(s2);
4164             /* Switch to floating-point upon encountering any f.p. arg */
4165             /* OR... if integer is too big */
4166             if (!fpflag) if (xxfloat(s2,0) == 2)
4167               fpflag++;
4168             fpj = atof(s2);
4169         }
4170         if (i == 1) {                   /* Initial result is first operand */
4171             result = (n == 2 && x == SX_SUB) ? 0-j : j;
4172             fpresult = (n == 2 && x == SX_SUB) ? -fpj : fpj;
4173             if ((x == SX_AND && result == 0) || /* Short circuit */
4174                 (x == SX_LOR && result != 0))
4175               quit++;
4176             if (!(kwflags & SXF_ONE))   /* Command with single arg */
4177               continue;
4178         }
4179         if (x == SX_MOD || x == SX_DIV) {
4180             if (!result)
4181               fpflag++;
4182             if (!fpj) {
4183                 printf("?Divide by zero - \"%s\"\n",cmdbuf);
4184                 sexprc++;
4185                 goto xdosexp;
4186             }
4187         }
4188         switch (x) {                    /* Accumulate result */
4189
4190           case SX_EVA:                  /* EVAL */
4191             result = j;
4192             fpresult = fpj;
4193             break;
4194
4195           case SX_ADD:                  /* + */
4196             result += j;
4197             fpresult += fpj;
4198 #ifdef FNFLOAT
4199             if (result != fpresult)
4200               fpflag++;
4201 #endif  /* FNFLOAT */
4202             break;
4203
4204           case SX_SUB:                  /* - */
4205             result -= j;
4206             fpresult -= fpj;
4207 #ifdef FNFLOAT
4208             if (result != fpresult)
4209               fpflag++;
4210 #endif  /* FNFLOAT */
4211             break;
4212
4213           case SX_MUL:                  /* * */
4214             result *= j;
4215             fpresult *= fpj;
4216 #ifdef FNFLOAT
4217             if (result != fpresult)
4218               fpflag++;
4219 #endif  /* FNFLOAT */
4220             break;
4221
4222           case SX_AND:                  /* AND */
4223             result = result && j;
4224             if (!result) quit++;
4225             fpresult = fpresult && fpj;
4226             break;
4227
4228           case SX_LOR:                  /* OR */
4229             result = result || j;
4230             if (!result) quit++;
4231             fpresult = fpresult || fpj;
4232             break;
4233
4234           case SX_MOD:                  /* Modulus */
4235             result = result % j;
4236 #ifdef FNFLOAT
4237             fpresult = (CKFLOAT)fmod(fpresult,fpj);
4238             if (result != fpresult)
4239               fpflag++;
4240 #else
4241             fpresult = result;
4242 #endif /* FNFLOAT */
4243             break;
4244
4245           case SX_DIV:                  /* / */
4246             if (j) {
4247                 result /= j;
4248                 fpresult /= fpj;
4249 #ifdef FNFLOAT
4250                 if (result != fpresult)
4251                   fpflag++;
4252 #endif  /* FNFLOAT */
4253             } else {
4254                 fpresult /= fpj;
4255                 result = fpj;
4256 #ifdef FNFLOAT
4257                   fpflag++;
4258 #endif  /* FNFLOAT */
4259             }
4260             break;
4261
4262           case SX_AEQ:                  /* Test for equality */
4263             if (fpflag) {
4264                 if (fpresult != fpj)
4265                   presult = 0;
4266             } else {
4267                 if (result != j)
4268                   presult = 0;
4269             }
4270             break;
4271
4272           case SX_NEQ:                  /* Test for ineqality */
4273             if (fpflag) {
4274                 if (fpresult == fpj)
4275                   presult = 0;
4276             } else {
4277                 if (result == j)
4278                   presult = 0;
4279             }
4280             break;
4281
4282           case SX_ALE:                  /* Arithmetic less-equal */
4283             if (fpflag) {
4284                 if (fpj < fpresult)
4285                   presult = 0;
4286                 fpresult = fpj;
4287             } else {
4288                 if (j < result)
4289                   presult = 0;
4290                 result = j;
4291             }
4292             break;
4293
4294           case SX_ALT:                  /* Arithmetic less-than */
4295             if (fpflag) {
4296                 if (fpj <= fpresult)
4297                   presult = 0;
4298                 fpresult = fpj;
4299             } else {
4300                 if (j <= result)
4301                   presult = 0;
4302                 result = j;
4303             }
4304             break;
4305
4306           case SX_AGT:                  /* Arithmetic greater-than */
4307             if (fpflag) {
4308                 if (fpj >= fpresult)
4309                   presult = 0;
4310                 fpresult = fpj;
4311             } else {
4312                 if (j >= result)
4313                   presult = 0;
4314                 result = j;
4315             }
4316             break;
4317
4318           case SX_AGE:                  /* Arithmetic greater-equal */
4319             if (fpflag) {
4320                 if (fpj > fpresult)
4321                   presult = 0;
4322                 fpresult = fpj;
4323             } else {
4324                 if (j > result)
4325                   presult = 0;
4326                 result = j;
4327             }
4328             break;
4329
4330           case SX_POW:                  /* Raise to power */
4331 #ifdef FNFLOAT
4332             {
4333                 double dummy;
4334                 if (!fpj) {
4335                     fpresult = 1.0;
4336                 } else if ((!fpresult && fpj <= 0.0)) {
4337                     printf("?Divide by zero - \"%s\"\n",cmdbuf);
4338                     sexprc++;
4339                     goto xdosexp;
4340                 } else if (fpresult < 0.0 && modf(fpj,&dummy)) {
4341                     printf("?Domain error - \"%s\"\n",cmdbuf);
4342                     sexprc++;
4343                     goto xdosexp;
4344                 } else {
4345                     fpresult = (CKFLOAT)pow(fpresult,fpj);
4346                 }
4347             }
4348 #endif /* FNFLOAT */
4349             if (j == 0) {
4350                 result = 1;
4351             } else {
4352                 CK_OFF_T z, sign = 0;
4353                 if (j < 0) {
4354                     if (result == 0) {
4355                         printf("?Divide by zero - \"%s\"\n",cmdbuf);
4356                         sexprc++;
4357                         goto xdosexp;
4358                     }
4359                     j = 0 - j;
4360                     sign++;
4361                 }
4362                 z = result;
4363                 while (--j > 0)
4364                   result *= z;
4365                 if (sign)
4366                   result = 1 / result;
4367             }
4368 #ifdef FNFLOAT
4369             if (result != fpresult)
4370               fpflag++;
4371 #endif  /* FNFLOAT */
4372             break;
4373
4374 #ifdef FNFLOAT
4375           case SX_EXP:                  /* e to the given power */
4376             fpresult = (CKFLOAT) exp(fpj);
4377             break;
4378
4379           case SX_LGN:                  /* Natural log */
4380           case SX_LGX:                  /* Log base 10 */
4381           case SX_SQR:                  /* Square root */
4382             if (fpj < 0.0) {
4383                 printf("?Argument out of range - \"%s\"\n",cmdbuf);
4384                 sexprc++;
4385                 goto xdosexp;
4386             }
4387             if (x == SX_SQR)
4388               fpresult = (CKFLOAT) sqrt(fpj);
4389             else if (x == SX_LGN)
4390               fpresult = (CKFLOAT) log(fpj);
4391             else
4392               fpresult = (CKFLOAT) log10(fpj);
4393             break;
4394
4395           case SX_SIN:                  /* sine */
4396             fpresult = (CKFLOAT) sin(fpj);
4397             break;
4398
4399           case SX_COS:                  /* cosine */
4400             fpresult = (CKFLOAT) cos(fpj);
4401             break;
4402
4403           case SX_TAN:                  /* tangent */
4404             fpresult = (CKFLOAT) tan(fpj);
4405             break;
4406 #endif /* FNFLOAT */
4407
4408           case SX_CEI:                  /* Ceiling */
4409             if (j != fpj)
4410               if (fpj > 0.0)
4411                 fpj += 1.0;
4412             fpresult = fpj;
4413             fpflag = 1;
4414             truncate = 1;
4415             break;
4416
4417           case SX_FLR:                  /* Floor */
4418             if (j != fpj)
4419               if (fpj < 0.0)
4420                 fpj -= 1.0;
4421             fpresult = fpj;
4422             fpflag = 1;
4423             truncate = 1;
4424             break;
4425
4426           case SX_TRU:                  /* Truncate */
4427             fpresult = fpj;
4428             fpflag = 1;
4429             truncate = 1;
4430             break;
4431
4432           case SX_ROU:                  /* Round */
4433             if (fpj > 0.0)
4434               fpj += 0.5;
4435             else if (fpj < 0.0)
4436               fpj -= 0.5;
4437             fpresult = fpj;
4438             fpflag = 1;
4439             truncate = 1;
4440             break;
4441
4442           case SX_ABS:                  /* Absolute value */
4443             result = (j < 0) ? 0 - j : j;
4444 #ifdef FNFLOAT
4445             fpresult = (fpj < 0.0) ? 0.0 - fpj : fpj;
4446             if (result != fpresult)
4447               fpflag++;
4448 #endif  /* FNFLOAT */
4449             break;
4450
4451           case SX_MAX:                  /* Max */
4452             if (j != fpj)
4453               fpflag++;
4454             if (fpflag) {
4455                 if (fpj > fpresult)
4456                   fpresult = fpj;
4457             } else
4458               if (j > result)
4459                 result = j;
4460             break;
4461
4462           case SX_MIN:                  /* Min */
4463             if (j != fpj)
4464               fpflag++;
4465             if (fpflag) {
4466                 if (fpj < fpresult)
4467                   fpresult = fpj;
4468             } else
4469               if (j < result)
4470                 result = j;
4471             break;
4472
4473           case SX_FLO:                  /* Float */
4474             fpflag++;
4475             fpresult = result;
4476             fpj = j;
4477             break;
4478
4479           case SX_NOT:                  /* NOT (reverse truth value) */
4480             fpflag = 0;
4481             not++;
4482             break;
4483
4484           case SX_BWA:                  /* Bitwise AND */
4485             fpflag = 0;
4486             result &= j;
4487             break;
4488
4489           case SX_BWO:                  /* Bitwise OR */
4490             fpflag = 0;
4491             result |= j;
4492             break;
4493
4494           case SX_BWX:                  /* Bitwise XOR */
4495           case SX_XOR:                  /* Logical XOR */
4496             if (n > 3) {
4497                 printf("?Too many operands - \"%s\"\n",s);
4498                 sexprc++;
4499                 goto xdosexp;
4500             }
4501             fpflag = 0;
4502             if (x == SX_BWX) {
4503                 result ^= j;
4504             } else {
4505                 result = (result && !j) || (!result && j);
4506                 if (result) result = 1;
4507             }
4508             break;
4509
4510           case SX_BWN:                  /* Bitwise Not */
4511             fpflag = 0;
4512             result = ~result;
4513             break;
4514
4515           default:
4516             printf("BAD OP [%s]\n",p[1]);
4517             sexprc++;
4518         }
4519     }
4520     if (!pflag)                         /* Not a predicate */
4521       sexppv = -1;                      /* So unset this */
4522
4523   /* domacro: */
4524
4525     if (macro) {                        /* User-defined macro */
4526         extern int fsexpflag;           /* (see fneval():ckuus4.c) */
4527         int lookagain = 0;              /* Maybe the macro table changed */
4528         if (mactab[mx].kwd) {           /* Check and see */
4529             if (ckstrcmp(mactab[mx].kwd,p[1],-1,0))
4530               lookagain++;
4531         } else
4532           lookagain++;
4533         if (lookagain) {                /* The table changed */
4534             mx = mxlook(mactab,p[1],nmac); /* Get the macro's new index */
4535             debug(F111,sexpdebug("macro moved"),p[1],mx);
4536             if (mx < 0) {                  /* Yikes! */
4537                 printf("?Macro disappeared! - \"%s\"\n",p[1]);
4538                 sexprc++;
4539                 goto xdosexp;
4540             }
4541         }
4542         debug(F111,sexpdebug("macro mx"),mactab[mx].kwd,mx);
4543         if (fsexpflag) {                /* If embedded in a function call */
4544             if (cmpush() > -1) {        /* get a new copy of the parsing */
4545                 extern int ifc;         /* environment, */
4546                 int k, ifcsav = ifc;    /* save the IF state */
4547                 dodo(mx,line,0);        /* Set up the macro */
4548                 k = parser(1);          /* Call the parser to execute it */
4549                 cmpop();                /* Pop back to previous level */
4550                 ifc = ifcsav;           /* restore IF state */
4551                 if (k == 0)             /* If no error */
4552                   s2 = mrval[maclvl+1]; /* get return value, if any */
4553                 if (!s2) s2 = "";
4554                 debug(F110,sexpdebug("macro return"),s2,0);
4555             } else {
4556                 printf("?Resources exhausted - \"%s\"\n",s);
4557                 sexprc++;
4558             }
4559         } else {                        /* Not embedded in a function call */
4560             dodo(mx,line,0);            /* As above but without cmpush/pop() */
4561             k = parser(1);
4562             if (k == 0)
4563               s2 = mrval[maclvl+1];
4564             if (!s2) s2 = "";
4565         }
4566     } else if (pflag) {                 /* Predicate */
4567         if (not) presult = presult ? 0 : 1;
4568         sexppv = presult;               /* So set predicate value (0 or 1) */
4569         s2 = presult ? "1" : "0";
4570     } else if (fpflag && !sexptrunc) {  /* Result is floating-point */
4571         if (not) fpresult = fpresult ? 0.0 : 1.0;
4572         s2 = fpformat(fpresult,0,0);
4573     } else if (x != SX_EVA) {
4574         if (not) result = result ? 0 : 1;
4575         s2 = ckfstoa(result);
4576     }
4577
4578 /* Common exit point.  Always come here to exit. */
4579
4580   xdosexp:
4581
4582     if (!s2) s2 = "";
4583     if (!sexprc && s2) {                /* Have a result */
4584         char * sx;
4585         char * q2 = s2; int xx = 0;
4586         if (*s2) {
4587             while (*q2++) xx++;         /* Get length */
4588             if (xx > sexprmax)          /* (stats) */
4589               sexprmax = xx;
4590         } else
4591           xx = 0;
4592         if (xx > sxrlen[sexpdep] || !sxresult[sexpdep]) {
4593             int k;
4594             k = xx + xx / 4;
4595             if (k < 32) k = 32;
4596             if (sxresult[sexpdep])
4597               free(sxresult[sexpdep]);
4598             if ((sxresult[sexpdep] = (char *)malloc(k))) {
4599                 sxrlen[sexpdep] = k;
4600             } else {
4601                 printf("?Memory allocation failure - \"%s\"\n",s2);
4602                 sexprc++;
4603             }
4604         }
4605         sx = sxresult[sexpdep];         /* Point to result buffer */
4606         while ((*sx++ = *s2++)) ;       /* copy result. */
4607         if (fpflag && truncate) {       /* Floating point + truncate */
4608             sx = sxresult[sexpdep];     /* at decimal point */
4609             for (i = xx - 1; i >= 0; i--) {
4610                 if (sx[i] == '.') {
4611                     sx[i] = NUL;
4612                     if (i == 0) {       /* If nothing left */
4613                         sx[0] = '0';    /* put a zero. */
4614                         sx[1] = NUL;
4615                     }
4616                 }
4617             }
4618         }
4619     }
4620     if (line)                           /* If macro arg buffer allocated */
4621       free(line);                       /* free it. */
4622     if (mustfree) {                     /* And free local copy of split list */
4623         for (i = 1; i <= n; i++) {
4624             if (p[i]) free(p[i]);
4625         }
4626     }
4627     debug(F111,sexpdebug("exit"),sxresult[sexpdep],sexprc);
4628     return(sxresult[sexpdep--]);
4629 }
4630 #endif /* NOSEXP */
4631 #endif /* NOSPL */
4632
4633 int                                     /* CHECK command */
4634 dochk() {
4635     int x, y;
4636     if ((y = cmkey(ftrtab,nftr,"","",xxstring)) < 0)
4637       return(y);
4638     ckstrncpy(line,atmbuf,LINBUFSIZ);
4639     if ((y = cmcfm()) < 0)
4640       return(y);
4641 #ifndef NOPUSH
4642     if (!ckstrcmp(line,"push",(int)strlen(line),0)) {
4643         if (msgflg)                     /* If at top level... */
4644           printf(" push%s available\n", nopush ? " not" : "");
4645         else if (nopush && !backgrd)
4646           printf(" CHECK: push not available\n");
4647         return(success = 1 - nopush);
4648     }
4649 #endif /* NOPUSH */
4650 #ifdef PIPESEND
4651     if (!ckstrcmp(line,"pipes",(int)strlen(line),0)) {
4652         if (msgflg)                     /* If at top level... */
4653           printf(" pipes%s available\n",
4654                  (nopush || protocol != PROTO_K) ? " not" : "");
4655         else if ((nopush || protocol != PROTO_K) && !backgrd)
4656           printf(" CHECK: pipes not available\n");
4657         return(success = 1 - nopush);
4658     }
4659 #endif /* PIPESEND */
4660     y = lookup(ftrtab,line,nftr,&x);    /* Look it up */
4661     debug(F111,"dochk",ftrtab[x].kwd,y);
4662     if (msgflg)                         /* If at top level... */
4663       printf(" %s%s available\n", ftrtab[x].kwd, y ? " not" : "");
4664     else if (y && !backgrd)
4665       printf(" CHECK: %s not available\n", ftrtab[x].kwd);
4666     return(success = 1 - y);
4667 }
4668
4669 #ifndef NOLOCAL
4670 #ifdef CKLOGDIAL
4671
4672 /* Connection log and elapsed-time reporting */
4673
4674 extern char cxlogbuf[];                 /* Log record buffer */
4675 extern char diafil[];                   /* Log file name */
4676 extern int dialog, cx_active;           /* Flags */
4677 static long cx_prev = 0L;               /* Elapsed time of previous session */
4678
4679 #endif /* CKLOGDIAL */
4680 #endif /* NOLOCAL */
4681
4682 VOID
4683 dologend() {                            /* Write record to connection log */
4684 #ifdef LOCUS
4685     extern int locus, autolocus;
4686 #endif /* LOCUS */
4687
4688 #ifndef NOLOCAL
4689 #ifdef CKLOGDIAL
4690     long d1, d2, t1, t2;
4691     char buf[32], * p;
4692 #endif /* CKLOGDIAL */
4693 #endif /* NOLOCAL */
4694
4695 #ifdef LOCUS
4696     if (autolocus) {
4697         int x = locus;
4698 #ifdef NEWFTP
4699         debug(F101,"dologend ftpisconnected","",ftpisconnected());
4700         setlocus(ftpisconnected() ? 0 : 1, 1);
4701 #else
4702         setlocus(1,1);
4703 #endif /* NEWFTP */
4704     }
4705 #endif /* LOCUS */
4706
4707 #ifndef NOLOCAL
4708 #ifdef CKLOGDIAL
4709     debug(F101,"dologend dialog","",dialog);
4710     debug(F101,"dologend cxlogbuf[0]","",cxlogbuf[0]);
4711 #ifdef CKSYSLOG
4712     debug(F101,"dologend ckxlogging","",ckxlogging);
4713 #endif /* CKSYSLOG */
4714
4715     if (!cx_active || !cxlogbuf[0])     /* No active record */
4716       return;
4717
4718     cx_active = 0;                      /* Record is not active */
4719     debug(F111,"dologend cxlogbuf 1",cxlogbuf,cx_active);
4720
4721     d1 = mjd((char *)cxlogbuf);         /* Get start date of this session */
4722     ckstrncpy(buf,ckdate(),31);         /* Get current date */
4723     d2 = mjd(buf);                      /* Convert them to mjds */
4724     p = cxlogbuf;                       /* Get start time */
4725     p[11] = NUL;
4726     p[14] = NUL;                        /* Convert to seconds */
4727     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4728     p[11] = ':';
4729     p[14] = ':';
4730     p = buf;                            /* Get end time */
4731     p[11] = NUL;
4732     p[14] = NUL;
4733     t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4734     t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Compute elapsed time */
4735     debug(F101,"dologend t2","",t2);
4736     if (t2 > -1L) {
4737         cx_prev = t2;
4738         p = hhmmss(t2);
4739         debug(F110,"dologend hhmmss",p,0);
4740         ckstrncat(cxlogbuf,"E=",CXLOGBUFL); /* Append to log record */
4741         ckstrncat(cxlogbuf,p,CXLOGBUFL);
4742         debug(F110,"dologend cxlogbuf 2",cxlogbuf,0);
4743     } else
4744       cx_prev = 0L;
4745     debug(F101,"dologend cx_prev","",cx_prev);
4746     if (dialog) {                       /* If logging */
4747         int x;
4748         x = diaopn(diafil,1,1);         /* Open log in append mode */
4749         debug(F101,"dologend diaopn","",x);
4750         x = zsoutl(ZDIFIL,cxlogbuf);    /* Write the record */
4751         debug(F101,"dologend zsoutl","",x);
4752         x = zclose(ZDIFIL);             /* Close the log */
4753         debug(F101,"dologend zclose","",x);
4754     }
4755 #ifdef CKSYSLOG
4756     debug(F101,"dologend ckxlogging","",ckxlogging);
4757     if (ckxlogging) {
4758         int x;
4759         x = ckindex("T=DIAL",cxlogbuf,0,0,1);
4760         debug(F111,"dologend ckxsyslog",cxlogbuf,ckxsyslog);
4761         debug(F111,"dologend ckindex","T=DIAL",x);
4762         if (x > 0) {
4763             if (ckxsyslog >= SYSLG_DI) {
4764                 debug(F110,"dologend syslog",cxlogbuf+18,0);
4765                 cksyslog(SYSLG_DI,1,"CONNECTION",(char *)(cxlogbuf+18),"");
4766             } else if (ckxsyslog >= SYSLG_AC) {
4767                 debug(F110,"dologend syslog",cxlogbuf+18,0);
4768                 cksyslog(SYSLG_AC,1,"CONNECTION",(char *)(cxlogbuf+18),"");
4769             }
4770         }
4771     }
4772 #endif /* CKSYSLOG */
4773 #endif /* CKLOGDIAL */
4774 #endif /* NOLOCAL */
4775 }
4776
4777 #ifndef NOLOCAL
4778 #ifdef CKLOGDIAL
4779
4780 /*  D O L O G S H O W  --  Show session/connection info  */
4781
4782 /* Call with fc == 1 to show, fc == 0 to only calculate. */
4783 /* Returns session elapsed time in seconds. */
4784 /* If no session active, returns elapsed time of previous session, if any, */
4785 /* otherwise 0 */
4786
4787 long
4788 dologshow(fc) int fc; {                 /* SHOW (current) CONNECTION */
4789     long d1, d2, t1, t2 = 0, prev;
4790     char c, buf1[32], buf2[32], * info[32], * p, * s;
4791     char * xlogbuf, xbuf[CXLOGBUFL+1];
4792     int i, x = 0, z, ftp = 0, active = 0;
4793
4794 #ifdef NEWFTP
4795     extern char ftplogbuf[];
4796     extern long ftplogprev;
4797     extern int ftplogactive;
4798     if (fc & W_FTP) {
4799         fc &= 63;
4800         ftp = 1;
4801         xlogbuf = ftplogbuf;
4802         prev = ftplogprev;
4803         active = ftplogactive;
4804     } else {
4805 #endif /* NEWFTP */
4806         ftp = 0;
4807         xlogbuf = cxlogbuf;
4808         prev = cx_prev;
4809         active = cx_active;
4810 #ifdef NEWFTP
4811     }
4812 #endif /* NEWFTP */
4813
4814     debug(F101,"dologshow local","",local);
4815     debug(F101,"dologshow ftp","",ftp);
4816     debug(F111,"dologshow active",xlogbuf,active);
4817
4818     if (!xlogbuf[0]) {
4819         if (fc) {
4820             if (didsetlin || ftp)
4821               printf(" %s: No record.\n", ftp ? "FTP" : "Kermit");
4822             else
4823               printf(" %s: No connection.\n", ftp ? "FTP" : "Kermit");
4824         }
4825         return(prev);
4826     }
4827
4828 #ifdef NEWFTP
4829     if (ftp) {
4830         z = ftpisconnected() ? 1 : -1;
4831     } else {
4832 #endif /* NEWFTP */
4833         if (local) {                    /* See if we have an open connection */
4834             z = ttchk();
4835             debug(F101,"dologshow ttchk","",z);
4836             z = (z > -1) ? 1 : -2;
4837         } else {
4838             z = active ? 1 : -2;
4839         }
4840 #ifdef NEWFTP
4841     }
4842 #endif /* NEWFTP */
4843     if (z < 0L) {
4844         if (!fc)
4845           return(prev);
4846         else
4847           t2 = prev;
4848     }
4849     /* Note: NOT ckstrncpy! */
4850     strncpy(buf1,xlogbuf,17);           /* Copy of just the timestamp */
4851     buf1[17] = NUL;                     /* Terminate it */
4852     ckstrncpy(xbuf,xlogbuf+18,CXLOGBUFL); /* Copy that can be poked */
4853     debug(F111,"dologshow prev",xbuf,prev);
4854
4855     xwords(xbuf,31,info,1);             /* Break up into fields */
4856     d1 = mjd(buf1);                     /* Convert start time to MJD */
4857     ckstrncpy(buf2,ckdate(),31);        /* Current date */
4858     d2 = mjd(buf2);                     /* Convert to MJD */
4859     p = buf1;                           /* Point to start time */
4860     p[11] = NUL;
4861     p[14] = NUL;                        /* Convert to seconds */
4862     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4863     p[11] = ':';
4864     p[14] = ':';
4865     p = buf2;                           /* Ditto for current time */
4866     p[11] = NUL;
4867     p[14] = NUL;
4868     if (z > -1L) {
4869         t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
4870         t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Elapsed time so far */
4871     }
4872     if (fc) {
4873         p = NULL;
4874         if (t2 > -1L)                   /* Convert seconds to hh:mm:ss */
4875           p = hhmmss(t2);
4876         if (z > -1)
4877           s = "Active";
4878         else if (z == -2)
4879           s = "Closed";
4880         else
4881           s = "Unknown";
4882         printf("\n");                   /* Show results */
4883         printf(" Status:       %s\n",s);
4884         printf(" Opened:       %s\n",buf1);
4885         printf(" User:         %s\n",info[1] ? info[1] : "");
4886         printf(" PID:          %s\n",info[2] ? info[2] : "");
4887         for (i = 3; info[i]; i++) {
4888             c = info[i][0];
4889             s = (info[i]) ? info[i]+2 : "";
4890             switch (c) {
4891               case 'T': printf(" Type:         %s\n", s); break;
4892               case 'N': printf(" To:           %s\n", s); break;
4893               case 'P': printf(" Port:         %s\n", s); break;
4894               case 'H': printf(" From:         %s\n", s); break;
4895               case 'D': printf(" Device:       %s\n", s); break;
4896               case 'O': printf(" Origin:       %s\n", s); break;
4897               case 'E': break;
4898               default:  printf(" %s\n",info[i] ? info[i] : "");
4899             }
4900         }
4901         if (z < 0L)
4902           printf(" Elapsed time: %s\n", hhmmss(t2));
4903         else
4904           printf(" Elapsed time: %s\n", p ? p : "(unknown)");
4905         x = 0;
4906 #ifdef NETCONN
4907 #ifdef SSHBUILTIN
4908         if ( IS_SSH() ) x++;
4909 #endif /* SSHBUILTIN */
4910 #ifdef CK_ENCRYPTION
4911         if (ck_tn_encrypting() && ck_tn_decrypting()) x++;
4912 #endif /* CK_ENCRYPTION */
4913 #ifdef CK_SSL
4914         if (tls_active_flag || ssl_active_flag) x++;
4915 #endif /* CK_SSL */
4916 #ifdef RLOGCODE
4917 #ifdef CK_KERBEROS
4918 #ifdef CK_ENCRYPTION
4919         if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) x++;
4920 #endif /* CK_ENCRYPTION */
4921 #endif /* CK_KERBEROS */
4922 #endif /* RLOGCODE */
4923 #endif /* NETCONN */
4924         if (z > 0)
4925           printf(" Encrypted:    %s\n", x ? "Yes" : "No");
4926         printf(" Log:          %s\n", dialog ? diafil : "(none)");
4927         printf("\n");
4928     }
4929     return(t2 > -1L ? t2 : 0L);
4930 }
4931
4932 VOID
4933 dologline() {
4934     char * p;
4935     int n, m = 0;
4936
4937     dologend();                         /* Previous session not closed out? */
4938     cx_active = 1;                      /* Record is active */
4939     cx_prev = 0L;
4940     p = ckdate();                       /* Get timestamp */
4941     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL-1); /* Start record off with it */
4942     if (!uidbuf[0]) {
4943         debug(F100,"dologline uidbuf empty","",0);
4944 #ifdef UNIX                             /* Who has whoami()... */
4945         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
4946 #else
4947 #ifdef STRATUS
4948         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
4949 #else
4950         ckstrncpy(uidbuf,"UNKNOWN",UIDBUFLEN);
4951 #endif /* STRATUS */
4952 #endif /* UNIX */
4953     }
4954     m = strlen(uidbuf) + strlen(myhost) + strlen(ttname) + 32;
4955     if (n+m < CXLOGBUFL-1) {            /* Add serial device info */
4956         p = cxlogbuf+n;
4957         sprintf(p," %s %s T=SERIAL H=%s D=%s ", /* SAFE */
4958                 uidbuf,
4959                 ckgetpid(),
4960                 myhost,
4961                 ttname
4962                 );
4963     } else
4964       ckstrncpy(cxlogbuf,"LOGLINE BUFFER OVERFLOW",CXLOGBUFL);
4965     debug(F110,"dologline",cxlogbuf,0);
4966 }
4967
4968 #ifdef NETCONN
4969 VOID
4970 dolognet() {
4971     char * p, * s = "NET", * uu = uidbuf;
4972     char * port = "";
4973     int n, m, tcp = 0;
4974     char * h = NULL;
4975
4976     dologend();                         /* Previous session not closed out? */
4977     cx_prev = 0L;
4978     cx_active = 1;                      /* Record is active */
4979     p = ckdate();
4980     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL);
4981 #ifdef TCPSOCKET
4982     if (nettype == NET_TCPB || nettype == NET_TCPA) {
4983         tcp++;
4984         s = "TCP";
4985     } else if (nettype == NET_SSH) {
4986         s = "SSH";
4987         tcp++;
4988     }
4989 #endif /* TCPSOCKET */
4990 #ifdef ANYX25
4991     if (nettype == NET_SX25 || nettype == NET_VX25 || nettype == NET_IX25)
4992       s = "X25";
4993 #endif /* ANYX25 */
4994 #ifdef DECNET
4995     if (nettype == NET_DEC)
4996       s = "DECNET";
4997 #endif /* DECNET */
4998 #ifdef SUPERLAT
4999     if (nettype == NET_SLAT)
5000       s = "SUPERLAT";
5001 #endif /* SUPERLAT */
5002 #ifdef CK_NETBIOS
5003     if (nettype == NET_BIOS)
5004       s = "NETBIOS";
5005 #endif /* CK_NETBIOS */
5006
5007     if (!uu[0]) {
5008         debug(F100,"dolognet uidbuf empty","",0);
5009 #ifdef OS2ORUNIX                        /* Who has whoami()... */
5010         uu = (char *)whoami();
5011 #else
5012 #ifdef STRATUS
5013         uu = (char *)whoami();
5014 #else
5015         uu = "UNKNOWN";
5016 #endif /* STRATUS */
5017 #endif /* UNIX */
5018     }
5019 #ifdef TCPSOCKET
5020     if (tcp) {
5021         int k;
5022         makestr(&h,myhost);
5023         if ((k = ckindex(":",h,0,0,0)) > 0) {
5024             h[k-1] = NUL;
5025             port = &h[k];
5026         } else {
5027             int svcnum = gettcpport();
5028             if (svcnum > 0)
5029               port = ckitoa(svcnum);
5030             else
5031               port = "unk";
5032         }
5033     }
5034 #endif  /* TCPSOCKET */
5035     m = strlen(uu) + strlen(myhost) + strlen(ttname) + strlen(s) + 32;
5036     if (n+m < CXLOGBUFL-1) {            /* SAFE */
5037         p = cxlogbuf+n;
5038         sprintf(p," %s %s T=%s N=%s H=%s P=%s ",
5039                 uu,
5040                 ckgetpid(),
5041                 s,
5042                 ttname,
5043                 myhost,
5044                 port
5045                 );
5046     } else
5047       ckstrncpy(cxlogbuf,"LOGNET BUFFER OVERFLOW",CXLOGBUFL);
5048     debug(F110,"dolognet cxlogbuf",cxlogbuf,0);
5049     if (h) makestr(&h,NULL);
5050 }
5051 #endif /* NETCONN */
5052 #endif /* CKLOGDIAL */
5053
5054 #ifndef NODIAL
5055 /*
5056   Parse a DIAL-related string, stripping enclosing braces, if any.
5057 */
5058 static int
5059 dialstr(p,msg) char **p; char *msg; {
5060     int x;
5061     char *s;
5062
5063     if ((x = cmtxt(msg, "", &s, xxstring)) < 0)
5064       return(x);
5065     s = brstrip(s);                     /* Strip braces around. */
5066     debug(F110,"dialstr",s,0);
5067     makestr(p,*s?s:NULL);
5068     return(success = 1);
5069 }
5070
5071 VOID
5072 initmdm(x) int x; {
5073     MDMINF * p;
5074     int m;
5075
5076     mdmtyp = x;                         /* Set global modem type */
5077     debug(F101,"initmdm mdmtyp","",mdmtyp);
5078     debug(F101,"initmdm usermdm","",usermdm);
5079     if (x < 1) return;
5080
5081     m = usermdm ? usermdm : mdmtyp;
5082
5083     p = modemp[m];                      /* Point to modem info struct, and */
5084     /* debug(F101,"initmdm p","",p); */
5085     if (p) {
5086         dialec = p->capas & CKD_EC;     /* set DIAL ERROR-CORRECTION, */
5087         dialdc = p->capas & CKD_DC;     /* DIAL DATA-COMPRESSION, and */
5088         mdmspd = p->capas & CKD_SB ? 0 : 1; /* DIAL SPEED-MATCHING from it. */
5089         dialfc = FLO_AUTO;                  /* Modem's local flow control.. */
5090         dialmax   = p->max_speed;
5091         dialcapas = p->capas;
5092         dialesc   = p->esc_char;
5093     } else if (mdmtyp > 0) {
5094         printf("WARNING: modem info for \"%s\" not filled in yet\n",
5095                gmdmtyp()
5096                );
5097     }
5098
5099 /* Reset or set the SET DIAL STRING items ... */
5100
5101 #ifdef DEBUG
5102     if (deblog) {
5103         debug(F110,"initmdm dialini",dialini,0);
5104         debug(F110,"initmdm dialmstr ",dialmstr,0);
5105         debug(F110,"initmdm dialmprmt",dialmprmt,0);
5106         debug(F110,"initmdm dialcmd",dialcmd,0);
5107         debug(F110,"initmdm dialdcon",dialdcon,0);
5108         debug(F110,"initmdm dialdcoff",dialdcoff,0);
5109         debug(F110,"initmdm dialecon",dialecon,0);
5110         debug(F110,"initmdm dialecoff",dialecoff,0);
5111         debug(F110,"initmdm dialhcmd",dialhcmd,0);
5112         debug(F110,"initmdm dialhwfc",dialhwfc,0);
5113         debug(F110,"initmdm dialswfc",dialswfc,0);
5114         debug(F110,"initmdm dialnofc",dialnofc,0);
5115         debug(F110,"initmdm dialtone",dialtone,0);
5116         debug(F110,"initmdm dialpulse",dialpulse,0);
5117         debug(F110,"initmdm dialname",dialname,0);
5118         debug(F110,"initmdm dialaaon",dialaaon,0);
5119         debug(F110,"initmdm dialaaoff",dialaaoff,0);
5120         debug(F110,"initmdm dialx3",dialx3,0);
5121         debug(F110,"initmdm dialspon",dialspon,0);
5122         debug(F110,"initmdm dialspoff",dialspoff,0);
5123         debug(F110,"initmdm dialvol1",dialvol1,0);
5124         debug(F110,"initmdm dialvol2",dialvol2,0);
5125         debug(F110,"initmdm dialvol3",dialvol3,0);
5126         debug(F110,"initmdm dialini2",dialini2,0);
5127     }
5128 #endif /* DEBUG */
5129
5130     if (usermdm && p) { /* USER-DEFINED: copy info from specified template */
5131
5132         makestr(&dialini  ,p->wake_str);
5133         makestr(&dialmstr ,p->dmode_str);
5134         makestr(&dialmprmt,p->dmode_prompt);
5135         makestr(&dialcmd  ,p->dial_str);
5136         makestr(&dialdcon ,p->dc_on_str);
5137         makestr(&dialdcoff,p->dc_off_str);
5138         makestr(&dialecon ,p->ec_on_str);
5139         makestr(&dialecoff,p->ec_off_str);
5140         makestr(&dialhcmd ,p->hup_str);
5141         makestr(&dialhwfc ,p->hwfc_str);
5142         makestr(&dialswfc ,p->swfc_str);
5143         makestr(&dialnofc ,p->nofc_str);
5144         makestr(&dialtone ,p->tone);
5145         makestr(&dialpulse,p->pulse);
5146         makestr(&dialname ,"This space available (use SET MODEM NAME)");
5147         makestr(&dialaaon ,p->aa_on_str);
5148         makestr(&dialaaoff,p->aa_off_str);
5149         makestr(&dialx3   ,p->ignoredt);
5150         makestr(&dialspon ,p->sp_on_str);
5151         makestr(&dialspoff,p->sp_off_str);
5152         makestr(&dialvol1 ,p->vol1_str);
5153         makestr(&dialvol2 ,p->vol2_str);
5154         makestr(&dialvol3 ,p->vol3_str);
5155         makestr(&dialini2 ,p->ini2);
5156
5157     } else {                    /* Not user-defined, so wipe out overrides */
5158
5159         if (dialini)   makestr(&dialini,NULL);   /* Init-string */
5160         if (dialmstr)  makestr(&dialmstr,NULL);  /* Dial-mode-str */
5161         if (dialmprmt) makestr(&dialmprmt,NULL); /* Dial-mode-pro */
5162         if (dialcmd)   makestr(&dialcmd,NULL);   /* Dial-command  */
5163         if (dialdcon)  makestr(&dialdcon,NULL);  /* DC ON command */
5164         if (dialdcoff) makestr(&dialdcoff,NULL); /* DC OFF command */
5165         if (dialecon)  makestr(&dialecon,NULL);  /* EC ON command */
5166         if (dialecoff) makestr(&dialecoff,NULL); /* EC OFF command */
5167         if (dialhcmd)  makestr(&dialhcmd,NULL);  /* Hangup command */
5168         if (dialhwfc)  makestr(&dialhwfc,NULL);  /* Flow control... */
5169         if (dialswfc)  makestr(&dialswfc,NULL);  /*  */
5170         if (dialnofc)  makestr(&dialnofc,NULL);  /*  */
5171         if (dialtone)  makestr(&dialtone,NULL);  /* Dialing method */
5172         if (dialpulse) makestr(&dialpulse,NULL); /*  */
5173         if (dialname)  makestr(&dialname,NULL);  /* Modem name */
5174         if (dialaaon)  makestr(&dialaaon,NULL);  /* Autoanswer On */
5175         if (dialaaoff) makestr(&dialaaoff,NULL); /* Autoanswer Off */
5176         if (dialx3)    makestr(&dialx3,NULL);    /* Ignore dialtone */
5177         if (dialspon)  makestr(&dialspon,NULL);  /* Speaker On */
5178         if (dialspoff) makestr(&dialspoff,NULL); /* Speaker Off */
5179         if (dialvol1)  makestr(&dialvol1,NULL);  /* Low volume */
5180         if (dialvol2)  makestr(&dialvol2,NULL);  /* Medium volume */
5181         if (dialvol3)  makestr(&dialvol3,NULL);  /* High volume */
5182         if (dialini2)  makestr(&dialini2,NULL);  /* Init string 2 */
5183     }
5184     if (autoflow)                       /* Maybe change flow control */
5185       setflow();
5186
5187 #ifndef MINIDIAL
5188 #ifdef OLDTBCODE
5189     tbmodel = 0;           /* If it's a Telebit, we don't know the model yet */
5190 #endif /* OLDTBCODE */
5191 #endif /* MINIDIAL */
5192 }
5193
5194 #ifdef COMMENT
5195 /* Not implemented yet */
5196 int
5197 setanswer() {
5198     int x, y;
5199     extern int ans_cid, ans_ring;
5200     if ((x = cmkey(answertab,nanswertab,"","",xxstring)) < 0)
5201       return(x);
5202     switch (x) {
5203       case XYA_CID:
5204         return(seton(&ans_cid));
5205       case XYA_RNG:
5206         y = cmnum("How many rings before answering","1",10,&x,xxstring);
5207         y = setnum(&ans_rings,x,y,254);
5208         return(y);
5209     }
5210 }
5211 #endif /* COMMENT */
5212
5213 int
5214 setmodem() {                            /* SET MODEM */
5215
5216     int x, y, z;
5217     long zz;
5218     struct FDB k1, k2;
5219     extern int mdmset;
5220
5221     cmfdbi(&k1,_CMKEY,
5222            "Modem parameter","","",nsetmdm, 0, xxstring, setmdm, &k2);
5223     cmfdbi(&k2,_CMKEY,"","","",nmdm,0,xxstring,mdmtab,NULL);
5224     x = cmfdb(&k1);
5225     if (x < 0) {                        /* Error */
5226         if (x == -2 || x == -9)
5227           printf("?No keywords match: \"%s\"\n",atmbuf);
5228         return(x);
5229     }
5230     y = cmresult.nresult;               /* Keyword value */
5231     if (cmresult.fdbaddr == &k2) {      /* Modem-type keyword table */
5232         if ((x = cmcfm()) < 0)
5233           return(x);
5234         usermdm = 0;
5235         initmdm(cmresult.nresult);      /* Set the modem type. */
5236         return(success = 1);            /* Done */
5237     }
5238     switch (cmresult.nresult) {         /* SET MODEM keyword table. */
5239 #ifdef MDMHUP
5240       case XYDMHU:                      /* DIAL MODEM-HANGUP */
5241         if ((y = cmkey(mdmhang,4,"how to hang up modem",
5242                        "modem-command", xxstring)) < 0)
5243           return(y);
5244         if ((x = cmcfm()) < 0)
5245           return(x);
5246         dialmhu = y;
5247 #ifdef COMMENT
5248 /* Nope, I fixed it (2001 11 08) */
5249 #ifdef CK_SCOV5
5250         if (dialmhu == 0 && !quiet) {
5251             printf(
5252 "\n WARNING: RS-232 signal sampling and manipulation do not work\n"
5253                     );
5254             printf(
5255 " in the standard SCO OSR5 serial i/o drivers.  SET MODEM HANGUP-METHOD\n"
5256                    );
5257             printf(
5258 " MODEM-COMMAND is recommended for OSR5.\n\n"
5259                     );
5260         }
5261 #endif /* CK_SCOV5 */
5262 #endif /* COMMENT */
5263         return(success = 1);
5264 #endif /* MDMHUP */
5265
5266       case XYDCAP:
5267         zz = 0L;
5268         y = 0;
5269         while (y != -3) {
5270             if ((y = cmkey(mdmcap,nmdmcap,
5271                            "capability of modem", "", xxstring)) < 0) {
5272                 if (y == -3)
5273                   break;
5274                 else
5275                   return(y);
5276             }
5277             zz |= y;
5278         }
5279         if ((x = cmcfm()) < 0)
5280           return(x);
5281         dialcapas = zz;
5282         debug(F101,"setmodem autoflow","",autoflow);
5283         debug(F101,"setmodem flow 1","",flow);
5284         if (autoflow)                   /* Maybe change flow control */
5285           setflow();
5286         debug(F101,"setmodem flow 2","",flow);
5287         mdmspd = zz & CKD_SB ? 0 : 1;   /* Set MODEM SPEED-MATCHING from it. */
5288         return(success = 1);
5289
5290       case XYDMAX:
5291 #ifdef TN_COMPORT
5292         if (network && istncomport())
5293           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
5294         else
5295 #endif /* TN_COMPORT */
5296           x = cmkey(spdtab,nspd,line,"",xxstring);
5297         if (x < 0) {
5298             if (x == -3) printf("?value required\n");
5299             return(x);
5300         }
5301         if ((y = cmcfm()) < 0) return(y);
5302         dialmax = (long) x * 10L;
5303         if (dialmax == 70) dialmax = 75;
5304         return(success = 1);
5305
5306       case XYDSTR:                      /* These moved from SET DIAL */
5307       case XYDDC:
5308       case XYDEC:
5309       case XYDESC:
5310       case XYDFC:
5311       case XYDKSP:
5312       case XYDSPD:
5313       case XYDDIA:
5314         return(setdial(x));
5315
5316       case XYDTYP:
5317         if ((y = cmkey(mdmtab,nmdm,"modem type","none", xxstring)) < 0)
5318           return(y);
5319         if (y == dialudt) {             /* User-defined modem type */
5320             if ((x = cmkey(mdmtab,nmdm,"based on existing modem type",
5321                            "unknown", xxstring)) < 0)
5322               return(x);
5323         }
5324         if ((z = cmcfm()) < 0)
5325           return(z);
5326         usermdm = 0;
5327         usermdm = (y == dialudt) ? x : 0;
5328         initmdm(y);
5329         mdmset = (mdmtyp > 0);
5330         return(success = 1);
5331
5332       case XYDNAM:
5333         return(dialstr(&dialname,"Descriptive name for modem"));
5334
5335       case XYDMCD:                      /* SET MODEM CARRIER-WATCH */
5336         return(setdcd());
5337
5338       case XYDSPK:                      /* SET MODEM SPEAKER */
5339         return(seton(&mdmspk));
5340
5341       case XYDVOL:                      /* SET MODEM VOLUME */
5342         if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0)
5343           return(x);
5344         if ((y = cmcfm()) < 0)
5345           return(y);
5346         mdmvol = x;
5347         return(success = 1);
5348
5349       default:
5350         printf("Unexpected SET MODEM parameter\n");
5351         return(-9);
5352     }
5353 }
5354
5355 static int                              /* Set DIAL command options */
5356 setdial(y) int y; {
5357     int x = 0, z = 0;
5358     char *s = NULL;
5359
5360     if (y < 0)
5361       if ((y = cmkey(dialtab,ndial,"","",xxstring)) < 0)
5362         return(y);
5363     switch (y) {
5364       case XYDHUP:                      /* DIAL HANGUP */
5365         return(seton(&dialhng));
5366       case XYDINI:                      /* DIAL INIT-STRING */
5367         return(dialstr(&dialini,"Modem initialization string"));
5368       case XYDNPR:                      /* DIAL PREFIX */
5369         return(dialstr(&dialnpr,"Telephone number prefix"));
5370       case XYDDIA:                      /* DIAL DIAL-COMMAND */
5371         x = cmtxt("Dialing command for modem,\n\
5372  include \"%s\" to stand for phone number,\n\
5373  for example, \"set dial dial-command ATDT%s\\13\"",
5374                   "",
5375                   &s,
5376                   xxstring);
5377         if (x < 0 && x != -3)           /* Handle parse errors */
5378           return(x);
5379         s = brstrip(s);                 /* Strip braces or quotes */
5380         y = x = strlen(s);              /* Get length of text */
5381         if (y > 0) {                    /* If there is any text (left), */
5382             for (x = 0; x < y; x++) {   /* make sure they included "%s" */
5383                 if (s[x] != '%') continue;
5384                 if (s[x+1] == 's') break;
5385             }
5386             if (x == y) {
5387                 printf(
5388 "?Dial-command must contain \"%cs\" for phone number.\n",'%');
5389                 return(-9);
5390             }
5391         }
5392         if (dialcmd) {                  /* Free any previous string. */
5393             free(dialcmd);
5394             dialcmd = (char *) 0;
5395         }
5396         if (y > 0) {
5397             dialcmd = malloc(y + 1);    /* Allocate space for it */
5398             if (dialcmd)
5399               strcpy(dialcmd,s);        /* and make a safe copy. */
5400         }
5401         return(success = 1);
5402 #ifndef NOXFER
5403       case XYDKSP:                      /* DIAL KERMIT-SPOOF */
5404         return(seton(&dialksp));
5405 #endif /* NOXFER */
5406       case XYDTMO:                      /* DIAL TIMEOUT */
5407         y = cmnum("Seconds to wait for call completion","0",10,&x,xxstring);
5408         if (y < 0) return(y);
5409         y = cmnum("Kermit/modem timeout differential","10",10,&z,xxstring);
5410         if (y < 0) return(y);
5411         if ((y = cmcfm()) < 0)
5412           return(y);
5413         dialtmo = x;
5414         mdmwaitd = z;
5415       case XYDESC:                      /* DIAL ESCAPE-CHARACTER */
5416         y = cmnum("ASCII value of character to escape back to modem",
5417                   "43",10,&x,xxstring);
5418         y = setnum(&dialesc,x,y,128);
5419         if (y > -1 && dialesc < 0)      /* No escape character */
5420           dialmhu = 0;                  /* So no hangup by modem command */
5421         return(y);
5422       case XYDDPY:                      /* DIAL DISPLAY */
5423         return(seton(&dialdpy));
5424       case XYDSPD:                      /* DIAL SPEED-MATCHING */
5425                                         /* used to be speed-changing */
5426         if ((y = seton(&mdmspd)) < 0) return(y);
5427 #ifdef COMMENT
5428         mdmspd = 1 - mdmspd;            /* so here we reverse the meaning */
5429 #endif /* COMMENT */
5430         return(success = 1);
5431       case XYDMNP:                      /* DIAL MNP-ENABLE */
5432       case XYDEC:                       /* DIAL ERROR-CORRECTION */
5433         x = seton(&dialec);
5434         if (x > 0)
5435           if (!dialec) dialdc = 0;      /* OFF also turns off compression */
5436         return(x);
5437
5438       case XYDDC:                       /* DIAL COMPRESSION */
5439         x = seton(&dialdc);
5440         if (x > 0)
5441           if (dialdc) dialec = 1;       /* ON also turns on error correction */
5442         return(x);
5443
5444 #ifdef MDMHUP
5445       case XYDMHU:                      /* DIAL MODEM-HANGUP */
5446         return(seton(&dialmhu));
5447 #endif /* MDMHUP */
5448
5449 #ifndef NOSPL
5450       case XYDDIR:                      /* DIAL DIRECTORY (zero or more) */
5451         return(parsdir(0));             /* 0 means DIAL */
5452 #endif /* NOSPL */
5453
5454       case XYDSTR:                      /* DIAL STRING */
5455         if ((y = cmkey(mdmcmd,nmdmcmd,"","",xxstring)) < 0) return(y);
5456         switch (y) {
5457           case XYDS_AN:                 /* Autoanswer ON/OFF */
5458           case XYDS_DC:                 /* Data compression ON/OFF */
5459           case XYDS_EC:                 /* Error correction ON/OFF */
5460             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
5461               return(x);
5462             sprintf(tmpbuf,"Modem's command to %sable %s", /* SAFE */
5463                     x ? "en" : "dis",
5464                     (y == XYDS_DC) ? "compression" :
5465                     ((y == XYDS_EC) ? "error-correction" :
5466                     "autoanswer")
5467                     );
5468             if (x) {
5469                 if (y == XYDS_DC)
5470                   return(dialstr(&dialdcon,tmpbuf));
5471                 else if (y == XYDS_EC)
5472                   return(dialstr(&dialecon,tmpbuf));
5473                 else
5474                   return(dialstr(&dialaaon,tmpbuf));
5475             } else {
5476                 if (y == XYDS_DC)
5477                   return(dialstr(&dialdcoff,tmpbuf));
5478                 else if (y == XYDS_EC)
5479                   return(dialstr(&dialecoff,tmpbuf));
5480                 else
5481                   return(dialstr(&dialaaoff,tmpbuf));
5482             }
5483           case XYDS_HU:                 /*    hangup command */
5484             return(dialstr(&dialhcmd,"Modem's hangup command"));
5485           case XYDS_HW:                 /*    hwfc */
5486             return(dialstr(&dialhwfc,
5487                            "Modem's command to enable hardware flow control"));
5488           case XYDS_IN:                 /*    init */
5489             return(dialstr(&dialini,"Modem's initialization string"));
5490           case XYDS_NF:                 /*    no flow control */
5491             return(dialstr(&dialnofc,
5492                            "Modem's command to disable local flow control"));
5493           case XYDS_PX:                 /*    prefix */
5494             return(dialstr(&dialnpr,"Telephone number prefix for dialing"));
5495           case XYDS_SW:                 /*    swfc */
5496             return(dialstr(&dialswfc,
5497                    "Modem's command to enable local software flow control"));
5498           case XYDS_DT:                 /*    tone dialing */
5499             return(dialstr(&dialtone,
5500                    "Command to configure modem for tone dialing"));
5501           case XYDS_DP:                 /*    pulse dialing */
5502             return(dialstr(&dialpulse,
5503                            "Command to configure modem for pulse dialing"));
5504           case XYDS_MS:                 /*    dial mode string */
5505             return(dialstr(&dialmstr,
5506                          "Command to enter dial mode"));
5507           case XYDS_MP:                 /*    dial mode prompt */
5508             return(dialstr(&dialmprmt,
5509                            "Modem response upon entering dial mode"));
5510           case XYDS_SP:                 /* SPEAKER OFF */
5511             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0) return(x);
5512             if (x)
5513               return(dialstr(&dialspon,"Command to turn modem speaker on"));
5514             else
5515               return(dialstr(&dialspoff,"Command to turn modem speaker off"));
5516
5517           case XYDS_VO:                 /* VOLUME LOW */
5518             if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0) return(x);
5519             switch (x) {
5520               case 0:
5521               case 1:
5522                 return(dialstr(&dialvol1,
5523                                "Command for low modem speaker volume"));
5524               case 2:
5525                 return(dialstr(&dialvol2,
5526                            "Command for medium modem speaker volume"));
5527
5528               case 3:
5529                 return(dialstr(&dialvol3,
5530                                "Command for high modem speaker volume"));
5531               default:
5532                 return(-2);
5533             }
5534
5535           case XYDS_ID:                 /* IGNORE-DIALTONE */
5536             return(dialstr(&dialx3,
5537                            "Command to tell modem to ignore dialtone"));
5538
5539           case XYDS_I2:                 /* PREDIAL-INIT */
5540             return(dialstr(&dialini2,
5541                            "Command to send to modem just prior to dialing"));
5542
5543           default:
5544             printf("?Unexpected SET DIAL STRING parameter\n");
5545         }
5546
5547       case XYDFC:                       /* DIAL FLOW-CONTROL */
5548         if ((y = cmkey(dial_fc,4,"","auto",xxstring)) < 0) return(y);
5549         if ((x = cmcfm()) < 0) return(x);
5550         dialfc = y;
5551         return(success = 1);
5552
5553       case XYDMTH: {                    /* DIAL METHOD */
5554         extern int dialmauto;
5555         if ((y = cmkey(dial_m,ndial_m,"","default",xxstring)) < 0)
5556           return(y);
5557         if ((x = cmcfm()) < 0)
5558           return(x);
5559         if (y == XYDM_A) {              /* AUTO */
5560             dialmauto = 1;              /* local country code, if known. */
5561             dialmth = XYDM_D;
5562         } else {
5563           dialmauto = 0;                /* use the method specified */
5564           dialmth = y;
5565         }
5566         return(success = 1);
5567       }
5568       case XYDRTM:
5569         y = cmnum("Number of times to try dialing a number",
5570                   "1",10,&x,xxstring);
5571         z = setnum(&dialrtr,x,y,-1);
5572         if (z > -1 && dialrtr < 0) {
5573             printf("?Sorry, negative dial retries not valid: %d\n",dialrtr);
5574             return(-9);
5575         }
5576         return(z);
5577
5578       case XYDINT:
5579         y = cmnum("Seconds to wait between redial attempts",
5580                   "30",10,&x,xxstring);
5581         z = setnum(&dialint,x,y,-1);
5582         if (z > -1 && dialint < 0) {
5583             printf("?Sorry, negative dial interval not valid: %d\n",dialint);
5584             return(-9);
5585         }
5586         return(z);
5587
5588       case XYDLAC:                      /* DIAL AREA-CODE */
5589         if ((x = dialstr(&diallac,"Area code you are calling from")) < 0)
5590           return(x);
5591         if (diallac) {
5592             if (!rdigits(diallac)) {
5593                 printf("?Sorry, area code must be numeric\n");
5594                 if (*diallac == '(')
5595                   printf("(please omit the parentheses)\n");
5596                 if (*diallac == '/')
5597                   printf("(no slashes, please)\n");
5598                 if (diallac) free(diallac);
5599                 diallac = NULL;
5600                 return(-9);
5601             }
5602         }
5603         return(x);
5604
5605       case XYDCNF:                      /* CONFIRMATION */
5606         return(success = seton(&dialcnf));
5607
5608       case XYDCVT:                      /* CONVERT-DIRECTORY */
5609         if ((y = cmkey(dcnvtab,3,"","ask",xxstring)) < 0)
5610           return(y);
5611         if ((x = cmcfm()) < 0)
5612           return(x);
5613         dialcvt = y;
5614         return(success = 1);
5615
5616       case XYDLCC:                      /* DIAL COUNTRY-CODE */
5617         x = dialstr(&diallcc,"Country code you are calling from");
5618         if (x < 1) return(x);
5619         if (diallcc) {
5620             if (!rdigits(diallcc)) {
5621                 printf("?Sorry, country code must be numeric\n");
5622                 if (*diallcc == '+')
5623                   printf("(please omit the plus sign)\n");
5624                 if (diallcc) free(diallcc);
5625                 diallcc = NULL;
5626                 return(-9);
5627             }
5628             if (!strcmp(diallcc,"1")) { /* Set defaults for USA and Canada */
5629                 if (!dialldp)           /* Long-distance prefix */
5630                   makestr(&dialldp,"1");
5631                 if (!dialixp)           /* International dialing prefix */
5632                   makestr(&dialixp,"011");
5633                 if (ntollfree == 0) {   /* Toll-free area codes */
5634                     if ((dialtfc[0] = malloc(4))) {
5635                         strcpy(dialtfc[0],"800"); /* 1970-something */
5636                         ntollfree++;
5637                         if ((dialtfc[1] = malloc(4))) {
5638                             strcpy(dialtfc[1],"888"); /* 1996 */
5639                             ntollfree++;
5640                             if ((dialtfc[2] = malloc(4))) {
5641                                 strcpy(dialtfc[2],"877"); /* 5 April 1998 */
5642                                 ntollfree++;
5643                                 if ((dialtfc[3] = malloc(4))) {
5644                                     strcpy(dialtfc[3],"866"); /* 2000? */
5645                                     ntollfree++;
5646                                 }
5647                             }
5648                         }
5649                     }
5650                 }
5651                 if (!dialtfp)           /* Toll-free dialing prefix */
5652                   makestr(&dialtfp,"1");
5653 #ifdef COMMENT
5654 /* The time for this is past */
5655             } else if (!strcmp(diallcc,"358") &&
5656                        ((int) strcmp(zzndate(),"19961011") > 0)
5657                        ) {              /* Finland */
5658                 if (!dialldp)           /* Long-distance prefix */
5659                   makestr(&dialldp,"9");
5660                 if (!dialixp)           /* International dialing prefix */
5661                   makestr(&dialixp,"990");
5662 #endif /* COMMENT */
5663             } else {                    /* Everywhere else ... */
5664                 if (!dialldp) {
5665                     if ((dialldp = malloc(4)))
5666                       strcpy(dialldp,"0");
5667                 }
5668                 if (!dialixp) {
5669                     if ((dialixp = malloc(4)))
5670                       strcpy(dialixp,"00");
5671                 }
5672             }
5673             if (!strcmp(diallcc,"33"))  /* France */
5674               dialfld = 1;              /* Long-distance dialing is forced */
5675         }
5676         return(success = 1);
5677
5678       case XYDIXP:                      /* DIAL INTL-PREFIX */
5679         return(dialstr(&dialixp,"International dialing prefix"));
5680
5681       case XYDIXS:                      /* DIAL INTL-SUFFIX */
5682         return(dialstr(&dialixs,"International dialing suffix"));
5683
5684       case XYDLDP:                      /* DIAL LD-PREFIX */
5685         return(dialstr(&dialldp,"Long-distance dialing prefix"));
5686
5687       case XYDLDS:                      /* DIAL LD-SUFFIX */
5688         return(dialstr(&diallds,"Long-distance dialing suffix"));
5689
5690       case XYDLCP:                      /* DIAL LC-PREFIX */
5691         return(dialstr(&diallcp,"Local dialing prefix"));
5692
5693       case XYDLCS:                      /* DIAL LC-SUFFIX */
5694         return(dialstr(&diallcs,"Local dialing suffix"));
5695
5696 #ifdef COMMENT
5697       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
5698         return(dialstr(&dialpxx,"Exchange of PBX you are calling from"));
5699 #endif /* COMMENT */
5700
5701       case XYDPXI: {                    /* DIAL PBX-INTERNAL-PREFIX */
5702 #ifdef COMMENT
5703           return(dialstr(&dialpxi,
5704                        "Internal-call prefix of PBX you are calling from"));
5705 #else
5706           int x;
5707           if ((x = cmtxt("Internal-call prefix of PBX you are calling from",
5708                          "",&s,NULL)) < 0) /* Don't evaluate */
5709             return(x);
5710 #ifndef NOSPL
5711           if (*s) {
5712               char c, * p = tmpbuf;
5713               if (*s == '\\') {
5714                   c = *(s+1);
5715                   if (isupper(c)) c = tolower(c);
5716                   if (c != 'f' &&
5717                       ckstrcmp(s,"\\v(d$px)",8,0) &&
5718                       ckstrcmp(s,"\\v(d$pxx)",9,0) &&
5719                       ckstrcmp(s,"\\v(d$p)",7,0)) {
5720                       x = TMPBUFSIZ;
5721                       zzstring(s,&p,&x);
5722                       s = tmpbuf;
5723                   }
5724               }
5725           }
5726 #endif /* NOSPL */
5727           makestr(&dialpxi,s);
5728           return(1);
5729       }
5730 #endif /* COMMENT */
5731
5732       case XYDPXO:                      /* DIAL PBX-OUTSIDE-PREFIX */
5733         return(dialstr(&dialpxo,
5734                        "Outside-line prefix of PBX you are calling from"));
5735
5736       case XYDSFX:                      /* DIAL INTL-SUFFIX */
5737         return(dialstr(&dialsfx," Telephone number suffix for dialing"));
5738
5739       case XYDSRT:                      /* DIAL SORT */
5740         return(success = seton(&dialsrt));
5741
5742       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
5743       case XYDTFC: {                    /* DIAL TOLL-FREE-AREA-CODE  */
5744           int n, i;                     /* (zero or more of them...) */
5745           char * p[MAXTOLLFREE];        /* Temporary pointers */
5746           char * m;
5747           for (n = 0; n < MAXTOLLFREE; n++) {
5748               if (n == 0) {
5749                   m = (y == XYDTFC) ?
5750                   "Toll-free area code(s) in the country you are calling from"
5751                     : "Exchange(s) of PBX you are calling from";
5752               } else {
5753                   m = (y == XYDTFC) ?
5754                     "Another toll-free area code"
5755                       : "Another PBX exchange";
5756               }
5757               if ((x = cmfld(m,"",&s,xxstring)) < 0)
5758                 break;
5759               if (s) {
5760                   int k;
5761                   k = (int) strlen(s);
5762                   if (k > 0) {
5763                       if ((p[n] = malloc(k + 1)))
5764                         strcpy(p[n], s); /* safe */
5765                   } else break;
5766               } else break;
5767           }
5768           if (x == -3) {                /* Command was successful */
5769               int m;
5770               m = (y == XYDTFC) ? ntollfree : ndialpxx;
5771               if ((x = cmcfm()) < 0)
5772                 return(x);
5773               x = 1;
5774               for (i = 0; i < m; i++) { /* Remove old list, if any */
5775                   if  (y == XYDTFC)
5776                     makestr(&(dialtfc[i]),NULL);
5777                   else
5778                     makestr(&(dialpxx[i]),NULL);
5779               }
5780               if  (y == XYDTFC)
5781                 ntollfree = n;          /* New count */
5782               else
5783                 ndialpxx = n;
5784               for (i = 0; i < n; i++) { /* New list */
5785                   if  (y == XYDTFC)
5786                     makestr(&(dialtfc[i]),p[i]);
5787                   else
5788                     makestr(&(dialpxx[i]),p[i]);
5789               }
5790               x = 1;
5791           }
5792           for (i = 0; i < n; i++)
5793             if (p[i]) free(p[i]);
5794           return(x);
5795       }
5796
5797       case XYDTFP:                      /* TOLL-FREE-PREFIX */
5798         return(dialstr(&dialtfp,
5799                        " Long-distance prefix for toll-free dialing"));
5800
5801       case XYDCON:                      /* CONNECT */
5802         z = -1;
5803         if ((y = cmkey(crrtab,ncrr,"","auto",xxstring)) < 0) return(y);
5804         if (y != CAR_OFF)               /* AUTO or ON? */
5805           if ((z = cmkey(qvtab,nqvt,"","verbose",xxstring)) < 0) return(z);
5806         if ((x = cmcfm()) < 0) return(x);
5807         if (z > -1)
5808           dialcq = z;
5809         dialcon = y;
5810         return(success = 1);
5811
5812       case XYDRSTR:                     /* RESTRICT */
5813         if ((y = cmkey(drstrtab,4,"","none",xxstring)) < 0) return(y);
5814         if ((x = cmcfm()) < 0) return(x);
5815         dialrstr = y;
5816         return(success = 1);
5817
5818       case XYDLLAC: {                   /* Local area-code list  */
5819           int n, i;                     /* (zero or more of them...) */
5820           char * p[MAXLOCALAC]; /* Temporary pointers */
5821           for (n = 0; n < MAXLOCALAC; n++) {
5822               if ((x = cmfld(
5823                     "Area code to which calls from your area are local",
5824                        "",&s,xxstring)) < 0)
5825                 break;
5826               if (s) {
5827                   int k;
5828                   k = (int) strlen(s);
5829                   if (k > 0) {
5830                       if ((p[n] = malloc(k + 1)))
5831                         strcpy(p[n], s); /* safe */
5832                   } else break;
5833               } else break;
5834           }
5835           if (x == -3) {                /* Command was successful */
5836               if ((x = cmcfm()) < 0)
5837                 return(x);
5838               for (i = 0; i < nlocalac; i++) /* Remove old list, if any */
5839                 if (diallcac[i]) {
5840                     free(diallcac[i]);
5841                     diallcac[i] = NULL;
5842                 }
5843               nlocalac = n;             /* New count */
5844               for (i = 0; i < nlocalac; i++) /* New list */
5845                 diallcac[i] = p[i];
5846               return(success = 1);
5847           } else {                      /* Parse error, undo everything */
5848               for (i = 0; i < n; i++)
5849                 if (p[i]) free(p[i]);
5850               return(x);
5851           }
5852       }
5853
5854       case XYDFLD:
5855         return(success = seton(&dialfld));
5856
5857       case XYDIDT:                      /* DIAL IGNORE-DIALTONE */
5858         return(seton(&dialidt));
5859
5860       case XYDPAC:
5861         y = cmnum(
5862               "Milliseconds to pause between each character sent to dialer",
5863                   "",10,&x,xxstring);
5864         return(setnum(&dialpace,x,y,9999));
5865
5866 #ifndef NOSPL
5867       case XYDMAC:
5868         if ((x = cmfld("Name of macro to execute just prior to dialing",
5869                        "",&s,xxstring)) < 0) {
5870             if (x == -3)
5871               s = NULL;
5872             else
5873               return(x);
5874         }
5875         if (s) {
5876             if (!*s) {
5877                 s = NULL;
5878             } else {
5879                 ckstrncpy(line,s,LINBUFSIZ);
5880                 s = line;
5881             }
5882         }
5883         if ((x = cmcfm()) < 0)
5884           return(x);
5885         makestr(&dialmac,s);
5886         return(success = 1);
5887 #endif /* NOSPL */
5888
5889       case XYDPUCC:                     /* Pulse country codes */
5890       case XYDTOCC: {                   /* Tone country codes */
5891           int n, i;
5892           char * p[MAXTPCC];
5893           char * m;
5894           for (n = 0; n < MAXTPCC; n++) {
5895               if (n == 0) {
5896                   m = (y == XYDPUCC) ?
5897                   "Country code where Pulse dialing is required"
5898                     : "Country code where Tone dialing is available";
5899               } else
5900                 m = "Another country code";
5901               if ((x = cmfld(m,"",&s,xxstring)) < 0)
5902                 break;
5903               if (s) {
5904                   int k;
5905                   k = (int) strlen(s);
5906                   if (k > 0) {
5907                       if ((p[n] = malloc(k + 1)))
5908                         strcpy(p[n], s); /* safe */
5909                   } else break;
5910               } else break;
5911           }
5912           if (x == -3) {                /* Command was successful */
5913               int m;
5914               m = (y == XYDPUCC) ? ndialpucc : ndialtocc;
5915               if ((x = cmcfm()) < 0)
5916                 return(x);
5917               x = 1;
5918               for (i = 0; i < m; i++) { /* Remove old list, if any */
5919                   if (y == XYDPUCC)
5920                     makestr(&(dialpucc[i]),NULL);
5921                   else
5922                     makestr(&(dialtocc[i]),NULL);
5923               }
5924               if (y == XYDPUCC) {
5925                   ndialpucc = n;                /* New count */
5926               } else {
5927                   ndialtocc = n;
5928               }
5929               for (i = 0; i < n; i++) { /* New list */
5930                   if (y == XYDPUCC) {
5931                       makestr(&(dialpucc[i]),p[i]);
5932                   } else {
5933                       makestr(&(dialtocc[i]),p[i]);
5934                   }
5935               }
5936               x = 1;
5937           }
5938           for (i = 0; i < n; i++)
5939             if (p[i]) free(p[i]);
5940           return(x);
5941       }
5942       case XYDTEST:
5943         return(seton(&dialtest));
5944
5945       default:
5946         printf("?Unexpected SET DIAL parameter\n");
5947         return(-9);
5948     }
5949 }
5950
5951 #ifndef NOSHOW
5952 int                                     /* SHOW MODEM */
5953 shomodem() {
5954     MDMINF * p;
5955     int x, n, mdm;
5956     char c;
5957     long zz;
5958
5959 #ifdef IKSD
5960     if (inserver) {
5961         printf("Sorry, command disabled\r\n");
5962         return(success = 0);
5963     }
5964 #endif /* IKSD */
5965
5966     shmdmlin();
5967     printf("\n");
5968
5969     mdm = (mdmtyp > 0) ? mdmtyp : mdmsav;
5970     p = (mdm > 0) ? modemp[mdm] : NULL;
5971
5972     if (p) {
5973         printf(" %s\n\n", dialname ? dialname : p->name);
5974
5975         printf(" Modem capabilities:    ");
5976         zz = dialcapas ? dialcapas : p->capas;
5977         if (!zz) {
5978             printf(" (none)");
5979         } else {
5980             if (zz & CKD_AT) printf(" AT");
5981             if (zz & CKD_V25) printf(" ITU");
5982             if (zz & CKD_SB) printf(" SB");
5983             if (zz & CKD_EC) printf(" EC");
5984             if (zz & CKD_DC) printf(" DC");
5985             if (zz & CKD_HW) printf(" HWFC");
5986             if (zz & CKD_SW) printf(" SWFC");
5987             if (zz & CKD_KS) printf(" KS");
5988             if (zz & CKD_TB) printf(" TB");
5989         }
5990         printf("\n Modem carrier-watch:    ");
5991         if (carrier == CAR_OFF) printf("off\n");
5992         else if (carrier == CAR_ON) printf("on\n");
5993         else if (carrier == CAR_AUT) printf("auto\n");
5994         else printf("unknown\n");
5995
5996         printf(" Modem maximum-speed:    ");
5997         zz = (dialmax > 0L) ? dialmax : p->max_speed;
5998         if (zz > 0)
5999           printf("%ld bps\n", zz);
6000         else
6001           printf("(unknown)\n");
6002         printf(" Modem error-correction: %s\n", dialec ? "on" : "off");
6003         printf(" Modem compression:      %s\n", dialdc ? "on" : "off");
6004         printf(" Modem speed-matching:   %s",   mdmspd ? "on" : "off");
6005         printf(" (interface speed %s)\n", mdmspd ? "changes" : "is locked");
6006         printf(" Modem flow-control:     ");
6007         if (dialfc == FLO_NONE) printf("none\n");
6008         else if (dialfc == FLO_XONX) printf("xon/xoff\n");
6009         else if (dialfc == FLO_RTSC) printf("rts/cts\n");
6010         else if (dialfc == FLO_AUTO) printf("auto\n");
6011         printf(" Modem hangup-method:    %s\n",
6012                dialmhu ?
6013                "modem-command" :
6014                "rs232-signal"
6015                );
6016         printf(" Modem speaker:          %s\n", showoff(mdmspk));
6017         printf(" Modem volume:           %s\n",
6018                (mdmvol == 2) ? "medium" : ((mdmvol <= 1) ? "low" : "high"));
6019         printf(" Modem kermit-spoof:     %s\n", dialksp ? "on" : "off");
6020         c = (char) (x = (dialesc ? dialesc : p->esc_char));
6021         printf(" Modem escape-character: %d", x);
6022         if (isprint(c))
6023           printf(" (= \"%c\")",c);
6024         printf(
6025 "\n\nMODEM COMMANDs (* = set automatically by SET MODEM TYPE):\n\n");
6026         debug(F110,"show dialini",dialini,0);
6027         printf(" %c Init-string:          ", dialini ? ' ' : '*' );
6028         shods(dialini ? dialini : p->wake_str);
6029         printf(" %c Dial-mode-string:     ", dialmstr ? ' ' : '*' );
6030         shods(dialmstr ? dialmstr : p->dmode_str);
6031         n = local ? 19 : 20;
6032         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6033         printf(" %c Dial-mode-prompt:     ", dialmprmt ? ' ' : '*' );
6034         shods(dialmprmt ? dialmprmt : p->dmode_prompt);
6035         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6036         printf(" %c Dial-command:         ", dialcmd ? ' ' : '*' );
6037         shods(dialcmd ? dialcmd : p->dial_str);
6038         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6039         printf(" %c Compression on:       ", dialdcon ? ' ' : '*' );
6040         if (!dialdcon)
6041           debug(F110,"dialdcon","(null)",0);
6042         else
6043           debug(F110,"dialdcon",dialdcon,0);
6044         shods(dialdcon ? dialdcon : p->dc_on_str);
6045         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6046         printf(" %c Compression off:      ", dialdcoff ? ' ' : '*' );
6047         shods(dialdcoff ? dialdcoff : p->dc_off_str);
6048         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6049         printf(" %c Error-correction on:  ", dialecon ? ' ' : '*' );
6050         shods(dialecon ? dialecon : p->ec_on_str);
6051         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6052         printf(" %c Error-correction off: ", dialecoff ? ' ' : '*' );
6053         shods(dialecoff ? dialecoff : p->ec_off_str);
6054         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6055         printf(" %c Autoanswer on:        ", dialaaon ? ' ' : '*' );
6056         shods(dialaaon ? dialaaon : p->aa_on_str);
6057         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6058         printf(" %c Autoanswer off:       ", dialaaoff ? ' ' : '*' );
6059         shods(dialaaoff ? dialaaoff : p->aa_off_str);
6060         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6061
6062         printf(" %c Speaker on:           ", dialspon ? ' ' : '*' );
6063         shods(dialspon ? dialspon : p->sp_on_str);
6064         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6065         printf(" %c Speaker off:          ", dialspoff ? ' ' : '*' );
6066         shods(dialspoff ? dialspoff : p->sp_off_str);
6067         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6068         printf(" %c Volume low:           ", dialvol1 ? ' ' : '*' );
6069         shods(dialvol1 ? dialvol1 : p->vol1_str);
6070         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6071         printf(" %c Volume medium:        ", dialvol2 ? ' ' : '*' );
6072         shods(dialvol2 ? dialvol2 : p->vol2_str);
6073         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6074         printf(" %c Volume high:          ", dialvol3 ? ' ' : '*' );
6075         shods(dialvol3 ? dialvol3 : p->vol3_str);
6076         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6077
6078         printf(" %c Hangup-command:       ", dialhcmd ? ' ' : '*' );
6079         shods(dialhcmd ? dialhcmd : p->hup_str);
6080         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6081         printf(" %c Hardware-flow:        ", dialhwfc ? ' ' : '*' );
6082         shods(dialhwfc ? dialhwfc : p->hwfc_str);
6083         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6084         printf(" %c Software-flow:        ", dialswfc ? ' ' : '*' );
6085         shods(dialswfc ? dialswfc : p->swfc_str);
6086         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6087         printf(" %c No-flow-control:      ", dialnofc ? ' ' : '*' );
6088         shods(dialnofc ? dialnofc : p->nofc_str);
6089         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6090         printf(" %c Pulse:                ", dialpulse ? ' ' : '*');
6091         shods(dialpulse ? dialpulse : p->pulse);
6092         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6093         printf(" %c Tone:                 ", dialtone ? ' ' : '*');
6094         shods(dialtone ? dialtone : p->tone);
6095
6096         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6097         printf(" %c Ignore-dialtone:      ", dialx3 ? ' ' : '*');
6098         shods(dialx3 ? dialx3 : p->ignoredt);
6099
6100         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
6101         printf(" %c Predial-init:         ", dialini2 ? ' ' : '*');
6102         shods(dialini2 ? dialini2 : p->ini2);
6103
6104         if (++n > cmd_rows - 4) if (!askmore()) return(0); else n = 0;
6105         printf("\n For more info: SHOW DIAL and SHOW COMMUNICATIONS\n");
6106
6107     } else if (mdm > 0) {
6108         printf("Modem info for \"%s\" not filled in yet\n", gmdmtyp());
6109     } else printf(
6110 " No modem selected, so DIAL and most SET MODEM commands have no effect.\n\
6111  Use SET MODEM TYPE to select a modem.\n");
6112     return(success = 1);
6113 }
6114 #endif /* NOSHOW */
6115 #endif /* NODIAL */
6116
6117 #ifdef CK_TAPI
6118 int                                             /* TAPI action commands */
6119 dotapi() {
6120     int x,y;
6121     char *s;
6122
6123     if (!TAPIAvail) {
6124         printf("\nTAPI is unavailable on this system.\n");
6125         return(-9);
6126     }
6127     if ((y = cmkey(tapitab,ntapitab,"MS TAPI command","",xxstring)) < 0)
6128       return(y);
6129     switch (y) {
6130       case XYTAPI_CFG: {                        /* TAPI CONFIGURE-LINE */
6131           extern struct keytab * tapilinetab;
6132           extern struct keytab * _tapilinetab;
6133           extern int ntapiline;
6134           extern int LineDeviceId;
6135           int lineID=LineDeviceId;
6136           if (TAPIAvail)
6137             cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
6138           if (tapilinetab && _tapilinetab && ntapiline > 0) {
6139               int i=0, j = 9999, k = -1;
6140
6141               if ( LineDeviceId == -1 ) {
6142                   /* Find out what the lowest numbered TAPI device is */
6143                   /* and use it as the default.                       */
6144                   for (i = 0; i < ntapiline; i++ ) {
6145                       if (tapilinetab[i].kwval < j) {
6146                           k = i;
6147                       }
6148                   }
6149               } else {
6150                   /* Find the LineDeviceId in the table and use that entry */
6151                   for (i = 0; i < ntapiline; i++ ) {
6152                       if (tapilinetab[i].kwval == LineDeviceId) {
6153                           k = i;
6154                           break;
6155                       }
6156                   }
6157               }
6158               if (k >= 0)
6159                 s = _tapilinetab[k].kwd;
6160               else
6161                 s = "";
6162
6163               if ((y = cmkey(_tapilinetab,ntapiline,
6164                               "TAPI device name",s,xxstring)) < 0)
6165                 return(y);
6166               lineID = y;
6167           }
6168           if ((x = cmcfm()) < 0) return(x);
6169 #ifdef IKSD
6170           if (inserver) {
6171               printf("Sorry, command disabled\r\n");
6172               return(success = 0);
6173           }
6174 #endif /* ISKD */
6175           cktapiConfigureLine(lineID);
6176           break;
6177       }
6178       case XYTAPI_DIAL:                 /* TAPI DIALING-PROPERTIES */
6179         if ((x = cmcfm()) < 0)
6180           return(x);
6181 #ifdef IKSD
6182         if (inserver) {
6183             printf("Sorry, command disabled\r\n");
6184             return(success = 0);
6185         }
6186 #endif /* ISKD */
6187         cktapiDialingProp();
6188         break;
6189     }
6190     return(success = 1);
6191 }
6192
6193 static int                              /* SET TAPI command options */
6194 settapi() {
6195     int x, y;
6196     char *s;
6197
6198     if (!TAPIAvail) {
6199         printf("\nTAPI is unavailable on this system.\n");
6200         return(-9);
6201     }
6202     if ((y = cmkey(settapitab,nsettapitab,"MS TAPI option","",xxstring)) < 0)
6203       return(y);
6204     switch (y) {
6205       case XYTAPI_USE:
6206         return (success = seton(&tapiusecfg));
6207       case XYTAPI_LGHT:
6208         return (success = seton(&tapilights));
6209       case XYTAPI_PRE:
6210         return (success = seton(&tapipreterm));
6211       case XYTAPI_PST:
6212         return (success = seton(&tapipostterm));
6213       case XYTAPI_INA:
6214         y = cmnum("seconds of inactivity before auto-disconnect",
6215                   "0",10,&x,xxstring);
6216         return(setnum(&tapiinactivity,x,y,65535));
6217       case XYTAPI_BNG:
6218         y = cmnum("seconds to wait for credit card tone",
6219                   "8",10,&x,xxstring);
6220         return(setnum(&tapibong,x,y,90));
6221       case XYTAPI_MAN:
6222         return (success = seton(&tapimanual));
6223       case XYTAPI_CON:                  /* TAPI CONVERSIONS */
6224         return (success = setonaut(&tapiconv));
6225       case XYTAPI_LIN:                  /* TAPI LINE */
6226         x = setlin(XYTAPI_LIN,1,0);
6227         if (x > -1) didsetlin++;
6228         return(x);
6229       case XYTAPI_PASS: {               /* TAPI PASSTHROUGH */
6230 #ifdef NODIAL
6231           printf("\n?Modem-dialing not supported\n");
6232           return(-9);
6233 #else /* NODIAL */
6234           /* Passthrough became Modem-dialing which is an antonym */
6235           success = seton(&tapipass);
6236           tapipass = !tapipass;
6237           return (success);
6238 #endif /* NODIAL */        
6239       }
6240       case XYTAPI_LOC: {                /* TAPI LOCATION */
6241           extern char tapiloc[];
6242           extern int tapilocid;
6243           int i = 0, j = 9999, k = -1;
6244
6245           cktapiBuildLocationTable(&tapiloctab, &ntapiloc);
6246           if (!tapiloctab || !ntapiloc) {
6247               printf("\nNo TAPI Locations are configured for this system\n");
6248               return(-9);
6249           }
6250           if (tapilocid == -1)
6251             tapilocid = cktapiGetCurrentLocationID();
6252
6253           /* Find the current tapiloc entry */
6254           /* and use it as the default. */
6255           for (k = 0; k < ntapiloc; k++) {
6256               if (tapiloctab[k].kwval == tapilocid)
6257                 break;
6258           }
6259           if (k >= 0 && k < ntapiloc)
6260             s = tapiloctab[k].kwd;
6261           else
6262             s = "";
6263
6264           if ((y = cmkey(tapiloctab,ntapiloc, "TAPI location",s,xxstring)) < 0)
6265             return(y);
6266
6267           if ((x = cmcfm()) < 0)
6268             return(x);
6269 #ifdef IKSD
6270           if (inserver) {
6271               printf("Sorry, command disabled\r\n");
6272               return(success = 0);
6273           }
6274 #endif /* IKSD */
6275           cktapiFetchLocationInfoByID( y );
6276 #ifndef NODIAL
6277           CopyTapiLocationInfoToKermitDialCmd();
6278 #endif /* NODIAL */
6279         }
6280         break;
6281     }
6282     return(success=1);
6283 }
6284 #endif /* CK_TAPI */
6285 #endif /* NOLOCAL */
6286
6287 #ifndef NOSPL
6288 /* Method for evaluating \%x and \&x[] variables */
6289
6290 static struct keytab varevaltab[] = {
6291     { "recursive", 1, 0 },
6292     { "simple",    0, 0 }
6293 };
6294 static int nvarevaltab = (sizeof(varevaltab) / sizeof(struct keytab));
6295
6296 int
6297 setvareval() {
6298     int x = 0, y = 0;
6299     extern int vareval;
6300 #ifdef DCMDBUF
6301     extern int * xvarev;
6302 #else
6303     extern int xvarev[];
6304 #endif /* DCMDBUF */
6305
6306     if ((x = cmkey(varevaltab,
6307                    nvarevaltab, 
6308                    "Method for evaluating \\%x and \\&x[] variables",
6309                    "",
6310                    xxstring)) < 0)
6311       return(x);
6312     if ((y = cmcfm()) < 0)
6313       return(y);
6314     xvarev[cmdlvl] = x;
6315     vareval = x;
6316     return(success = 1);
6317 }
6318
6319 #ifdef CK_ANSIC                         /* SET ALARM */
6320 int
6321 setalarm(long xx)
6322 #else
6323 int
6324 setalarm(xx) long xx;
6325 #endif /* CK_ANSIC */
6326 /* setalarm */ {
6327 #ifdef COMMENT
6328     int yyyy, mm, dd, x;
6329     char *s;
6330     long zz;
6331     char buf[6];
6332 #endif /* COMMENT */
6333     long sec, jd;
6334     char xbuf[20], * p;
6335
6336     debug(F101,"setalarm xx","",xx);
6337     ck_alarm = 0L;                      /* 0 = no alarm (in case of error) */
6338     if (xx < 0L) {
6339         printf("%ld - illegal value, must be 0 or positive\n", xx);
6340         return(-9);
6341     }
6342     if (xx == 0L) {                     /* CLEAR ALARM */
6343         alrm_date[0] = NUL;
6344         alrm_time[0] = NUL;
6345         return(1);
6346     }
6347 #ifdef COMMENT
6348     x = 8;                              /* Get current date */
6349     s = alrm_date;
6350     if (zzstring("\\v(ndate)",&s,&x) < 0) {
6351         printf("Internal date error, sorry.\n");
6352         alrm_date[0] = SP;
6353         return(-9);
6354     }
6355     x = 5;                              /* Get current time */
6356     s = alrm_time;
6357     if (zzstring("\\v(ntime)",&s,&x) < 0) {
6358         printf("Internal time error, sorry.\n");
6359         alrm_time[0] = SP;
6360         return(-9);
6361     }
6362     sprintf(buf,"%05ld",atol(alrm_time)); /* SAFE (20) */
6363     ckstrncpy(alrm_time,buf,8);
6364     debug(F110,"SET ALARM date (1)",alrm_date,0);
6365     debug(F110,"SET ALARM time (1)",alrm_time,0);
6366
6367     if ((zz = atol(alrm_time) + xx) < 0L) {
6368         printf("Internal time conversion error, sorry.\n");
6369         return(-9);
6370     }
6371     if (zz >= 86400L) {                 /* Alarm crosses midnight */
6372         char d[10];                     /* Local date buffer */
6373         int lastday;                    /* Last day of this month */
6374
6375         ckstrncpy(d,alrm_date,8);       /* We'll have to change the date */
6376
6377         x = (zz / 86400L);              /* How many days after today */
6378
6379         dd = atoi((char *)(d+6));       /* Parse yyyymmdd */
6380         d[6] = NUL;                     /* into yyyy, mm, dd ... */
6381         mm = atoi((char *)(d+4));
6382         d[4] = NUL;
6383         yyyy = atoi((char *)d);
6384
6385         /* How many days in this month */
6386
6387         lastday = mdays[mm];
6388         if (mm == 2 && yyyy % 4 == 0)   /* Works thru 2099 AD... */
6389           lastday++;
6390
6391         if (dd + x > lastday) {         /* Dumb loop */
6392             int y;
6393
6394             x -= (mdays[mm] - dd);      /* Deduct rest of this month's days */
6395
6396             /* There's a more elegant way to do this... */
6397
6398             while (1) {
6399                 mm++;                   /* Next month */
6400                 if (mm > 12) {          /* Wrap around */
6401                     mm = 1;             /* Jan, next year */
6402                     yyyy++;
6403                 }
6404                 y = mdays[mm];          /* Days in new month */
6405                 if (mm == 2 && yyyy % 4 == 0) /* Feb in leap year */
6406                   y++;                  /* Works until 2100 AD */
6407                 if (x - y < 1)
6408                   break;
6409                 x -= y;
6410             }
6411             dd = x;                     /* Day of alarm month */
6412         } else dd += x;
6413
6414         sprintf(alrm_date,"%04d%02d%02d",yyyy,mm,dd); /* SAFE (24) */
6415         zz = zz % 86400L;
6416     }
6417     sprintf(alrm_time,"%ld",zz);        /* SAFE (24) */
6418     debug(F110,"SET ALARM date (2)",alrm_date,0);
6419     debug(F110,"SET ALARM time (2)",alrm_time,0);
6420     ck_alarm = xx;
6421 #else
6422     /* Jul 1998 */
6423     ckstrncpy(xbuf,ckcvtdate("",1),20); /* Get current date and time */
6424     p = xbuf;
6425     ckstrncpy(alrm_date,xbuf,10);
6426     alrm_date[8] = NUL;
6427     sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
6428     debug(F110,"SET ALARM date (1)",alrm_date,0);
6429     debug(F101,"SET ALARM time (1)","",sec);
6430     if ((sec += xx) < 0L) {
6431         printf("Internal time conversion error, sorry.\n");
6432         return(-9);
6433     }
6434     if (sec >= 86400L) {                /* Alarm crosses midnight */
6435         long days;
6436         days = sec / 86400L;
6437         jd = mjd(p) + days;             /* Get modified Julian date */
6438         ckstrncpy(alrm_date,mjd2date(jd),10);
6439         sec %= 86400L;
6440     }
6441     sprintf(alrm_time,"%05ld",sec);     /* SAFE (24) */
6442     debug(F110,"SET ALARM date (2)",alrm_date,0);
6443     debug(F110,"SET ALARM time (2)",alrm_time,0);
6444     ck_alarm = 1;                       /* Alarm is set */
6445
6446 #endif /* COMMENT */
6447     return(success = 1);
6448 }
6449 #endif /* NOSPL */
6450
6451 #ifndef NOSETKEY
6452 int
6453 dosetkey() {                            /* SET KEY */
6454     int x, y;
6455     int flag = 0;
6456     int kc;                             /* Key code */
6457     char *s;                            /* Key binding */
6458 #ifndef NOKVERBS
6459     char *p;                            /* Worker */
6460 #endif /* NOKVERBS */
6461 #ifdef OS2
6462     extern int os2gks;
6463     extern int mskkeys;
6464     extern int initvik;
6465 #endif /* OS2 */
6466
6467     x_ifnum = 1;
6468     y = cmnum("numeric key code, or the word CLEAR,","",10,&kc,xxstring);
6469     x_ifnum = 0;
6470     if (y < 0) {
6471         debug(F111,"SET KEY",atmbuf,y);
6472         if (y == -2) {                  /* Not a valid number */
6473             if ((y = strlen(atmbuf)) < 0) /* Check for SET KEY CLEAR */
6474               return(-2);
6475             if (ckstrcmp(atmbuf,"clear",y,0))
6476               return(-2);
6477             if ((x = cmcfm()) < 0)
6478               return(x);
6479             for (y = 0; y < KMSIZE; y++) {
6480                 keymap[y] = (KEY) y;
6481                 macrotab[y] = NULL;
6482             }
6483 #ifdef OS2
6484             keymapinit();               /* Special OS/2 initializations */
6485             initvik = 1;                /* Update the VIK table */
6486 #endif /* OS2 */
6487             return(1);
6488         } else if (y == -3) {           /* SET KEY <Return> */
6489             printf(" Press key to be defined: "); /* Prompt for a keystroke */
6490 #ifdef UNIX
6491 #ifdef NOSETBUF
6492             fflush(stdout);
6493 #endif /* NOSETBUF */
6494 #endif /* UNIX */
6495             conbin((char)escape);       /* Put terminal in binary mode */
6496 #ifdef OS2
6497             os2gks = 0;                 /* Turn off Kverb preprocessing */
6498 #endif /* OS2 */
6499             kc = congks(0);             /* Get character or scan code */
6500 #ifdef OS2
6501             os2gks = 1;                 /* Turn on Kverb preprocessing */
6502 #endif /* OS2 */
6503             concb((char)escape);        /* Restore terminal to cbreak mode */
6504             if (kc < 0) {               /* Check for error */
6505                 printf("?Error reading key\n");
6506                 return(0);
6507             }
6508 #ifdef OS2
6509             shokeycode(kc,-1);          /* Show current definition */
6510 #else
6511             shokeycode(kc);             /* Show current definition */
6512 #endif /* OS2 */
6513             flag = 1;                   /* Remember it's a multiline command */
6514         } else                          /* Error */
6515           return(y);
6516     }
6517
6518     /* Normal SET KEY <scancode> <value> command... */
6519
6520 #ifdef OS2
6521     if (mskkeys)
6522       kc = msktock(kc);
6523 #endif /* OS2 */
6524
6525     if (kc < 0 || kc >= KMSIZE) {
6526         printf("?key code must be between 0 and %d\n", KMSIZE - 1);
6527         return(-9);
6528     }
6529     if (kc == escape) {
6530         printf("Sorry, %d is the CONNECT-mode escape character\n",kc);
6531         return(-9);
6532     }
6533 #ifdef OS2
6534     wideresult = -1;
6535 #endif /* OS2 */
6536     if (flag) {
6537         cmsavp(psave,PROMPTL);
6538         cmsetp(" Enter new definition: ");
6539         cmini(ckxech);
6540         cmflgs = 0;
6541         prompt(NULL);
6542     }
6543   def_again:
6544     if (flag)
6545       cmres();
6546     if ((y = cmtxt("key definition,\n\
6547 or Ctrl-C to cancel this command,\n\
6548 or Enter to restore default definition",
6549                    "",&s,NULL)) < 0) {
6550         if (flag)                       /* Handle parse errors */
6551           goto def_again;
6552         else
6553           return(y);
6554     }
6555     s = brstrip(s);
6556 #ifndef NOKVERBS
6557     p = s;                              /* Save this place */
6558 #endif /* NOKVERBS */
6559 /*
6560   If the definition included any \Kverbs, quote the backslash so the \Kverb
6561   will still be in the definition when the key is pressed.  We don't do this
6562   in zzstring(), because \Kverbs are valid only in this context and nowhere
6563   else.
6564
6565   We use this code active for all versions that support SET KEY, even if they
6566   don't support \Kverbs, because otherwise \K would behave differently for
6567   different versions.
6568 */
6569     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
6570         if ((x > 0) &&
6571             (s[x] == 'K' || s[x] == 'k')
6572             ) {                         /* Have K */
6573
6574             if ((x == 1 && s[x-1] == CMDQ) ||
6575                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
6576                 line[y++] = CMDQ;       /* Make it \\K */
6577             }
6578             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
6579                 line[y-1] = CMDQ;       /* Have \{K */
6580                 line[y++] = '{';        /* Make it \\{K */
6581             }
6582         }
6583         line[y] = s[x];
6584     }
6585     line[y++] = NUL;                    /* Terminate */
6586     s = line + y + 1;                   /* Point to after it */
6587     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
6588     if ((x < (LINBUFSIZ / 2)) ||
6589         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
6590         printf("?Key definition too long\n");
6591         if (flag) cmsetp(psave);
6592         return(-9);
6593     }
6594     s = line + y + 1;                   /* Point to result. */
6595
6596 #ifndef NOKVERBS
6597 /*
6598   Special case: see if the definition starts with a \Kverb.
6599   If it does, point to it with p, otherwise set p to NULL.
6600 */
6601     p = s;
6602     if (*p++ == CMDQ) {
6603         if (*p == '{') p++;
6604         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
6605     }
6606 #endif /* NOKVERBS */
6607
6608     if (macrotab[kc]) {                 /* Possibly free old macro from key. */
6609         free((char *)macrotab[kc]);
6610         macrotab[kc] = NULL;
6611     }
6612     switch (strlen(s)) {                /* Action depends on length */
6613       case 0:                           /* Reset to default binding */
6614         keymap[kc] = (KEY) kc;
6615         break;
6616       case 1:                           /* Single character */
6617         keymap[kc] = (CHAR) *s;
6618         break;
6619       default:                          /* Character string */
6620 #ifndef NOKVERBS
6621         if (p) {
6622             y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
6623             debug(F101,"set key kverb lookup",0,y); /* exact match required */
6624             if (y > -1) {
6625                 keymap[kc] = F_KVERB | y;
6626                 break;
6627             }
6628         }
6629 #endif /* NOKVERBS */
6630         keymap[kc] = (KEY) kc;
6631         macrotab[kc] = (MACRO) malloc(strlen(s)+1);
6632         if (macrotab[kc])
6633           strcpy((char *) macrotab[kc], s); /* safe */
6634         break;
6635     }
6636     if (flag) cmsetp(psave);
6637 #ifdef OS2
6638     initvik = 1;                        /* Update VIK table */
6639 #endif /* OS2 */
6640     return(1);
6641 }
6642 #endif /* NOSETKEY */
6643
6644 #ifdef STOPBITS
6645 struct keytab stoptbl[] = {
6646     { "1", 1, 0 },
6647     { "2", 2, 0 }
6648 };
6649 #endif /* STOPBITS */
6650
6651 static struct keytab sertbl[] = {
6652     { "7E1", 0, 0 },
6653     { "7E2", 1, 0 },
6654     { "7M1", 2, 0 },
6655     { "7M2", 3, 0 },
6656     { "7O1", 4, 0 },
6657     { "7O2", 5, 0 },
6658     { "7S1", 6, 0 },
6659     { "7S2", 7, 0 },
6660 #ifdef HWPARITY
6661     { "8E1", 9, 0 },
6662     { "8E2", 10, 0 },
6663 #endif /* HWPARITY */
6664     { "8N1", 8, 0 },
6665 #ifdef HWPARITY
6666     { "8N2", 11, 0 },
6667     { "8O1", 12, 0 },
6668     { "8O2", 13, 0 },
6669 #endif /* HWPARITY */
6670     { "", 0, 0 }
6671 };
6672 static int nsertbl = (sizeof(sertbl) / sizeof(struct keytab)) - 1;
6673
6674 static char * sernam[] = {              /* Keep this in sync with sertbl[] */
6675   "7E1", "7E2", "7M1", "7M2", "7O1", "7O2", "7S1", "7S2",
6676   "8N1", "8E1", "8E2", "8N2", "8O1", "8O2"
6677 };
6678
6679 static struct keytab optstab[] = {      /* SET OPTIONS table */
6680 #ifndef NOFRILLS
6681     { "delete",    XXDEL,   0},            /* DELETE */
6682 #endif /* NOFRILLS */
6683     { "directory", XXDIR,   0},         /* DIRECTORY */
6684 #ifdef CKPURGE
6685     { "purge",     XXPURGE, 0},         /* PURGE */
6686 #endif /* CKPURGE */
6687     { "type",      XXTYP,   0},         /* TYPE */
6688     { "", 0, 0}
6689 };
6690 static int noptstab =  (sizeof(optstab) / sizeof(struct keytab)) - 1;
6691
6692 #ifndef NOXFER
6693 /*
6694   PROTOCOL SELECTION.  Kermit is always available.  If CK_XYZ is defined at
6695   compile time, then the others become selections also.  In OS/2 and
6696   Windows, they are integrated and the various SET commands (e.g. "set file
6697   type") affect them as they would Kermit.  In other OS's (UNIX, VMS, etc),
6698   they are external protocols which are run via Kermit's REDIRECT mechanism.
6699   All we do is collect and verify the filenames and pass them along to the
6700   external protocol.
6701 */
6702 struct keytab protos[] = {
6703 #ifdef CK_XYZ
6704     "g",          PROTO_G,  CM_INV,
6705 #endif /* CK_XYZ */
6706     "kermit",     PROTO_K,  0,
6707 #ifdef CK_XYZ
6708     "other",      PROTO_O,  0,
6709     "x",          PROTO_X,  CM_INV|CM_ABR,
6710     "xmodem",     PROTO_X,  0,
6711     "xmodem-crc", PROTO_XC, 0,
6712     "y",          PROTO_Y,  CM_INV|CM_ABR,
6713     "ymodem",     PROTO_Y,  0,
6714     "ymodem-g",   PROTO_G,  0,
6715     "zmodem",     PROTO_Z,  0
6716 #endif /* CK_XYZ */
6717 };
6718 int nprotos =  (sizeof(protos) / sizeof(struct keytab));
6719
6720 #ifndef XYZ_INTERNAL
6721 #ifndef NOPUSH
6722 #define EXP_HANDLER 1
6723 #define EXP_STDERR  2
6724 #define EXP_TIMO    3
6725
6726 static struct keytab extprotab[] = {
6727     { "handler",          EXP_HANDLER, 0 },
6728     { "redirect-stderr",  EXP_STDERR, 0 },
6729     { "timeout",          EXP_TIMO, 0 }
6730 };
6731 static int nxtprotab =  (sizeof(extprotab) / sizeof(struct keytab));
6732 #endif  /* NOPUSH */
6733 #endif  /* XYZ_INTERNAL */
6734
6735 #define XPCMDLEN 71
6736
6737 _PROTOTYP(static int protofield, (char *, char *, char *));
6738 _PROTOTYP(static int setproto, (void));
6739
6740 static int
6741 protofield(current, help, px) char * current, * help, * px; {
6742
6743     char *s, tmpbuf[XPCMDLEN+1];
6744     int x;
6745
6746     if (current)                        /* Put braces around default */
6747       ckmakmsg(tmpbuf,TMPBUFSIZ,"{",current,"}",NULL);
6748     else
6749       tmpbuf[0] = NUL;
6750
6751     if ((x = cmfld(help, (char *)tmpbuf, &s, xxstring)) < 0)
6752       return(x);
6753     if ((int)strlen(s) > XPCMDLEN) {
6754         printf("?Sorry - maximum length is %d\n", XPCMDLEN);
6755         return(-9);
6756     } else if (*s) {
6757         strcpy(px,s);                   /* safe */
6758     } else {
6759         px = NULL;
6760     }
6761     return(x);
6762 }
6763
6764 static int
6765 setproto() {                            /* Select a file transfer protocol */
6766     /* char * s = NULL; */
6767     int x = 0, y;
6768     char s1[XPCMDLEN+1], s2[XPCMDLEN+1], s3[XPCMDLEN+1];
6769     char s4[XPCMDLEN+1], s5[XPCMDLEN+1], s6[XPCMDLEN+1], s7[XPCMDLEN+1];
6770     char * p1 = s1, * p2 = s2, *p3 = s3;
6771     char * p4 = s4, * p5 = s5, *p6 = s6, *p7 = s7;
6772
6773 #ifdef XYZ_INTERNAL
6774     extern int p_avail;
6775 #else
6776 #ifndef CK_REDIR
6777     x = 1;
6778 #endif /* CK_REDIR */
6779 #endif /* XYZ_INTERNAL */
6780     s1[0] = NUL;
6781     s2[0] = NUL;
6782     s3[0] = NUL;
6783     s4[0] = NUL;
6784     s5[0] = NUL;
6785     s6[0] = NUL;
6786
6787     if ((y = cmkey(protos,nprotos,"","kermit",xxstring)) < 0)
6788       return(y);
6789
6790     if (x && y != PROTO_K) {
6791         printf(
6792            "?Sorry, REDIRECT capability required for external protocols.\n");
6793         return(-9);
6794     }
6795     if ((x = protofield(ptab[y].h_b_init,
6796      "Optional command to send to host prior to uploading in binary mode",
6797                p1)) < 0) {
6798         if (x == -3) {
6799             protocol = y;               /* Set protocol but don't change */
6800             return(1);                  /* anything else */
6801         } else
6802           return(x);
6803     }
6804     if ((x = protofield(ptab[y].h_t_init,
6805      "Optional command to send to host prior to uploading in text mode",
6806                p2)) < 0) {
6807         if (x == -3)
6808           goto protoexit;
6809         else
6810           return(x);
6811     }
6812
6813     if (y == PROTO_K) {
6814         if ((x = protofield(ptab[y].h_x_init,
6815                     "Optional command to send to host to start Kermit server",
6816                             p3)) < 0) {
6817             if (x == -3)
6818               goto protoexit;
6819             else
6820               return(x);
6821         }
6822     }
6823
6824
6825 #ifndef XYZ_INTERNAL                    /* If XYZMODEM are external... */
6826
6827     if (y != PROTO_K) {
6828         if ((x = protofield(ptab[y].p_b_scmd,
6829                  "External command to SEND in BINARY mode with this protocol",
6830                             p4)) < 0) {
6831             if (x == -3)
6832               goto protoexit;
6833             else
6834               return(x);
6835         }
6836         if ((x = protofield(ptab[y].p_t_scmd,
6837                  "External command to SEND in TEXT mode with this protocol",
6838                             p5)) < 0) {
6839             if (x == -3)
6840               goto protoexit;
6841             else
6842               return(x);
6843         }
6844         if ((x = protofield(ptab[y].p_b_rcmd,
6845                "External command to RECEIVE in BINARY mode with this protocol",
6846                             p6)) < 0) {
6847             if (x == -3)
6848               goto protoexit;
6849             else
6850               return(x);
6851         }
6852         if ((x = protofield(ptab[y].p_t_rcmd,
6853                  "External command to RECEIVE in TEXT mode with this protocol",
6854                             p7)) < 0) {
6855             if (x == -3)
6856               goto protoexit;
6857             else
6858               return(x);
6859         }
6860     }
6861 #endif /* XYZ_INTERNAL */
6862
6863     if ((x = cmcfm()) < 0)              /* Confirm the command */
6864       return(x);
6865
6866 protoexit:                              /* Common exit from this routine */
6867
6868 #ifdef XYZ_INTERNAL
6869     if (!p_avail) {
6870         bleep(BP_WARN);
6871         printf("\n?X,Y, and Zmodem are unavailable\n");
6872         return(success = 0);
6873     }
6874 #endif /* XYZ_INTERNAL */
6875
6876     p1 = brstrip(p1);
6877     p2 = brstrip(p2);
6878     p3 = brstrip(p3);
6879     p4 = brstrip(p4);
6880     p5 = brstrip(p5);
6881     p6 = brstrip(p6);
6882     p7 = brstrip(p7);
6883     initproto(y,p1,p2,p3,p4,p5,p6,p7);
6884     return(success = 1);
6885 }
6886
6887 #ifndef NOPUSH
6888 #ifndef XYZ_INTERNAL
6889
6890 #define DEF_EXP_TIMO 12  /* Default timeout for external protocol (seconds) */
6891
6892 int exp_handler = 0;                    /* These are exported */
6893 int exp_timo = DEF_EXP_TIMO;
6894 int exp_stderr = SET_AUTO;
6895
6896 VOID
6897 shoextern() {                           /* Invoked by SHOW PROTOCOL */
6898     printf("\n External-protocol handler:         %s\n",
6899            exp_handler ? (exp_handler == 1 ? "pty" : "system") : "automatic");
6900 #ifdef COMMENT
6901     printf(" External-protocol redirect-stderr: %s\n", showooa(exp_stderr));
6902 #endif  /* COMMENT */
6903     printf(" External-protocol timeout:         %d (sec)\n", exp_timo);
6904 }
6905
6906 static struct keytab setexternhandler[] = {
6907     { "automatic", 0, 0 },
6908     { "pty",       1, 0 },
6909     { "system",    2, 0 }
6910 };
6911
6912 int
6913 setextern() {                           /* SET EXTERNAL-PROTOCOL */
6914     int x, y;
6915     if ((x = cmkey(extprotab,nxtprotab,"","",xxstring)) < 0)
6916       return(x);
6917     switch (x) {
6918       case EXP_HANDLER:
6919         if ((x = cmkey(setexternhandler,3,"","automatic",xxstring)) < 0)
6920           return(x);
6921         if ((y = cmcfm()) < 0)
6922           return(y);
6923         exp_handler = x;
6924         break;
6925         
6926 #ifdef COMMENT
6927       case EXP_STDERR:
6928         if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
6929           return(x);
6930         if ((y = cmcfm()) < 0)
6931           return(y);
6932         exp_stderr = x;
6933         break;
6934 #endif  /* COMMENT */
6935
6936       case EXP_TIMO:
6937         y = cmnum("Inactivity timeout, seconds,",ckitoa(DEF_EXP_TIMO),
6938                   10,&x,xxstring);
6939         return(setnum(&exp_timo,x,y,-1));
6940     }
6941     return(success = 1);
6942 }
6943 #endif  /* XYZ_INTERNAL */
6944 #endif  /* NOPUSH */
6945
6946 int
6947 setdest() {
6948     int x, y;
6949     if ((y = cmkey(desttab,ndests,"","disk",xxstring)) < 0) return(y);
6950     if ((x = cmcfm()) < 0) return(x);
6951     dest = y;
6952     return(1);
6953 }
6954 #endif /* NOXFER */
6955
6956 #ifdef DECNET
6957 struct keytab dnettab[] = {
6958 #ifndef OS2ONLY
6959     "cterm", NP_CTERM, 0,
6960 #endif /* OS2ONLY */
6961     "lat",   NP_LAT,   0
6962 };
6963 int ndnet =  (sizeof(dnettab) / sizeof(struct keytab));
6964 #endif /* DECNET */
6965
6966 /*  S E T P R I N T E R  --  SET PRINTER command  */
6967
6968 #ifdef PRINTSWI
6969 static struct keytab prntab[] = {       /* SET PRINTER switches */
6970     "/bidirectional",    PRN_BID, 0,
6971 #ifdef OS2
6972     "/character-set",    PRN_CS,  CM_ARG,
6973 #endif /* OS2 */
6974     "/command",          PRN_PIP, CM_ARG,
6975     "/dos-device",       PRN_DOS, CM_ARG,
6976     "/end-of-job-string",PRN_TRM, CM_ARG,
6977     "/file",             PRN_FIL, CM_ARG,
6978 #ifdef BPRINT
6979     "/flow-control",     PRN_FLO, CM_ARG,
6980 #endif /* BPRINT */
6981     "/job-header-file",  PRN_SEP, CM_ARG,
6982 #ifdef OS2
6983     "/length",           PRN_LEN, CM_ARG,
6984 #endif /* OS2 */
6985     "/none",             PRN_NON, 0,
6986 #ifdef OS2
6987     "/nopostscript",     PRN_RAW, 0,
6988     "/nops",             PRN_RAW, CM_INV,
6989 #endif /* OS2 */
6990     "/output-only",      PRN_OUT, 0,
6991 #ifdef BPRINT
6992     "/parity",           PRN_PAR, CM_ARG,
6993 #endif /* BPRINT */
6994     "/pipe",             PRN_PIP, CM_ARG|CM_INV,
6995 #ifdef OS2
6996     "/postscript",       PRN_PS,  0,
6997     "/ps",               PRN_PS,  CM_INV,
6998 #endif /* OS2 */
6999     "/separator",        PRN_SEP, CM_ARG|CM_INV,
7000 #ifdef BPRINT
7001     "/speed",            PRN_SPD, CM_ARG,
7002 #endif /* BPRINT */
7003     "/timeout",          PRN_TMO, CM_ARG,
7004     "/terminator",       PRN_TRM, CM_ARG|CM_INV,
7005 #ifdef OS2
7006 #ifdef NT
7007     "/w",                PRN_WIN, CM_ARG|CM_ABR|CM_INV,
7008     "/wi",               PRN_WIN, CM_ARG|CM_ABR|CM_INV,
7009 #endif /* NT */
7010     "/width",            PRN_WID, CM_ARG,
7011 #endif /* OS2 */
7012 #ifdef NT
7013     "/windows-queue",    PRN_WIN, CM_ARG,
7014 #endif /* NT */
7015     "",                 0,      0
7016 };
7017 int nprnswi =  (sizeof(prntab) / sizeof(struct keytab)) - 1;
7018 #endif /* PRINTSWI */
7019
7020 static int
7021 setprinter(xx) int xx; {
7022     int x, y;
7023     char * s;
7024     char * defname = NULL;
7025 #ifdef OS2
7026     extern int prncs;
7027 #endif /* OS2 */
7028
7029 #ifdef BPRINT
7030     char portbuf[64];
7031     long portspeed = 0L;
7032     int portparity = 0;
7033     int portflow = 0;
7034 #endif /* BPRINT */
7035
7036 #ifdef PRINTSWI
7037     int c, i, n, wild, confirmed = 0;   /* Workers */
7038     int getval = 0;                     /* Whether to get switch value */
7039     struct stringint pv[PRN_MAX+1];    /* Temporary array for switch values */
7040     struct FDB sw, of, cm;              /* FDBs for each parse function */
7041     int haveque = 0;
7042     int typeset = 0;
7043 #endif /* PRINTSWI */
7044
7045 #ifdef NT
7046     struct keytab * printtab = NULL, * _printtab = NULL;
7047     int nprint = 0, printdef=0;
7048 #endif /* NT */
7049
7050 #ifdef OS2
7051     defname = "PRN";                    /* default */
7052 #else
7053 #ifdef VMS
7054     defname = "LPT:";
7055 #else
7056 #ifdef UNIX
7057     defname = "|lpr";
7058 #endif /* UNIX */
7059 #endif /* VMS */
7060 #endif /* OS2 */
7061
7062 #ifdef PRINTSWI
7063 #ifdef NT
7064     haveque = Win32EnumPrt(&printtab,&_printtab,&nprint,&printdef);
7065     haveque = haveque && nprint;
7066 #endif /* NT */
7067
7068     for (i = 0; i <= PRN_MAX; i++) {    /* Initialize switch values */
7069         pv[i].sval = NULL;              /* to null pointers */
7070         pv[i].ival = -1;                /* and -1 int values */
7071         pv[i].wval = (CK_OFF_T)-1;      /* and -1 wide values */
7072     }
7073     if (xx == XYBDCP) {                 /* SET BPRINTER == /BIDIRECTIONAL */
7074         pv[PRN_BID].ival = 1;
7075         pv[PRN_OUT].ival = 0;
7076     }
7077
7078     /* Initialize defaults based upon current printer settings */
7079     if (printername) {
7080         defname = printername;
7081         switch (printertype) {
7082           case PRT_WIN: pv[PRN_WIN].ival = 1; break;
7083           case PRT_DOS: pv[PRN_DOS].ival = 1; break;
7084           case PRT_PIP: pv[PRN_PIP].ival = 1; break;
7085           case PRT_FIL: pv[PRN_FIL].ival = 1; break;
7086           case PRT_NON: pv[PRN_NON].ival = 1; break;
7087         }
7088     }
7089 #ifdef BPRINT
7090     /* only set the BIDI flag if we are bidi */
7091     if (printbidi)
7092         pv[PRN_BID].ival = 1;
7093
7094     /* serial port parameters may be set for non-bidi devices */
7095     pv[PRN_SPD].ival = pportspeed / 10L;
7096     pv[PRN_PAR].ival = pportparity;
7097     pv[PRN_FLO].ival = pportflow;
7098 #endif /* BPRINT */
7099     if (printtimo)
7100         pv[PRN_TMO].ival = printtimo;
7101     if (printterm) {
7102         pv[PRN_TRM].ival = 1;
7103         makestr(&pv[PRN_TRM].sval,printterm);
7104     }
7105     if (printsep) {
7106         pv[PRN_SEP].ival = 1;
7107         makestr(&pv[PRN_SEP].sval,printsep);
7108     }
7109     if (txt2ps) {
7110         pv[PRN_PS].ival = 1;
7111         pv[PRN_WID].ival = ps_width;
7112         pv[PRN_LEN].ival = ps_length;
7113     } else {
7114         pv[PRN_RAW].ival = 1;
7115     }
7116
7117     /* Set up chained parse functions... */
7118
7119     cmfdbi(&sw,                         /* First FDB - command switches */
7120            _CMKEY,                      /* fcode */
7121            "Switch",                    /* hlpmsg */
7122            "",                          /* default */
7123            "",                          /* addtl string data */
7124            nprnswi,                     /* addtl numeric data 1: tbl size */
7125            4,                           /* addtl numeric data 2: 4 = cmswi */
7126            xxstring,                    /* Processing function */
7127            prntab,                      /* Keyword table */
7128            &cm                          /* Pointer to next FDB */
7129            );
7130     cmfdbi(&cm,                         /* Second fdb for confirmation */
7131            _CMCFM,                      /* fcode */
7132            "",                          /* hlpmsg */
7133            "",                          /* default */
7134            "",                          /* addtl string data */
7135            0,                           /* addtl numeric data 1 */
7136            0,                           /* addtl numeric data 2 */
7137            NULL,
7138            NULL,
7139            &of
7140            );
7141     cmfdbi(&of,                         /* Third FDB for printer name */
7142            _CMOFI,                      /* fcode */
7143            "Printer or file name",      /* hlpmsg */
7144            defname,                     /* default */
7145            "",                          /* addtl string data */
7146            0,                           /* addtl numeric data 1: tbl size */
7147            0,                           /* addtl numeric data 2: 4 = cmswi */
7148            xxstring,                    /* Processing function */
7149            NULL,                        /* Nothing */
7150            NULL
7151            );
7152
7153     while (1) {                         /* Parse 0 or more switches */
7154         x = cmfdb(&sw);                 /* Parse switch or other thing */
7155         debug(F101,"setprinter cmfdb","",x);
7156         if (x < 0)                      /* Error */
7157           goto xsetprn;                 /* or reparse needed */
7158         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
7159           break;
7160         if (cmresult.fdbaddr != &sw)    /* Advanced usage :-) */
7161           break;
7162         c = cmgbrk();                   /* Get break character */
7163         getval = (c == ':' || c == '='); /* to see how they ended the switch */
7164         n = cmresult.nresult;           /* Numeric result = switch value */
7165         debug(F101,"setprinter switch","",n);
7166
7167         switch (n) {                    /* Process the switch */
7168           case PRN_PS:                  /* Text to Postscript */
7169             pv[PRN_PS].ival = 1;
7170             pv[PRN_BID].ival = 0;
7171             pv[PRN_OUT].ival = 1;
7172             pv[PRN_RAW].ival = 0;
7173             break;
7174
7175           case PRN_RAW:                 /* Non-Postscript */
7176             pv[PRN_PS].ival = 0;
7177             pv[PRN_RAW].ival = 1;
7178             break;
7179
7180           case PRN_BID:                 /* Bidirectional */
7181             pv[PRN_BID].ival = 1;
7182             pv[PRN_OUT].ival = 0;
7183             pv[PRN_PS].ival = 0;
7184             pv[PRN_RAW].ival = 1;
7185             break;
7186
7187           case PRN_OUT:                 /* Output-only */
7188             pv[PRN_OUT].ival = 1;
7189             pv[PRN_BID].ival = 0;
7190             pv[PRN_PS].ival = 0;
7191             pv[PRN_RAW].ival = 1;
7192             break;
7193
7194           case PRN_NON:                 /* NONE */
7195             typeset++;
7196             pv[n].ival = 1;
7197             pv[PRN_SPD].ival = 0;
7198             pv[PRN_PAR].ival = 0;
7199             pv[PRN_FLO].ival = FLO_KEEP;
7200             break;
7201
7202 #ifdef UNIX
7203           case PRN_WIN:
7204 #endif /* UNIX */
7205           case PRN_DOS:                 /* DOS printer name */
7206           case PRN_FIL:                 /* Or filename */
7207           case PRN_PIP:
7208             typeset++;
7209             if (pv[n].sval) free(pv[n].sval);
7210             pv[n].sval = NULL;
7211             pv[PRN_NON].ival = 0;       /* Zero any previous selections */
7212             pv[PRN_WIN].ival = 0;
7213             pv[PRN_DOS].ival = 0;
7214             pv[PRN_FIL].ival = 0;
7215             pv[PRN_PIP].ival = 0;
7216             pv[n].ival = 1;             /* Flag this one */
7217             if (!getval) break;         /* No value wanted */
7218
7219             if (n == PRN_FIL) {         /* File, check accessibility */
7220                 int wild = 0;
7221                 if ((x = cmiofi("Filename","kermit.prn",&s,&wild,xxstring))< 0)
7222                   if (x == -9) {
7223                       if (zchko(s) < 0) {
7224                           printf("Can't create \"%s\"\n",s);
7225                           return(x);
7226                       }
7227                   } else goto xsetprn;
7228                 if (iswild(s)) {
7229                     printf("?A single file please\n");
7230                     return(-9);
7231                 }
7232                 pv[PRN_SPD].ival = 0;
7233                 pv[PRN_PAR].ival = 0;
7234                 pv[PRN_FLO].ival = FLO_KEEP;
7235             } else if ((x = cmfld(n == PRN_DOS ? /* Value wanted - parse it */
7236                            "DOS printer device name" : /* Help message */
7237                            (n == PRN_PIP ?
7238                            "Program name" :
7239                            "Filename"),
7240                            n == PRN_DOS ?
7241                            "PRN" :      /* Default */
7242                            "",
7243                            &s,
7244                            xxstring
7245                            )) < 0)
7246               goto xsetprn;
7247             s = brstrip(s);             /* Strip enclosing braces */
7248             while (*s == SP)            /* Strip leading blanks */
7249               s++;
7250             if (n == PRN_PIP) {         /* If /PIPE: */
7251                 if (*s == '|') {        /* strip any extraneous pipe sign */
7252                     s++;
7253                     while (*s == SP)
7254                       s++;
7255                 }
7256                 pv[PRN_SPD].ival = 0;
7257                 pv[PRN_PAR].ival = 0;
7258                 pv[PRN_FLO].ival = FLO_KEEP;
7259             }
7260             if ((y = strlen(s)) > 0)    /* Anything left? */
7261               if (pv[n].sval = (char *) malloc(y+1)) /* Yes, keep it */
7262                 strcpy(pv[n].sval,s);   /* safe */
7263             break;
7264 #ifdef NT
7265           case PRN_WIN:                 /* Windows queue name */
7266             typeset++;
7267             if (pv[n].sval) free(pv[n].sval);
7268             pv[n].sval = NULL;
7269             pv[PRN_NON].ival = 0;
7270             pv[PRN_DOS].ival = 0;
7271             pv[PRN_FIL].ival = 0;
7272             pv[n].ival = 1;
7273             pv[PRN_SPD].ival = 0;
7274             pv[PRN_PAR].ival = 0;
7275             pv[PRN_FLO].ival = FLO_KEEP;
7276
7277             if (!getval || !haveque)
7278               break;
7279             if ((x = cmkey(_printtab,nprint,"Print queue name",
7280                            _printtab[printdef].kwd,xxstring)) < 0) {
7281                 if (x != -2)
7282                   goto xsetprn;
7283
7284                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7285                 s = atmbuf;
7286                 if ((y = strlen(s)) > 0)
7287                   if (pv[n].sval = (char *)malloc(y+1))
7288                     strcpy(pv[n].sval,s); /* safe */
7289             } else {
7290                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7291                 for (i = 0; i < nprint; i++) {
7292                     if (x == printtab[i].kwval) {
7293                         s = printtab[i].kwd;
7294                         break;
7295                     }
7296                 }
7297                 if ((y = strlen(s)) > 0)
7298                   if (pv[n].sval = (char *)malloc(y+1))
7299                     strcpy(pv[n].sval,s); /* safe */
7300             }
7301             break;
7302 #endif /* NT */
7303
7304           case PRN_SEP:                 /* /JOB-HEADER (separator) */
7305             if (pv[n].sval) free(pv[n].sval);
7306             pv[n].sval = NULL;
7307             pv[n].ival = 1;
7308             if (!getval) break;
7309             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0)
7310               goto xsetprn;
7311             if (y) {
7312                 printf("?Wildcards not allowed\n");
7313                 x = -9;
7314                 goto xsetprn;
7315             }
7316             if ((y = strlen(s)) > 0)
7317               if (pv[n].sval = (char *) malloc(y+1))
7318                 strcpy(pv[n].sval,s);   /* safe */
7319             break;
7320
7321           case PRN_TMO:                 /* /TIMEOUT:number */
7322             pv[n].ival = 0;
7323             if (!getval) break;
7324             if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
7325               goto xsetprn;
7326             if (y > 999) {
7327                 printf("?Sorry - 999 is the maximum\n");
7328                 x = -9;
7329                 goto xsetprn;
7330             } else
7331               pv[n].ival = y;
7332             break;
7333
7334           case PRN_TRM:                 /* /END-OF-JOB:string */
7335             if (pv[n].sval) free(pv[n].sval);
7336             pv[n].sval = NULL;
7337             pv[n].ival = 1;
7338             if (!getval) break;
7339             if ((x = cmfld("String (enclose in braces if it contains spaces)",
7340                            "",&s,xxstring)) < 0)
7341               goto xsetprn;
7342             s = brstrip(s);
7343             if ((y = strlen(s)) > 0)
7344               if (pv[n].sval = (char *) malloc(y+1))
7345                 strcpy(pv[n].sval,s);   /* safe */
7346             break;
7347
7348 #ifdef BPRINT
7349           case PRN_FLO:
7350             if (!getval) break;
7351             if ((x = cmkey(flotab,nflo,
7352                               "Serial printer-port flow control",
7353                               "rts/cts",xxstring)) < 0)
7354               goto xsetprn;
7355             pv[n].ival = x;
7356             break;
7357
7358 #ifndef NOLOCAL
7359           case PRN_SPD:
7360             if (!getval) break;
7361
7362             /* TN_COMPORT here too? */
7363
7364             if ((x = cmkey(spdtab,      /* Speed (no default) */
7365                            nspd,
7366                            "Serial printer-port interface speed",
7367                            "9600",
7368                            xxstring)
7369                  ) < 0)
7370               goto xsetprn;
7371             pv[n].ival = x;
7372             break;
7373 #endif /* NOLOCAL */
7374
7375           case PRN_PAR:
7376             pv[n].ival = 0;
7377             if (!getval) break;
7378             if ((x = cmkey(partbl,npar,"Serial printer-port parity",
7379                            "none",xxstring)) < 0)
7380               goto xsetprn;
7381             pv[n].ival = x;
7382             break;
7383 #endif /* BPRINT */
7384
7385 #ifdef OS2
7386           case PRN_LEN:
7387             if (!getval) break;
7388             if ((x = cmnum("PS page length", "66",10,&y,xxstring)) < 0)
7389               goto xsetprn;
7390             pv[n].ival = y;
7391             break;
7392
7393           case PRN_WID:
7394             if (!getval) break;
7395             if ((x = cmnum("PS page width", "80",10,&y,xxstring)) < 0)
7396               goto xsetprn;
7397             pv[n].ival = y;
7398             break;
7399
7400           case PRN_CS:
7401               pv[n].ival = 0;
7402               if (!getval) break;
7403               if ((y = cmkey(
7404 #ifdef CKOUNI
7405                        txrtab,ntxrtab,
7406 #else /* CKOUNI */
7407                        ttcstab,ntermc,
7408 #endif /* CKOUNI */
7409                        "auto-print/printscreen character-set",
7410                        "cp437",xxstring)) < 0)
7411                   goto xsetprn;
7412               pv[n].ival = y;
7413               break;
7414 #endif /* OS2 */
7415
7416           default:
7417             printf("?Unexpected switch value - %d\n",cmresult.nresult);
7418             x = -9;
7419             goto xsetprn;
7420         }
7421     }
7422     line[0] = NUL;                      /* Initialize printer name value */
7423     switch (cmresult.fcode) {           /* How did we get here? */
7424       case _CMOFI:                      /* They typed a filename */
7425         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
7426         wild = cmresult.nresult;        /* Wild flag */
7427         if (!typeset) {                 /* A printer name without a type */
7428             pv[PRN_NON].ival = 0;       /* is supposed to be treated as  */
7429             pv[PRN_WIN].ival = 0;       /* a DOS or Pipe printer.  We    */
7430             pv[PRN_FIL].ival = 0;       /* clear all the flags and let   */
7431             pv[PRN_PIP].ival = 0;       /* the code below dope out the   */
7432             pv[PRN_DOS].ival = 0;       /* type.                         */
7433         }
7434 #ifdef NT
7435         else if (pv[PRN_WIN].ival && lookup(_printtab,line,nprint,&y)) {
7436             /* invalid Window Queue name */
7437             printf("?invalid Windows Printer Queue name: \"%s\"\r\n",line);
7438             x = -9;
7439             goto xsetprn;
7440         }
7441 #endif /* NT */
7442         if ((x = cmcfm()) < 0)          /* Confirm the command */
7443           goto xsetprn;
7444         break;
7445       case _CMCFM:                      /* They entered the command */
7446         if (pv[PRN_DOS].ival > 0)
7447           ckstrncpy(line,pv[PRN_DOS].sval ? pv[PRN_DOS].sval : "",LINBUFSIZ);
7448         else if (pv[PRN_WIN].ival > 0)
7449           ckstrncpy(line,pv[PRN_WIN].sval ? pv[PRN_WIN].sval : "",LINBUFSIZ);
7450         else if (pv[PRN_FIL].ival > 0)
7451           ckstrncpy(line,pv[PRN_FIL].sval ? pv[PRN_FIL].sval : "",LINBUFSIZ);
7452         else if (pv[PRN_PIP].ival > 0)
7453           ckstrncpy(line,pv[PRN_PIP].sval ? pv[PRN_PIP].sval : "",LINBUFSIZ);
7454         break;
7455       default:                          /* By mistake */
7456         printf("?Unexpected function code: %d\n",cmresult.fcode);
7457         x = -9;
7458         goto xsetprn;
7459     }
7460
7461 #else  /* No PRINTSWI */
7462
7463     if ((x = cmofi("Printer or file name",defname,&s,xxstring)) < 0)
7464       return(x);
7465     if (x > 1) {
7466         printf("?Directory names not allowed\n");
7467         return(-9);
7468     }
7469     while (*s == SP || *s == HT) s++;   /* Trim leading whitespace */
7470     ckstrncpy(line,s,LINBUFSIZ);        /* Make a temporary safe copy */
7471     if ((x = cmcfm()) < 0) return(x);   /* Confirm the command */
7472 #endif /* PRINTSWI */
7473
7474 #ifdef IKSD
7475     if (inserver && (isguest
7476 #ifndef NOSERVER
7477                      || !ENABLED(en_pri)
7478 #endif /* NOSERVER */
7479                      )) {
7480         printf("Sorry, printing disabled\r\n");
7481         return(success = 0);
7482     }
7483 #endif /* ISKD */
7484
7485 #ifdef PRINTSWI
7486 #ifdef BPRINT
7487     if (printbidi) {                    /* If bidi printing active */
7488 #ifndef UNIX
7489         bprtstop();                     /* Stop it before proceeding */
7490 #endif /* UNIX */
7491         printbidi = 0;
7492     }
7493     if (pv[PRN_SPD].ival > 0) {
7494         portspeed = (long) pv[PRN_SPD].ival * 10L;
7495         if (portspeed == 70L) portspeed = 75L;
7496     }
7497     if (pv[PRN_PAR].ival > 0)
7498         portparity = pv[PRN_PAR].ival;
7499     if (pv[PRN_FLO].ival > 0)
7500         portflow = pv[PRN_FLO].ival;
7501 #endif /* BPRINT */
7502 #endif /* PRINTSWI */
7503
7504     s = line;                           /* Printer name, if given */
7505
7506 #ifdef OS2ORUNIX
7507 #ifdef PRINTSWI
7508     if (pv[PRN_PIP].ival > 0) {         /* /PIPE was given? */
7509         printpipe = 1;
7510         noprinter = 0;
7511         if (*s ==  '|') {               /* It might still have a pipe sign */
7512             s++;                        /* if name give later */
7513             while (*s == SP)            /* so remove it and spaces */
7514               s++;
7515         }
7516     } else
7517 #endif /* PRINTSWI */
7518       if (*s == '|') {                  /* Or pipe implied by name? */
7519           s++;                          /* Point past pipe sign */
7520           while (*s == SP)              /* Gobble whitespace */
7521             s++;
7522           if (*s) {
7523               printpipe = 1;
7524               noprinter = 0;
7525           }
7526       } else {
7527           printpipe = 0;
7528       }
7529
7530 #ifdef PRINTSWI
7531 #ifdef BPRINT
7532     if (printpipe && pv[PRN_BID].ival > 0) {
7533         printf("?Sorry, pipes not allowed for bidirectional printer\n");
7534         return(-9);
7535     }
7536 #endif /* BPRINT */
7537 #endif /* PRINTSWI */
7538 #endif /* OS2ORUNIX */
7539
7540 #ifdef OS2
7541     if ( pv[PRN_CS].ival > 0 ) 
7542         prncs = pv[PRN_CS].ival;
7543
7544     if ( pv[PRN_PS].ival > 0 ) {
7545         txt2ps = 1;
7546         ps_width = pv[PRN_WID].ival <= 0 ? 80 : pv[PRN_WID].ival;
7547         ps_length = pv[PRN_LEN].ival <= 0 ? 66 : pv[PRN_LEN].ival;
7548     }
7549 #endif /* OS2 */
7550
7551     y = strlen(s);                      /* Length of name of new print file */
7552     if (y > 0
7553 #ifdef OS2
7554         && ((y != 3) || (ckstrcmp(s,"PRN",3,0) != 0))
7555 #endif /* OS2 */
7556         ) {
7557         if (printername) {              /* Had a print file before? */
7558             free(printername);          /* Remove its name */
7559             printername = NULL;
7560         }
7561         printername = (char *) malloc(y + 1); /* Allocate space for it */
7562         if (!printername) {
7563             printf("?Memory allocation failure\n");
7564             return(-9);
7565         }
7566         strcpy(printername,s);          /* (safe) Copy new name to new space */
7567         debug(F110,"printername",printername,0);
7568     }
7569
7570 #ifdef PRINTSWI
7571     /* Set printer type from switches that were given explicitly */
7572
7573     if (pv[PRN_NON].ival > 0) {         /* No printer */
7574         printertype = PRT_NON;
7575         noprinter = 1;
7576         printpipe = 0;
7577     } else if (pv[PRN_FIL].ival > 0) {  /* File */
7578         printertype = PRT_FIL;
7579         noprinter = 0;
7580         printpipe = 0;
7581     } else if (pv[PRN_PIP].ival > 0) {  /* Pipe */
7582         printertype = PRT_PIP;
7583         noprinter = 0;
7584         printpipe = 1;
7585     } else if (pv[PRN_WIN].ival > 0) {  /* Windows print queue */
7586         printertype = PRT_WIN;
7587         noprinter = 0;
7588         printpipe = 0;
7589     } else if (pv[PRN_DOS].ival > 0) {  /* DOS device */
7590         printertype = PRT_DOS;
7591         noprinter = 0;
7592         printpipe = 0;
7593     } else if (line[0]) {               /* Name given without switches */
7594         noprinter = 0;
7595         printertype = printpipe ? PRT_PIP : PRT_DOS;
7596 #ifdef NT
7597         /* was the command SET PRINTER windows-queue ? */
7598         y = lookup(_printtab,line,nprint,&x);
7599         if (y >= 0) {
7600             printertype = PRT_WIN;
7601             if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
7602             if (printername) {          /* Had a print file before? */
7603                 free(printername);      /* Remove its name */
7604                 printername = NULL;
7605             }
7606             pv[PRN_WIN].sval = NULL;
7607             pv[PRN_WIN].ival = 1;
7608             s = printtab[x].kwd;        /* Get full new name */
7609             if ((y = strlen(s)) > 0) {
7610                 makestr(&pv[PRN_WIN].sval,s);
7611                 makestr(&printername,s);
7612                 if (!printername) {
7613                     printf("?Memory allocation failure\n");
7614                     return(-9);
7615                 }
7616                 debug(F110,"printername",printername,0);
7617             }
7618         } else if ( y == -2 ) {
7619             /* Ambiguous Print Queue Name */
7620             printf("?Ambiguous printer name provided.\n");
7621             return(-9);
7622         }
7623 #endif /* NT */
7624     }
7625
7626 #ifdef BPRINT
7627     /* Port parameters may be set for non-bidi mode */
7628
7629     pportspeed = portspeed;             /* Set parameters */
7630     pportparity = portparity;
7631     pportflow = portflow;
7632
7633     if (pv[PRN_BID].ival > 0) {         /* Bidirectional */
7634 #ifdef UNIX
7635         printbidi = 1;                  /* (just to test parsing...) */
7636 #else
7637         printbidi = bprtstart();        /* Start bidirectional printer */
7638 #endif /* UNIX */
7639         return(success = printbidi);
7640     } else
7641       printbidi = 0;                    /* Not BPRINTER, unset flag */
7642 #endif /* BPRINT */
7643
7644     if (pv[PRN_TMO].ival > -1) {        /* Take care of timeout */
7645         printtimo = pv[PRN_TMO].ival;
7646     }
7647     if (pv[PRN_TRM].ival > 0) {         /* Termination string */
7648         if (printterm) {
7649             free(printterm);
7650             printterm = NULL;
7651         }
7652         if (pv[PRN_TRM].sval)
7653           makestr(&printterm,pv[PRN_TRM].sval);
7654     }
7655     if (pv[PRN_SEP].ival > 0) {         /* and separator file */
7656         if (printsep) {
7657             free(printsep);
7658             printsep = NULL;
7659         }
7660         if (pv[PRN_SEP].sval)
7661           makestr(&printsep,pv[PRN_SEP].sval);
7662     }
7663 #endif /* PRINTSWI */
7664
7665 #ifdef UNIXOROSK
7666     if (!printpipe
7667 #ifdef PRINTSWI
7668         && !noprinter
7669 #endif /* PRINTSWI */
7670         ) {                             /* File - check access */
7671         if (zchko(s) < 0) {
7672             printf("?Access denied - %s\n",s);
7673             x = -9;
7674             goto xsetprn;
7675         }
7676     }
7677 #endif /* UNIXOROSK */
7678
7679     x = 1;                              /* Return code */
7680
7681   xsetprn:                              /* Common exit */
7682 #ifdef PRINTSWI
7683     for (i = 0; i <= PRN_MAX; i++) {    /* Free malloc'd memory */
7684         if (pv[i].sval)
7685           free(pv[i].sval);
7686     }
7687 #endif /* PRINTSWI */
7688     success = (x > 0) ? 1 : 0;
7689     return(x);
7690 }
7691
7692 #ifdef ANYSSH
7693 /* The SET SSH command */
7694
7695 #define SSH_CMD  1                      /* SET SSH COMMAND */
7696
7697 #ifdef SSHBUILTIN                       /* Built-in SET SSH options */
7698 #define SSH_ADD  2                      /* Add */
7699 #define SSH_AFW  3                      /* Agent-forwarding */
7700 #define SSH_CHI  4                      /* Check Host IP */
7701 #define SSH_XFW  5                      /* X11-forwarding */
7702 #define SSH_DYF  6                      /* Dynamic forwarding */
7703 #define SSH_GWP  7                      /* Gatewa portgs */
7704 #define SSH_GSS  8                      /* GSSAPI */
7705 #define SSH_KBD  9                      /* KBD Interactive Devices */
7706 #define SSH_K4  10                      /* Kerberos 4 */
7707 #define SSH_K5  11                      /* Kerberos 5 */
7708 #define SSH_SHK 12                      /* Strict Host Key Check */
7709 #define SSH_V1  13                      /* SSH V1 */
7710 #define SSH_V2  14                      /* SSH V2 */
7711 #define SSH_PRP 15                      /* Privd port */
7712 #define SSH_CMP 16                      /* Compression */
7713 #define SSH_XAL 17                      /* X Auth Location */
7714 #define SSH_SHH 18                      /* Quiet */
7715 #define SSH_VER 19                      /* Version */
7716 #define SSH_VRB 20                      /* Verbosity level */
7717 #define SSH_IDF 21                      /* Identity File */
7718 #define SSH_CFG 22                      /* Use OpenSSH Config */
7719 #define SSH_HBT 23                      /* Heartbeat Interval */
7720 #endif /* SSHBUILTIN */
7721
7722 static struct keytab sshtab[] = {       /* SET SSH command table */
7723 #ifdef SSHBUILTIN
7724     { "agent-forwarding",        SSH_AFW,  0 },
7725     { "check-host-ip",           SSH_CHI,  0 },
7726     { "compression",             SSH_CMP,  0 },
7727     { "dynamic-forwarding",      SSH_DYF,  0 },
7728     { "gateway-ports",           SSH_GWP,  0 },
7729     { "gssapi",                  SSH_GSS,  0 },
7730     { "heartbeat-interval",      SSH_HBT,  0 },
7731     { "identity-file",           SSH_IDF,  0 },
7732 #ifdef COMMENT
7733     { "kbd-interactive-devices", SSH_KBD,  0 },
7734 #endif /* COMMENT */
7735     { "k4",                      SSH_K4, CM_INV },
7736     { "k5",                      SSH_K5, CM_INV },
7737     { "kerberos4",               SSH_K4,   0 },
7738     { "kerberos5",               SSH_K5,   0 },
7739     { "krb4",                    SSH_K4, CM_INV },
7740     { "krb5",                    SSH_K5, CM_INV },
7741     { "privileged-port",         SSH_PRP,  0 },
7742     { "quiet",                   SSH_SHH,  0 },
7743     { "strict-host-key-check",   SSH_SHK,  0 },
7744     { "use-openssh-config",      SSH_CFG,  0 },
7745     { "v1",                      SSH_V1,   0 },
7746     { "v2",                      SSH_V2,   0 },
7747     { "verbose",                 SSH_VRB,  0 },
7748     { "version",                 SSH_VER,  0 },
7749     { "x11-forwarding",          SSH_XFW,  0 },
7750     { "xauth-location",          SSH_XAL,  0 },
7751 #else
7752 #ifdef SSHCMD
7753     { "command",                 SSH_CMD,  0 },
7754 #endif /* SSHCMD */
7755 #endif /* SSHBUILTIN */
7756     { "", 0, 0 }
7757 };
7758 static int nsshtab = (sizeof(sshtab) / sizeof(struct keytab)) - 1;
7759
7760 #ifdef SSHBUILTIN
7761 static struct keytab sshver[] = {       /* SET SSH VERSION command table */
7762     { "1",          1,  0 },
7763     { "2",          2,  0 },
7764     { "automatic",  0,  0 }
7765 };
7766
7767 #define SSHA_CRS   1
7768 #define SSHA_DSA   2
7769 #define SSHA_GSS   3
7770 #define SSHA_HOS   4
7771 #define SSHA_KBD   5
7772 #define SSHA_K4    6
7773 #define SSHA_K5    7
7774 #define SSHA_PSW   8
7775 #define SSHA_PK    9
7776 #define SSHA_SKE  10
7777 #define SSHA_TIS  11
7778 #define SSHA_EXT  12
7779 #define SSHA_SRP  13
7780
7781 static struct keytab ssh2aut[] = {      /* SET SSH V2 AUTH command table */
7782     { "external-keyx",      SSHA_EXT, 0 },
7783     { "gssapi",             SSHA_GSS, 0 },
7784     { "hostbased",          SSHA_HOS, 0 },
7785     { "keyboard-interactive",  SSHA_KBD, 0 },
7786     { "password",           SSHA_PSW, 0 },
7787     { "publickey",          SSHA_PK,  0 },
7788     { "srp-gex-sha1",       SSHA_SRP, 0 },
7789     { "", 0, 0 }
7790 };
7791 static int nssh2aut = (sizeof(ssh2aut) / sizeof(struct keytab)) - 1;
7792
7793 #define SSHF_LCL   1
7794 #define SSHF_RMT   2
7795
7796 static struct keytab addfwd[] = {       /* SET SSH ADD command table */
7797     { "local-port-forward",  SSHF_LCL, 0 },
7798     { "remote-port-forward", SSHF_RMT, 0 },
7799     { "", 0, 0 }
7800 };
7801 static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
7802
7803 #define SSH1_CIF   1
7804 #define SSH1_GNH   2
7805 #define SSH1_UNH   3
7806 #define SSH1_K54   4
7807
7808 #define SSH2_CIF   1
7809 #define SSH2_GNH   2
7810 #define SSH2_UNH   3
7811 #define SSH2_ARK   4
7812 #define SSH2_HKA   5
7813 #define SSH2_MAC   6
7814 #define SSH2_AUT   7
7815
7816 static struct keytab sshv1tab[] = {     /* SET SSH V1 command table */
7817     { "cipher",                  SSH1_CIF, 0 },
7818     { "global-known-hosts-file", SSH1_GNH, 0 },
7819     { "k5-reuse-k4-messages",    SSH1_K54, CM_INV },
7820     { "user-known-hosts-file",   SSH1_UNH, 0 },
7821     { "", 0, 0 }
7822 };
7823 static int nsshv1tab = (sizeof(sshv1tab) / sizeof(struct keytab)) - 1;
7824
7825 static struct keytab sshv2tab[] = {     /* SET SSH V2 command table */
7826     { "authentication",          SSH2_AUT, 0 },
7827     { "auto-rekey",              SSH2_ARK, 0 },
7828     { "ciphers",                 SSH2_CIF, 0 },
7829     { "global-known-hosts-file", SSH2_GNH, 0 },
7830     { "hostkey-algorithms",      SSH2_HKA, 0 },
7831     { "macs",                    SSH2_MAC, 0 },
7832     { "user-known-hosts-file",   SSH2_UNH, 0 },
7833     { "", 0, 0 }
7834 };
7835 static int nsshv2tab = (sizeof(sshv2tab) / sizeof(struct keytab)) - 1;
7836
7837 #define SSHC_3DES 1                     /* 3DES */
7838 #define SSHC_3CBC 2                     /* 3DES-CBC */
7839 #define SSHC_A128 3                     /* AES128-CBC */
7840 #define SSHC_A192 4                     /* AES192-CBC */
7841 #define SSHC_A256 5                     /* AES256-CBC */
7842 #define SSHC_ARC4 6                     /* ARCFOUR */
7843 #define SSHC_FISH 7                     /* BLOWFISH */
7844 #define SSHC_BCBC 9                     /* BLOWFISH-CBC */
7845 #define SSHC_C128 8                     /* CAST128-CBC */
7846 #define SSHC_1DES 10                    /* DES */
7847
7848 static struct keytab ssh1ciphers[] = {
7849     { "3des",         SSHC_3DES, 0 },
7850     { "blowfish",     SSHC_FISH, 0 },
7851     { "des",          SSHC_1DES, 0 },
7852     { "", 0, 0 }
7853 };
7854 static int nssh1ciphers = (sizeof(ssh1ciphers) / sizeof(struct keytab)) - 1;
7855
7856 static struct keytab ssh2ciphers[] = {  /* SET SSH V2 CIPHERS command table */
7857     { "3des-cbc",        SSHC_3DES, 0 },
7858     { "aes128-cbc",      SSHC_A128, 0 },
7859     { "aes192-cbc",      SSHC_A192, 0 },
7860     { "aes256-cbc",      SSHC_A256, 0 },
7861     { "arcfour",         SSHC_ARC4, 0 },
7862     { "blowfish-cbc",    SSHC_FISH, 0 },
7863     { "cast128-cbc",     SSHC_C128, 0 },
7864     { "rijndael128-cbc", SSHC_A128, 0 },
7865     { "rijndael192-cbc", SSHC_A192, 0 },
7866     { "rijndael256-cbc", SSHC_A256, 0 },
7867     { "", 0, 0 }
7868 };
7869 static int nssh2ciphers = (sizeof(ssh2ciphers) / sizeof(struct keytab)) - 1;
7870
7871 #define SSHM_SHA        1               /* HMAC-SHA1 */
7872 #define SSHM_SHA_96     2               /* HMAC-SHA1-96 */
7873 #define SSHM_MD5        3               /* HMAC-MD5 */
7874 #define SSHM_MD5_96     4               /* HMAC-MD5-96 */
7875 #define SSHM_RIPE       5               /* HMAC-RIPEMD160 */
7876
7877 static struct keytab ssh2macs[] = {     /* SET SSH V2 MACS command table */
7878     { "hmac-md5",       SSHM_MD5,    0 },
7879     { "hmac-md5-96",    SSHM_MD5_96, 0 },
7880     { "hmac-ripemd160", SSHM_RIPE,   0 },
7881     { "hmac-sha1",      SSHM_SHA,    0 },
7882     { "hmac-sha1-96",   SSHM_SHA_96, 0 },
7883     { "", 0, 0 }
7884 };
7885 static int nssh2macs = (sizeof(ssh2macs) / sizeof(struct keytab)) - 1;
7886
7887 static struct keytab tgtpass[] = {
7888     { "tgt-passing", 1, 0, },
7889     { "", 0, 0 }
7890 };
7891 static int ntgtpass = (sizeof(tgtpass) / sizeof(struct keytab)) - 1;
7892
7893 static struct keytab gssapitab[] = {
7894     { "delegate-credentials", 1, 0, },
7895     { "key-exchange",         2, CM_INV, },
7896     { "", 0, 0 }
7897 };
7898 static int ngssapitab = (sizeof(gssapitab) / sizeof(struct keytab)) - 1;
7899
7900 #define HKA_RSA 1
7901 #define HKA_DSS 2
7902
7903 static struct keytab hkatab[] = {
7904     { "ssh-dss", HKA_DSS, 0, },
7905     { "ssh-rsa", HKA_RSA, 0, },
7906     { "", 0, 0 }
7907 };
7908 static int nhkatab = (sizeof(hkatab) / sizeof(struct keytab)) - 1;
7909
7910 int                                     /* SET SSH variables */
7911   ssh_afw = 0,                          /* agent forwarding */
7912   ssh_xfw = 0,                          /* x11 forwarding   */
7913   ssh_prp = SET_OFF,                    /* privileged ports */
7914   ssh_cmp = 1,                          /* compression */
7915   ssh_shh = 0,                          /* quiet       */
7916   ssh_ver = 0,                          /* protocol version (auto,1,2) */
7917   ssh_vrb = 2,                          /* Report errors */
7918   ssh_chkip = 0,                        /* SSH Check Host IP flag */
7919   ssh_gwp = 0,                          /* gateway ports */
7920   ssh_dyf = 0,                          /* dynamic forwarding */
7921   ssh_gsd = 0,                          /* gssapi delegate credentials */
7922   ssh_k4tgt = 0,                        /* k4 tgt passing */
7923   ssh_k5tgt = 0,                        /* k5 tgt passing */
7924   ssh_shk = 2,                          /* Strict host key (no, yes, ask) */
7925   ssh2_ark = 1,                         /* Auto re-key */
7926   ssh_cas = 0,                          /* command as subsys */
7927   ssh_cfg = 0,                          /* use OpenSSH config? */
7928   ssh_gkx = 1,                          /* gssapi key exchange */
7929   ssh_k5_is_k4 = 1,                     /* some SSH v1 use same codes */
7930   ssh_hbt = 0,                          /* heartbeat (seconds) */
7931   ssh_dummy = 0;                        /* bottom of list */
7932
7933 char                                    /* The following are to be malloc'd */
7934   * ssh1_cif = NULL,                    /* v1 cipher */
7935   * ssh2_cif = NULL,                    /* v2 cipher list */
7936   * ssh2_mac = NULL,                    /* v2 mac list */
7937   * ssh2_auth = NULL,                   /* v2 authentication list */
7938   * ssh_hst = NULL,                     /* hostname */
7939   * ssh_prt = NULL,                     /* port/service */
7940   * ssh_cmd = NULL,                     /* command to execute */
7941   * ssh_xal = NULL,                     /* xauth-location */
7942   * ssh1_gnh = NULL,                    /* v1 global known hosts file */
7943   * ssh1_unh = NULL,                    /* v1 user known hosts file */
7944   * ssh2_gnh = NULL,                    /* v2 global known hosts file */
7945   * ssh2_unh = NULL,                    /* v2 user known hosts file */
7946   * ssh2_hka = NULL,                    /* Host Key Algorithms */
7947   * xxx_dummy = NULL;
7948
7949 char * ssh_idf[32] = {                  /* Identity file list */
7950   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7951   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7952   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7953   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
7954 };
7955 char * ssh_tmp[32] = {                  /* Temp identity file list */
7956   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7957   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7958   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
7959   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
7960 };
7961 int ssh_idf_n = 0;
7962
7963 extern int    ssh_pf_lcl_n,
7964               ssh_pf_rmt_n;
7965 extern struct ssh_pf ssh_pf_lcl[32];    /* Port forwarding structs */
7966 extern struct ssh_pf ssh_pf_rmt[32];    /* (declared in ckuusr.c) */
7967 #endif /* SSHBUILTIN */
7968
7969 #ifdef SFTP_BUILTIN
7970 static struct keytab sftptab[] = {
7971     { "end-of-line",            XY_SFTP_EOL, 0, },
7972     { "remote-character-set",   XY_SFTP_RCS, 0, },
7973     { "", 0, 0 }
7974 };
7975 static int nsftptab = (sizeof(sftptab) / sizeof(struct keytab)) - 1;
7976 #endif /* SFTP_BUILTIN */
7977
7978 VOID
7979 shossh() {
7980 #ifdef SSHBUILTIN
7981     int i, n = 0;                       /* ADD askmore()! */
7982
7983     printf("\nSSH is built in:\n\n");
7984
7985     printf(" ssh host:                        %s\n",showstring(ssh_hst));
7986     printf(" ssh port:                        %s\n",showstring(ssh_prt));
7987     printf(" ssh command:                     %s\n",showstring(ssh_cmd));
7988     printf(" ssh agent-forwarding:            %s\n",showoff(ssh_afw));
7989     printf(" ssh check-host-ip:               %s\n",showoff(ssh_chkip));
7990     printf(" ssh compression:                 %s\n",showoff(ssh_cmp));
7991     printf(" ssh dynamic-forwarding:          %s\n",showoff(ssh_dyf));
7992     if (ssh_pf_lcl[0].p1 && ssh_pf_lcl[0].host && ssh_pf_lcl[0].p2) {
7993       printf(" ssh forward-local-port:          %d %s %d\n",
7994              ssh_pf_lcl[0].p1, ssh_pf_lcl[0].host, ssh_pf_lcl[0].p2);
7995       for ( n=1;n<ssh_pf_lcl_n;n++ )
7996         printf("                       :          %d %s %d\n",
7997                ssh_pf_lcl[n].p1, ssh_pf_lcl[n].host, ssh_pf_lcl[n].p2);
7998     } else
7999       printf(" ssh forward-local-port:         (none)\n");
8000     if (ssh_pf_rmt[0].p1 && ssh_pf_rmt[0].host && ssh_pf_rmt[0].p2) {
8001       printf(" ssh forward-remote-port:         %d %s %d\n",
8002              ssh_pf_rmt[0].p1, ssh_pf_rmt[0].host, ssh_pf_rmt[0].p2);
8003       for ( n=1;n<ssh_pf_rmt_n;n++ )
8004         printf("                        :         %d %s %d\n",
8005                ssh_pf_rmt[n].p1, ssh_pf_rmt[n].host, ssh_pf_rmt[n].p2);
8006     } else
8007       printf(" ssh forward-remote-port:        (none)\n");
8008     printf(" ssh gateway-ports:               %s\n",showoff(ssh_gwp));
8009     printf(" ssh gssapi delegate-credentials: %s\n",showoff(ssh_gsd));
8010     printf(" ssh gssapi key-exchange        : %s\n",showoff(ssh_gkx));
8011     printf(" ssh identity-file:               %d\n",ssh_idf_n);
8012     for (i = 0; i < ssh_idf_n; i++)
8013       printf("  %2d. %s\n",i+1,showstring(ssh_idf[i]));
8014     printf(" ssh heartbeat interval:          %d\n", ssh_hbt);
8015     printf(" ssh k4 tgt-passing:              %s\n",showoff(ssh_k4tgt));
8016     printf(" ssh k5 tgt-passing:              %s\n",showoff(ssh_k5tgt));
8017
8018     printf(" ssh privileged-port:             %s\n",showooa(ssh_prp));
8019     printf(" ssh quiet:                       %s\n",showoff(ssh_shh));
8020     printf(" ssh strict-host-key-check:       %d\n",ssh_shk);
8021     printf(" ssh use-openssh-config:          %s\n",showoff(ssh_cfg));
8022     printf(" ssh verbose:                     %d\n",ssh_vrb);
8023     printf(" ssh version:                     %s\n",
8024            ssh_ver ? ckitoa(ssh_ver) : "automatic"
8025            );
8026     printf(" ssh x11-forwarding:              %s\n",showooa(ssh_xfw));
8027     printf(" ssh xauth-location:              %s\n",showstring(ssh_xal));
8028     printf("\n");
8029     printf(" ssh v1 cipher:                   %s\n",showstring(ssh1_cif));
8030     printf(" ssh v1 global-known-hosts-file:  %s\n",showstring(ssh1_gnh));
8031     printf(" ssh v1 user-known-hosts-file:    %s\n",showstring(ssh1_unh));
8032     printf("\n");
8033     printf(" ssh v2 authentication:           %s\n",showstring(ssh2_auth));
8034     printf(" ssh v2 auto-rekey:               %s\n",showoff(ssh2_ark));
8035     printf(" ssh v2 ciphers:                  %s\n",showstring(ssh2_cif));
8036     printf(" ssh v2 command-as-subsystem:     %s\n",showoff(ssh_cas));
8037     printf(" ssh v2 global-known-hosts-file:  %s\n",showstring(ssh2_gnh));
8038     printf(" ssh v2 hostkey-algorithms:       %s\n",showstring(ssh2_hka));
8039     printf(" ssh v2 mac:                      %s\n",showstring(ssh2_mac));
8040     printf(" ssh v2 user-known-hosts-file:    %s\n",showstring(ssh2_unh));
8041 #else
8042 #ifdef SSHCMD
8043     extern char * sshcmd, * defsshcmd;
8044     char * s;
8045     s = sshcmd ? sshcmd : defsshcmd;
8046     printf("\n SSH is external.\n\n");
8047     printf(" ssh command: %s\n",showstring(s));
8048 #endif /* SSHCMD */
8049 #endif /* SSHBUILTIN */
8050     printf("\n");
8051 }
8052
8053 static int
8054 dosetssh() {
8055 #ifdef SSHCMD
8056     extern char * sshcmd;
8057 #endif /* SSHCMD */
8058 #ifdef SSHBUILTIN
8059 #ifndef SSHTEST
8060     extern int sl_ssh_xfw_saved, sl_ssh_ver_saved;
8061 #endif /* SSHTEST */
8062 #endif /* SSHBUILTIN */
8063     int cx, x, y, z;
8064     char * s;
8065
8066     if ((cx = cmkey(sshtab,nsshtab,"","command", xxstring)) < 0)
8067       return(cx);
8068     switch (cx) {
8069 #ifdef SSHCMD
8070       case SSH_CMD:                     /* Command */
8071         if ((x = cmtxt("Command to start ssh","ssh -e none",
8072                        &s,xxstring)) < 0)
8073           return(x);
8074         makestr(&sshcmd,s);
8075         return(success = 1);
8076 #endif /* SSHCMD */
8077
8078 #ifdef SSHBUILTIN
8079       case SSH_AFW:                     /* Agent-forwarding */
8080         return(success = seton(&ssh_afw));
8081
8082       case SSH_CHI:                     /* Check Host IP */
8083         return(success = seton(&ssh_chkip));
8084         break;
8085
8086       case SSH_CMP:                     /* Compression */
8087         return(success = seton(&ssh_cmp));
8088
8089       case SSH_DYF:                     /* Dynamic Forwarding */
8090         return(success = seton(&ssh_dyf));
8091
8092       case SSH_GWP:                     /* Gateway ports */
8093         return(success = seton(&ssh_gwp));
8094
8095       case SSH_GSS:                     /* GSSAPI */
8096         if ((y = cmkey(gssapitab,ngssapitab,"","", xxstring)) < 0)
8097           return(y);
8098         switch (y) {
8099           case 1:                       /* Delegate credentials */
8100             return(success = seton(&ssh_gsd));
8101           case 2:                       /* key-exchange */
8102             return(success = seton(&ssh_gkx));
8103         }
8104         if ((x = cmcfm()) < 0)
8105           return(x);
8106         return(success = 0);
8107
8108 #ifdef COMMENT
8109       case SSH_KBD:                     /* Kbd Interactive Devices */
8110         if ((x = cmcfm()) < 0)
8111           return(x);
8112         /* TO BE FILLED IN */
8113         return(-2);
8114 #endif /* COMMENT */
8115
8116       case SSH_K4:                      /* Kerberos IV */
8117       case SSH_K5:                      /* Kerberos V */
8118         if ((y = cmkey(tgtpass,1,"","tgt-passing", xxstring)) < 0)
8119           return(y);
8120         switch (y) {
8121           case 1:
8122             return(success = (cx == SSH_K4) ?
8123                    seton(&ssh_k4tgt) : seton(&ssh_k5tgt));
8124         }
8125         if ((x = cmcfm()) < 0)
8126           return(x);
8127         return(success = 0);
8128
8129       case SSH_PRP:                     /* Privd port */
8130         return(success = seton(&ssh_prp));
8131
8132       case SSH_SHH:                     /* Quiet */
8133         return(success = seton(&ssh_shh));
8134
8135       case SSH_SHK:                     /* Strict Host Key Check */
8136         if ((y = cmkey(ooktab,3,"","", xxstring)) < 0)
8137           return(y);
8138         if ((x = cmcfm()) < 0)
8139           return(x);
8140         ssh_shk = y;
8141         return(success = 1);
8142
8143       case SSH_HBT:
8144         x = cmnum("Heartbeat interval, seconds","0",10,&z,xxstring);
8145         if (x < 0) return(x);
8146         if ((x = cmcfm()) < 0) return(x);
8147         ssh_hbt = z;
8148         return(success = 1);
8149
8150       case SSH_V1:                      /* SSH V1 */
8151         if ((y = cmkey(sshv1tab,nsshv1tab,"","", xxstring)) < 0)
8152           return(y);
8153         switch (y) {
8154           case SSH1_K54:
8155             return(success = seton(&ssh_k5_is_k4));
8156           case SSH1_CIF:                /* Not a list */
8157             if ((y = cmkey(ssh1ciphers,nssh1ciphers,"","", xxstring)) < 0)
8158               if (y != -3)
8159                 return(y);
8160             if ((x = cmcfm()) < 0) return(x);
8161             if (y == -3) {
8162                 makestr(&ssh1_cif,NULL);
8163             } else {
8164                 for (x = 0; x < nssh1ciphers; x++)
8165                   if (ssh1ciphers[x].kwval == y)
8166                     break;
8167                 makestr(&ssh1_cif,ssh1ciphers[x].kwd);
8168             }
8169             return(1);
8170           case SSH1_GNH:
8171           case SSH1_UNH:
8172             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
8173                 if (x != -3)
8174                   return(x);
8175             } else {
8176                 ckstrncpy(line,s,LINBUFSIZ);
8177                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8178                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
8179             }
8180             s = (x == -3) ? NULL : line;
8181             if ((x = cmcfm()) < 0)
8182               return(x);
8183             switch (y) {
8184               case SSH1_GNH: makestr(&ssh1_gnh,s); break;
8185               case SSH1_UNH: makestr(&ssh1_unh,s); break;
8186             }
8187             return(1);
8188         }
8189
8190       case SSH_V2:                      /* SSH V2 */
8191         if ((y = cmkey(sshv2tab,nsshv2tab,"","", xxstring)) < 0)
8192           return(y);
8193         switch (y) {
8194           case SSH2_ARK:
8195             return(success = seton(&ssh2_ark));
8196         case SSH2_AUT: {                        /* Authentication */
8197 #define TMPCNT 12
8198             int i, j, tmp[TMPCNT];
8199             for (i = 0; i < TMPCNT; i++)
8200               tmp[i] = 0;
8201             for (i = 0; i < TMPCNT; i++) {
8202                 if ((y = cmkey(ssh2aut,nssh2aut,
8203                                "Authentication method","",xxstring)) < 0) {
8204                     if (y == -3)
8205                       break;
8206                     return(y);
8207                 }
8208                 for (j = 0; j < i; j++) {
8209                     if (tmp[j] == y) {
8210                         printf("\r\n?Choice has already been used.\r\n");
8211                         return(-9);
8212                     }
8213                 }
8214                 tmp[i] = y;
8215             }
8216             if ((z = cmcfm()) < 0)
8217               return(z);
8218
8219             if (ssh2_auth) {
8220                 free(ssh2_auth);
8221                 ssh2_auth = NULL;
8222             }
8223             if (i > 0) {
8224                 int len = 0;
8225                 for (j = 0; j < i; j++) {
8226                     for (x = 0; x < nssh2aut; x++)
8227                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
8228                         break;
8229                     len += strlen(ssh2aut[x].kwd) + 1;
8230                 }
8231                 ssh2_auth = malloc(len);
8232                 ssh2_auth[0] = '\0';
8233                 for (j = 0; j < i; j++) {
8234                     for (x = 0; x < nssh2aut; x++)
8235                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
8236                         break;
8237                     ckstrncat(ssh2_auth,ssh2aut[x].kwd,len);
8238                     if (j < i - 1)
8239                       ckstrncat(ssh2_auth,",",len);
8240                 }
8241             }
8242             return(success = 1);
8243 #undef TMPCNT
8244           }
8245         case SSH2_CIF: {
8246 #define TMPCNT 12
8247             int i, j, tmp[TMPCNT];
8248             for (i = 0; i < TMPCNT; i++)
8249               tmp[i] = 0;
8250
8251             for (i = 0; i < TMPCNT; i++) {
8252                 if ((y = cmkey(ssh2ciphers,nssh2ciphers,
8253                                "","", xxstring)) < 0) {
8254                     if (y == -3)
8255                       break;
8256                     return(y);
8257                 }
8258                 for (j = 0; j < i; j++) {
8259                     if (tmp[j] == y) {
8260                         printf("\r\n?Choice has already been used.\r\n");
8261                         return(-9);
8262                     }
8263                 }
8264                 tmp[i] = y;
8265             }
8266             if ((z = cmcfm()) < 0)
8267               return(z);
8268
8269             if (ssh2_cif) {
8270                 free(ssh2_cif);
8271                 ssh2_cif = NULL;
8272             }
8273             if (i > 0) {
8274                 int len = 0;
8275                 for (j=0; j < i; j++) {
8276                     for (x = 0; x < nssh2ciphers; x++)
8277                       if (ssh2ciphers[x].kwval == tmp[j] &&
8278                           !ssh2ciphers[x].flgs)
8279                         break;
8280                     len += strlen(ssh2ciphers[x].kwd) + 1;
8281                 }
8282                 ssh2_cif = malloc(len);
8283                 ssh2_cif[0] = '\0';
8284                 for (j = 0; j < i; j++) {
8285                   for (x = 0; x < nssh2ciphers; x++)
8286                     if (ssh2ciphers[x].kwval == tmp[j] && !ssh2ciphers[x].flgs)
8287                       break;
8288                     ckstrncat(ssh2_cif,ssh2ciphers[x].kwd,len);
8289                     if (j < i - 1)
8290                       ckstrncat(ssh2_cif,",",len);
8291                 }
8292             }
8293             return(success = 1);
8294 #undef TMPCNT
8295         }
8296         case SSH2_MAC: {
8297 #define TMPCNT 12
8298             int i, j, tmp[TMPCNT];
8299             for (i = 0; i < TMPCNT; i++)
8300               tmp[i] = 0;
8301
8302             for (i = 0; i < TMPCNT; i++) {
8303                 if ((y = cmkey(ssh2macs,nssh2macs,"","", xxstring)) < 0) {
8304                     if (y == -3)
8305                       break;
8306                     return(y);
8307                 }
8308                 for (j = 0; j < i; j++) {
8309                     if (tmp[j] == y) {
8310                         printf("\r\n?Choice has already been used.\r\n");
8311                         return(-9);
8312                     }
8313                 }
8314                 tmp[i] = y;
8315             }
8316             if ((z = cmcfm()) < 0)
8317                 return(z);
8318
8319             if (ssh2_mac) {
8320                 free(ssh2_mac);
8321                 ssh2_mac = NULL;
8322             }
8323             if (i > 0) {
8324                 int len = 0;
8325                 for (j = 0; j < i; j++) {
8326                     for (x = 0; x < nssh2macs; x++)
8327                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
8328                         break;
8329                     len += strlen(ssh2macs[x].kwd) + 1;
8330                 }
8331                 ssh2_mac = malloc(len);
8332                 ssh2_mac[0] = '\0';
8333                 for (j=0; j < i; j++) {
8334                     for (x = 0; x < nssh2macs; x++)
8335                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
8336                         break;
8337                     ckstrncat(ssh2_mac,ssh2macs[x].kwd,len);
8338                     if (j < i - 1)
8339                       ckstrncat(ssh2_mac,",",len);
8340                 }
8341             }
8342             return(success = 1);
8343 #undef TMPCNT
8344           }
8345           case SSH2_HKA: {
8346 #define TMPCNT 12
8347             int i, j, tmp[TMPCNT];
8348             for (i = 0; i < TMPCNT; i++)
8349               tmp[i] = 0;
8350
8351             for (i = 0; i < TMPCNT; i++) {
8352                 if ((y = cmkey(hkatab,nhkatab,
8353                                "","", xxstring)) < 0) {
8354                     if (y == -3)
8355                       break;
8356                     return(y);
8357                 }
8358                 for (j = 0; j < i; j++) {
8359                     if (tmp[j] == y) {
8360                         printf("\r\n?Choice has already been used.\r\n");
8361                         return(-9);
8362                     }
8363                 }
8364                 tmp[i] = y;
8365             }
8366             if ((z = cmcfm()) < 0)
8367               return(z);
8368
8369             if (ssh2_hka) {
8370                 free(ssh2_hka);
8371                 ssh2_hka = NULL;
8372             }
8373             if (i > 0) {
8374                 int len = 0;
8375                 for (j=0; j < i; j++) {
8376                     for (x = 0; x < nhkatab; x++)
8377                       if (hkatab[x].kwval == tmp[j] &&
8378                           !hkatab[x].flgs)
8379                         break;
8380                     len += strlen(hkatab[x].kwd) + 1;
8381                 }
8382                 ssh2_hka = malloc(len);
8383                 ssh2_hka[0] = '\0';
8384                 for (j = 0; j < i; j++) {
8385                   for (x = 0; x < nhkatab; x++)
8386                     if (hkatab[x].kwval == tmp[j] && !hkatab[x].flgs)
8387                       break;
8388                     ckstrncat(ssh2_hka,hkatab[x].kwd,len);
8389                     if (j < i - 1)
8390                       ckstrncat(ssh2_hka,",",len);
8391                 }
8392             }
8393             return(success = 1);
8394 #undef TMPCNT
8395           }
8396           case SSH2_GNH:
8397           case SSH2_UNH:
8398             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
8399                 if (x != -3)
8400                   return(x);
8401             } else {
8402                 ckstrncpy(line,s,LINBUFSIZ);
8403                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8404                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
8405             }
8406             s = (x == -3) ? NULL : line;
8407             if ((x = cmcfm()) < 0)
8408               return(x);
8409             switch (y) {
8410               case SSH2_GNH: makestr(&ssh2_gnh,s); break;
8411               case SSH2_UNH: makestr(&ssh2_unh,s); break;
8412               default: return(success = 0);
8413             }
8414             return(success = 1);
8415         }
8416
8417       case SSH_VRB:                     /* Verbosity level */
8418         y = cmnum("SSH verbosity level, 0-7","2",10,&x,xxstring);
8419         return(setnum(&ssh_vrb,x,y,7));
8420
8421       case SSH_VER:                     /* Version */
8422         if ((y = cmkey(sshver,3,"","auto", xxstring)) < 0)
8423           return(y);
8424         if ((x = cmcfm()) < 0)
8425           return(x);
8426         ssh_ver = y;                    /* 0 == AUTO */
8427 #ifndef SSHTEST
8428         sl_ssh_ver_saved = 0;
8429 #endif /* SSHTEST */
8430         return(success = 1);
8431
8432       case SSH_IDF: {                   /* Identity file */
8433         int i, n;
8434         for (i = 0; i < 32; i++) {
8435             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
8436                 if (x == -3)
8437                   break;
8438                 return(x);
8439             }
8440             if (!zfnqfp(s,LINBUFSIZ,line))
8441               ckstrncpy(line,s,LINBUFSIZ);
8442             makestr(&ssh_tmp[i],line);
8443         }
8444         n = i;
8445         if ((x = cmcfm()) < 0) {
8446             for (i = 0; i < n; i++)
8447               makestr(&(ssh_tmp[i]),NULL);
8448             return(x);
8449         }
8450         for (i = 0; i < 32; i++) {
8451             makestr(&(ssh_idf[i]),NULL);
8452             if (i < n) {
8453                 ssh_idf[i] = ssh_tmp[i];
8454                 ssh_tmp[i] = NULL;
8455             } else {
8456                 makestr(&(ssh_tmp[i]),NULL);
8457             }
8458         }
8459         ssh_idf_n = n;
8460         return(success = 1);
8461       }
8462       case SSH_XFW:                     /* X11-forwarding */
8463         success = seton(&ssh_xfw);
8464 #ifndef SSHTEST
8465         if (success)
8466           sl_ssh_xfw_saved = 0;
8467 #endif /* SSHTEST */
8468         return(success);
8469
8470       case SSH_XAL:                     /* SSH Xauth Location */
8471         if ((x = cmifi("Path to executable", "",&s,&y,xxstring)) < 0) {
8472             if (x != -3)
8473               return(x);
8474         } else {
8475             ckstrncpy(line,s,LINBUFSIZ);
8476             if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
8477               ckstrncpy(line,tmpbuf,LINBUFSIZ);
8478         }
8479         s = (x == -3) ? NULL : line;
8480         if ((x = cmcfm()) < 0) return(x);
8481         makestr(&ssh_xal,s);
8482         return(success = 1);
8483
8484       case SSH_CFG:                     /* Use OpenSSH Config */
8485         return(success = seton(&ssh_cfg));
8486 #endif /* SSHBUILTIN */
8487
8488       default:
8489         return(-2);
8490     }
8491 }
8492 #endif /* ANYSSH */
8493
8494 #ifdef SFTP_BUILTIN
8495 static int
8496 dosetsftp() {
8497     int cx, x, y, z;
8498     char * s;
8499
8500     if ((cx = cmkey(sftptab,nsftptab,"","", xxstring)) < 0)
8501       return(cx);
8502     switch (cx) {
8503     case XY_SFTP_EOL:
8504     case XY_SFTP_RCS:
8505     default:
8506         return(-2);
8507     }
8508 }
8509 #endif /* SFTP_BUILTIN */
8510
8511 #ifdef KUI
8512 #include "ikui.h"
8513 extern ULONG RGBTable[16];
8514
8515 #define GUI_RGB  1
8516 #define GUI_WIN  2
8517 #define GUI_FON  3
8518 #define GUI_DIA  4
8519 #define GUI_TLB  5
8520 #define GUI_MNB  6
8521 #define GUI_CLS  7
8522
8523 #define GUIW_POS 1
8524 #define GUIW_RES 2
8525 #define GUIW_RUN 3
8526 #define GUIWR_NON 0
8527 #define GUIWR_FON 1
8528 #define GUIWR_DIM 2
8529 #define GUIWN_RES 1
8530 #define GUIWN_MIN 2
8531 #define GUIWN_MAX 3
8532
8533 static struct keytab guitab[] = {
8534     { "close",       GUI_CLS,  0 },
8535     { "dialogs",     GUI_DIA,  0 },
8536     { "font",        GUI_FON,  0 },
8537     { "menubar",     GUI_MNB,  0 },
8538     { "rgbcolor",    GUI_RGB,  0 },
8539     { "toolbar",     GUI_TLB,  0 },
8540     { "window",      GUI_WIN,  0 },
8541     { "", 0, 0}
8542 };
8543 static int nguitab = (sizeof(guitab) / sizeof(struct keytab));
8544
8545 static struct keytab guiwtab[] = {
8546     { "position",    GUIW_POS, 0 },
8547     { "resize-mode", GUIW_RES, 0 },
8548     { "run-mode",    GUIW_RUN, 0 },
8549     { "", 0, 0}
8550 };
8551 static int nguiwtab = (sizeof(guiwtab) / sizeof(struct keytab));
8552
8553 static struct keytab guiwrtab[] = {
8554     { "change-dimensions",  GUIWR_DIM, 0 },
8555     { "none",               GUIWR_NON, 0 },
8556     { "scale-font",         GUIWR_FON, 0 },
8557     { "", 0, 0}
8558 };
8559 static int nguiwrtab = (sizeof(guiwrtab) / sizeof(struct keytab));
8560
8561 static struct keytab guiwntab[] = {
8562     { "maximize",  GUIWN_MAX, 0 },
8563     { "minimize",  GUIWN_MIN, 0 },
8564     { "restore",   GUIWN_RES, 0 },
8565     { "", 0, 0}
8566 };
8567 static int nguiwntab = (sizeof(guiwntab) / sizeof(struct keytab));
8568
8569 static struct keytab rgbtab[] = {
8570     { "black",         0, 0 },
8571     { "blue",          1, 0 },
8572     { "brown",         6, 0 },
8573     { "cyan",          3, 0 },
8574     { "darkgray",      8, 0 },
8575     { "dgray",         8, CM_INV },
8576     { "green",         2, 0 },
8577     { "lblue",         9, CM_INV },
8578     { "lcyan",        11, CM_INV },
8579     { "lgreen",       10, CM_INV },
8580     { "lgray",         7, CM_INV },
8581     { "lightblue",     9, 0 },
8582     { "lightcyan",    11, 0 },
8583     { "lightgreen",   10, 0 },
8584     { "lightgray",     7, 0 },
8585     { "lightmagenta", 13, 0 },
8586     { "lightred",     12, 0 },
8587     { "lmagenta",     13, CM_INV },
8588     { "lred",         12, CM_INV },
8589     { "magenta",       5, 0 },
8590     { "red",           4, 0 },
8591     { "white",        15, 0 },
8592     { "yellow",       14, 0 },
8593
8594 };
8595 int nrgb = (sizeof(rgbtab) / sizeof(struct keytab));
8596
8597 VOID
8598 shogui() {
8599     extern gui_dialog;
8600     extern HWND getHwndKUI();
8601     unsigned char cmdsav = colorcmd;
8602     int i, red, green, blue, lines=0;
8603     char * s;
8604
8605
8606     printf("GUI paramters:\n");
8607     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8608     printf("  Dialogs:     %s\n",showoff(gui_dialog));
8609     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8610     printf("  Position:    %d,%d\n",get_gui_window_pos_x(),
8611             get_gui_window_pos_y());
8612     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8613     printf("  Resolution:  %d x %d\n",GetSystemMetrics(SM_CXSCREEN),
8614             GetSystemMetrics(SM_CYSCREEN));
8615     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8616     printf("  Run-mode:    %s\n",IsIconic(getHwndKUI()) ? "minimized" :
8617             IsZoomed(getHwndKUI()) ? "maximized" : "restored");
8618     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8619     switch ( get_gui_resize_mode() ) {
8620       case GUIWR_NON:
8621         s = "none";
8622         break;
8623       case GUIWR_FON:
8624         s = "scales font";
8625         break;
8626       case GUIWR_DIM:
8627         s= "changes dimensions";
8628         break;
8629     }
8630     printf("  Resize-mode: %s\n",s);
8631     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8632     printf("\n");
8633     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8634
8635     printf("RGB Color Table:\n");
8636     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8637     printf("  Color              Red Green Blue\n");
8638     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8639     printf("  ------------------------------------------\n");
8640     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
8641     for (i = 0; i < nrgb; i++) {
8642         if (!rgbtab[i].flgs) {
8643             blue = (RGBTable[rgbtab[i].kwval] & 0x00FF0000)>>16;
8644             green = (RGBTable[rgbtab[i].kwval] & 0x0000FF00)>>8;
8645             red = (RGBTable[rgbtab[i].kwval] & 0x000000FF);
8646             printf("  %-18s %3d  %3d  %3d  ",rgbtab[i].kwd,red,green,blue);
8647             colorcmd = rgbtab[i].kwval << 4;
8648             printf("********");
8649             colorcmd = cmdsav;
8650             printf("\n");
8651             if (++lines > cmd_rows - 3) {
8652                 if (!askmore())
8653                   return;
8654                 else
8655                   lines = 0;
8656             }
8657         }
8658     }
8659     printf("\n");
8660 }
8661
8662 int
8663 setrgb() {
8664     int cx, red = 0, blue = 0, green = 0, z, x;
8665
8666     if ((cx = cmkey(rgbtab,nrgb,"","",xxstring)) < 0)
8667       return(cx);
8668     if ((z = cmnum("Red value, 0-255","",10,&red,xxstring)) < 0)
8669       return(z);
8670     if ((z = cmnum("Green value, 0-255","",10,&green,xxstring)) < 0)
8671       return(z);
8672     if ((z = cmnum("Blue value, 0-255","",10,&blue,xxstring)) < 0)
8673       return(z);
8674     if ((x = cmcfm()) < 0) return(x);
8675     if (cx > 15 || red > 255 || blue > 255 || green > 255)
8676       return(-2);
8677     RGBTable[cx] = (unsigned)(((unsigned)blue << 16) |
8678         (unsigned)((unsigned)green << 8) |
8679         (unsigned)red);
8680     return(success = 1);
8681 }
8682
8683 /*
8684   Set GUI window position: XY coordinates of upper left corner,
8685   expressed as pixel numbers in the current screen resolution.
8686   (0,0) means put ourselves in the upper left corner.
8687   Can we check for out of bounds?
8688 */
8689
8690 int
8691 setguiwin() {
8692     int cx, x, y, z;
8693     if ((cx = cmkey(guiwtab,nguiwtab,"","",xxstring)) < 0)
8694       return(cx);
8695     switch (cx) {
8696       case GUIW_POS:
8697         if ((z = cmnum("X coordinate (pixel number)","",10,&x,xxstring)) < 0)
8698           return(z);
8699         if ((z = cmnum("Y coordinate (pixel number)","",10,&y,xxstring)) < 0)
8700           return(z);
8701         if ((z = cmcfm()) < 0)
8702           return(z);
8703         if (x < 0 || y < 0) {
8704             printf("?Coordinates must be 0 or greater\n");
8705             return(-9);
8706         }
8707         gui_position(x,y);
8708         return(success = 1);
8709       case GUIW_RES:
8710         if ((x = cmkey(guiwrtab,nguiwrtab,"","",xxstring)) < 0)
8711           return(x);
8712         if ((z = cmcfm()) < 0)
8713           return(z);
8714         gui_resize_mode(x);
8715         return(success = 1);
8716       case GUIW_RUN:
8717         if ((x = cmkey(guiwntab,nguiwntab,"","",xxstring)) < 0)
8718           return(x);
8719         if ((z = cmcfm()) < 0)
8720           return(z);
8721         gui_win_run_mode(x);
8722         return(success = 1);
8723       default:
8724         return(-2);
8725     }
8726 }
8727
8728 int
8729 setguifont() {                          /* Assumes that CKFLOAT is defined! */
8730
8731     extern struct keytab * term_font;
8732     extern struct keytab * _term_font;
8733     extern int tt_font, tt_font_size, ntermfont;
8734     int x, y, z;
8735     char *s;
8736
8737     if (ntermfont == 0)
8738       BuildFontTable(&term_font, &_term_font, &ntermfont);
8739     if (!(term_font && _term_font && ntermfont > 0)) {
8740         printf("?Internal error: Failure to enumerate fonts\n");
8741         return(-9);
8742     }
8743     if ((x = cmkey(_term_font,ntermfont,"","",xxstring)) < 0)
8744       return(x);
8745     if ((z = cmfld("Height of font in points","12",&s,xxstring)) < 0)
8746       return(z);
8747     if (isfloat(s,0) < 1) {             /* (sets floatval) */
8748         printf("?Integer or floating-point number required\n");
8749         return(-9);
8750     }
8751     if (floatval < 0.5) {
8752         printf("?Positive number required\n");
8753         return(-9);
8754     }
8755     if ((z = cmcfm()) < 0)
8756       return(z);
8757     tt_font = x;                        /* Font index */
8758     tt_font_size = (int)(floatval * 2); /* Font size in half points */
8759     KuiSetProperty(KUI_TERM_FONT, (long)tt_font, (long)tt_font_size);
8760     return(success = 1);
8761 }
8762
8763 VOID
8764 setguidialog(x) int x;
8765 {
8766     extern int gui_dialog;
8767     gui_dialog = x;
8768     KuiSetProperty(KUI_GUI_DIALOGS, (long)x, 0L);
8769 }
8770
8771 VOID
8772 setguimenubar(x) int x;
8773 {
8774     KuiSetProperty(KUI_GUI_MENUBAR, (long)x, 0L);
8775 }
8776
8777 VOID
8778 setguitoolbar(x) int x;
8779 {
8780     KuiSetProperty(KUI_GUI_TOOLBAR, (long)x, 0L);
8781 }
8782
8783 VOID
8784 setguiclose(x) int x;
8785 {
8786     KuiSetProperty(KUI_GUI_CLOSE, (long)x, 0L);
8787 }
8788
8789 int
8790 setgui() {
8791     int cx, x, rc;
8792     if ((cx = cmkey(guitab,nguitab,"","",xxstring)) < 0)
8793       return(cx);
8794     switch (cx) {
8795       case GUI_DIA:
8796         rc = seton(&x);
8797         if (rc >= 0)
8798           setguidialog(x);
8799         return(rc);
8800       case GUI_FON:
8801         return(setguifont());
8802       case GUI_RGB:
8803         return(setrgb());
8804       case GUI_WIN:
8805         return(setguiwin());
8806       case GUI_TLB:
8807         rc = seton(&x);
8808         if (rc >= 0)
8809           setguitoolbar(x);
8810         return(rc);
8811       case GUI_MNB:
8812         rc = seton(&x);
8813         if (rc >= 0)
8814           setguimenubar(x);
8815         return(rc);
8816       case GUI_CLS:
8817         rc = seton(&x);
8818         if (rc >= 0)
8819           setguiclose(x);
8820         return(rc);
8821       default:
8822         return(-2);
8823     }
8824 }
8825 #endif /* KUI */
8826
8827 VOID
8828 setexitwarn(x) int x; 
8829 {
8830     xitwarn = x;
8831 #ifdef KUI
8832     KuiSetProperty(KUI_EXIT_WARNING, (long)x, 0L);
8833 #endif /* KUI */
8834 }
8835
8836 #ifndef NOLOCAL
8837 VOID
8838 setdebses(x) int x; {
8839 #ifdef OS2
8840     if ((debses != 0) && (x == 0))      /* It was on and we turned it off? */
8841       os2debugoff();                    /* Fix OS/2 coloration */
8842 #endif /* OS2 */
8843     debses = x;
8844 #ifdef KUI
8845     KuiSetProperty(KUI_TERM_DEBUG,x,0);
8846 #endif /* KUI */
8847 }
8848 #endif /* NOLOCAL */
8849
8850 /*  D O P R M  --  Set a parameter.  */
8851 /*
8852  Returns:
8853   -2: illegal input
8854   -1: reparse needed
8855    0: success
8856 */
8857 int
8858 doprm(xx,rmsflg) int xx, rmsflg; {
8859     int i = 0, x = 0, y = 0, z = 0;
8860     long zz = 0L;
8861     char *s = NULL, *p = NULL;
8862 #ifdef OS2
8863     char portbuf[64];
8864     long portspeed = 0L;
8865     int portparity = 0;
8866     int portflow = 0;
8867 #endif /* OS2 */
8868
8869 #ifndef NOSETKEY
8870 #ifdef OS2
8871     if (xx == XYMSK)
8872       return(setmsk());
8873 #endif /* OS2 */
8874 #endif /* NOSETKEY */
8875
8876     if (xx == XYFLAG) {                 /* SET FLAG */
8877         extern int ooflag;
8878         return(success = seton(&ooflag));
8879     }
8880     if (xx == XYPRTR                    /* SET PRINTER (or BPRINTER) */
8881 #ifdef BPRINT
8882         || xx == XYBDCP
8883 #endif /* BPRINT */
8884         )
8885       return(setprinter(xx));
8886
8887     switch (xx) {
8888
8889 #ifdef ANYX25                           /* SET X25 ... */
8890 case XYX25:
8891         return(setx25());
8892
8893 #ifndef IBMX25
8894 case XYPAD:                             /* SET PAD ... */
8895         return(setpadp());
8896 #endif /* IBMX25 */
8897 #endif /* ANYX25 */
8898
8899 #ifndef NOXFER
8900       case XYEOL:       /* These have all been moved to set send/receive... */
8901       case XYLEN:       /* Let the user know what to do. */
8902       case XYMARK:
8903       case XYNPAD:
8904       case XYPADC:
8905       case XYTIMO:
8906         printf("...Use SET SEND or SET RECEIVE instead.\n");
8907         printf("Type HELP SET SEND or HELP SET RECEIVE for more info.\n");
8908         return(success = 0);
8909
8910       case XYATTR:                      /* File Attribute packets */
8911         return(setat(rmsflg));
8912
8913       case XYIFD:                       /* Incomplete file disposition */
8914         if ((y = cmkey(ifdatab,3,"","auto",xxstring)) < 0) return(y);
8915         if ((x = cmcfm()) < 0) return(x);
8916         if (rmsflg) {
8917             sstate = setgen('S',
8918                             "310",
8919                             y == 0 ? "0" : (y == 1 ? "1" : "2"),
8920                             ""
8921                             );
8922             return((int) sstate);
8923         } else {
8924             keep = y;
8925             return(success = 1);
8926         }
8927 #endif /* NOXFER */
8928
8929       case XYMATCH:                     /* [ REMOTE ] SET MATCH...  */
8930 #ifndef NOXFER
8931         if ((z = cmkey(matchtab,nmatchtab,"","",xxstring)) < 0)
8932           return(z);
8933         if (rmsflg) {
8934             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
8935             if ((x = cmcfm()) < 0) return(x);
8936             switch (z) {
8937               case MCH_DOTF:
8938                 return(sstate = setgen('S',"330", y == 0 ? "0" : "1", ""));
8939               case MCH_FIFO:
8940                 return(sstate = setgen('S',"331", y == 0 ? "0" : "1", ""));
8941               default:
8942                 return(-2);
8943               }
8944           }
8945 #endif /* NOXFER */
8946           switch (z) {
8947             case MCH_FIFO:
8948               return(success = seton(&matchfifo));
8949             case MCH_DOTF:
8950               x = seton(&matchdot); 
8951               if (x < 0) return(x);
8952               dir_dots = -1;
8953               return(success = x);
8954             default:
8955               return(-2);
8956           }
8957
8958 #ifndef NOSPL
8959       case XYINPU:                      /* SET INPUT */
8960         return(setinp());
8961 #endif /* NOSPL */
8962
8963 #ifdef NETCONN
8964       case XYNET: {                     /* SET NETWORK */
8965
8966           struct FDB k1, k2;
8967
8968           cmfdbi(&k1,_CMKEY,"","","",nnetkey, 0, xxstring, netkey, &k2);
8969           cmfdbi(&k2,_CMKEY,"","","",nnets,   0, xxstring, netcmd, NULL);
8970
8971 #ifdef OS2     /* Hide network-type keywords for networks not installed */
8972           for (z = 0; z < nnets; z++) {
8973               if (netcmd[z].kwval == NET_TCPB && tcp_avail == 0)
8974                 netcmd[z].flgs =  CM_INV;
8975 #ifdef SSHBUILTIN
8976               if (netcmd[z].kwval == NET_SSH &&
8977                    !ck_ssleay_is_installed())
8978                 netcmd[z].flgs =  CM_INV;
8979 #endif /* SSHBUILTIN */
8980 #ifdef DECNET
8981               else if (netcmd[z].kwval == NET_DEC  && dnet_avail == 0)
8982                 netcmd[z].flgs =  CM_INV;
8983 #endif /* DECNET */
8984 #ifdef CK_NETBIOS
8985               else if (netcmd[z].kwval == NET_BIOS && netbiosAvail == 0)
8986                 netcmd[z].flgs =  CM_INV;
8987 #endif /* CK_NETBIOS */
8988 #ifdef SUPERLAT
8989               else if (netcmd[z].kwval == NET_SLAT  && slat_avail == 0)
8990                 netcmd[z].flgs =  CM_INV;
8991 #endif /* SUPERLAT */
8992           }
8993           if (tcp_avail)                /* Default network type */
8994             ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
8995 #ifdef SSHBUILTIN
8996           else if ( ck_ssleay_is_installed() )
8997             ckstrncpy(tmpbuf,"ssh",TMPBUFSIZ);
8998 #endif /* SSHBUILTIN */
8999 #ifdef DECNET
9000           else if (dnet_avail)
9001             ckstrncpy(tmpbuf,"decnet",TMPBUFSIZ);
9002 #endif /* DECNET */
9003 #ifdef SUPERLAT
9004           else if (slat_avail)
9005             ckstrncpy(tmpbuf,"superlat",TMPBUFSIZ);
9006 #endif /* SUPERLAT */
9007 #ifdef CK_NETBIOS
9008           else if (netbiosAvail)
9009             ckstrncpy(tmpbuf,"netbios",TMPBUFSIZ);
9010 #endif /* CK_NETBIOS */
9011           else ckstrncpy(tmpbuf,"named-pipe",TMPBUFSIZ);
9012 #else  /* OS2 */
9013 #ifdef TCPSOCKET
9014           ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
9015 #else
9016 #ifdef ANYX25
9017           ckstrncpy(tmpbuf,"x.25",TMPBUFSIZ);
9018 #else
9019           ckstrncpy(tmpbuf,"",TMPBUFSIZ);
9020 #endif /* ANYX25 */
9021 #endif /* TCPSOCKET */
9022 #endif /* OS2 */
9023
9024           x = cmfdb(&k1);
9025           if (x < 0) {                  /* Error */
9026               if (x == -2 || x == -9)
9027                 printf("?No keywords match: \"%s\"\n",atmbuf);
9028               return(x);
9029           }
9030           z = cmresult.nresult;         /* Keyword value */
9031           if (cmresult.fdbaddr == &k1) { /* Which table? */
9032 #ifndef NOSPL
9033 #ifndef NODIAL
9034               if (z == XYNET_D)
9035                 return(parsdir(1));
9036 #endif /* NODIAL */
9037 #endif /* NOSPL */
9038               if ((z = cmkey(netcmd,nnets,"",tmpbuf,xxstring)) < 0)
9039                 return(z);
9040           }
9041
9042 #ifdef NETCMD
9043           if (z == NET_CMD && nopush) {
9044               printf("\n?Sorry, access to external commands is disabled\n");
9045               return(-9);
9046           }
9047 #endif /* NETCMD */
9048
9049 #ifndef NOPUSH
9050 #ifdef NETPTY
9051           if (z == NET_PTY && nopush) {
9052               printf("\n?Sorry, access to external commands is disabled\n");
9053               return(-9);
9054           }
9055 #endif /* NETPTY */
9056 #endif /* NOPUSH */
9057
9058 #ifdef OS2
9059           if (z == NET_TCPB && tcp_avail == 0) {
9060               printf(
9061 "\n?Sorry, either TCP/IP is not available on this system or\n\
9062 necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
9063               return(-9);
9064 #ifdef SSHBUILTIN
9065           } else if (z == NET_SSH && !ck_ssleay_is_installed()) {
9066             printf("\n?Sorry, SSH is not available on this system.\n") ;
9067             return(-9);
9068 #endif /* SSHBUILTIN */
9069 #ifdef CK_NETBIOS
9070           } else if (z == NET_BIOS && netbiosAvail == 0) {
9071               printf("\n?Sorry, NETBIOS is not available on this system.\n") ;
9072               return(-9);
9073 #endif /* CK_NETBIOS */
9074 #ifdef DECNET
9075           } else if (z == NET_DEC && dnet_avail == 0) {
9076               printf("\n?Sorry, DECnet is not available on this system.\n") ;
9077               return(-9);
9078 #endif /* DECNET */
9079 #ifdef SUPERLAT
9080           } else if (z == NET_SLAT && slat_avail == 0) {
9081               printf("\n?Sorry, SuperLAT is not available on this system.\n") ;
9082               return(-9);
9083 #endif /* SUPERLAT */
9084           }
9085 #endif /* OS2 */
9086
9087 #ifdef NPIPEORBIOS
9088           if (z == NET_PIPE ||          /* Named pipe -- also get pipename */
9089               z == NET_BIOS) {          /* NETBIOS -- also get local name */
9090               char *defnam;
9091 #ifdef CK_NETBIOS
9092               char tmpnbnam[NETBIOS_NAME_LEN+1];
9093 #endif /* CK_NETBIOS */
9094               /* Construct default name  */
9095               if (z == NET_PIPE) {      /* Named pipe */
9096                   defnam = "kermit";    /* Default name is always "kermit" */
9097               } 
9098 #ifdef CK_NETBIOS
9099               else {                    /* NetBIOS */
9100                   if (NetBiosName[0] != SP) { /* If there is already a name, */
9101                       char *p = NULL;
9102                       int n;            /* use it as the default. */
9103                       ckstrncpy(tmpnbnam,NetBiosName,NETBIOS_NAME_LEN+1);
9104                       /* convert trailing spaces to NULs */
9105                       p = &tmpnbnam[NETBIOS_NAME_LEN-1];
9106                       while (*p == SP) {
9107                           *p = NUL;
9108                           p--;
9109                       }
9110                       defnam = tmpnbnam;
9111                   } else if (*myhost)   /* Otherwise use this PC's host name */
9112                     defnam = (char *) myhost;
9113                   else                  /* Otherwise use "kermit" */
9114                     defnam = "kermit";
9115               }
9116 #endif /* CK_NETBIOS */
9117               if ((y = cmtxt((z == NET_PIPE) ? "name of named-pipe" :
9118                              "local NETBIOS name",
9119                              defnam, &s, xxstring)) < 0)
9120                 return(y);
9121 #ifdef NPIPE
9122               pipename[0] = NUL;
9123 #endif /* NPIPE */
9124               if ((y = (int) strlen(s)) < 1) {
9125                   printf("?You must also specify a %s name\n",
9126                          (z == NET_PIPE) ? "pipe" : "local NETBIOS" );
9127                   return(-9);
9128               }
9129 #ifdef CK_NETBIOS
9130               if (z == NET_BIOS) {
9131                   if (!netbiosAvail) {
9132                       printf("?NETBIOS is not available on this system.\n") ;
9133                       return(-9);
9134                   }
9135                   if (y - NETBIOS_NAME_LEN > 0) {
9136                       printf("?NETBIOS name too long, %ld maximum\n",
9137                              NETBIOS_NAME_LEN);
9138                       return(-9);
9139                   } else if ( !strcmp(s,tmpnbnam) ) {
9140                       nettype = z;      /* Returning to old connection... */
9141                       return(success = 1); /* Done */
9142                   } else if (strcmp("                ",NetBiosName)) {
9143                       printf("?NETBIOS name already assigned to \"%s\"\n",
9144                              NetBiosName);
9145                       return(-9);
9146                   } else {
9147                       NCB ncb;
9148                       APIRET rc;
9149                       ckstrncpy(NetBiosName,s,16);
9150                       for (x = y; x < NETBIOS_NAME_LEN; x++)
9151                         NetBiosName[x] = SP;
9152                       NetBiosName[NETBIOS_NAME_LEN] = NUL;
9153                       printf("Checking \"%s\" as a unique NetBIOS name...\n",
9154                              NetBiosName);
9155                       rc = NCBAddName( NetbeuiAPI,
9156                                       &ncb, NetBiosAdapter, NetBiosName );
9157                       if (rc) {
9158                           printf(
9159                 "?Sorry, \"%s\" is already in use by another NetBIOS node.\n",
9160                                  NetBiosName);
9161                           for (x = 0; x < NETBIOS_NAME_LEN; x++)
9162                             NetBiosName[x] = SP;
9163                           return(-9);
9164                       }
9165                   }
9166               }
9167 #endif /* CK_NETBIOS */
9168 #ifdef NPIPE
9169               if (z == NET_PIPE)
9170                 ckstrncpy(pipename,s,PIPENAML);
9171 #endif /* NPIPE */
9172           } else
9173 #endif /* NPIPEORBIOS */
9174 #ifdef DECNET
9175             if (z == NET_DEC) {
9176                 /* Determine if we are using LAT or CTERM */
9177                 if ((y = cmkey(dnettab,
9178                                ndnet,"DECNET protocol","lat",xxstring)) < 0)
9179                   return(y);
9180                 if ((x = cmcfm()) < 0) return(x);
9181                 ttnproto = y;
9182             } else
9183 #endif /* DECNET */
9184 #ifdef NETDLL
9185               if (z == NET_DLL) {
9186                   /* Find out which DLL they are using */
9187                   char dllname[256]="";
9188                   char * p=NULL;
9189                   if ((x = cmifi("Dynamic load library",
9190                                  "",&p,&y,xxstring)) < 0) {
9191                       if (x == -3) {
9192                           printf("?Name of DLL required\n");
9193                           return(-9);
9194                       }
9195                       return(x);
9196                   }
9197                   ckstrncpy(dllname,p,256);
9198                   if ((x = cmcfm()) < 0) return(x);
9199
9200                   if (netdll_load(dllname) < 0) /* Try to load the dll */
9201                     return(success = 0);
9202                   else {
9203                       nettype = z;
9204                       return(success = 1);
9205                   }
9206               } else
9207 #endif /* NETDLL */
9208                 if ((x = cmcfm()) < 0) return(x);
9209           nettype = z;
9210           if (
9211 #ifdef DECNET
9212               (nettype != NET_DEC)  &&
9213 #endif /* DECNET */
9214 #ifdef NPIPE
9215               (nettype != NET_PIPE) &&
9216 #endif /* NPIPE */
9217 #ifdef CK_NETBIOS
9218               (nettype != NET_BIOS) &&
9219 #endif /* CK_NETBIOS */
9220 #ifdef NETFILE
9221               (nettype != NET_FILE) &&
9222 #endif /* NETFILE */
9223 #ifdef NETCMD
9224               (nettype != NET_CMD) &&
9225 #endif /* NETCMD */
9226 #ifdef NETPTY
9227               (nettype != NET_PTY) &&
9228 #endif /* NETPTY */
9229 #ifdef NETDLL
9230               (nettype != NET_DLL) &&
9231 #endif /* NETDLL */
9232 #ifdef SUPERLAT
9233               (nettype != NET_SLAT) &&
9234 #endif /* SUPERLAT */
9235               (nettype != NET_SX25) &&
9236               (nettype != NET_VX25) &&
9237 #ifdef IBMX25
9238               (nettype != NET_IX25) &&
9239 #endif /* IBMX25 */
9240 #ifdef SSHBUILTIN
9241               (nettype != NET_SSH) &&
9242 #endif /* SSHBUILTIN */
9243               (nettype != NET_TCPB)) {
9244               printf("?Network type not supported\n");
9245               return(success = 0);
9246           } else {
9247               return(success = 1);
9248           }
9249       }
9250
9251 #ifndef NOTCPOPTS
9252 #ifdef TCPSOCKET
9253       case XYTCP: {
9254         extern int ttyfd;
9255
9256         if ((z = cmkey(tcpopt,ntcpopt,"TCP option","nodelay",xxstring)) < 0)
9257           return(z);
9258
9259         switch (z) {
9260 #ifndef NOHTTP
9261           case XYTCP_HTTP_PROXY: {
9262               struct FDB sw, tx;
9263               int n, x;
9264               char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1], abuf[256];
9265               ubuf[0] = pbuf[0] = abuf[0] = 0;
9266
9267               cmfdbi(&sw,               /* First FDB - switches */
9268                      _CMKEY,            /* fcode */
9269                      "HTTP proxy server host[:port] or switch",
9270                      "",                /* default */
9271                      "",                /* addtl string data */
9272                      nuserpass,         /* addtl numeric data 1: tbl size */
9273                      4,                 /* addtl numeric data 2: 4 = cmswi */
9274                      xxstring,          /* Processing function */
9275                      userpass,          /* Keyword table */
9276                      &tx                /* Pointer to next FDB */
9277                      );
9278               cmfdbi(&tx,
9279                      _CMTXT,            /* fcode */
9280                      "HTTP proxy server host[:port]",
9281                      "",                /* default */
9282                      "",                /* addtl string data */
9283                      0,                 /* addtl numeric data 1 */
9284                      0,                 /* addtl numeric data 2 */
9285                      xxstring,
9286                      NULL,
9287                      NULL
9288                      );
9289               while (1) {
9290                   if ((x = cmfdb(&sw)) < 0) {
9291                       if (x == -3) {
9292                           x = -9;
9293                           printf("?Hostname required\n");
9294                       }
9295                       return(x);
9296                   }
9297                   if (cmresult.fcode != _CMKEY)
9298                     break;
9299                   n = cmresult.nresult;
9300                   switch (n) {
9301                     case UPW_USER:
9302                     case UPW_PASS:
9303                     case UPW_AGENT:
9304                       if ((x = cmfld((n == UPW_USER) ?
9305                                      "Username" :
9306                                      ((n == UPW_PASS) ? "Password" : "Agent"),
9307                                      "", &s, xxstring)) < 0) {
9308                           if (x != -3)
9309                             return(x);
9310                       }
9311                       ckstrncpy((n == UPW_USER) ? ubuf :
9312                         ((n == UPW_PASS) ? pbuf : abuf), s, 
9313                         (n == UPW_AGENT) ? 256 : (LOGINLEN+1));
9314                   }
9315               }
9316               if (cmresult.fcode != _CMTXT)
9317                 return(-2);
9318               s = cmresult.sresult;
9319               if (s) if (!*s) s = NULL;
9320
9321 #ifdef IKSDCONF
9322               if (iksdcf)
9323                 return(success = 0);
9324 #endif /* IKSDCONF */
9325               makestr(&tcp_http_proxy_user,ubuf[0]?ubuf:NULL);
9326               makestr(&tcp_http_proxy_pwd,pbuf[0]?pbuf:NULL);
9327               makestr(&tcp_http_proxy_agent,abuf[0]?abuf:NULL);
9328               makestr(&tcp_http_proxy,s);
9329               memset(pbuf,0,sizeof(pbuf));
9330               return(success = 1);
9331           }
9332 #endif /* NOHTTP */
9333 /*
9334   It would have been easy to combine XYTCP_SOCKS_SVR with the previous
9335   one except for the #ifdefs...
9336 */
9337 #ifdef NT
9338 #ifdef CK_SOCKS
9339           case XYTCP_SOCKS_SVR: {
9340               char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1];
9341               char * p = getenv("SOCKS_SERVER");
9342               struct FDB sw, tx;
9343               int n, x;
9344
9345               if (!p) p = "";
9346
9347               cmfdbi(&sw,               /* First FDB - switches */
9348                      _CMKEY,            /* fcode */
9349                      "SOCKS server host[:port] or switch",
9350                      "",                /* default */
9351                      "",                /* addtl string data */
9352                      nuserpass,         /* addtl numeric data 1: tbl size */
9353                      4,                 /* addtl numeric data 2: 4 = cmswi */
9354                      xxstring,          /* Processing function */
9355                      userpass,          /* Keyword table */
9356                      &tx                /* Pointer to next FDB */
9357                      );
9358               cmfdbi(&tx,
9359                      _CMTXT,            /* fcode */
9360                      "SOCKS server host[:port]",
9361                      p,                 /* default */
9362                      "",                /* addtl string data */
9363                      0,                 /* addtl numeric data 1 */
9364                      0,                 /* addtl numeric data 2 */
9365                      xxstring,
9366                      NULL,
9367                      NULL
9368                      );
9369               while (1) {
9370                   if ((x = cmfdb(&sw)) < 0) {
9371                       if (x == -3) {
9372                           x = -9;
9373                           printf("?Hostname required\n");
9374                       }
9375                       return(x);
9376                   }
9377                   if (cmresult.fcode != _CMKEY)
9378                     break;
9379                   n = cmresult.nresult;
9380                   switch (n) {
9381                     case UPW_USER:
9382                     case UPW_PASS:
9383                       if ((x = cmfld((n == UPW_USER) ? "Username" : "Password",
9384                                      "", &s, xxstring)) < 0) {
9385                           if (x != -3)
9386                             return(x);
9387                       }
9388                       ckstrncpy((n == UPW_USER) ? ubuf : pbuf, s, LOGINLEN+1);
9389                   }
9390               }
9391               if (cmresult.fcode != _CMTXT)
9392                 return(-2);
9393               s = cmresult.sresult;
9394               if (s) if (!*s) s = NULL;
9395
9396 #ifdef IKSDCONF
9397               if (iksdcf)
9398                 return(success = 0);
9399 #endif /* IKSDCONF */
9400               makestr(&tcp_socks_user,ubuf);
9401               memset(pbuf,0,sizeof(pbuf));
9402               makestr(&tcp_socks_svr,s);
9403               return(success = 1);
9404           }
9405
9406 #ifdef CK_SOCKS_NS
9407           case XYTCP_SOCKS_NS: {
9408             char * p = getenv("SOCKS_NS");
9409             if (!p) p = "";
9410             if ((y = cmtxt("hostname or IP of SOCKS Name Server",p,
9411                             &s,xxstring)) < 0)
9412                 return(y);
9413 #ifdef IKSDCONF
9414               if (iksdcf) return(success = 0);
9415 #endif /* IKSDCONF */
9416               if (tcp_socks_ns) {
9417                   free(tcp_socks_ns);   /* Free any previous storage */
9418                   tcp_socks_ns = NULL;
9419               }
9420               if (s == NULL || *s == NUL) { /* If none given */
9421                   tcp_socks_ns = NULL;  /* remove the override string */
9422                   return(success = 1);
9423               } else if ((tcp_socks_ns = malloc(strlen(s)+1))) {
9424                   strcpy(tcp_socks_ns,s);
9425                   return(success = 1);
9426               } else
9427                 return(success = 0);
9428           }
9429 #endif /* CK_SOCKS_NS */
9430 #endif /* CK_SOCKS */
9431 #endif /* NT */
9432           case XYTCP_ADDRESS:
9433             if ((y = cmtxt("preferred IP Address for TCP connections","",
9434                            &s,xxstring)) < 0)
9435               return(y);
9436 #ifdef IKSDCONF
9437             if (iksdcf) return(success = 0);
9438 #endif /* IKSDCONF */
9439             if (tcp_address) {
9440                 free(tcp_address);      /* Free any previous storage */
9441                 tcp_address = NULL;
9442             }
9443             if (s == NULL || *s == NUL) { /* If none given */
9444                 tcp_address = NULL;     /* remove the override string */
9445                 return(success = 1);
9446             } else if ((tcp_address = malloc(strlen(s)+1))) {
9447                 strcpy(tcp_address,s);
9448                 return(success = 1);
9449             } else
9450               return(success = 0);
9451 #ifdef SO_KEEPALIVE
9452           case XYTCP_KEEPALIVE:
9453             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9454             if ((y = cmcfm()) < 0) return(y);
9455 #ifdef IKSDCONF
9456             if (iksdcf) return(success = 0);
9457 #endif /* IKSDCONF */
9458 #ifdef SSHBUILTIN
9459             if (network && nettype == NET_SSH && ssh_sock != -1)
9460               success = keepalive(ssh_sock,z);
9461             else
9462 #endif /* SSHBUILTIN */
9463               success = keepalive(ttyfd,z);
9464             return(success);
9465 #endif /* SO_KEEPALIVE */
9466 #ifdef SO_DONTROUTE
9467           case XYTCP_DONTROUTE:
9468             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
9469             if ((y = cmcfm()) < 0) return(y);
9470 #ifdef IKSDCONF
9471             if (iksdcf) return(success = 0);
9472 #endif /* IKSDCONF */
9473 #ifdef SSHBUILTIN
9474             if (network && nettype == NET_SSH && ssh_sock != -1)
9475               success = dontroute(ssh_sock,z);
9476             else
9477 #endif /* SSHBUILTIN */
9478               success = dontroute(ttyfd,z);
9479             return(success);
9480 #endif /* SO_DONTROUTE */
9481 #ifdef TCP_NODELAY
9482           case XYTCP_NODELAY:
9483             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
9484             if ((y = cmcfm()) < 0) return(y);
9485 #ifdef IKSDCONF
9486             if (iksdcf) return(success = 0);
9487 #endif /* IKSDCONF */
9488 #ifdef SSHBUILTIN
9489             if (network && nettype == NET_SSH && ssh_sock != -1)
9490               success = no_delay(ssh_sock,z);
9491             else
9492 #endif /* SSHBUILTIN */
9493               success = no_delay(ttyfd,z);
9494             return(success);
9495           case XYTCP_NAGLE:             /* The inverse of NODELAY */
9496             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
9497             if ((y = cmcfm()) < 0) return(y);
9498 #ifdef IKSDCONF
9499             if (iksdcf) return(success = 0);
9500 #endif /* IKSDCONF */
9501 #ifdef SSHBUILTIN
9502             if (network && nettype == NET_SSH && ssh_sock != -1)
9503               success = no_delay(ssh_sock,z);
9504             else
9505 #endif /* SSHBUILTIN */
9506               success = no_delay(ttyfd,!z);
9507             return(success);
9508 #endif /* TCP_NODELAY */
9509 #ifdef SO_LINGER
9510           case XYTCP_LINGER:
9511             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0)
9512               return(z);
9513             if (z) {                    /* if on, we need a timeout value */
9514                 if ((x = cmnum("Linger timeout in 10th of a millisecond",
9515                                "0",10,&y,xxstring)) < 0)
9516                   return(x);
9517             } else
9518               y = 0;
9519             if ((x = cmcfm()) < 0)
9520               return(x);
9521 #ifdef IKSDCONF
9522             if (iksdcf) return(success = 0);
9523 #endif /* IKSDCONF */
9524 #ifdef SSHBUILTIN
9525             if (network && nettype == NET_SSH && ssh_sock != -1)
9526               success = ck_linger(ssh_sock,z,y);
9527             else
9528 #endif /* SSHBUILTIN */
9529               success = ck_linger(ttyfd,z,y);
9530             return(success);
9531 #endif /* SO_LINGER */
9532 #ifdef SO_SNDBUF
9533           case XYTCP_SENDBUF:
9534             x = cmnum("Send buffer size, bytes","8192",10,&z,xxstring);
9535             if (x < 0) return(x);
9536             if ((x = cmcfm()) < 0) return(x);
9537 #ifdef IKSDCONF
9538             if (iksdcf) return(success = 0);
9539 #endif /* IKSDCONF */
9540 #ifdef SSHBUILTIN
9541             if (network && nettype == NET_SSH && ssh_sock != -1)
9542               success = sendbuf(ssh_sock,z);
9543             else
9544 #endif /* SSHBUILTIN */
9545               success = sendbuf(ttyfd,z);
9546             return(success);
9547 #endif /* SO_SNDBUF */
9548 #ifdef SO_RCVBUF
9549           case XYTCP_RECVBUF:
9550             x = cmnum("Receive buffer size, bytes","8192",10,&z,xxstring);
9551             if (x < 0) return(x);
9552             if ((x = cmcfm()) < 0) return(x);
9553 #ifdef IKSDCONF
9554             if (iksdcf) return(success = 0);
9555 #endif /* IKSDCONF */
9556
9557 /* Note: The following is not 16-bit safe */
9558
9559 #ifndef QNX16
9560             if (x > 52248) {
9561                 printf("?Warning: receive buffers larger than 52248 bytes\n");
9562                 printf(" may not be understood by all hosts.  Performance\n");
9563                 printf(" may suffer.\n");
9564                 return(-9);
9565             }
9566 #endif /* QNX16 */
9567 #ifdef SSHBUILTIN
9568             if (network && nettype == NET_SSH && ssh_sock != -1)
9569               success = recvbuf(ssh_sock,z);
9570             else
9571 #endif /* SSHBUILTIN */
9572               success = recvbuf(ttyfd,z);
9573             return(success);
9574 #endif /* SO_RCVBUF */
9575
9576 #ifdef VMS
9577 #ifdef DEC_TCPIP
9578           case XYTCP_UCX: {             /* UCX 2.0 port swabbing bug */
9579               extern int ucx_port_bug;
9580               return(success = seton(&ucx_port_bug));
9581           }
9582 #endif /* DEC_TCPIP */
9583 #endif /* VMS */
9584
9585           case XYTCP_RDNS: {
9586               extern int tcp_rdns;
9587               return(success = setonaut(&tcp_rdns));
9588           }
9589
9590 #ifdef CK_DNS_SRV
9591           case XYTCP_DNS_SRV: {
9592               extern int tcp_dns_srv;
9593               return(success = seton(&tcp_dns_srv));
9594           }
9595 #endif /* CK_DNS_SRV */
9596
9597           default:
9598             return(0);
9599         }
9600       }
9601 #endif /* TCPSOCKET */
9602 #endif /* NOTCPOPTS */
9603 #endif /* NETCONN */
9604     }
9605
9606     switch (xx) {
9607
9608 #ifndef NOLOCAL
9609 #ifdef NETCONN
9610       case XYHOST: {                    /* SET HOST */
9611           z = ttnproto;                 /* Save protocol in case of failure */
9612 #ifdef DECNET
9613           if (nettype != NET_DEC)
9614 #endif /* DECNET */
9615             ttnproto = NP_NONE;
9616           if ((y = setlin(XYHOST,1,0)) <= 0) { /* Sets success to 1 */
9617               debug(F101,"SET HOST fail mdmtyp","",mdmtyp);
9618               ttnproto = z;             /* Failed, restore protocol */
9619               success = 0;
9620           }
9621           didsetlin++;
9622           debug(F101,"SET HOST OK mdmtyp","",mdmtyp);
9623           debug(F101,"SET HOST reliable","",reliable);
9624           return(y);
9625       }
9626 #endif /* NETCONN */
9627
9628       case XYLINE:                      /* SET LINE (= SET PORT) */
9629         debug(F101,"setlin flow 1","",flow);
9630         x = setlin(xx,1,0);
9631         if (x > -1) didsetlin++;
9632         debug(F101,"SET LINE setlin","",x);
9633         debug(F101,"SET LINE flow","",flow);
9634         debug(F101,"SET LINE local","",local);
9635         debug(F101,"SET LINE reliable","",reliable);
9636         return(x);
9637 #endif /* NOLOCAL */
9638
9639 #ifndef NOSETKEY
9640       case XYKEY:                       /* SET KEY */
9641         return(dosetkey());
9642 #endif /* NOSETKEY */
9643
9644 #ifndef NOCSETS
9645       case XYLANG:                      /* Language */
9646         if ((y = cmkey(lngtab,nlng,"","none",xxstring)) < 0)
9647           return(y);
9648         if ((x = cmcfm()) < 0) return(x);
9649
9650         /* Look up language and get associated character sets */
9651         for (i = 0; (i < nlangs) && (langs[i].id != y); i++) ;
9652         if (i >= nlangs) {
9653             printf("?internal error, sorry\n");
9654             return(success = 0);
9655         } /*  */
9656         language = i;                   /* All good, set the language, */
9657         return(success = 1);
9658 #endif /* NOCSETS */
9659
9660 #ifndef MAC
9661       case XYBACK:                      /* BACKGROUND */
9662         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
9663         if ((y = cmcfm()) < 0) return(y);
9664 #ifdef COMMENT
9665         bgset = z;                      /* 0 = off (foreground) */
9666 #ifdef VMS                              /* 1 = on (background) */
9667         if (batch && bgset == 0)        /* To enable echoing of commands */
9668           ckxech = 1;                   /* in VMS batch logs */
9669 #endif /* VMS */
9670 #else  /* COMMENT */
9671         if (z) {                        /* 1 = Background */
9672             bgset = 1;
9673             backgrd = 1;
9674 #ifdef VMS
9675             batch = 1;
9676 #endif /* VMS */
9677         } else {                        /* 0 = Foreground */
9678             bgset = 0;
9679             backgrd = 0;
9680 #ifdef VMS
9681             batch = 0;
9682 #endif /* VMS */
9683         }
9684 #endif /* COMMENT */
9685         success = 1;
9686         bgchk();
9687         return(success);
9688 #endif /* MAC */
9689
9690       case XYQUIE: {                    /* QUIET */
9691 #ifdef DCMDBUF
9692           extern int * xquiet;
9693 #else
9694           extern int xquiet[];
9695 #endif /* DCMDBUF */
9696           x = seton(&quiet);
9697           if (x < 0) return(x);
9698           xquiet[cmdlvl] = quiet;
9699           return(success = x);
9700       }
9701
9702 #ifndef NOXFER
9703       case XYBUF: {                     /* BUFFERS */
9704 #ifdef DYNAMIC
9705           int sb, rb;
9706           if ((y = cmnum("Send buffer size","",10,&sb,xxstring)) < 0) {
9707               if (y == -3) printf("?Buffer size required\n");
9708               return(y);
9709           }
9710           if (sb < 0) {
9711               if (*atmbuf == '-')
9712                 printf("?Negative numbers can't be used here\n");
9713               else printf("?Integer overflow, use a smaller number please\n");
9714               return(-9);
9715           } else if (sb < 80) {
9716               printf("?Too small\n");
9717               return(-9);
9718           }
9719           if ((y=cmnum("Receive buffer size",ckitoa(sb),10,&rb,xxstring)) < 0)
9720             return(y);
9721           if (rb < 0) {
9722               if (*atmbuf == '-')
9723                 printf("?Negative numbers can't be used here\n");
9724               else printf("?Integer overflow, use a smaller number please\n");
9725               return(-9);
9726           } else if (rb < 80) {
9727               printf("?Too small\n");
9728               return(-9);
9729           }
9730           if ((y = cmcfm()) < 0) return(y);
9731           if ((y = inibufs(sb,rb)) < 0) return(y);
9732           y = adjpkl(urpsiz,wslotr,bigrbsiz); /* Maybe adjust packet sizes */
9733           if (y != urpsiz) urpsiz = y;
9734           y = adjpkl(spsiz,wslotr,bigsbsiz);
9735           if (y != spsiz) spsiz = spmax = spsizr = y;
9736           return(success = 1);
9737 #else
9738           printf("?Sorry, not available\n");
9739           return(success = 0);
9740 #endif /* DYNAMIC */
9741       }
9742
9743       case XYCHKT:                      /* BLOCK-CHECK */
9744         if ((x = cmkey(chktab,nchkt,"","3",xxstring)) < 0) return(x);
9745         if ((y = cmcfm()) < 0) return(y);
9746         if (x == 5) {
9747             bctf = 1;
9748 #ifdef COMMENT
9749             printf("?5 - Not implemented yet\n");
9750             return(success = 0);
9751 #endif  /* COMMENT */
9752         }
9753         bctr = x;                       /* Set local too even if REMOTE SET */
9754
9755         if (rmsflg) {
9756             if (x == 4) {
9757                 tmpbuf[0] = 'B';
9758                 tmpbuf[1] = '\0';
9759             } else
9760               ckstrncpy(tmpbuf,ckitoa(x),TMPBUFSIZ);
9761             sstate = setgen('S', "400", tmpbuf, "");
9762             return((int) sstate);
9763         } else {
9764             return(success = 1);
9765         }
9766 #endif /* NOXFER */
9767
9768 #ifndef NOLOCAL
9769 #ifndef MAC                             /* The Mac has no RS-232 */
9770 case XYCARR:                            /* CARRIER-WATCH */
9771         return(setdcd());
9772 #endif /* MAC */
9773 #endif /* NOLOCAL */
9774     }
9775
9776 #ifdef TNCODE
9777     switch (xx) {                       /* Avoid long switch statements... */
9778       case XYTELOP: {
9779           int c, n;                     /* Workers */
9780           int getval = 0;               /* Whether to get switch value */
9781           int tnserver = 0;             /* Client by default */
9782           int opt = -1;                 /* Telnet Option */
9783           struct FDB sw, op;            /* FDBs for each parse function */
9784 #ifdef CK_AUTHENTICATION
9785           extern int sl_topt_a_s_saved;
9786           extern int sl_topt_a_c_saved;
9787           extern int sl_topt_e_s_saved;
9788           extern int sl_topt_e_c_saved;
9789 #endif /* CK_AUTHENTICATION */
9790 #ifdef IKSD
9791           if (inserver)                 /* Server by default when IKSD */
9792             tnserver = 1;
9793 #endif /* IKSD */
9794
9795           /* Set up chained parse functions... */
9796
9797           cmfdbi(&op,                   /* First fdb - telopts*/
9798                  _CMKEY,                /* fcode */
9799                  "/client, /server or", /* hlpmsg */
9800                  "",                    /* default */
9801                  "",                    /* addtl string data */
9802                  ntnopt,                /* addtl numeric data 1 */
9803                  0,                     /* addtl numeric data 2 */
9804                  xxstring,
9805                  tnopttab,
9806                  &sw
9807                  );
9808           cmfdbi(&sw,                   /* Second FDB - command switches */
9809                  _CMKEY,                /* fcode */
9810                  "",                    /* hlpmsg */
9811                  "",                    /* default */
9812                  "",                    /* addtl string data */
9813                  ntnoptsw,              /* addtl numeric data 1: tbl size */
9814                  4,                     /* addtl numeric data 2: 4 = cmswi */
9815                  xxstring,              /* Processing function */
9816                  tnoptsw,               /* Keyword table */
9817                  NULL                   /* Pointer to next FDB */
9818                  );
9819
9820           while (opt < 0) {             /* Parse 0 or more switches */
9821               x = cmfdb(&op);           /* Parse switch or other thing */
9822               debug(F101,"XYTELOP cmfdb","",x);
9823               if (x < 0)                /* Error */
9824                 return(x);              /* or reparse needed */
9825               if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
9826                 break;
9827               c = cmgbrk();             /* Get break character */
9828               getval = (c == ':' || c == '='); /* see how switch ended */
9829               if (getval && !(cmresult.kflags & CM_ARG)) {
9830                   printf("?This switch does not take arguments\n");
9831                   return(-9);
9832               }
9833               z = cmresult.nresult;     /* Numeric result = switch value */
9834               debug(F101,"XYTELOP switch","",z);
9835
9836               switch (z) {              /* Process the switch */
9837                 case CK_TN_CLIENT:
9838                   tnserver = 0;
9839                   break;
9840                 case CK_TN_SERVER:
9841                   tnserver = 1;
9842                     break;
9843                 case CK_TN_EC:
9844                   opt = TELOPT_ECHO;
9845                   break;
9846                 case CK_TN_TT:
9847                   opt = TELOPT_TTYPE;
9848                   break;
9849                 case CK_TN_BM:
9850                   opt = TELOPT_BINARY;
9851                   break;
9852                 case CK_TN_ENV:
9853                   opt = TELOPT_NEWENVIRON;
9854                   break;
9855                 case CK_TN_LOC:
9856                   opt = TELOPT_SNDLOC;
9857                   break;
9858                 case CK_TN_AU:
9859                   opt = TELOPT_AUTHENTICATION;
9860                   break;
9861                 case CK_TN_FX:
9862                   opt = TELOPT_FORWARD_X;
9863                   break;
9864                 case CK_TN_ENC:
9865                   opt = TELOPT_ENCRYPTION;
9866                   break;
9867                 case CK_TN_IKS:
9868                   opt = TELOPT_KERMIT;
9869                   break;
9870                 case CK_TN_TLS:
9871                   opt = TELOPT_START_TLS;
9872                   break;
9873                 case CK_TN_XD:
9874                   opt = TELOPT_XDISPLOC;
9875                   break;
9876                 case CK_TN_NAWS:
9877                   opt = TELOPT_NAWS;
9878                   break;
9879                 case CK_TN_SGA:
9880                   opt = TELOPT_SGA;
9881                   break;
9882                 case CK_TN_PHR:
9883                   opt = TELOPT_PRAGMA_HEARTBEAT;
9884                   break;
9885                 case CK_TN_PSP:
9886                   opt = TELOPT_SSPI_LOGON;
9887                   break;
9888                 case CK_TN_PLG:
9889                   opt = TELOPT_PRAGMA_LOGON;
9890                   break;
9891                 case CK_TN_SAK:
9892                   opt = TELOPT_IBM_SAK;
9893                   break;
9894                 case CK_TN_CPC:
9895                   opt = TELOPT_COMPORT;
9896                   break;
9897                 case CK_TN_LOG:
9898                   opt = TELOPT_LOGOUT;
9899                   break;
9900                 case CK_TN_FLW:
9901                   opt = TELOPT_LFLOW;
9902                   break;
9903                 default:
9904                   printf("?Unexpected value - %d\n",z);
9905                   return(-9);
9906               }
9907 #ifdef COMMENT
9908               if (cmresult.fdbaddr == &op)
9909                 break;
9910 #endif /* COMMENT */
9911           }
9912           switch (opt) {
9913             case TELOPT_ECHO:           /* Options only the Server WILL */
9914             case TELOPT_FORWARD_X:
9915             case TELOPT_SEND_URL:
9916             case TELOPT_IBM_SAK:
9917             case TELOPT_LOGOUT:
9918               if ((x = cmkey(tnnegtab,
9919                              ntnnegtab,
9920                              "desired server state",
9921    TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
9922                              xxstring)
9923                    ) < 0)
9924                 return(x);
9925               if ((z = cmcfm()) < 0)
9926                   return(z);
9927               if (tnserver) {
9928                   TELOPT_DEF_S_ME_MODE(opt) = x;
9929                   TELOPT_ME_MODE(opt) = x;
9930               } else {
9931                   TELOPT_DEF_C_U_MODE(opt) = x;
9932                   TELOPT_U_MODE(opt) = x;
9933               }
9934               break;
9935
9936             case TELOPT_TTYPE:          /* Options only the Client WILL */
9937             case TELOPT_NEWENVIRON:
9938             case TELOPT_SNDLOC:
9939             case TELOPT_AUTHENTICATION:
9940             case TELOPT_START_TLS:
9941             case TELOPT_XDISPLOC:
9942             case TELOPT_NAWS:
9943             case TELOPT_LFLOW:
9944             case TELOPT_COMPORT:
9945               if ((x = cmkey(tnnegtab,
9946                              ntnnegtab,
9947                              "desired client state",
9948     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
9949                              xxstring)
9950                    ) < 0)
9951                 return(x);
9952               if ((z = cmcfm()) < 0)
9953                 return(z);
9954               if (tnserver) {
9955                   TELOPT_DEF_S_U_MODE(opt) = x;
9956                   TELOPT_U_MODE(opt) = x;
9957 #ifdef CK_AUTHENTICATION
9958                   if (opt == TELOPT_AUTHENTICATION)
9959                     sl_topt_a_s_saved = 0;
9960 #endif /* CK_AUTHENTICATION */
9961               } else {
9962                   TELOPT_DEF_C_ME_MODE(opt) = x;
9963                   TELOPT_ME_MODE(opt) = x;
9964 #ifdef CK_AUTHENTICATION
9965                   if (opt == TELOPT_AUTHENTICATION)
9966                     sl_topt_a_c_saved = 0;
9967 #endif /* CK_AUTHENTICATION */
9968               }
9969               break;
9970
9971             default:
9972               if ((x = cmkey(tnnegtab,
9973                              ntnnegtab,
9974                              tnserver ?
9975                              "desired server state" :
9976                              "desired client state",
9977     TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
9978                              xxstring
9979                              )
9980                    ) < 0)
9981                 return(x);
9982               if ((y = cmkey(tnnegtab,
9983                              ntnnegtab,
9984                              !tnserver ? "desired server state" :
9985                              "desired client state",
9986     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
9987                              xxstring
9988                              )
9989                    ) < 0)
9990                 return(y);
9991               if ((z = cmcfm()) < 0)
9992                 return(z);
9993               if (tnserver) {
9994                   TELOPT_DEF_S_ME_MODE(opt) = x;
9995                   TELOPT_ME_MODE(opt) = x;
9996                   TELOPT_DEF_S_U_MODE(opt) = y;
9997                   TELOPT_U_MODE(opt) = y;
9998 #ifdef CK_ENCRYPTION
9999                   if (opt == TELOPT_ENCRYPTION)
10000                     sl_topt_e_s_saved = 0;
10001 #endif /* CK_ENCRYPTION */
10002               } else {
10003                   TELOPT_DEF_C_ME_MODE(opt) = x;
10004                   TELOPT_ME_MODE(opt) = x;
10005                   TELOPT_DEF_C_U_MODE(opt) = y;
10006                   TELOPT_U_MODE(opt) = y;
10007 #ifdef CK_ENCRYPTION
10008                   if (opt == TELOPT_ENCRYPTION)
10009                     sl_topt_e_c_saved = 0;
10010 #endif /* CK_ENCRYPTION */
10011               }
10012           }
10013           return(success = 1);
10014       }
10015
10016       case XYTEL:                       /* TELNET */
10017         if ((z = cmkey(tntab,ntn,"parameter for TELNET negotiations", "",
10018                        xxstring)) < 0)
10019           return(z);
10020         switch (z) {
10021           case CK_TN_EC:                /* ECHO */
10022             if ((x = cmkey(rltab,nrlt,
10023                            "initial TELNET echoing state",
10024                            "local",xxstring)) < 0)
10025               return(x);
10026             if ((y = cmcfm()) < 0) return(y);
10027             tn_duplex = x;
10028             return(success = 1);
10029
10030           case CK_TN_RE:                /* REMOTE-ECHO */
10031             return(success = seton(&tn_rem_echo));
10032
10033           case CK_TN_DB:                /* DEBUG */
10034             return(success = seton(&tn_deb));
10035
10036           case CK_TN_TT:                /* TERMINAL TYPE */
10037             if ((y = cmtxt("terminal type for TELNET connections","",
10038                            &s,xxstring)) < 0)
10039               return(y);
10040             if (tn_term) {
10041                 free(tn_term);          /* Free any previous storage */
10042                 tn_term = NULL;
10043             }
10044             if (s == NULL || *s == NUL) { /* If none given */
10045                 tn_term = NULL;         /* remove the override string */
10046                 return(success = 1);
10047             } else if ((tn_term = malloc(strlen(s)+1))) {
10048                 strcpy(tn_term,s);
10049                 return(success = 1);
10050             } else return(success = 0);
10051
10052 #ifdef CK_FORWARD_X
10053           case CK_TN_FX:                /* FORWARD-X */
10054             if ((x=cmkey(tnfwdxtab,ntnfwdx,"","xauthority-file",xxstring)) < 0)
10055               return(x);
10056             switch (x) {
10057               case 0: {                 /* Xauthority-File */
10058                   x = cmifi("Full path of .Xauthority file","",&s,&y,xxstring);
10059                   if (x < 0 && x != -3)
10060                     return(x);
10061                   makestr(&tn_fwdx_xauthority,s);
10062                   return(success = 1);
10063               }
10064               case 1: {                 /* No-Encryption */
10065                   extern int fwdx_no_encrypt;
10066                   return(success = seton(&fwdx_no_encrypt));
10067               }
10068             }
10069             return(success = 0);
10070 #endif /* CK_FORWARD_X */
10071
10072           case CK_TN_NL:                /* TELNET NEWLINE-MODE */
10073             if ((x = cmkey(tn_nlmtab,ntn_nlm,"","nvt",xxstring)) < 0)
10074               return(x);
10075             if (x == TN_NL_BIN) {
10076               if ((x = cmkey(tnlmtab,ntnlm,"","raw",xxstring)) < 0)
10077                 return(x);
10078               if ((y = cmcfm()) < 0)
10079                 return(y);
10080               tn_b_nlm = x;
10081               return(success = 1);
10082           } else if (x == TN_NL_NVT) {
10083               if ((x = cmkey(tnlmtab,ntnlm,"","on",xxstring)) < 0)
10084                 return(x);
10085               if ((y = cmcfm()) < 0)
10086                 return(y);
10087               tn_nlm = x;
10088               return(success = 1);
10089           } else {
10090               if ((y = cmcfm()) < 0)
10091                 return(y);
10092               tn_nlm = x;
10093               return(success = 1);
10094           }
10095
10096         case CK_TN_XF:                  /* BINARY-TRANSFER-MODE */
10097             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10098             if ((y = cmcfm()) < 0) return(y);
10099             tn_b_xfer = z;
10100             return(success = 1);
10101
10102         case CK_TN_NE:                  /* NO-ENCRYPT-DURING-XFER */
10103             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10104             if ((y = cmcfm()) < 0) return(y);
10105 #ifdef CK_APC
10106             /* Don't let this be set remotely */
10107             if (apcactive == APC_LOCAL ||
10108                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
10109               return(success = 0);
10110 #endif /* CK_APC */
10111             tn_no_encrypt_xfer = z;
10112             return(success = 1);
10113
10114           case CK_TN_BM:                /* BINARY-MODE */
10115             if ((x = cmkey(tnnegtab,ntnnegtab,"","refused",xxstring)) < 0)
10116               return(x);
10117             if ((y = cmcfm()) < 0)
10118               return(y);
10119             TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = x;
10120             TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = x;
10121             TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = x;
10122             TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = x;
10123             return(success = 1);
10124
10125 #ifdef IKS_OPTION
10126           case CK_TN_IKS:               /* KERMIT */
10127             if ((x = cmkey(tnnegtab,ntnnegtab,"DO","accept",xxstring)) < 0)
10128               return(x);
10129             if ((y = cmkey(tnnegtab,ntnnegtab,"WILL","accept",xxstring)) < 0)
10130               return(y);
10131             if ((z = cmcfm()) < 0)
10132               return(z);
10133             TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = y;
10134             TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = x;
10135             TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = y;
10136             TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = x;
10137             return(success = 1);
10138 #endif /* IKS_OPTION */
10139
10140 #ifdef CK_SSL
10141           case CK_TN_TLS:               /* START_TLS */
10142             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10143               return(x);
10144             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10145               return(y);
10146             if ((z = cmcfm()) < 0)
10147               return(z);
10148             TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = x;
10149             TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = y;
10150             TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = x;
10151             TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = y;
10152             return(success = 1);
10153 #endif /* CK_SSL */
10154
10155 #ifdef CK_NAWS
10156           case CK_TN_NAWS:              /* NAWS */
10157             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10158               return(x);
10159             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10160               return(y);
10161             if ((z = cmcfm()) < 0)
10162               return(z);
10163             TELOPT_DEF_S_ME_MODE(TELOPT_NAWS) = x;
10164             TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = y;
10165             TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = x;
10166             TELOPT_DEF_C_U_MODE(TELOPT_NAWS) = y;
10167             return(success = 1);
10168 #endif /* CK_NAWS */
10169
10170 #ifdef CK_AUTHENTICATION
10171           case CK_TN_AU:                /* AUTHENTICATION */
10172             if ((x = cmkey(tnauthtab,ntnauth,"","",xxstring)) < 0)
10173               return(x);
10174             if (x == TN_AU_FWD) {
10175                 extern int forward_flag;
10176                 return(success = seton(&forward_flag));
10177             } else if (x == TN_AU_TYP) {
10178                 extern int auth_type_user[];
10179                 extern int sl_auth_type_user[];
10180                 extern int sl_auth_saved;
10181                 int i, j, atypes[AUTHTYPLSTSZ];
10182
10183                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
10184                     if ((y = cmkey(autyptab,nautyp,"",
10185                                    i == 0 ? "automatic" : "" ,
10186                                    xxstring)) < 0) {
10187                         if (y == -3)
10188                           break;
10189                         return(y);
10190                     }
10191                     if (i > 0 && (y == AUTHTYPE_AUTO || y == AUTHTYPE_NULL)) {
10192                         printf(
10193                         "\r\n?Choice may only be used in first position.\r\n");
10194                         return(-9);
10195                     }
10196                     for (j = 0; j < i; j++) {
10197                         if (atypes[j] == y) {
10198                             printf("\r\n?Choice has already been used.\r\n");
10199                             return(-9);
10200                         }
10201                     }
10202                     atypes[i] = y;
10203                     if (y == AUTHTYPE_NULL || y == AUTHTYPE_AUTO) {
10204                         i++;
10205                         break;
10206                     }
10207                 }
10208                 if (i < AUTHTYPLSTSZ)
10209                   atypes[i] = AUTHTYPE_NULL;
10210                 if ((z = cmcfm()) < 0)
10211                   return(z);
10212                 sl_auth_saved = 0;
10213                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
10214                     auth_type_user[i] = atypes[i];
10215                     sl_auth_type_user[i] = 0;
10216                 }
10217             } else if (x == TN_AU_HOW) {
10218                 if ((y = cmkey(auhowtab,nauhow,"","any",xxstring)) < 0)
10219                   return(y);
10220                 if ((z = cmcfm()) < 0)
10221                   return(z);
10222                 tn_auth_how = y;
10223             } else if (x == TN_AU_ENC) {
10224                 if ((y = cmkey(auenctab,nauenc,"","encrypt",xxstring)) < 0)
10225                   return(y);
10226                 if ((z = cmcfm()) < 0)
10227                   return(z);
10228                 tn_auth_enc = y;
10229             } else {
10230                 if ((y = cmcfm()) < 0)
10231                   return(y);
10232                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = x;
10233                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = x;
10234             }
10235             return(success = 1);
10236 #endif /* CK_AUTHENTICATION */
10237
10238 #ifdef CK_ENCRYPTION
10239           case CK_TN_ENC: {             /* ENCRYPTION */
10240               int c, tmp = -1;
10241               int getval = 0;
10242               static struct keytab * tnetbl = NULL;
10243               static int ntnetbl = 0;
10244
10245               if ((y = cmkey(tnenctab,ntnenc,"","",xxstring)) < 0)
10246                 return(y);
10247               switch (y) {
10248                 case TN_EN_TYP:
10249                   x = ck_get_crypt_table(&tnetbl,&ntnetbl);
10250                   debug(F101,"ck_get_crypt_table x","",x);
10251                   debug(F101,"ck_get_crypt_table n","",ntnetbl);
10252                   if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
10253                     x = 0;
10254                   if (!x) {
10255                       printf("?Oops, types not loaded\n");
10256                       return(-9);
10257                   }
10258                   if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
10259                                  "automatic",xxstring)) < 0)
10260                     return(x);
10261                   if ((z = cmcfm()) < 0)
10262                     return(z);
10263                   cx_type = x;
10264                   sl_cx_type = 0;
10265                   break;
10266                 case TN_EN_START:
10267                   if ((z = cmcfm()) < 0)
10268                     return(z);
10269 #ifdef CK_APC
10270                   /* Don't let this be set remotely */
10271                   if (apcactive == APC_LOCAL ||
10272                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10273                     return(success = 0);
10274 #endif /* CK_APC */
10275                   ck_tn_enc_start();
10276                   break;
10277                 case TN_EN_STOP:
10278                   if ((z = cmcfm()) < 0)
10279                     return(z);
10280 #ifdef CK_APC
10281                   /* Don't let this be set remotely */
10282                   if (apcactive == APC_LOCAL ||
10283                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
10284                     return(success = 0);
10285 #endif /* CK_APC */
10286                   ck_tn_enc_stop();
10287                   break;
10288                 default:
10289                   if ((z = cmcfm()) < 0)
10290                     return(z);
10291                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = y;
10292                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = y;
10293                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = y;
10294                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = y;
10295               }
10296               return(success = 1);
10297           }
10298 #endif /* CK_ENCRYPTION */
10299
10300           case CK_TN_BUG:               /* BUG */
10301             if ((x = cmkey(tnbugtab,4,"",
10302                            "binary-me-means-u-too",xxstring)) < 0)
10303               return(x);
10304             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
10305             if ((y = cmcfm()) < 0) return(y);
10306             switch (x) {
10307               case 0:
10308                 tn_b_meu = z;
10309                 break;
10310               case 1:
10311                 tn_b_ume = z;
10312                 break;
10313               case 2:
10314                 tn_infinite = z;
10315                 break;
10316               case 3:
10317                 tn_sb_bug = z;
10318                 break;
10319               case 4:
10320                 tn_auth_krb5_des_bug = z;
10321                 break;
10322             }
10323             return(success = 1);
10324
10325 #ifdef CK_ENVIRONMENT
10326           case CK_TN_XD:                /* XDISPLOC */
10327             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
10328               return(x);
10329             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
10330               return(y);
10331             if ((z = cmcfm()) < 0)
10332               return(z);
10333             TELOPT_DEF_S_ME_MODE(TELOPT_XDISPLOC) = x;
10334             TELOPT_DEF_S_U_MODE(TELOPT_XDISPLOC) = y;
10335             TELOPT_DEF_C_ME_MODE(TELOPT_XDISPLOC) = x;
10336             TELOPT_DEF_C_U_MODE(TELOPT_XDISPLOC) = y;
10337             return(success = 1);
10338
10339           case CK_TN_ENV: {
10340               char * msg = "value of telnet environment variable";
10341               extern int tn_env_flg;
10342               extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
10343               tn_env_prnt[], tn_env_sys[];
10344               extern char * tn_loc;
10345               if ((x = cmkey(tnenvtab,ntnenv,"","",xxstring)) < 0)
10346                 return(x);
10347               if (x == TN_ENV_UVAR) {   /* User variables */
10348                   char * uvar=NULL;
10349                   char * uval=NULL;
10350                   char * env;
10351                   extern char * tn_env_uservar[8][2];
10352
10353                   /* Get the user variable name */
10354                   if ((x = cmfld("Name of Environment Variable","",&s,
10355                                  xxstring)) < 0)
10356                     return(x);
10357                   makestr(&uvar,s);
10358
10359                   env = getenv(uvar);
10360                   if (!env) env = "";
10361
10362                   if ((x = cmtxt("Value of Environment Variable",env,
10363                                  &s,xxstring)) < 0)
10364                     return(x);
10365                   if (*s)
10366                     makestr(&uval,s);
10367
10368                   /* Now that we have the variable and perhaps a value */
10369                   /* there are three possibilities: (1) new variable   */
10370                   /* and associated value; (2) variable already exists */
10371                   /* but we have a new value; (3) variable already     */
10372                   /* exists but no new value therefore the user wants  */
10373                   /* to clear variable.                                */
10374
10375                   /* Try to find an existing variable */
10376                   for (x = 0; x < 8; x++) {
10377                       if (!ckstrcmp(tn_env_uservar[x][0],uvar,-1,0)) {
10378                           if (uval) {
10379                               free(tn_env_uservar[x][1]);
10380                               tn_env_uservar[x][1] = uval;
10381                               free(uvar);
10382                               return(success = 1);
10383                           } else {
10384                               free(tn_env_uservar[x][0]);
10385                               tn_env_uservar[x][0] = NULL;
10386                               free(tn_env_uservar[x][1]);
10387                               tn_env_uservar[x][1] = NULL;
10388                               free(uvar);
10389                               return(success = 1);
10390                           }
10391                       }
10392                   }
10393
10394                   /* Couldn't find one; look for empty location to insert */
10395                   for (x = 0; x < 8; x++) {
10396                       if (!tn_env_uservar[x][0]) {
10397                           tn_env_uservar[x][0] = uvar;
10398                           tn_env_uservar[x][1] = uval;
10399                           return(success = 1);
10400                       }
10401                   }
10402                   printf("?Sorry, no space for variable.\n");
10403                   return(success = 0);
10404               }
10405               if (x == TN_ENV_OFF || x == TN_ENV_ON) {
10406                   if ((y = cmcfm()) < 0) return(y);
10407 #ifdef IKSD
10408                   if (inserver) {
10409                       printf("?Sorry, command disabled.\r\n");
10410                       return(success = 0);
10411                   }
10412 #endif /* IKSD */
10413                   tn_env_flg = x == TN_ENV_OFF ? 0 : 1;
10414                   return(success = 1);
10415               }
10416
10417               /* Not ON/OFF - Get the value */
10418               z = cmdgquo();
10419               cmdsquo(0);
10420               if ((y = cmtxt(msg, "", &s, xxstring)) < 0) {
10421                   cmdsquo(z);
10422                   return(y);
10423               }
10424               cmdsquo(z);
10425 #ifdef IKSD
10426               if (inserver)
10427                 return(success = 0);
10428 #endif /* IKSD */
10429               if ((int)strlen(s) > 63) {
10430                   printf("Sorry, too long\n");
10431                   return(-9);
10432               }
10433               switch (x) {
10434                 case TN_ENV_USR:
10435                   ckstrncpy(uidbuf,s,UIDBUFLEN);
10436                   sl_uid_saved = 0;
10437                   break;
10438                 case TN_ENV_ACCT:
10439                   ckstrncpy(tn_env_acct,s,64);
10440                   break;
10441                 case TN_ENV_DISP:
10442                   ckstrncpy(tn_env_disp,s,64);
10443                   break;
10444                 case TN_ENV_JOB:
10445                   ckstrncpy(tn_env_job,s,64);
10446                   break;
10447                 case TN_ENV_PRNT:
10448                   ckstrncpy(tn_env_prnt,s,64);
10449                   break;
10450                 case TN_ENV_SYS:
10451                   ckstrncpy(tn_env_sys,s,64);
10452                   break;
10453                 case TN_ENV_LOC:
10454                   if (!*s) s = NULL;
10455                   makestr(&tn_loc,s);
10456                   break;
10457                 case TN_ENV_UVAR:
10458                   printf("\n?Not yet implemented\n");
10459                   break;
10460               }
10461               return(success = 1);
10462           }
10463 #endif /* CK_ENVIRONMENT */
10464
10465 #ifdef CK_SNDLOC
10466           case CK_TN_LOC: {             /* LOCATION */
10467               extern char * tn_loc;
10468               if ((y = cmtxt("Location string","",&s,xxstring)) < 0)
10469                 return(y);
10470               if (!*s) s = NULL;
10471               makestr(&tn_loc,s);
10472               return(success = 1);
10473           }
10474 #endif /* CK_SNDLOC */
10475           case CK_TN_SFU:               /* Microsoft SFU compatibility */
10476             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10477             if ((y = cmcfm()) < 0) return(y);
10478             tn_sfu = z;
10479             return(success = 1);
10480             break;
10481
10482           case CK_TN_WAIT:              /* WAIT-FOR-NEGOTIATIONS */
10483             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10484             if ((y = cmcfm()) < 0) return(y);
10485 #ifdef IKSD
10486             if (inserver &&
10487 #ifdef IKSDCONF
10488                 iksdcf
10489 #else
10490                 1
10491 #endif /* IKSDCONF */
10492                 ) {
10493                 printf("?Sorry, command disabled.\r\n");
10494                 return(success = 0);
10495             }
10496 #endif /* IKSD */
10497             tn_wait_flg = z;
10498             sl_tn_saved = 0;
10499             return(success = 1);
10500
10501           case CK_TN_DL:                /* DELAY SUBNEGOTIATIONS */
10502             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
10503             if ((y = cmcfm()) < 0) return(y);
10504 #ifdef IKSD
10505             if (inserver &&
10506 #ifdef IKSDCONF
10507                 iksdcf
10508 #else
10509                 1
10510 #endif /* IKSDCONF */
10511                 ) {
10512                 printf("?Sorry, command disabled.\r\n");
10513                 return(success = 0);
10514             }
10515 #endif /* IKSD */
10516             tn_delay_sb = z;
10517             return(success = 1);
10518
10519           case CK_TN_PUID: {            /* PROMPT-FOR-USERID */
10520               int i,len;
10521               if ((y = cmtxt("Prompt string","",&s,xxstring)) < 0)
10522                 return(y);
10523               s = brstrip(s);
10524               /* we must check to make sure there are no % fields */
10525               len = strlen(s);
10526               for (i = 0; i < len; i++) {
10527                   if (s[i] == '%') {
10528                       if (s[i+1] != '%') {
10529                           printf("%% fields are not used in this command.\n");
10530                           return(-9);
10531                       }
10532                       i++;
10533                   }
10534               }
10535               makestr(&tn_pr_uid,s);
10536               return(success = 1);
10537           }
10538           default:
10539             return(-2);
10540         }
10541     }
10542 #endif /* TNCODE */
10543
10544     switch (xx) {
10545 #ifndef NOSPL
10546       case XYCOUN:                      /* SET COUNT */
10547         x = cmnum("Positive number","0",10,&z,xxstring);
10548         if (x < 0) return(x);
10549         if ((x = cmcfm()) < 0) return(x);
10550         if (z < 0) {
10551             printf("?A positive number, please\n");
10552             return(0);
10553         }
10554         debug(F101,"XYCOUN: z","",z);
10555         return(success = setnum(&count[cmdlvl],z,0,10000));
10556 #endif /* NOSPL */
10557
10558 #ifndef NOSPL
10559       case XYCASE:
10560         return(success = seton(&inpcas[cmdlvl]));
10561 #endif /* NOSPL */
10562
10563       case XYCMD:                       /* COMMAND ... */
10564         if ((y = cmkey(scmdtab,nbytt,"","",xxstring)) < 0)
10565           return(y);
10566         switch (y) {
10567           case SCMD_CBR:
10568             if ((y = cmcfm()) < 0)
10569               return(y);
10570             concb((char)escape);
10571             return(success = 1);
10572
10573           case SCMD_BSZ:
10574             if ((y = cmnum("bytesize for command characters, 7 or 8","7",10,&x,
10575                            xxstring)) < 0)
10576               return(y);
10577             if (x != 7 && x != 8) {
10578                 printf("\n?The choices are 7 and 8\n");
10579                 return(success = 0);
10580             }
10581             if ((y = cmcfm()) < 0) return(y);
10582             if (x == 7) cmdmsk = 0177;
10583             else if (x == 8) cmdmsk = 0377;
10584             return(success = 1);
10585 #ifdef CK_RECALL
10586           case SCMD_RCL:
10587             if ((y = cmnum("maximum number of commands in recall buffer","10",
10588                            10,&x,xxstring)) < 0)
10589               return(y);
10590             if ((y = cmcfm()) < 0) return(y);
10591             return(success = cmrini(x));
10592 #endif /* CK_RECALL */
10593 #ifdef CK_RECALL
10594           case SCMD_RTR:
10595             return(success = seton(&cm_retry));
10596 #endif /* CK_RECALL */
10597           case SCMD_MOR:                /* More-prompting */
10598             success = seton(&xaskmore);
10599             if (success)
10600               saveask = xaskmore;
10601             return(success);
10602           case SCMD_QUO:
10603             if ((x = seton(&y)) < 0) return(x);
10604             cmdsquo(y);                 /* Do it the right way */
10605             cmd_quoting = y;            /* Also keep a global copy */
10606             /* Set string-processing function */
10607 #ifdef datageneral
10608             xxstring = y ? zzstring : (xx_strp) NULL;
10609 #else
10610 #ifdef CK_ANSIC
10611             xxstring = y ? zzstring : (xx_strp) NULL;
10612 #else
10613             xxstring = y ? zzstring : (xx_strp) NULL;
10614 #endif /* CK_ANSIC */
10615 #endif /* datageneral */
10616             return(success = 1);
10617
10618 #ifdef OS2
10619 #ifndef NOLOCAL
10620           case SCMD_COL: {              /* Command-screen colors */
10621               int fg, bg;
10622               fg = cmkey(ttyclrtab, nclrs,
10623                          "foreground color and then background color",
10624                          "white",
10625                          xxstring);
10626               if (fg < 0)
10627                 return(fg);
10628               if ((bg = cmkey(ttyclrtab,nclrs,
10629                               "background color","black",xxstring)) < 0)
10630                 return(bg);
10631               if ((y = cmcfm()) < 0)
10632                 return(y);
10633               colorcmd = fg | bg << 4;
10634               return(success = 1);
10635           }
10636           case SCMD_SCR:                /* Command Scrollback size */
10637             if ((y = cmnum("COMMAND scrollback buffer size, lines","512",10,&x,
10638                            xxstring)) < 0)
10639               return(y);
10640             /* The max number of lines is the RAM  */
10641             /* we can actually dedicate to a       */
10642             /* scrollback buffer given the maximum */
10643             /* process memory space of 512MB       */
10644             if (x < 256 || x > 2000000L) {
10645                 printf("\n?The size must be between 256 and 2,000,000.\n");
10646                 return(success = 0);
10647             }
10648             if ((y = cmcfm()) < 0) return(y);
10649             tt_scrsize[VCMD] = x;
10650             VscrnInit( VCMD );
10651             return(success = 1);
10652
10653           case SCMD_WID: {
10654               if ((y = cmnum("Number of columns in display window",
10655                          "80",10,&x,xxstring)) < 0)
10656                 return(y);
10657               if ((y = cmcfm()) < 0) return(y);
10658
10659               os2_setcmdwidth(x);
10660               return(success = 1);
10661           }
10662           case SCMD_HIG:
10663             if ((y = cmnum("Number of rows in display window",
10664                            "24",10,&x,xxstring)) < 0)
10665               return(y);
10666             if ((y = cmcfm()) < 0) return(y);
10667             os2_setcmdheight(x);
10668             return(success = 1);
10669
10670           case SCMD_STA: {
10671               extern int marginbot;
10672               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
10673               if ((x = cmcfm()) < 0) return(x);
10674               if (y != tt_status[VCMD]) {
10675                   /* Might need to fixup the margins */
10676                   tt_status[VCMD] = y;
10677                   if (y) {
10678                       tt_szchng[VCMD] = 2;
10679                       tt_rows[VCMD]--;
10680                       cmd_rows--;
10681                       VscrnInit(VCMD);  /* Height set here */
10682                       printf("\n");
10683                   } else {
10684                       tt_szchng[VCMD] = 1;
10685                       tt_rows[VCMD]++;
10686                       cmd_rows++;
10687                       VscrnInit(VCMD);  /* Height set here */
10688                   }
10689               }
10690               return(success = 1);
10691           }
10692
10693           case SCMD_CUR: {
10694               int row, col;
10695               position * ppos;
10696
10697               ppos = VscrnGetCurPos(VCMD);
10698 #ifdef NT
10699 #define itoa _itoa
10700 #endif /* NT */
10701               itoa(ppos->y+1, tmpbuf, 10);
10702               if ((y = cmnum("row (1-based)",tmpbuf,10,&row,xxstring)) < 0)
10703                 return(y);
10704
10705               itoa(ppos->x+1, tmpbuf, 10);
10706               if ((y = cmnum("col (1-based)",tmpbuf,10,&col,xxstring)) < 0)
10707                 return(y);
10708               if ((x = cmcfm()) < 0) return(x);
10709
10710               lgotoxy( VCMD, col, row ) ;
10711               VscrnIsDirty( VCMD );
10712               return(success=1);
10713           }
10714 #endif /* NOLOCAL */
10715 #else
10716           case SCMD_WID:
10717             y = cmnum("Command screen width, characters","80",10,&x,xxstring);
10718             return(setnum(&cmd_cols,x,y,1024));
10719
10720           case SCMD_HIG:
10721             y = cmnum("Command screen height, rows","24",10,&x,xxstring);
10722             return(setnum(&cmd_rows,x,y,1024));
10723 #endif /* OS2 */
10724
10725           case SCMD_INT:
10726             return(seton(&cmdint));
10727
10728 #ifdef CK_AUTODL
10729           case SCMD_ADL:
10730             return(seton(&cmdadl));
10731 #endif /* CK_AUTODL */
10732
10733 #ifdef DOUBLEQUOTING
10734           case SCMD_DBQ: {
10735               extern int dblquo;
10736               return(seton(&dblquo));
10737           }
10738 #endif /* DOUBLEQUOTING */
10739
10740           case SCMD_ERR:
10741             y = cmnum("Error message verbosity level, 0-3","1",10,&x,xxstring);
10742             return(setnum(&cmd_err,x,y,3));
10743
10744           case SCMD_VAR:
10745             return(setvareval());
10746
10747           default:
10748             return(-2);
10749         }
10750     }
10751
10752     switch (xx) {
10753
10754       case XYDFLT:                      /* SET DEFAULT = CD */
10755         return(success = docd(XXCWD));
10756
10757 case XYDEBU:                            /* SET DEBUG { on, off, session } */
10758         if ((y = cmkey(dbgtab,ndbg,"","",xxstring)) < 0)
10759           return(y);
10760         if (y == DEB_TIM)
10761 #ifdef COMMENT
10762           return(seton(&debtim) < 0 ? x : (success = 1));
10763 #else
10764           /* why this change? */
10765           return(success = seton(&debtim));
10766 #endif /* COMMENT */
10767
10768 #ifdef IKSD
10769         if (inserver && isguest) {
10770             printf("?Sorry, command disabled.\r\n");
10771             return(success = 0);
10772     }
10773 #endif /* IKSD */
10774
10775         switch (y) {
10776           case DEB_LEN:
10777             y = cmnum("Max length for debug log strings","",10,&x,xxstring);
10778             if ((z = setnum(&debxlen,x,y,-1)) < 0)
10779               return(z);
10780             if ((x = cmcfm()) < 0)
10781               return(x);
10782             return(success = 1);
10783
10784           case DEB_OFF:
10785             if ((x = cmcfm()) < 0)
10786               return(x);
10787 #ifndef NOLOCAL
10788             setdebses(0);
10789 #endif /* NOLOCAL */
10790 #ifdef DEBUG
10791             if (deblog) doclslog(LOGD);
10792 #endif /* DEBUG */
10793             return(success = 1);
10794
10795           case DEB_ON:
10796             if ((x = cmcfm()) < 0)
10797               return(x);
10798 #ifdef DEBUG
10799             deblog = debopn("debug.log", 0);
10800             return(success = deblog ? 1 : 0);
10801 #else
10802             printf("?Sorry, debug log feature not enabled\n");
10803             return(success = 0);
10804 #endif /* DEBUG */
10805           case DEB_SES:
10806             if ((x = cmcfm()) < 0)
10807               return(x);
10808 #ifndef NOLOCAL
10809             setdebses(1);
10810 #endif /* NOLOCAL */
10811             return(success = 1);
10812
10813           case DEB_MSG:                 /* Debug messages 2010/03/12 */
10814             if ((y = cmkey(ooetab,nooetab,"","on",xxstring)) < 0) return(y);
10815             if ((x = cmcfm()) < 0) return(x);
10816             debmsg = y;
10817             return(1);
10818         }
10819         break;
10820
10821 #ifndef NOXFER
10822       case XYDELA:                      /* SET DELAY */
10823         y = cmnum("Number of seconds before starting to send",
10824                   "5",10,&x,xxstring);
10825         if (x < 0) x = 0;
10826         return(success = setnum(&ckdelay,x,y,999));
10827 #endif /* NOXFER */
10828
10829       default:
10830         break;
10831     }
10832
10833     switch (xx) {
10834 #ifdef CK_TAPI
10835       case XYTAPI:
10836         return(settapi());
10837 #endif /* CK_TAPI */
10838 #ifndef NODIAL
10839       case XYDIAL:                      /* SET MODEM or SET DIAL */
10840         return(setdial(-1));
10841       case XYMODM:
10842         return(setmodem());
10843 #ifdef COMMENT
10844       /* not implemented yet */
10845       case XYANSWER:                    /* SET ANSWER */
10846         return(setanswer());
10847 #endif /* COMMENT */
10848 #endif /* NODIAL */
10849
10850 #ifndef NOLOCAL
10851       case XYDUPL:                      /* SET DUPLEX */
10852         if ((y = cmkey(dpxtab,2,"","full",xxstring)) < 0) return(y);
10853         if ((x = cmcfm()) < 0) return(x);
10854         duplex = y;
10855         return(success = 1);
10856
10857       case XYLCLE:                      /* LOCAL-ECHO (= DUPLEX) */
10858         return(success = seton(&duplex));
10859
10860       case XYESC:                       /* SET ESCAPE */
10861         return(success = setcc(ckitoa(DFESC),&escape));
10862 #endif /* NOLOCAL */
10863
10864       case XYEXIT:                      /* SET EXIT */
10865         if ((z = cmkey(xittab,nexit,"","",xxstring)) < 0)
10866           return(z);
10867         switch (z) {
10868           case 0:                       /* STATUS */
10869             y = cmnum("EXIT status code","",10,&x,xxstring);
10870             return(success = setnum(&xitsta,x,y,-1));
10871           case 1:                       /* WARNING */
10872             if ((z = cmkey(xitwtab,nexitw,"","",xxstring)) < 0)
10873               return(z);
10874             if ((y = cmcfm()) < 0) return(y);
10875             setexitwarn(z);
10876             return(success = 1);
10877           case 2:
10878             success = seton(&exitonclose);
10879 #ifdef TCPSOCKET
10880             if (success) tn_exit = exitonclose;
10881 #endif /* TCPSOCKET */
10882             return(success);
10883           case 3: {
10884               extern int exithangup;
10885               return((success = seton(&exithangup)));
10886           }
10887           default:
10888             return(-2);
10889         } /* End of SET EXIT switch() */
10890       default:
10891         break;
10892     }
10893
10894     switch (xx) {
10895
10896       case XYFILE:                      /* SET FILE */
10897         return(setfil(rmsflg));
10898
10899       case XYFLOW: {                    /* FLOW-CONTROL */
10900           extern int cxflow[];
10901           struct FDB k1, k2;
10902           int tncomport = 0;
10903           char * m;
10904
10905 #ifdef TN_COMPORT
10906           if (network && istncomport())
10907             tncomport = 1;
10908 #endif /* TN_COMPORT */
10909
10910           if (tncomport) {
10911               m = "Flow control type, one of the following:\n\
10912    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
10913  or connection type";
10914           } else {
10915           /* All this is because chained FDB's don't give chained help yet */
10916               m =
10917 #ifdef Plan9
10918 #ifdef CK_RTSCTS
10919            "Flow control type, one of the following:\n\
10920    keep   none    rts/cts\n\
10921  or connection type",
10922 #else
10923            "Flow control type, one of the following:\n\
10924    keep   none\n\
10925  or connection type";
10926 #endif /* CK_RTSCTS */
10927 #else
10928 #ifdef CK_RTSCTS
10929 #ifdef CK_DTRCD
10930 #ifdef CK_DTRCTS
10931            "Flow control type, one of the following:\n\
10932    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
10933  or connection type";
10934 #else /* CK_DTRCTS */
10935            "Flow control type, one of the following:\n\
10936    dtr/cd    keep    none    rts/cts   xon/xoff\n\
10937             or connection type";
10938 #endif /* CK_DTRCTS */
10939 #else /* CK_DTRCD */
10940 #ifdef CK_DTRCTS
10941            "Flow control type, one of the following:\n\
10942    dtr/cts   keep   none    rts/cts   xon/xoff\n\
10943  or connection type";
10944 #else /* CK_DTRCTS */
10945            "Flow control type, one of the following:\n\
10946    keep   none    rts/cts   xon/xoff\n\
10947  or connection type";
10948 #endif /* CK_DTRCTS */
10949 #endif /* CK_DTRCD */
10950 #else
10951            "Flow control type, one of the following:\n\
10952    keep   none    xon/xoff\n\
10953  or connection type";
10954 #endif /* CK_RTSCTS */
10955 #endif /* Plan9 */
10956           }
10957           cmfdbi(&k1,_CMKEY,m,"","",ncxtypesw, 4, xxstring, cxtypesw, &k2);
10958           cmfdbi(&k2,
10959                  _CMKEY,
10960                  "",
10961                  "",
10962                  "",
10963 #ifdef TN_COMPORT
10964                  (tncomport ? ntnflo : nflo),
10965 #else
10966                  nflo,
10967 #endif /* TN_COMPORT */
10968                  0,
10969                  xxstring,
10970 #ifdef TN_COMPORT
10971                  (tncomport ? tnflotab : flotab),
10972 #else
10973                  flotab,
10974 #endif /* TN_COMPORT */
10975                  NULL
10976                  );
10977           x = cmfdb(&k1);
10978           if (x < 0) {                  /* Error */
10979               if (x == -2 || x == -9)
10980                 printf("?No keywords or switches match: \"%s\"\n",atmbuf);
10981               return(x);
10982           }
10983           z = cmresult.nresult;         /* Keyword value */
10984           if (cmresult.fdbaddr == &k2) { /* Flow-control type keyword table */
10985               if ((x = cmcfm()) < 0)    /* Set it immediately */
10986                 return(x);
10987               flow = z;
10988               debug(F101,"set flow","",flow);
10989 #ifdef CK_SPEED
10990               if (flow == FLO_XONX)     /* Xon/Xoff forces prefixing */
10991                 ctlp[XON] = ctlp[XOFF] = ctlp[XON+128] = ctlp[XOFF+128] = 1;
10992 #endif /* CK_SPEED */
10993               autoflow = (flow == FLO_AUTO);
10994               return(success = 1);      /* Done */
10995           }
10996           debug(F101,"set flow /blah 1","",z); /* SET FLOW /for-what */
10997           if ((y = cmkey(flotab,nflo,"Flow control type","none",xxstring)) < 0)
10998             return(y);
10999           if ((x = cmcfm()) < 0)
11000             return(x);
11001           debug(F101,"set flow /blah 2","",y);
11002           if (y == FLO_AUTO) {
11003               printf(
11004   "?Sorry, \"automatic\" can not be assigned to a connection type.\n");
11005               return(-9);
11006           } else if (z >= 0 && z <= CXT_MAX)
11007             cxflow[z] = y;
11008           debug(F101,"set flow","",flow);
11009           debug(F101,"set flow autoflow","",autoflow);
11010           return(success = 1);
11011       }
11012
11013       case XYHAND:                      /* HANDSHAKE */
11014         if ((y = cmkey(hshtab,nhsh,"","none",xxstring)) < 0) return(y);
11015         if (y == 998) {
11016             if ((x = cmnum("ASCII value","",10,&y,xxstring)) < 0)
11017               return(x);
11018             if ((y < 1) || ((y > 31) && (y != 127))) {
11019                 printf("?Character must be in ASCII control range\n");
11020                 return(-9);
11021             }
11022         }
11023         if ((x = cmcfm()) < 0) return(x);
11024         turn = (y > 0127) ? 0 : 1;
11025         turnch = y;
11026         return(success = 1);
11027
11028 #ifndef NOSPL
11029       case XYMACR:                      /* SET MACRO */
11030         if ((y = cmkey(smactab,2,"","",xxstring)) < 0) return(y);
11031         switch (y) {
11032           case 0: return(success = seton(&mecho));
11033           case 1: return(success = seton(&merror[cmdlvl]));
11034           default: return(-2);
11035         }
11036 #endif /* NOSPL */
11037
11038       case XYMSGS:
11039 #ifdef VMS
11040         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
11041         if ((y = cmcfm()) < 0) return(y);
11042         vms_msgs = z;
11043         printf("Sorry, SET MESSAGES not implemented yet\n");
11044         return(success = 0);
11045 #endif /* VMS */
11046       default:
11047         break;
11048     }
11049
11050     switch (xx) {
11051
11052       case XYPARI:                      /* PARITY */
11053         if ((y = cmkey(partbl,npar,"","none",xxstring)) < 0)
11054           return(y);
11055
11056         /* If parity not none, then we also want 8th-bit prefixing */
11057
11058 #ifdef HWPARITY
11059         if (y == 'H') {                 /* Hardware */
11060             if ((x = cmkey(hwpartbl,nhwpar,"","even",xxstring)) < 0)
11061               return(x);
11062         }
11063 #endif /* HWPARITY */
11064
11065         if ((z = cmcfm()) < 0)
11066           return(z);
11067
11068 #ifdef HWPARITY
11069         if (y == 'H') {                 /* 8 data bits plus hardware parity */
11070             parity = 0;
11071 #ifndef NOXFER
11072             ebqflg = 0;
11073 #endif /* NOXFER */
11074             hwparity = x;
11075         } else {                        /* 7 data bits + software parity */
11076             hwparity = 0;
11077 #endif /* HWPARITY */
11078             parity = y;
11079 #ifndef NOXFER
11080             ebqflg = (parity) ? 1 : 0;
11081 #endif /* NOXFER */
11082 #ifdef HWPARITY
11083         }
11084 #endif /* HWPARITY */
11085
11086 #ifdef TN_COMPORT
11087         if (network && istncomport())
11088           tnsettings(parity, 0);
11089 #endif /* TN_COMPORT */
11090
11091         return(success = 1);
11092
11093 #ifndef NOFRILLS
11094       case XYPROM:                      /* SET PROMPT */
11095 /*
11096   Note: xxstring not invoked here.  Instead, it is invoked every time the
11097   prompt is issued.  This allows the prompt string to contain variables
11098   that can change, like \v(dir), \v(time), etc.
11099 */
11100         ckmakmsg(line,                  /* Default might have trailing space */
11101                  LINBUFSIZ,
11102                  "{",
11103                  inserver ? ikprompt : ckprompt,
11104                  "}",
11105                  NULL
11106                  );
11107         if ((x = cmtxt("Program's command prompt",line,&s,NULL)) < 0)
11108           return(x);
11109         s = brstrip(s);                 /* Remove enclosing braces, if any */
11110         cmsetp(s);                      /* Set the prompt */
11111         return(success = 1);
11112 #endif /* NOFRILLS */
11113
11114 #ifndef NOXFER
11115       case XYRETR:                      /* RETRY: per-packet retry limit */
11116         y = cmnum("Maximum retries per packet","10",10,&x,xxstring);
11117         if (x < 0) x = 0;
11118         if ((x = setnum(&maxtry,x,y,999)) < 0) return(x);
11119 #ifdef COMMENT
11120         if (maxtry <= wslotr) {
11121             printf("?Retry limit must be greater than window size\n");
11122             return(success = 0);
11123         }
11124 #endif /* COMMENT */
11125         if (rmsflg) {
11126             sstate = setgen('S', "403", ckitoa(maxtry), "");
11127             return((int) sstate);
11128         } else return(success = x);
11129 #endif /* NOXFER */
11130
11131 #ifndef NOSERVER
11132       case XYSERV:                      /* SET SERVER items */
11133         if ((y = cmkey(srvtab,nsrvt,"","",xxstring)) < 0) return(y);
11134         switch (y) {
11135           case XYSERI:
11136             if ((y = cmnum("Number of seconds, or 0 for no idle timeout",
11137                            "0",10,&x,xxstring)) < 0)
11138               return(y);
11139             if (x < 0)
11140               x = 0;
11141             if ((y = cmcfm()) < 0)
11142               return(y);
11143 #ifndef OS2
11144             srvtim = 0;
11145 #endif /* OS2 */
11146             srvidl = x;
11147             return(success = 1);
11148           case XYSERT:
11149             if ((y = cmnum("Interval for server NAKs, 0 = none",
11150                            ckitoa(DSRVTIM),
11151                            10,&x, xxstring)) < 0)
11152               return(y);
11153             if (x < 0) {
11154                 printf(
11155                    "\n?Specify a positive number, or 0 for no server NAKs\n");
11156                 return(0);
11157             }
11158             if ((y = cmcfm()) < 0) return(y);
11159             if (rmsflg) {
11160                 sstate = setgen('S', "404", ckitoa(x), "");
11161                 return((int) sstate);
11162             } else {
11163 #ifndef OS2
11164                 srvidl = 0;
11165 #endif /* OS2 */
11166                 srvtim = x;             /* Set the server timeout variable */
11167                 return(success = 1);
11168             }
11169           case XYSERD:                  /* SERVER DISPLAY */
11170             return(success = seton(&srvdis)); /* ON or OFF... */
11171
11172 #ifndef NOSPL
11173           case XYSERP:                  /* SERVER GET-PATH */
11174             return(parsdir(2));
11175 #endif /* NOSPL */
11176
11177           case XYSERL:                  /* SERVER LOGIN */
11178             return(cklogin());
11179
11180           case XYSERC:                  /* SERVER CD-MESSAGE */
11181             x = rmsflg ?
11182               cmkey(onoff,2,"","",xxstring) :
11183                 cmkey(cdmsg,3,"","",xxstring);
11184             if (x < 0)
11185               return(x);
11186             if (x == 2) {               /* CD-MESSAGE FILE */
11187                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
11188                   return(x);
11189                 if (!*s) {
11190                     s = NULL;
11191                     srvcdmsg = 0;
11192                 }
11193                 makestr(&cdmsgstr,s);
11194                 makelist(cdmsgstr,cdmsgfile,8);
11195                 return(success = 1);
11196             }
11197             if ((y = cmcfm()) < 0)      /* CD-MESSAGE ON/OFF */
11198               return(y);
11199             if (rmsflg) {
11200                 sstate = setgen('S', "420", x ? "1" : "0", "");
11201                 return((int) sstate);
11202             } else {
11203                 if (x > 0)
11204                   srvcdmsg |= 1;
11205                 else
11206                   srvcdmsg &= 2;
11207                 return(success = 1);
11208             }
11209           case XYSERK:                  /* SERVER KEEPALIVE */
11210             return(success = seton(&srvping)); /* ON or OFF... */
11211
11212           default:
11213             return(-2);
11214         }
11215 #endif /* NOSERVER */
11216     }
11217
11218     switch (xx) {
11219 #ifdef UNIX
11220 #ifndef NOJC
11221       case XYSUSP:                      /* SET SUSPEND */
11222         seton(&xsuspend);               /* on or off... */
11223         return(success = 1);
11224 #endif /* NOJC */
11225 #endif /* UNIX */
11226
11227       case XYTAKE:                      /* SET TAKE */
11228         if ((y = cmkey(taktab,4,"","",xxstring)) < 0) return(y);
11229         switch (y) {
11230           case 0: return(success = seton(&techo));
11231 #ifndef NOSPL
11232           case 1: return(success = seton(&takerr[cmdlvl]));
11233 #else
11234           case 1: return(success = seton(&takerr[tlevel]));
11235 #endif /* NOSPL */
11236           case 2: techo = 0; return(success = 1); /* For compatibility with */
11237           case 3: techo = 1; return(success = 1); /* MS-DOS Kermit */
11238           default: return(-2);
11239         }
11240
11241 #ifndef NOSCRIPT
11242       case XYSCRI:                      /* SET SCRIPT */
11243         if ((y = cmkey(scrtab,1,"","echo",xxstring)) < 0) return(y);
11244         switch (y) {
11245           case 0: return(success = seton(&secho));
11246           default: return(-2);
11247         }
11248 #endif /* NOSCRIPT */
11249
11250       default:
11251         break;
11252     }
11253
11254 #ifndef NOLOCAL
11255     switch (xx) {
11256       case XYTERM:                      /* SET TERMINAL */
11257         x = settrm();
11258         success = (x > 0) ? 1 : 0;
11259         return(x);
11260
11261 #ifdef NT
11262       case XYWIN95:                     /* SET WIN95 workarounds */
11263         x = setwin95();
11264         success = (x > 0 ? 1 : 0);
11265         return(x);
11266 #endif /* NT */
11267
11268 #ifdef OS2
11269       case XYDLR:                       /* SET DIALER workarounds */
11270         x = setdialer();
11271         success = (x > 0 ? 1 : 0);
11272         return(x);
11273
11274       case XYTITLE:                     /* SET TITLE of window */
11275         x = settitle();
11276         success = (x > 0 ? 1 : 0);
11277         return(x);
11278 #endif /* OS2 */
11279
11280 #ifdef OS2MOUSE
11281       case XYMOUSE:                     /* SET MOUSE */
11282         return(success = setmou());
11283 #endif /* OS2MOUSE */
11284
11285       case XYBELL:                      /* SET BELL */
11286         return(success = setbell());
11287
11288 #ifdef OS2
11289       case XYPRTY:
11290         return(success = setprty() );
11291 #endif /* OS2 */
11292
11293       default:
11294         break;
11295     }
11296 #endif /* NOLOCAL */
11297
11298     switch (xx) {
11299
11300 /* SET SEND/RECEIVE protocol parameters. */
11301
11302 #ifndef NOXFER
11303       case XYRECV:
11304       case XYSEND:
11305         return(setsr(xx,rmsflg));
11306 #endif /* NOXFER */
11307
11308 #ifndef NOLOCAL
11309       case XYSESS:                      /* SESSION-LOG */
11310         if ((x = cmkey(sfttab,nsfttab,"type of file",
11311 #ifdef OS2
11312                        "binary",
11313 #else /* OS2 */
11314                        "text",
11315 #endif /* OS2 */
11316                        xxstring
11317                        )
11318              ) < 0)
11319           return(x);
11320         if ((y = cmcfm()) < 0)
11321           return(y);
11322         if (x == 999) {                 /* TIMESTAMPED-TEXT */
11323             sessft = XYFT_T;            /* Implies text */
11324             slogts = 1;                 /* and timestamps */
11325         } else if (x == 998) {          /* NULL-PADDED-LINES */
11326             slognul = 1;                /* adds NUL after ^J */
11327         } else {                        /* A regular type */
11328             sessft = x;                 /* The type */
11329             slogts = 0;                 /* No timestampes */
11330         }
11331         return(success = 1);
11332
11333       case XYSPEE:                      /* SET SPEED */
11334         lp = line;
11335         if (local && !network) {
11336           ckmakmsg(lp,
11337                    LINBUFSIZ,
11338                    "Transmission rate for ",
11339                    ttname,
11340                    " (bits per second)",
11341                    NULL
11342                    );
11343         } else {
11344           ckstrncpy(lp,
11345                     "Serial-port speed (bits per second)",
11346                     LINBUFSIZ
11347                     );
11348         }
11349         zz = -1L;
11350
11351 #ifdef TN_COMPORT
11352         if (network && istncomport())
11353           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
11354         else
11355 #endif /* TN_COMPORT */
11356           x = cmkey(spdtab,nspd,line,"",xxstring);
11357         if (x < 0) {
11358             if (x == -3) printf("?value required\n");
11359 #ifdef USETCSETSPEED
11360             /* In this case, any number can be tried */
11361             /* There's a parse error message but the request still goes thru */
11362             if (rdigits(atmbuf))
11363               zz = atol(atmbuf);
11364             else
11365 #endif /* USETCSETSPEED */
11366               return(x);
11367         }
11368         if ((y = cmcfm()) < 0) return(y);
11369 #ifdef IKSD
11370         if (inserver) {
11371             printf("?Sorry, command disabled.\r\n");
11372             return(success = 0);
11373         }
11374 #endif /* IKSD */
11375         if (!local) {
11376             printf("?SET SPEED has no effect without prior SET LINE\n");
11377             return(success = 0);
11378         } else if (network
11379 #ifdef TN_COMPORT
11380                    && !istncomport()
11381 #endif /* TN_COMPORT */
11382                    ) {
11383             printf("\n?Speed cannot be set for network connections\n");
11384             return(success = 0);
11385         }
11386
11387 /*
11388   Note: This way of handling speeds is not 16-bit safe for speeds greater
11389   than 230400.  The argument to ttsspd() should have been a long.
11390 */
11391 #ifdef USETCSETSPEED
11392         if (zz > -1L)
11393           x = zz / 10L;
11394 #endif /* USETCSETSPEED */
11395         zz = (long) x * 10L;
11396         if (zz == 130L) zz = 134L;
11397         if (zz == 70L) zz = 75L;        /* (see spdtab[] definition) */
11398         if (ttsspd(x) < 0)  {           /* Call ttsspd with cps, not bps! */
11399             printf("?Unsupported line speed - %ld\n",zz);
11400             return(success = 0);
11401         } else {
11402 #ifdef CK_TAPI
11403             if (!tttapi || tapipass)
11404               speed = ttgspd();         /* Read it back */
11405             else
11406               speed = zz;
11407 #else /* CK_TAPI */
11408             speed = ttgspd();           /* Read it back */
11409 #endif /* CK_TAPI */
11410             if (speed != zz)  {         /* Call ttsspd with cps, not bps! */
11411                 printf("?SET SPEED fails, speed is %ld\n",speed);
11412                 return(success = 0);
11413             }
11414             if (pflag && !xcmdsrc) {
11415                 if (speed == 8880)
11416                   printf("%s, 75/1200 bps\n",ttname);
11417                 else if (speed == 134)
11418                   printf("%s, 134.5 bps\n",ttname);
11419                 else
11420                   printf("%s, %ld bps\n",ttname,speed);
11421             }
11422             return(success = 1);
11423         }
11424 #endif /* NOLOCAL */
11425
11426 #ifndef NOXFER
11427       case XYXFER:                      /* SET TRANSFER */
11428         if ((y = cmkey(rmsflg ? rtstab : tstab, /* (or REMOTE SET TRANSFER) */
11429                        rmsflg ? nrts : nts,
11430                        "","character-set",xxstring)) < 0) return(y);
11431         switch (y) {
11432 #ifdef XFRCAN
11433           case XYX_CAN:                 /* CANCELLATION */
11434             if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
11435             if (z == 0) {               /* OFF */
11436                 if ((y = cmcfm()) < 0) return(y);
11437                 xfrcan = 0;
11438             } else {
11439                 if ((y = cmnum("ASCII code for cancellation character",
11440                                "3",10,&x,
11441                                xxstring)) < 0)
11442                   return(y);
11443                 if (x > 31 && x != 127) {
11444                     printf("Cancel character must be 0-31 or 127\n");
11445                     return(-9);
11446                 }
11447                 if ((y = cmnum("How many required to cause cancellation",
11448                                "2",10,&z, xxstring)) < 0)
11449                   return(y);
11450                 if (z < 2) {
11451                     printf("Number must be 2 or greater\n");
11452                     return(-9);
11453                 }
11454                 if ((y = cmcfm()) < 0) return(y);
11455                 xfrcan = 1;             /* CANCELLATION ON */
11456                 xfrchr = x;             /* Using this character */
11457                 xfrnum = z;             /* Needing this many of them */
11458             }
11459             return(success = 1);
11460 #endif /* XFRCAN */
11461
11462 #ifndef NOCSETS
11463           case XYX_CSE:                 /* CHARACTER-SET */
11464             if ((y = cmkey(tcstab,ntcs,"","transparent",xxstring)) < 0)
11465               return(y);
11466             if ((x = cmcfm()) < 0) return(x);
11467             if (rmsflg) {
11468                 sstate = setgen('S', "405", tcsinfo[y].designator, "");
11469                 return((int) sstate);
11470             } else {
11471                 extern int s_cset, fcharset, axcset[], tcs_save;
11472                 tslevel = (y == TC_TRANSP) ? 0 : 1; /* transfer syntax level */
11473                 xfrxla = tslevel;
11474                 tcharset = y;           /* transfer character set */
11475                 /* SEND CHARACTER-SET AUTO */
11476                 if (tslevel > 0 && s_cset == XMODE_A)
11477                   if (y > -1 && y <= MAXTCSETS)
11478                     if (axcset[y] > -1 && axcset[y] > MAXFCSETS)
11479                       fcharset = axcset[y]; /* Auto-pick file charset */
11480                 setxlatype(tcharset,fcharset); /* Translation type */
11481                 tcs_save = -1;
11482                 return(success = 1);
11483             }
11484 #endif /* NOCSETS */
11485
11486           case XYX_LSH:                 /* LOCKING-SHIFT */
11487             if ((y = cmkey(lstab,nls,"","on",xxstring)) < 0)
11488               return(y);
11489             if ((x = cmcfm()) < 0) return(x);
11490             lscapr = (y == 1) ? 1 : 0;  /* ON: requested = 1 */
11491             lscapu = (y == 2) ? 2 : 0;  /* FORCED:  used = 1 */
11492             return(success = 1);
11493
11494 /* #ifdef CK_XYZ */
11495           case XYX_PRO:                 /* Protocol */
11496 #ifndef OS2
11497             if (inserver) {
11498                 printf("?Sorry, only Kermit protocol is available\n");
11499                 return(-9);
11500             }
11501 #endif /* OS2 */
11502             return(setproto());
11503 /* #endif */ /* CK_XYZ */
11504
11505           case XYX_MOD:                 /* Mode */
11506             if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
11507               return(y);
11508             if ((x = cmcfm()) < 0) return(x);
11509             if (rmsflg) {
11510                 sstate = setgen('S', "410", y == XMODE_A ? "0" : "1", "");
11511                 return((int)sstate);
11512             }
11513             g_xfermode = y;
11514             xfermode = y;
11515 #ifdef NEWFTP
11516             if (ftpisopen()) {          /* If an FTP connection is open */
11517                 extern int ftp_xfermode; /* change its transfer mode too */
11518                 ftp_xfermode = xfermode;
11519             }         
11520 #endif  /* NEWFTP */
11521             return(success = 1);
11522
11523 #ifndef NOLOCAL
11524           case XYX_DIS:                 /* Display */
11525             return(doxdis(1));          /* 1 == Kermit */
11526 #endif /* NOLOCAL */
11527
11528           case XYX_SLO:                 /* Slow-start */
11529             return(seton(&slostart));
11530
11531 #ifndef NOSPL
11532           case XYX_CRC:                 /* CRC */
11533             return(seton(&docrc));
11534 #endif /* NOSPL */
11535
11536           case XYX_BEL:                 /* Bell */
11537             return(seton(&xfrbel));
11538
11539 #ifdef PIPESEND
11540           case XYX_PIP:                 /* Pipes */
11541 #ifndef NOPUSH
11542             if (nopush) {
11543 #endif /* NOPUSH */
11544                 printf("Sorry, access to pipes is disabled\n");
11545                 return(-9);
11546 #ifndef NOPUSH
11547             } else
11548 #endif /* NOPUSH */
11549               return(seton(&usepipes));
11550 #endif /* PIPESEND */
11551
11552           case XYX_INT:                 /* Interruption */
11553             return(seton(&xfrint));
11554
11555           case XYX_XLA:
11556             return(seton(&xfrxla));     /* Translation */
11557
11558           case XYX_MSG: {
11559               extern char * xfrmsg;
11560               if ((x = cmtxt("Prompt string","",&s,xxstring)) < 0)
11561                 return(x);
11562               if (!*s) s = NULL;
11563               makestr(&xfrmsg,s);
11564               return(success = 1);
11565
11566           }
11567           case XYX_RPT: {
11568               extern int whereflg;
11569               return(seton(&whereflg));
11570           }
11571           default:
11572             return(-2);
11573         }
11574 #endif /* NOXFER */
11575     }
11576
11577     switch (xx) {
11578
11579 #ifndef NOXMIT
11580       case XYXMIT:                      /* SET TRANSMIT */
11581         return(setxmit());
11582 #endif /* NOXMIT */
11583
11584 #ifndef NOXFER
11585 #ifndef NOCSETS
11586       case XYUNCS:                      /* UNKNOWN-CHARACTER-SET */
11587         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
11588         if ((x = cmcfm()) < 0) return(x);
11589         unkcs = y;
11590         return(success = 1);
11591 #endif /* NOCSETS */
11592 #endif /* NOXFER */
11593
11594 #ifndef NOPUSH
11595 #ifdef UNIX
11596       case XYWILD:                      /* WILDCARD-EXPANSION */
11597         if ((y = cmkey(wildtab,nwild,
11598                        "Wildcard expansion option","on",xxstring)) < 0)
11599           return(y);
11600         if ((z = cmkey(wdottab,
11601                        2,
11602                        "whether to match filenames that start with \".\"",
11603                        "/no-match-dot-files",
11604                        xxstring)
11605              ) < 0)
11606           return(z);
11607         if ((x = cmcfm()) < 0) return(x);
11608         if (nopush) {
11609             if (y > 0) {
11610                 printf("Shell expansion is disabled\n");
11611                 return(success = 0);
11612             }
11613         }
11614         switch (y) {
11615           case WILD_ON:
11616             wildena = 1; 
11617             break;
11618           case WILD_OFF:
11619             wildena = 0; 
11620             break;
11621           case WILD_KER:
11622             wildxpand = 0;              /* These are the previous */
11623             break;                      /* hardwired values */
11624           case WILD_SHE:
11625             wildxpand = 1; 
11626             break;
11627         }
11628         matchdot = z;
11629         return(success = 1);
11630 #endif /* UNIX */
11631 #endif /* NOPUSH */
11632
11633 #ifndef NOXFER
11634       case XYWIND:                      /* WINDOW-SLOTS */
11635         if (protocol == PROTO_K) {
11636             y = cmnum("Window size for Kermit protocol, 1 to 32",
11637                       "1", 10, &x, xxstring);
11638             y = setnum(&z,x,y,MAXWS);   /* == 32 */
11639         }
11640 #ifdef CK_XYZ
11641         else if (protocol == PROTO_Z) {
11642             y = cmnum("Window size for ZMODEM protocol, 0 to 65535",
11643                       "0", 10, &x, xxstring);
11644             y = setnum(&z,x,y,65535);
11645         }
11646 #endif /* CK_XYZ */
11647         else {
11648             y = cmnum("Window size for current protocol",
11649                       "", 10, &x, xxstring);
11650             y = setnum(&z,x,y,65472);   /* Doesn't matter - we won't use it */
11651         }
11652         if (y < 0) return(y);
11653         if (protocol == PROTO_K) {
11654             if (z < 1)
11655               z = 1;
11656         }
11657 #ifdef CK_XYZ
11658         else if (protocol == PROTO_Z) {
11659             /* Zmodem windowing is closer to Kermit packet length */
11660             /* than Kermit window size.  If Window size is zero   */
11661             /* an end of frame and CRC is sent only at the end of */
11662             /* the file (default).  Otherwise, an End of Frame    */
11663             /* and CRC are sent after Window Size number of bytes */
11664             if (z < 0)                  /* Disable windowing  */
11665               z = 0;
11666         } else {
11667             printf("?SET WINDOW does not apply to %s protocol\n",
11668                    ptab[protocol].p_name
11669                    );
11670         }
11671 #endif /* CK_XYZ */
11672
11673 #ifdef COMMENT
11674         /* This is taken care of automatically now in protocol negotiation */
11675         if (maxtry < z) {
11676             printf("?Window slots must be less than retry limit\n");
11677             return(success = 0);
11678         }
11679 #endif /* COMMENT */
11680         if (protocol == PROTO_K && rmsflg) { /* Set remote window size */
11681             wslotr = z;                 /* Set local window size too */
11682             ptab[protocol].winsize = wslotr;
11683             sstate = setgen('S', "406", ckitoa(z), "");
11684             return((int) sstate);
11685         }
11686         wslotr = z;                     /* Set requested window size here */
11687         ptab[protocol].winsize = wslotr; /* and in protocol-specific table */
11688         if (protocol == PROTO_K) {      /* And for Kermit only... */
11689             swcapr = (wslotr > 1) ? 1 : 0; /* set window bit in capas word */
11690             if (wslotr > 1) {           /* Window size > 1? */
11691                 /* Maybe adjust packet size */
11692                 y = adjpkl(urpsiz,wslotr,bigrbsiz);
11693                 if (y != urpsiz) {      /* Did it change? */
11694                     urpsiz = y;
11695                     if (msgflg)
11696                       printf(
11697 " Adjusting receive packet-length to %d for %d window slots\n",
11698                              urpsiz,
11699                              wslotr
11700                              );
11701                 }
11702             }
11703         }
11704         return(success = 1);
11705 #endif /* NOXFER */
11706     }
11707
11708     switch (xx) {
11709
11710 #ifndef NOSPL
11711       case XYOUTP:                      /* OUTPUT command parameters */
11712         if ((y = cmkey(outptab,noutptab,"OUTPUT command parameter","pacing",
11713                        xxstring)) < 0)
11714           return(y);
11715         switch(y) {                     /* Which parameter */
11716           case OUT_PAC:                 /* PACING */
11717             y = cmnum("Milliseconds to pause between each OUTPUT character",
11718                       "100", 10,&x,xxstring);
11719             y = setnum(&z,x,y,16383);   /* Verify and get confirmation */
11720             if (y < 0) return(y);
11721             if (z < 0) z = 0;           /* (save some space) */
11722             pacing = z;
11723             return(success = 1);
11724           case OUT_ESC:                 /* Special-escapes */
11725             return(seton(&outesc));
11726           default:                      /* (shouldn't happen) */
11727             return(-2);
11728         }
11729 #endif /* NOSPL */
11730
11731 #ifdef CK_SPEED
11732       case XYQCTL: {
11733           short *p;
11734           int zz;
11735           if ((z = cmkey(ctltab,2, "control-character prefixing option",""
11736                          ,xxstring)) < 0)
11737             return(z);
11738           /* Make space for a temporary copy of the prefixing table */
11739
11740           p = (short *)malloc(256 * sizeof(short));
11741           if (!p) {
11742               printf("?Internal error - malloc failure\n");
11743               return(-9);
11744           }
11745           for (i = 0; i < 256; i++) p[i] = ctlp[i]; /* Copy current table */
11746
11747           switch (z) {
11748             case 0:                     /* UNPREFIXED control character */
11749             case 1:                     /* PREFIXED control character */
11750               while (1) {               /* Collect a list of numbers */
11751 #ifndef NOSPL
11752                   x_ifnum = 1;          /* Turn off complaints from eval() */
11753 #endif /* NOSPL */
11754                   if ((x = cmnum((z == 0) ?
11755 "\n Numeric ASCII value of control character that needs NO prefix,\n\
11756  or the word \"all\", or carriage return to complete the list" :
11757 "\n Numeric ASCII value of control character that MUST BE prefixed,\n\
11758  or the word \"all\", or carriage return to complete the list",
11759                                  "",10,&y,xxstring
11760                                  )) < 0) {
11761 #ifndef NOSPL
11762                       x_ifnum = 0;
11763 #endif /* NOSPL */
11764                       if (x == -3) {
11765                           if ((x = cmcfm()) < 0) return(x);
11766                           break;
11767                       }
11768                       if (x == -2) {
11769                           if (p) { free((char *)p); p = NULL; }
11770                           debug(F110,"SET CONTROL atmbuf",atmbuf,0);
11771                           if (!ckstrcmp(atmbuf,"all",3,0) || /* "ALL" */
11772                               !ckstrcmp(atmbuf,"al",2,0) ||
11773                               !ckstrcmp(atmbuf,"a",1,0)) {
11774                               if ((x = cmcfm()) < 0) /* Get confirmation */
11775                                 return(x);
11776                               prefixing = z ? PX_ALL : PX_NON;
11777                               setprefix(prefixing);
11778                               return(success = 1);
11779                           } else {      /* Not number, not ALL */
11780                               printf(
11781                                  "?Please specify a number or the word ALL\n");
11782                               return(-9);
11783                           }
11784                       } else {
11785                           if (p) free((char *)p);
11786                           return(x);
11787                       }
11788                   }
11789 #ifndef NOSPL
11790                   x_ifnum = 0;
11791 #endif /* NOSPL */
11792 #ifdef UNPREFIXZERO
11793                   zz = 0;
11794 #else
11795 #ifndef OS2
11796                   zz = 1 - z;
11797 #else
11798                   zz = 0;               /* Allow 0 (but only for Zmodem) */
11799 #endif /* OS2 */
11800 #endif /* UNPREFIXZERO */
11801
11802             /* printf("x = %d, y = %d, z = %d, zz = %d\n", x,y,z,zz); */
11803
11804                   if ((y >  31 && y < 127) || /* A specific numeric value */
11805                       (y > 159 && y < 255) || /* Check that it is a valid */
11806                       (y < zz) ||       /* control code. */
11807                       (y > 255)) {
11808                       printf("?Values allowed are: %d-31, 127-159, 255\n",zz);
11809                       if (p) free((char *)p);
11810                       return(-9);
11811                   }
11812                   x = y & 127;          /* Get 7-bit value */
11813                   if (z == 0) {         /* If they are saying it is safe... */
11814                       /* If flow control is Xon/Xoff */
11815                       if (((flow == FLO_XONX) &&
11816                            /* XON & XOFF chars not safe. */
11817                            (x == XON || x == XOFF))
11818                           ) {
11819                           if (msgflg)
11820                             printf(
11821                               "Sorry, not while Xon/Xoff is in effect.\n");
11822                           if (p) free((char *)p);
11823                           return(-9);
11824                       }
11825 #ifdef TNCODE
11826                       else if (network && IS_TELNET()
11827                                && (y == CR ||
11828                                    (unsigned) y == (unsigned) 255)) {
11829                           if (msgflg)
11830                             printf("Sorry, not on a TELNET connection.\n");
11831                           if (p) free((char *)p);
11832                           return(-9);
11833                       }
11834 #endif /* TNCODE */
11835                   }
11836                   p[y] = (char) z;      /* All OK, set flag */
11837               } /* End of while loop */
11838 /*
11839   Get here only if they have made no mistakes.  Copy temporary table back to
11840   permanent one, then free temporary table and return successfully.
11841 */
11842               for (i = 0; i < 256; i++) ctlp[i] = p[i];
11843               if (p) free((char *)p);
11844               if (z > 0) clearrq = 0;   /* 199 (see SET PREFIXING) */
11845               return(success = 1);
11846             default:
11847               return(-2);
11848           }
11849       }
11850 #endif /* CK_SPEED */
11851     }
11852
11853     switch (xx) {
11854
11855 #ifndef NOXFER
11856       case XYREPT:
11857         if ((y = cmkey(rpttab,2,
11858                        "repeat-count compression parameter","",xxstring)) < 0)
11859           return(y);
11860         switch(y) {
11861           case 0:
11862             return(success = seton(&rptena)); /* REPEAT COUNTS = ON, OFF */
11863           case 1:                       /* REPEAT MININUM number */
11864             printf("(not implemented yet, nothing happens)\n");
11865             return(-9);
11866           case 2:                       /* REPEAT PREFIX char */
11867             if ((x = cmnum("ASCII value","",10,&z,xxstring)) < 0)
11868               return(x);
11869             if ((x = cmcfm()) < 0) return(x);
11870             if ((z > 32 && z < 63) || (z > 95 && z < 127)) {
11871                 if (y == 1) rptmin = (CHAR) z; else myrptq = (CHAR) z;
11872                 return(success = 1);
11873             } else {
11874                 printf("?Illegal value for prefix character\n");
11875                 return(-9);
11876             }
11877         }
11878 #endif /* NOXFER */
11879
11880 #ifndef NOSPL
11881       case XYALRM: {
11882 #ifndef COMMENT
11883           int yy;
11884           long zz;
11885           zz = -1L;
11886           yy = x_ifnum;
11887           x_ifnum = 1;                  /* Turn off internal complaints */
11888           y = cmnum("Seconds from now, or time of day as hh:mm:ss",
11889                     "0" ,10, &x, xxstring);
11890           x_ifnum = yy;
11891           if (y < 0) {
11892               if (y == -2) {            /* Invalid number or expression */
11893                   zz = tod2sec(atmbuf); /* Convert to secs since midnight */
11894                   if (zz < 0L) {
11895                       printf("?Number, expression, or time of day required\n");
11896                       return(-9);
11897                   } else {
11898                       char now[32];     /* Current time */
11899                       char *p;
11900                       long tnow;
11901                       p = now;
11902                       ztime(&p);
11903                       tnow = atol(p+11) * 3600L +
11904                         atol(p+14) * 60L + atol(p+17);
11905                       if (zz < tnow)    /* User's time before now */
11906                         zz += 86400L;   /* So make it tomorrow */
11907                       zz -= tnow;       /* Seconds from now. */
11908                   }
11909               } else
11910                 return(y);
11911           }
11912           if (x < 0) {
11913               printf("?Alarm time is in the past.\n");
11914               return(-9);
11915           }
11916           if ((y = cmcfm()) < 0) return(y);
11917           if (zz > -1L) {               /* Time of day given? */
11918               x = zz;
11919               if (zz != (long) x) {
11920                   printf(
11921 "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
11922                          );
11923                   return(-9);
11924               }
11925           }
11926           return(setalarm((long)x));
11927       }
11928 #else
11929 /*
11930   This is to allow long values where int and long are not the same, e.g.
11931   on 16-bit systems.  But something is wrong with it.
11932 */
11933         if ((y = cmtxt("seconds from now", "0", &s, xxstring)) < 0)
11934           return(y);
11935         if (rdigits(s)) {
11936             return(setalarm(atol(s)));
11937         } else {
11938             printf("%s - not a number\n",s);
11939             return(-9);
11940         }
11941 #endif /* COMMENT */
11942 #endif /* NOSPL */
11943
11944 #ifndef NOXFER
11945       case XYPROTO:
11946         return(setproto());
11947 #endif /* NOXFER */
11948
11949 /*
11950   C-Kermit unprefixes control characters automatically on network connections
11951   if CLEAR-CHANNEL is ON, which it is by default.  But not all network
11952   connections are transparent to all control characters.  For example, the
11953   DEC-20, even when you TELNET to it, is sensitive to Ctrl-O and Ctrl-T.
11954   If you tell C-Kermit to SET CONTROL PREFIX 15 and/or 20, it doesn't help
11955   because CLEAR-CHANNEL is still in effect.  If the user goes to the trouble
11956   to set up some prefixing, then Kermit should do what the user said.  In
11957   C-Kermit 7.1 Alpha.03 we change the code to set clearrq to 0 if the user
11958   gives a SET PREFIXING or SET CONTROL PREFIX command.
11959 */
11960
11961 #ifdef CK_SPEED
11962       case XYPREFIX: {
11963 #ifdef COMMENT
11964           extern int clearrq;
11965 #endif /* COMMENT */
11966           if ((z = cmkey(pfxtab, 4, "control-character prefixing option",
11967                          "", xxstring)) < 0)
11968             return(z);
11969           if ((x = cmcfm()) < 0) return(x);
11970           clearrq = 0;                  /* 199 */
11971           setprefix(z);
11972 #ifdef COMMENT
11973           if (hints && (z == PX_ALL || z == PX_CAU) && clearrq) {
11974         printf("Hint: Use SET CLEAR-CHANNEL OFF to disable negotiation of\n");
11975         printf("      SET PREFIXING NONE during file transfers on reliable\n");
11976         printf("      connections.\n");
11977           }
11978 #endif /* COMMENT */
11979           return(success = 1);
11980       }
11981 #endif /* CK_SPEED */
11982
11983 #ifndef NOSPL
11984       case XYLOGIN:
11985         if ((z = cmkey(logintab, 3, "value for login script","userid",
11986                        xxstring)) < 0)
11987           return(z);
11988         x = cmdgquo();
11989         if (z == LOGI_PSW)
11990           cmdsquo(0);
11991         if ((y = cmtxt("text","", &s, NULL)) < 0) {
11992             cmdsquo(x);
11993             return(y);
11994         }
11995         cmdsquo(x);
11996 #ifdef IKSD
11997         if (inserver)
11998           return(success = 0);
11999 #endif /* IKSD */
12000         s = brstrip(s);
12001         if ((int)strlen(s) > 63) {
12002             printf("Sorry, too long\n");
12003             return(-9);
12004         }
12005         switch(z) {
12006           case LOGI_UID:
12007             ckstrncpy(uidbuf,s,UIDBUFLEN);
12008             sl_uid_saved = 0;
12009             break;
12010           case LOGI_PSW:
12011             ckstrncpy(pwbuf,s,PWBUFL);
12012             if (pwbuf[0]) {
12013                 pwflg = 1;
12014 #ifdef OS2
12015                 pwcrypt = 1;
12016 #else /* OS2 */
12017                 pwcrypt = 0;
12018 #endif /* OS2 */
12019             }
12020             break;
12021           case LOGI_PRM:
12022             ckstrncpy(prmbuf,s,PWBUFL);
12023         }
12024         return(success = 1);
12025 #endif /* NOSPL */
12026     }
12027
12028     switch (xx) {
12029
12030       case XYSTARTUP:
12031         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
12032         if ((x = cmcfm()) < 0) return(x);
12033         DeleteStartupFile = (y != 0) ? 0 : 1;
12034         return(success = 1);
12035
12036       case XYTMPDIR:
12037         x = cmdir("Name of temporary directory","",&s,xxstring);
12038         if (x == -3)
12039           s = "";
12040         else if (x < 0)
12041           return(x);
12042         if ((x = cmcfm()) < 0) return(x);
12043         makestr(&tempdir,s);
12044         return(tempdir ? 1 : 0);
12045
12046 #ifndef NOXFER
12047       case XYDEST:                      /* DESTINATION */
12048         return(setdest());
12049 #endif /* NOXFER */
12050
12051 #ifndef NOPUSH
12052 #ifndef NOFRILLS
12053
12054 /* Editor, Browser, and FTP Client */
12055
12056       case XYEDIT:                      /* EDITOR */
12057 #ifdef IKSD
12058         if (inserver) {
12059             printf("?Sorry, command disabled.\r\n");
12060             return(success = 0);
12061         }
12062 #endif /* IKSD */
12063 #ifdef CK_APC
12064         /* Don't let this be set remotely */
12065         if (apcactive == APC_LOCAL ||
12066             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12067           return(success = 0);
12068 #endif /* CK_APC */
12069
12070 #ifdef OS2ORUNIX
12071         {
12072             char *p = getenv("PATH");
12073             char *e;
12074             e = editor[0] ? (char *) editor : getenv("EDITOR");
12075             if (!e) e = "";
12076             if (p)
12077               x = cmifip("Name of preferred editor",e,&s,&y,0,p,xxstring);
12078             else
12079               x = cmifi("Full path of preferred editor",e,&s,&y,xxstring);
12080             if (x < 0 && x != -3)
12081               return(x);
12082         }
12083 #else
12084 #ifdef VMS
12085         if ((y = cmtxt("DCL command for editing", "edit", &s, NULL)) < 0) {
12086             if (x != -3)
12087               return(x);
12088         }
12089 #else
12090         if ((x = cmifi("Full path of preferred editor","",&s,&y,xxstring))<0) {
12091             if (x != -3)
12092               return(x);
12093         }
12094 #endif /* VMS */
12095 #endif /* OS2ORUNIX */
12096 #ifdef VMS
12097         ckstrncpy(editor,s,CKMAXPATH);
12098         editopts[0] = NUL;
12099 #else
12100         if (y != 0) {
12101             printf("?A single file please\n");
12102             return(-2);
12103         }
12104         ckstrncpy(line,s,LINBUFSIZ);
12105         if ((x = cmtxt("editor command-line options","",&s,NULL)) < 0)
12106           return(x);
12107         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12108         if ((z = cmcfm()) < 0) return(z);
12109         if (line[0]) {
12110             zfnqfp(line,CKMAXPATH,editor);
12111             ckstrncpy(editopts,tmpbuf,128);
12112         } else {
12113             editor[0] = NUL;
12114             editopts[0] = NUL;
12115         }
12116 #endif /* VMS */
12117         return(success = 1);
12118
12119 #ifndef NOFTP
12120 #ifndef SYSFTP
12121 #ifdef TCPSOCKET
12122       case XYFTPX:
12123         return(dosetftp());             /* SET FTP */
12124 #endif /* TCPSOCKET */
12125 #endif /* SYSFTP */
12126 #endif /* NOFTP */
12127
12128 #ifdef BROWSER
12129 #ifndef NOFTP
12130 #ifdef SYSFTP
12131       case XYFTP:                       /* SET FTP-CLIENT */
12132 #endif /* SYSFTP */
12133 #endif /* NOFTP */
12134       case XYBROWSE:                    /* SET BROWSER */
12135         {
12136             char *p = getenv("PATH");
12137             char *app = (char *) browser, *opts = (char *) browsopts;
12138 #ifndef NOFTP
12139 #ifdef SYSFTP
12140             extern char ftpapp[], ftpopts[];
12141             if (xx == XYFTP) {
12142                 app = (char *)ftpapp;
12143                 opts = (char *)ftpopts;
12144             }
12145 #endif /* SYSFTP */
12146 #endif /* NOFTP */
12147 #ifdef IKSD
12148             if (inserver) {
12149                 printf("?Sorry, command disabled.\r\n");
12150                 return(success = 0);
12151             }
12152 #endif /* IKSD */
12153 #ifdef CK_APC
12154             /* Don't let this be set remotely */
12155             if (apcactive == APC_LOCAL ||
12156                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12157               return(success = 0);
12158 #endif /* CK_APC */
12159 #ifdef OS2ORUNIX
12160             if (p)
12161               x = cmifip(xx == XYBROWSE ?
12162                          "Name of preferred browser" :
12163                          "Name of preferred ftp client",
12164 #ifdef OS2
12165                          xx == XYFTP ? "ftp.exe" : ""
12166 #else
12167                          xx == XYFTP ? "ftp" : ""
12168 #endif /* OS2 */
12169                          ,&s,&y,0,p,xxstring
12170                          );
12171             else
12172               x = cmifi(xx == XYBROWSE ?
12173                         "Full path of preferred browser" :
12174                         "Full path of preferred ftp client",
12175                         "",&s,&y,xxstring
12176                         );
12177             if (x < 0 && x != -3)
12178               return(x);
12179 #else
12180 #ifdef VMS
12181             if ((x = cmtxt("DCL command to start your preferred Web browser",
12182                            "", &s, NULL)) < 0) {
12183                 if (x != -3)
12184                   return(x);
12185             }
12186 #else
12187             if ((x = cmifi("Full path of preferred browser","",&s,&y,xxstring)
12188                  ) < 0) {
12189                 if (x != -3)
12190                   return(x);
12191             }
12192 #endif /* VMS */
12193 #endif /* OS2ORUNIX */
12194 #ifdef VMS
12195             ckstrncpy(app,s,CKMAXPATH);
12196             *opts = NUL;
12197 #else
12198             if (y != 0) {
12199                 printf("?A single file please\n");
12200                 return(-2);
12201             }
12202             ckstrncpy(line,s,LINBUFSIZ);
12203             if ((x = cmtxt(xx == XYBROWSE ?
12204                            "browser command-line options" :
12205                            "ftp client command-line options",
12206                            "",&s,NULL)
12207                  ) < 0)
12208               return(x);
12209             ckstrncpy(tmpbuf,s,TMPBUFSIZ);
12210             if ((z = cmcfm()) < 0) return(z);
12211             if (line[0]) {
12212                 zfnqfp(line,CKMAXPATH,app);
12213                 ckstrncpy(opts, tmpbuf, 128);
12214             } else {
12215                 *app = NUL;
12216                 *opts = NUL;
12217             }
12218 #endif /* VMS */
12219             return(success = 1);
12220         }
12221 #endif /* BROWSER */
12222 #endif /* NOFRILLS */
12223 #endif /* NOPUSH */
12224
12225 #ifdef CK_CTRLZ
12226       case XYEOF: {                     /* SET EOF */
12227           extern int eofmethod; extern struct keytab eoftab[];
12228           if ((x = cmkey(eoftab,3,"end-of-file detection method","",
12229                          xxstring)) < 0)
12230             return(x);
12231           if ((y = cmcfm()) < 0)
12232             return(y);
12233           eofmethod = x;
12234           return(success = 1);
12235       }
12236 #endif /* CK_CTRLZ */
12237
12238 #ifdef SESLIMIT
12239       case XYLIMIT: {  /* Session-Limit (length of session in seconds) */
12240           extern int seslimit;
12241 #ifdef OS2
12242           extern int downloaded;
12243 #endif /* OS2 */
12244           y = cmnum("Maximum length of session, seconds","0",10,&x,xxstring);
12245           if (inserver &&
12246 #ifdef IKSDCONF
12247               iksdcf
12248 #else
12249               1
12250 #endif /* IKSDCONF */
12251 #ifdef OS2
12252                || downloaded
12253 #endif /* OS2 */
12254               ) {
12255               if ((z = cmcfm()) < 0)
12256                 return(z);
12257               printf("?Sorry, command disabled.\r\n");
12258               return(success = 0);
12259           }
12260           return(setnum(&seslimit,x,y,86400));
12261       }
12262 #endif /* SESLIMIT */
12263
12264       case XYRELY: {                    /* SET RELIABLE */
12265           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12266             return(x);
12267           if ((y = cmcfm()) < 0) return(y);
12268           reliable = x;
12269           setreliable = (x != SET_AUTO);
12270           debug(F101,"SET RELIABLE reliable","",reliable);
12271           return(success = 1);
12272       }
12273
12274 #ifdef STREAMING
12275       case XYSTREAM: {                  /* SET STREAMING */
12276           extern int streamrq;
12277           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12278             return(x);
12279           if ((y = cmcfm()) < 0) return(y);
12280           streamrq = x;
12281           return(success = 1);
12282       }
12283 #endif /* STREAMING */
12284
12285 #ifdef CKSYSLOG
12286       case XYSYSL: {
12287           if ((x = cmkey(syslogtab,nsyslog,"","",xxstring)) < 0)
12288             return(x);
12289           if ((y = cmcfm()) < 0) return(y);
12290 #ifdef IKSD
12291           if (inserver &&
12292 #ifdef IKSDCONF
12293               iksdcf
12294 #else
12295               1
12296 #endif /* IKSDCONF */
12297               ) {
12298               printf("?Sorry, command disabled.\n");
12299               return(success = 0);
12300           }
12301 #endif /* IKSD */
12302 #ifdef CK_APC
12303           /* Don't let this be set remotely */
12304           if (apcactive == APC_LOCAL ||
12305               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12306             return(success = 0);
12307 #endif /* CK_APC */
12308           ckxsyslog = x;
12309           return(success = 1);
12310       }
12311 #endif /* CKSYSLOG */
12312
12313 #ifdef TLOG
12314       case XYTLOG: {                    /* SET TRANSACTION-LOG */
12315           extern int tlogsep;
12316           if ((x = cmkey(vbtab,nvb,"","verbose",xxstring)) < 0)
12317             return(x);
12318           if (x == 0) {
12319               if ((y = cmtxt("field separator",",",&s,NULL)) < 0) return(y);
12320               s = brstrip(s);
12321               if (*s) {
12322                   if (s[1]) {
12323                       printf("?A single character, please.\n");
12324                       return(-9);
12325                   } else if ((*s >= '0' && *s <= '9') ||
12326                              (*s >= 'A' && *s <= 'Z') ||
12327                              (*s >= 'a' && *s <= 'z')) {
12328                       printf("?A non-alphanumeric character, please.\n");
12329                       return(-9);
12330                   } else
12331                     tlogsep = *s;
12332               }
12333           } else {
12334               if ((y = cmcfm()) < 0) return(y);
12335           }
12336 #ifdef IKSD
12337           if (inserver && isguest) {
12338               printf("?Sorry, command disabled.\n");
12339               return(success = 0);
12340           }
12341 #endif /* IKSD */
12342 #ifdef CK_APC
12343           /* Don't let this be set remotely */
12344           if (apcactive == APC_LOCAL ||
12345               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
12346             return(success = 0);
12347 #endif /* CK_APC */
12348           tlogfmt = x;
12349           return(success = 1);
12350       }
12351 #endif /* TLOG */
12352
12353       case XYCLEAR: {                   /* SET CLEARCHANNEL */
12354           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
12355             return(x);
12356           if ((y = cmcfm()) < 0) return(y);
12357           clearrq = x;
12358           return(success = 1);
12359       }
12360
12361 #ifdef CK_AUTHENTICATION
12362       case XYAUTH: {                    /* SET AUTHENTICATION */
12363 #ifdef CK_KERBEROS
12364           int kv = 0;
12365           extern struct krb_op_data krb_op;
12366 #endif /* CK_KERBEROS */
12367           char * p = NULL;
12368           if ((x =
12369                cmkey(setauth,nsetauth,"authentication type","",xxstring)) < 0)
12370             return(x);
12371           switch (x) {
12372 #ifdef CK_KERBEROS
12373             case AUTH_KRB4: kv = 4; break; /* Don't assume values are same */
12374             case AUTH_KRB5: kv = 5; break;
12375 #endif /* CK_KERBEROS */
12376 #ifdef CK_SRP
12377             case AUTH_SRP: break;
12378 #endif /* CK_SRP */
12379 #ifdef CK_SSL
12380             case AUTH_SSL:
12381             case AUTH_TLS:
12382               break;
12383 #endif /* CK_SSL */
12384             default:
12385               printf("?Authorization type not supported yet - \"%s\"\n",
12386                      atmbuf);
12387               return(-9);
12388           }
12389 #ifdef IKSD
12390           if (inserver &&
12391 #ifdef IKSDCONF
12392               iksdcf
12393 #else
12394               1
12395 #endif /* IKSDCONF */
12396               ) {
12397               if ((y = cmcfm()) < 0) return(y);
12398               printf("?Sorry, command disabled.\n");
12399               return(success = 0);
12400           }
12401 #endif /* IKSD */
12402 #ifdef CK_APC
12403           /* Don't let this be set remotely */
12404           if (apcactive == APC_LOCAL ||
12405               apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)) {
12406               if ((y = cmcfm()) < 0) return(y);
12407               return(success = 0);
12408           }
12409 #endif /* CK_APC */
12410
12411           switch(x) {
12412 #ifdef CK_KERBEROS
12413             case AUTH_KRB4:
12414             case AUTH_KRB5: {
12415                 if ((x = cmkey(kv == 4 ? k4tab : k5tab,
12416                                kv == 4 ? nk4tab : nk5tab,
12417                                "Kerberos parameter","",xxstring)) < 0) {
12418                     return(x);
12419                 }
12420                 s = "";
12421                 switch (x) {
12422 #ifdef KRB4
12423                   case XYKRBDBG:
12424                     if (kv == 4) {
12425                         if ((y = seton(&k4debug)) < 0)
12426                           return(y);
12427 #ifdef NT
12428                         ck_krb4_debug(k4debug);
12429 #endif /* NT */
12430                     } else {
12431                         return(-9);
12432                     }
12433                     break;
12434 #endif /* KRB4 */
12435                   case XYKRBLIF:
12436                     if ((y = cmnum("TGT lifetime","600",10,&z,xxstring)) < 0)
12437                       return(y);
12438                     break;
12439                   case XYKRBPRE:
12440                     if (kv == 4) {
12441                         if ((y = seton(&krb4_d_preauth)) < 0)
12442                           return(y);
12443                     } else {
12444                         return(-9);
12445                     }
12446                     break;
12447                   case XYKRBINS:
12448                     if ((y = cmtxt("Instance name","",&s,xxstring)) < 0)
12449                       return(y);
12450                     break;
12451                   case XYKRBFWD:
12452                     if (kv == 5) {
12453                         if ((y = seton(&krb5_d_forwardable)) < 0)
12454                           return(y);
12455                     } else {
12456                         return(-9);
12457                     }
12458                     break;
12459                   case XYKRBPRX:
12460                     if (kv == 5) {
12461                         if ((y = seton(&krb5_d_proxiable)) < 0)
12462                           return(y);
12463                     } else {
12464                         return(-9);
12465                     }
12466                     break;
12467                   case XYKRBRNW:
12468                     if ((y = cmnum("TGT renewable lifetime",
12469                                    "0",10,&z,xxstring)) < 0)
12470                       return(y);
12471                     break;
12472                   case XYKRBADR:
12473                     if (kv == 5) {
12474                         if ((y = seton(&krb5_checkaddrs)) < 0)
12475                           return(y);
12476                     } else {
12477                         if ((y = seton(&krb4_checkaddrs)) < 0)
12478                           return(y);
12479                     }
12480                     break;
12481                   case XYKRBNAD:
12482                     if (kv == 5) {
12483                         if ((y = seton(&krb5_d_no_addresses)) < 0)
12484                           return(y);
12485                     }
12486                     break;
12487                   case XYKRBADD:
12488                     if (kv == 5) {
12489                         char * tmpaddrs[KRB5_NUM_OF_ADDRS];
12490                         for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
12491                           tmpaddrs[i] = NULL;
12492
12493                         if ((y =
12494                              cmfld("List of IP addresses","",&s,xxstring)) < 0)
12495                           return(y);
12496                         makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
12497                         if ((y = cmcfm()) < 0) {
12498                             for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
12499                                 if (tmpaddrs[i] != NULL)
12500                                   free(tmpaddrs[i]);
12501                             }
12502                             return(y);
12503                         }
12504                         for (i = 0;
12505                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
12506                              i++) {
12507                             if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
12508                                 printf("invalid ip address: %s\n",
12509                                        tmpaddrs[i]);
12510                                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
12511                                     if (tmpaddrs[i] != NULL)
12512                                       free(tmpaddrs[i]);
12513                                 }
12514                                 return(-9);
12515                             }
12516                         }
12517                         for (i = 0;
12518                              i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];
12519                              i++) {
12520                             if (krb5_d_addrs[i])
12521                               free(krb5_d_addrs[i]);
12522                             krb5_d_addrs[i] = NULL;
12523                         }
12524                         for (i = 0;
12525                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
12526                              i++) {
12527                             krb5_d_addrs[i] = tmpaddrs[i];
12528                             tmpaddrs[i] = NULL;
12529                         }
12530                         krb5_d_addrs[i] = NULL;
12531                         return(success = 1);
12532                     }
12533                     break;
12534
12535                   case XYKRBGET:
12536                     if (kv == 5) {
12537                         if ((y = seton(&krb5_autoget)) < 0)
12538                           return(y);
12539                     } else {
12540                         if ((y = seton(&krb4_autoget)) < 0)
12541                           return(y);
12542                     }
12543                     break;
12544                   case XYKRBDEL:
12545                     if ((z = cmkey(kdestab,nkdestab,
12546                                    "Auto Destroy Tickets",
12547                                    "never",xxstring)) < 0)
12548                       return(z);
12549                     break;
12550                   case XYKRBPR:
12551                     if ((y = cmtxt("User ID",uidbuf,&s,xxstring)) < 0)
12552                       return(y);
12553                     break;
12554                   case XYKRBRL:
12555                     if ((y = cmtxt("Name of realm","",&s,xxstring)) < 0)
12556                       return(y);
12557                     break;
12558                   case XYKRBKTB:
12559                     y = cmifi("Filename","",&s,&z,xxstring);
12560                     if (y != -3) {
12561                        if (y < 0)
12562                          return(y);
12563                        if (z) {
12564                          printf("?Wildcards not allowed\n");
12565                          return(-9);
12566                        }
12567                     }
12568                     break;
12569                   case XYKRBCC:
12570                     if ((y = cmofi("Filename","",&s,xxstring)) < 0)
12571                       return(y);
12572                     break;
12573                   case XYKRBSRV:
12574                     if ((y = cmtxt("Name of service to use in ticket",
12575                                    (kv == 4 ? "rcmd" : "host"),
12576                                    &s,
12577                                    xxstring
12578                                    )) < 0)
12579                       return(y);
12580                     break;
12581                   case XYKRBK5K4:
12582                     if (kv == 5) {
12583                         if ((y = seton(&krb5_d_getk4)) < 0)
12584                           return(y);
12585                     } else {
12586                         return(-9);
12587                     }
12588                     break;
12589                   case XYKRBPRM:        /* Prompt */
12590                     if ((z = cmkey(krbprmtab,2,"","",xxstring)) < 0)
12591                       return(z);
12592                     if ((y = cmtxt((z == KRB_PW_PRM) ?
12593   "Text of prompt;\nmay contain \"%s\" to be replaced by principal name" :
12594   "Text of prompt",
12595                                    "",
12596                                    &s,
12597                                    xxstring
12598                                    )
12599                          ) < 0)
12600                       return(y);
12601                     break;
12602                 }
12603                 ckstrncpy(line,s,LINBUFSIZ);
12604                 s = line;
12605                 if ((y = cmcfm()) < 0)
12606                   return(y);
12607 #ifdef IKSD
12608                 if (inserver &&
12609 #ifdef IKSDCONF
12610                     iksdcf
12611 #else /* IKSDCONF */
12612                     1
12613 #endif /* IKSDCONF */
12614                     )
12615                   return(success = 0);
12616 #endif /* IKSD */
12617
12618                 switch (x) {            /* Copy value to right place */
12619                   case XYKRBLIF:        /* Lifetime */
12620                     if (kv == 4)
12621                       krb4_d_lifetime = z;
12622                     else
12623                       krb5_d_lifetime = z;
12624                     break;
12625                   case XYKRBRNW:
12626                     if (kv == 5)
12627                       krb5_d_renewable = z;
12628                     break;
12629                   case XYKRBPR:         /* Principal */
12630                     s = brstrip(s);     /* Strip braces around. */
12631                     if (kv == 4)
12632                       makestr(&krb4_d_principal,s);
12633                     else
12634                       makestr(&krb5_d_principal,s);
12635                     break;
12636                   case XYKRBINS:        /* Instance */
12637                     if (kv == 4)
12638                       makestr(&krb4_d_instance,s);
12639                     else
12640                       makestr(&krb5_d_instance,s);
12641                     break;
12642                   case XYKRBRL:         /* Realm */
12643                     if (kv == 4)
12644                       makestr(&krb4_d_realm,s);
12645                     else
12646                       makestr(&krb5_d_realm,s);
12647                     break;
12648                   case XYKRBKTB:        /* Key Table */
12649                     if (kv == 4)
12650                       makestr(&k4_keytab,s);
12651                     else
12652                       makestr(&k5_keytab,s);
12653                     break;
12654                   case XYKRBCC:         /* Credentials cache */
12655                     makestr(&krb5_d_cc,s);
12656                     break;
12657                   case XYKRBSRV:        /* Service Name */
12658                     if (kv == 4)
12659                       makestr(&krb4_d_srv,s);
12660                     else
12661                       makestr(&krb5_d_srv,s);
12662                     break;
12663                   case XYKRBDEL:
12664                     if (kv == 5)
12665                       krb5_autodel = z;
12666                     else
12667                       krb4_autodel = z;
12668                     break;
12669                   case XYKRBPRM:        /* Prompt */
12670                     s = brstrip(s);
12671                     switch (z) {
12672                       case KRB_PW_PRM: { /* Password */
12673                           /* Check that there are no more than */
12674                           /* two % fields and % must followed by 's'. */
12675                           int i,n,len;
12676                           len = strlen(s);
12677                           for (i = 0, n = 0; i < len; i++) {
12678                               if (s[i] == '%') {
12679                                   if (s[i+1] != '%') {
12680                                       if (s[i+1] != 's') {
12681                                           printf(
12682                                            "Only %%s fields are permitted.\n"
12683                                                  );
12684                                           return(-9);
12685                                       }
12686                                       if (++n > 2) {
12687                                           printf(
12688                                       "Only two %%s fields are permitted.\n");
12689                                           return(-9);
12690                                       }
12691                                   }
12692                                   i++;
12693                               }
12694                           }
12695                           if (kv == 5)
12696                             makestr(&k5pwprompt,s);
12697                           else
12698                             makestr(&k4pwprompt,s);
12699                           break;
12700                       }
12701                       case KRB_PR_PRM: { /* Principal */
12702                           /* Check to make sure there are no % fields */
12703                           int i,len;
12704                           len = strlen(s);
12705                           for (i = 0; i < len; i++) {
12706                               if (s[i] == '%') {
12707                                   if (s[i+1] != '%') {
12708                                       printf(
12709                                   "%% fields are not used in this command.\n");
12710                                       return(-9);
12711                                   }
12712                                   i++;
12713                               }
12714                           }
12715                           if (kv == 5)
12716                             makestr(&k5prprompt,s);
12717                           else
12718                             makestr(&k4prprompt,s);
12719                           break;
12720                       }
12721                     }
12722                 }
12723                 break;
12724             }
12725 #endif /* CK_KERBEROS */
12726 #ifdef CK_SRP
12727             case AUTH_SRP: {
12728                 if ((x = cmkey(srptab, nsrptab,
12729                                "SRP parameter","",xxstring)) < 0) {
12730                     return(x);
12731                 }
12732                 s = "";
12733                 switch (x) {
12734                   case XYSRPPRM:        /* Prompt */
12735                     if ((z = cmkey(srpprmtab,1,"","",xxstring)) < 0)
12736                       return(z);
12737                     if ((y = cmtxt(
12738   "Text of prompt;\nmay contain one \"%s\" to be replaced by the username",
12739                                    "",
12740                                    &s,
12741                                    xxstring
12742                                    )
12743                          ) < 0)
12744                       return(y);
12745                     break;
12746                 }
12747                 ckstrncpy(line,s,LINBUFSIZ);
12748                 s = line;
12749                 if ((y = cmcfm()) < 0)
12750                   return(y);
12751                 switch (x) {            /* Copy value to right place */
12752                   case XYSRPPRM:        /* Prompt */
12753                     s = brstrip(s);
12754                     switch (z) {
12755                       case SRP_PW_PRM: { /* Password */
12756                           /* Check %s fields */
12757                           int i,n,len;
12758                           len = strlen(s);
12759                           for (i = 0, n = 0; i < len; i++) {
12760                               if (s[i] == '%') {
12761                                   if (s[i+1] != '%') {
12762                                       if (s[i+1] != 's') {
12763                                           printf(
12764                                           "Only %%s fields are permitted.\n");
12765                                           return(-9);
12766                                       }
12767                                       if (++n > 1) {
12768                                           printf(
12769                                        "Only one %%s field is permitted.\n");
12770                                           return(-9);
12771                                       }
12772                                   }
12773                                   i++;
12774                               }
12775                           }
12776                           makestr(&srppwprompt,s);
12777                           break;
12778                       }
12779                     }
12780                 }
12781                 break;
12782             }
12783 #endif /* CK_SRP */
12784 #ifdef CK_SSL
12785             case AUTH_SSL:
12786             case AUTH_TLS: {
12787                 if ((z = cmkey(ssltab, nssltab,
12788                            (x == AUTH_SSL ? "SSL parameter" : "TLS parameter"),
12789                            "",xxstring)) < 0)
12790                   return(z);
12791                 s = "";
12792                 switch (z) {
12793                   case XYSSLRCFL:       /* SSL/TLS RSA Certs file */
12794                   case XYSSLRCCF:       /* SSL/TLS RSA Certs Chain file */
12795                   case XYSSLRKFL:       /* SSL/TLS RSA Key File */
12796                   case XYSSLDCFL:       /* SSL/TLS DSA Certs file */
12797                   case XYSSLDCCF:       /* SSL/TLS DSA Certs Chain file */
12798                   case XYSSLDKFL:       /* SSL/TLS DH Key File */
12799                   case XYSSLDPFL:       /* SSL/TLS DH Param File */
12800                   case XYSSLCRL:        /* SSL/TLS CRL File */
12801                   case XYSSLVRFF:       /* SSL/TLS Verify File */
12802                   case XYSSLRND:        /* SSL/TLS Random File */
12803                     y = cmifi("Filename","",&s,&x,xxstring);
12804                     if (y != -3) {
12805                         if (y < 0)
12806                           return(y);
12807                         if (x) {
12808                             printf("?Wildcards not allowed\n");
12809                             return(-9);
12810                         }
12811                     }
12812                     ckstrncpy(line,s,LINBUFSIZ);
12813                     s = line;
12814                     s = brstrip(s);
12815                     if ((y = cmcfm()) < 0)
12816                       return(y);
12817                     switch (z) {
12818                       case XYSSLRCFL:   /* SSL/TLS RSA Certs file */
12819                         if (!s[0] && ssl_rsa_cert_file) {
12820                             free(ssl_rsa_cert_file);
12821                             ssl_rsa_cert_file = NULL;
12822                         } else if (s[0]) {
12823                             makestr(&ssl_rsa_cert_file,s);
12824                             if (!ssl_rsa_key_file)
12825                               makestr(&ssl_rsa_key_file,s);
12826                         }
12827                         break;
12828                       case XYSSLRCCF:   /* SSL/TLS RSA Certs Chain file */
12829                           if (!s[0] && ssl_rsa_cert_chain_file) {
12830                               free(ssl_rsa_cert_chain_file);
12831                               ssl_rsa_cert_chain_file = NULL;
12832                           } else if (s[0]) {
12833                               makestr(&ssl_rsa_cert_chain_file,s);
12834                           }
12835                           break;
12836                       case XYSSLRKFL:   /* SSL/TLS RSA Key File */
12837                         if (!s[0] && ssl_rsa_key_file) {
12838                             free(ssl_rsa_key_file);
12839                             ssl_rsa_key_file = NULL;
12840                         } else if (s[0]) {
12841                             makestr(&ssl_rsa_key_file,s);
12842                         }
12843                         break;
12844                       case XYSSLDCFL:   /* SSL/TLS DSA Certs file */
12845                         if (!s[0] && ssl_dsa_cert_file) {
12846                             free(ssl_dsa_cert_file);
12847                             ssl_dsa_cert_file = NULL;
12848                         } else if (s[0]) {
12849                             makestr(&ssl_dsa_cert_file,s);
12850                             if (!ssl_dh_key_file)
12851                               makestr(&ssl_dh_key_file,s);
12852                         }
12853                         break;
12854                       case XYSSLDCCF:   /* SSL/TLS DSA Certs Chain file */
12855                           if (!s[0] && ssl_dsa_cert_chain_file) {
12856                               free(ssl_dsa_cert_chain_file);
12857                               ssl_dsa_cert_chain_file = NULL;
12858                           } else if (s[0]) {
12859                               makestr(&ssl_dsa_cert_chain_file,s);
12860                           }
12861                           break;
12862                       case XYSSLDKFL:   /* SSL/TLS DH Key File */
12863                         if (!s[0] && ssl_dh_key_file) {
12864                             free(ssl_dh_key_file);
12865                             ssl_dh_key_file = NULL;
12866                         } else if (s[0]) {
12867                             makestr(&ssl_dh_key_file,s);
12868                         }
12869                         break;
12870                       case XYSSLDPFL:   /* SSL/TLS DH Param File */
12871                         if (!s[0] && ssl_dh_param_file) {
12872                             free(ssl_dh_param_file);
12873                             ssl_dh_param_file = NULL;
12874                         } else if (s[0]) {
12875                             makestr(&ssl_dh_param_file,s);
12876                         }
12877                         break;
12878                       case XYSSLCRL:    /* SSL/TLS CRL File */
12879                         if (!s[0] && ssl_crl_file) {
12880                             free(ssl_crl_file);
12881                             ssl_crl_file = NULL;
12882                         } else if (s[0]) {
12883                             makestr(&ssl_crl_file,s);
12884                         }
12885                         break;
12886                       case XYSSLVRFF:   /* SSL/TLS Verify File */
12887                         if (!s[0] && ssl_verify_file) {
12888                             free(ssl_verify_file);
12889                             ssl_verify_file = NULL;
12890                         } else if (s[0]) {
12891                             makestr(&ssl_verify_file,s);
12892                         }
12893                         break;
12894                       case XYSSLRND:    /* SSL/TLS Random File */
12895                         if (!s[0] && ssl_rnd_file) {
12896                             free(ssl_rnd_file);
12897                             ssl_rnd_file = NULL;
12898                         } else if (s[0]) {
12899                             makestr(&ssl_rnd_file,s);
12900                         }
12901                         break;
12902                     }
12903                     break;
12904
12905                   case XYSSLCRLD:
12906                   case XYSSLVRFD: {
12907                     char * d = NULL;
12908                     if (z == XYSSLVRFD)
12909                       d= getenv("SSL_CERT_DIR");
12910                     if (d == NULL)
12911                         d = "";
12912                     if ((y = cmdir("Directory",d,&s,xxstring)) < 0)
12913                       if (y != -3)
12914                         return(y);
12915                     ckstrncpy(line,s,LINBUFSIZ);
12916                     s = line;
12917                     s = brstrip(s);
12918                     if ((y = cmcfm()) < 0)
12919                       return(y);
12920                     switch(z) {
12921                       case XYSSLCRLD:
12922                         if (!s[0] && ssl_crl_dir) {
12923                             free(ssl_crl_dir);
12924                             ssl_crl_dir = NULL;
12925                         } else if (s[0]) {
12926                             makestr(&ssl_crl_dir,s);
12927                         }
12928                         break;
12929                       case XYSSLVRFD:
12930                         if (!s[0] && ssl_verify_dir) {
12931                             free(ssl_verify_dir);
12932                             ssl_verify_dir = NULL;
12933                         } else if (s[0]) {
12934                             makestr(&ssl_verify_dir,s);
12935                         }
12936                         break;
12937                     }
12938                     break;
12939                   }
12940                   case XYSSLCOK:        /* SSL/TLS Certs-Ok flag */
12941                     if ((y = seton(&ssl_certsok_flag)) < 0)
12942                       return(y);
12943                     break;
12944                   case XYSSLDBG:                /* SSL/TLS Debug flag */
12945                     if ((y = seton(&ssl_debug_flag)) < 0)
12946                       return(y);
12947                     break;
12948                   case XYSSLON:         /* SSL/TLS Only flag */
12949                     switch (x) {
12950                       case AUTH_SSL:
12951                         if ((y = seton(&ssl_only_flag)) < 0)
12952                           return(y);
12953                         break;
12954                       case AUTH_TLS:
12955                         if ((y = seton(&tls_only_flag)) < 0)
12956                           return(y);
12957                         break;
12958                     }
12959                     break;
12960                   case XYSSLVRB:        /* SSL/TLS Verbose flag */
12961                     if ((y = seton(&ssl_verbose_flag)) < 0)
12962                       return(y);
12963                     break;
12964                   case XYSSLVRF:        /* SSL/TLS Verify flag */
12965                     if ((x = cmkey(sslvertab, nsslvertab,
12966                                    "SSL/TLS verify mode",
12967                                    "peer-cert",xxstring)) < 0)
12968                       return(x);
12969                     if ((y = cmcfm()) < 0)
12970                       return(y);
12971                     ssl_verify_flag = x;
12972                     break;
12973                   case XYSSLDUM:
12974                     if ((y = seton(&ssl_dummy_flag)) < 0)
12975                       return(y);
12976                     break;
12977                   case XYSSLCL: {               /* SSL/TLS Cipher List */
12978 #ifdef COMMENT
12979                       /* This code is used to generate a colon delimited */
12980                       /* list of the ciphers currently in use to be used */
12981                       /* as the default for cmtxt().  However, a better  */
12982                       /* default is simply the magic keyword "ALL".      */
12983                       CHAR def[1024] = "";
12984                       if (ssl_con != NULL) {
12985                           CHAR * p = NULL, *q = def;
12986                           int i, len;
12987
12988                           for (i = 0; ; i++) {
12989                               p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
12990                               if (p == NULL)
12991                                 break;
12992                               len = strlen(p);
12993                               if (q+len+1 >= def+1024)
12994                                 break;
12995                               if (i != 0)
12996                                 *q++ = ':';
12997                               strcpy(q,p);
12998                               q += len;
12999                           }
13000                       }
13001 #endif /* COMMENT */
13002                       char * p = getenv("SSL_CIPHER");
13003                       if (!p)
13004                         p = "ALL";
13005                       if ((y = cmtxt(
13006                     "Colon-delimited list of ciphers or ALL (case-sensitive)",
13007                                      p,
13008                                      &s,
13009                                      xxstring
13010                                      )
13011                            ) < 0)
13012                         return(y);
13013                       makestr(&ssl_cipher_list,s);
13014                       if (ssl_con == NULL) {
13015                           SSL_library_init();
13016                           ssl_ctx = (SSL_CTX *)
13017                             SSL_CTX_new((SSL_METHOD *)TLSv1_method());
13018                           if (ssl_ctx != NULL)
13019                             ssl_con= (SSL *) SSL_new(ssl_ctx);
13020                       }
13021                       if (ssl_con) {
13022                           SSL_set_cipher_list(ssl_con,ssl_cipher_list);
13023                       }
13024                       break;
13025                   }
13026                 }
13027                 break;
13028             }
13029 #endif /* CK_SSL */
13030             default:
13031               break;
13032           }
13033           return(success = 1);
13034       }
13035 #endif /* CK_AUTHENTICATION */
13036
13037 #ifndef NOSPL
13038       case XYFUNC:
13039         if ((x = cmkey(functab,nfunctab,"","diagnostics",xxstring)) < 0)
13040           return(x);
13041         switch (x) {
13042           case FUNC_DI: return(seton(&fndiags));
13043           case FUNC_ER: return(seton(&fnerror));
13044           default:      return(-2);
13045         }
13046 #endif /* NOSPL */
13047
13048       case XYSLEEP:                     /* SET SLEEP / PAUSE */
13049         if ((x = cmkey(sleeptab,1,"","cancellation",xxstring)) < 0)
13050           return(x);
13051         return(seton(&sleepcan));
13052
13053       case XYCD:                        /* SET CD */
13054         if ((x = cmkey(cdtab,ncdtab,"","",xxstring)) < 0)
13055           return(x);
13056         switch (x) {
13057           case XYCD_H: {                /* SET CD HOME */
13058               extern char * myhome;
13059               if ((y = cmdir("Directory name",zhome(),&s,xxstring)) < 0)
13060                 return(y);
13061               makestr(&myhome,s);
13062               return(success = 1);
13063           }
13064           case XYCD_M:                  /* SET CD MESSAGE */
13065             if ((x = cmkey(cdmsg,ncdmsg,"","",xxstring)) < 0)
13066               return(x);
13067             if (x == 2) {               /* CD MESSAGE FILE */
13068                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
13069                   return(x);
13070                 if (!*s) {
13071                     s = NULL;
13072 #ifndef NOXFER
13073                     srvcdmsg = 0;
13074 #endif /* NOXFER */
13075                 }
13076                 makestr(&cdmsgstr,s);
13077                 makelist(cdmsgstr,cdmsgfile,8);
13078                 return(success = 1);
13079             }
13080
13081             if ((y = cmcfm()) < 0) return(y); /* CD-MESSAGE ON/OFF */
13082 #ifndef NOXFER
13083             if (x > 0)
13084               srvcdmsg |= 2;
13085             else
13086               srvcdmsg &= 1;
13087 #endif /* NOXFER */
13088             return(success = 1);
13089
13090           case XYCD_P: {                /* SET CD PATH */
13091               extern char * ckcdpath;
13092               if ((x = cmtxt("CD PATH string","",&s,xxstring)) < 0)
13093                 return(x);
13094               makestr(&ckcdpath,s);
13095               return(success = 1);
13096           }
13097         }
13098
13099 #ifndef NOLOCAL
13100 #ifdef STOPBITS
13101       case XYSTOP:                      /* STOP-BITS */
13102         if ((x = cmkey(stoptbl,2,"Stop bits for serial device","",
13103                        xxstring)) < 0)
13104           return(x);
13105         if ((y = cmcfm()) < 0)
13106           return(y);
13107         if (x > 0 && x < 3) {
13108             stopbits = x;
13109 #ifdef TN_COMPORT
13110             if (network && istncomport()) {
13111                 tnsettings(-1, x);
13112                 return(success = 1);
13113             }
13114 #endif /* TN_COMPORT */
13115 #ifdef HWPARITY
13116             return(success = 1);
13117 #else /* HWPARITY */
13118             return(-2);
13119 #endif /* HWPARITY */
13120         } else
13121           return(-2);
13122 #endif /* STOPBITS */
13123
13124       case XYDISC: {
13125           extern int clsondisc;
13126           return(seton(&clsondisc));
13127       }
13128
13129       case XYSERIAL: {
13130           /* char c; */
13131           extern int cmask;
13132           if ((x = cmkey(sertbl,nsertbl,
13133                          "Serial device character size, parity, and stop bits",
13134                          "8N1", xxstring)) < 0)
13135             return(x);
13136           ckstrncpy(line,atmbuf,LINBUFSIZ); /* Associated keyword string */
13137           s = line;
13138           if ((y = cmcfm()) < 0)
13139             return(y);
13140           ckstrncpy(line,sernam[x],LINBUFSIZ);
13141           s = line;
13142           if (s[0] != '8' && s[0] != '7') /* Char size */
13143             return(-2);
13144           else
13145             z = s[0] - '0';
13146           if (isupper(s[1]))            /* Parity */
13147             s[1] = tolower(s[1]);
13148           if (s[2] != '1' && s[2] != '2') /* Stop bits */
13149             return(-2);
13150           else
13151             stopbits = s[2] - '0';
13152           if (z == 8) {                 /* 8 bits + parity (or not) */
13153               parity = 0;               /* Set parity */
13154               hwparity = (s[1] == 'n') ? 0 : s[1];
13155               setcmask(8);              /* Also set TERM BYTESIZE to 8 */
13156           } else {                      /* 7 bits plus parity */
13157               parity = (s[1] == 'n') ? 0 : s[1];
13158               hwparity = 0;
13159               setcmask(7);              /* Also set TERM BYTESIZE to 7 */
13160           }
13161 #ifdef TN_COMPORT
13162           if (network && !istncomport())
13163             tnsettings(parity, stopbits);
13164 #endif /* TN_COMPORT */
13165
13166           return(success = 1);          /* from SET SERIAL */
13167       }
13168
13169       case XYOPTS: {                    /* SET OPTIONS */
13170           extern int setdiropts();
13171           extern int settypopts();
13172 #ifdef CKPURGE
13173           extern int setpurgopts();
13174 #endif /* CKPURGE */
13175           if ((x = cmkey(optstab,noptstab,"for command","", xxstring)) < 0)
13176             return(x);
13177           switch (x) {
13178 #ifndef NOFRILLS
13179             case XXDEL:
13180               return(setdelopts());
13181 #endif /* NOFRILLS */
13182             case XXDIR:
13183               return(setdiropts());
13184             case XXTYP:
13185               return(settypopts());
13186 #ifdef CKPURGE
13187             case XXPURGE:
13188               return(setpurgopts());
13189 #endif /* CKPURGE */
13190             default:
13191               return(-2);
13192           }
13193       }
13194 #endif /* NOLOCAL */
13195 #ifndef NOXFER
13196       case XYQ8FLG: {
13197           extern int q8flag;
13198           return(seton(&q8flag));
13199       }
13200       case XYTIMER: {
13201           extern int asktimer;
13202           y = cmnum("Time limit for ASK command, seconds","0",10,&x,xxstring);
13203 #ifdef QNX16
13204           return(setnum(&asktimer,x,y,32767));
13205 #else
13206           return(setnum(&asktimer,x,y,86400));
13207 #endif /* QNX16 */
13208       }
13209       case XYFACKB: {
13210           extern int fackbug;
13211           return(seton(&fackbug));
13212       }
13213 #endif /* NOXFER */
13214
13215       case XYHINTS:
13216         return(seton(&hints));
13217
13218 #ifndef NOSPL
13219       case XYEVAL: {
13220           extern int oldeval;
13221           if ((x = cmkey(oldnew,2,"","", xxstring)) < 0)
13222             return(x);
13223           if ((y = cmcfm()) < 0)
13224             return(y);
13225           oldeval = x;
13226           return(success = 1);
13227       }
13228 #endif /* NOSPL */
13229
13230 #ifndef NOXFER
13231       case XYFACKP: {
13232           extern int fackpath;
13233           return(seton(&fackpath));
13234       }
13235 #endif /* NOXFER */
13236
13237       case XYQNXPL: {
13238           extern int qnxportlock;
13239           return(seton(&qnxportlock));
13240       }
13241
13242 #ifndef NOCMDL
13243 #ifdef IKSD
13244       case XYIKS: {
13245           int setiks();
13246           return(setiks());
13247       }
13248 #endif /* IKSD */
13249 #endif /* NOCMDL */
13250
13251 #ifdef CKROOT
13252       case XYROOT:
13253         return(dochroot());
13254 #endif /* CKROOT */
13255
13256 #ifndef NOSPL
13257 #ifndef NOSEXP
13258       case XYSEXP: {
13259           if ((x = cmkey(sexptab,3,"","", xxstring)) < 0)
13260             return(x);
13261           switch (x) {
13262             case 0:
13263               if ((x = cmkey(ooatab,3,"","automatic", xxstring)) < 0)
13264                 return(x);
13265               if ((y = cmcfm()) < 0)
13266                 return(y);
13267               sexpecho = x;
13268               break;
13269             case 1: {
13270                 int i, xx;
13271                 xx = sexpmaxdep;
13272                 if ((y = cmnum("Maximum recursion depth",
13273                                "1000",10,&x,xxstring)) < 0)
13274                   return(y);
13275                 z = setnum(&sexpmaxdep,x,y,-1);
13276                 if (z < 0)
13277                   return(z);
13278                 if (sxresult) {         /* Free old stack if allocated */
13279                     for (i = 0; i < xx; i++)
13280                       if (sxresult[i]) free(sxresult[i]);
13281                     free((char *)sxresult);
13282                     if (sxrlen) free((char *)sxrlen);
13283                     sxresult = NULL;
13284                     sxrlen = NULL;
13285                 }
13286                 break;
13287             }
13288             case 2:
13289               return(seton(&sexptrunc));
13290           }
13291           return(success = 1);
13292       }
13293 #endif /* NOSEXPL */
13294 #endif /* NOSPL */
13295
13296 #ifdef NEWFTP
13297       case XYGPR: {
13298           extern struct keytab gprtab[];
13299           extern int ftpget;
13300           if ((x = cmkey(gprtab,3,"","kermit", xxstring)) < 0)
13301             return(x);
13302           if ((y = cmcfm()) < 0)
13303             return(y);
13304           ftpget = x;
13305           return(success = 1);
13306       }
13307 #endif /* NEWFTP */
13308
13309 #ifdef ANYSSH
13310       case XYSSH:
13311         return(dosetssh());
13312 #endif /* ANYSHH */
13313
13314 #ifdef SFTP_BUILTIN
13315       case XYSFTP:
13316         return(dosetsftp());
13317 #endif /* SFTP_BUILTIN */
13318
13319 #ifdef LOCUS
13320       case XYLOCUS:
13321           if ((x = cmkey(locustab,nlocustab,"",
13322 #ifdef KUI
13323                          "ask"
13324 #else
13325                          "auto"
13326 #endif /* KUI */
13327                          ,xxstring)) < 0)
13328             return(x);
13329           if ((y = cmcfm()) < 0)
13330             return(y);
13331           if (x == 2 || x == 3) {       /* AUTO or ASK */
13332               setautolocus(x - 1);      /* Two forms of automatic locusing */
13333               /* setlocus(1,0); */      /* we're not changing the locus here */
13334           } else {                      /* LOCAL or REMOTE */
13335               setautolocus(0);          /* No automatic Locus changing */
13336               setlocus(x,0);            /* Set Locus as requested */
13337           }
13338           return(success = 1);
13339 #endif /* LOCUS */
13340
13341 #ifdef KUI
13342       case XYGUI:
13343         return(setgui());
13344 #endif /* KUI */
13345
13346 #ifndef NOFRILLS
13347 #ifndef NORENAME
13348       case XY_REN:                      /* SET RENAME */
13349         return(setrename());
13350 #endif  /* NORENAME */
13351 #endif  /* NOFRILLS */
13352
13353 #ifndef NOPUSH
13354 #ifdef CK_REDIR
13355 #ifndef NOXFER
13356       case XYEXTRN:                     /* SET EXTERNAL-PROTOCOL */
13357         return(setextern());
13358 #endif  /* NOXFER */
13359 #endif  /* CK_REDIR */
13360 #endif  /* NOPUSH */
13361
13362 #ifndef NOSPL
13363       case XYVAREV:                     /* SET VARIABLE-EVALUATION */
13364         return(setvareval());
13365 #endif  /* NOSPL */
13366
13367       default:
13368          if ((x = cmcfm()) < 0) return(x);
13369          printf("Not implemented - %s\n",cmdbuf);
13370          return(success = 0);
13371     }
13372 }
13373
13374 /*
13375   H U P O K  --  Is Hangup OK?
13376
13377   Issues a warning and gets OK from user depending on whether a connection
13378   seems to be open and what the SET EXIT WARNING setting is.  Returns:
13379     0 if not OK to hang up or exit (i.e. user said No);
13380     nonzero if OK.
13381   Argument x is used to differentiate the EXIT command from SET LINE / HOST.
13382 */
13383 int
13384 hupok(x) int x; {                       /* Returns 1 if OK, 0 if not OK */
13385     int y, z = 1;
13386     extern int exithangup;
13387 #ifdef VMS
13388     extern int batch;
13389
13390     if (batch)                          /* No warnings in batch */
13391       return(1);
13392 #else
13393 #ifdef UNIX
13394     if (backgrd)                        /* No warnings in background */
13395       return(1);
13396 #endif /* UNIX */
13397 #endif /* VMS */
13398
13399 #ifndef K95G
13400     debug(F101,"hupok local","",local);
13401
13402     if (!local)                         /* No warnings in remote mode */
13403       return(1);
13404 #endif /* K95G */
13405
13406     if (x == 0 && exithangup == 0)      /* EXIT and EXIT HANGUP is OFF */
13407       return(1);
13408
13409     debug(F101,"hupok x","",x);
13410     debug(F101,"hupok xitwarn","",xitwarn);
13411     debug(F101,"hupok network","",network);
13412     debug(F101,"hupok haveline","",haveline);
13413
13414     if ((local && xitwarn) ||           /* Is a connection open? */
13415         (!x && xitwarn == 2)) {         /* Or Always give warning on EXIT */
13416         int needwarn = 0;
13417         char warning[256];
13418
13419         if (network) {
13420             if (ttchk() >= 0)
13421               needwarn = 1;
13422             /* A connection seems to be open but it can't possibly be */
13423             if (!haveline)
13424               needwarn = 0;
13425             if (needwarn) {
13426                 if (strcmp(ttname,"*"))
13427                     ckmakmsg(warning,256,
13428                               " A network connection to ",ttname,
13429                               " might still be active.\n",NULL);
13430                 else
13431                   ckstrncpy(warning,
13432                    " An incoming network connection might still be active.\n",
13433                              256);
13434             }
13435         } else {                        /* Serial connection */
13436             if (carrier == CAR_OFF)     /* SET CARRIER OFF */
13437               needwarn = 0;             /* so we don't care about carrier. */
13438             else if ((y = ttgmdm()) >= 0) /* else, get modem signals */
13439               needwarn = (y & BM_DCD);  /* Check for carrier */
13440             else                        /* If we can't get modem signals... */
13441               needwarn = (ttchk() >= 0);
13442             /* A connection seems to be open but it can't possibly be */
13443             if (!haveline || !exithangup)
13444               needwarn = 0;
13445             if (needwarn)
13446                 ckmakmsg(warning,256,
13447                      " A serial connection might still be active on ",
13448                      ttname,".\n",NULL);
13449         }
13450
13451 /* If a warning was issued, get user's permission to EXIT. */
13452
13453         if (needwarn || (!x && xitwarn == 2
13454 #ifndef K95G
13455                         && local
13456 #endif /* K95G */
13457                          )) {
13458             if ( !needwarn )
13459                 ckstrncpy(warning, "No active connections", 256);
13460
13461 #ifdef COMMENT
13462             printf("%s",warning);
13463             z = getyesno(x ? "OK to close? " : "OK to exit? ",0);
13464             debug(F101,"hupok getyesno","",z);
13465             if (z < -3) z = 0;
13466 #else
13467             z = uq_ok(warning,
13468                       x ? "OK to close? " : "OK to exit? ",
13469                       3,
13470                       NULL,
13471                       0
13472                       );
13473             debug(F101,"hupok uq_ok","",z);
13474             if (z < 0) z = 0;
13475 #endif /* COMMENT */
13476         }
13477     }
13478     return(z);
13479 }
13480
13481 #ifndef NOSHOW
13482 VOID
13483 shoctl() {                              /* SHOW CONTROL-PREFIXING */
13484 #ifdef CK_SPEED
13485     int i;
13486 #ifdef OS2
13487     int zero;
13488 #endif /* OS2 */
13489     printf(
13490 "\ncontrol quote = %d, applied to (0 = unprefixed, 1 = prefixed):\n\n",
13491            myctlq);
13492 #ifdef OS2
13493 #ifndef UNPREFIXZERO
13494     zero = ctlp[0];
13495     if (protocol == PROTO_K)            /* Zero can't be unprefixed */
13496       ctlp[0] = 1;                      /* for Kermit */
13497 #endif /* UNPREFIXZERO */
13498 #endif /* OS2 */
13499     for (i = 0; i < 16; i++) {
13500         printf("  %3d: %d   %3d: %d ",i,ctlp[i], i+16, ctlp[i+16]);
13501         if (i == 15)
13502           printf("  127: %d",ctlp[127]);
13503         else
13504           printf("        ");
13505         printf("  %3d: %d   %3d: %d ",i+128,ctlp[i+128], i+144, ctlp[i+144]);
13506         if (i == 15)  printf("  255: %d",ctlp[255]);
13507         printf("\n");
13508     }
13509     printf("\n");
13510 #ifndef UNPREFIXZERO
13511 #ifdef OS2
13512     ctlp[0] = zero;
13513 #endif /* OS2 */
13514 #endif /* UNPREFIXZERO */
13515
13516 #endif /* CK_SPEED */
13517 }
13518
13519 #ifndef NOXFER
13520 VOID
13521 shodbl() {                              /* SHOW DOUBLE/IGNORE */
13522 #ifdef CKXXCHAR
13523     int i, n = 0;
13524     printf("\nSET SEND DOUBLE characters:\n");
13525     for (i = 0; i < 255; i++) {
13526         if (dblt[i] & 2) {
13527             n++;
13528             printf(" %d", i);
13529         }
13530     }
13531     if (n == 0)
13532       printf(" (none)");
13533     n = 0;
13534     printf("\nSET RECEIVE IGNORE characters:\n");
13535     for (i = 0; i < 255; i++) {
13536         if (dblt[i] & 1) {
13537             n++;
13538             printf(" %d", i);
13539         }
13540     }
13541     if (n == 0)
13542       printf(" (none)");
13543     printf("\n\n");
13544 #endif /* CKXXCHAR */
13545 }
13546 #endif /* NOXFER */
13547 #endif /* NOSHOW */
13548
13549 #ifndef NOPUSH
13550 #ifdef CK_REXX
13551 /*
13552   Rexx command.  Note, this is not OS/2-specific, because Rexx also runs
13553   on other systems where C-Kermit also runs, like the Amiga.
13554 */
13555 #define REXBUFL 100                     /* Change this if neccessary */
13556 char rexxbuf[REXBUFL] = { '\0' };       /* Rexx's return value (string) */
13557
13558 int
13559 dorexx() {
13560     int x, y;
13561     char *rexxcmd;
13562
13563         if ((x = cmtxt("Rexx command","",&rexxcmd,xxstring)) < 0)
13564           return(x);
13565
13566 #ifdef IKSD
13567     if (inserver) {
13568         printf("?Sorry, command disabled.\r\n");
13569         return(success = 0);
13570     }
13571 #endif /* IKSD */
13572 #ifdef CK_APC
13573     /* Don't let this be set remotely */
13574     if (apcactive == APC_LOCAL ||
13575         apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
13576       return(success = 0);
13577 #endif /* CK_APC */
13578
13579         ckstrncpy(line,rexxcmd,LINBUFSIZ);
13580         rexxcmd = line;
13581 #ifdef OS2
13582         return(os2rexx(rexxcmd,rexxbuf,REXBUFL));
13583 #else /* !OS2 */
13584         printf("Sorry, nothing happens.\n");
13585         return(success = 0);
13586 #endif /* OS2 */
13587 }
13588 #endif /* CK_REXX */
13589 #endif /* NOPUSH */
13590 #else  /* NOICP */
13591 VOID
13592 dologend() {
13593     /* Dummy write record to connection log */
13594 }
13595 #endif /* NOICP */