home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckuus7.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  519KB  |  15,324 lines

  1. #include "ckcsym.h"
  2.  
  3. /*  C K U U S 7 --  "User Interface" for C-Kermit, part 7  */
  4.  
  5. /*
  6.   Authors:
  7.     Frank da Cruz <fdc@columbia.edu>,
  8.       The Kermit Project, Columbia University, New York City
  9.     Jeffrey E Altman <jaltman@secure-endpoints.com>
  10.       Secure Endpoints Inc., New York City
  11.  
  12.   Copyright (C) 1985, 2011,
  13.     Trustees of Columbia University in the City of New York.
  14.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  15.     copyright text in the ckcmai.c module for disclaimer and permissions.
  16. */
  17.  
  18. /*
  19.   This file created from parts of ckuus3.c, which became too big for
  20.   Mark Williams Coherent compiler to handle.
  21. */
  22.  
  23. /*
  24.   Definitions here supersede those from system include files.
  25. */
  26. #include "ckcdeb.h"                     /* Debugging & compiler things */
  27. #include "ckcasc.h"                     /* ASCII character symbols */
  28. #include "ckcker.h"                     /* Kermit application definitions */
  29. #include "ckcxla.h"                     /* Character set translation */
  30. #include "ckcnet.h"                     /* Network symbols */
  31. #include "ckuusr.h"                     /* User interface symbols */
  32. #include "ckucmd.h"
  33. #include "ckclib.h"
  34.  
  35. #ifdef VMS
  36. #ifndef TCPSOCKET
  37. #include <errno.h>
  38. #endif /* TCPSOCKET */
  39. #endif /* VMS */
  40.  
  41. #ifdef OS2
  42. #ifndef NT
  43. #define INCL_NOPM
  44. #define INCL_VIO                        /* Needed for ckocon.h */
  45. #define INCL_DOSMODULEMGR
  46. #include <os2.h>
  47. #undef COMMENT
  48. #else /* NT */
  49. #define APIRET ULONG
  50. #include <windows.h>
  51. #include <tapi.h>
  52. #include "cknwin.h"
  53. #include "ckntap.h"
  54. #endif /* NT */
  55. #include "ckowin.h"
  56. #include "ckocon.h"
  57. #include "ckodir.h"
  58. #ifdef OS2MOUSE
  59. #include "ckokey.h"
  60. #endif /* OS2MOUSE */
  61. #ifdef KUI
  62. #include "ikui.h"
  63. #endif /* KUI */
  64. #ifdef putchar
  65. #undef putchar
  66. #endif /* putchar */
  67. #define putchar(x) conoc(x)
  68. extern int mskkeys;
  69. extern int mskrename;
  70. #endif /* OS2 */
  71.  
  72. #ifdef CK_AUTHENTICATION
  73. #include "ckuath.h"
  74. #endif /* CK_AUTHENTICATION */
  75. #ifdef CK_SSL
  76. #include "ck_ssl.h"
  77. #endif /* CK_SSL */
  78. #ifdef SSHBUILTIN
  79. #include "ckossh.h"
  80. #endif /* SSHBUILTIN */
  81. #ifdef STRATUS                          /* Stratus Computer, Inc.  VOS */
  82. #ifdef putchar
  83. #undef putchar
  84. #endif /* putchar */
  85. #define putchar(x) conoc(x)
  86. #ifdef getchar
  87. #undef getchar
  88. #endif /* getchar */
  89. #define getchar(x) coninc(0)
  90. #endif /* STRATUS */
  91.  
  92. char * slmsg = NULL;
  93.  
  94. static int x, y = 0, z;
  95. static char *s;
  96.  
  97. extern CHAR feol;
  98. extern int g_matchdot, hints, xcmdsrc, rcdactive;
  99.  
  100. extern char * k_info_dir;
  101.  
  102. #ifdef CK_LOGIN
  103. #ifdef CK_PAM
  104. int gotemptypasswd = 0;   /* distinguish empty passwd from none given */
  105. #endif /* CK_PAM */
  106. #endif /* CK_LOGIN */
  107.  
  108. #ifndef NOSPL
  109. extern int nmac;
  110. extern struct mtab *mactab;
  111. #endif /* NOSPL */
  112.  
  113. #ifndef NOXFER
  114. #ifdef CK_SPEED
  115. extern short ctlp[];                    /* Control-char prefixing table */
  116. #endif /* CK_SPEED */
  117.  
  118. #ifdef PIPESEND
  119. extern char * sndfilter, * g_sfilter;
  120. extern char * rcvfilter, * g_rfilter;
  121. #endif /* PIPESEND */
  122.  
  123. extern char * snd_move;
  124. extern char * snd_rename;
  125. extern char * g_snd_move;
  126. extern char * g_snd_rename;
  127. extern char * rcv_move;
  128. extern char * rcv_rename;
  129. extern char * g_rcv_move;
  130. extern char * g_rcv_rename;
  131.  
  132. #ifdef PATTERNS
  133. extern char *binpatterns[], *txtpatterns[];
  134. extern int patterns;
  135. #endif /* PATTERNS */
  136.  
  137. extern char * remdest;
  138. #ifdef CK_TMPDIR
  139. char * dldir = NULL;
  140. #endif /* CK_TMPDIR */
  141.  
  142. extern struct ck_p ptab[];
  143.  
  144. extern int protocol, remfile, rempipe, remappd, reliable, xreliable, fmask,
  145.   fncnv, frecl, maxrps, wslotr, bigsbsiz, bigrbsiz, urpsiz, rpsiz, spsiz,
  146.   bctr, npad, timef, timint, spsizr, spsizf, maxsps, spmax, nfils, displa,
  147.   atcapr, pkttim, rtimo, fncact, mypadn, fdispla, f_save, pktpaus, setreliable,
  148.   fnrpath, fnspath, atenci, atenco, atdati, atdato, atleni, atleno, atblki,
  149.   atblko, attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
  150.  
  151. extern int stathack;
  152.  
  153. extern int atfrmi, atfrmo;
  154. #ifdef STRATUS
  155. extern int atcrei, atcreo, atacti, atacto;
  156. #endif /* STRATUS */
  157. #ifdef CK_PERMS
  158. extern int atlpri, atlpro, atgpri, atgpro;
  159. #endif /* CK_PERMS */
  160.  
  161. extern CHAR
  162.   sstate, eol, seol, stchr, mystch, mypadc, padch, ctlq, myctlq;
  163.  
  164. #ifdef IKSD
  165. extern int inserver;
  166. #ifdef IKSDCONF
  167. extern int iksdcf;
  168. #endif /* IKSDCONF */
  169. #endif /* IKSD */
  170.  
  171. extern char *cmarg, *cmarg2;
  172.  
  173. #ifndef NOFRILLS
  174. extern char optbuf[];                   /* Buffer for MAIL or PRINT options */
  175. extern int rprintf;                     /* REMOTE PRINT flag */
  176. #endif /* NOFRILLS */
  177. #endif /* NOXFER */
  178.  
  179. #ifdef CK_TRIGGER
  180. extern char * tt_trigger[];
  181. #endif /* CK_TRIGGER */
  182.  
  183. extern int tcs_transp;
  184. #ifdef PCTERM
  185. extern int tt_pcterm;
  186. #endif /* PCTERM */
  187. #ifdef NT
  188. extern int tt_vtnt;
  189. #endif /* NT */
  190.  
  191. #ifdef SSHBUILTIN
  192. int sl_ssh_xfw = 0;
  193. int sl_ssh_xfw_saved = 0;
  194. int sl_ssh_ver = 0;
  195. int sl_ssh_ver_saved = 0;
  196. #endif /* SSHBUILTIN */
  197.  
  198. #ifdef CK_AUTHENTICATION
  199. extern int auth_type_user[];
  200. int sl_auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_NULL, AUTHTYPE_NULL};
  201. int sl_auth_saved = 0;
  202. int sl_topt_a_su = 0;
  203. int sl_topt_a_s_saved = 0;
  204. int sl_topt_a_cm = 0;
  205. int sl_topt_a_c_saved = 0;
  206. #endif /* CK_AUTHENTICATION */
  207. #ifdef CK_ENCRYPTION
  208. extern int cx_type;
  209. int sl_cx_type = 0;
  210. int sl_cx_saved = 0;
  211. int sl_topt_e_su = 0;
  212. int sl_topt_e_sm = 0;
  213. int sl_topt_e_s_saved = 0;
  214. int sl_topt_e_cu = 0;
  215. int sl_topt_e_cm = 0;
  216. int sl_topt_e_c_saved = 0;
  217. #endif /* CK_ENCRYPTION */
  218. extern char uidbuf[];
  219. static int uidflag = 0;
  220. char sl_uidbuf[UIDBUFLEN] = { NUL, NUL };
  221. int  sl_uid_saved = 0;
  222. #ifdef TNCODE
  223. int  sl_tn_wait = 0;
  224. int  sl_tn_saved = 0;
  225. #endif /* TNCODE */
  226.  
  227. #ifdef TNCODE
  228. extern int tn_wait_flg;
  229. #endif /* TNCODE */
  230.  
  231. VOID
  232. slrestor() {
  233. #ifdef CK_AUTHENTICATION
  234.     int x;
  235.     if (sl_auth_saved) {
  236.         for (x = 0; x < AUTHTYPLSTSZ; x++)
  237.           auth_type_user[x] = sl_auth_type_user[x];
  238.         sl_auth_saved = 0;
  239.     }
  240.     if (sl_topt_a_s_saved) {
  241.         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = sl_topt_a_su;
  242.         sl_topt_a_s_saved = 0;
  243.     }
  244.     if (sl_topt_a_c_saved) {
  245.         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = sl_topt_a_cm;
  246.         sl_topt_a_c_saved = 0;
  247.     }
  248. #endif /* CK_AUTHENTICATION */
  249. #ifdef CK_ENCRYPTION
  250.     if (sl_cx_saved) {
  251.         cx_type = sl_cx_type;
  252.         sl_cx_saved = 0;
  253.     }
  254.     if (sl_topt_e_s_saved) {
  255.         TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION)  = sl_topt_e_su;
  256.         TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = sl_topt_e_sm;
  257.         sl_topt_e_s_saved = 0;
  258.     }
  259.     if (sl_topt_e_c_saved) {
  260.         TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION)  = sl_topt_e_cu;
  261.         TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = sl_topt_e_cm;
  262.         sl_topt_e_c_saved = 0;
  263.     }
  264. #endif /* CK_ENCRYPTION */
  265.     if (sl_uid_saved) {
  266.         ckstrncpy(uidbuf,sl_uidbuf,UIDBUFLEN);
  267.         sl_uid_saved = 0;
  268.     }
  269. #ifdef TNCODE
  270.     if (sl_tn_saved) {
  271.         tn_wait_flg = sl_tn_wait;
  272.         sl_tn_saved = 0;
  273.     }
  274. #endif /* TNCODE */
  275. #ifdef SSHBUILTIN
  276.     if (sl_ssh_xfw_saved) {
  277.         ssh_xfw = sl_ssh_xfw;
  278.         sl_ssh_xfw_saved = 0;
  279.     }
  280.     if (sl_ssh_ver_saved) {
  281.         ssh_ver = sl_ssh_ver;
  282.         sl_ssh_ver_saved = 0;
  283.     }
  284. #endif /* SSHBUILTIN */
  285. }
  286.  
  287. int oldplex = -1;                       /* Duplex holder around network */
  288.  
  289. #ifndef NOICP
  290. #ifdef LOCUS
  291. extern int locus, autolocus;
  292. #endif /* LOCUS */
  293. #ifndef NODIAL
  294. extern int dialsta;
  295. #endif /* NODIAL */
  296.  
  297. /* Note: gcc -Wall wants braces around each keyword table entry. */
  298.  
  299. static struct keytab psltab[] = {       /* SET LINE/PORT command options */
  300.     { "/connect", SL_CNX, 0 },
  301. #ifdef OS2ORVMS
  302.     { "/noshare", SL_NSH, 0 },
  303. #endif /* OS2ORVMS */
  304.     { "/server",  SL_SRV, 0 },
  305. #ifdef OS2ORVMS
  306.     { "/share",   SL_SHR, 0 },
  307. #endif /* OS2ORVMS */
  308.     { "", 0, 0 }
  309. };
  310. static int npsltab = sizeof(psltab)/sizeof(struct keytab) - 1;
  311.  
  312. #ifdef NETCONN
  313. static struct keytab shtab[] = {        /* SET HOST command options */
  314. #ifdef NETCMD
  315.     /* (COMMAND is also a network type) */
  316.     { "/command",      SL_CMD,    CM_INV },
  317. #endif /* NETCMD */
  318.     { "/connect",      SL_CNX,    0 },
  319.     { "/network-type", SL_NET,    CM_ARG },
  320.     { "/nowait",       SL_NOWAIT, 0 },
  321. #ifndef NOSPL
  322. #ifdef CK_AUTHENTICATION
  323.     { "/password",     SL_PSW,    CM_ARG },
  324. #endif /* CK_AUTHENTICATION */
  325. #endif /* NOSPL */
  326. #ifdef NETCMD
  327.     { "/pipe",         SL_CMD,    0 },
  328. #endif /* NETCMD */
  329. #ifdef NETPTY
  330.     { "/pty",          SL_PTY,    0 },
  331. #endif /* NETPTY */
  332.     { "/server",       SL_SRV,    0 },
  333.     { "/timeout",      SL_TMO,    CM_ARG },
  334.     { "/userid",       SL_UID,    CM_ARG },
  335.     { "/wait",         SL_WAIT,   0 },
  336.     { "", 0, 0 }
  337. };
  338. static int nshtab = sizeof(shtab)/sizeof(struct keytab) - 1;
  339.  
  340. static struct keytab shteltab[] = {     /* TELNET command options */
  341. #ifdef CK_AUTHENTICATION
  342.     { "/auth",         SL_AUTH,   CM_ARG },
  343. #endif /* CK_AUTHENTICATION */
  344. #ifdef CK_ENCRYPTION
  345.     { "/encrypt",      SL_ENC,    CM_ARG },
  346. #endif /* CK_ENCRYPTION */
  347.     { "/nowait",       SL_NOWAIT, 0 },
  348. #ifndef NOSPL
  349. #ifdef CK_AUTHENTICATION
  350.     { "/password",     SL_PSW,    CM_ARG },
  351. #endif /* CK_AUTHENTICATION */
  352. #endif /* NOSPL */
  353.     { "/timeout",      SL_TMO,    CM_ARG },
  354.     { "/userid",       SL_UID,    CM_ARG },
  355.     { "/wait",         SL_WAIT,   0 },
  356.     { "", 0 ,0 }
  357. };
  358. static int nshteltab = sizeof(shteltab)/sizeof(struct keytab) - 1;
  359.  
  360. #ifdef RLOGCODE
  361. static struct keytab shrlgtab[] = {     /* SET HOST RLOGIN command options */
  362. #ifdef CK_KERBEROS
  363. #ifdef CK_ENCRYPTION
  364.     { "/encrypt",      SL_ENC, 0 },
  365. #endif /* CK_ENCRYPTION */
  366.     { "/k4",           SL_KRB4, CM_INV },
  367.     { "/k5",           SL_KRB5, CM_INV },
  368.     { "/kerberos4",    SL_KRB4, 0 },
  369.     { "/kerberos5",    SL_KRB5, 0 },
  370.     { "/kerberos_iv",  SL_KRB4, CM_INV },
  371.     { "/kerberos_v",   SL_KRB5, CM_INV },
  372.     { "/krb4",         SL_KRB4, CM_INV },
  373.     { "/krb5",         SL_KRB5, CM_INV },
  374. #endif /* CK_KERBEROS */
  375.     { "", 0 ,0 }
  376. };
  377. static int nshrlgtab = sizeof(shrlgtab)/sizeof(struct keytab)-1;
  378. #endif /* RLOGCODE */
  379.  
  380. extern struct keytab netcmd[];
  381. extern int nnets;
  382. #ifndef NODIAL
  383. extern int dirline;
  384. extern int nnetdir;                     /* Network services directory */
  385. extern char *netdir[];
  386. _PROTOTYP( VOID ndreset, (void) );
  387. char *nh_p[MAXDNUMS + 1];               /* Network directory entry pointers */
  388. char *nh_p2[MAXDNUMS + 1];              /* Network directory entry nettype */
  389. char *nh_px[4][MAXDNUMS + 1];           /* Network-specific stuff... */
  390. #endif /* NODIAL */
  391. int nhcount = 0;
  392. int ndinited = 0;
  393. char * n_name = NULL;                   /* Network name pointer */
  394. #endif /* NETCONN */
  395.  
  396. _PROTOTYP(int remtxt, (char **) );
  397. _PROTOTYP(VOID rmsg, (void) );
  398. _PROTOTYP(static int remcfm, (void) );
  399.  
  400. extern int nopush;
  401.  
  402. int mdmsav = -1;                        /* Save modem type around network */
  403. extern int isguest;                     /* Global flag for anonymous login */
  404.  
  405. extern xx_strp xxstring;
  406.  
  407. extern int success, binary, b_save, ckwarn, msgflg, quiet, cmask, pflag, local,
  408.   nettype, escape, mdmtyp, duplex, dfloc, network, cdtimo, autoflow, tnlm,
  409.   sosi, tlevel, lf_opts, backgrd, flow, debses, parity, ttnproto, ckxech,
  410.   x_ifnum, cmflgs, haveline, cxtype, cxflow[], maclvl;
  411.  
  412. #ifdef DCMDBUF
  413. extern struct cmdptr *cmdstk;           /* The command stack itself */
  414. #else
  415. extern struct cmdptr cmdstk[];          /* The command stack itself */
  416. #endif /* DCMDBUF */
  417. extern FILE * tfile[];
  418. extern char * macp[];
  419.  
  420. extern char psave[];                    /* For saving & restoring prompt */
  421. extern int sprmlen, rprmlen;
  422.  
  423. #ifdef OS2
  424. static struct keytab strmkeytab[] = {
  425.     { "clear",   0, 0 },
  426.     { "default", 1, 0 }
  427. };
  428. static int nstrmkeytab = sizeof(strmkeytab)/sizeof(struct keytab);
  429.  
  430. static struct keytab strmswitab[] = {
  431.     { "/literal", 0, 0 }
  432. };
  433. static int nstrmswitab = sizeof(strmswitab)/sizeof(struct keytab);
  434.  
  435. static struct keytab normrev[] = {
  436.     { "dark-display", 0, 0 },
  437.     { "light-display", 1, 0 },
  438.     { "normal",   0, 0 },
  439.     { "reverse",  1, 0 }
  440. };
  441.  
  442. static struct keytab prnmtab[] = {
  443.     { "auto", 1, 0 },
  444.     { "copy", 2, 0 },
  445.     { "off",  0, 0 },
  446.     { "on",   1, CM_INV },              /* Compatibility with XPRINT version */
  447.     { "user", 3, 0 },
  448.     { "transparent", 3, CM_INV }        /* not really transparent */
  449. };
  450. static int nprnmtab = sizeof(prnmtab)/sizeof(struct keytab);
  451.  
  452. extern int tt_diff_upd;
  453.  
  454. #ifdef NT
  455. #define stricmp _stricmp
  456. extern int tt_attr_bug;
  457. #endif /* NT */
  458. extern int tt_rows[], tt_cols[];
  459. extern int tt_cols_usr;
  460. extern int tt_szchng[VNUM];
  461. int tt_modechg = TVC_ENA;
  462. extern int tt_url_hilite, tt_url_hilite_attr;
  463. extern struct _vtG G[4];
  464. extern int priority;
  465. extern bool send_c1;
  466. int send_c1_usr = FALSE;
  467. extern int sgrcolors;
  468. extern int marginbell, marginbellcol;
  469. extern int autoscroll, wy_autopage;
  470. extern int tt_sac;
  471. extern int dec_nrc, dec_lang, dec_kbd;
  472. #else /* OS2 */
  473. extern int tt_rows, tt_cols;
  474. #endif /*  OS2 */
  475.  
  476. extern int tt_escape;
  477. extern long speed;
  478.  
  479. extern char *dftty;
  480.  
  481. extern char *tp, *lp;                   /* Temporary buffer & pointers */
  482. extern char ttname[];
  483.  
  484. #ifdef CK_TAPI
  485. int tttapi = 0;                         /* is Line TAPI? */
  486. struct keytab * tapilinetab = NULL;
  487. struct keytab * _tapilinetab = NULL;
  488. int ntapiline = 0;
  489. #endif /* CK_TAPI */
  490.  
  491. #ifdef NETCONN                          /* Network items */
  492.  
  493. #ifdef ANYX25
  494. extern int revcall, closgr, cudata, nx25;
  495. extern char udata[];
  496. extern struct keytab x25tab[];
  497. #ifndef IBMX25
  498. extern int npadx3;
  499. extern CHAR padparms[];
  500. extern struct keytab padx3tab[];
  501. #endif /* IBMX25 */
  502. #endif /* ANYX25 */
  503.  
  504. #ifdef OS2
  505. extern bool ttshare;
  506. #ifndef NT
  507. extern bool ttslip,ttppp;
  508. #endif /* NT */
  509. #endif /* OS2 */
  510. #ifdef NPIPE
  511. extern char pipename[];
  512. #endif /* NPIPE */
  513.  
  514. #ifdef TCPSOCKET
  515. static struct keytab tcprawtab[] = {    /* SET HOST options */
  516.     { "/default",    NP_DEFAULT,    CM_INV },
  517. #ifdef CK_AUTHENTICATION
  518. #ifdef CK_KERBEROS
  519. #ifdef RLOGCODE
  520.     { "/ek4login",    NP_EK4LOGIN,    0 },
  521.     { "/ek5login",    NP_EK5LOGIN,    0 },
  522.     { "/k4login",     NP_K4LOGIN,     0 },
  523.     { "/k5login",     NP_K5LOGIN,     0 },
  524. #endif /* RLOGCODE */
  525. #ifdef KRB5_U2U
  526.     { "/k5user2user", NP_K5U2U,       0 },
  527. #endif /* KRB5_U2U */
  528. #endif /* CK_KERBEROS */
  529. #endif /* CK_AUTHENTICATION */
  530.     { "/no-telnet-init", NP_NONE,   0 },
  531.     { "/none",       NP_NONE,   CM_INV },
  532.     { "/raw-socket", NP_TCPRAW, 0 },
  533. #ifdef RLOGCODE
  534.     { "/rlogin",     NP_RLOGIN, 0 },
  535. #endif /* RLOGCODE */
  536. #ifdef CK_SSL
  537.     { "/ssl",        NP_SSL,    0 },
  538.     { "/ssl-raw",    NP_SSL_RAW, 0 },
  539.     { "/ssl-telnet", NP_SSL_TELNET, 0 },
  540. #endif /* CK_SSL */
  541.     { "/telnet",     NP_TELNET, 0 },
  542. #ifdef CK_SSL
  543.     { "/tls",        NP_TLS,    0 },
  544.     { "/tls-raw",    NP_TLS_RAW, 0 },
  545.     { "/tls-telnet", NP_TLS_TELNET, 0 },
  546. #endif /* CK_SSL */
  547.     { "", 0, 0 }
  548. };
  549. static int ntcpraw = (sizeof(tcprawtab) / sizeof(struct keytab)) - 1;
  550.  
  551. #ifdef RLOGCODE
  552. _PROTOTYP( int rlog_naws, (void) );
  553. #endif /* RLOGCODE */
  554. #endif /* TCPSOCKET */
  555.  
  556. #ifdef SUPERLAT
  557. extern char slat_pwd[18];
  558. #endif /* SUPERLAT */
  559. #endif /* NETCONN */
  560.  
  561. #ifdef COMMENT
  562. #ifndef NOSETKEY
  563. extern KEY *keymap;
  564. #ifndef OS2
  565. #define mapkey(x) keymap[x]
  566. #endif /* OS2 */
  567. extern MACRO *macrotab;
  568. #ifndef NOKVERBS
  569. extern struct keytab kverbs[];
  570. extern int nkverbs;
  571. #endif /* NOKVERBS */
  572. #endif /* NOSETKEY */
  573. #else
  574. #ifndef NOSETKEY
  575. extern KEY *keymap;
  576. extern MACRO *macrotab;
  577. #ifndef NOKVERBS
  578. extern struct keytab kverbs[];
  579. extern int nkverbs;
  580. #endif /* NOKVERBS */
  581. #endif /* NOSETKEY */
  582. #endif /* COMMENT */
  583.  
  584. #ifdef OS2                              /* AUTODOWNLOAD parameters */
  585. extern int    adl_kmode, adl_zmode;     /* Match Packet to signal download */
  586. extern char * adl_kstr;                 /* KERMIT Download String */
  587. extern char * adl_zstr;                 /* ZMODEM Download String */
  588. extern int adl_kc0, adl_zc0;            /* Process ADL C0s in emulation */
  589. #endif /* OS2 */
  590.  
  591. /* Keyword tables ... */
  592.  
  593. extern struct keytab onoff[], rltab[];
  594. extern int nrlt;
  595.  
  596. #ifndef NOCSETS
  597. static struct keytab fdfltab[] = {
  598.     { "7bit-character-set", 7, 0 },
  599.     { "8bit-character-set", 8, 0 }
  600. };
  601. static int nfdflt = (sizeof(fdfltab) / sizeof(struct keytab));
  602. #endif /* NOCSETS */
  603.  
  604. /* SET FILE parameters */
  605.  
  606. static struct keytab filtab[] = {
  607. #ifndef NOXFER
  608. #ifdef PATTERNS
  609.     { "binary-patterns",   XYFIBP,  0 },
  610. #endif /* PATTERNS */
  611.     { "bytesize",         XYFILS,   0 },
  612. #ifndef NOCSETS
  613.     { "character-set",    XYFILC,   0 },
  614. #endif /* NOCSETS */
  615.     { "collision",        XYFILX,   0 },
  616.     { "default",          XYF_DFLT, 0 },
  617.     { "destination",      XYFILY,   0 },
  618.     { "display",          XYFILD,   CM_INV },
  619. #ifdef CK_TMPDIR
  620.     { "download-directory", XYFILG, 0 },
  621. #endif /* CK_TMPDIR */
  622. #endif /* NOXFER */
  623.     { "end-of-line",      XYFILA,   0 },
  624.     { "eol",              XYFILA,   CM_INV },
  625. #ifdef CK_CTRLZ
  626.     { "eof",              XYFILV,   0 },
  627. #endif /* CK_CTRLZ */
  628. #ifndef NOXFER
  629.     { "fastlookups",      9997,     CM_INV },
  630.     { "incomplete",       XYFILI,   0 },
  631. #ifndef datageneral
  632.     { "inspection",       XYF_INSP, CM_INV },
  633. #endif /* datageneral */
  634. #ifdef CK_LABELED
  635.     { "label",            XYFILL, 0 },
  636. #endif /* CK_LABELED */
  637.  
  638. #ifdef UNIX
  639. #ifdef DYNAMIC
  640.     { "listsize",         XYF_LSIZ, 0 },
  641. #endif /* DYNAMIC */
  642. #endif /* UNIX */
  643.  
  644.     { "names",            XYFILN, 0 },
  645. #ifdef UNIX
  646.     { "output",           XYFILH, 0 },
  647. #endif /* UNIX */
  648. #ifdef PATTERNS
  649.     { "patterns",         XYFIPA, 0 },
  650. #endif /* PATTERNS */
  651. #ifdef COMMENT /* Not implemented (but see CHMOD) */
  652.     { "permissions",      XYF_PRM, CM_INV },
  653.     { "protection",       XYF_PRM, 0 },
  654. #endif /* COMMENt */
  655. #ifdef VMS
  656.     { "record-length",    XYFILR, 0 },
  657. #endif /* VMS */
  658. #ifndef datageneral
  659.     { "scan",             XYF_INSP, 0 },
  660. #endif /* datageneral */
  661.  
  662. #ifdef UNIX
  663. #ifdef DYNAMIC
  664.     { "stringspace",      XYF_SSPA, 0 },
  665. #endif /* DYNAMIC */
  666. #endif /* UNIX */
  667.  
  668. #ifdef PATTERNS
  669.     { "t",                XYFILT, CM_INV|CM_ABR },
  670.     { "text-patterns",    XYFITP, 0 },
  671. #endif /* PATTERNS */
  672. #endif /* NOXFER */
  673.     { "type",             XYFILT, 0 },
  674. #ifdef UNICODE
  675.     { "ucs",              XYFILU, 0 },
  676. #endif /* UNICODE */
  677. #ifndef NOXFER
  678.     { "warning",          XYFILW, CM_INV }
  679. #endif /* NOXFER */
  680. };
  681. static int nfilp = (sizeof(filtab) / sizeof(struct keytab));
  682.  
  683. struct keytab pathtab[] = {
  684.     { "absolute",  PATH_ABS,  0      },
  685.     { "none",      PATH_OFF,  CM_INV },
  686.     { "off",       PATH_OFF,  0      },
  687.     { "on",        PATH_ABS,  CM_INV },
  688.     { "relative",  PATH_REL,  0      }
  689. };
  690. int npathtab = (sizeof(pathtab) / sizeof(struct keytab));
  691.  
  692. struct keytab rpathtab[] = {
  693.     { "absolute",  PATH_ABS,  0      },
  694.     { "auto",      PATH_AUTO, 0      },
  695.     { "none",      PATH_OFF,  CM_INV },
  696.     { "off",       PATH_OFF,  0      },
  697.     { "on",        PATH_ABS,  CM_INV },
  698.     { "relative",  PATH_REL,  0      }
  699. };
  700. int nrpathtab = (sizeof(rpathtab) / sizeof(struct keytab));
  701.  
  702. #ifdef CK_CTRLZ
  703. struct keytab eoftab[] = {              /* EOF detection method */
  704.     { "ctrl-z",          1, 0      },
  705.     { "length",          0, 0      },
  706.     { "noctrl-z",        0, CM_INV }
  707. };
  708. #endif /* CK_CTRLZ */
  709.  
  710. struct keytab fttab[] = {               /* File types for SET FILE TYPE */
  711.     { "ascii",     XYFT_T, CM_INV },
  712. #ifdef VMS
  713.     { "b",         XYFT_B, CM_INV|CM_ABR },
  714. #endif /* VMS */
  715.     { "binary",    XYFT_B, 0 },
  716. #ifdef VMS
  717.     { "block",     XYFT_I, CM_INV },
  718.     { "image",     XYFT_I, 0 },
  719. #endif /* VMS */
  720. #ifdef CK_LABELED
  721.     { "labeled",   XYFT_L, 0 },
  722. #endif /* CK_LABELED */
  723. #ifdef MAC
  724.     { "macbinary", XYFT_M, 0 },
  725. #endif /* MAC */
  726.     { "text",      XYFT_T, 0 }
  727. };
  728. int nfttyp = (sizeof(fttab) / sizeof(struct keytab));
  729.  
  730. static struct keytab rfttab[] = {       /* File types for REMOTE SET FILE */
  731.     { "ascii",     XYFT_T, CM_INV },
  732.     { "binary",    XYFT_B, 0 },
  733. #ifdef VMS
  734.     { "labeled",   XYFT_L, 0 },
  735. #else
  736. #ifdef OS2
  737.     { "labeled",   XYFT_L, 0 },
  738. #endif /* OS2 */
  739. #endif /* VMS */
  740.     { "text",      XYFT_T, 0 }
  741. };
  742. static int nrfttyp = (sizeof(rfttab) / sizeof(struct keytab));
  743.  
  744. #ifdef OS2ORUNIX
  745. #define ZOF_BLK  0
  746. #define ZOF_NBLK 1
  747. #define ZOF_BUF  2
  748. #define ZOF_NBUF 3
  749. static struct keytab zoftab[] = {
  750.     { "blocking",    ZOF_BLK,  0 },
  751.     { "buffered",    ZOF_BUF,  0 },
  752.     { "nonblocking", ZOF_NBLK, 0 },
  753.     { "unbuffered",  ZOF_NBUF, 0 }
  754. };
  755. static int nzoftab = (sizeof(zoftab) / sizeof(struct keytab));
  756. #endif /* OS2ORUNIX */
  757.  
  758. extern int query;                       /* Global flag for QUERY active */
  759.  
  760. #ifndef NOSPL
  761. #ifndef NOXFER
  762. static struct keytab vartyp[] = {       /* Variable types for REMOTE QUERY */
  763.     { "global",   (int) 'G', CM_INV },
  764.     { "kermit",   (int) 'K', 0 },
  765.     { "system",   (int) 'S', 0 },
  766.     { "user",     (int) 'G', 0 }
  767. };
  768. static int nvartyp = (sizeof(vartyp) / sizeof(struct keytab));
  769. #endif /* NOXFER */
  770. #endif /* NOSPL */
  771.  
  772. #ifdef CK_TIMERS
  773. static struct keytab timotab[] = {      /* Timer types */
  774.     { "dynamic", 1, 0 },
  775.     { "fixed",   0, 0 }
  776. };
  777. #endif /* CK_TIMERS */
  778.  
  779. #ifdef DCMDBUF
  780. extern char *atxbuf, *atmbuf;           /* Atom buffer */
  781. extern char *cmdbuf;                    /* Command buffer */
  782. extern char *line, *tmpbuf;             /* Character buffers for anything */
  783. extern int *intime;                     /* INPUT TIMEOUT */
  784.  
  785. #else  /* Not DCMDBUF ... */
  786.  
  787. extern char atxbuf[], atmbuf[];         /* Atom buffer */
  788. extern char cmdbuf[];                   /* Command buffer */
  789. extern char line[], tmpbuf[];           /* Character buffer for anything */
  790. extern int intime[];
  791.  
  792. #endif /* DCMDBUF */
  793.  
  794. #ifndef NOCSETS
  795. extern struct keytab fcstab[];          /* For SET FILE CHARACTER-SET */
  796. extern struct csinfo fcsinfo[];         /* File character set info. */
  797. extern struct keytab ttcstab[];
  798. extern int nfilc, fcharset, tcharset, ntermc, tcsr, tcsl, dcset7, dcset8;
  799. #ifdef CKOUNI
  800. extern int tt_utf8;
  801. #endif /* CKOUNI */
  802. #ifdef OS2
  803. _PROTOTYP( int os2setcp, (int) );
  804. _PROTOTYP( int os2getcp, (void) );
  805. _PROTOTYP( void os2debugoff, (void) );
  806. #endif /* OS2 */
  807. #endif /* NOCSETS */
  808.  
  809. extern int cmdlvl;                      /* Overall command level */
  810.  
  811. #ifndef NOSPL
  812. #ifdef DCMDBUF
  813. extern int *inpcas;                     /* INPUT CASE setting on cmd stack */
  814. #else
  815. extern int inpcas[];
  816. #endif /* DCMDBUF */
  817. #endif /* NOSPL */
  818.  
  819. #ifdef CK_CURSES
  820. #ifndef VMS
  821. _PROTOTYP(int tgetent,(char *, char *));
  822. #else
  823. #ifdef __DECC
  824. _PROTOTYP(int tgetent,(char *, char *));
  825. #endif /* __DECC */
  826. #endif /* VMS */
  827. #endif /* CK_CURSES */
  828.  
  829. #ifndef NOXMIT
  830. #define XMITF 0                         /* SET TRANSMIT values */
  831. #define XMITL 1                         /* (Local to this module) */
  832. #define XMITP 2
  833. #define XMITE 3
  834. #define XMITX 4
  835. #define XMITS 5
  836. #define XMITW 6
  837. #define XMITT 7
  838.  
  839. #define XMBUFL 50
  840. extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw, xmitt;
  841. char xmitbuf[XMBUFL+1] = { NUL };       /* TRANSMIT eof string */
  842.  
  843. struct keytab xmitab[] = {              /* SET TRANSMIT */
  844.     { "echo",          XMITX, 0 },
  845.     { "eof",           XMITE, 0 },
  846.     { "fill",          XMITF, 0 },
  847.     { "linefeed",      XMITL, 0 },
  848.     { "locking-shift", XMITS, 0 },
  849.     { "pause",         XMITW, 0 },
  850.     { "prompt",        XMITP, 0 },
  851.     { "timeout",       XMITT, 0 }
  852. };
  853. int nxmit = (sizeof(xmitab) / sizeof(struct keytab));
  854. #endif /* NOXMIT */
  855.  
  856. /* For SET FILE COLLISION */
  857. /* Some of the following may be possible for some C-Kermit implementations */
  858. /* but not others.  Those that are not possible for your implementation */
  859. /* should be ifdef'd out. */
  860.  
  861. struct keytab colxtab[] = { /* SET FILE COLLISION options */
  862. #ifndef MAC
  863.     { "append",    XYFX_A, 0 },         /* append to old file */
  864. #endif /* MAC */
  865. #ifdef COMMENT
  866.     { "ask",       XYFX_Q, 0 },         /* ask what to do (not implemented) */
  867. #endif
  868.     { "backup",    XYFX_B, 0 },         /* rename old file */
  869. #ifndef MAC
  870.     /* This crashes Mac Kermit. */
  871.     { "discard",   XYFX_D, CM_INV },    /* don't accept new file */
  872.     { "no-supersede", XYFX_D, CM_INV }, /* ditto (MSK compatibility) */
  873. #endif /* MAC */
  874.     { "overwrite", XYFX_X, 0 },         /* overwrite the old file */
  875.     { "reject",    XYFX_D, 0 },        /* (better word than discard) */
  876.     { "rename",    XYFX_R, 0 },         /* rename the incoming file */
  877. #ifndef MAC                             /* This crashes Mac Kermit. */
  878.     { "update",    XYFX_U, 0 },         /* replace if newer */
  879. #endif /* MAC */
  880.     { "", 0, 0 }
  881. };
  882. int ncolx = (sizeof(colxtab) / sizeof(struct keytab)) - 1;
  883.  
  884. static struct keytab rfiltab[] = {      /* for REMOTE SET FILE */
  885. #ifndef NOCSETS
  886.     { "character-set", XYFILC, 0 },
  887. #endif /* NOCSETS */
  888.     { "collision",     XYFILX, 0 },
  889.     { "incomplete",    XYFILI, 0 },
  890.     { "names",         XYFILN, 0 },
  891.     { "record-length", XYFILR, 0 },
  892.     { "type",          XYFILT, 0 }
  893. };
  894. int nrfilp = (sizeof(rfiltab) / sizeof(struct keytab));
  895.  
  896. struct keytab eoltab[] = {              /* File eof delimiters */
  897.     { "cr",        XYFA_C, 0 },
  898.     { "crlf",      XYFA_2, 0 },
  899.     { "lf",        XYFA_L, 0 }
  900. };
  901. static int neoltab = (sizeof(eoltab) / sizeof(struct keytab));
  902.  
  903. struct keytab fntab[] = {               /* File naming */
  904.     { "converted", XYFN_C, 0      },
  905.     { "literal",   XYFN_L, 0      },
  906.     { "standard",  XYFN_C, CM_INV }
  907. };
  908. int nfntab = (sizeof(fntab) / sizeof(struct keytab));
  909.  
  910. #ifndef NOLOCAL
  911. /* Terminal parameters table */
  912. static struct keytab trmtab[] = {
  913. #ifdef OS2
  914.     { "answerback",    XYTANS,    0 },
  915. #endif /* OS2 */
  916. #ifdef CK_APC
  917.     { "apc",           XYTAPC,    0 },
  918. #endif /* CK_APC */
  919. #ifdef OS2
  920.     { "arrow-keys",    XYTARR,    0 },
  921. #endif /* OS2 */
  922. #ifdef NT
  923.     { "at",            XYTATTR,   CM_INV|CM_ABR },
  924.     { "att",           XYTATTR,   CM_INV|CM_ABR },
  925.     { "attr",          XYTATTR,   CM_INV|CM_ABR },
  926.     { "attr-bug",      XYTATTBUG, CM_INV },
  927. #endif /* NT */
  928. #ifdef OS2
  929.     { "attribute",     XYTATTR,   0 },
  930. #endif /* OS2 */
  931. #ifdef CK_APC
  932. #ifdef CK_AUTODL
  933.    { "autodownload",   XYTAUTODL, 0, },
  934. #endif /* CK_AUTODL */
  935. #endif /* CK_APC */
  936. #ifdef OS2
  937.     { "autopage",      XYTAPAGE,  0 },
  938.     { "autoscroll",    XYTASCRL,  0 },
  939.     { "bell",          XYTBEL,    CM_INV },
  940. #endif /* OS2 */
  941.     { "bytesize",      XYTBYT,    0 },
  942. #ifndef NOCSETS
  943.     { "character-set", XYTCS,     0 },
  944. #endif /* NOCSETS */
  945. #ifdef OS2
  946.     { "code-page",     XYTCPG,    0 },
  947.     { "color",         XYTCOL,    0 },
  948.     { "controls",      XYTCTRL,   0 },
  949. #endif /* OS2 */
  950.     { "cr-display",    XYTCRD,    0 },
  951. #ifdef OS2
  952.     { "cursor",        XYTCUR,    0 },
  953. #endif /* OS2 */
  954.     { "debug",         XYTDEB,    0 },
  955. #ifdef OS2
  956.     { "dg-unix-mode",  XYTUNX,    0 },
  957. #endif /* OS2 */
  958.     { "echo",          XYTEC,     0 },
  959.     { "escape-character", XYTESC, 0 },
  960. #ifdef OS2
  961. #ifdef PCFONTS
  962.     { "font",          XYTFON,    0 },
  963. #else
  964. #ifdef KUI
  965.     { "font",          XYTFON,    0 },
  966. #endif /* KUI */
  967. #endif /* PCFONTS */
  968. #endif /* OS2 */
  969.     { "height",        XYTHIG,    0 },
  970. #ifdef CKTIDLE
  971.     { "idle-action",   XYTIACT,   0 },
  972.     { "idle-limit",    XYTITMO,   CM_INV },
  973.     { "idle-send",     XYTIDLE,   CM_INV },
  974.     { "idle-timeout",  XYTITMO,   0 },
  975. #endif /* CKTIDLE */
  976. #ifdef OS2
  977. #ifndef NOCSETS
  978.     { "kbd-follows-gl/gr", XYTKBDGL, 0 },
  979. #endif /* NOCSETS */
  980.     { "key",           XYTKEY,    0 },
  981.     { "keyboard-mode", XYTKBMOD,  0 },
  982.     { "keypad-mode",   XYTKPD,    0 },
  983. #endif /* OS2 */
  984.     { "lf-display",    XYTLFD,    0 },
  985. #ifndef NOCSETS
  986. #ifdef OS2
  987. #ifndef KUI
  988.     { "line-spacing",  XYTLSP,    CM_INV },
  989.     { "local-character-set", XYTLCS,  0 },
  990. #else
  991.     { "line-spacing",  XYTLSP,    0 },
  992.     { "local-character-set", XYTLCS,  CM_INV },
  993. #endif /* KUI */
  994. #else
  995.     { "local-character-set", XYTLCS,  CM_INV },
  996. #endif /* OS2 */
  997. #endif /* NOCSETS */
  998.     { "locking-shift", XYTSO,     0 },
  999. #ifdef OS2
  1000.     { "margin-bell",   XYTMBEL,   0 },
  1001. #endif /* OS2 */
  1002. #ifdef OS2MOUSE
  1003.     { "mouse",         XYTMOU,    CM_INV },
  1004. #endif /* OS2MOUSE */
  1005.     { "newline-mode",  XYTNL,     0 },
  1006. #ifdef OS2
  1007.     { "output-pacing", XYTPAC,    0 },
  1008. #ifdef PCTERM
  1009.     { "pcterm",        XYTPCTERM, 0 },
  1010. #endif /* PCTERM */
  1011. #endif /* OS2 */
  1012. #ifdef OS2ORUNIX
  1013.     { "print",         XYTPRN,    0 },
  1014. #endif /* OS2ORUNIX */
  1015. #ifndef NOCSETS
  1016. #ifdef OS2
  1017.     { "remote-character-set", XYTRCS,  0 },
  1018. #else
  1019.     { "remote-character-set", XYTRCS,  CM_INV },
  1020. #endif /* OS2 */
  1021. #endif /* NOCSETS */
  1022. #ifdef OS2
  1023.     { "roll-mode",       XYTROL, 0 },
  1024.     { "s",               XYTUPD, CM_ABR|CM_INV },
  1025.     { "sc",              XYTUPD, CM_ABR|CM_INV },
  1026.     { "scr",             XYTUPD, CM_ABR|CM_INV },
  1027.     { "scree",           XYTUPD, CM_ABR|CM_INV },
  1028.     { "screen",          XYTUPD, CM_ABR|CM_INV },
  1029.     { "screen-",         XYTUPD, CM_ABR|CM_INV },
  1030.     { "screen-mode",     XYTSCNM,   0 },
  1031.     { "screen-optimize", XYTOPTI,   0 },
  1032.     { "screen-update",   XYTUPD,    0 },
  1033.     { "scrollback",      XYSCRS,    0 },
  1034.     { "send-data",         XYTSEND, 0 },
  1035.     { "send-end-of-block", XYTSEOB, 0 },
  1036.     { "sgr-colors",            XYTSGRC,  0 },
  1037.     { "sni-ch.code",           XYTSNICC, 0 },
  1038.     { "sni-firmware-versions", XYTSNIFV, 0 },
  1039.     { "sni-language",          XYTVTLNG, 0 },
  1040.     { "sni-pagemode",          XYTSNIPM, CM_INV },
  1041.     { "sni-scrollmode",              XYTSNISM, CM_INV },
  1042.     { "spacing-attribute-character", XYTSAC,   CM_INV },
  1043.     { "statusline",                  XYTSTAT,  0 },
  1044.     { "tra",                         XYTCTS,   CM_INV|CM_ABR },
  1045.     { "transmit-timeout",            XYTCTS,   0 },
  1046. #endif /* OS2 */
  1047.  
  1048. #ifdef OS2ORUNIX
  1049.     { "transparent-print", XYTPRN,   CM_INV },
  1050. #endif /* OS2ORUNIX */
  1051.  
  1052. #ifdef CK_TRIGGER
  1053.     { "trigger",           XYTRIGGER,0 },
  1054. #endif /* CK_TRIGGER */
  1055. #ifdef OS2
  1056.     { "type",              XYTTYP,   0 },
  1057. #else
  1058.     { "type",              XYTTYP,   CM_INV },
  1059. #endif /* OS2 */
  1060.  
  1061. #ifndef NOCSETS
  1062. #ifdef UNICODE
  1063. #ifdef CKOUNI
  1064.     { "unicode",           XYTUNI,   CM_INV },
  1065. #endif /* CKOUNI */
  1066. #endif /* UNICODE */
  1067. #endif /* NOCSETS */
  1068. #ifdef OS2
  1069.     { "unix-mode",         XYTUNX,   CM_INV },
  1070.     { "url-highlight",     XYTURLHI, 0 },
  1071. #ifdef NT
  1072.     { "video-change",      XYTVCH,   0 },
  1073. #endif /* NT */
  1074.     { "vt-language",       XYTVTLNG, 0 },
  1075.     { "vt-nrc-mode",       XYTVTNRC, 0 },
  1076. #endif /* OS2 */
  1077.     { "width",             XYTWID,   0 },
  1078. #ifdef OS2
  1079.     { "wrap",              XYTWRP,   0 },
  1080. #endif /* OS2 */
  1081.     { "", 0, 0 }
  1082. };
  1083. int ntrm = (sizeof(trmtab) / sizeof(struct keytab)) - 1;
  1084.  
  1085. #ifdef OS2
  1086. struct keytab termctrl[] = {    /* SET TERM CONTROLS */
  1087.     { "7",      7, 0 },
  1088.     { "8",      8, 0 }
  1089. };
  1090. int ntermctrl = (sizeof(termctrl) / sizeof(struct keytab));
  1091.  
  1092. struct keytab curontab[] = {    /* SET TERM CURSOR */
  1093. #ifdef KUI
  1094.     { "noblink", 2, 0 },
  1095. #else
  1096.     { "noblink", 2, CM_INV },
  1097. #endif /* KUI */
  1098.     { "off",     0, 0 },
  1099.     { "on",      1, 0 }
  1100. };
  1101. int ncuron = (sizeof(curontab) / sizeof(struct keytab));
  1102.  
  1103. struct keytab rolltab[] = {   /* Set TERM Roll Options */
  1104.     { "insert",    TTR_INSERT, 0      },
  1105.     { "keystrokes",TTR_KEYS,   0      },
  1106.     { "off",       TTR_OVER,   CM_INV },
  1107.     { "on",        TTR_INSERT, CM_INV },
  1108.     { "overwrite", TTR_OVER,   0      }
  1109. };
  1110. int nroll = (sizeof(rolltab) / sizeof(struct keytab));
  1111.  
  1112. struct keytab rollkeytab[] = {        /* Set TERM ROLL KEYSTROKES */
  1113.     { "ignore",            TTRK_IGN, 0 },
  1114.     { "restore-and-send",  TTRK_RST, 0 },
  1115.     { "send",              TTRK_SND, 0 }
  1116. };
  1117. int nrollkey = (sizeof(rollkeytab) / sizeof(struct keytab));
  1118.  
  1119. #define TT_GR_ALL 4
  1120. #define TT_GR_G0  0
  1121. #define TT_GR_G1  1
  1122. #define TT_GR_G2  2
  1123. #define TT_GR_G3  3
  1124. #define TT_GR_KBD 4
  1125. struct keytab graphsettab[] = {  /* DEC VT Graphic Sets */
  1126.     { "all",      TT_GR_ALL, 0 },
  1127.     { "g0",       TT_GR_G0,  0 },
  1128.     { "g1",       TT_GR_G1,  0 },
  1129.     { "g2",       TT_GR_G2,  0 },
  1130.     { "g3",       TT_GR_G3,  0 },
  1131.     { "keyboard", TT_GR_KBD, 0 }
  1132. };
  1133. int ngraphset = (sizeof(graphsettab) / sizeof(struct keytab));
  1134. #endif /* OS2 */
  1135.  
  1136. struct keytab adltab[] = {              /* Autodownload Options */
  1137.     { "ask",     TAD_ASK, 0 },
  1138.     { "error",   TAD_ERR, 0 },
  1139. #ifdef OS2
  1140.     { "kermit",  TAD_K,   0 },
  1141. #endif /* OS2 */
  1142.     { "off",     TAD_OFF, 0 },
  1143.     { "on",      TAD_ON,  0 },
  1144. #ifdef OS2
  1145.     { "zmodem",  TAD_Z,   0 },
  1146. #endif /* OS2 */
  1147.     { "", 0, 0 }
  1148. };
  1149. int nadltab = (sizeof(adltab) / sizeof(struct keytab)) - 1;
  1150.  
  1151. struct keytab adlerrtab[] = {           /* Autodownload Error Options */
  1152.     { "continue", 0, 0 },
  1153.     { "go",       0, CM_INV },
  1154.     { "stop",     1, 0 }
  1155. };
  1156. int nadlerrtab = (sizeof(adlerrtab) / sizeof(struct keytab));
  1157.  
  1158. #ifdef OS2
  1159. struct keytab adlxtab[] = {             /* Autodownload Options */
  1160.     { "c0-conflicts",     TAD_X_C0,     0 },
  1161.     { "detection-method", TAD_X_DETECT, 0 },
  1162.     { "string",           TAD_X_STR,    0 }
  1163. };
  1164. int nadlxtab = (sizeof(adlxtab) / sizeof(struct keytab));
  1165.  
  1166. struct keytab adldtab[] = {             /* Auto-dl Detection Methods */
  1167.     { "packet",           ADL_PACK,     0 },
  1168.     { "string",           ADL_STR,      0 }
  1169. };
  1170. int nadldtab = (sizeof(adldtab) / sizeof(struct keytab));
  1171.  
  1172. struct keytab adlc0tab[] = {            /* Auto-dl Detection Methods */
  1173.     { "ignored-by-emulator",    0,      0 },
  1174.     { "processed-by-emulator",  1,      0 }
  1175. };
  1176. int nadlc0tab = (sizeof(adlc0tab) / sizeof(struct keytab));
  1177.  
  1178. #ifndef NOCSETS
  1179. struct keytab vtlangtab[] = {
  1180.     { "belgian",        VTL_BELGIAN , 0 },
  1181.     { "british",        VTL_BRITISH , 0 },
  1182.     { "canadian",       VTL_CANADIAN, 0 },
  1183.     { "czech",          VTL_CZECH   , 0 },
  1184.     { "danish",         VTL_DANISH  , 0 },
  1185.     { "dutch",          VTL_DUTCH   , 0 },
  1186.     { "finnish",        VTL_FINNISH , 0 },
  1187.     { "french",         VTL_FRENCH  , 0 },
  1188.     { "french-canadian",VTL_FR_CAN  , 0 },
  1189.     { "german",         VTL_GERMAN  , 0 },
  1190.     { "greek",          VTL_GREEK   , 0 },
  1191.     { "hebrew",         VTL_HEBREW  , 0 },
  1192.     { "hungarian",      VTL_HUNGARIA, 0 },
  1193.     { "italian",        VTL_ITALIAN , 0 },
  1194.     { "latin-american", VTL_LATIN_AM, 0 },
  1195.     { "north-american", VTL_NORTH_AM, 0 },
  1196.     { "norwegian",      VTL_NORWEGIA, 0 },
  1197.     { "polish",         VTL_POLISH  , 0 },
  1198.     { "portugese",      VTL_PORTUGES, 0 },
  1199.     { "romanian",       VTL_ROMANIAN, 0 },
  1200.     { "russian",        VTL_RUSSIAN , 0 },
  1201.     { "scs",            VTL_SCS     , CM_INV },
  1202.     { "slovak",         VTL_SLOVAK  , 0 },
  1203.     { "spanish",        VTL_SPANISH , 0 },
  1204.     { "swedish",        VTL_SWEDISH , 0 },
  1205.     { "swiss-french",   VTL_SW_FR   , 0 },
  1206.     { "swiss-german",   VTL_SW_GR   , 0 },
  1207.     { "turkish-f",      VTL_TURK_F  , CM_INV },
  1208.     { "turkish-q",      VTL_TURK_Q  , CM_INV }
  1209. };
  1210. int nvtlangtab = (sizeof(vtlangtab) / sizeof(struct keytab));
  1211. #endif /* NOCSETS */
  1212. #endif /* OS2 */
  1213.  
  1214. struct keytab crdtab[] = {              /* Carriage-return display */
  1215.     { "crlf",        1, 0 },
  1216.     { "normal",      0, 0 }
  1217. };
  1218. extern int tt_crd;                      /* Carriage-return display variable */
  1219. extern int tt_lfd;            /* Linefeed display variable */
  1220.  
  1221. #ifdef CK_APC
  1222. extern int apcstatus, apcactive;
  1223. static struct keytab apctab[] = {       /* Terminal APC parameters */
  1224.     {  "no-input", APC_ON|APC_NOINP,0 },
  1225.     { "off",       APC_OFF,  0 },
  1226.     { "on",        APC_ON,   0 },
  1227.     { "unchecked", APC_ON|APC_UNCH, 0 },
  1228.     { "unchecked-no-input", APC_ON|APC_NOINP|APC_UNCH, 0 }
  1229. };
  1230. int napctab = (sizeof(apctab) / sizeof(struct keytab));
  1231. #endif /* CK_APC */
  1232. #endif /* NOLOCAL */
  1233.  
  1234. extern int autodl, adl_err, adl_ask;
  1235.  
  1236. struct keytab beltab[] = {              /* Terminal bell mode */
  1237. #ifdef OS2
  1238.     { "audible", XYB_AUD,  0 },
  1239.     { "none",    XYB_NONE, 0 },
  1240. #else
  1241.     { "audible", XYB_AUD,  CM_INV },
  1242.     { "none",    XYB_NONE, CM_INV },
  1243. #endif /* OS2 */
  1244. #ifdef OS2
  1245.     { "off",     XYB_NONE, CM_INV },
  1246.     { "on",      XYB_AUD,  CM_INV },
  1247. #else
  1248.     { "off",     XYB_NONE, 0 },
  1249.     { "on",      XYB_AUD,  0 },
  1250. #endif /* OS2 */
  1251. #ifdef OS2
  1252.     { "visible", XYB_VIS,  0 },
  1253. #endif /* OS2 */
  1254.     { "", 0, 0 }
  1255. };
  1256. int nbeltab = sizeof(beltab)/sizeof(struct keytab) - 1;
  1257.  
  1258. int tt_unicode = 1;                     /* Use Unicode if possible */
  1259. #ifdef CKTIDLE
  1260. int tt_idlesnd_tmo = 0;                 /* Idle Send Timeout, disabled */
  1261. char * tt_idlesnd_str = NULL;           /* Idle Send String, none */
  1262. char * tt_idlestr = NULL;
  1263. extern int tt_idleact, tt_idlelimit;
  1264. #endif /* CKTIDLE */
  1265.  
  1266. #ifdef OS2
  1267. #ifndef NOLOCAL
  1268. /*
  1269.   OS/2 serial communication devices.
  1270. */
  1271. struct keytab os2devtab[] = {
  1272.     { "1",    1, CM_INV },                      /* Invisible synonyms, like */
  1273.     { "2",    2, CM_INV },                      /* "set port 1" */
  1274.     { "3",    3, CM_INV },
  1275.     { "4",    4, CM_INV },
  1276.     { "5",    5, CM_INV },
  1277.     { "6",    6, CM_INV },
  1278.     { "7",    7, CM_INV },
  1279.     { "8",    8, CM_INV },
  1280.     { "com1", 1, 0 },                   /* Real device names */
  1281.     { "com2", 2, 0 },
  1282.     { "com3", 3, 0 },
  1283.     { "com4", 4, 0 },
  1284.     { "com5", 5, 0 },
  1285.     { "com6", 6, 0 },
  1286.     { "com7", 7, 0 },
  1287.     { "com8", 8, 0 },
  1288. #ifdef OS2ONLY
  1289.     { "slipcom1", 1, 0 },                       /* For use with SLIP driver */
  1290.     { "slipcom2", 2, 0 },                       /* shared access */
  1291.     { "slipcom3", 3, 0 },
  1292.     { "slipcom4", 4, 0 },
  1293.     { "slipcom5", 5, 0 },
  1294.     { "slipcom6", 6, 0 },
  1295.     { "slipcom7", 7, 0 },
  1296.     { "slipcom8", 8, 0 },
  1297.     { "pppcom1", 1, 0 },                        /* For use with PPP driver */
  1298.     { "pppcom2", 2, 0 },                        /* shared access */
  1299.     { "pppcom3", 3, 0 },
  1300.     { "pppcom4", 4, 0 },
  1301.     { "pppcom5", 5, 0 },
  1302.     { "pppcom6", 6, 0 },
  1303.     { "pppcom7", 7, 0 },
  1304.     { "pppcom8", 8, 0 }
  1305. #endif /* OS2ONLY */
  1306. };
  1307. int nos2dev = (sizeof(os2devtab) / sizeof(struct keytab)) - 1;
  1308.  
  1309. #ifdef OS2ONLY
  1310. struct keytab os2ppptab[] = {
  1311.     { "0",    0, CM_INV },
  1312.     { "1",    1, CM_INV },                      /* Invisible synonyms, like */
  1313.     { "2",    2, CM_INV },                      /* "set port 1" */
  1314.     { "3",    3, CM_INV },
  1315.     { "4",    4, CM_INV },
  1316.     { "5",    5, CM_INV },
  1317.     { "6",    6, CM_INV },
  1318.     { "7",    7, CM_INV },
  1319.     { "8",    8, CM_INV },
  1320.     { "9",    9, CM_INV },
  1321.     { "ppp0", 0, 0 },
  1322.     { "ppp1", 1, 0 },                   /* For use with PPP driver */
  1323.     { "ppp2", 2, 0 },                   /* shared access */
  1324.     { "ppp3", 3, 0 },
  1325.     { "ppp4", 4, 0 },
  1326.     { "ppp5", 5, 0 },
  1327.     { "ppp6", 6, 0 },
  1328.     { "ppp7", 7, 0 },
  1329.     { "ppp8", 8, 0 },
  1330.     { "ppp9", 9, 0 }
  1331. };
  1332. int nos2ppp = (sizeof(os2ppptab) / sizeof(struct keytab));
  1333. #endif /* OS2ONLY */
  1334.  
  1335. /*
  1336.   Terminal parameters that can be set by SET commands.
  1337.   Used by the ck?con.c terminal emulator code.
  1338.   For now, only used for #ifdef OS2.  Should add these for Macintosh.
  1339. */
  1340. int tt_arrow = TTK_NORM;                /* Arrow key mode: normal (cursor) */
  1341. int tt_keypad = TTK_NORM;               /* Keypad mode: normal (numeric) */
  1342. int tt_shift_keypad = 0;                /* Keypad Shift mode: Off */
  1343. int tt_wrap = 1;                        /* Terminal wrap, 1 = On */
  1344. int tt_type = TT_VT220;                 /* Terminal type, initially VT220 */
  1345. int tt_type_mode = TT_VT220;            /* Terminal type set by host command */
  1346. int tt_cursor = 0;                      /* Terminal cursor, 0 = Underline */
  1347. int tt_cursor_usr = 0;                  /* Users Terminal cursor type */
  1348. int tt_cursorena_usr = 1;               /* Users Terminal cursor enabled */
  1349. int tt_cursor_blink = 1;                /* Terminal Cursor Blink */
  1350. int tt_answer = 0;                      /* Terminal answerback (disabled) */
  1351. int tt_scrsize[VNUM] = {512,512,512,1}; /* Terminal scrollback buffer size */
  1352. int tt_roll[VNUM] = {1,1,1,1};          /* Terminal roll (on) */
  1353. int tt_rkeys[VNUM] = {1,1,1,1};        /* Terminal roll keys (send) */
  1354. int tt_pacing = 0;                      /* Terminal output-pacing (none) */
  1355. int tt_ctstmo = 15;                     /* Terminal transmit-timeout */
  1356. int tt_codepage = -1;                   /* Terminal code-page */
  1357. int tt_update = 100;                    /* Terminal screen-update interval */
  1358. int tt_updmode = TTU_FAST;              /* Terminal screen-update mode FAST */
  1359. extern int updmode;
  1360. #ifndef KUI
  1361. int tt_status[VNUM] = {1,1,0,0};        /* Terminal status line displayed */
  1362. int tt_status_usr[VNUM] = {1,1,0,0};
  1363. #else  /* KUI */
  1364. extern CKFLOAT floatval;
  1365. CKFLOAT tt_linespacing[VNUM] = {1.0,1.0,1.0,1.0};
  1366. #ifdef K95G
  1367. int tt_status[VNUM] = {1,1,0,0};        /* Terminal status line displayed */
  1368. int tt_status_usr[VNUM] = {1,1,0,0};
  1369. #else /* K95G */
  1370. int tt_status[VNUM] = {0,0,0,0};        /* Terminal status line displayed */
  1371. int tt_status_usr[VNUM] = {0,0,0,0};
  1372. #endif /* K95G */
  1373. #endif /* KUI */
  1374. int tt_senddata = 0;                    /* Let host read terminal data */
  1375. extern int wy_blockend;                 /* Terminal Send Data EOB type */
  1376. int tt_hidattr = 1;                     /* Attributes are hidden */
  1377.  
  1378. extern unsigned char colornormal, colorselect,
  1379. colorunderline, colorstatus, colorhelp, colorborder,
  1380. colorgraphic, colordebug, colorreverse, coloritalic;
  1381.  
  1382. extern int trueblink, trueunderline, truereverse, trueitalic, truedim;
  1383.  
  1384. extern int bgi, fgi;
  1385. extern int scrninitialized[];
  1386.  
  1387. struct keytab audibletab[] = {          /* Terminal Bell Audible mode */
  1388.     { "beep",          XYB_BEEP, 0 },   /* Values ORd with bell mode */
  1389.     { "system-sounds", XYB_SYS,  0 }
  1390. };
  1391. int naudibletab = sizeof(audibletab)/sizeof(struct keytab);
  1392.  
  1393. struct keytab akmtab[] = {              /* Arrow key mode */
  1394.     { "application", TTK_APPL, 0 },
  1395.     { "cursor",      TTK_NORM, 0 }
  1396. };
  1397. struct keytab kpmtab[] = {              /* Keypad mode */
  1398.     { "application", TTK_APPL, 0 },
  1399.     { "numeric",     TTK_NORM, 0 }
  1400. };
  1401.  
  1402. struct keytab ttcolmodetab[] = {
  1403.     { "current-color", 0, 0 },
  1404.     { "default-color", 1, 0 }
  1405. };
  1406. int ncolmode = sizeof(ttcolmodetab)/sizeof(struct keytab);
  1407.  
  1408. #define TTCOLNOR  0
  1409. #define TTCOLREV  1
  1410. #define TTCOLUND  2
  1411. #define TTCOLSTA  3
  1412. #define TTCOLHLP  4
  1413. #define TTCOLBOR  5
  1414. #define TTCOLSEL  6
  1415. #define TTCOLDEB  7
  1416. #define TTCOLGRP  8
  1417. #define TTCOLITA  9
  1418. #define TTCOLRES  10
  1419. #define TTCOLERA  11
  1420.  
  1421. struct keytab ttycoltab[] = {                   /* Terminal Screen coloring */
  1422.     { "border",             TTCOLBOR, 0 },      /* Screen border color */
  1423.     { "debug-terminal",     TTCOLDEB, 0 },      /* Debug color */
  1424.     { "erase",              TTCOLERA, 0 },      /* Erase mode */
  1425.     { "graphic",            TTCOLGRP, 0 },      /* Graphic Color */
  1426.     { "help-text",          TTCOLHLP, 0 },      /* Help screens */
  1427.     { "italic",             TTCOLITA, 0 },      /* Italic Color */
  1428.     { "normal",             TTCOLNOR, CM_INV }, /* Normal screen text */
  1429.     { "reset-on-esc[0m",    TTCOLRES, 0 },      /* Reset on ESC [ 0 m */
  1430.     { "reverse-video",      TTCOLREV, 0 },      /* Reverse video */
  1431.     { "status-line",        TTCOLSTA, 0 },      /* Status line */
  1432.     { "selection",          TTCOLSEL, 0 },      /* Selection color */
  1433.     { "terminal-screen",    TTCOLNOR, 0 },      /* Better name than "normal" */
  1434.     { "underlined-text",    TTCOLUND, 0 }       /* Underlined text */
  1435. };
  1436. int ncolors = (sizeof(ttycoltab) / sizeof(struct keytab));
  1437.  
  1438. #define TTATTNOR  0
  1439. #define TTATTBLI  1
  1440. #define TTATTREV  2
  1441. #define TTATTUND  3
  1442. #define TTATTPRO  4
  1443. #define TTATTBLD  5
  1444. #define TTATTDIM  6
  1445. #define TTATTINV  7
  1446. #define TTATTITA  8
  1447. #define TTATTDONE 9
  1448.  
  1449. struct keytab ttyattrtab[] = {
  1450.     { "blink",     TTATTBLI, 0 },
  1451.     { "dim",       TTATTDIM, 0 },
  1452.     { "italic",    TTATTITA, 0 },
  1453.     { "protected", TTATTPRO, 0 },
  1454.     { "reverse",   TTATTREV, 0 },
  1455.     { "underline", TTATTUND, 0 }
  1456. };
  1457. int nattrib = (sizeof(ttyattrtab) / sizeof(struct keytab));
  1458.  
  1459. struct keytab ttyprotab[] = {
  1460.     { "blink",       TTATTBLI,  0 },
  1461.     { "bold",        TTATTBLD,  0 },
  1462.     { "dim",         TTATTDIM,  0 },
  1463.     { "done",        TTATTDONE, CM_INV },
  1464.     { "invisible",   TTATTINV,  0 },
  1465.     { "italic",      TTATTITA,  0 },
  1466.     { "normal",      TTATTNOR,  0 },
  1467.     { "reverse",     TTATTREV,  0 },
  1468.     { "underlined",  TTATTUND,  0 }
  1469.  
  1470. };
  1471. int nprotect = (sizeof(ttyprotab) / sizeof(struct keytab));
  1472.  
  1473. struct keytab ttyseobtab[] = {
  1474.     { "crlf_etx",  1, 0 },
  1475.     { "us_cr",     0, 0 }
  1476. };
  1477.  
  1478. struct keytab ttyclrtab[] = {           /* Colors */
  1479.     { "black",         0, 0      },
  1480.     { "blue",          1, 0      },
  1481.     { "brown",         6, 0      },
  1482.     { "cyan",          3, 0      },
  1483.     { "darkgray",      8, CM_INV },
  1484.     { "dgray",         8, 0      },
  1485.     { "green",         2, 0      },
  1486.     { "lblue",         9, CM_INV },
  1487.     { "lcyan",        11, CM_INV },
  1488.     { "lgray",         7, CM_INV },
  1489.     { "lgreen",       10, CM_INV },
  1490.     { "lightblue",     9, 0      },
  1491.     { "lightcyan",    11, 0      },
  1492.     { "lightgray",     7, 0      },
  1493.     { "lightgreen",   10, 0      },
  1494.     { "lightmagenta", 13, 0      },
  1495.     { "lightred",     12, 0      },
  1496.     { "lmagenta",     13, CM_INV },
  1497.     { "lred",         12, CM_INV },
  1498.     { "magenta",       5, 0      },
  1499.     { "red",           4, 0      },
  1500.     { "white",        15, 0      },
  1501.     { "yellow",       14, 0      }
  1502. };
  1503. int nclrs = (sizeof (ttyclrtab) / sizeof (struct keytab));
  1504.  
  1505. struct keytab ttycurtab[] = {
  1506.     { "full",        TTC_BLOCK, 0 },
  1507.     { "half",        TTC_HALF,  0 },
  1508.     { "underline",   TTC_ULINE, 0 }
  1509. };
  1510. int ncursors = 3;
  1511.  
  1512. struct keytab ttyptab[] = {
  1513.     { "aaa",      TT_AAA,     CM_INV },     /* AnnArbor */
  1514.     { "adm3a",    TT_ADM3A,   0 },          /* LSI ADM-3A */
  1515.     { "adm5",     TT_ADM5,    0 },          /* LSI ADM-5 */
  1516.     { "aixterm",  TT_AIXTERM, 0 },          /* IBM AIXterm */
  1517.     { "annarbor", TT_AAA,     0 },          /* AnnArbor */
  1518.     { "ansi-bbs", TT_ANSI,    0 },          /* ANSI.SYS (BBS) */
  1519.     { "at386",    TT_AT386,   0 },          /* Unixware ANSI */
  1520.     { "avatar/0+",TT_ANSI,    0 },          /* AVATAR/0+ */
  1521.     { "ba80",     TT_BA80,    0 },          /* Nixdorf BA80 */
  1522.     { "be",       TT_BEOS,    CM_INV|CM_ABR },
  1523.     { "beos-ansi",TT_BEOS,    CM_INV },     /* BeOS ANSI */
  1524.     { "beterm",   TT_BEOS,    0 },          /* BeOS Terminal (as of PR2 ) */
  1525.     { "d200",     TT_DG200,   CM_INV|CM_ABR }, /* Data General DASHER 200 */
  1526.     { "d210",     TT_DG210,   CM_INV|CM_ABR }, /* Data General DASHER 210 */
  1527.     { "d217",     TT_DG217,   CM_INV|CM_ABR }, /* Data General DASHER 217 */
  1528.     { "dg200",    TT_DG200,   0 },          /* Data General DASHER 200 */
  1529.     { "dg210",    TT_DG210,   0 },          /* Data General DASHER 210 */
  1530.     { "dg217",    TT_DG217,   0 },          /* Data General DASHER 217 */
  1531.     { "h1500",    TT_HZL1500, CM_INV },     /* Hazeltine 1500 */
  1532.     { "h19",      TT_H19,     CM_INV },     /* Heath-19 */
  1533.     { "heath19",  TT_H19,     0 },          /* Heath-19 */
  1534.     { "hft",      TT_HFT,     0 },          /* IBM High Function Terminal */
  1535.     { "hp2621a",  TT_HP2621,  0 },          /* HP 2621A */
  1536.     { "hpterm",   TT_HPTERM,  0 },          /* HP TERM */
  1537.     { "hz1500",   TT_HZL1500, 0 },          /* Hazeltine 1500 */
  1538.     { "ibm3151",  TT_IBM31,   0 },          /* IBM 3101-xx,3161 */
  1539.     { "linux",    TT_LINUX,   0 },          /* Linux */
  1540.     { "qansi",    TT_QANSI,   0 },          /* QNX ANSI */
  1541.     { "qnx",      TT_QNX,     0 },          /* QNX Console */
  1542.     { "scoansi",  TT_SCOANSI, 0 },          /* SCO ANSI */
  1543.     { "sni-97801",TT_97801,   0 },          /* SNI 97801 */
  1544.     { "sun",      TT_SUN,     0 },          /* SUN Console */
  1545. /*
  1546.   The idea of NONE is to let the console driver handle the escape sequences,
  1547.   which, in theory at least, would give not only ANSI emulation, but also any
  1548.   other kind of emulation that might be provided by alternative console
  1549.   drivers, if any existed.
  1550.  
  1551.   For this to work, ckocon.c would need to be modified to make higher-level
  1552.   calls, like VioWrtTTY(), DosWrite(), or (simply) write(), rather than
  1553.   VioWrt*Cell() and similar, and it would also have to give up its rollback
  1554.   feature, and its status line and help screens would also have to be
  1555.   forgotten or else done in an ANSI way.
  1556.  
  1557.   As matters stand, we already have perfectly good ANSI emulation built in,
  1558.   and there are no alternative console drivers available, so there is no point
  1559.   in having a terminal type of NONE, so it is commented out.  However, should
  1560.   you uncomment it, it will work like a "glass tty" -- no escape sequence
  1561.   interpretation at all; somewhat similar to debug mode, except without the
  1562.   debugging (no highlighting of control chars or escape sequences); help
  1563.   screens, status line, and rollback will still work.
  1564. */
  1565. #ifdef OS2PM
  1566. #ifdef COMMENT
  1567.     { "tek4014", TT_TEK40,  0 },
  1568. #endif /* COMMENT */
  1569. #endif /* OS2PM */
  1570.     { "tty",     TT_NONE,   0 },
  1571.     { "tvi910+", TT_TVI910, 0 },
  1572.     { "tvi925",  TT_TVI925, 0 },
  1573.     { "tvi950",  TT_TVI950, 0 },
  1574.     { "vc404",   TT_VC4404, 0 },
  1575.     { "vc4404",  TT_VC4404, CM_INV },
  1576.     { "vip7809", TT_VIP7809,0 },
  1577.     { "vt100",   TT_VT100,  0 },
  1578.     { "vt102",   TT_VT102,  0 },
  1579.     { "vt220",   TT_VT220,  0 },
  1580.     { "vt220pc", TT_VT220PC,0 },
  1581.     { "vt320",   TT_VT320,  0 },
  1582.     { "vt320pc", TT_VT320PC,0 },
  1583.     { "vt52",    TT_VT52,   0 },
  1584. #ifdef NT
  1585.     { "vtnt",    TT_VTNT,   0 },
  1586. #else /* NT */
  1587.     { "vtnt",    TT_VTNT,  CM_INV },
  1588. #endif /* NT */
  1589.     { "wy160",   TT_WY160,  0 },
  1590.     { "wy30",    TT_WY30,   0 },
  1591.     { "wy370",   TT_WY370,  0 },
  1592.     { "wy50",    TT_WY50,   0 },
  1593.     { "wy60",    TT_WY60,   0 },
  1594.     { "wyse30",  TT_WY30,   CM_INV },
  1595.     { "wyse370", TT_WY370,  CM_INV },
  1596.     { "wyse50",  TT_WY50,   CM_INV },
  1597.     { "wyse60",  TT_WY60,   CM_INV }
  1598. };
  1599. int nttyp = (sizeof(ttyptab) / sizeof(struct keytab));
  1600.  
  1601. struct keytab ttkeytab[] = {
  1602.     { "aaa",       TT_AAA,        CM_INV },        /* AnnArbor */
  1603.     { "adm3a",     TT_ADM3A,      0 },             /* LSI ADM-3A */
  1604.     { "adm5",      TT_ADM5,       0 },             /* LSI ADM-5 */
  1605.     { "aixterm",   TT_AIXTERM,    0 },             /* IBM AIXterm */
  1606.     { "annarbor",  TT_AAA,        0 },             /* AnnArbor */
  1607.     { "ansi-bbs",  TT_ANSI,       0 },             /* ANSI.SYS (BBS) */
  1608.     { "at386",     TT_AT386,      0 },             /* Unixware ANSI */
  1609.     { "avatar/0+", TT_ANSI,       0 },             /* AVATAR/0+ */
  1610.     { "ba80",      TT_BA80,       0 },             /* Nixdorf BA80 */
  1611.     { "be",        TT_BEOS,       CM_INV|CM_ABR },
  1612.     { "beos-ansi", TT_BEOS,       CM_INV },        /* BeOS ANSI */
  1613.     { "beterm",    TT_BEOS,       0 },             /* BeOS Terminal (DR2) */
  1614.     { "d200",      TT_DG200,      CM_INV|CM_ABR }, /* DG DASHER 200 */
  1615.     { "d210",      TT_DG210,      CM_INV|CM_ABR }, /* DG DASHER 210 */
  1616.     { "d217",      TT_DG217,      CM_INV|CM_ABR }, /* DG DASHER 217 */
  1617.     { "dg200",     TT_DG200,      0 },             /* DG DASHER 200 */
  1618.     { "dg210",     TT_DG210,      0 },             /* DG DASHER 210 */
  1619.     { "dg217",     TT_DG217,      0 },             /* DG DASHER 217 */
  1620.     { "emacs",     TT_KBM_EMACS,  0 },             /* Emacs mode */
  1621.     { "h19",       TT_H19,        CM_INV },        /* Heath-19 */
  1622.     { "heath19",   TT_H19,        0 },             /* Heath-19 */
  1623.     { "hebrew",    TT_KBM_HEBREW, 0 },             /* Hebrew mode */
  1624.     { "hft",       TT_HFT,        0 },             /* IBM High Function Term */
  1625.     { "hp2621a",   TT_HP2621,     0 },             /* HP 2621A */
  1626.     { "hpterm",    TT_HPTERM,     0 },             /* HP TERM */
  1627.     { "hz1500",    TT_HZL1500,    0 },             /* Hazeltine 1500 */
  1628.     { "ibm3151",   TT_IBM31,      0 },             /* IBM 3101-xx,3161 */
  1629.     { "linux",     TT_LINUX,      0 },             /* Linux */
  1630.     { "qansi",     TT_QANSI,      0 },             /* QNX ANSI */
  1631.     { "qnx",       TT_QNX,        0 },             /* QNX */
  1632.     { "russian",   TT_KBM_RUSSIAN,0 },             /* Russian mode */
  1633.     { "scoansi",   TT_SCOANSI,    0 },             /* SCO ANSI */
  1634.     { "sni-97801", TT_97801,      0 },             /* SNI 97801 */
  1635.     { "sun",       TT_SUN,        0 },             /* SUN Console */
  1636. #ifdef OS2PM
  1637. #ifdef COMMENT
  1638.     { "tek4014",   TT_TEK40,      0 },
  1639. #endif /* COMMENT */
  1640. #endif /* OS2PM */
  1641.     { "tty",       TT_NONE,       0 },
  1642.     { "tvi910+",   TT_TVI910,     0 },
  1643.     { "tvi925",    TT_TVI925,     0 },
  1644.     { "tvi950",    TT_TVI950,     0 },
  1645.     { "vc404",     TT_VC4404,     0 },
  1646.     { "vc4404",    TT_VC4404,     CM_INV },
  1647.     { "vip7809",   TT_VIP7809,    0 },
  1648.     { "vt100",     TT_VT100,      0 },
  1649.     { "vt102",     TT_VT102,      0 },
  1650.     { "vt220",     TT_VT220,      0 },
  1651.     { "vt220pc",   TT_VT220PC,    0 },
  1652.     { "vt320",     TT_VT320,      0 },
  1653.     { "vt320pc",   TT_VT320PC,    0 },
  1654.     { "vt52",      TT_VT52,       0 },
  1655.     { "vtnt",      TT_VTNT,       CM_INV },
  1656.     { "wp",        TT_KBM_WP,     0 },             /* Word Perfect mode */
  1657.     { "wy160",     TT_WY160,      0 },
  1658.     { "wy30",      TT_WY30,       0 },
  1659.     { "wy370",     TT_WY370,      0 },
  1660.     { "wy50",      TT_WY50,       0 },
  1661.     { "wy60",      TT_WY60,       0 },
  1662.     { "wyse30",    TT_WY30,       CM_INV },
  1663.     { "wyse370",   TT_WY370,      CM_INV },
  1664.     { "wyse50",    TT_WY50,       CM_INV },
  1665.     { "wyse60",    TT_WY60,       CM_INV }
  1666. };
  1667. int nttkey = (sizeof(ttkeytab) / sizeof(struct keytab));
  1668.  
  1669. #ifndef NOSETKEY
  1670. struct keytab kbmodtab[] = {
  1671.     { "emacs",   KBM_EM, 0      },
  1672.     { "english", KBM_EN, CM_INV },
  1673.     { "hebrew",  KBM_HE, 0      },
  1674.     { "normal",  KBM_EN, 0      },
  1675.     { "none",    KBM_EN, CM_INV },
  1676.     { "russian", KBM_RU, 0      },
  1677.     { "wp",      KBM_WP, 0      }
  1678. };
  1679. int nkbmodtab = (sizeof(kbmodtab) / sizeof(struct keytab));
  1680. #endif /* NOSETKEY */
  1681. #endif /* NOLOCAL */
  1682.  
  1683. int tt_inpacing = 0;                    /* input-pacing (none) */
  1684.  
  1685. struct keytab prtytab[] = { /* OS/2 Priority Levels */
  1686.     { "foreground-server", XYP_SRV, 0       },
  1687.     { "idle",              XYP_IDLE, CM_INV },
  1688.     { "regular",           XYP_REG, 0       },
  1689.     { "time-critical",     XYP_RTP, 0       }
  1690. };
  1691. int nprty = (sizeof(prtytab) / sizeof(struct keytab));
  1692. #endif /* OS2 */
  1693.  
  1694. #ifdef NT
  1695. struct keytab win95tab[] = { /* Win95 work-arounds */
  1696.     { "8.3-filenames",         XYW8_3,    0 },
  1697.     { "alt-gr",                XYWAGR,    0 },
  1698.     { "horizontal-scan-line-substitutions", XYWHSL, 0 },
  1699.     { "keyboard-translation",  XYWKEY,    0 },
  1700.     { "lucida-substitutions",  XYWLUC,    0 },
  1701.     { "overlapped-io",         XYWOIO,    0 },
  1702.     { "popups",                XYWPOPUP,  0 },
  1703.     { "select-bug",            XYWSELECT, 0 }
  1704. };
  1705. int nwin95 = (sizeof(win95tab) / sizeof(struct keytab));
  1706. #endif /* NT */
  1707.  
  1708. #ifdef OS2MOUSE
  1709. extern int wideresult;
  1710. int tt_mouse = 1;                       /* Terminal mouse on/off */
  1711.  
  1712. struct keytab mousetab[] = {            /* Mouse items */
  1713.     { "activate", XYM_ON,     0 },
  1714.     { "button",   XYM_BUTTON, 0 },
  1715.     { "clear",    XYM_CLEAR,  0 },
  1716.     { "debug",    XYM_DEBUG,  0 }
  1717. };
  1718. int nmtab = (sizeof(mousetab)/sizeof(struct keytab));
  1719.  
  1720. struct keytab mousebuttontab[] = {      /* event button */
  1721.     { "1",             XYM_B1, 0 },
  1722.     { "2",             XYM_B2, 0 },
  1723.     { "3",             XYM_B3, 0 },
  1724.     { "one",           XYM_B1, CM_INV },
  1725.     { "three",         XYM_B3, CM_INV },
  1726.     { "two",           XYM_B2, CM_INV }
  1727. };
  1728. int nmbtab = (sizeof(mousebuttontab) / sizeof(struct keytab));
  1729.  
  1730. struct keytab mousemodtab[] = {         /* event button key modifier */
  1731.     { "alt",              XYM_ALT,   0 },
  1732.     { "alt-shift",        XYM_SHIFT|XYM_ALT, 0 },
  1733.     { "ctrl",             XYM_CTRL,  0 },
  1734.     { "ctrl-alt",         XYM_CTRL|XYM_ALT, 0 },
  1735.     { "ctrl-alt-shift",   XYM_CTRL|XYM_SHIFT|XYM_ALT, 0 },
  1736.     { "ctrl-shift",       XYM_CTRL|XYM_SHIFT, 0 },
  1737.     { "none",             0, 0 },
  1738.     { "shift",            XYM_SHIFT, 0 }
  1739. };
  1740. int nmmtab = (sizeof(mousemodtab) / sizeof(struct keytab));
  1741.  
  1742. struct keytab mclicktab[] = {           /* event button click modifier */
  1743.     { "click",        XYM_C1,   0 },
  1744.     { "drag",         XYM_DRAG, 0 },
  1745.     { "double-click", XYM_C2,   0 }
  1746. };
  1747. int nmctab = (sizeof(mclicktab) / sizeof(struct keytab));
  1748.  
  1749. #ifndef NOKVERBS
  1750. extern int nkverbs;
  1751. extern struct keytab kverbs[];
  1752. #endif /* NOKVERBS */
  1753. #endif /* OS2MOUSE */
  1754.  
  1755. /* #ifdef VMS */
  1756. struct keytab fbtab[] = {               /* Binary record types for VMS */
  1757.     { "fixed",     XYFT_B, 0 },         /* Fixed is normal for binary */
  1758.     { "undefined", XYFT_U, 0 }          /* Undefined if they ask for it */
  1759. };
  1760. int nfbtyp = (sizeof(fbtab) / sizeof(struct keytab));
  1761. /* #endif */
  1762.  
  1763. #ifdef VMS
  1764. struct keytab lbltab[] = {              /* Labeled File info */
  1765.     { "acl",         LBL_ACL, 0 },
  1766.     { "backup-date", LBL_BCK, 0 },
  1767.     { "name",        LBL_NAM, 0 },
  1768.     { "owner",       LBL_OWN, 0 },
  1769.     { "path",        LBL_PTH, 0 }
  1770. };
  1771. int nlblp = (sizeof(lbltab) / sizeof(struct keytab));
  1772. #else
  1773. #ifdef OS2
  1774. struct keytab lbltab[] = {              /* Labeled File info */
  1775.     { "archive",   LBL_ARC, 0 },
  1776.     { "extended",  LBL_EXT, 0 },
  1777.     { "hidden",    LBL_HID, 0 },
  1778.     { "read-only", LBL_RO,  0 },
  1779.     { "system",    LBL_SYS, 0 }
  1780. };
  1781. int nlblp = (sizeof(lbltab) / sizeof(struct keytab));
  1782. #endif /* OS2 */
  1783. #endif /* VMS */
  1784.  
  1785. #ifdef CK_CURSES
  1786. #ifdef CK_PCT_BAR
  1787. static struct keytab fdftab[] = {       /* SET FILE DISPLAY FULL options */
  1788.     { "thermometer",    1, 0, },
  1789.     { "no-thermometer", 0, 0  }
  1790. };
  1791. extern int thermometer;
  1792. #endif /* CK_PCT_BAR */
  1793. #endif /* CK_CURSES */
  1794.  
  1795. static struct keytab fdtab[] = {        /* SET FILE DISPLAY options */
  1796. #ifdef MAC                              /* Macintosh */
  1797.     { "fullscreen", XYFD_R,      0 },   /* Full-screen but not curses */
  1798.     { "none",       XYFD_N,      0 },
  1799.     { "off",        XYFD_N, CM_INV },
  1800.     { "on",         XYFD_R, CM_INV },
  1801.     { "quiet",      XYFD_N, CM_INV },
  1802. #else                                   /* Not Mac */
  1803.     { "brief", XYFD_B, 0 },             /* Brief */
  1804.     { "crt", XYFD_S, 0 },               /* CRT display */
  1805. #ifdef CK_CURSES
  1806. #ifdef COMMENT
  1807.     { "curses",     XYFD_C,  CM_INV },  /* Full-screen, curses */
  1808. #endif /* COMMENT */
  1809.     { "fullscreen", XYFD_C,  0 },       /* Full-screen, whatever the method */
  1810. #endif /* CK_CURSES */
  1811. #ifdef KUI
  1812.     { "gui",    XYFD_G, 0 },            /* GUI */
  1813. #endif /* KUI */        
  1814.     { "none",   XYFD_N, 0      },       /* No display */
  1815.     { "off",    XYFD_N, CM_INV },       /* Ditto */
  1816.     { "on",     XYFD_R, CM_INV },       /* On = Serial */
  1817.     { "quiet",  XYFD_N, CM_INV },       /* No display */
  1818.     { "serial", XYFD_R, 0      },       /* Serial */
  1819. #endif /* MAC */
  1820.     { "", 0, 0 }
  1821. };
  1822. int nfdtab = (sizeof(fdtab) / sizeof(struct keytab)) - 1;
  1823.  
  1824. struct keytab rsrtab[] = {              /* For REMOTE SET RECEIVE */
  1825.     { "packet-length", XYLEN,  0 },
  1826.     { "timeout",       XYTIMO, 0 }
  1827. };
  1828. int nrsrtab = (sizeof(rsrtab) / sizeof(struct keytab));
  1829.  
  1830. /* Send/Receive Parameters */
  1831.  
  1832. struct keytab srtab[] = {
  1833.     { "backup", XYBUP, 0 },
  1834. #ifndef NOCSETS
  1835.     { "character-set-selection", XYCSET, 0 },
  1836. #endif /* NOCSETS */
  1837.     { "control-prefix", XYQCTL, 0 },
  1838. #ifdef CKXXCHAR
  1839.     { "double-character", XYDBL, 0 },
  1840. #endif /* CKXXCHAR */
  1841.     { "end-of-packet", XYEOL, 0 },
  1842. #ifdef PIPESEND
  1843.     { "filter", XYFLTR, 0 },
  1844. #endif /* PIPESEND */
  1845. #ifdef CKXXCHAR
  1846.     { "ignore-character", XYIGN, 0 },
  1847. #endif /* CKXXCHAR */
  1848.     { "i-packets", 993, 0 },
  1849.     { "move-to", XYMOVE, 0 },
  1850.     { "negotiation-string-max-length", XYINIL, CM_INV },
  1851.     { "packet-length", XYLEN, 0 },
  1852.     { "pad-character", XYPADC, 0 },
  1853.     { "padding", XYNPAD, 0 },
  1854.     { "pathnames", XYFPATH, 0 },
  1855.     { "pause", XYPAUS, 0 },
  1856. #ifdef CK_PERMS
  1857.     { "permissions", 994, 0},        /* 206 */
  1858. #endif /* CK_PERMS */
  1859.     { "quote", XYQCTL, CM_INV },        /* = CONTROL-PREFIX */
  1860.     { "rename-to", XYRENAME, 0 },
  1861.     { "start-of-packet", XYMARK, 0 },
  1862.     { "timeout", XYTIMO, 0 },
  1863. #ifdef VMS
  1864.     { "version-numbers", 887, 0 },      /* VMS version numbers */
  1865. #endif /* VMS */
  1866.     { "", 0, 0 }
  1867. };
  1868. int nsrtab = (sizeof(srtab) / sizeof(struct keytab)) - 1;
  1869.  
  1870. #ifdef UNICODE
  1871. #define UCS_BOM 1
  1872. #define UCS_BYT 2
  1873. static struct keytab ucstab[] = {
  1874.     { "bom",        UCS_BOM, 0 },
  1875.     { "byte-order", UCS_BYT, 0 },
  1876.     { "", 0, 0 }
  1877. };
  1878. int nucstab = (sizeof(ucstab) / sizeof(struct keytab)) - 1;
  1879.  
  1880. static struct keytab botab[] = {
  1881.     { "big-endian",    0, 0 },
  1882.     { "little-endian", 1, 0 }
  1883. };
  1884. static int nbotab = 2;
  1885. #endif /* UNICODE */
  1886.  
  1887. /* REMOTE SET */
  1888.  
  1889. struct keytab rmstab[] = {
  1890.     { "attributes",  XYATTR, 0      },
  1891.     { "block-check", XYCHKT, 0      },
  1892.     { "file",        XYFILE, 0      },
  1893.     { "incomplete",  XYIFD,  CM_INV },  /* = REMOTE SET FILE INCOMPLETE */
  1894.     { "match",       XYMATCH,0      },
  1895.     { "receive",     XYRECV, 0      },
  1896.     { "retry",       XYRETR, 0      },
  1897.     { "server",      XYSERV, 0      },
  1898.     { "transfer",    XYXFER, 0      },
  1899.     { "window",      XYWIND, 0      },
  1900.     { "xfer",        XYXFER, CM_INV }
  1901. };
  1902. int nrms = (sizeof(rmstab) / sizeof(struct keytab));
  1903.  
  1904. struct keytab attrtab[] = {
  1905. #ifdef STRATUS
  1906.     { "account",       AT_ACCT, 0 },
  1907. #endif /* STRATUS */
  1908.     { "all",           AT_XALL, 0 },
  1909. #ifdef COMMENT
  1910.     { "blocksize",     AT_BLKS, 0 },    /* (not used) */
  1911. #endif /* COMMENT */
  1912. #ifndef NOCSETS
  1913.     { "character-set", AT_ENCO, 0 },
  1914. #endif /* NOCSETS */
  1915. #ifdef STRATUS
  1916.     { "creator",       AT_CREA, 0 },
  1917. #endif /* STRATUS */
  1918.     { "date",          AT_DATE, 0 },
  1919.     { "disposition",   AT_DISP, 0 },
  1920.     { "encoding",      AT_ENCO, CM_INV },
  1921.     { "format",        AT_RECF, CM_INV },
  1922.     { "length",        AT_LENK, 0 },
  1923.     { "off",           AT_ALLN, 0 },
  1924.     { "on",            AT_ALLY, 0 },
  1925. #ifdef COMMENT
  1926.     { "os-specific",   AT_SYSP, 0 },    /* (not used by UNIX or VMS) */
  1927. #endif /* COMMENT */
  1928. #ifdef CK_PERMS
  1929.     { "protection",    AT_LPRO, 0 },
  1930.     { "permissions",   AT_LPRO, CM_INV },
  1931. #endif /* CK_PERMS */
  1932.     { "record-format", AT_RECF, 0 },
  1933.     { "system-id",     AT_SYSI, 0 },
  1934.     { "type",          AT_FTYP, 0 }
  1935. };
  1936. int natr = (sizeof(attrtab) / sizeof(struct keytab)); /* how many attributes */
  1937.  
  1938. #ifdef CKTIDLE
  1939. struct keytab idlacts[] = {
  1940.     { "exit",       IDLE_EXIT, 0 },
  1941.     { "hangup",     IDLE_HANG, 0 },
  1942.     { "output",     IDLE_OUT,  0 },
  1943.     { "return",     IDLE_RET,  0 },
  1944. #ifdef TNCODE
  1945.     { "telnet-nop", IDLE_TNOP, 0 },
  1946.     { "telnet-ayt", IDLE_TAYT, 0 },
  1947. #endif /* TNCODE */
  1948.     { "", 0, 0 }
  1949. };
  1950. int nidlacts = (sizeof(idlacts) / sizeof(struct keytab)) - 1;
  1951. #endif /* CKTIDLE */
  1952.  
  1953. #ifndef NOSPL
  1954. extern int indef, inecho, insilence, inbufsize, inautodl, inintr;
  1955. #ifdef CKFLOAT
  1956. extern CKFLOAT inscale;
  1957. #endif    /* CKFLOAT */
  1958. extern char * inpbuf, * inpbp;
  1959. #ifdef OS2
  1960. extern int interm;
  1961. #endif /* OS2 */
  1962. struct keytab inptab[] = {              /* SET INPUT parameters */
  1963. #ifdef CK_AUTODL
  1964.     { "autodownload",    IN_ADL, 0 },
  1965. #endif /* CK_AUTODL */
  1966.     { "buffer-length",   IN_BUF, 0 },
  1967.     { "cancellation",    IN_CAN, 0 },
  1968.     { "case",            IN_CAS, 0 },
  1969.     { "default-timeout", IN_DEF, CM_INV }, /* There is no default timeout */
  1970.     { "echo",            IN_ECH, 0 },
  1971. #ifdef OS2
  1972.     { "pacing",          IN_PAC, CM_INV },
  1973. #endif /* OS2 */
  1974.     { "scale-factor",    IN_SCA, 0 },
  1975.     { "silence",         IN_SIL, 0 },
  1976. #ifdef OS2
  1977.     { "terminal",        IN_TRM, 0 },
  1978. #endif /* OS2 */
  1979.     { "timeout-action",  IN_TIM, 0 }
  1980. };
  1981. int ninp = (sizeof(inptab) / sizeof(struct keytab));
  1982.  
  1983. struct keytab intimt[] = {              /* SET INPUT TIMEOUT parameters */
  1984.     { "proceed", 0, 0 },                /* 0 = proceed */
  1985.     { "quit",    1, 0 }                 /* 1 = quit */
  1986. };
  1987.  
  1988. struct keytab incast[] = {              /* SET INPUT CASE parameters */
  1989.     { "ignore",  0, 0 },                /* 0 = ignore */
  1990.     { "observe", 1, 0 }                 /* 1 = observe */
  1991. };
  1992. #endif /* NOSPL */
  1993.  
  1994. struct keytab nabltab[] = {             /* For any command that needs */
  1995.     { "disabled", 0, 0 },
  1996.     { "enabled",  1, 0 },
  1997.     { "off",      0, CM_INV },          /* these keywords... */
  1998.     { "on",       1, CM_INV }
  1999. };
  2000. int nnabltab = sizeof(nabltab) / sizeof(struct keytab);
  2001.  
  2002. #ifdef OS2
  2003. struct keytab tvctab[] = {              /* SET TERM VIDEO-CHANGE */
  2004.     { "disabled",     TVC_DIS, 0 },
  2005.     { "enabled",      TVC_ENA, 0 },
  2006. #ifdef NT
  2007.     { "win95-safe",   TVC_W95, 0 },
  2008. #endif /* NT */
  2009.     { "", 0, 0 }
  2010. };
  2011. int ntvctab = (sizeof(tvctab) / sizeof(struct keytab)) - 1;
  2012.  
  2013. struct keytab msktab[] = { /* SET MS-DOS KERMIT compatibilities */
  2014. #ifdef COMMENT
  2015.     { "color",    MSK_COLOR,  0 },
  2016. #endif /* COMMENT */
  2017.     { "file-renaming", MSK_REN, 0 },
  2018.     { "keycodes", MSK_KEYS,   0 }
  2019. };
  2020. int nmsk = (sizeof(msktab) / sizeof(struct keytab));
  2021.  
  2022. struct keytab scrnupd[] = {             /* SET TERMINAL SCREEN-UPDATE */
  2023.     { "fast",   TTU_FAST,   0 },
  2024.     { "smooth", TTU_SMOOTH, 0 }
  2025. };
  2026. int nscrnupd = (sizeof(scrnupd) / sizeof(struct keytab));
  2027.  
  2028. #ifdef PCFONTS
  2029. /* This definition of the term_font[] table is only for     */
  2030. /* the OS/2 Full Screen Session and is not used on Windows */
  2031. struct keytab term_font[] = {           /* SET TERMINAL FONT */
  2032. #ifdef COMMENT
  2033.     { "cp111", TTF_111, 0 },
  2034.     { "cp112", TTF_112, 0 },
  2035.     { "cp113", TTF_113, 0 },
  2036. #endif /* COMMENT */
  2037.     { "cp437", TTF_437, 0 },
  2038.     { "cp850", TTF_850, 0 },
  2039. #ifdef COMMENT
  2040.     { "cp851", TTF_851, 0 },
  2041. #endif /* COMMENT */
  2042.     { "cp852", TTF_852, 0 },
  2043. #ifdef COMMENT
  2044.     { "cp853", TTF_853, 0 },
  2045.     { "cp860", TTF_860, 0 },
  2046.     { "cp861", TTF_861, 0 },
  2047. #endif /* COMMENT */
  2048.     { "cp862", TTF_862, 0 },
  2049. #ifdef COMMENT
  2050.     { "cp863", TTF_863, 0 },
  2051.     { "cp864", TTF_864, 0 },
  2052.     { "cp865", TTF_865, 0 },
  2053. #endif /* COMMENT */
  2054.     { "cp866", TTF_866, 0 },
  2055. #ifdef COMMENT
  2056.     { "cp880", TTF_880, 0 },
  2057.     { "cp881", TTF_881, 0 },
  2058.     { "cp882", TTF_882, 0 },
  2059.     { "cp883", TTF_883, 0 },
  2060.     { "cp884", TTF_884, 0 },
  2061.     { "cp885", TTF_885, 0 },
  2062. #endif /* COMMENT */
  2063.     { "default",TTF_ROM,0 }
  2064. };
  2065. int ntermfont = (sizeof(term_font) / sizeof(struct keytab));
  2066. int tt_font = TTF_ROM;                  /* Terminal screen font */
  2067. #else /* PCFONTS */
  2068. #ifdef NT
  2069. #ifdef KUI
  2070. struct keytab * term_font = NULL;
  2071. struct keytab * _term_font = NULL;
  2072. char * tt_facename = NULL;
  2073. int ntermfont = 0;
  2074. int tt_font = 0;
  2075. int tt_font_size = 0;
  2076. #endif /* KUI */
  2077. #endif /* NT */
  2078. #endif /* PCFONTS */
  2079.  
  2080. struct keytab anbktab[] = {             /* For any command that needs */
  2081.     { "message", 2, 0 },                /* these keywords... */
  2082.     { "off",     0, 0 },
  2083.     { "on",      1, 0 },
  2084.     { "unsafe-messag0", 99, CM_INV },
  2085.     { "unsafe-message", 3,  CM_INV }
  2086. };
  2087. int nansbk = (sizeof(anbktab) / sizeof(struct keytab));
  2088.  
  2089. int win95_popup = 1;
  2090. #ifdef NT
  2091. #ifdef KUI
  2092. int win95lucida = 0;
  2093. int win95hsl = 1;
  2094. #else /* KUI */
  2095. int win95lucida = 1;
  2096. int win95hsl = 1;
  2097. #endif /* KUI */
  2098. #else /* NT */
  2099. int win95lucida = 0;
  2100. int win95hsl = 1;
  2101. #endif /* NT */
  2102. #ifdef NT
  2103. int win95altgr  = 0;
  2104. extern int win95selectbug;
  2105. extern int win95_8_3;
  2106.  
  2107. #ifdef COMMENT
  2108. extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR);
  2109. extern struct keytab tcstab[];
  2110. extern int ntcs;
  2111. #endif /* COMMENT */
  2112. extern int maxow, maxow_usr; owwait;    /* Overlapped I/O variables */
  2113. #endif /* NT */
  2114. #endif /* OS2 */
  2115.  
  2116.  
  2117. /* The following routines broken out of doprm() to give compilers a break. */
  2118.  
  2119. /*  S E T O N  --  Parse on/off (default on), set parameter to result  */
  2120.  
  2121. int
  2122. seton(prm) int *prm; {
  2123.     int x, y;
  2124.     if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  2125.     if ((x = cmcfm()) < 0) return(x);
  2126.     *prm = y;
  2127.     return(1);
  2128. }
  2129.  
  2130. /*  S E T O N A U T O --  Parse on/off/auto (default auto) & set result */
  2131.  
  2132. struct keytab onoffaut[] = {
  2133.     { "auto", SET_AUTO, 0 },            /* 2 */
  2134.     { "off",  SET_OFF,  0 },            /* 0 */
  2135.     { "on",   SET_ON,   0 }             /* 1 */
  2136. };
  2137.  
  2138. int
  2139. setonaut(prm) int *prm; {
  2140.     int x, y;
  2141.     if ((y = cmkey(onoffaut,3,"","auto",xxstring)) < 0) return(y);
  2142.     if ((x = cmcfm()) < 0) return(x);
  2143.     *prm = y;
  2144.     return(1);
  2145. }
  2146.  
  2147. /*  S E T N U M  --  Set parameter to result of cmnum() parse.  */
  2148. /*
  2149.  Call with pointer to integer variable to be set,
  2150.    x = number from cnum parse, y = return code from cmnum,
  2151.    max = maximum value to accept, -1 if no maximum.
  2152.  Returns -9 on failure, after printing a message, or 1 on success.
  2153. */
  2154. int
  2155. setnum(prm,x,y,max) int x, y, *prm, max; {
  2156.     debug(F101,"setnum","",y);
  2157.     if (y == -3) {
  2158.         printf("\n?Value required\n");
  2159.         return(-9);
  2160.     }
  2161.     if (y == -2) {
  2162.         printf("%s?Not a number: %s\n",cmflgs == 1 ? "" : "\n", atxbuf);
  2163.         return(-9);
  2164.     }
  2165.     if (y < 0) return(y);
  2166.     if (max > -1 && x > max) {
  2167.         printf("?Sorry, %d is the maximum\n",max);
  2168.         return(-9);
  2169.     }
  2170.     if ((y = cmcfm()) < 0) return(y);
  2171.     *prm = x;
  2172.     return(1);
  2173. }
  2174.  
  2175. /*  S E T C C  --  Set parameter var to an ASCII control character value.  */
  2176. /*
  2177.   Parses a number, or a literal control character, or a caret (^) followed
  2178.   by an ASCII character whose value is 63-95 or 97-122, then gets confirmation,
  2179.   then sets the parameter to the code value of the character given.  If there
  2180.   are any parse errors, they are returned, otherwise on success 1 is returned.
  2181. */
  2182. int
  2183. setcc(dflt,var) char *dflt; int *var; {
  2184.     int x, y;
  2185.     unsigned int c;
  2186.     char *hlpmsg = "Control character,\n\
  2187.  numeric ASCII value,\n\
  2188.  or in ^X notation,\n\
  2189.  or preceded by a backslash and entered literally";
  2190.  
  2191.     /* This is a hack to turn off complaints from expression evaluator. */
  2192.     x_ifnum = 1;
  2193.     y = cmnum(hlpmsg, dflt, 10, &x, xxstring); /* Parse a number */
  2194.     x_ifnum = 0;                               /* Allow complaints again */
  2195.     if (y < 0) {                        /* Parse failed */
  2196.         if (y != -2)                    /* Reparse needed or somesuch */
  2197.           return(y);                    /* Pass failure back up the chain */
  2198.     }
  2199.     /* Real control character or literal 8-bit character... */
  2200.  
  2201.     for (c = strlen(atmbuf) - 1; c > 0; c--) /* Trim */
  2202.       if (atmbuf[c] == SP) atmbuf[c] = NUL;
  2203.  
  2204.     if (y < 0) {                        /* It was not a number */
  2205.         if (((c = atmbuf[0])) && !atmbuf[1]) { /* Literal character? */
  2206.             c &= 0xff;
  2207.             if (((c > 31) && (c < 127)) || (c > 255)) {
  2208.                 printf("\n?%d: Out of range - must be 0-31 or 127-255\n",c);
  2209.                 return(-9);
  2210.             } else {
  2211.                 if ((y = cmcfm()) < 0)  /* Confirm */
  2212.                   return(y);
  2213.                 *var = c;               /* Set the variable */
  2214.                 return(1);
  2215.             }
  2216.         } else if (atmbuf[0] == '^' && !atmbuf[2]) { /* Or ^X notation? */
  2217.             c = atmbuf[1];
  2218.             if (islower((char) c))      /* Uppercase lowercase letters */
  2219.               c = toupper(c);
  2220.             if (c > 62 && c < 96) {     /* Check range */
  2221.                 if ((y = cmcfm()) < 0)
  2222.                   return(y);
  2223.                 *var = ctl(c);          /* OK */
  2224.                 return(1);
  2225.             } else {
  2226.                 printf("?Not a control character - %s\n", atmbuf);
  2227.                 return(-9);
  2228.             }
  2229.         } else {                        /* Something illegal was typed */
  2230.             printf("?Invalid - %s\n", atmbuf);
  2231.             return(-9);
  2232.         }
  2233.     }
  2234.     if (((x > 31) && (x < 127)) || (x > 255)) { /* They typed a number */
  2235.         printf("\n?%d: Out of range - must be 0-31 or 127-255\n",x);
  2236.         return(-9);
  2237.     }
  2238.     if ((y = cmcfm()) < 0)              /* In range, confirm */
  2239.       return(y);
  2240.     *var = x;                           /* Set variable */
  2241.     return(1);
  2242. }
  2243.  
  2244. #ifndef NOSPL                           /* The SORT command... */
  2245.  
  2246. static struct keytab srtswtab[] = {     /* SORT command switches */
  2247.     { "/case",    SRT_CAS, CM_ARG },
  2248.     { "/key",     SRT_KEY, CM_ARG },
  2249.     { "/numeric", SRT_NUM, 0 },
  2250.     { "/range",   SRT_RNG, CM_ARG },
  2251.     { "/reverse", SRT_REV, 0 }
  2252. };
  2253. static int nsrtswtab = sizeof(srtswtab)/sizeof(struct keytab);
  2254.  
  2255. extern char **a_ptr[];                  /* Array pointers */
  2256. extern int a_dim[];                     /* Array dimensions */
  2257.  
  2258. int
  2259. dosort() {                              /* Do the SORT command */
  2260.     char c, *p = NULL, ** ap, ** xp = NULL;
  2261.     struct FDB sw, fl, cm;
  2262.     int hi, lo;
  2263.     int xn = 0, xr = -1, xk = -1, xc = -1, xs = 0;
  2264.     int getval = 0, range[2], confirmed = 0;
  2265.  
  2266.     cmfdbi(&sw,                         /* First FDB - command switches */
  2267.            _CMKEY,                      /* fcode */
  2268.            "Array name or switch",
  2269.            "",                          /* default */
  2270.            "",                          /* addtl string data */
  2271.            nsrtswtab,                   /* addtl numeric data 1: tbl size */
  2272.            4,                           /* addtl numeric data 2: 4 = cmswi */
  2273.            NULL,                        /* Processing function */
  2274.            srtswtab,                    /* Keyword table */
  2275.            &fl                          /* Pointer to next FDB */
  2276.            );
  2277.     cmfdbi(&fl,                         /* Anything that doesn't match */
  2278.            _CMFLD,                      /* fcode */
  2279.            "Array name",                /* hlpmsg */
  2280.            "",                          /* default */
  2281.            "",                          /* addtl string data */
  2282.            0,                           /* addtl numeric data 1 */
  2283.            0,                           /* addtl numeric data 2 */
  2284.            NULL,
  2285.            NULL,
  2286.            &cm
  2287.            );
  2288.     cmfdbi(&cm,                         /* Or premature confirmation */
  2289.            _CMCFM,                      /* fcode */
  2290.            "",                          /* hlpmsg */
  2291.            "",                          /* default */
  2292.            "",                          /* addtl string data */
  2293.            0,                           /* addtl numeric data 1 */
  2294.            0,                           /* addtl numeric data 2 */
  2295.            NULL,
  2296.            NULL,
  2297.            NULL
  2298.            );
  2299.  
  2300.     range[0] = -1;
  2301.     range[1] = -1;
  2302.  
  2303.     while (1) {                         /* Parse 0 or more switches */
  2304.         x = cmfdb(&sw);
  2305.         if (x < 0)
  2306.           return(x);
  2307.         if (cmresult.fcode != _CMKEY)   /* Break out if not a switch */
  2308.           break;
  2309.         c = cmgbrk();
  2310.         getval = (c == ':' || c == '=');
  2311.         if (getval && !(cmresult.kflags & CM_ARG)) {
  2312.             printf("?This switch does not take arguments\n");
  2313.             return(-9);
  2314.         }
  2315.         switch (cmresult.nresult) {
  2316.           case SRT_REV:
  2317.             xr = 1;
  2318.             break;
  2319.           case SRT_KEY:
  2320.             if (getval) {
  2321.                 if ((y = cmnum("Column for comparison (1-based)",
  2322.                                "1",10,&x,xxstring)) < 0)
  2323.                   return(y);
  2324.                 xk = x - 1;
  2325.             } else
  2326.               xk = 0;
  2327.             break;
  2328.           case SRT_CAS:
  2329.             if (getval) {
  2330.                 if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
  2331.                   return(y);
  2332.                 xc = y;
  2333.             } else
  2334.               xc = 1;
  2335.             break;
  2336.           case SRT_RNG:                 /* /RANGE */
  2337.             if (getval) {
  2338.                 char buf[32];
  2339.                 char buf2[16];
  2340.                 int i;
  2341.                 char * p, * q;
  2342.                 if ((y = cmfld("low:high element","1",&s,NULL)) < 0)
  2343.                   return(y);
  2344.                 s = brstrip(s);
  2345.                 ckstrncpy(buf,s,32);
  2346.                 p = buf;
  2347.                 for (i = 0; *p && i < 2; i++) { /* Get low and high */
  2348.                     q = p;              /* Start of this piece */
  2349.                     while (*p) {        /* Find end of this piece */
  2350.                         if (*p == ':') {
  2351.                             *p = NUL;
  2352.                             p++;
  2353.                             break;
  2354.                         }
  2355.                         p++;
  2356.                     }
  2357.                     y = 15;             /* Evaluate this piece */
  2358.                     s = buf2;
  2359.                     zzstring(q,&s,&y);
  2360.                     s = evalx(buf2);
  2361.                     if (s) if (*s) ckstrncpy(buf2,s,16);
  2362.                     if (!rdigits(buf2)) {
  2363.                         printf("?Not numeric: %s\n",buf2);
  2364.                         return(-9);
  2365.                     }
  2366.                     range[i] = atoi(buf2);
  2367.                 }
  2368.             }
  2369.             break;
  2370.           case SRT_NUM:                 /* /NUMERIC */
  2371.             xn = 1;
  2372.             break;
  2373.           default:
  2374.             return(-2);
  2375.         }
  2376.     }
  2377.     switch (cmresult.fcode) {
  2378.       case _CMCFM:
  2379.         confirmed = 1;
  2380.         break;
  2381.       case _CMFLD:
  2382.         ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Safe copy of name */
  2383.         s = line;
  2384.         break;
  2385.       default:
  2386.         printf("?Unexpected function code: %d\n",cmresult.fcode);
  2387.         return(-9);
  2388.     }
  2389.     if (confirmed) {
  2390.         printf("?Array name required\n");
  2391.         return(-9);
  2392.     }
  2393.     ckmakmsg(tmpbuf,TMPBUFSIZ,
  2394.              "Second array to sort according to ",s,NULL,NULL);
  2395.     if ((x = cmfld(tmpbuf,"",&p,NULL)) < 0)
  2396.       if (x != -3)
  2397.         return(x);
  2398.     tmpbuf[0] = NUL;
  2399.     ckstrncpy(tmpbuf,p,TMPBUFSIZ);
  2400.     p = tmpbuf;
  2401.     if ((x = cmcfm()) < 0)              /* Get confirmation */
  2402.       return(x);
  2403.  
  2404.     x = arraybounds(s,&lo,&hi);         /* Get array index & bounds */
  2405.     if (x < 0) {                        /* Check */
  2406.         printf("?Bad array name: %s\n",s);
  2407.         return(-9);
  2408.     }
  2409.     if (lo > -1) range[0] = lo;         /* Set range */
  2410.     if (hi > -1) range[1] = hi;
  2411.     ap = a_ptr[x];                      /* Get pointer to array element list */
  2412.     if (!ap) {                          /* Check */
  2413.         printf("?Array not declared: %s\n", s);
  2414.         return(-9);
  2415.     }
  2416.     if (range[0] < 0)                   /* Starting element */
  2417.       range[0] = 1;
  2418.     if (range[1] < 0)                   /* Final element */
  2419.       range[1] = a_dim[x];
  2420.     if (range[1] > a_dim[x]) {
  2421.         printf("?range %d:%d exceeds array dimension %d\n",
  2422.                range[0],range[1],a_dim[x]
  2423.                );
  2424.         return(-9);
  2425.     }
  2426.     ap += range[0];
  2427.     xs = range[1] - range[0] + 1;       /* Number of elements to sort */
  2428.     if (xs < 1) {                       /* Check */
  2429.         printf("?Bad range: %d:%d\n",range[0],range[1]);
  2430.         return(-9);
  2431.     }
  2432.     if (xk < 0) xk = 0;                 /* Key position */
  2433.     if (xr < 0) xr = 0;                 /* Reverse flag */
  2434.     if (xn)                             /* Numeric flag */
  2435.       xc = 2;
  2436.     else if (xc < 0)                    /* Not numeric */
  2437.       xc = inpcas[cmdlvl];              /* so alpha case option */
  2438.  
  2439.     if (*p) {                           /* Parallel array given? */
  2440.         y = xarray(p);                  /* Yes, get its index. */
  2441.         if (y < 0) {
  2442.             printf("?Bad array name: %s\n", p);
  2443.             return(-9);
  2444.         }
  2445.         if (y != x) {                   /* If the 2 arrays are different  */
  2446.             xp = a_ptr[y];              /* Pointer to 2nd array element list */
  2447.             if (!xp) {
  2448.                 printf("?Array not declared: %s\n", p);
  2449.                 return(-9);
  2450.             }
  2451.             if (a_dim[y] < range[1]) {
  2452.                 printf("?Array %s smaller than %s\n", p, s);
  2453.                 return(-9);
  2454.             }
  2455.             xp += range[0];             /* Set base to same as 1st array */
  2456.         }
  2457.     }
  2458.     sh_sort(ap,xp,xs,xk,xr,xc);         /* Sort the array(s) */
  2459.     return(success = 1);                /* Always succeeds */
  2460. }
  2461. #endif /* NOSPL */
  2462.  
  2463. static struct keytab purgtab[] = {      /* PURGE command switches */
  2464.     { "/after",        PU_AFT,  CM_ARG },
  2465.     { "/ask",          PU_ASK,  0 },
  2466.     { "/before",       PU_BEF,  CM_ARG },
  2467.     { "/delete",       PU_DELE, CM_INV },
  2468. #ifdef UNIXOROSK
  2469.     { "/dotfiles",     PU_DOT,  0 },
  2470. #endif /* UNIXOROSK */
  2471.     { "/except",       PU_EXC,  CM_ARG },
  2472.     { "/heading",      PU_HDG,  0 },
  2473.     { "/keep",         PU_KEEP, CM_ARG },
  2474.     { "/larger-than",  PU_LAR,  CM_ARG },
  2475.     { "/list",         PU_LIST, 0 },
  2476.     { "/log",          PU_LIST, CM_INV },
  2477.     { "/noask",        PU_NASK, 0 },
  2478.     { "/nodelete",     PU_NODE, CM_INV },
  2479. #ifdef UNIXOROSK
  2480.     { "/nodotfiles",   PU_NODOT,0 },
  2481. #endif /* UNIXOROSK */
  2482.     { "/noheading",    PU_NOH,  0 },
  2483.     { "/nol",          PU_NOLI, CM_INV|CM_ABR },
  2484.     { "/nolist",       PU_NOLI, 0 },
  2485.     { "/nolog",        PU_NOLI, CM_INV },
  2486. #ifdef CK_TTGWSIZ
  2487.     { "/nopage",       PU_NOPA, 0 },
  2488. #endif /* CK_TTGWSIZ */
  2489.     { "/not-after",    PU_NAF,  CM_ARG },
  2490.     { "/not-before",   PU_NBF,  CM_ARG },
  2491.     { "/not-since",    PU_NAF,  CM_INV|CM_ARG },
  2492. #ifdef CK_TTGWSIZ
  2493.     { "/page",         PU_PAGE, 0 },
  2494. #endif /* CK_TTGWSIZ */
  2495.     { "/quiet",        PU_QUIE, CM_INV },
  2496. #ifdef RECURSIVE
  2497.     { "/recursive",    PU_RECU, 0 },
  2498. #endif /* RECURSIVE */
  2499.     { "/since",        PU_AFT,  CM_ARG|CM_INV },
  2500.     { "/simulate",     PU_NODE, 0 },
  2501.     { "/smaller-than", PU_SMA,  CM_ARG },
  2502.     { "/verbose",      PU_VERB, CM_INV }
  2503. };
  2504. static int npurgtab = sizeof(purgtab)/sizeof(struct keytab);
  2505.  
  2506.  
  2507.  
  2508.  
  2509.  
  2510. int
  2511. bkupnum(s,i) char * s; int *i; {
  2512.     int k = 0, pos = 0;
  2513.     char * p = NULL, *q;
  2514.     *i = pos;
  2515.     if (!s) s = "";
  2516.     if (!*s)
  2517.       return(-1);
  2518.     if ((k = strlen(s)) < 5)
  2519.       return(-1);
  2520.  
  2521.     if (s[k-1] != '~')
  2522.       return(-1);
  2523.     pos = k - 2;
  2524.     q = s + pos;
  2525.     while (q >= s && isdigit(*q)) {
  2526.         p = q--;
  2527.         pos--;
  2528.     }
  2529.     if (!p)
  2530.       return(-1);
  2531.     if (q < s+2)
  2532.       return(-1);
  2533.     if (*q != '~' || *(q-1) != '.')
  2534.       return(-1);
  2535.     pos--;
  2536.     *i = pos;
  2537.     debug(F111,"bkupnum",s+pos,pos);
  2538.     return(atoi(p));
  2539. }
  2540.  
  2541. #ifdef CKPURGE
  2542. /* Presently only for UNIX because we need direct access to the file array. */
  2543. /* Not needed for VMS anyway, because we don't make backup files there. */
  2544.  
  2545. #define MAXKEEP 32                      /* Biggest /KEEP: value */
  2546.  
  2547. static int
  2548.   pu_keep = 0, pu_list = 0, pu_dot = 0, pu_ask = 0, pu_hdg = 0;
  2549.  
  2550. #ifdef CK_TTGWSIZ
  2551. static int pu_page = -1;
  2552. #else
  2553. static int pu_page = 0;
  2554. #endif /* CK_TTGWSIZ */
  2555.  
  2556. #ifndef NOSHOW
  2557. VOID
  2558. showpurgopts() {                        /* SHOW PURGE command options */
  2559.     int x = 0;
  2560.     extern int optlines;
  2561.     prtopt(&optlines,"PURGE");
  2562.     if (pu_ask > -1) {
  2563.         x++;
  2564.         prtopt(&optlines, pu_ask ? "/ASK" : "/NOASK");
  2565.     }
  2566. #ifdef UNIXOROSK
  2567.     if (pu_dot > -1) {
  2568.         x++;
  2569.         prtopt(&optlines, pu_dot ? "/DOTFILES" : "/NODOTFILES");
  2570.     }
  2571. #endif /* UNIXOROSK */
  2572.     if (pu_keep > -1) {
  2573.         x++;
  2574.         ckmakmsg(tmpbuf,TMPBUFSIZ,"/KEEP:",ckitoa(pu_keep),NULL,NULL);
  2575.         prtopt(&optlines,tmpbuf);
  2576.     }
  2577.     if (pu_list > -1) {
  2578.         x++;
  2579.         prtopt(&optlines, pu_list ? "/LIST" : "/NOLIST");
  2580.     }
  2581.     if (pu_hdg > -1) {
  2582.         x++;
  2583.         prtopt(&optlines, pu_hdg ? "/HEADING" : "/NOHEADING");
  2584.     }
  2585. #ifdef CK_TTGWSIZ
  2586.     if (pu_page > -1) {
  2587.         x++;
  2588.         prtopt(&optlines, pu_page ? "/PAGE" : "/NOPAGE");
  2589.     }
  2590. #endif /* CK_TTGWSIZ */
  2591.     if (!x) prtopt(&optlines,"(no options set)");
  2592.     prtopt(&optlines,"");
  2593. }
  2594. #endif /* NOSHOW */
  2595.  
  2596. int
  2597. setpurgopts() {                         /* Set PURGE command options */
  2598.     int c, z, getval = 0;
  2599.     int
  2600.       x_keep  = -1, x_list = -1, x_page = -1,
  2601.       x_hdg   = -1, x_ask  = -1, x_dot  = -1;
  2602.  
  2603.     while (1) {
  2604.         if ((y = cmswi(purgtab,npurgtab,"Switch","",xxstring)) < 0) {
  2605.             if (y == -3)
  2606.               break;
  2607.             else
  2608.               return(y);
  2609.         }
  2610.         c = cmgbrk();
  2611.         if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  2612.             printf("?This switch does not take an argument\n");
  2613.             return(-9);
  2614.         }
  2615.         if (!getval && (cmgkwflgs() & CM_ARG)) {
  2616.             printf("?This switch requires an argument\n");
  2617.             return(-9);
  2618.         }
  2619.         switch (y) {
  2620.           case PU_KEEP:
  2621.             z = 1;
  2622.             if (c == ':' || c == '=')
  2623.               if ((y = cmnum("How many backup files to keep",
  2624.                              "1",10,&z,xxstring)) < 0)
  2625.                 return(y);
  2626.             if (z < 0 || z > MAXKEEP) {
  2627.                 printf("?Please specify a number between 0 and %d\n",
  2628.                        MAXKEEP
  2629.                        );
  2630.                 return(-9);
  2631.             }
  2632.             x_keep = z;
  2633.             break;
  2634.           case PU_LIST:
  2635.           case PU_VERB:
  2636.             x_list = 1;
  2637.             break;
  2638.           case PU_QUIE:
  2639.           case PU_NOLI:
  2640.             x_list = 0;
  2641.             break;
  2642. #ifdef CK_TTGWSIZ
  2643.           case PU_PAGE:
  2644.             x_page = 1;
  2645.             break;
  2646.           case PU_NOPA:
  2647.             x_page = 0;
  2648.             break;
  2649. #endif /* CK_TTGWSIZ */
  2650.           case PU_HDG:
  2651.             x_hdg = 1;
  2652.             break;
  2653.           case PU_NOH:
  2654.             x_hdg = 0;
  2655.             break;
  2656.           case PU_ASK:
  2657.             x_ask = 1;
  2658.             break;
  2659.           case PU_NASK:
  2660.             x_ask = 0;
  2661.             break;
  2662. #ifdef UNIXOROSK
  2663.           case PU_DOT:
  2664.             x_dot = 1;
  2665.             break;
  2666.           case PU_NODOT:
  2667.             x_dot = 0;
  2668.             break;
  2669. #endif /* UNIXOROSK */
  2670.           default:
  2671.             printf("?This option can not be set\n");
  2672.             return(-9);
  2673.         }
  2674.     }
  2675.     if ((x = cmcfm()) < 0)              /* Get confirmation */
  2676.       return(x);
  2677.     if (x_keep > -1)                    /* Set PURGE defaults. */
  2678.       pu_keep = x_keep;
  2679.     if (x_list > -1)
  2680.       pu_list = x_list;
  2681. #ifdef CK_TTGWSIZ
  2682.     if (x_page > -1)
  2683.       pu_page = x_page;
  2684. #endif /* CK_TTGWSIZ */
  2685.     if (x_hdg > -1)
  2686.       pu_hdg = x_hdg;
  2687.     if (x_ask > -1)
  2688.       pu_ask = x_ask;
  2689.     if (x_dot > -1)
  2690.       pu_dot = x_dot;
  2691.     return(success = 1);
  2692. }
  2693.  
  2694. int
  2695. dopurge() {                             /* Do the PURGE command */
  2696.     extern char ** mtchs;
  2697.     extern int xaskmore, cmd_rows, recursive;
  2698.     int simulate = 0, asking = 0;
  2699.     int listing = 0, paging = -1, lines = 0, deleting = 1, errors = 0;
  2700.     struct FDB sw, sf, cm;
  2701.     int g, i, j, k, m = 0, n, x, y, z, done = 0, count = 0, flags = 0;
  2702.     int tokeep = 0, getval = 0, havename = 0, confirmed = 0;
  2703.     int xx[MAXKEEP+1];                  /* Array of numbers to keep */
  2704.     int min = -1;
  2705.     int x_hdg = 0, fs = 0, rc = 0;
  2706.     CK_OFF_T minsize = -1L, maxsize = -1L;
  2707.     char namebuf[CKMAXPATH+4];
  2708.     char basebuf[CKMAXPATH+4];
  2709.     char
  2710.       * pu_aft = NULL,
  2711.       * pu_bef = NULL,
  2712.       * pu_naf = NULL,
  2713.       * pu_nbf = NULL,
  2714.       * pu_exc = NULL;
  2715.     char * pxlist[8];                   /* Exception list */
  2716.  
  2717.     if (pu_keep > -1)                   /* Set PURGE defaults. */
  2718.       tokeep = pu_keep;
  2719.     if (pu_list > -1)
  2720.       listing = pu_list;
  2721. #ifdef CK_TTGWSIZ
  2722.     if (pu_page > -1)
  2723.       paging = pu_page;
  2724. #endif /* CK_TTGWSIZ */
  2725.  
  2726.     for (i = 0; i <= MAXKEEP; i++)      /* Clear this number buffer */
  2727.       xx[i] = 0;
  2728.     for (i = 0; i < 8; i++)             /* Initialize these... */
  2729.       pxlist[i] = NULL;
  2730.  
  2731.     g_matchdot = matchdot;              /* Save these... */
  2732.  
  2733.     cmfdbi(&sw,                         /* 1st FDB - PURGE switches */
  2734.            _CMKEY,                      /* fcode */
  2735.            "Filename or switch",        /* hlpmsg */
  2736.            "",                          /* default */
  2737.            "",                          /* addtl string data */
  2738.            npurgtab,                    /* addtl numeric data 1: tbl size */
  2739.            4,                           /* addtl numeric data 2: 4 = cmswi */
  2740.            xxstring,                    /* Processing function */
  2741.            purgtab,                     /* Keyword table */
  2742.            &sf                          /* Pointer to next FDB */
  2743.            );
  2744.     cmfdbi(&sf,                         /* 2nd FDB - filespec to purge */
  2745.            _CMIFI,                      /* fcode */
  2746.            "",
  2747.            "",                          /* default */
  2748.            "",                          /* addtl string data */
  2749.            0,                           /* addtl numeric data 1 */
  2750.            0,                           /* addtl numeric data 2 */
  2751.            xxstring,
  2752.            NULL,
  2753.            &cm
  2754.            );
  2755.     cmfdbi(&cm,                         /* Or premature confirmation */
  2756.            _CMCFM,                      /* fcode */
  2757.            "",                          /* hlpmsg */
  2758.            "",                          /* default */
  2759.            "",                          /* addtl string data */
  2760.            0,                           /* addtl numeric data 1 */
  2761.            0,                           /* addtl numeric data 2 */
  2762.            NULL,
  2763.            NULL,
  2764.            NULL
  2765.            );
  2766.  
  2767.     while (!havename && !confirmed) {
  2768.         x = cmfdb(&sw);                 /* Parse something */
  2769.         if (x < 0) {                    /* Error */
  2770.             rc = x;
  2771.             goto xpurge;
  2772.         } else if (cmresult.fcode == _CMKEY) {
  2773.             char c;
  2774.             c = cmgbrk();
  2775.             if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  2776.                 printf("?This switch does not take an argument\n");
  2777.                 rc = -9;
  2778.                 goto xpurge;
  2779.             }
  2780.             if (!getval && (cmgkwflgs() & CM_ARG)) {
  2781.                 printf("?This switch requires an argument\n");
  2782.                 rc = -9;
  2783.                 goto xpurge;
  2784.             }
  2785.             switch (k = cmresult.nresult) {
  2786.               case PU_KEEP:
  2787.                 z = 1;
  2788.                 if (c == ':' || c == '=') {
  2789.                     if ((y = cmnum("How many backup files to keep",
  2790.                                    "1",10,&z,xxstring)) < 0) {
  2791.                         rc = y;
  2792.                         goto xpurge;
  2793.                     }
  2794.                 }
  2795.                 if (z < 0 || z > MAXKEEP) {
  2796.                     printf("?Please specify a number between 0 and %d\n",
  2797.                            MAXKEEP
  2798.                            );
  2799.                     rc = -9;
  2800.                     goto xpurge;
  2801.                 }
  2802.                 tokeep = z;
  2803.                 break;
  2804.               case PU_LIST:
  2805.                 listing = 1;
  2806.                 break;
  2807.               case PU_NOLI:
  2808.                 listing = 0;
  2809.                 break;
  2810. #ifdef CK_TTGWSIZ
  2811.               case PU_PAGE:
  2812.                 paging = 1;
  2813.                 break;
  2814.               case PU_NOPA:
  2815.                 paging = 0;
  2816.                 break;
  2817. #endif /* CK_TTGWSIZ */
  2818.               case PU_DELE:
  2819.                 deleting = 1;
  2820.                 break;
  2821.               case PU_NODE:
  2822.                 deleting = 0;
  2823.                 simulate = 1;
  2824.                 listing = 1;
  2825.                 break;
  2826.               case PU_ASK:
  2827.                 asking = 1;
  2828.                 break;
  2829.               case PU_NASK:
  2830.                 asking = 0;
  2831.                 break;
  2832.               case PU_AFT:
  2833.               case PU_BEF:
  2834.               case PU_NAF:
  2835.               case PU_NBF:
  2836.                 if ((x = cmdate("File-time","",&s,0,xxstring)) < 0) {
  2837.                     if (x == -3) {
  2838.                         printf("?Date-time required\n");
  2839.                         rc = -9;
  2840.                     } else
  2841.                       rc = x;
  2842.                     goto xpurge;
  2843.                 }
  2844.                 fs++;
  2845.                 switch (k) {
  2846.                   case PU_AFT: makestr(&pu_aft,s); break;
  2847.                   case PU_BEF: makestr(&pu_bef,s); break;
  2848.                   case PU_NAF: makestr(&pu_naf,s); break;
  2849.                   case PU_NBF: makestr(&pu_nbf,s); break;
  2850.                 }
  2851.                 break;
  2852.               case PU_SMA:
  2853.               case PU_LAR:
  2854.                 if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0) {
  2855.                     rc = x;
  2856.                     goto xpurge;
  2857.                 }
  2858.                 fs++;
  2859.                 switch (cmresult.nresult) {
  2860.                   case PU_SMA: minsize = y; break;
  2861.                   case PU_LAR: maxsize = y; break;
  2862.                 }
  2863.                 break;
  2864.               case PU_DOT:
  2865.                 matchdot = 1;
  2866.                 break;
  2867.               case PU_NODOT:
  2868.                 matchdot = 0;
  2869.                 break;
  2870.               case PU_EXC:
  2871.                 if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
  2872.                     if (x == -3) {
  2873.                         printf("?Pattern required\n");
  2874.                         rc = -9;
  2875.                     } else
  2876.                       rc = x;
  2877.                     goto xpurge;
  2878.                 }
  2879.                 fs++;
  2880.                 makestr(&pu_exc,s);
  2881.                 break;
  2882.               case PU_HDG:
  2883.                 x_hdg = 1;
  2884.                 break;
  2885. #ifdef RECURSIVE
  2886.               case PU_RECU:             /* /RECURSIVE */
  2887.                 recursive = 2;
  2888.                 break;
  2889. #endif /* RECURSIVE */
  2890.               default:
  2891.                 printf("?Not implemented yet - \"%s\"\n",atmbuf);
  2892.                 rc = -9;
  2893.                 goto xpurge;
  2894.             }
  2895.         } else if (cmresult.fcode == _CMIFI) {
  2896.             havename = 1;
  2897.         } else if (cmresult.fcode == _CMCFM) {
  2898.             confirmed = 1;
  2899.         } else {
  2900.             rc = -2;
  2901.             goto xpurge;
  2902.         }
  2903.     }
  2904.     if (havename) {
  2905. #ifdef CKREGEX
  2906.         ckmakmsg(line,LINBUFSIZ,cmresult.sresult,".~[1-9]*~",NULL,NULL);
  2907. #else
  2908.         ckmakmsg(line,LINBUFSIZ,cmresult.sresult,".~*~",NULL,NULL);
  2909. #endif /* CKREGEX */
  2910.     } else {
  2911. #ifdef CKREGEX
  2912.         ckstrncpy(line,"*.~[1-9]*~",LINBUFSIZ);
  2913. #else
  2914.         ckstrncpy(line,"*.~*~",LINBUFSIZ);
  2915. #endif /* CKREGEX */
  2916.     }
  2917.     if (!confirmed) {
  2918.         if ((x = cmcfm()) < 0) {
  2919.             rc = x;
  2920.             goto xpurge;
  2921.         }
  2922.     }
  2923.     /* Parse finished - now action */
  2924.  
  2925. #ifdef CK_LOGIN
  2926.     if (isguest) {
  2927.         printf("?File deletion by guests not permitted.\n");
  2928.         rc = -9;
  2929.         goto xpurge;
  2930.     }
  2931. #endif /* CK_LOGIN */
  2932.  
  2933. #ifdef CK_TTGWSIZ
  2934.     if (paging < 0)                     /* /[NO]PAGE not given */
  2935.       paging = xaskmore;                /* so use prevailing */
  2936. #endif /* CK_TTGWSIZ */
  2937.  
  2938.     lines = 0;
  2939.     if (x_hdg > 0) {
  2940.         printf("Purging %s, keeping %d...%s\n",
  2941.                s,
  2942.                tokeep,
  2943.                simulate ? " (SIMULATION)" : "");
  2944.         lines += 2;
  2945.     }
  2946.     flags = ZX_FILONLY;
  2947.     if (recursive) flags |= ZX_RECURSE;
  2948.     n = nzxpand(line,flags);            /* Get list of backup files */
  2949.     if (tokeep < 1) {                   /* Deleting all of them... */
  2950.         for (i = 0; i < n; i++) {
  2951.             if (fs) if (fileselect(mtchs[i],
  2952.                                    pu_aft,pu_bef,pu_naf,pu_nbf,
  2953.                                    minsize,maxsize,0,8,pxlist) < 1) {
  2954.                 if (listing > 0) {
  2955.                     printf(" %s (SKIPPED)\n",mtchs[i]);
  2956. #ifdef CK_TTGWSIZ
  2957.                     if (paging)
  2958.                       if (++lines > cmd_rows - 3) {
  2959.                           if (!askmore()) goto xpurge; else lines = 0;
  2960.                       }
  2961. #endif /* CK_TTGWSIZ */
  2962.                 }
  2963.                 continue;
  2964.             }
  2965.             if (asking) {
  2966.                 int x;
  2967.                 ckmakmsg(tmpbuf,TMPBUFSIZ," Delete ",mtchs[i],"?",NULL);
  2968.                 x = getyesno(tmpbuf,1);
  2969.                 switch (x) {
  2970.                   case 0: continue;
  2971.                   case 1: break;
  2972.                   case 2: goto xpurge;
  2973.                 }
  2974.             }
  2975.             x = deleting ? zdelet(mtchs[i]) : 0;
  2976.             if (x > -1) {
  2977.                 if (listing)
  2978.                   printf(" %s (%s)\n", mtchs[i],deleting ? "OK" : "SELECTED");
  2979.                 count++;
  2980.             } else {
  2981.                 errors++;
  2982.                 if (listing)
  2983.                   printf(" %s (FAILED)\n", mtchs[i]);
  2984.             }
  2985. #ifdef CK_TTGWSIZ
  2986.             if (listing && paging)
  2987.               if (++lines > cmd_rows - 3) {
  2988.                   if (!askmore()) goto xpurge; else lines = 0;
  2989.               }
  2990. #endif /* CK_TTGWSIZ */
  2991.         }
  2992.         goto xpurge;
  2993.     }
  2994.     if (n < tokeep) {                   /* Not deleting any */
  2995.         count = 0;
  2996.         if (listing)
  2997.           printf(" Matches = %d: Not enough to purge.\n",n);
  2998.         goto xpurge;
  2999.     }
  3000.  
  3001.     /* General case - delete some but not others */
  3002.  
  3003.     sh_sort(mtchs,NULL,n,0,0,filecase); /* Alphabetize the list (ESSENTIAL) */
  3004.  
  3005.     g = 0;                              /* Start of current group */
  3006.     for (i = 0; i < n; i++) {           /* Go thru sorted file list */
  3007.         x = znext(namebuf);             /* Get next file */
  3008.         if (x < 1 || !namebuf[0] || i == n - 1) /* No more? */
  3009.           done = 1;                     /* NOTE: 'done' must be 0 or 1 only */
  3010.         if (fs) if (fileselect(namebuf,
  3011.                                pu_aft,pu_bef,pu_naf,pu_nbf,
  3012.                                minsize,maxsize,0,8,pxlist) < 1) {
  3013.             if (listing > 0) {
  3014.                 printf(" %s (SKIPPED)\n",namebuf);
  3015.                 if (++lines > cmd_rows - 3)
  3016.                   if (!askmore()) goto xpurge; else lines = 0;
  3017.             }
  3018.             continue;
  3019.         }
  3020.         if (x > 0)
  3021.           if ((m = bkupnum(namebuf,&z)) < 0) /* This file's backup number. */
  3022.             continue;
  3023.         for (j = 0; j < tokeep; j++) {  /* Insert in list. */
  3024.             if (m > xx[j]) {
  3025.                 for (k = tokeep - 1; k > j; k--)
  3026.                   xx[k] = xx[k-1];
  3027.                 xx[j] = m;
  3028.                 break;
  3029.             }
  3030.         }
  3031.         /* New group? */
  3032.         if (done || (i > 0 && ckstrcmp(namebuf,basebuf,z,1))) {
  3033.             if (i + done - g > tokeep) { /* Do we have enough to purge? */
  3034.                 min = xx[tokeep-1];     /* Yes, lowest backup number to keep */
  3035.                 debug(F111,"dopurge group",basebuf,min);
  3036.                 for (j = g; j < i + done; j++) { /* Go through this group */
  3037.                     x = bkupnum(mtchs[j],&z);    /* Get file backup number */
  3038.                     if (x > 0 && x < min) {      /* Below minimum? */
  3039.                         x = deleting ? zdelet(mtchs[j]) : 0;
  3040.                         if (x < 0) errors++;
  3041.                         if (listing)
  3042.                           printf(" %s (%s)\n",
  3043.                                  mtchs[j],
  3044.                                  ((x < 0) ? "ERROR" :
  3045.                                   (deleting ? "DELETED" : "SELECTED"))
  3046.                                  );
  3047.                         count++;
  3048.                     } else if (listing) /* Not below minimum - keep this one */
  3049.                       printf(" %s (KEPT)\n",mtchs[j]);
  3050. #ifdef CK_TTGWSIZ
  3051.                     if (listing && paging)
  3052.                       if (++lines > cmd_rows - 3) {
  3053.                           if (!askmore()) goto xpurge; else lines = 0;
  3054.                       }
  3055. #endif /* CK_TTGWSIZ */
  3056.                 }
  3057.             } else if (listing && paging) { /* Not enough to purge */
  3058.                 printf(" %s.~*~ (KEPT)\n",basebuf);
  3059. #ifdef CK_TTGWSIZ
  3060.                 if (++lines > cmd_rows - 3) {
  3061.                     if (!askmore()) goto xpurge; else lines = 0;
  3062.                 }
  3063. #endif /* CK_TTGWSIZ */
  3064.             }
  3065.             for (j = 0; j < tokeep; j++) /* Clear the backup number list */
  3066.               xx[j] = 0;
  3067.             g = i;                      /* Reset the group pointer */
  3068.         }
  3069.         if (done)                       /* No more files, done. */
  3070.           break;
  3071.         strncpy(basebuf,namebuf,z);     /* Set basename of this file */
  3072.         basebuf[z] = NUL;
  3073.     }
  3074.   xpurge:                               /* Common exit point */
  3075.     if (g_matchdot > -1) {
  3076.         matchdot = g_matchdot;          /* Restore these... */
  3077.         g_matchdot = -1;
  3078.     }
  3079.     if (rc < 0) return(rc);             /* Parse error */
  3080.     if (x_hdg)
  3081.       printf("Files purged: %d%s\n",
  3082.              count,
  3083.              deleting ? "" : " (not really)"
  3084.              );
  3085.     return(success = count > 0 ? 1 : (errors > 0) ? 0 : 1);
  3086. }
  3087. #endif /* CKPURGE */
  3088.  
  3089. #ifndef NOXFER
  3090. #ifndef NOLOCAL
  3091. int
  3092. doxdis(which) int which; {        /* 1 = Kermit, 2 = FTP */
  3093.     extern int nolocal;
  3094.     int x, y = 0, z;
  3095. #ifdef NEWFTP
  3096.     extern int ftp_dis;
  3097. #endif /* NEWFTP */
  3098.  
  3099. #ifdef COMMENT
  3100.     char *s;
  3101. #endif /* COMMENT */
  3102.  
  3103.     if ((x = cmkey(fdtab,nfdtab,"file transfer display style","",
  3104.                    xxstring)) < 0)
  3105.       return(x);
  3106. #ifdef CK_PCT_BAR
  3107.     if ((y = cmkey(fdftab,2,"","thermometer",xxstring)) < 0)
  3108.       return(y);
  3109. #endif /* CK_PCT_BAR */
  3110.     if ((z = cmcfm()) < 0) return(z);
  3111. #ifdef CK_CURSES
  3112.     if (x == XYFD_C) {                  /* FULLSCREEN */
  3113. #ifdef COMMENT
  3114. #ifndef MYCURSES
  3115.         extern char * trmbuf;           /* Real curses */
  3116.         int z;
  3117. #endif /* MYCURSES */
  3118. #endif /* COMMENT */
  3119.  
  3120.         if (nolocal)                    /* Nothing to do in this case */
  3121.       return(success = 1);
  3122.  
  3123. #ifdef COMMENT
  3124. #ifndef MYCURSES
  3125. #ifndef VMS
  3126.         s = getenv("TERM");
  3127.         debug(F110,"doxdis TERM",s,0);
  3128.         if (!s) s = "";
  3129.         fxdinit(x);
  3130.         if (*s && trmbuf) {             /* Don't call tgetent */
  3131.             z = tgetent(trmbuf,s);      /* if trmbuf not allocated */
  3132.             debug(F111,"doxdis tgetent",s,z);
  3133.         } else {
  3134.             z = 0;
  3135.             debug(F110,"doxdis tgetent skipped",s,0);
  3136.         }
  3137.         if (z < 1) {
  3138.             printf("Sorry, terminal type unknown: \"%s\"\n",s);
  3139.             return(success = 0);
  3140.         }
  3141. #endif /* VMS */
  3142. #endif /* MYCURSES */
  3143. #else
  3144.         fxdinit(x);
  3145. #endif /* COMMENT */
  3146.  
  3147. #ifdef CK_PCT_BAR
  3148.         thermometer = y;
  3149. #endif /* CK_PCT_BAR */
  3150.  
  3151.         line[0] = '\0';                 /* (What's this for?) */
  3152.     }
  3153. #endif /* CK_CURSES */
  3154.     if (which == 1)            /* It's OK. */
  3155.       fdispla = x;
  3156. #ifdef NEWFTP
  3157.     else if (which == 2)
  3158.       ftp_dis = x;
  3159. #endif /* NEWFTP */
  3160.     return(success = 1);
  3161. }
  3162. #endif /* NOLOCAL */
  3163. #endif /* NOXFER */
  3164.  
  3165. int
  3166. setfil(rmsflg) int rmsflg; {
  3167. #ifdef COMMENT
  3168.     extern int en_del;
  3169. #endif /* COMMENT */
  3170. #ifndef NOXFER
  3171.     if (rmsflg) {
  3172.         if ((y = cmkey(rfiltab,nrfilp,"Remote file parameter","",
  3173.                        xxstring)) < 0) {
  3174.             if (y == -3) {
  3175.                 printf("?Remote file parameter required\n");
  3176.                 return(-9);
  3177.             } else return(y);
  3178.         }
  3179.     } else {
  3180. #endif /* NOXFER */
  3181.         if ((y = cmkey(filtab,nfilp,"File parameter","",xxstring)) < 0)
  3182.           return(y);
  3183. #ifndef NOXFER
  3184.     }
  3185. #endif /* NOXFER */
  3186.     switch (y) {
  3187. #ifdef COMMENT                          /* Not needed */
  3188.       case XYFILB:                      /* Blocksize */
  3189.         if ((y = cmnum("file block size",ckitoa(DBLKSIZ),10,&z,xxstring)) < 0)
  3190.           return(y);
  3191.         if ((x = cmcfm()) < 0) return(x);
  3192.         if (rmsflg) {
  3193.             sstate = setgen('S', "311", ckitoa(z), "");
  3194.             return((int) sstate);
  3195.         } else {
  3196.             fblksiz = z;
  3197.             return(success = 1);
  3198.         }
  3199. #endif /* COMMENT */
  3200.  
  3201. #ifndef NOXFER
  3202.       case XYFILS:                      /* Byte size */
  3203.         if ((y = cmnum("file byte size (7 or 8)","8",10,&z,xxstring)) < 0)
  3204.           return(y);
  3205.         if (z != 7 && z != 8) {
  3206.             printf("\n?The choices are 7 and 8\n");
  3207.             return(0);
  3208.         }
  3209.         if ((y = cmcfm()) < 0) return(y);
  3210.         if (z == 7) fmask = 0177;
  3211.         else if (z == 8) fmask = 0377;
  3212.         return(success = 1);
  3213.  
  3214. #ifndef NOCSETS
  3215.       case XYFILC: {                    /* Character set */
  3216.           char * csetname = NULL;
  3217.           extern int
  3218.             r_cset, s_cset, afcset[];   /* SEND CHARACTER-SET AUTO or MANUAL */
  3219.  
  3220.           struct FDB kw, fl;
  3221.           cmfdbi(&kw,                   /* First FDB - command switches */
  3222.                  _CMKEY,                /* fcode */
  3223.                  rmsflg ? "server character-set name" : "",  /* help */
  3224.                  "",                    /* default */
  3225.                  "",                    /* addtl string data */
  3226.                  nfilc,                 /* addtl numeric data 1: tbl size */
  3227.                  0,                     /* addtl numeric data 2: 0 = keyword */
  3228.                  xxstring,              /* Processing function */
  3229.                  fcstab,                /* Keyword table */
  3230.                  rmsflg ? &fl : NULL    /* Pointer to next FDB */
  3231.            );
  3232.           cmfdbi(&fl,                   /* Anything that doesn't match */
  3233.                  _CMFLD,                /* fcode */
  3234.                  "",                    /* hlpmsg */
  3235.                  "",                    /* default */
  3236.                  "",                    /* addtl string data */
  3237.                  0,                     /* addtl numeric data 1 */
  3238.                  0,                     /* addtl numeric data 2 */
  3239.                  xxstring,
  3240.                  NULL,
  3241.                  NULL
  3242.                  );
  3243.           if ((x = cmfdb(&kw)) < 0)
  3244.             return(x);
  3245.           if (cmresult.fcode == _CMKEY) {
  3246.               x = cmresult.nresult;
  3247.               csetname = fcsinfo[x].keyword;
  3248.           } else {
  3249.               ckstrncpy(line,cmresult.sresult,LINBUFSIZ);
  3250.               csetname = line;
  3251.           }
  3252.           if ((z = cmcfm()) < 0) return(z);
  3253.           if (rmsflg) {
  3254.               sstate = setgen('S', "320", csetname, "");
  3255.               return((int) sstate);
  3256.           }
  3257.           fcharset = x;
  3258.           if (s_cset == XMODE_A)        /* If SEND CHARACTER-SET is AUTO */
  3259.             if (x > -1 && x <= MAXFCSETS)
  3260.               if (afcset[x] > -1 && afcset[x] <= MAXTCSETS)
  3261.                 tcharset = afcset[x]; /* Pick corresponding xfer charset */
  3262.           setxlatype(tcharset,fcharset); /* Translation type */
  3263.           /* If I say SET FILE CHARACTER-SET blah, I want to be blah! */
  3264.           r_cset = XMODE_M;             /* Don't switch incoming set! */
  3265.           x = fcsinfo[fcharset].size;   /* Also set default x-bit charset */
  3266.           if (x == 128)                 /* 7-bit... */
  3267.             dcset7 = fcharset;
  3268.           else if (x == 256)            /* 8-bit... */
  3269.             dcset8 = fcharset;
  3270.           return(success = 1);
  3271.       }
  3272. #endif /* NOCSETS */
  3273.  
  3274. #ifndef NOLOCAL
  3275.       case XYFILD:                      /* Display */
  3276.         return(doxdis(1));        /* 1 == kermit */
  3277. #endif /* NOLOCAL */
  3278. #endif /* NOXFER */
  3279.  
  3280.       case XYFILA:                      /* End-of-line */
  3281. #ifdef NLCHAR
  3282.         s = "";
  3283.         if (NLCHAR == 015)
  3284.           s = "cr";
  3285.         else if (NLCHAR == 012)
  3286.           s = "lf";
  3287.         if ((x = cmkey(eoltab, neoltab,
  3288.                        "local text-file line terminator",s,xxstring)) < 0)
  3289.           return(x);
  3290. #else
  3291.         if ((x = cmkey(eoltab, neoltab,
  3292.                        "local text-file line terminator","crlf",xxstring)) < 0)
  3293.           return(x);
  3294. #endif /* NLCHAR */
  3295.         if ((z = cmcfm()) < 0) return(z);
  3296.         feol = (CHAR) x;
  3297.         return(success = 1);
  3298.  
  3299. #ifndef NOXFER
  3300.       case XYFILN:                      /* Names */
  3301.         if ((x = cmkey(fntab,nfntab,"how to handle filenames","converted",
  3302.                        xxstring)) < 0)
  3303.           return(x);
  3304.         if ((z = cmcfm()) < 0) return(z);
  3305.         if (rmsflg) {
  3306.             sstate = setgen('S', "301", ckitoa(1 - x), "");
  3307.             return((int) sstate);
  3308.         } else {
  3309.             ptab[protocol].fncn = x;    /* Set structure */
  3310.             fncnv = x;                  /* Set variable */
  3311.             f_save = x;                 /* And set "permanent" variable */
  3312.             return(success = 1);
  3313.         }
  3314.  
  3315.       case XYFILR:                      /* Record length */
  3316.         if ((y = cmnum("file record length",
  3317.                        ckitoa(DLRECL),10,&z,xxstring)) < 0)
  3318.           return(y);
  3319.         if ((x = cmcfm()) < 0) return(x);
  3320.         if (rmsflg) {
  3321.             sstate = setgen('S', "312", ckitoa(z), "");
  3322.             return((int) sstate);
  3323.         } else {
  3324.             frecl = z;
  3325.             return(success = 1);
  3326.         }
  3327.  
  3328. #ifdef COMMENT
  3329.       case XYFILO:                      /* Organization */
  3330.         if ((x = cmkey(forgtab,nforg,"file organization","sequential",
  3331.                        xxstring)) < 0)
  3332.           return(x);
  3333.         if ((y = cmcfm()) < 0) return(y);
  3334.         if (rmsflg) {
  3335.             sstate = setgen('S', "314", ckitoa(x), "");
  3336.             return((int) sstate);
  3337.         } else {
  3338.             forg = x;
  3339.             return(success = 1);
  3340.         }
  3341. #endif /* COMMENT */
  3342.  
  3343. #ifdef COMMENT                          /* Not needed */
  3344.       case XYFILF:                      /* Format */
  3345.         if ((x = cmkey(frectab,nfrec,"file record format","stream",
  3346.                        xxstring)) < 0)
  3347.           return(x);
  3348.         if ((y = cmcfm()) < 0) return(y);
  3349.         if (rmsflg) {
  3350.             sstate = setgen('S', "313", ckitoa(x), "");
  3351.             return((int) sstate);
  3352.         } else {
  3353.             frecfm = x;
  3354.             return(success = 1);
  3355.         }
  3356. #endif /* COMMENT */
  3357.  
  3358. #ifdef COMMENT
  3359.       case XYFILP:                      /* Printer carriage control */
  3360.         if ((x = cmkey(fcctab,nfcc,"file carriage control","newline",
  3361.                        xxstring)) < 0)
  3362.           return(x);
  3363.         if ((y = cmcfm()) < 0) return(y);
  3364.         if (rmsflg) {
  3365.             sstate = setgen('S', "315", ckitoa(x), "");
  3366.             return((int) sstate);
  3367.         } else {
  3368.             fcctrl = x;
  3369.             return(success = 1);
  3370.         }
  3371. #endif /* COMMENT */
  3372. #endif /* NOXFER */
  3373.  
  3374.       case XYFILT:                      /* Type */
  3375.         if ((x = cmkey(rmsflg ? rfttab  : fttab,
  3376.                        rmsflg ? nrfttyp : nfttyp,
  3377.                        "type of file transfer","text",xxstring)) < 0)
  3378.           return(x);
  3379.  
  3380. #ifdef VMS
  3381.         /* Allow VMS users to choose record format for binary files */
  3382.         if ((x == XYFT_B) && (rmsflg == 0)) {
  3383.             if ((x = cmkey(fbtab,nfbtyp,"VMS record format","fixed",
  3384.                            xxstring)) < 0)
  3385.               return(x);
  3386.         }
  3387. #endif /* VMS */
  3388.         if ((y = cmcfm()) < 0) return(y);
  3389.         binary = x;
  3390.         b_save = x;
  3391. #ifdef MAC
  3392.         (void) mac_setfildflg(binary);
  3393. #endif /* MAC */
  3394. #ifndef NOXFER
  3395.         if (rmsflg) {
  3396.             /* Allow for LABELED in VMS & OS/2 */
  3397.             sstate = setgen('S', "300", ckitoa(x), "");
  3398.             return((int) sstate);
  3399.         } else {
  3400. #endif /* NOXFER */
  3401.             return(success = 1);
  3402. #ifndef NOXFER
  3403.         }
  3404. #endif /* NOXFER */
  3405.  
  3406. #ifndef NOXFER
  3407.       case XYFILX:                      /* Collision Action */
  3408.         if ((x = cmkey(colxtab,ncolx,"Filename collision action","backup",
  3409.                        xxstring)) < 0)
  3410.           return(x);
  3411.         if ((y = cmcfm()) < 0) return(y);
  3412. #ifdef CK_LOGIN
  3413.         if (isguest) {
  3414.             /* Don't let guests change existing files */
  3415.             printf("?This command not valid for guests\n");
  3416.             return(-9);
  3417.         }
  3418. #endif /* CK_LOGIN */
  3419. #ifdef COMMENT
  3420.         /* Not appropriate - DISABLE DELETE only refers to server */
  3421.         if ((x == XYFX_X || x == XYFX_B || x == XYFX_U || x == XYFX_A) &&
  3422.             (!ENABLED(en_del))) {
  3423.             printf("?Sorry, file deletion is disabled.\n");
  3424.             return(-9);
  3425.         }
  3426. #endif /* COMMENT */
  3427.         fncact = x;
  3428.         ptab[protocol].fnca = x;
  3429.         if (rmsflg) {
  3430.             sstate = setgen('S', "302", ckitoa(fncact), "");
  3431.             return((int) sstate);
  3432.         } else {
  3433.             if (fncact == XYFX_R) ckwarn = 1; /* FILE WARNING implications */
  3434.             if (fncact == XYFX_X) ckwarn = 0; /* ... */
  3435.             return(success = 1);
  3436.         }
  3437.  
  3438.       case XYFILW:                      /* Warning/Write-Protect */
  3439.         if ((x = seton(&ckwarn)) < 0) return(x);
  3440.         if (ckwarn)
  3441.           fncact = XYFX_R;
  3442.         else
  3443.           fncact = XYFX_X;
  3444.         return(success = 1);
  3445.  
  3446. #ifdef CK_LABELED
  3447.       case XYFILL:                      /* LABELED FILE parameters */
  3448.         if ((x = cmkey(lbltab,nlblp,"Labeled file feature","",
  3449.                        xxstring)) < 0)
  3450.           return(x);
  3451.         if ((success = seton(&y)) < 0)
  3452.           return(success);
  3453.         if (y)                          /* Set or reset the selected bit */
  3454.           lf_opts |= x;                 /* in the options bitmask. */
  3455.         else
  3456.           lf_opts &= ~x;
  3457.         return(success);
  3458. #endif /* CK_LABELED */
  3459.  
  3460.       case XYFILI: {                    /* INCOMPLETE */
  3461.           extern struct keytab ifdatab[];
  3462.           extern int keep;
  3463.           if ((y = cmkey(ifdatab,3,"","auto",xxstring)) < 0) return(y);
  3464.           if ((x = cmcfm()) < 0) return(x);
  3465.           if (rmsflg) {
  3466.               sstate = setgen('S',
  3467.                               "310",
  3468.                               y == 0 ? "0" : (y == 1 ? "1" : "2"),
  3469.                               ""
  3470.                               );
  3471.               return((int) sstate);
  3472.           } else {
  3473.               keep = y;
  3474.               return(success = 1);
  3475.           }
  3476.       }
  3477.  
  3478. #ifdef CK_TMPDIR
  3479.       case XYFILG: {                    /* Download directory */
  3480.           int x;
  3481.           char *s;
  3482. #ifdef ZFNQFP
  3483.           struct zfnfp * fnp;
  3484. #endif /* ZFNQFP */
  3485. #ifdef MAC
  3486.           char temp[34];
  3487. #endif /* MAC */
  3488.  
  3489. #ifdef GEMDOS
  3490.           if ((x = cmdir("Name of local directory, or carriage return",
  3491.                          "",&s,
  3492.                          NULL)) < 0 ) {
  3493.               if (x != -3)
  3494.                 return(x);
  3495.           }
  3496. #else
  3497. #ifdef OS2
  3498.           if ((x = cmdir("Name of PC disk and/or directory,\n\
  3499.        or press the Enter key to use current directory",
  3500.                          "",&s,xxstring)) < 0 ) {
  3501.               if (x != -3)
  3502.                 return(x);
  3503.           }
  3504. #else
  3505. #ifdef MAC
  3506.           x = ckstrncpy(temp,zhome(),32);
  3507.           if (x > 0) if (temp[x-1] != ':') { temp[x] = ':'; temp[x+1] = NUL; }
  3508.           if ((x = cmtxt("Name of Macintosh volume and/or folder,\n\
  3509.  or press the Return key for the desktop on the boot disk",
  3510.                          temp,&s, xxstring)) < 0 )
  3511.             return(x);
  3512. #else
  3513.           if ((x = cmdir("Name of local directory, or carriage return",
  3514.                          "", &s, xxstring)) < 0 ) {
  3515.               if (x != -3)
  3516.                 return(x);
  3517.           }
  3518. #endif /* MAC */
  3519. #endif /* OS2 */
  3520. #endif /* GEMDOS */
  3521.           debug(F110,"download dir",s,0);
  3522.  
  3523. #ifndef MAC
  3524.           if (x == 2) {
  3525.               printf("?Wildcards not allowed in directory name\n");
  3526.               return(-9);
  3527.           }
  3528. #endif /* MAC */
  3529.  
  3530. #ifdef ZFNQFP
  3531.           if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
  3532.               if (fnp->fpath)
  3533.                 if ((int) strlen(fnp->fpath) > 0)
  3534.                   s = fnp->fpath;
  3535.           }
  3536.           debug(F110,"download zfnqfp",s,0);
  3537. #endif /* ZFNQFP */
  3538.  
  3539.           ckstrncpy(line,s,LINBUFSIZ);  /* Make a safe copy */
  3540. #ifndef MAC
  3541.           if ((x = cmcfm()) < 0)        /* Get confirmation */
  3542.             return(x);
  3543. #endif /* MAC */
  3544.  
  3545. #ifdef CK_LOGIN
  3546.         if (isguest) {
  3547.             /* Don't let guests change existing files */
  3548.             printf("?This command not valid for guests\n");
  3549.             return(-9);
  3550.         }
  3551. #endif /* CK_LOGIN */
  3552.           x = strlen(s);
  3553.  
  3554.           if (x) {
  3555. #ifdef datageneral            /* AOS/VS */
  3556.               if (s[x-1] == ':')        /* homdir ends in colon, */
  3557.                 s[x-1] = NUL;           /* and "dir" doesn't like that... */
  3558. #else
  3559. #ifdef OS2ORUNIX            /* Unix or K-95... */
  3560.           if ((x < (LINBUFSIZ - 2)) && /* Add trailing dirsep */
  3561.           (s[x-1] != '/')) {    /* if none present.  */
  3562.           s[x] = '/';        /* Note that Windows path has */
  3563.           s[x+1] = NUL;        /* been canonicalized to forward */
  3564.           }                        /* slashes at this point. */
  3565. #endif /* OS2ORUNIX */
  3566. #endif /* datageneral */
  3567.               makestr(&dldir,s);
  3568.           } else
  3569.             makestr(&dldir,NULL);       /* dldir is NULL when not assigned */
  3570.  
  3571.           return(success = 1);
  3572.       }
  3573. #endif /* CK_TMPDIR */
  3574.       case XYFILY:
  3575.         return(setdest());
  3576. #endif /* NOXFER */
  3577.  
  3578. #ifdef CK_CTRLZ
  3579.       case XYFILV: {                    /* EOF */
  3580.           extern int eofmethod;
  3581.           if ((x = cmkey(eoftab,3,"end-of-file detection method","",
  3582.                          xxstring)) < 0)
  3583.             return(x);
  3584.           if ((y = cmcfm()) < 0)
  3585.             return(y);
  3586.           eofmethod = x;
  3587.           return(success = 1);
  3588.       }
  3589. #endif /* CK_CTRLZ */
  3590.  
  3591. #ifndef NOXFER
  3592. #ifdef UNIX
  3593.       case XYFILH: {                    /* OUTPUT */
  3594.           extern int zofbuffer, zobufsize, zofblock;
  3595. #ifdef DYNAMIC
  3596.           extern char * zoutbuffer;
  3597. #endif /* DYNAMIC */
  3598.  
  3599.           if ((x = cmkey(zoftab,nzoftab,"output file writing method","",
  3600.                          xxstring)) < 0)
  3601.             return(x);
  3602.           if (x == ZOF_BUF || x == ZOF_NBUF) {
  3603.               if ((y = cmnum("output buffer size","32768",10,&z,xxstring)) < 0)
  3604.                 return(y);
  3605.               if (z < 1) {
  3606.                   printf("?Bad size - %d\n", z);
  3607.                   return(-9);
  3608.               }
  3609.           }
  3610.           if ((y = cmcfm()) < 0) return(y);
  3611.           switch (x) {
  3612.             case ZOF_BUF:
  3613.             case ZOF_NBUF:
  3614.               zofbuffer = (x == ZOF_BUF);
  3615.               zobufsize = z;
  3616.               break;
  3617.             case ZOF_BLK:
  3618.             case ZOF_NBLK:
  3619.               zofblock = (x == ZOF_BLK);
  3620.               break;
  3621.           }
  3622. #ifdef DYNAMIC
  3623.           if (zoutbuffer) free(zoutbuffer);
  3624.           if (!(zoutbuffer = (char *)malloc(z))) {
  3625.               printf("MEMORY ALLOCATION ERROR - FATAL\n");
  3626.               doexit(BAD_EXIT,-1);
  3627.           } else
  3628.             zobufsize = z;
  3629. #else
  3630.           if (z <= OBUFSIZE) {
  3631.               zobufsize = z;
  3632.           } else {
  3633.               printf("?Sorry, %d is too big - %d is the maximum\n",z,OBUFSIZE);
  3634.               return(-9);
  3635.           }
  3636. #endif /* DYNAMIC */
  3637.           return(success = 1);
  3638.       }
  3639. #endif /* UNIX */
  3640.  
  3641. #ifdef PATTERNS
  3642.       case XYFIBP:                      /* BINARY-PATTERN */
  3643.       case XYFITP: {                    /* TEXT-PATTERN */
  3644.           char * tmp[FTPATTERNS];
  3645.           int i, n = 0;
  3646.           while (n < FTPATTERNS) {
  3647.               tmp[n] = NULL;
  3648.               if ((x = cmfld("Pattern","",&s,xxstring)) < 0)
  3649.                 break;
  3650.               ckstrncpy(line,s,LINBUFSIZ);
  3651.               s = brstrip(line);
  3652.               makestr(&(tmp[n++]),s);
  3653.           }
  3654.           if (x == -3) x = cmcfm();
  3655.           for (i = 0; i <= n; i++) {
  3656.               if (x > -1) {
  3657.                   if (y == XYFIBP)
  3658.                     makestr(&(binpatterns[i]),tmp[i]);
  3659.                   else
  3660.                     makestr(&(txtpatterns[i]),tmp[i]);
  3661.               }
  3662.               free(tmp[i]);
  3663.           }
  3664.           if (y == XYFIBP)              /* Null-terminate the list */
  3665.             makestr(&(binpatterns[i]),NULL);
  3666.           else
  3667.             makestr(&(txtpatterns[i]),NULL);
  3668.           return(x);
  3669.       }
  3670.  
  3671.       case XYFIPA:                      /* PATTERNS */
  3672.         if ((x = setonaut(&patterns)) < 0)
  3673.           return(x);
  3674.         return(success = 1);
  3675. #endif /* PATTERNS */
  3676. #endif /* NOXFER */
  3677.  
  3678. #ifdef UNICODE
  3679.       case XYFILU: {                    /* UCS */
  3680.           extern int ucsorder, ucsbom, byteorder;
  3681.           if ((x = cmkey(ucstab,nucstab,"","",xxstring)) < 0)
  3682.             return(x);
  3683.           switch (x) {
  3684.             case UCS_BYT:
  3685.               if ((y = cmkey(botab,nbotab,
  3686.                              "Byte order",
  3687.                              byteorder ? "little-endian" : "big-endian",
  3688.                              xxstring
  3689.                              )
  3690.                    ) < 0)
  3691.                 return(y);
  3692.               if ((x = cmcfm()) < 0)
  3693.                 return(x);
  3694.               ucsorder = y;
  3695.               return(success = 1);
  3696.             case UCS_BOM:
  3697.               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
  3698.                 return(y);
  3699.               if ((x = cmcfm()) < 0)
  3700.                 return(x);
  3701.               ucsbom = y;
  3702.               return(success = 1);
  3703.             default:
  3704.               return(-2);
  3705.           }
  3706.       }
  3707. #endif /* UNICODE */
  3708.  
  3709. #ifndef datageneral
  3710.       case XYF_INSP: {                  /* SCAN (INSPECTION) */
  3711.           extern int filepeek, nscanfile;
  3712.           if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
  3713.             return(x);
  3714.           if (y) {
  3715.               if ((y = cmnum("How much to scan",ckitoa(SCANFILEBUF),
  3716.                              10,&z,xxstring)) < 0)
  3717.                 return(y);
  3718.           }
  3719.           if ((y = cmcfm()) < 0)
  3720.             return(y);
  3721. #ifdef VMS
  3722.           filepeek = 0;
  3723.           nscanfile = 0;
  3724.           return(success = 0);
  3725. #else
  3726.           filepeek = x;
  3727.           nscanfile = z;
  3728.           return(success = 1);
  3729. #endif /* VMS */
  3730.       }
  3731. #endif /* datageneral */
  3732.  
  3733.       case XYF_DFLT:
  3734.         y = 0;
  3735. #ifndef NOCSETS
  3736.         if ((y = cmkey(fdfltab,nfdflt,"","",xxstring)) < 0)
  3737.           return(y);
  3738.         if (y == 7 || y == 8) {
  3739.             if (y == 7)
  3740.               s = fcsinfo[dcset7].keyword;
  3741.             else
  3742.               s = fcsinfo[dcset8].keyword;
  3743.             if ((x = cmkey(fcstab,nfilc,"character-set",s,xxstring)) < 0)
  3744.               return(x);
  3745.         }
  3746.         ckstrncpy(line,fcsinfo[x].keyword,LINBUFSIZ);
  3747.         s = line;
  3748. #endif /* NOCSETS */
  3749.         if ((z = cmcfm()) < 0)
  3750.           return(z);
  3751.         switch (y) {
  3752. #ifndef NOCSETS
  3753.           case 7:
  3754.             if (fcsinfo[x].size != 128) {
  3755.                 printf("%s - Not a 7-bit set\n",s);
  3756.                 return(-9);
  3757.             }
  3758.             dcset7 = x;
  3759.             break;
  3760.           case 8:
  3761.             if (fcsinfo[x].size != 256) {
  3762.                 printf("%s - Not an 8-bit set\n",s);
  3763.                 return(-9);
  3764.             }
  3765.             dcset8 = x;
  3766.             break;
  3767. #endif /* NOCSETS */
  3768.           default:
  3769.             return(-2);
  3770.         }
  3771.         return(success = 1);
  3772.  
  3773. #ifndef NOXFER
  3774.       case 9997:                        /* FASTLOOKUPS */
  3775.         return(success = seton(&stathack));
  3776. #endif /* NOXFER */
  3777.  
  3778. #ifdef UNIX
  3779. #ifdef DYNAMIC
  3780.       case XYF_LSIZ: {                  /* LISTSIZE */
  3781.           int zz;
  3782.           y = cmnum("Maximum number of filenames","",10,&x,xxstring);
  3783.           if ((x = setnum(&zz,x,y,-1)) < 0)
  3784.             return(x);
  3785.           if (zsetfil(zz,3) < 0) {
  3786.               printf("?Memory allocation failure\n");
  3787.               return(-9);
  3788.           }
  3789.           return(success = 1);
  3790.       }
  3791.       case XYF_SSPA: {                  /* STRINGSPACE */
  3792.           int zz;
  3793.           y = cmnum("Number of characters for filename list",
  3794.                     "",10,&x,xxstring);
  3795.           if ((x = setnum(&zz,x,y,-1)) < 0)
  3796.             return(x);
  3797.           if (zsetfil(zz,1) < 0) {
  3798.               printf("?Memory allocation failure\n");
  3799.               return(-9);
  3800.           }
  3801.           return(success = 1);
  3802.       }
  3803.  
  3804. #endif /* DYNAMIC */
  3805. #endif /* UNIX */
  3806.  
  3807.       default:
  3808.         printf("?unexpected file parameter\n");
  3809.         return(-2);
  3810.     }
  3811. }
  3812.  
  3813. #ifdef UNIX
  3814. #ifndef NOPUTENV
  3815. #ifdef BIGBUFOK
  3816. #define NPUTENVS 4096
  3817. #else
  3818. #define NPUTENVS 128
  3819. #endif    /* BIGBUFOK */
  3820. /* environment variables must be static, not automatic */
  3821.  
  3822. static char * putenvs[NPUTENVS];    /* Array of environment var strings */
  3823. static int nputenvs = -1;        /* Pointer into array */
  3824. /*
  3825.   If anyone ever notices the limitation on the number of PUTENVs, the list
  3826.   can be made dynamic, we can recycle entries with the same name, etc.
  3827. */
  3828. int
  3829. doputenv(s1, s2) char * s1; char * s2; {
  3830.     char * s, * t = tmpbuf;        /* Create or alter environment var */
  3831.  
  3832.     if (nputenvs == -1) {        /* Table not used yet */
  3833.     int i;                /* Initialize the pointers */
  3834.     for (i = 0; i < NPUTENVS; i++)
  3835.       putenvs[i] = NULL;
  3836.     nputenvs = 0;
  3837.     }
  3838.     if (!s1) return(1);            /* Nothing to do */
  3839.     if (!*s1) return(1);        /* ditto */
  3840.  
  3841.     if (ckindex("=",s1,0,0,0)) {    /* Does the name contain an '='? */
  3842.     printf(                /* putenv() does not allow this. */
  3843.      /* This also catches the 'putenv name=value' case */
  3844.          "?PUTENV - Equal sign in variable name - 'help putenv' for info.\n");
  3845.         return(-9);
  3846.     }
  3847.     nputenvs++;                /* Point to next free string */
  3848.  
  3849.     debug(F111,"doputenv s1",s1,nputenvs);
  3850.     debug(F111,"doputenv s2",s2,nputenvs);
  3851.  
  3852.     if (nputenvs > NPUTENVS - 1) {    /* Notice the end */
  3853.     printf("?PUTENV - static buffer space exhausted\n");
  3854.     return(-9);
  3855.     }
  3856.     /* Quotes are not needed but we allow them for familiarity */
  3857.     /* but then we strip them, so syntax is same as for Unix shell */
  3858.  
  3859.     if (s2) {
  3860.     s2 = brstrip(s2);
  3861.     } else {
  3862.     s2 = (char *)"";
  3863.     }
  3864.     ckmakmsg(t,TMPBUFSIZ,s1,"=",s2,NULL);
  3865.     debug(F111,"doputenv",t,nputenvs);
  3866.     (VOID) makestr(&(putenvs[nputenvs]),t); /* Make a safe permananent copy */
  3867.     if (!putenvs[nputenvs]) {
  3868.     printf("?PUTENV - memory allocation failure\n");
  3869.     return(-9);
  3870.     }
  3871.     if (putenv(putenvs[nputenvs])) {
  3872.     printf("?PUTENV - %s\n",ck_errstr());
  3873.     return(-9);
  3874.     } else return(success = 1);
  3875. }
  3876. #endif    /* NOPUTENV */
  3877. #endif    /* UNIX */
  3878.  
  3879. int
  3880. settrmtyp() {
  3881. #ifdef OS2
  3882. #ifdef TNCODE
  3883.     extern int ttnum;                    /* Last Telnet Terminal Type sent */
  3884.     extern int ttnumend;                 /* Has end of list been found */
  3885. #endif /* TNCODE */
  3886.     if ((x = cmkey(ttyptab,nttyp,"","vt220",xxstring)) < 0)
  3887.       return(x);
  3888.     if ((y = cmcfm()) < 0)
  3889.       return(y);
  3890.     settermtype(x,1);
  3891. #ifdef TNCODE
  3892.     /* So we send the correct terminal name to the host if it asks for it */
  3893.     ttnum = -1;                         /* Last Telnet Terminal Type sent */
  3894.     ttnumend = 0;                       /* end of list not found */
  3895. #endif /* TNCODE */
  3896.     return(success = 1);
  3897. #else  /* Not OS2 */
  3898. #ifdef UNIX
  3899.     extern int fxd_inited;
  3900.     x = cmtxt("Terminal type name, case sensitive","",&s,NULL);
  3901. #ifdef NOPUTENV
  3902.     success = 1;
  3903. #else
  3904.     success = doputenv("TERM",s);    /* Set the TERM variable */
  3905. #ifdef CK_CURSES
  3906.     fxd_inited = 0;           /* Force reinitialization of curses database */
  3907.     (void)doxdis(0);             /* Re-initialize file transfer display */
  3908.     concb((char)escape);        /* Fix command terminal */
  3909. #endif    /* CK_CURSES */
  3910. #endif    /* NOPUTENV */
  3911.     return(success);
  3912. #else
  3913.     printf(
  3914. "\n Sorry, this version of C-Kermit does not support the SET TERMINAL TYPE\n");
  3915.     printf(
  3916. " command.  Type \"help set terminal\" for further information.\n");
  3917.     return(success = 0);
  3918. #endif    /* UNIX */
  3919. #endif /* OS2 */
  3920. }
  3921.  
  3922. #ifndef NOLOCAL
  3923. #ifdef OS2
  3924. /* MS-DOS KERMIT compatibility modes */
  3925. int
  3926. setmsk() {
  3927.     if ((y = cmkey(msktab,nmsk,"MS-DOS Kermit compatibility mode",
  3928.                     "keycodes",xxstring)) < 0) return(y);
  3929.  
  3930.     switch ( y ) {
  3931. #ifdef COMMENT
  3932.       case MSK_COLOR:
  3933.         return(seton(&mskcolors));
  3934. #endif /* COMMENT */
  3935.       case MSK_KEYS:
  3936.         return(seton(&mskkeys));
  3937.       case MSK_REN:
  3938.         return(seton(&mskrename));
  3939.       default:                          /* Shouldn't get here. */
  3940.         return(-2);
  3941.     }
  3942. }
  3943. #endif /* OS2 */
  3944.  
  3945. #ifdef CKTIDLE
  3946. static char iactbuf[132];
  3947.  
  3948. char *
  3949. getiact() {
  3950.     switch (tt_idleact) {
  3951.       case IDLE_RET:  return("return");
  3952.       case IDLE_EXIT: return("exit");
  3953.       case IDLE_HANG: return("hangup");
  3954. #ifdef TNCODE
  3955.       case IDLE_TNOP: return("Telnet NOP");
  3956.       case IDLE_TAYT: return("Telnet AYT");
  3957. #endif /* TNCODE */
  3958.  
  3959.       case IDLE_OUT: {
  3960.           int c, k, n;
  3961.           char * p, * q, * t;
  3962.           k = ckstrncpy(iactbuf,"output ",132);
  3963.           n = k;
  3964.           q = &iactbuf[k];
  3965.           p = tt_idlestr;
  3966.           if (!p) p = "";
  3967.           if (!*p) return("output NUL");
  3968.           while ((c = *p++) && n < 131) {
  3969.               c &= 0xff;
  3970.               if (c == '\\') {
  3971.                   if (n > 130) break;
  3972.                   *q++ = '\\';
  3973.                   *q++ = '\\';
  3974.                   *q = NUL;
  3975.                   n += 2;
  3976.               } else if ((c > 32 && c < 127) || c > 159) {
  3977.                   *q++ = c;
  3978.                   *q = NUL;
  3979.                   n++;
  3980.               } else {
  3981.                   if (n > (131 - 6))
  3982.                     break;
  3983.                   sprintf(q,"\\{%d}",c);
  3984.                   k = strlen(q);
  3985.                   q += k;
  3986.                   n += k;
  3987.                   *q = NUL;
  3988.               }
  3989.           }
  3990.           *q = NUL;
  3991. #ifdef OS2
  3992.           k = tt_cols[VTERM];
  3993. #else
  3994.           k = tt_cols;
  3995. #endif /* OS2 */
  3996.           if (n > k - 52) {
  3997.               n = k - 52;
  3998.               iactbuf[n-2] = '.';
  3999.               iactbuf[n-1] = '.';
  4000.               iactbuf[n] = NUL;
  4001.           }
  4002.           return(iactbuf);
  4003.       }
  4004.       default: return("unknown");
  4005.     }
  4006. }
  4007. #endif /* CKTIDLE */
  4008.  
  4009. #ifndef NOCSETS
  4010. VOID
  4011. setlclcharset(x) int x; {
  4012.     int i;
  4013.     tcsl = y;                   /* Local character set */
  4014. #ifdef OS2
  4015.     for (i = 0; i < 4; i++) {
  4016.         G[i].init = TRUE;
  4017.         x = G[i].designation;
  4018.         G[i].c1 = (x != tcsl) && cs_is_std(x);
  4019.         x = G[i].def_designation;
  4020.         G[i].def_c1 = (x != tcsl) && cs_is_std(x);
  4021.     }
  4022. #endif /* OS2 */
  4023. }
  4024.  
  4025. VOID
  4026. setremcharset(x, z) int x, z; {
  4027.     int i;
  4028.  
  4029. #ifdef KUI
  4030.     KuiSetProperty( KUI_TERM_REMCHARSET, (long) x, (long) z ) ;
  4031. #endif /* KUI */
  4032. #ifdef UNICODE
  4033.     if (x == TX_TRANSP)
  4034. #else /* UNICODE */
  4035.     if (x == FC_TRANSP)
  4036. #endif /* UNICODE */
  4037.     {                           /* TRANSPARENT? */
  4038. #ifndef OS2
  4039.         tcsr = tcsl;            /* Make both sets the same */
  4040. #else /* OS2 */
  4041. #ifdef CKOUNI
  4042.         tt_utf8 = 0;            /* Turn off UTF8 flag */
  4043.         tcsr = tcsl = dec_kbd = TX_TRANSP; /* No translation */
  4044.         tcs_transp = 1;
  4045.  
  4046.         if (!cs_is_nrc(tcsl)) {
  4047.             G[0].def_designation = G[0].designation = TX_ASCII;
  4048.             G[0].init = TRUE;
  4049.             G[0].def_c1 = G[0].c1 = FALSE;
  4050.             G[0].size = cs94;
  4051.             G[0].national = FALSE;
  4052.         }
  4053.         for (i = cs_is_nrc(tcsl) ? 0 : 1; i < 4; i++) {
  4054.             G[i].def_designation = G[i].designation = tcsl;
  4055.             G[i].init = TRUE;
  4056.             G[i].def_c1 = G[i].c1 = FALSE;
  4057.             switch (cs_size(G[i].designation)) { /* 94, 96, or 128 */
  4058.             case 128:
  4059.             case 96:
  4060.                 G[i].size = G[i].def_size = cs96;
  4061.                 break;
  4062.             case 94:
  4063.                 G[i].size = G[i].def_size = cs94;
  4064.                 break;
  4065.             default:
  4066.                 G[i].size = G[i].def_size = csmb;
  4067.                 break;
  4068.             }
  4069.             G[i].national = cs_is_nrc(x);
  4070.         }
  4071. #else /* CKOUNI */
  4072.         tcsr = tcsl;            /* Make both sets the same */
  4073.         for (i = 0; i < 4; i++) {
  4074.             G[i].def_designation = G[i].designation = FC_TRANSP;
  4075.             G[i].init = FALSE;
  4076.             G[i].size = G[i].def_size = cs96;
  4077.             G[i].c1 = G[i].def_c1 = FALSE;
  4078.             G[i].rtoi = NULL;
  4079.             G[i].itol = NULL;
  4080.             G[i].ltoi = NULL;
  4081.             G[i].itor = NULL;
  4082.             G[i].national = FALSE;
  4083.         }
  4084. #endif /* CKOUNI */
  4085. #endif /* OS2 */
  4086.         return;
  4087.     }
  4088. #ifdef OS2
  4089. #ifdef CKOUNI
  4090.     else if (x == TX_UTF8) {
  4091.         tcs_transp = 0;
  4092.         tt_utf8 = 1;            /* Turn it on if we are UTF8 */
  4093.         return;
  4094.     }
  4095. #endif /* CKOUNI */
  4096.     else {
  4097.         tcs_transp = 0;
  4098.         tcsr = x;                       /* Remote character set */
  4099. #ifdef CKOUNI
  4100.         tt_utf8 = 0;                    /* Turn off UTF8 flag */
  4101. #endif /* CKOUNI */
  4102.  
  4103.         if (z == TT_GR_ALL) {
  4104.             int i;
  4105. #ifdef UNICODE
  4106.             dec_kbd = x;
  4107. #endif /* UNICODE */
  4108.             for (i = 0; i < 4; i++) {
  4109.                 G[i].init = TRUE;
  4110.                 if ( i == 0 && !cs_is_nrc(x) ) {
  4111.                     G[0].designation = G[0].def_designation = FC_USASCII;
  4112.                     G[0].size = G[0].def_size = cs94;
  4113.                     G[0].national = 1;
  4114.                 } else {
  4115.                     G[i].def_designation = G[i].designation = x;
  4116.                     switch (cs_size(x)) {       /* 94, 96, or 128 */
  4117.                     case 128:
  4118.                     case 96:
  4119.                         G[i].size = G[i].def_size = cs96;
  4120.                         break;
  4121.                     case 94:
  4122.                         G[i].size = G[i].def_size = cs94;
  4123.                         break;
  4124.                     default:
  4125.                         G[i].size = G[i].def_size = csmb;
  4126.                         break;
  4127.                     }
  4128.                     G[i].national = cs_is_nrc(x);
  4129.                 }
  4130.                 G[i].c1 = G[i].def_c1 = x != tcsl && cs_is_std(x);
  4131.             }
  4132. #ifdef UNICODE
  4133.         } else if (z == TT_GR_KBD) {    /* Keyboard only */
  4134.             dec_kbd = x;
  4135. #endif /* UNICODE */
  4136.         } else {                        /* Specific Gn */
  4137.             G[z].def_designation = G[z].designation = x;
  4138.             G[z].init = TRUE;
  4139.             switch (cs_size(x)) {       /* 94, 96, or 128 */
  4140.             case 128:
  4141.             case 96:
  4142.                 G[z].size = G[z].def_size = cs96;
  4143.                 break;
  4144.             case 94:
  4145.                 G[z].size = G[z].def_size = cs94;
  4146.                 break;
  4147.             default:
  4148.                 G[z].size = G[z].def_size = csmb;
  4149.                 break;
  4150.             }
  4151.             G[z].c1 = G[z].def_c1 = x != tcsl && cs_is_std(x);
  4152.             G[z].national = cs_is_nrc(x);
  4153.         }
  4154.     }
  4155. #else /* not OS2 */
  4156.     tcsr = x;                   /* Remote character set */
  4157. #endif /* OS2 */
  4158. }
  4159. #endif /* NOCSETS */
  4160.  
  4161. VOID
  4162. setcmask(x) int x; {
  4163.     if (x == 7) {
  4164.         cmask = 0177;
  4165.     } else if (x == 8) {
  4166.         cmask = 0377;
  4167.         parity = 0;
  4168.     }
  4169. #ifdef KUI      
  4170.     KuiSetProperty(KUI_TERM_CMASK,x,0);
  4171. #endif /* KUI */
  4172. }
  4173.  
  4174. #ifdef CK_AUTODL
  4175. VOID
  4176. setautodl(x,y) int x,y; {
  4177.     autodl = x;
  4178.     adl_ask = y;
  4179. #ifdef KUI      
  4180.     KuiSetProperty(KUI_TERM_AUTODOWNLOAD,x?(y?2:1):0,0);
  4181. #endif /* KUI */
  4182. }
  4183. #endif /* CK_AUTODL */
  4184.  
  4185. #ifdef OS2
  4186. VOID
  4187. seturlhl(int x) {
  4188.     tt_url_hilite = x;
  4189. #ifdef KUI      
  4190.     KuiSetProperty(KUI_TERM_URL_HIGHLIGHT,x,0);
  4191. #endif /* KUI */
  4192. }
  4193.  
  4194. VOID
  4195. setaprint(int x) {
  4196.     extern int aprint;
  4197.     aprint = x;
  4198. #ifdef KUI
  4199.     KuiSetProperty(KUI_TERM_PRINTERCOPY,x,0);
  4200. #endif /* KUI */
  4201. }
  4202. #endif /* OS2 */
  4203.  
  4204. int
  4205. settrm() {
  4206.     int i = 0;
  4207. #ifdef OS2
  4208.     extern int colorreset, user_erasemode;
  4209. #endif /* OS2 */
  4210.     if ((y = cmkey(trmtab,ntrm,"", "",xxstring)) < 0) return(y);
  4211. #ifdef MAC
  4212.     printf("\n?Sorry, not implemented yet.  Please use the Settings menu.\n");
  4213.     return(-9);
  4214. #else
  4215. #ifdef IKSD
  4216.     if (inserver) {
  4217.         if ((y = cmcfm()) < 0) return(y);
  4218.         printf("?Sorry, command disabled.\r\n");
  4219.         return(success = 0);
  4220.     }
  4221. #endif /* IKSD */
  4222.  
  4223.     switch (y) {
  4224.       case XYTBYT:                      /* SET TERMINAL BYTESIZE */
  4225.         if ((y = cmnum("bytesize for terminal connection","8",10,&x,
  4226.                        xxstring)) < 0)
  4227.           return(y);
  4228.         if (x != 7 && x != 8) {
  4229.             printf("\n?The choices are 7 and 8\n");
  4230.             return(success = 0);
  4231.         }
  4232.         if ((y = cmcfm()) < 0) return(y);
  4233.         setcmask(x);
  4234. #ifdef OS2
  4235.         if (IS97801(tt_type_mode))
  4236.           SNI_bitmode(x);
  4237. #endif /* OS2 */
  4238.         return(success = 1);
  4239.  
  4240.       case XYTSO:                       /* SET TERMINAL LOCKING-SHIFT */
  4241.         return(seton(&sosi));
  4242.  
  4243.       case XYTNL:                       /* SET TERMINAL NEWLINE-MODE */
  4244.         return(seton(&tnlm));
  4245.  
  4246. #ifdef OS2
  4247.       case XYTCOL:
  4248.         if ((x = cmkey(ttycoltab,ncolors,"","terminal",xxstring)) < 0)
  4249.           return(x);
  4250.         else if (x == TTCOLRES) {
  4251.             if ((y = cmkey(ttcolmodetab,ncolmode,
  4252.                            "","default-color",xxstring)) < 0)
  4253.               return(y);
  4254.             if ((z = cmcfm()) < 0)
  4255.               return(z);
  4256.             colorreset = y;
  4257.             return(success = 1);
  4258.         } else if (x == TTCOLERA) {
  4259.             if ((y = cmkey(ttcolmodetab,ncolmode,"",
  4260.                            "current-color",xxstring)) < 0)
  4261.               return(y);
  4262.             if ((z = cmcfm()) < 0)
  4263.               return(z);
  4264.             user_erasemode = y;
  4265.             return(success=1);
  4266.         } else {                        /* No parse error */
  4267.             int fg = 0, bg = 0;
  4268.             fg = cmkey(ttyclrtab, nclrs,
  4269.                        (x == TTCOLBOR ?
  4270.                         "color for screen border" :
  4271.                         "foreground color and then background color"),
  4272.                        "lgray", xxstring);
  4273.             if (fg < 0)
  4274.               return(fg);
  4275.             if (x != TTCOLBOR) {
  4276.                 if ((bg = cmkey(ttyclrtab,nclrs,
  4277.                                 "background color","blue",xxstring)) < 0)
  4278.                   return(bg);
  4279.             }
  4280.             if ((y = cmcfm()) < 0)
  4281.               return(y);
  4282.             switch (x) {
  4283.               case TTCOLNOR:
  4284.                 colornormal = fg | bg << 4;
  4285.                 fgi = fg & 0x08;
  4286.                 bgi = bg & 0x08;
  4287.                 break;
  4288.               case TTCOLREV:
  4289.                 colorreverse = fg | bg << 4;
  4290.                 break;
  4291.               case TTCOLITA:
  4292.                 coloritalic = fg | bg << 4;
  4293.                 break;
  4294.               case TTCOLUND:
  4295.                 colorunderline = fg | bg << 4;
  4296.                 break;
  4297.               case TTCOLGRP:
  4298.                 colorgraphic = fg | bg << 4;
  4299.                 break;
  4300.               case TTCOLDEB:
  4301.                 colordebug = fg | bg << 4;
  4302.                 break;
  4303.               case TTCOLSTA:
  4304.                 colorstatus = fg | bg << 4;
  4305.                 break;
  4306.               case TTCOLHLP:
  4307.                 colorhelp = fg | bg << 4;
  4308.                 break;
  4309.               case TTCOLBOR:
  4310.                 colorborder = fg;
  4311.                 break;
  4312.               case TTCOLSEL:
  4313.                 colorselect = fg | bg << 4;
  4314.                 break;
  4315.               default:
  4316.                 printf("%s - invalid\n",cmdbuf);
  4317.                 return(-9);
  4318.                 break;
  4319.             }
  4320.             scrninitialized[VTERM] = 0;
  4321.             VscrnInit(VTERM);
  4322.         }
  4323.         return(success = 1);
  4324.  
  4325.       case XYTCUR: {                    /* SET TERMINAL CURSOR */
  4326.           extern int cursorena[];
  4327.           extern int cursoron[] ;       /* Cursor state on/off       */
  4328.           if ((x = cmkey(ttycurtab,ncursors,"","underline",xxstring)) < 0)
  4329.             return(x);
  4330.           if ((z = cmkey(curontab,ncuron,"","on",xxstring)) < 0)
  4331.             return(z);
  4332.           if ((y = cmcfm()) < 0) return(y);
  4333.           tt_cursor = tt_cursor_usr = x;
  4334.           if ( z == 2 ) {
  4335.               cursorena[VTERM] = tt_cursorena_usr = 1;
  4336.               tt_cursor_blink = 0;
  4337.           } else {
  4338.               cursorena[VTERM] = tt_cursorena_usr = z;/* turn cursor on/off */
  4339.               tt_cursor_blink = 1;
  4340.           }
  4341.           cursoron[VTERM] = FALSE; /* Force newcursor to restore the cursor */
  4342.           return(success = 1);
  4343.       }
  4344. #endif /* OS2 */
  4345.  
  4346.       case XYTTYP:                      /* SET TERMINAL TYPE */
  4347.         return(settrmtyp());
  4348.  
  4349. #ifdef OS2
  4350.       case XYTARR:                      /* SET TERMINAL ARROW-KEYS */
  4351.         if ((x = cmkey(akmtab,2,"","",xxstring)) < 0) return(x);
  4352.         if ((y = cmcfm()) < 0) return(y);
  4353.         tt_arrow = x;                   /* TTK_NORM / TTK_APPL; see ckuusr.h */
  4354.         return(success = 1);
  4355.  
  4356.       case XYTKPD:                      /* SET TERMINAL KEYPAD-MODE */
  4357.         if ((x = cmkey(kpmtab,2,"","",xxstring)) < 0) return(x);
  4358.         if ((y = cmcfm()) < 0) return(y);
  4359.         tt_keypad = x;                  /* TTK_NORM / TTK_APPL; see ckuusr.h */
  4360.         return(success = 1);
  4361.  
  4362.       case XYTUNX: {                    /* SET TERM UNIX-MODE (DG) */
  4363.         extern int dgunix,dgunix_usr;
  4364.         x = seton(&dgunix);
  4365.         dgunix_usr = dgunix;
  4366.         return(x);
  4367.       }
  4368.       case XYTKBMOD: {                  /* SET TERM KEYBOARD MODE */
  4369.           extern int tt_kb_mode;
  4370.           if ((x = cmkey(kbmodtab,
  4371.                          nkbmodtab,
  4372.                          "normal",
  4373.                          "special keyboard mode for terminal emulation",
  4374.                          xxstring)
  4375.                ) < 0)
  4376.             return(x);
  4377.           if ((y = cmcfm()) < 0) return(y);
  4378.           tt_kb_mode = x;
  4379.           return(success = 1);
  4380.       }
  4381.  
  4382.       case XYTWRP:                      /* SET TERMINAL WRAP */
  4383.         return(seton(&tt_wrap));
  4384.  
  4385.       case XYSCRS:
  4386.         if ((y = cmnum("CONNECT scrollback buffer size, lines","2000",10,&x,
  4387.                        xxstring)) < 0)
  4388.           return(y);
  4389.         /* The max number of lines is the RAM  */
  4390.         /* we can actually dedicate to a       */
  4391.         /* scrollback buffer given the maximum */
  4392.         /* process memory space of 512MB       */
  4393.         if (x < 256 || x > 2000000L) {
  4394.             printf("\n?The size must be between 256 and 2,000,000.\n");
  4395.             return(success = 0);
  4396.         }
  4397.         if ((y = cmcfm()) < 0) return(y);
  4398.         tt_scrsize[VTERM] = x;
  4399.         VscrnInit(VTERM);
  4400.         return(success = 1);
  4401. #endif /* OS2 */
  4402.  
  4403. #ifndef NOCSETS
  4404.       case XYTCS: {                     /* SET TERMINAL CHARACTER-SET */
  4405.         int eol;
  4406.           /* set terminal character-set <remote> <local> */
  4407.         if ((x = cmkey(
  4408. #ifdef CKOUNI
  4409.                        txrtab,ntxrtab,
  4410. #else  /* CKOUNI */
  4411.                        ttcstab,ntermc,
  4412. #endif /* CKOUNI */
  4413.                        "remote terminal character-set","",xxstring)) < 0)
  4414.           return(x);
  4415.  
  4416. #ifdef UNICODE
  4417.         if (x == TX_TRANSP
  4418. #ifdef CKOUNI
  4419.             || x == TX_UTF8
  4420. #endif /* CKOUNI */
  4421.            ) {
  4422.               if ((y = cmcfm()) < 0)    /* Confirm the command */
  4423.                   return(y);
  4424. #ifdef OS2
  4425.             if ( isunicode() && x == TX_TRANSP ) {
  4426.                 /* If we are in unicode display mode then transparent
  4427.                  * only affects the output direction.  We need to know
  4428.                  * the actual remote character set in order to perform
  4429.                  * the tcsr -> ucs2 translation for display.
  4430.                  */
  4431.                 x = y = tcsl;
  4432.             } else
  4433. #endif /* OS2 */
  4434.                 y = x;
  4435.         }
  4436. #else /* UNICODE */
  4437.         if (x == FC_TRANSP) {
  4438.             if ((y = cmcfm()) < 0)      /* Confirm the command */
  4439.                 return(y);
  4440.             y = x;
  4441.         }
  4442. #endif /* UNICODE */
  4443.  
  4444.         /* Not transparent or UTF8, so get local set to translate it into */
  4445.         s = "";
  4446. #ifdef OS2
  4447.         y = os2getcp();                 /* Default is current code page */
  4448.         switch (y) {
  4449.           case 437: s = "cp437"; break;
  4450.           case 850: s = "cp850"; break;
  4451.           case 852: s = "cp852"; break;
  4452.           case 857: s = "cp857"; break;
  4453.           case 858: s = "cp858"; break;
  4454.           case 862: s = "cp862"; break;
  4455.           case 866: s = "cp866"; break;
  4456.           case 869: s = "cp869"; break;
  4457.           case 1250: s = "cp1250"; break;
  4458.           case 1251: s = "cp1251"; break;
  4459.           case 1252: s = "cp1252"; break;
  4460.           case 1253: s = "cp1253"; break;
  4461.           case 1254: s = "cp1254"; break;
  4462.           case 1255: s = "cp1255"; break;
  4463.           case 1256: s = "cp1256"; break;
  4464.           case 1257: s = "cp1257"; break;
  4465.           case 1258: s = "cp1258"; break;
  4466.         }
  4467. #ifdef PCFONTS
  4468. /*
  4469.    If the user has loaded a font with SET TERMINAL FONT then we want
  4470.    to change the default code page to the font that was loaded.
  4471. */
  4472.         if (tt_font != TTF_ROM) {
  4473.             for (y = 0; y < ntermfont; y++ ) {
  4474.                 if (term_font[y].kwval == tt_font) {
  4475.                     s = term_font[y].kwd;
  4476.                     break;
  4477.                 }
  4478.             }
  4479.         }
  4480. #endif /* PCFONTS */
  4481. #else  /* Not K95... */
  4482.         s = fcsinfo[fcharset].keyword;
  4483. #endif /* OS2 */
  4484.  
  4485.         if ((y = cmkey(
  4486. #ifdef CKOUNI
  4487.                        txrtab,ntxrtab,
  4488. #else /* CKOUNI */
  4489.                        ttcstab,ntermc,
  4490. #endif /* CKOUNI */
  4491.                        "local character-set",s,xxstring)) < 0)
  4492.           return(y);
  4493.  
  4494. #ifdef UNICODE
  4495.         if (y == TX_UTF8) {
  4496.             printf("?UTF8 may not be used as a local character set.\r\n");
  4497.             return(-9);
  4498.         }
  4499. #endif /* UNICODE */
  4500. #ifdef OS2
  4501.         if ((z = cmkey(graphsettab,ngraphset,
  4502.                        "DEC VT intermediate graphic set","all",xxstring)) < 0)
  4503.             return(z);
  4504. #endif /* OS2 */
  4505.         if ((eol = cmcfm()) < 0)
  4506.             return(eol); /* Confirm the command */
  4507.  
  4508.         /* End of command parsing - actions begin */
  4509.         setlclcharset(y);
  4510.         setremcharset(x,z);
  4511.         return(success = 1);
  4512.       }
  4513. #endif /* NOCSETS */
  4514.  
  4515. #ifndef NOCSETS
  4516.       case XYTLCS:                      /* SET TERMINAL LOCAL-CHARACTER-SET */
  4517.         /* set terminal character-set <local> */
  4518.         s = getdcset();                 /* Get display character-set name */
  4519.         if ((y = cmkey(
  4520. #ifdef CKOUNI
  4521.                        txrtab,ntxrtab,
  4522. #else /* CKOUNI */
  4523.                        fcstab,nfilc,
  4524. #endif /* CKOUNI */
  4525.                        "local character-set",s,xxstring)) < 0)
  4526.           return(y);
  4527.  
  4528. #ifdef UNICODE
  4529.           if (y == TX_UTF8) {
  4530.               printf("?UTF8 may not be used as a local character set.\r\n");
  4531.               return(-9);
  4532.           }
  4533. #endif /* UNICODE */
  4534.           if ((z = cmcfm()) < 0) return(z); /* Confirm the command */
  4535.  
  4536.           /* End of command parsing - action begins */
  4537.  
  4538.         setlclcharset(y);
  4539.         return(success = 1);
  4540. #endif /* NOCSETS */
  4541.  
  4542. #ifndef NOCSETS
  4543. #ifdef UNICODE
  4544.       case XYTUNI:                      /* SET TERMINAL UNICODE */
  4545.         return(seton(&tt_unicode));
  4546. #endif /* UNICODE */
  4547.  
  4548.       case XYTRCS:                      /* SET TERMINAL REMOTE-CHARACTER-SET */
  4549.         /* set terminal character-set <remote> <Graphic-set> */
  4550.         if ((x = cmkey(
  4551. #ifdef CKOUNI
  4552.                 txrtab, ntxrtab,
  4553. #else /* CKOUNI */
  4554.                 ttcstab,ntermc,
  4555. #endif /* CKOUNI */
  4556.                        "remote terminal character-set","",xxstring)) < 0)
  4557.           return(x);
  4558.  
  4559. #ifdef UNICODE
  4560.         if (x == TX_TRANSP
  4561. #ifdef CKOUNI
  4562.             || x == TX_UTF8
  4563. #endif /* CKOUNI */
  4564.            ) {
  4565.               if ((y = cmcfm()) < 0)    /* Confirm the command */
  4566.                   return(y);
  4567. #ifdef OS2
  4568.             if ( isunicode() && x == TX_TRANSP ) {
  4569.                 /* If we are in unicode display mode then transparent
  4570.                  * only affects the output direction.  We need to know
  4571.                  * the actual remote character set in order to perform
  4572.                  * the tcsr -> ucs2 translation for display.
  4573.                  */
  4574.                 x = tcsl;
  4575.             }
  4576. #endif /* OS2 */
  4577.         }
  4578. #else /* UNICODE */
  4579.         if (x == FC_TRANSP) {
  4580.           if ((y = cmcfm()) < 0)        /* Confirm the command */
  4581.             return(y);
  4582.         }
  4583. #endif /* UNICODE */
  4584.         else {
  4585. #ifdef OS2
  4586.           if ((z = cmkey(graphsettab,ngraphset,
  4587.                       "DEC VT intermediate graphic set","all",xxstring)) < 0)
  4588.             return(z);
  4589. #endif /* OS2 */
  4590.           if ((y = cmcfm()) < 0)        /* Confirm the command */
  4591.             return(y);
  4592.         }
  4593.         /* Command parsing ends here */
  4594.  
  4595.         setremcharset(x,z);
  4596.         return(success = 1);
  4597. #endif /* NOCSETS */
  4598.  
  4599.       case XYTEC:                       /* SET TERMINAL ECHO */
  4600.         if ((x = cmkey(rltab,nrlt,"which side echos during CONNECT",
  4601.                        "remote", xxstring)) < 0) return(x);
  4602.         if ((y = cmcfm()) < 0) return(y);
  4603. #ifdef NETCONN
  4604.         oldplex = x;
  4605. #endif /* NETCONN */
  4606.         duplex = x;
  4607.         return(success = 1);
  4608.  
  4609.       case XYTESC:                      /* SET TERM ESC */
  4610.         if ((x = cmkey(nabltab,nnabltab,"","enabled",xxstring)) < 0)
  4611.           return(x);
  4612.         if ((y = cmcfm()) < 0) return(y);
  4613.         tt_escape = x;
  4614.         return(1);
  4615.  
  4616.       case XYTCRD:                      /* SET TERMINAL CR-DISPLAY */
  4617.         if ((x = cmkey(crdtab,2,"", "normal", xxstring)) < 0) return(x);
  4618.         if ((y = cmcfm()) < 0) return(y);
  4619.         tt_crd = x;
  4620.         return(success = 1);
  4621.  
  4622.       case XYTLFD:                      /* SET TERMINAL LF-DISPLAY */
  4623.         if ((x = cmkey(crdtab,2,"", "normal", xxstring)) < 0) return(x);
  4624.         if ((y = cmcfm()) < 0) return(y);
  4625.         tt_lfd = x;
  4626.         return(success = 1);
  4627.  
  4628. #ifdef OS2
  4629.       case XYTANS: {                    /* SET TERMINAL ANSWERBACK */
  4630. /*
  4631.   NOTE: We let them enable and disable the answerback sequence, but we
  4632.   do NOT let them change it, and we definitely do not let the host set it.
  4633.   This is a security feature.
  4634.  
  4635.   As of 1.1.8 we allow the SET TERM ANSWERBACK MESSAGE <string> to be
  4636.   used just as MS-DOS Kermit does.  C0 and C1 controls as well as DEL
  4637.   are not allowed to be used as characters.  They are translated to
  4638.   underscore.  This may not be set by APC.
  4639. */
  4640.           if ((x = cmkey(anbktab,nansbk,"", "off", xxstring)) < 0)
  4641.             return(x);
  4642.           if (x < 2) {
  4643.               if ((y = cmcfm()) < 0)
  4644.                 return(y);
  4645.               tt_answer = x;
  4646.               return(success = 1);
  4647.           } else if ( x == 2 || x == 3) {
  4648.               int len = 0;
  4649.               extern int safeanswerbk;
  4650.               extern char useranswerbk[];
  4651.               if ((y = cmtxt("Answerback extension","",&s,xxstring)) < 0)
  4652.                 return(y);
  4653.               if (apcactive == APC_LOCAL ||
  4654.                   (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
  4655.                 return(success = 0);
  4656.               len = strlen(s);
  4657.               if (x == 2) {
  4658.                   /* Safe Answerback's don't have C0/C1 chars */
  4659.                   for (z = 0; z < len; z++) {
  4660.                       if ((s[z] & 0x7F) <= SP || (s[z] & 0x7F) == DEL)
  4661.                         useranswerbk[z] = '_';
  4662.                       else
  4663.                         useranswerbk[z] = s[z];
  4664.                   }
  4665.                   useranswerbk[z] = '\0';
  4666.                   safeanswerbk = 1 ;    /* TRUE */
  4667.               } else {
  4668.                   ckstrncpy(useranswerbk,s,60); /* (see ckocon.c) */
  4669.                   safeanswerbk = 0;     /* FALSE */
  4670.               }
  4671.               updanswerbk();
  4672.               return(success = 1);
  4673.           } else
  4674.             return(success = 0);
  4675.       }
  4676. #endif /* OS2 */
  4677.  
  4678. #ifdef CK_APC
  4679.       case XYTAPC:
  4680.         if ((y = cmkey(apctab,napctab,
  4681.                        "application program command execution","",
  4682.                        xxstring)) < 0)
  4683.           return(y);
  4684.         if ((x = cmcfm()) < 0)
  4685.           return(x);
  4686.         if (apcactive == APC_LOCAL ||
  4687.             (apcactive == APC_REMOTE && !(apcstatus & APC_UNCH)))
  4688.           return(success = 0);
  4689.         apcstatus = y;
  4690.         return(success = 1);
  4691.  
  4692. #ifdef CK_AUTODL
  4693.       case XYTAUTODL:                   /* AUTODOWNLOAD */
  4694.         if ((y = cmkey(adltab,nadltab,"Auto-download options","",
  4695.                        xxstring)) < 0)
  4696.           return(y);
  4697.         switch (y) {
  4698.           case TAD_ON:
  4699.           case TAD_OFF:
  4700.             if ((x = cmcfm()) < 0)
  4701.               return(x);
  4702.             setautodl(y,0);
  4703.             break;
  4704.           case TAD_ASK:
  4705.             if ((x = cmcfm()) < 0)
  4706.               return(x);
  4707.             setautodl(TAD_ON,1);
  4708.             break;
  4709.           case TAD_ERR:
  4710.             if ((y = cmkey(adlerrtab,nadlerrtab,"","", xxstring)) < 0)
  4711.               return(y);
  4712.             if ((x = cmcfm()) < 0)
  4713.               return(x);
  4714.             adl_err = y;
  4715.             break;
  4716. #ifdef OS2
  4717.           case TAD_K:
  4718.             if ((y = cmkey(adlxtab,nadlxtab,"","", xxstring)) < 0)
  4719.               return(y);
  4720.             switch (y) {
  4721.               case TAD_X_C0:
  4722.                 if ((y = cmkey(adlc0tab,nadlc0tab,"",
  4723.                                "processed-by-emulator",xxstring)) < 0)
  4724.                   return(y);
  4725.                 if ((x = cmcfm()) < 0)
  4726.                   return(x);
  4727.                 adl_kc0 = y;
  4728.                 break;
  4729.               case TAD_X_DETECT:
  4730.                 if ((y = cmkey(adldtab,nadldtab,"","packet",xxstring)) < 0)
  4731.                   return(y);
  4732.                 if ((x = cmcfm()) < 0)
  4733.                   return(x);
  4734.                 adl_kmode = y;
  4735.                 break;
  4736.               case TAD_X_STR:
  4737.                 if ((y = cmtxt("Kermit start string","KERMIT READY TO SEND...",
  4738.                                &s,xxstring)) < 0)
  4739.                   return(y);
  4740.                 free(adl_kstr);
  4741.                 adl_kstr = strdup(s);
  4742.                 break;
  4743.             }
  4744.             break;
  4745.  
  4746.           case TAD_Z:
  4747.             if ((y = cmkey(adlxtab,nadlxtab,"","",xxstring)) < 0)
  4748.               return(y);
  4749.             switch (y) {
  4750.               case TAD_X_C0:
  4751.                 if ((y = cmkey(adlc0tab,nadlc0tab,"",
  4752.                                "processed-by-emulator",xxstring)) < 0)
  4753.                   return(y);
  4754.                 if ((x = cmcfm()) < 0)
  4755.                   return(x);
  4756.                 adl_zc0 = y;
  4757.                 break;
  4758.               case TAD_X_DETECT:
  4759.                 if ((y = cmkey(adldtab,nadldtab,"","packet",xxstring)) < 0)
  4760.                   return(y);
  4761.                 if ((x = cmcfm()) < 0)
  4762.                   return(x);
  4763.                 adl_zmode = y;
  4764.                 break;
  4765.               case TAD_X_STR:
  4766.                 if ((y = cmtxt("","rz\\{13}",&s,xxstring)) < 0)
  4767.                   return(y);
  4768.                 free(adl_zstr);
  4769.                 adl_zstr = strdup(s);
  4770.                 break;
  4771.             }
  4772.             break;
  4773. #endif /* OS2 */
  4774.         }
  4775.         return(success = 1);
  4776.  
  4777. #endif /* CK_AUTODL */
  4778. #endif /* CK_APC */
  4779.  
  4780. #ifdef OS2
  4781.       case XYTBEL:
  4782.         return(success = setbell());
  4783.  
  4784.       case XYTMBEL:                     /* MARGIN-BELL */
  4785.         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  4786.         if (y) {                        /* ON */
  4787.             if ((z = cmnum("Column at which to set margin bell",
  4788.                            "72",10,&x,xxstring)) < 0)
  4789.               return(z);
  4790.         }
  4791.         if ((z = cmcfm()) < 0) return(z);
  4792.         marginbell = y;
  4793.         marginbellcol = x;
  4794.         return(success = 1);
  4795. #endif /* OS2 */
  4796.  
  4797. #ifdef CKTIDLE
  4798.       case XYTIDLE:                     /* IDLE-SEND */
  4799.       case XYTITMO:                     /* IDLE-TIMEOUT */
  4800.         if ((z = cmnum("seconds of idle time to wait, or 0 to disable",
  4801.                        "0",10,&x,xxstring)) < 0)
  4802.           return(z);
  4803.         if (y == XYTIDLE) {
  4804.             if ((y = cmtxt("string to send, may contain kverbs and variables",
  4805.                            "\\v(newline)",&s,xxstring)) < 0)
  4806.               return(y);
  4807.             tt_idlesnd_tmo = x;         /* (old) */
  4808.             tt_idlelimit = x;           /* (new) */
  4809.             makestr(&tt_idlestr,brstrip(s)); /* (new) */
  4810.             tt_idlesnd_str = tt_idlestr; /* (old) */
  4811.             tt_idleact = IDLE_OUT;      /* (new) */
  4812.         } else {
  4813.             if ((y = cmcfm()) < 0)
  4814.               return(y);
  4815.             tt_idlelimit = x;
  4816.         }
  4817. #ifdef OS2
  4818.         puterror(VTERM);
  4819. #endif /* OS2 */
  4820.         return(success = 1);
  4821.  
  4822.       case XYTIACT: {                   /* SET TERM IDLE-ACTION */
  4823.           if ((y = cmkey(idlacts,nidlacts,"","",xxstring)) < 0)
  4824.             return(y);
  4825.           if (y == IDLE_OUT) {
  4826.               if ((x = cmtxt("string to send, may contain kverbs and variables"
  4827.                              , "",&s,xxstring)) < 0)
  4828.                 return(x);
  4829.               makestr(&tt_idlestr,brstrip(s)); /* (new) */
  4830.               tt_idlesnd_str = tt_idlestr; /* (old) */
  4831.           } else {
  4832.               if ((x = cmcfm()) < 0)
  4833.                 return(x);
  4834.           }
  4835.           tt_idleact = y;
  4836.           return(success = 1);
  4837.       }
  4838. #endif /* CKTIDLE */
  4839.  
  4840.       case XYTDEB:                      /* TERMINAL DEBUG */
  4841.         y = seton(&x);                  /* Go parse ON or OFF */
  4842.         if (y > 0)                      /* Command succeeded? */
  4843.           setdebses(x);
  4844.         return(y);
  4845.  
  4846. #ifdef OS2
  4847.       case XYTASCRL:                    /* SET TERMINAL AUTOSCROLL */
  4848.           y = seton(&autoscroll);
  4849.           return(y);
  4850.  
  4851.       case XYTAPAGE:                    /* SET TERMINAL AUTOPAGE */
  4852.           y = seton(&wy_autopage);
  4853.           return(y);
  4854.  
  4855.       case XYTROL:                      /* SET TERMINAL ROLL */
  4856.         if ((y = cmkey(rolltab,nroll,"scrollback mode","insert",xxstring))<0)
  4857.       return(y);
  4858.     if (y == TTR_KEYS) {
  4859.         if ((x = cmkey(rollkeytab,nrollkey,"","send",xxstring))<0)
  4860.           return(x);
  4861.         if ((z = cmcfm()) < 0) return(z);
  4862.         tt_rkeys[VTERM] = x;
  4863.     } else {
  4864.         if ((x = cmcfm()) < 0) return(x);
  4865.         tt_roll[VTERM] = y;
  4866.     }
  4867.         return(success = 1);
  4868.  
  4869.       case XYTCTS:                      /* SET TERMINAL TRANSMIT-TIMEOUT */
  4870.         y = cmnum("Maximum seconds to allow CTS off during CONNECT",
  4871.                   "5",10,&x,xxstring);
  4872.         return(setnum(&tt_ctstmo,x,y,10000));
  4873.  
  4874.       case XYTCPG: {                    /* SET TERMINAL CODE-PAGE */
  4875.         int i;
  4876.         int cp = -1;
  4877.         y = cmnum("PC code page to use during terminal emulation",
  4878.                   ckitoa(os2getcp()),10,&x,xxstring);
  4879.         if ((x = setnum(&cp,x,y,11000)) < 0) return(x);
  4880.         if (os2setcp(cp) != 1) {
  4881. #ifdef NT
  4882.             if (isWin95())
  4883.               printf(
  4884.                  "Sorry, Windows 95 does not support code page switching\n");
  4885.             else
  4886. #endif /* NT */
  4887.               printf(
  4888.                  "Sorry, %d is not a valid code page for this system.\n",cp);
  4889.             return(-9);
  4890.         }
  4891.     /* Force the terminal character-sets conversions to be updated */
  4892.         for ( i = 0; i < 4; i++ )
  4893.           G[i].init = TRUE;
  4894.         return(1);
  4895.     }
  4896.  
  4897.       case XYTPAC:                      /* SET TERMINAL OUTPUT-PACING */
  4898.         y = cmnum(
  4899.            "Pause between sending each character during CONNECT, milliseconds",
  4900.                   "-1",10,&x,xxstring);
  4901.         return(setnum(&tt_pacing,x,y,10000));
  4902.  
  4903. #ifdef OS2MOUSE
  4904.       case XYTMOU: {                    /* SET TERMINAL MOUSE */
  4905.           int old_mou = tt_mouse;
  4906.           if ((x = seton(&tt_mouse)) < 0)
  4907.             return(x);
  4908.           if (tt_mouse != old_mou)
  4909.             if (tt_mouse)
  4910.               os2_mouseon();
  4911.             else
  4912.               os2_mouseoff();
  4913.           return(1);
  4914.       }
  4915. #endif /* OS2MOUSE */
  4916. #endif /* OS2 */
  4917.  
  4918.       case XYTWID: {
  4919.           if ((y = cmnum(
  4920. #ifdef OS2
  4921.                          "number of columns in display window during CONNECT",
  4922. #else
  4923.                          "number of columns on your screen",
  4924. #endif /* OS2 */
  4925.                          "80",10,&x,xxstring)) < 0)
  4926.             return(y);
  4927.           if ((y = cmcfm()) < 0) return(y);
  4928. #ifdef OS2
  4929.           return(success = os2_settermwidth(x));
  4930. #else  /* Not OS/2 */
  4931.           tt_cols = x;
  4932.           return(success = 1);
  4933. #endif /* OS2 */
  4934.       }
  4935.  
  4936.       case XYTHIG:
  4937.         if ((y = cmnum(
  4938. #ifdef OS2
  4939.  "number of rows in display window during CONNECT, not including status line",
  4940.  tt_status[VTERM]?"24":"25",
  4941. #else
  4942.  "24","number of rows on your screen",
  4943. #endif /* OS2 */
  4944.                        10,&x,xxstring)) < 0)
  4945.           return(y);
  4946.         if ((y = cmcfm()) < 0) return(y);
  4947.  
  4948. #ifdef OS2
  4949.         return (success = os2_settermheight(x));
  4950. #else  /* Not OS/2 */
  4951.         tt_rows = x;
  4952.         return(success = 1);
  4953. #endif /* OS2 */
  4954.  
  4955. #ifdef OS2
  4956.       case XYTPRN: {                    /* Print Mode */
  4957.           extern bool xprint, aprint, cprint, uprint;
  4958.           if ((y = cmkey(prnmtab,nprnmtab,"","off", xxstring)) < 0) return(y);
  4959.           if ((x = cmcfm()) < 0) return(x);
  4960.           switch (y) {
  4961.             case 0:
  4962.               if (cprint || uprint || aprint || xprint)
  4963.                 printeroff();
  4964.               cprint = xprint = uprint = 0;
  4965.               setaprint(0);
  4966.               break;
  4967.             case 1:
  4968.               if (!(cprint || uprint || aprint || xprint))
  4969.                 printeron();
  4970.               setaprint(1);
  4971.               cprint = xprint = uprint = 0;
  4972.               break;
  4973.             case 2:
  4974.               if (!(cprint || uprint || aprint || xprint))
  4975.                 printeron();
  4976.               cprint = 1;
  4977.               setaprint(0);
  4978.           xprint = uprint = 0;
  4979.               break;
  4980.             case 3:
  4981.               if (!(cprint || uprint || aprint || xprint))
  4982.                 printeron();
  4983.               uprint = 1;
  4984.               setaprint(0);
  4985.               xprint = cprint = 0;
  4986.               break;
  4987.           }
  4988.           return(1);
  4989.       }
  4990. #else
  4991. #ifdef XPRINT
  4992.       case XYTPRN: {
  4993.           extern int tt_print;
  4994.           if ((x = seton(&tt_print)) < 0)
  4995.             return(x);
  4996.           return(success = 1);
  4997.       }
  4998. #endif /* XPRINT */
  4999. #endif /* OS2 */
  5000.  
  5001. #ifdef OS2
  5002.       case XYTSCNM: {
  5003.           extern int decscnm, decscnm_usr;
  5004.           if ((y = cmkey(normrev,4,"",
  5005.                          decscnm_usr?"reverse":"normal",
  5006.                          xxstring)
  5007.                ) < 0)
  5008.             return(y);
  5009.           if ((x = cmcfm()) < 0) return(x);
  5010.           decscnm_usr = y;
  5011.           if (decscnm != decscnm_usr)
  5012.             flipscreen(VTERM);
  5013.           return(1);
  5014.     }
  5015.     case XYTOPTI:
  5016.         if ((y = cmkey(onoff,2,"",tt_diff_upd?"on":"off",
  5017.                         xxstring)) < 0) return(y);
  5018.         if ((x = cmcfm()) < 0) return(x);
  5019.         tt_diff_upd = y;
  5020.         return(1);
  5021.     case XYTUPD: {
  5022.         int mode, delay;
  5023.         if ((mode = cmkey(scrnupd,nscrnupd,"","fast",xxstring)) < 0) {
  5024.             return(mode);
  5025.         } else {
  5026.             y = cmnum(
  5027.             "Pause between FAST screen updates in CONNECT mode, milliseconds",
  5028.                       "100",10,&x,xxstring
  5029.                       );
  5030.             if (x < 0 || x > 1000 ) {
  5031.                 printf(
  5032.             "\n?The update rate must be between 0 and 1000 milliseconds.\n"
  5033.                        );
  5034.                 return(success = 0);
  5035.             }
  5036.             if ((y = cmcfm()) < 0) return(y);
  5037.  
  5038.             updmode = tt_updmode = mode;
  5039.             return(setnum(&tt_update,x,y,10000));
  5040.         }
  5041.     }
  5042.     case XYTCTRL:
  5043.           if ((x = cmkey(termctrl,ntermctrl,"","7",xxstring)) < 0) {
  5044.               return(x);
  5045.           } else {
  5046.               if ((y = cmcfm()) < 0)
  5047.                   return(y);
  5048.               switch ( x ) {
  5049.               case 8:
  5050.                   send_c1 = send_c1_usr = TRUE;
  5051.                   break;
  5052.               case 7:
  5053.               default:
  5054.                   send_c1 = send_c1_usr = FALSE;
  5055.                   break;
  5056.               }
  5057.           }
  5058.           return(success = TRUE);
  5059.           break;
  5060.  
  5061. #ifdef PCFONTS
  5062.       case XYTFON:
  5063.         if ( !IsOS2FullScreen() ) {
  5064.             printf(
  5065.         "\n?SET TERMINAL FONT is only supported in Full Screen sessions.\n");
  5066.             return(success = FALSE);
  5067.         }
  5068.  
  5069.         if ((x = cmkey(term_font,ntermfont,"","default",xxstring)) < 0) {
  5070.             return(x);
  5071.         } else {
  5072.             if ((y = cmcfm()) < 0) return(y);
  5073.             if ( !os2LoadPCFonts() ) {
  5074.                 tt_font = x;
  5075.                 return(success = TRUE);
  5076.             } else {
  5077.                 printf(
  5078.       "\n?PCFONTS.DLL is not available in CKERMIT executable directory.\n");
  5079.                 return(success = FALSE);
  5080.             }
  5081.         }
  5082.         break;
  5083. #else /* PCFONTS */
  5084. #ifdef NT
  5085. #ifdef KUI
  5086.     case XYTFON:
  5087.         return(setguifont());           /* ckuus3.c */
  5088. #endif /* KUI */
  5089. #endif /* NT */
  5090. #endif /* PCFONTS */
  5091.  
  5092.       case XYTVCH: {
  5093.           extern int pheight, marginbot, cmd_rows, cmd_cols;
  5094.           if ((x = cmkey(tvctab,ntvctab,"",isWin95()?"win95-safe":"enabled",
  5095.                          xxstring)) < 0)
  5096.             return(x);
  5097.           if ((y = cmcfm()) < 0) return(y);
  5098. #ifndef KUI
  5099.           if (x != tt_modechg) {
  5100.               switch (x) {
  5101.                 case TVC_DIS:
  5102.                   /* When disabled the heights of all of the virtual screens */
  5103.                   /* must be equal to the physical height of the console     */
  5104.                   /* window and may not be changed.                          */
  5105.                   /* The width of the window may not be altered.             */
  5106.                   tt_modechg = TVC_ENA;                 /* Temporary */
  5107.                   if (marginbot > pheight-(tt_status[VTERM]?1:0))
  5108.                     marginbot = pheight-(tt_status[VTERM]?1:0);
  5109.                   tt_szchng[VCMD] = 1 ;
  5110.                   tt_rows[VCMD] = pheight;
  5111.                   VscrnInit(VCMD);
  5112.                   SetCols(VCMD);
  5113.                   cmd_rows = y;
  5114.  
  5115.                   tt_szchng[VTERM] = 2 ;
  5116.                   tt_rows[VTERM] = pheight - (tt_status[VTERM]?1:0);
  5117.                   VscrnInit(VTERM);
  5118.  
  5119.                   break;
  5120.  
  5121.                 case TVC_ENA:
  5122.                   /* When enabled the physical height of the console windows */
  5123.                   /* should be adjusted to the height of the virtual screen  */
  5124.                   /* The width may be set to anything.                       */
  5125.                   /* nothing to do                                           */
  5126.                   break;
  5127.  
  5128.               case TVC_W95:
  5129.                   /* Win95-safe mode allows the physical height to change    */
  5130.                   /* but restricts it to a width of 80 and a height equal to */
  5131.                   /* 25, 43, or 50.  Must be adjusted now.                   */
  5132.                   /* The virtual heights must be equal to the above.         */
  5133.                   if (pheight != 25 && pheight != 43 && pheight != 50) {
  5134.                       if (pheight < 25)
  5135.                         y = 25;
  5136.                       else if (pheight < 43)
  5137.                         y = 43;
  5138.                       else
  5139.                         y = 50;
  5140.                   } else
  5141.                     y = pheight;
  5142.  
  5143.                   tt_modechg = TVC_ENA; /* Temporary */
  5144.  
  5145.                   tt_szchng[VCMD] = 1;
  5146.                   tt_rows[VCMD] = y;
  5147.                   tt_cols[VCMD] = 80;
  5148.                   VscrnInit(VCMD);
  5149.                   SetCols(VCMD);
  5150.                   cmd_rows = y;
  5151.                   cmd_cols = 80;
  5152.  
  5153.                   marginbot = y-(tt_status[VTERM]?1:0);
  5154.                   tt_szchng[VTERM] = 2;
  5155.                   tt_rows[VTERM] = y - (tt_status[VTERM]?1:0);
  5156.                   tt_cols[VTERM] = 80;
  5157.                   VscrnInit(VTERM);
  5158.                   break;
  5159.               }
  5160.               tt_modechg = x;
  5161.           }
  5162.           return(success = 1);
  5163. #else
  5164.           return(success = 0);
  5165. #endif /* KUI */
  5166.       }
  5167.       case XYTSTAT: {
  5168.           extern int marginbot;
  5169.           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5170.           if ((x = cmcfm()) < 0) return(x);
  5171.           if (y != tt_status[VTERM] || y != tt_status_usr[VTERM]) {
  5172.               /* Might need to fixup the margins */
  5173.               if ( marginbot == VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) )
  5174.                 if (y) {
  5175.                     marginbot--;
  5176.                 } else {
  5177.                     marginbot++;
  5178.                 }
  5179.               tt_status_usr[VTERM] = tt_status[VTERM] = y;
  5180.               if (y) {
  5181.                     tt_szchng[VTERM] = 2;
  5182.                     tt_rows[VTERM]--;
  5183.                     VscrnInit(VTERM);  /* Height set here */
  5184. #ifdef TNCODE
  5185.                     if (TELOPT_ME(TELOPT_NAWS))
  5186.                       tn_snaws();
  5187. #endif /* TNCODE */
  5188. #ifdef RLOGCODE
  5189.                     if (TELOPT_ME(TELOPT_NAWS))
  5190.                       rlog_naws();
  5191. #endif /* RLOGCODE */
  5192. #ifdef SSHBUILTIN
  5193.                     if (TELOPT_ME(TELOPT_NAWS))
  5194.                       ssh_snaws();
  5195. #endif /* SSHBUILTIN */
  5196.               } else {
  5197.                   tt_szchng[VTERM] = 1;
  5198.                   tt_rows[VTERM]++;
  5199.                   VscrnInit(VTERM);     /* Height set here */
  5200. #ifdef TNCODE
  5201.                   if (TELOPT_ME(TELOPT_NAWS))
  5202.                     tn_snaws();
  5203. #endif /* TNCODE */
  5204. #ifdef RLOGCODE
  5205.                   if (TELOPT_ME(TELOPT_NAWS))
  5206.                     rlog_naws();
  5207. #endif /* RLOGCODE */
  5208. #ifdef SSHBUILTIN
  5209.                   if (TELOPT_ME(TELOPT_NAWS))
  5210.                     ssh_snaws();
  5211. #endif /* SSHBUILTIN */
  5212.               }
  5213.           }
  5214.           return(1);
  5215.       }
  5216. #endif /* OS2 */
  5217.  
  5218. #ifdef NT
  5219.       case XYTATTBUG:
  5220.         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5221.         if ((x = cmcfm()) < 0) return(x);
  5222.         tt_attr_bug = y;
  5223.         return(1);
  5224. #endif /* NT */
  5225.  
  5226. #ifdef OS2
  5227.       case XYTSGRC:
  5228.         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5229.         if ((x = cmcfm()) < 0) return(x);
  5230.         sgrcolors = y;
  5231.         return(1);
  5232.  
  5233.       case XYTSEND:
  5234.           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5235.           if ((x = cmcfm()) < 0) return(x);
  5236.           tt_senddata = y;
  5237.           return(1);
  5238.  
  5239.       case XYTSEOB:
  5240.           if ((y = cmkey(ttyseobtab,2,"","us_cr",xxstring)) < 0) return(y);
  5241.           if ((x = cmcfm()) < 0) return(x);
  5242.           wy_blockend = y;
  5243.           return(1);
  5244.  
  5245.       case XYTURLHI: {
  5246.           int done = 0, attr = VT_CHAR_ATTR_NORMAL;
  5247.  
  5248.           if ((x = cmkey(onoff,2,"","on",xxstring)) < 0)
  5249.             return(x);
  5250.           if (x) {
  5251.               z = 0;
  5252.               while (!done) {
  5253.                   if ((y = cmkey(ttyprotab,nprotect,"",
  5254.                                  z?"done":"reverse",xxstring)) < 0)
  5255.                     return(y);
  5256.                   switch (y) {
  5257.                     case TTATTDONE:
  5258.                       done = TRUE;
  5259.                       break;
  5260.                     case TTATTBLI:
  5261.                       attr |= VT_CHAR_ATTR_BLINK;
  5262.                       break;
  5263.                     case TTATTREV:
  5264.                       attr |= VT_CHAR_ATTR_REVERSE;
  5265.                       break;
  5266.                     case TTATTITA:
  5267.                       attr |= VT_CHAR_ATTR_ITALIC;
  5268.                       break;
  5269.                     case TTATTUND:
  5270.                       attr |= VT_CHAR_ATTR_UNDERLINE;
  5271.                       break;
  5272.                     case TTATTBLD:
  5273.                       attr |= VT_CHAR_ATTR_BOLD;
  5274.                       break;
  5275.                     case TTATTDIM:
  5276.                       attr |= VT_CHAR_ATTR_DIM;
  5277.                       break;
  5278.                     case TTATTINV:
  5279.                       attr |= VT_CHAR_ATTR_INVISIBLE;
  5280.                       break;
  5281.                     case TTATTNOR:
  5282.                       break;
  5283.                   }
  5284.                   z = 1;                /* One attribute has been chosen */
  5285.               }
  5286.           }
  5287.           if ((z = cmcfm()) < 0) return(z);
  5288.           seturlhl(x);
  5289.           if (x)
  5290.             tt_url_hilite_attr = attr;
  5291.           return(1);
  5292.       }
  5293.       case XYTATTR:
  5294.         if ((x = cmkey(ttyattrtab,nattrib,"","underline",xxstring)) < 0)
  5295.           return(x);
  5296.         switch (x) {
  5297.           case TTATTBLI:
  5298.             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5299.             if ((x = cmcfm()) < 0) return(x);
  5300.             trueblink = y;
  5301. #ifndef KUI
  5302.             if ( !trueblink && trueunderline ) {
  5303.                 trueunderline = 0;
  5304.                 printf("Warning: Underline being simulated by color.\n");
  5305.             }
  5306.  
  5307. #endif /* KUI */
  5308.             break;
  5309.  
  5310.           case TTATTDIM:
  5311.             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5312.             if ((x = cmcfm()) < 0) return(x);
  5313.             truedim = y;
  5314.             break;
  5315.  
  5316.           case TTATTREV:
  5317.             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5318.             if ((x = cmcfm()) < 0) return(x);
  5319.             truereverse = y;
  5320.             break;
  5321.  
  5322.           case TTATTUND:
  5323.             if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5324.             if ((x = cmcfm()) < 0) return(x);
  5325.             trueunderline = y;
  5326. #ifndef KUI
  5327.             if (!trueblink && trueunderline) {
  5328.                 trueblink = 1;
  5329.                 printf("Warning: True blink mode is active.\n");
  5330.             }
  5331. #endif /* KUI */
  5332.             break;
  5333.  
  5334.           case TTATTITA:
  5335.               if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5336.               if ((x = cmcfm()) < 0) return(x);
  5337.               trueitalic = y;
  5338.             break;
  5339.  
  5340.           case TTATTPRO: {      /* Set default Protected Character attribute */
  5341.               extern vtattrib WPattrib;    /* current WP Mode Attrib */
  5342.               extern vtattrib defWPattrib; /* default WP Mode Attrib */
  5343.               vtattrib wpa = {0,0,0,0,0,1,0,0,0,0,0};   /* Protected */
  5344.               int done = 0;
  5345.  
  5346.               x = 0;
  5347.               while (!done) {
  5348.                   if ((y = cmkey(ttyprotab,nprotect,"",
  5349.                                  x?"done":"dim",xxstring)) < 0)
  5350.                     return(y);
  5351.                   switch (y) {
  5352.                     case TTATTNOR:
  5353.                       break;
  5354.                     case TTATTBLI:      /* Blinking doesn't work */
  5355.                       wpa.blinking = TRUE;
  5356.                       break;
  5357.                     case TTATTREV:
  5358.                       wpa.reversed = TRUE;
  5359.                       break;
  5360.                     case TTATTITA:
  5361.                       wpa.italic = TRUE;
  5362.                       break;
  5363.                     case TTATTUND:
  5364.                       wpa.underlined = TRUE;
  5365.                       break;
  5366.                     case TTATTBLD:
  5367.                       wpa.bold = TRUE;
  5368.                       break;
  5369.                     case TTATTDIM:
  5370.                       wpa.dim = TRUE;
  5371.                       break;
  5372.                     case TTATTINV:
  5373.                       wpa.invisible = TRUE ;
  5374.                       break;
  5375.                     case TTATTDONE:
  5376.                       done = TRUE;
  5377.                       break;
  5378.                   }
  5379.                   x = 1;                /* One attribute has been chosen */
  5380.               }
  5381.               if ((x = cmcfm()) < 0) return(x);
  5382.               WPattrib = defWPattrib = wpa;
  5383.               break;
  5384.           }
  5385.         }
  5386.         return(1);
  5387.  
  5388.       case XYTKEY: {                    /* SET TERMINAL KEY */
  5389.           int t, x, y;
  5390.           int clear = 0, deflt = 0;
  5391.           int confirmed = 0;
  5392.           int flag = 0;
  5393.           int kc = -1;                  /* Key code */
  5394.           int litstr = 0;               /* Literal String? */
  5395.           char *s = NULL;               /* Key binding */
  5396. #ifndef NOKVERBS
  5397.           char *p = NULL;               /* Worker */
  5398. #endif /* NOKVERBS */
  5399.           con_event defevt;
  5400.           extern int os2gks;
  5401.           extern int mskkeys;
  5402.           extern int initvik;
  5403.           struct FDB kw,sw,nu,cm;
  5404.  
  5405.           defevt.type = error;
  5406.  
  5407.           if ((t = cmkey(ttkeytab,nttkey,"","",xxstring)) < 0)
  5408.             return(t);
  5409.           cmfdbi(&nu,                   /* First FDB - command switches */
  5410.                  _CMNUM,                /* fcode */
  5411.                  "/literal, keycode, or action",
  5412.                  "",                    /* default */
  5413.                  "",                    /* addtl string data */
  5414.                  10,                    /* addtl numeric data 1: radix */
  5415.                  0,                     /* addtl numeric data 2: 0 */
  5416.                  xxstring,              /* Processing function */
  5417.                  NULL,                  /* Keyword table */
  5418.                  &sw                    /* Pointer to next FDB */
  5419.                  );                     /*  */
  5420.           cmfdbi(&sw,                   /* Second FDB - switches */
  5421.                  _CMKEY,                /* fcode */
  5422.                  "",
  5423.                  "",                    /* default */
  5424.                  "",                    /* addtl string data */
  5425.                  nstrmswitab,           /* addtl numeric data 1: tbl size */
  5426.                  4,                     /* addtl numeric data 2: 4 = cmswi */
  5427.                  xxstring,              /* Processing function */
  5428.                  strmswitab,            /* Keyword table */
  5429.                  &kw                    /* Pointer to next FDB */
  5430.                  );
  5431.           cmfdbi(&kw,                   /* Third FDB - command switches */
  5432.                  _CMKEY,                /* fcode */
  5433.                  "/literal, keycode, or action",
  5434.                  "",                    /* default */
  5435.                  "",                    /* addtl string data */
  5436.                  nstrmkeytab,           /* addtl numeric data 1: tbl size */
  5437.                  0,                     /* addtl numeric data 2 */
  5438.                  xxstring,              /* Processing function */
  5439.                  strmkeytab,            /* Keyword table */
  5440.                  &cm                    /* Pointer to next FDB */
  5441.                  );
  5442.           cmfdbi(&cm,                   /* Final FDB - Confirmation */
  5443.                  _CMCFM,                /* fcode */
  5444.                  "",
  5445.                  "",                    /* default */
  5446.                  "",                    /* addtl string data */
  5447.                  0,                     /* addtl numeric data 1: tbl size */
  5448.                  0,                     /* addtl numeric data 2: 4 = cmswi */
  5449.                  xxstring,              /* Processing function */
  5450.                  NULL,                  /* Keyword table */
  5451.                  NULL                   /* Pointer to next FDB */
  5452.                  );
  5453.           while (kc < 0) {
  5454.               x = cmfdb(&nu);           /* Parse something */
  5455.               if (x < 0)
  5456.                 return(x);
  5457.  
  5458.               switch (cmresult.fcode) {
  5459.                 case _CMCFM:
  5460.                   printf(" Press key to be defined: ");
  5461.                   conbin((char)escape); /* Put terminal in binary mode */
  5462.                   os2gks = 0;           /* Turn off Kverb preprocessing */
  5463.                   kc = congks(0);       /* Get character or scan code */
  5464.                   os2gks = 1;           /* Turn on Kverb preprocessing */
  5465.                   concb((char)escape);  /* Restore terminal to cbreak mode */
  5466.                   if (kc < 0) {         /* Check for error */
  5467.                       printf("?Error reading key\n");
  5468.                       return(0);
  5469.                   }
  5470.                   shokeycode(kc,t);     /* Show current definition */
  5471.                   flag = 1;             /* Remember it's a multiline command */
  5472.                   break;
  5473.                 case _CMNUM:
  5474.                   kc = cmresult.nresult;
  5475.                   break;
  5476.                 case _CMKEY:
  5477.                   if (cmresult.fdbaddr == &sw) { /* Switch */
  5478.                       if (cmresult.nresult == 0)
  5479.                         litstr = 1;
  5480.                   } else if (cmresult.fdbaddr == &kw) { /* Keyword */
  5481.                       if (cmresult.nresult == 0)
  5482.                         clear = 1;
  5483.                       else
  5484.                         deflt = 1;
  5485.                       if ((x = cmcfm()) < 0)
  5486.                         return(x);
  5487.                       if (clear)
  5488.                         clearkeymap(t);
  5489.                       else if (deflt)
  5490.                         defaultkeymap(t);
  5491.                       initvik = 1;
  5492.                       return(1);
  5493.                   }
  5494.               }
  5495.           }
  5496.  
  5497.     /* Normal SET TERMINAL KEY <terminal> <scancode> <value> command... */
  5498.  
  5499.           if (mskkeys)
  5500.             kc = msktock(kc);
  5501.  
  5502.           if (kc < 0 || kc >= KMSIZE) {
  5503.               printf("?key code must be between 0 and %d\n", KMSIZE - 1);
  5504.               return(-9);
  5505.           }
  5506.           if (kc == escape) {
  5507.               printf("Sorry, %d is the CONNECT-mode escape character\n",kc);
  5508.               return(-9);
  5509.           }
  5510.           wideresult = -1;
  5511.           if (flag) {
  5512.               cmsavp(psave,PROMPTL);
  5513.               cmsetp(" Enter new definition: ");
  5514.               cmini(ckxech);
  5515.           }
  5516.         def_again:
  5517.           if (flag) prompt(NULL);
  5518.           if ((y = cmtxt("key definition,\n\
  5519.  or Ctrl-C to cancel this command,\n\
  5520.  or Enter to restore default definition",
  5521.                          "",&s,NULL)) < 0) {
  5522.               if (flag)                 /* Handle parse errors */
  5523.                 goto def_again;
  5524.               else
  5525.                 return(y);
  5526.           }
  5527.           s = brstrip(s);
  5528. #ifndef NOKVERBS
  5529.           p = s;                        /* Save this place */
  5530. #endif /* NOKVERBS */
  5531. /*
  5532.   If the definition included any \Kverbs, quote the backslash so the \Kverb
  5533.   will still be in the definition when the key is pressed.  We don't do this
  5534.   in zzstring(), because \Kverbs are valid only in this context and nowhere
  5535.   else.
  5536.  
  5537.   We use this code active for all versions that support SET KEY, even if they
  5538.   don't support \Kverbs, because otherwise \K would behave differently for
  5539.   different versions.
  5540. */
  5541.           for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
  5542.               if ((x > 0) &&
  5543.                   (s[x] == 'K' || s[x] == 'k')
  5544.                   ) {                   /* Have K */
  5545.  
  5546.                   if ((x == 1 && s[x-1] == CMDQ) ||
  5547.                       (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
  5548.                       line[y++] = CMDQ; /* Make it \\K */
  5549.                   }
  5550.                   if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
  5551.                       line[y-1] = CMDQ; /* Have \{K */
  5552.                       line[y++] = '{';  /* Make it \\{K */
  5553.                   }
  5554.               }
  5555.               line[y] = s[x];
  5556.           }
  5557.           line[y++] = NUL;              /* Terminate */
  5558.           s = line + y + 1;             /* Point to after it */
  5559.           x = LINBUFSIZ - (int) strlen(line) - 1; /* Get remaining space */
  5560.           if ((x < (LINBUFSIZ / 2)) ||
  5561.               (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
  5562.               printf("?Key definition too long\n");
  5563.               if (flag) cmsetp(psave);
  5564.               return(-9);
  5565.           }
  5566.           s = line + y + 1;             /* Point to result. */
  5567.  
  5568. #ifndef NOKVERBS
  5569. /*
  5570.   Special case: see if the definition starts with a \Kverb.
  5571.   If it does, point to it with p, otherwise set p to NULL.
  5572. */
  5573.           p = s;
  5574.           if (*p++ == CMDQ) {
  5575.               if (*p == '{') p++;
  5576.               p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
  5577.           }
  5578. #endif /* NOKVERBS */
  5579.  
  5580.           switch (strlen(s)) {          /* Action depends on length */
  5581.             case 0:                     /* Clear individual key def */
  5582.               deletekeymap(t,kc);
  5583.               break;
  5584.             case 1:
  5585.               if (!litstr) {
  5586.                   defevt.type = key;    /* Single character */
  5587.                   defevt.key.scancode = *s;
  5588.                   break;
  5589.               }
  5590.             default:                    /* Character string */
  5591. #ifndef NOKVERBS
  5592.               if (p) {
  5593.                   y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
  5594.                   /* Need exact match */
  5595.                   debug(F101,"set key kverb lookup",0,y);
  5596.                   if (y > -1) {
  5597.                       defevt.type = kverb;
  5598.                       defevt.kverb.id = y;
  5599.                       break;
  5600.                   }
  5601.               }
  5602. #endif /* NOKVERBS */
  5603.               if (litstr) {
  5604.                   defevt.type = literal;
  5605.                   defevt.literal.string = (char *) malloc(strlen(s)+1);
  5606.                   if (defevt.literal.string)
  5607.                     strcpy(defevt.literal.string, s); /* safe */
  5608.               } else {
  5609.                   defevt.type = macro;
  5610.                   defevt.macro.string = (char *) malloc(strlen(s)+1);
  5611.                   if (defevt.macro.string)
  5612.                     strcpy(defevt.macro.string, s); /* safe */
  5613.               }
  5614.               break;
  5615.           }
  5616.           insertkeymap(t, kc, defevt);
  5617.           if (flag)
  5618.             cmsetp(psave);
  5619.           initvik = 1;                  /* Update VIK table */
  5620.           return(1);
  5621.       }
  5622.  
  5623. #ifdef PCTERM
  5624.       case XYTPCTERM:                   /* PCTERM Keyboard Mode */
  5625.         if ((x = seton(&tt_pcterm)) < 0) return(x);
  5626.         return(success = 1);
  5627. #endif /* PCTERM */
  5628. #endif /* OS2 */
  5629.  
  5630. #ifdef CK_TRIGGER
  5631.       case XYTRIGGER:
  5632.         if ((y = cmtxt("String to trigger automatic return to command mode",
  5633.                        "",&s,xxstring)) < 0)
  5634.           return(y);
  5635.         makelist(s,tt_trigger,TRIGGERS);
  5636.         return(1);
  5637. #endif /* CK_TRIGGER */
  5638.  
  5639. #ifdef OS2
  5640.       case XYTSAC:
  5641.         if ((y = cmnum("ASCII value to use for spacing attributes",
  5642.                        "32",10,&x,xxstring)) < 0)
  5643.           return(y);
  5644.         if ((y = cmcfm()) < 0) return(y);
  5645.         tt_sac = x;
  5646.         return(success = 1);
  5647.  
  5648.       case XYTKBDGL: {      /* SET TERM KBD-FOLLOWS-GL/GR */
  5649.           extern int tt_kb_glgr;        /* from ckoco3.c */
  5650.           if ((x = seton(&tt_kb_glgr)) < 0)
  5651.               return(x);
  5652.           return(success = 1);
  5653.       }
  5654. #ifndef NOCSETS
  5655.       case XYTVTLNG:        /* SET TERM DEC-LANGUAGE */
  5656.         if ((y = cmkey(vtlangtab,nvtlangtab,"VT language",
  5657.                        IS97801(tt_type_mode)?"german":"north-american",
  5658.                        xxstring)) < 0)
  5659.           return(y);
  5660.         if ((x = cmcfm()) < 0) return(x);
  5661.  
  5662.         /* A real VT terminal would use the language to set the   */
  5663.         /* default keyboard language for both 8-bit multinational */
  5664.         /* and 7-bit national modes.  For 8-bit mode it would     */
  5665.         /* set the terminal character-set to the ISO set if it    */
  5666.         /* is not already set.                                    */
  5667.         /* Latin-1 can be replaced by DEC Multinational           */
  5668.         switch (y) {
  5669.           case VTL_NORTH_AM:  /* North American */
  5670.             /* Multinational: Latin-1   */
  5671.             /* National:      US_ASCII  */
  5672.             dec_lang = y;
  5673.             dec_nrc = TX_ASCII;
  5674.             dec_kbd = TX_8859_1;
  5675.             break;
  5676.           case VTL_BRITISH :
  5677.             /* Multinational: Latin-1   */
  5678.             /* National:      UK_ASCII  */
  5679.             dec_lang = y;
  5680.             dec_nrc = TX_BRITISH;
  5681.             dec_kbd = TX_8859_1;
  5682.             break;
  5683.           case VTL_FRENCH  :
  5684.           case VTL_BELGIAN :
  5685.           case VTL_CANADIAN:
  5686.             /* Multinational: Latin-1   */
  5687.             /* National:      FR_ASCII  */
  5688.             dec_lang = y;
  5689.             dec_nrc = TX_FRENCH;
  5690.             dec_kbd = TX_8859_1;
  5691.             break;
  5692.           case VTL_FR_CAN  :
  5693.             /* Multinational: Latin-1   */
  5694.             /* National:      FC_ASCII  */
  5695.             dec_lang = y;
  5696.             dec_nrc = TX_CN_FRENCH;
  5697.             dec_kbd = TX_8859_1;
  5698.             break;
  5699.           case VTL_DANISH  :
  5700.           case VTL_NORWEGIA:
  5701.             /* Multinational: Latin-1   */
  5702.             /* National:      NO_ASCII  */
  5703.             dec_lang = y;
  5704.             dec_nrc = TX_NORWEGIAN;
  5705.             dec_kbd = TX_8859_1;
  5706.             break;
  5707.           case VTL_FINNISH :
  5708.             /* Multinational: Latin-1   */
  5709.             /* National:      FI_ASCII  */
  5710.             dec_lang = y;
  5711.             dec_nrc = TX_FINNISH;
  5712.             dec_kbd = TX_8859_1;
  5713.             break;
  5714.           case VTL_GERMAN  :
  5715.             /* Multinational: Latin-1   */
  5716.             /* National:      GR_ASCII  */
  5717.             dec_lang = y;
  5718.             dec_nrc = TX_GERMAN;
  5719.             dec_kbd = TX_8859_1;
  5720.             break;
  5721.           case VTL_DUTCH   :
  5722.             /* Multinational: Latin-1   */
  5723.             /* National:      DU_ASCII  */
  5724.             dec_lang = y;
  5725.             dec_nrc = TX_DUTCH;
  5726.             dec_kbd = TX_8859_1;
  5727.             break;
  5728.           case VTL_ITALIAN :
  5729.             /* Multinational: Latin-1   */
  5730.             /* National:      IT_ASCII  */
  5731.             dec_lang = y;
  5732.             dec_nrc = TX_ITALIAN;
  5733.             dec_kbd = TX_8859_1;
  5734.             break;
  5735.           case VTL_SW_FR   :
  5736.           case VTL_SW_GR   :
  5737.             /* Multinational: Latin-1   */
  5738.             /* National:      CH_ASCII  */
  5739.             dec_lang = y;
  5740.             dec_nrc = TX_SWISS;
  5741.             dec_kbd = TX_8859_1;
  5742.             break;
  5743.           case VTL_SWEDISH :
  5744.             /* Multinational: Latin-1   */
  5745.             /* National:      SW_ASCII  */
  5746.             dec_lang = y;
  5747.             dec_nrc = TX_SWEDISH;
  5748.             dec_kbd = TX_8859_1;
  5749.             break;
  5750.           case VTL_SPANISH :
  5751.             /* Multinational: Latin-1   */
  5752.             /* National:      SP_ASCII  */
  5753.             dec_lang = y;
  5754.             dec_nrc = TX_SPANISH;
  5755.             dec_kbd = TX_8859_1;
  5756.             break;
  5757.           case VTL_PORTUGES:
  5758.             /* Multinational: Latin-1   */
  5759.             /* National:      Portugese ASCII  */
  5760.             dec_lang = y;
  5761.             dec_nrc = TX_PORTUGUESE;
  5762.             dec_kbd = TX_8859_1;
  5763.             break;
  5764.           case VTL_HEBREW  :
  5765.             /* Multinational: Latin-Hebrew / DEC-Hebrew  */
  5766.             /* National:      DEC 7-bit Hebrew  */
  5767.             dec_lang = y;
  5768.             dec_nrc = TX_HE7;
  5769.             dec_kbd = TX_8859_8;
  5770.             break;
  5771.           case VTL_GREEK   :
  5772.             /* Multinational: Latin-Greek / DEC-Greek   */
  5773.             /* National:      DEC Greek NRC             */
  5774.             /* is ELOT927 equivalent to DEC Greek????   */
  5775.             dec_lang = y;
  5776.             dec_nrc = TX_ELOT927;
  5777.             dec_kbd = TX_8859_7;
  5778.             break;
  5779. #ifdef COMMENT
  5780.           case VTL_TURK_Q  :
  5781.           case VTL_TURK_F  :
  5782.             /* Multinational: Latin-Turkish / DEC-Turkish   */
  5783.             /* National:      DEC 7-bit Turkish             */
  5784.             break;
  5785. #endif /* COMMENT */
  5786.           case VTL_HUNGARIA:
  5787.             /* Multinational: Latin-2   */
  5788.             /* National:      no national mode  */
  5789.             dec_lang = y;
  5790.             dec_nrc = TX_HUNGARIAN;
  5791.             dec_kbd = TX_8859_2;
  5792.             break;
  5793.           case VTL_SLOVAK  :
  5794.           case VTL_CZECH   :
  5795.           case VTL_POLISH  :
  5796.           case VTL_ROMANIAN:
  5797.             /* Multinational: Latin-2   */
  5798.             /* National:      no national mode  */
  5799.             dec_lang = y;
  5800.             dec_nrc = TX_ASCII;
  5801.             dec_kbd = TX_8859_2;
  5802.             break;
  5803.           case VTL_RUSSIAN :
  5804.             /* Multinational: Latin-Cyrillic / KOI-8   */
  5805.             /* National:      DEC Russian NRC  */
  5806.             dec_lang = y;
  5807.             dec_nrc = TX_KOI7;
  5808.             dec_kbd = TX_8859_5;
  5809.             break;
  5810.           case VTL_LATIN_AM:
  5811.             /* Multinational: not listed in table   */
  5812.             /* National:      not listed in table  */
  5813.             dec_lang = y;
  5814.             dec_nrc = TX_ASCII;
  5815.             dec_kbd = TX_8859_1;
  5816.             break;
  5817. #ifdef COMMENT
  5818.           case VTL_SCS     :
  5819.             /* Multinational: Latin-2   */
  5820.             /* National:      SCS NRC   */
  5821.             break;
  5822. #endif /* COMMENT */
  5823.           default:
  5824.             return(success = 0);
  5825.         }
  5826.         if (IS97801(tt_type_mode)) {
  5827.             SNI_bitmode(cmask == 0377 ? 8 : 7);
  5828.         }
  5829.         return(success = 1);
  5830. #endif /* NOCSETS */
  5831.  
  5832.       case XYTVTNRC: {                  /* SET TERM DEC-NRC-MODE */
  5833.           extern int decnrcm_usr, decnrcm;        /* from ckoco3.c */
  5834.           if ((x = seton(&decnrcm_usr)) < 0)
  5835.             return(x);
  5836.           decnrcm = decnrcm_usr;
  5837.           return(success = 1);
  5838.       }
  5839.       case XYTSNIPM: {                  /* SET TERM SNI-PAGEMODE */
  5840.           extern int sni_pagemode, sni_pagemode_usr;
  5841.           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5842.           if ((x = cmcfm()) < 0) return(x);
  5843.           sni_pagemode_usr = sni_pagemode = y;
  5844.           return(success = 1);
  5845.       }
  5846.       case XYTSNISM: {                  /* SET TERM SNI-SCROLLMODE */
  5847.           extern int sni_scroll_mode, sni_scroll_mode_usr;
  5848.           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5849.           if ((x = cmcfm()) < 0) return(x);
  5850.           sni_scroll_mode_usr = sni_scroll_mode = y;
  5851.           return(success = 1);
  5852.       }
  5853.       case XYTSNICC: {  /* SET TERM SNI-CH.CODE */
  5854.           extern int sni_chcode_usr;
  5855.           if ((y = cmkey(onoff,2,"","on",xxstring)) < 0) return(y);
  5856.           if ((x = cmcfm()) < 0) return(x);
  5857.           sni_chcode_usr = y;
  5858.           SNI_chcode(y);
  5859.           return(success = 1);
  5860.       }
  5861.       case XYTSNIFV: {  /* SET TERM SNI-FIRMWARE-VERSIONS */
  5862.           extern CHAR sni_kbd_firmware[], sni_term_firmware[];
  5863.           CHAR kbd[7],term[7];
  5864.  
  5865.           if ((x = cmfld("Keyboard Firmware Version",sni_kbd_firmware,
  5866.                          &s, xxstring)) < 0)
  5867.             return(x);
  5868.           if ((int)strlen(s) != 6) {
  5869.               printf("?Sorry - the firmware version must be 6 digits long\n");
  5870.               return(-9);
  5871.           }
  5872.           for (i = 0; i < 6; i++) {
  5873.               if (!isdigit(s[i])) {
  5874.    printf("?Sorry - the firmware version can only contain digits [0-9]\n");
  5875.                   return(-9);
  5876.               }
  5877.           }
  5878.           ckstrncpy(kbd,s,7);
  5879.  
  5880.           if ((x = cmfld("Terminal Firmware Version",sni_term_firmware,
  5881.                          &s, xxstring)) < 0)
  5882.             return(x);
  5883.           if ((int)strlen(s) != 6) {
  5884.               printf("?Sorry - the firmware version must be 6 digits long\n");
  5885.               return(-9);
  5886.           }
  5887.           for (i = 0; i < 6; i++) {
  5888.               if (!isdigit(s[i])) {
  5889.    printf("?Sorry - the firmware version can only contain digits [0-9]\n");
  5890.                    return(-9);
  5891.               }
  5892.           }
  5893.           ckstrncpy(term,s,7);
  5894.           if ((x = cmcfm()) < 0) return(x);
  5895.  
  5896.           ckstrncpy(sni_kbd_firmware,kbd,7);
  5897.           ckstrncpy(sni_term_firmware,term,7);
  5898.           return(success = 1);
  5899.     }
  5900.  
  5901.     case XYTLSP: {              /* SET TERM LINE-SPACING */
  5902.         if ((x = cmfld("Line Spacing","1",&s, xxstring)) < 0)
  5903.           return(x);
  5904.         if (isfloat(s,0) < 1) {        /* (sets floatval) */
  5905.             printf("?Integer or floating-point number required\n");
  5906.             return(-9);
  5907.         }
  5908.         if (floatval < 1.0 || floatval > 3.0) {
  5909.             printf("?Value must within the range 1.0 and 3.0 (inclusive)\n");
  5910.             return(-9);
  5911.         }
  5912.         if ((x = cmcfm()) < 0) return(x);
  5913. #ifdef KUI
  5914.         tt_linespacing[VCMD] = tt_linespacing[VTERM] = floatval;
  5915.         return(success = 1);
  5916. #else /* KUI */
  5917.         printf("?Sorry, Line-spacing is only supported in K95G.EXE.\n");
  5918.         return(success = 0);
  5919. #endif /* KUI */
  5920.     }
  5921. #endif /* OS2 */
  5922.  
  5923.       default:                          /* Shouldn't get here. */
  5924.         return(-2);
  5925.     }
  5926. #endif /* MAC */
  5927. #ifdef COMMENT
  5928.     /*
  5929.       This was supposed to shut up picky compilers but instead it makes
  5930.       most compilers complain about "statement not reached".
  5931.     */
  5932.     return(-2);
  5933. #endif /* COMMENT */
  5934. #ifdef OS2
  5935.     return(-2);
  5936. #endif /* OS2 */
  5937. }
  5938.  
  5939. #ifdef OS2
  5940. int
  5941. settitle(void) {
  5942.     extern char usertitle[];
  5943.     if ((y = cmtxt("title text","",&s,xxstring)) < 0)
  5944.       return(y);
  5945. #ifdef IKSD
  5946.     if (inserver) {
  5947.         printf("?Sorry, command disabled.\r\n");
  5948.         return(success = 0);
  5949.     }
  5950. #endif /* IKSD */
  5951.     s = brstrip(s);
  5952.     ckstrncpy(usertitle,s,64);
  5953.     os2settitle("",1);
  5954.     return(1);
  5955. }
  5956.  
  5957. static struct keytab dialertab[] = {    /* K95 Dialer types */
  5958.     "backspace",        0, 0,
  5959.     "enter",            1, 0
  5960. };
  5961. static int ndialer = 2;
  5962.  
  5963. int
  5964. setdialer(void) {
  5965.     int t, x, y;
  5966.     int clear = 0, deflt = 0;
  5967.     int kc;                             /* Key code */
  5968.     char *s = NULL;                     /* Key binding */
  5969. #ifndef NOKVERBS
  5970.     char *p = NULL;                     /* Worker */
  5971. #endif /* NOKVERBS */
  5972.     con_event defevt;
  5973.     extern int os2gks;
  5974.     extern int mskkeys;
  5975.     extern int initvik;
  5976.  
  5977.     defevt.type = error;
  5978.  
  5979.     if (( x = cmkey(dialertab, ndialer,
  5980.                     "Kermit-95 dialer work-arounds",
  5981.                     "", xxstring)) < 0 )
  5982.       return(x);
  5983.     switch (x) {
  5984.       case 0:                           /* Backspace */
  5985.         kc = 264;
  5986.         break;
  5987.       case 1:                           /* Enter */
  5988.         kc = 269;
  5989.         break;
  5990.       default:
  5991.         printf("Illegal value in setdialer()\n");
  5992.         return(-9);
  5993.     }
  5994.     if ((y = cmtxt("Key definition","",&s,xxstring)) < 0)
  5995.       return(y);
  5996.  
  5997. #ifdef IKSD
  5998.     if (inserver) {
  5999.         printf("?Sorry, command disabled.\r\n");
  6000.         return(success = 0);
  6001.     }
  6002. #endif /* IKSD */
  6003.     s = brstrip(s);
  6004. #ifndef NOKVERBS
  6005.     p = s;                              /* Save this place */
  6006. #endif /* NOKVERBS */
  6007. /*
  6008.   If the definition included any \Kverbs, quote the backslash so the \Kverb
  6009.   will still be in the definition when the key is pressed.  We don't do this
  6010.   in zzstring(), because \Kverbs are valid only in this context and nowhere
  6011.   else.
  6012.  
  6013.   We use this code active for all versions that support SET KEY, even if they
  6014.   don't support \Kverbs, because otherwise \K would behave differently for
  6015.   different versions.
  6016. */
  6017.     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
  6018.         if ((x > 0) &&
  6019.             (s[x] == 'K' || s[x] == 'k')
  6020.             ) {                         /* Have K */
  6021.  
  6022.             if ((x == 1 && s[x-1] == CMDQ) ||
  6023.                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
  6024.                 line[y++] = CMDQ;       /* Make it \\K */
  6025.             }
  6026.             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
  6027.                 line[y-1] = CMDQ;       /* Have \{K */
  6028.                 line[y++] = '{';        /* Make it \\{K */
  6029.             }
  6030.         }
  6031.         line[y] = s[x];
  6032.     }
  6033.     line[y++] = NUL;                    /* Terminate */
  6034.     s = line + y + 1;                   /* Point to after it */
  6035.     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
  6036.     if ((x < (LINBUFSIZ / 2)) ||
  6037.         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
  6038.         printf("?Key definition too long\n");
  6039.         return(-9);
  6040.     }
  6041.     s = line + y + 1;                   /* Point to result. */
  6042.  
  6043. #ifndef NOKVERBS
  6044. /*
  6045.   Special case: see if the definition starts with a \Kverb.
  6046.   If it does, point to it with p, otherwise set p to NULL.
  6047. */
  6048.     p = s;
  6049.     if (*p++ == CMDQ) {
  6050.         if (*p == '{') p++;
  6051.         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
  6052.     }
  6053. #endif /* NOKVERBS */
  6054.  
  6055.     /* Clear the definition for SET KEY */
  6056.     if (macrotab[kc]) {                 /* Possibly free old macro from key. */
  6057.         free((char *)macrotab[kc]);
  6058.         macrotab[kc] = NULL;
  6059.     }
  6060.     keymap[kc] = (KEY) kc;
  6061.  
  6062.     /* Now reprogram the default value for all terminal types */
  6063.     /* remember to treat Wyse and Televideo terminals special */
  6064.     /* because of their use of Kverbs for Backspace and Enter */
  6065.     for (t = 0; t <= TT_MAX; t++) {
  6066.         if ( ISDG200(t) && kc == 264) {
  6067.             extern char * udkfkeys[] ;
  6068.             if (kc == 264) {            /* \Kdgbs */
  6069.                 if (udkfkeys[83])
  6070.                   free(udkfkeys[83]);
  6071.                 udkfkeys[83] = strdup(s);
  6072.             }
  6073.         } else if (ISWYSE(t) || ISTVI(t)) {
  6074.             extern char * udkfkeys[] ;
  6075.             if (kc == 264) {            /* \Kwybs or \Ktvibs */
  6076.                 if (udkfkeys[32])
  6077.                   free(udkfkeys[32]);
  6078.                 udkfkeys[32] = strdup(s);
  6079.             }
  6080.             if (kc == 269) {            /* \Kwyenter and \Kwyreturn */
  6081.                 if (udkfkeys[39])       /* \Ktvienter and \Ktvireturn */
  6082.                   free(udkfkeys[39]);
  6083.                 udkfkeys[39] = strdup(s);
  6084.                 if (udkfkeys[49])
  6085.                   free(udkfkeys[49]);
  6086.                 udkfkeys[49] = strdup(s);
  6087.             }
  6088.         } else {
  6089.             switch (strlen(s)) {        /* Action depends on length */
  6090.               case 0:                   /* Clear individual key def */
  6091.                 deletekeymap(t,kc);
  6092.                 break;
  6093.               case 1:
  6094.                 defevt.type = key;      /* Single character */
  6095.                 defevt.key.scancode = *s;
  6096.                 break;
  6097.               default:                  /* Character string */
  6098. #ifndef NOKVERBS
  6099.                 if (p) {
  6100.                     y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
  6101.                     /* Exact match req'd */
  6102.                     debug(F101,"set key kverb lookup",0,y);
  6103.                     if (y > -1) {
  6104.                         defevt.type = kverb;
  6105.                         defevt.kverb.id = y;
  6106.                         break;
  6107.                     }
  6108.                 }
  6109. #endif /* NOKVERBS */
  6110.                 defevt.type = macro;
  6111.                 defevt.macro.string = (char *) malloc(strlen(s)+1);
  6112.                 if (defevt.macro.string)
  6113.                   strcpy(defevt.macro.string, s); /* safe */
  6114.                 break;
  6115.             }
  6116.             insertkeymap( t, kc, defevt ) ;
  6117.             initvik = 1;                /* Update VIK table */
  6118.         }
  6119.     }
  6120.     return(1);
  6121. }
  6122. #endif /* OS2 */
  6123.  
  6124. #ifdef NT
  6125. int
  6126. setwin95( void ) {
  6127.     int x, y, z;
  6128.  
  6129.     if (( y = cmkey(win95tab, nwin95,
  6130.                     "Windows 95 specific work-arounds",
  6131.                     "keyboard-translation",
  6132.                     xxstring)) < 0 )
  6133.         return (y);
  6134.     switch (y) {
  6135.       case XYWPOPUP:
  6136.         if ((y = cmkey(onoff,2,"popups are used to prompt the user for data",
  6137.                        "on",xxstring)) < 0)
  6138.           return(y);
  6139.         if ((x = cmcfm()) < 0) return(x);
  6140.         win95_popup = y;
  6141.         return(1);
  6142.  
  6143.       case XYW8_3:
  6144.         if ((y = cmkey(onoff,2,"8.3 FAT file names","off",xxstring)) < 0)
  6145.           return(y);
  6146.         if ((x = cmcfm()) < 0) return(x);
  6147.         win95_8_3 = y;
  6148.         return(1);
  6149.  
  6150.       case XYWSELECT:
  6151.         if ((y = cmkey(onoff,2,"\"select()\" fails on write","off",
  6152.              xxstring)) < 0)
  6153.           return(y);
  6154.         if ((x = cmcfm()) < 0) return(x);
  6155.         win95selectbug = y;
  6156.         return(1);
  6157.  
  6158.       case XYWAGR:
  6159.         if ((y = cmkey(onoff,2,"Right-Alt is Alt-Gr","off",xxstring)) < 0)
  6160.           return(y);
  6161.         if ((x = cmcfm()) < 0) return(x);
  6162.         win95altgr = y;
  6163.         return(1);
  6164.  
  6165.       case XYWOIO:
  6166.         if ((y = cmkey(onoff,2,"Use Overlapped I/O","on",xxstring)) < 0)
  6167.           return(y);
  6168.         if (y) {
  6169.             if ((x = cmnum("Maximum number of outstanding I/O requests",
  6170.                            "10",10,&z,xxstring)) < 0)
  6171.               return(x);
  6172.             if (z < 1 || z > 7) {
  6173.                 printf(
  6174. "?Maximum outstanding I/O requests must be between 1 and 7.\n");
  6175.                 return(-9);
  6176.             }
  6177.         } else
  6178.           z = 1;
  6179.         if ((x = cmcfm()) < 0) return(x);
  6180.         owwait = !y;
  6181.         maxow = maxow_usr = z;
  6182.         return(1);
  6183.  
  6184.       case XYWKEY:
  6185. #ifndef COMMENT
  6186.         printf("\n?\"Keyboard-Translation\" is no longer required.\n");
  6187.         return(-9);
  6188. #else /* COMMENT */
  6189.         if (( z = cmkey(tcstab, ntcs,
  6190.                         "Keyboard Character Set",
  6191.                         "latin1-iso",
  6192.                         xxstring)) < 0)
  6193.           return (z);
  6194.         if ((x = cmcfm()) < 0)
  6195.           return(x);
  6196.  
  6197.         win95kcsi = z;
  6198.         win95kl2 = (win95kcsi == TC_2LATIN);
  6199.  
  6200.         if (win95kcsi == TC_TRANSP) {
  6201.             win95kcs = NULL;
  6202.         } else {
  6203. #ifdef UNICODE
  6204.             win95kcs = xlr[win95kcsi][tx2fc(tcsl)];
  6205. #else /* UNICODE */
  6206.             win95kcs = xlr[win95kcsi][tcsl];
  6207. #endif /* UNICODE */
  6208.         }
  6209.         return(1);
  6210. #endif /* COMMENT */
  6211.  
  6212.       case XYWLUC:
  6213.         if ((y = cmkey(onoff,2,"Unicode-to-Lucida-Console substitutions",
  6214.                        "on",xxstring)) < 0)
  6215.           return(y);
  6216.         if ((x = cmcfm()) < 0) return(x);
  6217.         win95lucida = y;
  6218.         return(1);
  6219.  
  6220.       case XYWHSL:
  6221.     if ((y = cmkey(onoff,2,"Horizontal Scan Line substitutions",
  6222.                "on",xxstring)) < 0)
  6223.       return(y);
  6224.     if ((x = cmcfm()) < 0) return(x);
  6225.     win95hsl = y;
  6226.     return(1);
  6227.  
  6228.       default:
  6229.         printf("Illegal value in setwin95()\n");
  6230.         return(-9);
  6231.     }
  6232. }
  6233. #endif /* NT */
  6234.  
  6235. #ifdef OS2
  6236. int
  6237. setprty (
  6238. #ifdef CK_ANSIC
  6239.     void
  6240. #endif /* CK_ANSIC */
  6241. /* setprty */ ) {
  6242.     int x, y, z;
  6243.  
  6244.     if (( y = cmkey(prtytab, nprty,
  6245.                     "priority level of terminal and communication threads",
  6246.                     "foreground-server",
  6247.                     xxstring)) < 0 )
  6248.       return (y);
  6249.  
  6250.     if ((x = cmcfm()) < 0)
  6251.       return (x);
  6252. #ifdef IKSD
  6253.     if (inserver &&
  6254. #ifdef IKSDCONF
  6255.          iksdcf
  6256. #else
  6257.          1
  6258. #endif /* IKSDCONF */
  6259.     ) {
  6260.         if ((y = cmcfm()) < 0) return(y);
  6261.         printf("?Sorry, command disabled.\r\n");
  6262.         return(success = 0);
  6263.     }
  6264. #endif /* IKSD */
  6265.     priority = y;
  6266.     return(TRUE);
  6267. }
  6268. #endif /* OS2 */
  6269.  
  6270. int
  6271. setbell() {
  6272.     int y, x;
  6273. #ifdef OS2
  6274.     int z;
  6275. #endif /* OS2 */
  6276.  
  6277.     if ((y = cmkey(beltab,nbeltab,
  6278. #ifdef OS2
  6279.         "how console and terminal bells should\nbe generated", "audible",
  6280. #else
  6281.         "Whether Kermit should ring the terminal bell (beep)", "on",
  6282. #endif /* OS2 */
  6283.                    xxstring)) < 0)
  6284.           return(y);
  6285.  
  6286. #ifdef IKSD
  6287.     if (inserver) {
  6288.         if ((y = cmcfm()) < 0) return(y);
  6289.         printf("?Sorry, command disabled.\r\n");
  6290.         return(success = 0);
  6291.     }
  6292. #endif /* IKSD */
  6293.  
  6294.     switch (y) {                        /* SET BELL */
  6295.       case XYB_NONE:
  6296. #ifdef OS2
  6297.       case XYB_VIS:
  6298. #endif /* OS2 */
  6299.         if ((x = cmcfm()) < 0)
  6300.           return(x);
  6301. #ifdef OS2
  6302.         tt_bell = y;
  6303. #else
  6304.         tt_bell = 0;
  6305. #endif /* OS2 */
  6306.         break;
  6307.  
  6308.       case XYB_AUD:
  6309. #ifdef OS2
  6310.         if ((x = cmkey(audibletab, naudibletab,
  6311.                "how audible console and terminal\nbells should be generated",
  6312.                        "beep",xxstring))<0)
  6313.           return(x);
  6314.         if ((z = cmcfm()) < 0)
  6315.           return(z);
  6316.         tt_bell = y | x;
  6317. #else
  6318.         /* This lets C-Kermit accept but ignore trailing K95 keywords */
  6319.         if ((x = cmtxt("Confirm with carriage return","",&s,xxstring)) < 0)
  6320.           return(x);
  6321.         tt_bell = 1;
  6322. #endif /* OS2 */
  6323.         break;
  6324.     }
  6325.     return(1);
  6326. }
  6327.  
  6328. #ifdef OS2MOUSE
  6329. int
  6330. setmou(
  6331. #ifdef CK_ANSIC
  6332.        void
  6333. #endif /* CK_ANSIC */
  6334.  /* setmou */ ) {
  6335.     extern int initvik;
  6336.     int button = 0, event = 0;
  6337.     char * p;
  6338.  
  6339.     if ((y = cmkey(mousetab,nmtab,"","",xxstring)) < 0)
  6340.       return(y);
  6341.  
  6342. #ifdef IKSD
  6343.     if (inserver) {
  6344.         if ((y = cmcfm()) < 0) return(y);
  6345.         printf("?Sorry, command disabled.\r\n");
  6346.         return(success = 0);
  6347.     }
  6348. #endif /* IKSD */
  6349.  
  6350.     if (y == XYM_ON) {                  /* MOUSE ACTIVATION */
  6351.         int old_mou = tt_mouse;
  6352.         if ((x = seton(&tt_mouse)) < 0)
  6353.             return(x);
  6354.         if (tt_mouse != old_mou)
  6355.           if (tt_mouse)
  6356.             os2_mouseon();
  6357.           else
  6358.             os2_mouseoff();
  6359.         return(1);
  6360.     }
  6361.  
  6362.     if (y == XYM_DEBUG) {               /* MOUSE DEBUG */
  6363.         extern int MouseDebug;
  6364.         if ((x = seton(&MouseDebug)) < 0)
  6365.             return(x);
  6366.         return(1);
  6367.     }
  6368.  
  6369.     if (y == XYM_CLEAR) {               /* Reset Mouse Defaults */
  6370.         if ((x = cmcfm()) < 0) return(x);
  6371.         mousemapinit(-1,-1);
  6372.         initvik = 1;                    /* Update VIK Table */
  6373.         return 1;
  6374.     }
  6375.     if (y != XYM_BUTTON) {              /* Shouldn't happen. */
  6376.         printf("Internal parsing error\n");
  6377.         return(-9);
  6378.     }
  6379.  
  6380.     /* MOUSE EVENT ... */
  6381.  
  6382.     if ((button = cmkey(mousebuttontab,nmbtab,
  6383.                         "Button number","1",
  6384.                         xxstring)) < 0)
  6385.       return(button);
  6386.  
  6387.     if ((y =  cmkey(mousemodtab,nmmtab,
  6388.                     "Keyboard modifier","none",
  6389.                     xxstring)) < 0)
  6390.       return(y);
  6391.  
  6392.     event |= y;                         /* OR in the bits */
  6393.  
  6394.     if ((y =  cmkey(mclicktab,nmctab,"","click",xxstring)) < 0)
  6395.       return(y);
  6396.  
  6397.     /* Two bits are assigned, if neither are set then it is button one */
  6398.  
  6399.     event |= y;                 /* OR in the bit */
  6400.  
  6401.     wideresult = -1;
  6402.  
  6403.     if ((y = cmtxt("definition,\n\
  6404. or Ctrl-C to cancel this command,\n\
  6405. or Enter to restore default definition",
  6406.                    "",&s,NULL)) < 0) {
  6407.         return(y);
  6408.     }
  6409.     s = brstrip(s);
  6410.     p = s;                              /* Save this place */
  6411. /*
  6412.   If the definition included any \Kverbs, quote the backslash so the \Kverb
  6413.   will still be in the definition when the key is pressed.  We don't do this
  6414.   in zzstring(), because \Kverbs are valid only in this context and nowhere
  6415.   else.  This code copied from SET KEY, q.v. for addt'l commentary.
  6416. */
  6417.     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \K to \\K */
  6418.         if ((x > 0) &&
  6419.             (s[x] == 'K' || s[x] == 'k')
  6420.             ) {                         /* Have K */
  6421.  
  6422.             if ((x == 1 && s[x-1] == CMDQ) ||
  6423.                 (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ)) {
  6424.                 line[y++] = CMDQ;       /* Make it \\K */
  6425.             }
  6426.             if (x > 1 && s[x-1] == '{' && s[x-2] == CMDQ) {
  6427.                 line[y-1] = CMDQ;       /* Have \{K */
  6428.                 line[y++] = '{';        /* Make it \\{K */
  6429.             }
  6430.         }
  6431.         line[y] = s[x];
  6432.     }
  6433.     line[y++] = NUL;                    /* Terminate */
  6434.     s = line + y + 1;                   /* Point to after it */
  6435.     x = LINBUFSIZ - (int) strlen(line) - 1; /* Calculate remaining space */
  6436.     if ((x < (LINBUFSIZ / 2)) ||
  6437.         (zzstring(line, &s, &x) < 0)) { /* Expand variables, etc. */
  6438.         printf("?Key definition too long\n");
  6439.         return(-9);
  6440.     }
  6441.     s = line + y + 1;                   /* Point to result. */
  6442.  
  6443. #ifndef NOKVERBS
  6444. /*
  6445.   Special case: see if the definition starts with a \Kverb.
  6446.   If it does, point to it with p, otherwise set p to NULL.
  6447. */
  6448.     p = s;
  6449.     if (*p++ == CMDQ) {
  6450.         if (*p == '{') p++;
  6451.         p = (*p == 'k' || *p == 'K') ? p + 1 : NULL;
  6452.     }
  6453. #else
  6454.     p = NULL;
  6455. #endif /* NOKVERBS */
  6456.  
  6457.     /* free the old definition if necessary */
  6458.     if (mousemap[button][event].type == macro) {
  6459.         free( mousemap[button][event].macro.string);
  6460.         mousemap[button][event].macro.string = NULL;
  6461.     }
  6462.     switch (strlen(s)) {                /* Action depends on length */
  6463.       case 0:                           /* Reset to default binding */
  6464.         mousemapinit( button, event );
  6465.         break;
  6466.       case 1:                           /* Single character */
  6467.             mousemap[button][event].type = key;
  6468.         mousemap[button][event].key.scancode = *s;
  6469.         break;
  6470.       default:                          /* Character string */
  6471. #ifndef NOKVERBS
  6472.         if (p) {
  6473.             y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
  6474.             debug(F101,"set mouse kverb lookup",0,y); /* need exact match */
  6475.             if (y > -1) {
  6476.             /* Assign the kverb to the event */
  6477.             mousemap[button][event].type = kverb;
  6478.             mousemap[button][event].kverb.id = F_KVERB | y;
  6479.             break;
  6480.             }
  6481.         }
  6482. #endif /* NOKVERBS */
  6483.  
  6484.        /* Otherwise, it's a macro, so assign the macro to the event */
  6485.        mousemap[button][event].type = macro;
  6486.        mousemap[button][event].macro.string = (MACRO) malloc(strlen(s)+1);
  6487.        if (mousemap[button][event].macro.string)
  6488.          strcpy((char *) mousemap[button][event].macro.string, s); /* safe */
  6489.         break;
  6490.     }
  6491.     initvik = 1;                        /* Update VIK Table */
  6492.     if ( (button == XYM_B3) && (mousebuttoncount() < 3) && !quiet )
  6493.     {
  6494.         printf("?Warning: this machine does not have a three button mouse.\n");
  6495.         return(0);
  6496.     }
  6497.     return(1);
  6498. }
  6499. #endif /* OS2MOUSE */
  6500. #endif /* NOLOCAL */
  6501.  
  6502. #ifndef NOXFER
  6503. int                                     /* SET SEND/RECEIVE */
  6504. setsr(xx, rmsflg) int xx; int rmsflg; {
  6505.     if (xx == XYRECV)
  6506.       ckstrncpy(line,"Parameter for inbound packets",LINBUFSIZ);
  6507.     else
  6508.       ckstrncpy(line,"Parameter for outbound packets",LINBUFSIZ);
  6509.  
  6510.     if (rmsflg) {
  6511.         if ((y = cmkey(rsrtab,nrsrtab,line,"",xxstring)) < 0) {
  6512.             if (y == -3) {
  6513.                 printf("?Remote receive parameter required\n");
  6514.                 return(-9);
  6515.             } else return(y);
  6516.         }
  6517.     } else {
  6518.         if ((y = cmkey(srtab,nsrtab,line,"",xxstring)) < 0) return(y);
  6519.     }
  6520.     switch (y) {
  6521.       case XYQCTL:                      /* CONTROL-PREFIX */
  6522.         if ((x = cmnum("ASCII value of control prefix","",10,&y,xxstring)) < 0)
  6523.           return(x);
  6524.         if ((x = cmcfm()) < 0) return(x);
  6525.         if ((y > 32 && y < 63) || (y > 95 && y < 127)) {
  6526.             if (xx == XYRECV)
  6527.               ctlq = (CHAR) y;          /* RECEIVE prefix, use with caution! */
  6528.             else
  6529.               myctlq = (CHAR) y;        /* SEND prefix, OK to change */
  6530.             return(success = 1);
  6531.         } else {
  6532.             printf("?Illegal value for prefix character\n");
  6533.             return(-9);
  6534.         }
  6535.  
  6536.       case XYEOL:
  6537.         if ((y = setcc("13",&z)) < 0)
  6538.             return(y);
  6539.         if (z > 31) {
  6540.             printf("Sorry, the legal values are 0-31\n");
  6541.             return(-9);
  6542.         }
  6543.         if (xx == XYRECV)
  6544.           eol = (CHAR) z;
  6545.         else
  6546.           seol = (CHAR) z;
  6547.         return(success = y);
  6548.  
  6549.       case XYLEN:
  6550.         y = cmnum("Maximum number of characters in a packet","90",10,&x,
  6551.                   xxstring);
  6552.         if (xx == XYRECV) {             /* Receive... */
  6553.             if ((y = setnum(&z,x,y,maxrps)) < 0)
  6554.               return(y);
  6555.             if (protocol != PROTO_K) {
  6556.                 printf("?Sorry, this command does not apply to %s protocol.\n",
  6557.                        ptab[protocol].p_name
  6558.                        );
  6559.                 printf("Use SET SEND PACKET-LENGTH for XYZMODEM\n");
  6560.                 return(-9);
  6561.             }
  6562.             if (z < 10) {
  6563.                 printf("Sorry, 10 is the minimum\n");
  6564.                 return(-9);
  6565.             }
  6566.             if (rmsflg) {
  6567.                 sstate = setgen('S', "401", ckitoa(z), "");
  6568.                 return((int) sstate);
  6569.             } else {
  6570.                 if (protocol == PROTO_K) {
  6571.                     if (z > MAXRP) z = MAXRP;
  6572.                     y = adjpkl(z,wslotr,bigrbsiz);
  6573.                     if (y != z) {
  6574.                         urpsiz = y;
  6575.                         if (!xcmdsrc)
  6576.                           if (msgflg) printf(
  6577. " Adjusting receive packet-length to %d for %d window slots\n",
  6578.                                              y, wslotr);
  6579.                     }
  6580.                     urpsiz = y;
  6581.                     ptab[protocol].rpktlen = urpsiz;
  6582.                     rpsiz =  (y > 94) ? 94 : y;
  6583.                 } else {
  6584. #ifdef CK_XYZ
  6585.                     if ((protocol == PROTO_X || protocol == PROTO_XC) &&
  6586.                          z != 128 && z != 1024) {
  6587.                         printf("Sorry, bad packet length for XMODEM.\n");
  6588.                         printf("Please use 128 or 1024.\n");
  6589.                         return(-9);
  6590.                     }
  6591. #endif /* CK_XYZ */
  6592.                     urpsiz = rpsiz = z;
  6593.                 }
  6594.             }
  6595.         } else {                        /* Send... */
  6596.             if ((y = setnum(&z,x,y,maxsps)) < 0)
  6597.               return(y);
  6598.             if (z < 10) {
  6599.                 printf("Sorry, 10 is the minimum\n");
  6600.                 return(-9);
  6601.             }
  6602.             if (protocol == PROTO_K) {
  6603.                 if (z > MAXSP) z = MAXSP;
  6604.                 spsiz = z;              /* Set it */
  6605.                 y = adjpkl(spsiz,wslotr,bigsbsiz);
  6606.                 if (y != spsiz && !xcmdsrc)
  6607.                   if (msgflg)
  6608.                     printf("Adjusting packet size to %d for %d window slots\n",
  6609.                            y,wslotr);
  6610.             } else
  6611.               y = z;
  6612. #ifdef CK_XYZ
  6613.             if ((protocol == PROTO_X || protocol == PROTO_XC) &&
  6614.                  z != 128 && z != 1024) {
  6615.                 printf("Sorry, bad packet length for XMODEM.\n");
  6616.                 printf("Please use 128 or 1024.\n");
  6617.                 return(-9);
  6618.             }
  6619. #endif /* CK_XYZ */
  6620.             spsiz = spmax = spsizr = y; /* Set it and flag that it was set */
  6621.             spsizf = 1;                 /* to allow overriding Send-Init. */
  6622.             ptab[protocol].spktflg = spsizf;
  6623.             ptab[protocol].spktlen = spsiz;
  6624.         }
  6625.         if (pflag && protocol == PROTO_K && !xcmdsrc) {
  6626.             if (z > 94 && !reliable && msgflg) {
  6627.                 /* printf("Extended-length packets requested.\n"); */
  6628.                 if (bctr < 2 && z > 200) printf("\
  6629. Remember to SET BLOCK 2 or 3 for long packets.\n");
  6630.             }
  6631.             if (speed <= 0L) speed = ttgspd();
  6632. #ifdef COMMENT
  6633. /*
  6634.   Kermit does this now itself.
  6635. */
  6636.             if (speed <= 0L && z > 200 && msgflg) {
  6637.                 printf("\
  6638. Make sure your timeout interval is long enough for %d-byte packets.\n",z);
  6639.             }
  6640. #endif /* COMMENT */
  6641.         }
  6642.         return(success = y);
  6643.  
  6644.       case XYMARK:
  6645. #ifdef DOOMSDAY
  6646. /*
  6647.   Printable start-of-packet works for UNIX and VMS only!
  6648. */
  6649.         x_ifnum = 1;
  6650.         y = cmnum("Code for packet-start character","1",10,&x,xxstring);
  6651.         x_ifnum = 0;
  6652.         if ((y = setnum(&z,x,y,126)) < 0) return(y);
  6653. #else
  6654.         if ((y = setcc("1",&z)) < 0)
  6655.             return(y);
  6656. #endif /* DOOMSDAY */
  6657.         if (xx == XYRECV)
  6658.           stchr = (CHAR) z;
  6659.         else {
  6660.             mystch = (CHAR) z;
  6661. #ifdef IKS_OPTION
  6662.             /* If IKS negotiation in use   */
  6663.             if (TELOPT_U(TELOPT_KERMIT) || TELOPT_ME(TELOPT_KERMIT))
  6664.               tn_siks(KERMIT_SOP);      /* Report change to other side */
  6665. #endif /* IKS_OPTION */
  6666.         }
  6667.         return(success = y);
  6668.  
  6669.       case XYNPAD:                      /* PADDING */
  6670.         y = cmnum("How many padding characters for inbound packets","0",10,&x,
  6671.                   xxstring);
  6672.         if ((y = setnum(&z,x,y,94)) < 0) return(y);
  6673.         if (xx == XYRECV)
  6674.           mypadn = (CHAR) z;
  6675.         else
  6676.           npad = (CHAR) z;
  6677.         return(success = y);
  6678.  
  6679.       case XYPADC:                      /* PAD-CHARACTER */
  6680.         if ((y = setcc("0",&z)) < 0) return(y);
  6681.         if (xx == XYRECV) mypadc = z; else padch = z;
  6682.         return(success = y);
  6683.  
  6684.       case XYTIMO:                      /* TIMEOUT */
  6685.         if (xx == XYRECV) {
  6686.             y = cmnum("Packet timeout interval",ckitoa(URTIME),10,&x,xxstring);
  6687.             if ((y = setnum(&z,x,y,94)) < 0) return(y);
  6688.  
  6689.             if (rmsflg) {               /* REMOTE SET RECEIVE TIMEOUT */
  6690.                 sstate = setgen('S', "402", ckitoa(z), "");
  6691.                 return((int) sstate);
  6692.             } else {                    /* SET RECEIVE TIMEOUT */
  6693.                 pkttim = z;             /*   Value to put in my negotiation */
  6694.             }                           /*   packet for other Kermit to use */
  6695.  
  6696.         } else {                        /* SET SEND TIMEOUT */
  6697. #ifdef CK_TIMERS
  6698.             extern int rttflg, mintime, maxtime;
  6699.             int tmin = 0, tmax = 0;
  6700. #endif /* CK_TIMERS */
  6701.             y = cmnum("Packet timeout interval",ckitoa(DMYTIM),10,&x,xxstring);
  6702.             if (y == -3) {              /* They cancelled a previous */
  6703.                 x = DMYTIM;             /* SET SEND command, so restore */
  6704.                 timef = 0;              /* and turn off the override flag */
  6705.                 y = cmcfm();
  6706.             }
  6707. #ifdef CK_TIMERS
  6708.             if (y < 0) return(y);
  6709.             if (x < 0) {
  6710.                 printf("?Out of range - %d\n",x);
  6711.                 return(-9);
  6712.             }
  6713.             if ((z = cmkey(timotab,2,"","dynamic",xxstring)) < 0) return(z);
  6714.             if (z) {
  6715.                 if ((y = cmnum("Minimum timeout to allow",
  6716.                                "1",10,&tmin,xxstring)) < 0)
  6717.                   return(y);
  6718.                 if (tmin < 1) {
  6719.                     printf("?Out of range - %d\n",tmin);
  6720.                     return(-9);
  6721.                 }
  6722.                 if ((y = cmnum("Maximum timeout to allow",
  6723.                                "0",10,&tmax,xxstring)) < 0)
  6724.                   return(y);
  6725.                 /* 0 means let Kermit choose, < 0 means no maximum */
  6726.             }
  6727.             if ((y = cmcfm()) < 0)
  6728.               return(y);
  6729.             rttflg = z;                 /* Round-trip timer flag */
  6730.             z = x;
  6731. #else
  6732.             if ((y = setnum(&z,x,y,94)) < 0)
  6733.               return(y);
  6734. #endif /* CK_TIMERS */
  6735.             timef = 1;                  /* Turn on the override flag */
  6736.             timint = rtimo = z;         /* Override value for me to use */
  6737. #ifdef CK_TIMERS
  6738.             if (rttflg) {               /* Lower and upper bounds */
  6739.                 mintime = tmin;
  6740.                 maxtime = tmax;
  6741.             }
  6742. #endif /* CK_TIMERS */
  6743.         }
  6744.         return(success = 1);
  6745.  
  6746.       case XYFPATH:                     /* PATHNAMES */
  6747.         if (xx == XYRECV) {
  6748.             y = cmkey(rpathtab,nrpathtab,"","auto",xxstring);
  6749.         } else {
  6750.             y = cmkey(pathtab,npathtab,"","off",xxstring);
  6751.         }
  6752.         if (y < 0) return(y);
  6753.  
  6754.         if ((x = cmcfm()) < 0) return(x);
  6755.         if (xx == XYRECV) {             /* SET RECEIVE PATHNAMES */
  6756.             fnrpath = y;
  6757.             ptab[protocol].fnrp = fnrpath;
  6758.         } else {                        /* SET SEND PATHNAMES */
  6759.             fnspath = y;
  6760.             ptab[protocol].fnsp = fnspath;
  6761.         }
  6762.         return(success = 1);            /* Note: 0 = ON, 1 = OFF */
  6763.         /* In other words, ON = leave pathnames ON, OFF = take them off. */
  6764.  
  6765.       case XYPAUS:                      /* SET SEND/RECEIVE PAUSE */
  6766.         y = cmnum("Milliseconds to pause between packets","0",10,&x,xxstring);
  6767.         if ((y = setnum(&z,x,y,15000)) < 0)
  6768.           return(y);
  6769.         pktpaus = z;
  6770.         return(success = 1);
  6771.  
  6772. #ifdef CKXXCHAR                         /* SET SEND/RECEIVE IGNORE/DOUBLE */
  6773.       case XYIGN:
  6774.       case XYDBL: {
  6775.           int i, zz;
  6776.           short *p;
  6777.           extern short dblt[];
  6778.           extern int dblflag, ignflag;
  6779.  
  6780.           /* Make space for a temporary copy of the ignore/double table */
  6781.  
  6782.           zz = y;
  6783. #ifdef COMMENT
  6784.           if (zz == XYIGN && xx == XYSEND) {
  6785.               blah blah who cares
  6786.           }
  6787.           if (zz == XYDBL && xx == XYRECV) {
  6788.               blah blah
  6789.           }
  6790. #endif /* COMMENT */
  6791.           p = (short *)malloc(256 * sizeof(short));
  6792.           if (!p) {
  6793.               printf("?Internal error - malloc failure\n");
  6794.               return(-9);
  6795.           }
  6796.           for (i = 0; i < 256; i++) p[i] = dblt[i]; /* Copy current table */
  6797.  
  6798.           while (1) {                   /* Collect a list of numbers */
  6799. #ifndef NOSPL
  6800.               x_ifnum = 1;              /* Turn off complaints from eval() */
  6801. #endif /* NOSPL */
  6802.               if ((x = cmnum(zz == XYDBL ?
  6803.                              "Character to double" :
  6804.                              "Character to ignore",
  6805.                              "",10,&y,xxstring
  6806.                              )) < 0) {
  6807. #ifndef NOSPL
  6808.                   x_ifnum = 0;
  6809. #endif /* NOSPL */
  6810.                   if (x == -3)          /* Done */
  6811.                     break;
  6812.                   if (x == -2) {
  6813.                       if (p) { free(p); p = NULL; }
  6814.                       debug(F110,"SET S/R DOUBLE/IGNORE atmbuf",atmbuf,0);
  6815.                       if (!ckstrcmp(atmbuf,"none",4,0) ||
  6816.                           !ckstrcmp(atmbuf,"non",3,0) ||
  6817.                           !ckstrcmp(atmbuf,"no",2,0) ||
  6818.                           !ckstrcmp(atmbuf,"n",1,0)) {
  6819.                           if ((x = cmcfm()) < 0) /* Get confirmation */
  6820.                             return(x);
  6821.                           for (y = 0; y < 256; y++)
  6822.                             dblt[y] &= (zz == XYDBL) ? 1 : 2;
  6823.                           if (zz == XYDBL) dblflag = 0;
  6824.                           if (zz == XYIGN) ignflag = 0;
  6825.                           return(success = 1);
  6826.                       } else {
  6827.                           printf(
  6828.                             "?Please specify a number or the word NONE\n");
  6829.                           return(-9);
  6830.                       }
  6831.                   } else {
  6832.                       free(p);
  6833.                       p = NULL;
  6834.                       return(x);
  6835.                   }
  6836.               }
  6837. #ifndef NOSPL
  6838.               x_ifnum = 0;
  6839. #endif /* NOSPL */
  6840.               if (y < 0 || y > 255) {
  6841.                   printf("?Please enter a character code in range 0-255\n");
  6842.                   free(p);
  6843.                   p = NULL;
  6844.                   return(-9);
  6845.               }
  6846.               p[y] |= (zz == XYDBL) ? 2 : 1;
  6847.               if (zz == XYDBL) dblflag = 1;
  6848.               if (zz == XYIGN) ignflag = 1;
  6849.           } /* End of while loop */
  6850.  
  6851.           if ((x = cmcfm()) < 0) return(x);
  6852. /*
  6853.   Get here only if they have made no mistakes.  Copy temporary table back to
  6854.   permanent one, then free temporary table and return successfully.
  6855. */
  6856.           if (p) {
  6857.               for (i = 0; i < 256; i++) dblt[i] = p[i];
  6858.               free(p);
  6859.               p = NULL;
  6860.           }
  6861.           return(success = 1);
  6862.       }
  6863. #endif /* CKXXCHAR */
  6864.  
  6865. #ifdef PIPESEND
  6866.       case XYFLTR: {                    /* SET { SEND, RECEIVE } FILTER */
  6867.           if ((y = cmtxt((xx == XYSEND) ?
  6868.                 "Filter program for sending files -\n\
  6869.  use \\v(filename) to substitute filename" :
  6870.                 "Filter program for receiving files -\n\
  6871.  use \\v(filename) to substitute filename",
  6872.                          "",&s,NULL)) < 0)
  6873.             return(y);
  6874.           if (!*s) {                    /* Removing a filter... */
  6875.               if (xx == XYSEND && sndfilter) {
  6876.                   makestr(&g_sfilter,NULL);
  6877.                   makestr(&sndfilter,NULL);
  6878.               } else if (rcvfilter) {
  6879.                   makestr(&g_rfilter,NULL);
  6880.                   makestr(&rcvfilter,NULL);
  6881.               }
  6882.               return(success = 1);
  6883.           }                             /* Adding a filter... */
  6884.           s = brstrip(s);               /* Strip any braces */
  6885.           y = strlen(s);
  6886.           if (xx == XYSEND) {           /* For SEND filter... */
  6887.               for (x = 0; x < y; x++) { /* make sure they included "\v(...)" */
  6888.                   if (s[x] != '\\') continue;
  6889.                   if (s[x+1] == 'v') break;
  6890.               }
  6891.               if (x == y) {
  6892.                   printf(
  6893.               "?Filter must contain a replacement variable for filename.\n"
  6894.                          );
  6895.                   return(-9);
  6896.               }
  6897.           }
  6898.           if (xx == XYSEND) {
  6899.               makestr(&sndfilter,s);
  6900.               makestr(&g_sfilter,s);
  6901.           } else {
  6902.               makestr(&rcvfilter,s);
  6903.               makestr(&g_rfilter,s);
  6904.           }
  6905.           return(success = 1);
  6906.       }
  6907. #endif /* PIPESEND */
  6908.  
  6909.       case XYINIL:
  6910.         y = cmnum("Max length for protocol init string","-1",10,&x,xxstring);
  6911.         if ((y = setnum(&z,x,y,-1)) < 0)
  6912.           return(y);
  6913.         if (xx == XYSEND)
  6914.           sprmlen = z;
  6915.         else
  6916.           rprmlen = z;
  6917.         return(success = 1);
  6918.  
  6919.       case 993: {
  6920.           extern int sendipkts;
  6921.           if (xx == XYSEND) {
  6922.               if ((x = seton(&sendipkts)) < 0)
  6923.                 return(x);
  6924.           }
  6925.           return(1);
  6926.       }
  6927. #ifdef CK_PERMS
  6928.       case 994:
  6929.     switch(xx) {
  6930.       case XYSEND:
  6931.         if ((x = seton(&atlpro)) < 0) return(x);
  6932.         atgpro = atlpro;
  6933.         return(1);
  6934.       case XYRECV:
  6935.         if ((x = seton(&atlpri)) < 0) return(x);
  6936.         atgpri = atlpri;
  6937.         return(1);
  6938.       default:
  6939.         return(-2);
  6940.     }
  6941. #endif /* CK_PERMS */
  6942.  
  6943. #ifndef NOCSETS
  6944.       case XYCSET: {                    /* CHARACTER-SET-SELECTION */
  6945.           extern struct keytab xfrmtab[];
  6946.           extern int r_cset, s_cset;
  6947.           if ((y = cmkey(xfrmtab,2,"","automatic",xxstring)) < 0)
  6948.             return(y);
  6949.           if ((x = cmcfm()) < 0)
  6950.             return(x);
  6951.           if (xx == XYSEND)
  6952.             s_cset = y;
  6953.           else
  6954.             r_cset = y;
  6955.           return(success = 1);
  6956.       }
  6957. #endif /* NOCSETS */
  6958.  
  6959.       case XYBUP:
  6960.         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
  6961.           return(y);
  6962.         if ((x = cmcfm()) < 0) return(x);
  6963.         if (xx == XYSEND) {
  6964.             extern int skipbup;
  6965.             skipbup = (y == 0) ? 1 : 0;
  6966.             return(success = 1);
  6967.         } else {
  6968.             printf(
  6969. "?Please use SET FILE COLLISION to choose the desired action\n");
  6970.             return(-9);
  6971.         }
  6972.  
  6973.       case XYMOVE:
  6974. #ifdef COMMENT
  6975.         y = cmdir("Directory to move file(s) to after successful transfer",
  6976.                   "",&s,xxstring);
  6977. #else
  6978.         y = cmtxt("Directory to move file(s) to after successful transfer",
  6979.           "",&s,xxstring);
  6980. #endif /* COMMENT */
  6981.  
  6982.         if (y < 0 && y != -3)
  6983.           return(y);
  6984.         ckstrncpy(line,s,LINBUFSIZ);
  6985.         s = brstrip(line);
  6986.  
  6987. #ifdef COMMENT
  6988.     /* Only needed for cmdir() */
  6989.         if ((x = cmcfm()) < 0)
  6990.           return(x);
  6991. #endif /* COMMENT */
  6992.     
  6993.     /* Check directory existence if absolute */
  6994.     /* THIS MEANS IT CAN'T INCLUDE ANY DEFERRED VARIABLES! */
  6995.     if (s) if (*s) {
  6996.         if (isabsolute(s) && !isdir(s)) {
  6997.         printf("?Directory does not exist - %s\n",s);
  6998.         return(-9);
  6999.         }
  7000.     }
  7001.         if (xx == XYSEND) {
  7002.             if (*s) {
  7003. #ifdef COMMENT
  7004.         /* Allow it to be relative */
  7005.                 zfnqfp(s,LINBUFSIZ,line);
  7006. #endif /* COMMENT */
  7007.                 makestr(&snd_move,line);
  7008.                 makestr(&g_snd_move,line);
  7009.             } else {
  7010.                 makestr(&snd_move,NULL);
  7011.                 makestr(&g_snd_move,NULL);
  7012.             }
  7013.         } else {
  7014.             if (*s) {
  7015. #ifdef COMMENT
  7016.         /* Allow it to be relative */
  7017.                 zfnqfp(s,LINBUFSIZ,line);
  7018. #endif /* COMMENT */
  7019.                 makestr(&rcv_move,line);
  7020.                 makestr(&g_rcv_move,line);
  7021.             } else {
  7022.                 makestr(&rcv_move,NULL);
  7023.                 makestr(&g_rcv_move,NULL);
  7024.             }
  7025.         }
  7026.         return(success = 1);
  7027.  
  7028.       case XYRENAME:
  7029.         y = cmtxt("Template to rename file(s) to after successful transfer",
  7030.                   "",&s,NULL);        /* NOTE: no xxstring */
  7031.         if (y < 0 && y != -3)        /* Evaluation is deferred */
  7032.           return(y);
  7033.         ckstrncpy(line,s,LINBUFSIZ);
  7034.         s = brstrip(line);
  7035.         if ((x = cmcfm()) < 0)
  7036.           return(x);
  7037.         if (xx == XYSEND) {
  7038.             if (*s) {
  7039.                 makestr(&snd_rename,s);
  7040.                 makestr(&g_snd_rename,s);
  7041.             } else {
  7042.                 makestr(&snd_rename,NULL);
  7043.                 makestr(&g_snd_rename,NULL);
  7044.             }
  7045.         } else {
  7046.             if (*s) {
  7047.                 makestr(&rcv_rename,s);
  7048.                 makestr(&g_rcv_rename,s);
  7049.             } else {
  7050.                 makestr(&rcv_rename,NULL);
  7051.                 makestr(&g_rcv_rename,NULL);
  7052.             }
  7053.         }
  7054.         return(success = 1);
  7055.  
  7056. #ifdef VMS
  7057.       case 887:                /* VERSION-NUMBERS */
  7058.         if (xx == XYSEND) {
  7059.             extern int vmssversions;
  7060.             return(seton(&vmssversions));
  7061.         } else {
  7062.             extern int vmsrversions;
  7063.             return(seton(&vmsrversions));
  7064.         }
  7065. #endif /* VMS */
  7066.  
  7067.       default:
  7068.         return(-2);
  7069.     }                                   /* End of SET SEND/RECEIVE... */
  7070. }
  7071. #endif /* NOXFER */
  7072.  
  7073. #ifndef NOXMIT
  7074. int
  7075. setxmit() {
  7076.     if ((y = cmkey(xmitab,nxmit,"","",xxstring)) < 0) return(y);
  7077.     switch (y) {
  7078.       case XMITE:                       /* EOF */
  7079.         y = cmtxt("Characters to send at end of file,\n\
  7080.  Use backslash codes for control characters","",&s,xxstring);
  7081.         if (y < 0) return(y);
  7082.         if ((int)strlen(s) > XMBUFL) {
  7083.             printf("?Too many characters, %d maximum\n",XMBUFL);
  7084.             return(-2);
  7085.         }
  7086.         ckstrncpy(xmitbuf,s,XMBUFL);
  7087.         return(success = 1);
  7088.  
  7089.       case XMITF:                       /* Fill */
  7090.         y = cmnum("Numeric code for blank-line fill character","0",10,&x,
  7091.                   xxstring);
  7092.         if ((y = setnum(&z,x,y,127)) < 0) return(y);
  7093.         xmitf = z;
  7094.         return(success = 1);
  7095.       case XMITL:                       /* Linefeed */
  7096.         return(seton(&xmitl));
  7097.       case XMITS:                       /* Locking-Shift */
  7098.         return(seton(&xmits));
  7099.       case XMITP:                       /* Prompt */
  7100.         y = cmnum("Numeric code for host's prompt character, 0 for none",
  7101.                   "10",10,&x,xxstring);
  7102.         if ((y = setnum(&z,x,y,127)) < 0) return(y);
  7103.         xmitp = z;
  7104.         return(success = 1);
  7105.       case XMITX:                       /* Echo */
  7106.         return(seton(&xmitx));
  7107.       case XMITW:                       /* Pause */
  7108.         y = cmnum("Number of milliseconds to pause between binary characters\n\
  7109. or text lines during transmission","0",10,&x,xxstring);
  7110.         if ((y = setnum(&z,x,y,1000)) < 0) return(y);
  7111.         xmitw = z;
  7112.         return(success = 1);
  7113.       case XMITT:                       /* Timeout */
  7114.         y = cmnum("Seconds to wait for each character to echo",
  7115.                   "1",10,&x,xxstring);
  7116.         if ((y = setnum(&z,x,y,1000)) < 0) return(y);
  7117.         xmitt = z;
  7118.         return(success = 1);
  7119.       default:
  7120.         return(-2);
  7121.     }
  7122. }
  7123. #endif /* NOXMIT */
  7124.  
  7125. #ifndef NOXFER
  7126. /*  D O R M T  --  Do a remote command  */
  7127.  
  7128. VOID
  7129. rmsg() {
  7130.     if (pflag && !quiet && fdispla != XYFD_N)
  7131.       printf(
  7132. #ifdef CK_NEED_SIG
  7133.        " Type your escape character, %s, followed by X or E to cancel.\n",
  7134.        dbchr(escape)
  7135. #else
  7136.        " Press the X or E key to cancel.\n"
  7137. #endif /* CK_NEED_SIG */
  7138.       );
  7139. }
  7140.  
  7141. static int xzcmd = 0;                   /* Global copy of REMOTE cmd index */
  7142.  
  7143. /*  R E M C F M  --  Confirm a REMOTE command  */
  7144. /*
  7145.   Like cmcfm(), but allows for a redirection indicator on the end,
  7146.   like "> filename" or "| command".  Returns what cmcfm() would have
  7147.   returned: -1 if reparse needed, etc etc blah blah.  On success,
  7148.   returns 1 with:
  7149.  
  7150.     char * remdest containing the name of the file or command.
  7151.     int remfile set to 1 if there is to be any redirection.
  7152.     int remappd set to 1 if output file is to be appended to.
  7153.     int rempipe set to 1 if remdest is a command, 0 if it is a file.
  7154. */
  7155. static int
  7156. remcfm() {
  7157.     int x;
  7158.     char *s;
  7159.     char c;
  7160.  
  7161.     remfile = 0;
  7162.     rempipe = 0;
  7163.     remappd = 0;
  7164.  
  7165.     if ((x = cmtxt(
  7166.              "> filename, | command,\n\
  7167. or type carriage return to confirm the command",
  7168.                    "",&s,xxstring)) < 0)
  7169.       return(x);
  7170.     if (remdest) {
  7171.         free(remdest);
  7172.         remdest = NULL;
  7173.     }
  7174.     debug(F101,"remcfm local","",local);
  7175.     debug(F110,"remcfm s",s,0);
  7176.     debug(F101,"remcfm cmd","",xzcmd);
  7177. /* 
  7178.   This check was added in C-Kermit 6.0 or 7.0 but it turns out to be
  7179.   unhelpful in the situation where the remote is running a script that sends
  7180.   REMOTE commands to the local workstation.  What happens is, the local
  7181.   server executes the command and sends the result back as screen text, which
  7182.   is indicated by using an X packet instead of an F packet as the file
  7183.   header.  There are two parts to this: executing the command under control
  7184.   of the remote Kermit, which is desirable (and in fact some big applications
  7185.   depend on it, and therefore never installed any new C-Kermit versions after
  7186.   5A), and displaying the result.  Commenting out the check allows the
  7187.   command to be executed, but the result is still sent back to the remote in
  7188.   a file transfer, where it vanishes into the ether.  Actually it's on the
  7189.   communication connection, mixed in with the packets.  Pretty amazing that
  7190.   the file transfer still works, right?
  7191. */
  7192. #ifdef COMMENT
  7193.     if (!*s) {                          /* No redirection indicator */
  7194.         if (!local &&
  7195.             (xzcmd == XZDIR || xzcmd == XZTYP ||
  7196.              xzcmd == XZXIT || xzcmd == XZSPA ||
  7197.              xzcmd == XZHLP || xzcmd == XZPWD ||
  7198.              xzcmd == XZLGI || xzcmd == XZLGO ||
  7199.              xzcmd == XZWHO || xzcmd == XZHOS)) {
  7200.             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
  7201.             return(-9);
  7202.         } else
  7203.           return(1);
  7204.     }
  7205. #endif    /* COMMENT */
  7206.     c = *s;                             /* We have something */
  7207.     if (c != '>' && c != '|') {         /* Is it > or | ? */
  7208.         printf("?Not confirmed\n");     /* No */
  7209.         return(-9);
  7210.     }
  7211.     s++;                                /* See what follows */
  7212.     if (c == '>' && *s == '>') {        /* Allow for ">>" too */
  7213.         s++;
  7214.         remappd = 1;                    /* Append to output file */
  7215.     }
  7216.     while (*s == SP || *s == HT) s++;   /* Strip intervening whitespace */
  7217.     if (!*s) {
  7218.         printf("?%s missing\n", c == '>' ? "Filename" : "Command");
  7219.         return(-9);
  7220.     }
  7221.     if (c == '>' && zchko(s) < 0) {     /* Check accessibility */
  7222.         printf("?Access denied - %s\n", s);
  7223.         return(-9);
  7224.     }
  7225.     remfile = 1;                        /* Set global results */
  7226.     rempipe = (c == '|');
  7227.     if (rempipe
  7228. #ifndef NOPUSH
  7229.         && nopush
  7230. #endif /* NOPUSH */
  7231.         ) {
  7232.         printf("?Sorry, access to external commands is disabled.\n");
  7233.         return(-9);
  7234.     }
  7235.     makestr(&remdest,s);
  7236. #ifndef NODEBUG
  7237.     if (deblog) {
  7238.         debug(F101,"remcfm remfile","",remfile);
  7239.         debug(F101,"remcfm remappd","",remappd);
  7240.         debug(F101,"remcfm rempipe","",rempipe);
  7241.         debug(F110,"remcfm remdest",remdest, 0);
  7242.     }
  7243. #endif /* NODEBUG */
  7244.     return(1);
  7245. }
  7246.  
  7247. /*  R E M T X T  --  Like remcfm()...  */
  7248. /*
  7249.    ... but for REMOTE commands that end with cmtxt().
  7250.    Here we must decipher braces to discover whether the trailing
  7251.    redirection indicator is intended for local use, or to be sent out
  7252.    to the server, as in:
  7253.  
  7254.      remote host blah blah > file                 This end
  7255.      remote host { blah blah } > file             This end
  7256.      remote host { blah blah > file }             That end
  7257.      remote host { blah blah > file } > file      Both ends
  7258.  
  7259.    Pipes too:
  7260.  
  7261.      remote host blah blah | cmd                  This end
  7262.      remote host { blah blah } | cmd              This end
  7263.      remote host { blah blah | cmd }              That end
  7264.      remote host { blah blah | cmd } | cmd        Both ends
  7265.  
  7266.    Or both:
  7267.  
  7268.      remote host blah blah | cmd > file           This end, etc etc...
  7269.  
  7270.    Note: this really only makes sense for REMOTE HOST, but why be picky?
  7271.    Call after calling cmtxt(), with pointer to string that cmtxt() parsed,
  7272.    as in "remtxt(&s);".
  7273.  
  7274.    Returns:
  7275.     1 on success with braces & redirection things removed & pointer updated,
  7276.    -9 on failure (bad indirection), after printing error message.
  7277. */
  7278. int
  7279. remtxt(p) char ** p; {
  7280.     int i, x, bpos, ppos;
  7281.     char c, *s, *q;
  7282.  
  7283.     remfile = 0;                        /* Initialize global results */
  7284.     rempipe = 0;
  7285.     remappd = 0;
  7286.     if (remdest) {
  7287.         free(remdest);
  7288.         remdest = NULL;
  7289.     }
  7290.     s = *p;
  7291.     if (!s)                             /* No redirection indicator */
  7292.       s = "";
  7293. #ifdef COMMENT
  7294.     if (!*s) {                          /* Ditto */
  7295.         if (!local &&
  7296.             (xzcmd == XZDIR || xzcmd == XZTYP ||
  7297.              xzcmd == XZXIT || xzcmd == XZSPA ||
  7298.              xzcmd == XZHLP || xzcmd == XZPWD ||
  7299.              xzcmd == XZLGI || xzcmd == XZLGO ||
  7300.              xzcmd == XZWHO || xzcmd == XZHOS)) {
  7301.             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
  7302.             if (hints) {
  7303.                 printf("Hint: Try again with an output redirector.\n");
  7304.             }
  7305.             return(-9);
  7306.         } else
  7307.           return(1);
  7308.     }
  7309. #endif    /* COMMENT */
  7310.     bpos = -1;                          /* Position of > (bracket) */
  7311.     ppos = -1;                          /* Position of | (pipe) */
  7312.     x = strlen(s);                      /* Length of cmtxt() string */
  7313.  
  7314.     for (i = x-1; i >= 0; i--) {        /* Search right to left. */
  7315.         c = s[i];
  7316.         if (c == '}')                   /* Break on first right brace */
  7317.           break;                        /* Don't look at contents of braces */
  7318.         else if (c == '>')              /* Record position of > */
  7319.           bpos = i;
  7320.         else if (c == '|')              /* and of | */
  7321.           ppos = i;
  7322.     }
  7323.     if (bpos < 0 && ppos < 0) {         /* No redirectors. */
  7324. #ifdef COMMENT
  7325.         if (!local &&
  7326.             (xzcmd == XZDIR || xzcmd == XZTYP ||
  7327.              xzcmd == XZXIT || xzcmd == XZSPA ||
  7328.              xzcmd == XZHLP || xzcmd == XZPWD ||
  7329.              xzcmd == XZLGI || xzcmd == XZLGO ||
  7330.              xzcmd == XZWHO || xzcmd == XZHOS)) {
  7331.             printf("?\"%s\" has no effect in remote mode\n",cmdbuf);
  7332.             if (hints) {
  7333.                 printf("Hint: Try again with an output redirector.\n");
  7334.             }
  7335.             return(-9);
  7336.         }
  7337. #endif    /* COMMENT */
  7338.         s = brstrip(s);                 /* Remove outer braces if any. */
  7339.         *p = s;                         /* Point to result */
  7340.         return(1);                      /* and return. */
  7341.     }
  7342.     remfile = 1;                        /* It's | or > */
  7343.     i = -1;                             /* Get leftmost symbol */
  7344.     if (bpos > -1)                      /* Bracket */
  7345.       i = bpos;
  7346.     if (ppos > -1 && (ppos < bpos || bpos < 0)) { /* or pipe */
  7347.         i = ppos;
  7348.         rempipe = 1;
  7349.     }
  7350.     if (rempipe
  7351. #ifndef NOPUSH
  7352.         && nopush
  7353. #endif /* NOPUSH */
  7354.         ) {
  7355.         printf("?Sorry, access to external commands is disabled.\n");
  7356.         return(-9);
  7357.     }
  7358.     c = s[i];                           /* Copy of symbol */
  7359.  
  7360.     if (c == '>' && s[i+1] == '>')      /* ">>" for append? */
  7361.       remappd = 1;                     /* It's not just a flag it's a number */
  7362.  
  7363.     q = s + i + 1 + remappd;            /* Point past symbol in string */
  7364.     while (*q == SP || *q == HT) q++;   /* and any intervening whitespace */
  7365.     if (!*q) {
  7366.         printf("?%s missing\n", c == '>' ? "Filename" : "Command");
  7367.         return(-9);
  7368.     }
  7369.     if (c == '>' && zchko(q) < 0) {     /* (Doesn't work for | cmd > file) */
  7370.         printf("?Access denied - %s\n", q);
  7371.         return(-9);
  7372.     }
  7373.     makestr(&remdest,q);                /* Create the destination string */
  7374.     q = s + i - 1;                      /* Point before symbol */
  7375.     while (q > s && (*q == SP || *q == HT)) /* Strip trailing whitespace */
  7376.       q--;
  7377.     *(q+1) = NUL;                       /* Terminate the string. */
  7378.     s = brstrip(s);                     /* Remove any braces */
  7379.     *p = s;                             /* Set return value */
  7380.  
  7381. #ifndef NODEBUG
  7382.     if (deblog) {
  7383.         debug(F101,"remtxt remfile","",remfile);
  7384.         debug(F101,"remtxt remappd","",remappd);
  7385.         debug(F101,"remtxt rempipe","",rempipe);
  7386.         debug(F110,"remtxt remdest",remdest, 0);
  7387.         debug(F110,"remtxt command",s,0);
  7388.     }
  7389. #endif /* NODEBUG */
  7390.  
  7391.     return(1);
  7392. }
  7393.  
  7394. int
  7395. plogin(xx) int xx; {
  7396.     char *p1 = NULL, *p2 = NULL, *p3 = NULL;
  7397.     int psaved = 0, rc = 0;
  7398. #ifdef CK_RECALL
  7399.     extern int on_recall;               /* around Password prompting */
  7400. #endif /* CK_RECALL */
  7401.     debug(F101,"plogin local","",local);
  7402.  
  7403.     if (!local || (network && ttchk() < 0)) {
  7404.         printf("?No connection\n");
  7405.         return(-9);
  7406.     }
  7407.     if ((x = cmfld("User ID","",&s,xxstring)) < 0) { /* Get User ID */
  7408.         if (x != -3) return(x);
  7409.     }
  7410.     y = strlen(s);
  7411.     if (y > 0) {
  7412.         if ((p1 = malloc(y + 1)) == NULL) {
  7413.             printf("?Internal error: malloc\n");
  7414.             rc = -9;
  7415.             goto XZXLGI;
  7416.         } else
  7417.           strcpy(p1,s);                 /* safe */
  7418.         if ((rc = cmfld("Password","",&s,xxstring)) < 0)
  7419.           if (rc != -3) goto XZXLGI;
  7420.         y = strlen(s);
  7421.         if (y > 0) {
  7422.             if ((p2 = malloc(y + 1)) == NULL) {
  7423.                 printf("?Internal error: malloc\n");
  7424.                 rc = -9;
  7425.                 goto XZXLGI;
  7426.             } else
  7427.               strcpy(p2,s);             /* safe */
  7428.             if ((rc = cmfld("Account","",&s,xxstring)) < 0)
  7429.               if (rc != -3) goto XZXLGI;
  7430.             y = strlen(s);
  7431.             if (y > 0) {
  7432.                 if ((p3 = malloc(y + 1)) == NULL) {
  7433.                     printf("?Internal error: malloc\n");
  7434.                     rc = -9;
  7435.                     goto XZXLGI;
  7436.                 } else
  7437.                   strcpy(p3,s);         /* safe */
  7438.             }
  7439.         }
  7440.     }
  7441.     if ((rc = remtxt(&s)) < 0)          /* Confirm & handle redirectors */
  7442.       goto XZXLGI;
  7443.  
  7444.     if (!p1) {                          /* No Userid specified... */
  7445.         debok = 0;                      /* Don't log this */
  7446.         /* Prompt for username, password, and account */
  7447. #ifdef CK_RECALL
  7448.         on_recall = 0;
  7449. #endif /* CK_RECALL */
  7450.         cmsavp(psave,PROMPTL);          /* Save old prompt */
  7451.         psaved = 1;
  7452.         debug(F110,"REMOTE LOGIN saved",psave,0);
  7453.  
  7454.         cmsetp("Username: ");           /* Make new prompt */
  7455.         concb((char)escape);            /* Put console in cbreak mode */
  7456.         cmini(1);
  7457.         prompt(xxstring);
  7458.         rc = -9;
  7459.         for (x = -1; x < 0; ) {         /* Prompt till they answer */
  7460.             cmres();                    /* Reset the parser */
  7461.             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
  7462.         }
  7463.         y = strlen(s);
  7464.         if (y < 1) {
  7465.             printf("?Canceled\n");
  7466.             goto XZXLGI;
  7467.         }
  7468.         if ((p1 = malloc(y + 1)) == NULL) {
  7469.             printf("?Internal error: malloc\n");
  7470.             goto XZXLGI;
  7471.         } else
  7472.           strcpy(p1,s);                 /* safe */
  7473.  
  7474.         cmsetp("Password: ");           /* Make new prompt */
  7475.         concb((char)escape);            /* Put console in cbreak mode */
  7476.         cmini(0);                       /* No echo */
  7477.         prompt(xxstring);
  7478.         debok = 0;
  7479.         for (x = -1; x < 0 && x != -3; ) { /* Get answer */
  7480.             cmres();                    /* Reset the parser */
  7481.             x = cmtxt("","",&s,NULL);   /* Get literal line of text */
  7482.         }
  7483.         if ((p2 = malloc((int)strlen(s) + 1)) == NULL) {
  7484.             printf("?Internal error: malloc\n");
  7485.             goto XZXLGI;
  7486.         } else
  7487.           strcpy(p2,s);                 /* safe */
  7488.         printf("\r\n");
  7489.         if ((rc = cmcfm()) < 0)
  7490.           goto XZXLGI;
  7491.     }
  7492.     sstate = setgen('I',p1,p2,p3);      /* Get here with at least user ID */
  7493.     rc = 0;
  7494.  
  7495.   XZXLGI:                               /* Common exit point */
  7496.     if (psaved)
  7497.       cmsetp(psave);                    /* Restore original prompt */
  7498.     if (p3) { free(p3); p3 = NULL; }    /* Free malloc'd storage */
  7499.     if (p2) { free(p2); p2 = NULL; }
  7500.     if (p1) { free(p1); p1 = NULL; }
  7501.     if (rc > -1) {
  7502.         if (local && rc > -1)           /* If local, flush tty input buffer */
  7503.           ttflui();
  7504.     }
  7505.     return(rc);
  7506. }
  7507.  
  7508. #ifdef OS2
  7509. #ifndef NOLOCAL
  7510. int
  7511. dormt(xx) int xx; {
  7512.     int rc = 0;
  7513.     extern int term_io;
  7514.     int term_io_sav = term_io;
  7515. #ifdef NEWFTP
  7516.     extern int ftpget, ftpisopen();
  7517.     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
  7518.       return(doftprmt(xx,0));
  7519. #endif /* NEWFTP */
  7520.     term_io = 0;
  7521.     rc = xxdormt(xx);
  7522.     term_io = term_io_sav;
  7523.     return rc;
  7524. }
  7525.  
  7526.  
  7527. int
  7528. xxdormt(xx) int xx;
  7529. #else /* NOLOCAL */
  7530. int
  7531. dormt(xx) int xx;
  7532. #endif /* NOLOCAL */
  7533. #else /* OS2 */
  7534. int
  7535. dormt(xx) int xx;
  7536. #endif /* OS2 */
  7537. {                                       /* REMOTE commands */
  7538.     int x, y, retcode;
  7539.     char *s, sbuf[50], *s2;
  7540.  
  7541. #ifdef NEWFTP
  7542.     extern int ftpget, ftpisopen();
  7543.     if ((ftpget == 1) || ((ftpget == 2) && ftpisopen()))
  7544.       return(doftprmt(xx,0));
  7545. #endif /* NEWFTP */
  7546.  
  7547.     remfile = 0;                        /* Clear these */
  7548.     rempipe = 0;
  7549.     remappd = 0;
  7550.  
  7551.     if (xx < 0) return(xx);             /* REMOTE what? */
  7552.  
  7553.     xzcmd = xx;                         /* Make global copy of arg */
  7554.  
  7555.     if (xx == XZSET) {                  /* REMOTE SET */
  7556.         if ((y = cmkey(rmstab,nrms,"","",xxstring)) < 0) {
  7557.             if (y == -3) {
  7558.                 printf("?Parameter name required\n");
  7559.                 return(-9);
  7560.             } else return(y);
  7561.         }
  7562.         return(doprm(y,1));
  7563.     }
  7564.  
  7565.     switch (xx) {                       /* Others... */
  7566.  
  7567.       case XZCDU:
  7568.         if ((x = cmcfm()) < 0) return(x);
  7569.         printf("?Sorry, REMOTE CDUP not supported yet\n");
  7570.         return(-9);
  7571.  
  7572.       case XZCWD:                       /* CWD (CD) */
  7573.         if ((x = cmtxt("Remote directory name","",&s,xxstring)) < 0)
  7574.           return(x);
  7575.         if ((x = remtxt(&s)) < 0)
  7576.           return(x);
  7577.         debug(F111,"XZCWD: ",s,x);
  7578.         *sbuf = NUL;
  7579.         s2 = sbuf;
  7580. /*
  7581.   The following is commented out because since the disappearance of the
  7582.   DECSYSTEM-20 from the planet, no known computer requires a password for
  7583.   changing directory.
  7584. */
  7585. #ifdef DIRPWDPR
  7586.         if (*s != NUL) {                /* If directory name given, */
  7587.                                         /* get password on separate line. */
  7588.             if (tlevel > -1) {          /* From take file... */
  7589.  
  7590.                 if (fgets(sbuf,50,tfile[tlevel]) == NULL)
  7591.                   fatal("take file ends prematurely in 'remote cwd'");
  7592.                 debug(F110," pswd from take file",s2,0);
  7593.                 for (x = (int)strlen(sbuf);
  7594.                      x > 0 && (sbuf[x-1] == NL || sbuf[x-1] == CR);
  7595.                      x--)
  7596.                   sbuf[x-1] = '\0';
  7597.  
  7598.             } else {                    /* From terminal... */
  7599.  
  7600.                 printf(" Password: ");  /* get a password */
  7601. #ifdef IKSD
  7602.                 if (!local && inserver) {
  7603.                     x = coninc(0);
  7604.                 } else
  7605. #endif /* IKSD */
  7606. #ifdef OS2
  7607.                   x = is_a_tty(0) ? coninc(0) : /* with no echo ... */
  7608.                     getchar();
  7609. #else /* OS2 */
  7610.                 x = getchar();
  7611. #endif /* OS2 */
  7612.                 while ((x != NL) && (x != CR)) {
  7613.                     if ((x &= 0177) == '?') {
  7614.                         printf("? Password of remote directory\n Password: ");
  7615.                         s2 = sbuf;
  7616.                         *sbuf = NUL;
  7617.                     } else if (x == ESC) /* Mini command line editor... */
  7618.                       bleep(BP_WARN);
  7619.                     else if (x == BS || x == 0177)
  7620.                       s2--;
  7621.                     else if (x == 025) {        /* Ctrl-U */
  7622.                         s2 = sbuf;
  7623.                         *sbuf = NUL;
  7624.                     } else
  7625.                       *s2++ = x;
  7626.  
  7627.                     /* Get the next character */
  7628. #ifdef IKSD
  7629.                     if (!local && inserver) {
  7630.                         x = coninc(0);
  7631.                     } else
  7632. #endif /* IKSD */
  7633. #ifdef OS2
  7634.                     x = is_a_tty(0) ? coninc(0) : /* with no echo ... */
  7635.                       getchar();
  7636. #else /* OS2 */
  7637.                     x = getchar();
  7638. #endif /* OS2 */
  7639.                 }
  7640.                 *s2 = NUL;
  7641.                 putchar('\n');
  7642.             }
  7643.             s2 = sbuf;
  7644.         } else s2 = "";
  7645. #endif /* DIRPWDPR */
  7646.  
  7647.         debug(F110," password",s2,0);
  7648.     rcdactive = 1;
  7649.         sstate = setgen('C',s,s2,"");
  7650.         retcode = 0;
  7651.         break;
  7652.  
  7653.       case XZDEL:                               /* Delete */
  7654.         if ((x = cmtxt("Name of remote file(s) to delete",
  7655.                        "",&s,xxstring)) < 0) {
  7656.             if (x == -3) {
  7657.                 printf("?Name of remote file(s) required\n");
  7658.                 return(-9);
  7659.             } else return(x);
  7660.         }
  7661.         if ((x = remtxt(&s)) < 0)
  7662.           return(x);
  7663.         if (local) ttflui();            /* If local, flush tty input buffer */
  7664.         retcode = sstate = rfilop(s,'E');
  7665.         break;
  7666.  
  7667.       case XZDIR:                       /* Directory */
  7668.         if ((x = cmtxt("Remote directory or file specification","",&s,
  7669.                        xxstring)) < 0)
  7670.           return(x);
  7671.         if ((x = remtxt(&s)) < 0)
  7672.           return(x);
  7673.         if (local) ttflui();            /* If local, flush tty input buffer */
  7674.         rmsg();
  7675.         retcode = sstate = setgen('D',s,"","");
  7676.         break;
  7677.  
  7678.       case XZHLP:                       /* Help */
  7679.         if ((x = remcfm()) < 0) return(x);
  7680.         sstate = setgen('H',"","","");
  7681.         retcode = 0;
  7682.         break;
  7683.  
  7684.       case XZHOS:                       /* Host */
  7685.         if ((x = cmtxt("Command for remote system","",&s,xxstring)) < 0)
  7686.           return(x);
  7687.         if ((x = remtxt(&s)) < 0)
  7688.           return(x);
  7689.         if ((y = (int)strlen(s)) < 1)
  7690.           return(x);
  7691.         ckstrncpy(line,s,LINBUFSIZ);
  7692.         cmarg = line;
  7693.         rmsg();
  7694.         retcode = sstate = 'c';
  7695.         break;
  7696.  
  7697. #ifndef NOFRILLS
  7698.       case XZKER:
  7699.         if ((x = cmtxt("Command for remote Kermit","",&s,xxstring)) < 0)
  7700.           return(x);
  7701.         if ((x = remtxt(&s)) < 0)
  7702.           return(x);
  7703.         if ((int)strlen(s) < 1)  {
  7704.             if (x == -3) {
  7705.                 printf("?Remote Kermit command required\n");
  7706.                 return(-9);
  7707.             } else return(x);
  7708.         }
  7709.         ckstrncpy(line,s,LINBUFSIZ);
  7710.         cmarg = line;
  7711.         retcode = sstate = 'k';
  7712.         rmsg();
  7713.         break;
  7714.  
  7715.       case XZLGI:                       /* Login */
  7716.     rcdactive = 1;            /* Suppress "Logged in" msg if quiet */
  7717.         return(plogin(XXREM));
  7718.  
  7719.       case XZLGO: {                     /* Logout */
  7720.           extern int bye_active;
  7721.           if ((x = remcfm()) < 0) return(x);
  7722.           sstate = setgen('I',"","","");
  7723.           retcode = 0;
  7724.           bye_active = 1;               /* Close connection when done */
  7725.           break;
  7726.       }
  7727.  
  7728.       case XZPRI:                       /* Print */
  7729.         if (!atdiso || !atcapr) {       /* Disposition attribute off? */
  7730.             printf("?Disposition Attribute is Off\n");
  7731.             return(-2);
  7732.         }
  7733.         cmarg = "";
  7734.         cmarg2 = "";
  7735.         if ((x = cmifi("Local file(s) to print on remote printer","",&s,&y,
  7736.                        xxstring)) < 0) {
  7737.             if (x == -3) {
  7738.                 printf("?Name of local file(s) required\n");
  7739.                 return(-9);
  7740.             }
  7741.             return(x);
  7742.         }
  7743.         ckstrncpy(line,s,LINBUFSIZ);    /* Make a safe copy of filename */
  7744.         *optbuf = NUL;                  /* Wipe out any old options */
  7745.         if ((x = cmtxt("Options for remote print command","",&s,xxstring)) < 0)
  7746.           return(x);
  7747.         if ((x = remtxt(&s)) < 0)
  7748.           return(x);
  7749.         if ((int)strlen(optbuf) > 94) { /* Make sure this is legal */
  7750.             printf("?Option string too long\n");
  7751.             return(-9);
  7752.         }
  7753.         ckstrncpy(optbuf,s,OPTBUFLEN);  /* Make a safe copy of options */
  7754.         nfils = -1;                     /* Expand file list internally */
  7755.         cmarg = line;                   /* Point to file list. */
  7756.         rprintf = 1;                    /* REMOTE PRINT modifier for SEND */
  7757.         sstate = 's';                   /* Set start state to SEND */
  7758.         if (local) displa = 1;
  7759.         retcode = 0;
  7760.         break;
  7761. #endif /* NOFRILLS */
  7762.  
  7763.       case XZSPA:                       /* Space */
  7764.         if ((x = cmtxt("Confirm, or remote directory name",
  7765.                        "",&s,xxstring)) < 0)
  7766.           return(x);
  7767.         if ((x = remtxt(&s)) < 0)
  7768.           return(x);
  7769.         retcode = sstate = setgen('U',s,"","");
  7770.         break;
  7771.  
  7772.       case XZMSG:                       /* Message */
  7773.         if ((x = cmtxt("Short text message for server","",&s,xxstring)) < 0)
  7774.           return(x);
  7775.         if ((x = remtxt(&s)) < 0)
  7776.           return(x);
  7777.         retcode = sstate = setgen('M',s,"","");
  7778.         break;
  7779.  
  7780. #ifndef NOFRILLS
  7781.       case XZTYP:                       /* Type */
  7782.         if ((x = cmtxt("Remote file specification","",&s,xxstring)) < 0)
  7783.           return(x);
  7784.         if ((int)strlen(s) < 1) {
  7785.             printf("?Remote filename required\n");
  7786.             return(-9);
  7787.         }
  7788.         if ((x = remtxt(&s)) < 0)
  7789.           return(x);
  7790.         rmsg();
  7791.         retcode = sstate = rfilop(s,'T');
  7792.         break;
  7793. #endif /* NOFRILLS */
  7794.  
  7795. #ifndef NOFRILLS
  7796.       case XZWHO:
  7797.         if ((x = cmtxt("Remote user name, or carriage return",
  7798.                        "",&s,xxstring)) < 0)
  7799.           return(x);
  7800.         if ((x = remtxt(&s)) < 0)
  7801.           return(x);
  7802.         retcode = sstate = setgen('W',s,"","");
  7803.         break;
  7804. #endif /* NOFRILLS */
  7805.  
  7806.       case XZPWD:                       /* PWD */
  7807.         if ((x = remcfm()) < 0) return(x);
  7808.         sstate = setgen('A',"","","");
  7809.         retcode = 0;
  7810.         break;
  7811.  
  7812. #ifndef NOSPL
  7813.       case XZQUE: {                     /* Query */
  7814.           char buf[2];
  7815.           extern char querybuf[], * qbufp;
  7816.           extern int qbufn;
  7817.           if ((y = cmkey(vartyp,nvartyp,"","",xxstring)) < 0)
  7818.             return(y);
  7819.           if ((x = cmtxt(y == 'F' ? "Remote function invocation" :
  7820.                          ('K' ? "Remote variable name or function":
  7821.                          "Remote variable name"),
  7822.                          "",
  7823.                          &s,
  7824.                          (y == 'K') ? xxstring : NULL
  7825.                          )) < 0)        /* Don't evaluate */
  7826.             return(x);
  7827.           if ((x = remtxt(&s)) < 0)
  7828.             return(x);
  7829.           query = 1;                    /* QUERY is active */
  7830.           qbufp = querybuf;             /* Initialize query response buffer */
  7831.           qbufn = 0;
  7832.           querybuf[0] = NUL;
  7833.           buf[0] = (char) (y & 127);
  7834.           buf[1] = NUL;
  7835.           retcode = sstate = setgen('V',"Q",(char *)buf,s);
  7836.           break;
  7837.       }
  7838.  
  7839.       case XZASG: {                     /* Assign */
  7840.           char buf[VNAML];
  7841.           if ((y = cmfld("Remote variable name","",&s,NULL)) < 0) /* No eval */
  7842.             return(y);
  7843.           if ((int)strlen(s) >= VNAML) {
  7844.               printf("?Too long\n");
  7845.               return(-9);
  7846.           }
  7847.           ckstrncpy(buf,s,VNAML);
  7848.           if ((x = cmtxt("Assignment for remote variable",
  7849.                    "",&s,xxstring)) < 0) /* Evaluate this one */
  7850.             return(x);
  7851.           if ((x = remtxt(&s)) < 0)
  7852.             return(x);
  7853. #ifdef COMMENT
  7854. /*
  7855.   Server commands can't be long packets.  In principle there's no reason
  7856.   why they shouldn't be, except that we don't know at this point if the
  7857.   server is capable of accepting long packets because we haven't started
  7858.   the protocol yet.  In practice, allowing a long packet here breaks a lot
  7859.   of assumptions, causes buffer overruns and crashes, etc.  To be fixed
  7860.   later.  (But since this is commented out, evidently I fixed it later...)
  7861. */
  7862.           if ((int)strlen(s) > 85) {    /* Allow for encoding expansion */
  7863.               printf("?Sorry, value is too long - 85 characters max\n");
  7864.               return(-9);
  7865.           }
  7866. #endif /* COMMENT */
  7867.           retcode = sstate = setgen('V',"S",(char *)buf,s);
  7868.           break;
  7869.       }
  7870. #endif /* NOSPL */
  7871.  
  7872.       case XZCPY: {                     /* COPY */
  7873.           char buf[TMPBUFSIZ];
  7874.           buf[TMPBUFSIZ-1] = '\0';
  7875.           if ((x = cmfld("Name of remote file to copy","",&s,xxstring)) < 0) {
  7876.               if (x == -3) {
  7877.                   printf("?Name of remote file required\n");
  7878.                   return(-9);
  7879.               }
  7880.               else
  7881.                 return(x);
  7882.           }
  7883.           ckstrncpy(buf,s,TMPBUFSIZ);
  7884.           if ((x = cmfld("Name of remote destination file or directory",
  7885.                          "",&s, xxstring)) < 0) {
  7886.               if (x == -3) {
  7887.                   printf("?Name of remote file or directory required\n");
  7888.                   return(-9);
  7889.               } else return(x);
  7890.           }
  7891.           ckstrncpy(tmpbuf,s,TMPBUFSIZ);
  7892.           if ((x = remcfm()) < 0)
  7893.             return(x);
  7894.           if (local) ttflui();          /* If local, flush tty input buffer */
  7895.           retcode = sstate = setgen('K',buf,tmpbuf,"");
  7896.           break;
  7897.       }
  7898.       case XZREN: {                     /* Rename */
  7899.           char buf[TMPBUFSIZ];
  7900.           buf[TMPBUFSIZ-1] = '\0';
  7901.           if ((x = cmfld("Name of remote file to rename",
  7902.                          "",&s,xxstring)) < 0) {
  7903.               if (x == -3) {
  7904.                   printf("?Name of remote file required\n");
  7905.                   return(-9);
  7906.               } else return(x);
  7907.           }
  7908.           ckstrncpy(buf,s,TMPBUFSIZ);
  7909.           if ((x = cmfld("New name of remote file","",&s, xxstring)) < 0) {
  7910.               if (x == -3) {
  7911.                   printf("?Name of remote file required\n");
  7912.                   return(-9);
  7913.               } else return(x);
  7914.           }
  7915.           ckstrncpy(tmpbuf,s,TMPBUFSIZ);
  7916.           if ((x = remcfm()) < 0)
  7917.             return(x);
  7918.           if (local) ttflui();          /* If local, flush device buffer */
  7919.           retcode = sstate = setgen('R',buf,tmpbuf,"");
  7920.           break;
  7921.       }
  7922.       case XZMKD:                       /* mkdir */
  7923.       case XZRMD:                       /* rmdir */
  7924.         if ((x = cmtxt((xx == XZMKD) ?
  7925.                        "Name of remote directory to create" :
  7926.                        "Name of remote directory to delete",
  7927.                        "",
  7928.                        &s,
  7929.                        xxstring
  7930.                        )) < 0) {
  7931.             if (x == -3) {
  7932.                 printf("?Name required\n");
  7933.                 return(-9);
  7934.             } else return(x);
  7935.         }
  7936.         if ((x = remtxt(&s)) < 0)
  7937.           return(x);
  7938.         if (local) ttflui();            /* If local, flush tty input buffer */
  7939.         retcode = sstate = rfilop(s, (char)(xx == XZMKD ? 'm' : 'd'));
  7940.         break;
  7941.  
  7942.       case XZXIT:                       /* Exit */
  7943.         if ((x = remcfm()) < 0) return(x);
  7944.         sstate = setgen('X',"","","");
  7945.         retcode = 0;
  7946.         break;
  7947.  
  7948.       default:
  7949.         if ((x = remcfm()) < 0) return(x);
  7950.         printf("?Not implemented - %s\n",cmdbuf);
  7951.         return(-2);
  7952.     }
  7953.     if (local && retcode > -1)          /* If local, flush tty input buffer */
  7954.       ttflui();
  7955.     return(retcode);
  7956. }
  7957.  
  7958.  
  7959. /*  R F I L O P  --  Remote File Operation  */
  7960.  
  7961. CHAR
  7962. #ifdef CK_ANSIC
  7963. rfilop(char * s, char t)
  7964. #else
  7965. rfilop(s,t) char *s, t;
  7966. #endif /* CK_ANSIC */
  7967. /* rfilop */ {
  7968.     if (*s == NUL) {
  7969.         printf("?File specification required\n");
  7970.         return((CHAR) 0);
  7971.     }
  7972.     debug(F111,"rfilop",s,t);
  7973.     return(setgen(t,s,"",""));
  7974. }
  7975. #endif /* NOXFER */
  7976.  
  7977. #ifdef ANYX25
  7978. int
  7979. setx25() {
  7980.     if ((y = cmkey(x25tab,nx25,"X.25 call options","",xxstring)) < 0)
  7981.       return(y);
  7982.     switch (y) {
  7983.       case XYUDAT:
  7984.         if ((z = cmkey(onoff,2,"X.25 call user data","",xxstring))
  7985.             < 0) return(z);
  7986.         if (z == 0) {
  7987.             if ((z = cmcfm()) < 0) return(z);
  7988.             cudata = 0;             /* disable call user data */
  7989.             return (success = 1);
  7990.         }
  7991.         if ((x = cmtxt("X.25 call user data string","",&s,xxstring)) < 0)
  7992.           return(x);
  7993.         if ((int)strlen(s) == 0) {
  7994.             return (-3);
  7995.         } else if ((int)strlen(s) > MAXCUDATA) {
  7996.             printf("?The length must be > 0 and <= %d\n",MAXCUDATA);
  7997.             return(-2);
  7998.         }
  7999.         if ((y = cmcfm()) < 0) return(y);
  8000.         ckstrncpy(udata,s,MAXCUDATA);
  8001.         cudata = 1;                     /* X.25 call user data specified */
  8002.         return (success = 1);
  8003.       case XYCLOS:
  8004.         if ((z = cmkey(onoff,2,"X.25 closed user group call","",xxstring))
  8005.             < 0) return(z);
  8006.         if (z == 0) {
  8007.             if ((z = cmcfm()) < 0) return(z);
  8008.             closgr = -1;                /* disable closed user group */
  8009.             return (success = 1);
  8010.         }
  8011.         if ((y = cmnum("0 <= cug index >= 99","",10,&x,xxstring)) < 0)
  8012.           return(y);
  8013.         if (x < 0 || x > 99) {
  8014.             printf("?The choices are 0 <= cug index >= 99\n");
  8015.             return(-2);
  8016.         }
  8017.         if ((y = cmcfm()) < 0) return(y);
  8018.         closgr = x;                     /* closed user group selected */
  8019.         return (success = 1);
  8020.  
  8021.       case XYREVC:
  8022.         if((z = cmkey(onoff,2,"X.25 reverse charge call","",xxstring)) < 0)
  8023.           return(z);
  8024.         if ((x = cmcfm()) < 0) return(x);
  8025.         revcall = z;
  8026.         return (success = 1);
  8027.     }
  8028. }
  8029.  
  8030. #ifndef IBMX25
  8031. int
  8032. setpadp() {
  8033.     if ((y = cmkey(padx3tab,npadx3,"PAD X.3 parameter name","",xxstring)) < 0)
  8034.       return(y);
  8035.     x = y;
  8036.     switch (x) {
  8037.       case PAD_BREAK_CHARACTER:
  8038.         if ((y = cmnum("PAD break character value","",10,&z,xxstring)) < 0)
  8039.           return(y);
  8040.         if ((y = cmcfm()) < 0) return(y);
  8041.         break;
  8042.       case PAD_ESCAPE:
  8043.         if ((y = cmnum("PAD escape","",10,&z,xxstring)) < 0) return(y);
  8044.         if (z != 0 && z != 1) {
  8045.             printf("?The choices are 0 or 1\n");
  8046.             return(-2);
  8047.         }
  8048.         if ((y = cmcfm()) < 0) return(y);
  8049.         break;
  8050.       case PAD_ECHO:
  8051.         if ((y = cmnum("PAD echo","",10,&z,xxstring)) < 0) return(y);
  8052.         if (z != 0 && z != 1) {
  8053.             printf("?The choices are 0 or 1\n");
  8054.             return(-2);
  8055.         }
  8056.         if ((y = cmcfm()) < 0) return(y);
  8057.         break;
  8058.       case PAD_DATA_FORWARD_CHAR:
  8059.         if ((y = cmnum("PAD data forward char","",10,&z,xxstring)) < 0)
  8060.           return(y);
  8061.         if (z != 0 && z != 2) {
  8062.             printf("?The choices are 0 or 2\n");
  8063.             return(-2);
  8064.         }
  8065.         if ((y = cmcfm()) < 0) return(y);
  8066.         break;
  8067.       case PAD_DATA_FORWARD_TIMEOUT:
  8068.         if ((y = cmnum("PAD data forward timeout","",10,&z,xxstring)) < 0)
  8069.             return(y);
  8070.         if (z < 0 || z > 255) {
  8071.             printf("?The choices are 0 or 1 <= timeout <= 255\n");
  8072.             return(-2);
  8073.         }
  8074.         if ((y = cmcfm()) < 0) return(y);
  8075.         break;
  8076.       case PAD_FLOW_CONTROL_BY_PAD:
  8077.         if ((y = cmnum("PAD pad flow control","",10,&z,xxstring)) < 0)
  8078.           return(y);
  8079.         if (z != 0 && z != 1) {
  8080.             printf("?The choices are 0 or 1\n");
  8081.             return(-2);
  8082.         }
  8083.         if ((y = cmcfm()) < 0) return(y);
  8084.         break;
  8085.       case PAD_SUPPRESSION_OF_SIGNALS:
  8086.         if ((y = cmnum("PAD service","",10,&z,xxstring)) < 0) return(y);
  8087.         if (z != 0 && z != 1) {
  8088.             printf("?The choices are 0 or 1\n");
  8089.             return(-2);
  8090.         }
  8091.         if ((y = cmcfm()) < 0) return(y);
  8092.         break;
  8093.  
  8094.       case PAD_BREAK_ACTION:
  8095.         if ((y = cmnum("PAD break action","",10,&z,xxstring)) < 0) return(y);
  8096.         if (z != 0 && z != 1 && z != 2 && z != 5 && z != 8 && z != 21) {
  8097.             printf("?The choices are 0, 1, 2, 5, 8 or 21\n");
  8098.             return(-2);
  8099.         }
  8100.         if ((y = cmcfm()) < 0) return(y);
  8101.         break;
  8102.  
  8103.       case PAD_SUPPRESSION_OF_DATA:
  8104.         if ((y = cmnum("PAD data delivery","",10,&z,xxstring)) < 0) return(y);
  8105.         if (z != 0 && z != 1) {
  8106.             printf("?The choices are 0 or 1\n");
  8107.             return(-2);
  8108.         }
  8109.         if ((y = cmcfm()) < 0) return(y);
  8110.         break;
  8111.  
  8112.       case PAD_PADDING_AFTER_CR:
  8113.         if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
  8114.         if (z < 0 || z > 7) {
  8115.             printf("?The choices are 0 or 1 <= crpad <= 7\n");
  8116.             return(-2);
  8117.         }
  8118.         if ((y = cmcfm()) < 0) return(y);
  8119.         break;
  8120.  
  8121.       case PAD_LINE_FOLDING:
  8122.         if ((y = cmnum("PAD linefold","",10,&z,xxstring)) < 0) return(y);
  8123.         if (z < 0 || z > 255) {
  8124.             printf("?The choices are 0 or 1 <= linefold <= 255\n");
  8125.             return(-2);
  8126.         }
  8127.         if ((y = cmcfm()) < 0) return(y);
  8128.         break;
  8129.  
  8130.       case PAD_LINE_SPEED:
  8131.         if ((y = cmnum("PAD baudrate","",10,&z,xxstring)) < 0) return(y);
  8132.         if (z < 0 || z > 18) {
  8133.             printf("?The choices are 0 <= baudrate <= 18\n");
  8134.             return(-2);
  8135.         }
  8136.         if ((y = cmcfm()) < 0) return(y);
  8137.         break;
  8138.  
  8139.       case PAD_FLOW_CONTROL_BY_USER:
  8140.         if ((y = cmnum("PAD terminal flow control","",10,&z,xxstring)) < 0)
  8141.             return(y);
  8142.         if (z != 0 && z != 1) {
  8143.             printf("?The choices are 0 or 1\n");
  8144.             return(-2);
  8145.         }
  8146.         if ((y = cmcfm()) < 0) return(y);
  8147.         break;
  8148.  
  8149.       case PAD_LF_AFTER_CR:
  8150.         if ((y = cmnum("PAD crpad","",10,&z,xxstring)) < 0) return(y);
  8151.         if (z < 0 || z == 3 || z > 7) {
  8152.             printf("?The choices are 0, 1, 2, 4, 5, 6 or 7\n");
  8153.             return(-2);
  8154.         }
  8155.         if ((y = cmcfm()) < 0) return(y);
  8156.         break;
  8157.  
  8158.       case PAD_PADDING_AFTER_LF:
  8159.         if ((y = cmnum("PAD lfpad","",10,&z,xxstring)) < 0) return(y);
  8160.         if (z < 0 || z > 7) {
  8161.             printf("?The choices are 0 or 1 <= lfpad <= 7\n");
  8162.             return(-2);
  8163.         }
  8164.         if ((y = cmcfm()) < 0) return(y);
  8165.         break;
  8166.  
  8167.       case PAD_EDITING:
  8168.         if ((y = cmnum("PAD edit control","",10,&z,xxstring)) < 0) return(y);
  8169.         if (z != 0 && z != 1) {
  8170.             printf("?The choices are 0 or 1\n");
  8171.             return(-2);
  8172.         }
  8173.         if ((y = cmcfm()) < 0) return(y);
  8174.         break;
  8175.  
  8176.       case PAD_CHAR_DELETE_CHAR:
  8177.         if ((y = cmnum("PAD char delete char","",10,&z,xxstring)) < 0)
  8178.             return(y);
  8179.         if (z < 0 || z > 127) {
  8180.             printf("?The choices are 0 or 1 <= chardelete <= 127\n");
  8181.             return(-2);
  8182.         }
  8183.         if ((y = cmcfm()) < 0) return(y);
  8184.         break;
  8185.  
  8186.       case PAD_BUFFER_DELETE_CHAR:
  8187.         if ((y = cmnum("PAD buffer delete char","",10,&z,xxstring)) < 0)
  8188.             return(y);
  8189.         if (z < 0 || z > 127) {
  8190.             printf("?The choices are 0 or 1 <= bufferdelete <= 127\n");
  8191.             return(-2);
  8192.         }
  8193.         if ((y = cmcfm()) < 0) return(y);
  8194.         break;
  8195.  
  8196.       case PAD_BUFFER_DISPLAY_CHAR:
  8197.         if ((y = cmnum("PAD display line char","",10,&z,xxstring)) < 0)
  8198.             return(y);
  8199.         if (z < 0 || z > 127) {
  8200.             printf("?The choices are 0 or 1 <= displayline <= 127\n");
  8201.             return(-2);
  8202.         }
  8203.         if ((y = cmcfm()) < 0) return(y);
  8204.         break;
  8205.     }
  8206.     padparms[x] = z;
  8207.     return(success = 1);
  8208. }
  8209. #endif /* IBMX25 */
  8210. #endif /* ANYX25 */
  8211.  
  8212. #ifndef NOXFER
  8213. int
  8214. setat(rmsflg) int rmsflg; {
  8215.     int xx;
  8216.     if ((y = cmkey(attrtab,natr,"File Attribute packets","",xxstring)) < 0)
  8217.       return(y);
  8218.     if (y == AT_XALL) {                 /* ATTRIBUTES ALL ON or ALL OFF */
  8219.         if ((z = seton(&xx)) < 0) return(z);
  8220.         if (rmsflg) {
  8221.             printf("Sorry, command not available\n");
  8222.             return(-9);
  8223.         } else {
  8224.             atenci = xx;                /* Encoding in */
  8225.             atenco = xx;                /* Encoding out */
  8226.             atdati = xx;                /* Date in */
  8227.             atdato = xx;                /* Date out */
  8228.             atdisi = xx;                /* Disposition in/out */
  8229.             atdiso = xx;
  8230.             atleni = xx;                /* Length in/out (both kinds) */
  8231.             atleno = xx;
  8232.             atblki = xx;                /* Blocksize in/out */
  8233.             atblko = xx;
  8234.             attypi = xx;                /* File type in/out */
  8235.             attypo = xx;
  8236.             atsidi = xx;                /* System ID in/out */
  8237.             atsido = xx;
  8238.             atsysi = xx;                /* System-dependent params in/out */
  8239.             atsyso = xx;
  8240. #ifdef CK_PERMS                         /* Protection */
  8241.             atlpri = xx;                /* Local in */
  8242.             atlpro = xx;                /* Local out */
  8243.             atgpri = xx;                /* Generic in */
  8244.             atgpro = xx;                /* Generic out */
  8245. #endif /* CK_PERMS */
  8246. #ifdef STRATUS
  8247.             atfrmi = xx;                /* Format in/out */
  8248.             atfrmo = xx;
  8249.             atcrei = xx;                /* Creator id in/out */
  8250.             atcreo = xx;
  8251.             atacti = xx;                /* Account in/out */
  8252.             atacto = xx;
  8253. #endif /* STRATUS */
  8254.         }
  8255.         return(z);
  8256.     } else if (y == AT_ALLY || y == AT_ALLN) { /* ATTRIBUTES ON or OFF */
  8257.         if ((x = cmcfm()) < 0) return(x);
  8258.         atcapr = (y == AT_ALLY) ? 1 : 0;
  8259.         if (rmsflg) {
  8260.             sstate = setgen('S', "132", atcapr ? "1" : "0", "");
  8261.             return((int) sstate);
  8262.         } else return(success = 1);
  8263.     }
  8264.     /* Otherwise, it's an individual attribute that wants turning off/on */
  8265.  
  8266.     if ((z = cmkey(onoff,2,"","",xxstring)) < 0) return(z);
  8267.     if ((x = cmcfm()) < 0) return(x);
  8268.  
  8269. /* There are better ways to do this... */
  8270. /* The real problem is that we're not separating the in and out cases */
  8271. /* and so we have to arbitrarily pick the "in" case, i.e tell the remote */
  8272. /* server to ignore incoming attributes of the specified type, rather */
  8273. /* than telling it not to send them.  The protocol does not (yet) define */
  8274. /* codes for "in-and-out-at-the-same-time". */
  8275.  
  8276.     switch (y) {
  8277. #ifdef CK_PERMS
  8278. /* We're lumping local and generic protection together for now... */
  8279.       case AT_LPRO:
  8280.       case AT_GPRO:
  8281.         if (rmsflg) {
  8282.             sstate = setgen('S', "143", z ? "1" : "0", "");
  8283.             return((int) sstate);
  8284.         }
  8285.         atlpri = atlpro = atgpri = atgpro = z; break;
  8286. #endif /* CK_PERMS */
  8287.       case AT_DISP:
  8288.         if (rmsflg) {
  8289.             sstate = setgen('S', "142", z ? "1" : "0", "");
  8290.             return((int) sstate);
  8291.         }
  8292.         atdisi = atdiso = z; break;
  8293.       case AT_ENCO:
  8294.         if (rmsflg) {
  8295.             sstate = setgen('S', "141", z ? "1" : "0", "");
  8296.             return((int) sstate);
  8297.         }
  8298.         atenci = atenco = z; break;
  8299.       case AT_DATE:
  8300.         if (rmsflg) {
  8301.             sstate = setgen('S', "135", z ? "1" : "0", "");
  8302.             return((int) sstate);
  8303.         }
  8304.         atdati = atdato = z; break;
  8305.       case AT_LENB:
  8306.       case AT_LENK:
  8307.         if (rmsflg) {
  8308.             sstate = setgen('S', "133", z ? "1" : "0", "");
  8309.             return((int) sstate);
  8310.         }
  8311.         atleni = atleno = z; break;
  8312.       case AT_BLKS:
  8313.         if (rmsflg) {
  8314.             sstate = setgen('S', "139", z ? "1" : "0", "");
  8315.             return((int) sstate);
  8316.         }
  8317.         atblki = atblko = z; break;
  8318.       case AT_FTYP:
  8319.         if (rmsflg) {
  8320.             sstate = setgen('S', "134", z ? "1" : "0", "");
  8321.             return((int) sstate);
  8322.         }
  8323.         attypi = attypo = z; break;
  8324. #ifdef STRATUS
  8325.       case AT_CREA:
  8326.         if (rmsflg) {
  8327.             sstate = setgen('S', "136", z ? "1" : "0", "");
  8328.             return((int) sstate);
  8329.         }
  8330.         atcrei = atcreo = z; break;
  8331.       case AT_ACCT:
  8332.         if (rmsflg) {
  8333.             sstate = setgen('S', "137", z ? "1" : "0", "");
  8334.             return((int) sstate);
  8335.         }
  8336.         atacti = atacto = z; break;
  8337. #endif /* STRATUS */
  8338.       case AT_SYSI:
  8339.         if (rmsflg) {
  8340.             sstate = setgen('S', "145", z ? "1" : "0", "");
  8341.             return((int) sstate);
  8342.         }
  8343.         atsidi = atsido = z; break;
  8344.       case AT_RECF:
  8345.         if (rmsflg) {
  8346.             sstate = setgen('S', "146", z ? "1" : "0", "");
  8347.             return((int) sstate);
  8348.         }
  8349.         atfrmi = atfrmo = z; break;
  8350.       case AT_SYSP:
  8351.         if (rmsflg) {
  8352.             sstate = setgen('S', "147", z ? "1" : "0", "");
  8353.             return((int) sstate);
  8354.         }
  8355.         atsysi = atsyso = z; break;
  8356.       default:
  8357.         printf("?Not available\n");
  8358.         return(-2);
  8359.     }
  8360.     return(1);
  8361. }
  8362. #endif /* NOXFER */
  8363.  
  8364. #ifndef NOSPL
  8365. int
  8366. setinp() {
  8367.     if ((y = cmkey(inptab,ninp,"","",xxstring)) < 0) return(y);
  8368.     switch (y) {
  8369. #ifdef OS2
  8370.       case IN_PAC:                      /* SET INPUT PACING */
  8371.         z = cmnum("milliseconds","0",10,&x,xxstring);
  8372.         return(setnum(&tt_inpacing,x,z,1000));
  8373.       case IN_TRM:                      /* SET INPUT TERMINAL */
  8374.         return(seton(&interm));
  8375. #endif /* OS2 */
  8376.       case IN_DEF:                      /* SET INPUT DEFAULT-TIMEOUT */
  8377.         z = cmnum("Positive number","",10,&x,xxstring);
  8378.         return(setnum(&indef,x,z,94));
  8379. #ifdef CKFLOAT
  8380.       case IN_SCA:                      /* SET INPUT SCALE-FACTOR */
  8381.     if ((x = cmfld("Number such as 2 or 0.5","1.0",&s, xxstring)) < 0)
  8382.       return(x);
  8383.         if (isfloat(s,0)) {        /* A floating-point number? */
  8384.             extern char * inpscale;
  8385.         inscale = floatval;        /* Yes, get its value */
  8386.         makestr(&inpscale,s);    /* Save it as \v(inscale) */
  8387.         return(success = 1);
  8388.     } else {
  8389.         return(-2);
  8390.     }
  8391. #endif    /* CKFLOAT */
  8392.       case IN_TIM:                      /* SET INPUT TIMEOUT-ACTION */
  8393.         if ((z = cmkey(intimt,2,"","",xxstring)) < 0) return(z);
  8394.         if ((x = cmcfm()) < 0) return(x);
  8395.         intime[cmdlvl] = z;
  8396.         return(success = 1);
  8397.       case IN_CAS:                      /* SET INPUT CASE */
  8398.         if ((z = cmkey(incast,2,"","",xxstring)) < 0) return(z);
  8399.         if ((x = cmcfm()) < 0) return(x);
  8400.         inpcas[cmdlvl] = z;
  8401.         return(success = 1);
  8402.       case IN_ECH:                      /* SET INPUT ECHO */
  8403.         return(seton(&inecho));
  8404.       case IN_SIL:                      /* SET INPUT SILENCE */
  8405.         z = cmnum("Seconds of inactivity before INPUT fails","",10,&x,
  8406.                   xxstring);
  8407.         return(setnum(&insilence,x,z,-1));
  8408.  
  8409.       case IN_BUF:                      /* SET INPUT BUFFER-SIZE */
  8410.         if ((z = cmnum("Number of bytes in INPUT buffer",
  8411.                        ckitoa(INPBUFSIZ),10,&x, xxstring)) < 0)
  8412.           return(z);
  8413.         if ((y = cmcfm()) < 0) return(y);
  8414.         inbufsize = 0;
  8415.         if (inpbuf) {
  8416.             free(inpbuf);
  8417.             inpbuf = NULL;
  8418.             inpbp = NULL;
  8419.         }
  8420.         if (!(s = (char *)malloc(x + 1)))
  8421.           return(0);
  8422.         inpbuf = s;
  8423.         inpbp = s;
  8424.         inbufsize = x;
  8425.         for (x = 0; x <= inbufsize; x++)
  8426.           inpbuf[x] = NUL;
  8427.         return(success = 1);
  8428.  
  8429. #ifdef CK_AUTODL
  8430.       case IN_ADL:                      /* AUTODOWNLOAD */
  8431.         return(seton(&inautodl));
  8432. #endif /* CK_AUTODL */
  8433.  
  8434.       case IN_CAN:                      /* SET INPUT INTERRUPTS */
  8435.         return(seton(&inintr));
  8436.     }
  8437.     return(0);
  8438. }
  8439. #endif /* NOSPL */
  8440.  
  8441. #ifdef NETCONN
  8442. VOID
  8443. ndreset() {
  8444. #ifndef NODIAL                          /* This depends on DIAL... */
  8445.     int i=0, j=0;
  8446.     if (!ndinited)                      /* Don't free garbage... */
  8447.       return;
  8448.     for (i = 0; i < nhcount; i++) {     /* Clean out previous list */
  8449.         if (nh_p[i])
  8450.           free(nh_p[i]);
  8451.         nh_p[i] = NULL;
  8452.         if (nh_p2[i])
  8453.           free(nh_p2[i]);
  8454.         nh_p2[i] = NULL;
  8455.         for (j = 0; j < 4; j++) {
  8456.             if (nh_px[j][i])
  8457.               free(nh_px[j][i]);
  8458.             nh_px[j][i] = NULL;
  8459.         }
  8460.     }
  8461. #endif /* NODIAL */
  8462. }
  8463.  
  8464. VOID
  8465. ndinit() {                              /* Net directory pointers */
  8466. #ifndef NODIAL                          /* This depends on DIAL... */
  8467.     int i, j;
  8468.     if (ndinited++)                     /* Don't do this more than once. */
  8469.       return;
  8470.     for (i = 0; i < MAXDDIR; i++) {     /* Init all pointers to NULL */
  8471.         netdir[i] = NULL;
  8472.     }
  8473.     for (i = 0; i < MAXDNUMS; i++) {
  8474.         nh_p[i] = NULL;
  8475.         nh_p2[i] = NULL;
  8476.         for (j = 0; j < 4; j++)
  8477.           nh_px[j][i] = NULL;
  8478.     }
  8479. #endif /* NODIAL */
  8480. }
  8481.  
  8482. #ifndef NODIAL
  8483. #ifdef NETCONN
  8484. VOID                                    /* Get net defaults from environment */
  8485. getnetenv() {
  8486.     char *p = NULL;
  8487.  
  8488.     makestr(&p,getenv("K_NET_DIRECTORY")); /* Dialing directories */
  8489.     if (p) {
  8490.         int i;
  8491.         xwords(p,MAXDDIR,netdir,0);
  8492.         for (i = 0; i < MAXDDIR; i++) { /* Fill in any gaps... */
  8493.             if (!netdir[i+1])
  8494.               break;
  8495.             else
  8496.               netdir[i] = netdir[i+1];
  8497.             debug(F111,"netdir[i]",netdir[i],i);
  8498.         }
  8499.         nnetdir = i;
  8500.     }
  8501. }
  8502. #endif /* NETCONN */
  8503. #endif /* NODIAL */
  8504.  
  8505. int
  8506. #ifdef CK_ANSIC
  8507. lunet(char *s)                          /* s = name to look up   */
  8508. #else
  8509. lunet(s) char *s;
  8510. #endif /* CK_ANSIC */
  8511. /* lunet */ {
  8512. #ifndef NODIAL                          /* This depends on DIAL... */
  8513.     int n, n1, t, dd = 0;
  8514.     int ambiguous = 0;
  8515.     FILE * f;
  8516.     char *line = NULL;
  8517.     extern int dialdpy;
  8518.     int netdpy = dialdpy;
  8519.     char *info[8];
  8520.  
  8521.     nhcount = 0;                        /* Set this before returning */
  8522.  
  8523.     if (!s || nnetdir < 1)              /* Validate arguments */
  8524.       return(-1);
  8525.  
  8526.     if (isdigit(*s) || *s == '*' || *s == '.')
  8527.       return(0);
  8528.  
  8529.     if ((n1 = (int) strlen(s)) < 1)     /* Length of string to look up */
  8530.       return(-1);
  8531.  
  8532.     if (!(line = malloc(1024)))         /* Allocate input buffer */
  8533.       return(-1);
  8534.  
  8535.   lu_again:
  8536.     f = NULL;                           /* Network directory file descriptor */
  8537.     t = nhcount = 0;                    /* Match count */
  8538.     dd = 0;                             /* Directory counter */
  8539.  
  8540.     dirline = 0;
  8541.     while (1) {                         /* We make one pass */
  8542.         if (!f) {                       /* Directory not open */
  8543.             if (dd >= nnetdir)          /* No directories left? */
  8544.               break;                    /* Done. */
  8545.             if ((f = fopen(netdir[dd],"r")) == NULL) { /* Open it */
  8546.                 perror(netdir[dd]);     /* Can't, print message saying why */
  8547.                 dd++;
  8548.                 continue;               /* But go on to next one. */
  8549.             }
  8550.             if (netdpy)
  8551.               printf("Opening %s...\n",netdir[dd]);
  8552.             dd++;
  8553.         }
  8554.         line[0] = NUL;
  8555.         if (getnct(line,1023,f,1) < 0) { /* Read a line */
  8556.             if (f) {                    /* f can be clobbered! */
  8557.                 fclose(f);              /* Close the file */
  8558.                 f = NULL;               /* Indicate next one needs opening */
  8559.             }
  8560.             continue;
  8561.         }
  8562.         if (!line[0])                   /* Empty line */
  8563.           continue;
  8564.  
  8565.         xwords(line,7,info,0);          /* Parse it */
  8566.  
  8567.         if (!info[1] || !info[2] || !info[3]) /* Required fields */
  8568.           continue;
  8569.         if (*info[1] == ';')            /* Full-line comment */
  8570.           continue;
  8571.         if ((n = (int) strlen(info[1])) < 1) /* Length of name-tag */
  8572.           continue;
  8573.         if (n < n1)                     /* Search name is longer */
  8574.           continue;                     /* Can't possibly match */
  8575.         if (ambiguous && n != n1)
  8576.           continue;
  8577.         if (ckstrcmp(s,info[1],n1,0))   /* Compare using length of */
  8578.           continue;                     /* search string s. */
  8579.  
  8580.         /* Have a match */
  8581.  
  8582.         makestr(&(nh_p[nhcount]), info[3]);    /* address */
  8583.         makestr(&(nh_p2[nhcount]),info[2]);    /* net type */
  8584.         makestr(&(nh_px[0][nhcount]),info[4]); /* net-specific stuff... */
  8585.         makestr(&(nh_px[1][nhcount]),info[5]);
  8586.         makestr(&(nh_px[2][nhcount]),info[6]);
  8587.         makestr(&(nh_px[3][nhcount]),info[7]);
  8588.  
  8589.         nhcount++;                      /* Count this match */
  8590.         if (nhcount > MAXDNUMS) {       /* Watch out for too many */
  8591.             printf("Warning: %d matches found, %d max\n",
  8592.                    nhcount,
  8593.                    MAXDNUMS
  8594.                    );
  8595.             nhcount = MAXDNUMS;
  8596.             break;
  8597.         }
  8598.         if (nhcount == 1) {             /* First one - save entry name */
  8599.             if (n_name) {               /* Free the one from before if any */
  8600.                 free(n_name);
  8601.                 n_name = NULL;
  8602.             }
  8603.             if (!(n_name = (char *)malloc(n + 1))) { /* Allocate new storage */
  8604.                 printf("?memory allocation error - lunet:3\n");
  8605.                 if (line) {
  8606.                     free(line);
  8607.                     line = NULL;
  8608.                 }
  8609.                 nhcount = 0;
  8610.                 return(-1);
  8611.             }
  8612.             t = n;                      /* Remember its length */
  8613.             strcpy(n_name,info[1]);     /* safe */
  8614.         } else {                        /* Second or subsequent one */
  8615.             if ((int) strlen(info[1]) == t) /* Lengths compare */
  8616.               if (!ckstrcmp(n_name,info[1],t,0)) /* Caseless compare OK */
  8617.                 continue;
  8618.  
  8619.             /* Name given by user matches entries with different names */
  8620.  
  8621.             if (ambiguous)              /* Been here before */
  8622.               break;
  8623.  
  8624.             ambiguous = 1;              /* Now an exact match is required */
  8625.             ndreset();                  /* Clear out previous list */
  8626.             goto lu_again;              /* Do it all over again. */
  8627.         }
  8628.     }
  8629.     if (line) {
  8630.         free(line);
  8631.         line = NULL;
  8632.     }
  8633.     if (nhcount == 0 && ambiguous)
  8634.       printf("?\"%s\" - ambiguous in network directory\n",s);
  8635. #else
  8636.     nhcount = 0;
  8637. #endif /* NODIAL */
  8638.     return(nhcount);
  8639. }
  8640. #endif /* NETCONN */
  8641.  
  8642. #ifndef NOLOCAL
  8643. /*  C L S C O N N X  --  Close connection  */
  8644.  
  8645. int
  8646. clsconnx(ask) int ask; {
  8647.     int x, rc = 0;
  8648. #ifdef NEWFTP
  8649.     extern int ftpget, ftpisopen();
  8650.     if ((ftpget == 1) || ((ftpget == 2) && !local && ftpisopen()))
  8651.       return(success = ftpbye());
  8652. #endif /* NEWFTP */
  8653.     debug(F101,"clsconnx local","",local);
  8654.     if (local) {
  8655.         x = ask ? hupok(1) : 1;         /* Make sure it's OK to close */
  8656.         if (!x) {
  8657.             rc = -1;
  8658.             debug(F101,"clsconnx hupok says no","",rc);
  8659.             return(rc);
  8660.         }
  8661.         ttflui();                       /* Clear away buffered up junk */
  8662. #ifndef NODIAL
  8663. #ifdef OS2ONLY
  8664. /* Don't hangup a line that is shared with the SLIP or PPP driver */
  8665.         if (!ttslip && !ttppp)
  8666. #endif /* OS2ONLY */
  8667.           mdmhup();
  8668. #endif /* NODIAL */
  8669.         if (network && msgflg)
  8670.           printf(" Closing connection\n");
  8671.         ttclos(0);                      /* Close old connection, if any */
  8672.         rc = 1;
  8673.         {
  8674.             extern int wasclosed, whyclosed;
  8675.             if (wasclosed) {
  8676.                 whyclosed = WC_CLOS;
  8677. #ifndef NOSPL
  8678.                 if (nmac) {             /* Any macros defined? */
  8679.                     int k;              /* Yes */
  8680.                     /* printf("ON_CLOSE CLSCONNX\n"); */
  8681.                     wasclosed = 0;
  8682.                     k = mlook(mactab,"on_close",nmac);  /* Look this up */
  8683.                     if (k >= 0) {                       /* If found, */
  8684.                         if (dodo(k,ckitoa(whyclosed),0) > -1) /* set it up, */
  8685.                           parser(1);                    /* and execute it */
  8686.                     }
  8687.                 }
  8688. #endif /* NOSPL */
  8689.                 whyclosed = WC_REMO;
  8690.                 wasclosed = 0;
  8691.             }
  8692.         }
  8693.     }
  8694. #ifdef VMS                              /* Or maybe #ifndef UNIX? */
  8695.     else {                              /* Need to do this in VMS to */
  8696.         ttclos(0);                      /* free the tty channel number */
  8697.         rc = 1;                         /* obtained in ttopen() or else */
  8698.     }                                   /* subsequent ttopen's won't work */
  8699. #endif /* VMS */
  8700.     dologend();
  8701.     haveline = 0;
  8702.     if (mdmtyp < 0) {                   /* Switching from net to async? */
  8703.         if (mdmsav > -1)                /* Restore modem type from last */
  8704.           mdmtyp = mdmsav;              /* SET MODEM command, if any. */
  8705.         else
  8706.           mdmtyp = 0;
  8707.         mdmsav = -1;
  8708.     }
  8709.     if (network)
  8710.       network = 0;
  8711. #ifdef NETCONN
  8712.     if (oldplex > -1) {                 /* Restore previous duplex setting. */
  8713.         duplex = oldplex;
  8714.         oldplex = -1;
  8715.     }
  8716. #endif /* NETCONN */
  8717. #ifndef MAC
  8718.     ckstrncpy(ttname,dftty,TTNAMLEN);   /* Restore default communication */
  8719. #endif /* MAC */
  8720.     local = dfloc;                      /* device and local/remote status */
  8721.     if (local) {
  8722.         cxtype = CXT_DIRECT;            /* Something reasonable */
  8723.         speed = ttgspd();               /* Get the current speed */
  8724.     } else {
  8725.         cxtype = CXT_REMOTE;
  8726.         speed = -1L;
  8727.     }
  8728. #ifndef NOXFER
  8729.     if (xreliable > -1 && !setreliable) {
  8730.         reliable = xreliable;
  8731.         debug(F101,"clsconnx reliable A","",reliable);
  8732.     } else if (!setreliable) {
  8733.         reliable = SET_AUTO;
  8734.         debug(F101,"clsconnx reliable B","",reliable);
  8735.     }
  8736. #endif /* NOXFER */
  8737.     setflow();                          /* Revert flow control */
  8738.     return(rc);
  8739. }
  8740.  
  8741. int
  8742. clskconnx(x) int x; {                   /* Close Kermit connection only */
  8743.     int t, rc;                          /* (not FTP) */
  8744. #ifdef NEWFTP
  8745.     extern int ftpget;
  8746.     t = ftpget;
  8747.     ftpget = 0;
  8748. #endif /* NEWFTP */
  8749.     rc = clsconnx(x);
  8750. #ifdef NEWFTP
  8751.     ftpget = t;
  8752. #endif /* NEWFTP */
  8753.     return(rc);
  8754. }
  8755.  
  8756. /* May 2002: setlin() decomposition starts here ... */
  8757.  
  8758. #ifdef OS2
  8759. #define SRVBUFSIZ PIPENAML
  8760. #else /* OS2 */
  8761. #define SRVBUFSIZ 63
  8762. #endif /* OS2 */
  8763. #define HOSTNAMLEN 15*65
  8764.  
  8765. int netsave = -1;
  8766. static char * tmpstring = NULL;
  8767. static char * tmpusrid = NULL;
  8768.  
  8769. #ifdef SSHCMD
  8770. char * sshcmd = NULL;
  8771. char * defsshcmd = "ssh -e none";
  8772. #else
  8773. #ifdef SSHBUILTIN
  8774. char * sshrcmd = NULL;
  8775. char * sshtmpcmd = NULL;
  8776. #endif /* SSHBUILTIN */
  8777. #endif /* SSHCMD */
  8778.  
  8779. /* c x _ f a i l  --  Common error exit routine for cx_net, cx_line */
  8780.  
  8781. int
  8782. cx_fail(msg, text) int msg; char * text; {
  8783.     makestr(&slmsg,text);        /* For the record (or GUI) */
  8784.     if (msg)                /* Not GUI, not quiet, etc */
  8785.       printf("?%s\n",text);        /* Print error message */
  8786.     slrestor();                /* Restore LINE/HOST to known state */
  8787.     return(msg ? -9 : (success = 0));    /* Return appropriate code */
  8788. }
  8789.  
  8790. #ifdef NETCONN
  8791. /* c x _ n e t  --  Make a network connection */
  8792.  
  8793. /*
  8794.   Call with:
  8795.     net      = network type
  8796.     protocol = protocol type
  8797.     host     = string pointer to host name.
  8798.     svc      = string pointer to service or port on host.
  8799.     username = username for connection
  8800.     password = password for connection
  8801.     command  = command to execute
  8802.     param1   = Telnet: Authentication type
  8803.                SSH:    Version
  8804.     param2   = Telnet: Encryption type
  8805.                SSH:    Command as Subsystem
  8806.     param3   = Telnet: 1 to wait for negotiations, 0 otherwise
  8807.                SSH:    X11 Forwarding
  8808.     cx       = 1 to automatically enter Connect mode, 0 otherwise.
  8809.     sx       = 1 to automatically enter Server mode, 0 otherwise.
  8810.     flag     = if no host name given, 1 = close current connection, 0 = resume
  8811.     gui      = 1 if called from GUI dialog, 0 otherwise.
  8812.   Returns:
  8813.     1 on success
  8814.     0 on failure and no message printed, slmsg set to failure message.
  8815.    -9 on failure and message printed, ditto.
  8816. */
  8817. int
  8818. #ifdef CK_ANSIC
  8819. cx_net( int net, int protocol, char * xhost, char * svc, 
  8820.         char * username, char * password, char * command,
  8821.         int param1, int param2, int param3, int cx, int sx, int flag, int gui)
  8822. #else /* CK_ANSIC */
  8823. cx_net(net, protocol, xhost, svc,
  8824.        username, password, command,
  8825.        param1, param2, param3, cx, sx, flag, gui)
  8826.     char * xhost, * svc, * username, *password, *command; 
  8827.     int net, protocol, cx, sx, flag, param1, param2, param3, gui; 
  8828. #endif /* CK_ANSIC */
  8829. /* cx_net */ {
  8830.  
  8831.     int i, n, x, msg;
  8832.     int _local = -1;
  8833.  
  8834.     extern char pwbuf[], * g_pswd;
  8835.     extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
  8836.  
  8837.     char srvbuf[SRVBUFSIZ+1];        /* Service */
  8838.     char hostbuf[HOSTNAMLEN];        /* Host buffer to manipulate */
  8839.     char hostname[HOSTNAMLEN];        /* Copy of host parameter */
  8840.     char * host = hostbuf;        /* Pointer to copy of host param */
  8841.  
  8842.     if (!xhost) xhost = "";        /* Watch out for null pointers */
  8843.     if (!svc) svc = "";
  8844.     ckstrncpy(host,xhost,HOSTNAMLEN);    /* Avoid buffer confusion */
  8845.  
  8846.     debug(F110,"cx_net host",host,0);
  8847.     debug(F111,"cx_net service",svc,SRVBUFSIZ);
  8848.     debug(F101,"cx_net network type","",net);
  8849.  
  8850.     msg = (gui == 0) && msgflg;        /* Whether to print messages */
  8851.  
  8852. #ifndef NODIAL
  8853.     debug(F101,"cx_net nnetdir","",nnetdir);
  8854.     x = 0;                /* Look up in network directory */
  8855.     if (*host == '=') {            /* If number starts with = sign */
  8856.     host++;                /* strip it */
  8857.     while (*host == SP) host++;    /* and any leading spaces */
  8858.     debug(F110,"cx_net host 2",host,0);
  8859.     nhcount = 0;
  8860.     } else if (*host) {            /* We want to look it up. */
  8861.     if (nnetdir > 0)        /* If there is a directory... */
  8862.       x = lunet(host);        /* (sets nhcount) */
  8863.     else                /* otherwise */
  8864.       nhcount = 0;            /* we didn't find any there */
  8865.     if (x < 0)            /* Internal error? */
  8866.       return(cx_fail(msg,"Network directory lookup error"));
  8867.     debug(F111,"cx_net lunet nhcount",host,nhcount);
  8868.     }
  8869. #endif /* NODIAL */
  8870.  
  8871.     /* New connection wanted.  Make a copy of the host name/address... */
  8872.  
  8873.     if (clskconnx(1) < 0)        /* Close current Kermit connection */
  8874.       return(cx_fail(msg,"Error closing previous connection"));
  8875.  
  8876.     if (*host) {            /* They gave a hostname */
  8877.     _local = 1;            /* Network connection always local */
  8878.     if (mdmsav < 0)
  8879.       mdmsav = mdmtyp;        /* Remember old modem type */
  8880.     mdmtyp = -net;            /* Special code for network */
  8881.     } else {                /* They just said "set host" */
  8882.     host = dftty;            /* So go back to normal */
  8883.     _local = dfloc;            /* default tty, location, */
  8884.     if (flag) {            /* Close current connection */
  8885.         setflow();            /* Maybe change flow control */
  8886.         haveline = 1;        /* (* is this right? *) */
  8887.         dologend();
  8888. #ifndef NODIAL
  8889.         dialsta = DIA_UNK;
  8890. #endif /* NODIAL */
  8891. #ifdef LOCUS
  8892.         if (autolocus) {
  8893.         setlocus(1,1);
  8894.         }
  8895. #endif /* LOCUS */
  8896.             /* XXX - Is this right? */
  8897.         /* Should we be returning without doing anything ? */
  8898.         /* Yes it's right -- we closed the old connection just above. */
  8899.         return(success = 1);        
  8900.     }
  8901.     }
  8902.     success = 0;
  8903.     if (host != line)                   /* line[] is a global */
  8904.       ckstrncpy(line,host,LINBUFSIZ);
  8905.     ckstrncpy(hostname,host,HOSTNAMLEN);
  8906.     ckstrncpy(srvbuf,svc,SRVBUFSIZ+1);
  8907.  
  8908. #ifndef NODIAL
  8909.     if ((nhcount > 1) && msg) {
  8910.     int k;
  8911.     printf("%d entr%s found for \"%s\"%s\n",
  8912.            nhcount,
  8913.            (nhcount == 1) ? "y" : "ies",
  8914.            s,
  8915.            (nhcount > 0) ? ":" : "."
  8916.            );
  8917.     for (i = 0; i < nhcount; i++) {
  8918.         printf("%3d. %-12s => %-9s %s",
  8919.                i+1,n_name,nh_p2[i],nh_p[i]);
  8920.         for (k = 0; k < 4; k++) { /* Also list net-specific items */
  8921.         if (nh_px[k][i])      /* free format... */
  8922.           printf(" %s",nh_px[k][i]);
  8923.         else
  8924.           break;
  8925.         }
  8926.         printf("\n");
  8927.     }
  8928.     }
  8929.     if (nhcount == 0)
  8930.       n = 1;
  8931.     else
  8932.       n = nhcount;
  8933. #else
  8934.     n = 1;
  8935.     nhcount = 0;
  8936. #endif /* NODIAL */
  8937.  
  8938.     for (i = 0; i < n; i++) {        /* Loop for each entry found */
  8939.     debug(F101,"cx_net loop i","",i);
  8940. #ifndef NODIAL
  8941.     if (nhcount > 0) {        /* If we found at least one entry... */
  8942.         ckstrncpy(line,nh_p[i],LINBUFSIZ); /* Copy current entry */
  8943.         if (lookup(netcmd,nh_p2[i],nnets,&x) > -1) { /* Net type */
  8944.         int xx;
  8945.         xx = netcmd[x].kwval;
  8946.         /* User specified SSH so don't let net directory override */
  8947.         if (net != NET_SSH || xx != NET_TCPB) {
  8948.             net = xx;
  8949.             mdmtyp  = 0 - net;
  8950.         }
  8951.         } else {
  8952.         makestr(&slmsg,"Network type not supported");
  8953.         if (msg)
  8954.           printf("Error - network type \"%s\" not supported\n",
  8955.              nh_p2[i]
  8956.                  );
  8957.         continue;
  8958.         }
  8959.         switch (net) {        /* Net-specific directory things */
  8960. #ifdef SSHBUILTIN
  8961.           case NET_SSH:        /* SSH */
  8962.                 /* Any SSH specific network directory stuff? */
  8963.                 break;                  /* NET_SSH */
  8964. #endif /* SSHBUILTIN */
  8965.  
  8966.           case NET_TCPB: {        /* TCP/IP TELNET,RLOGIN,... */
  8967. #ifdef TCPSOCKET
  8968.           char *q;
  8969.           int flag = 0;
  8970.  
  8971.           /* Extract ":service", if any, from host string */
  8972.           debug(F110,"cx_net service 1",line,0);
  8973.           for (q = line; (*q != '\0') && (*q != ':'); q++)
  8974.             ;
  8975.           if (*q == ':') { *q++ = NUL; flag = 1; }
  8976.           debug(F111,"cx_net service 2",line,flag);
  8977.  
  8978.           /* Get service, if any, from directory entry */
  8979.  
  8980.           if (!*srvbuf) {
  8981.               if (nh_px[0][i]) {
  8982.               ckstrncpy(srvbuf,nh_px[0][i],SRVBUFSIZ);
  8983.               debug(F110,"cx_net service 3",srvbuf,0);
  8984.               }
  8985.               if (flag) {
  8986.               ckstrncpy(srvbuf,q,SRVBUFSIZ);
  8987.               debug(F110,"cx_net service 4",srvbuf,0);
  8988.               }
  8989.           }
  8990.           ckstrncpy(hostname,line,HOSTNAMLEN);
  8991.  
  8992.           /* If we have a service, append to host name/address */
  8993.           if (*srvbuf) {
  8994.               ckstrncat(line, ":", LINBUFSIZ);
  8995.               ckstrncat(line, srvbuf, LINBUFSIZ);
  8996.               debug(F110,"cx_net service 5",line,0);
  8997.           }
  8998. #ifdef RLOGCODE
  8999.           /* If no service given but command was RLOGIN */
  9000.           else if (ttnproto == NP_RLOGIN) { /* add this... */
  9001.               ckstrncat(line, ":login",LINBUFSIZ);
  9002.               debug(F110,"cx_net service 6",line,0);
  9003.           }
  9004. #ifdef CK_AUTHENTICATION
  9005. #ifdef CK_KERBEROS
  9006.           else if (ttnproto == NP_K4LOGIN ||
  9007.                ttnproto == NP_K5LOGIN) { /* add this... */
  9008.               ckstrncat(line, ":klogin",LINBUFSIZ);
  9009.               debug(F110,"cx_net service 7",line,0);
  9010.           }
  9011.           else if (ttnproto == NP_EK4LOGIN ||
  9012.                ttnproto == NP_EK5LOGIN) { /* add this... */
  9013.               ckstrncat(line, ":eklogin",LINBUFSIZ);
  9014.               debug(F110,"cx_net service 8",line,0);
  9015.           }
  9016. #endif /* CK_KERBEROS */
  9017. #endif /* CK_AUTHENTICATION */
  9018. #endif /* RLOGCODE */
  9019.           else {        /* Otherwise, add ":telnet". */
  9020.               ckstrncat(line, ":telnet", LINBUFSIZ);
  9021.               debug(F110,"cx_net service 9",line,0);
  9022.           }
  9023.           if (username) {    /* This is a parameter... */
  9024.               ckstrncpy(uidbuf,username,UIDBUFLEN);
  9025.               uidflag = 1;
  9026.           }
  9027.           /* Fifth field, if any, is user ID (for rlogin) */
  9028.  
  9029.           if (nh_px[1][i] && !uidflag)
  9030.             ckstrncpy(uidbuf,username,UIDBUFLEN);
  9031. #ifdef RLOGCODE
  9032.           if (IS_RLOGIN() && !uidbuf[0])
  9033.             return(cx_fail(msg,"Username required"));
  9034. #endif /* RLOGCODE */
  9035. #endif /* TCPSOCKET */
  9036.           break;
  9037.           }
  9038.           case NET_PIPE:        /* Pipe */
  9039. #ifdef NPIPE
  9040.         if (!pipename[0]) { /* User didn't give a pipename */
  9041.             if (nh_px[0][i]) { /* But directory entry has one */
  9042.             if (strcmp(pipename,"\\pipe\\")) {
  9043.                 ckstrncpy(pipename,"\\pipe\\",LINBUFSIZ);
  9044.                 ckstrncat(srvbuf,nh_px[0][i],PIPENAML-6);
  9045.             } else {
  9046.                 ckstrncpy(pipename,nh_px[0][i],PIPENAML);
  9047.             }
  9048.             debug(F110,"cx_net pipeneme",pipename,0);
  9049.             }
  9050.         }
  9051. #endif /* NPIPE */
  9052.         break;
  9053.  
  9054.           case NET_SLAT:            /* LAT / CTERM */
  9055. #ifdef SUPERLAT
  9056.         if (!slat_pwd[0]) { /* User didn't give a password */
  9057.             if (nh_px[0][i]) { /* But directory entry has one */
  9058.             ckstrncpy(slat_pwd,nh_px[0][i],18);
  9059.             debug(F110,"cx_net SuperLAT password",slat_pwd,0);
  9060.             }
  9061.         }
  9062. #endif /* SUPERLAT */
  9063.         break;
  9064.  
  9065.           case NET_SX25:        /* X.25 keyword parameters */
  9066.           case NET_IX25:
  9067.           case NET_VX25: {
  9068. #ifdef ANYX25
  9069.           int k;            /* Cycle through the four fields */
  9070.           for (k = 0; k < 4; k++) {
  9071.               if (!nh_px[k][i]) /* Bail out if none left */
  9072.             break;
  9073.               if (!ckstrcmp(nh_px[k][i],"cug=",4,0)) {
  9074.               closgr = atoi(nh_px[k][i]+4);
  9075.               debug(F101,"X25 CUG","",closgr);
  9076.               } else if (!ckstrcmp(nh_px[k][i],"cud=",4,0)) {
  9077.               cudata = 1;
  9078.               ckstrncpy(udata,nh_px[k][i]+4,MAXCUDATA);
  9079.               debug(F110,"X25 CUD",cudata,0);
  9080.               } else if (!ckstrcmp(nh_px[k][i],"rev=",4,0)) {
  9081.               revcall = !ckstrcmp(nh_px[k][i]+4,"=on",3,0);
  9082.               debug(F101,"X25 REV","",revcall);
  9083. #ifndef IBMX25
  9084.               } else if (!ckstrcmp(nh_px[k][i],"pad=",4,0)) {
  9085.               int x3par, x3val;
  9086.               char *s1, *s2;
  9087.               s1 = s2 = nh_px[k][i]+4; /* PAD parameters */
  9088.               while (*s2) {            /* Pick them apart */
  9089.                   if (*s2 == ':') {
  9090.                   *s2 = NUL;
  9091.                   x3par = atoi(s1);
  9092.                   s1 = ++s2;
  9093.                   continue;
  9094.                   } else if (*s2 == ',') {
  9095.                   *s2 = NUL;
  9096.                   x3val = atoi(s1);
  9097.                   s1 = ++s2;
  9098.                   debug(F111,"X25 PAD",x3par,x3val);
  9099.                   if (x3par > -1 &&
  9100.                       x3par <= MAXPADPARMS)
  9101.                     padparms[x3par] = x3val;
  9102.                   continue;
  9103.                   } else
  9104.                 s2++;
  9105.               }
  9106. #endif /* IBMX25 */
  9107.               }
  9108.           }
  9109. #endif /* ANYX25 */
  9110.           break;
  9111.           }
  9112.           default:            /* Nothing special for other nets */
  9113.         break;
  9114.         }
  9115.     } else
  9116. #endif /* NODIAL */
  9117.     {                /* No directory entries found. */
  9118.         ckstrncpy(line,hostname,LINBUFSIZ); /* Put this back... */
  9119.         /* If the user gave a TCP service */
  9120.         if (net == NET_TCPB || net == NET_SSH)
  9121.           if (*srvbuf) {        /* Append it to host name/address */
  9122.           ckstrncat(line, ":", LINBUFSIZ);
  9123.           ckstrncat(line, srvbuf,LINBUFSIZ);
  9124.           }
  9125.     }
  9126.     /*
  9127.        Get here with host name/address and all net-specific
  9128.        parameters set, ready to open the connection.
  9129.     */
  9130.     mdmtyp = -net;            /* This should have been done */
  9131.                     /* already but just in case ... */
  9132.  
  9133.     debug(F110,"cx_net net line[] before ttopen",line,0);
  9134.     debug(F101,"cx_net net mdmtyp before ttopen","",mdmtyp);
  9135.     debug(F101,"cx_net net ttnproto","",ttnproto);
  9136.  
  9137. #ifdef SSHBUILTIN
  9138.         if (net == NET_SSH) {
  9139.             makestr(&ssh_hst,hostname);        /* Stash everything */
  9140.             if (username) {
  9141.                 if (!sl_uid_saved) {
  9142.                     ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
  9143.                     sl_uid_saved = 1;
  9144.                 }
  9145.                 ckstrncpy(uidbuf,username,UIDBUFLEN);
  9146.             }
  9147.             if (srvbuf[0]) {
  9148.                 makestr(&ssh_prt,srvbuf);
  9149.             } else
  9150.                 makestr(&ssh_prt,NULL);
  9151.  
  9152.             if (command) {
  9153.                 makestr(&ssh_cmd,brstrip(command));
  9154.                 ssh_cas = param2;
  9155.             } else
  9156.                 makestr(&ssh_cmd,NULL);
  9157.  
  9158.             if (param1 > -1) {
  9159. #ifndef SSHTEST
  9160.                 if (!sl_ssh_ver_saved) {
  9161.                     sl_ssh_ver = ssh_ver;
  9162.                     sl_ssh_ver_saved = 1;
  9163.                 }
  9164. #endif /* SSHTEST */
  9165.                 ssh_ver = param1;
  9166.             }
  9167.             if (param3 > -1) {
  9168. #ifndef SSHTEST
  9169.                 if (!sl_ssh_xfw_saved) {
  9170.                     sl_ssh_xfw = ssh_xfw;
  9171.                     sl_ssh_xfw_saved = 1;
  9172.                 }
  9173. #endif /* SSHTEST */
  9174.                 ssh_xfw = param3;
  9175.             }
  9176.         } else                          /* NET_SSH */
  9177. #endif /* SSHBUILTIN */
  9178. #ifdef TCPSOCKET
  9179.       if (net == NET_TCPB) {
  9180.             switch (protocol) {
  9181. #ifdef CK_SSL
  9182. #ifdef COMMENT
  9183. /*
  9184.   Jeff's version from 30 Dec 2006 - doesn't work - SSL/TLS_RAW still
  9185.   start Telnet negotions if a 0xff byte comes in.
  9186. */
  9187.           case NP_SSL_RAW:
  9188.                 ttnproto = NP_SSL_RAW;
  9189.         debug(F101,"NP_SSL_RAW ttnproto","",ttnproto);
  9190.                 ssl_only_flag = 1;
  9191.                 tls_only_flag = 0;
  9192.                 break;
  9193.  
  9194.           case NP_TLS_RAW:
  9195.           ttnproto = NP_TLS_RAW;
  9196.           debug(F101,"NP_TLS_RAW ttnproto","",ttnproto);
  9197.           ssl_only_flag = 0;
  9198.           tls_only_flag = 1;
  9199.           break;
  9200.  
  9201.           case NP_SSL:
  9202.                 ttnproto = NP_SSL;
  9203.         debug(F101,"NP_SSL ttnproto","",ttnproto);
  9204.                 ssl_only_flag = 1;
  9205.                 tls_only_flag = 0;
  9206.                 break;
  9207.  
  9208.           case NP_TLS:
  9209.                 ttnproto = NP_TLS;
  9210.         debug(F101,"NP_TLS ttnproto","",ttnproto);
  9211.                 ssl_only_flag = 0;
  9212.                 tls_only_flag = 1;
  9213.                 break;
  9214.  
  9215.           case NP_SSL_TELNET:
  9216.                 ttnproto = NP_TELNET;
  9217.         debug(F101,"NP_SSL_TELNET ttnproto","",ttnproto);
  9218.                 ssl_only_flag = 1;
  9219.                 tls_only_flag = 0;
  9220.                 break;
  9221.  
  9222.           case NP_TLS_TELNET:
  9223.                 ttnproto = NP_TELNET;
  9224.         debug(F101,"NP_TLS_TELNET ttnproto","",ttnproto);
  9225.                 ssl_only_flag = 0;
  9226.                 tls_only_flag = 1;
  9227.                 break;
  9228. #else
  9229. /* fdc version of 4 Dec 2006 works OK */
  9230.           case NP_SSL_RAW:
  9231.           case NP_SSL:
  9232.         ssl_raw_flag = (protocol == NP_SSL_RAW) ? 1 : 0;
  9233.                 ttnproto = protocol;
  9234.         debug(F101,protocol==NP_SSL ?
  9235.               "NP_SSL ttnproto" :
  9236.               "NP_SSL_RAW ttnproto",
  9237.               "",ttnproto);
  9238.                 ssl_only_flag = 1;
  9239.                 tls_only_flag = 0;
  9240.                 break;
  9241.  
  9242.           case NP_TLS:
  9243.           case NP_TLS_RAW:
  9244.         tls_raw_flag = (protocol == NP_SSL_RAW) ? 1 : 0;
  9245.                 ttnproto = protocol;
  9246.         debug(F101,protocol==NP_TLS ?
  9247.               "NP_TLS ttnproto" :
  9248.               "NP_TLS_RAW ttnproto",
  9249.               "",ttnproto);
  9250.                 ssl_only_flag = 0;
  9251.                 tls_only_flag = 1;
  9252.                 break;
  9253.  
  9254.           case NP_SSL_TELNET:
  9255.         ssl_raw_flag = 0;
  9256.                 ttnproto = NP_TELNET;
  9257.         debug(F101,"NP_SSL_TELNET ttnproto","",ttnproto);
  9258.                 ssl_only_flag = 1;
  9259.                 tls_only_flag = 0;
  9260.                 break;
  9261.  
  9262.           case NP_TLS_TELNET:
  9263.         tls_raw_flag = 0;
  9264.                 ttnproto = NP_TELNET;
  9265.         debug(F101,"NP_TLS_TELNET ttnproto","",ttnproto);
  9266.                 ssl_only_flag = 0;
  9267.                 tls_only_flag = 1;
  9268.                 break;
  9269. #endif    /* COMMENT */
  9270. #endif /* CK_SSL */
  9271.  
  9272.           case NP_NONE:
  9273.           case NP_TCPRAW:
  9274.           case NP_RLOGIN:
  9275.           case NP_K4LOGIN:
  9276.           case NP_K5LOGIN:
  9277.           case NP_EK4LOGIN:
  9278.           case NP_EK5LOGIN:
  9279.           case NP_TELNET:
  9280.           case NP_KERMIT:
  9281.           default:
  9282.                 ttnproto = protocol;
  9283. #ifdef CK_SSL
  9284. #ifdef COMMENT
  9285.         /* Jeff version from 30 Dec 2006 */
  9286.                 ssl_only_flag = 0;
  9287.                 tls_only_flag = 0;
  9288. #else
  9289.         /* fdc version from 4 Dec 2006 */
  9290.         ssl_raw_flag = 0;
  9291.         tls_raw_flag = 0;
  9292.                 ssl_only_flag = 0;
  9293.                 tls_only_flag = 0;
  9294. #endif    /* COMMENT */
  9295. #endif /* CK_SSL */
  9296.                 break;
  9297.             }
  9298. #ifdef CK_AUTHENTICATION
  9299.             if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
  9300.         param1 > -1) {
  9301.         if (!sl_auth_saved) {
  9302.         int x;
  9303.         for (x = 0; x < AUTHTYPLSTSZ; x++)
  9304.           sl_auth_type_user[x] = auth_type_user[x];
  9305.         sl_auth_saved = 1;
  9306.         }
  9307.         if (!sl_topt_a_s_saved) {
  9308.         sl_topt_a_su = TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION);
  9309.         sl_topt_a_s_saved = 1;
  9310.         }
  9311.         if (!sl_topt_a_c_saved) {
  9312.         sl_topt_a_cm = TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION);
  9313.         sl_topt_a_c_saved = 1;
  9314.         }
  9315.         switch (param1) {
  9316.           case AUTHTYPE_AUTO:
  9317.         auth_type_user[0] = AUTHTYPE_AUTO;
  9318.         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
  9319.         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
  9320.         break;
  9321.           case AUTHTYPE_NULL:
  9322.         auth_type_user[0] = AUTHTYPE_NULL;
  9323.         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  9324.         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  9325.         break;
  9326. #ifdef CK_SRP
  9327.           case AUTHTYPE_SRP:
  9328.         auth_type_user[0] = AUTHTYPE_SRP;
  9329.         auth_type_user[1] = AUTHTYPE_NULL;
  9330.         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9331.         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9332.         break;
  9333. #endif /* CK_SRP */
  9334. #ifdef CK_SSL
  9335.           case AUTHTYPE_SSL:
  9336.         auth_type_user[0] = AUTHTYPE_SSL;
  9337.         auth_type_user[1] = AUTHTYPE_NULL;
  9338.         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9339.         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9340.         break;
  9341. #endif /* CK_SSL */
  9342. #ifdef NT
  9343.           case AUTHTYPE_NTLM:
  9344.         auth_type_user[0] = AUTHTYPE_NTLM;
  9345.         auth_type_user[1] = AUTHTYPE_NULL;
  9346.         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9347.         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9348.         break;
  9349. #endif /* NT */
  9350. #ifdef CK_KERBEROS
  9351.           case AUTHTYPE_KERBEROS_V4:
  9352.         auth_type_user[0] = AUTHTYPE_KERBEROS_V4;
  9353.         auth_type_user[1] = AUTHTYPE_NULL;
  9354.         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9355.         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9356.         break;
  9357.  
  9358.           case AUTHTYPE_KERBEROS_V5:
  9359.         auth_type_user[0] = AUTHTYPE_KERBEROS_V5;
  9360.         auth_type_user[1] = AUTHTYPE_NULL;
  9361.         TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9362.         TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_MU;
  9363.         break;
  9364. #endif /* CK_KERBEROS */
  9365.         }
  9366.     }
  9367.     /*
  9368.        If the user requires a particular type of Kerberos connection,
  9369.        make sure we have a valid TGT.
  9370.     */
  9371.     makestr(&slmsg,"Authentication failure");
  9372.     if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
  9373.         (line[0] == '*' &&
  9374.          TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_MU ||
  9375.          line[0] != '*' &&
  9376.          TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_MU)
  9377.         ) {
  9378. #ifdef CK_KERBEROS
  9379.         if ( auth_type_user[0] == AUTHTYPE_KERBEROS_V4 ) {
  9380.         extern int krb4_autoget;
  9381.         if (!ck_krb4_is_installed())
  9382.           return(cx_fail(msg,
  9383.           "Required authentication method (Kerberos 4) is not installed"));
  9384. #ifdef COMMENT
  9385.         /* This code results in false failures when using */
  9386.         /* kerberos to machines in realms other than the  */
  9387.         /* default since we don't know the realm of the   */
  9388.         /* other machine until perform the reverse DNS    */
  9389.         /* lookup.                                        */
  9390.         else if (line[0] != '*' && !ck_krb4_is_tgt_valid() &&
  9391.                (!krb4_autoget ||
  9392.                 krb4_autoget && !ck_krb4_autoget_TGT(NULL))) {
  9393.             return(cx_fail(msg,
  9394.                "Kerberos 4: Ticket Getting Ticket not valid"));
  9395.         }
  9396. #endif /* COMMENT */
  9397.         } else if (auth_type_user[0] == AUTHTYPE_KERBEROS_V5) {
  9398.         extern int krb5_autoget;
  9399.         if (!ck_krb5_is_installed()) {
  9400.             return(cx_fail(msg,
  9401.        "Required authentication method (Kerberos 5) is not installed"));
  9402.         }
  9403. #ifdef COMMENT
  9404.         /* This code results in false failures when using */
  9405.         /* kerberos to machines in realms other than the  */
  9406.         /* default since we don't know the realm of the   */
  9407.         /* other machine until perform the reverse DNS    */
  9408.         /* lookup.                                        */
  9409.         else if (line[0] != '*' && !ck_krb5_is_tgt_valid() &&
  9410.                (!krb5_autoget ||
  9411.                 krb5_autoget && !ck_krb5_autoget_TGT(NULL))) {
  9412.             return(cx_fail(msg,
  9413.              "Kerberos 5: Ticket Getting Ticket not valid."));
  9414.         }
  9415. #endif /* COMMENT */
  9416.         }
  9417. #endif /* CK_KERBEROS */
  9418. #ifdef NT
  9419.         if (auth_type_user[0] == AUTHTYPE_NTLM) {
  9420.         if (!ck_ntlm_is_installed()) {
  9421.             return(cx_fail(msg,
  9422.            "Required authentication method (NTLM) is not installed"));
  9423.         } else if (line[0] != '*' && !ck_ntlm_is_valid(0)) {
  9424.             return(cx_fail(msg,"NTLM: Credentials are unavailable."));
  9425.         }
  9426.         }
  9427. #endif /* NT */
  9428. #ifdef CK_SSL
  9429.         if (auth_type_user[0] == AUTHTYPE_SSL) {
  9430.         if (!ck_ssleay_is_installed()) {
  9431.             return(cx_fail(msg,
  9432.              "Required authentication method (SSL) is not installed"));
  9433.         }
  9434.         }
  9435. #endif /* CK_SSL */
  9436. #ifdef CK_SRP
  9437.         if (auth_type_user[0] == AUTHTYPE_SRP) {
  9438.         if (!ck_srp_is_installed()) {
  9439.             return(cx_fail(msg,
  9440.              "Required authentication method (SRP) is not installed"));
  9441.         }
  9442.         }
  9443. #endif /* CK_SRP */
  9444.     }
  9445. #endif /* CK_AUTHENTICATION */
  9446. #ifdef CK_ENCRYPTION
  9447.     if ((ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
  9448.          param2 > -1) {
  9449.         if (!sl_cx_saved) {
  9450.         sl_cx_type = cx_type;
  9451.         sl_cx_saved = 1;
  9452.         }
  9453.         if (!sl_topt_e_s_saved) {
  9454.         sl_topt_e_su = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
  9455.         sl_topt_e_sm = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
  9456.         sl_topt_e_s_saved = 1;
  9457.         }
  9458.         if (!sl_topt_e_c_saved) {
  9459.         sl_topt_e_cu = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
  9460.         sl_topt_e_cm = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
  9461.         sl_topt_e_c_saved = 1;
  9462.         }
  9463.         cx_type = param2;
  9464.         if (cx_type == CX_AUTO) {
  9465.         TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  9466.         TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  9467.         TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  9468.         TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  9469.         } else if (cx_type == CX_NONE) {
  9470.         TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  9471.         TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  9472.         TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  9473.         TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  9474.         } else {
  9475.         TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  9476.         TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  9477.         TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  9478.         TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  9479.         }
  9480.     }
  9481.     if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN ||
  9482.         (ttnproto == NP_TELNET || ttnproto == NP_KERMIT) &&
  9483.         ((line[0] == '*' &&
  9484.           TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) == TN_NG_MU &&
  9485.           TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_MU) ||
  9486.          (line[0] != '*' &&
  9487.           TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) == TN_NG_MU &&
  9488.           TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_MU))
  9489.         ) {
  9490.         if (!ck_crypt_is_installed()) {
  9491.         return(cx_fail(msg,
  9492.           "Required Encryption methods are not installed"));
  9493.         }
  9494.     }
  9495. #endif /* CK_ENCRYPTION */
  9496. #ifdef RLOGCODE
  9497. #ifdef CK_KERBEROS
  9498. #ifdef KRB4
  9499.     if (ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN) {
  9500.         extern int krb4_autoget;
  9501.         char tgt[256];
  9502.         char * realm;
  9503.  
  9504.         /* We don't have the full hostname at yet so  */
  9505.         /* we do a DNS lookup before calling ttopen() */ 
  9506.  
  9507.         realm = ck_krb4_realmofhost(ckgetfqhostname(hostname));
  9508.         ckmakmsg(tgt,256,"krbtgt.",realm,"@",realm);
  9509.         if (!ck_krb4_is_installed()) {
  9510.         return(cx_fail(msg,
  9511.          "Required authentication method (Kerberos 4) is not installed"
  9512.                    ));
  9513.         } else {
  9514.         if ((ck_krb4_tkt_isvalid(tgt) <= 0) &&
  9515.             (!krb4_autoget ||
  9516.              krb4_autoget && !ck_krb4_autoget_TGT(realm))) {
  9517.             return(cx_fail(msg,
  9518.                "Kerberos 4: Ticket Getting Ticket not valid"));
  9519.         }
  9520.         }
  9521.     }
  9522. #endif /* KRB4 */
  9523. #ifdef KRB5
  9524.     if (ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN ||
  9525.         ttnproto == NP_K5U2U)
  9526.     {
  9527.         extern int krb5_autoget;
  9528.         char tgt[256];
  9529.         char * realm;
  9530.  
  9531.         /* Must get full hostname before calling ttopen() */
  9532.  
  9533.         realm = ck_krb5_realmofhost(ckgetfqhostname(hostname));
  9534.         ckmakmsg(tgt,256,"krbtgt/",realm,"@",realm);
  9535.  
  9536.         if (!ck_krb5_is_installed()) {
  9537.         return(cx_fail(msg,
  9538.                  "Required authentication method (Kerberos 5) not installed"));
  9539.         } else if (!((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  9540.               ck_krb5_is_tgt_valid()) &&
  9541.                (!krb5_autoget ||
  9542.             krb5_autoget && !ck_krb5_autoget_TGT(realm))) {
  9543.         return(cx_fail(msg,
  9544.                "Kerberos 5: Ticket Getting Ticket not valid."));
  9545.         }
  9546.     }
  9547. #endif /* KRB5 */
  9548. #endif /* CK_KERBEROS */
  9549. #endif /* RLOGCODE */
  9550.  
  9551. #ifndef NOSPL
  9552. #ifdef RLOGCODE
  9553.     if (username) {
  9554.         if (!sl_uid_saved) {
  9555.         ckstrncpy(sl_uidbuf,uidbuf,UIDBUFLEN);
  9556.         sl_uid_saved = 1;
  9557.         }
  9558.         ckstrncpy(uidbuf,username,UIDBUFLEN);
  9559.         uidflag = 1;
  9560.     }
  9561. #endif /* RLOGCODE */
  9562. #ifdef TNCODE
  9563.     if (!sl_tn_saved) {
  9564.         sl_tn_wait = tn_wait_flg;
  9565.         sl_tn_saved = 1;
  9566.     }
  9567.     tn_wait_flg = param3;
  9568. #endif /* TNCODE */
  9569. #endif /* NOSPL */
  9570.     } /* if (net == NET_TCPB) */
  9571. #endif /* TCPSOCKET */
  9572.  
  9573. #ifndef NOSPL
  9574. #ifdef CK_SECURITY
  9575.     if (password) {
  9576.         if (password[0]) {
  9577.         ckstrncpy(pwbuf,password,PWBUFL+1);
  9578.         pwflg = 1;
  9579.         pwcrypt = 0;
  9580.         } else
  9581.         pwflg = 0;
  9582.     }
  9583. #endif /* CK_SECURITY */
  9584. #endif /* NOSPL */
  9585.  
  9586.     /* Try to open - network */
  9587.     ckstrncpy(ttname,line,TTNAMLEN);
  9588.     y = ttopen(line, &_local, mdmtyp, 0 );
  9589.  
  9590. #ifndef NOHTTP
  9591.     /*  If the connection failed and we are using an HTTP Proxy
  9592.      *  and the reason for the failure was an authentication
  9593.      *  error, then we need to give the user to ability to
  9594.      *  enter a username and password, just like a browser.
  9595.      *
  9596.      *  I tried to do all of this within the netopen() call
  9597.      *  but it is much too much work.
  9598.      */
  9599.     while (y < 0 && tcp_http_proxy != NULL ) {
  9600.  
  9601.         if (tcp_http_proxy_errno == 401 ||
  9602.         tcp_http_proxy_errno == 407 ) {
  9603.         char uid[UIDBUFLEN];
  9604.         char pwd[256];
  9605.                 struct txtbox tb[2];
  9606.                 int ok;
  9607.  
  9608.                 tb[0].t_buf = uid;
  9609.                 tb[0].t_len = UIDBUFLEN;
  9610.                 tb[0].t_lbl = "Proxy Userid: ";
  9611.                 tb[0].t_dflt = NULL;
  9612.                 tb[0].t_echo = 1;
  9613.                 tb[1].t_buf = pwd;
  9614.                 tb[1].t_len = 256;
  9615.                 tb[1].t_lbl = "Proxy Passphrase: ";
  9616.                 tb[1].t_dflt = NULL;
  9617.                 tb[1].t_echo = 2;
  9618.  
  9619.                 ok = uq_mtxt("Proxy Server Authentication Required\n",
  9620.                               NULL, 2, tb);
  9621.  
  9622.         if (ok && uid[0]) {
  9623.             char * proxy_user, * proxy_pwd;
  9624.  
  9625.             proxy_user = tcp_http_proxy_user;
  9626.             proxy_pwd  = tcp_http_proxy_pwd;
  9627.  
  9628.             tcp_http_proxy_user = uid;
  9629.             tcp_http_proxy_pwd = pwd;
  9630.  
  9631.             ckstrncpy(ttname,line,TTNAMLEN);
  9632.             y = ttopen(line, &_local, mdmtyp, 0);
  9633.             memset(pwd,0,sizeof(pwd));
  9634.             tcp_http_proxy_user = proxy_user;
  9635.             tcp_http_proxy_pwd = proxy_pwd;
  9636.         } else
  9637.           break;
  9638.         } else
  9639.           break;
  9640.     }
  9641. #endif /* NOHTTP */
  9642.     if (y < 0) {
  9643.         slrestor();
  9644.         makestr(&slmsg,"Network connection failure");
  9645. #ifdef VMS
  9646.         if (msg && hints && !xcmdsrc && IS_RLOGIN()) {
  9647.         makestr(&slmsg,"RLOGIN failure");
  9648.         if  (socket_errno == EACCES) {
  9649.             printf("*************************\n");
  9650.             printf(
  9651.        "Hint: RLOGIN requires privileges to open an outbound port.\n");
  9652.             printf(
  9653.             "(Use SET HINTS OFF to suppress future hints.)\n");
  9654.             printf("*************************\n");
  9655.         }
  9656.         }
  9657. #else  /* Not VMS... */
  9658.         if (errno) {
  9659.         int x;
  9660.         debug(F111,"set host line, errno","",errno);
  9661.         makestr(&slmsg,ck_errstr());
  9662.         if (msg) {
  9663. #ifdef OS2
  9664.             printf("Can't connect to %s\n",line);
  9665. #else /* OS2 */
  9666. #ifdef UNIX
  9667.             if (hints && !xcmdsrc && IS_RLOGIN()) {
  9668.             makestr(&slmsg,"RLOGIN failure");
  9669.             printf("*************************\n");
  9670.             printf(
  9671.      "Hint: RLOGIN requires privileges to open an outbound port.\n");
  9672.             printf(
  9673.      "(Use SET HINTS OFF to suppress future hints.)\n");
  9674.             printf("*************************\n");
  9675.             }
  9676. #endif /* UNIX */
  9677. #endif /* OS2 */
  9678.         } else printf("Can't connect to %s\n",line);
  9679.         } else
  9680. #endif /* VMS */
  9681.           if (msg) printf("Can't open connection to %s\n",line);
  9682.         continue;
  9683.     } else {
  9684.         success = 1;
  9685. #ifndef NODIAL
  9686.         dialsta = DIA_UNK;
  9687. #endif /* NODIAL */
  9688.         switch (net) {
  9689.           case NET_TCPA:
  9690.           case NET_TCPB:
  9691.         cxtype = CXT_TCPIP;
  9692. #ifdef COMMENT
  9693. /* This works but it messes up interactive anonymous login */
  9694. #ifndef NOXFER
  9695. #ifdef IKS_OPTION
  9696.         /* If we have connected to an Internet Kermit service */
  9697.         /* and a /USER: switch was given, then log in. */
  9698.  
  9699.         if (TELOPT_U(TELOPT_KERMIT) || TELOPT_ME(TELOPT_KERMIT)) {
  9700.             debug(F111,"cx_net IKSD /USER:",uidbuf,haveuser);
  9701.             if (haveuser /* && cx == 0 */ ) { /* /USER: given */
  9702.             char * psw = pwbuf; /* Do we have a password? */
  9703.             if (!*psw) {        /* No... */
  9704.                 if (!strcmp(uidbuf,"anonymous") ||
  9705.                 !strcmp(uidbuf,"ftp")) {
  9706.                 extern char myhost[];
  9707.                 char * u = (char *)sl_uidbuf;
  9708.                 char * h = (char *)myhost;
  9709.                 if (!*u) u = "nobody";
  9710.                 if (!*h) h = "nowhere";
  9711.                 ckmakmsg(tmpbuf,TMPBUFSIZ,u,"@",h,NULL);
  9712.                 psw = tmpbuf;
  9713.                 debug(F110,"cx_net IKSD anon",psw,0);
  9714.                 } else {
  9715.                 readpass(" Password: ",pwbuf,PWBUFL);
  9716.                 }
  9717.             }
  9718.             sstate = setgen('I',uidbuf,psw,"");
  9719.             }
  9720.         }
  9721. #endif /* IKS_OPTION */
  9722. #endif /* NOXFER */
  9723. #endif /* COMMENT */
  9724.         break;
  9725.           case NET_SSH:
  9726.         cxtype = CXT_SSH;
  9727.         duplex = 0;         /* Remote echo */
  9728.         break;
  9729.           case NET_SLAT:
  9730.         cxtype = CXT_LAT;
  9731.         break;
  9732.           case NET_SX25:
  9733.           case NET_IX25:
  9734.           case NET_HX25:
  9735.           case NET_VX25:
  9736.         cxtype = CXT_X25;
  9737.         break;
  9738.           case NET_BIOS:
  9739.         cxtype = CXT_NETBIOS;
  9740.         break;
  9741.           case NET_FILE:
  9742.           case NET_PIPE:
  9743.           case NET_CMD:
  9744.           case NET_DLL:
  9745.           case NET_PTY:
  9746.         cxtype = CXT_PIPE;
  9747.         break;
  9748.           default:
  9749.         cxtype = CXT_PIPE;
  9750.         break;
  9751.         }
  9752.         break;
  9753.     }
  9754.     } /* for-loop */
  9755.     s = line;
  9756.  
  9757.     debug(F101,"cx_net post ttopen success","",success);
  9758.     if (!success) {
  9759.         local = dfloc;                  /* Go back to normal */
  9760. #ifndef MAC
  9761.         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty name */
  9762. #endif /* MAC */
  9763.         speed = ttgspd();
  9764.         network = 0;                    /* No network connection active */
  9765.         haveline = 0;
  9766.         if (mdmtyp < 0) {               /* Switching from net to async? */
  9767.             if (mdmsav > -1)            /* Restore modem type from last */
  9768.               mdmtyp = mdmsav;          /* SET MODEM command, if any. */
  9769.             else
  9770.               mdmtyp = 0;
  9771.             mdmsav = -1;
  9772.         }
  9773.         return(0);                      /* Return failure */
  9774.     }
  9775.     if (_local > -1) local = _local;    /* Opened ok, set local/remote. */
  9776.     makestr(&slmsg,NULL);
  9777.     network = (mdmtyp < 0);             /* Remember connection type. */
  9778.     ckstrncpy(ttname,s,TTNAMLEN);       /* Copy name into real place. */
  9779.     debug(F110,"cx_net ok",ttname,0);
  9780.     debug(F101,"cx_net network","",network);
  9781. #ifndef NOXFER
  9782.     if ((reliable != SET_OFF || !setreliable)) /* Assume not reliable. */
  9783.       reliable = SET_OFF;
  9784. #endif /* NOXFER */
  9785.     if (!network || istncomport())    
  9786.       speed = ttgspd();                 /* Get the current speed. */
  9787.     debug(F101,"cx_net local","",local);
  9788.     if (network) {
  9789.         debug(F101,"cx_net net","",net);
  9790. #ifndef NOXFER
  9791.         /* Force prefixing of 255 on TCP/IP connections... */
  9792.         if (net == NET_TCPB
  9793. #ifdef SSHBUILTIN
  9794.              || net == NET_SSH
  9795. #endif /* SSHBUILTIN */
  9796.              ) {
  9797.             debug(F101,"cx_net reliable A","",reliable);
  9798. #ifdef CK_SPEED
  9799.             ctlp[(unsigned)255] = 1;
  9800. #endif /* CK_SPEED */
  9801.             if ((reliable != SET_OFF || !setreliable)) {
  9802. #ifdef TN_COMPORT
  9803.                 if (istncomport()) {    /* Telnet communication port */
  9804.                     reliable = SET_OFF; /* Transport is not reliable */
  9805.                     debug(F101,"cx_net reliable istncomport()","",1);
  9806.                 } else {
  9807.                     reliable = SET_ON;  /* Transport is reliable end to end */
  9808.                     debug(F101,"cx_net reliable istncomport()","",0);
  9809.                 }
  9810. #else
  9811.                 reliable = SET_ON;      /* Transport is reliable end to end */
  9812. #endif /* ifdef TN_COMPORT */
  9813.             }
  9814.             debug(F101,"cx_net reliable B","",reliable);
  9815.         } else if (net == NET_SX25 ||
  9816.                    net == NET_VX25 ||
  9817.                    net == NET_IX25 ||
  9818.                    net == NET_HX25) {
  9819.             duplex = 1;                 /* Local echo for X.25 */
  9820.             if (reliable != SET_OFF || !setreliable)
  9821.               reliable = SET_ON;        /* Transport is reliable end to end */
  9822.         }
  9823. #endif /* NOXFER */
  9824.     }
  9825. #ifndef NOXFER
  9826.     debug(F101,"cx_net reliable","",reliable);
  9827. #endif /* NOXFER */
  9828. #ifdef OS2
  9829.     if (mdmtyp <= 0)                    /* Network or Direct Connection */
  9830.       DialerSend(OPT_KERMIT_CONNECT, 0);
  9831. #endif /* OS2 */
  9832.  
  9833.   xcx_net:
  9834.  
  9835.     setflow();                          /* Set appropriate flow control */
  9836.  
  9837.     haveline = 1;
  9838. #ifdef CKLOGDIAL
  9839.     dolognet();
  9840. #endif /* CKLOGDIAL */
  9841.  
  9842. #ifndef NOSPL
  9843.     if (local) {
  9844.         if (nmac) {                     /* Any macros defined? */
  9845.             int k;                      /* Yes */
  9846.             k = mlook(mactab,"on_open",nmac);   /* Look this up */
  9847.             if (k >= 0) {                       /* If found, */
  9848.                 if (dodo(k,ttname,0) > -1)      /* set it up, */
  9849.                   parser(1);                    /* and execute it */
  9850.             }
  9851.         }
  9852.     }
  9853. #endif /* NOSPL */
  9854.  
  9855.     if (local && (cx || sx)) {          /* /CONNECT or /SERVER switch given */
  9856.         if (cx) {                       /* /CONNECT */
  9857.         if (!gui) {
  9858.         /* Command was confirmed so we can pre-pop command level.  */
  9859.         /* This is so CONNECT module won't think we're executing a */
  9860.         /* script if CONNECT was the final command in the script.  */
  9861.         if (cmdlvl > 0)
  9862.           prepop();
  9863.         }
  9864. #ifndef NODIAL
  9865.             dialsta = DIA_UNK;
  9866. #endif /* NODIAL */
  9867. #ifdef LOCUS
  9868.             if (autolocus) {
  9869.         setlocus(1,1);
  9870.             }
  9871. #endif /* LOCUS */
  9872.             success = doconect(0, cmdlvl == 0 ? 1 : 0);
  9873.             if (ttchk() < 0)
  9874.               dologend();
  9875.         debug(F101,"cx_net post doconect success","",success);
  9876.             return(success);
  9877. #ifndef NOXFER
  9878.         } else if (sx) {                /* /SERVER */
  9879.             sstate = 'x';
  9880. #ifdef MAC
  9881.             what = W_RECV;
  9882.             scrcreate();
  9883. #endif /* MAC */
  9884.             if (local) displa = 1;
  9885. #ifdef AMIGA
  9886.             reqoff();                   /* No DOS requestors while server */
  9887. #endif /* AMIGA */
  9888. #endif /* NOXFER */
  9889.         }
  9890.     }
  9891. #ifndef NODIAL
  9892.     dialsta = DIA_UNK;
  9893. #endif /* NODIAL */
  9894. #ifdef LOCUS
  9895.     if (autolocus) {
  9896.         setlocus(1,1);
  9897.     }
  9898. #endif /* LOCUS */
  9899.     return(success = 1);
  9900. }
  9901. #endif /* NETCONN */
  9902.  
  9903. /* c x _ s e r i a l  --  Make a serial connection */
  9904.  
  9905. /*
  9906.   Call with:
  9907.     device  = string pointer to device name.
  9908.     cx      = 1 to automatically enter Connect mode, 0 otherwise.
  9909.     sx      = 1 to automatically enter Server mode, 0 otherwise.
  9910.     shr     = 1 if device should be opened in shareable mode, 0 otherwise.
  9911.     flag    = if no dev name given: 1 = close current connection, 0 = resume.
  9912.     gui     = 1 if called from GUI dialog, 0 otherwise.
  9913.   Returns:
  9914.     1 on success
  9915.     0 on failure and no message printed, slmsg set to failure message.
  9916.    -9 on failure and message printed, ditto.
  9917. */
  9918.  
  9919. /* these are bit flags */
  9920. #define CX_TAPI 1
  9921. #define CX_PPP  2
  9922. #define CX_SLIP 4
  9923.  
  9924. int
  9925. #ifdef CK_ANSIC
  9926. cx_serial(char *device, 
  9927.           int cx, int sx, int shr, int flag, int gui, int special)
  9928. #else /* CK_ANSIC */
  9929. cx_serial(device, cx, sx, shr, flag, gui, special)
  9930.     char * device; int cx, sx, shr, flag, gui, special; 
  9931. #endif /* CK_ANSIC */
  9932. /* cx_serial */ {
  9933.     int i, n, x, y, msg;
  9934.     int _local = -1;
  9935.     char *s;
  9936.  
  9937.     debug(F110,"cx_serial device",device,0);
  9938.     s = device;
  9939.     msg = (gui == 0) && msgflg;        /* Whether to print messages */
  9940.     success = 0;
  9941.  
  9942. #ifndef NODIAL
  9943.     dialsta = DIA_UNK;
  9944. #endif /* NODIAL */
  9945.     debug(F101,"cx_serial mdmtyp","",mdmtyp);
  9946.     if (clskconnx(1) < 0)        /* Close the Kermit connection */
  9947.       return(success = 0);
  9948.     if (*s) {                /* They gave a device name */
  9949.     _local = -1;            /* Let ttopen decide about it */
  9950.     } else {                /* They just said "set line" */
  9951.     s = dftty;            /* so go back to normal tty */
  9952.     _local = dfloc;            /* and mode. */
  9953.     }
  9954. #ifdef VMS
  9955.     {
  9956.     extern int ok_to_share;
  9957.     ok_to_share = shr;
  9958.     }
  9959. #endif /* VMS */
  9960.  
  9961. #ifdef OS2                              /* Must wait until after ttclos() */
  9962. #ifdef NT                               /* to change these settings       */
  9963. #ifdef CK_TAPI
  9964.     tttapi = special & CX_TAPI;
  9965. #endif /* CK_TAPI */
  9966. #else
  9967.     ttslip = special & CX_SLIP;
  9968.     ttppp  = special & CX_PPP;
  9969. #endif /* NT */
  9970.     ttshare = shr;            /* Shareable device ? */
  9971.     debug(F110,"OS2 SET PORT final s",s,"");
  9972. #endif /* OS2 */
  9973.  
  9974.     /* Open the new line */        
  9975.  
  9976.     ckstrncpy(ttname,s,TTNAMLEN);
  9977.     if ((y = ttopen(s,&_local,mdmtyp,cdtimo)) > -1) {
  9978.     cxtype = (mdmtyp > 0) ? CXT_MODEM : CXT_DIRECT;
  9979. #ifndef NODIAL
  9980.     dialsta = DIA_UNK;
  9981. #ifdef CK_TAPI
  9982.     /* if the line is a tapi device, then we need to auto-execute */
  9983.     /* SET MODEM TYPE TAPI - which we do the equivalent of here.  */
  9984.     if (tttapi) {
  9985.         extern int usermdm;
  9986.         usermdm = 0;
  9987.         initmdm(38);        /* From ckudia.c n_TAPI == 38 */
  9988.     }
  9989. #endif /* CK_TAPI */
  9990. #endif /* NODIAL */
  9991.     success = 1;
  9992.     } else {                /* Failed */
  9993. #ifdef OS2ONLY
  9994.     if (!strcmp(s,dftty))   /* Do not generate an error with dftty */
  9995.       ;
  9996.     else if (y == -6 && ttslip) {
  9997.         makestr(&slmsg,"Can't access SLIP driver");
  9998.         if (msg) printf("?%s\n",slmsg);
  9999.     } else if (y == -6 && ttppp) {
  10000.         makestr(&slmsg,"Can't access PPP driver");
  10001.         if (msg) printf("?%s\n",slmsg);
  10002.     } else
  10003. #endif /* OS2ONLY */
  10004.       if (y == -2) {
  10005.           makestr(&slmsg,"Timed out - no carrier");
  10006.           if (msg) {
  10007.           printf("?%s\n",slmsg);
  10008.           if (hints) {
  10009.               printf("\n*************************\n");
  10010.               printf(
  10011.                "HINT (Use SET HINTS OFF to suppress future hints):\n");
  10012.               printf(
  10013.               "Try SET CARRIER OFF and SET LINE again, or else\n");
  10014.               printf("SET MODEM, SET LINE, and then DIAL.\n");
  10015.               printf("*************************\n\n");
  10016.           }
  10017.           }
  10018.       } else if (y == -3) {
  10019.           makestr(&slmsg,"Access to lock denied");
  10020.           if (msg) {
  10021. #ifdef UNIX
  10022.           printf(
  10023.            "Sorry, write access to UUCP lockfile directory denied.\n");
  10024. #ifndef NOHINTS
  10025.           if (hints) {
  10026.               printf("\n*************************\n");
  10027.               printf(
  10028.                "HINT (Use SET HINTS OFF to suppress future hints):\n");
  10029.               printf(
  10030.       "Please read the installation instructions file, %sckuins.txt,\n",
  10031.                          k_info_dir ? k_info_dir : ""
  10032.                              );
  10033.               printf(
  10034.       "or the UNIX appendix of the manual, \"Using C-Kermit\"\n"
  10035.                              );
  10036.               printf(
  10037.           "or visit http://www.columbia.edu/kermit/ckuins.html \n"
  10038.                              );
  10039.               printf("*************************\n\n");
  10040.           }
  10041. #endif /* NOHINTS */
  10042. #else
  10043.           printf("Sorry, access to lock denied: %s\n",s);
  10044. #endif /* UNIX */
  10045.           }
  10046.       } else if (y == -4) {
  10047.           makestr(&slmsg,"Access to device denied");
  10048.           if (msg) {
  10049.           printf("Sorry, access to device denied: %s\n",s);
  10050. #ifdef UNIX
  10051. #ifndef NOHINTS
  10052.           if (hints) {
  10053.               printf("\n*************************\n");
  10054.               printf(
  10055.               "HINT (Use SET HINTS OFF to suppress future hints):\n");
  10056.               printf(
  10057.         "Please read the installation instructions file, %sckuins.txt,\n",
  10058.                              k_info_dir ? k_info_dir : ""
  10059.                              );
  10060.               printf(
  10061.         "or the UNIX appendix of the manual, \"Using C-Kermit\".\n"
  10062.                              );
  10063.               printf("*************************\n\n");
  10064.           }
  10065. #endif /* NOHINTS */
  10066. #endif /* UNIX */
  10067.           }
  10068.       } else if (y == -5) {
  10069.           makestr(&slmsg,"Device is in use or unavailable");
  10070.           if (msg)
  10071. #ifdef VMS
  10072.         printf(
  10073.           "Sorry, device is in use or otherwise unavailable: %s\n",s);
  10074. #else
  10075.           printf("Sorry, device is in use: %s\n",s);
  10076. #endif /* VMS */
  10077.       } else {            /* Other error. */
  10078.           makestr(&slmsg,"Device open failed");
  10079.           if (
  10080. #ifdef VMS
  10081.           1
  10082. #else
  10083.           errno
  10084. #endif /* VMS */
  10085.           ) {
  10086.           int x;        /* Find a safe, long buffer */
  10087.           makestr(&slmsg,ck_errstr());
  10088. #ifndef VMS
  10089.           debug(F111,"cx_serial serial errno",slmsg,errno);
  10090. #endif /* VMS */
  10091.           if (msg)
  10092.             printf("Connection to %s failed: %s\n",s,slmsg);
  10093.           } else if (msg)
  10094.         printf("Sorry, can't open connection: %s\n",s);
  10095.       }
  10096.     }
  10097.     network = 0;            /* No network connection active */
  10098.     speed = ttgspd();
  10099.     if (!success) {
  10100.         local = dfloc;                  /* Go back to normal */
  10101. #ifndef MAC
  10102.         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty name */
  10103. #endif /* MAC */
  10104.         haveline = 0;
  10105.         if (mdmtyp < 0) {               /* Switching from net to async? */
  10106.             if (mdmsav > -1)            /* Restore modem type from last */
  10107.               mdmtyp = mdmsav;          /* SET MODEM command, if any. */
  10108.             else
  10109.               mdmtyp = 0;
  10110.             mdmsav = -1;
  10111.         }
  10112.         return(msg ? -9 : 0);        /* Return failure */
  10113.     }
  10114.     if (_local > -1)
  10115.       local = _local;            /* Opened ok, set local/remote. */
  10116.     makestr(&slmsg,NULL);        /* Erase SET LINE message */
  10117.     ckstrncpy(ttname,s,TTNAMLEN);       /* Copy name into real place. */
  10118.     debug(F110,"cx_serial ok",ttname,0);
  10119. #ifndef NOXFER
  10120.     if ((reliable != SET_OFF || !setreliable)) /* Assume not reliable. */
  10121.       reliable = SET_OFF;
  10122. #endif /* NOXFER */
  10123.  
  10124.   xcx_serial:
  10125.     setflow();                          /* Set appropriate flow control */
  10126.     haveline = 1;
  10127. #ifdef CKLOGDIAL
  10128.       dologline();
  10129. #endif /* CKLOGDIAL */
  10130.  
  10131. #ifndef NOSPL
  10132.     if (local) {
  10133.         if (nmac) {                     /* Any macros defined? */
  10134.             int k;                      /* Yes */
  10135.             k = mlook(mactab,"on_open",nmac);   /* Look this up */
  10136.             if (k >= 0) {                       /* If found, */
  10137.                 if (dodo(k,ttname,0) > -1)      /* set it up, */
  10138.                   parser(1);                    /* and execute it */
  10139.             }
  10140.         }
  10141.     }
  10142. #endif /* NOSPL */
  10143.  
  10144.     if (local && (cx || sx)) {          /* /CONNECT or /SERVER switch given */
  10145.         extern int carrier;
  10146.         if (carrier != CAR_OFF) {    /* Looking for carrier? */
  10147.             /* Open() turns on DTR -- wait up to a second for CD to come up */
  10148.             int i, x;
  10149.             for (i = 0; i < 10; i++) {  /* WAIT 1 CD... */
  10150.                 x = ttgmdm();
  10151.                 if (x < 0 || x & BM_DCD)
  10152.                   break;
  10153.                 msleep(100);
  10154.             }
  10155.         }
  10156.         if (cx) {                       /* /CONNECT */
  10157.             /* Command was confirmed so we can pre-pop command level. */
  10158.             /* This is so CONNECT module won't think we're executing a */
  10159.             /* script if CONNECT was the final command in the script. */
  10160.  
  10161.             if (cmdlvl > 0)
  10162.               prepop();
  10163. #ifndef NODIAL
  10164.             dialsta = DIA_UNK;
  10165. #endif /* NODIAL */
  10166. #ifdef LOCUS
  10167.             if (autolocus) {
  10168.                 setlocus(1,1);
  10169.             }
  10170. #endif /* LOCUS */
  10171.             success = doconect(0, cmdlvl == 0 ? 1 : 0);
  10172.             if (ttchk() < 0)
  10173.               dologend();
  10174.             return(success);
  10175. #ifndef NOXFER
  10176.         } else if (sx) {                /* /SERVER */
  10177.             sstate = 'x';
  10178. #ifdef MAC
  10179.             what = W_RECV;
  10180.             scrcreate();
  10181. #endif /* MAC */
  10182.             if (local) displa = 1;
  10183. #ifdef AMIGA
  10184.             reqoff();                   /* No DOS requestors while server */
  10185. #endif /* AMIGA */
  10186. #endif /* NOXFER */
  10187.         }
  10188.     }
  10189. #ifndef NODIAL
  10190.     dialsta = DIA_UNK;
  10191. #endif /* NODIAL */
  10192. #ifdef LOCUS
  10193.     if (autolocus) {
  10194.         setlocus(1,1);
  10195.     }
  10196. #endif /* LOCUS */
  10197.     return(success = 1);
  10198. }
  10199.  
  10200.  
  10201. /* S E T L I N -- parse name of and then open communication device. */
  10202. /*
  10203.   Call with:
  10204.     xx == XYLINE for a serial (tty) line, XYHOST for a network host,
  10205.     zz == 0 means if user doesn't give a device name, continue current
  10206.             active connection (if any);
  10207.     zz != 0 means if user doesn't give a device name, then close the
  10208.             current connection and restore the default communication device.
  10209.     fc == 0 to just make the connection, 1 to also CONNECT (e.g. "telnet").
  10210. */
  10211. int
  10212. setlin(xx, zz, fc) 
  10213.     int xx, zz, fc; 
  10214. {
  10215.     extern char pwbuf[], * g_pswd;
  10216.     extern int pwflg, pwcrypt, g_pflg, g_pcpt, nolocal;
  10217.     int wait;
  10218.     /* int tn_wait_sv; */
  10219.     int mynet;
  10220.     int _local = -1;
  10221.     int c, i, haveswitch = 0;
  10222.     int haveuser = 0;
  10223.     int getval = 0;
  10224.     int wild = 0;                       /* Filespec has wildcards */
  10225.     int cx = 0;                         /* Connect after */
  10226.     int sx = 0;                         /* Become server after */
  10227.     int a_type = -1;                    /* Authentication type */
  10228.     int e_type = -1;                    /* Telnet /ENCRYPT type */
  10229. #ifdef CK_ENCRYPTION
  10230.     int encrypt = 0;                    /* Encrypted? */
  10231. #endif /* CK_ENCRYPTION */
  10232.     int shr = 0;                        /* Share serial device */
  10233.     int confirmed = 0;                  /* Command has been entered */
  10234.     struct FDB sw, tx, nx;
  10235. #ifdef OS2
  10236.     struct FDB fl;
  10237. #endif /* OS2 */
  10238.  
  10239.     char * ss;
  10240. #ifdef TCPSOCKET
  10241.     int rawflg = 0;
  10242. #endif /* TCPSOCKET */
  10243.  
  10244.     char srvbuf[SRVBUFSIZ+1];
  10245.  
  10246. #ifdef OS2
  10247. #ifdef NT
  10248.     int xxtapi = 0;
  10249. #else
  10250.     int xxslip = 0, xxppp = 0;
  10251. #endif /* NT */
  10252. #endif /* OS2 */
  10253.  
  10254.     int dossh = 0;
  10255.  
  10256.     debug(F101,"setlin fc","",fc);
  10257.     debug(F101,"setlin zz","",zz);
  10258.     debug(F101,"setlin xx","",xx);
  10259.  
  10260. #ifdef SSHCMD
  10261.     if (xx == XXSSH) {                  /* SSH becomes PTY SSH ... */
  10262.         dossh = 1;
  10263.         xx = XYHOST;
  10264.     } else if (!ckstrcmp("ssh ",line,4,0)) { /* 2010/03/01 */
  10265.         dossh = 1;
  10266.         xx = XYHOST;
  10267.     }
  10268.     debug(F101,"setlin dossh","",dossh);
  10269. #endif /* SSHCMD */
  10270.  
  10271. #ifdef TNCODE
  10272.     /* tn_wait_sv = tn_wait_flg; */
  10273.     wait = tn_wait_flg;
  10274. #else
  10275.     /* tn_wait_sv = 0; */
  10276.     wait = 0;
  10277. #endif /* TNCODE */
  10278.  
  10279.     mynet = nettype;
  10280.  
  10281.     if (nolocal) {
  10282.         makestr(&slmsg,"Making connections is disabled");
  10283.         printf("?Sorry, making connections is disabled\n");
  10284.         return(-9);
  10285.     }
  10286.     if (netsave > -1)
  10287.       nettype = netsave;
  10288.  
  10289.     if (fc != 0 || zz == 0)             /* Preset /CONNECT switch */
  10290.       cx = 1;
  10291.  
  10292.     debug(F101,"setlin cx","",cx);
  10293.  
  10294.     *srvbuf = NUL;
  10295.  
  10296.     line[0] = NUL;
  10297.     s = line;
  10298.  
  10299. #ifdef NETCONN
  10300. #ifdef CK_SECURITY
  10301.     if (tmpstring)
  10302.         makestr(&tmpstring,NULL);
  10303. #endif /* CK_SECURITY */
  10304.     if (tmpusrid)
  10305.         makestr(&tmpusrid,NULL);
  10306. #endif /* NETCONN */
  10307.  
  10308.     autoflow = 1;                       /* Enable automatic flow setting */
  10309.  
  10310.     if (xx == XYHOST) {                 /* SET HOST <hostname> */
  10311. #ifndef NETCONN
  10312.         makestr(&slmsg,"Network connections not supported");
  10313.         printf("?%s\n",slmsg);
  10314.         return(-9);
  10315. #else /* NETCONN */
  10316. #ifndef NOPUSH
  10317.         if ((mynet == NET_CMD || mynet == NET_PTY || dossh) && nopush) {
  10318.             makestr(&slmsg,"Access to external commands is disabled");
  10319.             printf("?Sorry, access to external commands is disabled\n");
  10320.             return(-9);
  10321.         }
  10322. #endif /* NOPUSH */
  10323.  
  10324. #ifdef SSHCMD
  10325.         if (dossh) {                    /* SSH connection via pty */
  10326.             int k;
  10327.         extern int ttyfd;        /* 2010/03/01 */
  10328.             k = ckstrncpy(line, sshcmd ? sshcmd : defsshcmd, LINBUFSIZ);
  10329.             debug(F111,"setlin sshcmd 1",line,k);
  10330.             if ((x = cmtxt("Optional switches and hostname","",&s,xxstring))<0)
  10331.               return(x);
  10332.  
  10333.             /* 2010-03-30 */
  10334.         if (!*s && ttyfd < 0 && !ckstrcmp("ssh ",ttname,4,0)) { 
  10335.         x = ckstrncpy(line,ttname,LINBUFSIZ);
  10336.         } else {
  10337.         if (!*s) {
  10338.             printf("?SSH to where?\n");
  10339.             return(-9);
  10340.         }
  10341.         if (k < LINBUFSIZ) {
  10342.             line[k++] = SP;
  10343.             line[k] = NUL;
  10344.             debug(F111,"setlin sshcmd 2",line,k);
  10345.         } if (k < LINBUFSIZ) {
  10346.             ckstrncpy(&line[k],s,LINBUFSIZ-k);
  10347.             debug(F111,"setlin sshcmd 3",line,k);
  10348.         } else {
  10349.             printf("?Too long\n");
  10350.             return(-9);
  10351.         }
  10352.         }
  10353.         x = cx_net( NET_PTY,                /* network type */
  10354.                         0,                      /* protocol (not used) */
  10355.                         line,                   /* host */
  10356.                         NULL,                   /* service (not used) */
  10357.                         NULL,                   /* username (not used) */
  10358.                         NULL,                   /* password (not used) */
  10359.                         NULL,                   /* command (not used) */
  10360.                         -1,-1,-1,               /* params 1-3 (not used) */
  10361.                         1,                      /* connect immediately */
  10362.                         sx,                     /* server? */
  10363.                         zz,                     /* close current? */
  10364.                         0);                     /* not gui */
  10365.         debug(F111,"setlin cx_net",line,x);
  10366.         return(x);
  10367.         }
  10368. #endif /* SSHCMD */
  10369.  
  10370. /*
  10371.   Here we parse optional switches and then the hostname or whatever,
  10372.   which depends on the network type.  The tricky part is, the network type
  10373.   can be set by a switch.
  10374. */
  10375. #ifndef NOSPL
  10376.         makestr(&g_pswd,pwbuf);         /* Save global pwbuf */
  10377.         g_pflg = pwflg;                 /* and flag */
  10378.         g_pcpt = pwcrypt;
  10379. #endif /* NOSPL */
  10380.  
  10381.         confirmed = 0;
  10382.         haveswitch = 0;
  10383. #ifdef NETFILE
  10384.         if (mynet != NET_FILE) {
  10385. #endif /* NETFILE */
  10386.             ss = (mynet == NET_CMD || mynet == NET_PTY) ?
  10387.               "Command, or switch" :
  10388.                 (mynet == NET_TCPA || mynet == NET_TCPB
  10389.                   || mynet == NET_SSH) ?
  10390.                   "Hostname, ip-address, or switch" :
  10391.                     "Host or switch";
  10392.             if (fc) {
  10393.                 if (mynet == NET_TCPB &&
  10394.                     (ttnproto == NP_TELNET || ttnproto == NP_KERMIT)) {
  10395.                     if (nshteltab) {
  10396.                         haveswitch++;
  10397.                         cmfdbi(&sw,_CMKEY,ss,"","",nshteltab,4,xxstring,
  10398.                              shteltab,&nx);
  10399.                     }
  10400.                 }
  10401. #ifdef RLOGCODE
  10402.                 else if (mynet == NET_TCPB && ttnproto == NP_RLOGIN) {
  10403.                     if (nshrlgtab) {
  10404.                         haveswitch++;
  10405.                         cmfdbi(&sw,_CMKEY,ss,"","",nshrlgtab,4,xxstring,
  10406.                                shrlgtab,&nx);
  10407.                     }
  10408.                 }
  10409. #endif /* RLOGCODE */
  10410.             } else {
  10411.                 haveswitch++;
  10412.                 cmfdbi(&sw,_CMKEY,ss,"","",nshtab,4,xxstring,shtab,&nx);
  10413.             }
  10414. #ifdef NETFILE
  10415.         }
  10416. #endif /* NETFILE */
  10417.         if (mynet == NET_TCPB || mynet == NET_SLAT ||
  10418.         mynet == NET_SSH  || mynet == NET_DEC) {
  10419.             cmfdbi(&nx,_CMFLD,"Host","","",0,0,xxstring,NULL,NULL);
  10420. #ifdef NETFILE
  10421.         } else if (mynet == NET_FILE) {
  10422.             cmfdbi(&nx,_CMIFI,"Filename","","",0,0,xxstring,NULL,NULL);
  10423. #endif /* NETFILE */
  10424. #ifdef PTYORPIPE
  10425.         } else if (mynet == NET_CMD || mynet == NET_PTY) {
  10426.             cmfdbi(&nx,_CMTXT,"Command","","",0,0,xxstring,NULL,NULL);
  10427. #endif /* PTYORPIPE */
  10428.         } else {
  10429.             cmfdbi(&nx,_CMTXT,"Host","","",0,0,xxstring,NULL,NULL);
  10430.         }
  10431.         while (1) {
  10432.             x = cmfdb(haveswitch ? &sw : &nx);
  10433.             debug(F101,"setlin cmfdb","",x);
  10434.             if (x < 0)
  10435.               if (x != -3)
  10436.                 return(x);
  10437.             if (x == -3) {
  10438.                 if ((x = cmcfm()) < 0) {
  10439.                     return(x);
  10440.                 } else {
  10441.                     confirmed = 1;
  10442.                     break;
  10443.                 }
  10444.             }
  10445.             if (cmresult.fcode != _CMKEY) {    /* Not a switch */
  10446.                 ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Save the data */
  10447.                 s = line;                      /* that was parsed... */
  10448.                 if (cmresult.fcode == _CMIFI) {
  10449.                     wild = cmresult.nresult;
  10450.                 } else if (cmresult.fcode == _CMTXT) {
  10451.                     confirmed = 1;
  10452.                 }
  10453.                 break;                  /* and break out of this loop */
  10454.             }
  10455.             c = cmgbrk();               /* Have switch - get break character */
  10456.             getval = (c == ':' || c == '='); /* Must parse an agument? */
  10457.             if (getval && !(cmresult.kflags & CM_ARG)) {
  10458.                 printf("?This switch does not take arguments\n");
  10459.                 return(-9);
  10460.             }
  10461.             if (!getval && (cmgkwflgs() & CM_ARG)) {
  10462.                 printf("?This switch requires an argument\n");
  10463.                 return(-9);
  10464.             }
  10465.             switch (cmresult.nresult) { /* It's a switch.. */
  10466.               case SL_CNX:              /* /CONNECT */
  10467.                 cx = 1;
  10468.                 sx = 0;
  10469.                 break;
  10470.               case SL_SRV:              /* /SERVER */
  10471.                 cx = 0;
  10472.                 sx = 1;
  10473.                 break;
  10474. #ifdef NETCMD
  10475.               case SL_CMD:              /* /COMMAND */
  10476.                 netsave = mynet;
  10477.                 mynet = NET_CMD;
  10478.                 break;
  10479. #endif /* NETCMD */
  10480. #ifdef NETPTY
  10481.               case SL_PTY:              /* /PTY */
  10482.                 netsave = mynet;
  10483.                 mynet = NET_PTY;
  10484.                 break;
  10485. #endif /* NETPTY */
  10486.               case SL_NET:              /* /NETWORK-TYPE */
  10487.                 if ((x = cmkey(netcmd,nnets,"","",xxstring)) < 0)
  10488.                   return(x);
  10489.                 mynet = x;
  10490.                 break;
  10491.  
  10492. #ifdef CK_SECURITY
  10493.               case SL_PSW:              /* /PASSWORD: */
  10494.                 if (!getval)
  10495.                   break;
  10496.                 debok = 0;
  10497.                 if ((x = cmfld("Password","",&s,xxstring)) < 0) {
  10498.                     if (x == -3) {
  10499.                         makestr(&tmpstring,"");
  10500.                     } else {
  10501.                         return(x);
  10502.                     }
  10503.                 } else {
  10504.                     s = brstrip(s);
  10505.                     if ((x = (int)strlen(s)) > PWBUFL) {
  10506.                         makestr(&slmsg,"Internal error");
  10507.                         printf("?Sorry, too long - max = %d\n",PWBUFL);
  10508.                         return(-9);
  10509.                     }
  10510.                     makestr(&tmpstring,s);
  10511.                 }
  10512.                 break;
  10513. #endif /* CK_SECURITY */
  10514.  
  10515.               case SL_UID:              /* /USERID: */
  10516.                 if (!getval)
  10517.                   break;
  10518.                 if ((x = cmfld("Userid","",&s,xxstring)) < 0) {
  10519.                     if (x == -3) {
  10520.                         makestr(&tmpusrid,"");
  10521.                     } else {
  10522.                         return(x);
  10523.                     }
  10524.                 } else {
  10525.                     s = brstrip(s);
  10526.                     if ((x = (int)strlen(s)) > 63) {
  10527.                         makestr(&slmsg,"Internal error");
  10528.                         printf("?Sorry, too long - max = %d\n",63);
  10529.                         return(-9);
  10530.                     }
  10531.                     makestr(&tmpusrid,s);
  10532.                     haveuser = 1;
  10533.                 }
  10534.                 break;
  10535.  
  10536. #ifdef CK_AUTHENTICATION
  10537. #ifdef CK_SRP
  10538.               case SL_SRP:
  10539.                 a_type = AUTHTYPE_SRP;
  10540.                 break;
  10541. #endif /* CK_SRP */
  10542. #ifdef CK_SSL
  10543.               case SL_SSL:
  10544.                 a_type = AUTHTYPE_SSL;
  10545.                 break;
  10546. #endif /* CK_SSL */
  10547. #ifdef NT
  10548.               case SL_NTLM:
  10549.                 a_type = AUTHTYPE_NTLM;
  10550.                 break;
  10551. #endif /* NT */
  10552. #ifdef CK_KERBEROS
  10553.               case SL_KRB4:
  10554.                 a_type = AUTHTYPE_KERBEROS_V4;
  10555.                 if (ttnproto == NP_RLOGIN)
  10556.                   ttnproto =
  10557. #ifdef CK_ENCRYPTION
  10558.                     encrypt ? NP_EK4LOGIN :
  10559. #endif /* CK_ENCRYPTION */
  10560.                       NP_K4LOGIN;
  10561.                 else if (ttnproto == NP_K5LOGIN)
  10562.                   ttnproto = NP_K4LOGIN;
  10563. #ifdef CK_ENCRYPTION
  10564.                 else if (ttnproto == NP_EK5LOGIN)
  10565.                   ttnproto = NP_EK4LOGIN;
  10566. #endif /* CK_ENCRYPTION */
  10567.                 break;
  10568.               case SL_KRB5:
  10569.                 a_type = AUTHTYPE_KERBEROS_V5;
  10570.                 if (ttnproto == NP_RLOGIN)
  10571.                   ttnproto =
  10572. #ifdef CK_ENCRYPTION
  10573.                     encrypt ? NP_EK5LOGIN :
  10574. #endif /* CK_ENCRYPTION */
  10575.                       NP_K5LOGIN;
  10576.                 else if (ttnproto == NP_K4LOGIN)
  10577.                   ttnproto = NP_K5LOGIN;
  10578. #ifdef CK_ENCRYPTION
  10579.                 else if (ttnproto == NP_EK4LOGIN)
  10580.                   ttnproto = NP_EK5LOGIN;
  10581. #endif /* CK_ENCRYPTION */
  10582.                 break;
  10583. #endif /* CK_KERBEROS */
  10584.               case SL_AUTH: {
  10585.                   extern struct keytab autyptab[];
  10586.                   extern int nautyp;
  10587.                   if ((x = cmkey(autyptab,nautyp,"type of authentication",
  10588.                                  "automatic",xxstring)) < 0)
  10589.                     return(x);
  10590.                   a_type = x;
  10591.                   break;
  10592.               }
  10593. #endif /* CK_AUTHENTICATION */
  10594. #ifdef CK_ENCRYPTION
  10595.               case SL_ENC:
  10596.                 switch (ttnproto) {
  10597.                   case NP_K4LOGIN:
  10598.                     ttnproto = NP_EK4LOGIN;
  10599.                     encrypt = 1;
  10600.                     break;
  10601.                   case NP_K5LOGIN:
  10602.                     ttnproto = NP_EK5LOGIN;
  10603.                     encrypt = 1;
  10604.                     break;
  10605.                   case NP_KERMIT:
  10606.                   case NP_TELNET: {
  10607.                       static struct keytab * tnetbl = NULL;
  10608.                       static int ntnetbl = 0;
  10609.                       x = ck_get_crypt_table(&tnetbl,&ntnetbl);
  10610.                       debug(F101,"ck_get_crypt_table x","",x);
  10611.                       debug(F101,"ck_get_crypt_table n","",ntnetbl);
  10612.                       if (x < 1 || !tnetbl || ntnetbl < 1) /* Didn't get it */
  10613.                         x = 0;
  10614.                       if (!x) {
  10615.                           makestr(&slmsg,"Internal error");
  10616.                           printf("?Oops, types not loaded\n");
  10617.                           return(-9);
  10618.                       }
  10619.                       if ((x = cmkey(tnetbl,ntnetbl,"type of encryption",
  10620.                                      "automatic",xxstring)) < 0)
  10621.                         return(x);
  10622.                       e_type = x;
  10623.                       break;
  10624.                   }
  10625.                 }
  10626.                 break;
  10627. #endif /* CK_ENCRYPTION */
  10628.               case SL_WAIT:
  10629.                 wait = 1;
  10630.                 break;
  10631.               case SL_NOWAIT:
  10632.                 wait = 0;
  10633.                 break;
  10634.             }
  10635.         }
  10636.  
  10637. #ifdef NETFILE
  10638.         if (mynet == NET_FILE) {        /* Parsed by cmifi() */
  10639.         if ((x = cmcfm()) < 0)    /* Needs confirmation */
  10640.           return(x);
  10641.         x = cx_net(mynet,        /* nettype */
  10642.                0,        /* protocol (not used) */
  10643.                line,        /* host */
  10644.                "",        /* port */
  10645.                NULL,        /* alternate username */
  10646.                NULL,        /* password */
  10647.                NULL,        /* command to execute */
  10648.                0,        /* param1 */
  10649.                0,        /* param2 */
  10650.                0,        /* param3 */
  10651.                cx,        /* enter CONNECT mode */
  10652.                sx,        /* enter SERVER mode */
  10653.                zz,        /* close connection if open */
  10654.                0        /* gui */
  10655.                );
  10656.         }
  10657. #endif /* NETFILE */
  10658.  
  10659. #ifdef NETCMD
  10660.         if (mynet == NET_CMD || mynet == NET_PTY) {
  10661.             char *p = NULL;
  10662.             if (!confirmed) {
  10663.                 if ((x = cmtxt("Rest of command","",&s,xxstring)) < 0)
  10664.                   return(x);
  10665.                 if (*s) {
  10666.                     ckstrncat(line," ",LINBUFSIZ);
  10667.                     ckstrncat(line,s,LINBUFSIZ);
  10668.                 }
  10669.                 s = line;
  10670.             }
  10671.             /* s == line - so we must protect the line buffer */
  10672.             s = brstrip(s);
  10673.             makestr(&p,s);
  10674.             ckstrncpy(line,p,LINBUFSIZ);
  10675.             makestr(&p,NULL);
  10676.  
  10677.             x = cx_net( mynet,                  /* nettype */
  10678.                         0,                      /* protocol (not used) */
  10679.                         line,                   /* host */
  10680.                         "",                     /* port */
  10681.                         NULL,                   /* alternate username */
  10682.                         NULL,                   /* password */
  10683.                         NULL,                   /* command to execute */
  10684.                         0,                      /* param1 */
  10685.                         0,                      /* param2 */
  10686.                         0,                      /* param3 */
  10687.                         cx,                     /* enter CONNECT mode */
  10688.                         sx,                     /* enter SERVER mode */
  10689.                         zz,                     /* close connection if open */
  10690.                         0                       /* gui */
  10691.                         );
  10692.         }
  10693. #endif /* NETCMD */
  10694.  
  10695. #ifdef NPIPE                            /* Named pipe */
  10696.         if (mynet == NET_PIPE) {        /* Needs backslash twiddling */
  10697.             if (line[0]) {
  10698.                 if (strcmp(line,"*")) {    /* If remote, begin with */
  10699.                     char * p = NULL;
  10700.                     makestr(&p,line);      
  10701.                     ckstrncpy(line,"\\\\",LINBUFSIZ); /* server name */
  10702.                     ckstrncat(line,p,LINBUFSIZ);
  10703.                     makestr(&p,NULL);      
  10704.                 } else {
  10705.                     line[0]='\0';
  10706.                 }
  10707.                 ckstrncat(line,"\\pipe\\", LINBUFSIZ); /* Make pipe name */
  10708.                 ckstrncat(line,pipename, LINBUFSIZ); /* Add name of pipe */
  10709.  
  10710.                 x = cx_net(mynet,    /* nettype */
  10711.                0,        /* protocol (not used) */
  10712.                line,    /* host */
  10713.                "",        /* port */
  10714.                NULL,    /* alternate username */
  10715.                NULL,    /* password */
  10716.                NULL,    /* command to execute */
  10717.                0,        /* param1 */
  10718.                0,        /* param2 */
  10719.                0,        /* param3 */
  10720.                cx,        /* enter CONNECT mode */
  10721.                sx,        /* enter SERVER mode */
  10722.                zz,        /* close connection if open */
  10723.                0        /* gui */
  10724.                );
  10725.             }
  10726.         }
  10727. #endif /* NPIPE */
  10728.  
  10729. #ifdef SUPERLAT
  10730.         if (mynet == NET_SLAT) {        /* Needs password, etc. */
  10731.             slat_pwd[0] = NUL;          /* Erase any previous password */
  10732.             debok = 0;
  10733.             if (*line) {        /* If they gave a host name... */
  10734.                 if ((x = cmfld(
  10735.                      "password,\n or carriage return if no password required",
  10736.                                "",
  10737.                                &s,
  10738.                                xxstring
  10739.                                )) < 0 && x != -3)
  10740.                   return(x);
  10741.                 ckstrncpy(slat_pwd,s,18); /* Set the password, if any */
  10742.             }
  10743.             if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
  10744.  
  10745.             x = cx_net(mynet,        /* nettype */
  10746.                        0,        /* protocol (not used) */
  10747.                        line,        /* host */
  10748.                        "",        /* port */
  10749.                        NULL,        /* alternate username */
  10750.                        NULL,        /* password */
  10751.                        NULL,        /* command to execute */
  10752.                        0,        /* param1 */
  10753.                        0,        /* param2 */
  10754.                        0,        /* param3 */
  10755.                        cx,        /* enter CONNECT mode */
  10756.                        sx,        /* enter SERVER mode */
  10757.                        zz,        /* close connection if open */
  10758.                        0        /* gui */
  10759.                        );
  10760.         }
  10761. #endif /* SUPERLAT */
  10762.  
  10763. #ifdef DECNET
  10764.         if (mynet == NET_DEC) {  
  10765.             if (!line[0]) {                   /* If they gave a host name... */
  10766.                 printf("?hostname required\n");
  10767.                 return(-3);
  10768.             }
  10769.             if ((x = cmcfm()) < 0) return(x); /* Confirm the command */
  10770.  
  10771.             x = cx_net(mynet,        /* nettype */
  10772.                        0,        /* protocol (not used) */
  10773.                        line,        /* host */
  10774.                        "",        /* port */
  10775.                        NULL,        /* alternate username */
  10776.                        NULL,        /* password */
  10777.                        NULL,        /* command to execute */
  10778.                        0,        /* param1 */
  10779.                        0,        /* param2 */
  10780.                        0,        /* param3 */
  10781.                        cx,        /* enter CONNECT mode */
  10782.                        sx,        /* enter SERVER mode */
  10783.                        zz,        /* close connection if open */
  10784.                        0        /* gui */
  10785.                        );
  10786.         }
  10787. #endif /* DECNET */
  10788.  
  10789. #ifdef SSHBUILTIN
  10790.         if (mynet == NET_SSH) {        /* SSH connection */
  10791.             int k, havehost = 0, trips = 0;
  10792.             int    tmpver = -1, tmpxfw = -1, tmpssh_cas;
  10793. #ifndef SSHTEST
  10794.             extern int sl_ssh_xfw, sl_ssh_xfw_saved;
  10795.             extern int sl_ssh_ver, sl_ssh_ver_saved;
  10796. #endif /* SSHTEST */
  10797.             extern struct keytab sshopnsw[];
  10798.             extern int nsshopnsw;
  10799.             extern char *ssh_tmpcmd, *ssh_tmpport;
  10800.             struct FDB sw, kw, fl;
  10801.  
  10802.             debug(F110,"setlin SSH service 0",srvbuf,0);
  10803.             debug(F110,"setlin SSH host s 2",s,0);
  10804.             if (*s) {           /* If they gave a host name... */
  10805.                 debug(F110,"setlin SSH host s 1",s,0);
  10806.                 if (*s == '*') {
  10807.                     makestr(&slmsg,"Incoming connections not supported");
  10808.                     printf(
  10809.      "?Sorry, incoming connections not supported for SSH.\n"
  10810.                            );
  10811.                     return(-9);
  10812.                 }
  10813.                 ckstrncpy(line,s,LINBUFSIZ);
  10814.             } else {
  10815.                 printf("?hostname required\n");
  10816.                 return(-3);
  10817.             }
  10818.  
  10819.             /* Parse [ port ] [ switches ] */
  10820.             cmfdbi(&kw,                 /* Switches */
  10821.                     _CMKEY,
  10822.                     "Port number or service name,\nor switch",
  10823.                     "",
  10824.                     "",
  10825.                     nsshopnsw,
  10826.                     4,
  10827.                     xxstring,
  10828.                     sshopnsw,
  10829.                     &fl
  10830.                     );
  10831.             cmfdbi(&fl,                 /* Port number or service name */
  10832.                     _CMFLD,
  10833.                     "",
  10834.                     "",
  10835.                     "",
  10836.                     0,
  10837.                     0,
  10838.                     xxstring,
  10839.                     NULL,
  10840.                     NULL
  10841.                     );
  10842.             trips = 0;                  /* Explained below */
  10843.             while (1) {                 /* Parse port and switches */
  10844.                 y = cmfdb(&kw);         /* Get a field */
  10845.                 if (y == -3)            /* User typed CR so quit from loop */
  10846.                     break;
  10847.                 if (y < 0)              /* Other parse error, pass it back */
  10848.                     return(y);
  10849.                 switch (cmresult.fcode) { /* Field or Keyword? */
  10850.                 case _CMFLD:              /* Field */
  10851.                     ckstrncpy(srvbuf,cmresult.sresult,SRVBUFSIZ);
  10852.                     break;
  10853.                 case _CMKEY:            /* Keyword */
  10854.                     switch (cmresult.nresult) { /* Which one? */
  10855.                     case SSHSW_PWD:
  10856.                         if (!cmgbrk()) {
  10857.                             printf("?This switch requires an argument\n");
  10858.                             return(-9);
  10859.                         }
  10860.                         debok = 0;
  10861.                         if ((y = cmfld("Password","",&s,xxstring)) < 0) {
  10862.                             if (y == -3) {
  10863.                                 makestr(&tmpstring,"");
  10864.                             } else {
  10865.                                 return(y);
  10866.                             }
  10867.                         } else {
  10868.                             s = brstrip(s);
  10869.                             if ((y = (int)strlen(s)) > PWBUFL) {
  10870.                                 makestr(&slmsg,"Internal error");
  10871.                                 printf("?Sorry, too long - max = %d\n",PWBUFL);
  10872.                                 return(-9);
  10873.                             }
  10874.                             makestr(&tmpstring,s);
  10875.                         }
  10876.                         break;
  10877.                     case SSHSW_USR:             /* /USER: */
  10878.                         if (!cmgbrk()) {
  10879.                             printf("?This switch requires an argument\n");
  10880.                             return(-9);
  10881.                         }
  10882.                         if ((y = cmfld("Username","",&s,xxstring)) < 0)
  10883.                             return(y);
  10884.                         s = brstrip(s);
  10885.                         makestr(&tmpusrid,s);
  10886.                         break;
  10887.                     case SSHSW_VER:
  10888.                         if ((y = cmnum("Number","",10,&z,xxstring)) < 0)
  10889.                             return(y);
  10890.                         if (z < 1 || z > 2) {
  10891.                             printf("?Out of range: %d\n",z);
  10892.                             return(-9);
  10893.                         }
  10894.                         tmpver = z;
  10895.                         break;
  10896.                     case SSHSW_CMD:
  10897.                     case SSHSW_SUB:
  10898.                         if ((y = cmfld("Text","",&s,xxstring)) < 0)
  10899.                           return(y);
  10900.                         makestr(&ssh_tmpcmd,s);
  10901.                         tmpssh_cas = (cmresult.nresult == SSHSW_SUB);
  10902.                         break;
  10903.                     case SSHSW_X11:
  10904.                         if ((y = cmkey(onoff,2,"","on",xxstring)) < 0)
  10905.                             return(y);
  10906.                         tmpxfw = y;
  10907.                         break;
  10908.                     default:
  10909.                         return(-2);
  10910.                     }
  10911.                 }
  10912.                 if (trips++ == 0) {     /* After first time through */
  10913.                     cmfdbi(&kw,         /* only parse switches, not port. */
  10914.                             _CMKEY,
  10915.                             "Switch",
  10916.                             "",
  10917.                             "",
  10918.                             nsshopnsw,
  10919.                             4,
  10920.                             xxstring,
  10921.                             sshopnsw,
  10922.                             NULL
  10923.                             );
  10924.                 }
  10925.             }
  10926.             if ((y = cmcfm()) < 0)      /* Get confirmation */
  10927.                 return(y);
  10928.  
  10929.             debug(F110,"setlin pre-cx_net line",line,0);
  10930.             debug(F110,"setlin pre-cx_net srvbuf",srvbuf,0);
  10931.             x = cx_net( mynet,                  /* nettype */
  10932.                         0,                      /* protocol (not used) */
  10933.                         line,                   /* host */
  10934.                         srvbuf,                 /* port */
  10935.                         tmpusrid,               /* alternate username */
  10936.                         tmpstring,              /* password */
  10937.                         ssh_tmpcmd,             /* command to execute */
  10938.                         tmpver,                 /* param1 - ssh version */
  10939.                         tmpssh_cas,             /* param2 - ssh cas  */
  10940.                         tmpxfw,                 /* param3 - ssh x11fwd */
  10941.                         cx,                     /* enter CONNECT mode */
  10942.                         sx,                     /* enter SERVER mode */
  10943.                         zz,                     /* close connection if open */
  10944.                         0                       /* gui */
  10945.                         );
  10946.             if (tmpusrid)
  10947.                 makestr(&tmpusrid,NULL);
  10948.             if (ssh_tmpcmd)
  10949.                 makestr(&ssh_tmpcmd,NULL);
  10950.         }
  10951. #endif /* SSHBUILTIN */
  10952.  
  10953. #ifdef TCPSOCKET
  10954.         if (mynet == NET_TCPB) {        /* TCP/IP connection */
  10955.             debug(F110,"setlin service 0",srvbuf,0);
  10956.             debug(F110,"setlin host s 2",s,0);
  10957.             if (*s) {            /* If they gave a host name... */
  10958.                 debug(F110,"setlin host s 1",s,0);
  10959. #ifdef NOLISTEN
  10960.                 if (*s == '*') {
  10961.                     makestr(&slmsg,"Incoming connections not supported");
  10962.                     printf(
  10963.      "?Sorry, incoming connections not supported in this version of Kermit.\n"
  10964.                            );
  10965.                     return(-9);
  10966.                 }
  10967. #endif /* NOLISTEN */
  10968. #ifdef RLOGCODE
  10969.                 /* Allow a username if rlogin is requested */
  10970.                 if (mynet == NET_TCPB &&
  10971.                     (ttnproto == NP_RLOGIN || ttnproto == NP_K5LOGIN ||
  10972.                      ttnproto == NP_EK5LOGIN || ttnproto == NP_K4LOGIN ||
  10973.                      ttnproto == NP_EK4LOGIN
  10974.                     )) {
  10975.                     int y;
  10976.                     uidflag = 0;
  10977.                     /* Check for "host:service" */
  10978.                     for ( ; (*s != '\0') && (*s != ':'); s++) ;
  10979.                     if (*s) {   /* Service, save it */
  10980.                         *s = NUL;
  10981.                         ckstrncpy(srvbuf,++s,SRVBUFSIZ);
  10982.                     } else {            /* No :service, then use default. */
  10983. #ifdef VMS
  10984.                         switch (ttnproto) {
  10985.                           case NP_RLOGIN:
  10986.                             ckstrncpy(srvbuf,"513",SRVBUFSIZ); /* "login" */
  10987.                             break;
  10988.                           case NP_K4LOGIN:
  10989.                           case NP_K5LOGIN:
  10990.                             ckstrncpy(srvbuf,"543",SRVBUFSIZ); /* "klogin" */
  10991.                             break;
  10992.                           case NP_EK4LOGIN:
  10993.                           case NP_EK5LOGIN:
  10994.                             ckstrncpy(srvbuf,"2105",SRVBUFSIZ); /* "eklogin" */
  10995.                             break;
  10996.                         }
  10997. #else /* VMS */
  10998.                         switch (ttnproto) {
  10999.                           case NP_RLOGIN:
  11000.                             ckstrncpy(srvbuf,"login",SRVBUFSIZ);
  11001.                             break;
  11002.                           case NP_K4LOGIN:
  11003.                           case NP_K5LOGIN:
  11004.                             ckstrncpy(srvbuf,"klogin",SRVBUFSIZ);
  11005.                             break;
  11006.                           case NP_EK4LOGIN:
  11007.                           case NP_EK5LOGIN:
  11008.                             ckstrncpy(srvbuf,"eklogin",SRVBUFSIZ);
  11009.                             break;
  11010.                         }
  11011. #endif /* VMS */
  11012.                     }
  11013.                     if (!confirmed) {
  11014.                         y = cmfld("Userid on remote system",
  11015.                                   uidbuf,&s,xxstring);
  11016.                         if (y < 0 && y != -3)
  11017.                           return(y);
  11018.                         if ((int)strlen(s) > 63) {
  11019.                             makestr(&slmsg,"Internal error");
  11020.                             printf("Sorry, too long\n");
  11021.                             return(-9);
  11022.                         }
  11023.                         makestr(&tmpusrid,s);
  11024.                     }
  11025.                 } else {        /* TELNET or SET HOST */
  11026. #endif /* RLOGCODE */
  11027.                     /* Check for "host:service" */
  11028.                     for ( ; (*s != '\0') && (*s != ':'); s++) ;
  11029.                     if (*s) {   /* Service, save it */
  11030.                         *s = NUL;
  11031.                         ckstrncpy(srvbuf,++s,SRVBUFSIZ);
  11032.                     } else if (!confirmed) {
  11033.                         /* No :service, let them type one. */
  11034.                         if (*line != '*') { /* Not incoming */
  11035.                             if (mynet == NET_TCPB && ttnproto == NP_KERMIT) {
  11036.                                 if ((x = cmfld(
  11037.                                                "TCP service name or number",
  11038.                                                "kermit",&s,xxstring)
  11039.                                      ) < 0 && x != -3)
  11040.                                   return(x);
  11041. #ifdef RLOGCODE
  11042.                             } else if (mynet == NET_TCPB &&
  11043.                                        ttnproto == NP_RLOGIN) {
  11044.                                 if ((x = cmfld(
  11045.   "TCP service name or number,\n or carriage return for rlogin (513)",
  11046.                                                "login",&s,xxstring)
  11047.                                      ) < 0 && x != -3)
  11048.                                   return(x);
  11049. #ifdef CK_AUTHENTICATION
  11050. #ifdef CK_KERBEROS
  11051.                             } else if (mynet == NET_TCPB &&
  11052.                                        (ttnproto == NP_K4LOGIN ||
  11053.                                        ttnproto == NP_K5LOGIN)) {
  11054.                                 if ((x = cmfld(
  11055.   "TCP service name or number,\n or carriage return for klogin (543)",
  11056.                                                "klogin",&s,xxstring)
  11057.                                      ) < 0 && x != -3)
  11058.                                   return(x);
  11059.                             } else if (mynet == NET_TCPB &&
  11060.                                        (ttnproto == NP_EK4LOGIN ||
  11061.                                         ttnproto == NP_EK5LOGIN)) {
  11062.                                 if ((x = cmfld(
  11063.   "TCP service name or number,\n or carriage return for eklogin (2105)",
  11064.                                                "eklogin",&s,xxstring)
  11065.                                      ) < 0 && x != -3)
  11066.                                   return(x);
  11067. #endif /* CK_KERBEROS */
  11068. #endif /* CK_AUTHENTICATION */
  11069. #endif /* RLOGCODE */
  11070.                             } else {
  11071.                                 /* Do not set a default value in this call */
  11072.                                 /* If you do then it will prevent entries  */
  11073.                                 /* in the network directory from accessing */
  11074.                                 /* alternate ports.                        */
  11075.  
  11076.                                 if ((x = cmfld(
  11077.                                                "TCP service name or number",
  11078.                                                "",&s,xxstring)
  11079.                                      ) < 0 && x != -3)
  11080.                                   return(x);
  11081.                             }
  11082.                         } else { /* Incoming connection */
  11083.                             if ((x = cmfld("TCP service name or number",
  11084.                                            "",&s,xxstring)
  11085.                                  ) < 0 && x != -3)
  11086.                               return(x);
  11087.                         }
  11088.                         if (*s)         /* If they gave a service, */
  11089.                           ckstrncpy(srvbuf,s,SRVBUFSIZ); /* copy it */
  11090.                         debug(F110,"setlin service 0.5",srvbuf,0);
  11091.                     }
  11092. #ifdef RLOGCODE
  11093.                 }
  11094. #endif /* RLOGCODE */
  11095.                 if (!confirmed) {
  11096.                     char * defproto;
  11097.                     switch (ttnproto) {
  11098.                       case NP_RLOGIN:
  11099.                         defproto = "/rlogin";
  11100.                         break;
  11101.                       case NP_K4LOGIN:
  11102.                         defproto = "/k4login";
  11103.                         break;
  11104.                       case NP_K5LOGIN:
  11105.                         defproto = "/k5login";
  11106.                         break;
  11107.                       case NP_EK4LOGIN:
  11108.                         defproto = "/ek4login";
  11109.                         break;
  11110.                       case NP_EK5LOGIN:
  11111.                         defproto = "/ek5login";
  11112.                         break;
  11113.                       case NP_KERMIT:
  11114.                       case NP_TELNET:
  11115.                         defproto = "/telnet";
  11116.                         break;
  11117.                       default:
  11118.                         defproto = "/default";
  11119.                     }
  11120.                     if ((x = cmkey(tcprawtab,ntcpraw,"Switch",defproto,
  11121.                                    xxstring)) < 0) {
  11122.                         if (x != -3)
  11123.                           return(x);
  11124.                         else if ((x = cmcfm()) < 0)
  11125.                           return(x);
  11126.                     } else {
  11127.                         rawflg = x;
  11128.                         if ((x = cmcfm()) < 0)
  11129.                           return(x);
  11130.                     }
  11131.                 }
  11132.             }
  11133.             debug(F110,"setlin pre-cx_net line",line,0);
  11134.             debug(F110,"setlin pre-cx_net srvbuf",srvbuf,0);
  11135.             x = cx_net( mynet,                  /* nettype */
  11136.                         rawflg                  /* protocol */,
  11137.                         line,                   /* host */
  11138.                         srvbuf,                 /* port */
  11139.                         tmpusrid,               /* alternate username */
  11140.                         tmpstring,              /* password */
  11141.                         NULL,                   /* command to execute */
  11142.                         a_type,                 /* param1 - telnet authtype */
  11143.                         e_type,                 /* param2 - telnet enctype  */
  11144.                         wait,                   /* param3 - telnet wait */
  11145.                         cx,                     /* enter CONNECT mode */
  11146.                         sx,                     /* enter SERVER mode */
  11147.                         zz,                     /* close connection if open */
  11148.                         0                       /* gui */
  11149.                         );
  11150.         }
  11151. #endif /* TCPSOCKET */
  11152.  
  11153. #ifdef CK_SECURITY
  11154.         if (tmpstring)
  11155.             makestr(&tmpstring,NULL);
  11156. #endif /* CK_SECURITY */
  11157.         if (tmpusrid)
  11158.             makestr(&tmpusrid,NULL);
  11159.     debug(F111,"setlin cx_net",line,x);
  11160.     return(x);
  11161. #endif /* NETCONN */
  11162.     }
  11163.  
  11164. /* Serial tty device, possibly modem, connection... */
  11165.  
  11166. #ifdef OS2
  11167. /*
  11168.   User can type:
  11169.     COM1..COM8 = Regular COM port
  11170.     1..8       = Synonym for COM1..COM8, is translated to COM1..COM8
  11171.     _n         = (n is a number) = open file handle
  11172.     string     = any text string = name of some other kind of device,
  11173.                  taken literally, as given.
  11174. */
  11175.     s = "Communication device name";
  11176.  
  11177. #ifdef CK_TAPI
  11178.     if (TAPIAvail)
  11179.       cktapiBuildLineTable(&tapilinetab, &_tapilinetab, &ntapiline);
  11180.     if (!(tapilinetab && _tapilinetab && ntapiline > 0) &&
  11181.     xx == XYTAPI_LIN ) {
  11182.     makestr(&slmsg,"TAPI device not configured");
  11183.     printf("\nNo TAPI Line Devices are configured for this system\n");
  11184.     return(-9);
  11185.     }
  11186.     if (xx == XYTAPI_LIN) {        /* Default (first) TAPI line */
  11187.     s = "tapi";            /* (whatever it is) */
  11188.     } else {                /* Query the user */
  11189. #endif /* CK_TAPI */
  11190.  
  11191. /* Now parse optional switches and then device name */
  11192.  
  11193.     confirmed = 0;
  11194.     cmfdbi(&sw,_CMKEY,"Device name, or switch",
  11195.            "","",npsltab,4,xxstring,psltab,&fl);
  11196.     cmfdbi(&fl,_CMFLD,"",dftty,"",0,0,xxstring,NULL,NULL);
  11197.     while (1) {
  11198.         x = cmfdb(&sw);
  11199.         debug(F101,"setlin cmfdb","",x);
  11200.         if (x < 0)
  11201.           if (x != -3)
  11202.         return(x);
  11203.         if (x == -3) {
  11204.         if ((x = cmcfm()) < 0) {
  11205.             return(x);
  11206.         } else {
  11207.             confirmed = 1;
  11208.             break;
  11209.         }
  11210.         }
  11211.         if (cmresult.fcode == _CMFLD) {
  11212.         s = cmresult.sresult;
  11213.         break;
  11214.         } else if (cmresult.fcode == _CMKEY) {
  11215.         switch (cmresult.nresult) {
  11216.           case SL_CNX:        /* /CONNECT */
  11217.             cx = 1;
  11218.             sx = 0;
  11219.             break;
  11220.           case SL_SRV:        /* /SERVER */
  11221.             cx = 0;
  11222.             sx = 1;
  11223.             break;
  11224.           case SL_SHR:        /* /SHARE */
  11225.             shr = 1;
  11226.             break;
  11227.           case SL_NSH:        /* /NOSHARE */
  11228.             shr = 0;
  11229.             break;
  11230.         }
  11231.         }
  11232.     }
  11233. #ifdef CK_TAPI
  11234.     }
  11235. #endif /* CK_TAPI */
  11236.  
  11237.     debug(F110,"OS2 SET PORT s",s,0);
  11238.     y = lookup(os2devtab,s,nos2dev,&x); /* Look up in keyword table */
  11239.     debug(F101,"OS2 SET PORT x","",x);
  11240.     debug(F101,"OS2 SET PORT y","",y);
  11241.     if ((y > -1) && (x >= 0 && x < 8)) { /* User typed a digit 1..8 */
  11242.     s = os2devtab[x+8].kwd;        /* Substitite its real name */
  11243. #ifdef NT
  11244.     xxtapi = 0;
  11245. #else /* NT */
  11246.     xxslip = xxppp = 0;
  11247. #endif /* NT */
  11248.     debug(F110,"OS2 SET PORT subst s",s,"");
  11249. #ifndef NT
  11250.     } else if ((y >-1) && (x >= 16 && x < 24)) { /* SLIP access */
  11251.     s = os2devtab[x-8].kwd;        /* Substitite its real name */
  11252.     debug(F110,"OS2 SET PORT SLIP subst s",s,"");
  11253.     xxslip = 1;
  11254.     xxppp  = 0;
  11255.     } else if ((y >-1) && (x >= 24 && x < 32)) { /* PPP access */
  11256.     s = os2devtab[x-16].kwd;    /* Substitite its real name */
  11257.     debug(F110,"OS2 SET PORT PPP subst s",s,"");
  11258.     xxppp = 1;
  11259.     xxslip = 0;
  11260.     if ((y = cmkey(os2ppptab,
  11261.                nos2ppp,
  11262.                "PPP driver interface",
  11263.                "ppp0",
  11264.                xxstring)
  11265.          ) < 0)
  11266.       return(y);
  11267.     debug(F101,"OS2 SET PORT PPP INTERFACE y","",y);
  11268.     xxppp = (y % 10) + 1;
  11269. #endif /* NT */
  11270.     } else if (*s == '_') {        /* User used "_" prefix */
  11271.     s++;                /* Remove it */
  11272.     /* Rest must be numeric */
  11273.     debug(F110,"OS2 SET PORT HANDLE _subst s",s,0);
  11274.     if (!rdigits(s)) {
  11275.         makestr(&slmsg,"Invalid file handle");
  11276.         printf("?Invalid format for file handle\n");
  11277.         return(-9);
  11278.     }
  11279. #ifdef NT
  11280.     xxtapi = 0;
  11281. #else /* NT */
  11282.     xxslip = xxppp = 0;
  11283. #endif /* NT */
  11284.     } else {                /* A normal COMx port or a string */
  11285.     s = brstrip(s);            /* Strip braces if any */
  11286. #ifdef NT
  11287. #ifdef CK_TAPI
  11288.     /* Windows TAPI support - Look up in keyword table */
  11289.     if (tapilinetab && _tapilinetab && ntapiline > 0) {
  11290.         if (!ckstrcmp(s,"tapi",4,0)) {
  11291.  
  11292.         /* Find out what the lowest numbered TAPI device is */
  11293.         /* and use it as the default.                       */
  11294.         int j = 9999, k = -1;
  11295.         for (i = 0; i < ntapiline; i++) {
  11296.             if (tapilinetab[i].kwval < j) {
  11297.             j = tapilinetab[i].kwval;
  11298.             k = i;
  11299.             }
  11300.         }
  11301.         if (k >= 0)
  11302.           s = _tapilinetab[k].kwd;
  11303.         else
  11304.           s = "";
  11305.  
  11306.         if ((y = cmkey(_tapilinetab,ntapiline,
  11307.                    "TAPI device name",s,xxstring)) < 0)
  11308.           return(y);
  11309.  
  11310.         xxtapi = 1;
  11311.  
  11312.         /* Get the non Underscored string */
  11313.         for (i = 0; i < ntapiline; i++ ) {
  11314.             if (tapilinetab[i].kwval == y) {
  11315.             s = tapilinetab[i].kwd;
  11316.             break;
  11317.             }
  11318.         }
  11319.         } else
  11320.           xxtapi = 0;
  11321.     }
  11322. #endif /* CK_TAPI */
  11323. #else /* NT */
  11324.     /* not OS/2 SLIP or PPP */
  11325.     xxslip = xxppp = 0;
  11326. #endif /* NT */
  11327.     }
  11328.     ckstrncpy(tmpbuf,s,TMPBUFSIZ);    /* Copy to a safe place */
  11329.     s = tmpbuf;
  11330.     if ((x = cmcfm()) < 0)
  11331.       return(x);
  11332.  
  11333. #else /* !OS2 */
  11334.  
  11335.     cmfdbi(&sw,_CMKEY,"Device name, or switch",
  11336.        "","",npsltab,4,xxstring,psltab,&tx);
  11337.     cmfdbi(&tx,_CMTXT,"",dftty,"",0,0,xxstring,NULL,NULL);
  11338.     while (!confirmed) {
  11339.     x = cmfdb(&sw);
  11340.     debug(F101,"setlin cmfdb","",x);
  11341.     if (x < 0)
  11342.       if (x != -3)
  11343.         return(x);
  11344.     if (x == -3) {
  11345.         if ((x = cmcfm()) < 0) {
  11346.         return(x);
  11347.         } else {
  11348.         confirmed = 1;
  11349.         break;
  11350.         }
  11351.     }
  11352.     switch (cmresult.fcode) {
  11353.       case _CMTXT:
  11354.         ckstrncpy(tmpbuf,cmresult.sresult,TMPBUFSIZ);
  11355.         s = tmpbuf;
  11356.         debug(F110,"setlin CMTXT",tmpbuf,0);
  11357.         confirmed = 1;
  11358.         break;
  11359.       case _CMKEY:            /* Switch */
  11360.         debug(F101,"setlin CMKEY",tmpbuf,cmresult.nresult);
  11361.         switch (cmresult.nresult) {
  11362.           case SL_CNX:        /* /CONNECT */
  11363.         cx = 1;
  11364.         sx = 0;
  11365.         break;
  11366.           case SL_SRV:        /* /SERVER */
  11367.         cx = 0;
  11368.         sx = 1;
  11369.         break;
  11370. #ifdef VMS
  11371.           case SL_SHR:        /* /SHARE */
  11372.         shr = 1;
  11373.         break;
  11374.           case SL_NSH:        /* /NOSHARE */
  11375.         shr = 0;
  11376.         break;
  11377. #endif /* VMS */
  11378.         }
  11379.         continue;
  11380.       default:
  11381.         debug(F101,"setlin bad cmfdb result","",cmresult.fcode);
  11382.         makestr(&slmsg,"Internal error");
  11383.         printf("?Internal parsing error\n");
  11384.         return(-9);
  11385.     }
  11386.     }
  11387. #endif /* OS2 */
  11388.     if (!confirmed)
  11389.       if ((x = cmcfm()) < 0)
  11390.     return(x);
  11391.  
  11392.     debug(F110,"setlin pre-cx_serial s",s,0);
  11393.     debug(F110,"setlin pre-cx_serial line",line,0);
  11394.     x = cx_serial(s,cx,sx,shr,zz,0,
  11395. #ifdef OS2
  11396. #ifdef NT
  11397.                    (xxtapi ? CX_TAPI : 0)
  11398. #else
  11399.                    (xxslip ? CX_SLIP : 0) | (xxppp ? CX_PPP : 0)
  11400. #endif /* NT */
  11401. #else /* OS2 */
  11402.                    0
  11403. #endif /* OS2 */
  11404.                    );
  11405.     debug(F111,"setlin cx_serial",line,x);
  11406.     return(x);
  11407. }
  11408. #endif /* NOLOCAL */
  11409.  
  11410. #ifdef CKCHANNELIO
  11411. /*
  11412.   C-Library based file-i/o package for scripts.  This should be portable to
  11413.   all C-Kermit versions since it uses the same APIs we have always used for
  11414.   processing command files.  The entire channel i/o package is contained
  11415.   herein, apart from some keyword table entries in the main keyword table
  11416.   and the help text in the HELP command module.
  11417.  
  11418.   On platforms like VMS and VOS, this package handles only UNIX-style
  11419.   stream files.  If desired, it can be replaced for those platforms by
  11420.   <#>ifdef'ing out this code and adding the equivalent replacement routines
  11421.   to the ck?fio.c module, e.g. for RMS-based file i/o in ckvfio.c.
  11422. */
  11423. #ifndef NOSTAT
  11424. #ifdef VMS
  11425. /* 2010-03-09 SMS.  VAX C needs help to find "sys".  It's easier not to try. */
  11426. #include <stat.h>
  11427. #else /* def VMS */
  11428. #include <sys/stat.h>
  11429. #endif /* def VMS [else] */
  11430. #endif /* NOSTAT */
  11431.  
  11432. #ifdef NLCHAR
  11433. static int z_lt = 1;                    /* Length of line terminator */
  11434. #else
  11435. static int z_lt = 2;
  11436. #endif /* NLCHAR */
  11437.  
  11438. struct ckz_file {                       /* C-Kermit file struct */
  11439.     FILE * z_fp;                        /* Includes the C-Lib file struct */
  11440.     unsigned int z_flags;               /* Plus C-Kermit mode flags, */
  11441.     CK_OFF_T z_nline;            /* current line number if known, */
  11442.     char z_name[CKMAXPATH+2];           /* and the file's name. */
  11443. };
  11444. static struct ckz_file ** z_file = NULL; /* Array of C-Kermit file structs */
  11445. static int z_inited = 0;                /* Flag for array initialized */
  11446. int z_maxchan = Z_MAXCHAN;              /* Max number of C-Kermit channels */
  11447. int z_openmax = CKMAXOPEN;              /* Max number of open files overall */
  11448. int z_nopen = 0;                        /* How many channels presently open */
  11449. int z_error = 0;                        /* Most recent error */
  11450. int z_filcount = -1;                    /* Most recent FILE COUNT result */
  11451.  
  11452. #define RD_LINE 0                       /* FILE READ options */
  11453. #define RD_CHAR 1
  11454. #define RD_SIZE 2
  11455. #define RD_TRIM 8            /* Like Snobol &TRIM = 1 */
  11456. #define RD_UNTA 9            /* Untabify */
  11457.  
  11458. #define WR_LINE RD_LINE                 /* FILE WRITE options */
  11459. #define WR_CHAR RD_CHAR
  11460. #define WR_SIZE RD_SIZE
  11461. #define WR_STRI 3
  11462. #define WR_LPAD 4
  11463. #define WR_RPAD 5
  11464.  
  11465. #ifdef UNIX
  11466. extern int ckmaxfiles;                  /* Filled in by sysinit(). */
  11467. #endif /* UNIX */
  11468.  
  11469. /* See ckcker.h for error numbers */
  11470. /* See ckcdeb.h for Z_MAXCHAN and CKMAXOPEN definitions */
  11471. /* NOTE: For VMS we might be able to fill in ckmaxfiles */
  11472. /* from FILLM and CHANNELCNT -- find out about these... */
  11473.  
  11474. static char * fopnargs[] = {            /* Mode combinations for fopen() */
  11475. #ifdef COMMENT
  11476.     /* All combinations of rwa */
  11477.     "",  "r",  "w",  "rw",  "a",  "ra",  "wa",  "rwa", /* Text mode */
  11478.     "b", "rb", "wb", "rwb", "ab", "rab", "wab", "rwab" /* Binary mode */
  11479. #else
  11480.     /* Combinations and syntax permitted by C libraries... */
  11481.     "",  "r",  "w",  "r+",  "a",  "",   "a",  "", /* Text mode */
  11482. #ifdef OS2
  11483.     "",  "rb", "wb", "r+b", "ab", "",   "ab", "" /* Binary modes for K95 */
  11484. #else
  11485. #ifdef VMS
  11486.     "",  "rb", "wb", "r+b", "ab", "",   "ab", "" /* Binary modes for VMS */
  11487. #else
  11488.     "",  "r",   "w", "r+",  "a",  "",   "a",  "" /* Binary modes for UNIX */
  11489. #endif /* VMS */
  11490. #endif /* OS2 */
  11491. #endif /* COMMENT */
  11492. };
  11493. static int nfopnargs = sizeof(fopnargs) / sizeof(char *);
  11494.  
  11495. char *                                  /* Error messages */
  11496. ckferror(n) int n; {
  11497.     switch (n) {
  11498.       case FX_NER: return("No error");
  11499.       case FX_SYS: return(ck_errstr());
  11500.       case FX_EOF: return("End of file");
  11501.       case FX_NOP: return("File not open");
  11502.       case FX_CHN: return("Channel out of range");
  11503.       case FX_RNG: return("Parameter out of range");
  11504.       case FX_NMF: return("Too many files open");
  11505.       case FX_FOP: return("Operation conflicts with OPEN mode");
  11506.       case FX_NYI: return("OPEN mode not supported");
  11507.       case FX_BOM: return("Illegal combination of OPEN modes");
  11508.       case FX_ACC: return("Access denied");
  11509.       case FX_FNF: return("File not found");
  11510.       case FX_OFL: return("Buffer overflow");
  11511.       case FX_LNU: return("Current line number unknown");
  11512.       case FX_ROO: return("Off limits");
  11513.       case FX_UNK: return("Operation fails - reason unknown");
  11514.       default: return("Error number out of range");
  11515.     }
  11516. }
  11517.  
  11518. /*
  11519.   Z _ O P E N --  Open a file for the requested type of access.
  11520.  
  11521.   Call with:
  11522.     name:  Name of file to be opened.
  11523.     flags: Any combination of FM_xxx values except FM_EOF (ckcker.h).
  11524.   Returns:
  11525.     >= 0 on success: The assigned channel number
  11526.     <  0 on failure: A negative FX_xxx error code (ckcker.h).
  11527. */
  11528. int
  11529. z_open(name, flags) char * name; int flags; {
  11530.     int i, n;
  11531.     FILE * t;
  11532.     char * mode;
  11533.     debug(F111,"z_open",name,flags);
  11534.     if (!name) name = "";               /* Check name argument */
  11535.     if (!name[0])
  11536.       return(z_error = FX_BFN);
  11537.     if (flags & FM_CMD)                 /* Opening pipes not implemented yet */
  11538.       return(z_error = FX_NYI);         /* (and not portable either) */
  11539.     debug(F101,"z_open nfopnargs","",nfopnargs);
  11540.     if (flags < 0 || flags >= nfopnargs) /* Range check flags */
  11541.       return(z_error = FX_RNG);
  11542.     mode = fopnargs[flags];             /* Get fopen() arg */
  11543.     debug(F111,"z_open fopen args",mode,flags);
  11544.     if (!mode[0])                       /* Check for illegal combinations */
  11545.       return(z_error = FX_BOM);
  11546.     if (!z_inited) {                    /* If file structs not inited */
  11547.         debug(F101,"z_open z_maxchan 1","",z_maxchan);
  11548. #ifdef UNIX
  11549.         debug(F101,"z_open ckmaxfiles","",ckmaxfiles);
  11550.         if (ckmaxfiles > 0) {           /* Set in ck?tio.c: sysinit() */
  11551.             int x;
  11552.             x = ckmaxfiles - ZNFILS - 5;
  11553.             if (x > z_maxchan)          /* sysconf() value greater than */
  11554.               z_maxchan = x;            /* value from header files. */
  11555.             debug(F101,"z_open z_maxchan 2","",z_maxchan);
  11556.         }
  11557. #endif /* UNIX */
  11558.         if (z_maxchan < Z_MINCHAN)      /* Allocate at least this many. */
  11559.           z_maxchan = Z_MINCHAN;
  11560.         debug(F101,"z_open z_maxchan 3","",z_maxchan);
  11561.         /* Note: This could be a pretty big chunk of memory */
  11562.         /* if z_maxchan is a big number.  If this becomes a problem */
  11563.         /* we'll need to malloc and free each element at open/close time */
  11564. #ifdef COMMENT
  11565.     /* May 2006 - it's time - in current Linux this about 3MB */
  11566.         if (!(z_file = (struct ckz_file *)
  11567.               malloc(sizeof(struct ckz_file) * (z_maxchan + 1))))
  11568.           return(z_error = FX_NMF);
  11569.         for (i = 0; i < z_maxchan; i++) {
  11570.             z_file[i].z_fp = NULL;
  11571.             z_file[i].z_flags = 0;
  11572.             z_file[i].z_nline = 0;
  11573.             *(z_file[i].z_name) = '\0';
  11574.         }
  11575. #else
  11576.     /* New economical way, allocate storage for each channel as needed */
  11577.     if (!z_file) {
  11578.         z_file = (struct ckz_file **)malloc((z_maxchan + 1) *
  11579.                         sizeof(struct ckz_file *));
  11580.         if (!z_file)
  11581.           return(z_error = FX_NMF);
  11582.         for (i = 0; i < z_maxchan; i++)
  11583.           z_file[i] = NULL;
  11584.     }
  11585. #endif    /* COMMENT */
  11586.         z_inited = 1;                   /* Remember we initialized */
  11587.     }
  11588.     for (n = -1, i = 0; i < z_maxchan; i++) { /* Find a free channel */
  11589. #ifdef COMMENT
  11590.         if (!z_file[i].z_fp) {
  11591.             n = i;
  11592.             break;
  11593.         }
  11594. #else
  11595.         if (!z_file[i]) {
  11596.         z_file[i] = (struct ckz_file *) malloc(sizeof(struct ckz_file));
  11597.         if (!z_file[i])
  11598.           return(z_error = FX_NMF);
  11599.             n = i;
  11600.             break;
  11601.         }
  11602. #endif    /* COMMENT */
  11603.  
  11604.     }
  11605.     if (n < 0 || n >= z_maxchan)        /* Any free channels? */
  11606.       return(z_error = FX_NMF);         /* No, fail. */
  11607.     errno = 0;
  11608.  
  11609.     z_file[n]->z_flags = 0;        /* In case of failure... */
  11610.     z_file[n]->z_fp = NULL;        /* Set file pointer to NULL */
  11611.  
  11612.     t = fopen(name, mode);              /* Try to open the file. */
  11613.     if (!t) {                           /* Failed... */
  11614.         debug(F111,"z_open error",name,errno);
  11615. #ifdef EMFILE
  11616.         if (errno == EMFILE)
  11617.           return(z_error = FX_NMF);
  11618. #endif /* EMFILE */
  11619.     free(z_file[n]);
  11620.     z_file[n] = NULL;
  11621.         return(z_error = (errno ?  FX_SYS : FX_UNK)); /* Return error code */
  11622.     }
  11623. #ifdef NT
  11624. #ifdef O_SEQUENTIAL
  11625.     if (t)                              /* Caching hint for NT */
  11626.       _setmode(_fileno(t),O_SEQUENTIAL);
  11627. #endif /* O_SEQUENTIAL */
  11628. #endif /* NT */
  11629.     z_nopen++;                          /* Open, count it. */
  11630.     z_file[n]->z_fp = t;        /* Stash the file pointer */
  11631.     z_file[n]->z_flags = flags;        /* and the flags */
  11632.     z_file[n]->z_nline = 0;        /* Current line number is 0 */
  11633.     z_error = 0;
  11634.     zfnqfp(name,CKMAXPATH,z_file[n]->z_name); /* and the file's full name */
  11635.     return(n);                          /* Return the channel number */
  11636. }
  11637.  
  11638. int
  11639. z_close(channel) int channel; {         /* Close file on given channel */
  11640.     int x;
  11641.     FILE * t;
  11642.     if (!z_inited)                      /* Called before any files are open? */
  11643.       return(z_error = FX_NOP);
  11644.     if (channel >= z_maxchan)           /* Channel out of range? */
  11645.       return(z_error = FX_CHN);
  11646.     if (!z_file[channel])
  11647.       return(z_error = FX_NOP);
  11648.     if (!(t = z_file[channel]->z_fp))    /* Channel wasn't open? */
  11649.       return(z_error = FX_NOP);
  11650.     errno = 0;                          /* Set errno 0 to get a good reading */
  11651.     x = fclose(t);                      /* Try to close */
  11652.     if (x == EOF)                       /* On failure */
  11653.       return(z_error = FX_SYS);         /* indicate system error. */
  11654.     z_nopen--;                          /* Closed OK, decrement open count */
  11655.     z_file[channel]->z_fp = NULL;    /* Set file pointer to NULL */
  11656.     z_file[channel]->z_nline = 0;    /* Current line number is 0 */
  11657.     z_file[channel]->z_flags = 0;    /* Set flags to 0 */
  11658.     *(z_file[channel]->z_name) = '\0';    /* Clear name */
  11659.     free(z_file[channel]);
  11660.     z_file[channel] = NULL;
  11661.     return(z_error = 0);
  11662. }
  11663.  
  11664. /*
  11665.   Z _ O U T  --  Output string to channel.
  11666.  
  11667.   Call with:
  11668.     channel:     Channel number to write to.
  11669.     s:           String to write.
  11670.     length > -1: How many characters of s to write.
  11671.     length < 0:  Write entire NUL-terminated string.
  11672.     flags == 0:  Supply line termination.
  11673.     flags >  0:  Don't supply line termination.
  11674.     flags <  0:  Write 'length' NUL characters.
  11675.   Special case:
  11676.     If flags > -1 and s is empty or NULL and length == 1, write 1 NUL.
  11677.   Returns:
  11678.     Number of characters written to channel on success, or
  11679.     negative FX_xxx error code on failure.
  11680. */
  11681. int
  11682. z_out(channel,s,length,flags) int channel, flags, length; char * s; {
  11683.     FILE * t;
  11684.     int x, n;
  11685.     char c = '\0';
  11686.  
  11687.     if (!s) s = "";                     /* Guard against null pointer */
  11688. #ifdef DEBUG
  11689.     if (deblog) {
  11690.         debug(F111,"z_out",s,channel);
  11691.         debug(F101,"z_out length","",length);
  11692.         debug(F101,"z_out flags","",flags);
  11693.     }
  11694. #endif /* DEBUG */
  11695.     if (!z_inited)                      /* File i/o inited? */
  11696.       return(z_error = FX_NOP);
  11697.     if (channel >= z_maxchan)           /* Channel in range? */
  11698.       return(z_error = FX_CHN);
  11699.     if (!z_file[channel])
  11700.       return(z_error = FX_NOP);
  11701.     if (!(t = z_file[channel]->z_fp))    /* File open? */
  11702.       return(z_error = FX_NOP);
  11703.     if (!((z_file[channel]->z_flags) & (FM_WRI|FM_APP))) /* In write mode? */
  11704.       return(z_error = FX_FOP);
  11705.     n = length;                         /* Length of string to write */
  11706.     if (n < 0) {                        /* Negative means get it ourselves */
  11707.         if (flags < 0)                  /* Except when told to write NULs in */
  11708.           return(z_error = FX_RNG);     /* which case args are inconsistent */
  11709.         n = strlen(s);                  /* Get length of string arg */
  11710.     }
  11711.     errno = 0;                          /* Reset errno */
  11712.     debug(F101,"z_out n","",n);
  11713.     if (flags < 0) {                    /* Writing NULs... */
  11714.         int i;
  11715.         for (i = 0; i < n; i++) {
  11716.             x = fwrite(&c,1,1,t);
  11717.             if (x < 1)
  11718.               return(z_error = (errno ? FX_SYS : FX_UNK));
  11719.         }
  11720.         z_file[channel]->z_nline = -1;   /* Current line no longer known */
  11721.         z_error = 0;
  11722.         return(i);
  11723.     } else {                            /* Writing string arg */
  11724.         if (n == 1 && !s[0])            /* Writing one char but it's NUL */
  11725.           x = fwrite(&c,1,1,t);
  11726.         else                            /* Writing non-NUL char or string */
  11727.           x = fwrite(s,1,n,t);
  11728.         debug(F101,"z_out fwrite",ckitoa(x),errno);
  11729.         if (x < n)                      /* Failure to write requested amount */
  11730.           return(z_error = (errno ? FX_SYS : FX_UNK)); /* Return error */
  11731.         if (flags == 0) {               /* If supplying line termination */
  11732.             if (fwrite("\n",1,1,t))     /* do that  */
  11733.               x += z_lt;                /* count the terminator */
  11734.             if (z_file[channel]->z_nline > -1) /* count this line */
  11735.               z_file[channel]->z_nline++;
  11736.         } else {
  11737.             z_file[channel]->z_nline = -1; /* Current line no longer known */
  11738.         }
  11739.     }
  11740.     z_error = 0;
  11741.     return(x);
  11742. }
  11743.  
  11744. #define Z_INBUFLEN 64
  11745.  
  11746. /*
  11747.   Z _ I N  --  Multichannel i/o file input function.
  11748.  
  11749.   Call with:
  11750.     channel number to read from.
  11751.     s = address of destination buffer.
  11752.     buflen = destination buffer length.
  11753.     length = Number of bytes to read, must be < buflen.
  11754.     flags: 0 = read a line; nonzero = read the given number of bytes.
  11755.   Returns:
  11756.     Number of bytes read into buffer or a negative error code.
  11757.     A terminating NUL is deposited after the last byte that was read.
  11758. */
  11759. int
  11760. z_in(channel,s,buflen,length,flags)
  11761.  int channel, buflen, length, flags; char * s;
  11762. /* z_in */ {
  11763.     int i, j, x;
  11764.     FILE * t;
  11765.     char * p;
  11766.  
  11767.     if (!z_inited)                      /* Check everything... */
  11768.       return(z_error = FX_NOP);
  11769.     if (channel >= z_maxchan)
  11770.       return(z_error = FX_CHN);
  11771.     if (!z_file[channel])
  11772.       return(z_error = FX_NOP);
  11773.     if (!(t = z_file[channel]->z_fp))
  11774.       return(z_error = FX_NOP);
  11775.     if (!((z_file[channel]->z_flags) & FM_REA))
  11776.       return(z_error = FX_FOP);
  11777.     if (!s)                             /* Check destination */
  11778.      return(z_error = FX_RNG);
  11779.     s[0] = NUL;
  11780.     if (length == 0)                    /* Read 0 bytes - easy. */
  11781.       return(z_error = 0);
  11782.     debug(F101,"z_in channel","",channel);
  11783.     debug(F101,"z_in buflen","",buflen);
  11784.     debug(F101,"z_in length","",length);
  11785.     debug(F101,"z_in flags","",flags);
  11786.     if (length < 0 || buflen < 0)       /* Check length args */
  11787.       return(z_error = FX_RNG);
  11788.     if (buflen <= length)
  11789.       return(z_error = FX_RNG);
  11790.     errno = 0;                          /* Reset errno */
  11791.     if (flags) {                        /* Read block or byte */
  11792.     int n;                /* 20050912 */
  11793.     n = length;            /* 20050912 */
  11794.     i = 0;                /* 20050912 */
  11795.     while (n > 0) {            /* 20050912 */
  11796.         i = fread(s,1,n,t);        /* 20050912 */
  11797. #ifdef DEBUG
  11798.         if (deblog) {
  11799.         debug(F111,"z_in block",s,i);
  11800.         debug(F101,"z_in block errno","",errno);
  11801.         debug(F101,"z_in block ferror","",ferror(t));
  11802.         debug(F101,"z_in block feof","",feof(t));
  11803.         }
  11804. #endif /* DEBUG */
  11805.         if (i == 0) break;        /* 20050912 */
  11806.         s += i;            /* 20050912 */
  11807.         n -= i;            /* 20050912 */
  11808.     }
  11809.     /* Current line no longer known */
  11810.         z_file[channel]->z_nline = (CK_OFF_T)-1;
  11811.     } else {                            /* Read line */
  11812. #ifndef COMMENT
  11813.         /* This method is used because it's simpler than the others */
  11814.         /* and also marginally faster. */
  11815.         debug(F101,"z_in getc loop","",CKFTELL(t));
  11816.         for (i = 0; i < length; i++) {
  11817.             if ((x = getc(t)) == EOF) {
  11818.                 debug(F101,"z_in getc error","",CKFTELL(t));
  11819.                 s[i] = '\0';
  11820.                 break;
  11821.             }
  11822.             s[i] = x;
  11823.             if (s[i] == '\n') {
  11824.                 s[i] = '\0';
  11825.                 break;
  11826.             }
  11827.         }
  11828.         debug(F111,"z_in line byte loop",ckitoa(errno),i);
  11829.         debug(F111,"z_in line got",s,z_file[channel]->z_nline);
  11830.         if (z_file[channel]->z_nline > -1)
  11831.           z_file[channel]->z_nline++;
  11832. #else
  11833. #ifdef COMMENT2
  11834.         /* Straightforward but strlen() slows it down. */
  11835.         s[0] = '\0';
  11836.         i = 0;
  11837.         if (fgets(s,length,t)) {
  11838.             i = strlen(s);
  11839.             if (i > 0 && s[i-1] == '\n') i--;
  11840.         }
  11841.         debug(F111,"z_in line fgets",ckitoa(errno),i);
  11842.         if (z_file[channel]->z_nline > -1)
  11843.           z_file[channel]->z_nline++;
  11844. #else
  11845.         /* This is a do-it-yourself fgets() with its own readahead and */
  11846.         /* putback.  It's a bit faster than real fgets() but not enough */
  11847.         /* to justify the added complexity or the risk of the ftell() and */
  11848.         /* fseek() calls failing. */
  11849.         int k, flag = 0;
  11850.         CK_OFF_T pos;
  11851.         for (i = 0; !flag && i <= (length - Z_INBUFLEN); i += Z_INBUFLEN) {
  11852.             k = ((length - i) < Z_INBUFLEN) ? length - i : Z_INBUFLEN;
  11853.             if ((x = fread(s+i,1,k,t)) < 1)
  11854.               break;
  11855.             s[i+x] = '\0';
  11856.             for (j = 0; j < x; j++) {
  11857.                 if (s[i+j] == '\n') {
  11858.                     s[i+j] = '\0';
  11859.                     flag ++;
  11860.                     pos = CKFTELL(t);
  11861.                     if (pos > -1) {
  11862.                         pos -= (x - j - 1);
  11863.                         x = CKFSEEK(t, pos, 0);
  11864.                         i += j;
  11865.                         break;
  11866.                     } else
  11867.                       return(z_error = FX_SYS);
  11868.                 }
  11869.             }
  11870.         }
  11871.         if (z_file[channel]->z_nline > -1)
  11872.           z_file[channel]->z_nline++;
  11873.         debug(F111,"z_in line chunk loop",ckitoa(errno),i);
  11874. #endif /* COMMENT2 */
  11875. #endif /* COMMENT */
  11876.     }
  11877.     debug(F111,"z_in i",ckitoa(errno),i);
  11878.     if (i < 0) i = 0;                   /* NUL-terminate result */
  11879.     s[i] = '\0';
  11880.     if (i > 0) {
  11881.         z_error = 0;
  11882.         return(i);
  11883.     }
  11884.     if (i == 0 && feof(t))              /* EOF on reading? */
  11885.       return(z_error = FX_EOF);         /* Return EOF code */
  11886.     return(errno ? (z_error = -1) : i); /* Return length or system error */
  11887. }
  11888.  
  11889. int
  11890. z_flush(channel) int channel; {         /* Flush output channel */
  11891.     FILE * t;
  11892.     int x;
  11893.     if (!z_inited)                      /* Regular checks */
  11894.       return(z_error = FX_NOP);
  11895.     if (channel >= z_maxchan)
  11896.       return(z_error = FX_CHN);
  11897.     if (!z_file[channel])
  11898.       return(z_error = FX_NOP);
  11899.     if (!(t = z_file[channel]->z_fp))
  11900.       return(z_error = FX_NOP);
  11901.     if (!((z_file[channel]->z_flags) & (FM_WRI|FM_APP))) /* Write access? */
  11902.       return(z_error = FX_FOP);
  11903.     errno = 0;                          /* Reset errno */
  11904.     x = fflush(t);                      /* Try to flush */
  11905.     return(x ? (z_error = FX_SYS) : 0); /* Return system error or 0 if OK */
  11906. }
  11907.  
  11908. int
  11909. #ifdef CK_ANSIC
  11910. z_seek(int channel, CK_OFF_T pos)    /* Move file pointer to byte */
  11911. #else
  11912. z_seek(channel,pos) int channel; CK_OFF_T pos; /* (seek to given position) */
  11913. #endif /* CK_ANSIC */
  11914. {
  11915.     int i, x = 0, rc;
  11916.     FILE * t;
  11917.     if (!z_inited)                      /* Check... */
  11918.       return(z_error = FX_NOP);
  11919.     if (channel >= z_maxchan)
  11920.       return(z_error = FX_CHN);
  11921.     if (!z_file[channel])
  11922.       return(z_error = FX_NOP);
  11923.     if (!(t = z_file[channel]->z_fp))
  11924.       return(z_error = FX_NOP);
  11925.     if (pos < 0L) {
  11926.         x = 2;
  11927.         pos = (pos == -2) ? -1L : 0L;
  11928.     }
  11929.     errno = 0;
  11930.     rc = CKFSEEK(t,pos,x);        /* Try to seek */
  11931.     debug(F111,"z_seek",ckitoa(errno),rc);
  11932.     if (rc < 0)                         /* OK? */
  11933.       return(z_error = FX_SYS); /* No. */
  11934.     z_file[channel]->z_nline = ((pos || x) ? -1 : 0);
  11935.     return(z_error = 0);
  11936. }
  11937.  
  11938. int
  11939. #ifdef CK_ANSIC
  11940. z_line(int channel, CK_OFF_T pos)           /* Move file pointer to line */
  11941. #else
  11942. z_line(channel,pos) int channel; CK_OFF_T pos; /* (seek to given position) */
  11943. #endif /* CK_ANSIC */
  11944. {
  11945.     int i, len, x = 0;
  11946.     CK_OFF_T current = (CK_OFF_T)0, prev = (CK_OFF_T)-1, old = (CK_OFF_T)-1;
  11947.     FILE * t;
  11948.     char tmpbuf[256];
  11949.     if (!z_inited)                      /* Check... */
  11950.       return(z_error = FX_NOP);
  11951.     if (channel >= z_maxchan)
  11952.       return(z_error = FX_CHN);
  11953.     if (!z_file[channel])
  11954.       return(z_error = FX_NOP);
  11955.     if (!(t = z_file[channel]->z_fp))
  11956.       return(z_error = FX_NOP);
  11957.     debug(F101,"z_line pos","",pos);
  11958.     if (pos < 0L) {                     /* EOF wanted */
  11959.         CK_OFF_T n;
  11960.         n = z_file[channel]->z_nline;
  11961.         debug(F101,"z_line n","",n);
  11962.         if (n < 0 || pos < 0) {
  11963.             rewind(t);
  11964.             n = 0;
  11965.         }
  11966.         while (1) {                     /* This could take a while... */
  11967.             if ((x = getc(t)) == EOF)
  11968.               break;
  11969.             if (x == '\n') {
  11970.                 n++;
  11971.                 if (pos == -2) {
  11972.                     old = prev;
  11973.                     prev = CKFTELL(t);
  11974.                 }
  11975.             }
  11976.         }
  11977.         debug(F101,"z_line old","",old);
  11978.         debug(F101,"z_line prev","",prev);
  11979.         if (pos == -2) {
  11980.             if ((x = z_seek(channel,old)) < 0)
  11981.               return(z_error = x);
  11982.             else
  11983.               n--;
  11984.         }
  11985.         z_file[channel]->z_nline = n;
  11986.         return(z_error = 0);
  11987.     }
  11988.     if (pos == 0L) {                    /* Rewind wanted */
  11989.         z_file[channel]->z_nline = 0L;
  11990.         rewind(t);
  11991.         debug(F100,"z_line rewind","",0);
  11992.         return(0L);
  11993.     }
  11994.     tmpbuf[255] = NUL;                  /* Make sure buf is NUL terminated */
  11995.     current = z_file[channel]->z_nline;  /* Current line */
  11996.     /*
  11997.       If necessary the following could be optimized, e.g. for positioning
  11998.       to a previous line in a large file without starting over.
  11999.     */
  12000.     if (current < 0 || pos < current) { /* Not known or behind us... */
  12001.         debug(F101,"z_line rewinding","",pos);
  12002.         if ((x = z_seek(channel, 0L)) < 0) /* Rewind */
  12003.           return(z_error = x);
  12004.         if (pos == 0)                   /* If 0th line wanted we're done */
  12005.           return(z_error = 0);
  12006.         current = 0;
  12007.     }
  12008.     while (current < pos) {             /* Search for specified line */
  12009.         if (fgets(tmpbuf,255,t)) {
  12010.             len = strlen(tmpbuf);
  12011.             if (len > 0 && tmpbuf[len-1] == '\n') {
  12012.                 current++;
  12013.                 debug(F111,"z_line read",ckitoa(len),current);
  12014.             } else if (len == 0) {
  12015.                 return(z_error = FX_UNK);
  12016.             }
  12017.         } else {
  12018.             z_file[channel]->z_nline = -1L;
  12019.             debug(F101,"z_line premature EOF","",current);
  12020.             return(z_error = FX_EOF);
  12021.         }
  12022.     }
  12023.     z_file[channel]->z_nline = current;
  12024.     debug(F101,"z_line result","",current);
  12025.     z_error = 0;
  12026.     return(current);
  12027. }
  12028.  
  12029. char *
  12030. z_getname(channel) int channel; {       /* Return name of file on channel */
  12031.     FILE * t;
  12032.     if (!z_inited) {
  12033.         z_error = FX_NOP;
  12034.         return(NULL);
  12035.     }
  12036.     if (channel >= z_maxchan) {
  12037.         z_error = FX_CHN;
  12038.         return(NULL);
  12039.     }
  12040.     if (!z_file[channel]) {
  12041.         z_error = FX_NOP;
  12042.         return(NULL);
  12043.     }
  12044.     if (!(t = z_file[channel]->z_fp)) {
  12045.         z_error = FX_NOP;
  12046.         return(NULL);
  12047.     }
  12048.     return((char *)(z_file[channel]->z_name));
  12049. }
  12050.  
  12051. int
  12052. z_getmode(channel) int channel; {       /* Return OPEN modes of channel */
  12053.     FILE * t;                           /* 0 if file not open */
  12054. #ifndef NOSTAT
  12055. #ifdef NT
  12056.     struct _stat statbuf;
  12057. #else /* NT */
  12058.     struct stat statbuf;
  12059. #endif /* NT */
  12060. #endif /* NOSTAT */
  12061.     int x;
  12062.     if (!z_inited)
  12063.       return(0);
  12064.     if (channel >= z_maxchan)
  12065.       return(z_error = FX_CHN);
  12066.     if (!z_file[channel])
  12067.       return(0);
  12068.     if (!(t = z_file[channel]->z_fp))
  12069.       return(0);
  12070.     x = z_file[channel]->z_flags;
  12071.     if (feof(t)) {                      /* This might not work for */
  12072.         x |= FM_EOF;                    /* output files */
  12073. #ifndef NOSTAT
  12074.     /* But this does if we can use it. */
  12075.     } else if (stat(z_file[channel]->z_name,&statbuf) > -1) {
  12076.         if (CKFTELL(t) == statbuf.st_size)
  12077.           x |= FM_EOF;
  12078. #endif /* NOSTAT */
  12079.     }
  12080.     return(x);
  12081. }
  12082.  
  12083. CK_OFF_T
  12084. z_getpos(channel) int channel; {        /* Get file pointer position */
  12085.     FILE * t;                           /* on this channel */
  12086.     CK_OFF_T x;
  12087.     if (!z_inited)
  12088.       return(z_error = FX_NOP);
  12089.     if (channel >= z_maxchan)
  12090.       return(z_error = FX_CHN);
  12091.     if (!z_file[channel])
  12092.       return(z_error = FX_NOP);
  12093.     if (!(t = z_file[channel]->z_fp))
  12094.       return(z_error = FX_NOP);
  12095.     x = CKFTELL(t);
  12096.     return((x < 0L) ? (z_error = FX_SYS) : x);
  12097. }
  12098.  
  12099. CK_OFF_T
  12100. z_getline(channel) int channel; {       /* Get current line number */
  12101.     FILE * t;                           /* in file on this channel */
  12102.     CK_OFF_T rc;
  12103.     if (!z_inited)
  12104.       return(z_error = FX_NOP);
  12105.     if (channel >= z_maxchan)
  12106.       return(z_error = FX_CHN);
  12107.     if (!z_file[channel])
  12108.       return(z_error = FX_NOP);
  12109.     if (!(t = z_file[channel]->z_fp))
  12110.       return(z_error = FX_NOP);
  12111.     debug(F101,"z_getline","",z_file[channel]->z_nline);
  12112.     rc = z_file[channel]->z_nline;
  12113.     return((rc < 0) ? (z_error = FX_LNU) : rc);
  12114. }
  12115.  
  12116. int
  12117. z_getfnum(channel) int channel; {       /* Get file number / handle */
  12118.     FILE * t;                           /* for file on this channel */
  12119.     if (!z_inited)
  12120.       return(z_error = FX_NOP);
  12121.     if (channel >= z_maxchan)
  12122.       return(z_error = FX_CHN);
  12123.     if (!z_file[channel])
  12124.       return(z_error = FX_NOP);
  12125.     if (!(t = z_file[channel]->z_fp))
  12126.       return(z_error = FX_NOP);
  12127.     z_error = 0;
  12128.     return(fileno(t));
  12129. }
  12130.  
  12131. /*
  12132.   Line-oriented counts and seeks are as dumb as they can be at the moment.
  12133.   Later we can speed them up by building little indexes.
  12134. */
  12135. CK_OFF_T
  12136. z_count(channel, what) int channel, what; { /* Count bytes or lines in file */
  12137.     FILE * t;
  12138.     int i, x;
  12139.     CK_OFF_T pos, count = (CK_OFF_T)0;
  12140.     if (!z_inited)                      /* Check stuff... */
  12141.       return(z_error = FX_NOP);
  12142.     if (channel >= z_maxchan)
  12143.       return(z_error = FX_CHN);
  12144.     if (!z_file[channel])
  12145.       return(z_error = FX_NOP);
  12146.     if (!(t = z_file[channel]->z_fp))
  12147.       return(z_error = FX_NOP);
  12148.     pos = CKFTELL(t);            /* Save current file pointer */
  12149.     errno = 0;
  12150.     z_error = 0;
  12151.     if (what == RD_CHAR) {              /* Size in bytes requested */
  12152. #ifdef COMMENT
  12153.         if (!CKFSEEK(t,0L,2)) {        /* Seek to end */
  12154.             count = CKFTELL(t);        /* Get file pointer */
  12155.             CKFSEEK(t,pos,0);        /* Restore file file pointer */
  12156.             return(count);
  12157.         } else                          /* Fallback in case seek fails */
  12158. #endif    /* COMMENT */
  12159.           return(zgetfs(z_file[channel]->z_name));
  12160.     }
  12161.     rewind(t);                          /* Line count requested - rewind. */
  12162.     while (1) {                         /* Count lines. */
  12163.         if ((x = getc(t)) == EOF)       /* Stupid byte loop */
  12164.           break;                        /* but it works as well as anything */
  12165.         if (x == '\n')                  /* else... */
  12166.           count++;
  12167.     }
  12168.     x = CKFSEEK(t,pos,0);        /* Restore file pointer */
  12169.     return(count);
  12170. }
  12171.  
  12172. /* User interface for generalized channel-oriented file i/o */
  12173.  
  12174. struct keytab fctab[] = {               /* FILE subcommands */
  12175.     { "close",      FIL_CLS, 0 },
  12176.     { "count",      FIL_COU, 0 },
  12177.     { "flush",      FIL_FLU, 0 },
  12178.     { "list",       FIL_LIS, 0 },
  12179.     { "open",       FIL_OPN, 0 },
  12180.     { "read",       FIL_REA, 0 },
  12181.     { "rewind",     FIL_REW, 0 },
  12182.     { "seek",       FIL_SEE, 0 },
  12183.     { "status",     FIL_STA, 0 },
  12184.     { "write",      FIL_WRI, 0 }
  12185. };
  12186. int nfctab = (sizeof (fctab) / sizeof (struct keytab));
  12187.  
  12188. static struct keytab fcswtab[] = {      /* OPEN modes */
  12189.     { "/append",    FM_APP,  0 },
  12190.     { "/binary",    FM_BIN,  0 },
  12191. #ifdef COMMENT
  12192.     { "/command",   FM_CMD,  0 },       /* Not implemented */
  12193. #endif /* COMMENT */
  12194.     { "/read",      FM_REA,  0 },
  12195.     { "/write",     FM_WRI,  0 }
  12196. };
  12197. static int nfcswtab = (sizeof (fcswtab) / sizeof (struct keytab));
  12198.  
  12199. static struct keytab fclkwtab[] = {     /* CLOSE options */
  12200.     { "all",        1,       0 }
  12201. };
  12202.  
  12203. static struct keytab fsekwtab[] = {     /* SEEK symbols */
  12204.     { "eof",        1,       0 },
  12205.     { "last",       2,       0 }
  12206. };
  12207. static int nfsekwtab = (sizeof (fsekwtab) / sizeof (struct keytab));
  12208.  
  12209. #define SEE_LINE  RD_LINE               /* SEEK options */
  12210. #define SEE_CHAR  RD_CHAR
  12211. #define SEE_REL   3
  12212. #define SEE_ABS   4
  12213. #define SEE_FIND  5
  12214.  
  12215. static struct keytab fskswtab[] = {
  12216.     { "/absolute",  SEE_ABS,  0 },
  12217.     { "/byte",      SEE_CHAR, 0 },
  12218.     { "/character", SEE_CHAR, CM_INV },
  12219.     { "/find",      SEE_FIND, CM_ARG },
  12220.     { "/line",      SEE_LINE, 0 },
  12221.     { "/relative",  SEE_REL,  0 }
  12222. };
  12223. static int nfskswtab = (sizeof (fskswtab) / sizeof (struct keytab));
  12224.  
  12225. #define COU_LINE  RD_LINE               /* COUNT options */
  12226. #define COU_CHAR  RD_CHAR
  12227. #define COU_LIS   3
  12228. #define COU_NOL   4
  12229.  
  12230. static struct keytab fcoswtab[] = {
  12231.     { "/bytes",     COU_CHAR, 0      },
  12232.     { "/characters",COU_CHAR, CM_INV },
  12233.     { "/lines",     COU_LINE, 0      },
  12234.     { "/list",      COU_LIS,  0      },
  12235.     { "/nolist",    COU_NOL,  0      },
  12236.     { "/quiet",     COU_NOL,  CM_INV }
  12237. };
  12238. static int nfcoswtab = (sizeof (fcoswtab) / sizeof (struct keytab));
  12239.  
  12240. static struct keytab frdtab[] = {       /* READ types */
  12241.     { "/block",     RD_SIZE, CM_INV|CM_ARG },
  12242.     { "/byte",      RD_CHAR, CM_INV },
  12243.     { "/character", RD_CHAR, 0      },
  12244.     { "/line",      RD_LINE, 0      },
  12245.     { "/size",      RD_SIZE, CM_ARG },
  12246.     { "/trim",      RD_TRIM, 0      },
  12247.     { "/untabify",  RD_UNTA, 0      }
  12248. };
  12249. static int nfrdtab = (sizeof (frdtab) / sizeof (struct keytab));
  12250.  
  12251. static struct keytab fwrtab[] = {       /* WRITE types */
  12252.     { "/block",     WR_SIZE, CM_INV|CM_ARG },
  12253.     { "/byte",      WR_CHAR, CM_INV },
  12254.     { "/character", WR_CHAR, 0      },
  12255.     { "/line",      WR_LINE, 0      },
  12256.     { "/lpad",      WR_LPAD, CM_ARG },
  12257.     { "/rpad",      WR_RPAD, CM_ARG },
  12258.     { "/size",      WR_SIZE, CM_ARG },
  12259.     { "/string",    WR_STRI, 0      }
  12260. };
  12261. static int nfwrtab = (sizeof (fwrtab) / sizeof (struct keytab));
  12262.  
  12263. static char blanks[] = "\040\040\040\040"; /* Some blanks for formatting */
  12264. static char * seek_target = NULL;
  12265.  
  12266. int
  12267. dofile(op) int op; {                    /* Do the FILE command */
  12268.     char vnambuf[VNAML];                /* Buffer for variable names */
  12269.     char *vnp = NULL;                   /* Pointer to same */
  12270.     char zfilnam[CKMAXPATH+2];
  12271.     char * p, * m;
  12272.     struct FDB fl, sw, nu;
  12273.     CK_OFF_T z;
  12274.     int rsize, filmode = 0, relative = -1, eofflg = 0;
  12275.     int rc, x, y, cx, n, getval, dummy, confirmed, listing = -1;
  12276.     int charflag = 0, sizeflag = 0;
  12277.     int pad = 32, wr_lpad = 0, wr_rpad = 0, rd_trim = 0, rd_untab = 0;
  12278.  
  12279.     makestr(&seek_target,NULL);
  12280.  
  12281.     if (op == XXFILE) {                 /* FILE command was given */
  12282.         /* Get subcommand */
  12283.         if ((cx = cmkey(fctab,nfctab,"Operation","",xxstring)) < 0) {
  12284.             if (cx == -3) {
  12285.                 printf("?File operation required\n");
  12286.                 x = -9;
  12287.             }
  12288.             return(cx);
  12289.         }
  12290.     } else {                            /* Shorthand command was given */
  12291.         switch (op) {
  12292.           case XXF_CL: cx = FIL_CLS; break; /* FCLOSE */
  12293.           case XXF_FL: cx = FIL_FLU; break; /* FFLUSH */
  12294.           case XXF_LI: cx = FIL_LIS; break; /* FLIST */
  12295.           case XXF_OP: cx = FIL_OPN; break; /* etc... */
  12296.           case XXF_RE: cx = FIL_REA; break;
  12297.           case XXF_RW: cx = FIL_REW; break;
  12298.           case XXF_SE: cx = FIL_SEE; break;
  12299.           case XXF_ST: cx = FIL_STA; break;
  12300.           case XXF_WR: cx = FIL_WRI; break;
  12301.           case XXF_CO: cx = FIL_COU; break;
  12302.           default: return(-2);
  12303.         }
  12304.     }
  12305.     switch (cx) {                       /* Do requested subcommand */
  12306.       case FIL_OPN:                     /* OPEN */
  12307.         cmfdbi(&sw,                     /* Switches */
  12308.                _CMKEY,                  /* fcode */
  12309.                "Variable or switch",    /* hlpmsg */
  12310.                "",                      /* default */
  12311.                "",                      /* addtl string data */
  12312.                nfcswtab,                /* addtl numeric data 1: tbl size */
  12313.                4,                       /* addtl numeric data 2: 4 = cmswi */
  12314.                xxstring,                /* Processing function */
  12315.                fcswtab,                 /* Keyword table */
  12316.                &fl                      /* Pointer to next FDB */
  12317.                );
  12318.         cmfdbi(&fl,                     /* Anything that doesn't match */
  12319.                _CMFLD,                  /* fcode */
  12320.                "Variable",              /* hlpmsg */
  12321.                "",
  12322.                "",
  12323.                0,
  12324.                0,
  12325.                NULL,
  12326.                NULL,
  12327.                NULL
  12328.                );
  12329.         while (1) {
  12330.             x = cmfdb(&sw);             /* Parse something */
  12331.             if (x < 0) {
  12332.                 if (x == -3) {
  12333.                     printf("?Variable name and file name required\n");
  12334.                     x = -9;
  12335.                 }
  12336.                 return(x);
  12337.             }
  12338.             if (cmresult.fcode == _CMFLD)
  12339.               break;
  12340.             else if (cmresult.fcode == _CMKEY) {
  12341.                 char c;
  12342.                 c = cmgbrk();
  12343.                 if ((getval =
  12344.                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  12345.                     printf("?This switch does not take an argument\n");
  12346.                     return(-9);
  12347.                 }
  12348. #ifdef COMMENT
  12349.                 /* Uncomment if we add any switches here that take args */
  12350.                 if (!getval && (cmgkwflgs() & CM_ARG)) {
  12351.                     printf("?This switch requires an argument\n");
  12352.                     return(-9);         /* (none do...) */
  12353.                 }
  12354. #endif /* COMMENT */
  12355.                 filmode |= cmresult.nresult; /* OR in the file mode */
  12356.             } else
  12357.               return(-2);
  12358.         }
  12359.         /* Not a switch - get the string */
  12360.         ckstrncpy(vnambuf,cmresult.sresult,VNAML);
  12361.         if (!vnambuf[0] || chknum(vnambuf)) { /* (if there is one...) */
  12362.             printf("?Variable name required\n");
  12363.             return(-9);
  12364.         }
  12365.         vnp = vnambuf;                  /* Check variable-name syntax */
  12366.         if (vnambuf[0] == CMDQ &&
  12367.             (vnambuf[1] == '%' || vnambuf[1] == '&'))
  12368.           vnp++;
  12369.         y = 0;
  12370.         if (*vnp == '%' || *vnp == '&') {
  12371.             if ((y = parsevar(vnp,&x,&dummy)) < 0) {
  12372.                 printf("?Syntax error in variable name\n");
  12373.                 return(-9);
  12374.             }
  12375.         }
  12376.     /* Assign a negative channel number in case we fail */
  12377.     addmac(vnambuf,"-1");
  12378.  
  12379.         if (!(filmode & FM_RWA))        /* If no access mode specified */
  12380.           filmode |= FM_REA;            /* default to /READ. */
  12381.  
  12382.         y = 0;                          /* Now parse the filename */
  12383.         if ((filmode & FM_RWA) == FM_WRI) {
  12384.         x = cmofi("Name of new file","",&s,xxstring);
  12385.     } else if ((filmode & FM_RWA) == FM_REA) {
  12386.         x = cmifi("Name of existing file","",&s,&y,xxstring);
  12387.     } else {
  12388.             x = cmiofi("Filename","",&s,&y,xxstring);
  12389.             debug(F111,"fopen /append x",s,x);
  12390.     }
  12391.         if (x < 0) {
  12392.             if (x == -3) {
  12393.                 printf("?Filename required\n");
  12394.                 x = -9;
  12395.             }
  12396.             return(x);
  12397.         }
  12398.         if (y) {                        /* No wildcards */
  12399.             printf("?Wildcards not allowed here\n");
  12400.             return(-9);
  12401.         }
  12402.         if (filmode & (FM_APP|FM_WRI)) { /* Check output access */
  12403. #ifndef VMS
  12404.             if (zchko(s) < 0) {          /* and set error code if denied */
  12405.                 z_error = FX_ACC;
  12406.                 printf("?Write access denied - \"%s\"\n",s);
  12407.                 return(-9);
  12408.             }
  12409. #endif /* VMS */
  12410.         }
  12411.         ckstrncpy(zfilnam,s,CKMAXPATH); /* Is OK - make safe copy */
  12412.         if ((x = cmcfm()) < 0)          /* Get confirmation of command */
  12413.           return(x);
  12414.         if ((n = z_open(zfilnam,filmode)) < 0) {
  12415.             printf("?OPEN failed - %s: %s\n",zfilnam,ckferror(n));
  12416.             return(-9);
  12417.         }
  12418.         addmac(vnambuf,ckitoa(n));      /* Assign channel number to variable */
  12419.         return(success = 1);
  12420.  
  12421.       case FIL_REW:                     /* REWIND */
  12422.         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
  12423.             if (x == -3) {
  12424.                 printf("?Channel number required\n");
  12425.                 x = -9;
  12426.             }
  12427.             return(x);
  12428.         }
  12429.         if ((x = cmcfm()) < 0)
  12430.           return(x);
  12431.     if (n == -9) return(success = 0);
  12432.     if (n == -8) return(success = 1);
  12433.  
  12434.         if ((rc = z_seek(n,0L)) < 0) {
  12435.             printf("?REWIND failed - Channel %d: %s\n",n,ckferror(rc));
  12436.             return(-9);
  12437.         }
  12438.         return(success = 1);
  12439.  
  12440.       case FIL_CLS:                     /* CLOSE */
  12441. #ifdef COMMENT                /* fdc 20100804 - bad idea */
  12442.          {
  12443.         int i, j, k;        /* Supply default if only one open */
  12444.         s = "";
  12445.         for (k = 0, j = 0, i = 0; i < z_maxchan; i++) {
  12446.         if (z_file)
  12447.           if (z_file[i])
  12448.             if (z_file[i]->z_fp) { k++; j = i; }
  12449.         }
  12450.         if (k == 1) s = ckitoa(j);
  12451.      }
  12452. #endif    /* COMMENT */
  12453.           cmfdbi(&nu,                   /* Second FDB - channel number */
  12454.                  _CMNUM,                /* fcode */
  12455.                  "Channel number or ALL", /* Help message */
  12456.                  s,            /* default */
  12457.                  "",                    /* addtl string data */
  12458.                  10,                    /* addtl numeric data 1: radix */
  12459.                  0,                     /* addtl numeric data 2: 0 */
  12460.                  xxstring,              /* Processing function */
  12461.                  NULL,                  /* Keyword table */
  12462.                  &sw            /* Pointer to next FDB */
  12463.                  );                     /* Pointer to next FDB */
  12464.      cmfdbi(&sw,            /* First FDB - command switches */
  12465.                  _CMKEY,                /* fcode */
  12466.                  "",            /* help message */
  12467.          "",            /* Default */
  12468.          "",            /* No addtl string data */
  12469.                  1,                     /* addtl numeric data 1: tbl size */
  12470.                  0,                     /* addtl numeric data 2: 4 = cmswi */
  12471.                  xxstring,              /* Processing function */
  12472.                  fclkwtab,              /* Keyword table */
  12473.          NULL            /* Last in chain */
  12474.                  );
  12475.         x = cmfdb(&nu);                 /* Parse something */
  12476.         if (x < 0) {
  12477.             if (x == -3) {
  12478.                 printf("?Channel number or ALL required\n");
  12479.                 x = -9;
  12480.             }
  12481.             return(x);
  12482.         }
  12483.         if (cmresult.fcode == _CMNUM)
  12484.           n = cmresult.nresult;
  12485.         else if (cmresult.fcode == _CMKEY)
  12486.           n = -1;
  12487.         if ((x = cmcfm()) < 0)
  12488.           return(x);
  12489.     if (n == -9) return(success = 0);
  12490.     if (n == -8) return(success = 1);
  12491.  
  12492.         rc = 1;
  12493.         if (n < 0) {
  12494.             int count = 0;
  12495.             int i;
  12496.             for (i = 0; i < z_maxchan; i++) {
  12497.                 x = z_close(i);
  12498.                 if (x == FX_SYS) {
  12499.                     printf("?CLOSE failed - Channel %d: %s\n",n,ckferror(x));
  12500.                     rc = 0;
  12501.                 } else if (x > -1)
  12502.                   count++;
  12503.             }
  12504.             debug(F101,"FILE CLOSE ALL","",count);
  12505.         } else if ((x = z_close(n)) < 0) {
  12506.             printf("?CLOSE failed - Channel %d: %s\n",n,ckferror(x));
  12507.             return(-9);
  12508.         }
  12509.         return(success = rc);
  12510.  
  12511.       case FIL_REA:                     /* READ */
  12512.       case FIL_WRI:                     /* WRITE */
  12513.         rsize = 0;
  12514.         cmfdbi(&sw,                     /* Switches */
  12515.                _CMKEY,                  /* fcode */
  12516.                "Channel or switch",     /* hlpmsg */
  12517.                "",                      /* default */
  12518.                "",                      /* addtl string data */
  12519.                (cx == FIL_REA) ? nfrdtab : nfwrtab,
  12520.                4,                       /* addtl numeric data 2: 4 = cmswi */
  12521.                xxstring,                /* Processing function */
  12522.                (cx == FIL_REA) ? frdtab : fwrtab, /* Keyword table */
  12523.                &nu                      /* Pointer to next FDB */
  12524.                );
  12525.         cmfdbi(&nu,                     /* Channel number */
  12526.                _CMNUM,                  /* fcode */
  12527.                "Channel",
  12528.                "",                      /* default */
  12529.                "",                      /* addtl string data */
  12530.                10,                      /* addtl numeric data 1: radix */
  12531.                0,                       /* addtl numeric data 2: 0 */
  12532.                xxstring,                /* Processing function */
  12533.                NULL,                    /* Keyword table */
  12534.                NULL                     /* Pointer to next FDB */
  12535.                );
  12536.         do {
  12537.             x = cmfdb(&sw);             /* Parse something */
  12538.             if (x < 0) {
  12539.                 if (x == -3) {
  12540.                     printf("?Channel number required\n");
  12541.                     x = -9;
  12542.                 }
  12543.                 return(x);
  12544.             }
  12545.             if (cmresult.fcode == _CMNUM) /* Channel number */
  12546.               break;
  12547.             else if (cmresult.fcode == _CMKEY) { /* Switch */
  12548.                 char c;
  12549.                 c = cmgbrk();
  12550.                 if ((getval =
  12551.                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  12552.                     printf("?This switch does not take an argument\n");
  12553.                     return(-9);
  12554.                 }
  12555.                 if (!getval && (cmgkwflgs() & CM_ARG)) {
  12556.                     printf("?This switch requires an argument\n");
  12557.                     return(-9);
  12558.                 }
  12559.                 switch (cmresult.nresult) {
  12560.                   case WR_LINE:
  12561.                     charflag = 0;
  12562.                     sizeflag = 0;
  12563.                     rsize = 0;
  12564.                     break;
  12565.                   case WR_CHAR:
  12566.                     rsize = 1;
  12567.                     charflag = 1;
  12568.                     sizeflag = 1;
  12569.                     break;
  12570.                   case WR_SIZE:
  12571.                     if ((x = cmnum("Bytes","",10,&rsize, xxstring)) < 0) {
  12572.                         if (x == -3) {
  12573.                             printf("?Number required\n");
  12574.                             x = -9;
  12575.                         }
  12576.                         return(x);
  12577.                     }
  12578.             if (rsize > LINBUFSIZ) {
  12579.             printf("?Maximum FREAD/FWRITE size is %d\n",LINBUFSIZ);
  12580.             rsize = 0;
  12581.             return(-9);
  12582.             }
  12583.                     charflag = 0;
  12584.                     sizeflag = 1;
  12585.                     break;
  12586.                   case WR_STRI:
  12587.                     rsize = 1;
  12588.                     charflag = 0;
  12589.                     sizeflag = 0;
  12590.                     break;
  12591.                   case WR_LPAD:
  12592.                   case WR_RPAD:
  12593.                     if ((x = cmnum("Numeric ASCII character value",
  12594.                                    "32",10,&pad, xxstring)) < 0)
  12595.                       return(x);
  12596.                     if (cmresult.nresult == WR_LPAD)
  12597.                       wr_lpad = 1;
  12598.                     else
  12599.                       wr_rpad = 1;
  12600.                     break;
  12601.           case RD_TRIM:
  12602.             rd_trim = 1;
  12603.             break;
  12604.           case RD_UNTA:
  12605.             rd_untab = 1;
  12606.             break;
  12607.                 }
  12608.                 debug(F101,"FILE READ rsize 2","",rsize);
  12609.             } else
  12610.               return(-2);
  12611.         } while
  12612.           (cmresult.fcode == _CMKEY);
  12613.  
  12614.         n = cmresult.nresult;           /* Channel */
  12615.         debug(F101,"FILE READ/WRITE channel","",n);
  12616.  
  12617.         if (cx == FIL_WRI) {            /* WRITE */
  12618.             int len = 0;
  12619.             if ((x = cmtxt("Text","",&s,xxstring)) < 0)
  12620.               return(x);
  12621.         if (n == -9) return(success = 0);
  12622.         if (n == -8) return(success = 1);
  12623.  
  12624.             ckstrncpy(line,s,LINBUFSIZ); /* Make a safe copy */
  12625.             s = line;
  12626.             s = brstrip(s);             /* Strip braces */
  12627.             if (charflag) {             /* Write one char */
  12628.                 len = 1;                /* So length = 1 */
  12629.                 rsize = 1;              /* Don't supply terminator */
  12630.             } else if (!sizeflag) {     /* Write a string */
  12631.                 len = -1;               /* So length is unspecified */
  12632.             } else {                    /* Write a block of given size */
  12633.                 int i, k, xx;
  12634.                 if (rsize > TMPBUFSIZ) {
  12635.                     z_error = FX_OFL;
  12636.                     printf("?Buffer overflow\n");
  12637.                     return(-9);
  12638.                 }
  12639.                 len = rsize;            /* rsize is really length */
  12640.                 rsize = 1;              /* Don't supply a terminator */
  12641.                 xx = strlen(s);         /* Size of given string */
  12642.                 if (xx >= len) {        /* Bigger or equal */
  12643.                     s[len] = NUL;
  12644.                 } else if (wr_lpad) {   /* Smaller, left-padding requested */
  12645.                     for (i = 0; i < len - xx; i++) /* Must make a copy */
  12646.                       tmpbuf[i] = pad;
  12647.                     ckstrncpy(tmpbuf+i,s,TMPBUFSIZ-i);
  12648.                     tmpbuf[len] = NUL;
  12649.                     s = tmpbuf;         /* Redirect write source */
  12650.                 } else if (wr_rpad) {   /* Smaller with right-padding */
  12651.                     for (i = xx; i < len; i++)
  12652.                       s[i] = pad;
  12653.                     s[len] = NUL;
  12654.                 }
  12655.             }
  12656.             if ((rc = z_out(n,s,len,rsize)) < 0) { /* Try to write */
  12657.                 printf("?Channel %d WRITE error: %s\n",n,ckferror(rc));
  12658.                 return(-9);
  12659.             }
  12660.         } else {                        /* FIL_REA READ */
  12661.             confirmed = 0;
  12662.             vnambuf[0] = NUL;
  12663.             x = cmfld("Variable name","",&s,NULL);
  12664.             debug(F111,"FILE READ cmfld",s,x);
  12665.             if (x < 0) {
  12666.                 if (x == -3 || !*s) {
  12667.                     if ((x = cmcfm()) < 0)
  12668.                       return(x);
  12669.                     else
  12670.                       confirmed++;
  12671.                 } else
  12672.                   return(x);
  12673.             }
  12674.             ckstrncpy(vnambuf,s,VNAML);
  12675.             debug(F111,"FILE READ vnambuf",vnambuf,confirmed);
  12676.             if (vnambuf[0]) {           /* Variable name given, check it */
  12677.                 if (!confirmed) {
  12678.                     x = cmcfm();
  12679.                     if (x < 0)
  12680.                       return(x);
  12681.                     else
  12682.                       confirmed++;
  12683.                 }
  12684.                 vnp = vnambuf;
  12685.                 if (vnambuf[0] == CMDQ &&
  12686.                     (vnambuf[1] == '%' || vnambuf[1] == '&'))
  12687.                   vnp++;
  12688.                 y = 0;
  12689.                 if (*vnp == '%' || *vnp == '&') {
  12690.                     if ((y = parsevar(vnp,&x,&dummy)) < 0) {
  12691.                         printf("?Syntax error in variable name\n");
  12692.                         return(-9);
  12693.                     }
  12694.                 }
  12695.             }
  12696.             debug(F111,"FILE READ variable",vnambuf,confirmed);
  12697.  
  12698.             if (!confirmed)
  12699.               if ((x = cmcfm()) < 0)
  12700.                 return(x);
  12701.  
  12702.         if (n == -9) return(success = 0);
  12703.         if (n == -8) return(success = 1);
  12704.  
  12705.             line[0] = NUL;              /* Clear destination buffer */
  12706. #ifdef COMMENT
  12707.             if (rsize >= LINBUFSIZ)     /* Don't overrun it */
  12708.               rsize = LINBUFSIZ - 1;
  12709. #endif    /* COMMENT */
  12710.  
  12711.             if (rsize == 0) {        /* Read a line */
  12712.         rc = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
  12713.             } else {
  12714.         rc = z_in(n,line,LINBUFSIZ,rsize,1); /* Read a block */
  12715.         }
  12716.             if (rc < 0) {               /* Error... */
  12717.                 debug(F101,"FILE READ error","",rc);
  12718.                 debug(F101,"FILE READ errno","",errno);
  12719.                 if (rc == FX_EOF) {     /* EOF - fail but no error message */
  12720.                     return(success = 0);
  12721.                 } else {                /* Other error - fail and print msg */
  12722.                     printf("?READ error: %s\n",ckferror(rc));
  12723.                     return(-9);
  12724.                 }
  12725.             }
  12726.         if (rsize == 0) {        /* FREAD /LINE postprocessing */
  12727.         if (rd_trim) {        /* Trim */
  12728.             int i, k;
  12729.             k = strlen(line);
  12730.             if (k > 0) {
  12731.             for (i = k-1; i > 0; i--) {
  12732.                 if (line[i] == SP || line[i] == '\t')
  12733.                   line[i] = NUL;
  12734.                 else
  12735.                   break;
  12736.             }
  12737.             }
  12738.         }
  12739.         if (rd_untab) {        /* Untabify */
  12740.             if (untabify(line,tmpbuf,TMPBUFSIZ) > -1)
  12741.               ckstrncpy(line,tmpbuf,LINBUFSIZ);
  12742.         }
  12743.         }
  12744.             debug(F110,"FILE READ data",line,0);
  12745.             if (vnambuf[0])             /* Read OK - If variable name given */
  12746.               addmac(vnambuf,line);     /* Assign result to variable */
  12747.             else                        /* otherwise */
  12748.               printf("%s\n",line);      /* just print it */
  12749.         }
  12750.         return(success = 1);
  12751.  
  12752.       case FIL_SEE:                     /* SEEK */
  12753.       case FIL_COU:                     /* COUNT */
  12754.         rsize = RD_CHAR;                /* Defaults to /BYTE */
  12755.         cmfdbi(&sw,                     /* Switches */
  12756.                _CMKEY,                  /* fcode */
  12757.                "Channel or switch",     /* hlpmsg */
  12758.                "",                      /* default */
  12759.                "",                      /* addtl string data */
  12760.                ((cx == FIL_SEE) ? nfskswtab : nfcoswtab),
  12761.                4,                       /* addtl numeric data 2: 4 = cmswi */
  12762.                xxstring,                /* Processing function */
  12763.                ((cx == FIL_SEE) ? fskswtab : fcoswtab),
  12764.                &nu                      /* Pointer to next FDB */
  12765.                );
  12766.         cmfdbi(&nu,                     /* Channel number */
  12767.                _CMNUM,                  /* fcode */
  12768.                "Channel",
  12769.                "",                      /* default */
  12770.                "",                      /* addtl string data */
  12771.                10,                      /* addtl numeric data 1: radix */
  12772.                0,                       /* addtl numeric data 2: 0 */
  12773.                xxstring,                /* Processing function */
  12774.                NULL,                    /* Keyword table */
  12775.                NULL                     /* Pointer to next FDB */
  12776.                );
  12777.         do {
  12778.             x = cmfdb(&sw);             /* Parse something */
  12779.             if (x < 0) {
  12780.                 if (x == -3) {
  12781.                     printf("?Channel number required\n");
  12782.                     x = -9;
  12783.                 }
  12784.                 return(x);
  12785.             }
  12786.             if (cmresult.fcode == _CMNUM) /* Channel number */
  12787.               break;
  12788.             else if (cmresult.fcode == _CMKEY) { /* Switch */
  12789.                 char c;
  12790.                 c = cmgbrk();
  12791.                 if ((getval =
  12792.                      (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  12793.                     printf("?This switch does not take an argument\n");
  12794.                     return(-9);
  12795.                 }
  12796.                 if (cx == FIL_SEE) {
  12797.                     switch (cmresult.nresult) {
  12798.                       case SEE_REL: relative = 1; break;
  12799.                       case SEE_ABS: relative = 0; break;
  12800.               case SEE_FIND: {
  12801.               if (getval) {
  12802.                   y = cmfld("string or pattern","",&s,xxstring);
  12803.                   if (y < 0)
  12804.                 return(y);
  12805.                   makestr(&seek_target,brstrip(s));
  12806.                   break;
  12807.               }
  12808.               }
  12809.                       default: rsize = cmresult.nresult;
  12810.                     }
  12811.                 } else if (cx == FIL_COU) {
  12812.                     switch (cmresult.nresult) {
  12813.                       case COU_LIS: listing = 1; break;
  12814.                       case COU_NOL: listing = 0; break;
  12815.                       default: rsize = cmresult.nresult;
  12816.                     }
  12817.                 }
  12818.             }
  12819.         } while
  12820.           (cmresult.fcode == _CMKEY);
  12821.  
  12822.         n = cmresult.nresult;           /* Channel */
  12823.         debug(F101,"FILE SEEK/COUNT channel","",n);
  12824.         if (cx == FIL_COU) {
  12825.             if ((x = cmcfm()) < 0)
  12826.               return(x);
  12827.         if (n == -9) return(success = 0);
  12828.         if (n == -8) return(success = 1);
  12829.  
  12830.             z_filcount = z_count(n,rsize);
  12831.             if (z_filcount < 0) {
  12832.                 rc = z_filcount;
  12833.                 printf("?COUNT error: %s\n",ckferror(rc));
  12834.                 return(-9);
  12835.             }
  12836.             if (listing < 0)
  12837.               listing = !xcmdsrc;
  12838.             if (listing)
  12839.               printf(" %ld %s%s\n",
  12840.                      z_filcount,
  12841.                      ((rsize == RD_CHAR) ? "byte" : "line"),
  12842.                      ((z_filcount == 1L) ? "" : "s")
  12843.                      );
  12844.             return(success = (z_filcount > -1) ? 1 : 0);
  12845.         }
  12846.     m = (rsize == RD_CHAR) ?
  12847.         "Number of bytes;\n or keyword" :
  12848.         "Number of lines;\n or keyword";
  12849.         cmfdbi(&sw,                     /* SEEK symbolic targets (EOF) */
  12850.                _CMKEY,                  /* fcode */
  12851.                m,
  12852.                "",
  12853.                "",                      /* addtl string data */
  12854.                nfsekwtab,               /* addtl numeric data 1: table size */
  12855.                0,                       /* addtl numeric data 2: 4 = cmswi */
  12856.                xxstring,                /* Processing function */
  12857.                fsekwtab,                /* Keyword table */
  12858.                &nu                      /* Pointer to next FDB */
  12859.                );
  12860.         cmfdbi(&nu,                     /* Byte or line number */
  12861.                _CMNUW,                  /* fcode */
  12862.                "",
  12863.                "",                      /* default */
  12864.                "",                      /* addtl string data */
  12865.                10,                      /* addtl numeric data 1: radix */
  12866.                0,                       /* addtl numeric data 2: 0 */
  12867.                xxstring,                /* Processing function */
  12868.                NULL,                    /* Keyword table */
  12869.                NULL                     /* Pointer to next FDB */
  12870.                );
  12871.         x = cmfdb(&sw);                 /* Parse something */
  12872.         if (x < 0) {
  12873.             if (x == -3) {
  12874.                 printf("?Channel number or EOF required\n");
  12875.                 x = -9;
  12876.             }
  12877.             return(x);
  12878.         }
  12879.         if (cmresult.fcode == _CMNUW) {
  12880.             z = cmresult.wresult;
  12881.             debug(F110,"FILE SEEK atmbuf",atmbuf,0);
  12882.             if (relative < 0) {
  12883.                 if (cx == FIL_SEE && (atmbuf[0] == '+' || atmbuf[0] == '-'))
  12884.                   relative = 1;
  12885.                 else
  12886.                   relative = 0;
  12887.             }
  12888.         } else if (cmresult.fcode == _CMKEY) {
  12889.             eofflg = cmresult.nresult;
  12890.             relative = 0;
  12891.             y = 0 - eofflg;
  12892.         }
  12893.         if ((x = cmcfm()) < 0)
  12894.           return(x);
  12895.     if (n == -9) return(success = 0);
  12896.     if (n == -8) return(success = 1);
  12897.         y = 1;                          /* Recycle this */
  12898.         z_flush(n);
  12899.         debug(F101,"FILE SEEK relative","",relative);
  12900.         debug(F101,"FILE SEEK rsize","",rsize);
  12901.  
  12902.         if (rsize == RD_CHAR) {         /* Seek to byte position */
  12903.             if (relative > 0) {
  12904.                 CK_OFF_T pos;
  12905.                 pos = z_getpos(n);
  12906.                 if (pos < (CK_OFF_T)0) {
  12907.                     rc = pos;
  12908.                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
  12909.                     return(-9);
  12910.                 }
  12911.                 z += pos;
  12912.             } else {
  12913.                 if (z < 0 && !eofflg) { /* Negative arg but not relative */
  12914.                     y = 0;              /* Remember this was bad */
  12915.                     z = 0;              /* but substitute 0 */
  12916.                 }
  12917.             }
  12918.             debug(F101,"FILE SEEK /CHAR z","",z);
  12919.             if (z < 0 && !eofflg) {
  12920.                 z_error = FX_RNG;
  12921.                 return(success = 0);
  12922.             }
  12923.             if ((rc = z_seek(n,z)) < 0) {
  12924.                 if (rc == FX_EOF) return(success = 0);
  12925.                 printf("?SEEK /BYTE failed - Channel %d: %s\n",n,ckferror(rc));
  12926.                 return(-9);
  12927.             }
  12928.         } else {                        /* Seek to line */
  12929.             if (relative > 0) {
  12930.                 CK_OFF_T pos;
  12931.                 pos = z_getline(n);
  12932.                 debug(F101,"FILE SEEK /LINE pos","",pos);
  12933.                 if (pos < 0) {
  12934.                     rc = pos;
  12935.                     printf("?Relative SEEK failed: %s\n",ckferror(rc));
  12936.                     return(-9);
  12937.                 }
  12938.                 z += pos;
  12939.             }
  12940.             debug(F101,"FILE SEEK /LINE z","",z);
  12941.             debug(F101,"FILE SEEK /LINE eofflg","",eofflg);
  12942.             if (z < 0 && !eofflg) {
  12943.                 z_error = FX_RNG;
  12944.                 return(success = 0);
  12945.             }
  12946.             if ((rc = z_line(n,z)) < 0) {
  12947.                 if (rc == FX_EOF) return(success = 0);
  12948.                 printf("?SEEK /LINE failed - Channel %d: %s\n",n,ckferror(rc));
  12949.                 return(-9);
  12950.             }
  12951.         }
  12952.     /*
  12953.       Now, having sought to the desired starting spot, if a /FIND:
  12954.       target was specified, look for it now.
  12955.     */
  12956.     if (seek_target) {
  12957.         int flag = 0, ispat = 0, matchresult = 0;
  12958.         while (!flag) {
  12959.         y = z_in(n,line,LINBUFSIZ,LINBUFSIZ-1,0);
  12960.         if (y < 0) {
  12961.             y = 0;
  12962.             break;
  12963.         }
  12964.         if (ispattern(seek_target)) {
  12965.             matchresult = ckmatch(seek_target,line,inpcas[cmdlvl],1+4);
  12966.         } else {
  12967.             /* This is faster */
  12968.             matchresult = ckindex(seek_target,line,0,0,inpcas[cmdlvl]);
  12969.         }
  12970.         if (matchresult) {
  12971.             flag = 1;
  12972.             break;
  12973.         }
  12974.         }
  12975.         if (flag) {
  12976.         debug(F111,"FSEEK HAVE MATCH",seek_target,z_getline(n));
  12977.         /* Back up to beginning of line where target found */
  12978.         if ((y = z_line(n,z_getline(n)-1)) < 0) {
  12979.             if (rc == FX_EOF) return(success = 0);
  12980.             printf("?SEEK /LINE failed - Channel %d: %s\n",
  12981.                n,ckferror(rc));
  12982.             return(-9);
  12983.         }
  12984.         debug(F101,"FSEEK LINE","",y);
  12985.         }
  12986.     }
  12987.         return(success = (y < 0) ? 0 : 1);
  12988.  
  12989.       case FIL_LIS: {                   /* LIST open files */
  12990. #ifdef CK_TTGWSIZ
  12991.           extern int cmd_rows, cmd_cols;
  12992. #endif /* CK_TTGWSIZ */
  12993.           extern int xaskmore;
  12994.           int i, x, n = 0, paging = 0;
  12995.           char * s;
  12996.  
  12997.           if ((x = cmcfm()) < 0)
  12998.             return(x);
  12999.  
  13000. #ifdef CK_TTGWSIZ
  13001.           if (cmd_rows > 0 && cmd_cols > 0)
  13002. #endif /* CK_TTGWSIZ */
  13003.             paging = xaskmore;
  13004.  
  13005.           printf("System open file limit:%5d\n", z_openmax);
  13006.           printf("Maximum for FILE OPEN: %5d\n", z_maxchan);
  13007.           printf("Files currently open:  %5d\n\n", z_nopen);
  13008.           n = 4;
  13009.           for (i = 0; i < z_maxchan; i++) {
  13010.               s = z_getname(i);         /* Got one? */
  13011.               if (s) {                  /* Yes */
  13012.                   char m[8];
  13013.                   m[0] = NUL;
  13014.                   printf("%2d. %s",i,s); /* Print name */
  13015.                   n++;                   /* Count it */
  13016.                   x = z_getmode(i);      /* Get modes & print them */
  13017.                   if (x > 0) {
  13018.                       if (x & FM_REA) ckstrncat(m,"R",8);
  13019.                       if (x & FM_WRI) ckstrncat(m,"W",8);
  13020.                       if (x & FM_APP) ckstrncat(m,"A",8);
  13021.                       if (x & FM_BIN) ckstrncat(m,"B",8);
  13022.                       if (m[0])
  13023.                         printf(" (%s)",m);
  13024.                       if (x & FM_EOF)
  13025.                         printf(" [EOF]");
  13026.                       else        /* And file position too */
  13027.                         printf(" %s",ckfstoa(z_getpos(i)));
  13028.                   }
  13029.                   printf("\n");
  13030. #ifdef CK_TTGWSIZ
  13031.                   if (paging > 0) {     /* Pause at end of screen */
  13032.                       if (n > cmd_rows - 3) {
  13033.                           if (!askmore())
  13034.                             break;
  13035.                           else
  13036.                             n = 0;
  13037.                       }
  13038.                   }
  13039. #endif /* CK_TTGWSIZ */
  13040.               }
  13041.           }
  13042.           return(success = 1);
  13043.       }
  13044.  
  13045.       case FIL_FLU:                     /* FLUSH */
  13046.         if ((x = cmnum("Channel number","",10,&n, xxstring)) < 0) {
  13047.             if (x == -3) {
  13048.                 printf("?Channel number required\n");
  13049.                 x = -9;
  13050.             }
  13051.             return(x);
  13052.         }
  13053.         if ((x = cmcfm()) < 0)
  13054.           return(x);
  13055.     if (n == -9) return(success = 0);
  13056.     if (n == -8) return(success = 1);
  13057.         if ((rc = z_flush(n)) < 0) {
  13058.             printf("?FLUSH failed - Channel %d: %s\n",n,ckferror(rc));
  13059.             return(-9);
  13060.         }
  13061.         return(success = 1);
  13062.  
  13063.       case FIL_STA:                     /* STATUS */
  13064.     {
  13065.         int i, j, k;        /* Supply default if only one open */
  13066.         s = "";
  13067.         for (k = 0, j = 0, i = 0; i < z_maxchan; i++) {
  13068.         if (z_file)
  13069.           if (z_file[i])
  13070.             if (z_file[i]->z_fp) { k++; j = i; }
  13071.         }
  13072.         if (k == 1) s = ckitoa(j);
  13073.     }
  13074.         if ((x = cmnum("Channel number",s,10,&n, xxstring)) < 0) {
  13075.             if (x == -3) {
  13076.         if (z_nopen > 1) {
  13077.             printf("?%d files open - please supply channel number\n",
  13078.                z_nopen);
  13079.             return(-9);
  13080.         }
  13081.             } else
  13082.           return(x);
  13083.         }
  13084.         if ((y = cmcfm()) < 0)
  13085.           return(y);
  13086.     if ((!z_file || z_nopen == 0) && x == -3) {
  13087.         printf("No files open\n");
  13088.         return(success = 1);
  13089.     }
  13090.         p = blanks + 3;                 /* Tricky formatting... */
  13091.         if (n < 1000) p--;
  13092.         if (n < 100) p--;
  13093.         if (n < 10) p--;
  13094.         if ((rc = z_getmode(n)) < 0) {
  13095.             printf("Channel %d:%s%s\n",n,p,ckferror(rc));
  13096.             return(success = 0);
  13097.         } else if (!rc) {
  13098.             printf("Channel %d:%sNot open\n",n,p);
  13099.             return(success = 0);
  13100.         } else {
  13101.             CK_OFF_T xx;
  13102.             s = z_getname(n);
  13103.             if (!s) s = "(name unknown)";
  13104.             printf("Channel %d:%sOpen\n",n,p);
  13105.             printf(" File:        %s\n Modes:      ",s);
  13106.             if (rc & FM_REA) printf(" /READ");
  13107.             if (rc & FM_WRI) printf(" /WRITE");
  13108.             if (rc & FM_APP) printf(" /APPEND");
  13109.             if (rc & FM_BIN) printf(" /BINARY");
  13110.             if (rc & FM_CMD) printf(" /COMMAND");
  13111.             if (rc & FM_EOF) printf(" [EOF]");
  13112.             printf("\n Size:        %s\n",ckfstoa(z_count(n,RD_CHAR)));
  13113.             printf(" At byte:     %s\n",ckfstoa(z_getpos(n)));
  13114.             xx = z_getline(n);
  13115.             if (xx > (CK_OFF_T)-1)
  13116.               printf(" At line:     %s\n",ckfstoa(xx));
  13117.             return(success = 1);
  13118.         }
  13119.       default:
  13120.         return(-2);
  13121.     }
  13122. }
  13123. #endif /* CKCHANNELIO */
  13124.  
  13125. #ifndef NOSETKEY
  13126. /* Save Key maps and in OS/2 Mouse maps */
  13127. int
  13128. savkeys(name,disp) char * name; int disp; {
  13129.     char *tp;
  13130.     static struct filinfo xx;
  13131.     int savfil, i, j, k;
  13132.     char buf[1024];
  13133.  
  13134.     zclose(ZMFILE);
  13135.  
  13136.     if (disp) {
  13137.         xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
  13138.         xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
  13139.         xx.lblopts = 0;
  13140.         savfil = zopeno(ZMFILE,name,NULL,&xx);
  13141.     } else savfil = zopeno(ZMFILE,name,NULL,NULL);
  13142.  
  13143.     if (savfil) {
  13144. #ifdef OS2
  13145.         ztime(&tp);
  13146.         zsout(ZMFILE, "; Kermit 95 SAVE KEYMAP file: ");
  13147.         zsoutl(ZMFILE,tp);
  13148.         if (mskkeys) {
  13149.             zsoutl(ZMFILE,
  13150.          "if eq \"\\v(program)\" \"C-Kermit\" set mskermit keycodes on");
  13151.         } else {
  13152.             zsoutl(ZMFILE,
  13153.          "if NOT eq \"\\v(program)\" \"C-Kermit\" stop 1 C-Kermit required.");
  13154.             zsoutl(ZMFILE,"set mskermit keycodes off");
  13155.         }
  13156.         zsoutl(ZMFILE,"");
  13157. #else /* OS2 */
  13158.         ztime(&tp);
  13159.         zsout(ZMFILE, "; C-Kermit SAVE KEYMAP file: ");
  13160.         zsoutl(ZMFILE,tp);
  13161. #endif /* OS2 */
  13162.  
  13163.         zsoutl(ZMFILE,"; Clear previous keyboard mappings ");
  13164.         zsoutl(ZMFILE,"set key clear");
  13165. #ifdef OS2
  13166.         for (k = 0; k < nttkey; k++) {
  13167.             if (!ttkeytab[k].flgs) {
  13168.                 ckmakmsg(buf,1024,
  13169.                          "set terminal key ",
  13170.                          ttkeytab[k].kwd,
  13171.                          " clear",
  13172.                          NULL
  13173.                          );
  13174.                 zsoutl(ZMFILE,buf);
  13175.             }
  13176.         }
  13177. #endif /* OS2 */
  13178.         zsoutl(ZMFILE,"");
  13179.  
  13180.         for (i = 0; i < KMSIZE; i++) {
  13181.             if (macrotab[i]) {
  13182.                 int len = strlen((char *)macrotab[i]);
  13183. #ifdef OS2
  13184.                 ckmakmsg(buf,
  13185.                          1024,
  13186.                          "set key \\",
  13187.                          ckitoa(mskkeys ? cktomsk(i) : i),
  13188.                          " ",
  13189.                          NULL
  13190.                          );
  13191. #else /* OS2 */
  13192.                 ckmakmsg(buf,
  13193.                          1024,
  13194.                          "set key \\",
  13195.                          ckitoa(i),
  13196.                          NULL,NULL
  13197.                          );
  13198. #endif /* OS2 */
  13199.                 zsout(ZMFILE,buf);
  13200.  
  13201.                 for (j = 0; j < len; j++) {
  13202.                     char ch = macrotab[i][j];
  13203.                     if (ch <= SP || ch >= DEL ||
  13204.                          ch == '-' || ch == ',' ||
  13205.                          ch == '{' || ch == '}' ||
  13206.                          ch == ';' || ch == '?' ||
  13207.                          ch == '.' || ch == '\'' ||
  13208.                          ch == '\\' || ch == '/' ||
  13209.                          ch == '#') {
  13210.                         ckmakmsg(buf,1024,"\\{",ckitoa((int)ch),"}",NULL);
  13211.                         zsout(ZMFILE,buf);
  13212.                     } else {
  13213.                         ckmakmsg(buf,1024,ckctoa((char)ch),NULL,NULL,NULL);
  13214.                         zsout(ZMFILE,buf);
  13215.                     }
  13216.                 }
  13217. #ifdef OS2
  13218.                 ckmakmsg(buf,1024,"\t; ",keyname(i),NULL,NULL);
  13219.                 zsoutl(ZMFILE,buf);
  13220. #else
  13221.                 zsoutl(ZMFILE,"");
  13222. #endif /* OS2 */
  13223.             } else if ( keymap[i] != i ) {
  13224. #ifndef NOKVERBS
  13225.                 if (IS_KVERB(keymap[i])) {
  13226.                     for (j = 0; j < nkverbs; j++)
  13227.                       if (kverbs[j].kwval == (keymap[i] & ~F_KVERB))
  13228.                         break;
  13229.                     if (j != nkverbs) {
  13230. #ifdef OS2
  13231. #ifdef COMMENT
  13232.                         sprintf(buf, "set key \\%d \\K%s\t; %s",
  13233.                                 mskkeys ? cktomsk(i) : i,
  13234.                                 kverbs[j].kwd, keyname(i)
  13235.                                 );
  13236. #else
  13237.                         ckmakxmsg(buf,  /* 12 string args */
  13238.                                   1024,
  13239.                                   "set key \\",
  13240.                                   ckitoa(mskkeys ? cktomsk(i) : i),
  13241.                                   " \\K",
  13242.                                   kverbs[j].kwd,
  13243.                                   "\t; ",
  13244.                                   keyname(i),
  13245.                                   NULL, NULL, NULL, NULL, NULL, NULL);
  13246. #endif /* COMMENT */
  13247.                         zsoutl(ZMFILE,buf);
  13248. #else
  13249. #ifdef COMMENT
  13250.                         sprintf(buf, "set key \\%d \\K%s", i, kverbs[j].kwd);
  13251. #else
  13252.                         ckmakmsg(buf,1024,
  13253.                                  "set key \\",
  13254.                                  ckitoa(i),
  13255.                                  " \\K",
  13256.                                  kverbs[j].kwd
  13257.                                  );
  13258. #endif /* COMMENT */
  13259.                         zsoutl(ZMFILE,buf);
  13260. #endif
  13261.                     }
  13262.                 } else
  13263. #endif /* NOKVERBS */
  13264.                   {
  13265. #ifdef OS2
  13266. #ifdef COMMENT
  13267.                       sprintf(buf, "set key \\%d \\{%d}\t; %s",
  13268.                               mskkeys ? cktomsk(i) : i,
  13269.                               keymap[i],
  13270.                               keyname(i)
  13271.                               );
  13272. #else
  13273.                       ckmakxmsg(buf,    /* 8 string args */
  13274.                                 1024,
  13275.                                 "set key \\",
  13276.                                 ckitoa(mskkeys ? cktomsk(i) : i),
  13277.                                 " \\{",
  13278.                                 ckitoa(keymap[i]),
  13279.                                 "}\t; ",
  13280.                                 keyname(i),
  13281.                                 NULL,NULL,NULL,NULL,NULL,NULL);
  13282. #endif /* COMMENT */
  13283.                       zsoutl(ZMFILE,buf);
  13284. #else
  13285. #ifdef COMMENT
  13286.                       sprintf(buf, "set key \\%d \\{%d}", i, keymap[i]);
  13287. #else
  13288.                       ckmakxmsg(buf,1024,
  13289.                                "set key \\",
  13290.                                ckitoa(i),
  13291.                                " \\{",
  13292.                                ckitoa(keymap[i]),
  13293.                                "}",
  13294.                                NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  13295. #endif /* COMMENT */
  13296.                       zsoutl(ZMFILE,buf);
  13297. #endif /* OS2 */
  13298.                   }
  13299.             }
  13300.         }
  13301. #ifdef OS2
  13302.         /* OS/2 also has the SET TERMINAL KEY <termtype> defines */
  13303.         for (k = 0; k < nttkey; k++) {
  13304.             extern struct keynode * ttkeymap[];
  13305.             struct keynode * pnode = NULL;
  13306.  
  13307.             if (ttkeytab[k].flgs)       /* Don't process CM_INV or CM_ABR */
  13308.               continue;
  13309.  
  13310.             zsoutl(ZMFILE,"");
  13311.             ckmakmsg(buf,1024,"; SET TERMINAL KEY ",ttkeytab[k].kwd,NULL,NULL);
  13312.             zsoutl(ZMFILE,buf);
  13313.  
  13314.             for (pnode = ttkeymap[ttkeytab[k].kwval];
  13315.                  pnode;
  13316.                  pnode = pnode->next
  13317.                  ) {
  13318.                 switch (pnode->def.type) {
  13319.                   case key:
  13320. #ifdef COMMENT
  13321.                     sprintf(buf, "set terminal key %s \\%d \\{%d}\t; %s",
  13322.                             ttkeytab[k].kwd,
  13323.                             mskkeys ? cktomsk(pnode->key) : pnode->key,
  13324.                             pnode->def.key.scancode,
  13325.                             keyname(pnode->key)
  13326.                             );
  13327. #else
  13328.                     ckmakxmsg(buf,
  13329.                               1024,
  13330.                               "set terminal key ",
  13331.                               ttkeytab[k].kwd,
  13332.                               " \\",
  13333.                               ckitoa(mskkeys ?
  13334.                                      cktomsk(pnode->key) :
  13335.                                      pnode->key),
  13336.                               " \\{",
  13337.                               ckitoa(pnode->def.key.scancode),
  13338.                               "}\t; ",
  13339.                               keyname(pnode->key),
  13340.                               NULL,NULL,NULL,NULL
  13341.                               );
  13342. #endif /* COMMENT */
  13343.                     zsoutl(ZMFILE,buf);
  13344.                     break;
  13345.                   case kverb:
  13346.                     for (j = 0; j < nkverbs; j++)
  13347.                       if (kverbs[j].kwval == (pnode->def.kverb.id & ~F_KVERB))
  13348.                         break;
  13349.                     if (j != nkverbs) {
  13350. #ifdef COMMENT
  13351.                         sprintf(buf, "set terminal key %s \\%d \\K%s\t; %s",
  13352.                                 ttkeytab[k].kwd,
  13353.                                 mskkeys ? cktomsk(pnode->key) : pnode->key,
  13354.                                 kverbs[j].kwd, keyname(pnode->key)
  13355.                                 );
  13356. #else
  13357.                         ckmakxmsg(buf,
  13358.                                   1024,
  13359.                                   "set terminal key ",
  13360.                                   ttkeytab[k].kwd,
  13361.                                   " \\",
  13362.                                   ckitoa(mskkeys ?
  13363.                                          cktomsk(pnode->key) :
  13364.                                          pnode->key),
  13365.                                   " \\K",
  13366.                                   kverbs[j].kwd,
  13367.                                   "\t; ",
  13368.                                   keyname(pnode->key),
  13369.                                   NULL,NULL,NULL,NULL
  13370.                                   );
  13371. #endif /* COMMENT */
  13372.                         zsoutl(ZMFILE,buf);
  13373.                     }
  13374.                     break;
  13375.                   case macro: {
  13376.                       int len = strlen((char *)pnode->def.macro.string);
  13377. #ifdef COMMENT
  13378.                       sprintf(buf,"set terminal key %s \\%d ",
  13379.                               ttkeytab[k].kwd,
  13380.                               mskkeys ? cktomsk(pnode->key) : pnode->key);
  13381. #else
  13382.                       ckmakxmsg(buf,
  13383.                                1024,
  13384.                                "set terminal key ",
  13385.                                ttkeytab[k].kwd,
  13386.                                " \\",
  13387.                                ckitoa(mskkeys ?
  13388.                                       cktomsk(pnode->key) :
  13389.                                       pnode->key),
  13390.                                " ",
  13391.                                NULL,NULL,NULL,NULL,NULL,NULL,NULL
  13392.                               );
  13393. #endif /* COMMENT */
  13394.                       zsout(ZMFILE,buf);
  13395.  
  13396.                       for (j = 0; j < len; j++) {
  13397.                           char ch = pnode->def.macro.string[j];
  13398.                           if (ch <= SP || ch >= DEL ||
  13399.                                ch == '-' || ch == ',' ||
  13400.                                ch == '{' || ch == '}' ||
  13401.                                ch == ';' || ch == '?' ||
  13402.                                ch == '.' || ch == '\'' ||
  13403.                                ch == '\\' || ch == '/' ||
  13404.                                ch == '#') {
  13405.                               ckmakmsg(buf,1024,
  13406.                                        "\\{",ckitoa((int)ch),"}",NULL);
  13407.                               zsout(ZMFILE,buf);
  13408.                           } else {
  13409.                               ckmakmsg(buf,1024,
  13410.                                        ckctoa((char)ch),NULL,NULL,NULL);
  13411.                               zsout(ZMFILE,buf);
  13412.                           }
  13413.                       }
  13414.                       ckmakmsg(buf,1024,"\t; ",keyname(pnode->key),NULL,NULL);
  13415.                       zsoutl(ZMFILE,buf);
  13416.                       break;
  13417.                   }
  13418.                   case literal: {
  13419.                       int len = strlen((char *)pnode->def.literal.string);
  13420. #ifdef COMMENT
  13421.                       sprintf(buf,"set terminal key %s /literal \\%d ",
  13422.                               ttkeytab[k].kwd,
  13423.                               mskkeys ? cktomsk(pnode->key) : pnode->key);
  13424. #else
  13425.                       ckmakxmsg(buf,
  13426.                                1024,
  13427.                                "set terminal key ",
  13428.                                ttkeytab[k].kwd,
  13429.                                " /literal \\",
  13430.                                ckitoa(mskkeys ?
  13431.                                       cktomsk(pnode->key) :
  13432.                                       pnode->key),
  13433.                                " ",
  13434.                                NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  13435. #endif /* COMMENT */
  13436.                       zsout(ZMFILE,buf);
  13437.  
  13438.                       for (j = 0; j < len; j++) {
  13439.                           char ch = pnode->def.literal.string[j];
  13440.                           if (ch <= SP || ch >= DEL ||
  13441.                                ch == '-' || ch == ',' ||
  13442.                                ch == '{' || ch == '}' ||
  13443.                                ch == ';' || ch == '?' ||
  13444.                                ch == '.' || ch == '\'' ||
  13445.                                ch == '\\' || ch == '/' ||
  13446.                                ch == '#') {
  13447.                               ckmakmsg(buf,1024,
  13448.                                        "\\{",ckitoa((int)ch),"}",NULL);
  13449.                               zsout(ZMFILE,buf);
  13450.                           } else {
  13451.                               ckmakmsg(buf,1024,
  13452.                                        ckctoa((char)ch),NULL,NULL,NULL);
  13453.                               zsout(ZMFILE,buf);
  13454.                           }
  13455.                       }
  13456.                       ckmakmsg(buf,1024,"\t; ",keyname(pnode->key),NULL,NULL);
  13457.                       zsoutl(ZMFILE,buf);
  13458.                       break;
  13459.                   }
  13460.                   case esc:
  13461. #ifdef COMMENT
  13462.                     sprintf(buf,
  13463.                        "set terminal key %s /literal \\%d \\{%d}\\{%d}\t; %s",
  13464.                             ttkeytab[k].kwd,
  13465.                             mskkeys ? cktomsk(pnode->key) : pnode->key,
  13466.                             ISDG200(ttkeytab[k].kwval) ? 30 : 27,
  13467.                             pnode->def.esc.key & ~F_ESC,
  13468.                             keyname(pnode->key)
  13469.                             );
  13470. #else
  13471.                     ckmakxmsg(buf,
  13472.                               1024,
  13473.                               "set terminal key ",
  13474.                               ttkeytab[k].kwd,
  13475.                               " /literal \\",
  13476.                               ckitoa(mskkeys ?
  13477.                                      cktomsk(pnode->key) :
  13478.                                      pnode->key),
  13479.                               " \\{",
  13480.                               ckitoa(ISDG200(ttkeytab[k].kwval) ? 30 : 27),
  13481.                               "}\\{",
  13482.                               ckitoa(pnode->def.esc.key & ~F_ESC),
  13483.                               "}\t; ",
  13484.                               keyname(pnode->key),
  13485.                               NULL,NULL
  13486.                               );
  13487. #endif /* COMMENT */
  13488.                     zsoutl(ZMFILE,buf);
  13489.                     break;
  13490.                   case csi:
  13491. #ifdef COMMENT
  13492.                     sprintf(buf,
  13493.                        "set terminal key %s /literal \\%d \\{27}[\\{%d}\t; %s",
  13494.                             ttkeytab[k].kwd,
  13495.                             mskkeys ? cktomsk(pnode->key) : pnode->key,
  13496.                             pnode->def.csi.key & ~F_CSI,
  13497.                             keyname(pnode->key)
  13498.                             );
  13499. #else
  13500.                     ckmakxmsg(buf,
  13501.                               1024,
  13502.                               "set terminal key ",
  13503.                               ttkeytab[k].kwd,
  13504.                               " /literal \\",
  13505.                               ckitoa(mskkeys ?
  13506.                                      cktomsk(pnode->key) :
  13507.                                      pnode->key),
  13508.                               " \\{27}[\\{",
  13509.                               ckitoa(pnode->def.csi.key & ~F_CSI),
  13510.                               "}\t; ",
  13511.                               keyname(pnode->key),
  13512.                               NULL,NULL,NULL,NULL
  13513.                               );
  13514. #endif /* COMMENT */
  13515.                     zsoutl(ZMFILE,buf);
  13516.                     break;
  13517.                   default:
  13518.                     continue;
  13519.                 }
  13520.             }
  13521.         }
  13522. #endif /* OS2 */
  13523.  
  13524.         zsoutl(ZMFILE,"");
  13525.         zsoutl(ZMFILE,"; End");
  13526.         zclose(ZMFILE);
  13527.         return(success = 1);
  13528.     } else {
  13529.         return(success = 0);
  13530.     }
  13531. }
  13532. #endif /* NOSETKEY */
  13533.  
  13534. #define SV_SCRL 0
  13535. #define SV_HIST 1
  13536.  
  13537. #ifdef OS2
  13538. #ifndef NOLOCAL
  13539. static struct keytab trmtrmopt[] = {
  13540.     { "scrollback", SV_SCRL, 0 }
  13541. };
  13542. #endif /* NOLOCAL */
  13543. #endif /* OS2 */
  13544.  
  13545. static struct keytab cmdtrmopt[] = {
  13546. #ifdef CK_RECALL
  13547.     { "history",    SV_HIST, 0 },
  13548. #endif /* CK_RECALL */
  13549. #ifdef OS2
  13550. #ifndef NOLOCAL
  13551.     { "scrollback", SV_SCRL, 0 },
  13552. #endif /* NOLOCAL */
  13553. #endif /* OS2 */
  13554.     { "", 0, 0 }
  13555. };
  13556. static int ncmdtrmopt = (sizeof (cmdtrmopt) / sizeof (struct keytab)) - 1;
  13557.  
  13558. #ifdef OS2
  13559. #ifndef NOLOCAL
  13560. _PROTOTYP(int savscrbk, (int, char *, int));
  13561. #endif /* NOLOCAL */
  13562. #endif /* OS2 */
  13563.  
  13564. #ifdef CK_RECALL
  13565. _PROTOTYP(int savhistory, (char *, int));
  13566. #endif /* CK_RECALL */
  13567.  
  13568. int
  13569. dosave(xx) int xx; {
  13570.     int x, y = 0, disp;
  13571.     char * s = NULL;
  13572.     extern struct keytab disptb[];
  13573. #ifdef ZFNQFP
  13574.     struct zfnfp * fnp;
  13575. #endif /* ZFNQFP */
  13576.  
  13577. #ifndef NOSETKEY
  13578.     if (xx == XSKEY) {                  /* SAVE KEYMAP.. */
  13579.         z = cmofi("Name of Kermit command file","keymap.ksc",&s,xxstring);
  13580.     } else {
  13581. #endif /* NOSETKEY */
  13582.         switch (xx) {
  13583.           case XSCMD:                   /* SAVE COMMAND.. */
  13584.             if ((y = cmkey(cmdtrmopt, ncmdtrmopt, "What to save",
  13585. #ifdef OS2
  13586.                            "scrollback",
  13587. #else
  13588.                            "history",
  13589. #endif /* OS2 */
  13590.                            xxstring)) < 0)
  13591.               return(y);
  13592.             break;
  13593. #ifdef OS2
  13594. #ifndef NOLOCAL
  13595.           case XSTERM:                  /* SAVE TERMINAL.. */
  13596.             if ((y = cmkey(trmtrmopt,1,
  13597.                            "What to save","scrollback",xxstring)) < 0)
  13598.               return(y);
  13599.             break;
  13600. #endif /* NOLOCAL */
  13601. #endif /* OS2 */
  13602.         }
  13603.         z = cmofi("Filename",
  13604.                   ((y == SV_SCRL) ? "scrollbk.txt" : "history.txt"),
  13605.                   &s,
  13606.                   xxstring
  13607.                   );
  13608. #ifndef NOSETKEY
  13609.     }
  13610. #endif /* NOSETKEY */
  13611.     if (z < 0)                          /* Check output-file parse results */
  13612.       return(z);
  13613.     if (z == 2) {
  13614.         printf("?Sorry, %s is a directory name\n",s);
  13615.         return(-9);
  13616.     }
  13617. #ifdef ZFNQFP
  13618.     if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {/* Convert to full pathname */
  13619.         if (fnp->fpath)
  13620.           if ((int) strlen(fnp->fpath) > 0)
  13621.             s = fnp->fpath;
  13622.     }
  13623. #endif /* ZFNQFP */
  13624.  
  13625.     ckstrncpy(line,s,LINBUFSIZ);        /* Make safe copy of pathname */
  13626.     s = line;
  13627. #ifdef MAC
  13628.     z = 0;
  13629. #else
  13630.     /* Get NEW/APPEND disposition */
  13631.     if ((z = cmkey(disptb,2,"Disposition","new",xxstring)) < 0)
  13632.       return(z);
  13633. #endif /* MAC */
  13634.     disp = z;
  13635.     if ((x = cmcfm()) < 0)              /* Get confirmation */
  13636.       return(x);
  13637.  
  13638.     switch (xx) {                       /* Do action.. */
  13639. #ifndef NOSETKEY
  13640.       case XSKEY:                       /* SAVE KEYMAP */
  13641.         return (savkeys(s,disp));
  13642. #endif /* NOSETKEY */
  13643.  
  13644.       case XSCMD:                       /* SAVE COMMAND.. */
  13645. #ifdef OS2
  13646. #ifndef NOLOCAL
  13647.         if (y == SV_SCRL)               /* .. SCROLLBACK */
  13648.           return(success = savscrbk(VCMD,s,disp));
  13649. #endif /* NOLOCAL */
  13650. #endif /* OS2 */
  13651. #ifndef NORECALL
  13652.         if (y == SV_HIST)               /* .. HISTORY */
  13653.           return(success = savhistory(s,disp));
  13654. #endif /* NORECALL */
  13655.         break;
  13656.  
  13657. #ifdef OS2
  13658. #ifndef NOLOCAL
  13659.       case XSTERM:                      /* SAVE TERMINAL SCROLLBACK */
  13660.         return(success = savscrbk(VTERM,s,disp));
  13661. #endif /* NOLOCAL */
  13662. #endif /* OS2 */
  13663.     }
  13664.     success = 0;
  13665.     return(-2);
  13666. }
  13667.  
  13668. /*
  13669.   R E A D T E X T
  13670.  
  13671.   Read text with a custom prompt into given buffer using command parser but
  13672.   with no echoing or entry into recall buffer.
  13673. */
  13674. int
  13675. readtext(prmpt, buffer, bufsiz) char * prmpt; char * buffer; int bufsiz; {
  13676. #ifdef CK_RECALL
  13677.     extern int on_recall;               /* Around Password prompting */
  13678. #endif /* CK_RECALL */
  13679.     int rc;
  13680. #ifndef NOLOCAL
  13681. #ifdef OS2
  13682.     extern int vmode;
  13683.     extern int startflags;
  13684.     int vmode_sav = vmode;
  13685.  
  13686.     if (!prmpt) prmpt = "";
  13687.  
  13688.     if (win95_popup && !(startflags & 96)
  13689. #ifdef IKSD
  13690.          && !inserver
  13691. #endif /* IKSD */
  13692.          )
  13693.       return(popup_readtext(vmode,NULL,prmpt,buffer,bufsiz,0));
  13694.  
  13695.     if (vmode == VTERM) {
  13696.         vmode = VCMD;
  13697.         VscrnIsDirty(VTERM);
  13698.         VscrnIsDirty(VCMD);
  13699.     }
  13700. #endif /* OS2 */
  13701. #endif /* NOLOCAL */
  13702.  
  13703. #ifdef CK_RECALL
  13704.     on_recall = 0;
  13705. #endif /* CK_RECALL */
  13706.     cmsavp(psave,PROMPTL);              /* Save old prompt */
  13707.     cmsetp(prmpt);                      /* Make new prompt */
  13708.     concb((char)escape);                /* Put console in cbreak mode */
  13709.     cmini(1);                           /* and echo mode */
  13710.     if (pflag) prompt(xxstring);        /* Issue prompt if at top level */
  13711.     cmres();                            /* Reset the parser */
  13712.     for (rc = -1; rc < 0; ) {           /* Prompt till they answer */
  13713.         rc = cmtxt("","",&s,NULL);      /* Get a literal line of text */
  13714.         cmres();                        /* Reset the parser again */
  13715.     }
  13716.     ckstrncpy(buffer,s,bufsiz);
  13717.     cmsetp(psave);                      /* Restore original prompt */
  13718.  
  13719. #ifndef NOLOCAL
  13720. #ifdef OS2
  13721.     if (vmode != vmode_sav) {
  13722.         vmode = VTERM;
  13723.         VscrnIsDirty(VCMD);
  13724.         VscrnIsDirty(VTERM);
  13725.     }
  13726. #endif /* OS2 */
  13727. #endif /* NOLOCAL */
  13728.     return(0);
  13729. }
  13730. #endif /* NOICP */
  13731.  
  13732. /* A general function to allow a Password or other information  */
  13733. /* to be read from the command prompt without it going into     */
  13734. /* the recall buffer or being echo'd.                           */
  13735.  
  13736. int
  13737. readpass(prmpt, buffer, bufsiz) char * prmpt; char * buffer; int bufsiz; {
  13738.     int x;
  13739. #ifdef NOICP
  13740.     if (!prmpt) prmpt = "";
  13741.     printf("%s", prmpt);
  13742. #ifdef COMMENT
  13743.     /* Some linkers won't allow this because it's unsafe */
  13744.     gets(buffer);
  13745. #else  /* COMMENT */
  13746.     {
  13747.         int c, i; char * p;
  13748.         p = buffer;
  13749.         for (i = 0; i < bufsiz-1; i++) {
  13750.             if ((c = getchar()) == EOF)
  13751.               break;
  13752.             if (c < SP)
  13753.               break;
  13754.             buffer[i] = c;
  13755.         }
  13756.         buffer[i] = NUL;
  13757.     }
  13758. #endif /* COMMENT */
  13759.     return(1);
  13760. #else  /* NOICP */
  13761. #ifdef CK_RECALL
  13762.     extern int on_recall;               /* around Password prompting */
  13763. #endif /* CK_RECALL */
  13764.     int rc;
  13765. #ifndef NOLOCAL
  13766. #ifdef OS2
  13767.     extern int vmode;
  13768.     extern int startflags;
  13769.     int vmode_sav = vmode;
  13770. #endif /* OS2 */
  13771. #endif /* NOLOCAL */
  13772. #ifdef CKSYSLOG
  13773.     int savlog;
  13774. #endif /* CKSYSLOG */
  13775.     if (!prmpt) prmpt = "";
  13776. #ifndef NOLOCAL
  13777.     debok = 0;                          /* Don't log */
  13778. #ifdef OS2
  13779.     if (win95_popup && !(startflags & 96)
  13780. #ifdef IKSD
  13781.          && !inserver
  13782. #endif /* IKSD */
  13783.          ) {
  13784.         x = popup_readpass(vmode,NULL,prmpt,buffer,bufsiz,0);
  13785.         debok = 1;
  13786.         return(x);
  13787.     }
  13788. #endif /* OS2 */
  13789. #endif /* NOLOCAL */
  13790.  
  13791. #ifdef CKSYSLOG
  13792.     savlog = ckxsyslog;                 /* Save and turn off syslogging */
  13793.     ckxsyslog = 0;
  13794. #endif /* CKSYSLOG */
  13795. #ifndef NOLOCAL
  13796. #ifdef OS2
  13797.     if (vmode == VTERM) {
  13798.         vmode = VCMD;
  13799.         VscrnIsDirty(VTERM);
  13800.         VscrnIsDirty(VCMD);
  13801.     }
  13802. #endif /* OS2 */
  13803. #endif /* NOLOCAL */
  13804. #ifdef CK_RECALL
  13805.     on_recall = 0;
  13806. #endif /* CK_RECALL */
  13807.     cmsavp(psave,PROMPTL);              /* Save old prompt */
  13808.     cmsetp(prmpt);                      /* Make new prompt */
  13809.     concb((char)escape);                /* Put console in cbreak mode */
  13810.     cmini(0);                           /* and no-echo mode */
  13811.     if (pflag) prompt(xxstring);        /* Issue prompt if at top level */
  13812.     cmres();                            /* Reset the parser */
  13813.     for (rc = -1; rc < 0; ) {           /* Prompt till they answer */
  13814.         rc = cmtxt("","",&s,NULL);      /* Get a literal line of text */
  13815.         cmres();                        /* Reset the parser again */
  13816.     }
  13817.     ckstrncpy(buffer,s,bufsiz);
  13818.     printf("\r\n");                     /* Echo a CRLF */
  13819.     cmsetp(psave);                      /* Restore original prompt */
  13820.     cmini(1);                           /* Restore echo mode */
  13821. #ifndef NOLOCAL
  13822. #ifdef OS2
  13823.     if (vmode != vmode_sav) {
  13824.         vmode = VTERM;
  13825.         VscrnIsDirty(VCMD);
  13826.         VscrnIsDirty(VTERM);
  13827.     }
  13828. #endif /* OS2 */
  13829. #endif /* NOLOCAL */
  13830. #ifdef CKSYSLOG
  13831.     ckxsyslog = savlog;                 /* Restore syslogging */
  13832. #endif /* CKSYSLOG */
  13833.     debok = 1;
  13834.     return(0);
  13835. #endif /* NOICP */
  13836. }
  13837.  
  13838. #ifndef NOICP
  13839. struct keytab authtab[] = {             /* Available authentication types */
  13840. #ifdef CK_KERBEROS
  13841.     { "k4",        AUTH_KRB4, CM_INV },
  13842.     { "k5",        AUTH_KRB5, CM_INV },
  13843.     { "kerberos4", AUTH_KRB4, 0      },
  13844.     { "kerberos5", AUTH_KRB5, 0      },
  13845.     { "krb4",      AUTH_KRB4, CM_INV },
  13846.     { "krb5",      AUTH_KRB5, CM_INV },
  13847. #endif /* CK_KERBEROS */
  13848. #ifdef NT
  13849.     { "ntlm",      AUTH_NTLM, 0 },
  13850. #endif /* NT */
  13851. #ifdef CK_SRP
  13852.     { "srp",       AUTH_SRP,  0 },
  13853. #endif /* CK_SRP */
  13854. #ifdef CK_SSL
  13855.     { "ssl",       AUTH_SSL,  0 },
  13856. #endif /* CK_SSL */
  13857.     { "",          0,         0 }
  13858. };
  13859. int authtabn = sizeof(authtab)/sizeof(struct keytab)-1;
  13860.  
  13861. #ifdef CK_KERBEROS
  13862. struct keytab kerbtab[] = {             /* Kerberos authentication types */
  13863.     { "k4",        AUTH_KRB4, CM_INV },
  13864.     { "k5",        AUTH_KRB5, CM_INV },
  13865.     { "kerberos4", AUTH_KRB4, 0      },
  13866.     { "kerberos5", AUTH_KRB5, 0      },
  13867.     { "krb4",      AUTH_KRB4, CM_INV },
  13868.     { "krb5",      AUTH_KRB5, CM_INV }
  13869. };
  13870. int kerbtabn = sizeof(kerbtab)/sizeof(struct keytab);
  13871.  
  13872. static struct keytab krb_s_tbl[] = {    /* AUTHENTICATE command switches: */
  13873.     { "/cache",   KRB_S_CA, CM_ARG }
  13874. };
  13875. static int krb_s_n = sizeof(krb_s_tbl)/sizeof(struct keytab);
  13876.  
  13877. static struct keytab krb_v_tbl[] = {    /* KERBEROS version values: */
  13878.     { "4",    4, 0 },
  13879.     { "5",    5, 0 },                   /* (add others as needed...) */
  13880.     { "auto", 0, 0 }                    /* Note: 0 = auto */
  13881. };
  13882. static int krb_v_n = sizeof(krb_v_tbl)/sizeof(struct keytab);
  13883.  
  13884. static struct keytab krb_a_tbl[] = {    /* KERBEROS actions: */
  13885.     { "destroy",           KRB_A_DE, 0 },
  13886.     { "initialize",        KRB_A_IN, 0 },
  13887.     { "list-credentials",  KRB_A_LC, 0 }
  13888. };
  13889. static int krb_a_n = sizeof(krb_a_tbl)/sizeof(struct keytab);
  13890.  
  13891. static struct keytab krb4_i_tbl[] = {   /* KERBEROS 4 INITIALIZE switches: */
  13892.     { "/brief",            KRB_I_BR, 0 },      /* /BRIEF       */
  13893.     { "/instance",         KRB_I_IN, CM_ARG }, /* /INSTANCE:   */
  13894.     { "/lifetime",         KRB_I_LF, CM_ARG }, /* /LIFETIME:   */
  13895.     { "/not-preauth",      KRB_I_NPA, 0 },     /* /NOT-PREAUTH */
  13896.     { "/password",         KRB_I_PW, CM_ARG }, /* /PASSWORD:   */
  13897. #ifdef OS2
  13898.     { "/popup",            KRB_I_POP, 0 },     /* /POPUP       */
  13899. #endif /* OS2 */
  13900.     { "/preauth",          KRB_I_PA, 0 },      /* /PREAUTH     */
  13901.     { "/realm",            KRB_I_RL, CM_ARG }, /* /REALM:      */
  13902.     { "/verbose",          KRB_I_VB, 0 },      /* /VERBOSE     */
  13903.     { "", 0, 0 }
  13904. };
  13905. static int krb4_i_n = sizeof(krb4_i_tbl)/sizeof(struct keytab) - 1;
  13906.  
  13907. static struct keytab krb5_i_tbl[] = {   /* KERBEROS 5 INITIALIZE switches: */
  13908.     { "/addresses",        KRB_I_ADR, CM_ARG },
  13909.     { "/forwardable",      KRB_I_FW,  0 },         /* /FORWARDABLE */
  13910.     { "/instance",         KRB_I_IN, CM_ARG }, /* /INSTANCE:   */
  13911.     { "/k4",               KRB_I_K4,  CM_INV }, /* /KERBEROS4   */
  13912.     { "/kerberos4",        KRB_I_K4,  0 },      /* /KERBEROS4   */
  13913.     { "/krb4",             KRB_I_K4,  CM_INV }, /* /KERBEROS4   */
  13914.     { "/lifetime",         KRB_I_LF,  CM_ARG }, /* /LIFETIME:   */
  13915.     { "/no-addresses",     KRB_I_NAD, 0 },      /* /NO-ADDRESSES */
  13916.     { "/no-k4",            KRB_I_NK4, CM_INV },/* /NO-KERBEROS4 */
  13917.     { "/no-kerberos4",     KRB_I_NK4, 0 },     /* /NO-KERBEROS4 */
  13918.     { "/no-krb4",          KRB_I_NK4, CM_INV },/* /NO-KERBEROS4 */
  13919.     { "/not-forwardable",  KRB_I_NFW, 0 },         /* /NOT-FORWARDABLE */
  13920.     { "/not-proxiable",    KRB_I_NPR, 0 },     /* /NOT-PROXIABLE   */
  13921.     { "/password",         KRB_I_PW,  CM_ARG }, /* /PASSWORD:   */
  13922. #ifdef OS2
  13923.     { "/popup",            KRB_I_POP, 0 },     /* /POPUP       */
  13924. #endif /* OS2 */
  13925.     { "/postdate",         KRB_I_PD, CM_ARG }, /* /POSTDATE:   */
  13926.     { "/pr",               KRB_I_PR, CM_INV|CM_ABR }, /* to allow for */
  13927.     { "/pro",              KRB_I_PR, CM_INV|CM_ABR }, /* different spellings */
  13928.     { "/prox",             KRB_I_PR, CM_INV|CM_ABR },
  13929.     { "/proxiable",        KRB_I_PR, 0 },      /* /PROXIABLE   */
  13930.     { "/proxyable",        KRB_I_PR, CM_INV }, /* /PROXYABLE   */
  13931.     { "/realm",            KRB_I_RL, CM_ARG }, /* /REALM:      */
  13932.     { "/renew",            KRB_I_RN, 0 },          /* /RENEW       */
  13933.     { "/renewable",        KRB_I_RB, CM_ARG }, /* /RENEWABLE:  */
  13934.     { "/service",          KRB_I_SR, CM_ARG }, /* /SERVICE:    */
  13935.     { "/validate",         KRB_I_VA, 0 },          /* /VALIDATE    */
  13936.     { "", 0, 0 }
  13937. };
  13938. static int krb5_i_n = sizeof(krb5_i_tbl)/sizeof(struct keytab) - 1;
  13939.  
  13940. static struct keytab klctab[] = {       /* List Credentials switches*/
  13941.     { "/addresses",  XYKLCAD, 0 },
  13942.     { "/encryption", XYKLCEN, 0 },
  13943.     { "/flags",      XYKLCFL, 0 }
  13944. };
  13945. static int nklctab = sizeof(klctab)/sizeof(struct keytab);
  13946.  
  13947. extern int krb_action;
  13948. extern struct krb_op_data krb_op;
  13949.  
  13950. extern struct krb5_list_cred_data krb5_lc;
  13951. extern struct krb5_init_data krb5_init;
  13952. extern char * krb5_d_principal;         /* Default principal */
  13953. extern char * krb5_d_instance;
  13954. extern char * krb5_d_realm;             /* Default realm */
  13955. extern char * krb5_d_cc;                /* Default credentials cache */
  13956. extern char * krb5_d_srv;               /* Default service name */
  13957. extern int    krb5_d_lifetime;          /* Default lifetime */
  13958. extern int    krb5_d_forwardable;
  13959. extern int    krb5_d_proxiable;
  13960. extern int    krb5_d_renewable;
  13961. extern int    krb5_autoget;
  13962. extern int    krb5_autodel;
  13963. extern int    krb5_d_getk4;
  13964. extern int    krb5_d_no_addresses;
  13965. extern int    krb5_checkaddrs;
  13966. extern char * krb5_d_addrs[];
  13967. extern char * k5_keytab;                /* Keytab file */
  13968.  
  13969. extern struct krb4_init_data krb4_init;
  13970. extern char * krb4_d_principal;         /* Default principal */
  13971. extern char * krb4_d_realm;             /* Default realm */
  13972. extern char * krb4_d_srv;               /* Default service name */
  13973. extern int    krb4_d_lifetime;          /* Default lifetime */
  13974. extern int    krb4_d_preauth;
  13975. extern char * krb4_d_instance;
  13976. extern int    krb4_autoget;
  13977. extern int    krb4_autodel;
  13978. extern int    krb4_checkaddrs;
  13979. extern char * k4_keytab;                /* Keytab file */
  13980. #endif /* CK_KERBEROS */
  13981.  
  13982. #ifndef NOSHOW
  13983. int
  13984. sho_iks() {
  13985. #ifdef IKSDCONF
  13986. #ifdef CK_LOGIN
  13987.     extern int ckxsyslog, ckxwtmp, ckxanon;
  13988. #ifdef UNIX
  13989.     extern int ckxpriv;
  13990. #endif /* UNIX */
  13991. #ifdef CK_PERMS
  13992.     extern int ckxperms;
  13993. #endif /* CK_PERMS */
  13994.     extern char * anonfile, * userfile, * anonroot;
  13995. #ifdef OS2
  13996.     extern char * anonacct;
  13997. #endif /* OS2 */
  13998. #ifdef NT
  13999.     extern char * iks_domain;
  14000. #endif /* NT */
  14001. #endif /* CK_LOGIN */
  14002. #ifdef CKWTMP
  14003.     extern char * wtmpfile;
  14004. #endif /* CKWTMP */
  14005. #ifdef IKSDB
  14006.     extern char * dbfile;
  14007.     extern int dbenabled;
  14008. #endif /* IKSDB */
  14009. #ifdef CK_LOGIN
  14010.     extern int logintimo;
  14011. #endif /* CK_LOGIN */
  14012.     extern int srvcdmsg, success, iksdcf, noinit, arg_x;
  14013.     extern char * cdmsgfile[], * cdmsgstr, *kermrc;
  14014.     char * bannerfile = NULL;
  14015.     char * helpfile = NULL;
  14016.     extern int xferlog;
  14017.     extern char * xferfile;
  14018.     int i;
  14019.  
  14020.     if (isguest) {
  14021.         printf("?Command disabled\r\n");
  14022.         return(success = 0);
  14023.     }
  14024.  
  14025.     printf("IKS Settings\r\n");
  14026. #ifdef CK_LOGIN
  14027. #ifdef OS2
  14028.     printf("  Anonymous Account:   %s\r\n",anonacct?anonacct:"<none>");
  14029. #endif /* OS2 */
  14030.     printf("  Anonymous Initfile:  %s\r\n",anonfile?anonfile:"<none>");
  14031.     printf("  Anonymous Login:     %d\r\n",ckxanon);
  14032.     printf("  Anonymous Root:      %s\r\n",anonroot?anonroot:"<none>");
  14033. #endif /* CK_LOGIN */
  14034.     printf("  Bannerfile:          %s\r\n",bannerfile?bannerfile:"<none>");
  14035.     printf("  CDfile:              %s\r\n",cdmsgfile[0]?cdmsgfile[0]:"<none>");
  14036.     for ( i=1;i<16 && cdmsgfile[i];i++ )
  14037.         printf("  CDfile:              %s\r\n",cdmsgfile[i]);
  14038.     printf("  CDMessage:           %d\r\n",srvcdmsg);
  14039. #ifdef IKSDB
  14040.     printf("  DBfile:              %s\r\n",dbfile?dbfile:"<none>");
  14041.     printf("  DBenabled:           %d\r\n",dbenabled);
  14042. #endif /* IKSDB */
  14043. #ifdef CK_LOGIN
  14044. #ifdef NT
  14045.     printf("  Default-domain:      %s\r\n",iks_domain?iks_domain:".");
  14046. #endif /* NT */
  14047. #endif /* CK_LOGIN */
  14048.     printf("  Helpfile:            %s\r\n",helpfile?helpfile:"<none>");
  14049.     printf("  Initfile:            %s\r\n",kermrc?kermrc:"<none>");
  14050.     printf("  No-Initfile:         %d\r\n",noinit);
  14051. #ifdef CK_LOGIN
  14052. #ifdef CK_PERM
  14053.     printf("  Permission code:     %0d\r\n",ckxperms);
  14054. #endif /* CK_PERM */
  14055. #ifdef UNIX
  14056.     printf("  Privileged Login:    %d\r\n",ckxpriv);
  14057. #endif /* UNIX */
  14058. #endif /* CK_LOGIN */
  14059.     printf("  Server-only:         %d\r\n",arg_x);
  14060.     printf("  Syslog:              %d\r\n",ckxsyslog);
  14061.     printf("  Timeout (seconds):   %d\r\n",logintimo);
  14062.     printf("  Userfile:            %s\r\n",userfile?userfile:"<none>");
  14063. #ifdef CK_LOGIN
  14064. #ifdef CKWTMP
  14065.     printf("  Wtmplog:             %d\r\n",ckxwtmp);
  14066.     printf("  Wtmpfile:            %s\r\n",wtmpfile?wtmpfile:"<none>");
  14067. #endif /* CKWTMP */
  14068. #endif /* CK_LOGIN */
  14069.     printf("  Xferfile:            %s\r\n",xferfile?xferfile:"<none>");
  14070.     printf("  Xferlog:             %d\r\n",xferlog);
  14071. #else /* IKSDCONF */
  14072.     printf("?Nothing to show.\r\n");
  14073. #endif /* IKSDCONF */
  14074.     return(success = 1);
  14075. }
  14076.  
  14077. #ifdef CK_AUTHENTICATION
  14078. int
  14079. sho_auth(cx) int cx; {
  14080.     extern int auth_type_user[], cmd_rows;
  14081.     int i;
  14082.     char * p;
  14083.     int kv = 0, all = 0, n = 0;
  14084.  
  14085. #ifdef IKSD
  14086.     if (inserver && isguest) {
  14087.         printf("?Sorry, command disabled.\r\n");
  14088.         return(success = 0);
  14089.     }
  14090. #endif /* IKSD */
  14091.     if (cx) {
  14092.         kv = cx;
  14093.     } else if (auth_type_user[0] != AUTHTYPE_AUTO) {
  14094.         kv = auth_type_user[0];
  14095.     } else {
  14096.         all = 1;
  14097.         kv = AUTHTYPE_KERBEROS_V4;
  14098.     }
  14099.     while (kv) {
  14100.         switch (kv) {
  14101.           case AUTHTYPE_KERBEROS_V4:
  14102.             kv = all ? AUTHTYPE_KERBEROS_V5 : 0;
  14103.             if (ck_krb4_is_installed()) {
  14104.                 printf(" Authentication:      Kerberos 4\n");
  14105.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14106.             } else {
  14107.                 printf(" Authentication:      Kerberos 4 (not installed)\n");
  14108.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14109.                 continue;
  14110.             }
  14111. #ifdef CK_KERBEROS
  14112.             printf(" Keytab file:         %s\n",
  14113.                       k4_keytab ? k4_keytab : "(none)");
  14114.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14115.             if (krb_action < 0) {
  14116.                 p = "(none)";
  14117.             } else {
  14118.                 for (p = "", i = 0; i < krb_a_n; i++) {
  14119.                     if (krb_action == krb_a_tbl[i].kwval) {
  14120.                         p = krb_a_tbl[i].kwd;
  14121.                         break;
  14122.                     }
  14123.                 }
  14124.             }
  14125.             printf(" Action:              %s\n", p);
  14126.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14127.             printf(" Default lifetime     %d\n",krb4_d_lifetime);
  14128.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14129.             printf(" Lifetime:            %d (minutes)\n",krb4_init.lifetime);
  14130.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14131.             printf(" Default preauth:     %d\n",krb4_d_preauth);
  14132.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14133.             printf(" Preauth:             %d\n",krb4_init.preauth);
  14134.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14135.             printf(" Default principal:   \"%s\"\n",
  14136.                     krb4_d_principal ? krb4_d_principal : "");
  14137.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14138.             printf(" Principal:           \"%s\"\n",
  14139.                     krb4_init.principal ? krb4_init.principal : "");
  14140.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14141.             printf(" Default realm:       \"%s\"\n",
  14142.                     krb4_d_realm ? krb4_d_realm : "");
  14143.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14144.             printf(" Realm:               \"%s\"\n",
  14145.                     krb4_init.realm ? krb4_init.realm : "");
  14146.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14147.             printf(" Default instance:    \"%s\"\n",
  14148.                     krb4_d_instance ? krb4_d_instance : "");
  14149.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14150.             printf(" Instance:            \"%s\"\n",
  14151.                     krb4_init.instance ? krb4_init.instance : "");
  14152.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14153.             printf(" Auto-Get TGTs:       %d\n",krb4_autoget);
  14154.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14155.             printf(" Auto-Destroy TGTs:   %s\n",
  14156.                     krb4_autodel==KRB_DEL_NO?"never":
  14157.                     krb4_autodel==KRB_DEL_CL?"on-close":"on-exit");
  14158.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14159.             printf(" Check IP Addresses:  %d\n",krb4_checkaddrs);
  14160.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14161. #ifdef COMMENT
  14162.             printf(" Password:    \"%s\"\n",
  14163.                     krb4_init.password  ? krb4_init.password  : "");
  14164.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14165. #endif /* COMMENT */
  14166. #endif /* CK_KERBEROS */
  14167.             printf("\n");
  14168.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14169.             break;
  14170.         case AUTHTYPE_KERBEROS_V5:
  14171.             kv = all ? AUTHTYPE_SSL : 0;
  14172.             if (ck_krb5_is_installed()) {
  14173.                 if (ck_gssapi_is_installed())
  14174.                     printf(" Authentication:      Kerberos 5 plus GSSAPI\n");
  14175.                 else
  14176.                     printf(" Authentication:      Kerberos 5\n");
  14177.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14178.             } else {
  14179.                 printf(" Authentication:      Kerberos 5 (not installed)\n");
  14180.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14181.                 continue;
  14182.             }
  14183.  
  14184. #ifdef CK_KERBEROS
  14185.             printf(" Cache file:          %s\n",
  14186.                     krb_op.cache ? krb_op.cache : "(none)");
  14187.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14188.             printf(" Default cache:       %s\n",
  14189.                     krb5_d_cc ? krb5_d_cc : "(none)");
  14190.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14191.             printf(" Keytab file:         %s\n",
  14192.                       k5_keytab ? k5_keytab : "(none)");
  14193.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14194.             if (krb_action < 0) {
  14195.                 p = "(none)";
  14196.             } else  {
  14197.                 for (p = "", i = 0; i < krb_a_n; i++) {
  14198.                     if (krb_action == krb_a_tbl[i].kwval) {
  14199.                         p = krb_a_tbl[i].kwd;
  14200.                         break;
  14201.                     }
  14202.                 }
  14203.             }
  14204.             printf(" Action:              %s\n", p);
  14205.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14206.  
  14207.             printf(" Default forwardable  %d\n",krb5_d_forwardable);
  14208.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14209.             printf(" Forwardable:         %d\n",krb5_init.forwardable);
  14210.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14211.             printf(" Default lifetime     %d\n",krb5_d_lifetime);
  14212.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14213.             printf(" Lifetime:            %d (minutes)\n",krb5_init.lifetime);
  14214.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14215.             printf(" Postdate:            \"%s\"\n",
  14216.                     krb5_init.postdate ? krb5_init.postdate: "");
  14217.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14218.             printf(" Default proxiable:   %d\n",krb5_d_proxiable);
  14219.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14220.             printf(" Proxiable:           %d\n",krb5_init.proxiable);
  14221.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14222.             printf(" Renew:               %d\n",krb5_init.renew);
  14223.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14224.             printf(" Default renewable:   %d (minutes)\n",krb5_d_renewable);
  14225.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14226.             printf(" Renewable:           %d (minutes)\n",krb5_init.renewable);
  14227.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14228.             printf(" Service:             \"%s\"\n",
  14229.                     krb5_init.service ? krb5_init.service : "");
  14230.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14231.             printf(" Validate:            %d\n",krb5_init.validate);
  14232.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14233.             printf(" Default principal:   \"%s\"\n",
  14234.                     krb5_d_principal ? krb5_d_principal : "");
  14235.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14236.             printf(" Principal:           \"%s\"\n",
  14237.                     krb5_init.principal ? krb5_init.principal : "");
  14238.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14239.             printf(" Default instance:    \"%s\"\n",
  14240.                     krb5_d_instance ? krb5_d_instance : "");
  14241.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14242.             printf(" Default realm:       \"%s\"\n",
  14243.                     krb5_d_realm ? krb5_d_realm : "");
  14244.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14245.             printf(" Realm:               \"%s\"\n",
  14246.                     krb5_init.realm ? krb5_init.realm : "");
  14247.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14248.             printf(" Auto-Get TGTs:       %d\n",krb5_autoget);
  14249.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14250.             printf(" Auto-Destroy TGTs:   %s\n",
  14251.                     krb5_autodel==KRB_DEL_NO?"never":
  14252.                     krb5_autodel==KRB_DEL_CL?"on-close":"on-exit");
  14253.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14254.             printf(" Default get K4 TGTs: %d\n",krb5_d_getk4);
  14255.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14256.             printf(" Get K4 TGTs: %d\n",krb5_init.getk4);
  14257.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14258.             printf(" Check IP Addresses:  %d\n",krb5_checkaddrs);
  14259.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14260.             printf(" No IP Addresses:  %d\n",krb5_d_no_addresses);
  14261.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14262.             printf(" IP-Addresses:        ");
  14263.             if (krb5_init.addrs && krb5_init.addrs[0]) {
  14264.                 for (i = 0; krb5_init.addrs[i]; i++) {
  14265.                     if (i)
  14266.                       printf(",");
  14267.                     printf("%s",krb5_init.addrs[i]);
  14268.                 }
  14269.             } else if (krb5_d_addrs[0]) {
  14270.                 for (i = 0;i < KRB5_NUM_OF_ADDRS && krb5_d_addrs[i];i++) {
  14271.                     if (i)
  14272.                       printf(",");
  14273.                     printf("%s",krb5_d_addrs[i]);
  14274.                 }
  14275.             } else {
  14276.                 printf("(use default)");
  14277.             }
  14278.             printf("\n");
  14279.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14280. #ifdef COMMENT
  14281.             printf(" Password:            \"%s\"\n",
  14282.                     krb5_init.password  ? krb5_init.password  : "");
  14283.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14284. #endif /* COMMENT */
  14285. #endif /* CK_KERBEROS */
  14286.             printf("\n");
  14287.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14288.             break;
  14289. #ifdef CK_SSL
  14290.           case AUTHTYPE_SSL:
  14291.             kv = all ? AUTHTYPE_SRP : 0;
  14292.             if (ck_ssleay_is_installed()) {
  14293.                 printf(" Authentication:      SSL/TLS (%s)\n",
  14294.                         SSLeay_version(SSLEAY_VERSION));
  14295.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14296.             } else {
  14297.                 printf(" Authentication:      SSL/TLS (not installed)\n");
  14298.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14299.                 continue;
  14300.             }
  14301.             printf(" RSA Certs file: %s\n",ssl_rsa_cert_file?
  14302.                   ssl_rsa_cert_file:"(none)");
  14303.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14304.             printf(" RSA Certs Chain file: %s\n",ssl_rsa_cert_chain_file?
  14305.                   ssl_rsa_cert_chain_file:"(none)");
  14306.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14307.             printf(" RSA Key file: %s\n",ssl_rsa_key_file?
  14308.                   ssl_rsa_key_file:"(none)");
  14309.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14310.             printf(" DSA Certs file: %s\n",ssl_dsa_cert_file?
  14311.                   ssl_dsa_cert_file:"(none)");
  14312.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14313.             printf(" DSA Certs Chain file: %s\n",ssl_dsa_cert_chain_file?
  14314.                   ssl_dsa_cert_chain_file:"(none)");
  14315.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14316.             printf(" DH Key file: %s\n",ssl_dh_key_file?
  14317.                   ssl_dh_key_file:"(none)");
  14318.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14319.             printf(" DH Param file: %s\n",ssl_dh_param_file?
  14320.                   ssl_dh_param_file:"(none)");
  14321.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14322.             printf(" CRL file: %s\n",ssl_crl_file?
  14323.                   ssl_crl_file:"(none)");
  14324.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14325.             printf(" CRL dir: %s\n",ssl_crl_dir?
  14326.                     ssl_crl_dir:"(none)");
  14327.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14328.             printf(" Random file: %s\n",ssl_rnd_file?
  14329.                   ssl_rnd_file:"(none)");
  14330.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14331.             printf(" Verify file: %s\n",ssl_verify_file?
  14332.                   ssl_verify_file:"(none)");
  14333.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14334.             printf(" Verify dir: %s\n",ssl_verify_dir?
  14335.                   ssl_verify_dir:"(none)");
  14336.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14337.             printf(" Cipher list: %s\n",ssl_cipher_list ? ssl_cipher_list : 
  14338.             DEFAULT_CIPHER_LIST);
  14339.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14340.             if (ssl_con == NULL) {
  14341.                 SSL_library_init();
  14342.                 ssl_ctx = (SSL_CTX *)
  14343.                   SSL_CTX_new((SSL_METHOD *)TLSv1_method());
  14344.                 if (ssl_ctx != NULL)
  14345.                   ssl_con= (SSL *) SSL_new(ssl_ctx);
  14346.             }
  14347.             if (ssl_con != NULL) {
  14348.                 CHAR * p = NULL;
  14349.                 int i;
  14350.  
  14351.                 for (i = 0; ; i++) {
  14352.                     p = (CHAR *) SSL_get_cipher_list(ssl_con,i);
  14353.                     if (p == NULL)
  14354.                       break;
  14355.                     printf("    %s\n",p);
  14356.                     if (++n > cmd_rows - 3)
  14357.                         if (!askmore()) return(0); else n = 0;
  14358.                 }
  14359.             }
  14360.             printf(" Certs OK? %s\n",ssl_certsok_flag? "yes" : "no");
  14361.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14362.             printf(" Debug mode: %s\n", ssl_debug_flag ? "on" : "off");
  14363.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14364.             printf(" Verbose mode: %s\n", ssl_verbose_flag ? "on" : "off");
  14365.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14366.             printf(" Verify mode: %s\n",
  14367.                     ssl_verify_flag == SSL_VERIFY_NONE ? "none" :
  14368.                     ssl_verify_flag == SSL_VERIFY_PEER ? "peer-cert" :
  14369.                     "fail-if-no-peer-cert");
  14370.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14371.             printf(" SSL only? %s\n", ssl_only_flag ? "yes" : "no");
  14372.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14373.             printf(" TLS only? %s\n", tls_only_flag ? "yes" : "no");
  14374.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14375. #endif /* CK_SSL */
  14376.             break;
  14377.           case AUTHTYPE_NTLM:
  14378.             kv = 0;
  14379.             if (ck_ntlm_is_installed()) {
  14380.                 printf(" Authentication:      NTLM\n");
  14381.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14382.                 printf(" No options\n");
  14383.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14384.             } else {
  14385.                 printf(" Authentication:      NTLM (not installed)\n");
  14386.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14387.                 continue;
  14388.             }
  14389.             printf("\n");
  14390.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14391.             break;
  14392.           case AUTHTYPE_SRP:
  14393.             kv = all ? AUTHTYPE_NTLM : 0;
  14394.             if (ck_srp_is_installed()) {
  14395.                 if (ck_krypto_is_installed())
  14396.                     printf(" Authentication:      SRP plus Krypto API\n");
  14397.                 else
  14398.                     printf(" Authentication:      SRP\n");
  14399.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14400.                 printf(" No options\n");
  14401.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14402.             } else {
  14403.                 printf(" Authentication:      SRP (not installed)\n");
  14404.                 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14405.                 continue;
  14406.             }
  14407.             printf("\n");
  14408.             if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
  14409.             break;
  14410.         }
  14411.     }
  14412.     return(success = 1);
  14413. }
  14414. #endif /* CK_AUTHENTICATION */
  14415. #endif /* NOSHOW */
  14416.  
  14417. #ifdef CK_KERBEROS
  14418.  
  14419. /*  C P _ A U T H  --  AUTHENTICATE command parsing  */
  14420.  
  14421. int
  14422. cp_auth() {                             /* Command_Parse AUTHENTICATE */
  14423.     int c, i, n;                        /* Workers */
  14424.     int rc = 0;                         /* Return code */
  14425.     int getval;                         /* Parsing helpers */
  14426.     int tmpauth = 0;                    /* Temporary authentication type */
  14427.     int kv = 0;                         /* Temporary Kerberos version */
  14428.     int tmp_action = -1;                /* Temporary Kerberos action */
  14429.     int tmp_klc = 0;                    /* Temporary list-credentials */
  14430.     char tmphlp[256];                   /* For building help message */
  14431.     char * p;
  14432.     char * tmppswd  = NULL;             /* Password */
  14433.     char * tmpprinz = NULL;             /* Principal */
  14434.     char * tmprealm = NULL;             /* Realm */
  14435.     char * tmpcache = NULL;             /* Cache file */
  14436.     char * tmpinst  = NULL;             /* K4 Instance */
  14437.     char * tmpaddrs[KRB5_NUM_OF_ADDRS];
  14438. #ifdef CK_RECALL
  14439.     extern int on_recall;               /* around Password prompting */
  14440. #endif /* CK_RECALL */
  14441.     struct stringint pv[KRB_I_MAX+1];   /* Temporary array for switch values */
  14442.     struct FDB kw, sw, fl;              /* FDBs for each parse function */
  14443.  
  14444.     krb_action = -1;                    /* Initialize Kerberos action. */
  14445.     tmp_action = -1;                    /* And our local copy. */
  14446.     for (i = 0; i < KRB5_NUM_OF_ADDRS; i++)
  14447.       tmpaddrs[i] = NULL;
  14448.  
  14449.     if ((y = cmkey(kerbtab,kerbtabn,"authentication type","",xxstring)) < 0)
  14450.       {
  14451.           if (y == -3)
  14452.             printf("?Authentication type not specified - nothing happens\n");
  14453.           return(y);
  14454.       }
  14455.     tmpauth = y;
  14456.     debug(F101,"kerberos authentication","",tmpauth);
  14457.     switch (tmpauth) {
  14458.       case AUTH_KRB4: kv = 4; break;    /* Don't assume values are the same */
  14459.       case AUTH_KRB5: kv = 5; break;
  14460.       default:
  14461.         printf("?Authentication type not supported: \"%s\"\n",atmbuf);
  14462.         return(-9);
  14463.     }
  14464.  
  14465.     /* From here down is Kerberos */
  14466.     ini_kerb();                         /* Reset Init data to defaults */
  14467.  
  14468.     if (kv == 4) {                      /* Set K4 defaults */
  14469.         if (krb4_d_realm)
  14470.           makestr(&tmprealm,krb4_d_realm);
  14471.         if (krb4_d_principal)
  14472.           makestr(&tmpprinz,krb4_d_principal);
  14473.         if (krb4_d_instance)
  14474.           makestr(&tmpinst,krb4_d_instance);
  14475.     } else if (kv == 5) {               /* Set K5 defaults */
  14476.         if (krb5_d_cc)
  14477.           makestr(&tmpcache,krb5_d_cc);
  14478.         if (krb5_d_realm)
  14479.           makestr(&tmprealm,krb5_d_realm);
  14480.         if (krb5_d_principal)
  14481.           makestr(&tmpprinz,krb5_d_principal);
  14482.         if (krb5_d_instance)
  14483.           makestr(&tmpinst,krb5_d_instance);
  14484.     }
  14485.     for (i = 0; i <= KRB_I_MAX; i++) {  /* Initialize switch values */
  14486.         pv[i].sval = NULL;              /* to null pointers */
  14487.         pv[i].ival = 0;                 /* and 0 int values */
  14488.         pv[i].wval = (CK_OFF_T)-1;    /* and -1 wide values */
  14489.     }
  14490.     if (kv == 4) {                      /* Kerberos 4 */
  14491.         pv[KRB_I_LF].ival = krb4_d_lifetime;
  14492.         pv[KRB_I_PA].ival = krb4_d_preauth;
  14493.  
  14494.         if ((n = cmkey(krb_a_tbl,krb_a_n,"Kerberos 4 action","",xxstring)) < 0)
  14495.           {
  14496.               if (n == -3)
  14497.                 printf("?Action not specified - nothing happens.\n");
  14498.               return(n);
  14499.           }
  14500.     } else if (kv == 5) {               /* Kerberos 5 */
  14501.         pv[KRB_I_FW].ival = krb5_d_forwardable;
  14502.         pv[KRB_I_PR].ival = krb5_d_proxiable;
  14503.         pv[KRB_I_LF].ival = krb5_d_lifetime;
  14504.         pv[KRB_I_RB].ival = krb5_d_renewable;
  14505.         pv[KRB_I_K4].ival = krb5_d_getk4;
  14506.         pv[KRB_I_NAD].ival = krb5_d_no_addresses;
  14507.  
  14508.         /* Make help message that shows switches and action keywords */
  14509.         ckstrncpy(tmphlp,"Kerberos 5 action, one of the following:\n ",256);
  14510.         for (i = 0; i < krb_a_n; i++) {
  14511.             ckstrncat(tmphlp,krb_a_tbl[i].kwd,sizeof(tmphlp));
  14512.             if (i == krb_a_n - 1)
  14513.               ckstrncat(tmphlp,"\nor switch",sizeof(tmphlp));
  14514.             else
  14515.               ckstrncat(tmphlp,"   ",sizeof(tmphlp));
  14516.         }
  14517.         /* Set up first set of chained FDB's */
  14518.  
  14519.         cmfdbi(&sw,                     /* First FDB - command switches */
  14520.                _CMKEY,                  /* fcode */
  14521.                tmphlp,                  /* hlpmsg */
  14522.                "",                      /* default (none) */
  14523.                "",                      /* addtl string data */
  14524.                krb_s_n,                 /* Switch table size */
  14525.                4,                       /* addtl numeric data 2: 4 = cmswi */
  14526.                xxstring,                /* Processing function */
  14527.                krb_s_tbl,               /* Switch table */
  14528.                &kw                      /* Pointer to next FDB */
  14529.                );
  14530.         cmfdbi(&kw,                     /* Second FDB - action keywords */
  14531.                _CMKEY,                  /* fcode */
  14532.                "Kerberos action",       /* hlpmsg */
  14533.                "",                      /* default (none) */
  14534.                "",                      /* addtl string data */
  14535.                krb_a_n,                 /* Switch table size */
  14536.                0,                       /* addtl num data (0 = NOT switch) */
  14537.                xxstring,                /* Processing function */
  14538.                krb_a_tbl,               /* Keyword table */
  14539.                NULL                     /* Pointer to next FDB (none) */
  14540.                );
  14541.  
  14542.         /* Parse */
  14543.  
  14544.         while (1) {                     /* Parse 0 or more switches */
  14545.             rc = cmfdb(&sw);            /* Parse something */
  14546.             debug(F101,"kerberos cmfdb 1 rc","",rc);
  14547.             if (rc < 0) {                       /* Error */
  14548.                 if (rc == -3)
  14549.                   printf("?Action not specified - nothing happens.\n");
  14550.                 return(rc);             /* or reparse needed */
  14551.             }
  14552.             if (cmresult.fdbaddr != &sw) /* Break out if not a switch */
  14553.               break;
  14554.             c = cmgbrk();               /* Have switch - get break character */
  14555.             getval = (c == ':' || c == '='); /* Must parse an agument? */
  14556.             if (getval && !(cmresult.kflags & CM_ARG)) {
  14557.                 printf("?This switch does not take arguments\n");
  14558.                 return(-9);             /* OK because nothing malloc'd yet */
  14559.             }
  14560.             if (!getval && (cmgkwflgs() & CM_ARG)) {
  14561.                 printf("?This switch requires an argument\n");
  14562.                 return(-9);
  14563.             }
  14564.             n = cmresult.nresult;       /* Numeric result = switch value */
  14565.             debug(F101,"kerberos command switch","",n);
  14566.  
  14567.             switch (n) {                /* Handle the switch */
  14568.               case KRB_S_CA:            /* /CACHE:<filename> */
  14569.                 p = krb5_d_cc ? krb5_d_cc : "";
  14570.                 if ((y = cmofi("Name of cache file",p,&s,xxstring)) < 0) {
  14571.                     if (y == -3)
  14572.                       s = NULL;
  14573.                     else
  14574.                       return(y);
  14575.                 }
  14576.                 makestr(&tmpcache,s);
  14577.                 break;
  14578.               default:
  14579.                 printf("?Unexpected switch value - internal error\n");
  14580.                 return(-9);             /* (if) nothing malloc'd yet. */
  14581.             }
  14582.         }
  14583.         if (cmresult.fdbaddr != &kw) {  /* Checking... */
  14584.             printf("?Unexpected result - internal error\n");
  14585.             return(-9);                 /* Nothing malloc'd yet. */
  14586.         }
  14587.         n = cmresult.nresult;           /* Get keyword value */
  14588.     } else {
  14589.         printf("?Unexpected Kerberos version - Internal error\n");
  14590.         return(-9);
  14591.     }
  14592.     debug(F101,"kerberos action","",n);
  14593.     switch (n) {
  14594.       case KRB_A_IN:                    /* INITIALIZE */
  14595.       case KRB_A_DE:                    /* DESTROY */
  14596.       case KRB_A_LC:                    /* LIST-CREDENTIALS */
  14597.         tmp_action = n;                 /* OK, set */
  14598.         break;
  14599.       default:                          /* Not OK, punt. */
  14600.         printf("?Unexpected action - internal error\n");
  14601.         return(-9);
  14602.     }
  14603.     if (tmp_action == KRB_A_IN) {       /* Action is INITIALIZE */
  14604.         int x;
  14605.         cmfdbi(&sw,                     /* INITIALIZE switches */
  14606.                _CMKEY,                  /* fcode */
  14607.                "Principal,\n or optional INITIALIZE switch(es)", /* hlpmsg */
  14608.                "",                      /* default (none) */
  14609.                "",                      /* addtl string data */
  14610.                kv == 4 ?  krb4_i_n : krb5_i_n, /* Switch table size */
  14611.                4,                       /* addtl numeric data 2: 4 = cmswi */
  14612.                xxstring,                /* Processing function */
  14613.                kv == 4 ?  krb4_i_tbl : krb5_i_tbl,      /* Switch table */
  14614.                &fl                      /* Pointer to next FDB */
  14615.                );
  14616.         cmfdbi(&fl,                     /* 3rd FDB - command to send from */
  14617.                _CMFLD,                  /* fcode */
  14618.                "Principal",             /* hlpmsg */
  14619.                kv == 4 ? krb4_d_principal : krb5_d_principal, /* principal */
  14620.                "",                      /* addtl string data */
  14621.                0,                       /* addtl numeric data 1 */
  14622.                0,                       /* addtl numeric data 2 */
  14623.                xxstring,
  14624.                NULL,
  14625.                NULL
  14626.                );
  14627.         while (1) {                     /* Parse INIT switches or principal */
  14628.             rc = cmfdb(&sw);
  14629.             debug(F101,"kerberos cmfdb 2 rc","",rc);
  14630.             if (rc < 0) {
  14631.                 if (rc == -3)
  14632.                   printf("?Principal name required\n");
  14633.                 goto kerbx;
  14634.             }
  14635.             debug(F101,"kerberos cmfdb 2 fcode","",cmresult.fcode);
  14636.             if (cmresult.fcode != _CMKEY) /* Not a switch, quit switch loop */
  14637.               break;
  14638.             c = cmgbrk();               /* Switch - get break character */
  14639.             debug(F101,"kerberos cmfdb 2 cmgbrk","",c);
  14640.             getval = (c == ':' || c == '=');
  14641.             if (getval && !(cmresult.kflags & CM_ARG)) {
  14642.                 printf("?This switch does not take arguments\n");
  14643.                 return(-9);             /* OK because nothing malloc'd yet */
  14644.             }
  14645.             if (!getval && (cmgkwflgs() & CM_ARG)) {
  14646.                 printf("?This switch requires an argument\n");
  14647.                 return(-9);
  14648.             }
  14649.             n = cmresult.nresult;       /* Numeric result = switch value */
  14650.             switch (n) {
  14651.               /* These don't take args... */
  14652.               case KRB_I_PA:            /* /PREAUTH */
  14653.               case KRB_I_FW:            /* /FORWARDABLE */
  14654.               case KRB_I_PR:            /* /PROXIABLE */
  14655.               case KRB_I_RN:            /* /RENEW */
  14656.               case KRB_I_VA:            /* /VALIDATE */
  14657.               case KRB_I_NPA:           /* /NOT-PREAUTH */
  14658.               case KRB_I_NFW:           /* /NOT-FORWARDABLE */
  14659.               case KRB_I_NPR:           /* /NOT-PROXIABLE */
  14660.               case KRB_I_VB:            /* /VERBOSE */
  14661.               case KRB_I_BR:            /* /BRIEF */
  14662.               case KRB_I_K4:            /* /KERBEROS4 */
  14663.               case KRB_I_NK4:           /* /NO-KERBEROS4 */
  14664.               case KRB_I_POP:           /* /POPUP */
  14665.               case KRB_I_NAD:           /* /NO-ADDRESSES */
  14666.                 if (getval) {
  14667.                     printf("?This switch does not take a value\n");
  14668.                     rc = -9;
  14669.                     goto kerbx;
  14670.                 }
  14671.                 switch (n) {
  14672.                   case KRB_I_NPA:
  14673.                     pv[KRB_I_PA].ival = 0;
  14674.                     break;
  14675.                   case KRB_I_NFW:
  14676.                     pv[KRB_I_FW].ival = 0;
  14677.                     break;
  14678.                   case KRB_I_NPR:
  14679.                     pv[KRB_I_PR].ival = 0;
  14680.                     break;
  14681.                   case KRB_I_VB:
  14682.                     pv[KRB_I_BR].ival = 0;
  14683.                     break;
  14684.                   case KRB_I_NK4:
  14685.                     pv[KRB_I_K4].ival = 0;
  14686.                     break;
  14687.                   default:
  14688.                     pv[n].ival = 1;
  14689.                 }
  14690.                 break;
  14691.  
  14692.                 /* These do take arguments */
  14693.  
  14694.               case KRB_I_RB:            /* /RENEWABLE:<minutes> */
  14695.                 pv[n].ival = 0;
  14696.                 if (!getval) break;
  14697.                 if ((rc = cmnum("Minutes",ckitoa(krb5_init.renewable),
  14698.                                 10,&y, xxstring)) < 0)
  14699.                   goto kerbx;
  14700.                 pv[n].ival = y;
  14701.                 break;
  14702.  
  14703.               case KRB_I_LF:            /* /LIFETIME:<minutes> */
  14704.                 pv[n].ival = 0;
  14705.                 /* Default is previous value */
  14706.                 sprintf(tmpbuf,"%d",    /* SAFE */
  14707.                         kv == 4 ?
  14708.                         krb4_init.lifetime :
  14709.                         krb5_init.lifetime
  14710.                         );
  14711.                 if (!getval) break;
  14712.                 if ((rc = cmnum("Minutes",tmpbuf,10,&y, xxstring)) < 0)
  14713.                   goto kerbx;
  14714.                 pv[n].ival = y;
  14715.                 break;
  14716.  
  14717.               case KRB_I_PD:            /* /POSTDATE:<timestamp> */
  14718.                 if (pv[n].sval) {
  14719.                     free(pv[n].sval);
  14720.                     pv[n].sval = NULL;
  14721.                 }
  14722.                 if (!getval) break;
  14723.                 if ((rc = cmdate("date-time","",&s,0,xxstring)) < 0)
  14724.                   goto kerbx;
  14725.                 makestr(&(pv[n].sval),s);
  14726.                 break;
  14727.  
  14728.               case KRB_I_SR:            /* /SERVICE:<name> */
  14729.                 if (pv[n].sval) {
  14730.                     free(pv[n].sval);
  14731.                     pv[n].sval = NULL;
  14732.                 }
  14733.                 if (!getval) break;
  14734.                 if ((rc = cmfld("Service-name","",&s,xxstring)) < 0)
  14735.                   goto kerbx;
  14736.                 makestr(&(pv[n].sval),s);
  14737.                 break;
  14738.  
  14739.               case KRB_I_RL:            /* /REALM:<name> */
  14740.                 if (pv[n].sval) {
  14741.                     free(pv[n].sval);
  14742.                     pv[n].sval = NULL;
  14743.                 }
  14744.                 if (!getval) break;
  14745.                 if (kv == 4)
  14746.                   p = krb4_d_realm ? krb4_d_realm : "";
  14747.                 else
  14748.                   p = krb5_d_realm ? krb5_d_realm : "";
  14749.                 if ((rc = cmfld("Realm",p,&s,xxstring)) < 0)
  14750.                   goto kerbx;
  14751.                 makestr(&(pv[n].sval),s);
  14752.                 break;
  14753.  
  14754.               case KRB_I_IN:            /* /INSTANCE:<name> */
  14755.                 if (pv[n].sval) {
  14756.                     free(pv[n].sval);
  14757.                     pv[n].sval = NULL;
  14758.                 }
  14759.                 if (!getval) break;
  14760.                 if (kv == 4)
  14761.                     p = krb4_d_instance ? krb4_d_instance : "";
  14762.                 else
  14763.                     p = krb5_d_instance ? krb5_d_instance : "";
  14764.                 if ((rc = cmfld("Instance",p,&s,xxstring)) < 0)
  14765.                   goto kerbx;
  14766.                 makestr(&(pv[n].sval),s);
  14767.                 break;
  14768.  
  14769.               case KRB_I_PW:            /* /PASSWORD:<password> */
  14770.                 debok = 0;
  14771.                 if (pv[n].sval) {
  14772.                     free(pv[n].sval);
  14773.                     pv[n].sval = NULL;
  14774.                 }
  14775.                 if (!getval) break;
  14776.                 if ((rc = cmfld("Password","",&s,xxstring)) < 0)
  14777.                   if (rc != -3)
  14778.                     goto kerbx;
  14779.                 makestr(&(pv[n].sval),s);
  14780.                 break;
  14781.  
  14782.               case KRB_I_ADR:           /* /ADDRESSES:{<address-list>} */
  14783.                 if (pv[n].sval) {
  14784.                     free(pv[n].sval);
  14785.                     pv[n].sval = NULL;
  14786.                 }
  14787.                 if (!getval) break;
  14788.                 if ((rc = cmfld("List of IP addresses","",&s,xxstring)) < 0)
  14789.                   goto kerbx;
  14790.                 makelist(s,tmpaddrs,KRB5_NUM_OF_ADDRS);
  14791.                 for (i = 0; i < KRB5_NUM_OF_ADDRS && tmpaddrs[i]; i++) {
  14792.                     if (inet_addr(tmpaddrs[i]) == 0xffffffff) {
  14793.                         printf("invalid ip address: %s\n",tmpaddrs[i]);
  14794.                         rc = -9;
  14795.                         goto kerbx;
  14796.                     }
  14797.                 }
  14798.                 pv[KRB_I_NAD].ival = 0;
  14799.                 break;
  14800.  
  14801.               default:
  14802.                 printf("?Unexpected switch value - internal error\n");
  14803.                 rc = -9;
  14804.                 goto kerbx;
  14805.             }
  14806.         }
  14807.         if (cmresult.fcode != _CMFLD) {
  14808.             printf("?Unexected result - internal error\n");
  14809.             rc = -9;
  14810.             goto kerbx;
  14811.         }
  14812.         /* cmresult.sresult may be of the form PRINCIPAL@REALM */
  14813.         i = ckindex("@",cmresult.sresult,0,0,0);
  14814.         if (i != 0) {
  14815.             makestr(&tmprealm,&cmresult.sresult[i]);
  14816.             cmresult.sresult[i-1] = '\0';
  14817.         }
  14818.         makestr(&tmpprinz,cmresult.sresult); /* Principal (user) */
  14819.  
  14820.         if ((rc = cmcfm()) < 0) {       /* Now get confirmation */
  14821.             if (rc == -3) {
  14822.                 printf("?Principal name required\n");
  14823.             }
  14824.             goto kerbx;
  14825.         }
  14826.         if (!tmpprinz || !tmpprinz[0]) {
  14827.             printf("?Principal name required\n");
  14828.             goto kerbx;
  14829.         }
  14830.         if (!pv[KRB_I_RN].ival && !pv[KRB_I_VA].ival) {
  14831.             /* Don't use a password if Validating or Renewing */
  14832.             if (pv[KRB_I_PW].sval) {    /* If they gave a /PASSWORD switch */
  14833.                 makestr(&tmppswd,pv[KRB_I_PW].sval); /* use this value */
  14834.             }
  14835. #ifdef COMMENT
  14836.             /* Password prompting has been moved to ck_krb[45]_initTGT() */
  14837.             else {                      /* Otherwise must prompt for it */
  14838.                 char prmpt[80];
  14839.                 if (pv[KRB_I_RL].sval)
  14840.                   sprintf(prmpt,"%s@%s's Password: ",
  14841.                           tmpprinz,pv[KRB_I_RL].sval);
  14842.                 else if (tmprealm)
  14843.                   sprintf(prmpt,"%s@%s's Password: ",
  14844.                           tmpprinz,tmprealm);
  14845.                 else
  14846.                   sprintf(prmpt,"%s's Password: ",tmpprinz);
  14847. #ifdef OS2
  14848.                 if (pv[KRB_I_POP].ival) {
  14849.                     char passwd[80]="";
  14850.                     readpass(prmpt,passwd,80);
  14851.                     makestr(&tmppswd,passwd);
  14852.                     memset(passwd,0,80);
  14853.                 } else
  14854. #endif /* OS2 */
  14855.                 {
  14856. #ifdef CK_RECALL
  14857.                     on_recall = 0;
  14858. #endif /* CK_RECALL */
  14859.                     cmsavp(psave,PROMPTL); /* Save old prompt */
  14860.                     cmsetp(prmpt);      /* Make new prompt */
  14861.                     concb((char)escape); /* Put console in cbreak mode */
  14862.                     cmini(0);           /* and no-echo mode */
  14863.                     /* Issue prompt if at top level */
  14864.                     if (pflag) prompt(xxstring);
  14865.                     cmres();            /* Reset the parser */
  14866.                     for (rc = -1; rc < 0; ) { /* Prompt till they answer */
  14867.                         /* Get a literal line of text */
  14868.                         rc = cmtxt("","",&s,NULL);
  14869.                         cmres();        /* Reset the parser again */
  14870.                     }
  14871.                     makestr(&tmppswd,s);
  14872.                     printf("\n");       /* Echo a CRLF */
  14873.                     cmsetp(psave);      /* Restore original prompt */
  14874.                 }
  14875.             }
  14876.             x = 0;                      /* Check for password */
  14877.             if (tmppswd)
  14878.               if (*tmppswd)
  14879.                 x = 1;
  14880.             if (!x) {
  14881.                 printf("?Password required\n");
  14882.                 goto kerbx;
  14883.             }
  14884. #endif /* COMMENT */
  14885.         }
  14886.     } else if (kv == 5 && tmp_action == KRB_A_LC) { /* LIST-CREDENTIALS */
  14887.         tmp_klc = 0;
  14888.         while (1) {
  14889.             if ((x = cmkey(klctab,nklctab,"Switch","",xxstring)) < 0) {
  14890.                 if (x == -3) {
  14891.                     if ((rc = cmcfm()) < 0)
  14892.                       goto kerbx;
  14893.                     else
  14894.                       break;
  14895.                 } else {
  14896.                     rc = x;
  14897.                     goto kerbx;
  14898.                 }
  14899.             }
  14900.             tmp_klc |= x;
  14901.         }
  14902.     } else if ((rc = cmcfm()) < 0)      /* DESTROY, just confirm */
  14903.         goto kerbx;
  14904.  
  14905. /* Done - Move confirmed data to final locations */
  14906.  
  14907.     krb_action = tmp_action;            /* Action requested */
  14908.     krb_op.version = kv;                /* Kerberos version */
  14909.     krb_op.cache = tmpcache;            /* Cache file */
  14910.     tmpcache = NULL;                    /* So we don't free it */
  14911.  
  14912.     switch (krb_action) {
  14913.       case KRB_A_IN:                    /* INITIALIZE */
  14914.         if (kv == 5) {
  14915.             krb5_init.forwardable = pv[KRB_I_FW].ival;
  14916.             krb5_init.proxiable   = pv[KRB_I_PR].ival;
  14917.             krb5_init.lifetime    = pv[KRB_I_LF].ival;
  14918.             krb5_init.renew       = pv[KRB_I_RN].ival;
  14919.             krb5_init.renewable   = pv[KRB_I_RB].ival;
  14920.             krb5_init.validate    = pv[KRB_I_VA].ival;
  14921.  
  14922.             /* Here we just reassign the pointers and then set them to NULL */
  14923.             /* so they won't be freed below. */
  14924.  
  14925.             krb5_init.postdate = pv[KRB_I_PD].sval; pv[KRB_I_PD].sval = NULL;
  14926.             krb5_init.service  = pv[KRB_I_SR].sval; pv[KRB_I_SR].sval = NULL;
  14927.             if (pv[KRB_I_RL].sval) {
  14928.                 krb5_init.realm  = pv[KRB_I_RL].sval; pv[KRB_I_RL].sval = NULL;
  14929.             } else if (tmprealm) {
  14930.                 krb5_init.realm = tmprealm; tmprealm = NULL;
  14931.             }
  14932.             if (pv[KRB_I_IN].sval) {
  14933.                 krb5_init.instance = pv[KRB_I_IN].sval;
  14934.                 pv[KRB_I_IN].sval = NULL;
  14935.             } else if ( tmpinst ) {
  14936.                 krb5_init.instance = tmpinst;
  14937.                 tmpinst = NULL;
  14938.             }
  14939.             if (tmpprinz) {
  14940.                 krb5_init.principal = tmpprinz;
  14941.                 tmpprinz = NULL;
  14942.             }
  14943.             krb5_init.password = tmppswd;
  14944.             tmppswd = NULL;
  14945.  
  14946.             krb5_init.getk4 = pv[KRB_I_K4].ival;
  14947.             if (krb5_init.getk4) {
  14948.                 krb4_init.lifetime = pv[KRB_I_LF].ival;
  14949.                 if (krb5_init.realm)
  14950.                     makestr(&krb4_init.realm,krb5_init.realm);
  14951.                 krb4_init.preauth  = krb4_d_preauth;
  14952.                 krb4_init.verbose  = pv[KRB_I_BR].ival ? 0 : 1;
  14953.                 if (krb5_init.principal)
  14954.                     makestr(&krb4_init.principal,krb5_init.principal);
  14955.                 if (krb5_init.principal)
  14956.                     makestr(&krb4_init.password,krb5_init.password);
  14957.             }
  14958.             krb5_init.no_addresses = pv[KRB_I_NAD].ival;
  14959.             if (tmpaddrs[0]) {
  14960.                 for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
  14961.                     if (krb5_init.addrs[i]) {
  14962.                         free(krb5_init.addrs[i]);
  14963.                         krb5_init.addrs[i] = NULL;
  14964.                     }
  14965.                     krb5_init.addrs[i] = tmpaddrs[i];
  14966.                     tmpaddrs[i] = NULL;
  14967.                 }
  14968.             }
  14969.         } else if (kv == 4) {           /* Same deal for Kerberos 4 */
  14970.             krb4_init.lifetime = pv[KRB_I_LF].ival;
  14971.             if (pv[KRB_I_RL].sval) {
  14972.                 krb4_init.realm  = pv[KRB_I_RL].sval;
  14973.                 pv[KRB_I_RL].sval = NULL;
  14974.             } else if ( tmprealm ) {
  14975.                 krb4_init.realm  = tmprealm;
  14976.                 tmprealm = NULL;
  14977.             }
  14978.             if (pv[KRB_I_IN].sval) {
  14979.                 krb4_init.instance = pv[KRB_I_IN].sval;
  14980.                 pv[KRB_I_IN].sval = NULL;
  14981.             } else if ( tmpinst ) {
  14982.                 krb4_init.instance = tmpinst;
  14983.                 tmpinst = NULL;
  14984.             }
  14985.             krb4_init.preauth  = pv[KRB_I_PA].ival;
  14986.             krb4_init.verbose  = pv[KRB_I_BR].ival ? 0 : 1;
  14987.  
  14988.             if (tmpprinz) {
  14989.                 krb4_init.principal = tmpprinz;
  14990.                 tmpprinz = NULL;
  14991.             }
  14992.             krb4_init.password = tmppswd;
  14993.             tmppswd = NULL;
  14994.         }
  14995.         break;
  14996.       case KRB_A_LC:                    /* List Credentials */
  14997.         krb5_lc.encryption = tmp_klc & XYKLCEN;
  14998.         krb5_lc.flags = tmp_klc & XYKLCFL;
  14999.         krb5_lc.addr  = tmp_klc & XYKLCAD;
  15000.         break;
  15001.     }
  15002.  
  15003. /* Common exit - Free temporary storage */
  15004.  
  15005.   kerbx:
  15006.     for (i = 0; i <= KRB_I_MAX; i++) {  /* Free malloc'd switch data */
  15007.         if (pv[i].sval)
  15008.           free(pv[i].sval);
  15009.     }
  15010.     for (i = 0; i < KRB5_NUM_OF_ADDRS; i++) {
  15011.         if (tmpaddrs[i])
  15012.           free(tmpaddrs[i]);
  15013.     }
  15014.     if (tmpprinz) free(tmpprinz);       /* And these too. */
  15015.     if (tmppswd)  free(tmppswd);
  15016.     if (tmpcache) free(tmpcache);
  15017.     if (tmprealm) free(tmprealm);
  15018.     if (tmpinst)  free(tmpinst);
  15019.  
  15020.     return(rc);                         /* Return the return code */
  15021. }
  15022. #endif /* CK_KERBEROS */
  15023.  
  15024. #ifdef CK_LOGIN
  15025. int
  15026. #ifdef CK_ANSIC
  15027. ckxlogin(CHAR * userid, CHAR * passwd, CHAR * acct, int promptok)
  15028. #else /* CK_ANSIC */
  15029. ckxlogin(userid, passwd, acct, promptok)
  15030.   CHAR * userid; CHAR * passwd; CHAR * acct; int promptok;
  15031. #endif /* CK_ANSIC */
  15032. /* ckxlogin */ {
  15033. #ifdef CK_RECALL
  15034.     extern int on_recall;               /* around Password prompting */
  15035. #endif /* CK_RECALL */
  15036. #ifdef COMMENT
  15037.     extern int guest;
  15038. #endif /* COMMENT */
  15039.     int rprompt = 0;                    /* Restore prompt */
  15040. #ifdef CKSYSLOG
  15041.     int savlog;
  15042. #endif /* CKSYSLOG */
  15043.  
  15044.     extern int what, srvcdmsg;
  15045.  
  15046.     int x = 0, ok = 0, rc = 0;
  15047.     CHAR * _u = NULL, * _p = NULL, * _a = NULL;
  15048.  
  15049.     debug(F111,"ckxlogin userid",userid,promptok);
  15050.     debug(F110,"ckxlogin passwd",passwd,0);
  15051.  
  15052.     isguest = 0;                        /* Global "anonymous" flag */
  15053.  
  15054.     if (!userid) userid = (CHAR *)"";
  15055.     if (!passwd) passwd = (CHAR *)"";
  15056.  
  15057.     debug(F111,"ckxlogin userid",userid,what);
  15058.  
  15059. #ifdef CK_RECALL
  15060.     on_recall = 0;
  15061. #endif /* CK_RECALL */
  15062.  
  15063. #ifdef CKSYSLOG
  15064.     savlog = ckxsyslog;                 /* Save and turn off syslogging */
  15065. #endif /* CKSYSLOG */
  15066.  
  15067.     if ((!*userid || !*passwd) &&       /* Need to prompt for missing info */
  15068.         promptok) {
  15069.         cmsavp(psave,PROMPTL);          /* Save old prompt */
  15070.         debug(F110,"ckxlogin saved",psave,0);
  15071.         rprompt = 1;
  15072.     }
  15073.     if (!*userid) {
  15074.         if (!promptok)
  15075.           return(0);
  15076.         cmsetp("Username: ");           /* Make new prompt */
  15077.         concb((char)escape);            /* Put console in cbreak mode */
  15078.         cmini(1);
  15079.  
  15080. /* Flush typeahead */
  15081.  
  15082. #ifdef IKS_OPTION
  15083.         debug(F101,
  15084.               "ckxlogin TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
  15085.               "",
  15086.               TELOPT_SB(TELOPT_KERMIT).kermit.me_start
  15087.               );
  15088. #endif /* IKS_OPTION */
  15089.  
  15090.         while (ttchk() > 0) {
  15091.             x = ttinc(0);
  15092.             debug(F101,"ckxlogin flush user x","",x);
  15093.             if (x < 0)
  15094.               doexit(GOOD_EXIT,0);      /* Connection lost */
  15095. #ifdef TNCODE
  15096.             if (sstelnet) {
  15097.                 if (x == IAC) {
  15098.                     x = tn_doop((CHAR)(x & 0xff),ckxech,ttinc);
  15099.                     debug(F101,"ckxlogin user tn_doop","",x);
  15100. #ifdef IKS_OPTION
  15101.                     debug(F101,
  15102.                       "ckxlogin user TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
  15103.                       "",
  15104.                       TELOPT_SB(TELOPT_KERMIT).kermit.me_start
  15105.                       );
  15106. #endif /* IKS_OPTION */
  15107.  
  15108.                     if (x < 0)
  15109.                       goto XCKXLOG;
  15110.                     switch (x) {
  15111.                       case 1: ckxech = 1; break; /* Turn on echoing */
  15112.                       case 2: ckxech = 0; break; /* Turn off echoing */
  15113. #ifdef IKS_OPTION
  15114.                       case 4:                    /* IKS event */
  15115.                         if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
  15116.                           break;                 /* else fall thru... */
  15117. #endif /* IKS_OPTION */
  15118.                       case 6:                    /* Logout */
  15119.                         goto XCKXLOG;
  15120.                     }
  15121.                 }
  15122.             }
  15123. #endif /* TNCODE */
  15124.         }
  15125.         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
  15126.         cmres();                        /* Reset the parser */
  15127.         for (x = -1; x < 0;) {          /* Prompt till they answer */
  15128.             /* Get a literal line of text */
  15129.             x=cmtxt("Your username, or \"ftp\", or \"anonymous\"","",&s,NULL);
  15130.             if (x == -4 || x == -10) {
  15131.                 printf("\r\n%sLogin cancelled\n",
  15132.                x == -10 ? "Timed out: " : "");
  15133. #ifdef CKSYSLOG
  15134.                 ckxsyslog = savlog;
  15135. #endif /* CKSYSLOG */
  15136.                 doexit(GOOD_EXIT,0);
  15137.             }
  15138.             if (sstate)                 /* Did a packet come instead? */
  15139.               goto XCKXLOG;
  15140.             cmres();                    /* Reset the parser again */
  15141.         }
  15142.         if ((_u = (CHAR *)malloc((int)strlen(s) + 1)) == NULL) {
  15143.             printf("?Internal error: malloc\n");
  15144.             goto XCKXLOG;
  15145.         } else {
  15146.             strcpy((char *)_u,s);       /* safe */
  15147.             userid = _u;
  15148.         }
  15149.     }
  15150.     ok = zvuser((char *)userid);        /* Verify username */
  15151.     debug(F111,"ckxlogin zvuser",userid,ok);
  15152.  
  15153.     if (!*passwd && promptok
  15154. #ifdef COMMENT
  15155.         && guest
  15156. #endif /* COMMENT */
  15157.         ) {
  15158.         char prmpt[80];
  15159.  
  15160. #ifdef CKSYSLOG
  15161.         savlog = ckxsyslog;             /* Save and turn off syslogging */
  15162.         ckxsyslog = 0;
  15163. #endif /* CKSYSLOG */
  15164.  
  15165. /* Flush typeahead again */
  15166.  
  15167.         while (ttchk() > 0) {
  15168.             x = ttinc(0);
  15169.             debug(F101,"ckxlogin flush user x","",x);
  15170. #ifdef TNCODE
  15171.             if (sstelnet) {
  15172.                 if (x == IAC) {
  15173.                     x = tn_doop((CHAR)(x & 0xff),ckxech,ttinc);
  15174.                     debug(F101,"ckxlogin pass tn_doop","",x);
  15175. #ifdef IKS_OPTION
  15176.                     debug(F101,
  15177.                       "ckxlogin pass TELOPT_SB(TELOPT_KERMIT).kermit.me_start",
  15178.                       "",
  15179.                       TELOPT_SB(TELOPT_KERMIT).kermit.me_start
  15180.                       );
  15181. #endif /* IKS_OPTION */
  15182.                     if (x < 0)
  15183.                       goto XCKXLOG;
  15184.                     switch (x) {
  15185.                       case 1: ckxech = 1; break; /* Turn on echoing */
  15186.                       case 2: ckxech = 0; break; /* Turn off echoing */
  15187.                       case 4:                    /* IKS event */
  15188.                         if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
  15189.                           break;                 /* else fall thru... */
  15190.                       case 6:                    /* Logout */
  15191.                         goto XCKXLOG;
  15192.                     }
  15193.                 }
  15194.             }
  15195. #endif /* TNCODE */
  15196.         }
  15197.         if (!strcmp((char *)userid,"anonymous") ||
  15198.             !strcmp((char *)userid,"ftp")) {
  15199.             if (!ok)
  15200.               goto XCKXLOG;
  15201.             ckstrncpy(prmpt,"Enter e-mail address as Password: ",80);
  15202.         } else if (*userid && strlen((char *)userid) < 60) {
  15203. #ifdef NT
  15204.             extern CHAR * pReferenceDomainName;
  15205.             if (pReferenceDomainName)
  15206.               ckmakxmsg(prmpt,
  15207.                        80,
  15208.                        "Enter ",
  15209.                        pReferenceDomainName,
  15210.                        "\\\\",
  15211.                        userid,
  15212.                        "'s Password: ",
  15213.                        NULL,NULL,NULL,NULL,NULL,NULL,NULL
  15214.                        );
  15215.             else
  15216. #endif /* NT */
  15217.               ckmakmsg(prmpt,80,"Enter ",(char *)userid,"'s Password: ",NULL);
  15218.         } else
  15219.           ckstrncpy(prmpt,"Enter Password: ",80);
  15220.         cmsetp(prmpt);                  /* Make new prompt */
  15221.         concb((char)escape);            /* Put console in cbreak mode */
  15222.         if (strcmp((char *)userid,"anonymous") &&
  15223.             strcmp((char *)userid,"ftp")) { /* and if not anonymous */
  15224.             debok = 0;
  15225.             cmini(0);                   /* and no-echo mode */
  15226.         } else {
  15227.             cmini(1);
  15228.         }
  15229.         if (pflag) prompt(xxstring);    /* Issue prompt if at top level */
  15230.         cmres();                        /* Reset the parser */
  15231.         for (x = -1; x < 0;) {          /* Prompt till they answer */
  15232. #ifdef CK_PAM
  15233.         gotemptypasswd=0;
  15234. #endif /* CK_PAM */
  15235.             x = cmtxt("","",&s,NULL);   /* Get a literal line of text */
  15236.             if (x == -4 || x == -10) {
  15237.                 printf("\r\n%sLogin cancelled\n",
  15238.                x == -10 ? "Timed out: " : "");
  15239. #ifdef CKSYSLOG
  15240.                 ckxsyslog = savlog;
  15241. #endif /* CKSYSLOG */
  15242.                 doexit(GOOD_EXIT,0);
  15243.             }
  15244. #ifdef CK_PAM
  15245.         if (!*s)
  15246.           gotemptypasswd = 1;
  15247. #endif /* CK_PAM */
  15248.             if (sstate)                 /* In case of a Kermit packet */
  15249.               goto XCKXLOG;
  15250.             cmres();                    /* Reset the parser again */
  15251.         }
  15252.         printf("\r\n");                 /* Echo a CRLF */
  15253.         if ((_p = (CHAR *)malloc((int)strlen(s) + 1)) == NULL) {
  15254.             printf("?Internal error: malloc\n");
  15255.             goto XCKXLOG;
  15256.         } else {
  15257.             strcpy((char *)_p,s);       /* safe */
  15258.             passwd = _p;
  15259.         }
  15260.     }
  15261. #ifdef CK_PAM
  15262.     else {
  15263.         cmres();                        /* Reset the parser */
  15264.  
  15265.         /* We restore the prompt now because the PAM engine will call  */
  15266.         /* readpass() which will overwrite psave. */
  15267.         if (rprompt) {
  15268.             cmsetp(psave);              /* Restore original prompt */
  15269.             debug(F110,"ckxlogin restored",psave,0);
  15270.             rprompt = 0;
  15271.         }
  15272.     }
  15273. #endif /* CK_PAM */
  15274.  
  15275. #ifdef CKSYSLOG
  15276.     ckxsyslog = savlog;
  15277. #endif /* CKSYSLOG */
  15278.  
  15279.     if (ok) {
  15280.         ok = zvpass((char *)passwd);    /* Check password */
  15281.         debug(F101,"ckxlogin zvpass","",ok);
  15282. #ifdef CK_PAM
  15283.     } else {
  15284.     /* Fake pam password failure for nonexistent users */
  15285.     sleep(1);
  15286.     printf("Authentication failure\n");
  15287. #endif    /* CK_PAM */
  15288.     }
  15289.  
  15290.     if (ok > 0 && isguest) {
  15291. #ifndef NOPUSH
  15292.         nopush = 1;
  15293. #endif /* NOPUSH */
  15294.         srvcdmsg = 1;
  15295.     }
  15296.     rc = ok;                            /* Set the return code */
  15297.     if ((char *)uidbuf != (char *)userid)
  15298.       ckstrncpy(uidbuf,(char *)userid,UIDBUFLEN); /* Remember username */
  15299.  
  15300.   XCKXLOG:                              /* Common exit */
  15301. #ifdef CKSYSLOG
  15302.     ckxsyslog = savlog;                 /* In case of GOTO above */
  15303. #endif /* CKSYSLOG */
  15304.     if (rprompt) {
  15305.         cmsetp(psave);                  /* Restore original prompt */
  15306.         debug(F110,"ckxlogin restored",psave,0);
  15307.     }
  15308.     if (_u || _p || _a) {
  15309.         if (_u) free(_u);
  15310.         if (_p) free(_p);
  15311.         if (_a) free(_a);
  15312.     }
  15313.     return(rc);
  15314. }
  15315.  
  15316. int
  15317. ckxlogout() {
  15318.     doexit(GOOD_EXIT,0);                /* doexit calls zvlogout */
  15319.     return(0);                          /* not reached */
  15320. }
  15321. #endif /* CK_LOGIN */
  15322.  
  15323. #endif /* NOICP */
  15324.