home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / cku208.tar / ckuus3.c < prev    next >
C/C++ Source or Header  |  2003-03-26  |  435KB  |  13,180 lines

  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.   Author: Frank da Cruz <fdc@columbia.edu>,
  11.   Columbia University Academic Information Systems, New York City.
  12.  
  13.   Copyright (C) 1985, 2003,
  14.     Trustees of Columbia University in the City of New York.
  15.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  16.     copyright text in the ckcmai.c module for disclaimer and permissions.
  17. */
  18.  
  19. /*  SET command (but much material has been split off into ckuus7.c). */
  20.  
  21. /*
  22.   Kermit-specific includes.
  23.   Definitions here supersede those from system include files.
  24. */
  25. #include "ckcdeb.h"                     /* Debugging & compiler things */
  26. #include "ckcasc.h"                     /* ASCII character symbols */
  27. #include "ckcker.h"                     /* Kermit application definitions */
  28. #include "ckcxla.h"                     /* Character set translation */
  29. #include "ckcnet.h"                     /* Network symbols */
  30.  
  31. char pwbuf[PWBUFL+1]  = { NUL, NUL };
  32. int pwflg = 0;
  33. int pwcrypt = 0;
  34.  
  35. #ifndef NOICP
  36.  
  37. #ifdef CK_AUTHENTICATION
  38. #include "ckuath.h"
  39. #endif /* CK_AUTHENTICATION */
  40. #ifdef CK_SSL
  41. #include "ck_ssl.h"
  42. #endif /* CK_SSL */
  43. #include "ckuusr.h"                     /* User interface symbols */
  44. #ifdef OS2
  45. #include "ckcuni.h"
  46. #ifdef SSHBUILTIN
  47. #include "ckossh.h"
  48. #endif /* SSHBUILTIN */
  49. #ifdef CK_NETBIOS
  50. #include <os2.h>
  51. #ifdef COMMENT                          /* Would you believe */
  52. #undef COMMENT                          /* <os2.h> defines this ? */
  53. #endif /* COMMENT */
  54. #include "ckonbi.h"
  55. extern UCHAR NetBiosAdapter;
  56. #endif /* CK_NETBIOS */
  57. #include "ckocon.h"
  58. #include "ckokey.h"
  59. #ifndef NOTERM
  60. extern unsigned char colorcmd;  /* Command-screen colors */
  61. extern struct keytab ttyclrtab[];
  62. extern int nclrs;
  63. extern int tt_cols[], tt_rows[], tt_szchng[], tt_status[];
  64. #endif /* NOTERM */
  65. _PROTOTYP(int setprty, (void));
  66. extern char startupdir[], exedir[];
  67. extern int tt_modechg;
  68. #ifdef NT
  69. #include <windows.h>
  70. #include <tapi.h>
  71. #include "ckntap.h"                     /* Microsoft TAPI */
  72. #endif /* NT */
  73. #endif /* OS2 */
  74.  
  75. #ifndef OS2
  76. extern char * exedir;
  77. #endif /* OS2 */
  78.  
  79. #ifdef CK_RECALL
  80. extern int cm_retry;
  81. #endif /* CK_RECALL */
  82.  
  83. extern int cmdint;
  84. extern int srvidl;
  85.  
  86. #ifdef CKFLOAT
  87. extern CKFLOAT floatval;        /* (see isfloat()) */
  88. #endif /* CKFLOAT */
  89.  
  90. #ifndef NOPUSH
  91. #ifndef NOFRILLS
  92. #ifdef VMS
  93. char editor[CKMAXPATH + 1] = "edit";
  94. #else
  95. char editor[CKMAXPATH + 1] = { NUL, NUL };
  96. #endif /* VMS */
  97. char editopts[128] = { NUL, NUL };
  98. char editfile[CKMAXPATH + 1] = { NUL, NUL };
  99. #ifdef BROWSER
  100. char browser[CKMAXPATH + 1] = { NUL, NUL };
  101. char browsopts[128] = { NUL, NUL };
  102. char browsurl[4096] = { NUL, NUL };
  103. #endif /* BROWSER */
  104. #endif /*  NOFRILLS */
  105. #endif /* NOPUSH */
  106.  
  107. /* Variables */
  108.  
  109. int cmd_quoting = 1;
  110. extern int hints, xcmdsrc;
  111.  
  112. #ifdef CK_KERBEROS
  113. char * k4pwprompt = NULL;               /* Kerberos 4 password prompt */
  114. char * k4prprompt = NULL;               /* Kerberos 4 principal prompt */
  115. char * k5pwprompt = NULL;               /* Kerberos 5 password prompt */
  116. char * k5prprompt = NULL;               /* Kerberos 5 principal prompt */
  117. #endif /* CK_KERBEROS */
  118. #ifdef CK_SRP
  119. char * srppwprompt = NULL;
  120. #endif /* CK_SRP */
  121.  
  122. extern char * ckprompt, * ikprompt;     /* Default prompt */
  123. extern xx_strp xxstring;
  124.  
  125. extern char * cdmsgfile[], * cdmsgstr;
  126.  
  127. extern int
  128.   local, server, success, dest, sleepcan, inserver, flow, autoflow, binary,
  129.   parity, escape, what, turn, duplex, backgrd, hwparity, stopbits, turnch,
  130.   mdmtyp, network, quiet, nettype, carrier, debses, debtim, cdtimo, nlangs,
  131.   bgset, pflag, msgflg, cmdmsk, xsuspend, techo, pacing, xitwarn, xitsta,
  132.   outesc, cmd_cols, cmd_rows, ckxech, xaskmore, haveline, didsetlin, isguest,
  133.   mdmsav, clearrq, saveask;
  134.  
  135. extern int reliable, setreliable, matchdot, matchfifo, dir_dots;
  136.  
  137. #ifndef NOSERVER
  138.   extern int en_pri;
  139. #endif /* NOSERVER */
  140.  
  141. #ifdef IKSDCONF
  142. extern int iksdcf;
  143. #endif /* IKSDCONF */
  144. #ifdef TCPSOCKET
  145.   extern int tn_exit;
  146. #endif /* TCPSOCKET */
  147. #ifdef TNCODE
  148.   char * tn_pr_uid = NULL;
  149. #endif /* TNCODE */
  150.   extern int exitonclose;
  151.  
  152. #ifndef NOKVERBS
  153. extern int nkverbs;
  154. extern struct keytab kverbs[];
  155. #endif /* NOKVERBS */
  156.  
  157. extern int ttnproto;                    /* Network protocol */
  158.  
  159. extern char *ccntab[];                  /* Names of control chars */
  160.  
  161. #ifdef CK_APC
  162. extern int apcactive, apcstatus;
  163. #endif /* CK_APC */
  164.  
  165. #ifndef NOSCRIPT
  166. extern int secho;                       /* Whether SCRIPT cmd should echo */
  167. #endif /* NOSCRIPT */
  168.  
  169. #ifdef DCMDBUF
  170. extern char *atmbuf, *atxbuf;
  171. #else
  172. extern char atmbuf[], atxbuf[];
  173. #endif /* DCMDBUF */
  174. extern int cmflgs;
  175.  
  176. extern char psave[];
  177. extern char uidbuf[];
  178. extern int  sl_uid_saved;
  179. int DeleteStartupFile = 0;
  180.  
  181. extern int cmdlvl;                      /* Overall command level */
  182.  
  183. #ifndef NOSPL
  184. _PROTOTYP( static int parsdir, (int) );
  185. char prmbuf[PWBUFL+1] = { NUL, NUL };
  186. int fndiags = 1;                        /* Function diagnostics on/off */
  187. int fnerror = 1;                        /* Function error treatment */
  188.  
  189. #ifdef DCMDBUF
  190. extern int *count, *takerr, *merror, *inpcas;
  191. #else
  192. extern int count[], takerr[], merror[], inpcas[];
  193. #endif /* DCMDBUF */
  194. extern int mecho;                       /* Macro echo */
  195. extern long ck_alarm;
  196. extern char alrm_date[], alrm_time[];
  197. #else
  198. extern int takerr[];
  199. #endif /* NOSPL */
  200.  
  201. extern int x_ifnum;
  202. extern int bigsbsiz, bigrbsiz;          /* Packet buffers */
  203.  
  204. extern long speed;                      /* Terminal speed */
  205.  
  206. extern char ttname[];                   /* Communication device name */
  207. extern char myhost[] ;
  208. extern char inidir[];                   /* Ini File directory */
  209.  
  210. #ifndef NOSETKEY
  211. extern KEY *keymap;                     /* Character map for SET KEY (1:1)  */
  212. extern MACRO *macrotab;                 /* Macro map for SET KEY (1:string) */
  213. #endif /* NOSETKEY */
  214. #ifdef OS2
  215. int wideresult;                         /* For wide OS/2 scan codes/cmnum() */
  216. #endif /* OS2 */
  217.  
  218. #ifndef NOLOCAL
  219. #ifdef OS2
  220. extern int tt_scrsize[];                /* Scrollback buffer Sizes */
  221. #endif /* OS2 */
  222. #endif /* NOLOCAL */
  223.  
  224. /* Printer settings */
  225.  
  226. extern char * printername;              /* NULL if printer not redirected */
  227. extern int printpipe;
  228. extern int noprinter;
  229. #ifdef PRINTSWI
  230. int printtimo = 0;
  231. char * printterm = NULL;
  232. char * printsep = NULL;
  233. int printertype = 0;
  234. #ifdef BPRINT
  235. int printbidi = 0;                      /* SET BPRINTER (bidirectional) */
  236. long pportspeed = 0L;                   /* Bidirection printer port speed, */
  237. int pportparity = 0;                    /*  parity, */
  238. int pportflow = FLO_KEEP;               /*  and flow control */
  239. #endif /* BPRINT */
  240. #ifdef OS2
  241. extern int txt2ps;                      /* Text2PS conversion? */
  242. extern int ps_width, ps_length;         /* Text2PS dimensions */
  243. #endif /* OS2 */
  244. #endif /* PRINTSWI */
  245.  
  246. #ifdef OS2
  247. extern int tcp_avail;                   /* Nonzero if TCP/IP is available */
  248. #ifdef DECNET
  249. extern int dnet_avail;                  /* Ditto for DECnet */
  250. #endif /* DECNET */
  251. #ifdef SUPERLAT
  252. extern int slat_avail;
  253. #endif /* SUPERLAT */
  254. #endif /* OS2 */
  255.  
  256. static struct keytab logintab[] = {
  257.     { "password", LOGI_PSW, CM_INV },
  258.     { "prompt",   LOGI_PRM, CM_INV },
  259.     { "userid",   LOGI_UID, 0 }
  260. };
  261.  
  262. #ifndef NOCSETS
  263. /* system-independent character sets, defined in ckcxla.[ch] */
  264. extern struct csinfo tcsinfo[];
  265. extern struct langinfo langs[];
  266.  
  267. /* Other character-set related variables */
  268. extern int tcharset, tslevel, language;
  269. #endif /* NOCSETS */
  270.  
  271. /* File-transfer variable declarations */
  272.  
  273. #ifndef NOXFER
  274. #ifdef CK_AUTODL
  275. extern int cmdadl;
  276. #endif /* CK_AUTODL */
  277.  
  278. #ifndef NOSERVER
  279. extern int ngetpath;
  280. extern char * getpath[];
  281. #endif /* NOSERVER */
  282.  
  283. extern struct ck_p ptab[];
  284.  
  285. extern CHAR sstate;                     /* Protocol start state */
  286. extern CHAR myctlq;                     /* Control-character prefix */
  287. extern CHAR myrptq;                     /* Repeat-count prefix */
  288.  
  289. extern int protocol, size, spsiz, spmax, urpsiz, srvtim, srvcdmsg, slostart,
  290.   srvdis, xfermode, ckdelay, keep, maxtry, unkcs, bctr, ebqflg, swcapr,
  291.   wslotr, lscapr, lscapu, spsizr, rptena, rptmin, docrc, xfrcan, xfrchr,
  292.   xfrnum, xfrbel, xfrint, srvping, g_xfermode, xfrxla;
  293.  
  294. #ifdef PIPESEND
  295. extern int usepipes;
  296. #endif /* PIPESEND */
  297.  
  298. #ifdef CKXXCHAR                         /* DOUBLE / IGNORE char table */
  299. extern int dblflag, ignflag, dblchar;
  300. extern short dblt[];
  301. #endif /* CKXXCHAR */
  302.  
  303. #ifdef CK_SPEED
  304. extern short ctlp[];                    /* Control-prefix table */
  305. extern int prefixing;
  306. static struct keytab pfxtab[] = {
  307.     "all",         PX_ALL, 0,
  308.     "cautious",    PX_CAU, 0,
  309.     "minimal",     PX_WIL, 0,
  310.     "none",        PX_NON, 0
  311. };
  312. #endif /* CK_SPEED */
  313. #endif /* NOXFER */
  314.  
  315. /* Declarations from cmd package */
  316.  
  317. #ifdef DCMDBUF
  318. extern char *cmdbuf;                    /* Command buffer */
  319. extern char *line;
  320. extern char *tmpbuf;
  321. #else
  322. extern char cmdbuf[];                   /* Command buffer */
  323. extern char line[];                     /* Character buffer for anything */
  324. extern char tmpbuf[];
  325. #endif /* DCMDBUF */
  326.  
  327. /* From main ckuser module... */
  328.  
  329. extern char *tp, *lp;                   /* Temporary buffer */
  330.  
  331. extern int tlevel;                      /* Take Command file level */
  332.  
  333. #ifndef NOLOCAL
  334. extern int sessft;                      /* Session-log file type */
  335. extern int slogts;                      /* Session-log timestamps on/off */
  336. #endif /* NOLOCAL */
  337.  
  338. char * tempdir = NULL;
  339.  
  340. #ifdef VMS
  341. int vms_msgs = 1;                       /* SET MESSAGES */
  342. extern int batch;
  343. #endif /* VMS */
  344.  
  345. /* Keyword tables for SET commands */
  346.  
  347. #ifdef CK_SPEED
  348. struct keytab ctltab[] = {
  349.     "prefixed",   1, 0,                 /* Note, the values are important. */
  350.     "unprefixed", 0, 0
  351. };
  352. #endif /* CK_SPEED */
  353.  
  354. static struct keytab oldnew[] = {
  355.     "new", 0, 0,
  356.     "old", 1, 0
  357. };
  358.  
  359. #define MCH_FIFO 1
  360. #define MCH_DOTF 2
  361. struct keytab matchtab[] = {
  362.     { "dotfile", MCH_DOTF, 0 },
  363.     { "fifo",    MCH_FIFO, 0 }
  364. };
  365. int nmatchtab = (sizeof(matchtab) / sizeof(struct keytab));
  366.  
  367. #ifndef NOSPL
  368. static struct keytab functab[] = {
  369.     "diagnostics", FUNC_DI, 0,
  370.     "error",       FUNC_ER, 0
  371. };
  372. static int nfunctab = (sizeof(functab) / sizeof(struct keytab));
  373.  
  374. struct keytab outptab[] = {             /* SET OUTPUT parameters */
  375.     "pacing", 0, 0,                     /* only one so far... */
  376.     "special-escapes", 1, 0
  377. };
  378. int noutptab = (sizeof(outptab) / sizeof(struct keytab)); /* How many */
  379. #endif /* NOSPL */
  380.  
  381. struct keytab chktab[] = {              /* Block check types */
  382.     "1", 1, 0,                          /* 1 =  6-bit checksum */
  383.     "2", 2, 0,                          /* 2 = 12-bit checksum */
  384.     "3", 3, 0,                          /* 3 = 16-bit CRC */
  385.     "4", 4, CM_INV,                     /* Same as B */
  386.     "blank-free-2", 4, 0                /* B = 12-bit checksum, no blanks */
  387. };
  388.  
  389. struct keytab rpttab[] = {              /* SET REPEAT */
  390.     "counts",    0, 0,                  /* On or Off */
  391. #ifdef COMMENT
  392.     "minimum",   1, 0,                  /* Threshhold */
  393. #endif /* COMMENT */
  394.     "prefix",    2, 0                   /* Repeat-prefix character value */
  395. };
  396.  
  397. #ifndef NOLOCAL
  398. /* For SET [ MODEM ] CARRIER, and also for SET DIAL CONNECT */
  399.  
  400. struct keytab crrtab[] = {
  401.     "automatic", CAR_AUT, 0,            /* 2 */
  402.     "off",       CAR_OFF, 0,            /* 0 */
  403.     "on",        CAR_ON,  0             /* 1 */
  404. };
  405. int ncrr = 3;
  406. #endif /* NOLOCAL */
  407.  
  408. struct keytab ooatab[] = {              /* On/Off/Auto table */
  409.     "automatic", SET_AUTO, 0,           /* 2 */
  410.     "off",       SET_OFF,  0,           /* 0 */
  411.     "on",        SET_ON,   0            /* 1 */
  412. };
  413.  
  414. struct keytab ooktab[] = {              /* On/Off/Ask table */
  415.     "ask",       2,        0,           /* 2 */
  416.     "off",       SET_OFF,  0,           /* 0 */
  417.     "on",        SET_ON,   0            /* 1 */
  418. };
  419.  
  420. struct keytab qvtab[] = {               /* Quiet/Verbose table */
  421.     "quiet", 1, 0,
  422.     "verbose", 0, 0
  423. };
  424. int nqvt = 2;
  425.  
  426. /* For SET DEBUG */
  427.  
  428. #define DEB_OFF  0
  429. #define DEB_ON   1
  430. #define DEB_SES  2
  431. #define DEB_TIM  3
  432. #define DEB_LEN  4
  433.  
  434. struct keytab dbgtab[] = {
  435.     "linelength", DEB_LEN, CM_INV,
  436.     "off",        DEB_OFF, 0,
  437.     "on",         DEB_ON,  0,
  438.     "session",    DEB_SES, 0,
  439.     "timestamps", DEB_TIM, 0
  440. };
  441. int ndbg = (sizeof(dbgtab) / sizeof(struct keytab));
  442.  
  443. #ifndef NOLOCAL
  444. /* Transmission speeds */
  445.  
  446. #ifdef TTSPDLIST /* Speed table constructed at runtime . . . */
  447.  
  448. struct keytab * spdtab = NULL;
  449. int nspd = 0;
  450.  
  451. #else
  452. /*
  453.   Note, the values are encoded in cps rather than bps because 19200 and higher
  454.   are too big for some ints.  All but 75bps are multiples of ten.  Result of
  455.   lookup in this table must be multiplied by 10 to get actual speed in bps.
  456.   If this number is 70, it must be changed to 75.  If it is 888, this means
  457.   75/1200 split speed.
  458.  
  459.   The values are generic, rather than specific to UNIX.  We can't use B75,
  460.   B1200, B9600, etc, because non-UNIX versions of C-Kermit will not
  461.   necessarily have these symbols defined.  The BPS_xxx symbols are
  462.   Kermit-specific, and are defined in ckcdeb.h or on the CC command line.
  463.  
  464.   Like all other keytabs, this one must be in "alphabetical" order,
  465.   rather than numeric order.
  466. */
  467. struct keytab spdtab[] = {
  468.     "0",      0,  CM_INV,
  469.     "110",   11,  0,
  470. #ifdef BPS_115K
  471.  "115200",11520,  0,
  472. #endif /* BPS_115K */
  473.   "1200",   120,  0,
  474. #ifdef BPS_134
  475.   "134.5",  134,  0,
  476. #endif /* BPS_134 */
  477. #ifdef BPS_14K
  478.   "14400", 1440,  0,
  479. #endif /* BPS_14K */
  480. #ifdef BPS_150
  481.   "150",     15,  0,
  482. #endif /* BPS_150 */
  483. #ifdef BPS_1800
  484.   "1800",     180,  0,
  485. #endif /* BPS_150 */
  486. #ifdef BPS_19K
  487.   "19200", 1920,  0,
  488. #endif /* BPS_19K */
  489. #ifdef BPS_200
  490.   "200",     20,  0,
  491. #endif /* BPS_200 */
  492. #ifdef BPS_230K
  493.   "230400", 23040, 0,
  494. #endif /* BPS_230K */
  495.   "2400",   240,  0,
  496. #ifdef BPS_28K
  497.   "28800", 2880,  0,
  498. #endif /* BPS_28K */
  499.   "300",     30,  0,
  500. #ifdef BPS_3600
  501.   "3600",   360,  0,
  502. #endif /* BPS_3600 */
  503. #ifdef BPS_38K
  504.   "38400", 3840,  0,
  505. #endif /* BPS_38K */
  506. #ifdef BPS_460K
  507.   "460800", 46080,  0,                  /* Need 32 bits for this... */
  508. #endif /* BPS_460K */
  509.   "4800",   480,  0,
  510. #ifdef BPS_50
  511.   "50",       5,  0,
  512. #endif /* BPS_50 */
  513. #ifdef BPS_57K
  514.   "57600", 5760,  0,
  515. #endif /* BPS_57K */
  516.   "600",     60,  0,
  517. #ifdef BPS_7200
  518.   "7200",   720,  0,
  519. #endif /* BPS_7200 */
  520. #ifdef BPS_75
  521.   "75",       7,  0,
  522. #endif /* BPS_75 */
  523. #ifdef BPS_7512
  524.   "75/1200",888,  0,                    /* Code "888" for split speed */
  525. #endif /* BPS_7512 */
  526. #ifdef BPS_76K
  527.   "76800", 7680,  0,
  528. #endif /* BPS_76K */
  529. #ifdef BPS_921K
  530.   "921600", 92160,0,                    /* Need 32 bits for this... */
  531. #endif /* BPS_921K */
  532.   "9600",   960,  0
  533. };
  534. int nspd = (sizeof(spdtab) / sizeof(struct keytab)); /* How many speeds */
  535. #endif /* TTSPDLIST */
  536.  
  537. #ifdef TN_COMPORT
  538. struct keytab tnspdtab[] = {            /* RFC 2217 TELNET COMPORT Option */
  539.     "115200", 11520,  0,                /* (add any other defined speeds) */
  540.     "1200",     120,  0,
  541.     "14400",   1440,  0,
  542.     "19200",   1920,  0,
  543.     "230400", 23040,  0,
  544.     "2400",     240,  0,
  545.     "28800",   2880,  0,
  546.     "300",       30,  0,
  547.     "38400",   3840,  0,
  548.     "460800", 46080,  0,
  549.     "4800",     480,  0,
  550.     "57600",   5760,  0,
  551.     "600",       60,  0,
  552.     "9600",     960,  0
  553. };
  554. int ntnspd = (sizeof(tnspdtab) / sizeof(struct keytab)); /* How many speeds */
  555. #endif /* TN_COMPORT */
  556. #endif /* NOLOCAL */
  557.  
  558. #ifndef NOCSETS
  559. extern struct keytab lngtab[];          /* Languages for SET LANGUAGE */
  560. extern int nlng;
  561. #endif /* NOCSETS */
  562.  
  563. #ifndef NOLOCAL
  564. /* Duplex keyword table */
  565.  
  566. struct keytab dpxtab[] = {
  567.     "full",      0, 0,
  568.     "half",      1, 0
  569. };
  570. #endif /* NOLOCAL */
  571.  
  572. /* Flow Control */
  573.  
  574. struct keytab cxtypesw[] = {
  575. #ifdef DECNET
  576.     "/decnet",         CXT_DECNET,  0,
  577. #endif /* DECNET */
  578.     "/direct-serial",  CXT_DIRECT,  0,
  579. #ifdef DECNET
  580.     "/lat",            CXT_LAT,     0,
  581. #else
  582. #ifdef SUPERLAT
  583.     "/lat",            CXT_LAT,     0,
  584. #endif /* SUPERLAT */
  585. #endif /* DECNET */
  586.     "/modem",          CXT_MODEM,   0,
  587. #ifdef NPIPE
  588.     "/named-pipe",     CXT_NPIPE,   0,
  589. #endif /* NPIPE */
  590. #ifdef NETBIOS
  591.     "/netbios",        CXT_NETBIOS, 0,
  592. #endif /* NETBIOS */
  593.     "/remote",         CXT_REMOTE,  0,
  594. #ifdef TCPSOCKET
  595.     "/tcpip",          CXT_TCPIP,   0,
  596. #endif /* TCPSOCKET */
  597. #ifdef ANYX25
  598.     "/x.25",           CXT_X25,     0,
  599. #endif /* ANYX25 */
  600.     "", 0, 0
  601. };
  602. int ncxtypesw = (sizeof(cxtypesw) / sizeof(struct keytab));
  603.  
  604. #ifdef TN_COMPORT
  605. struct keytab tnflotab[] = {            /* SET FLOW-CONTROL keyword table */
  606.     "dtr/cd",    FLO_DTRC, 0,           /* for RFC 2217 Telnet COMPORT */
  607.     "dtr/cts",   FLO_DTRT, 0,
  608.     "keep",      FLO_KEEP, 0,
  609.     "none",      FLO_NONE, 0,
  610.     "rts/cts",   FLO_RTSC, 0,
  611.     "xon/xoff",  FLO_XONX, 0
  612. };
  613. int ntnflo = (sizeof(tnflotab) / sizeof(struct keytab));
  614. #endif /* TN_COMPORT */
  615.  
  616. struct keytab flotab[] = {              /* SET FLOW-CONTROL keyword table */
  617.     "automatic", FLO_AUTO, CM_INV,      /* Not needed any more */
  618. #ifdef CK_DTRCD
  619.     "dtr/cd",    FLO_DTRC, 0,
  620. #endif /* CK_DTRCD */
  621. #ifdef CK_DTRCTS
  622.     "dtr/cts",   FLO_DTRT, 0,
  623. #endif /* CK_DTRCTS */
  624.     "keep",      FLO_KEEP, 0,
  625.     "none",      FLO_NONE, 0,
  626. #ifdef CK_RTSCTS
  627.     "rts/cts",   FLO_RTSC, 0,
  628. #endif /* CK_RTSCTS */
  629. #ifndef Plan9
  630.     "xon/xoff",  FLO_XONX, 0,
  631. #endif /* Plan9 */
  632.     "", 0, 0
  633. };
  634. int nflo = (sizeof(flotab) / sizeof(struct keytab)) - 1;
  635.  
  636. /*  Handshake characters  */
  637.  
  638. struct keytab hshtab[] = {
  639.     "bell", 007, 0,
  640.     "code", 998, 0,
  641.     "cr",   015, 0,
  642.     "esc",  033, 0,
  643.     "lf",   012, 0,
  644.     "none", 999, 0,                     /* (can't use negative numbers) */
  645.     "xoff", 023, 0,
  646.     "xon",  021, 0
  647. };
  648. int nhsh = (sizeof(hshtab) / sizeof(struct keytab));
  649.  
  650. #ifndef NOLOCAL
  651. static struct keytab sfttab[] = {       /* File types for SET SESSION-LOG */
  652.     "ascii",     XYFT_T, CM_INV,
  653.     "binary",    XYFT_B, 0,
  654.     "debug",     XYFT_D, 0,
  655.     "text",      XYFT_T, 0,
  656.     "timestamped-text", 999, 0
  657. };
  658. static int nsfttab = (sizeof(sfttab) / sizeof(struct keytab));
  659. #endif /* NOLOCAL */
  660.  
  661. #ifndef NODIAL
  662.  
  663. #ifdef NETCONN                          /* Networks directory depends */
  664. int nnetdir = 0;                        /* on DIAL code -- fix later... */
  665. char *netdir[MAXDDIR+2];
  666. #endif /* NETCONN */
  667.  
  668. _PROTOTYP( static int setdial, (int) );
  669. _PROTOTYP( static int setdcd, (void) );
  670. _PROTOTYP( static int cklogin, (void) );
  671.  
  672. #ifndef MINIDIAL
  673. #ifdef OLDTBCODE
  674. extern int tbmodel;                     /* Telebit model ID */
  675. #endif /* OLDTBCODE */
  676. #endif /* MINIDIAL */
  677.  
  678. extern MDMINF *modemp[];                /* Pointers to modem info structs */
  679. extern struct keytab mdmtab[];          /* Modem types (in module ckudia.c) */
  680. extern int nmdm;                        /* Number of them */
  681.  
  682. _PROTOTYP(static int dialstr,(char **, char *));
  683.  
  684. extern int dialhng, dialtmo, dialksp, dialdpy, dialmhu, dialec, dialdc;
  685. extern int dialrtr, dialint, dialudt, dialsrt, dialrstr, mdmwaitd;
  686. extern int mdmspd, dialfc, dialmth, dialesc, dialfld, dialidt, dialpace;
  687. extern int mdmspk, mdmvol, dialtest;
  688.  
  689. int dialcvt = 2;                        /* DIAL CONVERT-DIRECTORY */
  690. int dialcnf = 0;                        /* DIAL CONFIRMATION */
  691. int dialcon = 2;                        /* DIAL CONNECT */
  692. int dialcq  = 0;                        /* DIAL CONNECT AUTO quiet/verbose */
  693. extern long dialmax, dialcapas;
  694. int usermdm = 0;
  695. extern int ndialdir;
  696. extern char *dialini,   *dialmstr, *dialmprmt, *dialdir[], *dialcmd,  *dialnpr,
  697.  *dialdcon, *dialdcoff, *dialecon, *dialecoff, *dialhcmd,  *dialx3,
  698.  *dialhwfc, *dialswfc,  *dialnofc, *dialtone,  *dialpulse, *dialname, *diallac;
  699. extern char *diallcc,   *dialixp,  *dialixs,   *dialldp,   *diallds,  *dialtfp,
  700.  *dialpxi,  *dialpxo,   *dialsfx,  *dialaaon,  *dialaaoff;
  701. extern char *diallcp,   *diallcs,  *dialini2,  *dialmac;
  702. extern char *dialspoff, *dialspon, *dialvol1,  *dialvol2,  *dialvol3;
  703.  
  704. char *dialtocc[MAXTPCC] = { NULL, NULL };
  705. int ndialtocc = 0;
  706. char *dialpucc[MAXTPCC] = { NULL, NULL };
  707. int ndialpucc = 0;
  708.  
  709. char *dialtfc[MAXTOLLFREE] = {
  710.     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  711. };
  712. int ntollfree = 0;
  713.  
  714. char *dialpxx[MAXPBXEXCH] = {
  715.     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  716. };
  717. int ndialpxx = 0;
  718.  
  719. char *diallcac[MAXLOCALAC] = {
  720.     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  721.     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  722.     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  723.     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  724. };
  725. int nlocalac = 0;
  726.  
  727. static struct keytab drstrtab[] = {
  728.     "international", 5, 0,
  729.     "local",         2, 0,
  730.     "long-distance", 4, 0,
  731.     "none",          6, 0
  732. };
  733.  
  734. static struct keytab dcnvtab[] = {
  735.     "ask",  2, 0,
  736.     "off",  0, 0,
  737.     "on",   1, 0
  738. };
  739.  
  740. struct keytab setmdm[] = {
  741.     "capabilities",     XYDCAP,  0,
  742.     "carrier-watch",    XYDMCD,  0,
  743.     "command",          XYDSTR,  0,
  744.     "compression",      XYDDC,   CM_INV,
  745.     "data-compression", XYDDC,   0,
  746.     "dial-command",     XYDDIA,  0,
  747.     "error-correction", XYDEC,   0,
  748.     "escape-character", XYDESC,  0,
  749.     "flow-control",     XYDFC,   0,
  750.     "hangup-method",    XYDMHU,  0,
  751. #ifndef NOXFER
  752.     "kermit-spoof",     XYDKSP,  0,
  753. #endif /* NOXFER */
  754.     "maximum-speed",    XYDMAX,  0,
  755.     "name",             XYDNAM,  0,
  756.     "speaker",          XYDSPK,  0,
  757.     "speed-matching",   XYDSPD,  0,
  758.     "type",             XYDTYP,  0,
  759.     "volume",           XYDVOL,  0
  760. };
  761. int nsetmdm = (sizeof(setmdm) / sizeof(struct keytab));
  762.  
  763. struct keytab voltab[] = {
  764.     "high",   3,  0,
  765.     "low",    1,  0,
  766.     "medium", 2,  0
  767. };
  768.  
  769. struct keytab mdmcap[] = {
  770.     "at-commands",      CKD_AT,  0,
  771.     "compression",      CKD_DC,  0,
  772.     "dc",               CKD_DC,  CM_INV,
  773.     "ec",               CKD_EC,  CM_INV,
  774.     "error-correction", CKD_EC,  0,
  775.     "hardware-flow",    CKD_HW,  0,
  776.     "hwfc",             CKD_HW,  CM_INV,
  777.     "itu",              CKD_V25, CM_INV,
  778.     "kermit-spoof",     CKD_KS,  0,
  779.     "ks",               CKD_KS,  CM_INV,
  780.     "sb",               CKD_SB,  CM_INV,
  781.     "software-flow",    CKD_SW,  0,
  782.     "speed-buffering",  CKD_SB,  0,
  783.     "swfc",             CKD_SW,  CM_INV,
  784.     "tb",               CKD_TB,  CM_INV,
  785.     "telebit",          CKD_TB,  0,
  786.     "v25bis-commands",  CKD_V25, 0
  787. };
  788. int nmdmcap = (sizeof(mdmcap) / sizeof(struct keytab));
  789.  
  790. #ifdef COMMENT                          /* SET ANSWER not implemented yet */
  791. static struct keytab answertab[] = {
  792.     { "caller-id",  XYA_CID,  0 };
  793.     { "rings",      XYA_RNG,  0 };
  794.     { "", 0, 0 }
  795. };
  796. static int nanswertab =  (sizeof(answertab) / sizeof(struct keytab)) - 1;
  797. #endif /* COMMENT */
  798.  
  799. struct keytab dialtab[] = {             /* SET DIAL table */
  800.     "area-code",        XYDLAC, 0,      /* Also still includes items     */
  801.     "compression",      XYDDC,  CM_INV, /* that were moved to SET MODEM, */
  802.     "confirmation",     XYDCNF, 0,      /* but they are CM_INVisible...  */
  803.     "connect",          XYDCON, 0,
  804.     "convert-directory",XYDCVT, 0,
  805.     "country-code",     XYDLCC, 0,
  806.     "dial-command",     XYDDIA, CM_INV,
  807.     "directory",        XYDDIR, 0,
  808.     "display",          XYDDPY, 0,
  809.     "escape-character", XYDESC, CM_INV,
  810.     "error-correction", XYDEC,  CM_INV,
  811.     "flow-control",     XYDFC,  CM_INV,
  812.     "force-long-distance", XYDFLD, 0,
  813.     "hangup",           XYDHUP, 0,
  814.     "ignore-dialtone",  XYDIDT, 0,
  815.     "interval",         XYDINT, 0,
  816.     "in",               XYDINI, CM_INV|CM_ABR,
  817.     "init-string",      XYDINI, CM_INV,
  818.     "intl-prefix",      XYDIXP, 0,
  819.     "intl-suffix",      XYDIXS, 0,
  820. #ifndef NOXFER
  821.     "kermit-spoof",     XYDKSP, CM_INV,
  822. #endif /* NOXFER */
  823.     "lc-area-codes",    XYDLLAC, 0,
  824.     "lc-prefix",        XYDLCP, 0,
  825.     "lc-suffix",        XYDLCS, 0,
  826.     "ld-prefix",        XYDLDP, 0,
  827.     "ld-suffix",        XYDLDS, 0,
  828.     "local-area-code",  XYDLAC, CM_INV,
  829.     "local-prefix",     XYDLCP, CM_INV,
  830.     "local-suffix",     XYDLCS, CM_INV,
  831.     "m",                XYDMTH, CM_INV|CM_ABR,
  832. #ifndef NOSPL
  833.     "macro",            XYDMAC, 0,      /* 195 */
  834. #endif /* NOSPL */
  835. #ifdef MDMHUP
  836.     "me",               XYDMTH, CM_INV|CM_ABR,
  837. #endif /* MDMHUP */
  838.     "method",           XYDMTH, 0,
  839.     "mnp-enable",       XYDMNP, CM_INV, /* obsolete but still accepted */
  840. #ifdef MDMHUP
  841.     "modem-hangup",     XYDMHU, CM_INV,
  842. #endif /* MDMHUP */
  843.     "pacing",           XYDPAC,  0,
  844.     "pbx-exchange",     XYDPXX,  0,
  845.     "pbx-inside-prefix",XYDPXI,  0,
  846.     "pbx-outside-prefix",XYDPXO, 0,
  847.     "prefix",           XYDNPR,  0,
  848.     "pulse-countries",  XYDPUCC, 0,
  849.     "restrict",         XYDRSTR, 0,
  850.     "retries",          XYDRTM,  0,
  851.     "sort",             XYDSRT,  0,
  852.     "speed-matching",   XYDSPD,  CM_INV,
  853.     "string",           XYDSTR,  CM_INV,
  854.     "suffix",           XYDSFX,  0,
  855.     "test",             XYDTEST, 0,
  856.     "timeout",          XYDTMO,  0,
  857.     "tf-area-code",     XYDTFC,  CM_INV,
  858.     "tf-prefix",        XYDTFP,  CM_INV,
  859.     "toll-free-area-code",XYDTFC,0,
  860.     "toll-free-prefix", XYDTFP,  0,
  861.     "tone-countries",   XYDTOCC, 0
  862. };
  863. int ndial = (sizeof(dialtab) / sizeof(struct keytab));
  864.  
  865. #ifdef MDMHUP
  866. struct keytab mdmhang[] = {
  867.     "dtr",           0, 0,
  868.     "modem-command", 1, 0,
  869.     "rs232-signal",  0, 0,
  870.     "v24-signal",    0, CM_INV
  871. };
  872. #endif /* MDMHUP */
  873.  
  874. static struct keytab mdmcmd[] = {
  875.     "autoanswer",       XYDS_AN, 0,     /* autoanswer */
  876.     "compression",      XYDS_DC, 0,     /* data compression */
  877.     "dial-mode-prompt", XYDS_MP, 0,     /* dial mode prompt */
  878.     "dial-mode-string", XYDS_MS, 0,     /* dial mode string */
  879.     "error-correction", XYDS_EC, 0,     /* error correction */
  880.     "hangup-command",   XYDS_HU, 0,     /* hangup command */
  881.     "hardware-flow",    XYDS_HW, 0,     /* hwfc */
  882.     "ignore-dialtone",  XYDS_ID, 0,     /* ignore dialtone */
  883.     "init-string",      XYDS_IN, 0,     /* init string */
  884.     "no-flow-control",  XYDS_NF, 0,     /* no flow control */
  885.     "predial-init",     XYDS_I2, 0,     /* last-minute setup commands */
  886.     "pulse",            XYDS_DP, 0,     /* pulse */
  887.     "software-flow",    XYDS_SW, 0,     /* swfc */
  888.     "speaker",          XYDS_SP, 0,     /* Speaker */
  889.     "tone",             XYDS_DT, 0,     /* tone */
  890.     "volume",           XYDS_VO, 0      /* Volume */
  891. };
  892. static int nmdmcmd = (sizeof(mdmcmd) / sizeof(struct keytab));
  893.  
  894. struct keytab dial_fc[] = {
  895.     "auto",     FLO_AUTO, 0,
  896.     "none",     FLO_NONE, 0,
  897.     "rts/cts",  FLO_RTSC, 0,
  898.     "xon/xoff", FLO_XONX, 0
  899. };
  900.  
  901. struct keytab dial_m[] = {              /* DIAL METHOD */
  902.     "auto",    XYDM_A, 0,
  903.     "default", XYDM_D, 0,
  904.     "pulse",   XYDM_P, 0,
  905.     "tone",    XYDM_T, 0
  906. };
  907. int ndial_m = (sizeof(dial_m)/sizeof(struct keytab));
  908.  
  909. #ifdef CK_TAPI
  910. struct keytab tapitab[] = {             /* Top-Level Microsoft TAPI */
  911.     "configure-line",     XYTAPI_CFG,  0,
  912.     "dialing-properties", XYTAPI_DIAL, 0
  913. };
  914. int ntapitab = (sizeof(tapitab)/sizeof(struct keytab));
  915.  
  916. struct keytab settapitab[] = {          /* SET Microsoft TAPI */
  917.     "inactivity-timeout", XYTAPI_INA,  0,
  918.     "line",               XYTAPI_LIN,  0,
  919.     "location",           XYTAPI_LOC,  0,
  920.     "manual-dialing",     XYTAPI_MAN,  0,
  921.     "modem-dialing",      XYTAPI_PASS, 0,
  922.     "modem-lights",       XYTAPI_LGHT, 0,
  923.     "phone-number-conversions",   XYTAPI_CON,  0,
  924.     "port",               XYTAPI_LIN,  CM_INV,
  925.     "post-dial-terminal", XYTAPI_PST,  0,
  926.     "pre-dial-terminal",  XYTAPI_PRE,  0,
  927.     "use-windows-configuration", XYTAPI_USE, 0,
  928.     "wait-for-credit-card-tone", XYTAPI_BNG, 0
  929. };
  930. int nsettapitab = (sizeof(settapitab)/sizeof(struct keytab));
  931.  
  932. struct keytab * tapiloctab = NULL;      /* Microsoft TAPI Locations */
  933. int ntapiloc = 0;
  934. extern struct keytab * tapilinetab;     /* Microsoft TAPI Line Devices */
  935. extern int ntapiline;
  936. extern int tttapi;                      /* TAPI in use */
  937. extern int tapipass;                    /* TAPI Passthrough mode */
  938. extern int tapiconv;                    /* TAPI Conversion mode */
  939. extern int tapilights;
  940. extern int tapipreterm;
  941. extern int tapipostterm;
  942. extern int tapimanual;
  943. extern int tapiinactivity;
  944. extern int tapibong;
  945. extern int tapiusecfg;
  946. #endif /* CK_TAPI */
  947. #endif /* NODIAL */
  948.  
  949. #ifndef NOPUSH
  950. extern int nopush;
  951. #ifdef UNIX
  952. struct keytab wildtab[] = {             /* SET WILDCARD-EXPANSION */
  953.     "kermit",  0, 0,
  954.     "shell",   1, 0
  955. };
  956. struct keytab wdottab[] = {             /* cont'd */
  957.     "/match-dot-files",    1, 0,
  958.     "/no-match-dot-files", 0, 0
  959. };
  960. extern int wildxpand;
  961. #endif /* UNIX */
  962. #endif /* NOPUSH */
  963.  
  964. #ifdef NETCONN
  965. extern struct keytab netcmd[], netkey[];
  966. extern int nnets, nnetkey;
  967. #ifdef TCPSOCKET
  968. extern struct keytab tcpopt[];
  969. extern int ntcpopt;
  970. #endif /* TCPSOCKET */
  971. #ifdef NPIPE
  972. char pipename[PIPENAML+1] = { NUL, NUL };
  973. #endif /* NPIPE */
  974. #ifdef CK_NETBIOS
  975. extern unsigned char NetBiosName[];
  976. #endif /* CK_NETBIOS */
  977. #endif /* NETCONN */
  978.  
  979. #ifdef ANYX25
  980. struct keytab x25tab[] = {
  981.     "call-user-data",    XYUDAT, 0,
  982.     "closed-user-group", XYCLOS, 0,
  983.     "reverse-charge",    XYREVC, 0
  984. };
  985. int nx25 = (sizeof(x25tab) / sizeof(struct keytab));
  986.  
  987. #ifndef IBMX25
  988. struct keytab padx3tab[] = {
  989.     "break-action",         PAD_BREAK_ACTION,           0,
  990.     "break-character",      PAD_BREAK_CHARACTER,        0,
  991.     "character-delete",     PAD_CHAR_DELETE_CHAR,       0,
  992.     "cr-padding",           PAD_PADDING_AFTER_CR,       0,
  993.     "discard-output",       PAD_SUPPRESSION_OF_DATA,    0,
  994.     "echo",                 PAD_ECHO,                   0,
  995.     "editing",              PAD_EDITING,                0,
  996.     "escape",               PAD_ESCAPE,                 0,
  997.     "forward",              PAD_DATA_FORWARD_CHAR,      0,
  998.     "lf-padding",           PAD_PADDING_AFTER_LF,       0,
  999.     "lf-insert",            PAD_LF_AFTER_CR,            0,
  1000.     "line-delete",          PAD_BUFFER_DELETE_CHAR,     0,
  1001.     "line-display",         PAD_BUFFER_DISPLAY_CHAR,    0,
  1002.     "line-fold",            PAD_LINE_FOLDING,           0,
  1003.     "pad-flow-control",     PAD_FLOW_CONTROL_BY_PAD,    0,
  1004.     "service-signals",      PAD_SUPPRESSION_OF_SIGNALS, 0,
  1005.     "timeout",              PAD_DATA_FORWARD_TIMEOUT,   0,
  1006. /* Speed is read-only */
  1007.     "transmission-rate",    PAD_LINE_SPEED,             0,
  1008.     "user-flow-control",    PAD_FLOW_CONTROL_BY_USER,   0
  1009. };
  1010. int npadx3 = (sizeof(padx3tab) / sizeof(struct keytab));
  1011. #endif /* IBMX25 */
  1012. #endif /* ANYX25 */
  1013.  
  1014. #ifdef TLOG
  1015. static struct keytab vbtab[] = {
  1016.     "brief",   0, 0,
  1017. #ifdef OS2ORUNIX
  1018.     "ftp",     2, 0,
  1019. #endif /* OS2ORUNIX */
  1020.     "verbose", 1, 0
  1021. };
  1022. int nvb = (sizeof(vbtab) / sizeof(struct keytab));
  1023. #endif /* TLOG */
  1024.  
  1025. #ifdef CKSYSLOG
  1026. static struct keytab syslogtab[] = {
  1027.     "all",         SYSLG_CX, 0,
  1028.     "commands",    SYSLG_CM, 0,
  1029.     "connection",  SYSLG_AC, 0,
  1030.     "debug",       SYSLG_DB, 0,
  1031.     "dial",        SYSLG_DI, 0,
  1032.     "file-access", SYSLG_FA, 0,
  1033.     "file-create", SYSLG_FC, 0,
  1034.     "login",       SYSLG_LI, 0,
  1035.     "none",        SYSLG_NO, 0,
  1036.     "protocol",    SYSLG_PR, 0
  1037. };
  1038. int nsyslog = (sizeof(syslogtab) / sizeof(struct keytab));
  1039. #endif /* CKSYSLOG */
  1040.  
  1041. /* Parity keyword table */
  1042.  
  1043. struct keytab partbl[] = {
  1044.     "even",    'e', 0,
  1045. #ifdef HWPARITY
  1046.     "hardware",'H', 0,
  1047. #endif /* HWPARITY */
  1048.     "mark",    'm', 0,
  1049.     "none",     0 , 0,
  1050.     "odd",     'o', 0,
  1051.     "space",   's', 0
  1052. };
  1053. int npar = (sizeof(partbl) / sizeof(struct keytab));
  1054.  
  1055. #ifdef HWPARITY
  1056. struct keytab hwpartbl[] = {
  1057. /* Add mark and space if needed and possible */
  1058.     "even",    'e', 0,
  1059. #ifdef OS2
  1060.     "mark",    'm', 0,
  1061. #endif /* OS2 */
  1062.     "odd",     'o', 0,
  1063. #ifdef OS2
  1064.     "space",   's', 0,
  1065. #endif /* OS2 */
  1066.     "", 0, 0
  1067. };
  1068. int nhwpar = (sizeof(hwpartbl) / sizeof(struct keytab)) - 1;
  1069. #endif /* HWPARITY */
  1070.  
  1071. /* On/Off table */
  1072.  
  1073. struct keytab onoff[] = {
  1074.     "off",       0, 0,
  1075.     "on",        1, 0
  1076. };
  1077.  
  1078. #define XYCD_M    0            /* CD MESSAGE */
  1079. #define XYCD_P    1            /* CD PATH */
  1080. #define XYCD_H    2            /* CD HOME */
  1081.  
  1082. struct keytab cdtab[] = {
  1083.     "home",      XYCD_H, 0,
  1084.     "message",   XYCD_M, 0,
  1085.     "path",      XYCD_P, 0
  1086. };
  1087. int ncdtab = (sizeof(cdtab) / sizeof(struct keytab));
  1088.  
  1089. struct keytab cdmsg[] = {
  1090.     "file",      2, 0,
  1091.     "off",       0, 0,
  1092.     "on",        1, 0
  1093. };
  1094. int ncdmsg = (sizeof(cdmsg) / sizeof(struct keytab));
  1095.  
  1096. static
  1097. struct keytab xittab[] = {              /* SET EXIT */
  1098.     "hangup",        3, 0,              /* ...HANGUP */
  1099.     "on-disconnect", 2, 0,              /* ...ON-DISCONNECT */
  1100.     "status",        0, 0,              /* ...STATUS */
  1101.     "warning",       1, 0               /* ...WARNING */
  1102. };
  1103. int nexit = (sizeof(xittab) / sizeof(struct keytab));
  1104.  
  1105. struct keytab xitwtab[] = {             /* SET EXIT WARNING */
  1106.     "always", 2, 0,                     /* even when not connected */
  1107.     "off",    0, 0,                     /* no warning     */
  1108.     "on",     1, 0                      /* when connected */
  1109. };
  1110. int nexitw = (sizeof(xitwtab) / sizeof(struct keytab));
  1111.  
  1112. struct keytab rltab[] = {
  1113.     "local",     1, 0,                  /* ECHO values */
  1114.     "off",       0, CM_INV,
  1115.     "on",        1, CM_INV,
  1116.     "remote",    0, 0
  1117. };
  1118. int nrlt = (sizeof(rltab) / sizeof(struct keytab));
  1119.  
  1120. /* Incomplete File Disposition table */
  1121.  
  1122. struct keytab ifdtab[] = {
  1123.     "discard", SET_OFF, 0,
  1124.     "keep",    SET_ON,  0
  1125. };
  1126.  
  1127. struct keytab ifdatab[] = {
  1128.     "auto",    SET_AUTO, 0,
  1129.     "discard", SET_OFF,  0,
  1130.     "keep",    SET_ON,   0
  1131. };
  1132.  
  1133. char * ifdnam[] = { "discard", "keep", "auto" };
  1134.  
  1135. /* SET TAKE parameters table */
  1136. static
  1137. struct keytab taktab[] = {
  1138.     "echo",  0, 0,
  1139.     "error", 1, 0,
  1140.     "off",   2, CM_INV,                 /* For compatibility */
  1141.     "on",    3, CM_INV                  /* with MS-DOS Kermit... */
  1142. };
  1143.  
  1144. #ifndef NOSPL
  1145. #ifdef COMMENT
  1146. /* not used */
  1147. static
  1148. struct keytab suftab[] = {              /* (what to do with) STARTUP-FILE */
  1149.     "delete", 1, 0,
  1150.     "keep",   0, 0
  1151. };
  1152. #endif /* COMMENT */
  1153.  
  1154. /* SET MACRO parameters table */
  1155. static
  1156. struct keytab smactab[] = {
  1157.     "echo",  0, 0,
  1158.     "error", 1, 0
  1159. };
  1160. #endif /* NOSPL */
  1161.  
  1162. #ifndef NOSCRIPT
  1163. static
  1164. struct keytab scrtab[] = {
  1165.     "echo",  0, 0
  1166. };
  1167. #endif /* NOSCRIPT */
  1168.  
  1169. /* SET COMMAND table */
  1170.  
  1171. /* SET COMMAND items... */
  1172.  
  1173. #define SCMD_BSZ 0    /* BYTESIZE */
  1174. #define SCMD_RCL 1    /* RECALL */
  1175. #define SCMD_RTR 2    /* RETRY */
  1176. #define SCMD_QUO 3    /* QUOTING */
  1177. #define SCMD_COL 4    /* COLOR */
  1178. #define SCMD_HIG 5    /* HEIGHT */
  1179. #define SCMD_WID 6    /* WIDTH */
  1180. #define SCMD_CUR 7    /* CURSOR-POSITION */
  1181. #define SCMD_SCR 8    /* SCROLLBACK */
  1182. #define SCMD_MOR 9    /* MORE-PROMPTING */
  1183. #define SCMD_INT 10     /* INTERRUPTION */
  1184. #define SCMD_ADL 11     /* AUTODOWNLOAD */
  1185. #define SCMD_STA 12     /* STATUSLINE */
  1186. #define SCMD_DBQ 13    /* DOUBLEQUOTING */
  1187. #define SCMD_CBR 14    /* CBREAK */
  1188. #define SCMD_BFL 15    /* BUFFER-SIZE (not used) */
  1189.  
  1190. static struct keytab scmdtab[] = {
  1191. #ifdef CK_AUTODL
  1192.     "autodownload",       SCMD_ADL, 0,
  1193. #endif /* CK_AUTODL */
  1194. #ifdef COMMENT
  1195. /*
  1196.   To implement this requires that we change CMDBL and ATMBL
  1197.   from compile-time symbols to runtime variables.  Not a big deal,
  1198.   but not trivial either.
  1199.  */
  1200.     "buffer-size",        SCMD_BFL, 0,
  1201. #endif /* COMMENT */
  1202.     "bytesize",           SCMD_BSZ, 0,
  1203.     "cbreak",             SCMD_CBR, CM_INV,
  1204. #ifdef OS2
  1205.     "color",              SCMD_COL, 0,
  1206.     "cursor-position",    SCMD_CUR, 0,
  1207. #endif /* OS2 */
  1208. #ifdef DOUBLEQUOTING
  1209.     "doublequoting",      SCMD_DBQ, 0,
  1210. #endif /* DOUBLEQUOTING */
  1211.     "height",             SCMD_HIG, 0,
  1212.     "interruption",       SCMD_INT, 0,
  1213.     "more-prompting",     SCMD_MOR, 0,
  1214.     "quoting",            SCMD_QUO, 0,
  1215. #ifdef CK_RECALL
  1216.     "recall-buffer-size", SCMD_RCL, 0,
  1217. #endif /* CK_RECALL */
  1218. #ifdef CK_RECALL
  1219.     "retry",              SCMD_RTR, 0,
  1220. #endif /* CK_RECALL */
  1221. #ifdef OS2
  1222. #ifdef ONETERMUPD
  1223.     "scrollback",         SCMD_SCR, 0,
  1224.     "statusline",         SCMD_STA, 0,
  1225. #endif /* ONETERMUPD */
  1226. #endif /* OS2 */
  1227.     "width",              SCMD_WID, 0
  1228. };
  1229. static int nbytt = (sizeof(scmdtab) / sizeof(struct keytab));
  1230.  
  1231. #ifndef NOSERVER
  1232. /* Server parameters table */
  1233. static struct keytab srvtab[] = {
  1234.     "cd-message",   XYSERC, 0,
  1235.     "display",      XYSERD, 0,
  1236.     "get-path",     XYSERP, 0,
  1237.     "idle-timeout", XYSERI, 0,
  1238.     "keepalive",    XYSERK, 0,
  1239.     "login",        XYSERL, 0,
  1240.     "timeout",      XYSERT, 0
  1241. };
  1242. static int nsrvt = (sizeof(srvtab) / sizeof(struct keytab));
  1243. #endif /* NOSERVER */
  1244.  
  1245. static struct keytab sleeptab[] = {     /* SET SLEEP table */
  1246.     "cancellation",  0,   0
  1247. };
  1248.  
  1249. static struct keytab tstab[] = {        /* SET TRANSFER/XFER table */
  1250.     "bell",            XYX_BEL, 0,
  1251. #ifdef XFRCAN
  1252.     "cancellation",    XYX_CAN, 0,
  1253. #endif /* XFRCAN */
  1254. #ifndef NOCSETS
  1255.     "character-set",   XYX_CSE, 0,
  1256. #endif /* NOCSETS */
  1257. #ifndef NOSPL
  1258.     "crc-calculation", XYX_CRC, 0,
  1259. #endif /* NOSPL */
  1260.     "display",         XYX_DIS, 0,
  1261.     "interruption",    XYX_INT, 0,
  1262.     "locking-shift",   XYX_LSH, 0,
  1263.     "message",         XYX_MSG, 0,
  1264.     "mode",            XYX_MOD, 0,
  1265.     "msg",             XYX_MSG, CM_INV,
  1266. #ifdef PIPESEND
  1267.     "pipes",           XYX_PIP, 0,
  1268. #endif /* PIPESEND */
  1269. #ifdef CK_XYZ
  1270.     "protocol",        XYX_PRO, 0,
  1271. #endif /* CK_XYZ */
  1272.     "report",          XYX_RPT, 0,
  1273.     "slow-start",      XYX_SLO, 0,
  1274. #ifndef NOCSETS
  1275.     "translation",     XYX_XLA, 0,
  1276. #else
  1277.     "translation",     XYX_XLA, CM_INV,
  1278. #endif /* NOCSETS */
  1279.     "xlation",         XYX_XLA, CM_INV,
  1280.     "", 0, 0
  1281. };
  1282. static int nts = (sizeof(tstab) / sizeof(struct keytab)) - 1;
  1283.  
  1284. static struct keytab rtstab[] = {       /* REMOTE SET TRANSFER/XFER table */
  1285. #ifndef NOCSETS
  1286.     "character-set",   XYX_CSE, 0,
  1287. #endif /* NOCSETS */
  1288.     "mode",            XYX_MOD, 0
  1289. };
  1290. static int nrts = (sizeof(rtstab) / sizeof(struct keytab));
  1291.  
  1292. struct keytab xfrmtab[] = {             /* TRANSFER MODE table */
  1293.     "automatic", XMODE_A, 0,
  1294.     "manual",    XMODE_M, 0
  1295. };
  1296.  
  1297. #ifdef LOCUS
  1298. extern int locus, autolocus;
  1299.  
  1300. static struct keytab locustab[] = {
  1301. #ifdef KUI
  1302.     { "ask",     3, 0 },        /* Presently implemented in GUI only */
  1303. #endif /* KUI */
  1304.     { "auto",    2, 0 },
  1305.     { "local",   1, 0 },
  1306.     { "remote",  0, 0 }
  1307. };
  1308. static int nlocustab = (sizeof(locustab) / sizeof(struct keytab));
  1309.  
  1310. #endif /* LOCUS */
  1311.  
  1312. #ifndef NOCSETS
  1313. /* SET TRANSFER CHARACTER-SET table */
  1314.  
  1315. extern struct keytab tcstab[];
  1316. extern int ntcs;
  1317. #endif /* NOCSETS */
  1318.  
  1319. /* SET TRANSFER LOCKING-SHIFT table */
  1320. struct keytab lstab[] = {
  1321.     "forced", 2,   0,
  1322.     "off",    0,   0,
  1323.     "on",     1,   0
  1324. };
  1325. int nls = (sizeof(lstab) / sizeof(struct keytab));
  1326.  
  1327. /* SET TELNET tables */
  1328. #ifdef TNCODE
  1329. extern int tn_nlm, tn_b_nlm, tn_b_meu, tn_b_ume, tn_b_xfer, tn_sb_bug;
  1330. extern int tn_no_encrypt_xfer;
  1331. extern int tn_wait_flg, tn_duplex, tn_delay_sb, tn_sfu;
  1332. extern int sl_tn_saved;
  1333. extern int tn_infinite;
  1334. extern int tn_rem_echo;
  1335. extern int tn_deb;
  1336. extern int tn_auth_how;
  1337. extern int tn_auth_enc;
  1338. #ifdef CK_FORWARD_X
  1339. extern char * tn_fwdx_xauthority;
  1340. #endif /* CK_FORWARD_X */
  1341. #ifdef CK_AUTHENTICATION
  1342. static struct keytab setauth[] = {
  1343. #ifdef CK_KERBEROS
  1344.     "k4",        AUTH_KRB4, CM_INV,
  1345.     "k5",        AUTH_KRB5, CM_INV,
  1346.     "kerberos4", AUTH_KRB4, 0,
  1347.     "kerberos5", AUTH_KRB5, 0,
  1348.     "kerberos_iv",AUTH_KRB4, CM_INV,
  1349.     "kerberos_v", AUTH_KRB5, CM_INV,
  1350.     "krb4",      AUTH_KRB4, CM_INV,
  1351.     "krb5",      AUTH_KRB5, CM_INV,
  1352. #endif /* CK_KERBEROS */
  1353. #ifdef CK_SRP
  1354.     "srp",       AUTH_SRP,  0,
  1355. #endif /* CK_SRP */
  1356. #ifdef CK_SSL
  1357.     "ssl",      AUTH_SSL,   0,
  1358.     "tls",      AUTH_TLS,   0,
  1359. #endif /* CK_SSL */
  1360.     "",         0,      0
  1361. };
  1362. static int nsetauth = sizeof(setauth)/sizeof(struct keytab) - 1;
  1363. #ifdef CK_KERBEROS
  1364. extern char * krb5_d_principal;         /* Default principal */
  1365. extern char * krb5_d_instance;
  1366. extern char * krb5_d_realm;             /* Default realm */
  1367. extern char * krb5_d_cc;                /* Default credentials cache */
  1368. extern char * krb5_d_srv;               /* Default service name */
  1369. extern int    krb5_d_lifetime;          /* Default lifetime */
  1370. extern int    krb5_d_forwardable;
  1371. extern int    krb5_d_proxiable;
  1372. extern int    krb5_d_renewable;
  1373. extern int    krb5_autoget;
  1374. extern int    krb5_autodel;
  1375. extern int    krb5_d_getk4;
  1376. extern int    krb5_checkaddrs;          /* Check TGT Addrs */
  1377. extern int    krb5_d_no_addresses;
  1378. extern char * krb5_d_addrs[];
  1379. extern char * k5_keytab;                /* Keytab file */
  1380.  
  1381. extern struct krb4_init_data krb4_init;
  1382. extern char * krb4_d_principal;         /* Default principal */
  1383. extern char * krb4_d_realm;             /* Default realm */
  1384. extern char * krb4_d_srv;               /* Default service name */
  1385. extern int    krb4_d_lifetime;          /* Default lifetime */
  1386. extern int    krb4_d_preauth;
  1387. extern char * krb4_d_instance;
  1388. extern int    krb4_autoget;
  1389. extern int    krb4_autodel;
  1390. extern int    krb4_checkaddrs;          /* Check TGT Addrs */
  1391. extern char * k4_keytab;                /* Keytab file */
  1392. #ifdef KRB4
  1393. extern int    k4debug;
  1394. #endif /* KRB4 */
  1395. static struct keytab krbver[] = {
  1396.     "4",                 4, 0,
  1397.     "5",                 5, 0,
  1398.     "iv",                4, CM_INV,
  1399.     "v",                 5, CM_INV
  1400. };
  1401. static int nkrbver = sizeof(krbver)/sizeof(struct keytab);
  1402.  
  1403. static struct keytab kdestab[] = {
  1404.     "never",            KRB_DEL_NO, 0,
  1405.     "no",               KRB_DEL_NO, CM_INV,
  1406.     "on-close",         KRB_DEL_CL, 0,
  1407.     "on-exit",          KRB_DEL_EX, 0
  1408. };
  1409. static int nkdestab = sizeof(kdestab)/sizeof(struct keytab);
  1410.  
  1411. static struct keytab k4tab[] = {
  1412.     "autodel",           XYKRBDEL, CM_INV,
  1413.     "autodestroy",       XYKRBDEL, 0,
  1414.     "autoget",           XYKRBGET, 0,
  1415.     "check-address",     XYKRBADR, 0,
  1416.     "debug",             XYKRBDBG, CM_INV,
  1417.     "instance",          XYKRBINS, 0,
  1418.     "keytab",            XYKRBKTB, 0,
  1419.     "lifetime",          XYKRBLIF, 0,
  1420.     "preauth",           XYKRBPRE, 0,
  1421.     "principal",         XYKRBPR,  0,
  1422.     "prompt",            XYKRBPRM, 0,
  1423.     "realm",             XYKRBRL,  0,
  1424.     "service-name",      XYKRBSRV, 0
  1425. };
  1426. static int nk4tab = sizeof(k4tab)/sizeof(struct keytab);
  1427.  
  1428. static struct keytab k5tab[] = {
  1429.     "addresses",         XYKRBADD, 0,
  1430.     "autodelete",        XYKRBDEL, CM_INV,
  1431.     "autodestroy",       XYKRBDEL, 0,
  1432.     "autoget",           XYKRBGET, 0,
  1433.     "cc",                XYKRBCC,  CM_INV,
  1434.     "check-address",     XYKRBADR, 0,
  1435.     "credentials-cache", XYKRBCC,  0,
  1436.     "forwardable",       XYKRBFWD, 0,
  1437.     "get-k4-tgt",        XYKRBK5K4,0,
  1438.     "instance",          XYKRBINS, 0,
  1439.     "keytab",            XYKRBKTB, 0,
  1440.     "lifetime",          XYKRBLIF, 0,
  1441.     "no-addresses",      XYKRBNAD, 0,
  1442.     "principal",         XYKRBPR,  0,
  1443.     "prompt",            XYKRBPRM, 0,
  1444.     "proxiable",         XYKRBPRX, 0,
  1445.     "realm",             XYKRBRL,  0,
  1446.     "renewable",         XYKRBRNW, 0,
  1447.     "service-name",      XYKRBSRV, 0
  1448. };
  1449. static int nk5tab = sizeof(k5tab)/sizeof(struct keytab);
  1450.  
  1451. #define KRB_PW_PRM 1
  1452. #define KRB_PR_PRM 2
  1453.  
  1454. static struct keytab krbprmtab[] = {
  1455.     "password",  KRB_PW_PRM, 0,
  1456.     "principal", KRB_PR_PRM, 0
  1457. };
  1458.  
  1459. #endif /* CK_KERBEROS */
  1460. #ifdef CK_SRP
  1461. static struct keytab srptab[] = {
  1462.     "prompt",            XYSRPPRM, 0
  1463. };
  1464. static int nsrptab = sizeof(srptab)/sizeof(struct keytab);
  1465. #define SRP_PW_PRM 1
  1466.  
  1467. static struct keytab srpprmtab[] = {
  1468.     "password",  SRP_PW_PRM, 0
  1469. };
  1470. #endif /* CK_SRP */
  1471. #ifdef CK_SSL
  1472. static struct keytab ssltab[] = {
  1473.     "certs-ok",          XYSSLCOK,  CM_INV,
  1474.     "cipher-list",       XYSSLCL,   0,
  1475.     "crl-dir",           XYSSLCRLD, 0,
  1476.     "crl-file",          XYSSLCRL,  0,
  1477.     "debug",             XYSSLDBG,  0,
  1478.     "dh-key-file",       XYSSLDKFL, CM_INV,
  1479.     "dh-param-file",     XYSSLDPFL, 0,
  1480.     "dsa-cert-chain-file", XYSSLDCCF, 0,
  1481.     "dsa-cert-file",     XYSSLDCFL, 0,
  1482.     "dsa-key-file",      XYSSLDKFL, 0,
  1483.     "dummy",             XYSSLDUM,  CM_INV,
  1484.     "only",              XYSSLON,   CM_INV,
  1485.     "random-file",       XYSSLRND,  0,
  1486.     "rsa-cert-chain-file", XYSSLRCCF, 0,
  1487.     "rsa-cert-file",     XYSSLRCFL, 0,
  1488.     "rsa-key-file",      XYSSLRKFL, 0,
  1489.     "verbose",           XYSSLVRB,  0,
  1490.     "verify",            XYSSLVRF,  0,
  1491.     "verify-dir",        XYSSLVRFD, 0,
  1492.     "verify-file",       XYSSLVRFF, 0
  1493. };
  1494. static int nssltab = sizeof(ssltab)/sizeof(struct keytab);
  1495. static struct keytab sslvertab[] = {
  1496.     "fail-if-no-peer-cert", SSL_VERIFY_PEER |
  1497.                             SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0,
  1498.     "no",               SSL_VERIFY_NONE, 0,
  1499.     "none",             SSL_VERIFY_NONE, CM_INV,
  1500.     "off",              SSL_VERIFY_NONE, CM_INV,
  1501.     "on",               SSL_VERIFY_PEER, CM_INV,
  1502.     "peer-cert",        SSL_VERIFY_PEER, 0
  1503. };
  1504. static int nsslvertab = sizeof(sslvertab)/sizeof(struct keytab);
  1505. #endif /* CK_SSL */
  1506. #endif /* CK_AUTHENTICATION */
  1507. #ifdef CK_ENCRYPTION
  1508. int cx_type = CX_AUTO;
  1509. extern int sl_cx_type;
  1510. #endif /* CK_ENCRYPTION */
  1511. extern char *tcp_address;
  1512. #ifndef NOHTTP
  1513. extern char * tcp_http_proxy;
  1514. extern char * tcp_http_proxy_user;
  1515. extern char * tcp_http_proxy_pwd;
  1516. #endif /* NOHTTP */
  1517. #ifdef NT
  1518. #ifdef CK_SOCKS
  1519. extern char *tcp_socks_svr;
  1520. extern char *tcp_socks_user;
  1521. #ifdef CK_SOCKS_NS
  1522. extern char *tcp_socks_ns;
  1523. #endif /* CK_SOCKS_NS */
  1524. #endif /* CK_SOCKS */
  1525. #endif /* NT */
  1526.  
  1527. #define UPW_USER 1
  1528. #define UPW_PASS 2
  1529.  
  1530. static struct keytab userpass[] = {
  1531.     { "/password", UPW_PASS, CM_ARG },
  1532.     { "/user",     UPW_USER, CM_ARG },
  1533. };
  1534. static int nuserpass = sizeof(userpass)/sizeof(struct keytab);
  1535.  
  1536. static struct keytab tnnegtab[] = {     /* TELNET NEGOTIATION table */
  1537.     "accepted",  TN_NG_AC, 0,
  1538.     "refused",   TN_NG_RF, 0,
  1539.     "req",       TN_NG_RQ, CM_INV|CM_ABR,
  1540.     "requ",      TN_NG_RQ, CM_INV|CM_ABR,
  1541.     "reque",     TN_NG_RQ, CM_INV|CM_ABR,
  1542.     "reques",    TN_NG_RQ, CM_INV|CM_ABR,
  1543.     "request",   TN_NG_RQ, CM_INV|CM_ABR,
  1544.     "requeste",  TN_NG_RQ, CM_INV|CM_ABR,
  1545.     "requested", TN_NG_RQ, 0,
  1546.     "required",  TN_NG_MU, 0
  1547. };
  1548. static int ntnnegtab = sizeof(tnnegtab)/sizeof(struct keytab);
  1549.  
  1550. #ifdef CK_ENCRYPTION
  1551. static struct keytab typkwd[] = {
  1552.     "/type", 0, CM_ARG
  1553. };
  1554.  
  1555. static struct keytab tnenctab[] = {     /* TELNET ENCRYPTION table */
  1556.     "accepted",   TN_NG_AC,    CM_INV,
  1557.     "refused",    TN_NG_RF,    CM_INV,
  1558.     "req",        TN_NG_RQ,    CM_INV|CM_ABR,
  1559.     "requ",       TN_NG_RQ,    CM_INV|CM_ABR,
  1560.     "reque",      TN_NG_RQ,    CM_INV|CM_ABR,
  1561.     "reques",     TN_NG_RQ,    CM_INV|CM_ABR,
  1562.     "request",    TN_NG_RQ,    CM_INV|CM_ABR,
  1563.     "requeste",   TN_NG_RQ,    CM_INV|CM_ABR,
  1564.     "requested",  TN_NG_RQ,    CM_INV,
  1565.     "required",   TN_NG_MU,    CM_INV,
  1566.     "start",      TN_EN_START, CM_INV,
  1567.     "stop",       TN_EN_STOP,  CM_INV,
  1568.     "type",       TN_EN_TYP,   0
  1569. };
  1570. static int ntnenc = sizeof(tnenctab)/sizeof(struct keytab) ;
  1571. #endif /* CK_ENCRYPTION */
  1572.  
  1573. #ifdef CK_FORWARD_X
  1574. static struct keytab tnfwdxtab[] = {    /* TELNET FORWARD-X table */
  1575.     "no-encryption",    1,  CM_INV,
  1576.     "xauthority-file",  0,  0
  1577. };
  1578. static int ntnfwdx = sizeof(tnfwdxtab)/sizeof(struct keytab) ;
  1579. #endif /* CK_FORWARD_X */
  1580.  
  1581. static struct keytab tnbugtab[] = {     /* TELNET BUG table */
  1582.     "binary-me-means-u-too", 0, 0,
  1583.     "binary-u-means-me-too", 1, 0,
  1584.     "infinite-loop-check",   2, 0,
  1585.     "sb-implies-will-do",    3, 0
  1586. };
  1587.  
  1588. #ifdef CK_ENVIRONMENT
  1589. static struct keytab tnenvtab[] = {     /* TELNET ENVIRONMENT table */
  1590.     "acct",     TN_ENV_ACCT,    0,
  1591.     "display",  TN_ENV_DISP,    0,
  1592.     "job",      TN_ENV_JOB,     0,
  1593.     "location", TN_ENV_LOC,     0,
  1594.     "off",      TN_ENV_OFF,     CM_INV,
  1595.     "on",       TN_ENV_ON,      CM_INV,
  1596.     "printer",  TN_ENV_PRNT,    0,
  1597.     "systemtype",TN_ENV_SYS,    0,
  1598.     "user",     TN_ENV_USR,     0,
  1599.     "uservar",  TN_ENV_UVAR,    0,
  1600.     "", 0, 0
  1601. };
  1602. static int ntnenv = sizeof(tnenvtab)/sizeof(struct keytab) - 1;
  1603. #endif /* CK_ENVIRONMENT */
  1604.  
  1605. #ifdef CK_AUTHENTICATION
  1606. static struct keytab tnauthtab[] = {    /* TELNET AUTHENTICATION table */
  1607.     "accepted",   TN_NG_AC,  CM_INV,
  1608.     "encrypt-flag", TN_AU_ENC, 0,
  1609.     "forwarding", TN_AU_FWD,   0,
  1610.     "how-flag",   TN_AU_HOW,   0,
  1611.     "refused",    TN_NG_RF,  CM_INV,
  1612.     "req",        TN_NG_RQ,  CM_INV|CM_ABR,
  1613.     "requ",       TN_NG_RQ,  CM_INV|CM_ABR,
  1614.     "reque",      TN_NG_RQ,  CM_INV|CM_ABR,
  1615.     "reques",     TN_NG_RQ,  CM_INV|CM_ABR,
  1616.     "request",    TN_NG_RQ,  CM_INV|CM_ABR,
  1617.     "requeste",   TN_NG_RQ,  CM_INV|CM_ABR,
  1618.     "requested",  TN_NG_RQ,  CM_INV,
  1619.     "required",   TN_NG_MU,  CM_INV,
  1620.     "type",       TN_AU_TYP, 0
  1621. };
  1622. static int ntnauth = sizeof(tnauthtab)/sizeof(struct keytab) ;
  1623.  
  1624. struct keytab autyptab[] = {    /* TELNET AUTHENTICATION TYPE table */
  1625.     "automatic",  AUTH_AUTO, 0,
  1626. #ifdef CK_KERBEROS
  1627.     "k4",         AUTH_KRB4, CM_INV,
  1628.     "k5",         AUTH_KRB5, CM_INV,
  1629.     "kerberos4",  AUTH_KRB4, 0,
  1630.     "kerberos5",  AUTH_KRB5, 0,
  1631.     "kerberos_iv",AUTH_KRB4, CM_INV,
  1632.     "kerberos_v", AUTH_KRB5, CM_INV,
  1633.     "krb4",       AUTH_KRB4, CM_INV,
  1634.     "krb5",       AUTH_KRB5, CM_INV,
  1635. #endif /* CK_KERBEROS */
  1636.     "none",       AUTH_NONE, 0,
  1637. #ifdef NT
  1638.     "ntlm",       AUTH_NTLM, 0,
  1639. #endif /* NT */
  1640. #ifdef CK_SRP
  1641.     "srp",        AUTH_SRP,  0,
  1642. #endif /* CK_SRP */
  1643. #ifdef CK_SSL
  1644.     "ssl",        AUTH_SSL,  0,
  1645. #endif /* CK_SSL */
  1646.     "", 0, 0
  1647. };
  1648. int nautyp = sizeof(autyptab)/sizeof(struct keytab) - 1;
  1649.  
  1650. struct keytab auhowtab[] = {    /* TELNET AUTHENTICATION HOW table */
  1651.     "any",     TN_AUTH_HOW_ANY,     0,
  1652.     "mutual",  TN_AUTH_HOW_MUTUAL,  0,
  1653.     "one-way", TN_AUTH_HOW_ONE_WAY, 0,
  1654.     "", 0, 0
  1655. };
  1656. int nauhow = sizeof(auhowtab)/sizeof(struct keytab) - 1;
  1657.  
  1658. struct keytab auenctab[] = {    /* TELNET AUTHENTICATION ENCRYPT table */
  1659.     "any",     TN_AUTH_ENC_ANY,     0,
  1660.     "none",    TN_AUTH_ENC_NONE,    0,
  1661.     "telopt",  TN_AUTH_ENC_TELOPT,  0,
  1662. #ifdef CK_SSL
  1663.     "tls",     TN_AUTH_ENC_TLS,     0,
  1664. #endif /* CK_SSL */
  1665.     "", 0, 0
  1666. };
  1667. int nauenc = sizeof(auenctab)/sizeof(struct keytab) - 1;
  1668. #endif /* CK_AUTHENTICATION */
  1669.  
  1670. #define TN_NL_BIN 3
  1671. #define TN_NL_NVT 4
  1672. static struct keytab tn_nlmtab[] = {    /* TELNET NEWLINE-MODE table */
  1673.     "binary-mode", TN_NL_BIN, 0,        /* Binary mode */
  1674.     "nvt",    TN_NL_NVT, 0,             /* NVT mode */
  1675.     "off",    TNL_CRNUL, CM_INV,        /* CR-NUL (TELNET spec) */
  1676.     "on",     TNL_CRLF,  CM_INV,        /* CR-LF (TELNET spec) */
  1677.     "raw",    TNL_CR,    CM_INV         /* CR only (out of spec) */
  1678. };
  1679. static int ntn_nlm = (sizeof(tn_nlmtab) / sizeof(struct keytab));
  1680.  
  1681. static struct keytab tnlmtab[] = {      /* TELNET NEWLINE-MODE table */
  1682.     "cr",     TNL_CR,    CM_INV,        /* CR only (out of spec) */
  1683.     "cr-lf",  TNL_CRLF,  CM_INV,        /* CR-LF (TELNET spec) */
  1684.     "cr-nul", TNL_CRNUL, CM_INV,        /* CR-NUL (TELNET spec) */
  1685.     "lf",     TNL_LF,    CM_INV,        /* LF instead of CR-LF */
  1686.     "off",    TNL_CRNUL, 0,             /* CR-NUL (TELNET spec) */
  1687.     "on",     TNL_CRLF,  0,             /* CR-LF (TELNET spec) */
  1688.     "raw",    TNL_CR,    0              /* CR only (out of spec) */
  1689. };
  1690. static int ntnlm = (sizeof(tnlmtab) / sizeof(struct keytab));
  1691.  
  1692. struct keytab tntab[] = {
  1693. #ifdef CK_AUTHENTICATION
  1694.     "authentication",       CK_TN_AU,  0,
  1695. #endif /* CK_AUTHENTICATION */
  1696.     "b",                    CK_TN_BM,  CM_INV|CM_ABR,
  1697.     "bi",                   CK_TN_BM,  CM_INV|CM_ABR,
  1698.     "bin",                  CK_TN_BM,  CM_INV|CM_ABR,
  1699.     "bina",                 CK_TN_BM,  CM_INV|CM_ABR,
  1700.     "binar",                CK_TN_BM,  CM_INV|CM_ABR,
  1701.     "binary",               CK_TN_BM,  CM_INV|CM_ABR,
  1702.     "binary-",              CK_TN_BM,  CM_INV|CM_ABR,
  1703.     "binary-mode",          CK_TN_BM,  CM_INV,
  1704.     "binary-transfer-mode", CK_TN_XF,  0,
  1705.     "binary-xfer-mode",     CK_TN_XF,  CM_INV,
  1706.     "bug",                  CK_TN_BUG, 0,
  1707.     "debug",                CK_TN_DB,  0,
  1708.     "delay-sb",             CK_TN_DL,  0,
  1709.     "echo",                 CK_TN_EC,  0,
  1710. #ifdef CK_ENCRYPTION
  1711.     "encryption",      CK_TN_ENC,  0,
  1712. #endif /* CK_ENCRYPTION */
  1713. #ifdef CK_ENVIRONMENT
  1714.     "environment",     CK_TN_ENV,  0,
  1715. #endif /* CK_ENVIRONMENT */
  1716. #ifdef CK_FORWARD_X
  1717.     "forward-x",       CK_TN_FX,   0,
  1718. #endif /* CK_FORWARD_X */
  1719. #ifdef IKS_OPTION
  1720.     "kermit",          CK_TN_IKS,  CM_INV,
  1721. #endif /* IKS_OPTION */
  1722. #ifdef CK_SNDLOC
  1723.     "location",        CK_TN_LOC,  0,
  1724. #endif /* CK_SNDLOC */
  1725. #ifdef CK_NAWS
  1726.     "naws",            CK_TN_NAWS, CM_INV,
  1727. #endif /* CK_NAWS */
  1728.     "newline-mode",    CK_TN_NL,   0,
  1729.     "no-encrypt-during-xfer", CK_TN_NE, CM_INV,
  1730.     "prompt-for-userid",CK_TN_PUID,0,
  1731.     "remote-echo",     CK_TN_RE,   0,
  1732. #ifdef CK_SSL
  1733.     "start-tls",       CK_TN_TLS,  CM_INV,
  1734. #endif /* CK_SSL */
  1735. #ifdef NT
  1736.     "sfu-compatibility", CK_TN_SFU, 0,
  1737. #else
  1738.     "sfu-compatibility", CK_TN_SFU, CM_INV,
  1739. #endif /* NT */
  1740.     "terminal-type",   CK_TN_TT,   0,
  1741.     "wait-for-negotiations", CK_TN_WAIT, 0,
  1742. #ifdef CK_ENVIRONMENT
  1743.     "xdisplay-location",CK_TN_XD, CM_INV,
  1744. #endif /* CK_ENVIRONMENT */
  1745.     "", 0, 0
  1746. };
  1747. int ntn = (sizeof(tntab) / sizeof(struct keytab)) - 1;
  1748.  
  1749. struct keytab tnopttab[] = {
  1750. #ifdef CK_AUTHENTICATION
  1751.     "authentication",  CK_TN_AU,   0,
  1752. #else
  1753.     "authentication",  CK_TN_AU,   CM_INV,
  1754. #endif /* CK_AUTHENTICATION */
  1755.     "binary-mode",     CK_TN_BM,   0,
  1756. #ifdef TN_COMPORT
  1757.     "c",               CK_TN_CPC,   CM_INV|CM_ABR,
  1758.     "co",              CK_TN_CPC,   CM_INV|CM_ABR,
  1759.     "com",             CK_TN_CPC,   CM_INV|CM_ABR,
  1760.     "com-port-control",CK_TN_CPC,   0,
  1761.     "comport-control", CK_TN_CPC,   CM_INV,
  1762. #else /* TN_COMPORT */
  1763.     "com-port-control",CK_TN_CPC,  CM_INV,
  1764.     "comport-control", CK_TN_CPC,   CM_INV,
  1765. #endif /* TN_COMPORT */
  1766.     "echo",            CK_TN_EC,   0,
  1767. #ifdef CK_ENCRYPTION
  1768.     "encryption",      CK_TN_ENC,  0,
  1769. #else
  1770.     "encryption",      CK_TN_ENC,  CM_INV,
  1771. #endif /* CK_ENCRYPTION */
  1772. #ifdef CK_FORWARD_X
  1773.     "forward-x",       CK_TN_FX,   0,
  1774. #else /* CK_FORWARD_X */
  1775.     "forward-x",       CK_TN_FX,   CM_INV,
  1776. #endif /* CK_FORWARD_X */
  1777.     "ibm-sak",         CK_TN_SAK,  CM_INV,
  1778. #ifdef IKS_OPTION
  1779.     "kermit",          CK_TN_IKS,  0,
  1780. #else
  1781.     "kermit",          CK_TN_IKS,  CM_INV,
  1782. #endif /* IKS_OPTION */
  1783.     "lflow",           CK_TN_FLW,  CM_INV,
  1784.     "logout",          CK_TN_LOG,  0,
  1785. #ifdef CK_NAWS
  1786.     "naws",            CK_TN_NAWS, 0,
  1787. #else
  1788.     "naws",            CK_TN_NAWS, CM_INV,
  1789. #endif /* CK_NAWS */
  1790. #ifdef CK_ENVIRONMENT
  1791.     "new-environment", CK_TN_ENV,  0,
  1792. #else
  1793.     "new-environment", CK_TN_ENV,  CM_INV,
  1794. #endif /* CK_ENVIRONMENT */
  1795.     "pragma-heartbeat",CK_TN_PHR,  CM_INV,
  1796.     "pragma-logon",    CK_TN_PLG,  CM_INV,
  1797.     "pragma-sspi",     CK_TN_PSP,  CM_INV,
  1798.     "sak",             CK_TN_SAK,  CM_INV,
  1799. #ifdef CK_SNDLOC
  1800.     "send-location",   CK_TN_LOC,  0,
  1801. #else
  1802.     "send-location",   CK_TN_LOC,  CM_INV,
  1803. #endif /* CK_SNDLOC */
  1804.     "sga",             CK_TN_SGA, CM_INV|CM_ABR,
  1805. #ifdef CK_SSL
  1806.     "start-tls",       CK_TN_TLS,  0,
  1807. #else
  1808.     "start-tls",       CK_TN_TLS,  CM_INV,
  1809. #endif /* CK_SSL */
  1810.     "suppress-go-aheads", CK_TN_SGA, 0,
  1811.     "terminal-type",   CK_TN_TT,   0,
  1812.     "ttype",           CK_TN_TT,   CM_INV|CM_ABR,
  1813. #ifdef CK_ENVIRONMENT
  1814.     "xdisplay-location", CK_TN_XD, 0,
  1815. #else
  1816.     "xdisplay-location", CK_TN_XD, CM_INV,
  1817. #endif /* CK_ENVIRONMENT */
  1818.     "", 0, 0
  1819. };
  1820. int ntnopt = (sizeof(tnopttab) / sizeof(struct keytab)) - 1;
  1821.  
  1822. struct keytab tnoptsw[] = {
  1823.     "/client",  CK_TN_CLIENT,   0,
  1824.     "/server",  CK_TN_SERVER,   0
  1825. };
  1826. int ntnoptsw = (sizeof(tnoptsw) / sizeof(struct keytab));
  1827. #endif /* TNCODE */
  1828.  
  1829. struct keytab ftrtab[] = {              /* Feature table */
  1830. #ifndef NOCSETS                         /* 0 = we have it, 1 = we don't */
  1831. "character-sets",       0, 0,
  1832. #else
  1833. "character-sets",       1, 0,
  1834. #endif /* NOCSETS */
  1835. #ifndef NOCYRIL
  1836. "cyrillic",             0, 0,
  1837. #else
  1838. "cyrillic",             1, 0,
  1839. #endif /* NOCYRIL */
  1840.  
  1841. #ifndef NOLOGDIAL
  1842. "cx-log",               0, 0,
  1843. #else
  1844. "cx-log",               1, 0,
  1845. #endif /* NOLOGDIAL */
  1846.  
  1847. #ifndef NODEBUG
  1848. "debug",                0, 0,
  1849. #else
  1850. "debug",                1, 0,
  1851. #endif /* NODEBUG */
  1852.  
  1853. #ifndef NODIAL
  1854. "dial",                 0, 0,
  1855. #else
  1856. "dial",                 1, 0,
  1857. #endif /* NODIAL */
  1858.  
  1859. #ifdef DYNAMIC
  1860. "dynamic-memory",       0, 0,
  1861. #else
  1862. "dynamic-memory",       1, 0,
  1863. #endif /* DYNAMIC */
  1864.  
  1865. #ifndef NOXFER
  1866. "file-transfer",        0, 0,
  1867. #else
  1868. "file-transfer",        1, 0,
  1869. #endif /* NOXFER */
  1870.  
  1871. #ifdef XXFWD
  1872. "forward",              0, 0,
  1873. #else
  1874. "forward",              1, 0,
  1875. #endif /* XXFWD */
  1876.  
  1877. #ifdef NEWFTP
  1878. "ftp",                  0, 0,
  1879. #else
  1880. "ftp",                  1, 0,
  1881. #endif /* NEWFTP */
  1882.  
  1883. #ifdef CK_CURSES
  1884. "fullscreen-display",   0, 0,
  1885. #else
  1886. "fullscreen-display",   1, 0,
  1887. #endif /* CK_CURSES */
  1888. #ifdef GREEK
  1889. "greek",                0, 0,
  1890. #else
  1891. "greek",                1, 0,
  1892. #endif /* GREEK */
  1893. #ifdef HEBREW
  1894. "hebrew",               0, 0,
  1895. #else
  1896. "hebrew",               1, 0,
  1897. #endif /* HEBREW */
  1898. #ifndef NOHELP
  1899. "help",                 0, 0,
  1900. #else
  1901. "help",                 1, 0,
  1902. #endif /* NOHELP */
  1903.  
  1904. #ifndef NOIKSD
  1905. "iksd",                 0, 0,
  1906. #else
  1907. "iksd",                 1, 0,
  1908. #endif /* NOIKSD */
  1909.  
  1910. #ifndef NOSPL
  1911. "if-command",           0, 0,
  1912. #else
  1913. "if-command",           1, 0,
  1914. #endif /* NOSPL */
  1915. #ifndef NOJC
  1916. #ifdef UNIX
  1917. "job-control",          0, 0,
  1918. #else
  1919. "job-control",          1, 0,
  1920. #endif /* UNIX */
  1921. #else
  1922. "job-control",          1, 0,
  1923. #endif /* NOJC */
  1924. #ifdef KANJI
  1925. "kanji",                0, 0,
  1926. #else
  1927. "kanji",                1, 0,
  1928. #endif /* KANJI */
  1929.  
  1930. #ifndef NOXFER
  1931. "kermit",               0, 0,
  1932. #else
  1933. "kermit",               1, 0,
  1934. #endif /* NOXFER */
  1935.  
  1936. #ifdef CK_KERBEROS
  1937. "kerberos",             0, 0,
  1938. #else
  1939. "kerberos",             1, 0,
  1940. #endif /* CK_KERBEROS */
  1941.  
  1942. #ifndef NOCSETS
  1943. "latin1",               0, 0,
  1944. #else
  1945. "latin1",               1, 0,
  1946. #endif /* NOCSETS */
  1947. #ifdef LATIN2
  1948. "latin2",               0, 0,
  1949. #else
  1950. "latin2",               1, 0,
  1951. #endif /* LATIN2 */
  1952.  
  1953. #ifdef CKLEARN
  1954. "learned-scripts",       0, 0,
  1955. #else
  1956. "learned-scripts",       1, 0,
  1957. #endif /* CKLEARN */
  1958.  
  1959. #ifndef NOLOCAL
  1960. "making-connections",   0, 0,
  1961. #else
  1962. "making-connections",   1, 0,
  1963. #endif /* NOLOCAL */
  1964.  
  1965. #ifdef NETCONN
  1966. "network",              0, 0,
  1967. #else
  1968. "network",              1, 0,
  1969. #endif /* NETCONN */
  1970.  
  1971. #ifdef NT
  1972. #ifdef CK_AUTHENTICATION
  1973. "ntlm",                 1, 0,
  1974. #else /* CK_AUTHENTICATION */
  1975. "ntlm",                 0, 0,
  1976. #endif /* CK_AUTHENTICATION */
  1977. #else /* NT */
  1978. "ntlm",                 0, 0,
  1979. #endif /* NT */
  1980.  
  1981. #ifdef PIPESEND
  1982. "pipes",                0, 0,
  1983. #else
  1984. #ifdef NETCMD
  1985. "pipes",                0, 0,
  1986. #endif /* NETCMD */
  1987. #endif /* PIPESEND */
  1988. #ifndef PIPESEND
  1989. #ifndef NETCMD
  1990. "pipes",                1, 0,
  1991. #endif /* PIPESEND */
  1992. #endif /* NETCMD */
  1993.  
  1994. #ifdef NETPTY
  1995. "pty",                  0, 0,
  1996. #else
  1997. "pty",                  1, 0,
  1998. #endif /* NETPTY */
  1999.  
  2000. #ifndef NOPUSH
  2001. "push",                 0, 0,
  2002. #else
  2003. "push",                 1, 0,
  2004. #endif /* PUSH */
  2005.  
  2006. #ifdef CK_REDIR
  2007. "redirect",             0, 0,
  2008. #else
  2009. "redirect",             1, 0,
  2010. #endif /* CK_REDIR */
  2011.  
  2012. #ifdef CK_RTSCTS
  2013. "rts/cts",              0, 0,
  2014. #else
  2015. "rts/cts",              1, 0,
  2016. #endif /* RTS/CTS */
  2017.  
  2018. #ifndef NOSCRIPT
  2019. "script-command",       0, 0,
  2020. #else
  2021. "script-command",       1, 0,
  2022. #endif /* NOSCRIPT */
  2023. #ifndef NOSERVER
  2024. "server-mode",          0, 0,
  2025. #else
  2026. "server-mode",          1, 0,
  2027. #endif /* NOSERVER */
  2028.  
  2029. #ifndef NOSEXP
  2030. "sexpression",          0, 0,
  2031. #else
  2032. "sexpression",          1, 0,
  2033. #endif /* NOSEXP */
  2034.  
  2035. #ifndef NOSHOW
  2036. "show-command",         0, 0,
  2037. #else
  2038. "show-command",         1, 0,
  2039. #endif /* NOSHOW */
  2040.  
  2041. #ifdef CK_SRP
  2042. "srp",                  0, 0,
  2043. #else
  2044. "srp",                  1, 0,
  2045. #endif /* CK_SRP */
  2046.  
  2047. #ifdef SSHBUILTIN
  2048. "ssh",                  0, 0,
  2049. #else /* SSHBUILTIN */
  2050. "ssh",                  1, 0,
  2051. #endif /* SSHBUILTIN */
  2052.  
  2053. #ifdef CK_SSL
  2054. "ssl/tls",              0, 0,
  2055. #else
  2056. "ssl/tls",              1, 0,
  2057. #endif /* CK_SSL */
  2058.  
  2059. #ifndef NOXMIT
  2060. "transmit",             0, 0,
  2061. #else
  2062. "transmit",             1, 0,
  2063. #endif /* NOXMIT */
  2064.  
  2065. #ifdef UNICODE
  2066. "unicode",              0, 0,
  2067. #else
  2068. "unicode",              1, 0,
  2069. #endif /* UNICODE */
  2070.  
  2071. #ifdef CK_XYZ
  2072. "xyzmodem",             0, 0,
  2073. #else
  2074. "xyzmodem",             1, 0,
  2075. #endif /* NOXMIT */
  2076.  
  2077. "", 0, 0
  2078. };
  2079. int nftr = (sizeof(ftrtab) / sizeof(struct keytab)) - 1;
  2080.  
  2081. struct keytab desttab[] = {             /* SET DESTINATION */
  2082. #ifdef CALIBRATE
  2083.     "calibrate", DEST_N, CM_INV,
  2084. #endif /* CALIBRATE */
  2085.     "disk",    DEST_D, 0,
  2086. #ifdef CALIBRATE
  2087.     "nowhere", DEST_N, 0,
  2088. #endif /* CALIBRATE */
  2089.     "printer", DEST_P, 0,
  2090.     "screen",  DEST_S, 0
  2091. };
  2092. int ndests =  (sizeof(desttab) / sizeof(struct keytab));
  2093.  
  2094. #ifndef NOSPL           /* Used only with script programming items... */
  2095.  
  2096. #ifndef NOSERVER                        /* This is just to avoid some */
  2097. #define CK_PARSDIR                      /* "statement not reached" */
  2098. #else                                   /* complaints... */
  2099. #ifndef NODIAL
  2100. #define CK_PARSDIR
  2101. #endif /* NODIAL */
  2102. #endif /* NOSERVER */
  2103.  
  2104. /*
  2105.   cx == 0 means dial directory
  2106.   cx == 1 means network directory
  2107.   cx == 2 means a directory path list
  2108. */
  2109. static int
  2110. parsdir(cx) int cx; {
  2111.     int i, x, y, dd;                    /* Workers */
  2112.     int nxdir;
  2113.     char *s;
  2114.     char ** xdir;
  2115.     char *pp[MAXGETPATH];               /* Temporary name pointers */
  2116. #ifdef ZFNQFP
  2117.     struct zfnfp * fnp;
  2118. #ifdef OS2
  2119.     char * env;
  2120.     char dirpath[4096];
  2121. #else /* OS2 */
  2122.     char dirpath[1024];                 /* For fully qualified filenames */
  2123. #endif /* OS2 */
  2124. #endif /* ZFNQFP */
  2125.  
  2126.     int max = 0;                        /* Maximum number of things to parse */
  2127.     char c;
  2128.  
  2129. #ifndef NODIAL
  2130.     if (cx == 0) {                      /* Dialing */
  2131.         nxdir = ndialdir;
  2132.         xdir = dialdir;
  2133.         max = MAXDDIR;
  2134.     } else
  2135. #ifdef NETCONN
  2136.     if (cx == 1) {                      /* Network */
  2137.         nxdir = nnetdir;
  2138.         xdir = netdir;
  2139.         max = MAXDDIR;
  2140.     } else
  2141. #endif /* NETCONN */
  2142. #endif /* NODIAL */
  2143. #ifndef NOSERVER
  2144.     if (cx == 2) {                      /* GET path */
  2145.         nxdir = ngetpath;
  2146.         xdir = getpath;
  2147.         max = MAXGETPATH;
  2148.     } else                              /* Called with invalid function code */
  2149. #endif /* NOSERVER */
  2150.       return(-2);
  2151.  
  2152.     for (i = 0; i < MAXGETPATH; i++)    /* Init these. */
  2153.       pp[i] = NULL;
  2154.  
  2155. #ifdef CK_PARSDIR
  2156.     dd = 0;                             /* Temporary name counter */
  2157.     while (1) {
  2158.         if (cx != 2) {                  /* Dialing or Network Directory */
  2159. #ifdef OS2
  2160.             int len;
  2161.             char * appdata0 = NULL, * appdata1 = NULL;
  2162. #ifdef NT
  2163.             env = getenv("K95PHONES");
  2164.             makestr(&appdata0,(char *)GetAppData(0));
  2165.             makestr(&appdata1,(char *)GetAppData(1));
  2166. #else /* NT */
  2167.             env = getenv("K2PHONES");
  2168. #endif /* NT */
  2169.             if (!env)
  2170.               env = getenv("K95PHONES");
  2171.             if (!env)
  2172.               env = "";
  2173.  
  2174.             dirpath[0] = '\0';
  2175.             len = strlen(env) + 2*strlen(startupdir) + 2*strlen(inidir)
  2176.                 + (appdata0?2*strlen(appdata0):0) 
  2177.                 + (appdata1?2*strlen(appdata1):0)
  2178.                 + 2*strlen(zhome()) + 2*strlen(exedir) + 8*strlen("PHONES/")
  2179.                 + 12;
  2180.             if (len < 4096)             /* SAFE */
  2181.               sprintf(dirpath,
  2182.                     "%s%s%s;%s%s;%s%s%s%s%s%s%s%s%s;%s%s;%s;%s%s",
  2183.                     /* Semicolon-separated path list */
  2184.                     env,
  2185.                     (env[0] && env[strlen(env)-1] == ';') ? "" : ";",
  2186.                     startupdir,
  2187.                     startupdir, "PHONES/",
  2188.                     appdata1 ? appdata1 : "", 
  2189.                     appdata1 ? "Kermit 95;" : "",
  2190.                     appdata1 ? appdata1 : "", 
  2191.                     appdata1 ? "Kermit 95/PHONES/;" : "",
  2192.                     appdata0 ? appdata0 : "", 
  2193.                     appdata0 ? "Kermit 95;" : "",
  2194.                     appdata0 ? appdata0 : "", 
  2195.                     appdata0 ? "Kermit 95/PHONES/;" : "",
  2196.                     inidir,
  2197.                     inidir, "PHONES/",
  2198.                     zhome(),
  2199.                     zhome(), "PHONES/",
  2200.                     exedir,
  2201.                     exedir, "PHONES/"
  2202.                     );
  2203. #ifdef NT
  2204.             makestr(&appdata0,NULL);
  2205.             makestr(&appdata1,NULL);
  2206. #endif /* NT */
  2207. #else
  2208. #ifdef UNIX
  2209.             y = 1024;
  2210.             s = dirpath;
  2211.             zzstring("\\v(home)",&s,&y);
  2212. #endif /* UNIX */
  2213. #endif /* OS2 */
  2214.             y = cmifip(
  2215.                   "Names of one or more directory files, separated by spaces",
  2216.                        "",&s,&x,0,
  2217. #ifdef OS2ORUNIX
  2218.                        dirpath,
  2219. #else
  2220.                        NULL,
  2221. #endif /* OS2ORUNIX */
  2222.                        xxstring
  2223.                        );
  2224.         } else {                        /* List of directory names */
  2225.             x = 0;
  2226.             y = cmdir("Directory name","",&s,xxstring);
  2227.         }
  2228.         if (y < 0) {
  2229.             if (y == -3) {              /* EOL or user typed <CR> */
  2230.                 if ((y = cmcfm()) < 0) return(y);
  2231.                 for (i = 0; i < max; i++) { /* Clear these */
  2232.                     if (i < nxdir && xdir[i]) {
  2233.                         free(xdir[i]);
  2234.                     }
  2235.                     xdir[i] = (i < dd) ? pp[i] : NULL;
  2236.                 }
  2237. #ifndef NODIAL
  2238.                 if (cx == 0)
  2239.                   ndialdir = dd;
  2240. #ifdef NETCONN
  2241.                 if (cx == 1)
  2242.                   nnetdir = dd;
  2243. #endif /* NETCONN */
  2244. #endif /* NODIAL */
  2245. #ifndef NOSERVER
  2246.                 if (cx == 2)
  2247.                   ngetpath = dd;
  2248. #endif /* NOSERVER */
  2249.                 return(success = 1);
  2250.  
  2251.             } else {                    /* Parse error */
  2252.                 for (i = 0; i < dd; i++) {  /* Free temp storage */
  2253.                     if (pp[i]) free(pp[i]); /* but don't change */
  2254.                     pp[i] = NULL;           /* anything else */
  2255.                 }
  2256.                 return(y);
  2257.             }
  2258.         }
  2259.         if (x) {
  2260.             printf("?Wildcards not allowed\n");
  2261.             return(-9);
  2262.         }
  2263. #ifdef CK_TMPDIR
  2264.         if (cx == 2 && !isdir(s)) {
  2265.             printf("?Not a directory - %s\n", s);
  2266.             return(-9);
  2267.         }
  2268. #endif /* CK_TMPDIR */
  2269.  
  2270. #ifdef ZFNQFP
  2271.         if (cx < 2) {
  2272.             if (!isabsolute(s)) {       /* If not relative get full path */
  2273.                 if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
  2274.                     if (fnp->fpath)
  2275.                       if ((int) strlen(fnp->fpath) > 0)
  2276.                         s = fnp->fpath;
  2277.                 }
  2278.             }
  2279.         }
  2280. #endif /* ZFNQFP */
  2281.         c = NUL;
  2282.         x = strlen(s);
  2283.         if (x > 0)                      /* Get last char */
  2284.           c = s[x-1];
  2285.         debug(F000,"parsdir s",s,c);
  2286.         if ((pp[dd] = malloc(strlen(s)+2)) == NULL) {
  2287.             printf("?Internal error - malloc\n");
  2288.             for (i = 0; i < dd; i++) {  /* Free temp storage */
  2289.                 if (pp[i]) free(pp[i]);
  2290.                 pp[i] = NULL;
  2291.             }
  2292.             return(-9);
  2293.         } else {                        /* Have storage for name */
  2294.             strcpy(pp[dd],s);           /* Copy string into new storage */
  2295.             debug(F111,"parsdir pp[dd] 1",pp[dd],dd);
  2296. #ifndef NOXFER
  2297.             if (cx == 2) {              /* If we are parsing directories */
  2298.                 char dirsep[2];
  2299.                 extern int myindex;     /* Append directory separator if */
  2300.                 extern struct sysdata sysidlist[]; /* it is missing...   */
  2301.                 debug(F101,"parsdir myindex","",myindex);
  2302.                 if (myindex > -1)
  2303.                   if (sysidlist[myindex].sid_unixlike)
  2304.                     if (c != sysidlist[myindex].sid_dirsep) {
  2305.                         dirsep[0] = sysidlist[myindex].sid_dirsep;
  2306.                         dirsep[1] = NUL;
  2307.                         strcat(pp[dd], (char *) dirsep); /* safe */
  2308.                     }
  2309.             }
  2310. #endif /* NOXFER */
  2311.             debug(F111,"parsdir pp[dd] 2",pp[dd],dd);
  2312.             if (++dd > max) {
  2313.                 printf("?Too many directories - %d max\n", max);
  2314.                 for (i = 0; i < dd; i++) {  /* Free temp storage */
  2315.                     if (pp[i]) free(pp[i]);
  2316.                     pp[i] = NULL;
  2317.                 }
  2318.             }
  2319.         }
  2320.     }
  2321. #endif /* CK_PARSDIR */
  2322. }
  2323. #endif /* NOSPL */
  2324.  
  2325. #ifndef NOSERVER
  2326. static int
  2327. cklogin() {
  2328.     int x;
  2329.     char * s;
  2330.     char username[LOGINLEN+1];
  2331.     char password[LOGINLEN+1];
  2332.     char account[LOGINLEN+1];
  2333.     extern char * x_user, * x_passwd, * x_acct;
  2334.     extern int x_login, x_logged;
  2335.  
  2336.     username[0] = NUL;
  2337.     password[0] = NUL;
  2338.     account[0]  = NUL;
  2339.  
  2340.     x = cmfld("username", "", &s, xxstring);
  2341.     if (x != -3) {
  2342.         if (x < 0)
  2343.           return(x);
  2344.         if ((int)strlen(s) > LOGINLEN) {
  2345.             printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
  2346.             return(-9);
  2347.         }
  2348.         ckstrncpy(username,s,LOGINLEN+1);
  2349.         x = cmfld("password", "", &s, xxstring);
  2350.         if (x != -3) {
  2351.             if (x < 0)
  2352.               return(x);
  2353.             if ((int)strlen(s) > LOGINLEN) {
  2354.                 printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
  2355.                 return(-9);
  2356.             }
  2357.             ckstrncpy(password,s,LOGINLEN+1);
  2358.             x = cmfld("account", "", &s, xxstring);
  2359.             if (x != -3) {
  2360.                 if (x < 0)
  2361.                   return(x);
  2362.                 if ((int)strlen(s) > LOGINLEN) {
  2363.                     printf("\"%s\" - too long, %d max\n", s, LOGINLEN);
  2364.                     return(-9);
  2365.                 }
  2366.                 ckstrncpy(account,s,LOGINLEN+1);
  2367.                 if ((x = cmcfm()) < 0)
  2368.                   return(x);
  2369.             }
  2370.         }
  2371.     }
  2372.     makestr(&x_user,username);
  2373.     makestr(&x_passwd,password);
  2374.     makestr(&x_acct,account);
  2375.     x_login = (x_user) ? 1 : 0;
  2376.     x_logged = 0;
  2377.     return(1);
  2378. }
  2379. #endif /* NOSERVER */
  2380.  
  2381. #ifndef NOLOCAL
  2382. static int
  2383. setdcd() {
  2384.     int x, y, z = 0;
  2385.     if ((y = cmkey(crrtab,ncrr,"","automatic",xxstring)) < 0) return(y);
  2386.     if (y == CAR_ON) {
  2387.         x = cmnum("Carrier wait timeout, seconds","0",10,&z,xxstring);
  2388.         if (x < 0) return(x);
  2389.     }
  2390.     if ((x = cmcfm()) < 0) return(x);
  2391.     carrier = ttscarr(y);
  2392.     cdtimo = z;
  2393.     return(1);
  2394. }
  2395. #endif /* NOLOCAL */
  2396.  
  2397. extern struct keytab yesno[];
  2398. extern int nyesno;
  2399.  
  2400. /* g e t y e s n o  */
  2401.  
  2402. static struct keytab q0yesno[] = {      /* Yes/No/Quit keyword table */
  2403.     "no",    0, 0,
  2404.     "ok",    1, 0,
  2405.     "yes",   1, 0
  2406. };
  2407. static int nq0yesno = (sizeof(q0yesno) / sizeof(struct keytab));
  2408.  
  2409. static struct keytab q1yesno[] = {      /* Yes/No/Quit keyword table */
  2410.     "no",    0, 0,
  2411.     "ok",    1, 0,
  2412.     "quit",  2, 0,
  2413.     "yes",   1, 0
  2414. };
  2415. static int nq1yesno = (sizeof(q1yesno) / sizeof(struct keytab));
  2416.  
  2417. static struct keytab q2yesno[] = {      /* Yes/No/Quit keyword table */
  2418.     "go",    3, 0,
  2419.     "no",    0, 0,
  2420.     "ok",    1, 0,
  2421.     "yes",   1, 0
  2422. };
  2423. static int nq2yesno = (sizeof(q2yesno) / sizeof(struct keytab));
  2424.  
  2425. static struct keytab q3yesno[] = {      /* Yes/No/Quit keyword table */
  2426.     "go",    3, 0,
  2427.     "no",    0, 0,
  2428.     "ok",    1, 0,
  2429.     "quit",  2, 0,
  2430.     "yes",   1, 0
  2431. };
  2432. static int nq3yesno = (sizeof(q3yesno) / sizeof(struct keytab));
  2433.  
  2434.  
  2435. /* Ask question, get yes/no answer */
  2436.  
  2437. int
  2438. getyesno(msg, flags) char * msg; int flags; {
  2439. #ifdef CK_RECALL
  2440.     extern int on_recall;               /* around Password prompting */
  2441. #endif /* CK_RECALL */
  2442.     int y, z;
  2443.  
  2444. #ifndef NOLOCAL
  2445. #ifdef OS2
  2446.     extern int vmode, win95_popup, startflags;
  2447.     int vmode_sav = vmode;
  2448. #endif /* OS2 */
  2449. #endif /* NOLOCAL */
  2450.  
  2451. #ifdef CK_APC
  2452.     if ( apcactive != APC_INACTIVE && (apcstatus & APC_NOINP) ) {
  2453.         return(success = 0);
  2454.     }
  2455. #endif /* CK_APC */
  2456.  
  2457. #ifndef NOLOCAL
  2458. #ifdef OS2
  2459. #ifdef COMMENT
  2460.     if (win95_popup && !(startflags & 96)
  2461. #ifdef IKSD
  2462.         && !inserver
  2463. #endif /* IKSD */
  2464.         )
  2465.       return(popup_readyesno(vmode,NULL,msg,flags));
  2466. #endif /* COMMENT */
  2467.     if (vmode == VTERM) {
  2468.         vmode = VCMD;
  2469.         VscrnIsDirty(VTERM);
  2470.         VscrnIsDirty(VCMD);
  2471.     }
  2472. #endif /* OS2 */
  2473. #endif /* NOLOCAL */
  2474. #ifdef VMS
  2475. /*
  2476.   In VMS, whenever a TAKE file or macro is active, we restore the
  2477.   original console modes so Ctrl-C/Ctrl-Y can work.  But here we
  2478.   go interactive again, so we have to temporarily put them back.
  2479. */
  2480.     if (!xcmdsrc)
  2481.       concb((char)escape);
  2482. #endif /* VMS */
  2483.  
  2484. #ifdef CK_RECALL
  2485.     on_recall = 0;
  2486. #endif /* CK_RECALL */
  2487.     cmsavp(psave,PROMPTL);              /* Save old prompt */
  2488.     cmsetp(msg);                        /* Make new prompt */
  2489.     z = 0;                              /* Initialize answer to No. */
  2490.     cmini(ckxech);                      /* Initialize parser. */
  2491.     do {
  2492.         prompt(NULL);                   /* Issue prompt. */
  2493.         switch (flags) {
  2494.           case 0:  y = cmkey(q0yesno,nq0yesno,"","",NULL); break;
  2495.           case 1:  y = cmkey(q1yesno,nq1yesno,"","",NULL); break;
  2496.           case 2:  y = cmkey(q2yesno,nq2yesno,"","",NULL); break;
  2497.           default: y = cmkey(q3yesno,nq3yesno,"","",NULL);
  2498.         }
  2499.         if (y < 0) {
  2500.             if (y == -4) {              /* EOF */
  2501.                 z = y;
  2502.                 break;
  2503.             } else if (y == -3)         /* No answer? */
  2504.               printf(" Please respond; type '?' to see valid answers.\n");
  2505.             cmini(ckxech);
  2506.         } else {
  2507.             z = y;                      /* Save answer */
  2508.             y = cmcfm();                /* Get confirmation */
  2509.         }
  2510.     } while (y < 0);                    /* Continue till done */
  2511.     cmsetp(psave);                      /* Restore real prompt */
  2512. #ifdef VMS
  2513.     if (cmdlvl > 0)                     /* In VMS and not at top level, */
  2514.       conres();                         /*  restore console again. */
  2515. #endif /* VMS */
  2516. #ifndef NOLOCAL
  2517. #ifdef OS2
  2518.     if (vmode != vmode_sav) {
  2519.         vmode = VTERM;
  2520.         VscrnIsDirty(VCMD);
  2521.         VscrnIsDirty(VTERM);
  2522.     }
  2523. #endif /* OS2 */
  2524. #endif /* NOLOCAL */
  2525.     return(z);
  2526. }
  2527.  
  2528. #ifdef KUI
  2529. extern HWND hwndConsole;
  2530. _PROTOTYP(int gui_txt_dialog,(char *,char *,int,char *,int,char *,int));
  2531. _PROTOTYP(int gui_mtxt_dialog,(char *,int,struct txtbox []));
  2532. _PROTOTYP(int gui_position,(int, int));
  2533. _PROTOTYP(int gui_resize_mode,(int));
  2534. _PROTOTYP(int gui_win_run_mode,(int));
  2535. _PROTOTYP(int gui_saveas_dialog,(char *,char *, int, char *, char *, int));
  2536. extern int gui_dialog;
  2537. #endif /* KUI */
  2538.  
  2539. /* u q _ o k  --  User Query, get Yes/No or OK Cancel  */
  2540. /*
  2541.   Call with:  
  2542.     preface: Explanatory text to print, or NULL.
  2543.     prompt:  Prompt.
  2544.     mask:    Bitmask for legal responses: 1 = OK or Yes; 2 = No or Cancel.
  2545.     help:    Help text (array of strings or NULL) [not used by parser].
  2546.     dflt:    Default response (1 or 2) [not used by parser].
  2547.   Returns:
  2548.    -1:       Invalid argument(s).
  2549.     0:       User said No or Cancel.
  2550.     1        User said Yes or OK.    
  2551.   Notes:
  2552.     preface and prompt should not include final line terminator but may
  2553.     include embedded ones.  Help text is in case GUI dialog needs a Help
  2554.     button; final element of help-string array is "".  dflt is used by GUI
  2555.     to highlight the default response button.
  2556. */
  2557. int
  2558. #ifdef CK_ANSIC
  2559. uq_ok(char * preface, char * prompt, int mask,char ** help, int dflt)
  2560. #else /* CK_ANSIC */
  2561. uq_ok(preface,prompt,mask,help,dflt)
  2562.     char * preface, * prompt, ** help;
  2563.     int mask, dflt;
  2564. #endif /* CK_ANSIC */
  2565. /* uq_ok */ {
  2566.     int rc, len;
  2567.     char * text=NULL;
  2568.  
  2569.     if (!prompt)
  2570.       return(-1);
  2571.  
  2572.     if ((mask & 3) == 1) {        /* OK (GUI only) */
  2573. #ifdef KUI
  2574.       if ( gui_dialog ) {
  2575.     /* This one is for popup help, alerts, etc */
  2576.         if (preface) {
  2577.             len = strlen(preface) + strlen(prompt) + 4;
  2578.             text = (char *)malloc(len);
  2579.             ckmakmsg(text,len,preface,"\n",prompt,NULL);
  2580.         }
  2581.         rc = MessageBox(hwndConsole,
  2582.                          text ? text : prompt,
  2583.                          prompt,
  2584.                          MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
  2585.         ShowWindowAsync(hwndConsole,SW_SHOWNORMAL);
  2586.         SetForegroundWindow(hwndConsole);
  2587.         if (text)
  2588.       free(text);
  2589.         if (!rc)
  2590.       return(-1);
  2591.         else 
  2592.       return(1);
  2593.       } else
  2594. #endif  /* KUI */
  2595.       {
  2596.     if (preface)            /* Just display the text, if any */
  2597.       printf("%s\n",preface);
  2598.     if (prompt)
  2599.       printf("%s\n",prompt);
  2600.         return(1);
  2601.       }
  2602.     } else if ((mask & 3) == 3) {    /* Yes/No or OK/Cancel */
  2603. #ifdef KUI
  2604.       if ( gui_dialog ) {
  2605.         if (preface) {
  2606.             len = strlen(preface) + strlen(prompt) + 4;
  2607.             text = (char *)malloc(len);
  2608.             ckmakmsg(text,len,preface,"\n",prompt,NULL);
  2609.         }
  2610.         rc = MessageBox(hwndConsole,
  2611.                          text ? text : prompt,
  2612.                          prompt,
  2613.                          MB_YESNO | MB_ICONINFORMATION | MB_TASKMODAL | 
  2614.                          (dflt == 2 ? MB_DEFBUTTON2 : MB_DEFBUTTON1));
  2615.         ShowWindowAsync(hwndConsole,SW_SHOWNORMAL);
  2616.         SetForegroundWindow(hwndConsole);
  2617.         if (text)
  2618.       free(text);
  2619.         if (!rc)
  2620.       return(-1);
  2621.         else if (rc == IDNO || rc == IDCANCEL)
  2622.       return(0);
  2623.         else
  2624.       return(1);
  2625.       } else
  2626. #endif  /* KUI */
  2627.       {
  2628.     if (preface)
  2629.       printf("%s\n",preface);
  2630.     return(getyesno(prompt,0));
  2631.       }
  2632.     } else {
  2633.     printf("?Internal error: uq_ok()\n");
  2634.     return(-1);
  2635.     }
  2636. }
  2637.  
  2638. /* u q _ t x t  --  User Query, get single text response  */
  2639. /*
  2640.   Call with:  
  2641.     preface: Explanatory text to print, or NULL.
  2642.     prompt:  Prompt. 
  2643.     echo:    0 = don't echo; 1 = echo; 2 = echo with asterisks.
  2644.     help:    Help text (array of strings or NULL) [not used by parser].
  2645.     buf:     Pointer to result buffer.
  2646.     buflen:  Length of result buffer.
  2647.     dflt:    Default response text or NULL [not used by parser].
  2648.     timer:   Optional Timeout
  2649.   Returns:
  2650.     0:       User said No or Cancel.
  2651.     1        User said Yes or OK.    
  2652.   Notes:
  2653.     preface, prompt, and help as for uq_ok().
  2654. */
  2655. int
  2656. #ifdef CK_ANSIC
  2657. uq_txt(char * preface, char * prompt, int echo, char ** help, char * buf, 
  2658.        int buflen, char *dflt)
  2659. #else /* CK_ANSIC */
  2660. uq_txt(preface,prompt,echo,help,buf,buflen,dflt,timer)
  2661.     char * preface, * prompt, ** help, * buf, * dflt; 
  2662.     int buflen, echo, timer;
  2663. #endif /* CK_ANSIC */
  2664. {
  2665. #ifndef NOLOCAL
  2666. #ifdef OS2
  2667.     extern int vmode;
  2668.     extern int startflags;
  2669.     extern int win95_popup;
  2670. #endif /* OS2 */
  2671. #endif /* NOLOCAL */
  2672.     int rc; 
  2673.  
  2674.     if (buflen < 1 || !buf)
  2675.       return(0);
  2676. #ifdef KUI
  2677.     if ( gui_dialog ) {
  2678.         rc = gui_txt_dialog(preface,prompt,echo,buf,buflen,dflt,0);
  2679.         if ( rc > -1 )
  2680.             return(rc);
  2681.     /* Otherwise, the dialog could not be created.  Fallback to text mode */
  2682.     } 
  2683. #endif /* KUI */
  2684. #ifndef NOLOCAL
  2685. #ifdef OS2
  2686.     if (win95_popup && !(startflags & 96)
  2687. #ifdef IKSD
  2688.          && !inserver
  2689. #endif /* IKSD */
  2690.          ) {
  2691.         debok = 0;                          /* Don't log */
  2692.         if (echo == 1)
  2693.                 popup_readtext(vmode,preface,prompt,buf,buflen,0);
  2694.             else
  2695.                 popup_readpass(vmode,preface,prompt,buf,buflen,0);
  2696.         debok = 1;
  2697.         return(1);
  2698.     }
  2699. #endif /* OS2 */
  2700. #endif /* NOLOCAL */
  2701.  
  2702.     if (preface)
  2703.       printf("%s\n",preface);
  2704.     if (echo == 1)
  2705.       readtext(prompt,buf,buflen);
  2706.     else
  2707.       readpass(prompt,buf,buflen);
  2708.     return(1);                /* (no buttons in parser) */
  2709. }
  2710.  
  2711. /* u q _ m t x t  --  User Query, get multiple text responses */
  2712. /*
  2713.   Call with:  
  2714.     preface: Explanatory text to print, or NULL.
  2715.     help:    Help text (array of strings or NULL) [not used by parser].
  2716.     n:       Number of responses wanted.
  2717.     field:   Array of struct txtbox, one element per field, see ckuusr.h.
  2718.   Returns:
  2719.     0:       User said No or Cancel.
  2720.     1        User said Yes or OK.    
  2721.   Notes:
  2722.     preface and help as for uq_ok().
  2723. */
  2724. int
  2725. #ifdef CK_ANSIC
  2726. uq_mtxt(char * preface,char **help, int n, struct txtbox field[])
  2727. #else /* CK_ANSIC */
  2728. uq_mtxt(preface,help,n,field)
  2729.     char * preface; char ** help; int n; struct txtbox field[]; 
  2730. #endif /* CK_ANSIC */
  2731. {
  2732. #ifndef NOLOCAL
  2733. #ifdef OS2
  2734.     extern int vmode;
  2735.     extern int startflags;
  2736.     extern int win95_popup;
  2737. #endif /* OS2 */
  2738. #endif /* NOLOCAL */
  2739.     int i, rc;
  2740.  
  2741.     if (n < 1 || !field)
  2742.       return(0);
  2743. #ifdef KUI
  2744.     if ( gui_dialog ) {
  2745.         rc = gui_mtxt_dialog(preface, n, field);
  2746.         if ( rc > -1 )
  2747.             return(rc);
  2748.     /* Otherwise, the dialog could not be created.  Fallback to text mode */
  2749.     }
  2750. #endif /* KUI */
  2751. #ifndef NOLOCAL
  2752. #ifdef OS2
  2753.     if (win95_popup && !(startflags & 96)
  2754. #ifdef IKSD
  2755.          && !inserver
  2756. #endif /* IKSD */
  2757.          ) {
  2758.         debok = 0;                          /* Don't log */
  2759.         for (i = 0; i < n; i++) {
  2760.             if (field[i].t_echo == 1)
  2761.                 popup_readtext(vmode,preface,field[i].t_lbl,field[i].t_buf,field[i].t_len,0);
  2762.             else
  2763.                 popup_readpass(vmode,preface,field[i].t_lbl,field[i].t_buf,field[i].t_len,0);
  2764.         }
  2765.         debok = 1;
  2766.         return(1);
  2767.     }
  2768. #endif /* OS2 */
  2769. #endif /* NOLOCAL */
  2770.  
  2771.     if (preface)
  2772.       printf("%s\n",preface);
  2773.     for (i = 0; i < n; i++) {
  2774.     if (field[i].t_echo == 1)
  2775.       readtext(field[i].t_lbl,field[i].t_buf,field[i].t_len);
  2776.     else
  2777.       readpass(field[i].t_lbl,field[i].t_buf,field[i].t_len);
  2778.     }
  2779.     return(1);
  2780. }
  2781.  
  2782. /* u q _ f i l e  --  User Query, get file or directory name  */
  2783. /*
  2784.   Call with:  
  2785.     preface: Explanatory text to print, or NULL.
  2786.     prompt:  Prompt string.
  2787.     fc:      Function code:
  2788.            1 = input (existing) file
  2789.            2 = existing directory 
  2790.            3 = create new output file
  2791.            4 = output file allowing append access
  2792.     help:    Help text (array of strings or NULL) [not used by parser].
  2793.     dflt:    Default response.
  2794.     result:  Pointer to result buffer.
  2795.     rlength: Length of result buffer.
  2796.  
  2797.   Returns:
  2798.    -1:       Invalid argument, result too long, or other error.
  2799.     0:       User Canceled.
  2800.     1:       OK, with file/pathname copied to result buffer.
  2801.     2:       Like 1, but for output file that is to be appended to.
  2802.  
  2803.   Notes:
  2804.     1. preface and prompt should not include final line terminator but may
  2805.        include embedded ones.  Help text is in case GUI dialog needs a Help
  2806.        button; final element of help-string array is "".
  2807.  
  2808.     2. The default might be a filename, a directory name, a relative
  2809.        pathname, or an absolute pathname.  This routine must convert it into
  2810.        into a fully qualified (absolute) pathname so the user knows exactly
  2811.        where the file is to be found or stored.  In addition, the Windows
  2812.        version of this routine must separate the directory part from the
  2813.        name part, so it can display the given directory in the file dialog,
  2814.        and put name in the filename box to be edited, replaced, or
  2815.        accepted.
  2816.  
  2817.     3. When called with FC 4, the Windows version should include "New" and
  2818.        "Append" buttons in the dialog. so the user can say whether the file
  2819.        should overwrite any file of the same name, or be appended to it.
  2820. */
  2821.  
  2822. int
  2823. #ifdef CK_ANSIC
  2824. uq_file(char * preface, char * fprompt, int fc, char ** help,
  2825.     char * dflt, char * result, int rlength)
  2826. #else /* CK_ANSIC */
  2827. uq_file(preface,fprompt,fc,help,dflt,result,rlength)
  2828.     char * preface, * fprompt, ** help, * dflt, * result;
  2829.     int fc, rlength;
  2830. #endif /* CK_ANSIC */
  2831. /* uq_file */ {
  2832.  
  2833.     int rc = -1, x, y, z;
  2834.     char * s, * p, * fullpath;
  2835.     char filebuf[CKMAXPATH+1];
  2836.  
  2837. #ifdef CK_RECALL
  2838.     extern int on_recall;
  2839. #endif /* CK_RECALL */
  2840.  
  2841. #ifdef KUI
  2842.     if ( gui_dialog ) {
  2843.         rc = gui_saveas_dialog(preface,fprompt,fc,dflt,result,rlength);
  2844.         return rc;
  2845.     }
  2846. #endif /* KUI */
  2847.  
  2848. #ifdef CK_RECALL
  2849.     on_recall = 0;
  2850. #endif /* CK_RECALL */
  2851.  
  2852.     if (preface)            /* If prefatory text given... */
  2853.       printf("%s\n",preface);        /* display it. */
  2854.  
  2855.     cmsavp(psave,PROMPTL);              /* Save old prompt */
  2856.  
  2857.     /* We get the full pathname of the proposed output file just so */
  2858.     /* we can show it to the user but we don't use it ourselves. */
  2859.  
  2860.     p = NULL;                /* Build new prompt */
  2861.     if (!dflt) dflt = "";
  2862.     if (*dflt)                /* Have default filename */
  2863.       zfnqfp(dflt,CKMAXPATH+1,filebuf);    /* Get full path */
  2864.     else
  2865.       ckmakmsg(filebuf,CKMAXPATH+1,zgtdir(),"newfile",NULL,NULL);
  2866.     fullpath = filebuf;
  2867.     x = strlen(fullpath);
  2868.  
  2869.     /* If no prompt given, build one that shows the proposed full pathname. */
  2870.  
  2871.     if (!fprompt) fprompt = "";
  2872.     if (!*fprompt) fprompt = x ? " Filename" : " Filename: ";
  2873.     y = strlen(fprompt);
  2874.     if (x > 0) {            /* Have default pathname? */
  2875.     p = (char *)malloc(x + y + 7);    /* Get temp storage */
  2876.     if (p) {            /* Build prompt */
  2877.         ckmakmsg(p,x+y+7,fprompt," [",fullpath,"]: ");
  2878.         fprompt = p;
  2879.     }
  2880.     }
  2881.     cmsetp(fprompt);            /* Make new prompt */
  2882.     if (p) free(p);            /* Free temp storage */
  2883.     cmini(ckxech);                      /* Initialize parser. */
  2884.     x = -1;
  2885.     do {
  2886.         prompt(NULL);                   /* Issue prompt. */
  2887.         switch (fc) {            /* Parse depends on function code */
  2888.           case 1:            /* Input file */
  2889.         x = cmifi("Name of existing file",dflt,&s,&y,xxstring);
  2890.         rc = 1;
  2891.         break;
  2892.       case 2:            /* Directory */
  2893.         x = cmdir("Directory name",dflt,&s,xxstring);
  2894.         rc = 1;
  2895.         break;
  2896.           case 3:            /* New output file */
  2897.         /* Fall thru... */
  2898.       case 4:            /* Output file - Append allowed */
  2899.         x = cmofi("Output file specification",dflt,&s,xxstring);
  2900.         rc = (fc == 4) ? 1 : 2;
  2901.         break;
  2902.           default:            /* Bad function code */
  2903.         goto x_uq_file;
  2904.         }
  2905.         if (x < 0) {            /* Parse error */
  2906.         filebuf[0] = NUL;
  2907.             if (x == -4) {              /* EOF */
  2908.                 break;
  2909.             } else if (x == -3)         /* No answer? */
  2910.               printf(fc == 2 ?
  2911.              " Please enter a directory name.\n" :
  2912.              " Please enter a filename.\n"
  2913.              );
  2914.             cmini(ckxech);
  2915.         } else {
  2916.         z = strlen(s);
  2917.         if (z > rlength || ckstrncpy(filebuf,brstrip(s),CKMAXPATH+1) < z) {
  2918.         printf("?Name too long\n");
  2919.         x = -9;
  2920.         } else
  2921.           x = cmcfm();        /* Get confirmation */
  2922.         }
  2923.     if (fc == 1 && x > -1 && y > 0) {
  2924.         printf("?Wildcards not allowed\n");
  2925.         x = -9;
  2926.     }
  2927.     } while (x < 0);                    /* Continue till done */
  2928.  
  2929.   x_uq_file:
  2930.     if (x < 0)
  2931.       rc = -1;
  2932.  
  2933.     cmsetp(psave);                      /* Restore real prompt */
  2934.  
  2935.     if (rc > 0)
  2936.       ckstrncpy(result,filebuf,rlength);
  2937.     return(rc);
  2938. }
  2939.  
  2940.  
  2941. #ifdef CK_PERMS
  2942. #ifdef UNIX
  2943.  
  2944. _PROTOTYP( int zsetperm, (char *, int));
  2945.  
  2946. /* CHMOD command for UNIX only */
  2947.  
  2948. #define CHM_DIR 0
  2949. #define CHM_DOT 1
  2950. #define CHM_FIL 2
  2951. #define CHM_LIS 3
  2952. #define CHM_NOL 4
  2953. #define CHM_QUI 5
  2954. #define CHM_REC 6
  2955. #define CHM_VRB 7
  2956. #define CHM_PAG 8
  2957. #define CHM_NOP 9
  2958. #define CHM_TYP 10
  2959. #define CHM_SIM 11
  2960.  
  2961. static struct keytab uchmodsw[] = {
  2962.     "/directories", CHM_DIR, 0,
  2963.     "/dotfiles",    CHM_DOT, 0,
  2964.     "/files",       CHM_FIL, 0,
  2965.     "/list",        CHM_LIS, 0,
  2966.     "/nolist",      CHM_NOL, 0,
  2967.     "/nopage",      CHM_NOP, 0,
  2968.     "/page",        CHM_PAG, 0,
  2969.     "/quiet",       CHM_QUI, CM_INV,
  2970.     "/recursive",   CHM_REC, 0,
  2971.     "/simulate",    CHM_SIM, 0,
  2972.     "/type",        CHM_TYP, CM_ARG,
  2973.     "/verbose",     CHM_VRB, CM_INV,
  2974. };
  2975. static int nchmodsw = (sizeof(uchmodsw) / sizeof(struct keytab));
  2976.  
  2977. int
  2978. douchmod() {
  2979.     extern int recursive, nscanfile, diractive;
  2980. #ifdef CK_TTGWSIZ
  2981.     extern int tt_rows, tt_cols;
  2982.     int n = 0;
  2983. #endif /* CK_TTGWSIZ */
  2984.     int i, files = 1, t1 = 1, t2 = 0, x, y, z, verbose = 0, rc = 1, paging;
  2985.     int xmode = -1, fs = 0, getval = 0, simulate = 0, wild = 0;
  2986.     char c, * s;
  2987.     struct FDB sw, nu;
  2988.  
  2989.     if (xaskmore < 0) {
  2990. #ifdef CK_TTGWSIZ
  2991.         xaskmore = 1;
  2992. #else
  2993.         xaskmore = 0;
  2994. #endif /* CK_TTGWSIZ */
  2995.     }
  2996.     paging = xaskmore;
  2997.  
  2998.     cmfdbi(&sw,                         /* First FDB - command switches */
  2999.            _CMKEY,                      /* fcode */
  3000.            "Octal file permission code, or switch",
  3001.            "",                          /* default */
  3002.            "",                          /* addtl string data */
  3003.            nchmodsw,                    /* addtl numeric data 1: tbl size */
  3004.            4,                           /* addtl numeric data 2: 4 = cmswi */
  3005.            xxstring,                    /* Processing function */
  3006.            uchmodsw,                    /* Keyword table */
  3007.            &nu                          /* Pointer to next FDB */
  3008.            );
  3009.     cmfdbi(&nu,
  3010.            _CMNUM,                      /* Number */
  3011.            "",                          /* Help message */
  3012.            "",                          /* Default */
  3013.            "",                          /* N/A */
  3014.            8,                           /* Radix = 8 */
  3015.            0,                           /* N/A */
  3016.            xxstring,                    /* Processing function */
  3017.            NULL,                        /* N/A */
  3018.            NULL                         /* Next */
  3019.            );
  3020.  
  3021.     while (1) {
  3022.         if ((x = cmfdb(&sw)) < 0) {
  3023.             if (x == -3) {
  3024.                 x = -9;
  3025.                 printf("?Filename required\n");
  3026.             }
  3027.             return(x);
  3028.         }
  3029.         if (cmresult.fcode != _CMKEY)
  3030.           break;
  3031.         c = cmgbrk();
  3032.         getval = (c == ':' || c == '=');
  3033.         if (getval && !(cmgkwflgs() & CM_ARG)) {
  3034.             printf("?This switch does not take an argument\n");
  3035.             return(-9);
  3036.         }
  3037.         if (!getval && (cmgkwflgs() & CM_ARG)) {
  3038.             printf("?This switch requires an argument\n");
  3039.             return(-9);
  3040.         }
  3041.         switch (cmresult.nresult) {
  3042.           case CHM_DIR:
  3043.             t1 = 1;
  3044.             t2 = 1;
  3045.             break;
  3046.           case CHM_DOT:
  3047.             matchdot = 1;
  3048.             break;
  3049.           case CHM_FIL:
  3050.             t1 = 0;
  3051.             t2 = 0;
  3052.             break;
  3053.           case CHM_LIS:
  3054.           case CHM_VRB:
  3055.             verbose = 1;
  3056.             break;
  3057.           case CHM_NOL:
  3058.           case CHM_QUI:
  3059.             verbose = 0;
  3060.             break;
  3061.           case CHM_REC:
  3062.             recursive = 1;
  3063.             break;
  3064.           case CHM_PAG:
  3065.             verbose = 1;
  3066.             paging = 1;
  3067.             break;
  3068.           case CHM_NOP:
  3069.             paging = 0;
  3070.             break;
  3071.           case CHM_SIM:
  3072.             simulate = 1;
  3073.             break;
  3074.           case CHM_TYP: {
  3075.               extern struct keytab txtbin[];
  3076.               if ((x = cmkey(txtbin,3,"","",xxstring)) < 0)
  3077.                 return(x);
  3078.               if (x == 2) {             /* ALL */
  3079.                   xmode = -1;
  3080.               } else {                  /* TEXT or BINARY only */
  3081.                   xmode = x;
  3082.                   fs = 1;
  3083.               }
  3084.               break;
  3085.           }
  3086.         }
  3087.     }
  3088.     z = cmresult.nresult;
  3089.     x = cmifi2("File specification","",&s,&wild,t1,NULL,xxstring,t2);
  3090.     if (x < 0) {
  3091.         if (x == -3) {
  3092.             printf("?A file specification is required\n");
  3093.             return(-9);
  3094.         } else
  3095.           return(x);
  3096.     }
  3097.     ckstrncpy(tmpbuf,s,TMPBUFSIZ);
  3098.     s = tmpbuf;
  3099.     if ((x = cmcfm()) < 0)
  3100.       return(x);
  3101. #ifdef ZXREWIND
  3102.     if (wild) files = zxrewind();
  3103. #else
  3104.     if (wild) files = nzxpand(s,0);
  3105. #endif /* ZXREWIND */
  3106.  
  3107.     if (paging > -1)
  3108.       xaskmore = paging;
  3109.  
  3110. #ifdef CK_TTGWSIZ
  3111.     if (verbose && paging) {
  3112. #ifdef OS2
  3113.         ttgcwsz();
  3114. #else /* OS2 */
  3115.         if (ttgwsiz() > 0) {
  3116.             if (tt_rows > 0 && tt_cols > 0) {
  3117.                 cmd_rows = tt_rows;
  3118.                 cmd_cols = tt_cols;
  3119.             }
  3120.         }
  3121. #endif /* OS2 */
  3122.     }
  3123. #endif /* CK_TTGWSIZ */
  3124.  
  3125.     for (i = 0; i < files; i++) {
  3126.         if (files == 1 && wild == 0) {  /* For "chmod 777 ." */
  3127.             ckstrncpy(line,s,LINBUFSIZ);
  3128.         } else {
  3129.             x = znext(line);
  3130.             if (x < 1) {
  3131.                 if (i == 0) {
  3132.                     printf("?No files match - \"%s\"\n",line);
  3133.                     return(-9);
  3134.                 }
  3135.                 return(1);
  3136.             }
  3137.         }
  3138.         if (fs) {
  3139. #ifdef VMSORUNIX
  3140.             /* If /TYPE:TEXT or BINARY given, skip directories and links */
  3141.             /* since they are neither text nor binary. */
  3142.             extern int zgfs_dir, zgfs_link;
  3143.             zgetfs(line);
  3144.             if (zgfs_dir || zgfs_link)
  3145.               continue;
  3146. #else
  3147.             if (zchki(line) < 0)
  3148.               continue;
  3149. #endif /* VMSORUNIX */
  3150.             /* Regular file, scan it */
  3151.             switch (scanfile(line,&y,nscanfile)) {
  3152.               case FT_BIN:
  3153.                 if (xmode != 1)
  3154.                   continue;
  3155.                 break;
  3156.               case FT_TEXT:
  3157.               case FT_7BIT:
  3158.               case FT_8BIT:
  3159. #ifdef UNICODE
  3160.               case FT_UTF8:
  3161.               case FT_UCS2:
  3162. #endif /* UNICODE */
  3163.                 if (xmode != 0)
  3164.                   continue;
  3165.             }
  3166.         }
  3167.         if (simulate) {
  3168. #ifdef UNIX
  3169.             extern int zchkod;          /* Unidentified Flying */
  3170.             int xx = zchkod;            /* API Extension... */
  3171.             zchkod = 1;
  3172. #endif /* UNIX */
  3173.             if (zchko(line) < 0)
  3174.               printf("%s - Access denied\n",line);
  3175.             else
  3176.               printf("%s - OK\n",line);
  3177. #ifdef UNIX
  3178.             zchkod = xx;
  3179. #endif /* UNIX */
  3180.         } else {
  3181.             if (zsetperm(line,z) < 1) {
  3182.                 if (verbose || files < 2) {
  3183.                     printf("%s: %s\n",line,ck_errstr());
  3184.                 }
  3185.                 rc = 0;
  3186.             } else if (verbose) {
  3187.                 printf("%s  %s\n",ziperm(line),line);
  3188.             }
  3189.         }
  3190. #ifdef CK_TTGWSIZ
  3191.         if (verbose && paging) {        /* Pause at end of screen */
  3192.             if (cmd_rows > 0 && cmd_cols > 0) {
  3193.                 if (++n > cmd_rows - 3) {
  3194.                     if (!askmore())
  3195.                       break;
  3196.                     else
  3197.                       n = 0;
  3198.                 }
  3199.             }
  3200.         }
  3201. #endif /* CK_TTGWSIZ */
  3202.  
  3203.     }
  3204.     return(success = rc);
  3205. }
  3206. #endif /* UNIX */
  3207. #endif /* CK_PERMS */
  3208.  
  3209. #ifndef NOSPL                           /* S-Expressions */
  3210. #ifndef NOSEXP
  3211.  
  3212. struct keytab sexptab[] = {
  3213.     "depth-limit", 1, 0,
  3214.     "echo-result", 0, 0
  3215. };
  3216.  
  3217. static int sexpmaxdep = 1000;           /* Maximum depth */
  3218.  
  3219. #define xxfloat(s,x) \
  3220. ((isdigit(*s)||(*s=='-')||(*s=='+')||(*s=='.')||(*s=='\040'))?isfloat(s,x):0)
  3221.  
  3222. #define SX_ADD  1                       /* Symbols for built-in operators */
  3223. #define SX_SUB  2
  3224. #define SX_MUL  3
  3225. #define SX_DIV  4
  3226. #define SX_POW  5
  3227. #define SX_SET  6
  3228. #define SX_MOD  7
  3229. #define SX_EVA  8
  3230. #define SX_EXP  9
  3231. #define SX_AEQ 10
  3232. #define SX_ALT 11
  3233. #define SX_AGT 12
  3234. #define SX_ALE 13
  3235. #define SX_AGE 14
  3236. #define SX_MIN 15
  3237. #define SX_MAX 16
  3238. #define SX_SQR 17
  3239. #define SX_FLR 18
  3240. #define SX_CEI 19
  3241. #define SX_TRU 20
  3242. #define SX_ABS 21
  3243. #define SX_ROU 22
  3244. #define SX_LET 23
  3245. #define SX_LGN 24
  3246. #define SX_LGX 25
  3247. #define SX_FLO 26
  3248. #define SX_IFC 27
  3249. #define SX_NOT 28
  3250. #define SX_NEQ 29
  3251. #define SX_AND 30
  3252. #define SX_LOR 31
  3253. #define SX_SIN 32
  3254. #define SX_COS 33
  3255. #define SX_TAN 34
  3256. #define SX_BWA 35
  3257. #define SX_BWO 36
  3258. #define SX_BWX 37
  3259. #define SX_BWN 38
  3260. #define SX_XOR 39
  3261. #define SX_INC 40
  3262. #define SX_DEC 41
  3263. #define SX_QUO 42
  3264. #define SX_STR 43
  3265.  
  3266. /* Operator flags */
  3267.  
  3268. #define SXF_PRE 256                     /* Predicate */
  3269. #define SXF_ONE 512                     /* Requires one arg */
  3270. #define SXF_TWO 1024                    /* Requires two args or more */
  3271. #define SXF_FLO 2048                    /* Coerce to floating-point */
  3272.  
  3273. /* Built-in constants */
  3274.  
  3275. #define SXC_NIL 1                       /* NIL */
  3276. #define SXC_PI  2                       /* PI */
  3277. #define SXC_T   3                       /* T */
  3278.  
  3279. /*
  3280.   This is an xlookup() table and so need not be in "alhabetical" order.
  3281.   Therefore entries are arranged to minimize search for most common
  3282.   operators.
  3283. */
  3284. static struct keytab sexpops[] = {      /* Built-in operators */
  3285.     "setq",    SX_SET, 0,               /* Global assignment */
  3286.     "+",       SX_ADD, 0,               /* Simple arithmetic */
  3287.     "-",       SX_SUB, 0,
  3288.     "*",       SX_MUL, 0,
  3289.     "/",       SX_DIV, SXF_TWO,
  3290.     "^",       SX_POW, SXF_TWO,
  3291.  
  3292.     "if",      SX_IFC, SXF_TWO,         /* IF */
  3293.     "let",     SX_LET, 0,               /* Local assignment */
  3294.     "not",     SX_NOT, SXF_ONE,         /* NOT */
  3295.     "mod",     SX_MOD, SXF_TWO,         /* Modulus */
  3296.  
  3297.     "<",       SX_ALT, SXF_PRE|SXF_TWO, /* Comparisons */
  3298.     ">",       SX_AGT, SXF_PRE|SXF_TWO,
  3299.     "<=",      SX_ALE, SXF_PRE|SXF_TWO,
  3300.     "=",       SX_AEQ, SXF_PRE|SXF_TWO,
  3301.     ">=",      SX_AGE, SXF_PRE|SXF_TWO,
  3302.     "!=",      SX_NEQ, SXF_PRE|SXF_TWO,
  3303.  
  3304.     "++",      SX_INC, SXF_ONE|SXF_TWO, /* Increment */
  3305.     "--",      SX_DEC, SXF_ONE|SXF_TWO, /* Decrement */
  3306.  
  3307.     "**",      SX_POW, SXF_TWO,         /* Common synonyms */
  3308.     "==",      SX_AEQ, SXF_PRE|SXF_TWO,
  3309.     "!",       SX_NOT, SXF_ONE,
  3310.     ".",       SX_EVA, 0,
  3311.  
  3312.     "and",     SX_AND, 0,               /* Logical operators */
  3313.     "or",      SX_LOR, 0,
  3314.     "xor",     SX_XOR, SXF_TWO,
  3315.  
  3316.     "max",     SX_MAX, SXF_ONE|SXF_TWO, /* Max and min */
  3317.     "min",     SX_MIN, SXF_ONE|SXF_TWO,
  3318.  
  3319.     "%",       SX_MOD, SXF_TWO,         /* More synonyms */
  3320.     "||",      SX_LOR, 0,
  3321.     "&&",      SX_AND, 0,
  3322.  
  3323.     "quote",   SX_QUO, SXF_ONE,
  3324.     "string",  SX_STR, SXF_ONE,
  3325.  
  3326.     "eval",    SX_EVA, 0,               /* Assorted commands */
  3327.     "abs",     SX_ABS, SXF_ONE,
  3328.     "truncate",SX_TRU, SXF_ONE|SXF_FLO,
  3329.     "round",   SX_ROU, SXF_ONE|SXF_FLO,
  3330.     "ceiling", SX_CEI, SXF_ONE|SXF_FLO,
  3331.     "floor",   SX_FLR, SXF_ONE|SXF_FLO,
  3332.     "float",   SX_FLO, SXF_ONE|SXF_FLO,
  3333.  
  3334. #ifdef FNFLOAT
  3335.     "sqrt",    SX_SQR, SXF_ONE|SXF_FLO, /* Floating point functions */
  3336.     "exp",     SX_EXP, SXF_ONE|SXF_FLO,
  3337.     "sin",     SX_SIN, SXF_ONE|SXF_FLO,
  3338.     "cos",     SX_COS, SXF_ONE|SXF_FLO,
  3339.     "tan",     SX_TAN, SXF_ONE|SXF_FLO,
  3340.     "log",     SX_LGN, SXF_ONE|SXF_FLO,
  3341.     "log10",   SX_LGX, SXF_ONE|SXF_FLO,
  3342. #endif /* FNFLOAT */
  3343.  
  3344.     "#",       SX_BWX, SXF_TWO,         /* Bitwise operators */
  3345.     "&",       SX_BWA, 0,
  3346.     "|",       SX_BWO, 0,
  3347.     "~",       SX_BWN, SXF_ONE,
  3348.     "", 0, 0                            /* (end) */
  3349. };
  3350. static int nsexpops = (sizeof(sexpops) / sizeof(struct keytab)) - 1;
  3351.  
  3352. static struct keytab sexpconsts[] = {   /* Built-in constants */
  3353.     "nil", SXC_NIL, 0,                  /* NIL (false) */
  3354.     "pi",  SXC_PI,  0,                  /* Pi (3.1415926...) */
  3355.     "t",   SXC_T,   0,                  /* T (true) */
  3356.     "", 0, 0
  3357. };
  3358. static int nsexpconsts = (sizeof(sexpconsts) / sizeof(struct keytab)) - 1;
  3359.  
  3360. int sexprc = 0;                         /* S-Expression error flag */
  3361. int sexppv = -1;                        /* Predicate value */
  3362.  
  3363. #define SXMLEN 64                       /* Macro arg list initial length */
  3364. #include <math.h>                       /* Floating-point functions */
  3365.  
  3366. _PROTOTYP( char * fpformat, (CKFLOAT, int, int) );
  3367.  
  3368. extern char math_pi[];                  /* Value of Pi */
  3369. extern int sexpecho;                    /* SET SEXPRESSION ECHO value */
  3370. extern char * sexpval;                  /* Last top-level S-Expression value */
  3371. extern char * lastsexp;                 /* Last S-Expression */
  3372. int sexprmax = 0;                       /* Longest result (for stats) */
  3373. int sexpdmax = 0;                       /* Max depth reached (for stats) */
  3374. int sexpdep  = 0;                       /* dosexp() recursion depth */
  3375. static int * sxrlen = NULL;             /* Result stack string sizes */
  3376. static char ** sxresult = NULL;         /* Result stack */
  3377.  
  3378. /*  s h o s e x p  --  Show S-Expression info  */
  3379.  
  3380. VOID
  3381. shosexp() {
  3382.     printf("\n");
  3383.     printf(" sexpression echo-result: %s\n",showooa(sexpecho));
  3384.     printf(" sexpression depth-limit: %d\n",sexpmaxdep);
  3385.     printf("\n");
  3386.     printf(" maximum depth reached:   %d\n",sexpdmax);
  3387.     printf(" longest result returned: %d\n",sexprmax);
  3388.     printf("\n");
  3389.     printf(" last sexpression:        %s\n",lastsexp ? lastsexp : "(none)");
  3390.     printf(" last value:              %s\n",sexpval ? sexpval : "(none)");
  3391.     printf("\n");
  3392. }
  3393.  
  3394.  
  3395. static char *
  3396. sexpdebug(s) char * s; {
  3397.     /* For debugging -- includes recursion depth in each debug entry */
  3398.     static char buf[64];
  3399.     ckmakmsg(buf,64,"dosexp[",ckitoa(sexpdep),"] ",s);
  3400.     return((char *)buf);
  3401. }
  3402.  
  3403. /*  d o s e x p  --  S-Expression Reader  */
  3404.  
  3405. /*  Returns value as string (empty, numeric, or non-numeric) */
  3406.  
  3407. char *
  3408. dosexp(s) char *s; {                    /* s = S-Expression */
  3409.     extern struct mtab *mactab;         /* Macro table */
  3410.     extern int maclvl, nmac;
  3411.     extern char *mrval[];
  3412.     extern int makestrlen;              /* (see makestr()) */
  3413.     struct stringarray * q = NULL;      /* cksplit() return type */
  3414.     char * p[SEXPMAX+1], ** p2;         /* List items (must be on stack) */
  3415.     char * line = NULL;                 /* For building macro argument list */
  3416.     int linelen = 0;
  3417.     int linepos = 0;
  3418.     int quote = 0;                      /* LISP quote flag */
  3419.     char * s2;                          /* Workers */
  3420.     int i, j, k, n = 0, x = 0, kw, kwflags, mx = 0;
  3421.     int result = 0, not = 0, truncate = 0, builtin = 0;
  3422.     int fpflag = 0, quit = 0, macro = 0;
  3423.     CKFLOAT fpj, fpresult = 0.0;        /* Floating-point results */
  3424.     int pflag = 0;                      /* Have predicate */
  3425.     int presult = 0;                    /* Predicate result */
  3426.     int mustfree = 0;                   /* If we malloc'd we must free */
  3427.  
  3428.     sexppv = -1;                        /* Predicate value */
  3429.     s2 = "";                            /* Default return value */
  3430.  
  3431.     if (++sexpdep > sexpmaxdep) {       /* Keep track of depth */
  3432.         printf("?S-Expression depth limit exceeded: %d\n",sexpmaxdep);
  3433.         sexprc++;
  3434.         debug(F111,sexpdebug("max depth exceeded"),s,sexprc);
  3435.     }
  3436.     if (sexpdep > sexpdmax)             /* For stats */
  3437.       sexpdmax = sexpdep;
  3438.  
  3439.     if (sexprc)                         /* Error, quit all levels */
  3440.       goto xdosexp;                     /* Always goto common exit point */
  3441.  
  3442.     debug(F111,sexpdebug("entry"),s,sexprc);
  3443.  
  3444.     if (!s) s = "";                     /* Null or empty arg */
  3445.  
  3446.     while (*s == SP) s++;               /* Strip leading spaces */
  3447.     if (!*s)                            /* so empty result */
  3448.       goto xdosexp;
  3449.  
  3450. /*
  3451.   Allocate result stack upon first use, or after it has been resized with
  3452.   SET SEXP DEPTH-LIMIT.
  3453. */
  3454.     if (!sxresult) {
  3455.         sxresult = (char **)malloc(sexpmaxdep * sizeof(char *));
  3456.         if (!sxresult) {
  3457.             printf("?Memory allocation failure - \"%s\"\n", s);
  3458.             sexprc++;
  3459.             goto xdosexp;
  3460.         }
  3461.         sxrlen = (int *)malloc(sexpmaxdep * sizeof(int));
  3462.         if (!sxrlen) {
  3463.             printf("?Memory allocation failure - \"%s\"\n", s);
  3464.             sexprc++;
  3465.             goto xdosexp;
  3466.         }
  3467.         for (i = 0; i < sexpmaxdep; i++) {
  3468.             sxresult[i] = NULL;         /* Result pointers */
  3469.             sxrlen[i] = 0;              /* Buffer sizes */
  3470.         }
  3471.     }
  3472.     s2 = s;                             /* s2 is the result pointer */
  3473.     k = 0;                              /* Length accumulator */
  3474.     if (s[0] == '(') {                  /* Starts with open paren? */
  3475.         while (*s2++) k++;              /* Get length */
  3476.         if (s[k-1] == ')') {            /* Strip outer parens if any */
  3477.             s[k-1] = NUL;
  3478.             s++;
  3479.             k -= 2;
  3480.             while (*s == SP) {          /* Strip leading spaces from result */
  3481.                 s++;
  3482.                 k--;
  3483.             }
  3484.             while (k > 0 && s[k-1] == SP) { /* And trailing spaces. */
  3485.                 s[k-1] = NUL;
  3486.                 k--;
  3487.             }
  3488.         }
  3489.         if (!*s) {                      /* If nothing remains */
  3490.             s2 = "";                    /* return empty result. */
  3491.             goto xdosexp;
  3492.         }
  3493.     }
  3494.     /* Break result up into "words" (an SEXP counts as a word) */
  3495.  
  3496.     p[0] = NULL;                        /* (We don't use element 0) */
  3497.     if (!*(s+1) || !*(s+2)) {           /* No need to call cksplit() */
  3498.         n = 1;                          /* if it's one or two chars. */
  3499.         p[1] = s;                       /* No need to malloc this either. */
  3500.         debug(F101,sexpdebug("nosplit"),"",n);
  3501.         if (s[0] == '(') {              /* () empty */
  3502.             s2 = "";
  3503.             goto xdosexp;
  3504.         }
  3505.     } else {
  3506.         q = cksplit(1,SEXPMAX,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",8,39,0);
  3507.         if (!q)
  3508.           goto xdosexp;
  3509.         n = q->a_size;                  /* Number of items */
  3510.         debug(F101,sexpdebug("split"),"",n);
  3511.         if (n < 0 || n > SEXPMAX) {     /* Check for too many */
  3512.             printf("?Too many operands: max = %d\n",SEXPMAX);
  3513.             sexprc++;
  3514.             goto xdosexp;
  3515.         }
  3516.         if (n == 0)                     /* None, result is NULL, done. */
  3517.           goto xdosexp;
  3518.         if (n == 1 && s[0] == '(') {    /* One but it's another SEXP */
  3519.             s2 = dosexp(s);
  3520.             goto xdosexp;
  3521.         }
  3522.         p2 = q->a_head;                 /* Point to result array. */
  3523.         for (i = 1; i <= n; i++) {      /* We must copy it because */
  3524.             p[i] = NULL;                /* recursive calls to dosexp() */
  3525.             if (p2[i])                  /* write over the same array */
  3526.               makestr(&(p[i]),p2[i]);
  3527.         }
  3528.         if (s[0] == '(') {              /* Operator is an S-Expression */
  3529.             s2 = dosexp(p[1]);          /* Replace it by its value */
  3530.             makestr(&(p[1]),s2);
  3531.         }
  3532.         mustfree++;                     /* Remember to free it */
  3533.     }
  3534.     debug(F110,sexpdebug("head"),p[1],0);
  3535.  
  3536.     if (n == 1 && p[1]) {
  3537.         if (*(p[1]) == '\047') {
  3538.             s2 = p[1];
  3539.             goto xdosexp;
  3540.         }
  3541.     }
  3542. /*
  3543.   This section sidesteps xlookup() of the most common operators.
  3544.   It's not necessary but it speeds up SEXP-heavy loops by about 10%.
  3545. */
  3546.     kwflags = 0;
  3547.     if (n > 0) {                        /* Look up the operator */
  3548.         s2 = p[1];                      /* Prelookup optimization... */
  3549.         if (!s2)
  3550.           s2 = "";
  3551.         if (!*s2)
  3552.           goto xdosexp;
  3553.         kw = 0;
  3554.         x = 0;
  3555.         if (isdigit(*s2)) {             /* Digit */
  3556.             x = -2;
  3557.  
  3558.         } else if (isalpha(*s2) && !*(s2+1)) { /* Single letter */
  3559.             x = -1;
  3560.  
  3561.         } else if (*s2 == 's' || *s2 == 'S') { /* SETQ */
  3562.             s2++;
  3563.             if (*s2 == 'e' || *s2 == 'E') {
  3564.                 s2++;
  3565.                 if (*s2 == 't' || *s2 == 'T') {
  3566.                     s2++;
  3567.                     if (*s2 == 'q' || *s2 == 'Q') {
  3568.                         if (!*(s2+1)) {
  3569.                             x = SX_SET;
  3570.                             kwflags = 0;
  3571.                             builtin = 1;
  3572.                         }
  3573.                     }
  3574.                 }
  3575.             }
  3576.         }
  3577.         if (!x) {
  3578.             if (!*(s2+1)) {             /* Common single-character ops */
  3579.                 if (*s2 == '+') {
  3580.                     x = SX_ADD;
  3581.                     kwflags = 0;
  3582.                     builtin = 1;
  3583.                 } else if (*s2 == '-') {
  3584.                     x = SX_SUB;
  3585.                     kwflags = 0;
  3586.                     builtin = 1;
  3587.                 } else if (*s2 == '*') {
  3588.                     x = SX_MUL;
  3589.                     kwflags = 0;
  3590.                     builtin = 1;
  3591.                 } else if (*s2 == '/') {
  3592.                     x = SX_DIV;
  3593.                     kwflags = SXF_TWO;
  3594.                     builtin = 1;
  3595.                 }
  3596.             }
  3597.             if (!x) {                   /* None of the above, look it up */
  3598.                 x = xlookup(sexpops,p[1],nsexpops,&kw);
  3599.         debug(F111,"XXX",p[1],x);
  3600.                 if (x > 0) {
  3601.                     kwflags = sexpops[kw].flgs;
  3602.                     builtin = 1;
  3603.                 }
  3604.             }
  3605.         }
  3606.     }
  3607.     /* If none of the above, check built-in constants */
  3608.  
  3609.     if (x == -1) {
  3610.         x = xlookup(sexpconsts,p[1],nsexpconsts,&kw);
  3611.         if (x > 0) {
  3612.             switch (x) {
  3613.               case SXC_NIL:
  3614.                 s2 = "";
  3615.                 goto xdosexp;
  3616.               case SXC_PI:
  3617.                 s2 = math_pi;
  3618.                 goto xdosexp;
  3619.               case SXC_T:
  3620.                 s2 = "1";
  3621.                 goto xdosexp;
  3622.             }
  3623.         }
  3624.     }
  3625.     if (n == 1) {                       /* Not an expression */
  3626.         if (builtin) {                  /* Built-in operand? */
  3627.             switch (x) {                /* Operators with default values */
  3628.               case SX_EVA:
  3629.                 s2 = "";
  3630.                 goto xdosexp;
  3631.               case SX_MUL:              /* (*) */
  3632.                 s2 = sexpval ? sexpval : "1";
  3633.                 goto xdosexp;
  3634.               case SX_AND:              /* (AND) */
  3635.               case SX_BWA:              /* Bitwise (&) */
  3636.                 result++;
  3637.               case SX_LOR:              /* (OR) */
  3638.               case SX_BWO:              /* Bitwise (|) */
  3639.               case SX_ADD:              /* (+) */
  3640.               case SX_SUB:              /* (-) */
  3641.                 s2 = result ? "1" : "0";
  3642.                 goto xdosexp;
  3643.             }
  3644.  
  3645.         } else {                        /* Not a built-in operand */
  3646.             char * p1;
  3647.             p1 = p[1];
  3648.             while (*p1 == SP) p1++;
  3649.             if (!isalpha(*p1)) {
  3650.                 if (xxfloat(p1,0) > 0) { /* Is it a number? */
  3651.                     s2 = p1;
  3652.                     while (*s2 == '+') s2++;
  3653.                 } else if (*p1 == '(') { /* An S-Expression? */
  3654.  
  3655. #ifdef COMMENT
  3656.                     s2 = dosexp(s2);
  3657. #else
  3658.                     s2 = dosexp(p1);
  3659. #endif /* COMMENT */
  3660.                 }
  3661.                 goto xdosexp;
  3662.             } else if (x < 1) {         /* Is it a variable? */
  3663.                 j = mxlook(mactab,p[1],nmac); /* Look it up */
  3664.                 debug(F111,sexpdebug("n==1 mxlook"),p[1],j);
  3665.                 s2 = (j > -1) ? mactab[j].mval : "";
  3666.                 if (!s2) s2 = "";
  3667.                 if (xxfloat(s2,0) > 0)  /* Macro value is a number */
  3668.                   goto xdosexp;
  3669.  
  3670.                 if (j > -1) {           /* It's a macro */
  3671.                     mx = j;
  3672.                     x = j;              /* whose definition is not numeric */
  3673.                     if (*s2 == '(') {   /* Is it an S-Expression? */
  3674.                         /* We have to allocate memory on the stack */
  3675.                         /* to call ourselves recursively on it */
  3676.                         /* otherwise we'll wipe out the macro definition */
  3677.                         char * s3 = NULL;
  3678.                         /* int k = 0; */
  3679.                         s3 = s2;
  3680.                         while (*s3++) k++;
  3681.                         s3 = (char *)malloc(k + 4);
  3682.                         if (s3) {
  3683.                             strcpy(s3,s2);   /* SAFE */
  3684.                             s2 = dosexp(s3); /* Evaluate it */
  3685.                             free(s3);
  3686.                         } else {
  3687.                             printf("?Memory allocation failure - \"%s\"\n",s2);
  3688.                             sexprc++;
  3689.                         }
  3690.                         goto xdosexp;
  3691.                     }
  3692.                     if (*s2 == '\047') {
  3693.                         s2++;
  3694.                         makestr(&p[1],s2);
  3695.                         s2 = p[1];
  3696.                         if (*s2 == '(') {
  3697.                             if (s2[makestrlen-1] == ')') {
  3698.                                 s2[makestrlen-1] = NUL;
  3699.                                 s2++;
  3700.                             }
  3701.                         }
  3702.                         debug(F110,sexpdebug("'A"),s2,0);
  3703.                         goto xdosexp;
  3704.                     }
  3705.                     macro++;            /* Not an S-Expression */
  3706.                 } else {                /* Not found in macro table */
  3707.                     printf("?Not defined - \"%s\"\n", p[1]);
  3708.                     sexprc++;
  3709.                     goto xdosexp;
  3710.                 }
  3711.             }
  3712.         }
  3713.     } else if (x < 1 && !macro) {       /* n > 1 and not a built-in operator */
  3714.         x = mxlook(mactab,p[1],nmac);   /* See if it's a macro */
  3715.         debug(F111,sexpdebug("n!=1 mxlook"),p[1],x);
  3716.         if (x < 0) {
  3717.             printf("?Invalid operand - \"%s\"\n",p[1]);
  3718.             sexprc++;
  3719.             goto xdosexp;
  3720.         }
  3721.         mx = x;
  3722.         macro++;
  3723.     }
  3724.     if (builtin) {                      /* Built-in operator... */
  3725.         if (kwflags) {
  3726.             int flgs;
  3727.             if ((flgs = (kwflags & (SXF_ONE|SXF_TWO)))) {
  3728.                 switch (flgs) {
  3729.                   case (SXF_ONE|SXF_TWO):
  3730.                     if (n < 2) {
  3731.                         printf("?Too few operands - \"%s\"\n",s);
  3732.                         sexprc++;
  3733.                         goto xdosexp;
  3734.                     }
  3735.                     break;
  3736.                   case SXF_TWO:
  3737.                     if (n < 3) {
  3738.                         printf("?Too few operands - \"%s\"\n",s);
  3739.                         sexprc++;
  3740.                         goto xdosexp;
  3741.                     }
  3742.                     break;
  3743.                   case SXF_ONE:
  3744.                     if (n != 2) {
  3745.                         printf("?Too %s operands - \"%s\"\n",
  3746.                                (n > 2) ? "many" : "few", s);
  3747.                         sexprc++;
  3748.                         goto xdosexp;
  3749.                     }
  3750.                 }
  3751.             }
  3752.             if (kwflags & SXF_PRE) {    /* Predicate? */
  3753.                 pflag = 1;
  3754.                 presult = 1;
  3755.             }
  3756.             if (kwflags & SXF_FLO)      /* Operator requires floating point */
  3757.               fpflag++;                 /* Force it */
  3758.         }
  3759.         if (x == SX_SET || x == SX_LET || /* Assignment is special */
  3760.             x == SX_INC || x == SX_DEC) {
  3761.             int rc;
  3762.             char c, * m, * s3;
  3763.             if (n == 1) {
  3764.                 s2 = "";
  3765.                 goto xdosexp;
  3766.             }
  3767.             s2 = NULL;
  3768.             for (i = 1; i < n; i += 2) { /* Loop thru operand pairs */
  3769.                 rc = 0;
  3770.                 s3 = p[i+1];
  3771.                 c = *s3;
  3772.                 debug(F110,sexpdebug("target p"),s3,0);
  3773.  
  3774.                 /* Make sure target doesn't have multiple words */
  3775.                 while (*s3) { if (*s3 < '!') { rc = 1; break; }; s3++; }
  3776.                 s3 = p[i+1];
  3777.                 if (rc) {               /* If it does it must have been */
  3778.                     char * s4;          /* an SEXP so evaluate it */
  3779.                     s3 = dosexp(s3);
  3780.                     s4 = s3;
  3781.                     rc = 0;
  3782.                     while (*s4) { if (*s4 < '!') { rc = 1; break; }; s4++; }
  3783.                     if (rc == 0) makestr(&(p[i+1]),s3);
  3784.                 }
  3785.  
  3786.                 /* And that it's not a number, etc. */
  3787.                 if (rc > 0 || isdigit(c) || c == '(') {
  3788.                     printf("?Invalid assignment - \"%s\"\n",s);
  3789.                     sexprc++;
  3790.                     goto xdosexp;
  3791.                 } else if (isalpha(c)) {
  3792.                     rc = xlookup(sexpconsts,s3,nsexpconsts,NULL);
  3793.                     if (rc > 0) {
  3794.                         printf("?Assignment to constant - \"%s\"\n",s);
  3795.                         sexprc++;
  3796.                         goto xdosexp;
  3797.                     }
  3798.                 }
  3799.  
  3800.                 /* If ++ or --, get current value of variable */
  3801.                 if (x == SX_INC || x == SX_DEC) {
  3802.                     int ok = 1;
  3803.                     char buf[32];
  3804.                     if (c == CMDQ) {    /* A backslash variable */
  3805.                         int n = 32;
  3806.                         char * s = buf;
  3807.                         buf[0] = NUL;
  3808.                         if (zzstring(s3,&s,&n) < 0 || !buf[0])
  3809.                           ok = 0;
  3810.                         s2 = buf;
  3811.                     } else {            /* A macro */
  3812.                         if ((k = mxlook(mactab,s3,nmac)) < 0)
  3813.                           ok = 0;
  3814.                         else
  3815.                           s2 = mactab[k].mval;
  3816.                     }
  3817.                     if (!ok) {
  3818.                         printf("?Not defined - \"%s\"\n",p[i+1]);
  3819.                         sexprc++;
  3820.                         goto xdosexp;
  3821.                     }
  3822.                     if (!s2) s2 = "";
  3823.                     k = xxfloat(s2,0);
  3824.                     if (k < 1) {
  3825.                         printf("?Not numeric - \"%s\"\n",p[i+1]);
  3826.                         sexprc++;
  3827.                         goto xdosexp;
  3828.                     }
  3829.                     while (*s2 == '+') s2++;
  3830.                     result = atoi(s2);
  3831.                     fpresult = floatval;
  3832.                     if (k > 1 || fpresult != result)
  3833.                       fpflag++;
  3834.                 }
  3835.                 if (n < i+2) {          /* Variable with no value */
  3836.                     s2 = "";
  3837.                     if (x == SX_SET || x == SX_LET) {
  3838.                         delmac(p[i+1],1); /* Delete the variable */
  3839.                         break;
  3840.                     } else {
  3841.                         s2 = "1";
  3842.                     }
  3843.                 } else {                /* Variable with value */
  3844.                     k = xxfloat(p[i+2],0); /* Is it a number? */
  3845.                     if (k > 0) {
  3846.                         s2 = p[i+2];
  3847.                         while (*s2 == '+') s2++;
  3848.                     } else {
  3849.                         s2 = dosexp(p[i+2]); /* Have value, evaluate it */
  3850.                         if (sexprc) goto xdosexp;
  3851.                         if (!s2) s2 = "";
  3852.                         if (!*s2 && (x == SX_INC || x == SX_DEC))
  3853.                           continue;
  3854.                     }
  3855.                 }
  3856.                 if (x == SX_INC || x == SX_DEC) {
  3857.                     k = xxfloat(s2,0);
  3858.                     if (k < 1) {
  3859.                         printf("?Not numeric - \"%s\"\n",s2);
  3860.                         sexprc++;
  3861.                         goto xdosexp;
  3862.                     }
  3863.                     while (*s2 == '+') s2++;
  3864.                     j = atoi(s2);
  3865.                     if (k > 1) {
  3866.                         fpj = floatval;
  3867.                         fpflag++;
  3868.                     } else {
  3869.                         fpj = (CKFLOAT)j;
  3870.                     }
  3871.                     if (x == SX_INC) {
  3872.                         result += j;
  3873.                         fpresult += fpj;
  3874.                     } else if (x == SX_DEC) {
  3875.                         result -= j;
  3876.                         fpresult -= fpj;
  3877.                     }
  3878.                     if (result != fpresult) fpflag++;
  3879.                     s2 = fpflag ? fpformat(fpresult,0,0) : ckitoa(result);
  3880.                 }
  3881.                 if (x == SX_LET && cmdlvl > 0) /* LET makes var local */
  3882.                   addlocal(p[i+1]);
  3883.                 if ((rc = addmac(p[i+1],s2)) < 0) { /* Add the value */
  3884.                     switch (rc) {
  3885.                       case -3: m = "Array not declared"; break;
  3886.                       case -2: m = "Subscript out of range"; break;
  3887.                       case -4: m = "Out of memory"; break;
  3888.                       default: m = "Error creating variable";
  3889.                     }
  3890.                     printf("?%s - \"%s\"\n",m,s);
  3891.                     sexprc++;
  3892.                     goto xdosexp;
  3893.                 }
  3894.                 if (s2) result = atoi(s2);
  3895.             }
  3896.             goto xdosexp;
  3897.         } else if (x == SX_IFC) {               /* Conditional expression */
  3898.             int true = 0;
  3899.             if (n > 4) {
  3900.                 printf("?Too many operands: IF - \"%s\"\n",s);
  3901.                 sexprc++;
  3902.                 goto xdosexp;
  3903.             }
  3904.             s2 = dosexp(p[2]);
  3905.             if (sexprc) goto xdosexp;
  3906.             if (s2) {
  3907.                 j = atoi(s2);
  3908.                 if (xxfloat(s2,0) == 2) {
  3909.                     fpflag++;
  3910.                     fpresult = (CKFLOAT)result;
  3911.                     fpj = floatval;
  3912.                 } else {
  3913.                     fpj = atof(s2);
  3914.                 }
  3915.                 true = ((fpj != 0.0) ? 1 : 0);
  3916.             }
  3917.             if (!true && n < 4) {
  3918.                 s2 = NULL;
  3919.             } else {
  3920.                 s2 = dosexp(true ? p[3] : p[4]);
  3921.                 if (sexprc) goto xdosexp;
  3922.                 j = s2 ? atoi(s2) : 0;
  3923.                 if (xxfloat(s2,0) == 2) {
  3924.                     fpflag++;
  3925.                     fpresult = (CKFLOAT)result;
  3926.                     fpj = floatval;
  3927.                 } else {
  3928.                     fpj = s2 ? atof(s2) : 0.0;
  3929.                 }
  3930.                 fpresult = fpj;
  3931.                 result = j;
  3932.             }
  3933.             goto xdosexp;
  3934.         } else if (x == SX_QUO) {
  3935. #ifndef COMMENT
  3936.             int xx;
  3937.             xx = strlen(p[2]);
  3938.             p[3] = (char *)malloc(xx+4);
  3939.             s2 = p[3];
  3940.             ckmakmsg(p[3],xx+4,"'(",p[2],")",NULL);
  3941.             n++;
  3942. #else
  3943.             s2 = p[2];
  3944. #endif /* COMMENT */
  3945.             goto xdosexp;
  3946.         } else if (x == SX_STR) {
  3947.             int xx;
  3948.             s2 = dosexp(p[2]);
  3949.             if (sexprc) goto xdosexp;
  3950.             xx = strlen(s2);
  3951.             p[3] = (char *)malloc(xx+4);
  3952.             ckmakmsg(p[3],xx+4,"'(",s2,")",NULL);
  3953.             s2 = p[3];
  3954.             n++;
  3955.             goto xdosexp;
  3956.         }
  3957.     }
  3958.     /* Arithmetic operator or macro - Loop thru operands */
  3959.  
  3960.     quit = 0;                           /* Short-circuit flag. */
  3961.     if (macro && n > 1) {               /* If operator is a macro */
  3962.         if (!line) {                    /* allocate local buffer for */
  3963.             line = (char *)malloc(SXMLEN); /* the evaluated argument list. */
  3964.             if (!line) {
  3965.                 printf("?Memory allocation failure - \"%s\"\n",p[1]);
  3966.                 sexprc++;
  3967.                 goto xdosexp;
  3968.             }
  3969.             linelen = SXMLEN;
  3970.             /* debug(F101,"dosexp macro arg buffer","",linelen); */
  3971.         }
  3972.         linepos = 0;
  3973.         line[linepos] = NUL;
  3974.     }
  3975.     for (i = 1; ((i < n) && !sexprc && !quit); i++) { /* Loop thru operands */
  3976.         quote = 0;
  3977.         s2 = p[i+1];                    /* Get operand */
  3978.         if (!s2) s2 = "";
  3979. #ifdef COMMENT
  3980.         if (*s2 == '\047') {            /* Is it quoted? */
  3981.             debug(F110,sexpdebug("'B"),s2,0);
  3982.             s2++;                       /* Space past the quote */
  3983.             quote++;
  3984.             if (*s2 == '(') {           /* Quoted S-Expression? */
  3985.                 char c4, * s4 = s2+1;   /* Strip outer parens */
  3986.                 while ((c4 = *s4++)) {
  3987.                     if (c4 == ')' && !*s4) {
  3988.                         s2++;
  3989.                         *(s4-1) = NUL;
  3990.                         break;
  3991.                     }
  3992.                 }
  3993.             }
  3994.             debug(F110,sexpdebug("'C"),s2,0);
  3995.  
  3996.         } else {                        /* Not quoted */
  3997.             s2 = dosexp(p[i+1]);        /* evaluate it */
  3998.             if (sexprc) goto xdosexp;
  3999.             if (!s2) s2 = "";
  4000.             if (!macro && x == SX_EVA)
  4001.               continue;
  4002.         }
  4003. #else
  4004.         if (*s2 != '\047') {            /* Is it quoted? */
  4005.             s2 = dosexp(p[i+1]);        /* No, evaluate it */
  4006.             if (sexprc) goto xdosexp;
  4007.             if (!s2) s2 = "";
  4008.             if (!macro && x == SX_EVA)
  4009.               continue;
  4010.         }
  4011.         if (*s2 == '\047') {            /* Is result quoted? */
  4012.             debug(F110,sexpdebug("'B"),s2,0);
  4013.             s2++;                       /* Space past the quote */
  4014.             quote++;
  4015.             if (*s2 == '(') {           /* Quoted S-Expression? */
  4016.                 char c4, * s4 = s2+1;   /* Strip outer parens */
  4017.                 while ((c4 = *s4++)) {
  4018.                     if (c4 == ')' && !*s4) {
  4019.                         s2++;
  4020.                         *(s4-1) = NUL;
  4021.                         break;
  4022.                     }
  4023.                 }
  4024.             }
  4025.             debug(F110,sexpdebug("'C"),s2,0);
  4026.         }
  4027. #endif /* COMMENT */
  4028.         if (macro) {
  4029.             debug(F111,sexpdebug("macro arg"),s2,i);
  4030.             if (!*s2) quote++;
  4031.             if (!quote) {
  4032.                 register char c4, * s4 = s2;
  4033.                 while ((c4 = *s4++)) if (c4 == SP) { quote++; break; }
  4034.             }
  4035.             if (quote) line[linepos++] = '{';
  4036.             while ((line[linepos++] = *s2++)) {
  4037.                 if (linepos > linelen - 3) {
  4038.                     char * tmp = NULL;
  4039.                     line[linepos] = NUL;
  4040.                     linelen += SXMLEN;
  4041.                     tmp = (char *) malloc(linelen);
  4042.                     if (!tmp) {
  4043.                         printf("?Memory re-allocation failure - \"%s...\"\n",
  4044.                                line);
  4045.                         sexprc++;
  4046.                         goto xdosexp;
  4047.                     }
  4048.                     strcpy(tmp,line);
  4049.                     free(line);
  4050.                     line = tmp;
  4051.                 }
  4052.             }
  4053.             linepos--;                  /* Back up over NUL */
  4054.             if (quote)
  4055.               line[linepos++] = '}';    /* End quote group */
  4056.             line[linepos++] = SP;       /* add a space */
  4057.             line[linepos] = NUL;        /* and a NUL */
  4058.             continue;
  4059.         }
  4060.         if (!quote) {                   /* Built-in operator... */
  4061.             s2 = dosexp(s2);
  4062.             if (sexprc) goto xdosexp;
  4063.             if (!s2) s2 = "";
  4064.         }
  4065.         if (x == SX_EVA)
  4066.           continue;
  4067.  
  4068.         if (!*s2) {
  4069.             /* An empty value is not a legal number */
  4070.             /* but it is a legal truth value */
  4071.             if (x != SX_AND && x != SX_LOR && x != SX_NOT) {
  4072.                 printf("?Not Numeric - \"%s\"\n",p[i+1]);
  4073.                 sexprc++;
  4074.                 goto xdosexp;
  4075.             }
  4076.             j = 0;
  4077.             fpj = 0.0;
  4078.         } else {
  4079.             j = atoi(s2);
  4080.             /* Switch to floating-point upon encountering any f.p. arg */
  4081.             /* OR... if integer is too big */
  4082.             if (!fpflag) if (xxfloat(s2,0) == 2)
  4083.               fpflag++;
  4084.             fpj = atof(s2);
  4085.         }
  4086.         if (i == 1) {                   /* Initial result is first operand */
  4087.             result = (n == 2 && x == SX_SUB) ? 0-j : j;
  4088.             fpresult = (n == 2 && x == SX_SUB) ? -fpj : fpj;
  4089.             if (!(kwflags & SXF_ONE))   /* Command with single arg */
  4090.               continue;
  4091.         }
  4092.         if (x == SX_MOD || x == SX_DIV) {
  4093.             if (!result)
  4094.               fpflag++;
  4095.             if (!fpj) {
  4096.                 printf("?Divide by zero - \"%s\"\n",cmdbuf);
  4097.                 sexprc++;
  4098.                 goto xdosexp;
  4099.             }
  4100.         }
  4101.         switch (x) {                    /* Accumulate result */
  4102.  
  4103.           case SX_EVA:                  /* EVAL */
  4104.             result = j;
  4105.             fpresult = fpj;
  4106.             break;
  4107.  
  4108.           case SX_ADD:                  /* + */
  4109.             result += j;
  4110.             fpresult += fpj;
  4111.             if (result != fpresult)
  4112.               fpflag++;
  4113.             break;
  4114.  
  4115.           case SX_SUB:                  /* - */
  4116.             result -= j;
  4117.             fpresult -= fpj;
  4118.             if (result != fpresult)
  4119.               fpflag++;
  4120.             break;
  4121.  
  4122.           case SX_MUL:                  /* * */
  4123.             result *= j;
  4124.             fpresult *= fpj;
  4125.             if (result != fpresult)
  4126.               fpflag++;
  4127.             break;
  4128.  
  4129.           case SX_AND:                  /* AND */
  4130.             result = result && j;
  4131.             if (!result) quit++;
  4132.             fpresult = fpresult && fpj;
  4133.             break;
  4134.  
  4135.           case SX_LOR:                  /* OR */
  4136.             result = result || j;
  4137.             if (!result) quit++;
  4138.             fpresult = fpresult || fpj;
  4139.             break;
  4140.  
  4141.           case SX_MOD:                  /* Modulus */
  4142.             result = result % j;
  4143. #ifdef FNFLOAT
  4144.             fpresult = (CKFLOAT)fmod(fpresult,fpj);
  4145.             if (result != fpresult)
  4146.               fpflag++;
  4147. #else
  4148.             fpresult = result;
  4149. #endif /* FNFLOAT */
  4150.             break;
  4151.  
  4152.           case SX_DIV:                  /* / */
  4153.             result /= j;
  4154.             fpresult /= fpj;
  4155.             if (result != fpresult)
  4156.               fpflag++;
  4157.             break;
  4158.  
  4159.           case SX_AEQ:                  /* Test for equality */
  4160.             if (fpflag) {
  4161.                 if (fpresult != fpj)
  4162.                   presult = 0;
  4163.             } else {
  4164.                 if (result != j)
  4165.                   presult = 0;
  4166.             }
  4167.             break;
  4168.  
  4169.           case SX_NEQ:                  /* Test for ineqality */
  4170.             if (fpflag) {
  4171.                 if (fpresult == fpj)
  4172.                   presult = 0;
  4173.             } else {
  4174.                 if (result == j)
  4175.                   presult = 0;
  4176.             }
  4177.             break;
  4178.  
  4179.           case SX_ALE:                  /* Arithmetic less-equal */
  4180.             if (fpflag) {
  4181.                 if (fpj < fpresult)
  4182.                   presult = 0;
  4183.                 fpresult = fpj;
  4184.             } else {
  4185.                 if (j < result)
  4186.                   presult = 0;
  4187.                 result = j;
  4188.             }
  4189.             break;
  4190.  
  4191.           case SX_ALT:                  /* Arithmetic less-than */
  4192.             if (fpflag) {
  4193.                 if (fpj <= fpresult)
  4194.                   presult = 0;
  4195.                 fpresult = fpj;
  4196.             } else {
  4197.                 if (j <= result)
  4198.                   presult = 0;
  4199.                 result = j;
  4200.             }
  4201.             break;
  4202.  
  4203.           case SX_AGT:                  /* Arithmetic greater-than */
  4204.             if (fpflag) {
  4205.                 if (fpj >= fpresult)
  4206.                   presult = 0;
  4207.                 fpresult = fpj;
  4208.             } else {
  4209.                 if (j >= result)
  4210.                   presult = 0;
  4211.                 result = j;
  4212.             }
  4213.             break;
  4214.  
  4215.           case SX_AGE:                  /* Arithmetic greater-equal */
  4216.             if (fpflag) {
  4217.                 if (fpj > fpresult)
  4218.                   presult = 0;
  4219.                 fpresult = fpj;
  4220.             } else {
  4221.                 if (j > result)
  4222.                   presult = 0;
  4223.                 result = j;
  4224.             }
  4225.             break;
  4226.  
  4227.           case SX_POW:                  /* Raise to power */
  4228. #ifdef FNFLOAT
  4229.             {
  4230.                 double dummy;
  4231.                 if (!fpj) {
  4232.                     fpresult = 1.0;
  4233.                 } else if ((!fpresult && fpj <= 0.0)) {
  4234.                     printf("?Divide by zero - \"%s\"\n",cmdbuf);
  4235.                     sexprc++;
  4236.                     goto xdosexp;
  4237.                 } else if (fpresult < 0.0 && modf(fpj,&dummy)) {
  4238.                     printf("?Domain error - \"%s\"\n",cmdbuf);
  4239.                     sexprc++;
  4240.                     goto xdosexp;
  4241.                 } else {
  4242.                     fpresult = (CKFLOAT)pow(fpresult,fpj);
  4243.                 }
  4244.             }
  4245. #endif /* FNFLOAT */
  4246.             if (j == 0) {
  4247.                 result = 1;
  4248.             } else {
  4249.                 int z, sign = 0;
  4250.                 if (j < 0) {
  4251.                     if (result == 0) {
  4252.                         printf("?Divide by zero - \"%s\"\n",cmdbuf);
  4253.                         sexprc++;
  4254.                         goto xdosexp;
  4255.                     }
  4256.                     j = 0 - j;
  4257.                     sign++;
  4258.                 }
  4259.                 z = result;
  4260.                 while (--j > 0)
  4261.                   result *= z;
  4262.                 if (sign)
  4263.                   result = 1 / result;
  4264.             }
  4265.             if (result != fpresult)
  4266.               fpflag++;
  4267.             break;
  4268.  
  4269. #ifdef FNFLOAT
  4270.           case SX_EXP:                  /* e to the given power */
  4271.             fpresult = (CKFLOAT) exp(fpj);
  4272.             break;
  4273.  
  4274.           case SX_LGN:                  /* Natural log */
  4275.           case SX_LGX:                  /* Log base 10 */
  4276.           case SX_SQR:                  /* Square root */
  4277.             if (fpj < 0.0) {
  4278.                 printf("?Argument out of range - \"%s\"\n",cmdbuf);
  4279.                 sexprc++;
  4280.                 goto xdosexp;
  4281.             }
  4282.             if (x == SX_SQR)
  4283.               fpresult = (CKFLOAT) sqrt(fpj);
  4284.             else if (x == SX_LGN)
  4285.               fpresult = (CKFLOAT) log(fpj);
  4286.             else
  4287.               fpresult = (CKFLOAT) log10(fpj);
  4288.             break;
  4289.  
  4290.           case SX_SIN:                  /* sine */
  4291.             fpresult = (CKFLOAT) sin(fpj);
  4292.             break;
  4293.  
  4294.           case SX_COS:                  /* cosine */
  4295.             fpresult = (CKFLOAT) cos(fpj);
  4296.             break;
  4297.  
  4298.           case SX_TAN:                  /* tangent */
  4299.             fpresult = (CKFLOAT) tan(fpj);
  4300.             break;
  4301. #endif /* FNFLOAT */
  4302.  
  4303.           case SX_CEI:                  /* Ceiling */
  4304.             if (j != fpj)
  4305.               if (fpj > 0.0)
  4306.                 fpj += 1.0;
  4307.             fpresult = fpj;
  4308.             fpflag = 1;
  4309.             truncate = 1;
  4310.             break;
  4311.  
  4312.           case SX_FLR:                  /* Floor */
  4313.             if (j != fpj)
  4314.               if (fpj < 0.0)
  4315.                 fpj -= 1.0;
  4316.             fpresult = fpj;
  4317.             fpflag = 1;
  4318.             truncate = 1;
  4319.             break;
  4320.  
  4321.           case SX_TRU:                  /* Truncate */
  4322.             fpresult = fpj;
  4323.             fpflag = 1;
  4324.             truncate = 1;
  4325.             break;
  4326.  
  4327.           case SX_ROU:                  /* Round */
  4328.             if (fpj > 0.0)
  4329.               fpj += 0.5;
  4330.             else if (fpj < 0.0)
  4331.               fpj -= 0.5;
  4332.             fpresult = fpj;
  4333.             fpflag = 1;
  4334.             truncate = 1;
  4335.             break;
  4336.  
  4337.           case SX_ABS:                  /* Absolute value */
  4338.             result = (j < 0) ? 0 - j : j;
  4339.             fpresult = (fpj < 0.0) ? 0.0 - fpj : fpj;
  4340.             if (result != fpresult)
  4341.               fpflag++;
  4342.             break;
  4343.  
  4344.           case SX_MAX:                  /* Max */
  4345.             if (j != fpj)
  4346.               fpflag++;
  4347.             if (fpflag) {
  4348.                 if (fpj > fpresult)
  4349.                   fpresult = fpj;
  4350.             } else
  4351.               if (j > result)
  4352.                 result = j;
  4353.             break;
  4354.  
  4355.           case SX_MIN:                  /* Min */
  4356.             if (j != fpj)
  4357.               fpflag++;
  4358.             if (fpflag) {
  4359.                 if (fpj < fpresult)
  4360.                   fpresult = fpj;
  4361.             } else
  4362.               if (j < result)
  4363.                 result = j;
  4364.             break;
  4365.  
  4366.           case SX_FLO:                  /* Float */
  4367.             fpflag++;
  4368.             fpresult = result;
  4369.             fpj = j;
  4370.             break;
  4371.  
  4372.           case SX_NOT:                  /* NOT (reverse truth value) */
  4373.             fpflag = 0;
  4374.             not++;
  4375.             break;
  4376.  
  4377.           case SX_BWA:                  /* Bitwise AND */
  4378.             fpflag = 0;
  4379.             result &= j;
  4380.             break;
  4381.  
  4382.           case SX_BWO:                  /* Bitwise OR */
  4383.             fpflag = 0;
  4384.             result |= j;
  4385.             break;
  4386.  
  4387.           case SX_BWX:                  /* Bitwise XOR */
  4388.           case SX_XOR:                  /* Logical XOR */
  4389.             if (n > 3) {
  4390.                 printf("?Too many operands - \"%s\"\n",s);
  4391.                 sexprc++;
  4392.                 goto xdosexp;
  4393.             }
  4394.             fpflag = 0;
  4395.             if (x == SX_BWX) {
  4396.                 result ^= j;
  4397.             } else {
  4398.                 result = (result && !j) || (!result && j);
  4399.                 if (result) result = 1;
  4400.             }
  4401.             break;
  4402.  
  4403.           case SX_BWN:                  /* Bitwise Not */
  4404.             fpflag = 0;
  4405.             result = ~result;
  4406.             break;
  4407.  
  4408.           default:
  4409.             printf("BAD OP [%s]\n",p[1]);
  4410.             sexprc++;
  4411.         }
  4412.     }
  4413.     if (!pflag)                         /* Not a predicate */
  4414.       sexppv = -1;                      /* So unset this */
  4415.  
  4416.   /* domacro: */
  4417.  
  4418.     if (macro) {                        /* User-defined macro */
  4419.         extern int fsexpflag;           /* (see fneval():ckuus4.c) */
  4420.         int lookagain = 0;              /* Maybe the macro table changed */
  4421.         if (mactab[mx].kwd) {           /* Check and see */
  4422.             if (ckstrcmp(mactab[mx].kwd,p[1],-1,0))
  4423.               lookagain++;
  4424.         } else
  4425.           lookagain++;
  4426.         if (lookagain) {                /* The table changed */
  4427.             mx = mxlook(mactab,p[1],nmac); /* Get the macro's new index */
  4428.             debug(F111,sexpdebug("macro moved"),p[1],mx);
  4429.             if (mx < 0) {                  /* Yikes! */
  4430.                 printf("?Macro disappeared! - \"%s\"\n",p[1]);
  4431.                 sexprc++;
  4432.                 goto xdosexp;
  4433.             }
  4434.         }
  4435.         debug(F111,sexpdebug("macro mx"),mactab[mx].kwd,mx);
  4436.         if (fsexpflag) {                /* If embedded in a function call */
  4437.             if (cmpush() > -1) {        /* get a new copy of the parsing */
  4438.                 extern int ifc;         /* environment, */
  4439.                 int k, ifcsav = ifc;    /* save the IF state */
  4440.                 dodo(mx,line,0);        /* Set up the macro */
  4441.                 k = parser(1);          /* Call the parser to execute it */
  4442.                 cmpop();                /* Pop back to previous level */
  4443.                 ifc = ifcsav;           /* restore IF state */
  4444.                 if (k == 0)             /* If no error */
  4445.                   s2 = mrval[maclvl+1]; /* get return value, if any */
  4446.                 if (!s2) s2 = "";
  4447.                 debug(F110,sexpdebug("macro return"),s2,0);
  4448.             } else {
  4449.                 printf("?Resources exhausted - \"%s\"\n",s);
  4450.                 sexprc++;
  4451.             }
  4452.         } else {                        /* Not embedded in a function call */
  4453.             dodo(mx,line,0);            /* As above but without cmpush/pop() */
  4454.             k = parser(1);
  4455.             if (k == 0)
  4456.               s2 = mrval[maclvl+1];
  4457.             if (!s2) s2 = "";
  4458.         }
  4459.     } else if (pflag) {                 /* Predicate */
  4460.         if (not) presult = presult ? 0 : 1;
  4461.         sexppv = presult;               /* So set predicate value (0 or 1) */
  4462.         s2 = presult ? "1" : "0";
  4463.     } else if (fpflag) {                /* Result is floating-point */
  4464.         if (not) fpresult = fpresult ? 0.0 : 1.0;
  4465.         s2 = fpformat(fpresult,0,0);
  4466.     } else if (x != SX_EVA) {
  4467.         if (not) result = result ? 0 : 1;
  4468.         s2 = ckitoa(result);
  4469.     }
  4470.  
  4471. /* Common exit point.  Always come here to exit. */
  4472.  
  4473.   xdosexp:
  4474.  
  4475.     if (!s2) s2 = "";
  4476.     if (!sexprc && s2) {                /* Have a result */
  4477.         char * sx;
  4478.         char * q2 = s2; int xx = 0;
  4479.         if (*s2) {
  4480.             while (*q2++) xx++;         /* Get length */
  4481.             if (xx > sexprmax)          /* (stats) */
  4482.               sexprmax = xx;
  4483.         } else
  4484.           xx = 0;
  4485.         if (xx > sxrlen[sexpdep] || !sxresult[sexpdep]) {
  4486.             int k;
  4487.             k = xx + xx / 4;
  4488.             if (k < 32) k = 32;
  4489.             if (sxresult[sexpdep])
  4490.               free(sxresult[sexpdep]);
  4491.             if ((sxresult[sexpdep] = (char *)malloc(k))) {
  4492.                 sxrlen[sexpdep] = k;
  4493.             } else {
  4494.                 printf("?Memory allocation failure - \"%s\"\n",s2);
  4495.                 sexprc++;
  4496.             }
  4497.         }
  4498.         sx = sxresult[sexpdep];         /* Point to result buffer */
  4499.         while ((*sx++ = *s2++)) ;       /* copy result. */
  4500.         if (fpflag && truncate) {       /* Floating point + truncate */
  4501.             sx = sxresult[sexpdep];     /* at decimal point */
  4502.             for (i = xx - 1; i >= 0; i--) {
  4503.                 if (sx[i] == '.') {
  4504.                     sx[i] = NUL;
  4505.                     if (i == 0) {       /* If nothing left */
  4506.                         sx[0] = '0';    /* put a zero. */
  4507.                         sx[1] = NUL;
  4508.                     }
  4509.                 }
  4510.             }
  4511.         }
  4512.     }
  4513.     if (line)                           /* If macro arg buffer allocated */
  4514.       free(line);                       /* free it. */
  4515.     if (mustfree) {                     /* And free local copy of split list */
  4516.         for (i = 1; i <= n; i++) {
  4517.             if (p[i]) free(p[i]);
  4518.         }
  4519.     }
  4520.     debug(F111,sexpdebug("exit"),sxresult[sexpdep],sexprc);
  4521.     return(sxresult[sexpdep--]);
  4522. }
  4523. #endif /* NOSEXP */
  4524. #endif /* NOSPL */
  4525.  
  4526. int                                     /* CHECK command */
  4527. dochk() {
  4528.     int x, y;
  4529.     if ((y = cmkey(ftrtab,nftr,"","",xxstring)) < 0)
  4530.       return(y);
  4531.     ckstrncpy(line,atmbuf,LINBUFSIZ);
  4532.     if ((y = cmcfm()) < 0)
  4533.       return(y);
  4534. #ifndef NOPUSH
  4535.     if (!ckstrcmp(line,"push",(int)strlen(line),0)) {
  4536.         if (msgflg)                     /* If at top level... */
  4537.           printf(" push%s available\n", nopush ? " not" : "");
  4538.         else if (nopush && !backgrd)
  4539.           printf(" CHECK: push not available\n");
  4540.         return(success = 1 - nopush);
  4541.     }
  4542. #endif /* NOPUSH */
  4543. #ifdef PIPESEND
  4544.     if (!ckstrcmp(line,"pipes",(int)strlen(line),0)) {
  4545.         if (msgflg)                     /* If at top level... */
  4546.           printf(" pipes%s available\n",
  4547.                  (nopush || protocol != PROTO_K) ? " not" : "");
  4548.         else if ((nopush || protocol != PROTO_K) && !backgrd)
  4549.           printf(" CHECK: pipes not available\n");
  4550.         return(success = 1 - nopush);
  4551.     }
  4552. #endif /* PIPESEND */
  4553.     y = lookup(ftrtab,line,nftr,&x);    /* Look it up */
  4554.     debug(F111,"dochk",ftrtab[x].kwd,y);
  4555.     if (msgflg)                         /* If at top level... */
  4556.       printf(" %s%s available\n", ftrtab[x].kwd, y ? " not" : "");
  4557.     else if (y && !backgrd)
  4558.       printf(" CHECK: %s not available\n", ftrtab[x].kwd);
  4559.     return(success = 1 - y);
  4560. }
  4561.  
  4562. #ifndef NOLOCAL
  4563. #ifdef CKLOGDIAL
  4564.  
  4565. /* Connection log and elapsed-time reporting */
  4566.  
  4567. extern char cxlogbuf[];                 /* Log record buffer */
  4568. extern char diafil[];                   /* Log file name */
  4569. extern int dialog, cx_active;           /* Flags */
  4570. static long cx_prev = 0L;               /* Elapsed time of previous session */
  4571.  
  4572. #endif /* CKLOGDIAL */
  4573. #endif /* NOLOCAL */
  4574.  
  4575. VOID
  4576. dologend() {                            /* Write record to connection log */
  4577. #ifdef LOCUS
  4578.     extern int locus, autolocus;
  4579. #endif /* LOCUS */
  4580.  
  4581. #ifndef NOLOCAL
  4582. #ifdef CKLOGDIAL
  4583.     long d1, d2, t1, t2;
  4584.     char buf[32], * p;
  4585. #endif /* CKLOGDIAL */
  4586. #endif /* NOLOCAL */
  4587.  
  4588. #ifdef LOCUS
  4589.     if (autolocus) {
  4590.         int x = locus;
  4591. #ifdef NEWFTP
  4592.         extern int ftpisconnected();
  4593.     debug(F101,"dologend ftpisconnected","",ftpisconnected());
  4594.         setlocus(ftpisconnected() ? 0 : 1, 1);
  4595. #else
  4596.         setlocus(1,1);
  4597. #endif /* NEWFTP */
  4598.     }
  4599. #endif /* LOCUS */
  4600.  
  4601. #ifndef NOLOCAL
  4602. #ifdef CKLOGDIAL
  4603.     debug(F101,"dologend dialog","",dialog);
  4604.     debug(F101,"dologend cxlogbuf[0]","",cxlogbuf[0]);
  4605. #ifdef CKSYSLOG
  4606.     debug(F101,"dologend ckxlogging","",ckxlogging);
  4607. #endif /* CKSYSLOG */
  4608.  
  4609.     if (!cx_active || !cxlogbuf[0])     /* No active record */
  4610.       return;
  4611.  
  4612.     cx_active = 0;                      /* Record is not active */
  4613.     debug(F111,"dologend cxlogbuf 1",cxlogbuf,cx_active);
  4614.  
  4615.     d1 = mjd((char *)cxlogbuf);         /* Get start date of this session */
  4616.     ckstrncpy(buf,ckdate(),31);         /* Get current date */
  4617.     d2 = mjd(buf);                      /* Convert them to mjds */
  4618.     p = cxlogbuf;                       /* Get start time */
  4619.     p[11] = NUL;
  4620.     p[14] = NUL;                        /* Convert to seconds */
  4621.     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
  4622.     p[11] = ':';
  4623.     p[14] = ':';
  4624.     p = buf;                            /* Get end time */
  4625.     p[11] = NUL;
  4626.     p[14] = NUL;
  4627.     t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
  4628.     t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Compute elapsed time */
  4629.     debug(F101,"dologend t2","",t2);
  4630.     if (t2 > -1L) {
  4631.         cx_prev = t2;
  4632.         p = hhmmss(t2);
  4633.         debug(F110,"dologend hhmmss",p,0);
  4634.         strncat(cxlogbuf,"E=",CXLOGBUFL); /* Append to log record */
  4635.         strncat(cxlogbuf,p,CXLOGBUFL);
  4636.         debug(F110,"dologend cxlogbuf 2",cxlogbuf,0);
  4637.     } else
  4638.       cx_prev = 0L;
  4639.     debug(F101,"dologend cx_prev","",cx_prev);
  4640.     if (dialog) {                       /* If logging */
  4641.         int x;
  4642.         x = diaopn(diafil,1,1);         /* Open log in append mode */
  4643.         debug(F101,"dologend diaopn","",x);
  4644.         x = zsoutl(ZDIFIL,cxlogbuf);    /* Write the record */
  4645.         debug(F101,"dologend zsoutl","",x);
  4646.         x = zclose(ZDIFIL);             /* Close the log */
  4647.         debug(F101,"dologend zclose","",x);
  4648.     }
  4649. #ifdef CKSYSLOG
  4650.     debug(F101,"dologend ckxlogging","",ckxlogging);
  4651.     if (ckxlogging) {
  4652.         int x;
  4653.         x = ckindex("T=DIAL",cxlogbuf,0,0,1);
  4654.         debug(F111,"dologend ckxsyslog",cxlogbuf,ckxsyslog);
  4655.         debug(F111,"dologend ckindex","T=DIAL",x);
  4656.         if (x > 0) {
  4657.             if (ckxsyslog >= SYSLG_DI) {
  4658.                 debug(F110,"dologend syslog",cxlogbuf+18,0);
  4659.                 cksyslog(SYSLG_DI,1,"CONNECTION",(char *)(cxlogbuf+18),"");
  4660.             } else if (ckxsyslog >= SYSLG_AC) {
  4661.                 debug(F110,"dologend syslog",cxlogbuf+18,0);
  4662.                 cksyslog(SYSLG_AC,1,"CONNECTION",(char *)(cxlogbuf+18),"");
  4663.             }
  4664.         }
  4665.     }
  4666. #endif /* CKSYSLOG */
  4667. #endif /* CKLOGDIAL */
  4668. #endif /* NOLOCAL */
  4669. }
  4670.  
  4671. #ifndef NOLOCAL
  4672. #ifdef CKLOGDIAL
  4673.  
  4674. /*  D O L O G S H O W  --  Show session/connection info  */
  4675.  
  4676. /* Call with fc == 1 to show, fc == 0 to only calculate. */
  4677. /* Returns session elapsed time in seconds. */
  4678. /* If no session active, returns elapsed time of previous session, if any, */
  4679. /* otherwise 0 */
  4680.  
  4681. long
  4682. dologshow(fc) int fc; {                 /* SHOW (current) CONNECTION */
  4683.     long d1, d2, t1, t2 = 0, prev;
  4684.     char c, buf1[32], buf2[32], * info[32], * p, * s;
  4685.     char * xlogbuf, xbuf[CXLOGBUFL+1];
  4686.     int i, x = 0, z, ftp = 0, active = 0;
  4687.  
  4688. #ifdef NEWFTP
  4689.     extern char ftplogbuf[];
  4690.     extern long ftplogprev;
  4691.     extern int ftplogactive;
  4692.     if (fc & W_FTP) {
  4693.         fc &= 63;
  4694.         ftp = 1;
  4695.         xlogbuf = ftplogbuf;
  4696.         prev = ftplogprev;
  4697.         active = ftplogactive;
  4698.     } else {
  4699. #endif /* NEWFTP */
  4700.         ftp = 0;
  4701.         xlogbuf = cxlogbuf;
  4702.         prev = cx_prev;
  4703.         active = cx_active;
  4704. #ifdef NEWFTP
  4705.     }
  4706. #endif /* NEWFTP */
  4707.  
  4708.     debug(F101,"dologshow local","",local);
  4709.     debug(F101,"dologshow ftp","",ftp);
  4710.     debug(F111,"dologshow active",xlogbuf,active);
  4711.  
  4712.     if (!xlogbuf[0]) {
  4713.         if (fc) {
  4714.             if (didsetlin || ftp)
  4715.               printf(" %s: No record.\n", ftp ? "FTP" : "Kermit");
  4716.             else
  4717.               printf(" %s: No connection.\n", ftp ? "FTP" : "Kermit");
  4718.         }
  4719.         return(prev);
  4720.     }
  4721.  
  4722. #ifdef NEWFTP
  4723.     if (ftp) {
  4724.         z = ftpisconnected() ? 1 : -1;
  4725.     } else {
  4726. #endif /* NEWFTP */
  4727.         if (local) {                    /* See if we have an open connection */
  4728.             z = ttchk();
  4729.             debug(F101,"dologshow ttchk","",z);
  4730.             z = (z > -1) ? 1 : -2;
  4731.         } else {
  4732.             z = active ? 1 : -2;
  4733.         }
  4734. #ifdef NEWFTP
  4735.     }
  4736. #endif /* NEWFTP */
  4737.     if (z < 0L) {
  4738.         if (!fc)
  4739.           return(prev);
  4740.         else
  4741.           t2 = prev;
  4742.     }
  4743.     /* Note: NOT ckstrncpy! */
  4744.     strncpy(buf1,xlogbuf,17);           /* Copy of just the timestamp */
  4745.     buf1[17] = NUL;                     /* Terminate it */
  4746.     ckstrncpy(xbuf,xlogbuf+18,CXLOGBUFL); /* Copy that can be poked */
  4747.     debug(F111,"dologshow prev",xbuf,prev);
  4748.  
  4749.     xwords(xbuf,31,info,1);             /* Break up into fields */
  4750.     d1 = mjd(buf1);                     /* Convert start time to MJD */
  4751.     ckstrncpy(buf2,ckdate(),31);        /* Current date */
  4752.     d2 = mjd(buf2);                     /* Convert to MJD */
  4753.     p = buf1;                           /* Point to start time */
  4754.     p[11] = NUL;
  4755.     p[14] = NUL;                        /* Convert to seconds */
  4756.     t1 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
  4757.     p[11] = ':';
  4758.     p[14] = ':';
  4759.     p = buf2;                           /* Ditto for current time */
  4760.     p[11] = NUL;
  4761.     p[14] = NUL;
  4762.     if (z > -1L) {
  4763.         t2 = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
  4764.         t2 = ((d2 - d1) * 86400L) + (t2 - t1); /* Elapsed time so far */
  4765.     }
  4766.     if (fc) {
  4767.         p = NULL;
  4768.         if (t2 > -1L)                   /* Convert seconds to hh:mm:ss */
  4769.           p = hhmmss(t2);
  4770.         if (z > -1)
  4771.           s = "Active";
  4772.         else if (z == -2)
  4773.           s = "Closed";
  4774.         else
  4775.           s = "Unknown";
  4776.         printf("\n");                   /* Show results */
  4777.         printf(" Status:       %s\n",s);
  4778.         printf(" Opened:       %s\n",buf1);
  4779.         printf(" User:         %s\n",info[1] ? info[1] : "");
  4780.         printf(" PID:          %s\n",info[2] ? info[2] : "");
  4781.         for (i = 3; info[i]; i++) {
  4782.             c = info[i][0];
  4783.             s = (info[i]) ? info[i]+2 : "";
  4784.             switch (c) {
  4785.               case 'T': printf(" Type:         %s\n", s); break;
  4786.               case 'N': printf(" To:           %s\n", s); break;
  4787.               case 'H': printf(" From:         %s\n", s); break;
  4788.               case 'D': printf(" Device:       %s\n", s); break;
  4789.               case 'O': printf(" Origin:       %s\n", s); break;
  4790.               case 'E': break;
  4791.               default:  printf(" %s\n",info[i] ? info[i] : "");
  4792.             }
  4793.         }
  4794.         if (z < 0L)
  4795.           printf(" Elapsed time: %s\n", hhmmss(t2));
  4796.         else
  4797.           printf(" Elapsed time: %s\n", p ? p : "(unknown)");
  4798.         x = 0;
  4799. #ifdef NETCONN
  4800. #ifdef SSHBUILTIN
  4801.         if ( IS_SSH() ) x++;
  4802. #endif /* SSHBUILTIN */
  4803. #ifdef CK_ENCRYPTION
  4804.         if (ck_tn_encrypting() && ck_tn_decrypting()) x++;
  4805. #endif /* CK_ENCRYPTION */
  4806. #ifdef CK_SSL
  4807.         if (tls_active_flag || ssl_active_flag) x++;
  4808. #endif /* CK_SSL */
  4809. #ifdef RLOGCODE
  4810. #ifdef CK_KERBEROS
  4811. #ifdef CK_ENCRYPTION
  4812.         if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) x++;
  4813. #endif /* CK_ENCRYPTION */
  4814. #endif /* CK_KERBEROS */
  4815. #endif /* RLOGCODE */
  4816. #endif /* NETCONN */
  4817.         if (z > 0)
  4818.           printf(" Encrypted:    %s\n", x ? "Yes" : "No");
  4819.         printf(" Log:          %s\n", dialog ? diafil : "(none)");
  4820.         printf("\n");
  4821.     }
  4822.     return(t2 > -1L ? t2 : 0L);
  4823. }
  4824.  
  4825. VOID
  4826. dologline() {
  4827.     char * p;
  4828.     int n, m = 0;
  4829.  
  4830.     dologend();                         /* Previous session not closed out? */
  4831.     cx_active = 1;                      /* Record is active */
  4832.     cx_prev = 0L;
  4833.     p = ckdate();                       /* Get timestamp */
  4834.     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL-1); /* Start record off with it */
  4835.     if (!uidbuf[0]) {
  4836.         debug(F100,"dologline uidbuf empty","",0);
  4837. #ifdef UNIX                             /* Who has whoami()... */
  4838.         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
  4839. #else
  4840. #ifdef STRATUS
  4841.         ckstrncpy(uidbuf,(char *)whoami(),UIDBUFLEN);
  4842. #else
  4843.         ckstrncpy(uidbuf,"UNKNOWN",UIDBUFLEN);
  4844. #endif /* STRATUS */
  4845. #endif /* UNIX */
  4846.     }
  4847.     m = strlen(uidbuf) + strlen(myhost) + strlen(ttname) + 32;
  4848.     if (n+m < CXLOGBUFL-1) {            /* Add serial device info */
  4849.         p = cxlogbuf+n;
  4850.         sprintf(p," %s %s T=SERIAL H=%s D=%s ", /* SAFE */
  4851.                 uidbuf,
  4852.                 ckgetpid(),
  4853.                 myhost,
  4854.                 ttname
  4855.                 );
  4856.     } else
  4857.       ckstrncpy(cxlogbuf,"LOGLINE BUFFER OVERFLOW",CXLOGBUFL);
  4858.     debug(F110,"dologline",cxlogbuf,0);
  4859. }
  4860.  
  4861. #ifdef NETCONN
  4862. VOID
  4863. dolognet() {
  4864.     char * p, * s = "NET", * uu = uidbuf;
  4865.     int n, m;
  4866.  
  4867.     dologend();                         /* Previous session not closed out? */
  4868.     cx_prev = 0L;
  4869.     cx_active = 1;                      /* Record is active */
  4870.     p = ckdate();
  4871.     n = ckstrncpy(cxlogbuf,p,CXLOGBUFL);
  4872. #ifdef TCPSOCKET
  4873.     if (nettype == NET_TCPB || nettype == NET_TCPA)
  4874.       s = "TCP";
  4875. #endif /* TCPSOCKET */
  4876. #ifdef ANYX25
  4877.     if (nettype == NET_SX25 || nettype == NET_VX25 || nettype == NET_IX25)
  4878.       s = "X25";
  4879. #endif /* ANYX25 */
  4880. #ifdef DECNET
  4881.     if (nettype == NET_DEC)
  4882.       s = "DECNET";
  4883. #endif /* DECNET */
  4884. #ifdef SUPERLAT
  4885.     if (nettype == NET_SLAT)
  4886.       s = "SUPERLAT";
  4887. #endif /* SUPERLAT */
  4888. #ifdef CK_NETBIOS
  4889.     if (nettype == NET_BIOS)
  4890.       s = "NETBIOS";
  4891. #endif /* CK_NETBIOS */
  4892.  
  4893.     if (!uu[0]) {
  4894.         debug(F100,"dolognet uidbuf empty","",0);
  4895. #ifdef OS2ORUNIX                        /* Who has whoami()... */
  4896.         uu = (char *)whoami();
  4897. #else
  4898. #ifdef STRATUS
  4899.         uu = (char *)whoami();
  4900. #else
  4901.         uu = "UNKNOWN";
  4902. #endif /* STRATUS */
  4903. #endif /* UNIX */
  4904.     }
  4905.     m = strlen(uu) + strlen(myhost) + strlen(ttname) + strlen(s) + 32;
  4906.     if (n+m < CXLOGBUFL-1) {            /* SAFE */
  4907.         p = cxlogbuf+n;
  4908.         sprintf(p," %s %s T=%s N=%s H=%s ",
  4909.                 uu,
  4910.                 ckgetpid(),
  4911.                 s,
  4912.                 ttname,
  4913.                 myhost
  4914.                 );
  4915.     } else
  4916.       ckstrncpy(cxlogbuf,"LOGNET BUFFER OVERFLOW",CXLOGBUFL);
  4917.     debug(F110,"dolognet cxlogbuf",cxlogbuf,0);
  4918. }
  4919. #endif /* NETCONN */
  4920. #endif /* CKLOGDIAL */
  4921.  
  4922. #ifndef NODIAL
  4923. /*
  4924.   Parse a DIAL-related string, stripping enclosing braces, if any.
  4925. */
  4926. static int
  4927. dialstr(p,msg) char **p; char *msg; {
  4928.     int x;
  4929.     char *s;
  4930.  
  4931.     if ((x = cmtxt(msg, "", &s, xxstring)) < 0)
  4932.       return(x);
  4933.     s = brstrip(s);                     /* Strip braces around. */
  4934.     debug(F110,"dialstr",s,0);
  4935.     makestr(p,*s?s:NULL);
  4936.     return(success = 1);
  4937. }
  4938.  
  4939. VOID
  4940. initmdm(x) int x; {
  4941.     MDMINF * p;
  4942.     int m;
  4943.  
  4944.     mdmtyp = x;                         /* Set global modem type */
  4945.     debug(F101,"initmdm mdmtyp","",mdmtyp);
  4946.     debug(F101,"initmdm usermdm","",usermdm);
  4947.     if (x < 1) return;
  4948.  
  4949.     m = usermdm ? usermdm : mdmtyp;
  4950.  
  4951.     p = modemp[m];                      /* Point to modem info struct, and */
  4952.     debug(F101,"initmdm p","",p);
  4953.     if (p) {
  4954.         dialec = p->capas & CKD_EC;     /* set DIAL ERROR-CORRECTION, */
  4955.         dialdc = p->capas & CKD_DC;     /* DIAL DATA-COMPRESSION, and */
  4956.         mdmspd = p->capas & CKD_SB ? 0 : 1; /* DIAL SPEED-MATCHING from it. */
  4957.         dialfc = FLO_AUTO;                  /* Modem's local flow control.. */
  4958.         dialmax   = p->max_speed;
  4959.         dialcapas = p->capas;
  4960.         dialesc   = p->esc_char;
  4961.     } else if (mdmtyp > 0) {
  4962.         printf("WARNING: modem info for \"%s\" not filled in yet\n",
  4963.                gmdmtyp()
  4964.                );
  4965.     }
  4966.  
  4967. /* Reset or set the SET DIAL STRING items ... */
  4968.  
  4969. #ifdef DEBUG
  4970.     if (deblog) {
  4971.         debug(F110,"initmdm dialini",dialini,0);
  4972.         debug(F110,"initmdm dialmstr ",dialmstr,0);
  4973.         debug(F110,"initmdm dialmprmt",dialmprmt,0);
  4974.         debug(F110,"initmdm dialcmd",dialcmd,0);
  4975.         debug(F110,"initmdm dialdcon",dialdcon,0);
  4976.         debug(F110,"initmdm dialdcoff",dialdcoff,0);
  4977.         debug(F110,"initmdm dialecon",dialecon,0);
  4978.         debug(F110,"initmdm dialecoff",dialecoff,0);
  4979.         debug(F110,"initmdm dialhcmd",dialhcmd,0);
  4980.         debug(F110,"initmdm dialhwfc",dialhwfc,0);
  4981.         debug(F110,"initmdm dialswfc",dialswfc,0);
  4982.         debug(F110,"initmdm dialnofc",dialnofc,0);
  4983.         debug(F110,"initmdm dialtone",dialtone,0);
  4984.         debug(F110,"initmdm dialpulse",dialpulse,0);
  4985.         debug(F110,"initmdm dialname",dialname,0);
  4986.         debug(F110,"initmdm dialaaon",dialaaon,0);
  4987.         debug(F110,"initmdm dialaaoff",dialaaoff,0);
  4988.         debug(F110,"initmdm dialx3",dialx3,0);
  4989.         debug(F110,"initmdm dialspon",dialspon,0);
  4990.         debug(F110,"initmdm dialspoff",dialspoff,0);
  4991.         debug(F110,"initmdm dialvol1",dialvol1,0);
  4992.         debug(F110,"initmdm dialvol2",dialvol2,0);
  4993.         debug(F110,"initmdm dialvol3",dialvol3,0);
  4994.         debug(F110,"initmdm dialini2",dialini2,0);
  4995.     }
  4996. #endif /* DEBUG */
  4997.  
  4998.     if (usermdm && p) { /* USER-DEFINED: copy info from specified template */
  4999.  
  5000.         makestr(&dialini  ,p->wake_str);
  5001.         makestr(&dialmstr ,p->dmode_str);
  5002.         makestr(&dialmprmt,p->dmode_prompt);
  5003.         makestr(&dialcmd  ,p->dial_str);
  5004.         makestr(&dialdcon ,p->dc_on_str);
  5005.         makestr(&dialdcoff,p->dc_off_str);
  5006.         makestr(&dialecon ,p->ec_on_str);
  5007.         makestr(&dialecoff,p->ec_off_str);
  5008.         makestr(&dialhcmd ,p->hup_str);
  5009.         makestr(&dialhwfc ,p->hwfc_str);
  5010.         makestr(&dialswfc ,p->swfc_str);
  5011.         makestr(&dialnofc ,p->nofc_str);
  5012.         makestr(&dialtone ,p->tone);
  5013.         makestr(&dialpulse,p->pulse);
  5014.         makestr(&dialname ,"This space available (use SET MODEM NAME)");
  5015.         makestr(&dialaaon ,p->aa_on_str);
  5016.         makestr(&dialaaoff,p->aa_off_str);
  5017.         makestr(&dialx3   ,p->ignoredt);
  5018.         makestr(&dialspon ,p->sp_on_str);
  5019.         makestr(&dialspoff,p->sp_off_str);
  5020.         makestr(&dialvol1 ,p->vol1_str);
  5021.         makestr(&dialvol2 ,p->vol2_str);
  5022.         makestr(&dialvol3 ,p->vol3_str);
  5023.         makestr(&dialini2 ,p->ini2);
  5024.  
  5025.     } else {                    /* Not user-defined, so wipe out overrides */
  5026.  
  5027.         if (dialini)   makestr(&dialini,NULL);   /* Init-string */
  5028.         if (dialmstr)  makestr(&dialmstr,NULL);  /* Dial-mode-str */
  5029.         if (dialmprmt) makestr(&dialmprmt,NULL); /* Dial-mode-pro */
  5030.         if (dialcmd)   makestr(&dialcmd,NULL);   /* Dial-command  */
  5031.         if (dialdcon)  makestr(&dialdcon,NULL);  /* DC ON command */
  5032.         if (dialdcoff) makestr(&dialdcoff,NULL); /* DC OFF command */
  5033.         if (dialecon)  makestr(&dialecon,NULL);  /* EC ON command */
  5034.         if (dialecoff) makestr(&dialecoff,NULL); /* EC OFF command */
  5035.         if (dialhcmd)  makestr(&dialhcmd,NULL);  /* Hangup command */
  5036.         if (dialhwfc)  makestr(&dialhwfc,NULL);  /* Flow control... */
  5037.         if (dialswfc)  makestr(&dialswfc,NULL);  /*  */
  5038.         if (dialnofc)  makestr(&dialnofc,NULL);  /*  */
  5039.         if (dialtone)  makestr(&dialtone,NULL);  /* Dialing method */
  5040.         if (dialpulse) makestr(&dialpulse,NULL); /*  */
  5041.         if (dialname)  makestr(&dialname,NULL);  /* Modem name */
  5042.         if (dialaaon)  makestr(&dialaaon,NULL);  /* Autoanswer On */
  5043.         if (dialaaoff) makestr(&dialaaoff,NULL); /* Autoanswer Off */
  5044.         if (dialx3)    makestr(&dialx3,NULL);    /* Ignore dialtone */
  5045.         if (dialspon)  makestr(&dialspon,NULL);  /* Speaker On */
  5046.         if (dialspoff) makestr(&dialspoff,NULL); /* Speaker Off */
  5047.         if (dialvol1)  makestr(&dialvol1,NULL);  /* Low volume */
  5048.         if (dialvol2)  makestr(&dialvol2,NULL);  /* Medium volume */
  5049.         if (dialvol3)  makestr(&dialvol3,NULL);  /* High volume */
  5050.         if (dialini2)  makestr(&dialini2,NULL);  /* Init string 2 */
  5051.     }
  5052.     if (autoflow)                       /* Maybe change flow control */
  5053.       setflow();
  5054.  
  5055. #ifndef MINIDIAL
  5056. #ifdef OLDTBCODE
  5057.     tbmodel = 0;           /* If it's a Telebit, we don't know the model yet */
  5058. #endif /* OLDTBCODE */
  5059. #endif /* MINIDIAL */
  5060. }
  5061.  
  5062. #ifdef COMMENT
  5063. /* Not implemented yet */
  5064. int
  5065. setanswer() {
  5066.     int x, y;
  5067.     extern int ans_cid, ans_ring;
  5068.     if ((x = cmkey(answertab,nanswertab,"","",xxstring)) < 0)
  5069.       return(x);
  5070.     switch (x) {
  5071.       case XYA_CID:
  5072.         return(seton(&ans_cid));
  5073.       case XYA_RNG:
  5074.         y = cmnum("How many rings before answering","1",10,&x,xxstring);
  5075.         y = setnum(&ans_rings,x,y,254);
  5076.         return(y);
  5077.     }
  5078. }
  5079. #endif /* COMMENT */
  5080.  
  5081. int
  5082. setmodem() {                            /* SET MODEM */
  5083.  
  5084.     int x, y, z;
  5085.     long zz;
  5086.     struct FDB k1, k2;
  5087.     extern int mdmset;
  5088.  
  5089.     cmfdbi(&k1,_CMKEY,
  5090.            "Modem parameter","","",nsetmdm, 0, xxstring, setmdm, &k2);
  5091.     cmfdbi(&k2,_CMKEY,"","","",nmdm,0,xxstring,mdmtab,NULL);
  5092.     x = cmfdb(&k1);
  5093.     if (x < 0) {                        /* Error */
  5094.         if (x == -2 || x == -9)
  5095.           printf("?No keywords match: \"%s\"\n",atmbuf);
  5096.         return(x);
  5097.     }
  5098.     y = cmresult.nresult;               /* Keyword value */
  5099.     if (cmresult.fdbaddr == &k2) {      /* Modem-type keyword table */
  5100.         if ((x = cmcfm()) < 0)
  5101.           return(x);
  5102.         usermdm = 0;
  5103.         initmdm(cmresult.nresult);      /* Set the modem type. */
  5104.         return(success = 1);            /* Done */
  5105.     }
  5106.     switch (cmresult.nresult) {         /* SET MODEM keyword table. */
  5107. #ifdef MDMHUP
  5108.       case XYDMHU:                      /* DIAL MODEM-HANGUP */
  5109.         if ((y = cmkey(mdmhang,4,"how to hang up modem",
  5110.                        "modem-command", xxstring)) < 0)
  5111.           return(y);
  5112.         if ((x = cmcfm()) < 0)
  5113.           return(x);
  5114.         dialmhu = y;
  5115. #ifdef COMMENT
  5116. /* Nope, I fixed it (2001 11 08) */
  5117. #ifdef CK_SCOV5
  5118.         if (dialmhu == 0 && !quiet) {
  5119.             printf(
  5120. "\n WARNING: RS-232 signal sampling and manipulation do not work\n"
  5121.                     );
  5122.             printf(
  5123. " in the standard SCO OSR5 serial i/o drivers.  SET MODEM HANGUP-METHOD\n"
  5124.                    );
  5125.             printf(
  5126. " MODEM-COMMAND is recommended for OSR5.\n\n"
  5127.                     );
  5128.         }
  5129. #endif /* CK_SCOV5 */
  5130. #endif /* COMMENT */
  5131.         return(success = 1);
  5132. #endif /* MDMHUP */
  5133.  
  5134.       case XYDCAP:
  5135.         zz = 0L;
  5136.         y = 0;
  5137.         while (y != -3) {
  5138.             if ((y = cmkey(mdmcap,nmdmcap,
  5139.                            "capability of modem", "", xxstring)) < 0) {
  5140.                 if (y == -3)
  5141.                   break;
  5142.                 else
  5143.                   return(y);
  5144.             }
  5145.             zz |= y;
  5146.         }
  5147.         if ((x = cmcfm()) < 0)
  5148.           return(x);
  5149.         dialcapas = zz;
  5150.         debug(F101,"setmodem autoflow","",autoflow);
  5151.         debug(F101,"setmodem flow 1","",flow);
  5152.         if (autoflow)                   /* Maybe change flow control */
  5153.           setflow();
  5154.         debug(F101,"setmodem flow 2","",flow);
  5155.         mdmspd = zz & CKD_SB ? 0 : 1;   /* Set MODEM SPEED-MATCHING from it. */
  5156.         return(success = 1);
  5157.  
  5158.       case XYDMAX:
  5159. #ifdef TN_COMPORT
  5160.         if (network && istncomport())
  5161.           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
  5162.         else
  5163. #endif /* TN_COMPORT */
  5164.           x = cmkey(spdtab,nspd,line,"",xxstring);
  5165.         if (x < 0) {
  5166.             if (x == -3) printf("?value required\n");
  5167.             return(x);
  5168.         }
  5169.         if ((y = cmcfm()) < 0) return(y);
  5170.         dialmax = (long) x * 10L;
  5171.         if (dialmax == 70) dialmax = 75;
  5172.         return(success = 1);
  5173.  
  5174.       case XYDSTR:                      /* These moved from SET DIAL */
  5175.       case XYDDC:
  5176.       case XYDEC:
  5177.       case XYDESC:
  5178.       case XYDFC:
  5179.       case XYDKSP:
  5180.       case XYDSPD:
  5181.       case XYDDIA:
  5182.         return(setdial(x));
  5183.  
  5184.       case XYDTYP:
  5185.         if ((y = cmkey(mdmtab,nmdm,"modem type","none", xxstring)) < 0)
  5186.           return(y);
  5187.         if (y == dialudt) {             /* User-defined modem type */
  5188.             if ((x = cmkey(mdmtab,nmdm,"based on existing modem type",
  5189.                            "unknown", xxstring)) < 0)
  5190.               return(x);
  5191.         }
  5192.         if ((z = cmcfm()) < 0)
  5193.           return(z);
  5194.         usermdm = 0;
  5195.         usermdm = (y == dialudt) ? x : 0;
  5196.         initmdm(y);
  5197.         mdmset = (mdmtyp > 0);
  5198.         return(success = 1);
  5199.  
  5200.       case XYDNAM:
  5201.         return(dialstr(&dialname,"Descriptive name for modem"));
  5202.  
  5203.       case XYDMCD:                      /* SET MODEM CARRIER-WATCH */
  5204.         return(setdcd());
  5205.  
  5206.       case XYDSPK:                      /* SET MODEM SPEAKER */
  5207.         return(seton(&mdmspk));
  5208.  
  5209.       case XYDVOL:                      /* SET MODEM VOLUME */
  5210.         if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0)
  5211.           return(x);
  5212.         if ((y = cmcfm()) < 0)
  5213.           return(y);
  5214.         mdmvol = x;
  5215.         return(success = 1);
  5216.  
  5217.       default:
  5218.         printf("Unexpected SET MODEM parameter\n");
  5219.         return(-9);
  5220.     }
  5221. }
  5222.  
  5223. static int                              /* Set DIAL command options */
  5224. setdial(y) int y; {
  5225.     int x = 0, z = 0;
  5226.     char *s = NULL;
  5227.  
  5228.     if (y < 0)
  5229.       if ((y = cmkey(dialtab,ndial,"","",xxstring)) < 0)
  5230.         return(y);
  5231.     switch (y) {
  5232.       case XYDHUP:                      /* DIAL HANGUP */
  5233.         return(seton(&dialhng));
  5234.       case XYDINI:                      /* DIAL INIT-STRING */
  5235.         return(dialstr(&dialini,"Modem initialization string"));
  5236.       case XYDNPR:                      /* DIAL PREFIX */
  5237.         return(dialstr(&dialnpr,"Telephone number prefix"));
  5238.       case XYDDIA:                      /* DIAL DIAL-COMMAND */
  5239.         x = cmtxt("Dialing command for modem,\n\
  5240.  include \"%s\" to stand for phone number,\n\
  5241.  for example, \"set dial dial-command ATDT%s\\13\"",
  5242.                   "",
  5243.                   &s,
  5244.                   xxstring);
  5245.         if (x < 0 && x != -3)           /* Handle parse errors */
  5246.           return(x);
  5247.         s = brstrip(s);                 /* Strip braces or quotes */
  5248.         y = x = strlen(s);              /* Get length of text */
  5249.         if (y > 0) {                    /* If there is any text (left), */
  5250.             for (x = 0; x < y; x++) {   /* make sure they included "%s" */
  5251.                 if (s[x] != '%') continue;
  5252.                 if (s[x+1] == 's') break;
  5253.             }
  5254.             if (x == y) {
  5255.                 printf(
  5256. "?Dial-command must contain \"%cs\" for phone number.\n",'%');
  5257.                 return(-9);
  5258.             }
  5259.         }
  5260.         if (dialcmd) {                  /* Free any previous string. */
  5261.             free(dialcmd);
  5262.             dialcmd = (char *) 0;
  5263.         }
  5264.         if (y > 0) {
  5265.             dialcmd = malloc(y + 1);    /* Allocate space for it */
  5266.             if (dialcmd)
  5267.               strcpy(dialcmd,s);        /* and make a safe copy. */
  5268.         }
  5269.         return(success = 1);
  5270. #ifndef NOXFER
  5271.       case XYDKSP:                      /* DIAL KERMIT-SPOOF */
  5272.         return(seton(&dialksp));
  5273. #endif /* NOXFER */
  5274.       case XYDTMO:                      /* DIAL TIMEOUT */
  5275.         y = cmnum("Seconds to wait for call completion","0",10,&x,xxstring);
  5276.         if (y < 0) return(y);
  5277.         y = cmnum("Kermit/modem timeout differential","10",10,&z,xxstring);
  5278.         if (y < 0) return(y);
  5279.         if ((y = cmcfm()) < 0)
  5280.           return(y);
  5281.         dialtmo = x;
  5282.         mdmwaitd = z;
  5283.       case XYDESC:                      /* DIAL ESCAPE-CHARACTER */
  5284.         y = cmnum("ASCII value of character to escape back to modem",
  5285.                   "43",10,&x,xxstring);
  5286.         y = setnum(&dialesc,x,y,128);
  5287.         if (y > -1 && dialesc < 0)      /* No escape character */
  5288.           dialmhu = 0;                  /* So no hangup by modem command */
  5289.         return(y);
  5290.       case XYDDPY:                      /* DIAL DISPLAY */
  5291.         return(seton(&dialdpy));
  5292.       case XYDSPD:                      /* DIAL SPEED-MATCHING */
  5293.                                         /* used to be speed-changing */
  5294.         if ((y = seton(&mdmspd)) < 0) return(y);
  5295. #ifdef COMMENT
  5296.         mdmspd = 1 - mdmspd;            /* so here we reverse the meaning */
  5297. #endif /* COMMENT */
  5298.         return(success = 1);
  5299.       case XYDMNP:                      /* DIAL MNP-ENABLE */
  5300.       case XYDEC:                       /* DIAL ERROR-CORRECTION */
  5301.         x = seton(&dialec);
  5302.         if (x > 0)
  5303.           if (!dialec) dialdc = 0;      /* OFF also turns off compression */
  5304.         return(x);
  5305.  
  5306.       case XYDDC:                       /* DIAL COMPRESSION */
  5307.         x = seton(&dialdc);
  5308.         if (x > 0)
  5309.           if (dialdc) dialec = 1;       /* ON also turns on error correction */
  5310.         return(x);
  5311.  
  5312. #ifdef MDMHUP
  5313.       case XYDMHU:                      /* DIAL MODEM-HANGUP */
  5314.         return(seton(&dialmhu));
  5315. #endif /* MDMHUP */
  5316.  
  5317. #ifndef NOSPL
  5318.       case XYDDIR:                      /* DIAL DIRECTORY (zero or more) */
  5319.         return(parsdir(0));             /* 0 means DIAL */
  5320. #endif /* NOSPL */
  5321.  
  5322.       case XYDSTR:                      /* DIAL STRING */
  5323.         if ((y = cmkey(mdmcmd,nmdmcmd,"","",xxstring)) < 0) return(y);
  5324.         switch (y) {
  5325.           case XYDS_AN:                 /* Autoanswer ON/OFF */
  5326.           case XYDS_DC:                 /* Data compression ON/OFF */
  5327.           case XYDS_EC:                 /* Error correction ON/OFF */
  5328.             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
  5329.               return(x);
  5330.             sprintf(tmpbuf,"Modem's command to %sable %s", /* SAFE */
  5331.                     x ? "en" : "dis",
  5332.                     (y == XYDS_DC) ? "compression" :
  5333.                     ((y == XYDS_EC) ? "error-correction" :
  5334.                     "autoanswer")
  5335.                     );
  5336.             if (x) {
  5337.                 if (y == XYDS_DC)
  5338.                   return(dialstr(&dialdcon,tmpbuf));
  5339.                 else if (y == XYDS_EC)
  5340.                   return(dialstr(&dialecon,tmpbuf));
  5341.                 else
  5342.                   return(dialstr(&dialaaon,tmpbuf));
  5343.             } else {
  5344.                 if (y == XYDS_DC)
  5345.                   return(dialstr(&dialdcoff,tmpbuf));
  5346.                 else if (y == XYDS_EC)
  5347.                   return(dialstr(&dialecoff,tmpbuf));
  5348.                 else
  5349.                   return(dialstr(&dialaaoff,tmpbuf));
  5350.             }
  5351.           case XYDS_HU:                 /*    hangup command */
  5352.             return(dialstr(&dialhcmd,"Modem's hangup command"));
  5353.           case XYDS_HW:                 /*    hwfc */
  5354.             return(dialstr(&dialhwfc,
  5355.                            "Modem's command to enable hardware flow control"));
  5356.           case XYDS_IN:                 /*    init */
  5357.             return(dialstr(&dialini,"Modem's initialization string"));
  5358.           case XYDS_NF:                 /*    no flow control */
  5359.             return(dialstr(&dialnofc,
  5360.                            "Modem's command to disable local flow control"));
  5361.           case XYDS_PX:                 /*    prefix */
  5362.             return(dialstr(&dialnpr,"Telephone number prefix for dialing"));
  5363.           case XYDS_SW:                 /*    swfc */
  5364.             return(dialstr(&dialswfc,
  5365.                    "Modem's command to enable local software flow control"));
  5366.           case XYDS_DT:                 /*    tone dialing */
  5367.             return(dialstr(&dialtone,
  5368.                    "Command to configure modem for tone dialing"));
  5369.           case XYDS_DP:                 /*    pulse dialing */
  5370.             return(dialstr(&dialpulse,
  5371.                            "Command to configure modem for pulse dialing"));
  5372.           case XYDS_MS:                 /*    dial mode string */
  5373.             return(dialstr(&dialmstr,
  5374.                          "Command to enter dial mode"));
  5375.           case XYDS_MP:                 /*    dial mode prompt */
  5376.             return(dialstr(&dialmprmt,
  5377.                            "Modem response upon entering dial mode"));
  5378.           case XYDS_SP:                 /* SPEAKER OFF */
  5379.             if ((x = cmkey(onoff,2,"","on",xxstring)) < 0) return(x);
  5380.             if (x)
  5381.               return(dialstr(&dialspon,"Command to turn modem speaker on"));
  5382.             else
  5383.               return(dialstr(&dialspoff,"Command to turn modem speaker off"));
  5384.  
  5385.           case XYDS_VO:                 /* VOLUME LOW */
  5386.             if ((x = cmkey(voltab,3,"","medium",xxstring)) < 0) return(x);
  5387.             switch (x) {
  5388.               case 0:
  5389.               case 1:
  5390.                 return(dialstr(&dialvol1,
  5391.                                "Command for low modem speaker volume"));
  5392.               case 2:
  5393.                 return(dialstr(&dialvol2,
  5394.                            "Command for medium modem speaker volume"));
  5395.  
  5396.               case 3:
  5397.                 return(dialstr(&dialvol3,
  5398.                                "Command for high modem speaker volume"));
  5399.               default:
  5400.                 return(-2);
  5401.             }
  5402.  
  5403.           case XYDS_ID:                 /* IGNORE-DIALTONE */
  5404.             return(dialstr(&dialx3,
  5405.                            "Command to tell modem to ignore dialtone"));
  5406.  
  5407.           case XYDS_I2:                 /* PREDIAL-INIT */
  5408.             return(dialstr(&dialini2,
  5409.                            "Command to send to modem just prior to dialing"));
  5410.  
  5411.           default:
  5412.             printf("?Unexpected SET DIAL STRING parameter\n");
  5413.         }
  5414.  
  5415.       case XYDFC:                       /* DIAL FLOW-CONTROL */
  5416.         if ((y = cmkey(dial_fc,4,"","auto",xxstring)) < 0) return(y);
  5417.         if ((x = cmcfm()) < 0) return(x);
  5418.         dialfc = y;
  5419.         return(success = 1);
  5420.  
  5421.       case XYDMTH: {                    /* DIAL METHOD */
  5422.         extern int dialmauto;
  5423.         if ((y = cmkey(dial_m,ndial_m,"","default",xxstring)) < 0)
  5424.           return(y);
  5425.         if ((x = cmcfm()) < 0)
  5426.           return(x);
  5427.         if (y == XYDM_A) {              /* AUTO */
  5428.             dialmauto = 1;              /* local country code, if known. */
  5429.             dialmth = XYDM_D;
  5430.         } else {
  5431.           dialmauto = 0;                /* use the method specified */
  5432.           dialmth = y;
  5433.         }
  5434.         return(success = 1);
  5435.       }
  5436.       case XYDRTM:
  5437.         y = cmnum("Number of times to try dialing a number",
  5438.                   "1",10,&x,xxstring);
  5439.         return(setnum(&dialrtr,x,y,16383));
  5440.  
  5441.       case XYDINT:
  5442.         y = cmnum("Seconds to wait between redial attempts",
  5443.                   "30",10,&x,xxstring);
  5444.         return(setnum(&dialint,x,y,128));
  5445.  
  5446.       case XYDLAC:                      /* DIAL AREA-CODE */
  5447.         if ((x = dialstr(&diallac,"Area code you are calling from")) < 0)
  5448.           return(x);
  5449.         if (diallac) {
  5450.             if (!rdigits(diallac)) {
  5451.                 printf("?Sorry, area code must be numeric\n");
  5452.                 if (*diallac == '(')
  5453.                   printf("(please omit the parentheses)\n");
  5454.                 if (*diallac == '/')
  5455.                   printf("(no slashes, please)\n");
  5456.                 if (diallac) free(diallac);
  5457.                 diallac = NULL;
  5458.                 return(-9);
  5459.             }
  5460.         }
  5461.         return(x);
  5462.  
  5463.       case XYDCNF:                      /* CONFIRMATION */
  5464.         return(success = seton(&dialcnf));
  5465.  
  5466.       case XYDCVT:                      /* CONVERT-DIRECTORY */
  5467.         if ((y = cmkey(dcnvtab,3,"","ask",xxstring)) < 0)
  5468.           return(y);
  5469.         if ((x = cmcfm()) < 0)
  5470.           return(x);
  5471.         dialcvt = y;
  5472.         return(success = 1);
  5473.  
  5474.       case XYDLCC:                      /* DIAL COUNTRY-CODE */
  5475.         x = dialstr(&diallcc,"Country code you are calling from");
  5476.         if (x < 1) return(x);
  5477.         if (diallcc) {
  5478.             if (!rdigits(diallcc)) {
  5479.                 printf("?Sorry, country code must be numeric\n");
  5480.                 if (*diallcc == '+')
  5481.                   printf("(please omit the plus sign)\n");
  5482.                 if (diallcc) free(diallcc);
  5483.                 diallcc = NULL;
  5484.                 return(-9);
  5485.             }
  5486.             if (!strcmp(diallcc,"1")) { /* Set defaults for USA and Canada */
  5487.                 if (!dialldp)           /* Long-distance prefix */
  5488.                   makestr(&dialldp,"1");
  5489.                 if (!dialixp)           /* International dialing prefix */
  5490.                   makestr(&dialixp,"011");
  5491.                 if (ntollfree == 0) {   /* Toll-free area codes */
  5492.                     if ((dialtfc[0] = malloc(4))) {
  5493.                         strcpy(dialtfc[0],"800"); /* 1970-something */
  5494.                         ntollfree++;
  5495.                         if ((dialtfc[1] = malloc(4))) {
  5496.                             strcpy(dialtfc[1],"888"); /* 1996 */
  5497.                             ntollfree++;
  5498.                             if ((dialtfc[2] = malloc(4))) {
  5499.                                 strcpy(dialtfc[2],"877"); /* 5 April 1998 */
  5500.                                 ntollfree++;
  5501.                                 if ((dialtfc[3] = malloc(4))) {
  5502.                                     strcpy(dialtfc[3],"866"); /* 2000? */
  5503.                                     ntollfree++;
  5504.                                 }
  5505.                             }
  5506.                         }
  5507.                     }
  5508.                 }
  5509.                 if (!dialtfp)           /* Toll-free dialing prefix */
  5510.                   makestr(&dialtfp,"1");
  5511. #ifdef COMMENT
  5512. /* The time for this is past */
  5513.             } else if (!strcmp(diallcc,"358") &&
  5514.                        ((int) strcmp(zzndate(),"19961011") > 0)
  5515.                        ) {              /* Finland */
  5516.                 if (!dialldp)           /* Long-distance prefix */
  5517.                   makestr(&dialldp,"9");
  5518.                 if (!dialixp)           /* International dialing prefix */
  5519.                   makestr(&dialixp,"990");
  5520. #endif /* COMMENT */
  5521.             } else {                    /* Everywhere else ... */
  5522.                 if (!dialldp) {
  5523.                     if ((dialldp = malloc(4)))
  5524.                       strcpy(dialldp,"0");
  5525.                 }
  5526.                 if (!dialixp) {
  5527.                     if ((dialixp = malloc(4)))
  5528.                       strcpy(dialixp,"00");
  5529.                 }
  5530.             }
  5531.             if (!strcmp(diallcc,"33"))  /* France */
  5532.               dialfld = 1;              /* Long-distance dialing is forced */
  5533.         }
  5534.         return(success = 1);
  5535.  
  5536.       case XYDIXP:                      /* DIAL INTL-PREFIX */
  5537.         return(dialstr(&dialixp,"International dialing prefix"));
  5538.  
  5539.       case XYDIXS:                      /* DIAL INTL-SUFFIX */
  5540.         return(dialstr(&dialixs,"International dialing suffix"));
  5541.  
  5542.       case XYDLDP:                      /* DIAL LD-PREFIX */
  5543.         return(dialstr(&dialldp,"Long-distance dialing prefix"));
  5544.  
  5545.       case XYDLDS:                      /* DIAL LD-SUFFIX */
  5546.         return(dialstr(&diallds,"Long-distance dialing suffix"));
  5547.  
  5548.       case XYDLCP:                      /* DIAL LC-PREFIX */
  5549.         return(dialstr(&diallcp,"Local dialing prefix"));
  5550.  
  5551.       case XYDLCS:                      /* DIAL LC-SUFFIX */
  5552.         return(dialstr(&diallcs,"Local dialing suffix"));
  5553.  
  5554. #ifdef COMMENT
  5555.       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
  5556.         return(dialstr(&dialpxx,"Exchange of PBX you are calling from"));
  5557. #endif /* COMMENT */
  5558.  
  5559.       case XYDPXI: {                    /* DIAL PBX-INTERNAL-PREFIX */
  5560. #ifdef COMMENT
  5561.           return(dialstr(&dialpxi,
  5562.                        "Internal-call prefix of PBX you are calling from"));
  5563. #else
  5564.           int x;
  5565.           if ((x = cmtxt("Internal-call prefix of PBX you are calling from",
  5566.                          "",&s,NULL)) < 0) /* Don't evaluate */
  5567.             return(x);
  5568. #ifndef NOSPL
  5569.           if (*s) {
  5570.               char c, * p = tmpbuf;
  5571.               if (*s == '\\') {
  5572.                   c = *(s+1);
  5573.                   if (isupper(c)) c = tolower(c);
  5574.                   if (c != 'f' &&
  5575.                       ckstrcmp(s,"\\v(d$px)",8,0) &&
  5576.                       ckstrcmp(s,"\\v(d$pxx)",9,0) &&
  5577.                       ckstrcmp(s,"\\v(d$p)",7,0)) {
  5578.                       x = TMPBUFSIZ;
  5579.                       zzstring(s,&p,&x);
  5580.                       s = tmpbuf;
  5581.                   }
  5582.               }
  5583.           }
  5584. #endif /* NOSPL */
  5585.           makestr(&dialpxi,s);
  5586.           return(1);
  5587.       }
  5588. #endif /* COMMENT */
  5589.  
  5590.       case XYDPXO:                      /* DIAL PBX-OUTSIDE-PREFIX */
  5591.         return(dialstr(&dialpxo,
  5592.                        "Outside-line prefix of PBX you are calling from"));
  5593.  
  5594.       case XYDSFX:                      /* DIAL INTL-SUFFIX */
  5595.         return(dialstr(&dialsfx," Telephone number suffix for dialing"));
  5596.  
  5597.       case XYDSRT:                      /* DIAL SORT */
  5598.         return(success = seton(&dialsrt));
  5599.  
  5600.       case XYDPXX:                      /* DIAL PBX-EXCHANGE */
  5601.       case XYDTFC: {                    /* DIAL TOLL-FREE-AREA-CODE  */
  5602.           int n, i;                     /* (zero or more of them...) */
  5603.           char * p[MAXTOLLFREE];        /* Temporary pointers */
  5604.           char * m;
  5605.           for (n = 0; n < MAXTOLLFREE; n++) {
  5606.               if (n == 0) {
  5607.                   m = (y == XYDTFC) ?
  5608.                   "Toll-free area code(s) in the country you are calling from"
  5609.                     : "Exchange(s) of PBX you are calling from";
  5610.               } else {
  5611.                   m = (y == XYDTFC) ?
  5612.                     "Another toll-free area code"
  5613.                       : "Another PBX exchange";
  5614.               }
  5615.               if ((x = cmfld(m,"",&s,xxstring)) < 0)
  5616.                 break;
  5617.               if (s) {
  5618.                   int k;
  5619.                   k = (int) strlen(s);
  5620.                   if (k > 0) {
  5621.                       if ((p[n] = malloc(k + 1)))
  5622.                         strcpy(p[n], s); /* safe */
  5623.                   } else break;
  5624.               } else break;
  5625.           }
  5626.           if (x == -3) {                /* Command was successful */
  5627.               int m;
  5628.               m = (y == XYDTFC) ? ntollfree : ndialpxx;
  5629.               if ((x = cmcfm()) < 0)
  5630.                 return(x);
  5631.               x = 1;
  5632.               for (i = 0; i < m; i++) { /* Remove old list, if any */
  5633.                   if  (y == XYDTFC)
  5634.                     makestr(&(dialtfc[i]),NULL);
  5635.                   else
  5636.                     makestr(&(dialpxx[i]),NULL);
  5637.               }
  5638.               if  (y == XYDTFC)
  5639.                 ntollfree = n;          /* New count */
  5640.               else
  5641.                 ndialpxx = n;
  5642.               for (i = 0; i < n; i++) { /* New list */
  5643.                   if  (y == XYDTFC)
  5644.                     makestr(&(dialtfc[i]),p[i]);
  5645.                   else
  5646.                     makestr(&(dialpxx[i]),p[i]);
  5647.               }
  5648.               x = 1;
  5649.           }
  5650.           for (i = 0; i < n; i++)
  5651.             if (p[i]) free(p[i]);
  5652.           return(x);
  5653.       }
  5654.  
  5655.       case XYDTFP:                      /* TOLL-FREE-PREFIX */
  5656.         return(dialstr(&dialtfp,
  5657.                        " Long-distance prefix for toll-free dialing"));
  5658.  
  5659.       case XYDCON:                      /* CONNECT */
  5660.         z = -1;
  5661.         if ((y = cmkey(crrtab,ncrr,"","auto",xxstring)) < 0) return(y);
  5662.         if (y != CAR_OFF)               /* AUTO or ON? */
  5663.           if ((z = cmkey(qvtab,nqvt,"","verbose",xxstring)) < 0) return(z);
  5664.         if ((x = cmcfm()) < 0) return(x);
  5665.         if (z > -1)
  5666.           dialcq = z;
  5667.         dialcon = y;
  5668.         return(success = 1);
  5669.  
  5670.       case XYDRSTR:                     /* RESTRICT */
  5671.         if ((y = cmkey(drstrtab,4,"","none",xxstring)) < 0) return(y);
  5672.         if ((x = cmcfm()) < 0) return(x);
  5673.         dialrstr = y;
  5674.         return(success = 1);
  5675.  
  5676.       case XYDLLAC: {                   /* Local area-code list  */
  5677.           int n, i;                     /* (zero or more of them...) */
  5678.           char * p[MAXLOCALAC]; /* Temporary pointers */
  5679.           for (n = 0; n < MAXLOCALAC; n++) {
  5680.               if ((x = cmfld(
  5681.                     "Area code to which calls from your area are local",
  5682.                        "",&s,xxstring)) < 0)
  5683.                 break;
  5684.               if (s) {
  5685.                   int k;
  5686.                   k = (int) strlen(s);
  5687.                   if (k > 0) {
  5688.                       if ((p[n] = malloc(k + 1)))
  5689.                         strcpy(p[n], s); /* safe */
  5690.                   } else break;
  5691.               } else break;
  5692.           }
  5693.           if (x == -3) {                /* Command was successful */
  5694.               if ((x = cmcfm()) < 0)
  5695.                 return(x);
  5696.               for (i = 0; i < nlocalac; i++) /* Remove old list, if any */
  5697.                 if (diallcac[i]) {
  5698.                     free(diallcac[i]);
  5699.                     diallcac[i] = NULL;
  5700.                 }
  5701.               nlocalac = n;             /* New count */
  5702.               for (i = 0; i < nlocalac; i++) /* New list */
  5703.                 diallcac[i] = p[i];
  5704.               return(success = 1);
  5705.           } else {                      /* Parse error, undo everything */
  5706.               for (i = 0; i < n; i++)
  5707.                 if (p[i]) free(p[i]);
  5708.               return(x);
  5709.           }
  5710.       }
  5711.  
  5712.       case XYDFLD:
  5713.         return(success = seton(&dialfld));
  5714.  
  5715.       case XYDIDT:                      /* DIAL IGNORE-DIALTONE */
  5716.         return(seton(&dialidt));
  5717.  
  5718.       case XYDPAC:
  5719.         y = cmnum(
  5720.               "Milliseconds to pause between each character sent to dialer",
  5721.                   "",10,&x,xxstring);
  5722.         return(setnum(&dialpace,x,y,9999));
  5723.  
  5724. #ifndef NOSPL
  5725.       case XYDMAC:
  5726.         if ((x = cmfld("Name of macro to execute just prior to dialing",
  5727.                        "",&s,xxstring)) < 0) {
  5728.             if (x == -3)
  5729.               s = NULL;
  5730.             else
  5731.               return(x);
  5732.         }
  5733.         if (s) {
  5734.             if (!*s) {
  5735.                 s = NULL;
  5736.             } else {
  5737.                 ckstrncpy(line,s,LINBUFSIZ);
  5738.                 s = line;
  5739.             }
  5740.         }
  5741.         if ((x = cmcfm()) < 0)
  5742.           return(x);
  5743.         makestr(&dialmac,s);
  5744.         return(success = 1);
  5745. #endif /* NOSPL */
  5746.  
  5747.       case XYDPUCC:                     /* Pulse country codes */
  5748.       case XYDTOCC: {                   /* Tone country codes */
  5749.           int n, i;
  5750.           char * p[MAXTPCC];
  5751.           char * m;
  5752.           for (n = 0; n < MAXTPCC; n++) {
  5753.               if (n == 0) {
  5754.                   m = (y == XYDPUCC) ?
  5755.                   "Country code where Pulse dialing is required"
  5756.                     : "Country code where Tone dialing is available";
  5757.               } else
  5758.                 m = "Another country code";
  5759.               if ((x = cmfld(m,"",&s,xxstring)) < 0)
  5760.                 break;
  5761.               if (s) {
  5762.                   int k;
  5763.                   k = (int) strlen(s);
  5764.                   if (k > 0) {
  5765.                       if ((p[n] = malloc(k + 1)))
  5766.                         strcpy(p[n], s); /* safe */
  5767.                   } else break;
  5768.               } else break;
  5769.           }
  5770.           if (x == -3) {                /* Command was successful */
  5771.               int m;
  5772.               m = (y == XYDPUCC) ? ndialpucc : ndialtocc;
  5773.               if ((x = cmcfm()) < 0)
  5774.                 return(x);
  5775.               x = 1;
  5776.               for (i = 0; i < m; i++) { /* Remove old list, if any */
  5777.                   if (y == XYDPUCC)
  5778.                     makestr(&(dialpucc[i]),NULL);
  5779.                   else
  5780.                     makestr(&(dialtocc[i]),NULL);
  5781.               }
  5782.               if (y == XYDPUCC) {
  5783.                   ndialpucc = n;                /* New count */
  5784.               } else {
  5785.                   ndialtocc = n;
  5786.               }
  5787.               for (i = 0; i < n; i++) { /* New list */
  5788.                   if (y == XYDPUCC) {
  5789.                       makestr(&(dialpucc[i]),p[i]);
  5790.                   } else {
  5791.                       makestr(&(dialtocc[i]),p[i]);
  5792.                   }
  5793.               }
  5794.               x = 1;
  5795.           }
  5796.           for (i = 0; i < n; i++)
  5797.             if (p[i]) free(p[i]);
  5798.           return(x);
  5799.       }
  5800.       case XYDTEST:
  5801.         return(seton(&dialtest));
  5802.  
  5803.       default:
  5804.         printf("?Unexpected SET DIAL parameter\n");
  5805.         return(-9);
  5806.     }
  5807. }
  5808.  
  5809. #ifdef CK_TAPI
  5810. int                                             /* TAPI action commands */
  5811. dotapi() {
  5812.     int x,y;
  5813.     char *s;
  5814.  
  5815.     if (!TAPIAvail) {
  5816.         printf("\nTAPI is unavailable on this system.\n");
  5817.         return(-9);
  5818.     }
  5819.     if ((y = cmkey(tapitab,ntapitab,"MS TAPI command","",xxstring)) < 0)
  5820.       return(y);
  5821.     switch (y) {
  5822.       case XYTAPI_CFG: {                        /* TAPI CONFIGURE-LINE */
  5823.           extern struct keytab * tapilinetab;
  5824.           extern struct keytab * _tapilinetab;
  5825.           extern int ntapiline;
  5826.           extern int LineDeviceId;
  5827.           int lineID=LineDeviceId;
  5828.           if (TAPIAvail)
  5829.             cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
  5830.           if (tapilinetab && _tapilinetab && ntapiline > 0) {
  5831.               int i=0, j = 9999, k = -1;
  5832.  
  5833.               if ( LineDeviceId == -1 ) {
  5834.                   /* Find out what the lowest numbered TAPI device is */
  5835.                   /* and use it as the default.                       */
  5836.                   for (i = 0; i < ntapiline; i++ ) {
  5837.                       if (tapilinetab[i].kwval < j) {
  5838.                           k = i;
  5839.                       }
  5840.                   }
  5841.               } else {
  5842.                   /* Find the LineDeviceId in the table and use that entry */
  5843.                   for (i = 0; i < ntapiline; i++ ) {
  5844.                       if (tapilinetab[i].kwval == LineDeviceId) {
  5845.                           k = i;
  5846.                           break;
  5847.                       }
  5848.                   }
  5849.               }
  5850.               if (k >= 0)
  5851.                 s = _tapilinetab[k].kwd;
  5852.               else
  5853.                 s = "";
  5854.  
  5855.               if ((y = cmkey(_tapilinetab,ntapiline,
  5856.                               "TAPI device name",s,xxstring)) < 0)
  5857.                 return(y);
  5858.               lineID = y;
  5859.           }
  5860.           if ((x = cmcfm()) < 0) return(x);
  5861. #ifdef IKSD
  5862.           if (inserver) {
  5863.               printf("Sorry, command disabled\r\n");
  5864.               return(success = 0);
  5865.           }
  5866. #endif /* ISKD */
  5867.           cktapiConfigureLine(lineID);
  5868.           break;
  5869.       }
  5870.       case XYTAPI_DIAL:                 /* TAPI DIALING-PROPERTIES */
  5871.         if ((x = cmcfm()) < 0)
  5872.           return(x);
  5873. #ifdef IKSD
  5874.         if (inserver) {
  5875.             printf("Sorry, command disabled\r\n");
  5876.             return(success = 0);
  5877.         }
  5878. #endif /* ISKD */
  5879.         cktapiDialingProp();
  5880.         break;
  5881.     }
  5882.     return(success = 1);
  5883. }
  5884.  
  5885. static int                              /* SET TAPI command options */
  5886. settapi() {
  5887.     int x, y;
  5888.     char *s;
  5889.  
  5890.     if (!TAPIAvail) {
  5891.         printf("\nTAPI is unavailable on this system.\n");
  5892.         return(-9);
  5893.     }
  5894.     if ((y = cmkey(settapitab,nsettapitab,"MS TAPI option","",xxstring)) < 0)
  5895.       return(y);
  5896.     switch (y) {
  5897.       case XYTAPI_USE:
  5898.         return (success = seton(&tapiusecfg));
  5899.       case XYTAPI_LGHT:
  5900.         return (success = seton(&tapilights));
  5901.       case XYTAPI_PRE:
  5902.         return (success = seton(&tapipreterm));
  5903.       case XYTAPI_PST:
  5904.         return (success = seton(&tapipostterm));
  5905.       case XYTAPI_INA:
  5906.         y = cmnum("seconds of inactivity before auto-disconnect",
  5907.                   "0",10,&x,xxstring);
  5908.         return(setnum(&tapiinactivity,x,y,65535));
  5909.       case XYTAPI_BNG:
  5910.         y = cmnum("seconds to wait for credit card tone",
  5911.                   "8",10,&x,xxstring);
  5912.         return(setnum(&tapibong,x,y,90));
  5913.       case XYTAPI_MAN:
  5914.         return (success = seton(&tapimanual));
  5915.       case XYTAPI_CON:                  /* TAPI CONVERSIONS */
  5916.         return (success = setonaut(&tapiconv));
  5917.       case XYTAPI_LIN:                  /* TAPI LINE */
  5918.         x = setlin(XYTAPI_LIN,1,0);
  5919.         if (x > -1) didsetlin++;
  5920.         return(x);
  5921.       case XYTAPI_PASS: {               /* TAPI PASSTHROUGH */
  5922.         /* Passthrough became Modem-dialing which is an antonym */
  5923.         success = seton(&tapipass);
  5924.         tapipass = !tapipass;
  5925.         return (success);
  5926.       }
  5927.       case XYTAPI_LOC: {                /* TAPI LOCATION */
  5928.           extern char tapiloc[];
  5929.           extern int tapilocid;
  5930.           int i = 0, j = 9999, k = -1;
  5931.  
  5932.           cktapiBuildLocationTable(&tapiloctab, &ntapiloc);
  5933.           if (!tapiloctab || !ntapiloc) {
  5934.               printf("\nNo TAPI Locations are configured for this system\n");
  5935.               return(-9);
  5936.           }
  5937.           if (tapilocid == -1)
  5938.             tapilocid = cktapiGetCurrentLocationID();
  5939.  
  5940.           /* Find the current tapiloc entry */
  5941.           /* and use it as the default. */
  5942.           for (k = 0; k < ntapiloc; k++) {
  5943.               if (tapiloctab[k].kwval == tapilocid)
  5944.                 break;
  5945.           }
  5946.           if (k >= 0 && k < ntapiloc)
  5947.             s = tapiloctab[k].kwd;
  5948.           else
  5949.             s = "";
  5950.  
  5951.           if ((y = cmkey(tapiloctab,ntapiloc, "TAPI location",s,xxstring)) < 0)
  5952.             return(y);
  5953.  
  5954.           if ((x = cmcfm()) < 0)
  5955.             return(x);
  5956. #ifdef IKSD
  5957.           if (inserver) {
  5958.               printf("Sorry, command disabled\r\n");
  5959.               return(success = 0);
  5960.           }
  5961. #endif /* ISKD */
  5962.           cktapiFetchLocationInfoByID( y );
  5963.           CopyTapiLocationInfoToKermitDialCmd();
  5964.         }
  5965.         break;
  5966.     }
  5967.     return(success=1);
  5968. }
  5969. #endif /* CK_TAPI */
  5970.  
  5971. #ifndef NOSHOW
  5972. int                                     /* SHOW MODEM */
  5973. shomodem() {
  5974.     MDMINF * p;
  5975.     int x, n, mdm;
  5976.     char c;
  5977.     long zz;
  5978.  
  5979. #ifdef IKSD
  5980.     if (inserver) {
  5981.         printf("Sorry, command disabled\r\n");
  5982.         return(success = 0);
  5983.     }
  5984. #endif /* IKSD */
  5985.  
  5986.     shmdmlin();
  5987.     printf("\n");
  5988.  
  5989.     mdm = (mdmtyp > 0) ? mdmtyp : mdmsav;
  5990.     p = (mdm > 0) ? modemp[mdm] : NULL;
  5991.  
  5992.     if (p) {
  5993.         printf(" %s\n\n", dialname ? dialname : p->name);
  5994.  
  5995.         printf(" Modem capabilities:    ");
  5996.         zz = dialcapas ? dialcapas : p->capas;
  5997.         if (!zz) {
  5998.             printf(" (none)");
  5999.         } else {
  6000.             if (zz & CKD_AT) printf(" AT");
  6001.             if (zz & CKD_V25) printf(" ITU");
  6002.             if (zz & CKD_SB) printf(" SB");
  6003.             if (zz & CKD_EC) printf(" EC");
  6004.             if (zz & CKD_DC) printf(" DC");
  6005.             if (zz & CKD_HW) printf(" HWFC");
  6006.             if (zz & CKD_SW) printf(" SWFC");
  6007.             if (zz & CKD_KS) printf(" KS");
  6008.             if (zz & CKD_TB) printf(" TB");
  6009.         }
  6010.         printf("\n Modem carrier-watch:    ");
  6011.         if (carrier == CAR_OFF) printf("off\n");
  6012.         else if (carrier == CAR_ON) printf("on\n");
  6013.         else if (carrier == CAR_AUT) printf("auto\n");
  6014.         else printf("unknown\n");
  6015.  
  6016.         printf(" Modem maximum-speed:    ");
  6017.         zz = (dialmax > 0L) ? dialmax : p->max_speed;
  6018.         if (zz > 0)
  6019.           printf("%ld bps\n", zz);
  6020.         else
  6021.           printf("(unknown)\n");
  6022.         printf(" Modem error-correction: %s\n", dialec ? "on" : "off");
  6023.         printf(" Modem compression:      %s\n", dialdc ? "on" : "off");
  6024.         printf(" Modem speed-matching:   %s",   mdmspd ? "on" : "off");
  6025.         printf(" (interface speed %s)\n", mdmspd ? "changes" : "is locked");
  6026.         printf(" Modem flow-control:     ");
  6027.         if (dialfc == FLO_NONE) printf("none\n");
  6028.         else if (dialfc == FLO_XONX) printf("xon/xoff\n");
  6029.         else if (dialfc == FLO_RTSC) printf("rts/cts\n");
  6030.         else if (dialfc == FLO_AUTO) printf("auto\n");
  6031.         printf(" Modem hangup-method:    %s\n",
  6032.                dialmhu ?
  6033.                "modem-command" :
  6034.                "rs232-signal"
  6035.                );
  6036.         printf(" Modem speaker:          %s\n", showoff(mdmspk));
  6037.         printf(" Modem volume:           %s\n",
  6038.                (mdmvol == 2) ? "medium" : ((mdmvol <= 1) ? "low" : "high"));
  6039.         printf(" Modem kermit-spoof:     %s\n", dialksp ? "on" : "off");
  6040.         c = (char) (x = (dialesc ? dialesc : p->esc_char));
  6041.         printf(" Modem escape-character: %d", x);
  6042.         if (isprint(c))
  6043.           printf(" (= \"%c\")",c);
  6044.         printf(
  6045. "\n\nMODEM COMMANDs (* = set automatically by SET MODEM TYPE):\n\n");
  6046.         debug(F110,"show dialini",dialini,0);
  6047.         printf(" %c Init-string:          ", dialini ? ' ' : '*' );
  6048.         shods(dialini ? dialini : p->wake_str);
  6049.         printf(" %c Dial-mode-string:     ", dialmstr ? ' ' : '*' );
  6050.         shods(dialmstr ? dialmstr : p->dmode_str);
  6051.         n = local ? 19 : 20;
  6052.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6053.         printf(" %c Dial-mode-prompt:     ", dialmprmt ? ' ' : '*' );
  6054.         shods(dialmprmt ? dialmprmt : p->dmode_prompt);
  6055.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6056.         printf(" %c Dial-command:         ", dialcmd ? ' ' : '*' );
  6057.         shods(dialcmd ? dialcmd : p->dial_str);
  6058.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6059.         printf(" %c Compression on:       ", dialdcon ? ' ' : '*' );
  6060.         if (!dialdcon)
  6061.           debug(F110,"dialdcon","(null)",0);
  6062.         else
  6063.           debug(F110,"dialdcon",dialdcon,0);
  6064.         shods(dialdcon ? dialdcon : p->dc_on_str);
  6065.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6066.         printf(" %c Compression off:      ", dialdcoff ? ' ' : '*' );
  6067.         shods(dialdcoff ? dialdcoff : p->dc_off_str);
  6068.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6069.         printf(" %c Error-correction on:  ", dialecon ? ' ' : '*' );
  6070.         shods(dialecon ? dialecon : p->ec_on_str);
  6071.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6072.         printf(" %c Error-correction off: ", dialecoff ? ' ' : '*' );
  6073.         shods(dialecoff ? dialecoff : p->ec_off_str);
  6074.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6075.         printf(" %c Autoanswer on:        ", dialaaon ? ' ' : '*' );
  6076.         shods(dialaaon ? dialaaon : p->aa_on_str);
  6077.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6078.         printf(" %c Autoanswer off:       ", dialaaoff ? ' ' : '*' );
  6079.         shods(dialaaoff ? dialaaoff : p->aa_off_str);
  6080.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6081.  
  6082.         printf(" %c Speaker on:           ", dialspon ? ' ' : '*' );
  6083.         shods(dialspon ? dialspon : p->sp_on_str);
  6084.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6085.         printf(" %c Speaker off:          ", dialspoff ? ' ' : '*' );
  6086.         shods(dialspoff ? dialspoff : p->sp_off_str);
  6087.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6088.         printf(" %c Volume low:           ", dialvol1 ? ' ' : '*' );
  6089.         shods(dialvol1 ? dialvol1 : p->vol1_str);
  6090.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6091.         printf(" %c Volume medium:        ", dialvol2 ? ' ' : '*' );
  6092.         shods(dialvol2 ? dialvol2 : p->vol2_str);
  6093.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6094.         printf(" %c Volume high:          ", dialvol3 ? ' ' : '*' );
  6095.         shods(dialvol3 ? dialvol3 : p->vol3_str);
  6096.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6097.  
  6098.         printf(" %c Hangup-command:       ", dialhcmd ? ' ' : '*' );
  6099.         shods(dialhcmd ? dialhcmd : p->hup_str);
  6100.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6101.         printf(" %c Hardware-flow:        ", dialhwfc ? ' ' : '*' );
  6102.         shods(dialhwfc ? dialhwfc : p->hwfc_str);
  6103.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6104.         printf(" %c Software-flow:        ", dialswfc ? ' ' : '*' );
  6105.         shods(dialswfc ? dialswfc : p->swfc_str);
  6106.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6107.         printf(" %c No-flow-control:      ", dialnofc ? ' ' : '*' );
  6108.         shods(dialnofc ? dialnofc : p->nofc_str);
  6109.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6110.         printf(" %c Pulse:                ", dialpulse ? ' ' : '*');
  6111.         shods(dialpulse ? dialpulse : p->pulse);
  6112.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6113.         printf(" %c Tone:                 ", dialtone ? ' ' : '*');
  6114.         shods(dialtone ? dialtone : p->tone);
  6115.  
  6116.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6117.         printf(" %c Ignore-dialtone:      ", dialx3 ? ' ' : '*');
  6118.         shods(dialx3 ? dialx3 : p->ignoredt);
  6119.  
  6120.         if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  6121.         printf(" %c Predial-init:         ", dialini2 ? ' ' : '*');
  6122.         shods(dialini2 ? dialini2 : p->ini2);
  6123.  
  6124.         if (++n > cmd_rows - 4) if (!askmore()) return(0); else n = 0;
  6125.         printf("\n For more info: SHOW DIAL and SHOW COMMUNICATIONS\n");
  6126.  
  6127.     } else if (mdm > 0) {
  6128.         printf("Modem info for \"%s\" not filled in yet\n", gmdmtyp());
  6129.     } else printf(
  6130. " No modem selected, so DIAL and most SET MODEM commands have no effect.\n\
  6131.  Use SET MODEM TYPE to select a modem.\n");
  6132.     return(success = 1);
  6133. }
  6134. #endif /* NOSHOW */
  6135. #endif /* NODIAL */
  6136. #endif /* NOLOCAL */
  6137.  
  6138. #ifndef NOSPL
  6139. #ifdef CK_ANSIC                         /* SET ALARM */
  6140. int
  6141. setalarm(long xx)
  6142. #else
  6143. int
  6144. setalarm(xx) long xx;
  6145. #endif /* CK_ANSIC */
  6146. /* setalarm */ {
  6147. #ifdef COMMENT
  6148.     int yyyy, mm, dd, x;
  6149.     char *s;
  6150.     long zz;
  6151.     char buf[6];
  6152. #endif /* COMMENT */
  6153.     long sec, jd;
  6154.     char xbuf[20], * p;
  6155.  
  6156.     debug(F101,"setalarm xx","",xx);
  6157.     ck_alarm = 0L;                      /* 0 = no alarm (in case of error) */
  6158.     if (xx < 0L) {
  6159.         printf("%ld - illegal value, must be 0 or positive\n", xx);
  6160.         return(-9);
  6161.     }
  6162.     if (xx == 0L) {                     /* CLEAR ALARM */
  6163.         alrm_date[0] = NUL;
  6164.         alrm_time[0] = NUL;
  6165.         return(1);
  6166.     }
  6167. #ifdef COMMENT
  6168.     x = 8;                              /* Get current date */
  6169.     s = alrm_date;
  6170.     if (zzstring("\\v(ndate)",&s,&x) < 0) {
  6171.         printf("Internal date error, sorry.\n");
  6172.         alrm_date[0] = SP;
  6173.         return(-9);
  6174.     }
  6175.     x = 5;                              /* Get current time */
  6176.     s = alrm_time;
  6177.     if (zzstring("\\v(ntime)",&s,&x) < 0) {
  6178.         printf("Internal time error, sorry.\n");
  6179.         alrm_time[0] = SP;
  6180.         return(-9);
  6181.     }
  6182.     sprintf(buf,"%05ld",atol(alrm_time)); /* SAFE (20) */
  6183.     ckstrncpy(alrm_time,buf,8);
  6184.     debug(F110,"SET ALARM date (1)",alrm_date,0);
  6185.     debug(F110,"SET ALARM time (1)",alrm_time,0);
  6186.  
  6187.     if ((zz = atol(alrm_time) + xx) < 0L) {
  6188.         printf("Internal time conversion error, sorry.\n");
  6189.         return(-9);
  6190.     }
  6191.     if (zz >= 86400L) {                 /* Alarm crosses midnight */
  6192.         char d[10];                     /* Local date buffer */
  6193.         int lastday;                    /* Last day of this month */
  6194.  
  6195.         ckstrncpy(d,alrm_date,8);       /* We'll have to change the date */
  6196.  
  6197.         x = (zz / 86400L);              /* How many days after today */
  6198.  
  6199.         dd = atoi((char *)(d+6));       /* Parse yyyymmdd */
  6200.         d[6] = NUL;                     /* into yyyy, mm, dd ... */
  6201.         mm = atoi((char *)(d+4));
  6202.         d[4] = NUL;
  6203.         yyyy = atoi((char *)d);
  6204.  
  6205.         /* How many days in this month */
  6206.  
  6207.         lastday = mdays[mm];
  6208.         if (mm == 2 && yyyy % 4 == 0)   /* Works thru 2099 AD... */
  6209.           lastday++;
  6210.  
  6211.         if (dd + x > lastday) {         /* Dumb loop */
  6212.             int y;
  6213.  
  6214.             x -= (mdays[mm] - dd);      /* Deduct rest of this month's days */
  6215.  
  6216.             /* There's a more elegant way to do this... */
  6217.  
  6218.             while (1) {
  6219.                 mm++;                   /* Next month */
  6220.                 if (mm > 12) {          /* Wrap around */
  6221.                     mm = 1;             /* Jan, next year */
  6222.                     yyyy++;
  6223.                 }
  6224.                 y = mdays[mm];          /* Days in new month */
  6225.                 if (mm == 2 && yyyy % 4 == 0) /* Feb in leap year */
  6226.                   y++;                  /* Works until 2100 AD */
  6227.                 if (x - y < 1)
  6228.                   break;
  6229.                 x -= y;
  6230.             }
  6231.             dd = x;                     /* Day of alarm month */
  6232.         } else dd += x;
  6233.  
  6234.         sprintf(alrm_date,"%04d%02d%02d",yyyy,mm,dd); /* SAFE (24) */
  6235.         zz = zz % 86400L;
  6236.     }
  6237.     sprintf(alrm_time,"%ld",zz);        /* SAFE (24) */
  6238.     debug(F110,"SET ALARM date (2)",alrm_date,0);
  6239.     debug(F110,"SET ALARM time (2)",alrm_time,0);
  6240.     ck_alarm = xx;
  6241. #else
  6242.     /* Jul 1998 */
  6243.     ckstrncpy(xbuf,ckcvtdate("",1),20); /* Get current date and time */
  6244.     p = xbuf;
  6245.     ckstrncpy(alrm_date,xbuf,10);
  6246.     alrm_date[8] = NUL;
  6247.     sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
  6248.     debug(F110,"SET ALARM date (1)",alrm_date,0);
  6249.     debug(F101,"SET ALARM time (1)","",sec);
  6250.     if ((sec += xx) < 0L) {
  6251.         printf("Internal time conversion error, sorry.\n");
  6252.         return(-9);
  6253.     }
  6254.     if (sec >= 86400L) {                /* Alarm crosses midnight */
  6255.         long days;
  6256.         days = sec / 86400L;
  6257.         jd = mjd(p) + days;             /* Get modified Julian date */
  6258.         ckstrncpy(alrm_date,mjd2date(jd),10);
  6259.         sec %= 86400L;
  6260.     }
  6261.     sprintf(alrm_time,"%05ld",sec);     /* SAFE (24) */
  6262.     debug(F110,"SET ALARM date (2)",alrm_date,0);
  6263.     debug(F110,"SET ALARM time (2)",alrm_time,0);
  6264.     ck_alarm = 1;                       /* Alarm is set */
  6265.  
  6266. #endif /* COMMENT */
  6267.     return(success = 1);
  6268. }
  6269. #endif /* NOSPL */
  6270.  
  6271. #ifndef NOSETKEY
  6272. int
  6273. dosetkey() {                            /* SET KEY */
  6274.     int x, y;
  6275.     int flag = 0;
  6276.     int kc;                             /* Key code */
  6277.     char *s;                            /* Key binding */
  6278. #ifndef NOKVERBS
  6279.     char *p;                            /* Worker */
  6280. #endif /* NOKVERBS */
  6281. #ifdef OS2
  6282.     extern int os2gks;
  6283.     extern int mskkeys;
  6284.     extern int initvik;
  6285. #endif /* OS2 */
  6286.  
  6287.     x_ifnum = 1;
  6288.     y = cmnum("numeric key code, or the word CLEAR,","",10,&kc,xxstring);
  6289.     x_ifnum = 0;
  6290.     if (y < 0) {
  6291.         debug(F111,"SET KEY",atmbuf,y);
  6292.         if (y == -2) {                  /* Not a valid number */
  6293.             if ((y = strlen(atmbuf)) < 0) /* Check for SET KEY CLEAR */
  6294.               return(-2);
  6295.             if (ckstrcmp(atmbuf,"clear",y,0))
  6296.               return(-2);
  6297.             if ((x = cmcfm()) < 0)
  6298.               return(x);
  6299.             for (y = 0; y < KMSIZE; y++) {
  6300.                 keymap[y] = (KEY) y;
  6301.                 macrotab[y] = NULL;
  6302.             }
  6303. #ifdef OS2
  6304.             keymapinit();               /* Special OS/2 initializations */
  6305.             initvik = 1;                /* Update the VIK table */
  6306. #endif /* OS2 */
  6307.             return(1);
  6308.         } else if (y == -3) {           /* SET KEY <Return> */
  6309.             printf(" Press key to be defined: "); /* Prompt for a keystroke */
  6310. #ifdef UNIX
  6311. #ifdef NOSETBUF
  6312.             fflush(stdout);
  6313. #endif /* NOSETBUF */
  6314. #endif /* UNIX */
  6315.             conbin((char)escape);       /* Put terminal in binary mode */
  6316. #ifdef OS2
  6317.             os2gks = 0;                 /* Turn off Kverb preprocessing */
  6318. #endif /* OS2 */
  6319.             kc = congks(0);             /* Get character or scan code */
  6320. #ifdef OS2
  6321.             os2gks = 1;                 /* Turn on Kverb preprocessing */
  6322. #endif /* OS2 */
  6323.             concb((char)escape);        /* Restore terminal to cbreak mode */
  6324.             if (kc < 0) {               /* Check for error */
  6325.                 printf("?Error reading key\n");
  6326.                 return(0);
  6327.             }
  6328. #ifdef OS2
  6329.             shokeycode(kc,-1);          /* Show current definition */
  6330. #else
  6331.             shokeycode(kc);             /* Show current definition */
  6332. #endif /* OS2 */
  6333.             flag = 1;                   /* Remember it's a multiline command */
  6334.         } else                          /* Error */
  6335.           return(y);
  6336.     }
  6337.  
  6338.     /* Normal SET KEY <scancode> <value> command... */
  6339.  
  6340. #ifdef OS2
  6341.     if (mskkeys)
  6342.       kc = msktock(kc);
  6343. #endif /* OS2 */
  6344.  
  6345.     if (kc < 0 || kc >= KMSIZE) {
  6346.         printf("?key code must be between 0 and %d\n", KMSIZE - 1);
  6347.         return(-9);
  6348.     }
  6349.     if (kc == escape) {
  6350.         printf("Sorry, %d is the CONNECT-mode escape character\n",kc);
  6351.         return(-9);
  6352.     }
  6353. #ifdef OS2
  6354.     wideresult = -1;
  6355. #endif /* OS2 */
  6356.     if (flag) {
  6357.         cmsavp(psave,PROMPTL);
  6358.         cmsetp(" Enter new definition: ");
  6359.         cmini(ckxech);
  6360.         cmflgs = 0;
  6361.         prompt(NULL);
  6362.     }
  6363.   def_again:
  6364.     if (flag)
  6365.       cmres();
  6366.     if ((y = cmtxt("key definition,\n\
  6367. or Ctrl-C to cancel this command,\n\
  6368. or Enter to restore default definition",
  6369.                    "",&s,NULL)) < 0) {
  6370.         if (flag)                       /* Handle parse errors */
  6371.           goto def_again;
  6372.         else
  6373.           return(y);
  6374.     }
  6375.     s = brstrip(s);
  6376. #ifndef NOKVERBS
  6377.     p = s;                              /* Save this place */
  6378. #endif /* NOKVERBS */
  6379. /*
  6380.   If the definition included any \Kverbs, quote the backslash so the \Kverb
  6381.   will still be in the definition when the key is pressed.  We don't do this
  6382.   in zzstring(), because \Kverbs are valid only in this context and nowhere
  6383.   else.
  6384.  
  6385.   We use this code active for all versions that support SET KEY, even if they
  6386.   don't support \Kverbs, because otherwise \K would behave differently for
  6387.   different versions.
  6388. */
  6389.     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
  6390.         if ((x > 0) &&
  6391.             (s[x] == 'K' || s[x] == 'k')
  6392.             ) {                         /* Have K */
  6393.  
  6394.             if ((x == 1 && s[x-1] == CMDQ) ||
  6395.                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
  6396.                 line[y++] = CMDQ;       /* Make it \\K */
  6397.             }
  6398.             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
  6399.                 line[y-1] = CMDQ;       /* Have \{K */
  6400.                 line[y++] = '{';        /* Make it \\{K */
  6401.             }
  6402.         }
  6403.         line[y] = s[x];
  6404.     }
  6405.     line[y++] = NUL;                    /* Terminate */
  6406.     s = line + y + 1;                   /* Point to after it */
  6407.     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
  6408.     if ((x < (LINBUFSIZ / 2)) ||
  6409.         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
  6410.         printf("?Key definition too long\n");
  6411.         if (flag) cmsetp(psave);
  6412.         return(-9);
  6413.     }
  6414.     s = line + y + 1;                   /* Point to result. */
  6415.  
  6416. #ifndef NOKVERBS
  6417. /*
  6418.   Special case: see if the definition starts with a \Kverb.
  6419.   If it does, point to it with p, otherwise set p to NULL.
  6420. */
  6421.     p = s;
  6422.     if (*p++ == CMDQ) {
  6423.         if (*p == '{') p++;
  6424.         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
  6425.     }
  6426. #endif /* NOKVERBS */
  6427.  
  6428.     if (macrotab[kc]) {                 /* Possibly free old macro from key. */
  6429.         free((char *)macrotab[kc]);
  6430.         macrotab[kc] = NULL;
  6431.     }
  6432.     switch (strlen(s)) {                /* Action depends on length */
  6433.       case 0:                           /* Reset to default binding */
  6434.         keymap[kc] = (KEY) kc;
  6435.         break;
  6436.       case 1:                           /* Single character */
  6437.         keymap[kc] = (CHAR) *s;
  6438.         break;
  6439.       default:                          /* Character string */
  6440. #ifndef NOKVERBS
  6441.         if (p) {
  6442.             y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
  6443.             debug(F101,"set key kverb lookup",0,y); /* exact match required */
  6444.             if (y > -1) {
  6445.                 keymap[kc] = F_KVERB | y;
  6446.                 break;
  6447.             }
  6448.         }
  6449. #endif /* NOKVERBS */
  6450.         keymap[kc] = (KEY) kc;
  6451.         macrotab[kc] = (MACRO) malloc(strlen(s)+1);
  6452.         if (macrotab[kc])
  6453.           strcpy((char *) macrotab[kc], s); /* safe */
  6454.         break;
  6455.     }
  6456.     if (flag) cmsetp(psave);
  6457. #ifdef OS2
  6458.     initvik = 1;                        /* Update VIK table */
  6459. #endif /* OS2 */
  6460.     return(1);
  6461. }
  6462. #endif /* NOSETKEY */
  6463.  
  6464. #ifdef STOPBITS
  6465. struct keytab stoptbl[] = {
  6466.     { "1", 1, 0 },
  6467.     { "2", 2, 0 }
  6468. };
  6469. #endif /* STOPBITS */
  6470.  
  6471. static struct keytab sertbl[] = {
  6472.     { "7E1", 0, 0 },
  6473.     { "7E2", 1, 0 },
  6474.     { "7M1", 2, 0 },
  6475.     { "7M2", 3, 0 },
  6476.     { "7O1", 4, 0 },
  6477.     { "7O2", 5, 0 },
  6478.     { "7S1", 6, 0 },
  6479.     { "7S2", 7, 0 },
  6480. #ifdef HWPARITY
  6481.     { "8E1", 9, 0 },
  6482.     { "8E2", 10, 0 },
  6483. #endif /* HWPARITY */
  6484.     { "8N1", 8, 0 },
  6485. #ifdef HWPARITY
  6486.     { "8N2", 11, 0 },
  6487.     { "8O1", 12, 0 },
  6488.     { "8O2", 13, 0 },
  6489. #endif /* HWPARITY */
  6490.     { "", 0, 0 }
  6491. };
  6492. static int nsertbl = (sizeof(sertbl) / sizeof(struct keytab)) - 1;
  6493.  
  6494. static char * sernam[] = {              /* Keep this in sync with sertbl[] */
  6495.   "7E1", "7E2", "7M1", "7M2", "7O1", "7O2", "7S1", "7S2",
  6496.   "8N1", "8E1", "8E2", "8N2", "8O1", "8O2"
  6497. };
  6498.  
  6499. static struct keytab optstab[] = {      /* SET OPTIONS table */
  6500. #ifndef NOFRILLS
  6501.     { "delete",    XXDEL,   0},            /* DELETE */
  6502. #endif /* NOFRILLS */
  6503.     { "directory", XXDIR,   0},         /* DIRECTORY */
  6504. #ifdef CKPURGE
  6505.     { "purge",     XXPURGE, 0},         /* PURGE */
  6506. #endif /* CKPURGE */
  6507.     { "type",      XXTYP,   0},         /* TYPE */
  6508.     { "", 0, 0}
  6509. };
  6510. static int noptstab =  (sizeof(optstab) / sizeof(struct keytab)) - 1;
  6511.  
  6512. #ifndef NOXFER
  6513. /*
  6514.   PROTOCOL SELECTION.  Kermit is always available.  If CK_XYZ is defined at
  6515.   compile time, then the others become selections also.  In OS/2 and
  6516.   Windows, they are integrated and the various SET commands (e.g. "set file
  6517.   type") affect them as they would Kermit.  In other OS's (UNIX, VMS, etc),
  6518.   they are external protocols which are run via Kermit's REDIRECT mechanism.
  6519.   All we do is collect and verify the filenames and pass them along to the
  6520.   external protocol.
  6521. */
  6522. struct keytab protos[] = {
  6523. #ifdef CK_XYZ
  6524.     "g",          PROTO_G,  CM_INV,
  6525. #endif /* CK_XYZ */
  6526.     "kermit",     PROTO_K,  0,
  6527. #ifdef CK_XYZ
  6528.     "other",      PROTO_O,  0,
  6529.     "x",          PROTO_X,  CM_INV|CM_ABR,
  6530.     "xmodem",     PROTO_X,  0,
  6531.     "xmodem-crc", PROTO_XC, 0,
  6532.     "y",          PROTO_Y,  CM_INV|CM_ABR,
  6533.     "ymodem",     PROTO_Y,  0,
  6534.     "ymodem-g",   PROTO_G,  0,
  6535.     "zmodem",     PROTO_Z,  0
  6536. #endif /* CK_XYZ */
  6537. };
  6538. int nprotos =  (sizeof(protos) / sizeof(struct keytab));
  6539.  
  6540. #define XPCMDLEN 71
  6541.  
  6542. _PROTOTYP(static int protofield, (char *, char *, char *));
  6543. _PROTOTYP(static int setproto, (void));
  6544.  
  6545. static int
  6546. protofield(current, help, px) char * current, * help, * px; {
  6547.  
  6548.     char *s, tmpbuf[XPCMDLEN+1];
  6549.     int x;
  6550.  
  6551.     if (current)                        /* Put braces around default */
  6552.       ckmakmsg(tmpbuf,TMPBUFSIZ,"{",current,"}",NULL);
  6553.     else
  6554.       tmpbuf[0] = NUL;
  6555.  
  6556.     if ((x = cmfld(help, (char *)tmpbuf, &s, xxstring)) < 0)
  6557.       return(x);
  6558.     if ((int)strlen(s) > XPCMDLEN) {
  6559.         printf("?Sorry - maximum length is %d\n", XPCMDLEN);
  6560.         return(-9);
  6561.     } else if (*s) {
  6562.         strcpy(px,s);                   /* safe */
  6563.     } else {
  6564.         px = NULL;
  6565.     }
  6566.     return(x);
  6567. }
  6568.  
  6569. static int
  6570. setproto() {                            /* Select a file transfer protocol */
  6571.     /* char * s = NULL; */
  6572.     int x = 0, y;
  6573.     char s1[XPCMDLEN+1], s2[XPCMDLEN+1], s3[XPCMDLEN+1];
  6574.     char s4[XPCMDLEN+1], s5[XPCMDLEN+1], s6[XPCMDLEN+1], s7[XPCMDLEN+1];
  6575.     char * p1 = s1, * p2 = s2, *p3 = s3;
  6576.     char * p4 = s4, * p5 = s5, *p6 = s6, *p7 = s7;
  6577.  
  6578. #ifdef XYZ_INTERNAL
  6579.     extern int p_avail;
  6580. #else
  6581. #ifndef CK_REDIR
  6582.     x = 1;
  6583. #endif /* CK_REDIR */
  6584. #endif /* XYZ_INTERNAL */
  6585.     s1[0] = NUL;
  6586.     s2[0] = NUL;
  6587.     s3[0] = NUL;
  6588.     s4[0] = NUL;
  6589.     s5[0] = NUL;
  6590.     s6[0] = NUL;
  6591.  
  6592.     if ((y = cmkey(protos,nprotos,"","kermit",xxstring)) < 0)
  6593.       return(y);
  6594.  
  6595.     if (x && y != PROTO_K) {
  6596.         printf(
  6597.            "?Sorry, REDIRECT capability required for external protocols.\n");
  6598.         return(-9);
  6599.     }
  6600.     if ((x = protofield(ptab[y].h_b_init,
  6601.      "Optional command to send to host prior to uploading in binary mode",
  6602.                p1)) < 0) {
  6603.         if (x == -3) {
  6604.             protocol = y;               /* Set protocol but don't change */
  6605.             return(1);                  /* anything else */
  6606.         } else
  6607.           return(x);
  6608.     }
  6609.     if ((x = protofield(ptab[y].h_t_init,
  6610.      "Optional command to send to host prior to uploading in text mode",
  6611.                p2)) < 0) {
  6612.         if (x == -3)
  6613.           goto protoexit;
  6614.         else
  6615.           return(x);
  6616.     }
  6617.  
  6618.     if (y == PROTO_K) {
  6619.         if ((x = protofield(ptab[y].h_x_init,
  6620.                     "Optional command to send to host to start Kermit server",
  6621.                             p3)) < 0) {
  6622.             if (x == -3)
  6623.               goto protoexit;
  6624.             else
  6625.               return(x);
  6626.         }
  6627.     }
  6628.  
  6629.  
  6630. #ifndef XYZ_INTERNAL                    /* If XYZMODEM are external... */
  6631.  
  6632.     if (y != PROTO_K) {
  6633.         if ((x = protofield(ptab[y].p_b_scmd,
  6634.                  "External command to SEND in BINARY mode with this protocol",
  6635.                             p4)) < 0) {
  6636.             if (x == -3)
  6637.               goto protoexit;
  6638.             else
  6639.               return(x);
  6640.         }
  6641.         if ((x = protofield(ptab[y].p_t_scmd,
  6642.                  "External command to SEND in TEXT mode with this protocol",
  6643.                             p5)) < 0) {
  6644.             if (x == -3)
  6645.               goto protoexit;
  6646.             else
  6647.               return(x);
  6648.         }
  6649.         if ((x = protofield(ptab[y].p_b_rcmd,
  6650.                "External command to RECEIVE in BINARY mode with this protocol",
  6651.                             p6)) < 0) {
  6652.             if (x == -3)
  6653.               goto protoexit;
  6654.             else
  6655.               return(x);
  6656.         }
  6657.         if ((x = protofield(ptab[y].p_t_rcmd,
  6658.                  "External command to RECEIVE in TEXT mode with this protocol",
  6659.                             p7)) < 0) {
  6660.             if (x == -3)
  6661.               goto protoexit;
  6662.             else
  6663.               return(x);
  6664.         }
  6665.     }
  6666. #endif /* XYZ_INTERNAL */
  6667.  
  6668.     if ((x = cmcfm()) < 0)              /* Confirm the command */
  6669.       return(x);
  6670.  
  6671. protoexit:                              /* Common exit from this routine */
  6672.  
  6673. #ifdef XYZ_INTERNAL
  6674.     if (!p_avail) {
  6675.         bleep(BP_WARN);
  6676.         printf("\n?X,Y, and Zmodem are unavailable\n");
  6677.         return(success = 0);
  6678.     }
  6679. #endif /* XYZ_INTERNAL */
  6680.  
  6681.     p1 = brstrip(p1);
  6682.     p2 = brstrip(p2);
  6683.     p3 = brstrip(p3);
  6684.     p4 = brstrip(p4);
  6685.     p5 = brstrip(p5);
  6686.     p6 = brstrip(p6);
  6687.     p7 = brstrip(p7);
  6688.     initproto(y,p1,p2,p3,p4,p5,p6,p7);
  6689.     return(success = 1);
  6690. }
  6691.  
  6692. int
  6693. setdest() {
  6694.     int x, y;
  6695.     if ((y = cmkey(desttab,ndests,"","disk",xxstring)) < 0) return(y);
  6696.     if ((x = cmcfm()) < 0) return(x);
  6697.     dest = y;
  6698.     return(1);
  6699. }
  6700. #endif /* NOXFER */
  6701.  
  6702. #ifdef DECNET
  6703. struct keytab dnettab[] = {
  6704. #ifndef OS2ONLY
  6705.     "cterm", NP_CTERM, 0,
  6706. #endif /* OS2ONLY */
  6707.     "lat",   NP_LAT,   0
  6708. };
  6709. int ndnet =  (sizeof(dnettab) / sizeof(struct keytab));
  6710. #endif /* DECNET */
  6711.  
  6712. /*  S E T P R I N T E R  --  SET PRINTER command  */
  6713.  
  6714. #ifdef PRINTSWI
  6715. static struct keytab prntab[] = {       /* SET PRINTER switches */
  6716.     "/bidirectional",    PRN_BID, 0,
  6717. #ifdef OS2
  6718.     "/character-set",    PRN_CS,  CM_ARG,
  6719. #endif /* OS2 */
  6720.     "/command",          PRN_PIP, CM_ARG,
  6721.     "/dos-device",       PRN_DOS, CM_ARG,
  6722.     "/end-of-job-string",PRN_TRM, CM_ARG,
  6723.     "/file",             PRN_FIL, CM_ARG,
  6724. #ifdef BPRINT
  6725.     "/flow-control",     PRN_FLO, CM_ARG,
  6726. #endif /* BPRINT */
  6727.     "/job-header-file",  PRN_SEP, CM_ARG,
  6728. #ifdef OS2
  6729.     "/length",           PRN_LEN, CM_ARG,
  6730. #endif /* OS2 */
  6731.     "/none",             PRN_NON, 0,
  6732. #ifdef OS2
  6733.     "/nopostscript",     PRN_RAW, 0,
  6734.     "/nops",             PRN_RAW, CM_INV,
  6735. #endif /* OS2 */
  6736.     "/output-only",      PRN_OUT, 0,
  6737. #ifdef BPRINT
  6738.     "/parity",           PRN_PAR, CM_ARG,
  6739. #endif /* BPRINT */
  6740.     "/pipe",             PRN_PIP, CM_ARG|CM_INV,
  6741. #ifdef OS2
  6742.     "/postscript",       PRN_PS,  0,
  6743.     "/ps",               PRN_PS,  CM_INV,
  6744. #endif /* OS2 */
  6745.     "/separator",        PRN_SEP, CM_ARG|CM_INV,
  6746. #ifdef BPRINT
  6747.     "/speed",            PRN_SPD, CM_ARG,
  6748. #endif /* BPRINT */
  6749.     "/timeout",          PRN_TMO, CM_ARG,
  6750.     "/terminator",       PRN_TRM, CM_ARG|CM_INV,
  6751. #ifdef OS2
  6752. #ifdef NT
  6753.     "/w",                PRN_WIN, CM_ARG|CM_ABR|CM_INV,
  6754.     "/wi",               PRN_WIN, CM_ARG|CM_ABR|CM_INV,
  6755. #endif /* NT */
  6756.     "/width",            PRN_WID, CM_ARG,
  6757. #endif /* OS2 */
  6758. #ifdef NT
  6759.     "/windows-queue",    PRN_WIN, CM_ARG,
  6760. #endif /* NT */
  6761.     "",                 0,      0
  6762. };
  6763. int nprnswi =  (sizeof(prntab) / sizeof(struct keytab)) - 1;
  6764. #endif /* PRINTSWI */
  6765.  
  6766. static int
  6767. setprinter(xx) int xx; {
  6768.     int x, y;
  6769.     char * s;
  6770.     char * defname = NULL;
  6771. #ifdef OS2
  6772.     extern int prncs;
  6773. #endif /* OS2 */
  6774.  
  6775. #ifdef BPRINT
  6776.     char portbuf[64];
  6777.     long portspeed = 0L;
  6778.     int portparity = 0;
  6779.     int portflow = 0;
  6780. #endif /* BPRINT */
  6781.  
  6782. #ifdef PRINTSWI
  6783.     int c, i, n, wild, confirmed = 0;   /* Workers */
  6784.     int getval = 0;                     /* Whether to get switch value */
  6785.     struct stringint {                  /* Temporary array for switch values */
  6786.         char * sval;
  6787.         int ival;
  6788.     } pv[PRN_MAX+1];
  6789.     struct FDB sw, of, cm;              /* FDBs for each parse function */
  6790.     int haveque = 0;
  6791.     int typeset = 0;
  6792. #endif /* PRINTSWI */
  6793.  
  6794. #ifdef NT
  6795.     struct keytab * printtab = NULL, * _printtab = NULL;
  6796.     int nprint = 0, printdef=0;
  6797. #endif /* NT */
  6798.  
  6799. #ifdef OS2
  6800.     defname = "PRN";                    /* default */
  6801. #else
  6802. #ifdef VMS
  6803.     defname = "LPT:";
  6804. #else
  6805. #ifdef UNIX
  6806.     defname = "|lpr";
  6807. #endif /* UNIX */
  6808. #endif /* VMS */
  6809. #endif /* OS2 */
  6810.  
  6811. #ifdef PRINTSWI
  6812. #ifdef NT
  6813.     haveque = Win32EnumPrt(&printtab,&_printtab,&nprint,&printdef);
  6814.     haveque = haveque && nprint;
  6815. #endif /* NT */
  6816.  
  6817.     for (i = 0; i <= PRN_MAX; i++) {    /* Initialize switch values */
  6818.         pv[i].sval = NULL;              /* to null pointers */
  6819.         pv[i].ival = -1;                /* and -1 int values */
  6820.     }
  6821.     if (xx == XYBDCP) {                 /* SET BPRINTER == /BIDIRECTIONAL */
  6822.         pv[PRN_BID].ival = 1;
  6823.         pv[PRN_OUT].ival = 0;
  6824.     }
  6825.  
  6826.     /* Initialize defaults based upon current printer settings */
  6827.     if (printername) {
  6828.         defname = printername;
  6829.         switch (printertype) {
  6830.           case PRT_WIN: pv[PRN_WIN].ival = 1; break;
  6831.           case PRT_DOS: pv[PRN_DOS].ival = 1; break;
  6832.           case PRT_PIP: pv[PRN_PIP].ival = 1; break;
  6833.           case PRT_FIL: pv[PRN_FIL].ival = 1; break;
  6834.           case PRT_NON: pv[PRN_NON].ival = 1; break;
  6835.         }
  6836.     }
  6837. #ifdef BPRINT
  6838.     /* only set the BIDI flag if we are bidi */
  6839.     if (printbidi)
  6840.         pv[PRN_BID].ival = 1;
  6841.  
  6842.     /* serial port parameters may be set for non-bidi devices */
  6843.     pv[PRN_SPD].ival = pportspeed / 10L;
  6844.     pv[PRN_PAR].ival = pportparity;
  6845.     pv[PRN_FLO].ival = pportflow;
  6846. #endif /* BPRINT */
  6847.     if (printtimo)
  6848.         pv[PRN_TMO].ival = printtimo;
  6849.     if (printterm) {
  6850.         pv[PRN_TRM].ival = 1;
  6851.         makestr(&pv[PRN_TRM].sval,printterm);
  6852.     }
  6853.     if (printsep) {
  6854.         pv[PRN_SEP].ival = 1;
  6855.         makestr(&pv[PRN_SEP].sval,printsep);
  6856.     }
  6857.     if (txt2ps) {
  6858.         pv[PRN_PS].ival = 1;
  6859.         pv[PRN_WID].ival = ps_width;
  6860.         pv[PRN_LEN].ival = ps_length;
  6861.     } else {
  6862.         pv[PRN_RAW].ival = 1;
  6863.     }
  6864.  
  6865.     /* Set up chained parse functions... */
  6866.  
  6867.     cmfdbi(&sw,                         /* First FDB - command switches */
  6868.            _CMKEY,                      /* fcode */
  6869.            "Switch",                    /* hlpmsg */
  6870.            "",                          /* default */
  6871.            "",                          /* addtl string data */
  6872.            nprnswi,                     /* addtl numeric data 1: tbl size */
  6873.            4,                           /* addtl numeric data 2: 4 = cmswi */
  6874.            xxstring,                    /* Processing function */
  6875.            prntab,                      /* Keyword table */
  6876.            &cm                          /* Pointer to next FDB */
  6877.            );
  6878.     cmfdbi(&cm,                         /* Second fdb for confirmation */
  6879.            _CMCFM,                      /* fcode */
  6880.            "",                          /* hlpmsg */
  6881.            "",                          /* default */
  6882.            "",                          /* addtl string data */
  6883.            0,                           /* addtl numeric data 1 */
  6884.            0,                           /* addtl numeric data 2 */
  6885.            NULL,
  6886.            NULL,
  6887.            &of
  6888.            );
  6889.     cmfdbi(&of,                         /* Third FDB for printer name */
  6890.            _CMOFI,                      /* fcode */
  6891.            "Printer or file name",      /* hlpmsg */
  6892.            defname,                     /* default */
  6893.            "",                          /* addtl string data */
  6894.            0,                           /* addtl numeric data 1: tbl size */
  6895.            0,                           /* addtl numeric data 2: 4 = cmswi */
  6896.            xxstring,                    /* Processing function */
  6897.            NULL,                        /* Nothing */
  6898.            NULL
  6899.            );
  6900.  
  6901.     while (1) {                         /* Parse 0 or more switches */
  6902.         x = cmfdb(&sw);                 /* Parse switch or other thing */
  6903.         debug(F101,"setprinter cmfdb","",x);
  6904.         if (x < 0)                      /* Error */
  6905.           goto xsetprn;                 /* or reparse needed */
  6906.         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
  6907.           break;
  6908.         if (cmresult.fdbaddr != &sw)    /* Advanced usage :-) */
  6909.           break;
  6910.         c = cmgbrk();                   /* Get break character */
  6911.         getval = (c == ':' || c == '='); /* to see how they ended the switch */
  6912.         n = cmresult.nresult;           /* Numeric result = switch value */
  6913.         debug(F101,"setprinter switch","",n);
  6914.  
  6915.         switch (n) {                    /* Process the switch */
  6916.           case PRN_PS:                  /* Text to Postscript */
  6917.             pv[PRN_PS].ival = 1;
  6918.             pv[PRN_BID].ival = 0;
  6919.             pv[PRN_OUT].ival = 1;
  6920.             pv[PRN_RAW].ival = 0;
  6921.             break;
  6922.  
  6923.           case PRN_RAW:                 /* Non-Postscript */
  6924.             pv[PRN_PS].ival = 0;
  6925.             pv[PRN_RAW].ival = 1;
  6926.             break;
  6927.  
  6928.           case PRN_BID:                 /* Bidirectional */
  6929.             pv[PRN_BID].ival = 1;
  6930.             pv[PRN_OUT].ival = 0;
  6931.             pv[PRN_PS].ival = 0;
  6932.             pv[PRN_RAW].ival = 1;
  6933.             break;
  6934.  
  6935.           case PRN_OUT:                 /* Output-only */
  6936.             pv[PRN_OUT].ival = 1;
  6937.             pv[PRN_BID].ival = 0;
  6938.             pv[PRN_PS].ival = 0;
  6939.             pv[PRN_RAW].ival = 1;
  6940.             break;
  6941.  
  6942.           case PRN_NON:                 /* NONE */
  6943.             typeset++;
  6944.             pv[n].ival = 1;
  6945.             pv[PRN_SPD].ival = 0;
  6946.             pv[PRN_PAR].ival = 0;
  6947.             pv[PRN_FLO].ival = FLO_KEEP;
  6948.             break;
  6949.  
  6950. #ifdef UNIX
  6951.           case PRN_WIN:
  6952. #endif /* UNIX */
  6953.           case PRN_DOS:                 /* DOS printer name */
  6954.           case PRN_FIL:                 /* Or filename */
  6955.           case PRN_PIP:
  6956.             typeset++;
  6957.             if (pv[n].sval) free(pv[n].sval);
  6958.             pv[n].sval = NULL;
  6959.             pv[PRN_NON].ival = 0;       /* Zero any previous selections */
  6960.             pv[PRN_WIN].ival = 0;
  6961.             pv[PRN_DOS].ival = 0;
  6962.             pv[PRN_FIL].ival = 0;
  6963.             pv[PRN_PIP].ival = 0;
  6964.             pv[n].ival = 1;             /* Flag this one */
  6965.             if (!getval) break;         /* No value wanted */
  6966.  
  6967.             if (n == PRN_FIL) {         /* File, check accessibility */
  6968.                 int wild = 0;
  6969.                 if ((x = cmiofi("Filename","kermit.prn",&s,&wild,xxstring))< 0)
  6970.                   if (x == -9) {
  6971.                       if (zchko(s) < 0) {
  6972.                           printf("Can't create \"%s\"\n",s);
  6973.                           return(x);
  6974.                       }
  6975.                   } else goto xsetprn;
  6976.                 if (iswild(s)) {
  6977.                     printf("?A single file please\n");
  6978.                     return(-9);
  6979.                 }
  6980.                 pv[PRN_SPD].ival = 0;
  6981.                 pv[PRN_PAR].ival = 0;
  6982.                 pv[PRN_FLO].ival = FLO_KEEP;
  6983.             } else if ((x = cmfld(n == PRN_DOS ? /* Value wanted - parse it */
  6984.                            "DOS printer device name" : /* Help message */
  6985.                            (n == PRN_PIP ?
  6986.                            "Program name" :
  6987.                            "Filename"),
  6988.                            n == PRN_DOS ?
  6989.                            "PRN" :      /* Default */
  6990.                            "",
  6991.                            &s,
  6992.                            xxstring
  6993.                            )) < 0)
  6994.               goto xsetprn;
  6995.             s = brstrip(s);             /* Strip enclosing braces */
  6996.             while (*s == SP)            /* Strip leading blanks */
  6997.               s++;
  6998.             if (n == PRN_PIP) {         /* If /PIPE: */
  6999.                 if (*s == '|') {        /* strip any extraneous pipe sign */
  7000.                     s++;
  7001.                     while (*s == SP)
  7002.                       s++;
  7003.                 }
  7004.                 pv[PRN_SPD].ival = 0;
  7005.                 pv[PRN_PAR].ival = 0;
  7006.                 pv[PRN_FLO].ival = FLO_KEEP;
  7007.             }
  7008.             if ((y = strlen(s)) > 0)    /* Anything left? */
  7009.               if (pv[n].sval = (char *) malloc(y+1)) /* Yes, keep it */
  7010.                 strcpy(pv[n].sval,s);   /* safe */
  7011.             break;
  7012. #ifdef NT
  7013.           case PRN_WIN:                 /* Windows queue name */
  7014.             typeset++;
  7015.             if (pv[n].sval) free(pv[n].sval);
  7016.             pv[n].sval = NULL;
  7017.             pv[PRN_NON].ival = 0;
  7018.             pv[PRN_DOS].ival = 0;
  7019.             pv[PRN_FIL].ival = 0;
  7020.             pv[n].ival = 1;
  7021.             pv[PRN_SPD].ival = 0;
  7022.             pv[PRN_PAR].ival = 0;
  7023.             pv[PRN_FLO].ival = FLO_KEEP;
  7024.  
  7025.             if (!getval || !haveque)
  7026.               break;
  7027.             if ((x = cmkey(_printtab,nprint,"Print queue name",
  7028.                            _printtab[printdef].kwd,xxstring)) < 0) {
  7029.                 if (x != -2)
  7030.                   goto xsetprn;
  7031.  
  7032.                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
  7033.                 s = atmbuf;
  7034.                 if ((y = strlen(s)) > 0)
  7035.                   if (pv[n].sval = (char *)malloc(y+1))
  7036.                     strcpy(pv[n].sval,s); /* safe */
  7037.             } else {
  7038.                 if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
  7039.                 for (i = 0; i < nprint; i++) {
  7040.                     if (x == printtab[i].kwval) {
  7041.                         s = printtab[i].kwd;
  7042.                         break;
  7043.                     }
  7044.                 }
  7045.                 if ((y = strlen(s)) > 0)
  7046.                   if (pv[n].sval = (char *)malloc(y+1))
  7047.                     strcpy(pv[n].sval,s); /* safe */
  7048.             }
  7049.             break;
  7050. #endif /* NT */
  7051.  
  7052.           case PRN_SEP:                 /* /JOB-HEADER (separator) */
  7053.             if (pv[n].sval) free(pv[n].sval);
  7054.             pv[n].sval = NULL;
  7055.             pv[n].ival = 1;
  7056.             if (!getval) break;
  7057.             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0)
  7058.               goto xsetprn;
  7059.             if (y) {
  7060.                 printf("?Wildcards not allowed\n");
  7061.                 x = -9;
  7062.                 goto xsetprn;
  7063.             }
  7064.             if ((y = strlen(s)) > 0)
  7065.               if (pv[n].sval = (char *) malloc(y+1))
  7066.                 strcpy(pv[n].sval,s);   /* safe */
  7067.             break;
  7068.  
  7069.           case PRN_TMO:                 /* /TIMEOUT:number */
  7070.             pv[n].ival = 0;
  7071.             if (!getval) break;
  7072.             if ((x = cmnum("Seconds","0",10,&y,xxstring)) < 0)
  7073.               goto xsetprn;
  7074.             if (y > 999) {
  7075.                 printf("?Sorry - 999 is the maximum\n");
  7076.                 x = -9;
  7077.                 goto xsetprn;
  7078.             } else
  7079.               pv[n].ival = y;
  7080.             break;
  7081.  
  7082.           case PRN_TRM:                 /* /END-OF-JOB:string */
  7083.             if (pv[n].sval) free(pv[n].sval);
  7084.             pv[n].sval = NULL;
  7085.             pv[n].ival = 1;
  7086.             if (!getval) break;
  7087.             if ((x = cmfld("String (enclose in braces if it contains spaces)",
  7088.                            "",&s,xxstring)) < 0)
  7089.               goto xsetprn;
  7090.             s = brstrip(s);
  7091.             if ((y = strlen(s)) > 0)
  7092.               if (pv[n].sval = (char *) malloc(y+1))
  7093.                 strcpy(pv[n].sval,s);   /* safe */
  7094.             break;
  7095.  
  7096. #ifdef BPRINT
  7097.           case PRN_FLO:
  7098.             if (!getval) break;
  7099.             if ((x = cmkey(flotab,nflo,
  7100.                               "Serial printer-port flow control",
  7101.                               "rts/cts",xxstring)) < 0)
  7102.               goto xsetprn;
  7103.             pv[n].ival = x;
  7104.             break;
  7105.  
  7106. #ifndef NOLOCAL
  7107.           case PRN_SPD:
  7108.             if (!getval) break;
  7109.  
  7110.             /* TN_COMPORT here too? */
  7111.  
  7112.             if ((x = cmkey(spdtab,      /* Speed (no default) */
  7113.                            nspd,
  7114.                            "Serial printer-port interface speed",
  7115.                            "9600",
  7116.                            xxstring)
  7117.                  ) < 0)
  7118.               goto xsetprn;
  7119.             pv[n].ival = x;
  7120.             break;
  7121. #endif /* NOLOCAL */
  7122.  
  7123.           case PRN_PAR:
  7124.             pv[n].ival = 0;
  7125.             if (!getval) break;
  7126.             if ((x = cmkey(partbl,npar,"Serial printer-port parity",
  7127.                            "none",xxstring)) < 0)
  7128.               goto xsetprn;
  7129.             pv[n].ival = x;
  7130.             break;
  7131. #endif /* BPRINT */
  7132.  
  7133. #ifdef OS2
  7134.           case PRN_LEN:
  7135.             if (!getval) break;
  7136.             if ((x = cmnum("PS page length", "66",10,&y,xxstring)) < 0)
  7137.               goto xsetprn;
  7138.             pv[n].ival = y;
  7139.             break;
  7140.  
  7141.           case PRN_WID:
  7142.             if (!getval) break;
  7143.             if ((x = cmnum("PS page width", "80",10,&y,xxstring)) < 0)
  7144.               goto xsetprn;
  7145.             pv[n].ival = y;
  7146.             break;
  7147.  
  7148.           case PRN_CS:
  7149.               pv[n].ival = 0;
  7150.               if (!getval) break;
  7151.               if ((y = cmkey(
  7152. #ifdef CKOUNI
  7153.                        txrtab,ntxrtab,
  7154. #else /* CKOUNI */
  7155.                        ttcstab,ntermc,
  7156. #endif /* CKOUNI */
  7157.                        "auto-print/printscreen character-set",
  7158.                        "cp437",xxstring)) < 0)
  7159.                   goto xsetprn;
  7160.               pv[n].ival = x;
  7161.               break;
  7162. #endif /* OS2 */
  7163.  
  7164.           default:
  7165.             printf("?Unexpected switch value - %d\n",cmresult.nresult);
  7166.             x = -9;
  7167.             goto xsetprn;
  7168.         }
  7169.     }
  7170.     line[0] = NUL;                      /* Initialize printer name value */
  7171.     switch (cmresult.fcode) {           /* How did we get here? */
  7172.       case _CMOFI:                      /* They typed a filename */
  7173.         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Name */
  7174.         wild = cmresult.nresult;        /* Wild flag */
  7175.         if (!typeset) {                 /* A printer name without a type */
  7176.             pv[PRN_NON].ival = 0;       /* is supposed to be treated as  */
  7177.             pv[PRN_WIN].ival = 0;       /* a DOS or Pipe printer.  We    */
  7178.             pv[PRN_FIL].ival = 0;       /* clear all the flags and let   */
  7179.             pv[PRN_PIP].ival = 0;       /* the code below dope out the   */
  7180.             pv[PRN_DOS].ival = 0;       /* type.                         */
  7181.         }
  7182. #ifdef NT
  7183.         else if (pv[PRN_WIN].ival && lookup(_printtab,line,nprint,&y)) {
  7184.             /* invalid Window Queue name */
  7185.             printf("?invalid Windows Printer Queue name: \"%s\"\r\n",line);
  7186.             x = -9;
  7187.             goto xsetprn;
  7188.         }
  7189. #endif /* NT */
  7190.         if ((x = cmcfm()) < 0)          /* Confirm the command */
  7191.           goto xsetprn;
  7192.         break;
  7193.       case _CMCFM:                      /* They entered the command */
  7194.         if (pv[PRN_DOS].ival > 0)
  7195.           ckstrncpy(line,pv[PRN_DOS].sval ? pv[PRN_DOS].sval : "",LINBUFSIZ);
  7196.         else if (pv[PRN_WIN].ival > 0)
  7197.           ckstrncpy(line,pv[PRN_WIN].sval ? pv[PRN_WIN].sval : "",LINBUFSIZ);
  7198.         else if (pv[PRN_FIL].ival > 0)
  7199.           ckstrncpy(line,pv[PRN_FIL].sval ? pv[PRN_FIL].sval : "",LINBUFSIZ);
  7200.         else if (pv[PRN_PIP].ival > 0)
  7201.           ckstrncpy(line,pv[PRN_PIP].sval ? pv[PRN_PIP].sval : "",LINBUFSIZ);
  7202.         break;
  7203.       default:                          /* By mistake */
  7204.         printf("?Unexpected function code: %d\n",cmresult.fcode);
  7205.         x = -9;
  7206.         goto xsetprn;
  7207.     }
  7208.  
  7209. #else  /* No PRINTSWI */
  7210.  
  7211.     if ((x = cmofi("Printer or file name",defname,&s,xxstring)) < 0)
  7212.       return(x);
  7213.     if (x > 1) {
  7214.         printf("?Directory names not allowed\n");
  7215.         return(-9);
  7216.     }
  7217.     while (*s == SP || *s == HT) s++;   /* Trim leading whitespace */
  7218.     ckstrncpy(line,s,LINBUFSIZ);        /* Make a temporary safe copy */
  7219.     if ((x = cmcfm()) < 0) return(x);   /* Confirm the command */
  7220. #endif /* PRINTSWI */
  7221.  
  7222. #ifdef IKSD
  7223.     if (inserver && (isguest
  7224. #ifndef NOSERVER
  7225.                      || !ENABLED(en_pri)
  7226. #endif /* NOSERVER */
  7227.                      )) {
  7228.         printf("Sorry, printing disabled\r\n");
  7229.         return(success = 0);
  7230.     }
  7231. #endif /* ISKD */
  7232.  
  7233. #ifdef PRINTSWI
  7234. #ifdef BPRINT
  7235.     if (printbidi) {                    /* If bidi printing active */
  7236. #ifndef UNIX
  7237.         bprtstop();                     /* Stop it before proceeding */
  7238. #endif /* UNIX */
  7239.         printbidi = 0;
  7240.     }
  7241.     if (pv[PRN_SPD].ival > 0) {
  7242.         portspeed = (long) pv[PRN_SPD].ival * 10L;
  7243.         if (portspeed == 70L) portspeed = 75L;
  7244.     }
  7245.     if (pv[PRN_PAR].ival > 0)
  7246.         portparity = pv[PRN_PAR].ival;
  7247.     if (pv[PRN_FLO].ival > 0)
  7248.         portflow = pv[PRN_FLO].ival;
  7249. #endif /* BPRINT */
  7250. #endif /* PRINTSWI */
  7251.  
  7252.     s = line;                           /* Printer name, if given */
  7253.  
  7254. #ifdef OS2ORUNIX
  7255. #ifdef PRINTSWI
  7256.     if (pv[PRN_PIP].ival > 0) {         /* /PIPE was given? */
  7257.         printpipe = 1;
  7258.         noprinter = 0;
  7259.         if (*s ==  '|') {               /* It might still have a pipe sign */
  7260.             s++;                        /* if name give later */
  7261.             while (*s == SP)            /* so remove it and spaces */
  7262.               s++;
  7263.         }
  7264.     } else
  7265. #endif /* PRINTSWI */
  7266.       if (*s == '|') {                  /* Or pipe implied by name? */
  7267.           s++;                          /* Point past pipe sign */
  7268.           while (*s == SP)              /* Gobble whitespace */
  7269.             s++;
  7270.           if (*s) {
  7271.               printpipe = 1;
  7272.               noprinter = 0;
  7273.           }
  7274.       } else {
  7275.           printpipe = 0;
  7276.       }
  7277.  
  7278. #ifdef PRINTSWI
  7279. #ifdef BPRINT
  7280.     if (printpipe && pv[PRN_BID].ival > 0) {
  7281.         printf("?Sorry, pipes not allowed for bidirectional printer\n");
  7282.         return(-9);
  7283.     }
  7284. #endif /* BPRINT */
  7285. #endif /* PRINTSWI */
  7286. #endif /* OS2ORUNIX */
  7287.  
  7288. #ifdef OS2
  7289.     if ( pv[PRN_CS].ival > 0 ) 
  7290.         prncs = pv[PRN_CS].ival;
  7291.  
  7292.     if ( pv[PRN_PS].ival > 0 ) {
  7293.         txt2ps = 1;
  7294.         ps_width = pv[PRN_WID].ival <= 0 ? 80 : pv[PRN_WID].ival;
  7295.         ps_length = pv[PRN_LEN].ival <= 0 ? 66 : pv[PRN_LEN].ival;
  7296.     }
  7297. #endif /* OS2 */
  7298.  
  7299.     y = strlen(s);                      /* Length of name of new print file */
  7300.     if (y > 0
  7301. #ifdef OS2
  7302.         && ((y != 3) || (ckstrcmp(s,"PRN",3,0) != 0))
  7303. #endif /* OS2 */
  7304.         ) {
  7305.         if (printername) {              /* Had a print file before? */
  7306.             free(printername);          /* Remove its name */
  7307.             printername = NULL;
  7308.         }
  7309.         printername = (char *) malloc(y + 1); /* Allocate space for it */
  7310.         if (!printername) {
  7311.             printf("?Memory allocation failure\n");
  7312.             return(-9);
  7313.         }
  7314.         strcpy(printername,s);          /* (safe) Copy new name to new space */
  7315.         debug(F110,"printername",printername,0);
  7316.     }
  7317.  
  7318. #ifdef PRINTSWI
  7319.     /* Set printer type from switches that were given explicitly */
  7320.  
  7321.     if (pv[PRN_NON].ival > 0) {         /* No printer */
  7322.         printertype = PRT_NON;
  7323.         noprinter = 1;
  7324.         printpipe = 0;
  7325.     } else if (pv[PRN_FIL].ival > 0) {  /* File */
  7326.         printertype = PRT_FIL;
  7327.         noprinter = 0;
  7328.         printpipe = 0;
  7329.     } else if (pv[PRN_PIP].ival > 0) {  /* Pipe */
  7330.         printertype = PRT_PIP;
  7331.         noprinter = 0;
  7332.         printpipe = 1;
  7333.     } else if (pv[PRN_WIN].ival > 0) {  /* Windows print queue */
  7334.         printertype = PRT_WIN;
  7335.         noprinter = 0;
  7336.         printpipe = 0;
  7337.     } else if (pv[PRN_DOS].ival > 0) {  /* DOS device */
  7338.         printertype = PRT_DOS;
  7339.         noprinter = 0;
  7340.         printpipe = 0;
  7341.     } else if (line[0]) {               /* Name given without switches */
  7342.         noprinter = 0;
  7343.         printertype = printpipe ? PRT_PIP : PRT_DOS;
  7344. #ifdef NT
  7345.         /* was the command SET PRINTER windows-queue ? */
  7346.         y = lookup(_printtab,line,nprint,&x);
  7347.         if (y >= 0) {
  7348.             printertype = PRT_WIN;
  7349.             if (pv[PRN_WIN].sval) free(pv[PRN_WIN].sval);
  7350.             if (printername) {          /* Had a print file before? */
  7351.                 free(printername);      /* Remove its name */
  7352.                 printername = NULL;
  7353.             }
  7354.             pv[PRN_WIN].sval = NULL;
  7355.             pv[PRN_WIN].ival = 1;
  7356.             s = printtab[x].kwd;        /* Get full new name */
  7357.             if ((y = strlen(s)) > 0) {
  7358.                 makestr(&pv[PRN_WIN].sval,s);
  7359.                 makestr(&printername,s);
  7360.                 if (!printername) {
  7361.                     printf("?Memory allocation failure\n");
  7362.                     return(-9);
  7363.                 }
  7364.                 debug(F110,"printername",printername,0);
  7365.             }
  7366.         } else if ( y == -2 ) {
  7367.             /* Ambiguous Print Queue Name */
  7368.             printf("?Ambiguous printer name provided.\n");
  7369.             return(-9);
  7370.         }
  7371. #endif /* NT */
  7372.     }
  7373.  
  7374. #ifdef BPRINT
  7375.     /* Port parameters may be set for non-bidi mode */
  7376.  
  7377.     pportspeed = portspeed;             /* Set parameters */
  7378.     pportparity = portparity;
  7379.     pportflow = portflow;
  7380.  
  7381.     if (pv[PRN_BID].ival > 0) {         /* Bidirectional */
  7382. #ifdef UNIX
  7383.         printbidi = 1;                  /* (just to test parsing...) */
  7384. #else
  7385.         printbidi = bprtstart();        /* Start bidirectional printer */
  7386. #endif /* UNIX */
  7387.         return(success = printbidi);
  7388.     } else
  7389.       printbidi = 0;                    /* Not BPRINTER, unset flag */
  7390. #endif /* BPRINT */
  7391.  
  7392.     if (pv[PRN_TMO].ival > -1) {        /* Take care of timeout */
  7393.         printtimo = pv[PRN_TMO].ival;
  7394.     }
  7395.     if (pv[PRN_TRM].ival > 0) {         /* Termination string */
  7396.         if (printterm) {
  7397.             free(printterm);
  7398.             printterm = NULL;
  7399.         }
  7400.         if (pv[PRN_TRM].sval)
  7401.           makestr(&printterm,pv[PRN_TRM].sval);
  7402.     }
  7403.     if (pv[PRN_SEP].ival > 0) {         /* and separator file */
  7404.         if (printsep) {
  7405.             free(printsep);
  7406.             printsep = NULL;
  7407.         }
  7408.         if (pv[PRN_SEP].sval)
  7409.           makestr(&printsep,pv[PRN_SEP].sval);
  7410.     }
  7411. #endif /* PRINTSWI */
  7412.  
  7413. #ifdef UNIXOROSK
  7414.     if (!printpipe
  7415. #ifdef PRINTSWI
  7416.         && !noprinter
  7417. #endif /* PRINTSWI */
  7418.         ) {                             /* File - check access */
  7419.         if (zchko(s) < 0) {
  7420.             printf("?Access denied - %s\n",s);
  7421.             x = -9;
  7422.             goto xsetprn;
  7423.         }
  7424.     }
  7425. #endif /* UNIXOROSK */
  7426.  
  7427.     x = 1;                              /* Return code */
  7428.  
  7429.   xsetprn:                              /* Common exit */
  7430. #ifdef PRINTSWI
  7431.     for (i = 0; i <= PRN_MAX; i++) {    /* Free malloc'd memory */
  7432.         if (pv[i].sval)
  7433.           free(pv[i].sval);
  7434.     }
  7435. #endif /* PRINTSWI */
  7436.     success = (x > 0) ? 1 : 0;
  7437.     return(x);
  7438. }
  7439.  
  7440. #ifdef ANYSSH
  7441. /* The SET SSH command */
  7442.  
  7443. #define SSH_CMD  1                      /* SET SSH COMMAND */
  7444.  
  7445. #ifdef SSHBUILTIN                       /* Built-in SET SSH options */
  7446. #define SSH_ADD  2                      /* Add */
  7447. #define SSH_AFW  3                      /* Agent-forwarding */
  7448. #define SSH_CHI  4                      /* Check Host IP */
  7449. #define SSH_XFW  5                      /* X11-forwarding */
  7450. #define SSH_DYF  6                      /* Dynamic forwarding */
  7451. #define SSH_GWP  7                      /* Gatewa portgs */
  7452. #define SSH_GSS  8                      /* GSSAPI */
  7453. #define SSH_KBD  9                      /* KBD Interactive Devices */
  7454. #define SSH_K4  10                      /* Kerberos 4 */
  7455. #define SSH_K5  11                      /* Kerberos 5 */
  7456. #define SSH_SHK 12                      /* Strict Host Key Check */
  7457. #define SSH_V1  13                      /* SSH V1 */
  7458. #define SSH_V2  14                      /* SSH V2 */
  7459. #define SSH_PRP 15                      /* Privd port */
  7460. #define SSH_CMP 16                      /* Compression */
  7461. #define SSH_XAL 17                      /* X Auth Location */
  7462. #define SSH_SHH 18                      /* Quiet */
  7463. #define SSH_VER 19                      /* Version */
  7464. #define SSH_VRB 20                      /* Verbosity level */
  7465. #define SSH_IDF 21                      /* Identity File */
  7466. #define SSH_CFG 22                      /* Use OpenSSH Config */
  7467. #endif /* SSHBUILTIN */
  7468.  
  7469. static struct keytab sshtab[] = {       /* SET SSH command table */
  7470. #ifdef SSHBUILTIN
  7471.     { "agent-forwarding",        SSH_AFW,  0 },
  7472.     { "check-host-ip",           SSH_CHI,  0 },
  7473.     { "compression",             SSH_CMP,  0 },
  7474.     { "dynamic-forwarding",      SSH_DYF,  0 },
  7475.     { "gateway-ports",           SSH_GWP,  0 },
  7476.     { "gssapi",                  SSH_GSS,  0 },
  7477.     { "identity-file",           SSH_IDF,  0 },
  7478. #ifdef COMMENT
  7479.     { "kbd-interactive-devices", SSH_KBD,  0 },
  7480. #endif /* COMMENT */
  7481.     { "k4",                      SSH_K4, CM_INV },
  7482.     { "k5",                      SSH_K5, CM_INV },
  7483.     { "kerberos4",               SSH_K4,   0 },
  7484.     { "kerberos5",               SSH_K5,   0 },
  7485.     { "krb4",                    SSH_K4, CM_INV },
  7486.     { "krb5",                    SSH_K5, CM_INV },
  7487.     { "privileged-port",         SSH_PRP,  0 },
  7488.     { "quiet",                   SSH_SHH,  0 },
  7489.     { "strict-host-key-check",   SSH_SHK,  0 },
  7490.     { "use-openssh-config",      SSH_CFG,  0 },
  7491.     { "v1",                      SSH_V1,   0 },
  7492.     { "v2",                      SSH_V2,   0 },
  7493.     { "verbose",                 SSH_VRB,  0 },
  7494.     { "version",                 SSH_VER,  0 },
  7495.     { "x11-forwarding",          SSH_XFW,  0 },
  7496.     { "xauth-location",          SSH_XAL,  0 },
  7497. #else
  7498. #ifdef SSHCMD
  7499.     { "command",                 SSH_CMD,  0 },
  7500. #endif /* SSHCMD */
  7501. #endif /* SSHBUILTIN */
  7502.     { "", 0, 0 }
  7503. };
  7504. static int nsshtab = (sizeof(sshtab) / sizeof(struct keytab)) - 1;
  7505.  
  7506. #ifdef SSHBUILTIN
  7507. static struct keytab sshver[] = {       /* SET SSH VERSION command table */
  7508.     { "1",          1,  0 },
  7509.     { "2",          2,  0 },
  7510.     { "automatic",  0,  0 }
  7511. };
  7512.  
  7513. #define SSHA_CRS   1
  7514. #define SSHA_DSA   2
  7515. #define SSHA_GSS   3
  7516. #define SSHA_HOS   4
  7517. #define SSHA_KBD   5
  7518. #define SSHA_K4    6
  7519. #define SSHA_K5    7
  7520. #define SSHA_PSW   8
  7521. #define SSHA_PK    9
  7522. #define SSHA_SKE  10
  7523. #define SSHA_TIS  11
  7524. #define SSHA_EXT  12
  7525. #define SSHA_SRP  13
  7526.  
  7527. static struct keytab ssh2aut[] = {      /* SET SSH V2 AUTH command table */
  7528.     { "external-keyx",      SSHA_EXT, 0 },
  7529.     { "gssapi",             SSHA_GSS, 0 },
  7530.     { "hostbased",          SSHA_HOS, 0 },
  7531.     { "keyboard-interactive",  SSHA_KBD, 0 },
  7532.     { "password",           SSHA_PSW, 0 },
  7533.     { "publickey",          SSHA_PK,  0 },
  7534.     { "srp-gex-sha1",       SSHA_SRP, 0 },
  7535.     { "", 0, 0 }
  7536. };
  7537. static int nssh2aut = (sizeof(ssh2aut) / sizeof(struct keytab)) - 1;
  7538.  
  7539. #define SSHF_LCL   1
  7540. #define SSHF_RMT   2
  7541.  
  7542. static struct keytab addfwd[] = {       /* SET SSH ADD command table */
  7543.     { "local-port-forward",  SSHF_LCL, 0 },
  7544.     { "remote-port-forward", SSHF_RMT, 0 },
  7545.     { "", 0, 0 }
  7546. };
  7547. static int naddfwd = (sizeof(addfwd) / sizeof(struct keytab)) - 1;
  7548.  
  7549. #define SSH1_CIF   1
  7550. #define SSH1_GNH   2
  7551. #define SSH1_UNH   3
  7552. #define SSH1_K54   4
  7553.  
  7554. #define SSH2_CIF   1
  7555. #define SSH2_GNH   2
  7556. #define SSH2_UNH   3
  7557. #define SSH2_ARK   4
  7558. #define SSH2_HKA   5
  7559. #define SSH2_MAC   6
  7560. #define SSH2_AUT   7
  7561.  
  7562. static struct keytab sshv1tab[] = {     /* SET SSH V1 command table */
  7563.     { "cipher",                  SSH1_CIF, 0 },
  7564.     { "global-known-hosts-file", SSH1_GNH, 0 },
  7565.     { "k5-reuse-k4-messages",    SSH1_K54, CM_INV },
  7566.     { "user-known-hosts-file",   SSH1_UNH, 0 },
  7567.     { "", 0, 0 }
  7568. };
  7569. static int nsshv1tab = (sizeof(sshv1tab) / sizeof(struct keytab)) - 1;
  7570.  
  7571. static struct keytab sshv2tab[] = {     /* SET SSH V2 command table */
  7572.     { "authentication",          SSH2_AUT, 0 },
  7573.     { "auto-rekey",              SSH2_ARK, CM_INV },
  7574.     { "ciphers",                 SSH2_CIF, 0 },
  7575.     { "global-known-hosts-file", SSH2_GNH, 0 },
  7576.     { "hostkey-algorithms",      SSH2_HKA, 0 },
  7577.     { "macs",                    SSH2_MAC, 0 },
  7578.     { "user-known-hosts-file",   SSH2_UNH, 0 },
  7579.     { "", 0, 0 }
  7580. };
  7581. static int nsshv2tab = (sizeof(sshv2tab) / sizeof(struct keytab)) - 1;
  7582.  
  7583. #define SSHC_3DES 1                     /* 3DES */
  7584. #define SSHC_3CBC 2                     /* 3DES-CBC */
  7585. #define SSHC_A128 3                     /* AES128-CBC */
  7586. #define SSHC_A192 4                     /* AES192-CBC */
  7587. #define SSHC_A256 5                     /* AES256-CBC */
  7588. #define SSHC_ARC4 6                     /* ARCFOUR */
  7589. #define SSHC_FISH 7                     /* BLOWFISH */
  7590. #define SSHC_BCBC 9                     /* BLOWFISH-CBC */
  7591. #define SSHC_C128 8                     /* CAST128-CBC */
  7592. #define SSHC_1DES 10                    /* DES */
  7593.  
  7594. static struct keytab ssh1ciphers[] = {
  7595.     { "3des",         SSHC_3DES, 0 },
  7596.     { "blowfish",     SSHC_FISH, 0 },
  7597.     { "des",          SSHC_1DES, 0 },
  7598.     { "", 0, 0 }
  7599. };
  7600. static int nssh1ciphers = (sizeof(ssh1ciphers) / sizeof(struct keytab)) - 1;
  7601.  
  7602. static struct keytab ssh2ciphers[] = {  /* SET SSH V2 CIPHERS command table */
  7603.     { "3des-cbc",        SSHC_3DES, 0 },
  7604.     { "aes128-cbc",      SSHC_A128, 0 },
  7605.     { "aes192-cbc",      SSHC_A192, 0 },
  7606.     { "aes256-cbc",      SSHC_A256, 0 },
  7607.     { "arcfour",         SSHC_ARC4, 0 },
  7608.     { "blowfish-cbc",    SSHC_FISH, 0 },
  7609.     { "cast128-cbc",     SSHC_C128, 0 },
  7610.     { "rijndael128-cbc", SSHC_A128, 0 },
  7611.     { "rijndael192-cbc", SSHC_A192, 0 },
  7612.     { "rijndael256-cbc", SSHC_A256, 0 },
  7613.     { "", 0, 0 }
  7614. };
  7615. static int nssh2ciphers = (sizeof(ssh2ciphers) / sizeof(struct keytab)) - 1;
  7616.  
  7617. #define SSHM_SHA        1               /* HMAC-SHA1 */
  7618. #define SSHM_SHA_96     2               /* HMAC-SHA1-96 */
  7619. #define SSHM_MD5        3               /* HMAC-MD5 */
  7620. #define SSHM_MD5_96     4               /* HMAC-MD5-96 */
  7621. #define SSHM_RIPE       5               /* HMAC-RIPEMD160 */
  7622.  
  7623. static struct keytab ssh2macs[] = {     /* SET SSH V2 MACS command table */
  7624.     { "hmac-md5",       SSHM_MD5,    0 },
  7625.     { "hmac-md5-96",    SSHM_MD5_96, 0 },
  7626.     { "hmac-ripemd160", SSHM_RIPE,   0 },
  7627.     { "hmac-sha1",      SSHM_SHA,    0 },
  7628.     { "hmac-sha1-96",   SSHM_SHA_96, 0 },
  7629.     { "", 0, 0 }
  7630. };
  7631. static int nssh2macs = (sizeof(ssh2macs) / sizeof(struct keytab)) - 1;
  7632.  
  7633. static struct keytab tgtpass[] = {
  7634.     { "tgt-passing", 1, 0, },
  7635.     { "", 0, 0 }
  7636. };
  7637. static int ntgtpass = (sizeof(tgtpass) / sizeof(struct keytab)) - 1;
  7638.  
  7639. static struct keytab gssapitab[] = {
  7640.     { "delegate-credentials", 1, 0, },
  7641.     { "key-exchange",         2, CM_INV, },
  7642.     { "", 0, 0 }
  7643. };
  7644. static int ngssapitab = (sizeof(gssapitab) / sizeof(struct keytab)) - 1;
  7645.  
  7646. #define HKA_RSA 1
  7647. #define HKA_DSS 2
  7648.  
  7649. static struct keytab hkatab[] = {
  7650.     { "ssh-dss", HKA_DSS, 0, },
  7651.     { "ssh-rsa", HKA_RSA, 0, },
  7652.     { "", 0, 0 }
  7653. };
  7654. static int nhkatab = (sizeof(hkatab) / sizeof(struct keytab)) - 1;
  7655.  
  7656. int                                     /* SET SSH variables */
  7657.   ssh_afw = 0,                          /* agent forwarding */
  7658.   ssh_xfw = 0,                          /* x11 forwarding   */
  7659.   ssh_prp = SET_OFF,                    /* privileged ports */
  7660.   ssh_cmp = 1,                          /* compression */
  7661.   ssh_shh = 0,                          /* quiet       */
  7662.   ssh_ver = 0,                          /* protocol version (auto,1,2) */
  7663.   ssh_vrb = 2,                          /* Report errors */
  7664.   ssh_chkip = 0,                        /* SSH Check Host IP flag */
  7665.   ssh_gwp = 0,                          /* gateway ports */
  7666.   ssh_dyf = 0,                          /* dynamic forwarding */
  7667.   ssh_gsd = 0,                          /* gssapi delegate credentials */
  7668.   ssh_k4tgt = 0,                        /* k4 tgt passing */
  7669.   ssh_k5tgt = 0,                        /* k5 tgt passing */
  7670.   ssh_shk = 2,                          /* Strict host key (no, yes, ask) */
  7671.   ssh2_ark = 0,                         /* Auto re-key */
  7672.   ssh_cas = 0,                          /* command as subsys */
  7673.   ssh_cfg = 0,                          /* use OpenSSH config? */
  7674.   ssh_gkx = 1,                          /* gssapi key exchange */
  7675.   ssh_k5_is_k4 = 1,                     /* some SSH v1 use same codes */
  7676.   ssh_dummy = 0;                        /* bottom of list */
  7677.  
  7678. char                                    /* The following are to be malloc'd */
  7679.   * ssh1_cif = NULL,                    /* v1 cipher */
  7680.   * ssh2_cif = NULL,                    /* v2 cipher list */
  7681.   * ssh2_mac = NULL,                    /* v2 mac list */
  7682.   * ssh2_auth = NULL,                   /* v2 authentication list */
  7683.   * ssh_hst = NULL,                     /* hostname */
  7684.   * ssh_prt = NULL,                     /* port/service */
  7685.   * ssh_cmd = NULL,                     /* command to execute */
  7686.   * ssh_xal = NULL,                     /* xauth-location */
  7687.   * ssh1_gnh = NULL,                    /* v1 global known hosts file */
  7688.   * ssh1_unh = NULL,                    /* v1 user known hosts file */
  7689.   * ssh2_gnh = NULL,                    /* v2 global known hosts file */
  7690.   * ssh2_unh = NULL,                    /* v2 user known hosts file */
  7691.   * ssh2_hka = NULL,                    /* Host Key Algorithms */
  7692.   * xxx_dummy = NULL;
  7693.  
  7694. char * ssh_idf[32] = {                  /* Identity file list */
  7695.   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
  7696.   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
  7697.   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
  7698.   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
  7699. };
  7700. char * ssh_tmp[32] = {                  /* Temp identity file list */
  7701.   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
  7702.   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
  7703.   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
  7704.   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
  7705. };
  7706. int ssh_idf_n = 0;
  7707.  
  7708. extern int    ssh_pf_lcl_n,
  7709.               ssh_pf_rmt_n;
  7710. extern struct ssh_pf ssh_pf_lcl[32];    /* Port forwarding structs */
  7711. extern struct ssh_pf ssh_pf_rmt[32];    /* (declared in ckuusr.c) */
  7712. #endif /* SSHBUILTIN */
  7713.  
  7714. VOID
  7715. shossh() {
  7716. #ifdef SSHBUILTIN
  7717.     int i, n = 0;                       /* ADD askmore()! */
  7718.  
  7719.     printf("\nSSH is built in:\n\n");
  7720.  
  7721.     printf(" ssh host:                        %s\n",showstring(ssh_hst));
  7722.     printf(" ssh port:                        %s\n",showstring(ssh_prt));
  7723.     printf(" ssh command:                     %s\n",showstring(ssh_cmd));
  7724.     printf(" ssh agent-forwarding:            %s\n",showoff(ssh_afw));
  7725.     printf(" ssh check-host-ip:               %s\n",showoff(ssh_chkip));
  7726.     printf(" ssh compression:                 %s\n",showoff(ssh_cmp));
  7727.     printf(" ssh dynamic-forwarding:          %s\n",showoff(ssh_dyf));
  7728.     if (ssh_pf_lcl[0].p1 && ssh_pf_lcl[0].host && ssh_pf_lcl[0].p2) {
  7729.       printf(" ssh forward-local-port:          %d %s %d\n",
  7730.              ssh_pf_lcl[0].p1, ssh_pf_lcl[0].host, ssh_pf_lcl[0].p2);
  7731.       for ( n=1;n<ssh_pf_lcl_n;n++ )
  7732.         printf("                       :          %d %s %d\n",
  7733.                ssh_pf_lcl[n].p1, ssh_pf_lcl[n].host, ssh_pf_lcl[n].p2);
  7734.     } else
  7735.       printf(" ssh forward-local-port:         (none)\n");
  7736.     if (ssh_pf_rmt[0].p1 && ssh_pf_rmt[0].host && ssh_pf_rmt[0].p2) {
  7737.       printf(" ssh forward-remote-port:         %d %s %d\n",
  7738.              ssh_pf_rmt[0].p1, ssh_pf_rmt[0].host, ssh_pf_rmt[0].p2);
  7739.       for ( n=1;n<ssh_pf_rmt_n;n++ )
  7740.         printf("                        :         %d %s %d\n",
  7741.                ssh_pf_rmt[n].p1, ssh_pf_rmt[n].host, ssh_pf_rmt[n].p2);
  7742.     } else
  7743.       printf(" ssh forward-remote-port:        (none)\n");
  7744.     printf(" ssh gateway-ports:               %s\n",showoff(ssh_gwp));
  7745.     printf(" ssh gssapi delegate-credentials: %s\n",showoff(ssh_gsd));
  7746.     printf(" ssh gssapi key-exchange        : %s\n",showoff(ssh_gkx));
  7747.     printf(" ssh identity-file:               %d\n",ssh_idf_n);
  7748.     for (i = 0; i < ssh_idf_n; i++)
  7749.       printf("  %2d. %s\n",i+1,showstring(ssh_idf[i]));
  7750.     printf(" ssh k4 tgt-passing:              %s\n",showoff(ssh_k4tgt));
  7751.     printf(" ssh k5 tgt-passing:              %s\n",showoff(ssh_k5tgt));
  7752.  
  7753.     printf(" ssh privileged-port:             %s\n",showooa(ssh_prp));
  7754.     printf(" ssh quiet:                       %s\n",showoff(ssh_shh));
  7755.     printf(" ssh strict-host-key-check:       %d\n",ssh_shk);
  7756.     printf(" ssh use-openssh-config:          %s\n",showoff(ssh_cfg));
  7757.     printf(" ssh verbose:                     %d\n",ssh_vrb);
  7758.     printf(" ssh version:                     %s\n",
  7759.            ssh_ver ? ckitoa(ssh_ver) : "automatic"
  7760.            );
  7761.     printf(" ssh x11-forwarding:              %s\n",showooa(ssh_xfw));
  7762.     printf(" ssh xauth-location:              %s\n",showstring(ssh_xal));
  7763.     printf("\n");
  7764.     printf(" ssh v1 cipher:                   %s\n",showstring(ssh1_cif));
  7765.     printf(" ssh v1 global-known-hosts-file:  %s\n",showstring(ssh1_gnh));
  7766.     printf(" ssh v1 user-known-hosts-file:    %s\n",showstring(ssh1_unh));
  7767.     printf("\n");
  7768.     printf(" ssh v2 authentication:           %s\n",showstring(ssh2_auth));
  7769.     printf(" ssh v2 auto-rekey:               %s\n",showoff(ssh2_ark));
  7770.     printf(" ssh v2 ciphers:                  %s\n",showstring(ssh2_cif));
  7771.     printf(" ssh v2 command-as-subsystem:     %s\n",showoff(ssh_cas));
  7772.     printf(" ssh v2 global-known-hosts-file:  %s\n",showstring(ssh2_gnh));
  7773.     printf(" ssh v2 hostkey-algorithms:       %s\n",showstring(ssh2_hka));
  7774.     printf(" ssh v2 mac:                      %s\n",showstring(ssh2_mac));
  7775.     printf(" ssh v2 user-known-hosts-file:    %s\n",showstring(ssh2_unh));
  7776. #else
  7777. #ifdef SSHCMD
  7778.     extern char * sshcmd, * defsshcmd;
  7779.     char * s;
  7780.     s = sshcmd ? sshcmd : defsshcmd;
  7781.     printf("\n SSH is external.\n\n");
  7782.     printf(" ssh command: %s\n",showstring(s));
  7783. #endif /* SSHCMD */
  7784. #endif /* SSHBUILTIN */
  7785.     printf("\n");
  7786. }
  7787.  
  7788. static int
  7789. dosetssh() {
  7790. #ifdef SSHCMD
  7791.     extern char * sshcmd;
  7792. #endif /* SSHCMD */
  7793. #ifdef SSHBUILTIN
  7794. #ifndef SSHTEST
  7795.     extern int sl_ssh_xfw_saved, sl_ssh_ver_saved;
  7796. #endif /* SSHTEST */
  7797. #endif /* SSHBUILTIN */
  7798.     int cx, x, y, z;
  7799.     char * s;
  7800.  
  7801.     if ((cx = cmkey(sshtab,nsshtab,"","command", xxstring)) < 0)
  7802.       return(cx);
  7803.     switch (cx) {
  7804. #ifdef SSHCMD
  7805.       case SSH_CMD:                     /* Command */
  7806.         if ((x = cmtxt("Command to start ssh","ssh -e none",
  7807.                        &s,xxstring)) < 0)
  7808.           return(x);
  7809.         makestr(&sshcmd,s);
  7810.         return(success = 1);
  7811. #endif /* SSHCMD */
  7812.  
  7813. #ifdef SSHBUILTIN
  7814.       case SSH_AFW:                     /* Agent-forwarding */
  7815.         return(success = seton(&ssh_afw));
  7816.  
  7817.       case SSH_CHI:                     /* Check Host IP */
  7818.         return(success = seton(&ssh_chkip));
  7819.         break;
  7820.  
  7821.       case SSH_CMP:                     /* Compression */
  7822.         return(success = seton(&ssh_cmp));
  7823.  
  7824.       case SSH_DYF:                     /* Dynamic Forwarding */
  7825.         return(success = seton(&ssh_dyf));
  7826.  
  7827.       case SSH_GWP:                     /* Gateway ports */
  7828.         return(success = seton(&ssh_gwp));
  7829.  
  7830.       case SSH_GSS:                     /* GSSAPI */
  7831.         if ((y = cmkey(gssapitab,ngssapitab,"","", xxstring)) < 0)
  7832.           return(y);
  7833.         switch (y) {
  7834.           case 1:                       /* Delegate credentials */
  7835.             return(success = seton(&ssh_gsd));
  7836.           case 2:                       /* key-exchange */
  7837.             return(success = seton(&ssh_gkx));
  7838.         }
  7839.         if ((x = cmcfm()) < 0)
  7840.           return(x);
  7841.         return(success = 0);
  7842.  
  7843. #ifdef COMMENT
  7844.       case SSH_KBD:                     /* Kbd Interactive Devices */
  7845.         if ((x = cmcfm()) < 0)
  7846.           return(x);
  7847.         /* TO BE FILLED IN */
  7848.         return(-2);
  7849. #endif /* COMMENT */
  7850.  
  7851.       case SSH_K4:                      /* Kerberos IV */
  7852.       case SSH_K5:                      /* Kerberos V */
  7853.         if ((y = cmkey(tgtpass,1,"","tgt-passing", xxstring)) < 0)
  7854.           return(y);
  7855.         switch (y) {
  7856.           case 1:
  7857.             return(success = (cx == SSH_K4) ?
  7858.                    seton(&ssh_k4tgt) : seton(&ssh_k5tgt));
  7859.         }
  7860.         if ((x = cmcfm()) < 0)
  7861.           return(x);
  7862.         return(success = 0);
  7863.  
  7864.       case SSH_PRP:                     /* Privd port */
  7865.         return(success = seton(&ssh_prp));
  7866.  
  7867.       case SSH_SHH:                     /* Quiet */
  7868.         return(success = seton(&ssh_shh));
  7869.  
  7870.       case SSH_SHK:                     /* Strict Host Key Check */
  7871.         if ((y = cmkey(ooktab,3,"","", xxstring)) < 0)
  7872.           return(y);
  7873.         if ((x = cmcfm()) < 0)
  7874.           return(x);
  7875.         ssh_shk = y;
  7876.         return(success = 1);
  7877.  
  7878.       case SSH_V1:                      /* SSH V1 */
  7879.         if ((y = cmkey(sshv1tab,nsshv1tab,"","", xxstring)) < 0)
  7880.           return(y);
  7881.         switch (y) {
  7882.           case SSH1_K54:
  7883.             return(success = seton(&ssh_k5_is_k4));
  7884.           case SSH1_CIF:                /* Not a list */
  7885.             if ((y = cmkey(ssh1ciphers,nssh1ciphers,"","", xxstring)) < 0)
  7886.               if (y != -3)
  7887.                 return(y);
  7888.             if ((x = cmcfm()) < 0) return(x);
  7889.             if (y == -3) {
  7890.                 makestr(&ssh1_cif,NULL);
  7891.             } else {
  7892.                 for (x = 0; x < nssh1ciphers; x++)
  7893.                   if (ssh1ciphers[x].kwval == y)
  7894.                     break;
  7895.                 makestr(&ssh1_cif,ssh1ciphers[x].kwd);
  7896.             }
  7897.             return(1);
  7898.           case SSH1_GNH:
  7899.           case SSH1_UNH:
  7900.             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
  7901.                 if (x != -3)
  7902.                   return(x);
  7903.             } else {
  7904.                 ckstrncpy(line,s,LINBUFSIZ);
  7905.                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
  7906.                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
  7907.             }
  7908.             s = (x == -3) ? NULL : line;
  7909.             if ((x = cmcfm()) < 0)
  7910.               return(x);
  7911.             switch (y) {
  7912.               case SSH1_GNH: makestr(&ssh1_gnh,s); break;
  7913.               case SSH1_UNH: makestr(&ssh1_unh,s); break;
  7914.             }
  7915.             return(1);
  7916.         }
  7917.  
  7918.       case SSH_V2:                      /* SSH V2 */
  7919.         if ((y = cmkey(sshv2tab,nsshv2tab,"","", xxstring)) < 0)
  7920.           return(y);
  7921.         switch (y) {
  7922.           case SSH2_ARK:
  7923.             return(success = seton(&ssh2_ark));
  7924.         case SSH2_AUT: {                        /* Authentication */
  7925. #define TMPCNT 12
  7926.             int i, j, tmp[TMPCNT];
  7927.             for (i = 0; i < TMPCNT; i++)
  7928.               tmp[i] = 0;
  7929.             for (i = 0; i < TMPCNT; i++) {
  7930.                 if ((y = cmkey(ssh2aut,nssh2aut,
  7931.                                "Authentication method","",xxstring)) < 0) {
  7932.                     if (y == -3)
  7933.                       break;
  7934.                     return(y);
  7935.                 }
  7936.                 for (j = 0; j < i; j++) {
  7937.                     if (tmp[j] == y) {
  7938.                         printf("\r\n?Choice has already been used.\r\n");
  7939.                         return(-9);
  7940.                     }
  7941.                 }
  7942.                 tmp[i] = y;
  7943.             }
  7944.             if ((z = cmcfm()) < 0)
  7945.               return(z);
  7946.  
  7947.             if (ssh2_auth) {
  7948.                 free(ssh2_auth);
  7949.                 ssh2_auth = NULL;
  7950.             }
  7951.             if (i > 0) {
  7952.                 int len = 0;
  7953.                 for (j = 0; j < i; j++) {
  7954.                     for (x = 0; x < nssh2aut; x++)
  7955.                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
  7956.                         break;
  7957.                     len += strlen(ssh2aut[x].kwd) + 1;
  7958.                 }
  7959.                 ssh2_auth = malloc(len);
  7960.                 ssh2_auth[0] = '\0';
  7961.                 for (j = 0; j < i; j++) {
  7962.                     for (x = 0; x < nssh2aut; x++)
  7963.                       if (ssh2aut[x].kwval == tmp[j] && !ssh2aut[x].flgs)
  7964.                         break;
  7965.                     ckstrncat(ssh2_auth,ssh2aut[x].kwd,len);
  7966.                     if (j < i - 1)
  7967.                       ckstrncat(ssh2_auth,",",len);
  7968.                 }
  7969.             }
  7970.             return(success = 1);
  7971. #undef TMPCNT
  7972.           }
  7973.         case SSH2_CIF: {
  7974. #define TMPCNT 12
  7975.             int i, j, tmp[TMPCNT];
  7976.             for (i = 0; i < TMPCNT; i++)
  7977.               tmp[i] = 0;
  7978.  
  7979.             for (i = 0; i < TMPCNT; i++) {
  7980.                 if ((y = cmkey(ssh2ciphers,nssh2ciphers,
  7981.                                "","", xxstring)) < 0) {
  7982.                     if (y == -3)
  7983.                       break;
  7984.                     return(y);
  7985.                 }
  7986.                 for (j = 0; j < i; j++) {
  7987.                     if (tmp[j] == y) {
  7988.                         printf("\r\n?Choice has already been used.\r\n");
  7989.                         return(-9);
  7990.                     }
  7991.                 }
  7992.                 tmp[i] = y;
  7993.             }
  7994.             if ((z = cmcfm()) < 0)
  7995.               return(z);
  7996.  
  7997.             if (ssh2_cif) {
  7998.                 free(ssh2_cif);
  7999.                 ssh2_cif = NULL;
  8000.             }
  8001.             if (i > 0) {
  8002.                 int len = 0;
  8003.                 for (j=0; j < i; j++) {
  8004.                     for (x = 0; x < nssh2ciphers; x++)
  8005.                       if (ssh2ciphers[x].kwval == tmp[j] &&
  8006.                           !ssh2ciphers[x].flgs)
  8007.                         break;
  8008.                     len += strlen(ssh2ciphers[x].kwd) + 1;
  8009.                 }
  8010.                 ssh2_cif = malloc(len);
  8011.                 ssh2_cif[0] = '\0';
  8012.                 for (j = 0; j < i; j++) {
  8013.                   for (x = 0; x < nssh2ciphers; x++)
  8014.                     if (ssh2ciphers[x].kwval == tmp[j] && !ssh2ciphers[x].flgs)
  8015.                       break;
  8016.                     ckstrncat(ssh2_cif,ssh2ciphers[x].kwd,len);
  8017.                     if (j < i - 1)
  8018.                       ckstrncat(ssh2_cif,",",len);
  8019.                 }
  8020.             }
  8021.             return(success = 1);
  8022. #undef TMPCNT
  8023.         }
  8024.         case SSH2_MAC: {
  8025. #define TMPCNT 12
  8026.             int i, j, tmp[TMPCNT];
  8027.             for (i = 0; i < TMPCNT; i++)
  8028.               tmp[i] = 0;
  8029.  
  8030.             for (i = 0; i < TMPCNT; i++) {
  8031.                 if ((y = cmkey(ssh2macs,nssh2macs,"","", xxstring)) < 0) {
  8032.                     if (y == -3)
  8033.                       break;
  8034.                     return(y);
  8035.                 }
  8036.                 for (j = 0; j < i; j++) {
  8037.                     if (tmp[j] == y) {
  8038.                         printf("\r\n?Choice has already been used.\r\n");
  8039.                         return(-9);
  8040.                     }
  8041.                 }
  8042.                 tmp[i] = y;
  8043.             }
  8044.             if ((z = cmcfm()) < 0)
  8045.                 return(z);
  8046.  
  8047.             if (ssh2_mac) {
  8048.                 free(ssh2_mac);
  8049.                 ssh2_mac = NULL;
  8050.             }
  8051.             if (i > 0) {
  8052.                 int len = 0;
  8053.                 for (j = 0; j < i; j++) {
  8054.                     for (x = 0; x < nssh2macs; x++)
  8055.                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
  8056.                         break;
  8057.                     len += strlen(ssh2macs[x].kwd) + 1;
  8058.                 }
  8059.                 ssh2_mac = malloc(len);
  8060.                 ssh2_mac[0] = '\0';
  8061.                 for (j=0; j < i; j++) {
  8062.                     for (x = 0; x < nssh2macs; x++)
  8063.                       if (ssh2macs[x].kwval == tmp[j] && !ssh2macs[x].flgs)
  8064.                         break;
  8065.                     ckstrncat(ssh2_mac,ssh2macs[x].kwd,len);
  8066.                     if (j < i - 1)
  8067.                       ckstrncat(ssh2_mac,",",len);
  8068.                 }
  8069.             }
  8070.             return(success = 1);
  8071. #undef TMPCNT
  8072.           }
  8073.           case SSH2_HKA: {
  8074. #define TMPCNT 12
  8075.             int i, j, tmp[TMPCNT];
  8076.             for (i = 0; i < TMPCNT; i++)
  8077.               tmp[i] = 0;
  8078.  
  8079.             for (i = 0; i < TMPCNT; i++) {
  8080.                 if ((y = cmkey(hkatab,nhkatab,
  8081.                                "","", xxstring)) < 0) {
  8082.                     if (y == -3)
  8083.                       break;
  8084.                     return(y);
  8085.                 }
  8086.                 for (j = 0; j < i; j++) {
  8087.                     if (tmp[j] == y) {
  8088.                         printf("\r\n?Choice has already been used.\r\n");
  8089.                         return(-9);
  8090.                     }
  8091.                 }
  8092.                 tmp[i] = y;
  8093.             }
  8094.             if ((z = cmcfm()) < 0)
  8095.               return(z);
  8096.  
  8097.             if (ssh2_hka) {
  8098.                 free(ssh2_hka);
  8099.                 ssh2_hka = NULL;
  8100.             }
  8101.             if (i > 0) {
  8102.                 int len = 0;
  8103.                 for (j=0; j < i; j++) {
  8104.                     for (x = 0; x < nhkatab; x++)
  8105.                       if (hkatab[x].kwval == tmp[j] &&
  8106.                           !hkatab[x].flgs)
  8107.                         break;
  8108.                     len += strlen(hkatab[x].kwd) + 1;
  8109.                 }
  8110.                 ssh2_hka = malloc(len);
  8111.                 ssh2_hka[0] = '\0';
  8112.                 for (j = 0; j < i; j++) {
  8113.                   for (x = 0; x < nhkatab; x++)
  8114.                     if (hkatab[x].kwval == tmp[j] && !hkatab[x].flgs)
  8115.                       break;
  8116.                     ckstrncat(ssh2_hka,hkatab[x].kwd,len);
  8117.                     if (j < i - 1)
  8118.                       ckstrncat(ssh2_hka,",",len);
  8119.                 }
  8120.             }
  8121.             return(success = 1);
  8122. #undef TMPCNT
  8123.           }
  8124.           case SSH2_GNH:
  8125.           case SSH2_UNH:
  8126.             if ((x = cmifi("Filename","",&s,&z,xxstring)) < 0) {
  8127.                 if (x != -3)
  8128.                   return(y);
  8129.             } else {
  8130.                 ckstrncpy(line,s,LINBUFSIZ);
  8131.                 if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
  8132.                   ckstrncpy(line,tmpbuf,LINBUFSIZ);
  8133.             }
  8134.             s = (x == -3) ? NULL : line;
  8135.             if ((x = cmcfm()) < 0)
  8136.               return(x);
  8137.             switch (y) {
  8138.               case SSH2_GNH: makestr(&ssh2_gnh,s); break;
  8139.               case SSH2_UNH: makestr(&ssh2_unh,s); break;
  8140.               default: return(success = 0);
  8141.             }
  8142.             return(success = 1);
  8143.         }
  8144.  
  8145.       case SSH_VRB:                     /* Verbosity level */
  8146.         y = cmnum("SSH verbosity level, 0-7","2",10,&x,xxstring);
  8147.         return(setnum(&ssh_vrb,x,y,7));
  8148.  
  8149.       case SSH_VER:                     /* Version */
  8150.         if ((y = cmkey(sshver,3,"","auto", xxstring)) < 0)
  8151.           return(y);
  8152.         if ((x = cmcfm()) < 0)
  8153.           return(x);
  8154.         ssh_ver = y;                    /* 0 == AUTO */
  8155. #ifndef SSHTEST
  8156.         sl_ssh_ver_saved = 0;
  8157. #endif /* SSHTEST */
  8158.         return(success = 1);
  8159.  
  8160.       case SSH_IDF: {                   /* Identity file */
  8161.         int i, n;
  8162.         for (i = 0; i < 32; i++) {
  8163.             if ((x = cmifi("Filename","",&s,&y,xxstring)) < 0) {
  8164.                 if (x == -3)
  8165.                   break;
  8166.                 return(x);
  8167.             }
  8168.             if (!zfnqfp(s,LINBUFSIZ,line))
  8169.               ckstrncpy(line,s,LINBUFSIZ);
  8170.             makestr(&ssh_tmp[i],line);
  8171.         }
  8172.         n = i;
  8173.         if ((x = cmcfm()) < 0) {
  8174.             for (i = 0; i < n; i++)
  8175.               makestr(&(ssh_tmp[i]),NULL);
  8176.             return(x);
  8177.         }
  8178.         for (i = 0; i < 32; i++) {
  8179.             makestr(&(ssh_idf[i]),NULL);
  8180.             if (i < n) {
  8181.                 ssh_idf[i] = ssh_tmp[i];
  8182.                 ssh_tmp[i] = NULL;
  8183.             } else {
  8184.                 makestr(&(ssh_tmp[i]),NULL);
  8185.             }
  8186.         }
  8187.         ssh_idf_n = n;
  8188.         return(success = 1);
  8189.       }
  8190.       case SSH_XFW:                     /* X11-forwarding */
  8191.         success = seton(&ssh_xfw);
  8192. #ifndef SSHTEST
  8193.         if (success)
  8194.           sl_ssh_xfw_saved = 0;
  8195. #endif /* SSHTEST */
  8196.         return(success);
  8197.  
  8198.       case SSH_XAL:                     /* SSH Xauth Location */
  8199.         if ((x = cmifi("Path to executable", "",&s,&y,xxstring)) < 0) {
  8200.             if (x != -3)
  8201.               return(x);
  8202.         } else {
  8203.             ckstrncpy(line,s,LINBUFSIZ);
  8204.             if (zfnqfp(line,TMPBUFSIZ,tmpbuf))
  8205.               ckstrncpy(line,tmpbuf,LINBUFSIZ);
  8206.         }
  8207.         s = (x == -3) ? NULL : line;
  8208.         if ((x = cmcfm()) < 0) return(x);
  8209.         makestr(&ssh_xal,s);
  8210.         return(success = 1);
  8211.  
  8212.       case SSH_CFG:                     /* Use OpenSSH Config */
  8213.         return(success = seton(&ssh_cfg));
  8214. #endif /* SSHBUILTIN */
  8215.  
  8216.       default:
  8217.         return(-2);
  8218.     }
  8219. }
  8220. #endif /* ANYSSH */
  8221.  
  8222.  
  8223. #ifdef KUI
  8224. #include "ikui.h"
  8225. extern ULONG RGBTable[16];
  8226.  
  8227. #define GUI_RGB  1
  8228. #define GUI_WIN  2
  8229. #define GUI_FON  3
  8230. #define GUI_DIA  4
  8231. #define GUI_TLB  5
  8232. #define GUI_MNB  6
  8233.  
  8234. #define GUIW_POS 1
  8235. #define GUIW_RES 2
  8236. #define GUIW_RUN 3
  8237. #define GUIWR_NON 0
  8238. #define GUIWR_FON 1
  8239. #define GUIWR_DIM 2
  8240. #define GUIWN_RES 1
  8241. #define GUIWN_MIN 2
  8242. #define GUIWN_MAX 3
  8243.  
  8244. static struct keytab guitab[] = {
  8245.     { "dialogs",     GUI_DIA,  0 },
  8246.     { "font",        GUI_FON,  0 },
  8247.     { "menubar",     GUI_MNB,  0 },
  8248.     { "rgbcolor",    GUI_RGB,  0 },
  8249.     { "toolbar",     GUI_TLB,  0 },
  8250.     { "window",      GUI_WIN,  0 },
  8251.     { "", 0, 0}
  8252. };
  8253. static int nguitab = (sizeof(guitab) / sizeof(struct keytab));
  8254.  
  8255. static struct keytab guiwtab[] = {
  8256.     { "position",    GUIW_POS, 0 },
  8257.     { "resize-mode", GUIW_RES, 0 },
  8258.     { "run-mode",    GUIW_RUN, 0 },
  8259.     { "", 0, 0}
  8260. };
  8261. static int nguiwtab = (sizeof(guiwtab) / sizeof(struct keytab));
  8262.  
  8263. static struct keytab guiwrtab[] = {
  8264.     { "change-dimensions",  GUIWR_DIM, 0 },
  8265.     { "none",               GUIWR_NON, 0 },
  8266.     { "scale-font",         GUIWR_FON, 0 },
  8267.     { "", 0, 0}
  8268. };
  8269. static int nguiwrtab = (sizeof(guiwrtab) / sizeof(struct keytab));
  8270.  
  8271. static struct keytab guiwntab[] = {
  8272.     { "maximize",  GUIWN_MAX, 0 },
  8273.     { "minimize",  GUIWN_MIN, 0 },
  8274.     { "restore",   GUIWN_RES, 0 },
  8275.     { "", 0, 0}
  8276. };
  8277. static int nguiwntab = (sizeof(guiwntab) / sizeof(struct keytab));
  8278.  
  8279. static struct keytab rgbtab[] = {
  8280.     { "black",         0, 0 },
  8281.     { "blue",          1, 0 },
  8282.     { "brown",         6, 0 },
  8283.     { "cyan",          3, 0 },
  8284.     { "darkgray",      8, 0 },
  8285.     { "dgray",         8, CM_INV },
  8286.     { "green",         2, 0 },
  8287.     { "lblue",         9, CM_INV },
  8288.     { "lcyan",        11, CM_INV },
  8289.     { "lgreen",       10, CM_INV },
  8290.     { "lgray",         7, CM_INV },
  8291.     { "lightblue",     9, 0 },
  8292.     { "lightcyan",    11, 0 },
  8293.     { "lightgreen",   10, 0 },
  8294.     { "lightgray",     7, 0 },
  8295.     { "lightmagenta", 13, 0 },
  8296.     { "lightred",     12, 0 },
  8297.     { "lmagenta",     13, CM_INV },
  8298.     { "lred",         12, CM_INV },
  8299.     { "magenta",       5, 0 },
  8300.     { "red",           4, 0 },
  8301.     { "white",        15, 0 },
  8302.     { "yellow",       14, 0 },
  8303.  
  8304. };
  8305. int nrgb = (sizeof(rgbtab) / sizeof(struct keytab));
  8306.  
  8307. VOID
  8308. shogui() {
  8309.     extern gui_dialog;
  8310.     extern HWND getHwndKUI();
  8311.     unsigned char cmdsav = colorcmd;
  8312.     int i, red, green, blue, lines=0;
  8313.     char * s;
  8314.  
  8315.  
  8316.     printf("GUI paramters:\n");
  8317.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8318.     printf("  Dialogs:     %s\n",showoff(gui_dialog));
  8319.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8320.     printf("  Position:    %d,%d\n",get_gui_window_pos_x(),
  8321.             get_gui_window_pos_y());
  8322.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8323.     printf("  Resolution:  %d x %d\n",GetSystemMetrics(SM_CXSCREEN),
  8324.             GetSystemMetrics(SM_CYSCREEN));
  8325.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8326.     printf("  Run-mode:    %s\n",IsIconic(getHwndKUI()) ? "minimized" :
  8327.             IsZoomed(getHwndKUI()) ? "maximized" : "restored");
  8328.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8329.     switch ( get_gui_resize_mode() ) {
  8330.       case GUIWR_NON:
  8331.         s = "none";
  8332.         break;
  8333.       case GUIWR_FON:
  8334.         s = "scales font";
  8335.         break;
  8336.       case GUIWR_DIM:
  8337.         s= "changes dimensions";
  8338.         break;
  8339.     }
  8340.     printf("  Resize-mode: %s\n",s);
  8341.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8342.     printf("\n");
  8343.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8344.  
  8345.     printf("RGB Color Table:\n");
  8346.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8347.     printf("  Color              Red Green Blue\n");
  8348.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8349.     printf("  ------------------------------------------\n");
  8350.     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
  8351.     for (i = 0; i < nrgb; i++) {
  8352.         if (!rgbtab[i].flgs) {
  8353.             blue = (RGBTable[rgbtab[i].kwval] & 0x00FF0000)>>16;
  8354.             green = (RGBTable[rgbtab[i].kwval] & 0x0000FF00)>>8;
  8355.             red = (RGBTable[rgbtab[i].kwval] & 0x000000FF);
  8356.             printf("  %-18s %3d  %3d  %3d  ",rgbtab[i].kwd,red,green,blue);
  8357.             colorcmd = rgbtab[i].kwval << 4;
  8358.             printf("********");
  8359.             colorcmd = cmdsav;
  8360.             printf("\n");
  8361.             if (++lines > cmd_rows - 3) {
  8362.         if (!askmore())
  8363.           return;
  8364.         else
  8365.           lines = 0;
  8366.         }
  8367.         }
  8368.     }
  8369.     printf("\n");
  8370. }
  8371.  
  8372. int
  8373. setrgb() {
  8374.     int cx, red = 0, blue = 0, green = 0, z, x;
  8375.  
  8376.     if ((cx = cmkey(rgbtab,nrgb,"","",xxstring)) < 0)
  8377.       return(cx);
  8378.     if ((z = cmnum("Red value, 0-255","",10,&red,xxstring)) < 0)
  8379.       return(z);
  8380.     if ((z = cmnum("Green value, 0-255","",10,&green,xxstring)) < 0)
  8381.       return(z);
  8382.     if ((z = cmnum("Blue value, 0-255","",10,&blue,xxstring)) < 0)
  8383.       return(z);
  8384.     if ((x = cmcfm()) < 0) return(x);
  8385.     if (cx > 15 || red > 255 || blue > 255 || green > 255)
  8386.       return(-2);
  8387.     RGBTable[cx] = (unsigned)(((unsigned)blue << 16) |
  8388.         (unsigned)((unsigned)green << 8) |
  8389.         (unsigned)red);
  8390.     return(success = 1);
  8391. }
  8392.  
  8393. /*
  8394.   Set GUI window position: XY coordinates of upper left corner,
  8395.   expressed as pixel numbers in the current screen resolution.
  8396.   (0,0) means put ourselves in the upper left corner.
  8397.   Can we check for out of bounds?
  8398. */
  8399.  
  8400. int
  8401. setguiwin() {
  8402.     int cx, x, y, z;
  8403.     if ((cx = cmkey(guiwtab,nguiwtab,"","",xxstring)) < 0)
  8404.       return(cx);
  8405.     switch (cx) {
  8406.       case GUIW_POS:
  8407.         if ((z = cmnum("X coordinate (pixel number)","",10,&x,xxstring)) < 0)
  8408.           return(z);
  8409.         if ((z = cmnum("Y coordinate (pixel number)","",10,&y,xxstring)) < 0)
  8410.           return(z);
  8411.         if ((z = cmcfm()) < 0)
  8412.           return(z);
  8413.         if (x < 0 || y < 0) {
  8414.             printf("?Coordinates must be 0 or greater\n");
  8415.             return(-9);
  8416.         }
  8417.         gui_position(x,y);
  8418.         return(success = 1);
  8419.       case GUIW_RES:
  8420.         if ((x = cmkey(guiwrtab,nguiwrtab,"","",xxstring)) < 0)
  8421.           return(x);
  8422.         if ((z = cmcfm()) < 0)
  8423.           return(z);
  8424.         gui_resize_mode(x);
  8425.         return(success = 1);
  8426.       case GUIW_RUN:
  8427.     if ((x = cmkey(guiwntab,nguiwntab,"","",xxstring)) < 0)
  8428.       return(x);
  8429.     if ((z = cmcfm()) < 0)
  8430.       return(z);
  8431.     gui_win_run_mode(x);
  8432.     return(success = 1);
  8433.       default:
  8434.         return(-2);
  8435.     }
  8436. }
  8437.  
  8438. int
  8439. setguifont() {                /* Assumes that CKFLOAT is defined! */
  8440.  
  8441.     extern struct keytab * term_font;
  8442.     extern struct keytab * _term_font;
  8443.     extern int tt_font, tt_font_size, ntermfont;
  8444.     int x, y, z;
  8445.     char *s;
  8446.  
  8447.     if (ntermfont == 0)
  8448.       BuildFontTable(&term_font, &_term_font, &ntermfont);
  8449.     if (!(term_font && _term_font && ntermfont > 0)) {
  8450.         printf("?Internal error: Failure to enumerate fonts\n");
  8451.         return(-9);
  8452.     }
  8453.     if ((x = cmkey(_term_font,ntermfont,"","",xxstring)) < 0)
  8454.       return(x);
  8455.     if ((z = cmfld("Height of font in points","12",&s,xxstring)) < 0)
  8456.       return(z);
  8457.     if (isfloat(s,0) < 1) {        /* (sets floatval) */
  8458.     printf("?Integer or floating-point number required\n");
  8459.     return(-9);
  8460.     }
  8461.     if (floatval < 0.5) {
  8462.     printf("?Positive number required\n");
  8463.     return(-9);
  8464.     }
  8465.     if ((z = cmcfm()) < 0)
  8466.       return(z);
  8467.     tt_font = x;            /* Font index */
  8468.     tt_font_size = (int)(floatval * 2);    /* Font size in half points */
  8469.     KuiSetProperty(KUI_TERM_FONT, (long)tt_font, (long)tt_font_size);
  8470.     return(success = 1);
  8471. }
  8472.  
  8473. VOID
  8474. setguidialog(x) int x;
  8475. {
  8476.     extern int gui_dialog;
  8477.     gui_dialog = x;
  8478.     KuiSetProperty(KUI_GUI_DIALOGS, (long)x, 0L);
  8479. }
  8480.  
  8481. VOID
  8482. setguimenubar(x) int x;
  8483. {
  8484.     KuiSetProperty(KUI_GUI_MENUBAR, (long)x, 0L);
  8485. }
  8486.  
  8487. VOID
  8488. setguitoolbar(x) int x;
  8489. {
  8490.     KuiSetProperty(KUI_GUI_TOOLBAR, (long)x, 0L);
  8491. }
  8492.  
  8493. int
  8494. setgui() {
  8495.     int cx, x, rc;
  8496.     if ((cx = cmkey(guitab,nguitab,"","",xxstring)) < 0)
  8497.       return(cx);
  8498.     switch (cx) {
  8499.       case GUI_DIA:
  8500.         rc = seton(&x);
  8501.         if (rc >= 0)
  8502.           setguidialog(x);
  8503.         return(rc);
  8504.       case GUI_FON:
  8505.         return(setguifont());
  8506.       case GUI_RGB:
  8507.         return(setrgb());
  8508.       case GUI_WIN:
  8509.         return(setguiwin());
  8510.       case GUI_TLB:
  8511.         rc = seton(&x);
  8512.         if (rc >= 0)
  8513.           setguitoolbar(x);
  8514.         return(rc);
  8515.       case GUI_MNB:
  8516.         rc = seton(&x);
  8517.         if (rc >= 0)
  8518.           setguimenubar(x);
  8519.         return(rc);
  8520.       default:
  8521.         return(-2);
  8522.     }
  8523. }
  8524. #endif /* KUI */
  8525.  
  8526. VOID
  8527. setexitwarn(x) int x; 
  8528. {
  8529.     xitwarn = x;
  8530. #ifdef KUI
  8531.     KuiSetProperty(KUI_EXIT_WARNING, (long)x, 0L);
  8532. #endif /* KUI */
  8533. }
  8534.  
  8535. #ifndef NOLOCAL
  8536. VOID
  8537. setdebses(x) int x; {
  8538. #ifdef OS2
  8539.     if ((debses != 0) && (x == 0))    /* It was on and we turned it off? */
  8540.       os2debugoff();            /* Fix OS/2 coloration */
  8541. #endif /* OS2 */
  8542.     debses = x;
  8543. #ifdef KUI
  8544.     KuiSetProperty(KUI_TERM_DEBUG,x,0);
  8545. #endif /* KUI */
  8546. }
  8547. #endif /* NOLOCAL */
  8548.  
  8549. /*  D O P R M  --  Set a parameter.  */
  8550. /*
  8551.  Returns:
  8552.   -2: illegal input
  8553.   -1: reparse needed
  8554.    0: success
  8555. */
  8556. int
  8557. doprm(xx,rmsflg) int xx, rmsflg; {
  8558.     int i = 0, x = 0, y = 0, z = 0;
  8559.     long zz = 0L;
  8560.     char *s = NULL, *p = NULL;
  8561. #ifdef OS2
  8562.     char portbuf[64];
  8563.     long portspeed = 0L;
  8564.     int portparity = 0;
  8565.     int portflow = 0;
  8566. #endif /* OS2 */
  8567.  
  8568. #ifndef NOSETKEY
  8569. #ifdef OS2
  8570.     if (xx == XYMSK)
  8571.       return(setmsk());
  8572. #endif /* OS2 */
  8573. #endif /* NOSETKEY */
  8574.  
  8575.     if (xx == XYFLAG) {                 /* SET FLAG */
  8576.         extern int ooflag;
  8577.         return(success = seton(&ooflag));
  8578.     }
  8579.     if (xx == XYPRTR                    /* SET PRINTER (or BPRINTER) */
  8580. #ifdef BPRINT
  8581.         || xx == XYBDCP
  8582. #endif /* BPRINT */
  8583.         )
  8584.       return(setprinter(xx));
  8585.  
  8586.     switch (xx) {
  8587.  
  8588. #ifdef ANYX25                           /* SET X25 ... */
  8589. case XYX25:
  8590.         return(setx25());
  8591.  
  8592. #ifndef IBMX25
  8593. case XYPAD:                             /* SET PAD ... */
  8594.         return(setpadp());
  8595. #endif /* IBMX25 */
  8596. #endif /* ANYX25 */
  8597.  
  8598. #ifndef NOXFER
  8599.       case XYEOL:       /* These have all been moved to set send/receive... */
  8600.       case XYLEN:       /* Let the user know what to do. */
  8601.       case XYMARK:
  8602.       case XYNPAD:
  8603.       case XYPADC:
  8604.       case XYTIMO:
  8605.         printf("...Use SET SEND or SET RECEIVE instead.\n");
  8606.         printf("Type HELP SET SEND or HELP SET RECEIVE for more info.\n");
  8607.         return(success = 0);
  8608.  
  8609.       case XYATTR:                      /* File Attribute packets */
  8610.         return(setat(rmsflg));
  8611.  
  8612.       case XYIFD:                       /* Incomplete file disposition */
  8613.         if ((y = cmkey(ifdatab,3,"","auto",xxstring)) < 0) return(y);
  8614.         if ((x = cmcfm()) < 0) return(x);
  8615.         if (rmsflg) {
  8616.             sstate = setgen('S',
  8617.                             "310",
  8618.                             y == 0 ? "0" : (y == 1 ? "1" : "2"),
  8619.                             ""
  8620.                             );
  8621.             return((int) sstate);
  8622.         } else {
  8623.             keep = y;
  8624.             return(success = 1);
  8625.         }
  8626. #endif /* NOXFER */
  8627.  
  8628.       case XYMATCH:            /* [ REMOTE ] SET MATCH...  */
  8629. #ifndef NOXFER
  8630.     if ((z = cmkey(matchtab,nmatchtab,"","",xxstring)) < 0)
  8631.       return(z);
  8632.     if (rmsflg) {
  8633.             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  8634.         if ((x = cmcfm()) < 0) return(x);
  8635.         switch (z) {
  8636.           case MCH_DOTF:
  8637.         return(sstate = setgen('S',"330", y == 0 ? "0" : "1", ""));
  8638.           case MCH_FIFO:
  8639.         return(sstate = setgen('S',"331", y == 0 ? "0" : "1", ""));
  8640.           default:
  8641.         return(-2);
  8642.           }
  8643.       }
  8644. #endif /* NOXFER */
  8645.       switch (z) {
  8646.         case MCH_FIFO:
  8647.           return(success = seton(&matchfifo));
  8648.         case MCH_DOTF:
  8649.           x = seton(&matchdot); 
  8650.           if (x < 0) return(x);
  8651.           dir_dots = -1;
  8652.           return(success = x);
  8653.         default:
  8654.           return(-2);
  8655.       }
  8656.  
  8657. #ifndef NOSPL
  8658.       case XYINPU:                      /* SET INPUT */
  8659.         return(setinp());
  8660. #endif /* NOSPL */
  8661.  
  8662. #ifdef NETCONN
  8663.       case XYNET: {                     /* SET NETWORK */
  8664.  
  8665.           struct FDB k1, k2;
  8666.  
  8667.           cmfdbi(&k1,_CMKEY,"","","",nnetkey, 0, xxstring, netkey, &k2);
  8668.           cmfdbi(&k2,_CMKEY,"","","",nnets,   0, xxstring, netcmd, NULL);
  8669.  
  8670. #ifdef OS2     /* Hide network-type keywords for networks not installed */
  8671.           for (z = 0; z < nnets; z++) {
  8672.               if (netcmd[z].kwval == NET_TCPB && tcp_avail == 0)
  8673.                 netcmd[z].flgs =  CM_INV;
  8674. #ifdef SSHBUILTIN
  8675.               if (netcmd[z].kwval == NET_SSH &&
  8676.                    !ck_ssleay_is_installed())
  8677.                 netcmd[z].flgs =  CM_INV;
  8678. #endif /* SSHBUILTIN */
  8679. #ifdef DECNET
  8680.               else if (netcmd[z].kwval == NET_DEC  && dnet_avail == 0)
  8681.                 netcmd[z].flgs =  CM_INV;
  8682. #endif /* DECNET */
  8683. #ifdef CK_NETBIOS
  8684.               else if (netcmd[z].kwval == NET_BIOS && netbiosAvail == 0)
  8685.                 netcmd[z].flgs =  CM_INV;
  8686. #endif /* CK_NETBIOS */
  8687. #ifdef SUPERLAT
  8688.               else if (netcmd[z].kwval == NET_SLAT  && slat_avail == 0)
  8689.                 netcmd[z].flgs =  CM_INV;
  8690. #endif /* SUPERLAT */
  8691.           }
  8692.           if (tcp_avail)                /* Default network type */
  8693.             ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
  8694. #ifdef SSHBUILTIN
  8695.           else if ( ck_ssleay_is_installed() )
  8696.             ckstrncpy(tmpbuf,"ssh",TMPBUFSIZ);
  8697. #endif /* SSHBUILTIN */
  8698. #ifdef DECNET
  8699.           else if (dnet_avail)
  8700.             ckstrncpy(tmpbuf,"decnet",TMPBUFSIZ);
  8701. #endif /* DECNET */
  8702. #ifdef SUPERLAT
  8703.           else if (slat_avail)
  8704.             ckstrncpy(tmpbuf,"superlat",TMPBUFSIZ);
  8705. #endif /* SUPERLAT */
  8706. #ifdef CK_NETBIOS
  8707.           else if (netbiosAvail)
  8708.             ckstrncpy(tmpbuf,"netbios",TMPBUFSIZ);
  8709. #endif /* CK_NETBIOS */
  8710.           else ckstrncpy(tmpbuf,"named-pipe",TMPBUFSIZ);
  8711. #else  /* OS2 */
  8712. #ifdef TCPSOCKET
  8713.           ckstrncpy(tmpbuf,"tcp/ip",TMPBUFSIZ);
  8714. #else
  8715. #ifdef ANYX25
  8716.           ckstrncpy(tmpbuf,"x.25",TMPBUFSIZ);
  8717. #else
  8718.           ckstrncpy(tmpbuf,"",TMPBUFSIZ);
  8719. #endif /* ANYX25 */
  8720. #endif /* TCPSOCKET */
  8721. #endif /* OS2 */
  8722.  
  8723.           x = cmfdb(&k1);
  8724.           if (x < 0) {                  /* Error */
  8725.               if (x == -2 || x == -9)
  8726.                 printf("?No keywords match: \"%s\"\n",atmbuf);
  8727.               return(x);
  8728.           }
  8729.           z = cmresult.nresult;         /* Keyword value */
  8730.           if (cmresult.fdbaddr == &k1) { /* Which table? */
  8731. #ifndef NOSPL
  8732. #ifndef NODIAL
  8733.               if (z == XYNET_D)
  8734.                 return(parsdir(1));
  8735. #endif /* NODIAL */
  8736. #endif /* NOSPL */
  8737.               if ((z = cmkey(netcmd,nnets,"",tmpbuf,xxstring)) < 0)
  8738.                 return(z);
  8739.           }
  8740.  
  8741. #ifdef NETCMD
  8742.           if (z == NET_CMD && nopush) {
  8743.               printf("\n?Sorry, access to external commands is disabled\n");
  8744.               return(-9);
  8745.           }
  8746. #endif /* NETCMD */
  8747.  
  8748. #ifndef NOPUSH
  8749. #ifdef NETPTY
  8750.           if (z == NET_PTY && nopush) {
  8751.               printf("\n?Sorry, access to external commands is disabled\n");
  8752.               return(-9);
  8753.           }
  8754. #endif /* NETPTY */
  8755. #endif /* NOPUSH */
  8756.  
  8757. #ifdef OS2
  8758.           if (z == NET_TCPB && tcp_avail == 0) {
  8759.               printf(
  8760. "\n?Sorry, either TCP/IP is not available on this system or\n\
  8761. necessary DLLs did not load.  Use SHOW NETWORK to check network status.\n");
  8762.               return(-9);
  8763. #ifdef SSHBUILTIN
  8764.           } else if (z == NET_SSH && !ck_ssleay_is_installed()) {
  8765.             printf("\n?Sorry, SSH is not available on this system.\n") ;
  8766.             return(-9);
  8767. #endif /* SSHBUILTIN */
  8768. #ifdef CK_NETBIOS
  8769.           } else if (z == NET_BIOS && netbiosAvail == 0) {
  8770.               printf("\n?Sorry, NETBIOS is not available on this system.\n") ;
  8771.               return(-9);
  8772. #endif /* CK_NETBIOS */
  8773. #ifdef DECNET
  8774.           } else if (z == NET_DEC && dnet_avail == 0) {
  8775.               printf("\n?Sorry, DECnet is not available on this system.\n") ;
  8776.               return(-9);
  8777. #endif /* DECNET */
  8778. #ifdef SUPERLAT
  8779.           } else if (z == NET_SLAT && slat_avail == 0) {
  8780.               printf("\n?Sorry, SuperLAT is not available on this system.\n") ;
  8781.               return(-9);
  8782. #endif /* SUPERLAT */
  8783.           }
  8784. #endif /* OS2 */
  8785.  
  8786. #ifdef NPIPEORBIOS
  8787.           if (z == NET_PIPE ||          /* Named pipe -- also get pipename */
  8788.               z == NET_BIOS) {          /* NETBIOS -- also get local name */
  8789.               char *defnam;
  8790. #ifdef CK_NETBIOS
  8791.               char tmpnbnam[NETBIOS_NAME_LEN+1];
  8792. #endif /* CK_NETBIOS */
  8793.               /* Construct default name  */
  8794.               if (z == NET_PIPE) {      /* Named pipe */
  8795.                   defnam = "kermit";    /* Default name is always "kermit" */
  8796.               } else {                  /* NetBIOS */
  8797.                   if (NetBiosName[0] != SP) { /* If there is already a name, */
  8798.                       char *p = NULL;
  8799.                       int n;            /* use it as the default. */
  8800.                       ckstrncpy(tmpnbnam,NetBiosName,NETBIOS_NAME_LEN+1);
  8801.                       /* convert trailing spaces to NULs */
  8802.                       p = &tmpnbnam[NETBIOS_NAME_LEN-1];
  8803.                       while (*p == SP) {
  8804.                           *p = NUL;
  8805.                           p--;
  8806.                       }
  8807.                       defnam = tmpnbnam;
  8808.                   } else if (*myhost)   /* Otherwise use this PC's host name */
  8809.                     defnam = (char *) myhost;
  8810.                   else                  /* Otherwise use "kermit" */
  8811.                     defnam = "kermit";
  8812.               }
  8813.               if ((y = cmtxt((z == NET_PIPE) ? "pipe name" :
  8814.                              "local NETBIOS name",
  8815.                              defnam, &s, xxstring)) < 0)
  8816.                 return(y);
  8817. #ifdef NPIPE
  8818.               pipename[0] = NUL;
  8819. #endif /* NPIPE */
  8820.               if ((y = (int) strlen(s)) < 1) {
  8821.                   printf("?You must also specify a %s name\n",
  8822.                          (z == NET_PIPE) ? "pipe" : "local NETBIOS" );
  8823.                   return(-9);
  8824.               }
  8825. #ifdef CK_NETBIOS
  8826.               if (z == NET_BIOS) {
  8827.                   if (!netbiosAvail) {
  8828.                       printf("?NETBIOS is not available on this system.\n") ;
  8829.                       return(-9);
  8830.                   }
  8831.                   if (y - NETBIOS_NAME_LEN > 0) {
  8832.                       printf("?NETBIOS name too long, %ld maximum\n",
  8833.                              NETBIOS_NAME_LEN);
  8834.                       return(-9);
  8835.                   } else if ( !strcmp(s,tmpnbnam) ) {
  8836.                       nettype = z;      /* Returning to old connection... */
  8837.                       return(success = 1); /* Done */
  8838.                   } else if (strcmp("                ",NetBiosName)) {
  8839.                       printf("?NETBIOS name already assigned to \"%s\"\n",
  8840.                              NetBiosName);
  8841.                       return(-9);
  8842.                   } else {
  8843.                       NCB ncb;
  8844.                       APIRET rc;
  8845.                       ckstrncpy(NetBiosName,s,16);
  8846.                       for (x = y; x < NETBIOS_NAME_LEN; x++)
  8847.                         NetBiosName[x] = SP;
  8848.                       NetBiosName[NETBIOS_NAME_LEN] = NUL;
  8849.                       printf("Checking \"%s\" as a unique NetBIOS name...\n",
  8850.                              NetBiosName);
  8851.                       rc = NCBAddName( NetbeuiAPI,
  8852.                                       &ncb, NetBiosAdapter, NetBiosName );
  8853.                       if (rc) {
  8854.                           printf(
  8855.                 "?Sorry, \"%s\" is already in use by another NetBIOS node.\n",
  8856.                                  NetBiosName);
  8857.                           for (x = 0; x < NETBIOS_NAME_LEN; x++)
  8858.                             NetBiosName[x] = SP;
  8859.                           return(-9);
  8860.                       }
  8861.                   }
  8862.               }
  8863. #endif /* CK_NETBIOS */
  8864. #ifdef NPIPE
  8865.               if (z == NET_PIPE)
  8866.                 ckstrncpy(pipename,s,PIPENAML);
  8867. #endif /* NPIPE */
  8868.           } else
  8869. #endif /* NPIPEORBIOS */
  8870. #ifdef DECNET
  8871.             if (z == NET_DEC) {
  8872.                 /* Determine if we are using LAT or CTERM */
  8873.                 if ((y = cmkey(dnettab,
  8874.                                ndnet,"DECNET protocol","lat",xxstring)) < 0)
  8875.                   return(y);
  8876.                 if ((x = cmcfm()) < 0) return(x);
  8877.                 ttnproto = y;
  8878.             } else
  8879. #endif /* DECNET */
  8880. #ifdef NETDLL
  8881.               if (z == NET_DLL) {
  8882.                   /* Find out which DLL they are using */
  8883.                   char dllname[256]="";
  8884.                   char * p=NULL;
  8885.                   if ((x = cmifi("Dynamic load library",
  8886.                                  "",&p,&y,xxstring)) < 0) {
  8887.                       if (x == -3) {
  8888.                           printf("?Name of DLL required\n");
  8889.                           return(-9);
  8890.                       }
  8891.                       return(x);
  8892.                   }
  8893.                   ckstrncpy(dllname,p,256);
  8894.                   if ((x = cmcfm()) < 0) return(x);
  8895.  
  8896.                   if (netdll_load(dllname) < 0) /* Try to load the dll */
  8897.                     return(success = 0);
  8898.                   else {
  8899.                       nettype = z;
  8900.                       return(success = 1);
  8901.                   }
  8902.               } else
  8903. #endif /* NETDLL */
  8904.                 if ((x = cmcfm()) < 0) return(x);
  8905.           nettype = z;
  8906.           if (
  8907. #ifdef DECNET
  8908.               (nettype != NET_DEC)  &&
  8909. #endif /* DECNET */
  8910. #ifdef NPIPE
  8911.               (nettype != NET_PIPE) &&
  8912. #endif /* NPIPE */
  8913. #ifdef CK_NETBIOS
  8914.               (nettype != NET_BIOS) &&
  8915. #endif /* CK_NETBIOS */
  8916. #ifdef NETFILE
  8917.               (nettype != NET_FILE) &&
  8918. #endif /* NETFILE */
  8919. #ifdef NETCMD
  8920.               (nettype != NET_CMD) &&
  8921. #endif /* NETCMD */
  8922. #ifdef NETPTY
  8923.               (nettype != NET_PTY) &&
  8924. #endif /* NETPTY */
  8925. #ifdef NETDLL
  8926.               (nettype != NET_DLL) &&
  8927. #endif /* NETDLL */
  8928. #ifdef SUPERLAT
  8929.               (nettype != NET_SLAT) &&
  8930. #endif /* SUPERLAT */
  8931.               (nettype != NET_SX25) &&
  8932.               (nettype != NET_VX25) &&
  8933. #ifdef IBMX25
  8934.               (nettype != NET_IX25) &&
  8935. #endif /* IBMX25 */
  8936. #ifdef SSHBUILTIN
  8937.               (nettype != NET_SSH) &&
  8938. #endif /* SSHBUILTIN */
  8939.               (nettype != NET_TCPB)) {
  8940.               printf("?Network type not supported\n");
  8941.               return(success = 0);
  8942.           } else {
  8943.               return(success = 1);
  8944.           }
  8945.       }
  8946.  
  8947. #ifndef NOTCPOPTS
  8948. #ifdef TCPSOCKET
  8949.       case XYTCP: {
  8950.         extern int ttyfd;
  8951.  
  8952.         if ((z = cmkey(tcpopt,ntcpopt,"TCP option","nodelay",xxstring)) < 0)
  8953.           return(z);
  8954.  
  8955.         switch (z) {
  8956. #ifndef NOHTTP
  8957.           case XYTCP_HTTP_PROXY: {
  8958.           struct FDB sw, tx;
  8959.           int n, x;
  8960.           char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1];
  8961.  
  8962.           cmfdbi(&sw,        /* First FDB - switches */
  8963.              _CMKEY,        /* fcode */
  8964.              "HTTP proxy server host[:port] or switch",
  8965.              "",        /* default */
  8966.              "",        /* addtl string data */
  8967.              nuserpass,        /* addtl numeric data 1: tbl size */
  8968.              4,            /* addtl numeric data 2: 4 = cmswi */
  8969.              xxstring,        /* Processing function */
  8970.              userpass,        /* Keyword table */
  8971.              &tx        /* Pointer to next FDB */
  8972.              );
  8973.           cmfdbi(&tx,
  8974.              _CMTXT,        /* fcode */
  8975.              "HTTP proxy server host[:port]",
  8976.              "",        /* default */
  8977.              "",        /* addtl string data */
  8978.              0,            /* addtl numeric data 1 */
  8979.              0,            /* addtl numeric data 2 */
  8980.              xxstring,
  8981.              NULL,
  8982.              NULL
  8983.              );
  8984.           while (1) {
  8985.           if ((x = cmfdb(&sw)) < 0) {
  8986.               if (x == -3) {
  8987.               x = -9;
  8988.               printf("?Hostname required\n");
  8989.               }
  8990.               return(x);
  8991.           }
  8992.           if (cmresult.fcode != _CMKEY)
  8993.             break;
  8994.           n = cmresult.nresult;
  8995.           switch (n) {
  8996.             case UPW_USER:
  8997.             case UPW_PASS:
  8998.               if ((x = cmfld((n == UPW_USER) ? "Username" : "Password",
  8999.                      "", &s, xxstring)) < 0) {
  9000.               if (x != -3)
  9001.                 return(x);
  9002.               }
  9003.               ckstrncpy((n == UPW_USER) ? ubuf : pbuf, s, LOGINLEN+1);
  9004.           }
  9005.           }
  9006.           if (cmresult.fcode != _CMTXT)
  9007.         return(-2);
  9008.           s = cmresult.sresult;
  9009.           if (s) if (!*s) s = NULL;
  9010.  
  9011. #ifdef IKSDCONF
  9012.           if (iksdcf)
  9013.         return(success = 0);
  9014. #endif /* IKSDCONF */
  9015.           makestr(&tcp_http_proxy_user,ubuf);
  9016.               makestr(&tcp_http_proxy_pwd,pbuf);
  9017.           makestr(&tcp_http_proxy,s);
  9018.               memset(pbuf,0,sizeof(pbuf));
  9019.           return(success = 1);
  9020.       }
  9021. #endif /* NOHTTP */
  9022. /*
  9023.   It would have been easy to combine XYTCP_SOCKS_SVR with the previous
  9024.   one except for the #ifdefs...
  9025. */
  9026. #ifdef NT
  9027. #ifdef CK_SOCKS
  9028.           case XYTCP_SOCKS_SVR: {
  9029.           char ubuf[LOGINLEN+1], pbuf[LOGINLEN+1];
  9030.           char * p = getenv("SOCKS_SERVER");
  9031.           struct FDB sw, tx;
  9032.           int n, x;
  9033.  
  9034.           if (!p) p = "";
  9035.  
  9036.           cmfdbi(&sw,        /* First FDB - switches */
  9037.              _CMKEY,        /* fcode */
  9038.              "SOCKS server host[:port] or switch",
  9039.              "",        /* default */
  9040.              "",        /* addtl string data */
  9041.              nuserpass,        /* addtl numeric data 1: tbl size */
  9042.              4,            /* addtl numeric data 2: 4 = cmswi */
  9043.              xxstring,        /* Processing function */
  9044.              userpass,        /* Keyword table */
  9045.              &tx        /* Pointer to next FDB */
  9046.              );
  9047.           cmfdbi(&tx,
  9048.              _CMTXT,        /* fcode */
  9049.              "SOCKS server host[:port]",
  9050.              p,            /* default */
  9051.              "",        /* addtl string data */
  9052.              0,            /* addtl numeric data 1 */
  9053.              0,            /* addtl numeric data 2 */
  9054.              xxstring,
  9055.              NULL,
  9056.              NULL
  9057.              );
  9058.           while (1) {
  9059.           if ((x = cmfdb(&sw)) < 0) {
  9060.               if (x == -3) {
  9061.               x = -9;
  9062.               printf("?Hostname required\n");
  9063.               }
  9064.               return(x);
  9065.           }
  9066.           if (cmresult.fcode != _CMKEY)
  9067.             break;
  9068.           n = cmresult.nresult;
  9069.           switch (n) {
  9070.             case UPW_USER:
  9071.             case UPW_PASS:
  9072.               if ((x = cmfld((n == UPW_USER) ? "Username" : "Password",
  9073.                      "", &s, xxstring)) < 0) {
  9074.               if (x != -3)
  9075.                 return(x);
  9076.               }
  9077.               ckstrncpy((n == UPW_USER) ? ubuf : pbuf, s, LOGINLEN+1);
  9078.           }
  9079.           }
  9080.           if (cmresult.fcode != _CMTXT)
  9081.         return(-2);
  9082.           s = cmresult.sresult;
  9083.           if (s) if (!*s) s = NULL;
  9084.  
  9085. #ifdef IKSDCONF
  9086.           if (iksdcf)
  9087.         return(success = 0);
  9088. #endif /* IKSDCONF */
  9089.           makestr(&tcp_socks_user,ubuf);
  9090.               memset(pbuf,0,sizeof(pbuf));
  9091.           makestr(&tcp_socks_svr,s);
  9092.           return(success = 1);
  9093.       }
  9094.  
  9095. #ifdef CK_SOCKS_NS
  9096.           case XYTCP_SOCKS_NS: {
  9097.             char * p = getenv("SOCKS_NS");
  9098.             if (!p) p = "";
  9099.             if ((y = cmtxt("hostname or IP of SOCKS Name Server",p,
  9100.                             &s,xxstring)) < 0)
  9101.                 return(y);
  9102. #ifdef IKSDCONF
  9103.               if (iksdcf) return(success = 0);
  9104. #endif /* IKSDCONF */
  9105.               if (tcp_socks_ns) {
  9106.                   free(tcp_socks_ns);   /* Free any previous storage */
  9107.                   tcp_socks_ns = NULL;
  9108.               }
  9109.               if (s == NULL || *s == NUL) { /* If none given */
  9110.                   tcp_socks_ns = NULL;  /* remove the override string */
  9111.                   return(success = 1);
  9112.               } else if ((tcp_socks_ns = malloc(strlen(s)+1))) {
  9113.                   strcpy(tcp_socks_ns,s);
  9114.                   return(success = 1);
  9115.               } else
  9116.                 return(success = 0);
  9117.           }
  9118. #endif /* CK_SOCKS_NS */
  9119. #endif /* CK_SOCKS */
  9120. #endif /* NT */
  9121.           case XYTCP_ADDRESS:
  9122.             if ((y = cmtxt("preferred IP Address for TCP connections","",
  9123.                            &s,xxstring)) < 0)
  9124.               return(y);
  9125. #ifdef IKSDCONF
  9126.             if (iksdcf) return(success = 0);
  9127. #endif /* IKSDCONF */
  9128.             if (tcp_address) {
  9129.                 free(tcp_address);      /* Free any previous storage */
  9130.                 tcp_address = NULL;
  9131.             }
  9132.             if (s == NULL || *s == NUL) { /* If none given */
  9133.                 tcp_address = NULL;     /* remove the override string */
  9134.                 return(success = 1);
  9135.             } else if ((tcp_address = malloc(strlen(s)+1))) {
  9136.                 strcpy(tcp_address,s);
  9137.                 return(success = 1);
  9138.             } else
  9139.               return(success = 0);
  9140. #ifdef SO_KEEPALIVE
  9141.           case XYTCP_KEEPALIVE:
  9142.             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
  9143.             if ((y = cmcfm()) < 0) return(y);
  9144. #ifdef IKSDCONF
  9145.             if (iksdcf) return(success = 0);
  9146. #endif /* IKSDCONF */
  9147.             success = keepalive(ttyfd,z);
  9148.             return(success);
  9149. #endif /* SO_KEEPALIVE */
  9150. #ifdef SO_DONTROUTE
  9151.           case XYTCP_DONTROUTE:
  9152.             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
  9153.             if ((y = cmcfm()) < 0) return(y);
  9154. #ifdef IKSDCONF
  9155.             if (iksdcf) return(success = 0);
  9156. #endif /* IKSDCONF */
  9157.             success = dontroute(ttyfd,z);
  9158.             return(success);
  9159. #endif /* SO_DONTROUTE */
  9160. #ifdef TCP_NODELAY
  9161.           case XYTCP_NODELAY:
  9162.             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
  9163.             if ((y = cmcfm()) < 0) return(y);
  9164. #ifdef IKSDCONF
  9165.             if (iksdcf) return(success = 0);
  9166. #endif /* IKSDCONF */
  9167.             success = no_delay(ttyfd,z);
  9168.             return(success);
  9169.           case XYTCP_NAGLE:             /* The inverse of NODELAY */
  9170.             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
  9171.             if ((y = cmcfm()) < 0) return(y);
  9172. #ifdef IKSDCONF
  9173.             if (iksdcf) return(success = 0);
  9174. #endif /* IKSDCONF */
  9175.             success = no_delay(ttyfd,!z);
  9176.             return(success);
  9177. #endif /* TCP_NODELAY */
  9178. #ifdef SO_LINGER
  9179.           case XYTCP_LINGER:
  9180.             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0)
  9181.               return(z);
  9182.             if (z) {                    /* if on, we need a timeout value */
  9183.                 if ((x = cmnum("Linger timeout in 10th of a millisecond",
  9184.                                "0",10,&y,xxstring)) < 0)
  9185.                   return(x);
  9186.             } else
  9187.               y = 0;
  9188.             if ((x = cmcfm()) < 0)
  9189.               return(x);
  9190. #ifdef IKSDCONF
  9191.             if (iksdcf) return(success = 0);
  9192. #endif /* IKSDCONF */
  9193.             success = ck_linger(ttyfd,z,y);
  9194.             return(success);
  9195. #endif /* SO_LINGER */
  9196. #ifdef SO_SNDBUF
  9197.           case XYTCP_SENDBUF:
  9198.             x = cmnum("Send buffer size, bytes","8192",10,&z,xxstring);
  9199.             if (x < 0) return(x);
  9200.             if ((x = cmcfm()) < 0) return(x);
  9201. #ifdef IKSDCONF
  9202.             if (iksdcf) return(success = 0);
  9203. #endif /* IKSDCONF */
  9204.             success = sendbuf(ttyfd,z);
  9205.             return(success);
  9206. #endif /* SO_SNDBUF */
  9207. #ifdef SO_RCVBUF
  9208.           case XYTCP_RECVBUF:
  9209.             x = cmnum("Receive buffer size, bytes","8192",10,&z,xxstring);
  9210.             if (x < 0) return(x);
  9211.             if ((x = cmcfm()) < 0) return(x);
  9212. #ifdef IKSDCONF
  9213.             if (iksdcf) return(success = 0);
  9214. #endif /* IKSDCONF */
  9215.  
  9216. /* Note: The following is not 16-bit safe */
  9217.  
  9218. #ifndef QNX16
  9219.             if (x > 52248) {
  9220.                 printf("?Warning: receive buffers larger than 52248 bytes\n");
  9221.                 printf(" may not be understood by all hosts.  Performance\n");
  9222.                 printf(" may suffer.\n");
  9223.                 return(-9);
  9224.             }
  9225. #endif /* QNX16 */
  9226.             success = recvbuf(ttyfd,z);
  9227.             return(success);
  9228. #endif /* SO_RCVBUF */
  9229.  
  9230. #ifdef VMS
  9231. #ifdef DEC_TCPIP
  9232.           case XYTCP_UCX: {             /* UCX 2.0 port swabbing bug */
  9233.               extern int ucx_port_bug;
  9234.               return(success = seton(&ucx_port_bug));
  9235.           }
  9236. #endif /* DEC_TCPIP */
  9237. #endif /* VMS */
  9238.  
  9239.           case XYTCP_RDNS: {
  9240.               extern int tcp_rdns;
  9241.               return(success = setonaut(&tcp_rdns));
  9242.           }
  9243.  
  9244. #ifdef CK_DNS_SRV
  9245.           case XYTCP_DNS_SRV: {
  9246.               extern int tcp_dns_srv;
  9247.               return(success = seton(&tcp_dns_srv));
  9248.           }
  9249. #endif /* CK_DNS_SRV */
  9250.  
  9251.           default:
  9252.             return(0);
  9253.         }
  9254.       }
  9255. #endif /* TCPSOCKET */
  9256. #endif /* NOTCPOPTS */
  9257. #endif /* NETCONN */
  9258.     }
  9259.  
  9260.     switch (xx) {
  9261.  
  9262. #ifndef NOLOCAL
  9263. #ifdef NETCONN
  9264.       case XYHOST: {                    /* SET HOST */
  9265.           z = ttnproto;                 /* Save protocol in case of failure */
  9266. #ifdef DECNET
  9267.           if (nettype != NET_DEC)
  9268. #endif /* DECNET */
  9269.             ttnproto = NP_NONE;
  9270.           if ((y = setlin(XYHOST,1,0)) <= 0) { /* Sets success to 1 */
  9271.               debug(F101,"SET HOST fail mdmtyp","",mdmtyp);
  9272.               ttnproto = z;             /* Failed, restore protocol */
  9273.               success = 0;
  9274.           }
  9275.           didsetlin++;
  9276.           debug(F101,"SET HOST OK mdmtyp","",mdmtyp);
  9277.           debug(F101,"SET HOST reliable","",reliable);
  9278.           return(y);
  9279.       }
  9280. #endif /* NETCONN */
  9281.  
  9282.       case XYLINE:                      /* SET LINE (= SET PORT) */
  9283.         debug(F101,"setlin flow 1","",flow);
  9284.         x = setlin(xx,1,0);
  9285.         if (x > -1) didsetlin++;
  9286.         debug(F101,"SET LINE setlin","",x);
  9287.         debug(F101,"SET LINE flow","",flow);
  9288.         debug(F101,"SET LINE local","",local);
  9289.         debug(F101,"SET LINE reliable","",reliable);
  9290.         return(x);
  9291. #endif /* NOLOCAL */
  9292.  
  9293. #ifndef NOSETKEY
  9294.       case XYKEY:                       /* SET KEY */
  9295.         return(dosetkey());
  9296. #endif /* NOSETKEY */
  9297.  
  9298. #ifndef NOCSETS
  9299.       case XYLANG:                      /* Language */
  9300.         if ((y = cmkey(lngtab,nlng,"","none",xxstring)) < 0)
  9301.           return(y);
  9302.         if ((x = cmcfm()) < 0) return(x);
  9303.  
  9304.         /* Look up language and get associated character sets */
  9305.         for (i = 0; (i < nlangs) && (langs[i].id != y); i++) ;
  9306.         if (i >= nlangs) {
  9307.             printf("?internal error, sorry\n");
  9308.             return(success = 0);
  9309.         } /*  */
  9310.         language = i;                   /* All good, set the language, */
  9311.         return(success = 1);
  9312. #endif /* NOCSETS */
  9313.  
  9314. #ifndef MAC
  9315.       case XYBACK:                      /* BACKGROUND */
  9316.         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
  9317.         if ((y = cmcfm()) < 0) return(y);
  9318. #ifdef COMMENT
  9319.         bgset = z;                      /* 0 = off (foreground) */
  9320. #ifdef VMS                              /* 1 = on (background) */
  9321.         if (batch && bgset == 0)        /* To enable echoing of commands */
  9322.           ckxech = 1;                   /* in VMS batch logs */
  9323. #endif /* VMS */
  9324. #else  /* COMMENT */
  9325.         if (z) {                        /* 1 = Background */
  9326.             bgset = 1;
  9327.             backgrd = 1;
  9328. #ifdef VMS
  9329.             batch = 1;
  9330. #endif /* VMS */
  9331.         } else {                        /* 0 = Foreground */
  9332.             bgset = 0;
  9333.             backgrd = 0;
  9334. #ifdef VMS
  9335.             batch = 0;
  9336. #endif /* VMS */
  9337.         }
  9338. #endif /* COMMENT */
  9339.         success = 1;
  9340.         bgchk();
  9341.         return(success);
  9342. #endif /* MAC */
  9343.  
  9344.       case XYQUIE: {                    /* QUIET */
  9345. #ifdef DCMDBUF
  9346.           extern int * xquiet;
  9347. #else
  9348.           extern int xquiet[];
  9349. #endif /* DCMDBUF */
  9350.           x = seton(&quiet);
  9351.           if (x < 0) return(x);
  9352.           xquiet[cmdlvl] = quiet;
  9353.           return(success = x);
  9354.       }
  9355.  
  9356. #ifndef NOXFER
  9357.       case XYBUF: {                     /* BUFFERS */
  9358. #ifdef DYNAMIC
  9359.           int sb, rb;
  9360.           if ((y = cmnum("Send buffer size","",10,&sb,xxstring)) < 0) {
  9361.               if (y == -3) printf("?Buffer size required\n");
  9362.               return(y);
  9363.           }
  9364.           if (sb < 0) {
  9365.               if (*atmbuf == '-')
  9366.                 printf("?Negative numbers can't be used here\n");
  9367.               else printf("?Integer overflow, use a smaller number please\n");
  9368.               return(-9);
  9369.           } else if (sb < 80) {
  9370.               printf("?Too small\n");
  9371.               return(-9);
  9372.           }
  9373.           if ((y=cmnum("Receive buffer size",ckitoa(sb),10,&rb,xxstring)) < 0)
  9374.             return(y);
  9375.           if (rb < 0) {
  9376.               if (*atmbuf == '-')
  9377.                 printf("?Negative numbers can't be used here\n");
  9378.               else printf("?Integer overflow, use a smaller number please\n");
  9379.               return(-9);
  9380.           } else if (rb < 80) {
  9381.               printf("?Too small\n");
  9382.               return(-9);
  9383.           }
  9384.           if ((y = cmcfm()) < 0) return(y);
  9385.           if ((y = inibufs(sb,rb)) < 0) return(y);
  9386.           y = adjpkl(urpsiz,wslotr,bigrbsiz); /* Maybe adjust packet sizes */
  9387.           if (y != urpsiz) urpsiz = y;
  9388.           y = adjpkl(spsiz,wslotr,bigsbsiz);
  9389.           if (y != spsiz) spsiz = spmax = spsizr = y;
  9390.           return(success = 1);
  9391. #else
  9392.           printf("?Sorry, not available\n");
  9393.           return(success = 0);
  9394. #endif /* DYNAMIC */
  9395.       }
  9396.  
  9397.       case XYCHKT:                      /* BLOCK-CHECK */
  9398.         if ((x = cmkey(chktab,4,"","3",xxstring)) < 0) return(x);
  9399.         if ((y = cmcfm()) < 0) return(y);
  9400.         bctr = x;                       /* Set local too even if REMOTE SET */
  9401.         if (rmsflg) {
  9402.             if (x == 4) {
  9403.                 tmpbuf[0] = 'B';
  9404.                 tmpbuf[1] = '\0';
  9405.             } else
  9406.               ckstrncpy(tmpbuf,ckitoa(x),TMPBUFSIZ);
  9407.             sstate = setgen('S', "400", tmpbuf, "");
  9408.             return((int) sstate);
  9409.         } else {
  9410.             return(success = 1);
  9411.         }
  9412. #endif /* NOXFER */
  9413.  
  9414. #ifndef NOLOCAL
  9415. #ifndef MAC                             /* The Mac has no RS-232 */
  9416. case XYCARR:                            /* CARRIER-WATCH */
  9417.         return(setdcd());
  9418. #endif /* MAC */
  9419. #endif /* NOLOCAL */
  9420.     }
  9421.  
  9422. #ifdef TNCODE
  9423.     switch (xx) {                       /* Avoid long switch statements... */
  9424.       case XYTELOP: {
  9425.           int c, n;                     /* Workers */
  9426.           int getval = 0;               /* Whether to get switch value */
  9427.           int tnserver = 0;             /* Client by default */
  9428.           int opt = -1;                 /* Telnet Option */
  9429.           struct FDB sw, op;            /* FDBs for each parse function */
  9430. #ifdef CK_AUTHENTICATION
  9431.           extern int sl_topt_a_s_saved;
  9432.           extern int sl_topt_a_c_saved;
  9433.           extern int sl_topt_e_s_saved;
  9434.           extern int sl_topt_e_c_saved;
  9435. #endif /* CK_AUTHENTICATION */
  9436. #ifdef IKSD
  9437.           if (inserver)                 /* Server by default when IKSD */
  9438.             tnserver = 1;
  9439. #endif /* IKSD */
  9440.  
  9441.           /* Set up chained parse functions... */
  9442.  
  9443.           cmfdbi(&op,                   /* First fdb - telopts*/
  9444.                  _CMKEY,                /* fcode */
  9445.                  "/client, /server or", /* hlpmsg */
  9446.                  "",                    /* default */
  9447.                  "",                    /* addtl string data */
  9448.                  ntnopt,                /* addtl numeric data 1 */
  9449.                  0,                     /* addtl numeric data 2 */
  9450.                  xxstring,
  9451.                  tnopttab,
  9452.                  &sw
  9453.                  );
  9454.           cmfdbi(&sw,                   /* Second FDB - command switches */
  9455.                  _CMKEY,                /* fcode */
  9456.                  "",                    /* hlpmsg */
  9457.                  "",                    /* default */
  9458.                  "",                    /* addtl string data */
  9459.                  ntnoptsw,              /* addtl numeric data 1: tbl size */
  9460.                  4,                     /* addtl numeric data 2: 4 = cmswi */
  9461.                  xxstring,              /* Processing function */
  9462.                  tnoptsw,               /* Keyword table */
  9463.                  NULL                   /* Pointer to next FDB */
  9464.                  );
  9465.  
  9466.           while (opt < 0) {             /* Parse 0 or more switches */
  9467.               x = cmfdb(&op);           /* Parse switch or other thing */
  9468.               debug(F101,"XYTELOP cmfdb","",x);
  9469.               if (x < 0)                /* Error */
  9470.                 return(x);              /* or reparse needed */
  9471.               if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
  9472.                 break;
  9473.               c = cmgbrk();             /* Get break character */
  9474.               getval = (c == ':' || c == '='); /* see how switch ended */
  9475.               if (getval && !(cmresult.kflags & CM_ARG)) {
  9476.                   printf("?This switch does not take arguments\n");
  9477.                   return(-9);
  9478.               }
  9479.               z = cmresult.nresult;     /* Numeric result = switch value */
  9480.               debug(F101,"XYTELOP switch","",z);
  9481.  
  9482.               switch (z) {              /* Process the switch */
  9483.                 case CK_TN_CLIENT:
  9484.                   tnserver = 0;
  9485.                   break;
  9486.                 case CK_TN_SERVER:
  9487.                   tnserver = 1;
  9488.                     break;
  9489.                 case CK_TN_EC:
  9490.                   opt = TELOPT_ECHO;
  9491.                   break;
  9492.                 case CK_TN_TT:
  9493.                   opt = TELOPT_TTYPE;
  9494.                   break;
  9495.                 case CK_TN_BM:
  9496.                   opt = TELOPT_BINARY;
  9497.                   break;
  9498.                 case CK_TN_ENV:
  9499.                   opt = TELOPT_NEWENVIRON;
  9500.                   break;
  9501.                 case CK_TN_LOC:
  9502.                   opt = TELOPT_SNDLOC;
  9503.                   break;
  9504.                 case CK_TN_AU:
  9505.                   opt = TELOPT_AUTHENTICATION;
  9506.                   break;
  9507.                 case CK_TN_FX:
  9508.                   opt = TELOPT_FORWARD_X;
  9509.                   break;
  9510.                 case CK_TN_ENC:
  9511.                   opt = TELOPT_ENCRYPTION;
  9512.                   break;
  9513.                 case CK_TN_IKS:
  9514.                   opt = TELOPT_KERMIT;
  9515.                   break;
  9516.                 case CK_TN_TLS:
  9517.                   opt = TELOPT_START_TLS;
  9518.                   break;
  9519.                 case CK_TN_XD:
  9520.                   opt = TELOPT_XDISPLOC;
  9521.                   break;
  9522.                 case CK_TN_NAWS:
  9523.                   opt = TELOPT_NAWS;
  9524.                   break;
  9525.                 case CK_TN_SGA:
  9526.                   opt = TELOPT_SGA;
  9527.                   break;
  9528.                 case CK_TN_PHR:
  9529.                   opt = TELOPT_PRAGMA_HEARTBEAT;
  9530.                   break;
  9531.                 case CK_TN_PSP:
  9532.                   opt = TELOPT_SSPI_LOGON;
  9533.                   break;
  9534.                 case CK_TN_PLG:
  9535.                   opt = TELOPT_PRAGMA_LOGON;
  9536.                   break;
  9537.                 case CK_TN_SAK:
  9538.                   opt = TELOPT_IBM_SAK;
  9539.                   break;
  9540.                 case CK_TN_CPC:
  9541.                   opt = TELOPT_COMPORT;
  9542.                   break;
  9543.                 case CK_TN_LOG:
  9544.                   opt = TELOPT_LOGOUT;
  9545.                   break;
  9546.                 case CK_TN_FLW:
  9547.                   opt = TELOPT_LFLOW;
  9548.                   break;
  9549.                 default:
  9550.                   printf("?Unexpected value - %d\n",z);
  9551.                   return(-9);
  9552.               }
  9553. #ifdef COMMENT
  9554.               if (cmresult.fdbaddr == &op)
  9555.                 break;
  9556. #endif /* COMMENT */
  9557.           }
  9558.           switch (opt) {
  9559.             case TELOPT_ECHO:           /* Options only the Server WILL */
  9560.             case TELOPT_FORWARD_X:
  9561.             case TELOPT_SEND_URL:
  9562.             case TELOPT_IBM_SAK:
  9563.             case TELOPT_LOGOUT:
  9564.               if ((x = cmkey(tnnegtab,
  9565.                              ntnnegtab,
  9566.                              "desired server state",
  9567.    TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
  9568.                              xxstring)
  9569.                    ) < 0)
  9570.                 return(x);
  9571.               if ((z = cmcfm()) < 0)
  9572.                   return(z);
  9573.               if (tnserver) {
  9574.                   TELOPT_DEF_S_ME_MODE(opt) = x;
  9575.                   TELOPT_ME_MODE(opt) = x;
  9576.               } else {
  9577.                   TELOPT_DEF_C_U_MODE(opt) = x;
  9578.                   TELOPT_U_MODE(opt) = x;
  9579.               }
  9580.               break;
  9581.  
  9582.             case TELOPT_TTYPE:          /* Options only the Client WILL */
  9583.             case TELOPT_NEWENVIRON:
  9584.             case TELOPT_SNDLOC:
  9585.             case TELOPT_AUTHENTICATION:
  9586.             case TELOPT_START_TLS:
  9587.             case TELOPT_XDISPLOC:
  9588.             case TELOPT_NAWS:
  9589.             case TELOPT_LFLOW:
  9590.             case TELOPT_COMPORT:
  9591.               if ((x = cmkey(tnnegtab,
  9592.                              ntnnegtab,
  9593.                              "desired client state",
  9594.     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
  9595.                              xxstring)
  9596.                    ) < 0)
  9597.                 return(x);
  9598.               if ((z = cmcfm()) < 0)
  9599.                 return(z);
  9600.               if (tnserver) {
  9601.                   TELOPT_DEF_S_U_MODE(opt) = x;
  9602.                   TELOPT_U_MODE(opt) = x;
  9603. #ifdef CK_AUTHENTICATION
  9604.                   if (opt == TELOPT_AUTHENTICATION)
  9605.                     sl_topt_a_s_saved = 0;
  9606. #endif /* CK_AUTHENTICATION */
  9607.               } else {
  9608.                   TELOPT_DEF_C_ME_MODE(opt) = x;
  9609.                   TELOPT_ME_MODE(opt) = x;
  9610. #ifdef CK_AUTHENTICATION
  9611.                   if (opt == TELOPT_AUTHENTICATION)
  9612.                     sl_topt_a_c_saved = 0;
  9613. #endif /* CK_AUTHENTICATION */
  9614.               }
  9615.               break;
  9616.  
  9617.             default:
  9618.               if ((x = cmkey(tnnegtab,
  9619.                              ntnnegtab,
  9620.                              tnserver ?
  9621.                              "desired server state" :
  9622.                              "desired client state",
  9623.     TELOPT_MODE(tnserver?TELOPT_DEF_S_ME_MODE(opt):TELOPT_DEF_C_ME_MODE(opt)),
  9624.                              xxstring
  9625.                              )
  9626.                    ) < 0)
  9627.                 return(x);
  9628.               if ((y = cmkey(tnnegtab,
  9629.                              ntnnegtab,
  9630.                              !tnserver ? "desired server state" :
  9631.                              "desired client state",
  9632.     TELOPT_MODE(!tnserver?TELOPT_DEF_S_U_MODE(opt):TELOPT_DEF_C_U_MODE(opt)),
  9633.                              xxstring
  9634.                              )
  9635.                    ) < 0)
  9636.                 return(y);
  9637.               if ((z = cmcfm()) < 0)
  9638.                 return(z);
  9639.               if (tnserver) {
  9640.                   TELOPT_DEF_S_ME_MODE(opt) = x;
  9641.                   TELOPT_ME_MODE(opt) = x;
  9642.                   TELOPT_DEF_S_U_MODE(opt) = y;
  9643.                   TELOPT_U_MODE(opt) = y;
  9644. #ifdef CK_ENCRYPTION
  9645.                   if (opt == TELOPT_ENCRYPTION)
  9646.                     sl_topt_e_s_saved = 0;
  9647. #endif /* CK_ENCRYPTION */
  9648.               } else {
  9649.                   TELOPT_DEF_C_ME_MODE(opt) = x;
  9650.                   TELOPT_ME_MODE(opt) = x;
  9651.                   TELOPT_DEF_C_U_MODE(opt) = y;
  9652.                   TELOPT_U_MODE(opt) = y;
  9653. #ifdef CK_ENCRYPTION
  9654.                   if (opt == TELOPT_ENCRYPTION)
  9655.                     sl_topt_e_c_saved = 0;
  9656. #endif /* CK_ENCRYPTION */
  9657.               }
  9658.           }
  9659.           return(success = 1);
  9660.       }
  9661.  
  9662.       case XYTEL:                       /* TELNET */
  9663.         if ((z = cmkey(tntab,ntn,"parameter for TELNET negotiations", "",
  9664.                        xxstring)) < 0)
  9665.           return(z);
  9666.         switch (z) {
  9667.           case CK_TN_EC:                /* ECHO */
  9668.             if ((x = cmkey(rltab,nrlt,
  9669.                            "initial TELNET echoing state",
  9670.                            "local",xxstring)) < 0)
  9671.               return(x);
  9672.             if ((y = cmcfm()) < 0) return(y);
  9673.             tn_duplex = x;
  9674.             return(success = 1);
  9675.  
  9676.           case CK_TN_RE:                /* REMOTE-ECHO */
  9677.             return(success = seton(&tn_rem_echo));
  9678.  
  9679.           case CK_TN_DB:                /* DEBUG */
  9680.             return(success = seton(&tn_deb));
  9681.  
  9682.           case CK_TN_TT:                /* TERMINAL TYPE */
  9683.             if ((y = cmtxt("terminal type for TELNET connections","",
  9684.                            &s,xxstring)) < 0)
  9685.               return(y);
  9686.             if (tn_term) {
  9687.                 free(tn_term);          /* Free any previous storage */
  9688.                 tn_term = NULL;
  9689.             }
  9690.             if (s == NULL || *s == NUL) { /* If none given */
  9691.                 tn_term = NULL;         /* remove the override string */
  9692.                 return(success = 1);
  9693.             } else if ((tn_term = malloc(strlen(s)+1))) {
  9694.                 strcpy(tn_term,s);
  9695.                 return(success = 1);
  9696.             } else return(success = 0);
  9697.  
  9698. #ifdef CK_FORWARD_X
  9699.           case CK_TN_FX:                /* FORWARD-X */
  9700.             if ((x=cmkey(tnfwdxtab,ntnfwdx,"","xauthority-file",xxstring)) < 0)
  9701.               return(x);
  9702.             switch (x) {
  9703.               case 0: {                 /* Xauthority-File */
  9704.                   x = cmifi("Full path of .Xauthority file","",&s,&y,xxstring);
  9705.                   if (x < 0 && x != -3)
  9706.                     return(x);
  9707.                   makestr(&tn_fwdx_xauthority,s);
  9708.                   return(success = 1);
  9709.               }
  9710.               case 1: {                 /* No-Encryption */
  9711.                   extern int fwdx_no_encrypt;
  9712.                   return(success = seton(&fwdx_no_encrypt));
  9713.               }
  9714.             }
  9715.             return(success = 0);
  9716. #endif /* CK_FORWARD_X */
  9717.  
  9718.           case CK_TN_NL:                /* TELNET NEWLINE-MODE */
  9719.             if ((x = cmkey(tn_nlmtab,ntn_nlm,"","nvt",xxstring)) < 0)
  9720.               return(x);
  9721.             if (x == TN_NL_BIN) {
  9722.               if ((x = cmkey(tnlmtab,ntnlm,"","raw",xxstring)) < 0)
  9723.                 return(x);
  9724.               if ((y = cmcfm()) < 0)
  9725.                 return(y);
  9726.               tn_b_nlm = x;
  9727.               return(success = 1);
  9728.           } else if (x == TN_NL_NVT) {
  9729.               if ((x = cmkey(tnlmtab,ntnlm,"","on",xxstring)) < 0)
  9730.                 return(x);
  9731.               if ((y = cmcfm()) < 0)
  9732.                 return(y);
  9733.               tn_nlm = x;
  9734.               return(success = 1);
  9735.           } else {
  9736.               if ((y = cmcfm()) < 0)
  9737.                 return(y);
  9738.               tn_nlm = x;
  9739.               return(success = 1);
  9740.           }
  9741.  
  9742.         case CK_TN_XF:                  /* BINARY-TRANSFER-MODE */
  9743.             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
  9744.             if ((y = cmcfm()) < 0) return(y);
  9745.             tn_b_xfer = z;
  9746.             return(success = 1);
  9747.  
  9748.         case CK_TN_NE:                  /* NO-ENCRYPT-DURING-XFER */
  9749.             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
  9750.             if ((y = cmcfm()) < 0) return(y);
  9751. #ifdef CK_APC
  9752.             /* Don't let this be set remotely */
  9753.             if (apcactive == APC_LOCAL ||
  9754.                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
  9755.               return(success = 0);
  9756. #endif /* CK_APC */
  9757.             tn_no_encrypt_xfer = z;
  9758.             return(success = 1);
  9759.  
  9760.           case CK_TN_BM:                /* BINARY-MODE */
  9761.             if ((x = cmkey(tnnegtab,ntnnegtab,"","refused",xxstring)) < 0)
  9762.               return(x);
  9763.             if ((y = cmcfm()) < 0)
  9764.               return(y);
  9765.             TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = x;
  9766.             TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = x;
  9767.             TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = x;
  9768.             TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = x;
  9769.             return(success = 1);
  9770.  
  9771. #ifdef IKS_OPTION
  9772.           case CK_TN_IKS:               /* KERMIT */
  9773.             if ((x = cmkey(tnnegtab,ntnnegtab,"DO","accept",xxstring)) < 0)
  9774.               return(x);
  9775.             if ((y = cmkey(tnnegtab,ntnnegtab,"WILL","accept",xxstring)) < 0)
  9776.               return(y);
  9777.             if ((z = cmcfm()) < 0)
  9778.               return(z);
  9779.             TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = y;
  9780.             TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = x;
  9781.             TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = y;
  9782.             TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = x;
  9783.             return(success = 1);
  9784. #endif /* IKS_OPTION */
  9785.  
  9786. #ifdef CK_SSL
  9787.           case CK_TN_TLS:               /* START_TLS */
  9788.             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
  9789.               return(x);
  9790.             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
  9791.               return(y);
  9792.             if ((z = cmcfm()) < 0)
  9793.               return(z);
  9794.             TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = x;
  9795.             TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = y;
  9796.             TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = x;
  9797.             TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = y;
  9798.             return(success = 1);
  9799. #endif /* CK_SSL */
  9800.  
  9801. #ifdef CK_NAWS
  9802.           case CK_TN_NAWS:              /* NAWS */
  9803.             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
  9804.               return(x);
  9805.             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
  9806.               return(y);
  9807.             if ((z = cmcfm()) < 0)
  9808.               return(z);
  9809.             TELOPT_DEF_S_ME_MODE(TELOPT_NAWS) = x;
  9810.             TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = y;
  9811.             TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = x;
  9812.             TELOPT_DEF_C_U_MODE(TELOPT_NAWS) = y;
  9813.             return(success = 1);
  9814. #endif /* CK_NAWS */
  9815.  
  9816. #ifdef CK_AUTHENTICATION
  9817.           case CK_TN_AU:                /* AUTHENTICATION */
  9818.             if ((x = cmkey(tnauthtab,ntnauth,"","",xxstring)) < 0)
  9819.               return(x);
  9820.             if (x == TN_AU_FWD) {
  9821.                 extern int forward_flag;
  9822.                 return(success = seton(&forward_flag));
  9823.             } else if (x == TN_AU_TYP) {
  9824.                 extern int auth_type_user[];
  9825.                 extern int sl_auth_type_user[];
  9826.                 extern int sl_auth_saved;
  9827.                 int i, j, atypes[AUTHTYPLSTSZ];
  9828.  
  9829.                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
  9830.                     if ((y = cmkey(autyptab,nautyp,"",
  9831.                                    i == 0 ? "automatic" : "" ,
  9832.                                    xxstring)) < 0) {
  9833.                         if (y == -3)
  9834.                           break;
  9835.                         return(y);
  9836.                     }
  9837.                     if (i > 0 && (y == AUTHTYPE_AUTO || y == AUTHTYPE_NULL)) {
  9838.                         printf(
  9839.                         "\r\n?Choice may only be used in first position.\r\n");
  9840.                         return(-9);
  9841.                     }
  9842.                     for (j = 0; j < i; j++) {
  9843.                         if (atypes[j] == y) {
  9844.                             printf("\r\n?Choice has already been used.\r\n");
  9845.                             return(-9);
  9846.                         }
  9847.                     }
  9848.                     atypes[i] = y;
  9849.                     if (y == AUTHTYPE_NULL || y == AUTHTYPE_AUTO) {
  9850.                         i++;
  9851.                         break;
  9852.                     }
  9853.                 }
  9854.                 if (i < AUTHTYPLSTSZ)
  9855.                   atypes[i] = AUTHTYPE_NULL;
  9856.                 if ((z = cmcfm()) < 0)
  9857.                   return(z);
  9858.                 sl_auth_saved = 0;
  9859.                 for (i = 0; i < AUTHTYPLSTSZ; i++) {
  9860.                     auth_type_user[i] = atypes[i];
  9861.                     sl_auth_type_user[i] = 0;
  9862.                 }
  9863.             } else if (x == TN_AU_HOW) {
  9864.                 if ((y = cmkey(auhowtab,nauhow,"","any",xxstring)) < 0)
  9865.                   return(y);
  9866.                 if ((z = cmcfm()) < 0)
  9867.                   return(z);
  9868.                 tn_auth_how = y;
  9869.             } else if (x == TN_AU_ENC) {
  9870.                 if ((y = cmkey(auenctab,nauenc,"","encrypt",xxstring)) < 0)
  9871.                   return(y);
  9872.                 if ((z = cmcfm()) < 0)
  9873.                   return(z);
  9874.                 tn_auth_enc = y;
  9875.             } else {
  9876.                 if ((y = cmcfm()) < 0)
  9877.                   return(y);
  9878.                 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = x;
  9879.                 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = x;
  9880.             }
  9881.             return(success = 1);
  9882. #endif /* CK_AUTHENTICATION */
  9883.  
  9884. #ifdef CK_ENCRYPTION
  9885.           case CK_TN_ENC: {             /* ENCRYPTION */
  9886.               int c, tmp = -1;
  9887.               int getval = 0;
  9888.               static struct keytab * tnetbl = NULL;
  9889.               static int ntnetbl = 0;
  9890.  
  9891.               if ((y = cmkey(tnenctab,ntnenc,"","",xxstring)) < 0)
  9892.                 return(y);
  9893.               switch (y) {
  9894.                 case TN_EN_TYP:
  9895.                   x = ck_get_crypt_table(&tnetbl,&ntnetbl);
  9896.                   debug(F101,"ck_get_crypt_table x","",x);
  9897.                   debug(F101,"ck_get_crypt_table n","",ntnetbl);
  9898.                   if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
  9899.                     x = 0;
  9900.                   if (!x) {
  9901.                       printf("?Oops, types not loaded\n");
  9902.                       return(-9);
  9903.                   }
  9904.                   if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
  9905.                                  "automatic",xxstring)) < 0)
  9906.                     return(x);
  9907.                   if ((z = cmcfm()) < 0)
  9908.                     return(z);
  9909.                   cx_type = x;
  9910.                   sl_cx_type = 0;
  9911.                   break;
  9912.                 case TN_EN_START:
  9913.                   if ((z = cmcfm()) < 0)
  9914.                     return(z);
  9915. #ifdef CK_APC
  9916.                   /* Don't let this be set remotely */
  9917.                   if (apcactive == APC_LOCAL ||
  9918.                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
  9919.                     return(success = 0);
  9920. #endif /* CK_APC */
  9921.                   ck_tn_enc_start();
  9922.                   break;
  9923.                 case TN_EN_STOP:
  9924.                   if ((z = cmcfm()) < 0)
  9925.                     return(z);
  9926. #ifdef CK_APC
  9927.                   /* Don't let this be set remotely */
  9928.                   if (apcactive == APC_LOCAL ||
  9929.                       apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
  9930.                     return(success = 0);
  9931. #endif /* CK_APC */
  9932.                   ck_tn_enc_stop();
  9933.                   break;
  9934.                 default:
  9935.                   if ((z = cmcfm()) < 0)
  9936.                     return(z);
  9937.                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = y;
  9938.                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = y;
  9939.                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = y;
  9940.                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = y;
  9941.               }
  9942.               return(success = 1);
  9943.           }
  9944. #endif /* CK_ENCRYPTION */
  9945.  
  9946.           case CK_TN_BUG:               /* BUG */
  9947.             if ((x = cmkey(tnbugtab,4,"",
  9948.                            "binary-me-means-u-too",xxstring)) < 0)
  9949.               return(x);
  9950.             if ((z = cmkey(onoff,2,"","off",xxstring)) < 0) return(z);
  9951.             if ((y = cmcfm()) < 0) return(y);
  9952.             switch (x) {
  9953.               case 0:
  9954.                 tn_b_meu = z;
  9955.                 break;
  9956.               case 1:
  9957.                 tn_b_ume = z;
  9958.                 break;
  9959.               case 2:
  9960.                 tn_infinite = z;
  9961.                 break;
  9962.               case 3:
  9963.                 tn_sb_bug = z;
  9964.                 break;
  9965.             }
  9966.             return(success = 1);
  9967.  
  9968. #ifdef CK_ENVIRONMENT
  9969.           case CK_TN_XD:                /* XDISPLOC */
  9970.             if ((x = cmkey(tnnegtab,ntnnegtab,"me","accept",xxstring)) < 0)
  9971.               return(x);
  9972.             if ((y = cmkey(tnnegtab,ntnnegtab,"u","accept",xxstring)) < 0)
  9973.               return(y);
  9974.             if ((z = cmcfm()) < 0)
  9975.               return(z);
  9976.             TELOPT_DEF_S_ME_MODE(TELOPT_XDISPLOC) = x;
  9977.             TELOPT_DEF_S_U_MODE(TELOPT_XDISPLOC) = y;
  9978.             TELOPT_DEF_C_ME_MODE(TELOPT_XDISPLOC) = x;
  9979.             TELOPT_DEF_C_U_MODE(TELOPT_XDISPLOC) = y;
  9980.             return(success = 1);
  9981.  
  9982.           case CK_TN_ENV: {
  9983.               char * msg = "value of telnet environment variable";
  9984.               extern int tn_env_flg;
  9985.               extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
  9986.               tn_env_prnt[], tn_env_sys[];
  9987.               extern char * tn_loc;
  9988.               if ((x = cmkey(tnenvtab,ntnenv,"","",xxstring)) < 0)
  9989.                 return(x);
  9990.               if (x == TN_ENV_UVAR) {   /* User variables */
  9991.                   char * uvar=NULL;
  9992.                   char * uval=NULL;
  9993.                   char * env;
  9994.                   extern char * tn_env_uservar[8][2];
  9995.  
  9996.                   /* Get the user variable name */
  9997.                   if ((x = cmfld("Name of Environment Variable","",&s,
  9998.                                  xxstring)) < 0)
  9999.                     return(x);
  10000.                   makestr(&uvar,s);
  10001.  
  10002.                   env = getenv(uvar);
  10003.                   if (!env) env = "";
  10004.  
  10005.                   if ((x = cmtxt("Value of Environment Variable",env,
  10006.                                  &s,xxstring)) < 0)
  10007.                     return(x);
  10008.                   if (*s)
  10009.                     makestr(&uval,s);
  10010.  
  10011.                   /* Now that we have the variable and perhaps a value */
  10012.                   /* there are three possibilities: (1) new variable   */
  10013.                   /* and associated value; (2) variable already exists */
  10014.                   /* but we have a new value; (3) variable already     */
  10015.                   /* exists but no new value therefore the user wants  */
  10016.                   /* to clear variable.                                */
  10017.  
  10018.                   /* Try to find an existing variable */
  10019.                   for (x = 0; x < 8; x++) {
  10020.                       if (!ckstrcmp(tn_env_uservar[x][0],uvar,-1,0)) {
  10021.                           if (uval) {
  10022.                               free(tn_env_uservar[x][1]);
  10023.                               tn_env_uservar[x][1] = uval;
  10024.                               free(uvar);
  10025.                               return(success = 1);
  10026.                           } else {
  10027.                               free(tn_env_uservar[x][0]);
  10028.                               tn_env_uservar[x][0] = NULL;
  10029.                               free(tn_env_uservar[x][1]);
  10030.                               tn_env_uservar[x][1] = NULL;
  10031.                               free(uvar);
  10032.                               return(success = 1);
  10033.                           }
  10034.                       }
  10035.                   }
  10036.  
  10037.                   /* Couldn't find one; look for empty location to insert */
  10038.                   for (x = 0; x < 8; x++) {
  10039.                       if (!tn_env_uservar[x][0]) {
  10040.                           tn_env_uservar[x][0] = uvar;
  10041.                           tn_env_uservar[x][1] = uval;
  10042.                           return(success = 1);
  10043.                       }
  10044.                   }
  10045.                   printf("?Sorry, no space for variable.\n");
  10046.                   return(success = 0);
  10047.               }
  10048.               if (x == TN_ENV_OFF || x == TN_ENV_ON) {
  10049.                   if ((y = cmcfm()) < 0) return(y);
  10050. #ifdef IKSD
  10051.                   if (inserver) {
  10052.                       printf("?Sorry, command disabled.\r\n");
  10053.                       return(success = 0);
  10054.                   }
  10055. #endif /* IKSD */
  10056.                   tn_env_flg = x == TN_ENV_OFF ? 0 : 1;
  10057.                   return(success = 1);
  10058.               }
  10059.  
  10060.               /* Not ON/OFF - Get the value */
  10061.               z = cmdgquo();
  10062.               cmdsquo(0);
  10063.               if ((y = cmtxt(msg, "", &s, xxstring)) < 0) {
  10064.                   cmdsquo(z);
  10065.                   return(y);
  10066.               }
  10067.               cmdsquo(z);
  10068. #ifdef IKSD
  10069.               if (inserver)
  10070.                 return(success = 0);
  10071. #endif /* IKSD */
  10072.               if ((int)strlen(s) > 63) {
  10073.                   printf("Sorry, too long\n");
  10074.                   return(-9);
  10075.               }
  10076.               switch (x) {
  10077.                 case TN_ENV_USR:
  10078.                   ckstrncpy(uidbuf,s,UIDBUFLEN);
  10079.                   sl_uid_saved = 0;
  10080.                   break;
  10081.                 case TN_ENV_ACCT:
  10082.                   ckstrncpy(tn_env_acct,s,64);
  10083.                   break;
  10084.                 case TN_ENV_DISP:
  10085.                   ckstrncpy(tn_env_disp,s,64);
  10086.                   break;
  10087.                 case TN_ENV_JOB:
  10088.                   ckstrncpy(tn_env_job,s,64);
  10089.                   break;
  10090.                 case TN_ENV_PRNT:
  10091.                   ckstrncpy(tn_env_prnt,s,64);
  10092.                   break;
  10093.                 case TN_ENV_SYS:
  10094.                   ckstrncpy(tn_env_sys,s,64);
  10095.                   break;
  10096.                 case TN_ENV_LOC:
  10097.                   if (!*s) s = NULL;
  10098.                   makestr(&tn_loc,s);
  10099.                   break;
  10100.                 case TN_ENV_UVAR:
  10101.                   printf("\n?Not yet implemented\n");
  10102.                   break;
  10103.               }
  10104.               return(success = 1);
  10105.           }
  10106. #endif /* CK_ENVIRONMENT */
  10107.  
  10108. #ifdef CK_SNDLOC
  10109.           case CK_TN_LOC: {             /* LOCATION */
  10110.               extern char * tn_loc;
  10111.               if ((y = cmtxt("Location string","",&s,xxstring)) < 0)
  10112.                 return(y);
  10113.               if (!*s) s = NULL;
  10114.               makestr(&tn_loc,s);
  10115.               return(success = 1);
  10116.           }
  10117. #endif /* CK_SNDLOC */
  10118.           case CK_TN_SFU:               /* Microsoft SFU compatibility */
  10119.             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
  10120.             if ((y = cmcfm()) < 0) return(y);
  10121.             tn_sfu = z;
  10122.             return(success = 1);
  10123.             break;
  10124.  
  10125.           case CK_TN_WAIT:              /* WAIT-FOR-NEGOTIATIONS */
  10126.             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
  10127.             if ((y = cmcfm()) < 0) return(y);
  10128. #ifdef IKSD
  10129.             if (inserver &&
  10130. #ifdef IKSDCONF
  10131.                 iksdcf
  10132. #else
  10133.                 1
  10134. #endif /* IKSDCONF */
  10135.                 ) {
  10136.                 printf("?Sorry, command disabled.\r\n");
  10137.                 return(success = 0);
  10138.             }
  10139. #endif /* IKSD */
  10140.             tn_wait_flg = z;
  10141.             sl_tn_saved = 0;
  10142.             return(success = 1);
  10143.  
  10144.           case CK_TN_DL:                /* DELAY SUBNEGOTIATIONS */
  10145.             if ((z = cmkey(onoff,2,"","on",xxstring)) < 0) return(z);
  10146.             if ((y = cmcfm()) < 0) return(y);
  10147. #ifdef IKSD
  10148.             if (inserver &&
  10149. #ifdef IKSDCONF
  10150.                 iksdcf
  10151. #else
  10152.                 1
  10153. #endif /* IKSDCONF */
  10154.                 ) {
  10155.                 printf("?Sorry, command disabled.\r\n");
  10156.                 return(success = 0);
  10157.             }
  10158. #endif /* IKSD */
  10159.             tn_delay_sb = z;
  10160.             return(success = 1);
  10161.  
  10162.           case CK_TN_PUID: {            /* PROMPT-FOR-USERID */
  10163.               int i,len;
  10164.               if ((y = cmtxt("Prompt string","",&s,xxstring)) < 0)
  10165.                 return(y);
  10166.               if (s == "") s = NULL;
  10167.               if (s) {
  10168.                   s = brstrip(s);
  10169.                   if (s == "") s = NULL;
  10170.               }
  10171.               /* we must check to make sure there are no % fields */
  10172.               len = strlen(s);
  10173.               for (i = 0; i < len; i++) {
  10174.                   if (s[i] == '%') {
  10175.                       if (s[i+1] != '%') {
  10176.                           printf("%% fields are not used in this command.\n");
  10177.                           return(-9);
  10178.                       }
  10179.                       i++;
  10180.                   }
  10181.               }
  10182.               makestr(&tn_pr_uid,s);
  10183.               return(success = 1);
  10184.           }
  10185.           default:
  10186.             return(-2);
  10187.         }
  10188.     }
  10189. #endif /* TNCODE */
  10190.  
  10191.     switch (xx) {
  10192. #ifndef NOSPL
  10193.       case XYCOUN:                      /* SET COUNT */
  10194.         x = cmnum("Positive number","0",10,&z,xxstring);
  10195.         if (x < 0) return(x);
  10196.         if ((x = cmcfm()) < 0) return(x);
  10197.         if (z < 0) {
  10198.             printf("?A positive number, please\n");
  10199.             return(0);
  10200.         }
  10201.         debug(F101,"XYCOUN: z","",z);
  10202.         return(success = setnum(&count[cmdlvl],z,0,10000));
  10203. #endif /* NOSPL */
  10204.  
  10205. #ifndef NOSPL
  10206.       case XYCASE:
  10207.         return(success = seton(&inpcas[cmdlvl]));
  10208. #endif /* NOSPL */
  10209.  
  10210.       case XYCMD:                       /* COMMAND ... */
  10211.         if ((y = cmkey(scmdtab,nbytt,"","",xxstring)) < 0)
  10212.           return(y);
  10213.         switch (y) {
  10214.           case SCMD_CBR:
  10215.             if ((y = cmcfm()) < 0)
  10216.               return(y);
  10217.             concb((char)escape);
  10218.             return(success = 1);
  10219.  
  10220.           case SCMD_BSZ:
  10221.             if ((y = cmnum("bytesize for command characters, 7 or 8","7",10,&x,
  10222.                            xxstring)) < 0)
  10223.               return(y);
  10224.             if (x != 7 && x != 8) {
  10225.                 printf("\n?The choices are 7 and 8\n");
  10226.                 return(success = 0);
  10227.             }
  10228.             if ((y = cmcfm()) < 0) return(y);
  10229.             if (x == 7) cmdmsk = 0177;
  10230.             else if (x == 8) cmdmsk = 0377;
  10231.             return(success = 1);
  10232. #ifdef CK_RECALL
  10233.           case SCMD_RCL:
  10234.             if ((y = cmnum("maximum number of commands in recall buffer","10",
  10235.                            10,&x,xxstring)) < 0)
  10236.               return(y);
  10237.             if ((y = cmcfm()) < 0) return(y);
  10238.             return(success = cmrini(x));
  10239. #endif /* CK_RECALL */
  10240. #ifdef CK_RECALL
  10241.           case SCMD_RTR:
  10242.             return(success = seton(&cm_retry));
  10243. #endif /* CK_RECALL */
  10244.           case SCMD_MOR:                /* More-prompting */
  10245.             success = seton(&xaskmore);
  10246.             if (success)
  10247.               saveask = xaskmore;
  10248.             return(success);
  10249.           case SCMD_QUO:
  10250.             if ((x = seton(&y)) < 0) return(x);
  10251.             cmdsquo(y);                 /* Do it the right way */
  10252.             cmd_quoting = y;            /* Also keep a global copy */
  10253.             /* Set string-processing function */
  10254. #ifdef datageneral
  10255.             xxstring = y ? zzstring : (xx_strp) NULL;
  10256. #else
  10257. #ifdef CK_ANSIC
  10258.             xxstring = y ? zzstring : (xx_strp) NULL;
  10259. #else
  10260.             xxstring = y ? zzstring : (xx_strp) NULL;
  10261. #endif /* CK_ANSIC */
  10262. #endif /* datageneral */
  10263.             return(success = 1);
  10264.  
  10265. #ifdef OS2
  10266. #ifndef NOLOCAL
  10267.           case SCMD_COL: {              /* Command-screen colors */
  10268.               int fg, bg;
  10269.               fg = cmkey(ttyclrtab, nclrs,
  10270.                          "foreground color and then background color",
  10271.                          "white",
  10272.                          xxstring);
  10273.               if (fg < 0)
  10274.                 return(fg);
  10275.               if ((bg = cmkey(ttyclrtab,nclrs,
  10276.                               "background color","black",xxstring)) < 0)
  10277.                 return(bg);
  10278.               if ((y = cmcfm()) < 0)
  10279.                 return(y);
  10280.               colorcmd = fg | bg << 4;
  10281.               return(success = 1);
  10282.           }
  10283.           case SCMD_SCR:                /* Command Scrollback size */
  10284.             if ((y = cmnum("COMMAND scrollback buffer size, lines","512",10,&x,
  10285.                            xxstring)) < 0)
  10286.               return(y);
  10287.             /* The max number of lines is the RAM  */
  10288.             /* we can actually dedicate to a       */
  10289.             /* scrollback buffer given the maximum */
  10290.             /* process memory space of 512MB       */
  10291.             if (x < 256 || x > 2000000L) {
  10292.                 printf("\n?The size must be between 256 and 2,000,000.\n");
  10293.                 return(success = 0);
  10294.             }
  10295.             if ((y = cmcfm()) < 0) return(y);
  10296.             tt_scrsize[VCMD] = x;
  10297.             VscrnInit( VCMD );
  10298.             return(success = 1);
  10299.  
  10300.           case SCMD_WID: {
  10301.               if ((y = cmnum("Number of columns in display window",
  10302.                          "80",10,&x,xxstring)) < 0)
  10303.                 return(y);
  10304.               if ((y = cmcfm()) < 0) return(y);
  10305.  
  10306.               os2_setcmdwidth(x);
  10307.               return(success = 1);
  10308.           }
  10309.           case SCMD_HIG:
  10310.             if ((y = cmnum("Number of rows in display window",
  10311.                            "24",10,&x,xxstring)) < 0)
  10312.               return(y);
  10313.             if ((y = cmcfm()) < 0) return(y);
  10314.             os2_setcmdheight(x);
  10315.             return(success = 1);
  10316.  
  10317.           case SCMD_STA: {
  10318.               extern int marginbot;
  10319.               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  10320.               if ((x = cmcfm()) < 0) return(x);
  10321.               if (y != tt_status[VCMD]) {
  10322.                   /* Might need to fixup the margins */
  10323.                   tt_status[VCMD] = y;
  10324.                   if (y) {
  10325.                       tt_szchng[VCMD] = 2;
  10326.                       tt_rows[VCMD]--;
  10327.                       cmd_rows--;
  10328.                       VscrnInit(VCMD);  /* Height set here */
  10329.                       printf("\n");
  10330.                   } else {
  10331.                       tt_szchng[VCMD] = 1;
  10332.                       tt_rows[VCMD]++;
  10333.                       cmd_rows++;
  10334.                       VscrnInit(VCMD);  /* Height set here */
  10335.                   }
  10336.               }
  10337.               return(success = 1);
  10338.           }
  10339.  
  10340.           case SCMD_CUR: {
  10341.               int row, col;
  10342.               position * ppos;
  10343.  
  10344.               ppos = VscrnGetCurPos(VCMD);
  10345. #ifdef NT
  10346. #define itoa _itoa
  10347. #endif /* NT */
  10348.               itoa(ppos->y+1, tmpbuf, 10);
  10349.               if ((y = cmnum("row (1-based)",tmpbuf,10,&row,xxstring)) < 0)
  10350.                 return(y);
  10351.  
  10352.               itoa(ppos->x+1, tmpbuf, 10);
  10353.               if ((y = cmnum("col (1-based)",tmpbuf,10,&col,xxstring)) < 0)
  10354.                 return(y);
  10355.               if ((x = cmcfm()) < 0) return(x);
  10356.  
  10357.               lgotoxy( VCMD, col, row ) ;
  10358.               VscrnIsDirty( VCMD );
  10359.               return(success=1);
  10360.           }
  10361. #endif /* NOLOCAL */
  10362. #else
  10363.           case SCMD_WID:
  10364.             y = cmnum("Command screen width, characters","80",10,&x,xxstring);
  10365.             return(setnum(&cmd_cols,x,y,1024));
  10366.  
  10367.           case SCMD_HIG:
  10368.             y = cmnum("Command screen height, rows","24",10,&x,xxstring);
  10369.             return(setnum(&cmd_rows,x,y,1024));
  10370. #endif /* OS2 */
  10371.  
  10372.           case SCMD_INT:
  10373.             return(seton(&cmdint));
  10374.  
  10375. #ifdef CK_AUTODL
  10376.           case SCMD_ADL:
  10377.             return(seton(&cmdadl));
  10378. #endif /* CK_AUTODL */
  10379.  
  10380. #ifdef DOUBLEQUOTING
  10381.           case SCMD_DBQ: {
  10382.               extern int dblquo;
  10383.               return(seton(&dblquo));
  10384.           }
  10385. #endif /* DOUBLEQUOTING */
  10386.  
  10387.           default:
  10388.             return(-2);
  10389.         }
  10390.     }
  10391.  
  10392.     switch (xx) {
  10393.  
  10394.       case XYDFLT:                      /* SET DEFAULT = CD */
  10395.         return(success = docd(XXCWD));
  10396.  
  10397. case XYDEBU:                            /* SET DEBUG { on, off, session } */
  10398.         if ((y = cmkey(dbgtab,ndbg,"","",xxstring)) < 0)
  10399.           return(y);
  10400.         if (y == DEB_TIM)
  10401. #ifdef COMMENT
  10402.           return(seton(&debtim) < 0 ? x : (success = 1));
  10403. #else
  10404.           /* why this change? */
  10405.           return(success = seton(&debtim));
  10406. #endif /* COMMENT */
  10407.  
  10408. #ifdef IKSD
  10409.         if (inserver && isguest) {
  10410.             printf("?Sorry, command disabled.\r\n");
  10411.             return(success = 0);
  10412.     }
  10413. #endif /* IKSD */
  10414.  
  10415.         switch (y) {
  10416.           case DEB_LEN:
  10417.             y = cmnum("Max length for debug log strings","",10,&x,xxstring);
  10418.             if ((z = setnum(&debxlen,x,y,-1)) < 0)
  10419.               return(z);
  10420.             if ((x = cmcfm()) < 0)
  10421.               return(x);
  10422.             return(success = 1);
  10423.  
  10424.           case DEB_OFF:
  10425.             if ((x = cmcfm()) < 0)
  10426.               return(x);
  10427. #ifndef NOLOCAL
  10428.             setdebses(0);
  10429. #endif /* NOLOCAL */
  10430. #ifdef DEBUG
  10431.             if (deblog) doclslog(LOGD);
  10432. #endif /* DEBUG */
  10433.             return(success = 1);
  10434.  
  10435.           case DEB_ON:
  10436.             if ((x = cmcfm()) < 0)
  10437.               return(x);
  10438. #ifdef DEBUG
  10439.             deblog = debopn("debug.log", 0);
  10440.             return(success = deblog ? 1 : 0);
  10441. #else
  10442.             printf("?Sorry, debug log feature not enabled\n");
  10443.             return(success = 0);
  10444. #endif /* DEBUG */
  10445.           case DEB_SES:
  10446.             if ((x = cmcfm()) < 0)
  10447.               return(x);
  10448. #ifndef NOLOCAL
  10449.             setdebses(1);
  10450. #endif /* NOLOCAL */
  10451.             return(success = 1);
  10452.         }
  10453.         break;
  10454.  
  10455. #ifndef NOXFER
  10456.       case XYDELA:                      /* SET DELAY */
  10457.         y = cmnum("Number of seconds before starting to send",
  10458.                   "5",10,&x,xxstring);
  10459.         if (x < 0) x = 0;
  10460.         return(success = setnum(&ckdelay,x,y,999));
  10461. #endif /* NOXFER */
  10462.  
  10463.       default:
  10464.         break;
  10465.     }
  10466.  
  10467.     switch (xx) {
  10468. #ifndef NODIAL
  10469. #ifdef CK_TAPI
  10470.       case XYTAPI:
  10471.         return(settapi());
  10472. #endif /* CK_TAPI */
  10473.       case XYDIAL:                      /* SET MODEM or SET DIAL */
  10474.         return(setdial(-1));
  10475.       case XYMODM:
  10476.         return(setmodem());
  10477. #ifdef COMMENT
  10478.       /* not implemented yet */
  10479.       case XYANSWER:                    /* SET ANSWER */
  10480.         return(setanswer());
  10481. #endif /* COMMENT */
  10482. #endif /* NODIAL */
  10483.  
  10484. #ifndef NOLOCAL
  10485.       case XYDUPL:                      /* SET DUPLEX */
  10486.         if ((y = cmkey(dpxtab,2,"","full",xxstring)) < 0) return(y);
  10487.         if ((x = cmcfm()) < 0) return(x);
  10488.         duplex = y;
  10489.         return(success = 1);
  10490.  
  10491.       case XYLCLE:                      /* LOCAL-ECHO (= DUPLEX) */
  10492.         return(success = seton(&duplex));
  10493.  
  10494.       case XYESC:                       /* SET ESCAPE */
  10495.         return(success = setcc(ckitoa(DFESC),&escape));
  10496. #endif /* NOLOCAL */
  10497.  
  10498.       case XYEXIT:                      /* SET EXIT */
  10499.         if ((z = cmkey(xittab,nexit,"","",xxstring)) < 0)
  10500.           return(z);
  10501.         switch (z) {
  10502.           case 0:                       /* STATUS */
  10503.             y = cmnum("EXIT status code","",10,&x,xxstring);
  10504.             return(success = setnum(&xitsta,x,y,-1));
  10505.           case 1:                       /* WARNING */
  10506.             if ((z = cmkey(xitwtab,nexitw,"","",xxstring)) < 0)
  10507.               return(z);
  10508.             if ((y = cmcfm()) < 0) return(y);
  10509.             setexitwarn(z);
  10510.             return(success = 1);
  10511.           case 2:
  10512.             success = seton(&exitonclose);
  10513. #ifdef TCPSOCKET
  10514.             if (success) tn_exit = exitonclose;
  10515. #endif /* TCPSOCKET */
  10516.             return(success);
  10517.           case 3: {
  10518.               extern int exithangup;
  10519.               return((success = seton(&exithangup)));
  10520.           }
  10521.           default:
  10522.             return(-2);
  10523.         } /* End of SET EXIT switch() */
  10524.       default:
  10525.         break;
  10526.     }
  10527.  
  10528.     switch (xx) {
  10529.  
  10530.       case XYFILE:                      /* SET FILE */
  10531.         return(setfil(rmsflg));
  10532.  
  10533.       case XYFLOW: {                    /* FLOW-CONTROL */
  10534.           extern int cxflow[];
  10535.           struct FDB k1, k2;
  10536.           int tncomport = 0;
  10537.           char * m;
  10538.  
  10539. #ifdef TN_COMPORT
  10540.           if (network && istncomport())
  10541.             tncomport = 1;
  10542. #endif /* TN_COMPORT */
  10543.  
  10544.           if (tncomport) {
  10545.               m = "Flow control type, one of the following:\n\
  10546.    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
  10547.  or connection type";
  10548.           } else {
  10549.           /* All this is because chained FDB's don't give chained help yet */
  10550.               m =
  10551. #ifdef Plan9
  10552. #ifdef CK_RTSCTS
  10553.            "Flow control type, one of the following:\n\
  10554.    keep   none    rts/cts\n\
  10555.  or connection type",
  10556. #else
  10557.            "Flow control type, one of the following:\n\
  10558.    keep   none\n\
  10559.  or connection type";
  10560. #endif /* CK_RTSCTS */
  10561. #else
  10562. #ifdef CK_RTSCTS
  10563. #ifdef CK_DTRCD
  10564. #ifdef CK_DTRCTS
  10565.            "Flow control type, one of the following:\n\
  10566.    dtr/cd    dtr/cts   keep    none    rts/cts   xon/xoff\n\
  10567.  or connection type";
  10568. #else /* CK_DTRCTS */
  10569.            "Flow control type, one of the following:\n\
  10570.    dtr/cd    keep    none    rts/cts   xon/xoff\n\
  10571.             or connection type";
  10572. #endif /* CK_DTRCTS */
  10573. #else /* CK_DTRCD */
  10574. #ifdef CK_DTRCTS
  10575.            "Flow control type, one of the following:\n\
  10576.    dtr/cts   keep   none    rts/cts   xon/xoff\n\
  10577.  or connection type";
  10578. #else /* CK_DTRCTS */
  10579.            "Flow control type, one of the following:\n\
  10580.    keep   none    rts/cts   xon/xoff\n\
  10581.  or connection type";
  10582. #endif /* CK_DTRCTS */
  10583. #endif /* CK_DTRCD */
  10584. #else
  10585.            "Flow control type, one of the following:\n\
  10586.    keep   none    xon/xoff\n\
  10587.  or connection type";
  10588. #endif /* CK_RTSCTS */
  10589. #endif /* Plan9 */
  10590.           }
  10591.           cmfdbi(&k1,_CMKEY,m,"","",ncxtypesw, 4, xxstring, cxtypesw, &k2);
  10592.           cmfdbi(&k2,
  10593.                  _CMKEY,
  10594.                  "",
  10595.                  "",
  10596.                  "",
  10597. #ifdef TN_COMPORT
  10598.                  (tncomport ? ntnflo : nflo),
  10599. #else
  10600.                  nflo,
  10601. #endif /* TN_COMPORT */
  10602.                  0,
  10603.                  xxstring,
  10604. #ifdef TN_COMPORT
  10605.                  (tncomport ? tnflotab : flotab),
  10606. #else
  10607.                  flotab,
  10608. #endif /* TN_COMPORT */
  10609.                  NULL
  10610.                  );
  10611.           x = cmfdb(&k1);
  10612.           if (x < 0) {                  /* Error */
  10613.               if (x == -2 || x == -9)
  10614.                 printf("?No keywords or switches match: \"%s\"\n",atmbuf);
  10615.               return(x);
  10616.           }
  10617.           z = cmresult.nresult;         /* Keyword value */
  10618.           if (cmresult.fdbaddr == &k2) { /* Flow-control type keyword table */
  10619.               if ((x = cmcfm()) < 0)    /* Set it immediately */
  10620.                 return(x);
  10621.               flow = z;
  10622.               debug(F101,"set flow","",flow);
  10623. #ifdef CK_SPEED
  10624.               if (flow == FLO_XONX)     /* Xon/Xoff forces prefixing */
  10625.                 ctlp[XON] = ctlp[XOFF] = ctlp[XON+128] = ctlp[XOFF+128] = 1;
  10626. #endif /* CK_SPEED */
  10627.               autoflow = (flow == FLO_AUTO);
  10628.               return(success = 1);      /* Done */
  10629.           }
  10630.           debug(F101,"set flow /blah 1","",z); /* SET FLOW /for-what */
  10631.           if ((y = cmkey(flotab,nflo,"Flow control type","none",xxstring)) < 0)
  10632.             return(y);
  10633.           if ((x = cmcfm()) < 0)
  10634.             return(x);
  10635.           debug(F101,"set flow /blah 2","",y);
  10636.           if (y == FLO_AUTO) {
  10637.               printf(
  10638.   "?Sorry, \"automatic\" can not be assigned to a connection type.\n");
  10639.               return(-9);
  10640.           } else if (z >= 0 && z <= CXT_MAX)
  10641.             cxflow[z] = y;
  10642.           debug(F101,"set flow","",flow);
  10643.           debug(F101,"set flow autoflow","",autoflow);
  10644.           return(success = 1);
  10645.       }
  10646.  
  10647.       case XYHAND:                      /* HANDSHAKE */
  10648.         if ((y = cmkey(hshtab,nhsh,"","none",xxstring)) < 0) return(y);
  10649.         if (y == 998) {
  10650.             if ((x = cmnum("ASCII value","",10,&y,xxstring)) < 0)
  10651.               return(x);
  10652.             if ((y < 1) || ((y > 31) && (y != 127))) {
  10653.                 printf("?Character must be in ASCII control range\n");
  10654.                 return(-9);
  10655.             }
  10656.         }
  10657.         if ((x = cmcfm()) < 0) return(x);
  10658.         turn = (y > 0127) ? 0 : 1;
  10659.         turnch = y;
  10660.         return(success = 1);
  10661.  
  10662. #ifndef NOSPL
  10663.       case XYMACR:                      /* SET MACRO */
  10664.         if ((y = cmkey(smactab,2,"","",xxstring)) < 0) return(y);
  10665.         switch (y) {
  10666.           case 0: return(success = seton(&mecho));
  10667.           case 1: return(success = seton(&merror[cmdlvl]));
  10668.           default: return(-2);
  10669.         }
  10670. #endif /* NOSPL */
  10671.  
  10672.       case XYMSGS:
  10673. #ifdef VMS
  10674.         if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
  10675.         if ((y = cmcfm()) < 0) return(y);
  10676.         vms_msgs = z;
  10677.         printf("Sorry, SET MESSAGES not implemented yet\n");
  10678.         return(success = 0);
  10679. #endif /* VMS */
  10680.       default:
  10681.         break;
  10682.     }
  10683.  
  10684.     switch (xx) {
  10685.  
  10686.       case XYPARI:                      /* PARITY */
  10687.         if ((y = cmkey(partbl,npar,"","none",xxstring)) < 0)
  10688.           return(y);
  10689.  
  10690.         /* If parity not none, then we also want 8th-bit prefixing */
  10691.  
  10692. #ifdef HWPARITY
  10693.         if (y == 'H') {                 /* Hardware */
  10694.             if ((x = cmkey(hwpartbl,nhwpar,"","even",xxstring)) < 0)
  10695.               return(x);
  10696.         }
  10697. #endif /* HWPARITY */
  10698.  
  10699.         if ((z = cmcfm()) < 0)
  10700.           return(z);
  10701.  
  10702. #ifdef HWPARITY
  10703.         if (y == 'H') {                 /* 8 data bits plus hardware parity */
  10704.             parity = 0;
  10705. #ifndef NOXFER
  10706.             ebqflg = 0;
  10707. #endif /* NOXFER */
  10708.             hwparity = x;
  10709.         } else {                        /* 7 data bits + software parity */
  10710.             hwparity = 0;
  10711. #endif /* HWPARITY */
  10712.             parity = y;
  10713. #ifndef NOXFER
  10714.             ebqflg = (parity) ? 1 : 0;
  10715. #endif /* NOXFER */
  10716. #ifdef HWPARITY
  10717.         }
  10718. #endif /* HWPARITY */
  10719.  
  10720. #ifdef TN_COMPORT
  10721.         if (network && istncomport())
  10722.           tnsettings(parity, 0);
  10723. #endif /* TN_COMPORT */
  10724.  
  10725.         return(success = 1);
  10726.  
  10727. #ifndef NOFRILLS
  10728.       case XYPROM:                      /* SET PROMPT */
  10729. /*
  10730.   Note: xxstring not invoked here.  Instead, it is invoked every time the
  10731.   prompt is issued.  This allows the prompt string to contain variables
  10732.   that can change, like \v(dir), \v(time), etc.
  10733. */
  10734.         ckmakmsg(line,                  /* Default might have trailing space */
  10735.                  LINBUFSIZ,
  10736.                  "{",
  10737.                  inserver ? ikprompt : ckprompt,
  10738.                  "}",
  10739.                  NULL
  10740.                  );
  10741.         if ((x = cmtxt("Program's command prompt",line,&s,NULL)) < 0)
  10742.           return(x);
  10743.         s = brstrip(s);                 /* Remove enclosing braces, if any */
  10744.         cmsetp(s);                      /* Set the prompt */
  10745.         return(success = 1);
  10746. #endif /* NOFRILLS */
  10747.  
  10748. #ifndef NOXFER
  10749.       case XYRETR:                      /* RETRY: per-packet retry limit */
  10750.         y = cmnum("Maximum retries per packet","10",10,&x,xxstring);
  10751.         if (x < 0) x = 0;
  10752.         if ((x = setnum(&maxtry,x,y,999)) < 0) return(x);
  10753. #ifdef COMMENT
  10754.         if (maxtry <= wslotr) {
  10755.             printf("?Retry limit must be greater than window size\n");
  10756.             return(success = 0);
  10757.         }
  10758. #endif /* COMMENT */
  10759.         if (rmsflg) {
  10760.             sstate = setgen('S', "403", ckitoa(maxtry), "");
  10761.             return((int) sstate);
  10762.         } else return(success = x);
  10763. #endif /* NOXFER */
  10764.  
  10765. #ifndef NOSERVER
  10766.       case XYSERV:                      /* SET SERVER items */
  10767.         if ((y = cmkey(srvtab,nsrvt,"","",xxstring)) < 0) return(y);
  10768.         switch (y) {
  10769.           case XYSERI:
  10770.             if ((y = cmnum("Number of seconds, or 0 for no idle timeout",
  10771.                            "0",10,&x,xxstring)) < 0)
  10772.               return(y);
  10773.             if (x < 0)
  10774.               x = 0;
  10775.             if ((y = cmcfm()) < 0)
  10776.               return(y);
  10777. #ifndef OS2
  10778.             srvtim = 0;
  10779. #endif /* OS2 */
  10780.             srvidl = x;
  10781.             return(success = 1);
  10782.           case XYSERT:
  10783.             if ((y = cmnum("Interval for server NAKs, 0 = none",
  10784.                            ckitoa(DSRVTIM),
  10785.                            10,&x, xxstring)) < 0)
  10786.               return(y);
  10787.             if (x < 0) {
  10788.                 printf(
  10789.                    "\n?Specify a positive number, or 0 for no server NAKs\n");
  10790.                 return(0);
  10791.             }
  10792.             if ((y = cmcfm()) < 0) return(y);
  10793.             if (rmsflg) {
  10794.                 sstate = setgen('S', "404", ckitoa(x), "");
  10795.                 return((int) sstate);
  10796.             } else {
  10797. #ifndef OS2
  10798.                 srvidl = 0;
  10799. #endif /* OS2 */
  10800.                 srvtim = x;             /* Set the server timeout variable */
  10801.                 return(success = 1);
  10802.             }
  10803.           case XYSERD:                  /* SERVER DISPLAY */
  10804.             return(success = seton(&srvdis)); /* ON or OFF... */
  10805.  
  10806. #ifndef NOSPL
  10807.           case XYSERP:                  /* SERVER GET-PATH */
  10808.             return(parsdir(2));
  10809. #endif /* NOSPL */
  10810.  
  10811.           case XYSERL:                  /* SERVER LOGIN */
  10812.             return(cklogin());
  10813.  
  10814.           case XYSERC:                  /* SERVER CD-MESSAGE */
  10815.             x = rmsflg ?
  10816.               cmkey(onoff,2,"","",xxstring) :
  10817.                 cmkey(cdmsg,3,"","",xxstring);
  10818.             if (x < 0)
  10819.               return(x);
  10820.             if (x == 2) {               /* CD-MESSAGE FILE */
  10821.                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
  10822.                   return(x);
  10823.                 if (!*s) {
  10824.                     s = NULL;
  10825.                     srvcdmsg = 0;
  10826.                 }
  10827.                 makestr(&cdmsgstr,s);
  10828.                 makelist(cdmsgstr,cdmsgfile,8);
  10829.                 return(success = 1);
  10830.             }
  10831.             if ((y = cmcfm()) < 0)      /* CD-MESSAGE ON/OFF */
  10832.               return(y);
  10833.             if (rmsflg) {
  10834.                 sstate = setgen('S', "420", x ? "1" : "0", "");
  10835.                 return((int) sstate);
  10836.             } else {
  10837.                 if (x > 0)
  10838.                   srvcdmsg |= 1;
  10839.                 else
  10840.                   srvcdmsg &= 2;
  10841.                 return(success = 1);
  10842.             }
  10843.           case XYSERK:                  /* SERVER KEEPALIVE */
  10844.             return(success = seton(&srvping)); /* ON or OFF... */
  10845.  
  10846.           default:
  10847.             return(-2);
  10848.         }
  10849. #endif /* NOSERVER */
  10850.     }
  10851.  
  10852.     switch (xx) {
  10853. #ifdef UNIX
  10854. #ifndef NOJC
  10855.       case XYSUSP:                      /* SET SUSPEND */
  10856.         seton(&xsuspend);        /* on or off... */
  10857.         return(success = 1);
  10858. #endif /* NOJC */
  10859. #endif /* UNIX */
  10860.  
  10861.       case XYTAKE:                      /* SET TAKE */
  10862.         if ((y = cmkey(taktab,4,"","",xxstring)) < 0) return(y);
  10863.         switch (y) {
  10864.           case 0: return(success = seton(&techo));
  10865. #ifndef NOSPL
  10866.           case 1: return(success = seton(&takerr[cmdlvl]));
  10867. #else
  10868.           case 1: return(success = seton(&takerr[tlevel]));
  10869. #endif /* NOSPL */
  10870.           case 2: techo = 0; return(success = 1); /* For compatibility with */
  10871.           case 3: techo = 1; return(success = 1); /* MS-DOS Kermit */
  10872.           default: return(-2);
  10873.         }
  10874.  
  10875. #ifndef NOSCRIPT
  10876.       case XYSCRI:                      /* SET SCRIPT */
  10877.         if ((y = cmkey(scrtab,1,"","echo",xxstring)) < 0) return(y);
  10878.         switch (y) {
  10879.           case 0: return(success = seton(&secho));
  10880.           default: return(-2);
  10881.         }
  10882. #endif /* NOSCRIPT */
  10883.  
  10884.       default:
  10885.         break;
  10886.     }
  10887.  
  10888. #ifndef NOLOCAL
  10889.     switch (xx) {
  10890.       case XYTERM:                      /* SET TERMINAL */
  10891.         x = settrm();
  10892.         success = (x > 0) ? 1 : 0;
  10893.         return(x);
  10894.  
  10895. #ifdef NT
  10896.       case XYWIN95:                     /* SET WIN95 workarounds */
  10897.         x = setwin95();
  10898.         success = (x > 0 ? 1 : 0);
  10899.         return(x);
  10900. #endif /* NT */
  10901.  
  10902. #ifdef OS2
  10903.       case XYDLR:                       /* SET DIALER workarounds */
  10904.         x = setdialer();
  10905.         success = (x > 0 ? 1 : 0);
  10906.         return(x);
  10907.  
  10908.       case XYTITLE:                     /* SET TITLE of window */
  10909.         x = settitle();
  10910.         success = (x > 0 ? 1 : 0);
  10911.         return(x);
  10912. #endif /* OS2 */
  10913.  
  10914. #ifdef OS2MOUSE
  10915.       case XYMOUSE:                     /* SET MOUSE */
  10916.         return(success = setmou());
  10917. #endif /* OS2MOUSE */
  10918.  
  10919.       case XYBELL:                      /* SET BELL */
  10920.         return(success = setbell());
  10921.  
  10922. #ifdef OS2
  10923.       case XYPRTY:
  10924.         return(success = setprty() );
  10925. #endif /* OS2 */
  10926.  
  10927.       default:
  10928.         break;
  10929.     }
  10930. #endif /* NOLOCAL */
  10931.  
  10932.     switch (xx) {
  10933.  
  10934. /* SET SEND/RECEIVE protocol parameters. */
  10935.  
  10936. #ifndef NOXFER
  10937.       case XYRECV:
  10938.       case XYSEND:
  10939.         return(setsr(xx,rmsflg));
  10940. #endif /* NOXFER */
  10941.  
  10942. #ifndef NOLOCAL
  10943.       case XYSESS:                      /* SESSION-LOG */
  10944.         if ((x = cmkey(sfttab,nsfttab,"type of file",
  10945. #ifdef OS2
  10946.                        "binary",
  10947. #else /* OS2 */
  10948.                        "text",
  10949. #endif /* OS2 */
  10950.                        xxstring
  10951.                        )
  10952.              ) < 0)
  10953.           return(x);
  10954.         if ((y = cmcfm()) < 0)
  10955.           return(y);
  10956.         if (x == 999) {                 /* TIMESTAMPED-TEXT */
  10957.             sessft = XYFT_T;            /* Implies text */
  10958.             slogts = 1;                 /* and timestamps */
  10959.         } else {                        /* A regular type */
  10960.             sessft = x;                 /* The type */
  10961.             slogts = 0;                 /* No timestampes */
  10962.         }
  10963.         return(success = 1);
  10964.  
  10965.       case XYSPEE:                      /* SET SPEED */
  10966.         lp = line;
  10967.         if (local && !network) {
  10968.           ckmakmsg(lp,
  10969.                    LINBUFSIZ,
  10970.                    "Transmission rate for ",
  10971.                    ttname,
  10972.                    " (bits per second)",
  10973.                    NULL
  10974.                    );
  10975.         } else {
  10976.           ckstrncpy(lp,
  10977.                     "Serial-port speed (bits per second)",
  10978.                     LINBUFSIZ
  10979.                     );
  10980.         }
  10981.         zz = -1L;
  10982.  
  10983. #ifdef TN_COMPORT
  10984.         if (network && istncomport())
  10985.           x = cmkey(tnspdtab,ntnspd,line,"",xxstring);
  10986.         else
  10987. #endif /* TN_COMPORT */
  10988.           x = cmkey(spdtab,nspd,line,"",xxstring);
  10989.         if (x < 0) {
  10990.             if (x == -3) printf("?value required\n");
  10991. #ifdef USETCSETSPEED
  10992.             /* In this case, any number can be tried */
  10993.             /* There's a parse error message but the request still goes thru */
  10994.             if (rdigits(atmbuf))
  10995.               zz = atol(atmbuf);
  10996.             else
  10997. #endif /* USETCSETSPEED */
  10998.               return(x);
  10999.         }
  11000.         if ((y = cmcfm()) < 0) return(y);
  11001. #ifdef IKSD
  11002.         if (inserver) {
  11003.             printf("?Sorry, command disabled.\r\n");
  11004.             return(success = 0);
  11005.         }
  11006. #endif /* IKSD */
  11007.         if (!local) {
  11008.             printf("?SET SPEED has no effect without prior SET LINE\n");
  11009.             return(success = 0);
  11010.         } else if (network
  11011. #ifdef TN_COMPORT
  11012.                    && !istncomport()
  11013. #endif /* TN_COMPORT */
  11014.                    ) {
  11015.             printf("\n?Speed cannot be set for network connections\n");
  11016.             return(success = 0);
  11017.         }
  11018.  
  11019. /*
  11020.   Note: This way of handling speeds is not 16-bit safe for speeds greater
  11021.   than 230400.  The argument to ttsspd() should have been a long.
  11022. */
  11023. #ifdef USETCSETSPEED
  11024.         if (zz > -1L)
  11025.           x = zz / 10L;
  11026. #endif /* USETCSETSPEED */
  11027.         zz = (long) x * 10L;
  11028.         if (zz == 130L) zz = 134L;
  11029.         if (zz == 70L) zz = 75L;        /* (see spdtab[] definition) */
  11030.         if (ttsspd(x) < 0)  {           /* Call ttsspd with cps, not bps! */
  11031.             printf("?Unsupported line speed - %ld\n",zz);
  11032.             return(success = 0);
  11033.         } else {
  11034. #ifdef CK_TAPI
  11035.             if (!tttapi || tapipass)
  11036.               speed = ttgspd();         /* Read it back */
  11037.             else
  11038.               speed = zz;
  11039. #else /* CK_TAPI */
  11040.             speed = ttgspd();           /* Read it back */
  11041. #endif /* CK_TAPI */
  11042.             if (speed != zz)  {         /* Call ttsspd with cps, not bps! */
  11043.                 printf("?SET SPEED fails, speed is %ld\n",speed);
  11044.                 return(success = 0);
  11045.             }
  11046.             if (pflag && !xcmdsrc) {
  11047.                 if (speed == 8880)
  11048.                   printf("%s, 75/1200 bps\n",ttname);
  11049.                 else if (speed == 134)
  11050.                   printf("%s, 134.5 bps\n",ttname);
  11051.                 else
  11052.                   printf("%s, %ld bps\n",ttname,speed);
  11053.             }
  11054.             return(success = 1);
  11055.         }
  11056. #endif /* NOLOCAL */
  11057.  
  11058. #ifndef NOXFER
  11059.       case XYXFER:                      /* SET TRANSFER */
  11060.         if ((y = cmkey(rmsflg ? rtstab : tstab, /* (or REMOTE SET TRANSFER) */
  11061.                        rmsflg ? nrts : nts,
  11062.                        "","character-set",xxstring)) < 0) return(y);
  11063.         switch (y) {
  11064. #ifdef XFRCAN
  11065.           case XYX_CAN:                 /* CANCELLATION */
  11066.             if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
  11067.             if (z == 0) {               /* OFF */
  11068.                 if ((y = cmcfm()) < 0) return(y);
  11069.                 xfrcan = 0;
  11070.             } else {
  11071.                 if ((y = cmnum("ASCII code for cancellation character",
  11072.                                "3",10,&x,
  11073.                                xxstring)) < 0)
  11074.                   return(y);
  11075.                 if (x > 31 && x != 127) {
  11076.                     printf("Cancel character must be 0-31 or 127\n");
  11077.                     return(-9);
  11078.                 }
  11079.                 if ((y = cmnum("How many required to cause cancellation",
  11080.                                "2",10,&z, xxstring)) < 0)
  11081.                   return(y);
  11082.                 if (z < 2) {
  11083.                     printf("Number must be 2 or greater\n");
  11084.                     return(-9);
  11085.                 }
  11086.                 if ((y = cmcfm()) < 0) return(y);
  11087.                 xfrcan = 1;             /* CANCELLATION ON */
  11088.                 xfrchr = x;             /* Using this character */
  11089.                 xfrnum = z;             /* Needing this many of them */
  11090.             }
  11091.             return(success = 1);
  11092. #endif /* XFRCAN */
  11093.  
  11094. #ifndef NOCSETS
  11095.           case XYX_CSE:                 /* CHARACTER-SET */
  11096.             if ((y = cmkey(tcstab,ntcs,"","transparent",xxstring)) < 0)
  11097.               return(y);
  11098.             if ((x = cmcfm()) < 0) return(x);
  11099.             if (rmsflg) {
  11100.                 sstate = setgen('S', "405", tcsinfo[y].designator, "");
  11101.                 return((int) sstate);
  11102.             } else {
  11103.                 extern int s_cset, fcharset, axcset[], tcs_save;
  11104.                 tslevel = (y == TC_TRANSP) ? 0 : 1; /* transfer syntax level */
  11105.         xfrxla = tslevel;
  11106.                 tcharset = y;           /* transfer character set */
  11107.                 /* SEND CHARACTER-SET AUTO */
  11108.                 if (tslevel > 0 && s_cset == XMODE_A)
  11109.                   if (y > -1 && y <= MAXTCSETS)
  11110.                     if (axcset[y] > -1 && axcset[y] > MAXFCSETS)
  11111.                       fcharset = axcset[y]; /* Auto-pick file charset */
  11112.                 setxlatype(tcharset,fcharset); /* Translation type */
  11113.         tcs_save = -1;
  11114.                 return(success = 1);
  11115.             }
  11116. #endif /* NOCSETS */
  11117.  
  11118.           case XYX_LSH:                 /* LOCKING-SHIFT */
  11119.             if ((y = cmkey(lstab,nls,"","on",xxstring)) < 0)
  11120.               return(y);
  11121.             if ((x = cmcfm()) < 0) return(x);
  11122.             lscapr = (y == 1) ? 1 : 0;  /* ON: requested = 1 */
  11123.             lscapu = (y == 2) ? 2 : 0;  /* FORCED:  used = 1 */
  11124.             return(success = 1);
  11125.  
  11126. #ifdef CK_XYZ
  11127.           case XYX_PRO:                 /* Protocol */
  11128. #ifndef OS2
  11129.             if (inserver) {
  11130.                 printf("?Sorry, only Kermit protocol is available\n");
  11131.                 return(-9);
  11132.             }
  11133. #endif /* OS2 */
  11134.             return(setproto());
  11135. #endif /* CK_XYZ */
  11136.  
  11137.           case XYX_MOD:                 /* Mode */
  11138.             if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
  11139.               return(y);
  11140.             if ((x = cmcfm()) < 0) return(x);
  11141.             if (rmsflg) {
  11142.                 sstate = setgen('S', "410", y == XMODE_A ? "0" : "1", "");
  11143.                 return((int)sstate);
  11144.             }
  11145.             g_xfermode = y;
  11146.             xfermode = y;
  11147.             return(success = 1);
  11148.  
  11149. #ifndef NOLOCAL
  11150.           case XYX_DIS:                 /* Display */
  11151.             return(doxdis(1));        /* 1 == Kermit */
  11152. #endif /* NOLOCAL */
  11153.  
  11154.           case XYX_SLO:                 /* Slow-start */
  11155.             return(seton(&slostart));
  11156.  
  11157. #ifndef NOSPL
  11158.           case XYX_CRC:                 /* CRC */
  11159.             return(seton(&docrc));
  11160. #endif /* NOSPL */
  11161.  
  11162.           case XYX_BEL:                 /* Bell */
  11163.             return(seton(&xfrbel));
  11164.  
  11165. #ifdef PIPESEND
  11166.           case XYX_PIP:                 /* Pipes */
  11167. #ifndef NOPUSH
  11168.             if (nopush) {
  11169. #endif /* NOPUSH */
  11170.                 printf("Sorry, access to pipes is disabled\n");
  11171.                 return(-9);
  11172. #ifndef NOPUSH
  11173.             } else
  11174. #endif /* NOPUSH */
  11175.               return(seton(&usepipes));
  11176. #endif /* PIPESEND */
  11177.  
  11178.           case XYX_INT:                 /* Interruption */
  11179.             return(seton(&xfrint));
  11180.  
  11181.           case XYX_XLA:
  11182.             return(seton(&xfrxla));     /* Translation */
  11183.  
  11184.           case XYX_MSG: {
  11185.               extern char * xfrmsg;
  11186.               if ((x = cmtxt("Prompt string","",&s,xxstring)) < 0)
  11187.                 return(x);
  11188.               if (!*s) s = NULL;
  11189.               makestr(&xfrmsg,s);
  11190.               return(success = 1);
  11191.  
  11192.       }
  11193.       case XYX_RPT: {
  11194.           extern int whereflg;
  11195.           return(seton(&whereflg));
  11196.           }
  11197.           default:
  11198.             return(-2);
  11199.         }
  11200. #endif /* NOXFER */
  11201.     }
  11202.  
  11203.     switch (xx) {
  11204.  
  11205. #ifndef NOXMIT
  11206.       case XYXMIT:                      /* SET TRANSMIT */
  11207.         return(setxmit());
  11208. #endif /* NOXMIT */
  11209.  
  11210. #ifndef NOXFER
  11211. #ifndef NOCSETS
  11212.       case XYUNCS:                      /* UNKNOWN-CHARACTER-SET */
  11213.         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
  11214.         if ((x = cmcfm()) < 0) return(x);
  11215.         unkcs = y;
  11216.         return(success = 1);
  11217. #endif /* NOCSETS */
  11218. #endif /* NOXFER */
  11219.  
  11220. #ifndef NOPUSH
  11221. #ifdef UNIX
  11222.       case XYWILD:                      /* WILDCARD-EXPANSION */
  11223.         if ((y = cmkey(wildtab,2,
  11224.                        "Who expands wildcards","kermit",xxstring)) < 0)
  11225.           return(y);
  11226.         if ((z = cmkey(wdottab,
  11227.                        2,
  11228.                        "whether to match filenames that start with \".\"",
  11229.                        "/no-match-dot-files",
  11230.                        xxstring)
  11231.              ) < 0)
  11232.           return(z);
  11233.         if ((x = cmcfm()) < 0) return(x);
  11234.         if (nopush) {
  11235.             if (y > 0) {
  11236.                 printf("Shell expansion is disabled\n");
  11237.                 return(success = 0);
  11238.             }
  11239.         }
  11240.         wildxpand = y;
  11241.         matchdot = z;
  11242.         return(success = 1);
  11243. #endif /* UNIX */
  11244. #endif /* NOPUSH */
  11245.  
  11246. #ifndef NOXFER
  11247.       case XYWIND:                      /* WINDOW-SLOTS */
  11248.         if (protocol == PROTO_K) {
  11249.             y = cmnum("Window size for Kermit protocol, 1 to 32",
  11250.                       "1", 10, &x, xxstring);
  11251.             y = setnum(&z,x,y,MAXWS);   /* == 32 */
  11252.         }
  11253. #ifdef CK_XYZ
  11254.         else if (protocol == PROTO_Z) {
  11255.             y = cmnum("Window size for ZMODEM protocol, 0 to 65535",
  11256.                       "0", 10, &x, xxstring);
  11257.             y = setnum(&z,x,y,65535);
  11258.         }
  11259. #endif /* CK_XYZ */
  11260.         else {
  11261.             y = cmnum("Window size for current protocol",
  11262.                       "", 10, &x, xxstring);
  11263.             y = setnum(&z,x,y,65472);   /* Doesn't matter - we won't use it */
  11264.         }
  11265.         if (y < 0) return(y);
  11266.         if (protocol == PROTO_K) {
  11267.             if (z < 1)
  11268.               z = 1;
  11269.         }
  11270. #ifdef CK_XYZ
  11271.         else if (protocol == PROTO_Z) {
  11272.             /* Zmodem windowing is closer to Kermit packet length */
  11273.             /* than Kermit window size.  If Window size is zero   */
  11274.             /* an end of frame and CRC is sent only at the end of */
  11275.             /* the file (default).  Otherwise, an End of Frame    */
  11276.             /* and CRC are sent after Window Size number of bytes */
  11277.             if (z < 0)                  /* Disable windowing  */
  11278.               z = 0;
  11279.         } else {
  11280.             printf("?SET WINDOW does not apply to %s protocol\n",
  11281.                    ptab[protocol].p_name
  11282.                    );
  11283.         }
  11284. #endif /* CK_XYZ */
  11285.  
  11286. #ifdef COMMENT
  11287.         /* This is taken care of automatically now in protocol negotiation */
  11288.         if (maxtry < z) {
  11289.             printf("?Window slots must be less than retry limit\n");
  11290.             return(success = 0);
  11291.         }
  11292. #endif /* COMMENT */
  11293.         if (protocol == PROTO_K && rmsflg) { /* Set remote window size */
  11294.             wslotr = z;                 /* Set local window size too */
  11295.             ptab[protocol].winsize = wslotr;
  11296.             sstate = setgen('S', "406", ckitoa(z), "");
  11297.             return((int) sstate);
  11298.         }
  11299.         wslotr = z;                     /* Set requested window size here */
  11300.         ptab[protocol].winsize = wslotr; /* and in protocol-specific table */
  11301.         if (protocol == PROTO_K) {      /* And for Kermit only... */
  11302.             swcapr = (wslotr > 1) ? 1 : 0; /* set window bit in capas word */
  11303.             if (wslotr > 1) {           /* Window size > 1? */
  11304.                 /* Maybe adjust packet size */
  11305.                 y = adjpkl(urpsiz,wslotr,bigrbsiz);
  11306.                 if (y != urpsiz) {      /* Did it change? */
  11307.                     urpsiz = y;
  11308.                     if (msgflg)
  11309.                       printf(
  11310. " Adjusting receive packet-length to %d for %d window slots\n",
  11311.                              urpsiz,
  11312.                              wslotr
  11313.                              );
  11314.                 }
  11315.             }
  11316.         }
  11317.         return(success = 1);
  11318. #endif /* NOXFER */
  11319.     }
  11320.  
  11321.     switch (xx) {
  11322.  
  11323. #ifndef NOSPL
  11324.       case XYOUTP:                      /* OUTPUT command parameters */
  11325.         if ((y = cmkey(outptab,noutptab,"OUTPUT command parameter","pacing",
  11326.                        xxstring)) < 0)
  11327.           return(y);
  11328.         switch(y) {                     /* Which parameter */
  11329.           case OUT_PAC:                 /* PACING */
  11330.             y = cmnum("Milliseconds to pause between each OUTPUT character",
  11331.                       "100", 10,&x,xxstring);
  11332.             y = setnum(&z,x,y,16383);   /* Verify and get confirmation */
  11333.             if (y < 0) return(y);
  11334.             if (z < 0) z = 0;           /* (save some space) */
  11335.             pacing = z;
  11336.             return(success = 1);
  11337.           case OUT_ESC:                 /* Special-escapes */
  11338.             return(seton(&outesc));
  11339.           default:                      /* (shouldn't happen) */
  11340.             return(-2);
  11341.         }
  11342. #endif /* NOSPL */
  11343.  
  11344. #ifdef CK_SPEED
  11345.       case XYQCTL: {
  11346.           short *p;
  11347.           int zz;
  11348.           if ((z = cmkey(ctltab,2, "control-character prefixing option",""
  11349.                          ,xxstring)) < 0)
  11350.             return(z);
  11351.           /* Make space for a temporary copy of the prefixing table */
  11352.  
  11353.           p = (short *)malloc(256 * sizeof(short));
  11354.           if (!p) {
  11355.               printf("?Internal error - malloc failure\n");
  11356.               return(-9);
  11357.           }
  11358.           for (i = 0; i < 256; i++) p[i] = ctlp[i]; /* Copy current table */
  11359.  
  11360.           switch (z) {
  11361.             case 0:                     /* UNPREFIXED control character */
  11362.             case 1:                     /* PREFIXED control character */
  11363.               while (1) {               /* Collect a list of numbers */
  11364. #ifndef NOSPL
  11365.                   x_ifnum = 1;          /* Turn off complaints from eval() */
  11366. #endif /* NOSPL */
  11367.                   if ((x = cmnum((z == 0) ?
  11368. "\n Numeric ASCII value of control character that needs NO prefix,\n\
  11369.  or the word \"all\", or carriage return to complete the list" :
  11370. "\n Numeric ASCII value of control character that MUST BE prefixed,\n\
  11371.  or the word \"all\", or carriage return to complete the list",
  11372.                                  "",10,&y,xxstring
  11373.                                  )) < 0) {
  11374. #ifndef NOSPL
  11375.                       x_ifnum = 0;
  11376. #endif /* NOSPL */
  11377.                       if (x == -3) {
  11378.                           if ((x = cmcfm()) < 0) return(x);
  11379.                           break;
  11380.                       }
  11381.                       if (x == -2) {
  11382.                           if (p) { free((char *)p); p = NULL; }
  11383.                           debug(F110,"SET CONTROL atmbuf",atmbuf,0);
  11384.                           if (!ckstrcmp(atmbuf,"all",3,0) || /* "ALL" */
  11385.                               !ckstrcmp(atmbuf,"al",2,0) ||
  11386.                               !ckstrcmp(atmbuf,"a",1,0)) {
  11387.                               if ((x = cmcfm()) < 0) /* Get confirmation */
  11388.                                 return(x);
  11389.                   prefixing = z ? PX_ALL : PX_NON;
  11390.                   setprefix(prefixing);
  11391.                   return(success = 1);
  11392.                           } else {    /* Not number, not ALL */
  11393.                               printf(
  11394.                                  "?Please specify a number or the word ALL\n");
  11395.                               return(-9);
  11396.                           }
  11397.                       } else {
  11398.                           if (p) free((char *)p);
  11399.                           return(x);
  11400.                       }
  11401.                   }
  11402. #ifndef NOSPL
  11403.                   x_ifnum = 0;
  11404. #endif /* NOSPL */
  11405. #ifdef UNPREFIXZERO
  11406.                   zz = 0;
  11407. #else
  11408. #ifndef OS2
  11409.                   zz = 1 - z;
  11410. #else
  11411.                   zz = 0;               /* Allow 0 (but only for Zmodem) */
  11412. #endif /* OS2 */
  11413. #endif /* UNPREFIXZERO */
  11414.  
  11415.             /* printf("x = %d, y = %d, z = %d, zz = %d\n", x,y,z,zz); */
  11416.  
  11417.                   if ((y >  31 && y < 127) || /* A specific numeric value */
  11418.                       (y > 159 && y < 255) || /* Check that it is a valid */
  11419.                       (y < zz) ||       /* control code. */
  11420.                       (y > 255)) {
  11421.                       printf("?Values allowed are: %d-31, 127-159, 255\n",zz);
  11422.                       if (p) free((char *)p);
  11423.                       return(-9);
  11424.                   }
  11425.                   x = y & 127;          /* Get 7-bit value */
  11426.                   if (z == 0) {         /* If they are saying it is safe... */
  11427.                       /* If flow control is Xon/Xoff */
  11428.                       if (((flow == FLO_XONX) &&
  11429.                            /* XON & XOFF chars not safe. */
  11430.                            (x == XON || x == XOFF))
  11431.                           ) {
  11432.                           if (msgflg)
  11433.                             printf(
  11434.                               "Sorry, not while Xon/Xoff is in effect.\n");
  11435.                           if (p) free((char *)p);
  11436.                           return(-9);
  11437.                       }
  11438. #ifdef TNCODE
  11439.                       else if (network && IS_TELNET()
  11440.                                && (y == CR ||
  11441.                                    (unsigned) y == (unsigned) 255)) {
  11442.                           if (msgflg)
  11443.                             printf("Sorry, not on a TELNET connection.\n");
  11444.                           if (p) free((char *)p);
  11445.                           return(-9);
  11446.                       }
  11447. #endif /* TNCODE */
  11448.                   }
  11449.                   p[y] = (char) z;      /* All OK, set flag */
  11450.               } /* End of while loop */
  11451. /*
  11452.   Get here only if they have made no mistakes.  Copy temporary table back to
  11453.   permanent one, then free temporary table and return successfully.
  11454. */
  11455.               for (i = 0; i < 256; i++) ctlp[i] = p[i];
  11456.               if (p) free((char *)p);
  11457.               if (z > 0) clearrq = 0;   /* 199 (see SET PREFIXING) */
  11458.               return(success = 1);
  11459.             default:
  11460.               return(-2);
  11461.           }
  11462.       }
  11463. #endif /* CK_SPEED */
  11464.     }
  11465.  
  11466.     switch (xx) {
  11467.  
  11468. #ifndef NOXFER
  11469.       case XYREPT:
  11470.         if ((y = cmkey(rpttab,2,
  11471.                        "repeat-count compression parameter","",xxstring)) < 0)
  11472.           return(y);
  11473.         switch(y) {
  11474.           case 0:
  11475.             return(success = seton(&rptena)); /* REPEAT COUNTS = ON, OFF */
  11476.           case 1:                       /* REPEAT MININUM number */
  11477.             printf("(not implemented yet, nothing happens)\n");
  11478.             return(-9);
  11479.           case 2:                       /* REPEAT PREFIX char */
  11480.             if ((x = cmnum("ASCII value","",10,&z,xxstring)) < 0)
  11481.               return(x);
  11482.             if ((x = cmcfm()) < 0) return(x);
  11483.             if ((z > 32 && z < 63) || (z > 95 && z < 127)) {
  11484.                 if (y == 1) rptmin = (CHAR) z; else myrptq = (CHAR) z;
  11485.                 return(success = 1);
  11486.             } else {
  11487.                 printf("?Illegal value for prefix character\n");
  11488.                 return(-9);
  11489.             }
  11490.         }
  11491. #endif /* NOXFER */
  11492.  
  11493. #ifndef NOSPL
  11494.       case XYALRM: {
  11495. #ifndef COMMENT
  11496.           int yy;
  11497.           long zz;
  11498.           zz = -1L;
  11499.           yy = x_ifnum;
  11500.           x_ifnum = 1;                  /* Turn off internal complaints */
  11501.           y = cmnum("Seconds from now, or time of day as hh:mm:ss",
  11502.                     "0" ,10, &x, xxstring);
  11503.           x_ifnum = yy;
  11504.           if (y < 0) {
  11505.               if (y == -2) {            /* Invalid number or expression */
  11506.                   zz = tod2sec(atmbuf); /* Convert to secs since midnight */
  11507.                   if (zz < 0L) {
  11508.                       printf("?Number, expression, or time of day required\n");
  11509.                       return(-9);
  11510.                   } else {
  11511.                       char now[32];     /* Current time */
  11512.                       char *p;
  11513.                       long tnow;
  11514.                       p = now;
  11515.                       ztime(&p);
  11516.                       tnow = atol(p+11) * 3600L +
  11517.                         atol(p+14) * 60L + atol(p+17);
  11518.                       if (zz < tnow)    /* User's time before now */
  11519.                         zz += 86400L;   /* So make it tomorrow */
  11520.                       zz -= tnow;       /* Seconds from now. */
  11521.                   }
  11522.               } else
  11523.                 return(y);
  11524.           }
  11525.           if (x < 0) {
  11526.               printf("?Alarm time is in the past.\n");
  11527.               return(-9);
  11528.           }
  11529.           if ((y = cmcfm()) < 0) return(y);
  11530.           if (zz > -1L) {               /* Time of day given? */
  11531.               x = zz;
  11532.               if (zz != (long) x) {
  11533.                   printf(
  11534. "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n"
  11535.                          );
  11536.                   return(-9);
  11537.               }
  11538.           }
  11539.           return(setalarm((long)x));
  11540.       }
  11541. #else
  11542. /*
  11543.   This is to allow long values where int and long are not the same, e.g.
  11544.   on 16-bit systems.  But something is wrong with it.
  11545. */
  11546.         if ((y = cmtxt("seconds from now", "0", &s, xxstring)) < 0)
  11547.           return(y);
  11548.         if (rdigits(s)) {
  11549.             return(setalarm(atol(s)));
  11550.         } else {
  11551.             printf("%s - not a number\n",s);
  11552.             return(-9);
  11553.         }
  11554. #endif /* COMMENT */
  11555. #endif /* NOSPL */
  11556.  
  11557. #ifndef NOXFER
  11558.       case XYPROTO:
  11559.         return(setproto());
  11560. #endif /* NOXFER */
  11561.  
  11562. /*
  11563.   C-Kermit unprefixes control characters automatically on network connections
  11564.   if CLEAR-CHANNEL is ON, which it is by default.  But not all network
  11565.   connections are transparent to all control characters.  For example, the
  11566.   DEC-20, even when you TELNET to it, is sensitive to Ctrl-O and Ctrl-T.
  11567.   If you tell C-Kermit to SET CONTROL PREFIX 15 and/or 20, it doesn't help
  11568.   because CLEAR-CHANNEL is still in effect.  If the user goes to the trouble
  11569.   to set up some prefixing, then Kermit should do what the user said.  In
  11570.   C-Kermit 7.1 Alpha.03 we change the code to set clearrq to 0 if the user
  11571.   gives a SET PREFIXING or SET CONTROL PREFIX command.
  11572. */
  11573.  
  11574. #ifdef CK_SPEED
  11575.       case XYPREFIX: {
  11576. #ifdef COMMENT
  11577.           extern int clearrq;
  11578. #endif /* COMMENT */
  11579.           if ((z = cmkey(pfxtab, 4, "control-character prefixing option",
  11580.                          "", xxstring)) < 0)
  11581.             return(z);
  11582.           if ((x = cmcfm()) < 0) return(x);
  11583.           clearrq = 0;                  /* 199 */
  11584.           setprefix(z);
  11585. #ifdef COMMENT
  11586.           if (hints && (z == PX_ALL || z == PX_CAU) && clearrq) {
  11587.         printf("Hint: Use SET CLEAR-CHANNEL OFF to disable negotiation of\n");
  11588.         printf("      SET PREFIXING NONE during file transfers on reliable\n");
  11589.         printf("      connections.\n");
  11590.           }
  11591. #endif /* COMMENT */
  11592.           return(success = 1);
  11593.       }
  11594. #endif /* CK_SPEED */
  11595.  
  11596. #ifndef NOSPL
  11597.       case XYLOGIN:
  11598.         if ((z = cmkey(logintab, 3, "value for login script","userid",
  11599.                        xxstring)) < 0)
  11600.           return(z);
  11601.         x = cmdgquo();
  11602.         if (z == LOGI_PSW)
  11603.           cmdsquo(0);
  11604.         if ((y = cmtxt("text","", &s, NULL)) < 0) {
  11605.             cmdsquo(x);
  11606.             return(y);
  11607.         }
  11608.         cmdsquo(x);
  11609. #ifdef IKSD
  11610.         if (inserver)
  11611.           return(success = 0);
  11612. #endif /* IKSD */
  11613.         s = brstrip(s);
  11614.         if ((int)strlen(s) > 63) {
  11615.             printf("Sorry, too long\n");
  11616.             return(-9);
  11617.         }
  11618.         switch(z) {
  11619.           case LOGI_UID:
  11620.             ckstrncpy(uidbuf,s,UIDBUFLEN);
  11621.             sl_uid_saved = 0;
  11622.             break;
  11623.           case LOGI_PSW:
  11624.             ckstrncpy(pwbuf,s,PWBUFL);
  11625.             if (pwbuf[0]) {
  11626.                 pwflg = 1;
  11627. #ifdef OS2
  11628.                 pwcrypt = 1;
  11629. #else /* OS2 */
  11630.                 pwcrypt = 0;
  11631. #endif /* OS2 */
  11632.             }
  11633.             break;
  11634.           case LOGI_PRM:
  11635.             ckstrncpy(prmbuf,s,PWBUFL);
  11636.         }
  11637.         return(success = 1);
  11638. #endif /* NOSPL */
  11639.     }
  11640.  
  11641.     switch (xx) {
  11642.  
  11643.       case XYSTARTUP:
  11644.         if ((y = cmkey(ifdtab,2,"","discard",xxstring)) < 0) return(y);
  11645.         if ((x = cmcfm()) < 0) return(x);
  11646.         DeleteStartupFile = (y != 0) ? 0 : 1;
  11647.         return(success = 1);
  11648.  
  11649.       case XYTMPDIR:
  11650.         x = cmdir("Name of temporary directory","",&s,xxstring);
  11651.         if (x == -3)
  11652.           s = "";
  11653.         else if (x < 0)
  11654.           return(x);
  11655.         if ((x = cmcfm()) < 0) return(x);
  11656.         makestr(&tempdir,s);
  11657.         return(tempdir ? 1 : 0);
  11658.  
  11659. #ifndef NOXFER
  11660.       case XYDEST:                      /* DESTINATION */
  11661.         return(setdest());
  11662. #endif /* NOXFER */
  11663.  
  11664. #ifndef NOPUSH
  11665. #ifndef NOFRILLS
  11666.  
  11667. /* Editor, Browser, and FTP Client */
  11668.  
  11669.       case XYEDIT:                      /* EDITOR */
  11670. #ifdef IKSD
  11671.         if (inserver) {
  11672.             printf("?Sorry, command disabled.\r\n");
  11673.             return(success = 0);
  11674.         }
  11675. #endif /* IKSD */
  11676. #ifdef CK_APC
  11677.         /* Don't let this be set remotely */
  11678.         if (apcactive == APC_LOCAL ||
  11679.             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
  11680.           return(success = 0);
  11681. #endif /* CK_APC */
  11682.  
  11683. #ifdef OS2ORUNIX
  11684.         {
  11685.             char *p = getenv("PATH");
  11686.             char *e;
  11687.             e = editor[0] ? (char *) editor : getenv("EDITOR");
  11688.             if (!e) e = "";
  11689.             if (p)
  11690.               x = cmifip("Name of preferred editor",e,&s,&y,0,p,xxstring);
  11691.             else
  11692.               x = cmifi("Full path of preferred editor",e,&s,&y,xxstring);
  11693.             if (x < 0 && x != -3)
  11694.               return(x);
  11695.         }
  11696. #else
  11697. #ifdef VMS
  11698.         if ((y = cmtxt("DCL command for editing", "edit", &s, NULL)) < 0) {
  11699.             if (x != -3)
  11700.               return(x);
  11701.         }
  11702. #else
  11703.         if ((x = cmifi("Full path of preferred editor","",&s,&y,xxstring))<0) {
  11704.             if (x != -3)
  11705.               return(x);
  11706.         }
  11707. #endif /* VMS */
  11708. #endif /* OS2ORUNIX */
  11709. #ifdef VMS
  11710.         ckstrncpy(editor,s,CKMAXPATH);
  11711.         editopts[0] = NUL;
  11712. #else
  11713.         if (y != 0) {
  11714.             printf("?A single file please\n");
  11715.             return(-2);
  11716.         }
  11717.         ckstrncpy(line,s,LINBUFSIZ);
  11718.         if ((x = cmtxt("editor command-line options","",&s,NULL)) < 0)
  11719.           return(x);
  11720.         ckstrncpy(tmpbuf,s,TMPBUFSIZ);
  11721.         if ((z = cmcfm()) < 0) return(z);
  11722.         if (line[0]) {
  11723.             zfnqfp(line,CKMAXPATH,editor);
  11724.             ckstrncpy(editopts,tmpbuf,128);
  11725.         } else {
  11726.             editor[0] = NUL;
  11727.             editopts[0] = NUL;
  11728.         }
  11729. #endif /* VMS */
  11730.         return(success = 1);
  11731.  
  11732. #ifndef NOFTP
  11733. #ifndef SYSFTP
  11734. #ifdef TCPSOCKET
  11735.       case XYFTPX:
  11736.         return(dosetftp());             /* SET FTP */
  11737. #endif /* TCPSOCKET */
  11738. #endif /* SYSFTP */
  11739. #endif /* NOFTP */
  11740.  
  11741. #ifdef BROWSER
  11742. #ifndef NOFTP
  11743. #ifdef SYSFTP
  11744.       case XYFTP:                       /* SET FTP-CLIENT */
  11745. #endif /* SYSFTP */
  11746. #endif /* NOFTP */
  11747.       case XYBROWSE:                    /* SET BROWSER */
  11748.         {
  11749.             char *p = getenv("PATH");
  11750.             char *app = (char *) browser, *opts = (char *) browsopts;
  11751. #ifndef NOFTP
  11752. #ifdef SYSFTP
  11753.             extern char ftpapp[], ftpopts[];
  11754.             if (xx == XYFTP) {
  11755.                 app = (char *)ftpapp;
  11756.                 opts = (char *)ftpopts;
  11757.             }
  11758. #endif /* SYSFTP */
  11759. #endif /* NOFTP */
  11760. #ifdef IKSD
  11761.             if (inserver) {
  11762.                 printf("?Sorry, command disabled.\r\n");
  11763.                 return(success = 0);
  11764.             }
  11765. #endif /* IKSD */
  11766. #ifdef CK_APC
  11767.             /* Don't let this be set remotely */
  11768.             if (apcactive == APC_LOCAL ||
  11769.                 (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
  11770.               return(success = 0);
  11771. #endif /* CK_APC */
  11772. #ifdef OS2ORUNIX
  11773.             if (p)
  11774.               x = cmifip(xx == XYBROWSE ?
  11775.                          "Name of preferred browser" :
  11776.                          "Name of preferred ftp client",
  11777. #ifdef OS2
  11778.                          xx == XYFTP ? "ftp.exe" : ""
  11779. #else
  11780.                          xx == XYFTP ? "ftp" : ""
  11781. #endif /* OS2 */
  11782.                          ,&s,&y,0,p,xxstring
  11783.                          );
  11784.             else
  11785.               x = cmifi(xx == XYBROWSE ?
  11786.                         "Full path of preferred browser" :
  11787.                         "Full path of preferred ftp client",
  11788.                         "",&s,&y,xxstring
  11789.                         );
  11790.             if (x < 0 && x != -3)
  11791.               return(x);
  11792. #else
  11793. #ifdef VMS
  11794.             if ((x = cmtxt("DCL command to start your preferred Web browser",
  11795.                            "", &s, NULL)) < 0) {
  11796.                 if (x != -3)
  11797.                   return(x);
  11798.             }
  11799. #else
  11800.             if ((x = cmifi("Full path of preferred browser","",&s,&y,xxstring)
  11801.                  ) < 0) {
  11802.                 if (x != -3)
  11803.                   return(x);
  11804.             }
  11805. #endif /* VMS */
  11806. #endif /* OS2ORUNIX */
  11807. #ifdef VMS
  11808.             ckstrncpy(app,s,CKMAXPATH);
  11809.             *opts = NUL;
  11810. #else
  11811.             if (y != 0) {
  11812.                 printf("?A single file please\n");
  11813.                 return(-2);
  11814.             }
  11815.             ckstrncpy(line,s,LINBUFSIZ);
  11816.             if ((x = cmtxt(xx == XYBROWSE ?
  11817.                            "browser command-line options" :
  11818.                            "ftp client command-line options",
  11819.                            "",&s,NULL)
  11820.                  ) < 0)
  11821.               return(x);
  11822.             ckstrncpy(tmpbuf,s,TMPBUFSIZ);
  11823.             if ((z = cmcfm()) < 0) return(z);
  11824.             if (line[0]) {
  11825.                 zfnqfp(line,CKMAXPATH,app);
  11826.                 ckstrncpy(opts, tmpbuf, 128);
  11827.             } else {
  11828.                 *app = NUL;
  11829.                 *opts = NUL;
  11830.             }
  11831. #endif /* VMS */
  11832.             return(success = 1);
  11833.         }
  11834. #endif /* BROWSER */
  11835. #endif /* NOFRILLS */
  11836. #endif /* NOPUSH */
  11837.  
  11838. #ifdef CK_CTRLZ
  11839.       case XYEOF: {                     /* SET EOF */
  11840.           extern int eofmethod; extern struct keytab eoftab[];
  11841.           if ((x = cmkey(eoftab,3,"end-of-file detection method","",
  11842.                          xxstring)) < 0)
  11843.             return(x);
  11844.           if ((y = cmcfm()) < 0)
  11845.             return(y);
  11846.           eofmethod = x;
  11847.           return(success = 1);
  11848.       }
  11849. #endif /* CK_CTRLZ */
  11850.  
  11851. #ifdef SESLIMIT
  11852.       case XYLIMIT: {  /* Session-Limit (length of session in seconds) */
  11853.           extern int seslimit;
  11854. #ifdef OS2
  11855.           extern int downloaded;
  11856. #endif /* OS2 */
  11857.           y = cmnum("Maximum length of session, seconds","0",10,&x,xxstring);
  11858.           if (inserver &&
  11859. #ifdef IKSDCONF
  11860.               iksdcf
  11861. #else
  11862.               1
  11863. #endif /* IKSDCONF */
  11864. #ifdef OS2
  11865.                || downloaded
  11866. #endif /* OS2 */
  11867.               ) {
  11868.               if ((z = cmcfm()) < 0)
  11869.                 return(z);
  11870.               printf("?Sorry, command disabled.\r\n");
  11871.               return(success = 0);
  11872.           }
  11873.           return(setnum(&seslimit,x,y,86400));
  11874.       }
  11875. #endif /* SESLIMIT */
  11876.  
  11877.       case XYRELY: {                    /* SET RELIABLE */
  11878.           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
  11879.             return(x);
  11880.           if ((y = cmcfm()) < 0) return(y);
  11881.           reliable = x;
  11882.           setreliable = (x != SET_AUTO);
  11883.           debug(F101,"SET RELIABLE reliable","",reliable);
  11884.           return(success = 1);
  11885.       }
  11886.  
  11887. #ifdef STREAMING
  11888.       case XYSTREAM: {                  /* SET STREAMING */
  11889.           extern int streamrq;
  11890.           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
  11891.             return(x);
  11892.           if ((y = cmcfm()) < 0) return(y);
  11893.           streamrq = x;
  11894.           return(success = 1);
  11895.       }
  11896. #endif /* STREAMING */
  11897.  
  11898. #ifdef CKSYSLOG
  11899.       case XYSYSL: {
  11900.           if ((x = cmkey(syslogtab,nsyslog,"","",xxstring)) < 0)
  11901.             return(x);
  11902.           if ((y = cmcfm()) < 0) return(y);
  11903. #ifdef IKSD
  11904.           if (inserver &&
  11905. #ifdef IKSDCONF
  11906.               iksdcf
  11907. #else
  11908.               1
  11909. #endif /* IKSDCONF */
  11910.               ) {
  11911.               printf("?Sorry, command disabled.\n");
  11912.               return(success = 0);
  11913.           }
  11914. #endif /* IKSD */
  11915. #ifdef CK_APC
  11916.           /* Don't let this be set remotely */
  11917.           if (apcactive == APC_LOCAL ||
  11918.               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
  11919.             return(success = 0);
  11920. #endif /* CK_APC */
  11921.           ckxsyslog = x;
  11922.           return(success = 1);
  11923.       }
  11924. #endif /* CKSYSLOG */
  11925.  
  11926. #ifdef TLOG
  11927.       case XYTLOG: {                    /* SET TRANSACTION-LOG */
  11928.           extern int tlogsep;
  11929.           if ((x = cmkey(vbtab,nvb,"","verbose",xxstring)) < 0)
  11930.             return(x);
  11931.           if (x == 0) {
  11932.               if ((y = cmtxt("field separator",",",&s,NULL)) < 0) return(y);
  11933.               s = brstrip(s);
  11934.               if (*s) {
  11935.                   if (s[1]) {
  11936.                       printf("?A single character, please.\n");
  11937.                       return(-9);
  11938.                   } else if ((*s >= '0' && *s <= '9') ||
  11939.                              (*s >= 'A' && *s <= 'Z') ||
  11940.                              (*s >= 'a' && *s <= 'z')) {
  11941.                       printf("?A non-alphanumeric character, please.\n");
  11942.                       return(-9);
  11943.                   } else
  11944.                     tlogsep = *s;
  11945.               }
  11946.           } else {
  11947.               if ((y = cmcfm()) < 0) return(y);
  11948.           }
  11949. #ifdef IKSD
  11950.           if (inserver && isguest) {
  11951.               printf("?Sorry, command disabled.\n");
  11952.               return(success = 0);
  11953.           }
  11954. #endif /* IKSD */
  11955. #ifdef CK_APC
  11956.           /* Don't let this be set remotely */
  11957.           if (apcactive == APC_LOCAL ||
  11958.               (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
  11959.             return(success = 0);
  11960. #endif /* CK_APC */
  11961.           tlogfmt = x;
  11962.           return(success = 1);
  11963.       }
  11964. #endif /* TLOG */
  11965.  
  11966.       case XYCLEAR: {                   /* SET CLEARCHANNEL */
  11967.           if ((x = cmkey(ooatab,3,"","automatic",xxstring)) < 0)
  11968.             return(x);
  11969.           if ((y = cmcfm()) < 0) return(y);
  11970.           clearrq = x;
  11971.           return(success = 1);
  11972.       }
  11973.  
  11974. #ifdef CK_AUTHENTICATION
  11975.       case XYAUTH: {                    /* SET AUTHENTICATION */
  11976. #ifdef CK_KERBEROS
  11977.           int kv = 0;
  11978.           extern struct krb_op_data krb_op;
  11979. #endif /* CK_KERBEROS */
  11980.           char * p = NULL;
  11981.           if ((x =
  11982.                cmkey(setauth,nsetauth,"authentication type","",xxstring)) < 0)
  11983.             return(x);
  11984.           switch (x) {
  11985. #ifdef CK_KERBEROS
  11986.             case AUTH_KRB4: kv = 4; break; /* Don't assume values are same */
  11987.             case AUTH_KRB5: kv = 5; break;
  11988. #endif /* CK_KERBEROS */
  11989. #ifdef CK_SRP
  11990.             case AUTH_SRP: break;
  11991. #endif /* CK_SRP */
  11992. #ifdef CK_SSL
  11993.             case AUTH_SSL:
  11994.             case AUTH_TLS:
  11995.               break;
  11996. #endif /* CK_SSL */
  11997.             default:
  11998.               printf("?Authorization type not supported yet - \"%s\"\n",
  11999.                      atmbuf);
  12000.               return(-9);
  12001.           }
  12002. #ifdef IKSD
  12003.           if (inserver &&
  12004. #ifdef IKSDCONF
  12005.               iksdcf
  12006. #else
  12007.               1
  12008. #endif /* IKSDCONF */
  12009.               ) {
  12010.               if ((y = cmcfm()) < 0) return(y);
  12011.               printf("?Sorry, command disabled.\n");
  12012.               return(success = 0);
  12013.           }
  12014. #endif /* IKSD */
  12015. #ifdef CK_APC
  12016.           /* Don't let this be set remotely */
  12017.           if (apcactive == APC_LOCAL ||
  12018.               apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)) {
  12019.               if ((y = cmcfm()) < 0) return(y);
  12020.               return(success = 0);
  12021.           }
  12022. #endif /* CK_APC */
  12023.  
  12024.           switch(x) {
  12025. #ifdef CK_KERBEROS
  12026.             case AUTH_KRB4:
  12027.             case AUTH_KRB5: {
  12028.                 if ((x = cmkey(kv == 4 ? k4tab : k5tab,
  12029.                                kv == 4 ? nk4tab : nk5tab,
  12030.                                "Kerberos parameter","",xxstring)) < 0) {
  12031.                     return(x);
  12032.                 }
  12033.                 s = "";
  12034.                 switch (x) {
  12035. #ifdef KRB4
  12036.                   case XYKRBDBG:
  12037.                     if (kv == 4) {
  12038.                         if ((y = seton(&k4debug)) < 0)
  12039.                           return(y);
  12040. #ifdef NT
  12041.                         ck_krb4_debug(k4debug);
  12042. #endif /* NT */
  12043.                     } else {
  12044.                         return(-9);
  12045.                     }
  12046.                     break;
  12047. #endif /* KRB4 */
  12048.                   case XYKRBLIF:
  12049.                     if ((y = cmnum("TGT lifetime","600",10,&z,xxstring)) < 0)
  12050.                       return(y);
  12051.                     break;
  12052.                   case XYKRBPRE:
  12053.                     if (kv == 4) {
  12054.                         if ((y = seton(&krb4_d_preauth)) < 0)
  12055.                           return(y);
  12056.                     } else {
  12057.                         return(-9);
  12058.                     }
  12059.                     break;
  12060.                   case XYKRBINS:
  12061.                     if ((y = cmtxt("Instance name","",&s,xxstring)) < 0)
  12062.                       return(y);
  12063.                     break;
  12064.                   case XYKRBFWD:
  12065.                     if (kv == 5) {
  12066.                         if ((y = seton(&krb5_d_forwardable)) < 0)
  12067.                           return(y);
  12068.                     } else {
  12069.                         return(-9);
  12070.                     }
  12071.                     break;
  12072.                   case XYKRBPRX:
  12073.                     if (kv == 5) {
  12074.                         if ((y = seton(&krb5_d_proxiable)) < 0)
  12075.                           return(y);
  12076.                     } else {
  12077.                         return(-9);
  12078.                     }
  12079.                     break;
  12080.                   case XYKRBRNW:
  12081.                     if ((y = cmnum("TGT renewable lifetime",
  12082.                                    "0",10,&z,xxstring)) < 0)
  12083.                       return(y);
  12084.                     break;
  12085.                   case XYKRBADR:
  12086.                     if (kv == 5) {
  12087.                         if ((y = seton(&krb5_checkaddrs)) < 0)
  12088.                           return(y);
  12089.                     } else {
  12090.                         if ((y = seton(&krb4_checkaddrs)) < 0)
  12091.                           return(y);
  12092.                     }
  12093.                     break;
  12094.                   case XYKRBNAD:
  12095.                     if (kv == 5) {
  12096.                         if ((y = seton(&krb5_d_no_addresses)) < 0)
  12097.                           return(y);
  12098.                     }
  12099.                     break;
  12100.                   case XYKRBADD:
  12101.                     if (kv == 5) {
  12102.                         char * tmpaddrs[KRB5_NUM_OF_ADDRS];
  12103.                         for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
  12104.                           tmpaddrs[i] = NULL;
  12105.  
  12106.                         if ((y =
  12107.                              cmfld("List of IP addresses","",&s,xxstring)) < 0)
  12108.                           return(y);
  12109.                         makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
  12110.                         if ((y = cmcfm()) < 0) {
  12111.                             for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
  12112.                                 if (tmpaddrs[i] != NULL)
  12113.                                   free(tmpaddrs[i]);
  12114.                             }
  12115.                             return(y);
  12116.                         }
  12117.                         for (i = 0;
  12118.                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
  12119.                              i++) {
  12120.                             if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
  12121.                                 printf("invalid ip address: %s\n",
  12122.                                        tmpaddrs[i]);
  12123.                                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
  12124.                                     if (tmpaddrs[i] != NULL)
  12125.                                       free(tmpaddrs[i]);
  12126.                                 }
  12127.                                 return(-9);
  12128.                             }
  12129.                         }
  12130.                         for (i = 0;
  12131.                              i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];
  12132.                              i++) {
  12133.                             if (krb5_d_addrs[i])
  12134.                               free(krb5_d_addrs[i]);
  12135.                             krb5_d_addrs[i] = NULL;
  12136.                         }
  12137.                         for (i = 0;
  12138.                              i < KRB5_NUM_OF_ADDRS && tmpaddrs[i];
  12139.                              i++) {
  12140.                             krb5_d_addrs[i] = tmpaddrs[i];
  12141.                             tmpaddrs[i] = NULL;
  12142.                         }
  12143.                         krb5_d_addrs[i] = NULL;
  12144.                         return(success = 1);
  12145.                     }
  12146.                     break;
  12147.  
  12148.                   case XYKRBGET:
  12149.                     if (kv == 5) {
  12150.                         if ((y = seton(&krb5_autoget)) < 0)
  12151.                           return(y);
  12152.                     } else {
  12153.                         if ((y = seton(&krb4_autoget)) < 0)
  12154.                           return(y);
  12155.                     }
  12156.                     break;
  12157.                   case XYKRBDEL:
  12158.                     if ((z = cmkey(kdestab,nkdestab,
  12159.                                    "Auto Destroy Tickets",
  12160.                                    "never",xxstring)) < 0)
  12161.                       return(z);
  12162.                     break;
  12163.                   case XYKRBPR:
  12164.                     if ((y = cmtxt("User ID",uidbuf,&s,xxstring)) < 0)
  12165.                       return(y);
  12166.                     break;
  12167.                   case XYKRBRL:
  12168.                     if ((y = cmtxt("Name of realm","",&s,xxstring)) < 0)
  12169.                       return(y);
  12170.                     break;
  12171.                   case XYKRBKTB:
  12172.                     y = cmifi("Filename","",&s,&z,xxstring);
  12173.                     if (y != -3) {
  12174.                        if (y < 0)
  12175.                          return(y);
  12176.                        if (z) {
  12177.                          printf("?Wildcards not allowed\n");
  12178.                          return(-9);
  12179.                        }
  12180.                     }
  12181.                     break;
  12182.                   case XYKRBCC:
  12183.                     if ((y = cmofi("Filename","",&s,xxstring)) < 0)
  12184.                       return(y);
  12185.                     break;
  12186.                   case XYKRBSRV:
  12187.                     if ((y = cmtxt("Name of service to use in ticket",
  12188.                                    (kv == 4 ? "rcmd" : "host"),
  12189.                                    &s,
  12190.                                    xxstring
  12191.                                    )) < 0)
  12192.                       return(y);
  12193.                     break;
  12194.                   case XYKRBK5K4:
  12195.                     if (kv == 5) {
  12196.                         if ((y = seton(&krb5_d_getk4)) < 0)
  12197.                           return(y);
  12198.                     } else {
  12199.                         return(-9);
  12200.                     }
  12201.                     break;
  12202.                   case XYKRBPRM:        /* Prompt */
  12203.                     if ((z = cmkey(krbprmtab,2,"","",xxstring)) < 0)
  12204.                       return(z);
  12205.                     if ((y = cmtxt((z == KRB_PW_PRM) ?
  12206.   "Text of prompt;\nmay contain \"%s\" to be replaced by principal name" :
  12207.   "Text of prompt",
  12208.                                    "",
  12209.                                    &s,
  12210.                                    xxstring
  12211.                                    )
  12212.                          ) < 0)
  12213.                       return(y);
  12214.                     break;
  12215.                 }
  12216.                 ckstrncpy(line,s,LINBUFSIZ);
  12217.                 s = line;
  12218.                 if ((y = cmcfm()) < 0)
  12219.                   return(y);
  12220. #ifdef IKSD
  12221.                 if (inserver &&
  12222. #ifdef IKSDCONF
  12223.                     iksdcf
  12224. #else /* IKSDCONF */
  12225.                     1
  12226. #endif /* IKSDCONF */
  12227.                     )
  12228.                   return(success = 0);
  12229. #endif /* IKSD */
  12230.  
  12231.                 switch (x) {            /* Copy value to right place */
  12232.                   case XYKRBLIF:        /* Lifetime */
  12233.                     if (kv == 4)
  12234.                       krb4_d_lifetime = z;
  12235.                     else
  12236.                       krb5_d_lifetime = z;
  12237.                     break;
  12238.                   case XYKRBRNW:
  12239.                     if (kv == 5)
  12240.                       krb5_d_renewable = z;
  12241.                     break;
  12242.                   case XYKRBPR:         /* Principal */
  12243.                     s = brstrip(s);    /* Strip braces around. */
  12244.                     if (kv == 4)
  12245.                       makestr(&krb4_d_principal,s);
  12246.                     else
  12247.                       makestr(&krb5_d_principal,s);
  12248.                     break;
  12249.                   case XYKRBINS:        /* Instance */
  12250.                     if (kv == 4)
  12251.                       makestr(&krb4_d_instance,s);
  12252.                     else
  12253.                       makestr(&krb5_d_instance,s);
  12254.                     break;
  12255.                   case XYKRBRL:         /* Realm */
  12256.                     if (kv == 4)
  12257.                       makestr(&krb4_d_realm,s);
  12258.                     else
  12259.                       makestr(&krb5_d_realm,s);
  12260.                     break;
  12261.                   case XYKRBKTB:        /* Key Table */
  12262.                     if (kv == 4)
  12263.                       makestr(&k4_keytab,s);
  12264.                     else
  12265.                       makestr(&k5_keytab,s);
  12266.                     break;
  12267.                   case XYKRBCC:         /* Credentials cache */
  12268.                     makestr(&krb5_d_cc,s);
  12269.                     break;
  12270.                   case XYKRBSRV:        /* Service Name */
  12271.                     if (kv == 4)
  12272.                       makestr(&krb4_d_srv,s);
  12273.                     else
  12274.                       makestr(&krb5_d_srv,s);
  12275.                     break;
  12276.                   case XYKRBDEL:
  12277.                     if (kv == 5)
  12278.                       krb5_autodel = z;
  12279.                     else
  12280.                       krb4_autodel = z;
  12281.                     break;
  12282.                   case XYKRBPRM:        /* Prompt */
  12283.                     if (s == "") s = NULL;
  12284.                     if (s) {
  12285.                         s = brstrip(s);
  12286.                         if (s == "") s = NULL;
  12287.                     }
  12288.                     switch (z) {
  12289.                       case KRB_PW_PRM: { /* Password */
  12290.                           /* Check that there are no more than */
  12291.                           /* two % fields and % must followed by 's'. */
  12292.                           int i,n,len;
  12293.                           len = strlen(s);
  12294.                           for (i = 0, n = 0; i < len; i++) {
  12295.                               if (s[i] == '%') {
  12296.                                   if (s[i+1] != '%') {
  12297.                                       if (s[i+1] != 's') {
  12298.                                           printf(
  12299.                                            "Only %%s fields are permitted.\n"
  12300.                                                  );
  12301.                                           return(-9);
  12302.                                       }
  12303.                                       if (++n > 2) {
  12304.                                           printf(
  12305.                                       "Only two %%s fields are permitted.\n");
  12306.                                           return(-9);
  12307.                                       }
  12308.                                   }
  12309.                                   i++;
  12310.                               }
  12311.                           }
  12312.                           if (kv == 5)
  12313.                             makestr(&k5pwprompt,s);
  12314.                           else
  12315.                             makestr(&k4pwprompt,s);
  12316.                           break;
  12317.                       }
  12318.                       case KRB_PR_PRM: { /* Principal */
  12319.                           /* Check to make sure there are no % fields */
  12320.                           int i,len;
  12321.                           len = strlen(s);
  12322.                           for (i = 0; i < len; i++) {
  12323.                               if (s[i] == '%') {
  12324.                                   if (s[i+1] != '%') {
  12325.                                       printf(
  12326.                                   "%% fields are not used in this command.\n");
  12327.                                       return(-9);
  12328.                                   }
  12329.                                   i++;
  12330.                               }
  12331.                           }
  12332.                           if (kv == 5)
  12333.                             makestr(&k5prprompt,s);
  12334.                           else
  12335.                             makestr(&k4prprompt,s);
  12336.                           break;
  12337.                       }
  12338.                     }
  12339.                 }
  12340.                 break;
  12341.             }
  12342. #endif /* CK_KERBEROS */
  12343. #ifdef CK_SRP
  12344.             case AUTH_SRP: {
  12345.                 if ((x = cmkey(srptab, nsrptab,
  12346.                                "SRP parameter","",xxstring)) < 0) {
  12347.                     return(x);
  12348.                 }
  12349.                 s = "";
  12350.                 switch (x) {
  12351.                   case XYSRPPRM:        /* Prompt */
  12352.                     if ((z = cmkey(srpprmtab,1,"","",xxstring)) < 0)
  12353.                       return(z);
  12354.                     if ((y = cmtxt(
  12355.   "Text of prompt;\nmay contain one \"%s\" to be replaced by the username",
  12356.                                    "",
  12357.                                    &s,
  12358.                                    xxstring
  12359.                                    )
  12360.                          ) < 0)
  12361.                       return(y);
  12362.                     break;
  12363.                 }
  12364.                 ckstrncpy(line,s,LINBUFSIZ);
  12365.                 s = line;
  12366.                 if ((y = cmcfm()) < 0)
  12367.                   return(y);
  12368.                 switch (x) {            /* Copy value to right place */
  12369.                   case XYSRPPRM:        /* Prompt */
  12370.                     if (s == "") s = NULL;
  12371.                     if (s) {
  12372.                         s = brstrip(s);
  12373.                         if (s == "") s = NULL;
  12374.                     }
  12375.                     switch (z) {
  12376.                       case SRP_PW_PRM: { /* Password */
  12377.                           /* Check %s fields */
  12378.                           int i,n,len;
  12379.                           len = strlen(s);
  12380.                           for (i = 0, n = 0; i < len; i++) {
  12381.                               if (s[i] == '%') {
  12382.                                   if (s[i+1] != '%') {
  12383.                                       if (s[i+1] != 's') {
  12384.                                           printf(
  12385.                                           "Only %%s fields are permitted.\n");
  12386.                                           return(-9);
  12387.                                       }
  12388.                                       if (++n > 1) {
  12389.                                           printf(
  12390.                                        "Only one %%s field is permitted.\n");
  12391.                                           return(-9);
  12392.                                       }
  12393.                                   }
  12394.                                   i++;
  12395.                               }
  12396.                           }
  12397.                           makestr(&srppwprompt,s);
  12398.                           break;
  12399.                       }
  12400.                     }
  12401.                 }
  12402.                 break;
  12403.             }
  12404. #endif /* CK_SRP */
  12405. #ifdef CK_SSL
  12406.             case AUTH_SSL:
  12407.             case AUTH_TLS: {
  12408.                 if ((z = cmkey(ssltab, nssltab,
  12409.                            (x == AUTH_SSL ? "SSL parameter" : "TLS parameter"),
  12410.                            "",xxstring)) < 0)
  12411.                   return(z);
  12412.                 s = "";
  12413.                 switch (z) {
  12414.                   case XYSSLRCFL:       /* SSL/TLS RSA Certs file */
  12415.                   case XYSSLRCCF:       /* SSL/TLS RSA Certs Chain file */
  12416.                   case XYSSLRKFL:       /* SSL/TLS RSA Key File */
  12417.                   case XYSSLDCFL:       /* SSL/TLS DSA Certs file */
  12418.                   case XYSSLDCCF:       /* SSL/TLS DSA Certs Chain file */
  12419.                   case XYSSLDKFL:       /* SSL/TLS DH Key File */
  12420.                   case XYSSLDPFL:       /* SSL/TLS DH Param File */
  12421.                   case XYSSLCRL:        /* SSL/TLS CRL File */
  12422.                   case XYSSLVRFF:       /* SSL/TLS Verify File */
  12423.                   case XYSSLRND:        /* SSL/TLS Random File */
  12424.                     y = cmifi("Filename","",&s,&x,xxstring);
  12425.                     if (y != -3) {
  12426.                         if (y < 0)
  12427.                           return(y);
  12428.                         if (x) {
  12429.                             printf("?Wildcards not allowed\n");
  12430.                             return(-9);
  12431.                         }
  12432.                     }
  12433.                     ckstrncpy(line,s,LINBUFSIZ);
  12434.                     s = line;
  12435.                     s = brstrip(s);
  12436.                     if ((y = cmcfm()) < 0)
  12437.                       return(y);
  12438.                     switch (z) {
  12439.                       case XYSSLRCFL:   /* SSL/TLS RSA Certs file */
  12440.                         if (!s[0] && ssl_rsa_cert_file) {
  12441.                             free(ssl_rsa_cert_file);
  12442.                             ssl_rsa_cert_file = NULL;
  12443.                         } else if (s[0]) {
  12444.                             makestr(&ssl_rsa_cert_file,s);
  12445.                             if (!ssl_rsa_key_file)
  12446.                               makestr(&ssl_rsa_key_file,s);
  12447.                         }
  12448.                         break;
  12449.                       case XYSSLRCCF:   /* SSL/TLS RSA Certs Chain file */
  12450.                           if (!s[0] && ssl_rsa_cert_chain_file) {
  12451.                               free(ssl_rsa_cert_chain_file);
  12452.                               ssl_rsa_cert_chain_file = NULL;
  12453.                           } else if (s[0]) {
  12454.                               makestr(&ssl_rsa_cert_chain_file,s);
  12455.                           }
  12456.                           break;
  12457.                       case XYSSLRKFL:   /* SSL/TLS RSA Key File */
  12458.                         if (!s[0] && ssl_rsa_key_file) {
  12459.                             free(ssl_rsa_key_file);
  12460.                             ssl_rsa_key_file = NULL;
  12461.                         } else if (s[0]) {
  12462.                             makestr(&ssl_rsa_key_file,s);
  12463.                         }
  12464.                         break;
  12465.                       case XYSSLDCFL:   /* SSL/TLS DSA Certs file */
  12466.                         if (!s[0] && ssl_dsa_cert_file) {
  12467.                             free(ssl_dsa_cert_file);
  12468.                             ssl_dsa_cert_file = NULL;
  12469.                         } else if (s[0]) {
  12470.                             makestr(&ssl_dsa_cert_file,s);
  12471.                             if (!ssl_dh_key_file)
  12472.                               makestr(&ssl_dh_key_file,s);
  12473.                         }
  12474.                         break;
  12475.                       case XYSSLDCCF:   /* SSL/TLS DSA Certs Chain file */
  12476.                           if (!s[0] && ssl_dsa_cert_chain_file) {
  12477.                               free(ssl_dsa_cert_chain_file);
  12478.                               ssl_dsa_cert_chain_file = NULL;
  12479.                           } else if (s[0]) {
  12480.                               makestr(&ssl_dsa_cert_chain_file,s);
  12481.                           }
  12482.                           break;
  12483.                       case XYSSLDKFL:   /* SSL/TLS DH Key File */
  12484.                         if (!s[0] && ssl_dh_key_file) {
  12485.                             free(ssl_dh_key_file);
  12486.                             ssl_dh_key_file = NULL;
  12487.                         } else if (s[0]) {
  12488.                             makestr(&ssl_dh_key_file,s);
  12489.                         }
  12490.                         break;
  12491.                       case XYSSLDPFL:   /* SSL/TLS DH Param File */
  12492.                         if (!s[0] && ssl_dh_param_file) {
  12493.                             free(ssl_dh_param_file);
  12494.                             ssl_dh_param_file = NULL;
  12495.                         } else if (s[0]) {
  12496.                             makestr(&ssl_dh_param_file,s);
  12497.                         }
  12498.                         break;
  12499.                       case XYSSLCRL:    /* SSL/TLS CRL File */
  12500.                         if (!s[0] && ssl_crl_file) {
  12501.                             free(ssl_crl_file);
  12502.                             ssl_crl_file = NULL;
  12503.                         } else if (s[0]) {
  12504.                             makestr(&ssl_crl_file,s);
  12505.                         }
  12506.                         break;
  12507.                       case XYSSLVRFF:   /* SSL/TLS Verify File */
  12508.                         if (!s[0] && ssl_verify_file) {
  12509.                             free(ssl_verify_file);
  12510.                             ssl_verify_file = NULL;
  12511.                         } else if (s[0]) {
  12512.                             makestr(&ssl_verify_file,s);
  12513.                         }
  12514.                         break;
  12515.                       case XYSSLRND:    /* SSL/TLS Random File */
  12516.                         if (!s[0] && ssl_rnd_file) {
  12517.                             free(ssl_rnd_file);
  12518.                             ssl_rnd_file = NULL;
  12519.                         } else if (s[0]) {
  12520.                             makestr(&ssl_rnd_file,s);
  12521.                         }
  12522.                         break;
  12523.                     }
  12524.                     break;
  12525.  
  12526.                   case XYSSLCRLD:
  12527.                   case XYSSLVRFD: {
  12528.                     char * d = NULL;
  12529.                     if (z == XYSSLVRFD)
  12530.                       d= getenv("SSL_CERT_DIR");
  12531.                     if (d == NULL)
  12532.                         d = "";
  12533.                     if ((y = cmdir("Directory",d,&s,xxstring)) < 0)
  12534.               if (y != -3)
  12535.             return(y);
  12536.                     ckstrncpy(line,s,LINBUFSIZ);
  12537.                     s = line;
  12538.                     s = brstrip(s);
  12539.                     if ((y = cmcfm()) < 0)
  12540.                       return(y);
  12541.                     switch(z) {
  12542.                       case XYSSLCRLD:
  12543.                         if (!s[0] && ssl_crl_dir) {
  12544.                             free(ssl_crl_dir);
  12545.                             ssl_crl_dir = NULL;
  12546.                         } else if (s[0]) {
  12547.                             makestr(&ssl_crl_dir,s);
  12548.                         }
  12549.                         break;
  12550.                       case XYSSLVRFD:
  12551.                         if (!s[0] && ssl_verify_dir) {
  12552.                             free(ssl_verify_dir);
  12553.                             ssl_verify_dir = NULL;
  12554.                         } else if (s[0]) {
  12555.                             makestr(&ssl_verify_dir,s);
  12556.                         }
  12557.                         break;
  12558.                     }
  12559.                     break;
  12560.                   }
  12561.                   case XYSSLCOK:        /* SSL/TLS Certs-Ok flag */
  12562.                     if ((y = seton(&ssl_certsok_flag)) < 0)
  12563.                       return(y);
  12564.                     break;
  12565.                   case XYSSLDBG:                /* SSL/TLS Debug flag */
  12566.                     if ((y = seton(&ssl_debug_flag)) < 0)
  12567.                       return(y);
  12568.                     break;
  12569.                   case XYSSLON:         /* SSL/TLS Only flag */
  12570.                     switch (x) {
  12571.                       case AUTH_SSL:
  12572.                         if ((y = seton(&ssl_only_flag)) < 0)
  12573.                           return(y);
  12574.                         break;
  12575.                       case AUTH_TLS:
  12576.                         if ((y = seton(&tls_only_flag)) < 0)
  12577.                           return(y);
  12578.                         break;
  12579.                     }
  12580.                     break;
  12581.                   case XYSSLVRB:        /* SSL/TLS Verbose flag */
  12582.                     if ((y = seton(&ssl_verbose_flag)) < 0)
  12583.                       return(y);
  12584.                     break;
  12585.                   case XYSSLVRF:        /* SSL/TLS Verify flag */
  12586.                     if ((x = cmkey(sslvertab, nsslvertab,
  12587.                                    "SSL/TLS verify mode",
  12588.                                    "peer-cert",xxstring)) < 0)
  12589.                       return(x);
  12590.                     if ((y = cmcfm()) < 0)
  12591.                       return(y);
  12592.                     ssl_verify_flag = x;
  12593.                     break;
  12594.                   case XYSSLDUM:
  12595.                     if ((y = seton(&ssl_dummy_flag)) < 0)
  12596.                       return(y);
  12597.                     break;
  12598.                   case XYSSLCL: {               /* SSL/TLS Cipher List */
  12599. #ifdef COMMENT
  12600.                       /* This code is used to generate a colon delimited */
  12601.                       /* list of the ciphers currently in use to be used */
  12602.                       /* as the default for cmtxt().  However, a better  */
  12603.                       /* default is simply the magic keyword "ALL".      */
  12604.                       CHAR def[1024] = "";
  12605.                       if (ssl_con != NULL) {
  12606.                           CHAR * p = NULL, *q = def;
  12607.                           int i, len;
  12608.  
  12609.                           for (i = 0; ; i++) {
  12610.                               p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
  12611.                               if (p == NULL)
  12612.                                 break;
  12613.                               len = strlen(p);
  12614.                               if (q+len+1 >= def+1024)
  12615.                                 break;
  12616.                               if (i != 0)
  12617.                                 *q++ = ':';
  12618.                               strcpy(q,p);
  12619.                               q += len;
  12620.                           }
  12621.                       }
  12622. #endif /* COMMENT */
  12623.                       char * p = getenv("SSL_CIPHER");
  12624.                       if (!p)
  12625.                         p = "ALL";
  12626.                       if ((y = cmtxt(
  12627.                     "Colon-delimited list of ciphers or ALL (case-sensitive)",
  12628.                                      p,
  12629.                                      &s,
  12630.                                      xxstring
  12631.                                      )
  12632.                            ) < 0)
  12633.                         return(y);
  12634.                       makestr(&ssl_cipher_list,s);
  12635.                       if (ssl_con == NULL) {
  12636.                           SSL_library_init();
  12637.                           ssl_ctx = (SSL_CTX *)
  12638.                             SSL_CTX_new((SSL_METHOD *)TLSv1_method());
  12639.                           if (ssl_ctx != NULL)
  12640.                             ssl_con= (SSL *) SSL_new(ssl_ctx);
  12641.                       }
  12642.                       if (ssl_con) {
  12643.                           SSL_set_cipher_list(ssl_con,ssl_cipher_list);
  12644.                       }
  12645.                       break;
  12646.                   }
  12647.                 }
  12648.                 break;
  12649.             }
  12650. #endif /* CK_SSL */
  12651.             default:
  12652.               break;
  12653.           }
  12654.           return(success = 1);
  12655.       }
  12656. #endif /* CK_AUTHENTICATION */
  12657.  
  12658. #ifndef NOSPL
  12659.       case XYFUNC:
  12660.         if ((x = cmkey(functab,nfunctab,"","diagnostics",xxstring)) < 0)
  12661.           return(x);
  12662.         switch (x) {
  12663.           case FUNC_DI: return(seton(&fndiags));
  12664.           case FUNC_ER: return(seton(&fnerror));
  12665.           default:      return(-2);
  12666.         }
  12667. #endif /* NOSPL */
  12668.  
  12669.       case XYSLEEP:                     /* SET SLEEP / PAUSE */
  12670.         if ((x = cmkey(sleeptab,1,"","cancellation",xxstring)) < 0)
  12671.           return(x);
  12672.         return(seton(&sleepcan));
  12673.  
  12674.       case XYCD:                        /* SET CD */
  12675.         if ((x = cmkey(cdtab,ncdtab,"","",xxstring)) < 0)
  12676.           return(x);
  12677.         switch (x) {
  12678.       case XYCD_H: {        /* SET CD HOME */
  12679.           extern char * myhome;
  12680.           if ((y = cmdir("Directory name",zhome(),&s,xxstring)) < 0)
  12681.         return(y);
  12682.           makestr(&myhome,s);
  12683.           return(success = 1);
  12684.       }
  12685.           case XYCD_M:                  /* SET CD MESSAGE */
  12686.             if ((x = cmkey(cdmsg,ncdmsg,"","",xxstring)) < 0)
  12687.               return(x);
  12688.             if (x == 2) {               /* CD MESSAGE FILE */
  12689.                 if ((x = cmtxt("Name of file","",&s,NULL)) < 0)
  12690.                   return(x);
  12691.                 if (!*s) {
  12692.                     s = NULL;
  12693. #ifndef NOXFER
  12694.                     srvcdmsg = 0;
  12695. #endif /* NOXFER */
  12696.                 }
  12697.                 makestr(&cdmsgstr,s);
  12698.                 makelist(cdmsgstr,cdmsgfile,8);
  12699.                 return(success = 1);
  12700.             }
  12701.  
  12702.             if ((y = cmcfm()) < 0) return(y); /* CD-MESSAGE ON/OFF */
  12703. #ifndef NOXFER
  12704.             if (x > 0)
  12705.               srvcdmsg |= 2;
  12706.             else
  12707.               srvcdmsg &= 1;
  12708. #endif /* NOXFER */
  12709.             return(success = 1);
  12710.  
  12711.           case XYCD_P: {                /* SET CD PATH */
  12712.               extern char * ckcdpath;
  12713.               if ((x = cmtxt("CD PATH string","",&s,xxstring)) < 0)
  12714.                 return(x);
  12715.               makestr(&ckcdpath,s);
  12716.               return(success = 1);
  12717.           }
  12718.         }
  12719.  
  12720. #ifndef NOLOCAL
  12721. #ifdef STOPBITS
  12722.       case XYSTOP:                      /* STOP-BITS */
  12723.         if ((x = cmkey(stoptbl,2,"Stop bits for serial device","",
  12724.                        xxstring)) < 0)
  12725.           return(x);
  12726.         if ((y = cmcfm()) < 0)
  12727.           return(y);
  12728.         if (x > 0 && x < 3) {
  12729.             stopbits = x;
  12730. #ifdef TN_COMPORT
  12731.             if (network && istncomport()) {
  12732.                 tnsettings(-1, x);
  12733.                 return(success = 1);
  12734.             }
  12735. #endif /* TN_COMPORT */
  12736. #ifdef HWPARITY
  12737.             return(success = 1);
  12738. #else /* HWPARITY */
  12739.             return(-2);
  12740. #endif /* HWPARITY */
  12741.         } else
  12742.           return(-2);
  12743. #endif /* STOPBITS */
  12744.  
  12745.       case XYDISC: {
  12746.           extern int clsondisc;
  12747.           return(seton(&clsondisc));
  12748.       }
  12749.  
  12750.       case XYSERIAL: {
  12751.           /* char c; */
  12752.           extern int cmask;
  12753.           if ((x = cmkey(sertbl,nsertbl,
  12754.                          "Serial device character size, parity, and stop bits",
  12755.                          "8N1", xxstring)) < 0)
  12756.             return(x);
  12757.           ckstrncpy(line,atmbuf,LINBUFSIZ); /* Associated keyword string */
  12758.           s = line;
  12759.           if ((y = cmcfm()) < 0)
  12760.             return(y);
  12761.           ckstrncpy(line,sernam[x],LINBUFSIZ);
  12762.           s = line;
  12763.           if (s[0] != '8' && s[0] != '7') /* Char size */
  12764.             return(-2);
  12765.           else
  12766.             z = s[0] - '0';
  12767.           if (isupper(s[1]))            /* Parity */
  12768.             s[1] = tolower(s[1]);
  12769.           if (s[2] != '1' && s[2] != '2') /* Stop bits */
  12770.             return(-2);
  12771.           else
  12772.             stopbits = s[2] - '0';
  12773.           if (z == 8) {                 /* 8 bits + parity (or not) */
  12774.               parity = 0;               /* Set parity */
  12775.               hwparity = (s[1] == 'n') ? 0 : s[1];
  12776.               setcmask(8);              /* Also set TERM BYTESIZE to 8 */
  12777.           } else {                      /* 7 bits plus parity */
  12778.               parity = (s[1] == 'n') ? 0 : s[1];
  12779.               hwparity = 0;
  12780.               setcmask(7);              /* Also set TERM BYTESIZE to 7 */
  12781.           }
  12782. #ifdef TN_COMPORT
  12783.           if (network && !istncomport())
  12784.             tnsettings(parity, stopbits);
  12785. #endif /* TN_COMPORT */
  12786.  
  12787.           return(success = 1);          /* from SET SERIAL */
  12788.       }
  12789.  
  12790.       case XYOPTS: {                    /* SET OPTIONS */
  12791.           extern int setdiropts();
  12792.           extern int settypopts();
  12793. #ifdef CKPURGE
  12794.           extern int setpurgopts();
  12795. #endif /* CKPURGE */
  12796.           if ((x = cmkey(optstab,noptstab,"for command","", xxstring)) < 0)
  12797.             return(x);
  12798.           switch (x) {
  12799. #ifndef NOFRILLS
  12800.             case XXDEL:
  12801.               return(setdelopts());
  12802. #endif /* NOFRILLS */
  12803.             case XXDIR:
  12804.               return(setdiropts());
  12805.             case XXTYP:
  12806.               return(settypopts());
  12807. #ifdef CKPURGE
  12808.             case XXPURGE:
  12809.               return(setpurgopts());
  12810. #endif /* CKPURGE */
  12811.             default:
  12812.               return(-2);
  12813.           }
  12814.       }
  12815. #endif /* NOLOCAL */
  12816. #ifndef NOXFER
  12817.       case XYQ8FLG: {
  12818.           extern int q8flag;
  12819.           return(seton(&q8flag));
  12820.       }
  12821.       case XYTIMER: {
  12822.           extern int asktimer;
  12823.           y = cmnum("Time limit for ASK command, seconds","0",10,&x,xxstring);
  12824. #ifdef QNX16
  12825.           return(setnum(&asktimer,x,y,32767));
  12826. #else
  12827.           return(setnum(&asktimer,x,y,86400));
  12828. #endif /* QNX16 */
  12829.       }
  12830.       case XYFACKB: {
  12831.           extern int fackbug;
  12832.           return(seton(&fackbug));
  12833.       }
  12834. #endif /* NOXFER */
  12835.  
  12836.       case XYHINTS:
  12837.         return(seton(&hints));
  12838.  
  12839. #ifndef NOSPL
  12840.       case XYEVAL: {
  12841.           extern int oldeval;
  12842.           if ((x = cmkey(oldnew,2,"","", xxstring)) < 0)
  12843.             return(x);
  12844.           if ((y = cmcfm()) < 0)
  12845.             return(y);
  12846.           oldeval = x;
  12847.           return(success = 1);
  12848.       }
  12849. #endif /* NOSPL */
  12850.  
  12851. #ifndef NOXFER
  12852.       case XYFACKP: {
  12853.           extern int fackpath;
  12854.           return(seton(&fackpath));
  12855.       }
  12856. #endif /* NOXFER */
  12857.  
  12858.       case XYQNXPL: {
  12859.           extern int qnxportlock;
  12860.           return(seton(&qnxportlock));
  12861.       }
  12862.  
  12863. #ifndef NOCMDL
  12864. #ifdef IKSD
  12865.       case XYIKS: {
  12866.           int setiks();
  12867.           return(setiks());
  12868.       }
  12869. #endif /* IKSD */
  12870. #endif /* NOCMDL */
  12871.  
  12872. #ifdef CKROOT
  12873.       case XYROOT:
  12874.         return(dochroot());
  12875. #endif /* CKROOT */
  12876.  
  12877. #ifndef NOSPL
  12878. #ifndef NOSEXP
  12879.       case XYSEXP: {
  12880.           if ((x = cmkey(sexptab,2,"","", xxstring)) < 0)
  12881.             return(x);
  12882.           switch (x) {
  12883.             case 0:
  12884.               if ((x = cmkey(ooatab,3,"","automatic", xxstring)) < 0)
  12885.                 return(x);
  12886.               if ((y = cmcfm()) < 0)
  12887.                 return(y);
  12888.               sexpecho = x;
  12889.               break;
  12890.             case 1: {
  12891.                 int i, xx;
  12892.                 xx = sexpmaxdep;
  12893.                 if ((y = cmnum("Maximum recursion depth",
  12894.                                "1000",10,&x,xxstring)) < 0)
  12895.                   return(y);
  12896.                 z = setnum(&sexpmaxdep,x,y,-1);
  12897.                 if (z < 0)
  12898.                   return(z);
  12899.                 if (sxresult) {         /* Free old stack if allocated */
  12900.                     for (i = 0; i < xx; i++)
  12901.                       if (sxresult[i]) free(sxresult[i]);
  12902.                     free((char *)sxresult);
  12903.                     if (sxrlen) free((char *)sxrlen);
  12904.                     sxresult = NULL;
  12905.                     sxrlen = NULL;
  12906.                 }
  12907.                 break;
  12908.             }
  12909.           }
  12910.           return(success = 1);
  12911.       }
  12912. #endif /* NOSEXPL */
  12913. #endif /* NOSPL */
  12914.  
  12915. #ifdef NEWFTP
  12916.       case XYGPR: {
  12917.           extern struct keytab gprtab[];
  12918.           extern int ftpget;
  12919.           if ((x = cmkey(gprtab,3,"","kermit", xxstring)) < 0)
  12920.             return(x);
  12921.           if ((y = cmcfm()) < 0)
  12922.             return(y);
  12923.           ftpget = x;
  12924.           return(success = 1);
  12925.       }
  12926. #endif /* NEWFTP */
  12927.  
  12928. #ifdef ANYSSH
  12929.       case XYSSH:
  12930.         return(dosetssh());
  12931. #endif /* ANYSHH */
  12932.  
  12933. #ifdef LOCUS
  12934.       case XYLOCUS:
  12935.           if ((x = cmkey(locustab,nlocustab,"",
  12936. #ifdef KUI
  12937.              "ask"
  12938. #else
  12939.              "auto"
  12940. #endif /* KUI */
  12941.              ,xxstring)) < 0)
  12942.             return(x);
  12943.           if ((y = cmcfm()) < 0)
  12944.             return(y);
  12945.           if (x == 2 || x == 3) {    /* AUTO or ASK */
  12946.               setautolocus(x - 1);    /* Two forms of automatic locusing */
  12947.           /* setlocus(1,0); */      /* we're not changing the locus here */
  12948.           } else {            /* LOCAL or REMOTE */
  12949.               setautolocus(0);        /* No automatic Locus changing */
  12950.               setlocus(x,0);        /* Set Locus as requested */
  12951.           }
  12952.           return(success = 1);
  12953. #endif /* LOCUS */
  12954.  
  12955. #ifdef KUI
  12956.       case XYGUI:
  12957.         return(setgui());
  12958. #endif /* KUI */
  12959.  
  12960.       default:
  12961.          if ((x = cmcfm()) < 0) return(x);
  12962.          printf("Not implemented - %s\n",cmdbuf);
  12963.          return(success = 0);
  12964.     }
  12965. }
  12966.  
  12967. /*
  12968.   H U P O K  --  Is Hangup OK?
  12969.  
  12970.   Issues a warning and gets OK from user depending on whether a connection
  12971.   seems to be open and what the SET EXIT WARNING setting is.  Returns:
  12972.     0 if not OK to hang up or exit (i.e. user said No);
  12973.     nonzero if OK.
  12974.   Argument x is used to differentiate the EXIT command from SET LINE / HOST.
  12975. */
  12976. int
  12977. hupok(x) int x; {                       /* Returns 1 if OK, 0 if not OK */
  12978.     int y, z = 1;
  12979.     extern int exithangup;
  12980. #ifdef VMS
  12981.     extern int batch;
  12982.  
  12983.     if (batch)                          /* No warnings in batch */
  12984.       return(1);
  12985. #else
  12986. #ifdef UNIX
  12987.     if (backgrd)                        /* No warnings in background */
  12988.       return(1);
  12989. #endif /* UNIX */
  12990. #endif /* VMS */
  12991.  
  12992.     debug(F101,"hupok local","",local);
  12993.  
  12994.     if (!local)                         /* No warnings in remote mode */
  12995.       return(1);
  12996.  
  12997.     if (x == 0 && exithangup == 0)      /* EXIT and EXIT HANGUP is OFF */
  12998.       return(1);
  12999.  
  13000.     debug(F101,"hupok x","",x);
  13001.     debug(F101,"hupok xitwarn","",xitwarn);
  13002.     debug(F101,"hupok network","",network);
  13003.     debug(F101,"hupok haveline","",haveline);
  13004.  
  13005.     if ((local && xitwarn) ||           /* Is a connection open? */
  13006.         (!x && xitwarn == 2)) {         /* Or Always give warning on EXIT */
  13007.         int needwarn = 0;
  13008.         char warning[256];
  13009.  
  13010.         if (network) {
  13011.             if (ttchk() >= 0)
  13012.               needwarn = 1;
  13013.             /* A connection seems to be open but it can't possibly be */
  13014.             if (!haveline)
  13015.               needwarn = 0;
  13016.             if (needwarn) {
  13017.                 if (strcmp(ttname,"*"))
  13018.                     ckmakmsg(warning,256,
  13019.                               " A network connection to ",ttname,
  13020.                               " might still be active.\n",NULL);
  13021.                 else
  13022.                   ckstrncpy(warning,
  13023.                    " An incoming network connection might still be active.\n",
  13024.                              256);
  13025.             }
  13026.         } else {                        /* Serial connection */
  13027.             if (carrier == CAR_OFF)     /* SET CARRIER OFF */
  13028.               needwarn = 0;             /* so we don't care about carrier. */
  13029.             else if ((y = ttgmdm()) >= 0) /* else, get modem signals */
  13030.               needwarn = (y & BM_DCD);  /* Check for carrier */
  13031.             else                        /* If we can't get modem signals... */
  13032.               needwarn = (ttchk() >= 0);
  13033.             /* A connection seems to be open but it can't possibly be */
  13034.             if (!haveline || !exithangup)
  13035.               needwarn = 0;
  13036.             if (needwarn)
  13037.                 ckmakmsg(warning,256,
  13038.                      " A serial connection might still be active on ",
  13039.                      ttname,".\n",NULL);
  13040.         }
  13041.  
  13042. /* If a warning was issued, get user's permission to EXIT. */
  13043.  
  13044.         if (needwarn || (!x && xitwarn == 2 && local)) {
  13045. #ifdef COMMENT
  13046.         printf("%s",warning);
  13047.             z = getyesno(x ? "OK to close? " : "OK to exit? ",0);
  13048.             debug(F101,"hupok getyesno","",z);
  13049.             if (z < -3) z = 0;
  13050. #else
  13051.         z = uq_ok(warning,
  13052.               x ? "OK to close? " : "OK to exit? ",
  13053.               3,
  13054.               NULL,
  13055.               0
  13056.               );
  13057.             debug(F101,"hupok uq_ok","",z);
  13058.         if (z < 0) z = 0;
  13059. #endif /* COMMENT */
  13060.         }
  13061.     }
  13062.     return(z);
  13063. }
  13064.  
  13065. #ifndef NOSHOW
  13066. VOID
  13067. shoctl() {                              /* SHOW CONTROL-PREFIXING */
  13068. #ifdef CK_SPEED
  13069.     int i;
  13070. #ifdef OS2
  13071.     int zero;
  13072. #endif /* OS2 */
  13073.     printf(
  13074. "\ncontrol quote = %d, applied to (0 = unprefixed, 1 = prefixed):\n\n",
  13075.            myctlq);
  13076. #ifdef OS2
  13077. #ifndef UNPREFIXZERO
  13078.     zero = ctlp[0];
  13079.     if (protocol == PROTO_K)            /* Zero can't be unprefixed */
  13080.       ctlp[0] = 1;                      /* for Kermit */
  13081. #endif /* UNPREFIXZERO */
  13082. #endif /* OS2 */
  13083.     for (i = 0; i < 16; i++) {
  13084.         printf("  %3d: %d   %3d: %d ",i,ctlp[i], i+16, ctlp[i+16]);
  13085.         if (i == 15)
  13086.           printf("  127: %d",ctlp[127]);
  13087.         else
  13088.           printf("        ");
  13089.         printf("  %3d: %d   %3d: %d ",i+128,ctlp[i+128], i+144, ctlp[i+144]);
  13090.         if (i == 15)  printf("  255: %d",ctlp[255]);
  13091.         printf("\n");
  13092.     }
  13093.     printf("\n");
  13094. #ifndef UNPREFIXZERO
  13095. #ifdef OS2
  13096.     ctlp[0] = zero;
  13097. #endif /* OS2 */
  13098. #endif /* UNPREFIXZERO */
  13099.  
  13100. #endif /* CK_SPEED */
  13101. }
  13102.  
  13103. #ifndef NOXFER
  13104. VOID
  13105. shodbl() {                              /* SHOW DOUBLE/IGNORE */
  13106. #ifdef CKXXCHAR
  13107.     int i, n = 0;
  13108.     printf("\nSET SEND DOUBLE characters:\n");
  13109.     for (i = 0; i < 255; i++) {
  13110.         if (dblt[i] & 2) {
  13111.             n++;
  13112.             printf(" %d", i);
  13113.         }
  13114.     }
  13115.     if (n == 0)
  13116.       printf(" (none)");
  13117.     n = 0;
  13118.     printf("\nSET RECEIVE IGNORE characters:\n");
  13119.     for (i = 0; i < 255; i++) {
  13120.         if (dblt[i] & 1) {
  13121.             n++;
  13122.             printf(" %d", i);
  13123.         }
  13124.     }
  13125.     if (n == 0)
  13126.       printf(" (none)");
  13127.     printf("\n\n");
  13128. #endif /* CKXXCHAR */
  13129. }
  13130. #endif /* NOXFER */
  13131. #endif /* NOSHOW */
  13132.  
  13133. #ifndef NOPUSH
  13134. #ifdef CK_REXX
  13135. /*
  13136.   Rexx command.  Note, this is not OS/2-specific, because Rexx also runs
  13137.   on other systems where C-Kermit also runs, like the Amiga.
  13138. */
  13139. #define REXBUFL 100                     /* Change this if neccessary */
  13140. char rexxbuf[REXBUFL] = { '\0' };       /* Rexx's return value (string) */
  13141.  
  13142. int
  13143. dorexx() {
  13144.     int x, y;
  13145.     char *rexxcmd;
  13146.  
  13147.         if ((x = cmtxt("Rexx command","",&rexxcmd,xxstring)) < 0)
  13148.           return(x);
  13149.  
  13150. #ifdef IKSD
  13151.     if (inserver) {
  13152.         printf("?Sorry, command disabled.\r\n");
  13153.         return(success = 0);
  13154.     }
  13155. #endif /* IKSD */
  13156. #ifdef CK_APC
  13157.     /* Don't let this be set remotely */
  13158.     if (apcactive == APC_LOCAL ||
  13159.         apcactive == APC_REMOTE && !(apcstatus & APC_UNCH))
  13160.       return(success = 0);
  13161. #endif /* CK_APC */
  13162.  
  13163.         ckstrncpy(line,rexxcmd,LINBUFSIZ);
  13164.         rexxcmd = line;
  13165. #ifdef OS2
  13166.         return(os2rexx(rexxcmd,rexxbuf,REXBUFL));
  13167. #else /* !OS2 */
  13168.         printf("Sorry, nothing happens.\n");
  13169.         return(success = 0);
  13170. #endif /* OS2 */
  13171. }
  13172. #endif /* CK_REXX */
  13173. #endif /* NOPUSH */
  13174. #else  /* NOICP */
  13175. VOID
  13176. dologend() {
  13177.     /* Dummy write record to connection log */
  13178. }
  13179. #endif /* NOICP */
  13180.